This is the start of the stable review cycle for the 6.16.4 release. There are 457 patches in this series, all will be posted as a response to this one. If anyone has any issues with these being applied, please let me know.
Responses should be made by Thu, 28 Aug 2025 11:08:27 +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.16.4-rc1.... or in the git tree and branch at: git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.git linux-6.16.y and the diffstat can be found below.
thanks,
greg k-h
------------- Pseudo-Shortlog of commits:
Greg Kroah-Hartman gregkh@linuxfoundation.org Linux 6.16.4-rc1
Christoph Manszewski christoph.manszewski@intel.com drm/xe: Fix vm_bind_ioctl double free bug
Piotr Piórkowski piotr.piorkowski@intel.com drm/xe: Move ASID allocation and user PT BO tracking into xe_vm_create
Florian Westphal fw@strlen.de netfilter: nf_reject: don't leak dst refcount for loopback packets
Peter Oberparleiter oberpar@linux.ibm.com s390/hypfs: Enable limited access during lockdown
Peter Oberparleiter oberpar@linux.ibm.com s390/hypfs: Avoid unnecessary ioctl registration in debugfs
Takashi Iwai tiwai@suse.de ALSA: usb-audio: Use correct sub-type for UAC3 feature unit validation
Armen Ratner armeng@nvidia.com net/mlx5e: Preserve shared buffer capacity during headroom updates
Alexei Lazar alazar@nvidia.com net/mlx5e: Query FW for buffer ownership
Oren Sidi osidi@nvidia.com net/mlx5: Add IFC bits and enums for buf_ownership
Daniel Jurgens danielj@nvidia.com net/mlx5: Base ECVF devlink port attrs from 0
Hariprasad Kelam hkelam@marvell.com Octeontx2-af: Skip overlap check for SPI field
Nilay Shroff nilay@linux.ibm.com block: avoid cpu_hotplug_lock depedency on freeze_lock
Nilay Shroff nilay@linux.ibm.com block: skip q->rq_qos check in rq_qos_done_bio()
Nilay Shroff nilay@linux.ibm.com block: decrement block_rq_qos static key in rq_qos_del()
Ming Lei ming.lei@redhat.com blk-mq: fix lockdep warning in __blk_mq_update_nr_hw_queues
Nilay Shroff nilay@linux.ibm.com block: fix potential deadlock while running nr_hw_queue update
Nilay Shroff nilay@linux.ibm.com block: fix lockdep warning caused by lock dependency in elv_iosched_store
Nilay Shroff nilay@linux.ibm.com block: move elevator queue allocation logic into blk_mq_init_sched
Lorenzo Bianconi lorenzo@kernel.org net: airoha: ppe: Do not invalid PPE entries in case of SW hash collision
Hangbin Liu liuhangbin@gmail.com bonding: send LACPDUs periodically in passive mode after receiving partner's LACPDU
Hangbin Liu liuhangbin@gmail.com bonding: update LACP activity flag after setting lacp_active
Dewei Meng mengdewei@cqsoftware.com.cn ALSA: timer: fix ida_free call while not allocated
William Liu will@willsroot.io net/sched: Remove unnecessary WARNING condition for empty child qdisc in htb_activate
William Liu will@willsroot.io net/sched: Make cake_enqueue return NET_XMIT_CN when past buffer_limit
Tristram Ha tristram.ha@microchip.com net: dsa: microchip: Fix KSZ9477 HSR port setup issue
ValdikSS iam@valdikss.org.ru igc: fix disabling L1.2 PCI-E link substate on I226 on init
Jason Xing kernelxing@tencent.com ixgbe: xsk: resolve the negative overflow of budget in ixgbe_xmit_zc
Song Gao gaosong@loongson.cn LoongArch: KVM: Use kvm_get_vcpu_by_id() instead of kvm_get_vcpu()
Bibo Mao maobibo@loongson.cn LoongArch: KVM: Use standard bitops API with eiointc
Heiko Carstens hca@linux.ibm.com s390/mm: Do not map lowcore with identity mapping
Stefan Binding sbinding@opensource.cirrus.com ASoC: cs35l56: Remove SoundWire Clock Divider workaround for CS35L63
Richard Fitzgerald rf@opensource.cirrus.com ASoC: cs35l56: Handle new algorithms IDs for CS35L63
Stefan Binding sbinding@opensource.cirrus.com ASoC: cs35l56: Update Firmware Addresses for CS35L63 for production silicon
Kanglong Wang wangkanglong@loongson.cn LoongArch: Optimize module load time by optimizing PLT/GOT counting
Tiezhu Yang yangtiezhu@loongson.cn LoongArch: Pass annotate-tablejump option if LTO is enabled
Tiezhu Yang yangtiezhu@loongson.cn objtool/LoongArch: Get table size correctly if LTO is enabled
Parthiban Veerasooran parthiban.veerasooran@microchip.com microchip: lan865x: fix missing Timer Increment config for Rev.B0/B1
Parthiban Veerasooran parthiban.veerasooran@microchip.com microchip: lan865x: fix missing netif_start_queue() call on device open
Vlad Dogaru vdogaru@nvidia.com net/mlx5: CT: Use the correct counter offset
Alex Vesker valex@nvidia.com net/mlx5: HWS, Fix table creation UID
Yevgeny Kliteynik kliteyn@nvidia.com net/mlx5: HWS, fix complex rules rehash error flow
Yevgeny Kliteynik kliteyn@nvidia.com net/mlx5: HWS, fix bad parameter in CQ creation
D. Wythe alibuda@linux.alibaba.com net/smc: fix UAF on smcsk after smc_listen_out()
Yao Zi ziyao@disroot.org net: stmmac: thead: Enable TX clock before MAC initialization
Jordan Rhee jordanrhee@google.com gve: prevent ethtool ops after shutdown
Yuichiro Tsuji yuichtsu@amazon.com net: usb: asix_devices: Fix PHY address mask in MDIO bus initialization
Horatiu Vultur horatiu.vultur@microchip.com phy: mscc: Fix timestamping for vsc8584
David Howells dhowells@redhat.com cifs: Fix oops due to uninitialised variable
Dan Carpenter dan.carpenter@linaro.org regulator: tps65219: regulator: tps65219: Fix error codes in probe()
Piotr Piórkowski piotr.piorkowski@intel.com drm/xe: Assign ioctl xe file handler to vm in xe_vm_create
MD Danish Anwar danishanwar@ti.com net: ti: icssg-prueth: Fix HSR and switch offload Enablement during firwmare reload.
Qingfang Deng dqfext@gmail.com ppp: fix race conditions in ppp_fill_forward_path
Qingfang Deng dqfext@gmail.com net: ethernet: mtk_ppe: add RCU lock around dev_fill_forward_path
Nitin Rawat quic_nitirawa@quicinc.com scsi: ufs: ufs-qcom: Fix ESI null pointer dereference
Bao D. Nguyen quic_nguyenb@quicinc.com scsi: ufs: ufs-qcom: Update esi_vec_mask for HW major version >= 6
Bart Van Assche bvanassche@acm.org scsi: ufs: core: Remove WARN_ON_ONCE() call from ufshcd_uic_cmd_compl()
Bart Van Assche bvanassche@acm.org scsi: ufs: core: Fix IRQ lock inversion for the SCSI host lock
Michael Chan michael.chan@broadcom.com bnxt_en: Fix lockdep warning during rmmod
Minhong He heminhong@kylinos.cn ipv6: sr: validate HMAC algorithm ID in seg6_hmac_info_add
Jakub Ramaseuski jramaseu@redhat.com net: gso: Forbid IPv6 TSO with extensions on devices with only IPV6_CSUM
Timur Kristóf timur.kristof@gmail.com drm/amd/display: Don't print errors for nonexistent connectors
Timur Kristóf timur.kristof@gmail.com drm/amd/display: Adjust DCE 8-10 clock, don't overclock by 15%
Chenyuan Yang chenyuan0y@gmail.com drm/amd/display: Add null pointer check in mod_hdcp_hdcp1_create_session()
Peng Fan peng.fan@nxp.com regulator: pca9450: Use devm_register_sys_off_handler
Dan Carpenter dan.carpenter@linaro.org ALSA: usb-audio: Fix size validation in convert_chmap_v3()
Baihan Li libaihan@huawei.com drm/hisilicon/hibmc: fix dp and vga cannot show together
Baihan Li libaihan@huawei.com drm/hisilicon/hibmc: fix rare monitors cannot display problem
Baihan Li libaihan@huawei.com drm/hisilicon/hibmc: fix the hibmc loaded failed bug
Baihan Li libaihan@huawei.com drm/hisilicon/hibmc: fix irq_request()'s irq name variable is local
Baihan Li libaihan@huawei.com drm/hisilicon/hibmc: fix the i2c device resource leak when vdac init failed
Miguel Ojeda ojeda@kernel.org rust: alloc: fix `rusttest` by providing `Cmalloc::aligned_layout` too
Zheng Qixing zhengqixing@huawei.com md: fix sync_action incorrect display during resync
Zheng Qixing zhengqixing@huawei.com md: add helper rdev_needs_recovery()
Li Nan linan122@huawei.com md: rename recovery_cp to resync_offset
Miguel Ojeda ojeda@kernel.org drm: nova-drm: fix 32-bit arm build
Ido Schimmel idosch@nvidia.com mlxsw: spectrum: Forward packets with an IPv4 link-local source IP
Luiz Augusto von Dentz luiz.von.dentz@intel.com Bluetooth: hci_core: Fix not accounting for BIS/CIS/PA links separately
Yang Li yang.li@amlogic.com Bluetooth: Add PA_LINK to distinguish BIG sync and PA sync connections
Sergey Shtylyov s.shtylyov@omp.ru Bluetooth: hci_conn: do return error from hci_enhanced_setup_sync()
Pauli Virtanen pav@iki.fi Bluetooth: hci_event: fix MTU for BN == 0 in CIS Established
Yang Li yang.li@amlogic.com Bluetooth: hci_sync: Prevent unintended PA sync when SID is 0xFF
Luiz Augusto von Dentz luiz.von.dentz@intel.com Bluetooth: hci_core: Fix using ll_privacy_capable for current settings
Luiz Augusto von Dentz luiz.von.dentz@intel.com Bluetooth: hci_core: Fix using {cis,bis}_capable for current settings
Jiande Lu jiande.lu@mediatek.com Bluetooth: btmtk: Fix wait_on_bit_timeout interruption during shutdown
Luiz Augusto von Dentz luiz.von.dentz@intel.com Bluetooth: hci_sync: Fix scan state after PA Sync has been established
Kees Cook kees@kernel.org iommu/amd: Avoid stack buffer overflow from kernel cmdline
Dan Carpenter dan.carpenter@linaro.org scsi: qla4xxx: Prevent a potential error pointer dereference
Justin Lai justinlai0215@realtek.com rtase: Fix Rx descriptor CRC error bit definition
William Liu will@willsroot.io net/sched: Fix backlog accounting in qdisc_dequeue_internal
Wang Liang wangliang74@huawei.com net: bridge: fix soft lockup in br_multicast_query_expired()
Suraj Gupta suraj.gupta2@amd.com net: xilinx: axienet: Fix RX skb ring management in DMAengine mode
Junxian Huang huangjunxian6@hisilicon.com RDMA/hns: Fix dip entries leak on devices newer than hip09
Akhilesh Patil akhilesh@ee.iitb.ac.in RDMA/core: Free pfn_list with appropriate kvfree call
Anantha Prabhu anantha.prabhu@broadcom.com RDMA/bnxt_re: Fix to initialize the PBL array
Kalesh AP kalesh-anakkur.purayil@broadcom.com RDMA/bnxt_re: Fix a possible memory leak in the driver
Kashyap Desai kashyap.desai@broadcom.com RDMA/bnxt_re: Fix to remove workload check in SRQ limit path
Kashyap Desai kashyap.desai@broadcom.com RDMA/bnxt_re: Fix to do SRQ armena by default
wenglianfa wenglianfa@huawei.com RDMA/hns: Fix querying wrong SCC context for DIP algorithm
Boshi Yu boshiyu@linux.alibaba.com RDMA/erdma: Fix unset QPN of GSI QP
Boshi Yu boshiyu@linux.alibaba.com RDMA/erdma: Fix ignored return value of init_kernel_qp
Suma Hegde suma.hegde@amd.com platform/x86/amd/hsmp: Ensure sock->metric_tbl_addr is non-NULL
Jocelyn Falempe jfalempe@redhat.com drm/panic: Add a u64 divide by 10 for arm32
Danilo Krummrich dakr@kernel.org rust: drm: don't pass the address of drm::Device to drm_dev_put()
Danilo Krummrich dakr@kernel.org rust: drm: remove pin annotations from drm::Device
Danilo Krummrich dakr@kernel.org rust: drm: ensure kmalloc() compatible Layout
Danilo Krummrich dakr@kernel.org rust: alloc: replace aligned_size() with Kmalloc::aligned_layout()
Nitin Gote nitin.r.gote@intel.com iosys-map: Fix undefined behavior in iosys_map_clear()
José Expósito jose.exposito89@gmail.com drm/tests: Fix drm_test_fb_xrgb8888_to_xrgb2101010() on big-endian
Thomas Zimmermann tzimmermann@suse.de drm/tests: Do not use drm_fb_blit() in format-helper tests
José Expósito jose.exposito89@gmail.com drm/tests: Fix endian warning
Waiman Long longman@redhat.com cgroup/cpuset: Fix a partition error with CPU hotplug
Waiman Long longman@redhat.com cgroup/cpuset: Use static_branch_enable_cpuslocked() on cpusets_insane_config_key
Fanhua Li lifanhua5@huawei.com drm/nouveau/nvif: Fix potential memory leak in nvif_vmm_ctor().
Gabor Juhos j4g8y7@gmail.com spi: spi-qpic-snand: fix calculating of ECC OOB regions' properties
Stefan Wahren wahrenst@gmx.net spi: spi-fsl-lpspi: Clamp too high speed_hz
Gabor Juhos j4g8y7@gmail.com spi: spi-qpic-snand: use correct CW_PER_PAGE value for OOB write
Jean-Baptiste Maneyrol jean-baptiste.maneyrol@tdk.com iio: imu: inv_icm42600: change invalid data error to -EBUSY
Andy Shevchenko andriy.shevchenko@linux.intel.com iio: imu: inv_icm42600: Convert to uXX and sXX integer types
David Lechner dlechner@baylibre.com iio: imu: inv_icm42600: use = { } instead of memset()
Jedrzej Jagielski jedrzej.jagielski@intel.com ixgbe: prevent from unwanted interface name changes
Jedrzej Jagielski jedrzej.jagielski@intel.com devlink: let driver opt out of automatic phys_port_name generation
Sven Eckelmann sven@narfation.org i2c: rtl9300: Add missing count byte for SMBus Block Ops
Sven Eckelmann sven@narfation.org i2c: rtl9300: Increase timeout for transfer polling
Harshal Gohel hg@simonwunderlich.de i2c: rtl9300: Fix multi-byte I2C write
Alex Guo alexguo1023@gmail.com i2c: rtl9300: Fix out-of-bounds bug in rtl9300_i2c_smbus_xfer
Tianxiang Peng txpeng@tencent.com x86/cpu/hygon: Add missing resctrl_cpu_detect() in bsp_init helper
Yazen Ghannam yazen.ghannam@amd.com x86/CPU/AMD: Ignore invalid reset reason value
Jakub Kicinski kuba@kernel.org tls: fix handling of zero-length records on the rx_list
Niklas Cassel cassel@kernel.org PCI: dwc: Ensure that dw_pcie_wait_for_link() waits 100 ms after link up
NeilBrown neil@brown.name ovl: use I_MUTEX_PARENT when locking parent in ovl_create_temp()
Pu Lehui pulehui@huawei.com tracing: Limit access to parser->buffer when trace_get_user failed
Steven Rostedt rostedt@goodmis.org tracing: Remove unneeded goto out logic
Heikki Krogerus heikki.krogerus@linux.intel.com usb: dwc3: pci: add support for the Intel Wildcat Lake
Selvarasu Ganesan selvarasu.g@samsung.com usb: dwc3: Remove WARN_ON for device endpoint command timeouts
Kuen-Han Tsai khtsai@google.com usb: dwc3: Ignore late xferNotReady event to prevent halt timeout
Niklas Neronin niklas.neronin@linux.intel.com usb: xhci: fix host not responding after suspend and resume
Weitao Wang WeitaoWang-oc@zhaoxin.com usb: xhci: Fix slot_id resource race conflict
Amit Sunil Dhamne amitsd@google.com usb: typec: maxim_contaminant: re-enable cc toggle if cc is open and port is clean
Amit Sunil Dhamne amitsd@google.com usb: typec: maxim_contaminant: disable low power mode when reading comparator values
Zenm Chen zenmchen@gmail.com USB: storage: Ignore driver CD mode for Realtek multi-mode Wi-Fi dongles
Thorsten Blum thorsten.blum@linux.dev usb: storage: realtek_cr: Use correct byte order for bcs->Residue
Mael GUERIN mael.guerin@murena.io USB: storage: Add unusual-devs entry for Novatek NTK96550-based camera
Marek Vasut marek.vasut+renesas@mailbox.org usb: renesas-xhci: Fix External ROM access timeouts
Xu Yang xu.yang_2@nxp.com usb: core: hcd: fix accessing unmapped memory in SINGLE_STEP_SET_FEATURE test
Ian Abbott abbotti@mev.co.uk comedi: Fix use of uninitialized memory in do_insn_ioctl() and do_insnlist_ioctl()
Edward Adam Davis eadavis@qq.com comedi: pcl726: Prevent invalid irq number
Ian Abbott abbotti@mev.co.uk comedi: Make insn_rw_emulate_bits() do insn->n samples
Miao Li limiao@kylinos.cn usb: quirks: Add DELAY_INIT quick for another SanDisk 3.2Gen1 Flash Drive
Thorsten Blum thorsten.blum@linux.dev cdx: Fix off-by-one error in cdx_rpmsg_probe()
Sebastian Andrzej Siewior bigeasy@linutronix.de kcov, usb: Don't disable interrupts in kcov_remote_start_usb_softirq()
Miaoqian Lin linmq006@gmail.com most: core: Drop device reference after usage in get_channel()
Claudiu Beznea claudiu.beznea.uj@bp.renesas.com iio: adc: rzg2l: Cleanup suspend/resume path
David Lechner dlechner@baylibre.com iio: proximity: isl29501: fix buffered read on big-endian systems
David Lechner dlechner@baylibre.com iio: adc: ad7173: prevent scan if too many setups requested
Matti Vaittinen mazziesaccount@gmail.com iio: adc: bd79124: Add GPIOLIB dependency
Claudiu Beznea claudiu.beznea.uj@bp.renesas.com iio: adc: rzg2l_adc: Set driver data before enabling runtime PM
Salah Triki salah.triki@gmail.com iio: pressure: bmp280: Use IS_ERR() in bmp280_common_probe()
Jonathan Cameron Jonathan.Cameron@huawei.com iio: light: as73211: Ensure buffer holes are zeroed
David Lechner dlechner@baylibre.com iio: adc: ad7124: fix channel lookup in syscalib functions
David Lechner dlechner@baylibre.com iio: temperature: maxim_thermocouple: use DMA-safe buffer for spi_read()
Steven Rostedt rostedt@goodmis.org ftrace: Also allocate and copy hash for reading of filter files
David Lechner dlechner@baylibre.com iio: accel: sca3300: fix uninitialized iio scan data
David Lechner dlechner@baylibre.com iio: adc: ad7380: fix missing max_conversion_rate_hz on adaq4381-4
Xu Yilun yilun.xu@linux.intel.com fpga: zynq_fpga: Fix the wrong usage of dma_map_sgtable()
Imre Deak imre.deak@intel.com drm/dp: Change AUX DPCD probe address from DPCD_REV to LANE0_1_STATUS
Mario Limonciello mario.limonciello@amd.com drm/amd: Restore cached manual clock settings during resume
Robin Murphy robin.murphy@arm.com iommu/virtio: Make instance lookup robust
Jason Gunthorpe jgg@ziepe.ca iommu: Remove ops.pgsize_bitmap from drivers that don't use it
Al Viro viro@zeniv.linux.org.uk use uniform permission checks for all mount propagation changes
Adrian Huang (Lenovo) adrianhuang0701@gmail.com signal: Fix memory leak for PIDFD_SELF* sentinels
Ye Bin yebin10@huawei.com fs/buffer: fix use-after-free when call bh_read() helper
Stefan Metzmacher metze@samba.org smb: server: split ksmbd_rdma_stop_listening() out of ksmbd_rdma_destroy()
Christian Brauner brauner@kernel.org libfs: massage path_from_stashed() to allow custom stashing behavior
Thomas Bertschinger tahbertschinger@gmail.com fhandle: do_handle_open() should get FD with user flags
Naohiro Aota naohiro.aota@wdc.com btrfs: zoned: fix data relocation block group reservation
Yuntao Wang yuntao.wang@linux.dev fs: fix incorrect lflags value in the move_mount syscall
Charalampos Mitrodimas charmitro@posteo.net debugfs: fix mount options not being applied
Miguel Ojeda ojeda@kernel.org rust: faux: fix C header link
Christoph Hellwig hch@lst.de xfs: fix frozen file system assert in xfs_trans_alloc
Dan Carpenter dan.carpenter@linaro.org soc: qcom: mdt_loader: Fix error return values in mdt_header_valid()
Liu01 Tong Tong.Liu01@amd.com drm/amdgpu: fix task hang from failed job submission during process kill
Geraldo Nascimento geraldogabriel@gmail.com PCI: rockchip: Set Target Link Speed to 5.0 GT/s before retraining
Geraldo Nascimento geraldogabriel@gmail.com PCI: rockchip: Use standard PCIe definitions
Ranjan Kumar ranjan.kumar@broadcom.com scsi: mpi3mr: Serialize admin queue BAR writes on 32-bit systems
Ranjan Kumar ranjan.kumar@broadcom.com scsi: mpi3mr: Drop unnecessary volatile from __iomem pointers
Timur Kristóf timur.kristof@gmail.com drm/amd/display: Fill display clock and vblank time in dce110_fill_display_configs
Timur Kristóf timur.kristof@gmail.com drm/amd/display: Find first CRTC and its line time in dce110_fill_display_configs
Timur Kristóf timur.kristof@gmail.com drm/amd/display: Fix DP audio DTO1 clock source on DCE 6.
Tom Chung chiahsuan.chung@amd.com drm/amd/display: Fix Xorg desktop unresponsive on Replay panel
Timur Kristóf timur.kristof@gmail.com drm/amd/display: Fix fractional fb divider in set_pixel_clock_v3
Timur Kristóf timur.kristof@gmail.com drm/amd/display: Don't overclock DCE 6 by 15%
Mario Limonciello mario.limonciello@amd.com drm/amd/display: Avoid a NULL pointer dereference
Imre Deak imre.deak@intel.com drm/i915/icl+/tc: Convert AUX powered WARN to a debug message
Imre Deak imre.deak@intel.com drm/i915/lnl+/tc: Use the cached max lane count value
Imre Deak imre.deak@intel.com drm/i915/lnl+/tc: Fix max lane count HW readout
Imre Deak imre.deak@intel.com drm/i915/icl+/tc: Cache the max lane count value
Imre Deak imre.deak@intel.com drm/i915/lnl+/tc: Fix handling of an enabled/disconnected dp-alt sink
Sebastian Brzezinka sebastian.brzezinka@intel.com drm/i915/gt: Relocate compression repacking WA for JSL/EHL
Qianfeng Rong rongqianfeng@vivo.com drm/nouveau/gsp: fix mismatched alloc/free for kvmalloc()
Jani Nikula jani.nikula@intel.com drm/i915: silence rpm wakeref asserts on GEN11_GU_MISC_IIR access
Alex Deucher alexander.deucher@amd.com drm/amdgpu/swm14: Update power limit logic
Thorsten Blum thorsten.blum@linux.dev accel/habanalabs/gaudi2: Use kvfree() for memory allocated with kvcalloc()
Jan Beulich jbeulich@suse.com compiler: remove __ADDRESSABLE_ASM{_STR,}() again
Srinivas Pandruvada srinivas.pandruvada@linux.intel.com platform/x86/intel-uncore-freq: Check write blocked for ELC
Peter Oberparleiter oberpar@linux.ibm.com s390/sclp: Fix SCCB present check
Zhu Yanjun yanjun.zhu@linux.dev RDMA/rxe: Flush delayed SKBs while releasing RXE resources
Evgeniy Harchenko evgeniyharchenko.dev@gmail.com ALSA: hda/realtek: Add support for HP EliteBook x360 830 G6 and EliteBook 830 G6
Takashi Iwai tiwai@suse.de ALSA: hda: tas2781: Fix wrong reference of tasdevice_priv
David Hildenbrand david@redhat.com mm/mremap: fix WARN with uffd that has remap events disabled
Jinjiang Tu tujinjiang@huawei.com mm/memory-failure: fix infinite UCE for VM_PFNMAP pfn
Herton R. Krzesinski herton@redhat.com mm/debug_vm_pgtable: clear page table entries at destroy_args()
Sang-Heon Jeon ekffu200098@gmail.com mm/damon/core: fix damos_commit_filter not changing allow
Phillip Lougher phillip@squashfs.org.uk squashfs: fix memory leak in squashfs_fill_super
Trond Myklebust trond.myklebust@hammerspace.com NFS: Fix a race when updating an existing write
Judith Mendez jm@ti.com mmc: sdhci_am654: Disable HS400 for AM62P SR1.0 and SR1.1
Victor Shih victor.shih@genesyslogic.com.tw mmc: sdhci-pci-gli: GL9763e: Rename the gli_set_gl9763e() for consistency
Victor Shih victor.shih@genesyslogic.com.tw mmc: sdhci-pci-gli: GL9763e: Mask the replay timer timeout of AER
Jiayi Li lijiayi@kylinos.cn memstick: Fix deadlock by moving removing flag earlier
Pasha Tatashin pasha.tatashin@soleen.com kho: warn if KHO is disabled due to an error
Pasha Tatashin pasha.tatashin@soleen.com kho: mm: don't allow deferred struct page with KHO
Pasha Tatashin pasha.tatashin@soleen.com kho: init new_physxa->phys_bits to fix lockdep
Victor Shih victor.shih@genesyslogic.com.tw mmc: sdhci-pci-gli: Add a new function to simplify the code
Sai Krishna Potthuri sai.krishna.potthuri@amd.com mmc: sdhci-of-arasan: Ensure CD logic stabilization before power-up
Sang-Heon Jeon ekffu200098@gmail.com mm/damon/core: fix commit_ops_filters by using correct nth function
Nicolin Chen nicolinc@nvidia.com iommu/arm-smmu-v3: Fix smmu_domain->nr_ats_masters decrement
Dominique Martinet asmadeus@codewreck.org iov_iter: iterate_folioq: fix handling of offset >= folio size
Jens Axboe axboe@kernel.dk io_uring/futex: ensure io_futex_wait() cleans up properly on failure
XianLiang Huang huangxianliang@lanxincomputing.com iommu/riscv: prevent NULL deref in iova_to_phys
Eric Biggers ebiggers@kernel.org crypto: acomp - Fix CFI failure due to type punning
Geert Uytterhoeven geert+renesas@glider.be erofs: Do not select tristate symbols from bool symbols
Bo Liu (OpenAnolis) liubo03@inspur.com erofs: fix build error with CONFIG_EROFS_FS_ZIP_ACCEL=y
Alan Huang mmpgouride@gmail.com xfs: Remove unused label in xfs_dax_notify_dev_failure
Christoph Hellwig hch@lst.de xfs: fully decouple XFS_IBULK* flags from XFS_IWALK* flags
Christoph Hellwig hch@lst.de xfs: improve the comments in xfs_select_zone_nowait
Christoph Hellwig hch@lst.de xfs: return the allocated transaction from xfs_trans_alloc_empty
Christoph Hellwig hch@lst.de xfs: decouple xfs_trans_alloc_empty from xfs_trans_alloc
Naohiro Aota naohiro.aota@wdc.com btrfs: subpage: keep TOWRITE tag until folio is cleaned
Qu Wenruo wqu@suse.com btrfs: rename btrfs_subpage structure
Qu Wenruo wqu@suse.com btrfs: add comments on the extra btrfs specific subpage bitmaps
Leo Martins loemra.dev@gmail.com btrfs: fix subpage deadlock in try_release_subpage_extent_buffer()
Filipe Manana fdmanana@suse.com btrfs: use refcount_t type for the extent buffer reference counter
Filipe Manana fdmanana@suse.com btrfs: add comment for optimization in free_extent_buffer()
Filipe Manana fdmanana@suse.com btrfs: reorganize logic at free_extent_buffer() for better readability
Filipe Manana fdmanana@suse.com btrfs: abort transaction on unexpected eb generation at btrfs_copy_root()
Filipe Manana fdmanana@suse.com btrfs: always abort transaction on failure to add block group to free space tree
David Sterba dsterba@suse.com btrfs: move transaction aborts to the error site in add_block_group_free_space()
SeongJae Park sj@kernel.org mm/damon/ops-common: ignore migration request to invalid nodes
Matthieu Baerts (NGI0) matttbe@kernel.org selftests: mptcp: sockopt: fix C23 extension warning
Matthieu Baerts (NGI0) matttbe@kernel.org selftests: mptcp: connect: fix C23 extension warning
Matthieu Baerts (NGI0) matttbe@kernel.org selftests: mptcp: pm: check flush doesn't reset limits
Geliang Tang geliang@kernel.org mptcp: disable add_addr retransmission when timeout is 0
Geliang Tang geliang@kernel.org mptcp: remove duplicate sk_reset_timer call
Matthieu Baerts (NGI0) matttbe@kernel.org mptcp: pm: kernel: flush: do not reset ADD_ADDR limit
Christoph Paasch cpaasch@openai.com mptcp: drop skb if MPTCP skb extension allocation fails
Uwe Kleine-König u.kleine-koenig@baylibre.com ACPI: APEI: EINJ: Fix resource leak by remove callback in .exit.text
Chen Yu yu.c.chen@intel.com ACPI: pfr_update: Fix the driver update version check
Rafael J. Wysocki rafael.j.wysocki@intel.com cpuidle: governors: menu: Avoid selecting states with too much latency
JP Kobryn inwardvessel@gmail.com cgroup: avoid null de-ref in css_rstat_exit()
Eric Biggers ebiggers@kernel.org ipv6: sr: Fix MAC comparison to be constant-time
Andrea Righi arighi@nvidia.com sched/ext: Fix invalid task state transitions on class switch
Jakub Acs acsjakub@amazon.de net, hsr: reject HSR frame if skb can't hold tag
Bibo Mao maobibo@loongson.cn LoongArch: KVM: Add address alignment check in pch_pic register access
Bibo Mao maobibo@loongson.cn LoongArch: KVM: Fix stack protector issue in send_ipi_data()
Bibo Mao maobibo@loongson.cn LoongArch: KVM: Make function kvm_own_lbt() robust
Timur Kristóf timur.kristof@gmail.com drm/amd/display: Don't overwrite dce60_clk_mgr
Mario Limonciello mario.limonciello@amd.com drm/amd/display: Revert "drm/amd/display: Fix AMDGPU_MAX_BL_LEVEL value"
Mario Limonciello mario.limonciello@amd.com drm/amd/display: Pass up errors for reset GPU that fails to init HW
Lauri Tirkkonen lauri@hacktheplanet.fi drm/amd/display: fix initial backlight brightness calculation
Timur Kristóf timur.kristof@gmail.com drm/amd/display: Fix DCE 6.0 and 6.4 PLL programming.
Siyang Liu Security@tencent.com drm/amd/display: fix a Null pointer dereference vulnerability
Michel Dänzer mdaenzer@redhat.com drm/amd/display: Add primary plane to commits for correct VRR handling
David Yat Sin David.YatSin@amd.com drm/amdkfd: Fix checkpoint-restore on multi-xcc
Amber Lin Amber.Lin@amd.com drm/amdkfd: Destroy KFD debugfs after destroy KFD wq
Lijo Lazar lijo.lazar@amd.com drm/amdgpu: Update supported modes for GC v9.5.0
Alex Deucher alexander.deucher@amd.com drm/amdgpu: update mmhub 4.1.0 client id mappings
Alex Deucher alexander.deucher@amd.com drm/amdgpu: update mmhub 3.3 client id mappings
Alex Deucher alexander.deucher@amd.com drm/amdgpu: update mmhub 3.0.1 client id mappings
Lijo Lazar lijo.lazar@amd.com drm/amdgpu: Update external revid for GC v9.5.0
Alex Deucher alexander.deucher@amd.com drm/amdgpu: track whether a queue is a kernel queue in amdgpu_mqd_prop
YuanShang YuanShang.Mao@amd.com drm/amdgpu: Retain job->vm in amdgpu_job_prepare_job
Nathan Chancellor nathan@kernel.org drm/amdgpu: Initialize data to NULL in imu_v12_0_program_rlc_ram()
Peter Shkenev mustela@erminea.space drm/amdgpu: check if hubbub is NULL in debugfs/amdgpu_dm_capabilities
Gang Ba Gang.Ba@amd.com drm/amdgpu: Avoid extra evict-restore process.
Alex Deucher alexander.deucher@amd.com drm/amdgpu: add missing vram lost check for LEGACY RESET
Frank Min Frank.Min@amd.com drm/amdgpu: add kicker fws loading for gfx12/smu14/psp14
Mario Limonciello mario.limonciello@amd.com drm/amd: Restore cached power limit during resume
Alex Deucher alexander.deucher@amd.com drm/amdgpu/discovery: fix fw based ip discovery
Yang Wang kevinyang.wang@amd.com drm/amd/amdgpu: fix missing lock for cper.ring->rptr/wptr access
Thomas Hellström thomas.hellstrom@linux.intel.com drm/xe: Defer buffer object shrinker write-backs and GPU waits
Vodapalli, Ravi Kumar ravi.kumar.vodapalli@intel.com drm/xe/bmg: Add one additional PCI ID
Dikshita Agarwal quic_dikshita@quicinc.com media: iris: Remove unnecessary re-initialization of flush completion
Dikshita Agarwal quic_dikshita@quicinc.com media: iris: Verify internal buffer release on close
Dikshita Agarwal quic_dikshita@quicinc.com media: iris: Update CAPTURE format info based on OUTPUT format
Dikshita Agarwal quic_dikshita@quicinc.com media: iris: Track flush responses to prevent premature completion
Dikshita Agarwal quic_dikshita@quicinc.com media: iris: Skip flush on first sequence change
Dikshita Agarwal quic_dikshita@quicinc.com media: iris: Skip destroying internal buffer if not dequeued
Dikshita Agarwal quic_dikshita@quicinc.com media: iris: Send V4L2_BUF_FLAG_ERROR for capture buffers with 0 filled length
Dikshita Agarwal quic_dikshita@quicinc.com media: iris: Remove error check for non-zero v4l2 controls
Dikshita Agarwal quic_dikshita@quicinc.com media: iris: Remove deprecated property setting to firmware
Dikshita Agarwal quic_dikshita@quicinc.com media: iris: Prevent HFI queue writes when core is in deinit state
Dikshita Agarwal quic_dikshita@quicinc.com media: iris: Fix typo in depth variable
Dikshita Agarwal quic_dikshita@quicinc.com media: iris: Fix NULL pointer dereference
Dikshita Agarwal quic_dikshita@quicinc.com media: iris: Fix missing function pointer initialization
Dikshita Agarwal quic_dikshita@quicinc.com media: iris: Fix buffer preparation failure during resolution change
Dikshita Agarwal quic_dikshita@quicinc.com media: iris: Drop port check for session property response
Dikshita Agarwal quic_dikshita@quicinc.com media: iris: Avoid updating frame size to firmware during reconfig
Ricardo Ribalda ribalda@chromium.org media: venus: venc: Clamp param smaller than 1fps and bigger than 240
Ricardo Ribalda ribalda@chromium.org media: venus: vdec: Clamp param smaller than 1fps and bigger than 240.
Jorge Ramirez-Ortiz jorge.ramirez@oss.qualcomm.com media: venus: protect against spurious interrupts during probe
Jorge Ramirez-Ortiz jorge.ramirez@oss.qualcomm.com media: venus: hfi: explicitly release IRQ during teardown
Konrad Dybcio konrad.dybcio@oss.qualcomm.com media: venus: Fix MSM8998 frequency table
Vedang Nagar quic_vnagar@quicinc.com media: venus: Add a check for packet size after reading from shared memory
Bryan O'Donoghue bryan.odonoghue@linaro.org media: qcom: camss: Remove extraneous -supply postfix on supply names
Vladimir Zapolskiy vladimir.zapolskiy@linaro.org media: qcom: camss: cleanup media device allocated resource on error path
Bryan O'Donoghue bryan.odonoghue@linaro.org media: qcom: camss: csiphy-3ph: Fix inadvertent dropping of SDM660/SDM670 phy init
Hans de Goede hansg@kernel.org media: ivsc: Fix crash at shutdown due to missing mei_cldev_disable() calls
Mathis Foerst mathis.foerst@mt.com media: mt9m114: Fix deadlock in get_frame_interval/set_frame_interval
Zhang Shurong zhang_shurong@foxmail.com media: ov2659: Fix memory leaks in ov2659_probe()
Jacopo Mondi jacopo.mondi@ideasonboard.com media: pisp_be: Fix pm_runtime underrun in probe
Gui-Dong Han hanguidong02@gmail.com media: rainshadow-cec: fix TOCTOU race condition in rain_interrupt()
Ludwig Disterhof ludwig@disterhof.eu media: usbtv: Lock resolution while streaming
Sakari Ailus sakari.ailus@linux.intel.com media: v4l2-ctrls: Don't reset handler's error in v4l2_ctrl_handler_free()
Nicolas Dufresne nicolas.dufresne@collabora.com media: verisilicon: Fix AV1 decoder clock frequency
Hans Verkuil hverkuil@xs4all.nl media: vivid: fix wrong pixel_array control size
Sakari Ailus sakari.ailus@linux.intel.com media: ipu6: isys: Use correct pads for xlate_streams()
Haoxiang Li haoxiang_li2024@163.com media: imx: fix a potential memory leak in imx_media_csc_scaler_device_init()
Bingbu Cao bingbu.cao@intel.com media: hi556: correct the test pattern configuration
Dan Carpenter dan.carpenter@linaro.org media: gspca: Add bounds checking to firmware parser
John David Anglin dave.anglin@bell.net parisc: Update comments in make_insert_tlb
John David Anglin dave.anglin@bell.net parisc: Try to fixup kernel exception in bad_area_nosemaphore path of do_page_fault()
John David Anglin dave.anglin@bell.net parisc: Revise gateway LWS calls to probe user read access
John David Anglin dave.anglin@bell.net parisc: Revise __get_user() to probe user read access
John David Anglin dave.anglin@bell.net parisc: Rename pte_needs_flush() to pte_needs_cache_flush() in cache.c
Randy Dunlap rdunlap@infradead.org parisc: Makefile: explain that 64BIT requires both 32-bit and 64-bit compilers
John David Anglin dave.anglin@bell.net parisc: Drop WARN_ON_ONCE() from flush_cache_vmap
John David Anglin dave.anglin@bell.net parisc: Define and use set_pte_at()
John David Anglin dave.anglin@bell.net parisc: Check region is readable by user in raw_copy_from_user()
Jon Hunter jonathanh@nvidia.com soc/tegra: pmc: Ensure power-domains are in a known state
Jialin Wang wjl.linux@gmail.com proc: proc_maps_open allow proc_mem_open to return NULL
Aleksa Sarai cyphar@cyphar.com open_tree_attr: do not allow id-mapping changes without OPEN_TREE_CLONE
Simon Richter Simon.Richter@hogyros.de Mark xe driver as BROKEN if kernel page size is not 4kB
Thomas Weißschuh thomas.weissschuh@linutronix.de kbuild: userprogs: use correct linker when mixing clang and GNU ld
Jann Horn jannh@google.com kasan/test: fix protection against compiler elision
Baokun Li libaokun1@huawei.com jbd2: prevent softlockup in jbd2_log_do_checkpoint()
Jan Kara jack@suse.cz iomap: Fix broken data integrity guarantees for O_SYNC writes
Kathiravan Thirumoorthy kathiravan.thirumoorthy@oss.qualcomm.com i2c: qcom-geni: fix I2C frequency table to achieve accurate bus rates
Chao Yu chao@kernel.org f2fs: fix to avoid out-of-boundary access in dnode page
Julian Sun sunjunchao2870@gmail.com block: restore default wbt enablement
Muhammad Usama Anjum usama.anjum@collabora.com ASoC: SOF: amd: acp-loader: Use GFP_KERNEL for DMA allocations in resume context
Xaver Hugl xaver.hugl@kde.org amdgpu/amdgpu_discovery: increase timeout limit for IFWI init
Kathiravan Thirumoorthy kathiravan.thirumoorthy@oss.qualcomm.com phy: qcom: phy-qcom-m31: Update IPQ5332 M31 USB phy initialization sequence
Will Deacon will@kernel.org vhost/vsock: Avoid allocating arbitrarily-sized SKBs
Will Deacon will@kernel.org vsock/virtio: Validate length in packet header before skb_put()
Richard Zhu hongxing.zhu@nxp.com PCI: imx6: Delay link start until configfs 'start' written
Richard Zhu hongxing.zhu@nxp.com PCI: imx6: Remove apps_reset toggling from imx_pcie_{assert/deassert}_core_reset
Richard Zhu hongxing.zhu@nxp.com PCI: imx6: Add IMX8MM_EP and IMX8MP_EP fixed 256-byte BAR 4 in epc_features
Richard Zhu hongxing.zhu@nxp.com PCI: imx6: Add IMX8MQ_EP third 64-bit BAR in epc_features
Damien Le Moal dlemoal@kernel.org PCI: endpoint: Fix configfs group removal on driver teardown
Damien Le Moal dlemoal@kernel.org PCI: endpoint: Fix configfs group list head handling
Jiwei Sun sunjw10@lenovo.com PCI: Fix link speed calculation on retrain failure
Lukas Wunner lukas@wunner.de PCI/portdrv: Use is_pciehp instead of is_hotplug_bridge
Chi Zhiling chizhiling@kylinos.cn readahead: fix return value of page_cache_next_miss() when no hole is found
Dmitry Torokhov dmitry.torokhov@gmail.com mfd: mt6397: Do not use generic name for keypad sub-devices
Thomas Fourier fourier.thomas@gmail.com mtd: rawnand: renesas: Add missing check after DMA map
Thomas Fourier fourier.thomas@gmail.com mtd: rawnand: fsmc: Add missing check after DMA map
Gabor Juhos j4g8y7@gmail.com mtd: spinand: propagate spinand_wait() errors from spinand_write_page()
Michael Walle mwalle@kernel.org mtd: spi-nor: Fix spi_nor_try_unlock_all()
Tim Harvey tharvey@gateworks.com hwmon: (gsc-hwmon) fix fan pwm setpoint show functions
Uwe Kleine-König u.kleine-koenig@baylibre.com pwm: mediatek: Fix duty and period setting
Uwe Kleine-König u.kleine-koenig@baylibre.com pwm: mediatek: Handle hardware enable and clock enable separately
Laurentiu Mihalcea laurentiu.mihalcea@nxp.com pwm: imx-tpm: Reset counter if CMOD is 0
Johan Hovold johan+linaro@kernel.org wifi: ath11k: fix dest ring-buffer corruption when ring is full
Johan Hovold johan+linaro@kernel.org wifi: ath11k: fix source ring-buffer corruption
Johan Hovold johan+linaro@kernel.org wifi: ath11k: fix dest ring-buffer corruption
Johan Hovold johan+linaro@kernel.org wifi: ath12k: fix dest ring-buffer corruption when ring is full
Johan Hovold johan+linaro@kernel.org wifi: ath12k: fix source ring-buffer corruption
Johan Hovold johan+linaro@kernel.org wifi: ath12k: fix dest ring-buffer corruption
Nathan Chancellor nathan@kernel.org wifi: brcmsmac: Remove const from tbl_ptr parameter in wlc_lcnphy_common_read_table()
David Lechner dlechner@baylibre.com iio: adc: ad7173: fix setting ODR in probe
David Lechner dlechner@baylibre.com iio: adc: ad7173: fix calibration channel
David Lechner dlechner@baylibre.com iio: adc: ad7173: fix channels index for syscalib_mode
David Lechner dlechner@baylibre.com iio: adc: ad_sigma_delta: change to buffer predisable
David Lechner dlechner@baylibre.com iio: imu: bno055: fix OOB access of hw_xlate array
Marek Szyprowski m.szyprowski@samsung.com zynq_fpga: use sgtable-based scatterlist wrappers
Bjorn Andersson bjorn.andersson@oss.qualcomm.com soc: qcom: mdt_loader: Ensure we don't read past the ELF header
Igor Pylypiv ipylypiv@google.com ata: libata-scsi: Fix CDL control
Adrian Hunter adrian.hunter@intel.com scsi: ufs: ufs-pci: Fix default runtime and system PM levels
Archana Patni archana.patni@intel.com scsi: ufs: ufs-pci: Fix hibernate state transition for Intel MTL-like host controllers
Damien Le Moal dlemoal@kernel.org ata: libata-scsi: Return aborted command when missing sense and result TF
Damien Le Moal dlemoal@kernel.org ata: libata-scsi: Fix ata_to_sense_error() status handling
Ranjan Kumar ranjan.kumar@broadcom.com scsi: mpi3mr: Fix race between config read submit and interrupt completion
André Draszik andre.draszik@linaro.org scsi: ufs: exynos: Fix programming of HCI_UTRL_NEXUS_TYPE
Macpaul Lin macpaul.lin@mediatek.com scsi: dt-bindings: mediatek,ufs: Add ufs-disable-mcq flag for UFS host
Cristian Ciocaltea cristian.ciocaltea@collabora.com dt-bindings: display: vop2: Add optional PLL clock property for rk3576
Krzysztof Kozlowski krzysztof.kozlowski@linaro.org dt-bindings: display: sprd,sharkl3-dsi-host: Fix missing clocks constraints
Krzysztof Kozlowski krzysztof.kozlowski@linaro.org dt-bindings: display: sprd,sharkl3-dpu: Fix missing clocks constraints
Helge Deller deller@gmx.de apparmor: Fix 8-byte alignment for initial dfa blob streams
Sam Edwards cfsworks@gmail.com arm64: dts: rockchip: Remove workaround that prevented Turing RK1 GPU power regulator control
Emanuele Ghidoli emanuele.ghidoli@toradex.com arm64: dts: ti: k3-am62-verdin: Enable pull-ups on I2C buses
Kaustabh Chakraborty kauschluss@disroot.org arm64: dts: exynos7870-on7xelte: reduce memory ranges to base amount
Judith Mendez jm@ti.com arm64: dts: ti: k3-am62*: Move eMMC pinmux to top level board file
Hong Guan hguan@ti.com arm64: dts: ti: k3-am62a7-sk: fix pinmux for main_uart1
Peter Griffin peter.griffin@linaro.org arm64: dts: exynos: gs101: ufs: add dma-coherent property
Cristian Ciocaltea cristian.ciocaltea@collabora.com arm64: dts: rockchip: Enable HDMI PHY clk provider on rk3576
Cristian Ciocaltea cristian.ciocaltea@collabora.com arm64: dts: rockchip: Add HDMI PHY PLL clock source to VOP2 on rk3576
Kaustabh Chakraborty kauschluss@disroot.org arm64: dts: exynos7870: add quirk to disable USB2 LPM in gadget mode
Alexander Sverdlin alexander.sverdlin@gmail.com arm64: dts: ti: k3-pinctrl: Enable Schmitt Trigger by default
Kaustabh Chakraborty kauschluss@disroot.org arm64: dts: exynos7870-j6lte: reduce memory ranges to base amount
Judith Mendez jm@ti.com arm64: dts: ti: k3-am62-main: Remove eMMC High Speed DDR support
Nick Chan towinchenmi@gmail.com arm64: dts: apple: t8012-j132: Include touchbar framebuffer node
Kyoji Ogasawara sawara04.o@gmail.com btrfs: fix printing of mount info messages for NODATACOW/NODATASUM
Kyoji Ogasawara sawara04.o@gmail.com btrfs: restore mount option info messages during mount
Kyoji Ogasawara sawara04.o@gmail.com btrfs: fix incorrect log message for nobarrier mount option
Naohiro Aota naohiro.aota@wdc.com btrfs: zoned: fix write time activation failure for metadata block group
Zhang Yi yi.zhang@huawei.com ext4: fix hole length calculation overflow in non-extent inodes
Liao Yuanhong liaoyuanhong@vivo.com ext4: use kmalloc_array() for array space allocation
Theodore Ts'o tytso@mit.edu ext4: don't try to clear the orphan_present feature block device is r/o
Ojaswin Mujoo ojaswin@linux.ibm.com ext4: fix reserved gdt blocks handling in fsmap
Ojaswin Mujoo ojaswin@linux.ibm.com ext4: fix fsmap end of range reporting with bigalloc
Andreas Dilger adilger@dilger.ca ext4: check fast symlink for ea_inode correctly
Baokun Li libaokun1@huawei.com ext4: preserve SB_I_VERSION on remount
Masami Hiramatsu (Google) mhiramat@kernel.org tracing: fprobe-event: Sanitize wildcard for fprobe event name
Namjae Jeon linkinjeon@kernel.org ksmbd: extend the connection limiting mechanism to support IPv6
Ziyan Xu ziyan@securitygossip.com ksmbd: fix refcount leak causing resource not released
Helge Deller deller@gmx.de Revert "vgacon: Add check for vc_origin address range in vgacon_scroll()"
Herbert Xu herbert@gondor.apana.org.au crypto: hash - Increase HASH_MAX_DESCSIZE for hmac(sha3-224-s390)
Bharat Bhushan bbhushan2@marvell.com crypto: octeontx2 - Fix address alignment on CN10KB and CN10KA-B0
Bharat Bhushan bbhushan2@marvell.com crypto: octeontx2 - Fix address alignment on CN10K A0/A1 and OcteonTX2
Bharat Bhushan bbhushan2@marvell.com crypto: octeontx2 - Fix address alignment issue on ucode loading
Eric Biggers ebiggers@kernel.org crypto: x86/aegis - Add missing error checks
Eric Biggers ebiggers@kernel.org crypto: x86/aegis - Fix sleeping when disallowed on PREEMPT_RT
Giovanni Cabiddu giovanni.cabiddu@intel.com crypto: qat - flush misc workqueue during device shutdown
John Ernberg john.ernberg@actia.se crypto: caam - Prevent crash on suspend with iMX8QM / iMX8ULP
Ashish Kalra ashish.kalra@amd.com crypto: ccp - Fix SNP panic notifier unregistration
Giovanni Cabiddu giovanni.cabiddu@intel.com crypto: qat - lower priority for skcipher and aead algorithms
Eric Biggers ebiggers@kernel.org lib/crypto: arm64/poly1305: Fix register corruption in no-SIMD contexts
Eric Biggers ebiggers@kernel.org lib/crypto: arm/poly1305: Fix register corruption in no-SIMD contexts
Eric Biggers ebiggers@kernel.org lib/crypto: mips/chacha: Fix clang build and remove unneeded byteswap
David Howells dhowells@redhat.com netfs: Fix unbuffered write error handling
Myrrh Periwinkle myrrhperiwinkle@qtmlabs.xyz vt: defkeymap: Map keycodes above 127 to K_HOLE
Myrrh Periwinkle myrrhperiwinkle@qtmlabs.xyz vt: keyboard: Don't process Unicode characters in K_OFF mode
Youssef Samir quic_yabdulra@quicinc.com bus: mhi: host: Detect events pointing to unexpected TREs
Alexander Wilhelm alexander.wilhelm@westermo.com bus: mhi: host: Fix endianness of BHI vector table
Johan Hovold johan@kernel.org usb: dwc3: imx8mp: fix device leak at unbind
Johan Hovold johan@kernel.org usb: dwc3: meson-g12a: fix device leaks at unbind
Johan Hovold johan@kernel.org usb: musb: omap2430: fix device leak at unbind
Johan Hovold johan@kernel.org usb: gadget: udc: renesas_usb3: fix device leak at unbind
Nathan Chancellor nathan@kernel.org usb: atm: cxacru: Merge cxacru_upload_firmware() into cxacru_heavy_init()
David Lechner dlechner@baylibre.com iio: adc: ad7173: fix num_slots
Finn Thain fthain@linux-m68k.org m68k: Fix lost column on framebuffer debug console
Damien Le Moal dlemoal@kernel.org dm: Check for forbidden splitting of zone write operations
Damien Le Moal dlemoal@kernel.org dm: dm-crypt: Do not partially accept write BIOs with zoned targets
Rafael J. Wysocki rafael.j.wysocki@intel.com PM: runtime: Take active children into account in pm_runtime_get_if_in_use()
Tzung-Bi Shih tzungbi@kernel.org platform/chrome: cros_ec: Unregister notifier in cros_ec_unregister()
Dan Carpenter dan.carpenter@linaro.org cpufreq: armada-8k: Fix off by one in armada_8k_cpufreq_free_table()
Damien Le Moal dlemoal@kernel.org ata: Fix SATA_MOBILE_LPM_POLICY description in Kconfig
Yunhui Cui cuiyunhui@bytedance.com serial: 8250: fix panic due to PSLVERR
-------------
Diffstat:
.../bindings/display/rockchip/rockchip-vop2.yaml | 56 ++++- .../bindings/display/sprd/sprd,sharkl3-dpu.yaml | 2 +- .../display/sprd/sprd,sharkl3-dsi-host.yaml | 2 +- .../devicetree/bindings/ufs/mediatek,ufs.yaml | 4 + Documentation/networking/mptcp-sysctl.rst | 2 + Makefile | 6 +- arch/arm/lib/crypto/poly1305-glue.c | 3 +- arch/arm64/boot/dts/apple/t8012-j132.dts | 1 + arch/arm64/boot/dts/exynos/exynos7870-j6lte.dts | 2 +- arch/arm64/boot/dts/exynos/exynos7870-on7xelte.dts | 2 +- arch/arm64/boot/dts/exynos/exynos7870.dtsi | 1 + arch/arm64/boot/dts/exynos/google/gs101.dtsi | 1 + arch/arm64/boot/dts/rockchip/rk3576.dtsi | 7 +- .../arm64/boot/dts/rockchip/rk3588-turing-rk1.dtsi | 11 - arch/arm64/boot/dts/ti/k3-am62-lp-sk.dts | 24 ++ arch/arm64/boot/dts/ti/k3-am62-main.dtsi | 1 - arch/arm64/boot/dts/ti/k3-am62-verdin.dtsi | 12 +- arch/arm64/boot/dts/ti/k3-am625-sk.dts | 24 ++ arch/arm64/boot/dts/ti/k3-am62a7-sk.dts | 4 +- arch/arm64/boot/dts/ti/k3-am62x-sk-common.dtsi | 24 -- arch/arm64/boot/dts/ti/k3-pinctrl.h | 15 +- arch/arm64/lib/crypto/poly1305-glue.c | 3 +- arch/loongarch/Makefile | 6 + arch/loongarch/kernel/module-sections.c | 38 +-- arch/loongarch/kvm/intc/eiointc.c | 32 +-- arch/loongarch/kvm/intc/ipi.c | 8 +- arch/loongarch/kvm/intc/pch_pic.c | 10 + arch/loongarch/kvm/vcpu.c | 8 +- arch/m68k/kernel/head.S | 31 ++- arch/mips/lib/crypto/chacha-core.S | 20 +- arch/parisc/Makefile | 4 +- arch/parisc/include/asm/pgtable.h | 7 +- arch/parisc/include/asm/special_insns.h | 28 +++ arch/parisc/include/asm/uaccess.h | 21 +- arch/parisc/kernel/cache.c | 6 +- arch/parisc/kernel/entry.S | 17 +- arch/parisc/kernel/syscall.S | 30 ++- arch/parisc/lib/memcpy.c | 19 +- arch/parisc/mm/fault.c | 4 + arch/s390/boot/vmem.c | 3 + arch/s390/hypfs/hypfs_dbfs.c | 19 +- arch/x86/crypto/aegis128-aesni-glue.c | 40 +++- arch/x86/include/asm/xen/hypercall.h | 5 +- arch/x86/kernel/cpu/amd.c | 8 +- arch/x86/kernel/cpu/hygon.c | 3 + block/bfq-iosched.c | 13 +- block/blk-mq-debugfs.c | 1 + block/blk-mq-sched.c | 223 ++++++++++++------ block/blk-mq-sched.h | 12 +- block/blk-mq.c | 29 ++- block/blk-rq-qos.c | 8 +- block/blk-rq-qos.h | 48 ++-- block/blk-sysfs.c | 2 +- block/blk.h | 4 +- block/elevator.c | 38 ++- block/elevator.h | 16 +- block/kyber-iosched.c | 11 +- block/mq-deadline.c | 14 +- crypto/deflate.c | 7 +- drivers/accel/habanalabs/gaudi2/gaudi2.c | 2 +- drivers/acpi/apei/einj-core.c | 12 +- drivers/acpi/pfr_update.c | 2 +- drivers/ata/Kconfig | 32 ++- drivers/ata/libata-scsi.c | 49 ++-- drivers/base/power/runtime.c | 27 ++- drivers/bluetooth/btmtk.c | 7 +- drivers/bus/mhi/host/boot.c | 8 +- drivers/bus/mhi/host/internal.h | 4 +- drivers/bus/mhi/host/main.c | 12 +- drivers/cdx/controller/cdx_rpmsg.c | 3 +- drivers/comedi/comedi_fops.c | 5 + drivers/comedi/drivers.c | 27 +-- drivers/comedi/drivers/pcl726.c | 3 +- drivers/cpufreq/armada-8k-cpufreq.c | 2 +- drivers/cpuidle/governors/menu.c | 29 +-- drivers/crypto/caam/ctrl.c | 5 +- drivers/crypto/caam/intern.h | 1 + drivers/crypto/ccp/sev-dev.c | 10 +- .../crypto/intel/qat/qat_common/adf_common_drv.h | 1 + drivers/crypto/intel/qat/qat_common/adf_init.c | 1 + drivers/crypto/intel/qat/qat_common/adf_isr.c | 5 + drivers/crypto/intel/qat/qat_common/qat_algs.c | 12 +- drivers/crypto/marvell/octeontx2/otx2_cpt_reqmgr.h | 125 +++++++--- .../crypto/marvell/octeontx2/otx2_cptpf_ucode.c | 35 +-- drivers/fpga/zynq-fpga.c | 10 +- drivers/gpu/drm/amd/amdgpu/amdgpu.h | 1 + drivers/gpu/drm/amd/amdgpu/amdgpu_cper.c | 8 +- drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c | 3 + drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 6 +- drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c | 76 +++--- drivers/gpu/drm/amd/amdgpu/amdgpu_job.c | 7 - drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c | 1 + drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.c | 1 + drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c | 21 +- drivers/gpu/drm/amd/amdgpu/aqua_vanjaram.c | 5 +- drivers/gpu/drm/amd/amdgpu/gfx_v12_0.c | 14 +- drivers/gpu/drm/amd/amdgpu/imu_v12_0.c | 13 +- drivers/gpu/drm/amd/amdgpu/mmhub_v3_0_1.c | 57 +++-- drivers/gpu/drm/amd/amdgpu/mmhub_v3_3.c | 121 +++++++++- drivers/gpu/drm/amd/amdgpu/mmhub_v4_1_0.c | 34 ++- drivers/gpu/drm/amd/amdgpu/psp_v14_0.c | 2 + drivers/gpu/drm/amd/amdgpu/soc15.c | 2 + .../gpu/drm/amd/amdkfd/kfd_device_queue_manager.c | 2 +- drivers/gpu/drm/amd/amdkfd/kfd_module.c | 2 +- drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_v9.c | 61 ++++- .../gpu/drm/amd/amdkfd/kfd_process_queue_manager.c | 20 +- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 19 +- .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crtc.c | 28 +++ .../drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c | 2 +- drivers/gpu/drm/amd/display/dc/bios/bios_parser.c | 5 +- .../gpu/drm/amd/display/dc/bios/command_table.c | 2 +- drivers/gpu/drm/amd/display/dc/clk_mgr/clk_mgr.c | 1 - .../amd/display/dc/clk_mgr/dce100/dce_clk_mgr.c | 19 +- .../amd/display/dc/clk_mgr/dce110/dce110_clk_mgr.c | 40 ++-- .../amd/display/dc/clk_mgr/dce60/dce60_clk_mgr.c | 31 +-- drivers/gpu/drm/amd/display/dc/core/dc.c | 34 ++- .../amd/display/dc/resource/dce60/dce60_resource.c | 34 +-- .../gpu/drm/amd/display/modules/hdcp/hdcp_psp.c | 3 + drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c | 16 ++ drivers/gpu/drm/amd/pm/swsmu/smu14/smu_v14_0.c | 11 +- .../gpu/drm/amd/pm/swsmu/smu14/smu_v14_0_2_ppt.c | 30 ++- drivers/gpu/drm/display/drm_dp_helper.c | 2 +- drivers/gpu/drm/drm_format_helper.c | 108 ++++++++- drivers/gpu/drm/drm_format_internal.h | 8 + drivers/gpu/drm/drm_panic_qr.rs | 22 +- drivers/gpu/drm/hisilicon/hibmc/dp/dp_link.c | 14 +- drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c | 22 +- drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h | 1 + drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_i2c.c | 5 + drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_vdac.c | 11 +- drivers/gpu/drm/i915/display/intel_display_irq.c | 4 + drivers/gpu/drm/i915/display/intel_tc.c | 93 ++++++-- drivers/gpu/drm/i915/gt/intel_workarounds.c | 20 +- drivers/gpu/drm/nouveau/nvif/vmm.c | 3 +- .../gpu/drm/nouveau/nvkm/subdev/gsp/rm/r535/rpc.c | 4 +- drivers/gpu/drm/nova/file.rs | 3 +- drivers/gpu/drm/tests/drm_format_helper_test.c | 111 ++------- drivers/gpu/drm/xe/Kconfig | 1 + drivers/gpu/drm/xe/xe_migrate.c | 2 +- drivers/gpu/drm/xe/xe_pxp_submit.c | 2 +- drivers/gpu/drm/xe/xe_shrinker.c | 51 +++- drivers/gpu/drm/xe/xe_vm.c | 48 ++-- drivers/gpu/drm/xe/xe_vm.h | 2 +- drivers/hwmon/gsc-hwmon.c | 4 +- drivers/i2c/busses/i2c-qcom-geni.c | 6 +- drivers/i2c/busses/i2c-rtl9300.c | 20 +- drivers/iio/accel/sca3300.c | 2 +- drivers/iio/adc/Kconfig | 2 +- drivers/iio/adc/ad7124.c | 14 +- drivers/iio/adc/ad7173.c | 137 ++++++++--- drivers/iio/adc/ad7380.c | 1 + drivers/iio/adc/ad_sigma_delta.c | 4 +- drivers/iio/adc/rzg2l_adc.c | 33 +-- drivers/iio/imu/bno055/bno055.c | 11 +- drivers/iio/imu/inv_icm42600/inv_icm42600.h | 8 +- drivers/iio/imu/inv_icm42600/inv_icm42600_accel.c | 31 ++- drivers/iio/imu/inv_icm42600/inv_icm42600_buffer.c | 22 +- drivers/iio/imu/inv_icm42600/inv_icm42600_buffer.h | 10 +- drivers/iio/imu/inv_icm42600/inv_icm42600_core.c | 6 +- drivers/iio/imu/inv_icm42600/inv_icm42600_gyro.c | 41 ++-- drivers/iio/imu/inv_icm42600/inv_icm42600_temp.c | 12 +- drivers/iio/light/as73211.c | 2 +- drivers/iio/pressure/bmp280-core.c | 9 +- drivers/iio/proximity/isl29501.c | 14 +- drivers/iio/temperature/maxim_thermocouple.c | 26 ++- drivers/infiniband/core/umem_odp.c | 4 +- drivers/infiniband/hw/bnxt_re/ib_verbs.c | 8 +- drivers/infiniband/hw/bnxt_re/main.c | 23 ++ drivers/infiniband/hw/bnxt_re/qplib_fp.c | 30 +-- drivers/infiniband/hw/bnxt_re/qplib_fp.h | 2 - drivers/infiniband/hw/bnxt_re/qplib_res.c | 2 + drivers/infiniband/hw/erdma/erdma_verbs.c | 6 +- drivers/infiniband/hw/hns/hns_roce_hw_v2.c | 6 +- drivers/infiniband/hw/hns/hns_roce_restrack.c | 9 +- drivers/infiniband/sw/rxe/rxe_net.c | 29 +-- drivers/infiniband/sw/rxe/rxe_qp.c | 2 +- drivers/iommu/amd/init.c | 4 +- drivers/iommu/apple-dart.c | 1 - drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c | 2 +- drivers/iommu/intel/iommu.c | 1 - drivers/iommu/iommufd/selftest.c | 1 - drivers/iommu/riscv/iommu.c | 3 +- drivers/iommu/virtio-iommu.c | 19 +- drivers/md/dm-crypt.c | 47 +++- drivers/md/dm-raid.c | 42 ++-- drivers/md/dm.c | 17 +- drivers/md/md-bitmap.c | 8 +- drivers/md/md-cluster.c | 16 +- drivers/md/md.c | 110 ++++++--- drivers/md/md.h | 2 +- drivers/md/raid0.c | 6 +- drivers/md/raid1-10.c | 2 +- drivers/md/raid1.c | 10 +- drivers/md/raid10.c | 16 +- drivers/md/raid5-ppl.c | 6 +- drivers/md/raid5.c | 30 +-- drivers/media/cec/usb/rainshadow/rainshadow-cec.c | 3 +- drivers/media/i2c/hi556.c | 26 ++- drivers/media/i2c/mt9m114.c | 8 - drivers/media/i2c/ov2659.c | 3 +- drivers/media/pci/intel/ipu6/ipu6-isys-csi2.c | 12 +- drivers/media/pci/intel/ivsc/mei_ace.c | 2 + drivers/media/pci/intel/ivsc/mei_csi.c | 2 + .../platform/qcom/camss/camss-csiphy-3ph-1-0.c | 3 +- drivers/media/platform/qcom/camss/camss.c | 20 +- drivers/media/platform/qcom/iris/iris_buffer.c | 20 +- drivers/media/platform/qcom/iris/iris_buffer.h | 3 +- drivers/media/platform/qcom/iris/iris_ctrls.c | 7 +- .../platform/qcom/iris/iris_hfi_gen1_command.c | 27 +-- .../platform/qcom/iris/iris_hfi_gen1_defines.h | 1 - .../platform/qcom/iris/iris_hfi_gen1_response.c | 20 +- .../platform/qcom/iris/iris_hfi_gen2_command.c | 4 +- .../platform/qcom/iris/iris_hfi_gen2_response.c | 11 +- drivers/media/platform/qcom/iris/iris_hfi_queue.c | 2 +- drivers/media/platform/qcom/iris/iris_instance.h | 2 + .../platform/qcom/iris/iris_platform_common.h | 2 +- .../platform/qcom/iris/iris_platform_sm8250.c | 9 - drivers/media/platform/qcom/iris/iris_state.c | 2 +- drivers/media/platform/qcom/iris/iris_state.h | 1 + drivers/media/platform/qcom/iris/iris_vb2.c | 15 +- drivers/media/platform/qcom/iris/iris_vdec.c | 9 +- drivers/media/platform/qcom/iris/iris_vidc.c | 33 ++- drivers/media/platform/qcom/venus/core.c | 18 +- drivers/media/platform/qcom/venus/core.h | 2 + drivers/media/platform/qcom/venus/hfi_venus.c | 5 + drivers/media/platform/qcom/venus/vdec.c | 5 +- drivers/media/platform/qcom/venus/venc.c | 5 +- drivers/media/platform/raspberrypi/pisp_be/Kconfig | 1 + .../media/platform/raspberrypi/pisp_be/pisp_be.c | 5 +- .../media/platform/verisilicon/rockchip_vpu_hw.c | 9 - drivers/media/test-drivers/vivid/vivid-ctrls.c | 3 +- drivers/media/test-drivers/vivid/vivid-vid-cap.c | 4 +- drivers/media/usb/gspca/vicam.c | 10 +- drivers/media/usb/usbtv/usbtv-video.c | 4 + drivers/media/v4l2-core/v4l2-ctrls-core.c | 1 - drivers/memstick/core/memstick.c | 1 - drivers/memstick/host/rtsx_usb_ms.c | 1 + drivers/mfd/mt6397-core.c | 12 +- drivers/mmc/host/sdhci-of-arasan.c | 33 ++- drivers/mmc/host/sdhci-pci-gli.c | 37 +-- drivers/mmc/host/sdhci_am654.c | 18 ++ drivers/most/core.c | 2 +- drivers/mtd/nand/raw/fsmc_nand.c | 2 + drivers/mtd/nand/raw/renesas-nand-controller.c | 6 + drivers/mtd/nand/spi/core.c | 5 +- drivers/mtd/spi-nor/swp.c | 19 +- drivers/net/bonding/bond_3ad.c | 67 ++++-- drivers/net/bonding/bond_options.c | 1 + drivers/net/dsa/microchip/ksz_common.c | 6 + drivers/net/ethernet/airoha/airoha_ppe.c | 4 +- drivers/net/ethernet/broadcom/bnxt/bnxt.c | 2 +- drivers/net/ethernet/google/gve/gve_main.c | 2 + drivers/net/ethernet/intel/igc/igc_main.c | 14 +- drivers/net/ethernet/intel/ixgbe/devlink/devlink.c | 1 + drivers/net/ethernet/intel/ixgbe/ixgbe_xsk.c | 4 +- .../net/ethernet/marvell/octeontx2/af/rvu_npc_fs.c | 4 +- drivers/net/ethernet/mediatek/mtk_ppe_offload.c | 2 + drivers/net/ethernet/mellanox/mlx5/core/en/dcbnl.h | 1 - .../ethernet/mellanox/mlx5/core/en/port_buffer.c | 18 +- .../ethernet/mellanox/mlx5/core/en/tc/ct_fs_hmfs.c | 2 + drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c | 12 +- .../ethernet/mellanox/mlx5/core/esw/devlink_port.c | 4 +- .../net/ethernet/mellanox/mlx5/core/mlx5_core.h | 2 + drivers/net/ethernet/mellanox/mlx5/core/port.c | 20 ++ .../mellanox/mlx5/core/steering/hws/bwc_complex.c | 41 ++-- .../ethernet/mellanox/mlx5/core/steering/hws/cmd.c | 1 + .../ethernet/mellanox/mlx5/core/steering/hws/cmd.h | 1 + .../mellanox/mlx5/core/steering/hws/fs_hws.c | 1 + .../mellanox/mlx5/core/steering/hws/matcher.c | 5 +- .../mellanox/mlx5/core/steering/hws/mlx5hws.h | 1 + .../mellanox/mlx5/core/steering/hws/send.c | 1 - .../mellanox/mlx5/core/steering/hws/table.c | 13 +- .../mellanox/mlx5/core/steering/hws/table.h | 3 +- drivers/net/ethernet/mellanox/mlxsw/spectrum.c | 2 + drivers/net/ethernet/mellanox/mlxsw/trap.h | 1 + drivers/net/ethernet/microchip/lan865x/lan865x.c | 21 ++ drivers/net/ethernet/realtek/rtase/rtase.h | 2 +- drivers/net/ethernet/stmicro/stmmac/dwmac-thead.c | 9 +- drivers/net/ethernet/ti/icssg/icssg_prueth.c | 72 +++--- drivers/net/ethernet/xilinx/xilinx_axienet_main.c | 8 +- drivers/net/phy/mscc/mscc.h | 12 + drivers/net/phy/mscc/mscc_main.c | 12 + drivers/net/phy/mscc/mscc_ptp.c | 49 +++- drivers/net/ppp/ppp_generic.c | 17 +- drivers/net/usb/asix_devices.c | 2 +- drivers/net/wireless/ath/ath11k/ce.c | 3 - drivers/net/wireless/ath/ath11k/dp_rx.c | 3 - drivers/net/wireless/ath/ath11k/hal.c | 33 ++- drivers/net/wireless/ath/ath12k/ce.c | 3 - drivers/net/wireless/ath/ath12k/hal.c | 38 ++- .../broadcom/brcm80211/brcmsmac/phy/phy_lcn.c | 2 +- drivers/pci/controller/dwc/pci-imx6.c | 12 +- drivers/pci/controller/dwc/pcie-designware.c | 8 + drivers/pci/controller/pcie-rockchip-ep.c | 4 +- drivers/pci/controller/pcie-rockchip-host.c | 49 ++-- drivers/pci/controller/pcie-rockchip.h | 12 +- drivers/pci/endpoint/pci-ep-cfs.c | 1 + drivers/pci/endpoint/pci-epf-core.c | 2 +- drivers/pci/pci.h | 32 +-- drivers/pci/pcie/portdrv.c | 2 +- drivers/phy/qualcomm/phy-qcom-m31.c | 14 +- drivers/platform/chrome/cros_ec.c | 3 + drivers/platform/x86/amd/hsmp/hsmp.c | 5 + .../intel/uncore-frequency/uncore-frequency-tpmi.c | 5 + drivers/pwm/pwm-imx-tpm.c | 9 + drivers/pwm/pwm-mediatek.c | 71 +++--- drivers/regulator/pca9450-regulator.c | 13 +- drivers/regulator/tps65219-regulator.c | 12 +- drivers/s390/char/sclp.c | 11 +- drivers/scsi/mpi3mr/mpi3mr.h | 6 +- drivers/scsi/mpi3mr/mpi3mr_fw.c | 17 +- drivers/scsi/mpi3mr/mpi3mr_os.c | 2 + drivers/scsi/qla4xxx/ql4_os.c | 2 + drivers/soc/qcom/mdt_loader.c | 43 ++++ drivers/soc/tegra/pmc.c | 51 ++-- drivers/spi/spi-fsl-lpspi.c | 8 +- drivers/spi/spi-qpic-snand.c | 22 +- drivers/staging/media/imx/imx-media-csc-scaler.c | 2 +- drivers/tty/serial/8250/8250_port.c | 3 +- drivers/tty/vt/defkeymap.c_shipped | 112 +++++++++ drivers/tty/vt/keyboard.c | 2 +- drivers/ufs/core/ufshcd.c | 10 +- drivers/ufs/host/ufs-exynos.c | 4 +- drivers/ufs/host/ufs-qcom.c | 42 ++-- drivers/ufs/host/ufshcd-pci.c | 42 +++- drivers/usb/atm/cxacru.c | 172 +++++++------- drivers/usb/core/hcd.c | 20 +- drivers/usb/core/quirks.c | 1 + drivers/usb/dwc3/dwc3-imx8mp.c | 7 +- drivers/usb/dwc3/dwc3-meson-g12a.c | 3 + drivers/usb/dwc3/dwc3-pci.c | 2 + drivers/usb/dwc3/ep0.c | 20 +- drivers/usb/dwc3/gadget.c | 19 +- drivers/usb/gadget/udc/renesas_usb3.c | 1 + drivers/usb/host/xhci-hub.c | 3 +- drivers/usb/host/xhci-mem.c | 22 +- drivers/usb/host/xhci-pci-renesas.c | 7 +- drivers/usb/host/xhci-ring.c | 9 +- drivers/usb/host/xhci.c | 23 +- drivers/usb/host/xhci.h | 3 +- drivers/usb/musb/omap2430.c | 14 +- drivers/usb/storage/realtek_cr.c | 2 +- drivers/usb/storage/unusual_devs.h | 29 +++ drivers/usb/typec/tcpm/maxim_contaminant.c | 58 +++++ drivers/usb/typec/tcpm/tcpci_maxim.h | 1 + drivers/vhost/vsock.c | 6 +- drivers/video/console/vgacon.c | 2 +- fs/btrfs/ctree.c | 23 +- fs/btrfs/extent-tree.c | 2 +- fs/btrfs/extent_io.c | 94 ++++---- fs/btrfs/extent_io.h | 2 +- fs/btrfs/fiemap.c | 2 +- fs/btrfs/free-space-tree.c | 17 +- fs/btrfs/inode.c | 8 +- fs/btrfs/print-tree.c | 2 +- fs/btrfs/qgroup.c | 6 +- fs/btrfs/relocation.c | 4 +- fs/btrfs/subpage.c | 258 +++++++++++---------- fs/btrfs/subpage.h | 45 +++- fs/btrfs/super.c | 13 +- fs/btrfs/tree-log.c | 4 +- fs/btrfs/zoned.c | 70 ++++-- fs/buffer.c | 2 +- fs/debugfs/inode.c | 11 +- fs/erofs/Kconfig | 18 +- fs/ext4/fsmap.c | 23 +- fs/ext4/indirect.c | 4 +- fs/ext4/inode.c | 2 +- fs/ext4/orphan.c | 5 +- fs/ext4/super.c | 8 +- fs/f2fs/node.c | 10 + fs/fhandle.c | 2 +- fs/internal.h | 3 + fs/iomap/direct-io.c | 14 +- fs/jbd2/checkpoint.c | 1 + fs/libfs.c | 27 ++- fs/namespace.c | 69 +++--- fs/netfs/read_collect.c | 4 +- fs/netfs/write_collect.c | 10 +- fs/netfs/write_issue.c | 4 +- fs/nfs/pagelist.c | 9 +- fs/nfs/write.c | 29 +-- fs/overlayfs/copy_up.c | 2 +- fs/proc/task_mmu.c | 4 +- fs/smb/client/smb2ops.c | 2 +- fs/smb/server/connection.c | 3 +- fs/smb/server/connection.h | 7 +- fs/smb/server/oplock.c | 13 +- fs/smb/server/transport_rdma.c | 5 +- fs/smb/server/transport_rdma.h | 4 +- fs/smb/server/transport_tcp.c | 26 ++- fs/splice.c | 3 + fs/squashfs/super.c | 14 +- fs/xfs/libxfs/xfs_refcount.c | 4 +- fs/xfs/scrub/common.c | 3 +- fs/xfs/scrub/repair.c | 12 +- fs/xfs/scrub/scrub.c | 5 +- fs/xfs/xfs_attr_item.c | 5 +- fs/xfs/xfs_discard.c | 12 +- fs/xfs/xfs_fsmap.c | 4 +- fs/xfs/xfs_icache.c | 5 +- fs/xfs/xfs_inode.c | 7 +- fs/xfs/xfs_itable.c | 24 +- fs/xfs/xfs_iwalk.c | 11 +- fs/xfs/xfs_notify_failure.c | 6 +- fs/xfs/xfs_qm.c | 10 +- fs/xfs/xfs_rtalloc.c | 13 +- fs/xfs/xfs_trans.c | 56 ++--- fs/xfs/xfs_trans.h | 3 +- fs/xfs/xfs_zone_alloc.c | 10 +- fs/xfs/xfs_zone_gc.c | 5 +- include/crypto/hash.h | 2 +- include/crypto/internal/acompress.h | 5 +- include/drm/drm_format_helper.h | 9 + include/drm/intel/pciids.h | 1 + include/linux/blkdev.h | 1 + include/linux/compiler.h | 8 - include/linux/iosys-map.h | 7 +- include/linux/iov_iter.h | 20 +- include/linux/kcov.h | 47 +--- include/linux/mlx5/mlx5_ifc.h | 14 +- include/linux/netfs.h | 1 + include/linux/nfs_page.h | 1 + include/net/bluetooth/bluetooth.h | 4 +- include/net/bluetooth/hci.h | 1 + include/net/bluetooth/hci_core.h | 54 ++++- include/net/bond_3ad.h | 1 + include/net/devlink.h | 6 +- include/net/sch_generic.h | 11 +- include/sound/cs35l56.h | 5 +- include/trace/events/btrfs.h | 2 +- include/uapi/linux/pfrut.h | 1 + include/uapi/linux/raid/md_p.h | 2 +- io_uring/futex.c | 3 + kernel/Kconfig.kexec | 1 + kernel/cgroup/cpuset.c | 9 +- kernel/cgroup/rstat.c | 3 + kernel/kexec_handover.c | 29 ++- kernel/sched/ext.c | 4 + kernel/signal.c | 6 +- kernel/trace/ftrace.c | 19 +- kernel/trace/trace.c | 34 ++- kernel/trace/trace.h | 10 +- mm/damon/core.c | 15 +- mm/damon/paddr.c | 4 + mm/debug_vm_pgtable.c | 9 +- mm/filemap.c | 3 +- mm/kasan/kasan_test_c.c | 2 +- mm/memory-failure.c | 8 + mm/mremap.c | 41 ++-- net/bluetooth/hci_conn.c | 17 +- net/bluetooth/hci_core.c | 27 ++- net/bluetooth/hci_event.c | 15 +- net/bluetooth/hci_sync.c | 33 +-- net/bluetooth/iso.c | 20 +- net/bluetooth/mgmt.c | 13 +- net/bridge/br_multicast.c | 16 ++ net/bridge/br_private.h | 2 + net/core/dev.c | 12 + net/devlink/port.c | 2 +- net/hsr/hsr_slave.c | 8 +- net/ipv4/netfilter/nf_reject_ipv4.c | 6 +- net/ipv6/netfilter/nf_reject_ipv6.c | 5 +- net/ipv6/seg6_hmac.c | 6 +- net/mptcp/options.c | 6 +- net/mptcp/pm.c | 18 +- net/mptcp/pm_kernel.c | 1 - net/sched/sch_cake.c | 14 +- net/sched/sch_codel.c | 12 +- net/sched/sch_fq.c | 12 +- net/sched/sch_fq_codel.c | 12 +- net/sched/sch_fq_pie.c | 12 +- net/sched/sch_hhf.c | 12 +- net/sched/sch_htb.c | 2 +- net/sched/sch_pie.c | 12 +- net/smc/af_smc.c | 3 +- net/tls/tls_sw.c | 7 +- net/vmw_vsock/virtio_transport.c | 12 +- rust/kernel/alloc/allocator.rs | 30 ++- rust/kernel/alloc/allocator_test.rs | 11 + rust/kernel/drm/device.rs | 32 ++- rust/kernel/faux.rs | 2 +- security/apparmor/lsm.c | 4 +- sound/core/timer.c | 4 +- sound/pci/hda/patch_realtek.c | 2 + sound/pci/hda/tas2781_hda_i2c.c | 2 +- sound/soc/codecs/cs35l56-sdw.c | 69 ------ sound/soc/codecs/cs35l56-shared.c | 29 ++- sound/soc/codecs/cs35l56.c | 2 +- sound/soc/codecs/cs35l56.h | 3 - sound/soc/sof/amd/acp-loader.c | 6 +- sound/usb/stream.c | 2 +- sound/usb/validate.c | 2 +- tools/objtool/arch/loongarch/special.c | 23 ++ tools/testing/selftests/net/mptcp/mptcp_connect.c | 5 +- tools/testing/selftests/net/mptcp/mptcp_inq.c | 5 +- tools/testing/selftests/net/mptcp/mptcp_sockopt.c | 5 +- tools/testing/selftests/net/mptcp/pm_netlink.sh | 1 + 498 files changed, 4907 insertions(+), 2746 deletions(-)
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Yunhui Cui cuiyunhui@bytedance.com
commit 7f8fdd4dbffc05982b96caf586f77a014b2a9353 upstream.
When the PSLVERR_RESP_EN parameter is set to 1, the device generates an error response if an attempt is made to read an empty RBR (Receive Buffer Register) while the FIFO is enabled.
In serial8250_do_startup(), calling serial_port_out(port, UART_LCR, UART_LCR_WLEN8) triggers dw8250_check_lcr(), which invokes dw8250_force_idle() and serial8250_clear_and_reinit_fifos(). The latter function enables the FIFO via serial_out(p, UART_FCR, p->fcr). Execution proceeds to the serial_port_in(port, UART_RX). This satisfies the PSLVERR trigger condition.
When another CPU (e.g., using printk()) is accessing the UART (UART is busy), the current CPU fails the check (value & ~UART_LCR_SPAR) == (lcr & ~UART_LCR_SPAR) in dw8250_check_lcr(), causing it to enter dw8250_force_idle().
Put serial_port_out(port, UART_LCR, UART_LCR_WLEN8) under the port->lock to fix this issue.
Panic backtrace: [ 0.442336] Oops - unknown exception [#1] [ 0.442343] epc : dw8250_serial_in32+0x1e/0x4a [ 0.442351] ra : serial8250_do_startup+0x2c8/0x88e ... [ 0.442416] console_on_rootfs+0x26/0x70
Fixes: c49436b657d0 ("serial: 8250_dw: Improve unwritable LCR workaround") Link: https://lore.kernel.org/all/84cydt5peu.fsf@jogness.linutronix.de/T/ Signed-off-by: Yunhui Cui cuiyunhui@bytedance.com Reviewed-by: John Ogness john.ogness@linutronix.de Cc: stable stable@kernel.org Link: https://lore.kernel.org/r/20250723023322.464-2-cuiyunhui@bytedance.com [ adapted to inline code structure without separate serial8250_initialize helper function ] Signed-off-by: Sasha Levin sashal@kernel.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/tty/serial/8250/8250_port.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-)
--- a/drivers/tty/serial/8250/8250_port.c +++ b/drivers/tty/serial/8250/8250_port.c @@ -2376,9 +2376,8 @@ int serial8250_do_startup(struct uart_po /* * Now, initialize the UART */ - serial_port_out(port, UART_LCR, UART_LCR_WLEN8); - uart_port_lock_irqsave(port, &flags); + serial_port_out(port, UART_LCR, UART_LCR_WLEN8); if (up->port.flags & UPF_FOURPORT) { if (!up->port.irq) up->port.mctrl |= TIOCM_OUT1;
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Damien Le Moal dlemoal@kernel.org
commit ed62a62a18bc144f73eadf866ae46842e8f6606e upstream.
Improve the description of the possible default SATA link power management policies and add the missing description for policy 5. No functional changes.
Fixes: a5ec5a7bfd1f ("ata: ahci: Support state with min power but Partial low power state") Cc: stable@vger.kernel.org Signed-off-by: Damien Le Moal dlemoal@kernel.org Reviewed-by: Hannes Reinecke hare@suse.de Reviewed-by: Niklas Cassel cassel@kernel.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/ata/Kconfig | 32 ++++++++++++++++++++++++-------- 1 file changed, 24 insertions(+), 8 deletions(-)
--- a/drivers/ata/Kconfig +++ b/drivers/ata/Kconfig @@ -117,23 +117,39 @@ config SATA_AHCI
config SATA_MOBILE_LPM_POLICY int "Default SATA Link Power Management policy" - range 0 4 + range 0 5 default 3 depends on SATA_AHCI help Select the Default SATA Link Power Management (LPM) policy to use for chipsets / "South Bridges" supporting low-power modes. Such chipsets are ubiquitous across laptops, desktops and servers. + Each policy combines power saving states and features: + - Partial: The Phy logic is powered but is in a reduced power + state. The exit latency from this state is no longer than + 10us). + - Slumber: The Phy logic is powered but is in an even lower power + state. The exit latency from this state is potentially + longer, but no longer than 10ms. + - DevSleep: The Phy logic may be powered down. The exit latency from + this state is no longer than 20 ms, unless otherwise + specified by DETO in the device Identify Device Data log. + - HIPM: Host Initiated Power Management (host automatically + transitions to partial and slumber). + - DIPM: Device Initiated Power Management (device automatically + transitions to partial and slumber).
- The value set has the following meanings: + The possible values for the default SATA link power management + policies are: 0 => Keep firmware settings - 1 => Maximum performance - 2 => Medium power - 3 => Medium power with Device Initiated PM enabled - 4 => Minimum power + 1 => No power savings (maximum performance) + 2 => HIPM (Partial) + 3 => HIPM (Partial) and DIPM (Partial and Slumber) + 4 => HIPM (Partial and DevSleep) and DIPM (Partial and Slumber) + 5 => HIPM (Slumber and DevSleep) and DIPM (Partial and Slumber)
- Note "Minimum power" is known to cause issues, including disk - corruption, with some disks and should not be used. + Excluding the value 0, higher values represent policies with higher + power savings.
config SATA_AHCI_PLATFORM tristate "Platform AHCI SATA support"
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Dan Carpenter dan.carpenter@linaro.org
commit 4a26df233266a628157d7f0285451d8655defdfc upstream.
The freq_tables[] array has num_possible_cpus() elements so, to avoid an out of bounds access, this loop should be capped at "< nb_cpus" instead of "<= nb_cpus". The freq_tables[] array is allocated in armada_8k_cpufreq_init().
Cc: stable@vger.kernel.org Fixes: f525a670533d ("cpufreq: ap806: add cpufreq driver for Armada 8K") Signed-off-by: Dan Carpenter dan.carpenter@linaro.org Signed-off-by: Viresh Kumar viresh.kumar@linaro.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/cpufreq/armada-8k-cpufreq.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
--- a/drivers/cpufreq/armada-8k-cpufreq.c +++ b/drivers/cpufreq/armada-8k-cpufreq.c @@ -103,7 +103,7 @@ static void armada_8k_cpufreq_free_table { int opps_index, nb_cpus = num_possible_cpus();
- for (opps_index = 0 ; opps_index <= nb_cpus; opps_index++) { + for (opps_index = 0 ; opps_index < nb_cpus; opps_index++) { int i;
/* If cpu_dev is NULL then we reached the end of the array */
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Tzung-Bi Shih tzungbi@kernel.org
commit e2374953461947eee49f69b3e3204ff080ef31b1 upstream.
The blocking notifier is registered in cros_ec_register(); however, it isn't unregistered in cros_ec_unregister().
Fix it.
Fixes: 42cd0ab476e2 ("platform/chrome: cros_ec: Query EC protocol version if EC transitions between RO/RW") Cc: stable@vger.kernel.org Reviewed-by: Benson Leung bleung@chromium.org Link: https://lore.kernel.org/r/20250722120513.234031-1-tzungbi@kernel.org Signed-off-by: Tzung-Bi Shih tzungbi@kernel.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/platform/chrome/cros_ec.c | 3 +++ 1 file changed, 3 insertions(+)
--- a/drivers/platform/chrome/cros_ec.c +++ b/drivers/platform/chrome/cros_ec.c @@ -318,6 +318,9 @@ EXPORT_SYMBOL(cros_ec_register); */ void cros_ec_unregister(struct cros_ec_device *ec_dev) { + if (ec_dev->mkbp_event_supported) + blocking_notifier_chain_unregister(&ec_dev->event_notifier, + &ec_dev->notifier_ready); platform_device_unregister(ec_dev->pd); platform_device_unregister(ec_dev->ec); mutex_destroy(&ec_dev->lock);
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Rafael J. Wysocki rafael.j.wysocki@intel.com
commit 51888393cc64dd0462d0b96c13ab94873abbc030 upstream.
For all practical purposes, there is no difference between the situation in which a given device is not ignoring children and its active child count is nonzero and the situation in which its runtime PM usage counter is nonzero. However, pm_runtime_get_if_in_use() will only increment the device's usage counter and return 1 in the latter case.
For consistency, make it do so in the former case either by adjusting pm_runtime_get_conditional() and update the related kerneldoc comments accordingly.
Fixes: c111566bea7c ("PM: runtime: Add pm_runtime_get_if_active()") Signed-off-by: Rafael J. Wysocki rafael.j.wysocki@intel.com Reviewed-by: Ulf Hansson ulf.hansson@linaro.org Reviewed-by: Sakari Ailus sakari.ailus@linux.intel.com Cc: 5.10+ stable@vger.kernel.org # 5.10+: c0ef3df8dbae: PM: runtime: Simplify pm_runtime_get_if_active() usage Cc: 5.10+ stable@vger.kernel.org # 5.10+ Link: https://patch.msgid.link/12700973.O9o76ZdvQC@rjwysocki.net Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/base/power/runtime.c | 27 ++++++++++++++++++--------- 1 file changed, 18 insertions(+), 9 deletions(-)
--- a/drivers/base/power/runtime.c +++ b/drivers/base/power/runtime.c @@ -1191,10 +1191,12 @@ EXPORT_SYMBOL_GPL(__pm_runtime_resume); * * Return -EINVAL if runtime PM is disabled for @dev. * - * Otherwise, if the runtime PM status of @dev is %RPM_ACTIVE and either - * @ign_usage_count is %true or the runtime PM usage counter of @dev is not - * zero, increment the usage counter of @dev and return 1. Otherwise, return 0 - * without changing the usage counter. + * Otherwise, if its runtime PM status is %RPM_ACTIVE and (1) @ign_usage_count + * is set, or (2) @dev is not ignoring children and its active child count is + * nonero, or (3) the runtime PM usage counter of @dev is not zero, increment + * the usage counter of @dev and return 1. + * + * Otherwise, return 0 without changing the usage counter. * * If @ign_usage_count is %true, this function can be used to prevent suspending * the device when its runtime PM status is %RPM_ACTIVE. @@ -1216,7 +1218,8 @@ static int pm_runtime_get_conditional(st retval = -EINVAL; } else if (dev->power.runtime_status != RPM_ACTIVE) { retval = 0; - } else if (ign_usage_count) { + } else if (ign_usage_count || (!dev->power.ignore_children && + atomic_read(&dev->power.child_count) > 0)) { retval = 1; atomic_inc(&dev->power.usage_count); } else { @@ -1249,10 +1252,16 @@ EXPORT_SYMBOL_GPL(pm_runtime_get_if_acti * @dev: Target device. * * Increment the runtime PM usage counter of @dev if its runtime PM status is - * %RPM_ACTIVE and its runtime PM usage counter is greater than 0, in which case - * it returns 1. If the device is in a different state or its usage_count is 0, - * 0 is returned. -EINVAL is returned if runtime PM is disabled for the device, - * in which case also the usage_count will remain unmodified. + * %RPM_ACTIVE and its runtime PM usage counter is greater than 0 or it is not + * ignoring children and its active child count is nonzero. 1 is returned in + * this case. + * + * If @dev is in a different state or it is not in use (that is, its usage + * counter is 0, or it is ignoring children, or its active child count is 0), + * 0 is returned. + * + * -EINVAL is returned if runtime PM is disabled for the device, in which case + * also the usage counter of @dev is not updated. */ int pm_runtime_get_if_in_use(struct device *dev) {
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Damien Le Moal dlemoal@kernel.org
commit e549663849e5bb3b985dc2d293069f0d9747ae72 upstream.
Read and write operations issued to a dm-crypt target may be split according to the dm-crypt internal limits defined by the max_read_size and max_write_size module parameters (default is 128 KB). The intent is to improve processing time of large BIOs by splitting them into smaller operations that can be parallelized on different CPUs.
For zoned dm-crypt targets, this BIO splitting is still done but without the parallel execution to ensure that the issuing order of write operations to the underlying devices remains sequential. However, the splitting itself causes other problems:
1) Since dm-crypt relies on the block layer zone write plugging to handle zone append emulation using regular write operations, the reminder of a split write BIO will always be plugged into the target zone write plugged. Once the on-going write BIO finishes, this reminder BIO is unplugged and issued from the zone write plug work. If this reminder BIO itself needs to be split, the reminder will be re-issued and plugged again, but that causes a call to a blk_queue_enter(), which may block if a queue freeze operation was initiated. This results in a deadlock as DM submission still holds BIOs that the queue freeze side is waiting for.
2) dm-crypt relies on the emulation done by the block layer using regular write operations for processing zone append operations. This still requires to properly return the written sector as the BIO sector of the original BIO. However, this can be done correctly only and only if there is a single clone BIO used for processing the original zone append operation issued by the user. If the size of a zone append operation is larger than dm-crypt max_write_size, then the orginal BIO will be split and processed as a chain of regular write operations. Such chaining result in an incorrect written sector being returned to the zone append issuer using the original BIO sector. This in turn results in file system data corruptions using xfs or btrfs.
Fix this by modifying get_max_request_size() to always return the size of the BIO to avoid it being split with dm_accpet_partial_bio() in crypt_map(). get_max_request_size() is renamed to get_max_request_sectors() to clarify the unit of the value returned and its interface is changed to take a struct dm_target pointer and a pointer to the struct bio being processed. In addition to this change, to ensure that crypt_alloc_buffer() works correctly, set the dm-crypt device max_hw_sectors limit to be at most BIO_MAX_VECS << PAGE_SECTORS_SHIFT (1 MB with a 4KB page architecture). This forces DM core to split write BIOs before passing them to crypt_map(), and thus guaranteeing that dm-crypt can always accept an entire write BIO without needing to split it.
This change does not have any effect on the read path of dm-crypt. Read operations can still be split and the BIO fragments processed in parallel. There is also no impact on the performance of the write path given that all zone write BIOs were already processed inline instead of in parallel.
This change also does not affect in any way regular dm-crypt block devices.
Fixes: f211268ed1f9 ("dm: Use the block layer zone append emulation") Cc: stable@vger.kernel.org Signed-off-by: Damien Le Moal dlemoal@kernel.org Reviewed-by: Mikulas Patocka mpatocka@redhat.com Link: https://lore.kernel.org/r/20250625093327.548866-5-dlemoal@kernel.org Signed-off-by: Jens Axboe axboe@kernel.dk Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/md/dm-crypt.c | 47 ++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 38 insertions(+), 9 deletions(-)
--- a/drivers/md/dm-crypt.c +++ b/drivers/md/dm-crypt.c @@ -253,17 +253,35 @@ MODULE_PARM_DESC(max_read_size, "Maximum static unsigned int max_write_size = 0; module_param(max_write_size, uint, 0644); MODULE_PARM_DESC(max_write_size, "Maximum size of a write request"); -static unsigned get_max_request_size(struct crypt_config *cc, bool wrt) + +static unsigned get_max_request_sectors(struct dm_target *ti, struct bio *bio) { + struct crypt_config *cc = ti->private; unsigned val, sector_align; - val = !wrt ? READ_ONCE(max_read_size) : READ_ONCE(max_write_size); - if (likely(!val)) - val = !wrt ? DM_CRYPT_DEFAULT_MAX_READ_SIZE : DM_CRYPT_DEFAULT_MAX_WRITE_SIZE; - if (wrt || cc->used_tag_size) { - if (unlikely(val > BIO_MAX_VECS << PAGE_SHIFT)) - val = BIO_MAX_VECS << PAGE_SHIFT; + bool wrt = op_is_write(bio_op(bio)); + + if (wrt) { + /* + * For zoned devices, splitting write operations creates the + * risk of deadlocking queue freeze operations with zone write + * plugging BIO work when the reminder of a split BIO is + * issued. So always allow the entire BIO to proceed. + */ + if (ti->emulate_zone_append) + return bio_sectors(bio); + + val = min_not_zero(READ_ONCE(max_write_size), + DM_CRYPT_DEFAULT_MAX_WRITE_SIZE); + } else { + val = min_not_zero(READ_ONCE(max_read_size), + DM_CRYPT_DEFAULT_MAX_READ_SIZE); } - sector_align = max(bdev_logical_block_size(cc->dev->bdev), (unsigned)cc->sector_size); + + if (wrt || cc->used_tag_size) + val = min(val, BIO_MAX_VECS << PAGE_SHIFT); + + sector_align = max(bdev_logical_block_size(cc->dev->bdev), + (unsigned)cc->sector_size); val = round_down(val, sector_align); if (unlikely(!val)) val = sector_align; @@ -3496,7 +3514,7 @@ static int crypt_map(struct dm_target *t /* * Check if bio is too large, split as needed. */ - max_sectors = get_max_request_size(cc, bio_data_dir(bio) == WRITE); + max_sectors = get_max_request_sectors(ti, bio); if (unlikely(bio_sectors(bio) > max_sectors)) dm_accept_partial_bio(bio, max_sectors);
@@ -3733,6 +3751,17 @@ static void crypt_io_hints(struct dm_tar max_t(unsigned int, limits->physical_block_size, cc->sector_size); limits->io_min = max_t(unsigned int, limits->io_min, cc->sector_size); limits->dma_alignment = limits->logical_block_size - 1; + + /* + * For zoned dm-crypt targets, there will be no internal splitting of + * write BIOs to avoid exceeding BIO_MAX_VECS vectors per BIO. But + * without respecting this limit, crypt_alloc_buffer() will trigger a + * BUG(). Avoid this by forcing DM core to split write BIOs to this + * limit. + */ + if (ti->emulate_zone_append) + limits->max_hw_sectors = min(limits->max_hw_sectors, + BIO_MAX_VECS << PAGE_SECTORS_SHIFT); }
static struct target_type crypt_target = {
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Damien Le Moal dlemoal@kernel.org
commit 409f9287dab3b53bffe8d28d883a529028aa6a42 upstream.
DM targets must not split zone append and write operations using dm_accept_partial_bio() as doing so is forbidden for zone append BIOs, breaks zone append emulation using regular write BIOs and potentially creates deadlock situations with queue freeze operations.
Modify dm_accept_partial_bio() to add missing BUG_ON() checks for all these cases, that is, check that the BIO is a write or write zeroes operation. This change packs all the zone related checks together under a static_branch_unlikely(&zoned_enabled) and done only if the target is a zoned device.
Fixes: f211268ed1f9 ("dm: Use the block layer zone append emulation") Cc: stable@vger.kernel.org Signed-off-by: Damien Le Moal dlemoal@kernel.org Reviewed-by: Mikulas Patocka mpatocka@redhat.com Link: https://lore.kernel.org/r/20250625093327.548866-6-dlemoal@kernel.org Signed-off-by: Jens Axboe axboe@kernel.dk Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/md/dm.c | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-)
--- a/drivers/md/dm.c +++ b/drivers/md/dm.c @@ -1293,8 +1293,9 @@ out: /* * A target may call dm_accept_partial_bio only from the map routine. It is * allowed for all bio types except REQ_PREFLUSH, REQ_OP_ZONE_* zone management - * operations, REQ_OP_ZONE_APPEND (zone append writes) and any bio serviced by - * __send_duplicate_bios(). + * operations, zone append writes (native with REQ_OP_ZONE_APPEND or emulated + * with write BIOs flagged with BIO_EMULATES_ZONE_APPEND) and any bio serviced + * by __send_duplicate_bios(). * * dm_accept_partial_bio informs the dm that the target only wants to process * additional n_sectors sectors of the bio and the rest of the data should be @@ -1327,11 +1328,19 @@ void dm_accept_partial_bio(struct bio *b unsigned int bio_sectors = bio_sectors(bio);
BUG_ON(dm_tio_flagged(tio, DM_TIO_IS_DUPLICATE_BIO)); - BUG_ON(op_is_zone_mgmt(bio_op(bio))); - BUG_ON(bio_op(bio) == REQ_OP_ZONE_APPEND); BUG_ON(bio_sectors > *tio->len_ptr); BUG_ON(n_sectors > bio_sectors);
+ if (static_branch_unlikely(&zoned_enabled) && + unlikely(bdev_is_zoned(bio->bi_bdev))) { + enum req_op op = bio_op(bio); + + BUG_ON(op_is_zone_mgmt(op)); + BUG_ON(op == REQ_OP_WRITE); + BUG_ON(op == REQ_OP_WRITE_ZEROES); + BUG_ON(op == REQ_OP_ZONE_APPEND); + } + *tio->len_ptr -= bio_sectors - n_sectors; bio->bi_iter.bi_size = n_sectors << SECTOR_SHIFT;
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Finn Thain fthain@linux-m68k.org
commit 210a1ce8ed4391b64a888b3fb4b5611a13f5ccc7 upstream.
Move the cursor position rightward after rendering the character, not before. This avoids complications that arise when the recursive console_putc call has to wrap the line and/or scroll the display. This also fixes the linewrap bug that crops off the rightmost column.
When the cursor is at the bottom of the display, a linefeed will not move the cursor position further downward. Instead, the display scrolls upward. Avoid the repeated add/subtract sequence by way of a single subtraction at the initialization of console_struct_num_rows.
Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") Cc: stable@vger.kernel.org Signed-off-by: Finn Thain fthain@linux-m68k.org Tested-by: Stan Johnson userm57@yahoo.com Reviewed-by: Geert Uytterhoeven geert@linux-m68k.org Link: https://lore.kernel.org/9d4e8c68a456d5f2bc254ac6f87a472d066ebd5e.1743115195.... Signed-off-by: Geert Uytterhoeven geert@linux-m68k.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- arch/m68k/kernel/head.S | 31 +++++++++++++++++++++---------- 1 file changed, 21 insertions(+), 10 deletions(-)
--- a/arch/m68k/kernel/head.S +++ b/arch/m68k/kernel/head.S @@ -3400,6 +3400,7 @@ L(console_clear_loop):
movel %d4,%d1 /* screen height in pixels */ divul %a0@(FONT_DESC_HEIGHT),%d1 /* d1 = max num rows */ + subql #1,%d1 /* row range is 0 to num - 1 */
movel %d0,%a2@(Lconsole_struct_num_columns) movel %d1,%a2@(Lconsole_struct_num_rows) @@ -3546,15 +3547,14 @@ func_start console_putc,%a0/%a1/%d0-%d7 cmpib #10,%d7 jne L(console_not_lf) movel %a0@(Lconsole_struct_cur_row),%d0 - addil #1,%d0 - movel %d0,%a0@(Lconsole_struct_cur_row) movel %a0@(Lconsole_struct_num_rows),%d1 cmpl %d1,%d0 jcs 1f - subil #1,%d0 - movel %d0,%a0@(Lconsole_struct_cur_row) console_scroll + jra L(console_exit) 1: + addql #1,%d0 + movel %d0,%a0@(Lconsole_struct_cur_row) jra L(console_exit)
L(console_not_lf): @@ -3581,12 +3581,6 @@ L(console_not_cr): */ L(console_not_home): movel %a0@(Lconsole_struct_cur_column),%d0 - addql #1,%a0@(Lconsole_struct_cur_column) - movel %a0@(Lconsole_struct_num_columns),%d1 - cmpl %d1,%d0 - jcs 1f - console_putc #'\n' /* recursion is OK! */ -1: movel %a0@(Lconsole_struct_cur_row),%d1
/* @@ -3633,6 +3627,23 @@ L(console_do_font_scanline): addq #1,%d1 dbra %d7,L(console_read_char_scanline)
+ /* + * Register usage in the code below: + * a0 = pointer to console globals + * d0 = cursor column + * d1 = cursor column limit + */ + + lea %pc@(L(console_globals)),%a0 + + movel %a0@(Lconsole_struct_cur_column),%d0 + addql #1,%d0 + movel %d0,%a0@(Lconsole_struct_cur_column) /* Update cursor pos */ + movel %a0@(Lconsole_struct_num_columns),%d1 + cmpl %d1,%d0 + jcs L(console_exit) + console_putc #'\n' /* Line wrap using tail recursion */ + L(console_exit): func_return console_putc
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: David Lechner dlechner@baylibre.com
commit 92c247216918fcaa64244248ee38a0f1d342278c upstream.
Fix the num_slots value for most chips in the ad7173 driver. The correct value is the number of CHANNELx registers on the chip.
In commit 4310e15b3140 ("iio: adc: ad7173: don't make copy of ad_sigma_delta_info struct"), we refactored struct ad_sigma_delta_info to be static const data instead of being dynamically populated during driver probe. However, there was an existing bug in commit 76a1e6a42802 ("iio: adc: ad7173: add AD7173 driver") where num_slots was incorrectly set to the number of CONFIGx registers instead of the number of CHANNELx registers. This bug was partially propagated to the refactored code in that the 16-channel chips were only given 8 slots instead of 16 although we did managed to fix the 8-channel chips and one of the 4-channel chips in that commit. However, we botched two of the 4-channel chips and ended up incorrectly giving them 8 slots during the refactoring.
This patch fixes that mistake on the 4-channel chips and also corrects the 16-channel chips to have 16 slots.
Fixes: 4310e15b3140 ("iio: adc: ad7173: don't make copy of ad_sigma_delta_info struct") Signed-off-by: David Lechner dlechner@baylibre.com Reviewed-by: Nuno Sá nuno.sa@analog.com Link: https://patch.msgid.link/20250706-iio-adc-ad7173-fix-num_slots-on-most-chips... Cc: Stable@vger.kernel.org Signed-off-by: Jonathan Cameron Jonathan.Cameron@huawei.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/iio/adc/ad7173.c | 36 ++++++++++++++++++++++++++---------- 1 file changed, 26 insertions(+), 10 deletions(-)
--- a/drivers/iio/adc/ad7173.c +++ b/drivers/iio/adc/ad7173.c @@ -772,10 +772,26 @@ static const struct ad_sigma_delta_info .num_slots = 8, };
+static const struct ad_sigma_delta_info ad7173_sigma_delta_info_16_slots = { + .set_channel = ad7173_set_channel, + .append_status = ad7173_append_status, + .disable_all = ad7173_disable_all, + .disable_one = ad7173_disable_one, + .set_mode = ad7173_set_mode, + .has_registers = true, + .has_named_irqs = true, + .addr_shift = 0, + .read_mask = BIT(6), + .status_ch_mask = GENMASK(3, 0), + .data_reg = AD7173_REG_DATA, + .num_resetclks = 64, + .num_slots = 16, +}; + static const struct ad7173_device_info ad4111_device_info = { .name = "ad4111", .id = AD4111_ID, - .sd_info = &ad7173_sigma_delta_info_8_slots, + .sd_info = &ad7173_sigma_delta_info_16_slots, .num_voltage_in_div = 8, .num_channels = 16, .num_configs = 8, @@ -797,7 +813,7 @@ static const struct ad7173_device_info a static const struct ad7173_device_info ad4112_device_info = { .name = "ad4112", .id = AD4112_ID, - .sd_info = &ad7173_sigma_delta_info_8_slots, + .sd_info = &ad7173_sigma_delta_info_16_slots, .num_voltage_in_div = 8, .num_channels = 16, .num_configs = 8, @@ -818,7 +834,7 @@ static const struct ad7173_device_info a static const struct ad7173_device_info ad4113_device_info = { .name = "ad4113", .id = AD4113_ID, - .sd_info = &ad7173_sigma_delta_info_8_slots, + .sd_info = &ad7173_sigma_delta_info_16_slots, .num_voltage_in_div = 8, .num_channels = 16, .num_configs = 8, @@ -837,7 +853,7 @@ static const struct ad7173_device_info a static const struct ad7173_device_info ad4114_device_info = { .name = "ad4114", .id = AD4114_ID, - .sd_info = &ad7173_sigma_delta_info_8_slots, + .sd_info = &ad7173_sigma_delta_info_16_slots, .num_voltage_in_div = 16, .num_channels = 16, .num_configs = 8, @@ -856,7 +872,7 @@ static const struct ad7173_device_info a static const struct ad7173_device_info ad4115_device_info = { .name = "ad4115", .id = AD4115_ID, - .sd_info = &ad7173_sigma_delta_info_8_slots, + .sd_info = &ad7173_sigma_delta_info_16_slots, .num_voltage_in_div = 16, .num_channels = 16, .num_configs = 8, @@ -875,7 +891,7 @@ static const struct ad7173_device_info a static const struct ad7173_device_info ad4116_device_info = { .name = "ad4116", .id = AD4116_ID, - .sd_info = &ad7173_sigma_delta_info_8_slots, + .sd_info = &ad7173_sigma_delta_info_16_slots, .num_voltage_in_div = 11, .num_channels = 16, .num_configs = 8, @@ -894,7 +910,7 @@ static const struct ad7173_device_info a static const struct ad7173_device_info ad7172_2_device_info = { .name = "ad7172-2", .id = AD7172_2_ID, - .sd_info = &ad7173_sigma_delta_info_8_slots, + .sd_info = &ad7173_sigma_delta_info_4_slots, .num_voltage_in = 5, .num_channels = 4, .num_configs = 4, @@ -927,7 +943,7 @@ static const struct ad7173_device_info a static const struct ad7173_device_info ad7173_8_device_info = { .name = "ad7173-8", .id = AD7173_ID, - .sd_info = &ad7173_sigma_delta_info_8_slots, + .sd_info = &ad7173_sigma_delta_info_16_slots, .num_voltage_in = 17, .num_channels = 16, .num_configs = 8, @@ -944,7 +960,7 @@ static const struct ad7173_device_info a static const struct ad7173_device_info ad7175_2_device_info = { .name = "ad7175-2", .id = AD7175_2_ID, - .sd_info = &ad7173_sigma_delta_info_8_slots, + .sd_info = &ad7173_sigma_delta_info_4_slots, .num_voltage_in = 5, .num_channels = 4, .num_configs = 4, @@ -961,7 +977,7 @@ static const struct ad7173_device_info a static const struct ad7173_device_info ad7175_8_device_info = { .name = "ad7175-8", .id = AD7175_8_ID, - .sd_info = &ad7173_sigma_delta_info_8_slots, + .sd_info = &ad7173_sigma_delta_info_16_slots, .num_voltage_in = 17, .num_channels = 16, .num_configs = 8,
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Nathan Chancellor nathan@kernel.org
commit 8d1b02e5d7e3a6d2acffb1f4c094678fda9e3456 upstream.
After a recent change in clang to expose uninitialized warnings from const variables [1], there is a warning in cxacru_heavy_init():
drivers/usb/atm/cxacru.c:1104:6: error: variable 'bp' is used uninitialized whenever 'if' condition is false [-Werror,-Wsometimes-uninitialized] 1104 | if (instance->modem_type->boot_rom_patch) { | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ drivers/usb/atm/cxacru.c:1113:39: note: uninitialized use occurs here 1113 | cxacru_upload_firmware(instance, fw, bp); | ^~ drivers/usb/atm/cxacru.c:1104:2: note: remove the 'if' if its condition is always true 1104 | if (instance->modem_type->boot_rom_patch) { | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ drivers/usb/atm/cxacru.c:1095:32: note: initialize the variable 'bp' to silence this warning 1095 | const struct firmware *fw, *bp; | ^ | = NULL
While the warning is technically correct that bp is conditionally passed uninitialized to cxacru_upload_firmware(), it is ultimately a false positive warning on the uninitialized use of bp because the same condition that initializes bp, instance->modem_type->boot_rom_patch, is the same one that gates the use of bp within cxacru_upload_firmware(). As this warning occurs in clang's frontend before inlining occurs, it cannot know that these conditions are indentical to avoid the warning.
Manually inline cxacru_upload_firmware() into cxacru_heavy_init(), as that is its only callsite, so that clang can see that bp is initialized and used under the same condition, clearing up the warning without any functional changes to the code (LLVM was already doing this inlining later).
Cc: stable@vger.kernel.org Fixes: 1b0e61465234 ("[PATCH] USB ATM: driver for the Conexant AccessRunner chipset cxacru") Closes: https://github.com/ClangBuiltLinux/linux/issues/2102 Link: https://github.com/llvm/llvm-project/commit/2464313eef01c5b1edf0eccf57a32cde... [1] Signed-off-by: Nathan Chancellor nathan@kernel.org Link: https://lore.kernel.org/r/20250722-usb-cxacru-fix-clang-21-uninit-warning-v2... Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/usb/atm/cxacru.c | 106 +++++++++++++++++++++-------------------------- 1 file changed, 49 insertions(+), 57 deletions(-)
--- a/drivers/usb/atm/cxacru.c +++ b/drivers/usb/atm/cxacru.c @@ -980,25 +980,60 @@ cleanup: return ret; }
-static void cxacru_upload_firmware(struct cxacru_data *instance, - const struct firmware *fw, - const struct firmware *bp) + +static int cxacru_find_firmware(struct cxacru_data *instance, + char *phase, const struct firmware **fw_p) { - int ret; + struct usbatm_data *usbatm = instance->usbatm; + struct device *dev = &usbatm->usb_intf->dev; + char buf[16]; + + sprintf(buf, "cxacru-%s.bin", phase); + usb_dbg(usbatm, "cxacru_find_firmware: looking for %s\n", buf); + + if (request_firmware(fw_p, buf, dev)) { + usb_dbg(usbatm, "no stage %s firmware found\n", phase); + return -ENOENT; + } + + usb_info(usbatm, "found firmware %s\n", buf); + + return 0; +} + +static int cxacru_heavy_init(struct usbatm_data *usbatm_instance, + struct usb_interface *usb_intf) +{ + const struct firmware *fw, *bp; + struct cxacru_data *instance = usbatm_instance->driver_data; struct usbatm_data *usbatm = instance->usbatm; struct usb_device *usb_dev = usbatm->usb_dev; __le16 signature[] = { usb_dev->descriptor.idVendor, usb_dev->descriptor.idProduct }; __le32 val; + int ret; + + ret = cxacru_find_firmware(instance, "fw", &fw); + if (ret) { + usb_warn(usbatm_instance, "firmware (cxacru-fw.bin) unavailable (system misconfigured?)\n"); + return ret; + }
- usb_dbg(usbatm, "%s\n", __func__); + if (instance->modem_type->boot_rom_patch) { + ret = cxacru_find_firmware(instance, "bp", &bp); + if (ret) { + usb_warn(usbatm_instance, "boot ROM patch (cxacru-bp.bin) unavailable (system misconfigured?)\n"); + release_firmware(fw); + return ret; + } + }
/* FirmwarePllFClkValue */ val = cpu_to_le32(instance->modem_type->pll_f_clk); ret = cxacru_fw(usb_dev, FW_WRITE_MEM, 0x2, 0x0, PLLFCLK_ADDR, (u8 *) &val, 4); if (ret) { usb_err(usbatm, "FirmwarePllFClkValue failed: %d\n", ret); - return; + goto done; }
/* FirmwarePllBClkValue */ @@ -1006,7 +1041,7 @@ static void cxacru_upload_firmware(struc ret = cxacru_fw(usb_dev, FW_WRITE_MEM, 0x2, 0x0, PLLBCLK_ADDR, (u8 *) &val, 4); if (ret) { usb_err(usbatm, "FirmwarePllBClkValue failed: %d\n", ret); - return; + goto done; }
/* Enable SDRAM */ @@ -1014,7 +1049,7 @@ static void cxacru_upload_firmware(struc ret = cxacru_fw(usb_dev, FW_WRITE_MEM, 0x2, 0x0, SDRAMEN_ADDR, (u8 *) &val, 4); if (ret) { usb_err(usbatm, "Enable SDRAM failed: %d\n", ret); - return; + goto done; }
/* Firmware */ @@ -1022,7 +1057,7 @@ static void cxacru_upload_firmware(struc ret = cxacru_fw(usb_dev, FW_WRITE_MEM, 0x2, 0x0, FW_ADDR, fw->data, fw->size); if (ret) { usb_err(usbatm, "Firmware upload failed: %d\n", ret); - return; + goto done; }
/* Boot ROM patch */ @@ -1031,7 +1066,7 @@ static void cxacru_upload_firmware(struc ret = cxacru_fw(usb_dev, FW_WRITE_MEM, 0x2, 0x0, BR_ADDR, bp->data, bp->size); if (ret) { usb_err(usbatm, "Boot ROM patching failed: %d\n", ret); - return; + goto done; } }
@@ -1039,7 +1074,7 @@ static void cxacru_upload_firmware(struc ret = cxacru_fw(usb_dev, FW_WRITE_MEM, 0x2, 0x0, SIG_ADDR, (u8 *) signature, 4); if (ret) { usb_err(usbatm, "Signature storing failed: %d\n", ret); - return; + goto done; }
usb_info(usbatm, "starting device\n"); @@ -1051,7 +1086,7 @@ static void cxacru_upload_firmware(struc } if (ret) { usb_err(usbatm, "Passing control to firmware failed: %d\n", ret); - return; + goto done; }
/* Delay to allow firmware to start up. */ @@ -1065,53 +1100,10 @@ static void cxacru_upload_firmware(struc ret = cxacru_cm(instance, CM_REQUEST_CARD_GET_STATUS, NULL, 0, NULL, 0); if (ret < 0) { usb_err(usbatm, "modem failed to initialize: %d\n", ret); - return; - } -} - -static int cxacru_find_firmware(struct cxacru_data *instance, - char *phase, const struct firmware **fw_p) -{ - struct usbatm_data *usbatm = instance->usbatm; - struct device *dev = &usbatm->usb_intf->dev; - char buf[16]; - - sprintf(buf, "cxacru-%s.bin", phase); - usb_dbg(usbatm, "cxacru_find_firmware: looking for %s\n", buf); - - if (request_firmware(fw_p, buf, dev)) { - usb_dbg(usbatm, "no stage %s firmware found\n", phase); - return -ENOENT; + goto done; }
- usb_info(usbatm, "found firmware %s\n", buf); - - return 0; -} - -static int cxacru_heavy_init(struct usbatm_data *usbatm_instance, - struct usb_interface *usb_intf) -{ - const struct firmware *fw, *bp; - struct cxacru_data *instance = usbatm_instance->driver_data; - int ret = cxacru_find_firmware(instance, "fw", &fw); - - if (ret) { - usb_warn(usbatm_instance, "firmware (cxacru-fw.bin) unavailable (system misconfigured?)\n"); - return ret; - } - - if (instance->modem_type->boot_rom_patch) { - ret = cxacru_find_firmware(instance, "bp", &bp); - if (ret) { - usb_warn(usbatm_instance, "boot ROM patch (cxacru-bp.bin) unavailable (system misconfigured?)\n"); - release_firmware(fw); - return ret; - } - } - - cxacru_upload_firmware(instance, fw, bp); - +done: if (instance->modem_type->boot_rom_patch) release_firmware(bp); release_firmware(fw);
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Johan Hovold johan@kernel.org
commit 868837b0a94c6b1b1fdbc04d3ba218ca83432393 upstream.
Make sure to drop the reference to the companion device taken during probe when the driver is unbound.
Fixes: 39facfa01c9f ("usb: gadget: udc: renesas_usb3: Add register of usb role switch") Cc: stable@vger.kernel.org # 4.19 Cc: Yoshihiro Shimoda yoshihiro.shimoda.uh@renesas.com Signed-off-by: Johan Hovold johan@kernel.org Link: https://lore.kernel.org/r/20250724091910.21092-4-johan@kernel.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/usb/gadget/udc/renesas_usb3.c | 1 + 1 file changed, 1 insertion(+)
--- a/drivers/usb/gadget/udc/renesas_usb3.c +++ b/drivers/usb/gadget/udc/renesas_usb3.c @@ -2657,6 +2657,7 @@ static void renesas_usb3_remove(struct p struct renesas_usb3 *usb3 = platform_get_drvdata(pdev);
debugfs_remove_recursive(usb3->dentry); + put_device(usb3->host_dev); device_remove_file(&pdev->dev, &dev_attr_role);
cancel_work_sync(&usb3->role_work);
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Johan Hovold johan@kernel.org
commit 1473e9e7679bd4f5a62d1abccae894fb86de280f upstream.
Make sure to drop the reference to the control device taken by of_find_device_by_node() during probe when the driver is unbound.
Fixes: 8934d3e4d0e7 ("usb: musb: omap2430: Don't use omap_get_control_dev()") Cc: stable@vger.kernel.org # 3.13 Cc: Roger Quadros rogerq@kernel.org Signed-off-by: Johan Hovold johan@kernel.org Link: https://lore.kernel.org/r/20250724091910.21092-5-johan@kernel.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/usb/musb/omap2430.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-)
--- a/drivers/usb/musb/omap2430.c +++ b/drivers/usb/musb/omap2430.c @@ -400,7 +400,7 @@ static int omap2430_probe(struct platfor ret = platform_device_add_resources(musb, pdev->resource, pdev->num_resources); if (ret) { dev_err(&pdev->dev, "failed to add resources\n"); - goto err2; + goto err_put_control_otghs; }
if (populate_irqs) { @@ -413,7 +413,7 @@ static int omap2430_probe(struct platfor res = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!res) { ret = -EINVAL; - goto err2; + goto err_put_control_otghs; }
musb_res[i].start = res->start; @@ -441,14 +441,14 @@ static int omap2430_probe(struct platfor ret = platform_device_add_resources(musb, musb_res, i); if (ret) { dev_err(&pdev->dev, "failed to add IRQ resources\n"); - goto err2; + goto err_put_control_otghs; } }
ret = platform_device_add_data(musb, pdata, sizeof(*pdata)); if (ret) { dev_err(&pdev->dev, "failed to add platform_data\n"); - goto err2; + goto err_put_control_otghs; }
pm_runtime_enable(glue->dev); @@ -463,7 +463,9 @@ static int omap2430_probe(struct platfor
err3: pm_runtime_disable(glue->dev); - +err_put_control_otghs: + if (!IS_ERR(glue->control_otghs)) + put_device(glue->control_otghs); err2: platform_device_put(musb);
@@ -477,6 +479,8 @@ static void omap2430_remove(struct platf
platform_device_unregister(glue->musb); pm_runtime_disable(glue->dev); + if (!IS_ERR(glue->control_otghs)) + put_device(glue->control_otghs); }
#ifdef CONFIG_PM
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Johan Hovold johan@kernel.org
commit 93b400f4951404d040197943a25d6fef9f8ccabb upstream.
Make sure to drop the references taken to the child devices by of_find_device_by_node() during probe on driver unbind.
Fixes: c99993376f72 ("usb: dwc3: Add Amlogic G12A DWC3 glue") Cc: stable@vger.kernel.org # 5.2 Cc: Neil Armstrong neil.armstrong@linaro.org Signed-off-by: Johan Hovold johan@kernel.org Reviewed-by: Martin Blumenstingl martin.blumenstingl@googlemail.com Link: https://lore.kernel.org/r/20250724091910.21092-3-johan@kernel.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/usb/dwc3/dwc3-meson-g12a.c | 3 +++ 1 file changed, 3 insertions(+)
--- a/drivers/usb/dwc3/dwc3-meson-g12a.c +++ b/drivers/usb/dwc3/dwc3-meson-g12a.c @@ -837,6 +837,9 @@ static void dwc3_meson_g12a_remove(struc
usb_role_switch_unregister(priv->role_switch);
+ put_device(priv->switch_desc.udc); + put_device(priv->switch_desc.usb2_port); + of_platform_depopulate(dev);
for (i = 0 ; i < PHY_COUNT ; ++i) {
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Johan Hovold johan@kernel.org
commit 086a0e516f7b3844e6328a5c69e2708b66b0ce18 upstream.
Make sure to drop the reference to the dwc3 device taken by of_find_device_by_node() on probe errors and on driver unbind.
Fixes: 6dd2565989b4 ("usb: dwc3: add imx8mp dwc3 glue layer driver") Cc: stable@vger.kernel.org # 5.12 Cc: Li Jun jun.li@nxp.com Signed-off-by: Johan Hovold johan@kernel.org Link: https://lore.kernel.org/r/20250724091910.21092-2-johan@kernel.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/usb/dwc3/dwc3-imx8mp.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-)
--- a/drivers/usb/dwc3/dwc3-imx8mp.c +++ b/drivers/usb/dwc3/dwc3-imx8mp.c @@ -244,7 +244,7 @@ static int dwc3_imx8mp_probe(struct plat IRQF_ONESHOT, dev_name(dev), dwc3_imx); if (err) { dev_err(dev, "failed to request IRQ #%d --> %d\n", irq, err); - goto depopulate; + goto put_dwc3; }
device_set_wakeup_capable(dev, true); @@ -252,6 +252,8 @@ static int dwc3_imx8mp_probe(struct plat
return 0;
+put_dwc3: + put_device(&dwc3_imx->dwc3->dev); depopulate: of_platform_depopulate(dev); remove_swnode: @@ -265,8 +267,11 @@ disable_rpm:
static void dwc3_imx8mp_remove(struct platform_device *pdev) { + struct dwc3_imx8mp *dwc3_imx = platform_get_drvdata(pdev); struct device *dev = &pdev->dev;
+ put_device(&dwc3_imx->dwc3->dev); + pm_runtime_get_sync(dev); of_platform_depopulate(dev); device_remove_software_node(dev);
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Alexander Wilhelm alexander.wilhelm@westermo.com
commit f471578e8b1a90623674433a01a8845110bc76ce upstream.
On big endian platform like PowerPC, the MHI bus (which is little endian) does not start properly. The following example shows the error messages by using QCN9274 WLAN device with ath12k driver:
ath12k_pci 0001:01:00.0: BAR 0: assigned [mem 0xc00000000-0xc001fffff 64bit] ath12k_pci 0001:01:00.0: MSI vectors: 1 ath12k_pci 0001:01:00.0: Hardware name: qcn9274 hw2.0 ath12k_pci 0001:01:00.0: failed to set mhi state: POWER_ON(2) ath12k_pci 0001:01:00.0: failed to start mhi: -110 ath12k_pci 0001:01:00.0: failed to power up :-110 ath12k_pci 0001:01:00.0: failed to create soc core: -110 ath12k_pci 0001:01:00.0: failed to init core: -110 ath12k_pci: probe of 0001:01:00.0 failed with error -110
The issue seems to be with the incorrect DMA address/size used for transferring the firmware image over BHI. So fix it by converting the DMA address and size of the BHI vector table to little endian format before sending them to the device.
Fixes: 6cd330ae76ff ("bus: mhi: core: Add support for ringing channel/event ring doorbells") Signed-off-by: Alexander Wilhelm alexander.wilhelm@westermo.com [mani: added stable tag and reworded commit message] Signed-off-by: Manivannan Sadhasivam mani@kernel.org Reviewed-by: Jeff Hugo jeff.hugo@oss.qualcomm.com Reviewed-by: Krishna Chaitanya Chundru krishna.chundru@oss.qualcomm.com Cc: stable@vger.kernel.org Link: https://patch.msgid.link/20250519145837.958153-1-alexander.wilhelm@westermo.... Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/bus/mhi/host/boot.c | 8 ++++---- drivers/bus/mhi/host/internal.h | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-)
--- a/drivers/bus/mhi/host/boot.c +++ b/drivers/bus/mhi/host/boot.c @@ -31,8 +31,8 @@ int mhi_rddm_prepare(struct mhi_controll int ret;
for (i = 0; i < img_info->entries - 1; i++, mhi_buf++, bhi_vec++) { - bhi_vec->dma_addr = mhi_buf->dma_addr; - bhi_vec->size = mhi_buf->len; + bhi_vec->dma_addr = cpu_to_le64(mhi_buf->dma_addr); + bhi_vec->size = cpu_to_le64(mhi_buf->len); }
dev_dbg(dev, "BHIe programming for RDDM\n"); @@ -431,8 +431,8 @@ static void mhi_firmware_copy_bhie(struc while (remainder) { to_cpy = min(remainder, mhi_buf->len); memcpy(mhi_buf->buf, buf, to_cpy); - bhi_vec->dma_addr = mhi_buf->dma_addr; - bhi_vec->size = to_cpy; + bhi_vec->dma_addr = cpu_to_le64(mhi_buf->dma_addr); + bhi_vec->size = cpu_to_le64(to_cpy);
buf += to_cpy; remainder -= to_cpy; --- a/drivers/bus/mhi/host/internal.h +++ b/drivers/bus/mhi/host/internal.h @@ -25,8 +25,8 @@ struct mhi_ctxt { };
struct bhi_vec_entry { - u64 dma_addr; - u64 size; + __le64 dma_addr; + __le64 size; };
enum mhi_fw_load_type {
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Youssef Samir quic_yabdulra@quicinc.com
commit 5bd398e20f0833ae8a1267d4f343591a2dd20185 upstream.
When a remote device sends a completion event to the host, it contains a pointer to the consumed TRE. The host uses this pointer to process all of the TREs between it and the host's local copy of the ring's read pointer. This works when processing completion for chained transactions, but can lead to nasty results if the device sends an event for a single-element transaction with a read pointer that is multiple elements ahead of the host's read pointer.
For instance, if the host accesses an event ring while the device is updating it, the pointer inside of the event might still point to an old TRE. If the host uses the channel's xfer_cb() to directly free the buffer pointed to by the TRE, the buffer will be double-freed.
This behavior was observed on an ep that used upstream EP stack without 'commit 6f18d174b73d ("bus: mhi: ep: Update read pointer only after buffer is written")'. Where the device updated the events ring pointer before updating the event contents, so it left a window where the host was able to access the stale data the event pointed to, before the device had the chance to update them. The usual pattern was that the host received an event pointing to a TRE that is not immediately after the last processed one, so it got treated as if it was a chained transaction, processing all of the TREs in between the two read pointers.
This commit aims to harden the host by ensuring transactions where the event points to a TRE that isn't local_rp + 1 are chained.
Fixes: 1d3173a3bae7 ("bus: mhi: core: Add support for processing events from client device") Signed-off-by: Youssef Samir quic_yabdulra@quicinc.com [mani: added stable tag and reworded commit message] Signed-off-by: Manivannan Sadhasivam mani@kernel.org Reviewed-by: Jeff Hugo jeff.hugo@oss.qualcomm.com Cc: stable@vger.kernel.org Link: https://patch.msgid.link/20250714163039.3438985-1-quic_yabdulra@quicinc.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/bus/mhi/host/main.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-)
--- a/drivers/bus/mhi/host/main.c +++ b/drivers/bus/mhi/host/main.c @@ -602,7 +602,7 @@ static int parse_xfer_event(struct mhi_c { dma_addr_t ptr = MHI_TRE_GET_EV_PTR(event); struct mhi_ring_element *local_rp, *ev_tre; - void *dev_rp; + void *dev_rp, *next_rp; struct mhi_buf_info *buf_info; u16 xfer_len;
@@ -621,6 +621,16 @@ static int parse_xfer_event(struct mhi_c result.dir = mhi_chan->dir;
local_rp = tre_ring->rp; + + next_rp = local_rp + 1; + if (next_rp >= tre_ring->base + tre_ring->len) + next_rp = tre_ring->base; + if (dev_rp != next_rp && !MHI_TRE_DATA_GET_CHAIN(local_rp)) { + dev_err(&mhi_cntrl->mhi_dev->dev, + "Event element points to an unexpected TRE\n"); + break; + } + while (local_rp != dev_rp) { buf_info = buf_ring->rp; /* If it's the last TRE, get length from the event */
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Myrrh Periwinkle myrrhperiwinkle@qtmlabs.xyz
commit b1cc2092ea7a52e2c435aee6d2b1bcb773202663 upstream.
We don't process Unicode characters if the virtual terminal is in raw mode, so there's no reason why we shouldn't do the same for K_OFF (especially since people would expect K_OFF to actually turn off all VT key processing).
Fixes: 9fc3de9c8356 ("vt: Add virtual console keyboard mode OFF") Signed-off-by: Myrrh Periwinkle myrrhperiwinkle@qtmlabs.xyz Cc: stable stable@kernel.org Reviewed-by: Jiri Slaby jirislaby@kernel.org Link: https://lore.kernel.org/r/20250702-vt-misc-unicode-fixes-v1-1-c27e143cc2eb@q... Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/tty/vt/keyboard.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
--- a/drivers/tty/vt/keyboard.c +++ b/drivers/tty/vt/keyboard.c @@ -1487,7 +1487,7 @@ static void kbd_keycode(unsigned int key rc = atomic_notifier_call_chain(&keyboard_notifier_list, KBD_UNICODE, ¶m); if (rc != NOTIFY_STOP) - if (down && !raw_mode) + if (down && !(raw_mode || kbd->kbdmode == VC_OFF)) k_unicode(vc, keysym, !down); return; }
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Myrrh Periwinkle myrrhperiwinkle@qtmlabs.xyz
commit b43cb4ff85da5cf29c4cd351ef1d7dd8210780f7 upstream.
The maximum number of keycodes got bumped to 256 a very long time ago, but the default keymaps were never adjusted to match. This is causing the kernel to interpret keycodes above 127 as U+0000 if the shipped generated keymap is used.
Fix this by mapping all keycodes above 127 to K_HOLE so the kernel ignores them.
The contents of this patche were generated by rerunning `loadkeys --mktable --unicode` and only including the changes to map keycodes above 127 to K_HOLE.
Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") Signed-off-by: Myrrh Periwinkle myrrhperiwinkle@qtmlabs.xyz Cc: stable stable@kernel.org Reviewed-by: Jiri Slaby jirislaby@kernel.org Link: https://lore.kernel.org/r/20250702-vt-misc-unicode-fixes-v1-2-c27e143cc2eb@q... Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/tty/vt/defkeymap.c_shipped | 112 +++++++++++++++++++++++++++++++++++++ 1 file changed, 112 insertions(+)
--- a/drivers/tty/vt/defkeymap.c_shipped +++ b/drivers/tty/vt/defkeymap.c_shipped @@ -23,6 +23,22 @@ unsigned short plain_map[NR_KEYS] = { 0xf118, 0xf601, 0xf602, 0xf117, 0xf600, 0xf119, 0xf115, 0xf116, 0xf11a, 0xf10c, 0xf10d, 0xf11b, 0xf11c, 0xf110, 0xf311, 0xf11d, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, };
static unsigned short shift_map[NR_KEYS] = { @@ -42,6 +58,22 @@ static unsigned short shift_map[NR_KEYS] 0xf20b, 0xf601, 0xf602, 0xf117, 0xf600, 0xf20a, 0xf115, 0xf116, 0xf11a, 0xf10c, 0xf10d, 0xf11b, 0xf11c, 0xf110, 0xf311, 0xf11d, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, };
static unsigned short altgr_map[NR_KEYS] = { @@ -61,6 +93,22 @@ static unsigned short altgr_map[NR_KEYS] 0xf118, 0xf601, 0xf602, 0xf117, 0xf600, 0xf119, 0xf115, 0xf116, 0xf11a, 0xf10c, 0xf10d, 0xf11b, 0xf11c, 0xf110, 0xf311, 0xf11d, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, };
static unsigned short ctrl_map[NR_KEYS] = { @@ -80,6 +128,22 @@ static unsigned short ctrl_map[NR_KEYS] 0xf118, 0xf601, 0xf602, 0xf117, 0xf600, 0xf119, 0xf115, 0xf116, 0xf11a, 0xf10c, 0xf10d, 0xf11b, 0xf11c, 0xf110, 0xf311, 0xf11d, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, };
static unsigned short shift_ctrl_map[NR_KEYS] = { @@ -99,6 +163,22 @@ static unsigned short shift_ctrl_map[NR_ 0xf118, 0xf601, 0xf602, 0xf117, 0xf600, 0xf119, 0xf115, 0xf116, 0xf11a, 0xf10c, 0xf10d, 0xf11b, 0xf11c, 0xf110, 0xf311, 0xf11d, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, };
static unsigned short alt_map[NR_KEYS] = { @@ -118,6 +198,22 @@ static unsigned short alt_map[NR_KEYS] = 0xf118, 0xf210, 0xf211, 0xf117, 0xf600, 0xf119, 0xf115, 0xf116, 0xf11a, 0xf10c, 0xf10d, 0xf11b, 0xf11c, 0xf110, 0xf311, 0xf11d, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, };
static unsigned short ctrl_alt_map[NR_KEYS] = { @@ -137,6 +233,22 @@ static unsigned short ctrl_alt_map[NR_KE 0xf118, 0xf601, 0xf602, 0xf117, 0xf600, 0xf119, 0xf115, 0xf20c, 0xf11a, 0xf10c, 0xf10d, 0xf11b, 0xf11c, 0xf110, 0xf311, 0xf11d, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, };
unsigned short *key_maps[MAX_NR_KEYMAPS] = {
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: David Howells dhowells@redhat.com
commit a3de58b12ce074ec05b8741fa28d62ccb1070468 upstream.
If all the subrequests in an unbuffered write stream fail, the subrequest collector doesn't update the stream->transferred value and it retains its initial LONG_MAX value. Unfortunately, if all active streams fail, then we take the smallest value of { LONG_MAX, LONG_MAX, ... } as the value to set in wreq->transferred - which is then returned from ->write_iter().
LONG_MAX was chosen as the initial value so that all the streams can be quickly assessed by taking the smallest value of all stream->transferred - but this only works if we've set any of them.
Fix this by adding a flag to indicate whether the value in stream->transferred is valid and checking that when we integrate the values. stream->transferred can then be initialised to zero.
This was found by running the generic/750 xfstest against cifs with cache=none. It splices data to the target file. Once (if) it has used up all the available scratch space, the writes start failing with ENOSPC. This causes ->write_iter() to fail. However, it was returning wreq->transferred, i.e. LONG_MAX, rather than an error (because it thought the amount transferred was non-zero) and iter_file_splice_write() would then try to clean up that amount of pipe bufferage - leading to an oops when it overran. The kernel log showed:
CIFS: VFS: Send error in write = -28
followed by:
BUG: kernel NULL pointer dereference, address: 0000000000000008
with:
RIP: 0010:iter_file_splice_write+0x3a4/0x520 do_splice+0x197/0x4e0
or:
RIP: 0010:pipe_buf_release (include/linux/pipe_fs_i.h:282) iter_file_splice_write (fs/splice.c:755)
Also put a warning check into splice to announce if ->write_iter() returned that it had written more than it was asked to.
Fixes: 288ace2f57c9 ("netfs: New writeback implementation") Reported-by: Xiaoli Feng fengxiaoli0714@gmail.com Closes: https://bugzilla.kernel.org/show_bug.cgi?id=220445 Signed-off-by: David Howells dhowells@redhat.com Link: https://lore.kernel.org/915443.1755207950@warthog.procyon.org.uk cc: Paulo Alcantara pc@manguebit.org cc: Steve French sfrench@samba.org cc: Shyam Prasad N sprasad@microsoft.com cc: netfs@lists.linux.dev cc: linux-cifs@vger.kernel.org cc: linux-fsdevel@vger.kernel.org cc: stable@vger.kernel.org Signed-off-by: Christian Brauner brauner@kernel.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- fs/netfs/read_collect.c | 4 +++- fs/netfs/write_collect.c | 10 ++++++++-- fs/netfs/write_issue.c | 4 ++-- fs/splice.c | 3 +++ include/linux/netfs.h | 1 + 5 files changed, 17 insertions(+), 5 deletions(-)
--- a/fs/netfs/read_collect.c +++ b/fs/netfs/read_collect.c @@ -281,8 +281,10 @@ reassess: } else if (test_bit(NETFS_RREQ_SHORT_TRANSFER, &rreq->flags)) { notes |= MADE_PROGRESS; } else { - if (!stream->failed) + if (!stream->failed) { stream->transferred += transferred; + stream->transferred_valid = true; + } if (front->transferred < front->len) set_bit(NETFS_RREQ_SHORT_TRANSFER, &rreq->flags); notes |= MADE_PROGRESS; --- a/fs/netfs/write_collect.c +++ b/fs/netfs/write_collect.c @@ -254,6 +254,7 @@ reassess_streams: if (front->start + front->transferred > stream->collected_to) { stream->collected_to = front->start + front->transferred; stream->transferred = stream->collected_to - wreq->start; + stream->transferred_valid = true; notes |= MADE_PROGRESS; } if (test_bit(NETFS_SREQ_FAILED, &front->flags)) { @@ -356,6 +357,7 @@ bool netfs_write_collection(struct netfs { struct netfs_inode *ictx = netfs_inode(wreq->inode); size_t transferred; + bool transferred_valid = false; int s;
_enter("R=%x", wreq->debug_id); @@ -376,12 +378,16 @@ bool netfs_write_collection(struct netfs continue; if (!list_empty(&stream->subrequests)) return false; - if (stream->transferred < transferred) + if (stream->transferred_valid && + stream->transferred < transferred) { transferred = stream->transferred; + transferred_valid = true; + } }
/* Okay, declare that all I/O is complete. */ - wreq->transferred = transferred; + if (transferred_valid) + wreq->transferred = transferred; trace_netfs_rreq(wreq, netfs_rreq_trace_write_done);
if (wreq->io_streams[1].active && --- a/fs/netfs/write_issue.c +++ b/fs/netfs/write_issue.c @@ -118,12 +118,12 @@ struct netfs_io_request *netfs_create_wr wreq->io_streams[0].prepare_write = ictx->ops->prepare_write; wreq->io_streams[0].issue_write = ictx->ops->issue_write; wreq->io_streams[0].collected_to = start; - wreq->io_streams[0].transferred = LONG_MAX; + wreq->io_streams[0].transferred = 0;
wreq->io_streams[1].stream_nr = 1; wreq->io_streams[1].source = NETFS_WRITE_TO_CACHE; wreq->io_streams[1].collected_to = start; - wreq->io_streams[1].transferred = LONG_MAX; + wreq->io_streams[1].transferred = 0; if (fscache_resources_valid(&wreq->cache_resources)) { wreq->io_streams[1].avail = true; wreq->io_streams[1].active = true; --- a/fs/splice.c +++ b/fs/splice.c @@ -739,6 +739,9 @@ iter_file_splice_write(struct pipe_inode sd.pos = kiocb.ki_pos; if (ret <= 0) break; + WARN_ONCE(ret > sd.total_len - left, + "Splice Exceeded! ret=%zd tot=%zu left=%zu\n", + ret, sd.total_len, left);
sd.num_spliced += ret; sd.total_len -= ret; --- a/include/linux/netfs.h +++ b/include/linux/netfs.h @@ -150,6 +150,7 @@ struct netfs_io_stream { bool active; /* T if stream is active */ bool need_retry; /* T if this stream needs retrying */ bool failed; /* T if this stream failed */ + bool transferred_valid; /* T is ->transferred is valid */ };
/*
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Eric Biggers ebiggers@kernel.org
commit 22375adaa0d9fbba9646c8e2b099c6e87c97bfae upstream.
The MIPS32r2 ChaCha code has never been buildable with the clang assembler. First, clang doesn't support the 'rotl' pseudo-instruction:
error: unknown instruction, did you mean: rol, rotr?
Second, clang requires that both operands of the 'wsbh' instruction be explicitly given:
error: too few operands for instruction
To fix this, align the code with the real instruction set by (1) using the real instruction 'rotr' instead of the nonstandard pseudo- instruction 'rotl', and (2) explicitly giving both operands to 'wsbh'.
To make removing the use of 'rotl' a bit easier, also remove the unnecessary special-casing for big endian CPUs at .Lchacha_mips_xor_bytes. The tail handling is actually endian-independent since it processes one byte at a time. On big endian CPUs the old code byte-swapped SAVED_X, then iterated through it in reverse order. But the byteswap and reverse iteration canceled out.
Tested with chacha20poly1305-selftest in QEMU using "-M malta" with both little endian and big endian mips32r2 kernels.
Fixes: 49aa7c00eddf ("crypto: mips/chacha - import 32r2 ChaCha code from Zinc") Cc: stable@vger.kernel.org Reported-by: kernel test robot lkp@intel.com Closes: https://lore.kernel.org/oe-kbuild-all/202505080409.EujEBwA0-lkp@intel.com/ Link: https://lore.kernel.org/r/20250619225535.679301-1-ebiggers@kernel.org Signed-off-by: Eric Biggers ebiggers@kernel.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- arch/mips/lib/crypto/chacha-core.S | 20 +++++++------------- 1 file changed, 7 insertions(+), 13 deletions(-)
--- a/arch/mips/lib/crypto/chacha-core.S +++ b/arch/mips/lib/crypto/chacha-core.S @@ -55,17 +55,13 @@ #if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ #define MSB 0 #define LSB 3 -#define ROTx rotl -#define ROTR(n) rotr n, 24 #define CPU_TO_LE32(n) \ - wsbh n; \ + wsbh n, n; \ rotr n, 16; #else #define MSB 3 #define LSB 0 -#define ROTx rotr #define CPU_TO_LE32(n) -#define ROTR(n) #endif
#define FOR_EACH_WORD(x) \ @@ -192,10 +188,10 @@ CONCAT3(.Lchacha_mips_xor_aligned_, PLUS xor X(W), X(B); \ xor X(Y), X(C); \ xor X(Z), X(D); \ - rotl X(V), S; \ - rotl X(W), S; \ - rotl X(Y), S; \ - rotl X(Z), S; + rotr X(V), 32 - S; \ + rotr X(W), 32 - S; \ + rotr X(Y), 32 - S; \ + rotr X(Z), 32 - S;
.text .set reorder @@ -372,21 +368,19 @@ chacha_crypt_arch: /* First byte */ lbu T1, 0(IN) addiu $at, BYTES, 1 - CPU_TO_LE32(SAVED_X) - ROTR(SAVED_X) xor T1, SAVED_X sb T1, 0(OUT) beqz $at, .Lchacha_mips_xor_done /* Second byte */ lbu T1, 1(IN) addiu $at, BYTES, 2 - ROTx SAVED_X, 8 + rotr SAVED_X, 8 xor T1, SAVED_X sb T1, 1(OUT) beqz $at, .Lchacha_mips_xor_done /* Third byte */ lbu T1, 2(IN) - ROTx SAVED_X, 8 + rotr SAVED_X, 8 xor T1, SAVED_X sb T1, 2(OUT) b .Lchacha_mips_xor_done
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Eric Biggers ebiggers@kernel.org
commit 52c3e242f4d0043186b70d65460ba1767f27494a upstream.
Restore the SIMD usability check that was removed by commit 773426f4771b ("crypto: arm/poly1305 - Add block-only interface").
This safety check is cheap and is well worth eliminating a footgun. While the Poly1305 functions should not be called when SIMD registers are unusable, if they are anyway, they should just do the right thing instead of corrupting random tasks' registers and/or computing incorrect MACs. Fixing this is also needed for poly1305_kunit to pass.
Just use may_use_simd() instead of the original crypto_simd_usable(), since poly1305_kunit won't rely on crypto_simd_disabled_for_test.
Fixes: 773426f4771b ("crypto: arm/poly1305 - Add block-only interface") Cc: stable@vger.kernel.org Reviewed-by: Ard Biesheuvel ardb@kernel.org Link: https://lore.kernel.org/r/20250706231100.176113-3-ebiggers@kernel.org Signed-off-by: Eric Biggers ebiggers@kernel.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- arch/arm/lib/crypto/poly1305-glue.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
--- a/arch/arm/lib/crypto/poly1305-glue.c +++ b/arch/arm/lib/crypto/poly1305-glue.c @@ -7,6 +7,7 @@
#include <asm/hwcap.h> #include <asm/neon.h> +#include <asm/simd.h> #include <crypto/internal/poly1305.h> #include <linux/cpufeature.h> #include <linux/jump_label.h> @@ -39,7 +40,7 @@ void poly1305_blocks_arch(struct poly130 { len = round_down(len, POLY1305_BLOCK_SIZE); if (IS_ENABLED(CONFIG_KERNEL_MODE_NEON) && - static_branch_likely(&have_neon)) { + static_branch_likely(&have_neon) && likely(may_use_simd())) { do { unsigned int todo = min_t(unsigned int, len, SZ_4K);
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Eric Biggers ebiggers@kernel.org
commit eec76ea5a7213c48529a46eed1b343e5cee3aaab upstream.
Restore the SIMD usability check that was removed by commit a59e5468a921 ("crypto: arm64/poly1305 - Add block-only interface").
This safety check is cheap and is well worth eliminating a footgun. While the Poly1305 functions should not be called when SIMD registers are unusable, if they are anyway, they should just do the right thing instead of corrupting random tasks' registers and/or computing incorrect MACs. Fixing this is also needed for poly1305_kunit to pass.
Just use may_use_simd() instead of the original crypto_simd_usable(), since poly1305_kunit won't rely on crypto_simd_disabled_for_test.
Fixes: a59e5468a921 ("crypto: arm64/poly1305 - Add block-only interface") Cc: stable@vger.kernel.org Reviewed-by: Ard Biesheuvel ardb@kernel.org Link: https://lore.kernel.org/r/20250706231100.176113-4-ebiggers@kernel.org Signed-off-by: Eric Biggers ebiggers@kernel.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- arch/arm64/lib/crypto/poly1305-glue.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
--- a/arch/arm64/lib/crypto/poly1305-glue.c +++ b/arch/arm64/lib/crypto/poly1305-glue.c @@ -7,6 +7,7 @@
#include <asm/hwcap.h> #include <asm/neon.h> +#include <asm/simd.h> #include <crypto/internal/poly1305.h> #include <linux/cpufeature.h> #include <linux/jump_label.h> @@ -33,7 +34,7 @@ void poly1305_blocks_arch(struct poly130 unsigned int len, u32 padbit) { len = round_down(len, POLY1305_BLOCK_SIZE); - if (static_branch_likely(&have_neon)) { + if (static_branch_likely(&have_neon) && likely(may_use_simd())) { do { unsigned int todo = min_t(unsigned int, len, SZ_4K);
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Giovanni Cabiddu giovanni.cabiddu@intel.com
commit 8024774190a5ef2af2c5846f60a50b23e0980a32 upstream.
Most kernel applications utilizing the crypto API operate synchronously and on small buffer sizes, therefore do not benefit from QAT acceleration.
Reduce the priority of QAT implementations for both skcipher and aead algorithms, allowing more suitable alternatives to be selected by default.
Signed-off-by: Giovanni Cabiddu giovanni.cabiddu@intel.com Link: https://lore.kernel.org/all/20250613012357.GA3603104@google.com/ Cc: stable@vger.kernel.org Acked-by: Eric Biggers ebiggers@kernel.org Signed-off-by: Herbert Xu herbert@gondor.apana.org.au Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/crypto/intel/qat/qat_common/qat_algs.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-)
--- a/drivers/crypto/intel/qat/qat_common/qat_algs.c +++ b/drivers/crypto/intel/qat/qat_common/qat_algs.c @@ -1277,7 +1277,7 @@ static struct aead_alg qat_aeads[] = { { .base = { .cra_name = "authenc(hmac(sha1),cbc(aes))", .cra_driver_name = "qat_aes_cbc_hmac_sha1", - .cra_priority = 4001, + .cra_priority = 100, .cra_flags = CRYPTO_ALG_ASYNC | CRYPTO_ALG_ALLOCATES_MEMORY, .cra_blocksize = AES_BLOCK_SIZE, .cra_ctxsize = sizeof(struct qat_alg_aead_ctx), @@ -1294,7 +1294,7 @@ static struct aead_alg qat_aeads[] = { { .base = { .cra_name = "authenc(hmac(sha256),cbc(aes))", .cra_driver_name = "qat_aes_cbc_hmac_sha256", - .cra_priority = 4001, + .cra_priority = 100, .cra_flags = CRYPTO_ALG_ASYNC | CRYPTO_ALG_ALLOCATES_MEMORY, .cra_blocksize = AES_BLOCK_SIZE, .cra_ctxsize = sizeof(struct qat_alg_aead_ctx), @@ -1311,7 +1311,7 @@ static struct aead_alg qat_aeads[] = { { .base = { .cra_name = "authenc(hmac(sha512),cbc(aes))", .cra_driver_name = "qat_aes_cbc_hmac_sha512", - .cra_priority = 4001, + .cra_priority = 100, .cra_flags = CRYPTO_ALG_ASYNC | CRYPTO_ALG_ALLOCATES_MEMORY, .cra_blocksize = AES_BLOCK_SIZE, .cra_ctxsize = sizeof(struct qat_alg_aead_ctx), @@ -1329,7 +1329,7 @@ static struct aead_alg qat_aeads[] = { { static struct skcipher_alg qat_skciphers[] = { { .base.cra_name = "cbc(aes)", .base.cra_driver_name = "qat_aes_cbc", - .base.cra_priority = 4001, + .base.cra_priority = 100, .base.cra_flags = CRYPTO_ALG_ASYNC | CRYPTO_ALG_ALLOCATES_MEMORY, .base.cra_blocksize = AES_BLOCK_SIZE, .base.cra_ctxsize = sizeof(struct qat_alg_skcipher_ctx), @@ -1347,7 +1347,7 @@ static struct skcipher_alg qat_skciphers }, { .base.cra_name = "ctr(aes)", .base.cra_driver_name = "qat_aes_ctr", - .base.cra_priority = 4001, + .base.cra_priority = 100, .base.cra_flags = CRYPTO_ALG_ASYNC | CRYPTO_ALG_ALLOCATES_MEMORY, .base.cra_blocksize = 1, .base.cra_ctxsize = sizeof(struct qat_alg_skcipher_ctx), @@ -1365,7 +1365,7 @@ static struct skcipher_alg qat_skciphers }, { .base.cra_name = "xts(aes)", .base.cra_driver_name = "qat_aes_xts", - .base.cra_priority = 4001, + .base.cra_priority = 100, .base.cra_flags = CRYPTO_ALG_ASYNC | CRYPTO_ALG_NEED_FALLBACK | CRYPTO_ALG_ALLOCATES_MEMORY, .base.cra_blocksize = AES_BLOCK_SIZE,
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ashish Kalra ashish.kalra@amd.com
commit ab8b9fd39c45b7760093528cbef93e7353359d82 upstream.
Panic notifiers are invoked with RCU read lock held and when the SNP panic notifier tries to unregister itself from the panic notifier callback itself it causes a deadlock as notifier unregistration does RCU synchronization.
Code flow for SNP panic notifier: snp_shutdown_on_panic() -> __sev_firmware_shutdown() -> __sev_snp_shutdown_locked() -> atomic_notifier_chain_unregister(.., &snp_panic_notifier)
Fix SNP panic notifier to unregister itself during SNP shutdown only if panic is not in progress.
Reviewed-by: Tom Lendacky thomas.lendacky@amd.com Cc: stable@vger.kernel.org Fixes: 19860c3274fb ("crypto: ccp - Register SNP panic notifier only if SNP is enabled") Signed-off-by: Ashish Kalra ashish.kalra@amd.com Signed-off-by: Herbert Xu herbert@gondor.apana.org.au Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/crypto/ccp/sev-dev.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-)
diff --git a/drivers/crypto/ccp/sev-dev.c b/drivers/crypto/ccp/sev-dev.c index 8fb94c5f006a..17edc6bf5622 100644 --- a/drivers/crypto/ccp/sev-dev.c +++ b/drivers/crypto/ccp/sev-dev.c @@ -1787,8 +1787,14 @@ static int __sev_snp_shutdown_locked(int *error, bool panic) sev->snp_initialized = false; dev_dbg(sev->dev, "SEV-SNP firmware shutdown\n");
- atomic_notifier_chain_unregister(&panic_notifier_list, - &snp_panic_notifier); + /* + * __sev_snp_shutdown_locked() deadlocks when it tries to unregister + * itself during panic as the panic notifier is called with RCU read + * lock held and notifier unregistration does RCU synchronization. + */ + if (!panic) + atomic_notifier_chain_unregister(&panic_notifier_list, + &snp_panic_notifier);
/* Reset TMR size back to default */ sev_es_tmr_size = SEV_TMR_SIZE;
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: John Ernberg john.ernberg@actia.se
commit 5ffc47feddcf8eb4d8ac7b42111a02c8e8146512 upstream.
Since the CAAM on these SoCs is managed by another ARM core, called the SECO (Security Controller) on iMX8QM and Secure Enclave on iMX8ULP, which also reserves access to register page 0 suspend operations cannot touch this page.
This is similar to when running OPTEE, where OPTEE will reserve page 0.
Track this situation using a new state variable no_page0, reflecting if page 0 is reserved elsewhere, either by other management cores in SoC or by OPTEE.
Replace the optee_en check in suspend/resume with the new check.
optee_en cannot go away as it's needed elsewhere to gate OPTEE specific situations.
Fixes the following splat at suspend:
Internal error: synchronous external abort: 0000000096000010 [#1] SMP Hardware name: Freescale i.MX8QXP ACU6C (DT) pstate: 60400005 (nZCv daif +PAN -UAO -TCO -DIT -SSBS BTYPE=--) pc : readl+0x0/0x18 lr : rd_reg32+0x18/0x3c sp : ffffffc08192ba20 x29: ffffffc08192ba20 x28: ffffff8025190000 x27: 0000000000000000 x26: ffffffc0808ae808 x25: ffffffc080922338 x24: ffffff8020e89090 x23: 0000000000000000 x22: ffffffc080922000 x21: ffffff8020e89010 x20: ffffffc080387ef8 x19: ffffff8020e89010 x18: 000000005d8000d5 x17: 0000000030f35963 x16: 000000008f785f3f x15: 000000003b8ef57c x14: 00000000c418aef8 x13: 00000000f5fea526 x12: 0000000000000001 x11: 0000000000000002 x10: 0000000000000001 x9 : 0000000000000000 x8 : ffffff8025190870 x7 : ffffff8021726880 x6 : 0000000000000002 x5 : ffffff80217268f0 x4 : ffffff8021726880 x3 : ffffffc081200000 x2 : 0000000000000001 x1 : ffffff8020e89010 x0 : ffffffc081200004 Call trace: readl+0x0/0x18 caam_ctrl_suspend+0x30/0xdc dpm_run_callback.constprop.0+0x24/0x5c device_suspend+0x170/0x2e8 dpm_suspend+0xa0/0x104 dpm_suspend_start+0x48/0x50 suspend_devices_and_enter+0x7c/0x45c pm_suspend+0x148/0x160 state_store+0xb4/0xf8 kobj_attr_store+0x14/0x24 sysfs_kf_write+0x38/0x48 kernfs_fop_write_iter+0xb4/0x178 vfs_write+0x118/0x178 ksys_write+0x6c/0xd0 __arm64_sys_write+0x14/0x1c invoke_syscall.constprop.0+0x64/0xb0 do_el0_svc+0x90/0xb0 el0_svc+0x18/0x44 el0t_64_sync_handler+0x88/0x124 el0t_64_sync+0x150/0x154 Code: 88dffc21 88dffc21 5ac00800 d65f03c0 (b9400000)
Fixes: d2835701d93c ("crypto: caam - i.MX8ULP donot have CAAM page0 access") Cc: stable@kernel.org # v6.10+ Signed-off-by: John Ernberg john.ernberg@actia.se Reviewed-by: Peng Fan peng.fan@nxp.com Reviewed-by: Frank Li Frank.Li@nxp.com Signed-off-by: Herbert Xu herbert@gondor.apana.org.au Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/crypto/caam/ctrl.c | 5 +++-- drivers/crypto/caam/intern.h | 1 + 2 files changed, 4 insertions(+), 2 deletions(-)
--- a/drivers/crypto/caam/ctrl.c +++ b/drivers/crypto/caam/ctrl.c @@ -831,7 +831,7 @@ static int caam_ctrl_suspend(struct devi { const struct caam_drv_private *ctrlpriv = dev_get_drvdata(dev);
- if (ctrlpriv->caam_off_during_pm && !ctrlpriv->optee_en) + if (ctrlpriv->caam_off_during_pm && !ctrlpriv->no_page0) caam_state_save(dev);
return 0; @@ -842,7 +842,7 @@ static int caam_ctrl_resume(struct devic struct caam_drv_private *ctrlpriv = dev_get_drvdata(dev); int ret = 0;
- if (ctrlpriv->caam_off_during_pm && !ctrlpriv->optee_en) { + if (ctrlpriv->caam_off_during_pm && !ctrlpriv->no_page0) { caam_state_restore(dev);
/* HW and rng will be reset so deinstantiation can be removed */ @@ -908,6 +908,7 @@ static int caam_probe(struct platform_de
imx_soc_data = imx_soc_match->data; reg_access = reg_access && imx_soc_data->page0_access; + ctrlpriv->no_page0 = !reg_access; /* * CAAM clocks cannot be controlled from kernel. */ --- a/drivers/crypto/caam/intern.h +++ b/drivers/crypto/caam/intern.h @@ -115,6 +115,7 @@ struct caam_drv_private { u8 blob_present; /* Nonzero if BLOB support present in device */ u8 mc_en; /* Nonzero if MC f/w is active */ u8 optee_en; /* Nonzero if OP-TEE f/w is active */ + u8 no_page0; /* Nonzero if register page 0 is not controlled by Linux */ bool pr_support; /* RNG prediction resistance available */ int secvio_irq; /* Security violation interrupt number */ int virt_en; /* Virtualization enabled in CAAM */
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Giovanni Cabiddu giovanni.cabiddu@intel.com
commit 3d4df408ba9bad2b205c7fb8afc1836a6a4ca88a upstream.
Repeated loading and unloading of a device specific QAT driver, for example qat_4xxx, in a tight loop can lead to a crash due to a use-after-free scenario. This occurs when a power management (PM) interrupt triggers just before the device-specific driver (e.g., qat_4xxx.ko) is unloaded, while the core driver (intel_qat.ko) remains loaded.
Since the driver uses a shared workqueue (`qat_misc_wq`) across all devices and owned by intel_qat.ko, a deferred routine from the device-specific driver may still be pending in the queue. If this routine executes after the driver is unloaded, it can dereference freed memory, resulting in a page fault and kernel crash like the following:
BUG: unable to handle page fault for address: ffa000002e50a01c #PF: supervisor read access in kernel mode RIP: 0010:pm_bh_handler+0x1d2/0x250 [intel_qat] Call Trace: pm_bh_handler+0x1d2/0x250 [intel_qat] process_one_work+0x171/0x340 worker_thread+0x277/0x3a0 kthread+0xf0/0x120 ret_from_fork+0x2d/0x50
To prevent this, flush the misc workqueue during device shutdown to ensure that all pending work items are completed before the driver is unloaded.
Note: This approach may slightly increase shutdown latency if the workqueue contains jobs from other devices, but it ensures correctness and stability.
Fixes: e5745f34113b ("crypto: qat - enable power management for QAT GEN4") Signed-off-by: Giovanni Cabiddu giovanni.cabiddu@intel.com Cc: stable@vger.kernel.org Reviewed-by: Ahsan Atta ahsan.atta@intel.com Signed-off-by: Herbert Xu herbert@gondor.apana.org.au Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/crypto/intel/qat/qat_common/adf_common_drv.h | 1 + drivers/crypto/intel/qat/qat_common/adf_init.c | 1 + drivers/crypto/intel/qat/qat_common/adf_isr.c | 5 +++++ 3 files changed, 7 insertions(+)
--- a/drivers/crypto/intel/qat/qat_common/adf_common_drv.h +++ b/drivers/crypto/intel/qat/qat_common/adf_common_drv.h @@ -189,6 +189,7 @@ void adf_exit_misc_wq(void); bool adf_misc_wq_queue_work(struct work_struct *work); bool adf_misc_wq_queue_delayed_work(struct delayed_work *work, unsigned long delay); +void adf_misc_wq_flush(void); #if defined(CONFIG_PCI_IOV) int adf_sriov_configure(struct pci_dev *pdev, int numvfs); void adf_disable_sriov(struct adf_accel_dev *accel_dev); --- a/drivers/crypto/intel/qat/qat_common/adf_init.c +++ b/drivers/crypto/intel/qat/qat_common/adf_init.c @@ -404,6 +404,7 @@ static void adf_dev_shutdown(struct adf_ hw_data->exit_admin_comms(accel_dev);
adf_cleanup_etr_data(accel_dev); + adf_misc_wq_flush(); adf_dev_restore(accel_dev); }
--- a/drivers/crypto/intel/qat/qat_common/adf_isr.c +++ b/drivers/crypto/intel/qat/qat_common/adf_isr.c @@ -407,3 +407,8 @@ bool adf_misc_wq_queue_delayed_work(stru { return queue_delayed_work(adf_misc_wq, work, delay); } + +void adf_misc_wq_flush(void) +{ + flush_workqueue(adf_misc_wq); +}
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Eric Biggers ebiggers@kernel.org
commit c7f49dadfcdf27e1f747442e874e9baa52ab7674 upstream.
skcipher_walk_done() can call kfree(), which takes a spinlock, which makes it incorrect to call while preemption is disabled on PREEMPT_RT. Therefore, end the kernel-mode FPU section before calling skcipher_walk_done(), and restart it afterwards.
Moreover, pass atomic=false to skcipher_walk_aead_encrypt() instead of atomic=true. The point of atomic=true was to make skcipher_walk_done() safe to call while in a kernel-mode FPU section, but that does not actually work. So just use the usual atomic=false.
Fixes: 1d373d4e8e15 ("crypto: x86 - Add optimized AEGIS implementations") Cc: stable@vger.kernel.org Signed-off-by: Eric Biggers ebiggers@kernel.org Signed-off-by: Herbert Xu herbert@gondor.apana.org.au Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- arch/x86/crypto/aegis128-aesni-glue.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-)
--- a/arch/x86/crypto/aegis128-aesni-glue.c +++ b/arch/x86/crypto/aegis128-aesni-glue.c @@ -119,7 +119,9 @@ crypto_aegis128_aesni_process_crypt(stru walk->dst.virt.addr, round_down(walk->nbytes, AEGIS128_BLOCK_SIZE)); + kernel_fpu_end(); skcipher_walk_done(walk, walk->nbytes % AEGIS128_BLOCK_SIZE); + kernel_fpu_begin(); }
if (walk->nbytes) { @@ -131,7 +133,9 @@ crypto_aegis128_aesni_process_crypt(stru aegis128_aesni_dec_tail(state, walk->src.virt.addr, walk->dst.virt.addr, walk->nbytes); + kernel_fpu_end(); skcipher_walk_done(walk, 0); + kernel_fpu_begin(); } }
@@ -176,9 +180,9 @@ crypto_aegis128_aesni_crypt(struct aead_ struct aegis_state state;
if (enc) - skcipher_walk_aead_encrypt(&walk, req, true); + skcipher_walk_aead_encrypt(&walk, req, false); else - skcipher_walk_aead_decrypt(&walk, req, true); + skcipher_walk_aead_decrypt(&walk, req, false);
kernel_fpu_begin();
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Eric Biggers ebiggers@kernel.org
commit 3d9eb180fbe8828cce43bce4c370124685b205c3 upstream.
The skcipher_walk functions can allocate memory and can fail, so checking for errors is necessary.
Fixes: 1d373d4e8e15 ("crypto: x86 - Add optimized AEGIS implementations") Cc: stable@vger.kernel.org Signed-off-by: Eric Biggers ebiggers@kernel.org Signed-off-by: Herbert Xu herbert@gondor.apana.org.au Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- arch/x86/crypto/aegis128-aesni-glue.c | 36 +++++++++++++++++++++++----------- 1 file changed, 25 insertions(+), 11 deletions(-)
--- a/arch/x86/crypto/aegis128-aesni-glue.c +++ b/arch/x86/crypto/aegis128-aesni-glue.c @@ -104,10 +104,12 @@ static void crypto_aegis128_aesni_proces } }
-static __always_inline void +static __always_inline int crypto_aegis128_aesni_process_crypt(struct aegis_state *state, struct skcipher_walk *walk, bool enc) { + int err = 0; + while (walk->nbytes >= AEGIS128_BLOCK_SIZE) { if (enc) aegis128_aesni_enc(state, walk->src.virt.addr, @@ -120,7 +122,8 @@ crypto_aegis128_aesni_process_crypt(stru round_down(walk->nbytes, AEGIS128_BLOCK_SIZE)); kernel_fpu_end(); - skcipher_walk_done(walk, walk->nbytes % AEGIS128_BLOCK_SIZE); + err = skcipher_walk_done(walk, + walk->nbytes % AEGIS128_BLOCK_SIZE); kernel_fpu_begin(); }
@@ -134,9 +137,10 @@ crypto_aegis128_aesni_process_crypt(stru walk->dst.virt.addr, walk->nbytes); kernel_fpu_end(); - skcipher_walk_done(walk, 0); + err = skcipher_walk_done(walk, 0); kernel_fpu_begin(); } + return err; }
static struct aegis_ctx *crypto_aegis128_aesni_ctx(struct crypto_aead *aead) @@ -169,7 +173,7 @@ static int crypto_aegis128_aesni_setauth return 0; }
-static __always_inline void +static __always_inline int crypto_aegis128_aesni_crypt(struct aead_request *req, struct aegis_block *tag_xor, unsigned int cryptlen, bool enc) @@ -178,20 +182,24 @@ crypto_aegis128_aesni_crypt(struct aead_ struct aegis_ctx *ctx = crypto_aegis128_aesni_ctx(tfm); struct skcipher_walk walk; struct aegis_state state; + int err;
if (enc) - skcipher_walk_aead_encrypt(&walk, req, false); + err = skcipher_walk_aead_encrypt(&walk, req, false); else - skcipher_walk_aead_decrypt(&walk, req, false); + err = skcipher_walk_aead_decrypt(&walk, req, false); + if (err) + return err;
kernel_fpu_begin();
aegis128_aesni_init(&state, &ctx->key, req->iv); crypto_aegis128_aesni_process_ad(&state, req->src, req->assoclen); - crypto_aegis128_aesni_process_crypt(&state, &walk, enc); - aegis128_aesni_final(&state, tag_xor, req->assoclen, cryptlen); - + err = crypto_aegis128_aesni_process_crypt(&state, &walk, enc); + if (err == 0) + aegis128_aesni_final(&state, tag_xor, req->assoclen, cryptlen); kernel_fpu_end(); + return err; }
static int crypto_aegis128_aesni_encrypt(struct aead_request *req) @@ -200,8 +208,11 @@ static int crypto_aegis128_aesni_encrypt struct aegis_block tag = {}; unsigned int authsize = crypto_aead_authsize(tfm); unsigned int cryptlen = req->cryptlen; + int err;
- crypto_aegis128_aesni_crypt(req, &tag, cryptlen, true); + err = crypto_aegis128_aesni_crypt(req, &tag, cryptlen, true); + if (err) + return err;
scatterwalk_map_and_copy(tag.bytes, req->dst, req->assoclen + cryptlen, authsize, 1); @@ -216,11 +227,14 @@ static int crypto_aegis128_aesni_decrypt struct aegis_block tag; unsigned int authsize = crypto_aead_authsize(tfm); unsigned int cryptlen = req->cryptlen - authsize; + int err;
scatterwalk_map_and_copy(tag.bytes, req->src, req->assoclen + cryptlen, authsize, 0);
- crypto_aegis128_aesni_crypt(req, &tag, cryptlen, false); + err = crypto_aegis128_aesni_crypt(req, &tag, cryptlen, false); + if (err) + return err;
return crypto_memneq(tag.bytes, zeros.bytes, authsize) ? -EBADMSG : 0; }
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Bharat Bhushan bbhushan2@marvell.com
commit b7b88b4939e71ef2aed8238976a2bbabcb63a790 upstream.
octeontx2 crypto driver allocates memory using kmalloc/kzalloc, and uses this memory for dma (does dma_map_single()). It assumes that kmalloc/kzalloc will return 128-byte aligned address. But kmalloc/kzalloc returns 8-byte aligned address after below changes: "9382bc44b5f5 arm64: allow kmalloc() caches aligned to the smaller cache_line_size()"
Completion address should be 32-Byte alignment when loading microcode.
Signed-off-by: Bharat Bhushan bbhushan2@marvell.com Cc: stable@vger.kernel.org # v6.5+ Signed-off-by: Herbert Xu herbert@gondor.apana.org.au Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/crypto/marvell/octeontx2/otx2_cptpf_ucode.c | 35 ++++++++++++-------- 1 file changed, 21 insertions(+), 14 deletions(-)
--- a/drivers/crypto/marvell/octeontx2/otx2_cptpf_ucode.c +++ b/drivers/crypto/marvell/octeontx2/otx2_cptpf_ucode.c @@ -1491,12 +1491,13 @@ int otx2_cpt_discover_eng_capabilities(s union otx2_cpt_opcode opcode; union otx2_cpt_res_s *result; union otx2_cpt_inst_s inst; + dma_addr_t result_baddr; dma_addr_t rptr_baddr; struct pci_dev *pdev; - u32 len, compl_rlen; int timeout = 10000; + void *base, *rptr; int ret, etype; - void *rptr; + u32 len;
/* * We don't get capabilities if it was already done @@ -1519,22 +1520,28 @@ int otx2_cpt_discover_eng_capabilities(s if (ret) goto delete_grps;
- compl_rlen = ALIGN(sizeof(union otx2_cpt_res_s), OTX2_CPT_DMA_MINALIGN); - len = compl_rlen + LOADFVC_RLEN; + /* Allocate extra memory for "rptr" and "result" pointer alignment */ + len = LOADFVC_RLEN + ARCH_DMA_MINALIGN + + sizeof(union otx2_cpt_res_s) + OTX2_CPT_RES_ADDR_ALIGN;
- result = kzalloc(len, GFP_KERNEL); - if (!result) { + base = kzalloc(len, GFP_KERNEL); + if (!base) { ret = -ENOMEM; goto lf_cleanup; } - rptr_baddr = dma_map_single(&pdev->dev, (void *)result, len, - DMA_BIDIRECTIONAL); + + rptr = PTR_ALIGN(base, ARCH_DMA_MINALIGN); + rptr_baddr = dma_map_single(&pdev->dev, rptr, len, DMA_BIDIRECTIONAL); if (dma_mapping_error(&pdev->dev, rptr_baddr)) { dev_err(&pdev->dev, "DMA mapping failed\n"); ret = -EFAULT; - goto free_result; + goto free_rptr; } - rptr = (u8 *)result + compl_rlen; + + result = (union otx2_cpt_res_s *)PTR_ALIGN(rptr + LOADFVC_RLEN, + OTX2_CPT_RES_ADDR_ALIGN); + result_baddr = ALIGN(rptr_baddr + LOADFVC_RLEN, + OTX2_CPT_RES_ADDR_ALIGN);
/* Fill in the command */ opcode.s.major = LOADFVC_MAJOR_OP; @@ -1546,14 +1553,14 @@ int otx2_cpt_discover_eng_capabilities(s /* 64-bit swap for microcode data reads, not needed for addresses */ cpu_to_be64s(&iq_cmd.cmd.u); iq_cmd.dptr = 0; - iq_cmd.rptr = rptr_baddr + compl_rlen; + iq_cmd.rptr = rptr_baddr; iq_cmd.cptr.u = 0;
for (etype = 1; etype < OTX2_CPT_MAX_ENG_TYPES; etype++) { result->s.compcode = OTX2_CPT_COMPLETION_CODE_INIT; iq_cmd.cptr.s.grp = otx2_cpt_get_eng_grp(&cptpf->eng_grps, etype); - otx2_cpt_fill_inst(&inst, &iq_cmd, rptr_baddr); + otx2_cpt_fill_inst(&inst, &iq_cmd, result_baddr); lfs->ops->send_cmd(&inst, 1, &cptpf->lfs.lf[0]); timeout = 10000;
@@ -1576,8 +1583,8 @@ int otx2_cpt_discover_eng_capabilities(s
error_no_response: dma_unmap_single(&pdev->dev, rptr_baddr, len, DMA_BIDIRECTIONAL); -free_result: - kfree(result); +free_rptr: + kfree(base); lf_cleanup: otx2_cptlf_shutdown(lfs); delete_grps:
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Bharat Bhushan bbhushan2@marvell.com
commit 2e13163b43e6bb861182ea999a80dd1d893c0cbf upstream.
octeontx2 crypto driver allocates memory using kmalloc/kzalloc, and uses this memory for dma (does dma_map_single()). It assumes that kmalloc/kzalloc will return 128-byte aligned address. But kmalloc/kzalloc returns 8-byte aligned address after below changes: "9382bc44b5f5 arm64: allow kmalloc() caches aligned to the smaller cache_line_size()
Memory allocated are used for following purpose: - Input data or scatter list address - 8-Byte alignment - Output data or gather list address - 8-Byte alignment - Completion address - 32-Byte alignment.
This patch ensures all addresses are aligned as mentioned above.
Signed-off-by: Bharat Bhushan bbhushan2@marvell.com Cc: stable@vger.kernel.org # v6.5+ Signed-off-by: Herbert Xu herbert@gondor.apana.org.au Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/crypto/marvell/octeontx2/otx2_cpt_reqmgr.h | 66 ++++++++++++++++----- 1 file changed, 51 insertions(+), 15 deletions(-)
--- a/drivers/crypto/marvell/octeontx2/otx2_cpt_reqmgr.h +++ b/drivers/crypto/marvell/octeontx2/otx2_cpt_reqmgr.h @@ -34,6 +34,9 @@ #define SG_COMP_2 2 #define SG_COMP_1 1
+#define OTX2_CPT_DPTR_RPTR_ALIGN 8 +#define OTX2_CPT_RES_ADDR_ALIGN 32 + union otx2_cpt_opcode { u16 flags; struct { @@ -417,10 +420,9 @@ static inline struct otx2_cpt_inst_info otx2_sg_info_create(struct pci_dev *pdev, struct otx2_cpt_req_info *req, gfp_t gfp) { - int align = OTX2_CPT_DMA_MINALIGN; struct otx2_cpt_inst_info *info; - u32 dlen, align_dlen, info_len; - u16 g_sz_bytes, s_sz_bytes; + u32 dlen, info_len; + u16 g_len, s_len; u32 total_mem_len;
if (unlikely(req->in_cnt > OTX2_CPT_MAX_SG_IN_CNT || @@ -429,22 +431,54 @@ otx2_sg_info_create(struct pci_dev *pdev return NULL; }
- g_sz_bytes = ((req->in_cnt + 3) / 4) * - sizeof(struct otx2_cpt_sglist_component); - s_sz_bytes = ((req->out_cnt + 3) / 4) * - sizeof(struct otx2_cpt_sglist_component); + /* Allocate memory to meet below alignment requirement: + * ------------------------------------ + * | struct otx2_cpt_inst_info | + * | (No alignment required) | + * | --------------------------------| + * | | padding for ARCH_DMA_MINALIGN | + * | | alignment | + * |------------------------------------| + * | SG List Header of 8 Byte | + * |------------------------------------| + * | SG List Gather/Input memory | + * | Length = multiple of 32Bytes | + * | Alignment = 8Byte | + * |---------------------------------- | + * | SG List Scatter/Output memory | + * | Length = multiple of 32Bytes | + * | Alignment = 8Byte | + * | -------------------------------| + * | | padding for 32B alignment | + * |------------------------------------| + * | Result response memory | + * | Alignment = 32Byte | + * ------------------------------------ + */
- dlen = g_sz_bytes + s_sz_bytes + SG_LIST_HDR_SIZE; - align_dlen = ALIGN(dlen, align); - info_len = ALIGN(sizeof(*info), align); - total_mem_len = align_dlen + info_len + sizeof(union otx2_cpt_res_s); + info_len = sizeof(*info); + + g_len = ((req->in_cnt + 3) / 4) * + sizeof(struct otx2_cpt_sglist_component); + s_len = ((req->out_cnt + 3) / 4) * + sizeof(struct otx2_cpt_sglist_component); + + dlen = g_len + s_len + SG_LIST_HDR_SIZE; + + /* Allocate extra memory for SG and response address alignment */ + total_mem_len = ALIGN(info_len, OTX2_CPT_DPTR_RPTR_ALIGN); + total_mem_len += (ARCH_DMA_MINALIGN - 1) & + ~(OTX2_CPT_DPTR_RPTR_ALIGN - 1); + total_mem_len += ALIGN(dlen, OTX2_CPT_RES_ADDR_ALIGN); + total_mem_len += sizeof(union otx2_cpt_res_s);
info = kzalloc(total_mem_len, gfp); if (unlikely(!info)) return NULL;
info->dlen = dlen; - info->in_buffer = (u8 *)info + info_len; + info->in_buffer = PTR_ALIGN((u8 *)info + info_len, ARCH_DMA_MINALIGN); + info->out_buffer = info->in_buffer + SG_LIST_HDR_SIZE + g_len;
((u16 *)info->in_buffer)[0] = req->out_cnt; ((u16 *)info->in_buffer)[1] = req->in_cnt; @@ -460,7 +494,7 @@ otx2_sg_info_create(struct pci_dev *pdev }
if (setup_sgio_components(pdev, req->out, req->out_cnt, - &info->in_buffer[8 + g_sz_bytes])) { + info->out_buffer)) { dev_err(&pdev->dev, "Failed to setup scatter list\n"); goto destroy_info; } @@ -476,8 +510,10 @@ otx2_sg_info_create(struct pci_dev *pdev * Get buffer for union otx2_cpt_res_s response * structure and its physical address */ - info->completion_addr = info->in_buffer + align_dlen; - info->comp_baddr = info->dptr_baddr + align_dlen; + info->completion_addr = PTR_ALIGN((info->in_buffer + dlen), + OTX2_CPT_RES_ADDR_ALIGN); + info->comp_baddr = ALIGN((info->dptr_baddr + dlen), + OTX2_CPT_RES_ADDR_ALIGN);
return info;
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Bharat Bhushan bbhushan2@marvell.com
commit a091a58b8a1eba2f243b0c05bcc82bdc2a4a338d upstream.
octeontx2 crypto driver allocates memory using kmalloc/kzalloc, and uses this memory for dma (does dma_map_single()). It assumes that kmalloc/kzalloc will return 128-byte aligned address. But kmalloc/kzalloc returns 8-byte aligned address after below changes: "9382bc44b5f5 arm64: allow kmalloc() caches aligned to the smaller cache_line_size()
Memory allocated are used for following purpose: - Input data or scatter list address - 8-Byte alignment - Output data or gather list address - 8-Byte alignment - Completion address - 32-Byte alignment.
This patch ensures all addresses are aligned as mentioned above.
Signed-off-by: Bharat Bhushan bbhushan2@marvell.com Cc: stable@vger.kernel.org # v6.8+ Signed-off-by: Herbert Xu herbert@gondor.apana.org.au Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/crypto/marvell/octeontx2/otx2_cpt_reqmgr.h | 61 +++++++++++++++------ 1 file changed, 45 insertions(+), 16 deletions(-)
--- a/drivers/crypto/marvell/octeontx2/otx2_cpt_reqmgr.h +++ b/drivers/crypto/marvell/octeontx2/otx2_cpt_reqmgr.h @@ -350,22 +350,48 @@ static inline struct otx2_cpt_inst_info cn10k_sgv2_info_create(struct pci_dev *pdev, struct otx2_cpt_req_info *req, gfp_t gfp) { - u32 dlen = 0, g_len, sg_len, info_len; - int align = OTX2_CPT_DMA_MINALIGN; + u32 dlen = 0, g_len, s_len, sg_len, info_len; struct otx2_cpt_inst_info *info; - u16 g_sz_bytes, s_sz_bytes; u32 total_mem_len; int i;
- g_sz_bytes = ((req->in_cnt + 2) / 3) * - sizeof(struct cn10kb_cpt_sglist_component); - s_sz_bytes = ((req->out_cnt + 2) / 3) * - sizeof(struct cn10kb_cpt_sglist_component); - - g_len = ALIGN(g_sz_bytes, align); - sg_len = ALIGN(g_len + s_sz_bytes, align); - info_len = ALIGN(sizeof(*info), align); - total_mem_len = sg_len + info_len + sizeof(union otx2_cpt_res_s); + /* Allocate memory to meet below alignment requirement: + * ------------------------------------ + * | struct otx2_cpt_inst_info | + * | (No alignment required) | + * | --------------------------------| + * | | padding for ARCH_DMA_MINALIGN | + * | | alignment | + * |------------------------------------| + * | SG List Gather/Input memory | + * | Length = multiple of 32Bytes | + * | Alignment = 8Byte | + * |---------------------------------- | + * | SG List Scatter/Output memory | + * | Length = multiple of 32Bytes | + * | Alignment = 8Byte | + * | -------------------------------| + * | | padding for 32B alignment | + * |------------------------------------| + * | Result response memory | + * | Alignment = 32Byte | + * ------------------------------------ + */ + + info_len = sizeof(*info); + + g_len = ((req->in_cnt + 2) / 3) * + sizeof(struct cn10kb_cpt_sglist_component); + s_len = ((req->out_cnt + 2) / 3) * + sizeof(struct cn10kb_cpt_sglist_component); + sg_len = g_len + s_len; + + /* Allocate extra memory for SG and response address alignment */ + total_mem_len = ALIGN(info_len, OTX2_CPT_DPTR_RPTR_ALIGN); + total_mem_len += (ARCH_DMA_MINALIGN - 1) & + ~(OTX2_CPT_DPTR_RPTR_ALIGN - 1); + total_mem_len += ALIGN(sg_len, OTX2_CPT_RES_ADDR_ALIGN); + total_mem_len += sizeof(union otx2_cpt_res_s);
info = kzalloc(total_mem_len, gfp); if (unlikely(!info)) @@ -375,7 +401,8 @@ cn10k_sgv2_info_create(struct pci_dev *p dlen += req->in[i].size;
info->dlen = dlen; - info->in_buffer = (u8 *)info + info_len; + info->in_buffer = PTR_ALIGN((u8 *)info + info_len, ARCH_DMA_MINALIGN); + info->out_buffer = info->in_buffer + g_len; info->gthr_sz = req->in_cnt; info->sctr_sz = req->out_cnt;
@@ -387,7 +414,7 @@ cn10k_sgv2_info_create(struct pci_dev *p }
if (sgv2io_components_setup(pdev, req->out, req->out_cnt, - &info->in_buffer[g_len])) { + info->out_buffer)) { dev_err(&pdev->dev, "Failed to setup scatter list\n"); goto destroy_info; } @@ -404,8 +431,10 @@ cn10k_sgv2_info_create(struct pci_dev *p * Get buffer for union otx2_cpt_res_s response * structure and its physical address */ - info->completion_addr = info->in_buffer + sg_len; - info->comp_baddr = info->dptr_baddr + sg_len; + info->completion_addr = PTR_ALIGN((info->in_buffer + sg_len), + OTX2_CPT_RES_ADDR_ALIGN); + info->comp_baddr = ALIGN((info->dptr_baddr + sg_len), + OTX2_CPT_RES_ADDR_ALIGN);
return info;
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Herbert Xu herbert@gondor.apana.org.au
commit 9d9b193ed73a65ec47cf1fd39925b09da8216461 upstream.
The value of HASH_MAX_DESCSIZE is off by one for hmac(sha3-224-s390). Fix this so that hmac(sha3-224-s390) can be registered.
Reported-by: Ingo Franzki ifranzki@linux.ibm.com Reported-by: Eric Biggers ebiggers@kernel.org Fixes: 6f90ba706551 ("crypto: s390/sha3 - Use API partial block handling") Cc: stable@vger.kernel.org Signed-off-by: Herbert Xu herbert@gondor.apana.org.au Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- include/crypto/hash.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/include/crypto/hash.h b/include/crypto/hash.h index 6f6b9de12cd3..ed63b904837d 100644 --- a/include/crypto/hash.h +++ b/include/crypto/hash.h @@ -184,7 +184,7 @@ struct shash_desc { * Worst case is hmac(sha3-224-s390). Its context is a nested 'shash_desc' * containing a 'struct s390_sha_ctx'. */ -#define HASH_MAX_DESCSIZE (sizeof(struct shash_desc) + 360) +#define HASH_MAX_DESCSIZE (sizeof(struct shash_desc) + 361) #define MAX_SYNC_HASH_REQSIZE (sizeof(struct ahash_request) + \ HASH_MAX_DESCSIZE)
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Helge Deller deller@gmx.de
commit e4fc307d8e24f122402907ebf585248cad52841d upstream.
This reverts commit 864f9963ec6b4b76d104d595ba28110b87158003.
The patch is wrong as it checks vc_origin against vc_screenbuf, while in text mode it should compare against vga_vram_base.
As such it broke VGA text scrolling, which can be reproduced like this: (1) boot a kernel that is configured to use text mode VGA-console (2) type commands: ls -l /usr/bin | less -S (3) scroll up/down with cursor-down/up keys
Reported-by: Jari Ruusu jariruusu@protonmail.com Cc: stable@vger.kernel.org Cc: Yi Yang yiyang13@huawei.com Cc: GONG Ruiqi gongruiqi1@huawei.com Signed-off-by: Helge Deller deller@gmx.de Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/video/console/vgacon.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
--- a/drivers/video/console/vgacon.c +++ b/drivers/video/console/vgacon.c @@ -1168,7 +1168,7 @@ static bool vgacon_scroll(struct vc_data c->vc_screenbuf_size - delta); c->vc_origin = vga_vram_end - c->vc_screenbuf_size; vga_rolled_over = 0; - } else if (oldo - delta >= (unsigned long)c->vc_screenbuf) + } else c->vc_origin -= delta; c->vc_scr_end = c->vc_origin + c->vc_screenbuf_size; scr_memsetw((u16 *) (c->vc_origin), c->vc_video_erase_char,
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ziyan Xu ziyan@securitygossip.com
commit 89bb430f621124af39bb31763c4a8b504c9651e2 upstream.
When ksmbd_conn_releasing(opinfo->conn) returns true,the refcount was not decremented properly, causing a refcount leak that prevents the count from reaching zero and the memory from being released.
Cc: stable@vger.kernel.org Signed-off-by: Ziyan Xu ziyan@securitygossip.com Signed-off-by: Namjae Jeon linkinjeon@kernel.org Signed-off-by: Steve French stfrench@microsoft.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- fs/smb/server/oplock.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-)
--- a/fs/smb/server/oplock.c +++ b/fs/smb/server/oplock.c @@ -1102,8 +1102,10 @@ void smb_send_parent_lease_break_noti(st if (!atomic_inc_not_zero(&opinfo->refcount)) continue;
- if (ksmbd_conn_releasing(opinfo->conn)) + if (ksmbd_conn_releasing(opinfo->conn)) { + opinfo_put(opinfo); continue; + }
oplock_break(opinfo, SMB2_OPLOCK_LEVEL_NONE, NULL); opinfo_put(opinfo); @@ -1139,8 +1141,11 @@ void smb_lazy_parent_lease_break_close(s if (!atomic_inc_not_zero(&opinfo->refcount)) continue;
- if (ksmbd_conn_releasing(opinfo->conn)) + if (ksmbd_conn_releasing(opinfo->conn)) { + opinfo_put(opinfo); continue; + } + oplock_break(opinfo, SMB2_OPLOCK_LEVEL_NONE, NULL); opinfo_put(opinfo); } @@ -1343,8 +1348,10 @@ void smb_break_all_levII_oplock(struct k if (!atomic_inc_not_zero(&brk_op->refcount)) continue;
- if (ksmbd_conn_releasing(brk_op->conn)) + if (ksmbd_conn_releasing(brk_op->conn)) { + opinfo_put(brk_op); continue; + }
if (brk_op->is_lease && (brk_op->o_lease->state & (~(SMB2_LEASE_READ_CACHING_LE |
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Namjae Jeon linkinjeon@kernel.org
commit c0d41112f1a5828c194b59cca953114bc3776ef2 upstream.
Update the connection tracking logic to handle both IPv4 and IPv6 address families.
Cc: stable@vger.kernel.org Fixes: e6bb91939740 ("ksmbd: limit repeated connections from clients with the same IP") Signed-off-by: Namjae Jeon linkinjeon@kernel.org Signed-off-by: Steve French stfrench@microsoft.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- fs/smb/server/connection.h | 7 ++++++- fs/smb/server/transport_tcp.c | 26 +++++++++++++++++++++++--- 2 files changed, 29 insertions(+), 4 deletions(-)
--- a/fs/smb/server/connection.h +++ b/fs/smb/server/connection.h @@ -46,7 +46,12 @@ struct ksmbd_conn { struct mutex srv_mutex; int status; unsigned int cli_cap; - __be32 inet_addr; + union { + __be32 inet_addr; +#if IS_ENABLED(CONFIG_IPV6) + u8 inet6_addr[16]; +#endif + }; char *request_buf; struct ksmbd_transport *transport; struct nls_table *local_nls; --- a/fs/smb/server/transport_tcp.c +++ b/fs/smb/server/transport_tcp.c @@ -87,7 +87,14 @@ static struct tcp_transport *alloc_trans return NULL; }
+#if IS_ENABLED(CONFIG_IPV6) + if (client_sk->sk->sk_family == AF_INET6) + memcpy(&conn->inet6_addr, &client_sk->sk->sk_v6_daddr, 16); + else + conn->inet_addr = inet_sk(client_sk->sk)->inet_daddr; +#else conn->inet_addr = inet_sk(client_sk->sk)->inet_daddr; +#endif conn->transport = KSMBD_TRANS(t); KSMBD_TRANS(t)->conn = conn; KSMBD_TRANS(t)->ops = &ksmbd_tcp_transport_ops; @@ -231,7 +238,6 @@ static int ksmbd_kthread_fn(void *p) { struct socket *client_sk = NULL; struct interface *iface = (struct interface *)p; - struct inet_sock *csk_inet; struct ksmbd_conn *conn; int ret;
@@ -254,13 +260,27 @@ static int ksmbd_kthread_fn(void *p) /* * Limits repeated connections from clients with the same IP. */ - csk_inet = inet_sk(client_sk->sk); down_read(&conn_list_lock); list_for_each_entry(conn, &conn_list, conns_list) - if (csk_inet->inet_daddr == conn->inet_addr) { +#if IS_ENABLED(CONFIG_IPV6) + if (client_sk->sk->sk_family == AF_INET6) { + if (memcmp(&client_sk->sk->sk_v6_daddr, + &conn->inet6_addr, 16) == 0) { + ret = -EAGAIN; + break; + } + } else if (inet_sk(client_sk->sk)->inet_daddr == + conn->inet_addr) { ret = -EAGAIN; break; } +#else + if (inet_sk(client_sk->sk)->inet_daddr == + conn->inet_addr) { + ret = -EAGAIN; + break; + } +#endif up_read(&conn_list_lock); if (ret == -EAGAIN) continue;
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Masami Hiramatsu (Google) mhiramat@kernel.org
commit ec879e1a0be8007aa232ffedcf6a6445dfc1a3d7 upstream.
Fprobe event accepts wildcards for the target functions, but unless user specifies its event name, it makes an event with the wildcards.
/sys/kernel/tracing # echo 'f mutex*' >> dynamic_events /sys/kernel/tracing # cat dynamic_events f:fprobes/mutex*__entry mutex* /sys/kernel/tracing # ls events/fprobes/ enable filter mutex*__entry
To fix this, replace the wildcard ('*') with an underscore.
Link: https://lore.kernel.org/all/175535345114.282990.12294108192847938710.stgit@d...
Fixes: 334e5519c375 ("tracing/probes: Add fprobe events for tracing function entry and exit.") Signed-off-by: Masami Hiramatsu (Google) mhiramat@kernel.org Cc: stable@vger.kernel.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- kernel/trace/trace.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
--- a/kernel/trace/trace.h +++ b/kernel/trace/trace.h @@ -2204,7 +2204,7 @@ static inline bool is_good_system_name(c static inline void sanitize_event_name(char *name) { while (*name++ != '\0') - if (*name == ':' || *name == '.') + if (*name == ':' || *name == '.' || *name == '*') *name = '_'; }
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Baokun Li libaokun1@huawei.com
commit f2326fd14a224e4cccbab89e14c52279ff79b7ec upstream.
IMA testing revealed that after an ext4 remount, file accesses triggered full measurements even without modifications, instead of skipping as expected when i_version is unchanged.
Debugging showed `SB_I_VERSION` was cleared in reconfigure_super() during remount due to commit 1ff20307393e ("ext4: unconditionally enable the i_version counter") removing the fix from commit 960e0ab63b2e ("ext4: fix i_version handling on remount").
To rectify this, `SB_I_VERSION` is always set for `fc->sb_flags` in ext4_init_fs_context(), instead of `sb->s_flags` in __ext4_fill_super(), ensuring it persists across all mounts.
Cc: stable@kernel.org Fixes: 1ff20307393e ("ext4: unconditionally enable the i_version counter") Signed-off-by: Baokun Li libaokun1@huawei.com Reviewed-by: Jan Kara jack@suse.cz Link: https://patch.msgid.link/20250703073903.6952-2-libaokun@huaweicloud.com Signed-off-by: Theodore Ts'o tytso@mit.edu Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- fs/ext4/super.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
--- a/fs/ext4/super.c +++ b/fs/ext4/super.c @@ -1998,6 +1998,9 @@ int ext4_init_fs_context(struct fs_conte fc->fs_private = ctx; fc->ops = &ext4_context_ops;
+ /* i_version is always enabled now */ + fc->sb_flags |= SB_I_VERSION; + return 0; }
@@ -5314,9 +5317,6 @@ static int __ext4_fill_super(struct fs_c sb->s_flags = (sb->s_flags & ~SB_POSIXACL) | (test_opt(sb, POSIX_ACL) ? SB_POSIXACL : 0);
- /* i_version is always enabled now */ - sb->s_flags |= SB_I_VERSION; - /* HSM events are allowed by default. */ sb->s_iflags |= SB_I_ALLOW_HSM;
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Andreas Dilger adilger@dilger.ca
commit b4cc4a4077268522e3d0d34de4b2dc144e2330fa upstream.
The check for a fast symlink in the presence of only an external xattr inode is incorrect. If a fast symlink does not have an xattr block (i_file_acl == 0), but does have an external xattr inode that increases inode i_blocks, then the check for a fast symlink will incorrectly fail and __ext4_iget()->ext4_ind_check_inode() will report the inode is corrupt when it "validates" i_data[] on the next read:
# ln -s foo /mnt/tmp/bar # setfattr -h -n trusted.test \ -v "$(yes | head -n 4000)" /mnt/tmp/bar # umount /mnt/tmp # mount /mnt/tmp # ls -l /mnt/tmp ls: cannot access '/mnt/tmp/bar': Structure needs cleaning total 4 ? l?????????? ? ? ? ? ? bar # dmesg | tail -1 EXT4-fs error (device dm-8): __ext4_iget:5098: inode #24578: block 7303014: comm ls: invalid block
(note that "block 7303014" = 0x6f6f66 = "foo" in LE order).
ext4_inode_is_fast_symlink() should check the superblock EXT4_FEATURE_INCOMPAT_EA_INODE feature flag, not the inode EXT4_EA_INODE_FL, since the latter is only set on the xattr inode itself, and not on the inode that uses this xattr.
Cc: stable@vger.kernel.org Fixes: fc82228a5e38 ("ext4: support fast symlinks from ext3 file systems") Signed-off-by: Andreas Dilger adilger@whamcloud.com Reviewed-by: Li Dongyang dongyangli@ddn.com Reviewed-by: Alex Zhuravlev bzzz@whamcloud.com Reviewed-by: Oleg Drokin green@whamcloud.com Reviewed-on: https://review.whamcloud.com/59879 Lustre-bug-id: https://jira.whamcloud.com/browse/LU-19121 Link: https://patch.msgid.link/20250717063709.757077-1-adilger@dilger.ca Signed-off-by: Theodore Ts'o tytso@mit.edu Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- fs/ext4/inode.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
--- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c @@ -146,7 +146,7 @@ static inline int ext4_begin_ordered_tru */ int ext4_inode_is_fast_symlink(struct inode *inode) { - if (!(EXT4_I(inode)->i_flags & EXT4_EA_INODE_FL)) { + if (!ext4_has_feature_ea_inode(inode->i_sb)) { int ea_blocks = EXT4_I(inode)->i_file_acl ? EXT4_CLUSTER_SIZE(inode->i_sb) >> 9 : 0;
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ojaswin Mujoo ojaswin@linux.ibm.com
commit bae76c035bf0852844151e68098c9b7cd63ef238 upstream.
With bigalloc enabled, the logic to report last extent has a bug since we try to use cluster units instead of block units. This can cause an issue where extra incorrect entries might be returned back to the user. This was flagged by generic/365 with 64k bs and -O bigalloc.
** Details of issue **
The issue was noticed on 5G 64k blocksize FS with -O bigalloc which has only 1 bg.
$ xfs_io -c "fsmap -d" /mnt/scratch
0: 253:48 [0..127]: static fs metadata 128 /* sb */ 1: 253:48 [128..255]: special 102:1 128 /* gdt */ 3: 253:48 [256..383]: special 102:3 128 /* block bitmap */ 4: 253:48 [384..2303]: unknown 1920 /* flex bg empty space */ 5: 253:48 [2304..2431]: special 102:4 128 /* inode bitmap */ 6: 253:48 [2432..4351]: unknown 1920 /* flex bg empty space */ 7: 253:48 [4352..6911]: inodes 2560 8: 253:48 [6912..538623]: unknown 531712 9: 253:48 [538624..10485759]: free space 9947136
The issue can be seen with:
$ xfs_io -c "fsmap -d 0 3" /mnt/scratch
0: 253:48 [0..127]: static fs metadata 128 1: 253:48 [384..2047]: unknown 1664
Only the first entry was expected to be returned but we get 2. This is because:
ext4_getfsmap_datadev() first_cluster, last_cluster = 0 ... info->gfi_last = true; ext4_getfsmap_datadev_helper(sb, end_ag, last_cluster + 1, 0, info); fsb = C2B(1) = 16 fslen = 0 ... /* Merge in any relevant extents from the meta_list */ list_for_each_entry_safe(p, tmp, &info->gfi_meta_list, fmr_list) { ... // since fsb = 16, considers all metadata which starts before 16 blockno iter 1: error = ext4_getfsmap_helper(sb, info, p); // p = sb (0,1), nop info->gfi_next_fsblk = 1 iter 2: error = ext4_getfsmap_helper(sb, info, p); // p = gdt (1,2), nop info->gfi_next_fsblk = 2 iter 3: error = ext4_getfsmap_helper(sb, info, p); // p = blk bitmap (2,3), nop info->gfi_next_fsblk = 3 iter 4: error = ext4_getfsmap_helper(sb, info, p); // p = ino bitmap (18,19) if (rec_blk > info->gfi_next_fsblk) { // (18 > 3) // emits an extra entry ** BUG ** } }
Fix this by directly calling ext4_getfsmap_datadev() with a dummy record that has fmr_physical set to (end_fsb + 1) instead of last_cluster + 1. By using the block instead of cluster we get the correct behavior.
Replacing ext4_getfsmap_datadev_helper() with ext4_getfsmap_helper() is okay since the gfi_lastfree and metadata checks in ext4_getfsmap_datadev_helper() are anyways redundant when we only want to emit the last allocated block of the range, as we have already taken care of emitting metadata and any last free blocks.
Cc: stable@kernel.org Reported-by: Disha Goel disgoel@linux.ibm.com Fixes: 4a622e4d477b ("ext4: fix FS_IOC_GETFSMAP handling") Signed-off-by: Ojaswin Mujoo ojaswin@linux.ibm.com Reviewed-by: Darrick J. Wong djwong@kernel.org Link: https://patch.msgid.link/e7472c8535c9c5ec10f425f495366864ea12c9da.1754377641... Signed-off-by: Theodore Ts'o tytso@mit.edu Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- fs/ext4/fsmap.c | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-)
--- a/fs/ext4/fsmap.c +++ b/fs/ext4/fsmap.c @@ -526,6 +526,7 @@ static int ext4_getfsmap_datadev(struct ext4_group_t end_ag; ext4_grpblk_t first_cluster; ext4_grpblk_t last_cluster; + struct ext4_fsmap irec; int error = 0;
bofs = le32_to_cpu(sbi->s_es->s_first_data_block); @@ -609,10 +610,18 @@ static int ext4_getfsmap_datadev(struct goto err; }
- /* Report any gaps at the end of the bg */ + /* + * The dummy record below will cause ext4_getfsmap_helper() to report + * any allocated blocks at the end of the range. + */ + irec.fmr_device = 0; + irec.fmr_physical = end_fsb + 1; + irec.fmr_length = 0; + irec.fmr_owner = EXT4_FMR_OWN_FREE; + irec.fmr_flags = 0; + info->gfi_last = true; - error = ext4_getfsmap_datadev_helper(sb, end_ag, last_cluster + 1, - 0, info); + error = ext4_getfsmap_helper(sb, info, &irec); if (error) goto err;
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ojaswin Mujoo ojaswin@linux.ibm.com
commit 3ffbdd1f1165f1b2d6a94d1b1aabef57120deaf7 upstream.
In some cases like small FSes with no meta_bg and where the resize doesn't need extra gdt blocks as it can fit in the current one, s_reserved_gdt_blocks is set as 0, which causes fsmap to emit a 0 length entry, which is incorrect.
$ mkfs.ext4 -b 65536 -O bigalloc /dev/sda 5G $ mount /dev/sda /mnt/scratch $ xfs_io -c "fsmap -d" /mnt/scartch
0: 253:48 [0..127]: static fs metadata 128 1: 253:48 [128..255]: special 102:1 128 2: 253:48 [256..255]: special 102:2 0 <---- 0 len entry 3: 253:48 [256..383]: special 102:3 128
Fix this by adding a check for this case.
Cc: stable@kernel.org Fixes: 0c9ec4beecac ("ext4: support GETFSMAP ioctls") Signed-off-by: Ojaswin Mujoo ojaswin@linux.ibm.com Reviewed-by: Darrick J. Wong djwong@kernel.org Link: https://patch.msgid.link/08781b796453a5770112aa96ad14c864fbf31935.1754377641... Signed-off-by: Theodore Ts'o tytso@mit.edu Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- fs/ext4/fsmap.c | 8 ++++++++ 1 file changed, 8 insertions(+)
--- a/fs/ext4/fsmap.c +++ b/fs/ext4/fsmap.c @@ -393,6 +393,14 @@ static unsigned int ext4_getfsmap_find_s /* Reserved GDT blocks */ if (!ext4_has_feature_meta_bg(sb) || metagroup < first_meta_bg) { len = le16_to_cpu(sbi->s_es->s_reserved_gdt_blocks); + + /* + * mkfs.ext4 can set s_reserved_gdt_blocks as 0 in some cases, + * check for that. + */ + if (!len) + return 0; + error = ext4_getfsmap_fill(meta_list, fsb, len, EXT4_FMR_OWN_RESV_GDT); if (error)
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Theodore Ts'o tytso@mit.edu
commit c5e104a91e7b6fa12c1dc2d8bf84abb7ef9b89ad upstream.
When the file system is frozen in preparation for taking an LVM snapshot, the journal is checkpointed and if the orphan_file feature is enabled, and the orphan file is empty, we clear the orphan_present feature flag. But if there are pending inodes that need to be removed the orphan_present feature flag can't be cleared.
The problem comes if the block device is read-only. In that case, we can't process the orphan inode list, so it is skipped in ext4_orphan_cleanup(). But then in ext4_mark_recovery_complete(), this results in the ext4 error "Orphan file not empty on read-only fs" firing and the file system mount is aborted.
Fix this by clearing the needs_recovery flag in the block device is read-only. We do this after the call to ext4_load_and_init-journal() since there are some error checks need to be done in case the journal needs to be replayed and the block device is read-only, or if the block device containing the externa journal is read-only, etc.
Cc: stable@kernel.org Link: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=1108271 Cc: stable@vger.kernel.org Fixes: 02f310fcf47f ("ext4: Speedup ext4 orphan inode handling") Signed-off-by: Theodore Ts'o tytso@mit.edu Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- fs/ext4/super.c | 2 ++ 1 file changed, 2 insertions(+)
--- a/fs/ext4/super.c +++ b/fs/ext4/super.c @@ -5414,6 +5414,8 @@ static int __ext4_fill_super(struct fs_c err = ext4_load_and_init_journal(sb, es, ctx); if (err) goto failed_mount3a; + if (bdev_read_only(sb->s_bdev)) + needs_recovery = 0; } else if (test_opt(sb, NOLOAD) && !sb_rdonly(sb) && ext4_has_feature_journal_needs_recovery(sb)) { ext4_msg(sb, KERN_ERR, "required journal recovery "
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Liao Yuanhong liaoyuanhong@vivo.com
commit 76dba1fe277f6befd6ef650e1946f626c547387a upstream.
Replace kmalloc(size * sizeof) with kmalloc_array() for safer memory allocation and overflow prevention.
Cc: stable@kernel.org Signed-off-by: Liao Yuanhong liaoyuanhong@vivo.com Link: https://patch.msgid.link/20250811125816.570142-1-liaoyuanhong@vivo.com Signed-off-by: Theodore Ts'o tytso@mit.edu Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- fs/ext4/orphan.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-)
--- a/fs/ext4/orphan.c +++ b/fs/ext4/orphan.c @@ -589,8 +589,9 @@ int ext4_init_orphan_info(struct super_b } oi->of_blocks = inode->i_size >> sb->s_blocksize_bits; oi->of_csum_seed = EXT4_I(inode)->i_csum_seed; - oi->of_binfo = kmalloc(oi->of_blocks*sizeof(struct ext4_orphan_block), - GFP_KERNEL); + oi->of_binfo = kmalloc_array(oi->of_blocks, + sizeof(struct ext4_orphan_block), + GFP_KERNEL); if (!oi->of_binfo) { ret = -ENOMEM; goto out_put;
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Zhang Yi yi.zhang@huawei.com
commit 02c7f7219ac0e2277b3379a3a0e9841ef464b6d4 upstream.
In a filesystem with a block size larger than 4KB, the hole length calculation for a non-extent inode in ext4_ind_map_blocks() can easily exceed INT_MAX. Then it could return a zero length hole and trigger the following waring and infinite in the iomap infrastructure.
------------[ cut here ]------------ WARNING: CPU: 3 PID: 434101 at fs/iomap/iter.c:34 iomap_iter_done+0x148/0x190 CPU: 3 UID: 0 PID: 434101 Comm: fsstress Not tainted 6.16.0-rc7+ #128 PREEMPT(voluntary) Hardware name: QEMU KVM Virtual Machine, BIOS unknown 2/2/2022 pstate: 60400005 (nZCv daif +PAN -UAO -TCO -DIT -SSBS BTYPE=--) pc : iomap_iter_done+0x148/0x190 lr : iomap_iter+0x174/0x230 sp : ffff8000880af740 x29: ffff8000880af740 x28: ffff0000db8e6840 x27: 0000000000000000 x26: 0000000000000000 x25: ffff8000880af830 x24: 0000004000000000 x23: 0000000000000002 x22: 000001bfdbfa8000 x21: ffffa6a41c002e48 x20: 0000000000000001 x19: ffff8000880af808 x18: 0000000000000000 x17: 0000000000000000 x16: ffffa6a495ee6cd0 x15: 0000000000000000 x14: 00000000000003d4 x13: 00000000fa83b2da x12: 0000b236fc95f18c x11: ffffa6a4978b9c08 x10: 0000000000001da0 x9 : ffffa6a41c1a2a44 x8 : ffff8000880af5c8 x7 : 0000000001000000 x6 : 0000000000000000 x5 : 0000000000000004 x4 : 000001bfdbfa8000 x3 : 0000000000000000 x2 : 0000000000000000 x1 : 0000004004030000 x0 : 0000000000000000 Call trace: iomap_iter_done+0x148/0x190 (P) iomap_iter+0x174/0x230 iomap_fiemap+0x154/0x1d8 ext4_fiemap+0x110/0x140 [ext4] do_vfs_ioctl+0x4b8/0xbc0 __arm64_sys_ioctl+0x8c/0x120 invoke_syscall+0x6c/0x100 el0_svc_common.constprop.0+0x48/0xf0 do_el0_svc+0x24/0x38 el0_svc+0x38/0x120 el0t_64_sync_handler+0x10c/0x138 el0t_64_sync+0x198/0x1a0 ---[ end trace 0000000000000000 ]---
Cc: stable@kernel.org Fixes: facab4d9711e ("ext4: return hole from ext4_map_blocks()") Reported-by: Qu Wenruo wqu@suse.com Closes: https://lore.kernel.org/linux-ext4/9b650a52-9672-4604-a765-bb6be55d1e4a@gmx.... Tested-by: Qu Wenruo wqu@suse.com Signed-off-by: Zhang Yi yi.zhang@huawei.com Link: https://patch.msgid.link/20250811064532.1788289-1-yi.zhang@huaweicloud.com Signed-off-by: Theodore Ts'o tytso@mit.edu Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- fs/ext4/indirect.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
--- a/fs/ext4/indirect.c +++ b/fs/ext4/indirect.c @@ -539,7 +539,7 @@ int ext4_ind_map_blocks(handle_t *handle int indirect_blks; int blocks_to_boundary = 0; int depth; - int count = 0; + u64 count = 0; ext4_fsblk_t first_block = 0;
trace_ext4_ind_map_blocks_enter(inode, map->m_lblk, map->m_len, flags); @@ -588,7 +588,7 @@ int ext4_ind_map_blocks(handle_t *handle count++; /* Fill in size of a hole we found */ map->m_pblk = 0; - map->m_len = min_t(unsigned int, map->m_len, count); + map->m_len = umin(map->m_len, count); goto cleanup; }
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Naohiro Aota naohiro.aota@wdc.com
commit 5c4b93f4c8e5c53574c1a48d66a27a2c68b414af upstream.
Since commit 13bb483d32ab ("btrfs: zoned: activate metadata block group on write time"), we activate a metadata block group at the write time. If the zone capacity is small enough, we can allocate the entire region before the first write. Then, we hit the btrfs_zoned_bg_is_full() in btrfs_zone_activate() and the activation fails.
For a data block group, we activate it at the allocation time and we should check the fullness condition in the caller side. Add, a WARN to check the fullness condition.
For a metadata block group, we don't need the fullness check because we activate it at the write time. Instead, activating it once it is written should be invalid. Catch that with a WARN too.
Fixes: 13bb483d32ab ("btrfs: zoned: activate metadata block group on write time") CC: stable@vger.kernel.org # 6.6+ Reviewed-by: Johannes Thumshirn johannes.thumshirn@wdc.com Signed-off-by: Naohiro Aota naohiro.aota@wdc.com Signed-off-by: David Sterba dsterba@suse.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- fs/btrfs/zoned.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-)
--- a/fs/btrfs/zoned.c +++ b/fs/btrfs/zoned.c @@ -2169,10 +2169,15 @@ bool btrfs_zone_activate(struct btrfs_bl goto out_unlock; }
- /* No space left */ - if (btrfs_zoned_bg_is_full(block_group)) { - ret = false; - goto out_unlock; + if (block_group->flags & BTRFS_BLOCK_GROUP_DATA) { + /* The caller should check if the block group is full. */ + if (WARN_ON_ONCE(btrfs_zoned_bg_is_full(block_group))) { + ret = false; + goto out_unlock; + } + } else { + /* Since it is already written, it should have been active. */ + WARN_ON_ONCE(block_group->meta_write_pointer != block_group->start); }
for (i = 0; i < map->num_stripes; i++) {
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Kyoji Ogasawara sawara04.o@gmail.com
commit edf842abe4368ce3c423343cf4b23b210fcf1622 upstream.
Fix a wrong log message that appears when the "nobarrier" mount option is unset. When "nobarrier" is unset, barrier is actually enabled. However, the log incorrectly stated "turning off barriers".
Fixes: eddb1a433f26 ("btrfs: add reconfigure callback for fs_context") CC: stable@vger.kernel.org # 6.12+ Reviewed-by: Qu Wenruo wqu@suse.com Signed-off-by: Kyoji Ogasawara sawara04.o@gmail.com Reviewed-by: David Sterba dsterba@suse.com Signed-off-by: David Sterba dsterba@suse.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- fs/btrfs/super.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
--- a/fs/btrfs/super.c +++ b/fs/btrfs/super.c @@ -1453,7 +1453,7 @@ static void btrfs_emit_options(struct bt btrfs_info_if_unset(info, old, NODATACOW, "setting datacow"); btrfs_info_if_unset(info, old, SSD, "not using ssd optimizations"); btrfs_info_if_unset(info, old, SSD_SPREAD, "not using spread ssd allocation scheme"); - btrfs_info_if_unset(info, old, NOBARRIER, "turning off barriers"); + btrfs_info_if_unset(info, old, NOBARRIER, "turning on barriers"); btrfs_info_if_unset(info, old, NOTREELOG, "enabling tree log"); btrfs_info_if_unset(info, old, SPACE_CACHE, "disabling disk space caching"); btrfs_info_if_unset(info, old, FREE_SPACE_TREE, "disabling free space tree");
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Kyoji Ogasawara sawara04.o@gmail.com
commit b435ab556bea875c088485f271ef2709ca1d75f5 upstream.
After the fsconfig migration in 6.8, mount option info messages are no longer displayed during mount operations because btrfs_emit_options() is only called during remount, not during initial mount.
Fix this by calling btrfs_emit_options() in btrfs_fill_super() after open_ctree() succeeds. Additionally, prevent log duplication by ensuring btrfs_check_options() handles validation with warn-level and err-level messages, while btrfs_emit_options() provides info-level messages.
Fixes: eddb1a433f26 ("btrfs: add reconfigure callback for fs_context") CC: stable@vger.kernel.org # 6.8+ Reviewed-by: Qu Wenruo wqu@suse.com Signed-off-by: Kyoji Ogasawara sawara04.o@gmail.com Reviewed-by: David Sterba dsterba@suse.com Signed-off-by: David Sterba dsterba@suse.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- fs/btrfs/super.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-)
--- a/fs/btrfs/super.c +++ b/fs/btrfs/super.c @@ -88,6 +88,9 @@ struct btrfs_fs_context { refcount_t refs; };
+static void btrfs_emit_options(struct btrfs_fs_info *info, + struct btrfs_fs_context *old); + enum { Opt_acl, Opt_clear_cache, @@ -689,12 +692,9 @@ bool btrfs_check_options(const struct bt
if (!test_bit(BTRFS_FS_STATE_REMOUNTING, &info->fs_state)) { if (btrfs_raw_test_opt(*mount_opt, SPACE_CACHE)) { - btrfs_info(info, "disk space caching is enabled"); btrfs_warn(info, "space cache v1 is being deprecated and will be removed in a future release, please use -o space_cache=v2"); } - if (btrfs_raw_test_opt(*mount_opt, FREE_SPACE_TREE)) - btrfs_info(info, "using free-space-tree"); }
return ret; @@ -971,6 +971,8 @@ static int btrfs_fill_super(struct super return err; }
+ btrfs_emit_options(fs_info, NULL); + inode = btrfs_iget(BTRFS_FIRST_FREE_OBJECTID, fs_info->fs_root); if (IS_ERR(inode)) { err = PTR_ERR(inode);
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Kyoji Ogasawara sawara04.o@gmail.com
commit 74857fdc5dd2cdcdeb6e99bdf26976fd9299d2bb upstream.
The NODATASUM message was printed twice by mistake and the NODATACOW was missing from the 'unset' part. Fix the duplication and make the output look the same.
Fixes: eddb1a433f26 ("btrfs: add reconfigure callback for fs_context") CC: stable@vger.kernel.org # 6.8+ Reviewed-by: Qu Wenruo wqu@suse.com Signed-off-by: Kyoji Ogasawara sawara04.o@gmail.com Reviewed-by: David Sterba dsterba@suse.com Signed-off-by: David Sterba dsterba@suse.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- fs/btrfs/super.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
--- a/fs/btrfs/super.c +++ b/fs/btrfs/super.c @@ -1430,7 +1430,7 @@ static void btrfs_emit_options(struct bt { btrfs_info_if_set(info, old, NODATASUM, "setting nodatasum"); btrfs_info_if_set(info, old, DEGRADED, "allowing degraded mounts"); - btrfs_info_if_set(info, old, NODATASUM, "setting nodatasum"); + btrfs_info_if_set(info, old, NODATACOW, "setting nodatacow"); btrfs_info_if_set(info, old, SSD, "enabling ssd optimizations"); btrfs_info_if_set(info, old, SSD_SPREAD, "using spread ssd allocation scheme"); btrfs_info_if_set(info, old, NOBARRIER, "turning off barriers"); @@ -1452,6 +1452,7 @@ static void btrfs_emit_options(struct bt btrfs_info_if_set(info, old, IGNOREMETACSUMS, "ignoring meta csums"); btrfs_info_if_set(info, old, IGNORESUPERFLAGS, "ignoring unknown super block flags");
+ btrfs_info_if_unset(info, old, NODATASUM, "setting datasum"); btrfs_info_if_unset(info, old, NODATACOW, "setting datacow"); btrfs_info_if_unset(info, old, SSD, "not using ssd optimizations"); btrfs_info_if_unset(info, old, SSD_SPREAD, "not using spread ssd allocation scheme");
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Nick Chan towinchenmi@gmail.com
commit ef68a0e1087882850628000f28078e1c4df917ee upstream.
Apple T2 MacBookPro15,2 (j132) has a touchbar so include the framebuffer node.
Cc: stable@vger.kernel.org Fixes: 4efbcb623e9bc ("arm64: dts: apple: Add T2 devices") Signed-off-by: Nick Chan towinchenmi@gmail.com Link: https://lore.kernel.org/stable/20250620-j132-fb-v1-1-bc6937baf0b9%40gmail.co... Link: https://lore.kernel.org/r/20250620-j132-fb-v2-1-65f100182085@gmail.com Signed-off-by: Sven Peter sven@kernel.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- arch/arm64/boot/dts/apple/t8012-j132.dts | 1 + 1 file changed, 1 insertion(+)
diff --git a/arch/arm64/boot/dts/apple/t8012-j132.dts b/arch/arm64/boot/dts/apple/t8012-j132.dts index 778a69be18dd..7dcac51703ff 100644 --- a/arch/arm64/boot/dts/apple/t8012-j132.dts +++ b/arch/arm64/boot/dts/apple/t8012-j132.dts @@ -7,6 +7,7 @@ /dts-v1/;
#include "t8012-jxxx.dtsi" +#include "t8012-touchbar.dtsi"
/ { model = "Apple T2 MacBookPro15,2 (j132)";
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Judith Mendez jm@ti.com
commit 265f70af805f33a0dfc90f50cc0f116f702c3811 upstream.
For eMMC, High Speed DDR mode is not supported [0], so remove mmc-ddr-1_8v flag which adds the capability.
[0] https://www.ti.com/lit/gpn/am625
Fixes: c37c58fdeb8a ("arm64: dts: ti: k3-am62: Add more peripheral nodes") Cc: stable@vger.kernel.org Signed-off-by: Judith Mendez jm@ti.com Link: https://lore.kernel.org/r/20250707191250.3953990-1-jm@ti.com Signed-off-by: Vignesh Raghavendra vigneshr@ti.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- arch/arm64/boot/dts/ti/k3-am62-main.dtsi | 1 - 1 file changed, 1 deletion(-)
--- a/arch/arm64/boot/dts/ti/k3-am62-main.dtsi +++ b/arch/arm64/boot/dts/ti/k3-am62-main.dtsi @@ -553,7 +553,6 @@ clocks = <&k3_clks 57 5>, <&k3_clks 57 6>; clock-names = "clk_ahb", "clk_xin"; bus-width = <8>; - mmc-ddr-1_8v; mmc-hs200-1_8v; ti,clkbuf-sel = <0x7>; ti,otap-del-sel-legacy = <0x0>;
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Kaustabh Chakraborty kauschluss@disroot.org
commit 49a27c6c392dec46c826ee586f7ec8973acaeed7 upstream.
The device is available in multiple variants with differing RAM capacities. The memory range defined in the 0x80000000 bank exceeds the address range of the memory controller, which eventually leads to ARM SError crashes. Reduce the bank size to a value which is available to all devices.
The bootloader must be responsible for identifying the RAM capacity and editing the memory node accordingly.
Fixes: d6f3a7f91fdb ("arm64: dts: exynos: add initial devicetree support for exynos7870") Cc: stable@vger.kernel.org # v6.16 Signed-off-by: Kaustabh Chakraborty kauschluss@disroot.org Link: https://lore.kernel.org/r/20250626-exynos7870-dts-fixes-v1-3-349987874d9a@di... Signed-off-by: Krzysztof Kozlowski krzysztof.kozlowski@linaro.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- arch/arm64/boot/dts/exynos/exynos7870-j6lte.dts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/arch/arm64/boot/dts/exynos/exynos7870-j6lte.dts b/arch/arm64/boot/dts/exynos/exynos7870-j6lte.dts index 61eec1aff32e..b8ce433b93b1 100644 --- a/arch/arm64/boot/dts/exynos/exynos7870-j6lte.dts +++ b/arch/arm64/boot/dts/exynos/exynos7870-j6lte.dts @@ -89,7 +89,7 @@ memory@40000000 { device_type = "memory"; reg = <0x0 0x40000000 0x3d800000>, - <0x0 0x80000000 0x7d800000>; + <0x0 0x80000000 0x40000000>; };
pwrseq_mmc1: pwrseq-mmc1 {
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Alexander Sverdlin alexander.sverdlin@siemens.com
commit 5b272127884bded21576a6ddceca13725a351c63 upstream.
Switch Schmitt Trigger functions for PIN_INPUT* macros by default. This is HW PoR configuration, the slew rate requirements without ST enabled are pretty tough for these devices. We've noticed spurious GPIO interrupts even with noise-free edges but not meeting slew rate requirements (3.3E+6 V/s for 3.3v LVCMOS).
It's not obvious why one might want to disable the PoR-enabled ST on any pin. Just enable it by default. As it's not possible to provide OR-able macros to disable the ST, shall anyone require it, provide a set of new macros with _NOST suffix.
Fixes: fe49f2d776f7 ("arm64: dts: ti: Use local header for pinctrl register values") Cc: stable@vger.kernel.org Signed-off-by: Alexander Sverdlin alexander.sverdlin@siemens.com Link: https://lore.kernel.org/r/20250701105437.3539924-1-alexander.sverdlin@siemen... [vigneshr@ti.com: Add Fixes tag] Signed-off-by: Vignesh Raghavendra vigneshr@ti.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- arch/arm64/boot/dts/ti/k3-pinctrl.h | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-)
--- a/arch/arm64/boot/dts/ti/k3-pinctrl.h +++ b/arch/arm64/boot/dts/ti/k3-pinctrl.h @@ -8,6 +8,7 @@ #ifndef DTS_ARM64_TI_K3_PINCTRL_H #define DTS_ARM64_TI_K3_PINCTRL_H
+#define ST_EN_SHIFT (14) #define PULLUDEN_SHIFT (16) #define PULLTYPESEL_SHIFT (17) #define RXACTIVE_SHIFT (18) @@ -19,6 +20,10 @@ #define DS_PULLUD_EN_SHIFT (27) #define DS_PULLTYPE_SEL_SHIFT (28)
+/* Schmitt trigger configuration */ +#define ST_DISABLE (0 << ST_EN_SHIFT) +#define ST_ENABLE (1 << ST_EN_SHIFT) + #define PULL_DISABLE (1 << PULLUDEN_SHIFT) #define PULL_ENABLE (0 << PULLUDEN_SHIFT)
@@ -32,9 +37,13 @@ #define PIN_OUTPUT (INPUT_DISABLE | PULL_DISABLE) #define PIN_OUTPUT_PULLUP (INPUT_DISABLE | PULL_UP) #define PIN_OUTPUT_PULLDOWN (INPUT_DISABLE | PULL_DOWN) -#define PIN_INPUT (INPUT_EN | PULL_DISABLE) -#define PIN_INPUT_PULLUP (INPUT_EN | PULL_UP) -#define PIN_INPUT_PULLDOWN (INPUT_EN | PULL_DOWN) +#define PIN_INPUT (INPUT_EN | ST_ENABLE | PULL_DISABLE) +#define PIN_INPUT_PULLUP (INPUT_EN | ST_ENABLE | PULL_UP) +#define PIN_INPUT_PULLDOWN (INPUT_EN | ST_ENABLE | PULL_DOWN) +/* Input configurations with Schmitt Trigger disabled */ +#define PIN_INPUT_NOST (INPUT_EN | PULL_DISABLE) +#define PIN_INPUT_PULLUP_NOST (INPUT_EN | PULL_UP) +#define PIN_INPUT_PULLDOWN_NOST (INPUT_EN | PULL_DOWN)
#define PIN_DEBOUNCE_DISABLE (0 << DEBOUNCE_SHIFT) #define PIN_DEBOUNCE_CONF1 (1 << DEBOUNCE_SHIFT)
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Kaustabh Chakraborty kauschluss@disroot.org
commit e9355e894aebcbeacffd284644749190cc5f33a4 upstream.
In gadget mode, USB connections are sluggish. The device won't send packets to the host unless the host sends packets to the device. For instance, SSH-ing through the USB network would apparently not work unless you're flood-pinging the device's IP.
Add the property snps,usb2-gadget-lpm-disable to the dwc3 node, which seems to solve this issue.
Fixes: d6f3a7f91fdb ("arm64: dts: exynos: add initial devicetree support for exynos7870") Cc: stable@vger.kernel.org # v6.16 Signed-off-by: Kaustabh Chakraborty kauschluss@disroot.org Link: https://lore.kernel.org/r/20250626-exynos7870-dts-fixes-v1-1-349987874d9a@di... Signed-off-by: Krzysztof Kozlowski krzysztof.kozlowski@linaro.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- arch/arm64/boot/dts/exynos/exynos7870.dtsi | 1 + 1 file changed, 1 insertion(+)
diff --git a/arch/arm64/boot/dts/exynos/exynos7870.dtsi b/arch/arm64/boot/dts/exynos/exynos7870.dtsi index 5cba8c9bb403..d5d347623b90 100644 --- a/arch/arm64/boot/dts/exynos/exynos7870.dtsi +++ b/arch/arm64/boot/dts/exynos/exynos7870.dtsi @@ -327,6 +327,7 @@ phys = <&usbdrd_phy 0>;
usb-role-switch; + snps,usb2-gadget-lpm-disable; }; };
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Cristian Ciocaltea cristian.ciocaltea@collabora.com
commit 4ab8b8ac952fb08d03655e1da0cfee07589e428f upstream.
Since commit c871a311edf0 ("phy: rockchip: samsung-hdptx: Setup TMDS char rate via phy_configure_opts_hdmi"), the workaround of passing the rate from DW HDMI QP bridge driver via phy_set_bus_width() became partially broken, as it cannot reliably handle mode switches anymore.
Attempting to fix this up at PHY level would not only introduce additional hacks, but it would also fail to adequately resolve the display issues that are a consequence of the system CRU limitations.
Instead, proceed with the solution already implemented for RK3588: make use of the HDMI PHY PLL as a better suited DCLK source for VOP2. This will not only address the aforementioned problem, but it should also facilitate the proper operation of display modes up to 4K@60Hz.
It's worth noting that anything above 4K@30Hz still requires high TMDS clock ratio and scrambling support, which hasn't been mainlined yet.
Fixes: d74b842cab08 ("arm64: dts: rockchip: Add vop for rk3576") Cc: stable@vger.kernel.org Signed-off-by: Cristian Ciocaltea cristian.ciocaltea@collabora.com Tested-By: Detlev Casanova detlev.casanova@collabora.com Tested-by: Nicolas Frattaroli nicolas.frattaroli@collabora.com Link: https://lore.kernel.org/r/20250612-rk3576-hdmitx-fix-v1-3-4b11007d8675@colla... Signed-off-by: Heiko Stuebner heiko@sntech.de Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- arch/arm64/boot/dts/rockchip/rk3576.dtsi | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/arch/arm64/boot/dts/rockchip/rk3576.dtsi b/arch/arm64/boot/dts/rockchip/rk3576.dtsi index 9fc18384f609..1fec0ecea91d 100644 --- a/arch/arm64/boot/dts/rockchip/rk3576.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3576.dtsi @@ -1155,12 +1155,14 @@ <&cru HCLK_VOP>, <&cru DCLK_VP0>, <&cru DCLK_VP1>, - <&cru DCLK_VP2>; + <&cru DCLK_VP2>, + <&hdptxphy>; clock-names = "aclk", "hclk", "dclk_vp0", "dclk_vp1", - "dclk_vp2"; + "dclk_vp2", + "pll_hdmiphy0"; iommus = <&vop_mmu>; power-domains = <&power RK3576_PD_VOP>; rockchip,grf = <&sys_grf>;
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Cristian Ciocaltea cristian.ciocaltea@collabora.com
commit aba7987a536cee67fb0cb724099096fd8f8f5350 upstream.
As with the RK3588 SoC, the HDMI PHY PLL on RK3576 can be used as a more accurate pixel clock source for VOP2, which is actually mandatory to ensure proper support for display modes handling.
Add the missing #clock-cells property to allow using the clock provider functionality of HDMI PHY.
Fixes: ad0ea230ab2a ("arm64: dts: rockchip: Add hdmi for rk3576") Cc: stable@vger.kernel.org Signed-off-by: Cristian Ciocaltea cristian.ciocaltea@collabora.com Tested-by: Nicolas Frattaroli nicolas.frattaroli@collabora.com Link: https://lore.kernel.org/r/20250612-rk3576-hdmitx-fix-v1-2-4b11007d8675@colla... Signed-off-by: Heiko Stuebner heiko@sntech.de Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- arch/arm64/boot/dts/rockchip/rk3576.dtsi | 1 + 1 file changed, 1 insertion(+)
--- a/arch/arm64/boot/dts/rockchip/rk3576.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3576.dtsi @@ -2393,6 +2393,7 @@ reg = <0x0 0x2b000000 0x0 0x2000>; clocks = <&cru CLK_PHY_REF_SRC>, <&cru PCLK_HDPTX_APB>; clock-names = "ref", "apb"; + #clock-cells = <0>; resets = <&cru SRST_P_HDPTX_APB>, <&cru SRST_HDPTX_INIT>, <&cru SRST_HDPTX_CMN>, <&cru SRST_HDPTX_LANE>; reset-names = "apb", "init", "cmn", "lane";
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Peter Griffin peter.griffin@linaro.org
commit 4292564c71cffd8094abcc52dd4840870d05cd30 upstream.
ufs-exynos driver configures the sysreg shareability as cacheable for gs101 so we need to set the dma-coherent property so the descriptors are also allocated cacheable.
This fixes the UFS stability issues we have seen with the upstream UFS driver on gs101.
Fixes: 4c65d7054b4c ("arm64: dts: exynos: gs101: Add ufs and ufs-phy dt nodes") Cc: stable@vger.kernel.org Suggested-by: Will McVicker willmcvicker@google.com Signed-off-by: Peter Griffin peter.griffin@linaro.org Tested-by: Will McVicker willmcvicker@google.com Tested-by: André Draszik andre.draszik@linaro.org Reviewed-by: André Draszik andre.draszik@linaro.org Link: https://lore.kernel.org/r/20250314-ufs-dma-coherent-v1-1-bdf9f9be2919@linaro... Signed-off-by: Krzysztof Kozlowski krzysztof.kozlowski@linaro.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- arch/arm64/boot/dts/exynos/google/gs101.dtsi | 1 + 1 file changed, 1 insertion(+)
--- a/arch/arm64/boot/dts/exynos/google/gs101.dtsi +++ b/arch/arm64/boot/dts/exynos/google/gs101.dtsi @@ -1371,6 +1371,7 @@ <&cmu_hsi2 CLK_GOUT_HSI2_SYSREG_HSI2_PCLK>; clock-names = "core_clk", "sclk_unipro_main", "fmp", "aclk", "pclk", "sysreg"; + dma-coherent; freq-table-hz = <0 0>, <0 0>, <0 0>, <0 0>, <0 0>, <0 0>; pinctrl-0 = <&ufs_rst_n &ufs_refclk_out>; pinctrl-names = "default";
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Hong Guan hguan@ti.com
commit 8e44ac61abaae56fc6eb537a04ed78b458c5b984 upstream.
main_uart1 reserved for TIFS firmware traces is routed to the onboard FT4232 via a FET switch which is connected to pin A21 and B21 of the SoC and not E17 and C17. Fix it.
Fixes: cf39ff15cc01a ("arm64: dts: ti: k3-am62a7-sk: Describe main_uart1 and wkup_uart") Cc: stable@vger.kernel.org Signed-off-by: Hong Guan hguan@ti.com [bb@ti.com: expanded commit message] Signed-off-by: Bryan Brattlof bb@ti.com Link: https://lore.kernel.org/r/20250707-uart-fixes-v1-1-8164147218b0@ti.com Signed-off-by: Vignesh Raghavendra vigneshr@ti.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- arch/arm64/boot/dts/ti/k3-am62a7-sk.dts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
--- a/arch/arm64/boot/dts/ti/k3-am62a7-sk.dts +++ b/arch/arm64/boot/dts/ti/k3-am62a7-sk.dts @@ -301,8 +301,8 @@
main_uart1_pins_default: main-uart1-default-pins { pinctrl-single,pins = < - AM62AX_IOPAD(0x01e8, PIN_INPUT, 1) /* (C17) I2C1_SCL.UART1_RXD */ - AM62AX_IOPAD(0x01ec, PIN_OUTPUT, 1) /* (E17) I2C1_SDA.UART1_TXD */ + AM62AX_IOPAD(0x01ac, PIN_INPUT, 2) /* (B21) MCASP0_AFSR.UART1_RXD */ + AM62AX_IOPAD(0x01b0, PIN_OUTPUT, 2) /* (A21) MCASP0_ACLKR.UART1_TXD */ AM62AX_IOPAD(0x0194, PIN_INPUT, 2) /* (C19) MCASP0_AXR3.UART1_CTSn */ AM62AX_IOPAD(0x0198, PIN_OUTPUT, 2) /* (B19) MCASP0_AXR2.UART1_RTSn */ >;
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Judith Mendez jm@ti.com
commit a0b8da04153eb61cc2eaeeea5cc404e91e557f6b upstream.
This moves pinmux child nodes for sdhci0 node from k3-am62x-sk-common to each top level board file. This is needed since we require internal pullups for AM62x SK and not for AM62 LP SK since it has external pullups on DATA 1-7.
Internal pulls are required for AM62 SK as per JESD84 spec recommendation to prevent unconnected lines floating.
Fixes: d19a66ae488a ("arm64: dts: ti: k3-am625-sk: Enable on board peripherals") Cc: stable@vger.kernel.org Signed-off-by: Judith Mendez jm@ti.com Link: https://lore.kernel.org/r/20250707190830.3951619-1-jm@ti.com Signed-off-by: Vignesh Raghavendra vigneshr@ti.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- arch/arm64/boot/dts/ti/k3-am62-lp-sk.dts | 24 ++++++++++++++++++++++++ arch/arm64/boot/dts/ti/k3-am625-sk.dts | 24 ++++++++++++++++++++++++ arch/arm64/boot/dts/ti/k3-am62x-sk-common.dtsi | 24 ------------------------ 3 files changed, 48 insertions(+), 24 deletions(-)
--- a/arch/arm64/boot/dts/ti/k3-am62-lp-sk.dts +++ b/arch/arm64/boot/dts/ti/k3-am62-lp-sk.dts @@ -74,6 +74,22 @@ };
&main_pmx0 { + main_mmc0_pins_default: main-mmc0-default-pins { + bootph-all; + pinctrl-single,pins = < + AM62X_IOPAD(0x220, PIN_INPUT, 0) /* (V3) MMC0_CMD */ + AM62X_IOPAD(0x218, PIN_INPUT, 0) /* (Y1) MMC0_CLK */ + AM62X_IOPAD(0x214, PIN_INPUT, 0) /* (V2) MMC0_DAT0 */ + AM62X_IOPAD(0x210, PIN_INPUT, 0) /* (V1) MMC0_DAT1 */ + AM62X_IOPAD(0x20c, PIN_INPUT, 0) /* (W2) MMC0_DAT2 */ + AM62X_IOPAD(0x208, PIN_INPUT, 0) /* (W1) MMC0_DAT3 */ + AM62X_IOPAD(0x204, PIN_INPUT, 0) /* (Y2) MMC0_DAT4 */ + AM62X_IOPAD(0x200, PIN_INPUT, 0) /* (W3) MMC0_DAT5 */ + AM62X_IOPAD(0x1fc, PIN_INPUT, 0) /* (W4) MMC0_DAT6 */ + AM62X_IOPAD(0x1f8, PIN_INPUT, 0) /* (V4) MMC0_DAT7 */ + >; + }; + vddshv_sdio_pins_default: vddshv-sdio-default-pins { pinctrl-single,pins = < AM62X_IOPAD(0x07c, PIN_OUTPUT, 7) /* (M19) GPMC0_CLK.GPIO0_31 */ @@ -144,6 +160,14 @@ }; };
+&sdhci0 { + bootph-all; + non-removable; + pinctrl-names = "default"; + pinctrl-0 = <&main_mmc0_pins_default>; + status = "okay"; +}; + &sdhci1 { vmmc-supply = <&vdd_mmc1>; vqmmc-supply = <&vddshv_sdio>; --- a/arch/arm64/boot/dts/ti/k3-am625-sk.dts +++ b/arch/arm64/boot/dts/ti/k3-am625-sk.dts @@ -106,6 +106,22 @@ };
&main_pmx0 { + main_mmc0_pins_default: main-mmc0-default-pins { + bootph-all; + pinctrl-single,pins = < + AM62X_IOPAD(0x220, PIN_INPUT, 0) /* (Y3) MMC0_CMD */ + AM62X_IOPAD(0x218, PIN_INPUT, 0) /* (AB1) MMC0_CLK */ + AM62X_IOPAD(0x214, PIN_INPUT, 0) /* (AA2) MMC0_DAT0 */ + AM62X_IOPAD(0x210, PIN_INPUT_PULLUP, 0) /* (AA1) MMC0_DAT1 */ + AM62X_IOPAD(0x20c, PIN_INPUT_PULLUP, 0) /* (AA3) MMC0_DAT2 */ + AM62X_IOPAD(0x208, PIN_INPUT_PULLUP, 0) /* (Y4) MMC0_DAT3 */ + AM62X_IOPAD(0x204, PIN_INPUT_PULLUP, 0) /* (AB2) MMC0_DAT4 */ + AM62X_IOPAD(0x200, PIN_INPUT_PULLUP, 0) /* (AC1) MMC0_DAT5 */ + AM62X_IOPAD(0x1fc, PIN_INPUT_PULLUP, 0) /* (AD2) MMC0_DAT6 */ + AM62X_IOPAD(0x1f8, PIN_INPUT_PULLUP, 0) /* (AC2) MMC0_DAT7 */ + >; + }; + main_rgmii2_pins_default: main-rgmii2-default-pins { bootph-all; pinctrl-single,pins = < @@ -195,6 +211,14 @@ }; };
+&sdhci0 { + bootph-all; + non-removable; + pinctrl-names = "default"; + pinctrl-0 = <&main_mmc0_pins_default>; + status = "okay"; +}; + &sdhci1 { vmmc-supply = <&vdd_mmc1>; vqmmc-supply = <&vdd_sd_dv>; --- a/arch/arm64/boot/dts/ti/k3-am62x-sk-common.dtsi +++ b/arch/arm64/boot/dts/ti/k3-am62x-sk-common.dtsi @@ -203,22 +203,6 @@ >; };
- main_mmc0_pins_default: main-mmc0-default-pins { - bootph-all; - pinctrl-single,pins = < - AM62X_IOPAD(0x220, PIN_INPUT, 0) /* (Y3/V3) MMC0_CMD */ - AM62X_IOPAD(0x218, PIN_INPUT, 0) /* (AB1/Y1) MMC0_CLK */ - AM62X_IOPAD(0x214, PIN_INPUT, 0) /* (AA2/V2) MMC0_DAT0 */ - AM62X_IOPAD(0x210, PIN_INPUT, 0) /* (AA1/V1) MMC0_DAT1 */ - AM62X_IOPAD(0x20c, PIN_INPUT, 0) /* (AA3/W2) MMC0_DAT2 */ - AM62X_IOPAD(0x208, PIN_INPUT, 0) /* (Y4/W1) MMC0_DAT3 */ - AM62X_IOPAD(0x204, PIN_INPUT, 0) /* (AB2/Y2) MMC0_DAT4 */ - AM62X_IOPAD(0x200, PIN_INPUT, 0) /* (AC1/W3) MMC0_DAT5 */ - AM62X_IOPAD(0x1fc, PIN_INPUT, 0) /* (AD2/W4) MMC0_DAT6 */ - AM62X_IOPAD(0x1f8, PIN_INPUT, 0) /* (AC2/V4) MMC0_DAT7 */ - >; - }; - main_mmc1_pins_default: main-mmc1-default-pins { bootph-all; pinctrl-single,pins = < @@ -457,14 +441,6 @@ clock-frequency = <400000>; };
-&sdhci0 { - bootph-all; - status = "okay"; - non-removable; - pinctrl-names = "default"; - pinctrl-0 = <&main_mmc0_pins_default>; -}; - &sdhci1 { /* SD/MMC */ bootph-all;
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Kaustabh Chakraborty kauschluss@disroot.org
commit 2bdfa35a7bb6e3a319e7a290baa44720bc96e5e4 upstream.
The device is available in multiple variants with differing RAM capacities. The memory range defined in the 0x80000000 bank exceeds the address range of the memory controller, which eventually leads to ARM SError crashes. Reduce the bank size to a value which is available to all devices.
The bootloader must be responsible for identifying the RAM capacity and editing the memory node accordingly.
Fixes: d6f3a7f91fdb ("arm64: dts: exynos: add initial devicetree support for exynos7870") Cc: stable@vger.kernel.org # v6.16 Signed-off-by: Kaustabh Chakraborty kauschluss@disroot.org Link: https://lore.kernel.org/r/20250626-exynos7870-dts-fixes-v1-2-349987874d9a@di... Signed-off-by: Krzysztof Kozlowski krzysztof.kozlowski@linaro.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- arch/arm64/boot/dts/exynos/exynos7870-on7xelte.dts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/arch/arm64/boot/dts/exynos/exynos7870-on7xelte.dts b/arch/arm64/boot/dts/exynos/exynos7870-on7xelte.dts index eb97dcc41542..b1d9eff5a827 100644 --- a/arch/arm64/boot/dts/exynos/exynos7870-on7xelte.dts +++ b/arch/arm64/boot/dts/exynos/exynos7870-on7xelte.dts @@ -78,7 +78,7 @@ memory@40000000 { device_type = "memory"; reg = <0x0 0x40000000 0x3e400000>, - <0x0 0x80000000 0xbe400000>; + <0x0 0x80000000 0x80000000>; };
pwrseq_mmc1: pwrseq-mmc1 {
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Emanuele Ghidoli emanuele.ghidoli@toradex.com
commit bdf4252f736cc1d2a8e3e633c70fe6c728f0756e upstream.
Enable internal bias pull-ups on the SoC-side I2C buses that do not have external pull resistors populated on the SoM. This ensures proper default line levels.
Cc: stable@vger.kernel.org Fixes: 316b80246b16 ("arm64: dts: ti: add verdin am62") Signed-off-by: Emanuele Ghidoli emanuele.ghidoli@toradex.com Reviewed-by: Francesco Dolcini francesco.dolcini@toradex.com Link: https://lore.kernel.org/r/20250528110741.262336-1-ghidoliemanuele@gmail.com Signed-off-by: Vignesh Raghavendra vigneshr@ti.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- arch/arm64/boot/dts/ti/k3-am62-verdin.dtsi | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-)
--- a/arch/arm64/boot/dts/ti/k3-am62-verdin.dtsi +++ b/arch/arm64/boot/dts/ti/k3-am62-verdin.dtsi @@ -507,16 +507,16 @@ /* Verdin I2C_2_DSI */ pinctrl_i2c2: main-i2c2-default-pins { pinctrl-single,pins = < - AM62X_IOPAD(0x00b0, PIN_INPUT, 1) /* (K22) GPMC0_CSn2.I2C2_SCL */ /* SODIMM 55 */ - AM62X_IOPAD(0x00b4, PIN_INPUT, 1) /* (K24) GPMC0_CSn3.I2C2_SDA */ /* SODIMM 53 */ + AM62X_IOPAD(0x00b0, PIN_INPUT_PULLUP, 1) /* (K22) GPMC0_CSn2.I2C2_SCL */ /* SODIMM 55 */ + AM62X_IOPAD(0x00b4, PIN_INPUT_PULLUP, 1) /* (K24) GPMC0_CSn3.I2C2_SDA */ /* SODIMM 53 */ >; };
/* Verdin I2C_4_CSI */ pinctrl_i2c3: main-i2c3-default-pins { pinctrl-single,pins = < - AM62X_IOPAD(0x01d0, PIN_INPUT, 2) /* (A15) UART0_CTSn.I2C3_SCL */ /* SODIMM 95 */ - AM62X_IOPAD(0x01d4, PIN_INPUT, 2) /* (B15) UART0_RTSn.I2C3_SDA */ /* SODIMM 93 */ + AM62X_IOPAD(0x01d0, PIN_INPUT_PULLUP, 2) /* (A15) UART0_CTSn.I2C3_SCL */ /* SODIMM 95 */ + AM62X_IOPAD(0x01d4, PIN_INPUT_PULLUP, 2) /* (B15) UART0_RTSn.I2C3_SDA */ /* SODIMM 93 */ >; };
@@ -786,8 +786,8 @@ /* Verdin I2C_3_HDMI */ pinctrl_mcu_i2c0: mcu-i2c0-default-pins { pinctrl-single,pins = < - AM62X_MCU_IOPAD(0x0044, PIN_INPUT, 0) /* (A8) MCU_I2C0_SCL */ /* SODIMM 59 */ - AM62X_MCU_IOPAD(0x0048, PIN_INPUT, 0) /* (D10) MCU_I2C0_SDA */ /* SODIMM 57 */ + AM62X_MCU_IOPAD(0x0044, PIN_INPUT_PULLUP, 0) /* (A8) MCU_I2C0_SCL */ /* SODIMM 59 */ + AM62X_MCU_IOPAD(0x0048, PIN_INPUT_PULLUP, 0) /* (D10) MCU_I2C0_SDA */ /* SODIMM 57 */ >; };
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sam Edwards cfsworks@gmail.com
commit de5b39d16318f9345f1ba7c1b684ba0c1cb6fdad upstream.
The RK3588 GPU power domain cannot be activated unless the external power regulator is already on. When GPU support was added to this DT, we had no way to represent this requirement, so `regulator-always-on` was added to the `vdd_gpu_s0` regulator in order to ensure stability. A later patch series (see "Fixes:" commit) resolved this shortcoming, but that commit left the workaround -- and rendered the comment above it no longer correct.
Remove the workaround to allow the GPU power regulator to power off, now that the DT includes the necessary information to power it back on correctly.
Fixes: f94500eb7328b ("arm64: dts: rockchip: Add GPU power domain regulator dependency for RK3588") Signed-off-by: Sam Edwards CFSworks@gmail.com Cc: stable@vger.kernel.org Link: https://lore.kernel.org/r/20250608184855.130206-1-CFSworks@gmail.com Signed-off-by: Heiko Stuebner heiko@sntech.de Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- arch/arm64/boot/dts/rockchip/rk3588-turing-rk1.dtsi | 11 ----------- 1 file changed, 11 deletions(-)
diff --git a/arch/arm64/boot/dts/rockchip/rk3588-turing-rk1.dtsi b/arch/arm64/boot/dts/rockchip/rk3588-turing-rk1.dtsi index 60ad272982ad..6daea8961fdd 100644 --- a/arch/arm64/boot/dts/rockchip/rk3588-turing-rk1.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3588-turing-rk1.dtsi @@ -398,17 +398,6 @@
regulators { vdd_gpu_s0: vdd_gpu_mem_s0: dcdc-reg1 { - /* - * RK3588's GPU power domain cannot be enabled - * without this regulator active, but it - * doesn't have to be on when the GPU PD is - * disabled. Because the PD binding does not - * currently allow us to express this - * relationship, we have no choice but to do - * this instead: - */ - regulator-always-on; - regulator-boot-on; regulator-min-microvolt = <550000>; regulator-max-microvolt = <950000>;
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Helge Deller deller@gmx.de
commit c567de2c4f5fe6e079672e074e1bc6122bf7e444 upstream.
The dfa blob stream for the aa_dfa_unpack() function is expected to be aligned on a 8 byte boundary.
The static nulldfa_src[] and stacksplitdfa_src[] arrays store the initial apparmor dfa blob streams, but since they are declared as an array-of-chars the compiler and linker will only ensure a "char" (1-byte) alignment.
Add an __aligned(8) annotation to the arrays to tell the linker to always align them on a 8-byte boundary. This avoids runtime warnings at startup on alignment-sensitive platforms like parisc such as:
Kernel: unaligned access to 0x7f2a584a in aa_dfa_unpack+0x124/0x788 (iir 0xca0109f) Kernel: unaligned access to 0x7f2a584e in aa_dfa_unpack+0x210/0x788 (iir 0xca8109c) Kernel: unaligned access to 0x7f2a586a in aa_dfa_unpack+0x278/0x788 (iir 0xcb01090)
Signed-off-by: Helge Deller deller@gmx.de Cc: stable@vger.kernel.org Fixes: 98b824ff8984 ("apparmor: refcount the pdb") Signed-off-by: John Johansen john.johansen@canonical.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- security/apparmor/lsm.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
--- a/security/apparmor/lsm.c +++ b/security/apparmor/lsm.c @@ -2149,12 +2149,12 @@ static int __init apparmor_nf_ip_init(vo __initcall(apparmor_nf_ip_init); #endif
-static char nulldfa_src[] = { +static char nulldfa_src[] __aligned(8) = { #include "nulldfa.in" }; static struct aa_dfa *nulldfa;
-static char stacksplitdfa_src[] = { +static char stacksplitdfa_src[] __aligned(8) = { #include "stacksplitdfa.in" }; struct aa_dfa *stacksplitdfa;
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Krzysztof Kozlowski krzysztof.kozlowski@linaro.org
commit 934da599e694d476f493d3927a30414e98a81561 upstream.
'minItems' alone does not impose upper bound, unlike 'maxItems' which implies lower bound. Add missing clock constraint so the list will have exact number of items (clocks).
Fixes: 8cae15c60cf0 ("dt-bindings: display: add Unisoc's dpu bindings") Cc: stable@vger.kernel.org Signed-off-by: Krzysztof Kozlowski krzysztof.kozlowski@linaro.org Link: https://lore.kernel.org/r/20250720123003.37662-3-krzysztof.kozlowski@linaro.... Signed-off-by: Rob Herring (Arm) robh@kernel.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- Documentation/devicetree/bindings/display/sprd/sprd,sharkl3-dpu.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
--- a/Documentation/devicetree/bindings/display/sprd/sprd,sharkl3-dpu.yaml +++ b/Documentation/devicetree/bindings/display/sprd/sprd,sharkl3-dpu.yaml @@ -25,7 +25,7 @@ properties: maxItems: 1
clocks: - minItems: 2 + maxItems: 2
clock-names: items:
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Krzysztof Kozlowski krzysztof.kozlowski@linaro.org
commit 2558df8c13ae3bd6c303b28f240ceb0189519c91 upstream.
'minItems' alone does not impose upper bound, unlike 'maxItems' which implies lower bound. Add missing clock constraint so the list will have exact number of items (clocks).
Fixes: 2295bbd35edb ("dt-bindings: display: add Unisoc's mipi dsi controller bindings") Cc: stable@vger.kernel.org Signed-off-by: Krzysztof Kozlowski krzysztof.kozlowski@linaro.org Link: https://lore.kernel.org/r/20250720123003.37662-4-krzysztof.kozlowski@linaro.... Signed-off-by: Rob Herring (Arm) robh@kernel.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- Documentation/devicetree/bindings/display/sprd/sprd,sharkl3-dsi-host.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
--- a/Documentation/devicetree/bindings/display/sprd/sprd,sharkl3-dsi-host.yaml +++ b/Documentation/devicetree/bindings/display/sprd/sprd,sharkl3-dsi-host.yaml @@ -20,7 +20,7 @@ properties: maxItems: 2
clocks: - minItems: 1 + maxItems: 1
clock-names: items:
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Cristian Ciocaltea cristian.ciocaltea@collabora.com
commit 3832dc42aed9b047ccecebf5917d008bd2dac940 upstream.
As with the RK3588 SoC, RK3576 also allows the use of HDMI PHY PLL as an alternative and more accurate pixel clock source for VOP2.
Document the optional PLL clock property.
Moreover, given that this is part of a series intended to address some recent display problems, provide the appropriate tags to facilitate backporting.
Fixes: c3b7c5a4d7c1 ("dt-bindings: display: vop2: Add rk3576 support") Cc: stable@vger.kernel.org Signed-off-by: Cristian Ciocaltea cristian.ciocaltea@collabora.com Reviewed-by: "Rob Herring (Arm)" robh@kernel.org Tested-by: Nicolas Frattaroli nicolas.frattaroli@collabora.com Signed-off-by: Heiko Stuebner heiko@sntech.de Link: https://lore.kernel.org/r/20250612-rk3576-hdmitx-fix-v1-1-4b11007d8675@colla... Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- Documentation/devicetree/bindings/display/rockchip/rockchip-vop2.yaml | 56 +++++++--- 1 file changed, 44 insertions(+), 12 deletions(-)
--- a/Documentation/devicetree/bindings/display/rockchip/rockchip-vop2.yaml +++ b/Documentation/devicetree/bindings/display/rockchip/rockchip-vop2.yaml @@ -64,10 +64,10 @@ properties: - description: Pixel clock for video port 0. - description: Pixel clock for video port 1. - description: Pixel clock for video port 2. - - description: Pixel clock for video port 3. - - description: Peripheral(vop grf/dsi) clock. - - description: Alternative pixel clock provided by HDMI0 PHY PLL. - - description: Alternative pixel clock provided by HDMI1 PHY PLL. + - {} + - {} + - {} + - {}
clock-names: minItems: 5 @@ -77,10 +77,10 @@ properties: - const: dclk_vp0 - const: dclk_vp1 - const: dclk_vp2 - - const: dclk_vp3 - - const: pclk_vop - - const: pll_hdmiphy0 - - const: pll_hdmiphy1 + - {} + - {} + - {} + - {}
rockchip,grf: $ref: /schemas/types.yaml#/definitions/phandle @@ -175,10 +175,24 @@ allOf: then: properties: clocks: - maxItems: 5 + minItems: 5 + items: + - {} + - {} + - {} + - {} + - {} + - description: Alternative pixel clock provided by HDMI PHY PLL.
clock-names: - maxItems: 5 + minItems: 5 + items: + - {} + - {} + - {} + - {} + - {} + - const: pll_hdmiphy0
interrupts: minItems: 4 @@ -208,11 +222,29 @@ allOf: properties: clocks: minItems: 7 - maxItems: 9 + items: + - {} + - {} + - {} + - {} + - {} + - description: Pixel clock for video port 3. + - description: Peripheral(vop grf/dsi) clock. + - description: Alternative pixel clock provided by HDMI0 PHY PLL. + - description: Alternative pixel clock provided by HDMI1 PHY PLL.
clock-names: minItems: 7 - maxItems: 9 + items: + - {} + - {} + - {} + - {} + - {} + - const: dclk_vp3 + - const: pclk_vop + - const: pll_hdmiphy0 + - const: pll_hdmiphy1
interrupts: maxItems: 1
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Macpaul Lin macpaul.lin@mediatek.com
commit 794ff7a0a6e76af93c5ec09a49b86fe73373ca59 upstream.
Add the 'mediatek,ufs-disable-mcq' property to the UFS device-tree bindings. This flag corresponds to the UFS_MTK_CAP_DISABLE_MCQ host capability recently introduced in the UFS host driver, allowing it to disable the Multiple Circular Queue (MCQ) feature when present. The binding schema has also been updated to resolve DTBS check errors.
Cc: stable@vger.kernel.org Fixes: 46bd3e31d74b ("scsi: ufs: mediatek: Add UFS_MTK_CAP_DISABLE_MCQ") Signed-off-by: Macpaul Lin macpaul.lin@mediatek.com Link: https://lore.kernel.org/r/20250722085721.2062657-2-macpaul.lin@mediatek.com Reviewed-by: Rob Herring (Arm) robh@kernel.org Reviewed-by: Peter Wang peter.wang@mediatek.com Signed-off-by: Martin K. Petersen martin.petersen@oracle.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- Documentation/devicetree/bindings/ufs/mediatek,ufs.yaml | 4 ++++ 1 file changed, 4 insertions(+)
--- a/Documentation/devicetree/bindings/ufs/mediatek,ufs.yaml +++ b/Documentation/devicetree/bindings/ufs/mediatek,ufs.yaml @@ -33,6 +33,10 @@ properties:
vcc-supply: true
+ mediatek,ufs-disable-mcq: + $ref: /schemas/types.yaml#/definitions/flag + description: The mask to disable MCQ (Multi-Circular Queue) for UFS host. + required: - compatible - clocks
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: André Draszik andre.draszik@linaro.org
commit 01aad16c2257ab8ff33b152b972c9f2e1af47912 upstream.
On Google gs101, the number of UTP transfer request slots (nutrs) is 32, and in this case the driver ends up programming the UTRL_NEXUS_TYPE incorrectly as 0.
This is because the left hand side of the shift is 1, which is of type int, i.e. 31 bits wide. Shifting by more than that width results in undefined behaviour.
Fix this by switching to the BIT() macro, which applies correct type casting as required. This ensures the correct value is written to UTRL_NEXUS_TYPE (0xffffffff on gs101), and it also fixes a UBSAN shift warning:
UBSAN: shift-out-of-bounds in drivers/ufs/host/ufs-exynos.c:1113:21 shift exponent 32 is too large for 32-bit type 'int'
For consistency, apply the same change to the nutmrs / UTMRL_NEXUS_TYPE write.
Fixes: 55f4b1f73631 ("scsi: ufs: ufs-exynos: Add UFS host support for Exynos SoCs") Cc: stable@vger.kernel.org Signed-off-by: André Draszik andre.draszik@linaro.org Link: https://lore.kernel.org/r/20250707-ufs-exynos-shift-v1-1-1418e161ae40@linaro... Reviewed-by: Bart Van Assche bvanassche@acm.org Reviewed-by: Peter Griffin peter.griffin@linaro.org Signed-off-by: Martin K. Petersen martin.petersen@oracle.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/ufs/host/ufs-exynos.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
--- a/drivers/ufs/host/ufs-exynos.c +++ b/drivers/ufs/host/ufs-exynos.c @@ -1110,8 +1110,8 @@ static int exynos_ufs_post_link(struct u hci_writel(ufs, val, HCI_TXPRDT_ENTRY_SIZE);
hci_writel(ufs, ilog2(DATA_UNIT_SIZE), HCI_RXPRDT_ENTRY_SIZE); - hci_writel(ufs, (1 << hba->nutrs) - 1, HCI_UTRL_NEXUS_TYPE); - hci_writel(ufs, (1 << hba->nutmrs) - 1, HCI_UTMRL_NEXUS_TYPE); + hci_writel(ufs, BIT(hba->nutrs) - 1, HCI_UTRL_NEXUS_TYPE); + hci_writel(ufs, BIT(hba->nutmrs) - 1, HCI_UTMRL_NEXUS_TYPE); hci_writel(ufs, 0xf, HCI_AXIDMA_RWDATA_BURST_LEN);
if (ufs->opts & EXYNOS_UFS_OPT_SKIP_CONNECTION_ESTAB)
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ranjan Kumar ranjan.kumar@broadcom.com
commit e6327c4acf925bb6d6d387d76fc3bd94471e10d8 upstream.
The "is_waiting" flag was updated after calling complete(), which could lead to a race where the waiting thread wakes up before the flag is cleared. This may cause a missed wakeup or stale state check.
Reorder the operations to update "is_waiting" before signaling completion to ensure consistent state.
Fixes: 824a156633df ("scsi: mpi3mr: Base driver code") Cc: stable@vger.kernel.org Co-developed-by: Chandrakanth Patil chandrakanth.patil@broadcom.com Signed-off-by: Chandrakanth Patil chandrakanth.patil@broadcom.com Signed-off-by: Ranjan Kumar ranjan.kumar@broadcom.com Link: https://lore.kernel.org/r/20250627194539.48851-2-ranjan.kumar@broadcom.com Signed-off-by: Martin K. Petersen martin.petersen@oracle.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/scsi/mpi3mr/mpi3mr_fw.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
--- a/drivers/scsi/mpi3mr/mpi3mr_fw.c +++ b/drivers/scsi/mpi3mr/mpi3mr_fw.c @@ -428,8 +428,8 @@ static void mpi3mr_process_admin_reply_d MPI3MR_SENSE_BUF_SZ); } if (cmdptr->is_waiting) { - complete(&cmdptr->done); cmdptr->is_waiting = 0; + complete(&cmdptr->done); } else if (cmdptr->callback) cmdptr->callback(mrioc, cmdptr); }
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Damien Le Moal dlemoal@kernel.org
commit cf3fc037623c54de48d2ec1a1ee686e2d1de2d45 upstream.
Commit 8ae720449fca ("libata: whitespace fixes in ata_to_sense_error()") inadvertantly added the entry 0x40 (ATA_DRDY) to the stat_table array in the function ata_to_sense_error(). This entry ties a failed qc which has a status filed equal to ATA_DRDY to the sense key ILLEGAL REQUEST with the additional sense code UNALIGNED WRITE COMMAND. This entry will be used to generate a failed qc sense key and sense code when the qc is missing sense data and there is no match for the qc error field in the sense_table array of ata_to_sense_error().
As a result, for a failed qc for which we failed to get sense data (e.g. read log 10h failed if qc is an NCQ command, or REQUEST SENSE EXT command failed for the non-ncq case, the user very often end up seeing the completely misleading "unaligned write command" error, even if qc was not a write command. E.g.:
sd 0:0:0:0: [sda] tag#12 FAILED Result: hostbyte=DID_OK driverbyte=DRIVER_OK cmd_age=0s sd 0:0:0:0: [sda] tag#12 Sense Key : Illegal Request [current] sd 0:0:0:0: [sda] tag#12 Add. Sense: Unaligned write command sd 0:0:0:0: [sda] tag#12 CDB: Read(10) 28 00 00 00 10 00 00 00 08 00 I/O error, dev sda, sector 4096 op 0x0:(READ) flags 0x80700 phys_seg 1 prio class 0
Fix this by removing the ATA_DRDY entry from the stat_table array so that we default to always returning ABORTED COMMAND without any additional sense code, since we do not know any better. The entry 0x08 (ATA_DRQ) is also removed since signaling ABORTED COMMAND with a parity error is also misleading (as a parity error would likely be signaled through a bus error). So for this case, also default to returning ABORTED COMMAND without any additional sense code. With this, the previous example error case becomes:
sd 0:0:0:0: [sda] tag#17 FAILED Result: hostbyte=DID_OK driverbyte=DRIVER_OK cmd_age=0s sd 0:0:0:0: [sda] tag#17 Sense Key : Aborted Command [current] sd 0:0:0:0: [sda] tag#17 Add. Sense: No additional sense information sd 0:0:0:0: [sda] tag#17 CDB: Read(10) 28 00 00 00 10 00 00 00 08 00 I/O error, dev sda, sector 4096 op 0x0:(READ) flags 0x80700 phys_seg 1 prio class 0
Together with these fixes, refactor stat_table to make it more readable by putting the entries comments in front of the entries and using the defined status bits macros instead of hardcoded values.
Reported-by: Lorenz Brun lorenz@brun.one Reported-by: Brandon Schwartz Brandon.Schwartz@wdc.com Fixes: 8ae720449fca ("libata: whitespace fixes in ata_to_sense_error()") Cc: stable@vger.kernel.org Signed-off-by: Damien Le Moal dlemoal@kernel.org Reviewed-by: Hannes Reinecke hare@suse.de Reviewed-by: Martin K. Petersen martin.petersen@oracle.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/ata/libata-scsi.c | 20 ++++++++------------ 1 file changed, 8 insertions(+), 12 deletions(-)
--- a/drivers/ata/libata-scsi.c +++ b/drivers/ata/libata-scsi.c @@ -859,18 +859,14 @@ static void ata_to_sense_error(u8 drv_st {0xFF, 0xFF, 0xFF, 0xFF}, // END mark }; static const unsigned char stat_table[][4] = { - /* Must be first because BUSY means no other bits valid */ - {0x80, ABORTED_COMMAND, 0x47, 0x00}, - // Busy, fake parity for now - {0x40, ILLEGAL_REQUEST, 0x21, 0x04}, - // Device ready, unaligned write command - {0x20, HARDWARE_ERROR, 0x44, 0x00}, - // Device fault, internal target failure - {0x08, ABORTED_COMMAND, 0x47, 0x00}, - // Timed out in xfer, fake parity for now - {0x04, RECOVERED_ERROR, 0x11, 0x00}, - // Recovered ECC error Medium error, recovered - {0xFF, 0xFF, 0xFF, 0xFF}, // END mark + /* Busy: must be first because BUSY means no other bits valid */ + { ATA_BUSY, ABORTED_COMMAND, 0x00, 0x00 }, + /* Device fault: INTERNAL TARGET FAILURE */ + { ATA_DF, HARDWARE_ERROR, 0x44, 0x00 }, + /* Corrected data error */ + { ATA_CORR, RECOVERED_ERROR, 0x00, 0x00 }, + + { 0xFF, 0xFF, 0xFF, 0xFF }, /* END mark */ };
/*
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Damien Le Moal dlemoal@kernel.org
commit d2be9ea9a75550a35c5127a6c2633658bc38c76b upstream.
ata_gen_ata_sense() is always called for a failed qc missing sense data so that a sense key, code and code qualifier can be generated using ata_to_sense_error() from the qc status and error fields of its result task file. However, if the qc does not have its result task file filled, ata_gen_ata_sense() returns early without setting a sense key.
Improve this by defaulting to returning ABORTED COMMAND without any additional sense code, since we do not know the reason for the failure. The same fix is also applied in ata_gen_passthru_sense() with the additional check that the qc failed (qc->err_mask is set).
Fixes: 816be86c7993 ("ata: libata-scsi: Check ATA_QCFLAG_RTF_FILLED before using result_tf") Cc: stable@vger.kernel.org Signed-off-by: Damien Le Moal dlemoal@kernel.org Reviewed-by: Hannes Reinecke hare@suse.de Reviewed-by: Martin K. Petersen martin.petersen@oracle.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/ata/libata-scsi.c | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-)
--- a/drivers/ata/libata-scsi.c +++ b/drivers/ata/libata-scsi.c @@ -938,6 +938,8 @@ static void ata_gen_passthru_sense(struc if (!(qc->flags & ATA_QCFLAG_RTF_FILLED)) { ata_dev_dbg(dev, "missing result TF: can't generate ATA PT sense data\n"); + if (qc->err_mask) + ata_scsi_set_sense(dev, cmd, ABORTED_COMMAND, 0, 0); return; }
@@ -992,8 +994,8 @@ static void ata_gen_ata_sense(struct ata
if (!(qc->flags & ATA_QCFLAG_RTF_FILLED)) { ata_dev_dbg(dev, - "missing result TF: can't generate sense data\n"); - return; + "Missing result TF: reporting aborted command\n"); + goto aborted; }
/* Use ata_to_sense_error() to map status register bits @@ -1004,13 +1006,15 @@ static void ata_gen_ata_sense(struct ata ata_to_sense_error(tf->status, tf->error, &sense_key, &asc, &ascq); ata_scsi_set_sense(dev, cmd, sense_key, asc, ascq); - } else { - /* Could not decode error */ - ata_dev_warn(dev, "could not decode error status 0x%x err_mask 0x%x\n", - tf->status, qc->err_mask); - ata_scsi_set_sense(dev, cmd, ABORTED_COMMAND, 0, 0); return; } + + /* Could not decode error */ + ata_dev_warn(dev, + "Could not decode error 0x%x, status 0x%x (err_mask=0x%x)\n", + tf->error, tf->status, qc->err_mask); +aborted: + ata_scsi_set_sense(dev, cmd, ABORTED_COMMAND, 0, 0); }
void ata_scsi_sdev_config(struct scsi_device *sdev)
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Archana Patni archana.patni@intel.com
commit 4428ddea832cfdb63e476eb2e5c8feb5d36057fe upstream.
UFSHCD core disables the UIC completion interrupt when issuing UIC hibernation commands, and re-enables it afterwards if it was enabled to start with, refer ufshcd_uic_pwr_ctrl(). For Intel MTL-like host controllers, accessing the register to re-enable the interrupt disrupts the state transition.
Use hibern8_notify variant operation to disable the interrupt during the entire hibernation, thereby preventing the disruption.
Fixes: 4049f7acef3e ("scsi: ufs: ufs-pci: Add support for Intel MTL") Cc: stable@vger.kernel.org Signed-off-by: Archana Patni archana.patni@intel.com Link: https://lore.kernel.org/r/20250723165856.145750-2-adrian.hunter@intel.com Reviewed-by: Bart Van Assche bvanassche@acm.org Signed-off-by: Martin K. Petersen martin.petersen@oracle.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/ufs/host/ufshcd-pci.c | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+)
--- a/drivers/ufs/host/ufshcd-pci.c +++ b/drivers/ufs/host/ufshcd-pci.c @@ -216,6 +216,32 @@ out: return ret; }
+static void ufs_intel_ctrl_uic_compl(struct ufs_hba *hba, bool enable) +{ + u32 set = ufshcd_readl(hba, REG_INTERRUPT_ENABLE); + + if (enable) + set |= UIC_COMMAND_COMPL; + else + set &= ~UIC_COMMAND_COMPL; + ufshcd_writel(hba, set, REG_INTERRUPT_ENABLE); +} + +static void ufs_intel_mtl_h8_notify(struct ufs_hba *hba, + enum uic_cmd_dme cmd, + enum ufs_notify_change_status status) +{ + /* + * Disable UIC COMPL INTR to prevent access to UFSHCI after + * checking HCS.UPMCRS + */ + if (status == PRE_CHANGE && cmd == UIC_CMD_DME_HIBER_ENTER) + ufs_intel_ctrl_uic_compl(hba, false); + + if (status == POST_CHANGE && cmd == UIC_CMD_DME_HIBER_EXIT) + ufs_intel_ctrl_uic_compl(hba, true); +} + #define INTEL_ACTIVELTR 0x804 #define INTEL_IDLELTR 0x808
@@ -533,6 +559,7 @@ static struct ufs_hba_variant_ops ufs_in .init = ufs_intel_mtl_init, .exit = ufs_intel_common_exit, .hce_enable_notify = ufs_intel_hce_enable_notify, + .hibern8_notify = ufs_intel_mtl_h8_notify, .link_startup_notify = ufs_intel_link_startup_notify, .resume = ufs_intel_resume, .device_reset = ufs_intel_device_reset,
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Adrian Hunter adrian.hunter@intel.com
commit 6de7435e6b81fe52c0ab4c7e181f6b5decd18eb1 upstream.
Intel MTL-like host controllers support auto-hibernate. Using auto-hibernate with manual (driver initiated) hibernate produces more complex operation. For example, the host controller will have to exit auto-hibernate simply to allow the driver to enter hibernate state manually. That is not recommended.
The default rpm_lvl and spm_lvl is 3, which includes manual hibernate.
Change the default values to 2, which does not.
Note, to be simpler to backport to stable kernels, utilize the UFS PCI driver's ->late_init() call back. Recent commits have made it possible to set up a controller-specific default in the regular ->init() call back, but not all stable kernels have those changes.
Fixes: 4049f7acef3e ("scsi: ufs: ufs-pci: Add support for Intel MTL") Cc: stable@vger.kernel.org Signed-off-by: Adrian Hunter adrian.hunter@intel.com Link: https://lore.kernel.org/r/20250723165856.145750-3-adrian.hunter@intel.com Reviewed-by: Bart Van Assche bvanassche@acm.org Signed-off-by: Martin K. Petersen martin.petersen@oracle.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/ufs/host/ufshcd-pci.c | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-)
--- a/drivers/ufs/host/ufshcd-pci.c +++ b/drivers/ufs/host/ufshcd-pci.c @@ -468,10 +468,23 @@ static int ufs_intel_adl_init(struct ufs return ufs_intel_common_init(hba); }
+static void ufs_intel_mtl_late_init(struct ufs_hba *hba) +{ + hba->rpm_lvl = UFS_PM_LVL_2; + hba->spm_lvl = UFS_PM_LVL_2; +} + static int ufs_intel_mtl_init(struct ufs_hba *hba) { + struct ufs_host *ufs_host; + int err; + hba->caps |= UFSHCD_CAP_CRYPTO | UFSHCD_CAP_WB_EN; - return ufs_intel_common_init(hba); + err = ufs_intel_common_init(hba); + /* Get variant after it is set in ufs_intel_common_init() */ + ufs_host = ufshcd_get_variant(hba); + ufs_host->late_init = ufs_intel_mtl_late_init; + return err; }
static int ufs_qemu_get_hba_mac(struct ufs_hba *hba)
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Igor Pylypiv ipylypiv@google.com
commit 58768b0563916ddcb73d8ed26ede664915f8df31 upstream.
Delete extra checks for the ATA_DFLAG_CDL_ENABLED flag that prevent SET FEATURES command from being issued to a drive when NCQ commands are active.
ata_mselect_control_ata_feature() sets / clears the ATA_DFLAG_CDL_ENABLED flag during the translation of MODE SELECT to SET FEATURES. If SET FEATURES gets deferred due to outstanding NCQ commands, the original MODE SELECT command will be re-queued. When the re-queued MODE SELECT goes through the ata_mselect_control_ata_feature() translation again, SET FEATURES will not be issued because ATA_DFLAG_CDL_ENABLED has been already set or cleared by the initial translation of MODE SELECT.
The ATA_DFLAG_CDL_ENABLED checks in ata_mselect_control_ata_feature() are safe to remove because scsi_cdl_enable() implements a similar logic that avoids enabling CDL if it has been enabled already.
Fixes: 17e897a45675 ("ata: libata-scsi: Improve CDL control") Cc: stable@vger.kernel.org Signed-off-by: Igor Pylypiv ipylypiv@google.com Reviewed-by: Niklas Cassel cassel@kernel.org Signed-off-by: Damien Le Moal dlemoal@kernel.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/ata/libata-scsi.c | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-)
--- a/drivers/ata/libata-scsi.c +++ b/drivers/ata/libata-scsi.c @@ -3905,21 +3905,16 @@ static int ata_mselect_control_ata_featu /* Check cdl_ctrl */ switch (buf[0] & 0x03) { case 0: - /* Disable CDL if it is enabled */ - if (!(dev->flags & ATA_DFLAG_CDL_ENABLED)) - return 0; + /* Disable CDL */ ata_dev_dbg(dev, "Disabling CDL\n"); cdl_action = 0; dev->flags &= ~ATA_DFLAG_CDL_ENABLED; break; case 0x02: /* - * Enable CDL if not already enabled. Since this is mutually - * exclusive with NCQ priority, allow this only if NCQ priority - * is disabled. + * Enable CDL. Since CDL is mutually exclusive with NCQ + * priority, allow this only if NCQ priority is disabled. */ - if (dev->flags & ATA_DFLAG_CDL_ENABLED) - return 0; if (dev->flags & ATA_DFLAG_NCQ_PRIO_ENABLED) { ata_dev_err(dev, "NCQ priority must be disabled to enable CDL\n");
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Bjorn Andersson bjorn.andersson@oss.qualcomm.com
commit 9f9967fed9d066ed3dae9372b45ffa4f6fccfeef upstream.
When the MDT loader is used in remoteproc, the ELF header is sanitized beforehand, but that's not necessary the case for other clients.
Validate the size of the firmware buffer to ensure that we don't read past the end as we iterate over the header. e_phentsize and e_shentsize are validated as well, to ensure that the assumptions about step size in the traversal are valid.
Fixes: 2aad40d911ee ("remoteproc: Move qcom_mdt_loader into drivers/soc/qcom") Cc: stable@vger.kernel.org Reported-by: Doug Anderson dianders@chromium.org Signed-off-by: Bjorn Andersson bjorn.andersson@oss.qualcomm.com Reviewed-by: Dmitry Baryshkov dmitry.baryshkov@oss.qualcomm.com Link: https://lore.kernel.org/r/20250610-mdt-loader-validation-and-fixes-v2-1-f707... Signed-off-by: Bjorn Andersson andersson@kernel.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/soc/qcom/mdt_loader.c | 43 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+)
--- a/drivers/soc/qcom/mdt_loader.c +++ b/drivers/soc/qcom/mdt_loader.c @@ -18,6 +18,37 @@ #include <linux/slab.h> #include <linux/soc/qcom/mdt_loader.h>
+static bool mdt_header_valid(const struct firmware *fw) +{ + const struct elf32_hdr *ehdr; + size_t phend; + size_t shend; + + if (fw->size < sizeof(*ehdr)) + return false; + + ehdr = (struct elf32_hdr *)fw->data; + + if (memcmp(ehdr->e_ident, ELFMAG, SELFMAG)) + return false; + + if (ehdr->e_phentsize != sizeof(struct elf32_phdr)) + return -EINVAL; + + phend = size_add(size_mul(sizeof(struct elf32_phdr), ehdr->e_phnum), ehdr->e_phoff); + if (phend > fw->size) + return false; + + if (ehdr->e_shentsize != sizeof(struct elf32_shdr)) + return -EINVAL; + + shend = size_add(size_mul(sizeof(struct elf32_shdr), ehdr->e_shnum), ehdr->e_shoff); + if (shend > fw->size) + return false; + + return true; +} + static bool mdt_phdr_valid(const struct elf32_phdr *phdr) { if (phdr->p_type != PT_LOAD) @@ -82,6 +113,9 @@ ssize_t qcom_mdt_get_size(const struct f phys_addr_t max_addr = 0; int i;
+ if (!mdt_header_valid(fw)) + return -EINVAL; + ehdr = (struct elf32_hdr *)fw->data; phdrs = (struct elf32_phdr *)(fw->data + ehdr->e_phoff);
@@ -134,6 +168,9 @@ void *qcom_mdt_read_metadata(const struc ssize_t ret; void *data;
+ if (!mdt_header_valid(fw)) + return ERR_PTR(-EINVAL); + ehdr = (struct elf32_hdr *)fw->data; phdrs = (struct elf32_phdr *)(fw->data + ehdr->e_phoff);
@@ -214,6 +251,9 @@ int qcom_mdt_pas_init(struct device *dev int ret; int i;
+ if (!mdt_header_valid(fw)) + return -EINVAL; + ehdr = (struct elf32_hdr *)fw->data; phdrs = (struct elf32_phdr *)(fw->data + ehdr->e_phoff);
@@ -310,6 +350,9 @@ static int __qcom_mdt_load(struct device if (!fw || !mem_region || !mem_phys || !mem_size) return -EINVAL;
+ if (!mdt_header_valid(fw)) + return -EINVAL; + is_split = qcom_mdt_bins_are_split(fw, fw_name); ehdr = (struct elf32_hdr *)fw->data; phdrs = (struct elf32_phdr *)(fw->data + ehdr->e_phoff);
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Marek Szyprowski m.szyprowski@samsung.com
commit 37e00703228ab44d0aacc32a97809a4f6f58df1b upstream.
Use common wrappers operating directly on the struct sg_table objects to fix incorrect use of statterlists related calls. dma_unmap_sg() function has to be called with the number of elements originally passed to the dma_map_sg() function, not the one returned in sgtable's nents.
CC: stable@vger.kernel.org Fixes: 425902f5c8e3 ("fpga zynq: Use the scatterlist interface") Signed-off-by: Marek Szyprowski m.szyprowski@samsung.com Reviewed-by: Jason Gunthorpe jgg@nvidia.com Reviewed-by: Xu Yilun yilun.xu@intel.com Link: https://lore.kernel.org/r/20250616120932.1090614-1-m.szyprowski@samsung.com Signed-off-by: Xu Yilun yilun.xu@linux.intel.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/fpga/zynq-fpga.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
--- a/drivers/fpga/zynq-fpga.c +++ b/drivers/fpga/zynq-fpga.c @@ -406,7 +406,7 @@ static int zynq_fpga_ops_write(struct fp }
priv->dma_nelms = - dma_map_sg(mgr->dev.parent, sgt->sgl, sgt->nents, DMA_TO_DEVICE); + dma_map_sgtable(mgr->dev.parent, sgt, DMA_TO_DEVICE, 0); if (priv->dma_nelms == 0) { dev_err(&mgr->dev, "Unable to DMA map (TO_DEVICE)\n"); return -ENOMEM; @@ -478,7 +478,7 @@ out_clk: clk_disable(priv->clk);
out_free: - dma_unmap_sg(mgr->dev.parent, sgt->sgl, sgt->nents, DMA_TO_DEVICE); + dma_unmap_sgtable(mgr->dev.parent, sgt, DMA_TO_DEVICE, 0); return err; }
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: David Lechner dlechner@baylibre.com
commit 399b883ec828e436f1a721bf8551b4da8727e65b upstream.
Fix a potential out-of-bounds array access of the hw_xlate array in bno055.c.
In bno055_get_regmask(), hw_xlate was iterated over the length of the vals array instead of the length of the hw_xlate array. In the case of bno055_gyr_scale, the vals array is larger than the hw_xlate array, so this could result in an out-of-bounds access. In practice, this shouldn't happen though because a match should always be found which breaks out of the for loop before it iterates beyond the end of the hw_xlate array.
By adding a new hw_xlate_len field to the bno055_sysfs_attr, we can be sure we are iterating over the correct length.
Reported-by: kernel test robot lkp@intel.com Closes: https://lore.kernel.org/oe-kbuild-all/202507100510.rGt1YOOx-lkp@intel.com/ Fixes: 4aefe1c2bd0c ("iio: imu: add Bosch Sensortec BNO055 core driver") Signed-off-by: David Lechner dlechner@baylibre.com Link: https://patch.msgid.link/20250709-iio-const-data-19-v2-1-fb3fc9191251@baylib... Cc: Stable@vger.kernel.org Signed-off-by: Jonathan Cameron Jonathan.Cameron@huawei.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/iio/imu/bno055/bno055.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-)
--- a/drivers/iio/imu/bno055/bno055.c +++ b/drivers/iio/imu/bno055/bno055.c @@ -118,6 +118,7 @@ struct bno055_sysfs_attr { int len; int *fusion_vals; int *hw_xlate; + int hw_xlate_len; int type; };
@@ -170,20 +171,24 @@ static int bno055_gyr_scale_vals[] = { 1000, 1877467, 2000, 1877467, };
+static int bno055_gyr_scale_hw_xlate[] = {0, 1, 2, 3, 4}; static struct bno055_sysfs_attr bno055_gyr_scale = { .vals = bno055_gyr_scale_vals, .len = ARRAY_SIZE(bno055_gyr_scale_vals), .fusion_vals = (int[]){1, 900}, - .hw_xlate = (int[]){4, 3, 2, 1, 0}, + .hw_xlate = bno055_gyr_scale_hw_xlate, + .hw_xlate_len = ARRAY_SIZE(bno055_gyr_scale_hw_xlate), .type = IIO_VAL_FRACTIONAL, };
static int bno055_gyr_lpf_vals[] = {12, 23, 32, 47, 64, 116, 230, 523}; +static int bno055_gyr_lpf_hw_xlate[] = {5, 4, 7, 3, 6, 2, 1, 0}; static struct bno055_sysfs_attr bno055_gyr_lpf = { .vals = bno055_gyr_lpf_vals, .len = ARRAY_SIZE(bno055_gyr_lpf_vals), .fusion_vals = (int[]){32}, - .hw_xlate = (int[]){5, 4, 7, 3, 6, 2, 1, 0}, + .hw_xlate = bno055_gyr_lpf_hw_xlate, + .hw_xlate_len = ARRAY_SIZE(bno055_gyr_lpf_hw_xlate), .type = IIO_VAL_INT, };
@@ -561,7 +566,7 @@ static int bno055_get_regmask(struct bno
idx = (hwval & mask) >> shift; if (attr->hw_xlate) - for (i = 0; i < attr->len; i++) + for (i = 0; i < attr->hw_xlate_len; i++) if (attr->hw_xlate[i] == idx) { idx = i; break;
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: David Lechner dlechner@baylibre.com
commit 66d4374d97f85516b5a22418c5e798aed2606dec upstream.
Change the buffer disable callback from postdisable to predisable. This balances the existing posteanble callback. Using postdisable with posteanble can be problematic, for example, if update_scan_mode fails, it would call postdisable without ever having called posteanble, so the drivers using this would be in an unexpected state when postdisable was called.
Fixes: af3008485ea0 ("iio:adc: Add common code for ADI Sigma Delta devices") Signed-off-by: David Lechner dlechner@baylibre.com Reviewed-by: Nuno Sá nuno.sa@analog.com Link: https://patch.msgid.link/20250703-iio-adc-ad_sigma_delta-buffer-predisable-v... Cc: stable@vger.kernel.org Signed-off-by: Jonathan Cameron Jonathan.Cameron@huawei.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/iio/adc/ad_sigma_delta.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
--- a/drivers/iio/adc/ad_sigma_delta.c +++ b/drivers/iio/adc/ad_sigma_delta.c @@ -520,7 +520,7 @@ err_unlock: return ret; }
-static int ad_sd_buffer_postdisable(struct iio_dev *indio_dev) +static int ad_sd_buffer_predisable(struct iio_dev *indio_dev) { struct ad_sigma_delta *sigma_delta = iio_device_get_drvdata(indio_dev);
@@ -644,7 +644,7 @@ static bool ad_sd_validate_scan_mask(str
static const struct iio_buffer_setup_ops ad_sd_buffer_setup_ops = { .postenable = &ad_sd_buffer_postenable, - .postdisable = &ad_sd_buffer_postdisable, + .predisable = &ad_sd_buffer_predisable, .validate_scan_mask = &ad_sd_validate_scan_mask, };
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: David Lechner dlechner@baylibre.com
commit 0eb8d7b25397330beab8ee62c681975b79f37223 upstream.
Fix the index used to look up the channel when accessing the syscalib_mode attribute. The address field is a 0-based index (same as scan_index) that it used to access the channel in the ad7173_channels array throughout the driver. The channels field, on the other hand, may not match the address field depending on the channel configuration specified in the device tree and could result in an out-of-bounds access.
Fixes: 031bdc8aee01 ("iio: adc: ad7173: add calibration support") Signed-off-by: David Lechner dlechner@baylibre.com Link: https://patch.msgid.link/20250703-iio-adc-ad7173-fix-channels-index-for-sysc... Cc: Stable@vger.kernel.org Signed-off-by: Jonathan Cameron Jonathan.Cameron@huawei.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/iio/adc/ad7173.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
--- a/drivers/iio/adc/ad7173.c +++ b/drivers/iio/adc/ad7173.c @@ -319,7 +319,7 @@ static int ad7173_set_syscalib_mode(stru { struct ad7173_state *st = iio_priv(indio_dev);
- st->channels[chan->channel].syscalib_mode = mode; + st->channels[chan->address].syscalib_mode = mode;
return 0; } @@ -329,7 +329,7 @@ static int ad7173_get_syscalib_mode(stru { struct ad7173_state *st = iio_priv(indio_dev);
- return st->channels[chan->channel].syscalib_mode; + return st->channels[chan->address].syscalib_mode; }
static ssize_t ad7173_write_syscalib(struct iio_dev *indio_dev, @@ -348,7 +348,7 @@ static ssize_t ad7173_write_syscalib(str if (!iio_device_claim_direct(indio_dev)) return -EBUSY;
- mode = st->channels[chan->channel].syscalib_mode; + mode = st->channels[chan->address].syscalib_mode; if (sys_calib) { if (mode == AD7173_SYSCALIB_ZERO_SCALE) ret = ad_sd_calibrate(&st->sd, AD7173_MODE_CAL_SYS_ZERO,
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: David Lechner dlechner@baylibre.com
commit 1d9a21ffb43b6fd326ead98f0d0afd6d104b739a upstream.
Fix the channel index values passed to ad_sd_calibrate() in ad7173_calibrate_all().
ad7173_calibrate_all() expects these values to be that of the CHANNELx register assigned to the channel, not the datasheet INPUTx number of the channel. The incorrect values were causing register writes to fail for some channels because they set the WEN bit that must always be 0 for register access and set the R/W bit to read instead of write. For other channels, the channel number was just wrong because the CHANNELx registers are generally assigned in reverse order and so almost never match the INPUTx numbers.
Fixes: 031bdc8aee01 ("iio: adc: ad7173: add calibration support") Signed-off-by: David Lechner dlechner@baylibre.com Reviewed-by: Nuno Sá nuno.sa@analog.com Link: https://patch.msgid.link/20250708-iio-adc-ad7313-fix-calibration-channel-v1-... Cc: Stable@vger.kernel.org Signed-off-by: Jonathan Cameron Jonathan.Cameron@huawei.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/iio/adc/ad7173.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-)
--- a/drivers/iio/adc/ad7173.c +++ b/drivers/iio/adc/ad7173.c @@ -392,13 +392,12 @@ static int ad7173_calibrate_all(struct a if (indio_dev->channels[i].type != IIO_VOLTAGE) continue;
- ret = ad_sd_calibrate(&st->sd, AD7173_MODE_CAL_INT_ZERO, st->channels[i].ain); + ret = ad_sd_calibrate(&st->sd, AD7173_MODE_CAL_INT_ZERO, i); if (ret < 0) return ret;
if (st->info->has_internal_fs_calibration) { - ret = ad_sd_calibrate(&st->sd, AD7173_MODE_CAL_INT_FULL, - st->channels[i].ain); + ret = ad_sd_calibrate(&st->sd, AD7173_MODE_CAL_INT_FULL, i); if (ret < 0) return ret; }
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: David Lechner dlechner@baylibre.com
commit 6fa908abd19cc35c205f343b79c67ff38dbc9b76 upstream.
Fix the setting of the ODR register value in the probe function for AD7177. The AD7177 chip has a different ODR value after reset than the other chips (0x7 vs. 0x0) and 0 is a reserved value on that chip.
The driver already has this information available in odr_start_value and uses it when checking valid values when writing to the sampling_frequency attribute, but failed to set the correct initial value in the probe function.
Fixes: 37ae8381ccda ("iio: adc: ad7173: add support for additional models") Signed-off-by: David Lechner dlechner@baylibre.com Link: https://patch.msgid.link/20250710-iio-adc-ad7173-fix-setting-odr-in-probe-v1... Cc: Stable@vger.kernel.org Signed-off-by: Jonathan Cameron Jonathan.Cameron@huawei.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/iio/adc/ad7173.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
--- a/drivers/iio/adc/ad7173.c +++ b/drivers/iio/adc/ad7173.c @@ -1595,6 +1595,7 @@ static int ad7173_fw_parse_channel_confi chan_st_priv->cfg.bipolar = false; chan_st_priv->cfg.input_buf = st->info->has_input_buf; chan_st_priv->cfg.ref_sel = AD7173_SETUP_REF_SEL_INT_REF; + chan_st_priv->cfg.odr = st->info->odr_start_value; chan_st_priv->cfg.openwire_comp_chan = -1; st->adc_mode |= AD7173_ADC_MODE_REF_EN; if (st->info->data_reg_only_16bit) @@ -1661,7 +1662,7 @@ static int ad7173_fw_parse_channel_confi chan->scan_index = chan_index; chan->channel = ain[0]; chan_st_priv->cfg.input_buf = st->info->has_input_buf; - chan_st_priv->cfg.odr = 0; + chan_st_priv->cfg.odr = st->info->odr_start_value; chan_st_priv->cfg.openwire_comp_chan = -1;
chan_st_priv->cfg.bipolar = fwnode_property_read_bool(child, "bipolar");
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Nathan Chancellor nathan@kernel.org
commit 81284e86bf8849f8e98e8ead3ff5811926b2107f upstream.
A new warning in clang [1] complains that diq_start in wlc_lcnphy_tx_iqlo_cal() is passed uninitialized as a const pointer to wlc_lcnphy_common_read_table():
drivers/net/wireless/broadcom/brcm80211/brcmsmac/phy/phy_lcn.c:2728:13: error: variable 'diq_start' is uninitialized when passed as a const pointer argument here [-Werror,-Wuninitialized-const-pointer] 2728 | &diq_start, 1, 16, 69); | ^~~~~~~~~
The table pointer passed to wlc_lcnphy_common_read_table() should not be considered constant, as wlc_phy_read_table() is ultimately going to update it. Remove the const qualifier from the tbl_ptr to clear up the warning.
Cc: stable@vger.kernel.org Closes: https://github.com/ClangBuiltLinux/linux/issues/2108 Fixes: 5b435de0d786 ("net: wireless: add brcm80211 drivers") Link: https://github.com/llvm/llvm-project/commit/00dacf8c22f065cb52efb14cd091d441... [1] Signed-off-by: Nathan Chancellor nathan@kernel.org Acked-by: Arend van Spriel arend.vanspriel@broadcom.com> Link: https://patch.msgid.link/20250715-brcmsmac-fix-uninit-const-pointer-v1-1-16e... Signed-off-by: Johannes Berg johannes.berg@intel.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/net/wireless/broadcom/brcm80211/brcmsmac/phy/phy_lcn.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
--- a/drivers/net/wireless/broadcom/brcm80211/brcmsmac/phy/phy_lcn.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/phy/phy_lcn.c @@ -919,7 +919,7 @@ void wlc_lcnphy_read_table(struct brcms_
static void wlc_lcnphy_common_read_table(struct brcms_phy *pi, u32 tbl_id, - const u16 *tbl_ptr, u32 tbl_len, + u16 *tbl_ptr, u32 tbl_len, u32 tbl_width, u32 tbl_offset) { struct phytbl_info tab;
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Johan Hovold johan+linaro@kernel.org
commit 8157ce533a60521f21d466eb4de45d9735b19484 upstream.
Add the missing memory barrier to make sure that destination ring descriptors are read after the head pointers to avoid using stale data on weakly ordered architectures like aarch64.
The barrier is added to the ath12k_hal_srng_access_begin() helper for symmetry with follow-on fixes for source ring buffer corruption which will add barriers to ath12k_hal_srng_access_end().
Tested-on: WCN7850 hw2.0 WLAN.HMT.1.0.c5-00481-QCAHMTSWPL_V1.0_V2.0_SILICONZ-3
Fixes: d889913205cf ("wifi: ath12k: driver for Qualcomm Wi-Fi 7 devices") Cc: stable@vger.kernel.org # 6.3 Signed-off-by: Johan Hovold johan+linaro@kernel.org Reviewed-by: Baochen Qiang quic_bqiang@quicinc.com Link: https://patch.msgid.link/20250617084402.14475-2-johan+linaro@kernel.org Signed-off-by: Jeff Johnson jeff.johnson@oss.qualcomm.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/net/wireless/ath/ath12k/ce.c | 3 --- drivers/net/wireless/ath/ath12k/hal.c | 17 ++++++++++++++--- 2 files changed, 14 insertions(+), 6 deletions(-)
--- a/drivers/net/wireless/ath/ath12k/ce.c +++ b/drivers/net/wireless/ath/ath12k/ce.c @@ -433,9 +433,6 @@ static int ath12k_ce_completed_recv_next goto err; }
- /* Make sure descriptor is read after the head pointer. */ - dma_rmb(); - *nbytes = ath12k_hal_ce_dst_status_get_length(desc);
*skb = pipe->dest_ring->skb[sw_index]; --- a/drivers/net/wireless/ath/ath12k/hal.c +++ b/drivers/net/wireless/ath/ath12k/hal.c @@ -2143,13 +2143,24 @@ void *ath12k_hal_srng_src_get_next_reape
void ath12k_hal_srng_access_begin(struct ath12k_base *ab, struct hal_srng *srng) { + u32 hp; + lockdep_assert_held(&srng->lock);
- if (srng->ring_dir == HAL_SRNG_DIR_SRC) + if (srng->ring_dir == HAL_SRNG_DIR_SRC) { srng->u.src_ring.cached_tp = *(volatile u32 *)srng->u.src_ring.tp_addr; - else - srng->u.dst_ring.cached_hp = READ_ONCE(*srng->u.dst_ring.hp_addr); + } else { + hp = READ_ONCE(*srng->u.dst_ring.hp_addr); + + if (hp != srng->u.dst_ring.cached_hp) { + srng->u.dst_ring.cached_hp = hp; + /* Make sure descriptor is read after the head + * pointer. + */ + dma_rmb(); + } + } }
/* Update cached ring head/tail pointers to HW. ath12k_hal_srng_access_begin()
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Johan Hovold johan+linaro@kernel.org
commit e834da4cbd6fe1d24f89368bf0c80adcad212726 upstream.
Add the missing memory barrier to make sure that LMAC source ring descriptors are written before updating the head pointer to avoid passing stale data to the firmware on weakly ordered architectures like aarch64.
Note that non-LMAC rings use MMIO write accessors which have the required write memory barrier.
Tested-on: WCN7850 hw2.0 WLAN.HMT.1.0.c5-00481-QCAHMTSWPL_V1.0_V2.0_SILICONZ-3
Fixes: d889913205cf ("wifi: ath12k: driver for Qualcomm Wi-Fi 7 devices") Cc: stable@vger.kernel.org # 6.3 Signed-off-by: Johan Hovold johan+linaro@kernel.org Reviewed-by: Baochen Qiang quic_bqiang@quicinc.com Link: https://patch.msgid.link/20250617084402.14475-4-johan+linaro@kernel.org Signed-off-by: Jeff Johnson jeff.johnson@oss.qualcomm.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/net/wireless/ath/ath12k/hal.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-)
--- a/drivers/net/wireless/ath/ath12k/hal.c +++ b/drivers/net/wireless/ath/ath12k/hal.c @@ -2178,7 +2178,11 @@ void ath12k_hal_srng_access_end(struct a if (srng->ring_dir == HAL_SRNG_DIR_SRC) { srng->u.src_ring.last_tp = *(volatile u32 *)srng->u.src_ring.tp_addr; - *srng->u.src_ring.hp_addr = srng->u.src_ring.hp; + /* Make sure descriptor is written before updating the + * head pointer. + */ + dma_wmb(); + WRITE_ONCE(*srng->u.src_ring.hp_addr, srng->u.src_ring.hp); } else { srng->u.dst_ring.last_hp = *srng->u.dst_ring.hp_addr; *srng->u.dst_ring.tp_addr = srng->u.dst_ring.tp; @@ -2187,6 +2191,10 @@ void ath12k_hal_srng_access_end(struct a if (srng->ring_dir == HAL_SRNG_DIR_SRC) { srng->u.src_ring.last_tp = *(volatile u32 *)srng->u.src_ring.tp_addr; + /* Assume implementation use an MMIO write accessor + * which has the required wmb() so that the descriptor + * is written before the updating the head pointer. + */ ath12k_hif_write32(ab, (unsigned long)srng->u.src_ring.hp_addr - (unsigned long)ab->mem,
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Johan Hovold johan+linaro@kernel.org
commit ed32169be1ccb9b1a295275ba7746dc6bf103e80 upstream.
Add the missing memory barriers to make sure that destination ring descriptors are read before updating the tail pointer (and passing ownership to the device) to avoid memory corruption on weakly ordered architectures like aarch64 when the ring is full.
Tested-on: WCN7850 hw2.0 WLAN.HMT.1.0.c5-00481-QCAHMTSWPL_V1.0_V2.0_SILICONZ-3
Fixes: d889913205cf ("wifi: ath12k: driver for Qualcomm Wi-Fi 7 devices") Cc: stable@vger.kernel.org # 6.3 Signed-off-by: Johan Hovold johan+linaro@kernel.org Reviewed-by: Baochen Qiang quic_bqiang@quicinc.com Link: https://patch.msgid.link/20250617084402.14475-5-johan+linaro@kernel.org Signed-off-by: Jeff Johnson jeff.johnson@oss.qualcomm.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/net/wireless/ath/ath12k/hal.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-)
--- a/drivers/net/wireless/ath/ath12k/hal.c +++ b/drivers/net/wireless/ath/ath12k/hal.c @@ -2170,7 +2170,6 @@ void ath12k_hal_srng_access_end(struct a { lockdep_assert_held(&srng->lock);
- /* TODO: See if we need a write memory barrier here */ if (srng->flags & HAL_SRNG_FLAGS_LMAC_RING) { /* For LMAC rings, ring pointer updates are done through FW and * hence written to a shared memory location that is read by FW @@ -2185,7 +2184,11 @@ void ath12k_hal_srng_access_end(struct a WRITE_ONCE(*srng->u.src_ring.hp_addr, srng->u.src_ring.hp); } else { srng->u.dst_ring.last_hp = *srng->u.dst_ring.hp_addr; - *srng->u.dst_ring.tp_addr = srng->u.dst_ring.tp; + /* Make sure descriptor is read before updating the + * tail pointer. + */ + dma_mb(); + WRITE_ONCE(*srng->u.dst_ring.tp_addr, srng->u.dst_ring.tp); } } else { if (srng->ring_dir == HAL_SRNG_DIR_SRC) { @@ -2201,6 +2204,10 @@ void ath12k_hal_srng_access_end(struct a srng->u.src_ring.hp); } else { srng->u.dst_ring.last_hp = *srng->u.dst_ring.hp_addr; + /* Make sure descriptor is read before updating the + * tail pointer. + */ + mb(); ath12k_hif_write32(ab, (unsigned long)srng->u.dst_ring.tp_addr - (unsigned long)ab->mem,
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Johan Hovold johan+linaro@kernel.org
commit 8c1ba5091fa9a2d1478da63173b16a701bdf86bb upstream.
Add the missing memory barrier to make sure that destination ring descriptors are read after the head pointers to avoid using stale data on weakly ordered architectures like aarch64.
The barrier is added to the ath11k_hal_srng_access_begin() helper for symmetry with follow-on fixes for source ring buffer corruption which will add barriers to ath11k_hal_srng_access_end().
Tested-on: WCN6855 hw2.1 WLAN.HSP.1.1-03125-QCAHSPSWPL_V1_V2_SILICONZ_LITE-3.6510.41
Fixes: d5c65159f289 ("ath11k: driver for Qualcomm IEEE 802.11ax devices") Cc: stable@vger.kernel.org # 5.6 Signed-off-by: Johan Hovold johan+linaro@kernel.org Reviewed-by: Baochen Qiang quic_bqiang@quicinc.com Link: https://patch.msgid.link/20250604143457.26032-2-johan+linaro@kernel.org Signed-off-by: Jeff Johnson jeff.johnson@oss.qualcomm.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/net/wireless/ath/ath11k/ce.c | 3 --- drivers/net/wireless/ath/ath11k/dp_rx.c | 3 --- drivers/net/wireless/ath/ath11k/hal.c | 12 +++++++++++- 3 files changed, 11 insertions(+), 7 deletions(-)
--- a/drivers/net/wireless/ath/ath11k/ce.c +++ b/drivers/net/wireless/ath/ath11k/ce.c @@ -393,9 +393,6 @@ static int ath11k_ce_completed_recv_next goto err; }
- /* Make sure descriptor is read after the head pointer. */ - dma_rmb(); - *nbytes = ath11k_hal_ce_dst_status_get_length(desc);
*skb = pipe->dest_ring->skb[sw_index]; --- a/drivers/net/wireless/ath/ath11k/dp_rx.c +++ b/drivers/net/wireless/ath/ath11k/dp_rx.c @@ -2650,9 +2650,6 @@ int ath11k_dp_process_rx(struct ath11k_b try_again: ath11k_hal_srng_access_begin(ab, srng);
- /* Make sure descriptor is read after the head pointer. */ - dma_rmb(); - while (likely(desc = (struct hal_reo_dest_ring *)ath11k_hal_srng_dst_get_next_entry(ab, srng))) { --- a/drivers/net/wireless/ath/ath11k/hal.c +++ b/drivers/net/wireless/ath/ath11k/hal.c @@ -823,13 +823,23 @@ u32 *ath11k_hal_srng_src_peek(struct ath
void ath11k_hal_srng_access_begin(struct ath11k_base *ab, struct hal_srng *srng) { + u32 hp; + lockdep_assert_held(&srng->lock);
if (srng->ring_dir == HAL_SRNG_DIR_SRC) { srng->u.src_ring.cached_tp = *(volatile u32 *)srng->u.src_ring.tp_addr; } else { - srng->u.dst_ring.cached_hp = READ_ONCE(*srng->u.dst_ring.hp_addr); + hp = READ_ONCE(*srng->u.dst_ring.hp_addr); + + if (hp != srng->u.dst_ring.cached_hp) { + srng->u.dst_ring.cached_hp = hp; + /* Make sure descriptor is read after the head + * pointer. + */ + dma_rmb(); + }
/* Try to prefetch the next descriptor in the ring */ if (srng->flags & HAL_SRNG_FLAGS_CACHED)
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Johan Hovold johan+linaro@kernel.org
commit 6efa0df54022c6c9fd4d294b87622c7fcdc418c8 upstream.
Add the missing memory barrier to make sure that LMAC source ring descriptors are written before updating the head pointer to avoid passing stale data to the firmware on weakly ordered architectures like aarch64.
Note that non-LMAC rings use MMIO write accessors which have the required write memory barrier.
Tested-on: WCN6855 hw2.1 WLAN.HSP.1.1-03125-QCAHSPSWPL_V1_V2_SILICONZ_LITE-3.6510.41
Fixes: d5c65159f289 ("ath11k: driver for Qualcomm IEEE 802.11ax devices") Cc: stable@vger.kernel.org # 5.6 Signed-off-by: Johan Hovold johan+linaro@kernel.org Reviewed-by: Baochen Qiang quic_bqiang@quicinc.com Link: https://patch.msgid.link/20250604143457.26032-5-johan+linaro@kernel.org Signed-off-by: Jeff Johnson jeff.johnson@oss.qualcomm.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/net/wireless/ath/ath11k/hal.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-)
--- a/drivers/net/wireless/ath/ath11k/hal.c +++ b/drivers/net/wireless/ath/ath11k/hal.c @@ -862,7 +862,11 @@ void ath11k_hal_srng_access_end(struct a if (srng->ring_dir == HAL_SRNG_DIR_SRC) { srng->u.src_ring.last_tp = *(volatile u32 *)srng->u.src_ring.tp_addr; - *srng->u.src_ring.hp_addr = srng->u.src_ring.hp; + /* Make sure descriptor is written before updating the + * head pointer. + */ + dma_wmb(); + WRITE_ONCE(*srng->u.src_ring.hp_addr, srng->u.src_ring.hp); } else { srng->u.dst_ring.last_hp = *srng->u.dst_ring.hp_addr; *srng->u.dst_ring.tp_addr = srng->u.dst_ring.tp; @@ -871,6 +875,10 @@ void ath11k_hal_srng_access_end(struct a if (srng->ring_dir == HAL_SRNG_DIR_SRC) { srng->u.src_ring.last_tp = *(volatile u32 *)srng->u.src_ring.tp_addr; + /* Assume implementation use an MMIO write accessor + * which has the required wmb() so that the descriptor + * is written before the updating the head pointer. + */ ath11k_hif_write32(ab, (unsigned long)srng->u.src_ring.hp_addr - (unsigned long)ab->mem,
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Johan Hovold johan+linaro@kernel.org
commit aa6956150f820e6a6deba44be325ddfcb5b10f88 upstream.
Add the missing memory barriers to make sure that destination ring descriptors are read before updating the tail pointer (and passing ownership to the device) to avoid memory corruption on weakly ordered architectures like aarch64 when the ring is full.
Tested-on: WCN6855 hw2.1 WLAN.HSP.1.1-03125-QCAHSPSWPL_V1_V2_SILICONZ_LITE-3.6510.41
Fixes: d5c65159f289 ("ath11k: driver for Qualcomm IEEE 802.11ax devices") Cc: stable@vger.kernel.org # 5.6 Signed-off-by: Johan Hovold johan+linaro@kernel.org Reviewed-by: Baochen Qiang quic_bqiang@quicinc.com Link: https://patch.msgid.link/20250604143457.26032-6-johan+linaro@kernel.org Signed-off-by: Jeff Johnson jeff.johnson@oss.qualcomm.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/net/wireless/ath/ath11k/hal.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-)
--- a/drivers/net/wireless/ath/ath11k/hal.c +++ b/drivers/net/wireless/ath/ath11k/hal.c @@ -854,7 +854,6 @@ void ath11k_hal_srng_access_end(struct a { lockdep_assert_held(&srng->lock);
- /* TODO: See if we need a write memory barrier here */ if (srng->flags & HAL_SRNG_FLAGS_LMAC_RING) { /* For LMAC rings, ring pointer updates are done through FW and * hence written to a shared memory location that is read by FW @@ -869,7 +868,11 @@ void ath11k_hal_srng_access_end(struct a WRITE_ONCE(*srng->u.src_ring.hp_addr, srng->u.src_ring.hp); } else { srng->u.dst_ring.last_hp = *srng->u.dst_ring.hp_addr; - *srng->u.dst_ring.tp_addr = srng->u.dst_ring.tp; + /* Make sure descriptor is read before updating the + * tail pointer. + */ + dma_mb(); + WRITE_ONCE(*srng->u.dst_ring.tp_addr, srng->u.dst_ring.tp); } } else { if (srng->ring_dir == HAL_SRNG_DIR_SRC) { @@ -885,6 +888,10 @@ void ath11k_hal_srng_access_end(struct a srng->u.src_ring.hp); } else { srng->u.dst_ring.last_hp = *srng->u.dst_ring.hp_addr; + /* Make sure descriptor is read before updating the + * tail pointer. + */ + mb(); ath11k_hif_write32(ab, (unsigned long)srng->u.dst_ring.tp_addr - (unsigned long)ab->mem,
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Laurentiu Mihalcea laurentiu.mihalcea@nxp.com
commit 65c6f742ab14ab1a2679fba72b82dcc0289d96f1 upstream.
As per the i.MX93 TRM, section 67.3.2.1 "MOD register update", the value of the TPM counter does NOT get updated when writing MOD.MOD unless SC.CMOD != 0. Therefore, with the current code, assuming the following sequence:
1) pwm_disable() 2) pwm_apply_might_sleep() /* period is changed here */ 3) pwm_enable()
and assuming only one channel is active, if CNT.COUNT is higher than the MOD.MOD value written during the pwm_apply_might_sleep() call then, when re-enabling the PWM during pwm_enable(), the counter will end up resetting after UINT32_MAX - CNT.COUNT + MOD.MOD cycles instead of MOD.MOD cycles as normally expected.
Fix this problem by forcing a reset of the TPM counter before MOD.MOD is written.
Fixes: 738a1cfec2ed ("pwm: Add i.MX TPM PWM driver support") Cc: stable@vger.kernel.org Signed-off-by: Laurentiu Mihalcea laurentiu.mihalcea@nxp.com Link: https://lore.kernel.org/r/20250728194144.22884-1-laurentiumihalcea111@gmail.... Signed-off-by: Uwe Kleine-König ukleinek@kernel.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/pwm/pwm-imx-tpm.c | 9 +++++++++ 1 file changed, 9 insertions(+)
--- a/drivers/pwm/pwm-imx-tpm.c +++ b/drivers/pwm/pwm-imx-tpm.c @@ -205,6 +205,15 @@ static int pwm_imx_tpm_apply_hw(struct p writel(val, tpm->base + PWM_IMX_TPM_SC);
/* + * if the counter is disabled (CMOD == 0), programming the new + * period length (MOD) will not reset the counter (CNT). If + * CNT.COUNT happens to be bigger than the new MOD value then + * the counter will end up being reset way too late. Therefore, + * manually reset it to 0. + */ + if (!cmod) + writel(0x0, tpm->base + PWM_IMX_TPM_CNT); + /* * set period count: * if the PWM is disabled (CMOD[1:0] = 2b00), then MOD register * is updated when MOD register is written.
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Uwe Kleine-König u.kleine-koenig@baylibre.com
commit 704d918341c378c5f9505dfdf32d315e256d3846 upstream.
Stop handling the clocks in pwm_mediatek_enable() and pwm_mediatek_disable(). This is a preparing change for the next commit that requires that clocks and the enable bit are handled separately.
Also move these two functions a bit further up in the source file to make them usable in pwm_mediatek_config(), which is needed in the next commit, too.
Signed-off-by: Uwe Kleine-König u.kleine-koenig@baylibre.com Reviewed-by: AngeloGioacchino Del Regno angelogioacchino.delregno@collabora.com Link: https://lore.kernel.org/r/55c94fe2917ece152ee1e998f4675642a7716f13.175371797... Cc: stable@vger.kernel.org Signed-off-by: Uwe Kleine-König ukleinek@kernel.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/pwm/pwm-mediatek.c | 60 +++++++++++++++++++++------------------------ 1 file changed, 28 insertions(+), 32 deletions(-)
--- a/drivers/pwm/pwm-mediatek.c +++ b/drivers/pwm/pwm-mediatek.c @@ -115,6 +115,26 @@ static inline void pwm_mediatek_writel(s writel(value, chip->regs + chip->soc->reg_offset[num] + offset); }
+static void pwm_mediatek_enable(struct pwm_chip *chip, struct pwm_device *pwm) +{ + struct pwm_mediatek_chip *pc = to_pwm_mediatek_chip(chip); + u32 value; + + value = readl(pc->regs); + value |= BIT(pwm->hwpwm); + writel(value, pc->regs); +} + +static void pwm_mediatek_disable(struct pwm_chip *chip, struct pwm_device *pwm) +{ + struct pwm_mediatek_chip *pc = to_pwm_mediatek_chip(chip); + u32 value; + + value = readl(pc->regs); + value &= ~BIT(pwm->hwpwm); + writel(value, pc->regs); +} + static int pwm_mediatek_config(struct pwm_chip *chip, struct pwm_device *pwm, int duty_ns, int period_ns) { @@ -177,35 +197,6 @@ out: return ret; }
-static int pwm_mediatek_enable(struct pwm_chip *chip, struct pwm_device *pwm) -{ - struct pwm_mediatek_chip *pc = to_pwm_mediatek_chip(chip); - u32 value; - int ret; - - ret = pwm_mediatek_clk_enable(chip, pwm); - if (ret < 0) - return ret; - - value = readl(pc->regs); - value |= BIT(pwm->hwpwm); - writel(value, pc->regs); - - return 0; -} - -static void pwm_mediatek_disable(struct pwm_chip *chip, struct pwm_device *pwm) -{ - struct pwm_mediatek_chip *pc = to_pwm_mediatek_chip(chip); - u32 value; - - value = readl(pc->regs); - value &= ~BIT(pwm->hwpwm); - writel(value, pc->regs); - - pwm_mediatek_clk_disable(chip, pwm); -} - static int pwm_mediatek_apply(struct pwm_chip *chip, struct pwm_device *pwm, const struct pwm_state *state) { @@ -215,8 +206,10 @@ static int pwm_mediatek_apply(struct pwm return -EINVAL;
if (!state->enabled) { - if (pwm->state.enabled) + if (pwm->state.enabled) { pwm_mediatek_disable(chip, pwm); + pwm_mediatek_clk_disable(chip, pwm); + }
return 0; } @@ -225,8 +218,11 @@ static int pwm_mediatek_apply(struct pwm if (err) return err;
- if (!pwm->state.enabled) - err = pwm_mediatek_enable(chip, pwm); + if (!pwm->state.enabled) { + err = pwm_mediatek_clk_enable(chip, pwm); + if (!err) + pwm_mediatek_enable(chip, pwm); + }
return err; }
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Uwe Kleine-König u.kleine-koenig@baylibre.com
commit f21d136caf8171f94159d975ea4620c164431bd9 upstream.
The period generated by the hardware is
(PWMDWIDTH + 1) << CLKDIV) / freq
according to my tests with a signal analyser and also the documentation.
The current algorithm doesn't consider the `+ 1` part and so configures slightly too high periods. The same issue exists for the duty cycle setting. So subtract 1 from both the register values for period and duty cycle. If period is 0, bail out, if duty_cycle is 0, just disable the PWM which results in a constant low output.
Fixes: caf065f8fd58 ("pwm: Add MediaTek PWM support") Signed-off-by: Uwe Kleine-König u.kleine-koenig@baylibre.com Reviewed-by: AngeloGioacchino Del Regno angelogioacchino.delregno@collabora.com Link: https://lore.kernel.org/r/6d1fa87a76f8020bfe3171529b8e19baffceab10.175371797... Cc: stable@vger.kernel.org Signed-off-by: Uwe Kleine-König ukleinek@kernel.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/pwm/pwm-mediatek.c | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-)
--- a/drivers/pwm/pwm-mediatek.c +++ b/drivers/pwm/pwm-mediatek.c @@ -164,7 +164,10 @@ static int pwm_mediatek_config(struct pw do_div(resolution, clk_rate);
cnt_period = DIV_ROUND_CLOSEST_ULL((u64)period_ns * 1000, resolution); - while (cnt_period > 8191) { + if (!cnt_period) + return -EINVAL; + + while (cnt_period > 8192) { resolution *= 2; clkdiv++; cnt_period = DIV_ROUND_CLOSEST_ULL((u64)period_ns * 1000, @@ -187,9 +190,16 @@ static int pwm_mediatek_config(struct pw }
cnt_duty = DIV_ROUND_CLOSEST_ULL((u64)duty_ns * 1000, resolution); + pwm_mediatek_writel(pc, pwm->hwpwm, PWMCON, BIT(15) | clkdiv); - pwm_mediatek_writel(pc, pwm->hwpwm, reg_width, cnt_period); - pwm_mediatek_writel(pc, pwm->hwpwm, reg_thres, cnt_duty); + pwm_mediatek_writel(pc, pwm->hwpwm, reg_width, cnt_period - 1); + + if (cnt_duty) { + pwm_mediatek_writel(pc, pwm->hwpwm, reg_thres, cnt_duty - 1); + pwm_mediatek_enable(chip, pwm); + } else { + pwm_mediatek_disable(chip, pwm); + }
out: pwm_mediatek_clk_disable(chip, pwm); @@ -218,11 +228,8 @@ static int pwm_mediatek_apply(struct pwm if (err) return err;
- if (!pwm->state.enabled) { + if (!pwm->state.enabled) err = pwm_mediatek_clk_enable(chip, pwm); - if (!err) - pwm_mediatek_enable(chip, pwm); - }
return err; }
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Tim Harvey tharvey@gateworks.com
commit 9c62e2282900332c8b711d9f9e37af369a8ef71b upstream.
The Linux hwmon sysfs API values for pwmX_auto_pointY_pwm represent an integer value between 0 (0%) to 255 (100%) and the pwmX_auto_pointY_temp represent millidegrees Celcius.
Commit a6d80df47ee2 ("hwmon: (gsc-hwmon) fix fan pwm temperature scaling") properly addressed the incorrect scaling in the pwm_auto_point_temp_store implementation but erroneously scaled the pwm_auto_point_pwm_show (pwm value) instead of the pwm_auto_point_temp_show (temp value) resulting in: # cat /sys/class/hwmon/hwmon0/pwm1_auto_point6_pwm 25500 # cat /sys/class/hwmon/hwmon0/pwm1_auto_point6_temp 4500
Fix the scaling of these attributes: # cat /sys/class/hwmon/hwmon0/pwm1_auto_point6_pwm 255 # cat /sys/class/hwmon/hwmon0/pwm1_auto_point6_temp 45000
Fixes: a6d80df47ee2 ("hwmon: (gsc-hwmon) fix fan pwm temperature scaling") Cc: stable@vger.kernel.org Signed-off-by: Tim Harvey tharvey@gateworks.com Link: https://lore.kernel.org/r/20250718200259.1840792-1-tharvey@gateworks.com Signed-off-by: Guenter Roeck linux@roeck-us.net Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/hwmon/gsc-hwmon.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
--- a/drivers/hwmon/gsc-hwmon.c +++ b/drivers/hwmon/gsc-hwmon.c @@ -64,7 +64,7 @@ static ssize_t pwm_auto_point_temp_show( return ret;
ret = regs[0] | regs[1] << 8; - return sprintf(buf, "%d\n", ret * 10); + return sprintf(buf, "%d\n", ret * 100); }
static ssize_t pwm_auto_point_temp_store(struct device *dev, @@ -99,7 +99,7 @@ static ssize_t pwm_auto_point_pwm_show(s { struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
- return sprintf(buf, "%d\n", 255 * (50 + (attr->index * 10))); + return sprintf(buf, "%d\n", 255 * (50 + (attr->index * 10)) / 100); }
static SENSOR_DEVICE_ATTR_RO(pwm1_auto_point1_pwm, pwm_auto_point_pwm, 0);
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Michael Walle mwalle@kernel.org
commit 2e3a7476ec3989e77270b9481e76e137824b17c0 upstream.
Commit ff67592cbdfc ("mtd: spi-nor: Introduce spi_nor_set_mtd_info()") moved all initialization of the mtd fields at the end of spi_nor_scan(). Normally, the mtd info is only needed for the mtd ops on the device, with one exception: spi_nor_try_unlock_all(), which will also make use of the mtd->size parameter. With that commit, the size will always be zero because it is not initialized. Fix that by not using the size of the mtd_info struct, but use the size from struct spi_nor_flash_parameter.
Fixes: ff67592cbdfc ("mtd: spi-nor: Introduce spi_nor_set_mtd_info()") Cc: stable@vger.kernel.org Reported-by: Jean-Marc Ranger jmranger@hotmail.com Closes: https://lore.kernel.org/all/DM6PR06MB561177323DC5207E34AF2A06C547A@DM6PR06MB... Tested-by: Jean-Marc Ranger jmranger@hotmail.com Signed-off-by: Michael Walle mwalle@kernel.org Reviewed-by: Pratyush Yadav pratyush@kernel.org Signed-off-by: Pratyush Yadav pratyush@kernel.org Link: https://lore.kernel.org/r/20250701140426.2355182-1-mwalle@kernel.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/mtd/spi-nor/swp.c | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-)
--- a/drivers/mtd/spi-nor/swp.c +++ b/drivers/mtd/spi-nor/swp.c @@ -56,7 +56,6 @@ static u64 spi_nor_get_min_prot_length_s static void spi_nor_get_locked_range_sr(struct spi_nor *nor, u8 sr, loff_t *ofs, u64 *len) { - struct mtd_info *mtd = &nor->mtd; u64 min_prot_len; u8 mask = spi_nor_get_sr_bp_mask(nor); u8 tb_mask = spi_nor_get_sr_tb_mask(nor); @@ -77,13 +76,13 @@ static void spi_nor_get_locked_range_sr( min_prot_len = spi_nor_get_min_prot_length_sr(nor); *len = min_prot_len << (bp - 1);
- if (*len > mtd->size) - *len = mtd->size; + if (*len > nor->params->size) + *len = nor->params->size;
if (nor->flags & SNOR_F_HAS_SR_TB && sr & tb_mask) *ofs = 0; else - *ofs = mtd->size - *len; + *ofs = nor->params->size - *len; }
/* @@ -158,7 +157,6 @@ static bool spi_nor_is_unlocked_sr(struc */ static int spi_nor_sr_lock(struct spi_nor *nor, loff_t ofs, u64 len) { - struct mtd_info *mtd = &nor->mtd; u64 min_prot_len; int ret, status_old, status_new; u8 mask = spi_nor_get_sr_bp_mask(nor); @@ -183,7 +181,7 @@ static int spi_nor_sr_lock(struct spi_no can_be_bottom = false;
/* If anything above us is unlocked, we can't use 'top' protection */ - if (!spi_nor_is_locked_sr(nor, ofs + len, mtd->size - (ofs + len), + if (!spi_nor_is_locked_sr(nor, ofs + len, nor->params->size - (ofs + len), status_old)) can_be_top = false;
@@ -195,11 +193,11 @@ static int spi_nor_sr_lock(struct spi_no
/* lock_len: length of region that should end up locked */ if (use_top) - lock_len = mtd->size - ofs; + lock_len = nor->params->size - ofs; else lock_len = ofs + len;
- if (lock_len == mtd->size) { + if (lock_len == nor->params->size) { val = mask; } else { min_prot_len = spi_nor_get_min_prot_length_sr(nor); @@ -248,7 +246,6 @@ static int spi_nor_sr_lock(struct spi_no */ static int spi_nor_sr_unlock(struct spi_nor *nor, loff_t ofs, u64 len) { - struct mtd_info *mtd = &nor->mtd; u64 min_prot_len; int ret, status_old, status_new; u8 mask = spi_nor_get_sr_bp_mask(nor); @@ -273,7 +270,7 @@ static int spi_nor_sr_unlock(struct spi_ can_be_top = false;
/* If anything above us is locked, we can't use 'bottom' protection */ - if (!spi_nor_is_unlocked_sr(nor, ofs + len, mtd->size - (ofs + len), + if (!spi_nor_is_unlocked_sr(nor, ofs + len, nor->params->size - (ofs + len), status_old)) can_be_bottom = false;
@@ -285,7 +282,7 @@ static int spi_nor_sr_unlock(struct spi_
/* lock_len: length of region that should remain locked */ if (use_top) - lock_len = mtd->size - (ofs + len); + lock_len = nor->params->size - (ofs + len); else lock_len = ofs;
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Gabor Juhos j4g8y7@gmail.com
commit 091d9e35b85b0f8f7e1c73535299f91364a5c73a upstream.
Since commit 3d1f08b032dc ("mtd: spinand: Use the external ECC engine logic") the spinand_write_page() function ignores the errors returned by spinand_wait(). Change the code to propagate those up to the stack as it was done before the offending change.
Cc: stable@vger.kernel.org Fixes: 3d1f08b032dc ("mtd: spinand: Use the external ECC engine logic") Signed-off-by: Gabor Juhos j4g8y7@gmail.com Signed-off-by: Miquel Raynal miquel.raynal@bootlin.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/mtd/nand/spi/core.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-)
--- a/drivers/mtd/nand/spi/core.c +++ b/drivers/mtd/nand/spi/core.c @@ -688,7 +688,10 @@ int spinand_write_page(struct spinand_de SPINAND_WRITE_INITIAL_DELAY_US, SPINAND_WRITE_POLL_DELAY_US, &status); - if (!ret && (status & STATUS_PROG_FAILED)) + if (ret) + return ret; + + if (status & STATUS_PROG_FAILED) return -EIO;
return nand_ecc_finish_io_req(nand, (struct nand_page_io_req *)req);
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Thomas Fourier fourier.thomas@gmail.com
commit 6c4dab38431fee3d39a841d66ba6f2890b31b005 upstream.
The DMA map functions can fail and should be tested for errors.
Fixes: 4774fb0a48aa ("mtd: nand/fsmc: Add DMA support") Cc: stable@vger.kernel.org Signed-off-by: Thomas Fourier fourier.thomas@gmail.com Rule: add Link: https://lore.kernel.org/stable/20250702065806.20983-2-fourier.thomas%40gmail... Signed-off-by: Miquel Raynal miquel.raynal@bootlin.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/mtd/nand/raw/fsmc_nand.c | 2 ++ 1 file changed, 2 insertions(+)
--- a/drivers/mtd/nand/raw/fsmc_nand.c +++ b/drivers/mtd/nand/raw/fsmc_nand.c @@ -503,6 +503,8 @@ static int dma_xfer(struct fsmc_nand_dat
dma_dev = chan->device; dma_addr = dma_map_single(dma_dev->dev, buffer, len, direction); + if (dma_mapping_error(dma_dev->dev, dma_addr)) + return -EINVAL;
if (direction == DMA_TO_DEVICE) { dma_src = dma_addr;
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Thomas Fourier fourier.thomas@gmail.com
commit 79e441ee47949376e3bc20f085cf017b70523d0f upstream.
The DMA map functions can fail and should be tested for errors.
Fixes: d8701fe890ec ("mtd: rawnand: renesas: Add new NAND controller driver") Cc: stable@vger.kernel.org Signed-off-by: Thomas Fourier fourier.thomas@gmail.com Signed-off-by: Miquel Raynal miquel.raynal@bootlin.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/mtd/nand/raw/renesas-nand-controller.c | 6 ++++++ 1 file changed, 6 insertions(+)
--- a/drivers/mtd/nand/raw/renesas-nand-controller.c +++ b/drivers/mtd/nand/raw/renesas-nand-controller.c @@ -426,6 +426,9 @@ static int rnandc_read_page_hw_ecc(struc /* Configure DMA */ dma_addr = dma_map_single(rnandc->dev, rnandc->buf, mtd->writesize, DMA_FROM_DEVICE); + if (dma_mapping_error(rnandc->dev, dma_addr)) + return -ENOMEM; + writel(dma_addr, rnandc->regs + DMA_ADDR_LOW_REG); writel(mtd->writesize, rnandc->regs + DMA_CNT_REG); writel(DMA_TLVL_MAX, rnandc->regs + DMA_TLVL_REG); @@ -606,6 +609,9 @@ static int rnandc_write_page_hw_ecc(stru /* Configure DMA */ dma_addr = dma_map_single(rnandc->dev, (void *)rnandc->buf, mtd->writesize, DMA_TO_DEVICE); + if (dma_mapping_error(rnandc->dev, dma_addr)) + return -ENOMEM; + writel(dma_addr, rnandc->regs + DMA_ADDR_LOW_REG); writel(mtd->writesize, rnandc->regs + DMA_CNT_REG); writel(DMA_TLVL_MAX, rnandc->regs + DMA_TLVL_REG);
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Dmitry Torokhov dmitry.torokhov@gmail.com
commit 92ab1e41569416c639643cd75eea2379190a65f2 upstream.
Do not use "mtk-pmic-keys" when creating sub-device for the keypad to make sure the keypad driver will only bind to the sub-device if it has support for the variant/has matching compatible.
Cc: stable@vger.kernel.org Fixes: 6e31bb8d3a63 ("mfd: mt6397: Add initial support for MT6328") Fixes: de58cee8c6b8 ("mfd: mt6397-core: Add MT6357 PMIC support") Fixes: 4a901e305011 ("mfd: mt6397-core: Add resources for PMIC keys for MT6359") Reported-by: Louis-Alexis Eyraud louisalexis.eyraud@collabora.com Signed-off-by: Dmitry Torokhov dmitry.torokhov@gmail.com Tested-by: Louis-Alexis Eyraud louisalexis.eyraud@collabora.com # on Link: https://lore.kernel.org/r/r4k3pgd3ew3ypne7ernxuzwgniiyvzosbce4cfajbcu7equblt... Signed-off-by: Lee Jones lee@kernel.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/mfd/mt6397-core.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-)
--- a/drivers/mfd/mt6397-core.c +++ b/drivers/mfd/mt6397-core.c @@ -136,7 +136,7 @@ static const struct mfd_cell mt6323_devs .name = "mt6323-led", .of_compatible = "mediatek,mt6323-led" }, { - .name = "mtk-pmic-keys", + .name = "mt6323-keys", .num_resources = ARRAY_SIZE(mt6323_keys_resources), .resources = mt6323_keys_resources, .of_compatible = "mediatek,mt6323-keys" @@ -153,7 +153,7 @@ static const struct mfd_cell mt6328_devs .name = "mt6328-regulator", .of_compatible = "mediatek,mt6328-regulator" }, { - .name = "mtk-pmic-keys", + .name = "mt6328-keys", .num_resources = ARRAY_SIZE(mt6328_keys_resources), .resources = mt6328_keys_resources, .of_compatible = "mediatek,mt6328-keys" @@ -175,7 +175,7 @@ static const struct mfd_cell mt6357_devs .name = "mt6357-sound", .of_compatible = "mediatek,mt6357-sound" }, { - .name = "mtk-pmic-keys", + .name = "mt6357-keys", .num_resources = ARRAY_SIZE(mt6357_keys_resources), .resources = mt6357_keys_resources, .of_compatible = "mediatek,mt6357-keys" @@ -196,7 +196,7 @@ static const struct mfd_cell mt6331_mt63 .name = "mt6332-regulator", .of_compatible = "mediatek,mt6332-regulator" }, { - .name = "mtk-pmic-keys", + .name = "mt6331-keys", .num_resources = ARRAY_SIZE(mt6331_keys_resources), .resources = mt6331_keys_resources, .of_compatible = "mediatek,mt6331-keys" @@ -240,7 +240,7 @@ static const struct mfd_cell mt6359_devs }, { .name = "mt6359-sound", }, { - .name = "mtk-pmic-keys", + .name = "mt6359-keys", .num_resources = ARRAY_SIZE(mt6359_keys_resources), .resources = mt6359_keys_resources, .of_compatible = "mediatek,mt6359-keys" @@ -272,7 +272,7 @@ static const struct mfd_cell mt6397_devs .name = "mt6397-pinctrl", .of_compatible = "mediatek,mt6397-pinctrl", }, { - .name = "mtk-pmic-keys", + .name = "mt6397-keys", .num_resources = ARRAY_SIZE(mt6397_keys_resources), .resources = mt6397_keys_resources, .of_compatible = "mediatek,mt6397-keys"
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chi Zhiling chizhiling@kylinos.cn
commit bbcaee20e03ecaeeecba32a703816a0d4502b6c4 upstream.
max_scan in page_cache_next_miss always decreases to zero when no hole is found, causing the return value to be index + 0.
Fix this by preserving the max_scan value throughout the loop.
Jan said "From what I know and have seen in the past, wrong responses from page_cache_next_miss() can lead to readahead window reduction and thus reduced read speeds."
Link: https://lkml.kernel.org/r/20250605054935.2323451-1-chizhiling@163.com Fixes: 901a269ff3d5 ("filemap: fix page_cache_next_miss() when no hole found") Signed-off-by: Chi Zhiling chizhiling@kylinos.cn Reviewed-by: Jan Kara jack@suse.cz Cc: Josef Bacik josef@toxicpanda.com Cc: Matthew Wilcox (Oracle) willy@infradead.org Cc: stable@vger.kernel.org Signed-off-by: Andrew Morton akpm@linux-foundation.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- mm/filemap.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
--- a/mm/filemap.c +++ b/mm/filemap.c @@ -1778,8 +1778,9 @@ pgoff_t page_cache_next_miss(struct addr pgoff_t index, unsigned long max_scan) { XA_STATE(xas, &mapping->i_pages, index); + unsigned long nr = max_scan;
- while (max_scan--) { + while (nr--) { void *entry = xas_next(&xas); if (!entry || xa_is_value(entry)) return xas.xa_index;
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Lukas Wunner lukas@wunner.de
commit 1d60796a62f327cd9e0a6a0865ded7656d2c67f9 upstream.
The PCIe port driver erroneously creates a subdevice for hotplug on ACPI slots which are handled by the ACPI hotplug driver.
Avoid by checking the is_pciehp flag instead of is_hotplug_bridge when deciding whether to create a subdevice. The latter encompasses ACPI slots whereas the former doesn't.
The superfluous subdevice has no real negative impact, it occupies memory and interrupt resources but otherwise just sits there waiting for interrupts from the slot that are never signaled.
Fixes: f8415222837b ("PCI: Use cached copy of PCI_EXP_SLTCAP_HPC bit") Signed-off-by: Lukas Wunner lukas@wunner.de Signed-off-by: Bjorn Helgaas bhelgaas@google.com Cc: stable@vger.kernel.org # v4.7+ Link: https://patch.msgid.link/40d5a5fe8d40595d505949c620a067fa110ee85e.1752390102... Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/pci/pcie/portdrv.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
--- a/drivers/pci/pcie/portdrv.c +++ b/drivers/pci/pcie/portdrv.c @@ -220,7 +220,7 @@ static int get_port_device_capability(st struct pci_host_bridge *host = pci_find_host_bridge(dev->bus); int services = 0;
- if (dev->is_hotplug_bridge && + if (dev->is_pciehp && (pci_pcie_type(dev) == PCI_EXP_TYPE_ROOT_PORT || pci_pcie_type(dev) == PCI_EXP_TYPE_DOWNSTREAM) && (pcie_ports_native || host->native_pcie_hotplug)) {
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jiwei Sun sunjw10@lenovo.com
commit 9989e0ca7462c62f93dbc62f684448aa2efb9226 upstream.
When pcie_failed_link_retrain() fails to retrain, it tries to revert to the previous link speed. However it calculates that speed from the Link Control 2 register without masking out non-speed bits first.
PCIE_LNKCTL2_TLS2SPEED() converts such incorrect values to PCI_SPEED_UNKNOWN (0xff), which in turn causes a WARN splat in pcie_set_target_speed():
pci 0000:00:01.1: [1022:14ed] type 01 class 0x060400 PCIe Root Port pci 0000:00:01.1: broken device, retraining non-functional downstream link at 2.5GT/s pci 0000:00:01.1: retraining failed WARNING: CPU: 1 PID: 1 at drivers/pci/pcie/bwctrl.c:168 pcie_set_target_speed RDX: 0000000000000001 RSI: 00000000000000ff RDI: ffff9acd82efa000 pcie_failed_link_retrain pci_device_add pci_scan_single_device
Mask out the non-speed bits in PCIE_LNKCTL2_TLS2SPEED() and PCIE_LNKCAP_SLS2SPEED() so they don't incorrectly return PCI_SPEED_UNKNOWN.
Fixes: de9a6c8d5dbf ("PCI/bwctrl: Add pcie_set_target_speed() to set PCIe Link Speed") Reported-by: Andrew andreasx0@protonmail.com Closes: https://lore.kernel.org/r/7iNzXbCGpf8yUMJZBQjLdbjPcXrEJqBxy5-bHfppz0ek-h4_-G... Suggested-by: Maciej W. Rozycki macro@orcam.me.uk Suggested-by: Ilpo Järvinen ilpo.jarvinen@linux.intel.com Signed-off-by: Jiwei Sun sunjw10@lenovo.com [bhelgaas: commit log, add details from https://lore.kernel.org/r/1c92ef6bcb314ee6977839b46b393282e4f52e74.175068477...] Signed-off-by: Bjorn Helgaas bhelgaas@google.com Reviewed-by: Ilpo Järvinen ilpo.jarvinen@linux.intel.com Cc: stable@vger.kernel.org # v6.13+ Link: https://patch.msgid.link/20250123055155.22648-2-sjiwei@163.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/pci/pci.h | 32 +++++++++++++++++++------------- 1 file changed, 19 insertions(+), 13 deletions(-)
--- a/drivers/pci/pci.h +++ b/drivers/pci/pci.h @@ -391,12 +391,14 @@ void pci_bus_put(struct pci_bus *bus);
#define PCIE_LNKCAP_SLS2SPEED(lnkcap) \ ({ \ - ((lnkcap) == PCI_EXP_LNKCAP_SLS_64_0GB ? PCIE_SPEED_64_0GT : \ - (lnkcap) == PCI_EXP_LNKCAP_SLS_32_0GB ? PCIE_SPEED_32_0GT : \ - (lnkcap) == PCI_EXP_LNKCAP_SLS_16_0GB ? PCIE_SPEED_16_0GT : \ - (lnkcap) == PCI_EXP_LNKCAP_SLS_8_0GB ? PCIE_SPEED_8_0GT : \ - (lnkcap) == PCI_EXP_LNKCAP_SLS_5_0GB ? PCIE_SPEED_5_0GT : \ - (lnkcap) == PCI_EXP_LNKCAP_SLS_2_5GB ? PCIE_SPEED_2_5GT : \ + u32 lnkcap_sls = (lnkcap) & PCI_EXP_LNKCAP_SLS; \ + \ + (lnkcap_sls == PCI_EXP_LNKCAP_SLS_64_0GB ? PCIE_SPEED_64_0GT : \ + lnkcap_sls == PCI_EXP_LNKCAP_SLS_32_0GB ? PCIE_SPEED_32_0GT : \ + lnkcap_sls == PCI_EXP_LNKCAP_SLS_16_0GB ? PCIE_SPEED_16_0GT : \ + lnkcap_sls == PCI_EXP_LNKCAP_SLS_8_0GB ? PCIE_SPEED_8_0GT : \ + lnkcap_sls == PCI_EXP_LNKCAP_SLS_5_0GB ? PCIE_SPEED_5_0GT : \ + lnkcap_sls == PCI_EXP_LNKCAP_SLS_2_5GB ? PCIE_SPEED_2_5GT : \ PCI_SPEED_UNKNOWN); \ })
@@ -411,13 +413,17 @@ void pci_bus_put(struct pci_bus *bus); PCI_SPEED_UNKNOWN)
#define PCIE_LNKCTL2_TLS2SPEED(lnkctl2) \ - ((lnkctl2) == PCI_EXP_LNKCTL2_TLS_64_0GT ? PCIE_SPEED_64_0GT : \ - (lnkctl2) == PCI_EXP_LNKCTL2_TLS_32_0GT ? PCIE_SPEED_32_0GT : \ - (lnkctl2) == PCI_EXP_LNKCTL2_TLS_16_0GT ? PCIE_SPEED_16_0GT : \ - (lnkctl2) == PCI_EXP_LNKCTL2_TLS_8_0GT ? PCIE_SPEED_8_0GT : \ - (lnkctl2) == PCI_EXP_LNKCTL2_TLS_5_0GT ? PCIE_SPEED_5_0GT : \ - (lnkctl2) == PCI_EXP_LNKCTL2_TLS_2_5GT ? PCIE_SPEED_2_5GT : \ - PCI_SPEED_UNKNOWN) +({ \ + u16 lnkctl2_tls = (lnkctl2) & PCI_EXP_LNKCTL2_TLS; \ + \ + (lnkctl2_tls == PCI_EXP_LNKCTL2_TLS_64_0GT ? PCIE_SPEED_64_0GT : \ + lnkctl2_tls == PCI_EXP_LNKCTL2_TLS_32_0GT ? PCIE_SPEED_32_0GT : \ + lnkctl2_tls == PCI_EXP_LNKCTL2_TLS_16_0GT ? PCIE_SPEED_16_0GT : \ + lnkctl2_tls == PCI_EXP_LNKCTL2_TLS_8_0GT ? PCIE_SPEED_8_0GT : \ + lnkctl2_tls == PCI_EXP_LNKCTL2_TLS_5_0GT ? PCIE_SPEED_5_0GT : \ + lnkctl2_tls == PCI_EXP_LNKCTL2_TLS_2_5GT ? PCIE_SPEED_2_5GT : \ + PCI_SPEED_UNKNOWN); \ +})
/* PCIe speed to Mb/s reduced by encoding overhead */ #define PCIE_SPEED2MBS_ENC(speed) \
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Damien Le Moal dlemoal@kernel.org
commit d79123d79a8154b4318529b7b2ff7e15806f480b upstream.
Doing a list_del() on the epf_group field of struct pci_epf_driver in pci_epf_remove_cfs() is not correct as this field is a list head, not a list entry. This list_del() call triggers a KASAN warning when an endpoint function driver which has a configfs attribute group is torn down:
================================================================== BUG: KASAN: slab-use-after-free in pci_epf_remove_cfs+0x17c/0x198 Write of size 8 at addr ffff00010f4a0d80 by task rmmod/319
CPU: 3 UID: 0 PID: 319 Comm: rmmod Not tainted 6.16.0-rc2 #1 NONE Hardware name: Radxa ROCK 5B (DT) Call trace: show_stack+0x2c/0x84 (C) dump_stack_lvl+0x70/0x98 print_report+0x17c/0x538 kasan_report+0xb8/0x190 __asan_report_store8_noabort+0x20/0x2c pci_epf_remove_cfs+0x17c/0x198 pci_epf_unregister_driver+0x18/0x30 nvmet_pci_epf_cleanup_module+0x24/0x30 [nvmet_pci_epf] __arm64_sys_delete_module+0x264/0x424 invoke_syscall+0x70/0x260 el0_svc_common.constprop.0+0xac/0x230 do_el0_svc+0x40/0x58 el0_svc+0x48/0xdc el0t_64_sync_handler+0x10c/0x138 el0t_64_sync+0x198/0x19c ...
Remove this incorrect list_del() call from pci_epf_remove_cfs().
Fixes: ef1433f717a2 ("PCI: endpoint: Create configfs entry for each pci_epf_device_id table entry") Signed-off-by: Damien Le Moal dlemoal@kernel.org Signed-off-by: Manivannan Sadhasivam mani@kernel.org Reviewed-by: Niklas Cassel cassel@kernel.org Cc: stable@vger.kernel.org Link: https://patch.msgid.link/20250624114544.342159-2-dlemoal@kernel.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/pci/endpoint/pci-epf-core.c | 1 - 1 file changed, 1 deletion(-)
--- a/drivers/pci/endpoint/pci-epf-core.c +++ b/drivers/pci/endpoint/pci-epf-core.c @@ -338,7 +338,6 @@ static void pci_epf_remove_cfs(struct pc mutex_lock(&pci_epf_mutex); list_for_each_entry_safe(group, tmp, &driver->epf_group, group_entry) pci_ep_cfs_remove_epf_group(group); - list_del(&driver->epf_group); mutex_unlock(&pci_epf_mutex); }
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Damien Le Moal dlemoal@kernel.org
commit 910bdb8197f9322790c738bb32feaa11dba26909 upstream.
An endpoint driver configfs attributes group is added to the epf_group list of struct pci_epf_driver by pci_epf_add_cfs() but an added group is not removed from this list when the attribute group is unregistered with pci_ep_cfs_remove_epf_group().
Add the missing list_del() call in pci_ep_cfs_remove_epf_group() to correctly remove the attribute group from the driver list.
With this change, once the loop over all attribute groups in pci_epf_remove_cfs() completes, the driver epf_group list should be empty. Add a WARN_ON() to make sure of that.
Fixes: ef1433f717a2 ("PCI: endpoint: Create configfs entry for each pci_epf_device_id table entry") Signed-off-by: Damien Le Moal dlemoal@kernel.org Signed-off-by: Manivannan Sadhasivam mani@kernel.org Reviewed-by: Niklas Cassel cassel@kernel.org Cc: stable@vger.kernel.org Link: https://patch.msgid.link/20250624114544.342159-3-dlemoal@kernel.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/pci/endpoint/pci-ep-cfs.c | 1 + drivers/pci/endpoint/pci-epf-core.c | 1 + 2 files changed, 2 insertions(+)
--- a/drivers/pci/endpoint/pci-ep-cfs.c +++ b/drivers/pci/endpoint/pci-ep-cfs.c @@ -691,6 +691,7 @@ void pci_ep_cfs_remove_epf_group(struct if (IS_ERR_OR_NULL(group)) return;
+ list_del(&group->group_entry); configfs_unregister_default_group(group); } EXPORT_SYMBOL(pci_ep_cfs_remove_epf_group); --- a/drivers/pci/endpoint/pci-epf-core.c +++ b/drivers/pci/endpoint/pci-epf-core.c @@ -338,6 +338,7 @@ static void pci_epf_remove_cfs(struct pc mutex_lock(&pci_epf_mutex); list_for_each_entry_safe(group, tmp, &driver->epf_group, group_entry) pci_ep_cfs_remove_epf_group(group); + WARN_ON(!list_empty(&driver->epf_group)); mutex_unlock(&pci_epf_mutex); }
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Richard Zhu hongxing.zhu@nxp.com
commit c523fa63ac1d452abeeb4e699560ec3365037f32 upstream.
IMX8MQ_EP has three 64-bit BAR0/2/4 capable and programmable BARs. For IMX8MQ_EP, use imx8q_pcie_epc_features (64-bit BARs 0, 2, 4) instead of imx8m_pcie_epc_features (64-bit BARs 0, 2).
Fixes: 75c2f26da03f ("PCI: imx6: Add i.MX PCIe EP mode support") Signed-off-by: Richard Zhu hongxing.zhu@nxp.com [bhelgaas: add details in subject] Signed-off-by: Bjorn Helgaas bhelgaas@google.com Reviewed-by: Frank Li Frank.Li@nxp.com Cc: stable@vger.kernel.org Link: https://patch.msgid.link/20250708091003.2582846-2-hongxing.zhu@nxp.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/pci/controller/dwc/pci-imx6.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
--- a/drivers/pci/controller/dwc/pci-imx6.c +++ b/drivers/pci/controller/dwc/pci-imx6.c @@ -1912,7 +1912,7 @@ static const struct imx_pcie_drvdata drv .mode_mask[0] = IMX6Q_GPR12_DEVICE_TYPE, .mode_off[1] = IOMUXC_GPR12, .mode_mask[1] = IMX8MQ_GPR12_PCIE2_CTRL_DEVICE_TYPE, - .epc_features = &imx8m_pcie_epc_features, + .epc_features = &imx8q_pcie_epc_features, .init_phy = imx8mq_pcie_init_phy, .enable_ref_clk = imx8mm_pcie_enable_ref_clk, },
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Richard Zhu hongxing.zhu@nxp.com
commit 399444a87acdea5d21c218bc8e9b621fea1cd218 upstream.
For IMX8MM_EP and IMX8MP_EP, add fixed 256-byte BAR 4 and reserved BAR 5 in imx8m_pcie_epc_features.
Fixes: 75c2f26da03f ("PCI: imx6: Add i.MX PCIe EP mode support") Signed-off-by: Richard Zhu hongxing.zhu@nxp.com [bhelgaas: add details in subject] Signed-off-by: Bjorn Helgaas bhelgaas@google.com Reviewed-by: Frank Li Frank.Li@nxp.com Cc: stable@vger.kernel.org Link: https://patch.msgid.link/20250708091003.2582846-3-hongxing.zhu@nxp.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/pci/controller/dwc/pci-imx6.c | 2 ++ 1 file changed, 2 insertions(+)
--- a/drivers/pci/controller/dwc/pci-imx6.c +++ b/drivers/pci/controller/dwc/pci-imx6.c @@ -1385,6 +1385,8 @@ static const struct pci_epc_features imx .msix_capable = false, .bar[BAR_1] = { .type = BAR_RESERVED, }, .bar[BAR_3] = { .type = BAR_RESERVED, }, + .bar[BAR_4] = { .type = BAR_FIXED, .fixed_size = SZ_256, }, + .bar[BAR_5] = { .type = BAR_RESERVED, }, .align = SZ_64K, };
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Richard Zhu hongxing.zhu@nxp.com
commit d31eb217425591e100b475fad6360cd3da2073c6 upstream.
apps_reset corresponds to LTSSM_EN in i.MX7, i.MX8MQ, i.MX8MM and i.MX8MP platforms. Since assertion/de-assertion of apps_reset is done in imx_pcie_ltssm_enable() and imx_pcie_ltssm_disable(), remove it from imx_pcie_assert_core_reset() and imx_pcie_deassert_core_reset().
This also fixes a failure in enumerating the PI7C9X2G608GP (hotplug) chip reliably on i.MX8MM, as reported by Tim.
It should be noted that only i.MX7D, i.MX8MQ, i.MX8MM, and i.MX8MP platforms have the apps_reset logic, so this change doesn't have any effect on other platforms.
Fixes: ef61c7d8d032 ("PCI: imx6: Deassert apps_reset in imx_pcie_deassert_core_reset()") Reported-by: Tim Harvey tharvey@gateworks.com Closes: https://lore.kernel.org/all/CAJ+vNU3ohR2YKTwC4xoYrc1z-neDoH2TTZcMHDy+poj9=jS... Signed-off-by: Richard Zhu hongxing.zhu@nxp.com [mani: reworded commit subject and description] Signed-off-by: Manivannan Sadhasivam mani@kernel.org [bhelgaas: commit log] Signed-off-by: Bjorn Helgaas bhelgaas@google.com Tested-by: Tim Harvey tharvey@gateworks.com # imx8mp-venice-gw74xx (i.MX8MP + hotplug capable switch) Reviewed-by: Frank Li Frank.Li@nxp.com Cc: stable@vger.kernel.org Link: https://patch.msgid.link/20250709033722.2924372-2-hongxing.zhu@nxp.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/pci/controller/dwc/pci-imx6.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-)
--- a/drivers/pci/controller/dwc/pci-imx6.c +++ b/drivers/pci/controller/dwc/pci-imx6.c @@ -860,7 +860,6 @@ static int imx95_pcie_core_reset(struct static void imx_pcie_assert_core_reset(struct imx_pcie *imx_pcie) { reset_control_assert(imx_pcie->pciephy_reset); - reset_control_assert(imx_pcie->apps_reset);
if (imx_pcie->drvdata->core_reset) imx_pcie->drvdata->core_reset(imx_pcie, true); @@ -872,7 +871,6 @@ static void imx_pcie_assert_core_reset(s static int imx_pcie_deassert_core_reset(struct imx_pcie *imx_pcie) { reset_control_deassert(imx_pcie->pciephy_reset); - reset_control_deassert(imx_pcie->apps_reset);
if (imx_pcie->drvdata->core_reset) imx_pcie->drvdata->core_reset(imx_pcie, false); @@ -1247,6 +1245,9 @@ static int imx_pcie_host_init(struct dw_ } }
+ /* Make sure that PCIe LTSSM is cleared */ + imx_pcie_ltssm_disable(dev); + ret = imx_pcie_deassert_core_reset(imx_pcie); if (ret < 0) { dev_err(dev, "pcie deassert core reset failed: %d\n", ret);
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Richard Zhu hongxing.zhu@nxp.com
commit 2e6ea70690ddd1ffa422423fd0d4523e4dfe4b62 upstream.
According to Documentation/PCI/endpoint/pci-endpoint-cfs.rst, the Endpoint controller (EPC) should only start the link when userspace writes '1' to the '/sys/kernel/config/pci_ep/controllers/<EPC>/start' attribute, which ultimately results in calling imx_pcie_start_link() via pci_epc_start_store().
To align with the documented behavior, do not start the link automatically when adding the EP controller.
Fixes: 75c2f26da03f ("PCI: imx6: Add i.MX PCIe EP mode support") Signed-off-by: Richard Zhu hongxing.zhu@nxp.com [mani: reworded commit subject and description] Signed-off-by: Manivannan Sadhasivam mani@kernel.org [bhelgaas: commit log] Signed-off-by: Bjorn Helgaas bhelgaas@google.com Reviewed-by: Frank Li Frank.Li@nxp.com Cc: stable@vger.kernel.org Link: https://patch.msgid.link/20250709033722.2924372-3-hongxing.zhu@nxp.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/pci/controller/dwc/pci-imx6.c | 3 --- 1 file changed, 3 deletions(-)
--- a/drivers/pci/controller/dwc/pci-imx6.c +++ b/drivers/pci/controller/dwc/pci-imx6.c @@ -1468,9 +1468,6 @@ static int imx_add_pcie_ep(struct imx_pc
pci_epc_init_notify(ep->epc);
- /* Start LTSSM. */ - imx_pcie_ltssm_enable(dev); - return 0; }
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Will Deacon will@kernel.org
commit 0dab92484474587b82e8e0455839eaf5ac7bf894 upstream.
When receiving a vsock packet in the guest, only the virtqueue buffer size is validated prior to virtio_vsock_skb_rx_put(). Unfortunately, virtio_vsock_skb_rx_put() uses the length from the packet header as the length argument to skb_put(), potentially resulting in SKB overflow if the host has gone wonky.
Validate the length as advertised by the packet header before calling virtio_vsock_skb_rx_put().
Cc: stable@vger.kernel.org Fixes: 71dc9ec9ac7d ("virtio/vsock: replace virtio_vsock_pkt with sk_buff") Signed-off-by: Will Deacon will@kernel.org Message-Id: 20250717090116.11987-3-will@kernel.org Signed-off-by: Michael S. Tsirkin mst@redhat.com Reviewed-by: Stefano Garzarella sgarzare@redhat.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- net/vmw_vsock/virtio_transport.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-)
--- a/net/vmw_vsock/virtio_transport.c +++ b/net/vmw_vsock/virtio_transport.c @@ -624,8 +624,9 @@ static void virtio_transport_rx_work(str do { virtqueue_disable_cb(vq); for (;;) { + unsigned int len, payload_len; + struct virtio_vsock_hdr *hdr; struct sk_buff *skb; - unsigned int len;
if (!virtio_transport_more_replies(vsock)) { /* Stop rx until the device processes already @@ -642,11 +643,18 @@ static void virtio_transport_rx_work(str vsock->rx_buf_nr--;
/* Drop short/long packets */ - if (unlikely(len < sizeof(struct virtio_vsock_hdr) || + if (unlikely(len < sizeof(*hdr) || len > virtio_vsock_skb_len(skb))) { kfree_skb(skb); continue; } + + hdr = virtio_vsock_hdr(skb); + payload_len = le32_to_cpu(hdr->len); + if (unlikely(payload_len > len - sizeof(*hdr))) { + kfree_skb(skb); + continue; + }
virtio_vsock_skb_rx_put(skb); virtio_transport_deliver_tap_pkt(skb);
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Will Deacon will@kernel.org
commit 10a886aaed293c4db3417951f396827216299e3d upstream.
vhost_vsock_alloc_skb() returns NULL for packets advertising a length larger than VIRTIO_VSOCK_MAX_PKT_BUF_SIZE in the packet header. However, this is only checked once the SKB has been allocated and, if the length in the packet header is zero, the SKB may not be freed immediately.
Hoist the size check before the SKB allocation so that an iovec larger than VIRTIO_VSOCK_MAX_PKT_BUF_SIZE + the header size is rejected outright. The subsequent check on the length field in the header can then simply check that the allocated SKB is indeed large enough to hold the packet.
Cc: stable@vger.kernel.org Fixes: 71dc9ec9ac7d ("virtio/vsock: replace virtio_vsock_pkt with sk_buff") Reviewed-by: Stefano Garzarella sgarzare@redhat.com Signed-off-by: Will Deacon will@kernel.org Message-Id: 20250717090116.11987-2-will@kernel.org Signed-off-by: Michael S. Tsirkin mst@redhat.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/vhost/vsock.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-)
--- a/drivers/vhost/vsock.c +++ b/drivers/vhost/vsock.c @@ -344,6 +344,9 @@ vhost_vsock_alloc_skb(struct vhost_virtq
len = iov_length(vq->iov, out);
+ if (len > VIRTIO_VSOCK_MAX_PKT_BUF_SIZE + VIRTIO_VSOCK_SKB_HEADROOM) + return NULL; + /* len contains both payload and hdr */ skb = virtio_vsock_alloc_skb(len, GFP_KERNEL); if (!skb) @@ -367,8 +370,7 @@ vhost_vsock_alloc_skb(struct vhost_virtq return skb;
/* The pkt is too big or the length in the header is invalid */ - if (payload_len > VIRTIO_VSOCK_MAX_PKT_BUF_SIZE || - payload_len + sizeof(*hdr) > len) { + if (payload_len + sizeof(*hdr) > len) { kfree_skb(skb); return NULL; }
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Kathiravan Thirumoorthy kathiravan.thirumoorthy@oss.qualcomm.com
commit 4a3556b81b99f0c8c0358f7cc6801a62b4538fe2 upstream.
The current configuration used for the IPQ5332 M31 USB PHY fails the Near End High Speed Signal Quality compliance test. To resolve this, update the initialization sequence as specified in the Hardware Design Document.
Fixes: 08e49af50701 ("phy: qcom: Introduce M31 USB PHY driver") Cc: stable@kernel.org Signed-off-by: Kathiravan Thirumoorthy kathiravan.thirumoorthy@oss.qualcomm.com Reviewed-by: Konrad Dybcio konrad.dybcio@oss.qualcomm.com Link: https://lore.kernel.org/r/20250630-ipq5332_hsphy_complaince-v2-1-63621439ebd... Signed-off-by: Vinod Koul vkoul@kernel.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/phy/qualcomm/phy-qcom-m31.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-)
--- a/drivers/phy/qualcomm/phy-qcom-m31.c +++ b/drivers/phy/qualcomm/phy-qcom-m31.c @@ -58,14 +58,16 @@ #define USB2_0_TX_ENABLE BIT(2)
#define USB2PHY_USB_PHY_M31_XCFGI_4 0xc8 - #define HSTX_SLEW_RATE_565PS GENMASK(1, 0) + #define HSTX_SLEW_RATE_400PS GENMASK(2, 0) #define PLL_CHARGING_PUMP_CURRENT_35UA GENMASK(4, 3) #define ODT_VALUE_38_02_OHM GENMASK(7, 6)
#define USB2PHY_USB_PHY_M31_XCFGI_5 0xcc - #define ODT_VALUE_45_02_OHM BIT(2) #define HSTX_PRE_EMPHASIS_LEVEL_0_55MA BIT(0)
+#define USB2PHY_USB_PHY_M31_XCFGI_9 0xdc + #define HSTX_CURRENT_17_1MA_385MV BIT(1) + #define USB2PHY_USB_PHY_M31_XCFGI_11 0xe4 #define XCFG_COARSE_TUNE_NUM BIT(1) #define XCFG_FINE_TUNE_NUM BIT(3) @@ -164,7 +166,7 @@ static struct m31_phy_regs m31_ipq5332_r }, { USB2PHY_USB_PHY_M31_XCFGI_4, - HSTX_SLEW_RATE_565PS | PLL_CHARGING_PUMP_CURRENT_35UA | ODT_VALUE_38_02_OHM, + HSTX_SLEW_RATE_400PS | PLL_CHARGING_PUMP_CURRENT_35UA | ODT_VALUE_38_02_OHM, 0 }, { @@ -174,10 +176,14 @@ static struct m31_phy_regs m31_ipq5332_r }, { USB2PHY_USB_PHY_M31_XCFGI_5, - ODT_VALUE_45_02_OHM | HSTX_PRE_EMPHASIS_LEVEL_0_55MA, + HSTX_PRE_EMPHASIS_LEVEL_0_55MA, 4 }, { + USB2PHY_USB_PHY_M31_XCFGI_9, + HSTX_CURRENT_17_1MA_385MV, + }, + { USB_PHY_UTMI_CTRL5, 0x0, 0
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Xaver Hugl xaver.hugl@kde.org
commit 928587381b54b1b6c62736486b1dc6cb16c568c2 upstream.
With a timeout of only 1 second, my rx 5700XT fails to initialize, so this increases the timeout to 2s.
Closes: https://gitlab.freedesktop.org/drm/amd/-/issues/3697 Signed-off-by: Xaver Hugl xaver.hugl@kde.org Signed-off-by: Alex Deucher alexander.deucher@amd.com (cherry picked from commit 9ed3d7bdf2dcdf1a1196630fab89a124526e9cc2) Cc: stable@vger.kernel.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c @@ -276,7 +276,7 @@ static int amdgpu_discovery_read_binary_ u32 msg;
if (!amdgpu_sriov_vf(adev)) { - /* It can take up to a second for IFWI init to complete on some dGPUs, + /* It can take up to two 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 @@ -284,7 +284,7 @@ static int amdgpu_discovery_read_binary_ * continue. */
- for (i = 0; i < 1000; i++) { + for (i = 0; i < 2000; i++) { msg = RREG32(mmMP0_SMN_C2PMSG_33); if (msg & 0x80000000) break;
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Muhammad Usama Anjum usama.anjum@collabora.com
commit eb3bb145280b6c857a748731a229698e4a7cf37b upstream.
Replace GFP_ATOMIC with GFP_KERNEL for dma_alloc_coherent() calls. This change improves memory allocation reliability during firmware loading, particularly during system resume when memory pressure is high. Because of using GFP_KERNEL, reclaim can happen which can reduce the probability of failure.
Fixes memory allocation failures observed during system resume with fragmented memory conditions.
snd_sof_amd_vangogh 0000:04:00.5: error: failed to load DSP firmware after resume -12
Fixes: 145d7e5ae8f4e ("ASoC: SOF: amd: add option to use sram for data bin loading") Fixes: 7e51a9e38ab20 ("ASoC: SOF: amd: Add fw loader and renoir dsp ops to load firmware") Cc: stable@vger.kernel.org Signed-off-by: Muhammad Usama Anjum usama.anjum@collabora.com Link: https://patch.msgid.link/20250725190254.1081184-1-usama.anjum@collabora.com Signed-off-by: Mark Brown broonie@kernel.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- sound/soc/sof/amd/acp-loader.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
--- a/sound/soc/sof/amd/acp-loader.c +++ b/sound/soc/sof/amd/acp-loader.c @@ -65,7 +65,7 @@ int acp_dsp_block_write(struct snd_sof_d dma_size = page_count * ACP_PAGE_SIZE; adata->bin_buf = dma_alloc_coherent(&pci->dev, dma_size, &adata->sha_dma_addr, - GFP_ATOMIC); + GFP_KERNEL); if (!adata->bin_buf) return -ENOMEM; } @@ -77,7 +77,7 @@ int acp_dsp_block_write(struct snd_sof_d adata->data_buf = dma_alloc_coherent(&pci->dev, ACP_DEFAULT_DRAM_LENGTH, &adata->dma_addr, - GFP_ATOMIC); + GFP_KERNEL); if (!adata->data_buf) return -ENOMEM; } @@ -90,7 +90,7 @@ int acp_dsp_block_write(struct snd_sof_d adata->sram_data_buf = dma_alloc_coherent(&pci->dev, ACP_DEFAULT_SRAM_LENGTH, &adata->sram_dma_addr, - GFP_ATOMIC); + GFP_KERNEL); if (!adata->sram_data_buf) return -ENOMEM; }
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Julian Sun sunjunchao2870@gmail.com
commit 8f5845e0743bf3512b71b3cb8afe06c192d6acc4 upstream.
The commit 245618f8e45f ("block: protect wbt_lat_usec using q->elevator_lock") protected wbt_enable_default() with q->elevator_lock; however, it also placed wbt_enable_default() before blk_queue_flag_set(QUEUE_FLAG_REGISTERED, q);, resulting in wbt failing to be enabled.
Moreover, the protection of wbt_enable_default() by q->elevator_lock was removed in commit 78c271344b6f ("block: move wbt_enable_default() out of queue freezing from sched ->exit()"), so we can directly fix this issue by placing wbt_enable_default() after blk_queue_flag_set(QUEUE_FLAG_REGISTERED, q);.
Additionally, this issue also causes the inability to read the wbt_lat_usec file, and the scenario is as follows:
root@q:/sys/block/sda/queue# cat wbt_lat_usec cat: wbt_lat_usec: Invalid argument
root@q:/data00/sjc/linux# ls /sys/kernel/debug/block/sda/rqos cannot access '/sys/kernel/debug/block/sda/rqos': No such file or directory
root@q:/data00/sjc/linux# find /sys -name wbt /sys/kernel/debug/tracing/events/wbt
After testing with this patch, wbt can be enabled normally.
Signed-off-by: Julian Sun sunjunchao@bytedance.com Cc: stable@vger.kernel.org Fixes: 245618f8e45f ("block: protect wbt_lat_usec using q->elevator_lock") Reviewed-by: Nilay Shroff nilay@linux.ibm.com Reviewed-by: Yu Kuai yukuai3@huawei.com Reviewed-by: Ming Lei ming.lei@redhat.com Link: https://lore.kernel.org/r/20250812154257.57540-1-sunjunchao@bytedance.com Signed-off-by: Jens Axboe axboe@kernel.dk Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- block/blk-sysfs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
--- a/block/blk-sysfs.c +++ b/block/blk-sysfs.c @@ -876,9 +876,9 @@ int blk_register_queue(struct gendisk *d
if (queue_is_mq(q)) elevator_set_default(q); - wbt_enable_default(disk);
blk_queue_flag_set(QUEUE_FLAG_REGISTERED, q); + wbt_enable_default(disk);
/* Now everything is ready and send out KOBJ_ADD uevent */ kobject_uevent(&disk->queue_kobj, KOBJ_ADD);
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chao Yu chao@kernel.org
commit 77de19b6867f2740cdcb6c9c7e50d522b47847a4 upstream.
As Jiaming Zhang reported:
<TASK> __dump_stack lib/dump_stack.c:94 [inline] dump_stack_lvl+0x1c1/0x2a0 lib/dump_stack.c:120 print_address_description mm/kasan/report.c:378 [inline] print_report+0x17e/0x800 mm/kasan/report.c:480 kasan_report+0x147/0x180 mm/kasan/report.c:593 data_blkaddr fs/f2fs/f2fs.h:3053 [inline] f2fs_data_blkaddr fs/f2fs/f2fs.h:3058 [inline] f2fs_get_dnode_of_data+0x1a09/0x1c40 fs/f2fs/node.c:855 f2fs_reserve_block+0x53/0x310 fs/f2fs/data.c:1195 prepare_write_begin fs/f2fs/data.c:3395 [inline] f2fs_write_begin+0xf39/0x2190 fs/f2fs/data.c:3594 generic_perform_write+0x2c7/0x910 mm/filemap.c:4112 f2fs_buffered_write_iter fs/f2fs/file.c:4988 [inline] f2fs_file_write_iter+0x1ec8/0x2410 fs/f2fs/file.c:5216 new_sync_write fs/read_write.c:593 [inline] vfs_write+0x546/0xa90 fs/read_write.c:686 ksys_write+0x149/0x250 fs/read_write.c:738 do_syscall_x64 arch/x86/entry/syscall_64.c:63 [inline] do_syscall_64+0xf3/0x3d0 arch/x86/entry/syscall_64.c:94 entry_SYSCALL_64_after_hwframe+0x77/0x7f
The root cause is in the corrupted image, there is a dnode has the same node id w/ its inode, so during f2fs_get_dnode_of_data(), it tries to access block address in dnode at offset 934, however it parses the dnode as inode node, so that get_dnode_addr() returns 360, then it tries to access page address from 360 + 934 * 4 = 4096 w/ 4 bytes.
To fix this issue, let's add sanity check for node id of all direct nodes during f2fs_get_dnode_of_data().
Cc: stable@kernel.org Reported-by: Jiaming Zhang r772577952@gmail.com Closes: https://groups.google.com/g/syzkaller/c/-ZnaaOOfO3M Signed-off-by: Chao Yu chao@kernel.org Signed-off-by: Jaegeuk Kim jaegeuk@kernel.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- fs/f2fs/node.c | 10 ++++++++++ 1 file changed, 10 insertions(+)
--- a/fs/f2fs/node.c +++ b/fs/f2fs/node.c @@ -816,6 +816,16 @@ int f2fs_get_dnode_of_data(struct dnode_ for (i = 1; i <= level; i++) { bool done = false;
+ if (nids[i] && nids[i] == dn->inode->i_ino) { + err = -EFSCORRUPTED; + f2fs_err_ratelimited(sbi, + "inode mapping table is corrupted, run fsck to fix it, " + "ino:%lu, nid:%u, level:%d, offset:%d", + dn->inode->i_ino, nids[i], level, offset[level]); + set_sbi_flag(sbi, SBI_NEED_FSCK); + goto release_pages; + } + if (!nids[i] && mode == ALLOC_NODE) { /* alloc new node */ if (!f2fs_alloc_nid(sbi, &(nids[i]))) {
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Kathiravan Thirumoorthy kathiravan.thirumoorthy@oss.qualcomm.com
commit 85c34532849dae0fdcf880900ac9d7718a73fd1b upstream.
Update the I2C frequency table to match the recommended values specified in the I2C hardware programming guide. In the current IPQ5424 configuration where 32MHz is the source clock, the I2C bus frequencies do not meet expectations—for instance, 363KHz is achieved instead of the expected 400KHz.
Fixes: 506bb2ab0075 ("i2c: qcom-geni: Support systems with 32MHz serial engine clock") Signed-off-by: Kathiravan Thirumoorthy kathiravan.thirumoorthy@oss.qualcomm.com Cc: stable@vger.kernel.org # v6.13+ Reviewed-by: Mukesh Kumar Savaliya quic_msavaliy@quicinc.com Signed-off-by: Andi Shyti andi.shyti@kernel.org Link: https://lore.kernel.org/r/20250513-i2c-bus-freq-v1-1-9a333ad5757f@oss.qualco... Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/i2c/busses/i2c-qcom-geni.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
--- a/drivers/i2c/busses/i2c-qcom-geni.c +++ b/drivers/i2c/busses/i2c-qcom-geni.c @@ -155,9 +155,9 @@ static const struct geni_i2c_clk_fld gen
/* source_clock = 32 MHz */ static const struct geni_i2c_clk_fld geni_i2c_clk_map_32mhz[] = { - { I2C_MAX_STANDARD_MODE_FREQ, 8, 14, 18, 40 }, - { I2C_MAX_FAST_MODE_FREQ, 4, 3, 11, 20 }, - { I2C_MAX_FAST_MODE_PLUS_FREQ, 2, 3, 6, 15 }, + { I2C_MAX_STANDARD_MODE_FREQ, 8, 14, 18, 38 }, + { I2C_MAX_FAST_MODE_FREQ, 4, 3, 9, 19 }, + { I2C_MAX_FAST_MODE_PLUS_FREQ, 2, 3, 5, 15 }, {} };
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jan Kara jack@suse.cz
commit 6b65028e2b51c023a816eabffea88980fdd5564e upstream.
Commit d279c80e0bac ("iomap: inline iomap_dio_bio_opflags()") has broken the logic in iomap_dio_bio_iter() in a way that when the device does support FUA (or has no writeback cache) and the direct IO happens to freshly allocated or unwritten extents, we will *not* issue fsync after completing direct IO O_SYNC / O_DSYNC write because the IOMAP_DIO_WRITE_THROUGH flag stays mistakenly set. Fix the problem by clearing IOMAP_DIO_WRITE_THROUGH whenever we do not perform FUA write as it was originally intended.
CC: John Garry john.g.garry@oracle.com CC: Ritesh Harjani (IBM) ritesh.list@gmail.com Fixes: d279c80e0bac ("iomap: inline iomap_dio_bio_opflags()") CC: stable@vger.kernel.org Signed-off-by: Jan Kara jack@suse.cz Link: https://lore.kernel.org/20250730102840.20470-2-jack@suse.cz Reviewed-by: Ritesh Harjani (IBM) ritesh.list@gmail.com Reviewed-by: John Garry john.g.garry@oracle.com Reviewed-by: Darrick J. Wong djwong@kernel.org Reviewed-by: Christoph Hellwig hch@lst.de Signed-off-by: Christian Brauner brauner@kernel.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- fs/iomap/direct-io.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-)
--- a/fs/iomap/direct-io.c +++ b/fs/iomap/direct-io.c @@ -368,14 +368,14 @@ static int iomap_dio_bio_iter(struct iom if (iomap->flags & IOMAP_F_SHARED) dio->flags |= IOMAP_DIO_COW;
- if (iomap->flags & IOMAP_F_NEW) { + if (iomap->flags & IOMAP_F_NEW) need_zeroout = true; - } else if (iomap->type == IOMAP_MAPPED) { - if (iomap_dio_can_use_fua(iomap, dio)) - bio_opf |= REQ_FUA; - else - dio->flags &= ~IOMAP_DIO_WRITE_THROUGH; - } + else if (iomap->type == IOMAP_MAPPED && + iomap_dio_can_use_fua(iomap, dio)) + bio_opf |= REQ_FUA; + + if (!(bio_opf & REQ_FUA)) + dio->flags &= ~IOMAP_DIO_WRITE_THROUGH;
/* * We can only do deferred completion for pure overwrites that
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Baokun Li libaokun1@huawei.com
commit 9d98cf4632258720f18265a058e62fde120c0151 upstream.
Both jbd2_log_do_checkpoint() and jbd2_journal_shrink_checkpoint_list() periodically release j_list_lock after processing a batch of buffers to avoid long hold times on the j_list_lock. However, since both functions contend for j_list_lock, the combined time spent waiting and processing can be significant.
jbd2_journal_shrink_checkpoint_list() explicitly calls cond_resched() when need_resched() is true to avoid softlockups during prolonged operations. But jbd2_log_do_checkpoint() only exits its loop when need_resched() is true, relying on potentially sleeping functions like __flush_batch() or wait_on_buffer() to trigger rescheduling. If those functions do not sleep, the kernel may hit a softlockup.
watchdog: BUG: soft lockup - CPU#3 stuck for 156s! [kworker/u129:2:373] CPU: 3 PID: 373 Comm: kworker/u129:2 Kdump: loaded Not tainted 6.6.0+ #10 Hardware name: Huawei TaiShan 2280 /BC11SPCD, BIOS 1.27 06/13/2017 Workqueue: writeback wb_workfn (flush-7:2) pstate: 20000005 (nzCv daif -PAN -UAO -TCO -DIT -SSBS BTYPE=--) pc : native_queued_spin_lock_slowpath+0x358/0x418 lr : jbd2_log_do_checkpoint+0x31c/0x438 [jbd2] Call trace: native_queued_spin_lock_slowpath+0x358/0x418 jbd2_log_do_checkpoint+0x31c/0x438 [jbd2] __jbd2_log_wait_for_space+0xfc/0x2f8 [jbd2] add_transaction_credits+0x3bc/0x418 [jbd2] start_this_handle+0xf8/0x560 [jbd2] jbd2__journal_start+0x118/0x228 [jbd2] __ext4_journal_start_sb+0x110/0x188 [ext4] ext4_do_writepages+0x3dc/0x740 [ext4] ext4_writepages+0xa4/0x190 [ext4] do_writepages+0x94/0x228 __writeback_single_inode+0x48/0x318 writeback_sb_inodes+0x204/0x590 __writeback_inodes_wb+0x54/0xf8 wb_writeback+0x2cc/0x3d8 wb_do_writeback+0x2e0/0x2f8 wb_workfn+0x80/0x2a8 process_one_work+0x178/0x3e8 worker_thread+0x234/0x3b8 kthread+0xf0/0x108 ret_from_fork+0x10/0x20
So explicitly call cond_resched() in jbd2_log_do_checkpoint() to avoid softlockup.
Cc: stable@kernel.org Signed-off-by: Baokun Li libaokun1@huawei.com Link: https://patch.msgid.link/20250812063752.912130-1-libaokun@huaweicloud.com Signed-off-by: Theodore Ts'o tytso@mit.edu Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- fs/jbd2/checkpoint.c | 1 + 1 file changed, 1 insertion(+)
--- a/fs/jbd2/checkpoint.c +++ b/fs/jbd2/checkpoint.c @@ -285,6 +285,7 @@ restart: retry: if (batch_count) __flush_batch(journal, &batch_count); + cond_resched(); spin_lock(&journal->j_list_lock); goto restart; }
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jann Horn jannh@google.com
commit 475356fe2814f2f0b188da8bf0f1fcc579d81272 upstream.
The kunit test is using assignments to "static volatile void *kasan_ptr_result" to prevent elision of memory loads, but that's not working: In this variable definition, the "volatile" applies to the "void", not to the pointer. To make "volatile" apply to the pointer as intended, it must follow after the "*".
This makes the kasan_memchr test pass again on my system. The kasan_strings test is still failing because all the definitions of load_unaligned_zeropad() are lacking explicit instrumentation hooks and ASAN does not instrument asm() memory operands.
Link: https://lkml.kernel.org/r/20250728-kasan-kunit-fix-volatile-v1-1-e7157c9af82... Fixes: 5f1c8108e7ad ("mm:kasan: fix sparse warnings: Should it be static?") Signed-off-by: Jann Horn jannh@google.com Cc: Alexander Potapenko glider@google.com Cc: Andrey Konovalov andreyknvl@gmail.com Cc: Andrey Ryabinin ryabinin.a.a@gmail.com Cc: Dmitriy Vyukov dvyukov@google.com Cc: Jann Horn jannh@google.com Cc: Nihar Chaithanya niharchaithanya@gmail.com Cc: Vincenzo Frascino vincenzo.frascino@arm.com Cc: stable@vger.kernel.org Signed-off-by: Andrew Morton akpm@linux-foundation.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- mm/kasan/kasan_test_c.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
--- a/mm/kasan/kasan_test_c.c +++ b/mm/kasan/kasan_test_c.c @@ -47,7 +47,7 @@ static struct { * Some tests use these global variables to store return values from function * calls that could otherwise be eliminated by the compiler as dead code. */ -static volatile void *kasan_ptr_result; +static void *volatile kasan_ptr_result; static volatile int kasan_int_result;
/* Probe for console output: obtains test_status lines of interest. */
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Thomas Weißschuh thomas.weissschuh@linutronix.de
commit 936599ca514973d44a766b7376c6bbdc96b6a8cc upstream.
The userprogs infrastructure does not expect clang being used with GNU ld and in that case uses /usr/bin/ld for linking, not the configured $(LD). This fallback is problematic as it will break when cross-compiling. Mixing clang and GNU ld is used for example when building for SPARC64, as ld.lld is not sufficient; see Documentation/kbuild/llvm.rst.
Relax the check around --ld-path so it gets used for all linkers.
Fixes: dfc1b168a8c4 ("kbuild: userprogs: use correct lld when linking through clang") Cc: stable@vger.kernel.org Signed-off-by: Thomas Weißschuh thomas.weissschuh@linutronix.de Reviewed-by: Nathan Chancellor nathan@kernel.org Signed-off-by: Masahiro Yamada masahiroy@kernel.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
--- a/Makefile +++ b/Makefile @@ -1134,7 +1134,7 @@ KBUILD_USERCFLAGS += $(filter -m32 -m64 KBUILD_USERLDFLAGS += $(filter -m32 -m64 --target=%, $(KBUILD_CPPFLAGS) $(KBUILD_CFLAGS))
# userspace programs are linked via the compiler, use the correct linker -ifeq ($(CONFIG_CC_IS_CLANG)$(CONFIG_LD_IS_LLD),yy) +ifdef CONFIG_CC_IS_CLANG KBUILD_USERLDFLAGS += --ld-path=$(LD) endif
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Simon Richter Simon.Richter@hogyros.de
commit 022906afdf90327bce33d52fb4fb41b6c7d618fb upstream.
This driver, for the time being, assumes that the kernel page size is 4kB, so it fails on loong64 and aarch64 with 16kB pages, and ppc64el with 64kB pages.
Signed-off-by: Simon Richter Simon.Richter@hogyros.de Reviewed-by: Thomas Hellström thomas.hellstrom@linux.intel.com Fixes: dd08ebf6c352 ("drm/xe: Introduce a new DRM driver for Intel GPUs") Cc: stable@vger.kernel.org # v6.8+ Signed-off-by: Thomas Hellström thomas.hellstrom@linux.intel.com Link: https://lore.kernel.org/r/20250802024152.3021-1-Simon.Richter@hogyros.de (cherry picked from commit 0521a868222ffe636bf202b6e9d29292c1e19c62) Signed-off-by: Rodrigo Vivi rodrigo.vivi@intel.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/gpu/drm/xe/Kconfig | 1 + 1 file changed, 1 insertion(+)
--- a/drivers/gpu/drm/xe/Kconfig +++ b/drivers/gpu/drm/xe/Kconfig @@ -5,6 +5,7 @@ config DRM_XE depends on KUNIT || !KUNIT depends on INTEL_VSEC || !INTEL_VSEC depends on X86_PLATFORM_DEVICES || !(X86 && ACPI) + depends on PAGE_SIZE_4KB || COMPILE_TEST || BROKEN select INTERVAL_TREE # we need shmfs for the swappable backing store, and in particular # the shmem_readpage() which depends upon tmpfs
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Aleksa Sarai cyphar@cyphar.com
commit 9308366f062129d52e0ee3f7a019f7dd41db33df upstream.
As described in commit 7a54947e727b ('Merge patch series "fs: allow changing idmappings"'), open_tree_attr(2) was necessary in order to allow for a detached mount to be created and have its idmappings changed without the risk of any racing threads operating on it. For this reason, mount_setattr(2) still does not allow for id-mappings to be changed.
However, there was a bug in commit 2462651ffa76 ("fs: allow changing idmappings") which allowed users to bypass this restriction by calling open_tree_attr(2) *without* OPEN_TREE_CLONE.
can_idmap_mount() prevented this bug from allowing an attached mountpoint's id-mapping from being modified (thanks to an is_anon_ns() check), but this still allows for detached (but visible) mounts to have their be id-mapping changed. This risks the same UAF and locking issues as described in the merge commit, and was likely unintentional.
Fixes: 2462651ffa76 ("fs: allow changing idmappings") Cc: stable@vger.kernel.org # v6.15+ Signed-off-by: Aleksa Sarai cyphar@cyphar.com Link: https://lore.kernel.org/20250808-open_tree_attr-bugfix-idmap-v1-1-0ec7bc0564... Signed-off-by: Christian Brauner brauner@kernel.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- fs/namespace.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
--- a/fs/namespace.c +++ b/fs/namespace.c @@ -5302,7 +5302,8 @@ SYSCALL_DEFINE5(open_tree_attr, int, dfd int ret; struct mount_kattr kattr = {};
- kattr.kflags = MOUNT_KATTR_IDMAP_REPLACE; + if (flags & OPEN_TREE_CLONE) + kattr.kflags = MOUNT_KATTR_IDMAP_REPLACE; if (flags & AT_RECURSIVE) kattr.kflags |= MOUNT_KATTR_RECURSE;
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jialin Wang wjl.linux@gmail.com
commit c0e1b774f68bdbea1618e356e30672c7f1e32509 upstream.
The commit 65c66047259f ("proc: fix the issue of proc_mem_open returning NULL") caused proc_maps_open() to return -ESRCH when proc_mem_open() returns NULL. This breaks legitimate /proc/<pid>/maps access for kernel threads since kernel threads have NULL mm_struct.
The regression causes perf to fail and exit when profiling a kernel thread:
# perf record -v -g -p $(pgrep kswapd0) ... couldn't open /proc/65/task/65/maps
This patch partially reverts the commit to fix it.
Link: https://lkml.kernel.org/r/20250807165455.73656-1-wjl.linux@gmail.com Fixes: 65c66047259f ("proc: fix the issue of proc_mem_open returning NULL") Signed-off-by: Jialin Wang wjl.linux@gmail.com Cc: Penglei Jiang superman.xpt@gmail.com Cc: stable@vger.kernel.org Signed-off-by: Andrew Morton akpm@linux-foundation.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- fs/proc/task_mmu.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
--- a/fs/proc/task_mmu.c +++ b/fs/proc/task_mmu.c @@ -212,8 +212,8 @@ static int proc_maps_open(struct inode *
priv->inode = inode; priv->mm = proc_mem_open(inode, PTRACE_MODE_READ); - if (IS_ERR_OR_NULL(priv->mm)) { - int err = priv->mm ? PTR_ERR(priv->mm) : -ESRCH; + if (IS_ERR(priv->mm)) { + int err = PTR_ERR(priv->mm);
seq_release_private(inode, file); return err;
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jon Hunter jonathanh@nvidia.com
commit b6bcbce3359619d05bf387d4f5cc3af63668dbaa upstream.
After commit 13a4b7fb6260 ("pmdomain: core: Leave powered-on genpds on until late_initcall_sync") was applied, the Tegra210 Jetson TX1 board failed to boot. Looking into this issue, before this commit was applied, if any of the Tegra power-domains were in 'on' state when the kernel booted, they were being turned off by the genpd core before any driver had chance to request them. This was purely by luck and a consequence of the power-domains being turned off earlier during boot. After this commit was applied, any power-domains in the 'on' state are kept on for longer during boot and therefore, may never transitioned to the off state before they are requested/used. The hang on the Tegra210 Jetson TX1 is caused because devices in some power-domains are accessed without the power-domain being turned off and on, indicating that the power-domain is not in a completely on state.
From reviewing the Tegra PMC driver code, if a power-domain is in the
'on' state there is no guarantee that all the necessary clocks associated with the power-domain are on and even if they are they would not have been requested via the clock framework and so could be turned off later. Some power-domains also have a 'clamping' register that needs to be configured as well. In short, if a power-domain is already 'on' it is difficult to know if it has been configured correctly. Given that the power-domains happened to be switched off during boot previously, to ensure that they are in a good known state on boot, fix this by switching off any power-domains that are on initially when registering the power-domains with the genpd framework.
Note that commit 05cfb988a4d0 ("soc/tegra: pmc: Initialise resets associated with a power partition") updated the tegra_powergate_of_get_resets() function to pass the 'off' to ensure that the resets for the power-domain are in the correct state on boot. However, now that we may power off a domain on boot, if it is on, it is better to move this logic into the tegra_powergate_add() function so that there is a single place where we are handling the initial state of the power-domain.
Fixes: a38045121bf4 ("soc/tegra: pmc: Add generic PM domain support") Signed-off-by: Jon Hunter jonathanh@nvidia.com Cc: stable@vger.kernel.org Link: https://lore.kernel.org/r/20250731121832.213671-1-jonathanh@nvidia.com Signed-off-by: Ulf Hansson ulf.hansson@linaro.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/soc/tegra/pmc.c | 51 +++++++++++++++++++++++++++--------------------- 1 file changed, 29 insertions(+), 22 deletions(-)
--- a/drivers/soc/tegra/pmc.c +++ b/drivers/soc/tegra/pmc.c @@ -1234,7 +1234,7 @@ err: }
static int tegra_powergate_of_get_resets(struct tegra_powergate *pg, - struct device_node *np, bool off) + struct device_node *np) { struct device *dev = pg->pmc->dev; int err; @@ -1249,22 +1249,6 @@ static int tegra_powergate_of_get_resets err = reset_control_acquire(pg->reset); if (err < 0) { pr_err("failed to acquire resets: %d\n", err); - goto out; - } - - if (off) { - err = reset_control_assert(pg->reset); - } else { - err = reset_control_deassert(pg->reset); - if (err < 0) - goto out; - - reset_control_release(pg->reset); - } - -out: - if (err) { - reset_control_release(pg->reset); reset_control_put(pg->reset); }
@@ -1309,20 +1293,43 @@ static int tegra_powergate_add(struct te goto set_available; }
- err = tegra_powergate_of_get_resets(pg, np, off); + err = tegra_powergate_of_get_resets(pg, np); if (err < 0) { dev_err(dev, "failed to get resets for %pOFn: %d\n", np, err); goto remove_clks; }
- if (!IS_ENABLED(CONFIG_PM_GENERIC_DOMAINS)) { - if (off) - WARN_ON(tegra_powergate_power_up(pg, true)); + /* + * If the power-domain is off, then ensure the resets are asserted. + * If the power-domain is on, then power down to ensure that when is + * it turned on the power-domain, clocks and resets are all in the + * expected state. + */ + if (off) { + err = reset_control_assert(pg->reset); + if (err) { + pr_err("failed to assert resets: %d\n", err); + goto remove_resets; + } + } else { + err = tegra_powergate_power_down(pg); + if (err) { + dev_err(dev, "failed to turn off PM domain %s: %d\n", + pg->genpd.name, err); + goto remove_resets; + } + }
+ /* + * If PM_GENERIC_DOMAINS is not enabled, power-on + * the domain and skip the genpd registration. + */ + if (!IS_ENABLED(CONFIG_PM_GENERIC_DOMAINS)) { + WARN_ON(tegra_powergate_power_up(pg, true)); goto remove_resets; }
- err = pm_genpd_init(&pg->genpd, NULL, off); + err = pm_genpd_init(&pg->genpd, NULL, true); if (err < 0) { dev_err(dev, "failed to initialise PM domain %pOFn: %d\n", np, err);
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: John David Anglin dave.anglin@bell.net
commit 91428ca9320edbab1211851d82429d33b9cd73ef upstream.
Because of the way the _PAGE_READ is handled in the parisc PTE, an access interruption is not generated when the kernel reads from a region where the _PAGE_READ is zero. The current code was written assuming read access faults would also occur in the kernel.
This change adds user access checks to raw_copy_from_user(). The prober_user() define checks whether user code has read access to a virtual address. Note that page faults are not handled in the exception support for the probe instruction. For this reason, we precede the probe by a ldb access check.
Signed-off-by: John David Anglin dave.anglin@bell.net Signed-off-by: Helge Deller deller@gmx.de Cc: stable@vger.kernel.org # v5.12+ Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- arch/parisc/include/asm/special_insns.h | 28 ++++++++++++++++++++++++++++ arch/parisc/lib/memcpy.c | 19 ++++++++++++++++++- 2 files changed, 46 insertions(+), 1 deletion(-)
--- a/arch/parisc/include/asm/special_insns.h +++ b/arch/parisc/include/asm/special_insns.h @@ -32,6 +32,34 @@ pa; \ })
+/** + * prober_user() - Probe user read access + * @sr: Space regster. + * @va: Virtual address. + * + * Return: Non-zero if address is accessible. + * + * Due to the way _PAGE_READ is handled in TLB entries, we need + * a special check to determine whether a user address is accessible. + * The ldb instruction does the initial access check. If it is + * successful, the probe instruction checks user access rights. + */ +#define prober_user(sr, va) ({ \ + unsigned long read_allowed; \ + __asm__ __volatile__( \ + "copy %%r0,%0\n" \ + "8:\tldb 0(%%sr%1,%2),%%r0\n" \ + "\tproberi (%%sr%1,%2),%3,%0\n" \ + "9:\n" \ + ASM_EXCEPTIONTABLE_ENTRY(8b, 9b, \ + "or %%r0,%%r0,%%r0") \ + : "=&r" (read_allowed) \ + : "i" (sr), "r" (va), "i" (PRIV_USER) \ + : "memory" \ + ); \ + read_allowed; \ +}) + #define CR_EIEM 15 /* External Interrupt Enable Mask */ #define CR_CR16 16 /* CR16 Interval Timer */ #define CR_EIRR 23 /* External Interrupt Request Register */ --- a/arch/parisc/lib/memcpy.c +++ b/arch/parisc/lib/memcpy.c @@ -12,6 +12,7 @@ #include <linux/module.h> #include <linux/compiler.h> #include <linux/uaccess.h> +#include <linux/mm.h>
#define get_user_space() mfsp(SR_USER) #define get_kernel_space() SR_KERNEL @@ -32,9 +33,25 @@ EXPORT_SYMBOL(raw_copy_to_user); unsigned long raw_copy_from_user(void *dst, const void __user *src, unsigned long len) { + unsigned long start = (unsigned long) src; + unsigned long end = start + len; + unsigned long newlen = len; + mtsp(get_user_space(), SR_TEMP1); mtsp(get_kernel_space(), SR_TEMP2); - return pa_memcpy(dst, (void __force *)src, len); + + /* Check region is user accessible */ + if (start) + while (start < end) { + if (!prober_user(SR_TEMP1, start)) { + newlen = (start - (unsigned long) src); + break; + } + start += PAGE_SIZE; + /* align to page boundry which may have different permission */ + start = PAGE_ALIGN_DOWN(start); + } + return len - newlen + pa_memcpy(dst, (void __force *)src, newlen); } EXPORT_SYMBOL(raw_copy_from_user);
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: John David Anglin dave.anglin@bell.net
commit 802e55488bc2cc1ab6423b720255a785ccac42ce upstream.
When a PTE is changed, we need to flush the PTE. set_pte_at() was lost in the folio update. PA-RISC version is the same as the generic version.
Signed-off-by: John David Anglin dave.anglin@bell.net Signed-off-by: Helge Deller deller@gmx.de Cc: stable@vger.kernel.org # v5.12+ Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- arch/parisc/include/asm/pgtable.h | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-)
--- a/arch/parisc/include/asm/pgtable.h +++ b/arch/parisc/include/asm/pgtable.h @@ -276,7 +276,7 @@ extern unsigned long *empty_zero_page; #define pte_none(x) (pte_val(x) == 0) #define pte_present(x) (pte_val(x) & _PAGE_PRESENT) #define pte_user(x) (pte_val(x) & _PAGE_USER) -#define pte_clear(mm, addr, xp) set_pte(xp, __pte(0)) +#define pte_clear(mm, addr, xp) set_pte_at((mm), (addr), (xp), __pte(0))
#define pmd_flag(x) (pmd_val(x) & PxD_FLAG_MASK) #define pmd_address(x) ((unsigned long)(pmd_val(x) &~ PxD_FLAG_MASK) << PxD_VALUE_SHIFT) @@ -392,6 +392,7 @@ static inline void set_ptes(struct mm_st } } #define set_ptes set_ptes +#define set_pte_at(mm, addr, ptep, pte) set_ptes(mm, addr, ptep, pte, 1)
/* Used for deferring calls to flush_dcache_page() */
@@ -456,7 +457,7 @@ static inline int ptep_test_and_clear_yo if (!pte_young(pte)) { return 0; } - set_pte(ptep, pte_mkold(pte)); + set_pte_at(vma->vm_mm, addr, ptep, pte_mkold(pte)); return 1; }
@@ -466,7 +467,7 @@ pte_t ptep_clear_flush(struct vm_area_st struct mm_struct; static inline void ptep_set_wrprotect(struct mm_struct *mm, unsigned long addr, pte_t *ptep) { - set_pte(ptep, pte_wrprotect(*ptep)); + set_pte_at(mm, addr, ptep, pte_wrprotect(*ptep)); }
#define pte_same(A,B) (pte_val(A) == pte_val(B))
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: John David Anglin dave.anglin@bell.net
commit 4eab1c27ce1f0e89ab67b01bf1e4e4c75215708a upstream.
I have observed warning to occassionally trigger.
Signed-off-by: John David Anglin dave.anglin@bell.net Signed-off-by: Helge Deller deller@gmx.de Cc: stable@vger.kernel.org # v5.12+ Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- arch/parisc/kernel/cache.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
--- a/arch/parisc/kernel/cache.c +++ b/arch/parisc/kernel/cache.c @@ -841,7 +841,7 @@ void flush_cache_vmap(unsigned long star }
vm = find_vm_area((void *)start); - if (WARN_ON_ONCE(!vm)) { + if (!vm) { flush_cache_all(); return; }
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Randy Dunlap rdunlap@infradead.org
commit 305ab0a748c52eeaeb01d8cff6408842d19e5cb5 upstream.
For building a 64-bit kernel, both 32-bit and 64-bit VDSO binaries are built, so both 32-bit and 64-bit compilers (and tools) should be in the PATH environment variable.
Signed-off-by: Randy Dunlap rdunlap@infradead.org Cc: "James E.J. Bottomley" James.Bottomley@HansenPartnership.com Cc: Helge Deller deller@gmx.de Cc: linux-parisc@vger.kernel.org Signed-off-by: Helge Deller deller@gmx.de Cc: stable@vger.kernel.org # v5.3+ Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- arch/parisc/Makefile | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
--- a/arch/parisc/Makefile +++ b/arch/parisc/Makefile @@ -39,7 +39,9 @@ endif
export LD_BFD
-# Set default 32 bits cross compilers for vdso +# Set default 32 bits cross compilers for vdso. +# This means that for 64BIT, both the 64-bit tools and the 32-bit tools +# need to be in the path. CC_ARCHES_32 = hppa hppa2.0 hppa1.1 CC_SUFFIXES = linux linux-gnu unknown-linux-gnu suse-linux CROSS32_COMPILE := $(call cc-cross-prefix, \
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: John David Anglin dave.anglin@bell.net
commit 52ce9406a9625c4498c4eaa51e7a7ed9dcb9db16 upstream.
The local name used in cache.c conflicts the declaration in include/asm-generic/tlb.h.
Signed-off-by: John David Anglin dave.anglin@bell.net Signed-off-by: Helge Deller deller@gmx.de Cc: stable@vger.kernel.org # v5.12+ Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- arch/parisc/kernel/cache.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
--- a/arch/parisc/kernel/cache.c +++ b/arch/parisc/kernel/cache.c @@ -429,7 +429,7 @@ static inline pte_t *get_ptep(struct mm_ return ptep; }
-static inline bool pte_needs_flush(pte_t pte) +static inline bool pte_needs_cache_flush(pte_t pte) { return (pte_val(pte) & (_PAGE_PRESENT | _PAGE_ACCESSED | _PAGE_NO_CACHE)) == (_PAGE_PRESENT | _PAGE_ACCESSED); @@ -630,7 +630,7 @@ static void flush_cache_page_if_present( ptep = get_ptep(vma->vm_mm, vmaddr); if (ptep) { pte = ptep_get(ptep); - needs_flush = pte_needs_flush(pte); + needs_flush = pte_needs_cache_flush(pte); pte_unmap(ptep); } if (needs_flush)
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: John David Anglin dave.anglin@bell.net
commit 89f686a0fb6e473a876a9a60a13aec67a62b9a7e upstream.
Because of the way read access support is implemented, read access interruptions are only triggered at privilege levels 2 and 3. The kernel executes at privilege level 0, so __get_user() never triggers a read access interruption (code 26). Thus, it is currently possible for user code to access a read protected address via a system call.
Fix this by probing read access rights at privilege level 3 (PRIV_USER) and setting __gu_err to -EFAULT (-14) if access isn't allowed.
Note the cmpiclr instruction does a 32-bit compare because COND macro doesn't work inside asm.
Signed-off-by: John David Anglin dave.anglin@bell.net Signed-off-by: Helge Deller deller@gmx.de Cc: stable@vger.kernel.org # v5.12+ Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- arch/parisc/include/asm/uaccess.h | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-)
--- a/arch/parisc/include/asm/uaccess.h +++ b/arch/parisc/include/asm/uaccess.h @@ -42,9 +42,24 @@ __gu_err; \ })
-#define __get_user(val, ptr) \ -({ \ - __get_user_internal(SR_USER, val, ptr); \ +#define __probe_user_internal(sr, error, ptr) \ +({ \ + __asm__("\tproberi (%%sr%1,%2),%3,%0\n" \ + "\tcmpiclr,= 1,%0,%0\n" \ + "\tldi %4,%0\n" \ + : "=r"(error) \ + : "i"(sr), "r"(ptr), "i"(PRIV_USER), \ + "i"(-EFAULT)); \ +}) + +#define __get_user(val, ptr) \ +({ \ + register long __gu_err; \ + \ + __gu_err = __get_user_internal(SR_USER, val, ptr); \ + if (likely(!__gu_err)) \ + __probe_user_internal(SR_USER, __gu_err, ptr); \ + __gu_err; \ })
#define __get_user_asm(sr, val, ldx, ptr) \
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: John David Anglin dave.anglin@bell.net
commit f6334f4ae9a4e962ba74b026e1d965dfdf8cbef8 upstream.
We use load and stbys,e instructions to trigger memory reference interruptions without writing to memory. Because of the way read access support is implemented, read access interruptions are only triggered at privilege levels 2 and 3. The kernel and gateway page execute at privilege level 0, so this code never triggers a read access interruption. Thus, it is currently possible for user code to execute a LWS compare and swap operation at an address that is read protected at privilege level 3 (PRIV_USER).
Fix this by probing read access rights at privilege level 3 and branching to lws_fault if access isn't allowed.
Signed-off-by: John David Anglin dave.anglin@bell.net Signed-off-by: Helge Deller deller@gmx.de Cc: stable@vger.kernel.org # v5.12+ Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- arch/parisc/kernel/syscall.S | 30 +++++++++++++++++++++--------- 1 file changed, 21 insertions(+), 9 deletions(-)
--- a/arch/parisc/kernel/syscall.S +++ b/arch/parisc/kernel/syscall.S @@ -613,6 +613,9 @@ lws_compare_and_swap32: lws_compare_and_swap: /* Trigger memory reference interruptions without writing to memory */ 1: ldw 0(%r26), %r28 + proberi (%r26), PRIV_USER, %r28 + comb,=,n %r28, %r0, lws_fault /* backwards, likely not taken */ + nop 2: stbys,e %r0, 0(%r26)
/* Calculate 8-bit hash index from virtual address */ @@ -767,6 +770,9 @@ cas2_lock_start: copy %r26, %r28 depi_safe 0, 31, 2, %r28 10: ldw 0(%r28), %r1 + proberi (%r28), PRIV_USER, %r1 + comb,=,n %r1, %r0, lws_fault /* backwards, likely not taken */ + nop 11: stbys,e %r0, 0(%r28)
/* Calculate 8-bit hash index from virtual address */ @@ -951,41 +957,47 @@ atomic_xchg_begin:
/* 8-bit exchange */ 1: ldb 0(%r24), %r20 + proberi (%r24), PRIV_USER, %r20 + comb,=,n %r20, %r0, lws_fault /* backwards, likely not taken */ + nop copy %r23, %r20 depi_safe 0, 31, 2, %r20 b atomic_xchg_start 2: stbys,e %r0, 0(%r20) - nop - nop - nop
/* 16-bit exchange */ 3: ldh 0(%r24), %r20 + proberi (%r24), PRIV_USER, %r20 + comb,=,n %r20, %r0, lws_fault /* backwards, likely not taken */ + nop copy %r23, %r20 depi_safe 0, 31, 2, %r20 b atomic_xchg_start 4: stbys,e %r0, 0(%r20) - nop - nop - nop
/* 32-bit exchange */ 5: ldw 0(%r24), %r20 + proberi (%r24), PRIV_USER, %r20 + comb,=,n %r20, %r0, lws_fault /* backwards, likely not taken */ + nop b atomic_xchg_start 6: stbys,e %r0, 0(%r23) nop nop - nop - nop - nop
/* 64-bit exchange */ #ifdef CONFIG_64BIT 7: ldd 0(%r24), %r20 + proberi (%r24), PRIV_USER, %r20 + comb,=,n %r20, %r0, lws_fault /* backwards, likely not taken */ + nop 8: stdby,e %r0, 0(%r23) #else 7: ldw 0(%r24), %r20 8: ldw 4(%r24), %r20 + proberi (%r24), PRIV_USER, %r20 + comb,=,n %r20, %r0, lws_fault /* backwards, likely not taken */ + nop copy %r23, %r20 depi_safe 0, 31, 2, %r20 9: stbys,e %r0, 0(%r20)
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: John David Anglin dave.anglin@bell.net
commit f92a5e36b0c45cd12ac0d1bc44680c0dfae34543 upstream.
Signed-off-by: John David Anglin dave.anglin@bell.net Signed-off-by: Helge Deller deller@gmx.de Cc: stable@vger.kernel.org # v5.12+ Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- arch/parisc/mm/fault.c | 4 ++++ 1 file changed, 4 insertions(+)
--- a/arch/parisc/mm/fault.c +++ b/arch/parisc/mm/fault.c @@ -363,6 +363,10 @@ bad_area: mmap_read_unlock(mm);
bad_area_nosemaphore: + if (!user_mode(regs) && fixup_exception(regs)) { + return; + } + if (user_mode(regs)) { int signo, si_code;
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: John David Anglin dave.anglin@bell.net
commit cb22f247f371bd206a88cf0e0c05d80b8b62fb26 upstream.
The following testcase exposed a problem with our read access checks in get_user() and raw_copy_from_user():
#include <stdint.h> #include <stddef.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <errno.h> #include <sys/mman.h> #include <sys/types.h>
int main(int argc, char **argv) { unsigned long page_size = sysconf(_SC_PAGESIZE); char *p = malloc(3 * page_size); char *p_aligned;
/* initialize memory region. If not initialized, write syscall below will correctly return EFAULT. */ if (1) memset(p, 'X', 3 * page_size);
p_aligned = (char *) ((((uintptr_t) p) + (2*page_size - 1)) & ~(page_size - 1)); /* Drop PROT_READ protection. Kernel and userspace should fault when accessing that memory region */ mprotect(p_aligned, page_size, PROT_NONE);
/* the following write() should return EFAULT, since PROT_READ was dropped by previous mprotect() */ int ret = write(2, p_aligned, 1); if (!ret || errno != EFAULT) printf("\n FAILURE: write() did not returned expected EFAULT value\n");
return 0; }
Because of the way _PAGE_READ is handled, kernel code never generates a read access fault when it access a page as the kernel privilege level is always less than PL1 in the PTE.
This patch reworks the comments in the make_insert_tlb macro to try to make this clearer.
Signed-off-by: John David Anglin dave.anglin@bell.net Signed-off-by: Helge Deller deller@gmx.de Cc: stable@vger.kernel.org # v5.12+ Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- arch/parisc/kernel/entry.S | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-)
--- a/arch/parisc/kernel/entry.S +++ b/arch/parisc/kernel/entry.S @@ -499,6 +499,12 @@ * this happens is quite subtle, read below */ .macro make_insert_tlb spc,pte,prot,tmp space_to_prot \spc \prot /* create prot id from space */ + +#if _PAGE_SPECIAL_BIT == _PAGE_DMB_BIT + /* need to drop DMB bit, as it's used as SPECIAL flag */ + depi 0,_PAGE_SPECIAL_BIT,1,\pte +#endif + /* The following is the real subtlety. This is depositing * T <-> _PAGE_REFTRAP * D <-> _PAGE_DIRTY @@ -511,17 +517,18 @@ * Finally, _PAGE_READ goes in the top bit of PL1 (so we * trigger an access rights trap in user space if the user * tries to read an unreadable page */ -#if _PAGE_SPECIAL_BIT == _PAGE_DMB_BIT - /* need to drop DMB bit, as it's used as SPECIAL flag */ - depi 0,_PAGE_SPECIAL_BIT,1,\pte -#endif depd \pte,8,7,\prot
/* PAGE_USER indicates the page can be read with user privileges, * so deposit X1|11 to PL1|PL2 (remember the upper bit of PL1 - * contains _PAGE_READ) */ + * contains _PAGE_READ). While the kernel can't directly write + * user pages which have _PAGE_WRITE zero, it can read pages + * which have _PAGE_READ zero (PL <= PL1). Thus, the kernel + * exception fault handler doesn't trigger when reading pages + * that aren't user read accessible */ extrd,u,*= \pte,_PAGE_USER_BIT+32,1,%r0 depdi 7,11,3,\prot + /* If we're a gateway page, drop PL2 back to zero for promotion * to kernel privilege (so we can execute the page as kernel). * Any privilege promotion page always denys read and write */
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Dan Carpenter dan.carpenter@linaro.org
commit aef89c0b2417da79cb2062a95476288f9f203ab0 upstream.
This sd_init() function reads the firmware. The firmware data holds a series of records and the function reads each record and sends the data to the device. The request_ihex_firmware() function calls ihex_validate_fw() which ensures that the total length of all the records won't read out of bounds of the fw->data[].
However, a potential issue is if there is a single very large record (larger than PAGE_SIZE) and that would result in memory corruption. Generally we trust the firmware, but it's always better to double check.
Fixes: 49b61ec9b5af ("[media] gspca: Add new vicam subdriver") Cc: stable@vger.kernel.org Signed-off-by: Dan Carpenter dan.carpenter@linaro.org Signed-off-by: Hans Verkuil hverkuil@xs4all.nl Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/media/usb/gspca/vicam.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-)
--- a/drivers/media/usb/gspca/vicam.c +++ b/drivers/media/usb/gspca/vicam.c @@ -227,6 +227,7 @@ static int sd_init(struct gspca_dev *gsp const struct ihex_binrec *rec; const struct firmware *fw; u8 *firmware_buf; + int len;
ret = request_ihex_firmware(&fw, VICAM_FIRMWARE, &gspca_dev->dev->dev); @@ -241,9 +242,14 @@ static int sd_init(struct gspca_dev *gsp goto exit; } for (rec = (void *)fw->data; rec; rec = ihex_next_binrec(rec)) { - memcpy(firmware_buf, rec->data, be16_to_cpu(rec->len)); + len = be16_to_cpu(rec->len); + if (len > PAGE_SIZE) { + ret = -EINVAL; + break; + } + memcpy(firmware_buf, rec->data, len); ret = vicam_control_msg(gspca_dev, 0xff, 0, 0, firmware_buf, - be16_to_cpu(rec->len)); + len); if (ret < 0) break; }
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Bingbu Cao bingbu.cao@intel.com
commit 020f602b068c9ce18d5056d02c8302199377d98d upstream.
Hynix hi556 support 8 test pattern modes: hi556_test_pattern_menu[] = { { "Disabled", "Solid Colour", "100% Colour Bars", "Fade To Grey Colour Bars", "PN9", "Gradient Horizontal", "Gradient Vertical", "Check Board", "Slant Pattern", }
The test pattern is set by a 8-bit register according to the specification. +--------+-------------------------------+ | BIT[0] | Solid color | +--------+-------------------------------+ | BIT[1] | Color bar | +--------+-------------------------------+ | BIT[2] | Fade to grey color bar | +--------+-------------------------------+ | BIT[3] | PN9 | +--------+-------------------------------+ | BIT[4] | Gradient horizontal | +--------+-------------------------------+ | BIT[5] | Gradient vertical | +--------+-------------------------------+ | BIT[6] | Check board | +--------+-------------------------------+ | BIT[7] | Slant pattern | +--------+-------------------------------+ Based on function above, current test pattern programming is wrong. This patch fixes it by 'BIT(pattern - 1)'. If pattern is 0, driver will disable the test pattern generation and set the pattern to 0.
Fixes: e62138403a84 ("media: hi556: Add support for Hi-556 sensor") Cc: stable@vger.kernel.org Signed-off-by: Bingbu Cao bingbu.cao@intel.com Signed-off-by: Sakari Ailus sakari.ailus@linux.intel.com Signed-off-by: Hans Verkuil hverkuil@xs4all.nl Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/media/i2c/hi556.c | 28 +++++++++++++++------------- 1 file changed, 15 insertions(+), 13 deletions(-)
--- a/drivers/media/i2c/hi556.c +++ b/drivers/media/i2c/hi556.c @@ -756,21 +756,23 @@ static int hi556_test_pattern(struct hi5 int ret; u32 val;
- if (pattern) { - ret = hi556_read_reg(hi556, HI556_REG_ISP, - HI556_REG_VALUE_08BIT, &val); - if (ret) - return ret; - - ret = hi556_write_reg(hi556, HI556_REG_ISP, - HI556_REG_VALUE_08BIT, - val | HI556_REG_ISP_TPG_EN); - if (ret) - return ret; - } + ret = hi556_read_reg(hi556, HI556_REG_ISP, + HI556_REG_VALUE_08BIT, &val); + if (ret) + return ret; + + val = pattern ? (val | HI556_REG_ISP_TPG_EN) : + (val & ~HI556_REG_ISP_TPG_EN); + + ret = hi556_write_reg(hi556, HI556_REG_ISP, + HI556_REG_VALUE_08BIT, val); + if (ret) + return ret; + + val = pattern ? BIT(pattern - 1) : 0;
return hi556_write_reg(hi556, HI556_REG_TEST_PATTERN, - HI556_REG_VALUE_08BIT, pattern); + HI556_REG_VALUE_08BIT, val); }
static int hi556_set_ctrl(struct v4l2_ctrl *ctrl)
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Haoxiang Li haoxiang_li2024@163.com
commit fc5f8aec77704373ee804b5dba0e0e5029c0f180 upstream.
Add video_device_release() in label 'err_m2m' to release the memory allocated by video_device_alloc() and prevent potential memory leaks. Remove the reduntant code in label 'err_m2m'.
Fixes: a8ef0488cc59 ("media: imx: add csc/scaler mem2mem device") Cc: stable@vger.kernel.org Signed-off-by: Haoxiang Li haoxiang_li2024@163.com Reviewed-by: Dan Carpenter dan.carpenter@linaro.org Signed-off-by: Nicolas Dufresne nicolas.dufresne@collabora.com Signed-off-by: Hans Verkuil hverkuil@xs4all.nl Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/staging/media/imx/imx-media-csc-scaler.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
--- a/drivers/staging/media/imx/imx-media-csc-scaler.c +++ b/drivers/staging/media/imx/imx-media-csc-scaler.c @@ -912,7 +912,7 @@ imx_media_csc_scaler_device_init(struct return &priv->vdev;
err_m2m: - video_set_drvdata(vfd, NULL); + video_device_release(vfd); err_vfd: kfree(priv); return ERR_PTR(ret);
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sakari Ailus sakari.ailus@linux.intel.com
commit ff49672a28f3a856717f09d61380e524e243121f upstream.
The pad argument to v4l2_subdev_state_xlate_streams() is incorrect, static pad number is used for the source pad even though the pad number is dependent on the stream. Fix it.
Fixes: 3a5c59ad926b ("media: ipu6: Rework CSI-2 sub-device streaming control") Cc: stable@vger.kernel.org Signed-off-by: Sakari Ailus sakari.ailus@linux.intel.com Signed-off-by: Hans Verkuil hverkuil@xs4all.nl Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/media/pci/intel/ipu6/ipu6-isys-csi2.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-)
--- a/drivers/media/pci/intel/ipu6/ipu6-isys-csi2.c +++ b/drivers/media/pci/intel/ipu6/ipu6-isys-csi2.c @@ -354,9 +354,9 @@ static int ipu6_isys_csi2_enable_streams remote_pad = media_pad_remote_pad_first(&sd->entity.pads[CSI2_PAD_SINK]); remote_sd = media_entity_to_v4l2_subdev(remote_pad->entity);
- sink_streams = v4l2_subdev_state_xlate_streams(state, CSI2_PAD_SRC, - CSI2_PAD_SINK, - &streams_mask); + sink_streams = + v4l2_subdev_state_xlate_streams(state, pad, CSI2_PAD_SINK, + &streams_mask);
ret = ipu6_isys_csi2_calc_timing(csi2, &timing, CSI2_ACCINV); if (ret) @@ -384,9 +384,9 @@ static int ipu6_isys_csi2_disable_stream struct media_pad *remote_pad; u64 sink_streams;
- sink_streams = v4l2_subdev_state_xlate_streams(state, CSI2_PAD_SRC, - CSI2_PAD_SINK, - &streams_mask); + sink_streams = + v4l2_subdev_state_xlate_streams(state, pad, CSI2_PAD_SINK, + &streams_mask);
remote_pad = media_pad_remote_pad_first(&sd->entity.pads[CSI2_PAD_SINK]); remote_sd = media_entity_to_v4l2_subdev(remote_pad->entity);
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Hans Verkuil hverkuil@xs4all.nl
commit 3e43442d4994c9e1e202c98129a87e330f7faaed upstream.
The pixel_array control size was calculated incorrectly: the dimensions were swapped (dims[0] should be the height), and the values should be the width or height divided by PIXEL_ARRAY_DIV and rounded up. So don't use roundup, but use DIV_ROUND_UP instead.
This bug is harmless in the sense that nothing will break, except that it consumes way too much memory for this control.
Fixes: 6bc7643d1b9c ("media: vivid: add pixel_array test control") Cc: stable@vger.kernel.org Signed-off-by: Hans Verkuil hverkuil@xs4all.nl Signed-off-by: Mauro Carvalho Chehab mchehab+huawei@kernel.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/media/test-drivers/vivid/vivid-ctrls.c | 3 ++- drivers/media/test-drivers/vivid/vivid-vid-cap.c | 4 ++-- 2 files changed, 4 insertions(+), 3 deletions(-)
--- a/drivers/media/test-drivers/vivid/vivid-ctrls.c +++ b/drivers/media/test-drivers/vivid/vivid-ctrls.c @@ -244,7 +244,8 @@ static const struct v4l2_ctrl_config viv .min = 0x00, .max = 0xff, .step = 1, - .dims = { 640 / PIXEL_ARRAY_DIV, 360 / PIXEL_ARRAY_DIV }, + .dims = { DIV_ROUND_UP(360, PIXEL_ARRAY_DIV), + DIV_ROUND_UP(640, PIXEL_ARRAY_DIV) }, };
static const struct v4l2_ctrl_config vivid_ctrl_s32_array = { --- a/drivers/media/test-drivers/vivid/vivid-vid-cap.c +++ b/drivers/media/test-drivers/vivid/vivid-vid-cap.c @@ -454,8 +454,8 @@ void vivid_update_format_cap(struct vivi if (keep_controls) return;
- dims[0] = roundup(dev->src_rect.width, PIXEL_ARRAY_DIV); - dims[1] = roundup(dev->src_rect.height, PIXEL_ARRAY_DIV); + dims[0] = DIV_ROUND_UP(dev->src_rect.height, PIXEL_ARRAY_DIV); + dims[1] = DIV_ROUND_UP(dev->src_rect.width, PIXEL_ARRAY_DIV); v4l2_ctrl_modify_dimensions(dev->pixel_array, dims); }
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Nicolas Dufresne nicolas.dufresne@collabora.com
commit 01350185fe02ae3ea2c12d578e06af0d5186f33e upstream.
The desired clock frequency was correctly set to 400MHz in the device tree but was lowered by the driver to 300MHz breaking 4K 60Hz content playback. Fix the issue by removing the driver call to clk_set_rate(), which reduce the amount of board specific code.
Fixes: 003afda97c65 ("media: verisilicon: Enable AV1 decoder on rk3588") Cc: stable@vger.kernel.org Reviewed-by: Benjamin Gaignard benjamin.gaignard@collabora.com Reviewed-by: Philipp Zabel p.zabel@pengutronix.de Signed-off-by: Nicolas Dufresne nicolas.dufresne@collabora.com Signed-off-by: Hans Verkuil hverkuil@xs4all.nl Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/media/platform/verisilicon/rockchip_vpu_hw.c | 9 --------- 1 file changed, 9 deletions(-)
--- a/drivers/media/platform/verisilicon/rockchip_vpu_hw.c +++ b/drivers/media/platform/verisilicon/rockchip_vpu_hw.c @@ -17,7 +17,6 @@
#define RK3066_ACLK_MAX_FREQ (300 * 1000 * 1000) #define RK3288_ACLK_MAX_FREQ (400 * 1000 * 1000) -#define RK3588_ACLK_MAX_FREQ (300 * 1000 * 1000)
#define ROCKCHIP_VPU981_MIN_SIZE 64
@@ -454,13 +453,6 @@ static int rk3066_vpu_hw_init(struct han return 0; }
-static int rk3588_vpu981_hw_init(struct hantro_dev *vpu) -{ - /* Bump ACLKs to max. possible freq. to improve performance. */ - clk_set_rate(vpu->clocks[0].clk, RK3588_ACLK_MAX_FREQ); - return 0; -} - static int rockchip_vpu_hw_init(struct hantro_dev *vpu) { /* Bump ACLK to max. possible freq. to improve performance. */ @@ -821,7 +813,6 @@ const struct hantro_variant rk3588_vpu98 .codec_ops = rk3588_vpu981_codec_ops, .irqs = rk3588_vpu981_irqs, .num_irqs = ARRAY_SIZE(rk3588_vpu981_irqs), - .init = rk3588_vpu981_hw_init, .clk_names = rk3588_vpu981_vpu_clk_names, .num_clocks = ARRAY_SIZE(rk3588_vpu981_vpu_clk_names) };
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sakari Ailus sakari.ailus@linux.intel.com
commit 5a0400aca5fa7c6b8ba456c311a460e733571c88 upstream.
It's a common pattern in drivers to free the control handler's resources and then return the handler's error code on drivers' error handling paths. Alas, the v4l2_ctrl_handler_free() function also zeroes the error field, effectively indicating successful return to the caller.
There's no apparent need to touch the error field while releasing the control handler's resources and cleaning up stale pointers. Not touching the handler's error field is a more certain way to address this problem than changing all the users, in which case the pattern would be likely to re-emerge in new drivers.
Do just that, don't touch the control handler's error field in v4l2_ctrl_handler_free().
Fixes: 0996517cf8ea ("V4L/DVB: v4l2: Add new control handling framework") Cc: stable@vger.kernel.org Signed-off-by: Sakari Ailus sakari.ailus@linux.intel.com Reviewed-by: Hans Verkuil hverkuil@xs4all.nl Reviewed-by: Laurent Pinchart laurent.pinchart@ideasonboard.com Signed-off-by: Hans Verkuil hverkuil@xs4all.nl Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/media/v4l2-core/v4l2-ctrls-core.c | 1 - 1 file changed, 1 deletion(-)
--- a/drivers/media/v4l2-core/v4l2-ctrls-core.c +++ b/drivers/media/v4l2-core/v4l2-ctrls-core.c @@ -1661,7 +1661,6 @@ void v4l2_ctrl_handler_free(struct v4l2_ kvfree(hdl->buckets); hdl->buckets = NULL; hdl->cached = NULL; - hdl->error = 0; mutex_unlock(hdl->lock); mutex_destroy(&hdl->_lock); }
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ludwig Disterhof ludwig@disterhof.eu
commit 7e40e0bb778907b2441bff68d73c3eb6b6cd319f upstream.
When an program is streaming (ffplay) and another program (qv4l2) changes the TV standard from NTSC to PAL, the kernel crashes due to trying to copy to unmapped memory.
Changing from NTSC to PAL increases the resolution in the usbtv struct, but the video plane buffer isn't adjusted, so it overflows.
Fixes: 0e0fe3958fdd13d ("[media] usbtv: Add support for PAL video source") Cc: stable@vger.kernel.org Signed-off-by: Ludwig Disterhof ludwig@disterhof.eu Signed-off-by: Hans Verkuil hverkuil@xs4all.nl [hverkuil: call vb2_is_busy instead of vb2_is_streaming] Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/media/usb/usbtv/usbtv-video.c | 4 ++++ 1 file changed, 4 insertions(+)
--- a/drivers/media/usb/usbtv/usbtv-video.c +++ b/drivers/media/usb/usbtv/usbtv-video.c @@ -73,6 +73,10 @@ static int usbtv_configure_for_norm(stru }
if (params) { + if (vb2_is_busy(&usbtv->vb2q) && + (usbtv->width != params->cap_width || + usbtv->height != params->cap_height)) + return -EBUSY; usbtv->width = params->cap_width; usbtv->height = params->cap_height; usbtv->n_chunks = usbtv->width * usbtv->height
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Gui-Dong Han hanguidong02@gmail.com
commit 7af160aea26c7dc9e6734d19306128cce156ec40 upstream.
In the interrupt handler rain_interrupt(), the buffer full check on rain->buf_len is performed before acquiring rain->buf_lock. This creates a Time-of-Check to Time-of-Use (TOCTOU) race condition, as rain->buf_len is concurrently accessed and modified in the work handler rain_irq_work_handler() under the same lock.
Multiple interrupt invocations can race, with each reading buf_len before it becomes full and then proceeding. This can lead to both interrupts attempting to write to the buffer, incrementing buf_len beyond its capacity (DATA_SIZE) and causing a buffer overflow.
Fix this bug by moving the spin_lock() to before the buffer full check. This ensures that the check and the subsequent buffer modification are performed atomically, preventing the race condition. An corresponding spin_unlock() is added to the overflow path to correctly release the lock.
This possible bug was found by an experimental static analysis tool developed by our team.
Fixes: 0f314f6c2e77 ("[media] rainshadow-cec: new RainShadow Tech HDMI CEC driver") Cc: stable@vger.kernel.org Signed-off-by: Gui-Dong Han hanguidong02@gmail.com Signed-off-by: Hans Verkuil hverkuil@xs4all.nl Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/media/cec/usb/rainshadow/rainshadow-cec.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
--- a/drivers/media/cec/usb/rainshadow/rainshadow-cec.c +++ b/drivers/media/cec/usb/rainshadow/rainshadow-cec.c @@ -171,11 +171,12 @@ static irqreturn_t rain_interrupt(struct { struct rain *rain = serio_get_drvdata(serio);
+ spin_lock(&rain->buf_lock); if (rain->buf_len == DATA_SIZE) { + spin_unlock(&rain->buf_lock); dev_warn_once(rain->dev, "buffer overflow\n"); return IRQ_HANDLED; } - spin_lock(&rain->buf_lock); rain->buf_len++; rain->buf[rain->buf_wr_idx] = data; rain->buf_wr_idx = (rain->buf_wr_idx + 1) & 0xff;
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jacopo Mondi jacopo.mondi@ideasonboard.com
commit e9bb2eacc7222ff8210903eb3b7d56709cc53228 upstream.
During the probe() routine, the PiSP BE driver needs to power up the interface in order to identify and initialize the hardware.
The driver resumes the interface by calling the pispbe_runtime_resume() function directly, without going through the pm_runtime helpers, but later suspends it by calling pm_runtime_put_autosuspend().
This causes a PM usage count imbalance at probe time, notified by the runtime_pm framework with the below message in the system log:
pispbe 1000880000.pisp_be: Runtime PM usage count underflow!
Fix this by resuming the interface using the pm runtime helpers instead of calling the resume function directly and use the pm_runtime framework in the probe() error path. While at it, remove manual suspend of the interface in the remove() function. The driver cannot be unloaded if in use, so simply disable runtime pm.
To simplify the implementation, make the driver depend on PM as the RPI5 platform where the ISP is integrated in uses the PM framework by default.
Fixes: 12187bd5d4f8 ("media: raspberrypi: Add support for PiSP BE") Cc: stable@vger.kernel.org Tested-by: Naushir Patuck naush@raspberrypi.com Reviewed-by: Naushir Patuck naush@raspberrypi.com Reviewed-by: Laurent Pinchart laurent.pinchart@ideasonboard.com Signed-off-by: Jacopo Mondi jacopo.mondi@ideasonboard.com Signed-off-by: Hans Verkuil hverkuil@xs4all.nl Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/media/platform/raspberrypi/pisp_be/Kconfig | 1 + drivers/media/platform/raspberrypi/pisp_be/pisp_be.c | 5 ++--- 2 files changed, 3 insertions(+), 3 deletions(-)
--- a/drivers/media/platform/raspberrypi/pisp_be/Kconfig +++ b/drivers/media/platform/raspberrypi/pisp_be/Kconfig @@ -3,6 +3,7 @@ config VIDEO_RASPBERRYPI_PISP_BE depends on V4L_PLATFORM_DRIVERS depends on VIDEO_DEV depends on ARCH_BCM2835 || COMPILE_TEST + depends on PM select VIDEO_V4L2_SUBDEV_API select MEDIA_CONTROLLER select VIDEOBUF2_DMA_CONTIG --- a/drivers/media/platform/raspberrypi/pisp_be/pisp_be.c +++ b/drivers/media/platform/raspberrypi/pisp_be/pisp_be.c @@ -1726,7 +1726,7 @@ static int pispbe_probe(struct platform_ pm_runtime_use_autosuspend(pispbe->dev); pm_runtime_enable(pispbe->dev);
- ret = pispbe_runtime_resume(pispbe->dev); + ret = pm_runtime_resume_and_get(pispbe->dev); if (ret) goto pm_runtime_disable_err;
@@ -1748,7 +1748,7 @@ static int pispbe_probe(struct platform_ disable_devs_err: pispbe_destroy_devices(pispbe); pm_runtime_suspend_err: - pispbe_runtime_suspend(pispbe->dev); + pm_runtime_put(pispbe->dev); pm_runtime_disable_err: pm_runtime_dont_use_autosuspend(pispbe->dev); pm_runtime_disable(pispbe->dev); @@ -1762,7 +1762,6 @@ static void pispbe_remove(struct platfor
pispbe_destroy_devices(pispbe);
- pispbe_runtime_suspend(pispbe->dev); pm_runtime_dont_use_autosuspend(pispbe->dev); pm_runtime_disable(pispbe->dev); }
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Zhang Shurong zhang_shurong@foxmail.com
commit 76142b137b968d47b35cdd8d1dc924677d319c8b upstream.
ov2659_probe() doesn't properly free control handler resources in failure paths, causing memory leaks. Add v4l2_ctrl_handler_free() to prevent these memory leaks and reorder the ctrl_handler assignment for better code flow.
Fixes: c4c0283ab3cd ("[media] media: i2c: add support for omnivision's ov2659 sensor") Cc: stable@vger.kernel.org Signed-off-by: Zhang Shurong zhang_shurong@foxmail.com Signed-off-by: Sakari Ailus sakari.ailus@linux.intel.com Signed-off-by: Hans Verkuil hverkuil@xs4all.nl Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/media/i2c/ov2659.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
--- a/drivers/media/i2c/ov2659.c +++ b/drivers/media/i2c/ov2659.c @@ -1469,14 +1469,15 @@ static int ov2659_probe(struct i2c_clien V4L2_CID_TEST_PATTERN, ARRAY_SIZE(ov2659_test_pattern_menu) - 1, 0, 0, ov2659_test_pattern_menu); - ov2659->sd.ctrl_handler = &ov2659->ctrls;
if (ov2659->ctrls.error) { dev_err(&client->dev, "%s: control initialization error %d\n", __func__, ov2659->ctrls.error); + v4l2_ctrl_handler_free(&ov2659->ctrls); return ov2659->ctrls.error; }
+ ov2659->sd.ctrl_handler = &ov2659->ctrls; sd = &ov2659->sd; client->flags |= I2C_CLIENT_SCCB;
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Mathis Foerst mathis.foerst@mt.com
commit 298d1471cf83d5a2a05970e41822a2403f451086 upstream.
Getting / Setting the frame interval using the V4L2 subdev pad ops get_frame_interval/set_frame_interval causes a deadlock, as the subdev state is locked in the [1] but also in the driver itself.
In [2] it's described that the caller is responsible to acquire and release the lock in this case. Therefore, acquiring the lock in the driver is wrong.
Remove the lock acquisitions/releases from mt9m114_ifp_get_frame_interval() and mt9m114_ifp_set_frame_interval().
[1] drivers/media/v4l2-core/v4l2-subdev.c - line 1129 [2] Documentation/driver-api/media/v4l2-subdev.rst
Fixes: 24d756e914fc ("media: i2c: Add driver for onsemi MT9M114 camera sensor") Cc: stable@vger.kernel.org Signed-off-by: Mathis Foerst mathis.foerst@mt.com Reviewed-by: Laurent Pinchart laurent.pinchart@ideasonboard.com Signed-off-by: Sakari Ailus sakari.ailus@linux.intel.com Signed-off-by: Hans Verkuil hverkuil@xs4all.nl Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/media/i2c/mt9m114.c | 8 -------- 1 file changed, 8 deletions(-)
--- a/drivers/media/i2c/mt9m114.c +++ b/drivers/media/i2c/mt9m114.c @@ -1599,13 +1599,9 @@ static int mt9m114_ifp_get_frame_interva if (interval->which != V4L2_SUBDEV_FORMAT_ACTIVE) return -EINVAL;
- mutex_lock(sensor->ifp.hdl.lock); - ival->numerator = 1; ival->denominator = sensor->ifp.frame_rate;
- mutex_unlock(sensor->ifp.hdl.lock); - return 0; }
@@ -1624,8 +1620,6 @@ static int mt9m114_ifp_set_frame_interva if (interval->which != V4L2_SUBDEV_FORMAT_ACTIVE) return -EINVAL;
- mutex_lock(sensor->ifp.hdl.lock); - if (ival->numerator != 0 && ival->denominator != 0) sensor->ifp.frame_rate = min_t(unsigned int, ival->denominator / ival->numerator, @@ -1639,8 +1633,6 @@ static int mt9m114_ifp_set_frame_interva if (sensor->streaming) ret = mt9m114_set_frame_rate(sensor);
- mutex_unlock(sensor->ifp.hdl.lock); - return ret; }
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Hans de Goede hansg@kernel.org
commit 0c92c49fc688cfadacc47ae99b06a31237702e9e upstream.
Both the ACE and CSI driver are missing a mei_cldev_disable() call in their remove() function.
This causes the mei_cl client to stay part of the mei_device->file_list list even though its memory is freed by mei_cl_bus_dev_release() calling kfree(cldev->cl).
This leads to a use-after-free when mei_vsc_remove() runs mei_stop() which first removes all mei bus devices calling mei_ace_remove() and mei_csi_remove() followed by mei_cl_bus_dev_release() and then calls mei_cl_all_disconnect() which walks over mei_device->file_list dereferecing the just freed cldev->cl.
And mei_vsc_remove() it self is run at shutdown because of the platform_device_unregister(tp->pdev) in vsc_tp_shutdown()
When building a kernel with KASAN this leads to the following KASAN report:
[ 106.634504] ================================================================== [ 106.634623] BUG: KASAN: slab-use-after-free in mei_cl_set_disconnected (drivers/misc/mei/client.c:783) mei [ 106.634683] Read of size 4 at addr ffff88819cb62018 by task systemd-shutdow/1 [ 106.634729] [ 106.634767] Tainted: [E]=UNSIGNED_MODULE [ 106.634770] Hardware name: Dell Inc. XPS 16 9640/09CK4V, BIOS 1.12.0 02/10/2025 [ 106.634773] Call Trace: [ 106.634777] <TASK> ... [ 106.634871] kasan_report (mm/kasan/report.c:221 mm/kasan/report.c:636) [ 106.634901] mei_cl_set_disconnected (drivers/misc/mei/client.c:783) mei [ 106.634921] mei_cl_all_disconnect (drivers/misc/mei/client.c:2165 (discriminator 4)) mei [ 106.634941] mei_reset (drivers/misc/mei/init.c:163) mei ... [ 106.635042] mei_stop (drivers/misc/mei/init.c:348) mei [ 106.635062] mei_vsc_remove (drivers/misc/mei/mei_dev.h:784 drivers/misc/mei/platform-vsc.c:393) mei_vsc [ 106.635066] platform_remove (drivers/base/platform.c:1424)
Add the missing mei_cldev_disable() calls so that the mei_cl gets removed from mei_device->file_list before it is freed to fix this.
Fixes: 78876f71b3e9 ("media: pci: intel: ivsc: Add ACE submodule") Fixes: 29006e196a56 ("media: pci: intel: ivsc: Add CSI submodule") Cc: stable@vger.kernel.org Signed-off-by: Hans de Goede hansg@kernel.org Signed-off-by: Sakari Ailus sakari.ailus@linux.intel.com Signed-off-by: Hans Verkuil hverkuil@xs4all.nl Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/media/pci/intel/ivsc/mei_ace.c | 2 ++ drivers/media/pci/intel/ivsc/mei_csi.c | 2 ++ 2 files changed, 4 insertions(+)
--- a/drivers/media/pci/intel/ivsc/mei_ace.c +++ b/drivers/media/pci/intel/ivsc/mei_ace.c @@ -529,6 +529,8 @@ static void mei_ace_remove(struct mei_cl
ace_set_camera_owner(ace, ACE_CAMERA_IVSC);
+ mei_cldev_disable(cldev); + mutex_destroy(&ace->lock); }
--- a/drivers/media/pci/intel/ivsc/mei_csi.c +++ b/drivers/media/pci/intel/ivsc/mei_csi.c @@ -760,6 +760,8 @@ static void mei_csi_remove(struct mei_cl
pm_runtime_disable(&cldev->dev);
+ mei_cldev_disable(cldev); + mutex_destroy(&csi->lock); }
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Bryan O'Donoghue bryan.odonoghue@linaro.org
commit 868423c834a29981fe3a77d32caf645c6b91a4c5 upstream.
The moving of init sequence hook from gen2() to subdev_init() doesn't account for gen1 devices such as SDM660 and SDM670. The switch should find the right offset for gen2 PHYs only, not reject gen1. Remove the default error case to restore gen1 CSIPHY support.
Cc: stable@vger.kernel.org Fixes: fbce0ca24c3a ("media: qcom: camss: csiphy-3ph: Move CSIPHY variables to data field inside csiphy struct") Signed-off-by: Bryan O'Donoghue bryan.odonoghue@linaro.org Reviewed-by: Vladimir Zapolskiy vladimir.zapolskiy@linaro.org Signed-off-by: Bryan O'Donoghue bod@kernel.org Signed-off-by: Hans Verkuil hverkuil@xs4all.nl Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/media/platform/qcom/camss/camss-csiphy-3ph-1-0.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/drivers/media/platform/qcom/camss/camss-csiphy-3ph-1-0.c b/drivers/media/platform/qcom/camss/camss-csiphy-3ph-1-0.c index f732a76de93e..88c0ba495c32 100644 --- a/drivers/media/platform/qcom/camss/camss-csiphy-3ph-1-0.c +++ b/drivers/media/platform/qcom/camss/camss-csiphy-3ph-1-0.c @@ -849,8 +849,7 @@ static int csiphy_init(struct csiphy_device *csiphy) regs->offset = 0x1000; break; default: - WARN(1, "unknown csiphy version\n"); - return -ENODEV; + break; }
return 0;
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Vladimir Zapolskiy vladimir.zapolskiy@linaro.org
commit 69080ec3d0daba8a894025476c98ab16b5a505a4 upstream.
A call to media_device_init() requires media_device_cleanup() counterpart to complete cleanup and release any allocated resources.
This has been done in the driver .remove() right from the beginning, but error paths on .probe() shall also be fixed.
Fixes: a1d7c116fcf7 ("media: camms: Add core files") Cc: stable@vger.kernel.org Signed-off-by: Vladimir Zapolskiy vladimir.zapolskiy@linaro.org Reviewed-by: Bryan O'Donoghue bryan.odonoghue@linaro.org Signed-off-by: Bryan O'Donoghue bod@kernel.org Signed-off-by: Hans Verkuil hverkuil@xs4all.nl Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/media/platform/qcom/camss/camss.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
--- a/drivers/media/platform/qcom/camss/camss.c +++ b/drivers/media/platform/qcom/camss/camss.c @@ -3625,7 +3625,7 @@ static int camss_probe(struct platform_d ret = v4l2_device_register(camss->dev, &camss->v4l2_dev); if (ret < 0) { dev_err(dev, "Failed to register V4L2 device: %d\n", ret); - goto err_genpd_cleanup; + goto err_media_device_cleanup; }
v4l2_async_nf_init(&camss->notifier, &camss->v4l2_dev); @@ -3680,6 +3680,8 @@ err_v4l2_device_unregister: v4l2_device_unregister(&camss->v4l2_dev); v4l2_async_nf_cleanup(&camss->notifier); pm_runtime_disable(dev); +err_media_device_cleanup: + media_device_cleanup(&camss->media_dev); err_genpd_cleanup: camss_genpd_cleanup(camss);
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Bryan O'Donoghue bryan.odonoghue@linaro.org
commit c26e8dcd9d4e86d788c5bf7a5dd0ea70a95ab067 upstream.
The -supply postfix is wrong but wasn't noticed on the CRD devices or indeed the Dell devices, however on Lenovo devices the error comes up.
Fixes: 1830cf0f56c3 ("media: qcom: camss: Add x1e80100 specific support") Cc: stable@vger.kernel.org Signed-off-by: Bryan O'Donoghue bryan.odonoghue@linaro.org [bod: reworded commit log per Konrad's feedback] Reviewed-by: Konrad Dybcio konrad.dybcio@oss.qualcomm.com Signed-off-by: Hans Verkuil hverkuil@xs4all.nl Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/media/platform/qcom/camss/camss.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-)
diff --git a/drivers/media/platform/qcom/camss/camss.c b/drivers/media/platform/qcom/camss/camss.c index e1d64c8f42ae..e08e70b93824 100644 --- a/drivers/media/platform/qcom/camss/camss.c +++ b/drivers/media/platform/qcom/camss/camss.c @@ -2486,8 +2486,8 @@ static const struct resources_icc icc_res_sm8550[] = { static const struct camss_subdev_resources csiphy_res_x1e80100[] = { /* CSIPHY0 */ { - .regulators = { "vdd-csiphy-0p8-supply", - "vdd-csiphy-1p2-supply" }, + .regulators = { "vdd-csiphy-0p8", + "vdd-csiphy-1p2" }, .clock = { "csiphy0", "csiphy0_timer" }, .clock_rate = { { 300000000, 400000000, 480000000 }, { 266666667, 400000000 } }, @@ -2501,8 +2501,8 @@ static const struct camss_subdev_resources csiphy_res_x1e80100[] = { }, /* CSIPHY1 */ { - .regulators = { "vdd-csiphy-0p8-supply", - "vdd-csiphy-1p2-supply" }, + .regulators = { "vdd-csiphy-0p8", + "vdd-csiphy-1p2" }, .clock = { "csiphy1", "csiphy1_timer" }, .clock_rate = { { 300000000, 400000000, 480000000 }, { 266666667, 400000000 } }, @@ -2516,8 +2516,8 @@ static const struct camss_subdev_resources csiphy_res_x1e80100[] = { }, /* CSIPHY2 */ { - .regulators = { "vdd-csiphy-0p8-supply", - "vdd-csiphy-1p2-supply" }, + .regulators = { "vdd-csiphy-0p8", + "vdd-csiphy-1p2" }, .clock = { "csiphy2", "csiphy2_timer" }, .clock_rate = { { 300000000, 400000000, 480000000 }, { 266666667, 400000000 } }, @@ -2531,8 +2531,8 @@ static const struct camss_subdev_resources csiphy_res_x1e80100[] = { }, /* CSIPHY4 */ { - .regulators = { "vdd-csiphy-0p8-supply", - "vdd-csiphy-1p2-supply" }, + .regulators = { "vdd-csiphy-0p8", + "vdd-csiphy-1p2" }, .clock = { "csiphy4", "csiphy4_timer" }, .clock_rate = { { 300000000, 400000000, 480000000 }, { 266666667, 400000000 } },
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Vedang Nagar quic_vnagar@quicinc.com
commit 49befc830daa743e051a65468c05c2ff9e8580e6 upstream.
Add a check to ensure that the packet size does not exceed the number of available words after reading the packet header from shared memory. This ensures that the size provided by the firmware is safe to process and prevent potential out-of-bounds memory access.
Fixes: d96d3f30c0f2 ("[media] media: venus: hfi: add Venus HFI files") Cc: stable@vger.kernel.org Signed-off-by: Vedang Nagar quic_vnagar@quicinc.com Co-developed-by: Dikshita Agarwal quic_dikshita@quicinc.com Signed-off-by: Dikshita Agarwal quic_dikshita@quicinc.com Reviewed-by: Bryan O'Donoghue bryan.odonoghue@linaro.org Signed-off-by: Bryan O'Donoghue bod@kernel.org Signed-off-by: Hans Verkuil hverkuil@xs4all.nl Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/media/platform/qcom/venus/hfi_venus.c | 4 ++++ 1 file changed, 4 insertions(+)
--- a/drivers/media/platform/qcom/venus/hfi_venus.c +++ b/drivers/media/platform/qcom/venus/hfi_venus.c @@ -239,6 +239,7 @@ static int venus_write_queue(struct venu static int venus_read_queue(struct venus_hfi_device *hdev, struct iface_queue *queue, void *pkt, u32 *tx_req) { + struct hfi_pkt_hdr *pkt_hdr = NULL; struct hfi_queue_header *qhdr; u32 dwords, new_rd_idx; u32 rd_idx, wr_idx, type, qsize; @@ -304,6 +305,9 @@ static int venus_read_queue(struct venus memcpy(pkt, rd_ptr, len); memcpy(pkt + len, queue->qmem.kva, new_rd_idx << 2); } + pkt_hdr = (struct hfi_pkt_hdr *)(pkt); + if ((pkt_hdr->size >> 2) != dwords) + return -EINVAL; } else { /* bad packet received, dropping */ new_rd_idx = qhdr->write_idx;
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Konrad Dybcio konrad.dybcio@oss.qualcomm.com
commit ee3b94f22638e0f7a1893d95d87b08698b680052 upstream.
Fill in the correct data for the production SKU.
Fixes: 193b3dac29a4 ("media: venus: add msm8998 support") Cc: stable@vger.kernel.org Signed-off-by: Konrad Dybcio konrad.dybcio@oss.qualcomm.com Reviewed-by: Vikash Garodia quic_vgarodia@quicinc.com Reviewed-by: Bryan O'Donoghue bryan.odonoghue@linaro.org Reviewed-by: Dmitry Baryshkov dmitry.baryshkov@oss.qualcomm.com Signed-off-by: Bryan O'Donoghue bod@kernel.org Signed-off-by: Hans Verkuil hverkuil@xs4all.nl Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/media/platform/qcom/venus/core.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-)
--- a/drivers/media/platform/qcom/venus/core.c +++ b/drivers/media/platform/qcom/venus/core.c @@ -709,11 +709,11 @@ static const struct venus_resources msm8 };
static const struct freq_tbl msm8998_freq_table[] = { - { 1944000, 465000000 }, /* 4k UHD @ 60 (decode only) */ - { 972000, 465000000 }, /* 4k UHD @ 30 */ - { 489600, 360000000 }, /* 1080p @ 60 */ - { 244800, 186000000 }, /* 1080p @ 30 */ - { 108000, 100000000 }, /* 720p @ 30 */ + { 1728000, 533000000 }, /* 4k UHD @ 60 (decode only) */ + { 1036800, 444000000 }, /* 2k @ 120 */ + { 829440, 355200000 }, /* 4k @ 44 */ + { 489600, 269330000 },/* 4k @ 30 */ + { 108000, 200000000 }, /* 1080p @ 60 */ };
static const struct reg_val msm8998_reg_preset[] = {
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jorge Ramirez-Ortiz jorge.ramirez@oss.qualcomm.com
commit 640803003cd903cea73dc6a86bf6963e238e2b3f upstream.
Ensure the IRQ is disabled - and all pending handlers completed - before dismantling the interrupt routing and clearing related pointers.
This prevents any possibility of the interrupt triggering after the handler context has been invalidated.
Fixes: d96d3f30c0f2 ("[media] media: venus: hfi: add Venus HFI files") Cc: stable@vger.kernel.org Signed-off-by: Jorge Ramirez-Ortiz jorge.ramirez@oss.qualcomm.com Reviewed-by: Dikshita Agarwal quic_dikshita@quicinc.com Tested-by: Dikshita Agarwal quic_dikshita@quicinc.com # RB5 Reviewed-by: Bryan O'Donoghue bryan.odonoghue@linaro.org Signed-off-by: Bryan O'Donoghue bod@kernel.org Signed-off-by: Hans Verkuil hverkuil@xs4all.nl Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/media/platform/qcom/venus/hfi_venus.c | 1 + 1 file changed, 1 insertion(+)
--- a/drivers/media/platform/qcom/venus/hfi_venus.c +++ b/drivers/media/platform/qcom/venus/hfi_venus.c @@ -1682,6 +1682,7 @@ void venus_hfi_destroy(struct venus_core venus_interface_queues_release(hdev); mutex_destroy(&hdev->lock); kfree(hdev); + disable_irq(core->irq); core->ops = NULL; }
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jorge Ramirez-Ortiz jorge.ramirez@oss.qualcomm.com
commit 3200144a2fa4209dc084a19941b9b203b43580f0 upstream.
Make sure the interrupt handler is initialized before the interrupt is registered.
If the IRQ is registered before hfi_create(), it's possible that an interrupt fires before the handler setup is complete, leading to a NULL dereference.
This error condition has been observed during system boot on Rb3Gen2.
Fixes: af2c3834c8ca ("[media] media: venus: adding core part and helper functions") Cc: stable@vger.kernel.org Signed-off-by: Jorge Ramirez-Ortiz jorge.ramirez@oss.qualcomm.com Reviewed-by: Bryan O'Donoghue bryan.odonoghue@linaro.org Reviewed-by: Vikash Garodia quic_vgarodia@quicinc.com Reviewed-by: Dikshita Agarwal quic_dikshita@quicinc.com Tested-by: Dikshita Agarwal quic_dikshita@quicinc.com # RB5 Signed-off-by: Bryan O'Donoghue bod@kernel.org Signed-off-by: Hans Verkuil hverkuil@xs4all.nl Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/media/platform/qcom/venus/core.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-)
--- a/drivers/media/platform/qcom/venus/core.c +++ b/drivers/media/platform/qcom/venus/core.c @@ -424,13 +424,13 @@ static int venus_probe(struct platform_d INIT_DELAYED_WORK(&core->work, venus_sys_error_handler); init_waitqueue_head(&core->sys_err_done);
- ret = devm_request_threaded_irq(dev, core->irq, hfi_isr, venus_isr_thread, - IRQF_TRIGGER_HIGH | IRQF_ONESHOT, - "venus", core); + ret = hfi_create(core, &venus_core_ops); if (ret) goto err_core_put;
- ret = hfi_create(core, &venus_core_ops); + ret = devm_request_threaded_irq(dev, core->irq, hfi_isr, venus_isr_thread, + IRQF_TRIGGER_HIGH | IRQF_ONESHOT, + "venus", core); if (ret) goto err_core_put;
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ricardo Ribalda ribalda@chromium.org
commit 377dc500d253f0b26732b2cb062e89668aef890a upstream.
The driver uses "whole" fps in all its calculations (e.g. in load_per_instance()). Those calculation expect an fps bigger than 1, and not big enough to overflow.
Clamp the value if the user provides a param that will result in an invalid fps.
Reported-by: Hans Verkuil hverkuil@xs4all.nl Closes: https://lore.kernel.org/linux-media/f11653a7-bc49-48cd-9cdb-1659147453e4@xs4... Fixes: 7472c1c69138 ("[media] media: venus: vdec: add video decoder files") Cc: stable@vger.kernel.org Tested-by: Bryan O'Donoghue bryan.odonoghue@linaro.org # qrb5615-rb5 Reviewed-by: Bryan O'Donoghue bryan.odonoghue@linaro.org Signed-off-by: Ricardo Ribalda ribalda@chromium.org [bod: Change "parm" to "param"] Signed-off-by: Bryan O'Donoghue bod@kernel.org Signed-off-by: Hans Verkuil hverkuil@xs4all.nl Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/media/platform/qcom/venus/core.h | 2 ++ drivers/media/platform/qcom/venus/vdec.c | 5 ++--- 2 files changed, 4 insertions(+), 3 deletions(-)
--- a/drivers/media/platform/qcom/venus/core.h +++ b/drivers/media/platform/qcom/venus/core.h @@ -28,6 +28,8 @@ #define VIDC_RESETS_NUM_MAX 2 #define VIDC_MAX_HIER_CODING_LAYER 6
+#define VENUS_MAX_FPS 240 + extern int venus_fw_debug;
struct freq_tbl { --- a/drivers/media/platform/qcom/venus/vdec.c +++ b/drivers/media/platform/qcom/venus/vdec.c @@ -481,11 +481,10 @@ static int vdec_s_parm(struct file *file us_per_frame = timeperframe->numerator * (u64)USEC_PER_SEC; do_div(us_per_frame, timeperframe->denominator);
- if (!us_per_frame) - return -EINVAL; - + us_per_frame = clamp(us_per_frame, 1, USEC_PER_SEC); fps = (u64)USEC_PER_SEC; do_div(fps, us_per_frame); + fps = min(VENUS_MAX_FPS, fps);
inst->fps = fps; inst->timeperframe = *timeperframe;
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ricardo Ribalda ribalda@chromium.org
commit 417c01b92ec278a1118a05c6ad8a796eaa0c9c52 upstream.
The driver uses "whole" fps in all its calculations (e.g. in load_per_instance()). Those calculation expect an fps bigger than 1, and not big enough to overflow.
Clamp the param if the user provides a value that will result in an invalid fps.
Reported-by: Hans Verkuil hverkuil@xs4all.nl Closes: https://lore.kernel.org/linux-media/f11653a7-bc49-48cd-9cdb-1659147453e4@xs4... Fixes: aaaa93eda64b ("[media] media: venus: venc: add video encoder files") Cc: stable@vger.kernel.org Signed-off-by: Ricardo Ribalda ribalda@chromium.org [bod: Change "parm" to "param"] Signed-off-by: Bryan O'Donoghue bod@kernel.org Signed-off-by: Hans Verkuil hverkuil@xs4all.nl Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/media/platform/qcom/venus/venc.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-)
--- a/drivers/media/platform/qcom/venus/venc.c +++ b/drivers/media/platform/qcom/venus/venc.c @@ -411,11 +411,10 @@ static int venc_s_parm(struct file *file us_per_frame = timeperframe->numerator * (u64)USEC_PER_SEC; do_div(us_per_frame, timeperframe->denominator);
- if (!us_per_frame) - return -EINVAL; - + us_per_frame = clamp(us_per_frame, 1, USEC_PER_SEC); fps = (u64)USEC_PER_SEC; do_div(fps, us_per_frame); + fps = min(VENUS_MAX_FPS, fps);
inst->timeperframe = *timeperframe; inst->fps = fps;
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Dikshita Agarwal quic_dikshita@quicinc.com
commit caf2055487694b6cb52f2ecb161c6c5de660dd72 upstream.
During reconfig, the firmware sends the resolution aligned to 8 bytes. If the driver sends the same resolution back to the firmware the resolution will be aligned to 16 bytes not 8.
The alignment mismatch would then subsequently cause the firmware to send another redundant sequence change event.
Fix this by not setting the resolution property during reconfig.
Cc: stable@vger.kernel.org Fixes: 3a19d7b9e08b ("media: iris: implement set properties to firmware during streamon") Reviewed-by: Bryan O'Donoghue bryan.odonoghue@linaro.org Tested-by: Neil Armstrong neil.armstrong@linaro.org # on SM8550-QRD Tested-by: Neil Armstrong neil.armstrong@linaro.org # on SM8550-HDK Tested-by: Neil Armstrong neil.armstrong@linaro.org # on SM8650-QRD Tested-by: Neil Armstrong neil.armstrong@linaro.org # on SM8650-HDK Signed-off-by: Dikshita Agarwal quic_dikshita@quicinc.com Tested-by: Vikash Garodia quic_vgarodia@quicinc.com # on sa8775p-ride Signed-off-by: Bryan O'Donoghue bod@kernel.org Signed-off-by: Hans Verkuil hverkuil@xs4all.nl Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/media/platform/qcom/iris/iris_hfi_gen1_command.c | 15 ++++++++------- drivers/media/platform/qcom/iris/iris_state.c | 2 +- drivers/media/platform/qcom/iris/iris_state.h | 1 + 3 files changed, 10 insertions(+), 8 deletions(-)
--- a/drivers/media/platform/qcom/iris/iris_hfi_gen1_command.c +++ b/drivers/media/platform/qcom/iris/iris_hfi_gen1_command.c @@ -546,14 +546,15 @@ static int iris_hfi_gen1_set_resolution( struct hfi_framesize fs; int ret;
- fs.buffer_type = HFI_BUFFER_INPUT; - fs.width = inst->fmt_src->fmt.pix_mp.width; - fs.height = inst->fmt_src->fmt.pix_mp.height; - - ret = hfi_gen1_set_property(inst, ptype, &fs, sizeof(fs)); - if (ret) - return ret; + if (!iris_drc_pending(inst)) { + fs.buffer_type = HFI_BUFFER_INPUT; + fs.width = inst->fmt_src->fmt.pix_mp.width; + fs.height = inst->fmt_src->fmt.pix_mp.height;
+ ret = hfi_gen1_set_property(inst, ptype, &fs, sizeof(fs)); + if (ret) + return ret; + } fs.buffer_type = HFI_BUFFER_OUTPUT2; fs.width = inst->fmt_dst->fmt.pix_mp.width; fs.height = inst->fmt_dst->fmt.pix_mp.height; --- a/drivers/media/platform/qcom/iris/iris_state.c +++ b/drivers/media/platform/qcom/iris/iris_state.c @@ -245,7 +245,7 @@ int iris_inst_sub_state_change_pause(str return iris_inst_change_sub_state(inst, 0, set_sub_state); }
-static inline bool iris_drc_pending(struct iris_inst *inst) +bool iris_drc_pending(struct iris_inst *inst) { return inst->sub_state & IRIS_INST_SUB_DRC && inst->sub_state & IRIS_INST_SUB_DRC_LAST; --- a/drivers/media/platform/qcom/iris/iris_state.h +++ b/drivers/media/platform/qcom/iris/iris_state.h @@ -140,5 +140,6 @@ int iris_inst_sub_state_change_drain_las int iris_inst_sub_state_change_drc_last(struct iris_inst *inst); int iris_inst_sub_state_change_pause(struct iris_inst *inst, u32 plane); bool iris_allow_cmd(struct iris_inst *inst, u32 cmd); +bool iris_drc_pending(struct iris_inst *inst);
#endif
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Dikshita Agarwal quic_dikshita@quicinc.com
commit f3516f856d1f11d9dff7d72491d474a2bae1cf8e upstream.
Currently, port check enforces that session property response must arrive only on the BITSTREAM port. However, firmware can send some responses on other port as well.
Remove the strict port validation to correctly handle session property responses from the firmware.
Cc: stable@vger.kernel.org Fixes: 3a19d7b9e08b ("media: iris: implement set properties to firmware during streamon") Acked-by: Vikash Garodia quic_vgarodia@quicinc.com Tested-by: Neil Armstrong neil.armstrong@linaro.org # on SM8550-QRD Tested-by: Neil Armstrong neil.armstrong@linaro.org # on SM8550-HDK Tested-by: Neil Armstrong neil.armstrong@linaro.org # on SM8650-QRD Tested-by: Neil Armstrong neil.armstrong@linaro.org # on SM8650-HDK Signed-off-by: Dikshita Agarwal quic_dikshita@quicinc.com Tested-by: Vikash Garodia quic_vgarodia@quicinc.com # on sa8775p-ride Signed-off-by: Bryan O'Donoghue bod@kernel.org Signed-off-by: Hans Verkuil hverkuil@xs4all.nl Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/media/platform/qcom/iris/iris_hfi_gen2_response.c | 3 --- 1 file changed, 3 deletions(-)
diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen2_response.c b/drivers/media/platform/qcom/iris/iris_hfi_gen2_response.c index b75a01641d5d..d1a2a497a7b2 100644 --- a/drivers/media/platform/qcom/iris/iris_hfi_gen2_response.c +++ b/drivers/media/platform/qcom/iris/iris_hfi_gen2_response.c @@ -636,9 +636,6 @@ static int iris_hfi_gen2_handle_session_property(struct iris_inst *inst, { struct iris_inst_hfi_gen2 *inst_hfi_gen2 = to_iris_inst_hfi_gen2(inst);
- if (pkt->port != HFI_PORT_BITSTREAM) - return 0; - if (pkt->flags & HFI_FW_FLAGS_INFORMATION) return 0;
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Dikshita Agarwal quic_dikshita@quicinc.com
commit 91c6d55b477e1b66578c268214e915dff9f5ea57 upstream.
When the resolution changes, the driver internally updates the width and height, but the client continue to queue buffers with the older resolution until the last flag is received. This results in a mismatch when the buffers are prepared, causing failure due to outdated size.
Introduce a check to prevent size validation during buffer preparation if a resolution reconfiguration is in progress, to handle this.
Cc: stable@vger.kernel.org Fixes: 17f2a485ca67 ("media: iris: implement vb2 ops for buf_queue and firmware response") Reviewed-by: Vikash Garodia quic_vgarodia@quicinc.com Tested-by: Neil Armstrong neil.armstrong@linaro.org # on SM8550-QRD Tested-by: Neil Armstrong neil.armstrong@linaro.org # on SM8550-HDK Tested-by: Neil Armstrong neil.armstrong@linaro.org # on SM8650-QRD Tested-by: Neil Armstrong neil.armstrong@linaro.org # on SM8650-HDK Signed-off-by: Dikshita Agarwal quic_dikshita@quicinc.com Tested-by: Vikash Garodia quic_vgarodia@quicinc.com # on sa8775p-ride Signed-off-by: Bryan O'Donoghue bod@kernel.org Signed-off-by: Hans Verkuil hverkuil@xs4all.nl Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/media/platform/qcom/iris/iris_vb2.c | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-)
diff --git a/drivers/media/platform/qcom/iris/iris_vb2.c b/drivers/media/platform/qcom/iris/iris_vb2.c index cdf11feb590b..b3bde10eb6d2 100644 --- a/drivers/media/platform/qcom/iris/iris_vb2.c +++ b/drivers/media/platform/qcom/iris/iris_vb2.c @@ -259,13 +259,14 @@ int iris_vb2_buf_prepare(struct vb2_buffer *vb) return -EINVAL; }
- if (vb->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE && - vb2_plane_size(vb, 0) < iris_get_buffer_size(inst, BUF_OUTPUT)) - return -EINVAL; - if (vb->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE && - vb2_plane_size(vb, 0) < iris_get_buffer_size(inst, BUF_INPUT)) - return -EINVAL; - + if (!(inst->sub_state & IRIS_INST_SUB_DRC)) { + if (vb->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE && + vb2_plane_size(vb, 0) < iris_get_buffer_size(inst, BUF_OUTPUT)) + return -EINVAL; + if (vb->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE && + vb2_plane_size(vb, 0) < iris_get_buffer_size(inst, BUF_INPUT)) + return -EINVAL; + } return 0; }
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Dikshita Agarwal quic_dikshita@quicinc.com
commit c314a28cdabe45f050fe7bd403ddeaf4b9c960d1 upstream.
The function pointers responsible for setting firmware properties were never initialized in the instance capability structure, causing it to remain NULL. As a result, the firmware properties were not being set correctly.
Fix this by properly assigning the function pointers from the core capability to the instance capability, ensuring that the properties are correctly applied to the firmware.
Cc: stable@vger.kernel.org Fixes: 3a19d7b9e08b ("media: iris: implement set properties to firmware during streamon") Acked-by: Vikash Garodia quic_vgarodia@quicinc.com Reviewed-by: Bryan O'Donoghue bryan.odonoghue@linaro.org Tested-by: Neil Armstrong neil.armstrong@linaro.org # on SM8550-QRD Tested-by: Neil Armstrong neil.armstrong@linaro.org # on SM8550-HDK Tested-by: Neil Armstrong neil.armstrong@linaro.org # on SM8650-QRD Tested-by: Neil Armstrong neil.armstrong@linaro.org # on SM8650-HDK Signed-off-by: Dikshita Agarwal quic_dikshita@quicinc.com Tested-by: Vikash Garodia quic_vgarodia@quicinc.com # on sa8775p-ride Signed-off-by: Bryan O'Donoghue bod@kernel.org Signed-off-by: Hans Verkuil hverkuil@xs4all.nl Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/media/platform/qcom/iris/iris_ctrls.c | 1 + 1 file changed, 1 insertion(+)
--- a/drivers/media/platform/qcom/iris/iris_ctrls.c +++ b/drivers/media/platform/qcom/iris/iris_ctrls.c @@ -163,6 +163,7 @@ void iris_session_init_caps(struct iris_ core->inst_fw_caps[cap_id].value = caps[i].value; core->inst_fw_caps[cap_id].flags = caps[i].flags; core->inst_fw_caps[cap_id].hfi_id = caps[i].hfi_id; + core->inst_fw_caps[cap_id].set = caps[i].set; } }
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Dikshita Agarwal quic_dikshita@quicinc.com
commit 0f837559ccdd275c5a059e6ac4d5034b03409f1d upstream.
A warning reported by smatch indicated a possible null pointer dereference where one of the arguments to API "iris_hfi_gen2_handle_system_error" could sometimes be null.
To fix this, add a check to validate that the argument passed is not null before accessing its members.
Cc: stable@vger.kernel.org Fixes: fb583a214337 ("media: iris: introduce host firmware interface with necessary hooks") Reported-by: Dan Carpenter dan.carpenter@linaro.org Closes: https://lore.kernel.org/linux-media/634cc9b8-f099-4b54-8556-d879fb2b5169@sta... Acked-by: Vikash Garodia quic_vgarodia@quicinc.com Reviewed-by: Bryan O'Donoghue bryan.odonoghue@linaro.org Tested-by: Neil Armstrong neil.armstrong@linaro.org # on SM8550-QRD Tested-by: Neil Armstrong neil.armstrong@linaro.org # on SM8550-HDK Tested-by: Neil Armstrong neil.armstrong@linaro.org # on SM8650-QRD Tested-by: Neil Armstrong neil.armstrong@linaro.org # on SM8650-HDK Signed-off-by: Dikshita Agarwal quic_dikshita@quicinc.com Tested-by: Vikash Garodia quic_vgarodia@quicinc.com # on sa8775p-ride Signed-off-by: Bryan O'Donoghue bod@kernel.org Signed-off-by: Hans Verkuil hverkuil@xs4all.nl Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/media/platform/qcom/iris/iris_hfi_gen2_response.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen2_response.c b/drivers/media/platform/qcom/iris/iris_hfi_gen2_response.c index d1a2a497a7b2..4488540d1d41 100644 --- a/drivers/media/platform/qcom/iris/iris_hfi_gen2_response.c +++ b/drivers/media/platform/qcom/iris/iris_hfi_gen2_response.c @@ -265,7 +265,8 @@ static int iris_hfi_gen2_handle_system_error(struct iris_core *core, { struct iris_inst *instance;
- dev_err(core->dev, "received system error of type %#x\n", pkt->type); + if (pkt) + dev_err(core->dev, "received system error of type %#x\n", pkt->type);
core->state = IRIS_CORE_ERROR;
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Dikshita Agarwal quic_dikshita@quicinc.com
commit 58edc8a68de7af45a4c815636595daa530f02c13 upstream.
Correct a typo from "dpeth" to "depth".
Cc: stable@vger.kernel.org Fixes: 3a19d7b9e08b ("media: iris: implement set properties to firmware during streamon") Acked-by: Vikash Garodia quic_vgarodia@quicinc.com Reviewed-by: Bryan O'Donoghue bryan.odonoghue@linaro.org Tested-by: Neil Armstrong neil.armstrong@linaro.org # on SM8550-QRD Tested-by: Neil Armstrong neil.armstrong@linaro.org # on SM8550-HDK Tested-by: Neil Armstrong neil.armstrong@linaro.org # on SM8650-QRD Tested-by: Neil Armstrong neil.armstrong@linaro.org # on SM8650-HDK Signed-off-by: Dikshita Agarwal quic_dikshita@quicinc.com Tested-by: Vikash Garodia quic_vgarodia@quicinc.com # on sa8775p-ride Signed-off-by: Bryan O'Donoghue bod@kernel.org Signed-off-by: Hans Verkuil hverkuil@xs4all.nl Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/media/platform/qcom/iris/iris_hfi_gen2_command.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen2_command.c b/drivers/media/platform/qcom/iris/iris_hfi_gen2_command.c index a908b41e2868..802fa62c26eb 100644 --- a/drivers/media/platform/qcom/iris/iris_hfi_gen2_command.c +++ b/drivers/media/platform/qcom/iris/iris_hfi_gen2_command.c @@ -178,7 +178,7 @@ static int iris_hfi_gen2_set_crop_offsets(struct iris_inst *inst) sizeof(u64)); }
-static int iris_hfi_gen2_set_bit_dpeth(struct iris_inst *inst) +static int iris_hfi_gen2_set_bit_depth(struct iris_inst *inst) { struct iris_inst_hfi_gen2 *inst_hfi_gen2 = to_iris_inst_hfi_gen2(inst); u32 port = iris_hfi_gen2_get_port(V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE); @@ -378,7 +378,7 @@ static int iris_hfi_gen2_session_set_config_params(struct iris_inst *inst, u32 p {HFI_PROP_BITSTREAM_RESOLUTION, iris_hfi_gen2_set_bitstream_resolution }, {HFI_PROP_CROP_OFFSETS, iris_hfi_gen2_set_crop_offsets }, {HFI_PROP_CODED_FRAMES, iris_hfi_gen2_set_coded_frames }, - {HFI_PROP_LUMA_CHROMA_BIT_DEPTH, iris_hfi_gen2_set_bit_dpeth }, + {HFI_PROP_LUMA_CHROMA_BIT_DEPTH, iris_hfi_gen2_set_bit_depth }, {HFI_PROP_BUFFER_FW_MIN_OUTPUT_COUNT, iris_hfi_gen2_set_min_output_count }, {HFI_PROP_PIC_ORDER_CNT_TYPE, iris_hfi_gen2_set_picture_order_count }, {HFI_PROP_SIGNAL_COLOR_INFO, iris_hfi_gen2_set_colorspace },
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Dikshita Agarwal quic_dikshita@quicinc.com
commit 2781662dee7bbb9675e5440f5dff4e3991dc5624 upstream.
The current check only considers the core error state before allowing writes to the HFI queues. However, the core can also transition to the deinit state due to a system error triggered by the response thread. In such cases, writing to the HFI queues should not be allowed.
Fix this by adding a check for the core deinit state, ensuring that writes are rejected when core is not in a valid state.
Cc: stable@vger.kernel.org Fixes: fb583a214337 ("media: iris: introduce host firmware interface with necessary hooks") Acked-by: Vikash Garodia quic_vgarodia@quicinc.com Tested-by: Neil Armstrong neil.armstrong@linaro.org # on SM8550-QRD Tested-by: Neil Armstrong neil.armstrong@linaro.org # on SM8550-HDK Tested-by: Neil Armstrong neil.armstrong@linaro.org # on SM8650-QRD Tested-by: Neil Armstrong neil.armstrong@linaro.org # on SM8650-HDK Signed-off-by: Dikshita Agarwal quic_dikshita@quicinc.com Reviewed-by: Bryan O'Donoghue bryan.odonoghue@linaro.org Tested-by: Vikash Garodia quic_vgarodia@quicinc.com # on sa8775p-ride Signed-off-by: Bryan O'Donoghue bod@kernel.org Signed-off-by: Hans Verkuil hverkuil@xs4all.nl Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/media/platform/qcom/iris/iris_hfi_queue.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
--- a/drivers/media/platform/qcom/iris/iris_hfi_queue.c +++ b/drivers/media/platform/qcom/iris/iris_hfi_queue.c @@ -113,7 +113,7 @@ int iris_hfi_queue_cmd_write_locked(stru { struct iris_iface_q_info *q_info = &core->command_queue;
- if (core->state == IRIS_CORE_ERROR) + if (core->state == IRIS_CORE_ERROR || core->state == IRIS_CORE_DEINIT) return -EINVAL;
if (!iris_hfi_queue_write(q_info, pkt, pkt_size)) {
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Dikshita Agarwal quic_dikshita@quicinc.com
commit a693b4a3e7a95c010bedef4c8b3122bd8b0961b7 upstream.
HFI_PROPERTY_CONFIG_VDEC_POST_LOOP_DEBLOCKER is deprecated and no longer supported on current firmware, remove setting the same to firmware.
Cc: stable@vger.kernel.org Fixes: 79865252acb6 ("media: iris: enable video driver probe of SM8250 SoC") Acked-by: Vikash Garodia quic_vgarodia@quicinc.com Tested-by: Neil Armstrong neil.armstrong@linaro.org # on SM8550-QRD Tested-by: Neil Armstrong neil.armstrong@linaro.org # on SM8550-HDK Tested-by: Neil Armstrong neil.armstrong@linaro.org # on SM8650-QRD Tested-by: Neil Armstrong neil.armstrong@linaro.org # on SM8650-HDK Signed-off-by: Dikshita Agarwal quic_dikshita@quicinc.com Tested-by: Vikash Garodia quic_vgarodia@quicinc.com # on sa8775p-ride Signed-off-by: Bryan O'Donoghue bod@kernel.org Signed-off-by: Hans Verkuil hverkuil@xs4all.nl Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/media/platform/qcom/iris/iris_ctrls.c | 4 ---- drivers/media/platform/qcom/iris/iris_hfi_gen1_command.c | 8 -------- drivers/media/platform/qcom/iris/iris_hfi_gen1_defines.h | 1 - drivers/media/platform/qcom/iris/iris_platform_common.h | 2 +- drivers/media/platform/qcom/iris/iris_platform_sm8250.c | 9 --------- 5 files changed, 1 insertion(+), 23 deletions(-)
--- a/drivers/media/platform/qcom/iris/iris_ctrls.c +++ b/drivers/media/platform/qcom/iris/iris_ctrls.c @@ -17,8 +17,6 @@ static inline bool iris_valid_cap_id(enu static enum platform_inst_fw_cap_type iris_get_cap_id(u32 id) { switch (id) { - case V4L2_CID_MPEG_VIDEO_DECODER_MPEG4_DEBLOCK_FILTER: - return DEBLOCK; case V4L2_CID_MPEG_VIDEO_H264_PROFILE: return PROFILE; case V4L2_CID_MPEG_VIDEO_H264_LEVEL: @@ -34,8 +32,6 @@ static u32 iris_get_v4l2_id(enum platfor return 0;
switch (cap_id) { - case DEBLOCK: - return V4L2_CID_MPEG_VIDEO_DECODER_MPEG4_DEBLOCK_FILTER; case PROFILE: return V4L2_CID_MPEG_VIDEO_H264_PROFILE; case LEVEL: --- a/drivers/media/platform/qcom/iris/iris_hfi_gen1_command.c +++ b/drivers/media/platform/qcom/iris/iris_hfi_gen1_command.c @@ -490,14 +490,6 @@ iris_hfi_gen1_packet_session_set_propert packet->shdr.hdr.size += sizeof(u32) + sizeof(*wm); break; } - case HFI_PROPERTY_CONFIG_VDEC_POST_LOOP_DEBLOCKER: { - struct hfi_enable *en = prop_data; - u32 *in = pdata; - - en->enable = *in; - packet->shdr.hdr.size += sizeof(u32) + sizeof(*en); - break; - } default: return -EINVAL; } --- a/drivers/media/platform/qcom/iris/iris_hfi_gen1_defines.h +++ b/drivers/media/platform/qcom/iris/iris_hfi_gen1_defines.h @@ -65,7 +65,6 @@
#define HFI_PROPERTY_CONFIG_BUFFER_REQUIREMENTS 0x202001
-#define HFI_PROPERTY_CONFIG_VDEC_POST_LOOP_DEBLOCKER 0x1200001 #define HFI_PROPERTY_PARAM_VDEC_DPB_COUNTS 0x120300e #define HFI_PROPERTY_CONFIG_VDEC_ENTROPY 0x1204004
--- a/drivers/media/platform/qcom/iris/iris_platform_common.h +++ b/drivers/media/platform/qcom/iris/iris_platform_common.h @@ -89,7 +89,7 @@ enum platform_inst_fw_cap_type { CODED_FRAMES, BIT_DEPTH, RAP_FRAME, - DEBLOCK, + TIER, INST_FW_CAP_MAX, };
--- a/drivers/media/platform/qcom/iris/iris_platform_sm8250.c +++ b/drivers/media/platform/qcom/iris/iris_platform_sm8250.c @@ -30,15 +30,6 @@ static struct platform_inst_fw_cap inst_ .hfi_id = HFI_PROPERTY_PARAM_WORK_MODE, .set = iris_set_stage, }, - { - .cap_id = DEBLOCK, - .min = 0, - .max = 1, - .step_or_mask = 1, - .value = 0, - .hfi_id = HFI_PROPERTY_CONFIG_VDEC_POST_LOOP_DEBLOCKER, - .set = iris_set_u32, - }, };
static struct platform_inst_caps platform_inst_cap_sm8250 = {
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Dikshita Agarwal quic_dikshita@quicinc.com
commit 03e29ab0e94831fcca2f62c96121fd14263b399b upstream.
Remove the check for non-zero number of v4l2 controls as some SOCs might not expose any capability which requires v4l2 control.
Cc: stable@vger.kernel.org Fixes: 33be1dde17e3 ("media: iris: implement iris v4l2_ctrl_ops") Tested-by: Neil Armstrong neil.armstrong@linaro.org # on SM8550-QRD Tested-by: Neil Armstrong neil.armstrong@linaro.org # on SM8550-HDK Tested-by: Neil Armstrong neil.armstrong@linaro.org # on SM8650-QRD Tested-by: Neil Armstrong neil.armstrong@linaro.org # on SM8650-HDK Signed-off-by: Dikshita Agarwal quic_dikshita@quicinc.com Tested-by: Vikash Garodia quic_vgarodia@quicinc.com # on sa8775p-ride Signed-off-by: Bryan O'Donoghue bod@kernel.org Signed-off-by: Hans Verkuil hverkuil@xs4all.nl Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/media/platform/qcom/iris/iris_ctrls.c | 2 -- 1 file changed, 2 deletions(-)
--- a/drivers/media/platform/qcom/iris/iris_ctrls.c +++ b/drivers/media/platform/qcom/iris/iris_ctrls.c @@ -80,8 +80,6 @@ int iris_ctrls_init(struct iris_inst *in if (iris_get_v4l2_id(cap[idx].cap_id)) num_ctrls++; } - if (!num_ctrls) - return -EINVAL;
/* Adding 1 to num_ctrls to include V4L2_CID_MIN_BUFFERS_FOR_CAPTURE */
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Dikshita Agarwal quic_dikshita@quicinc.com
commit 7adc11e6abf619d0bb0c05918d5da5b9d4bcb81e upstream.
Firmware sends capture buffers with 0 filled length which are not to be displayed and should be dropped by client. To achieve the same, add V4L2_BUF_FLAG_ERROR to such buffers by making sure: - These 0 length buffers are not returned as result of flush. - Its not a buffer with LAST flag enabled which will also have 0 filled length.
Cc: stable@vger.kernel.org Fixes: d09100763bed ("media: iris: add support for drain sequence") Acked-by: Vikash Garodia quic_vgarodia@quicinc.com Tested-by: Neil Armstrong neil.armstrong@linaro.org # on SM8550-QRD Tested-by: Neil Armstrong neil.armstrong@linaro.org # on SM8550-HDK Tested-by: Neil Armstrong neil.armstrong@linaro.org # on SM8650-QRD Tested-by: Neil Armstrong neil.armstrong@linaro.org # on SM8650-HDK Signed-off-by: Dikshita Agarwal quic_dikshita@quicinc.com Tested-by: Vikash Garodia quic_vgarodia@quicinc.com # on sa8775p-ride Signed-off-by: Bryan O'Donoghue bod@kernel.org Signed-off-by: Hans Verkuil hverkuil@xs4all.nl Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/media/platform/qcom/iris/iris_hfi_gen2_response.c | 5 +++++ 1 file changed, 5 insertions(+)
diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen2_response.c b/drivers/media/platform/qcom/iris/iris_hfi_gen2_response.c index 4488540d1d41..d2cede2fe1b5 100644 --- a/drivers/media/platform/qcom/iris/iris_hfi_gen2_response.c +++ b/drivers/media/platform/qcom/iris/iris_hfi_gen2_response.c @@ -378,6 +378,11 @@ static int iris_hfi_gen2_handle_output_buffer(struct iris_inst *inst,
buf->flags = iris_hfi_gen2_get_driver_buffer_flags(inst, hfi_buffer->flags);
+ if (!buf->data_size && inst->state == IRIS_INST_STREAMING && + !(hfi_buffer->flags & HFI_BUF_FW_FLAG_LAST)) { + buf->flags |= V4L2_BUF_FLAG_ERROR; + } + return 0; }
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Dikshita Agarwal quic_dikshita@quicinc.com
commit 7c452ffda30c0460c568273993a3d3c611486467 upstream.
Firmware might hold the DPB buffers for reference in case of sequence change, so skip destroying buffers for which QUEUED flag is not removed.
Cc: stable@vger.kernel.org Fixes: 73702f45db81 ("media: iris: allocate, initialize and queue internal buffers") Reviewed-by: Vikash Garodia quic_vgarodia@quicinc.com Tested-by: Neil Armstrong neil.armstrong@linaro.org # on SM8550-QRD Tested-by: Neil Armstrong neil.armstrong@linaro.org # on SM8550-HDK Tested-by: Neil Armstrong neil.armstrong@linaro.org # on SM8650-QRD Tested-by: Neil Armstrong neil.armstrong@linaro.org # on SM8650-HDK Signed-off-by: Dikshita Agarwal quic_dikshita@quicinc.com Tested-by: Vikash Garodia quic_vgarodia@quicinc.com # on sa8775p-ride Signed-off-by: Bryan O'Donoghue bod@kernel.org Signed-off-by: Hans Verkuil hverkuil@xs4all.nl Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/media/platform/qcom/iris/iris_buffer.c | 20 +++++++++++++++++++- drivers/media/platform/qcom/iris/iris_buffer.h | 3 ++- drivers/media/platform/qcom/iris/iris_vdec.c | 4 ++-- drivers/media/platform/qcom/iris/iris_vidc.c | 4 ++-- 4 files changed, 25 insertions(+), 6 deletions(-)
--- a/drivers/media/platform/qcom/iris/iris_buffer.c +++ b/drivers/media/platform/qcom/iris/iris_buffer.c @@ -376,7 +376,7 @@ int iris_destroy_internal_buffer(struct return 0; }
-int iris_destroy_internal_buffers(struct iris_inst *inst, u32 plane) +static int iris_destroy_internal_buffers(struct iris_inst *inst, u32 plane, bool force) { const struct iris_platform_data *platform_data = inst->core->iris_platform_data; struct iris_buffer *buf, *next; @@ -396,6 +396,14 @@ int iris_destroy_internal_buffers(struct for (i = 0; i < len; i++) { buffers = &inst->buffers[internal_buf_type[i]]; list_for_each_entry_safe(buf, next, &buffers->list, list) { + /* + * during stream on, skip destroying internal(DPB) buffer + * if firmware did not return it. + * during close, destroy all buffers irrespectively. + */ + if (!force && buf->attr & BUF_ATTR_QUEUED) + continue; + ret = iris_destroy_internal_buffer(inst, buf); if (ret) return ret; @@ -405,6 +413,16 @@ int iris_destroy_internal_buffers(struct return 0; }
+int iris_destroy_all_internal_buffers(struct iris_inst *inst, u32 plane) +{ + return iris_destroy_internal_buffers(inst, plane, true); +} + +int iris_destroy_dequeued_internal_buffers(struct iris_inst *inst, u32 plane) +{ + return iris_destroy_internal_buffers(inst, plane, false); +} + static int iris_release_internal_buffers(struct iris_inst *inst, enum iris_buffer_type buffer_type) { --- a/drivers/media/platform/qcom/iris/iris_buffer.h +++ b/drivers/media/platform/qcom/iris/iris_buffer.h @@ -106,7 +106,8 @@ void iris_get_internal_buffers(struct ir int iris_create_internal_buffers(struct iris_inst *inst, u32 plane); int iris_queue_internal_buffers(struct iris_inst *inst, u32 plane); int iris_destroy_internal_buffer(struct iris_inst *inst, struct iris_buffer *buffer); -int iris_destroy_internal_buffers(struct iris_inst *inst, u32 plane); +int iris_destroy_all_internal_buffers(struct iris_inst *inst, u32 plane); +int iris_destroy_dequeued_internal_buffers(struct iris_inst *inst, u32 plane); int iris_alloc_and_queue_persist_bufs(struct iris_inst *inst); int iris_alloc_and_queue_input_int_bufs(struct iris_inst *inst); int iris_queue_buffer(struct iris_inst *inst, struct iris_buffer *buf); --- a/drivers/media/platform/qcom/iris/iris_vdec.c +++ b/drivers/media/platform/qcom/iris/iris_vdec.c @@ -408,7 +408,7 @@ int iris_vdec_streamon_input(struct iris
iris_get_internal_buffers(inst, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE);
- ret = iris_destroy_internal_buffers(inst, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE); + ret = iris_destroy_dequeued_internal_buffers(inst, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE); if (ret) return ret;
@@ -496,7 +496,7 @@ int iris_vdec_streamon_output(struct iri
iris_get_internal_buffers(inst, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE);
- ret = iris_destroy_internal_buffers(inst, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE); + ret = iris_destroy_dequeued_internal_buffers(inst, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE); if (ret) return ret;
--- a/drivers/media/platform/qcom/iris/iris_vidc.c +++ b/drivers/media/platform/qcom/iris/iris_vidc.c @@ -233,8 +233,8 @@ int iris_close(struct file *filp) iris_session_close(inst); iris_inst_change_state(inst, IRIS_INST_DEINIT); iris_v4l2_fh_deinit(inst); - iris_destroy_internal_buffers(inst, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE); - iris_destroy_internal_buffers(inst, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE); + iris_destroy_all_internal_buffers(inst, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE); + iris_destroy_all_internal_buffers(inst, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE); iris_remove_session(inst); mutex_unlock(&inst->lock); mutex_destroy(&inst->ctx_q_lock);
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Dikshita Agarwal quic_dikshita@quicinc.com
commit 1e27e9ffce59ac41cde71673d74eb368a533cdb2 upstream.
Add a condition to skip the flush operation during the first sequence change event. At this point, the capture queue is not streaming, making the flush unnecessary.
Cc: stable@vger.kernel.org Fixes: 84e17adae3e3 ("media: iris: add support for dynamic resolution change") Acked-by: Vikash Garodia quic_vgarodia@quicinc.com Tested-by: Neil Armstrong neil.armstrong@linaro.org # on SM8550-QRD Tested-by: Neil Armstrong neil.armstrong@linaro.org # on SM8550-HDK Tested-by: Neil Armstrong neil.armstrong@linaro.org # on SM8650-QRD Tested-by: Neil Armstrong neil.armstrong@linaro.org # on SM8650-HDK Signed-off-by: Dikshita Agarwal quic_dikshita@quicinc.com Tested-by: Vikash Garodia quic_vgarodia@quicinc.com # on sa8775p-ride Signed-off-by: Bryan O'Donoghue bod@kernel.org Signed-off-by: Hans Verkuil hverkuil@xs4all.nl Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/media/platform/qcom/iris/iris_hfi_gen1_response.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen1_response.c b/drivers/media/platform/qcom/iris/iris_hfi_gen1_response.c index 271e14469223..aaad32a70b9e 100644 --- a/drivers/media/platform/qcom/iris/iris_hfi_gen1_response.c +++ b/drivers/media/platform/qcom/iris/iris_hfi_gen1_response.c @@ -200,7 +200,7 @@ static void iris_hfi_gen1_event_seq_changed(struct iris_inst *inst,
iris_hfi_gen1_read_changed_params(inst, pkt);
- if (inst->state != IRIS_INST_ERROR) { + if (inst->state != IRIS_INST_ERROR && !(inst->sub_state & IRIS_INST_SUB_FIRST_IPSC)) { reinit_completion(&inst->flush_completion);
flush_pkt.shdr.hdr.size = sizeof(struct hfi_session_flush_pkt);
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Dikshita Agarwal quic_dikshita@quicinc.com
commit 9bf58db157139abcd60e425e5718c8e6a917f9dc upstream.
Currently, two types of flush commands are queued to the firmware, the first flush queued as part of sequence change, does not wait for a response, while the second flush queued as part of stop, expects a completion response before proceeding further.
Due to timing issue, the flush response corresponding to the first command could arrive after the second flush is issued. This casuses the driver to incorrectly assume that the second flush has completed, leading to the premature signaling of flush_completion.
To address this, introduce a counter to track the number of pending flush responses and signal flush completion only when all expected responses are received.
Cc: stable@vger.kernel.org Fixes: 11712ce70f8e ("media: iris: implement vb2 streaming ops") Reviewed-by: Vikash Garodia quic_vgarodia@quicinc.com Tested-by: Neil Armstrong neil.armstrong@linaro.org # on SM8550-QRD Tested-by: Neil Armstrong neil.armstrong@linaro.org # on SM8550-HDK Tested-by: Neil Armstrong neil.armstrong@linaro.org # on SM8650-QRD Tested-by: Neil Armstrong neil.armstrong@linaro.org # on SM8650-HDK Signed-off-by: Dikshita Agarwal quic_dikshita@quicinc.com Tested-by: Vikash Garodia quic_vgarodia@quicinc.com # on sa8775p-ride Signed-off-by: Bryan O'Donoghue bod@kernel.org Signed-off-by: Hans Verkuil hverkuil@xs4all.nl Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/media/platform/qcom/iris/iris_hfi_gen1_command.c | 4 ++- drivers/media/platform/qcom/iris/iris_hfi_gen1_response.c | 17 +++++++++----- drivers/media/platform/qcom/iris/iris_instance.h | 2 + 3 files changed, 16 insertions(+), 7 deletions(-)
--- a/drivers/media/platform/qcom/iris/iris_hfi_gen1_command.c +++ b/drivers/media/platform/qcom/iris/iris_hfi_gen1_command.c @@ -208,8 +208,10 @@ static int iris_hfi_gen1_session_stop(st flush_pkt.flush_type = flush_type;
ret = iris_hfi_queue_cmd_write(core, &flush_pkt, flush_pkt.shdr.hdr.size); - if (!ret) + if (!ret) { + inst->flush_responses_pending++; ret = iris_wait_for_session_response(inst, true); + } }
return ret; --- a/drivers/media/platform/qcom/iris/iris_hfi_gen1_response.c +++ b/drivers/media/platform/qcom/iris/iris_hfi_gen1_response.c @@ -207,7 +207,8 @@ static void iris_hfi_gen1_event_seq_chan flush_pkt.shdr.hdr.pkt_type = HFI_CMD_SESSION_FLUSH; flush_pkt.shdr.session_id = inst->session_id; flush_pkt.flush_type = HFI_FLUSH_OUTPUT; - iris_hfi_queue_cmd_write(inst->core, &flush_pkt, flush_pkt.shdr.hdr.size); + if (!iris_hfi_queue_cmd_write(inst->core, &flush_pkt, flush_pkt.shdr.hdr.size)) + inst->flush_responses_pending++; }
iris_vdec_src_change(inst); @@ -408,7 +409,9 @@ static void iris_hfi_gen1_session_ftb_do flush_pkt.shdr.hdr.pkt_type = HFI_CMD_SESSION_FLUSH; flush_pkt.shdr.session_id = inst->session_id; flush_pkt.flush_type = HFI_FLUSH_OUTPUT; - iris_hfi_queue_cmd_write(core, &flush_pkt, flush_pkt.shdr.hdr.size); + if (!iris_hfi_queue_cmd_write(core, &flush_pkt, flush_pkt.shdr.hdr.size)) + inst->flush_responses_pending++; + iris_inst_sub_state_change_drain_last(inst);
return; @@ -564,7 +567,6 @@ static void iris_hfi_gen1_handle_respons const struct iris_hfi_gen1_response_pkt_info *pkt_info; struct device *dev = core->dev; struct hfi_session_pkt *pkt; - struct completion *done; struct iris_inst *inst; bool found = false; u32 i; @@ -625,9 +627,12 @@ static void iris_hfi_gen1_handle_respons if (shdr->error_type != HFI_ERR_NONE) iris_inst_change_state(inst, IRIS_INST_ERROR);
- done = pkt_info->pkt == HFI_MSG_SESSION_FLUSH ? - &inst->flush_completion : &inst->completion; - complete(done); + if (pkt_info->pkt == HFI_MSG_SESSION_FLUSH) { + if (!(--inst->flush_responses_pending)) + complete(&inst->flush_completion); + } else { + complete(&inst->completion); + } } mutex_unlock(&inst->lock);
--- a/drivers/media/platform/qcom/iris/iris_instance.h +++ b/drivers/media/platform/qcom/iris/iris_instance.h @@ -27,6 +27,7 @@ * @crop: structure of crop info * @completion: structure of signal completions * @flush_completion: structure of signal completions for flush cmd + * @flush_responses_pending: counter to track number of pending flush responses * @fw_caps: array of supported instance firmware capabilities * @buffers: array of different iris buffers * @fw_min_count: minimnum count of buffers needed by fw @@ -57,6 +58,7 @@ struct iris_inst { struct iris_hfi_rect_desc crop; struct completion completion; struct completion flush_completion; + u32 flush_responses_pending; struct platform_inst_fw_cap fw_caps[INST_FW_CAP_MAX]; struct iris_buffers buffers[BUF_TYPE_MAX]; u32 fw_min_count;
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Dikshita Agarwal quic_dikshita@quicinc.com
commit 8aadfd445373b74de4a5cd36736843ae01856636 upstream.
Update the width, height and buffer size of CAPTURE based on the resolution set to OUTPUT via VIDIOC_S_FMT. This is required to set the updated capture resolution to firmware when S_FMT is called only for OUTPUT.
Cc: stable@vger.kernel.org Fixes: b530b95de22c ("media: iris: implement s_fmt, g_fmt and try_fmt ioctls") Reviewed-by: Bryan O'Donoghue bryan.odonoghue@linaro.org Acked-by: Vikash Garodia quic_vgarodia@quicinc.com Tested-by: Neil Armstrong neil.armstrong@linaro.org # on SM8550-QRD Tested-by: Neil Armstrong neil.armstrong@linaro.org # on SM8550-HDK Tested-by: Neil Armstrong neil.armstrong@linaro.org # on SM8650-QRD Tested-by: Neil Armstrong neil.armstrong@linaro.org # on SM8650-HDK Signed-off-by: Dikshita Agarwal quic_dikshita@quicinc.com Tested-by: Vikash Garodia quic_vgarodia@quicinc.com # on sa8775p-ride Signed-off-by: Bryan O'Donoghue bod@kernel.org Signed-off-by: Hans Verkuil hverkuil@xs4all.nl Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/media/platform/qcom/iris/iris_vdec.c | 5 +++++ 1 file changed, 5 insertions(+)
diff --git a/drivers/media/platform/qcom/iris/iris_vdec.c b/drivers/media/platform/qcom/iris/iris_vdec.c index 9c049b9671cc..d342f733feb9 100644 --- a/drivers/media/platform/qcom/iris/iris_vdec.c +++ b/drivers/media/platform/qcom/iris/iris_vdec.c @@ -171,6 +171,11 @@ int iris_vdec_s_fmt(struct iris_inst *inst, struct v4l2_format *f) output_fmt->fmt.pix_mp.ycbcr_enc = f->fmt.pix_mp.ycbcr_enc; output_fmt->fmt.pix_mp.quantization = f->fmt.pix_mp.quantization;
+ /* Update capture format based on new ip w/h */ + output_fmt->fmt.pix_mp.width = ALIGN(f->fmt.pix_mp.width, 128); + output_fmt->fmt.pix_mp.height = ALIGN(f->fmt.pix_mp.height, 32); + inst->buffers[BUF_OUTPUT].size = iris_get_buffer_size(inst, BUF_OUTPUT); + inst->crop.left = 0; inst->crop.top = 0; inst->crop.width = f->fmt.pix_mp.width;
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Dikshita Agarwal quic_dikshita@quicinc.com
commit d2abb1ff5a3c13321d407ee19865d0d8d834c7c6 upstream.
Validate all internal buffers queued to firmware are released back to driver on close. This helps ensure buffer lifecycle correctness and aids in debugging any resporce leaks.
Cc: stable@vger.kernel.org Fixes: 73702f45db81 ("media: iris: allocate, initialize and queue internal buffers") Tested-by: Neil Armstrong neil.armstrong@linaro.org # on SM8550-QRD Tested-by: Neil Armstrong neil.armstrong@linaro.org # on SM8550-HDK Tested-by: Neil Armstrong neil.armstrong@linaro.org # on SM8650-QRD Tested-by: Neil Armstrong neil.armstrong@linaro.org # on SM8650-HDK Signed-off-by: Dikshita Agarwal quic_dikshita@quicinc.com Tested-by: Vikash Garodia quic_vgarodia@quicinc.com # on sa8775p-ride Signed-off-by: Bryan O'Donoghue bod@kernel.org Signed-off-by: Hans Verkuil hverkuil@xs4all.nl Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/media/platform/qcom/iris/iris_vidc.c | 29 ++++++++++++++++++++ 1 file changed, 29 insertions(+)
diff --git a/drivers/media/platform/qcom/iris/iris_vidc.c b/drivers/media/platform/qcom/iris/iris_vidc.c index 663f5602b5ad..a8144595cc78 100644 --- a/drivers/media/platform/qcom/iris/iris_vidc.c +++ b/drivers/media/platform/qcom/iris/iris_vidc.c @@ -221,6 +221,33 @@ static void iris_session_close(struct iris_inst *inst) iris_wait_for_session_response(inst, false); }
+static void iris_check_num_queued_internal_buffers(struct iris_inst *inst, u32 plane) +{ + const struct iris_platform_data *platform_data = inst->core->iris_platform_data; + struct iris_buffer *buf, *next; + struct iris_buffers *buffers; + const u32 *internal_buf_type; + u32 internal_buffer_count, i; + u32 count = 0; + + if (V4L2_TYPE_IS_OUTPUT(plane)) { + internal_buf_type = platform_data->dec_ip_int_buf_tbl; + internal_buffer_count = platform_data->dec_ip_int_buf_tbl_size; + } else { + internal_buf_type = platform_data->dec_op_int_buf_tbl; + internal_buffer_count = platform_data->dec_op_int_buf_tbl_size; + } + + for (i = 0; i < internal_buffer_count; i++) { + buffers = &inst->buffers[internal_buf_type[i]]; + list_for_each_entry_safe(buf, next, &buffers->list, list) + count++; + if (count) + dev_err(inst->core->dev, "%d buffer of type %d not released", + count, internal_buf_type[i]); + } +} + int iris_close(struct file *filp) { struct iris_inst *inst = iris_get_inst(filp, NULL); @@ -235,6 +262,8 @@ int iris_close(struct file *filp) iris_v4l2_fh_deinit(inst); iris_destroy_all_internal_buffers(inst, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE); iris_destroy_all_internal_buffers(inst, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE); + iris_check_num_queued_internal_buffers(inst, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE); + iris_check_num_queued_internal_buffers(inst, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE); iris_remove_session(inst); mutex_unlock(&inst->lock); mutex_destroy(&inst->ctx_q_lock);
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Dikshita Agarwal quic_dikshita@quicinc.com
commit b7a898184e74a8261c34f1265139ac1799ee4e1c upstream.
Currently, The flush completion signal is being re-initialized even though no response is expected during a sequence change.
Simplify the code by removing re-initialization of flush completion signal as it is redundant.
Cc: stable@vger.kernel.org Fixes: 84e17adae3e3 ("media: iris: add support for dynamic resolution change") Acked-by: Vikash Garodia quic_vgarodia@quicinc.com Tested-by: Neil Armstrong neil.armstrong@linaro.org # on SM8550-QRD Tested-by: Neil Armstrong neil.armstrong@linaro.org # on SM8550-HDK Tested-by: Neil Armstrong neil.armstrong@linaro.org # on SM8650-QRD Tested-by: Neil Armstrong neil.armstrong@linaro.org # on SM8650-HDK Signed-off-by: Dikshita Agarwal quic_dikshita@quicinc.com Tested-by: Vikash Garodia quic_vgarodia@quicinc.com # on sa8775p-ride Signed-off-by: Bryan O'Donoghue bod@kernel.org Signed-off-by: Hans Verkuil hverkuil@xs4all.nl Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/media/platform/qcom/iris/iris_hfi_gen1_response.c | 1 - 1 file changed, 1 deletion(-)
diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen1_response.c b/drivers/media/platform/qcom/iris/iris_hfi_gen1_response.c index aaad32a70b9e..c8c0aa23536b 100644 --- a/drivers/media/platform/qcom/iris/iris_hfi_gen1_response.c +++ b/drivers/media/platform/qcom/iris/iris_hfi_gen1_response.c @@ -201,7 +201,6 @@ static void iris_hfi_gen1_event_seq_changed(struct iris_inst *inst, iris_hfi_gen1_read_changed_params(inst, pkt);
if (inst->state != IRIS_INST_ERROR && !(inst->sub_state & IRIS_INST_SUB_FIRST_IPSC)) { - reinit_completion(&inst->flush_completion);
flush_pkt.shdr.hdr.size = sizeof(struct hfi_session_flush_pkt); flush_pkt.shdr.hdr.pkt_type = HFI_CMD_SESSION_FLUSH;
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Vodapalli, Ravi Kumar ravi.kumar.vodapalli@intel.com
commit ccfb15b8158c11a8304204aeac354c7b1cfb18a3 upstream.
One additional PCI ID is added in Bspec for BMG, Add it so that driver recognizes this device with this new ID.
Bspec: 68090 Cc: stable@vger.kernel.org # v6.12+ Signed-off-by: Vodapalli, Ravi Kumar ravi.kumar.vodapalli@intel.com Reviewed-by: Shekhar Chauhan shekhar.chauhan@intel.com Acked-by: Matthew Auld matthew.auld@intel.com Signed-off-by: Matthew Auld matthew.auld@intel.com Link: https://lore.kernel.org/r/20250704103527.100178-1-ravi.kumar.vodapalli@intel... Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- include/drm/intel/pciids.h | 1 + 1 file changed, 1 insertion(+)
--- a/include/drm/intel/pciids.h +++ b/include/drm/intel/pciids.h @@ -846,6 +846,7 @@ /* BMG */ #define INTEL_BMG_IDS(MACRO__, ...) \ MACRO__(0xE202, ## __VA_ARGS__), \ + MACRO__(0xE209, ## __VA_ARGS__), \ MACRO__(0xE20B, ## __VA_ARGS__), \ MACRO__(0xE20C, ## __VA_ARGS__), \ MACRO__(0xE20D, ## __VA_ARGS__), \
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Thomas Hellström thomas.hellstrom@linux.intel.com
commit 2dd7a47669ae6c1da18c55f8e89c4a44418c7006 upstream.
When the xe buffer-object shrinker allows GPU waits and write-back, (typically from kswapd), perform multiple passes, skipping subsequent passes if the shrinker number of scanned objects target is reached.
1) Without GPU waits and write-back 2) Without write-back 3) With both GPU-waits and write-back
This is to avoid stalls and costly write- and readbacks unless they are really necessary.
v2: - Don't test for scan completion twice. (Stuart Summers) - Update tags.
Reported-by: melvyn melvyn2@dnsense.pub Closes: https://gitlab.freedesktop.org/drm/xe/kernel/-/issues/5557 Cc: Summers Stuart stuart.summers@intel.com Fixes: 00c8efc3180f ("drm/xe: Add a shrinker for xe bos") Cc: stable@vger.kernel.org # v6.15+ Signed-off-by: Thomas Hellström thomas.hellstrom@linux.intel.com Reviewed-by: Stuart Summers stuart.summers@intel.com Link: https://lore.kernel.org/r/20250805074842.11359-1-thomas.hellstrom@linux.inte... (cherry picked from commit 80944d334182ce5eb27d00e2bf20a88bfc32dea1) Signed-off-by: Rodrigo Vivi rodrigo.vivi@intel.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/gpu/drm/xe/xe_shrinker.c | 51 +++++++++++++++++++++++++++++++++++---- 1 file changed, 47 insertions(+), 4 deletions(-)
--- a/drivers/gpu/drm/xe/xe_shrinker.c +++ b/drivers/gpu/drm/xe/xe_shrinker.c @@ -53,10 +53,10 @@ xe_shrinker_mod_pages(struct xe_shrinker write_unlock(&shrinker->lock); }
-static s64 xe_shrinker_walk(struct xe_device *xe, - struct ttm_operation_ctx *ctx, - const struct xe_bo_shrink_flags flags, - unsigned long to_scan, unsigned long *scanned) +static s64 __xe_shrinker_walk(struct xe_device *xe, + struct ttm_operation_ctx *ctx, + const struct xe_bo_shrink_flags flags, + unsigned long to_scan, unsigned long *scanned) { unsigned int mem_type; s64 freed = 0, lret; @@ -86,6 +86,48 @@ static s64 xe_shrinker_walk(struct xe_de return freed; }
+/* + * Try shrinking idle objects without writeback first, then if not sufficient, + * try also non-idle objects and finally if that's not sufficient either, + * add writeback. This avoids stalls and explicit writebacks with light or + * moderate memory pressure. + */ +static s64 xe_shrinker_walk(struct xe_device *xe, + struct ttm_operation_ctx *ctx, + const struct xe_bo_shrink_flags flags, + unsigned long to_scan, unsigned long *scanned) +{ + bool no_wait_gpu = true; + struct xe_bo_shrink_flags save_flags = flags; + s64 lret, freed; + + swap(no_wait_gpu, ctx->no_wait_gpu); + save_flags.writeback = false; + lret = __xe_shrinker_walk(xe, ctx, save_flags, to_scan, scanned); + swap(no_wait_gpu, ctx->no_wait_gpu); + if (lret < 0 || *scanned >= to_scan) + return lret; + + freed = lret; + if (!ctx->no_wait_gpu) { + lret = __xe_shrinker_walk(xe, ctx, save_flags, to_scan, scanned); + if (lret < 0) + return lret; + freed += lret; + if (*scanned >= to_scan) + return freed; + } + + if (flags.writeback) { + lret = __xe_shrinker_walk(xe, ctx, flags, to_scan, scanned); + if (lret < 0) + return lret; + freed += lret; + } + + return freed; +} + static unsigned long xe_shrinker_count(struct shrinker *shrink, struct shrink_control *sc) { @@ -192,6 +234,7 @@ static unsigned long xe_shrinker_scan(st runtime_pm = xe_shrinker_runtime_pm_get(shrinker, true, 0, can_backup);
shrink_flags.purge = false; + lret = xe_shrinker_walk(shrinker->xe, &ctx, shrink_flags, nr_to_scan, &nr_scanned); if (lret >= 0)
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Yang Wang kevinyang.wang@amd.com
commit 8e0d1edb5c16732b695eaf4bd7096b1569817cf0 upstream.
Add lock protection for 'ring->wptr'/'ring->rptr' to ensure the correct execution.
Fixes: 8652920d2c00 ("drm/amdgpu: add mutex lock for cper ring") Signed-off-by: Yang Wang kevinyang.wang@amd.com Reviewed-by: Tao Zhou tao.zhou1@amd.com Signed-off-by: Alex Deucher alexander.deucher@amd.com Cc: stable@vger.kernel.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/gpu/drm/amd/amdgpu/amdgpu_cper.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-)
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_cper.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_cper.c index 15dde1f50328..25252231a68a 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_cper.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_cper.c @@ -459,7 +459,7 @@ static u32 amdgpu_cper_ring_get_ent_sz(struct amdgpu_ring *ring, u64 pos)
void amdgpu_cper_ring_write(struct amdgpu_ring *ring, void *src, int count) { - u64 pos, wptr_old, rptr = *ring->rptr_cpu_addr & ring->ptr_mask; + u64 pos, wptr_old, rptr; int rec_cnt_dw = count >> 2; u32 chunk, ent_sz; u8 *s = (u8 *)src; @@ -472,9 +472,11 @@ void amdgpu_cper_ring_write(struct amdgpu_ring *ring, void *src, int count) return; }
- wptr_old = ring->wptr; - mutex_lock(&ring->adev->cper.ring_lock); + + wptr_old = ring->wptr; + rptr = *ring->rptr_cpu_addr & ring->ptr_mask; + while (count) { ent_sz = amdgpu_cper_ring_get_ent_sz(ring, ring->wptr); chunk = umin(ent_sz, count);
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Alex Deucher alexander.deucher@amd.com
commit 514678da56da089b756b4d433efd964fa22b2079 upstream.
We only need the fw based discovery table for sysfs. No need to parse it. Additionally parsing some of the board specific tables may result in incorrect data on some boards. just load the binary and don't parse it on those boards.
Closes: https://gitlab.freedesktop.org/drm/amd/-/issues/4441 Fixes: 80a0e8282933 ("drm/amdgpu/discovery: optionally use fw based ip discovery") Reviewed-by: Mario Limonciello (AMD) superm1@kernel.org Signed-off-by: Alex Deucher alexander.deucher@amd.com (cherry picked from commit 62eedd150fa11aefc2d377fc746633fdb1baeb55) Cc: stable@vger.kernel.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 5 - drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c | 72 ++++++++++++++------------ 2 files changed, 41 insertions(+), 36 deletions(-)
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c @@ -2561,9 +2561,6 @@ static int amdgpu_device_parse_gpu_info_
adev->firmware.gpu_info_fw = NULL;
- if (adev->mman.discovery_bin) - return 0; - switch (adev->asic_type) { default: return 0; @@ -2585,6 +2582,8 @@ static int amdgpu_device_parse_gpu_info_ chip_name = "arcturus"; break; case CHIP_NAVI12: + if (adev->mman.discovery_bin) + return 0; chip_name = "navi12"; break; } --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c @@ -2555,40 +2555,11 @@ int amdgpu_discovery_set_ip_blocks(struc
switch (adev->asic_type) { case CHIP_VEGA10: - case CHIP_VEGA12: - case CHIP_RAVEN: - case CHIP_VEGA20: - case CHIP_ARCTURUS: - case CHIP_ALDEBARAN: - /* this is not fatal. We have a fallback below - * if the new firmwares are not present. some of - * this will be overridden below to keep things - * consistent with the current behavior. + /* This is not fatal. We only need the discovery + * binary for sysfs. We don't need it for a + * functional system. */ - r = amdgpu_discovery_reg_base_init(adev); - if (!r) { - amdgpu_discovery_harvest_ip(adev); - amdgpu_discovery_get_gfx_info(adev); - amdgpu_discovery_get_mall_info(adev); - amdgpu_discovery_get_vcn_info(adev); - } - break; - default: - r = amdgpu_discovery_reg_base_init(adev); - if (r) { - drm_err(&adev->ddev, "discovery failed: %d\n", r); - return r; - } - - amdgpu_discovery_harvest_ip(adev); - amdgpu_discovery_get_gfx_info(adev); - amdgpu_discovery_get_mall_info(adev); - amdgpu_discovery_get_vcn_info(adev); - break; - } - - switch (adev->asic_type) { - case CHIP_VEGA10: + amdgpu_discovery_init(adev); vega10_reg_base_init(adev); adev->sdma.num_instances = 2; adev->gmc.num_umc = 4; @@ -2611,6 +2582,11 @@ int amdgpu_discovery_set_ip_blocks(struc adev->ip_versions[DCI_HWIP][0] = IP_VERSION(12, 0, 0); break; case CHIP_VEGA12: + /* This is not fatal. We only need the discovery + * binary for sysfs. We don't need it for a + * functional system. + */ + amdgpu_discovery_init(adev); vega10_reg_base_init(adev); adev->sdma.num_instances = 2; adev->gmc.num_umc = 4; @@ -2633,6 +2609,11 @@ int amdgpu_discovery_set_ip_blocks(struc adev->ip_versions[DCI_HWIP][0] = IP_VERSION(12, 0, 1); break; case CHIP_RAVEN: + /* This is not fatal. We only need the discovery + * binary for sysfs. We don't need it for a + * functional system. + */ + amdgpu_discovery_init(adev); vega10_reg_base_init(adev); adev->sdma.num_instances = 1; adev->vcn.num_vcn_inst = 1; @@ -2674,6 +2655,11 @@ int amdgpu_discovery_set_ip_blocks(struc } break; case CHIP_VEGA20: + /* This is not fatal. We only need the discovery + * binary for sysfs. We don't need it for a + * functional system. + */ + amdgpu_discovery_init(adev); vega20_reg_base_init(adev); adev->sdma.num_instances = 2; adev->gmc.num_umc = 8; @@ -2697,6 +2683,11 @@ int amdgpu_discovery_set_ip_blocks(struc adev->ip_versions[DCI_HWIP][0] = IP_VERSION(12, 1, 0); break; case CHIP_ARCTURUS: + /* This is not fatal. We only need the discovery + * binary for sysfs. We don't need it for a + * functional system. + */ + amdgpu_discovery_init(adev); arct_reg_base_init(adev); adev->sdma.num_instances = 8; adev->vcn.num_vcn_inst = 2; @@ -2725,6 +2716,11 @@ int amdgpu_discovery_set_ip_blocks(struc adev->ip_versions[UVD_HWIP][1] = IP_VERSION(2, 5, 0); break; case CHIP_ALDEBARAN: + /* This is not fatal. We only need the discovery + * binary for sysfs. We don't need it for a + * functional system. + */ + amdgpu_discovery_init(adev); aldebaran_reg_base_init(adev); adev->sdma.num_instances = 5; adev->vcn.num_vcn_inst = 2; @@ -2751,6 +2747,16 @@ int amdgpu_discovery_set_ip_blocks(struc adev->ip_versions[XGMI_HWIP][0] = IP_VERSION(6, 1, 0); break; default: + r = amdgpu_discovery_reg_base_init(adev); + if (r) { + drm_err(&adev->ddev, "discovery failed: %d\n", r); + return r; + } + + amdgpu_discovery_harvest_ip(adev); + amdgpu_discovery_get_gfx_info(adev); + amdgpu_discovery_get_mall_info(adev); + amdgpu_discovery_get_vcn_info(adev); break; }
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Mario Limonciello mario.limonciello@amd.com
commit ed4efe426a49729952b3dc05d20e33b94409bdd1 upstream.
The power limit will be cached in smu->current_power_limit but if the ASIC goes into S3 this value won't be restored.
Restore the value during SMU resume.
Acked-by: Alex Deucher alexander.deucher@amd.com Link: https://lore.kernel.org/r/20250725031222.3015095-2-superm1@kernel.org Signed-off-by: Mario Limonciello mario.limonciello@amd.com Signed-off-by: Alex Deucher alexander.deucher@amd.com (cherry picked from commit 26a609e053a6fc494403e95403bc6a2470383bec) Cc: stable@vger.kernel.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c | 6 ++++++ 1 file changed, 6 insertions(+)
--- a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c +++ b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c @@ -2175,6 +2175,12 @@ static int smu_resume(struct amdgpu_ip_b
adev->pm.dpm_enabled = true;
+ if (smu->current_power_limit) { + ret = smu_set_power_limit(smu, smu->current_power_limit); + if (ret && ret != -EOPNOTSUPP) + return ret; + } + dev_info(adev->dev, "SMU is resumed successfully!\n");
return 0;
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Frank Min Frank.Min@amd.com
commit 0395cde08e1f7eee810b5799466e41635a21e599 upstream.
1. Add kicker firmwares loading for gfx12/smu14/psp14 2. Register additional MODULE_FIRMWARE entries for kicker fws - gc_12_0_1_rlc_kicker.bin - gc_12_0_1_imu_kicker.bin - psp_14_0_3_sos_kicker.bin - psp_14_0_3_ta_kicker.bin - smu_14_0_3_kicker.bin
Signed-off-by: Frank Min Frank.Min@amd.com Reviewed-by: Gui Chengming Jack.Gui@amd.com Signed-off-by: Alex Deucher alexander.deucher@amd.com Cc: stable@vger.kernel.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.c | 1 + drivers/gpu/drm/amd/amdgpu/gfx_v12_0.c | 14 ++++++++++---- drivers/gpu/drm/amd/amdgpu/imu_v12_0.c | 11 ++++++++--- drivers/gpu/drm/amd/amdgpu/psp_v14_0.c | 2 ++ drivers/gpu/drm/amd/pm/swsmu/smu14/smu_v14_0.c | 11 ++++++++--- 5 files changed, 29 insertions(+), 10 deletions(-)
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.c @@ -32,6 +32,7 @@
static const struct kicker_device kicker_device_list[] = { {0x744B, 0x00}, + {0x7551, 0xC8} };
static void amdgpu_ucode_print_common_hdr(const struct common_firmware_header *hdr) --- a/drivers/gpu/drm/amd/amdgpu/gfx_v12_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v12_0.c @@ -79,6 +79,7 @@ MODULE_FIRMWARE("amdgpu/gc_12_0_1_pfp.bi MODULE_FIRMWARE("amdgpu/gc_12_0_1_me.bin"); MODULE_FIRMWARE("amdgpu/gc_12_0_1_mec.bin"); MODULE_FIRMWARE("amdgpu/gc_12_0_1_rlc.bin"); +MODULE_FIRMWARE("amdgpu/gc_12_0_1_rlc_kicker.bin"); MODULE_FIRMWARE("amdgpu/gc_12_0_1_toc.bin");
static const struct amdgpu_hwip_reg_entry gc_reg_list_12_0[] = { @@ -586,7 +587,7 @@ out:
static int gfx_v12_0_init_microcode(struct amdgpu_device *adev) { - char ucode_prefix[15]; + char ucode_prefix[30]; int err; const struct rlc_firmware_header_v2_0 *rlc_hdr; uint16_t version_major; @@ -613,9 +614,14 @@ static int gfx_v12_0_init_microcode(stru amdgpu_gfx_cp_init_microcode(adev, AMDGPU_UCODE_ID_CP_RS64_ME_P0_STACK);
if (!amdgpu_sriov_vf(adev)) { - err = amdgpu_ucode_request(adev, &adev->gfx.rlc_fw, - AMDGPU_UCODE_REQUIRED, - "amdgpu/%s_rlc.bin", ucode_prefix); + if (amdgpu_is_kicker_fw(adev)) + err = amdgpu_ucode_request(adev, &adev->gfx.rlc_fw, + AMDGPU_UCODE_REQUIRED, + "amdgpu/%s_rlc_kicker.bin", ucode_prefix); + else + err = amdgpu_ucode_request(adev, &adev->gfx.rlc_fw, + AMDGPU_UCODE_REQUIRED, + "amdgpu/%s_rlc.bin", ucode_prefix); if (err) goto out; rlc_hdr = (const struct rlc_firmware_header_v2_0 *)adev->gfx.rlc_fw->data; --- a/drivers/gpu/drm/amd/amdgpu/imu_v12_0.c +++ b/drivers/gpu/drm/amd/amdgpu/imu_v12_0.c @@ -34,12 +34,13 @@
MODULE_FIRMWARE("amdgpu/gc_12_0_0_imu.bin"); MODULE_FIRMWARE("amdgpu/gc_12_0_1_imu.bin"); +MODULE_FIRMWARE("amdgpu/gc_12_0_1_imu_kicker.bin");
#define TRANSFER_RAM_MASK 0x001c0000
static int imu_v12_0_init_microcode(struct amdgpu_device *adev) { - char ucode_prefix[15]; + char ucode_prefix[30]; int err; const struct imu_firmware_header_v1_0 *imu_hdr; struct amdgpu_firmware_info *info = NULL; @@ -47,8 +48,12 @@ static int imu_v12_0_init_microcode(stru DRM_DEBUG("\n");
amdgpu_ucode_ip_version_decode(adev, GC_HWIP, ucode_prefix, sizeof(ucode_prefix)); - err = amdgpu_ucode_request(adev, &adev->gfx.imu_fw, AMDGPU_UCODE_REQUIRED, - "amdgpu/%s_imu.bin", ucode_prefix); + if (amdgpu_is_kicker_fw(adev)) + err = amdgpu_ucode_request(adev, &adev->gfx.imu_fw, AMDGPU_UCODE_REQUIRED, + "amdgpu/%s_imu_kicker.bin", ucode_prefix); + else + err = amdgpu_ucode_request(adev, &adev->gfx.imu_fw, AMDGPU_UCODE_REQUIRED, + "amdgpu/%s_imu.bin", ucode_prefix); if (err) goto out;
--- a/drivers/gpu/drm/amd/amdgpu/psp_v14_0.c +++ b/drivers/gpu/drm/amd/amdgpu/psp_v14_0.c @@ -34,7 +34,9 @@ MODULE_FIRMWARE("amdgpu/psp_14_0_2_sos.bin"); MODULE_FIRMWARE("amdgpu/psp_14_0_2_ta.bin"); MODULE_FIRMWARE("amdgpu/psp_14_0_3_sos.bin"); +MODULE_FIRMWARE("amdgpu/psp_14_0_3_sos_kicker.bin"); MODULE_FIRMWARE("amdgpu/psp_14_0_3_ta.bin"); +MODULE_FIRMWARE("amdgpu/psp_14_0_3_ta_kicker.bin"); MODULE_FIRMWARE("amdgpu/psp_14_0_5_toc.bin"); MODULE_FIRMWARE("amdgpu/psp_14_0_5_ta.bin");
--- a/drivers/gpu/drm/amd/pm/swsmu/smu14/smu_v14_0.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu14/smu_v14_0.c @@ -62,13 +62,14 @@ const int decoded_link_width[8] = {0, 1,
MODULE_FIRMWARE("amdgpu/smu_14_0_2.bin"); MODULE_FIRMWARE("amdgpu/smu_14_0_3.bin"); +MODULE_FIRMWARE("amdgpu/smu_14_0_3_kicker.bin");
#define ENABLE_IMU_ARG_GFXOFF_ENABLE 1
int smu_v14_0_init_microcode(struct smu_context *smu) { struct amdgpu_device *adev = smu->adev; - char ucode_prefix[15]; + char ucode_prefix[30]; int err = 0; const struct smc_firmware_header_v1_0 *hdr; const struct common_firmware_header *header; @@ -79,8 +80,12 @@ int smu_v14_0_init_microcode(struct smu_ return 0;
amdgpu_ucode_ip_version_decode(adev, MP1_HWIP, ucode_prefix, sizeof(ucode_prefix)); - err = amdgpu_ucode_request(adev, &adev->pm.fw, AMDGPU_UCODE_REQUIRED, - "amdgpu/%s.bin", ucode_prefix); + if (amdgpu_is_kicker_fw(adev)) + err = amdgpu_ucode_request(adev, &adev->pm.fw, AMDGPU_UCODE_REQUIRED, + "amdgpu/%s_kicker.bin", ucode_prefix); + else + err = amdgpu_ucode_request(adev, &adev->pm.fw, AMDGPU_UCODE_REQUIRED, + "amdgpu/%s.bin", ucode_prefix); if (err) goto out;
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Alex Deucher alexander.deucher@amd.com
commit 81699fe81b0be287fb28b6210324db48e8458d9f upstream.
Legacy resets reset the memory controllers so VRAM contents may be unreliable after reset.
Reviewed-by: Hawking Zhang Hawking.Zhang@amd.com Signed-off-by: Alex Deucher alexander.deucher@amd.com (cherry picked from commit aae94897b6661a2a4b1de2d328090fc388b3e0af) Cc: stable@vger.kernel.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 1 + 1 file changed, 1 insertion(+)
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c @@ -3234,6 +3234,7 @@ static bool amdgpu_device_check_vram_los * always assumed to be lost. */ switch (amdgpu_asic_reset_method(adev)) { + case AMD_RESET_METHOD_LEGACY: case AMD_RESET_METHOD_LINK: case AMD_RESET_METHOD_BACO: case AMD_RESET_METHOD_MODE1:
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Gang Ba Gang.Ba@amd.com
commit 1f02f2044bda1db1fd995bc35961ab075fa7b5a2 upstream.
If vm belongs to another process, this is fclose after fork, wait may enable signaling KFD eviction fence and cause parent process queue evicted.
[677852.634569] amdkfd_fence_enable_signaling+0x56/0x70 [amdgpu] [677852.634814] __dma_fence_enable_signaling+0x3e/0xe0 [677852.634820] dma_fence_wait_timeout+0x3a/0x140 [677852.634825] amddma_resv_wait_timeout+0x7f/0xf0 [amdkcl] [677852.634831] amdgpu_vm_wait_idle+0x2d/0x60 [amdgpu] [677852.635026] amdgpu_flush+0x34/0x50 [amdgpu] [677852.635208] filp_flush+0x38/0x90 [677852.635213] filp_close+0x14/0x30 [677852.635216] do_close_on_exec+0xdd/0x130 [677852.635221] begin_new_exec+0x1da/0x490 [677852.635225] load_elf_binary+0x307/0xea0 [677852.635231] ? srso_alias_return_thunk+0x5/0xfbef5 [677852.635235] ? ima_bprm_check+0xa2/0xd0 [677852.635240] search_binary_handler+0xda/0x260 [677852.635245] exec_binprm+0x58/0x1a0 [677852.635249] bprm_execve.part.0+0x16f/0x210 [677852.635254] bprm_execve+0x45/0x80 [677852.635257] do_execveat_common.isra.0+0x190/0x200
Suggested-by: Christian König christian.koenig@amd.com Signed-off-by: Gang Ba Gang.Ba@amd.com Reviewed-by: Christian König christian.koenig@amd.com Signed-off-by: Alex Deucher alexander.deucher@amd.com Cc: stable@vger.kernel.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-)
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c @@ -2409,13 +2409,11 @@ void amdgpu_vm_adjust_size(struct amdgpu */ long amdgpu_vm_wait_idle(struct amdgpu_vm *vm, long timeout) { - timeout = dma_resv_wait_timeout(vm->root.bo->tbo.base.resv, - DMA_RESV_USAGE_BOOKKEEP, - true, timeout); + timeout = drm_sched_entity_flush(&vm->immediate, timeout); if (timeout <= 0) return timeout;
- return dma_fence_wait_timeout(vm->last_unlocked, true, timeout); + return drm_sched_entity_flush(&vm->delayed, timeout); }
static void amdgpu_vm_destroy_task_info(struct kref *kref)
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Peter Shkenev mustela@erminea.space
commit b4a69f7f29c8a459ad6b4d8a8b72450f1d9fd288 upstream.
HUBBUB structure is not initialized on DCE hardware, so check if it is NULL to avoid null dereference while accessing amdgpu_dm_capabilities file in debugfs.
Signed-off-by: Peter Shkenev mustela@erminea.space Signed-off-by: Alex Deucher alexander.deucher@amd.com Cc: stable@vger.kernel.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c @@ -3988,7 +3988,7 @@ static int capabilities_show(struct seq_
struct hubbub *hubbub = dc->res_pool->hubbub;
- if (hubbub->funcs->get_mall_en) + if (hubbub && hubbub->funcs->get_mall_en) hubbub->funcs->get_mall_en(hubbub, &mall_in_use);
if (dc->cap_funcs.get_subvp_en)
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Nathan Chancellor nathan@kernel.org
commit c90f2e1172c51fa25492471dc9910e2d7c1444b9 upstream.
After a recent change in clang to expose uninitialized warnings from const variables and pointers [1], there is a warning in imu_v12_0_program_rlc_ram() because data is passed uninitialized to program_imu_rlc_ram():
drivers/gpu/drm/amd/amdgpu/imu_v12_0.c:374:30: error: variable 'data' is uninitialized when used here [-Werror,-Wuninitialized] 374 | program_imu_rlc_ram(adev, data, (const u32)size); | ^~~~
As this warning happens early in clang's frontend, it does not realize that due to the assignment of r to -EINVAL, program_imu_rlc_ram() is never actually called, and even if it were, data would not be dereferenced because size is 0.
Just initialize data to NULL to silence the warning, as the commit that added program_imu_rlc_ram() mentioned it would eventually be used over the old method, at which point data can be properly initialized and used.
Cc: stable@vger.kernel.org Closes: https://github.com/ClangBuiltLinux/linux/issues/2107 Fixes: 56159fffaab5 ("drm/amdgpu: use new method to program rlc ram") Link: https://github.com/llvm/llvm-project/commit/2464313eef01c5b1edf0eccf57a32cde... [1] Signed-off-by: Nathan Chancellor nathan@kernel.org Signed-off-by: Alex Deucher alexander.deucher@amd.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/gpu/drm/amd/amdgpu/imu_v12_0.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
--- a/drivers/gpu/drm/amd/amdgpu/imu_v12_0.c +++ b/drivers/gpu/drm/amd/amdgpu/imu_v12_0.c @@ -367,7 +367,7 @@ static void program_imu_rlc_ram(struct a static void imu_v12_0_program_rlc_ram(struct amdgpu_device *adev) { u32 reg_data, size = 0; - const u32 *data; + const u32 *data = NULL; int r = -EINVAL;
WREG32_SOC15(GC, 0, regGFX_IMU_RLC_RAM_INDEX, 0x2);
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: YuanShang YuanShang.Mao@amd.com
commit c00d8b79fd2167c6ac65e096619535acdf8678d5 upstream.
The field job->vm is used in function amdgpu_job_run to get the page table re-generation counter and decide whether the job should be skipped.
Specifically, function amdgpu_vm_generation checks if the VM is valid for this job to use. For instance, if a gfx job depends on a cancelled sdma job from entity vm->delayed, then the gfx job should be skipped.
Fixes: 26c95e838e63 ("drm/amdgpu: set the VM pointer to NULL in amdgpu_job_prepare") Signed-off-by: YuanShang YuanShang.Mao@amd.com Reviewed-by: Alex Deucher alexander.deucher@amd.com Signed-off-by: Alex Deucher alexander.deucher@amd.com (cherry picked from commit ed76936c6b10b547c6df4ca75412331e9ef6d339) Cc: stable@vger.kernel.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/gpu/drm/amd/amdgpu/amdgpu_job.c | 7 ------- 1 file changed, 7 deletions(-)
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_job.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_job.c @@ -387,13 +387,6 @@ amdgpu_job_prepare_job(struct drm_sched_ dev_err(ring->adev->dev, "Error getting VM ID (%d)\n", r); goto error; } - /* - * The VM structure might be released after the VMID is - * assigned, we had multiple problems with people trying to use - * the VM pointer so better set it to NULL. - */ - if (!fence) - job->vm = NULL; return fence; }
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Alex Deucher alexander.deucher@amd.com
commit 284d4dfe850e665f0e7d4dfaf4d3d3da76d11fb0 upstream.
Used to to set the MQD appropriately for each queue type. Kernel queues have additional privileges.
Acked-by: Christian König christian.koenig@amd.com Reviewed-by: Lijo Lazar lijo.lazar@amd.com Signed-off-by: Alex Deucher alexander.deucher@amd.com Cc: stable@vger.kernel.org # 6.16.x Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/gpu/drm/amd/amdgpu/amdgpu.h | 1 + drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c | 1 + 2 files changed, 2 insertions(+)
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h @@ -886,6 +886,7 @@ struct amdgpu_mqd_prop { uint64_t csa_addr; uint64_t fence_address; bool tmz_queue; + bool kernel_queue; };
struct amdgpu_mqd { --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c @@ -687,6 +687,7 @@ static void amdgpu_ring_to_mqd_prop(stru prop->eop_gpu_addr = ring->eop_gpu_addr; prop->use_doorbell = ring->use_doorbell; prop->doorbell_index = ring->doorbell_index; + prop->kernel_queue = true;
/* map_queues packet doesn't need activate the queue, * so only kiq need set this field.
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Lijo Lazar lijo.lazar@amd.com
commit 05c8b690511854ba31d8d1bff7139a13ec66b9e7 upstream.
Use different external revid for GC v9.5.0 SOCs.
Signed-off-by: Lijo Lazar lijo.lazar@amd.com Reviewed-by: Hawking Zhang Hawking.Zhang@amd.com Reviewed-by: Asad Kamal asad.kamal@amd.com Signed-off-by: Alex Deucher alexander.deucher@amd.com (cherry picked from commit 21c6764ed4bfaecad034bc4fd15dd64c5a436325) Cc: stable@vger.kernel.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/gpu/drm/amd/amdgpu/soc15.c | 2 ++ 1 file changed, 2 insertions(+)
--- a/drivers/gpu/drm/amd/amdgpu/soc15.c +++ b/drivers/gpu/drm/amd/amdgpu/soc15.c @@ -1218,6 +1218,8 @@ static int soc15_common_early_init(struc AMD_PG_SUPPORT_JPEG; /*TODO: need a new external_rev_id for GC 9.4.4? */ adev->external_rev_id = adev->rev_id + 0x46; + if (amdgpu_ip_version(adev, GC_HWIP, 0) == IP_VERSION(9, 5, 0)) + adev->external_rev_id = adev->rev_id + 0x50; break; default: /* FIXME: not supported yet */
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Alex Deucher alexander.deucher@amd.com
commit 0bae62cc989fa99ac9cb564eb573aad916d1eb61 upstream.
Update the client id mapping so the correct clients get printed when there is a mmhub page fault.
Reviewed-by: David (Ming Qiang) Wu David.Wu3@amd.com Signed-off-by: Alex Deucher alexander.deucher@amd.com (cherry picked from commit 2a2681eda73b99a2c1ee8cdb006099ea5d0c2505) Cc: stable@vger.kernel.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/gpu/drm/amd/amdgpu/mmhub_v3_0_1.c | 57 ++++++++++++++++-------------- 1 file changed, 32 insertions(+), 25 deletions(-)
--- a/drivers/gpu/drm/amd/amdgpu/mmhub_v3_0_1.c +++ b/drivers/gpu/drm/amd/amdgpu/mmhub_v3_0_1.c @@ -36,40 +36,47 @@
static const char *mmhub_client_ids_v3_0_1[][2] = { [0][0] = "VMC", + [1][0] = "ISPXT", + [2][0] = "ISPIXT", [4][0] = "DCEDMC", [5][0] = "DCEVGA", [6][0] = "MP0", [7][0] = "MP1", - [8][0] = "MPIO", - [16][0] = "HDP", - [17][0] = "LSDMA", - [18][0] = "JPEG", - [19][0] = "VCNU0", - [21][0] = "VSCH", - [22][0] = "VCNU1", - [23][0] = "VCN1", - [32+20][0] = "VCN0", - [2][1] = "DBGUNBIO", + [8][0] = "MPM", + [12][0] = "ISPTNR", + [14][0] = "ISPCRD0", + [15][0] = "ISPCRD1", + [16][0] = "ISPCRD2", + [22][0] = "HDP", + [23][0] = "LSDMA", + [24][0] = "JPEG", + [27][0] = "VSCH", + [28][0] = "VCNU", + [29][0] = "VCN", + [1][1] = "ISPXT", + [2][1] = "ISPIXT", [3][1] = "DCEDWB", [4][1] = "DCEDMC", [5][1] = "DCEVGA", [6][1] = "MP0", [7][1] = "MP1", - [8][1] = "MPIO", - [10][1] = "DBGU0", - [11][1] = "DBGU1", - [12][1] = "DBGU2", - [13][1] = "DBGU3", - [14][1] = "XDP", - [15][1] = "OSSSYS", - [16][1] = "HDP", - [17][1] = "LSDMA", - [18][1] = "JPEG", - [19][1] = "VCNU0", - [20][1] = "VCN0", - [21][1] = "VSCH", - [22][1] = "VCNU1", - [23][1] = "VCN1", + [8][1] = "MPM", + [10][1] = "ISPMWR0", + [11][1] = "ISPMWR1", + [12][1] = "ISPTNR", + [13][1] = "ISPSWR", + [14][1] = "ISPCWR0", + [15][1] = "ISPCWR1", + [16][1] = "ISPCWR2", + [17][1] = "ISPCWR3", + [18][1] = "XDP", + [21][1] = "OSSSYS", + [22][1] = "HDP", + [23][1] = "LSDMA", + [24][1] = "JPEG", + [27][1] = "VSCH", + [28][1] = "VCNU", + [29][1] = "VCN", };
static uint32_t mmhub_v3_0_1_get_invalidate_req(unsigned int vmid,
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Alex Deucher alexander.deucher@amd.com
commit 9f9bddfa31d87b084700a6e9eca1a8b4f8ddcdf6 upstream.
Update the client id mapping so the correct clients get printed when there is a mmhub page fault.
v2: fix typos spotted by David Wu. v3: fix additional typo spotted by David.
Reviewed-by: David (Ming Qiang) Wu David.Wu3@amd.com Signed-off-by: Alex Deucher alexander.deucher@amd.com (cherry picked from commit e932f4779a2d329841bb9ca70bb80a4bb2d707b6) Cc: stable@vger.kernel.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/gpu/drm/amd/amdgpu/mmhub_v3_3.c | 105 +++++++++++++++++++++++++++++++- 1 file changed, 104 insertions(+), 1 deletion(-)
--- a/drivers/gpu/drm/amd/amdgpu/mmhub_v3_3.c +++ b/drivers/gpu/drm/amd/amdgpu/mmhub_v3_3.c @@ -40,30 +40,129 @@
static const char *mmhub_client_ids_v3_3[][2] = { [0][0] = "VMC", + [1][0] = "ISPXT", + [2][0] = "ISPIXT", [4][0] = "DCEDMC", [6][0] = "MP0", [7][0] = "MP1", [8][0] = "MPM", + [9][0] = "ISPPDPRD", + [10][0] = "ISPCSTATRD", + [11][0] = "ISPBYRPRD", + [12][0] = "ISPRGBPRD", + [13][0] = "ISPMCFPRD", + [14][0] = "ISPMCFPRD1", + [15][0] = "ISPYUVPRD", + [16][0] = "ISPMCSCRD", + [17][0] = "ISPGDCRD", + [18][0] = "ISPLMERD", + [22][0] = "ISPXT1", + [23][0] = "ISPIXT1", [24][0] = "HDP", [25][0] = "LSDMA", [26][0] = "JPEG", [27][0] = "VPE", + [28][0] = "VSCH", [29][0] = "VCNU", [30][0] = "VCN", + [1][1] = "ISPXT", + [2][1] = "ISPIXT", [3][1] = "DCEDWB", [4][1] = "DCEDMC", + [5][1] = "ISPCSISWR", [6][1] = "MP0", [7][1] = "MP1", [8][1] = "MPM", + [9][1] = "ISPPDPWR", + [10][1] = "ISPCSTATWR", + [11][1] = "ISPBYRPWR", + [12][1] = "ISPRGBPWR", + [13][1] = "ISPMCFPWR", + [14][1] = "ISPMWR0", + [15][1] = "ISPYUVPWR", + [16][1] = "ISPMCSCWR", + [17][1] = "ISPGDCWR", + [18][1] = "ISPLMEWR", + [20][1] = "ISPMWR2", [21][1] = "OSSSYS", + [22][1] = "ISPXT1", + [23][1] = "ISPIXT1", [24][1] = "HDP", [25][1] = "LSDMA", [26][1] = "JPEG", [27][1] = "VPE", + [28][1] = "VSCH", [29][1] = "VCNU", [30][1] = "VCN", };
+static const char *mmhub_client_ids_v3_3_1[][2] = { + [0][0] = "VMC", + [4][0] = "DCEDMC", + [6][0] = "MP0", + [7][0] = "MP1", + [8][0] = "MPM", + [24][0] = "HDP", + [25][0] = "LSDMA", + [26][0] = "JPEG0", + [27][0] = "VPE0", + [28][0] = "VSCH", + [29][0] = "VCNU0", + [30][0] = "VCN0", + [32+1][0] = "ISPXT", + [32+2][0] = "ISPIXT", + [32+9][0] = "ISPPDPRD", + [32+10][0] = "ISPCSTATRD", + [32+11][0] = "ISPBYRPRD", + [32+12][0] = "ISPRGBPRD", + [32+13][0] = "ISPMCFPRD", + [32+14][0] = "ISPMCFPRD1", + [32+15][0] = "ISPYUVPRD", + [32+16][0] = "ISPMCSCRD", + [32+17][0] = "ISPGDCRD", + [32+18][0] = "ISPLMERD", + [32+22][0] = "ISPXT1", + [32+23][0] = "ISPIXT1", + [32+26][0] = "JPEG1", + [32+27][0] = "VPE1", + [32+29][0] = "VCNU1", + [32+30][0] = "VCN1", + [3][1] = "DCEDWB", + [4][1] = "DCEDMC", + [6][1] = "MP0", + [7][1] = "MP1", + [8][1] = "MPM", + [21][1] = "OSSSYS", + [24][1] = "HDP", + [25][1] = "LSDMA", + [26][1] = "JPEG0", + [27][1] = "VPE0", + [28][1] = "VSCH", + [29][1] = "VCNU0", + [30][1] = "VCN0", + [32+1][1] = "ISPXT", + [32+2][1] = "ISPIXT", + [32+5][1] = "ISPCSISWR", + [32+9][1] = "ISPPDPWR", + [32+10][1] = "ISPCSTATWR", + [32+11][1] = "ISPBYRPWR", + [32+12][1] = "ISPRGBPWR", + [32+13][1] = "ISPMCFPWR", + [32+14][1] = "ISPMWR0", + [32+15][1] = "ISPYUVPWR", + [32+16][1] = "ISPMCSCWR", + [32+17][1] = "ISPGDCWR", + [32+18][1] = "ISPLMEWR", + [32+19][1] = "ISPMWR1", + [32+20][1] = "ISPMWR2", + [32+22][1] = "ISPXT1", + [32+23][1] = "ISPIXT1", + [32+26][1] = "JPEG1", + [32+27][1] = "VPE1", + [32+29][1] = "VCNU1", + [32+30][1] = "VCN1", +}; + static uint32_t mmhub_v3_3_get_invalidate_req(unsigned int vmid, uint32_t flush_type) { @@ -102,12 +201,16 @@ mmhub_v3_3_print_l2_protection_fault_sta
switch (amdgpu_ip_version(adev, MMHUB_HWIP, 0)) { case IP_VERSION(3, 3, 0): - case IP_VERSION(3, 3, 1): case IP_VERSION(3, 3, 2): mmhub_cid = cid < ARRAY_SIZE(mmhub_client_ids_v3_3) ? mmhub_client_ids_v3_3[cid][rw] : cid == 0x140 ? "UMSCH" : NULL; break; + case IP_VERSION(3, 3, 1): + mmhub_cid = cid < ARRAY_SIZE(mmhub_client_ids_v3_3_1) ? + mmhub_client_ids_v3_3_1[cid][rw] : + cid == 0x140 ? "UMSCH" : NULL; + break; default: mmhub_cid = NULL; break;
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Alex Deucher alexander.deucher@amd.com
commit a0b34e4c8663b13e45c78267b4de3004b1a72490 upstream.
Update the client id mapping so the correct clients get printed when there is a mmhub page fault.
Tested-by: David (Ming Qiang) Wu David.Wu3@amd.com Reviewed-by: David (Ming Qiang) Wu David.Wu3@amd.com Signed-off-by: Alex Deucher alexander.deucher@amd.com Cc: stable@vger.kernel.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/gpu/drm/amd/amdgpu/mmhub_v4_1_0.c | 34 +++++++++++------------------- 1 file changed, 13 insertions(+), 21 deletions(-)
--- a/drivers/gpu/drm/amd/amdgpu/mmhub_v4_1_0.c +++ b/drivers/gpu/drm/amd/amdgpu/mmhub_v4_1_0.c @@ -37,39 +37,31 @@ static const char *mmhub_client_ids_v4_1_0[][2] = { [0][0] = "VMC", [4][0] = "DCEDMC", - [5][0] = "DCEVGA", [6][0] = "MP0", [7][0] = "MP1", [8][0] = "MPIO", - [16][0] = "HDP", - [17][0] = "LSDMA", - [18][0] = "JPEG", - [19][0] = "VCNU0", - [21][0] = "VSCH", - [22][0] = "VCNU1", - [23][0] = "VCN1", - [32+20][0] = "VCN0", - [2][1] = "DBGUNBIO", + [16][0] = "LSDMA", + [17][0] = "JPEG", + [19][0] = "VCNU", + [22][0] = "VSCH", + [23][0] = "HDP", + [32+23][0] = "VCNRD", [3][1] = "DCEDWB", [4][1] = "DCEDMC", - [5][1] = "DCEVGA", [6][1] = "MP0", [7][1] = "MP1", [8][1] = "MPIO", [10][1] = "DBGU0", [11][1] = "DBGU1", - [12][1] = "DBGU2", - [13][1] = "DBGU3", + [12][1] = "DBGUNBIO", [14][1] = "XDP", [15][1] = "OSSSYS", - [16][1] = "HDP", - [17][1] = "LSDMA", - [18][1] = "JPEG", - [19][1] = "VCNU0", - [20][1] = "VCN0", - [21][1] = "VSCH", - [22][1] = "VCNU1", - [23][1] = "VCN1", + [16][1] = "LSDMA", + [17][1] = "JPEG", + [18][1] = "VCNWR", + [19][1] = "VCNU", + [22][1] = "VSCH", + [23][1] = "HDP", };
static uint32_t mmhub_v4_1_0_get_invalidate_req(unsigned int vmid,
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Lijo Lazar lijo.lazar@amd.com
commit 389d79a195a9f71a103b39097ee8341a7ca60927 upstream.
For GC v9.5.0 SOCs, both CPX and QPX compute modes are also supported in NPS2 mode.
Signed-off-by: Lijo Lazar lijo.lazar@amd.com Acked-by: Mangesh Gadre Mangesh.Gadre@amd.com Reviewed-by: Asad Kamal asad.kamal@amd.com Signed-off-by: Alex Deucher alexander.deucher@amd.com (cherry picked from commit 9d1ac25c7f830e0132aa816393b1e9f140e71148) Cc: stable@vger.kernel.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/gpu/drm/amd/amdgpu/aqua_vanjaram.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-)
--- a/drivers/gpu/drm/amd/amdgpu/aqua_vanjaram.c +++ b/drivers/gpu/drm/amd/amdgpu/aqua_vanjaram.c @@ -453,6 +453,7 @@ static int __aqua_vanjaram_get_px_mode_i uint16_t *nps_modes) { struct amdgpu_device *adev = xcp_mgr->adev; + uint32_t gc_ver = amdgpu_ip_version(adev, GC_HWIP, 0);
if (!num_xcp || !nps_modes || !(xcp_mgr->supp_xcp_modes & BIT(px_mode))) return -EINVAL; @@ -476,12 +477,14 @@ static int __aqua_vanjaram_get_px_mode_i *num_xcp = 4; *nps_modes = BIT(AMDGPU_NPS1_PARTITION_MODE) | BIT(AMDGPU_NPS4_PARTITION_MODE); + if (gc_ver == IP_VERSION(9, 5, 0)) + *nps_modes |= BIT(AMDGPU_NPS2_PARTITION_MODE); break; case AMDGPU_CPX_PARTITION_MODE: *num_xcp = NUM_XCC(adev->gfx.xcc_mask); *nps_modes = BIT(AMDGPU_NPS1_PARTITION_MODE) | BIT(AMDGPU_NPS4_PARTITION_MODE); - if (amdgpu_sriov_vf(adev)) + if (gc_ver == IP_VERSION(9, 5, 0)) *nps_modes |= BIT(AMDGPU_NPS2_PARTITION_MODE); break; default:
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Amber Lin Amber.Lin@amd.com
commit 2e58401a24e7b2d4ec619104e1a76590c1284a4c upstream.
Since KFD proc content was moved to kernel debugfs, we can't destroy KFD debugfs before kfd_process_destroy_wq. Move kfd_process_destroy_wq prior to kfd_debugfs_fini to fix a kernel NULL pointer problem. It happens when /sys/kernel/debug/kfd was already destroyed in kfd_debugfs_fini but kfd_process_destroy_wq calls kfd_debugfs_remove_process. This line debugfs_remove_recursive(entry->proc_dentry); tries to remove /sys/kernel/debug/kfd/proc/<pid> while /sys/kernel/debug/kfd is already gone. It hangs the kernel by kernel NULL pointer.
Signed-off-by: Amber Lin Amber.Lin@amd.com Reviewed-by: Eric Huang jinhuieric.huang@amd.com Signed-off-by: Alex Deucher alexander.deucher@amd.com (cherry picked from commit 0333052d90683d88531558dcfdbf2525cc37c233) Cc: stable@vger.kernel.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/gpu/drm/amd/amdkfd/kfd_module.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
--- a/drivers/gpu/drm/amd/amdkfd/kfd_module.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_module.c @@ -78,8 +78,8 @@ err_ioctl: static void kfd_exit(void) { kfd_cleanup_processes(); - kfd_debugfs_fini(); kfd_process_destroy_wq(); + kfd_debugfs_fini(); kfd_procfs_shutdown(); kfd_topology_shutdown(); kfd_chardev_exit();
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: David Yat Sin David.YatSin@amd.com
commit f6c0f3d24478a0792e50a64c2eba9f34d65519f2 upstream.
GPUs with multi-xcc have multiple MQDs per queue. This patch saves and restores all the MQDs within the partition.
Signed-off-by: David Yat Sin David.YatSin@amd.com Reviewed-by: Felix Kuehling felix.kuehling@amd.com Signed-off-by: Alex Deucher alexander.deucher@amd.com (cherry picked from commit a578f2a58c3ab38f0643b1b6e7534af860233cb1) Cc: stable@vger.kernel.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c | 2 drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_v9.c | 61 ++++++++++++++--- drivers/gpu/drm/amd/amdkfd/kfd_process_queue_manager.c | 20 ++++- 3 files changed, 67 insertions(+), 16 deletions(-)
--- a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c @@ -2716,7 +2716,7 @@ static void get_queue_checkpoint_info(st
dqm_lock(dqm); mqd_mgr = dqm->mqd_mgrs[mqd_type]; - *mqd_size = mqd_mgr->mqd_size; + *mqd_size = mqd_mgr->mqd_size * NUM_XCC(mqd_mgr->dev->xcc_mask); *ctl_stack_size = 0;
if (q->properties.type == KFD_QUEUE_TYPE_COMPUTE && mqd_mgr->get_checkpoint_info) --- a/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_v9.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_v9.c @@ -373,7 +373,7 @@ static void get_checkpoint_info(struct m { struct v9_mqd *m = get_mqd(mqd);
- *ctl_stack_size = m->cp_hqd_cntl_stack_size; + *ctl_stack_size = m->cp_hqd_cntl_stack_size * NUM_XCC(mm->dev->xcc_mask); }
static void checkpoint_mqd(struct mqd_manager *mm, void *mqd, void *mqd_dst, void *ctl_stack_dst) @@ -388,6 +388,24 @@ static void checkpoint_mqd(struct mqd_ma memcpy(ctl_stack_dst, ctl_stack, m->cp_hqd_cntl_stack_size); }
+static void checkpoint_mqd_v9_4_3(struct mqd_manager *mm, + void *mqd, + void *mqd_dst, + void *ctl_stack_dst) +{ + struct v9_mqd *m; + int xcc; + uint64_t size = get_mqd(mqd)->cp_mqd_stride_size; + + for (xcc = 0; xcc < NUM_XCC(mm->dev->xcc_mask); xcc++) { + m = get_mqd(mqd + size * xcc); + + checkpoint_mqd(mm, m, + (uint8_t *)mqd_dst + sizeof(*m) * xcc, + (uint8_t *)ctl_stack_dst + m->cp_hqd_cntl_stack_size * xcc); + } +} + static void restore_mqd(struct mqd_manager *mm, void **mqd, struct kfd_mem_obj *mqd_mem_obj, uint64_t *gart_addr, struct queue_properties *qp, @@ -764,13 +782,35 @@ static void restore_mqd_v9_4_3(struct mq const void *mqd_src, const void *ctl_stack_src, u32 ctl_stack_size) { - restore_mqd(mm, mqd, mqd_mem_obj, gart_addr, qp, mqd_src, ctl_stack_src, ctl_stack_size); - if (amdgpu_sriov_multi_vf_mode(mm->dev->adev)) { - struct v9_mqd *m; + struct kfd_mem_obj xcc_mqd_mem_obj; + u32 mqd_ctl_stack_size; + struct v9_mqd *m; + u32 num_xcc; + int xcc;
- m = (struct v9_mqd *) mqd_mem_obj->cpu_ptr; - m->cp_hqd_pq_doorbell_control |= 1 << - CP_HQD_PQ_DOORBELL_CONTROL__DOORBELL_MODE__SHIFT; + uint64_t offset = mm->mqd_stride(mm, qp); + + mm->dev->dqm->current_logical_xcc_start++; + + num_xcc = NUM_XCC(mm->dev->xcc_mask); + mqd_ctl_stack_size = ctl_stack_size / num_xcc; + + memset(&xcc_mqd_mem_obj, 0x0, sizeof(struct kfd_mem_obj)); + + /* Set the MQD pointer and gart address to XCC0 MQD */ + *mqd = mqd_mem_obj->cpu_ptr; + if (gart_addr) + *gart_addr = mqd_mem_obj->gpu_addr; + + for (xcc = 0; xcc < num_xcc; xcc++) { + get_xcc_mqd(mqd_mem_obj, &xcc_mqd_mem_obj, offset * xcc); + restore_mqd(mm, (void **)&m, + &xcc_mqd_mem_obj, + NULL, + qp, + (uint8_t *)mqd_src + xcc * sizeof(*m), + (uint8_t *)ctl_stack_src + xcc * mqd_ctl_stack_size, + mqd_ctl_stack_size); } } static int destroy_mqd_v9_4_3(struct mqd_manager *mm, void *mqd, @@ -906,7 +946,6 @@ struct mqd_manager *mqd_manager_init_v9( mqd->free_mqd = kfd_free_mqd_cp; mqd->is_occupied = kfd_is_occupied_cp; mqd->get_checkpoint_info = get_checkpoint_info; - mqd->checkpoint_mqd = checkpoint_mqd; mqd->mqd_size = sizeof(struct v9_mqd); mqd->mqd_stride = mqd_stride_v9; #if defined(CONFIG_DEBUG_FS) @@ -918,16 +957,18 @@ struct mqd_manager *mqd_manager_init_v9( mqd->init_mqd = init_mqd_v9_4_3; mqd->load_mqd = load_mqd_v9_4_3; mqd->update_mqd = update_mqd_v9_4_3; - mqd->restore_mqd = restore_mqd_v9_4_3; mqd->destroy_mqd = destroy_mqd_v9_4_3; mqd->get_wave_state = get_wave_state_v9_4_3; + mqd->checkpoint_mqd = checkpoint_mqd_v9_4_3; + mqd->restore_mqd = restore_mqd_v9_4_3; } else { mqd->init_mqd = init_mqd; mqd->load_mqd = load_mqd; mqd->update_mqd = update_mqd; - mqd->restore_mqd = restore_mqd; mqd->destroy_mqd = kfd_destroy_mqd_cp; mqd->get_wave_state = get_wave_state; + mqd->checkpoint_mqd = checkpoint_mqd; + mqd->restore_mqd = restore_mqd; } break; case KFD_MQD_TYPE_HIQ: --- a/drivers/gpu/drm/amd/amdkfd/kfd_process_queue_manager.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_process_queue_manager.c @@ -914,7 +914,10 @@ static int criu_checkpoint_queues_device
q_data = (struct kfd_criu_queue_priv_data *)q_private_data;
- /* data stored in this order: priv_data, mqd, ctl_stack */ + /* + * data stored in this order: + * priv_data, mqd[xcc0], mqd[xcc1],..., ctl_stack[xcc0], ctl_stack[xcc1]... + */ q_data->mqd_size = mqd_size; q_data->ctl_stack_size = ctl_stack_size;
@@ -963,7 +966,7 @@ int kfd_criu_checkpoint_queues(struct kf }
static void set_queue_properties_from_criu(struct queue_properties *qp, - struct kfd_criu_queue_priv_data *q_data) + struct kfd_criu_queue_priv_data *q_data, uint32_t num_xcc) { qp->is_interop = false; qp->queue_percent = q_data->q_percent; @@ -976,7 +979,11 @@ static void set_queue_properties_from_cr qp->eop_ring_buffer_size = q_data->eop_ring_buffer_size; qp->ctx_save_restore_area_address = q_data->ctx_save_restore_area_address; qp->ctx_save_restore_area_size = q_data->ctx_save_restore_area_size; - qp->ctl_stack_size = q_data->ctl_stack_size; + if (q_data->type == KFD_QUEUE_TYPE_COMPUTE) + qp->ctl_stack_size = q_data->ctl_stack_size / num_xcc; + else + qp->ctl_stack_size = q_data->ctl_stack_size; + qp->type = q_data->type; qp->format = q_data->format; } @@ -1036,12 +1043,15 @@ int kfd_criu_restore_queue(struct kfd_pr goto exit; }
- /* data stored in this order: mqd, ctl_stack */ + /* + * data stored in this order: + * mqd[xcc0], mqd[xcc1],..., ctl_stack[xcc0], ctl_stack[xcc1]... + */ mqd = q_extra_data; ctl_stack = mqd + q_data->mqd_size;
memset(&qp, 0, sizeof(qp)); - set_queue_properties_from_criu(&qp, q_data); + set_queue_properties_from_criu(&qp, q_data, NUM_XCC(pdd->dev->adev->gfx.xcc_mask));
print_queue_properties(&qp);
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Michel Dänzer mdaenzer@redhat.com
commit 3477c1b0972dc1c8a46f78e8fb1fa6966095b5ec upstream.
amdgpu_dm_commit_planes calls update_freesync_state_on_stream only for the primary plane. If a commit affects a CRTC but not its primary plane, it would previously not trigger a refresh cycle or affect LFC, violating current UAPI semantics.
Fixes e.g. atomic commits affecting only the cursor plane being limited to the minimum refresh rate.
Don't do this for the legacy cursor ioctls though, it would break the UAPI semantics for those.
Suggested-by: Xaver Hugl xaver.hugl@kde.org Closes: https://gitlab.freedesktop.org/drm/amd/-/issues/3034 Signed-off-by: Michel Dänzer mdaenzer@redhat.com Reviewed-by: Harry Wentland harry.wentland@amd.com Signed-off-by: Alex Deucher alexander.deucher@amd.com (cherry picked from commit cc7bfba95966251b254cb970c21627124da3b7f4) Cc: stable@vger.kernel.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crtc.c | 9 +++++++++ 1 file changed, 9 insertions(+)
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crtc.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crtc.c @@ -661,6 +661,15 @@ static int amdgpu_dm_crtc_helper_atomic_ return -EINVAL; }
+ if (!state->legacy_cursor_update && amdgpu_dm_crtc_vrr_active(dm_crtc_state)) { + struct drm_plane_state *primary_state; + + /* Pull in primary plane for correct VRR handling */ + primary_state = drm_atomic_get_plane_state(state, crtc->primary); + if (IS_ERR(primary_state)) + return PTR_ERR(primary_state); + } + /* In some use cases, like reset, no stream is attached */ if (!dm_crtc_state->stream) return 0;
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Siyang Liu Security@tencent.com
commit 1bcf63a44381691d6192872801f830ce3250e367 upstream.
[Why] A null pointer dereference vulnerability exists in the AMD display driver's (DC module) cleanup function dc_destruct(). When display control context (dc->ctx) construction fails (due to memory allocation failure), this pointer remains NULL. During subsequent error handling when dc_destruct() is called, there's no NULL check before dereferencing the perf_trace member (dc->ctx->perf_trace), causing a kernel null pointer dereference crash.
[How] Check if dc->ctx is non-NULL before dereferencing.
Link: https://lore.kernel.org/r/tencent_54FF4252EDFB6533090A491A25EEF3EDBF06@qq.co... Co-developed-by: Mario Limonciello mario.limonciello@amd.com Signed-off-by: Mario Limonciello mario.limonciello@amd.com (Updated commit text and removed unnecessary error message) Signed-off-by: Siyang Liu Security@tencent.com Signed-off-by: Roman Li roman.li@amd.com Reviewed-by: Alex Hung alex.hung@amd.com Tested-by: Daniel Wheeler daniel.wheeler@amd.com Signed-off-by: Alex Deucher alexander.deucher@amd.com (cherry picked from commit 9dd8e2ba268c636c240a918e0a31e6feaee19404) Cc: stable@vger.kernel.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/gpu/drm/amd/display/dc/core/dc.c | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-)
--- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -938,17 +938,18 @@ static void dc_destruct(struct dc *dc) if (dc->link_srv) link_destroy_link_service(&dc->link_srv);
- if (dc->ctx->gpio_service) - dal_gpio_service_destroy(&dc->ctx->gpio_service); + if (dc->ctx) { + if (dc->ctx->gpio_service) + dal_gpio_service_destroy(&dc->ctx->gpio_service);
- if (dc->ctx->created_bios) - dal_bios_parser_destroy(&dc->ctx->dc_bios); + if (dc->ctx->created_bios) + dal_bios_parser_destroy(&dc->ctx->dc_bios); + kfree(dc->ctx->logger); + dc_perf_trace_destroy(&dc->ctx->perf_trace);
- kfree(dc->ctx->logger); - dc_perf_trace_destroy(&dc->ctx->perf_trace); - - kfree(dc->ctx); - dc->ctx = NULL; + kfree(dc->ctx); + dc->ctx = NULL; + }
kfree(dc->bw_vbios); dc->bw_vbios = NULL;
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Timur Kristóf timur.kristof@gmail.com
commit 1c8dc3e088e09531bcdfc9fe348204abc3decb6c upstream.
Apparently, both DCE 6.0 and 6.4 have 3 PLLs, but PLL0 can only be used for DP. Make sure to initialize the correct amount of PLLs in DC for these DCE versions and use PLL0 only for DP.
Also, on DCE 6.0 and 6.4, the PLL0 needs to be powered on at initialization as opposed to DCE 6.1 and 7.x which use a different clock source for DFS.
The following functions were used as reference from the old radeon driver implementation of DCE 6.x: - radeon_atom_pick_pll - atombios_crtc_set_disp_eng_pll
Reviewed-by: Rodrigo Siqueira siqueira@igalia.com Reviewed-by: Alex Deucher alexander.deucher@amd.com Signed-off-by: Timur Kristóf timur.kristof@gmail.com Signed-off-by: Alex Deucher alexander.deucher@amd.com (cherry picked from commit 35222b5934ec8d762473592ece98659baf6bc48e) Cc: stable@vger.kernel.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/gpu/drm/amd/display/dc/clk_mgr/dce100/dce_clk_mgr.c | 5 + drivers/gpu/drm/amd/display/dc/resource/dce60/dce60_resource.c | 34 +++++----- 2 files changed, 25 insertions(+), 14 deletions(-)
--- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dce100/dce_clk_mgr.c +++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dce100/dce_clk_mgr.c @@ -245,6 +245,11 @@ int dce_set_clock( pxl_clk_params.target_pixel_clock_100hz = requested_clk_khz * 10; pxl_clk_params.pll_id = CLOCK_SOURCE_ID_DFS;
+ /* DCE 6.0, DCE 6.4: engine clock is the same as PLL0 */ + if (clk_mgr_base->ctx->dce_version == DCE_VERSION_6_0 || + clk_mgr_base->ctx->dce_version == DCE_VERSION_6_4) + pxl_clk_params.pll_id = CLOCK_SOURCE_ID_PLL0; + if (clk_mgr_dce->dfs_bypass_active) pxl_clk_params.flags.SET_DISPCLK_DFS_BYPASS = true;
--- a/drivers/gpu/drm/amd/display/dc/resource/dce60/dce60_resource.c +++ b/drivers/gpu/drm/amd/display/dc/resource/dce60/dce60_resource.c @@ -373,7 +373,7 @@ static const struct resource_caps res_ca .num_timing_generator = 6, .num_audio = 6, .num_stream_encoder = 6, - .num_pll = 2, + .num_pll = 3, .num_ddc = 6, };
@@ -389,7 +389,7 @@ static const struct resource_caps res_ca .num_timing_generator = 2, .num_audio = 2, .num_stream_encoder = 2, - .num_pll = 2, + .num_pll = 3, .num_ddc = 2, };
@@ -973,21 +973,24 @@ static bool dce60_construct(
if (bp->fw_info_valid && bp->fw_info.external_clock_source_frequency_for_dp != 0) { pool->base.dp_clock_source = - dce60_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_EXTERNAL, NULL, true); + dce60_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_EXTERNAL, NULL, true);
+ /* DCE 6.0 and 6.4: PLL0 can only be used with DP. Don't initialize it here. */ pool->base.clock_sources[0] = - dce60_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_PLL0, &clk_src_regs[0], false); + dce60_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_PLL1, &clk_src_regs[1], false); pool->base.clock_sources[1] = - dce60_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_PLL1, &clk_src_regs[1], false); + dce60_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_PLL2, &clk_src_regs[2], false); pool->base.clk_src_count = 2;
} else { pool->base.dp_clock_source = - dce60_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_PLL0, &clk_src_regs[0], true); + dce60_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_PLL0, &clk_src_regs[0], true);
pool->base.clock_sources[0] = - dce60_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_PLL1, &clk_src_regs[1], false); - pool->base.clk_src_count = 1; + dce60_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_PLL1, &clk_src_regs[1], false); + pool->base.clock_sources[1] = + dce60_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_PLL2, &clk_src_regs[2], false); + pool->base.clk_src_count = 2; }
if (pool->base.dp_clock_source == NULL) { @@ -1365,21 +1368,24 @@ static bool dce64_construct(
if (bp->fw_info_valid && bp->fw_info.external_clock_source_frequency_for_dp != 0) { pool->base.dp_clock_source = - dce60_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_EXTERNAL, NULL, true); + dce60_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_EXTERNAL, NULL, true);
+ /* DCE 6.0 and 6.4: PLL0 can only be used with DP. Don't initialize it here. */ pool->base.clock_sources[0] = - dce60_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_PLL1, &clk_src_regs[0], false); + dce60_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_PLL1, &clk_src_regs[1], false); pool->base.clock_sources[1] = - dce60_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_PLL2, &clk_src_regs[1], false); + dce60_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_PLL2, &clk_src_regs[2], false); pool->base.clk_src_count = 2;
} else { pool->base.dp_clock_source = - dce60_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_PLL1, &clk_src_regs[0], true); + dce60_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_PLL0, &clk_src_regs[0], true);
pool->base.clock_sources[0] = - dce60_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_PLL2, &clk_src_regs[1], false); - pool->base.clk_src_count = 1; + dce60_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_PLL1, &clk_src_regs[1], false); + pool->base.clock_sources[1] = + dce60_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_PLL2, &clk_src_regs[2], false); + pool->base.clk_src_count = 2; }
if (pool->base.dp_clock_source == NULL) {
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Lauri Tirkkonen lauri@hacktheplanet.fi
commit 9c2883057b3c861879b647f34e8bc448954e8729 upstream.
DIV_ROUND_CLOSEST(x, 100) returns either 0 or 1 if 0<x<=100, so the division needs to be performed after the multiplication and not the other way around, to properly scale the value.
Fixes: 8b5f3a229a70 ("drm/amd/display: Fix default DC and AC levels") Signed-off-by: Lauri Tirkkonen lauri@hacktheplanet.fi Cc: stable@vger.kernel.org Reviewed-by: Mario Limonciello mario.limonciello@amd.com Link: https://lore.kernel.org/r/aH2Q_HJvxKbW74vU@hacktheplanet.fi Signed-off-by: Mario Limonciello mario.limonciello@amd.com Signed-off-by: Alex Deucher alexander.deucher@amd.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -4952,9 +4952,9 @@ amdgpu_dm_register_backlight_device(stru caps = &dm->backlight_caps[aconnector->bl_idx]; if (get_brightness_range(caps, &min, &max)) { if (power_supply_is_system_supplied() > 0) - props.brightness = (max - min) * DIV_ROUND_CLOSEST(caps->ac_level, 100); + props.brightness = DIV_ROUND_CLOSEST((max - min) * caps->ac_level, 100); else - props.brightness = (max - min) * DIV_ROUND_CLOSEST(caps->dc_level, 100); + props.brightness = DIV_ROUND_CLOSEST((max - min) * caps->dc_level, 100); /* min is zero, so max needs to be adjusted */ props.max_brightness = max - min; drm_dbg(drm, "Backlight caps: min: %d, max: %d, ac %d, dc %d\n", min, max,
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Mario Limonciello mario.limonciello@amd.com
commit 2b6943df54136f40aff8a6d7ba7c26724d89a0bd upstream.
[Why] If a GPU is in reset and the hardware fails to initialize the rest of the resume sequence shouldn't be run.
[How] Pass error code up to caller of dm_resume().
Reviewed-by: Alex Hung alex.hung@amd.com Signed-off-by: Mario Limonciello mario.limonciello@amd.com Signed-off-by: Ivan Lipski ivan.lipski@amd.com Tested-by: Daniel Wheeler daniel.wheeler@amd.com Signed-off-by: Alex Deucher alexander.deucher@amd.com Cc: stable@vger.kernel.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -3343,8 +3343,10 @@ static int dm_resume(struct amdgpu_ip_bl link_enc_cfg_copy(adev->dm.dc->current_state, dc_state);
r = dm_dmub_hw_init(adev); - if (r) + if (r) { drm_err(adev_to_drm(adev), "DMUB interface failed to initialize: status=%d\n", r); + return r; + }
dc_dmub_srv_set_power_state(dm->dc->ctx->dmub_srv, DC_ACPI_CM_POWER_STATE_D0); dc_set_power_state(dm->dc, DC_ACPI_CM_POWER_STATE_D0);
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Mario Limonciello mario.limonciello@amd.com
commit 8e6a18cbf3ee2c1e3d0afd8d3debd0ba8738ad0c upstream.
This reverts commit 66abb996999de0d440a02583a6e70c2c24deab45. This broke custom brightness curves but it wasn't obvious because of other related changes. Custom brightness curves are always from a 0-255 input signal. The correct fix was to fix the default value which was done by [1].
Closes: https://gitlab.freedesktop.org/drm/amd/-/issues/4412 Link: https://lore.kernel.org/amd-gfx/0f094c4b-d2a3-42cd-824c-dc2858a5618d@kernel.... Reviewed-by: Alex Hung alex.hung@amd.com Signed-off-by: Mario Limonciello mario.limonciello@amd.com Signed-off-by: Roman Li roman.li@amd.com Tested-by: Daniel Wheeler daniel.wheeler@amd.com Signed-off-by: Alex Deucher alexander.deucher@amd.com (cherry picked from commit 6ec8a5cbec751625133461600d0d4950ffd3a214) Cc: stable@vger.kernel.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-)
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -4733,16 +4733,16 @@ static int get_brightness_range(const st return 1; }
-/* Rescale from [min..max] to [0..MAX_BACKLIGHT_LEVEL] */ +/* Rescale from [min..max] to [0..AMDGPU_MAX_BL_LEVEL] */ static inline u32 scale_input_to_fw(int min, int max, u64 input) { - return DIV_ROUND_CLOSEST_ULL(input * MAX_BACKLIGHT_LEVEL, max - min); + return DIV_ROUND_CLOSEST_ULL(input * AMDGPU_MAX_BL_LEVEL, max - min); }
-/* Rescale from [0..MAX_BACKLIGHT_LEVEL] to [min..max] */ +/* Rescale from [0..AMDGPU_MAX_BL_LEVEL] to [min..max] */ static inline u32 scale_fw_to_input(int min, int max, u64 input) { - return min + DIV_ROUND_CLOSEST_ULL(input * (max - min), MAX_BACKLIGHT_LEVEL); + return min + DIV_ROUND_CLOSEST_ULL(input * (max - min), AMDGPU_MAX_BL_LEVEL); }
static void convert_custom_brightness(const struct amdgpu_dm_backlight_caps *caps,
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Timur Kristóf timur.kristof@gmail.com
commit 4db9cd554883e051df1840d4d58d636043101034 upstream.
dc_clk_mgr_create accidentally overwrites the dce60_clk_mgr with the dce_clk_mgr, causing incorrect behaviour on DCE6. Fix it by removing the extra dce_clk_mgr_construct.
Fixes: 62eab49faae7 ("drm/amd/display: hide VGH asic specific structs") Reviewed-by: Rodrigo Siqueira siqueira@igalia.com Reviewed-by: Alex Deucher alexander.deucher@amd.com Signed-off-by: Timur Kristóf timur.kristof@gmail.com Signed-off-by: Alex Deucher alexander.deucher@amd.com (cherry picked from commit bbddcbe36a686af03e91341b9bbfcca94bd45fb6) Cc: stable@vger.kernel.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/gpu/drm/amd/display/dc/clk_mgr/clk_mgr.c | 1 - 1 file changed, 1 deletion(-)
--- a/drivers/gpu/drm/amd/display/dc/clk_mgr/clk_mgr.c +++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/clk_mgr.c @@ -158,7 +158,6 @@ struct clk_mgr *dc_clk_mgr_create(struct return NULL; } dce60_clk_mgr_construct(ctx, clk_mgr); - dce_clk_mgr_construct(ctx, clk_mgr); return &clk_mgr->base; } #endif
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Bibo Mao maobibo@loongson.cn
commit 4be8cefc132606b4a6e851f37f8e8c40c406c910 upstream.
Add the flag KVM_LARCH_LBT checking in function kvm_own_lbt(), so that it can be called safely rather than duplicated enabling again.
Cc: stable@vger.kernel.org Signed-off-by: Bibo Mao maobibo@loongson.cn Signed-off-by: Huacai Chen chenhuacai@loongson.cn Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- arch/loongarch/kvm/vcpu.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-)
--- a/arch/loongarch/kvm/vcpu.c +++ b/arch/loongarch/kvm/vcpu.c @@ -1277,9 +1277,11 @@ int kvm_own_lbt(struct kvm_vcpu *vcpu) return -EINVAL;
preempt_disable(); - set_csr_euen(CSR_EUEN_LBTEN); - _restore_lbt(&vcpu->arch.lbt); - vcpu->arch.aux_inuse |= KVM_LARCH_LBT; + if (!(vcpu->arch.aux_inuse & KVM_LARCH_LBT)) { + set_csr_euen(CSR_EUEN_LBTEN); + _restore_lbt(&vcpu->arch.lbt); + vcpu->arch.aux_inuse |= KVM_LARCH_LBT; + } preempt_enable();
return 0;
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Bibo Mao maobibo@loongson.cn
commit 5c68549c81bcca70fc464e305ffeefd9af968287 upstream.
Function kvm_io_bus_read() is called in function send_ipi_data(), buffer size of parameter *val should be at least 8 bytes. Since some emulation functions like loongarch_ipi_readl() and kvm_eiointc_read() will write the buffer *val with 8 bytes signed extension regardless parameter len.
Otherwise there will be buffer overflow issue when CONFIG_STACKPROTECTOR is enabled. The bug report is shown as follows:
Kernel panic - not syncing: stack-protector: Kernel stack is corrupted in: send_ipi_data+0x194/0x1a0 [kvm] CPU: 11 UID: 107 PID: 2692 Comm: CPU 0/KVM Not tainted 6.17.0-rc1+ #102 PREEMPT(full) Stack : 9000000005901568 0000000000000000 9000000003af371c 900000013c68c000 900000013c68f850 900000013c68f858 0000000000000000 900000013c68f998 900000013c68f990 900000013c68f990 900000013c68f6c0 fffffffffffdb058 fffffffffffdb0e0 900000013c68f858 911e1d4d39cf0ec2 9000000105657a00 0000000000000001 fffffffffffffffe 0000000000000578 282049464555206e 6f73676e6f6f4c20 0000000000000001 00000000086b4000 0000000000000000 0000000000000000 0000000000000000 9000000005709968 90000000058f9000 900000013c68fa68 900000013c68fab4 90000000029279f0 900000010153f940 900000010001f360 0000000000000000 9000000003af3734 000000004390000c 00000000000000b0 0000000000000004 0000000000000000 0000000000071c1d ... Call Trace: [<9000000003af3734>] show_stack+0x5c/0x180 [<9000000003aed168>] dump_stack_lvl+0x6c/0x9c [<9000000003ad0ab0>] vpanic+0x108/0x2c4 [<9000000003ad0ca8>] panic+0x3c/0x40 [<9000000004eb0a1c>] __stack_chk_fail+0x14/0x18 [<ffff8000023473f8>] send_ipi_data+0x190/0x1a0 [kvm] [<ffff8000023313e4>] __kvm_io_bus_write+0xa4/0xe8 [kvm] [<ffff80000233147c>] kvm_io_bus_write+0x54/0x90 [kvm] [<ffff80000233f9f8>] kvm_emu_iocsr+0x180/0x310 [kvm] [<ffff80000233fe08>] kvm_handle_gspr+0x280/0x478 [kvm] [<ffff8000023443e8>] kvm_handle_exit+0xc0/0x130 [kvm]
Cc: stable@vger.kernel.org Fixes: daee2f9cae551 ("LoongArch: KVM: Add IPI read and write function") Signed-off-by: Bibo Mao maobibo@loongson.cn Signed-off-by: Huacai Chen chenhuacai@loongson.cn Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- arch/loongarch/kvm/intc/ipi.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
--- a/arch/loongarch/kvm/intc/ipi.c +++ b/arch/loongarch/kvm/intc/ipi.c @@ -99,7 +99,7 @@ static void write_mailbox(struct kvm_vcp static int send_ipi_data(struct kvm_vcpu *vcpu, gpa_t addr, uint64_t data) { int i, idx, ret; - uint32_t val = 0, mask = 0; + uint64_t val = 0, mask = 0;
/* * Bit 27-30 is mask for byte writing. @@ -108,7 +108,7 @@ static int send_ipi_data(struct kvm_vcpu if ((data >> 27) & 0xf) { /* Read the old val */ idx = srcu_read_lock(&vcpu->kvm->srcu); - ret = kvm_io_bus_read(vcpu, KVM_IOCSR_BUS, addr, sizeof(val), &val); + ret = kvm_io_bus_read(vcpu, KVM_IOCSR_BUS, addr, 4, &val); srcu_read_unlock(&vcpu->kvm->srcu, idx); if (unlikely(ret)) { kvm_err("%s: : read data from addr %llx failed\n", __func__, addr); @@ -124,7 +124,7 @@ static int send_ipi_data(struct kvm_vcpu } val |= ((uint32_t)(data >> 32) & ~mask); idx = srcu_read_lock(&vcpu->kvm->srcu); - ret = kvm_io_bus_write(vcpu, KVM_IOCSR_BUS, addr, sizeof(val), &val); + ret = kvm_io_bus_write(vcpu, KVM_IOCSR_BUS, addr, 4, &val); srcu_read_unlock(&vcpu->kvm->srcu, idx); if (unlikely(ret)) kvm_err("%s: : write data to addr %llx failed\n", __func__, addr);
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Bibo Mao maobibo@loongson.cn
commit 538c06e3964a8e94b645686cc58ccc4a06fa6330 upstream.
With pch_pic device, its register is based on MMIO address space, different access size 1/2/4/8 is supported. And base address should be naturally aligned with its access size, here add alignment check in its register access emulation function.
Cc: stable@vger.kernel.org Signed-off-by: Bibo Mao maobibo@loongson.cn Signed-off-by: Huacai Chen chenhuacai@loongson.cn Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- arch/loongarch/kvm/intc/pch_pic.c | 10 ++++++++++ 1 file changed, 10 insertions(+)
--- a/arch/loongarch/kvm/intc/pch_pic.c +++ b/arch/loongarch/kvm/intc/pch_pic.c @@ -195,6 +195,11 @@ static int kvm_pch_pic_read(struct kvm_v return -EINVAL; }
+ if (addr & (len - 1)) { + kvm_err("%s: pch pic not aligned addr %llx len %d\n", __func__, addr, len); + return -EINVAL; + } + /* statistics of pch pic reading */ vcpu->kvm->stat.pch_pic_read_exits++; ret = loongarch_pch_pic_read(s, addr, len, val); @@ -302,6 +307,11 @@ static int kvm_pch_pic_write(struct kvm_ return -EINVAL; }
+ if (addr & (len - 1)) { + kvm_err("%s: pch pic not aligned addr %llx len %d\n", __func__, addr, len); + return -EINVAL; + } + /* statistics of pch pic writing */ vcpu->kvm->stat.pch_pic_write_exits++; ret = loongarch_pch_pic_write(s, addr, len, val);
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jakub Acs acsjakub@amazon.de
commit 7af76e9d18a9fd6f8611b3313c86c190f9b6a5a7 upstream.
Receiving HSR frame with insufficient space to hold HSR tag in the skb can result in a crash (kernel BUG):
[ 45.390915] skbuff: skb_under_panic: text:ffffffff86f32cac len:26 put:14 head:ffff888042418000 data:ffff888042417ff4 tail:0xe end:0x180 dev:bridge_slave_1 [ 45.392559] ------------[ cut here ]------------ [ 45.392912] kernel BUG at net/core/skbuff.c:211! [ 45.393276] Oops: invalid opcode: 0000 [#1] SMP DEBUG_PAGEALLOC KASAN NOPTI [ 45.393809] CPU: 1 UID: 0 PID: 2496 Comm: reproducer Not tainted 6.15.0 #12 PREEMPT(undef) [ 45.394433] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS rel-1.16.3-0-ga6ed6b701f0a-prebuilt.qemu.org 04/01/2014 [ 45.395273] RIP: 0010:skb_panic+0x15b/0x1d0
<snip registers, remove unreliable trace>
[ 45.402911] Call Trace: [ 45.403105] <IRQ> [ 45.404470] skb_push+0xcd/0xf0 [ 45.404726] br_dev_queue_push_xmit+0x7c/0x6c0 [ 45.406513] br_forward_finish+0x128/0x260 [ 45.408483] __br_forward+0x42d/0x590 [ 45.409464] maybe_deliver+0x2eb/0x420 [ 45.409763] br_flood+0x174/0x4a0 [ 45.410030] br_handle_frame_finish+0xc7c/0x1bc0 [ 45.411618] br_handle_frame+0xac3/0x1230 [ 45.413674] __netif_receive_skb_core.constprop.0+0x808/0x3df0 [ 45.422966] __netif_receive_skb_one_core+0xb4/0x1f0 [ 45.424478] __netif_receive_skb+0x22/0x170 [ 45.424806] process_backlog+0x242/0x6d0 [ 45.425116] __napi_poll+0xbb/0x630 [ 45.425394] net_rx_action+0x4d1/0xcc0 [ 45.427613] handle_softirqs+0x1a4/0x580 [ 45.427926] do_softirq+0x74/0x90 [ 45.428196] </IRQ>
This issue was found by syzkaller.
The panic happens in br_dev_queue_push_xmit() once it receives a corrupted skb with ETH header already pushed in linear data. When it attempts the skb_push() call, there's not enough headroom and skb_push() panics.
The corrupted skb is put on the queue by HSR layer, which makes a sequence of unintended transformations when it receives a specific corrupted HSR frame (with incomplete TAG).
Fix it by dropping and consuming frames that are not long enough to contain both ethernet and hsr headers.
Alternative fix would be to check for enough headroom before skb_push() in br_dev_queue_push_xmit().
In the reproducer, this is injected via AF_PACKET, but I don't easily see why it couldn't be sent over the wire from adjacent network.
Further Details:
In the reproducer, the following network interface chain is set up:
┌────────────────┐ ┌────────────────┐ │ veth0_to_hsr ├───┤ hsr_slave0 ┼───┐ └────────────────┘ └────────────────┘ │ │ ┌──────┐ ├─┤ hsr0 ├───┐ │ └──────┘ │ ┌────────────────┐ ┌────────────────┐ │ │┌────────┐ │ veth1_to_hsr ┼───┤ hsr_slave1 ├───┘ └┤ │ └────────────────┘ └────────────────┘ ┌┼ bridge │ ││ │ │└────────┘ │ ┌───────┐ │ │ ... ├──────┘ └───────┘
To trigger the events leading up to crash, reproducer sends a corrupted HSR frame with incomplete TAG, via AF_PACKET socket on 'veth0_to_hsr'.
The first HSR-layer function to process this frame is hsr_handle_frame(). It and then checks if the protocol is ETH_P_PRP or ETH_P_HSR. If it is, it calls skb_set_network_header(skb, ETH_HLEN + HSR_HLEN), without checking that the skb is long enough. For the crashing frame it is not, and hence the skb->network_header and skb->mac_len fields are set incorrectly, pointing after the end of the linear buffer.
I will call this a BUG#1 and it is what is addressed by this patch. In the crashing scenario before the fix, the skb continues to go down the hsr path as follows.
hsr_handle_frame() then calls this sequence hsr_forward_skb() fill_frame_info() hsr->proto_ops->fill_frame_info() hsr_fill_frame_info()
hsr_fill_frame_info() contains a check that intends to check whether the skb actually contains the HSR header. But the check relies on the skb->mac_len field which was erroneously setup due to BUG#1, so the check passes and the execution continues back in the hsr_forward_skb():
hsr_forward_skb() hsr_forward_do() hsr->proto_ops->get_untagged_frame() hsr_get_untagged_frame() create_stripped_skb_hsr()
In create_stripped_skb_hsr(), a copy of the skb is created and is further corrupted by operation that attempts to strip the HSR tag in a call to __pskb_copy().
The skb enters create_stripped_skb_hsr() with ethernet header pushed in linear buffer. The skb_pull(skb_in, HSR_HLEN) thus pulls 6 bytes of ethernet header into the headroom, creating skb_in with a headroom of size 8. The subsequent __pskb_copy() then creates an skb with headroom of just 2 and skb->len of just 12, this is how it looks after the copy:
gdb) p skb->len $10 = 12 (gdb) p skb->data $11 = (unsigned char *) 0xffff888041e45382 "\252\252\252\252\252!\210\373", (gdb) p skb->head $12 = (unsigned char *) 0xffff888041e45380 ""
It seems create_stripped_skb_hsr() assumes that ETH header is pulled in the headroom when it's entered, because it just pulls HSR header on top. But that is not the case in our code-path and we end up with the corrupted skb instead. I will call this BUG#2
*I got confused here because it seems that under no conditions can create_stripped_skb_hsr() work well, the assumption it makes is not true during the processing of hsr frames - since the skb_push() in hsr_handle_frame to skb_pull in hsr_deliver_master(). I wonder whether I missed something here.*
Next, the execution arrives in hsr_deliver_master(). It calls skb_pull(ETH_HLEN), which just returns NULL - the SKB does not have enough space for the pull (as it only has 12 bytes in total at this point).
*The skb_pull() here further suggests that ethernet header is meant to be pushed through the whole hsr processing and create_stripped_skb_hsr() should pull it before doing the HSR header pull.*
hsr_deliver_master() then puts the corrupted skb on the queue, it is then picked up from there by bridge frame handling layer and finally lands in br_dev_queue_push_xmit where it panics.
Cc: stable@kernel.org Fixes: 48b491a5cc74 ("net: hsr: fix mac_len checks") Reported-by: syzbot+a81f2759d022496b40ab@syzkaller.appspotmail.com Signed-off-by: Jakub Acs acsjakub@amazon.de Reviewed-by: Eric Dumazet edumazet@google.com Link: https://patch.msgid.link/20250819082842.94378-1-acsjakub@amazon.de Signed-off-by: Jakub Kicinski kuba@kernel.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- net/hsr/hsr_slave.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-)
--- a/net/hsr/hsr_slave.c +++ b/net/hsr/hsr_slave.c @@ -63,8 +63,14 @@ static rx_handler_result_t hsr_handle_fr skb_push(skb, ETH_HLEN); skb_reset_mac_header(skb); if ((!hsr->prot_version && protocol == htons(ETH_P_PRP)) || - protocol == htons(ETH_P_HSR)) + protocol == htons(ETH_P_HSR)) { + if (!pskb_may_pull(skb, ETH_HLEN + HSR_HLEN)) { + kfree_skb(skb); + goto finish_consume; + } + skb_set_network_header(skb, ETH_HLEN + HSR_HLEN); + } skb_reset_mac_len(skb);
/* Only the frames received over the interlink port will assign a
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Andrea Righi arighi@nvidia.com
commit ddf7233fcab6c247379d0928d46cc316ee122229 upstream.
When enabling a sched_ext scheduler, we may trigger invalid task state transitions, resulting in warnings like the following (which can be easily reproduced by running the hotplug selftest in a loop):
sched_ext: Invalid task state transition 0 -> 3 for fish[770] WARNING: CPU: 18 PID: 787 at kernel/sched/ext.c:3862 scx_set_task_state+0x7c/0xc0 ... RIP: 0010:scx_set_task_state+0x7c/0xc0 ... Call Trace: <TASK> scx_enable_task+0x11f/0x2e0 switching_to_scx+0x24/0x110 scx_enable.isra.0+0xd14/0x13d0 bpf_struct_ops_link_create+0x136/0x1a0 __sys_bpf+0x1edd/0x2c30 __x64_sys_bpf+0x21/0x30 do_syscall_64+0xbb/0x370 entry_SYSCALL_64_after_hwframe+0x77/0x7f
This happens because we skip initialization for tasks that are already dead (with their usage counter set to zero), but we don't exclude them during the scheduling class transition phase.
Fix this by also skipping dead tasks during class swiching, preventing invalid task state transitions.
Fixes: a8532fac7b5d2 ("sched_ext: TASK_DEAD tasks must be switched into SCX on ops_enable") Cc: stable@vger.kernel.org # v6.12+ Signed-off-by: Andrea Righi arighi@nvidia.com Signed-off-by: Tejun Heo tj@kernel.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- kernel/sched/ext.c | 4 ++++ 1 file changed, 4 insertions(+)
--- a/kernel/sched/ext.c +++ b/kernel/sched/ext.c @@ -5694,6 +5694,9 @@ static int scx_enable(struct sched_ext_o __setscheduler_class(p->policy, p->prio); struct sched_enq_and_set_ctx ctx;
+ if (!tryget_task_struct(p)) + continue; + if (old_class != new_class && p->se.sched_delayed) dequeue_task(task_rq(p), p, DEQUEUE_SLEEP | DEQUEUE_DELAYED);
@@ -5706,6 +5709,7 @@ static int scx_enable(struct sched_ext_o sched_enq_and_set_task(&ctx);
check_class_changed(task_rq(p), p, old_class, p->prio); + put_task_struct(p); } scx_task_iter_stop(&sti); percpu_up_write(&scx_fork_rwsem);
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Eric Biggers ebiggers@kernel.org
commit a458b2902115b26a25d67393b12ddd57d1216aaa upstream.
To prevent timing attacks, MACs need to be compared in constant time. Use the appropriate helper function for this.
Fixes: bf355b8d2c30 ("ipv6: sr: add core files for SR HMAC support") Cc: stable@vger.kernel.org Signed-off-by: Eric Biggers ebiggers@kernel.org Reviewed-by: Andrea Mayer andrea.mayer@uniroma2.it Link: https://patch.msgid.link/20250818202724.15713-1-ebiggers@kernel.org Signed-off-by: Jakub Kicinski kuba@kernel.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- net/ipv6/seg6_hmac.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
--- a/net/ipv6/seg6_hmac.c +++ b/net/ipv6/seg6_hmac.c @@ -35,6 +35,7 @@ #include <net/xfrm.h>
#include <crypto/hash.h> +#include <crypto/utils.h> #include <net/seg6.h> #include <net/genetlink.h> #include <net/seg6_hmac.h> @@ -280,7 +281,7 @@ bool seg6_hmac_validate_skb(struct sk_bu if (seg6_hmac_compute(hinfo, srh, &ipv6_hdr(skb)->saddr, hmac_output)) return false;
- if (memcmp(hmac_output, tlv->hmac, SEG6_HMAC_FIELD_LEN) != 0) + if (crypto_memneq(hmac_output, tlv->hmac, SEG6_HMAC_FIELD_LEN)) return false;
return true;
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: JP Kobryn inwardvessel@gmail.com
commit eea51c6e3f6675b795f6439eaa960eb2948d6905 upstream.
css_rstat_exit() may be called asynchronously in scenarios where preceding calls to css_rstat_init() have not completed. One such example is this sequence below:
css_create(...) { ... init_and_link_css(css, ...);
err = percpu_ref_init(...); if (err) goto err_free_css; err = cgroup_idr_alloc(...); if (err) goto err_free_css; err = css_rstat_init(css, ...); if (err) goto err_free_css; ... err_free_css: INIT_RCU_WORK(&css->destroy_rwork, css_free_rwork_fn); queue_rcu_work(cgroup_destroy_wq, &css->destroy_rwork); return ERR_PTR(err); }
If any of the three goto jumps are taken, async cleanup will begin and css_rstat_exit() will be invoked on an uninitialized css->rstat_cpu.
Avoid accessing the unitialized field by returning early in css_rstat_exit() if this is the case.
Signed-off-by: JP Kobryn inwardvessel@gmail.com Suggested-by: Michal Koutný mkoutny@suse.com Fixes: 5da3bfa029d68 ("cgroup: use separate rstat trees for each subsystem") Cc: stable@vger.kernel.org # v6.16 Reported-by: syzbot+8d052e8b99e40bc625ed@syzkaller.appspotmail.com Acked-by: Shakeel Butt shakeel.butt@linux.dev Signed-off-by: Tejun Heo tj@kernel.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- kernel/cgroup/rstat.c | 3 +++ 1 file changed, 3 insertions(+)
--- a/kernel/cgroup/rstat.c +++ b/kernel/cgroup/rstat.c @@ -488,6 +488,9 @@ void css_rstat_exit(struct cgroup_subsys if (!css_uses_rstat(css)) return;
+ if (!css->rstat_cpu) + return; + css_rstat_flush(css);
/* sanity check */
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Rafael J. Wysocki rafael.j.wysocki@intel.com
commit 779b1a1cb13ae17028aeddb2fbbdba97357a1e15 upstream.
Occasionally, the exit latency of the idle state selected by the menu governor may exceed the PM QoS CPU wakeup latency limit. Namely, if the scheduler tick has been stopped already and predicted_ns is greater than the tick period length, the governor may return an idle state whose exit latency exceeds latency_req because that decision is made before checking the current idle state's exit latency.
For instance, say that there are 3 idle states, 0, 1, and 2. For idle states 0 and 1, the exit latency is equal to the target residency and the values are 0 and 5 us, respectively. State 2 is deeper and has the exit latency and target residency of 200 us and 2 ms (which is greater than the tick period length), respectively.
Say that predicted_ns is equal to TICK_NSEC and the PM QoS latency limit is 20 us. After the first two iterations of the main loop in menu_select(), idx becomes 1 and in the third iteration of it the target residency of the current state (state 2) is greater than predicted_ns. State 2 is not a polling one and predicted_ns is not less than TICK_NSEC, so the check on whether or not the tick has been stopped is done. Say that the tick has been stopped already and there are no imminent timers (that is, delta_tick is greater than the target residency of state 2). In that case, idx becomes 2 and it is returned immediately, but the exit latency of state 2 exceeds the latency limit.
Address this issue by modifying the code to compare the exit latency of the current idle state (idle state i) with the latency limit before comparing its target residency with predicted_ns, which allows one more exit_latency_ns check that becomes redundant to be dropped.
However, after the above change, latency_req cannot take the predicted_ns value any more, which takes place after commit 38f83090f515 ("cpuidle: menu: Remove iowait influence"), because it may cause a polling state to be returned prematurely.
In the context of the previous example say that predicted_ns is 3000 and the PM QoS latency limit is still 20 us. Additionally, say that idle state 0 is a polling one. Moving the exit_latency_ns check before the target_residency_ns one causes the loop to terminate in the second iteration, before the target_residency_ns check, so idle state 0 will be returned even though previously state 1 would be returned if there were no imminent timers.
For this reason, remove the assignment of the predicted_ns value to latency_req from the code.
Fixes: 5ef499cd571c ("cpuidle: menu: Handle stopped tick more aggressively") Cc: 4.17+ stable@vger.kernel.org # 4.17+ Signed-off-by: Rafael J. Wysocki rafael.j.wysocki@intel.com Reviewed-by: Christian Loehle christian.loehle@arm.com Link: https://patch.msgid.link/5043159.31r3eYUQgx@rafael.j.wysocki Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/cpuidle/governors/menu.c | 29 ++++++++++++----------------- 1 file changed, 12 insertions(+), 17 deletions(-)
--- a/drivers/cpuidle/governors/menu.c +++ b/drivers/cpuidle/governors/menu.c @@ -287,20 +287,15 @@ static int menu_select(struct cpuidle_dr return 0; }
- if (tick_nohz_tick_stopped()) { - /* - * If the tick is already stopped, the cost of possible short - * idle duration misprediction is much higher, because the CPU - * may be stuck in a shallow idle state for a long time as a - * result of it. In that case say we might mispredict and use - * the known time till the closest timer event for the idle - * state selection. - */ - if (predicted_ns < TICK_NSEC) - predicted_ns = data->next_timer_ns; - } else if (latency_req > predicted_ns) { - latency_req = predicted_ns; - } + /* + * If the tick is already stopped, the cost of possible short idle + * duration misprediction is much higher, because the CPU may be stuck + * in a shallow idle state for a long time as a result of it. In that + * case, say we might mispredict and use the known time till the closest + * timer event for the idle state selection. + */ + if (tick_nohz_tick_stopped() && predicted_ns < TICK_NSEC) + predicted_ns = data->next_timer_ns;
/* * Find the idle state with the lowest power while satisfying @@ -316,13 +311,15 @@ static int menu_select(struct cpuidle_dr if (idx == -1) idx = i; /* first enabled state */
+ if (s->exit_latency_ns > latency_req) + break; + if (s->target_residency_ns > predicted_ns) { /* * Use a physical idle state, not busy polling, unless * a timer is going to trigger soon enough. */ if ((drv->states[idx].flags & CPUIDLE_FLAG_POLLING) && - s->exit_latency_ns <= latency_req && s->target_residency_ns <= data->next_timer_ns) { predicted_ns = s->target_residency_ns; idx = i; @@ -354,8 +351,6 @@ static int menu_select(struct cpuidle_dr
return idx; } - if (s->exit_latency_ns > latency_req) - break;
idx = i; }
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chen Yu yu.c.chen@intel.com
commit 8151320c747efb22d30b035af989fed0d502176e upstream.
The security-version-number check should be used rather than the runtime version check for driver updates.
Otherwise, the firmware update would fail when the update binary had a lower runtime version number than the current one.
Fixes: 0db89fa243e5 ("ACPI: Introduce Platform Firmware Runtime Update device driver") Cc: 5.17+ stable@vger.kernel.org # 5.17+ Reported-by: "Govindarajulu, Hariganesh" hariganesh.govindarajulu@intel.com Signed-off-by: Chen Yu yu.c.chen@intel.com Link: https://patch.msgid.link/20250722143233.3970607-1-yu.c.chen@intel.com [ rjw: Changelog edits ] Signed-off-by: Rafael J. Wysocki rafael.j.wysocki@intel.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/acpi/pfr_update.c | 2 +- include/uapi/linux/pfrut.h | 1 + 2 files changed, 2 insertions(+), 1 deletion(-)
--- a/drivers/acpi/pfr_update.c +++ b/drivers/acpi/pfr_update.c @@ -310,7 +310,7 @@ static bool applicable_image(const void if (type == PFRU_CODE_INJECT_TYPE) return payload_hdr->rt_ver >= cap->code_rt_version;
- return payload_hdr->rt_ver >= cap->drv_rt_version; + return payload_hdr->svn_ver >= cap->drv_svn; }
static void print_update_debug_info(struct pfru_updated_result *result, --- a/include/uapi/linux/pfrut.h +++ b/include/uapi/linux/pfrut.h @@ -89,6 +89,7 @@ struct pfru_payload_hdr { __u32 hw_ver; __u32 rt_ver; __u8 platform_id[16]; + __u32 svn_ver; };
enum pfru_dsm_status {
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Uwe Kleine-König u.kleine-koenig@baylibre.com
commit b21d1fbb97c814c76ffa392cd603f8cd3ecc0355 upstream.
The .remove() callback is also used during error handling in faux_probe(). As einj_remove() was marked with __exit it's not linked into the kernel if the driver is built-in, potentially resulting in resource leaks.
Also remove the comment justifying the __exit annotation which doesn't apply any more since the driver was converted to the faux device interface.
Fixes: 6cb9441bfe8d ("ACPI: APEI: EINJ: Transition to the faux device interface") Signed-off-by: Uwe Kleine-König u.kleine-koenig@baylibre.com Cc: 6.16+ stable@vger.kernel.org # 6.16+ Link: https://patch.msgid.link/20250814051157.35867-2-u.kleine-koenig@baylibre.com Signed-off-by: Rafael J. Wysocki rafael.j.wysocki@intel.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/acpi/apei/einj-core.c | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-)
--- a/drivers/acpi/apei/einj-core.c +++ b/drivers/acpi/apei/einj-core.c @@ -842,7 +842,7 @@ err_put_table: return rc; }
-static void __exit einj_remove(struct faux_device *fdev) +static void einj_remove(struct faux_device *fdev) { struct apei_exec_context ctx;
@@ -864,15 +864,9 @@ static void __exit einj_remove(struct fa }
static struct faux_device *einj_dev; -/* - * einj_remove() lives in .exit.text. For drivers registered via - * platform_driver_probe() this is ok because they cannot get unbound at - * runtime. So mark the driver struct with __refdata to prevent modpost - * triggering a section mismatch warning. - */ -static struct faux_device_ops einj_device_ops __refdata = { +static struct faux_device_ops einj_device_ops = { .probe = einj_probe, - .remove = __exit_p(einj_remove), + .remove = einj_remove, };
static int __init einj_init(void)
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Christoph Paasch cpaasch@openai.com
commit ccab044697980c6c01ab51f43f48f13b8a3e5c33 upstream.
When skb_ext_add(skb, SKB_EXT_MPTCP) fails in mptcp_incoming_options(), we used to return true, letting the segment proceed through the TCP receive path without a DSS mapping. Such segments can leave inconsistent mapping state and trigger a mid-stream fallback to TCP, which in testing collapsed (by artificially forcing failures in skb_ext_add) throughput to zero.
Return false instead so the TCP input path drops the skb (see tcp_data_queue() and step-7 processing). This is the safer choice under memory pressure: it preserves MPTCP correctness and provides backpressure to the sender.
Control packets remain unaffected: ACK updates and DATA_FIN handling happen before attempting the extension allocation, and tcp_reset() continues to ignore the return value.
With this change, MPTCP continues to work at high throughput if we artificially inject failures into skb_ext_add.
Fixes: 6787b7e350d3 ("mptcp: avoid processing packet if a subflow reset") Cc: stable@vger.kernel.org Signed-off-by: Christoph Paasch cpaasch@openai.com Reviewed-by: Matthieu Baerts (NGI0) matttbe@kernel.org Signed-off-by: Matthieu Baerts (NGI0) matttbe@kernel.org Link: https://patch.msgid.link/20250815-net-mptcp-misc-fixes-6-17-rc2-v1-1-521fe99... Signed-off-by: Jakub Kicinski kuba@kernel.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- net/mptcp/options.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-)
--- a/net/mptcp/options.c +++ b/net/mptcp/options.c @@ -1117,7 +1117,9 @@ static bool add_addr_hmac_valid(struct m return hmac == mp_opt->ahmac; }
-/* Return false if a subflow has been reset, else return true */ +/* Return false in case of error (or subflow has been reset), + * else return true. + */ bool mptcp_incoming_options(struct sock *sk, struct sk_buff *skb) { struct mptcp_subflow_context *subflow = mptcp_subflow_ctx(sk); @@ -1221,7 +1223,7 @@ bool mptcp_incoming_options(struct sock
mpext = skb_ext_add(skb, SKB_EXT_MPTCP); if (!mpext) - return true; + return false;
memset(mpext, 0, sizeof(*mpext));
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Matthieu Baerts (NGI0) matttbe@kernel.org
commit 68fc0f4b0d25692940cdc85c68e366cae63e1757 upstream.
A flush of the MPTCP endpoints should not affect the MPTCP limits. In other words, 'ip mptcp endpoint flush' should not change 'ip mptcp limits'.
But it was the case: the MPTCP_PM_ATTR_RCV_ADD_ADDRS (add_addr_accepted) limit was reset by accident. Removing the reset of this counter during a flush fixes this issue.
Fixes: 01cacb00b35c ("mptcp: add netlink-based PM") Cc: stable@vger.kernel.org Reported-by: Thomas Dreibholz dreibh@simula.no Closes: https://github.com/multipath-tcp/mptcp_net-next/issues/579 Reviewed-by: Mat Martineau martineau@kernel.org Signed-off-by: Matthieu Baerts (NGI0) matttbe@kernel.org Link: https://patch.msgid.link/20250815-net-mptcp-misc-fixes-6-17-rc2-v1-2-521fe99... Signed-off-by: Jakub Kicinski kuba@kernel.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- net/mptcp/pm_kernel.c | 1 - 1 file changed, 1 deletion(-)
--- a/net/mptcp/pm_kernel.c +++ b/net/mptcp/pm_kernel.c @@ -1085,7 +1085,6 @@ static void __flush_addrs(struct list_he static void __reset_counters(struct pm_nl_pernet *pernet) { WRITE_ONCE(pernet->add_addr_signal_max, 0); - WRITE_ONCE(pernet->add_addr_accept_max, 0); WRITE_ONCE(pernet->local_addr_max, 0); pernet->addrs = 0; }
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Geliang Tang tanggeliang@kylinos.cn
commit 5d13349472ac8abcbcb94407969aa0fdc2e1f1be upstream.
sk_reset_timer() was called twice in mptcp_pm_alloc_anno_list.
Simplify the code by using a 'goto' statement to eliminate the duplication.
Note that this is not a fix, but it will help backporting the following patch. The same "Fixes" tag has been added for this reason.
Fixes: 93f323b9cccc ("mptcp: add a new sysctl add_addr_timeout") Cc: stable@vger.kernel.org Signed-off-by: Geliang Tang tanggeliang@kylinos.cn Reviewed-by: Matthieu Baerts (NGI0) matttbe@kernel.org Signed-off-by: Matthieu Baerts (NGI0) matttbe@kernel.org Link: https://patch.msgid.link/20250815-net-mptcp-misc-fixes-6-17-rc2-v1-4-521fe99... Signed-off-by: Jakub Kicinski kuba@kernel.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- net/mptcp/pm.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-)
--- a/net/mptcp/pm.c +++ b/net/mptcp/pm.c @@ -353,9 +353,7 @@ bool mptcp_pm_alloc_anno_list(struct mpt if (WARN_ON_ONCE(mptcp_pm_is_kernel(msk))) return false;
- sk_reset_timer(sk, &add_entry->add_timer, - jiffies + mptcp_get_add_addr_timeout(net)); - return true; + goto reset_timer; }
add_entry = kmalloc(sizeof(*add_entry), GFP_ATOMIC); @@ -369,6 +367,7 @@ bool mptcp_pm_alloc_anno_list(struct mpt add_entry->retrans_times = 0;
timer_setup(&add_entry->add_timer, mptcp_pm_add_timer, 0); +reset_timer: sk_reset_timer(sk, &add_entry->add_timer, jiffies + mptcp_get_add_addr_timeout(net));
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Geliang Tang tanggeliang@kylinos.cn
commit f5ce0714623cffd00bf2a83e890d09c609b7f50a upstream.
When add_addr_timeout was set to 0, this caused the ADD_ADDR to be retransmitted immediately, which looks like a buggy behaviour. Instead, interpret 0 as "no retransmissions needed".
The documentation is updated to explicitly state that setting the timeout to 0 disables retransmission.
Fixes: 93f323b9cccc ("mptcp: add a new sysctl add_addr_timeout") Cc: stable@vger.kernel.org Suggested-by: Matthieu Baerts matttbe@kernel.org Signed-off-by: Geliang Tang tanggeliang@kylinos.cn Reviewed-by: Matthieu Baerts (NGI0) matttbe@kernel.org Signed-off-by: Matthieu Baerts (NGI0) matttbe@kernel.org Link: https://patch.msgid.link/20250815-net-mptcp-misc-fixes-6-17-rc2-v1-5-521fe99... Signed-off-by: Jakub Kicinski kuba@kernel.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- Documentation/networking/mptcp-sysctl.rst | 2 ++ net/mptcp/pm.c | 13 ++++++++++--- 2 files changed, 12 insertions(+), 3 deletions(-)
--- a/Documentation/networking/mptcp-sysctl.rst +++ b/Documentation/networking/mptcp-sysctl.rst @@ -12,6 +12,8 @@ add_addr_timeout - INTEGER (seconds) resent to an MPTCP peer that has not acknowledged a previous ADD_ADDR message.
+ Do not retransmit if set to 0. + The default value matches TCP_RTO_MAX. This is a per-namespace sysctl.
--- a/net/mptcp/pm.c +++ b/net/mptcp/pm.c @@ -274,6 +274,7 @@ static void mptcp_pm_add_timer(struct ti add_timer); struct mptcp_sock *msk = entry->sock; struct sock *sk = (struct sock *)msk; + unsigned int timeout;
pr_debug("msk=%p\n", msk);
@@ -291,6 +292,10 @@ static void mptcp_pm_add_timer(struct ti goto out; }
+ timeout = mptcp_get_add_addr_timeout(sock_net(sk)); + if (!timeout) + goto out; + spin_lock_bh(&msk->pm.lock);
if (!mptcp_pm_should_add_signal_addr(msk)) { @@ -302,7 +307,7 @@ static void mptcp_pm_add_timer(struct ti
if (entry->retrans_times < ADD_ADDR_RETRANS_MAX) sk_reset_timer(sk, timer, - jiffies + mptcp_get_add_addr_timeout(sock_net(sk))); + jiffies + timeout);
spin_unlock_bh(&msk->pm.lock);
@@ -344,6 +349,7 @@ bool mptcp_pm_alloc_anno_list(struct mpt struct mptcp_pm_add_entry *add_entry = NULL; struct sock *sk = (struct sock *)msk; struct net *net = sock_net(sk); + unsigned int timeout;
lockdep_assert_held(&msk->pm.lock);
@@ -368,8 +374,9 @@ bool mptcp_pm_alloc_anno_list(struct mpt
timer_setup(&add_entry->add_timer, mptcp_pm_add_timer, 0); reset_timer: - sk_reset_timer(sk, &add_entry->add_timer, - jiffies + mptcp_get_add_addr_timeout(net)); + timeout = mptcp_get_add_addr_timeout(net); + if (timeout) + sk_reset_timer(sk, &add_entry->add_timer, jiffies + timeout);
return true; }
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Matthieu Baerts (NGI0) matttbe@kernel.org
commit 452690be7de2f91cc0de68cb9e95252875b33503 upstream.
This modification is linked to the parent commit where the received ADD_ADDR limit was accidentally reset when the endpoints were flushed.
To validate that, the test is now flushing endpoints after having set new limits, and before checking them.
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: 01cacb00b35c ("mptcp: add netlink-based PM") Cc: stable@vger.kernel.org Reviewed-by: Mat Martineau martineau@kernel.org Signed-off-by: Matthieu Baerts (NGI0) matttbe@kernel.org Link: https://patch.msgid.link/20250815-net-mptcp-misc-fixes-6-17-rc2-v1-3-521fe99... Signed-off-by: Jakub Kicinski kuba@kernel.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- tools/testing/selftests/net/mptcp/pm_netlink.sh | 1 + 1 file changed, 1 insertion(+)
--- a/tools/testing/selftests/net/mptcp/pm_netlink.sh +++ b/tools/testing/selftests/net/mptcp/pm_netlink.sh @@ -198,6 +198,7 @@ set_limits 1 9 2>/dev/null check "get_limits" "${default_limits}" "subflows above hard limit"
set_limits 8 8 +flush_endpoint ## to make sure it doesn't affect the limits check "get_limits" "$(format_limits 8 8)" "set limits"
flush_endpoint
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Matthieu Baerts (NGI0) matttbe@kernel.org
commit 2eefbed30d46d5e68593baf6b52923e00e7678af upstream.
GCC was complaining about the new label:
mptcp_connect.c:187:2: warning: label followed by a declaration is a C23 extension [-Wc23-extensions] 187 | int err = getaddrinfo(node, service, hints, res); | ^
Simply declare 'err' before the label to avoid this warning.
Fixes: a862771d1aa4 ("selftests: mptcp: use IPPROTO_MPTCP for getaddrinfo") Cc: stable@vger.kernel.org Reviewed-by: Geliang Tang geliang@kernel.org Signed-off-by: Matthieu Baerts (NGI0) matttbe@kernel.org Link: https://patch.msgid.link/20250815-net-mptcp-misc-fixes-6-17-rc2-v1-7-521fe99... Signed-off-by: Jakub Kicinski kuba@kernel.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- tools/testing/selftests/net/mptcp/mptcp_connect.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/tools/testing/selftests/net/mptcp/mptcp_connect.c b/tools/testing/selftests/net/mptcp/mptcp_connect.c index ac1349c4b9e5..4f07ac9fa207 100644 --- a/tools/testing/selftests/net/mptcp/mptcp_connect.c +++ b/tools/testing/selftests/net/mptcp/mptcp_connect.c @@ -183,9 +183,10 @@ static void xgetaddrinfo(const char *node, const char *service, struct addrinfo *hints, struct addrinfo **res) { -again: - int err = getaddrinfo(node, service, hints, res); + int err;
+again: + err = getaddrinfo(node, service, hints, res); if (err) { const char *errstr;
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Matthieu Baerts (NGI0) matttbe@kernel.org
commit 3259889fd3c0cc165b7e9ee375c789875dd32326 upstream.
GCC was complaining about the new label:
mptcp_inq.c:79:2: warning: label followed by a declaration is a C23 extension [-Wc23-extensions] 79 | int err = getaddrinfo(node, service, hints, res); | ^
mptcp_sockopt.c:166:2: warning: label followed by a declaration is a C23 extension [-Wc23-extensions] 166 | int err = getaddrinfo(node, service, hints, res); | ^
Simply declare 'err' before the label to avoid this warning.
Fixes: dd367e81b79a ("selftests: mptcp: sockopt: use IPPROTO_MPTCP for getaddrinfo") Cc: stable@vger.kernel.org Reviewed-by: Geliang Tang geliang@kernel.org Signed-off-by: Matthieu Baerts (NGI0) matttbe@kernel.org Link: https://patch.msgid.link/20250815-net-mptcp-misc-fixes-6-17-rc2-v1-8-521fe99... Signed-off-by: Jakub Kicinski kuba@kernel.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- tools/testing/selftests/net/mptcp/mptcp_inq.c | 5 +++-- tools/testing/selftests/net/mptcp/mptcp_sockopt.c | 5 +++-- 2 files changed, 6 insertions(+), 4 deletions(-)
--- a/tools/testing/selftests/net/mptcp/mptcp_inq.c +++ b/tools/testing/selftests/net/mptcp/mptcp_inq.c @@ -75,9 +75,10 @@ static void xgetaddrinfo(const char *nod struct addrinfo *hints, struct addrinfo **res) { -again: - int err = getaddrinfo(node, service, hints, res); + int err;
+again: + err = getaddrinfo(node, service, hints, res); if (err) { const char *errstr;
--- a/tools/testing/selftests/net/mptcp/mptcp_sockopt.c +++ b/tools/testing/selftests/net/mptcp/mptcp_sockopt.c @@ -162,9 +162,10 @@ static void xgetaddrinfo(const char *nod struct addrinfo *hints, struct addrinfo **res) { -again: - int err = getaddrinfo(node, service, hints, res); + int err;
+again: + err = getaddrinfo(node, service, hints, res); if (err) { const char *errstr;
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: SeongJae Park sj@kernel.org
commit 7e6c3130690a01076efdf45aa02ba5d5c16849a0 upstream.
damon_migrate_pages() tries migration even if the target node is invalid. If users mistakenly make such invalid requests via DAMOS_MIGRATE_{HOT,COLD} action, the below kernel BUG can happen.
[ 7831.883495] BUG: unable to handle page fault for address: 0000000000001f48 [ 7831.884160] #PF: supervisor read access in kernel mode [ 7831.884681] #PF: error_code(0x0000) - not-present page [ 7831.885203] PGD 0 P4D 0 [ 7831.885468] Oops: Oops: 0000 [#1] SMP PTI [ 7831.885852] CPU: 31 UID: 0 PID: 94202 Comm: kdamond.0 Not tainted 6.16.0-rc5-mm-new-damon+ #93 PREEMPT(voluntary) [ 7831.886913] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.16.3-4.el9 04/01/2014 [ 7831.887777] RIP: 0010:__alloc_frozen_pages_noprof (include/linux/mmzone.h:1724 include/linux/mmzone.h:1750 mm/page_alloc.c:4936 mm/page_alloc.c:5137) [...] [ 7831.895953] Call Trace: [ 7831.896195] <TASK> [ 7831.896397] __folio_alloc_noprof (mm/page_alloc.c:5183 mm/page_alloc.c:5192) [ 7831.896787] migrate_pages_batch (mm/migrate.c:1189 mm/migrate.c:1851) [ 7831.897228] ? __pfx_alloc_migration_target (mm/migrate.c:2137) [ 7831.897735] migrate_pages (mm/migrate.c:2078) [ 7831.898141] ? __pfx_alloc_migration_target (mm/migrate.c:2137) [ 7831.898664] damon_migrate_folio_list (mm/damon/ops-common.c:321 mm/damon/ops-common.c:354) [ 7831.899140] damon_migrate_pages (mm/damon/ops-common.c:405) [...]
Add a target node validity check in damon_migrate_pages(). The validity check is stolen from that of do_pages_move(), which is being used for the move_pages() system call.
Link: https://lkml.kernel.org/r/20250720185822.1451-1-sj@kernel.org Fixes: b51820ebea65 ("mm/damon/paddr: introduce DAMOS_MIGRATE_COLD action for demotion") [6.11.x] Signed-off-by: SeongJae Park sj@kernel.org Reviewed-by: Joshua Hahn joshua.hahnjy@gmail.com Cc: Honggyu Kim honggyu.kim@sk.com Cc: Hyeongtak Ji hyeongtak.ji@sk.com Cc: stable@vger.kernel.org Signed-off-by: Andrew Morton akpm@linux-foundation.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- mm/damon/paddr.c | 4 ++++ 1 file changed, 4 insertions(+)
--- a/mm/damon/paddr.c +++ b/mm/damon/paddr.c @@ -476,6 +476,10 @@ static unsigned long damon_pa_migrate_pa if (list_empty(folio_list)) return nr_migrated;
+ if (target_nid < 0 || target_nid >= MAX_NUMNODES || + !node_state(target_nid, N_MEMORY)) + return nr_migrated; + noreclaim_flag = memalloc_noreclaim_save();
nid = folio_nid(lru_to_folio(folio_list));
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: David Sterba dsterba@suse.com
[ Upstream commit b63c8c1ede4407835cb8c8bed2014d96619389f3 ]
Transaction aborts should be done next to the place the error happens, which was not done in add_block_group_free_space().
Reviewed-by: Filipe Manana fdmanana@suse.com Signed-off-by: David Sterba dsterba@suse.com Stable-dep-of: 1f06c942aa70 ("btrfs: always abort transaction on failure to add block group to free space tree") Signed-off-by: Sasha Levin sashal@kernel.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- fs/btrfs/free-space-tree.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-)
--- a/fs/btrfs/free-space-tree.c +++ b/fs/btrfs/free-space-tree.c @@ -1456,16 +1456,17 @@ int add_block_group_free_space(struct bt path = btrfs_alloc_path(); if (!path) { ret = -ENOMEM; + btrfs_abort_transaction(trans, ret); goto out; }
ret = __add_block_group_free_space(trans, block_group, path); + if (ret) + btrfs_abort_transaction(trans, ret);
out: btrfs_free_path(path); mutex_unlock(&block_group->free_space_lock); - if (ret) - btrfs_abort_transaction(trans, ret); return ret; }
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Filipe Manana fdmanana@suse.com
[ Upstream commit 1f06c942aa709d397cf6bed577a0d10a61509667 ]
Only one of the callers of __add_block_group_free_space() aborts the transaction if the call fails, while the others don't do it and it's either never done up the call chain or much higher in the call chain.
So make sure we abort the transaction at __add_block_group_free_space() if it fails, which brings a couple benefits:
1) If some call chain never aborts the transaction, we avoid having some metadata inconsistency because BLOCK_GROUP_FLAG_NEEDS_FREE_SPACE is cleared when we enter __add_block_group_free_space() and therefore __add_block_group_free_space() is never called again to add the block group items to the free space tree, since the function is only called when that flag is set in a block group;
2) If the call chain already aborts the transaction, then we get a better trace that points to the exact step from __add_block_group_free_space() which failed, which is better for analysis.
So abort the transaction at __add_block_group_free_space() if any of its steps fails.
CC: stable@vger.kernel.org # 6.6+ Reviewed-by: Boris Burkov boris@bur.io Signed-off-by: Filipe Manana fdmanana@suse.com Reviewed-by: David Sterba dsterba@suse.com Signed-off-by: David Sterba dsterba@suse.com Signed-off-by: Sasha Levin sashal@kernel.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- fs/btrfs/free-space-tree.c | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-)
--- a/fs/btrfs/free-space-tree.c +++ b/fs/btrfs/free-space-tree.c @@ -1431,12 +1431,17 @@ static int __add_block_group_free_space( set_bit(BLOCK_GROUP_FLAG_FREE_SPACE_ADDED, &block_group->runtime_flags);
ret = add_new_free_space_info(trans, block_group, path); - if (ret) + if (ret) { + btrfs_abort_transaction(trans, ret); return ret; + }
- return __add_to_free_space_tree(trans, block_group, path, - block_group->start, - block_group->length); + ret = __add_to_free_space_tree(trans, block_group, path, + block_group->start, block_group->length); + if (ret) + btrfs_abort_transaction(trans, ret); + + return 0; }
int add_block_group_free_space(struct btrfs_trans_handle *trans, @@ -1461,9 +1466,6 @@ int add_block_group_free_space(struct bt }
ret = __add_block_group_free_space(trans, block_group, path); - if (ret) - btrfs_abort_transaction(trans, ret); - out: btrfs_free_path(path); mutex_unlock(&block_group->free_space_lock);
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Filipe Manana fdmanana@suse.com
[ Upstream commit 33e8f24b52d2796b8cfb28c19a1a7dd6476323a8 ]
If we find an unexpected generation for the extent buffer we are cloning at btrfs_copy_root(), we just WARN_ON() and don't error out and abort the transaction, meaning we allow to persist metadata with an unexpected generation. Instead of warning only, abort the transaction and return -EUCLEAN.
CC: stable@vger.kernel.org # 6.1+ Reviewed-by: Daniel Vacek neelx@suse.com Reviewed-by: Qu Wenruo wqu@suse.com Signed-off-by: Filipe Manana fdmanana@suse.com Reviewed-by: David Sterba dsterba@suse.com Signed-off-by: David Sterba dsterba@suse.com Signed-off-by: Sasha Levin sashal@kernel.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- fs/btrfs/ctree.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-)
--- a/fs/btrfs/ctree.c +++ b/fs/btrfs/ctree.c @@ -283,7 +283,14 @@ int btrfs_copy_root(struct btrfs_trans_h
write_extent_buffer_fsid(cow, fs_info->fs_devices->metadata_uuid);
- WARN_ON(btrfs_header_generation(buf) > trans->transid); + if (unlikely(btrfs_header_generation(buf) > trans->transid)) { + btrfs_tree_unlock(cow); + free_extent_buffer(cow); + ret = -EUCLEAN; + btrfs_abort_transaction(trans, ret); + return ret; + } + if (new_root_objectid == BTRFS_TREE_RELOC_OBJECTID) ret = btrfs_inc_ref(trans, root, cow, 1); else
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Filipe Manana fdmanana@suse.com
[ Upstream commit 71c086b30d4373a01bd5627f54516a72891a026a ]
It's hard to read the logic to break out of the while loop since it's a very long expression consisting of a logical or of two composite expressions, each one composed by a logical and. Further each one is also testing for the EXTENT_BUFFER_UNMAPPED bit, making it more verbose than necessary.
So change from this:
if ((!test_bit(EXTENT_BUFFER_UNMAPPED, &eb->bflags) && refs <= 3) || (test_bit(EXTENT_BUFFER_UNMAPPED, &eb->bflags) && refs == 1)) break;
To this:
if (test_bit(EXTENT_BUFFER_UNMAPPED, &eb->bflags)) { if (refs == 1) break; } else if (refs <= 3) { break; }
At least on x86_64 using gcc 9.3.0, this doesn't change the object size.
Reviewed-by: Boris Burkov boris@bur.io Signed-off-by: Filipe Manana fdmanana@suse.com Reviewed-by: David Sterba dsterba@suse.com Signed-off-by: David Sterba dsterba@suse.com Stable-dep-of: ad580dfa388f ("btrfs: fix subpage deadlock in try_release_subpage_extent_buffer()") Signed-off-by: Sasha Levin sashal@kernel.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- fs/btrfs/extent_io.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-)
--- a/fs/btrfs/extent_io.c +++ b/fs/btrfs/extent_io.c @@ -3486,10 +3486,13 @@ void free_extent_buffer(struct extent_bu
refs = atomic_read(&eb->refs); while (1) { - if ((!test_bit(EXTENT_BUFFER_UNMAPPED, &eb->bflags) && refs <= 3) - || (test_bit(EXTENT_BUFFER_UNMAPPED, &eb->bflags) && - refs == 1)) + if (test_bit(EXTENT_BUFFER_UNMAPPED, &eb->bflags)) { + if (refs == 1) + break; + } else if (refs <= 3) { break; + } + if (atomic_try_cmpxchg(&eb->refs, &refs, refs - 1)) return; }
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Filipe Manana fdmanana@suse.com
[ Upstream commit 2697b6159744e5afae0f7715da9f830ba6f9e45a ]
There's this special atomic compare and exchange logic which serves to avoid locking the extent buffers refs_lock spinlock and therefore reduce lock contention, so add a comment to make it more obvious.
Reviewed-by: Boris Burkov boris@bur.io Signed-off-by: Filipe Manana fdmanana@suse.com Reviewed-by: David Sterba dsterba@suse.com Signed-off-by: David Sterba dsterba@suse.com Stable-dep-of: ad580dfa388f ("btrfs: fix subpage deadlock in try_release_subpage_extent_buffer()") Signed-off-by: Sasha Levin sashal@kernel.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- fs/btrfs/extent_io.c | 1 + 1 file changed, 1 insertion(+)
--- a/fs/btrfs/extent_io.c +++ b/fs/btrfs/extent_io.c @@ -3493,6 +3493,7 @@ void free_extent_buffer(struct extent_bu break; }
+ /* Optimization to avoid locking eb->refs_lock. */ if (atomic_try_cmpxchg(&eb->refs, &refs, refs - 1)) return; }
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Filipe Manana fdmanana@suse.com
[ Upstream commit b769777d927af168b1389388392bfd7dc4e38399 ]
Instead of using a bare atomic, use the refcount_t type, which despite being a structure that contains only an atomic, has an API that checks for underflows and other hazards. This doesn't change the size of the extent_buffer structure.
This removes the need to do things like this:
WARN_ON(atomic_read(&eb->refs) == 0); if (atomic_dec_and_test(&eb->refs)) { (...) }
And do just:
if (refcount_dec_and_test(&eb->refs)) { (...) }
Since refcount_dec_and_test() already triggers a warning when we decrement a ref count that has a value of 0 (or below zero).
Reviewed-by: Boris Burkov boris@bur.io Signed-off-by: Filipe Manana fdmanana@suse.com Reviewed-by: David Sterba dsterba@suse.com Signed-off-by: David Sterba dsterba@suse.com Stable-dep-of: ad580dfa388f ("btrfs: fix subpage deadlock in try_release_subpage_extent_buffer()") Signed-off-by: Sasha Levin sashal@kernel.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- fs/btrfs/ctree.c | 14 ++++++------- fs/btrfs/extent-tree.c | 2 - fs/btrfs/extent_io.c | 45 +++++++++++++++++++++---------------------- fs/btrfs/extent_io.h | 2 - fs/btrfs/fiemap.c | 2 - fs/btrfs/print-tree.c | 2 - fs/btrfs/qgroup.c | 6 ++--- fs/btrfs/relocation.c | 4 +-- fs/btrfs/tree-log.c | 4 +-- fs/btrfs/zoned.c | 2 - include/trace/events/btrfs.h | 2 - 11 files changed, 42 insertions(+), 43 deletions(-)
--- a/fs/btrfs/ctree.c +++ b/fs/btrfs/ctree.c @@ -198,7 +198,7 @@ struct extent_buffer *btrfs_root_node(st * the inc_not_zero dance and if it doesn't work then * synchronize_rcu and try again. */ - if (atomic_inc_not_zero(&eb->refs)) { + if (refcount_inc_not_zero(&eb->refs)) { rcu_read_unlock(); break; } @@ -556,7 +556,7 @@ int btrfs_force_cow_block(struct btrfs_t btrfs_abort_transaction(trans, ret); goto error_unlock_cow; } - atomic_inc(&cow->refs); + refcount_inc(&cow->refs); rcu_assign_pointer(root->node, cow);
ret = btrfs_free_tree_block(trans, btrfs_root_id(root), buf, @@ -1088,7 +1088,7 @@ static noinline int balance_level(struct /* update the path */ if (left) { if (btrfs_header_nritems(left) > orig_slot) { - atomic_inc(&left->refs); + refcount_inc(&left->refs); /* left was locked after cow */ path->nodes[level] = left; path->slots[level + 1] -= 1; @@ -1692,7 +1692,7 @@ static struct extent_buffer *btrfs_searc
if (p->search_commit_root) { b = root->commit_root; - atomic_inc(&b->refs); + refcount_inc(&b->refs); level = btrfs_header_level(b); /* * Ensure that all callers have set skip_locking when @@ -2893,7 +2893,7 @@ static noinline int insert_new_root(stru free_extent_buffer(old);
add_root_to_dirty_list(root); - atomic_inc(&c->refs); + refcount_inc(&c->refs); path->nodes[level] = c; path->locks[level] = BTRFS_WRITE_LOCK; path->slots[level] = 0; @@ -4450,7 +4450,7 @@ static noinline int btrfs_del_leaf(struc
root_sub_used_bytes(root);
- atomic_inc(&leaf->refs); + refcount_inc(&leaf->refs); ret = btrfs_free_tree_block(trans, btrfs_root_id(root), leaf, 0, 1); free_extent_buffer_stale(leaf); if (ret < 0) @@ -4535,7 +4535,7 @@ int btrfs_del_items(struct btrfs_trans_h * for possible call to btrfs_del_ptr below */ slot = path->slots[1]; - atomic_inc(&leaf->refs); + refcount_inc(&leaf->refs); /* * We want to be able to at least push one item to the * left neighbour leaf, and that's the first item. --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c @@ -6342,7 +6342,7 @@ int btrfs_drop_subtree(struct btrfs_tran
btrfs_assert_tree_write_locked(parent); parent_level = btrfs_header_level(parent); - atomic_inc(&parent->refs); + refcount_inc(&parent->refs); path->nodes[parent_level] = parent; path->slots[parent_level] = btrfs_header_nritems(parent);
--- a/fs/btrfs/extent_io.c +++ b/fs/btrfs/extent_io.c @@ -77,7 +77,7 @@ void btrfs_extent_buffer_leak_debug_chec struct extent_buffer, leak_list); pr_err( "BTRFS: buffer leak start %llu len %u refs %d bflags %lu owner %llu\n", - eb->start, eb->len, atomic_read(&eb->refs), eb->bflags, + eb->start, eb->len, refcount_read(&eb->refs), eb->bflags, btrfs_header_owner(eb)); list_del(&eb->leak_list); WARN_ON_ONCE(1); @@ -1961,7 +1961,7 @@ retry: if (!eb) return NULL;
- if (!atomic_inc_not_zero(&eb->refs)) { + if (!refcount_inc_not_zero(&eb->refs)) { xas_reset(xas); goto retry; } @@ -2012,7 +2012,7 @@ static struct extent_buffer *find_extent
rcu_read_lock(); eb = xa_load(&fs_info->buffer_tree, index); - if (eb && !atomic_inc_not_zero(&eb->refs)) + if (eb && !refcount_inc_not_zero(&eb->refs)) eb = NULL; rcu_read_unlock(); return eb; @@ -2842,7 +2842,7 @@ static struct extent_buffer *__alloc_ext btrfs_leak_debug_add_eb(eb);
spin_lock_init(&eb->refs_lock); - atomic_set(&eb->refs, 1); + refcount_set(&eb->refs, 1);
ASSERT(eb->len <= BTRFS_MAX_METADATA_BLOCKSIZE);
@@ -2975,13 +2975,13 @@ static void check_buffer_tree_ref(struct * once io is initiated, TREE_REF can no longer be cleared, so that is * the moment at which any such race is best fixed. */ - refs = atomic_read(&eb->refs); + refs = refcount_read(&eb->refs); if (refs >= 2 && test_bit(EXTENT_BUFFER_TREE_REF, &eb->bflags)) return;
spin_lock(&eb->refs_lock); if (!test_and_set_bit(EXTENT_BUFFER_TREE_REF, &eb->bflags)) - atomic_inc(&eb->refs); + refcount_inc(&eb->refs); spin_unlock(&eb->refs_lock); }
@@ -3047,7 +3047,7 @@ again: return ERR_PTR(ret); } if (exists) { - if (!atomic_inc_not_zero(&exists->refs)) { + if (!refcount_inc_not_zero(&exists->refs)) { /* The extent buffer is being freed, retry. */ xa_unlock_irq(&fs_info->buffer_tree); goto again; @@ -3092,7 +3092,7 @@ static struct extent_buffer *grab_extent * just overwrite folio private. */ exists = folio_get_private(folio); - if (atomic_inc_not_zero(&exists->refs)) + if (refcount_inc_not_zero(&exists->refs)) return exists;
WARN_ON(folio_test_dirty(folio)); @@ -3362,7 +3362,7 @@ again: goto out; } if (existing_eb) { - if (!atomic_inc_not_zero(&existing_eb->refs)) { + if (!refcount_inc_not_zero(&existing_eb->refs)) { xa_unlock_irq(&fs_info->buffer_tree); goto again; } @@ -3391,7 +3391,7 @@ again: return eb;
out: - WARN_ON(!atomic_dec_and_test(&eb->refs)); + WARN_ON(!refcount_dec_and_test(&eb->refs));
/* * Any attached folios need to be detached before we unlock them. This @@ -3437,8 +3437,7 @@ static int release_extent_buffer(struct { lockdep_assert_held(&eb->refs_lock);
- WARN_ON(atomic_read(&eb->refs) == 0); - if (atomic_dec_and_test(&eb->refs)) { + if (refcount_dec_and_test(&eb->refs)) { struct btrfs_fs_info *fs_info = eb->fs_info;
spin_unlock(&eb->refs_lock); @@ -3484,7 +3483,7 @@ void free_extent_buffer(struct extent_bu if (!eb) return;
- refs = atomic_read(&eb->refs); + refs = refcount_read(&eb->refs); while (1) { if (test_bit(EXTENT_BUFFER_UNMAPPED, &eb->bflags)) { if (refs == 1) @@ -3494,16 +3493,16 @@ void free_extent_buffer(struct extent_bu }
/* Optimization to avoid locking eb->refs_lock. */ - if (atomic_try_cmpxchg(&eb->refs, &refs, refs - 1)) + if (atomic_try_cmpxchg(&eb->refs.refs, &refs, refs - 1)) return; }
spin_lock(&eb->refs_lock); - if (atomic_read(&eb->refs) == 2 && + if (refcount_read(&eb->refs) == 2 && test_bit(EXTENT_BUFFER_STALE, &eb->bflags) && !extent_buffer_under_io(eb) && test_and_clear_bit(EXTENT_BUFFER_TREE_REF, &eb->bflags)) - atomic_dec(&eb->refs); + refcount_dec(&eb->refs);
/* * I know this is terrible, but it's temporary until we stop tracking @@ -3520,9 +3519,9 @@ void free_extent_buffer_stale(struct ext spin_lock(&eb->refs_lock); set_bit(EXTENT_BUFFER_STALE, &eb->bflags);
- if (atomic_read(&eb->refs) == 2 && !extent_buffer_under_io(eb) && + if (refcount_read(&eb->refs) == 2 && !extent_buffer_under_io(eb) && test_and_clear_bit(EXTENT_BUFFER_TREE_REF, &eb->bflags)) - atomic_dec(&eb->refs); + refcount_dec(&eb->refs); release_extent_buffer(eb); }
@@ -3580,7 +3579,7 @@ void btrfs_clear_buffer_dirty(struct btr btree_clear_folio_dirty_tag(folio); folio_unlock(folio); } - WARN_ON(atomic_read(&eb->refs) == 0); + WARN_ON(refcount_read(&eb->refs) == 0); }
void set_extent_buffer_dirty(struct extent_buffer *eb) @@ -3591,7 +3590,7 @@ void set_extent_buffer_dirty(struct exte
was_dirty = test_and_set_bit(EXTENT_BUFFER_DIRTY, &eb->bflags);
- WARN_ON(atomic_read(&eb->refs) == 0); + WARN_ON(refcount_read(&eb->refs) == 0); WARN_ON(!test_bit(EXTENT_BUFFER_TREE_REF, &eb->bflags)); WARN_ON(test_bit(EXTENT_BUFFER_ZONED_ZEROOUT, &eb->bflags));
@@ -3717,7 +3716,7 @@ int read_extent_buffer_pages_nowait(stru
eb->read_mirror = 0; check_buffer_tree_ref(eb); - atomic_inc(&eb->refs); + refcount_inc(&eb->refs);
bbio = btrfs_bio_alloc(INLINE_EXTENT_BUFFER_PAGES, REQ_OP_READ | REQ_META, eb->fs_info, @@ -4312,7 +4311,7 @@ static int try_release_subpage_extent_bu * won't disappear out from under us. */ spin_lock(&eb->refs_lock); - if (atomic_read(&eb->refs) != 1 || extent_buffer_under_io(eb)) { + if (refcount_read(&eb->refs) != 1 || extent_buffer_under_io(eb)) { spin_unlock(&eb->refs_lock); continue; } @@ -4378,7 +4377,7 @@ int try_release_extent_buffer(struct fol * this page. */ spin_lock(&eb->refs_lock); - if (atomic_read(&eb->refs) != 1 || extent_buffer_under_io(eb)) { + if (refcount_read(&eb->refs) != 1 || extent_buffer_under_io(eb)) { spin_unlock(&eb->refs_lock); spin_unlock(&folio->mapping->i_private_lock); return 0; --- a/fs/btrfs/extent_io.h +++ b/fs/btrfs/extent_io.h @@ -98,7 +98,7 @@ struct extent_buffer { void *addr;
spinlock_t refs_lock; - atomic_t refs; + refcount_t refs; int read_mirror; /* >= 0 if eb belongs to a log tree, -1 otherwise */ s8 log_index; --- a/fs/btrfs/fiemap.c +++ b/fs/btrfs/fiemap.c @@ -320,7 +320,7 @@ static int fiemap_next_leaf_item(struct * the cost of allocating a new one. */ ASSERT(test_bit(EXTENT_BUFFER_UNMAPPED, &clone->bflags)); - atomic_inc(&clone->refs); + refcount_inc(&clone->refs);
ret = btrfs_next_leaf(inode->root, path); if (ret != 0) --- a/fs/btrfs/print-tree.c +++ b/fs/btrfs/print-tree.c @@ -223,7 +223,7 @@ static void print_eb_refs_lock(const str { #ifdef CONFIG_BTRFS_DEBUG btrfs_info(eb->fs_info, "refs %u lock_owner %u current %u", - atomic_read(&eb->refs), eb->lock_owner, current->pid); + refcount_read(&eb->refs), eb->lock_owner, current->pid); #endif }
--- a/fs/btrfs/qgroup.c +++ b/fs/btrfs/qgroup.c @@ -2348,7 +2348,7 @@ static int qgroup_trace_extent_swap(stru btrfs_item_key_to_cpu(dst_path->nodes[dst_level], &key, 0);
/* For src_path */ - atomic_inc(&src_eb->refs); + refcount_inc(&src_eb->refs); src_path->nodes[root_level] = src_eb; src_path->slots[root_level] = dst_path->slots[root_level]; src_path->locks[root_level] = 0; @@ -2581,7 +2581,7 @@ static int qgroup_trace_subtree_swap(str goto out; } /* For dst_path */ - atomic_inc(&dst_eb->refs); + refcount_inc(&dst_eb->refs); dst_path->nodes[level] = dst_eb; dst_path->slots[level] = 0; dst_path->locks[level] = 0; @@ -2673,7 +2673,7 @@ int btrfs_qgroup_trace_subtree(struct bt * walk back up the tree (adjusting slot pointers as we go) * and restart the search process. */ - atomic_inc(&root_eb->refs); /* For path */ + refcount_inc(&root_eb->refs); /* For path */ path->nodes[root_level] = root_eb; path->slots[root_level] = 0; path->locks[root_level] = 0; /* so release_path doesn't try to unlock */ --- a/fs/btrfs/relocation.c +++ b/fs/btrfs/relocation.c @@ -1535,7 +1535,7 @@ static noinline_for_stack int merge_relo
if (btrfs_disk_key_objectid(&root_item->drop_progress) == 0) { level = btrfs_root_level(root_item); - atomic_inc(&reloc_root->node->refs); + refcount_inc(&reloc_root->node->refs); path->nodes[level] = reloc_root->node; path->slots[level] = 0; } else { @@ -4358,7 +4358,7 @@ int btrfs_reloc_cow_block(struct btrfs_t }
btrfs_backref_drop_node_buffer(node); - atomic_inc(&cow->refs); + refcount_inc(&cow->refs); node->eb = cow; node->new_bytenr = cow->start;
--- a/fs/btrfs/tree-log.c +++ b/fs/btrfs/tree-log.c @@ -2747,7 +2747,7 @@ static int walk_log_tree(struct btrfs_tr level = btrfs_header_level(log->node); orig_level = level; path->nodes[level] = log->node; - atomic_inc(&log->node->refs); + refcount_inc(&log->node->refs); path->slots[level] = 0;
while (1) { @@ -3711,7 +3711,7 @@ static int clone_leaf(struct btrfs_path * Add extra ref to scratch eb so that it is not freed when callers * release the path, so we can reuse it later if needed. */ - atomic_inc(&ctx->scratch_eb->refs); + refcount_inc(&ctx->scratch_eb->refs);
return 0; } --- a/fs/btrfs/zoned.c +++ b/fs/btrfs/zoned.c @@ -2491,7 +2491,7 @@ void btrfs_schedule_zone_finish_bg(struc
/* For the work */ btrfs_get_block_group(bg); - atomic_inc(&eb->refs); + refcount_inc(&eb->refs); bg->last_eb = eb; INIT_WORK(&bg->zone_finish_work, btrfs_zone_finish_endio_workfn); queue_work(system_unbound_wq, &bg->zone_finish_work); --- a/include/trace/events/btrfs.h +++ b/include/trace/events/btrfs.h @@ -1095,7 +1095,7 @@ TRACE_EVENT(btrfs_cow_block, TP_fast_assign_btrfs(root->fs_info, __entry->root_objectid = btrfs_root_id(root); __entry->buf_start = buf->start; - __entry->refs = atomic_read(&buf->refs); + __entry->refs = refcount_read(&buf->refs); __entry->cow_start = cow->start; __entry->buf_level = btrfs_header_level(buf); __entry->cow_level = btrfs_header_level(cow);
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Leo Martins loemra.dev@gmail.com
[ Upstream commit ad580dfa388fabb52af033e3f8cc5d04be985e54 ]
There is a potential deadlock that can happen in try_release_subpage_extent_buffer() because the irq-safe xarray spin lock fs_info->buffer_tree is being acquired before the irq-unsafe eb->refs_lock.
This leads to the potential race: // T1 (random eb->refs user) // T2 (release folio)
spin_lock(&eb->refs_lock); // interrupt end_bbio_meta_write() btrfs_meta_folio_clear_writeback() btree_release_folio() folio_test_writeback() //false try_release_extent_buffer() try_release_subpage_extent_buffer() xa_lock_irq(&fs_info->buffer_tree) spin_lock(&eb->refs_lock); // blocked; held by T1 buffer_tree_clear_mark() xas_lock_irqsave() // blocked; held by T2
I believe that the spin lock can safely be replaced by an rcu_read_lock. The xa_for_each loop does not need the spin lock as it's already internally protected by the rcu_read_lock. The extent buffer is also protected by the rcu_read_lock so it won't be freed before we take the eb->refs_lock and check the ref count.
The rcu_read_lock is taken and released every iteration, just like the spin lock, which means we're not protected against concurrent insertions into the xarray. This is fine because we rely on folio->private to detect if there are any ebs remaining in the folio.
There is already some precedent for this with find_extent_buffer_nolock, which loads an extent buffer from the xarray with only rcu_read_lock.
lockdep warning:
===================================================== WARNING: HARDIRQ-safe -> HARDIRQ-unsafe lock order detected 6.16.0-0_fbk701_debug_rc0_123_g4c06e63b9203 #1 Tainted: G E N ----------------------------------------------------- kswapd0/66 [HC0[0]:SC0[0]:HE0:SE1] is trying to acquire: ffff000011ffd600 (&eb->refs_lock){+.+.}-{3:3}, at: try_release_extent_buffer+0x18c/0x560
and this task is already holding: ffff0000c1d91b88 (&buffer_xa_class){-.-.}-{3:3}, at: try_release_extent_buffer+0x13c/0x560 which would create a new lock dependency: (&buffer_xa_class){-.-.}-{3:3} -> (&eb->refs_lock){+.+.}-{3:3}
but this new dependency connects a HARDIRQ-irq-safe lock: (&buffer_xa_class){-.-.}-{3:3}
... which became HARDIRQ-irq-safe at: lock_acquire+0x178/0x358 _raw_spin_lock_irqsave+0x60/0x88 buffer_tree_clear_mark+0xc4/0x160 end_bbio_meta_write+0x238/0x398 btrfs_bio_end_io+0x1f8/0x330 btrfs_orig_write_end_io+0x1c4/0x2c0 bio_endio+0x63c/0x678 blk_update_request+0x1c4/0xa00 blk_mq_end_request+0x54/0x88 virtblk_request_done+0x124/0x1d0 blk_mq_complete_request+0x84/0xa0 virtblk_done+0x130/0x238 vring_interrupt+0x130/0x288 __handle_irq_event_percpu+0x1e8/0x708 handle_irq_event+0x98/0x1b0 handle_fasteoi_irq+0x264/0x7c0 generic_handle_domain_irq+0xa4/0x108 gic_handle_irq+0x7c/0x1a0 do_interrupt_handler+0xe4/0x148 el1_interrupt+0x30/0x50 el1h_64_irq_handler+0x14/0x20 el1h_64_irq+0x6c/0x70 _raw_spin_unlock_irq+0x38/0x70 __run_timer_base+0xdc/0x5e0 run_timer_softirq+0xa0/0x138 handle_softirqs.llvm.13542289750107964195+0x32c/0xbd0 ____do_softirq.llvm.17674514681856217165+0x18/0x28 call_on_irq_stack+0x24/0x30 __irq_exit_rcu+0x164/0x430 irq_exit_rcu+0x18/0x88 el1_interrupt+0x34/0x50 el1h_64_irq_handler+0x14/0x20 el1h_64_irq+0x6c/0x70 arch_local_irq_enable+0x4/0x8 do_idle+0x1a0/0x3b8 cpu_startup_entry+0x60/0x80 rest_init+0x204/0x228 start_kernel+0x394/0x3f0 __primary_switched+0x8c/0x8958
to a HARDIRQ-irq-unsafe lock: (&eb->refs_lock){+.+.}-{3:3}
... which became HARDIRQ-irq-unsafe at: ... lock_acquire+0x178/0x358 _raw_spin_lock+0x4c/0x68 free_extent_buffer_stale+0x2c/0x170 btrfs_read_sys_array+0x1b0/0x338 open_ctree+0xeb0/0x1df8 btrfs_get_tree+0xb60/0x1110 vfs_get_tree+0x8c/0x250 fc_mount+0x20/0x98 btrfs_get_tree+0x4a4/0x1110 vfs_get_tree+0x8c/0x250 do_new_mount+0x1e0/0x6c0 path_mount+0x4ec/0xa58 __arm64_sys_mount+0x370/0x490 invoke_syscall+0x6c/0x208 el0_svc_common+0x14c/0x1b8 do_el0_svc+0x4c/0x60 el0_svc+0x4c/0x160 el0t_64_sync_handler+0x70/0x100 el0t_64_sync+0x168/0x170
other info that might help us debug this: Possible interrupt unsafe locking scenario: CPU0 CPU1 ---- ---- lock(&eb->refs_lock); local_irq_disable(); lock(&buffer_xa_class); lock(&eb->refs_lock); <Interrupt> lock(&buffer_xa_class);
*** DEADLOCK *** 2 locks held by kswapd0/66: #0: ffff800085506e40 (fs_reclaim){+.+.}-{0:0}, at: balance_pgdat+0xe8/0xe50 #1: ffff0000c1d91b88 (&buffer_xa_class){-.-.}-{3:3}, at: try_release_extent_buffer+0x13c/0x560
Link: https://www.kernel.org/doc/Documentation/locking/lockdep-design.rst#:~:text=... Fixes: 19d7f65f032f ("btrfs: convert the buffer_radix to an xarray") CC: stable@vger.kernel.org # 6.16+ Reviewed-by: Boris Burkov boris@bur.io Reviewed-by: Qu Wenruo wqu@suse.com Signed-off-by: Leo Martins loemra.dev@gmail.com Signed-off-by: David Sterba dsterba@suse.com Signed-off-by: Sasha Levin sashal@kernel.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- fs/btrfs/extent_io.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-)
--- a/fs/btrfs/extent_io.c +++ b/fs/btrfs/extent_io.c @@ -4304,15 +4304,18 @@ static int try_release_subpage_extent_bu unsigned long end = index + (PAGE_SIZE >> fs_info->sectorsize_bits) - 1; int ret;
- xa_lock_irq(&fs_info->buffer_tree); + rcu_read_lock(); xa_for_each_range(&fs_info->buffer_tree, index, eb, start, end) { /* * The same as try_release_extent_buffer(), to ensure the eb * won't disappear out from under us. */ spin_lock(&eb->refs_lock); + rcu_read_unlock(); + if (refcount_read(&eb->refs) != 1 || extent_buffer_under_io(eb)) { spin_unlock(&eb->refs_lock); + rcu_read_lock(); continue; }
@@ -4331,11 +4334,10 @@ static int try_release_subpage_extent_bu * check the folio private at the end. And * release_extent_buffer() will release the refs_lock. */ - xa_unlock_irq(&fs_info->buffer_tree); release_extent_buffer(eb); - xa_lock_irq(&fs_info->buffer_tree); + rcu_read_lock(); } - xa_unlock_irq(&fs_info->buffer_tree); + rcu_read_unlock();
/* * Finally to check if we have cleared folio private, as if we have @@ -4348,7 +4350,6 @@ static int try_release_subpage_extent_bu ret = 0; spin_unlock(&folio->mapping->i_private_lock); return ret; - }
int try_release_extent_buffer(struct folio *folio)
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Qu Wenruo wqu@suse.com
[ Upstream commit 1e17738d6b76cdc76d240d64de87fa66ba2365f7 ]
Unlike the iomap_folio_state structure, the btrfs_subpage structure has a lot of extra sub-bitmaps, namely:
- writeback sub-bitmap - locked sub-bitmap iomap_folio_state uses an atomic for writeback tracking, while it has no per-block locked tracking.
This is because iomap always locks a single folio, and submits dirty blocks with that folio locked.
But btrfs has async delalloc ranges (for compression), which are queued with their range locked, until the compression is done, then marks the involved range writeback and unlocked.
This means a range can be unlocked and marked writeback at seemingly random timing, thus it needs the extra tracking.
This needs a huge rework on the lifespan of async delalloc range before we can remove/simplify these two sub-bitmaps.
- ordered sub-bitmap - checked sub-bitmap These are for COW-fixup, but as I mentioned in the past, the COW-fixup is not really needed anymore and these two flags are already marked deprecated, and will be removed in the near future after comprehensive tests.
Add related comments to indicate we're actively trying to align the sub-bitmaps to the iomap ones.
Signed-off-by: Qu Wenruo wqu@suse.com Reviewed-by: David Sterba dsterba@suse.com Signed-off-by: David Sterba dsterba@suse.com Stable-dep-of: b1511360c8ac ("btrfs: subpage: keep TOWRITE tag until folio is cleaned") Signed-off-by: Sasha Levin sashal@kernel.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- fs/btrfs/subpage.h | 14 ++++++++++++++ 1 file changed, 14 insertions(+)
--- a/fs/btrfs/subpage.h +++ b/fs/btrfs/subpage.h @@ -33,8 +33,22 @@ enum { btrfs_bitmap_nr_uptodate = 0, btrfs_bitmap_nr_dirty, btrfs_bitmap_nr_writeback, + /* + * The ordered and checked flags are for COW fixup, already marked + * deprecated, and will be removed eventually. + */ btrfs_bitmap_nr_ordered, btrfs_bitmap_nr_checked, + + /* + * The locked bit is for async delalloc range (compression), currently + * async extent is queued with the range locked, until the compression + * is done. + * So an async extent can unlock the range at any random timing. + * + * This will need a rework on the async extent lifespan (mark writeback + * and do compression) before deprecating this flag. + */ btrfs_bitmap_nr_locked, btrfs_bitmap_nr_max };
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Qu Wenruo wqu@suse.com
[ Upstream commit 582cd4bad4332cca95c578e99442eb148366eb82 ]
With the incoming large data folios support, the structure name btrfs_subpage is no longer correct, as for we can have multiple blocks inside a large folio, and the block size is still page size.
So to follow the schema of iomap, rename btrfs_subpage to btrfs_folio_state, along with involved enums.
There are still exported functions with "btrfs_subpage_" prefix, and I believe for metadata the name "subpage" will stay forever as we will never allocate a folio larger than nodesize anyway.
The full cleanup of the word "subpage" will happen in much smaller steps in the future.
Signed-off-by: Qu Wenruo wqu@suse.com Reviewed-by: David Sterba dsterba@suse.com Signed-off-by: David Sterba dsterba@suse.com Stable-dep-of: b1511360c8ac ("btrfs: subpage: keep TOWRITE tag until folio is cleaned") Signed-off-by: Sasha Levin sashal@kernel.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- fs/btrfs/extent_io.c | 28 ++--- fs/btrfs/inode.c | 8 - fs/btrfs/subpage.c | 239 ++++++++++++++++++++++++--------------------------- fs/btrfs/subpage.h | 31 ++++-- 4 files changed, 156 insertions(+), 150 deletions(-)
--- a/fs/btrfs/extent_io.c +++ b/fs/btrfs/extent_io.c @@ -782,7 +782,7 @@ static void submit_extent_folio(struct b
static int attach_extent_buffer_folio(struct extent_buffer *eb, struct folio *folio, - struct btrfs_subpage *prealloc) + struct btrfs_folio_state *prealloc) { struct btrfs_fs_info *fs_info = eb->fs_info; int ret = 0; @@ -806,7 +806,7 @@ static int attach_extent_buffer_folio(st
/* Already mapped, just free prealloc */ if (folio_test_private(folio)) { - btrfs_free_subpage(prealloc); + btrfs_free_folio_state(prealloc); return 0; }
@@ -815,7 +815,7 @@ static int attach_extent_buffer_folio(st folio_attach_private(folio, prealloc); else /* Do new allocation to attach subpage */ - ret = btrfs_attach_subpage(fs_info, folio, BTRFS_SUBPAGE_METADATA); + ret = btrfs_attach_folio_state(fs_info, folio, BTRFS_SUBPAGE_METADATA); return ret; }
@@ -831,7 +831,7 @@ int set_folio_extent_mapped(struct folio fs_info = folio_to_fs_info(folio);
if (btrfs_is_subpage(fs_info, folio)) - return btrfs_attach_subpage(fs_info, folio, BTRFS_SUBPAGE_DATA); + return btrfs_attach_folio_state(fs_info, folio, BTRFS_SUBPAGE_DATA);
folio_attach_private(folio, (void *)EXTENT_FOLIO_PRIVATE); return 0; @@ -848,7 +848,7 @@ void clear_folio_extent_mapped(struct fo
fs_info = folio_to_fs_info(folio); if (btrfs_is_subpage(fs_info, folio)) - return btrfs_detach_subpage(fs_info, folio, BTRFS_SUBPAGE_DATA); + return btrfs_detach_folio_state(fs_info, folio, BTRFS_SUBPAGE_DATA);
folio_detach_private(folio); } @@ -2731,13 +2731,13 @@ static int extent_buffer_under_io(const
static bool folio_range_has_eb(struct folio *folio) { - struct btrfs_subpage *subpage; + struct btrfs_folio_state *bfs;
lockdep_assert_held(&folio->mapping->i_private_lock);
if (folio_test_private(folio)) { - subpage = folio_get_private(folio); - if (atomic_read(&subpage->eb_refs)) + bfs = folio_get_private(folio); + if (atomic_read(&bfs->eb_refs)) return true; } return false; @@ -2787,7 +2787,7 @@ static void detach_extent_buffer_folio(c * attached to one dummy eb, no sharing. */ if (!mapped) { - btrfs_detach_subpage(fs_info, folio, BTRFS_SUBPAGE_METADATA); + btrfs_detach_folio_state(fs_info, folio, BTRFS_SUBPAGE_METADATA); return; }
@@ -2798,7 +2798,7 @@ static void detach_extent_buffer_folio(c * page range and no unfinished IO. */ if (!folio_range_has_eb(folio)) - btrfs_detach_subpage(fs_info, folio, BTRFS_SUBPAGE_METADATA); + btrfs_detach_folio_state(fs_info, folio, BTRFS_SUBPAGE_METADATA);
spin_unlock(&mapping->i_private_lock); } @@ -3141,7 +3141,7 @@ static bool check_eb_alignment(struct bt * The caller needs to free the existing folios and retry using the same order. */ static int attach_eb_folio_to_filemap(struct extent_buffer *eb, int i, - struct btrfs_subpage *prealloc, + struct btrfs_folio_state *prealloc, struct extent_buffer **found_eb_ret) {
@@ -3224,7 +3224,7 @@ struct extent_buffer *alloc_extent_buffe int attached = 0; struct extent_buffer *eb; struct extent_buffer *existing_eb = NULL; - struct btrfs_subpage *prealloc = NULL; + struct btrfs_folio_state *prealloc = NULL; u64 lockdep_owner = owner_root; bool page_contig = true; int uptodate = 1; @@ -3269,7 +3269,7 @@ struct extent_buffer *alloc_extent_buffe * manually if we exit earlier. */ if (btrfs_meta_is_subpage(fs_info)) { - prealloc = btrfs_alloc_subpage(fs_info, PAGE_SIZE, BTRFS_SUBPAGE_METADATA); + prealloc = btrfs_alloc_folio_state(fs_info, PAGE_SIZE, BTRFS_SUBPAGE_METADATA); if (IS_ERR(prealloc)) { ret = PTR_ERR(prealloc); goto out; @@ -3280,7 +3280,7 @@ reallocate: /* Allocate all pages first. */ ret = alloc_eb_folio_array(eb, true); if (ret < 0) { - btrfs_free_subpage(prealloc); + btrfs_free_folio_state(prealloc); goto out; }
--- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c @@ -7364,13 +7364,13 @@ struct extent_map *btrfs_create_io_em(st static void wait_subpage_spinlock(struct folio *folio) { struct btrfs_fs_info *fs_info = folio_to_fs_info(folio); - struct btrfs_subpage *subpage; + struct btrfs_folio_state *bfs;
if (!btrfs_is_subpage(fs_info, folio)) return;
ASSERT(folio_test_private(folio) && folio_get_private(folio)); - subpage = folio_get_private(folio); + bfs = folio_get_private(folio);
/* * This may look insane as we just acquire the spinlock and release it, @@ -7383,8 +7383,8 @@ static void wait_subpage_spinlock(struct * Here we just acquire the spinlock so that all existing callers * should exit and we're safe to release/invalidate the page. */ - spin_lock_irq(&subpage->lock); - spin_unlock_irq(&subpage->lock); + spin_lock_irq(&bfs->lock); + spin_unlock_irq(&bfs->lock); }
static int btrfs_launder_folio(struct folio *folio) --- a/fs/btrfs/subpage.c +++ b/fs/btrfs/subpage.c @@ -49,7 +49,7 @@ * Implementation: * * - Common - * Both metadata and data will use a new structure, btrfs_subpage, to + * Both metadata and data will use a new structure, btrfs_folio_state, to * record the status of each sector inside a page. This provides the extra * granularity needed. * @@ -63,10 +63,10 @@ * This means a slightly higher tree locking latency. */
-int btrfs_attach_subpage(const struct btrfs_fs_info *fs_info, - struct folio *folio, enum btrfs_subpage_type type) +int btrfs_attach_folio_state(const struct btrfs_fs_info *fs_info, + struct folio *folio, enum btrfs_folio_type type) { - struct btrfs_subpage *subpage; + struct btrfs_folio_state *bfs;
/* For metadata we don't support large folio yet. */ if (type == BTRFS_SUBPAGE_METADATA) @@ -87,18 +87,18 @@ int btrfs_attach_subpage(const struct bt if (type == BTRFS_SUBPAGE_DATA && !btrfs_is_subpage(fs_info, folio)) return 0;
- subpage = btrfs_alloc_subpage(fs_info, folio_size(folio), type); - if (IS_ERR(subpage)) - return PTR_ERR(subpage); + bfs = btrfs_alloc_folio_state(fs_info, folio_size(folio), type); + if (IS_ERR(bfs)) + return PTR_ERR(bfs);
- folio_attach_private(folio, subpage); + folio_attach_private(folio, bfs); return 0; }
-void btrfs_detach_subpage(const struct btrfs_fs_info *fs_info, struct folio *folio, - enum btrfs_subpage_type type) +void btrfs_detach_folio_state(const struct btrfs_fs_info *fs_info, struct folio *folio, + enum btrfs_folio_type type) { - struct btrfs_subpage *subpage; + struct btrfs_folio_state *bfs;
/* Either not subpage, or the folio already has private attached. */ if (!folio_test_private(folio)) @@ -108,15 +108,15 @@ void btrfs_detach_subpage(const struct b if (type == BTRFS_SUBPAGE_DATA && !btrfs_is_subpage(fs_info, folio)) return;
- subpage = folio_detach_private(folio); - ASSERT(subpage); - btrfs_free_subpage(subpage); + bfs = folio_detach_private(folio); + ASSERT(bfs); + btrfs_free_folio_state(bfs); }
-struct btrfs_subpage *btrfs_alloc_subpage(const struct btrfs_fs_info *fs_info, - size_t fsize, enum btrfs_subpage_type type) +struct btrfs_folio_state *btrfs_alloc_folio_state(const struct btrfs_fs_info *fs_info, + size_t fsize, enum btrfs_folio_type type) { - struct btrfs_subpage *ret; + struct btrfs_folio_state *ret; unsigned int real_size;
ASSERT(fs_info->sectorsize < fsize); @@ -136,11 +136,6 @@ struct btrfs_subpage *btrfs_alloc_subpag return ret; }
-void btrfs_free_subpage(struct btrfs_subpage *subpage) -{ - kfree(subpage); -} - /* * Increase the eb_refs of current subpage. * @@ -152,7 +147,7 @@ void btrfs_free_subpage(struct btrfs_sub */ void btrfs_folio_inc_eb_refs(const struct btrfs_fs_info *fs_info, struct folio *folio) { - struct btrfs_subpage *subpage; + struct btrfs_folio_state *bfs;
if (!btrfs_meta_is_subpage(fs_info)) return; @@ -160,13 +155,13 @@ void btrfs_folio_inc_eb_refs(const struc ASSERT(folio_test_private(folio) && folio->mapping); lockdep_assert_held(&folio->mapping->i_private_lock);
- subpage = folio_get_private(folio); - atomic_inc(&subpage->eb_refs); + bfs = folio_get_private(folio); + atomic_inc(&bfs->eb_refs); }
void btrfs_folio_dec_eb_refs(const struct btrfs_fs_info *fs_info, struct folio *folio) { - struct btrfs_subpage *subpage; + struct btrfs_folio_state *bfs;
if (!btrfs_meta_is_subpage(fs_info)) return; @@ -174,9 +169,9 @@ void btrfs_folio_dec_eb_refs(const struc ASSERT(folio_test_private(folio) && folio->mapping); lockdep_assert_held(&folio->mapping->i_private_lock);
- subpage = folio_get_private(folio); - ASSERT(atomic_read(&subpage->eb_refs)); - atomic_dec(&subpage->eb_refs); + bfs = folio_get_private(folio); + ASSERT(atomic_read(&bfs->eb_refs)); + atomic_dec(&bfs->eb_refs); }
static void btrfs_subpage_assert(const struct btrfs_fs_info *fs_info, @@ -228,7 +223,7 @@ static void btrfs_subpage_clamp_range(st static bool btrfs_subpage_end_and_test_lock(const struct btrfs_fs_info *fs_info, struct folio *folio, u64 start, u32 len) { - struct btrfs_subpage *subpage = folio_get_private(folio); + struct btrfs_folio_state *bfs = folio_get_private(folio); const int start_bit = subpage_calc_start_bit(fs_info, folio, locked, start, len); const int nbits = (len >> fs_info->sectorsize_bits); unsigned long flags; @@ -238,7 +233,7 @@ static bool btrfs_subpage_end_and_test_l
btrfs_subpage_assert(fs_info, folio, start, len);
- spin_lock_irqsave(&subpage->lock, flags); + spin_lock_irqsave(&bfs->lock, flags); /* * We have call sites passing @lock_page into * extent_clear_unlock_delalloc() for compression path. @@ -246,18 +241,18 @@ static bool btrfs_subpage_end_and_test_l * This @locked_page is locked by plain lock_page(), thus its * subpage::locked is 0. Handle them in a special way. */ - if (atomic_read(&subpage->nr_locked) == 0) { - spin_unlock_irqrestore(&subpage->lock, flags); + if (atomic_read(&bfs->nr_locked) == 0) { + spin_unlock_irqrestore(&bfs->lock, flags); return true; }
- for_each_set_bit_from(bit, subpage->bitmaps, start_bit + nbits) { - clear_bit(bit, subpage->bitmaps); + for_each_set_bit_from(bit, bfs->bitmaps, start_bit + nbits) { + clear_bit(bit, bfs->bitmaps); cleared++; } - ASSERT(atomic_read(&subpage->nr_locked) >= cleared); - last = atomic_sub_and_test(cleared, &subpage->nr_locked); - spin_unlock_irqrestore(&subpage->lock, flags); + ASSERT(atomic_read(&bfs->nr_locked) >= cleared); + last = atomic_sub_and_test(cleared, &bfs->nr_locked); + spin_unlock_irqrestore(&bfs->lock, flags); return last; }
@@ -280,7 +275,7 @@ static bool btrfs_subpage_end_and_test_l void btrfs_folio_end_lock(const struct btrfs_fs_info *fs_info, struct folio *folio, u64 start, u32 len) { - struct btrfs_subpage *subpage = folio_get_private(folio); + struct btrfs_folio_state *bfs = folio_get_private(folio);
ASSERT(folio_test_locked(folio));
@@ -296,7 +291,7 @@ void btrfs_folio_end_lock(const struct b * Since we own the page lock, no one else could touch subpage::locked * and we are safe to do several atomic operations without spinlock. */ - if (atomic_read(&subpage->nr_locked) == 0) { + if (atomic_read(&bfs->nr_locked) == 0) { /* No subpage lock, locked by plain lock_page(). */ folio_unlock(folio); return; @@ -310,7 +305,7 @@ void btrfs_folio_end_lock(const struct b void btrfs_folio_end_lock_bitmap(const struct btrfs_fs_info *fs_info, struct folio *folio, unsigned long bitmap) { - struct btrfs_subpage *subpage = folio_get_private(folio); + struct btrfs_folio_state *bfs = folio_get_private(folio); const unsigned int blocks_per_folio = btrfs_blocks_per_folio(fs_info, folio); const int start_bit = blocks_per_folio * btrfs_bitmap_nr_locked; unsigned long flags; @@ -323,42 +318,42 @@ void btrfs_folio_end_lock_bitmap(const s return; }
- if (atomic_read(&subpage->nr_locked) == 0) { + if (atomic_read(&bfs->nr_locked) == 0) { /* No subpage lock, locked by plain lock_page(). */ folio_unlock(folio); return; }
- spin_lock_irqsave(&subpage->lock, flags); + spin_lock_irqsave(&bfs->lock, flags); for_each_set_bit(bit, &bitmap, blocks_per_folio) { - if (test_and_clear_bit(bit + start_bit, subpage->bitmaps)) + if (test_and_clear_bit(bit + start_bit, bfs->bitmaps)) cleared++; } - ASSERT(atomic_read(&subpage->nr_locked) >= cleared); - last = atomic_sub_and_test(cleared, &subpage->nr_locked); - spin_unlock_irqrestore(&subpage->lock, flags); + ASSERT(atomic_read(&bfs->nr_locked) >= cleared); + last = atomic_sub_and_test(cleared, &bfs->nr_locked); + spin_unlock_irqrestore(&bfs->lock, flags); if (last) folio_unlock(folio); }
#define subpage_test_bitmap_all_set(fs_info, folio, name) \ ({ \ - struct btrfs_subpage *subpage = folio_get_private(folio); \ + struct btrfs_folio_state *bfs = folio_get_private(folio); \ const unsigned int blocks_per_folio = \ btrfs_blocks_per_folio(fs_info, folio); \ \ - bitmap_test_range_all_set(subpage->bitmaps, \ + bitmap_test_range_all_set(bfs->bitmaps, \ blocks_per_folio * btrfs_bitmap_nr_##name, \ blocks_per_folio); \ })
#define subpage_test_bitmap_all_zero(fs_info, folio, name) \ ({ \ - struct btrfs_subpage *subpage = folio_get_private(folio); \ + struct btrfs_folio_state *bfs = folio_get_private(folio); \ const unsigned int blocks_per_folio = \ btrfs_blocks_per_folio(fs_info, folio); \ \ - bitmap_test_range_all_zero(subpage->bitmaps, \ + bitmap_test_range_all_zero(bfs->bitmaps, \ blocks_per_folio * btrfs_bitmap_nr_##name, \ blocks_per_folio); \ }) @@ -366,43 +361,43 @@ void btrfs_folio_end_lock_bitmap(const s void btrfs_subpage_set_uptodate(const struct btrfs_fs_info *fs_info, struct folio *folio, u64 start, u32 len) { - struct btrfs_subpage *subpage = folio_get_private(folio); + struct btrfs_folio_state *bfs = folio_get_private(folio); unsigned int start_bit = subpage_calc_start_bit(fs_info, folio, uptodate, start, len); unsigned long flags;
- spin_lock_irqsave(&subpage->lock, flags); - bitmap_set(subpage->bitmaps, start_bit, len >> fs_info->sectorsize_bits); + spin_lock_irqsave(&bfs->lock, flags); + bitmap_set(bfs->bitmaps, start_bit, len >> fs_info->sectorsize_bits); if (subpage_test_bitmap_all_set(fs_info, folio, uptodate)) folio_mark_uptodate(folio); - spin_unlock_irqrestore(&subpage->lock, flags); + spin_unlock_irqrestore(&bfs->lock, flags); }
void btrfs_subpage_clear_uptodate(const struct btrfs_fs_info *fs_info, struct folio *folio, u64 start, u32 len) { - struct btrfs_subpage *subpage = folio_get_private(folio); + struct btrfs_folio_state *bfs = folio_get_private(folio); unsigned int start_bit = subpage_calc_start_bit(fs_info, folio, uptodate, start, len); unsigned long flags;
- spin_lock_irqsave(&subpage->lock, flags); - bitmap_clear(subpage->bitmaps, start_bit, len >> fs_info->sectorsize_bits); + spin_lock_irqsave(&bfs->lock, flags); + bitmap_clear(bfs->bitmaps, start_bit, len >> fs_info->sectorsize_bits); folio_clear_uptodate(folio); - spin_unlock_irqrestore(&subpage->lock, flags); + spin_unlock_irqrestore(&bfs->lock, flags); }
void btrfs_subpage_set_dirty(const struct btrfs_fs_info *fs_info, struct folio *folio, u64 start, u32 len) { - struct btrfs_subpage *subpage = folio_get_private(folio); + struct btrfs_folio_state *bfs = folio_get_private(folio); unsigned int start_bit = subpage_calc_start_bit(fs_info, folio, dirty, start, len); unsigned long flags;
- spin_lock_irqsave(&subpage->lock, flags); - bitmap_set(subpage->bitmaps, start_bit, len >> fs_info->sectorsize_bits); - spin_unlock_irqrestore(&subpage->lock, flags); + spin_lock_irqsave(&bfs->lock, flags); + bitmap_set(bfs->bitmaps, start_bit, len >> fs_info->sectorsize_bits); + spin_unlock_irqrestore(&bfs->lock, flags); folio_mark_dirty(folio); }
@@ -419,17 +414,17 @@ void btrfs_subpage_set_dirty(const struc bool btrfs_subpage_clear_and_test_dirty(const struct btrfs_fs_info *fs_info, struct folio *folio, u64 start, u32 len) { - struct btrfs_subpage *subpage = folio_get_private(folio); + struct btrfs_folio_state *bfs = folio_get_private(folio); unsigned int start_bit = subpage_calc_start_bit(fs_info, folio, dirty, start, len); unsigned long flags; bool last = false;
- spin_lock_irqsave(&subpage->lock, flags); - bitmap_clear(subpage->bitmaps, start_bit, len >> fs_info->sectorsize_bits); + spin_lock_irqsave(&bfs->lock, flags); + bitmap_clear(bfs->bitmaps, start_bit, len >> fs_info->sectorsize_bits); if (subpage_test_bitmap_all_zero(fs_info, folio, dirty)) last = true; - spin_unlock_irqrestore(&subpage->lock, flags); + spin_unlock_irqrestore(&bfs->lock, flags); return last; }
@@ -446,91 +441,91 @@ void btrfs_subpage_clear_dirty(const str void btrfs_subpage_set_writeback(const struct btrfs_fs_info *fs_info, struct folio *folio, u64 start, u32 len) { - struct btrfs_subpage *subpage = folio_get_private(folio); + struct btrfs_folio_state *bfs = folio_get_private(folio); unsigned int start_bit = subpage_calc_start_bit(fs_info, folio, writeback, start, len); unsigned long flags;
- spin_lock_irqsave(&subpage->lock, flags); - bitmap_set(subpage->bitmaps, start_bit, len >> fs_info->sectorsize_bits); + spin_lock_irqsave(&bfs->lock, flags); + bitmap_set(bfs->bitmaps, start_bit, len >> fs_info->sectorsize_bits); if (!folio_test_writeback(folio)) folio_start_writeback(folio); - spin_unlock_irqrestore(&subpage->lock, flags); + spin_unlock_irqrestore(&bfs->lock, flags); }
void btrfs_subpage_clear_writeback(const struct btrfs_fs_info *fs_info, struct folio *folio, u64 start, u32 len) { - struct btrfs_subpage *subpage = folio_get_private(folio); + struct btrfs_folio_state *bfs = folio_get_private(folio); unsigned int start_bit = subpage_calc_start_bit(fs_info, folio, writeback, start, len); unsigned long flags;
- spin_lock_irqsave(&subpage->lock, flags); - bitmap_clear(subpage->bitmaps, start_bit, len >> fs_info->sectorsize_bits); + spin_lock_irqsave(&bfs->lock, flags); + bitmap_clear(bfs->bitmaps, start_bit, len >> fs_info->sectorsize_bits); if (subpage_test_bitmap_all_zero(fs_info, folio, writeback)) { ASSERT(folio_test_writeback(folio)); folio_end_writeback(folio); } - spin_unlock_irqrestore(&subpage->lock, flags); + spin_unlock_irqrestore(&bfs->lock, flags); }
void btrfs_subpage_set_ordered(const struct btrfs_fs_info *fs_info, struct folio *folio, u64 start, u32 len) { - struct btrfs_subpage *subpage = folio_get_private(folio); + struct btrfs_folio_state *bfs = folio_get_private(folio); unsigned int start_bit = subpage_calc_start_bit(fs_info, folio, ordered, start, len); unsigned long flags;
- spin_lock_irqsave(&subpage->lock, flags); - bitmap_set(subpage->bitmaps, start_bit, len >> fs_info->sectorsize_bits); + spin_lock_irqsave(&bfs->lock, flags); + bitmap_set(bfs->bitmaps, start_bit, len >> fs_info->sectorsize_bits); folio_set_ordered(folio); - spin_unlock_irqrestore(&subpage->lock, flags); + spin_unlock_irqrestore(&bfs->lock, flags); }
void btrfs_subpage_clear_ordered(const struct btrfs_fs_info *fs_info, struct folio *folio, u64 start, u32 len) { - struct btrfs_subpage *subpage = folio_get_private(folio); + struct btrfs_folio_state *bfs = folio_get_private(folio); unsigned int start_bit = subpage_calc_start_bit(fs_info, folio, ordered, start, len); unsigned long flags;
- spin_lock_irqsave(&subpage->lock, flags); - bitmap_clear(subpage->bitmaps, start_bit, len >> fs_info->sectorsize_bits); + spin_lock_irqsave(&bfs->lock, flags); + bitmap_clear(bfs->bitmaps, start_bit, len >> fs_info->sectorsize_bits); if (subpage_test_bitmap_all_zero(fs_info, folio, ordered)) folio_clear_ordered(folio); - spin_unlock_irqrestore(&subpage->lock, flags); + spin_unlock_irqrestore(&bfs->lock, flags); }
void btrfs_subpage_set_checked(const struct btrfs_fs_info *fs_info, struct folio *folio, u64 start, u32 len) { - struct btrfs_subpage *subpage = folio_get_private(folio); + struct btrfs_folio_state *bfs = folio_get_private(folio); unsigned int start_bit = subpage_calc_start_bit(fs_info, folio, checked, start, len); unsigned long flags;
- spin_lock_irqsave(&subpage->lock, flags); - bitmap_set(subpage->bitmaps, start_bit, len >> fs_info->sectorsize_bits); + spin_lock_irqsave(&bfs->lock, flags); + bitmap_set(bfs->bitmaps, start_bit, len >> fs_info->sectorsize_bits); if (subpage_test_bitmap_all_set(fs_info, folio, checked)) folio_set_checked(folio); - spin_unlock_irqrestore(&subpage->lock, flags); + spin_unlock_irqrestore(&bfs->lock, flags); }
void btrfs_subpage_clear_checked(const struct btrfs_fs_info *fs_info, struct folio *folio, u64 start, u32 len) { - struct btrfs_subpage *subpage = folio_get_private(folio); + struct btrfs_folio_state *bfs = folio_get_private(folio); unsigned int start_bit = subpage_calc_start_bit(fs_info, folio, checked, start, len); unsigned long flags;
- spin_lock_irqsave(&subpage->lock, flags); - bitmap_clear(subpage->bitmaps, start_bit, len >> fs_info->sectorsize_bits); + spin_lock_irqsave(&bfs->lock, flags); + bitmap_clear(bfs->bitmaps, start_bit, len >> fs_info->sectorsize_bits); folio_clear_checked(folio); - spin_unlock_irqrestore(&subpage->lock, flags); + spin_unlock_irqrestore(&bfs->lock, flags); }
/* @@ -541,16 +536,16 @@ void btrfs_subpage_clear_checked(const s bool btrfs_subpage_test_##name(const struct btrfs_fs_info *fs_info, \ struct folio *folio, u64 start, u32 len) \ { \ - struct btrfs_subpage *subpage = folio_get_private(folio); \ + struct btrfs_folio_state *bfs = folio_get_private(folio); \ unsigned int start_bit = subpage_calc_start_bit(fs_info, folio, \ name, start, len); \ unsigned long flags; \ bool ret; \ \ - spin_lock_irqsave(&subpage->lock, flags); \ - ret = bitmap_test_range_all_set(subpage->bitmaps, start_bit, \ + spin_lock_irqsave(&bfs->lock, flags); \ + ret = bitmap_test_range_all_set(bfs->bitmaps, start_bit, \ len >> fs_info->sectorsize_bits); \ - spin_unlock_irqrestore(&subpage->lock, flags); \ + spin_unlock_irqrestore(&bfs->lock, flags); \ return ret; \ } IMPLEMENT_BTRFS_SUBPAGE_TEST_OP(uptodate); @@ -662,10 +657,10 @@ IMPLEMENT_BTRFS_PAGE_OPS(checked, folio_ { \ const unsigned int blocks_per_folio = \ btrfs_blocks_per_folio(fs_info, folio); \ - const struct btrfs_subpage *subpage = folio_get_private(folio); \ + const struct btrfs_folio_state *bfs = folio_get_private(folio); \ \ ASSERT(blocks_per_folio <= BITS_PER_LONG); \ - *dst = bitmap_read(subpage->bitmaps, \ + *dst = bitmap_read(bfs->bitmaps, \ blocks_per_folio * btrfs_bitmap_nr_##name, \ blocks_per_folio); \ } @@ -690,7 +685,7 @@ IMPLEMENT_BTRFS_PAGE_OPS(checked, folio_ void btrfs_folio_assert_not_dirty(const struct btrfs_fs_info *fs_info, struct folio *folio, u64 start, u32 len) { - struct btrfs_subpage *subpage; + struct btrfs_folio_state *bfs; unsigned int start_bit; unsigned int nbits; unsigned long flags; @@ -705,15 +700,15 @@ void btrfs_folio_assert_not_dirty(const
start_bit = subpage_calc_start_bit(fs_info, folio, dirty, start, len); nbits = len >> fs_info->sectorsize_bits; - subpage = folio_get_private(folio); - ASSERT(subpage); - spin_lock_irqsave(&subpage->lock, flags); - if (unlikely(!bitmap_test_range_all_zero(subpage->bitmaps, start_bit, nbits))) { + bfs = folio_get_private(folio); + ASSERT(bfs); + spin_lock_irqsave(&bfs->lock, flags); + if (unlikely(!bitmap_test_range_all_zero(bfs->bitmaps, start_bit, nbits))) { SUBPAGE_DUMP_BITMAP(fs_info, folio, dirty, start, len); - ASSERT(bitmap_test_range_all_zero(subpage->bitmaps, start_bit, nbits)); + ASSERT(bitmap_test_range_all_zero(bfs->bitmaps, start_bit, nbits)); } - ASSERT(bitmap_test_range_all_zero(subpage->bitmaps, start_bit, nbits)); - spin_unlock_irqrestore(&subpage->lock, flags); + ASSERT(bitmap_test_range_all_zero(bfs->bitmaps, start_bit, nbits)); + spin_unlock_irqrestore(&bfs->lock, flags); }
/* @@ -726,7 +721,7 @@ void btrfs_folio_assert_not_dirty(const void btrfs_folio_set_lock(const struct btrfs_fs_info *fs_info, struct folio *folio, u64 start, u32 len) { - struct btrfs_subpage *subpage; + struct btrfs_folio_state *bfs; unsigned long flags; unsigned int start_bit; unsigned int nbits; @@ -736,19 +731,19 @@ void btrfs_folio_set_lock(const struct b if (unlikely(!fs_info) || !btrfs_is_subpage(fs_info, folio)) return;
- subpage = folio_get_private(folio); + bfs = folio_get_private(folio); start_bit = subpage_calc_start_bit(fs_info, folio, locked, start, len); nbits = len >> fs_info->sectorsize_bits; - spin_lock_irqsave(&subpage->lock, flags); + spin_lock_irqsave(&bfs->lock, flags); /* Target range should not yet be locked. */ - if (unlikely(!bitmap_test_range_all_zero(subpage->bitmaps, start_bit, nbits))) { + if (unlikely(!bitmap_test_range_all_zero(bfs->bitmaps, start_bit, nbits))) { SUBPAGE_DUMP_BITMAP(fs_info, folio, locked, start, len); - ASSERT(bitmap_test_range_all_zero(subpage->bitmaps, start_bit, nbits)); + ASSERT(bitmap_test_range_all_zero(bfs->bitmaps, start_bit, nbits)); } - bitmap_set(subpage->bitmaps, start_bit, nbits); - ret = atomic_add_return(nbits, &subpage->nr_locked); + bitmap_set(bfs->bitmaps, start_bit, nbits); + ret = atomic_add_return(nbits, &bfs->nr_locked); ASSERT(ret <= btrfs_blocks_per_folio(fs_info, folio)); - spin_unlock_irqrestore(&subpage->lock, flags); + spin_unlock_irqrestore(&bfs->lock, flags); }
/* @@ -776,7 +771,7 @@ bool btrfs_meta_folio_clear_and_test_dir void __cold btrfs_subpage_dump_bitmap(const struct btrfs_fs_info *fs_info, struct folio *folio, u64 start, u32 len) { - struct btrfs_subpage *subpage; + struct btrfs_folio_state *bfs; const unsigned int blocks_per_folio = btrfs_blocks_per_folio(fs_info, folio); unsigned long uptodate_bitmap; unsigned long dirty_bitmap; @@ -788,18 +783,18 @@ void __cold btrfs_subpage_dump_bitmap(co
ASSERT(folio_test_private(folio) && folio_get_private(folio)); ASSERT(blocks_per_folio > 1); - subpage = folio_get_private(folio); + bfs = folio_get_private(folio);
- spin_lock_irqsave(&subpage->lock, flags); + spin_lock_irqsave(&bfs->lock, flags); GET_SUBPAGE_BITMAP(fs_info, folio, uptodate, &uptodate_bitmap); GET_SUBPAGE_BITMAP(fs_info, folio, dirty, &dirty_bitmap); GET_SUBPAGE_BITMAP(fs_info, folio, writeback, &writeback_bitmap); GET_SUBPAGE_BITMAP(fs_info, folio, ordered, &ordered_bitmap); GET_SUBPAGE_BITMAP(fs_info, folio, checked, &checked_bitmap); GET_SUBPAGE_BITMAP(fs_info, folio, locked, &locked_bitmap); - spin_unlock_irqrestore(&subpage->lock, flags); + spin_unlock_irqrestore(&bfs->lock, flags);
- dump_page(folio_page(folio, 0), "btrfs subpage dump"); + dump_page(folio_page(folio, 0), "btrfs folio state dump"); btrfs_warn(fs_info, "start=%llu len=%u page=%llu, bitmaps uptodate=%*pbl dirty=%*pbl locked=%*pbl writeback=%*pbl ordered=%*pbl checked=%*pbl", start, len, folio_pos(folio), @@ -815,14 +810,14 @@ void btrfs_get_subpage_dirty_bitmap(stru struct folio *folio, unsigned long *ret_bitmap) { - struct btrfs_subpage *subpage; + struct btrfs_folio_state *bfs; unsigned long flags;
ASSERT(folio_test_private(folio) && folio_get_private(folio)); ASSERT(btrfs_blocks_per_folio(fs_info, folio) > 1); - subpage = folio_get_private(folio); + bfs = folio_get_private(folio);
- spin_lock_irqsave(&subpage->lock, flags); + spin_lock_irqsave(&bfs->lock, flags); GET_SUBPAGE_BITMAP(fs_info, folio, dirty, ret_bitmap); - spin_unlock_irqrestore(&subpage->lock, flags); + spin_unlock_irqrestore(&bfs->lock, flags); } --- a/fs/btrfs/subpage.h +++ b/fs/btrfs/subpage.h @@ -32,7 +32,15 @@ struct folio; enum { btrfs_bitmap_nr_uptodate = 0, btrfs_bitmap_nr_dirty, + + /* + * This can be changed to atomic eventually. But this change will rely + * on the async delalloc range rework for locked bitmap. As async + * delalloc can unlock its range and mark blocks writeback at random + * timing. + */ btrfs_bitmap_nr_writeback, + /* * The ordered and checked flags are for COW fixup, already marked * deprecated, and will be removed eventually. @@ -57,7 +65,7 @@ enum { * Structure to trace status of each sector inside a page, attached to * page::private for both data and metadata inodes. */ -struct btrfs_subpage { +struct btrfs_folio_state { /* Common members for both data and metadata pages */ spinlock_t lock; union { @@ -65,7 +73,7 @@ struct btrfs_subpage { * Structures only used by metadata * * @eb_refs should only be operated under private_lock, as it - * manages whether the subpage can be detached. + * manages whether the btrfs_folio_state can be detached. */ atomic_t eb_refs;
@@ -79,7 +87,7 @@ struct btrfs_subpage { unsigned long bitmaps[]; };
-enum btrfs_subpage_type { +enum btrfs_folio_type { BTRFS_SUBPAGE_METADATA, BTRFS_SUBPAGE_DATA, }; @@ -119,15 +127,18 @@ static inline bool btrfs_is_subpage(cons } #endif
-int btrfs_attach_subpage(const struct btrfs_fs_info *fs_info, - struct folio *folio, enum btrfs_subpage_type type); -void btrfs_detach_subpage(const struct btrfs_fs_info *fs_info, struct folio *folio, - enum btrfs_subpage_type type); +int btrfs_attach_folio_state(const struct btrfs_fs_info *fs_info, + struct folio *folio, enum btrfs_folio_type type); +void btrfs_detach_folio_state(const struct btrfs_fs_info *fs_info, struct folio *folio, + enum btrfs_folio_type type);
/* Allocate additional data where page represents more than one sector */ -struct btrfs_subpage *btrfs_alloc_subpage(const struct btrfs_fs_info *fs_info, - size_t fsize, enum btrfs_subpage_type type); -void btrfs_free_subpage(struct btrfs_subpage *subpage); +struct btrfs_folio_state *btrfs_alloc_folio_state(const struct btrfs_fs_info *fs_info, + size_t fsize, enum btrfs_folio_type type); +static inline void btrfs_free_folio_state(struct btrfs_folio_state *bfs) +{ + kfree(bfs); +}
void btrfs_folio_inc_eb_refs(const struct btrfs_fs_info *fs_info, struct folio *folio); void btrfs_folio_dec_eb_refs(const struct btrfs_fs_info *fs_info, struct folio *folio);
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Naohiro Aota naohiro.aota@wdc.com
[ Upstream commit b1511360c8ac882b0c52caa263620538e8d73220 ]
btrfs_subpage_set_writeback() calls folio_start_writeback() the first time a folio is written back, and it also clears the PAGECACHE_TAG_TOWRITE tag even if there are still dirty blocks in the folio. This can break ordering guarantees, such as those required by btrfs_wait_ordered_extents().
That ordering breakage leads to a real failure. For example, running generic/464 on a zoned setup will hit the following ASSERT. This happens because the broken ordering fails to flush existing dirty pages before the file size is truncated.
assertion failed: !list_empty(&ordered->list) :: 0, in fs/btrfs/zoned.c:1899 ------------[ cut here ]------------ kernel BUG at fs/btrfs/zoned.c:1899! Oops: invalid opcode: 0000 [#1] SMP NOPTI CPU: 2 UID: 0 PID: 1906169 Comm: kworker/u130:2 Kdump: loaded Not tainted 6.16.0-rc6-BTRFS-ZNS+ #554 PREEMPT(voluntary) Hardware name: Supermicro Super Server/H12SSL-NT, BIOS 2.0 02/22/2021 Workqueue: btrfs-endio-write btrfs_work_helper [btrfs] RIP: 0010:btrfs_finish_ordered_zoned.cold+0x50/0x52 [btrfs] RSP: 0018:ffffc9002efdbd60 EFLAGS: 00010246 RAX: 000000000000004c RBX: ffff88811923c4e0 RCX: 0000000000000000 RDX: 0000000000000000 RSI: ffffffff827e38b1 RDI: 00000000ffffffff RBP: ffff88810005d000 R08: 00000000ffffdfff R09: ffffffff831051c8 R10: ffffffff83055220 R11: 0000000000000000 R12: ffff8881c2458c00 R13: ffff88811923c540 R14: ffff88811923c5e8 R15: ffff8881c1bd9680 FS: 0000000000000000(0000) GS:ffff88a04acd0000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: 00007f907c7a918c CR3: 0000000004024000 CR4: 0000000000350ef0 Call Trace: <TASK> ? srso_return_thunk+0x5/0x5f btrfs_finish_ordered_io+0x4a/0x60 [btrfs] btrfs_work_helper+0xf9/0x490 [btrfs] process_one_work+0x204/0x590 ? srso_return_thunk+0x5/0x5f worker_thread+0x1d6/0x3d0 ? __pfx_worker_thread+0x10/0x10 kthread+0x118/0x230 ? __pfx_kthread+0x10/0x10 ret_from_fork+0x205/0x260 ? __pfx_kthread+0x10/0x10 ret_from_fork_asm+0x1a/0x30 </TASK>
Consider process A calling writepages() with WB_SYNC_NONE. In zoned mode or for compressed writes, it locks several folios for delalloc and starts writing them out. Let's call the last locked folio folio X. Suppose the write range only partially covers folio X, leaving some pages dirty. Process A calls btrfs_subpage_set_writeback() when building a bio. This function call clears the TOWRITE tag of folio X, whose size = 8K and the block size = 4K. It is following state.
0 4K 8K |/////|/////| (flag: DIRTY, tag: DIRTY) <-----> Process A will write this range.
Now suppose process B concurrently calls writepages() with WB_SYNC_ALL. It calls tag_pages_for_writeback() to tag dirty folios with PAGECACHE_TAG_TOWRITE. Since folio X is still dirty, it gets tagged. Then, B collects tagged folios using filemap_get_folios_tag() and must wait for folio X to be written before returning from writepages().
0 4K 8K |/////|/////| (flag: DIRTY, tag: DIRTY|TOWRITE)
However, between tagging and collecting, process A may call btrfs_subpage_set_writeback() and clear folio X's TOWRITE tag. 0 4K 8K | |/////| (flag: DIRTY|WRITEBACK, tag: DIRTY)
As a result, process B won't see folio X in its batch, and returns without waiting for it. This breaks the WB_SYNC_ALL ordering requirement.
Fix this by using btrfs_subpage_set_writeback_keepwrite(), which retains the TOWRITE tag. We now manually clear the tag only after the folio becomes clean, via the xas operation.
Fixes: 3470da3b7d87 ("btrfs: subpage: introduce helpers for writeback status") CC: stable@vger.kernel.org # 6.12+ Reviewed-by: Qu Wenruo wqu@suse.com Reviewed-by: Johannes Thumshirn johannes.thumshirn@wdc.com Signed-off-by: Naohiro Aota naohiro.aota@wdc.com Signed-off-by: David Sterba dsterba@suse.com Signed-off-by: Sasha Levin sashal@kernel.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- fs/btrfs/subpage.c | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-)
--- a/fs/btrfs/subpage.c +++ b/fs/btrfs/subpage.c @@ -448,8 +448,25 @@ void btrfs_subpage_set_writeback(const s
spin_lock_irqsave(&bfs->lock, flags); bitmap_set(bfs->bitmaps, start_bit, len >> fs_info->sectorsize_bits); + + /* + * Don't clear the TOWRITE tag when starting writeback on a still-dirty + * folio. Doing so can cause WB_SYNC_ALL writepages() to overlook it, + * assume writeback is complete, and exit too early — violating sync + * ordering guarantees. + */ if (!folio_test_writeback(folio)) - folio_start_writeback(folio); + __folio_start_writeback(folio, true); + if (!folio_test_dirty(folio)) { + struct address_space *mapping = folio_mapping(folio); + XA_STATE(xas, &mapping->i_pages, folio->index); + unsigned long flags; + + xas_lock_irqsave(&xas, flags); + xas_load(&xas); + xas_clear_mark(&xas, PAGECACHE_TAG_TOWRITE); + xas_unlock_irqrestore(&xas, flags); + } spin_unlock_irqrestore(&bfs->lock, flags); }
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Christoph Hellwig hch@lst.de
[ Upstream commit 83a80e95e797a2a6d14bf7983e5e6eecf8f5facb ]
xfs_trans_alloc_empty only shares the very basic transaction structure allocation and initialization with xfs_trans_alloc.
Split out a new __xfs_trans_alloc helper for that and otherwise decouple xfs_trans_alloc_empty from xfs_trans_alloc.
Signed-off-by: Christoph Hellwig hch@lst.de Reviewed-by: Darrick J. Wong djwong@kernel.org Signed-off-by: Carlos Maiolino cem@kernel.org Stable-dep-of: d2845519b072 ("xfs: fully decouple XFS_IBULK* flags from XFS_IWALK* flags") Signed-off-by: Sasha Levin sashal@kernel.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- fs/xfs/xfs_trans.c | 52 ++++++++++++++++++++++++++++------------------------ 1 file changed, 28 insertions(+), 24 deletions(-)
--- a/fs/xfs/xfs_trans.c +++ b/fs/xfs/xfs_trans.c @@ -241,6 +241,28 @@ undo_blocks: return error; }
+static struct xfs_trans * +__xfs_trans_alloc( + struct xfs_mount *mp, + uint flags) +{ + struct xfs_trans *tp; + + ASSERT(!(flags & XFS_TRANS_RES_FDBLKS) || xfs_has_lazysbcount(mp)); + + tp = kmem_cache_zalloc(xfs_trans_cache, GFP_KERNEL | __GFP_NOFAIL); + if (!(flags & XFS_TRANS_NO_WRITECOUNT)) + sb_start_intwrite(mp->m_super); + xfs_trans_set_context(tp); + tp->t_flags = flags; + tp->t_mountp = mp; + INIT_LIST_HEAD(&tp->t_items); + INIT_LIST_HEAD(&tp->t_busy); + INIT_LIST_HEAD(&tp->t_dfops); + tp->t_highest_agno = NULLAGNUMBER; + return tp; +} + int xfs_trans_alloc( struct xfs_mount *mp, @@ -254,33 +276,16 @@ xfs_trans_alloc( bool want_retry = true; int error;
+ ASSERT(resp->tr_logres > 0); + /* * Allocate the handle before we do our freeze accounting and setting up * GFP_NOFS allocation context so that we avoid lockdep false positives * by doing GFP_KERNEL allocations inside sb_start_intwrite(). */ retry: - tp = kmem_cache_zalloc(xfs_trans_cache, GFP_KERNEL | __GFP_NOFAIL); - if (!(flags & XFS_TRANS_NO_WRITECOUNT)) - sb_start_intwrite(mp->m_super); - xfs_trans_set_context(tp); - - /* - * Zero-reservation ("empty") transactions can't modify anything, so - * they're allowed to run while we're frozen. - */ - WARN_ON(resp->tr_logres > 0 && - mp->m_super->s_writers.frozen == SB_FREEZE_COMPLETE); - ASSERT(!(flags & XFS_TRANS_RES_FDBLKS) || - xfs_has_lazysbcount(mp)); - - tp->t_flags = flags; - tp->t_mountp = mp; - INIT_LIST_HEAD(&tp->t_items); - INIT_LIST_HEAD(&tp->t_busy); - INIT_LIST_HEAD(&tp->t_dfops); - tp->t_highest_agno = NULLAGNUMBER; - + WARN_ON(mp->m_super->s_writers.frozen == SB_FREEZE_COMPLETE); + tp = __xfs_trans_alloc(mp, flags); error = xfs_trans_reserve(tp, resp, blocks, rtextents); if (error == -ENOSPC && want_retry) { xfs_trans_cancel(tp); @@ -329,9 +334,8 @@ xfs_trans_alloc_empty( struct xfs_mount *mp, struct xfs_trans **tpp) { - struct xfs_trans_res resv = {0}; - - return xfs_trans_alloc(mp, &resv, 0, 0, XFS_TRANS_NO_WRITECOUNT, tpp); + *tpp = __xfs_trans_alloc(mp, XFS_TRANS_NO_WRITECOUNT); + return 0; }
/*
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Christoph Hellwig hch@lst.de
[ Upstream commit d8e1ea43e5a314bc01ec059ce93396639dcf9112 ]
xfs_trans_alloc_empty can't return errors, so return the allocated transaction directly instead of an output double pointer argument.
Signed-off-by: Christoph Hellwig hch@lst.de Reviewed-by: Darrick J. Wong djwong@kernel.org Signed-off-by: Carlos Maiolino cem@kernel.org Stable-dep-of: d2845519b072 ("xfs: fully decouple XFS_IBULK* flags from XFS_IWALK* flags") Signed-off-by: Sasha Levin sashal@kernel.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- fs/xfs/libxfs/xfs_refcount.c | 4 +--- fs/xfs/scrub/common.c | 3 ++- fs/xfs/scrub/repair.c | 12 ++---------- fs/xfs/scrub/scrub.c | 5 +---- fs/xfs/xfs_attr_item.c | 5 +---- fs/xfs/xfs_discard.c | 12 +++--------- fs/xfs/xfs_fsmap.c | 4 +--- fs/xfs/xfs_icache.c | 5 +---- fs/xfs/xfs_inode.c | 7 ++----- fs/xfs/xfs_itable.c | 18 +++--------------- fs/xfs/xfs_iwalk.c | 11 +++-------- fs/xfs/xfs_notify_failure.c | 5 +---- fs/xfs/xfs_qm.c | 10 ++-------- fs/xfs/xfs_rtalloc.c | 13 +++---------- fs/xfs/xfs_trans.c | 8 +++----- fs/xfs/xfs_trans.h | 3 +-- fs/xfs/xfs_zone_gc.c | 5 +---- 17 files changed, 31 insertions(+), 99 deletions(-)
--- a/fs/xfs/libxfs/xfs_refcount.c +++ b/fs/xfs/libxfs/xfs_refcount.c @@ -2099,9 +2099,7 @@ xfs_refcount_recover_cow_leftovers( * recording the CoW debris we cancel the (empty) transaction * and everything goes away cleanly. */ - error = xfs_trans_alloc_empty(mp, &tp); - if (error) - return error; + tp = xfs_trans_alloc_empty(mp);
if (isrt) { xfs_rtgroup_lock(to_rtg(xg), XFS_RTGLOCK_REFCOUNT); --- a/fs/xfs/scrub/common.c +++ b/fs/xfs/scrub/common.c @@ -870,7 +870,8 @@ int xchk_trans_alloc_empty( struct xfs_scrub *sc) { - return xfs_trans_alloc_empty(sc->mp, &sc->tp); + sc->tp = xfs_trans_alloc_empty(sc->mp); + return 0; }
/* --- a/fs/xfs/scrub/repair.c +++ b/fs/xfs/scrub/repair.c @@ -1279,18 +1279,10 @@ xrep_trans_alloc_hook_dummy( void **cookiep, struct xfs_trans **tpp) { - int error; - *cookiep = current->journal_info; current->journal_info = NULL; - - error = xfs_trans_alloc_empty(mp, tpp); - if (!error) - return 0; - - current->journal_info = *cookiep; - *cookiep = NULL; - return error; + *tpp = xfs_trans_alloc_empty(mp); + return 0; }
/* Cancel a dummy transaction used by a live update hook function. */ --- a/fs/xfs/scrub/scrub.c +++ b/fs/xfs/scrub/scrub.c @@ -876,10 +876,7 @@ xchk_scrubv_open_by_handle( struct xfs_inode *ip; int error;
- error = xfs_trans_alloc_empty(mp, &tp); - if (error) - return NULL; - + tp = xfs_trans_alloc_empty(mp); error = xfs_iget(mp, tp, head->svh_ino, XCHK_IGET_FLAGS, 0, &ip); xfs_trans_cancel(tp); if (error) --- a/fs/xfs/xfs_attr_item.c +++ b/fs/xfs/xfs_attr_item.c @@ -616,10 +616,7 @@ xfs_attri_iread_extents( struct xfs_trans *tp; int error;
- error = xfs_trans_alloc_empty(ip->i_mount, &tp); - if (error) - return error; - + tp = xfs_trans_alloc_empty(ip->i_mount); xfs_ilock(ip, XFS_ILOCK_EXCL); error = xfs_iread_extents(tp, ip, XFS_ATTR_FORK); xfs_iunlock(ip, XFS_ILOCK_EXCL); --- a/fs/xfs/xfs_discard.c +++ b/fs/xfs/xfs_discard.c @@ -189,9 +189,7 @@ xfs_trim_gather_extents( */ xfs_log_force(mp, XFS_LOG_SYNC);
- error = xfs_trans_alloc_empty(mp, &tp); - if (error) - return error; + tp = xfs_trans_alloc_empty(mp);
error = xfs_alloc_read_agf(pag, tp, 0, &agbp); if (error) @@ -583,9 +581,7 @@ xfs_trim_rtextents( struct xfs_trans *tp; int error;
- error = xfs_trans_alloc_empty(mp, &tp); - if (error) - return error; + tp = xfs_trans_alloc_empty(mp);
/* * Walk the free ranges between low and high. The query_range function @@ -701,9 +697,7 @@ xfs_trim_rtgroup_extents( struct xfs_trans *tp; int error;
- error = xfs_trans_alloc_empty(mp, &tp); - if (error) - return error; + tp = xfs_trans_alloc_empty(mp);
/* * Walk the free ranges between low and high. The query_range function --- a/fs/xfs/xfs_fsmap.c +++ b/fs/xfs/xfs_fsmap.c @@ -1270,9 +1270,7 @@ xfs_getfsmap( * buffer locking abilities to detect cycles in the rmapbt * without deadlocking. */ - error = xfs_trans_alloc_empty(mp, &tp); - if (error) - break; + tp = xfs_trans_alloc_empty(mp);
info.dev = handlers[i].dev; info.last = false; --- a/fs/xfs/xfs_icache.c +++ b/fs/xfs/xfs_icache.c @@ -893,10 +893,7 @@ xfs_metafile_iget( struct xfs_trans *tp; int error;
- error = xfs_trans_alloc_empty(mp, &tp); - if (error) - return error; - + tp = xfs_trans_alloc_empty(mp); error = xfs_trans_metafile_iget(tp, ino, metafile_type, ipp); xfs_trans_cancel(tp); return error; --- a/fs/xfs/xfs_inode.c +++ b/fs/xfs/xfs_inode.c @@ -2932,12 +2932,9 @@ xfs_inode_reload_unlinked( struct xfs_inode *ip) { struct xfs_trans *tp; - int error; - - error = xfs_trans_alloc_empty(ip->i_mount, &tp); - if (error) - return error; + int error = 0;
+ tp = xfs_trans_alloc_empty(ip->i_mount); xfs_ilock(ip, XFS_ILOCK_SHARED); if (xfs_inode_unlinked_incomplete(ip)) error = xfs_inode_reload_unlinked_bucket(tp, ip); --- a/fs/xfs/xfs_itable.c +++ b/fs/xfs/xfs_itable.c @@ -239,14 +239,10 @@ xfs_bulkstat_one( * Grab an empty transaction so that we can use its recursive buffer * locking abilities to detect cycles in the inobt without deadlocking. */ - error = xfs_trans_alloc_empty(breq->mp, &tp); - if (error) - goto out; - + tp = xfs_trans_alloc_empty(breq->mp); error = xfs_bulkstat_one_int(breq->mp, breq->idmap, tp, breq->startino, &bc); xfs_trans_cancel(tp); -out: kfree(bc.buf);
/* @@ -331,17 +327,13 @@ xfs_bulkstat( * Grab an empty transaction so that we can use its recursive buffer * locking abilities to detect cycles in the inobt without deadlocking. */ - error = xfs_trans_alloc_empty(breq->mp, &tp); - if (error) - goto out; - + tp = xfs_trans_alloc_empty(breq->mp); if (breq->flags & XFS_IBULK_SAME_AG) iwalk_flags |= XFS_IWALK_SAME_AG;
error = xfs_iwalk(breq->mp, tp, breq->startino, iwalk_flags, xfs_bulkstat_iwalk, breq->icount, &bc); xfs_trans_cancel(tp); -out: kfree(bc.buf);
/* @@ -464,14 +456,10 @@ xfs_inumbers( * Grab an empty transaction so that we can use its recursive buffer * locking abilities to detect cycles in the inobt without deadlocking. */ - error = xfs_trans_alloc_empty(breq->mp, &tp); - if (error) - goto out; - + tp = xfs_trans_alloc_empty(breq->mp); error = xfs_inobt_walk(breq->mp, tp, breq->startino, breq->flags, xfs_inumbers_walk, breq->icount, &ic); xfs_trans_cancel(tp); -out:
/* * We found some inode groups, so clear the error status and return --- a/fs/xfs/xfs_iwalk.c +++ b/fs/xfs/xfs_iwalk.c @@ -377,11 +377,8 @@ xfs_iwalk_run_callbacks( if (!has_more) return 0;
- if (iwag->drop_trans) { - error = xfs_trans_alloc_empty(mp, &iwag->tp); - if (error) - return error; - } + if (iwag->drop_trans) + iwag->tp = xfs_trans_alloc_empty(mp);
/* ...and recreate the cursor just past where we left off. */ error = xfs_ialloc_read_agi(iwag->pag, iwag->tp, 0, agi_bpp); @@ -617,9 +614,7 @@ xfs_iwalk_ag_work( * Grab an empty transaction so that we can use its recursive buffer * locking abilities to detect cycles in the inobt without deadlocking. */ - error = xfs_trans_alloc_empty(mp, &iwag->tp); - if (error) - goto out; + iwag->tp = xfs_trans_alloc_empty(mp); iwag->drop_trans = 1;
error = xfs_iwalk_ag(iwag); --- a/fs/xfs/xfs_notify_failure.c +++ b/fs/xfs/xfs_notify_failure.c @@ -279,10 +279,7 @@ xfs_dax_notify_dev_failure( kernel_frozen = xfs_dax_notify_failure_freeze(mp) == 0; }
- error = xfs_trans_alloc_empty(mp, &tp); - if (error) - goto out; - + tp = xfs_trans_alloc_empty(mp); start_gno = xfs_fsb_to_gno(mp, start_bno, type); end_gno = xfs_fsb_to_gno(mp, end_bno, type); while ((xg = xfs_group_next_range(mp, xg, start_gno, end_gno, type))) { --- a/fs/xfs/xfs_qm.c +++ b/fs/xfs/xfs_qm.c @@ -660,10 +660,7 @@ xfs_qm_load_metadir_qinos( struct xfs_trans *tp; int error;
- error = xfs_trans_alloc_empty(mp, &tp); - if (error) - return error; - + tp = xfs_trans_alloc_empty(mp); error = xfs_dqinode_load_parent(tp, &qi->qi_dirip); if (error == -ENOENT) { /* no quota dir directory, but we'll create one later */ @@ -1755,10 +1752,7 @@ xfs_qm_qino_load( struct xfs_inode *dp = NULL; int error;
- error = xfs_trans_alloc_empty(mp, &tp); - if (error) - return error; - + tp = xfs_trans_alloc_empty(mp); if (xfs_has_metadir(mp)) { error = xfs_dqinode_load_parent(tp, &dp); if (error) --- a/fs/xfs/xfs_rtalloc.c +++ b/fs/xfs/xfs_rtalloc.c @@ -729,9 +729,7 @@ xfs_rtginode_ensure( if (rtg->rtg_inodes[type]) return 0;
- error = xfs_trans_alloc_empty(rtg_mount(rtg), &tp); - if (error) - return error; + tp = xfs_trans_alloc_empty(rtg_mount(rtg)); error = xfs_rtginode_load(rtg, type, tp); xfs_trans_cancel(tp);
@@ -1305,9 +1303,7 @@ xfs_growfs_rt_prep_groups( if (!mp->m_rtdirip) { struct xfs_trans *tp;
- error = xfs_trans_alloc_empty(mp, &tp); - if (error) - return error; + tp = xfs_trans_alloc_empty(mp); error = xfs_rtginode_load_parent(tp); xfs_trans_cancel(tp);
@@ -1674,10 +1670,7 @@ xfs_rtmount_inodes( struct xfs_rtgroup *rtg = NULL; int error;
- error = xfs_trans_alloc_empty(mp, &tp); - if (error) - return error; - + tp = xfs_trans_alloc_empty(mp); if (xfs_has_rtgroups(mp) && mp->m_sb.sb_rgcount > 0) { error = xfs_rtginode_load_parent(tp); if (error) --- a/fs/xfs/xfs_trans.c +++ b/fs/xfs/xfs_trans.c @@ -329,13 +329,11 @@ retry: * where we can be grabbing buffers at the same time that freeze is trying to * drain the buffer LRU list. */ -int +struct xfs_trans * xfs_trans_alloc_empty( - struct xfs_mount *mp, - struct xfs_trans **tpp) + struct xfs_mount *mp) { - *tpp = __xfs_trans_alloc(mp, XFS_TRANS_NO_WRITECOUNT); - return 0; + return __xfs_trans_alloc(mp, XFS_TRANS_NO_WRITECOUNT); }
/* --- a/fs/xfs/xfs_trans.h +++ b/fs/xfs/xfs_trans.h @@ -168,8 +168,7 @@ int xfs_trans_alloc(struct xfs_mount *m struct xfs_trans **tpp); int xfs_trans_reserve_more(struct xfs_trans *tp, unsigned int blocks, unsigned int rtextents); -int xfs_trans_alloc_empty(struct xfs_mount *mp, - struct xfs_trans **tpp); +struct xfs_trans *xfs_trans_alloc_empty(struct xfs_mount *mp); void xfs_trans_mod_sb(xfs_trans_t *, uint, int64_t);
int xfs_trans_get_buf_map(struct xfs_trans *tp, struct xfs_buftarg *target, --- a/fs/xfs/xfs_zone_gc.c +++ b/fs/xfs/xfs_zone_gc.c @@ -328,10 +328,7 @@ xfs_zone_gc_query( iter->rec_idx = 0; iter->rec_count = 0;
- error = xfs_trans_alloc_empty(mp, &tp); - if (error) - return error; - + tp = xfs_trans_alloc_empty(mp); xfs_rtgroup_lock(rtg, XFS_RTGLOCK_RMAP); cur = xfs_rtrmapbt_init_cursor(tp, rtg); error = xfs_rmap_query_range(cur, &ri_low, &ri_high,
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Christoph Hellwig hch@lst.de
[ Upstream commit 60e02f956d77af31b85ed4e73abf85d5f12d0a98 ]
The top of the function comment is outdated, and the parts still correct duplicate information in comment inside the function. Remove the top of the function comment and instead improve a comment inside the function.
Signed-off-by: Christoph Hellwig hch@lst.de Reviewed-by: Darrick J. Wong djwong@kernel.org Signed-off-by: Carlos Maiolino cem@kernel.org Stable-dep-of: d2845519b072 ("xfs: fully decouple XFS_IBULK* flags from XFS_IWALK* flags") Signed-off-by: Sasha Levin sashal@kernel.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- fs/xfs/xfs_zone_alloc.c | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-)
--- a/fs/xfs/xfs_zone_alloc.c +++ b/fs/xfs/xfs_zone_alloc.c @@ -654,13 +654,6 @@ static inline bool xfs_zoned_pack_tight( !(ip->i_diflags & XFS_DIFLAG_APPEND); }
-/* - * Pick a new zone for writes. - * - * If we aren't using up our budget of open zones just open a new one from the - * freelist. Else try to find one that matches the expected data lifetime. If - * we don't find one that is good pick any zone that is available. - */ static struct xfs_open_zone * xfs_select_zone_nowait( struct xfs_mount *mp, @@ -688,7 +681,8 @@ xfs_select_zone_nowait( goto out_unlock;
/* - * See if we can open a new zone and use that. + * See if we can open a new zone and use that so that data for different + * files is mixed as little as possible. */ oz = xfs_try_open_zone(mp, write_hint); if (oz)
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Christoph Hellwig hch@lst.de
[ Upstream commit d2845519b0723c5d5a0266cbf410495f9b8fd65c ]
Fix up xfs_inumbers to now pass in the XFS_IBULK* flags into the flags argument to xfs_inobt_walk, which expects the XFS_IWALK* flags.
Currently passing the wrong flags works for non-debug builds because the only XFS_IWALK* flag has the same encoding as the corresponding XFS_IBULK* flag, but in debug builds it can trigger an assert that no incorrect flag is passed. Instead just extra the relevant flag.
Fixes: 5b35d922c52798 ("xfs: Decouple XFS_IBULK flags from XFS_IWALK flags") Cc: stable@vger.kernel.org # v5.19 Reported-by: cen zhang zzzccc427@gmail.com Signed-off-by: Christoph Hellwig hch@lst.de Reviewed-by: Darrick J. Wong djwong@kernel.org Signed-off-by: Carlos Maiolino cem@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- fs/xfs/xfs_itable.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-)
--- a/fs/xfs/xfs_itable.c +++ b/fs/xfs/xfs_itable.c @@ -447,17 +447,21 @@ xfs_inumbers( .breq = breq, }; struct xfs_trans *tp; + unsigned int iwalk_flags = 0; int error = 0;
if (xfs_bulkstat_already_done(breq->mp, breq->startino)) return 0;
+ if (breq->flags & XFS_IBULK_SAME_AG) + iwalk_flags |= XFS_IWALK_SAME_AG; + /* * Grab an empty transaction so that we can use its recursive buffer * locking abilities to detect cycles in the inobt without deadlocking. */ tp = xfs_trans_alloc_empty(breq->mp); - error = xfs_inobt_walk(breq->mp, tp, breq->startino, breq->flags, + error = xfs_inobt_walk(breq->mp, tp, breq->startino, iwalk_flags, xfs_inumbers_walk, breq->icount, &ic); xfs_trans_cancel(tp);
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Alan Huang mmpgouride@gmail.com
[ Upstream commit 8c10b04f9fc1760cb79068073686d8866e59d40f ]
Fixes: e967dc40d501 ("xfs: return the allocated transaction from xfs_trans_alloc_empty") Signed-off-by: Alan Huang mmpgouride@gmail.com Reviewed-by: Christoph Hellwig hch@lst.de Signed-off-by: Carlos Maiolino cem@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- fs/xfs/xfs_notify_failure.c | 1 - 1 file changed, 1 deletion(-)
--- a/fs/xfs/xfs_notify_failure.c +++ b/fs/xfs/xfs_notify_failure.c @@ -350,7 +350,6 @@ xfs_dax_notify_dev_failure( error = -EFSCORRUPTED; }
-out: /* Thaw the fs if it has been frozen before. */ if (mf_flags & MF_MEM_PRE_REMOVE) xfs_dax_notify_failure_thaw(mp, kernel_frozen);
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Bo Liu (OpenAnolis) liubo03@inspur.com
commit 5e0bf36fd156b8d9b09f8481ee6daa6cdba1b064 upstream.
fix build err: ld.lld: error: undefined symbol: crypto_req_done referenced by decompressor_crypto.c fs/erofs/decompressor_crypto.o:(z_erofs_crypto_decompress) in archive vmlinux.a referenced by decompressor_crypto.c fs/erofs/decompressor_crypto.o:(z_erofs_crypto_decompress) in archive vmlinux.a
ld.lld: error: undefined symbol: crypto_acomp_decompress referenced by decompressor_crypto.c fs/erofs/decompressor_crypto.o:(z_erofs_crypto_decompress) in archive vmlinux.a
ld.lld: error: undefined symbol: crypto_alloc_acomp referenced by decompressor_crypto.c fs/erofs/decompressor_crypto.o:(z_erofs_crypto_enable_engine) in archive vmlinux.a
Reported-by: kernel test robot lkp@intel.com Closes: https://lore.kernel.org/oe-kbuild-all/202507161032.QholMPtn-lkp@intel.com/ Fixes: b4a29efc5146 ("erofs: support DEFLATE decompression by using Intel QAT") Signed-off-by: Bo Liu (OpenAnolis) liubo03@inspur.com Link: https://lore.kernel.org/r/20250718033039.3609-1-liubo03@inspur.com Reviewed-by: Gao Xiang hsiangkao@linux.alibaba.com Signed-off-by: Gao Xiang hsiangkao@linux.alibaba.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- fs/erofs/Kconfig | 2 ++ 1 file changed, 2 insertions(+)
--- a/fs/erofs/Kconfig +++ b/fs/erofs/Kconfig @@ -147,6 +147,8 @@ config EROFS_FS_ZIP_ZSTD config EROFS_FS_ZIP_ACCEL bool "EROFS hardware decompression support" depends on EROFS_FS_ZIP + select CRYPTO + select CRYPTO_DEFLATE help Saying Y here includes hardware accelerator support for reading EROFS file systems containing compressed data. It gives better
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Geert Uytterhoeven geert+renesas@glider.be
commit 74da24f0ac9b8aabfb8d7feeba6c32ddff3065e0 upstream.
The EROFS filesystem has many configurable options, controlled through boolean Kconfig symbols. When enabled, these options may need to enable additional library functionality elsewhere. Currently this is done by selecting the symbol for the additional functionality. However, if EROFS_FS itself is modular, and the target symbol is a tristate symbol, the additional functionality is always forced built-in.
Selecting tristate symbols from a tristate symbol does keep modular transitivity. Hence fix this by moving selects of tristate symbols to the main EROFS_FS symbol.
Signed-off-by: Geert Uytterhoeven geert+renesas@glider.be Reviewed-by: Gao Xiang hsiangkao@linux.alibaba.com Link: https://lore.kernel.org/r/da1b899e511145dd43fd2d398f64b2e03c6a39e7.175387935... Signed-off-by: Gao Xiang hsiangkao@linux.alibaba.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- fs/erofs/Kconfig | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-)
--- a/fs/erofs/Kconfig +++ b/fs/erofs/Kconfig @@ -3,8 +3,18 @@ config EROFS_FS tristate "EROFS filesystem support" depends on BLOCK + select CACHEFILES if EROFS_FS_ONDEMAND select CRC32 + select CRYPTO if EROFS_FS_ZIP_ACCEL + select CRYPTO_DEFLATE if EROFS_FS_ZIP_ACCEL select FS_IOMAP + select LZ4_DECOMPRESS if EROFS_FS_ZIP + select NETFS_SUPPORT if EROFS_FS_ONDEMAND + select XXHASH if EROFS_FS_XATTR + select XZ_DEC if EROFS_FS_ZIP_LZMA + select XZ_DEC_MICROLZMA if EROFS_FS_ZIP_LZMA + select ZLIB_INFLATE if EROFS_FS_ZIP_DEFLATE + select ZSTD_DECOMPRESS if EROFS_FS_ZIP_ZSTD help EROFS (Enhanced Read-Only File System) is a lightweight read-only file system with modern designs (e.g. no buffer heads, inline @@ -38,7 +48,6 @@ config EROFS_FS_DEBUG config EROFS_FS_XATTR bool "EROFS extended attributes" depends on EROFS_FS - select XXHASH default y help Extended attributes are name:value pairs associated with inodes by @@ -94,7 +103,6 @@ config EROFS_FS_BACKED_BY_FILE config EROFS_FS_ZIP bool "EROFS Data Compression Support" depends on EROFS_FS - select LZ4_DECOMPRESS default y help Enable transparent compression support for EROFS file systems. @@ -104,8 +112,6 @@ config EROFS_FS_ZIP config EROFS_FS_ZIP_LZMA bool "EROFS LZMA compressed data support" depends on EROFS_FS_ZIP - select XZ_DEC - select XZ_DEC_MICROLZMA help Saying Y here includes support for reading EROFS file systems containing LZMA compressed data, specifically called microLZMA. It @@ -117,7 +123,6 @@ config EROFS_FS_ZIP_LZMA config EROFS_FS_ZIP_DEFLATE bool "EROFS DEFLATE compressed data support" depends on EROFS_FS_ZIP - select ZLIB_INFLATE help Saying Y here includes support for reading EROFS file systems containing DEFLATE compressed data. It gives better compression @@ -132,7 +137,6 @@ config EROFS_FS_ZIP_DEFLATE config EROFS_FS_ZIP_ZSTD bool "EROFS Zstandard compressed data support" depends on EROFS_FS_ZIP - select ZSTD_DECOMPRESS help Saying Y here includes support for reading EROFS file systems containing Zstandard compressed data. It gives better compression @@ -147,8 +151,6 @@ config EROFS_FS_ZIP_ZSTD config EROFS_FS_ZIP_ACCEL bool "EROFS hardware decompression support" depends on EROFS_FS_ZIP - select CRYPTO - select CRYPTO_DEFLATE help Saying Y here includes hardware accelerator support for reading EROFS file systems containing compressed data. It gives better @@ -163,9 +165,7 @@ config EROFS_FS_ZIP_ACCEL config EROFS_FS_ONDEMAND bool "EROFS fscache-based on-demand read support (deprecated)" depends on EROFS_FS - select NETFS_SUPPORT select FSCACHE - select CACHEFILES select CACHEFILES_ONDEMAND help This permits EROFS to use fscache-backed data blobs with on-demand
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Eric Biggers ebiggers@kernel.org
commit 962ddc5a7a4b04c007bba0f3e7298cda13c62efd upstream.
To avoid a crash when control flow integrity is enabled, make the workspace ("stream") free function use a consistent type, and call it through a function pointer that has that same type.
Fixes: 42d9f6c77479 ("crypto: acomp - Move scomp stream allocation code into acomp") Cc: stable@vger.kernel.org Signed-off-by: Eric Biggers ebiggers@kernel.org Reviewed-by: Giovanni Cabiddu giovanni.cabiddu@intel.com Signed-off-by: Herbert Xu herbert@gondor.apana.org.au [Giovanni: Backport to 6.16.y. Removed logic in crypto/zstd.c as commit f5ad93ffb541 ("crypto: zstd - convert to acomp") is not going to be backported to stable.] Signed-off-by: Giovanni Cabiddu giovanni.cabiddu@intel.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- crypto/deflate.c | 7 ++++++- include/crypto/internal/acompress.h | 5 +---- 2 files changed, 7 insertions(+), 5 deletions(-)
--- a/crypto/deflate.c +++ b/crypto/deflate.c @@ -48,9 +48,14 @@ static void *deflate_alloc_stream(void) return ctx; }
+static void deflate_free_stream(void *ctx) +{ + kvfree(ctx); +} + static struct crypto_acomp_streams deflate_streams = { .alloc_ctx = deflate_alloc_stream, - .cfree_ctx = kvfree, + .free_ctx = deflate_free_stream, };
static int deflate_compress_one(struct acomp_req *req, --- a/include/crypto/internal/acompress.h +++ b/include/crypto/internal/acompress.h @@ -63,10 +63,7 @@ struct crypto_acomp_stream { struct crypto_acomp_streams { /* These must come first because of struct scomp_alg. */ void *(*alloc_ctx)(void); - union { - void (*free_ctx)(void *); - void (*cfree_ctx)(const void *); - }; + void (*free_ctx)(void *);
struct crypto_acomp_stream __percpu *streams; struct work_struct stream_work;
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: XianLiang Huang huangxianliang@lanxincomputing.com
commit 99d4d1a070870aa08163af8ce0522992b7f35d8c upstream.
The riscv_iommu_pte_fetch() function returns either NULL for unmapped/never-mapped iova, or a valid leaf pte pointer that requires no further validation.
riscv_iommu_iova_to_phys() failed to handle NULL returns. Prevent null pointer dereference in riscv_iommu_iova_to_phys(), and remove the pte validation.
Fixes: 488ffbf18171 ("iommu/riscv: Paging domain support") Cc: Tomasz Jeznach tjeznach@rivosinc.com Signed-off-by: XianLiang Huang huangxianliang@lanxincomputing.com Link: https://lore.kernel.org/r/20250820072248.312-1-huangxianliang@lanxincomputin... Signed-off-by: Joerg Roedel joerg.roedel@amd.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/iommu/riscv/iommu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
--- a/drivers/iommu/riscv/iommu.c +++ b/drivers/iommu/riscv/iommu.c @@ -1283,7 +1283,7 @@ static phys_addr_t riscv_iommu_iova_to_p unsigned long *ptr;
ptr = riscv_iommu_pte_fetch(domain, iova, &pte_size); - if (_io_pte_none(*ptr) || !_io_pte_present(*ptr)) + if (!ptr) return 0;
return pfn_to_phys(__page_val_to_pfn(*ptr)) | (iova & (pte_size - 1));
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jens Axboe axboe@kernel.dk
commit 508c1314b342b78591f51c4b5dadee31a88335df upstream.
The io_futex_data is allocated upfront and assigned to the io_kiocb async_data field, but the request isn't marked with REQ_F_ASYNC_DATA at that point. Those two should always go together, as the flag tells io_uring whether the field is valid or not.
Additionally, on failure cleanup, the futex handler frees the data but does not clear ->async_data. Clear the data and the flag in the error path as well.
Thanks to Trend Micro Zero Day Initiative and particularly ReDress for reporting this.
Cc: stable@vger.kernel.org Fixes: 194bb58c6090 ("io_uring: add support for futex wake and wait") Signed-off-by: Jens Axboe axboe@kernel.dk Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- io_uring/futex.c | 3 +++ 1 file changed, 3 insertions(+)
--- a/io_uring/futex.c +++ b/io_uring/futex.c @@ -288,6 +288,7 @@ int io_futex_wait(struct io_kiocb *req, goto done_unlock; }
+ req->flags |= REQ_F_ASYNC_DATA; req->async_data = ifd; ifd->q = futex_q_init; ifd->q.bitset = iof->futex_mask; @@ -309,6 +310,8 @@ done: if (ret < 0) req_set_fail(req); io_req_set_res(req, ret, 0); + req->async_data = NULL; + req->flags &= ~REQ_F_ASYNC_DATA; kfree(ifd); return IOU_COMPLETE; }
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Dominique Martinet asmadeus@codewreck.org
commit 808471ddb0fa785559c3e7aee59be20a13b46ef5 upstream.
It's apparently possible to get an iov advanced all the way up to the end of the current page we're looking at, e.g.
(gdb) p *iter $24 = {iter_type = 4 '\004', nofault = false, data_source = false, iov_offset = 4096, {__ubuf_iovec = { iov_base = 0xffff88800f5bc000, iov_len = 655}, {{__iov = 0xffff88800f5bc000, kvec = 0xffff88800f5bc000, bvec = 0xffff88800f5bc000, folioq = 0xffff88800f5bc000, xarray = 0xffff88800f5bc000, ubuf = 0xffff88800f5bc000}, count = 655}}, {nr_segs = 2, folioq_slot = 2 '\002', xarray_start = 2}}
Where iov_offset is 4k with 4k-sized folios
This should have been fine because we're only in the 2nd slot and there's another one after this, but iterate_folioq should not try to map a folio that skips the whole size, and more importantly part here does not end up zero (because 'PAGE_SIZE - skip % PAGE_SIZE' ends up PAGE_SIZE and not zero..), so skip forward to the "advance to next folio" code
Link: https://lkml.kernel.org/r/20250813-iot_iter_folio-v3-0-a0ffad2b665a@codewrec... Link: https://lkml.kernel.org/r/20250813-iot_iter_folio-v3-1-a0ffad2b665a@codewrec... Signed-off-by: Dominique Martinet asmadeus@codewreck.org Fixes: db0aa2e9566f ("mm: Define struct folio_queue and ITER_FOLIOQ to handle a sequence of folios") Reported-by: Maximilian Bosch maximilian@mbosch.me Reported-by: Ryan Lahfa ryan@lahfa.xyz Reported-by: Christian Theune ct@flyingcircus.io Reported-by: Arnout Engelen arnout@bzzt.net Link: https://lkml.kernel.org/r/D4LHHUNLG79Y.12PI0X6BEHRHW@mbosch.me/ Acked-by: David Howells dhowells@redhat.com Cc: Al Viro viro@zeniv.linux.org.uk Cc: Christian Brauner brauner@kernel.org Cc: Matthew Wilcox (Oracle) willy@infradead.org Cc: stable@vger.kernel.org [6.12+] Signed-off-by: Andrew Morton akpm@linux-foundation.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- include/linux/iov_iter.h | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-)
--- a/include/linux/iov_iter.h +++ b/include/linux/iov_iter.h @@ -160,7 +160,7 @@ size_t iterate_folioq(struct iov_iter *i
do { struct folio *folio = folioq_folio(folioq, slot); - size_t part, remain, consumed; + size_t part, remain = 0, consumed; size_t fsize; void *base;
@@ -168,14 +168,16 @@ size_t iterate_folioq(struct iov_iter *i break;
fsize = folioq_folio_size(folioq, slot); - base = kmap_local_folio(folio, skip); - part = umin(len, PAGE_SIZE - skip % PAGE_SIZE); - remain = step(base, progress, part, priv, priv2); - kunmap_local(base); - consumed = part - remain; - len -= consumed; - progress += consumed; - skip += consumed; + if (skip < fsize) { + base = kmap_local_folio(folio, skip); + part = umin(len, PAGE_SIZE - skip % PAGE_SIZE); + remain = step(base, progress, part, priv, priv2); + kunmap_local(base); + consumed = part - remain; + len -= consumed; + progress += consumed; + skip += consumed; + } if (skip >= fsize) { skip = 0; slot++;
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Nicolin Chen nicolinc@nvidia.com
commit 685ca577b408ffd9c5a4057a2acc0cd3e6978b36 upstream.
The arm_smmu_attach_commit() updates master->ats_enabled before calling arm_smmu_remove_master_domain() that is supposed to clean up everything in the old domain, including the old domain's nr_ats_masters. So, it is supposed to use the old ats_enabled state of the device, not an updated state.
This isn't a problem if switching between two domains where: - old ats_enabled = false; new ats_enabled = false - old ats_enabled = true; new ats_enabled = true but can fail cases where: - old ats_enabled = false; new ats_enabled = true (old domain should keep the counter but incorrectly decreased it) - old ats_enabled = true; new ats_enabled = false (old domain needed to decrease the counter but incorrectly missed it)
Update master->ats_enabled after arm_smmu_remove_master_domain() to fix this.
Fixes: 7497f4211f4f ("iommu/arm-smmu-v3: Make changing domains be hitless for ATS") Cc: stable@vger.kernel.org Signed-off-by: Nicolin Chen nicolinc@nvidia.com Acked-by: Will Deacon will@kernel.org Reviewed-by: Jason Gunthorpe jgg@nvidia.com Reviewed-by: Pranjal Shrivastava praan@google.com Link: https://lore.kernel.org/r/20250801030127.2006979-1-nicolinc@nvidia.com Signed-off-by: Joerg Roedel joerg.roedel@amd.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
--- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c +++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c @@ -2997,9 +2997,9 @@ void arm_smmu_attach_commit(struct arm_s /* ATS is being switched off, invalidate the entire ATC */ arm_smmu_atc_inv_master(master, IOMMU_NO_PASID); } - master->ats_enabled = state->ats_enabled;
arm_smmu_remove_master_domain(master, state->old_domain, state->ssid); + master->ats_enabled = state->ats_enabled; }
static int arm_smmu_attach_dev(struct iommu_domain *domain, struct device *dev)
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sang-Heon Jeon ekffu200098@gmail.com
commit 63f5dec16760f2cd7d3f9034d18fc1fa0d83652f upstream.
damos_commit_ops_filters() incorrectly uses damos_nth_filter() which iterates core_filters. As a result, performing a commit unintentionally corrupts ops_filters.
Add damos_nth_ops_filter() which iterates ops_filters. Use this function to fix issues caused by wrong iteration.
Link: https://lkml.kernel.org/r/20250810124201.15743-1-ekffu200098@gmail.com Fixes: 3607cc590f18 ("mm/damon/core: support committing ops_filters") # 6.15.x Signed-off-by: Sang-Heon Jeon ekffu200098@gmail.com Reviewed-by: SeongJae Park sj@kernel.org Cc: stable@vger.kernel.org Signed-off-by: Andrew Morton akpm@linux-foundation.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- mm/damon/core.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-)
--- a/mm/damon/core.c +++ b/mm/damon/core.c @@ -843,6 +843,18 @@ static struct damos_filter *damos_nth_fi return NULL; }
+static struct damos_filter *damos_nth_ops_filter(int n, struct damos *s) +{ + struct damos_filter *filter; + int i = 0; + + damos_for_each_ops_filter(filter, s) { + if (i++ == n) + return filter; + } + return NULL; +} + static void damos_commit_filter_arg( struct damos_filter *dst, struct damos_filter *src) { @@ -906,7 +918,7 @@ static int damos_commit_ops_filters(stru int i = 0, j = 0;
damos_for_each_ops_filter_safe(dst_filter, next, dst) { - src_filter = damos_nth_filter(i++, src); + src_filter = damos_nth_ops_filter(i++, src); if (src_filter) damos_commit_filter(dst_filter, src_filter); else
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sai Krishna Potthuri sai.krishna.potthuri@amd.com
commit e251709aaddb3ee1e8ac1ed5e361a608a1cc92de upstream.
During SD suspend/resume without a full card rescan (when using non-removable SD cards for rootfs), the SD card initialization may fail after resume. This occurs because, after a host controller reset, the card detect logic may take time to stabilize due to debounce logic. Without waiting for stabilization, the host may attempt powering up the card prematurely, leading to command timeouts during resume flow. Add sdhci_arasan_set_power_and_bus_voltage() to wait for the card detect stable bit before power up the card. Since the stabilization time is not fixed, a maximum timeout of one second is used to ensure sufficient wait time for the card detect signal to stabilize.
Signed-off-by: Sai Krishna Potthuri sai.krishna.potthuri@amd.com Cc: stable@vger.kernel.org Link: https://lore.kernel.org/r/20250730060543.1735971-1-sai.krishna.potthuri@amd.... Signed-off-by: Ulf Hansson ulf.hansson@linaro.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/mmc/host/sdhci-of-arasan.c | 33 +++++++++++++++++++++++++++++++-- 1 file changed, 31 insertions(+), 2 deletions(-)
--- a/drivers/mmc/host/sdhci-of-arasan.c +++ b/drivers/mmc/host/sdhci-of-arasan.c @@ -99,6 +99,9 @@ #define HIWORD_UPDATE(val, mask, shift) \ ((val) << (shift) | (mask) << ((shift) + 16))
+#define CD_STABLE_TIMEOUT_US 1000000 +#define CD_STABLE_MAX_SLEEP_US 10 + /** * struct sdhci_arasan_soc_ctl_field - Field used in sdhci_arasan_soc_ctl_map * @@ -206,12 +209,15 @@ struct sdhci_arasan_data { * 19MHz instead */ #define SDHCI_ARASAN_QUIRK_CLOCK_25_BROKEN BIT(2) +/* Enable CD stable check before power-up */ +#define SDHCI_ARASAN_QUIRK_ENSURE_CD_STABLE BIT(3) };
struct sdhci_arasan_of_data { const struct sdhci_arasan_soc_ctl_map *soc_ctl_map; const struct sdhci_pltfm_data *pdata; const struct sdhci_arasan_clk_ops *clk_ops; + u32 quirks; };
static const struct sdhci_arasan_soc_ctl_map rk3399_soc_ctl_map = { @@ -514,6 +520,24 @@ static int sdhci_arasan_voltage_switch(s return -EINVAL; }
+static void sdhci_arasan_set_power_and_bus_voltage(struct sdhci_host *host, unsigned char mode, + unsigned short vdd) +{ + struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); + struct sdhci_arasan_data *sdhci_arasan = sdhci_pltfm_priv(pltfm_host); + u32 reg; + + /* + * Ensure that the card detect logic has stabilized before powering up, this is + * necessary after a host controller reset. + */ + if (mode == MMC_POWER_UP && sdhci_arasan->quirks & SDHCI_ARASAN_QUIRK_ENSURE_CD_STABLE) + read_poll_timeout(sdhci_readl, reg, reg & SDHCI_CD_STABLE, CD_STABLE_MAX_SLEEP_US, + CD_STABLE_TIMEOUT_US, false, host, SDHCI_PRESENT_STATE); + + sdhci_set_power_and_bus_voltage(host, mode, vdd); +} + static const struct sdhci_ops sdhci_arasan_ops = { .set_clock = sdhci_arasan_set_clock, .get_max_clock = sdhci_pltfm_clk_get_max_clock, @@ -521,7 +545,7 @@ static const struct sdhci_ops sdhci_aras .set_bus_width = sdhci_set_bus_width, .reset = sdhci_arasan_reset, .set_uhs_signaling = sdhci_set_uhs_signaling, - .set_power = sdhci_set_power_and_bus_voltage, + .set_power = sdhci_arasan_set_power_and_bus_voltage, .hw_reset = sdhci_arasan_hw_reset, };
@@ -570,7 +594,7 @@ static const struct sdhci_ops sdhci_aras .set_bus_width = sdhci_set_bus_width, .reset = sdhci_arasan_reset, .set_uhs_signaling = sdhci_set_uhs_signaling, - .set_power = sdhci_set_power_and_bus_voltage, + .set_power = sdhci_arasan_set_power_and_bus_voltage, .irq = sdhci_arasan_cqhci_irq, };
@@ -1447,6 +1471,7 @@ static const struct sdhci_arasan_clk_ops static struct sdhci_arasan_of_data sdhci_arasan_zynqmp_data = { .pdata = &sdhci_arasan_zynqmp_pdata, .clk_ops = &zynqmp_clk_ops, + .quirks = SDHCI_ARASAN_QUIRK_ENSURE_CD_STABLE, };
static const struct sdhci_arasan_clk_ops versal_clk_ops = { @@ -1457,6 +1482,7 @@ static const struct sdhci_arasan_clk_ops static struct sdhci_arasan_of_data sdhci_arasan_versal_data = { .pdata = &sdhci_arasan_zynqmp_pdata, .clk_ops = &versal_clk_ops, + .quirks = SDHCI_ARASAN_QUIRK_ENSURE_CD_STABLE, };
static const struct sdhci_arasan_clk_ops versal_net_clk_ops = { @@ -1467,6 +1493,7 @@ static const struct sdhci_arasan_clk_ops static struct sdhci_arasan_of_data sdhci_arasan_versal_net_data = { .pdata = &sdhci_arasan_versal_net_pdata, .clk_ops = &versal_net_clk_ops, + .quirks = SDHCI_ARASAN_QUIRK_ENSURE_CD_STABLE, };
static struct sdhci_arasan_of_data intel_keembay_emmc_data = { @@ -1945,6 +1972,8 @@ static int sdhci_arasan_probe(struct pla if (of_device_is_compatible(np, "rockchip,rk3399-sdhci-5.1")) sdhci_arasan_update_clockmultiplier(host, 0x0);
+ sdhci_arasan->quirks |= data->quirks; + if (of_device_is_compatible(np, "intel,keembay-sdhci-5.1-emmc") || of_device_is_compatible(np, "intel,keembay-sdhci-5.1-sd") || of_device_is_compatible(np, "intel,keembay-sdhci-5.1-sdio")) {
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Victor Shih victor.shih@genesyslogic.com.tw
commit dec8b38be4b35cae5f7fa086daf2631e2cfa09c1 upstream.
In preparation to fix replay timer timeout, add sdhci_gli_mask_replay_timer_timeout() function to simplify some of the code, allowing it to be re-used.
Signed-off-by: Victor Shih victor.shih@genesyslogic.com.tw Fixes: 1ae1d2d6e555 ("mmc: sdhci-pci-gli: Add Genesys Logic GL9763E support") Cc: stable@vger.kernel.org Acked-by: Adrian Hunter adrian.hunter@intel.com Link: https://lore.kernel.org/r/20250731065752.450231-2-victorshihgli@gmail.com Signed-off-by: Ulf Hansson ulf.hansson@linaro.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/mmc/host/sdhci-pci-gli.c | 30 ++++++++++++++++-------------- 1 file changed, 16 insertions(+), 14 deletions(-)
--- a/drivers/mmc/host/sdhci-pci-gli.c +++ b/drivers/mmc/host/sdhci-pci-gli.c @@ -287,6 +287,20 @@ #define GLI_MAX_TUNING_LOOP 40
/* Genesys Logic chipset */ +static void sdhci_gli_mask_replay_timer_timeout(struct pci_dev *pdev) +{ + int aer; + u32 value; + + /* mask the replay timer timeout of AER */ + aer = pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_ERR); + if (aer) { + pci_read_config_dword(pdev, aer + PCI_ERR_COR_MASK, &value); + value |= PCI_ERR_COR_REP_TIMER; + pci_write_config_dword(pdev, aer + PCI_ERR_COR_MASK, value); + } +} + static inline void gl9750_wt_on(struct sdhci_host *host) { u32 wt_value; @@ -607,7 +621,6 @@ static void gl9750_hw_setting(struct sdh { struct sdhci_pci_slot *slot = sdhci_priv(host); struct pci_dev *pdev; - int aer; u32 value;
pdev = slot->chip->pdev; @@ -626,12 +639,7 @@ static void gl9750_hw_setting(struct sdh pci_set_power_state(pdev, PCI_D0);
/* mask the replay timer timeout of AER */ - aer = pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_ERR); - if (aer) { - pci_read_config_dword(pdev, aer + PCI_ERR_COR_MASK, &value); - value |= PCI_ERR_COR_REP_TIMER; - pci_write_config_dword(pdev, aer + PCI_ERR_COR_MASK, value); - } + sdhci_gli_mask_replay_timer_timeout(pdev);
gl9750_wt_off(host); } @@ -806,7 +814,6 @@ static void sdhci_gl9755_set_clock(struc static void gl9755_hw_setting(struct sdhci_pci_slot *slot) { struct pci_dev *pdev = slot->chip->pdev; - int aer; u32 value;
gl9755_wt_on(pdev); @@ -841,12 +848,7 @@ static void gl9755_hw_setting(struct sdh pci_set_power_state(pdev, PCI_D0);
/* mask the replay timer timeout of AER */ - aer = pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_ERR); - if (aer) { - pci_read_config_dword(pdev, aer + PCI_ERR_COR_MASK, &value); - value |= PCI_ERR_COR_REP_TIMER; - pci_write_config_dword(pdev, aer + PCI_ERR_COR_MASK, value); - } + sdhci_gli_mask_replay_timer_timeout(pdev);
gl9755_wt_off(pdev); }
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Pasha Tatashin pasha.tatashin@soleen.com
commit 63b17b653df30e90f95338083cb44c35d64bcae4 upstream.
Patch series "Several KHO Hotfixes".
Three unrelated fixes for Kexec Handover.
This patch (of 3):
Lockdep shows the following warning:
INFO: trying to register non-static key. The code is fine but needs lockdep annotation, or maybe you didn't initialize this object before use? turning off the locking correctness validator.
[<ffffffff810133a6>] dump_stack_lvl+0x66/0xa0 [<ffffffff8136012c>] assign_lock_key+0x10c/0x120 [<ffffffff81358bb4>] register_lock_class+0xf4/0x2f0 [<ffffffff813597ff>] __lock_acquire+0x7f/0x2c40 [<ffffffff81360cb0>] ? __pfx_hlock_conflict+0x10/0x10 [<ffffffff811707be>] ? native_flush_tlb_global+0x8e/0xa0 [<ffffffff8117096e>] ? __flush_tlb_all+0x4e/0xa0 [<ffffffff81172fc2>] ? __kernel_map_pages+0x112/0x140 [<ffffffff813ec327>] ? xa_load_or_alloc+0x67/0xe0 [<ffffffff81359556>] lock_acquire+0xe6/0x280 [<ffffffff813ec327>] ? xa_load_or_alloc+0x67/0xe0 [<ffffffff8100b9e0>] _raw_spin_lock+0x30/0x40 [<ffffffff813ec327>] ? xa_load_or_alloc+0x67/0xe0 [<ffffffff813ec327>] xa_load_or_alloc+0x67/0xe0 [<ffffffff813eb4c0>] kho_preserve_folio+0x90/0x100 [<ffffffff813ebb7f>] __kho_finalize+0xcf/0x400 [<ffffffff813ebef4>] kho_finalize+0x34/0x70
This is becase xa has its own lock, that is not initialized in xa_load_or_alloc.
Modifiy __kho_preserve_order(), to properly call xa_init(&new_physxa->phys_bits);
Link: https://lkml.kernel.org/r/20250808201804.772010-2-pasha.tatashin@soleen.com Fixes: fc33e4b44b27 ("kexec: enable KHO support for memory preservation") Signed-off-by: Pasha Tatashin pasha.tatashin@soleen.com Acked-by: Mike Rapoport (Microsoft) rppt@kernel.org Cc: Alexander Graf graf@amazon.com Cc: Arnd Bergmann arnd@arndb.de Cc: Baoquan He bhe@redhat.com Cc: Changyuan Lyu changyuanl@google.com Cc: Coiby Xu coxu@redhat.com Cc: Dave Vasilevsky dave@vasilevsky.ca Cc: Eric Biggers ebiggers@google.com Cc: Kees Cook kees@kernel.org Cc: Pratyush Yadav pratyush@kernel.org Cc: stable@vger.kernel.org Signed-off-by: Andrew Morton akpm@linux-foundation.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- kernel/kexec_handover.c | 28 ++++++++++++++++++++++++---- 1 file changed, 24 insertions(+), 4 deletions(-)
diff --git a/kernel/kexec_handover.c b/kernel/kexec_handover.c index e49743ae52c5..65145972d6d6 100644 --- a/kernel/kexec_handover.c +++ b/kernel/kexec_handover.c @@ -144,14 +144,34 @@ static int __kho_preserve_order(struct kho_mem_track *track, unsigned long pfn, unsigned int order) { struct kho_mem_phys_bits *bits; - struct kho_mem_phys *physxa; + struct kho_mem_phys *physxa, *new_physxa; const unsigned long pfn_high = pfn >> order;
might_sleep();
- physxa = xa_load_or_alloc(&track->orders, order, sizeof(*physxa)); - if (IS_ERR(physxa)) - return PTR_ERR(physxa); + physxa = xa_load(&track->orders, order); + if (!physxa) { + int err; + + new_physxa = kzalloc(sizeof(*physxa), GFP_KERNEL); + if (!new_physxa) + return -ENOMEM; + + xa_init(&new_physxa->phys_bits); + physxa = xa_cmpxchg(&track->orders, order, NULL, new_physxa, + GFP_KERNEL); + + err = xa_err(physxa); + if (err || physxa) { + xa_destroy(&new_physxa->phys_bits); + kfree(new_physxa); + + if (err) + return err; + } else { + physxa = new_physxa; + } + }
bits = xa_load_or_alloc(&physxa->phys_bits, pfn_high / PRESERVE_BITS, sizeof(*bits));
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Pasha Tatashin pasha.tatashin@soleen.com
commit 8b66ed2c3f42cc462e05704af6b94e6a7bad2f5e upstream.
KHO uses struct pages for the preserved memory early in boot, however, with deferred struct page initialization, only a small portion of memory has properly initialized struct pages.
This problem was detected where vmemmap is poisoned, and illegal flag combinations are detected.
Don't allow them to be enabled together, and later we will have to teach KHO to work properly with deferred struct page init kernel feature.
Link: https://lkml.kernel.org/r/20250808201804.772010-3-pasha.tatashin@soleen.com Fixes: 4e1d010e3bda ("kexec: add config option for KHO") Signed-off-by: Pasha Tatashin pasha.tatashin@soleen.com Acked-by: Mike Rapoport (Microsoft) rppt@kernel.org Acked-by: Pratyush Yadav pratyush@kernel.org Cc: Alexander Graf graf@amazon.com Cc: Arnd Bergmann arnd@arndb.de Cc: Baoquan He bhe@redhat.com Cc: Changyuan Lyu changyuanl@google.com Cc: Coiby Xu coxu@redhat.com Cc: Dave Vasilevsky dave@vasilevsky.ca Cc: Eric Biggers ebiggers@google.com Cc: Kees Cook kees@kernel.org Cc: stable@vger.kernel.org Signed-off-by: Andrew Morton akpm@linux-foundation.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- kernel/Kconfig.kexec | 1 + 1 file changed, 1 insertion(+)
diff --git a/kernel/Kconfig.kexec b/kernel/Kconfig.kexec index 2ee603a98813..1224dd937df0 100644 --- a/kernel/Kconfig.kexec +++ b/kernel/Kconfig.kexec @@ -97,6 +97,7 @@ config KEXEC_JUMP config KEXEC_HANDOVER bool "kexec handover" depends on ARCH_SUPPORTS_KEXEC_HANDOVER && ARCH_SUPPORTS_KEXEC_FILE + depends on !DEFERRED_STRUCT_PAGE_INIT select MEMBLOCK_KHO_SCRATCH select KEXEC_FILE select DEBUG_FS
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Pasha Tatashin pasha.tatashin@soleen.com
commit 44958f2025ed3f29fc3e93bb1f6c16121d7847ad upstream.
During boot scratch area is allocated based on command line parameters or auto calculated. However, scratch area may fail to allocate, and in that case KHO is disabled. Currently, no warning is printed that KHO is disabled, which makes it confusing for the end user to figure out why KHO is not available. Add the missing warning message.
Link: https://lkml.kernel.org/r/20250808201804.772010-4-pasha.tatashin@soleen.com Signed-off-by: Pasha Tatashin pasha.tatashin@soleen.com Acked-by: Mike Rapoport (Microsoft) rppt@kernel.org Acked-by: Pratyush Yadav pratyush@kernel.org Cc: Alexander Graf graf@amazon.com Cc: Arnd Bergmann arnd@arndb.de Cc: Baoquan He bhe@redhat.com Cc: Changyuan Lyu changyuanl@google.com Cc: Coiby Xu coxu@redhat.com Cc: Dave Vasilevsky dave@vasilevsky.ca Cc: Eric Biggers ebiggers@google.com Cc: Kees Cook kees@kernel.org Cc: stable@vger.kernel.org Signed-off-by: Andrew Morton akpm@linux-foundation.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- kernel/kexec_handover.c | 1 + 1 file changed, 1 insertion(+)
diff --git a/kernel/kexec_handover.c b/kernel/kexec_handover.c index 65145972d6d6..ecd1ac210dbd 100644 --- a/kernel/kexec_handover.c +++ b/kernel/kexec_handover.c @@ -564,6 +564,7 @@ err_free_scratch_areas: err_free_scratch_desc: memblock_free(kho_scratch, kho_scratch_cnt * sizeof(*kho_scratch)); err_disable_kho: + pr_warn("Failed to reserve scratch area, disabling kexec handover\n"); kho_enable = false; }
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jiayi Li lijiayi@kylinos.cn
commit 99d7ab8db9d8230b243f5ed20ba0229e54cc0dfa upstream.
The existing memstick core patch: commit 62c59a8786e6 ("memstick: Skip allocating card when removing host") sets host->removing in memstick_remove_host(),but still exists a critical time window where memstick_check can run after host->eject is set but before removing is set.
In the rtsx_usb_ms driver, the problematic sequence is:
rtsx_usb_ms_drv_remove: memstick_check: host->eject = true cancel_work_sync(handle_req) if(!host->removing) ... memstick_alloc_card() memstick_set_rw_addr() memstick_new_req() rtsx_usb_ms_request() if(!host->eject) skip schedule_work wait_for_completion() memstick_remove_host: [blocks indefinitely] host->removing = true flush_workqueue() [block]
1. rtsx_usb_ms_drv_remove sets host->eject = true 2. cancel_work_sync(&host->handle_req) runs 3. memstick_check work may be executed here <-- danger window 4. memstick_remove_host sets removing = 1
During this window (step 3), memstick_check calls memstick_alloc_card, which may indefinitely waiting for mrq_complete completion that will never occur because rtsx_usb_ms_request sees eject=true and skips scheduling work, memstick_set_rw_addr waits forever for completion.
This causes a deadlock when memstick_remove_host tries to flush_workqueue, waiting for memstick_check to complete, while memstick_check is blocked waiting for mrq_complete completion.
Fix this by setting removing=true at the start of rtsx_usb_ms_drv_remove, before any work cancellation. This ensures memstick_check will see the removing flag immediately and exit early, avoiding the deadlock.
Fixes: 62c59a8786e6 ("memstick: Skip allocating card when removing host") Signed-off-by: Jiayi Li lijiayi@kylinos.cn Cc: stable@vger.kernel.org Link: https://lore.kernel.org/r/20250804013604.1311218-1-lijiayi@kylinos.cn Signed-off-by: Ulf Hansson ulf.hansson@linaro.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/memstick/core/memstick.c | 1 - drivers/memstick/host/rtsx_usb_ms.c | 1 + 2 files changed, 1 insertion(+), 1 deletion(-)
--- a/drivers/memstick/core/memstick.c +++ b/drivers/memstick/core/memstick.c @@ -555,7 +555,6 @@ EXPORT_SYMBOL(memstick_add_host); */ void memstick_remove_host(struct memstick_host *host) { - host->removing = 1; flush_workqueue(workqueue); mutex_lock(&host->lock); if (host->card) --- a/drivers/memstick/host/rtsx_usb_ms.c +++ b/drivers/memstick/host/rtsx_usb_ms.c @@ -812,6 +812,7 @@ static void rtsx_usb_ms_drv_remove(struc int err;
host->eject = true; + msh->removing = true; cancel_work_sync(&host->handle_req); cancel_delayed_work_sync(&host->poll_card);
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Victor Shih victor.shih@genesyslogic.com.tw
commit 340be332e420ed37d15d4169a1b4174e912ad6cb upstream.
Due to a flaw in the hardware design, the GL9763e replay timer frequently times out when ASPM is enabled. As a result, the warning messages will often appear in the system log when the system accesses the GL9763e PCI config. Therefore, the replay timer timeout must be masked.
Signed-off-by: Victor Shih victor.shih@genesyslogic.com.tw Fixes: 1ae1d2d6e555 ("mmc: sdhci-pci-gli: Add Genesys Logic GL9763E support") Cc: stable@vger.kernel.org Acked-by: Adrian Hunter adrian.hunter@intel.com Link: https://lore.kernel.org/r/20250731065752.450231-4-victorshihgli@gmail.com Signed-off-by: Ulf Hansson ulf.hansson@linaro.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/mmc/host/sdhci-pci-gli.c | 3 +++ 1 file changed, 3 insertions(+)
--- a/drivers/mmc/host/sdhci-pci-gli.c +++ b/drivers/mmc/host/sdhci-pci-gli.c @@ -1782,6 +1782,9 @@ static void gli_set_gl9763e(struct sdhci value |= FIELD_PREP(GLI_9763E_HS400_RXDLY, GLI_9763E_HS400_RXDLY_5); pci_write_config_dword(pdev, PCIE_GLI_9763E_CLKRXDLY, value);
+ /* mask the replay timer timeout of AER */ + sdhci_gli_mask_replay_timer_timeout(pdev); + pci_read_config_dword(pdev, PCIE_GLI_9763E_VHS, &value); value &= ~GLI_9763E_VHS_REV; value |= FIELD_PREP(GLI_9763E_VHS_REV, GLI_9763E_VHS_REV_R);
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Victor Shih victor.shih@genesyslogic.com.tw
commit 293ed0f5f34e1e9df888456af4b0a021f57b5f54 upstream.
In preparation to fix replay timer timeout, rename the gli_set_gl9763e() to gl9763e_hw_setting() for consistency.
Signed-off-by: Victor Shih victor.shih@genesyslogic.com.tw Fixes: 1ae1d2d6e555 ("mmc: sdhci-pci-gli: Add Genesys Logic GL9763E support") Cc: stable@vger.kernel.org Acked-by: Adrian Hunter adrian.hunter@intel.com Link: https://lore.kernel.org/r/20250731065752.450231-3-victorshihgli@gmail.com Signed-off-by: Ulf Hansson ulf.hansson@linaro.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/mmc/host/sdhci-pci-gli.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
--- a/drivers/mmc/host/sdhci-pci-gli.c +++ b/drivers/mmc/host/sdhci-pci-gli.c @@ -1753,7 +1753,7 @@ cleanup: return ret; }
-static void gli_set_gl9763e(struct sdhci_pci_slot *slot) +static void gl9763e_hw_setting(struct sdhci_pci_slot *slot) { struct pci_dev *pdev = slot->chip->pdev; u32 value; @@ -1928,7 +1928,7 @@ static int gli_probe_slot_gl9763e(struct gli_pcie_enable_msi(slot); host->mmc_host_ops.hs400_enhanced_strobe = gl9763e_hs400_enhanced_strobe; - gli_set_gl9763e(slot); + gl9763e_hw_setting(slot); sdhci_enable_v4_mode(host);
return 0;
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Judith Mendez jm@ti.com
commit d2d7a96b29ea6ab093973a1a37d26126db70c79f upstream.
This adds SDHCI_AM654_QUIRK_DISABLE_HS400 quirk which shall be used to disable HS400 support. AM62P SR1.0 and SR1.1 do not support HS400 due to errata i2458 [0] so disable HS400 for these SoC revisions.
[0] https://www.ti.com/lit/er/sprz574a/sprz574a.pdf Fixes: 37f28165518f ("arm64: dts: ti: k3-am62p: Add ITAP/OTAP values for MMC") Cc: stable@vger.kernel.org Signed-off-by: Judith Mendez jm@ti.com Reviewed-by: Andrew Davis afd@ti.com Acked-by: Adrian Hunter adrian.hunter@intel.com Link: https://lore.kernel.org/r/20250820193047.4064142-1-jm@ti.com Signed-off-by: Ulf Hansson ulf.hansson@linaro.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/mmc/host/sdhci_am654.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+)
--- a/drivers/mmc/host/sdhci_am654.c +++ b/drivers/mmc/host/sdhci_am654.c @@ -156,6 +156,7 @@ struct sdhci_am654_data {
#define SDHCI_AM654_QUIRK_FORCE_CDTEST BIT(0) #define SDHCI_AM654_QUIRK_SUPPRESS_V1P8_ENA BIT(1) +#define SDHCI_AM654_QUIRK_DISABLE_HS400 BIT(2) };
struct window { @@ -765,6 +766,7 @@ static int sdhci_am654_init(struct sdhci { struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); struct sdhci_am654_data *sdhci_am654 = sdhci_pltfm_priv(pltfm_host); + struct device *dev = mmc_dev(host->mmc); u32 ctl_cfg_2 = 0; u32 mask; u32 val; @@ -820,6 +822,12 @@ static int sdhci_am654_init(struct sdhci if (ret) goto err_cleanup_host;
+ if (sdhci_am654->quirks & SDHCI_AM654_QUIRK_DISABLE_HS400 && + host->mmc->caps2 & (MMC_CAP2_HS400 | MMC_CAP2_HS400_ES)) { + dev_info(dev, "HS400 mode not supported on this silicon revision, disabling it\n"); + host->mmc->caps2 &= ~(MMC_CAP2_HS400 | MMC_CAP2_HS400_ES); + } + ret = __sdhci_add_host(host); if (ret) goto err_cleanup_host; @@ -883,6 +891,12 @@ static int sdhci_am654_get_of_property(s return 0; }
+static const struct soc_device_attribute sdhci_am654_descope_hs400[] = { + { .family = "AM62PX", .revision = "SR1.0" }, + { .family = "AM62PX", .revision = "SR1.1" }, + { /* sentinel */ } +}; + static const struct of_device_id sdhci_am654_of_match[] = { { .compatible = "ti,am654-sdhci-5.1", @@ -975,6 +989,10 @@ static int sdhci_am654_probe(struct plat goto err_pltfm_free; }
+ soc = soc_device_match(sdhci_am654_descope_hs400); + if (soc) + sdhci_am654->quirks |= SDHCI_AM654_QUIRK_DISABLE_HS400; + host->mmc_host_ops.start_signal_voltage_switch = sdhci_am654_start_signal_voltage_switch; host->mmc_host_ops.execute_tuning = sdhci_am654_execute_tuning;
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Trond Myklebust trond.myklebust@hammerspace.com
commit 76d2e3890fb169168c73f2e4f8375c7cc24a765e upstream.
After nfs_lock_and_join_requests() tests for whether the request is still attached to the mapping, nothing prevents a call to nfs_inode_remove_request() from succeeding until we actually lock the page group. The reason is that whoever called nfs_inode_remove_request() doesn't necessarily have a lock on the page group head.
So in order to avoid races, let's take the page group lock earlier in nfs_lock_and_join_requests(), and hold it across the removal of the request in nfs_inode_remove_request().
Reported-by: Jeff Layton jlayton@kernel.org Tested-by: Joe Quanaim jdq@meta.com Tested-by: Andrew Steffen aksteffen@meta.com Reviewed-by: Jeff Layton jlayton@kernel.org Fixes: bd37d6fce184 ("NFSv4: Convert nfs_lock_and_join_requests() to use nfs_page_find_head_request()") Cc: stable@vger.kernel.org Signed-off-by: Trond Myklebust trond.myklebust@hammerspace.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- fs/nfs/pagelist.c | 9 +++++---- fs/nfs/write.c | 29 ++++++++++------------------- include/linux/nfs_page.h | 1 + 3 files changed, 16 insertions(+), 23 deletions(-)
--- a/fs/nfs/pagelist.c +++ b/fs/nfs/pagelist.c @@ -253,13 +253,14 @@ nfs_page_group_unlock(struct nfs_page *r nfs_page_clear_headlock(req); }
-/* - * nfs_page_group_sync_on_bit_locked +/** + * nfs_page_group_sync_on_bit_locked - Test if all requests have @bit set + * @req: request in page group + * @bit: PG_* bit that is used to sync page group * * must be called with page group lock held */ -static bool -nfs_page_group_sync_on_bit_locked(struct nfs_page *req, unsigned int bit) +bool nfs_page_group_sync_on_bit_locked(struct nfs_page *req, unsigned int bit) { struct nfs_page *head = req->wb_head; struct nfs_page *tmp; --- a/fs/nfs/write.c +++ b/fs/nfs/write.c @@ -153,20 +153,10 @@ nfs_page_set_inode_ref(struct nfs_page * } }
-static int -nfs_cancel_remove_inode(struct nfs_page *req, struct inode *inode) +static void nfs_cancel_remove_inode(struct nfs_page *req, struct inode *inode) { - int ret; - - if (!test_bit(PG_REMOVE, &req->wb_flags)) - return 0; - ret = nfs_page_group_lock(req); - if (ret) - return ret; if (test_and_clear_bit(PG_REMOVE, &req->wb_flags)) nfs_page_set_inode_ref(req, inode); - nfs_page_group_unlock(req); - return 0; }
/** @@ -585,19 +575,18 @@ retry: } }
+ ret = nfs_page_group_lock(head); + if (ret < 0) + goto out_unlock; + /* Ensure that nobody removed the request before we locked it */ if (head != folio->private) { + nfs_page_group_unlock(head); nfs_unlock_and_release_request(head); goto retry; }
- ret = nfs_cancel_remove_inode(head, inode); - if (ret < 0) - goto out_unlock; - - ret = nfs_page_group_lock(head); - if (ret < 0) - goto out_unlock; + nfs_cancel_remove_inode(head, inode);
/* lock each request in the page group */ for (subreq = head->wb_this_page; @@ -786,7 +775,8 @@ static void nfs_inode_remove_request(str { struct nfs_inode *nfsi = NFS_I(nfs_page_to_inode(req));
- if (nfs_page_group_sync_on_bit(req, PG_REMOVE)) { + nfs_page_group_lock(req); + if (nfs_page_group_sync_on_bit_locked(req, PG_REMOVE)) { struct folio *folio = nfs_page_to_folio(req->wb_head); struct address_space *mapping = folio->mapping;
@@ -798,6 +788,7 @@ static void nfs_inode_remove_request(str } spin_unlock(&mapping->i_private_lock); } + nfs_page_group_unlock(req);
if (test_and_clear_bit(PG_INODE_REF, &req->wb_flags)) { atomic_long_dec(&nfsi->nrequests); --- a/include/linux/nfs_page.h +++ b/include/linux/nfs_page.h @@ -160,6 +160,7 @@ extern void nfs_join_page_group(struct n extern int nfs_page_group_lock(struct nfs_page *); extern void nfs_page_group_unlock(struct nfs_page *); extern bool nfs_page_group_sync_on_bit(struct nfs_page *, unsigned int); +extern bool nfs_page_group_sync_on_bit_locked(struct nfs_page *, unsigned int); extern int nfs_page_set_headlock(struct nfs_page *req); extern void nfs_page_clear_headlock(struct nfs_page *req); extern bool nfs_async_iocounter_wait(struct rpc_task *, struct nfs_lock_context *);
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Phillip Lougher phillip@squashfs.org.uk
commit b64700d41bdc4e9f82f1346c15a3678ebb91a89c upstream.
If sb_min_blocksize returns 0, squashfs_fill_super exits without freeing allocated memory (sb->s_fs_info).
Fix this by moving the call to sb_min_blocksize to before memory is allocated.
Link: https://lkml.kernel.org/r/20250811223740.110392-1-phillip@squashfs.org.uk Fixes: 734aa85390ea ("Squashfs: check return result of sb_min_blocksize") Signed-off-by: Phillip Lougher phillip@squashfs.org.uk Reported-by: Scott GUO scottzhguo@tencent.com Closes: https://lore.kernel.org/all/20250811061921.3807353-1-scott_gzh@163.com Cc: stable@vger.kernel.org Signed-off-by: Andrew Morton akpm@linux-foundation.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- fs/squashfs/super.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-)
--- a/fs/squashfs/super.c +++ b/fs/squashfs/super.c @@ -187,10 +187,15 @@ static int squashfs_fill_super(struct su unsigned short flags; unsigned int fragments; u64 lookup_table_start, xattr_id_table_start, next_table; - int err; + int err, devblksize = sb_min_blocksize(sb, SQUASHFS_DEVBLK_SIZE);
TRACE("Entered squashfs_fill_superblock\n");
+ if (!devblksize) { + errorf(fc, "squashfs: unable to set blocksize\n"); + return -EINVAL; + } + sb->s_fs_info = kzalloc(sizeof(*msblk), GFP_KERNEL); if (sb->s_fs_info == NULL) { ERROR("Failed to allocate squashfs_sb_info\n"); @@ -201,12 +206,7 @@ static int squashfs_fill_super(struct su
msblk->panic_on_errors = (opts->errors == Opt_errors_panic);
- msblk->devblksize = sb_min_blocksize(sb, SQUASHFS_DEVBLK_SIZE); - if (!msblk->devblksize) { - errorf(fc, "squashfs: unable to set blocksize\n"); - return -EINVAL; - } - + msblk->devblksize = devblksize; msblk->devblksize_log2 = ffz(~msblk->devblksize);
mutex_init(&msblk->meta_index_mutex);
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sang-Heon Jeon ekffu200098@gmail.com
commit b3dee902b6c26b7d8031a4df19753e27dcfcba01 upstream.
Current damos_commit_filter() does not persist the `allow' value of the filter. As a result, changing the `allow' value of a filter and committing doesn't change the `allow' value.
Add the missing `allow' value update, so committing the filter persistently changes the `allow' value well.
Link: https://lkml.kernel.org/r/20250816015116.194589-1-ekffu200098@gmail.com Fixes: fe6d7fdd6249 ("mm/damon/core: add damos_filter->allow field") Signed-off-by: Sang-Heon Jeon ekffu200098@gmail.com Reviewed-by: SeongJae Park sj@kernel.org Cc: stable@vger.kernel.org [6.14.x] Signed-off-by: Andrew Morton akpm@linux-foundation.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- mm/damon/core.c | 1 + 1 file changed, 1 insertion(+)
--- a/mm/damon/core.c +++ b/mm/damon/core.c @@ -881,6 +881,7 @@ static void damos_commit_filter( { dst->type = src->type; dst->matching = src->matching; + dst->allow = src->allow; damos_commit_filter_arg(dst, src); }
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Herton R. Krzesinski herton@redhat.com
commit dde30854bddfb5d69f30022b53c5955a41088b33 upstream.
The mm/debug_vm_pagetable test allocates manually page table entries for the tests it runs, using also its manually allocated mm_struct. That in itself is ok, but when it exits, at destroy_args() it fails to clear those entries with the *_clear functions.
The problem is that leaves stale entries. If another process allocates an mm_struct with a pgd at the same address, it may end up running into the stale entry. This is happening in practice on a debug kernel with CONFIG_DEBUG_VM_PGTABLE=y, for example this is the output with some extra debugging I added (it prints a warning trace if pgtables_bytes goes negative, in addition to the warning at check_mm() function):
[ 2.539353] debug_vm_pgtable: [get_random_vaddr ]: random_vaddr is 0x7ea247140000 [ 2.539366] kmem_cache info [ 2.539374] kmem_cachep 0x000000002ce82385 - freelist 0x0000000000000000 - offset 0x508 [ 2.539447] debug_vm_pgtable: [init_args ]: args->mm is 0x000000002267cc9e (...) [ 2.552800] WARNING: CPU: 5 PID: 116 at include/linux/mm.h:2841 free_pud_range+0x8bc/0x8d0 [ 2.552816] Modules linked in: [ 2.552843] CPU: 5 UID: 0 PID: 116 Comm: modprobe Not tainted 6.12.0-105.debug_vm2.el10.ppc64le+debug #1 VOLUNTARY [ 2.552859] Hardware name: IBM,9009-41A POWER9 (architected) 0x4e0202 0xf000005 of:IBM,FW910.00 (VL910_062) hv:phyp pSeries [ 2.552872] NIP: c0000000007eef3c LR: c0000000007eef30 CTR: c0000000003d8c90 [ 2.552885] REGS: c0000000622e73b0 TRAP: 0700 Not tainted (6.12.0-105.debug_vm2.el10.ppc64le+debug) [ 2.552899] MSR: 800000000282b033 <SF,VEC,VSX,EE,FP,ME,IR,DR,RI,LE> CR: 24002822 XER: 0000000a [ 2.552954] CFAR: c0000000008f03f0 IRQMASK: 0 [ 2.552954] GPR00: c0000000007eef30 c0000000622e7650 c000000002b1ac00 0000000000000001 [ 2.552954] GPR04: 0000000000000008 0000000000000000 c0000000007eef30 ffffffffffffffff [ 2.552954] GPR08: 00000000ffff00f5 0000000000000001 0000000000000048 0000000000004000 [ 2.552954] GPR12: 00000003fa440000 c000000017ffa300 c0000000051d9f80 ffffffffffffffdb [ 2.552954] GPR16: 0000000000000000 0000000000000008 000000000000000a 60000000000000e0 [ 2.552954] GPR20: 4080000000000000 c0000000113af038 00007fffcf130000 0000700000000000 [ 2.552954] GPR24: c000000062a6a000 0000000000000001 8000000062a68000 0000000000000001 [ 2.552954] GPR28: 000000000000000a c000000062ebc600 0000000000002000 c000000062ebc760 [ 2.553170] NIP [c0000000007eef3c] free_pud_range+0x8bc/0x8d0 [ 2.553185] LR [c0000000007eef30] free_pud_range+0x8b0/0x8d0 [ 2.553199] Call Trace: [ 2.553207] [c0000000622e7650] [c0000000007eef30] free_pud_range+0x8b0/0x8d0 (unreliable) [ 2.553229] [c0000000622e7750] [c0000000007f40b4] free_pgd_range+0x284/0x3b0 [ 2.553248] [c0000000622e7800] [c0000000007f4630] free_pgtables+0x450/0x570 [ 2.553274] [c0000000622e78e0] [c0000000008161c0] exit_mmap+0x250/0x650 [ 2.553292] [c0000000622e7a30] [c0000000001b95b8] __mmput+0x98/0x290 [ 2.558344] [c0000000622e7a80] [c0000000001d1018] exit_mm+0x118/0x1b0 [ 2.558361] [c0000000622e7ac0] [c0000000001d141c] do_exit+0x2ec/0x870 [ 2.558376] [c0000000622e7b60] [c0000000001d1ca8] do_group_exit+0x88/0x150 [ 2.558391] [c0000000622e7bb0] [c0000000001d1db8] sys_exit_group+0x48/0x50 [ 2.558407] [c0000000622e7be0] [c00000000003d810] system_call_exception+0x1e0/0x4c0 [ 2.558423] [c0000000622e7e50] [c00000000000d05c] system_call_vectored_common+0x15c/0x2ec (...) [ 2.558892] ---[ end trace 0000000000000000 ]--- [ 2.559022] BUG: Bad rss-counter state mm:000000002267cc9e type:MM_ANONPAGES val:1 [ 2.559037] BUG: non-zero pgtables_bytes on freeing mm: -6144
Here the modprobe process ended up with an allocated mm_struct from the mm_struct slab that was used before by the debug_vm_pgtable test. That is not a problem, since the mm_struct is initialized again etc., however, if it ends up using the same pgd table, it bumps into the old stale entry when clearing/freeing the page table entries, so it tries to free an entry already gone (that one which was allocated by the debug_vm_pgtable test), which also explains the negative pgtables_bytes since it's accounting for not allocated entries in the current process.
As far as I looked pgd_{alloc,free} etc. does not clear entries, and clearing of the entries is explicitly done in the free_pgtables-> free_pgd_range->free_p4d_range->free_pud_range->free_pmd_range-> free_pte_range path. However, the debug_vm_pgtable test does not call free_pgtables, since it allocates mm_struct and entries manually for its test and eg. not goes through page faults. So it also should clear manually the entries before exit at destroy_args().
This problem was noticed on a reboot X number of times test being done on a powerpc host, with a debug kernel with CONFIG_DEBUG_VM_PGTABLE enabled. Depends on the system, but on a 100 times reboot loop the problem could manifest once or twice, if a process ends up getting the right mm->pgd entry with the stale entries used by mm/debug_vm_pagetable. After using this patch, I couldn't reproduce/experience the problems anymore. I was able to reproduce the problem as well on latest upstream kernel (6.16).
I also modified destroy_args() to use mmput() instead of mmdrop(), there is no reason to hold mm_users reference and not release the mm_struct entirely, and in the output above with my debugging prints I already had patched it to use mmput, it did not fix the problem, but helped in the debugging as well.
Link: https://lkml.kernel.org/r/20250731214051.4115182-1-herton@redhat.com Fixes: 3c9b84f044a9 ("mm/debug_vm_pgtable: introduce struct pgtable_debug_args") Signed-off-by: Herton R. Krzesinski herton@redhat.com Cc: Anshuman Khandual anshuman.khandual@arm.com Cc: Christophe Leroy christophe.leroy@csgroup.eu Cc: Gavin Shan gshan@redhat.com Cc: Gerald Schaefer gerald.schaefer@linux.ibm.com Cc: stable@vger.kernel.org Signed-off-by: Andrew Morton akpm@linux-foundation.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- mm/debug_vm_pgtable.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-)
--- a/mm/debug_vm_pgtable.c +++ b/mm/debug_vm_pgtable.c @@ -1041,29 +1041,34 @@ static void __init destroy_args(struct p
/* Free page table entries */ if (args->start_ptep) { + pmd_clear(args->pmdp); pte_free(args->mm, args->start_ptep); mm_dec_nr_ptes(args->mm); }
if (args->start_pmdp) { + pud_clear(args->pudp); pmd_free(args->mm, args->start_pmdp); mm_dec_nr_pmds(args->mm); }
if (args->start_pudp) { + p4d_clear(args->p4dp); pud_free(args->mm, args->start_pudp); mm_dec_nr_puds(args->mm); }
- if (args->start_p4dp) + if (args->start_p4dp) { + pgd_clear(args->pgdp); p4d_free(args->mm, args->start_p4dp); + }
/* Free vma and mm struct */ if (args->vma) vm_area_free(args->vma);
if (args->mm) - mmdrop(args->mm); + mmput(args->mm); }
static struct page * __init
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jinjiang Tu tujinjiang@huawei.com
commit 2e6053fea379806269c4f7f5e36b523c9c0fb35c upstream.
When memory_failure() is called for a already hwpoisoned pfn, kill_accessing_process() will be called to kill current task. However, if the vma of the accessing vaddr is VM_PFNMAP, walk_page_range() will skip the vma in walk_page_test() and return 0.
Before commit aaf99ac2ceb7 ("mm/hwpoison: do not send SIGBUS to processes with recovered clean pages"), kill_accessing_process() will return EFAULT. For x86, the current task will be killed in kill_me_maybe().
However, after this commit, kill_accessing_process() simplies return 0, that means UCE is handled properly, but it doesn't actually. In such case, the user task will trigger UCE infinitely.
To fix it, add .test_walk callback for hwpoison_walk_ops to scan all vmas.
Link: https://lkml.kernel.org/r/20250815073209.1984582-1-tujinjiang@huawei.com Fixes: aaf99ac2ceb7 ("mm/hwpoison: do not send SIGBUS to processes with recovered clean pages") Signed-off-by: Jinjiang Tu tujinjiang@huawei.com Acked-by: David Hildenbrand david@redhat.com Acked-by: Miaohe Lin linmiaohe@huawei.com Reviewed-by: Jane Chu jane.chu@oracle.com Cc: Kefeng Wang wangkefeng.wang@huawei.com Cc: Naoya Horiguchi nao.horiguchi@gmail.com Cc: Oscar Salvador osalvador@suse.de Cc: Shuai Xue xueshuai@linux.alibaba.com Cc: Zi Yan ziy@nvidia.com Cc: stable@vger.kernel.org Signed-off-by: Andrew Morton akpm@linux-foundation.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- mm/memory-failure.c | 8 ++++++++ 1 file changed, 8 insertions(+)
--- a/mm/memory-failure.c +++ b/mm/memory-failure.c @@ -847,9 +847,17 @@ static int hwpoison_hugetlb_range(pte_t #define hwpoison_hugetlb_range NULL #endif
+static int hwpoison_test_walk(unsigned long start, unsigned long end, + struct mm_walk *walk) +{ + /* We also want to consider pages mapped into VM_PFNMAP. */ + return 0; +} + static const struct mm_walk_ops hwpoison_walk_ops = { .pmd_entry = hwpoison_pte_range, .hugetlb_entry = hwpoison_hugetlb_range, + .test_walk = hwpoison_test_walk, .walk_lock = PGWALK_RDLOCK, };
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: David Hildenbrand david@redhat.com
commit 772e5b4a5e8360743645b9a466842d16092c4f94 upstream.
Registering userfaultd on a VMA that spans at least one PMD and then mremap()'ing that VMA can trigger a WARN when recovering from a failed page table move due to a page table allocation error.
The code ends up doing the right thing (recurse, avoiding moving actual page tables), but triggering that WARN is unpleasant:
WARNING: CPU: 2 PID: 6133 at mm/mremap.c:357 move_normal_pmd mm/mremap.c:357 [inline] WARNING: CPU: 2 PID: 6133 at mm/mremap.c:357 move_pgt_entry mm/mremap.c:595 [inline] WARNING: CPU: 2 PID: 6133 at mm/mremap.c:357 move_page_tables+0x3832/0x44a0 mm/mremap.c:852 Modules linked in: CPU: 2 UID: 0 PID: 6133 Comm: syz.0.19 Not tainted 6.17.0-rc1-syzkaller-00004-g53e760d89498 #0 PREEMPT(full) Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 1.16.3-debian-1.16.3-2~bpo12+1 04/01/2014 RIP: 0010:move_normal_pmd mm/mremap.c:357 [inline] RIP: 0010:move_pgt_entry mm/mremap.c:595 [inline] RIP: 0010:move_page_tables+0x3832/0x44a0 mm/mremap.c:852 Code: ... RSP: 0018:ffffc900037a76d8 EFLAGS: 00010293 RAX: 0000000000000000 RBX: 0000000032930007 RCX: ffffffff820c6645 RDX: ffff88802e56a440 RSI: ffffffff820c7201 RDI: 0000000000000007 RBP: ffff888037728fc0 R08: 0000000000000007 R09: 0000000000000000 R10: 0000000032930007 R11: 0000000000000000 R12: 0000000000000000 R13: ffffc900037a79a8 R14: 0000000000000001 R15: dffffc0000000000 FS: 000055556316a500(0000) GS:ffff8880d68bc000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: 0000001b30863fff CR3: 0000000050171000 CR4: 0000000000352ef0 Call Trace: <TASK> copy_vma_and_data+0x468/0x790 mm/mremap.c:1215 move_vma+0x548/0x1780 mm/mremap.c:1282 mremap_to+0x1b7/0x450 mm/mremap.c:1406 do_mremap+0xfad/0x1f80 mm/mremap.c:1921 __do_sys_mremap+0x119/0x170 mm/mremap.c:1977 do_syscall_x64 arch/x86/entry/syscall_64.c:63 [inline] do_syscall_64+0xcd/0x4c0 arch/x86/entry/syscall_64.c:94 entry_SYSCALL_64_after_hwframe+0x77/0x7f RIP: 0033:0x7f00d0b8ebe9 Code: ... RSP: 002b:00007ffe5ea5ee98 EFLAGS: 00000246 ORIG_RAX: 0000000000000019 RAX: ffffffffffffffda RBX: 00007f00d0db5fa0 RCX: 00007f00d0b8ebe9 RDX: 0000000000400000 RSI: 0000000000c00000 RDI: 0000200000000000 RBP: 00007ffe5ea5eef0 R08: 0000200000c00000 R09: 0000000000000000 R10: 0000000000000003 R11: 0000000000000246 R12: 0000000000000002 R13: 00007f00d0db5fa0 R14: 00007f00d0db5fa0 R15: 0000000000000005 </TASK>
The underlying issue is that we recurse during the original page table move, but not during the recovery move.
Fix it by checking for both VMAs and performing the check before the pmd_none() sanity check.
Add a new helper where we perform+document that check for the PMD and PUD level.
Thanks to Harry for bisecting.
Link: https://lkml.kernel.org/r/20250818175358.1184757-1-david@redhat.com Fixes: 0cef0bb836e3 ("mm: clear uffd-wp PTE/PMD state on mremap()") Signed-off-by: David Hildenbrand david@redhat.com Reported-by: syzbot+4d9a13f0797c46a29e42@syzkaller.appspotmail.com Closes: https://lkml.kernel.org/r/689bb893.050a0220.7f033.013a.GAE@google.com Tested-by: Harry Yoo harry.yoo@oracle.com Cc: "Liam R. Howlett" Liam.Howlett@oracle.com Cc: Lorenzo Stoakes lorenzo.stoakes@oracle.com Cc: Vlastimil Babka vbabka@suse.cz Cc: Jann Horn jannh@google.com Cc: Pedro Falcato pfalcato@suse.de Cc: stable@vger.kernel.org Signed-off-by: Andrew Morton akpm@linux-foundation.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- mm/mremap.c | 41 +++++++++++++++++++++++------------------ 1 file changed, 23 insertions(+), 18 deletions(-)
--- a/mm/mremap.c +++ b/mm/mremap.c @@ -294,6 +294,25 @@ static inline bool arch_supports_page_ta } #endif
+static inline bool uffd_supports_page_table_move(struct pagetable_move_control *pmc) +{ + /* + * If we are moving a VMA that has uffd-wp registered but with + * remap events disabled (new VMA will not be registered with uffd), we + * need to ensure that the uffd-wp state is cleared from all pgtables. + * This means recursing into lower page tables in move_page_tables(). + * + * We might get called with VMAs reversed when recovering from a + * failed page table move. In that case, the + * "old"-but-actually-"originally new" VMA during recovery will not have + * a uffd context. Recursing into lower page tables during the original + * move but not during the recovery move will cause trouble, because we + * run into already-existing page tables. So check both VMAs. + */ + return !vma_has_uffd_without_event_remap(pmc->old) && + !vma_has_uffd_without_event_remap(pmc->new); +} + #ifdef CONFIG_HAVE_MOVE_PMD static bool move_normal_pmd(struct pagetable_move_control *pmc, pmd_t *old_pmd, pmd_t *new_pmd) @@ -306,6 +325,8 @@ static bool move_normal_pmd(struct paget
if (!arch_supports_page_table_move()) return false; + if (!uffd_supports_page_table_move(pmc)) + return false; /* * The destination pmd shouldn't be established, free_pgtables() * should have released it. @@ -332,15 +353,6 @@ static bool move_normal_pmd(struct paget if (WARN_ON_ONCE(!pmd_none(*new_pmd))) return false;
- /* If this pmd belongs to a uffd vma with remap events disabled, we need - * to ensure that the uffd-wp state is cleared from all pgtables. This - * means recursing into lower page tables in move_page_tables(), and we - * can reuse the existing code if we simply treat the entry as "not - * moved". - */ - if (vma_has_uffd_without_event_remap(vma)) - return false; - /* * We don't have to worry about the ordering of src and dst * ptlocks because exclusive mmap_lock prevents deadlock. @@ -389,6 +401,8 @@ static bool move_normal_pud(struct paget
if (!arch_supports_page_table_move()) return false; + if (!uffd_supports_page_table_move(pmc)) + return false; /* * The destination pud shouldn't be established, free_pgtables() * should have released it. @@ -396,15 +410,6 @@ static bool move_normal_pud(struct paget if (WARN_ON_ONCE(!pud_none(*new_pud))) return false;
- /* If this pud belongs to a uffd vma with remap events disabled, we need - * to ensure that the uffd-wp state is cleared from all pgtables. This - * means recursing into lower page tables in move_page_tables(), and we - * can reuse the existing code if we simply treat the entry as "not - * moved". - */ - if (vma_has_uffd_without_event_remap(vma)) - return false; - /* * We don't have to worry about the ordering of src and dst * ptlocks because exclusive mmap_lock prevents deadlock.
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Takashi Iwai tiwai@suse.de
commit 3f4422e7c9436abf81a00270be7e4d6d3760ec0e upstream.
During the conversion to unify the calibration data management, the reference to tasdevice_priv was wrongly set to h->hda_priv instead of h->priv. This resulted in memory corruption and crashes eventually. Unfortunately it's a void pointer, hence the compiler couldn't know that it's wrong.
Fixes: 4fe238513407 ("ALSA: hda/tas2781: Move and unified the calibrated-data getting function for SPI and I2C into the tas2781_hda lib") Link: https://bugzilla.suse.com/show_bug.cgi?id=1248270 Cc: stable@vger.kernel.org Link: https://patch.msgid.link/20250820051902.4523-1-tiwai@suse.de Signed-off-by: Takashi Iwai tiwai@suse.de Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- sound/pci/hda/tas2781_hda_i2c.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
--- a/sound/pci/hda/tas2781_hda_i2c.c +++ b/sound/pci/hda/tas2781_hda_i2c.c @@ -287,7 +287,7 @@ static int tas2563_save_calibration(stru efi_char16_t efi_name[TAS2563_CAL_VAR_NAME_MAX]; unsigned long max_size = TAS2563_CAL_DATA_SIZE; unsigned char var8[TAS2563_CAL_VAR_NAME_MAX]; - struct tasdevice_priv *p = h->hda_priv; + struct tasdevice_priv *p = h->priv; struct calidata *cd = &p->cali_data; struct cali_reg *r = &cd->cali_reg_array; unsigned int offset = 0;
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Evgeniy Harchenko evgeniyharchenko.dev@gmail.com
commit eafae0fdd115a71b3a200ef1a31f86da04bac77f upstream.
The HP EliteBook x360 830 G6 and HP EliteBook 830 G6 have Realtek HDA codec ALC215. It needs the ALC285_FIXUP_HP_GPIO_LED quirk to enable the mute LED.
Cc: stable@vger.kernel.org Signed-off-by: Evgeniy Harchenko evgeniyharchenko.dev@gmail.com Link: https://patch.msgid.link/20250815095814.75845-1-evgeniyharchenko.dev@gmail.c... Signed-off-by: Takashi Iwai tiwai@suse.de Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- sound/pci/hda/patch_realtek.c | 2 ++ 1 file changed, 2 insertions(+)
--- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -10662,6 +10662,8 @@ static const struct hda_quirk alc269_fix SND_PCI_QUIRK(0x103c, 0x84e7, "HP Pavilion 15", ALC269_FIXUP_HP_MUTE_LED_MIC3), SND_PCI_QUIRK(0x103c, 0x8519, "HP Spectre x360 15-df0xxx", ALC285_FIXUP_HP_SPECTRE_X360), SND_PCI_QUIRK(0x103c, 0x8537, "HP ProBook 440 G6", ALC236_FIXUP_HP_MUTE_LED_MICMUTE_VREF), + SND_PCI_QUIRK(0x103c, 0x8548, "HP EliteBook x360 830 G6", ALC285_FIXUP_HP_GPIO_LED), + SND_PCI_QUIRK(0x103c, 0x854a, "HP EliteBook 830 G6", ALC285_FIXUP_HP_GPIO_LED), SND_PCI_QUIRK(0x103c, 0x85c6, "HP Pavilion x360 Convertible 14-dy1xxx", ALC295_FIXUP_HP_MUTE_LED_COEFBIT11), SND_PCI_QUIRK(0x103c, 0x85de, "HP Envy x360 13-ar0xxx", ALC285_FIXUP_HP_ENVY_X360), SND_PCI_QUIRK(0x103c, 0x860f, "HP ZBook 15 G6", ALC285_FIXUP_HP_GPIO_AMP_INIT),
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Zhu Yanjun yanjun.zhu@linux.dev
commit 3c3e9a9f2972b364e8c2cfbfdeb23c6d6be4f87f upstream.
When skb packets are sent out, these skb packets still depends on the rxe resources, for example, QP, sk, when these packets are destroyed.
If these rxe resources are released when the skb packets are destroyed, the call traces will appear.
To avoid skb packets hang too long time in some network devices, a timestamp is added when these skb packets are created. If these skb packets hang too long time in network devices, these network devices can free these skb packets to release rxe resources.
Reported-by: syzbot+8425ccfb599521edb153@syzkaller.appspotmail.com Closes: https://syzkaller.appspot.com/bug?extid=8425ccfb599521edb153 Tested-by: syzbot+8425ccfb599521edb153@syzkaller.appspotmail.com Fixes: 1a633bdc8fd9 ("RDMA/rxe: Let destroy qp succeed with stuck packet") Signed-off-by: Zhu Yanjun yanjun.zhu@linux.dev Link: https://patch.msgid.link/20250726013104.463570-1-yanjun.zhu@linux.dev Signed-off-by: Leon Romanovsky leon@kernel.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/infiniband/sw/rxe/rxe_net.c | 29 ++++++++--------------------- drivers/infiniband/sw/rxe/rxe_qp.c | 2 +- 2 files changed, 9 insertions(+), 22 deletions(-)
--- a/drivers/infiniband/sw/rxe/rxe_net.c +++ b/drivers/infiniband/sw/rxe/rxe_net.c @@ -345,33 +345,15 @@ int rxe_prepare(struct rxe_av *av, struc
static void rxe_skb_tx_dtor(struct sk_buff *skb) { - struct net_device *ndev = skb->dev; - struct rxe_dev *rxe; - unsigned int qp_index; - struct rxe_qp *qp; + struct rxe_qp *qp = skb->sk->sk_user_data; int skb_out;
- rxe = rxe_get_dev_from_net(ndev); - if (!rxe && is_vlan_dev(ndev)) - rxe = rxe_get_dev_from_net(vlan_dev_real_dev(ndev)); - if (WARN_ON(!rxe)) - return; - - qp_index = (int)(uintptr_t)skb->sk->sk_user_data; - if (!qp_index) - return; - - qp = rxe_pool_get_index(&rxe->qp_pool, qp_index); - if (!qp) - goto put_dev; - skb_out = atomic_dec_return(&qp->skb_out); - if (qp->need_req_skb && skb_out < RXE_INFLIGHT_SKBS_PER_QP_LOW) + if (unlikely(qp->need_req_skb && + skb_out < RXE_INFLIGHT_SKBS_PER_QP_LOW)) rxe_sched_task(&qp->send_task);
rxe_put(qp); -put_dev: - ib_device_put(&rxe->ib_dev); sock_put(skb->sk); }
@@ -383,6 +365,7 @@ static int rxe_send(struct sk_buff *skb, sock_hold(sk); skb->sk = sk; skb->destructor = rxe_skb_tx_dtor; + rxe_get(pkt->qp); atomic_inc(&pkt->qp->skb_out);
if (skb->protocol == htons(ETH_P_IP)) @@ -405,6 +388,7 @@ static int rxe_loopback(struct sk_buff * sock_hold(sk); skb->sk = sk; skb->destructor = rxe_skb_tx_dtor; + rxe_get(pkt->qp); atomic_inc(&pkt->qp->skb_out);
if (skb->protocol == htons(ETH_P_IP)) @@ -497,6 +481,9 @@ struct sk_buff *rxe_init_packet(struct r goto out; }
+ /* Add time stamp to skb. */ + skb->tstamp = ktime_get(); + skb_reserve(skb, hdr_len + LL_RESERVED_SPACE(ndev));
/* FIXME: hold reference to this netdev until life of this skb. */ --- a/drivers/infiniband/sw/rxe/rxe_qp.c +++ b/drivers/infiniband/sw/rxe/rxe_qp.c @@ -244,7 +244,7 @@ static int rxe_qp_init_req(struct rxe_de err = sock_create_kern(&init_net, AF_INET, SOCK_DGRAM, 0, &qp->sk); if (err < 0) return err; - qp->sk->sk->sk_user_data = (void *)(uintptr_t)qp->elem.index; + qp->sk->sk->sk_user_data = qp;
/* pick a source UDP port number for this QP based on * the source QPN. this spreads traffic for different QPs
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Peter Oberparleiter oberpar@linux.ibm.com
commit 430fa71027b6ac9bb0ce5532b8d0676777d4219a upstream.
Tracing code called by the SCLP interrupt handler contains early exits if the SCCB address associated with an interrupt is NULL. This check is performed after physical to virtual address translation.
If the kernel identity mapping does not start at address zero, the resulting virtual address is never zero, so that the NULL checks won't work. Subsequently this may result in incorrect accesses to the first page of the identity mapping.
Fix this by introducing a function that handles the NULL case before address translation.
Fixes: ada1da31ce34 ("s390/sclp: sort out physical vs virtual pointers usage") Cc: stable@vger.kernel.org Reviewed-by: Alexander Gordeev agordeev@linux.ibm.com Signed-off-by: Peter Oberparleiter oberpar@linux.ibm.com Signed-off-by: Alexander Gordeev agordeev@linux.ibm.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/s390/char/sclp.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-)
--- a/drivers/s390/char/sclp.c +++ b/drivers/s390/char/sclp.c @@ -76,6 +76,13 @@ unsigned long sclp_console_full; /* The currently active SCLP command word. */ static sclp_cmdw_t active_cmd;
+static inline struct sccb_header *sclpint_to_sccb(u32 sccb_int) +{ + if (sccb_int) + return __va(sccb_int); + return NULL; +} + static inline void sclp_trace(int prio, char *id, u32 a, u64 b, bool err) { struct sclp_trace_entry e; @@ -619,7 +626,7 @@ __sclp_find_req(u32 sccb)
static bool ok_response(u32 sccb_int, sclp_cmdw_t cmd) { - struct sccb_header *sccb = (struct sccb_header *)__va(sccb_int); + struct sccb_header *sccb = sclpint_to_sccb(sccb_int); struct evbuf_header *evbuf; u16 response;
@@ -658,7 +665,7 @@ static void sclp_interrupt_handler(struc
/* INT: Interrupt received (a=intparm, b=cmd) */ sclp_trace_sccb(0, "INT", param32, active_cmd, active_cmd, - (struct sccb_header *)__va(finished_sccb), + sclpint_to_sccb(finished_sccb), !ok_response(finished_sccb, active_cmd));
if (finished_sccb) {
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Srinivas Pandruvada srinivas.pandruvada@linux.intel.com
commit dff6f36878799a5ffabd15336ce993dc737374dc upstream.
Add the missing write_blocked check for updating sysfs related to uncore efficiency latency control (ELC). If write operation is blocked return error.
Fixes: bb516dc79c4a ("platform/x86/intel-uncore-freq: Add support for efficiency latency control") Signed-off-by: Srinivas Pandruvada srinivas.pandruvada@linux.intel.com Cc: stable@vger.kernel.org Link: https://lore.kernel.org/r/20250727210513.2898630-1-srinivas.pandruvada@linux... Reviewed-by: Ilpo Järvinen ilpo.jarvinen@linux.intel.com Signed-off-by: Ilpo Järvinen ilpo.jarvinen@linux.intel.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/platform/x86/intel/uncore-frequency/uncore-frequency-tpmi.c | 5 +++++ 1 file changed, 5 insertions(+)
--- a/drivers/platform/x86/intel/uncore-frequency/uncore-frequency-tpmi.c +++ b/drivers/platform/x86/intel/uncore-frequency/uncore-frequency-tpmi.c @@ -191,9 +191,14 @@ static int uncore_read_control_freq(stru static int write_eff_lat_ctrl(struct uncore_data *data, unsigned int val, enum uncore_index index) { struct tpmi_uncore_cluster_info *cluster_info; + struct tpmi_uncore_struct *uncore_root; u64 control;
cluster_info = container_of(data, struct tpmi_uncore_cluster_info, uncore_data); + uncore_root = cluster_info->uncore_root; + + if (uncore_root->write_blocked) + return -EPERM;
if (cluster_info->root_domain) return -ENODATA;
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jan Beulich jbeulich@suse.com
commit 8ea815399c3fcce1889bd951fec25b5b9a3979c1 upstream.
__ADDRESSABLE_ASM_STR() is where the necessary stringification happens. As long as "sym" doesn't contain any odd characters, no quoting is required for its use with .quad / .long. In fact the quotation gets in the way with gas 2.25; it's only from 2.26 onwards that quoted symbols are half-way properly supported.
However, assembly being different from C anyway, drop __ADDRESSABLE_ASM_STR() and its helper macro altogether. A simple .global directive will suffice to get the symbol "declared", i.e. into the symbol table. While there also stop open-coding STATIC_CALL_TRAMP() and STATIC_CALL_KEY().
Fixes: 0ef8047b737d ("x86/static-call: provide a way to do very early static-call updates") Signed-off-by: Jan Beulich jbeulich@suse.com Acked-by: Josh Poimboeuf jpoimboe@kernel.org Cc: stable@vger.kernel.org Signed-off-by: Juergen Gross jgross@suse.com Message-ID: 609d2c74-de13-4fae-ab1a-1ec44afb948d@suse.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- arch/x86/include/asm/xen/hypercall.h | 5 +++-- include/linux/compiler.h | 8 -------- 2 files changed, 3 insertions(+), 10 deletions(-)
--- a/arch/x86/include/asm/xen/hypercall.h +++ b/arch/x86/include/asm/xen/hypercall.h @@ -94,12 +94,13 @@ DECLARE_STATIC_CALL(xen_hypercall, xen_h #ifdef MODULE #define __ADDRESSABLE_xen_hypercall #else -#define __ADDRESSABLE_xen_hypercall __ADDRESSABLE_ASM_STR(__SCK__xen_hypercall) +#define __ADDRESSABLE_xen_hypercall \ + __stringify(.global STATIC_CALL_KEY(xen_hypercall);) #endif
#define __HYPERCALL \ __ADDRESSABLE_xen_hypercall \ - "call __SCT__xen_hypercall" + __stringify(call STATIC_CALL_TRAMP(xen_hypercall))
#define __HYPERCALL_ENTRY(x) "a" (x)
--- a/include/linux/compiler.h +++ b/include/linux/compiler.h @@ -288,14 +288,6 @@ static inline void *offset_to_ptr(const #define __ADDRESSABLE(sym) \ ___ADDRESSABLE(sym, __section(".discard.addressable"))
-#define __ADDRESSABLE_ASM(sym) \ - .pushsection .discard.addressable,"aw"; \ - .align ARCH_SEL(8,4); \ - ARCH_SEL(.quad, .long) __stringify(sym); \ - .popsection; - -#define __ADDRESSABLE_ASM_STR(sym) __stringify(__ADDRESSABLE_ASM(sym)) - /* * This returns a constant expression while determining if an argument is * a constant expression, most importantly without evaluating the argument.
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Thorsten Blum thorsten.blum@toblux.com
commit a44458dfd5bc0c79c6739c3f4c658361d3a5126b upstream.
Use kvfree() to fix the following Coccinelle/coccicheck warning reported by kfree_mismatch.cocci:
WARNING kvmalloc is used to allocate this memory at line 10398
Fixes: f728c17fc97a ("accel/habanalabs/gaudi2: move HMMU page tables to device memory") Reported-by: Qianfeng Rong rongqianfeng@vivo.com Closes: https://patch.msgid.link/20250808085530.233737-1-rongqianfeng@vivo.com Signed-off-by: Thorsten Blum thorsten.blum@linux.dev [lukas: acknowledge Qianfeng, adjust Thorsten's domain, add Fixes tag] Signed-off-by: Lukas Wunner lukas@wunner.de Reviewed-by: Tomer Tayar ttayar@habana.ai Cc: stable@vger.kernel.org # v6.9+ Link: https://patch.msgid.link/20240820231028.136126-1-thorsten.blum@toblux.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/accel/habanalabs/gaudi2/gaudi2.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
--- a/drivers/accel/habanalabs/gaudi2/gaudi2.c +++ b/drivers/accel/habanalabs/gaudi2/gaudi2.c @@ -10437,7 +10437,7 @@ end: (u64 *)(lin_dma_pkts_arr), DEBUGFS_WRITE64); WREG32(sob_addr, 0);
- kfree(lin_dma_pkts_arr); + kvfree(lin_dma_pkts_arr);
return rc; }
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Alex Deucher alexander.deucher@amd.com
commit 79e25cd06e85105c75701ef1773c6c64bb304091 upstream.
Take into account the limits from the vbios. Ported from the SMU13 code.
Closes: https://gitlab.freedesktop.org/drm/amd/-/issues/4352 Reviewed-by: Jesse Zhang Jesse.Zhang@amd.com Reviewed-by: Kenneth Feng kenneth.feng@amd.com Signed-off-by: Alex Deucher alexander.deucher@amd.com (cherry picked from commit 203cc7f1dd86f2c8de5c3c6182f19adac7c9c206) Cc: stable@vger.kernel.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/gpu/drm/amd/pm/swsmu/smu14/smu_v14_0_2_ppt.c | 30 +++++++++++++++---- 1 file changed, 25 insertions(+), 5 deletions(-)
--- a/drivers/gpu/drm/amd/pm/swsmu/smu14/smu_v14_0_2_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu14/smu_v14_0_2_ppt.c @@ -1689,9 +1689,11 @@ static int smu_v14_0_2_get_power_limit(s uint32_t *min_power_limit) { struct smu_table_context *table_context = &smu->smu_table; + struct smu_14_0_2_powerplay_table *powerplay_table = + table_context->power_play_table; PPTable_t *pptable = table_context->driver_pptable; CustomSkuTable_t *skutable = &pptable->CustomSkuTable; - uint32_t power_limit; + uint32_t power_limit, od_percent_upper = 0, od_percent_lower = 0; uint32_t msg_limit = pptable->SkuTable.MsgLimits.Power[PPT_THROTTLER_PPT0][POWER_SOURCE_AC];
if (smu_v14_0_get_current_power_limit(smu, &power_limit)) @@ -1704,11 +1706,29 @@ static int smu_v14_0_2_get_power_limit(s if (default_power_limit) *default_power_limit = power_limit;
- if (max_power_limit) - *max_power_limit = msg_limit; + if (powerplay_table) { + if (smu->od_enabled && + smu_v14_0_2_is_od_feature_supported(smu, PP_OD_FEATURE_PPT_BIT)) { + od_percent_upper = pptable->SkuTable.OverDriveLimitsBasicMax.Ppt; + od_percent_lower = pptable->SkuTable.OverDriveLimitsBasicMin.Ppt; + } else if (smu_v14_0_2_is_od_feature_supported(smu, PP_OD_FEATURE_PPT_BIT)) { + od_percent_upper = 0; + od_percent_lower = pptable->SkuTable.OverDriveLimitsBasicMin.Ppt; + } + }
- if (min_power_limit) - *min_power_limit = 0; + dev_dbg(smu->adev->dev, "od percent upper:%d, od percent lower:%d (default power: %d)\n", + od_percent_upper, od_percent_lower, power_limit); + + if (max_power_limit) { + *max_power_limit = msg_limit * (100 + od_percent_upper); + *max_power_limit /= 100; + } + + if (min_power_limit) { + *min_power_limit = power_limit * (100 + od_percent_lower); + *min_power_limit /= 100; + }
return 0; }
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jani Nikula jani.nikula@intel.com
commit ff646d033783068cc5b38924873cab4a536b17c1 upstream.
Commit 8d9908e8fe9c ("drm/i915/display: remove small micro-optimizations in irq handling") not only removed the optimizations, it also enabled wakeref asserts for the GEN11_GU_MISC_IIR access. Silence the asserts by wrapping the access inside intel_display_rpm_assert_{block,unblock}().
Reported-by: "Jason A. Donenfeld" Jason@zx2c4.com Closes: https://lore.kernel.org/r/aG0tWkfmxWtxl_xc@zx2c4.com Fixes: 8d9908e8fe9c ("drm/i915/display: remove small micro-optimizations in irq handling") Cc: stable@vger.kernel.org # v6.13+ Suggested-by: Ville Syrjälä ville.syrjala@linux.intel.com Reviewed-by: Jouni Högander jouni.hogander@intel.com Link: https://lore.kernel.org/r/20250805115656.832235-1-jani.nikula@intel.com Signed-off-by: Jani Nikula jani.nikula@intel.com (cherry picked from commit cbd3baeffbc08052ce7dc53f11bf5524b4411056) Signed-off-by: Tvrtko Ursulin tursulin@ursulin.net Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/gpu/drm/i915/display/intel_display_irq.c | 4 ++++ 1 file changed, 4 insertions(+)
--- a/drivers/gpu/drm/i915/display/intel_display_irq.c +++ b/drivers/gpu/drm/i915/display/intel_display_irq.c @@ -1492,10 +1492,14 @@ u32 gen11_gu_misc_irq_ack(struct intel_d if (!(master_ctl & GEN11_GU_MISC_IRQ)) return 0;
+ intel_display_rpm_assert_block(display); + iir = intel_de_read(display, GEN11_GU_MISC_IIR); if (likely(iir)) intel_de_write(display, GEN11_GU_MISC_IIR, iir);
+ intel_display_rpm_assert_unblock(display); + return iir; }
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Qianfeng Rong rongqianfeng@vivo.com
commit 989fe6771266bdb82a815d78802c5aa7c918fdfd upstream.
Replace kfree() with kvfree() for memory allocated by kvmalloc().
Compile-tested only.
Cc: stable@vger.kernel.org Fixes: 8a8b1ec5261f ("drm/nouveau/gsp: split rpc handling out on its own") Signed-off-by: Qianfeng Rong rongqianfeng@vivo.com Reviewed-by: Timur Tabi ttabi@nvidia.com Acked-by: Zhi Wang zhiw@nvidia.com Link: https://lore.kernel.org/r/20250813125412.96178-1-rongqianfeng@vivo.com Signed-off-by: Danilo Krummrich dakr@kernel.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/gpu/drm/nouveau/nvkm/subdev/gsp/rm/r535/rpc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/rm/r535/rpc.c b/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/rm/r535/rpc.c index 9d06ff722fea..0dc4782df8c0 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/rm/r535/rpc.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/rm/r535/rpc.c @@ -325,7 +325,7 @@ r535_gsp_msgq_recv(struct nvkm_gsp *gsp, u32 gsp_rpc_len, int *retries)
rpc = r535_gsp_msgq_peek(gsp, sizeof(*rpc), info.retries); if (IS_ERR_OR_NULL(rpc)) { - kfree(buf); + kvfree(buf); return rpc; }
@@ -334,7 +334,7 @@ r535_gsp_msgq_recv(struct nvkm_gsp *gsp, u32 gsp_rpc_len, int *retries)
rpc = r535_gsp_msgq_recv_one_elem(gsp, &info); if (IS_ERR_OR_NULL(rpc)) { - kfree(buf); + kvfree(buf); return rpc; }
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sebastian Brzezinka sebastian.brzezinka@intel.com
commit 8236820fd767f400d1baefb71bc7e36e37730a1e upstream.
CACHE_MODE_0 registers should be saved and restored as part of the context, not during engine reset. Move the related workaround (Disable Repacking for Compression) from rcs_engine_wa_init() to icl_ctx_workarounds_init() for Jasper Lake and Elkhart Lake platforms. This ensures the WA is applied during context initialisation.
BSPEC: 11322
Fixes: 0ddae025ab6c ("drm/i915: Disable compression tricks on JSL") Closes: Fixes: 0ddae025ab6c ("drm/i915: Disable compression tricks on JSL") Signed-off-by: Sebastian Brzezinka sebastian.brzezinka@intel.com Cc: stable@vger.kernel.org # v6.13+ Reviewed-by: Andi Shyti andi.shyti@linux.intel.com Reviewed-by: Krzysztof Karas krzysztof.karas@intel.com Signed-off-by: Andi Shyti andi.shyti@linux.intel.com Link: https://lore.kernel.org/r/4feaa24094e019e000ceb6011d8cd419b0361b3f.175490240... (cherry picked from commit c9932f0d604e4c8f2c6018e598a322acb43c68a2) Signed-off-by: Tvrtko Ursulin tursulin@ursulin.net Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/gpu/drm/i915/gt/intel_workarounds.c | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-)
--- a/drivers/gpu/drm/i915/gt/intel_workarounds.c +++ b/drivers/gpu/drm/i915/gt/intel_workarounds.c @@ -634,6 +634,8 @@ static void cfl_ctx_workarounds_init(str static void icl_ctx_workarounds_init(struct intel_engine_cs *engine, struct i915_wa_list *wal) { + struct drm_i915_private *i915 = engine->i915; + /* Wa_1406697149 (WaDisableBankHangMode:icl) */ wa_write(wal, GEN8_L3CNTLREG, GEN8_ERRDETBCTRL);
@@ -669,6 +671,15 @@ static void icl_ctx_workarounds_init(str
/* Wa_1406306137:icl,ehl */ wa_mcr_masked_en(wal, GEN9_ROW_CHICKEN4, GEN11_DIS_PICK_2ND_EU); + + if (IS_JASPERLAKE(i915) || IS_ELKHARTLAKE(i915)) { + /* + * Disable Repacking for Compression (masked R/W access) + * before rendering compressed surfaces for display. + */ + wa_masked_en(wal, CACHE_MODE_0_GEN7, + DISABLE_REPACKING_FOR_COMPRESSION); + } }
/* @@ -2306,15 +2317,6 @@ rcs_engine_wa_init(struct intel_engine_c GEN8_RC_SEMA_IDLE_MSG_DISABLE); }
- if (IS_JASPERLAKE(i915) || IS_ELKHARTLAKE(i915)) { - /* - * "Disable Repacking for Compression (masked R/W access) - * before rendering compressed surfaces for display." - */ - wa_masked_en(wal, CACHE_MODE_0_GEN7, - DISABLE_REPACKING_FOR_COMPRESSION); - } - if (GRAPHICS_VER(i915) == 11) { /* This is not an Wa. Enable for better image quality */ wa_masked_en(wal,
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Imre Deak imre.deak@intel.com
commit f52d6aa98379842fc255d93282655566f2114e0c upstream.
The TypeC PHY HW readout during driver loading and system resume determines which TypeC mode the PHY is in (legacy/DP-alt/TBT-alt) and whether the PHY is connected, based on the PHY's Owned and Ready flags. For the PHY to be in DP-alt or legacy mode and for the PHY to be in the connected state in these modes, both the Owned (set by the BIOS/driver) and the Ready (set by the HW) flags should be set.
On ICL-MTL the HW kept the PHY's Ready flag set after the driver connected the PHY by acquiring the PHY ownership (by setting the Owned flag), until the driver disconnected the PHY by releasing the PHY ownership (by clearing the Owned flag). On LNL+ this has changed, in that the HW clears the Ready flag as soon as the sink gets disconnected, even if the PHY ownership was acquired already and hence the PHY is being used by the display.
When inheriting the HW state from BIOS for a PHY connected in DP-alt mode on which the sink got disconnected - i.e. in a case where the sink was connected while BIOS/GOP was running and so the sink got enabled connecting the PHY, but the user disconnected the sink by the time the driver loaded - the PHY Owned but not Ready state must be accounted for on LNL+ according to the above. Do that by assuming on LNL+ that the PHY is connected in DP-alt mode whenever the PHY Owned flag is set, regardless of the PHY Ready flag.
This fixes a problem on LNL+, where the PHY TypeC mode / connected state was detected incorrectly for a DP-alt sink, which got connected and then disconnected by the user in the above way.
v2: Rename tc_phy_in_legacy_or_dp_alt_mode() to tc_phy_owned_by_display(). (Luca, Jani)
Cc: Jani Nikula jani.nikula@intel.com Cc: stable@vger.kernel.org # v6.8+ Reported-by: Charlton Lin charlton.lin@intel.com Tested-by: Khaled Almahallawy khaled.almahallawy@intel.com Reviewed-by: Mika Kahola mika.kahola@intel.com Reviewed-by: Luca Coelho luciano.coelho@intel.com [Imre: Add one-liner function documentation for tc_phy_owned_by_display()] Signed-off-by: Imre Deak imre.deak@intel.com Link: https://lore.kernel.org/r/20250811080152.906216-2-imre.deak@intel.com (cherry picked from commit 89f4b196ee4b056e0e8c179b247b29d4a71a4e7e) Signed-off-by: Tvrtko Ursulin tursulin@ursulin.net Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/gpu/drm/i915/display/intel_tc.c | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-)
--- a/drivers/gpu/drm/i915/display/intel_tc.c +++ b/drivers/gpu/drm/i915/display/intel_tc.c @@ -1225,14 +1225,19 @@ static void tc_phy_get_hw_state(struct i tc->phy_ops->get_hw_state(tc); }
-static bool tc_phy_is_ready_and_owned(struct intel_tc_port *tc, - bool phy_is_ready, bool phy_is_owned) +/* Is the PHY owned by display i.e. is it in legacy or DP-alt mode? */ +static bool tc_phy_owned_by_display(struct intel_tc_port *tc, + bool phy_is_ready, bool phy_is_owned) { struct intel_display *display = to_intel_display(tc->dig_port);
- drm_WARN_ON(display->drm, phy_is_owned && !phy_is_ready); + if (DISPLAY_VER(display) < 20) { + drm_WARN_ON(display->drm, phy_is_owned && !phy_is_ready);
- return phy_is_ready && phy_is_owned; + return phy_is_ready && phy_is_owned; + } else { + return phy_is_owned; + } }
static bool tc_phy_is_connected(struct intel_tc_port *tc, @@ -1243,7 +1248,7 @@ static bool tc_phy_is_connected(struct i bool phy_is_owned = tc_phy_is_owned(tc); bool is_connected;
- if (tc_phy_is_ready_and_owned(tc, phy_is_ready, phy_is_owned)) + if (tc_phy_owned_by_display(tc, phy_is_ready, phy_is_owned)) is_connected = port_pll_type == ICL_PORT_DPLL_MG_PHY; else is_connected = port_pll_type == ICL_PORT_DPLL_DEFAULT; @@ -1351,7 +1356,7 @@ tc_phy_get_current_mode(struct intel_tc_ phy_is_ready = tc_phy_is_ready(tc); phy_is_owned = tc_phy_is_owned(tc);
- if (!tc_phy_is_ready_and_owned(tc, phy_is_ready, phy_is_owned)) { + if (!tc_phy_owned_by_display(tc, phy_is_ready, phy_is_owned)) { mode = get_tc_mode_in_phy_not_owned_state(tc, live_mode); } else { drm_WARN_ON(display->drm, live_mode == TC_PORT_TBT_ALT);
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Imre Deak imre.deak@intel.com
commit 5fd35236546abe780eaadb7561e09953719d4fc3 upstream.
The PHY's pin assignment value in the TCSS_DDI_STATUS register - as set by the HW/FW based on the connected DP-alt sink's TypeC/PD pin assignment negotiation - gets cleared by the HW/FW on LNL+ as soon as the sink gets disconnected, even if the PHY ownership got acquired already by the driver (and hence the PHY itself is still connected and used by the display). This is similar to how the PHY Ready flag gets cleared on LNL+ in the same register.
To be able to query the max lane count value on LNL+ - which is based on the above pin assignment - at all times even after the sink gets disconnected, the max lane count must be determined and cached during the PHY's HW readout and connect sequences. Do that here, leaving the actual use of the cached value to a follow-up change.
v2: Don't read out the pin configuration if the PHY is disconnected.
Cc: stable@vger.kernel.org # v6.8+ Reported-by: Charlton Lin charlton.lin@intel.com Tested-by: Khaled Almahallawy khaled.almahallawy@intel.com Reviewed-by: Mika Kahola mika.kahola@intel.com Signed-off-by: Imre Deak imre.deak@intel.com Link: https://lore.kernel.org/r/20250811080152.906216-3-imre.deak@intel.com (cherry picked from commit 3e32438fc406761f81b1928d210b3d2a5e7501a0) Signed-off-by: Tvrtko Ursulin tursulin@ursulin.net Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/gpu/drm/i915/display/intel_tc.c | 57 ++++++++++++++++++++++++++------ 1 file changed, 48 insertions(+), 9 deletions(-)
--- a/drivers/gpu/drm/i915/display/intel_tc.c +++ b/drivers/gpu/drm/i915/display/intel_tc.c @@ -65,6 +65,7 @@ struct intel_tc_port { enum tc_port_mode init_mode; enum phy_fia phy_fia; u8 phy_fia_idx; + u8 max_lane_count; };
static enum intel_display_power_domain @@ -364,12 +365,12 @@ static int intel_tc_port_get_max_lane_co } }
-int intel_tc_port_max_lane_count(struct intel_digital_port *dig_port) +static int get_max_lane_count(struct intel_tc_port *tc) { - struct intel_display *display = to_intel_display(dig_port); - struct intel_tc_port *tc = to_tc_port(dig_port); + struct intel_display *display = to_intel_display(tc->dig_port); + struct intel_digital_port *dig_port = tc->dig_port;
- if (!intel_encoder_is_tc(&dig_port->base) || tc->mode != TC_PORT_DP_ALT) + if (tc->mode != TC_PORT_DP_ALT) return 4;
assert_tc_cold_blocked(tc); @@ -383,6 +384,21 @@ int intel_tc_port_max_lane_count(struct return intel_tc_port_get_max_lane_count(dig_port); }
+static void read_pin_configuration(struct intel_tc_port *tc) +{ + tc->max_lane_count = get_max_lane_count(tc); +} + +int intel_tc_port_max_lane_count(struct intel_digital_port *dig_port) +{ + struct intel_tc_port *tc = to_tc_port(dig_port); + + if (!intel_encoder_is_tc(&dig_port->base)) + return 4; + + return get_max_lane_count(tc); +} + void intel_tc_port_set_fia_lane_count(struct intel_digital_port *dig_port, int required_lanes) { @@ -595,9 +611,12 @@ static void icl_tc_phy_get_hw_state(stru tc_cold_wref = __tc_cold_block(tc, &domain);
tc->mode = tc_phy_get_current_mode(tc); - if (tc->mode != TC_PORT_DISCONNECTED) + if (tc->mode != TC_PORT_DISCONNECTED) { tc->lock_wakeref = tc_cold_block(tc);
+ read_pin_configuration(tc); + } + __tc_cold_unblock(tc, domain, tc_cold_wref); }
@@ -655,8 +674,11 @@ static bool icl_tc_phy_connect(struct in
tc->lock_wakeref = tc_cold_block(tc);
- if (tc->mode == TC_PORT_TBT_ALT) + if (tc->mode == TC_PORT_TBT_ALT) { + read_pin_configuration(tc); + return true; + }
if ((!tc_phy_is_ready(tc) || !icl_tc_phy_take_ownership(tc, true)) && @@ -667,6 +689,7 @@ static bool icl_tc_phy_connect(struct in goto out_unblock_tc_cold; }
+ read_pin_configuration(tc);
if (!tc_phy_verify_legacy_or_dp_alt_mode(tc, required_lanes)) goto out_release_phy; @@ -857,9 +880,12 @@ static void adlp_tc_phy_get_hw_state(str port_wakeref = intel_display_power_get(display, port_power_domain);
tc->mode = tc_phy_get_current_mode(tc); - if (tc->mode != TC_PORT_DISCONNECTED) + if (tc->mode != TC_PORT_DISCONNECTED) { tc->lock_wakeref = tc_cold_block(tc);
+ read_pin_configuration(tc); + } + intel_display_power_put(display, port_power_domain, port_wakeref); }
@@ -872,6 +898,9 @@ static bool adlp_tc_phy_connect(struct i
if (tc->mode == TC_PORT_TBT_ALT) { tc->lock_wakeref = tc_cold_block(tc); + + read_pin_configuration(tc); + return true; }
@@ -893,6 +922,8 @@ static bool adlp_tc_phy_connect(struct i
tc->lock_wakeref = tc_cold_block(tc);
+ read_pin_configuration(tc); + if (!tc_phy_verify_legacy_or_dp_alt_mode(tc, required_lanes)) goto out_unblock_tc_cold;
@@ -1123,9 +1154,12 @@ static void xelpdp_tc_phy_get_hw_state(s tc_cold_wref = __tc_cold_block(tc, &domain);
tc->mode = tc_phy_get_current_mode(tc); - if (tc->mode != TC_PORT_DISCONNECTED) + if (tc->mode != TC_PORT_DISCONNECTED) { tc->lock_wakeref = tc_cold_block(tc);
+ read_pin_configuration(tc); + } + drm_WARN_ON(display->drm, (tc->mode == TC_PORT_DP_ALT || tc->mode == TC_PORT_LEGACY) && !xelpdp_tc_phy_tcss_power_is_enabled(tc)); @@ -1137,14 +1171,19 @@ static bool xelpdp_tc_phy_connect(struct { tc->lock_wakeref = tc_cold_block(tc);
- if (tc->mode == TC_PORT_TBT_ALT) + if (tc->mode == TC_PORT_TBT_ALT) { + read_pin_configuration(tc); + return true; + }
if (!xelpdp_tc_phy_enable_tcss_power(tc, true)) goto out_unblock_tccold;
xelpdp_tc_phy_take_ownership(tc, true);
+ read_pin_configuration(tc); + if (!tc_phy_verify_legacy_or_dp_alt_mode(tc, required_lanes)) goto out_release_phy;
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Imre Deak imre.deak@intel.com
commit c87514a0bb0a64507412a2d98264060dc0c1562a upstream.
On LNL+ for a disconnected sink the pin assignment value gets cleared by the HW/FW as soon as the sink gets disconnected, even if the PHY ownership got acquired already by the BIOS/driver (and hence the PHY itself is still connected and used by the display). During HW readout this can result in detecting the PHY's max lane count as 0 - matching the above cleared aka NONE pin assignment HW state. For a connected PHY the driver in general (outside of intel_tc.c) expects the max lane count value to be valid for the video mode enabled on the corresponding output (1, 2 or 4). Ensure this by setting the max lane count to 4 in this case. Note, that it doesn't matter if this lane count happened to be more than the max lane count with which the PHY got connected and enabled, since the only thing the driver can do with such an output - where the DP-alt sink is disconnected - is to disable the output.
v2: Rebased on change reading out the pin configuration only if the PHY is connected.
Cc: stable@vger.kernel.org # v6.8+ Reported-by: Charlton Lin charlton.lin@intel.com Tested-by: Khaled Almahallawy khaled.almahallawy@intel.com Reviewed-by: Mika Kahola mika.kahola@intel.com Signed-off-by: Imre Deak imre.deak@intel.com Link: https://lore.kernel.org/r/20250811080152.906216-4-imre.deak@intel.com (cherry picked from commit 33cf70bc0fe760224f892bc1854a33665f27d482) Signed-off-by: Tvrtko Ursulin tursulin@ursulin.net Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/gpu/drm/i915/display/intel_tc.c | 9 +++++++++ 1 file changed, 9 insertions(+)
--- a/drivers/gpu/drm/i915/display/intel_tc.c +++ b/drivers/gpu/drm/i915/display/intel_tc.c @@ -22,6 +22,7 @@ #include "intel_modeset_lock.h" #include "intel_tc.h"
+#define DP_PIN_ASSIGNMENT_NONE 0x0 #define DP_PIN_ASSIGNMENT_C 0x3 #define DP_PIN_ASSIGNMENT_D 0x4 #define DP_PIN_ASSIGNMENT_E 0x5 @@ -307,6 +308,8 @@ static int lnl_tc_port_get_max_lane_coun REG_FIELD_GET(TCSS_DDI_STATUS_PIN_ASSIGNMENT_MASK, val);
switch (pin_assignment) { + case DP_PIN_ASSIGNMENT_NONE: + return 0; default: MISSING_CASE(pin_assignment); fallthrough; @@ -1158,6 +1161,12 @@ static void xelpdp_tc_phy_get_hw_state(s tc->lock_wakeref = tc_cold_block(tc);
read_pin_configuration(tc); + /* + * Set a valid lane count value for a DP-alt sink which got + * disconnected. The driver can only disable the output on this PHY. + */ + if (tc->max_lane_count == 0) + tc->max_lane_count = 4; }
drm_WARN_ON(display->drm,
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Imre Deak imre.deak@intel.com
commit c5c2b4b3841666be3a45346d0ffa96b4b143504e upstream.
Use the cached max lane count value on LNL+, to account for scenarios where this value is queried after the HW cleared the corresponding pin assignment value in the TCSS_DDI_STATUS register after the sink got disconnected.
For consistency, follow-up changes will use the cached max lane count value on other platforms as well and will also cache the pin assignment value in a similar way.
Cc: stable@vger.kernel.org # v6.8+ Reported-by: Charlton Lin charlton.lin@intel.com Tested-by: Khaled Almahallawy khaled.almahallawy@intel.com Reviewed-by: Mika Kahola mika.kahola@intel.com Signed-off-by: Imre Deak imre.deak@intel.com Link: https://lore.kernel.org/r/20250811080152.906216-5-imre.deak@intel.com (cherry picked from commit afc4e84388079f4d5ba05271632b7a4d8d85165c) Signed-off-by: Tvrtko Ursulin tursulin@ursulin.net Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/gpu/drm/i915/display/intel_tc.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-)
--- a/drivers/gpu/drm/i915/display/intel_tc.c +++ b/drivers/gpu/drm/i915/display/intel_tc.c @@ -394,12 +394,16 @@ static void read_pin_configuration(struc
int intel_tc_port_max_lane_count(struct intel_digital_port *dig_port) { + struct intel_display *display = to_intel_display(dig_port); struct intel_tc_port *tc = to_tc_port(dig_port);
if (!intel_encoder_is_tc(&dig_port->base)) return 4;
- return get_max_lane_count(tc); + if (DISPLAY_VER(display) < 20) + return get_max_lane_count(tc); + + return tc->max_lane_count; }
void intel_tc_port_set_fia_lane_count(struct intel_digital_port *dig_port,
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Imre Deak imre.deak@intel.com
commit d7fa5754e83cd36c4327eb2d806064e598a72ff6 upstream.
The BIOS can leave the AUX power well enabled on an output, even if this isn't required (on platforms where the AUX power is only needed for an AUX access). This was observed at least on PTL. To avoid the WARN which would be triggered by this during the HW readout, convert the WARN to a debug message.
Cc: stable@vger.kernel.org # v6.8+ Reported-by: Charlton Lin charlton.lin@intel.com Tested-by: Khaled Almahallawy khaled.almahallawy@intel.com Reviewed-by: Mika Kahola mika.kahola@intel.com Signed-off-by: Imre Deak imre.deak@intel.com Link: https://lore.kernel.org/r/20250811080152.906216-6-imre.deak@intel.com (cherry picked from commit 6cb52cba474b2bec1a3018d3dbf75292059a29a1) Signed-off-by: Tvrtko Ursulin tursulin@ursulin.net Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/gpu/drm/i915/display/intel_tc.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
--- a/drivers/gpu/drm/i915/display/intel_tc.c +++ b/drivers/gpu/drm/i915/display/intel_tc.c @@ -1497,11 +1497,11 @@ static void intel_tc_port_reset_mode(str intel_display_power_flush_work(display); if (!intel_tc_cold_requires_aux_pw(dig_port)) { enum intel_display_power_domain aux_domain; - bool aux_powered;
aux_domain = intel_aux_power_domain(dig_port); - aux_powered = intel_display_power_is_enabled(display, aux_domain); - drm_WARN_ON(display->drm, aux_powered); + if (intel_display_power_is_enabled(display, aux_domain)) + drm_dbg_kms(display->drm, "Port %s: AUX unexpectedly powered\n", + tc->port_name); }
tc_phy_disconnect(tc);
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Mario Limonciello mario.limonciello@amd.com
commit 07b93a5704b0b72002f0c4bd1076214af67dc661 upstream.
[WHY] Although unlikely drm_atomic_get_new_connector_state() or drm_atomic_get_old_connector_state() can return NULL.
[HOW] Check returns before dereference.
Cc: Mario Limonciello mario.limonciello@amd.com Cc: Alex Deucher alexander.deucher@amd.com Reviewed-by: Harry Wentland harry.wentland@amd.com Signed-off-by: Mario Limonciello mario.limonciello@amd.com Signed-off-by: Alex Hung alex.hung@amd.com Tested-by: Dan Wheeler daniel.wheeler@amd.com Signed-off-by: Alex Deucher alexander.deucher@amd.com (cherry picked from commit 1e5e8d672fec9f2ab352be121be971877bff2af9) Cc: stable@vger.kernel.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 3 +++ 1 file changed, 3 insertions(+)
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -7761,6 +7761,9 @@ amdgpu_dm_connector_atomic_check(struct struct amdgpu_dm_connector *aconn = to_amdgpu_dm_connector(conn); int ret;
+ if (WARN_ON(unlikely(!old_con_state || !new_con_state))) + return -EINVAL; + trace_amdgpu_dm_connector_atomic_check(new_con_state);
if (conn->connector_type == DRM_MODE_CONNECTOR_DisplayPort) {
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Timur Kristóf timur.kristof@gmail.com
commit cb7b7ae53b557d168b4af5cd8549f3eff920bfb5 upstream.
The extra 15% clock was added as a workaround for a Polaris issue which uses DCE 11, and should not have been used on DCE 6 which is already hardcoded to the highest possible display clock. Unfortunately, the extra 15% was mistakenly copied and kept even on code paths which don't affect Polaris.
This commit fixes that and also adds a check to make sure not to exceed the maximum DCE 6 display clock.
Fixes: 8cd61c313d8b ("drm/amd/display: Raise dispclk value for Polaris") Fixes: dc88b4a684d2 ("drm/amd/display: make clk mgr soc specific") Fixes: 3ecb3b794e2c ("drm/amd/display: dc/clk_mgr: add support for SI parts (v2)") Signed-off-by: Timur Kristóf timur.kristof@gmail.com Acked-by: Alex Deucher alexander.deucher@amd.com Reviewed-by: Rodrigo Siqueira siqueira@igalia.com Reviewed-by: Alex Hung alex.hung@amd.com Signed-off-by: Alex Deucher alexander.deucher@amd.com (cherry picked from commit 427980c1cbd22bb256b9385f5ce73c0937562408) Cc: stable@vger.kernel.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/gpu/drm/amd/display/dc/clk_mgr/dce60/dce60_clk_mgr.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-)
--- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dce60/dce60_clk_mgr.c +++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dce60/dce60_clk_mgr.c @@ -123,11 +123,9 @@ static void dce60_update_clocks(struct c { struct clk_mgr_internal *clk_mgr_dce = TO_CLK_MGR_INTERNAL(clk_mgr_base); struct dm_pp_power_level_change_request level_change_req; - int patched_disp_clk = context->bw_ctx.bw.dce.dispclk_khz; - - /*TODO: W/A for dal3 linux, investigate why this works */ - if (!clk_mgr_dce->dfs_bypass_active) - patched_disp_clk = patched_disp_clk * 115 / 100; + const int max_disp_clk = + clk_mgr_dce->max_clks_by_state[DM_PP_CLOCKS_STATE_PERFORMANCE].display_clk_khz; + int patched_disp_clk = MIN(max_disp_clk, context->bw_ctx.bw.dce.dispclk_khz);
level_change_req.power_level = dce_get_required_clocks_state(clk_mgr_base, context); /* get max clock state from PPLIB */
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Timur Kristóf timur.kristof@gmail.com
commit 10507478468f165ea681605d133991ed05cdff62 upstream.
For later VBIOS versions, the fractional feedback divider is calculated as the remainder of dividing the feedback divider by a factor, which is set to 1000000. For reference, see: - calculate_fb_and_fractional_fb_divider - calc_pll_max_vco_construct
However, in case of old VBIOS versions that have set_pixel_clock_v3, they only have 1 byte available for the fractional feedback divider, and it's expected to be set to the remainder from dividing the feedback divider by 10. For reference see the legacy display code: - amdgpu_pll_compute - amdgpu_atombios_crtc_program_pll
This commit fixes set_pixel_clock_v3 by dividing the fractional feedback divider passed to the function by 100000.
Fixes: 4562236b3bc0 ("drm/amd/dc: Add dc display driver (v2)") Signed-off-by: Timur Kristóf timur.kristof@gmail.com Acked-by: Alex Deucher alexander.deucher@amd.com Reviewed-by: Rodrigo Siqueira siqueira@igalia.com Reviewed-by: Alex Hung alex.hung@amd.com Signed-off-by: Alex Deucher alexander.deucher@amd.com (cherry picked from commit 027e7acc7e17802ebf28e1edb88a404836ad50d6) Cc: stable@vger.kernel.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/gpu/drm/amd/display/dc/bios/command_table.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
--- a/drivers/gpu/drm/amd/display/dc/bios/command_table.c +++ b/drivers/gpu/drm/amd/display/dc/bios/command_table.c @@ -993,7 +993,7 @@ static enum bp_result set_pixel_clock_v3 allocation.sPCLKInput.usFbDiv = cpu_to_le16((uint16_t)bp_params->feedback_divider); allocation.sPCLKInput.ucFracFbDiv = - (uint8_t)bp_params->fractional_feedback_divider; + (uint8_t)(bp_params->fractional_feedback_divider / 100000); allocation.sPCLKInput.ucPostDiv = (uint8_t)bp_params->pixel_clock_post_divider;
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Tom Chung chiahsuan.chung@amd.com
commit 66af73a1c319336694a8610fe4c2943f7b33066c upstream.
[WHY & HOW] IPS & self-fresh feature can cause vblank counter resets between vblank disable and enable. It may cause system stuck due to wait the vblank counter.
Call the drm_crtc_vblank_restore() during vblank enable to estimate missed vblanks by using timestamps and update the vblank counter in DRM.
It can make the vblank counter increase smoothly and resolve this issue.
Cc: Mario Limonciello mario.limonciello@amd.com Cc: Alex Deucher alexander.deucher@amd.com Reviewed-by: Sun peng (Leo) Li sunpeng.li@amd.com Signed-off-by: Tom Chung chiahsuan.chung@amd.com Signed-off-by: Alex Hung alex.hung@amd.com Tested-by: Dan Wheeler daniel.wheeler@amd.com Signed-off-by: Alex Deucher alexander.deucher@amd.com (cherry picked from commit 34d66bc7ff10e146a4cec76cf286979740a10954) Cc: stable@vger.kernel.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crtc.c | 19 +++++++++++++++++ 1 file changed, 19 insertions(+)
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crtc.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crtc.c @@ -299,6 +299,25 @@ static inline int amdgpu_dm_crtc_set_vbl irq_type = amdgpu_display_crtc_idx_to_irq_type(adev, acrtc->crtc_id);
if (enable) { + struct dc *dc = adev->dm.dc; + struct drm_vblank_crtc *vblank = drm_crtc_vblank_crtc(crtc); + struct psr_settings *psr = &acrtc_state->stream->link->psr_settings; + struct replay_settings *pr = &acrtc_state->stream->link->replay_settings; + bool sr_supported = (psr->psr_version != DC_PSR_VERSION_UNSUPPORTED) || + pr->config.replay_supported; + + /* + * IPS & self-refresh feature can cause vblank counter resets between + * vblank disable and enable. + * It may cause system stuck due to waiting for the vblank counter. + * Call this function to estimate missed vblanks by using timestamps and + * update the vblank counter in DRM. + */ + if (dc->caps.ips_support && + dc->config.disable_ips != DMUB_IPS_DISABLE_ALL && + sr_supported && vblank->config.disable_immediate) + drm_crtc_vblank_restore(crtc); + /* vblank irq on -> Only need vupdate irq in vrr mode */ if (amdgpu_dm_crtc_vrr_active(acrtc_state)) rc = amdgpu_dm_crtc_set_vupdate_irq(crtc, true);
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Timur Kristóf timur.kristof@gmail.com
commit 297a4833a68aac3316eb808b4123eb016ef242d7 upstream.
On DCE 6, DP audio was not working. However, it worked when an HDMI monitor was also plugged in.
Looking at dce_aud_wall_dto_setup it seems that the main difference is that we use DTO1 when only DP is plugged in.
When programming DTO1, it uses audio_dto_source_clock_in_khz which is set from get_dp_ref_freq_khz
The dce60_get_dp_ref_freq_khz implementation looks incorrect, because DENTIST_DISPCLK_CNTL seems to be always zero on DCE 6, so it isn't usable. I compared dce60_get_dp_ref_freq_khz to the legacy display code, specifically dce_v6_0_audio_set_dto, and it turns out that in case of DCE 6, it needs to use the display clock. With that, DP audio started working on Pitcairn, Oland and Cape Verde.
However, it still didn't work on Tahiti. Despite having the same DCE version, Tahiti seems to have a different audio device. After some trial and error I realized that it works with the default display clock as reported by the VBIOS, not the current display clock.
The patch was tested on all four SI GPUs:
* Pitcairn (DCE 6.0) * Oland (DCE 6.4) * Cape Verde (DCE 6.0) * Tahiti (DCE 6.0 but different)
The testing was done on Samsung Odyssey G7 LS28BG700EPXEN on each of the above GPUs, at the following settings:
* 4K 60 Hz * 1080p 60 Hz * 1080p 144 Hz
Acked-by: Alex Deucher alexander.deucher@amd.com Reviewed-by: Rodrigo Siqueira siqueira@igalia.com Signed-off-by: Timur Kristóf timur.kristof@gmail.com Signed-off-by: Alex Deucher alexander.deucher@amd.com (cherry picked from commit 645cc7863da5de700547d236697dffd6760cf051) Cc: stable@vger.kernel.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/gpu/drm/amd/display/dc/clk_mgr/dce60/dce60_clk_mgr.c | 21 +++-------- 1 file changed, 6 insertions(+), 15 deletions(-)
--- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dce60/dce60_clk_mgr.c +++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dce60/dce60_clk_mgr.c @@ -83,22 +83,13 @@ static const struct state_dependent_cloc static int dce60_get_dp_ref_freq_khz(struct clk_mgr *clk_mgr_base) { struct clk_mgr_internal *clk_mgr = TO_CLK_MGR_INTERNAL(clk_mgr_base); - int dprefclk_wdivider; - int dp_ref_clk_khz; - int target_div; + struct dc_context *ctx = clk_mgr_base->ctx; + int dp_ref_clk_khz = 0;
- /* DCE6 has no DPREFCLK_CNTL to read DP Reference Clock source */ - - /* Read the mmDENTIST_DISPCLK_CNTL to get the currently - * programmed DID DENTIST_DPREFCLK_WDIVIDER*/ - REG_GET(DENTIST_DISPCLK_CNTL, DENTIST_DPREFCLK_WDIVIDER, &dprefclk_wdivider); - - /* Convert DENTIST_DPREFCLK_WDIVIDERto actual divider*/ - target_div = dentist_get_divider_from_did(dprefclk_wdivider); - - /* Calculate the current DFS clock, in kHz.*/ - dp_ref_clk_khz = (DENTIST_DIVIDER_RANGE_SCALE_FACTOR - * clk_mgr->base.dentist_vco_freq_khz) / target_div; + if (ASIC_REV_IS_TAHITI_P(ctx->asic_id.hw_internal_rev)) + dp_ref_clk_khz = ctx->dc_bios->fw_info.default_display_engine_pll_frequency; + else + dp_ref_clk_khz = clk_mgr_base->clks.dispclk_khz;
return dce_adjust_dp_ref_freq_for_ss(clk_mgr, dp_ref_clk_khz); }
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Timur Kristóf timur.kristof@gmail.com
commit 669f73a26f6112eedbadac53a2f2707ac6d0b9c8 upstream.
dce110_fill_display_configs is shared between DCE 6-11, and finding the first CRTC and its line time is relevant to DCE 6 too. Move the code to find it from DCE 11 specific code.
Signed-off-by: Timur Kristóf timur.kristof@gmail.com Acked-by: Alex Deucher alexander.deucher@amd.com Reviewed-by: Rodrigo Siqueira siqueira@igalia.com Reviewed-by: Alex Hung alex.hung@amd.com Signed-off-by: Alex Deucher alexander.deucher@amd.com (cherry picked from commit 4ab09785f8d5d03df052827af073d5c508ff5f63) Cc: stable@vger.kernel.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/gpu/drm/amd/display/dc/clk_mgr/dce110/dce110_clk_mgr.c | 30 ++++++---- 1 file changed, 20 insertions(+), 10 deletions(-)
--- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dce110/dce110_clk_mgr.c +++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dce110/dce110_clk_mgr.c @@ -120,9 +120,12 @@ void dce110_fill_display_configs( const struct dc_state *context, struct dm_pp_display_configuration *pp_display_cfg) { + struct dc *dc = context->clk_mgr->ctx->dc; int j; int num_cfgs = 0;
+ pp_display_cfg->crtc_index = dc->res_pool->res_cap->num_timing_generator; + for (j = 0; j < context->stream_count; j++) { int k;
@@ -164,6 +167,23 @@ void dce110_fill_display_configs( cfg->v_refresh /= stream->timing.h_total; cfg->v_refresh = (cfg->v_refresh + stream->timing.v_total / 2) / stream->timing.v_total; + + /* Find first CRTC index and calculate its line time. + * This is necessary for DPM on SI GPUs. + */ + if (cfg->pipe_idx < pp_display_cfg->crtc_index) { + const struct dc_crtc_timing *timing = + &context->streams[0]->timing; + + pp_display_cfg->crtc_index = cfg->pipe_idx; + pp_display_cfg->line_time_in_us = + timing->h_total * 10000 / timing->pix_clk_100hz; + } + } + + if (!num_cfgs) { + pp_display_cfg->crtc_index = 0; + pp_display_cfg->line_time_in_us = 0; }
pp_display_cfg->display_count = num_cfgs; @@ -232,16 +252,6 @@ void dce11_pplib_apply_display_requireme
dce110_fill_display_configs(context, pp_display_cfg);
- /* TODO: is this still applicable?*/ - if (pp_display_cfg->display_count == 1) { - const struct dc_crtc_timing *timing = - &context->streams[0]->timing; - - pp_display_cfg->crtc_index = - pp_display_cfg->disp_configs[0].pipe_idx; - pp_display_cfg->line_time_in_us = timing->h_total * 10000 / timing->pix_clk_100hz; - } - if (memcmp(&dc->current_state->pp_display_cfg, pp_display_cfg, sizeof(*pp_display_cfg)) != 0) dm_pp_apply_display_requirements(dc->ctx, pp_display_cfg); }
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Timur Kristóf timur.kristof@gmail.com
commit 7d07140d37f792f01cfdb8ca9a6a792ab1d29126 upstream.
Also needed by DCE 6. This way the code that gathers this info can be shared between different DCE versions and doesn't have to be repeated.
Signed-off-by: Timur Kristóf timur.kristof@gmail.com Acked-by: Alex Deucher alexander.deucher@amd.com Reviewed-by: Rodrigo Siqueira siqueira@igalia.com Reviewed-by: Alex Hung alex.hung@amd.com Signed-off-by: Alex Deucher alexander.deucher@amd.com (cherry picked from commit 8107432dff37db26fcb641b6cebeae8981cd73a0) Cc: stable@vger.kernel.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/gpu/drm/amd/display/dc/clk_mgr/dce100/dce_clk_mgr.c | 2 -- drivers/gpu/drm/amd/display/dc/clk_mgr/dce110/dce110_clk_mgr.c | 10 +++------- drivers/gpu/drm/amd/display/dc/clk_mgr/dce60/dce60_clk_mgr.c | 2 -- 3 files changed, 3 insertions(+), 11 deletions(-)
--- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dce100/dce_clk_mgr.c +++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dce100/dce_clk_mgr.c @@ -391,8 +391,6 @@ static void dce_pplib_apply_display_requ { struct dm_pp_display_configuration *pp_display_cfg = &context->pp_display_cfg;
- pp_display_cfg->avail_mclk_switch_time_us = dce110_get_min_vblank_time_us(context); - dce110_fill_display_configs(context, pp_display_cfg);
if (memcmp(&dc->current_state->pp_display_cfg, pp_display_cfg, sizeof(*pp_display_cfg)) != 0) --- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dce110/dce110_clk_mgr.c +++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dce110/dce110_clk_mgr.c @@ -124,6 +124,9 @@ void dce110_fill_display_configs( int j; int num_cfgs = 0;
+ pp_display_cfg->avail_mclk_switch_time_us = dce110_get_min_vblank_time_us(context); + pp_display_cfg->disp_clk_khz = dc->clk_mgr->clks.dispclk_khz; + pp_display_cfg->avail_mclk_switch_time_in_disp_active_us = 0; pp_display_cfg->crtc_index = dc->res_pool->res_cap->num_timing_generator;
for (j = 0; j < context->stream_count; j++) { @@ -243,13 +246,6 @@ void dce11_pplib_apply_display_requireme pp_display_cfg->min_engine_clock_deep_sleep_khz = context->bw_ctx.bw.dce.sclk_deep_sleep_khz;
- pp_display_cfg->avail_mclk_switch_time_us = - dce110_get_min_vblank_time_us(context); - /* TODO: dce11.2*/ - pp_display_cfg->avail_mclk_switch_time_in_disp_active_us = 0; - - pp_display_cfg->disp_clk_khz = dc->clk_mgr->clks.dispclk_khz; - dce110_fill_display_configs(context, pp_display_cfg);
if (memcmp(&dc->current_state->pp_display_cfg, pp_display_cfg, sizeof(*pp_display_cfg)) != 0) --- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dce60/dce60_clk_mgr.c +++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dce60/dce60_clk_mgr.c @@ -100,8 +100,6 @@ static void dce60_pplib_apply_display_re { struct dm_pp_display_configuration *pp_display_cfg = &context->pp_display_cfg;
- pp_display_cfg->avail_mclk_switch_time_us = dce110_get_min_vblank_time_us(context); - dce110_fill_display_configs(context, pp_display_cfg);
if (memcmp(&dc->current_state->pp_display_cfg, pp_display_cfg, sizeof(*pp_display_cfg)) != 0)
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ranjan Kumar ranjan.kumar@broadcom.com
[ Upstream commit 6853885b21cb1d7157cc14c9d30cc17141565bae ]
The volatile qualifier is redundant for __iomem pointers.
Cleaned up usage in mpi3mr_writeq() and sysif_regs pointer as per Upstream compliance.
Signed-off-by: Ranjan Kumar ranjan.kumar@broadcom.com Link: https://lore.kernel.org/r/20250627194539.48851-3-ranjan.kumar@broadcom.com Signed-off-by: Martin K. Petersen martin.petersen@oracle.com Stable-dep-of: c91e140c82eb ("scsi: mpi3mr: Serialize admin queue BAR writes on 32-bit systems") Signed-off-by: Sasha Levin sashal@kernel.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/scsi/mpi3mr/mpi3mr.h | 2 +- drivers/scsi/mpi3mr/mpi3mr_fw.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-)
--- a/drivers/scsi/mpi3mr/mpi3mr.h +++ b/drivers/scsi/mpi3mr/mpi3mr.h @@ -1185,7 +1185,7 @@ struct mpi3mr_ioc { char name[MPI3MR_NAME_LENGTH]; char driver_name[MPI3MR_NAME_LENGTH];
- volatile struct mpi3_sysif_registers __iomem *sysif_regs; + struct mpi3_sysif_registers __iomem *sysif_regs; resource_size_t sysif_regs_phys; int bars; u64 dma_mask; --- a/drivers/scsi/mpi3mr/mpi3mr_fw.c +++ b/drivers/scsi/mpi3mr/mpi3mr_fw.c @@ -23,12 +23,12 @@ module_param(poll_queues, int, 0444); MODULE_PARM_DESC(poll_queues, "Number of queues for io_uring poll mode. (Range 1 - 126)");
#if defined(writeq) && defined(CONFIG_64BIT) -static inline void mpi3mr_writeq(__u64 b, volatile void __iomem *addr) +static inline void mpi3mr_writeq(__u64 b, void __iomem *addr) { writeq(b, addr); } #else -static inline void mpi3mr_writeq(__u64 b, volatile void __iomem *addr) +static inline void mpi3mr_writeq(__u64 b, void __iomem *addr) { __u64 data_out = b;
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ranjan Kumar ranjan.kumar@broadcom.com
[ Upstream commit c91e140c82eb58724c435f623702e51cc7896646 ]
On 32-bit systems, 64-bit BAR writes to admin queue registers are performed as two 32-bit writes. Without locking, this can cause partial writes when accessed concurrently.
Updated per-queue spinlocks is used to serialize these writes and prevent race conditions.
Fixes: 824a156633df ("scsi: mpi3mr: Base driver code") Cc: stable@vger.kernel.org Signed-off-by: Ranjan Kumar ranjan.kumar@broadcom.com Link: https://lore.kernel.org/r/20250627194539.48851-4-ranjan.kumar@broadcom.com Signed-off-by: Martin K. Petersen martin.petersen@oracle.com Signed-off-by: Sasha Levin sashal@kernel.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/scsi/mpi3mr/mpi3mr.h | 4 ++++ drivers/scsi/mpi3mr/mpi3mr_fw.c | 15 +++++++++++---- drivers/scsi/mpi3mr/mpi3mr_os.c | 2 ++ 3 files changed, 17 insertions(+), 4 deletions(-)
--- a/drivers/scsi/mpi3mr/mpi3mr.h +++ b/drivers/scsi/mpi3mr/mpi3mr.h @@ -1137,6 +1137,8 @@ struct scmd_priv { * @logdata_buf: Circular buffer to store log data entries * @logdata_buf_idx: Index of entry in buffer to store * @logdata_entry_sz: log data entry size + * @adm_req_q_bar_writeq_lock: Admin request queue lock + * @adm_reply_q_bar_writeq_lock: Admin reply queue lock * @pend_large_data_sz: Counter to track pending large data * @io_throttle_data_length: I/O size to track in 512b blocks * @io_throttle_high: I/O size to start throttle in 512b blocks @@ -1339,6 +1341,8 @@ struct mpi3mr_ioc { u8 *logdata_buf; u16 logdata_buf_idx; u16 logdata_entry_sz; + spinlock_t adm_req_q_bar_writeq_lock; + spinlock_t adm_reply_q_bar_writeq_lock;
atomic_t pend_large_data_sz; u32 io_throttle_data_length; --- a/drivers/scsi/mpi3mr/mpi3mr_fw.c +++ b/drivers/scsi/mpi3mr/mpi3mr_fw.c @@ -23,17 +23,22 @@ module_param(poll_queues, int, 0444); MODULE_PARM_DESC(poll_queues, "Number of queues for io_uring poll mode. (Range 1 - 126)");
#if defined(writeq) && defined(CONFIG_64BIT) -static inline void mpi3mr_writeq(__u64 b, void __iomem *addr) +static inline void mpi3mr_writeq(__u64 b, void __iomem *addr, + spinlock_t *write_queue_lock) { writeq(b, addr); } #else -static inline void mpi3mr_writeq(__u64 b, void __iomem *addr) +static inline void mpi3mr_writeq(__u64 b, void __iomem *addr, + spinlock_t *write_queue_lock) { __u64 data_out = b; + unsigned long flags;
+ spin_lock_irqsave(write_queue_lock, flags); writel((u32)(data_out), addr); writel((u32)(data_out >> 32), (addr + 4)); + spin_unlock_irqrestore(write_queue_lock, flags); } #endif
@@ -2954,9 +2959,11 @@ static int mpi3mr_setup_admin_qpair(stru (mrioc->num_admin_req); writel(num_admin_entries, &mrioc->sysif_regs->admin_queue_num_entries); mpi3mr_writeq(mrioc->admin_req_dma, - &mrioc->sysif_regs->admin_request_queue_address); + &mrioc->sysif_regs->admin_request_queue_address, + &mrioc->adm_req_q_bar_writeq_lock); mpi3mr_writeq(mrioc->admin_reply_dma, - &mrioc->sysif_regs->admin_reply_queue_address); + &mrioc->sysif_regs->admin_reply_queue_address, + &mrioc->adm_reply_q_bar_writeq_lock); writel(mrioc->admin_req_pi, &mrioc->sysif_regs->admin_request_queue_pi); writel(mrioc->admin_reply_ci, &mrioc->sysif_regs->admin_reply_queue_ci); return retval; --- a/drivers/scsi/mpi3mr/mpi3mr_os.c +++ b/drivers/scsi/mpi3mr/mpi3mr_os.c @@ -5383,6 +5383,8 @@ mpi3mr_probe(struct pci_dev *pdev, const spin_lock_init(&mrioc->tgtdev_lock); spin_lock_init(&mrioc->watchdog_lock); spin_lock_init(&mrioc->chain_buf_lock); + spin_lock_init(&mrioc->adm_req_q_bar_writeq_lock); + spin_lock_init(&mrioc->adm_reply_q_bar_writeq_lock); spin_lock_init(&mrioc->sas_node_lock); spin_lock_init(&mrioc->trigger_lock);
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Geraldo Nascimento geraldogabriel@gmail.com
[ Upstream commit cbbfe9f683f0f9b6a1da2eaa53b995a4b5961086 ]
Current code uses custom-defined register offsets and bitfields for the standard PCIe registers. This creates duplication as the PCI header already defines them. So, switch to using the standard PCIe definitions and drop the custom ones.
Suggested-by: Bjorn Helgaas bhelgaas@google.com Signed-off-by: Geraldo Nascimento geraldogabriel@gmail.com [mani: commit message rewording] Signed-off-by: Manivannan Sadhasivam mani@kernel.org [bhelgaas: include bitfield.h] Signed-off-by: Bjorn Helgaas bhelgaas@google.com Link: https://patch.msgid.link/e81700ef4b49f584bc8834bfb07b6d8995fc1f42.1751322015... Stable-dep-of: 114b06ee108c ("PCI: rockchip: Set Target Link Speed to 5.0 GT/s before retraining") Signed-off-by: Sasha Levin sashal@kernel.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/pci/controller/pcie-rockchip-ep.c | 4 +- drivers/pci/controller/pcie-rockchip-host.c | 45 ++++++++++++++-------------- drivers/pci/controller/pcie-rockchip.h | 12 ------- 3 files changed, 26 insertions(+), 35 deletions(-)
--- a/drivers/pci/controller/pcie-rockchip-ep.c +++ b/drivers/pci/controller/pcie-rockchip-ep.c @@ -518,9 +518,9 @@ static void rockchip_pcie_ep_retrain_lin { u32 status;
- status = rockchip_pcie_read(rockchip, PCIE_EP_CONFIG_LCS); + status = rockchip_pcie_read(rockchip, PCIE_EP_CONFIG_BASE + PCI_EXP_LNKCTL); status |= PCI_EXP_LNKCTL_RL; - rockchip_pcie_write(rockchip, status, PCIE_EP_CONFIG_LCS); + rockchip_pcie_write(rockchip, status, PCIE_EP_CONFIG_BASE + PCI_EXP_LNKCTL); }
static bool rockchip_pcie_ep_link_up(struct rockchip_pcie *rockchip) --- a/drivers/pci/controller/pcie-rockchip-host.c +++ b/drivers/pci/controller/pcie-rockchip-host.c @@ -11,6 +11,7 @@ * ARM PCI Host generic driver. */
+#include <linux/bitfield.h> #include <linux/bitrev.h> #include <linux/clk.h> #include <linux/delay.h> @@ -40,18 +41,18 @@ static void rockchip_pcie_enable_bw_int( { u32 status;
- status = rockchip_pcie_read(rockchip, PCIE_RC_CONFIG_LCS); + status = rockchip_pcie_read(rockchip, PCIE_RC_CONFIG_CR + PCI_EXP_LNKCTL); status |= (PCI_EXP_LNKCTL_LBMIE | PCI_EXP_LNKCTL_LABIE); - rockchip_pcie_write(rockchip, status, PCIE_RC_CONFIG_LCS); + rockchip_pcie_write(rockchip, status, PCIE_RC_CONFIG_CR + PCI_EXP_LNKCTL); }
static void rockchip_pcie_clr_bw_int(struct rockchip_pcie *rockchip) { u32 status;
- status = rockchip_pcie_read(rockchip, PCIE_RC_CONFIG_LCS); + status = rockchip_pcie_read(rockchip, PCIE_RC_CONFIG_CR + PCI_EXP_LNKCTL); status |= (PCI_EXP_LNKSTA_LBMS | PCI_EXP_LNKSTA_LABS) << 16; - rockchip_pcie_write(rockchip, status, PCIE_RC_CONFIG_LCS); + rockchip_pcie_write(rockchip, status, PCIE_RC_CONFIG_CR + PCI_EXP_LNKCTL); }
static void rockchip_pcie_update_txcredit_mui(struct rockchip_pcie *rockchip) @@ -269,7 +270,7 @@ static void rockchip_pcie_set_power_limi scale = 3; /* 0.001x */ curr = curr / 1000; /* convert to mA */ power = (curr * 3300) / 1000; /* milliwatt */ - while (power > PCIE_RC_CONFIG_DCR_CSPL_LIMIT) { + while (power > FIELD_MAX(PCI_EXP_DEVCAP_PWR_VAL)) { if (!scale) { dev_warn(rockchip->dev, "invalid power supply\n"); return; @@ -278,10 +279,10 @@ static void rockchip_pcie_set_power_limi power = power / 10; }
- status = rockchip_pcie_read(rockchip, PCIE_RC_CONFIG_DCR); - status |= (power << PCIE_RC_CONFIG_DCR_CSPL_SHIFT) | - (scale << PCIE_RC_CONFIG_DCR_CPLS_SHIFT); - rockchip_pcie_write(rockchip, status, PCIE_RC_CONFIG_DCR); + status = rockchip_pcie_read(rockchip, PCIE_RC_CONFIG_CR + PCI_EXP_DEVCAP); + status |= FIELD_PREP(PCI_EXP_DEVCAP_PWR_VAL, power); + status |= FIELD_PREP(PCI_EXP_DEVCAP_PWR_SCL, scale); + rockchip_pcie_write(rockchip, status, PCIE_RC_CONFIG_CR + PCI_EXP_DEVCAP); }
/** @@ -309,14 +310,14 @@ static int rockchip_pcie_host_init_port( rockchip_pcie_set_power_limit(rockchip);
/* Set RC's clock architecture as common clock */ - status = rockchip_pcie_read(rockchip, PCIE_RC_CONFIG_LCS); + status = rockchip_pcie_read(rockchip, PCIE_RC_CONFIG_CR + PCI_EXP_LNKCTL); status |= PCI_EXP_LNKSTA_SLC << 16; - rockchip_pcie_write(rockchip, status, PCIE_RC_CONFIG_LCS); + rockchip_pcie_write(rockchip, status, PCIE_RC_CONFIG_CR + PCI_EXP_LNKCTL);
/* Set RC's RCB to 128 */ - status = rockchip_pcie_read(rockchip, PCIE_RC_CONFIG_LCS); + status = rockchip_pcie_read(rockchip, PCIE_RC_CONFIG_CR + PCI_EXP_LNKCTL); status |= PCI_EXP_LNKCTL_RCB; - rockchip_pcie_write(rockchip, status, PCIE_RC_CONFIG_LCS); + rockchip_pcie_write(rockchip, status, PCIE_RC_CONFIG_CR + PCI_EXP_LNKCTL);
/* Enable Gen1 training */ rockchip_pcie_write(rockchip, PCIE_CLIENT_LINK_TRAIN_ENABLE, @@ -341,9 +342,9 @@ static int rockchip_pcie_host_init_port( * Enable retrain for gen2. This should be configured only after * gen1 finished. */ - status = rockchip_pcie_read(rockchip, PCIE_RC_CONFIG_LCS); + status = rockchip_pcie_read(rockchip, PCIE_RC_CONFIG_CR + PCI_EXP_LNKCTL); status |= PCI_EXP_LNKCTL_RL; - rockchip_pcie_write(rockchip, status, PCIE_RC_CONFIG_LCS); + rockchip_pcie_write(rockchip, status, PCIE_RC_CONFIG_CR + PCI_EXP_LNKCTL);
err = readl_poll_timeout(rockchip->apb_base + PCIE_CORE_CTRL, status, PCIE_LINK_IS_GEN2(status), 20, @@ -380,15 +381,15 @@ static int rockchip_pcie_host_init_port(
/* Clear L0s from RC's link cap */ if (of_property_read_bool(dev->of_node, "aspm-no-l0s")) { - status = rockchip_pcie_read(rockchip, PCIE_RC_CONFIG_LINK_CAP); - status &= ~PCIE_RC_CONFIG_LINK_CAP_L0S; - rockchip_pcie_write(rockchip, status, PCIE_RC_CONFIG_LINK_CAP); + status = rockchip_pcie_read(rockchip, PCIE_RC_CONFIG_CR + PCI_EXP_LNKCAP); + status &= ~PCI_EXP_LNKCAP_ASPM_L0S; + rockchip_pcie_write(rockchip, status, PCIE_RC_CONFIG_CR + PCI_EXP_LNKCAP); }
- status = rockchip_pcie_read(rockchip, PCIE_RC_CONFIG_DCSR); - status &= ~PCIE_RC_CONFIG_DCSR_MPS_MASK; - status |= PCIE_RC_CONFIG_DCSR_MPS_256; - rockchip_pcie_write(rockchip, status, PCIE_RC_CONFIG_DCSR); + status = rockchip_pcie_read(rockchip, PCIE_RC_CONFIG_CR + PCI_EXP_DEVCTL); + status &= ~PCI_EXP_DEVCTL_PAYLOAD; + status |= PCI_EXP_DEVCTL_PAYLOAD_256B; + rockchip_pcie_write(rockchip, status, PCIE_RC_CONFIG_CR + PCI_EXP_DEVCTL);
return 0; err_power_off_phy: --- a/drivers/pci/controller/pcie-rockchip.h +++ b/drivers/pci/controller/pcie-rockchip.h @@ -155,17 +155,7 @@ #define PCIE_EP_CONFIG_DID_VID (PCIE_EP_CONFIG_BASE + 0x00) #define PCIE_EP_CONFIG_LCS (PCIE_EP_CONFIG_BASE + 0xd0) #define PCIE_RC_CONFIG_RID_CCR (PCIE_RC_CONFIG_BASE + 0x08) -#define PCIE_RC_CONFIG_DCR (PCIE_RC_CONFIG_BASE + 0xc4) -#define PCIE_RC_CONFIG_DCR_CSPL_SHIFT 18 -#define PCIE_RC_CONFIG_DCR_CSPL_LIMIT 0xff -#define PCIE_RC_CONFIG_DCR_CPLS_SHIFT 26 -#define PCIE_RC_CONFIG_DCSR (PCIE_RC_CONFIG_BASE + 0xc8) -#define PCIE_RC_CONFIG_DCSR_MPS_MASK GENMASK(7, 5) -#define PCIE_RC_CONFIG_DCSR_MPS_256 (0x1 << 5) -#define PCIE_RC_CONFIG_LINK_CAP (PCIE_RC_CONFIG_BASE + 0xcc) -#define PCIE_RC_CONFIG_LINK_CAP_L0S BIT(10) -#define PCIE_RC_CONFIG_LCS (PCIE_RC_CONFIG_BASE + 0xd0) -#define PCIE_EP_CONFIG_LCS (PCIE_EP_CONFIG_BASE + 0xd0) +#define PCIE_RC_CONFIG_CR (PCIE_RC_CONFIG_BASE + 0xc0) #define PCIE_RC_CONFIG_L1_SUBSTATE_CTRL2 (PCIE_RC_CONFIG_BASE + 0x90c) #define PCIE_RC_CONFIG_THP_CAP (PCIE_RC_CONFIG_BASE + 0x274) #define PCIE_RC_CONFIG_THP_CAP_NEXT_MASK GENMASK(31, 20)
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Geraldo Nascimento geraldogabriel@gmail.com
[ Upstream commit 114b06ee108cabc82b995fbac6672230a9776936 ]
Rockchip controllers can support up to 5.0 GT/s link speed. But the driver doesn't set the Target Link Speed currently. This may cause failure in retraining the link to 5.0 GT/s if supported by the endpoint. So set the Target Link Speed to 5.0 GT/s in the Link Control and Status Register 2.
Fixes: e77f847df54c ("PCI: rockchip: Add Rockchip PCIe controller support") Signed-off-by: Geraldo Nascimento geraldogabriel@gmail.com [mani: fixed whitespace warning, commit message rewording, added fixes tag] Signed-off-by: Manivannan Sadhasivam mani@kernel.org Signed-off-by: Bjorn Helgaas bhelgaas@google.com Tested-by: Robin Murphy robin.murphy@arm.com Cc: stable@vger.kernel.org Link: https://patch.msgid.link/0afa6bc47b7f50e2e81b0b47d51c66feb0fb565f.1751322015... Signed-off-by: Sasha Levin sashal@kernel.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/pci/controller/pcie-rockchip-host.c | 4 ++++ 1 file changed, 4 insertions(+)
--- a/drivers/pci/controller/pcie-rockchip-host.c +++ b/drivers/pci/controller/pcie-rockchip-host.c @@ -342,6 +342,10 @@ static int rockchip_pcie_host_init_port( * Enable retrain for gen2. This should be configured only after * gen1 finished. */ + status = rockchip_pcie_read(rockchip, PCIE_RC_CONFIG_CR + PCI_EXP_LNKCTL2); + status &= ~PCI_EXP_LNKCTL2_TLS; + status |= PCI_EXP_LNKCTL2_TLS_5_0GT; + rockchip_pcie_write(rockchip, status, PCIE_RC_CONFIG_CR + PCI_EXP_LNKCTL2); status = rockchip_pcie_read(rockchip, PCIE_RC_CONFIG_CR + PCI_EXP_LNKCTL); status |= PCI_EXP_LNKCTL_RL; rockchip_pcie_write(rockchip, status, PCIE_RC_CONFIG_CR + PCI_EXP_LNKCTL);
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Liu01 Tong Tong.Liu01@amd.com
commit aa5fc4362fac9351557eb27c745579159a2e4520 upstream.
During process kill, drm_sched_entity_flush() will kill the vm entities. The following job submissions of this process will fail, and the resources of these jobs have not been released, nor have the fences been signalled, causing tasks to hang and timeout.
Fix by check entity status in amdgpu_vm_ready() and avoid submit jobs to stopped entity.
v2: add amdgpu_vm_ready() check before amdgpu_vm_clear_freed() in function amdgpu_cs_vm_handling().
Fixes: 1f02f2044bda ("drm/amdgpu: Avoid extra evict-restore process.") Signed-off-by: Liu01 Tong Tong.Liu01@amd.com Signed-off-by: Lin.Cao lincao12@amd.com Reviewed-by: Christian König christian.koenig@amd.com Signed-off-by: Alex Deucher alexander.deucher@amd.com (cherry picked from commit f101c13a8720c73e67f8f9d511fbbeda95bcedb1) Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c | 3 +++ drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c | 15 +++++++++++---- 2 files changed, 14 insertions(+), 4 deletions(-)
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c @@ -1138,6 +1138,9 @@ static int amdgpu_cs_vm_handling(struct } }
+ if (!amdgpu_vm_ready(vm)) + return -EINVAL; + r = amdgpu_vm_clear_freed(adev, vm, NULL); if (r) return r; --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c @@ -654,11 +654,10 @@ int amdgpu_vm_validate(struct amdgpu_dev * Check if all VM PDs/PTs are ready for updates * * Returns: - * True if VM is not evicting. + * True if VM is not evicting and all VM entities are not stopped */ bool amdgpu_vm_ready(struct amdgpu_vm *vm) { - bool empty; bool ret;
amdgpu_vm_eviction_lock(vm); @@ -666,10 +665,18 @@ bool amdgpu_vm_ready(struct amdgpu_vm *v amdgpu_vm_eviction_unlock(vm);
spin_lock(&vm->status_lock); - empty = list_empty(&vm->evicted); + ret &= list_empty(&vm->evicted); spin_unlock(&vm->status_lock);
- return ret && empty; + spin_lock(&vm->immediate.lock); + ret &= !vm->immediate.stopped; + spin_unlock(&vm->immediate.lock); + + spin_lock(&vm->delayed.lock); + ret &= !vm->delayed.stopped; + spin_unlock(&vm->delayed.lock); + + return ret; }
/**
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Dan Carpenter dan.carpenter@linaro.org
commit 9f35ab0e53ccbea57bb9cbad8065e0406d516195 upstream.
This function is supposed to return true for valid headers and false for invalid. In a couple places it returns -EINVAL instead which means the invalid headers are counted as true. Change it to return false.
Fixes: 9f9967fed9d0 ("soc: qcom: mdt_loader: Ensure we don't read past the ELF header") Signed-off-by: Dan Carpenter dan.carpenter@linaro.org Reviewed-by: Konrad Dybcio konrad.dybcio@oss.qualcomm.com Link: https://lore.kernel.org/r/db57c01c-bdcc-4a0f-95db-b0f2784ea91f@sabinyo.mount... Signed-off-by: Bjorn Andersson andersson@kernel.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/soc/qcom/mdt_loader.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
--- a/drivers/soc/qcom/mdt_loader.c +++ b/drivers/soc/qcom/mdt_loader.c @@ -33,14 +33,14 @@ static bool mdt_header_valid(const struc return false;
if (ehdr->e_phentsize != sizeof(struct elf32_phdr)) - return -EINVAL; + return false;
phend = size_add(size_mul(sizeof(struct elf32_phdr), ehdr->e_phnum), ehdr->e_phoff); if (phend > fw->size) return false;
if (ehdr->e_shentsize != sizeof(struct elf32_shdr)) - return -EINVAL; + return false;
shend = size_add(size_mul(sizeof(struct elf32_shdr), ehdr->e_shnum), ehdr->e_shoff); if (shend > fw->size)
Hi Greg,
On Tue, Aug 26, 2025 at 01:09:22PM +0200, Greg Kroah-Hartman wrote:
6.16-stable review patch. If anyone has any objections, please let me know.
From: Dan Carpenter dan.carpenter@linaro.org
commit 9f35ab0e53ccbea57bb9cbad8065e0406d516195 upstream.
This function is supposed to return true for valid headers and false for invalid. In a couple places it returns -EINVAL instead which means the invalid headers are counted as true. Change it to return false.
Fixes: 9f9967fed9d0 ("soc: qcom: mdt_loader: Ensure we don't read past the ELF header") Signed-off-by: Dan Carpenter dan.carpenter@linaro.org Reviewed-by: Konrad Dybcio konrad.dybcio@oss.qualcomm.com Link: https://lore.kernel.org/r/db57c01c-bdcc-4a0f-95db-b0f2784ea91f@sabinyo.mount... Signed-off-by: Bjorn Andersson andersson@kernel.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org
This patch breaks firmware loading on most Qualcomm platforms, see e.g. the replies from Val and Neil on the original patch [1, 2].
There is a fix pending, which should soon land in mainline: https://git.kernel.org/pub/scm/linux/kernel/git/qcom/linux.git/commit/?h=qco...
For the next 5.4-6.16 stable releases, could you pick up either the fix or revert this patch together with commit "soc: qcom: mdt_loader: Ensure we dont read past the ELF header"?
The problematic commit ("soc: qcom: mdt_loader: Fix error return values in mdt_header_valid()") wasn't backported directly to 5.4-6.1, but a quick look suggests that Sasha squashed the problematic change in the manual backports of "soc: qcom: mdt_loader: Ensure we dont read past the ELF header" (at least for 5.4-5.15). I think we will need the fix for all trees (5.4-6.16), or we should revert the patch(es) to avoid the regression.
Thanks, Stephan
[1]: https://lore.kernel.org/linux-arm-msm/ece307c3-7d65-440f-babd-88cf9705b908@p... [2]: https://lore.kernel.org/linux-arm-msm/aec9cd03-6fc2-4dc8-b937-8b7cf7bf4128@l...
On Sun, Aug 31, 2025 at 06:52:09PM +0200, Stephan Gerhold wrote:
Hi Greg,
On Tue, Aug 26, 2025 at 01:09:22PM +0200, Greg Kroah-Hartman wrote:
6.16-stable review patch. If anyone has any objections, please let me know.
From: Dan Carpenter dan.carpenter@linaro.org
commit 9f35ab0e53ccbea57bb9cbad8065e0406d516195 upstream.
This function is supposed to return true for valid headers and false for invalid. In a couple places it returns -EINVAL instead which means the invalid headers are counted as true. Change it to return false.
Fixes: 9f9967fed9d0 ("soc: qcom: mdt_loader: Ensure we don't read past the ELF header") Signed-off-by: Dan Carpenter dan.carpenter@linaro.org Reviewed-by: Konrad Dybcio konrad.dybcio@oss.qualcomm.com Link: https://lore.kernel.org/r/db57c01c-bdcc-4a0f-95db-b0f2784ea91f@sabinyo.mount... Signed-off-by: Bjorn Andersson andersson@kernel.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org
This patch breaks firmware loading on most Qualcomm platforms, see e.g. the replies from Val and Neil on the original patch [1, 2].
There is a fix pending, which should soon land in mainline: https://git.kernel.org/pub/scm/linux/kernel/git/qcom/linux.git/commit/?h=qco...
For the next 5.4-6.16 stable releases, could you pick up either the fix or revert this patch together with commit "soc: qcom: mdt_loader: Ensure we dont read past the ELF header"?
The problematic commit ("soc: qcom: mdt_loader: Fix error return values in mdt_header_valid()") wasn't backported directly to 5.4-6.1, but a quick look suggests that Sasha squashed the problematic change in the manual backports of "soc: qcom: mdt_loader: Ensure we dont read past the ELF header" (at least for 5.4-5.15). I think we will need the fix for all trees (5.4-6.16), or we should revert the patch(es) to avoid the regression.
Oh, heh, when I backported it I got a warning from the compiler so I assumed it was because of API differences on older trees, so I just fixed it up. Haven't realized it was broken upstream too.
We can wait for the fix to land and take it in too.
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Christoph Hellwig hch@lst.de
commit 647b3d59c768d7638dd17c78c8044178364383ca upstream.
Commit 83a80e95e797 ("xfs: decouple xfs_trans_alloc_empty from xfs_trans_alloc") move the place of the assert for a frozen file system after the sb_start_intwrite call that ensures it doesn't run on frozen file systems, and thus allows to incorrect trigger it.
Fix that by moving it back to where it belongs.
Fixes: 83a80e95e797 ("xfs: decouple xfs_trans_alloc_empty from xfs_trans_alloc") Reported-by: Dave Chinner david@fromorbit.com Signed-off-by: Christoph Hellwig hch@lst.de Reviewed-by: Darrick J. Wong djwong@kernel.org Signed-off-by: Carlos Maiolino cem@kernel.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- fs/xfs/xfs_trans.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
--- a/fs/xfs/xfs_trans.c +++ b/fs/xfs/xfs_trans.c @@ -284,8 +284,8 @@ xfs_trans_alloc( * by doing GFP_KERNEL allocations inside sb_start_intwrite(). */ retry: - WARN_ON(mp->m_super->s_writers.frozen == SB_FREEZE_COMPLETE); tp = __xfs_trans_alloc(mp, flags); + WARN_ON(mp->m_super->s_writers.frozen == SB_FREEZE_COMPLETE); error = xfs_trans_reserve(tp, resp, blocks, rtextents); if (error == -ENOSPC && want_retry) { xfs_trans_cancel(tp);
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Miguel Ojeda ojeda@kernel.org
commit a5ba9ad417254c49ecf06ac5ab36ec4b12ee133f upstream.
Starting with Rust 1.91.0 (expected 2025-10-30), `rustdoc` has improved some false negatives around intra-doc links [1], and it found a broken intra-doc link we currently have:
error: unresolved link to `include/linux/device/faux.h` --> rust/kernel/faux.rs:7:17 | 7 | //! C header: [`include/linux/device/faux.h`] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ no item named `include/linux/device/faux.h` in scope | = help: to escape `[` and `]` characters, add '' before them like `[` or `]` = note: `-D rustdoc::broken-intra-doc-links` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(rustdoc::broken_intra_doc_links)]`
Our `srctree/` C header links are not intra-doc links, thus they need the link destination.
Thus fix it.
Cc: stable stable@kernel.org Link: https://github.com/rust-lang/rust/pull/132748 [1] Fixes: 78418f300d39 ("rust/kernel: Add faux device bindings") Signed-off-by: Miguel Ojeda ojeda@kernel.org Reviewed-by: Benno Lossin lossin@kernel.org Reviewed-by: Alice Ryhl aliceryhl@google.com Link: https://lore.kernel.org/r/20250804171311.1186538-1-ojeda@kernel.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- rust/kernel/faux.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/rust/kernel/faux.rs b/rust/kernel/faux.rs index 7a906099993f..7fe2dd197e37 100644 --- a/rust/kernel/faux.rs +++ b/rust/kernel/faux.rs @@ -4,7 +4,7 @@ //! //! This module provides bindings for working with faux devices in kernel modules. //! -//! C header: [`include/linux/device/faux.h`] +//! C header: [`include/linux/device/faux.h`](srctree/include/linux/device/faux.h)
use crate::{bindings, device, error::code::*, prelude::*}; use core::ptr::{addr_of_mut, null, null_mut, NonNull};
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Charalampos Mitrodimas charmitro@posteo.net
commit ba6cc29351b1fa0cb9adce91b88b9f3c3cbe9c46 upstream.
Mount options (uid, gid, mode) are silently ignored when debugfs is mounted. This is a regression introduced during the conversion to the new mount API.
When the mount API conversion was done, the parsed options were never applied to the superblock when it was reused. As a result, the mount options were ignored when debugfs was mounted.
Fix this by following the same pattern as the tracefs fix in commit e4d32142d1de ("tracing: Fix tracefs mount options"). Call debugfs_reconfigure() in debugfs_get_tree() to apply the mount options to the superblock after it has been created or reused.
As an example, with the bug the "mode" mount option is ignored:
$ mount -o mode=0666 -t debugfs debugfs /tmp/debugfs_test $ mount | grep debugfs_test debugfs on /tmp/debugfs_test type debugfs (rw,relatime) $ ls -ld /tmp/debugfs_test drwx------ 25 root root 0 Aug 4 14:16 /tmp/debugfs_test
With the fix applied, it works as expected:
$ mount -o mode=0666 -t debugfs debugfs /tmp/debugfs_test $ mount | grep debugfs_test debugfs on /tmp/debugfs_test type debugfs (rw,relatime,mode=666) $ ls -ld /tmp/debugfs_test drw-rw-rw- 37 root root 0 Aug 2 17:28 /tmp/debugfs_test
Fixes: a20971c18752 ("vfs: Convert debugfs to use the new mount API") Closes: https://bugzilla.kernel.org/show_bug.cgi?id=220406 Cc: stable stable@kernel.org Reviewed-by: Eric Sandeen sandeen@redhat.com Signed-off-by: Charalampos Mitrodimas charmitro@posteo.net Link: https://lore.kernel.org/r/20250816-debugfs-mount-opts-v3-1-d271dad57b5b@post... Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- fs/debugfs/inode.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-)
--- a/fs/debugfs/inode.c +++ b/fs/debugfs/inode.c @@ -183,6 +183,9 @@ static int debugfs_reconfigure(struct fs struct debugfs_fs_info *sb_opts = sb->s_fs_info; struct debugfs_fs_info *new_opts = fc->s_fs_info;
+ if (!new_opts) + return 0; + sync_filesystem(sb);
/* structure copy of new mount options to sb */ @@ -282,10 +285,16 @@ static int debugfs_fill_super(struct sup
static int debugfs_get_tree(struct fs_context *fc) { + int err; + if (!(debugfs_allow & DEBUGFS_ALLOW_API)) return -EPERM;
- return get_tree_single(fc, debugfs_fill_super); + err = get_tree_single(fc, debugfs_fill_super); + if (err) + return err; + + return debugfs_reconfigure(fc); }
static void debugfs_free_fc(struct fs_context *fc)
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Yuntao Wang yuntao.wang@linux.dev
[ Upstream commit 593d9e4c3d634c370f226f55453c376bf43b3684 ]
The lflags value used to look up from_path was overwritten by the one used to look up to_path.
In other words, from_path was looked up with the wrong lflags value. Fix it.
Fixes: f9fde814de37 ("fs: support getname_maybe_null() in move_mount()") Signed-off-by: Yuntao Wang yuntao.wang@linux.dev Link: https://lore.kernel.org/20250811052426.129188-1-yuntao.wang@linux.dev [Christian Brauner brauner@kernel.org: massage patch] Signed-off-by: Christian Brauner brauner@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- fs/namespace.c | 32 ++++++++++++++++++++------------ 1 file changed, 20 insertions(+), 12 deletions(-)
diff --git a/fs/namespace.c b/fs/namespace.c index ea724ad3d113..49d016711469 100644 --- a/fs/namespace.c +++ b/fs/namespace.c @@ -4657,20 +4657,10 @@ SYSCALL_DEFINE5(move_mount, if (flags & MOVE_MOUNT_SET_GROUP) mflags |= MNT_TREE_PROPAGATION; if (flags & MOVE_MOUNT_BENEATH) mflags |= MNT_TREE_BENEATH;
- lflags = 0; - if (flags & MOVE_MOUNT_F_SYMLINKS) lflags |= LOOKUP_FOLLOW; - if (flags & MOVE_MOUNT_F_AUTOMOUNTS) lflags |= LOOKUP_AUTOMOUNT; uflags = 0; - if (flags & MOVE_MOUNT_F_EMPTY_PATH) uflags = AT_EMPTY_PATH; - from_name = getname_maybe_null(from_pathname, uflags); - if (IS_ERR(from_name)) - return PTR_ERR(from_name); + if (flags & MOVE_MOUNT_T_EMPTY_PATH) + uflags = AT_EMPTY_PATH;
- lflags = 0; - if (flags & MOVE_MOUNT_T_SYMLINKS) lflags |= LOOKUP_FOLLOW; - if (flags & MOVE_MOUNT_T_AUTOMOUNTS) lflags |= LOOKUP_AUTOMOUNT; - uflags = 0; - if (flags & MOVE_MOUNT_T_EMPTY_PATH) uflags = AT_EMPTY_PATH; to_name = getname_maybe_null(to_pathname, uflags); if (IS_ERR(to_name)) return PTR_ERR(to_name); @@ -4683,11 +4673,24 @@ SYSCALL_DEFINE5(move_mount, to_path = fd_file(f_to)->f_path; path_get(&to_path); } else { + lflags = 0; + if (flags & MOVE_MOUNT_T_SYMLINKS) + lflags |= LOOKUP_FOLLOW; + if (flags & MOVE_MOUNT_T_AUTOMOUNTS) + lflags |= LOOKUP_AUTOMOUNT; ret = filename_lookup(to_dfd, to_name, lflags, &to_path, NULL); if (ret) return ret; }
+ uflags = 0; + if (flags & MOVE_MOUNT_F_EMPTY_PATH) + uflags = AT_EMPTY_PATH; + + from_name = getname_maybe_null(from_pathname, uflags); + if (IS_ERR(from_name)) + return PTR_ERR(from_name); + if (!from_name && from_dfd >= 0) { CLASS(fd_raw, f_from)(from_dfd); if (fd_empty(f_from)) @@ -4696,6 +4699,11 @@ SYSCALL_DEFINE5(move_mount, return vfs_move_mount(&fd_file(f_from)->f_path, &to_path, mflags); }
+ lflags = 0; + if (flags & MOVE_MOUNT_F_SYMLINKS) + lflags |= LOOKUP_FOLLOW; + if (flags & MOVE_MOUNT_F_AUTOMOUNTS) + lflags |= LOOKUP_AUTOMOUNT; ret = filename_lookup(from_dfd, from_name, lflags, &from_path, NULL); if (ret) return ret;
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Naohiro Aota naohiro.aota@wdc.com
[ Upstream commit daa0fde322350b467bc62bc1b141bf62df6123f8 ]
btrfs_zoned_reserve_data_reloc_bg() is called on mount and at that point, all data block groups belong to the primary data space_info. So, we don't find anything in the data relocation space_info.
Also, the condition "bg->used > 0" can select a block group with full of zone_unusable bytes for the candidate. As we cannot allocate from the block group, it is useless to reserve it as the data relocation block group.
Furthermore, because of the space_info separation, we need to migrate the selected block group to the data relocation space_info. If not, the extent allocator cannot use the block group to do the allocation.
This commit fixes these three issues.
Fixes: e606ff985ec7 ("btrfs: zoned: reserve data_reloc block group on mount") Reviewed-by: Johannes Thumshirn johannes.thumshirn@wdc.com Signed-off-by: Naohiro Aota naohiro.aota@wdc.com Signed-off-by: David Sterba dsterba@suse.com Signed-off-by: Sasha Levin sashal@kernel.org --- fs/btrfs/zoned.c | 55 +++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 47 insertions(+), 8 deletions(-)
diff --git a/fs/btrfs/zoned.c b/fs/btrfs/zoned.c index 936448b1f716..af5ba3ad2eb8 100644 --- a/fs/btrfs/zoned.c +++ b/fs/btrfs/zoned.c @@ -18,6 +18,7 @@ #include "accessors.h" #include "bio.h" #include "transaction.h" +#include "sysfs.h"
/* Maximum number of zones to report per blkdev_report_zones() call */ #define BTRFS_REPORT_NR_ZONES 4096 @@ -2510,12 +2511,12 @@ void btrfs_clear_data_reloc_bg(struct btrfs_block_group *bg) void btrfs_zoned_reserve_data_reloc_bg(struct btrfs_fs_info *fs_info) { struct btrfs_space_info *data_sinfo = fs_info->data_sinfo; - struct btrfs_space_info *space_info = data_sinfo->sub_group[0]; + struct btrfs_space_info *space_info = data_sinfo; struct btrfs_trans_handle *trans; struct btrfs_block_group *bg; struct list_head *bg_list; u64 alloc_flags; - bool initial = false; + bool first = true; bool did_chunk_alloc = false; int index; int ret; @@ -2529,21 +2530,52 @@ void btrfs_zoned_reserve_data_reloc_bg(struct btrfs_fs_info *fs_info) if (sb_rdonly(fs_info->sb)) return;
- ASSERT(space_info->subgroup_id == BTRFS_SUB_GROUP_DATA_RELOC); alloc_flags = btrfs_get_alloc_profile(fs_info, space_info->flags); index = btrfs_bg_flags_to_raid_index(alloc_flags);
- bg_list = &data_sinfo->block_groups[index]; + /* Scan the data space_info to find empty block groups. Take the second one. */ again: + bg_list = &space_info->block_groups[index]; list_for_each_entry(bg, bg_list, list) { - if (bg->used > 0) + if (bg->alloc_offset != 0) continue;
- if (!initial) { - initial = true; + if (first) { + first = false; continue; }
+ if (space_info == data_sinfo) { + /* Migrate the block group to the data relocation space_info. */ + struct btrfs_space_info *reloc_sinfo = data_sinfo->sub_group[0]; + int factor; + + ASSERT(reloc_sinfo->subgroup_id == BTRFS_SUB_GROUP_DATA_RELOC); + factor = btrfs_bg_type_to_factor(bg->flags); + + down_write(&space_info->groups_sem); + list_del_init(&bg->list); + /* We can assume this as we choose the second empty one. */ + ASSERT(!list_empty(&space_info->block_groups[index])); + up_write(&space_info->groups_sem); + + spin_lock(&space_info->lock); + space_info->total_bytes -= bg->length; + space_info->disk_total -= bg->length * factor; + /* There is no allocation ever happened. */ + ASSERT(bg->used == 0); + ASSERT(bg->zone_unusable == 0); + /* No super block in a block group on the zoned setup. */ + ASSERT(bg->bytes_super == 0); + spin_unlock(&space_info->lock); + + bg->space_info = reloc_sinfo; + if (reloc_sinfo->block_group_kobjs[index] == NULL) + btrfs_sysfs_add_block_group_type(bg); + + btrfs_add_bg_to_space_info(fs_info, bg); + } + fs_info->data_reloc_bg = bg->start; set_bit(BLOCK_GROUP_FLAG_ZONED_DATA_RELOC, &bg->runtime_flags); btrfs_zone_activate(bg); @@ -2558,11 +2590,18 @@ void btrfs_zoned_reserve_data_reloc_bg(struct btrfs_fs_info *fs_info) if (IS_ERR(trans)) return;
+ /* Allocate new BG in the data relocation space_info. */ + space_info = data_sinfo->sub_group[0]; + ASSERT(space_info->subgroup_id == BTRFS_SUB_GROUP_DATA_RELOC); ret = btrfs_chunk_alloc(trans, space_info, alloc_flags, CHUNK_ALLOC_FORCE); btrfs_end_transaction(trans); if (ret == 1) { + /* + * We allocated a new block group in the data relocation space_info. We + * can take that one. + */ + first = false; did_chunk_alloc = true; - bg_list = &space_info->block_groups[index]; goto again; } }
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Thomas Bertschinger tahbertschinger@gmail.com
[ Upstream commit b5ca88927e353185b3d9ac4362d33e5aeb25771f ]
In f07c7cc4684a, do_handle_open() was switched to use the automatic cleanup method for getting a FD. In that change it was also switched to pass O_CLOEXEC unconditionally to get_unused_fd_flags() instead of passing the user-specified flags.
I don't see anything in that commit description that indicates this was intentional, so I am assuming it was an oversight.
With this fix, the FD will again be opened with, or without, O_CLOEXEC according to what the user requested.
Fixes: f07c7cc4684a ("fhandle: simplify error handling") Signed-off-by: Thomas Bertschinger tahbertschinger@gmail.com Link: https://lore.kernel.org/20250814235431.995876-4-tahbertschinger@gmail.com Reviewed-by: Amir Goldstein amir73il@gmail.com Signed-off-by: Christian Brauner brauner@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- fs/fhandle.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/fs/fhandle.c b/fs/fhandle.c index 66ff60591d17..e21ec857f2ab 100644 --- a/fs/fhandle.c +++ b/fs/fhandle.c @@ -404,7 +404,7 @@ static long do_handle_open(int mountdirfd, struct file_handle __user *ufh, if (retval) return retval;
- CLASS(get_unused_fd, fd)(O_CLOEXEC); + CLASS(get_unused_fd, fd)(open_flag); if (fd < 0) return fd;
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Christian Brauner brauner@kernel.org
[ Upstream commit bda3f1608d993419fa247dc11263fc931ceca58a ]
* Add a callback to struct stashed_operations so it's possible to implement custom behavior for pidfs and allow for it to return errors.
* Teach stashed_dentry_get() to handle error pointers.
Link: https://lore.kernel.org/20250618-work-pidfs-persistent-v2-2-98f3456fd552@ker... Reviewed-by: Alexander Mikhalitsyn aleksandr.mikhalitsyn@canonical.com Signed-off-by: Christian Brauner brauner@kernel.org Stable-dep-of: 0b2d71a7c826 ("pidfs: Fix memory leak in pidfd_info()") Signed-off-by: Sasha Levin sashal@kernel.org --- fs/internal.h | 3 +++ fs/libfs.c | 27 ++++++++++++++++++++------- 2 files changed, 23 insertions(+), 7 deletions(-)
diff --git a/fs/internal.h b/fs/internal.h index 393f6c5c24f6..22ba066d1dba 100644 --- a/fs/internal.h +++ b/fs/internal.h @@ -322,12 +322,15 @@ struct mnt_idmap *alloc_mnt_idmap(struct user_namespace *mnt_userns); struct mnt_idmap *mnt_idmap_get(struct mnt_idmap *idmap); void mnt_idmap_put(struct mnt_idmap *idmap); struct stashed_operations { + struct dentry *(*stash_dentry)(struct dentry **stashed, + struct dentry *dentry); void (*put_data)(void *data); int (*init_inode)(struct inode *inode, void *data); }; int path_from_stashed(struct dentry **stashed, struct vfsmount *mnt, void *data, struct path *path); void stashed_dentry_prune(struct dentry *dentry); +struct dentry *stash_dentry(struct dentry **stashed, struct dentry *dentry); struct dentry *stashed_dentry_get(struct dentry **stashed); /** * path_mounted - check whether path is mounted diff --git a/fs/libfs.c b/fs/libfs.c index 972b95cc7433..5b936ee71892 100644 --- a/fs/libfs.c +++ b/fs/libfs.c @@ -2126,6 +2126,8 @@ struct dentry *stashed_dentry_get(struct dentry **stashed) dentry = rcu_dereference(*stashed); if (!dentry) return NULL; + if (IS_ERR(dentry)) + return dentry; if (!lockref_get_not_dead(&dentry->d_lockref)) return NULL; return dentry; @@ -2174,8 +2176,7 @@ static struct dentry *prepare_anon_dentry(struct dentry **stashed, return dentry; }
-static struct dentry *stash_dentry(struct dentry **stashed, - struct dentry *dentry) +struct dentry *stash_dentry(struct dentry **stashed, struct dentry *dentry) { guard(rcu)(); for (;;) { @@ -2216,12 +2217,15 @@ static struct dentry *stash_dentry(struct dentry **stashed, int path_from_stashed(struct dentry **stashed, struct vfsmount *mnt, void *data, struct path *path) { - struct dentry *dentry; + struct dentry *dentry, *res; const struct stashed_operations *sops = mnt->mnt_sb->s_fs_info;
/* See if dentry can be reused. */ - path->dentry = stashed_dentry_get(stashed); - if (path->dentry) { + res = stashed_dentry_get(stashed); + if (IS_ERR(res)) + return PTR_ERR(res); + if (res) { + path->dentry = res; sops->put_data(data); goto out_path; } @@ -2232,8 +2236,17 @@ int path_from_stashed(struct dentry **stashed, struct vfsmount *mnt, void *data, return PTR_ERR(dentry);
/* Added a new dentry. @data is now owned by the filesystem. */ - path->dentry = stash_dentry(stashed, dentry); - if (path->dentry != dentry) + if (sops->stash_dentry) + res = sops->stash_dentry(stashed, dentry); + else + res = stash_dentry(stashed, dentry); + if (IS_ERR(res)) { + dput(dentry); + return PTR_ERR(res); + } + path->dentry = res; + /* A dentry was reused. */ + if (res != dentry) dput(dentry);
out_path:
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Stefan Metzmacher metze@samba.org
[ Upstream commit bac7b996d42e458a94578f4227795a0d4deef6fa ]
We can't call destroy_workqueue(smb_direct_wq); before stop_sessions()!
Otherwise already existing connections try to use smb_direct_wq as a NULL pointer.
Cc: Namjae Jeon linkinjeon@kernel.org Cc: Steve French smfrench@gmail.com Cc: Tom Talpey tom@talpey.com Cc: linux-cifs@vger.kernel.org Cc: samba-technical@lists.samba.org Fixes: 0626e6641f6b ("cifsd: add server handler for central processing and tranport layers") Signed-off-by: Stefan Metzmacher metze@samba.org Acked-by: Namjae Jeon linkinjeon@kernel.org Signed-off-by: Steve French stfrench@microsoft.com Signed-off-by: Sasha Levin sashal@kernel.org --- fs/smb/server/connection.c | 3 ++- fs/smb/server/transport_rdma.c | 5 ++++- fs/smb/server/transport_rdma.h | 4 +++- 3 files changed, 9 insertions(+), 3 deletions(-)
diff --git a/fs/smb/server/connection.c b/fs/smb/server/connection.c index 3f04a2977ba8..67c4f73398df 100644 --- a/fs/smb/server/connection.c +++ b/fs/smb/server/connection.c @@ -504,7 +504,8 @@ void ksmbd_conn_transport_destroy(void) { mutex_lock(&init_lock); ksmbd_tcp_destroy(); - ksmbd_rdma_destroy(); + ksmbd_rdma_stop_listening(); stop_sessions(); + ksmbd_rdma_destroy(); mutex_unlock(&init_lock); } diff --git a/fs/smb/server/transport_rdma.c b/fs/smb/server/transport_rdma.c index 8d366db5f605..5466aa8c39b1 100644 --- a/fs/smb/server/transport_rdma.c +++ b/fs/smb/server/transport_rdma.c @@ -2194,7 +2194,7 @@ int ksmbd_rdma_init(void) return 0; }
-void ksmbd_rdma_destroy(void) +void ksmbd_rdma_stop_listening(void) { if (!smb_direct_listener.cm_id) return; @@ -2203,7 +2203,10 @@ void ksmbd_rdma_destroy(void) rdma_destroy_id(smb_direct_listener.cm_id);
smb_direct_listener.cm_id = NULL; +}
+void ksmbd_rdma_destroy(void) +{ if (smb_direct_wq) { destroy_workqueue(smb_direct_wq); smb_direct_wq = NULL; diff --git a/fs/smb/server/transport_rdma.h b/fs/smb/server/transport_rdma.h index 77aee4e5c9dc..a2291b77488a 100644 --- a/fs/smb/server/transport_rdma.h +++ b/fs/smb/server/transport_rdma.h @@ -54,13 +54,15 @@ struct smb_direct_data_transfer {
#ifdef CONFIG_SMB_SERVER_SMBDIRECT int ksmbd_rdma_init(void); +void ksmbd_rdma_stop_listening(void); void ksmbd_rdma_destroy(void); bool ksmbd_rdma_capable_netdev(struct net_device *netdev); void init_smbd_max_io_size(unsigned int sz); unsigned int get_smbd_max_read_write_size(void); #else static inline int ksmbd_rdma_init(void) { return 0; } -static inline int ksmbd_rdma_destroy(void) { return 0; } +static inline void ksmbd_rdma_stop_listening(void) { } +static inline void ksmbd_rdma_destroy(void) { } static inline bool ksmbd_rdma_capable_netdev(struct net_device *netdev) { return false; } static inline void init_smbd_max_io_size(unsigned int sz) { } static inline unsigned int get_smbd_max_read_write_size(void) { return 0; }
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ye Bin yebin10@huawei.com
[ Upstream commit 7375f22495e7cd1c5b3b5af9dcc4f6dffe34ce49 ]
There's issue as follows: BUG: KASAN: stack-out-of-bounds in end_buffer_read_sync+0xe3/0x110 Read of size 8 at addr ffffc9000168f7f8 by task swapper/3/0 CPU: 3 UID: 0 PID: 0 Comm: swapper/3 Not tainted 6.16.0-862.14.0.6.x86_64 Hardware name: QEMU Standard PC (i440FX + PIIX, 1996) Call Trace: <IRQ> dump_stack_lvl+0x55/0x70 print_address_description.constprop.0+0x2c/0x390 print_report+0xb4/0x270 kasan_report+0xb8/0xf0 end_buffer_read_sync+0xe3/0x110 end_bio_bh_io_sync+0x56/0x80 blk_update_request+0x30a/0x720 scsi_end_request+0x51/0x2b0 scsi_io_completion+0xe3/0x480 ? scsi_device_unbusy+0x11e/0x160 blk_complete_reqs+0x7b/0x90 handle_softirqs+0xef/0x370 irq_exit_rcu+0xa5/0xd0 sysvec_apic_timer_interrupt+0x6e/0x90 </IRQ>
Above issue happens when do ntfs3 filesystem mount, issue may happens as follows: mount IRQ ntfs_fill_super read_cache_page do_read_cache_folio filemap_read_folio mpage_read_folio do_mpage_readpage ntfs_get_block_vbo bh_read submit_bh wait_on_buffer(bh); blk_complete_reqs scsi_io_completion scsi_end_request blk_update_request end_bio_bh_io_sync end_buffer_read_sync __end_buffer_read_notouch unlock_buffer
wait_on_buffer(bh);--> return will return to caller
put_bh --> trigger stack-out-of-bounds In the mpage_read_folio() function, the stack variable 'map_bh' is passed to ntfs_get_block_vbo(). Once unlock_buffer() unlocks and wait_on_buffer() returns to continue processing, the stack variable is likely to be reclaimed. Consequently, during the end_buffer_read_sync() process, calling put_bh() may result in stack overrun.
If the bh is not allocated on the stack, it belongs to a folio. Freeing a buffer head which belongs to a folio is done by drop_buffers() which will fail to free buffers which are still locked. So it is safe to call put_bh() before __end_buffer_read_notouch().
Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") Signed-off-by: Ye Bin yebin10@huawei.com Link: https://lore.kernel.org/20250811141830.343774-1-yebin@huaweicloud.com Reviewed-by: Matthew Wilcox (Oracle) willy@infradead.org Signed-off-by: Christian Brauner brauner@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- fs/buffer.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/fs/buffer.c b/fs/buffer.c index 8cf4a1dc481e..eb6d85edc37a 100644 --- a/fs/buffer.c +++ b/fs/buffer.c @@ -157,8 +157,8 @@ static void __end_buffer_read_notouch(struct buffer_head *bh, int uptodate) */ void end_buffer_read_sync(struct buffer_head *bh, int uptodate) { - __end_buffer_read_notouch(bh, uptodate); put_bh(bh); + __end_buffer_read_notouch(bh, uptodate); } EXPORT_SYMBOL(end_buffer_read_sync);
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Adrian Huang (Lenovo) adrianhuang0701@gmail.com
[ Upstream commit a2c1f82618b0b65f1ef615aa9cfdac8122537d69 ]
Commit f08d0c3a7111 ("pidfd: add PIDFD_SELF* sentinels to refer to own thread/process") introduced a leak by acquiring a pid reference through get_task_pid(), which increments pid->count but never drops it with put_pid().
As a result, kmemleak reports unreferenced pid objects after running tools/testing/selftests/pidfd/pidfd_test, for example:
unreferenced object 0xff1100206757a940 (size 160): comm "pidfd_test", pid 16965, jiffies 4294853028 hex dump (first 32 bytes): 01 00 00 00 00 00 00 00 00 00 00 00 fd 57 50 04 .............WP. 5e 44 00 00 00 00 00 00 18 de 34 17 01 00 11 ff ^D........4..... backtrace (crc cd8844d4): kmem_cache_alloc_noprof+0x2f4/0x3f0 alloc_pid+0x54/0x3d0 copy_process+0xd58/0x1740 kernel_clone+0x99/0x3b0 __do_sys_clone3+0xbe/0x100 do_syscall_64+0x7b/0x2c0 entry_SYSCALL_64_after_hwframe+0x76/0x7e
Fix this by calling put_pid() after do_pidfd_send_signal() returns.
Fixes: f08d0c3a7111 ("pidfd: add PIDFD_SELF* sentinels to refer to own thread/process") Signed-off-by: Adrian Huang (Lenovo) adrianhuang0701@gmail.com Link: https://lore.kernel.org/20250818134310.12273-1-adrianhuang0701@gmail.com Tested-by: Lorenzo Stoakes lorenzo.stoakes@oracle.com Reviewed-by: Lorenzo Stoakes lorenzo.stoakes@oracle.com Signed-off-by: Christian Brauner brauner@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- kernel/signal.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/kernel/signal.c b/kernel/signal.c index 148082db9a55..6b1493558a3d 100644 --- a/kernel/signal.c +++ b/kernel/signal.c @@ -4067,6 +4067,7 @@ SYSCALL_DEFINE4(pidfd_send_signal, int, pidfd, int, sig, { struct pid *pid; enum pid_type type; + int ret;
/* Enforce flags be set to 0 until we add an extension. */ if (flags & ~PIDFD_SEND_SIGNAL_FLAGS) @@ -4108,7 +4109,10 @@ SYSCALL_DEFINE4(pidfd_send_signal, int, pidfd, int, sig, } }
- return do_pidfd_send_signal(pid, sig, type, info, flags); + ret = do_pidfd_send_signal(pid, sig, type, info, flags); + put_pid(pid); + + return ret; }
static int
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Al Viro viro@zeniv.linux.org.uk
[ Upstream commit cffd0441872e7f6b1fce5e78fb1c99187a291330 ]
do_change_type() and do_set_group() are operating on different aspects of the same thing - propagation graph. The latter asks for mounts involved to be mounted in namespace(s) the caller has CAP_SYS_ADMIN for. The former is a mess - originally it didn't even check that mount *is* mounted. That got fixed, but the resulting check turns out to be too strict for userland - in effect, we check that mount is in our namespace, having already checked that we have CAP_SYS_ADMIN there.
What we really need (in both cases) is * only touch mounts that are mounted. That's a must-have constraint - data corruption happens if it get violated. * don't allow to mess with a namespace unless you already have enough permissions to do so (i.e. CAP_SYS_ADMIN in its userns).
That's an equivalent of what do_set_group() does; let's extract that into a helper (may_change_propagation()) and use it in both do_set_group() and do_change_type().
Fixes: 12f147ddd6de "do_change_type(): refuse to operate on unmounted/not ours mounts" Acked-by: Andrei Vagin avagin@gmail.com Reviewed-by: Pavel Tikhomirov ptikhomirov@virtuozzo.com Tested-by: Pavel Tikhomirov ptikhomirov@virtuozzo.com Reviewed-by: Christian Brauner brauner@kernel.org Signed-off-by: Al Viro viro@zeniv.linux.org.uk Signed-off-by: Sasha Levin sashal@kernel.org --- fs/namespace.c | 34 ++++++++++++++++++++-------------- 1 file changed, 20 insertions(+), 14 deletions(-)
diff --git a/fs/namespace.c b/fs/namespace.c index 49d016711469..6b038bf74a3d 100644 --- a/fs/namespace.c +++ b/fs/namespace.c @@ -2925,6 +2925,19 @@ static int graft_tree(struct mount *mnt, struct mount *p, struct mountpoint *mp) return attach_recursive_mnt(mnt, p, mp, 0); }
+static int may_change_propagation(const struct mount *m) +{ + struct mnt_namespace *ns = m->mnt_ns; + + // it must be mounted in some namespace + if (IS_ERR_OR_NULL(ns)) // is_mounted() + return -EINVAL; + // and the caller must be admin in userns of that namespace + if (!ns_capable(ns->user_ns, CAP_SYS_ADMIN)) + return -EPERM; + return 0; +} + /* * Sanity check the flags to change_mnt_propagation. */ @@ -2961,10 +2974,10 @@ static int do_change_type(struct path *path, int ms_flags) return -EINVAL;
namespace_lock(); - if (!check_mnt(mnt)) { - err = -EINVAL; + err = may_change_propagation(mnt); + if (err) goto out_unlock; - } + if (type == MS_SHARED) { err = invent_group_ids(mnt, recurse); if (err) @@ -3419,18 +3432,11 @@ static int do_set_group(struct path *from_path, struct path *to_path)
namespace_lock();
- err = -EINVAL; - /* To and From must be mounted */ - if (!is_mounted(&from->mnt)) - goto out; - if (!is_mounted(&to->mnt)) - goto out; - - err = -EPERM; - /* We should be allowed to modify mount namespaces of both mounts */ - if (!ns_capable(from->mnt_ns->user_ns, CAP_SYS_ADMIN)) + err = may_change_propagation(from); + if (err) goto out; - if (!ns_capable(to->mnt_ns->user_ns, CAP_SYS_ADMIN)) + err = may_change_propagation(to); + if (err) goto out;
err = -EINVAL;
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jason Gunthorpe jgg@nvidia.com
[ Upstream commit 8901812485de1356e3757958af40fe0d3a48e986 ]
These drivers all set the domain->pgsize_bitmap in their domain_alloc_paging() functions, so the ops value is never used. Delete it.
Reviewed-by: Sven Peter sven@svenpeter.dev # for Apple DART Reviewed-by: Lu Baolu baolu.lu@linux.intel.com Reviewed-by: Kevin Tian kevin.tian@intel.com Reviewed-by: Tomasz Jeznach tjeznach@rivosinc.com # for RISC-V Signed-off-by: Jason Gunthorpe jgg@nvidia.com Tested-by: Nicolin Chen nicolinc@nvidia.com Link: https://lore.kernel.org/r/3-v2-68a2e1ba507c+1fb-iommu_rm_ops_pgsize_jgg@nvid... Signed-off-by: Joerg Roedel joerg.roedel@amd.com Stable-dep-of: 72b6f7cd89ce ("iommu/virtio: Make instance lookup robust") Signed-off-by: Sasha Levin sashal@kernel.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/iommu/apple-dart.c | 1 - drivers/iommu/intel/iommu.c | 1 - drivers/iommu/iommufd/selftest.c | 1 - drivers/iommu/riscv/iommu.c | 1 - drivers/iommu/virtio-iommu.c | 6 ++---- 5 files changed, 2 insertions(+), 8 deletions(-)
--- a/drivers/iommu/apple-dart.c +++ b/drivers/iommu/apple-dart.c @@ -991,7 +991,6 @@ static const struct iommu_ops apple_dart .of_xlate = apple_dart_of_xlate, .def_domain_type = apple_dart_def_domain_type, .get_resv_regions = apple_dart_get_resv_regions, - .pgsize_bitmap = -1UL, /* Restricted during dart probe */ .owner = THIS_MODULE, .default_domain_ops = &(const struct iommu_domain_ops) { .attach_dev = apple_dart_attach_dev_paging, --- a/drivers/iommu/intel/iommu.c +++ b/drivers/iommu/intel/iommu.c @@ -4390,7 +4390,6 @@ const struct iommu_ops intel_iommu_ops = .device_group = intel_iommu_device_group, .is_attach_deferred = intel_iommu_is_attach_deferred, .def_domain_type = device_def_domain_type, - .pgsize_bitmap = SZ_4K, .page_response = intel_iommu_page_response, .default_domain_ops = &(const struct iommu_domain_ops) { .attach_dev = intel_iommu_attach_device, --- a/drivers/iommu/iommufd/selftest.c +++ b/drivers/iommu/iommufd/selftest.c @@ -801,7 +801,6 @@ static const struct iommu_ops mock_ops = .default_domain = &mock_blocking_domain, .blocked_domain = &mock_blocking_domain, .owner = THIS_MODULE, - .pgsize_bitmap = MOCK_IO_PAGE_SIZE, .hw_info = mock_domain_hw_info, .domain_alloc_paging_flags = mock_domain_alloc_paging_flags, .domain_alloc_nested = mock_domain_alloc_nested, --- a/drivers/iommu/riscv/iommu.c +++ b/drivers/iommu/riscv/iommu.c @@ -1533,7 +1533,6 @@ static void riscv_iommu_release_device(s }
static const struct iommu_ops riscv_iommu_ops = { - .pgsize_bitmap = SZ_4K, .of_xlate = riscv_iommu_of_xlate, .identity_domain = &riscv_iommu_identity_domain, .blocked_domain = &riscv_iommu_blocking_domain, --- a/drivers/iommu/virtio-iommu.c +++ b/drivers/iommu/virtio-iommu.c @@ -998,7 +998,7 @@ static void viommu_get_resv_regions(stru iommu_dma_get_resv_regions(dev, head); }
-static struct iommu_ops viommu_ops; +static const struct iommu_ops viommu_ops; static struct virtio_driver virtio_iommu_drv;
static int viommu_match_node(struct device *dev, const void *data) @@ -1086,7 +1086,7 @@ static bool viommu_capable(struct device } }
-static struct iommu_ops viommu_ops = { +static const struct iommu_ops viommu_ops = { .capable = viommu_capable, .domain_alloc_identity = viommu_domain_alloc_identity, .domain_alloc_paging = viommu_domain_alloc_paging, @@ -1217,8 +1217,6 @@ static int viommu_probe(struct virtio_de viommu->first_domain++; }
- viommu_ops.pgsize_bitmap = viommu->pgsize_bitmap; - virtio_device_ready(vdev);
/* Populate the event queue with buffers */
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Robin Murphy robin.murphy@arm.com
[ Upstream commit 72b6f7cd89cea8251979b65528d302f9c0ed37bf ]
Much like arm-smmu in commit 7d835134d4e1 ("iommu/arm-smmu: Make instance lookup robust"), virtio-iommu appears to have the same issue where iommu_device_register() makes the IOMMU instance visible to other API callers (including itself) straight away, but internally the instance isn't ready to recognise itself for viommu_probe_device() to work correctly until after viommu_probe() has returned. This matters a lot more now that bus_iommu_probe() has the DT/VIOT knowledge to probe client devices the way that was always intended. Tweak the lookup and initialisation in much the same way as for arm-smmu, to ensure that what we register is functional and ready to go.
Cc: stable@vger.kernel.org Fixes: bcb81ac6ae3c ("iommu: Get DT/ACPI parsing into the proper probe path") Signed-off-by: Robin Murphy robin.murphy@arm.com Tested-by: Eric Auger eric.auger@redhat.com Link: https://lore.kernel.org/r/308911aaa1f5be32a3a709996c7bd6cf71d30f33.175519003... Signed-off-by: Joerg Roedel joerg.roedel@amd.com Signed-off-by: Sasha Levin sashal@kernel.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/iommu/virtio-iommu.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-)
--- a/drivers/iommu/virtio-iommu.c +++ b/drivers/iommu/virtio-iommu.c @@ -998,8 +998,7 @@ static void viommu_get_resv_regions(stru iommu_dma_get_resv_regions(dev, head); }
-static const struct iommu_ops viommu_ops; -static struct virtio_driver virtio_iommu_drv; +static const struct bus_type *virtio_bus_type;
static int viommu_match_node(struct device *dev, const void *data) { @@ -1008,8 +1007,9 @@ static int viommu_match_node(struct devi
static struct viommu_dev *viommu_get_by_fwnode(struct fwnode_handle *fwnode) { - struct device *dev = driver_find_device(&virtio_iommu_drv.driver, NULL, - fwnode, viommu_match_node); + struct device *dev = bus_find_device(virtio_bus_type, NULL, fwnode, + viommu_match_node); + put_device(dev);
return dev ? dev_to_virtio(dev)->priv : NULL; @@ -1160,6 +1160,9 @@ static int viommu_probe(struct virtio_de if (!viommu) return -ENOMEM;
+ /* Borrow this for easy lookups later */ + virtio_bus_type = dev->bus; + spin_lock_init(&viommu->request_lock); ida_init(&viommu->domain_ids); viommu->dev = dev; @@ -1229,10 +1232,10 @@ static int viommu_probe(struct virtio_de if (ret) goto err_free_vqs;
- iommu_device_register(&viommu->iommu, &viommu_ops, parent_dev); - vdev->priv = viommu;
+ iommu_device_register(&viommu->iommu, &viommu_ops, parent_dev); + dev_info(dev, "input address: %u bits\n", order_base_2(viommu->geometry.aperture_end)); dev_info(dev, "page mask: %#llx\n", viommu->pgsize_bitmap);
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Mario Limonciello mario.limonciello@amd.com
[ Upstream commit 796ff8a7e01bd18738d3bb4111f9d6f963145d29 ]
If the SCLK limits have been set before S3 they will not be restored. The limits are however cached in the driver and so they can be restored by running a commit sequence during resume.
Acked-by: Alex Deucher alexander.deucher@amd.com Link: https://lore.kernel.org/r/20250725031222.3015095-3-superm1@kernel.org Signed-off-by: Mario Limonciello mario.limonciello@amd.com Signed-off-by: Alex Deucher alexander.deucher@amd.com (cherry picked from commit 4e9526924d09057a9ba854305e17eded900ced82) Cc: stable@vger.kernel.org [ Adjust context ] Signed-off-by: Sasha Levin sashal@kernel.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c | 10 ++++++++++ 1 file changed, 10 insertions(+)
--- a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c +++ b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c @@ -76,6 +76,9 @@ static void smu_power_profile_mode_get(s enum PP_SMC_POWER_PROFILE profile_mode); static void smu_power_profile_mode_put(struct smu_context *smu, enum PP_SMC_POWER_PROFILE profile_mode); +static int smu_od_edit_dpm_table(void *handle, + enum PP_OD_DPM_TABLE_COMMAND type, + long *input, uint32_t size);
static int smu_sys_get_pp_feature_mask(void *handle, char *buf) @@ -2144,6 +2147,7 @@ static int smu_resume(struct amdgpu_ip_b int ret; struct amdgpu_device *adev = ip_block->adev; struct smu_context *smu = adev->powerplay.pp_handle; + struct smu_dpm_context *smu_dpm_ctx = &(smu->smu_dpm);
if (amdgpu_sriov_multi_vf_mode(adev)) return 0; @@ -2181,6 +2185,12 @@ static int smu_resume(struct amdgpu_ip_b return ret; }
+ if (smu_dpm_ctx->dpm_level == AMD_DPM_FORCED_LEVEL_MANUAL) { + ret = smu_od_edit_dpm_table(smu, PP_OD_COMMIT_DPM_TABLE, NULL, 0); + if (ret) + return ret; + } + dev_info(adev->dev, "SMU is resumed successfully!\n");
return 0;
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Imre Deak imre.deak@intel.com
[ Upstream commit a40c5d727b8111b5db424a1e43e14a1dcce1e77f ]
Reading DPCD registers has side-effects in general. In particular accessing registers outside of the link training register range (0x102-0x106, 0x202-0x207, 0x200c-0x200f, 0x2216) is explicitly forbidden by the DP v2.1 Standard, see
3.6.5.1 DPTX AUX Transaction Handling Mandates 3.6.7.4 128b/132b DP Link Layer LTTPR Link Training Mandates
Based on my tests, accessing the DPCD_REV register during the link training of an UHBR TBT DP tunnel sink leads to link training failures.
Solve the above by using the DP_LANE0_1_STATUS (0x202) register for the DPCD register access quirk.
Cc: stable@vger.kernel.org Cc: Ville Syrjälä ville.syrjala@linux.intel.com Cc: Jani Nikula jani.nikula@linux.intel.com Acked-by: Jani Nikula jani.nikula@intel.com Signed-off-by: Imre Deak imre.deak@intel.com Link: https://lore.kernel.org/r/20250605082850.65136-2-imre.deak@intel.com [ DP_TRAINING_PATTERN_SET => DP_LANE0_1_STATUS ] Signed-off-by: Sasha Levin sashal@kernel.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/gpu/drm/display/drm_dp_helper.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
--- a/drivers/gpu/drm/display/drm_dp_helper.c +++ b/drivers/gpu/drm/display/drm_dp_helper.c @@ -725,7 +725,7 @@ ssize_t drm_dp_dpcd_read(struct drm_dp_a * monitor doesn't power down exactly after the throw away read. */ if (!aux->is_remote) { - ret = drm_dp_dpcd_probe(aux, DP_TRAINING_PATTERN_SET); + ret = drm_dp_dpcd_probe(aux, DP_LANE0_1_STATUS); if (ret < 0) return ret; }
Hi Greg,
could you please drop this patch from all the stable tree queues? I got a review notification now for the 6.12 and 6.16 stable tree, but I also see the patch in all the stable queues (5.4, 5.10, 5.15, 6.1, 6.6, 6.12, 6.16). The change would cause a regression which I described at
https://lore.kernel.org/all/aKwQfhfSu5aCUktw@ideak-desk and https://lore.kernel.org/stable/aGaiASySvb3BVXlM@ideak-desk
Thanks, Imre
On Tue, Aug 26, 2025 at 01:09:37PM +0200, Greg Kroah-Hartman wrote:
6.16-stable review patch. If anyone has any objections, please let me know.
From: Imre Deak imre.deak@intel.com
[ Upstream commit a40c5d727b8111b5db424a1e43e14a1dcce1e77f ]
Reading DPCD registers has side-effects in general. In particular accessing registers outside of the link training register range (0x102-0x106, 0x202-0x207, 0x200c-0x200f, 0x2216) is explicitly forbidden by the DP v2.1 Standard, see
3.6.5.1 DPTX AUX Transaction Handling Mandates 3.6.7.4 128b/132b DP Link Layer LTTPR Link Training Mandates
Based on my tests, accessing the DPCD_REV register during the link training of an UHBR TBT DP tunnel sink leads to link training failures.
Solve the above by using the DP_LANE0_1_STATUS (0x202) register for the DPCD register access quirk.
Cc: stable@vger.kernel.org Cc: Ville Syrjälä ville.syrjala@linux.intel.com Cc: Jani Nikula jani.nikula@linux.intel.com Acked-by: Jani Nikula jani.nikula@intel.com Signed-off-by: Imre Deak imre.deak@intel.com Link: https://lore.kernel.org/r/20250605082850.65136-2-imre.deak@intel.com [ DP_TRAINING_PATTERN_SET => DP_LANE0_1_STATUS ] Signed-off-by: Sasha Levin sashal@kernel.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org
drivers/gpu/drm/display/drm_dp_helper.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
--- a/drivers/gpu/drm/display/drm_dp_helper.c +++ b/drivers/gpu/drm/display/drm_dp_helper.c @@ -725,7 +725,7 @@ ssize_t drm_dp_dpcd_read(struct drm_dp_a * monitor doesn't power down exactly after the throw away read. */ if (!aux->is_remote) {
ret = drm_dp_dpcd_probe(aux, DP_TRAINING_PATTERN_SET);
if (ret < 0) return ret; }ret = drm_dp_dpcd_probe(aux, DP_LANE0_1_STATUS);
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Xu Yilun yilun.xu@linux.intel.com
commit 1ca61060de92a4320d73adfe5dc8d335653907ac upstream.
dma_map_sgtable() returns only 0 or the error code. Read sgt->nents to get the number of mapped segments.
Fixes: 37e00703228a ("zynq_fpga: use sgtable-based scatterlist wrappers") Reported-by: Pavel Pisa pisa@fel.cvut.cz Closes: https://lore.kernel.org/linux-fpga/202508041548.22955.pisa@fel.cvut.cz/ Reviewed-by: Jason Gunthorpe jgg@nvidia.com Reviewed-by: Marek Szyprowski m.szyprowski@samsung.com Signed-off-by: Xu Yilun yilun.xu@linux.intel.com Tested-by: Pavel Pisa pisa@fel.cvut.cz Link: https://lore.kernel.org/r/20250806070605.1920909-2-yilun.xu@linux.intel.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/fpga/zynq-fpga.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-)
--- a/drivers/fpga/zynq-fpga.c +++ b/drivers/fpga/zynq-fpga.c @@ -405,12 +405,12 @@ static int zynq_fpga_ops_write(struct fp } }
- priv->dma_nelms = - dma_map_sgtable(mgr->dev.parent, sgt, DMA_TO_DEVICE, 0); - if (priv->dma_nelms == 0) { + err = dma_map_sgtable(mgr->dev.parent, sgt, DMA_TO_DEVICE, 0); + if (err) { dev_err(&mgr->dev, "Unable to DMA map (TO_DEVICE)\n"); - return -ENOMEM; + return err; } + priv->dma_nelms = sgt->nents;
/* enable clock */ err = clk_enable(priv->clk);
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: David Lechner dlechner@baylibre.com
commit b04e4551893fb8a06106a175ed7055d41a9279c4 upstream.
Add max_conversion_rate_hz to the chip info for "adaq4381-4". Without this, the driver fails to probe because it tries to set the initial sample rate to 0 Hz, which is not valid.
Fixes: bbeaec81a03e ("iio: ad7380: add support for SPI offload") Signed-off-by: David Lechner dlechner@baylibre.com Reviewed-by: Andy Shevchenko andy@kernel.org Link: https://patch.msgid.link/20250811-iio-adc-ad7380-fix-missing-max_conversion_... Signed-off-by: Jonathan Cameron Jonathan.Cameron@huawei.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/iio/adc/ad7380.c | 1 + 1 file changed, 1 insertion(+)
diff --git a/drivers/iio/adc/ad7380.c b/drivers/iio/adc/ad7380.c index 6f7034b6c266..fa251dc1aae6 100644 --- a/drivers/iio/adc/ad7380.c +++ b/drivers/iio/adc/ad7380.c @@ -873,6 +873,7 @@ static const struct ad7380_chip_info adaq4381_4_chip_info = { .has_hardware_gain = true, .available_scan_masks = ad7380_4_channel_scan_masks, .timing_specs = &ad7380_4_timing, + .max_conversion_rate_hz = 4 * MEGA, };
static const struct spi_offload_config ad7380_offload_config = {
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: David Lechner dlechner@baylibre.com
commit 4e5b705cc6147f0b9173c6219079f41416bdd3c0 upstream.
Fix potential leak of uninitialized stack data to userspace by ensuring that the `channels` array is zeroed before use.
Fixes: edeb67fbbf4b ("iio: accel: sca3300: use IIO_DECLARE_BUFFER_WITH_TS") Signed-off-by: David Lechner dlechner@baylibre.com Link: https://patch.msgid.link/20250723-iio-accel-sca3300-fix-uninitialized-iio-sc... Signed-off-by: Jonathan Cameron Jonathan.Cameron@huawei.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/iio/accel/sca3300.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
--- a/drivers/iio/accel/sca3300.c +++ b/drivers/iio/accel/sca3300.c @@ -479,7 +479,7 @@ static irqreturn_t sca3300_trigger_handl struct iio_dev *indio_dev = pf->indio_dev; struct sca3300_data *data = iio_priv(indio_dev); int bit, ret, val, i = 0; - IIO_DECLARE_BUFFER_WITH_TS(s16, channels, SCA3300_SCAN_MAX); + IIO_DECLARE_BUFFER_WITH_TS(s16, channels, SCA3300_SCAN_MAX) = { };
iio_for_each_active_channel(indio_dev, bit) { ret = sca3300_read_reg(data, indio_dev->channels[bit].address, &val);
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Steven Rostedt rostedt@goodmis.org
commit bfb336cf97df7b37b2b2edec0f69773e06d11955 upstream.
Currently the reader of set_ftrace_filter and set_ftrace_notrace just adds the pointer to the global tracer hash to its iterator. Unlike the writer that allocates a copy of the hash, the reader keeps the pointer to the filter hashes. This is problematic because this pointer is static across function calls that release the locks that can update the global tracer hashes. This can cause UAF and similar bugs.
Allocate and copy the hash for reading the filter files like it is done for the writers. This not only fixes UAF bugs, but also makes the code a bit simpler as it doesn't have to differentiate when to free the iterator's hash between writers and readers.
Cc: stable@vger.kernel.org Cc: Masami Hiramatsu mhiramat@kernel.org Cc: Mathieu Desnoyers mathieu.desnoyers@efficios.com Cc: Nathan Chancellor nathan@kernel.org Cc: Linus Torvalds torvalds@linux-foundation.org Link: https://lore.kernel.org/20250822183606.12962cc3@batman.local.home Fixes: c20489dad156 ("ftrace: Assign iter->hash to filter or notrace hashes on seq read") Closes: https://lore.kernel.org/all/20250813023044.2121943-1-wutengda@huaweicloud.co... Closes: https://lore.kernel.org/all/20250822192437.GA458494@ax162/ Reported-by: Tengda Wu wutengda@huaweicloud.com Tested-by: Tengda Wu wutengda@huaweicloud.com Tested-by: Nathan Chancellor nathan@kernel.org Signed-off-by: Steven Rostedt (Google) rostedt@goodmis.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- kernel/trace/ftrace.c | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-)
--- a/kernel/trace/ftrace.c +++ b/kernel/trace/ftrace.c @@ -4665,13 +4665,17 @@ ftrace_regex_open(struct ftrace_ops *ops } else { iter->hash = alloc_and_copy_ftrace_hash(size_bits, hash); } + } else { + if (hash) + iter->hash = alloc_and_copy_ftrace_hash(hash->size_bits, hash); + else + iter->hash = EMPTY_HASH; + }
- if (!iter->hash) { - trace_parser_put(&iter->parser); - goto out_unlock; - } - } else - iter->hash = hash; + if (!iter->hash) { + trace_parser_put(&iter->parser); + goto out_unlock; + }
ret = 0;
@@ -6547,9 +6551,6 @@ int ftrace_regex_release(struct inode *i ftrace_hash_move_and_update_ops(iter->ops, orig_hash, iter->hash, filter_hash); mutex_unlock(&ftrace_lock); - } else { - /* For read only, the hash is the ops hash */ - iter->hash = NULL; }
mutex_unlock(&iter->ops->func_hash->regex_lock);
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: David Lechner dlechner@baylibre.com
commit ae5bc07ec9f73a41734270ef3f800c5c8a7e0ad3 upstream.
Replace using stack-allocated buffers with a DMA-safe buffer for use with spi_read(). This allows the driver to be safely used with DMA-enabled SPI controllers.
The buffer array is also converted to a struct with a union to make the usage of the memory in the buffer more clear and ensure proper alignment.
Fixes: 1f25ca11d84a ("iio: temperature: add support for Maxim thermocouple chips") Signed-off-by: David Lechner dlechner@baylibre.com Reviewed-by: Nuno Sá nuno.sa@analog.com Link: https://patch.msgid.link/20250721-iio-use-more-iio_declare_buffer_with_ts-3-... Cc: Stable@vger.kernel.org Signed-off-by: Jonathan Cameron Jonathan.Cameron@huawei.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/iio/temperature/maxim_thermocouple.c | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-)
--- a/drivers/iio/temperature/maxim_thermocouple.c +++ b/drivers/iio/temperature/maxim_thermocouple.c @@ -11,6 +11,7 @@ #include <linux/module.h> #include <linux/err.h> #include <linux/spi/spi.h> +#include <linux/types.h> #include <linux/iio/iio.h> #include <linux/iio/sysfs.h> #include <linux/iio/trigger.h> @@ -121,8 +122,15 @@ struct maxim_thermocouple_data { struct spi_device *spi; const struct maxim_thermocouple_chip *chip; char tc_type; - - u8 buffer[16] __aligned(IIO_DMA_MINALIGN); + /* Buffer for reading up to 2 hardware channels. */ + struct { + union { + __be16 raw16; + __be32 raw32; + __be16 raw[2]; + }; + aligned_s64 timestamp; + } buffer __aligned(IIO_DMA_MINALIGN); };
static int maxim_thermocouple_read(struct maxim_thermocouple_data *data, @@ -130,18 +138,16 @@ static int maxim_thermocouple_read(struc { unsigned int storage_bytes = data->chip->read_size; unsigned int shift = chan->scan_type.shift + (chan->address * 8); - __be16 buf16; - __be32 buf32; int ret;
switch (storage_bytes) { case 2: - ret = spi_read(data->spi, (void *)&buf16, storage_bytes); - *val = be16_to_cpu(buf16); + ret = spi_read(data->spi, &data->buffer.raw16, storage_bytes); + *val = be16_to_cpu(data->buffer.raw16); break; case 4: - ret = spi_read(data->spi, (void *)&buf32, storage_bytes); - *val = be32_to_cpu(buf32); + ret = spi_read(data->spi, &data->buffer.raw32, storage_bytes); + *val = be32_to_cpu(data->buffer.raw32); break; default: ret = -EINVAL; @@ -166,9 +172,9 @@ static irqreturn_t maxim_thermocouple_tr struct maxim_thermocouple_data *data = iio_priv(indio_dev); int ret;
- ret = spi_read(data->spi, data->buffer, data->chip->read_size); + ret = spi_read(data->spi, data->buffer.raw, data->chip->read_size); if (!ret) { - iio_push_to_buffers_with_ts(indio_dev, data->buffer, + iio_push_to_buffers_with_ts(indio_dev, &data->buffer, sizeof(data->buffer), iio_get_time_ns(indio_dev)); }
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: David Lechner dlechner@baylibre.com
commit 197e299aae42ffa19028eaea92b2f30dd9fb8445 upstream.
Fix possible incorrect channel lookup in the syscalib functions by using the correct channel address instead of the channel number.
In the ad7124 driver, the channel field of struct iio_chan_spec is the input pin number of the positive input of the channel. This can be, but is not always the same as the index in the channels array. The correct index in the channels array is stored in the address field (and also scan_index). We use the address field to perform the correct lookup.
Fixes: 47036a03a303 ("iio: adc: ad7124: Implement internal calibration at probe time") Signed-off-by: David Lechner dlechner@baylibre.com Reviewed-by: Nuno Sá nuno.sa@analog.com Link: https://patch.msgid.link/20250726-iio-adc-ad7124-fix-channel-lookup-in-sysca... Cc: Stable@vger.kernel.org Signed-off-by: Jonathan Cameron Jonathan.Cameron@huawei.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/iio/adc/ad7124.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-)
--- a/drivers/iio/adc/ad7124.c +++ b/drivers/iio/adc/ad7124.c @@ -855,7 +855,7 @@ enum { static int ad7124_syscalib_locked(struct ad7124_state *st, const struct iio_chan_spec *chan) { struct device *dev = &st->sd.spi->dev; - struct ad7124_channel *ch = &st->channels[chan->channel]; + struct ad7124_channel *ch = &st->channels[chan->address]; int ret;
if (ch->syscalib_mode == AD7124_SYSCALIB_ZERO_SCALE) { @@ -871,8 +871,8 @@ static int ad7124_syscalib_locked(struct if (ret < 0) return ret;
- dev_dbg(dev, "offset for channel %d after zero-scale calibration: 0x%x\n", - chan->channel, ch->cfg.calibration_offset); + dev_dbg(dev, "offset for channel %lu after zero-scale calibration: 0x%x\n", + chan->address, ch->cfg.calibration_offset); } else { ch->cfg.calibration_gain = st->gain_default;
@@ -886,8 +886,8 @@ static int ad7124_syscalib_locked(struct if (ret < 0) return ret;
- dev_dbg(dev, "gain for channel %d after full-scale calibration: 0x%x\n", - chan->channel, ch->cfg.calibration_gain); + dev_dbg(dev, "gain for channel %lu after full-scale calibration: 0x%x\n", + chan->address, ch->cfg.calibration_gain); }
return 0; @@ -930,7 +930,7 @@ static int ad7124_set_syscalib_mode(stru { struct ad7124_state *st = iio_priv(indio_dev);
- st->channels[chan->channel].syscalib_mode = mode; + st->channels[chan->address].syscalib_mode = mode;
return 0; } @@ -940,7 +940,7 @@ static int ad7124_get_syscalib_mode(stru { struct ad7124_state *st = iio_priv(indio_dev);
- return st->channels[chan->channel].syscalib_mode; + return st->channels[chan->address].syscalib_mode; }
static const struct iio_enum ad7124_syscalib_mode_enum = {
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jonathan Cameron Jonathan.Cameron@huawei.com
commit 433b99e922943efdfd62b9a8e3ad1604838181f2 upstream.
Given that the buffer is copied to a kfifo that ultimately user space can read, ensure we zero it.
Fixes: 403e5586b52e ("iio: light: as73211: New driver") Reviewed-by: Matti Vaittinen mazziesaccount@gmail.com Reviewed-by: Andy Shevchenko andy@kernel.org Link: https://patch.msgid.link/20250802164436.515988-2-jic23@kernel.org Cc: Stable@vger.kernel.org Signed-off-by: Jonathan Cameron Jonathan.Cameron@huawei.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/iio/light/as73211.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
--- a/drivers/iio/light/as73211.c +++ b/drivers/iio/light/as73211.c @@ -639,7 +639,7 @@ static irqreturn_t as73211_trigger_handl struct { __le16 chan[4]; aligned_s64 ts; - } scan; + } scan = { }; int data_result, ret;
mutex_lock(&data->mutex);
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Salah Triki salah.triki@gmail.com
commit 43c0f6456f801181a80b73d95def0e0fd134e1cc upstream.
`devm_gpiod_get_optional()` may return non-NULL error pointer on failure. Check its return value using `IS_ERR()` and propagate the error if necessary.
Fixes: df6e71256c84 ("iio: pressure: bmp280: Explicitly mark GPIO optional") Signed-off-by: Salah Triki salah.triki@gmail.com Reviewed-by: David Lechner dlechner@baylibre.com Link: https://patch.msgid.link/20250818092740.545379-2-salah.triki@gmail.com Cc: Stable@vger.kernel.org Signed-off-by: Jonathan Cameron Jonathan.Cameron@huawei.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/iio/pressure/bmp280-core.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-)
--- a/drivers/iio/pressure/bmp280-core.c +++ b/drivers/iio/pressure/bmp280-core.c @@ -3216,11 +3216,12 @@ int bmp280_common_probe(struct device *d
/* Bring chip out of reset if there is an assigned GPIO line */ gpiod = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_HIGH); + if (IS_ERR(gpiod)) + return dev_err_probe(dev, PTR_ERR(gpiod), "failed to get reset GPIO\n"); + /* Deassert the signal */ - if (gpiod) { - dev_info(dev, "release reset\n"); - gpiod_set_value(gpiod, 0); - } + dev_info(dev, "release reset\n"); + gpiod_set_value(gpiod, 0);
data->regmap = regmap;
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Claudiu Beznea claudiu.beznea.uj@bp.renesas.com
commit c69e13965f26b8058f538ea8bdbd2d7718cf1fbe upstream.
When stress-testing the system by repeatedly unbinding and binding the ADC device in a loop, and the ADC is a supplier for another device (e.g., a thermal hardware block that reads temperature through the ADC), it may happen that the ADC device is runtime-resumed immediately after runtime PM is enabled, triggered by its consumer. At this point, since drvdata is not yet set and the driver's runtime PM callbacks rely on it, a crash can occur. To avoid this, set drvdata just after it was allocated.
Fixes: 89ee8174e8c8 ("iio: adc: rzg2l_adc: Simplify the runtime PM code") Signed-off-by: Claudiu Beznea claudiu.beznea.uj@bp.renesas.com Link: https://patch.msgid.link/20250810123328.800104-3-claudiu.beznea.uj@bp.renesa... Cc: Stable@vger.kernel.org Signed-off-by: Jonathan Cameron Jonathan.Cameron@huawei.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/iio/adc/rzg2l_adc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
--- a/drivers/iio/adc/rzg2l_adc.c +++ b/drivers/iio/adc/rzg2l_adc.c @@ -428,6 +428,8 @@ static int rzg2l_adc_probe(struct platfo if (!indio_dev) return -ENOMEM;
+ platform_set_drvdata(pdev, indio_dev); + adc = iio_priv(indio_dev);
adc->hw_params = device_get_match_data(dev); @@ -460,8 +462,6 @@ static int rzg2l_adc_probe(struct platfo if (ret) return ret;
- platform_set_drvdata(pdev, indio_dev); - ret = rzg2l_adc_hw_init(dev, adc); if (ret) return dev_err_probe(&pdev->dev, ret,
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Matti Vaittinen mazziesaccount@gmail.com
commit 8a6ededaad2d2dcaac8e545bffee1073dca9db95 upstream.
The bd79124 has ADC inputs which can be muxed to be GPIOs. The driver supports this by registering a GPIO-chip for channels which aren't used as ADC.
The Kconfig entry does not handle the dependency to GPIOLIB, which causes errors:
ERROR: modpost: "devm_gpiochip_add_data_with_key" [drivers/iio/adc/rohm-bd79124.ko] undefined! ERROR: modpost: "gpiochip_get_data" [drivers/iio/adc/rohm-bd79124.ko] undefined!
at linking phase if GPIOLIB is not configured to be used.
Fix this by adding dependency to the GPIOLIB.
Reported-by: kernel test robot lkp@intel.com Closes: https://lore.kernel.org/oe-kbuild-all/202508131533.5sSkq80B-lkp@intel.com/ Fixes: 3f57a3b9ab74 ("iio: adc: Support ROHM BD79124 ADC") Signed-off-by: Matti Vaittinen mazziesaccount@gmail.com Reviewed-by: Bartosz Golaszewski bartosz.golaszewski@linaro.org Link: https://patch.msgid.link/6837249bddf358924e67566293944506206d2d62.1755076369... Cc: Stable@vger.kernel.org Signed-off-by: Jonathan Cameron Jonathan.Cameron@huawei.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/iio/adc/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
--- a/drivers/iio/adc/Kconfig +++ b/drivers/iio/adc/Kconfig @@ -1257,7 +1257,7 @@ config RN5T618_ADC
config ROHM_BD79124 tristate "Rohm BD79124 ADC driver" - depends on I2C + depends on I2C && GPIOLIB select REGMAP_I2C select IIO_ADC_HELPER help
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: David Lechner dlechner@baylibre.com
commit 1cfb22c277c7274f54babaa5b416dfbc00181e16 upstream.
Add a check to ad7173_update_scan_mode() to ensure that we didn't exceed the maximum number of unique channel configurations.
In the AD7173 family of chips, there are some chips that have 16 CHANNELx registers but only 8 setups (combination of CONFIGx, FILTERx, GAINx and OFFSETx registers). Since commit 92c247216918 ("iio: adc: ad7173: fix num_slots"), it is possible to have more than 8 channels enabled in a scan at the same time, so it is possible to get a bad configuration when more than 8 channels are using unique configurations. This happens because the algorithm to allocate the setup slots only takes into account which slot has been least recently used and doesn't know about the maximum number of slots available.
Since the algorithm to allocate the setup slots is quite complex, it is simpler to check after the fact if the current state is valid or not. So this patch adds a check in ad7173_update_scan_mode() after setting up all of the configurations to make sure that the actual setup still matches the requested setup for each enabled channel. If not, we prevent the scan from being enabled and return an error.
The setup comparison in ad7173_setup_equal() is refactored to a separate function since we need to call it in two places now.
Fixes: 92c247216918 ("iio: adc: ad7173: fix num_slots") Signed-off-by: David Lechner dlechner@baylibre.com Link: https://patch.msgid.link/20250722-iio-adc-ad7173-fix-setup-use-limits-v2-1-8... Cc: Stable@vger.kernel.org Signed-off-by: Jonathan Cameron Jonathan.Cameron@huawei.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/iio/adc/ad7173.c | 87 ++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 75 insertions(+), 12 deletions(-)
--- a/drivers/iio/adc/ad7173.c +++ b/drivers/iio/adc/ad7173.c @@ -200,7 +200,7 @@ struct ad7173_channel_config { /* * Following fields are used to compare equality. If you * make adaptations in it, you most likely also have to adapt - * ad7173_find_live_config(), too. + * ad7173_is_setup_equal(), too. */ struct_group(config_props, bool bipolar; @@ -562,12 +562,19 @@ static void ad7173_reset_usage_cnts(stru st->config_usage_counter = 0; }
-static struct ad7173_channel_config * -ad7173_find_live_config(struct ad7173_state *st, struct ad7173_channel_config *cfg) +/** + * ad7173_is_setup_equal - Compare two channel setups + * @cfg1: First channel configuration + * @cfg2: Second channel configuration + * + * Compares all configuration options that affect the registers connected to + * SETUP_SEL, namely CONFIGx, FILTERx, GAINx and OFFSETx. + * + * Returns: true if the setups are identical, false otherwise + */ +static bool ad7173_is_setup_equal(const struct ad7173_channel_config *cfg1, + const struct ad7173_channel_config *cfg2) { - struct ad7173_channel_config *cfg_aux; - int i; - /* * This is just to make sure that the comparison is adapted after * struct ad7173_channel_config was changed. @@ -580,14 +587,22 @@ ad7173_find_live_config(struct ad7173_st u8 ref_sel; }));
+ return cfg1->bipolar == cfg2->bipolar && + cfg1->input_buf == cfg2->input_buf && + cfg1->odr == cfg2->odr && + cfg1->ref_sel == cfg2->ref_sel; +} + +static struct ad7173_channel_config * +ad7173_find_live_config(struct ad7173_state *st, struct ad7173_channel_config *cfg) +{ + struct ad7173_channel_config *cfg_aux; + int i; + for (i = 0; i < st->num_channels; i++) { cfg_aux = &st->channels[i].cfg;
- if (cfg_aux->live && - cfg->bipolar == cfg_aux->bipolar && - cfg->input_buf == cfg_aux->input_buf && - cfg->odr == cfg_aux->odr && - cfg->ref_sel == cfg_aux->ref_sel) + if (cfg_aux->live && ad7173_is_setup_equal(cfg, cfg_aux)) return cfg_aux; } return NULL; @@ -1229,7 +1244,7 @@ static int ad7173_update_scan_mode(struc const unsigned long *scan_mask) { struct ad7173_state *st = iio_priv(indio_dev); - int i, ret; + int i, j, k, ret;
for (i = 0; i < indio_dev->num_channels; i++) { if (test_bit(i, scan_mask)) @@ -1240,6 +1255,54 @@ static int ad7173_update_scan_mode(struc return ret; }
+ /* + * On some chips, there are more channels that setups, so if there were + * more unique setups requested than the number of available slots, + * ad7173_set_channel() will have written over some of the slots. We + * can detect this by making sure each assigned cfg_slot matches the + * requested configuration. If it doesn't, we know that the slot was + * overwritten by a different channel. + */ + for_each_set_bit(i, scan_mask, indio_dev->num_channels) { + const struct ad7173_channel_config *cfg1, *cfg2; + + cfg1 = &st->channels[i].cfg; + + for_each_set_bit(j, scan_mask, indio_dev->num_channels) { + cfg2 = &st->channels[j].cfg; + + /* + * Only compare configs that are assigned to the same + * SETUP_SEL slot and don't compare channel to itself. + */ + if (i == j || cfg1->cfg_slot != cfg2->cfg_slot) + continue; + + /* + * If we find two different configs trying to use the + * same SETUP_SEL slot, then we know that the that we + * have too many unique configurations requested for + * the available slots and at least one was overwritten. + */ + if (!ad7173_is_setup_equal(cfg1, cfg2)) { + /* + * At this point, there isn't a way to tell + * which setups are actually programmed in the + * ADC anymore, so we could read them back to + * see, but it is simpler to just turn off all + * of the live flags so that everything gets + * reprogramed on the next attempt read a sample. + */ + for (k = 0; k < st->num_channels; k++) + st->channels[k].cfg.live = false; + + dev_err(&st->sd.spi->dev, + "Too many unique channel configurations requested for scan\n"); + return -EINVAL; + } + } + } + return 0; }
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: David Lechner dlechner@baylibre.com
commit de18e978d0cda23e4c102e18092b63a5b0b3a800 upstream.
Fix passing a u32 value as a u16 buffer scan item. This works on little- endian systems, but not on big-endian systems.
A new local variable is introduced for getting the register value and the array is changed to a struct to make the data layout more explicit rather than just changing the type and having to recalculate the proper length needed for the timestamp.
Fixes: 1c28799257bc ("iio: light: isl29501: Add support for the ISL29501 ToF sensor.") Signed-off-by: David Lechner dlechner@baylibre.com Link: https://patch.msgid.link/20250722-iio-use-more-iio_declare_buffer_with_ts-7-... Cc: Stable@vger.kernel.org Signed-off-by: Jonathan Cameron Jonathan.Cameron@huawei.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/iio/proximity/isl29501.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-)
--- a/drivers/iio/proximity/isl29501.c +++ b/drivers/iio/proximity/isl29501.c @@ -938,12 +938,18 @@ static irqreturn_t isl29501_trigger_hand struct iio_dev *indio_dev = pf->indio_dev; struct isl29501_private *isl29501 = iio_priv(indio_dev); const unsigned long *active_mask = indio_dev->active_scan_mask; - u32 buffer[4] __aligned(8) = {}; /* 1x16-bit + naturally aligned ts */ + u32 value; + struct { + u16 data; + aligned_s64 ts; + } scan = { };
- if (test_bit(ISL29501_DISTANCE_SCAN_INDEX, active_mask)) - isl29501_register_read(isl29501, REG_DISTANCE, buffer); + if (test_bit(ISL29501_DISTANCE_SCAN_INDEX, active_mask)) { + isl29501_register_read(isl29501, REG_DISTANCE, &value); + scan.data = value; + }
- iio_push_to_buffers_with_timestamp(indio_dev, buffer, pf->timestamp); + iio_push_to_buffers_with_timestamp(indio_dev, &scan, pf->timestamp); iio_trigger_notify_done(indio_dev->trig);
return IRQ_HANDLED;
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Claudiu Beznea claudiu.beznea.uj@bp.renesas.com
commit a3c6eabe3bbd6b0e7124d68b2d3bc32fed17362e upstream.
There is no need to manually track the runtime PM status in the driver. The pm_runtime_force_suspend() and pm_runtime_force_resume() functions already call pm_runtime_status_suspended() to check the runtime PM state.
Additionally, avoid calling pm_runtime_put_autosuspend() during the suspend/resume path, as this would decrease the usage counter of a potential user that had the ADC open before the suspend/resume cycle.
Fixes: 563cf94f9329 ("iio: adc: rzg2l_adc: Add suspend/resume support") Reviewed-by: Ulf Hansson ulf.hansson@linaro.org Reviewed-by: Lad Prabhakar prabhakar.mahadev-lad.rj@bp.renesas.com Signed-off-by: Claudiu Beznea claudiu.beznea.uj@bp.renesas.com Link: https://patch.msgid.link/20250810123328.800104-2-claudiu.beznea.uj@bp.renesa... Cc: Stable@vger.kernel.org Signed-off-by: Jonathan Cameron Jonathan.Cameron@huawei.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/iio/adc/rzg2l_adc.c | 29 ++++++++--------------------- 1 file changed, 8 insertions(+), 21 deletions(-)
diff --git a/drivers/iio/adc/rzg2l_adc.c b/drivers/iio/adc/rzg2l_adc.c index 9674d48074c9..0cb5a67fd497 100644 --- a/drivers/iio/adc/rzg2l_adc.c +++ b/drivers/iio/adc/rzg2l_adc.c @@ -89,7 +89,6 @@ struct rzg2l_adc { struct completion completion; struct mutex lock; u16 last_val[RZG2L_ADC_MAX_CHANNELS]; - bool was_rpm_active; };
/** @@ -541,14 +540,9 @@ static int rzg2l_adc_suspend(struct device *dev) }; int ret;
- if (pm_runtime_suspended(dev)) { - adc->was_rpm_active = false; - } else { - ret = pm_runtime_force_suspend(dev); - if (ret) - return ret; - adc->was_rpm_active = true; - } + ret = pm_runtime_force_suspend(dev); + if (ret) + return ret;
ret = reset_control_bulk_assert(ARRAY_SIZE(resets), resets); if (ret) @@ -557,9 +551,7 @@ static int rzg2l_adc_suspend(struct device *dev) return 0;
rpm_restore: - if (adc->was_rpm_active) - pm_runtime_force_resume(dev); - + pm_runtime_force_resume(dev); return ret; }
@@ -577,11 +569,9 @@ static int rzg2l_adc_resume(struct device *dev) if (ret) return ret;
- if (adc->was_rpm_active) { - ret = pm_runtime_force_resume(dev); - if (ret) - goto resets_restore; - } + ret = pm_runtime_force_resume(dev); + if (ret) + goto resets_restore;
ret = rzg2l_adc_hw_init(dev, adc); if (ret) @@ -590,10 +580,7 @@ static int rzg2l_adc_resume(struct device *dev) return 0;
rpm_restore: - if (adc->was_rpm_active) { - pm_runtime_mark_last_busy(dev); - pm_runtime_put_autosuspend(dev); - } + pm_runtime_force_suspend(dev); resets_restore: reset_control_bulk_assert(ARRAY_SIZE(resets), resets); return ret;
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Miaoqian Lin linmq006@gmail.com
commit b47b493d6387ae437098112936f32be27f73516c upstream.
In get_channel(), the reference obtained by bus_find_device_by_name() was dropped via put_device() before accessing the device's driver data Move put_device() after usage to avoid potential issues.
Fixes: 2485055394be ("staging: most: core: drop device reference") Cc: stable stable@kernel.org Signed-off-by: Miaoqian Lin linmq006@gmail.com Link: https://lore.kernel.org/r/20250804082955.3621026-1-linmq006@gmail.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/most/core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
--- a/drivers/most/core.c +++ b/drivers/most/core.c @@ -538,8 +538,8 @@ static struct most_channel *get_channel( dev = bus_find_device_by_name(&mostbus, NULL, mdev); if (!dev) return NULL; - put_device(dev); iface = dev_get_drvdata(dev); + put_device(dev); list_for_each_entry_safe(c, tmp, &iface->p->channel_list, list) { if (!strcmp(dev_name(&c->dev), mdev_ch)) return c;
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sebastian Andrzej Siewior bigeasy@linutronix.de
commit 9528d32873b38281ae105f2f5799e79ae9d086c2 upstream.
kcov_remote_start_usb_softirq() the begin of urb's completion callback. HCDs marked HCD_BH will invoke this function from the softirq and in_serving_softirq() will detect this properly. Root-HUB (RH) requests will not be delayed to softirq but complete immediately in IRQ context. This will confuse kcov because in_serving_softirq() will report true if the softirq is served after the hardirq and if the softirq got interrupted by the hardirq in which currently runs.
This was addressed by simply disabling interrupts in kcov_remote_start_usb_softirq() which avoided the interruption by the RH while a regular completion callback was invoked. This not only changes the behaviour while kconv is enabled but also breaks PREEMPT_RT because now sleeping locks can no longer be acquired.
Revert the previous fix. Address the issue by invoking kcov_remote_start_usb() only if the context is just "serving softirqs" which is identified by checking in_serving_softirq() and in_hardirq() must be false.
Fixes: f85d39dd7ed89 ("kcov, usb: disable interrupts in kcov_remote_start_usb_softirq") Cc: stable stable@kernel.org Reported-by: Yunseong Kim ysk@kzalloc.com Closes: https://lore.kernel.org/all/20250725201400.1078395-2-ysk@kzalloc.com/ Tested-by: Yunseong Kim ysk@kzalloc.com Signed-off-by: Sebastian Andrzej Siewior bigeasy@linutronix.de Link: https://lore.kernel.org/r/20250811082745.ycJqBXMs@linutronix.de Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/usb/core/hcd.c | 12 +++++------- include/linux/kcov.h | 47 +++++++++-------------------------------------- 2 files changed, 14 insertions(+), 45 deletions(-)
--- a/drivers/usb/core/hcd.c +++ b/drivers/usb/core/hcd.c @@ -1623,7 +1623,6 @@ static void __usb_hcd_giveback_urb(struc struct usb_hcd *hcd = bus_to_hcd(urb->dev->bus); struct usb_anchor *anchor = urb->anchor; int status = urb->unlinked; - unsigned long flags;
urb->hcpriv = NULL; if (unlikely((urb->transfer_flags & URB_SHORT_NOT_OK) && @@ -1641,14 +1640,13 @@ static void __usb_hcd_giveback_urb(struc /* pass ownership to the completion handler */ urb->status = status; /* - * Only collect coverage in the softirq context and disable interrupts - * to avoid scenarios with nested remote coverage collection sections - * that KCOV does not support. - * See the comment next to kcov_remote_start_usb_softirq() for details. + * This function can be called in task context inside another remote + * coverage collection section, but kcov doesn't support that kind of + * recursion yet. Only collect coverage in softirq context for now. */ - flags = kcov_remote_start_usb_softirq((u64)urb->dev->bus->busnum); + kcov_remote_start_usb_softirq((u64)urb->dev->bus->busnum); urb->complete(urb); - kcov_remote_stop_softirq(flags); + kcov_remote_stop_softirq();
usb_anchor_resume_wakeups(anchor); atomic_dec(&urb->use_count); --- a/include/linux/kcov.h +++ b/include/linux/kcov.h @@ -57,47 +57,21 @@ static inline void kcov_remote_start_usb
/* * The softirq flavor of kcov_remote_*() functions is introduced as a temporary - * workaround for KCOV's lack of nested remote coverage sections support. - * - * Adding support is tracked in https://bugzilla.kernel.org/show_bug.cgi?id=210337. - * - * kcov_remote_start_usb_softirq(): - * - * 1. Only collects coverage when called in the softirq context. This allows - * avoiding nested remote coverage collection sections in the task context. - * For example, USB/IP calls usb_hcd_giveback_urb() in the task context - * within an existing remote coverage collection section. Thus, KCOV should - * not attempt to start collecting coverage within the coverage collection - * section in __usb_hcd_giveback_urb() in this case. - * - * 2. Disables interrupts for the duration of the coverage collection section. - * This allows avoiding nested remote coverage collection sections in the - * softirq context (a softirq might occur during the execution of a work in - * the BH workqueue, which runs with in_serving_softirq() > 0). - * For example, usb_giveback_urb_bh() runs in the BH workqueue with - * interrupts enabled, so __usb_hcd_giveback_urb() might be interrupted in - * the middle of its remote coverage collection section, and the interrupt - * handler might invoke __usb_hcd_giveback_urb() again. + * work around for kcov's lack of nested remote coverage sections support in + * task context. Adding support for nested sections is tracked in: + * https://bugzilla.kernel.org/show_bug.cgi?id=210337 */
-static inline unsigned long kcov_remote_start_usb_softirq(u64 id) +static inline void kcov_remote_start_usb_softirq(u64 id) { - unsigned long flags = 0; - - if (in_serving_softirq()) { - local_irq_save(flags); + if (in_serving_softirq() && !in_hardirq()) kcov_remote_start_usb(id); - } - - return flags; }
-static inline void kcov_remote_stop_softirq(unsigned long flags) +static inline void kcov_remote_stop_softirq(void) { - if (in_serving_softirq()) { + if (in_serving_softirq() && !in_hardirq()) kcov_remote_stop(); - local_irq_restore(flags); - } }
#ifdef CONFIG_64BIT @@ -131,11 +105,8 @@ static inline u64 kcov_common_handle(voi } static inline void kcov_remote_start_common(u64 id) {} static inline void kcov_remote_start_usb(u64 id) {} -static inline unsigned long kcov_remote_start_usb_softirq(u64 id) -{ - return 0; -} -static inline void kcov_remote_stop_softirq(unsigned long flags) {} +static inline void kcov_remote_start_usb_softirq(u64 id) {} +static inline void kcov_remote_stop_softirq(void) {}
#endif /* CONFIG_KCOV */ #endif /* _LINUX_KCOV_H */
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Thorsten Blum thorsten.blum@linux.dev
commit 300a0cfe9f375b2843bcb331bcfa7503475ef5dd upstream.
In cdx_rpmsg_probe(), strscpy() is incorrectly called with the length of the source string (excluding the NUL terminator) rather than the size of the destination buffer. This results in one character less being copied from 'cdx_rpmsg_id_table[0].name' to 'chinfo.name'.
Use the destination buffer size instead to ensure the name is copied correctly.
Cc: stable stable@kernel.org Fixes: 2a226927d9b8 ("cdx: add rpmsg communication channel for CDX") Signed-off-by: Thorsten Blum thorsten.blum@linux.dev Link: https://lore.kernel.org/r/20250806090512.121260-2-thorsten.blum@linux.dev Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/cdx/controller/cdx_rpmsg.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-)
--- a/drivers/cdx/controller/cdx_rpmsg.c +++ b/drivers/cdx/controller/cdx_rpmsg.c @@ -129,8 +129,7 @@ static int cdx_rpmsg_probe(struct rpmsg_
chinfo.src = RPMSG_ADDR_ANY; chinfo.dst = rpdev->dst; - strscpy(chinfo.name, cdx_rpmsg_id_table[0].name, - strlen(cdx_rpmsg_id_table[0].name)); + strscpy(chinfo.name, cdx_rpmsg_id_table[0].name, sizeof(chinfo.name));
cdx_mcdi->ept = rpmsg_create_ept(rpdev, cdx_rpmsg_cb, NULL, chinfo); if (!cdx_mcdi->ept) {
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Miao Li limiao@kylinos.cn
commit e664036cf36480414936cd91f4cfa2179a3d8367 upstream.
Another SanDisk 3.2Gen1 Flash Drive also need DELAY_INIT quick, or it will randomly work incorrectly on Huawei hisi platforms when doing reboot test.
Signed-off-by: Miao Li limiao@kylinos.cn Cc: stable stable@kernel.org Link: https://lore.kernel.org/r/20250801082728.469406-1-limiao870622@163.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/usb/core/quirks.c | 1 + 1 file changed, 1 insertion(+)
--- a/drivers/usb/core/quirks.c +++ b/drivers/usb/core/quirks.c @@ -371,6 +371,7 @@ static const struct usb_device_id usb_qu { USB_DEVICE(0x0781, 0x5591), .driver_info = USB_QUIRK_NO_LPM },
/* SanDisk Corp. SanDisk 3.2Gen1 */ + { USB_DEVICE(0x0781, 0x5596), .driver_info = USB_QUIRK_DELAY_INIT }, { USB_DEVICE(0x0781, 0x55a3), .driver_info = USB_QUIRK_DELAY_INIT },
/* SanDisk Extreme 55AE */
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ian Abbott abbotti@mev.co.uk
commit 7afba9221f70d4cbce0f417c558879cba0eb5e66 upstream.
The `insn_rw_emulate_bits()` function is used as a default handler for `INSN_READ` instructions for subdevices that have a handler for `INSN_BITS` but not for `INSN_READ`. Similarly, it is used as a default handler for `INSN_WRITE` instructions for subdevices that have a handler for `INSN_BITS` but not for `INSN_WRITE`. It works by emulating the `INSN_READ` or `INSN_WRITE` instruction handling with a constructed `INSN_BITS` instruction. However, `INSN_READ` and `INSN_WRITE` instructions are supposed to be able read or write multiple samples, indicated by the `insn->n` value, but `insn_rw_emulate_bits()` currently only handles a single sample. For `INSN_READ`, the comedi core will copy `insn->n` samples back to user-space. (That triggered KASAN kernel-infoleak errors when `insn->n` was greater than 1, but that is being fixed more generally elsewhere in the comedi core.)
Make `insn_rw_emulate_bits()` either handle `insn->n` samples, or return an error, to conform to the general expectation for `INSN_READ` and `INSN_WRITE` handlers.
Fixes: ed9eccbe8970 ("Staging: add comedi core") Cc: stable stable@kernel.org # 5.13+ Signed-off-by: Ian Abbott abbotti@mev.co.uk Link: https://lore.kernel.org/r/20250725141034.87297-1-abbotti@mev.co.uk Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/comedi/drivers.c | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-)
--- a/drivers/comedi/drivers.c +++ b/drivers/comedi/drivers.c @@ -620,11 +620,9 @@ static int insn_rw_emulate_bits(struct c unsigned int chan = CR_CHAN(insn->chanspec); unsigned int base_chan = (chan < 32) ? 0 : chan; unsigned int _data[2]; + unsigned int i; int ret;
- if (insn->n == 0) - return 0; - memset(_data, 0, sizeof(_data)); memset(&_insn, 0, sizeof(_insn)); _insn.insn = INSN_BITS; @@ -635,18 +633,21 @@ static int insn_rw_emulate_bits(struct c if (insn->insn == INSN_WRITE) { if (!(s->subdev_flags & SDF_WRITABLE)) return -EINVAL; - _data[0] = 1U << (chan - base_chan); /* mask */ - _data[1] = data[0] ? (1U << (chan - base_chan)) : 0; /* bits */ + _data[0] = 1U << (chan - base_chan); /* mask */ } + for (i = 0; i < insn->n; i++) { + if (insn->insn == INSN_WRITE) + _data[1] = data[i] ? _data[0] : 0; /* bits */ + + ret = s->insn_bits(dev, s, &_insn, _data); + if (ret < 0) + return ret;
- ret = s->insn_bits(dev, s, &_insn, _data); - if (ret < 0) - return ret; - - if (insn->insn == INSN_READ) - data[0] = (_data[1] >> (chan - base_chan)) & 1; + if (insn->insn == INSN_READ) + data[i] = (_data[1] >> (chan - base_chan)) & 1; + }
- return 1; + return insn->n; }
static int __comedi_device_postconfig_async(struct comedi_device *dev,
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Edward Adam Davis eadavis@qq.com
commit 96cb948408b3adb69df7e451ba7da9d21f814d00 upstream.
The reproducer passed in an irq number(0x80008000) that was too large, which triggered the oob.
Added an interrupt number check to prevent users from passing in an irq number that was too large.
If `it->options[1]` is 31, then `1 << it->options[1]` is still invalid because it shifts a 1-bit into the sign bit (which is UB in C). Possible solutions include reducing the upper bound on the `it->options[1]` value to 30 or lower, or using `1U << it->options[1]`.
The old code would just not attempt to request the IRQ if the `options[1]` value were invalid. And it would still configure the device without interrupts even if the call to `request_irq` returned an error. So it would be better to combine this test with the test below.
Fixes: fff46207245c ("staging: comedi: pcl726: enable the interrupt support code") Cc: stable stable@kernel.org # 5.13+ Reported-by: syzbot+5cd373521edd68bebcb3@syzkaller.appspotmail.com Closes: https://syzkaller.appspot.com/bug?extid=5cd373521edd68bebcb3 Tested-by: syzbot+5cd373521edd68bebcb3@syzkaller.appspotmail.com Signed-off-by: Edward Adam Davis eadavis@qq.com Reviewed-by: Ian Abbott abbotti@mev.co.uk Link: https://lore.kernel.org/r/tencent_3C66983CC1369E962436264A50759176BF09@qq.co... Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/comedi/drivers/pcl726.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
--- a/drivers/comedi/drivers/pcl726.c +++ b/drivers/comedi/drivers/pcl726.c @@ -328,7 +328,8 @@ static int pcl726_attach(struct comedi_d * Hook up the external trigger source interrupt only if the * user config option is valid and the board supports interrupts. */ - if (it->options[1] && (board->irq_mask & (1 << it->options[1]))) { + if (it->options[1] > 0 && it->options[1] < 16 && + (board->irq_mask & (1U << it->options[1]))) { ret = request_irq(it->options[1], pcl726_interrupt, 0, dev->board_name, dev); if (ret == 0) {
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ian Abbott abbotti@mev.co.uk
commit 3cd212e895ca2d58963fdc6422502b10dd3966bb upstream.
syzbot reports a KMSAN kernel-infoleak in `do_insn_ioctl()`. A kernel buffer is allocated to hold `insn->n` samples (each of which is an `unsigned int`). For some instruction types, `insn->n` samples are copied back to user-space, unless an error code is being returned. The problem is that not all the instruction handlers that need to return data to userspace fill in the whole `insn->n` samples, so that there is an information leak. There is a similar syzbot report for `do_insnlist_ioctl()`, although it does not have a reproducer for it at the time of writing.
One culprit is `insn_rw_emulate_bits()` which is used as the handler for `INSN_READ` or `INSN_WRITE` instructions for subdevices that do not have a specific handler for that instruction, but do have an `INSN_BITS` handler. For `INSN_READ` it only fills in at most 1 sample, so if `insn->n` is greater than 1, the remaining `insn->n - 1` samples copied to userspace will be uninitialized kernel data.
Another culprit is `vm80xx_ai_insn_read()` in the "vm80xx" driver. It never returns an error, even if it fails to fill the buffer.
Fix it in `do_insn_ioctl()` and `do_insnlist_ioctl()` by making sure that uninitialized parts of the allocated buffer are zeroed before handling each instruction.
Thanks to Arnaud Lecomte for their fix to `do_insn_ioctl()`. That fix replaced the call to `kmalloc_array()` with `kcalloc()`, but it is not always necessary to clear the whole buffer.
Fixes: ed9eccbe8970 ("Staging: add comedi core") Reported-by: syzbot+a5e45f768aab5892da5d@syzkaller.appspotmail.com Closes: https://syzkaller.appspot.com/bug?extid=a5e45f768aab5892da5d Reported-by: syzbot+fb4362a104d45ab09cf9@syzkaller.appspotmail.com Closes: https://syzkaller.appspot.com/bug?extid=fb4362a104d45ab09cf9 Cc: stable stable@kernel.org # 5.13+ Cc: Arnaud Lecomte contact@arnaud-lcm.com Signed-off-by: Ian Abbott abbotti@mev.co.uk Link: https://lore.kernel.org/r/20250725125324.80276-1-abbotti@mev.co.uk Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/comedi/comedi_fops.c | 5 +++++ 1 file changed, 5 insertions(+)
--- a/drivers/comedi/comedi_fops.c +++ b/drivers/comedi/comedi_fops.c @@ -1587,6 +1587,9 @@ static int do_insnlist_ioctl(struct come memset(&data[n], 0, (MIN_SAMPLES - n) * sizeof(unsigned int)); } + } else { + memset(data, 0, max_t(unsigned int, n, MIN_SAMPLES) * + sizeof(unsigned int)); } ret = parse_insn(dev, insns + i, data, file); if (ret < 0) @@ -1670,6 +1673,8 @@ static int do_insn_ioctl(struct comedi_d memset(&data[insn->n], 0, (MIN_SAMPLES - insn->n) * sizeof(unsigned int)); } + } else { + memset(data, 0, n_data * sizeof(unsigned int)); } ret = parse_insn(dev, insn, data, file); if (ret < 0)
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Xu Yang xu.yang_2@nxp.com
commit 8fe06185e11ae753414aa6117f0e798aa77567ff upstream.
The USB core will unmap urb->transfer_dma after SETUP stage completes. Then the USB controller will access unmapped memory when it received device descriptor. If iommu is equipped, the entire test can't be completed due to the memory accessing is blocked.
Fix it by calling map_urb_for_dma() again for IN stage. To reduce redundant map for urb->transfer_buffer, this will also set URB_NO_TRANSFER_DMA_MAP flag before first map_urb_for_dma() to skip dma map for urb->transfer_buffer and clear URB_NO_TRANSFER_DMA_MAP flag before second map_urb_for_dma().
Fixes: 216e0e563d81 ("usb: core: hcd: use map_urb_for_dma for single step set feature urb") Cc: stable stable@kernel.org Reviewed-by: Jun Li jun.li@nxp.com Signed-off-by: Xu Yang xu.yang_2@nxp.com Acked-by: Alan Stern stern@rowland.harvard.edu Link: https://lore.kernel.org/r/20250806083955.3325299-1-xu.yang_2@nxp.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/usb/core/hcd.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-)
--- a/drivers/usb/core/hcd.c +++ b/drivers/usb/core/hcd.c @@ -2151,7 +2151,7 @@ static struct urb *request_single_step_s urb->complete = usb_ehset_completion; urb->status = -EINPROGRESS; urb->actual_length = 0; - urb->transfer_flags = URB_DIR_IN; + urb->transfer_flags = URB_DIR_IN | URB_NO_TRANSFER_DMA_MAP; usb_get_urb(urb); atomic_inc(&urb->use_count); atomic_inc(&urb->dev->urbnum); @@ -2215,9 +2215,15 @@ int ehset_single_step_set_feature(struct
/* Complete remaining DATA and STATUS stages using the same URB */ urb->status = -EINPROGRESS; + urb->transfer_flags &= ~URB_NO_TRANSFER_DMA_MAP; usb_get_urb(urb); atomic_inc(&urb->use_count); atomic_inc(&urb->dev->urbnum); + if (map_urb_for_dma(hcd, urb, GFP_KERNEL)) { + usb_put_urb(urb); + goto out1; + } + retval = hcd->driver->submit_single_step_set_feature(hcd, urb, 0); if (!retval && !wait_for_completion_timeout(&done, msecs_to_jiffies(2000))) {
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Marek Vasut marek.vasut+renesas@mailbox.org
commit f9420f4757752f056144896024d5ea89e5a611f1 upstream.
Increase the External ROM access timeouts to prevent failures during programming of External SPI EEPROM chips. The current timeouts are too short for some SPI EEPROMs used with uPD720201 controllers.
The current timeout for Chip Erase in renesas_rom_erase() is 100 ms , the current timeout for Sector Erase issued by the controller before Page Program in renesas_fw_download_image() is also 100 ms. Neither timeout is sufficient for e.g. the Macronix MX25L5121E or MX25V5126F.
MX25L5121E reference manual [1] page 35 section "ERASE AND PROGRAMMING PERFORMANCE" and page 23 section "Table 8. AC CHARACTERISTICS (Temperature = 0°C to 70°C for Commercial grade, VCC = 2.7V ~ 3.6V)" row "tCE" indicate that the maximum time required for Chip Erase opcode to complete is 2 s, and for Sector Erase it is 300 ms .
MX25V5126F reference manual [2] page 47 section "13. ERASE AND PROGRAMMING PERFORMANCE (2.3V - 3.6V)" and page 42 section "Table 8. AC CHARACTERISTICS (Temperature = -40°C to 85°C for Industrial grade, VCC = 2.3V - 3.6V)" row "tCE" indicate that the maximum time required for Chip Erase opcode to complete is 3.2 s, and for Sector Erase it is 400 ms .
Update the timeouts such, that Chip Erase timeout is set to 5 seconds, and Sector Erase timeout is set to 500 ms. Such lengthy timeouts ought to be sufficient for majority of SPI EEPROM chips.
[1] https://www.macronix.com/Lists/Datasheet/Attachments/8634/MX25L5121E,%203V,%... [2] https://www.macronix.com/Lists/Datasheet/Attachments/8750/MX25V5126F,%202.5V...
Fixes: 2478be82de44 ("usb: renesas-xhci: Add ROM loader for uPD720201") Cc: stable stable@kernel.org Signed-off-by: Marek Vasut marek.vasut+renesas@mailbox.org Link: https://lore.kernel.org/r/20250802225526.25431-1-marek.vasut+renesas@mailbox... Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/usb/host/xhci-pci-renesas.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-)
--- a/drivers/usb/host/xhci-pci-renesas.c +++ b/drivers/usb/host/xhci-pci-renesas.c @@ -47,8 +47,9 @@ #define RENESAS_ROM_ERASE_MAGIC 0x5A65726F #define RENESAS_ROM_WRITE_MAGIC 0x53524F4D
-#define RENESAS_RETRY 10000 -#define RENESAS_DELAY 10 +#define RENESAS_RETRY 50000 /* 50000 * RENESAS_DELAY ~= 500ms */ +#define RENESAS_CHIP_ERASE_RETRY 500000 /* 500000 * RENESAS_DELAY ~= 5s */ +#define RENESAS_DELAY 10
#define RENESAS_FW_NAME "renesas_usb_fw.mem"
@@ -407,7 +408,7 @@ static void renesas_rom_erase(struct pci /* sleep a bit while ROM is erased */ msleep(20);
- for (i = 0; i < RENESAS_RETRY; i++) { + for (i = 0; i < RENESAS_CHIP_ERASE_RETRY; i++) { retval = pci_read_config_byte(pdev, RENESAS_ROM_STATUS, &status); status &= RENESAS_ROM_STATUS_ERASE;
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Mael GUERIN mael.guerin@murena.io
commit 6ca8af3c8fb584f3424a827f554ff74f898c27cd upstream.
Add the US_FL_BULK_IGNORE_TAG quirk for Novatek NTK96550-based camera to fix USB resets after sending SCSI vendor commands due to CBW and CSW tags difference, leading to undesired slowness while communicating with the device.
Please find below the copy of /sys/kernel/debug/usb/devices with my device plugged in (listed as TechSys USB mass storage here, the underlying chipset being the Novatek NTK96550-based camera):
T: Bus=03 Lev=01 Prnt=01 Port=00 Cnt=01 Dev#= 3 Spd=480 MxCh= 0 D: Ver= 2.00 Cls=00(>ifc ) Sub=00 Prot=00 MxPS=64 #Cfgs= 1 P: Vendor=0603 ProdID=8611 Rev= 0.01 S: Manufacturer=TechSys S: Product=USB Mass Storage S: SerialNumber=966110000000100 C:* #Ifs= 1 Cfg#= 1 Atr=c0 MxPwr=100mA I:* If#= 0 Alt= 0 #EPs= 2 Cls=08(stor.) Sub=06 Prot=50 Driver=usb-storage E: Ad=81(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=02(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms
Signed-off-by: Mael GUERIN mael.guerin@murena.io Cc: stable stable@kernel.org Acked-by: Alan Stern stern@rowland.harvard.edu Link: https://lore.kernel.org/r/20250806164406.43450-1-mael.guerin@murena.io Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/usb/storage/unusual_devs.h | 7 +++++++ 1 file changed, 7 insertions(+)
--- a/drivers/usb/storage/unusual_devs.h +++ b/drivers/usb/storage/unusual_devs.h @@ -934,6 +934,13 @@ UNUSUAL_DEV( 0x05e3, 0x0723, 0x9451, 0x USB_SC_DEVICE, USB_PR_DEVICE, NULL, US_FL_SANE_SENSE ),
+/* Added by Maël GUERIN mael.guerin@murena.io */ +UNUSUAL_DEV( 0x0603, 0x8611, 0x0000, 0xffff, + "Novatek", + "NTK96550-based camera", + USB_SC_SCSI, USB_PR_BULK, NULL, + US_FL_BULK_IGNORE_TAG ), + /* * Reported by Hanno Boeck hanno@gmx.de * Taken from the Lycoris Kernel
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Thorsten Blum thorsten.blum@linux.dev
commit 98da66a70ad2396e5a508c4245367797ebc052ce upstream.
Since 'bcs->Residue' has the data type '__le32', convert it to the correct byte order of the CPU using this driver when assigning it to the local variable 'residue'.
Cc: stable stable@kernel.org Fixes: 50a6cb932d5c ("USB: usb_storage: add ums-realtek driver") Suggested-by: Alan Stern stern@rowland.harvard.edu Acked-by: Alan Stern stern@rowland.harvard.edu Signed-off-by: Thorsten Blum thorsten.blum@linux.dev Link: https://lore.kernel.org/r/20250813145247.184717-3-thorsten.blum@linux.dev Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/usb/storage/realtek_cr.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
--- a/drivers/usb/storage/realtek_cr.c +++ b/drivers/usb/storage/realtek_cr.c @@ -252,7 +252,7 @@ static int rts51x_bulk_transport(struct return USB_STOR_TRANSPORT_ERROR; }
- residue = bcs->Residue; + residue = le32_to_cpu(bcs->Residue); if (bcs->Tag != us->tag) return USB_STOR_TRANSPORT_ERROR;
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Zenm Chen zenmchen@gmail.com
commit a3dc32c635bae0ae569f489e00de0e8f015bfc25 upstream.
Many Realtek USB Wi-Fi dongles released in recent years have two modes: one is driver CD mode which has Windows driver onboard, another one is Wi-Fi mode. Add the US_FL_IGNORE_DEVICE quirk for these multi-mode devices. Otherwise, usb_modeswitch may fail to switch them to Wi-Fi mode.
Currently there are only two USB IDs known to be used by these multi-mode Wi-Fi dongles: 0bda:1a2b and 0bda:a192.
Information about Mercury MW310UH in /sys/kernel/debug/usb/devices. T: Bus=02 Lev=01 Prnt=01 Port=01 Cnt=01 Dev#= 12 Spd=480 MxCh= 0 D: Ver= 2.00 Cls=00(>ifc ) Sub=00 Prot=00 MxPS=64 #Cfgs= 1 P: Vendor=0bda ProdID=a192 Rev= 2.00 S: Manufacturer=Realtek S: Product=DISK C:* #Ifs= 1 Cfg#= 1 Atr=80 MxPwr=500mA I:* If#= 0 Alt= 0 #EPs= 2 Cls=08(stor.) Sub=06 Prot=50 Driver=(none) E: Ad=8a(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=0b(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms
Information about D-Link AX9U rev. A1 in /sys/kernel/debug/usb/devices. T: Bus=03 Lev=01 Prnt=01 Port=02 Cnt=01 Dev#= 55 Spd=480 MxCh= 0 D: Ver= 2.00 Cls=00(>ifc ) Sub=00 Prot=00 MxPS=64 #Cfgs= 1 P: Vendor=0bda ProdID=1a2b Rev= 0.00 S: Manufacturer=Realtek S: Product=DISK C:* #Ifs= 1 Cfg#= 1 Atr=e0 MxPwr=500mA I:* If#= 0 Alt= 0 #EPs= 2 Cls=08(stor.) Sub=06 Prot=50 Driver=(none) E: Ad=84(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=05(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms
Cc: stable stable@kernel.org Signed-off-by: Zenm Chen zenmchen@gmail.com Acked-by: Alan Stern stern@rowland.harvard.edu Link: https://lore.kernel.org/r/20250813162415.2630-1-zenmchen@gmail.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/usb/storage/unusual_devs.h | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+)
--- a/drivers/usb/storage/unusual_devs.h +++ b/drivers/usb/storage/unusual_devs.h @@ -1501,6 +1501,28 @@ UNUSUAL_DEV( 0x0bc2, 0x3332, 0x0000, 0x9 USB_SC_DEVICE, USB_PR_DEVICE, NULL, US_FL_NO_WP_DETECT ),
+/* + * Reported by Zenm Chen zenmchen@gmail.com + * Ignore driver CD mode, otherwise usb_modeswitch may fail to switch + * the device into Wi-Fi mode. + */ +UNUSUAL_DEV( 0x0bda, 0x1a2b, 0x0000, 0xffff, + "Realtek", + "DISK", + USB_SC_DEVICE, USB_PR_DEVICE, NULL, + US_FL_IGNORE_DEVICE ), + +/* + * Reported by Zenm Chen zenmchen@gmail.com + * Ignore driver CD mode, otherwise usb_modeswitch may fail to switch + * the device into Wi-Fi mode. + */ +UNUSUAL_DEV( 0x0bda, 0xa192, 0x0000, 0xffff, + "Realtek", + "DISK", + USB_SC_DEVICE, USB_PR_DEVICE, NULL, + US_FL_IGNORE_DEVICE ), + UNUSUAL_DEV( 0x0d49, 0x7310, 0x0000, 0x9999, "Maxtor", "USB to SATA",
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Amit Sunil Dhamne amitsd@google.com
commit cabb6c5f4d9e7f49bdf8c0a13c74bd93ee35f45a upstream.
Low power mode is enabled when reading CC resistance as part of `max_contaminant_read_resistance_kohm()` and left in that state. However, it's supposed to work with 1uA current source. To read CC comparator values current source is changed to 80uA. This causes a storm of CC interrupts as it (falsely) detects a potential contaminant. To prevent this, disable low power mode current sourcing before reading comparator values.
Fixes: 02b332a06397 ("usb: typec: maxim_contaminant: Implement check_contaminant callback") Cc: stable stable@kernel.org Signed-off-by: Amit Sunil Dhamne amitsd@google.com Reviewed-by: Badhri Jagan Sridharan badhri@google.com Link: https://lore.kernel.org/stable/20250814-fix-upstream-contaminant-v1-1-801ce8... Link: https://lore.kernel.org/r/20250815-fix-upstream-contaminant-v2-1-6c8d6c3adaf... Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/usb/typec/tcpm/maxim_contaminant.c | 5 +++++ drivers/usb/typec/tcpm/tcpci_maxim.h | 1 + 2 files changed, 6 insertions(+)
--- a/drivers/usb/typec/tcpm/maxim_contaminant.c +++ b/drivers/usb/typec/tcpm/maxim_contaminant.c @@ -188,6 +188,11 @@ static int max_contaminant_read_comparat if (ret < 0) return ret;
+ /* Disable low power mode */ + ret = regmap_update_bits(regmap, TCPC_VENDOR_CC_CTRL2, CCLPMODESEL, + FIELD_PREP(CCLPMODESEL, + LOW_POWER_MODE_DISABLE)); + /* Sleep to allow comparators settle */ usleep_range(5000, 6000); ret = regmap_update_bits(regmap, TCPC_TCPC_CTRL, TCPC_TCPC_CTRL_ORIENTATION, PLUG_ORNT_CC1); --- a/drivers/usb/typec/tcpm/tcpci_maxim.h +++ b/drivers/usb/typec/tcpm/tcpci_maxim.h @@ -21,6 +21,7 @@ #define CCOVPDIS BIT(6) #define SBURPCTRL BIT(5) #define CCLPMODESEL GENMASK(4, 3) +#define LOW_POWER_MODE_DISABLE 0 #define ULTRA_LOW_POWER_MODE 1 #define CCRPCTRL GENMASK(2, 0) #define UA_1_SRC 1
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Amit Sunil Dhamne amitsd@google.com
commit a381c6d6f646226924809d0ad01a9465786da463 upstream.
Presently in `max_contaminant_is_contaminant()` if there's no contaminant detected previously, CC is open & stopped toggling and no contaminant is currently present, TCPC.RC would be programmed to do DRP toggling. However, it didn't actively look for a connection. This would lead to Type-C not detect *any* new connections. Hence, in the above situation, re-enable toggling & program TCPC to look for a new connection.
Also, return early if TCPC was looking for connection as this indicates TCPC has neither detected a potential connection nor a change in contaminant state.
In addition, once dry detection is complete (port is dry), restart toggling.
Fixes: 02b332a06397e ("usb: typec: maxim_contaminant: Implement check_contaminant callback") Cc: stable stable@kernel.org Signed-off-by: Amit Sunil Dhamne amitsd@google.com Reviewed-by: Badhri Jagan Sridharan badhri@google.com Link: https://lore.kernel.org/r/20250815-fix-upstream-contaminant-v2-2-6c8d6c3adaf... Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/usb/typec/tcpm/maxim_contaminant.c | 53 +++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+)
--- a/drivers/usb/typec/tcpm/maxim_contaminant.c +++ b/drivers/usb/typec/tcpm/maxim_contaminant.c @@ -329,6 +329,39 @@ static int max_contaminant_enable_dry_de return 0; }
+static int max_contaminant_enable_toggling(struct max_tcpci_chip *chip) +{ + struct regmap *regmap = chip->data.regmap; + int ret; + + /* Disable dry detection if enabled. */ + ret = regmap_update_bits(regmap, TCPC_VENDOR_CC_CTRL2, CCLPMODESEL, + FIELD_PREP(CCLPMODESEL, + LOW_POWER_MODE_DISABLE)); + if (ret) + return ret; + + ret = regmap_update_bits(regmap, TCPC_VENDOR_CC_CTRL1, CCCONNDRY, 0); + if (ret) + return ret; + + ret = max_tcpci_write8(chip, TCPC_ROLE_CTRL, TCPC_ROLE_CTRL_DRP | + FIELD_PREP(TCPC_ROLE_CTRL_CC1, + TCPC_ROLE_CTRL_CC_RD) | + FIELD_PREP(TCPC_ROLE_CTRL_CC2, + TCPC_ROLE_CTRL_CC_RD)); + if (ret) + return ret; + + ret = regmap_update_bits(regmap, TCPC_TCPC_CTRL, + TCPC_TCPC_CTRL_EN_LK4CONN_ALRT, + TCPC_TCPC_CTRL_EN_LK4CONN_ALRT); + if (ret) + return ret; + + return max_tcpci_write8(chip, TCPC_COMMAND, TCPC_CMD_LOOK4CONNECTION); +} + bool max_contaminant_is_contaminant(struct max_tcpci_chip *chip, bool disconnect_while_debounce, bool *cc_handled) { @@ -345,6 +378,12 @@ bool max_contaminant_is_contaminant(stru if (ret < 0) return false;
+ if (cc_status & TCPC_CC_STATUS_TOGGLING) { + if (chip->contaminant_state == DETECTED) + return true; + return false; + } + if (chip->contaminant_state == NOT_DETECTED || chip->contaminant_state == SINK) { if (!disconnect_while_debounce) msleep(100); @@ -377,6 +416,12 @@ bool max_contaminant_is_contaminant(stru max_contaminant_enable_dry_detection(chip); return true; } + + ret = max_contaminant_enable_toggling(chip); + if (ret) + dev_err(chip->dev, + "Failed to enable toggling, ret=%d", + ret); } } else if (chip->contaminant_state == DETECTED) { if (!(cc_status & TCPC_CC_STATUS_TOGGLING)) { @@ -384,6 +429,14 @@ bool max_contaminant_is_contaminant(stru if (chip->contaminant_state == DETECTED) { max_contaminant_enable_dry_detection(chip); return true; + } else { + ret = max_contaminant_enable_toggling(chip); + if (ret) { + dev_err(chip->dev, + "Failed to enable toggling, ret=%d", + ret); + return true; + } } } }
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Weitao Wang WeitaoWang-oc@zhaoxin.com
commit 2eb03376151bb8585caa23ed2673583107bb5193 upstream.
xHC controller may immediately reuse a slot_id after it's disabled, giving it to a new enumerating device before the xhci driver freed all resources related to the disabled device.
In such a scenario, device-A with slot_id equal to 1 is disconnecting while device-B is enumerating, device-B will fail to enumerate in the follow sequence.
1.[device-A] send disable slot command 2.[device-B] send enable slot command 3.[device-A] disable slot command completed and wakeup waiting thread 4.[device-B] enable slot command completed with slot_id equal to 1 and wakeup waiting thread 5.[device-B] driver checks that slot_id is still in use (by device-A) in xhci_alloc_virt_device, and fail to enumerate due to this conflict 6.[device-A] xhci->devs[slot_id] set to NULL in xhci_free_virt_device
To fix driver's slot_id resources conflict, clear xhci->devs[slot_id] and xhci->dcbba->dev_context_ptrs[slot_id] pointers in the interrupt context when disable slot command completes successfully. Simultaneously, adjust function xhci_free_virt_device to accurately handle device release.
[minor smatch warning and commit message fix -Mathias]
Cc: stable@vger.kernel.org Fixes: 7faac1953ed1 ("xhci: avoid race between disable slot command and host runtime suspend") Signed-off-by: Weitao Wang WeitaoWang-oc@zhaoxin.com Signed-off-by: Mathias Nyman mathias.nyman@linux.intel.com Link: https://lore.kernel.org/r/20250819125844.2042452-2-mathias.nyman@linux.intel... Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/usb/host/xhci-hub.c | 3 +-- drivers/usb/host/xhci-mem.c | 22 +++++++++++----------- drivers/usb/host/xhci-ring.c | 9 +++++++-- drivers/usb/host/xhci.c | 21 ++++++++++++++------- drivers/usb/host/xhci.h | 3 ++- 5 files changed, 35 insertions(+), 23 deletions(-)
--- a/drivers/usb/host/xhci-hub.c +++ b/drivers/usb/host/xhci-hub.c @@ -704,8 +704,7 @@ static int xhci_enter_test_mode(struct x if (!xhci->devs[i]) continue;
- retval = xhci_disable_slot(xhci, i); - xhci_free_virt_device(xhci, i); + retval = xhci_disable_and_free_slot(xhci, i); if (retval) xhci_err(xhci, "Failed to disable slot %d, %d. Enter test mode anyway\n", i, retval); --- a/drivers/usb/host/xhci-mem.c +++ b/drivers/usb/host/xhci-mem.c @@ -865,21 +865,20 @@ free_tts: * will be manipulated by the configure endpoint, allocate device, or update * hub functions while this function is removing the TT entries from the list. */ -void xhci_free_virt_device(struct xhci_hcd *xhci, int slot_id) +void xhci_free_virt_device(struct xhci_hcd *xhci, struct xhci_virt_device *dev, + int slot_id) { - struct xhci_virt_device *dev; int i; int old_active_eps = 0;
/* Slot ID 0 is reserved */ - if (slot_id == 0 || !xhci->devs[slot_id]) + if (slot_id == 0 || !dev) return;
- dev = xhci->devs[slot_id]; - - xhci->dcbaa->dev_context_ptrs[slot_id] = 0; - if (!dev) - return; + /* If device ctx array still points to _this_ device, clear it */ + if (dev->out_ctx && + xhci->dcbaa->dev_context_ptrs[slot_id] == cpu_to_le64(dev->out_ctx->dma)) + xhci->dcbaa->dev_context_ptrs[slot_id] = 0;
trace_xhci_free_virt_device(dev);
@@ -920,8 +919,9 @@ void xhci_free_virt_device(struct xhci_h dev->udev->slot_id = 0; if (dev->rhub_port && dev->rhub_port->slot_id == slot_id) dev->rhub_port->slot_id = 0; - kfree(xhci->devs[slot_id]); - xhci->devs[slot_id] = NULL; + if (xhci->devs[slot_id] == dev) + xhci->devs[slot_id] = NULL; + kfree(dev); }
/* @@ -962,7 +962,7 @@ static void xhci_free_virt_devices_depth out: /* we are now at a leaf device */ xhci_debugfs_remove_slot(xhci, slot_id); - xhci_free_virt_device(xhci, slot_id); + xhci_free_virt_device(xhci, vdev, slot_id); }
int xhci_alloc_virt_device(struct xhci_hcd *xhci, int slot_id, --- a/drivers/usb/host/xhci-ring.c +++ b/drivers/usb/host/xhci-ring.c @@ -1592,7 +1592,8 @@ static void xhci_handle_cmd_enable_slot( command->slot_id = 0; }
-static void xhci_handle_cmd_disable_slot(struct xhci_hcd *xhci, int slot_id) +static void xhci_handle_cmd_disable_slot(struct xhci_hcd *xhci, int slot_id, + u32 cmd_comp_code) { struct xhci_virt_device *virt_dev; struct xhci_slot_ctx *slot_ctx; @@ -1607,6 +1608,10 @@ static void xhci_handle_cmd_disable_slot if (xhci->quirks & XHCI_EP_LIMIT_QUIRK) /* Delete default control endpoint resources */ xhci_free_device_endpoint_resources(xhci, virt_dev, true); + if (cmd_comp_code == COMP_SUCCESS) { + xhci->dcbaa->dev_context_ptrs[slot_id] = 0; + xhci->devs[slot_id] = NULL; + } }
static void xhci_handle_cmd_config_ep(struct xhci_hcd *xhci, int slot_id) @@ -1856,7 +1861,7 @@ static void handle_cmd_completion(struct xhci_handle_cmd_enable_slot(slot_id, cmd, cmd_comp_code); break; case TRB_DISABLE_SLOT: - xhci_handle_cmd_disable_slot(xhci, slot_id); + xhci_handle_cmd_disable_slot(xhci, slot_id, cmd_comp_code); break; case TRB_CONFIG_EP: if (!cmd->completion) --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -3932,8 +3932,7 @@ static int xhci_discover_or_reset_device * Obtaining a new device slot to inform the xHCI host that * the USB device has been reset. */ - ret = xhci_disable_slot(xhci, udev->slot_id); - xhci_free_virt_device(xhci, udev->slot_id); + ret = xhci_disable_and_free_slot(xhci, udev->slot_id); if (!ret) { ret = xhci_alloc_dev(hcd, udev); if (ret == 1) @@ -4090,7 +4089,7 @@ static void xhci_free_dev(struct usb_hcd xhci_disable_slot(xhci, udev->slot_id);
spin_lock_irqsave(&xhci->lock, flags); - xhci_free_virt_device(xhci, udev->slot_id); + xhci_free_virt_device(xhci, virt_dev, udev->slot_id); spin_unlock_irqrestore(&xhci->lock, flags);
} @@ -4139,6 +4138,16 @@ int xhci_disable_slot(struct xhci_hcd *x return 0; }
+int xhci_disable_and_free_slot(struct xhci_hcd *xhci, u32 slot_id) +{ + struct xhci_virt_device *vdev = xhci->devs[slot_id]; + int ret; + + ret = xhci_disable_slot(xhci, slot_id); + xhci_free_virt_device(xhci, vdev, slot_id); + return ret; +} + /* * Checks if we have enough host controller resources for the default control * endpoint. @@ -4245,8 +4254,7 @@ int xhci_alloc_dev(struct usb_hcd *hcd, return 1;
disable_slot: - xhci_disable_slot(xhci, udev->slot_id); - xhci_free_virt_device(xhci, udev->slot_id); + xhci_disable_and_free_slot(xhci, udev->slot_id);
return 0; } @@ -4382,8 +4390,7 @@ static int xhci_setup_device(struct usb_ dev_warn(&udev->dev, "Device not responding to setup %s.\n", act);
mutex_unlock(&xhci->mutex); - ret = xhci_disable_slot(xhci, udev->slot_id); - xhci_free_virt_device(xhci, udev->slot_id); + ret = xhci_disable_and_free_slot(xhci, udev->slot_id); if (!ret) { if (xhci_alloc_dev(hcd, udev) == 1) xhci_setup_addressable_virt_dev(xhci, udev); --- a/drivers/usb/host/xhci.h +++ b/drivers/usb/host/xhci.h @@ -1791,7 +1791,7 @@ void xhci_dbg_trace(struct xhci_hcd *xhc /* xHCI memory management */ void xhci_mem_cleanup(struct xhci_hcd *xhci); int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags); -void xhci_free_virt_device(struct xhci_hcd *xhci, int slot_id); +void xhci_free_virt_device(struct xhci_hcd *xhci, struct xhci_virt_device *dev, int slot_id); int xhci_alloc_virt_device(struct xhci_hcd *xhci, int slot_id, struct usb_device *udev, gfp_t flags); int xhci_setup_addressable_virt_dev(struct xhci_hcd *xhci, struct usb_device *udev); void xhci_copy_ep0_dequeue_into_input_ctx(struct xhci_hcd *xhci, @@ -1888,6 +1888,7 @@ void xhci_reset_bandwidth(struct usb_hcd int xhci_update_hub_device(struct usb_hcd *hcd, struct usb_device *hdev, struct usb_tt *tt, gfp_t mem_flags); int xhci_disable_slot(struct xhci_hcd *xhci, u32 slot_id); +int xhci_disable_and_free_slot(struct xhci_hcd *xhci, u32 slot_id); int xhci_ext_cap_init(struct xhci_hcd *xhci);
int xhci_suspend(struct xhci_hcd *xhci, bool do_wakeup);
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Niklas Neronin niklas.neronin@linux.intel.com
commit ff9a09b3e09c7b794b56f2f5858f5ce42ba46cb3 upstream.
Partially revert commit e1db856bd288 ("usb: xhci: remove '0' write to write-1-to-clear register") because the patch cleared the Interrupt Pending bit during interrupt enabling and disabling. The Interrupt Pending bit should only be cleared when the driver has handled the interrupt.
Ideally, all interrupts should be handled before disabling the interrupt; consequently, no interrupt should be pending when enabling the interrupt. For this reason, keep the debug message informing if an interrupt is still pending when an interrupt is disabled.
Because the Interrupt Pending bit is write-1-to-clear, writing '0' to it ensures that the state does not change.
Link: https://lore.kernel.org/linux-usb/20250818231103.672ec7ed@foxbook Fixes: e1db856bd288 ("usb: xhci: remove '0' write to write-1-to-clear register") Closes: https://bbs.archlinux.org/viewtopic.php?id=307641 cc: stable@vger.kernel.org # 6.16+ Signed-off-by: Niklas Neronin niklas.neronin@linux.intel.com Signed-off-by: Mathias Nyman mathias.nyman@linux.intel.com Link: https://lore.kernel.org/r/20250819125844.2042452-3-mathias.nyman@linux.intel... Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/usb/host/xhci.c | 2 ++ 1 file changed, 2 insertions(+)
diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index 0e03691f03bf..742c23826e17 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -309,6 +309,7 @@ int xhci_enable_interrupter(struct xhci_interrupter *ir) return -EINVAL;
iman = readl(&ir->ir_set->iman); + iman &= ~IMAN_IP; iman |= IMAN_IE; writel(iman, &ir->ir_set->iman);
@@ -325,6 +326,7 @@ int xhci_disable_interrupter(struct xhci_hcd *xhci, struct xhci_interrupter *ir) return -EINVAL;
iman = readl(&ir->ir_set->iman); + iman &= ~IMAN_IP; iman &= ~IMAN_IE; writel(iman, &ir->ir_set->iman);
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Kuen-Han Tsai khtsai@google.com
commit 58577118cc7cec9eb7c1836bf88f865ff2c5e3a3 upstream.
During a device-initiated disconnect, the End Transfer command resets the event filter, allowing a new xferNotReady event to be generated before the controller is fully halted. Processing this late event incorrectly triggers a Start Transfer, which prevents the controller from halting and results in a DSTS.DEVCTLHLT bit polling timeout.
Ignore the late xferNotReady event if the controller is already in a disconnected state.
Fixes: 72246da40f37 ("usb: Introduce DesignWare USB3 DRD Driver") Cc: stable stable@kernel.org Signed-off-by: Kuen-Han Tsai khtsai@google.com Acked-by: Thinh Nguyen Thinh.Nguyen@synopsys.com Link: https://lore.kernel.org/r/20250807090700.2397190-1-khtsai@google.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/usb/dwc3/gadget.c | 9 +++++++++ 1 file changed, 9 insertions(+)
--- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -3779,6 +3779,15 @@ static void dwc3_gadget_endpoint_transfe static void dwc3_gadget_endpoint_transfer_not_ready(struct dwc3_ep *dep, const struct dwc3_event_depevt *event) { + /* + * During a device-initiated disconnect, a late xferNotReady event can + * be generated after the End Transfer command resets the event filter, + * but before the controller is halted. Ignore it to prevent a new + * transfer from starting. + */ + if (!dep->dwc->connected) + return; + dwc3_gadget_endpoint_frame_from_event(dep, event);
/*
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Selvarasu Ganesan selvarasu.g@samsung.com
commit 45eae113dccaf8e502090ecf5b3d9e9b805add6f upstream.
This commit addresses a rarely observed endpoint command timeout which causes kernel panic due to warn when 'panic_on_warn' is enabled and unnecessary call trace prints when 'panic_on_warn' is disabled. It is seen during fast software-controlled connect/disconnect testcases. The following is one such endpoint command timeout that we observed:
1. Connect ======= ->dwc3_thread_interrupt ->dwc3_ep0_interrupt ->configfs_composite_setup ->composite_setup ->usb_ep_queue ->dwc3_gadget_ep0_queue ->__dwc3_gadget_ep0_queue ->__dwc3_ep0_do_control_data ->dwc3_send_gadget_ep_cmd
2. Disconnect ========== ->dwc3_thread_interrupt ->dwc3_gadget_disconnect_interrupt ->dwc3_ep0_reset_state ->dwc3_ep0_end_control_data ->dwc3_send_gadget_ep_cmd
In the issue scenario, in Exynos platforms, we observed that control transfers for the previous connect have not yet been completed and end transfer command sent as a part of the disconnect sequence and processing of USB_ENDPOINT_HALT feature request from the host timeout. This maybe an expected scenario since the controller is processing EP commands sent as a part of the previous connect. It maybe better to remove WARN_ON in all places where device endpoint commands are sent to avoid unnecessary kernel panic due to warn.
Cc: stable stable@kernel.org Co-developed-by: Akash M akash.m5@samsung.com Signed-off-by: Akash M akash.m5@samsung.com Signed-off-by: Selvarasu Ganesan selvarasu.g@samsung.com Acked-by: Thinh Nguyen Thinh.Nguyen@synopsys.com Reviewed-by: Sebastian Andrzej Siewior bigeasy@linutronix.de Link: https://lore.kernel.org/r/20250808125315.1607-1-selvarasu.g@samsung.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/usb/dwc3/ep0.c | 20 ++++++++++++++++---- drivers/usb/dwc3/gadget.c | 10 ++++++++-- 2 files changed, 24 insertions(+), 6 deletions(-)
--- a/drivers/usb/dwc3/ep0.c +++ b/drivers/usb/dwc3/ep0.c @@ -288,7 +288,9 @@ void dwc3_ep0_out_start(struct dwc3 *dwc dwc3_ep0_prepare_one_trb(dep, dwc->ep0_trb_addr, 8, DWC3_TRBCTL_CONTROL_SETUP, false); ret = dwc3_ep0_start_trans(dep); - WARN_ON(ret < 0); + if (ret < 0) + dev_err(dwc->dev, "ep0 out start transfer failed: %d\n", ret); + for (i = 2; i < DWC3_ENDPOINTS_NUM; i++) { struct dwc3_ep *dwc3_ep;
@@ -1061,7 +1063,9 @@ static void __dwc3_ep0_do_control_data(s ret = dwc3_ep0_start_trans(dep); }
- WARN_ON(ret < 0); + if (ret < 0) + dev_err(dwc->dev, + "ep0 data phase start transfer failed: %d\n", ret); }
static int dwc3_ep0_start_control_status(struct dwc3_ep *dep) @@ -1078,7 +1082,12 @@ static int dwc3_ep0_start_control_status
static void __dwc3_ep0_do_control_status(struct dwc3 *dwc, struct dwc3_ep *dep) { - WARN_ON(dwc3_ep0_start_control_status(dep)); + int ret; + + ret = dwc3_ep0_start_control_status(dep); + if (ret) + dev_err(dwc->dev, + "ep0 status phase start transfer failed: %d\n", ret); }
static void dwc3_ep0_do_control_status(struct dwc3 *dwc, @@ -1121,7 +1130,10 @@ void dwc3_ep0_end_control_data(struct dw cmd |= DWC3_DEPCMD_PARAM(dep->resource_index); memset(¶ms, 0, sizeof(params)); ret = dwc3_send_gadget_ep_cmd(dep, cmd, ¶ms); - WARN_ON_ONCE(ret); + if (ret) + dev_err_ratelimited(dwc->dev, + "ep0 data phase end transfer failed: %d\n", ret); + dep->resource_index = 0; }
--- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -1774,7 +1774,11 @@ static int __dwc3_stop_active_transfer(s dep->flags |= DWC3_EP_DELAY_STOP; return 0; } - WARN_ON_ONCE(ret); + + if (ret) + dev_err_ratelimited(dep->dwc->dev, + "end transfer failed: %d\n", ret); + dep->resource_index = 0;
if (!interrupt) @@ -4050,7 +4054,9 @@ static void dwc3_clear_stall_all_ep(stru dep->flags &= ~DWC3_EP_STALL;
ret = dwc3_send_clear_stall_ep_cmd(dep); - WARN_ON_ONCE(ret); + if (ret) + dev_err_ratelimited(dwc->dev, + "failed to clear STALL on %s\n", dep->name); } }
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Heikki Krogerus heikki.krogerus@linux.intel.com
commit 86f390ba59cd8d5755bafe2b163c3e6b89d6bbd9 upstream.
This patch adds the necessary PCI ID for Intel Wildcat Lake devices.
Signed-off-by: Heikki Krogerus heikki.krogerus@linux.intel.com Cc: stable stable@kernel.org Link: https://lore.kernel.org/r/20250812131101.2930199-1-heikki.krogerus@linux.int... Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/usb/dwc3/dwc3-pci.c | 2 ++ 1 file changed, 2 insertions(+)
--- a/drivers/usb/dwc3/dwc3-pci.c +++ b/drivers/usb/dwc3/dwc3-pci.c @@ -41,6 +41,7 @@ #define PCI_DEVICE_ID_INTEL_TGPLP 0xa0ee #define PCI_DEVICE_ID_INTEL_TGPH 0x43ee #define PCI_DEVICE_ID_INTEL_JSP 0x4dee +#define PCI_DEVICE_ID_INTEL_WCL 0x4d7e #define PCI_DEVICE_ID_INTEL_ADL 0x460e #define PCI_DEVICE_ID_INTEL_ADL_PCH 0x51ee #define PCI_DEVICE_ID_INTEL_ADLN 0x465e @@ -431,6 +432,7 @@ static const struct pci_device_id dwc3_p { PCI_DEVICE_DATA(INTEL, TGPLP, &dwc3_pci_intel_swnode) }, { PCI_DEVICE_DATA(INTEL, TGPH, &dwc3_pci_intel_swnode) }, { PCI_DEVICE_DATA(INTEL, JSP, &dwc3_pci_intel_swnode) }, + { PCI_DEVICE_DATA(INTEL, WCL, &dwc3_pci_intel_swnode) }, { PCI_DEVICE_DATA(INTEL, ADL, &dwc3_pci_intel_swnode) }, { PCI_DEVICE_DATA(INTEL, ADL_PCH, &dwc3_pci_intel_swnode) }, { PCI_DEVICE_DATA(INTEL, ADLN, &dwc3_pci_intel_swnode) },
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Steven Rostedt rostedt@goodmis.org
[ Upstream commit c89504a703fb779052213add0e8ed642f4a4f1c8 ]
Several places in the trace.c file there's a goto out where the out is simply a return. There's no reason to jump to the out label if it's not doing any more logic but simply returning from the function.
Replace the goto outs with a return and remove the out labels.
Cc: Masami Hiramatsu mhiramat@kernel.org Cc: Mark Rutland mark.rutland@arm.com Cc: Mathieu Desnoyers mathieu.desnoyers@efficios.com Cc: Andrew Morton akpm@linux-foundation.org Link: https://lore.kernel.org/20250801203857.538726745@kernel.org Signed-off-by: Steven Rostedt (Google) rostedt@goodmis.org Stable-dep-of: 6a909ea83f22 ("tracing: Limit access to parser->buffer when trace_get_user failed") Signed-off-by: Sasha Levin sashal@kernel.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- kernel/trace/trace.c | 38 +++++++++++++++----------------------- 1 file changed, 15 insertions(+), 23 deletions(-)
--- a/kernel/trace/trace.c +++ b/kernel/trace/trace.c @@ -1846,7 +1846,7 @@ int trace_get_user(struct trace_parser *
ret = get_user(ch, ubuf++); if (ret) - goto out; + return ret;
read++; cnt--; @@ -1860,7 +1860,7 @@ int trace_get_user(struct trace_parser * while (cnt && isspace(ch)) { ret = get_user(ch, ubuf++); if (ret) - goto out; + return ret; read++; cnt--; } @@ -1870,8 +1870,7 @@ int trace_get_user(struct trace_parser * /* only spaces were written */ if (isspace(ch) || !ch) { *ppos += read; - ret = read; - goto out; + return read; } }
@@ -1879,13 +1878,12 @@ int trace_get_user(struct trace_parser * while (cnt && !isspace(ch) && ch) { if (parser->idx < parser->size - 1) parser->buffer[parser->idx++] = ch; - else { - ret = -EINVAL; - goto out; - } + else + return -EINVAL; + ret = get_user(ch, ubuf++); if (ret) - goto out; + return ret; read++; cnt--; } @@ -1900,15 +1898,11 @@ int trace_get_user(struct trace_parser * /* Make sure the parsed string always terminates with '\0'. */ parser->buffer[parser->idx] = 0; } else { - ret = -EINVAL; - goto out; + return -EINVAL; }
*ppos += read; - ret = read; - -out: - return ret; + return read; }
/* TODO add a seq_buf_to_buffer() */ @@ -2410,10 +2404,10 @@ int __init register_tracer(struct tracer mutex_unlock(&trace_types_lock);
if (ret || !default_bootup_tracer) - goto out_unlock; + return ret;
if (strncmp(default_bootup_tracer, type->name, MAX_TRACER_SIZE)) - goto out_unlock; + return 0;
printk(KERN_INFO "Starting tracer '%s'\n", type->name); /* Do we want this tracer to start on bootup? */ @@ -2425,8 +2419,7 @@ int __init register_tracer(struct tracer /* disable other selftests, since this will break it. */ disable_tracing_selftest("running a tracer");
- out_unlock: - return ret; + return 0; }
static void tracing_reset_cpu(struct array_buffer *buf, int cpu) @@ -8954,12 +8947,12 @@ ftrace_trace_snapshot_callback(struct tr out_reg: ret = tracing_arm_snapshot(tr); if (ret < 0) - goto out; + return ret;
ret = register_ftrace_function_probe(glob, tr, ops, count); if (ret < 0) tracing_disarm_snapshot(tr); - out: + return ret < 0 ? ret : 0; }
@@ -11057,7 +11050,7 @@ __init static int tracer_alloc_buffers(v BUILD_BUG_ON(TRACE_ITER_LAST_BIT > TRACE_FLAGS_MAX_SIZE);
if (!alloc_cpumask_var(&tracing_buffer_mask, GFP_KERNEL)) - goto out; + return -ENOMEM;
if (!alloc_cpumask_var(&global_trace.tracing_cpumask, GFP_KERNEL)) goto out_free_buffer_mask; @@ -11175,7 +11168,6 @@ out_free_cpumask: free_cpumask_var(global_trace.tracing_cpumask); out_free_buffer_mask: free_cpumask_var(tracing_buffer_mask); -out: return ret; }
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Pu Lehui pulehui@huawei.com
[ Upstream commit 6a909ea83f226803ea0e718f6e88613df9234d58 ]
When the length of the string written to set_ftrace_filter exceeds FTRACE_BUFF_MAX, the following KASAN alarm will be triggered:
BUG: KASAN: slab-out-of-bounds in strsep+0x18c/0x1b0 Read of size 1 at addr ffff0000d00bd5ba by task ash/165
CPU: 1 UID: 0 PID: 165 Comm: ash Not tainted 6.16.0-g6bcdbd62bd56-dirty Hardware name: linux,dummy-virt (DT) Call trace: show_stack+0x34/0x50 (C) dump_stack_lvl+0xa0/0x158 print_address_description.constprop.0+0x88/0x398 print_report+0xb0/0x280 kasan_report+0xa4/0xf0 __asan_report_load1_noabort+0x20/0x30 strsep+0x18c/0x1b0 ftrace_process_regex.isra.0+0x100/0x2d8 ftrace_regex_release+0x484/0x618 __fput+0x364/0xa58 ____fput+0x28/0x40 task_work_run+0x154/0x278 do_notify_resume+0x1f0/0x220 el0_svc+0xec/0xf0 el0t_64_sync_handler+0xa0/0xe8 el0t_64_sync+0x1ac/0x1b0
The reason is that trace_get_user will fail when processing a string longer than FTRACE_BUFF_MAX, but not set the end of parser->buffer to 0. Then an OOB access will be triggered in ftrace_regex_release-> ftrace_process_regex->strsep->strpbrk. We can solve this problem by limiting access to parser->buffer when trace_get_user failed.
Cc: stable@vger.kernel.org Link: https://lore.kernel.org/20250813040232.1344527-1-pulehui@huaweicloud.com Fixes: 8c9af478c06b ("ftrace: Handle commands when closing set_ftrace_filter file") Signed-off-by: Pu Lehui pulehui@huawei.com Signed-off-by: Steven Rostedt (Google) rostedt@goodmis.org Signed-off-by: Sasha Levin sashal@kernel.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- kernel/trace/trace.c | 18 ++++++++++++------ kernel/trace/trace.h | 8 +++++++- 2 files changed, 19 insertions(+), 7 deletions(-)
--- a/kernel/trace/trace.c +++ b/kernel/trace/trace.c @@ -1846,7 +1846,7 @@ int trace_get_user(struct trace_parser *
ret = get_user(ch, ubuf++); if (ret) - return ret; + goto fail;
read++; cnt--; @@ -1860,7 +1860,7 @@ int trace_get_user(struct trace_parser * while (cnt && isspace(ch)) { ret = get_user(ch, ubuf++); if (ret) - return ret; + goto fail; read++; cnt--; } @@ -1878,12 +1878,14 @@ int trace_get_user(struct trace_parser * while (cnt && !isspace(ch) && ch) { if (parser->idx < parser->size - 1) parser->buffer[parser->idx++] = ch; - else - return -EINVAL; + else { + ret = -EINVAL; + goto fail; + }
ret = get_user(ch, ubuf++); if (ret) - return ret; + goto fail; read++; cnt--; } @@ -1898,11 +1900,15 @@ int trace_get_user(struct trace_parser * /* Make sure the parsed string always terminates with '\0'. */ parser->buffer[parser->idx] = 0; } else { - return -EINVAL; + ret = -EINVAL; + goto fail; }
*ppos += read; return read; +fail: + trace_parser_fail(parser); + return ret; }
/* TODO add a seq_buf_to_buffer() */ --- a/kernel/trace/trace.h +++ b/kernel/trace/trace.h @@ -1292,6 +1292,7 @@ bool ftrace_event_is_function(struct tra */ struct trace_parser { bool cont; + bool fail; char *buffer; unsigned idx; unsigned size; @@ -1299,7 +1300,7 @@ struct trace_parser {
static inline bool trace_parser_loaded(struct trace_parser *parser) { - return (parser->idx != 0); + return !parser->fail && parser->idx != 0; }
static inline bool trace_parser_cont(struct trace_parser *parser) @@ -1313,6 +1314,11 @@ static inline void trace_parser_clear(st parser->idx = 0; }
+static inline void trace_parser_fail(struct trace_parser *parser) +{ + parser->fail = true; +} + extern int trace_parser_get_init(struct trace_parser *parser, int size); extern void trace_parser_put(struct trace_parser *parser); extern int trace_get_user(struct trace_parser *parser, const char __user *ubuf,
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: NeilBrown neil@brown.name
commit 5f1c8965e748c150d580a2ea8fbee1bd80d07a24 upstream.
ovl_create_temp() treats "workdir" as a parent in which it creates an object so it should use I_MUTEX_PARENT.
Prior to the commit identified below the lock was taken by the caller which sometimes used I_MUTEX_PARENT and sometimes used I_MUTEX_NORMAL. The use of I_MUTEX_NORMAL was incorrect but unfortunately copied into ovl_create_temp().
Note to backporters: This patch only applies after the last Fixes given below (post v6.16). To fix the bug in v6.7 and later the inode_lock() call in ovl_copy_up_workdir() needs to nest using I_MUTEX_PARENT.
Link: https://lore.kernel.org/all/67a72070.050a0220.3d72c.0022.GAE@google.com/ Cc: stable@vger.kernel.org Reported-by: syzbot+7836a68852a10ec3d790@syzkaller.appspotmail.com Tested-by: syzbot+7836a68852a10ec3d790@syzkaller.appspotmail.com Fixes: c63e56a4a652 ("ovl: do not open/llseek lower file with upper sb_writers held") Fixes: d2c995581c7c ("ovl: Call ovl_create_temp() without lock held.") Signed-off-by: NeilBrown neil@brown.name Signed-off-by: Amir Goldstein amir73il@gmail.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- fs/overlayfs/copy_up.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
--- a/fs/overlayfs/copy_up.c +++ b/fs/overlayfs/copy_up.c @@ -779,7 +779,7 @@ static int ovl_copy_up_workdir(struct ov return err;
ovl_start_write(c->dentry); - inode_lock(wdir); + inode_lock_nested(wdir, I_MUTEX_PARENT); temp = ovl_create_temp(ofs, c->workdir, &cattr); inode_unlock(wdir); ovl_end_write(c->dentry);
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Niklas Cassel cassel@kernel.org
commit 80dc18a0cba8dea42614f021b20a04354b213d86 upstream.
As per PCIe r6.0, sec 6.6.1, a Downstream Port that supports Link speeds greater than 5.0 GT/s, software must wait a minimum of 100 ms after Link training completes before sending a Configuration Request.
Add this delay in dw_pcie_wait_for_link(), after the link is reported as up. The delay will only be performed in the success case where the link came up.
DWC glue drivers that have a link up IRQ (drivers that set use_linkup_irq = true) do not call dw_pcie_wait_for_link(), instead they perform this delay in their threaded link up IRQ handler.
Signed-off-by: Niklas Cassel cassel@kernel.org Signed-off-by: Manivannan Sadhasivam mani@kernel.org Reviewed-by: Damien Le Moal dlemoal@kernel.org Reviewed-by: Wilfred Mallawa wilfred.mallawa@wdc.com Link: https://patch.msgid.link/20250625102347.1205584-14-cassel@kernel.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/pci/controller/dwc/pcie-designware.c | 8 ++++++++ 1 file changed, 8 insertions(+)
--- a/drivers/pci/controller/dwc/pcie-designware.c +++ b/drivers/pci/controller/dwc/pcie-designware.c @@ -714,6 +714,14 @@ int dw_pcie_wait_for_link(struct dw_pcie return -ETIMEDOUT; }
+ /* + * As per PCIe r6.0, sec 6.6.1, a Downstream Port that supports Link + * speeds greater than 5.0 GT/s, software must wait a minimum of 100 ms + * after Link training completes before sending a Configuration Request. + */ + if (pci->max_link_speed > 2) + msleep(PCIE_RESET_CONFIG_WAIT_MS); + offset = dw_pcie_find_capability(pci, PCI_CAP_ID_EXP); val = dw_pcie_readw_dbi(pci, offset + PCI_EXP_LNKSTA);
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jakub Kicinski kuba@kernel.org
commit 62708b9452f8eb77513115b17c4f8d1a22ebf843 upstream.
Each recvmsg() call must process either - only contiguous DATA records (any number of them) - one non-DATA record
If the next record has different type than what has already been processed we break out of the main processing loop. If the record has already been decrypted (which may be the case for TLS 1.3 where we don't know type until decryption) we queue the pending record to the rx_list. Next recvmsg() will pick it up from there.
Queuing the skb to rx_list after zero-copy decrypt is not possible, since in that case we decrypted directly to the user space buffer, and we don't have an skb to queue (darg.skb points to the ciphertext skb for access to metadata like length).
Only data records are allowed zero-copy, and we break the processing loop after each non-data record. So we should never zero-copy and then find out that the record type has changed. The corner case we missed is when the initial record comes from rx_list, and it's zero length.
Reported-by: Muhammad Alifa Ramdhan ramdhan@starlabs.sg Reported-by: Billy Jheng Bing-Jhong billy@starlabs.sg Fixes: 84c61fe1a75b ("tls: rx: do not use the standard strparser") Reviewed-by: Sabrina Dubroca sd@queasysnail.net Link: https://patch.msgid.link/20250820021952.143068-1-kuba@kernel.org Signed-off-by: Jakub Kicinski kuba@kernel.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- net/tls/tls_sw.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-)
--- a/net/tls/tls_sw.c +++ b/net/tls/tls_sw.c @@ -1808,6 +1808,9 @@ int decrypt_skb(struct sock *sk, struct return tls_decrypt_sg(sk, NULL, sgout, &darg); }
+/* All records returned from a recvmsg() call must have the same type. + * 0 is not a valid content type. Use it as "no type reported, yet". + */ static int tls_record_content_type(struct msghdr *msg, struct tls_msg *tlm, u8 *control) { @@ -2051,8 +2054,10 @@ int tls_sw_recvmsg(struct sock *sk, if (err < 0) goto end;
+ /* process_rx_list() will set @control if it processed any records */ copied = err; - if (len <= copied || (copied && control != TLS_RECORD_TYPE_DATA) || rx_more) + if (len <= copied || rx_more || + (control && control != TLS_RECORD_TYPE_DATA)) goto end;
target = sock_rcvlowat(sk, flags & MSG_WAITALL, len);
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Yazen Ghannam yazen.ghannam@amd.com
commit e9576e078220c50ace9e9087355423de23e25fa5 upstream.
The reset reason value may be "all bits set", e.g. 0xFFFFFFFF. This is a commonly used error response from hardware. This may occur due to a real hardware issue or when running in a VM.
The user will see all reset reasons reported in this case.
Check for an error response value and return early to avoid decoding invalid data.
Also, adjust the data variable type to match the hardware register size.
Fixes: ab8131028710 ("x86/CPU/AMD: Print the reason for the last reset") Reported-by: Libing He libhe@redhat.com Signed-off-by: Yazen Ghannam yazen.ghannam@amd.com Signed-off-by: Borislav Petkov (AMD) bp@alien8.de Reviewed-by: Mario Limonciello mario.limonciello@amd.com Cc: stable@vger.kernel.org Link: https://lore.kernel.org/20250721181155.3536023-1-yazen.ghannam@amd.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- arch/x86/kernel/cpu/amd.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-)
--- a/arch/x86/kernel/cpu/amd.c +++ b/arch/x86/kernel/cpu/amd.c @@ -1324,8 +1324,8 @@ static const char * const s5_reset_reaso
static __init int print_s5_reset_status_mmio(void) { - unsigned long value; void __iomem *addr; + u32 value; int i;
if (!cpu_feature_enabled(X86_FEATURE_ZEN)) @@ -1338,12 +1338,16 @@ static __init int print_s5_reset_status_ value = ioread32(addr); iounmap(addr);
+ /* Value with "all bits set" is an error response and should be ignored. */ + if (value == U32_MAX) + return 0; + for (i = 0; i < ARRAY_SIZE(s5_reset_reason_txt); i++) { if (!(value & BIT(i))) continue;
if (s5_reset_reason_txt[i]) { - pr_info("x86/amd: Previous system reset reason [0x%08lx]: %s\n", + pr_info("x86/amd: Previous system reset reason [0x%08x]: %s\n", value, s5_reset_reason_txt[i]); } }
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Tianxiang Peng txpeng@tencent.com
commit d8df126349dad855cdfedd6bbf315bad2e901c2f upstream.
Since
923f3a2b48bd ("x86/resctrl: Query LLC monitoring properties once during boot")
resctrl_cpu_detect() has been moved from common CPU initialization code to the vendor-specific BSP init helper, while Hygon didn't put that call in their code.
This triggers a division by zero fault during early booting stage on our machines with X86_FEATURE_CQM* supported, where get_rdt_mon_resources() tries to calculate mon_l3_config with uninitialized boot_cpu_data.x86_cache_occ_scale.
Add the missing resctrl_cpu_detect() in the Hygon BSP init helper.
[ bp: Massage commit message. ]
Fixes: 923f3a2b48bd ("x86/resctrl: Query LLC monitoring properties once during boot") Signed-off-by: Tianxiang Peng txpeng@tencent.com Signed-off-by: Borislav Petkov (AMD) bp@alien8.de Reviewed-by: Hui Li caelli@tencent.com Cc: stable@kernel.org Link: https://lore.kernel.org/20250623093153.3016937-1-txpeng@tencent.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- arch/x86/kernel/cpu/hygon.c | 3 +++ 1 file changed, 3 insertions(+)
--- a/arch/x86/kernel/cpu/hygon.c +++ b/arch/x86/kernel/cpu/hygon.c @@ -16,6 +16,7 @@ #include <asm/spec-ctrl.h> #include <asm/delay.h> #include <asm/msr.h> +#include <asm/resctrl.h>
#include "cpu.h"
@@ -117,6 +118,8 @@ static void bsp_init_hygon(struct cpuinf x86_amd_ls_cfg_ssbd_mask = 1ULL << 10; } } + + resctrl_cpu_detect(c); }
static void early_init_hygon(struct cpuinfo_x86 *c)
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Alex Guo alexguo1023@gmail.com
commit 57f312b955938fc4663f430cb57a71f2414f601b upstream.
The data->block[0] variable comes from user. Without proper check, the variable may be very large to cause an out-of-bounds bug.
Fix this bug by checking the value of data->block[0] first.
1. commit 39244cc75482 ("i2c: ismt: Fix an out-of-bounds bug in ismt_access()") 2. commit 92fbb6d1296f ("i2c: xgene-slimpro: Fix out-of-bounds bug in xgene_slimpro_i2c_xfer()")
Fixes: c366be720235 ("i2c: Add driver for the RTL9300 I2C controller") Signed-off-by: Alex Guo alexguo1023@gmail.com Cc: stable@vger.kernel.org # v6.13+ Reviewed-by: Chris Packham chris.packham@alliedtelesis.co.nz Tested-by: Chris Packham chris.packham@alliedtelesis.co.nz Reviewed-by: Wolfram Sang wsa+renesas@sang-engineering.com Signed-off-by: Sven Eckelmann sven@narfation.org Signed-off-by: Andi Shyti andi.shyti@kernel.org Link: https://lore.kernel.org/r/20250810-i2c-rtl9300-multi-byte-v5-1-cd9dca0db722@... Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/i2c/busses/i2c-rtl9300.c | 4 ++++ 1 file changed, 4 insertions(+)
--- a/drivers/i2c/busses/i2c-rtl9300.c +++ b/drivers/i2c/busses/i2c-rtl9300.c @@ -281,6 +281,10 @@ static int rtl9300_i2c_smbus_xfer(struct ret = rtl9300_i2c_reg_addr_set(i2c, command, 1); if (ret) goto out_unlock; + if (data->block[0] < 1 || data->block[0] > I2C_SMBUS_BLOCK_MAX) { + ret = -EINVAL; + goto out_unlock; + } ret = rtl9300_i2c_config_xfer(i2c, chan, addr, data->block[0]); if (ret) goto out_unlock;
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Harshal Gohel hg@simonwunderlich.de
commit d67b740b9edfa46310355e2b68050f79ebf05a4c upstream.
The RTL93xx I2C controller has 4 32 bit registers to store the bytes for the upcoming I2C transmission. The first byte is stored in the least-significant byte of the first register. And the last byte in the most significant byte of the last register. A map of the transferred bytes to their order in the registers is:
reg 0: 0x04_03_02_01 reg 1: 0x08_07_06_05 reg 2: 0x0c_0b_0a_09 reg 3: 0x10_0f_0e_0d
The i2c_read() function basically demonstrates how the hardware would pick up bytes from this register set. But the i2c_write() function was just pushing bytes one after another to the least significant byte of a register AFTER shifting the last one to the next more significant byte position.
If you would then have tried to send a buffer with numbers 1-11 using i2c_write(), you would have ended up with following register content:
reg 0: 0x01_02_03_04 reg 1: 0x05_06_07_08 reg 2: 0x00_09_0a_0b reg 3: 0x00_00_00_00
On the wire, you would then have seen:
Sr Addr Wr [A] 04 A 03 A 02 A 01 A 08 A 07 A 06 A 05 A 0b A 0a A 09 A P
But the correct data transmission was expected to be
Sr Addr Wr [A] 01 A 02 A 03 A 04 A 05 A 06 A 07 A 08 A 09 A 0a A 0b A P
Because of this multi-byte ordering problem, only single byte i2c_write() operations were executed correctly (on the wire).
By shifting the byte directly to the correct end position in the register, it is possible to avoid this incorrect byte ordering and fix multi-byte transmissions.
The second initialization (to 0) of vals was also be dropped because this array is initialized to 0 on the stack by using `= {};`. This makes the fix a lot more readable.
Fixes: c366be720235 ("i2c: Add driver for the RTL9300 I2C controller") Signed-off-by: Harshal Gohel hg@simonwunderlich.de Cc: stable@vger.kernel.org # v6.13+ Co-developed-by: Sven Eckelmann sven@narfation.org Signed-off-by: Sven Eckelmann sven@narfation.org Reviewed-by: Chris Packham chris.packham@alliedtelesis.co.nz Tested-by: Chris Packham chris.packham@alliedtelesis.co.nz Signed-off-by: Andi Shyti andi.shyti@kernel.org Link: https://lore.kernel.org/r/20250810-i2c-rtl9300-multi-byte-v5-2-cd9dca0db722@... Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/i2c/busses/i2c-rtl9300.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-)
--- a/drivers/i2c/busses/i2c-rtl9300.c +++ b/drivers/i2c/busses/i2c-rtl9300.c @@ -143,10 +143,10 @@ static int rtl9300_i2c_write(struct rtl9 return -EIO;
for (i = 0; i < len; i++) { - if (i % 4 == 0) - vals[i/4] = 0; - vals[i/4] <<= 8; - vals[i/4] |= buf[i]; + unsigned int shift = (i % 4) * 8; + unsigned int reg = i / 4; + + vals[reg] |= buf[i] << shift; }
return regmap_bulk_write(i2c->regmap, i2c->reg_base + RTL9300_I2C_MST_DATA_WORD0,
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sven Eckelmann sven@narfation.org
commit ceee7776c010c5f09d30985c9e5223b363a6172a upstream.
The timeout for transfers was only set to 2ms. Because of this relatively low limit, 12-byte read operations to the frontend MCU of a RTL8239 POE PSE chip cluster was consistently resulting in a timeout.
The original OpenWrt downstream driver [1] was not using any timeout limit at all. This is also possible by setting the timeout_us parameter of regmap_read_poll_timeout() to 0. But since the driver currently implements the ETIMEDOUT error, it is more sensible to increase the timeout in such a way that communication with the (quite common) Realtek I2C-connected POE management solution is possible.
[1] https://git.openwrt.org/?p=openwrt/openwrt.git%3Ba=blob%3Bf=target/linux/rea...
Fixes: c366be720235 ("i2c: Add driver for the RTL9300 I2C controller") Signed-off-by: Sven Eckelmann sven@narfation.org Cc: stable@vger.kernel.org # v6.13+ Reviewed-by: Chris Packham chris.packham@alliedtelesis.co.nz Tested-by: Chris Packham chris.packham@alliedtelesis.co.nz Signed-off-by: Andi Shyti andi.shyti@kernel.org Link: https://lore.kernel.org/r/20250810-i2c-rtl9300-multi-byte-v5-3-cd9dca0db722@... Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/i2c/busses/i2c-rtl9300.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/i2c/busses/i2c-rtl9300.c b/drivers/i2c/busses/i2c-rtl9300.c index 4a538b266080..4a282d57e2c1 100644 --- a/drivers/i2c/busses/i2c-rtl9300.c +++ b/drivers/i2c/busses/i2c-rtl9300.c @@ -175,7 +175,7 @@ static int rtl9300_i2c_execute_xfer(struct rtl9300_i2c *i2c, char read_write, return ret;
ret = regmap_read_poll_timeout(i2c->regmap, i2c->reg_base + RTL9300_I2C_MST_CTRL1, - val, !(val & RTL9300_I2C_MST_CTRL1_I2C_TRIG), 100, 2000); + val, !(val & RTL9300_I2C_MST_CTRL1_I2C_TRIG), 100, 100000); if (ret) return ret;
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sven Eckelmann sven@narfation.org
commit 82b350dd8185ce790e61555c436f90b6501af23c upstream.
The expected on-wire format of an SMBus Block Write is
S Addr Wr [A] Comm [A] Count [A] Data [A] Data [A] ... [A] Data [A] P
Everything starting from the Count byte is provided by the I2C subsystem in the array data->block. But the driver was skipping the Count byte (data->block[0]) when sending it to the RTL93xx I2C controller.
Only the actual data could be seen on the wire:
S Addr Wr [A] Comm [A] Data [A] Data [A] ... [A] Data [A] P
This wire format is not SMBus Block Write compatible but matches the format of an I2C Block Write. Simply adding the count byte to the buffer for the I2C controller is enough to fix the transmission.
This also affects read because the I2C controller must receive the count byte + $count * data bytes.
Fixes: c366be720235 ("i2c: Add driver for the RTL9300 I2C controller") Signed-off-by: Sven Eckelmann sven@narfation.org Cc: stable@vger.kernel.org # v6.13+ Reviewed-by: Chris Packham chris.packham@alliedtelesis.co.nz Tested-by: Chris Packham chris.packham@alliedtelesis.co.nz Signed-off-by: Andi Shyti andi.shyti@kernel.org Link: https://lore.kernel.org/r/20250810-i2c-rtl9300-multi-byte-v5-4-cd9dca0db722@... Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/i2c/busses/i2c-rtl9300.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
--- a/drivers/i2c/busses/i2c-rtl9300.c +++ b/drivers/i2c/busses/i2c-rtl9300.c @@ -285,15 +285,15 @@ static int rtl9300_i2c_smbus_xfer(struct ret = -EINVAL; goto out_unlock; } - ret = rtl9300_i2c_config_xfer(i2c, chan, addr, data->block[0]); + ret = rtl9300_i2c_config_xfer(i2c, chan, addr, data->block[0] + 1); if (ret) goto out_unlock; if (read_write == I2C_SMBUS_WRITE) { - ret = rtl9300_i2c_write(i2c, &data->block[1], data->block[0]); + ret = rtl9300_i2c_write(i2c, &data->block[0], data->block[0] + 1); if (ret) goto out_unlock; } - len = data->block[0]; + len = data->block[0] + 1; break;
default:
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jedrzej Jagielski jedrzej.jagielski@intel.com
[ Upstream commit c5ec7f49b480db0dfc83f395755b1c2a7c979920 ]
Currently when adding devlink port, phys_port_name is automatically generated within devlink port initialization flow. As a result adding devlink port support to driver may result in forced changes of interface names, which breaks already existing network configs.
This is an expected behavior but in some scenarios it would not be preferable to provide such limitation for legacy driver not being able to keep 'pre-devlink' interface name.
Add flag no_phys_port_name to devlink_port_attrs struct which indicates if devlink should not alter name of interface.
Suggested-by: Jiri Pirko jiri@resnulli.us Link: https://lore.kernel.org/all/nbwrfnjhvrcduqzjl4a2jafnvvud6qsbxlvxaxilnryglf4j... Signed-off-by: Jedrzej Jagielski jedrzej.jagielski@intel.com Signed-off-by: Tony Nguyen anthony.l.nguyen@intel.com Cc: stable@vger.kernel.org # 6.16 Tested-By: Calvin Owens calvin@wbinvd.org Signed-off-by: Calvin Owens calvin@wbinvd.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- include/net/devlink.h | 6 +++++- net/devlink/port.c | 2 +- 2 files changed, 6 insertions(+), 2 deletions(-)
--- a/include/net/devlink.h +++ b/include/net/devlink.h @@ -78,6 +78,9 @@ struct devlink_port_pci_sf_attrs { * @flavour: flavour of the port * @split: indicates if this is split port * @splittable: indicates if the port can be split. + * @no_phys_port_name: skip automatic phys_port_name generation; for + * compatibility only, newly added driver/port instance + * should never set this. * @lanes: maximum number of lanes the port supports. 0 value is not passed to netlink. * @switch_id: if the port is part of switch, this is buffer with ID, otherwise this is NULL * @phys: physical port attributes @@ -87,7 +90,8 @@ struct devlink_port_pci_sf_attrs { */ struct devlink_port_attrs { u8 split:1, - splittable:1; + splittable:1, + no_phys_port_name:1; u32 lanes; enum devlink_port_flavour flavour; struct netdev_phys_item_id switch_id; --- a/net/devlink/port.c +++ b/net/devlink/port.c @@ -1519,7 +1519,7 @@ static int __devlink_port_phys_port_name struct devlink_port_attrs *attrs = &devlink_port->attrs; int n = 0;
- if (!devlink_port->attrs_set) + if (!devlink_port->attrs_set || devlink_port->attrs.no_phys_port_name) return -EOPNOTSUPP;
switch (attrs->flavour) {
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jedrzej Jagielski jedrzej.jagielski@intel.com
[ upstream commit e67a0bc3ed4fd8ee1697cb6d937e2b294ec13b5e ]
Users of the ixgbe driver report that after adding devlink support by the commit a0285236ab93 ("ixgbe: add initial devlink support") their configs got broken due to unwanted changes of interface names. It's caused by automatic phys_port_name generation during devlink port initialization flow.
To prevent from that set no_phys_port_name flag for ixgbe devlink ports.
Reported-by: David Howells dhowells@redhat.com Closes: https://lore.kernel.org/netdev/3452224.1745518016@warthog.procyon.org.uk/ Reported-by: David Kaplan David.Kaplan@amd.com Closes: https://lore.kernel.org/netdev/LV3PR12MB92658474624CCF60220157199470A@LV3PR1... Fixes: a0285236ab93 ("ixgbe: add initial devlink support") Signed-off-by: Jedrzej Jagielski jedrzej.jagielski@intel.com Tested-by: Rinitha S sx.rinitha@intel.com (A Contingent worker at Intel) Signed-off-by: Tony Nguyen anthony.l.nguyen@intel.com Cc: stable@vger.kernel.org # 6.16 Tested-By: Calvin Owens calvin@wbinvd.org Signed-off-by: Calvin Owens calvin@wbinvd.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/net/ethernet/intel/ixgbe/devlink/devlink.c | 1 + 1 file changed, 1 insertion(+)
--- a/drivers/net/ethernet/intel/ixgbe/devlink/devlink.c +++ b/drivers/net/ethernet/intel/ixgbe/devlink/devlink.c @@ -543,6 +543,7 @@ int ixgbe_devlink_register_port(struct i
attrs.flavour = DEVLINK_PORT_FLAVOUR_PHYSICAL; attrs.phys.port_number = adapter->hw.bus.func; + attrs.no_phys_port_name = 1; ixgbe_devlink_set_switch_id(adapter, &attrs.switch_id);
devlink_port_attrs_set(devlink_port, &attrs);
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: David Lechner dlechner@baylibre.com
[ Upstream commit 352112e2d9aab6a156c2803ae14eb89a9fd93b7d ]
Use { } instead of memset() to zero-initialize stack memory to simplify the code.
Signed-off-by: David Lechner dlechner@baylibre.com Reviewed-by: Nuno Sá nuno.sa@analog.com Reviewed-by: Andy Shevchenko andriy.shevchenko@linux.intel.com Link: https://patch.msgid.link/20250611-iio-zero-init-stack-with-instead-of-memset... Signed-off-by: Jonathan Cameron Jonathan.Cameron@huawei.com Stable-dep-of: dfdc31e7ccf3 ("iio: imu: inv_icm42600: change invalid data error to -EBUSY") Signed-off-by: Sasha Levin sashal@kernel.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/iio/imu/inv_icm42600/inv_icm42600_accel.c | 5 ++--- drivers/iio/imu/inv_icm42600/inv_icm42600_gyro.c | 5 ++--- 2 files changed, 4 insertions(+), 6 deletions(-)
--- a/drivers/iio/imu/inv_icm42600/inv_icm42600_accel.c +++ b/drivers/iio/imu/inv_icm42600/inv_icm42600_accel.c @@ -902,7 +902,8 @@ int inv_icm42600_accel_parse_fifo(struct const int8_t *temp; unsigned int odr; int64_t ts_val; - struct inv_icm42600_accel_buffer buffer; + /* buffer is copied to userspace, zeroing it to avoid any data leak */ + struct inv_icm42600_accel_buffer buffer = { };
/* parse all fifo packets */ for (i = 0, no = 0; i < st->fifo.count; i += size, ++no) { @@ -921,8 +922,6 @@ int inv_icm42600_accel_parse_fifo(struct inv_sensors_timestamp_apply_odr(ts, st->fifo.period, st->fifo.nb.total, no);
- /* buffer is copied to userspace, zeroing it to avoid any data leak */ - memset(&buffer, 0, sizeof(buffer)); memcpy(&buffer.accel, accel, sizeof(buffer.accel)); /* convert 8 bits FIFO temperature in high resolution format */ buffer.temp = temp ? (*temp * 64) : 0; --- a/drivers/iio/imu/inv_icm42600/inv_icm42600_gyro.c +++ b/drivers/iio/imu/inv_icm42600/inv_icm42600_gyro.c @@ -806,7 +806,8 @@ int inv_icm42600_gyro_parse_fifo(struct const int8_t *temp; unsigned int odr; int64_t ts_val; - struct inv_icm42600_gyro_buffer buffer; + /* buffer is copied to userspace, zeroing it to avoid any data leak */ + struct inv_icm42600_gyro_buffer buffer = { };
/* parse all fifo packets */ for (i = 0, no = 0; i < st->fifo.count; i += size, ++no) { @@ -825,8 +826,6 @@ int inv_icm42600_gyro_parse_fifo(struct inv_sensors_timestamp_apply_odr(ts, st->fifo.period, st->fifo.nb.total, no);
- /* buffer is copied to userspace, zeroing it to avoid any data leak */ - memset(&buffer, 0, sizeof(buffer)); memcpy(&buffer.gyro, gyro, sizeof(buffer.gyro)); /* convert 8 bits FIFO temperature in high resolution format */ buffer.temp = temp ? (*temp * 64) : 0;
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Andy Shevchenko andriy.shevchenko@linux.intel.com
[ Upstream commit a4135386fa49c2a170b89296da12c4a3be2089d9 ]
The driver code is full of intXX_t and uintXX_t types which is not the pattern we use in the IIO subsystem. Switch the driver to use kernel internal types for that. No functional changes.
Signed-off-by: Andy Shevchenko andriy.shevchenko@linux.intel.com Acked-by: Jean-Baptiste Maneyrol jean-baptiste.maneyrol@tdk.com Link: https://patch.msgid.link/20250616090423.575736-1-andriy.shevchenko@linux.int... Signed-off-by: Jonathan Cameron Jonathan.Cameron@huawei.com Stable-dep-of: dfdc31e7ccf3 ("iio: imu: inv_icm42600: change invalid data error to -EBUSY") Signed-off-by: Sasha Levin sashal@kernel.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/iio/imu/inv_icm42600/inv_icm42600.h | 8 ++-- drivers/iio/imu/inv_icm42600/inv_icm42600_accel.c | 26 +++++++-------- drivers/iio/imu/inv_icm42600/inv_icm42600_buffer.c | 22 ++++++------ drivers/iio/imu/inv_icm42600/inv_icm42600_buffer.h | 10 ++--- drivers/iio/imu/inv_icm42600/inv_icm42600_core.c | 6 +-- drivers/iio/imu/inv_icm42600/inv_icm42600_gyro.c | 36 ++++++++++----------- drivers/iio/imu/inv_icm42600/inv_icm42600_temp.c | 6 +-- 7 files changed, 57 insertions(+), 57 deletions(-)
--- a/drivers/iio/imu/inv_icm42600/inv_icm42600.h +++ b/drivers/iio/imu/inv_icm42600/inv_icm42600.h @@ -164,11 +164,11 @@ struct inv_icm42600_state { struct inv_icm42600_suspended suspended; struct iio_dev *indio_gyro; struct iio_dev *indio_accel; - uint8_t buffer[2] __aligned(IIO_DMA_MINALIGN); + u8 buffer[2] __aligned(IIO_DMA_MINALIGN); struct inv_icm42600_fifo fifo; struct { - int64_t gyro; - int64_t accel; + s64 gyro; + s64 accel; } timestamp; };
@@ -410,7 +410,7 @@ const struct iio_mount_matrix * inv_icm42600_get_mount_matrix(const struct iio_dev *indio_dev, const struct iio_chan_spec *chan);
-uint32_t inv_icm42600_odr_to_period(enum inv_icm42600_odr odr); +u32 inv_icm42600_odr_to_period(enum inv_icm42600_odr odr);
int inv_icm42600_set_accel_conf(struct inv_icm42600_state *st, struct inv_icm42600_sensor_conf *conf, --- a/drivers/iio/imu/inv_icm42600/inv_icm42600_accel.c +++ b/drivers/iio/imu/inv_icm42600/inv_icm42600_accel.c @@ -177,7 +177,7 @@ static const struct iio_chan_spec inv_ic */ struct inv_icm42600_accel_buffer { struct inv_icm42600_fifo_sensor_data accel; - int16_t temp; + s16 temp; aligned_s64 timestamp; };
@@ -241,7 +241,7 @@ out_unlock:
static int inv_icm42600_accel_read_sensor(struct iio_dev *indio_dev, struct iio_chan_spec const *chan, - int16_t *val) + s16 *val) { struct inv_icm42600_state *st = iio_device_get_drvdata(indio_dev); struct inv_icm42600_sensor_state *accel_st = iio_priv(indio_dev); @@ -284,7 +284,7 @@ static int inv_icm42600_accel_read_senso if (ret) goto exit;
- *val = (int16_t)be16_to_cpup(data); + *val = (s16)be16_to_cpup(data); if (*val == INV_ICM42600_DATA_INVALID) ret = -EINVAL; exit: @@ -492,11 +492,11 @@ static int inv_icm42600_accel_read_offse int *val, int *val2) { struct device *dev = regmap_get_device(st->map); - int64_t val64; - int32_t bias; + s64 val64; + s32 bias; unsigned int reg; - int16_t offset; - uint8_t data[2]; + s16 offset; + u8 data[2]; int ret;
if (chan->type != IIO_ACCEL) @@ -550,7 +550,7 @@ static int inv_icm42600_accel_read_offse * result in micro (1000000) * (offset * 5 * 9.806650 * 1000000) / 10000 */ - val64 = (int64_t)offset * 5LL * 9806650LL; + val64 = (s64)offset * 5LL * 9806650LL; /* for rounding, add + or - divisor (10000) divided by 2 */ if (val64 >= 0) val64 += 10000LL / 2LL; @@ -568,10 +568,10 @@ static int inv_icm42600_accel_write_offs int val, int val2) { struct device *dev = regmap_get_device(st->map); - int64_t val64; - int32_t min, max; + s64 val64; + s32 min, max; unsigned int reg, regval; - int16_t offset; + s16 offset; int ret;
if (chan->type != IIO_ACCEL) @@ -596,7 +596,7 @@ static int inv_icm42600_accel_write_offs inv_icm42600_accel_calibbias[1]; max = inv_icm42600_accel_calibbias[4] * 1000000L + inv_icm42600_accel_calibbias[5]; - val64 = (int64_t)val * 1000000LL + (int64_t)val2; + val64 = (s64)val * 1000000LL + (s64)val2; if (val64 < min || val64 > max) return -EINVAL;
@@ -671,7 +671,7 @@ static int inv_icm42600_accel_read_raw(s int *val, int *val2, long mask) { struct inv_icm42600_state *st = iio_device_get_drvdata(indio_dev); - int16_t data; + s16 data; int ret;
switch (chan->type) { --- a/drivers/iio/imu/inv_icm42600/inv_icm42600_buffer.c +++ b/drivers/iio/imu/inv_icm42600/inv_icm42600_buffer.c @@ -26,28 +26,28 @@ #define INV_ICM42600_FIFO_HEADER_ODR_GYRO BIT(0)
struct inv_icm42600_fifo_1sensor_packet { - uint8_t header; + u8 header; struct inv_icm42600_fifo_sensor_data data; - int8_t temp; + s8 temp; } __packed; #define INV_ICM42600_FIFO_1SENSOR_PACKET_SIZE 8
struct inv_icm42600_fifo_2sensors_packet { - uint8_t header; + u8 header; struct inv_icm42600_fifo_sensor_data accel; struct inv_icm42600_fifo_sensor_data gyro; - int8_t temp; + s8 temp; __be16 timestamp; } __packed; #define INV_ICM42600_FIFO_2SENSORS_PACKET_SIZE 16
ssize_t inv_icm42600_fifo_decode_packet(const void *packet, const void **accel, - const void **gyro, const int8_t **temp, + const void **gyro, const s8 **temp, const void **timestamp, unsigned int *odr) { const struct inv_icm42600_fifo_1sensor_packet *pack1 = packet; const struct inv_icm42600_fifo_2sensors_packet *pack2 = packet; - uint8_t header = *((const uint8_t *)packet); + u8 header = *((const u8 *)packet);
/* FIFO empty */ if (header & INV_ICM42600_FIFO_HEADER_MSG) { @@ -100,7 +100,7 @@ ssize_t inv_icm42600_fifo_decode_packet(
void inv_icm42600_buffer_update_fifo_period(struct inv_icm42600_state *st) { - uint32_t period_gyro, period_accel, period; + u32 period_gyro, period_accel, period;
if (st->fifo.en & INV_ICM42600_SENSOR_GYRO) period_gyro = inv_icm42600_odr_to_period(st->conf.gyro.odr); @@ -204,8 +204,8 @@ int inv_icm42600_buffer_update_watermark { size_t packet_size, wm_size; unsigned int wm_gyro, wm_accel, watermark; - uint32_t period_gyro, period_accel, period; - uint32_t latency_gyro, latency_accel, latency; + u32 period_gyro, period_accel, period; + u32 latency_gyro, latency_accel, latency; bool restore; __le16 raw_wm; int ret; @@ -459,7 +459,7 @@ int inv_icm42600_buffer_fifo_read(struct __be16 *raw_fifo_count; ssize_t i, size; const void *accel, *gyro, *timestamp; - const int8_t *temp; + const s8 *temp; unsigned int odr; int ret;
@@ -550,7 +550,7 @@ int inv_icm42600_buffer_hwfifo_flush(str struct inv_icm42600_sensor_state *gyro_st = iio_priv(st->indio_gyro); struct inv_icm42600_sensor_state *accel_st = iio_priv(st->indio_accel); struct inv_sensors_timestamp *ts; - int64_t gyro_ts, accel_ts; + s64 gyro_ts, accel_ts; int ret;
gyro_ts = iio_get_time_ns(st->indio_gyro); --- a/drivers/iio/imu/inv_icm42600/inv_icm42600_buffer.h +++ b/drivers/iio/imu/inv_icm42600/inv_icm42600_buffer.h @@ -28,7 +28,7 @@ struct inv_icm42600_state; struct inv_icm42600_fifo { unsigned int on; unsigned int en; - uint32_t period; + u32 period; struct { unsigned int gyro; unsigned int accel; @@ -41,7 +41,7 @@ struct inv_icm42600_fifo { size_t accel; size_t total; } nb; - uint8_t data[2080] __aligned(IIO_DMA_MINALIGN); + u8 data[2080] __aligned(IIO_DMA_MINALIGN); };
/* FIFO data packet */ @@ -52,7 +52,7 @@ struct inv_icm42600_fifo_sensor_data { } __packed; #define INV_ICM42600_FIFO_DATA_INVALID -32768
-static inline int16_t inv_icm42600_fifo_get_sensor_data(__be16 d) +static inline s16 inv_icm42600_fifo_get_sensor_data(__be16 d) { return be16_to_cpu(d); } @@ -60,7 +60,7 @@ static inline int16_t inv_icm42600_fifo_ static inline bool inv_icm42600_fifo_is_data_valid(const struct inv_icm42600_fifo_sensor_data *s) { - int16_t x, y, z; + s16 x, y, z;
x = inv_icm42600_fifo_get_sensor_data(s->x); y = inv_icm42600_fifo_get_sensor_data(s->y); @@ -75,7 +75,7 @@ inv_icm42600_fifo_is_data_valid(const st }
ssize_t inv_icm42600_fifo_decode_packet(const void *packet, const void **accel, - const void **gyro, const int8_t **temp, + const void **gyro, const s8 **temp, const void **timestamp, unsigned int *odr);
extern const struct iio_buffer_setup_ops inv_icm42600_buffer_ops; --- a/drivers/iio/imu/inv_icm42600/inv_icm42600_core.c +++ b/drivers/iio/imu/inv_icm42600/inv_icm42600_core.c @@ -103,7 +103,7 @@ const struct regmap_config inv_icm42600_ EXPORT_SYMBOL_NS_GPL(inv_icm42600_spi_regmap_config, "IIO_ICM42600");
struct inv_icm42600_hw { - uint8_t whoami; + u8 whoami; const char *name; const struct inv_icm42600_conf *conf; }; @@ -188,9 +188,9 @@ inv_icm42600_get_mount_matrix(const stru return &st->orientation; }
-uint32_t inv_icm42600_odr_to_period(enum inv_icm42600_odr odr) +u32 inv_icm42600_odr_to_period(enum inv_icm42600_odr odr) { - static uint32_t odr_periods[INV_ICM42600_ODR_NB] = { + static u32 odr_periods[INV_ICM42600_ODR_NB] = { /* reserved values */ 0, 0, 0, /* 8kHz */ --- a/drivers/iio/imu/inv_icm42600/inv_icm42600_gyro.c +++ b/drivers/iio/imu/inv_icm42600/inv_icm42600_gyro.c @@ -77,7 +77,7 @@ static const struct iio_chan_spec inv_ic */ struct inv_icm42600_gyro_buffer { struct inv_icm42600_fifo_sensor_data gyro; - int16_t temp; + s16 temp; aligned_s64 timestamp; };
@@ -139,7 +139,7 @@ out_unlock:
static int inv_icm42600_gyro_read_sensor(struct inv_icm42600_state *st, struct iio_chan_spec const *chan, - int16_t *val) + s16 *val) { struct device *dev = regmap_get_device(st->map); struct inv_icm42600_sensor_conf conf = INV_ICM42600_SENSOR_CONF_INIT; @@ -179,7 +179,7 @@ static int inv_icm42600_gyro_read_sensor if (ret) goto exit;
- *val = (int16_t)be16_to_cpup(data); + *val = (s16)be16_to_cpup(data); if (*val == INV_ICM42600_DATA_INVALID) ret = -EINVAL; exit: @@ -399,11 +399,11 @@ static int inv_icm42600_gyro_read_offset int *val, int *val2) { struct device *dev = regmap_get_device(st->map); - int64_t val64; - int32_t bias; + s64 val64; + s32 bias; unsigned int reg; - int16_t offset; - uint8_t data[2]; + s16 offset; + u8 data[2]; int ret;
if (chan->type != IIO_ANGL_VEL) @@ -457,7 +457,7 @@ static int inv_icm42600_gyro_read_offset * result in nano (1000000000) * (offset * 64 * Pi * 1000000000) / (2048 * 180) */ - val64 = (int64_t)offset * 64LL * 3141592653LL; + val64 = (s64)offset * 64LL * 3141592653LL; /* for rounding, add + or - divisor (2048 * 180) divided by 2 */ if (val64 >= 0) val64 += 2048 * 180 / 2; @@ -475,9 +475,9 @@ static int inv_icm42600_gyro_write_offse int val, int val2) { struct device *dev = regmap_get_device(st->map); - int64_t val64, min, max; + s64 val64, min, max; unsigned int reg, regval; - int16_t offset; + s16 offset; int ret;
if (chan->type != IIO_ANGL_VEL) @@ -498,11 +498,11 @@ static int inv_icm42600_gyro_write_offse }
/* inv_icm42600_gyro_calibbias: min - step - max in nano */ - min = (int64_t)inv_icm42600_gyro_calibbias[0] * 1000000000LL + - (int64_t)inv_icm42600_gyro_calibbias[1]; - max = (int64_t)inv_icm42600_gyro_calibbias[4] * 1000000000LL + - (int64_t)inv_icm42600_gyro_calibbias[5]; - val64 = (int64_t)val * 1000000000LL + (int64_t)val2; + min = (s64)inv_icm42600_gyro_calibbias[0] * 1000000000LL + + (s64)inv_icm42600_gyro_calibbias[1]; + max = (s64)inv_icm42600_gyro_calibbias[4] * 1000000000LL + + (s64)inv_icm42600_gyro_calibbias[5]; + val64 = (s64)val * 1000000000LL + (s64)val2; if (val64 < min || val64 > max) return -EINVAL;
@@ -577,7 +577,7 @@ static int inv_icm42600_gyro_read_raw(st int *val, int *val2, long mask) { struct inv_icm42600_state *st = iio_device_get_drvdata(indio_dev); - int16_t data; + s16 data; int ret;
switch (chan->type) { @@ -803,9 +803,9 @@ int inv_icm42600_gyro_parse_fifo(struct ssize_t i, size; unsigned int no; const void *accel, *gyro, *timestamp; - const int8_t *temp; + const s8 *temp; unsigned int odr; - int64_t ts_val; + s64 ts_val; /* buffer is copied to userspace, zeroing it to avoid any data leak */ struct inv_icm42600_gyro_buffer buffer = { };
--- a/drivers/iio/imu/inv_icm42600/inv_icm42600_temp.c +++ b/drivers/iio/imu/inv_icm42600/inv_icm42600_temp.c @@ -13,7 +13,7 @@ #include "inv_icm42600.h" #include "inv_icm42600_temp.h"
-static int inv_icm42600_temp_read(struct inv_icm42600_state *st, int16_t *temp) +static int inv_icm42600_temp_read(struct inv_icm42600_state *st, s16 *temp) { struct device *dev = regmap_get_device(st->map); __be16 *raw; @@ -31,7 +31,7 @@ static int inv_icm42600_temp_read(struct if (ret) goto exit;
- *temp = (int16_t)be16_to_cpup(raw); + *temp = (s16)be16_to_cpup(raw); if (*temp == INV_ICM42600_DATA_INVALID) ret = -EINVAL;
@@ -48,7 +48,7 @@ int inv_icm42600_temp_read_raw(struct ii int *val, int *val2, long mask) { struct inv_icm42600_state *st = iio_device_get_drvdata(indio_dev); - int16_t temp; + s16 temp; int ret;
if (chan->type != IIO_TEMP)
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jean-Baptiste Maneyrol jean-baptiste.maneyrol@tdk.com
[ Upstream commit dfdc31e7ccf3ac1d5ec01d5120c71e14745e3dd8 ]
Temperature sensor returns the temperature of the mechanical parts of the chip. If both accel and gyro are off, the temperature sensor is also automatically turned off and returns invalid data.
In this case, returning -EBUSY error code is better then -EINVAL and indicates userspace that it needs to retry reading temperature in another context.
Fixes: bc3eb0207fb5 ("iio: imu: inv_icm42600: add temperature sensor support") Signed-off-by: Jean-Baptiste Maneyrol jean-baptiste.maneyrol@tdk.com Cc: stable@vger.kernel.org Reviewed-by: Andy Shevchenko andy@kernel.org Reviewed-by: Sean Nyekjaer sean@geanix.com Link: https://patch.msgid.link/20250808-inv-icm42600-change-temperature-error-code... Signed-off-by: Jonathan Cameron Jonathan.Cameron@huawei.com Signed-off-by: Sasha Levin sashal@kernel.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/iio/imu/inv_icm42600/inv_icm42600_temp.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-)
--- a/drivers/iio/imu/inv_icm42600/inv_icm42600_temp.c +++ b/drivers/iio/imu/inv_icm42600/inv_icm42600_temp.c @@ -32,8 +32,12 @@ static int inv_icm42600_temp_read(struct goto exit;
*temp = (s16)be16_to_cpup(raw); + /* + * Temperature data is invalid if both accel and gyro are off. + * Return -EBUSY in this case. + */ if (*temp == INV_ICM42600_DATA_INVALID) - ret = -EINVAL; + ret = -EBUSY;
exit: mutex_unlock(&st->lock);
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Gabor Juhos j4g8y7@gmail.com
[ Upstream commit 6bc829220b33da8522572cc50fdf5067c51d3bf3 ]
The qcom_spi_program_oob() function uses only the last codeword to write the OOB data into the flash, but it sets the CW_PER_PAGE field in the CFG0 register as it would use all codewords.
It seems that this confuses the hardware somehow, and any access to the flash fails with a timeout error after the function is called. The problem can be easily reproduced with the following commands:
# dd if=/dev/zero bs=2176 count=1 > /tmp/test.bin 1+0 records in 1+0 records out # flash_erase /dev/mtd4 0 0 Erasing 128 Kibyte @ 0 -- 100 % complete # nandwrite -O /dev/mtd4 /tmp/test.bin Writing data to block 0 at offset 0x0 # nanddump -o /dev/mtd4 >/dev/null ECC failed: 0 ECC corrected: 0 Number of bad blocks: 0 Number of bbt blocks: 0 Block size 131072, page size 2048, OOB size 128 Dumping data starting at 0x00000000 and ending at 0x00020000... [ 33.197605] qcom_snand 79b0000.spi: failure to read oob libmtd: error!: MEMREADOOB64 ioctl failed for mtd4, offset 0 (eraseblock 0) error 110 (Operation timed out) [ 35.277582] qcom_snand 79b0000.spi: failure in submitting cmd descriptor libmtd: error!: cannot read 2048 bytes from mtd4 (eraseblock 0, offset 2048) error 110 (Operation timed out) nanddump: error!: mtd_read
Change the code to use the correct CW_PER_PAGE value to avoid this.
Fixes: 7304d1909080 ("spi: spi-qpic: add driver for QCOM SPI NAND flash Interface") Signed-off-by: Gabor Juhos j4g8y7@gmail.com Link: https://patch.msgid.link/20250801-qpic-snand-oob-cwpp-fix-v1-1-f5a41b86af2e@... Signed-off-by: Mark Brown broonie@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/spi/spi-qpic-snand.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/spi/spi-qpic-snand.c b/drivers/spi/spi-qpic-snand.c index 3b757e3d00c0..722ab60d616f 100644 --- a/drivers/spi/spi-qpic-snand.c +++ b/drivers/spi/spi-qpic-snand.c @@ -1185,7 +1185,7 @@ static int qcom_spi_program_oob(struct qcom_nand_controller *snandc, u32 cfg0, cfg1, ecc_bch_cfg, ecc_buf_cfg;
cfg0 = (ecc_cfg->cfg0 & ~CW_PER_PAGE_MASK) | - FIELD_PREP(CW_PER_PAGE_MASK, num_cw - 1); + FIELD_PREP(CW_PER_PAGE_MASK, 0); cfg1 = ecc_cfg->cfg1; ecc_bch_cfg = ecc_cfg->ecc_bch_cfg; ecc_buf_cfg = ecc_cfg->ecc_buf_cfg;
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Stefan Wahren wahrenst@gmx.net
[ Upstream commit af357a6a3b7d685e7aa621c6fb1d4ed6c349ec9e ]
Currently the driver is not able to handle the case that a SPI device specifies a higher spi-max-frequency than half of per-clk:
per-clk should be at least two times of transfer speed
Fix this by clamping to the max possible value and use the minimum SCK period of 2 cycles.
Fixes: 77736a98b859 ("spi: lpspi: add the error info of transfer speed setting") Signed-off-by: Stefan Wahren wahrenst@gmx.net Link: https://patch.msgid.link/20250807100742.9917-1-wahrenst@gmx.net Signed-off-by: Mark Brown broonie@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/spi/spi-fsl-lpspi.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-)
diff --git a/drivers/spi/spi-fsl-lpspi.c b/drivers/spi/spi-fsl-lpspi.c index 5e3818445234..1a22d356a73d 100644 --- a/drivers/spi/spi-fsl-lpspi.c +++ b/drivers/spi/spi-fsl-lpspi.c @@ -331,13 +331,11 @@ static int fsl_lpspi_set_bitrate(struct fsl_lpspi_data *fsl_lpspi) }
if (config.speed_hz > perclk_rate / 2) { - dev_err(fsl_lpspi->dev, - "per-clk should be at least two times of transfer speed"); - return -EINVAL; + div = 2; + } else { + div = DIV_ROUND_UP(perclk_rate, config.speed_hz); }
- div = DIV_ROUND_UP(perclk_rate, config.speed_hz); - for (prescale = 0; prescale <= prescale_max; prescale++) { scldiv = div / (1 << prescale) - 2; if (scldiv >= 0 && scldiv < 256) {
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Gabor Juhos j4g8y7@gmail.com
[ Upstream commit 13d0fe84a214658254a7412b2b46ec1507dc51f0 ]
The OOB layout used by the driver has two distinct regions which contains hardware specific ECC data, yet the qcom_spi_ooblayout_ecc() function sets the same offset and length values for both regions which is clearly wrong.
Change the code to calculate the correct values for both regions.
For reference, the following table shows the computed offset and length values for various OOB size/ECC strength configurations:
+-----------------+-----------------+ |before the change| after the change| +-------+----------+--------+--------+--------+--------+--------+ | OOB | ECC | region | region | region | region | region | | size | strength | index | offset | length | offset | length | +-------+----------+--------+--------+--------+--------+--------+ | 128 | 8 | 0 | 113 | 15 | 0 | 49 | | | | 1 | 113 | 15 | 65 | 63 | +-------+----------+--------+--------+--------+--------+--------+ | 128 | 4 | 0 | 117 | 11 | 0 | 37 | | | | 1 | 117 | 11 | 53 | 75 | +-------+----------+--------+--------+--------+--------+--------+ | 64 | 4 | 0 | 53 | 11 | 0 | 37 | | | | 1 | 53 | 11 | 53 | 11 | +-------+----------+--------+--------+--------+--------+--------+
Fixes: 7304d1909080 ("spi: spi-qpic: add driver for QCOM SPI NAND flash Interface") Signed-off-by: Gabor Juhos j4g8y7@gmail.com Reviewed-by: Konrad Dybcio konrad.dybcio@oss.qualcomm.com Link: https://patch.msgid.link/20250805-qpic-snand-oob-ecc-fix-v2-1-e6f811c70d6f@g... Signed-off-by: Mark Brown broonie@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/spi/spi-qpic-snand.c | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-)
diff --git a/drivers/spi/spi-qpic-snand.c b/drivers/spi/spi-qpic-snand.c index 722ab60d616f..e98e997680c7 100644 --- a/drivers/spi/spi-qpic-snand.c +++ b/drivers/spi/spi-qpic-snand.c @@ -216,13 +216,21 @@ static int qcom_spi_ooblayout_ecc(struct mtd_info *mtd, int section, struct qcom_nand_controller *snandc = nand_to_qcom_snand(nand); struct qpic_ecc *qecc = snandc->qspi->ecc;
- if (section > 1) - return -ERANGE; - - oobregion->length = qecc->ecc_bytes_hw + qecc->spare_bytes; - oobregion->offset = mtd->oobsize - oobregion->length; + switch (section) { + case 0: + oobregion->offset = 0; + oobregion->length = qecc->bytes * (qecc->steps - 1) + + qecc->bbm_size; + return 0; + case 1: + oobregion->offset = qecc->bytes * (qecc->steps - 1) + + qecc->bbm_size + + qecc->steps * 4; + oobregion->length = mtd->oobsize - oobregion->offset; + return 0; + }
- return 0; + return -ERANGE; }
static int qcom_spi_ooblayout_free(struct mtd_info *mtd, int section,
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Fanhua Li lifanhua5@huawei.com
[ Upstream commit bb8aeaa3191b617c6faf8ae937252e059673b7ea ]
When the nvif_vmm_type is invalid, we will return error directly without freeing the args in nvif_vmm_ctor(), which leading a memory leak. Fix it by setting the ret -EINVAL and goto done.
Reported-by: kernel test robot lkp@intel.com Closes: https://lore.kernel.org/all/202312040659.4pJpMafN-lkp@intel.com/ Fixes: 6b252cf42281 ("drm/nouveau: nvkm/vmm: implement raw ops to manage uvmm") Signed-off-by: Fanhua Li lifanhua5@huawei.com Link: https://lore.kernel.org/r/20250728115027.50878-1-lifanhua5@huawei.com Signed-off-by: Danilo Krummrich dakr@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/gpu/drm/nouveau/nvif/vmm.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/nouveau/nvif/vmm.c b/drivers/gpu/drm/nouveau/nvif/vmm.c index 99296f03371a..07c1ebc2a941 100644 --- a/drivers/gpu/drm/nouveau/nvif/vmm.c +++ b/drivers/gpu/drm/nouveau/nvif/vmm.c @@ -219,7 +219,8 @@ nvif_vmm_ctor(struct nvif_mmu *mmu, const char *name, s32 oclass, case RAW: args->type = NVIF_VMM_V0_TYPE_RAW; break; default: WARN_ON(1); - return -EINVAL; + ret = -EINVAL; + goto done; }
memcpy(args->data, argv, argc);
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Waiman Long longman@redhat.com
[ Upstream commit 65f97cc81b0adc5f49cf6cff5d874be0058e3f41 ]
The following lockdep splat was observed.
[ 812.359086] ============================================ [ 812.359089] WARNING: possible recursive locking detected [ 812.359097] -------------------------------------------- [ 812.359100] runtest.sh/30042 is trying to acquire lock: [ 812.359105] ffffffffa7f27420 (cpu_hotplug_lock){++++}-{0:0}, at: static_key_enable+0xe/0x20 [ 812.359131] [ 812.359131] but task is already holding lock: [ 812.359134] ffffffffa7f27420 (cpu_hotplug_lock){++++}-{0:0}, at: cpuset_write_resmask+0x98/0xa70 : [ 812.359267] Call Trace: [ 812.359272] <TASK> [ 812.359367] cpus_read_lock+0x3c/0xe0 [ 812.359382] static_key_enable+0xe/0x20 [ 812.359389] check_insane_mems_config.part.0+0x11/0x30 [ 812.359398] cpuset_write_resmask+0x9f2/0xa70 [ 812.359411] cgroup_file_write+0x1c7/0x660 [ 812.359467] kernfs_fop_write_iter+0x358/0x530 [ 812.359479] vfs_write+0xabe/0x1250 [ 812.359529] ksys_write+0xf9/0x1d0 [ 812.359558] do_syscall_64+0x5f/0xe0
Since commit d74b27d63a8b ("cgroup/cpuset: Change cpuset_rwsem and hotplug lock order"), the ordering of cpu hotplug lock and cpuset_mutex had been reversed. That patch correctly used the cpuslocked version of the static branch API to enable cpusets_pre_enable_key and cpusets_enabled_key, but it didn't do the same for cpusets_insane_config_key.
The cpusets_insane_config_key can be enabled in the check_insane_mems_config() which is called from update_nodemask() or cpuset_hotplug_update_tasks() with both cpu hotplug lock and cpuset_mutex held. Deadlock can happen with a pending hotplug event that tries to acquire the cpu hotplug write lock which will block further cpus_read_lock() attempt from check_insane_mems_config(). Fix that by switching to use static_branch_enable_cpuslocked().
Fixes: d74b27d63a8b ("cgroup/cpuset: Change cpuset_rwsem and hotplug lock order") Signed-off-by: Waiman Long longman@redhat.com Reviewed-by: Juri Lelli juri.lelli@redhat.com Signed-off-by: Tejun Heo tj@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- kernel/cgroup/cpuset.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/kernel/cgroup/cpuset.c b/kernel/cgroup/cpuset.c index 3bc4301466f3..77396bab071a 100644 --- a/kernel/cgroup/cpuset.c +++ b/kernel/cgroup/cpuset.c @@ -280,7 +280,7 @@ static inline void check_insane_mems_config(nodemask_t *nodes) { if (!cpusets_insane_config() && movable_only_nodes(nodes)) { - static_branch_enable(&cpusets_insane_config_key); + static_branch_enable_cpuslocked(&cpusets_insane_config_key); pr_info("Unsupported (movable nodes only) cpuset configuration detected (nmask=%*pbl)!\n" "Cpuset allocations might fail even with a lot of memory available.\n", nodemask_pr_args(nodes));
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Waiman Long longman@redhat.com
[ Upstream commit 150e298ae0ccbecff2357a72fbabd80f8849ea6e ]
It was found during testing that an invalid leaf partition with an empty effective exclusive CPU list can become a valid empty partition with no CPU afer an offline/online operation of an unrelated CPU. An empty partition root is allowed in the special case that it has no task in its cgroup and has distributed out all its CPUs to its child partitions. That is certainly not the case here.
The problem is in the cpumask_subsets() test in the hotplug case (update with no new mask) of update_parent_effective_cpumask() as it also returns true if the effective exclusive CPU list is empty. Fix that by addding the cpumask_empty() test to root out this exception case. Also add the cpumask_empty() test in cpuset_hotplug_update_tasks() to avoid calling update_parent_effective_cpumask() for this special case.
Fixes: 0c7f293efc87 ("cgroup/cpuset: Add cpuset.cpus.exclusive.effective for v2") Signed-off-by: Waiman Long longman@redhat.com Signed-off-by: Tejun Heo tj@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- kernel/cgroup/cpuset.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-)
diff --git a/kernel/cgroup/cpuset.c b/kernel/cgroup/cpuset.c index 77396bab071a..f9d7799c5c94 100644 --- a/kernel/cgroup/cpuset.c +++ b/kernel/cgroup/cpuset.c @@ -1843,7 +1843,7 @@ static int update_parent_effective_cpumask(struct cpuset *cs, int cmd, if (is_partition_valid(cs)) adding = cpumask_and(tmp->addmask, xcpus, parent->effective_xcpus); - } else if (is_partition_invalid(cs) && + } else if (is_partition_invalid(cs) && !cpumask_empty(xcpus) && cpumask_subset(xcpus, parent->effective_xcpus)) { struct cgroup_subsys_state *css; struct cpuset *child; @@ -3870,9 +3870,10 @@ static void cpuset_hotplug_update_tasks(struct cpuset *cs, struct tmpmasks *tmp) partcmd = partcmd_invalidate; /* * On the other hand, an invalid partition root may be transitioned - * back to a regular one. + * back to a regular one with a non-empty effective xcpus. */ - else if (is_partition_valid(parent) && is_partition_invalid(cs)) + else if (is_partition_valid(parent) && is_partition_invalid(cs) && + !cpumask_empty(cs->effective_xcpus)) partcmd = partcmd_update;
if (partcmd >= 0) {
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: José Expósito jose.exposito89@gmail.com
[ Upstream commit d28b9d2925b4f773adb21b1fc20260ddc370fb13 ]
When compiling with sparse enabled, this warning is thrown:
warning: incorrect type in argument 2 (different base types) expected restricted __le32 const [usertype] *buf got unsigned int [usertype] *[assigned] buf
Add a cast to fix it.
Fixes: 453114319699 ("drm/format-helper: Add KUnit tests for drm_fb_xrgb8888_to_xrgb2101010()") Signed-off-by: José Expósito jose.exposito89@gmail.com Reviewed-by: Thomas Zimmermann tzimmermann@suse.de Signed-off-by: Thomas Zimmermann tzimmermann@suse.de Link: https://lore.kernel.org/r/20250630090054.353246-1-jose.exposito89@gmail.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/gpu/drm/tests/drm_format_helper_test.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/tests/drm_format_helper_test.c b/drivers/gpu/drm/tests/drm_format_helper_test.c index 35cd3405d045..2a3d80b27cae 100644 --- a/drivers/gpu/drm/tests/drm_format_helper_test.c +++ b/drivers/gpu/drm/tests/drm_format_helper_test.c @@ -1071,7 +1071,7 @@ static void drm_test_fb_xrgb8888_to_xrgb2101010(struct kunit *test) NULL : &result->dst_pitch;
drm_fb_xrgb8888_to_xrgb2101010(&dst, dst_pitch, &src, &fb, ¶ms->clip, &fmtcnv_state); - buf = le32buf_to_cpu(test, buf, dst_size / sizeof(u32)); + buf = le32buf_to_cpu(test, (__force const __le32 *)buf, dst_size / sizeof(u32)); KUNIT_EXPECT_MEMEQ(test, buf, result->expected, dst_size);
buf = dst.vaddr; /* restore original value of buf */
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Thomas Zimmermann tzimmermann@suse.de
[ Upstream commit 5a4856e0e38109ba994f369962f054ecb445c098 ]
Export additional helpers from the format-helper library and open-code drm_fb_blit() in tests. Prepares for the removal of drm_fb_blit(). Only sysfb drivers use drm_fb_blit(). The function will soon be removed from format helpers and be refactored within sysfb helpers.
Signed-off-by: Thomas Zimmermann tzimmermann@suse.de Reviewed-by: José Expósito jose.exposito89@gmail.com Acked-by: Maxime Ripard mripard@kernel.org Link: https://lore.kernel.org/r/20250616083846.221396-2-tzimmermann@suse.de Stable-dep-of: 05663d88fd0b ("drm/tests: Fix drm_test_fb_xrgb8888_to_xrgb2101010() on big-endian") Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/gpu/drm/drm_format_helper.c | 108 ++++++++++++++++-- drivers/gpu/drm/drm_format_internal.h | 8 ++ .../gpu/drm/tests/drm_format_helper_test.c | 108 +++--------------- include/drm/drm_format_helper.h | 9 ++ 4 files changed, 131 insertions(+), 102 deletions(-)
diff --git a/drivers/gpu/drm/drm_format_helper.c b/drivers/gpu/drm/drm_format_helper.c index d36e6cacc575..73b5a80771cc 100644 --- a/drivers/gpu/drm/drm_format_helper.c +++ b/drivers/gpu/drm/drm_format_helper.c @@ -857,11 +857,33 @@ static void drm_fb_xrgb8888_to_abgr8888_line(void *dbuf, const void *sbuf, unsig drm_fb_xfrm_line_32to32(dbuf, sbuf, pixels, drm_pixel_xrgb8888_to_abgr8888); }
-static void drm_fb_xrgb8888_to_abgr8888(struct iosys_map *dst, const unsigned int *dst_pitch, - const struct iosys_map *src, - const struct drm_framebuffer *fb, - const struct drm_rect *clip, - struct drm_format_conv_state *state) +/** + * drm_fb_xrgb8888_to_abgr8888 - Convert XRGB8888 to ABGR8888 clip buffer + * @dst: Array of ABGR8888 destination buffers + * @dst_pitch: Array of numbers of bytes between the start of two consecutive scanlines + * within @dst; can be NULL if scanlines are stored next to each other. + * @src: Array of XRGB8888 source buffer + * @fb: DRM framebuffer + * @clip: Clip rectangle area to copy + * @state: Transform and conversion state + * + * This function copies parts of a framebuffer to display memory and converts the + * color format during the process. The parameters @dst, @dst_pitch and @src refer + * to arrays. Each array must have at least as many entries as there are planes in + * @fb's format. Each entry stores the value for the format's respective color plane + * at the same index. + * + * This function does not apply clipping on @dst (i.e. the destination is at the + * top-left corner). + * + * Drivers can use this function for ABGR8888 devices that don't support XRGB8888 + * natively. It sets an opaque alpha channel as part of the conversion. + */ +void drm_fb_xrgb8888_to_abgr8888(struct iosys_map *dst, const unsigned int *dst_pitch, + const struct iosys_map *src, + const struct drm_framebuffer *fb, + const struct drm_rect *clip, + struct drm_format_conv_state *state) { static const u8 dst_pixsize[DRM_FORMAT_MAX_PLANES] = { 4, @@ -870,17 +892,40 @@ static void drm_fb_xrgb8888_to_abgr8888(struct iosys_map *dst, const unsigned in drm_fb_xfrm(dst, dst_pitch, dst_pixsize, src, fb, clip, false, state, drm_fb_xrgb8888_to_abgr8888_line); } +EXPORT_SYMBOL(drm_fb_xrgb8888_to_abgr8888);
static void drm_fb_xrgb8888_to_xbgr8888_line(void *dbuf, const void *sbuf, unsigned int pixels) { drm_fb_xfrm_line_32to32(dbuf, sbuf, pixels, drm_pixel_xrgb8888_to_xbgr8888); }
-static void drm_fb_xrgb8888_to_xbgr8888(struct iosys_map *dst, const unsigned int *dst_pitch, - const struct iosys_map *src, - const struct drm_framebuffer *fb, - const struct drm_rect *clip, - struct drm_format_conv_state *state) +/** + * drm_fb_xrgb8888_to_xbgr8888 - Convert XRGB8888 to XBGR8888 clip buffer + * @dst: Array of XBGR8888 destination buffers + * @dst_pitch: Array of numbers of bytes between the start of two consecutive scanlines + * within @dst; can be NULL if scanlines are stored next to each other. + * @src: Array of XRGB8888 source buffer + * @fb: DRM framebuffer + * @clip: Clip rectangle area to copy + * @state: Transform and conversion state + * + * This function copies parts of a framebuffer to display memory and converts the + * color format during the process. The parameters @dst, @dst_pitch and @src refer + * to arrays. Each array must have at least as many entries as there are planes in + * @fb's format. Each entry stores the value for the format's respective color plane + * at the same index. + * + * This function does not apply clipping on @dst (i.e. the destination is at the + * top-left corner). + * + * Drivers can use this function for XBGR8888 devices that don't support XRGB8888 + * natively. + */ +void drm_fb_xrgb8888_to_xbgr8888(struct iosys_map *dst, const unsigned int *dst_pitch, + const struct iosys_map *src, + const struct drm_framebuffer *fb, + const struct drm_rect *clip, + struct drm_format_conv_state *state) { static const u8 dst_pixsize[DRM_FORMAT_MAX_PLANES] = { 4, @@ -889,6 +934,49 @@ static void drm_fb_xrgb8888_to_xbgr8888(struct iosys_map *dst, const unsigned in drm_fb_xfrm(dst, dst_pitch, dst_pixsize, src, fb, clip, false, state, drm_fb_xrgb8888_to_xbgr8888_line); } +EXPORT_SYMBOL(drm_fb_xrgb8888_to_xbgr8888); + +static void drm_fb_xrgb8888_to_bgrx8888_line(void *dbuf, const void *sbuf, unsigned int pixels) +{ + drm_fb_xfrm_line_32to32(dbuf, sbuf, pixels, drm_pixel_xrgb8888_to_bgrx8888); +} + +/** + * drm_fb_xrgb8888_to_bgrx8888 - Convert XRGB8888 to BGRX8888 clip buffer + * @dst: Array of BGRX8888 destination buffers + * @dst_pitch: Array of numbers of bytes between the start of two consecutive scanlines + * within @dst; can be NULL if scanlines are stored next to each other. + * @src: Array of XRGB8888 source buffer + * @fb: DRM framebuffer + * @clip: Clip rectangle area to copy + * @state: Transform and conversion state + * + * This function copies parts of a framebuffer to display memory and converts the + * color format during the process. The parameters @dst, @dst_pitch and @src refer + * to arrays. Each array must have at least as many entries as there are planes in + * @fb's format. Each entry stores the value for the format's respective color plane + * at the same index. + * + * This function does not apply clipping on @dst (i.e. the destination is at the + * top-left corner). + * + * Drivers can use this function for BGRX8888 devices that don't support XRGB8888 + * natively. + */ +void drm_fb_xrgb8888_to_bgrx8888(struct iosys_map *dst, const unsigned int *dst_pitch, + const struct iosys_map *src, + const struct drm_framebuffer *fb, + const struct drm_rect *clip, + struct drm_format_conv_state *state) +{ + static const u8 dst_pixsize[DRM_FORMAT_MAX_PLANES] = { + 4, + }; + + drm_fb_xfrm(dst, dst_pitch, dst_pixsize, src, fb, clip, false, state, + drm_fb_xrgb8888_to_bgrx8888_line); +} +EXPORT_SYMBOL(drm_fb_xrgb8888_to_bgrx8888);
static void drm_fb_xrgb8888_to_xrgb2101010_line(void *dbuf, const void *sbuf, unsigned int pixels) { diff --git a/drivers/gpu/drm/drm_format_internal.h b/drivers/gpu/drm/drm_format_internal.h index 9f857bfa368d..0aa458b8a3e0 100644 --- a/drivers/gpu/drm/drm_format_internal.h +++ b/drivers/gpu/drm/drm_format_internal.h @@ -111,6 +111,14 @@ static inline u32 drm_pixel_xrgb8888_to_xbgr8888(u32 pix) ((pix & 0x000000ff) << 16); }
+static inline u32 drm_pixel_xrgb8888_to_bgrx8888(u32 pix) +{ + return ((pix & 0xff000000) >> 24) | /* also copy filler bits */ + ((pix & 0x00ff0000) >> 8) | + ((pix & 0x0000ff00) << 8) | + ((pix & 0x000000ff) << 24); +} + static inline u32 drm_pixel_xrgb8888_to_abgr8888(u32 pix) { return GENMASK(31, 24) | /* fill alpha bits */ diff --git a/drivers/gpu/drm/tests/drm_format_helper_test.c b/drivers/gpu/drm/tests/drm_format_helper_test.c index 2a3d80b27cae..8b62adbd4dfa 100644 --- a/drivers/gpu/drm/tests/drm_format_helper_test.c +++ b/drivers/gpu/drm/tests/drm_format_helper_test.c @@ -748,14 +748,9 @@ static void drm_test_fb_xrgb8888_to_rgb565(struct kunit *test) buf = dst.vaddr; memset(buf, 0, dst_size);
- int blit_result = 0; - - blit_result = drm_fb_blit(&dst, dst_pitch, DRM_FORMAT_RGB565, &src, &fb, ¶ms->clip, - &fmtcnv_state); - + drm_fb_xrgb8888_to_rgb565(&dst, dst_pitch, &src, &fb, ¶ms->clip, + &fmtcnv_state, false); buf = le16buf_to_cpu(test, (__force const __le16 *)buf, dst_size / sizeof(__le16)); - - KUNIT_EXPECT_FALSE(test, blit_result); KUNIT_EXPECT_MEMEQ(test, buf, result->expected, dst_size); }
@@ -795,14 +790,8 @@ static void drm_test_fb_xrgb8888_to_xrgb1555(struct kunit *test) buf = dst.vaddr; /* restore original value of buf */ memset(buf, 0, dst_size);
- int blit_result = 0; - - blit_result = drm_fb_blit(&dst, dst_pitch, DRM_FORMAT_XRGB1555, &src, &fb, ¶ms->clip, - &fmtcnv_state); - + drm_fb_xrgb8888_to_xrgb1555(&dst, dst_pitch, &src, &fb, ¶ms->clip, &fmtcnv_state); buf = le16buf_to_cpu(test, (__force const __le16 *)buf, dst_size / sizeof(__le16)); - - KUNIT_EXPECT_FALSE(test, blit_result); KUNIT_EXPECT_MEMEQ(test, buf, result->expected, dst_size); }
@@ -842,14 +831,8 @@ static void drm_test_fb_xrgb8888_to_argb1555(struct kunit *test) buf = dst.vaddr; /* restore original value of buf */ memset(buf, 0, dst_size);
- int blit_result = 0; - - blit_result = drm_fb_blit(&dst, dst_pitch, DRM_FORMAT_ARGB1555, &src, &fb, ¶ms->clip, - &fmtcnv_state); - + drm_fb_xrgb8888_to_argb1555(&dst, dst_pitch, &src, &fb, ¶ms->clip, &fmtcnv_state); buf = le16buf_to_cpu(test, (__force const __le16 *)buf, dst_size / sizeof(__le16)); - - KUNIT_EXPECT_FALSE(test, blit_result); KUNIT_EXPECT_MEMEQ(test, buf, result->expected, dst_size); }
@@ -889,14 +872,8 @@ static void drm_test_fb_xrgb8888_to_rgba5551(struct kunit *test) buf = dst.vaddr; /* restore original value of buf */ memset(buf, 0, dst_size);
- int blit_result = 0; - - blit_result = drm_fb_blit(&dst, dst_pitch, DRM_FORMAT_RGBA5551, &src, &fb, ¶ms->clip, - &fmtcnv_state); - + drm_fb_xrgb8888_to_rgba5551(&dst, dst_pitch, &src, &fb, ¶ms->clip, &fmtcnv_state); buf = le16buf_to_cpu(test, (__force const __le16 *)buf, dst_size / sizeof(__le16)); - - KUNIT_EXPECT_FALSE(test, blit_result); KUNIT_EXPECT_MEMEQ(test, buf, result->expected, dst_size); }
@@ -939,12 +916,7 @@ static void drm_test_fb_xrgb8888_to_rgb888(struct kunit *test) buf = dst.vaddr; /* restore original value of buf */ memset(buf, 0, dst_size);
- int blit_result = 0; - - blit_result = drm_fb_blit(&dst, dst_pitch, DRM_FORMAT_RGB888, &src, &fb, ¶ms->clip, - &fmtcnv_state); - - KUNIT_EXPECT_FALSE(test, blit_result); + drm_fb_xrgb8888_to_rgb888(&dst, dst_pitch, &src, &fb, ¶ms->clip, &fmtcnv_state); KUNIT_EXPECT_MEMEQ(test, buf, result->expected, dst_size); }
@@ -985,12 +957,8 @@ static void drm_test_fb_xrgb8888_to_bgr888(struct kunit *test) buf = dst.vaddr; /* restore original value of buf */ memset(buf, 0, dst_size);
- int blit_result = 0; - - blit_result = drm_fb_blit(&dst, &result->dst_pitch, DRM_FORMAT_BGR888, &src, &fb, ¶ms->clip, + drm_fb_xrgb8888_to_bgr888(&dst, &result->dst_pitch, &src, &fb, ¶ms->clip, &fmtcnv_state); - - KUNIT_EXPECT_FALSE(test, blit_result); KUNIT_EXPECT_MEMEQ(test, buf, result->expected, dst_size); }
@@ -1030,14 +998,8 @@ static void drm_test_fb_xrgb8888_to_argb8888(struct kunit *test) buf = dst.vaddr; /* restore original value of buf */ memset(buf, 0, dst_size);
- int blit_result = 0; - - blit_result = drm_fb_blit(&dst, dst_pitch, DRM_FORMAT_ARGB8888, &src, &fb, ¶ms->clip, - &fmtcnv_state); - + drm_fb_xrgb8888_to_argb8888(&dst, dst_pitch, &src, &fb, ¶ms->clip, &fmtcnv_state); buf = le32buf_to_cpu(test, (__force const __le32 *)buf, dst_size / sizeof(u32)); - - KUNIT_EXPECT_FALSE(test, blit_result); KUNIT_EXPECT_MEMEQ(test, buf, result->expected, dst_size); }
@@ -1077,12 +1039,7 @@ static void drm_test_fb_xrgb8888_to_xrgb2101010(struct kunit *test) buf = dst.vaddr; /* restore original value of buf */ memset(buf, 0, dst_size);
- int blit_result = 0; - - blit_result = drm_fb_blit(&dst, dst_pitch, DRM_FORMAT_XRGB2101010, &src, &fb, - ¶ms->clip, &fmtcnv_state); - - KUNIT_EXPECT_FALSE(test, blit_result); + drm_fb_xrgb8888_to_xrgb2101010(&dst, dst_pitch, &src, &fb, ¶ms->clip, &fmtcnv_state); KUNIT_EXPECT_MEMEQ(test, buf, result->expected, dst_size); }
@@ -1122,14 +1079,8 @@ static void drm_test_fb_xrgb8888_to_argb2101010(struct kunit *test) buf = dst.vaddr; /* restore original value of buf */ memset(buf, 0, dst_size);
- int blit_result = 0; - - blit_result = drm_fb_blit(&dst, dst_pitch, DRM_FORMAT_ARGB2101010, &src, &fb, - ¶ms->clip, &fmtcnv_state); - + drm_fb_xrgb8888_to_argb2101010(&dst, dst_pitch, &src, &fb, ¶ms->clip, &fmtcnv_state); buf = le32buf_to_cpu(test, (__force const __le32 *)buf, dst_size / sizeof(u32)); - - KUNIT_EXPECT_FALSE(test, blit_result); KUNIT_EXPECT_MEMEQ(test, buf, result->expected, dst_size); }
@@ -1202,23 +1153,15 @@ static void drm_test_fb_swab(struct kunit *test) buf = dst.vaddr; /* restore original value of buf */ memset(buf, 0, dst_size);
- int blit_result; - - blit_result = drm_fb_blit(&dst, dst_pitch, DRM_FORMAT_XRGB8888 | DRM_FORMAT_BIG_ENDIAN, - &src, &fb, ¶ms->clip, &fmtcnv_state); + drm_fb_swab(&dst, dst_pitch, &src, &fb, ¶ms->clip, false, &fmtcnv_state); buf = le32buf_to_cpu(test, (__force const __le32 *)buf, dst_size / sizeof(u32)); - - KUNIT_EXPECT_FALSE(test, blit_result); KUNIT_EXPECT_MEMEQ(test, buf, result->expected, dst_size);
buf = dst.vaddr; memset(buf, 0, dst_size);
- blit_result = drm_fb_blit(&dst, dst_pitch, DRM_FORMAT_BGRX8888, &src, &fb, ¶ms->clip, - &fmtcnv_state); + drm_fb_xrgb8888_to_bgrx8888(&dst, dst_pitch, &src, &fb, ¶ms->clip, &fmtcnv_state); buf = le32buf_to_cpu(test, (__force const __le32 *)buf, dst_size / sizeof(u32)); - - KUNIT_EXPECT_FALSE(test, blit_result); KUNIT_EXPECT_MEMEQ(test, buf, result->expected, dst_size);
buf = dst.vaddr; @@ -1229,11 +1172,8 @@ static void drm_test_fb_swab(struct kunit *test) mock_format.format |= DRM_FORMAT_BIG_ENDIAN; fb.format = &mock_format;
- blit_result = drm_fb_blit(&dst, dst_pitch, DRM_FORMAT_XRGB8888, &src, &fb, ¶ms->clip, - &fmtcnv_state); + drm_fb_swab(&dst, dst_pitch, &src, &fb, ¶ms->clip, false, &fmtcnv_state); buf = le32buf_to_cpu(test, (__force const __le32 *)buf, dst_size / sizeof(u32)); - - KUNIT_EXPECT_FALSE(test, blit_result); KUNIT_EXPECT_MEMEQ(test, buf, result->expected, dst_size); }
@@ -1266,14 +1206,8 @@ static void drm_test_fb_xrgb8888_to_abgr8888(struct kunit *test) const unsigned int *dst_pitch = (result->dst_pitch == TEST_USE_DEFAULT_PITCH) ? NULL : &result->dst_pitch;
- int blit_result = 0; - - blit_result = drm_fb_blit(&dst, dst_pitch, DRM_FORMAT_ABGR8888, &src, &fb, ¶ms->clip, - &fmtcnv_state); - + drm_fb_xrgb8888_to_abgr8888(&dst, dst_pitch, &src, &fb, ¶ms->clip, &fmtcnv_state); buf = le32buf_to_cpu(test, (__force const __le32 *)buf, dst_size / sizeof(u32)); - - KUNIT_EXPECT_FALSE(test, blit_result); KUNIT_EXPECT_MEMEQ(test, buf, result->expected, dst_size); }
@@ -1306,14 +1240,8 @@ static void drm_test_fb_xrgb8888_to_xbgr8888(struct kunit *test) const unsigned int *dst_pitch = (result->dst_pitch == TEST_USE_DEFAULT_PITCH) ? NULL : &result->dst_pitch;
- int blit_result = 0; - - blit_result = drm_fb_blit(&dst, dst_pitch, DRM_FORMAT_XBGR8888, &src, &fb, ¶ms->clip, - &fmtcnv_state); - + drm_fb_xrgb8888_to_xbgr8888(&dst, dst_pitch, &src, &fb, ¶ms->clip, &fmtcnv_state); buf = le32buf_to_cpu(test, (__force const __le32 *)buf, dst_size / sizeof(u32)); - - KUNIT_EXPECT_FALSE(test, blit_result); KUNIT_EXPECT_MEMEQ(test, buf, result->expected, dst_size); }
@@ -1910,12 +1838,8 @@ static void drm_test_fb_memcpy(struct kunit *test) memset(buf[i], 0, dst_size[i]); }
- int blit_result; - - blit_result = drm_fb_blit(dst, dst_pitches, params->format, src, &fb, ¶ms->clip, - &fmtcnv_state); + drm_fb_memcpy(dst, dst_pitches, src, &fb, ¶ms->clip);
- KUNIT_EXPECT_FALSE(test, blit_result); for (size_t i = 0; i < fb.format->num_planes; i++) { expected[i] = cpubuf_to_le32(test, params->expected[i], TEST_BUF_SIZE); KUNIT_EXPECT_MEMEQ_MSG(test, buf[i], expected[i], dst_size[i], diff --git a/include/drm/drm_format_helper.h b/include/drm/drm_format_helper.h index d8539174ca11..49a2e09155d1 100644 --- a/include/drm/drm_format_helper.h +++ b/include/drm/drm_format_helper.h @@ -102,6 +102,15 @@ void drm_fb_xrgb8888_to_bgr888(struct iosys_map *dst, const unsigned int *dst_pi void drm_fb_xrgb8888_to_argb8888(struct iosys_map *dst, const unsigned int *dst_pitch, const struct iosys_map *src, const struct drm_framebuffer *fb, const struct drm_rect *clip, struct drm_format_conv_state *state); +void drm_fb_xrgb8888_to_abgr8888(struct iosys_map *dst, const unsigned int *dst_pitch, + const struct iosys_map *src, const struct drm_framebuffer *fb, + const struct drm_rect *clip, struct drm_format_conv_state *state); +void drm_fb_xrgb8888_to_xbgr8888(struct iosys_map *dst, const unsigned int *dst_pitch, + const struct iosys_map *src, const struct drm_framebuffer *fb, + const struct drm_rect *clip, struct drm_format_conv_state *state); +void drm_fb_xrgb8888_to_bgrx8888(struct iosys_map *dst, const unsigned int *dst_pitch, + const struct iosys_map *src, const struct drm_framebuffer *fb, + const struct drm_rect *clip, struct drm_format_conv_state *state); void drm_fb_xrgb8888_to_xrgb2101010(struct iosys_map *dst, const unsigned int *dst_pitch, const struct iosys_map *src, const struct drm_framebuffer *fb, const struct drm_rect *clip,
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: José Expósito jose.exposito89@gmail.com
[ Upstream commit 05663d88fd0b8ee1c54ab2d5fb36f9b6a3ed37f7 ]
Fix failures on big-endian architectures on tests cases single_pixel_source_buffer, single_pixel_clip_rectangle, well_known_colors and destination_pitch.
Fixes: 15bda1f8de5d ("drm/tests: Add calls to drm_fb_blit() on supported format conversion tests") Signed-off-by: José Expósito jose.exposito89@gmail.com Reviewed-by: Thomas Zimmermann tzimmermann@suse.de Signed-off-by: Thomas Zimmermann tzimmermann@suse.de Link: https://lore.kernel.org/r/20250630090054.353246-2-jose.exposito89@gmail.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/gpu/drm/tests/drm_format_helper_test.c | 1 + 1 file changed, 1 insertion(+)
diff --git a/drivers/gpu/drm/tests/drm_format_helper_test.c b/drivers/gpu/drm/tests/drm_format_helper_test.c index 8b62adbd4dfa..e17643c408bf 100644 --- a/drivers/gpu/drm/tests/drm_format_helper_test.c +++ b/drivers/gpu/drm/tests/drm_format_helper_test.c @@ -1040,6 +1040,7 @@ static void drm_test_fb_xrgb8888_to_xrgb2101010(struct kunit *test) memset(buf, 0, dst_size);
drm_fb_xrgb8888_to_xrgb2101010(&dst, dst_pitch, &src, &fb, ¶ms->clip, &fmtcnv_state); + buf = le32buf_to_cpu(test, (__force const __le32 *)buf, dst_size / sizeof(u32)); KUNIT_EXPECT_MEMEQ(test, buf, result->expected, dst_size); }
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Nitin Gote nitin.r.gote@intel.com
[ Upstream commit 5634c8cb298a7146b4e38873473e280b50e27a2c ]
The current iosys_map_clear() implementation reads the potentially uninitialized 'is_iomem' boolean field to decide which union member to clear. This causes undefined behavior when called on uninitialized structures, as 'is_iomem' may contain garbage values like 0xFF.
UBSAN detects this as: UBSAN: invalid-load in include/linux/iosys-map.h:267 load of value 255 is not a valid value for type '_Bool'
Fix by unconditionally clearing the entire structure with memset(), eliminating the need to read uninitialized data and ensuring all fields are set to known good values.
Closes: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/14639 Fixes: 01fd30da0474 ("dma-buf: Add struct dma-buf-map for storing struct dma_buf.vaddr_ptr") Signed-off-by: Nitin Gote nitin.r.gote@intel.com Reviewed-by: Andi Shyti andi.shyti@linux.intel.com Reviewed-by: Thomas Zimmermann tzimmermann@suse.de Signed-off-by: Thomas Zimmermann tzimmermann@suse.de Link: https://lore.kernel.org/r/20250718105051.2709487-1-nitin.r.gote@intel.com Signed-off-by: Sasha Levin sashal@kernel.org --- include/linux/iosys-map.h | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-)
diff --git a/include/linux/iosys-map.h b/include/linux/iosys-map.h index 4696abfd311c..3e85afe794c0 100644 --- a/include/linux/iosys-map.h +++ b/include/linux/iosys-map.h @@ -264,12 +264,7 @@ static inline bool iosys_map_is_set(const struct iosys_map *map) */ static inline void iosys_map_clear(struct iosys_map *map) { - if (map->is_iomem) { - map->vaddr_iomem = NULL; - map->is_iomem = false; - } else { - map->vaddr = NULL; - } + memset(map, 0, sizeof(*map)); }
/**
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Danilo Krummrich dakr@kernel.org
[ Upstream commit fde578c86281f27b182680c7642836a0dbbd0be7 ]
aligned_size() dates back to when Rust did support kmalloc() only, but is now used in ReallocFunc::call() and hence for all allocators.
However, the additional padding applied by aligned_size() is only required by the kmalloc() allocator backend.
Hence, replace aligned_size() with Kmalloc::aligned_layout() and use it for the affected allocators, i.e. kmalloc() and kvmalloc(), only.
While at it, make Kmalloc::aligned_layout() public, such that Rust abstractions, which have to call subsystem specific kmalloc() based allocation primitives directly, can make use of it.
Fixes: 8a799831fc63 ("rust: alloc: implement `ReallocFunc`") Reviewed-by: Alice Ryhl aliceryhl@google.com Link: https://lore.kernel.org/r/20250731154919.4132-2-dakr@kernel.org [ Remove `const` from Kmalloc::aligned_layout(). - Danilo ] Signed-off-by: Danilo Krummrich dakr@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- rust/kernel/alloc/allocator.rs | 30 ++++++++++++++++++------------ 1 file changed, 18 insertions(+), 12 deletions(-)
diff --git a/rust/kernel/alloc/allocator.rs b/rust/kernel/alloc/allocator.rs index aa2dfa9dca4c..2692cf90c948 100644 --- a/rust/kernel/alloc/allocator.rs +++ b/rust/kernel/alloc/allocator.rs @@ -43,17 +43,6 @@ pub struct Vmalloc; /// For more details see [self]. pub struct KVmalloc;
-/// Returns a proper size to alloc a new object aligned to `new_layout`'s alignment. -fn aligned_size(new_layout: Layout) -> usize { - // Customized layouts from `Layout::from_size_align()` can have size < align, so pad first. - let layout = new_layout.pad_to_align(); - - // Note that `layout.size()` (after padding) is guaranteed to be a multiple of `layout.align()` - // which together with the slab guarantees means the `krealloc` will return a properly aligned - // object (see comments in `kmalloc()` for more information). - layout.size() -} - /// # Invariants /// /// One of the following: `krealloc`, `vrealloc`, `kvrealloc`. @@ -88,7 +77,7 @@ impl ReallocFunc { old_layout: Layout, flags: Flags, ) -> Result<NonNull<[u8]>, AllocError> { - let size = aligned_size(layout); + let size = layout.size(); let ptr = match ptr { Some(ptr) => { if old_layout.size() == 0 { @@ -123,6 +112,17 @@ impl ReallocFunc { } }
+impl Kmalloc { + /// Returns a [`Layout`] that makes [`Kmalloc`] fulfill the requested size and alignment of + /// `layout`. + pub fn aligned_layout(layout: Layout) -> Layout { + // Note that `layout.size()` (after padding) is guaranteed to be a multiple of + // `layout.align()` which together with the slab guarantees means that `Kmalloc` will return + // a properly aligned object (see comments in `kmalloc()` for more information). + layout.pad_to_align() + } +} + // SAFETY: `realloc` delegates to `ReallocFunc::call`, which guarantees that // - memory remains valid until it is explicitly freed, // - passing a pointer to a valid memory allocation is OK, @@ -135,6 +135,8 @@ unsafe impl Allocator for Kmalloc { old_layout: Layout, flags: Flags, ) -> Result<NonNull<[u8]>, AllocError> { + let layout = Kmalloc::aligned_layout(layout); + // SAFETY: `ReallocFunc::call` has the same safety requirements as `Allocator::realloc`. unsafe { ReallocFunc::KREALLOC.call(ptr, layout, old_layout, flags) } } @@ -176,6 +178,10 @@ unsafe impl Allocator for KVmalloc { old_layout: Layout, flags: Flags, ) -> Result<NonNull<[u8]>, AllocError> { + // `KVmalloc` may use the `Kmalloc` backend, hence we have to enforce a `Kmalloc` + // compatible layout. + let layout = Kmalloc::aligned_layout(layout); + // TODO: Support alignments larger than PAGE_SIZE. if layout.align() > bindings::PAGE_SIZE { pr_warn!("KVmalloc does not support alignments larger than PAGE_SIZE yet.\n");
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Danilo Krummrich dakr@kernel.org
[ Upstream commit 22ab0641b939967f630d108e33a3582841ad6846 ]
drm::Device is allocated through __drm_dev_alloc() (which uses kmalloc()) and the driver private data, <T as drm::Driver>::Data, is initialized in-place.
Due to the order of fields in drm::Device
pub struct Device<T: drm::Driver> { dev: Opaquebindings::drm_device, data: T::Data, }
even with an arbitrary large alignment requirement of T::Data it can't happen that the size of Device is smaller than its alignment requirement.
However, let's not rely on this subtle circumstance and create a proper kmalloc() compatible Layout.
Fixes: 1e4b8896c0f3 ("rust: drm: add device abstraction") Reviewed-by: Alice Ryhl aliceryhl@google.com Link: https://lore.kernel.org/r/20250731154919.4132-3-dakr@kernel.org Signed-off-by: Danilo Krummrich dakr@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- rust/kernel/drm/device.rs | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-)
diff --git a/rust/kernel/drm/device.rs b/rust/kernel/drm/device.rs index 14c1aa402951..6c1fc33cdc68 100644 --- a/rust/kernel/drm/device.rs +++ b/rust/kernel/drm/device.rs @@ -5,6 +5,7 @@ //! C header: [`include/linux/drm/drm_device.h`](srctree/include/linux/drm/drm_device.h)
use crate::{ + alloc::allocator::Kmalloc, bindings, device, drm, drm::driver::AllocImpl, error::from_err_ptr, @@ -12,7 +13,7 @@ use crate::{ prelude::*, types::{ARef, AlwaysRefCounted, Opaque}, }; -use core::{mem, ops::Deref, ptr, ptr::NonNull}; +use core::{alloc::Layout, mem, ops::Deref, ptr, ptr::NonNull};
#[cfg(CONFIG_DRM_LEGACY)] macro_rules! drm_legacy_fields { @@ -96,6 +97,10 @@ impl<T: drm::Driver> Device<T> {
/// Create a new `drm::Device` for a `drm::Driver`. pub fn new(dev: &device::Device, data: impl PinInit<T::Data, Error>) -> Result<ARef<Self>> { + // `__drm_dev_alloc` uses `kmalloc()` to allocate memory, hence ensure a `kmalloc()` + // compatible `Layout`. + let layout = Kmalloc::aligned_layout(Layout::new::<Self>()); + // SAFETY: // - `VTABLE`, as a `const` is pinned to the read-only section of the compilation, // - `dev` is valid by its type invarants, @@ -103,7 +108,7 @@ impl<T: drm::Driver> Device<T> { bindings::__drm_dev_alloc( dev.as_raw(), &Self::VTABLE, - mem::size_of::<Self>(), + layout.size(), mem::offset_of!(Self, dev), ) }
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Danilo Krummrich dakr@kernel.org
[ Upstream commit 0c04a81c1d0214d5b2025f805ccec1ac37c96b08 ]
The #[pin_data] and #[pin] annotations are not necessary for drm::Device, since we don't use any pin-init macros, but only __pinned_init() on the impl PinInit<T::Data, Error> argument of drm::Device::new().
Fixes: 1e4b8896c0f3 ("rust: drm: add device abstraction") Reviewed-by: Benno Lossin lossin@kernel.org Link: https://lore.kernel.org/r/20250731154919.4132-4-dakr@kernel.org Signed-off-by: Danilo Krummrich dakr@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- rust/kernel/drm/device.rs | 2 -- 1 file changed, 2 deletions(-)
diff --git a/rust/kernel/drm/device.rs b/rust/kernel/drm/device.rs index 6c1fc33cdc68..cb6bbd024a1e 100644 --- a/rust/kernel/drm/device.rs +++ b/rust/kernel/drm/device.rs @@ -54,10 +54,8 @@ macro_rules! drm_legacy_fields { /// /// `self.dev` is a valid instance of a `struct device`. #[repr(C)] -#[pin_data] pub struct Device<T: drm::Driver> { dev: Opaquebindings::drm_device, - #[pin] data: T::Data, }
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Danilo Krummrich dakr@kernel.org
[ Upstream commit 360077278ba62e81310080f075a1a3028e778ef9 ]
In drm_dev_put() call in AlwaysRefCounted::dec_ref() we rely on struct drm_device to be the first field in drm::Device, whereas everywhere else we correctly obtain the address of the actual struct drm_device.
Analogous to the from_drm_device() helper, provide the into_drm_device() helper in order to address this.
Fixes: 1e4b8896c0f3 ("rust: drm: add device abstraction") Reviewed-by: Alice Ryhl aliceryhl@google.com Link: https://lore.kernel.org/r/20250731154919.4132-5-dakr@kernel.org Signed-off-by: Danilo Krummrich dakr@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- rust/kernel/drm/device.rs | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-)
diff --git a/rust/kernel/drm/device.rs b/rust/kernel/drm/device.rs index cb6bbd024a1e..3832779f439f 100644 --- a/rust/kernel/drm/device.rs +++ b/rust/kernel/drm/device.rs @@ -120,9 +120,13 @@ impl<T: drm::Driver> Device<T> { // - `raw_data` is a valid pointer to uninitialized memory. // - `raw_data` will not move until it is dropped. unsafe { data.__pinned_init(raw_data) }.inspect_err(|_| { - // SAFETY: `__drm_dev_alloc()` was successful, hence `raw_drm` must be valid and the + // SAFETY: `raw_drm` is a valid pointer to `Self`, given that `__drm_dev_alloc` was + // successful. + let drm_dev = unsafe { Self::into_drm_device(raw_drm) }; + + // SAFETY: `__drm_dev_alloc()` was successful, hence `drm_dev` must be valid and the // refcount must be non-zero. - unsafe { bindings::drm_dev_put(ptr::addr_of_mut!((*raw_drm.as_ptr()).dev).cast()) }; + unsafe { bindings::drm_dev_put(drm_dev) }; })?;
// SAFETY: The reference count is one, and now we take ownership of that reference as a @@ -145,6 +149,14 @@ impl<T: drm::Driver> Device<T> { unsafe { crate::container_of!(ptr, Self, dev) }.cast_mut() }
+ /// # Safety + /// + /// `ptr` must be a valid pointer to `Self`. + unsafe fn into_drm_device(ptr: NonNull<Self>) -> *mut bindings::drm_device { + // SAFETY: By the safety requirements of this function, `ptr` is a valid pointer to `Self`. + unsafe { &raw mut (*ptr.as_ptr()).dev }.cast() + } + /// Not intended to be called externally, except via declare_drm_ioctls!() /// /// # Safety @@ -194,8 +206,11 @@ unsafe impl<T: drm::Driver> AlwaysRefCounted for Device<T> { }
unsafe fn dec_ref(obj: NonNull<Self>) { + // SAFETY: `obj` is a valid pointer to `Self`. + let drm_dev = unsafe { Self::into_drm_device(obj) }; + // SAFETY: The safety requirements guarantee that the refcount is non-zero. - unsafe { bindings::drm_dev_put(obj.cast().as_ptr()) }; + unsafe { bindings::drm_dev_put(drm_dev) }; } }
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jocelyn Falempe jfalempe@redhat.com
[ Upstream commit 9af8f2b469c0438620832f3729a3c5c03853b56b ]
On 32bits ARM, u64 divided by a constant is not optimized to a multiply by inverse by the compiler [1]. So do the multiply by inverse explicitly for this architecture.
Link: https://github.com/llvm/llvm-project/issues/37280 [1] Reported-by: Andrei Lalaev andrey.lalaev@gmail.com Closes: https://lore.kernel.org/dri-devel/c0a2771c-f3f5-4d4c-aa82-d673b3c5cb46@gmail... Fixes: 675008f196ca ("drm/panic: Use a decimal fifo to avoid u64 by u64 divide") Reviewed-by: Alice Ryhl aliceryhl@google.com Signed-off-by: Jocelyn Falempe jfalempe@redhat.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/gpu/drm/drm_panic_qr.rs | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/drm_panic_qr.rs b/drivers/gpu/drm/drm_panic_qr.rs index 18492daae4b3..b9cc64458437 100644 --- a/drivers/gpu/drm/drm_panic_qr.rs +++ b/drivers/gpu/drm/drm_panic_qr.rs @@ -381,6 +381,26 @@ struct DecFifo { len: usize, }
+// On arm32 architecture, dividing an `u64` by a constant will generate a call +// to `__aeabi_uldivmod` which is not present in the kernel. +// So use the multiply by inverse method for this architecture. +fn div10(val: u64) -> u64 { + if cfg!(target_arch = "arm") { + let val_h = val >> 32; + let val_l = val & 0xFFFFFFFF; + let b_h: u64 = 0x66666666; + let b_l: u64 = 0x66666667; + + let tmp1 = val_h * b_l + ((val_l * b_l) >> 32); + let tmp2 = val_l * b_h + (tmp1 & 0xffffffff); + let tmp3 = val_h * b_h + (tmp1 >> 32) + (tmp2 >> 32); + + tmp3 >> 2 + } else { + val / 10 + } +} + impl DecFifo { fn push(&mut self, data: u64, len: usize) { let mut chunk = data; @@ -389,7 +409,7 @@ impl DecFifo { } for i in 0..len { self.decimals[i] = (chunk % 10) as u8; - chunk /= 10; + chunk = div10(chunk); } self.len += len; }
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Suma Hegde suma.hegde@amd.com
[ Upstream commit 2c78fb287e1f430b929f2e49786518350d15605c ]
If metric table address is not allocated, accessing metrics_bin will result in a NULL pointer dereference, so add a check.
Fixes: 5150542b8ec5 ("platform/x86/amd/hsmp: add support for metrics tbl") Signed-off-by: Suma Hegde suma.hegde@amd.com Link: https://lore.kernel.org/r/20250807100637.952729-1-suma.hegde@amd.com Reviewed-by: Ilpo Järvinen ilpo.jarvinen@linux.intel.com Signed-off-by: Ilpo Järvinen ilpo.jarvinen@linux.intel.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/platform/x86/amd/hsmp/hsmp.c | 5 +++++ 1 file changed, 5 insertions(+)
diff --git a/drivers/platform/x86/amd/hsmp/hsmp.c b/drivers/platform/x86/amd/hsmp/hsmp.c index 885e2f8136fd..19f82c1d3090 100644 --- a/drivers/platform/x86/amd/hsmp/hsmp.c +++ b/drivers/platform/x86/amd/hsmp/hsmp.c @@ -356,6 +356,11 @@ ssize_t hsmp_metric_tbl_read(struct hsmp_socket *sock, char *buf, size_t size) if (!sock || !buf) return -EINVAL;
+ if (!sock->metric_tbl_addr) { + dev_err(sock->dev, "Metrics table address not available\n"); + return -ENOMEM; + } + /* Do not support lseek(), also don't allow more than the size of metric table */ if (size != sizeof(struct hsmp_metric_table)) { dev_err(sock->dev, "Wrong buffer size\n");
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Boshi Yu boshiyu@linux.alibaba.com
[ Upstream commit d5c74713f0117d07f91eb48b10bc2ad44e23c9b9 ]
The init_kernel_qp interface may fail. Check its return value and free related resources properly when it does.
Fixes: 155055771704 ("RDMA/erdma: Add verbs implementation") Reviewed-by: Cheng Xu chengyou@linux.alibaba.com Signed-off-by: Boshi Yu boshiyu@linux.alibaba.com Link: https://patch.msgid.link/20250725055410.67520-3-boshiyu@linux.alibaba.com Signed-off-by: Leon Romanovsky leon@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/infiniband/hw/erdma/erdma_verbs.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/drivers/infiniband/hw/erdma/erdma_verbs.c b/drivers/infiniband/hw/erdma/erdma_verbs.c index ec0ad4086066..c1b2b8c3cdcc 100644 --- a/drivers/infiniband/hw/erdma/erdma_verbs.c +++ b/drivers/infiniband/hw/erdma/erdma_verbs.c @@ -1031,7 +1031,9 @@ int erdma_create_qp(struct ib_qp *ibqp, struct ib_qp_init_attr *attrs, if (ret) goto err_out_cmd; } else { - init_kernel_qp(dev, qp, attrs); + ret = init_kernel_qp(dev, qp, attrs); + if (ret) + goto err_out_xa; }
qp->attrs.max_send_sge = attrs->cap.max_send_sge;
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Boshi Yu boshiyu@linux.alibaba.com
[ Upstream commit d4ac86b47563c7895dae28658abd1879d266b2b4 ]
The QPN of the GSI QP was not set, which may cause issues. Set the QPN to 1 when creating the GSI QP.
Fixes: 999a0a2e9b87 ("RDMA/erdma: Support UD QPs and UD WRs") Reviewed-by: Cheng Xu chengyou@linux.alibaba.com Signed-off-by: Boshi Yu boshiyu@linux.alibaba.com Link: https://patch.msgid.link/20250725055410.67520-4-boshiyu@linux.alibaba.com Reviewed-by: Zhu Yanjun yanjun.zhu@linux.dev Signed-off-by: Leon Romanovsky leon@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/infiniband/hw/erdma/erdma_verbs.c | 2 ++ 1 file changed, 2 insertions(+)
diff --git a/drivers/infiniband/hw/erdma/erdma_verbs.c b/drivers/infiniband/hw/erdma/erdma_verbs.c index c1b2b8c3cdcc..8d7596abb822 100644 --- a/drivers/infiniband/hw/erdma/erdma_verbs.c +++ b/drivers/infiniband/hw/erdma/erdma_verbs.c @@ -994,6 +994,8 @@ int erdma_create_qp(struct ib_qp *ibqp, struct ib_qp_init_attr *attrs, old_entry = xa_store(&dev->qp_xa, 1, qp, GFP_KERNEL); if (xa_is_err(old_entry)) ret = xa_err(old_entry); + else + qp->ibqp.qp_num = 1; } else { ret = xa_alloc_cyclic(&dev->qp_xa, &qp->ibqp.qp_num, qp, XA_LIMIT(1, dev->attrs.max_qp - 1),
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: wenglianfa wenglianfa@huawei.com
[ Upstream commit 085a1b42e52750769a3fa29d4da6c05ab56f18f8 ]
When using DIP algorithm, all QPs establishing connections with the same destination IP share the same SCC, which is indexed by dip_idx, but dip_idx isn't necessarily equal to qpn. Therefore, dip_idx should be used to query SCC context instead of qpn.
Fixes: 124a9fbe43aa ("RDMA/hns: Append SCC context to the raw dump of QPC") Signed-off-by: wenglianfa wenglianfa@huawei.com Signed-off-by: Junxian Huang huangjunxian6@hisilicon.com Link: https://patch.msgid.link/20250726075345.846957-1-huangjunxian6@hisilicon.com Reviewed-by: Zhu Yanjun yanjun.zhu@linux.dev Signed-off-by: Leon Romanovsky leon@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/infiniband/hw/hns/hns_roce_hw_v2.c | 4 ++-- drivers/infiniband/hw/hns/hns_roce_restrack.c | 9 ++++++++- 2 files changed, 10 insertions(+), 3 deletions(-)
diff --git a/drivers/infiniband/hw/hns/hns_roce_hw_v2.c b/drivers/infiniband/hw/hns/hns_roce_hw_v2.c index b30dce00f240..256757f0ff65 100644 --- a/drivers/infiniband/hw/hns/hns_roce_hw_v2.c +++ b/drivers/infiniband/hw/hns/hns_roce_hw_v2.c @@ -5514,7 +5514,7 @@ static int hns_roce_v2_query_srqc(struct hns_roce_dev *hr_dev, u32 srqn, return ret; }
-static int hns_roce_v2_query_sccc(struct hns_roce_dev *hr_dev, u32 qpn, +static int hns_roce_v2_query_sccc(struct hns_roce_dev *hr_dev, u32 sccn, void *buffer) { struct hns_roce_v2_scc_context *context; @@ -5526,7 +5526,7 @@ static int hns_roce_v2_query_sccc(struct hns_roce_dev *hr_dev, u32 qpn, return PTR_ERR(mailbox);
ret = hns_roce_cmd_mbox(hr_dev, 0, mailbox->dma, HNS_ROCE_CMD_QUERY_SCCC, - qpn); + sccn); if (ret) goto out;
diff --git a/drivers/infiniband/hw/hns/hns_roce_restrack.c b/drivers/infiniband/hw/hns/hns_roce_restrack.c index f637b73b946e..230187dda6a0 100644 --- a/drivers/infiniband/hw/hns/hns_roce_restrack.c +++ b/drivers/infiniband/hw/hns/hns_roce_restrack.c @@ -100,6 +100,7 @@ int hns_roce_fill_res_qp_entry_raw(struct sk_buff *msg, struct ib_qp *ib_qp) struct hns_roce_v2_qp_context qpc; struct hns_roce_v2_scc_context sccc; } context = {}; + u32 sccn = hr_qp->qpn; int ret;
if (!hr_dev->hw->query_qpc) @@ -116,7 +117,13 @@ int hns_roce_fill_res_qp_entry_raw(struct sk_buff *msg, struct ib_qp *ib_qp) !hr_dev->hw->query_sccc) goto out;
- ret = hr_dev->hw->query_sccc(hr_dev, hr_qp->qpn, &context.sccc); + if (hr_qp->cong_type == CONG_TYPE_DIP) { + if (!hr_qp->dip) + goto out; + sccn = hr_qp->dip->dip_idx; + } + + ret = hr_dev->hw->query_sccc(hr_dev, sccn, &context.sccc); if (ret) ibdev_warn_ratelimited(&hr_dev->ib_dev, "failed to query SCCC, ret = %d.\n",
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Kashyap Desai kashyap.desai@broadcom.com
[ Upstream commit 6296f9a5293ada28558f2867ac54c487e1e2b9f2 ]
Whenever SRQ is created, make sure SRQ arm enable is always set. Driver is always ready to receive SRQ ASYNC event.
Additional note - There is no need to do srq arm enable conditionally. See bnxt_qplib_armen_db in bnxt_qplib_create_cq().
Fixes: 37cb11acf1f7 ("RDMA/bnxt_re: Add SRQ support for Broadcom adapters") Signed-off-by: Kashyap Desai kashyap.desai@broadcom.com Signed-off-by: Saravanan Vajravel saravanan.vajravel@broadcom.com Link: https://patch.msgid.link/20250805101000.233310-2-kalesh-anakkur.purayil@broa... Reviewed-by: Kalesh AP kalesh-anakkur.purayil@broadcom.com Signed-off-by: Leon Romanovsky leon@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/infiniband/hw/bnxt_re/qplib_fp.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/drivers/infiniband/hw/bnxt_re/qplib_fp.c b/drivers/infiniband/hw/bnxt_re/qplib_fp.c index be34c605d516..eb82440cdded 100644 --- a/drivers/infiniband/hw/bnxt_re/qplib_fp.c +++ b/drivers/infiniband/hw/bnxt_re/qplib_fp.c @@ -705,8 +705,7 @@ int bnxt_qplib_create_srq(struct bnxt_qplib_res *res, srq->dbinfo.db = srq->dpi->dbr; srq->dbinfo.max_slot = 1; srq->dbinfo.priv_db = res->dpi_tbl.priv_db; - if (srq->threshold) - bnxt_qplib_armen_db(&srq->dbinfo, DBC_DBC_TYPE_SRQ_ARMENA); + bnxt_qplib_armen_db(&srq->dbinfo, DBC_DBC_TYPE_SRQ_ARMENA); srq->arm_req = false;
return 0;
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Kashyap Desai kashyap.desai@broadcom.com
[ Upstream commit 666bce0bd7e771127cb0cda125cc9d32d9f9f15d ]
There should not be any checks of current workload to set srq_limit value to SRQ hw context.
Remove all such workload checks and make a direct call to set srq_limit via doorbell SRQ_ARM.
Fixes: 37cb11acf1f7 ("RDMA/bnxt_re: Add SRQ support for Broadcom adapters") Signed-off-by: Kashyap Desai kashyap.desai@broadcom.com Signed-off-by: Saravanan Vajravel saravanan.vajravel@broadcom.com Signed-off-by: Kalesh AP kalesh-anakkur.purayil@broadcom.com Link: https://patch.msgid.link/20250805101000.233310-3-kalesh-anakkur.purayil@broa... Signed-off-by: Leon Romanovsky leon@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/infiniband/hw/bnxt_re/ib_verbs.c | 8 ++----- drivers/infiniband/hw/bnxt_re/qplib_fp.c | 27 ------------------------ drivers/infiniband/hw/bnxt_re/qplib_fp.h | 2 -- 3 files changed, 2 insertions(+), 35 deletions(-)
diff --git a/drivers/infiniband/hw/bnxt_re/ib_verbs.c b/drivers/infiniband/hw/bnxt_re/ib_verbs.c index 3a627acb82ce..9b33072f9a06 100644 --- a/drivers/infiniband/hw/bnxt_re/ib_verbs.c +++ b/drivers/infiniband/hw/bnxt_re/ib_verbs.c @@ -1921,7 +1921,6 @@ int bnxt_re_modify_srq(struct ib_srq *ib_srq, struct ib_srq_attr *srq_attr, struct bnxt_re_srq *srq = container_of(ib_srq, struct bnxt_re_srq, ib_srq); struct bnxt_re_dev *rdev = srq->rdev; - int rc;
switch (srq_attr_mask) { case IB_SRQ_MAX_WR: @@ -1933,11 +1932,8 @@ int bnxt_re_modify_srq(struct ib_srq *ib_srq, struct ib_srq_attr *srq_attr, return -EINVAL;
srq->qplib_srq.threshold = srq_attr->srq_limit; - rc = bnxt_qplib_modify_srq(&rdev->qplib_res, &srq->qplib_srq); - if (rc) { - ibdev_err(&rdev->ibdev, "Modify HW SRQ failed!"); - return rc; - } + bnxt_qplib_srq_arm_db(&srq->qplib_srq.dbinfo, srq->qplib_srq.threshold); + /* On success, update the shadow */ srq->srq_limit = srq_attr->srq_limit; /* No need to Build and send response back to udata */ diff --git a/drivers/infiniband/hw/bnxt_re/qplib_fp.c b/drivers/infiniband/hw/bnxt_re/qplib_fp.c index eb82440cdded..c2784561156f 100644 --- a/drivers/infiniband/hw/bnxt_re/qplib_fp.c +++ b/drivers/infiniband/hw/bnxt_re/qplib_fp.c @@ -706,7 +706,6 @@ int bnxt_qplib_create_srq(struct bnxt_qplib_res *res, srq->dbinfo.max_slot = 1; srq->dbinfo.priv_db = res->dpi_tbl.priv_db; bnxt_qplib_armen_db(&srq->dbinfo, DBC_DBC_TYPE_SRQ_ARMENA); - srq->arm_req = false;
return 0; fail: @@ -716,24 +715,6 @@ int bnxt_qplib_create_srq(struct bnxt_qplib_res *res, return rc; }
-int bnxt_qplib_modify_srq(struct bnxt_qplib_res *res, - struct bnxt_qplib_srq *srq) -{ - struct bnxt_qplib_hwq *srq_hwq = &srq->hwq; - u32 count; - - count = __bnxt_qplib_get_avail(srq_hwq); - if (count > srq->threshold) { - srq->arm_req = false; - bnxt_qplib_srq_arm_db(&srq->dbinfo, srq->threshold); - } else { - /* Deferred arming */ - srq->arm_req = true; - } - - return 0; -} - int bnxt_qplib_query_srq(struct bnxt_qplib_res *res, struct bnxt_qplib_srq *srq) { @@ -775,7 +756,6 @@ int bnxt_qplib_post_srq_recv(struct bnxt_qplib_srq *srq, struct bnxt_qplib_hwq *srq_hwq = &srq->hwq; struct rq_wqe *srqe; struct sq_sge *hw_sge; - u32 count = 0; int i, next;
spin_lock(&srq_hwq->lock); @@ -807,15 +787,8 @@ int bnxt_qplib_post_srq_recv(struct bnxt_qplib_srq *srq,
bnxt_qplib_hwq_incr_prod(&srq->dbinfo, srq_hwq, srq->dbinfo.max_slot);
- spin_lock(&srq_hwq->lock); - count = __bnxt_qplib_get_avail(srq_hwq); - spin_unlock(&srq_hwq->lock); /* Ring DB */ bnxt_qplib_ring_prod_db(&srq->dbinfo, DBC_DBC_TYPE_SRQ); - if (srq->arm_req == true && count > srq->threshold) { - srq->arm_req = false; - bnxt_qplib_srq_arm_db(&srq->dbinfo, srq->threshold); - }
return 0; } diff --git a/drivers/infiniband/hw/bnxt_re/qplib_fp.h b/drivers/infiniband/hw/bnxt_re/qplib_fp.h index 0d9487c889ff..846501f12227 100644 --- a/drivers/infiniband/hw/bnxt_re/qplib_fp.h +++ b/drivers/infiniband/hw/bnxt_re/qplib_fp.h @@ -543,8 +543,6 @@ int bnxt_qplib_enable_nq(struct pci_dev *pdev, struct bnxt_qplib_nq *nq, srqn_handler_t srq_handler); int bnxt_qplib_create_srq(struct bnxt_qplib_res *res, struct bnxt_qplib_srq *srq); -int bnxt_qplib_modify_srq(struct bnxt_qplib_res *res, - struct bnxt_qplib_srq *srq); int bnxt_qplib_query_srq(struct bnxt_qplib_res *res, struct bnxt_qplib_srq *srq); void bnxt_qplib_destroy_srq(struct bnxt_qplib_res *res,
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Kalesh AP kalesh-anakkur.purayil@broadcom.com
[ Upstream commit ba60a1e8cbbd396c69ff9c8bc3242f5ab133e38a ]
The GID context reuse logic requires the context memory to be not freed if and when DEL_GID firmware command fails. But, if there's no subsequent ADD_GID to reuse it, the context memory must be freed when the driver is unloaded. Otherwise it leads to a memory leak.
Below is the kmemleak trace reported:
unreferenced object 0xffff88817a4f34d0 (size 8): comm "insmod", pid 1072504, jiffies 4402561550 hex dump (first 8 bytes): 01 00 00 00 00 00 00 00 ........ backtrace (crc ccaa009e): __kmalloc_cache_noprof+0x33e/0x400 0xffffffffc2db9d48 add_modify_gid+0x5e0/0xb60 [ib_core] __ib_cache_gid_add+0x213/0x350 [ib_core] update_gid+0xf2/0x180 [ib_core] enum_netdev_ipv4_ips+0x3f3/0x690 [ib_core] enum_all_gids_of_dev_cb+0x125/0x1b0 [ib_core] ib_enum_roce_netdev+0x14b/0x250 [ib_core] ib_cache_setup_one+0x2e5/0x540 [ib_core] ib_register_device+0x82c/0xf10 [ib_core] 0xffffffffc2df5ad9 0xffffffffc2da8b07 0xffffffffc2db174d auxiliary_bus_probe+0xa5/0x120 really_probe+0x1e4/0x850 __driver_probe_device+0x18f/0x3d0
Fixes: 4a62c5e9e2e1 ("RDMA/bnxt_re: Do not free the ctx_tbl entry if delete GID fails") Signed-off-by: Kalesh AP kalesh-anakkur.purayil@broadcom.com Link: https://patch.msgid.link/20250805101000.233310-4-kalesh-anakkur.purayil@broa... Reviewed-by: Sriharsha Basavapatna sriharsha.basavapatna@broadcom.com Signed-off-by: Leon Romanovsky leon@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/infiniband/hw/bnxt_re/main.c | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+)
diff --git a/drivers/infiniband/hw/bnxt_re/main.c b/drivers/infiniband/hw/bnxt_re/main.c index 293b0a96c8e3..df7cf8d68e27 100644 --- a/drivers/infiniband/hw/bnxt_re/main.c +++ b/drivers/infiniband/hw/bnxt_re/main.c @@ -2017,6 +2017,28 @@ static void bnxt_re_free_nqr_mem(struct bnxt_re_dev *rdev) rdev->nqr = NULL; }
+/* When DEL_GID fails, driver is not freeing GID ctx memory. + * To avoid the memory leak, free the memory during unload + */ +static void bnxt_re_free_gid_ctx(struct bnxt_re_dev *rdev) +{ + struct bnxt_qplib_sgid_tbl *sgid_tbl = &rdev->qplib_res.sgid_tbl; + struct bnxt_re_gid_ctx *ctx, **ctx_tbl; + int i; + + if (!sgid_tbl->active) + return; + + ctx_tbl = sgid_tbl->ctx; + for (i = 0; i < sgid_tbl->max; i++) { + if (sgid_tbl->hw_id[i] == 0xFFFF) + continue; + + ctx = ctx_tbl[i]; + kfree(ctx); + } +} + static void bnxt_re_dev_uninit(struct bnxt_re_dev *rdev, u8 op_type) { u8 type; @@ -2030,6 +2052,7 @@ static void bnxt_re_dev_uninit(struct bnxt_re_dev *rdev, u8 op_type) if (test_and_clear_bit(BNXT_RE_FLAG_QOS_WORK_REG, &rdev->flags)) cancel_delayed_work_sync(&rdev->worker);
+ bnxt_re_free_gid_ctx(rdev); if (test_and_clear_bit(BNXT_RE_FLAG_RESOURCES_INITIALIZED, &rdev->flags)) bnxt_re_cleanup_res(rdev);
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Anantha Prabhu anantha.prabhu@broadcom.com
[ Upstream commit 806b9f494f62791ee6d68f515a8056c615a0e7b2 ]
memset the PBL page pointer and page map arrays before populating the SGL addresses of the HWQ.
Fixes: 0c4dcd602817 ("RDMA/bnxt_re: Refactor hardware queue memory allocation") Signed-off-by: Anantha Prabhu anantha.prabhu@broadcom.com Reviewed-by: Saravanan Vajravel saravanan.vajravel@broadcom.com Reviewed-by: Selvin Xavier selvin.xavier@broadcom.com Signed-off-by: Kalesh AP kalesh-anakkur.purayil@broadcom.com Link: https://patch.msgid.link/20250805101000.233310-5-kalesh-anakkur.purayil@broa... Signed-off-by: Leon Romanovsky leon@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/infiniband/hw/bnxt_re/qplib_res.c | 2 ++ 1 file changed, 2 insertions(+)
diff --git a/drivers/infiniband/hw/bnxt_re/qplib_res.c b/drivers/infiniband/hw/bnxt_re/qplib_res.c index 6cd05207ffed..cc5c82d96839 100644 --- a/drivers/infiniband/hw/bnxt_re/qplib_res.c +++ b/drivers/infiniband/hw/bnxt_re/qplib_res.c @@ -121,6 +121,7 @@ static int __alloc_pbl(struct bnxt_qplib_res *res, pbl->pg_arr = vmalloc_array(pages, sizeof(void *)); if (!pbl->pg_arr) return -ENOMEM; + memset(pbl->pg_arr, 0, pages * sizeof(void *));
pbl->pg_map_arr = vmalloc_array(pages, sizeof(dma_addr_t)); if (!pbl->pg_map_arr) { @@ -128,6 +129,7 @@ static int __alloc_pbl(struct bnxt_qplib_res *res, pbl->pg_arr = NULL; return -ENOMEM; } + memset(pbl->pg_map_arr, 0, pages * sizeof(dma_addr_t)); pbl->pg_count = 0; pbl->pg_size = sginfo->pgsize;
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Akhilesh Patil akhilesh@ee.iitb.ac.in
[ Upstream commit 111aea0464c20f3eb25a48d5ff6c036e6b416123 ]
Ensure that pfn_list allocated by kvcalloc() is freed using corresponding kvfree() function. Match memory allocation and free routines kvcalloc -> kvfree.
Fixes: 259e9bd07c57 ("RDMA/core: Avoid hmm_dma_map_alloc() for virtual DMA devices") Signed-off-by: Akhilesh Patil akhilesh@ee.iitb.ac.in Link: https://patch.msgid.link/aJjcPjL1BVh8QrMN@bhairav-test.ee.iitb.ac.in Signed-off-by: Leon Romanovsky leon@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/infiniband/core/umem_odp.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/infiniband/core/umem_odp.c b/drivers/infiniband/core/umem_odp.c index b1c44ec1a3f3..572a91a62a7b 100644 --- a/drivers/infiniband/core/umem_odp.c +++ b/drivers/infiniband/core/umem_odp.c @@ -115,7 +115,7 @@ static int ib_init_umem_odp(struct ib_umem_odp *umem_odp,
out_free_map: if (ib_uses_virt_dma(dev)) - kfree(map->pfn_list); + kvfree(map->pfn_list); else hmm_dma_map_free(dev->dma_device, map); return ret; @@ -287,7 +287,7 @@ static void ib_umem_odp_free(struct ib_umem_odp *umem_odp) mutex_unlock(&umem_odp->umem_mutex); mmu_interval_notifier_remove(&umem_odp->notifier); if (ib_uses_virt_dma(dev)) - kfree(umem_odp->map.pfn_list); + kvfree(umem_odp->map.pfn_list); else hmm_dma_map_free(dev->dma_device, &umem_odp->map); }
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Junxian Huang huangjunxian6@hisilicon.com
[ Upstream commit fa2e2d31ee3b7212079323b4b09201ef68af3a97 ]
DIP algorithm is also supported on devices newer than hip09, so free dip entries too.
Fixes: f91696f2f053 ("RDMA/hns: Support congestion control type selection according to the FW") Signed-off-by: Junxian Huang huangjunxian6@hisilicon.com Link: https://patch.msgid.link/20250812122602.3524602-1-huangjunxian6@hisilicon.co... Signed-off-by: Leon Romanovsky leon@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/infiniband/hw/hns/hns_roce_hw_v2.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/infiniband/hw/hns/hns_roce_hw_v2.c b/drivers/infiniband/hw/hns/hns_roce_hw_v2.c index 256757f0ff65..b544ca024484 100644 --- a/drivers/infiniband/hw/hns/hns_roce_hw_v2.c +++ b/drivers/infiniband/hw/hns/hns_roce_hw_v2.c @@ -3043,7 +3043,7 @@ static void hns_roce_v2_exit(struct hns_roce_dev *hr_dev) if (!hr_dev->is_vf) hns_roce_free_link_table(hr_dev);
- if (hr_dev->pci_dev->revision == PCI_REVISION_ID_HIP09) + if (hr_dev->pci_dev->revision >= PCI_REVISION_ID_HIP09) free_dip_entry(hr_dev); }
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Suraj Gupta suraj.gupta2@amd.com
[ Upstream commit fd980bf6e9cdae885105685259421164f843ca55 ]
Submit multiple descriptors in axienet_rx_cb() to fill Rx skb ring. This ensures the ring "catches up" on previously missed allocations.
Increment Rx skb ring head pointer after BD is successfully allocated. Previously, head pointer was incremented before verifying if descriptor is successfully allocated and has valid entries, which could lead to ring state inconsistency if descriptor setup failed.
These changes improve reliability by maintaining adequate descriptor availability and ensuring proper ring buffer state management.
Fixes: 6a91b846af85 ("net: axienet: Introduce dmaengine support") Signed-off-by: Suraj Gupta suraj.gupta2@amd.com Link: https://patch.msgid.link/20250813135559.1555652-1-suraj.gupta2@amd.com Signed-off-by: Jakub Kicinski kuba@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/net/ethernet/xilinx/xilinx_axienet_main.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-)
diff --git a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c index 6011d7eae0c7..0d8a05fe541a 100644 --- a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c +++ b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c @@ -1160,6 +1160,7 @@ static void axienet_dma_rx_cb(void *data, const struct dmaengine_result *result) struct axienet_local *lp = data; struct sk_buff *skb; u32 *app_metadata; + int i;
skbuf_dma = axienet_get_rx_desc(lp, lp->rx_ring_tail++); skb = skbuf_dma->skb; @@ -1178,7 +1179,10 @@ static void axienet_dma_rx_cb(void *data, const struct dmaengine_result *result) u64_stats_add(&lp->rx_packets, 1); u64_stats_add(&lp->rx_bytes, rx_len); u64_stats_update_end(&lp->rx_stat_sync); - axienet_rx_submit_desc(lp->ndev); + + for (i = 0; i < CIRC_SPACE(lp->rx_ring_head, lp->rx_ring_tail, + RX_BUF_NUM_DEFAULT); i++) + axienet_rx_submit_desc(lp->ndev); dma_async_issue_pending(lp->rx_chan); }
@@ -1457,7 +1461,6 @@ static void axienet_rx_submit_desc(struct net_device *ndev) if (!skbuf_dma) return;
- lp->rx_ring_head++; skb = netdev_alloc_skb(ndev, lp->max_frm_size); if (!skb) return; @@ -1482,6 +1485,7 @@ static void axienet_rx_submit_desc(struct net_device *ndev) skbuf_dma->desc = dma_rx_desc; dma_rx_desc->callback_param = lp; dma_rx_desc->callback_result = axienet_dma_rx_cb; + lp->rx_ring_head++; dmaengine_submit(dma_rx_desc);
return;
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Wang Liang wangliang74@huawei.com
[ Upstream commit d1547bf460baec718b3398365f8de33d25c5f36f ]
When set multicast_query_interval to a large value, the local variable 'time' in br_multicast_send_query() may overflow. If the time is smaller than jiffies, the timer will expire immediately, and then call mod_timer() again, which creates a loop and may trigger the following soft lockup issue.
watchdog: BUG: soft lockup - CPU#1 stuck for 221s! [rb_consumer:66] CPU: 1 UID: 0 PID: 66 Comm: rb_consumer Not tainted 6.16.0+ #259 PREEMPT(none) Call Trace: <IRQ> __netdev_alloc_skb+0x2e/0x3a0 br_ip6_multicast_alloc_query+0x212/0x1b70 __br_multicast_send_query+0x376/0xac0 br_multicast_send_query+0x299/0x510 br_multicast_query_expired.constprop.0+0x16d/0x1b0 call_timer_fn+0x3b/0x2a0 __run_timers+0x619/0x950 run_timer_softirq+0x11c/0x220 handle_softirqs+0x18e/0x560 __irq_exit_rcu+0x158/0x1a0 sysvec_apic_timer_interrupt+0x76/0x90 </IRQ>
This issue can be reproduced with: ip link add br0 type bridge echo 1 > /sys/class/net/br0/bridge/multicast_querier echo 0xffffffffffffffff > /sys/class/net/br0/bridge/multicast_query_interval ip link set dev br0 up
The multicast_startup_query_interval can also cause this issue. Similar to the commit 99b40610956a ("net: bridge: mcast: add and enforce query interval minimum"), add check for the query interval maximum to fix this issue.
Link: https://lore.kernel.org/netdev/20250806094941.1285944-1-wangliang74@huawei.c... Link: https://lore.kernel.org/netdev/20250812091818.542238-1-wangliang74@huawei.co... Fixes: d902eee43f19 ("bridge: Add multicast count/interval sysfs entries") Suggested-by: Nikolay Aleksandrov razor@blackwall.org Signed-off-by: Wang Liang wangliang74@huawei.com Reviewed-by: Ido Schimmel idosch@nvidia.com Acked-by: Nikolay Aleksandrov razor@blackwall.org Link: https://patch.msgid.link/20250813021054.1643649-1-wangliang74@huawei.com Signed-off-by: Jakub Kicinski kuba@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- net/bridge/br_multicast.c | 16 ++++++++++++++++ net/bridge/br_private.h | 2 ++ 2 files changed, 18 insertions(+)
diff --git a/net/bridge/br_multicast.c b/net/bridge/br_multicast.c index 1377f31b719c..8ce145938b02 100644 --- a/net/bridge/br_multicast.c +++ b/net/bridge/br_multicast.c @@ -4818,6 +4818,14 @@ void br_multicast_set_query_intvl(struct net_bridge_mcast *brmctx, intvl_jiffies = BR_MULTICAST_QUERY_INTVL_MIN; }
+ if (intvl_jiffies > BR_MULTICAST_QUERY_INTVL_MAX) { + br_info(brmctx->br, + "trying to set multicast query interval above maximum, setting to %lu (%ums)\n", + jiffies_to_clock_t(BR_MULTICAST_QUERY_INTVL_MAX), + jiffies_to_msecs(BR_MULTICAST_QUERY_INTVL_MAX)); + intvl_jiffies = BR_MULTICAST_QUERY_INTVL_MAX; + } + brmctx->multicast_query_interval = intvl_jiffies; }
@@ -4834,6 +4842,14 @@ void br_multicast_set_startup_query_intvl(struct net_bridge_mcast *brmctx, intvl_jiffies = BR_MULTICAST_STARTUP_QUERY_INTVL_MIN; }
+ if (intvl_jiffies > BR_MULTICAST_STARTUP_QUERY_INTVL_MAX) { + br_info(brmctx->br, + "trying to set multicast startup query interval above maximum, setting to %lu (%ums)\n", + jiffies_to_clock_t(BR_MULTICAST_STARTUP_QUERY_INTVL_MAX), + jiffies_to_msecs(BR_MULTICAST_STARTUP_QUERY_INTVL_MAX)); + intvl_jiffies = BR_MULTICAST_STARTUP_QUERY_INTVL_MAX; + } + brmctx->multicast_startup_query_interval = intvl_jiffies; }
diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h index b159aae594c0..8de0904b9627 100644 --- a/net/bridge/br_private.h +++ b/net/bridge/br_private.h @@ -31,6 +31,8 @@ #define BR_MULTICAST_DEFAULT_HASH_MAX 4096 #define BR_MULTICAST_QUERY_INTVL_MIN msecs_to_jiffies(1000) #define BR_MULTICAST_STARTUP_QUERY_INTVL_MIN BR_MULTICAST_QUERY_INTVL_MIN +#define BR_MULTICAST_QUERY_INTVL_MAX msecs_to_jiffies(86400000) /* 24 hours */ +#define BR_MULTICAST_STARTUP_QUERY_INTVL_MAX BR_MULTICAST_QUERY_INTVL_MAX
#define BR_HWDOM_MAX BITS_PER_LONG
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: William Liu will@willsroot.io
[ Upstream commit 52bf272636bda69587952b35ae97690b8dc89941 ]
This issue applies for the following qdiscs: hhf, fq, fq_codel, and fq_pie, and occurs in their change handlers when adjusting to the new limit. The problem is the following in the values passed to the subsequent qdisc_tree_reduce_backlog call given a tbf parent:
When the tbf parent runs out of tokens, skbs of these qdiscs will be placed in gso_skb. Their peek handlers are qdisc_peek_dequeued, which accounts for both qlen and backlog. However, in the case of qdisc_dequeue_internal, ONLY qlen is accounted for when pulling from gso_skb. This means that these qdiscs are missing a qdisc_qstats_backlog_dec when dropping packets to satisfy the new limit in their change handlers.
One can observe this issue with the following (with tc patched to support a limit of 0):
export TARGET=fq tc qdisc del dev lo root tc qdisc add dev lo root handle 1: tbf rate 8bit burst 100b latency 1ms tc qdisc replace dev lo handle 3: parent 1:1 $TARGET limit 1000 echo ''; echo 'add child'; tc -s -d qdisc show dev lo ping -I lo -f -c2 -s32 -W0.001 127.0.0.1 2>&1 >/dev/null echo ''; echo 'after ping'; tc -s -d qdisc show dev lo tc qdisc change dev lo handle 3: parent 1:1 $TARGET limit 0 echo ''; echo 'after limit drop'; tc -s -d qdisc show dev lo tc qdisc replace dev lo handle 2: parent 1:1 sfq echo ''; echo 'post graft'; tc -s -d qdisc show dev lo
The second to last show command shows 0 packets but a positive number (74) of backlog bytes. The problem becomes clearer in the last show command, where qdisc_purge_queue triggers qdisc_tree_reduce_backlog with the positive backlog and causes an underflow in the tbf parent's backlog (4096 Mb instead of 0).
To fix this issue, the codepath for all clients of qdisc_dequeue_internal has been simplified: codel, pie, hhf, fq, fq_pie, and fq_codel. qdisc_dequeue_internal handles the backlog adjustments for all cases that do not directly use the dequeue handler.
The old fq_codel_change limit adjustment loop accumulated the arguments to the subsequent qdisc_tree_reduce_backlog call through the cstats field. However, this is confusing and error prone as fq_codel_dequeue could also potentially mutate this field (which qdisc_dequeue_internal calls in the non gso_skb case), so we have unified the code here with other qdiscs.
Fixes: 2d3cbfd6d54a ("net_sched: Flush gso_skb list too during ->change()") Fixes: 4b549a2ef4be ("fq_codel: Fair Queue Codel AQM") Fixes: 10239edf86f1 ("net-qdisc-hhf: Heavy-Hitter Filter (HHF) qdisc") Signed-off-by: William Liu will@willsroot.io Reviewed-by: Savino Dicanosa savy@syst3mfailure.io Link: https://patch.msgid.link/20250812235725.45243-1-will@willsroot.io Signed-off-by: Jakub Kicinski kuba@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- include/net/sch_generic.h | 11 ++++++++--- net/sched/sch_codel.c | 12 +++++++----- net/sched/sch_fq.c | 12 +++++++----- net/sched/sch_fq_codel.c | 12 +++++++----- net/sched/sch_fq_pie.c | 12 +++++++----- net/sched/sch_hhf.c | 12 +++++++----- net/sched/sch_pie.c | 12 +++++++----- 7 files changed, 50 insertions(+), 33 deletions(-)
diff --git a/include/net/sch_generic.h b/include/net/sch_generic.h index 638948be4c50..738cd5b13c62 100644 --- a/include/net/sch_generic.h +++ b/include/net/sch_generic.h @@ -1038,12 +1038,17 @@ static inline struct sk_buff *qdisc_dequeue_internal(struct Qdisc *sch, bool dir skb = __skb_dequeue(&sch->gso_skb); if (skb) { sch->q.qlen--; + qdisc_qstats_backlog_dec(sch, skb); return skb; } - if (direct) - return __qdisc_dequeue_head(&sch->q); - else + if (direct) { + skb = __qdisc_dequeue_head(&sch->q); + if (skb) + qdisc_qstats_backlog_dec(sch, skb); + return skb; + } else { return sch->dequeue(sch); + } }
static inline struct sk_buff *qdisc_dequeue_head(struct Qdisc *sch) diff --git a/net/sched/sch_codel.c b/net/sched/sch_codel.c index c93761040c6e..fa0314679e43 100644 --- a/net/sched/sch_codel.c +++ b/net/sched/sch_codel.c @@ -101,9 +101,9 @@ static const struct nla_policy codel_policy[TCA_CODEL_MAX + 1] = { static int codel_change(struct Qdisc *sch, struct nlattr *opt, struct netlink_ext_ack *extack) { + unsigned int dropped_pkts = 0, dropped_bytes = 0; struct codel_sched_data *q = qdisc_priv(sch); struct nlattr *tb[TCA_CODEL_MAX + 1]; - unsigned int qlen, dropped = 0; int err;
err = nla_parse_nested_deprecated(tb, TCA_CODEL_MAX, opt, @@ -142,15 +142,17 @@ static int codel_change(struct Qdisc *sch, struct nlattr *opt, WRITE_ONCE(q->params.ecn, !!nla_get_u32(tb[TCA_CODEL_ECN]));
- qlen = sch->q.qlen; while (sch->q.qlen > sch->limit) { struct sk_buff *skb = qdisc_dequeue_internal(sch, true);
- dropped += qdisc_pkt_len(skb); - qdisc_qstats_backlog_dec(sch, skb); + if (!skb) + break; + + dropped_pkts++; + dropped_bytes += qdisc_pkt_len(skb); rtnl_qdisc_drop(skb, sch); } - qdisc_tree_reduce_backlog(sch, qlen - sch->q.qlen, dropped); + qdisc_tree_reduce_backlog(sch, dropped_pkts, dropped_bytes);
sch_tree_unlock(sch); return 0; diff --git a/net/sched/sch_fq.c b/net/sched/sch_fq.c index 902ff5470607..fee922da2f99 100644 --- a/net/sched/sch_fq.c +++ b/net/sched/sch_fq.c @@ -1013,11 +1013,11 @@ static int fq_load_priomap(struct fq_sched_data *q, static int fq_change(struct Qdisc *sch, struct nlattr *opt, struct netlink_ext_ack *extack) { + unsigned int dropped_pkts = 0, dropped_bytes = 0; struct fq_sched_data *q = qdisc_priv(sch); struct nlattr *tb[TCA_FQ_MAX + 1]; - int err, drop_count = 0; - unsigned drop_len = 0; u32 fq_log; + int err;
err = nla_parse_nested_deprecated(tb, TCA_FQ_MAX, opt, fq_policy, NULL); @@ -1135,16 +1135,18 @@ static int fq_change(struct Qdisc *sch, struct nlattr *opt, err = fq_resize(sch, fq_log); sch_tree_lock(sch); } + while (sch->q.qlen > sch->limit) { struct sk_buff *skb = qdisc_dequeue_internal(sch, false);
if (!skb) break; - drop_len += qdisc_pkt_len(skb); + + dropped_pkts++; + dropped_bytes += qdisc_pkt_len(skb); rtnl_kfree_skbs(skb, skb); - drop_count++; } - qdisc_tree_reduce_backlog(sch, drop_count, drop_len); + qdisc_tree_reduce_backlog(sch, dropped_pkts, dropped_bytes);
sch_tree_unlock(sch); return err; diff --git a/net/sched/sch_fq_codel.c b/net/sched/sch_fq_codel.c index 2a0f3a513bfa..a14142392939 100644 --- a/net/sched/sch_fq_codel.c +++ b/net/sched/sch_fq_codel.c @@ -366,6 +366,7 @@ static const struct nla_policy fq_codel_policy[TCA_FQ_CODEL_MAX + 1] = { static int fq_codel_change(struct Qdisc *sch, struct nlattr *opt, struct netlink_ext_ack *extack) { + unsigned int dropped_pkts = 0, dropped_bytes = 0; struct fq_codel_sched_data *q = qdisc_priv(sch); struct nlattr *tb[TCA_FQ_CODEL_MAX + 1]; u32 quantum = 0; @@ -443,13 +444,14 @@ static int fq_codel_change(struct Qdisc *sch, struct nlattr *opt, q->memory_usage > q->memory_limit) { struct sk_buff *skb = qdisc_dequeue_internal(sch, false);
- q->cstats.drop_len += qdisc_pkt_len(skb); + if (!skb) + break; + + dropped_pkts++; + dropped_bytes += qdisc_pkt_len(skb); rtnl_kfree_skbs(skb, skb); - q->cstats.drop_count++; } - qdisc_tree_reduce_backlog(sch, q->cstats.drop_count, q->cstats.drop_len); - q->cstats.drop_count = 0; - q->cstats.drop_len = 0; + qdisc_tree_reduce_backlog(sch, dropped_pkts, dropped_bytes);
sch_tree_unlock(sch); return 0; diff --git a/net/sched/sch_fq_pie.c b/net/sched/sch_fq_pie.c index b0e34daf1f75..7b96bc3ff891 100644 --- a/net/sched/sch_fq_pie.c +++ b/net/sched/sch_fq_pie.c @@ -287,10 +287,9 @@ static struct sk_buff *fq_pie_qdisc_dequeue(struct Qdisc *sch) static int fq_pie_change(struct Qdisc *sch, struct nlattr *opt, struct netlink_ext_ack *extack) { + unsigned int dropped_pkts = 0, dropped_bytes = 0; struct fq_pie_sched_data *q = qdisc_priv(sch); struct nlattr *tb[TCA_FQ_PIE_MAX + 1]; - unsigned int len_dropped = 0; - unsigned int num_dropped = 0; int err;
err = nla_parse_nested(tb, TCA_FQ_PIE_MAX, opt, fq_pie_policy, extack); @@ -368,11 +367,14 @@ static int fq_pie_change(struct Qdisc *sch, struct nlattr *opt, while (sch->q.qlen > sch->limit) { struct sk_buff *skb = qdisc_dequeue_internal(sch, false);
- len_dropped += qdisc_pkt_len(skb); - num_dropped += 1; + if (!skb) + break; + + dropped_pkts++; + dropped_bytes += qdisc_pkt_len(skb); rtnl_kfree_skbs(skb, skb); } - qdisc_tree_reduce_backlog(sch, num_dropped, len_dropped); + qdisc_tree_reduce_backlog(sch, dropped_pkts, dropped_bytes);
sch_tree_unlock(sch); return 0; diff --git a/net/sched/sch_hhf.c b/net/sched/sch_hhf.c index 5aa434b46707..2d4855e28a28 100644 --- a/net/sched/sch_hhf.c +++ b/net/sched/sch_hhf.c @@ -508,9 +508,9 @@ static const struct nla_policy hhf_policy[TCA_HHF_MAX + 1] = { static int hhf_change(struct Qdisc *sch, struct nlattr *opt, struct netlink_ext_ack *extack) { + unsigned int dropped_pkts = 0, dropped_bytes = 0; struct hhf_sched_data *q = qdisc_priv(sch); struct nlattr *tb[TCA_HHF_MAX + 1]; - unsigned int qlen, prev_backlog; int err; u64 non_hh_quantum; u32 new_quantum = q->quantum; @@ -561,15 +561,17 @@ static int hhf_change(struct Qdisc *sch, struct nlattr *opt, usecs_to_jiffies(us)); }
- qlen = sch->q.qlen; - prev_backlog = sch->qstats.backlog; while (sch->q.qlen > sch->limit) { struct sk_buff *skb = qdisc_dequeue_internal(sch, false);
+ if (!skb) + break; + + dropped_pkts++; + dropped_bytes += qdisc_pkt_len(skb); rtnl_kfree_skbs(skb, skb); } - qdisc_tree_reduce_backlog(sch, qlen - sch->q.qlen, - prev_backlog - sch->qstats.backlog); + qdisc_tree_reduce_backlog(sch, dropped_pkts, dropped_bytes);
sch_tree_unlock(sch); return 0; diff --git a/net/sched/sch_pie.c b/net/sched/sch_pie.c index ad46ee3ed5a9..0a377313b6a9 100644 --- a/net/sched/sch_pie.c +++ b/net/sched/sch_pie.c @@ -141,9 +141,9 @@ static const struct nla_policy pie_policy[TCA_PIE_MAX + 1] = { static int pie_change(struct Qdisc *sch, struct nlattr *opt, struct netlink_ext_ack *extack) { + unsigned int dropped_pkts = 0, dropped_bytes = 0; struct pie_sched_data *q = qdisc_priv(sch); struct nlattr *tb[TCA_PIE_MAX + 1]; - unsigned int qlen, dropped = 0; int err;
err = nla_parse_nested_deprecated(tb, TCA_PIE_MAX, opt, pie_policy, @@ -193,15 +193,17 @@ static int pie_change(struct Qdisc *sch, struct nlattr *opt, nla_get_u32(tb[TCA_PIE_DQ_RATE_ESTIMATOR]));
/* Drop excess packets if new limit is lower */ - qlen = sch->q.qlen; while (sch->q.qlen > sch->limit) { struct sk_buff *skb = qdisc_dequeue_internal(sch, true);
- dropped += qdisc_pkt_len(skb); - qdisc_qstats_backlog_dec(sch, skb); + if (!skb) + break; + + dropped_pkts++; + dropped_bytes += qdisc_pkt_len(skb); rtnl_qdisc_drop(skb, sch); } - qdisc_tree_reduce_backlog(sch, qlen - sch->q.qlen, dropped); + qdisc_tree_reduce_backlog(sch, dropped_pkts, dropped_bytes);
sch_tree_unlock(sch); return 0;
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Justin Lai justinlai0215@realtek.com
[ Upstream commit 065c31f2c6915b38f45b1c817b31f41f62eaa774 ]
The CRC error bit is located at bit 17 in the Rx descriptor, but the driver was incorrectly using bit 16. Fix it.
Fixes: a36e9f5cfe9e ("rtase: Add support for a pci table in this module") Signed-off-by: Justin Lai justinlai0215@realtek.com Link: https://patch.msgid.link/20250813071631.7566-1-justinlai0215@realtek.com Signed-off-by: Jakub Kicinski kuba@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/net/ethernet/realtek/rtase/rtase.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/net/ethernet/realtek/rtase/rtase.h b/drivers/net/ethernet/realtek/rtase/rtase.h index 498cfe4d0cac..5f2e1ab6a100 100644 --- a/drivers/net/ethernet/realtek/rtase/rtase.h +++ b/drivers/net/ethernet/realtek/rtase/rtase.h @@ -241,7 +241,7 @@ union rtase_rx_desc { #define RTASE_RX_RES BIT(20) #define RTASE_RX_RUNT BIT(19) #define RTASE_RX_RWT BIT(18) -#define RTASE_RX_CRC BIT(16) +#define RTASE_RX_CRC BIT(17) #define RTASE_RX_V6F BIT(31) #define RTASE_RX_V4F BIT(30) #define RTASE_RX_UDPT BIT(29)
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Dan Carpenter dan.carpenter@linaro.org
[ Upstream commit 9dcf111dd3e7ed5fce82bb108e3a3fc001c07225 ]
The qla4xxx_get_ep_fwdb() function is supposed to return NULL on error, but qla4xxx_ep_connect() returns error pointers. Propagating the error pointers will lead to an Oops in the caller, so change the error pointers to NULL.
Fixes: 13483730a13b ("[SCSI] qla4xxx: fix flash/ddb support") Signed-off-by: Dan Carpenter dan.carpenter@linaro.org Link: https://lore.kernel.org/r/aJwnVKS9tHsw1tEu@stanley.mountain Reviewed-by: Chris Leech cleech@redhat.com Signed-off-by: Martin K. Petersen martin.petersen@oracle.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/scsi/qla4xxx/ql4_os.c | 2 ++ 1 file changed, 2 insertions(+)
diff --git a/drivers/scsi/qla4xxx/ql4_os.c b/drivers/scsi/qla4xxx/ql4_os.c index a39f1da4ce47..a761c0aa5127 100644 --- a/drivers/scsi/qla4xxx/ql4_os.c +++ b/drivers/scsi/qla4xxx/ql4_os.c @@ -6606,6 +6606,8 @@ static struct iscsi_endpoint *qla4xxx_get_ep_fwdb(struct scsi_qla_host *ha,
ep = qla4xxx_ep_connect(ha->host, (struct sockaddr *)dst_addr, 0); vfree(dst_addr); + if (IS_ERR(ep)) + return NULL; return ep; }
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Kees Cook kees@kernel.org
[ Upstream commit 8503d0fcb1086a7cfe26df67ca4bd9bd9e99bdec ]
While the kernel command line is considered trusted in most environments, avoid writing 1 byte past the end of "acpiid" if the "str" argument is maximum length.
Reported-by: Simcha Kosman simcha.kosman@cyberark.com Closes: https://lore.kernel.org/all/AS8P193MB2271C4B24BCEDA31830F37AE84A52@AS8P193MB... Fixes: b6b26d86c61c ("iommu/amd: Add a length limitation for the ivrs_acpihid command-line parameter") Signed-off-by: Kees Cook kees@kernel.org Reviewed-by: Ankit Soni Ankit.Soni@amd.com Link: https://lore.kernel.org/r/20250804154023.work.970-kees@kernel.org Signed-off-by: Joerg Roedel joerg.roedel@amd.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/iommu/amd/init.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/iommu/amd/init.c b/drivers/iommu/amd/init.c index 9c17dfa76703..7add9bcf45dc 100644 --- a/drivers/iommu/amd/init.c +++ b/drivers/iommu/amd/init.c @@ -3596,7 +3596,7 @@ static int __init parse_ivrs_acpihid(char *str) { u32 seg = 0, bus, dev, fn; char *hid, *uid, *p, *addr; - char acpiid[ACPIID_LEN] = {0}; + char acpiid[ACPIID_LEN + 1] = { }; /* size with NULL terminator */ int i;
addr = strchr(str, '@'); @@ -3622,7 +3622,7 @@ static int __init parse_ivrs_acpihid(char *str) /* We have the '@', make it the terminator to get just the acpiid */ *addr++ = 0;
- if (strlen(str) > ACPIID_LEN + 1) + if (strlen(str) > ACPIID_LEN) goto not_found;
if (sscanf(str, "=%s", acpiid) != 1)
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Luiz Augusto von Dentz luiz.von.dentz@intel.com
[ Upstream commit ca88be1a2725a42f8dbad579181611d9dcca8e88 ]
Passive scanning is used to program the address of the peer to be synchronized, so once HCI_EV_LE_PA_SYNC_ESTABLISHED is received it needs to be updated after clearing HCI_PA_SYNC then call hci_update_passive_scan_sync to return it to its original state.
Fixes: 6d0417e4e1cf ("Bluetooth: hci_conn: Fix not setting conn_timeout for Broadcast Receiver") Signed-off-by: Luiz Augusto von Dentz luiz.von.dentz@intel.com Signed-off-by: Sasha Levin sashal@kernel.org --- net/bluetooth/hci_sync.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-)
diff --git a/net/bluetooth/hci_sync.c b/net/bluetooth/hci_sync.c index 7938c004071c..6c3218bac116 100644 --- a/net/bluetooth/hci_sync.c +++ b/net/bluetooth/hci_sync.c @@ -6985,8 +6985,6 @@ static void create_pa_complete(struct hci_dev *hdev, void *data, int err)
hci_dev_lock(hdev);
- hci_dev_clear_flag(hdev, HCI_PA_SYNC); - if (!hci_conn_valid(hdev, conn)) clear_bit(HCI_CONN_CREATE_PA_SYNC, &conn->flags);
@@ -7080,6 +7078,11 @@ static int hci_le_pa_create_sync(struct hci_dev *hdev, void *data) __hci_cmd_sync_status(hdev, HCI_OP_LE_PA_CREATE_SYNC_CANCEL, 0, NULL, HCI_CMD_TIMEOUT);
+ hci_dev_clear_flag(hdev, HCI_PA_SYNC); + + /* Update passive scan since HCI_PA_SYNC flag has been cleared */ + hci_update_passive_scan_sync(hdev); + return err; }
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jiande Lu jiande.lu@mediatek.com
[ Upstream commit 099799fa9b76c5c02b49e07005a85117a25b01ea ]
During the shutdown process, an interrupt occurs that prematurely terminates the wait for the expected event. This change replaces TASK_INTERRUPTIBLE with TASK_UNINTERRUPTIBLE in the wait_on_bit_timeout call to ensure the shutdown process completes as intended without being interrupted by signals.
Fixes: d019930b0049 ("Bluetooth: btmtk: move btusb_mtk_hci_wmt_sync to btmtk.c") Signed-off-by: Jiande Lu jiande.lu@mediatek.com Signed-off-by: Luiz Augusto von Dentz luiz.von.dentz@intel.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/bluetooth/btmtk.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-)
diff --git a/drivers/bluetooth/btmtk.c b/drivers/bluetooth/btmtk.c index 4390fd571dbd..a8c520dc09e1 100644 --- a/drivers/bluetooth/btmtk.c +++ b/drivers/bluetooth/btmtk.c @@ -642,12 +642,7 @@ static int btmtk_usb_hci_wmt_sync(struct hci_dev *hdev, * WMT command. */ err = wait_on_bit_timeout(&data->flags, BTMTK_TX_WAIT_VND_EVT, - TASK_INTERRUPTIBLE, HCI_INIT_TIMEOUT); - if (err == -EINTR) { - bt_dev_err(hdev, "Execution of wmt command interrupted"); - clear_bit(BTMTK_TX_WAIT_VND_EVT, &data->flags); - goto err_free_wc; - } + TASK_UNINTERRUPTIBLE, HCI_INIT_TIMEOUT);
if (err) { bt_dev_err(hdev, "Execution of wmt command timed out");
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Luiz Augusto von Dentz luiz.von.dentz@intel.com
[ Upstream commit 709788b154caf042874d765628ffa860f0bb0d1e ]
{cis,bis}_capable only indicates the controller supports the feature since it doesn't check that LE is enabled so it shall not be used for current setting, instead this introduces {cis,bis}_enabled macros that can be used to indicate that these features are currently enabled.
Fixes: 26afbd826ee3 ("Bluetooth: Add initial implementation of CIS connections") Fixes: eca0ae4aea66 ("Bluetooth: Add initial implementation of BIS connections") Fixes: ae7533613133 ("Bluetooth: Check for ISO support in controller") Signed-off-by: Luiz Augusto von Dentz luiz.von.dentz@intel.com Signed-off-by: Sasha Levin sashal@kernel.org --- include/net/bluetooth/bluetooth.h | 4 ++-- include/net/bluetooth/hci_core.h | 13 ++++++++++++- net/bluetooth/hci_sync.c | 4 ++-- net/bluetooth/iso.c | 14 +++++++------- net/bluetooth/mgmt.c | 10 +++++----- 5 files changed, 28 insertions(+), 17 deletions(-)
diff --git a/include/net/bluetooth/bluetooth.h b/include/net/bluetooth/bluetooth.h index 114299bd8b98..b847cdd2c9d3 100644 --- a/include/net/bluetooth/bluetooth.h +++ b/include/net/bluetooth/bluetooth.h @@ -638,7 +638,7 @@ static inline void sco_exit(void) #if IS_ENABLED(CONFIG_BT_LE) int iso_init(void); int iso_exit(void); -bool iso_enabled(void); +bool iso_inited(void); #else static inline int iso_init(void) { @@ -650,7 +650,7 @@ static inline int iso_exit(void) return 0; }
-static inline bool iso_enabled(void) +static inline bool iso_inited(void) { return false; } diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h index f22881bf1b39..e77cb840deee 100644 --- a/include/net/bluetooth/hci_core.h +++ b/include/net/bluetooth/hci_core.h @@ -1932,6 +1932,8 @@ void hci_conn_del_sysfs(struct hci_conn *conn); !hci_dev_test_flag(dev, HCI_RPA_EXPIRED)) #define adv_rpa_valid(adv) (bacmp(&adv->random_addr, BDADDR_ANY) && \ !adv->rpa_expired) +#define le_enabled(dev) (lmp_le_capable(dev) && \ + hci_dev_test_flag(dev, HCI_LE_ENABLED))
#define scan_1m(dev) (((dev)->le_tx_def_phys & HCI_LE_SET_PHY_1M) || \ ((dev)->le_rx_def_phys & HCI_LE_SET_PHY_1M)) @@ -1998,14 +2000,23 @@ void hci_conn_del_sysfs(struct hci_conn *conn);
/* CIS Master/Slave and BIS support */ #define iso_capable(dev) (cis_capable(dev) || bis_capable(dev)) +#define iso_enabled(dev) (le_enabled(dev) && iso_capable(dev)) #define cis_capable(dev) \ (cis_central_capable(dev) || cis_peripheral_capable(dev)) +#define cis_enabled(dev) (le_enabled(dev) && cis_capable(dev)) #define cis_central_capable(dev) \ ((dev)->le_features[3] & HCI_LE_CIS_CENTRAL) +#define cis_central_enabled(dev) \ + (le_enabled(dev) && cis_central_capable(dev)) #define cis_peripheral_capable(dev) \ ((dev)->le_features[3] & HCI_LE_CIS_PERIPHERAL) +#define cis_peripheral_enabled(dev) \ + (le_enabled(dev) && cis_peripheral_capable(dev)) #define bis_capable(dev) ((dev)->le_features[3] & HCI_LE_ISO_BROADCASTER) -#define sync_recv_capable(dev) ((dev)->le_features[3] & HCI_LE_ISO_SYNC_RECEIVER) +#define bis_enabled(dev) (le_enabled(dev) && bis_capable(dev)) +#define sync_recv_capable(dev) \ + ((dev)->le_features[3] & HCI_LE_ISO_SYNC_RECEIVER) +#define sync_recv_enabled(dev) (le_enabled(dev) && sync_recv_capable(dev))
#define mws_transport_config_capable(dev) (((dev)->commands[30] & 0x08) && \ (!hci_test_quirk((dev), HCI_QUIRK_BROKEN_MWS_TRANSPORT_CONFIG))) diff --git a/net/bluetooth/hci_sync.c b/net/bluetooth/hci_sync.c index 6c3218bac116..892eca21c6c4 100644 --- a/net/bluetooth/hci_sync.c +++ b/net/bluetooth/hci_sync.c @@ -4531,14 +4531,14 @@ static int hci_le_set_host_feature_sync(struct hci_dev *hdev) { struct hci_cp_le_set_host_feature cp;
- if (!cis_capable(hdev)) + if (!iso_capable(hdev)) return 0;
memset(&cp, 0, sizeof(cp));
/* Connected Isochronous Channels (Host Support) */ cp.bit_number = 32; - cp.bit_value = 1; + cp.bit_value = iso_enabled(hdev) ? 0x01 : 0x00;
return __hci_cmd_sync_status(hdev, HCI_OP_LE_SET_HOST_FEATURE, sizeof(cp), &cp, HCI_CMD_TIMEOUT); diff --git a/net/bluetooth/iso.c b/net/bluetooth/iso.c index 3c2c98eecc62..f6fad466d16d 100644 --- a/net/bluetooth/iso.c +++ b/net/bluetooth/iso.c @@ -2455,11 +2455,11 @@ static const struct net_proto_family iso_sock_family_ops = { .create = iso_sock_create, };
-static bool iso_inited; +static bool inited;
-bool iso_enabled(void) +bool iso_inited(void) { - return iso_inited; + return inited; }
int iso_init(void) @@ -2468,7 +2468,7 @@ int iso_init(void)
BUILD_BUG_ON(sizeof(struct sockaddr_iso) > sizeof(struct sockaddr));
- if (iso_inited) + if (inited) return -EALREADY;
err = proto_register(&iso_proto, 0); @@ -2496,7 +2496,7 @@ int iso_init(void) iso_debugfs = debugfs_create_file("iso", 0444, bt_debugfs, NULL, &iso_debugfs_fops);
- iso_inited = true; + inited = true;
return 0;
@@ -2507,7 +2507,7 @@ int iso_init(void)
int iso_exit(void) { - if (!iso_inited) + if (!inited) return -EALREADY;
bt_procfs_cleanup(&init_net, "iso"); @@ -2521,7 +2521,7 @@ int iso_exit(void)
proto_unregister(&iso_proto);
- iso_inited = false; + inited = false;
return 0; } diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c index 63dba0503653..7a75309e6fd4 100644 --- a/net/bluetooth/mgmt.c +++ b/net/bluetooth/mgmt.c @@ -922,16 +922,16 @@ static u32 get_current_settings(struct hci_dev *hdev) if (hci_dev_test_flag(hdev, HCI_WIDEBAND_SPEECH_ENABLED)) settings |= MGMT_SETTING_WIDEBAND_SPEECH;
- if (cis_central_capable(hdev)) + if (cis_central_enabled(hdev)) settings |= MGMT_SETTING_CIS_CENTRAL;
- if (cis_peripheral_capable(hdev)) + if (cis_peripheral_enabled(hdev)) settings |= MGMT_SETTING_CIS_PERIPHERAL;
- if (bis_capable(hdev)) + if (bis_enabled(hdev)) settings |= MGMT_SETTING_ISO_BROADCASTER;
- if (sync_recv_capable(hdev)) + if (sync_recv_enabled(hdev)) settings |= MGMT_SETTING_ISO_SYNC_RECEIVER;
if (ll_privacy_capable(hdev)) @@ -4512,7 +4512,7 @@ static int read_exp_features_info(struct sock *sk, struct hci_dev *hdev, }
if (IS_ENABLED(CONFIG_BT_LE)) { - flags = iso_enabled() ? BIT(0) : 0; + flags = iso_inited() ? BIT(0) : 0; memcpy(rp->features[idx].uuid, iso_socket_uuid, 16); rp->features[idx].flags = cpu_to_le32(flags); idx++;
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Luiz Augusto von Dentz luiz.von.dentz@intel.com
[ Upstream commit 3dcf7175f2c04bd3a7d50db3fa42a0bd933b6e23 ]
ll_privacy_capable only indicates that the controller supports the feature but it doesnt' check that LE is enabled so it end up being marked as active in the current settings when it shouldn't.
Fixes: ad383c2c65a5 ("Bluetooth: hci_sync: Enable advertising when LL privacy is enabled") Signed-off-by: Luiz Augusto von Dentz luiz.von.dentz@intel.com Signed-off-by: Sasha Levin sashal@kernel.org --- include/net/bluetooth/hci_core.h | 1 + net/bluetooth/mgmt.c | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-)
diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h index e77cb840deee..2fcd62fdbc87 100644 --- a/include/net/bluetooth/hci_core.h +++ b/include/net/bluetooth/hci_core.h @@ -1951,6 +1951,7 @@ void hci_conn_del_sysfs(struct hci_conn *conn); ((dev)->le_rx_def_phys & HCI_LE_SET_PHY_CODED))
#define ll_privacy_capable(dev) ((dev)->le_features[0] & HCI_LE_LL_PRIVACY) +#define ll_privacy_enabled(dev) (le_enabled(dev) && ll_privacy_capable(dev))
#define privacy_mode_capable(dev) (ll_privacy_capable(dev) && \ ((dev)->commands[39] & 0x04)) diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c index 7a75309e6fd4..d4405d3d9bc1 100644 --- a/net/bluetooth/mgmt.c +++ b/net/bluetooth/mgmt.c @@ -934,7 +934,7 @@ static u32 get_current_settings(struct hci_dev *hdev) if (sync_recv_enabled(hdev)) settings |= MGMT_SETTING_ISO_SYNC_RECEIVER;
- if (ll_privacy_capable(hdev)) + if (ll_privacy_enabled(hdev)) settings |= MGMT_SETTING_LL_PRIVACY;
return settings;
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Yang Li yang.li@amlogic.com
[ Upstream commit 4d19cd228bbe8ff84a63fe7b11bc756b4b4370c7 ]
After LE Extended Scan times out, conn->sid remains 0xFF, so the PA sync creation process should be aborted.
Btmon snippet from PA sync with SID=0xFF:
< HCI Command: LE Set Extended.. (0x08|0x0042) plen 6 #74726 [hci0] 863.107927 Extended scan: Enabled (0x01) Filter duplicates: Enabled (0x01) Duration: 0 msec (0x0000) Period: 0.00 sec (0x0000)
HCI Event: Command Complete (0x0e) plen 4 #74727 [hci0] 863.109389
LE Set Extended Scan Enable (0x08|0x0042) ncmd 1 Status: Success (0x00) < HCI Command: LE Periodic Ad.. (0x08|0x0044) plen 14 #74728 [hci0] 865.141168 Options: 0x0000 Use advertising SID, Advertiser Address Type and address Reporting initially enabled SID: 0xff Adv address type: Random (0x01) Adv address: 0D:D7:2C:E7:42:46 (Non-Resolvable) Skip: 0x0000 Sync timeout: 20000 msec (0x07d0) Sync CTE type: 0x0000
HCI Event: Command Status (0x0f) plen 4 #74729 [hci0] 865.143223
LE Periodic Advertising Create Sync (0x08|0x0044) ncmd 1 Status: Success (0x00)
Fixes: e2d471b7806b ("Bluetooth: ISO: Fix not using SID from adv report") Signed-off-by: Yang Li yang.li@amlogic.com Signed-off-by: Luiz Augusto von Dentz luiz.von.dentz@intel.com Signed-off-by: Sasha Levin sashal@kernel.org --- net/bluetooth/hci_sync.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-)
diff --git a/net/bluetooth/hci_sync.c b/net/bluetooth/hci_sync.c index 892eca21c6c4..a1b063fde286 100644 --- a/net/bluetooth/hci_sync.c +++ b/net/bluetooth/hci_sync.c @@ -7045,10 +7045,13 @@ static int hci_le_pa_create_sync(struct hci_dev *hdev, void *data) /* SID has not been set listen for HCI_EV_LE_EXT_ADV_REPORT to update * it. */ - if (conn->sid == HCI_SID_INVALID) - __hci_cmd_sync_status_sk(hdev, HCI_OP_NOP, 0, NULL, - HCI_EV_LE_EXT_ADV_REPORT, - conn->conn_timeout, NULL); + if (conn->sid == HCI_SID_INVALID) { + err = __hci_cmd_sync_status_sk(hdev, HCI_OP_NOP, 0, NULL, + HCI_EV_LE_EXT_ADV_REPORT, + conn->conn_timeout, NULL); + if (err == -ETIMEDOUT) + goto done; + }
memset(&cp, 0, sizeof(cp)); cp.options = qos->bcast.options; @@ -7078,6 +7081,7 @@ static int hci_le_pa_create_sync(struct hci_dev *hdev, void *data) __hci_cmd_sync_status(hdev, HCI_OP_LE_PA_CREATE_SYNC_CANCEL, 0, NULL, HCI_CMD_TIMEOUT);
+done: hci_dev_clear_flag(hdev, HCI_PA_SYNC);
/* Update passive scan since HCI_PA_SYNC flag has been cleared */
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Pauli Virtanen pav@iki.fi
[ Upstream commit 0b3725dbf61b51e7c663834811b3691157ae17d6 ]
BN == 0x00 in CIS Established means no isochronous data for the corresponding direction (Core v6.1 pp. 2394). In this case SDU MTU should be 0.
However, the specification does not say the Max_PDU_C_To_P or P_To_C are then zero. Intel AX210 in Framed CIS mode sets nonzero Max_PDU for direction with zero BN. This causes failure later when we try to LE Setup ISO Data Path for disabled direction, which is disallowed (Core v6.1 pp. 2750).
Fix by setting SDU MTU to 0 if BN == 0.
Fixes: 2be22f1941d5f ("Bluetooth: hci_event: Fix parsing of CIS Established Event") Signed-off-by: Pauli Virtanen pav@iki.fi Reviewed-by: Paul Menzel pmenzel@molgen.mpg.de Signed-off-by: Luiz Augusto von Dentz luiz.von.dentz@intel.com Signed-off-by: Sasha Levin sashal@kernel.org --- net/bluetooth/hci_event.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index b83995898da0..f93509007e92 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c @@ -6744,8 +6744,8 @@ static void hci_le_cis_estabilished_evt(struct hci_dev *hdev, void *data, qos->ucast.out.latency = DIV_ROUND_CLOSEST(get_unaligned_le24(ev->p_latency), 1000); - qos->ucast.in.sdu = le16_to_cpu(ev->c_mtu); - qos->ucast.out.sdu = le16_to_cpu(ev->p_mtu); + qos->ucast.in.sdu = ev->c_bn ? le16_to_cpu(ev->c_mtu) : 0; + qos->ucast.out.sdu = ev->p_bn ? le16_to_cpu(ev->p_mtu) : 0; qos->ucast.in.phy = ev->c_phy; qos->ucast.out.phy = ev->p_phy; break; @@ -6759,8 +6759,8 @@ static void hci_le_cis_estabilished_evt(struct hci_dev *hdev, void *data, qos->ucast.in.latency = DIV_ROUND_CLOSEST(get_unaligned_le24(ev->p_latency), 1000); - qos->ucast.out.sdu = le16_to_cpu(ev->c_mtu); - qos->ucast.in.sdu = le16_to_cpu(ev->p_mtu); + qos->ucast.out.sdu = ev->c_bn ? le16_to_cpu(ev->c_mtu) : 0; + qos->ucast.in.sdu = ev->p_bn ? le16_to_cpu(ev->p_mtu) : 0; qos->ucast.out.phy = ev->c_phy; qos->ucast.in.phy = ev->p_phy; break;
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sergey Shtylyov s.shtylyov@omp.ru
[ Upstream commit 0eaf7c7e85da7495c0e03a99375707fc954f5e7b ]
The commit e07a06b4eb41 ("Bluetooth: Convert SCO configure_datapath to hci_sync") missed to update the *return* statement under the *case* of BT_CODEC_TRANSPARENT in hci_enhanced_setup_sync(), which led to returning success (0) instead of the negative error code (-EINVAL). However, the result of hci_enhanced_setup_sync() seems to be ignored anyway, since NULL gets passed to hci_cmd_sync_queue() as the last argument in that case and the only function interested in that result is specified by that argument.
Fixes: e07a06b4eb41 ("Bluetooth: Convert SCO configure_datapath to hci_sync") Signed-off-by: Sergey Shtylyov s.shtylyov@omp.ru Reviewed-by: Paul Menzel pmenzel@molgen.mpg.de Signed-off-by: Luiz Augusto von Dentz luiz.von.dentz@intel.com Signed-off-by: Sasha Levin sashal@kernel.org --- net/bluetooth/hci_conn.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c index f5cd935490ad..2d4cbc483e77 100644 --- a/net/bluetooth/hci_conn.c +++ b/net/bluetooth/hci_conn.c @@ -339,7 +339,8 @@ static int hci_enhanced_setup_sync(struct hci_dev *hdev, void *data) case BT_CODEC_TRANSPARENT: if (!find_next_esco_param(conn, esco_param_msbc, ARRAY_SIZE(esco_param_msbc))) - return false; + return -EINVAL; + param = &esco_param_msbc[conn->attempt - 1]; cp.tx_coding_format.id = 0x03; cp.rx_coding_format.id = 0x03;
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Yang Li yang.li@amlogic.com
[ Upstream commit a7bcffc673de219af2698fbb90627016233de67b ]
Currently, BIS_LINK is used for both BIG sync and PA sync connections, which makes it impossible to distinguish them when searching for a PA sync connection.
Adding PA_LINK will make the distinction clearer and simplify future extensions for PA-related features.
Signed-off-by: Yang Li yang.li@amlogic.com Signed-off-by: Luiz Augusto von Dentz luiz.von.dentz@intel.com Stable-dep-of: 9d4b01a0bf8d ("Bluetooth: hci_core: Fix not accounting for BIS/CIS/PA links separately") Signed-off-by: Sasha Levin sashal@kernel.org --- include/net/bluetooth/hci.h | 1 + include/net/bluetooth/hci_core.h | 10 +++++++--- net/bluetooth/hci_conn.c | 14 +++++++++----- net/bluetooth/hci_core.c | 27 +++++++++++++++------------ net/bluetooth/hci_event.c | 7 ++++--- net/bluetooth/hci_sync.c | 10 +++++----- net/bluetooth/iso.c | 6 ++++-- net/bluetooth/mgmt.c | 1 + 8 files changed, 46 insertions(+), 30 deletions(-)
diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h index 8fa829873134..7d1ba92b71f6 100644 --- a/include/net/bluetooth/hci.h +++ b/include/net/bluetooth/hci.h @@ -562,6 +562,7 @@ enum { #define LE_LINK 0x80 #define CIS_LINK 0x82 #define BIS_LINK 0x83 +#define PA_LINK 0x84 #define INVALID_LINK 0xff
/* LMP features */ diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h index 2fcd62fdbc87..459f26d63451 100644 --- a/include/net/bluetooth/hci_core.h +++ b/include/net/bluetooth/hci_core.h @@ -1015,6 +1015,7 @@ static inline void hci_conn_hash_add(struct hci_dev *hdev, struct hci_conn *c) break; case CIS_LINK: case BIS_LINK: + case PA_LINK: h->iso_num++; break; } @@ -1042,6 +1043,7 @@ static inline void hci_conn_hash_del(struct hci_dev *hdev, struct hci_conn *c) break; case CIS_LINK: case BIS_LINK: + case PA_LINK: h->iso_num--; break; } @@ -1060,6 +1062,7 @@ static inline unsigned int hci_conn_num(struct hci_dev *hdev, __u8 type) return h->sco_num; case CIS_LINK: case BIS_LINK: + case PA_LINK: return h->iso_num; default: return 0; @@ -1142,7 +1145,7 @@ hci_conn_hash_lookup_create_pa_sync(struct hci_dev *hdev) rcu_read_lock();
list_for_each_entry_rcu(c, &h->list, list) { - if (c->type != BIS_LINK) + if (c->type != PA_LINK) continue;
if (!test_bit(HCI_CONN_CREATE_PA_SYNC, &c->flags)) @@ -1337,7 +1340,7 @@ hci_conn_hash_lookup_big_sync_pend(struct hci_dev *hdev, rcu_read_lock();
list_for_each_entry_rcu(c, &h->list, list) { - if (c->type != BIS_LINK) + if (c->type != PA_LINK) continue;
if (handle == c->iso_qos.bcast.big && num_bis == c->num_bis) { @@ -1407,7 +1410,7 @@ hci_conn_hash_lookup_pa_sync_handle(struct hci_dev *hdev, __u16 sync_handle) rcu_read_lock();
list_for_each_entry_rcu(c, &h->list, list) { - if (c->type != BIS_LINK) + if (c->type != PA_LINK) continue;
/* Ignore the listen hcon, we are looking @@ -2038,6 +2041,7 @@ static inline int hci_proto_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr,
case CIS_LINK: case BIS_LINK: + case PA_LINK: return iso_connect_ind(hdev, bdaddr, flags);
default: diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c index 2d4cbc483e77..6a064a6b0e43 100644 --- a/net/bluetooth/hci_conn.c +++ b/net/bluetooth/hci_conn.c @@ -786,7 +786,7 @@ static int hci_le_big_terminate(struct hci_dev *hdev, u8 big, struct hci_conn *c d->sync_handle = conn->sync_handle;
if (test_and_clear_bit(HCI_CONN_PA_SYNC, &conn->flags)) { - hci_conn_hash_list_flag(hdev, find_bis, BIS_LINK, + hci_conn_hash_list_flag(hdev, find_bis, PA_LINK, HCI_CONN_PA_SYNC, d);
if (!d->count) @@ -915,6 +915,7 @@ static struct hci_conn *__hci_conn_add(struct hci_dev *hdev, int type, bdaddr_t break; case CIS_LINK: case BIS_LINK: + case PA_LINK: if (hdev->iso_mtu) /* Dedicated ISO Buffer exists */ break; @@ -980,6 +981,7 @@ static struct hci_conn *__hci_conn_add(struct hci_dev *hdev, int type, bdaddr_t break; case CIS_LINK: case BIS_LINK: + case PA_LINK: /* conn->src should reflect the local identity address */ hci_copy_identity_address(hdev, &conn->src, &conn->src_type);
@@ -1034,7 +1036,6 @@ static struct hci_conn *__hci_conn_add(struct hci_dev *hdev, int type, bdaddr_t }
hci_conn_init_sysfs(conn); - return conn; }
@@ -1078,6 +1079,7 @@ static void hci_conn_cleanup_child(struct hci_conn *conn, u8 reason) break; case CIS_LINK: case BIS_LINK: + case PA_LINK: if ((conn->state != BT_CONNECTED && !test_bit(HCI_CONN_CREATE_CIS, &conn->flags)) || test_bit(HCI_CONN_BIG_CREATED, &conn->flags)) @@ -1153,7 +1155,8 @@ void hci_conn_del(struct hci_conn *conn) } else { /* Unacked ISO frames */ if (conn->type == CIS_LINK || - conn->type == BIS_LINK) { + conn->type == BIS_LINK || + conn->type == PA_LINK) { if (hdev->iso_pkts) hdev->iso_cnt += conn->sent; else if (hdev->le_pkts) @@ -2082,7 +2085,7 @@ struct hci_conn *hci_pa_create_sync(struct hci_dev *hdev, bdaddr_t *dst,
bt_dev_dbg(hdev, "dst %pMR type %d sid %d", dst, dst_type, sid);
- conn = hci_conn_add_unset(hdev, BIS_LINK, dst, HCI_ROLE_SLAVE); + conn = hci_conn_add_unset(hdev, PA_LINK, dst, HCI_ROLE_SLAVE); if (IS_ERR(conn)) return conn;
@@ -2247,7 +2250,7 @@ struct hci_conn *hci_connect_bis(struct hci_dev *hdev, bdaddr_t *dst, * the start periodic advertising and create BIG commands have * been queued */ - hci_conn_hash_list_state(hdev, bis_mark_per_adv, BIS_LINK, + hci_conn_hash_list_state(hdev, bis_mark_per_adv, PA_LINK, BT_BOUND, &data);
/* Queue start periodic advertising and create BIG */ @@ -2981,6 +2984,7 @@ void hci_conn_tx_queue(struct hci_conn *conn, struct sk_buff *skb) switch (conn->type) { case CIS_LINK: case BIS_LINK: + case PA_LINK: case ACL_LINK: case LE_LINK: break; diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c index 441cb1700f99..0aa8a591ce42 100644 --- a/net/bluetooth/hci_core.c +++ b/net/bluetooth/hci_core.c @@ -2938,12 +2938,14 @@ int hci_recv_frame(struct hci_dev *hdev, struct sk_buff *skb) case HCI_ACLDATA_PKT: /* Detect if ISO packet has been sent as ACL */ if (hci_conn_num(hdev, CIS_LINK) || - hci_conn_num(hdev, BIS_LINK)) { + hci_conn_num(hdev, BIS_LINK) || + hci_conn_num(hdev, PA_LINK)) { __u16 handle = __le16_to_cpu(hci_acl_hdr(skb)->handle); __u8 type;
type = hci_conn_lookup_type(hdev, hci_handle(handle)); - if (type == CIS_LINK || type == BIS_LINK) + if (type == CIS_LINK || type == BIS_LINK || + type == PA_LINK) hci_skb_pkt_type(skb) = HCI_ISODATA_PKT; } break; @@ -3398,6 +3400,7 @@ static inline void hci_quote_sent(struct hci_conn *conn, int num, int *quote) break; case CIS_LINK: case BIS_LINK: + case PA_LINK: cnt = hdev->iso_mtu ? hdev->iso_cnt : hdev->le_mtu ? hdev->le_cnt : hdev->acl_cnt; break; @@ -3411,7 +3414,7 @@ static inline void hci_quote_sent(struct hci_conn *conn, int num, int *quote) }
static struct hci_conn *hci_low_sent(struct hci_dev *hdev, __u8 type, - __u8 type2, int *quote) + int *quote) { struct hci_conn_hash *h = &hdev->conn_hash; struct hci_conn *conn = NULL, *c; @@ -3423,7 +3426,7 @@ static struct hci_conn *hci_low_sent(struct hci_dev *hdev, __u8 type, rcu_read_lock();
list_for_each_entry_rcu(c, &h->list, list) { - if ((c->type != type && c->type != type2) || + if (c->type != type || skb_queue_empty(&c->data_q)) continue;
@@ -3627,7 +3630,7 @@ static void hci_sched_sco(struct hci_dev *hdev, __u8 type) else cnt = &hdev->sco_cnt;
- while (*cnt && (conn = hci_low_sent(hdev, type, type, "e))) { + while (*cnt && (conn = hci_low_sent(hdev, type, "e))) { while (quote-- && (skb = skb_dequeue(&conn->data_q))) { BT_DBG("skb %p len %d", skb, skb->len); hci_send_conn_frame(hdev, conn, skb); @@ -3746,8 +3749,8 @@ static void hci_sched_le(struct hci_dev *hdev) hci_prio_recalculate(hdev, LE_LINK); }
-/* Schedule CIS */ -static void hci_sched_iso(struct hci_dev *hdev) +/* Schedule iso */ +static void hci_sched_iso(struct hci_dev *hdev, __u8 type) { struct hci_conn *conn; struct sk_buff *skb; @@ -3755,14 +3758,12 @@ static void hci_sched_iso(struct hci_dev *hdev)
BT_DBG("%s", hdev->name);
- if (!hci_conn_num(hdev, CIS_LINK) && - !hci_conn_num(hdev, BIS_LINK)) + if (!hci_conn_num(hdev, type)) return;
cnt = hdev->iso_pkts ? &hdev->iso_cnt : hdev->le_pkts ? &hdev->le_cnt : &hdev->acl_cnt; - while (*cnt && (conn = hci_low_sent(hdev, CIS_LINK, BIS_LINK, - "e))) { + while (*cnt && (conn = hci_low_sent(hdev, type, "e))) { while (quote-- && (skb = skb_dequeue(&conn->data_q))) { BT_DBG("skb %p len %d", skb, skb->len); hci_send_conn_frame(hdev, conn, skb); @@ -3787,7 +3788,9 @@ static void hci_tx_work(struct work_struct *work) /* Schedule queues and send stuff to HCI driver */ hci_sched_sco(hdev, SCO_LINK); hci_sched_sco(hdev, ESCO_LINK); - hci_sched_iso(hdev); + hci_sched_iso(hdev, CIS_LINK); + hci_sched_iso(hdev, BIS_LINK); + hci_sched_iso(hdev, PA_LINK); hci_sched_acl(hdev); hci_sched_le(hdev); } diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index f93509007e92..5ef54853bc5e 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c @@ -4432,6 +4432,7 @@ static void hci_num_comp_pkts_evt(struct hci_dev *hdev, void *data,
case CIS_LINK: case BIS_LINK: + case PA_LINK: if (hdev->iso_pkts) { hdev->iso_cnt += count; if (hdev->iso_cnt > hdev->iso_pkts) @@ -6381,7 +6382,7 @@ static void hci_le_pa_sync_estabilished_evt(struct hci_dev *hdev, void *data, conn->sync_handle = le16_to_cpu(ev->handle); conn->sid = HCI_SID_INVALID;
- mask |= hci_proto_connect_ind(hdev, &ev->bdaddr, BIS_LINK, + mask |= hci_proto_connect_ind(hdev, &ev->bdaddr, PA_LINK, &flags); if (!(mask & HCI_LM_ACCEPT)) { hci_le_pa_term_sync(hdev, ev->handle); @@ -6392,7 +6393,7 @@ static void hci_le_pa_sync_estabilished_evt(struct hci_dev *hdev, void *data, goto unlock;
/* Add connection to indicate PA sync event */ - pa_sync = hci_conn_add_unset(hdev, BIS_LINK, BDADDR_ANY, + pa_sync = hci_conn_add_unset(hdev, PA_LINK, BDADDR_ANY, HCI_ROLE_SLAVE);
if (IS_ERR(pa_sync)) @@ -6423,7 +6424,7 @@ static void hci_le_per_adv_report_evt(struct hci_dev *hdev, void *data,
hci_dev_lock(hdev);
- mask |= hci_proto_connect_ind(hdev, BDADDR_ANY, BIS_LINK, &flags); + mask |= hci_proto_connect_ind(hdev, BDADDR_ANY, PA_LINK, &flags); if (!(mask & HCI_LM_ACCEPT)) goto unlock;
diff --git a/net/bluetooth/hci_sync.c b/net/bluetooth/hci_sync.c index a1b063fde286..115dc1cd99ce 100644 --- a/net/bluetooth/hci_sync.c +++ b/net/bluetooth/hci_sync.c @@ -2929,7 +2929,7 @@ static int hci_le_set_ext_scan_param_sync(struct hci_dev *hdev, u8 type, if (sent) { struct hci_conn *conn;
- conn = hci_conn_hash_lookup_ba(hdev, BIS_LINK, + conn = hci_conn_hash_lookup_ba(hdev, PA_LINK, &sent->bdaddr); if (conn) { struct bt_iso_qos *qos = &conn->iso_qos; @@ -5493,7 +5493,7 @@ static int hci_disconnect_sync(struct hci_dev *hdev, struct hci_conn *conn, { struct hci_cp_disconnect cp;
- if (conn->type == BIS_LINK) { + if (conn->type == BIS_LINK || conn->type == PA_LINK) { /* This is a BIS connection, hci_conn_del will * do the necessary cleanup. */ @@ -5562,7 +5562,7 @@ static int hci_connect_cancel_sync(struct hci_dev *hdev, struct hci_conn *conn, return HCI_ERROR_LOCAL_HOST_TERM; }
- if (conn->type == BIS_LINK) { + if (conn->type == BIS_LINK || conn->type == PA_LINK) { /* There is no way to cancel a BIS without terminating the BIG * which is done later on connection cleanup. */ @@ -5627,7 +5627,7 @@ static int hci_reject_conn_sync(struct hci_dev *hdev, struct hci_conn *conn, if (conn->type == CIS_LINK) return hci_le_reject_cis_sync(hdev, conn, reason);
- if (conn->type == BIS_LINK) + if (conn->type == BIS_LINK || conn->type == PA_LINK) return -EINVAL;
if (conn->type == SCO_LINK || conn->type == ESCO_LINK) @@ -6992,7 +6992,7 @@ static void create_pa_complete(struct hci_dev *hdev, void *data, int err) goto unlock;
/* Add connection to indicate PA sync error */ - pa_sync = hci_conn_add_unset(hdev, BIS_LINK, BDADDR_ANY, + pa_sync = hci_conn_add_unset(hdev, PA_LINK, BDADDR_ANY, HCI_ROLE_SLAVE);
if (IS_ERR(pa_sync)) diff --git a/net/bluetooth/iso.c b/net/bluetooth/iso.c index f6fad466d16d..14a4215352d5 100644 --- a/net/bluetooth/iso.c +++ b/net/bluetooth/iso.c @@ -2226,7 +2226,8 @@ int iso_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr, __u8 *flags)
static void iso_connect_cfm(struct hci_conn *hcon, __u8 status) { - if (hcon->type != CIS_LINK && hcon->type != BIS_LINK) { + if (hcon->type != CIS_LINK && hcon->type != BIS_LINK && + hcon->type != PA_LINK) { if (hcon->type != LE_LINK) return;
@@ -2267,7 +2268,8 @@ static void iso_connect_cfm(struct hci_conn *hcon, __u8 status)
static void iso_disconn_cfm(struct hci_conn *hcon, __u8 reason) { - if (hcon->type != CIS_LINK && hcon->type != BIS_LINK) + if (hcon->type != CIS_LINK && hcon->type != BIS_LINK && + hcon->type != PA_LINK) return;
BT_DBG("hcon %p reason %d", hcon, reason); diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c index d4405d3d9bc1..3166f5fb876b 100644 --- a/net/bluetooth/mgmt.c +++ b/net/bluetooth/mgmt.c @@ -3237,6 +3237,7 @@ static u8 link_to_bdaddr(u8 link_type, u8 addr_type) switch (link_type) { case CIS_LINK: case BIS_LINK: + case PA_LINK: case LE_LINK: switch (addr_type) { case ADDR_LE_DEV_PUBLIC:
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Luiz Augusto von Dentz luiz.von.dentz@intel.com
[ Upstream commit 9d4b01a0bf8d2163ae129c9c537cb0753ad5a2aa ]
This fixes the likes of hci_conn_num(CIS_LINK) returning the total of ISO connection which includes BIS_LINK as well, so this splits the iso_num into each link type and introduces hci_iso_num that can be used in places where the total number of ISO connection still needs to be used.
Fixes: 23205562ffc8 ("Bluetooth: separate CIS_LINK and BIS_LINK link types") Fixes: a7bcffc673de ("Bluetooth: Add PA_LINK to distinguish BIG sync and PA sync connections") Signed-off-by: Luiz Augusto von Dentz luiz.von.dentz@intel.com Signed-off-by: Sasha Levin sashal@kernel.org --- include/net/bluetooth/hci_core.h | 30 +++++++++++++++++++++++++----- 1 file changed, 25 insertions(+), 5 deletions(-)
diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h index 459f26d63451..439bc124ce70 100644 --- a/include/net/bluetooth/hci_core.h +++ b/include/net/bluetooth/hci_core.h @@ -129,7 +129,9 @@ struct hci_conn_hash { struct list_head list; unsigned int acl_num; unsigned int sco_num; - unsigned int iso_num; + unsigned int cis_num; + unsigned int bis_num; + unsigned int pa_num; unsigned int le_num; unsigned int le_num_peripheral; }; @@ -1014,9 +1016,13 @@ static inline void hci_conn_hash_add(struct hci_dev *hdev, struct hci_conn *c) h->sco_num++; break; case CIS_LINK: + h->cis_num++; + break; case BIS_LINK: + h->bis_num++; + break; case PA_LINK: - h->iso_num++; + h->pa_num++; break; } } @@ -1042,9 +1048,13 @@ static inline void hci_conn_hash_del(struct hci_dev *hdev, struct hci_conn *c) h->sco_num--; break; case CIS_LINK: + h->cis_num--; + break; case BIS_LINK: + h->bis_num--; + break; case PA_LINK: - h->iso_num--; + h->pa_num--; break; } } @@ -1061,9 +1071,11 @@ static inline unsigned int hci_conn_num(struct hci_dev *hdev, __u8 type) case ESCO_LINK: return h->sco_num; case CIS_LINK: + return h->cis_num; case BIS_LINK: + return h->bis_num; case PA_LINK: - return h->iso_num; + return h->pa_num; default: return 0; } @@ -1073,7 +1085,15 @@ static inline unsigned int hci_conn_count(struct hci_dev *hdev) { struct hci_conn_hash *c = &hdev->conn_hash;
- return c->acl_num + c->sco_num + c->le_num + c->iso_num; + return c->acl_num + c->sco_num + c->le_num + c->cis_num + c->bis_num + + c->pa_num; +} + +static inline unsigned int hci_iso_count(struct hci_dev *hdev) +{ + struct hci_conn_hash *c = &hdev->conn_hash; + + return c->cis_num + c->bis_num; }
static inline bool hci_conn_valid(struct hci_dev *hdev, struct hci_conn *conn)
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ido Schimmel idosch@nvidia.com
[ Upstream commit f604d3aaf64ff0d90cc875295474d3abf4155629 ]
By default, the device does not forward IPv4 packets with a link-local source IP (i.e., 169.254.0.0/16). This behavior does not align with the kernel which does forward them.
Fix by instructing the device to forward such packets instead of dropping them.
Fixes: ca360db4b825 ("mlxsw: spectrum: Disable DIP_LINK_LOCAL check in hardware pipeline") Reported-by: Zoey Mertes zoey@cloudflare.com Signed-off-by: Ido Schimmel idosch@nvidia.com Reviewed-by: Petr Machata petrm@nvidia.com Signed-off-by: Petr Machata petrm@nvidia.com Link: https://patch.msgid.link/6721e6b2c96feb80269e72ce8d0b426e2f32d99c.1755174341... Signed-off-by: Jakub Kicinski kuba@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/net/ethernet/mellanox/mlxsw/spectrum.c | 2 ++ drivers/net/ethernet/mellanox/mlxsw/trap.h | 1 + 2 files changed, 3 insertions(+)
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c index 618957d65663..9a2d64a0a858 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c @@ -2375,6 +2375,8 @@ static const struct mlxsw_listener mlxsw_sp_listener[] = { ROUTER_EXP, false), MLXSW_SP_RXL_NO_MARK(DISCARD_ING_ROUTER_DIP_LINK_LOCAL, FORWARD, ROUTER_EXP, false), + MLXSW_SP_RXL_NO_MARK(DISCARD_ING_ROUTER_SIP_LINK_LOCAL, FORWARD, + ROUTER_EXP, false), /* Multicast Router Traps */ MLXSW_SP_RXL_MARK(ACL1, TRAP_TO_CPU, MULTICAST, false), MLXSW_SP_RXL_L3_MARK(ACL2, TRAP_TO_CPU, MULTICAST, false), diff --git a/drivers/net/ethernet/mellanox/mlxsw/trap.h b/drivers/net/ethernet/mellanox/mlxsw/trap.h index 80ee5c4825dc..9962dc157901 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/trap.h +++ b/drivers/net/ethernet/mellanox/mlxsw/trap.h @@ -94,6 +94,7 @@ enum { MLXSW_TRAP_ID_DISCARD_ING_ROUTER_IPV4_SIP_BC = 0x16A, MLXSW_TRAP_ID_DISCARD_ING_ROUTER_IPV4_DIP_LOCAL_NET = 0x16B, MLXSW_TRAP_ID_DISCARD_ING_ROUTER_DIP_LINK_LOCAL = 0x16C, + MLXSW_TRAP_ID_DISCARD_ING_ROUTER_SIP_LINK_LOCAL = 0x16D, MLXSW_TRAP_ID_DISCARD_ROUTER_IRIF_EN = 0x178, MLXSW_TRAP_ID_DISCARD_ROUTER_ERIF_EN = 0x179, MLXSW_TRAP_ID_DISCARD_ROUTER_LPM4 = 0x17B,
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Miguel Ojeda ojeda@kernel.org
[ Upstream commit db2e7bcee11cd57f95fef3c6cbb562d0577eb84a ]
In 32-bit arm, the build fails with:
error[E0308]: mismatched types --> drivers/gpu/drm/nova/file.rs:42:28 | 42 | getparam.set_value(value); | --------- ^^^^^ expected `u64`, found `u32` | | | arguments to this method are incorrect | note: method defined here --> drivers/gpu/drm/nova/uapi.rs:29:12 | 29 | pub fn set_value(&self, v: u64) { | ^^^^^^^^^ ------ help: you can convert a `u32` to a `u64` | 42 | getparam.set_value(value.into()); | +++++++
The reason is that `Getparam::set_value` takes a `u64` (from the UAPI), but `pci::Device::resource_len()` returns a `resource_size_t`, which is a `phys_addr_t`, which may be 32- or 64-bit.
Thus add an `into()` call to support the 32-bit case, while allowing the Clippy lint that complains in the 64-bit case where the type is the same.
Fixes: cdeaeb9dd762 ("drm: nova-drm: add initial driver skeleton") Signed-off-by: Miguel Ojeda ojeda@kernel.org Reviewed-by: Christian Schrefl chrisi.schrefl@gmail.com Link: https://lore.kernel.org/r/20250724165441.2105632-1-ojeda@kernel.org Signed-off-by: Danilo Krummrich dakr@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/gpu/drm/nova/file.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/nova/file.rs b/drivers/gpu/drm/nova/file.rs index 7e59a34b830d..4fe62cf98a23 100644 --- a/drivers/gpu/drm/nova/file.rs +++ b/drivers/gpu/drm/nova/file.rs @@ -39,7 +39,8 @@ impl File { _ => return Err(EINVAL), };
- getparam.set_value(value); + #[allow(clippy::useless_conversion)] + getparam.set_value(value.into());
Ok(0) }
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Li Nan linan122@huawei.com
[ Upstream commit 907a99c314a5a695e35acff78ac61f4ec950a6d3 ]
'recovery_cp' was used to represent the progress of sync, but its name contains recovery, which can cause confusion. Replaces 'recovery_cp' with 'resync_offset' for clarity.
Signed-off-by: Li Nan linan122@huawei.com Link: https://lore.kernel.org/linux-raid/20250722033340.1933388-1-linan666@huaweic... Signed-off-by: Yu Kuai yukuai3@huawei.com Stable-dep-of: b7ee30f0efd1 ("md: fix sync_action incorrect display during resync") Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/md/dm-raid.c | 42 ++++++++++++++-------------- drivers/md/md-bitmap.c | 8 +++--- drivers/md/md-cluster.c | 16 +++++------ drivers/md/md.c | 50 +++++++++++++++++----------------- drivers/md/md.h | 2 +- drivers/md/raid0.c | 6 ++-- drivers/md/raid1-10.c | 2 +- drivers/md/raid1.c | 10 +++---- drivers/md/raid10.c | 16 +++++------ drivers/md/raid5-ppl.c | 6 ++-- drivers/md/raid5.c | 30 ++++++++++---------- include/uapi/linux/raid/md_p.h | 2 +- 12 files changed, 95 insertions(+), 95 deletions(-)
diff --git a/drivers/md/dm-raid.c b/drivers/md/dm-raid.c index e8c0a8c6fb51..9835f2fe26e9 100644 --- a/drivers/md/dm-raid.c +++ b/drivers/md/dm-raid.c @@ -439,7 +439,7 @@ static bool rs_is_reshapable(struct raid_set *rs) /* Return true, if raid set in @rs is recovering */ static bool rs_is_recovering(struct raid_set *rs) { - return rs->md.recovery_cp < rs->md.dev_sectors; + return rs->md.resync_offset < rs->md.dev_sectors; }
/* Return true, if raid set in @rs is reshaping */ @@ -769,7 +769,7 @@ static struct raid_set *raid_set_alloc(struct dm_target *ti, struct raid_type *r rs->md.layout = raid_type->algorithm; rs->md.new_layout = rs->md.layout; rs->md.delta_disks = 0; - rs->md.recovery_cp = MaxSector; + rs->md.resync_offset = MaxSector;
for (i = 0; i < raid_devs; i++) md_rdev_init(&rs->dev[i].rdev); @@ -913,7 +913,7 @@ static int parse_dev_params(struct raid_set *rs, struct dm_arg_set *as) rs->md.external = 0; rs->md.persistent = 1; rs->md.major_version = 2; - } else if (rebuild && !rs->md.recovery_cp) { + } else if (rebuild && !rs->md.resync_offset) { /* * Without metadata, we will not be able to tell if the array * is in-sync or not - we must assume it is not. Therefore, @@ -1696,20 +1696,20 @@ static void rs_setup_recovery(struct raid_set *rs, sector_t dev_sectors) { /* raid0 does not recover */ if (rs_is_raid0(rs)) - rs->md.recovery_cp = MaxSector; + rs->md.resync_offset = MaxSector; /* * A raid6 set has to be recovered either * completely or for the grown part to * ensure proper parity and Q-Syndrome */ else if (rs_is_raid6(rs)) - rs->md.recovery_cp = dev_sectors; + rs->md.resync_offset = dev_sectors; /* * Other raid set types may skip recovery * depending on the 'nosync' flag. */ else - rs->md.recovery_cp = test_bit(__CTR_FLAG_NOSYNC, &rs->ctr_flags) + rs->md.resync_offset = test_bit(__CTR_FLAG_NOSYNC, &rs->ctr_flags) ? MaxSector : dev_sectors; }
@@ -2144,7 +2144,7 @@ static void super_sync(struct mddev *mddev, struct md_rdev *rdev) sb->events = cpu_to_le64(mddev->events);
sb->disk_recovery_offset = cpu_to_le64(rdev->recovery_offset); - sb->array_resync_offset = cpu_to_le64(mddev->recovery_cp); + sb->array_resync_offset = cpu_to_le64(mddev->resync_offset);
sb->level = cpu_to_le32(mddev->level); sb->layout = cpu_to_le32(mddev->layout); @@ -2335,18 +2335,18 @@ static int super_init_validation(struct raid_set *rs, struct md_rdev *rdev) }
if (!test_bit(__CTR_FLAG_NOSYNC, &rs->ctr_flags)) - mddev->recovery_cp = le64_to_cpu(sb->array_resync_offset); + mddev->resync_offset = le64_to_cpu(sb->array_resync_offset);
/* * During load, we set FirstUse if a new superblock was written. * There are two reasons we might not have a superblock: * 1) The raid set is brand new - in which case, all of the * devices must have their In_sync bit set. Also, - * recovery_cp must be 0, unless forced. + * resync_offset must be 0, unless forced. * 2) This is a new device being added to an old raid set * and the new device needs to be rebuilt - in which * case the In_sync bit will /not/ be set and - * recovery_cp must be MaxSector. + * resync_offset must be MaxSector. * 3) This is/are a new device(s) being added to an old * raid set during takeover to a higher raid level * to provide capacity for redundancy or during reshape @@ -2391,8 +2391,8 @@ static int super_init_validation(struct raid_set *rs, struct md_rdev *rdev) new_devs > 1 ? "s" : ""); return -EINVAL; } else if (!test_bit(__CTR_FLAG_REBUILD, &rs->ctr_flags) && rs_is_recovering(rs)) { - DMERR("'rebuild' specified while raid set is not in-sync (recovery_cp=%llu)", - (unsigned long long) mddev->recovery_cp); + DMERR("'rebuild' specified while raid set is not in-sync (resync_offset=%llu)", + (unsigned long long) mddev->resync_offset); return -EINVAL; } else if (rs_is_reshaping(rs)) { DMERR("'rebuild' specified while raid set is being reshaped (reshape_position=%llu)", @@ -2697,11 +2697,11 @@ static int rs_adjust_data_offsets(struct raid_set *rs) } out: /* - * Raise recovery_cp in case data_offset != 0 to + * Raise resync_offset in case data_offset != 0 to * avoid false recovery positives in the constructor. */ - if (rs->md.recovery_cp < rs->md.dev_sectors) - rs->md.recovery_cp += rs->dev[0].rdev.data_offset; + if (rs->md.resync_offset < rs->md.dev_sectors) + rs->md.resync_offset += rs->dev[0].rdev.data_offset;
/* Adjust data offsets on all rdevs but on any raid4/5/6 journal device */ rdev_for_each(rdev, &rs->md) { @@ -2756,7 +2756,7 @@ static int rs_setup_takeover(struct raid_set *rs) }
clear_bit(MD_ARRAY_FIRST_USE, &mddev->flags); - mddev->recovery_cp = MaxSector; + mddev->resync_offset = MaxSector;
while (d--) { rdev = &rs->dev[d].rdev; @@ -2764,7 +2764,7 @@ static int rs_setup_takeover(struct raid_set *rs) if (test_bit(d, (void *) rs->rebuild_disks)) { clear_bit(In_sync, &rdev->flags); clear_bit(Faulty, &rdev->flags); - mddev->recovery_cp = rdev->recovery_offset = 0; + mddev->resync_offset = rdev->recovery_offset = 0; /* Bitmap has to be created when we do an "up" takeover */ set_bit(MD_ARRAY_FIRST_USE, &mddev->flags); } @@ -3222,7 +3222,7 @@ static int raid_ctr(struct dm_target *ti, unsigned int argc, char **argv) if (r) goto bad;
- rs_setup_recovery(rs, rs->md.recovery_cp < rs->md.dev_sectors ? rs->md.recovery_cp : rs->md.dev_sectors); + rs_setup_recovery(rs, rs->md.resync_offset < rs->md.dev_sectors ? rs->md.resync_offset : rs->md.dev_sectors); } else { /* This is no size change or it is shrinking, update size and record in superblocks */ r = rs_set_dev_and_array_sectors(rs, rs->ti->len, false); @@ -3446,7 +3446,7 @@ static sector_t rs_get_progress(struct raid_set *rs, unsigned long recovery,
} else { if (state == st_idle && !test_bit(MD_RECOVERY_INTR, &recovery)) - r = mddev->recovery_cp; + r = mddev->resync_offset; else r = mddev->curr_resync_completed;
@@ -4074,9 +4074,9 @@ static int raid_preresume(struct dm_target *ti) }
/* Check for any resize/reshape on @rs and adjust/initiate */ - if (mddev->recovery_cp && mddev->recovery_cp < MaxSector) { + if (mddev->resync_offset && mddev->resync_offset < MaxSector) { set_bit(MD_RECOVERY_REQUESTED, &mddev->recovery); - mddev->resync_min = mddev->recovery_cp; + mddev->resync_min = mddev->resync_offset; if (test_bit(RT_FLAG_RS_GROW, &rs->runtime_flags)) mddev->resync_max_sectors = mddev->dev_sectors; } diff --git a/drivers/md/md-bitmap.c b/drivers/md/md-bitmap.c index 7f524a26cebc..334b71404930 100644 --- a/drivers/md/md-bitmap.c +++ b/drivers/md/md-bitmap.c @@ -1987,12 +1987,12 @@ static void bitmap_dirty_bits(struct mddev *mddev, unsigned long s,
md_bitmap_set_memory_bits(bitmap, sec, 1); md_bitmap_file_set_bit(bitmap, sec); - if (sec < bitmap->mddev->recovery_cp) + if (sec < bitmap->mddev->resync_offset) /* We are asserting that the array is dirty, - * so move the recovery_cp address back so + * so move the resync_offset address back so * that it is obvious that it is dirty */ - bitmap->mddev->recovery_cp = sec; + bitmap->mddev->resync_offset = sec; } }
@@ -2258,7 +2258,7 @@ static int bitmap_load(struct mddev *mddev) || bitmap->events_cleared == mddev->events) /* no need to keep dirty bits to optimise a * re-add of a missing device */ - start = mddev->recovery_cp; + start = mddev->resync_offset;
mutex_lock(&mddev->bitmap_info.mutex); err = md_bitmap_init_from_disk(bitmap, start); diff --git a/drivers/md/md-cluster.c b/drivers/md/md-cluster.c index 94221d964d4f..5497eaee96e7 100644 --- a/drivers/md/md-cluster.c +++ b/drivers/md/md-cluster.c @@ -337,11 +337,11 @@ static void recover_bitmaps(struct md_thread *thread) md_wakeup_thread(mddev->sync_thread);
if (hi > 0) { - if (lo < mddev->recovery_cp) - mddev->recovery_cp = lo; + if (lo < mddev->resync_offset) + mddev->resync_offset = lo; /* wake up thread to continue resync in case resync * is not finished */ - if (mddev->recovery_cp != MaxSector) { + if (mddev->resync_offset != MaxSector) { /* * clear the REMOTE flag since we will launch * resync thread in current node. @@ -863,9 +863,9 @@ static int gather_all_resync_info(struct mddev *mddev, int total_slots) lockres_free(bm_lockres); continue; } - if ((hi > 0) && (lo < mddev->recovery_cp)) { + if ((hi > 0) && (lo < mddev->resync_offset)) { set_bit(MD_RECOVERY_NEEDED, &mddev->recovery); - mddev->recovery_cp = lo; + mddev->resync_offset = lo; md_check_recovery(mddev); }
@@ -1027,7 +1027,7 @@ static int leave(struct mddev *mddev) * Also, we should send BITMAP_NEEDS_SYNC message in * case reshaping is interrupted. */ - if ((cinfo->slot_number > 0 && mddev->recovery_cp != MaxSector) || + if ((cinfo->slot_number > 0 && mddev->resync_offset != MaxSector) || (mddev->reshape_position != MaxSector && test_bit(MD_CLOSING, &mddev->flags))) resync_bitmap(mddev); @@ -1605,8 +1605,8 @@ static int gather_bitmaps(struct md_rdev *rdev) pr_warn("md-cluster: Could not gather bitmaps from slot %d", sn); goto out; } - if ((hi > 0) && (lo < mddev->recovery_cp)) - mddev->recovery_cp = lo; + if ((hi > 0) && (lo < mddev->resync_offset)) + mddev->resync_offset = lo; } out: return err; diff --git a/drivers/md/md.c b/drivers/md/md.c index 10670c62b09e..80470bcf4383 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -1402,13 +1402,13 @@ static int super_90_validate(struct mddev *mddev, struct md_rdev *freshest, stru mddev->layout = -1;
if (sb->state & (1<<MD_SB_CLEAN)) - mddev->recovery_cp = MaxSector; + mddev->resync_offset = MaxSector; else { if (sb->events_hi == sb->cp_events_hi && sb->events_lo == sb->cp_events_lo) { - mddev->recovery_cp = sb->recovery_cp; + mddev->resync_offset = sb->resync_offset; } else - mddev->recovery_cp = 0; + mddev->resync_offset = 0; }
memcpy(mddev->uuid+0, &sb->set_uuid0, 4); @@ -1534,13 +1534,13 @@ static void super_90_sync(struct mddev *mddev, struct md_rdev *rdev) mddev->minor_version = sb->minor_version; if (mddev->in_sync) { - sb->recovery_cp = mddev->recovery_cp; + sb->resync_offset = mddev->resync_offset; sb->cp_events_hi = (mddev->events>>32); sb->cp_events_lo = (u32)mddev->events; - if (mddev->recovery_cp == MaxSector) + if (mddev->resync_offset == MaxSector) sb->state = (1<< MD_SB_CLEAN); } else - sb->recovery_cp = 0; + sb->resync_offset = 0;
sb->layout = mddev->layout; sb->chunk_size = mddev->chunk_sectors << 9; @@ -1888,7 +1888,7 @@ static int super_1_validate(struct mddev *mddev, struct md_rdev *freshest, struc mddev->bitmap_info.default_space = (4096-1024) >> 9; mddev->reshape_backwards = 0;
- mddev->recovery_cp = le64_to_cpu(sb->resync_offset); + mddev->resync_offset = le64_to_cpu(sb->resync_offset); memcpy(mddev->uuid, sb->set_uuid, 16);
mddev->max_disks = (4096-256)/2; @@ -2074,7 +2074,7 @@ static void super_1_sync(struct mddev *mddev, struct md_rdev *rdev) sb->utime = cpu_to_le64((__u64)mddev->utime); sb->events = cpu_to_le64(mddev->events); if (mddev->in_sync) - sb->resync_offset = cpu_to_le64(mddev->recovery_cp); + sb->resync_offset = cpu_to_le64(mddev->resync_offset); else if (test_bit(MD_JOURNAL_CLEAN, &mddev->flags)) sb->resync_offset = cpu_to_le64(MaxSector); else @@ -2754,7 +2754,7 @@ void md_update_sb(struct mddev *mddev, int force_change) /* If this is just a dirty<->clean transition, and the array is clean * and 'events' is odd, we can roll back to the previous clean state */ if (nospares - && (mddev->in_sync && mddev->recovery_cp == MaxSector) + && (mddev->in_sync && mddev->resync_offset == MaxSector) && mddev->can_decrease_events && mddev->events != 1) { mddev->events--; @@ -4290,9 +4290,9 @@ __ATTR(chunk_size, S_IRUGO|S_IWUSR, chunk_size_show, chunk_size_store); static ssize_t resync_start_show(struct mddev *mddev, char *page) { - if (mddev->recovery_cp == MaxSector) + if (mddev->resync_offset == MaxSector) return sprintf(page, "none\n"); - return sprintf(page, "%llu\n", (unsigned long long)mddev->recovery_cp); + return sprintf(page, "%llu\n", (unsigned long long)mddev->resync_offset); }
static ssize_t @@ -4318,7 +4318,7 @@ resync_start_store(struct mddev *mddev, const char *buf, size_t len) err = -EBUSY;
if (!err) { - mddev->recovery_cp = n; + mddev->resync_offset = n; if (mddev->pers) set_bit(MD_SB_CHANGE_CLEAN, &mddev->sb_flags); } @@ -6405,7 +6405,7 @@ static void md_clean(struct mddev *mddev) mddev->external_size = 0; mddev->dev_sectors = 0; mddev->raid_disks = 0; - mddev->recovery_cp = 0; + mddev->resync_offset = 0; mddev->resync_min = 0; mddev->resync_max = MaxSector; mddev->reshape_position = MaxSector; @@ -7359,9 +7359,9 @@ int md_set_array_info(struct mddev *mddev, struct mdu_array_info_s *info) * openned */ if (info->state & (1<<MD_SB_CLEAN)) - mddev->recovery_cp = MaxSector; + mddev->resync_offset = MaxSector; else - mddev->recovery_cp = 0; + mddev->resync_offset = 0; mddev->persistent = ! info->not_persistent; mddev->external = 0;
@@ -8300,7 +8300,7 @@ static int status_resync(struct seq_file *seq, struct mddev *mddev) seq_printf(seq, "\tresync=REMOTE"); return 1; } - if (mddev->recovery_cp < MaxSector) { + if (mddev->resync_offset < MaxSector) { seq_printf(seq, "\tresync=PENDING"); return 1; } @@ -8943,7 +8943,7 @@ static sector_t md_sync_position(struct mddev *mddev, enum sync_action action) return mddev->resync_min; case ACTION_RESYNC: if (!mddev->bitmap) - return mddev->recovery_cp; + return mddev->resync_offset; return 0; case ACTION_RESHAPE: /* @@ -9181,8 +9181,8 @@ void md_do_sync(struct md_thread *thread) atomic_read(&mddev->recovery_active) == 0); mddev->curr_resync_completed = j; if (test_bit(MD_RECOVERY_SYNC, &mddev->recovery) && - j > mddev->recovery_cp) - mddev->recovery_cp = j; + j > mddev->resync_offset) + mddev->resync_offset = j; update_time = jiffies; set_bit(MD_SB_CHANGE_CLEAN, &mddev->sb_flags); sysfs_notify_dirent_safe(mddev->sysfs_completed); @@ -9302,19 +9302,19 @@ void md_do_sync(struct md_thread *thread) mddev->curr_resync > MD_RESYNC_ACTIVE) { if (test_bit(MD_RECOVERY_SYNC, &mddev->recovery)) { if (test_bit(MD_RECOVERY_INTR, &mddev->recovery)) { - if (mddev->curr_resync >= mddev->recovery_cp) { + if (mddev->curr_resync >= mddev->resync_offset) { pr_debug("md: checkpointing %s of %s.\n", desc, mdname(mddev)); if (test_bit(MD_RECOVERY_ERROR, &mddev->recovery)) - mddev->recovery_cp = + mddev->resync_offset = mddev->curr_resync_completed; else - mddev->recovery_cp = + mddev->resync_offset = mddev->curr_resync; } } else - mddev->recovery_cp = MaxSector; + mddev->resync_offset = MaxSector; } else { if (!test_bit(MD_RECOVERY_INTR, &mddev->recovery)) mddev->curr_resync = MaxSector; @@ -9536,7 +9536,7 @@ static bool md_choose_sync_action(struct mddev *mddev, int *spares) }
/* Check if resync is in progress. */ - if (mddev->recovery_cp < MaxSector) { + if (mddev->resync_offset < MaxSector) { remove_spares(mddev, NULL); set_bit(MD_RECOVERY_SYNC, &mddev->recovery); clear_bit(MD_RECOVERY_RECOVER, &mddev->recovery); @@ -9717,7 +9717,7 @@ void md_check_recovery(struct mddev *mddev) test_bit(MD_RECOVERY_DONE, &mddev->recovery) || (mddev->external == 0 && mddev->safemode == 1) || (mddev->safemode == 2 - && !mddev->in_sync && mddev->recovery_cp == MaxSector) + && !mddev->in_sync && mddev->resync_offset == MaxSector) )) return;
diff --git a/drivers/md/md.h b/drivers/md/md.h index d45a9e6ead80..43ae2d03faa1 100644 --- a/drivers/md/md.h +++ b/drivers/md/md.h @@ -523,7 +523,7 @@ struct mddev { unsigned long normal_io_events; /* IO event timestamp */ atomic_t recovery_active; /* blocks scheduled, but not written */ wait_queue_head_t recovery_wait; - sector_t recovery_cp; + sector_t resync_offset; sector_t resync_min; /* user requested sync * starts here */ sector_t resync_max; /* resync should pause diff --git a/drivers/md/raid0.c b/drivers/md/raid0.c index d8f639f4ae12..613f4fab83b2 100644 --- a/drivers/md/raid0.c +++ b/drivers/md/raid0.c @@ -673,7 +673,7 @@ static void *raid0_takeover_raid45(struct mddev *mddev) mddev->raid_disks--; mddev->delta_disks = -1; /* make sure it will be not marked as dirty */ - mddev->recovery_cp = MaxSector; + mddev->resync_offset = MaxSector; mddev_clear_unsupported_flags(mddev, UNSUPPORTED_MDDEV_FLAGS);
create_strip_zones(mddev, &priv_conf); @@ -716,7 +716,7 @@ static void *raid0_takeover_raid10(struct mddev *mddev) mddev->raid_disks += mddev->delta_disks; mddev->degraded = 0; /* make sure it will be not marked as dirty */ - mddev->recovery_cp = MaxSector; + mddev->resync_offset = MaxSector; mddev_clear_unsupported_flags(mddev, UNSUPPORTED_MDDEV_FLAGS);
create_strip_zones(mddev, &priv_conf); @@ -759,7 +759,7 @@ static void *raid0_takeover_raid1(struct mddev *mddev) mddev->delta_disks = 1 - mddev->raid_disks; mddev->raid_disks = 1; /* make sure it will be not marked as dirty */ - mddev->recovery_cp = MaxSector; + mddev->resync_offset = MaxSector; mddev_clear_unsupported_flags(mddev, UNSUPPORTED_MDDEV_FLAGS);
create_strip_zones(mddev, &priv_conf); diff --git a/drivers/md/raid1-10.c b/drivers/md/raid1-10.c index b8b3a9069701..52881e6032da 100644 --- a/drivers/md/raid1-10.c +++ b/drivers/md/raid1-10.c @@ -283,7 +283,7 @@ static inline int raid1_check_read_range(struct md_rdev *rdev, static inline bool raid1_should_read_first(struct mddev *mddev, sector_t this_sector, int len) { - if ((mddev->recovery_cp < this_sector + len)) + if ((mddev->resync_offset < this_sector + len)) return true;
if (mddev_is_clustered(mddev) && diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c index 64b8176907a9..6cee738a645f 100644 --- a/drivers/md/raid1.c +++ b/drivers/md/raid1.c @@ -2822,7 +2822,7 @@ static sector_t raid1_sync_request(struct mddev *mddev, sector_t sector_nr, }
if (mddev->bitmap == NULL && - mddev->recovery_cp == MaxSector && + mddev->resync_offset == MaxSector && !test_bit(MD_RECOVERY_REQUESTED, &mddev->recovery) && conf->fullsync == 0) { *skipped = 1; @@ -3282,9 +3282,9 @@ static int raid1_run(struct mddev *mddev) }
if (conf->raid_disks - mddev->degraded == 1) - mddev->recovery_cp = MaxSector; + mddev->resync_offset = MaxSector;
- if (mddev->recovery_cp != MaxSector) + if (mddev->resync_offset != MaxSector) pr_info("md/raid1:%s: not clean -- starting background reconstruction\n", mdname(mddev)); pr_info("md/raid1:%s: active with %d out of %d mirrors\n", @@ -3345,8 +3345,8 @@ static int raid1_resize(struct mddev *mddev, sector_t sectors)
md_set_array_sectors(mddev, newsize); if (sectors > mddev->dev_sectors && - mddev->recovery_cp > mddev->dev_sectors) { - mddev->recovery_cp = mddev->dev_sectors; + mddev->resync_offset > mddev->dev_sectors) { + mddev->resync_offset = mddev->dev_sectors; set_bit(MD_RECOVERY_NEEDED, &mddev->recovery); } mddev->dev_sectors = sectors; diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c index 95dc354a86a0..b60c30bfb6c7 100644 --- a/drivers/md/raid10.c +++ b/drivers/md/raid10.c @@ -2117,7 +2117,7 @@ static int raid10_add_disk(struct mddev *mddev, struct md_rdev *rdev) int last = conf->geo.raid_disks - 1; struct raid10_info *p;
- if (mddev->recovery_cp < MaxSector) + if (mddev->resync_offset < MaxSector) /* only hot-add to in-sync arrays, as recovery is * very different from resync */ @@ -3185,7 +3185,7 @@ static sector_t raid10_sync_request(struct mddev *mddev, sector_t sector_nr, * of a clean array, like RAID1 does. */ if (mddev->bitmap == NULL && - mddev->recovery_cp == MaxSector && + mddev->resync_offset == MaxSector && mddev->reshape_position == MaxSector && !test_bit(MD_RECOVERY_SYNC, &mddev->recovery) && !test_bit(MD_RECOVERY_REQUESTED, &mddev->recovery) && @@ -4145,7 +4145,7 @@ static int raid10_run(struct mddev *mddev) disk->recovery_disabled = mddev->recovery_disabled - 1; }
- if (mddev->recovery_cp != MaxSector) + if (mddev->resync_offset != MaxSector) pr_notice("md/raid10:%s: not clean -- starting background reconstruction\n", mdname(mddev)); pr_info("md/raid10:%s: active with %d out of %d devices\n", @@ -4245,8 +4245,8 @@ static int raid10_resize(struct mddev *mddev, sector_t sectors)
md_set_array_sectors(mddev, size); if (sectors > mddev->dev_sectors && - mddev->recovery_cp > oldsize) { - mddev->recovery_cp = oldsize; + mddev->resync_offset > oldsize) { + mddev->resync_offset = oldsize; set_bit(MD_RECOVERY_NEEDED, &mddev->recovery); } calc_sectors(conf, sectors); @@ -4275,7 +4275,7 @@ static void *raid10_takeover_raid0(struct mddev *mddev, sector_t size, int devs) mddev->delta_disks = mddev->raid_disks; mddev->raid_disks *= 2; /* make sure it will be not marked as dirty */ - mddev->recovery_cp = MaxSector; + mddev->resync_offset = MaxSector; mddev->dev_sectors = size;
conf = setup_conf(mddev); @@ -5087,8 +5087,8 @@ static void raid10_finish_reshape(struct mddev *mddev) return;
if (mddev->delta_disks > 0) { - if (mddev->recovery_cp > mddev->resync_max_sectors) { - mddev->recovery_cp = mddev->resync_max_sectors; + if (mddev->resync_offset > mddev->resync_max_sectors) { + mddev->resync_offset = mddev->resync_max_sectors; set_bit(MD_RECOVERY_NEEDED, &mddev->recovery); } mddev->resync_max_sectors = mddev->array_sectors; diff --git a/drivers/md/raid5-ppl.c b/drivers/md/raid5-ppl.c index c0fb335311aa..56b234683ee6 100644 --- a/drivers/md/raid5-ppl.c +++ b/drivers/md/raid5-ppl.c @@ -1163,7 +1163,7 @@ static int ppl_load_distributed(struct ppl_log *log) le64_to_cpu(pplhdr->generation));
/* attempt to recover from log if we are starting a dirty array */ - if (pplhdr && !mddev->pers && mddev->recovery_cp != MaxSector) + if (pplhdr && !mddev->pers && mddev->resync_offset != MaxSector) ret = ppl_recover(log, pplhdr, pplhdr_offset);
/* write empty header if we are starting the array */ @@ -1422,14 +1422,14 @@ int ppl_init_log(struct r5conf *conf)
if (ret) { goto err; - } else if (!mddev->pers && mddev->recovery_cp == 0 && + } else if (!mddev->pers && mddev->resync_offset == 0 && ppl_conf->recovered_entries > 0 && ppl_conf->mismatch_count == 0) { /* * If we are starting a dirty array and the recovery succeeds * without any issues, set the array as clean. */ - mddev->recovery_cp = MaxSector; + mddev->resync_offset = MaxSector; set_bit(MD_SB_CHANGE_CLEAN, &mddev->sb_flags); } else if (mddev->pers && ppl_conf->mismatch_count > 0) { /* no mismatch allowed when enabling PPL for a running array */ diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c index ca5b0e8ba707..38a193c0fdae 100644 --- a/drivers/md/raid5.c +++ b/drivers/md/raid5.c @@ -3740,7 +3740,7 @@ static int want_replace(struct stripe_head *sh, int disk_idx) && !test_bit(Faulty, &rdev->flags) && !test_bit(In_sync, &rdev->flags) && (rdev->recovery_offset <= sh->sector - || rdev->mddev->recovery_cp <= sh->sector)) + || rdev->mddev->resync_offset <= sh->sector)) rv = 1; return rv; } @@ -3832,7 +3832,7 @@ static int need_this_block(struct stripe_head *sh, struct stripe_head_state *s, * is missing/faulty, then we need to read everything we can. */ if (!force_rcw && - sh->sector < sh->raid_conf->mddev->recovery_cp) + sh->sector < sh->raid_conf->mddev->resync_offset) /* reconstruct-write isn't being forced */ return 0; for (i = 0; i < s->failed && i < 2; i++) { @@ -4097,7 +4097,7 @@ static int handle_stripe_dirtying(struct r5conf *conf, int disks) { int rmw = 0, rcw = 0, i; - sector_t recovery_cp = conf->mddev->recovery_cp; + sector_t resync_offset = conf->mddev->resync_offset;
/* Check whether resync is now happening or should start. * If yes, then the array is dirty (after unclean shutdown or @@ -4107,14 +4107,14 @@ static int handle_stripe_dirtying(struct r5conf *conf, * generate correct data from the parity. */ if (conf->rmw_level == PARITY_DISABLE_RMW || - (recovery_cp < MaxSector && sh->sector >= recovery_cp && + (resync_offset < MaxSector && sh->sector >= resync_offset && s->failed == 0)) { /* Calculate the real rcw later - for now make it * look like rcw is cheaper */ rcw = 1; rmw = 2; - pr_debug("force RCW rmw_level=%u, recovery_cp=%llu sh->sector=%llu\n", - conf->rmw_level, (unsigned long long)recovery_cp, + pr_debug("force RCW rmw_level=%u, resync_offset=%llu sh->sector=%llu\n", + conf->rmw_level, (unsigned long long)resync_offset, (unsigned long long)sh->sector); } else for (i = disks; i--; ) { /* would I have to read this buffer for read_modify_write */ @@ -4770,14 +4770,14 @@ static void analyse_stripe(struct stripe_head *sh, struct stripe_head_state *s) if (test_bit(STRIPE_SYNCING, &sh->state)) { /* If there is a failed device being replaced, * we must be recovering. - * else if we are after recovery_cp, we must be syncing + * else if we are after resync_offset, we must be syncing * else if MD_RECOVERY_REQUESTED is set, we also are syncing. * else we can only be replacing * sync and recovery both need to read all devices, and so * use the same flag. */ if (do_recovery || - sh->sector >= conf->mddev->recovery_cp || + sh->sector >= conf->mddev->resync_offset || test_bit(MD_RECOVERY_REQUESTED, &(conf->mddev->recovery))) s->syncing = 1; else @@ -7780,7 +7780,7 @@ static int raid5_run(struct mddev *mddev) int first = 1; int ret = -EIO;
- if (mddev->recovery_cp != MaxSector) + if (mddev->resync_offset != MaxSector) pr_notice("md/raid:%s: not clean -- starting background reconstruction\n", mdname(mddev));
@@ -7921,7 +7921,7 @@ static int raid5_run(struct mddev *mddev) mdname(mddev)); mddev->ro = 1; set_disk_ro(mddev->gendisk, 1); - } else if (mddev->recovery_cp == MaxSector) + } else if (mddev->resync_offset == MaxSector) set_bit(MD_JOURNAL_CLEAN, &mddev->flags); }
@@ -7988,7 +7988,7 @@ static int raid5_run(struct mddev *mddev) mddev->resync_max_sectors = mddev->dev_sectors;
if (mddev->degraded > dirty_parity_disks && - mddev->recovery_cp != MaxSector) { + mddev->resync_offset != MaxSector) { if (test_bit(MD_HAS_PPL, &mddev->flags)) pr_crit("md/raid:%s: starting dirty degraded array with PPL.\n", mdname(mddev)); @@ -8328,8 +8328,8 @@ static int raid5_resize(struct mddev *mddev, sector_t sectors)
md_set_array_sectors(mddev, newsize); if (sectors > mddev->dev_sectors && - mddev->recovery_cp > mddev->dev_sectors) { - mddev->recovery_cp = mddev->dev_sectors; + mddev->resync_offset > mddev->dev_sectors) { + mddev->resync_offset = mddev->dev_sectors; set_bit(MD_RECOVERY_NEEDED, &mddev->recovery); } mddev->dev_sectors = sectors; @@ -8423,7 +8423,7 @@ static int raid5_start_reshape(struct mddev *mddev) return -EINVAL;
/* raid5 can't handle concurrent reshape and recovery */ - if (mddev->recovery_cp < MaxSector) + if (mddev->resync_offset < MaxSector) return -EBUSY; for (i = 0; i < conf->raid_disks; i++) if (conf->disks[i].replacement) @@ -8648,7 +8648,7 @@ static void *raid45_takeover_raid0(struct mddev *mddev, int level) mddev->raid_disks += 1; mddev->delta_disks = 1; /* make sure it will be not marked as dirty */ - mddev->recovery_cp = MaxSector; + mddev->resync_offset = MaxSector;
return setup_conf(mddev); } diff --git a/include/uapi/linux/raid/md_p.h b/include/uapi/linux/raid/md_p.h index ff47b6f0ba0f..b13946287277 100644 --- a/include/uapi/linux/raid/md_p.h +++ b/include/uapi/linux/raid/md_p.h @@ -173,7 +173,7 @@ typedef struct mdp_superblock_s { #else #error unspecified endianness #endif - __u32 recovery_cp; /* 11 recovery checkpoint sector count */ + __u32 resync_offset; /* 11 resync checkpoint sector count */ /* There are only valid for minor_version > 90 */ __u64 reshape_position; /* 12,13 next address in array-space for reshape */ __u32 new_level; /* 14 new level we are reshaping to */
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Zheng Qixing zhengqixing@huawei.com
[ Upstream commit cb0780ad4333040a98e10f014b593ef738a3f31e ]
Add a helper for checking if an rdev needs recovery.
Signed-off-by: Zheng Qixing zhengqixing@huawei.com Link: https://lore.kernel.org/linux-raid/20250816002534.1754356-2-zhengqixing@huaw... Signed-off-by: Yu Kuai yukuai3@huawei.com Stable-dep-of: b7ee30f0efd1 ("md: fix sync_action incorrect display during resync") Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/md/md.c | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-)
diff --git a/drivers/md/md.c b/drivers/md/md.c index 80470bcf4383..0348b5f3adc5 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -4822,6 +4822,15 @@ metadata_store(struct mddev *mddev, const char *buf, size_t len) static struct md_sysfs_entry md_metadata = __ATTR_PREALLOC(metadata_version, S_IRUGO|S_IWUSR, metadata_show, metadata_store);
+static bool rdev_needs_recovery(struct md_rdev *rdev, sector_t sectors) +{ + return rdev->raid_disk >= 0 && + !test_bit(Journal, &rdev->flags) && + !test_bit(Faulty, &rdev->flags) && + !test_bit(In_sync, &rdev->flags) && + rdev->recovery_offset < sectors; +} + enum sync_action md_sync_action(struct mddev *mddev) { unsigned long recovery = mddev->recovery; @@ -8959,11 +8968,7 @@ static sector_t md_sync_position(struct mddev *mddev, enum sync_action action) start = MaxSector; rcu_read_lock(); rdev_for_each_rcu(rdev, mddev) - if (rdev->raid_disk >= 0 && - !test_bit(Journal, &rdev->flags) && - !test_bit(Faulty, &rdev->flags) && - !test_bit(In_sync, &rdev->flags) && - rdev->recovery_offset < start) + if (rdev_needs_recovery(rdev, start)) start = rdev->recovery_offset; rcu_read_unlock();
@@ -9322,12 +9327,8 @@ void md_do_sync(struct md_thread *thread) test_bit(MD_RECOVERY_RECOVER, &mddev->recovery)) { rcu_read_lock(); rdev_for_each_rcu(rdev, mddev) - if (rdev->raid_disk >= 0 && - mddev->delta_disks >= 0 && - !test_bit(Journal, &rdev->flags) && - !test_bit(Faulty, &rdev->flags) && - !test_bit(In_sync, &rdev->flags) && - rdev->recovery_offset < mddev->curr_resync) + if (mddev->delta_disks >= 0 && + rdev_needs_recovery(rdev, mddev->curr_resync)) rdev->recovery_offset = mddev->curr_resync; rcu_read_unlock(); }
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Zheng Qixing zhengqixing@huawei.com
[ Upstream commit b7ee30f0efd12f42735ae233071015389407966c ]
During raid resync, if a disk becomes faulty, the operation is briefly interrupted. The MD_RECOVERY_RECOVER flag triggered by the disk failure causes sync_action to incorrectly show "recover" instead of "resync". The same issue affects reshape operations.
Reproduction steps: mdadm -Cv /dev/md1 -l1 -n4 -e1.2 /dev/sd{a..d} // -> resync happened mdadm -f /dev/md1 /dev/sda // -> resync interrupted cat sync_action -> recover
Add progress checks in md_sync_action() for resync/recover/reshape to ensure the interface correctly reports the actual operation type.
Fixes: 4b10a3bc67c1 ("md: ensure resync is prioritized over recovery") Signed-off-by: Zheng Qixing zhengqixing@huawei.com Link: https://lore.kernel.org/linux-raid/20250816002534.1754356-3-zhengqixing@huaw... Signed-off-by: Yu Kuai yukuai3@huawei.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/md/md.c | 37 +++++++++++++++++++++++++++++++++++-- 1 file changed, 35 insertions(+), 2 deletions(-)
diff --git a/drivers/md/md.c b/drivers/md/md.c index 0348b5f3adc5..8746b22060a7 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -4831,9 +4831,33 @@ static bool rdev_needs_recovery(struct md_rdev *rdev, sector_t sectors) rdev->recovery_offset < sectors; }
+static enum sync_action md_get_active_sync_action(struct mddev *mddev) +{ + struct md_rdev *rdev; + bool is_recover = false; + + if (mddev->resync_offset < MaxSector) + return ACTION_RESYNC; + + if (mddev->reshape_position != MaxSector) + return ACTION_RESHAPE; + + rcu_read_lock(); + rdev_for_each_rcu(rdev, mddev) { + if (rdev_needs_recovery(rdev, MaxSector)) { + is_recover = true; + break; + } + } + rcu_read_unlock(); + + return is_recover ? ACTION_RECOVER : ACTION_IDLE; +} + enum sync_action md_sync_action(struct mddev *mddev) { unsigned long recovery = mddev->recovery; + enum sync_action active_action;
/* * frozen has the highest priority, means running sync_thread will be @@ -4857,8 +4881,17 @@ enum sync_action md_sync_action(struct mddev *mddev) !test_bit(MD_RECOVERY_NEEDED, &recovery)) return ACTION_IDLE;
- if (test_bit(MD_RECOVERY_RESHAPE, &recovery) || - mddev->reshape_position != MaxSector) + /* + * Check if any sync operation (resync/recover/reshape) is + * currently active. This ensures that only one sync operation + * can run at a time. Returns the type of active operation, or + * ACTION_IDLE if none are active. + */ + active_action = md_get_active_sync_action(mddev); + if (active_action != ACTION_IDLE) + return active_action; + + if (test_bit(MD_RECOVERY_RESHAPE, &recovery)) return ACTION_RESHAPE;
if (test_bit(MD_RECOVERY_RECOVER, &recovery))
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Miguel Ojeda ojeda@kernel.org
[ Upstream commit 0f580d5d3d9d9cd0953695cd32e43aac3a946338 ]
Commit fde578c86281 ("rust: alloc: replace aligned_size() with Kmalloc::aligned_layout()") provides a public `aligned_layout` function in `Kamlloc`, but not in `Cmalloc`, and thus uses of it will trigger an error in `rusttest`.
Such a user appeared in the following commit 22ab0641b939 ("rust: drm: ensure kmalloc() compatible Layout"):
error[E0599]: no function or associated item named `aligned_layout` found for struct `alloc::allocator_test::Cmalloc` in the current scope --> rust/kernel/drm/device.rs:100:31 | 100 | let layout = Kmalloc::aligned_layout(Layout::new::<Self>()); | ^^^^^^^^^^^^^^ function or associated item not found in `Cmalloc` | ::: rust/kernel/alloc/allocator_test.rs:19:1 | 19 | pub struct Cmalloc; | ------------------ function or associated item `aligned_layout` not found for this struct
Thus add an equivalent one for `Cmalloc`.
Fixes: fde578c86281 ("rust: alloc: replace aligned_size() with Kmalloc::aligned_layout()") Signed-off-by: Miguel Ojeda ojeda@kernel.org Link: https://lore.kernel.org/r/20250816204215.2719559-1-ojeda@kernel.org Signed-off-by: Danilo Krummrich dakr@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- rust/kernel/alloc/allocator_test.rs | 11 +++++++++++ 1 file changed, 11 insertions(+)
diff --git a/rust/kernel/alloc/allocator_test.rs b/rust/kernel/alloc/allocator_test.rs index d19c06ef0498..981e002ae3fc 100644 --- a/rust/kernel/alloc/allocator_test.rs +++ b/rust/kernel/alloc/allocator_test.rs @@ -22,6 +22,17 @@ pub type Kmalloc = Cmalloc; pub type Vmalloc = Kmalloc; pub type KVmalloc = Kmalloc;
+impl Cmalloc { + /// Returns a [`Layout`] that makes [`Kmalloc`] fulfill the requested size and alignment of + /// `layout`. + pub fn aligned_layout(layout: Layout) -> Layout { + // Note that `layout.size()` (after padding) is guaranteed to be a multiple of + // `layout.align()` which together with the slab guarantees means that `Kmalloc` will return + // a properly aligned object (see comments in `kmalloc()` for more information). + layout.pad_to_align() + } +} + extern "C" { #[link_name = "aligned_alloc"] fn libc_aligned_alloc(align: usize, size: usize) -> *mut crate::ffi::c_void;
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Baihan Li libaihan@huawei.com
[ Upstream commit e5f48bfa2ae0806d5f51fb8061afc619a73599a7 ]
Currently the driver missed to clean the i2c adapter when vdac init failed. It may cause resource leak.
Fixes: a0d078d06e516 ("drm/hisilicon: Features to support reading resolutions from EDID") Signed-off-by: Baihan Li libaihan@huawei.com Signed-off-by: Yongbang Shi shiyongbang@huawei.com Reviewed-by: Dmitry Baryshkov dmitry.baryshkov@oss.qualcomm.com Link: https://lore.kernel.org/r/20250813094238.3722345-2-shiyongbang@huawei.com Signed-off-by: Dmitry Baryshkov dmitry.baryshkov@oss.qualcomm.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h | 1 + drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_i2c.c | 5 +++++ drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_vdac.c | 11 ++++++++--- 3 files changed, 14 insertions(+), 3 deletions(-)
diff --git a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h index 274feabe7df0..ca8502e2760c 100644 --- a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h +++ b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h @@ -69,6 +69,7 @@ int hibmc_de_init(struct hibmc_drm_private *priv); int hibmc_vdac_init(struct hibmc_drm_private *priv);
int hibmc_ddc_create(struct drm_device *drm_dev, struct hibmc_vdac *connector); +void hibmc_ddc_del(struct hibmc_vdac *vdac);
int hibmc_dp_init(struct hibmc_drm_private *priv);
diff --git a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_i2c.c b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_i2c.c index 99b3b77b5445..44860011855e 100644 --- a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_i2c.c +++ b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_i2c.c @@ -95,3 +95,8 @@ int hibmc_ddc_create(struct drm_device *drm_dev, struct hibmc_vdac *vdac)
return i2c_bit_add_bus(&vdac->adapter); } + +void hibmc_ddc_del(struct hibmc_vdac *vdac) +{ + i2c_del_adapter(&vdac->adapter); +} diff --git a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_vdac.c b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_vdac.c index e8a527ede854..841e81f47b68 100644 --- a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_vdac.c +++ b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_vdac.c @@ -53,7 +53,7 @@ static void hibmc_connector_destroy(struct drm_connector *connector) { struct hibmc_vdac *vdac = to_hibmc_vdac(connector);
- i2c_del_adapter(&vdac->adapter); + hibmc_ddc_del(vdac); drm_connector_cleanup(connector); }
@@ -110,7 +110,7 @@ int hibmc_vdac_init(struct hibmc_drm_private *priv) ret = drmm_encoder_init(dev, encoder, NULL, DRM_MODE_ENCODER_DAC, NULL); if (ret) { drm_err(dev, "failed to init encoder: %d\n", ret); - return ret; + goto err; }
drm_encoder_helper_add(encoder, &hibmc_encoder_helper_funcs); @@ -121,7 +121,7 @@ int hibmc_vdac_init(struct hibmc_drm_private *priv) &vdac->adapter); if (ret) { drm_err(dev, "failed to init connector: %d\n", ret); - return ret; + goto err; }
drm_connector_helper_add(connector, &hibmc_connector_helper_funcs); @@ -131,4 +131,9 @@ int hibmc_vdac_init(struct hibmc_drm_private *priv) connector->polled = DRM_CONNECTOR_POLL_CONNECT | DRM_CONNECTOR_POLL_DISCONNECT;
return 0; + +err: + hibmc_ddc_del(vdac); + + return ret; }
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Baihan Li libaihan@huawei.com
[ Upstream commit 8bed4ec42a4e0dc8113172696ff076d1eb6d8bcb ]
The local variable is passed in request_irq (), and there will be use after free problem, which will make request_irq failed. Using the global irq name instead of it to fix.
Fixes: b11bc1ae4658 ("drm/hisilicon/hibmc: Add MSI irq getting and requesting for HPD") Signed-off-by: Baihan Li libaihan@huawei.com Signed-off-by: Yongbang Shi shiyongbang@huawei.com Reviewed-by: Dmitry Baryshkov dmitry.baryshkov@oss.qualcomm.com Link: https://lore.kernel.org/r/20250813094238.3722345-4-shiyongbang@huawei.com Signed-off-by: Dmitry Baryshkov dmitry.baryshkov@oss.qualcomm.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-)
diff --git a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c index 768b97f9e74a..4cdcc34070ee 100644 --- a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c +++ b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c @@ -32,7 +32,7 @@
DEFINE_DRM_GEM_FOPS(hibmc_fops);
-static const char *g_irqs_names_map[HIBMC_MAX_VECTORS] = { "vblank", "hpd" }; +static const char *g_irqs_names_map[HIBMC_MAX_VECTORS] = { "hibmc-vblank", "hibmc-hpd" };
static irqreturn_t hibmc_interrupt(int irq, void *arg) { @@ -277,7 +277,6 @@ static void hibmc_unload(struct drm_device *dev) static int hibmc_msi_init(struct drm_device *dev) { struct pci_dev *pdev = to_pci_dev(dev->dev); - char name[32] = {0}; int valid_irq_num; int irq; int ret; @@ -292,9 +291,6 @@ static int hibmc_msi_init(struct drm_device *dev) valid_irq_num = ret;
for (int i = 0; i < valid_irq_num; i++) { - snprintf(name, ARRAY_SIZE(name) - 1, "%s-%s-%s", - dev->driver->name, pci_name(pdev), g_irqs_names_map[i]); - irq = pci_irq_vector(pdev, i);
if (i) @@ -302,10 +298,10 @@ static int hibmc_msi_init(struct drm_device *dev) ret = devm_request_threaded_irq(&pdev->dev, irq, hibmc_dp_interrupt, hibmc_dp_hpd_isr, - IRQF_SHARED, name, dev); + IRQF_SHARED, g_irqs_names_map[i], dev); else ret = devm_request_irq(&pdev->dev, irq, hibmc_interrupt, - IRQF_SHARED, name, dev); + IRQF_SHARED, g_irqs_names_map[i], dev); if (ret) { drm_err(dev, "install irq failed: %d\n", ret); return ret;
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Baihan Li libaihan@huawei.com
[ Upstream commit 93a08f856fcc5aaeeecad01f71bef3088588216a ]
When hibmc loaded failed, the driver use hibmc_unload to free the resource, but the mutexes in mode.config are not init, which will access an NULL pointer. Just change goto statement to return, because hibnc_hw_init() doesn't need to free anything.
Fixes: b3df5e65cc03 ("drm/hibmc: Drop drm_vblank_cleanup") Signed-off-by: Baihan Li libaihan@huawei.com Signed-off-by: Yongbang Shi shiyongbang@huawei.com Reviewed-by: Dmitry Baryshkov dmitry.baryshkov@oss.qualcomm.com Link: https://lore.kernel.org/r/20250813094238.3722345-5-shiyongbang@huawei.com Signed-off-by: Dmitry Baryshkov dmitry.baryshkov@oss.qualcomm.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c index 4cdcc34070ee..ac552c339671 100644 --- a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c +++ b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c @@ -319,13 +319,13 @@ static int hibmc_load(struct drm_device *dev)
ret = hibmc_hw_init(priv); if (ret) - goto err; + return ret;
ret = drmm_vram_helper_init(dev, pci_resource_start(pdev, 0), pci_resource_len(pdev, 0)); if (ret) { drm_err(dev, "Error initializing VRAM MM; %d\n", ret); - goto err; + return ret; }
ret = hibmc_kms_init(priv);
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Baihan Li libaihan@huawei.com
[ Upstream commit 9f98b429ba67d430b873e06bcfb90afa22888978 ]
In some case, the dp link training success at 8.1Gbps, but the sink's maximum supported rate is less than 8.1G. So change the default 8.1Gbps link rate to the rate that reads from devices' capabilities.
Fixes: 54063d86e036 ("drm/hisilicon/hibmc: add dp link moduel in hibmc drivers") Signed-off-by: Baihan Li libaihan@huawei.com Signed-off-by: Yongbang Shi shiyongbang@huawei.com Reviewed-by: Dmitry Baryshkov dmitry.baryshkov@oss.qualcomm.com Link: https://lore.kernel.org/r/20250813094238.3722345-6-shiyongbang@huawei.com Signed-off-by: Dmitry Baryshkov dmitry.baryshkov@oss.qualcomm.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/gpu/drm/hisilicon/hibmc/dp/dp_link.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-)
diff --git a/drivers/gpu/drm/hisilicon/hibmc/dp/dp_link.c b/drivers/gpu/drm/hisilicon/hibmc/dp/dp_link.c index 74f7832ea53e..0726cb5b736e 100644 --- a/drivers/gpu/drm/hisilicon/hibmc/dp/dp_link.c +++ b/drivers/gpu/drm/hisilicon/hibmc/dp/dp_link.c @@ -325,6 +325,17 @@ static int hibmc_dp_link_downgrade_training_eq(struct hibmc_dp_dev *dp) return hibmc_dp_link_reduce_rate(dp); }
+static void hibmc_dp_update_caps(struct hibmc_dp_dev *dp) +{ + dp->link.cap.link_rate = dp->dpcd[DP_MAX_LINK_RATE]; + if (dp->link.cap.link_rate > DP_LINK_BW_8_1 || !dp->link.cap.link_rate) + dp->link.cap.link_rate = DP_LINK_BW_8_1; + + dp->link.cap.lanes = dp->dpcd[DP_MAX_LANE_COUNT] & DP_MAX_LANE_COUNT_MASK; + if (dp->link.cap.lanes > HIBMC_DP_LANE_NUM_MAX) + dp->link.cap.lanes = HIBMC_DP_LANE_NUM_MAX; +} + int hibmc_dp_link_training(struct hibmc_dp_dev *dp) { struct hibmc_dp_link *link = &dp->link; @@ -334,8 +345,7 @@ int hibmc_dp_link_training(struct hibmc_dp_dev *dp) if (ret) drm_err(dp->dev, "dp aux read dpcd failed, ret: %d\n", ret);
- dp->link.cap.link_rate = dp->dpcd[DP_MAX_LINK_RATE]; - dp->link.cap.lanes = 0x2; + hibmc_dp_update_caps(dp);
ret = hibmc_dp_get_serdes_rate_cfg(dp); if (ret < 0)
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Baihan Li libaihan@huawei.com
[ Upstream commit 3271faf42d135bcf569c3ff6af55c21858eec212 ]
If VGA and DP connected together, there will be only one can get crtc. Add encoder possible_clones to support two connectors enable.
Fixes: 3c7623fb5bb6 ("drm/hisilicon/hibmc: Enable this hot plug detect of irq feature") Signed-off-by: Baihan Li libaihan@huawei.com Signed-off-by: Yongbang Shi shiyongbang@huawei.com Reviewed-by: Dmitry Baryshkov dmitry.baryshkov@oss.qualcomm.com Link: https://lore.kernel.org/r/20250813094238.3722345-8-shiyongbang@huawei.com Signed-off-by: Dmitry Baryshkov dmitry.baryshkov@oss.qualcomm.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c | 8 ++++++++ 1 file changed, 8 insertions(+)
diff --git a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c index ac552c339671..289304500ab0 100644 --- a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c +++ b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c @@ -115,6 +115,8 @@ static const struct drm_mode_config_funcs hibmc_mode_funcs = { static int hibmc_kms_init(struct hibmc_drm_private *priv) { struct drm_device *dev = &priv->dev; + struct drm_encoder *encoder; + u32 clone_mask = 0; int ret;
ret = drmm_mode_config_init(dev); @@ -154,6 +156,12 @@ static int hibmc_kms_init(struct hibmc_drm_private *priv) return ret; }
+ drm_for_each_encoder(encoder, dev) + clone_mask |= drm_encoder_mask(encoder); + + drm_for_each_encoder(encoder, dev) + encoder->possible_clones = clone_mask; + return 0; }
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Dan Carpenter dan.carpenter@linaro.org
[ Upstream commit 89f0addeee3cb2dc49837599330ed9c4612f05b0 ]
The "p" pointer is void so sizeof(*p) is 1. The intent was to check sizeof(*cs_desc), which is 3, instead.
Fixes: ecfd41166b72 ("ALSA: usb-audio: Validate UAC3 cluster segment descriptors") Signed-off-by: Dan Carpenter dan.carpenter@linaro.org Link: https://patch.msgid.link/aKL5kftC1qGt6lpv@stanley.mountain Signed-off-by: Takashi Iwai tiwai@suse.de Signed-off-by: Sasha Levin sashal@kernel.org --- sound/usb/stream.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/sound/usb/stream.c b/sound/usb/stream.c index 1cb52373e70f..db2c9bac00ad 100644 --- a/sound/usb/stream.c +++ b/sound/usb/stream.c @@ -349,7 +349,7 @@ snd_pcm_chmap_elem *convert_chmap_v3(struct uac3_cluster_header_descriptor u16 cs_len; u8 cs_type;
- if (len < sizeof(*p)) + if (len < sizeof(*cs_desc)) break; cs_len = le16_to_cpu(cs_desc->wLength); if (len < cs_len)
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Peng Fan peng.fan@nxp.com
[ Upstream commit 447be50598c05499f7ccc2b1f6ddb3da30f8099a ]
With module test, there is error dump: ------------[ cut here ]------------ notifier callback pca9450_i2c_restart_handler already registered WARNING: kernel/notifier.c:23 at notifier_chain_register+0x5c/0x88, CPU#0: kworker/u16:3/50 Call trace: notifier_chain_register+0x5c/0x88 (P) atomic_notifier_chain_register+0x30/0x58 register_restart_handler+0x1c/0x28 pca9450_i2c_probe+0x418/0x538 i2c_device_probe+0x220/0x3d0 really_probe+0x114/0x410 __driver_probe_device+0xa0/0x150 driver_probe_device+0x40/0x114 __device_attach_driver+0xd4/0x12c
So use devm_register_sys_off_handler to let kernel handle the resource free to avoid kernel dump.
Fixes: 6157e62b07d9 ("regulator: pca9450: Add restart handler") Signed-off-by: Peng Fan peng.fan@nxp.com Link: https://patch.msgid.link/20250815-pca9450-v1-1-7748e362dc97@nxp.com Signed-off-by: Mark Brown broonie@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/regulator/pca9450-regulator.c | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-)
diff --git a/drivers/regulator/pca9450-regulator.c b/drivers/regulator/pca9450-regulator.c index 14d19a6d6655..49ff762eb33e 100644 --- a/drivers/regulator/pca9450-regulator.c +++ b/drivers/regulator/pca9450-regulator.c @@ -34,7 +34,6 @@ struct pca9450 { struct device *dev; struct regmap *regmap; struct gpio_desc *sd_vsel_gpio; - struct notifier_block restart_nb; enum pca9450_chip_type type; unsigned int rcnt; int irq; @@ -967,10 +966,9 @@ static irqreturn_t pca9450_irq_handler(int irq, void *data) return IRQ_HANDLED; }
-static int pca9450_i2c_restart_handler(struct notifier_block *nb, - unsigned long action, void *data) +static int pca9450_i2c_restart_handler(struct sys_off_data *data) { - struct pca9450 *pca9450 = container_of(nb, struct pca9450, restart_nb); + struct pca9450 *pca9450 = data->cb_data; struct i2c_client *i2c = container_of(pca9450->dev, struct i2c_client, dev);
dev_dbg(&i2c->dev, "Restarting device..\n"); @@ -1128,10 +1126,9 @@ static int pca9450_i2c_probe(struct i2c_client *i2c) pca9450->sd_vsel_fixed_low = of_property_read_bool(ldo5->dev.of_node, "nxp,sd-vsel-fixed-low");
- pca9450->restart_nb.notifier_call = pca9450_i2c_restart_handler; - pca9450->restart_nb.priority = PCA9450_RESTART_HANDLER_PRIORITY; - - if (register_restart_handler(&pca9450->restart_nb)) + if (devm_register_sys_off_handler(&i2c->dev, SYS_OFF_MODE_RESTART, + PCA9450_RESTART_HANDLER_PRIORITY, + pca9450_i2c_restart_handler, pca9450)) dev_warn(&i2c->dev, "Failed to register restart handler\n");
dev_info(&i2c->dev, "%s probed.\n",
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chenyuan Yang chenyuan0y@gmail.com
[ Upstream commit 7a2ca2ea64b1b63c8baa94a8f5deb70b2248d119 ]
The function mod_hdcp_hdcp1_create_session() calls the function get_first_active_display(), but does not check its return value. The return value is a null pointer if the display list is empty. This will lead to a null pointer dereference.
Add a null pointer check for get_first_active_display() and return MOD_HDCP_STATUS_DISPLAY_NOT_FOUND if the function return null.
This is similar to the commit c3e9826a2202 ("drm/amd/display: Add null pointer check for get_first_active_display()").
Fixes: 2deade5ede56 ("drm/amd/display: Remove hdcp display state with mst fix") Signed-off-by: Chenyuan Yang chenyuan0y@gmail.com Reviewed-by: Alex Hung alex.hung@amd.com Tested-by: Dan Wheeler daniel.wheeler@amd.com Signed-off-by: Alex Deucher alexander.deucher@amd.com (cherry picked from commit 5e43eb3cd731649c4f8b9134f857be62a416c893) Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/gpu/drm/amd/display/modules/hdcp/hdcp_psp.c | 3 +++ 1 file changed, 3 insertions(+)
diff --git a/drivers/gpu/drm/amd/display/modules/hdcp/hdcp_psp.c b/drivers/gpu/drm/amd/display/modules/hdcp/hdcp_psp.c index e58e7b93810b..6b7db8ec9a53 100644 --- a/drivers/gpu/drm/amd/display/modules/hdcp/hdcp_psp.c +++ b/drivers/gpu/drm/amd/display/modules/hdcp/hdcp_psp.c @@ -260,6 +260,9 @@ enum mod_hdcp_status mod_hdcp_hdcp1_create_session(struct mod_hdcp *hdcp) return MOD_HDCP_STATUS_FAILURE; }
+ if (!display) + return MOD_HDCP_STATUS_DISPLAY_NOT_FOUND; + hdcp_cmd = (struct ta_hdcp_shared_memory *)psp->hdcp_context.context.mem_context.shared_buf;
mutex_lock(&psp->hdcp_context.mutex);
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Timur Kristóf timur.kristof@gmail.com
[ Upstream commit 1fc931be2f47fde23ca5aff6f19421375c312fb2 ]
Adjust the nominal (and performance) clocks for DCE 8-10, and set them to 625 MHz, which is the value used by the legacy display code in amdgpu_atombios_get_clock_info.
This was tested with Hawaii, Tonga and Fiji. These GPUs can output 4K 60Hz (10-bit depth) at 625 MHz.
The extra 15% clock was added as a workaround for a Polaris issue which uses DCE 11, and should not have been used on DCE 8-10 which are already hardcoded to the highest possible display clock. Unfortunately, the extra 15% was mistakenly copied and kept even on code paths which don't affect Polaris.
This commit fixes that and also adds a check to make sure not to exceed the maximum DCE 8-10 display clock.
Fixes: 8cd61c313d8b ("drm/amd/display: Raise dispclk value for Polaris") Fixes: dc88b4a684d2 ("drm/amd/display: make clk mgr soc specific") Signed-off-by: Timur Kristóf timur.kristof@gmail.com Acked-by: Alex Deucher alexander.deucher@amd.com Reviewed-by: Rodrigo Siqueira siqueira@igalia.com Reviewed-by: Alex Hung alex.hung@amd.com Signed-off-by: Alex Deucher alexander.deucher@amd.com (cherry picked from commit 1ae45b5d4f371af8ae51a3827d0ec9fe27eeb867) Signed-off-by: Sasha Levin sashal@kernel.org --- .../drm/amd/display/dc/clk_mgr/dce100/dce_clk_mgr.c | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-)
diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dce100/dce_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dce100/dce_clk_mgr.c index e846e4920393..dbd6ef1b60a0 100644 --- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dce100/dce_clk_mgr.c +++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dce100/dce_clk_mgr.c @@ -72,9 +72,9 @@ static const struct state_dependent_clocks dce80_max_clks_by_state[] = { /* ClocksStateLow */ { .display_clk_khz = 352000, .pixel_clk_khz = 330000}, /* ClocksStateNominal */ -{ .display_clk_khz = 600000, .pixel_clk_khz = 400000 }, +{ .display_clk_khz = 625000, .pixel_clk_khz = 400000 }, /* ClocksStatePerformance */ -{ .display_clk_khz = 600000, .pixel_clk_khz = 400000 } }; +{ .display_clk_khz = 625000, .pixel_clk_khz = 400000 } };
int dentist_get_divider_from_did(int did) { @@ -403,11 +403,9 @@ static void dce_update_clocks(struct clk_mgr *clk_mgr_base, { struct clk_mgr_internal *clk_mgr_dce = TO_CLK_MGR_INTERNAL(clk_mgr_base); struct dm_pp_power_level_change_request level_change_req; - int patched_disp_clk = context->bw_ctx.bw.dce.dispclk_khz; - - /*TODO: W/A for dal3 linux, investigate why this works */ - if (!clk_mgr_dce->dfs_bypass_active) - patched_disp_clk = patched_disp_clk * 115 / 100; + const int max_disp_clk = + clk_mgr_dce->max_clks_by_state[DM_PP_CLOCKS_STATE_PERFORMANCE].display_clk_khz; + int patched_disp_clk = MIN(max_disp_clk, context->bw_ctx.bw.dce.dispclk_khz);
level_change_req.power_level = dce_get_required_clocks_state(clk_mgr_base, context); /* get max clock state from PPLIB */
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Timur Kristóf timur.kristof@gmail.com
[ Upstream commit f14ee2e7a86c5e57295b48b8e198cae7189b3b93 ]
When getting the number of connectors, the VBIOS reports the number of valid indices, but it doesn't say which indices are valid, and not every valid index has an actual connector. If we don't find a connector on an index, that is not an error.
Considering these are not actual errors, don't litter the logs.
Fixes: 60df5628144b ("drm/amd/display: handle invalid connector indices") Signed-off-by: Timur Kristóf timur.kristof@gmail.com Acked-by: Alex Deucher alexander.deucher@amd.com Reviewed-by: Rodrigo Siqueira siqueira@igalia.com Reviewed-by: Alex Hung alex.hung@amd.com Signed-off-by: Alex Deucher alexander.deucher@amd.com (cherry picked from commit 249d4bc5f1935f04bb45b3b63c0f8922565124f7) Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/gpu/drm/amd/display/dc/bios/bios_parser.c | 5 +---- drivers/gpu/drm/amd/display/dc/core/dc.c | 15 ++++++++++++++- 2 files changed, 15 insertions(+), 5 deletions(-)
diff --git a/drivers/gpu/drm/amd/display/dc/bios/bios_parser.c b/drivers/gpu/drm/amd/display/dc/bios/bios_parser.c index 67f08495b7e6..154fd2c18e88 100644 --- a/drivers/gpu/drm/amd/display/dc/bios/bios_parser.c +++ b/drivers/gpu/drm/amd/display/dc/bios/bios_parser.c @@ -174,11 +174,8 @@ static struct graphics_object_id bios_parser_get_connector_id( return object_id; }
- if (tbl->ucNumberOfObjects <= i) { - dm_error("Can't find connector id %d in connector table of size %d.\n", - i, tbl->ucNumberOfObjects); + if (tbl->ucNumberOfObjects <= i) return object_id; - }
id = le16_to_cpu(tbl->asObjects[i].usObjectID); object_id = object_id_from_bios_object_id(id); diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index aab1f8c9d717..eb76611a42a5 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -217,11 +217,24 @@ static bool create_links( connectors_num, num_virtual_links);
- // condition loop on link_count to allow skipping invalid indices + /* When getting the number of connectors, the VBIOS reports the number of valid indices, + * but it doesn't say which indices are valid, and not every index has an actual connector. + * So, if we don't find a connector on an index, that is not an error. + * + * - There is no guarantee that the first N indices will be valid + * - VBIOS may report a higher amount of valid indices than there are actual connectors + * - Some VBIOS have valid configurations for more connectors than there actually are + * on the card. This may be because the manufacturer used the same VBIOS for different + * variants of the same card. + */ for (i = 0; dc->link_count < connectors_num && i < MAX_LINKS; i++) { + struct graphics_object_id connector_id = bios->funcs->get_connector_id(bios, i); struct link_init_data link_init_params = {0}; struct dc_link *link;
+ if (connector_id.id == CONNECTOR_ID_UNKNOWN) + continue; + DC_LOG_DC("BIOS object table - printing link object info for connector number: %d, link_index: %d", i, dc->link_count);
link_init_params.ctx = dc->ctx;
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jakub Ramaseuski jramaseu@redhat.com
[ Upstream commit 864e3396976ef41de6cc7bc366276bf4e084fff2 ]
When performing Generic Segmentation Offload (GSO) on an IPv6 packet that contains extension headers, the kernel incorrectly requests checksum offload if the egress device only advertises NETIF_F_IPV6_CSUM feature, which has a strict contract: it supports checksum offload only for plain TCP or UDP over IPv6 and explicitly does not support packets with extension headers. The current GSO logic violates this contract by failing to disable the feature for packets with extension headers, such as those used in GREoIPv6 tunnels.
This violation results in the device being asked to perform an operation it cannot support, leading to a `skb_warn_bad_offload` warning and a collapse of network throughput. While device TSO/USO is correctly bypassed in favor of software GSO for these packets, the GSO stack must be explicitly told not to request checksum offload.
Mask NETIF_F_IPV6_CSUM, NETIF_F_TSO6 and NETIF_F_GSO_UDP_L4 in gso_features_check if the IPv6 header contains extension headers to compute checksum in software.
The exception is a BIG TCP extension, which, as stated in commit 68e068cabd2c6c53 ("net: reenable NETIF_F_IPV6_CSUM offload for BIG TCP packets"): "The feature is only enabled on devices that support BIG TCP TSO. The header is only present for PF_PACKET taps like tcpdump, and not transmitted by physical devices."
kernel log output (truncated): WARNING: CPU: 1 PID: 5273 at net/core/dev.c:3535 skb_warn_bad_offload+0x81/0x140 ... Call Trace: <TASK> skb_checksum_help+0x12a/0x1f0 validate_xmit_skb+0x1a3/0x2d0 validate_xmit_skb_list+0x4f/0x80 sch_direct_xmit+0x1a2/0x380 __dev_xmit_skb+0x242/0x670 __dev_queue_xmit+0x3fc/0x7f0 ip6_finish_output2+0x25e/0x5d0 ip6_finish_output+0x1fc/0x3f0 ip6_tnl_xmit+0x608/0xc00 [ip6_tunnel] ip6gre_tunnel_xmit+0x1c0/0x390 [ip6_gre] dev_hard_start_xmit+0x63/0x1c0 __dev_queue_xmit+0x6d0/0x7f0 ip6_finish_output2+0x214/0x5d0 ip6_finish_output+0x1fc/0x3f0 ip6_xmit+0x2ca/0x6f0 ip6_finish_output+0x1fc/0x3f0 ip6_xmit+0x2ca/0x6f0 inet6_csk_xmit+0xeb/0x150 __tcp_transmit_skb+0x555/0xa80 tcp_write_xmit+0x32a/0xe90 tcp_sendmsg_locked+0x437/0x1110 tcp_sendmsg+0x2f/0x50 ... skb linear: 00000000: e4 3d 1a 7d ec 30 e4 3d 1a 7e 5d 90 86 dd 60 0e skb linear: 00000010: 00 0a 1b 34 3c 40 20 11 00 00 00 00 00 00 00 00 skb linear: 00000020: 00 00 00 00 00 12 20 11 00 00 00 00 00 00 00 00 skb linear: 00000030: 00 00 00 00 00 11 2f 00 04 01 04 01 01 00 00 00 skb linear: 00000040: 86 dd 60 0e 00 0a 1b 00 06 40 20 23 00 00 00 00 skb linear: 00000050: 00 00 00 00 00 00 00 00 00 12 20 23 00 00 00 00 skb linear: 00000060: 00 00 00 00 00 00 00 00 00 11 bf 96 14 51 13 f9 skb linear: 00000070: ae 27 a0 a8 2b e3 80 18 00 40 5b 6f 00 00 01 01 skb linear: 00000080: 08 0a 42 d4 50 d5 4b 70 f8 1a
Fixes: 04c20a9356f283da ("net: skip offload for NETIF_F_IPV6_CSUM if ipv6 header contains extension") Reported-by: Tianhao Zhao tizhao@redhat.com Suggested-by: Michal Schmidt mschmidt@redhat.com Suggested-by: Willem de Bruijn willemdebruijn.kernel@gmail.com Signed-off-by: Jakub Ramaseuski jramaseu@redhat.com Reviewed-by: Willem de Bruijn willemb@google.com Link: https://patch.msgid.link/20250814105119.1525687-1-jramaseu@redhat.com Signed-off-by: Jakub Kicinski kuba@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- net/core/dev.c | 12 ++++++++++++ 1 file changed, 12 insertions(+)
diff --git a/net/core/dev.c b/net/core/dev.c index be97c440ecd5..b014a5ce9e0f 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -3782,6 +3782,18 @@ static netdev_features_t gso_features_check(const struct sk_buff *skb, features &= ~NETIF_F_TSO_MANGLEID; }
+ /* NETIF_F_IPV6_CSUM does not support IPv6 extension headers, + * so neither does TSO that depends on it. + */ + if (features & NETIF_F_IPV6_CSUM && + (skb_shinfo(skb)->gso_type & SKB_GSO_TCPV6 || + (skb_shinfo(skb)->gso_type & SKB_GSO_UDP_L4 && + vlan_get_protocol(skb) == htons(ETH_P_IPV6))) && + skb_transport_header_was_set(skb) && + skb_network_header_len(skb) != sizeof(struct ipv6hdr) && + !ipv6_has_hopopt_jumbo(skb)) + features &= ~(NETIF_F_IPV6_CSUM | NETIF_F_TSO6 | NETIF_F_GSO_UDP_L4); + return features; }
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Minhong He heminhong@kylinos.cn
[ Upstream commit 84967deee9d9870b15bc4c3acb50f1d401807902 ]
The seg6_genl_sethmac() directly uses the algorithm ID provided by the userspace without verifying whether it is an HMAC algorithm supported by the system. If an unsupported HMAC algorithm ID is configured, packets using SRv6 HMAC will be dropped during encapsulation or decapsulation.
Fixes: 4f4853dc1c9c ("ipv6: sr: implement API to control SR HMAC structure") Signed-off-by: Minhong He heminhong@kylinos.cn Reviewed-by: Kuniyuki Iwashima kuniyu@google.com Link: https://patch.msgid.link/20250815063845.85426-1-heminhong@kylinos.cn Signed-off-by: Jakub Kicinski kuba@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- net/ipv6/seg6_hmac.c | 3 +++ 1 file changed, 3 insertions(+)
diff --git a/net/ipv6/seg6_hmac.c b/net/ipv6/seg6_hmac.c index 5dae892bbc73..fd58426f222b 100644 --- a/net/ipv6/seg6_hmac.c +++ b/net/ipv6/seg6_hmac.c @@ -305,6 +305,9 @@ int seg6_hmac_info_add(struct net *net, u32 key, struct seg6_hmac_info *hinfo) struct seg6_pernet_data *sdata = seg6_pernet(net); int err;
+ if (!__hmac_get_algo(hinfo->alg_id)) + return -EINVAL; + err = rhashtable_lookup_insert_fast(&sdata->hmac_infos, &hinfo->node, rht_params);
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Michael Chan michael.chan@broadcom.com
[ Upstream commit 4611d88a37cfc18cbabc6978aaf7325d1ae3f53a ]
The commit under the Fixes tag added a netdev_assert_locked() in bnxt_free_ntp_fltrs(). The lock should be held during normal run-time but the assert will be triggered (see below) during bnxt_remove_one() which should not need the lock. The netdev is already unregistered by then. Fix it by calling netdev_assert_locked_or_invisible() which will not assert if the netdev is unregistered.
WARNING: CPU: 5 PID: 2241 at ./include/net/netdev_lock.h:17 bnxt_free_ntp_fltrs+0xf8/0x100 [bnxt_en] Modules linked in: rpcrdma rdma_cm iw_cm ib_cm configfs ib_core bnxt_en(-) bridge stp llc x86_pkg_temp_thermal xfs tg3 [last unloaded: bnxt_re] CPU: 5 UID: 0 PID: 2241 Comm: rmmod Tainted: G S W 6.16.0 #2 PREEMPT(voluntary) Tainted: [S]=CPU_OUT_OF_SPEC, [W]=WARN Hardware name: Dell Inc. PowerEdge R730/072T6D, BIOS 2.4.3 01/17/2017 RIP: 0010:bnxt_free_ntp_fltrs+0xf8/0x100 [bnxt_en] Code: 41 5c 41 5d 41 5e 41 5f c3 cc cc cc cc 48 8b 47 60 be ff ff ff ff 48 8d b8 28 0c 00 00 e8 d0 cf 41 c3 85 c0 0f 85 2e ff ff ff <0f> 0b e9 27 ff ff ff 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 RSP: 0018:ffffa92082387da0 EFLAGS: 00010246 RAX: 0000000000000000 RBX: ffff9e5b593d8000 RCX: 0000000000000001 RDX: 0000000000000001 RSI: ffffffff83dc9a70 RDI: ffffffff83e1a1cf RBP: ffff9e5b593d8c80 R08: 0000000000000000 R09: ffffffff8373a2b3 R10: 000000008100009f R11: 0000000000000001 R12: 0000000000000001 R13: ffffffffc01c4478 R14: dead000000000122 R15: dead000000000100 FS: 00007f3a8a52c740(0000) GS:ffff9e631ad1c000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: 000055bb289419c8 CR3: 000000011274e001 CR4: 00000000003706f0 Call Trace: <TASK> bnxt_remove_one+0x57/0x180 [bnxt_en] pci_device_remove+0x39/0xc0 device_release_driver_internal+0xa5/0x130 driver_detach+0x42/0x90 bus_remove_driver+0x61/0xc0 pci_unregister_driver+0x38/0x90 bnxt_exit+0xc/0x7d0 [bnxt_en]
Fixes: 004b5008016a ("eth: bnxt: remove most dependencies on RTNL") Reviewed-by: Pavan Chebbi pavan.chebbi@broadcom.com Signed-off-by: Michael Chan michael.chan@broadcom.com Reviewed-by: Vadim Fedorenko vadim.fedorenko@linux.dev Link: https://patch.msgid.link/20250816183850.4125033-1-michael.chan@broadcom.com Signed-off-by: Jakub Kicinski kuba@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/net/ethernet/broadcom/bnxt/bnxt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c index 25681c2343fb..ec8752c298e6 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c @@ -5325,7 +5325,7 @@ static void bnxt_free_ntp_fltrs(struct bnxt *bp, bool all) { int i;
- netdev_assert_locked(bp->dev); + netdev_assert_locked_or_invisible(bp->dev);
/* Under netdev instance lock and all our NAPIs have been disabled. * It's safe to delete the hash table.
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Bart Van Assche bvanassche@acm.org
[ Upstream commit eabcac808ca3ee9878223d4b49b750979029016b ]
Commit 3c7ac40d7322 ("scsi: ufs: core: Delegate the interrupt service routine to a threaded IRQ handler") introduced an IRQ lock inversion issue. Fix this lock inversion by changing the spin_lock_irq() calls into spin_lock_irqsave() calls in code that can be called either from interrupt context or from thread context. This patch fixes the following lockdep complaint:
WARNING: possible irq lock inversion dependency detected 6.12.30-android16-5-maybe-dirty-4k #1 Tainted: G W OE -------------------------------------------------------- kworker/u28:0/12 just changed the state of lock: ffffff881e29dd60 (&hba->clk_gating.lock){-...}-{2:2}, at: ufshcd_release_scsi_cmd+0x60/0x110 but this lock took another, HARDIRQ-unsafe lock in the past: (shost->host_lock){+.+.}-{2:2}
and interrupts could create inverse lock ordering between them.
other info that might help us debug this: Possible interrupt unsafe locking scenario:
CPU0 CPU1 ---- ---- lock(shost->host_lock); local_irq_disable(); lock(&hba->clk_gating.lock); lock(shost->host_lock); <Interrupt> lock(&hba->clk_gating.lock);
*** DEADLOCK ***
4 locks held by kworker/u28:0/12: #0: ffffff8800ac6158 ((wq_completion)async){+.+.}-{0:0}, at: process_one_work+0x1bc/0x65c #1: ffffffc085c93d70 ((work_completion)(&entry->work)){+.+.}-{0:0}, at: process_one_work+0x1e4/0x65c #2: ffffff881e29c0e0 (&shost->scan_mutex){+.+.}-{3:3}, at: __scsi_add_device+0x74/0x120 #3: ffffff881960ea00 (&hwq->cq_lock){-...}-{2:2}, at: ufshcd_mcq_poll_cqe_lock+0x28/0x104
the shortest dependencies between 2nd lock and 1st lock: -> (shost->host_lock){+.+.}-{2:2} { HARDIRQ-ON-W at: lock_acquire+0x134/0x2b4 _raw_spin_lock+0x48/0x64 ufshcd_sl_intr+0x4c/0xa08 ufshcd_threaded_intr+0x70/0x12c irq_thread_fn+0x48/0xa8 irq_thread+0x130/0x1ec kthread+0x110/0x134 ret_from_fork+0x10/0x20 SOFTIRQ-ON-W at: lock_acquire+0x134/0x2b4 _raw_spin_lock+0x48/0x64 ufshcd_sl_intr+0x4c/0xa08 ufshcd_threaded_intr+0x70/0x12c irq_thread_fn+0x48/0xa8 irq_thread+0x130/0x1ec kthread+0x110/0x134 ret_from_fork+0x10/0x20 INITIAL USE at: lock_acquire+0x134/0x2b4 _raw_spin_lock+0x48/0x64 ufshcd_sl_intr+0x4c/0xa08 ufshcd_threaded_intr+0x70/0x12c irq_thread_fn+0x48/0xa8 irq_thread+0x130/0x1ec kthread+0x110/0x134 ret_from_fork+0x10/0x20 } ... key at: [<ffffffc085ba1a98>] scsi_host_alloc.__key+0x0/0x10 ... acquired at: _raw_spin_lock_irqsave+0x5c/0x80 __ufshcd_release+0x78/0x118 ufshcd_send_uic_cmd+0xe4/0x118 ufshcd_dme_set_attr+0x88/0x1c8 ufs_google_phy_initialization+0x68/0x418 [ufs] ufs_google_link_startup_notify+0x78/0x27c [ufs] ufshcd_link_startup+0x84/0x720 ufshcd_init+0xf3c/0x1330 ufshcd_pltfrm_init+0x728/0x7d8 ufs_google_probe+0x30/0x84 [ufs] platform_probe+0xa0/0xe0 really_probe+0x114/0x454 __driver_probe_device+0xa4/0x160 driver_probe_device+0x44/0x23c __driver_attach_async_helper+0x60/0xd4 async_run_entry_fn+0x4c/0x17c process_one_work+0x26c/0x65c worker_thread+0x33c/0x498 kthread+0x110/0x134 ret_from_fork+0x10/0x20
-> (&hba->clk_gating.lock){-...}-{2:2} { IN-HARDIRQ-W at: lock_acquire+0x134/0x2b4 _raw_spin_lock_irqsave+0x5c/0x80 ufshcd_release_scsi_cmd+0x60/0x110 ufshcd_compl_one_cqe+0x2c0/0x3f4 ufshcd_mcq_poll_cqe_lock+0xb0/0x104 ufs_google_mcq_intr+0x80/0xa0 [ufs] __handle_irq_event_percpu+0x104/0x32c handle_irq_event+0x40/0x9c handle_fasteoi_irq+0x170/0x2e8 generic_handle_domain_irq+0x58/0x80 gic_handle_irq+0x48/0x104 call_on_irq_stack+0x3c/0x50 do_interrupt_handler+0x7c/0xd8 el1_interrupt+0x34/0x58 el1h_64_irq_handler+0x18/0x24 el1h_64_irq+0x68/0x6c _raw_spin_unlock_irqrestore+0x3c/0x6c debug_object_assert_init+0x16c/0x21c __mod_timer+0x4c/0x48c schedule_timeout+0xd4/0x16c io_schedule_timeout+0x48/0x70 do_wait_for_common+0x100/0x194 wait_for_completion_io_timeout+0x48/0x6c blk_execute_rq+0x124/0x17c scsi_execute_cmd+0x18c/0x3f8 scsi_probe_and_add_lun+0x204/0xd74 __scsi_add_device+0xbc/0x120 ufshcd_async_scan+0x80/0x3c0 async_run_entry_fn+0x4c/0x17c process_one_work+0x26c/0x65c worker_thread+0x33c/0x498 kthread+0x110/0x134 ret_from_fork+0x10/0x20 INITIAL USE at: lock_acquire+0x134/0x2b4 _raw_spin_lock_irqsave+0x5c/0x80 ufshcd_hold+0x34/0x14c ufshcd_send_uic_cmd+0x28/0x118 ufshcd_dme_set_attr+0x88/0x1c8 ufs_google_phy_initialization+0x68/0x418 [ufs] ufs_google_link_startup_notify+0x78/0x27c [ufs] ufshcd_link_startup+0x84/0x720 ufshcd_init+0xf3c/0x1330 ufshcd_pltfrm_init+0x728/0x7d8 ufs_google_probe+0x30/0x84 [ufs] platform_probe+0xa0/0xe0 really_probe+0x114/0x454 __driver_probe_device+0xa4/0x160 driver_probe_device+0x44/0x23c __driver_attach_async_helper+0x60/0xd4 async_run_entry_fn+0x4c/0x17c process_one_work+0x26c/0x65c worker_thread+0x33c/0x498 kthread+0x110/0x134 ret_from_fork+0x10/0x20 } ... key at: [<ffffffc085ba6fe8>] ufshcd_init.__key+0x0/0x10 ... acquired at: mark_lock+0x1c4/0x224 __lock_acquire+0x438/0x2e1c lock_acquire+0x134/0x2b4 _raw_spin_lock_irqsave+0x5c/0x80 ufshcd_release_scsi_cmd+0x60/0x110 ufshcd_compl_one_cqe+0x2c0/0x3f4 ufshcd_mcq_poll_cqe_lock+0xb0/0x104 ufs_google_mcq_intr+0x80/0xa0 [ufs] __handle_irq_event_percpu+0x104/0x32c handle_irq_event+0x40/0x9c handle_fasteoi_irq+0x170/0x2e8 generic_handle_domain_irq+0x58/0x80 gic_handle_irq+0x48/0x104 call_on_irq_stack+0x3c/0x50 do_interrupt_handler+0x7c/0xd8 el1_interrupt+0x34/0x58 el1h_64_irq_handler+0x18/0x24 el1h_64_irq+0x68/0x6c _raw_spin_unlock_irqrestore+0x3c/0x6c debug_object_assert_init+0x16c/0x21c __mod_timer+0x4c/0x48c schedule_timeout+0xd4/0x16c io_schedule_timeout+0x48/0x70 do_wait_for_common+0x100/0x194 wait_for_completion_io_timeout+0x48/0x6c blk_execute_rq+0x124/0x17c scsi_execute_cmd+0x18c/0x3f8 scsi_probe_and_add_lun+0x204/0xd74 __scsi_add_device+0xbc/0x120 ufshcd_async_scan+0x80/0x3c0 async_run_entry_fn+0x4c/0x17c process_one_work+0x26c/0x65c worker_thread+0x33c/0x498 kthread+0x110/0x134 ret_from_fork+0x10/0x20
stack backtrace: CPU: 6 UID: 0 PID: 12 Comm: kworker/u28:0 Tainted: G W OE 6.12.30-android16-5-maybe-dirty-4k #1 ccd4020fe444bdf629efc3b86df6be920b8df7d0 Tainted: [W]=WARN, [O]=OOT_MODULE, [E]=UNSIGNED_MODULE Hardware name: Spacecraft board based on MALIBU (DT) Workqueue: async async_run_entry_fn Call trace: dump_backtrace+0xfc/0x17c show_stack+0x18/0x28 dump_stack_lvl+0x40/0xa0 dump_stack+0x18/0x24 print_irq_inversion_bug+0x2fc/0x304 mark_lock_irq+0x388/0x4fc mark_lock+0x1c4/0x224 __lock_acquire+0x438/0x2e1c lock_acquire+0x134/0x2b4 _raw_spin_lock_irqsave+0x5c/0x80 ufshcd_release_scsi_cmd+0x60/0x110 ufshcd_compl_one_cqe+0x2c0/0x3f4 ufshcd_mcq_poll_cqe_lock+0xb0/0x104 ufs_google_mcq_intr+0x80/0xa0 [ufs dd6f385554e109da094ab91d5f7be18625a2222a] __handle_irq_event_percpu+0x104/0x32c handle_irq_event+0x40/0x9c handle_fasteoi_irq+0x170/0x2e8 generic_handle_domain_irq+0x58/0x80 gic_handle_irq+0x48/0x104 call_on_irq_stack+0x3c/0x50 do_interrupt_handler+0x7c/0xd8 el1_interrupt+0x34/0x58 el1h_64_irq_handler+0x18/0x24 el1h_64_irq+0x68/0x6c _raw_spin_unlock_irqrestore+0x3c/0x6c debug_object_assert_init+0x16c/0x21c __mod_timer+0x4c/0x48c schedule_timeout+0xd4/0x16c io_schedule_timeout+0x48/0x70 do_wait_for_common+0x100/0x194 wait_for_completion_io_timeout+0x48/0x6c blk_execute_rq+0x124/0x17c scsi_execute_cmd+0x18c/0x3f8 scsi_probe_and_add_lun+0x204/0xd74 __scsi_add_device+0xbc/0x120 ufshcd_async_scan+0x80/0x3c0 async_run_entry_fn+0x4c/0x17c process_one_work+0x26c/0x65c worker_thread+0x33c/0x498 kthread+0x110/0x134 ret_from_fork+0x10/0x20
Cc: Neil Armstrong neil.armstrong@linaro.org Cc: André Draszik andre.draszik@linaro.org Reviewed-by: Peter Wang peter.wang@mediatek.com Fixes: 3c7ac40d7322 ("scsi: ufs: core: Delegate the interrupt service routine to a threaded IRQ handler") Signed-off-by: Bart Van Assche bvanassche@acm.org Link: https://lore.kernel.org/r/20250815155842.472867-2-bvanassche@acm.org Signed-off-by: Martin K. Petersen martin.petersen@oracle.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/ufs/core/ufshcd.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-)
diff --git a/drivers/ufs/core/ufshcd.c b/drivers/ufs/core/ufshcd.c index 3cc566e8bd1d..f2eeb82ffa9b 100644 --- a/drivers/ufs/core/ufshcd.c +++ b/drivers/ufs/core/ufshcd.c @@ -5531,7 +5531,7 @@ static irqreturn_t ufshcd_uic_cmd_compl(struct ufs_hba *hba, u32 intr_status) irqreturn_t retval = IRQ_NONE; struct uic_command *cmd;
- spin_lock(hba->host->host_lock); + guard(spinlock_irqsave)(hba->host->host_lock); cmd = hba->active_uic_cmd; if (WARN_ON_ONCE(!cmd)) goto unlock; @@ -5558,8 +5558,6 @@ static irqreturn_t ufshcd_uic_cmd_compl(struct ufs_hba *hba, u32 intr_status) ufshcd_add_uic_command_trace(hba, cmd, UFS_CMD_COMP);
unlock: - spin_unlock(hba->host->host_lock); - return retval; }
@@ -6892,7 +6890,7 @@ static irqreturn_t ufshcd_check_errors(struct ufs_hba *hba, u32 intr_status) bool queue_eh_work = false; irqreturn_t retval = IRQ_NONE;
- spin_lock(hba->host->host_lock); + guard(spinlock_irqsave)(hba->host->host_lock); hba->errors |= UFSHCD_ERROR_MASK & intr_status;
if (hba->errors & INT_FATAL_ERRORS) { @@ -6951,7 +6949,7 @@ static irqreturn_t ufshcd_check_errors(struct ufs_hba *hba, u32 intr_status) */ hba->errors = 0; hba->uic_error = 0; - spin_unlock(hba->host->host_lock); + return retval; }
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Bart Van Assche bvanassche@acm.org
[ Upstream commit e5203d89d59bfcbe1f348aa0d2dc4449a8ba644c ]
The UIC completion interrupt may be disabled while an UIC command is being processed. When the UIC completion interrupt is reenabled, an UIC interrupt is triggered and the WARN_ON_ONCE(!cmd) statement is hit. Hence this patch that removes this kernel warning.
Fixes: fcd8b0450a9a ("scsi: ufs: core: Make ufshcd_uic_cmd_compl() easier to analyze") Reviewed-by: Peter Wang peter.wang@mediatek.com Signed-off-by: Bart Van Assche bvanassche@acm.org Link: https://lore.kernel.org/r/20250815155842.472867-3-bvanassche@acm.org Signed-off-by: Martin K. Petersen martin.petersen@oracle.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/ufs/core/ufshcd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/ufs/core/ufshcd.c b/drivers/ufs/core/ufshcd.c index f2eeb82ffa9b..5224a2145402 100644 --- a/drivers/ufs/core/ufshcd.c +++ b/drivers/ufs/core/ufshcd.c @@ -5533,7 +5533,7 @@ static irqreturn_t ufshcd_uic_cmd_compl(struct ufs_hba *hba, u32 intr_status)
guard(spinlock_irqsave)(hba->host->host_lock); cmd = hba->active_uic_cmd; - if (WARN_ON_ONCE(!cmd)) + if (!cmd) goto unlock;
if (ufshcd_is_auto_hibern8_error(hba, intr_status))
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Bao D. Nguyen quic_nguyenb@quicinc.com
[ Upstream commit 7a9d5195a7f5871a4ad4e55fc567a2b3bee49a59 ]
The MCQ feature and ESI are supported by all Qualcomm UFS controller versions 6 and above.
Therefore, update the ESI vector mask in the UFS_MEM_CFG3 register for platforms with major version number of 6 or higher.
Reviewed-by: Manivannan Sadhasivam mani@kernel.org Signed-off-by: Bao D. Nguyen quic_nguyenb@quicinc.com Signed-off-by: Nitin Rawat quic_nitirawa@quicinc.com Link: https://lore.kernel.org/r/20250714075336.2133-2-quic_nitirawa@quicinc.com Signed-off-by: Martin K. Petersen martin.petersen@oracle.com Stable-dep-of: 6300d5c54387 ("scsi: ufs: ufs-qcom: Fix ESI null pointer dereference") Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/ufs/host/ufs-qcom.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/drivers/ufs/host/ufs-qcom.c b/drivers/ufs/host/ufs-qcom.c index 18a978452001..53301a2c27be 100644 --- a/drivers/ufs/host/ufs-qcom.c +++ b/drivers/ufs/host/ufs-qcom.c @@ -2109,8 +2109,7 @@ static int ufs_qcom_config_esi(struct ufs_hba *hba)
retain_and_null_ptr(qi);
- if (host->hw_ver.major == 6 && host->hw_ver.minor == 0 && - host->hw_ver.step == 0) { + if (host->hw_ver.major >= 6) { ufshcd_rmwl(hba, ESI_VEC_MASK, FIELD_PREP(ESI_VEC_MASK, MAX_ESI_VEC - 1), REG_UFS_CFG3); }
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Nitin Rawat quic_nitirawa@quicinc.com
[ Upstream commit 6300d5c5438724c0876828da2f6e2c1a661871fc ]
ESI/MSI is a performance optimization feature that provides dedicated interrupts per MCQ hardware queue. This is optional feature and UFS MCQ should work with and without ESI feature.
Commit e46a28cea29a ("scsi: ufs: qcom: Remove the MSI descriptor abuse") brings a regression in ESI (Enhanced System Interrupt) configuration that causes a null pointer dereference when Platform MSI allocation fails.
The issue occurs in when platform_device_msi_init_and_alloc_irqs() in ufs_qcom_config_esi() fails (returns -EINVAL) but the current code uses __free() macro for automatic cleanup free MSI resources that were never successfully allocated.
Unable to handle kernel NULL pointer dereference at virtual address 0000000000000008
Call trace: mutex_lock+0xc/0x54 (P) platform_device_msi_free_irqs_all+0x1c/0x40 ufs_qcom_config_esi+0x1d0/0x220 [ufs_qcom] ufshcd_config_mcq+0x28/0x104 ufshcd_init+0xa3c/0xf40 ufshcd_pltfrm_init+0x504/0x7d4 ufs_qcom_probe+0x20/0x58 [ufs_qcom]
Fix by restructuring the ESI configuration to try MSI allocation first, before any other resource allocation and instead use explicit cleanup instead of __free() macro to avoid cleanup of unallocated resources.
Tested on SM8750 platform with MCQ enabled, both with and without Platform ESI support.
Fixes: e46a28cea29a ("scsi: ufs: qcom: Remove the MSI descriptor abuse") Cc: Manivannan Sadhasivam manivannan.sadhasivam@linaro.org Cc: Thomas Gleixner tglx@linutronix.de Cc: James Bottomley James.Bottomley@HansenPartnership.com Signed-off-by: Nitin Rawat quic_nitirawa@quicinc.com Link: https://lore.kernel.org/r/20250811073330.20230-1-quic_nitirawa@quicinc.com Signed-off-by: Martin K. Petersen martin.petersen@oracle.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/ufs/host/ufs-qcom.c | 39 ++++++++++++++----------------------- 1 file changed, 15 insertions(+), 24 deletions(-)
diff --git a/drivers/ufs/host/ufs-qcom.c b/drivers/ufs/host/ufs-qcom.c index 53301a2c27be..2e4edc192e8e 100644 --- a/drivers/ufs/host/ufs-qcom.c +++ b/drivers/ufs/host/ufs-qcom.c @@ -2053,17 +2053,6 @@ static irqreturn_t ufs_qcom_mcq_esi_handler(int irq, void *data) return IRQ_HANDLED; }
-static void ufs_qcom_irq_free(struct ufs_qcom_irq *uqi) -{ - for (struct ufs_qcom_irq *q = uqi; q->irq; q++) - devm_free_irq(q->hba->dev, q->irq, q->hba); - - platform_device_msi_free_irqs_all(uqi->hba->dev); - devm_kfree(uqi->hba->dev, uqi); -} - -DEFINE_FREE(ufs_qcom_irq, struct ufs_qcom_irq *, if (_T) ufs_qcom_irq_free(_T)) - static int ufs_qcom_config_esi(struct ufs_hba *hba) { struct ufs_qcom_host *host = ufshcd_get_variant(hba); @@ -2078,18 +2067,18 @@ static int ufs_qcom_config_esi(struct ufs_hba *hba) */ nr_irqs = hba->nr_hw_queues - hba->nr_queues[HCTX_TYPE_POLL];
- struct ufs_qcom_irq *qi __free(ufs_qcom_irq) = - devm_kcalloc(hba->dev, nr_irqs, sizeof(*qi), GFP_KERNEL); - if (!qi) - return -ENOMEM; - /* Preset so __free() has a pointer to hba in all error paths */ - qi[0].hba = hba; - ret = platform_device_msi_init_and_alloc_irqs(hba->dev, nr_irqs, ufs_qcom_write_msi_msg); if (ret) { - dev_err(hba->dev, "Failed to request Platform MSI %d\n", ret); - return ret; + dev_warn(hba->dev, "Platform MSI not supported or failed, continuing without ESI\n"); + return ret; /* Continue without ESI */ + } + + struct ufs_qcom_irq *qi = devm_kcalloc(hba->dev, nr_irqs, sizeof(*qi), GFP_KERNEL); + + if (!qi) { + platform_device_msi_free_irqs_all(hba->dev); + return -ENOMEM; }
for (int idx = 0; idx < nr_irqs; idx++) { @@ -2100,15 +2089,17 @@ static int ufs_qcom_config_esi(struct ufs_hba *hba) ret = devm_request_irq(hba->dev, qi[idx].irq, ufs_qcom_mcq_esi_handler, IRQF_SHARED, "qcom-mcq-esi", qi + idx); if (ret) { - dev_err(hba->dev, "%s: Fail to request IRQ for %d, err = %d\n", + dev_err(hba->dev, "%s: Failed to request IRQ for %d, err = %d\n", __func__, qi[idx].irq, ret); - qi[idx].irq = 0; + /* Free previously allocated IRQs */ + for (int j = 0; j < idx; j++) + devm_free_irq(hba->dev, qi[j].irq, qi + j); + platform_device_msi_free_irqs_all(hba->dev); + devm_kfree(hba->dev, qi); return ret; } }
- retain_and_null_ptr(qi); - if (host->hw_ver.major >= 6) { ufshcd_rmwl(hba, ESI_VEC_MASK, FIELD_PREP(ESI_VEC_MASK, MAX_ESI_VEC - 1), REG_UFS_CFG3);
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Qingfang Deng dqfext@gmail.com
[ Upstream commit 62c30c544359aa18b8fb2734166467a07d435c2d ]
Ensure ndo_fill_forward_path() is called with RCU lock held.
Fixes: 2830e314778d ("net: ethernet: mtk-ppe: fix traffic offload with bridged wlan") Signed-off-by: Qingfang Deng dqfext@gmail.com Link: https://patch.msgid.link/20250814012559.3705-1-dqfext@gmail.com Signed-off-by: Paolo Abeni pabeni@redhat.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/net/ethernet/mediatek/mtk_ppe_offload.c | 2 ++ 1 file changed, 2 insertions(+)
diff --git a/drivers/net/ethernet/mediatek/mtk_ppe_offload.c b/drivers/net/ethernet/mediatek/mtk_ppe_offload.c index c855fb799ce1..e9bd32741983 100644 --- a/drivers/net/ethernet/mediatek/mtk_ppe_offload.c +++ b/drivers/net/ethernet/mediatek/mtk_ppe_offload.c @@ -101,7 +101,9 @@ mtk_flow_get_wdma_info(struct net_device *dev, const u8 *addr, struct mtk_wdma_i if (!IS_ENABLED(CONFIG_NET_MEDIATEK_SOC_WED)) return -1;
+ rcu_read_lock(); err = dev_fill_forward_path(dev, addr, &stack); + rcu_read_unlock(); if (err) return err;
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Qingfang Deng dqfext@gmail.com
[ Upstream commit 0417adf367a0af11adf7ace849af4638cfb573f7 ]
ppp_fill_forward_path() has two race conditions:
1. The ppp->channels list can change between list_empty() and list_first_entry(), as ppp_lock() is not held. If the only channel is deleted in ppp_disconnect_channel(), list_first_entry() may access an empty head or a freed entry, and trigger a panic.
2. pch->chan can be NULL. When ppp_unregister_channel() is called, pch->chan is set to NULL before pch is removed from ppp->channels.
Fix these by using a lockless RCU approach: - Use list_first_or_null_rcu() to safely test and access the first list entry. - Convert list modifications on ppp->channels to their RCU variants and add synchronize_net() after removal. - Check for a NULL pch->chan before dereferencing it.
Fixes: f6efc675c9dd ("net: ppp: resolve forwarding path for bridge pppoe devices") Signed-off-by: Qingfang Deng dqfext@gmail.com Link: https://patch.msgid.link/20250814012559.3705-2-dqfext@gmail.com Signed-off-by: Paolo Abeni pabeni@redhat.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/net/ppp/ppp_generic.c | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-)
diff --git a/drivers/net/ppp/ppp_generic.c b/drivers/net/ppp/ppp_generic.c index def84e87e05b..5e7672d2022c 100644 --- a/drivers/net/ppp/ppp_generic.c +++ b/drivers/net/ppp/ppp_generic.c @@ -33,6 +33,7 @@ #include <linux/ppp_channel.h> #include <linux/ppp-comp.h> #include <linux/skbuff.h> +#include <linux/rculist.h> #include <linux/rtnetlink.h> #include <linux/if_arp.h> #include <linux/ip.h> @@ -1612,11 +1613,14 @@ static int ppp_fill_forward_path(struct net_device_path_ctx *ctx, if (ppp->flags & SC_MULTILINK) return -EOPNOTSUPP;
- if (list_empty(&ppp->channels)) + pch = list_first_or_null_rcu(&ppp->channels, struct channel, clist); + if (!pch) + return -ENODEV; + + chan = READ_ONCE(pch->chan); + if (!chan) return -ENODEV;
- pch = list_first_entry(&ppp->channels, struct channel, clist); - chan = pch->chan; if (!chan->ops->fill_forward_path) return -EOPNOTSUPP;
@@ -2999,7 +3003,7 @@ ppp_unregister_channel(struct ppp_channel *chan) */ down_write(&pch->chan_sem); spin_lock_bh(&pch->downl); - pch->chan = NULL; + WRITE_ONCE(pch->chan, NULL); spin_unlock_bh(&pch->downl); up_write(&pch->chan_sem); ppp_disconnect_channel(pch); @@ -3509,7 +3513,7 @@ ppp_connect_channel(struct channel *pch, int unit) hdrlen = pch->file.hdrlen + 2; /* for protocol bytes */ if (hdrlen > ppp->dev->hard_header_len) ppp->dev->hard_header_len = hdrlen; - list_add_tail(&pch->clist, &ppp->channels); + list_add_tail_rcu(&pch->clist, &ppp->channels); ++ppp->n_channels; pch->ppp = ppp; refcount_inc(&ppp->file.refcnt); @@ -3539,10 +3543,11 @@ ppp_disconnect_channel(struct channel *pch) if (ppp) { /* remove it from the ppp unit's list */ ppp_lock(ppp); - list_del(&pch->clist); + list_del_rcu(&pch->clist); if (--ppp->n_channels == 0) wake_up_interruptible(&ppp->file.rwait); ppp_unlock(ppp); + synchronize_net(); if (refcount_dec_and_test(&ppp->file.refcnt)) ppp_destroy_interface(ppp); err = 0;
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: MD Danish Anwar danishanwar@ti.com
[ Upstream commit 01792bc3e5bdafa171dd83c7073f00e7de93a653 ]
To enable HSR / Switch offload, certain configurations are needed. Currently they are done inside icssg_change_mode(). This function only gets called if we move from one mode to another without bringing the links up / down.
Once in HSR / Switch mode, if we bring the links down and bring it back up again. The callback sequence is,
- emac_ndo_stop() Firmwares are stopped - emac_ndo_open() Firmwares are loaded
In this path icssg_change_mode() doesn't get called and as a result the configurations needed for HSR / Switch is not done.
To fix this, put all these configurations in a separate function icssg_enable_fw_offload() and call this from both icssg_change_mode() and emac_ndo_open()
Fixes: 56375086d093 ("net: ti: icssg-prueth: Enable HSR Tx duplication, Tx Tag and Rx Tag offload") Signed-off-by: MD Danish Anwar danishanwar@ti.com Link: https://patch.msgid.link/20250814105106.1491871-1-danishanwar@ti.com Signed-off-by: Paolo Abeni pabeni@redhat.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/net/ethernet/ti/icssg/icssg_prueth.c | 72 +++++++++++--------- 1 file changed, 41 insertions(+), 31 deletions(-)
diff --git a/drivers/net/ethernet/ti/icssg/icssg_prueth.c b/drivers/net/ethernet/ti/icssg/icssg_prueth.c index 008d77727400..f436d7cf565a 100644 --- a/drivers/net/ethernet/ti/icssg/icssg_prueth.c +++ b/drivers/net/ethernet/ti/icssg/icssg_prueth.c @@ -240,6 +240,44 @@ static void prueth_emac_stop(struct prueth *prueth) } }
+static void icssg_enable_fw_offload(struct prueth *prueth) +{ + struct prueth_emac *emac; + int mac; + + for (mac = PRUETH_MAC0; mac < PRUETH_NUM_MACS; mac++) { + emac = prueth->emac[mac]; + if (prueth->is_hsr_offload_mode) { + if (emac->ndev->features & NETIF_F_HW_HSR_TAG_RM) + icssg_set_port_state(emac, ICSSG_EMAC_HSR_RX_OFFLOAD_ENABLE); + else + icssg_set_port_state(emac, ICSSG_EMAC_HSR_RX_OFFLOAD_DISABLE); + } + + if (prueth->is_switch_mode || prueth->is_hsr_offload_mode) { + if (netif_running(emac->ndev)) { + icssg_fdb_add_del(emac, eth_stp_addr, prueth->default_vlan, + ICSSG_FDB_ENTRY_P0_MEMBERSHIP | + ICSSG_FDB_ENTRY_P1_MEMBERSHIP | + ICSSG_FDB_ENTRY_P2_MEMBERSHIP | + ICSSG_FDB_ENTRY_BLOCK, + true); + icssg_vtbl_modify(emac, emac->port_vlan | DEFAULT_VID, + BIT(emac->port_id) | DEFAULT_PORT_MASK, + BIT(emac->port_id) | DEFAULT_UNTAG_MASK, + true); + if (prueth->is_hsr_offload_mode) + icssg_vtbl_modify(emac, DEFAULT_VID, + DEFAULT_PORT_MASK, + DEFAULT_UNTAG_MASK, true); + icssg_set_pvid(prueth, emac->port_vlan, emac->port_id); + if (prueth->is_switch_mode) + icssg_set_port_state(emac, ICSSG_EMAC_PORT_VLAN_AWARE_ENABLE); + } + } + } +} + static int prueth_emac_common_start(struct prueth *prueth) { struct prueth_emac *emac; @@ -790,6 +828,7 @@ static int emac_ndo_open(struct net_device *ndev) ret = prueth_emac_common_start(prueth); if (ret) goto free_rx_irq; + icssg_enable_fw_offload(prueth); }
flow_cfg = emac->dram.va + ICSSG_CONFIG_OFFSET + PSI_L_REGULAR_FLOW_ID_BASE_OFFSET; @@ -1397,8 +1436,7 @@ static int prueth_emac_restart(struct prueth *prueth)
static void icssg_change_mode(struct prueth *prueth) { - struct prueth_emac *emac; - int mac, ret; + int ret;
ret = prueth_emac_restart(prueth); if (ret) { @@ -1406,35 +1444,7 @@ static void icssg_change_mode(struct prueth *prueth) return; }
- for (mac = PRUETH_MAC0; mac < PRUETH_NUM_MACS; mac++) { - emac = prueth->emac[mac]; - if (prueth->is_hsr_offload_mode) { - if (emac->ndev->features & NETIF_F_HW_HSR_TAG_RM) - icssg_set_port_state(emac, ICSSG_EMAC_HSR_RX_OFFLOAD_ENABLE); - else - icssg_set_port_state(emac, ICSSG_EMAC_HSR_RX_OFFLOAD_DISABLE); - } - - if (netif_running(emac->ndev)) { - icssg_fdb_add_del(emac, eth_stp_addr, prueth->default_vlan, - ICSSG_FDB_ENTRY_P0_MEMBERSHIP | - ICSSG_FDB_ENTRY_P1_MEMBERSHIP | - ICSSG_FDB_ENTRY_P2_MEMBERSHIP | - ICSSG_FDB_ENTRY_BLOCK, - true); - icssg_vtbl_modify(emac, emac->port_vlan | DEFAULT_VID, - BIT(emac->port_id) | DEFAULT_PORT_MASK, - BIT(emac->port_id) | DEFAULT_UNTAG_MASK, - true); - if (prueth->is_hsr_offload_mode) - icssg_vtbl_modify(emac, DEFAULT_VID, - DEFAULT_PORT_MASK, - DEFAULT_UNTAG_MASK, true); - icssg_set_pvid(prueth, emac->port_vlan, emac->port_id); - if (prueth->is_switch_mode) - icssg_set_port_state(emac, ICSSG_EMAC_PORT_VLAN_AWARE_ENABLE); - } - } + icssg_enable_fw_offload(prueth); }
static int prueth_netdevice_port_link(struct net_device *ndev,
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Piotr Piórkowski piotr.piorkowski@intel.com
[ Upstream commit 658a1c8e0a66d0777e0e37a11ba19f27a81e77f4 ]
In several code paths, such as xe_pt_create(), the vm->xef field is used to determine whether a VM originates from userspace or the kernel.
Previously, this handler was only assigned in xe_vm_create_ioctl(), after the VM was created by xe_vm_create(). However, xe_vm_create() triggers page table creation, and that function assumes vm->xef should be already set. This could lead to incorrect origin detection.
To fix this problem and ensure consistency in the initialization of the VM object, let's move the assignment of this handler to xe_vm_create.
v2: - take reference to the xe file object only when xef is not NULL - release the reference to the xe file object on the error path (Matthew)
Fixes: 7f387e6012b6 ("drm/xe: add XE_BO_FLAG_PINNED_LATE_RESTORE") Signed-off-by: Piotr Piórkowski piotr.piorkowski@intel.com Cc: Matthew Auld matthew.auld@intel.com Reviewed-by: Matthew Auld matthew.auld@intel.com Link: https://lore.kernel.org/r/20250811104358.2064150-2-piotr.piorkowski@intel.co... Signed-off-by: Michał Winiarski michal.winiarski@intel.com (cherry picked from commit 9337166fa1d80f7bb7c7d3a8f901f21c348c0f2a) Signed-off-by: Rodrigo Vivi rodrigo.vivi@intel.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/gpu/drm/xe/xe_migrate.c | 2 +- drivers/gpu/drm/xe/xe_pxp_submit.c | 2 +- drivers/gpu/drm/xe/xe_vm.c | 11 ++++++----- drivers/gpu/drm/xe/xe_vm.h | 2 +- 4 files changed, 9 insertions(+), 8 deletions(-)
diff --git a/drivers/gpu/drm/xe/xe_migrate.c b/drivers/gpu/drm/xe/xe_migrate.c index 1e3fd139dfcb..0a481190f3e6 100644 --- a/drivers/gpu/drm/xe/xe_migrate.c +++ b/drivers/gpu/drm/xe/xe_migrate.c @@ -408,7 +408,7 @@ struct xe_migrate *xe_migrate_init(struct xe_tile *tile)
/* Special layout, prepared below.. */ vm = xe_vm_create(xe, XE_VM_FLAG_MIGRATION | - XE_VM_FLAG_SET_TILE_ID(tile)); + XE_VM_FLAG_SET_TILE_ID(tile), NULL); if (IS_ERR(vm)) return ERR_CAST(vm);
diff --git a/drivers/gpu/drm/xe/xe_pxp_submit.c b/drivers/gpu/drm/xe/xe_pxp_submit.c index d92ec0f515b0..ca95f2a4d4ef 100644 --- a/drivers/gpu/drm/xe/xe_pxp_submit.c +++ b/drivers/gpu/drm/xe/xe_pxp_submit.c @@ -101,7 +101,7 @@ static int allocate_gsc_client_resources(struct xe_gt *gt, xe_assert(xe, hwe);
/* PXP instructions must be issued from PPGTT */ - vm = xe_vm_create(xe, XE_VM_FLAG_GSC); + vm = xe_vm_create(xe, XE_VM_FLAG_GSC, NULL); if (IS_ERR(vm)) return PTR_ERR(vm);
diff --git a/drivers/gpu/drm/xe/xe_vm.c b/drivers/gpu/drm/xe/xe_vm.c index 861577746929..7251f23b919c 100644 --- a/drivers/gpu/drm/xe/xe_vm.c +++ b/drivers/gpu/drm/xe/xe_vm.c @@ -1612,7 +1612,7 @@ static void xe_vm_free_scratch(struct xe_vm *vm) } }
-struct xe_vm *xe_vm_create(struct xe_device *xe, u32 flags) +struct xe_vm *xe_vm_create(struct xe_device *xe, u32 flags, struct xe_file *xef) { struct drm_gem_object *vm_resv_obj; struct xe_vm *vm; @@ -1633,9 +1633,10 @@ struct xe_vm *xe_vm_create(struct xe_device *xe, u32 flags) vm->xe = xe;
vm->size = 1ull << xe->info.va_bits; - vm->flags = flags;
+ if (xef) + vm->xef = xe_file_get(xef); /** * GSC VMs are kernel-owned, only used for PXP ops and can sometimes be * manipulated under the PXP mutex. However, the PXP mutex can be taken @@ -1786,6 +1787,8 @@ struct xe_vm *xe_vm_create(struct xe_device *xe, u32 flags) for_each_tile(tile, xe, id) xe_range_fence_tree_fini(&vm->rftree[id]); ttm_lru_bulk_move_fini(&xe->ttm, &vm->lru_bulk_move); + if (vm->xef) + xe_file_put(vm->xef); kfree(vm); if (flags & XE_VM_FLAG_LR_MODE) xe_pm_runtime_put(xe); @@ -2069,7 +2072,7 @@ int xe_vm_create_ioctl(struct drm_device *dev, void *data, if (args->flags & DRM_XE_VM_CREATE_FLAG_FAULT_MODE) flags |= XE_VM_FLAG_FAULT_MODE;
- vm = xe_vm_create(xe, flags); + vm = xe_vm_create(xe, flags, xef); if (IS_ERR(vm)) return PTR_ERR(vm);
@@ -2085,8 +2088,6 @@ int xe_vm_create_ioctl(struct drm_device *dev, void *data, vm->usm.asid = asid; }
- vm->xef = xe_file_get(xef); - /* Record BO memory for VM pagetable created against client */ for_each_tile(tile, xe, id) if (vm->pt_root[id]) diff --git a/drivers/gpu/drm/xe/xe_vm.h b/drivers/gpu/drm/xe/xe_vm.h index 494af6bdc646..0158ec0ae3b2 100644 --- a/drivers/gpu/drm/xe/xe_vm.h +++ b/drivers/gpu/drm/xe/xe_vm.h @@ -26,7 +26,7 @@ struct xe_sync_entry; struct xe_svm_range; struct drm_exec;
-struct xe_vm *xe_vm_create(struct xe_device *xe, u32 flags); +struct xe_vm *xe_vm_create(struct xe_device *xe, u32 flags, struct xe_file *xef);
struct xe_vm *xe_vm_lookup(struct xe_file *xef, u32 id); int xe_vma_cmp_vma_cb(const void *key, const struct rb_node *node);
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Dan Carpenter dan.carpenter@linaro.org
[ Upstream commit 11cd7a5c21db020b8001aedcae27bd3fa9e1e901 ]
There is a copy and paste error and we accidentally use "PTR_ERR(rdev)" instead of "error". The "rdev" pointer is valid at this point.
Also there is no need to print the error code in the error message because dev_err_probe() already prints that. So clean up the error message a bit.
Fixes: 38c9f98db20a ("regulator: tps65219: Add support for TPS65215 Regulator IRQs") Signed-off-by: Dan Carpenter dan.carpenter@linaro.org Link: https://patch.msgid.link/aKRGmVdbvT1HBvm8@stanley.mountain Signed-off-by: Mark Brown broonie@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/regulator/tps65219-regulator.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-)
diff --git a/drivers/regulator/tps65219-regulator.c b/drivers/regulator/tps65219-regulator.c index 5e67fdc88f49..d77ca486879f 100644 --- a/drivers/regulator/tps65219-regulator.c +++ b/drivers/regulator/tps65219-regulator.c @@ -454,9 +454,9 @@ static int tps65219_regulator_probe(struct platform_device *pdev) irq_type->irq_name, irq_data); if (error) - return dev_err_probe(tps->dev, PTR_ERR(rdev), - "Failed to request %s IRQ %d: %d\n", - irq_type->irq_name, irq, error); + return dev_err_probe(tps->dev, error, + "Failed to request %s IRQ %d\n", + irq_type->irq_name, irq); }
for (i = 0; i < pmic->dev_irq_size; ++i) { @@ -477,9 +477,9 @@ static int tps65219_regulator_probe(struct platform_device *pdev) irq_type->irq_name, irq_data); if (error) - return dev_err_probe(tps->dev, PTR_ERR(rdev), - "Failed to request %s IRQ %d: %d\n", - irq_type->irq_name, irq, error); + return dev_err_probe(tps->dev, error, + "Failed to request %s IRQ %d\n", + irq_type->irq_name, irq); }
return 0;
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: David Howells dhowells@redhat.com
[ Upstream commit 453a6d2a68e54a483d67233c6e1e24c4095ee4be ]
Fix smb3_init_transform_rq() to initialise buffer to NULL before calling netfs_alloc_folioq_buffer() as netfs assumes it can append to the buffer it is given. Setting it to NULL means it should start a fresh buffer, but the value is currently undefined.
Fixes: a2906d3316fc ("cifs: Switch crypto buffer to use a folio_queue rather than an xarray") Signed-off-by: David Howells dhowells@redhat.com cc: Steve French sfrench@samba.org cc: Paulo Alcantara pc@manguebit.org cc: linux-cifs@vger.kernel.org cc: linux-fsdevel@vger.kernel.org Signed-off-by: Steve French stfrench@microsoft.com Signed-off-by: Sasha Levin sashal@kernel.org --- fs/smb/client/smb2ops.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/fs/smb/client/smb2ops.c b/fs/smb/client/smb2ops.c index 4bb065a6fbaa..d3e09b10dea4 100644 --- a/fs/smb/client/smb2ops.c +++ b/fs/smb/client/smb2ops.c @@ -4496,7 +4496,7 @@ smb3_init_transform_rq(struct TCP_Server_Info *server, int num_rqst, for (int i = 1; i < num_rqst; i++) { struct smb_rqst *old = &old_rq[i - 1]; struct smb_rqst *new = &new_rq[i]; - struct folio_queue *buffer; + struct folio_queue *buffer = NULL; size_t size = iov_iter_count(&old->rq_iter);
orig_len += smb_rqst_len(server, old);
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Horatiu Vultur horatiu.vultur@microchip.com
[ Upstream commit bc1a59cff9f797bfbf8f3104507584d89e9ecf2e ]
There was a problem when we received frames and the frames were timestamped. The driver is configured to store the nanosecond part of the timestmap in the ptp reserved bits and it would take the second part by reading the LTC. The problem is that when reading the LTC we are in atomic context and to read the second part will go over mdio bus which might sleep, so we get an error. The fix consists in actually put all the frames in a queue and start the aux work and in that work to read the LTC and then calculate the full received time.
Fixes: 7d272e63e0979d ("net: phy: mscc: timestamping and PHC support") Signed-off-by: Horatiu Vultur horatiu.vultur@microchip.com Reviewed-by: Vadim Fedorenko vadim.fedorenko@linux.dev Reviewed-by: Vladimir Oltean vladimir.oltean@nxp.com Link: https://patch.msgid.link/20250818081029.1300780-1-horatiu.vultur@microchip.c... Signed-off-by: Jakub Kicinski kuba@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/net/phy/mscc/mscc.h | 12 ++++++++ drivers/net/phy/mscc/mscc_main.c | 12 ++++++++ drivers/net/phy/mscc/mscc_ptp.c | 49 ++++++++++++++++++++++++-------- 3 files changed, 61 insertions(+), 12 deletions(-)
diff --git a/drivers/net/phy/mscc/mscc.h b/drivers/net/phy/mscc/mscc.h index 6a3d8a754eb8..58c6d47fbe04 100644 --- a/drivers/net/phy/mscc/mscc.h +++ b/drivers/net/phy/mscc/mscc.h @@ -362,6 +362,13 @@ struct vsc85xx_hw_stat { u16 mask; };
+struct vsc8531_skb_cb { + u32 ns; +}; + +#define VSC8531_SKB_CB(skb) \ + ((struct vsc8531_skb_cb *)((skb)->cb)) + struct vsc8531_private { int rate_magic; u16 supp_led_modes; @@ -410,6 +417,11 @@ struct vsc8531_private { */ struct mutex ts_lock; struct mutex phc_lock; + + /* list of skbs that were received and need timestamp information but it + * didn't received it yet + */ + struct sk_buff_head rx_skbs_list; };
/* Shared structure between the PHYs of the same package. diff --git a/drivers/net/phy/mscc/mscc_main.c b/drivers/net/phy/mscc/mscc_main.c index 7ff975efd8e7..c3209cf00e96 100644 --- a/drivers/net/phy/mscc/mscc_main.c +++ b/drivers/net/phy/mscc/mscc_main.c @@ -2336,6 +2336,13 @@ static int vsc85xx_probe(struct phy_device *phydev) return vsc85xx_dt_led_modes_get(phydev, default_mode); }
+static void vsc85xx_remove(struct phy_device *phydev) +{ + struct vsc8531_private *priv = phydev->priv; + + skb_queue_purge(&priv->rx_skbs_list); +} + /* Microsemi VSC85xx PHYs */ static struct phy_driver vsc85xx_driver[] = { { @@ -2590,6 +2597,7 @@ static struct phy_driver vsc85xx_driver[] = { .config_intr = &vsc85xx_config_intr, .suspend = &genphy_suspend, .resume = &genphy_resume, + .remove = &vsc85xx_remove, .probe = &vsc8574_probe, .set_wol = &vsc85xx_wol_set, .get_wol = &vsc85xx_wol_get, @@ -2615,6 +2623,7 @@ static struct phy_driver vsc85xx_driver[] = { .config_intr = &vsc85xx_config_intr, .suspend = &genphy_suspend, .resume = &genphy_resume, + .remove = &vsc85xx_remove, .probe = &vsc8574_probe, .set_wol = &vsc85xx_wol_set, .get_wol = &vsc85xx_wol_get, @@ -2640,6 +2649,7 @@ static struct phy_driver vsc85xx_driver[] = { .config_intr = &vsc85xx_config_intr, .suspend = &genphy_suspend, .resume = &genphy_resume, + .remove = &vsc85xx_remove, .probe = &vsc8584_probe, .get_tunable = &vsc85xx_get_tunable, .set_tunable = &vsc85xx_set_tunable, @@ -2663,6 +2673,7 @@ static struct phy_driver vsc85xx_driver[] = { .config_intr = &vsc85xx_config_intr, .suspend = &genphy_suspend, .resume = &genphy_resume, + .remove = &vsc85xx_remove, .probe = &vsc8584_probe, .get_tunable = &vsc85xx_get_tunable, .set_tunable = &vsc85xx_set_tunable, @@ -2686,6 +2697,7 @@ static struct phy_driver vsc85xx_driver[] = { .config_intr = &vsc85xx_config_intr, .suspend = &genphy_suspend, .resume = &genphy_resume, + .remove = &vsc85xx_remove, .probe = &vsc8584_probe, .get_tunable = &vsc85xx_get_tunable, .set_tunable = &vsc85xx_set_tunable, diff --git a/drivers/net/phy/mscc/mscc_ptp.c b/drivers/net/phy/mscc/mscc_ptp.c index 275706de5847..de6c7312e8f2 100644 --- a/drivers/net/phy/mscc/mscc_ptp.c +++ b/drivers/net/phy/mscc/mscc_ptp.c @@ -1194,9 +1194,7 @@ static bool vsc85xx_rxtstamp(struct mii_timestamper *mii_ts, { struct vsc8531_private *vsc8531 = container_of(mii_ts, struct vsc8531_private, mii_ts); - struct skb_shared_hwtstamps *shhwtstamps = NULL; struct vsc85xx_ptphdr *ptphdr; - struct timespec64 ts; unsigned long ns;
if (!vsc8531->ptp->configured) @@ -1206,27 +1204,52 @@ static bool vsc85xx_rxtstamp(struct mii_timestamper *mii_ts, type == PTP_CLASS_NONE) return false;
- vsc85xx_gettime(&vsc8531->ptp->caps, &ts); - ptphdr = get_ptp_header_rx(skb, vsc8531->ptp->rx_filter); if (!ptphdr) return false;
- shhwtstamps = skb_hwtstamps(skb); - memset(shhwtstamps, 0, sizeof(struct skb_shared_hwtstamps)); - ns = ntohl(ptphdr->rsrvd2);
- /* nsec is in reserved field */ - if (ts.tv_nsec < ns) - ts.tv_sec--; + VSC8531_SKB_CB(skb)->ns = ns; + skb_queue_tail(&vsc8531->rx_skbs_list, skb);
- shhwtstamps->hwtstamp = ktime_set(ts.tv_sec, ns); - netif_rx(skb); + ptp_schedule_worker(vsc8531->ptp->ptp_clock, 0);
return true; }
+static long vsc85xx_do_aux_work(struct ptp_clock_info *info) +{ + struct vsc85xx_ptp *ptp = container_of(info, struct vsc85xx_ptp, caps); + struct skb_shared_hwtstamps *shhwtstamps = NULL; + struct phy_device *phydev = ptp->phydev; + struct vsc8531_private *priv = phydev->priv; + struct sk_buff_head received; + struct sk_buff *rx_skb; + struct timespec64 ts; + unsigned long flags; + + __skb_queue_head_init(&received); + spin_lock_irqsave(&priv->rx_skbs_list.lock, flags); + skb_queue_splice_tail_init(&priv->rx_skbs_list, &received); + spin_unlock_irqrestore(&priv->rx_skbs_list.lock, flags); + + vsc85xx_gettime(info, &ts); + while ((rx_skb = __skb_dequeue(&received)) != NULL) { + shhwtstamps = skb_hwtstamps(rx_skb); + memset(shhwtstamps, 0, sizeof(struct skb_shared_hwtstamps)); + + if (ts.tv_nsec < VSC8531_SKB_CB(rx_skb)->ns) + ts.tv_sec--; + + shhwtstamps->hwtstamp = ktime_set(ts.tv_sec, + VSC8531_SKB_CB(rx_skb)->ns); + netif_rx(rx_skb); + } + + return -1; +} + static const struct ptp_clock_info vsc85xx_clk_caps = { .owner = THIS_MODULE, .name = "VSC85xx timer", @@ -1240,6 +1263,7 @@ static const struct ptp_clock_info vsc85xx_clk_caps = { .adjfine = &vsc85xx_adjfine, .gettime64 = &vsc85xx_gettime, .settime64 = &vsc85xx_settime, + .do_aux_work = &vsc85xx_do_aux_work, };
static struct vsc8531_private *vsc8584_base_priv(struct phy_device *phydev) @@ -1567,6 +1591,7 @@ int vsc8584_ptp_probe(struct phy_device *phydev)
mutex_init(&vsc8531->phc_lock); mutex_init(&vsc8531->ts_lock); + skb_queue_head_init(&vsc8531->rx_skbs_list);
/* Retrieve the shared load/save GPIO. Request it as non exclusive as * the same GPIO can be requested by all the PHYs of the same package.
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Yuichiro Tsuji yuichtsu@amazon.com
[ Upstream commit 24ef2f53c07f273bad99173e27ee88d44d135b1c ]
Syzbot reported shift-out-of-bounds exception on MDIO bus initialization.
The PHY address should be masked to 5 bits (0-31). Without this mask, invalid PHY addresses could be used, potentially causing issues with MDIO bus operations.
Fix this by masking the PHY address with 0x1f (31 decimal) to ensure it stays within the valid range.
Fixes: 4faff70959d5 ("net: usb: asix_devices: add phy_mask for ax88772 mdio bus") Reported-by: syzbot+20537064367a0f98d597@syzkaller.appspotmail.com Closes: https://syzkaller.appspot.com/bug?extid=20537064367a0f98d597 Tested-by: syzbot+20537064367a0f98d597@syzkaller.appspotmail.com Signed-off-by: Yuichiro Tsuji yuichtsu@amazon.com Reviewed-by: Andrew Lunn andrew@lunn.ch Link: https://patch.msgid.link/20250818084541.1958-1-yuichtsu@amazon.com Signed-off-by: Jakub Kicinski kuba@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/net/usb/asix_devices.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/net/usb/asix_devices.c b/drivers/net/usb/asix_devices.c index d9f5942ccc44..792ddda1ad49 100644 --- a/drivers/net/usb/asix_devices.c +++ b/drivers/net/usb/asix_devices.c @@ -676,7 +676,7 @@ static int ax88772_init_mdio(struct usbnet *dev) priv->mdio->read = &asix_mdio_bus_read; priv->mdio->write = &asix_mdio_bus_write; priv->mdio->name = "Asix MDIO Bus"; - priv->mdio->phy_mask = ~(BIT(priv->phy_addr) | BIT(AX_EMBD_PHY_ADDR)); + priv->mdio->phy_mask = ~(BIT(priv->phy_addr & 0x1f) | BIT(AX_EMBD_PHY_ADDR)); /* mii bus name is usb-<usb bus number>-<usb device number> */ snprintf(priv->mdio->id, MII_BUS_ID_SIZE, "usb-%03d:%03d", dev->udev->bus->busnum, dev->udev->devnum);
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jordan Rhee jordanrhee@google.com
[ Upstream commit 75a9a46d67f46d608205888f9b34e315c1786345 ]
A crash can occur if an ethtool operation is invoked after shutdown() is called.
shutdown() is invoked during system shutdown to stop DMA operations without performing expensive deallocations. It is discouraged to unregister the netdev in this path, so the device may still be visible to userspace and kernel helpers.
In gve, shutdown() tears down most internal data structures. If an ethtool operation is dispatched after shutdown(), it will dereference freed or NULL pointers, leading to a kernel panic. While graceful shutdown normally quiesces userspace before invoking the reboot syscall, forced shutdowns (as observed on GCP VMs) can still trigger this path.
Fix by calling netif_device_detach() in shutdown(). This marks the device as detached so the ethtool ioctl handler will skip dispatching operations to the driver.
Fixes: 974365e51861 ("gve: Implement suspend/resume/shutdown") Signed-off-by: Jordan Rhee jordanrhee@google.com Signed-off-by: Jeroen de Borst jeroendb@google.com Link: https://patch.msgid.link/20250818211245.1156919-1-jeroendb@google.com Signed-off-by: Jakub Kicinski kuba@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/net/ethernet/google/gve/gve_main.c | 2 ++ 1 file changed, 2 insertions(+)
diff --git a/drivers/net/ethernet/google/gve/gve_main.c b/drivers/net/ethernet/google/gve/gve_main.c index d1aeb722d48f..36a6d766b638 100644 --- a/drivers/net/ethernet/google/gve/gve_main.c +++ b/drivers/net/ethernet/google/gve/gve_main.c @@ -2726,6 +2726,8 @@ static void gve_shutdown(struct pci_dev *pdev) struct gve_priv *priv = netdev_priv(netdev); bool was_up = netif_running(priv->dev);
+ netif_device_detach(netdev); + rtnl_lock(); netdev_lock(netdev); if (was_up && gve_close(priv->dev)) {
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Yao Zi ziyao@disroot.org
[ Upstream commit 6d6714bf0c4e8eb2274081b4b023dfa01581c123 ]
The clk_tx_i clock must be supplied to the MAC for successful initialization. On TH1520 SoC, the clock is provided by an internal divider configured through GMAC_PLLCLK_DIV register when using RGMII interface. However, currently we don't setup the divider before initialization of the MAC, resulting in DMA reset failures if the bootloader/firmware doesn't enable the divider,
[ 7.839601] thead-dwmac ffe7060000.ethernet eth0: Register MEM_TYPE_PAGE_POOL RxQ-0 [ 7.938338] thead-dwmac ffe7060000.ethernet eth0: PHY [stmmac-0:02] driver [RTL8211F Gigabit Ethernet] (irq=POLL) [ 8.160746] thead-dwmac ffe7060000.ethernet eth0: Failed to reset the dma [ 8.170118] thead-dwmac ffe7060000.ethernet eth0: stmmac_hw_setup: DMA engine initialization failed [ 8.179384] thead-dwmac ffe7060000.ethernet eth0: __stmmac_open: Hw setup failed
Let's simply write GMAC_PLLCLK_DIV_EN to GMAC_PLLCLK_DIV to enable the divider before MAC initialization. Note that for reconfiguring the divisor, the divider must be disabled first and re-enabled later to make sure the new divisor take effect.
The exact clock rate doesn't affect MAC's initialization according to my test. It's set to the speed required by RGMII when the linkspeed is 1Gbps and could be reclocked later after link is up if necessary.
Fixes: 33a1a01e3afa ("net: stmmac: Add glue layer for T-HEAD TH1520 SoC") Signed-off-by: Yao Zi ziyao@disroot.org Reviewed-by: Drew Fustini fustini@kernel.org Link: https://patch.msgid.link/20250815104803.55294-1-ziyao@disroot.org Signed-off-by: Jakub Kicinski kuba@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/net/ethernet/stmicro/stmmac/dwmac-thead.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-)
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-thead.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-thead.c index f2946bea0bc2..6c6c49e4b66f 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-thead.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-thead.c @@ -152,7 +152,7 @@ static int thead_set_clk_tx_rate(void *bsp_priv, struct clk *clk_tx_i, static int thead_dwmac_enable_clk(struct plat_stmmacenet_data *plat) { struct thead_dwmac *dwmac = plat->bsp_priv; - u32 reg; + u32 reg, div;
switch (plat->mac_interface) { case PHY_INTERFACE_MODE_MII: @@ -164,6 +164,13 @@ static int thead_dwmac_enable_clk(struct plat_stmmacenet_data *plat) case PHY_INTERFACE_MODE_RGMII_RXID: case PHY_INTERFACE_MODE_RGMII_TXID: /* use pll */ + div = clk_get_rate(plat->stmmac_clk) / rgmii_clock(SPEED_1000); + reg = FIELD_PREP(GMAC_PLLCLK_DIV_EN, 1) | + FIELD_PREP(GMAC_PLLCLK_DIV_NUM, div); + + writel(0, dwmac->apb_base + GMAC_PLLCLK_DIV); + writel(reg, dwmac->apb_base + GMAC_PLLCLK_DIV); + writel(GMAC_GTXCLK_SEL_PLL, dwmac->apb_base + GMAC_GTXCLK_SEL); reg = GMAC_TX_CLK_EN | GMAC_TX_CLK_N_EN | GMAC_TX_CLK_OUT_EN | GMAC_RX_CLK_EN | GMAC_RX_CLK_N_EN;
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: D. Wythe alibuda@linux.alibaba.com
[ Upstream commit d9cef55ed49117bd63695446fb84b4b91815c0b4 ]
BPF CI testing report a UAF issue:
[ 16.446633] BUG: kernel NULL pointer dereference, address: 000000000000003 0 [ 16.447134] #PF: supervisor read access in kernel mod e [ 16.447516] #PF: error_code(0x0000) - not-present pag e [ 16.447878] PGD 0 P4D 0 [ 16.448063] Oops: Oops: 0000 [#1] PREEMPT SMP NOPT I [ 16.448409] CPU: 0 UID: 0 PID: 9 Comm: kworker/0:1 Tainted: G OE 6.13.0-rc3-g89e8a75fda73-dirty #4 2 [ 16.449124] Tainted: [O]=OOT_MODULE, [E]=UNSIGNED_MODUL E [ 16.449502] Hardware name: QEMU Ubuntu 24.04 PC (i440FX + PIIX, 1996), BIOS 1.16.3-debian-1.16.3-2 04/01/201 4 [ 16.450201] Workqueue: smc_hs_wq smc_listen_wor k [ 16.450531] RIP: 0010:smc_listen_work+0xc02/0x159 0 [ 16.452158] RSP: 0018:ffffb5ab40053d98 EFLAGS: 0001024 6 [ 16.452526] RAX: 0000000000000001 RBX: 0000000000000002 RCX: 000000000000030 0 [ 16.452994] RDX: 0000000000000280 RSI: 00003513840053f0 RDI: 000000000000000 0 [ 16.453492] RBP: ffffa097808e3800 R08: ffffa09782dba1e0 R09: 000000000000000 5 [ 16.453987] R10: 0000000000000000 R11: 0000000000000000 R12: ffffa0978274640 0 [ 16.454497] R13: 0000000000000000 R14: 0000000000000000 R15: ffffa09782d4092 0 [ 16.454996] FS: 0000000000000000(0000) GS:ffffa097bbc00000(0000) knlGS:000000000000000 0 [ 16.455557] CS: 0010 DS: 0000 ES: 0000 CR0: 000000008005003 3 [ 16.455961] CR2: 0000000000000030 CR3: 0000000102788004 CR4: 0000000000770ef 0 [ 16.456459] PKRU: 5555555 4 [ 16.456654] Call Trace : [ 16.456832] <TASK > [ 16.456989] ? __die+0x23/0x7 0 [ 16.457215] ? page_fault_oops+0x180/0x4c 0 [ 16.457508] ? __lock_acquire+0x3e6/0x249 0 [ 16.457801] ? exc_page_fault+0x68/0x20 0 [ 16.458080] ? asm_exc_page_fault+0x26/0x3 0 [ 16.458389] ? smc_listen_work+0xc02/0x159 0 [ 16.458689] ? smc_listen_work+0xc02/0x159 0 [ 16.458987] ? lock_is_held_type+0x8f/0x10 0 [ 16.459284] process_one_work+0x1ea/0x6d 0 [ 16.459570] worker_thread+0x1c3/0x38 0 [ 16.459839] ? __pfx_worker_thread+0x10/0x1 0 [ 16.460144] kthread+0xe0/0x11 0 [ 16.460372] ? __pfx_kthread+0x10/0x1 0 [ 16.460640] ret_from_fork+0x31/0x5 0 [ 16.460896] ? __pfx_kthread+0x10/0x1 0 [ 16.461166] ret_from_fork_asm+0x1a/0x3 0 [ 16.461453] </TASK > [ 16.461616] Modules linked in: bpf_testmod(OE) [last unloaded: bpf_testmod(OE) ] [ 16.462134] CR2: 000000000000003 0 [ 16.462380] ---[ end trace 0000000000000000 ]--- [ 16.462710] RIP: 0010:smc_listen_work+0xc02/0x1590
The direct cause of this issue is that after smc_listen_out_connected(), newclcsock->sk may be NULL since it will releases the smcsk. Therefore, if the application closes the socket immediately after accept, newclcsock->sk can be NULL. A possible execution order could be as follows:
smc_listen_work | userspace ----------------------------------------------------------------- lock_sock(sk) | smc_listen_out_connected() | | - smc_listen_out | | | - release_sock | | |- sk->sk_data_ready() | | fd = accept(); | close(fd); | - socket->sk = NULL; /* newclcsock->sk is NULL now */ SMC_STAT_SERV_SUCC_INC(sock_net(newclcsock->sk))
Since smc_listen_out_connected() will not fail, simply swapping the order of the code can easily fix this issue.
Fixes: 3b2dec2603d5 ("net/smc: restructure client and server code in af_smc") Signed-off-by: D. Wythe alibuda@linux.alibaba.com Reviewed-by: Guangguan Wang guangguan.wang@linux.alibaba.com Reviewed-by: Alexandra Winter wintera@linux.ibm.com Reviewed-by: Dust Li dust.li@linux.alibaba.com Link: https://patch.msgid.link/20250818054618.41615-1-alibuda@linux.alibaba.com Signed-off-by: Jakub Kicinski kuba@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- net/smc/af_smc.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/net/smc/af_smc.c b/net/smc/af_smc.c index 1882bab8e00e..dc72ff353813 100644 --- a/net/smc/af_smc.c +++ b/net/smc/af_smc.c @@ -2568,8 +2568,9 @@ static void smc_listen_work(struct work_struct *work) goto out_decl; }
- smc_listen_out_connected(new_smc); SMC_STAT_SERV_SUCC_INC(sock_net(newclcsock->sk), ini); + /* smc_listen_out() will release smcsk */ + smc_listen_out_connected(new_smc); goto out_free;
out_unlock:
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Yevgeny Kliteynik kliteyn@nvidia.com
[ Upstream commit 2462c1b9217246a889ec318b3894d84e4dd709c6 ]
'cqe_sz' valid value should be 0 for 64-byte CQE.
Fixes: 2ca62599aa0b ("net/mlx5: HWS, added send engine and context handling") Signed-off-by: Yevgeny Kliteynik kliteyn@nvidia.com Reviewed-by: Vlad Dogaru vdogaru@nvidia.com Signed-off-by: Mark Bloch mbloch@nvidia.com Link: https://patch.msgid.link/20250817202323.308604-2-mbloch@nvidia.com Signed-off-by: Jakub Kicinski kuba@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/net/ethernet/mellanox/mlx5/core/steering/hws/send.c | 1 - 1 file changed, 1 deletion(-)
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/send.c b/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/send.c index c4b22be19a9b..b0595c9b09e4 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/send.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/send.c @@ -964,7 +964,6 @@ static int hws_send_ring_open_cq(struct mlx5_core_dev *mdev, return -ENOMEM;
MLX5_SET(cqc, cqc_data, uar_page, mdev->priv.uar->index); - MLX5_SET(cqc, cqc_data, cqe_sz, queue->num_entries); MLX5_SET(cqc, cqc_data, log_cq_size, ilog2(queue->num_entries));
err = hws_send_ring_alloc_cq(mdev, numa_node, queue, cqc_data, cq);
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Yevgeny Kliteynik kliteyn@nvidia.com
[ Upstream commit 4a842b1bf18a32ee0c25dd6dd98728b786a76fe4 ]
Moving rules from matcher to matcher should not fail. However, if it does fail due to various reasons, the error flow should allow the kernel to continue functioning (albeit with broken steering rules) instead of going into series of soft lock-ups or some other problematic behaviour.
Similar to the simple rules, complex rules rehash logic suffers from the same problems. This patch fixes the error flow for moving complex rules: - If new rule creation fails before it was even enqeued, do not poll for completion - If TIMEOUT happened while moving the rule, no point trying to poll for completions for other rules. Something is broken, completion won't come, just abort the rehash sequence. - If some other completion with error received, don't give up. Continue handling rest of the rules to minimize the damage. - Make sure that the first error code that was received will be actually returned to the caller instead of replacing it with the generic error code.
All the aforementioned issues stem from the same bad error flow, so no point fixing them one by one and leaving partially broken code - fixing them in one patch.
Fixes: 17e0accac577 ("net/mlx5: HWS, support complex matchers") Signed-off-by: Yevgeny Kliteynik kliteyn@nvidia.com Reviewed-by: Vlad Dogaru vdogaru@nvidia.com Signed-off-by: Mark Bloch mbloch@nvidia.com Link: https://patch.msgid.link/20250817202323.308604-4-mbloch@nvidia.com Signed-off-by: Jakub Kicinski kuba@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- .../mlx5/core/steering/hws/bwc_complex.c | 41 +++++++++++++------ 1 file changed, 28 insertions(+), 13 deletions(-)
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/bwc_complex.c b/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/bwc_complex.c index ca7501c57468..14e79579c719 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/bwc_complex.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/bwc_complex.c @@ -1328,11 +1328,11 @@ mlx5hws_bwc_matcher_move_all_complex(struct mlx5hws_bwc_matcher *bwc_matcher) { struct mlx5hws_context *ctx = bwc_matcher->matcher->tbl->ctx; struct mlx5hws_matcher *matcher = bwc_matcher->matcher; - bool move_error = false, poll_error = false; u16 bwc_queues = mlx5hws_bwc_queues(ctx); struct mlx5hws_bwc_rule *tmp_bwc_rule; struct mlx5hws_rule_attr rule_attr; struct mlx5hws_table *isolated_tbl; + int move_error = 0, poll_error = 0; struct mlx5hws_rule *tmp_rule; struct list_head *rules_list; u32 expected_completions = 1; @@ -1391,11 +1391,15 @@ mlx5hws_bwc_matcher_move_all_complex(struct mlx5hws_bwc_matcher *bwc_matcher) ret = mlx5hws_matcher_resize_rule_move(matcher, tmp_rule, &rule_attr); - if (unlikely(ret && !move_error)) { - mlx5hws_err(ctx, - "Moving complex BWC rule failed (%d), attempting to move rest of the rules\n", - ret); - move_error = true; + if (unlikely(ret)) { + if (!move_error) { + mlx5hws_err(ctx, + "Moving complex BWC rule: move failed (%d), attempting to move rest of the rules\n", + ret); + move_error = ret; + } + /* Rule wasn't queued, no need to poll */ + continue; }
expected_completions = 1; @@ -1403,11 +1407,19 @@ mlx5hws_bwc_matcher_move_all_complex(struct mlx5hws_bwc_matcher *bwc_matcher) rule_attr.queue_id, &expected_completions, true); - if (unlikely(ret && !poll_error)) { - mlx5hws_err(ctx, - "Moving complex BWC rule: poll failed (%d), attempting to move rest of the rules\n", - ret); - poll_error = true; + if (unlikely(ret)) { + if (ret == -ETIMEDOUT) { + mlx5hws_err(ctx, + "Moving complex BWC rule: timeout polling for completions (%d), aborting rehash\n", + ret); + return ret; + } + if (!poll_error) { + mlx5hws_err(ctx, + "Moving complex BWC rule: polling for completions failed (%d), attempting to move rest of the rules\n", + ret); + poll_error = ret; + } }
/* Done moving the rule to the new matcher, @@ -1422,8 +1434,11 @@ mlx5hws_bwc_matcher_move_all_complex(struct mlx5hws_bwc_matcher *bwc_matcher) } }
- if (move_error || poll_error) - ret = -EINVAL; + /* Return the first error that happened */ + if (unlikely(move_error)) + return move_error; + if (unlikely(poll_error)) + return poll_error;
return ret; }
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Alex Vesker valex@nvidia.com
[ Upstream commit 8a51507320ebddaab32610199774f69cd7d53e78 ]
During table creation, caller passes a UID using ft_attr. The UID value was ignored, which leads to problems when the caller sets the UID to a non-zero value, such as SHARED_RESOURCE_UID (0xffff) - the internal FT objects will be created with UID=0.
Fixes: 0869701cba3d ("net/mlx5: HWS, added FW commands handling") Signed-off-by: Alex Vesker valex@nvidia.com Reviewed-by: Yevgeny Kliteynik kliteyn@nvidia.com Signed-off-by: Mark Bloch mbloch@nvidia.com Link: https://patch.msgid.link/20250817202323.308604-7-mbloch@nvidia.com Signed-off-by: Jakub Kicinski kuba@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- .../ethernet/mellanox/mlx5/core/steering/hws/cmd.c | 1 + .../ethernet/mellanox/mlx5/core/steering/hws/cmd.h | 1 + .../mellanox/mlx5/core/steering/hws/fs_hws.c | 1 + .../mellanox/mlx5/core/steering/hws/matcher.c | 5 ++++- .../mellanox/mlx5/core/steering/hws/mlx5hws.h | 1 + .../mellanox/mlx5/core/steering/hws/table.c | 13 ++++++++++--- .../mellanox/mlx5/core/steering/hws/table.h | 3 ++- 7 files changed, 20 insertions(+), 5 deletions(-)
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/cmd.c b/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/cmd.c index 9c83753e4592..0bdcab2e5cf3 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/cmd.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/cmd.c @@ -55,6 +55,7 @@ int mlx5hws_cmd_flow_table_create(struct mlx5_core_dev *mdev,
MLX5_SET(create_flow_table_in, in, opcode, MLX5_CMD_OP_CREATE_FLOW_TABLE); MLX5_SET(create_flow_table_in, in, table_type, ft_attr->type); + MLX5_SET(create_flow_table_in, in, uid, ft_attr->uid);
ft_ctx = MLX5_ADDR_OF(create_flow_table_in, in, flow_table_context); MLX5_SET(flow_table_context, ft_ctx, level, ft_attr->level); diff --git a/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/cmd.h b/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/cmd.h index fa6bff210266..122ccc671628 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/cmd.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/cmd.h @@ -36,6 +36,7 @@ struct mlx5hws_cmd_set_fte_attr { struct mlx5hws_cmd_ft_create_attr { u8 type; u8 level; + u16 uid; bool rtc_valid; bool decap_en; bool reformat_en; diff --git a/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/fs_hws.c b/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/fs_hws.c index bf4643d0ce17..47e3947e7b51 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/fs_hws.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/fs_hws.c @@ -267,6 +267,7 @@ static int mlx5_cmd_hws_create_flow_table(struct mlx5_flow_root_namespace *ns,
tbl_attr.type = MLX5HWS_TABLE_TYPE_FDB; tbl_attr.level = ft_attr->level; + tbl_attr.uid = ft_attr->uid; tbl = mlx5hws_table_create(ctx, &tbl_attr); if (!tbl) { mlx5_core_err(ns->dev, "Failed creating hws flow_table\n"); diff --git a/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/matcher.c b/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/matcher.c index ce28ee1c0e41..6000f2c641e0 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/matcher.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/matcher.c @@ -85,6 +85,7 @@ static int hws_matcher_create_end_ft_isolated(struct mlx5hws_matcher *matcher)
ret = mlx5hws_table_create_default_ft(tbl->ctx->mdev, tbl, + 0, &matcher->end_ft_id); if (ret) { mlx5hws_err(tbl->ctx, "Isolated matcher: failed to create end flow table\n"); @@ -112,7 +113,9 @@ static int hws_matcher_create_end_ft(struct mlx5hws_matcher *matcher) if (mlx5hws_matcher_is_isolated(matcher)) ret = hws_matcher_create_end_ft_isolated(matcher); else - ret = mlx5hws_table_create_default_ft(tbl->ctx->mdev, tbl, + ret = mlx5hws_table_create_default_ft(tbl->ctx->mdev, + tbl, + 0, &matcher->end_ft_id);
if (ret) { diff --git a/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/mlx5hws.h b/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/mlx5hws.h index d8ac6c196211..a2fe2f9e832d 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/mlx5hws.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/mlx5hws.h @@ -75,6 +75,7 @@ struct mlx5hws_context_attr { struct mlx5hws_table_attr { enum mlx5hws_table_type type; u32 level; + u16 uid; };
enum mlx5hws_matcher_flow_src { diff --git a/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/table.c b/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/table.c index 568f691733f3..6113383ae47b 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/table.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/table.c @@ -9,6 +9,7 @@ u32 mlx5hws_table_get_id(struct mlx5hws_table *tbl) }
static void hws_table_init_next_ft_attr(struct mlx5hws_table *tbl, + u16 uid, struct mlx5hws_cmd_ft_create_attr *ft_attr) { ft_attr->type = tbl->fw_ft_type; @@ -16,7 +17,9 @@ static void hws_table_init_next_ft_attr(struct mlx5hws_table *tbl, ft_attr->level = tbl->ctx->caps->fdb_ft.max_level - 1; else ft_attr->level = tbl->ctx->caps->nic_ft.max_level - 1; + ft_attr->rtc_valid = true; + ft_attr->uid = uid; }
static void hws_table_set_cap_attr(struct mlx5hws_table *tbl, @@ -119,12 +122,12 @@ static int hws_table_connect_to_default_miss_tbl(struct mlx5hws_table *tbl, u32
int mlx5hws_table_create_default_ft(struct mlx5_core_dev *mdev, struct mlx5hws_table *tbl, - u32 *ft_id) + u16 uid, u32 *ft_id) { struct mlx5hws_cmd_ft_create_attr ft_attr = {0}; int ret;
- hws_table_init_next_ft_attr(tbl, &ft_attr); + hws_table_init_next_ft_attr(tbl, uid, &ft_attr); hws_table_set_cap_attr(tbl, &ft_attr);
ret = mlx5hws_cmd_flow_table_create(mdev, &ft_attr, ft_id); @@ -189,7 +192,10 @@ static int hws_table_init(struct mlx5hws_table *tbl) }
mutex_lock(&ctx->ctrl_lock); - ret = mlx5hws_table_create_default_ft(tbl->ctx->mdev, tbl, &tbl->ft_id); + ret = mlx5hws_table_create_default_ft(tbl->ctx->mdev, + tbl, + tbl->uid, + &tbl->ft_id); if (ret) { mlx5hws_err(tbl->ctx, "Failed to create flow table object\n"); mutex_unlock(&ctx->ctrl_lock); @@ -239,6 +245,7 @@ struct mlx5hws_table *mlx5hws_table_create(struct mlx5hws_context *ctx, tbl->ctx = ctx; tbl->type = attr->type; tbl->level = attr->level; + tbl->uid = attr->uid;
ret = hws_table_init(tbl); if (ret) { diff --git a/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/table.h b/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/table.h index 0400cce0c317..1246f9bd8422 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/table.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/table.h @@ -18,6 +18,7 @@ struct mlx5hws_table { enum mlx5hws_table_type type; u32 fw_ft_type; u32 level; + u16 uid; struct list_head matchers_list; struct list_head tbl_list_node; struct mlx5hws_default_miss default_miss; @@ -47,7 +48,7 @@ u32 mlx5hws_table_get_res_fw_ft_type(enum mlx5hws_table_type tbl_type,
int mlx5hws_table_create_default_ft(struct mlx5_core_dev *mdev, struct mlx5hws_table *tbl, - u32 *ft_id); + u16 uid, u32 *ft_id);
void mlx5hws_table_destroy_default_ft(struct mlx5hws_table *tbl, u32 ft_id);
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Vlad Dogaru vdogaru@nvidia.com
[ Upstream commit d2d6f950cb43be6845a41cac5956cb2a10e657e5 ]
Specifying the counter action is not enough, as it is used by multiple counters that were allocated in a bulk. By omitting the offset, rules will be associated with a different counter from the same bulk. Subsequently, the CT subsystem checks the correct counter, assumes that no traffic has triggered the rule, and ages out the rule. The end result is intermittent offloading of long lived connections, as rules are aged out then promptly re-added.
Fix this by specifying the correct offset along with the counter rule.
Fixes: 34eea5b12a10 ("net/mlx5e: CT: Add initial support for Hardware Steering") Signed-off-by: Vlad Dogaru vdogaru@nvidia.com Reviewed-by: Yevgeny Kliteynik kliteyn@nvidia.com Signed-off-by: Mark Bloch mbloch@nvidia.com Link: https://patch.msgid.link/20250817202323.308604-8-mbloch@nvidia.com Signed-off-by: Jakub Kicinski kuba@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/net/ethernet/mellanox/mlx5/core/en/tc/ct_fs_hmfs.c | 2 ++ 1 file changed, 2 insertions(+)
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/tc/ct_fs_hmfs.c b/drivers/net/ethernet/mellanox/mlx5/core/en/tc/ct_fs_hmfs.c index a4263137fef5..01d522b02947 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en/tc/ct_fs_hmfs.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en/tc/ct_fs_hmfs.c @@ -173,6 +173,8 @@ static void mlx5_ct_fs_hmfs_fill_rule_actions(struct mlx5_ct_fs_hmfs *fs_hmfs,
memset(rule_actions, 0, NUM_CT_HMFS_RULES * sizeof(*rule_actions)); rule_actions[0].action = mlx5_fc_get_hws_action(fs_hmfs->ctx, attr->counter); + rule_actions[0].counter.offset = + attr->counter->id - attr->counter->bulk->base_id; /* Modify header is special, it may require extra arguments outside the action itself. */ if (mh_action->mh_data) { rule_actions[1].modify_header.offset = mh_action->mh_data->offset;
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Parthiban Veerasooran parthiban.veerasooran@microchip.com
[ Upstream commit 1683fd1b2fa79864d3c7a951d9cea0a9ba1a1923 ]
This fixes an issue where the transmit queue is started implicitly only the very first time the device is registered. When the device is taken down and brought back up again (using `ip` or `ifconfig`), the transmit queue is not restarted, causing packet transmission to hang.
Adding an explicit call to netif_start_queue() in lan865x_net_open() ensures the transmit queue is properly started every time the device is reopened.
Fixes: 5cd2340cb6a3 ("microchip: lan865x: add driver support for Microchip's LAN865X MAC-PHY") Signed-off-by: Parthiban Veerasooran parthiban.veerasooran@microchip.com Link: https://patch.msgid.link/20250818060514.52795-2-parthiban.veerasooran@microc... Signed-off-by: Jakub Kicinski kuba@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/net/ethernet/microchip/lan865x/lan865x.c | 2 ++ 1 file changed, 2 insertions(+)
diff --git a/drivers/net/ethernet/microchip/lan865x/lan865x.c b/drivers/net/ethernet/microchip/lan865x/lan865x.c index dd436bdff0f8..d03f5a8de58d 100644 --- a/drivers/net/ethernet/microchip/lan865x/lan865x.c +++ b/drivers/net/ethernet/microchip/lan865x/lan865x.c @@ -311,6 +311,8 @@ static int lan865x_net_open(struct net_device *netdev)
phy_start(netdev->phydev);
+ netif_start_queue(netdev); + return 0; }
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Parthiban Veerasooran parthiban.veerasooran@microchip.com
[ Upstream commit 2cd58fec912acec273cb155911ab8f06ddbb131a ]
Fix missing configuration for LAN865x silicon revisions B0 and B1 as per Microchip Application Note AN1760 (Rev F, June 2024).
The Timer Increment register was not being set, which is required for accurate timestamping. As per the application note, configure the MAC to set timestamping at the end of the Start of Frame Delimiter (SFD), and set the Timer Increment register to 40 ns (corresponding to a 25 MHz internal clock).
Link: https://www.microchip.com/en-us/application-notes/an1760
Fixes: 5cd2340cb6a3 ("microchip: lan865x: add driver support for Microchip's LAN865X MAC-PHY") Signed-off-by: Parthiban Veerasooran parthiban.veerasooran@microchip.com Reviewed-by: Vadim Fedorenko vadim.fedorenko@linux.dev Link: https://patch.msgid.link/20250818060514.52795-3-parthiban.veerasooran@microc... Signed-off-by: Jakub Kicinski kuba@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- .../net/ethernet/microchip/lan865x/lan865x.c | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+)
diff --git a/drivers/net/ethernet/microchip/lan865x/lan865x.c b/drivers/net/ethernet/microchip/lan865x/lan865x.c index d03f5a8de58d..84c41f193561 100644 --- a/drivers/net/ethernet/microchip/lan865x/lan865x.c +++ b/drivers/net/ethernet/microchip/lan865x/lan865x.c @@ -32,6 +32,10 @@ /* MAC Specific Addr 1 Top Reg */ #define LAN865X_REG_MAC_H_SADDR1 0x00010023
+/* MAC TSU Timer Increment Register */ +#define LAN865X_REG_MAC_TSU_TIMER_INCR 0x00010077 +#define MAC_TSU_TIMER_INCR_COUNT_NANOSECONDS 0x0028 + struct lan865x_priv { struct work_struct multicast_work; struct net_device *netdev; @@ -346,6 +350,21 @@ static int lan865x_probe(struct spi_device *spi) goto free_netdev; }
+ /* LAN865x Rev.B0/B1 configuration parameters from AN1760 + * As per the Configuration Application Note AN1760 published in the + * link, https://www.microchip.com/en-us/application-notes/an1760 + * Revision F (DS60001760G - June 2024), configure the MAC to set time + * stamping at the end of the Start of Frame Delimiter (SFD) and set the + * Timer Increment reg to 40 ns to be used as a 25 MHz internal clock. + */ + ret = oa_tc6_write_register(priv->tc6, LAN865X_REG_MAC_TSU_TIMER_INCR, + MAC_TSU_TIMER_INCR_COUNT_NANOSECONDS); + if (ret) { + dev_err(&spi->dev, "Failed to config TSU Timer Incr reg: %d\n", + ret); + goto oa_tc6_exit; + } + /* As per the point s3 in the below errata, SPI receive Ethernet frame * transfer may halt when starting the next frame in the same data block * (chunk) as the end of a previous frame. The RFA field should be
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Tiezhu Yang yangtiezhu@loongson.cn
[ Upstream commit a47bc954cf0eb51f2828e1607d169d487df7f11f ]
When compiling with LLVM and CONFIG_LTO_CLANG is set, there exist many objtool warnings "sibling call from callable instruction with modified stack frame".
For this special case, the related object file shows that there is no generated relocation section '.rela.discard.tablejump_annotate' for the table jump instruction jirl, thus objtool can not know that what is the actual destination address.
It needs to do something on the LLVM side to make sure that there is the relocation section '.rela.discard.tablejump_annotate' if LTO is enabled, but in order to maintain compatibility for the current LLVM compiler, this can be done in the kernel Makefile for now. Ensure it is aware of linker with LTO, '--loongarch-annotate-tablejump' needs to be passed via '-mllvm' to ld.lld.
Before doing the above changes, it should handle the special case of the relocation section '.rela.discard.tablejump_annotate' to get the correct table size first, otherwise there are many objtool warnings and errors if LTO is enabled.
There are many different rodata for each function if LTO is enabled, it is necessary to enhance get_rodata_table_size_by_table_annotate().
Fixes: b95f852d3af2 ("objtool/LoongArch: Add support for switch table") Closes: https://lore.kernel.org/loongarch/20250731175655.GA1455142@ax162/ Reported-by: Nathan Chancellor nathan@kernel.org Tested-by: Nathan Chancellor nathan@kernel.org Signed-off-by: Tiezhu Yang yangtiezhu@loongson.cn Signed-off-by: Huacai Chen chenhuacai@loongson.cn Signed-off-by: Sasha Levin sashal@kernel.org --- tools/objtool/arch/loongarch/special.c | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+)
diff --git a/tools/objtool/arch/loongarch/special.c b/tools/objtool/arch/loongarch/special.c index e39f86d97002..a80b75f7b061 100644 --- a/tools/objtool/arch/loongarch/special.c +++ b/tools/objtool/arch/loongarch/special.c @@ -27,6 +27,7 @@ static void get_rodata_table_size_by_table_annotate(struct objtool_file *file, struct table_info *next_table; unsigned long tmp_insn_offset; unsigned long tmp_rodata_offset; + bool is_valid_list = false;
rsec = find_section_by_name(file->elf, ".rela.discard.tablejump_annotate"); if (!rsec) @@ -35,6 +36,12 @@ static void get_rodata_table_size_by_table_annotate(struct objtool_file *file, INIT_LIST_HEAD(&table_list);
for_each_reloc(rsec, reloc) { + if (reloc->sym->sec->rodata) + continue; + + if (strcmp(insn->sec->name, reloc->sym->sec->name)) + continue; + orig_table = malloc(sizeof(struct table_info)); if (!orig_table) { WARN("malloc failed"); @@ -49,6 +56,22 @@ static void get_rodata_table_size_by_table_annotate(struct objtool_file *file,
if (reloc_idx(reloc) + 1 == sec_num_entries(rsec)) break; + + if (strcmp(insn->sec->name, (reloc + 1)->sym->sec->name)) { + list_for_each_entry(orig_table, &table_list, jump_info) { + if (orig_table->insn_offset == insn->offset) { + is_valid_list = true; + break; + } + } + + if (!is_valid_list) { + list_del_init(&table_list); + continue; + } + + break; + } }
list_for_each_entry(orig_table, &table_list, jump_info) {
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Tiezhu Yang yangtiezhu@loongson.cn
[ Upstream commit 5dfea6644d201bfeffaa7e0d79d62309856613b7 ]
When compiling with LLVM and CONFIG_LTO_CLANG is set, there exist many objtool warnings "sibling call from callable instruction with modified stack frame".
For this special case, the related object file shows that there is no generated relocation section '.rela.discard.tablejump_annotate' for the table jump instruction jirl, thus objtool can not know that what is the actual destination address.
It needs to do something on the LLVM side to make sure that there is the relocation section '.rela.discard.tablejump_annotate' if LTO is enabled, but in order to maintain compatibility for the current LLVM compiler, this can be done in the kernel Makefile for now. Ensure it is aware of linker with LTO, '--loongarch-annotate-tablejump' needs to be passed via '-mllvm' to ld.lld.
Note that it should also pass the compiler option -mannotate-tablejump rather than only pass '-mllvm --loongarch-annotate-tablejump' to ld.lld if LTO is enabled, otherwise there are no jump info for some table jump instructions.
Fixes: e20ab7d454ee ("LoongArch: Enable jump table for objtool") Closes: https://lore.kernel.org/loongarch/20250731175655.GA1455142@ax162/ Reported-by: Nathan Chancellor nathan@kernel.org Tested-by: Nathan Chancellor nathan@kernel.org Co-developed-by: WANG Rui wangrui@loongson.cn Signed-off-by: WANG Rui wangrui@loongson.cn Signed-off-by: Tiezhu Yang yangtiezhu@loongson.cn Signed-off-by: Huacai Chen chenhuacai@loongson.cn Signed-off-by: Sasha Levin sashal@kernel.org --- arch/loongarch/Makefile | 6 ++++++ 1 file changed, 6 insertions(+)
diff --git a/arch/loongarch/Makefile b/arch/loongarch/Makefile index b0703a4e02a2..a3a9759414f4 100644 --- a/arch/loongarch/Makefile +++ b/arch/loongarch/Makefile @@ -102,7 +102,13 @@ KBUILD_CFLAGS += $(call cc-option,-mthin-add-sub) $(call cc-option,-Wa$(comma)
ifdef CONFIG_OBJTOOL ifdef CONFIG_CC_HAS_ANNOTATE_TABLEJUMP +# The annotate-tablejump option can not be passed to LLVM backend when LTO is enabled. +# Ensure it is aware of linker with LTO, '--loongarch-annotate-tablejump' also needs to +# be passed via '-mllvm' to ld.lld. KBUILD_CFLAGS += -mannotate-tablejump +ifdef CONFIG_LTO_CLANG +KBUILD_LDFLAGS += -mllvm --loongarch-annotate-tablejump +endif else KBUILD_CFLAGS += -fno-jump-tables # keep compatibility with older compilers endif
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Kanglong Wang wangkanglong@loongson.cn
[ Upstream commit 63dbd8fb2af3a89466538599a9acb2d11ef65c06 ]
When enabling CONFIG_KASAN, CONFIG_PREEMPT_VOLUNTARY_BUILD and CONFIG_PREEMPT_VOLUNTARY at the same time, there will be soft deadlock, the relevant logs are as follows:
rcu: INFO: rcu_sched self-detected stall on CPU ... Call Trace: [<900000000024f9e4>] show_stack+0x5c/0x180 [<90000000002482f4>] dump_stack_lvl+0x94/0xbc [<9000000000224544>] rcu_dump_cpu_stacks+0x1fc/0x280 [<900000000037ac80>] rcu_sched_clock_irq+0x720/0xf88 [<9000000000396c34>] update_process_times+0xb4/0x150 [<90000000003b2474>] tick_nohz_handler+0xf4/0x250 [<9000000000397e28>] __hrtimer_run_queues+0x1d0/0x428 [<9000000000399b2c>] hrtimer_interrupt+0x214/0x538 [<9000000000253634>] constant_timer_interrupt+0x64/0x80 [<9000000000349938>] __handle_irq_event_percpu+0x78/0x1a0 [<9000000000349a78>] handle_irq_event_percpu+0x18/0x88 [<9000000000354c00>] handle_percpu_irq+0x90/0xf0 [<9000000000348c74>] handle_irq_desc+0x94/0xb8 [<9000000001012b28>] handle_cpu_irq+0x68/0xa0 [<9000000001def8c0>] handle_loongarch_irq+0x30/0x48 [<9000000001def958>] do_vint+0x80/0xd0 [<9000000000268a0c>] kasan_mem_to_shadow.part.0+0x2c/0x2a0 [<90000000006344f4>] __asan_load8+0x4c/0x120 [<900000000025c0d0>] module_frob_arch_sections+0x5c8/0x6b8 [<90000000003895f0>] load_module+0x9e0/0x2958 [<900000000038b770>] __do_sys_init_module+0x208/0x2d0 [<9000000001df0c34>] do_syscall+0x94/0x190 [<900000000024d6fc>] handle_syscall+0xbc/0x158
After analysis, this is because the slow speed of loading the amdgpu module leads to the long time occupation of the cpu and then the soft deadlock.
When loading a module, module_frob_arch_sections() tries to figure out the number of PLTs/GOTs that will be needed to handle all the RELAs. It will call the count_max_entries() to find in an out-of-order date which counting algorithm has O(n^2) complexity.
To make it faster, we sort the relocation list by info and addend. That way, to check for a duplicate relocation, it just needs to compare with the previous entry. This reduces the complexity of the algorithm to O(n log n), as done in commit d4e0340919fb ("arm64/module: Optimize module load time by optimizing PLT counting"). This gives sinificant reduction in module load time for modules with large number of relocations.
After applying this patch, the soft deadlock problem has been solved, and the kernel starts normally without "Call Trace".
Using the default configuration to test some modules, the results are as follows:
Module Size ip_tables 36K fat 143K radeon 2.5MB amdgpu 16MB
Without this patch: Module Module load time (ms) Count(PLTs/GOTs) ip_tables 18 59/6 fat 0 162/14 radeon 54 1221/84 amdgpu 1411 4525/1098
With this patch: Module Module load time (ms) Count(PLTs/GOTs) ip_tables 18 59/6 fat 0 162/14 radeon 22 1221/84 amdgpu 45 4525/1098
Fixes: fcdfe9d22bed ("LoongArch: Add ELF and module support") Signed-off-by: Kanglong Wang wangkanglong@loongson.cn Signed-off-by: Huacai Chen chenhuacai@loongson.cn Signed-off-by: Sasha Levin sashal@kernel.org --- arch/loongarch/kernel/module-sections.c | 36 ++++++++++++------------- 1 file changed, 18 insertions(+), 18 deletions(-)
diff --git a/arch/loongarch/kernel/module-sections.c b/arch/loongarch/kernel/module-sections.c index e2f30ff9afde..a43ba7f9f987 100644 --- a/arch/loongarch/kernel/module-sections.c +++ b/arch/loongarch/kernel/module-sections.c @@ -8,6 +8,7 @@ #include <linux/module.h> #include <linux/moduleloader.h> #include <linux/ftrace.h> +#include <linux/sort.h>
Elf_Addr module_emit_got_entry(struct module *mod, Elf_Shdr *sechdrs, Elf_Addr val) { @@ -61,39 +62,38 @@ Elf_Addr module_emit_plt_entry(struct module *mod, Elf_Shdr *sechdrs, Elf_Addr v return (Elf_Addr)&plt[nr]; }
-static int is_rela_equal(const Elf_Rela *x, const Elf_Rela *y) -{ - return x->r_info == y->r_info && x->r_addend == y->r_addend; -} +#define cmp_3way(a, b) ((a) < (b) ? -1 : (a) > (b))
-static bool duplicate_rela(const Elf_Rela *rela, int idx) +static int compare_rela(const void *x, const void *y) { - int i; + int ret; + const Elf_Rela *rela_x = x, *rela_y = y;
- for (i = 0; i < idx; i++) { - if (is_rela_equal(&rela[i], &rela[idx])) - return true; - } + ret = cmp_3way(rela_x->r_info, rela_y->r_info); + if (ret == 0) + ret = cmp_3way(rela_x->r_addend, rela_y->r_addend);
- return false; + return ret; }
static void count_max_entries(Elf_Rela *relas, int num, unsigned int *plts, unsigned int *gots) { - unsigned int i, type; + unsigned int i; + + sort(relas, num, sizeof(Elf_Rela), compare_rela, NULL);
for (i = 0; i < num; i++) { - type = ELF_R_TYPE(relas[i].r_info); - switch (type) { + if (i && !compare_rela(&relas[i-1], &relas[i])) + continue; + + switch (ELF_R_TYPE(relas[i].r_info)) { case R_LARCH_SOP_PUSH_PLT_PCREL: case R_LARCH_B26: - if (!duplicate_rela(relas, i)) - (*plts)++; + (*plts)++; break; case R_LARCH_GOT_PC_HI20: - if (!duplicate_rela(relas, i)) - (*gots)++; + (*gots)++; break; default: break; /* Do nothing. */
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Stefan Binding sbinding@opensource.cirrus.com
[ Upstream commit f135fb24ef29335b94921077588cae445bc7f099 ]
Production silicon for CS36L63 has some small differences compared to pre-production silicon. Update firmware addresses, which are different.
No product was ever released with pre-production silicon so there is no need for the driver to include support for it.
Fixes: 978858791ced ("ASoC: cs35l56: Add initial support for CS35L63 for I2C and SoundWire")
Signed-off-by: Stefan Binding sbinding@opensource.cirrus.com Link: https://patch.msgid.link/20250820142209.127575-2-sbinding@opensource.cirrus.... Signed-off-by: Mark Brown broonie@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- include/sound/cs35l56.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/include/sound/cs35l56.h b/include/sound/cs35l56.h index e17c4cadd04d..f44aabde805e 100644 --- a/include/sound/cs35l56.h +++ b/include/sound/cs35l56.h @@ -107,8 +107,8 @@ #define CS35L56_DSP1_PMEM_5114 0x3804FE8
#define CS35L63_DSP1_FW_VER CS35L56_DSP1_FW_VER -#define CS35L63_DSP1_HALO_STATE 0x280396C -#define CS35L63_DSP1_PM_CUR_STATE 0x28042C8 +#define CS35L63_DSP1_HALO_STATE 0x2803C04 +#define CS35L63_DSP1_PM_CUR_STATE 0x2804518 #define CS35L63_PROTECTION_STATUS 0x340009C #define CS35L63_TRANSDUCER_ACTUAL_PS 0x34000F4 #define CS35L63_MAIN_RENDER_USER_MUTE 0x3400020
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Richard Fitzgerald rf@opensource.cirrus.com
[ Upstream commit 8dadc11b67d4b83deff45e4889b3b5540b9c0a7f ]
CS35L63 uses different algorithm IDs from CS35L56. Add a new mechanism to handle different alg IDs between parts in the CS35L56 driver.
Fixes: 978858791ced ("ASoC: cs35l56: Add initial support for CS35L63 for I2C and SoundWire")
Signed-off-by: Richard Fitzgerald rf@opensource.cirrus.com Signed-off-by: Stefan Binding sbinding@opensource.cirrus.com Link: https://patch.msgid.link/20250820142209.127575-3-sbinding@opensource.cirrus.... Signed-off-by: Mark Brown broonie@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- include/sound/cs35l56.h | 1 + sound/soc/codecs/cs35l56-shared.c | 29 ++++++++++++++++++++++++++--- sound/soc/codecs/cs35l56.c | 2 +- 3 files changed, 28 insertions(+), 4 deletions(-)
diff --git a/include/sound/cs35l56.h b/include/sound/cs35l56.h index f44aabde805e..7c8bbe8ad1e2 100644 --- a/include/sound/cs35l56.h +++ b/include/sound/cs35l56.h @@ -306,6 +306,7 @@ struct cs35l56_base { struct gpio_desc *reset_gpio; struct cs35l56_spi_payload *spi_payload_buf; const struct cs35l56_fw_reg *fw_reg; + const struct cirrus_amp_cal_controls *calibration_controls; };
static inline bool cs35l56_is_otp_register(unsigned int reg) diff --git a/sound/soc/codecs/cs35l56-shared.c b/sound/soc/codecs/cs35l56-shared.c index ba653f6ccfae..850fcf385996 100644 --- a/sound/soc/codecs/cs35l56-shared.c +++ b/sound/soc/codecs/cs35l56-shared.c @@ -838,6 +838,15 @@ const struct cirrus_amp_cal_controls cs35l56_calibration_controls = { }; EXPORT_SYMBOL_NS_GPL(cs35l56_calibration_controls, "SND_SOC_CS35L56_SHARED");
+static const struct cirrus_amp_cal_controls cs35l63_calibration_controls = { + .alg_id = 0xbf210, + .mem_region = WMFW_ADSP2_YM, + .ambient = "CAL_AMBIENT", + .calr = "CAL_R", + .status = "CAL_STATUS", + .checksum = "CAL_CHECKSUM", +}; + int cs35l56_get_calibration(struct cs35l56_base *cs35l56_base) { u64 silicon_uid = 0; @@ -912,19 +921,31 @@ EXPORT_SYMBOL_NS_GPL(cs35l56_read_prot_status, "SND_SOC_CS35L56_SHARED"); void cs35l56_log_tuning(struct cs35l56_base *cs35l56_base, struct cs_dsp *cs_dsp) { __be32 pid, sid, tid; + unsigned int alg_id; int ret;
+ switch (cs35l56_base->type) { + case 0x54: + case 0x56: + case 0x57: + alg_id = 0x9f212; + break; + default: + alg_id = 0xbf212; + break; + } + scoped_guard(mutex, &cs_dsp->pwr_lock) { ret = cs_dsp_coeff_read_ctrl(cs_dsp_get_ctl(cs_dsp, "AS_PRJCT_ID", - WMFW_ADSP2_XM, 0x9f212), + WMFW_ADSP2_XM, alg_id), 0, &pid, sizeof(pid)); if (!ret) ret = cs_dsp_coeff_read_ctrl(cs_dsp_get_ctl(cs_dsp, "AS_CHNNL_ID", - WMFW_ADSP2_XM, 0x9f212), + WMFW_ADSP2_XM, alg_id), 0, &sid, sizeof(sid)); if (!ret) ret = cs_dsp_coeff_read_ctrl(cs_dsp_get_ctl(cs_dsp, "AS_SNPSHT_ID", - WMFW_ADSP2_XM, 0x9f212), + WMFW_ADSP2_XM, alg_id), 0, &tid, sizeof(tid)); }
@@ -974,8 +995,10 @@ int cs35l56_hw_init(struct cs35l56_base *cs35l56_base) case 0x35A54: case 0x35A56: case 0x35A57: + cs35l56_base->calibration_controls = &cs35l56_calibration_controls; break; case 0x35A630: + cs35l56_base->calibration_controls = &cs35l63_calibration_controls; devid = devid >> 4; break; default: diff --git a/sound/soc/codecs/cs35l56.c b/sound/soc/codecs/cs35l56.c index 1b42586794ad..76306282b2e6 100644 --- a/sound/soc/codecs/cs35l56.c +++ b/sound/soc/codecs/cs35l56.c @@ -695,7 +695,7 @@ static int cs35l56_write_cal(struct cs35l56_private *cs35l56) return ret;
ret = cs_amp_write_cal_coeffs(&cs35l56->dsp.cs_dsp, - &cs35l56_calibration_controls, + cs35l56->base.calibration_controls, &cs35l56->base.cal_data);
wm_adsp_stop(&cs35l56->dsp);
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Stefan Binding sbinding@opensource.cirrus.com
[ Upstream commit 8d13d1bdb59d0a2c526869ee571ec51a3a887463 ]
Production silicon for CS36L63 has some small differences compared to pre-production silicon. Remove soundwire clock workaround as no longer necessary. We don't want to do tricks with low-level clocking controls if we don't need to.
Fixes: 978858791ced ("ASoC: cs35l56: Add initial support for CS35L63 for I2C and SoundWire")
Signed-off-by: Stefan Binding sbinding@opensource.cirrus.com Link: https://patch.msgid.link/20250820142209.127575-4-sbinding@opensource.cirrus.... Signed-off-by: Mark Brown broonie@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- sound/soc/codecs/cs35l56-sdw.c | 69 ---------------------------------- sound/soc/codecs/cs35l56.h | 3 -- 2 files changed, 72 deletions(-)
diff --git a/sound/soc/codecs/cs35l56-sdw.c b/sound/soc/codecs/cs35l56-sdw.c index fa9693af3722..d7fa12d287e0 100644 --- a/sound/soc/codecs/cs35l56-sdw.c +++ b/sound/soc/codecs/cs35l56-sdw.c @@ -394,74 +394,6 @@ static int cs35l56_sdw_update_status(struct sdw_slave *peripheral, return 0; }
-static int cs35l63_sdw_kick_divider(struct cs35l56_private *cs35l56, - struct sdw_slave *peripheral) -{ - unsigned int curr_scale_reg, next_scale_reg; - int curr_scale, next_scale, ret; - - if (!cs35l56->base.init_done) - return 0; - - if (peripheral->bus->params.curr_bank) { - curr_scale_reg = SDW_SCP_BUSCLOCK_SCALE_B1; - next_scale_reg = SDW_SCP_BUSCLOCK_SCALE_B0; - } else { - curr_scale_reg = SDW_SCP_BUSCLOCK_SCALE_B0; - next_scale_reg = SDW_SCP_BUSCLOCK_SCALE_B1; - } - - /* - * Current clock scale value must be different to new value. - * Modify current to guarantee this. If next still has the dummy - * value we wrote when it was current, the core code has not set - * a new scale so restore its original good value - */ - curr_scale = sdw_read_no_pm(peripheral, curr_scale_reg); - if (curr_scale < 0) { - dev_err(cs35l56->base.dev, "Failed to read current clock scale: %d\n", curr_scale); - return curr_scale; - } - - next_scale = sdw_read_no_pm(peripheral, next_scale_reg); - if (next_scale < 0) { - dev_err(cs35l56->base.dev, "Failed to read next clock scale: %d\n", next_scale); - return next_scale; - } - - if (next_scale == CS35L56_SDW_INVALID_BUS_SCALE) { - next_scale = cs35l56->old_sdw_clock_scale; - ret = sdw_write_no_pm(peripheral, next_scale_reg, next_scale); - if (ret < 0) { - dev_err(cs35l56->base.dev, "Failed to modify current clock scale: %d\n", - ret); - return ret; - } - } - - cs35l56->old_sdw_clock_scale = curr_scale; - ret = sdw_write_no_pm(peripheral, curr_scale_reg, CS35L56_SDW_INVALID_BUS_SCALE); - if (ret < 0) { - dev_err(cs35l56->base.dev, "Failed to modify current clock scale: %d\n", ret); - return ret; - } - - dev_dbg(cs35l56->base.dev, "Next bus scale: %#x\n", next_scale); - - return 0; -} - -static int cs35l56_sdw_bus_config(struct sdw_slave *peripheral, - struct sdw_bus_params *params) -{ - struct cs35l56_private *cs35l56 = dev_get_drvdata(&peripheral->dev); - - if ((cs35l56->base.type == 0x63) && (cs35l56->base.rev < 0xa1)) - return cs35l63_sdw_kick_divider(cs35l56, peripheral); - - return 0; -} - static int __maybe_unused cs35l56_sdw_clk_stop(struct sdw_slave *peripheral, enum sdw_clk_stop_mode mode, enum sdw_clk_stop_type type) @@ -477,7 +409,6 @@ static const struct sdw_slave_ops cs35l56_sdw_ops = { .read_prop = cs35l56_sdw_read_prop, .interrupt_callback = cs35l56_sdw_interrupt, .update_status = cs35l56_sdw_update_status, - .bus_config = cs35l56_sdw_bus_config, #ifdef DEBUG .clk_stop = cs35l56_sdw_clk_stop, #endif diff --git a/sound/soc/codecs/cs35l56.h b/sound/soc/codecs/cs35l56.h index bd77a57249d7..40a1800a4585 100644 --- a/sound/soc/codecs/cs35l56.h +++ b/sound/soc/codecs/cs35l56.h @@ -20,8 +20,6 @@ #define CS35L56_SDW_GEN_INT_MASK_1 0xc1 #define CS35L56_SDW_INT_MASK_CODEC_IRQ BIT(0)
-#define CS35L56_SDW_INVALID_BUS_SCALE 0xf - #define CS35L56_RX_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE) #define CS35L56_TX_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE \ | SNDRV_PCM_FMTBIT_S32_LE) @@ -52,7 +50,6 @@ struct cs35l56_private { u8 asp_slot_count; bool tdm_mode; bool sysclk_set; - u8 old_sdw_clock_scale; u8 sdw_link_num; u8 sdw_unique_id; };
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Heiko Carstens hca@linux.ibm.com
[ Upstream commit 93f616ff870a1fb7e84d472cad0af651b18f9f87 ]
Since the identity mapping is pinned to address zero the lowcore is always also mapped to address zero, this happens regardless of the relocate_lowcore command line option. If the option is specified the lowcore is mapped twice, instead of only once.
This means that NULL pointer accesses will succeed instead of causing an exception (low address protection still applies, but covers only parts). To fix this never map the first two pages of physical memory with the identity mapping.
Fixes: 32db401965f1 ("s390/mm: Pin identity mapping base to zero") Reviewed-by: Alexander Gordeev agordeev@linux.ibm.com Signed-off-by: Heiko Carstens hca@linux.ibm.com Signed-off-by: Alexander Gordeev agordeev@linux.ibm.com Signed-off-by: Sasha Levin sashal@kernel.org --- arch/s390/boot/vmem.c | 3 +++ 1 file changed, 3 insertions(+)
diff --git a/arch/s390/boot/vmem.c b/arch/s390/boot/vmem.c index 1d073acd05a7..cea3de4dce8c 100644 --- a/arch/s390/boot/vmem.c +++ b/arch/s390/boot/vmem.c @@ -530,6 +530,9 @@ void setup_vmem(unsigned long kernel_start, unsigned long kernel_end, unsigned l lowcore_address + sizeof(struct lowcore), POPULATE_LOWCORE); for_each_physmem_usable_range(i, &start, &end) { + /* Do not map lowcore with identity mapping */ + if (!start) + start = sizeof(struct lowcore); pgtable_populate((unsigned long)__identity_va(start), (unsigned long)__identity_va(end), POPULATE_IDENTITY);
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Bibo Mao maobibo@loongson.cn
[ Upstream commit d23bd878f6ea9cff93104159356e012a8b2bbfaf ]
Standard bitops APIs such test_bit() is used here, rather than manually calculating the offset and mask. Also use non-atomic API __set_bit() and __clear_bit() rather than set_bit() and clear_bit(), since the global spinlock is held already.
Signed-off-by: Bibo Mao maobibo@loongson.cn Signed-off-by: Huacai Chen chenhuacai@loongson.cn Stable-dep-of: 0dfd9ea7bf80 ("LoongArch: KVM: Use kvm_get_vcpu_by_id() instead of kvm_get_vcpu()") Signed-off-by: Sasha Levin sashal@kernel.org --- arch/loongarch/kvm/intc/eiointc.c | 27 +++++++++++---------------- 1 file changed, 11 insertions(+), 16 deletions(-)
diff --git a/arch/loongarch/kvm/intc/eiointc.c b/arch/loongarch/kvm/intc/eiointc.c index a75f865d6fb9..3cf9894999da 100644 --- a/arch/loongarch/kvm/intc/eiointc.c +++ b/arch/loongarch/kvm/intc/eiointc.c @@ -9,7 +9,7 @@
static void eiointc_set_sw_coreisr(struct loongarch_eiointc *s) { - int ipnum, cpu, cpuid, irq_index, irq_mask, irq; + int ipnum, cpu, cpuid, irq; struct kvm_vcpu *vcpu;
for (irq = 0; irq < EIOINTC_IRQS; irq++) { @@ -18,8 +18,6 @@ static void eiointc_set_sw_coreisr(struct loongarch_eiointc *s) ipnum = count_trailing_zeros(ipnum); ipnum = (ipnum >= 0 && ipnum < 4) ? ipnum : 0; } - irq_index = irq / 32; - irq_mask = BIT(irq & 0x1f);
cpuid = s->coremap.reg_u8[irq]; vcpu = kvm_get_vcpu_by_cpuid(s->kvm, cpuid); @@ -27,16 +25,16 @@ static void eiointc_set_sw_coreisr(struct loongarch_eiointc *s) continue;
cpu = vcpu->vcpu_id; - if (!!(s->coreisr.reg_u32[cpu][irq_index] & irq_mask)) - set_bit(irq, s->sw_coreisr[cpu][ipnum]); + if (test_bit(irq, (unsigned long *)s->coreisr.reg_u32[cpu])) + __set_bit(irq, s->sw_coreisr[cpu][ipnum]); else - clear_bit(irq, s->sw_coreisr[cpu][ipnum]); + __clear_bit(irq, s->sw_coreisr[cpu][ipnum]); } }
static void eiointc_update_irq(struct loongarch_eiointc *s, int irq, int level) { - int ipnum, cpu, found, irq_index, irq_mask; + int ipnum, cpu, found; struct kvm_vcpu *vcpu; struct kvm_interrupt vcpu_irq;
@@ -48,19 +46,16 @@ static void eiointc_update_irq(struct loongarch_eiointc *s, int irq, int level)
cpu = s->sw_coremap[irq]; vcpu = kvm_get_vcpu(s->kvm, cpu); - irq_index = irq / 32; - irq_mask = BIT(irq & 0x1f); - if (level) { /* if not enable return false */ - if (((s->enable.reg_u32[irq_index]) & irq_mask) == 0) + if (!test_bit(irq, (unsigned long *)s->enable.reg_u32)) return; - s->coreisr.reg_u32[cpu][irq_index] |= irq_mask; + __set_bit(irq, (unsigned long *)s->coreisr.reg_u32[cpu]); found = find_first_bit(s->sw_coreisr[cpu][ipnum], EIOINTC_IRQS); - set_bit(irq, s->sw_coreisr[cpu][ipnum]); + __set_bit(irq, s->sw_coreisr[cpu][ipnum]); } else { - s->coreisr.reg_u32[cpu][irq_index] &= ~irq_mask; - clear_bit(irq, s->sw_coreisr[cpu][ipnum]); + __clear_bit(irq, (unsigned long *)s->coreisr.reg_u32[cpu]); + __clear_bit(irq, s->sw_coreisr[cpu][ipnum]); found = find_first_bit(s->sw_coreisr[cpu][ipnum], EIOINTC_IRQS); }
@@ -110,8 +105,8 @@ void eiointc_set_irq(struct loongarch_eiointc *s, int irq, int level) unsigned long flags; unsigned long *isr = (unsigned long *)s->isr.reg_u8;
- level ? set_bit(irq, isr) : clear_bit(irq, isr); spin_lock_irqsave(&s->lock, flags); + level ? __set_bit(irq, isr) : __clear_bit(irq, isr); eiointc_update_irq(s, irq, level); spin_unlock_irqrestore(&s->lock, flags); }
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Song Gao gaosong@loongson.cn
[ Upstream commit 0dfd9ea7bf80fabe11f5b775d762a5cd168cdf41 ]
Since using kvm_get_vcpu() may fail to retrieve the vCPU context, kvm_get_vcpu_by_id() should be used instead.
Fixes: 8e3054261bc3 ("LoongArch: KVM: Add IPI user mode read and write function") Fixes: 3956a52bc05b ("LoongArch: KVM: Add EIOINTC read and write functions") Reviewed-by: Yanteng Si siyanteng@cqsoftware.com.cm Signed-off-by: Song Gao gaosong@loongson.cn Signed-off-by: Huacai Chen chenhuacai@loongson.cn Signed-off-by: Sasha Levin sashal@kernel.org --- arch/loongarch/kvm/intc/eiointc.c | 7 ++++++- arch/loongarch/kvm/intc/ipi.c | 2 +- 2 files changed, 7 insertions(+), 2 deletions(-)
diff --git a/arch/loongarch/kvm/intc/eiointc.c b/arch/loongarch/kvm/intc/eiointc.c index 3cf9894999da..0207cfe1dbd6 100644 --- a/arch/loongarch/kvm/intc/eiointc.c +++ b/arch/loongarch/kvm/intc/eiointc.c @@ -45,7 +45,12 @@ static void eiointc_update_irq(struct loongarch_eiointc *s, int irq, int level) }
cpu = s->sw_coremap[irq]; - vcpu = kvm_get_vcpu(s->kvm, cpu); + vcpu = kvm_get_vcpu_by_id(s->kvm, cpu); + if (unlikely(vcpu == NULL)) { + kvm_err("%s: invalid target cpu: %d\n", __func__, cpu); + return; + } + if (level) { /* if not enable return false */ if (!test_bit(irq, (unsigned long *)s->enable.reg_u32)) diff --git a/arch/loongarch/kvm/intc/ipi.c b/arch/loongarch/kvm/intc/ipi.c index 6a13d2f44575..4859e320e3a1 100644 --- a/arch/loongarch/kvm/intc/ipi.c +++ b/arch/loongarch/kvm/intc/ipi.c @@ -318,7 +318,7 @@ static int kvm_ipi_regs_access(struct kvm_device *dev, cpu = (attr->attr >> 16) & 0x3ff; addr = attr->attr & 0xff;
- vcpu = kvm_get_vcpu(dev->kvm, cpu); + vcpu = kvm_get_vcpu_by_id(dev->kvm, cpu); if (unlikely(vcpu == NULL)) { kvm_err("%s: invalid target cpu: %d\n", __func__, cpu); return -EINVAL;
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jason Xing kernelxing@tencent.com
[ Upstream commit 4d4d9ef9dfee877d494e5418f68a1016ef08cad6 ]
Resolve the budget negative overflow which leads to returning true in ixgbe_xmit_zc even when the budget of descs are thoroughly consumed.
Before this patch, when the budget is decreased to zero and finishes sending the last allowed desc in ixgbe_xmit_zc, it will always turn back and enter into the while() statement to see if it should keep processing packets, but in the meantime it unexpectedly decreases the value again to 'unsigned int (0--)', namely, UINT_MAX. Finally, the ixgbe_xmit_zc returns true, showing 'we complete cleaning the budget'. That also means 'clean_complete = true' in ixgbe_poll.
The true theory behind this is if that budget number of descs are consumed, it implies that we might have more descs to be done. So we should return false in ixgbe_xmit_zc to tell napi poll to find another chance to start polling to handle the rest of descs. On the contrary, returning true here means job done and we know we finish all the possible descs this time and we don't intend to start a new napi poll.
It is apparently against our expectations. Please also see how ixgbe_clean_tx_irq() handles the problem: it uses do..while() statement to make sure the budget can be decreased to zero at most and the negative overflow never happens.
The patch adds 'likely' because we rarely would not hit the loop condition since the standard budget is 256.
Fixes: 8221c5eba8c1 ("ixgbe: add AF_XDP zero-copy Tx support") Signed-off-by: Jason Xing kernelxing@tencent.com Reviewed-by: Larysa Zaremba larysa.zaremba@intel.com Reviewed-by: Paul Menzel pmenzel@molgen.mpg.de Reviewed-by: Aleksandr Loktionov aleksandr.loktionov@intel.com Tested-by: Priya Singh priyax.singh@intel.com Signed-off-by: Tony Nguyen anthony.l.nguyen@intel.com Link: https://patch.msgid.link/20250819222000.3504873-4-anthony.l.nguyen@intel.com Signed-off-by: Jakub Kicinski kuba@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/net/ethernet/intel/ixgbe/ixgbe_xsk.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_xsk.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_xsk.c index ac58964b2f08..7b941505a9d0 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_xsk.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_xsk.c @@ -398,7 +398,7 @@ static bool ixgbe_xmit_zc(struct ixgbe_ring *xdp_ring, unsigned int budget) dma_addr_t dma; u32 cmd_type;
- while (budget-- > 0) { + while (likely(budget)) { if (unlikely(!ixgbe_desc_unused(xdp_ring))) { work_done = false; break; @@ -433,6 +433,8 @@ static bool ixgbe_xmit_zc(struct ixgbe_ring *xdp_ring, unsigned int budget) xdp_ring->next_to_use++; if (xdp_ring->next_to_use == xdp_ring->count) xdp_ring->next_to_use = 0; + + budget--; }
if (tx_desc) {
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: ValdikSS iam@valdikss.org.ru
[ Upstream commit 1468c1f97cf32418e34dbb40b784ed9333b9e123 ]
Device ID comparison in igc_is_device_id_i226 is performed before the ID is set, resulting in always failing check on init.
Before the patch: * L1.2 is not disabled on init * L1.2 is properly disabled after suspend-resume cycle
With the patch: * L1.2 is properly disabled both on init and after suspend-resume
How to test: Connect to the 1G link with 300+ mbit/s Internet speed, and run the download speed test, such as:
curl -o /dev/null http://speedtest.selectel.ru/1GB
Without L1.2 disabled, the speed would be no more than ~200 mbit/s. With L1.2 disabled, the speed would reach 1 gbit/s. Note: it's required that the latency between your host and the remote be around 3-5 ms, the test inside LAN (<1 ms latency) won't trigger the issue.
Link: https://lore.kernel.org/intel-wired-lan/15248b4f-3271-42dd-8e35-02bfc92b25e1... Fixes: 0325143b59c6 ("igc: disable L1.2 PCI-E link substate to avoid performance issue") Signed-off-by: ValdikSS iam@valdikss.org.ru Reviewed-by: Vitaly Lifshits vitaly.lifshits@intel.com Reviewed-by: Paul Menzel pmenzel@molgen.mpg.de Signed-off-by: Tony Nguyen anthony.l.nguyen@intel.com Link: https://patch.msgid.link/20250819222000.3504873-6-anthony.l.nguyen@intel.com Signed-off-by: Jakub Kicinski kuba@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/net/ethernet/intel/igc/igc_main.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-)
diff --git a/drivers/net/ethernet/intel/igc/igc_main.c b/drivers/net/ethernet/intel/igc/igc_main.c index 031c332f66c4..1b4465d6b2b7 100644 --- a/drivers/net/ethernet/intel/igc/igc_main.c +++ b/drivers/net/ethernet/intel/igc/igc_main.c @@ -7115,6 +7115,13 @@ static int igc_probe(struct pci_dev *pdev, adapter->port_num = hw->bus.func; adapter->msg_enable = netif_msg_init(debug, DEFAULT_MSG_ENABLE);
+ /* PCI config space info */ + hw->vendor_id = pdev->vendor; + hw->device_id = pdev->device; + hw->revision_id = pdev->revision; + hw->subsystem_vendor_id = pdev->subsystem_vendor; + hw->subsystem_device_id = pdev->subsystem_device; + /* Disable ASPM L1.2 on I226 devices to avoid packet loss */ if (igc_is_device_id_i226(hw)) pci_disable_link_state(pdev, PCIE_LINK_STATE_L1_2); @@ -7141,13 +7148,6 @@ static int igc_probe(struct pci_dev *pdev, netdev->mem_start = pci_resource_start(pdev, 0); netdev->mem_end = pci_resource_end(pdev, 0);
- /* PCI config space info */ - hw->vendor_id = pdev->vendor; - hw->device_id = pdev->device; - hw->revision_id = pdev->revision; - hw->subsystem_vendor_id = pdev->subsystem_vendor; - hw->subsystem_device_id = pdev->subsystem_device; - /* Copy the default MAC and PHY function pointers */ memcpy(&hw->mac.ops, ei->mac_ops, sizeof(hw->mac.ops)); memcpy(&hw->phy.ops, ei->phy_ops, sizeof(hw->phy.ops));
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Tristram Ha tristram.ha@microchip.com
[ Upstream commit e318cd6714592fb762fcab59c5684a442243a12f ]
ksz9477_hsr_join() is called once to setup the HSR port membership, but the port can be enabled later, or disabled and enabled back and the port membership is not set correctly inside ksz_update_port_member(). The added code always use the correct HSR port membership for HSR port that is enabled.
Fixes: 2d61298fdd7b ("net: dsa: microchip: Enable HSR offloading for KSZ9477") Reported-by: Frieder Schrempf frieder.schrempf@kontron.de Signed-off-by: Tristram Ha tristram.ha@microchip.com Reviewed-by: Łukasz Majewski lukma@nabladev.com Tested-by: Frieder Schrempf frieder.schrempf@kontron.de Reviewed-by: Frieder Schrempf frieder.schrempf@kontron.de Link: https://patch.msgid.link/20250819010457.563286-1-Tristram.Ha@microchip.com Signed-off-by: Jakub Kicinski kuba@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/net/dsa/microchip/ksz_common.c | 6 ++++++ 1 file changed, 6 insertions(+)
diff --git a/drivers/net/dsa/microchip/ksz_common.c b/drivers/net/dsa/microchip/ksz_common.c index 7c142c17b3f6..adef7aa327ce 100644 --- a/drivers/net/dsa/microchip/ksz_common.c +++ b/drivers/net/dsa/microchip/ksz_common.c @@ -2347,6 +2347,12 @@ static void ksz_update_port_member(struct ksz_device *dev, int port) dev->dev_ops->cfg_port_member(dev, i, val | cpu_port); }
+ /* HSR ports are setup once so need to use the assigned membership + * when the port is enabled. + */ + if (!port_member && p->stp_state == BR_STATE_FORWARDING && + (dev->hsr_ports & BIT(port))) + port_member = dev->hsr_ports; dev->dev_ops->cfg_port_member(dev, port, port_member | cpu_port); }
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: William Liu will@willsroot.io
[ Upstream commit 15de71d06a400f7fdc15bf377a2552b0ec437cf5 ]
The following setup can trigger a WARNING in htb_activate due to the condition: !cl->leaf.q->q.qlen
tc qdisc del dev lo root tc qdisc add dev lo root handle 1: htb default 1 tc class add dev lo parent 1: classid 1:1 \ htb rate 64bit tc qdisc add dev lo parent 1:1 handle f: \ cake memlimit 1b ping -I lo -f -c1 -s64 -W0.001 127.0.0.1
This is because the low memlimit leads to a low buffer_limit, which causes packet dropping. However, cake_enqueue still returns NET_XMIT_SUCCESS, causing htb_enqueue to call htb_activate with an empty child qdisc. We should return NET_XMIT_CN when packets are dropped from the same tin and flow.
I do not believe return value of NET_XMIT_CN is necessary for packet drops in the case of ack filtering, as that is meant to optimize performance, not to signal congestion.
Fixes: 046f6fd5daef ("sched: Add Common Applications Kept Enhanced (cake) qdisc") Signed-off-by: William Liu will@willsroot.io Reviewed-by: Savino Dicanosa savy@syst3mfailure.io Acked-by: Toke Høiland-Jørgensen toke@toke.dk Reviewed-by: Jamal Hadi Salim jhs@mojatatu.com Link: https://patch.msgid.link/20250819033601.579821-1-will@willsroot.io Signed-off-by: Jakub Kicinski kuba@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- net/sched/sch_cake.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-)
diff --git a/net/sched/sch_cake.c b/net/sched/sch_cake.c index 48dd8c88903f..aa9f31e4415a 100644 --- a/net/sched/sch_cake.c +++ b/net/sched/sch_cake.c @@ -1747,7 +1747,7 @@ static s32 cake_enqueue(struct sk_buff *skb, struct Qdisc *sch, ktime_t now = ktime_get(); struct cake_tin_data *b; struct cake_flow *flow; - u32 idx; + u32 idx, tin;
/* choose flow to insert into */ idx = cake_classify(sch, &b, skb, q->flow_mode, &ret); @@ -1757,6 +1757,7 @@ static s32 cake_enqueue(struct sk_buff *skb, struct Qdisc *sch, __qdisc_drop(skb, to_free); return ret; } + tin = (u32)(b - q->tins); idx--; flow = &b->flows[idx];
@@ -1924,13 +1925,22 @@ static s32 cake_enqueue(struct sk_buff *skb, struct Qdisc *sch, q->buffer_max_used = q->buffer_used;
if (q->buffer_used > q->buffer_limit) { + bool same_flow = false; u32 dropped = 0; + u32 drop_id;
while (q->buffer_used > q->buffer_limit) { dropped++; - cake_drop(sch, to_free); + drop_id = cake_drop(sch, to_free); + + if ((drop_id >> 16) == tin && + (drop_id & 0xFFFF) == idx) + same_flow = true; } b->drop_overlimit += dropped; + + if (same_flow) + return NET_XMIT_CN; } return NET_XMIT_SUCCESS; }
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: William Liu will@willsroot.io
[ Upstream commit 2c2192e5f9c7c2892fe2363244d1387f62710d83 ]
The WARN_ON trigger based on !cl->leaf.q->q.qlen is unnecessary in htb_activate. htb_dequeue_tree already accounts for that scenario.
Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") Signed-off-by: William Liu will@willsroot.io Reviewed-by: Savino Dicanosa savy@syst3mfailure.io Link: https://patch.msgid.link/20250819033632.579854-1-will@willsroot.io Signed-off-by: Jakub Kicinski kuba@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- net/sched/sch_htb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/net/sched/sch_htb.c b/net/sched/sch_htb.c index c968ea763774..b5e40c51655a 100644 --- a/net/sched/sch_htb.c +++ b/net/sched/sch_htb.c @@ -592,7 +592,7 @@ htb_change_class_mode(struct htb_sched *q, struct htb_class *cl, s64 *diff) */ static inline void htb_activate(struct htb_sched *q, struct htb_class *cl) { - WARN_ON(cl->level || !cl->leaf.q || !cl->leaf.q->q.qlen); + WARN_ON(cl->level || !cl->leaf.q);
if (!cl->prio_activity) { cl->prio_activity = 1 << cl->prio;
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Dewei Meng mengdewei@cqsoftware.com.cn
[ Upstream commit 5003a65790ed66be882d1987cc2ca86af0de3db1 ]
In the snd_utimer_create() function, if the kasprintf() function return NULL, snd_utimer_put_id() will be called, finally use ida_free() to free the unallocated id 0.
the syzkaller reported the following information: ------------[ cut here ]------------ ida_free called for id=0 which is not allocated. WARNING: CPU: 1 PID: 1286 at lib/idr.c:592 ida_free+0x1fd/0x2f0 lib/idr.c:592 Modules linked in: CPU: 1 UID: 0 PID: 1286 Comm: syz-executor164 Not tainted 6.15.8 #3 PREEMPT(lazy) Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.16.3-4.fc42 04/01/2014 RIP: 0010:ida_free+0x1fd/0x2f0 lib/idr.c:592 Code: f8 fc 41 83 fc 3e 76 69 e8 70 b2 f8 (...) RSP: 0018:ffffc900007f79c8 EFLAGS: 00010282 RAX: 0000000000000000 RBX: 1ffff920000fef3b RCX: ffffffff872176a5 RDX: ffff88800369d200 RSI: 0000000000000000 RDI: ffff88800369d200 RBP: 0000000000000000 R08: ffffffff87ba60a5 R09: 0000000000000000 R10: 0000000000000001 R11: 0000000000000000 R12: 0000000000000000 R13: 0000000000000002 R14: 0000000000000000 R15: 0000000000000000 FS: 00007f6f1abc1740(0000) GS:ffff8880d76a0000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: 00007f6f1ad7a784 CR3: 000000007a6e2000 CR4: 00000000000006f0 Call Trace: <TASK> snd_utimer_put_id sound/core/timer.c:2043 [inline] [snd_timer] snd_utimer_create+0x59b/0x6a0 sound/core/timer.c:2184 [snd_timer] snd_utimer_ioctl_create sound/core/timer.c:2202 [inline] [snd_timer] __snd_timer_user_ioctl.isra.0+0x724/0x1340 sound/core/timer.c:2287 [snd_timer] snd_timer_user_ioctl+0x75/0xc0 sound/core/timer.c:2298 [snd_timer] vfs_ioctl fs/ioctl.c:51 [inline] __do_sys_ioctl fs/ioctl.c:907 [inline] __se_sys_ioctl fs/ioctl.c:893 [inline] __x64_sys_ioctl+0x198/0x200 fs/ioctl.c:893 do_syscall_x64 arch/x86/entry/syscall_64.c:63 [inline] do_syscall_64+0x7b/0x160 arch/x86/entry/syscall_64.c:94 entry_SYSCALL_64_after_hwframe+0x76/0x7e [...]
The utimer->id should be set properly before the kasprintf() function, ensures the snd_utimer_put_id() function will free the allocated id.
Fixes: 37745918e0e75 ("ALSA: timer: Introduce virtual userspace-driven timers") Signed-off-by: Dewei Meng mengdewei@cqsoftware.com.cn Link: https://patch.msgid.link/20250821014317.40786-1-mengdewei@cqsoftware.com.cn Signed-off-by: Takashi Iwai tiwai@suse.de Signed-off-by: Sasha Levin sashal@kernel.org --- sound/core/timer.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/sound/core/timer.c b/sound/core/timer.c index 8072183c33d3..a352247519be 100644 --- a/sound/core/timer.c +++ b/sound/core/timer.c @@ -2139,14 +2139,14 @@ static int snd_utimer_create(struct snd_timer_uinfo *utimer_info, goto err_take_id; }
+ utimer->id = utimer_id; + utimer->name = kasprintf(GFP_KERNEL, "snd-utimer%d", utimer_id); if (!utimer->name) { err = -ENOMEM; goto err_get_name; }
- utimer->id = utimer_id; - tid.dev_sclass = SNDRV_TIMER_SCLASS_APPLICATION; tid.dev_class = SNDRV_TIMER_CLASS_GLOBAL; tid.card = -1;
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Hangbin Liu liuhangbin@gmail.com
[ Upstream commit b64d035f77b1f02ab449393342264b44950a75ae ]
The port's actor_oper_port_state activity flag should be updated immediately after changing the lacp_active option to reflect the current mode correctly.
Fixes: 3a755cd8b7c6 ("bonding: add new option lacp_active") Signed-off-by: Hangbin Liu liuhangbin@gmail.com Link: https://patch.msgid.link/20250815062000.22220-2-liuhangbin@gmail.com Signed-off-by: Paolo Abeni pabeni@redhat.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/net/bonding/bond_3ad.c | 25 +++++++++++++++++++++++++ drivers/net/bonding/bond_options.c | 1 + include/net/bond_3ad.h | 1 + 3 files changed, 27 insertions(+)
diff --git a/drivers/net/bonding/bond_3ad.c b/drivers/net/bonding/bond_3ad.c index c6807e473ab7..a51305423d28 100644 --- a/drivers/net/bonding/bond_3ad.c +++ b/drivers/net/bonding/bond_3ad.c @@ -2869,6 +2869,31 @@ void bond_3ad_update_lacp_rate(struct bonding *bond) spin_unlock_bh(&bond->mode_lock); }
+/** + * bond_3ad_update_lacp_active - change the lacp active + * @bond: bonding struct + * + * Update actor_oper_port_state when lacp_active is modified. + */ +void bond_3ad_update_lacp_active(struct bonding *bond) +{ + struct port *port = NULL; + struct list_head *iter; + struct slave *slave; + int lacp_active; + + lacp_active = bond->params.lacp_active; + spin_lock_bh(&bond->mode_lock); + bond_for_each_slave(bond, slave, iter) { + port = &(SLAVE_AD_INFO(slave)->port); + if (lacp_active) + port->actor_oper_port_state |= LACP_STATE_LACP_ACTIVITY; + else + port->actor_oper_port_state &= ~LACP_STATE_LACP_ACTIVITY; + } + spin_unlock_bh(&bond->mode_lock); +} + size_t bond_3ad_stats_size(void) { return nla_total_size_64bit(sizeof(u64)) + /* BOND_3AD_STAT_LACPDU_RX */ diff --git a/drivers/net/bonding/bond_options.c b/drivers/net/bonding/bond_options.c index 91893c29b899..28c53f1b1382 100644 --- a/drivers/net/bonding/bond_options.c +++ b/drivers/net/bonding/bond_options.c @@ -1637,6 +1637,7 @@ static int bond_option_lacp_active_set(struct bonding *bond, netdev_dbg(bond->dev, "Setting LACP active to %s (%llu)\n", newval->string, newval->value); bond->params.lacp_active = newval->value; + bond_3ad_update_lacp_active(bond);
return 0; } diff --git a/include/net/bond_3ad.h b/include/net/bond_3ad.h index 2053cd8e788a..dba369a2cf27 100644 --- a/include/net/bond_3ad.h +++ b/include/net/bond_3ad.h @@ -307,6 +307,7 @@ int bond_3ad_lacpdu_recv(const struct sk_buff *skb, struct bonding *bond, struct slave *slave); int bond_3ad_set_carrier(struct bonding *bond); void bond_3ad_update_lacp_rate(struct bonding *bond); +void bond_3ad_update_lacp_active(struct bonding *bond); void bond_3ad_update_ad_actor_settings(struct bonding *bond); int bond_3ad_stats_fill(struct sk_buff *skb, struct bond_3ad_stats *stats); size_t bond_3ad_stats_size(void);
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Hangbin Liu liuhangbin@gmail.com
[ Upstream commit 0599640a21e98f0d6a3e9ff85c0a687c90a8103b ]
When `lacp_active` is set to `off`, the bond operates in passive mode, meaning it only "speaks when spoken to." However, the current kernel implementation only sends an LACPDU in response when the partner's state changes.
As a result, once LACP negotiation succeeds, the actor stops sending LACPDUs until the partner times out and sends an "expired" LACPDU. This causes continuous LACP state flapping.
According to IEEE 802.1AX-2014, 6.4.13 Periodic Transmission machine. The values of Partner_Oper_Port_State.LACP_Activity and Actor_Oper_Port_State.LACP_Activity determine whether periodic transmissions take place. If either or both parameters are set to Active LACP, then periodic transmissions occur; if both are set to Passive LACP, then periodic transmissions do not occur.
To comply with this, we remove the `!bond->params.lacp_active` check in `ad_periodic_machine()`. Instead, we initialize the actor's port's `LACP_STATE_LACP_ACTIVITY` state based on `lacp_active` setting.
Additionally, we avoid setting the partner's state to `LACP_STATE_LACP_ACTIVITY` in the EXPIRED state, since we should not assume the partner is active by default.
This ensures that in passive mode, the bond starts sending periodic LACPDUs after receiving one from the partner, and avoids flapping due to inactivity.
Fixes: 3a755cd8b7c6 ("bonding: add new option lacp_active") Signed-off-by: Hangbin Liu liuhangbin@gmail.com Link: https://patch.msgid.link/20250815062000.22220-3-liuhangbin@gmail.com Signed-off-by: Paolo Abeni pabeni@redhat.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/net/bonding/bond_3ad.c | 42 +++++++++++++++++++--------------- 1 file changed, 24 insertions(+), 18 deletions(-)
diff --git a/drivers/net/bonding/bond_3ad.c b/drivers/net/bonding/bond_3ad.c index a51305423d28..4c2560ae8866 100644 --- a/drivers/net/bonding/bond_3ad.c +++ b/drivers/net/bonding/bond_3ad.c @@ -95,13 +95,13 @@ static int ad_marker_send(struct port *port, struct bond_marker *marker); static void ad_mux_machine(struct port *port, bool *update_slave_arr); static void ad_rx_machine(struct lacpdu *lacpdu, struct port *port); static void ad_tx_machine(struct port *port); -static void ad_periodic_machine(struct port *port, struct bond_params *bond_params); +static void ad_periodic_machine(struct port *port); static void ad_port_selection_logic(struct port *port, bool *update_slave_arr); static void ad_agg_selection_logic(struct aggregator *aggregator, bool *update_slave_arr); static void ad_clear_agg(struct aggregator *aggregator); static void ad_initialize_agg(struct aggregator *aggregator); -static void ad_initialize_port(struct port *port, int lacp_fast); +static void ad_initialize_port(struct port *port, const struct bond_params *bond_params); static void ad_enable_collecting(struct port *port); static void ad_disable_distributing(struct port *port, bool *update_slave_arr); @@ -1296,10 +1296,16 @@ static void ad_rx_machine(struct lacpdu *lacpdu, struct port *port) * case of EXPIRED even if LINK_DOWN didn't arrive for * the port. */ - port->partner_oper.port_state &= ~LACP_STATE_SYNCHRONIZATION; port->sm_vars &= ~AD_PORT_MATCHED; + /* Based on IEEE 8021AX-2014, Figure 6-18 - Receive + * machine state diagram, the statue should be + * Partner_Oper_Port_State.Synchronization = FALSE; + * Partner_Oper_Port_State.LACP_Timeout = Short Timeout; + * start current_while_timer(Short Timeout); + * Actor_Oper_Port_State.Expired = TRUE; + */ + port->partner_oper.port_state &= ~LACP_STATE_SYNCHRONIZATION; port->partner_oper.port_state |= LACP_STATE_LACP_TIMEOUT; - port->partner_oper.port_state |= LACP_STATE_LACP_ACTIVITY; port->sm_rx_timer_counter = __ad_timer_to_ticks(AD_CURRENT_WHILE_TIMER, (u16)(AD_SHORT_TIMEOUT)); port->actor_oper_port_state |= LACP_STATE_EXPIRED; port->sm_vars |= AD_PORT_CHURNED; @@ -1405,11 +1411,10 @@ static void ad_tx_machine(struct port *port) /** * ad_periodic_machine - handle a port's periodic state machine * @port: the port we're looking at - * @bond_params: bond parameters we will use * * Turn ntt flag on priodically to perform periodic transmission of lacpdu's. */ -static void ad_periodic_machine(struct port *port, struct bond_params *bond_params) +static void ad_periodic_machine(struct port *port) { periodic_states_t last_state;
@@ -1418,8 +1423,7 @@ static void ad_periodic_machine(struct port *port, struct bond_params *bond_para
/* check if port was reinitialized */ if (((port->sm_vars & AD_PORT_BEGIN) || !(port->sm_vars & AD_PORT_LACP_ENABLED) || !port->is_enabled) || - (!(port->actor_oper_port_state & LACP_STATE_LACP_ACTIVITY) && !(port->partner_oper.port_state & LACP_STATE_LACP_ACTIVITY)) || - !bond_params->lacp_active) { + (!(port->actor_oper_port_state & LACP_STATE_LACP_ACTIVITY) && !(port->partner_oper.port_state & LACP_STATE_LACP_ACTIVITY))) { port->sm_periodic_state = AD_NO_PERIODIC; } /* check if state machine should change state */ @@ -1943,16 +1947,16 @@ static void ad_initialize_agg(struct aggregator *aggregator) /** * ad_initialize_port - initialize a given port's parameters * @port: the port we're looking at - * @lacp_fast: boolean. whether fast periodic should be used + * @bond_params: bond parameters we will use */ -static void ad_initialize_port(struct port *port, int lacp_fast) +static void ad_initialize_port(struct port *port, const struct bond_params *bond_params) { static const struct port_params tmpl = { .system_priority = 0xffff, .key = 1, .port_number = 1, .port_priority = 0xff, - .port_state = 1, + .port_state = 0, }; static const struct lacpdu lacpdu = { .subtype = 0x01, @@ -1970,12 +1974,14 @@ static void ad_initialize_port(struct port *port, int lacp_fast) port->actor_port_priority = 0xff; port->actor_port_aggregator_identifier = 0; port->ntt = false; - port->actor_admin_port_state = LACP_STATE_AGGREGATION | - LACP_STATE_LACP_ACTIVITY; - port->actor_oper_port_state = LACP_STATE_AGGREGATION | - LACP_STATE_LACP_ACTIVITY; + port->actor_admin_port_state = LACP_STATE_AGGREGATION; + port->actor_oper_port_state = LACP_STATE_AGGREGATION; + if (bond_params->lacp_active) { + port->actor_admin_port_state |= LACP_STATE_LACP_ACTIVITY; + port->actor_oper_port_state |= LACP_STATE_LACP_ACTIVITY; + }
- if (lacp_fast) + if (bond_params->lacp_fast) port->actor_oper_port_state |= LACP_STATE_LACP_TIMEOUT;
memcpy(&port->partner_admin, &tmpl, sizeof(tmpl)); @@ -2187,7 +2193,7 @@ void bond_3ad_bind_slave(struct slave *slave) /* port initialization */ port = &(SLAVE_AD_INFO(slave)->port);
- ad_initialize_port(port, bond->params.lacp_fast); + ad_initialize_port(port, &bond->params);
port->slave = slave; port->actor_port_number = SLAVE_AD_INFO(slave)->id; @@ -2499,7 +2505,7 @@ void bond_3ad_state_machine_handler(struct work_struct *work) }
ad_rx_machine(NULL, port); - ad_periodic_machine(port, &bond->params); + ad_periodic_machine(port); ad_port_selection_logic(port, &update_slave_arr); ad_mux_machine(port, &update_slave_arr); ad_tx_machine(port);
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Lorenzo Bianconi lorenzo@kernel.org
[ Upstream commit 9f6b606b6b37e61427412708411e8e04b1a858e8 ]
SW hash computed by airoha_ppe_foe_get_entry_hash routine (used for foe_flow hlist) can theoretically produce collisions between two different HW PPE entries. In airoha_ppe_foe_insert_entry() if the collision occurs we will mark the second PPE entry in the list as stale (setting the hw hash to 0xffff). Stale entries are no more updated in airoha_ppe_foe_flow_entry_update routine and so they are removed by Netfilter. Fix the problem not marking the second entry as stale in airoha_ppe_foe_insert_entry routine if we have already inserted the brand new entry in the PPE table and let Netfilter remove real stale entries according to their timestamp. Please note this is just a theoretical issue spotted reviewing the code and not faced running the system.
Fixes: cd53f622611f9 ("net: airoha: Add L2 hw acceleration support") Signed-off-by: Lorenzo Bianconi lorenzo@kernel.org Link: https://patch.msgid.link/20250818-airoha-en7581-hash-collision-fix-v1-1-d190... Signed-off-by: Paolo Abeni pabeni@redhat.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/net/ethernet/airoha/airoha_ppe.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-)
diff --git a/drivers/net/ethernet/airoha/airoha_ppe.c b/drivers/net/ethernet/airoha/airoha_ppe.c index 7832fe8fc202..af6e4d4c0ece 100644 --- a/drivers/net/ethernet/airoha/airoha_ppe.c +++ b/drivers/net/ethernet/airoha/airoha_ppe.c @@ -726,10 +726,8 @@ static void airoha_ppe_foe_insert_entry(struct airoha_ppe *ppe, continue; }
- if (commit_done || !airoha_ppe_foe_compare_entry(e, hwe)) { - e->hash = 0xffff; + if (!airoha_ppe_foe_compare_entry(e, hwe)) continue; - }
airoha_ppe_foe_commit_entry(ppe, &e->data, hash); commit_done = true;
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Nilay Shroff nilay@linux.ibm.com
[ Upstream commit 49811586be373e26a3ab52f54e0dfa663c02fddd ]
In preparation for allocating sched_tags before freezing the request queue and acquiring ->elevator_lock, move the elevator queue allocation logic from the elevator ops ->init_sched callback into blk_mq_init_sched. As elevator_alloc is now only invoked from block layer core, we don't need to export it, so unexport elevator_alloc function.
This refactoring provides a centralized location for elevator queue initialization, which makes it easier to store pre-allocated sched_tags in the struct elevator_queue during later changes.
Reviewed-by: Ming Lei ming.lei@redhat.com Reviewed-by: Hannes Reinecke hare@suse.de Reviewed-by: Christoph Hellwig hch@lst.de Signed-off-by: Nilay Shroff nilay@linux.ibm.com Link: https://lore.kernel.org/r/20250730074614.2537382-2-nilay@linux.ibm.com Signed-off-by: Jens Axboe axboe@kernel.dk Stable-dep-of: 2d82f3bd8910 ("blk-mq: fix lockdep warning in __blk_mq_update_nr_hw_queues") Signed-off-by: Sasha Levin sashal@kernel.org --- block/bfq-iosched.c | 13 +++---------- block/blk-mq-sched.c | 11 ++++++++--- block/elevator.c | 1 - block/elevator.h | 2 +- block/kyber-iosched.c | 11 ++--------- block/mq-deadline.c | 14 ++------------ 6 files changed, 16 insertions(+), 36 deletions(-)
diff --git a/block/bfq-iosched.c b/block/bfq-iosched.c index d68da9e92e1e..9483c529c958 100644 --- a/block/bfq-iosched.c +++ b/block/bfq-iosched.c @@ -7229,22 +7229,16 @@ static void bfq_init_root_group(struct bfq_group *root_group, root_group->sched_data.bfq_class_idle_last_service = jiffies; }
-static int bfq_init_queue(struct request_queue *q, struct elevator_type *e) +static int bfq_init_queue(struct request_queue *q, struct elevator_queue *eq) { struct bfq_data *bfqd; - struct elevator_queue *eq; unsigned int i; struct blk_independent_access_ranges *ia_ranges = q->disk->ia_ranges;
- eq = elevator_alloc(q, e); - if (!eq) - return -ENOMEM; - bfqd = kzalloc_node(sizeof(*bfqd), GFP_KERNEL, q->node); - if (!bfqd) { - kobject_put(&eq->kobj); + if (!bfqd) return -ENOMEM; - } + eq->elevator_data = bfqd;
spin_lock_irq(&q->queue_lock); @@ -7402,7 +7396,6 @@ static int bfq_init_queue(struct request_queue *q, struct elevator_type *e)
out_free: kfree(bfqd); - kobject_put(&eq->kobj); return -ENOMEM; }
diff --git a/block/blk-mq-sched.c b/block/blk-mq-sched.c index 55a0fd105147..359e0704e09b 100644 --- a/block/blk-mq-sched.c +++ b/block/blk-mq-sched.c @@ -475,10 +475,14 @@ int blk_mq_init_sched(struct request_queue *q, struct elevator_type *e) q->nr_requests = 2 * min_t(unsigned int, q->tag_set->queue_depth, BLKDEV_DEFAULT_RQ);
+ eq = elevator_alloc(q, e); + if (!eq) + return -ENOMEM; + if (blk_mq_is_shared_tags(flags)) { ret = blk_mq_init_sched_shared_tags(q); if (ret) - return ret; + goto err_put_elevator; }
queue_for_each_hw_ctx(q, hctx, i) { @@ -487,7 +491,7 @@ int blk_mq_init_sched(struct request_queue *q, struct elevator_type *e) goto err_free_map_and_rqs; }
- ret = e->ops.init_sched(q, e); + ret = e->ops.init_sched(q, eq); if (ret) goto err_free_map_and_rqs;
@@ -508,7 +512,8 @@ int blk_mq_init_sched(struct request_queue *q, struct elevator_type *e) err_free_map_and_rqs: blk_mq_sched_free_rqs(q); blk_mq_sched_tags_teardown(q, flags); - +err_put_elevator: + kobject_put(&eq->kobj); q->elevator = NULL; return ret; } diff --git a/block/elevator.c b/block/elevator.c index 88f8f36bed98..939b0c590fbe 100644 --- a/block/elevator.c +++ b/block/elevator.c @@ -148,7 +148,6 @@ struct elevator_queue *elevator_alloc(struct request_queue *q,
return eq; } -EXPORT_SYMBOL(elevator_alloc);
static void elevator_release(struct kobject *kobj) { diff --git a/block/elevator.h b/block/elevator.h index a07ce773a38f..a4de5f9ad790 100644 --- a/block/elevator.h +++ b/block/elevator.h @@ -24,7 +24,7 @@ struct blk_mq_alloc_data; struct blk_mq_hw_ctx;
struct elevator_mq_ops { - int (*init_sched)(struct request_queue *, struct elevator_type *); + int (*init_sched)(struct request_queue *, struct elevator_queue *); void (*exit_sched)(struct elevator_queue *); int (*init_hctx)(struct blk_mq_hw_ctx *, unsigned int); void (*exit_hctx)(struct blk_mq_hw_ctx *, unsigned int); diff --git a/block/kyber-iosched.c b/block/kyber-iosched.c index bfd9a40bb33d..70cbc7b2deb4 100644 --- a/block/kyber-iosched.c +++ b/block/kyber-iosched.c @@ -399,20 +399,13 @@ static struct kyber_queue_data *kyber_queue_data_alloc(struct request_queue *q) return ERR_PTR(ret); }
-static int kyber_init_sched(struct request_queue *q, struct elevator_type *e) +static int kyber_init_sched(struct request_queue *q, struct elevator_queue *eq) { struct kyber_queue_data *kqd; - struct elevator_queue *eq; - - eq = elevator_alloc(q, e); - if (!eq) - return -ENOMEM;
kqd = kyber_queue_data_alloc(q); - if (IS_ERR(kqd)) { - kobject_put(&eq->kobj); + if (IS_ERR(kqd)) return PTR_ERR(kqd); - }
blk_stat_enable_accounting(q);
diff --git a/block/mq-deadline.c b/block/mq-deadline.c index 9ab6c6256695..b9b7cdf1d3c9 100644 --- a/block/mq-deadline.c +++ b/block/mq-deadline.c @@ -554,20 +554,14 @@ static void dd_exit_sched(struct elevator_queue *e) /* * initialize elevator private data (deadline_data). */ -static int dd_init_sched(struct request_queue *q, struct elevator_type *e) +static int dd_init_sched(struct request_queue *q, struct elevator_queue *eq) { struct deadline_data *dd; - struct elevator_queue *eq; enum dd_prio prio; - int ret = -ENOMEM; - - eq = elevator_alloc(q, e); - if (!eq) - return ret;
dd = kzalloc_node(sizeof(*dd), GFP_KERNEL, q->node); if (!dd) - goto put_eq; + return -ENOMEM;
eq->elevator_data = dd;
@@ -594,10 +588,6 @@ static int dd_init_sched(struct request_queue *q, struct elevator_type *e)
q->elevator = eq; return 0; - -put_eq: - kobject_put(&eq->kobj); - return ret; }
/*
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Nilay Shroff nilay@linux.ibm.com
[ Upstream commit f5a6604f7a4405450e4a1f54e5430f47290c500f ]
Recent lockdep reports [1] have revealed a potential deadlock caused by a lock dependency between the percpu allocator lock and the elevator lock. This issue can be avoided by ensuring that the allocation and release of scheduler tags (sched_tags) are performed outside the elevator lock. Furthermore, the queue does not need to be remain frozen during these operations.
To address this, move all sched_tags allocations and deallocations outside of both the ->elevator_lock and the ->freeze_lock. Since the lifetime of the elevator queue and its associated sched_tags is closely tied, the allocated sched_tags are now stored in the elevator queue structure. Then, during the actual elevator switch (which runs under ->freeze_lock and ->elevator_lock), the pre-allocated sched_tags are assigned to the appropriate q->hctx. Once the elevator switch is complete and the locks are released, the old elevator queue and its associated sched_tags are freed.
This commit specifically addresses the allocation/deallocation of sched_ tags during elevator switching. Note that sched_tags may also be allocated in other contexts, such as during nr_hw_queues updates. Supporting that use case will require batch allocation/deallocation, which will be handled in a follow-up patch.
This restructuring ensures that sched_tags memory management occurs entirely outside of the ->elevator_lock and ->freeze_lock context, eliminating the lock dependency problem seen during scheduler updates.
[1] https://lore.kernel.org/all/0659ea8d-a463-47c8-9180-43c719e106eb@linux.ibm.c...
Reported-by: Stefan Haberland sth@linux.ibm.com Closes: https://lore.kernel.org/all/0659ea8d-a463-47c8-9180-43c719e106eb@linux.ibm.c... Reviewed-by: Ming Lei ming.lei@redhat.com Reviewed-by: Christoph Hellwig hch@lst.de Reviewed-by: Hannes Reinecke hare@suse.de Signed-off-by: Nilay Shroff nilay@linux.ibm.com Link: https://lore.kernel.org/r/20250730074614.2537382-3-nilay@linux.ibm.com Signed-off-by: Jens Axboe axboe@kernel.dk Stable-dep-of: 2d82f3bd8910 ("blk-mq: fix lockdep warning in __blk_mq_update_nr_hw_queues") Signed-off-by: Sasha Levin sashal@kernel.org --- block/blk-mq-sched.c | 155 +++++++++++++++++++++++-------------------- block/blk-mq-sched.h | 8 ++- block/elevator.c | 40 +++++++++-- block/elevator.h | 14 +++- 4 files changed, 136 insertions(+), 81 deletions(-)
diff --git a/block/blk-mq-sched.c b/block/blk-mq-sched.c index 359e0704e09b..2d6d1ebdd8fb 100644 --- a/block/blk-mq-sched.c +++ b/block/blk-mq-sched.c @@ -374,64 +374,17 @@ bool blk_mq_sched_try_insert_merge(struct request_queue *q, struct request *rq, } EXPORT_SYMBOL_GPL(blk_mq_sched_try_insert_merge);
-static int blk_mq_sched_alloc_map_and_rqs(struct request_queue *q, - struct blk_mq_hw_ctx *hctx, - unsigned int hctx_idx) -{ - if (blk_mq_is_shared_tags(q->tag_set->flags)) { - hctx->sched_tags = q->sched_shared_tags; - return 0; - } - - hctx->sched_tags = blk_mq_alloc_map_and_rqs(q->tag_set, hctx_idx, - q->nr_requests); - - if (!hctx->sched_tags) - return -ENOMEM; - return 0; -} - -static void blk_mq_exit_sched_shared_tags(struct request_queue *queue) -{ - blk_mq_free_rq_map(queue->sched_shared_tags); - queue->sched_shared_tags = NULL; -} - /* called in queue's release handler, tagset has gone away */ static void blk_mq_sched_tags_teardown(struct request_queue *q, unsigned int flags) { struct blk_mq_hw_ctx *hctx; unsigned long i;
- queue_for_each_hw_ctx(q, hctx, i) { - if (hctx->sched_tags) { - if (!blk_mq_is_shared_tags(flags)) - blk_mq_free_rq_map(hctx->sched_tags); - hctx->sched_tags = NULL; - } - } + queue_for_each_hw_ctx(q, hctx, i) + hctx->sched_tags = NULL;
if (blk_mq_is_shared_tags(flags)) - blk_mq_exit_sched_shared_tags(q); -} - -static int blk_mq_init_sched_shared_tags(struct request_queue *queue) -{ - struct blk_mq_tag_set *set = queue->tag_set; - - /* - * Set initial depth at max so that we don't need to reallocate for - * updating nr_requests. - */ - queue->sched_shared_tags = blk_mq_alloc_map_and_rqs(set, - BLK_MQ_NO_HCTX_IDX, - MAX_SCHED_RQ); - if (!queue->sched_shared_tags) - return -ENOMEM; - - blk_mq_tag_update_sched_shared_tags(queue); - - return 0; + q->sched_shared_tags = NULL; }
void blk_mq_sched_reg_debugfs(struct request_queue *q) @@ -458,8 +411,75 @@ void blk_mq_sched_unreg_debugfs(struct request_queue *q) mutex_unlock(&q->debugfs_mutex); }
+void blk_mq_free_sched_tags(struct elevator_tags *et, + struct blk_mq_tag_set *set) +{ + unsigned long i; + + /* Shared tags are stored at index 0 in @tags. */ + if (blk_mq_is_shared_tags(set->flags)) + blk_mq_free_map_and_rqs(set, et->tags[0], BLK_MQ_NO_HCTX_IDX); + else { + for (i = 0; i < et->nr_hw_queues; i++) + blk_mq_free_map_and_rqs(set, et->tags[i], i); + } + + kfree(et); +} + +struct elevator_tags *blk_mq_alloc_sched_tags(struct blk_mq_tag_set *set, + unsigned int nr_hw_queues) +{ + unsigned int nr_tags; + int i; + struct elevator_tags *et; + gfp_t gfp = GFP_NOIO | __GFP_ZERO | __GFP_NOWARN | __GFP_NORETRY; + + if (blk_mq_is_shared_tags(set->flags)) + nr_tags = 1; + else + nr_tags = nr_hw_queues; + + et = kmalloc(sizeof(struct elevator_tags) + + nr_tags * sizeof(struct blk_mq_tags *), gfp); + if (!et) + return NULL; + /* + * Default to double of smaller one between hw queue_depth and + * 128, since we don't split into sync/async like the old code + * did. Additionally, this is a per-hw queue depth. + */ + et->nr_requests = 2 * min_t(unsigned int, set->queue_depth, + BLKDEV_DEFAULT_RQ); + et->nr_hw_queues = nr_hw_queues; + + if (blk_mq_is_shared_tags(set->flags)) { + /* Shared tags are stored at index 0 in @tags. */ + et->tags[0] = blk_mq_alloc_map_and_rqs(set, BLK_MQ_NO_HCTX_IDX, + MAX_SCHED_RQ); + if (!et->tags[0]) + goto out; + } else { + for (i = 0; i < et->nr_hw_queues; i++) { + et->tags[i] = blk_mq_alloc_map_and_rqs(set, i, + et->nr_requests); + if (!et->tags[i]) + goto out_unwind; + } + } + + return et; +out_unwind: + while (--i >= 0) + blk_mq_free_map_and_rqs(set, et->tags[i], i); +out: + kfree(et); + return NULL; +} + /* caller must have a reference to @e, will grab another one if successful */ -int blk_mq_init_sched(struct request_queue *q, struct elevator_type *e) +int blk_mq_init_sched(struct request_queue *q, struct elevator_type *e, + struct elevator_tags *et) { unsigned int flags = q->tag_set->flags; struct blk_mq_hw_ctx *hctx; @@ -467,40 +487,33 @@ int blk_mq_init_sched(struct request_queue *q, struct elevator_type *e) unsigned long i; int ret;
- /* - * Default to double of smaller one between hw queue_depth and 128, - * since we don't split into sync/async like the old code did. - * Additionally, this is a per-hw queue depth. - */ - q->nr_requests = 2 * min_t(unsigned int, q->tag_set->queue_depth, - BLKDEV_DEFAULT_RQ); - - eq = elevator_alloc(q, e); + eq = elevator_alloc(q, e, et); if (!eq) return -ENOMEM;
+ q->nr_requests = et->nr_requests; + if (blk_mq_is_shared_tags(flags)) { - ret = blk_mq_init_sched_shared_tags(q); - if (ret) - goto err_put_elevator; + /* Shared tags are stored at index 0 in @et->tags. */ + q->sched_shared_tags = et->tags[0]; + blk_mq_tag_update_sched_shared_tags(q); }
queue_for_each_hw_ctx(q, hctx, i) { - ret = blk_mq_sched_alloc_map_and_rqs(q, hctx, i); - if (ret) - goto err_free_map_and_rqs; + if (blk_mq_is_shared_tags(flags)) + hctx->sched_tags = q->sched_shared_tags; + else + hctx->sched_tags = et->tags[i]; }
ret = e->ops.init_sched(q, eq); if (ret) - goto err_free_map_and_rqs; + goto out;
queue_for_each_hw_ctx(q, hctx, i) { if (e->ops.init_hctx) { ret = e->ops.init_hctx(hctx, i); if (ret) { - eq = q->elevator; - blk_mq_sched_free_rqs(q); blk_mq_exit_sched(q, eq); kobject_put(&eq->kobj); return ret; @@ -509,10 +522,8 @@ int blk_mq_init_sched(struct request_queue *q, struct elevator_type *e) } return 0;
-err_free_map_and_rqs: - blk_mq_sched_free_rqs(q); +out: blk_mq_sched_tags_teardown(q, flags); -err_put_elevator: kobject_put(&eq->kobj); q->elevator = NULL; return ret; diff --git a/block/blk-mq-sched.h b/block/blk-mq-sched.h index 1326526bb733..0cde00cd1c47 100644 --- a/block/blk-mq-sched.h +++ b/block/blk-mq-sched.h @@ -18,10 +18,16 @@ void __blk_mq_sched_restart(struct blk_mq_hw_ctx *hctx);
void blk_mq_sched_dispatch_requests(struct blk_mq_hw_ctx *hctx);
-int blk_mq_init_sched(struct request_queue *q, struct elevator_type *e); +int blk_mq_init_sched(struct request_queue *q, struct elevator_type *e, + struct elevator_tags *et); void blk_mq_exit_sched(struct request_queue *q, struct elevator_queue *e); void blk_mq_sched_free_rqs(struct request_queue *q);
+struct elevator_tags *blk_mq_alloc_sched_tags(struct blk_mq_tag_set *set, + unsigned int nr_hw_queues); +void blk_mq_free_sched_tags(struct elevator_tags *et, + struct blk_mq_tag_set *set); + static inline void blk_mq_sched_restart(struct blk_mq_hw_ctx *hctx) { if (test_bit(BLK_MQ_S_SCHED_RESTART, &hctx->state)) diff --git a/block/elevator.c b/block/elevator.c index 939b0c590fbe..e9dc837b7b70 100644 --- a/block/elevator.c +++ b/block/elevator.c @@ -54,6 +54,8 @@ struct elv_change_ctx { struct elevator_queue *old; /* for registering new elevator */ struct elevator_queue *new; + /* holds sched tags data */ + struct elevator_tags *et; };
static DEFINE_SPINLOCK(elv_list_lock); @@ -132,7 +134,7 @@ static struct elevator_type *elevator_find_get(const char *name) static const struct kobj_type elv_ktype;
struct elevator_queue *elevator_alloc(struct request_queue *q, - struct elevator_type *e) + struct elevator_type *e, struct elevator_tags *et) { struct elevator_queue *eq;
@@ -145,6 +147,7 @@ struct elevator_queue *elevator_alloc(struct request_queue *q, kobject_init(&eq->kobj, &elv_ktype); mutex_init(&eq->sysfs_lock); hash_init(eq->hash); + eq->et = et;
return eq; } @@ -165,7 +168,6 @@ static void elevator_exit(struct request_queue *q) lockdep_assert_held(&q->elevator_lock);
ioc_clear_queue(q); - blk_mq_sched_free_rqs(q);
mutex_lock(&e->sysfs_lock); blk_mq_exit_sched(q, e); @@ -591,7 +593,7 @@ static int elevator_switch(struct request_queue *q, struct elv_change_ctx *ctx) }
if (new_e) { - ret = blk_mq_init_sched(q, new_e); + ret = blk_mq_init_sched(q, new_e, ctx->et); if (ret) goto out_unfreeze; ctx->new = q->elevator; @@ -626,8 +628,10 @@ static void elv_exit_and_release(struct request_queue *q) elevator_exit(q); mutex_unlock(&q->elevator_lock); blk_mq_unfreeze_queue(q, memflags); - if (e) + if (e) { + blk_mq_free_sched_tags(e->et, q->tag_set); kobject_put(&e->kobj); + } }
static int elevator_change_done(struct request_queue *q, @@ -640,6 +644,7 @@ static int elevator_change_done(struct request_queue *q, &ctx->old->flags);
elv_unregister_queue(q, ctx->old); + blk_mq_free_sched_tags(ctx->old->et, q->tag_set); kobject_put(&ctx->old->kobj); if (enable_wbt) wbt_enable_default(q->disk); @@ -658,9 +663,16 @@ static int elevator_change_done(struct request_queue *q, static int elevator_change(struct request_queue *q, struct elv_change_ctx *ctx) { unsigned int memflags; + struct blk_mq_tag_set *set = q->tag_set; int ret = 0;
- lockdep_assert_held(&q->tag_set->update_nr_hwq_lock); + lockdep_assert_held(&set->update_nr_hwq_lock); + + if (strncmp(ctx->name, "none", 4)) { + ctx->et = blk_mq_alloc_sched_tags(set, set->nr_hw_queues); + if (!ctx->et) + return -ENOMEM; + }
memflags = blk_mq_freeze_queue(q); /* @@ -680,6 +692,11 @@ static int elevator_change(struct request_queue *q, struct elv_change_ctx *ctx) blk_mq_unfreeze_queue(q, memflags); if (!ret) ret = elevator_change_done(q, ctx); + /* + * Free sched tags if it's allocated but we couldn't switch elevator. + */ + if (ctx->et && !ctx->new) + blk_mq_free_sched_tags(ctx->et, set);
return ret; } @@ -690,6 +707,7 @@ static int elevator_change(struct request_queue *q, struct elv_change_ctx *ctx) */ void elv_update_nr_hw_queues(struct request_queue *q, struct elevator_type *e) { + struct blk_mq_tag_set *set = q->tag_set; struct elv_change_ctx ctx = {}; int ret = -ENODEV;
@@ -697,15 +715,25 @@ void elv_update_nr_hw_queues(struct request_queue *q, struct elevator_type *e)
if (e && !blk_queue_dying(q) && blk_queue_registered(q)) { ctx.name = e->elevator_name; - + ctx.et = blk_mq_alloc_sched_tags(set, set->nr_hw_queues); + if (!ctx.et) { + WARN_ON_ONCE(1); + goto unfreeze; + } mutex_lock(&q->elevator_lock); /* force to reattach elevator after nr_hw_queue is updated */ ret = elevator_switch(q, &ctx); mutex_unlock(&q->elevator_lock); } +unfreeze: blk_mq_unfreeze_queue_nomemrestore(q); if (!ret) WARN_ON_ONCE(elevator_change_done(q, &ctx)); + /* + * Free sched tags if it's allocated but we couldn't switch elevator. + */ + if (ctx.et && !ctx.new) + blk_mq_free_sched_tags(ctx.et, set); }
/* diff --git a/block/elevator.h b/block/elevator.h index a4de5f9ad790..adc5c157e17e 100644 --- a/block/elevator.h +++ b/block/elevator.h @@ -23,6 +23,15 @@ enum elv_merge { struct blk_mq_alloc_data; struct blk_mq_hw_ctx;
+struct elevator_tags { + /* num. of hardware queues for which tags are allocated */ + unsigned int nr_hw_queues; + /* depth used while allocating tags */ + unsigned int nr_requests; + /* shared tag is stored at index 0 */ + struct blk_mq_tags *tags[]; +}; + struct elevator_mq_ops { int (*init_sched)(struct request_queue *, struct elevator_queue *); void (*exit_sched)(struct elevator_queue *); @@ -113,6 +122,7 @@ struct request *elv_rqhash_find(struct request_queue *q, sector_t offset); struct elevator_queue { struct elevator_type *type; + struct elevator_tags *et; void *elevator_data; struct kobject kobj; struct mutex sysfs_lock; @@ -152,8 +162,8 @@ ssize_t elv_iosched_show(struct gendisk *disk, char *page); ssize_t elv_iosched_store(struct gendisk *disk, const char *page, size_t count);
extern bool elv_bio_merge_ok(struct request *, struct bio *); -extern struct elevator_queue *elevator_alloc(struct request_queue *, - struct elevator_type *); +struct elevator_queue *elevator_alloc(struct request_queue *, + struct elevator_type *, struct elevator_tags *);
/* * Helper functions.
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Nilay Shroff nilay@linux.ibm.com
[ Upstream commit 04225d13aef11b2a539014def5e47d8c21fd74a5 ]
Move scheduler tags (sched_tags) allocation and deallocation outside both the ->elevator_lock and ->freeze_lock when updating nr_hw_queues. This change breaks the dependency chain from the percpu allocator lock to the elevator lock, helping to prevent potential deadlocks, as observed in the reported lockdep splat[1].
This commit introduces batch allocation and deallocation helpers for sched_tags, which are now used from within __blk_mq_update_nr_hw_queues routine while iterating through the tagset.
With this change, all sched_tags memory management is handled entirely outside the ->elevator_lock and the ->freeze_lock context, thereby eliminating the lock dependency that could otherwise manifest during nr_hw_queues updates.
[1] https://lore.kernel.org/all/0659ea8d-a463-47c8-9180-43c719e106eb@linux.ibm.c...
Reported-by: Stefan Haberland sth@linux.ibm.com Closes: https://lore.kernel.org/all/0659ea8d-a463-47c8-9180-43c719e106eb@linux.ibm.c... Reviewed-by: Ming Lei ming.lei@redhat.com Reviewed-by: Christoph Hellwig hch@lst.de Reviewed-by: Hannes Reinecke hare@suse.de Signed-off-by: Nilay Shroff nilay@linux.ibm.com Link: https://lore.kernel.org/r/20250730074614.2537382-4-nilay@linux.ibm.com Signed-off-by: Jens Axboe axboe@kernel.dk Stable-dep-of: 2d82f3bd8910 ("blk-mq: fix lockdep warning in __blk_mq_update_nr_hw_queues") Signed-off-by: Sasha Levin sashal@kernel.org --- block/blk-mq-sched.c | 65 ++++++++++++++++++++++++++++++++++++++++++++ block/blk-mq-sched.h | 4 +++ block/blk-mq.c | 16 +++++++---- block/blk.h | 4 ++- block/elevator.c | 15 ++++------ 5 files changed, 89 insertions(+), 15 deletions(-)
diff --git a/block/blk-mq-sched.c b/block/blk-mq-sched.c index 2d6d1ebdd8fb..e2ce4a28e6c9 100644 --- a/block/blk-mq-sched.c +++ b/block/blk-mq-sched.c @@ -427,6 +427,32 @@ void blk_mq_free_sched_tags(struct elevator_tags *et, kfree(et); }
+void blk_mq_free_sched_tags_batch(struct xarray *et_table, + struct blk_mq_tag_set *set) +{ + struct request_queue *q; + struct elevator_tags *et; + + lockdep_assert_held_write(&set->update_nr_hwq_lock); + + list_for_each_entry(q, &set->tag_list, tag_set_list) { + /* + * Accessing q->elevator without holding q->elevator_lock is + * safe because we're holding here set->update_nr_hwq_lock in + * the writer context. So, scheduler update/switch code (which + * acquires the same lock but in the reader context) can't run + * concurrently. + */ + if (q->elevator) { + et = xa_load(et_table, q->id); + if (unlikely(!et)) + WARN_ON_ONCE(1); + else + blk_mq_free_sched_tags(et, set); + } + } +} + struct elevator_tags *blk_mq_alloc_sched_tags(struct blk_mq_tag_set *set, unsigned int nr_hw_queues) { @@ -477,6 +503,45 @@ struct elevator_tags *blk_mq_alloc_sched_tags(struct blk_mq_tag_set *set, return NULL; }
+int blk_mq_alloc_sched_tags_batch(struct xarray *et_table, + struct blk_mq_tag_set *set, unsigned int nr_hw_queues) +{ + struct request_queue *q; + struct elevator_tags *et; + gfp_t gfp = GFP_NOIO | __GFP_ZERO | __GFP_NOWARN | __GFP_NORETRY; + + lockdep_assert_held_write(&set->update_nr_hwq_lock); + + list_for_each_entry(q, &set->tag_list, tag_set_list) { + /* + * Accessing q->elevator without holding q->elevator_lock is + * safe because we're holding here set->update_nr_hwq_lock in + * the writer context. So, scheduler update/switch code (which + * acquires the same lock but in the reader context) can't run + * concurrently. + */ + if (q->elevator) { + et = blk_mq_alloc_sched_tags(set, nr_hw_queues); + if (!et) + goto out_unwind; + if (xa_insert(et_table, q->id, et, gfp)) + goto out_free_tags; + } + } + return 0; +out_free_tags: + blk_mq_free_sched_tags(et, set); +out_unwind: + list_for_each_entry_continue_reverse(q, &set->tag_list, tag_set_list) { + if (q->elevator) { + et = xa_load(et_table, q->id); + if (et) + blk_mq_free_sched_tags(et, set); + } + } + return -ENOMEM; +} + /* caller must have a reference to @e, will grab another one if successful */ int blk_mq_init_sched(struct request_queue *q, struct elevator_type *e, struct elevator_tags *et) diff --git a/block/blk-mq-sched.h b/block/blk-mq-sched.h index 0cde00cd1c47..b554e1d55950 100644 --- a/block/blk-mq-sched.h +++ b/block/blk-mq-sched.h @@ -25,8 +25,12 @@ void blk_mq_sched_free_rqs(struct request_queue *q);
struct elevator_tags *blk_mq_alloc_sched_tags(struct blk_mq_tag_set *set, unsigned int nr_hw_queues); +int blk_mq_alloc_sched_tags_batch(struct xarray *et_table, + struct blk_mq_tag_set *set, unsigned int nr_hw_queues); void blk_mq_free_sched_tags(struct elevator_tags *et, struct blk_mq_tag_set *set); +void blk_mq_free_sched_tags_batch(struct xarray *et_table, + struct blk_mq_tag_set *set);
static inline void blk_mq_sched_restart(struct blk_mq_hw_ctx *hctx) { diff --git a/block/blk-mq.c b/block/blk-mq.c index 32d11305d51b..4cb2f5ca8656 100644 --- a/block/blk-mq.c +++ b/block/blk-mq.c @@ -4972,12 +4972,13 @@ int blk_mq_update_nr_requests(struct request_queue *q, unsigned int nr) * Switch back to the elevator type stored in the xarray. */ static void blk_mq_elv_switch_back(struct request_queue *q, - struct xarray *elv_tbl) + struct xarray *elv_tbl, struct xarray *et_tbl) { struct elevator_type *e = xa_load(elv_tbl, q->id); + struct elevator_tags *t = xa_load(et_tbl, q->id);
/* The elv_update_nr_hw_queues unfreezes the queue. */ - elv_update_nr_hw_queues(q, e); + elv_update_nr_hw_queues(q, e, t);
/* Drop the reference acquired in blk_mq_elv_switch_none. */ if (e) @@ -5029,7 +5030,7 @@ static void __blk_mq_update_nr_hw_queues(struct blk_mq_tag_set *set, int prev_nr_hw_queues = set->nr_hw_queues; unsigned int memflags; int i; - struct xarray elv_tbl; + struct xarray elv_tbl, et_tbl;
lockdep_assert_held(&set->tag_list_lock);
@@ -5042,6 +5043,10 @@ static void __blk_mq_update_nr_hw_queues(struct blk_mq_tag_set *set,
memflags = memalloc_noio_save();
+ xa_init(&et_tbl); + if (blk_mq_alloc_sched_tags_batch(&et_tbl, set, nr_hw_queues) < 0) + goto out_memalloc_restore; + xa_init(&elv_tbl);
list_for_each_entry(q, &set->tag_list, tag_set_list) { @@ -5085,7 +5090,7 @@ static void __blk_mq_update_nr_hw_queues(struct blk_mq_tag_set *set, switch_back: /* The blk_mq_elv_switch_back unfreezes queue for us. */ list_for_each_entry(q, &set->tag_list, tag_set_list) - blk_mq_elv_switch_back(q, &elv_tbl); + blk_mq_elv_switch_back(q, &elv_tbl, &et_tbl);
list_for_each_entry(q, &set->tag_list, tag_set_list) { blk_mq_sysfs_register_hctxs(q); @@ -5096,7 +5101,8 @@ static void __blk_mq_update_nr_hw_queues(struct blk_mq_tag_set *set, }
xa_destroy(&elv_tbl); - + xa_destroy(&et_tbl); +out_memalloc_restore: memalloc_noio_restore(memflags);
/* Free the excess tags when nr_hw_queues shrink. */ diff --git a/block/blk.h b/block/blk.h index 4746a7704856..5d9ca8c95193 100644 --- a/block/blk.h +++ b/block/blk.h @@ -12,6 +12,7 @@ #include "blk-crypto-internal.h"
struct elevator_type; +struct elevator_tags;
#define BLK_DEV_MAX_SECTORS (LLONG_MAX >> 9) #define BLK_MIN_SEGMENT_SIZE 4096 @@ -322,7 +323,8 @@ bool blk_bio_list_merge(struct request_queue *q, struct list_head *list,
bool blk_insert_flush(struct request *rq);
-void elv_update_nr_hw_queues(struct request_queue *q, struct elevator_type *e); +void elv_update_nr_hw_queues(struct request_queue *q, struct elevator_type *e, + struct elevator_tags *t); void elevator_set_default(struct request_queue *q); void elevator_set_none(struct request_queue *q);
diff --git a/block/elevator.c b/block/elevator.c index e9dc837b7b70..fe96c6f4753c 100644 --- a/block/elevator.c +++ b/block/elevator.c @@ -705,7 +705,8 @@ static int elevator_change(struct request_queue *q, struct elv_change_ctx *ctx) * The I/O scheduler depends on the number of hardware queues, this forces a * reattachment when nr_hw_queues changes. */ -void elv_update_nr_hw_queues(struct request_queue *q, struct elevator_type *e) +void elv_update_nr_hw_queues(struct request_queue *q, struct elevator_type *e, + struct elevator_tags *t) { struct blk_mq_tag_set *set = q->tag_set; struct elv_change_ctx ctx = {}; @@ -715,25 +716,21 @@ void elv_update_nr_hw_queues(struct request_queue *q, struct elevator_type *e)
if (e && !blk_queue_dying(q) && blk_queue_registered(q)) { ctx.name = e->elevator_name; - ctx.et = blk_mq_alloc_sched_tags(set, set->nr_hw_queues); - if (!ctx.et) { - WARN_ON_ONCE(1); - goto unfreeze; - } + ctx.et = t; + mutex_lock(&q->elevator_lock); /* force to reattach elevator after nr_hw_queue is updated */ ret = elevator_switch(q, &ctx); mutex_unlock(&q->elevator_lock); } -unfreeze: blk_mq_unfreeze_queue_nomemrestore(q); if (!ret) WARN_ON_ONCE(elevator_change_done(q, &ctx)); /* * Free sched tags if it's allocated but we couldn't switch elevator. */ - if (ctx.et && !ctx.new) - blk_mq_free_sched_tags(ctx.et, set); + if (t && !ctx.new) + blk_mq_free_sched_tags(t, set); }
/*
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ming Lei ming.lei@redhat.com
[ Upstream commit 2d82f3bd8910eb65e30bb2a3c9b945bfb3b6d661 ]
Commit 5989bfe6ac6b ("block: restore two stage elevator switch while running nr_hw_queue update") reintroduced a lockdep warning by calling blk_mq_freeze_queue_nomemsave() before switching the I/O scheduler.
The function blk_mq_elv_switch_none() calls elevator_change_done(). Running this while the queue is frozen causes a lockdep warning.
Fix this by reordering the operations: first, switch the I/O scheduler to 'none', and then freeze the queue. This ensures that elevator_change_done() is not called on an already frozen queue. And this way is safe because elevator_set_none() does freeze queue before switching to none.
Also we still have to rely on blk_mq_elv_switch_back() for switching back, and it has to cover unfrozen queue case.
Cc: Nilay Shroff nilay@linux.ibm.com Cc: Yu Kuai yukuai3@huawei.com Fixes: 5989bfe6ac6b ("block: restore two stage elevator switch while running nr_hw_queue update") Signed-off-by: Ming Lei ming.lei@redhat.com Reviewed-by: Yu Kuai yukuai3@huawei.com Reviewed-by: Nilay Shroff nilay@linux.ibm.com Link: https://lore.kernel.org/r/20250815131737.331692-1-ming.lei@redhat.com Signed-off-by: Jens Axboe axboe@kernel.dk Signed-off-by: Sasha Levin sashal@kernel.org --- block/blk-mq.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-)
diff --git a/block/blk-mq.c b/block/blk-mq.c index 4cb2f5ca8656..355db0abe44b 100644 --- a/block/blk-mq.c +++ b/block/blk-mq.c @@ -5031,6 +5031,7 @@ static void __blk_mq_update_nr_hw_queues(struct blk_mq_tag_set *set, unsigned int memflags; int i; struct xarray elv_tbl, et_tbl; + bool queues_frozen = false;
lockdep_assert_held(&set->tag_list_lock);
@@ -5054,9 +5055,6 @@ static void __blk_mq_update_nr_hw_queues(struct blk_mq_tag_set *set, blk_mq_sysfs_unregister_hctxs(q); }
- list_for_each_entry(q, &set->tag_list, tag_set_list) - blk_mq_freeze_queue_nomemsave(q); - /* * Switch IO scheduler to 'none', cleaning up the data associated * with the previous scheduler. We will switch back once we are done @@ -5066,6 +5064,9 @@ static void __blk_mq_update_nr_hw_queues(struct blk_mq_tag_set *set, if (blk_mq_elv_switch_none(q, &elv_tbl)) goto switch_back;
+ list_for_each_entry(q, &set->tag_list, tag_set_list) + blk_mq_freeze_queue_nomemsave(q); + queues_frozen = true; if (blk_mq_realloc_tag_set_tags(set, nr_hw_queues) < 0) goto switch_back;
@@ -5089,8 +5090,12 @@ static void __blk_mq_update_nr_hw_queues(struct blk_mq_tag_set *set, } switch_back: /* The blk_mq_elv_switch_back unfreezes queue for us. */ - list_for_each_entry(q, &set->tag_list, tag_set_list) + list_for_each_entry(q, &set->tag_list, tag_set_list) { + /* switch_back expects queue to be frozen */ + if (!queues_frozen) + blk_mq_freeze_queue_nomemsave(q); blk_mq_elv_switch_back(q, &elv_tbl, &et_tbl); + }
list_for_each_entry(q, &set->tag_list, tag_set_list) { blk_mq_sysfs_register_hctxs(q);
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Nilay Shroff nilay@linux.ibm.com
[ Upstream commit ade1beea1c27657712aa8f594226d461639382ff ]
rq_qos_add() increments the block_rq_qos static key when a QoS policy is attached. When a QoS policy is removed via rq_qos_del(), we must symmetrically decrement the static key. If this removal drops the last QoS policy from the queue (q->rq_qos becomes NULL), the static branch can be disabled and the jump label patched to a NOP, avoiding overhead on the hot path.
This change ensures rq_qos_add()/rq_qos_del() keep the block_rq_qos static key balanced and prevents leaving the branch permanently enabled after the last policy is removed.
Fixes: 033b667a823e ("block: blk-rq-qos: guard rq-qos helpers by static key") Signed-off-by: Nilay Shroff nilay@linux.ibm.com Reviewed-by: Ming Lei ming.lei@redhat.com Reviewed-by: Yu Kuai yukuai3@huawei.com Link: https://lore.kernel.org/r/20250814082612.500845-3-nilay@linux.ibm.com Signed-off-by: Jens Axboe axboe@kernel.dk Signed-off-by: Sasha Levin sashal@kernel.org --- block/blk-rq-qos.c | 1 + 1 file changed, 1 insertion(+)
diff --git a/block/blk-rq-qos.c b/block/blk-rq-qos.c index 848591fb3c57..b1e24bb85ad2 100644 --- a/block/blk-rq-qos.c +++ b/block/blk-rq-qos.c @@ -374,6 +374,7 @@ void rq_qos_del(struct rq_qos *rqos) for (cur = &q->rq_qos; *cur; cur = &(*cur)->next) { if (*cur == rqos) { *cur = rqos->next; + static_branch_dec(&block_rq_qos); break; } }
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Nilay Shroff nilay@linux.ibm.com
[ Upstream commit 275332877e2fa9d6efa7402b1e897f6c6ee695bb ]
If a bio has BIO_QOS_THROTTLED or BIO_QOS_MERGED set, it implicitly guarantees that q->rq_qos is present. Avoid re-checking q->rq_qos in this case and call __rq_qos_done_bio() directly as a minor optimization.
Suggested-by : Yu Kuai yukuai1@huaweicloud.com
Signed-off-by: Nilay Shroff nilay@linux.ibm.com Reviewed-by: Ming Lei ming.lei@redhat.com Reviewed-by: Yu Kuai yukuai3@huawei.com Link: https://lore.kernel.org/r/20250814082612.500845-2-nilay@linux.ibm.com Signed-off-by: Jens Axboe axboe@kernel.dk Stable-dep-of: 370ac285f23a ("block: avoid cpu_hotplug_lock depedency on freeze_lock") Signed-off-by: Sasha Levin sashal@kernel.org --- block/blk-rq-qos.h | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-)
diff --git a/block/blk-rq-qos.h b/block/blk-rq-qos.h index 39749f4066fb..28125fc49eff 100644 --- a/block/blk-rq-qos.h +++ b/block/blk-rq-qos.h @@ -142,8 +142,14 @@ static inline void rq_qos_done_bio(struct bio *bio) bio->bi_bdev && (bio_flagged(bio, BIO_QOS_THROTTLED) || bio_flagged(bio, BIO_QOS_MERGED))) { struct request_queue *q = bdev_get_queue(bio->bi_bdev); - if (q->rq_qos) - __rq_qos_done_bio(q->rq_qos, bio); + + /* + * If a bio has BIO_QOS_xxx set, it implicitly implies that + * q->rq_qos is present. So, we skip re-checking q->rq_qos + * here as an extra optimization and directly call + * __rq_qos_done_bio(). + */ + __rq_qos_done_bio(q->rq_qos, bio); } }
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Nilay Shroff nilay@linux.ibm.com
[ Upstream commit 370ac285f23aecae40600851fb4a1a9e75e50973 ]
A recent lockdep[1] splat observed while running blktest block/005 reveals a potential deadlock caused by the cpu_hotplug_lock dependency on ->freeze_lock. This dependency was introduced by commit 033b667a823e ("block: blk-rq-qos: guard rq-qos helpers by static key").
That change added a static key to avoid fetching q->rq_qos when neither blk-wbt nor blk-iolatency is configured. The static key dynamically patches kernel text to a NOP when disabled, eliminating overhead of fetching q->rq_qos in the I/O hot path. However, enabling a static key at runtime requires acquiring both cpu_hotplug_lock and jump_label_mutex. When this happens after the queue has already been frozen (i.e., while holding ->freeze_lock), it creates a locking dependency from cpu_hotplug_lock to ->freeze_lock, which leads to a potential deadlock reported by lockdep [1].
To resolve this, replace the static key mechanism with q->queue_flags: QUEUE_FLAG_QOS_ENABLED. This flag is evaluated in the fast path before accessing q->rq_qos. If the flag is set, we proceed to fetch q->rq_qos; otherwise, the access is skipped.
Since q->queue_flags is commonly accessed in IO hotpath and resides in the first cacheline of struct request_queue, checking it imposes minimal overhead while eliminating the deadlock risk.
This change avoids the lockdep splat without introducing performance regressions.
[1] https://lore.kernel.org/linux-block/4fdm37so3o4xricdgfosgmohn63aa7wj3ua4e5vp...
Reported-by: Shinichiro Kawasaki shinichiro.kawasaki@wdc.com Closes: https://lore.kernel.org/linux-block/4fdm37so3o4xricdgfosgmohn63aa7wj3ua4e5vp... Fixes: 033b667a823e ("block: blk-rq-qos: guard rq-qos helpers by static key") Tested-by: Shin'ichiro Kawasaki shinichiro.kawasaki@wdc.com Signed-off-by: Nilay Shroff nilay@linux.ibm.com Reviewed-by: Ming Lei ming.lei@redhat.com Reviewed-by: Yu Kuai yukuai3@huawei.com Link: https://lore.kernel.org/r/20250814082612.500845-4-nilay@linux.ibm.com Signed-off-by: Jens Axboe axboe@kernel.dk Signed-off-by: Sasha Levin sashal@kernel.org --- block/blk-mq-debugfs.c | 1 + block/blk-rq-qos.c | 9 ++++--- block/blk-rq-qos.h | 54 ++++++++++++++++++++++++------------------ include/linux/blkdev.h | 1 + 4 files changed, 37 insertions(+), 28 deletions(-)
diff --git a/block/blk-mq-debugfs.c b/block/blk-mq-debugfs.c index 29b3540dd180..bdcb27ab5606 100644 --- a/block/blk-mq-debugfs.c +++ b/block/blk-mq-debugfs.c @@ -95,6 +95,7 @@ static const char *const blk_queue_flag_name[] = { QUEUE_FLAG_NAME(SQ_SCHED), QUEUE_FLAG_NAME(DISABLE_WBT_DEF), QUEUE_FLAG_NAME(NO_ELV_SWITCH), + QUEUE_FLAG_NAME(QOS_ENABLED), }; #undef QUEUE_FLAG_NAME
diff --git a/block/blk-rq-qos.c b/block/blk-rq-qos.c index b1e24bb85ad2..654478dfbc20 100644 --- a/block/blk-rq-qos.c +++ b/block/blk-rq-qos.c @@ -2,8 +2,6 @@
#include "blk-rq-qos.h"
-__read_mostly DEFINE_STATIC_KEY_FALSE(block_rq_qos); - /* * Increment 'v', if 'v' is below 'below'. Returns true if we succeeded, * false if 'v' + 1 would be bigger than 'below'. @@ -319,8 +317,8 @@ void rq_qos_exit(struct request_queue *q) struct rq_qos *rqos = q->rq_qos; q->rq_qos = rqos->next; rqos->ops->exit(rqos); - static_branch_dec(&block_rq_qos); } + blk_queue_flag_clear(QUEUE_FLAG_QOS_ENABLED, q); mutex_unlock(&q->rq_qos_mutex); }
@@ -346,7 +344,7 @@ int rq_qos_add(struct rq_qos *rqos, struct gendisk *disk, enum rq_qos_id id, goto ebusy; rqos->next = q->rq_qos; q->rq_qos = rqos; - static_branch_inc(&block_rq_qos); + blk_queue_flag_set(QUEUE_FLAG_QOS_ENABLED, q);
blk_mq_unfreeze_queue(q, memflags);
@@ -374,10 +372,11 @@ void rq_qos_del(struct rq_qos *rqos) for (cur = &q->rq_qos; *cur; cur = &(*cur)->next) { if (*cur == rqos) { *cur = rqos->next; - static_branch_dec(&block_rq_qos); break; } } + if (!q->rq_qos) + blk_queue_flag_clear(QUEUE_FLAG_QOS_ENABLED, q); blk_mq_unfreeze_queue(q, memflags);
mutex_lock(&q->debugfs_mutex); diff --git a/block/blk-rq-qos.h b/block/blk-rq-qos.h index 28125fc49eff..1fe22000a379 100644 --- a/block/blk-rq-qos.h +++ b/block/blk-rq-qos.h @@ -12,7 +12,6 @@ #include "blk-mq-debugfs.h"
struct blk_mq_debugfs_attr; -extern struct static_key_false block_rq_qos;
enum rq_qos_id { RQ_QOS_WBT, @@ -113,49 +112,55 @@ void __rq_qos_queue_depth_changed(struct rq_qos *rqos);
static inline void rq_qos_cleanup(struct request_queue *q, struct bio *bio) { - if (static_branch_unlikely(&block_rq_qos) && q->rq_qos) + if (unlikely(test_bit(QUEUE_FLAG_QOS_ENABLED, &q->queue_flags)) && + q->rq_qos) __rq_qos_cleanup(q->rq_qos, bio); }
static inline void rq_qos_done(struct request_queue *q, struct request *rq) { - if (static_branch_unlikely(&block_rq_qos) && q->rq_qos && - !blk_rq_is_passthrough(rq)) + if (unlikely(test_bit(QUEUE_FLAG_QOS_ENABLED, &q->queue_flags)) && + q->rq_qos && !blk_rq_is_passthrough(rq)) __rq_qos_done(q->rq_qos, rq); }
static inline void rq_qos_issue(struct request_queue *q, struct request *rq) { - if (static_branch_unlikely(&block_rq_qos) && q->rq_qos) + if (unlikely(test_bit(QUEUE_FLAG_QOS_ENABLED, &q->queue_flags)) && + q->rq_qos) __rq_qos_issue(q->rq_qos, rq); }
static inline void rq_qos_requeue(struct request_queue *q, struct request *rq) { - if (static_branch_unlikely(&block_rq_qos) && q->rq_qos) + if (unlikely(test_bit(QUEUE_FLAG_QOS_ENABLED, &q->queue_flags)) && + q->rq_qos) __rq_qos_requeue(q->rq_qos, rq); }
static inline void rq_qos_done_bio(struct bio *bio) { - if (static_branch_unlikely(&block_rq_qos) && - bio->bi_bdev && (bio_flagged(bio, BIO_QOS_THROTTLED) || - bio_flagged(bio, BIO_QOS_MERGED))) { - struct request_queue *q = bdev_get_queue(bio->bi_bdev); - - /* - * If a bio has BIO_QOS_xxx set, it implicitly implies that - * q->rq_qos is present. So, we skip re-checking q->rq_qos - * here as an extra optimization and directly call - * __rq_qos_done_bio(). - */ - __rq_qos_done_bio(q->rq_qos, bio); - } + struct request_queue *q; + + if (!bio->bi_bdev || (!bio_flagged(bio, BIO_QOS_THROTTLED) && + !bio_flagged(bio, BIO_QOS_MERGED))) + return; + + q = bdev_get_queue(bio->bi_bdev); + + /* + * If a bio has BIO_QOS_xxx set, it implicitly implies that + * q->rq_qos is present. So, we skip re-checking q->rq_qos + * here as an extra optimization and directly call + * __rq_qos_done_bio(). + */ + __rq_qos_done_bio(q->rq_qos, bio); }
static inline void rq_qos_throttle(struct request_queue *q, struct bio *bio) { - if (static_branch_unlikely(&block_rq_qos) && q->rq_qos) { + if (unlikely(test_bit(QUEUE_FLAG_QOS_ENABLED, &q->queue_flags)) && + q->rq_qos) { bio_set_flag(bio, BIO_QOS_THROTTLED); __rq_qos_throttle(q->rq_qos, bio); } @@ -164,14 +169,16 @@ static inline void rq_qos_throttle(struct request_queue *q, struct bio *bio) static inline void rq_qos_track(struct request_queue *q, struct request *rq, struct bio *bio) { - if (static_branch_unlikely(&block_rq_qos) && q->rq_qos) + if (unlikely(test_bit(QUEUE_FLAG_QOS_ENABLED, &q->queue_flags)) && + q->rq_qos) __rq_qos_track(q->rq_qos, rq, bio); }
static inline void rq_qos_merge(struct request_queue *q, struct request *rq, struct bio *bio) { - if (static_branch_unlikely(&block_rq_qos) && q->rq_qos) { + if (unlikely(test_bit(QUEUE_FLAG_QOS_ENABLED, &q->queue_flags)) && + q->rq_qos) { bio_set_flag(bio, BIO_QOS_MERGED); __rq_qos_merge(q->rq_qos, rq, bio); } @@ -179,7 +186,8 @@ static inline void rq_qos_merge(struct request_queue *q, struct request *rq,
static inline void rq_qos_queue_depth_changed(struct request_queue *q) { - if (static_branch_unlikely(&block_rq_qos) && q->rq_qos) + if (unlikely(test_bit(QUEUE_FLAG_QOS_ENABLED, &q->queue_flags)) && + q->rq_qos) __rq_qos_queue_depth_changed(q->rq_qos); }
diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h index 620345ce3aaa..3921188c9e13 100644 --- a/include/linux/blkdev.h +++ b/include/linux/blkdev.h @@ -652,6 +652,7 @@ enum { QUEUE_FLAG_SQ_SCHED, /* single queue style io dispatch */ QUEUE_FLAG_DISABLE_WBT_DEF, /* for sched to disable/enable wbt */ QUEUE_FLAG_NO_ELV_SWITCH, /* can't switch elevator any more */ + QUEUE_FLAG_QOS_ENABLED, /* qos is enabled */ QUEUE_FLAG_MAX };
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Hariprasad Kelam hkelam@marvell.com
[ Upstream commit 8c5d95988c34f0aeba1f34cd5e4ba69494c90c5f ]
Octeontx2/CN10K silicon supports generating a 256-bit key per packet. The specific fields to be extracted from a packet for key generation are configurable via a Key Extraction (MKEX) Profile.
The AF driver scans the configured extraction profile to ensure that fields from upper layers do not overwrite fields from lower layers in the key.
Example Packet Field Layout: LA: DMAC + SMAC LB: VLAN LC: IPv4/IPv6 LD: TCP/UDP
Valid MKEX Profile Configuration:
LA -> DMAC -> key_offset[0-5] LC -> SIP -> key_offset[20-23] LD -> SPORT -> key_offset[30-31]
Invalid MKEX profile configuration:
LA -> DMAC -> key_offset[0-5] LC -> SIP -> key_offset[20-23] LD -> SPORT -> key_offset[2-3] // Overlaps with DMAC field
In another scenario, if the MKEX profile is configured to extract the SPI field from both AH and ESP headers at the same key offset, the driver rejecting this configuration. In a regular traffic, ipsec packet will be having either AH(LD) or ESP (LE). This patch relaxes the check for the same.
Fixes: 12aa0a3b93f3 ("octeontx2-af: Harden rule validation.") Signed-off-by: Hariprasad Kelam hkelam@marvell.com Link: https://patch.msgid.link/20250820063919.1463518-1-hkelam@marvell.com Signed-off-by: Jakub Kicinski kuba@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/net/ethernet/marvell/octeontx2/af/rvu_npc_fs.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc_fs.c b/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc_fs.c index 1b765045aa63..b56395ac5a74 100644 --- a/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc_fs.c +++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc_fs.c @@ -606,8 +606,8 @@ static void npc_set_features(struct rvu *rvu, int blkaddr, u8 intf) if (!npc_check_field(rvu, blkaddr, NPC_LB, intf)) *features &= ~BIT_ULL(NPC_OUTER_VID);
- /* Set SPI flag only if AH/ESP and IPSEC_SPI are in the key */ - if (npc_check_field(rvu, blkaddr, NPC_IPSEC_SPI, intf) && + /* Allow extracting SPI field from AH and ESP headers at same offset */ + if (npc_is_field_present(rvu, NPC_IPSEC_SPI, intf) && (*features & (BIT_ULL(NPC_IPPROTO_ESP) | BIT_ULL(NPC_IPPROTO_AH)))) *features |= BIT_ULL(NPC_IPSEC_SPI);
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Daniel Jurgens danielj@nvidia.com
[ Upstream commit bc17455bc843b2f4b206e0bb8139013eb3d3c08b ]
Adjust the vport number by the base ECVF vport number so the port attributes start at 0. Previously the port attributes would start 1 after the maximum number of host VFs.
Fixes: dc13180824b7 ("net/mlx5: Enable devlink port for embedded cpu VF vports") Signed-off-by: Daniel Jurgens danielj@nvidia.com Reviewed-by: Parav Pandit parav@nvidia.com Reviewed-by: Saeed Mahameed saeedm@nvidia.com Signed-off-by: Tariq Toukan tariqt@nvidia.com Signed-off-by: Mark Bloch mbloch@nvidia.com Link: https://patch.msgid.link/20250820133209.389065-2-mbloch@nvidia.com Signed-off-by: Jakub Kicinski kuba@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/net/ethernet/mellanox/mlx5/core/esw/devlink_port.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/esw/devlink_port.c b/drivers/net/ethernet/mellanox/mlx5/core/esw/devlink_port.c index b7102e14d23d..c33accadae0f 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/esw/devlink_port.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/esw/devlink_port.c @@ -47,10 +47,12 @@ static void mlx5_esw_offloads_pf_vf_devlink_port_attrs_set(struct mlx5_eswitch * devlink_port_attrs_pci_vf_set(dl_port, controller_num, pfnum, vport_num - 1, external); } else if (mlx5_core_is_ec_vf_vport(esw->dev, vport_num)) { + u16 base_vport = mlx5_core_ec_vf_vport_base(dev); + memcpy(dl_port->attrs.switch_id.id, ppid.id, ppid.id_len); dl_port->attrs.switch_id.id_len = ppid.id_len; devlink_port_attrs_pci_vf_set(dl_port, 0, pfnum, - vport_num - 1, false); + vport_num - base_vport, false); } }
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Oren Sidi osidi@nvidia.com
[ Upstream commit 6f09ee0b583cad4f2b6a82842c26235bee3d5c2e ]
Extend structure layouts and defines buf_ownership. buf_ownership indicates whether the buffer is managed by SW or FW.
Signed-off-by: Oren Sidi osidi@nvidia.com Reviewed-by: Alex Lazar alazar@nvidia.com Signed-off-by: Tariq Toukan tariqt@nvidia.com Link: https://patch.msgid.link/1752734895-257735-3-git-send-email-tariqt@nvidia.co... Signed-off-by: Leon Romanovsky leon@kernel.org Stable-dep-of: 451d2849ea66 ("net/mlx5e: Query FW for buffer ownership") Signed-off-by: Sasha Levin sashal@kernel.org --- include/linux/mlx5/mlx5_ifc.h | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-)
diff --git a/include/linux/mlx5/mlx5_ifc.h b/include/linux/mlx5/mlx5_ifc.h index 2c09df4ee574..83288df7bb45 100644 --- a/include/linux/mlx5/mlx5_ifc.h +++ b/include/linux/mlx5/mlx5_ifc.h @@ -10460,8 +10460,16 @@ struct mlx5_ifc_pifr_reg_bits { u8 port_filter_update_en[8][0x20]; };
+enum { + MLX5_BUF_OWNERSHIP_UNKNOWN = 0x0, + MLX5_BUF_OWNERSHIP_FW_OWNED = 0x1, + MLX5_BUF_OWNERSHIP_SW_OWNED = 0x2, +}; + struct mlx5_ifc_pfcc_reg_bits { - u8 reserved_at_0[0x8]; + u8 reserved_at_0[0x4]; + u8 buf_ownership[0x2]; + u8 reserved_at_6[0x2]; u8 local_port[0x8]; u8 reserved_at_10[0xb]; u8 ppan_mask_n[0x1]; @@ -10597,7 +10605,9 @@ struct mlx5_ifc_pcam_enhanced_features_bits { u8 fec_200G_per_lane_in_pplm[0x1]; u8 reserved_at_1e[0x2a]; u8 fec_100G_per_lane_in_pplm[0x1]; - u8 reserved_at_49[0x1f]; + u8 reserved_at_49[0xa]; + u8 buffer_ownership[0x1]; + u8 resereved_at_54[0x14]; u8 fec_50G_per_lane_in_pplm[0x1]; u8 reserved_at_69[0x4]; u8 rx_icrc_encapsulated_counter[0x1];
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Alexei Lazar alazar@nvidia.com
[ Upstream commit 451d2849ea66659040b59ae3cb7e50cc97404733 ]
The SW currently saves local buffer ownership when setting the buffer. This means that the SW assumes it has ownership of the buffer after the command is set.
If setting the buffer fails and we remain in FW ownership, the local buffer ownership state incorrectly remains as SW-owned. This leads to incorrect behavior in subsequent PFC commands, causing failures.
Instead of saving local buffer ownership in SW, query the FW for buffer ownership when setting the buffer. This ensures that the buffer ownership state is accurately reflected, avoiding the issues caused by incorrect ownership states.
Fixes: ecdf2dadee8e ("net/mlx5e: Receive buffer support for DCBX") Signed-off-by: Alexei Lazar alazar@nvidia.com Reviewed-by: Shahar Shitrit shshitrit@nvidia.com Reviewed-by: Dragos Tatulea dtatulea@nvidia.com Signed-off-by: Mark Bloch mbloch@nvidia.com Link: https://patch.msgid.link/20250820133209.389065-8-mbloch@nvidia.com Signed-off-by: Jakub Kicinski kuba@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- .../ethernet/mellanox/mlx5/core/en/dcbnl.h | 1 - .../ethernet/mellanox/mlx5/core/en_dcbnl.c | 12 ++++++++--- .../ethernet/mellanox/mlx5/core/mlx5_core.h | 2 ++ .../net/ethernet/mellanox/mlx5/core/port.c | 20 +++++++++++++++++++ 4 files changed, 31 insertions(+), 4 deletions(-)
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/dcbnl.h b/drivers/net/ethernet/mellanox/mlx5/core/en/dcbnl.h index b59aee75de94..2c98a5299df3 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en/dcbnl.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/en/dcbnl.h @@ -26,7 +26,6 @@ struct mlx5e_dcbx { u8 cap;
/* Buffer configuration */ - bool manual_buffer; u32 cable_len; u32 xoff; u16 port_buff_cell_sz; diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c b/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c index 5fe016e477b3..d166c0d5189e 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c @@ -362,6 +362,7 @@ static int mlx5e_dcbnl_ieee_getpfc(struct net_device *dev, static int mlx5e_dcbnl_ieee_setpfc(struct net_device *dev, struct ieee_pfc *pfc) { + u8 buffer_ownership = MLX5_BUF_OWNERSHIP_UNKNOWN; struct mlx5e_priv *priv = netdev_priv(dev); struct mlx5_core_dev *mdev = priv->mdev; u32 old_cable_len = priv->dcbx.cable_len; @@ -389,7 +390,14 @@ static int mlx5e_dcbnl_ieee_setpfc(struct net_device *dev,
if (MLX5_BUFFER_SUPPORTED(mdev)) { pfc_new.pfc_en = (changed & MLX5E_PORT_BUFFER_PFC) ? pfc->pfc_en : curr_pfc_en; - if (priv->dcbx.manual_buffer) + ret = mlx5_query_port_buffer_ownership(mdev, + &buffer_ownership); + if (ret) + netdev_err(dev, + "%s, Failed to get buffer ownership: %d\n", + __func__, ret); + + if (buffer_ownership == MLX5_BUF_OWNERSHIP_SW_OWNED) ret = mlx5e_port_manual_buffer_config(priv, changed, dev->mtu, &pfc_new, NULL, NULL); @@ -982,7 +990,6 @@ static int mlx5e_dcbnl_setbuffer(struct net_device *dev, if (!changed) return 0;
- priv->dcbx.manual_buffer = true; err = mlx5e_port_manual_buffer_config(priv, changed, dev->mtu, NULL, buffer_size, prio2buffer); return err; @@ -1252,7 +1259,6 @@ void mlx5e_dcbnl_initialize(struct mlx5e_priv *priv) priv->dcbx.cap |= DCB_CAP_DCBX_HOST;
priv->dcbx.port_buff_cell_sz = mlx5e_query_port_buffers_cell_size(priv); - priv->dcbx.manual_buffer = false; priv->dcbx.cable_len = MLX5E_DEFAULT_CABLE_LEN;
mlx5e_ets_init(priv); diff --git a/drivers/net/ethernet/mellanox/mlx5/core/mlx5_core.h b/drivers/net/ethernet/mellanox/mlx5/core/mlx5_core.h index 2e02bdea8361..c2f6d205ddb1 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/mlx5_core.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/mlx5_core.h @@ -358,6 +358,8 @@ int mlx5_query_port_dcbx_param(struct mlx5_core_dev *mdev, u32 *out); int mlx5_set_port_dcbx_param(struct mlx5_core_dev *mdev, u32 *in); int mlx5_set_trust_state(struct mlx5_core_dev *mdev, u8 trust_state); int mlx5_query_trust_state(struct mlx5_core_dev *mdev, u8 *trust_state); +int mlx5_query_port_buffer_ownership(struct mlx5_core_dev *mdev, + u8 *buffer_ownership); int mlx5_set_dscp2prio(struct mlx5_core_dev *mdev, u8 dscp, u8 prio); int mlx5_query_dscp2prio(struct mlx5_core_dev *mdev, u8 *dscp2prio);
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/port.c b/drivers/net/ethernet/mellanox/mlx5/core/port.c index 549f1066d2a5..2d7adf7444ba 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/port.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/port.c @@ -968,6 +968,26 @@ int mlx5_query_trust_state(struct mlx5_core_dev *mdev, u8 *trust_state) return err; }
+int mlx5_query_port_buffer_ownership(struct mlx5_core_dev *mdev, + u8 *buffer_ownership) +{ + u32 out[MLX5_ST_SZ_DW(pfcc_reg)] = {}; + int err; + + if (!MLX5_CAP_PCAM_FEATURE(mdev, buffer_ownership)) { + *buffer_ownership = MLX5_BUF_OWNERSHIP_UNKNOWN; + return 0; + } + + err = mlx5_query_pfcc_reg(mdev, out, sizeof(out)); + if (err) + return err; + + *buffer_ownership = MLX5_GET(pfcc_reg, out, buf_ownership); + + return 0; +} + int mlx5_set_dscp2prio(struct mlx5_core_dev *mdev, u8 dscp, u8 prio) { int sz = MLX5_ST_SZ_BYTES(qpdpm_reg);
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Armen Ratner armeng@nvidia.com
[ Upstream commit 8b0587a885fdb34fd6090a3f8625cb7ac1444826 ]
When port buffer headroom changes, port_update_shared_buffer() recalculates the shared buffer size and splits it in a 3:1 ratio (lossy:lossless) - Currently, the calculation is: lossless = shared / 4; lossy = (shared / 4) * 3;
Meaning, the calculation dropped the remainder of shared % 4 due to integer division, unintentionally reducing the total shared buffer by up to three cells on each update. Over time, this could shrink the buffer below usable size.
Fix it by changing the calculation to: lossless = shared / 4; lossy = shared - lossless;
This retains all buffer cells while still approximating the intended 3:1 split, preventing capacity loss over time.
While at it, perform headroom calculations in units of cells rather than in bytes for more accurate calculations avoiding extra divisions.
Fixes: a440030d8946 ("net/mlx5e: Update shared buffer along with device buffer changes") Signed-off-by: Armen Ratner armeng@nvidia.com Signed-off-by: Maher Sanalla msanalla@nvidia.com Reviewed-by: Tariq Toukan tariqt@nvidia.com Signed-off-by: Alexei Lazar alazar@nvidia.com Signed-off-by: Mark Bloch mbloch@nvidia.com Reviewed-by: Przemek Kitszel przemyslaw.kitszel@intel.com Link: https://patch.msgid.link/20250820133209.389065-9-mbloch@nvidia.com Signed-off-by: Jakub Kicinski kuba@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- .../mellanox/mlx5/core/en/port_buffer.c | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-)
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/port_buffer.c b/drivers/net/ethernet/mellanox/mlx5/core/en/port_buffer.c index 5ae787656a7c..3efa8bf1d14e 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en/port_buffer.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en/port_buffer.c @@ -272,8 +272,8 @@ static int port_update_shared_buffer(struct mlx5_core_dev *mdev, /* Total shared buffer size is split in a ratio of 3:1 between * lossy and lossless pools respectively. */ - lossy_epool_size = (shared_buffer_size / 4) * 3; lossless_ipool_size = shared_buffer_size / 4; + lossy_epool_size = shared_buffer_size - lossless_ipool_size;
mlx5e_port_set_sbpr(mdev, 0, MLX5_EGRESS_DIR, MLX5_LOSSY_POOL, 0, lossy_epool_size); @@ -288,14 +288,12 @@ static int port_set_buffer(struct mlx5e_priv *priv, u16 port_buff_cell_sz = priv->dcbx.port_buff_cell_sz; struct mlx5_core_dev *mdev = priv->mdev; int sz = MLX5_ST_SZ_BYTES(pbmc_reg); - u32 new_headroom_size = 0; - u32 current_headroom_size; + u32 current_headroom_cells = 0; + u32 new_headroom_cells = 0; void *in; int err; int i;
- current_headroom_size = port_buffer->headroom_size; - in = kzalloc(sz, GFP_KERNEL); if (!in) return -ENOMEM; @@ -306,12 +304,14 @@ static int port_set_buffer(struct mlx5e_priv *priv,
for (i = 0; i < MLX5E_MAX_NETWORK_BUFFER; i++) { void *buffer = MLX5_ADDR_OF(pbmc_reg, in, buffer[i]); + current_headroom_cells += MLX5_GET(bufferx_reg, buffer, size); + u64 size = port_buffer->buffer[i].size; u64 xoff = port_buffer->buffer[i].xoff; u64 xon = port_buffer->buffer[i].xon;
- new_headroom_size += size; do_div(size, port_buff_cell_sz); + new_headroom_cells += size; do_div(xoff, port_buff_cell_sz); do_div(xon, port_buff_cell_sz); MLX5_SET(bufferx_reg, buffer, size, size); @@ -320,10 +320,8 @@ static int port_set_buffer(struct mlx5e_priv *priv, MLX5_SET(bufferx_reg, buffer, xon_threshold, xon); }
- new_headroom_size /= port_buff_cell_sz; - current_headroom_size /= port_buff_cell_sz; - err = port_update_shared_buffer(priv->mdev, current_headroom_size, - new_headroom_size); + err = port_update_shared_buffer(priv->mdev, current_headroom_cells, + new_headroom_cells); if (err) goto out;
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Takashi Iwai tiwai@suse.de
[ Upstream commit 8410fe81093ff231e964891e215b624dabb734b0 ]
The entry of the validators table for UAC3 feature unit is defined with a wrong sub-type UAC_FEATURE (= 0x06) while it should have been UAC3_FEATURE (= 0x07). This patch corrects the entry value.
Fixes: 57f8770620e9 ("ALSA: usb-audio: More validations of descriptor units") Link: https://patch.msgid.link/20250821150835.8894-1-tiwai@suse.de Signed-off-by: Takashi Iwai tiwai@suse.de Signed-off-by: Sasha Levin sashal@kernel.org --- sound/usb/validate.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/sound/usb/validate.c b/sound/usb/validate.c index 4f4e8e87a14c..a0d55b77c994 100644 --- a/sound/usb/validate.c +++ b/sound/usb/validate.c @@ -285,7 +285,7 @@ static const struct usb_desc_validator audio_validators[] = { /* UAC_VERSION_3, UAC3_EXTENDED_TERMINAL: not implemented yet */ FUNC(UAC_VERSION_3, UAC3_MIXER_UNIT, validate_mixer_unit), FUNC(UAC_VERSION_3, UAC3_SELECTOR_UNIT, validate_selector_unit), - FUNC(UAC_VERSION_3, UAC_FEATURE_UNIT, validate_uac3_feature_unit), + FUNC(UAC_VERSION_3, UAC3_FEATURE_UNIT, validate_uac3_feature_unit), /* UAC_VERSION_3, UAC3_EFFECT_UNIT: not implemented yet */ FUNC(UAC_VERSION_3, UAC3_PROCESSING_UNIT, validate_processing_unit), FUNC(UAC_VERSION_3, UAC3_EXTENSION_UNIT, validate_processing_unit),
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Peter Oberparleiter oberpar@linux.ibm.com
[ Upstream commit fec7bdfe7f8694a0c39e6c3ec026ff61ca1058b9 ]
Currently, hypfs registers ioctl callbacks for all debugfs files, despite only one file requiring them. This leads to unintended exposure of unused interfaces to user space and can trigger side effects such as restricted access when kernel lockdown is enabled.
Restrict ioctl registration to only those files that implement ioctl functionality to avoid interface clutter and unnecessary access restrictions.
Tested-by: Mete Durlu meted@linux.ibm.com Reviewed-by: Vasily Gorbik gor@linux.ibm.com Fixes: 5496197f9b08 ("debugfs: Restrict debugfs when the kernel is locked down") Signed-off-by: Peter Oberparleiter oberpar@linux.ibm.com Signed-off-by: Alexander Gordeev agordeev@linux.ibm.com Signed-off-by: Sasha Levin sashal@kernel.org --- arch/s390/hypfs/hypfs_dbfs.c | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-)
diff --git a/arch/s390/hypfs/hypfs_dbfs.c b/arch/s390/hypfs/hypfs_dbfs.c index 5d9effb0867c..e74eb8f9b23a 100644 --- a/arch/s390/hypfs/hypfs_dbfs.c +++ b/arch/s390/hypfs/hypfs_dbfs.c @@ -66,23 +66,27 @@ static long dbfs_ioctl(struct file *file, unsigned int cmd, unsigned long arg) long rc;
mutex_lock(&df->lock); - if (df->unlocked_ioctl) - rc = df->unlocked_ioctl(file, cmd, arg); - else - rc = -ENOTTY; + rc = df->unlocked_ioctl(file, cmd, arg); mutex_unlock(&df->lock); return rc; }
-static const struct file_operations dbfs_ops = { +static const struct file_operations dbfs_ops_ioctl = { .read = dbfs_read, .unlocked_ioctl = dbfs_ioctl, };
+static const struct file_operations dbfs_ops = { + .read = dbfs_read, +}; + void hypfs_dbfs_create_file(struct hypfs_dbfs_file *df) { - df->dentry = debugfs_create_file(df->name, 0400, dbfs_dir, df, - &dbfs_ops); + const struct file_operations *fops = &dbfs_ops; + + if (df->unlocked_ioctl) + fops = &dbfs_ops_ioctl; + df->dentry = debugfs_create_file(df->name, 0400, dbfs_dir, df, fops); mutex_init(&df->lock); }
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Peter Oberparleiter oberpar@linux.ibm.com
[ Upstream commit 3868f910440c47cd5d158776be4ba4e2186beda7 ]
When kernel lockdown is active, debugfs_locked_down() blocks access to hypfs files that register ioctl callbacks, even if the ioctl interface is not required for a function. This unnecessarily breaks userspace tools that only rely on read operations.
Resolve this by registering a minimal set of file operations during lockdown, avoiding ioctl registration and preserving access for affected tooling.
Note that this change restores hypfs functionality when lockdown is active from early boot (e.g. via lockdown=integrity kernel parameter), but does not apply to scenarios where lockdown is enabled dynamically while Linux is running.
Tested-by: Mete Durlu meted@linux.ibm.com Reviewed-by: Vasily Gorbik gor@linux.ibm.com Fixes: 5496197f9b08 ("debugfs: Restrict debugfs when the kernel is locked down") Signed-off-by: Peter Oberparleiter oberpar@linux.ibm.com Signed-off-by: Alexander Gordeev agordeev@linux.ibm.com Signed-off-by: Sasha Levin sashal@kernel.org --- arch/s390/hypfs/hypfs_dbfs.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/arch/s390/hypfs/hypfs_dbfs.c b/arch/s390/hypfs/hypfs_dbfs.c index e74eb8f9b23a..41a0d2066fa0 100644 --- a/arch/s390/hypfs/hypfs_dbfs.c +++ b/arch/s390/hypfs/hypfs_dbfs.c @@ -6,6 +6,7 @@ * Author(s): Michael Holzheu holzheu@linux.vnet.ibm.com */
+#include <linux/security.h> #include <linux/slab.h> #include "hypfs.h"
@@ -84,7 +85,7 @@ void hypfs_dbfs_create_file(struct hypfs_dbfs_file *df) { const struct file_operations *fops = &dbfs_ops;
- if (df->unlocked_ioctl) + if (df->unlocked_ioctl && !security_locked_down(LOCKDOWN_DEBUGFS)) fops = &dbfs_ops_ioctl; df->dentry = debugfs_create_file(df->name, 0400, dbfs_dir, df, fops); mutex_init(&df->lock);
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Florian Westphal fw@strlen.de
[ Upstream commit 91a79b792204313153e1bdbbe5acbfc28903b3a5 ]
recent patches to add a WARN() when replacing skb dst entry found an old bug:
WARNING: include/linux/skbuff.h:1165 skb_dst_check_unset include/linux/skbuff.h:1164 [inline] WARNING: include/linux/skbuff.h:1165 skb_dst_set include/linux/skbuff.h:1210 [inline] WARNING: include/linux/skbuff.h:1165 nf_reject_fill_skb_dst+0x2a4/0x330 net/ipv4/netfilter/nf_reject_ipv4.c:234 [..] Call Trace: nf_send_unreach+0x17b/0x6e0 net/ipv4/netfilter/nf_reject_ipv4.c:325 nft_reject_inet_eval+0x4bc/0x690 net/netfilter/nft_reject_inet.c:27 expr_call_ops_eval net/netfilter/nf_tables_core.c:237 [inline] ..
This is because blamed commit forgot about loopback packets. Such packets already have a dst_entry attached, even at PRE_ROUTING stage.
Instead of checking hook just check if the skb already has a route attached to it.
Fixes: f53b9b0bdc59 ("netfilter: introduce support for reject at prerouting stage") Signed-off-by: Florian Westphal fw@strlen.de Link: https://patch.msgid.link/20250820123707.10671-1-fw@strlen.de Signed-off-by: Jakub Kicinski kuba@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- net/ipv4/netfilter/nf_reject_ipv4.c | 6 ++---- net/ipv6/netfilter/nf_reject_ipv6.c | 5 ++--- 2 files changed, 4 insertions(+), 7 deletions(-)
diff --git a/net/ipv4/netfilter/nf_reject_ipv4.c b/net/ipv4/netfilter/nf_reject_ipv4.c index 87fd945a0d27..0d3cb2ba6fc8 100644 --- a/net/ipv4/netfilter/nf_reject_ipv4.c +++ b/net/ipv4/netfilter/nf_reject_ipv4.c @@ -247,8 +247,7 @@ void nf_send_reset(struct net *net, struct sock *sk, struct sk_buff *oldskb, if (!oth) return;
- if ((hook == NF_INET_PRE_ROUTING || hook == NF_INET_INGRESS) && - nf_reject_fill_skb_dst(oldskb) < 0) + if (!skb_dst(oldskb) && nf_reject_fill_skb_dst(oldskb) < 0) return;
if (skb_rtable(oldskb)->rt_flags & (RTCF_BROADCAST | RTCF_MULTICAST)) @@ -321,8 +320,7 @@ void nf_send_unreach(struct sk_buff *skb_in, int code, int hook) if (iph->frag_off & htons(IP_OFFSET)) return;
- if ((hook == NF_INET_PRE_ROUTING || hook == NF_INET_INGRESS) && - nf_reject_fill_skb_dst(skb_in) < 0) + if (!skb_dst(skb_in) && nf_reject_fill_skb_dst(skb_in) < 0) return;
if (skb_csum_unnecessary(skb_in) || diff --git a/net/ipv6/netfilter/nf_reject_ipv6.c b/net/ipv6/netfilter/nf_reject_ipv6.c index 9ae2b2725bf9..c3d64c4b69d7 100644 --- a/net/ipv6/netfilter/nf_reject_ipv6.c +++ b/net/ipv6/netfilter/nf_reject_ipv6.c @@ -293,7 +293,7 @@ void nf_send_reset6(struct net *net, struct sock *sk, struct sk_buff *oldskb, fl6.fl6_sport = otcph->dest; fl6.fl6_dport = otcph->source;
- if (hook == NF_INET_PRE_ROUTING || hook == NF_INET_INGRESS) { + if (!skb_dst(oldskb)) { nf_ip6_route(net, &dst, flowi6_to_flowi(&fl6), false); if (!dst) return; @@ -397,8 +397,7 @@ void nf_send_unreach6(struct net *net, struct sk_buff *skb_in, if (hooknum == NF_INET_LOCAL_OUT && skb_in->dev == NULL) skb_in->dev = net->loopback_dev;
- if ((hooknum == NF_INET_PRE_ROUTING || hooknum == NF_INET_INGRESS) && - nf_reject6_fill_skb_dst(skb_in) < 0) + if (!skb_dst(skb_in) && nf_reject6_fill_skb_dst(skb_in) < 0) return;
icmpv6_send(skb_in, ICMPV6_DEST_UNREACH, code, 0);
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Piotr Piórkowski piotr.piorkowski@intel.com
[ Upstream commit 8a30114073639fd97f2c7390abbc34fb8711327a ]
Currently, ASID assignment for user VMs and page-table BO accounting for client memory tracking are performed in xe_vm_create_ioctl. To consolidate VM object initialization, move this logic to xe_vm_create.
v2: - removed unnecessary duplicate BO tracking code - using the local variable xef to verify whether the VM is being created by userspace
Fixes: 658a1c8e0a66 ("drm/xe: Assign ioctl xe file handler to vm in xe_vm_create") Suggested-by: Matthew Auld matthew.auld@intel.com Signed-off-by: Piotr Piórkowski piotr.piorkowski@intel.com Reviewed-by: Matthew Auld matthew.auld@intel.com Link: https://lore.kernel.org/r/20250811104358.2064150-3-piotr.piorkowski@intel.co... Signed-off-by: Michał Winiarski michal.winiarski@intel.com (cherry picked from commit 30e0c3f43a414616e0b6ca76cf7f7b2cd387e1d4) Signed-off-by: Rodrigo Vivi rodrigo.vivi@intel.com [Rodrigo: Added fixes tag] Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/gpu/drm/xe/xe_vm.c | 34 +++++++++++++++------------------- 1 file changed, 15 insertions(+), 19 deletions(-)
diff --git a/drivers/gpu/drm/xe/xe_vm.c b/drivers/gpu/drm/xe/xe_vm.c index 7251f23b919c..3135de124c18 100644 --- a/drivers/gpu/drm/xe/xe_vm.c +++ b/drivers/gpu/drm/xe/xe_vm.c @@ -1767,6 +1767,20 @@ struct xe_vm *xe_vm_create(struct xe_device *xe, u32 flags, struct xe_file *xef) if (number_tiles > 1) vm->composite_fence_ctx = dma_fence_context_alloc(1);
+ if (xef && xe->info.has_asid) { + u32 asid; + + down_write(&xe->usm.lock); + err = xa_alloc_cyclic(&xe->usm.asid_to_vm, &asid, vm, + XA_LIMIT(1, XE_MAX_ASID - 1), + &xe->usm.next_asid, GFP_KERNEL); + up_write(&xe->usm.lock); + if (err < 0) + goto err_unlock_close; + + vm->usm.asid = asid; + } + trace_xe_vm_create(vm);
return vm; @@ -2034,9 +2048,8 @@ int xe_vm_create_ioctl(struct drm_device *dev, void *data, struct xe_device *xe = to_xe_device(dev); struct xe_file *xef = to_xe_file(file); struct drm_xe_vm_create *args = data; - struct xe_tile *tile; struct xe_vm *vm; - u32 id, asid; + u32 id; int err; u32 flags = 0;
@@ -2076,23 +2089,6 @@ int xe_vm_create_ioctl(struct drm_device *dev, void *data, if (IS_ERR(vm)) return PTR_ERR(vm);
- if (xe->info.has_asid) { - down_write(&xe->usm.lock); - err = xa_alloc_cyclic(&xe->usm.asid_to_vm, &asid, vm, - XA_LIMIT(1, XE_MAX_ASID - 1), - &xe->usm.next_asid, GFP_KERNEL); - up_write(&xe->usm.lock); - if (err < 0) - goto err_close_and_put; - - vm->usm.asid = asid; - } - - /* Record BO memory for VM pagetable created against client */ - for_each_tile(tile, xe, id) - if (vm->pt_root[id]) - xe_drm_client_add_bo(vm->xef->client, vm->pt_root[id]->bo); - #if IS_ENABLED(CONFIG_DRM_XE_DEBUG_MEM) /* Warning: Security issue - never enable by default */ args->reserved[0] = xe_bo_main_addr(vm->pt_root[0]->bo, XE_PAGE_SIZE);
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Christoph Manszewski christoph.manszewski@intel.com
[ Upstream commit 111fb43a557726079a67ce3ab51f602ddbf7097e ]
If the argument check during an array bind fails, the bind_ops are freed twice as seen below. Fix this by setting bind_ops to NULL after freeing.
================================================================== BUG: KASAN: double-free in xe_vm_bind_ioctl+0x1b2/0x21f0 [xe] Free of addr ffff88813bb9b800 by task xe_vm/14198
CPU: 5 UID: 0 PID: 14198 Comm: xe_vm Not tainted 6.16.0-xe-eudebug-cmanszew+ #520 PREEMPT(full) Hardware name: Intel Corporation Alder Lake Client Platform/AlderLake-P DDR5 RVP, BIOS ADLPFWI1.R00.2411.A02.2110081023 10/08/2021 Call Trace: <TASK> dump_stack_lvl+0x82/0xd0 print_report+0xcb/0x610 ? __virt_addr_valid+0x19a/0x300 ? xe_vm_bind_ioctl+0x1b2/0x21f0 [xe] kasan_report_invalid_free+0xc8/0xf0 ? xe_vm_bind_ioctl+0x1b2/0x21f0 [xe] ? xe_vm_bind_ioctl+0x1b2/0x21f0 [xe] check_slab_allocation+0x102/0x130 kfree+0x10d/0x440 ? should_fail_ex+0x57/0x2f0 ? xe_vm_bind_ioctl+0x1b2/0x21f0 [xe] xe_vm_bind_ioctl+0x1b2/0x21f0 [xe] ? __pfx_xe_vm_bind_ioctl+0x10/0x10 [xe] ? __lock_acquire+0xab9/0x27f0 ? lock_acquire+0x165/0x300 ? drm_dev_enter+0x53/0xe0 [drm] ? find_held_lock+0x2b/0x80 ? drm_dev_exit+0x30/0x50 [drm] ? drm_ioctl_kernel+0x128/0x1c0 [drm] drm_ioctl_kernel+0x128/0x1c0 [drm] ? __pfx_xe_vm_bind_ioctl+0x10/0x10 [xe] ? find_held_lock+0x2b/0x80 ? __pfx_drm_ioctl_kernel+0x10/0x10 [drm] ? should_fail_ex+0x57/0x2f0 ? __pfx_xe_vm_bind_ioctl+0x10/0x10 [xe] drm_ioctl+0x352/0x620 [drm] ? __pfx_drm_ioctl+0x10/0x10 [drm] ? __pfx_rpm_resume+0x10/0x10 ? do_raw_spin_lock+0x11a/0x1b0 ? find_held_lock+0x2b/0x80 ? __pm_runtime_resume+0x61/0xc0 ? rcu_is_watching+0x20/0x50 ? trace_irq_enable.constprop.0+0xac/0xe0 xe_drm_ioctl+0x91/0xc0 [xe] __x64_sys_ioctl+0xb2/0x100 ? rcu_is_watching+0x20/0x50 do_syscall_64+0x68/0x2e0 entry_SYSCALL_64_after_hwframe+0x76/0x7e RIP: 0033:0x7fa9acb24ded
Fixes: b43e864af0d4 ("drm/xe/uapi: Add DRM_XE_VM_BIND_FLAG_CPU_ADDR_MIRROR") Cc: Matthew Brost matthew.brost@intel.com Cc: Himal Prasad Ghimiray himal.prasad.ghimiray@intel.com Cc: Thomas Hellström thomas.hellstrom@linux.intel.com Signed-off-by: Christoph Manszewski christoph.manszewski@intel.com Reviewed-by: Matthew Brost matthew.brost@intel.com Signed-off-by: Matthew Brost matthew.brost@intel.com Link: https://lore.kernel.org/r/20250813101231.196632-2-christoph.manszewski@intel... (cherry picked from commit a01b704527c28a2fd43a17a85f8996b75ec8492a) Signed-off-by: Rodrigo Vivi rodrigo.vivi@intel.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/gpu/drm/xe/xe_vm.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/xe/xe_vm.c b/drivers/gpu/drm/xe/xe_vm.c index 3135de124c18..3b11b1d52bee 100644 --- a/drivers/gpu/drm/xe/xe_vm.c +++ b/drivers/gpu/drm/xe/xe_vm.c @@ -3200,6 +3200,7 @@ static int vm_bind_ioctl_check_args(struct xe_device *xe, struct xe_vm *vm, free_bind_ops: if (args->num_binds > 1) kvfree(*bind_ops); + *bind_ops = NULL; return err; }
@@ -3305,7 +3306,7 @@ int xe_vm_bind_ioctl(struct drm_device *dev, void *data, struct drm_file *file) struct xe_exec_queue *q = NULL; u32 num_syncs, num_ufence = 0; struct xe_sync_entry *syncs = NULL; - struct drm_xe_vm_bind_op *bind_ops; + struct drm_xe_vm_bind_op *bind_ops = NULL; struct xe_vma_ops vops; struct dma_fence *fence; int err;
Hi Greg
On Tue, Aug 26, 2025 at 8:14 PM Greg Kroah-Hartman gregkh@linuxfoundation.org wrote:
This is the start of the stable review cycle for the 6.16.4 release. There are 457 patches in this series, all will be posted as a response to this one. If anyone has any issues with these being applied, please let me know.
Responses should be made by Thu, 28 Aug 2025 11:08:27 +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.16.4-rc1.... or in the git tree and branch at: git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.git linux-6.16.y and the diffstat can be found below.
thanks,
greg k-h
6.16.4-rc1 tested.
Build successfully completed. Boot successfully completed. No dmesg regressions. Video output normal. Sound output normal.
Lenovo ThinkPad X1 Carbon Gen10(Intel i7-1260P(x86_64) arch linux)
[ 0.000000] Linux version 6.16.4-rc1rv-g2894c4c9dabd (takeshi@ThinkPadX1Gen10J0764) (gcc (GCC) 15.2.1 20250813, GNU ld (GNU Binutils) 2.45.0) #1 SMP PREEMPT_DYNAMIC Tue Aug 26 21:54:15 JST 2025
Thanks
Tested-by: Takeshi Ogasawara takeshi.ogasawara@futuring-girl.com
On Tue, 26 Aug 2025 13:04:44 +0200 Greg Kroah-Hartman gregkh@linuxfoundation.org wrote:
This is the start of the stable review cycle for the 6.16.4 release. There are 457 patches in this series, all will be posted as a response to this one. If anyone has any issues with these being applied, please let me know.
Responses should be made by Thu, 28 Aug 2025 11:08:27 +0000. Anything received after that time might be too late.
Boot-tested under QEMU for Rust x86_64, arm64 and riscv64; built-tested for loongarch64:
Tested-by: Miguel Ojeda ojeda@kernel.org
(By the way, this one builds cleanly for arm 32-bit too -- I normally don't report on it since it is not clean, but it is nice to see it may be getting there).
Thanks!
Cheers, Miguel
[2025-08-26 13:04] Greg Kroah-Hartman:
This is the start of the stable review cycle for the 6.16.4 release. There are 457 patches in this series, all will be posted as a response to this one. If anyone has any issues with these being applied, please let me know.
Responses should be made by Thu, 28 Aug 2025 11:08:27 +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.16.4-rc1.... or in the git tree and branch at: git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.git linux-6.16.y and the diffstat can be found below.
Hi Greg, 6.16.4-rc1 (6.16.3 + all patches from the stable queue from 24h ago) compiles fine for x86_64 using GCC 15.2.1+r22+gc4e96a094636 and binutils 2.45+r29+g2b2e51a31ec7, and the resulting kernel has been running without any discernible issues since roughly 00:00 UTC today on various physical machines of mine (Ivy Bridge, Haswell, Kaby Lake, Coffee Lake) and in a Zen 2 VM and a bunch of Kaby Lake VMs.
Regards Pascal
[2025-08-26 17:10] Pascal Ernster:
[2025-08-26 13:04] Greg Kroah-Hartman:
This is the start of the stable review cycle for the 6.16.4 release. There are 457 patches in this series, all will be posted as a response to this one. If anyone has any issues with these being applied, please let me know.
Responses should be made by Thu, 28 Aug 2025 11:08:27 +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.16.4-rc1.... or in the git tree and branch at: git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.git linux-6.16.y and the diffstat can be found below.
Hi Greg, 6.16.4-rc1 (6.16.3 + all patches from the stable queue from 24h ago) compiles fine for x86_64 using GCC 15.2.1+r22+gc4e96a094636 and binutils 2.45+r29+g2b2e51a31ec7, and the resulting kernel has been running without any discernible issues since roughly 00:00 UTC today on various physical machines of mine (Ivy Bridge, Haswell, Kaby Lake, Coffee Lake) and in a Zen 2 VM and a bunch of Kaby Lake VMs.
Regards Pascal
Tested-by: Pascal Ernster git@hardfalcon.net
Hi
no regressions here on x86_64 (RKL, Intel 11th Gen. CPU)
Thanks
Tested-by: Ronald Warsow rwarsow@gmx.de
On Tue, Aug 26, 2025 at 4:44 PM Greg Kroah-Hartman gregkh@linuxfoundation.org wrote:
This is the start of the stable review cycle for the 6.16.4 release. There are 457 patches in this series, all will be posted as a response to this one. If anyone has any issues with these being applied, please let me know.
Responses should be made by Thu, 28 Aug 2025 11:08:27 +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.16.4-rc1.... or in the git tree and branch at: git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.git linux-6.16.y and the diffstat can be found below.
thanks,
greg k-h
Build and boot tested 6.16.4-rc1 using qemu-x86_64. The kernel was successfully built and booted in a virtualized environment without issues.
Tested-by: Dileep Malepu dileep.debian@gmail.com
On Tue, Aug 26, 2025 at 01:04:44PM +0200, Greg Kroah-Hartman wrote:
This is the start of the stable review cycle for the 6.16.4 release. There are 457 patches in this series, all will be posted as a response to this one. If anyone has any issues with these being applied, please let me know.
Responses should be made by Thu, 28 Aug 2025 11:08:27 +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.16.4-rc1.... or in the git tree and branch at: git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.git linux-6.16.y and the diffstat can be found below.
thanks,
greg k-h
Tested rc1 against the Fedora build system (aarch64, ppc64le, s390x, x86_64), and boot tested x86_64. No regressions noted.
Tested-by: Justin M. Forbes jforbes@fedoraproject.org
On Tue, 26 Aug 2025 13:04:44 +0200, Greg Kroah-Hartman wrote:
This is the start of the stable review cycle for the 6.16.4 release. There are 457 patches in this series, all will be posted as a response to this one. If anyone has any issues with these being applied, please let me know.
Responses should be made by Thu, 28 Aug 2025 11:08:27 +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.16.4-rc1.... or in the git tree and branch at: git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.git linux-6.16.y and the diffstat can be found below.
thanks,
greg k-h
All tests passing for Tegra ...
Test results for stable-v6.16: 10 builds: 10 pass, 0 fail 28 boots: 28 pass, 0 fail 120 tests: 120 pass, 0 fail
Linux version: 6.16.4-rc1-g2894c4c9dabd Boards tested: tegra124-jetson-tk1, tegra186-p2771-0000, tegra186-p3509-0000+p3636-0001, tegra194-p2972-0000, tegra194-p3509-0000+p3668-0000, tegra20-ventana, tegra210-p2371-2180, tegra210-p3450-0000, tegra30-cardhu-a04
Tested-by: Jon Hunter jonathanh@nvidia.com
Jon
# Librecast Test Results
010/010 [ OK ] libmld 120/120 [ OK ] liblibrecast
CPU/kernel: Linux auntie 6.16.4-rc1-g2894c4c9dabd #52 SMP PREEMPT_DYNAMIC Tue Aug 26 17:28:33 -00 2025 x86_64 AMD Ryzen 9 9950X 16-Core Processor AuthenticAMD GNU/Linux
Tested-by: Brett A C Sheffield bacs@librecast.net
On Tue Aug 26, 2025 at 1:04 PM CEST, Greg Kroah-Hartman wrote:
This is the start of the stable review cycle for the 6.16.4 release. There are 457 patches in this series, all will be posted as a response to this one. If anyone has any issues with these being applied, please let me know.
Responses should be made by Thu, 28 Aug 2025 11:08:27 +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.16.4-rc1.... or in the git tree and branch at: git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.git linux-6.16.y and the diffstat can be found below.
thanks,
greg k-h
Thanks! Builded on all Alpine architectures (aarch64, armv7, loongarch64, ppc64le, riscv64, s390x, x86, x86_64) and boot-tested on x86_64.
Tested-By: Achill Gilgenast achill@achill.org
On 8/26/25 04:04, Greg Kroah-Hartman wrote:
This is the start of the stable review cycle for the 6.16.4 release. There are 457 patches in this series, all will be posted as a response to this one. If anyone has any issues with these being applied, please let me know.
Responses should be made by Thu, 28 Aug 2025 11:08:27 +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.16.4-rc1.... or in the git tree and branch at: git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.git linux-6.16.y and the diffstat can be found below.
thanks,
greg k-h
On ARCH_BRCMSTB using 32-bit and 64-bit ARM kernels, build tested on BMIPS_GENERIC:
Tested-by: Florian Fainelli florian.fainelli@broadcom.com
Am 26.08.2025 um 13:04 schrieb Greg Kroah-Hartman:
This is the start of the stable review cycle for the 6.16.4 release. There are 457 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.
Builds, boots and works on my 2-socket Ivy Bridge Xeon E5-2697 v2 server. No dmesg oddities or regressions found.
Tested-by: Peter Schneider pschneider1968@googlemail.com
Beste Grüße, Peter Schneider
On Tue, 26 Aug 2025 at 16:43, Greg Kroah-Hartman gregkh@linuxfoundation.org wrote:
This is the start of the stable review cycle for the 6.16.4 release. There are 457 patches in this series, all will be posted as a response to this one. If anyone has any issues with these being applied, please let me know.
Responses should be made by Thu, 28 Aug 2025 11:08:27 +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.16.4-rc1.... or in the git tree and branch at: git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.git linux-6.16.y and the diffstat can be found below.
thanks,
greg k-h
Results from Linaro’s test farm. No regressions on arm64, arm, x86_64, and i386.
Tested-by: Linux Kernel Functional Testing lkft@linaro.org
## Build * kernel: 6.16.4-rc1 * git: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.git * git commit: 2894c4c9dabd275ab1a7338d9631bc10e5649c91 * git describe: v6.16.3-458-g2894c4c9dabd * test details: https://qa-reports.linaro.org/lkft/linux-stable-rc-linux-6.16.y/build/v6.16....
## Test Regressions (compared to v6.16.2-10-g3fb8628191b4)
## Metric Regressions (compared to v6.16.2-10-g3fb8628191b4)
## Test Fixes (compared to v6.16.2-10-g3fb8628191b4)
## Metric Fixes (compared to v6.16.2-10-g3fb8628191b4)
## Test result summary total: 344576, pass: 317202, fail: 7069, skip: 20305, xfail: 0
## Build Summary * arc: 5 total, 5 passed, 0 failed * arm: 139 total, 138 passed, 1 failed * arm64: 57 total, 56 passed, 1 failed * i386: 18 total, 18 passed, 0 failed * mips: 34 total, 27 passed, 7 failed * parisc: 4 total, 4 passed, 0 failed * powerpc: 40 total, 39 passed, 1 failed * riscv: 25 total, 24 passed, 1 failed * s390: 22 total, 22 passed, 0 failed * sh: 5 total, 5 passed, 0 failed * sparc: 4 total, 3 passed, 1 failed * x86_64: 49 total, 48 passed, 1 failed
## Test suites summary * boot * commands * kselftest-arm64 * kselftest-breakpoints * kselftest-capabilities * kselftest-cgroup * kselftest-clone3 * kselftest-core * kselftest-cpu-hotplug * kselftest-cpufreq * kselftest-efivarfs * kselftest-exec * kselftest-fpu * kselftest-ftrace * kselftest-futex * kselftest-gpio * kselftest-intel_pstate * kselftest-ipc * kselftest-kcmp * kselftest-kvm * kselftest-livepatch * kselftest-membarrier * kselftest-memfd * kselftest-mincore * kselftest-mm * kselftest-mqueue * kselftest-net * kselftest-net-mptcp * kselftest-openat2 * kselftest-ptrace * kselftest-rseq * kselftest-rtc * kselftest-rust * kselftest-seccomp * kselftest-sigaltstack * kselftest-size * kselftest-tc-testing * kselftest-timers * kselftest-tmpfs * kselftest-tpm2 * kselftest-user_events * kselftest-vDSO * kselftest-x86 * kunit * kvm-unit-tests * lava * libgpiod * libhugetlbfs * log-parser-boot * log-parser-build-clang * log-parser-build-gcc * log-parser-test * ltp-capability * ltp-commands * ltp-containers * ltp-controllers * ltp-cpuhotplug * ltp-crypto * ltp-cve * ltp-dio * ltp-fcntl-locktests * ltp-fs * ltp-fs_bind * ltp-fs_perms_simple * ltp-hugetlb * ltp-math * ltp-mm * ltp-nptl * ltp-pty * ltp-sched * ltp-smoke * ltp-syscalls * ltp-tracing * modules * perf * rcutorture * rt-tests-cyclicdeadline * rt-tests-pi-stress * rt-tests-pmqtest * rt-tests-rt-migrate-test * rt-tests-signaltest
-- Linaro LKFT https://lkft.linaro.org
On 8/26/25 04:04, Greg Kroah-Hartman wrote:
This is the start of the stable review cycle for the 6.16.4 release. There are 457 patches in this series, all will be posted as a response to this one. If anyone has any issues with these being applied, please let me know.
Responses should be made by Thu, 28 Aug 2025 11:08:27 +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.16.4-rc1.... or in the git tree and branch at: git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.git linux-6.16.y and the diffstat can be found below.
thanks,
greg k-h
Built and booted successfully on RISC-V RV64 (HiFive Unmatched).
Tested-by: Ron Economos re@w6rz.net
On Tue, Aug 26, 2025 at 01:04:44PM +0200, Greg Kroah-Hartman wrote:
This is the start of the stable review cycle for the 6.16.4 release. There are 457 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.
Tested-by: Mark Brown broonie@kernel.org
On 25/08/26 01:04PM, Greg Kroah-Hartman wrote:
This is the start of the stable review cycle for the 6.16.4 release. There are 457 patches in this series, all will be posted as a response to this one. If anyone has any issues with these being applied, please let me know.
Responses should be made by Thu, 28 Aug 2025 11:08:27 +0000. Anything received after that time might be too late.
Tested-by: Christian Heusel christian@heusel.eu
Tested on the following hardware:
* a ThinkPad E14 Gen 3 with a AMD Ryzen 5 5500U CPU * a Framework Laptop with a Ryzen AI 5 340 * a Framework Desktop * a Steam Deck (LCD Edition)
Hi!
This is the start of the stable review cycle for the 6.16.4 release. There are 457 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.
CIP testing did not find any problems here:
https://gitlab.com/cip-project/cip-testing/linux-stable-rc-ci/-/tree/linux-6...
6.6, 6.15, 5.15 pass our testing, too:
https://gitlab.com/cip-project/cip-testing/linux-stable-rc-ci/-/tree/linux-6... https://gitlab.com/cip-project/cip-testing/linux-stable-rc-ci/-/tree/linux-6... https://gitlab.com/cip-project/cip-testing/linux-stable-rc-ci/-/tree/linux-5...
Tested-by: Pavel Machek (CIP) pavel@denx.de
Best regards, Pavel
linux-stable-mirror@lists.linaro.org