This is the start of the stable review cycle for the 5.10.191 release. There are 135 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 Sat, 26 Aug 2023 14:50:00 +0000. Anything received after that time might be too late.
The whole patch series can be found in one patch at: https://www.kernel.org/pub/linux/kernel/v5.x/stable-review/patch-5.10.191-rc... or in the git tree and branch at: git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.git linux-5.10.y and the diffstat can be found below.
thanks,
greg k-h
------------- Pseudo-Shortlog of commits:
Greg Kroah-Hartman gregkh@linuxfoundation.org Linux 5.10.191-rc1
Borislav Petkov (AMD) bp@alien8.de x86/srso: Correct the mitigation status when SMT is disabled
Peter Zijlstra peterz@infradead.org objtool/x86: Fixup frame-pointer vs rethunk
Petr Pavlu petr.pavlu@suse.com x86/retpoline,kprobes: Fix position of thunk sections with CONFIG_LTO_CLANG
Borislav Petkov (AMD) bp@alien8.de x86/srso: Disable the mitigation on unaffected configurations
Borislav Petkov (AMD) bp@alien8.de x86/CPU/AMD: Fix the DIV(0) initial fix attempt
Sean Christopherson seanjc@google.com x86/retpoline: Don't clobber RFLAGS during srso_safe_ret()
Peter Zijlstra peterz@infradead.org x86/static_call: Fix __static_call_fixup()
Borislav Petkov (AMD) bp@alien8.de x86/srso: Explain the untraining sequences a bit more
Peter Zijlstra peterz@infradead.org x86/cpu: Cleanup the untrain mess
Peter Zijlstra peterz@infradead.org x86/cpu: Rename srso_(.*)_alias to srso_alias_\1
Peter Zijlstra peterz@infradead.org x86/cpu: Rename original retbleed methods
Peter Zijlstra peterz@infradead.org x86/cpu: Clean up SRSO return thunk mess
Peter Zijlstra peterz@infradead.org x86/ibt: Add ANNOTATE_NOENDBR
Josh Poimboeuf jpoimboe@redhat.com objtool: Add frame-pointer-specific function ignore
Peter Zijlstra peterz@infradead.org x86/alternative: Make custom return thunk unconditional
Peter Zijlstra peterz@infradead.org x86/cpu: Fix up srso_safe_ret() and __x86_return_thunk()
Peter Zijlstra peterz@infradead.org x86/cpu: Fix __x86_return_thunk symbol type
Yangtao Li frank.li@vivo.com mmc: f-sdh30: fix order of function calls in sdhci_f_sdh30_remove
Jason Xing kernelxing@tencent.com net: fix the RTO timer retransmitting skb every 1ms if linear option is enabled
Jason Wang jasowang@redhat.com virtio-net: set queues after driver_ok
Kuniyuki Iwashima kuniyu@amazon.com af_unix: Fix null-ptr-deref in unix_stream_sendpage().
Xin Long lucien.xin@gmail.com netfilter: set default timeout to 3 secs for sctp shutdown send and recv state
Yibin Ding yibin.ding@unisoc.com mmc: block: Fix in_flight[issue_type] value error
Yang Yingliang yangyingliang@huawei.com mmc: wbsd: fix double mmc_free_host() in wbsd_init()
Russell Harmon via samba-technical samba-technical@lists.samba.org cifs: Release folio lock on fscache read hit.
dengxiang dengxiang@nfschina.com ALSA: usb-audio: Add support for Mythware XA001AU capture and playback interfaces.
Tony Lindgren tony@atomide.com serial: 8250: Fix oops for port->pm on uart_change_pm()
Alexandre Ghiti alexghiti@rivosinc.com riscv: uaccess: Return the number of bytes effectively not copied
Chen Lifu chenlifu@huawei.com riscv: lib: uaccess: fix CSR_STATUS SR_SUM bit
Jisheng Zhang jszhang@kernel.org riscv: lib: uaccess: fold fixups into body
Akira Tsukamoto akira.tsukamoto@gmail.com riscv: __asm_copy_to-from_user: Optimize unaligned memory access and pipeline stall
Kailang Yang kailang@realtek.com ALSA: hda/realtek - Remodified 3k pull low procedure
Jerome Brunet jbrunet@baylibre.com ASoC: meson: axg-tdm-formatter: fix channel slot allocation
Zhang Shurong zhang_shurong@foxmail.com ASoC: rt5665: add missed regulator_bulk_disable
Christopher Obbard chris.obbard@collabora.com arm64: dts: rockchip: Disable HS400 for eMMC on ROCK Pi 4
FUKAUMI Naoki naoki@radxa.com arm64: dts: rockchip: sort nodes/properties on rk3399-rock-4
FUKAUMI Naoki naoki@radxa.com arm64: dts: rockchip: fix regulator name on rk3399-rock-4
Alex Bee knaerzche@gmail.com arm64: dts: rockchip: add SPDIF node for ROCK Pi 4
Alex Bee knaerzche@gmail.com arm64: dts: rockchip: add ES8316 codec for ROCK Pi 4
Vicente Bergas vicencb@gmail.com arm64: dts: rockchip: use USB host by default on rk3399-rock-pi-4
Vicente Bergas vicencb@gmail.com arm64: dts: rockchip: fix supplies on rk3399-rock-pi-4
Tony Lindgren tony@atomide.com bus: ti-sysc: Flush posted write on enable before reset
Eric Dumazet edumazet@google.com net: do not allow gso_size to be set to GSO_BY_FRAGS
Abel Wu wuyun.abel@bytedance.com sock: Fix misuse of sk_under_memory_pressure()
Alfred Lee l00g33k@gmail.com net: dsa: mv88e6xxx: Wait for EEPROM done before HW reset
Andrii Staikov andrii.staikov@intel.com i40e: fix misleading debug logs
Ziyang Xuan william.xuanziyang@huawei.com team: Fix incorrect deletion of ETH_P_8021AD protocol vid from slaves
Justin Chen justin.chen@broadcom.com net: phy: broadcom: stub c45 read/write for 54810
Pablo Neira Ayuso pablo@netfilter.org netfilter: nft_dynset: disallow object maps
Sishuai Gong sishuai.system@gmail.com ipvs: fix racy memcpy in proc_do_sync_threshold
Luca Ceresoli luca.ceresoli@bootlin.com drm/panel: simple: Fix AUO G121EAN01 panel timings according to the docs
Petr Machata petrm@nvidia.com selftests: mirror_gre_changes: Tighten up the TTL test match
Lin Ma linma@zju.edu.cn xfrm: add forgotten nla_policy for XFRMA_MTIMER_THRESH
Lin Ma linma@zju.edu.cn xfrm: add NULL check in xfrm_update_ae_params
Zhengchao Shao shaozhengchao@huawei.com ip_vti: fix potential slab-use-after-free in decode_session6
Zhengchao Shao shaozhengchao@huawei.com ip6_vti: fix slab-use-after-free in decode_session6
Zhengchao Shao shaozhengchao@huawei.com xfrm: fix slab-use-after-free in decode_session6
Lin Ma linma@zju.edu.cn net: xfrm: Amend XFRMA_SEC_CTX nla_policy structure
Lin Ma linma@zju.edu.cn net: af_key: fix sadb_x_filter validation
Lin Ma linma@zju.edu.cn net: xfrm: Fix xfrm_address_filter OOB read
Tam Nguyen tamnguyenchi@os.amperecomputing.com i2c: designware: Handle invalid SMBus block data response length value
xiaoshoukui xiaoshoukui@gmail.com btrfs: fix BUG_ON condition in btrfs_cancel_balance
Sherry Sun sherry.sun@nxp.com tty: serial: fsl_lpuart: Clear the error flags by writing 1 for lpuart32 platforms
Yi Yang yiyang13@huawei.com tty: n_gsm: fix the UAF caused by race condition in gsm_cleanup_mux
Nathan Lynch nathanl@linux.ibm.com powerpc/rtas_flash: allow user copy to flash block cache objects
Yuanjun Gong ruc_gongyuanjun@163.com fbdev: mmp: fix value check in mmphw_probe()
Chengfeng Ye dg573847474@gmail.com i2c: bcm-iproc: Fix bcm_iproc_i2c_isr deadlock issue
Wolfram Sang wsa+renesas@sang-engineering.com virtio-mmio: don't break lifecycle of vm_dev
Tang Bin tangbin@cmss.chinamobile.com virtio-mmio: Use to_virtio_mmio_device() to simply code
Ivan Mikhaylov fr0st61te@gmail.com net/ncsi: change from ndo_set_mac_address to dev_set_mac_address
Masami Hiramatsu (Google) mhiramat@kernel.org tracing/probes: Fix to update dynamic data counter if fetcharg uses it
Steven Rostedt (VMware) rostedt@goodmis.org tracing/probes: Have process_fetch_insn() take a void * instead of pt_regs
Sergey Shtylyov s.shtylyov@omp.ru mmc: meson-gx: fix deferred probing
Heiner Kallweit hkallweit1@gmail.com mmc: meson-gx: use devm_mmc_alloc_host
Heiner Kallweit hkallweit1@gmail.com mmc: core: add devm_mmc_alloc_host
Sergey Shtylyov s.shtylyov@omp.ru mmc: sunxi: fix deferred probing
Sergey Shtylyov s.shtylyov@omp.ru mmc: bcm2835: fix deferred probing
Johan Hovold johan+linaro@kernel.org USB: dwc3: qcom: fix NULL-deref on suspend
Frank Li Frank.Li@nxp.com usb: cdns3: fix NCM gadget RX speed 20x slow than expection at iMX8QM
Frank Li Frank.Li@nxp.com usb: cdns3: allocate TX FIFO size according to composite EP number
Wesley Cheng wcheng@codeaurora.org usb: gadget: udc: core: Introduce check_config to verify USB configuration
Pawel Laszczak pawell@cadence.com usb: cdnsp: Device side header file for CDNSP driver
Jiaxun Yang jiaxun.yang@flygoat.com irqchip/mips-gic: Use raw spinlock for gic_lock
Marc Zyngier maz@kernel.org irqchip/mips-gic: Get rid of the reliance on irq_cpu_online()
Jeffrey Hugo quic_jhugo@quicinc.com bus: mhi: host: Range check CHDBOFF and ERDBOFF
Manivannan Sadhasivam manivannan.sadhasivam@linaro.org bus: mhi: Move host MHI code to "host" directory
Bhaumik Bhatt bbhatt@codeaurora.org bus: mhi: Add MMIO region length to controller structure
Loic Poulain loic.poulain@linaro.org bus: mhi: Add MHI PCI support for WWAN modems
William Breathitt Gray william.gray@linaro.org iio: addac: stx104: Fix race condition when converting analog-to-digital
William Breathitt Gray william.gray@linaro.org iio: addac: stx104: Fix race condition for stx104_write_raw()
William Breathitt Gray william.gray@linaro.org iio: adc: stx104: Implement and utilize register structures
William Breathitt Gray william.gray@linaro.org iio: adc: stx104: Utilize iomap interface
Cosmin Tanislav demonsingur@gmail.com dt-bindings: iio: add AD74413R
Cosmin Tanislav demonsingur@gmail.com iio: add addac subdirectory
Randy Dunlap rdunlap@infradead.org IMA: allow/fix UML builds
Chen Lin chen.lin5@zte.com.cn ring-buffer: Do not swap cpu_buffer during resize process
Benjamin Gray bgray@linux.ibm.com powerpc/kasan: Disable KCOV in KASAN code
Tuo Li islituo@gmail.com ALSA: hda: fix a possible null-pointer dereference due to data race in snd_hdac_regmap_sync()
dengxiang dengxiang@nfschina.com ALSA: hda/realtek: Add quirks for Unis H3C Desktop B760 & Q760
shanzhulig shanzhulig@gmail.com drm/amdgpu: Fix potential fence use-after-free v2
Matthew Anderson ruinairas1992@gmail.com Bluetooth: btusb: Add MT7922 bluetooth ID for the Asus Ally
Zhengping Jiang jiangzp@google.com Bluetooth: L2CAP: Fix use-after-free
Armin Wolf W_Armin@gmx.de pcmcia: rsrc_nonstatic: Fix memory leak in nonstatic_release_resource_db()
Tuo Li islituo@gmail.com gfs2: Fix possible data races in gfs2_show_options()
Xu Yang xu.yang_2@nxp.com usb: chipidea: imx: add missing USB PHY DPDM wakeup setting
Xu Yang xu.yang_2@nxp.com usb: chipidea: imx: don't request QoS for imx8ulp
Hans Verkuil hverkuil-cisco@xs4all.nl media: platform: mediatek: vpu: fix NULL ptr dereference
Prashanth K quic_prashk@quicinc.com usb: gadget: u_serial: Avoid spinlock recursion in __gs_console_push
Yunfei Dong yunfei.dong@mediatek.com media: v4l2-mem2mem: add lock to protect parameter num_rdy
Immad Mir mirimmad17@gmail.com FS: JFS: Check for read-only mounted filesystem in txBegin
Immad Mir mirimmad17@gmail.com FS: JFS: Fix null-ptr-deref Read in txBegin
Gustavo A. R. Silva gustavoars@kernel.org MIPS: dec: prom: Address -Warray-bounds warning
Yogesh yogi.kernel@gmail.com fs: jfs: Fix UBSAN: array-index-out-of-bounds in dbAllocDmapLev
Jan Kara jack@suse.cz udf: Fix uninitialized array access for some pathnames
Christian Brauner brauner@kernel.org ovl: check type and offset of struct vfsmount in ovl_entry
Patrisious Haddad phaddad@nvidia.com RDMA/mlx5: Return the firmware result upon destroying QP/RQ
Marco Morandini marco.morandini@polimi.it HID: add quirk for 03f0:464a HP Elite Presenter Mouse
Lang Yu Lang.Yu@amd.com drm/amdgpu: install stub fence into potential unused fence pointers
gaoxu gaoxu2@hihonor.com dma-remap: use kvmalloc_array/kvfree for larger dma memory remap
Ye Bin yebin10@huawei.com quota: fix warning in dqgrab()
Jan Kara jack@suse.cz quota: Properly disable quotas when add_dquot_ref() fails
Geert Uytterhoeven geert+renesas@glider.be iopoll: Call cpu_relax() in busy loops
Uday M Bhat uday.m.bhat@intel.com ASoC: Intel: sof_sdw: Add support for Rex soundwire
Oleksij Rempel linux@rempel-privat.de ARM: dts: imx6dl: prtrvt, prtvt7, prti6q, prtwd2: fix USB related warnings
Sumit Gupta sumitg@nvidia.com PCI: tegra194: Fix possible array out of bounds access
Peter Ujfalusi peter.ujfalusi@linux.intel.com ASoC: Intel: sof_sdw: add quirk for LNL RVP
Bard Liao yung-chuan.liao@linux.intel.com ASoC: Intel: sof_sdw: add quirk for MTL RVP
Oswald Buddenhagen oswald.buddenhagen@gmx.de ALSA: emu10k1: roll up loops in DSP setup code for Audigy
hackyzh002 hackyzh002@gmail.com drm/radeon: Fix integer overflow in radeon_cs_parser_init
Moshe Shemesh moshe@nvidia.com net/mlx5: Skip clock update work when device is in error state
Eran Ben Elisha eranbe@mellanox.com net/mlx5: Move all internal timer metadata into a dedicated struct
Eran Ben Elisha eranbe@mellanox.com net/mlx5: Refactor init clock function
Eric Dumazet edumazet@google.com macsec: use DEV_STATS_INC()
Clayton Yager Clayton_Yager@selinc.com macsec: Fix traffic counters/statistics
Kunihiko Hayashi hayashi.kunihiko@socionext.com mmc: sdhci-f-sdh30: Replace with sdhci_pltfm
-------------
Diffstat:
Documentation/admin-guide/hw-vuln/srso.rst | 4 +- .../bindings/iio/addac/adi,ad74413r.yaml | 158 +++ Makefile | 4 +- arch/arm/boot/dts/imx6dl-prtrvt.dts | 4 + arch/arm/boot/dts/imx6qdl-prti6q.dtsi | 11 +- arch/arm64/boot/dts/rockchip/rk3399-rock-pi-4.dtsi | 207 +-- arch/mips/include/asm/dec/prom.h | 2 +- arch/powerpc/kernel/rtas_flash.c | 6 +- arch/powerpc/mm/kasan/Makefile | 1 + arch/riscv/lib/uaccess.S | 212 ++- arch/x86/include/asm/entry-common.h | 1 + arch/x86/include/asm/nospec-branch.h | 28 +- arch/x86/kernel/cpu/amd.c | 1 + arch/x86/kernel/cpu/bugs.c | 28 +- arch/x86/kernel/static_call.c | 13 + arch/x86/kernel/traps.c | 2 - arch/x86/kernel/vmlinux.lds.S | 18 +- arch/x86/kvm/svm/svm.c | 1 + arch/x86/lib/retpoline.S | 141 +- drivers/bluetooth/btusb.c | 3 + drivers/bus/Makefile | 2 +- drivers/bus/mhi/Kconfig | 18 +- drivers/bus/mhi/Makefile | 4 +- drivers/bus/mhi/host/Kconfig | 31 + drivers/bus/mhi/{core => host}/Makefile | 4 +- drivers/bus/mhi/{core => host}/boot.c | 0 drivers/bus/mhi/{core => host}/debugfs.c | 0 drivers/bus/mhi/{core => host}/init.c | 12 + drivers/bus/mhi/{core => host}/internal.h | 0 drivers/bus/mhi/{core => host}/main.c | 0 drivers/bus/mhi/host/pci_generic.c | 345 +++++ drivers/bus/mhi/{core => host}/pm.c | 0 drivers/bus/ti-sysc.c | 2 + drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c | 6 +- drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c | 6 +- drivers/gpu/drm/panel/panel-simple.c | 24 +- drivers/gpu/drm/radeon/radeon_cs.c | 3 +- drivers/hid/hid-ids.h | 1 + drivers/hid/hid-quirks.c | 1 + drivers/i2c/busses/i2c-bcm-iproc.c | 11 +- drivers/i2c/busses/i2c-designware-master.c | 15 +- drivers/iio/Kconfig | 1 + drivers/iio/Makefile | 1 + drivers/iio/adc/stx104.c | 98 +- drivers/iio/addac/Kconfig | 8 + drivers/iio/addac/Makefile | 6 + drivers/infiniband/hw/mlx5/qpc.c | 10 +- drivers/irqchip/irq-mips-gic.c | 63 +- drivers/media/platform/mtk-vpu/mtk_vpu.c | 6 +- drivers/mmc/core/block.c | 7 +- drivers/mmc/core/host.c | 26 + drivers/mmc/host/bcm2835.c | 4 +- drivers/mmc/host/meson-gx-mmc.c | 52 +- drivers/mmc/host/sdhci_f_sdh30.c | 66 +- drivers/mmc/host/sunxi-mmc.c | 4 +- drivers/mmc/host/wbsd.c | 2 - drivers/net/dsa/mv88e6xxx/chip.c | 8 + drivers/net/ethernet/intel/i40e/i40e_nvm.c | 16 +- .../net/ethernet/mellanox/mlx5/core/lib/clock.c | 166 ++- .../net/ethernet/mellanox/mlx5/core/lib/clock.h | 3 +- drivers/net/macsec.c | 70 +- drivers/net/phy/broadcom.c | 13 + drivers/net/team/team.c | 4 +- drivers/net/virtio_net.c | 4 +- drivers/pci/controller/dwc/pcie-tegra194.c | 13 +- drivers/pcmcia/rsrc_nonstatic.c | 2 + drivers/tty/n_gsm.c | 3 +- drivers/tty/serial/8250/8250_port.c | 1 + drivers/tty/serial/fsl_lpuart.c | 4 +- drivers/usb/cdns3/cdnsp-gadget.h | 1463 ++++++++++++++++++++ drivers/usb/cdns3/gadget.c | 60 +- drivers/usb/cdns3/gadget.h | 9 +- drivers/usb/chipidea/ci_hdrc_imx.c | 5 + drivers/usb/chipidea/usbmisc_imx.c | 2 +- drivers/usb/dwc3/dwc3-qcom.c | 11 +- drivers/usb/gadget/function/u_serial.c | 3 + drivers/usb/gadget/udc/core.c | 19 + drivers/video/fbdev/mmp/hw/mmp_ctrl.c | 4 +- drivers/virtio/virtio_mmio.c | 8 +- fs/btrfs/volumes.c | 3 +- fs/cifs/file.c | 2 +- fs/gfs2/super.c | 26 +- fs/jfs/jfs_dmap.c | 3 + fs/jfs/jfs_txnmgr.c | 5 + fs/jfs/namei.c | 5 + fs/overlayfs/ovl_entry.h | 9 + fs/quota/dquot.c | 5 +- fs/udf/unicode.c | 2 +- include/dt-bindings/iio/addac/adi,ad74413r.h | 21 + include/linux/iopoll.h | 2 + include/linux/mhi.h | 2 + include/linux/mlx5/driver.h | 12 +- include/linux/mmc/host.h | 1 + include/linux/objtool.h | 28 + include/linux/usb/gadget.h | 4 + include/linux/virtio_net.h | 4 + include/media/v4l2-mem2mem.h | 18 +- include/net/sock.h | 6 + kernel/dma/remap.c | 4 +- kernel/trace/ring_buffer.c | 14 +- kernel/trace/trace.c | 3 +- kernel/trace/trace_kprobe.c | 3 +- kernel/trace/trace_probe_tmpl.h | 18 +- kernel/trace/trace_uprobe.c | 3 +- net/bluetooth/l2cap_core.c | 5 + net/core/sock.c | 2 +- net/ipv4/ip_vti.c | 4 +- net/ipv4/tcp_timer.c | 4 +- net/ipv6/ip6_vti.c | 4 +- net/key/af_key.c | 4 +- net/ncsi/ncsi-rsp.c | 5 +- net/netfilter/ipvs/ip_vs_ctl.c | 4 + net/netfilter/nf_conntrack_proto_sctp.c | 6 +- net/netfilter/nft_dynset.c | 3 + net/unix/af_unix.c | 9 +- net/xfrm/xfrm_compat.c | 2 +- net/xfrm/xfrm_interface_core.c | 4 +- net/xfrm/xfrm_user.c | 14 +- security/integrity/ima/Kconfig | 2 +- sound/hda/hdac_regmap.c | 7 +- sound/pci/emu10k1/emufx.c | 112 +- sound/pci/hda/patch_realtek.c | 16 +- sound/soc/codecs/rt5665.c | 2 + sound/soc/intel/boards/sof_sdw.c | 25 + sound/soc/meson/axg-tdm-formatter.c | 42 +- sound/usb/quirks-table.h | 29 + tools/include/linux/objtool.h | 28 + tools/objtool/arch/x86/decode.c | 2 +- tools/objtool/check.c | 21 +- .../selftests/net/forwarding/mirror_gre_changes.sh | 3 +- 130 files changed, 3442 insertions(+), 695 deletions(-)
From: Kunihiko Hayashi hayashi.kunihiko@socionext.com
[ Upstream commit 5def5c1c15bf22934ee227af85c1716762f3829f ]
Even if sdhci_pltfm_pmops is specified for PM, this driver doesn't apply sdhci_pltfm, so the structure is not correctly referenced in PM functions. This applies sdhci_pltfm to this driver to fix this issue.
- Call sdhci_pltfm_init() instead of sdhci_alloc_host() and other functions that covered by sdhci_pltfm. - Move ops and quirks to sdhci_pltfm_data - Replace sdhci_priv() with own private function sdhci_f_sdh30_priv().
Fixes: 87a507459f49 ("mmc: sdhci: host: add new f_sdh30") Signed-off-by: Kunihiko Hayashi hayashi.kunihiko@socionext.com Acked-by: Adrian Hunter adrian.hunter@intel.com Cc: stable@vger.kernel.org Link: https://lore.kernel.org/r/20230630004533.26644-1-hayashi.kunihiko@socionext.... Signed-off-by: Ulf Hansson ulf.hansson@linaro.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/mmc/host/sdhci_f_sdh30.c | 60 ++++++++++++++------------------ 1 file changed, 27 insertions(+), 33 deletions(-)
diff --git a/drivers/mmc/host/sdhci_f_sdh30.c b/drivers/mmc/host/sdhci_f_sdh30.c index 6c4f43e112826..8876fd1c7eee0 100644 --- a/drivers/mmc/host/sdhci_f_sdh30.c +++ b/drivers/mmc/host/sdhci_f_sdh30.c @@ -26,9 +26,16 @@ struct f_sdhost_priv { bool enable_cmd_dat_delay; };
+static void *sdhci_f_sdhost_priv(struct sdhci_host *host) +{ + struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); + + return sdhci_pltfm_priv(pltfm_host); +} + static void sdhci_f_sdh30_soft_voltage_switch(struct sdhci_host *host) { - struct f_sdhost_priv *priv = sdhci_priv(host); + struct f_sdhost_priv *priv = sdhci_f_sdhost_priv(host); u32 ctrl = 0;
usleep_range(2500, 3000); @@ -61,7 +68,7 @@ static unsigned int sdhci_f_sdh30_get_min_clock(struct sdhci_host *host)
static void sdhci_f_sdh30_reset(struct sdhci_host *host, u8 mask) { - struct f_sdhost_priv *priv = sdhci_priv(host); + struct f_sdhost_priv *priv = sdhci_f_sdhost_priv(host); u32 ctl;
if (sdhci_readw(host, SDHCI_CLOCK_CONTROL) == 0) @@ -85,30 +92,32 @@ static const struct sdhci_ops sdhci_f_sdh30_ops = { .set_uhs_signaling = sdhci_set_uhs_signaling, };
+static const struct sdhci_pltfm_data sdhci_f_sdh30_pltfm_data = { + .ops = &sdhci_f_sdh30_ops, + .quirks = SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC + | SDHCI_QUIRK_INVERTED_WRITE_PROTECT, + .quirks2 = SDHCI_QUIRK2_SUPPORT_SINGLE + | SDHCI_QUIRK2_TUNING_WORK_AROUND, +}; + static int sdhci_f_sdh30_probe(struct platform_device *pdev) { struct sdhci_host *host; struct device *dev = &pdev->dev; - int irq, ctrl = 0, ret = 0; + int ctrl = 0, ret = 0; struct f_sdhost_priv *priv; + struct sdhci_pltfm_host *pltfm_host; u32 reg = 0;
- irq = platform_get_irq(pdev, 0); - if (irq < 0) - return irq; - - host = sdhci_alloc_host(dev, sizeof(struct f_sdhost_priv)); + host = sdhci_pltfm_init(pdev, &sdhci_f_sdh30_pltfm_data, + sizeof(struct f_sdhost_priv)); if (IS_ERR(host)) return PTR_ERR(host);
- priv = sdhci_priv(host); + pltfm_host = sdhci_priv(host); + priv = sdhci_pltfm_priv(pltfm_host); priv->dev = dev;
- host->quirks = SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC | - SDHCI_QUIRK_INVERTED_WRITE_PROTECT; - host->quirks2 = SDHCI_QUIRK2_SUPPORT_SINGLE | - SDHCI_QUIRK2_TUNING_WORK_AROUND; - priv->enable_cmd_dat_delay = device_property_read_bool(dev, "fujitsu,cmd-dat-delay-select");
@@ -116,18 +125,6 @@ static int sdhci_f_sdh30_probe(struct platform_device *pdev) if (ret) goto err;
- platform_set_drvdata(pdev, host); - - host->hw_name = "f_sdh30"; - host->ops = &sdhci_f_sdh30_ops; - host->irq = irq; - - host->ioaddr = devm_platform_ioremap_resource(pdev, 0); - if (IS_ERR(host->ioaddr)) { - ret = PTR_ERR(host->ioaddr); - goto err; - } - if (dev_of_node(dev)) { sdhci_get_of_property(pdev);
@@ -182,23 +179,20 @@ static int sdhci_f_sdh30_probe(struct platform_device *pdev) err_clk: clk_disable_unprepare(priv->clk_iface); err: - sdhci_free_host(host); + sdhci_pltfm_free(pdev); + return ret; }
static int sdhci_f_sdh30_remove(struct platform_device *pdev) { struct sdhci_host *host = platform_get_drvdata(pdev); - struct f_sdhost_priv *priv = sdhci_priv(host); - - sdhci_remove_host(host, readl(host->ioaddr + SDHCI_INT_STATUS) == - 0xffffffff); + struct f_sdhost_priv *priv = sdhci_f_sdhost_priv(host);
clk_disable_unprepare(priv->clk_iface); clk_disable_unprepare(priv->clk);
- sdhci_free_host(host); - platform_set_drvdata(pdev, NULL); + sdhci_pltfm_unregister(pdev);
return 0; }
From: Clayton Yager Clayton_Yager@selinc.com
[ Upstream commit 91ec9bd57f3524ff3d86bfb7c9ee5a315019733c ]
OutOctetsProtected, OutOctetsEncrypted, InOctetsValidated, and InOctetsDecrypted were incrementing by the total number of octets in frames instead of by the number of octets of User Data in frames.
The Controlled Port statistics ifOutOctets and ifInOctets were incrementing by the total number of octets instead of the number of octets of the MSDUs plus octets of the destination and source MAC addresses.
The Controlled Port statistics ifInDiscards and ifInErrors were not incrementing each time the counters they aggregate were.
The Controlled Port statistic ifInErrors was not included in the output of macsec_get_stats64 so the value was not present in ip commands output.
The ReceiveSA counters InPktsNotValid, InPktsNotUsingSA, and InPktsUnusedSA were not incrementing.
Signed-off-by: Clayton Yager Clayton_Yager@selinc.com Signed-off-by: David S. Miller davem@davemloft.net Stable-dep-of: 32d0a49d36a2 ("macsec: use DEV_STATS_INC()") Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/net/macsec.c | 58 +++++++++++++++++++++++++++++++++++++------- 1 file changed, 49 insertions(+), 9 deletions(-)
diff --git a/drivers/net/macsec.c b/drivers/net/macsec.c index 4fdb970e34823..6691c941f8bb8 100644 --- a/drivers/net/macsec.c +++ b/drivers/net/macsec.c @@ -159,6 +159,19 @@ static struct macsec_rx_sa *macsec_rxsa_get(struct macsec_rx_sa __rcu *ptr) return sa; }
+static struct macsec_rx_sa *macsec_active_rxsa_get(struct macsec_rx_sc *rx_sc) +{ + struct macsec_rx_sa *sa = NULL; + int an; + + for (an = 0; an < MACSEC_NUM_AN; an++) { + sa = macsec_rxsa_get(rx_sc->sa[an]); + if (sa) + break; + } + return sa; +} + static void free_rx_sc_rcu(struct rcu_head *head) { struct macsec_rx_sc *rx_sc = container_of(head, struct macsec_rx_sc, rcu_head); @@ -497,18 +510,28 @@ static void macsec_encrypt_finish(struct sk_buff *skb, struct net_device *dev) skb->protocol = eth_hdr(skb)->h_proto; }
+static unsigned int macsec_msdu_len(struct sk_buff *skb) +{ + struct macsec_dev *macsec = macsec_priv(skb->dev); + struct macsec_secy *secy = &macsec->secy; + bool sci_present = macsec_skb_cb(skb)->has_sci; + + return skb->len - macsec_hdr_len(sci_present) - secy->icv_len; +} + static void macsec_count_tx(struct sk_buff *skb, struct macsec_tx_sc *tx_sc, struct macsec_tx_sa *tx_sa) { + unsigned int msdu_len = macsec_msdu_len(skb); struct pcpu_tx_sc_stats *txsc_stats = this_cpu_ptr(tx_sc->stats);
u64_stats_update_begin(&txsc_stats->syncp); if (tx_sc->encrypt) { - txsc_stats->stats.OutOctetsEncrypted += skb->len; + txsc_stats->stats.OutOctetsEncrypted += msdu_len; txsc_stats->stats.OutPktsEncrypted++; this_cpu_inc(tx_sa->stats->OutPktsEncrypted); } else { - txsc_stats->stats.OutOctetsProtected += skb->len; + txsc_stats->stats.OutOctetsProtected += msdu_len; txsc_stats->stats.OutPktsProtected++; this_cpu_inc(tx_sa->stats->OutPktsProtected); } @@ -538,9 +561,10 @@ static void macsec_encrypt_done(struct crypto_async_request *base, int err) aead_request_free(macsec_skb_cb(skb)->req);
rcu_read_lock_bh(); - macsec_encrypt_finish(skb, dev); macsec_count_tx(skb, &macsec->secy.tx_sc, macsec_skb_cb(skb)->tx_sa); - len = skb->len; + /* packet is encrypted/protected so tx_bytes must be calculated */ + len = macsec_msdu_len(skb) + 2 * ETH_ALEN; + macsec_encrypt_finish(skb, dev); ret = dev_queue_xmit(skb); count_tx(dev, ret, len); rcu_read_unlock_bh(); @@ -699,6 +723,7 @@ static struct sk_buff *macsec_encrypt(struct sk_buff *skb,
macsec_skb_cb(skb)->req = req; macsec_skb_cb(skb)->tx_sa = tx_sa; + macsec_skb_cb(skb)->has_sci = sci_present; aead_request_set_callback(req, 0, macsec_encrypt_done, skb);
dev_hold(skb->dev); @@ -740,15 +765,17 @@ static bool macsec_post_decrypt(struct sk_buff *skb, struct macsec_secy *secy, u u64_stats_update_begin(&rxsc_stats->syncp); rxsc_stats->stats.InPktsLate++; u64_stats_update_end(&rxsc_stats->syncp); + secy->netdev->stats.rx_dropped++; return false; }
if (secy->validate_frames != MACSEC_VALIDATE_DISABLED) { + unsigned int msdu_len = macsec_msdu_len(skb); u64_stats_update_begin(&rxsc_stats->syncp); if (hdr->tci_an & MACSEC_TCI_E) - rxsc_stats->stats.InOctetsDecrypted += skb->len; + rxsc_stats->stats.InOctetsDecrypted += msdu_len; else - rxsc_stats->stats.InOctetsValidated += skb->len; + rxsc_stats->stats.InOctetsValidated += msdu_len; u64_stats_update_end(&rxsc_stats->syncp); }
@@ -761,6 +788,8 @@ static bool macsec_post_decrypt(struct sk_buff *skb, struct macsec_secy *secy, u u64_stats_update_begin(&rxsc_stats->syncp); rxsc_stats->stats.InPktsNotValid++; u64_stats_update_end(&rxsc_stats->syncp); + this_cpu_inc(rx_sa->stats->InPktsNotValid); + secy->netdev->stats.rx_errors++; return false; }
@@ -853,9 +882,9 @@ static void macsec_decrypt_done(struct crypto_async_request *base, int err)
macsec_finalize_skb(skb, macsec->secy.icv_len, macsec_extra_len(macsec_skb_cb(skb)->has_sci)); + len = skb->len; macsec_reset_skb(skb, macsec->secy.netdev);
- len = skb->len; if (gro_cells_receive(&macsec->gro_cells, skb) == NET_RX_SUCCESS) count_rx(dev, len);
@@ -1046,6 +1075,7 @@ static enum rx_handler_result handle_not_macsec(struct sk_buff *skb) u64_stats_update_begin(&secy_stats->syncp); secy_stats->stats.InPktsNoTag++; u64_stats_update_end(&secy_stats->syncp); + macsec->secy.netdev->stats.rx_dropped++; continue; }
@@ -1155,6 +1185,7 @@ static rx_handler_result_t macsec_handle_frame(struct sk_buff **pskb) u64_stats_update_begin(&secy_stats->syncp); secy_stats->stats.InPktsBadTag++; u64_stats_update_end(&secy_stats->syncp); + secy->netdev->stats.rx_errors++; goto drop_nosa; }
@@ -1165,11 +1196,15 @@ static rx_handler_result_t macsec_handle_frame(struct sk_buff **pskb) /* If validateFrames is Strict or the C bit in the * SecTAG is set, discard */ + struct macsec_rx_sa *active_rx_sa = macsec_active_rxsa_get(rx_sc); if (hdr->tci_an & MACSEC_TCI_C || secy->validate_frames == MACSEC_VALIDATE_STRICT) { u64_stats_update_begin(&rxsc_stats->syncp); rxsc_stats->stats.InPktsNotUsingSA++; u64_stats_update_end(&rxsc_stats->syncp); + secy->netdev->stats.rx_errors++; + if (active_rx_sa) + this_cpu_inc(active_rx_sa->stats->InPktsNotUsingSA); goto drop_nosa; }
@@ -1179,6 +1214,8 @@ static rx_handler_result_t macsec_handle_frame(struct sk_buff **pskb) u64_stats_update_begin(&rxsc_stats->syncp); rxsc_stats->stats.InPktsUnusedSA++; u64_stats_update_end(&rxsc_stats->syncp); + if (active_rx_sa) + this_cpu_inc(active_rx_sa->stats->InPktsUnusedSA); goto deliver; }
@@ -1199,6 +1236,7 @@ static rx_handler_result_t macsec_handle_frame(struct sk_buff **pskb) u64_stats_update_begin(&rxsc_stats->syncp); rxsc_stats->stats.InPktsLate++; u64_stats_update_end(&rxsc_stats->syncp); + macsec->secy.netdev->stats.rx_dropped++; goto drop; } } @@ -1227,6 +1265,7 @@ static rx_handler_result_t macsec_handle_frame(struct sk_buff **pskb) deliver: macsec_finalize_skb(skb, secy->icv_len, macsec_extra_len(macsec_skb_cb(skb)->has_sci)); + len = skb->len; macsec_reset_skb(skb, secy->netdev);
if (rx_sa) @@ -1234,7 +1273,6 @@ static rx_handler_result_t macsec_handle_frame(struct sk_buff **pskb) macsec_rxsc_put(rx_sc);
skb_orphan(skb); - len = skb->len; ret = gro_cells_receive(&macsec->gro_cells, skb); if (ret == NET_RX_SUCCESS) count_rx(dev, len); @@ -1276,6 +1314,7 @@ static rx_handler_result_t macsec_handle_frame(struct sk_buff **pskb) u64_stats_update_begin(&secy_stats->syncp); secy_stats->stats.InPktsNoSCI++; u64_stats_update_end(&secy_stats->syncp); + macsec->secy.netdev->stats.rx_errors++; continue; }
@@ -3407,6 +3446,7 @@ static netdev_tx_t macsec_start_xmit(struct sk_buff *skb, return NETDEV_TX_OK; }
+ len = skb->len; skb = macsec_encrypt(skb, dev); if (IS_ERR(skb)) { if (PTR_ERR(skb) != -EINPROGRESS) @@ -3417,7 +3457,6 @@ static netdev_tx_t macsec_start_xmit(struct sk_buff *skb, macsec_count_tx(skb, &macsec->secy.tx_sc, macsec_skb_cb(skb)->tx_sa);
macsec_encrypt_finish(skb, dev); - len = skb->len; ret = dev_queue_xmit(skb); count_tx(dev, ret, len); return ret; @@ -3648,6 +3687,7 @@ static void macsec_get_stats64(struct net_device *dev,
s->rx_dropped = dev->stats.rx_dropped; s->tx_dropped = dev->stats.tx_dropped; + s->rx_errors = dev->stats.rx_errors; }
static int macsec_get_iflink(const struct net_device *dev)
From: Eric Dumazet edumazet@google.com
[ Upstream commit 32d0a49d36a2a306c2e47fe5659361e424f0ed3f ]
syzbot/KCSAN reported data-races in macsec whenever dev->stats fields are updated.
It appears all of these updates can happen from multiple cpus.
Adopt SMP safe DEV_STATS_INC() to update dev->stats fields.
Fixes: c09440f7dcb3 ("macsec: introduce IEEE 802.1AE driver") Reported-by: syzbot syzkaller@googlegroups.com Signed-off-by: Eric Dumazet edumazet@google.com Cc: Sabrina Dubroca sd@queasysnail.net Signed-off-by: David S. Miller davem@davemloft.net Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/net/macsec.c | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-)
diff --git a/drivers/net/macsec.c b/drivers/net/macsec.c index 6691c941f8bb8..2ad15b1d7ffd7 100644 --- a/drivers/net/macsec.c +++ b/drivers/net/macsec.c @@ -765,7 +765,7 @@ static bool macsec_post_decrypt(struct sk_buff *skb, struct macsec_secy *secy, u u64_stats_update_begin(&rxsc_stats->syncp); rxsc_stats->stats.InPktsLate++; u64_stats_update_end(&rxsc_stats->syncp); - secy->netdev->stats.rx_dropped++; + DEV_STATS_INC(secy->netdev, rx_dropped); return false; }
@@ -789,7 +789,7 @@ static bool macsec_post_decrypt(struct sk_buff *skb, struct macsec_secy *secy, u rxsc_stats->stats.InPktsNotValid++; u64_stats_update_end(&rxsc_stats->syncp); this_cpu_inc(rx_sa->stats->InPktsNotValid); - secy->netdev->stats.rx_errors++; + DEV_STATS_INC(secy->netdev, rx_errors); return false; }
@@ -1075,7 +1075,7 @@ static enum rx_handler_result handle_not_macsec(struct sk_buff *skb) u64_stats_update_begin(&secy_stats->syncp); secy_stats->stats.InPktsNoTag++; u64_stats_update_end(&secy_stats->syncp); - macsec->secy.netdev->stats.rx_dropped++; + DEV_STATS_INC(macsec->secy.netdev, rx_dropped); continue; }
@@ -1185,7 +1185,7 @@ static rx_handler_result_t macsec_handle_frame(struct sk_buff **pskb) u64_stats_update_begin(&secy_stats->syncp); secy_stats->stats.InPktsBadTag++; u64_stats_update_end(&secy_stats->syncp); - secy->netdev->stats.rx_errors++; + DEV_STATS_INC(secy->netdev, rx_errors); goto drop_nosa; }
@@ -1202,7 +1202,7 @@ static rx_handler_result_t macsec_handle_frame(struct sk_buff **pskb) u64_stats_update_begin(&rxsc_stats->syncp); rxsc_stats->stats.InPktsNotUsingSA++; u64_stats_update_end(&rxsc_stats->syncp); - secy->netdev->stats.rx_errors++; + DEV_STATS_INC(secy->netdev, rx_errors); if (active_rx_sa) this_cpu_inc(active_rx_sa->stats->InPktsNotUsingSA); goto drop_nosa; @@ -1236,7 +1236,7 @@ static rx_handler_result_t macsec_handle_frame(struct sk_buff **pskb) u64_stats_update_begin(&rxsc_stats->syncp); rxsc_stats->stats.InPktsLate++; u64_stats_update_end(&rxsc_stats->syncp); - macsec->secy.netdev->stats.rx_dropped++; + DEV_STATS_INC(macsec->secy.netdev, rx_dropped); goto drop; } } @@ -1277,7 +1277,7 @@ static rx_handler_result_t macsec_handle_frame(struct sk_buff **pskb) if (ret == NET_RX_SUCCESS) count_rx(dev, len); else - macsec->secy.netdev->stats.rx_dropped++; + DEV_STATS_INC(macsec->secy.netdev, rx_dropped);
rcu_read_unlock();
@@ -1314,7 +1314,7 @@ static rx_handler_result_t macsec_handle_frame(struct sk_buff **pskb) u64_stats_update_begin(&secy_stats->syncp); secy_stats->stats.InPktsNoSCI++; u64_stats_update_end(&secy_stats->syncp); - macsec->secy.netdev->stats.rx_errors++; + DEV_STATS_INC(macsec->secy.netdev, rx_errors); continue; }
@@ -1333,7 +1333,7 @@ static rx_handler_result_t macsec_handle_frame(struct sk_buff **pskb) secy_stats->stats.InPktsUnknownSCI++; u64_stats_update_end(&secy_stats->syncp); } else { - macsec->secy.netdev->stats.rx_dropped++; + DEV_STATS_INC(macsec->secy.netdev, rx_dropped); } }
@@ -3442,7 +3442,7 @@ static netdev_tx_t macsec_start_xmit(struct sk_buff *skb,
if (!secy->operational) { kfree_skb(skb); - dev->stats.tx_dropped++; + DEV_STATS_INC(dev, tx_dropped); return NETDEV_TX_OK; }
@@ -3450,7 +3450,7 @@ static netdev_tx_t macsec_start_xmit(struct sk_buff *skb, skb = macsec_encrypt(skb, dev); if (IS_ERR(skb)) { if (PTR_ERR(skb) != -EINPROGRESS) - dev->stats.tx_dropped++; + DEV_STATS_INC(dev, tx_dropped); return NETDEV_TX_OK; }
@@ -3685,9 +3685,9 @@ static void macsec_get_stats64(struct net_device *dev,
dev_fetch_sw_netstats(s, dev->tstats);
- s->rx_dropped = dev->stats.rx_dropped; - s->tx_dropped = dev->stats.tx_dropped; - s->rx_errors = dev->stats.rx_errors; + s->rx_dropped = atomic_long_read(&dev->stats.__rx_dropped); + s->tx_dropped = atomic_long_read(&dev->stats.__tx_dropped); + s->rx_errors = atomic_long_read(&dev->stats.__rx_errors); }
static int macsec_get_iflink(const struct net_device *dev)
From: Eran Ben Elisha eranbe@mellanox.com
[ Upstream commit 1436de0b991548fd859a00c889b8c4dcbbb5f463 ]
Function mlx5_init_clock() is responsible for internal PTP related metadata initializations. Break mlx5_init_clock() to sub functions, each takes care of its own logic.
Signed-off-by: Eran Ben Elisha eranbe@mellanox.com Signed-off-by: Aya Levin ayal@nvidia.com Reviewed-by: Moshe Shemesh moshe@mellanox.com Signed-off-by: Saeed Mahameed saeedm@nvidia.com Stable-dep-of: d00620762565 ("net/mlx5: Skip clock update work when device is in error state") Signed-off-by: Sasha Levin sashal@kernel.org --- .../ethernet/mellanox/mlx5/core/lib/clock.c | 76 +++++++++++++------ 1 file changed, 53 insertions(+), 23 deletions(-)
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/lib/clock.c b/drivers/net/ethernet/mellanox/mlx5/core/lib/clock.c index 44a434b1178b5..3fbceb4af54e4 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/lib/clock.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/lib/clock.c @@ -591,20 +591,12 @@ static int mlx5_pps_event(struct notifier_block *nb, return NOTIFY_OK; }
-void mlx5_init_clock(struct mlx5_core_dev *mdev) +static void mlx5_timecounter_init(struct mlx5_core_dev *mdev) { struct mlx5_clock *clock = &mdev->clock; - u64 overflow_cycles; - u64 ns; - u64 frac = 0; u32 dev_freq;
dev_freq = MLX5_CAP_GEN(mdev, device_frequency_khz); - if (!dev_freq) { - mlx5_core_warn(mdev, "invalid device_frequency_khz, aborting HW clock init\n"); - return; - } - seqlock_init(&clock->lock); clock->cycles.read = read_internal_timer; clock->cycles.shift = MLX5_CYCLES_SHIFT; clock->cycles.mult = clocksource_khz2mult(dev_freq, @@ -614,6 +606,15 @@ void mlx5_init_clock(struct mlx5_core_dev *mdev)
timecounter_init(&clock->tc, &clock->cycles, ktime_to_ns(ktime_get_real())); +} + +static void mlx5_init_overflow_period(struct mlx5_clock *clock) +{ + struct mlx5_core_dev *mdev = container_of(clock, struct mlx5_core_dev, clock); + struct mlx5_ib_clock_info *clock_info = mdev->clock_info; + u64 overflow_cycles; + u64 frac = 0; + u64 ns;
/* Calculate period in seconds to call the overflow watchdog - to make * sure counter is checked at least twice every wrap around. @@ -630,24 +631,53 @@ void mlx5_init_clock(struct mlx5_core_dev *mdev) do_div(ns, NSEC_PER_SEC / HZ); clock->overflow_period = ns;
- mdev->clock_info = - (struct mlx5_ib_clock_info *)get_zeroed_page(GFP_KERNEL); - if (mdev->clock_info) { - mdev->clock_info->nsec = clock->tc.nsec; - mdev->clock_info->cycles = clock->tc.cycle_last; - mdev->clock_info->mask = clock->cycles.mask; - mdev->clock_info->mult = clock->nominal_c_mult; - mdev->clock_info->shift = clock->cycles.shift; - mdev->clock_info->frac = clock->tc.frac; - mdev->clock_info->overflow_period = clock->overflow_period; - } - - INIT_WORK(&clock->pps_info.out_work, mlx5_pps_out); INIT_DELAYED_WORK(&clock->overflow_work, mlx5_timestamp_overflow); if (clock->overflow_period) schedule_delayed_work(&clock->overflow_work, 0); else - mlx5_core_warn(mdev, "invalid overflow period, overflow_work is not scheduled\n"); + mlx5_core_warn(mdev, + "invalid overflow period, overflow_work is not scheduled\n"); + + if (clock_info) + clock_info->overflow_period = clock->overflow_period; +} + +static void mlx5_init_clock_info(struct mlx5_core_dev *mdev) +{ + struct mlx5_clock *clock = &mdev->clock; + struct mlx5_ib_clock_info *info; + + mdev->clock_info = (struct mlx5_ib_clock_info *)get_zeroed_page(GFP_KERNEL); + if (!mdev->clock_info) { + mlx5_core_warn(mdev, "Failed to allocate IB clock info page\n"); + return; + } + + info = mdev->clock_info; + + info->nsec = clock->tc.nsec; + info->cycles = clock->tc.cycle_last; + info->mask = clock->cycles.mask; + info->mult = clock->nominal_c_mult; + info->shift = clock->cycles.shift; + info->frac = clock->tc.frac; +} + +void mlx5_init_clock(struct mlx5_core_dev *mdev) +{ + struct mlx5_clock *clock = &mdev->clock; + + if (!MLX5_CAP_GEN(mdev, device_frequency_khz)) { + mlx5_core_warn(mdev, "invalid device_frequency_khz, aborting HW clock init\n"); + return; + } + + seqlock_init(&clock->lock); + + mlx5_timecounter_init(mdev); + mlx5_init_clock_info(mdev); + mlx5_init_overflow_period(clock); + INIT_WORK(&clock->pps_info.out_work, mlx5_pps_out);
/* Configure the PHC */ clock->ptp_info = mlx5_ptp_clock_info;
From: Eran Ben Elisha eranbe@mellanox.com
[ Upstream commit d6f3dc8f509ce6288e2537eb4b0614ef444fd84a ]
Internal timer mode (SW clock) requires some PTP clock related metadata structs. Real time mode (HW clock) will not need these metadata structs. This separation emphasize the different interfaces for HW clock and SW clock.
Signed-off-by: Eran Ben Elisha eranbe@mellanox.com Signed-off-by: Aya Levin ayal@nvidia.com Signed-off-by: Saeed Mahameed saeedm@nvidia.com Stable-dep-of: d00620762565 ("net/mlx5: Skip clock update work when device is in error state") Signed-off-by: Sasha Levin sashal@kernel.org --- .../ethernet/mellanox/mlx5/core/lib/clock.c | 107 ++++++++++-------- .../ethernet/mellanox/mlx5/core/lib/clock.h | 3 +- include/linux/mlx5/driver.h | 12 +- 3 files changed, 71 insertions(+), 51 deletions(-)
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/lib/clock.c b/drivers/net/ethernet/mellanox/mlx5/core/lib/clock.c index 3fbceb4af54e4..01b8a9648b16f 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/lib/clock.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/lib/clock.c @@ -89,7 +89,8 @@ static u64 mlx5_read_internal_timer(struct mlx5_core_dev *dev,
static u64 read_internal_timer(const struct cyclecounter *cc) { - struct mlx5_clock *clock = container_of(cc, struct mlx5_clock, cycles); + struct mlx5_timer *timer = container_of(cc, struct mlx5_timer, cycles); + struct mlx5_clock *clock = container_of(timer, struct mlx5_clock, timer); struct mlx5_core_dev *mdev = container_of(clock, struct mlx5_core_dev, clock);
@@ -100,6 +101,7 @@ static void mlx5_update_clock_info_page(struct mlx5_core_dev *mdev) { struct mlx5_ib_clock_info *clock_info = mdev->clock_info; struct mlx5_clock *clock = &mdev->clock; + struct mlx5_timer *timer; u32 sign;
if (!clock_info) @@ -109,10 +111,11 @@ static void mlx5_update_clock_info_page(struct mlx5_core_dev *mdev) smp_store_mb(clock_info->sign, sign | MLX5_IB_CLOCK_INFO_KERNEL_UPDATING);
- clock_info->cycles = clock->tc.cycle_last; - clock_info->mult = clock->cycles.mult; - clock_info->nsec = clock->tc.nsec; - clock_info->frac = clock->tc.frac; + timer = &clock->timer; + clock_info->cycles = timer->tc.cycle_last; + clock_info->mult = timer->cycles.mult; + clock_info->nsec = timer->tc.nsec; + clock_info->frac = timer->tc.frac;
smp_store_release(&clock_info->sign, sign + MLX5_IB_CLOCK_INFO_KERNEL_UPDATING * 2); @@ -151,28 +154,32 @@ static void mlx5_timestamp_overflow(struct work_struct *work) { struct delayed_work *dwork = to_delayed_work(work); struct mlx5_core_dev *mdev; + struct mlx5_timer *timer; struct mlx5_clock *clock; unsigned long flags;
- clock = container_of(dwork, struct mlx5_clock, overflow_work); + timer = container_of(dwork, struct mlx5_timer, overflow_work); + clock = container_of(timer, struct mlx5_clock, timer); mdev = container_of(clock, struct mlx5_core_dev, clock); + write_seqlock_irqsave(&clock->lock, flags); - timecounter_read(&clock->tc); + timecounter_read(&timer->tc); mlx5_update_clock_info_page(mdev); write_sequnlock_irqrestore(&clock->lock, flags); - schedule_delayed_work(&clock->overflow_work, clock->overflow_period); + schedule_delayed_work(&timer->overflow_work, timer->overflow_period); }
static int mlx5_ptp_settime(struct ptp_clock_info *ptp, const struct timespec64 *ts) { struct mlx5_clock *clock = container_of(ptp, struct mlx5_clock, ptp_info); + struct mlx5_timer *timer = &clock->timer; u64 ns = timespec64_to_ns(ts); struct mlx5_core_dev *mdev; unsigned long flags;
mdev = container_of(clock, struct mlx5_core_dev, clock); write_seqlock_irqsave(&clock->lock, flags); - timecounter_init(&clock->tc, &clock->cycles, ns); + timecounter_init(&timer->tc, &timer->cycles, ns); mlx5_update_clock_info_page(mdev); write_sequnlock_irqrestore(&clock->lock, flags);
@@ -183,6 +190,7 @@ static int mlx5_ptp_gettimex(struct ptp_clock_info *ptp, struct timespec64 *ts, struct ptp_system_timestamp *sts) { struct mlx5_clock *clock = container_of(ptp, struct mlx5_clock, ptp_info); + struct mlx5_timer *timer = &clock->timer; struct mlx5_core_dev *mdev; unsigned long flags; u64 cycles, ns; @@ -190,7 +198,7 @@ static int mlx5_ptp_gettimex(struct ptp_clock_info *ptp, struct timespec64 *ts, mdev = container_of(clock, struct mlx5_core_dev, clock); write_seqlock_irqsave(&clock->lock, flags); cycles = mlx5_read_internal_timer(mdev, sts); - ns = timecounter_cyc2time(&clock->tc, cycles); + ns = timecounter_cyc2time(&timer->tc, cycles); write_sequnlock_irqrestore(&clock->lock, flags);
*ts = ns_to_timespec64(ns); @@ -201,12 +209,13 @@ static int mlx5_ptp_gettimex(struct ptp_clock_info *ptp, struct timespec64 *ts, static int mlx5_ptp_adjtime(struct ptp_clock_info *ptp, s64 delta) { struct mlx5_clock *clock = container_of(ptp, struct mlx5_clock, ptp_info); + struct mlx5_timer *timer = &clock->timer; struct mlx5_core_dev *mdev; unsigned long flags;
mdev = container_of(clock, struct mlx5_core_dev, clock); write_seqlock_irqsave(&clock->lock, flags); - timecounter_adjtime(&clock->tc, delta); + timecounter_adjtime(&timer->tc, delta); mlx5_update_clock_info_page(mdev); write_sequnlock_irqrestore(&clock->lock, flags);
@@ -216,27 +225,27 @@ static int mlx5_ptp_adjtime(struct ptp_clock_info *ptp, s64 delta) static int mlx5_ptp_adjfreq(struct ptp_clock_info *ptp, s32 delta) { struct mlx5_clock *clock = container_of(ptp, struct mlx5_clock, ptp_info); + struct mlx5_timer *timer = &clock->timer; struct mlx5_core_dev *mdev; unsigned long flags; int neg_adj = 0; u32 diff; u64 adj;
- if (delta < 0) { neg_adj = 1; delta = -delta; }
- adj = clock->nominal_c_mult; + adj = timer->nominal_c_mult; adj *= delta; diff = div_u64(adj, 1000000000ULL);
mdev = container_of(clock, struct mlx5_core_dev, clock); write_seqlock_irqsave(&clock->lock, flags); - timecounter_read(&clock->tc); - clock->cycles.mult = neg_adj ? clock->nominal_c_mult - diff : - clock->nominal_c_mult + diff; + timecounter_read(&timer->tc); + timer->cycles.mult = neg_adj ? timer->nominal_c_mult - diff : + timer->nominal_c_mult + diff; mlx5_update_clock_info_page(mdev); write_sequnlock_irqrestore(&clock->lock, flags);
@@ -313,6 +322,7 @@ static int mlx5_perout_configure(struct ptp_clock_info *ptp, container_of(ptp, struct mlx5_clock, ptp_info); struct mlx5_core_dev *mdev = container_of(clock, struct mlx5_core_dev, clock); + struct mlx5_timer *timer = &clock->timer; u32 in[MLX5_ST_SZ_DW(mtpps_reg)] = {0}; u64 nsec_now, nsec_delta, time_stamp = 0; u64 cycles_now, cycles_delta; @@ -355,10 +365,10 @@ static int mlx5_perout_configure(struct ptp_clock_info *ptp, ns = timespec64_to_ns(&ts); cycles_now = mlx5_read_internal_timer(mdev, NULL); write_seqlock_irqsave(&clock->lock, flags); - nsec_now = timecounter_cyc2time(&clock->tc, cycles_now); + nsec_now = timecounter_cyc2time(&timer->tc, cycles_now); nsec_delta = ns - nsec_now; - cycles_delta = div64_u64(nsec_delta << clock->cycles.shift, - clock->cycles.mult); + cycles_delta = div64_u64(nsec_delta << timer->cycles.shift, + timer->cycles.mult); write_sequnlock_irqrestore(&clock->lock, flags); time_stamp = cycles_now + cycles_delta; field_select = MLX5_MTPPS_FS_PIN_MODE | @@ -541,6 +551,7 @@ static int mlx5_pps_event(struct notifier_block *nb, unsigned long type, void *data) { struct mlx5_clock *clock = mlx5_nb_cof(nb, struct mlx5_clock, pps_nb); + struct mlx5_timer *timer = &clock->timer; struct ptp_clock_event ptp_event; u64 cycles_now, cycles_delta; u64 nsec_now, nsec_delta, ns; @@ -575,10 +586,10 @@ static int mlx5_pps_event(struct notifier_block *nb, ts.tv_nsec = 0; ns = timespec64_to_ns(&ts); write_seqlock_irqsave(&clock->lock, flags); - nsec_now = timecounter_cyc2time(&clock->tc, cycles_now); + nsec_now = timecounter_cyc2time(&timer->tc, cycles_now); nsec_delta = ns - nsec_now; - cycles_delta = div64_u64(nsec_delta << clock->cycles.shift, - clock->cycles.mult); + cycles_delta = div64_u64(nsec_delta << timer->cycles.shift, + timer->cycles.mult); clock->pps_info.start[pin] = cycles_now + cycles_delta; write_sequnlock_irqrestore(&clock->lock, flags); schedule_work(&clock->pps_info.out_work); @@ -594,17 +605,18 @@ static int mlx5_pps_event(struct notifier_block *nb, static void mlx5_timecounter_init(struct mlx5_core_dev *mdev) { struct mlx5_clock *clock = &mdev->clock; + struct mlx5_timer *timer = &clock->timer; u32 dev_freq;
dev_freq = MLX5_CAP_GEN(mdev, device_frequency_khz); - clock->cycles.read = read_internal_timer; - clock->cycles.shift = MLX5_CYCLES_SHIFT; - clock->cycles.mult = clocksource_khz2mult(dev_freq, - clock->cycles.shift); - clock->nominal_c_mult = clock->cycles.mult; - clock->cycles.mask = CLOCKSOURCE_MASK(41); - - timecounter_init(&clock->tc, &clock->cycles, + timer->cycles.read = read_internal_timer; + timer->cycles.shift = MLX5_CYCLES_SHIFT; + timer->cycles.mult = clocksource_khz2mult(dev_freq, + timer->cycles.shift); + timer->nominal_c_mult = timer->cycles.mult; + timer->cycles.mask = CLOCKSOURCE_MASK(41); + + timecounter_init(&timer->tc, &timer->cycles, ktime_to_ns(ktime_get_real())); }
@@ -612,6 +624,7 @@ static void mlx5_init_overflow_period(struct mlx5_clock *clock) { struct mlx5_core_dev *mdev = container_of(clock, struct mlx5_core_dev, clock); struct mlx5_ib_clock_info *clock_info = mdev->clock_info; + struct mlx5_timer *timer = &clock->timer; u64 overflow_cycles; u64 frac = 0; u64 ns; @@ -623,29 +636,30 @@ static void mlx5_init_overflow_period(struct mlx5_clock *clock) * multiplied by clock multiplier where the result doesn't exceed * 64bits. */ - overflow_cycles = div64_u64(~0ULL >> 1, clock->cycles.mult); - overflow_cycles = min(overflow_cycles, div_u64(clock->cycles.mask, 3)); + overflow_cycles = div64_u64(~0ULL >> 1, timer->cycles.mult); + overflow_cycles = min(overflow_cycles, div_u64(timer->cycles.mask, 3));
- ns = cyclecounter_cyc2ns(&clock->cycles, overflow_cycles, + ns = cyclecounter_cyc2ns(&timer->cycles, overflow_cycles, frac, &frac); do_div(ns, NSEC_PER_SEC / HZ); - clock->overflow_period = ns; + timer->overflow_period = ns;
- INIT_DELAYED_WORK(&clock->overflow_work, mlx5_timestamp_overflow); - if (clock->overflow_period) - schedule_delayed_work(&clock->overflow_work, 0); + INIT_DELAYED_WORK(&timer->overflow_work, mlx5_timestamp_overflow); + if (timer->overflow_period) + schedule_delayed_work(&timer->overflow_work, 0); else mlx5_core_warn(mdev, "invalid overflow period, overflow_work is not scheduled\n");
if (clock_info) - clock_info->overflow_period = clock->overflow_period; + clock_info->overflow_period = timer->overflow_period; }
static void mlx5_init_clock_info(struct mlx5_core_dev *mdev) { struct mlx5_clock *clock = &mdev->clock; struct mlx5_ib_clock_info *info; + struct mlx5_timer *timer;
mdev->clock_info = (struct mlx5_ib_clock_info *)get_zeroed_page(GFP_KERNEL); if (!mdev->clock_info) { @@ -654,13 +668,14 @@ static void mlx5_init_clock_info(struct mlx5_core_dev *mdev) }
info = mdev->clock_info; - - info->nsec = clock->tc.nsec; - info->cycles = clock->tc.cycle_last; - info->mask = clock->cycles.mask; - info->mult = clock->nominal_c_mult; - info->shift = clock->cycles.shift; - info->frac = clock->tc.frac; + timer = &clock->timer; + + info->nsec = timer->tc.nsec; + info->cycles = timer->tc.cycle_last; + info->mask = timer->cycles.mask; + info->mult = timer->nominal_c_mult; + info->shift = timer->cycles.shift; + info->frac = timer->tc.frac; }
void mlx5_init_clock(struct mlx5_core_dev *mdev) @@ -714,7 +729,7 @@ void mlx5_cleanup_clock(struct mlx5_core_dev *mdev) }
cancel_work_sync(&clock->pps_info.out_work); - cancel_delayed_work_sync(&clock->overflow_work); + cancel_delayed_work_sync(&clock->timer.overflow_work);
if (mdev->clock_info) { free_page((unsigned long)mdev->clock_info); diff --git a/drivers/net/ethernet/mellanox/mlx5/core/lib/clock.h b/drivers/net/ethernet/mellanox/mlx5/core/lib/clock.h index 31600924bdc36..6e8804ebc773b 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/lib/clock.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/lib/clock.h @@ -45,12 +45,13 @@ static inline int mlx5_clock_get_ptp_index(struct mlx5_core_dev *mdev) static inline ktime_t mlx5_timecounter_cyc2time(struct mlx5_clock *clock, u64 timestamp) { + struct mlx5_timer *timer = &clock->timer; unsigned int seq; u64 nsec;
do { seq = read_seqbegin(&clock->lock); - nsec = timecounter_cyc2time(&clock->tc, timestamp); + nsec = timecounter_cyc2time(&timer->tc, timestamp); } while (read_seqretry(&clock->lock, seq));
return ns_to_ktime(nsec); diff --git a/include/linux/mlx5/driver.h b/include/linux/mlx5/driver.h index ae88362216a4e..4f95b98215d81 100644 --- a/include/linux/mlx5/driver.h +++ b/include/linux/mlx5/driver.h @@ -644,18 +644,22 @@ struct mlx5_pps { u8 enabled; };
-struct mlx5_clock { - struct mlx5_nb pps_nb; - seqlock_t lock; +struct mlx5_timer { struct cyclecounter cycles; struct timecounter tc; - struct hwtstamp_config hwtstamp_config; u32 nominal_c_mult; unsigned long overflow_period; struct delayed_work overflow_work; +}; + +struct mlx5_clock { + struct mlx5_nb pps_nb; + seqlock_t lock; + struct hwtstamp_config hwtstamp_config; struct ptp_clock *ptp; struct ptp_clock_info ptp_info; struct mlx5_pps pps_info; + struct mlx5_timer timer; };
struct mlx5_dm;
From: Moshe Shemesh moshe@nvidia.com
[ Upstream commit d006207625657322ba8251b6e7e829f9659755dc ]
When device is in error state, marked by the flag MLX5_DEVICE_STATE_INTERNAL_ERROR, the HW and PCI may not be accessible and so clock update work should be skipped. Furthermore, such access through PCI in error state, after calling mlx5_pci_disable_device() can result in failing to recover from pci errors.
Fixes: ef9814deafd0 ("net/mlx5e: Add HW timestamping (TS) support") Reported-and-tested-by: Ganesh G R ganeshgr@linux.ibm.com Closes: https://lore.kernel.org/netdev/9bdb9b9d-140a-7a28-f0de-2e64e873c068@nvidia.c... Signed-off-by: Moshe Shemesh moshe@nvidia.com Reviewed-by: Aya Levin ayal@nvidia.com Signed-off-by: Saeed Mahameed saeedm@nvidia.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/net/ethernet/mellanox/mlx5/core/lib/clock.c | 5 +++++ 1 file changed, 5 insertions(+)
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/lib/clock.c b/drivers/net/ethernet/mellanox/mlx5/core/lib/clock.c index 01b8a9648b16f..80dee8c692495 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/lib/clock.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/lib/clock.c @@ -162,10 +162,15 @@ static void mlx5_timestamp_overflow(struct work_struct *work) clock = container_of(timer, struct mlx5_clock, timer); mdev = container_of(clock, struct mlx5_core_dev, clock);
+ if (mdev->state == MLX5_DEVICE_STATE_INTERNAL_ERROR) + goto out; + write_seqlock_irqsave(&clock->lock, flags); timecounter_read(&timer->tc); mlx5_update_clock_info_page(mdev); write_sequnlock_irqrestore(&clock->lock, flags); + +out: schedule_delayed_work(&timer->overflow_work, timer->overflow_period); }
From: hackyzh002 hackyzh002@gmail.com
[ Upstream commit f828b681d0cd566f86351c0b913e6cb6ed8c7b9c ]
The type of size is unsigned, if size is 0x40000000, there will be an integer overflow, size will be zero after size *= sizeof(uint32_t), will cause uninitialized memory to be referenced later
Reviewed-by: Christian König christian.koenig@amd.com Signed-off-by: hackyzh002 hackyzh002@gmail.com Signed-off-by: Alex Deucher alexander.deucher@amd.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/gpu/drm/radeon/radeon_cs.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/radeon/radeon_cs.c b/drivers/gpu/drm/radeon/radeon_cs.c index a78b60b62caf2..87a57e5588a28 100644 --- a/drivers/gpu/drm/radeon/radeon_cs.c +++ b/drivers/gpu/drm/radeon/radeon_cs.c @@ -271,7 +271,8 @@ int radeon_cs_parser_init(struct radeon_cs_parser *p, void *data) { struct drm_radeon_cs *cs = data; uint64_t *chunk_array_ptr; - unsigned size, i; + u64 size; + unsigned i; u32 ring = RADEON_CS_RING_GFX; s32 priority = 0;
From: Oswald Buddenhagen oswald.buddenhagen@gmx.de
[ Upstream commit 8cabf83c7aa54530e699be56249fb44f9505c4f3 ]
There is no apparent reason for the massive code duplication.
Signed-off-by: Oswald Buddenhagen oswald.buddenhagen@gmx.de Link: https://lore.kernel.org/r/20230510173917.3073107-3-oswald.buddenhagen@gmx.de Signed-off-by: Takashi Iwai tiwai@suse.de Signed-off-by: Sasha Levin sashal@kernel.org --- sound/pci/emu10k1/emufx.c | 112 +++----------------------------------- 1 file changed, 9 insertions(+), 103 deletions(-)
diff --git a/sound/pci/emu10k1/emufx.c b/sound/pci/emu10k1/emufx.c index 4e76ed0e91d5d..e17b93b25d2ff 100644 --- a/sound/pci/emu10k1/emufx.c +++ b/sound/pci/emu10k1/emufx.c @@ -1560,14 +1560,8 @@ A_OP(icode, &ptr, iMAC0, A_GPR(var), A_GPR(var), A_GPR(vol), A_EXTIN(input)) gpr += 2;
/* Master volume (will be renamed later) */ - A_OP(icode, &ptr, iMAC0, A_GPR(playback+0+SND_EMU10K1_PLAYBACK_CHANNELS), A_C_00000000, A_GPR(gpr), A_GPR(playback+0+SND_EMU10K1_PLAYBACK_CHANNELS)); - A_OP(icode, &ptr, iMAC0, A_GPR(playback+1+SND_EMU10K1_PLAYBACK_CHANNELS), A_C_00000000, A_GPR(gpr), A_GPR(playback+1+SND_EMU10K1_PLAYBACK_CHANNELS)); - A_OP(icode, &ptr, iMAC0, A_GPR(playback+2+SND_EMU10K1_PLAYBACK_CHANNELS), A_C_00000000, A_GPR(gpr), A_GPR(playback+2+SND_EMU10K1_PLAYBACK_CHANNELS)); - A_OP(icode, &ptr, iMAC0, A_GPR(playback+3+SND_EMU10K1_PLAYBACK_CHANNELS), A_C_00000000, A_GPR(gpr), A_GPR(playback+3+SND_EMU10K1_PLAYBACK_CHANNELS)); - A_OP(icode, &ptr, iMAC0, A_GPR(playback+4+SND_EMU10K1_PLAYBACK_CHANNELS), A_C_00000000, A_GPR(gpr), A_GPR(playback+4+SND_EMU10K1_PLAYBACK_CHANNELS)); - A_OP(icode, &ptr, iMAC0, A_GPR(playback+5+SND_EMU10K1_PLAYBACK_CHANNELS), A_C_00000000, A_GPR(gpr), A_GPR(playback+5+SND_EMU10K1_PLAYBACK_CHANNELS)); - A_OP(icode, &ptr, iMAC0, A_GPR(playback+6+SND_EMU10K1_PLAYBACK_CHANNELS), A_C_00000000, A_GPR(gpr), A_GPR(playback+6+SND_EMU10K1_PLAYBACK_CHANNELS)); - A_OP(icode, &ptr, iMAC0, A_GPR(playback+7+SND_EMU10K1_PLAYBACK_CHANNELS), A_C_00000000, A_GPR(gpr), A_GPR(playback+7+SND_EMU10K1_PLAYBACK_CHANNELS)); + for (z = 0; z < 8; z++) + A_OP(icode, &ptr, iMAC0, A_GPR(playback+z+SND_EMU10K1_PLAYBACK_CHANNELS), A_C_00000000, A_GPR(gpr), A_GPR(playback+z+SND_EMU10K1_PLAYBACK_CHANNELS)); snd_emu10k1_init_mono_control(&controls[nctl++], "Wave Master Playback Volume", gpr, 0); gpr += 2;
@@ -1651,102 +1645,14 @@ A_OP(icode, &ptr, iMAC0, A_GPR(var), A_GPR(var), A_GPR(vol), A_EXTIN(input)) dev_dbg(emu->card->dev, "emufx.c: gpr=0x%x, tmp=0x%x\n", gpr, tmp); */ - /* For the EMU1010: How to get 32bit values from the DSP. High 16bits into L, low 16bits into R. */ - /* A_P16VIN(0) is delayed by one sample, - * so all other A_P16VIN channels will need to also be delayed - */ - /* Left ADC in. 1 of 2 */ snd_emu10k1_audigy_dsp_convert_32_to_2x16( icode, &ptr, tmp, bit_shifter16, A_P16VIN(0x0), A_FXBUS2(0) ); - /* Right ADC in 1 of 2 */ - gpr_map[gpr++] = 0x00000000; - /* Delaying by one sample: instead of copying the input - * value A_P16VIN to output A_FXBUS2 as in the first channel, - * we use an auxiliary register, delaying the value by one - * sample - */ - snd_emu10k1_audigy_dsp_convert_32_to_2x16( icode, &ptr, tmp, bit_shifter16, A_GPR(gpr - 1), A_FXBUS2(2) ); - A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0x1), A_C_00000000, A_C_00000000); - gpr_map[gpr++] = 0x00000000; - snd_emu10k1_audigy_dsp_convert_32_to_2x16( icode, &ptr, tmp, bit_shifter16, A_GPR(gpr - 1), A_FXBUS2(4) ); - A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0x2), A_C_00000000, A_C_00000000); - gpr_map[gpr++] = 0x00000000; - snd_emu10k1_audigy_dsp_convert_32_to_2x16( icode, &ptr, tmp, bit_shifter16, A_GPR(gpr - 1), A_FXBUS2(6) ); - A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0x3), A_C_00000000, A_C_00000000); - /* For 96kHz mode */ - /* Left ADC in. 2 of 2 */ - gpr_map[gpr++] = 0x00000000; - snd_emu10k1_audigy_dsp_convert_32_to_2x16( icode, &ptr, tmp, bit_shifter16, A_GPR(gpr - 1), A_FXBUS2(0x8) ); - A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0x4), A_C_00000000, A_C_00000000); - /* Right ADC in 2 of 2 */ - gpr_map[gpr++] = 0x00000000; - snd_emu10k1_audigy_dsp_convert_32_to_2x16( icode, &ptr, tmp, bit_shifter16, A_GPR(gpr - 1), A_FXBUS2(0xa) ); - A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0x5), A_C_00000000, A_C_00000000); - gpr_map[gpr++] = 0x00000000; - snd_emu10k1_audigy_dsp_convert_32_to_2x16( icode, &ptr, tmp, bit_shifter16, A_GPR(gpr - 1), A_FXBUS2(0xc) ); - A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0x6), A_C_00000000, A_C_00000000); - gpr_map[gpr++] = 0x00000000; - snd_emu10k1_audigy_dsp_convert_32_to_2x16( icode, &ptr, tmp, bit_shifter16, A_GPR(gpr - 1), A_FXBUS2(0xe) ); - A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0x7), A_C_00000000, A_C_00000000); - /* Pavel Hofman - we still have voices, A_FXBUS2s, and - * A_P16VINs available - - * let's add 8 more capture channels - total of 16 - */ - gpr_map[gpr++] = 0x00000000; - snd_emu10k1_audigy_dsp_convert_32_to_2x16(icode, &ptr, tmp, - bit_shifter16, - A_GPR(gpr - 1), - A_FXBUS2(0x10)); - A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0x8), - A_C_00000000, A_C_00000000); - gpr_map[gpr++] = 0x00000000; - snd_emu10k1_audigy_dsp_convert_32_to_2x16(icode, &ptr, tmp, - bit_shifter16, - A_GPR(gpr - 1), - A_FXBUS2(0x12)); - A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0x9), - A_C_00000000, A_C_00000000); - gpr_map[gpr++] = 0x00000000; - snd_emu10k1_audigy_dsp_convert_32_to_2x16(icode, &ptr, tmp, - bit_shifter16, - A_GPR(gpr - 1), - A_FXBUS2(0x14)); - A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0xa), - A_C_00000000, A_C_00000000); - gpr_map[gpr++] = 0x00000000; - snd_emu10k1_audigy_dsp_convert_32_to_2x16(icode, &ptr, tmp, - bit_shifter16, - A_GPR(gpr - 1), - A_FXBUS2(0x16)); - A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0xb), - A_C_00000000, A_C_00000000); - gpr_map[gpr++] = 0x00000000; - snd_emu10k1_audigy_dsp_convert_32_to_2x16(icode, &ptr, tmp, - bit_shifter16, - A_GPR(gpr - 1), - A_FXBUS2(0x18)); - A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0xc), - A_C_00000000, A_C_00000000); - gpr_map[gpr++] = 0x00000000; - snd_emu10k1_audigy_dsp_convert_32_to_2x16(icode, &ptr, tmp, - bit_shifter16, - A_GPR(gpr - 1), - A_FXBUS2(0x1a)); - A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0xd), - A_C_00000000, A_C_00000000); - gpr_map[gpr++] = 0x00000000; - snd_emu10k1_audigy_dsp_convert_32_to_2x16(icode, &ptr, tmp, - bit_shifter16, - A_GPR(gpr - 1), - A_FXBUS2(0x1c)); - A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0xe), - A_C_00000000, A_C_00000000); - gpr_map[gpr++] = 0x00000000; - snd_emu10k1_audigy_dsp_convert_32_to_2x16(icode, &ptr, tmp, - bit_shifter16, - A_GPR(gpr - 1), - A_FXBUS2(0x1e)); - A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0xf), - A_C_00000000, A_C_00000000); + /* A_P16VIN(0) is delayed by one sample, so all other A_P16VIN channels + * will need to also be delayed; we use an auxiliary register for that. */ + for (z = 1; z < 0x10; z++) { + snd_emu10k1_audigy_dsp_convert_32_to_2x16( icode, &ptr, tmp, bit_shifter16, A_GPR(gpr), A_FXBUS2(z * 2) ); + A_OP(icode, &ptr, iACC3, A_GPR(gpr), A_P16VIN(z), A_C_00000000, A_C_00000000); + gpr_map[gpr++] = 0x00000000; + } }
#if 0
From: Bard Liao yung-chuan.liao@linux.intel.com
[ Upstream commit 289e1df00e49a229a1c924c059242e759a552f01 ]
We should use RT711_JD2_100K for on board rt711.
Signed-off-by: Bard Liao <yung-chuan.liao@linux.intel.com Signed-off-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com Reviewed-by: Ranjani Sridharan <ranjani.sridharan@linux.intel.com Link: https://lore.kernel.org/r/20230512173305.65399-4-pierre-louis.bossart@linux.... Signed-off-by: Mark Brown <broonie@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- sound/soc/intel/boards/sof_sdw.c | 8 ++++++++ 1 file changed, 8 insertions(+)
diff --git a/sound/soc/intel/boards/sof_sdw.c b/sound/soc/intel/boards/sof_sdw.c index f5d8f7951cfc3..91a7cb33042d8 100644 --- a/sound/soc/intel/boards/sof_sdw.c +++ b/sound/soc/intel/boards/sof_sdw.c @@ -199,6 +199,14 @@ static const struct dmi_system_id sof_sdw_quirk_table[] = { SOF_RT715_DAI_ID_FIX | SOF_SDW_PCH_DMIC), }, + { + .callback = sof_sdw_quirk_cb, + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Intel Corporation"), + DMI_MATCH(DMI_PRODUCT_NAME, "Meteor Lake Client Platform"), + }, + .driver_data = (void *)(RT711_JD2_100K), + }, {} };
From: Peter Ujfalusi peter.ujfalusi@linux.intel.com
[ Upstream commit dfe25fea968dc4884e12d471c8263f0f611b380a ]
We should use RT711_JD2_100K for on board rt711
Signed-off-by: Peter Ujfalusi <peter.ujfalusi@linux.intel.com Signed-off-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com Reviewed-by: Bard Liao <yung-chuan.liao@linux.intel.com Link: https://lore.kernel.org/r/20230512173305.65399-9-pierre-louis.bossart@linux.... Signed-off-by: Mark Brown <broonie@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- sound/soc/intel/boards/sof_sdw.c | 9 +++++++++ 1 file changed, 9 insertions(+)
diff --git a/sound/soc/intel/boards/sof_sdw.c b/sound/soc/intel/boards/sof_sdw.c index 91a7cb33042d8..30cc8bbceb79b 100644 --- a/sound/soc/intel/boards/sof_sdw.c +++ b/sound/soc/intel/boards/sof_sdw.c @@ -207,6 +207,15 @@ static const struct dmi_system_id sof_sdw_quirk_table[] = { }, .driver_data = (void *)(RT711_JD2_100K), }, + /* LunarLake devices */ + { + .callback = sof_sdw_quirk_cb, + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Intel Corporation"), + DMI_MATCH(DMI_PRODUCT_NAME, "Lunar Lake Client Platform"), + }, + .driver_data = (void *)(RT711_JD2_100K), + }, {} };
From: Sumit Gupta sumitg@nvidia.com
[ Upstream commit 205b3d02d57ce6dce96f6d2b9c230f56a9bf9817 ]
Add check to fix the possible array out of bounds violation by making speed equal to GEN1_CORE_CLK_FREQ when its value is more than the size of "pcie_gen_freq" array. This array has size of four but possible speed (CLS) values are from "0 to 0xF". So, "speed - 1" values are "-1 to 0xE".
Suggested-by: Bjorn Helgaas helgaas@kernel.org Signed-off-by: Sumit Gupta sumitg@nvidia.com Link: https://lore.kernel.org/lkml/72b9168b-d4d6-4312-32ea-69358df2f2d0@nvidia.com... Acked-by: Lorenzo Pieralisi lpieralisi@kernel.org Signed-off-by: Thierry Reding treding@nvidia.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/pci/controller/dwc/pcie-tegra194.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-)
diff --git a/drivers/pci/controller/dwc/pcie-tegra194.c b/drivers/pci/controller/dwc/pcie-tegra194.c index 1222f5749bc67..a215777df96c7 100644 --- a/drivers/pci/controller/dwc/pcie-tegra194.c +++ b/drivers/pci/controller/dwc/pcie-tegra194.c @@ -239,6 +239,7 @@ #define EP_STATE_ENABLED 1
static const unsigned int pcie_gen_freq[] = { + GEN1_CORE_CLK_FREQ, /* PCI_EXP_LNKSTA_CLS == 0; undefined */ GEN1_CORE_CLK_FREQ, GEN2_CORE_CLK_FREQ, GEN3_CORE_CLK_FREQ, @@ -470,7 +471,11 @@ static irqreturn_t tegra_pcie_ep_irq_thread(int irq, void *arg)
speed = dw_pcie_readw_dbi(pci, pcie->pcie_cap_base + PCI_EXP_LNKSTA) & PCI_EXP_LNKSTA_CLS; - clk_set_rate(pcie->core_clk, pcie_gen_freq[speed - 1]); + + if (speed >= ARRAY_SIZE(pcie_gen_freq)) + speed = 0; + + clk_set_rate(pcie->core_clk, pcie_gen_freq[speed]);
/* If EP doesn't advertise L1SS, just return */ val = dw_pcie_readl_dbi(pci, pcie->cfg_link_cap_l1sub); @@ -973,7 +978,11 @@ static int tegra_pcie_dw_host_init(struct pcie_port *pp)
speed = dw_pcie_readw_dbi(pci, pcie->pcie_cap_base + PCI_EXP_LNKSTA) & PCI_EXP_LNKSTA_CLS; - clk_set_rate(pcie->core_clk, pcie_gen_freq[speed - 1]); + + if (speed >= ARRAY_SIZE(pcie_gen_freq)) + speed = 0; + + clk_set_rate(pcie->core_clk, pcie_gen_freq[speed]);
tegra_pcie_enable_interrupts(pp);
From: Oleksij Rempel o.rempel@pengutronix.de
[ Upstream commit 1d14bd943fa2bbdfda1efbcc080b298fed5f1803 ]
Fix USB-related warnings in prtrvt, prtvt7, prti6q and prtwd2 device trees by disabling unused usbphynop1 and usbphynop2 USB PHYs and providing proper configuration for the over-current detection. This fixes the following warnings with the current kernel: usb_phy_generic usbphynop1: dummy supplies not allowed for exclusive requests usb_phy_generic usbphynop2: dummy supplies not allowed for exclusive requests imx_usb 2184200.usb: No over current polarity defined
By the way, fix over-current detection on usbotg port for prtvt7, prti6q and prtwd2 boards. Only prtrvt do not have OC on USB OTG port.
Signed-off-by: Oleksij Rempel o.rempel@pengutronix.de Signed-off-by: Shawn Guo shawnguo@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- arch/arm/boot/dts/imx6dl-prtrvt.dts | 4 ++++ arch/arm/boot/dts/imx6qdl-prti6q.dtsi | 11 ++++++++++- 2 files changed, 14 insertions(+), 1 deletion(-)
diff --git a/arch/arm/boot/dts/imx6dl-prtrvt.dts b/arch/arm/boot/dts/imx6dl-prtrvt.dts index 5ac84445e9cc1..90e01de8c2c15 100644 --- a/arch/arm/boot/dts/imx6dl-prtrvt.dts +++ b/arch/arm/boot/dts/imx6dl-prtrvt.dts @@ -126,6 +126,10 @@ &usbh1 { status = "disabled"; };
+&usbotg { + disable-over-current; +}; + &vpu { status = "disabled"; }; diff --git a/arch/arm/boot/dts/imx6qdl-prti6q.dtsi b/arch/arm/boot/dts/imx6qdl-prti6q.dtsi index 19578f660b092..70dfa07a16981 100644 --- a/arch/arm/boot/dts/imx6qdl-prti6q.dtsi +++ b/arch/arm/boot/dts/imx6qdl-prti6q.dtsi @@ -69,6 +69,7 @@ &usbh1 { vbus-supply = <®_usb_h1_vbus>; phy_type = "utmi"; dr_mode = "host"; + disable-over-current; status = "okay"; };
@@ -78,10 +79,18 @@ &usbotg { pinctrl-0 = <&pinctrl_usbotg>; phy_type = "utmi"; dr_mode = "host"; - disable-over-current; + over-current-active-low; status = "okay"; };
+&usbphynop1 { + status = "disabled"; +}; + +&usbphynop2 { + status = "disabled"; +}; + &usdhc1 { pinctrl-names = "default"; pinctrl-0 = <&pinctrl_usdhc1>;
From: Uday M Bhat uday.m.bhat@intel.com
[ Upstream commit 164e5dc17525181c05563f0a06796f1a363801d5 ]
Add rex entry in the soundwire quirk table
Reviewed-by: Ranjani Sridharan ranjani.sridharan@linux.intel.com Signed-off-by: Bard Liao yung-chuan.liao@linux.intel.com Signed-off-by: Yong Zhi yong.zhi@intel.com Signed-off-by: Uday M Bhat uday.m.bhat@intel.com Signed-off-by: Pierre-Louis Bossart pierre-louis.bossart@linux.intel.com Link: https://lore.kernel.org/r/20230602202225.249209-28-pierre-louis.bossart@linu... Signed-off-by: Mark Brown broonie@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- sound/soc/intel/boards/sof_sdw.c | 8 ++++++++ 1 file changed, 8 insertions(+)
diff --git a/sound/soc/intel/boards/sof_sdw.c b/sound/soc/intel/boards/sof_sdw.c index 30cc8bbceb79b..cbbb50ddc7954 100644 --- a/sound/soc/intel/boards/sof_sdw.c +++ b/sound/soc/intel/boards/sof_sdw.c @@ -207,6 +207,14 @@ static const struct dmi_system_id sof_sdw_quirk_table[] = { }, .driver_data = (void *)(RT711_JD2_100K), }, + { + .callback = sof_sdw_quirk_cb, + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Google"), + DMI_MATCH(DMI_PRODUCT_NAME, "Rex"), + }, + .driver_data = (void *)(SOF_SDW_PCH_DMIC), + }, /* LunarLake devices */ { .callback = sof_sdw_quirk_cb,
From: Geert Uytterhoeven geert+renesas@glider.be
[ Upstream commit b407460ee99033503993ac7437d593451fcdfe44 ]
It is considered good practice to call cpu_relax() in busy loops, see Documentation/process/volatile-considered-harmful.rst. This can not only lower CPU power consumption or yield to a hyperthreaded twin processor, but also allows an architecture to mitigate hardware issues (e.g. ARM Erratum 754327 for Cortex-A9 prior to r2p0) in the architecture-specific cpu_relax() implementation.
In addition, cpu_relax() is also a compiler barrier. It is not immediately obvious that the @op argument "function" will result in an actual function call (e.g. in case of inlining).
Where a function call is a C sequence point, this is lost on inlining. Therefore, with agressive enough optimization it might be possible for the compiler to hoist the:
(val) = op(args);
"load" out of the loop because it doesn't see the value changing. The addition of cpu_relax() would inhibit this.
As the iopoll helpers lack calls to cpu_relax(), people are sometimes reluctant to use them, and may fall back to open-coded polling loops (including cpu_relax() calls) instead.
Fix this by adding calls to cpu_relax() to the iopoll helpers: - For the non-atomic case, it is sufficient to call cpu_relax() in case of a zero sleep-between-reads value, as a call to usleep_range() is a safe barrier otherwise. However, it doesn't hurt to add the call regardless, for simplicity, and for similarity with the atomic case below. - For the atomic case, cpu_relax() must be called regardless of the sleep-between-reads value, as there is no guarantee all architecture-specific implementations of udelay() handle this.
Signed-off-by: Geert Uytterhoeven geert+renesas@glider.be Acked-by: Peter Zijlstra (Intel) peterz@infradead.org Acked-by: Arnd Bergmann arnd@arndb.de Reviewed-by: Tony Lindgren tony@atomide.com Reviewed-by: Ulf Hansson ulf.hansson@linaro.org Link: https://lore.kernel.org/r/45c87bec3397fdd704376807f0eec5cc71be440f.168569281... Signed-off-by: Sasha Levin sashal@kernel.org --- include/linux/iopoll.h | 2 ++ 1 file changed, 2 insertions(+)
diff --git a/include/linux/iopoll.h b/include/linux/iopoll.h index 2c8860e406bd8..0417360a6db9b 100644 --- a/include/linux/iopoll.h +++ b/include/linux/iopoll.h @@ -53,6 +53,7 @@ } \ if (__sleep_us) \ usleep_range((__sleep_us >> 2) + 1, __sleep_us); \ + cpu_relax(); \ } \ (cond) ? 0 : -ETIMEDOUT; \ }) @@ -95,6 +96,7 @@ } \ if (__delay_us) \ udelay(__delay_us); \ + cpu_relax(); \ } \ (cond) ? 0 : -ETIMEDOUT; \ })
From: Jan Kara jack@suse.cz
[ Upstream commit 6a4e3363792e30177cc3965697e34ddcea8b900b ]
When add_dquot_ref() fails (usually due to IO error or ENOMEM), we want to disable quotas we are trying to enable. However dquot_disable() call was passed just the flags we are enabling so in case flags == DQUOT_USAGE_ENABLED dquot_disable() call will just fail with EINVAL instead of properly disabling quotas. Fix the problem by always passing DQUOT_LIMITS_ENABLED | DQUOT_USAGE_ENABLED to dquot_disable() in this case.
Reported-and-tested-by: Ye Bin yebin10@huawei.com Reported-by: syzbot+e633c79ceaecbf479854@syzkaller.appspotmail.com Signed-off-by: Jan Kara jack@suse.cz Message-Id: 20230605140731.2427629-2-yebin10@huawei.com Signed-off-by: Sasha Levin sashal@kernel.org --- fs/quota/dquot.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/fs/quota/dquot.c b/fs/quota/dquot.c index ad255f8ab5c55..135984a1a52f4 100644 --- a/fs/quota/dquot.c +++ b/fs/quota/dquot.c @@ -2415,7 +2415,8 @@ int dquot_load_quota_sb(struct super_block *sb, int type, int format_id,
error = add_dquot_ref(sb, type); if (error) - dquot_disable(sb, type, flags); + dquot_disable(sb, type, + DQUOT_USAGE_ENABLED | DQUOT_LIMITS_ENABLED);
return error; out_fmt:
From: Ye Bin yebin10@huawei.com
[ Upstream commit d6a95db3c7ad160bc16b89e36449705309b52bcb ]
There's issue as follows when do fault injection: WARNING: CPU: 1 PID: 14870 at include/linux/quotaops.h:51 dquot_disable+0x13b7/0x18c0 Modules linked in: CPU: 1 PID: 14870 Comm: fsconfig Not tainted 6.3.0-next-20230505-00006-g5107a9c821af-dirty #541 RIP: 0010:dquot_disable+0x13b7/0x18c0 RSP: 0018:ffffc9000acc79e0 EFLAGS: 00010246 RAX: 0000000000000000 RBX: 0000000000000000 RCX: ffff88825e41b980 RDX: 0000000000000000 RSI: ffff88825e41b980 RDI: 0000000000000002 RBP: ffff888179f68000 R08: ffffffff82087ca7 R09: 0000000000000000 R10: 0000000000000001 R11: ffffed102f3ed026 R12: ffff888179f68130 R13: ffff888179f68110 R14: dffffc0000000000 R15: ffff888179f68118 FS: 00007f450a073740(0000) GS:ffff88882fc00000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: 00007ffe96f2efd8 CR3: 000000025c8ad000 CR4: 00000000000006e0 DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400 Call Trace: <TASK> dquot_load_quota_sb+0xd53/0x1060 dquot_resume+0x172/0x230 ext4_reconfigure+0x1dc6/0x27b0 reconfigure_super+0x515/0xa90 __x64_sys_fsconfig+0xb19/0xd20 do_syscall_64+0x39/0xb0 entry_SYSCALL_64_after_hwframe+0x63/0xcd
Above issue may happens as follows: ProcessA ProcessB ProcessC sys_fsconfig vfs_fsconfig_locked reconfigure_super ext4_remount dquot_suspend -> suspend all type quota
sys_fsconfig vfs_fsconfig_locked reconfigure_super ext4_remount dquot_resume ret = dquot_load_quota_sb add_dquot_ref do_open -> open file O_RDWR vfs_open do_dentry_open get_write_access atomic_inc_unless_negative(&inode->i_writecount) ext4_file_open dquot_file_open dquot_initialize __dquot_initialize dqget atomic_inc(&dquot->dq_count);
__dquot_initialize __dquot_initialize dqget if (!test_bit(DQ_ACTIVE_B, &dquot->dq_flags)) ext4_acquire_dquot -> Return error DQ_ACTIVE_B flag isn't set dquot_disable invalidate_dquots if (atomic_read(&dquot->dq_count)) dqgrab WARN_ON_ONCE(!test_bit(DQ_ACTIVE_B, &dquot->dq_flags)) -> Trigger warning
In the above scenario, 'dquot->dq_flags' has no DQ_ACTIVE_B is normal when dqgrab(). To solve above issue just replace the dqgrab() use in invalidate_dquots() with atomic_inc(&dquot->dq_count).
Signed-off-by: Ye Bin yebin10@huawei.com Signed-off-by: Jan Kara jack@suse.cz Message-Id: 20230605140731.2427629-3-yebin10@huawei.com Signed-off-by: Sasha Levin sashal@kernel.org --- fs/quota/dquot.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/fs/quota/dquot.c b/fs/quota/dquot.c index 135984a1a52f4..8d0cd68fc90a4 100644 --- a/fs/quota/dquot.c +++ b/fs/quota/dquot.c @@ -557,7 +557,7 @@ static void invalidate_dquots(struct super_block *sb, int type) continue; /* Wait for dquot users */ if (atomic_read(&dquot->dq_count)) { - dqgrab(dquot); + atomic_inc(&dquot->dq_count); spin_unlock(&dq_list_lock); /* * Once dqput() wakes us up, we know it's time to free
From: gaoxu gaoxu2@hihonor.com
[ Upstream commit 51ff97d54f02b4444dfc42e380ac4c058e12d5dd ]
If dma_direct_alloc() alloc memory in size of 64MB, the inner function dma_common_contiguous_remap() will allocate 128KB memory by invoking the function kmalloc_array(). and the kmalloc_array seems to fail to try to allocate 128KB mem.
Call trace: [14977.928623] qcrosvm: page allocation failure: order:5, mode:0x40cc0 [14977.928638] dump_backtrace.cfi_jt+0x0/0x8 [14977.928647] dump_stack_lvl+0x80/0xb8 [14977.928652] warn_alloc+0x164/0x200 [14977.928657] __alloc_pages_slowpath+0x9f0/0xb4c [14977.928660] __alloc_pages+0x21c/0x39c [14977.928662] kmalloc_order+0x48/0x108 [14977.928666] kmalloc_order_trace+0x34/0x154 [14977.928668] __kmalloc+0x548/0x7e4 [14977.928673] dma_direct_alloc+0x11c/0x4f8 [14977.928678] dma_alloc_attrs+0xf4/0x138 [14977.928680] gh_vm_ioctl_set_fw_name+0x3c4/0x610 [gunyah] [14977.928698] gh_vm_ioctl+0x90/0x14c [gunyah] [14977.928705] __arm64_sys_ioctl+0x184/0x210
work around by doing kvmalloc_array instead.
Signed-off-by: Gao Xu gaoxu2@hihonor.com Reviewed-by: Suren Baghdasaryan surenb@google.com Signed-off-by: Christoph Hellwig hch@lst.de Signed-off-by: Sasha Levin sashal@kernel.org --- kernel/dma/remap.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/kernel/dma/remap.c b/kernel/dma/remap.c index 905c3fa005f10..5bff061993102 100644 --- a/kernel/dma/remap.c +++ b/kernel/dma/remap.c @@ -43,13 +43,13 @@ void *dma_common_contiguous_remap(struct page *page, size_t size, void *vaddr; int i;
- pages = kmalloc_array(count, sizeof(struct page *), GFP_KERNEL); + pages = kvmalloc_array(count, sizeof(struct page *), GFP_KERNEL); if (!pages) return NULL; for (i = 0; i < count; i++) pages[i] = nth_page(page, i); vaddr = vmap(pages, count, VM_DMA_COHERENT, prot); - kfree(pages); + kvfree(pages);
return vaddr; }
From: Lang Yu Lang.Yu@amd.com
[ Upstream commit 187916e6ed9d0c3b3abc27429f7a5f8c936bd1f0 ]
When using cpu to update page tables, vm update fences are unused. Install stub fence into these fence pointers instead of NULL to avoid NULL dereference when calling dma_fence_wait() on them.
Suggested-by: Christian König christian.koenig@amd.com Signed-off-by: Lang Yu Lang.Yu@amd.com Reviewed-by: Christian König christian.koenig@amd.com Signed-off-by: Alex Deucher alexander.deucher@amd.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c index 8445bb7ae06ab..3b4724d60868f 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c @@ -2155,6 +2155,7 @@ struct amdgpu_bo_va *amdgpu_vm_bo_add(struct amdgpu_device *adev, amdgpu_vm_bo_base_init(&bo_va->base, vm, bo);
bo_va->ref_count = 1; + bo_va->last_pt_update = dma_fence_get_stub(); INIT_LIST_HEAD(&bo_va->valids); INIT_LIST_HEAD(&bo_va->invalids);
@@ -2867,7 +2868,8 @@ int amdgpu_vm_init(struct amdgpu_device *adev, struct amdgpu_vm *vm, vm->update_funcs = &amdgpu_vm_cpu_funcs; else vm->update_funcs = &amdgpu_vm_sdma_funcs; - vm->last_update = NULL; + + vm->last_update = dma_fence_get_stub(); vm->last_unlocked = dma_fence_get_stub();
mutex_init(&vm->eviction_lock); @@ -3042,7 +3044,7 @@ int amdgpu_vm_make_compute(struct amdgpu_device *adev, struct amdgpu_vm *vm, vm->update_funcs = &amdgpu_vm_sdma_funcs; } dma_fence_put(vm->last_update); - vm->last_update = NULL; + vm->last_update = dma_fence_get_stub(); vm->is_compute_context = true;
if (vm->pasid) {
From: Marco Morandini marco.morandini@polimi.it
[ Upstream commit 0db117359e47750d8bd310d19f13e1c4ef7fc26a ]
HP Elite Presenter Mouse HID Record Descriptor shows two mouses (Repord ID 0x1 and 0x2), one keypad (Report ID 0x5), two Consumer Controls (Report IDs 0x6 and 0x3). Previous to this commit it registers one mouse, one keypad and one Consumer Control, and it was usable only as a digitl laser pointer (one of the two mouses). This patch defines the 464a USB device ID and enables the HID_QUIRK_MULTI_INPUT quirk for it, allowing to use the device both as a mouse and a digital laser pointer.
Signed-off-by: Marco Morandini marco.morandini@polimi.it Signed-off-by: Jiri Kosina jkosina@suse.cz Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/hid/hid-ids.h | 1 + drivers/hid/hid-quirks.c | 1 + 2 files changed, 2 insertions(+)
diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h index 2b658d820b800..6712d99ad80da 100644 --- a/drivers/hid/hid-ids.h +++ b/drivers/hid/hid-ids.h @@ -582,6 +582,7 @@ #define USB_DEVICE_ID_UGCI_FIGHTING 0x0030
#define USB_VENDOR_ID_HP 0x03f0 +#define USB_PRODUCT_ID_HP_ELITE_PRESENTER_MOUSE_464A 0x464a #define USB_PRODUCT_ID_HP_LOGITECH_OEM_USB_OPTICAL_MOUSE_0A4A 0x0a4a #define USB_PRODUCT_ID_HP_LOGITECH_OEM_USB_OPTICAL_MOUSE_0B4A 0x0b4a #define USB_PRODUCT_ID_HP_PIXART_OEM_USB_OPTICAL_MOUSE 0x134a diff --git a/drivers/hid/hid-quirks.c b/drivers/hid/hid-quirks.c index 9f1fcbea19eb7..4229e5de06745 100644 --- a/drivers/hid/hid-quirks.c +++ b/drivers/hid/hid-quirks.c @@ -96,6 +96,7 @@ static const struct hid_device_id hid_quirks[] = { { HID_USB_DEVICE(USB_VENDOR_ID_HOLTEK_ALT, USB_DEVICE_ID_HOLTEK_ALT_KEYBOARD_A096), HID_QUIRK_NO_INIT_REPORTS }, { HID_USB_DEVICE(USB_VENDOR_ID_HOLTEK_ALT, USB_DEVICE_ID_HOLTEK_ALT_KEYBOARD_A293), HID_QUIRK_ALWAYS_POLL }, { HID_USB_DEVICE(USB_VENDOR_ID_HP, USB_PRODUCT_ID_HP_LOGITECH_OEM_USB_OPTICAL_MOUSE_0A4A), HID_QUIRK_ALWAYS_POLL }, + { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_HP, USB_PRODUCT_ID_HP_ELITE_PRESENTER_MOUSE_464A), HID_QUIRK_MULTI_INPUT }, { HID_USB_DEVICE(USB_VENDOR_ID_HP, USB_PRODUCT_ID_HP_LOGITECH_OEM_USB_OPTICAL_MOUSE_0B4A), HID_QUIRK_ALWAYS_POLL }, { HID_USB_DEVICE(USB_VENDOR_ID_HP, USB_PRODUCT_ID_HP_PIXART_OEM_USB_OPTICAL_MOUSE), HID_QUIRK_ALWAYS_POLL }, { HID_USB_DEVICE(USB_VENDOR_ID_HP, USB_PRODUCT_ID_HP_PIXART_OEM_USB_OPTICAL_MOUSE_094A), HID_QUIRK_ALWAYS_POLL },
From: Patrisious Haddad phaddad@nvidia.com
[ Upstream commit 22664c06e997087fe37f9ba208008c948571214a ]
Previously when destroying a QP/RQ, the result of the firmware destruction function was ignored and upper layers weren't informed about the failure. Which in turn could lead to various problems since when upper layer isn't aware of the failure it continues its operation thinking that the related QP/RQ was successfully destroyed while it actually wasn't, which could lead to the below kernel WARN.
Currently, we return the correct firmware destruction status to upper layers which in case of the RQ would be mlx5_ib_destroy_wq() which was already capable of handling RQ destruction failure or in case of a QP to destroy_qp_common(), which now would actually warn upon qp destruction failure.
WARNING: CPU: 3 PID: 995 at drivers/infiniband/core/rdma_core.c:940 uverbs_destroy_ufile_hw+0xcb/0xe0 [ib_uverbs] Modules linked in: xt_conntrack xt_MASQUERADE nf_conntrack_netlink nfnetlink xt_addrtype iptable_nat nf_nat br_netfilter rpcrdma rdma_ucm ib_iser libiscsi scsi_transport_iscsi rdma_cm ib_umad ib_ipoib iw_cm ib_cm mlx5_ib ib_uverbs ib_core overlay mlx5_core fuse CPU: 3 PID: 995 Comm: python3 Not tainted 5.16.0-rc5+ #1 Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS rel-1.13.0-0-gf21b5a4aeb02-prebuilt.qemu.org 04/01/2014 RIP: 0010:uverbs_destroy_ufile_hw+0xcb/0xe0 [ib_uverbs] Code: 41 5c 41 5d 41 5e e9 44 34 f0 e0 48 89 df e8 4c 77 ff ff 49 8b 86 10 01 00 00 48 85 c0 74 a1 4c 89 e7 ff d0 eb 9a 0f 0b eb c1 <0f> 0b be 04 00 00 00 48 89 df e8 b6 f6 ff ff e9 75 ff ff ff 90 0f RSP: 0018:ffff8881533e3e78 EFLAGS: 00010287 RAX: ffff88811b2cf3e0 RBX: ffff888106209700 RCX: 0000000000000000 RDX: ffff888106209780 RSI: ffff8881533e3d30 RDI: ffff888109b101a0 RBP: 0000000000000001 R08: ffff888127cb381c R09: 0de9890000000009 R10: ffff888127cb3800 R11: 0000000000000000 R12: ffff888106209780 R13: ffff888106209750 R14: ffff888100f20660 R15: 0000000000000000 FS: 00007f8be353b740(0000) GS:ffff88852c980000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: 00007f8bd5b117c0 CR3: 000000012cd8a004 CR4: 0000000000370ea0 DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400 Call Trace: <TASK> ib_uverbs_close+0x1a/0x90 [ib_uverbs] __fput+0x82/0x230 task_work_run+0x59/0x90 exit_to_user_mode_prepare+0x138/0x140 syscall_exit_to_user_mode+0x1d/0x50 ? __x64_sys_close+0xe/0x40 do_syscall_64+0x4a/0x90 entry_SYSCALL_64_after_hwframe+0x44/0xae RIP: 0033:0x7f8be3ae0abb Code: 03 00 00 00 0f 05 48 3d 00 f0 ff ff 77 41 c3 48 83 ec 18 89 7c 24 0c e8 83 43 f9 ff 8b 7c 24 0c 41 89 c0 b8 03 00 00 00 0f 05 <48> 3d 00 f0 ff ff 77 35 44 89 c7 89 44 24 0c e8 c1 43 f9 ff 8b 44 RSP: 002b:00007ffdb51909c0 EFLAGS: 00000293 ORIG_RAX: 0000000000000003 RAX: 0000000000000000 RBX: 0000557bb7f7c020 RCX: 00007f8be3ae0abb RDX: 0000557bb7c74010 RSI: 0000557bb7f14ca0 RDI: 0000000000000005 RBP: 0000557bb7fbd598 R08: 0000000000000000 R09: 0000000000000000 R10: 0000000000000000 R11: 0000000000000293 R12: 0000557bb7fbd5b8 R13: 0000557bb7fbd5a8 R14: 0000000000001000 R15: 0000557bb7f7c020 </TASK>
Signed-off-by: Patrisious Haddad phaddad@nvidia.com Link: https://lore.kernel.org/r/c6df677f931d18090bafbe7f7dbb9524047b7d9b.168595349... Signed-off-by: Leon Romanovsky leon@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/infiniband/hw/mlx5/qpc.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-)
diff --git a/drivers/infiniband/hw/mlx5/qpc.c b/drivers/infiniband/hw/mlx5/qpc.c index c683d7000168d..9a306da7f9496 100644 --- a/drivers/infiniband/hw/mlx5/qpc.c +++ b/drivers/infiniband/hw/mlx5/qpc.c @@ -297,8 +297,7 @@ int mlx5_core_destroy_qp(struct mlx5_ib_dev *dev, struct mlx5_core_qp *qp) MLX5_SET(destroy_qp_in, in, opcode, MLX5_CMD_OP_DESTROY_QP); MLX5_SET(destroy_qp_in, in, qpn, qp->qpn); MLX5_SET(destroy_qp_in, in, uid, qp->uid); - mlx5_cmd_exec_in(dev->mdev, destroy_qp, in); - return 0; + return mlx5_cmd_exec_in(dev->mdev, destroy_qp, in); }
int mlx5_core_set_delay_drop(struct mlx5_ib_dev *dev, @@ -542,14 +541,14 @@ int mlx5_core_xrcd_dealloc(struct mlx5_ib_dev *dev, u32 xrcdn) return mlx5_cmd_exec_in(dev->mdev, dealloc_xrcd, in); }
-static void destroy_rq_tracked(struct mlx5_ib_dev *dev, u32 rqn, u16 uid) +static int destroy_rq_tracked(struct mlx5_ib_dev *dev, u32 rqn, u16 uid) { u32 in[MLX5_ST_SZ_DW(destroy_rq_in)] = {};
MLX5_SET(destroy_rq_in, in, opcode, MLX5_CMD_OP_DESTROY_RQ); MLX5_SET(destroy_rq_in, in, rqn, rqn); MLX5_SET(destroy_rq_in, in, uid, uid); - mlx5_cmd_exec_in(dev->mdev, destroy_rq, in); + return mlx5_cmd_exec_in(dev->mdev, destroy_rq, in); }
int mlx5_core_create_rq_tracked(struct mlx5_ib_dev *dev, u32 *in, int inlen, @@ -580,8 +579,7 @@ int mlx5_core_destroy_rq_tracked(struct mlx5_ib_dev *dev, struct mlx5_core_qp *rq) { destroy_resource_common(dev, rq); - destroy_rq_tracked(dev, rq->qpn, rq->uid); - return 0; + return destroy_rq_tracked(dev, rq->qpn, rq->uid); }
static void destroy_sq_tracked(struct mlx5_ib_dev *dev, u32 sqn, u16 uid)
From: Christian Brauner brauner@kernel.org
[ Upstream commit f723edb8a532cd26e1ff0a2b271d73762d48f762 ]
Porting overlayfs to the new amount api I started experiencing random crashes that couldn't be explained easily. So after much debugging and reasoning it became clear that struct ovl_entry requires the point to struct vfsmount to be the first member and of type struct vfsmount.
During the port I added a new member at the beginning of struct ovl_entry which broke all over the place in the form of random crashes and cache corruptions. While there's a comment in ovl_free_fs() to the effect of "Hack! Reuse ofs->layers as a vfsmount array before freeing it" there's no such comment on struct ovl_entry which makes this easy to trip over.
Add a comment and two static asserts for both the offset and the type of pointer in struct ovl_entry.
Signed-off-by: Christian Brauner brauner@kernel.org Signed-off-by: Amir Goldstein amir73il@gmail.com Signed-off-by: Sasha Levin sashal@kernel.org --- fs/overlayfs/ovl_entry.h | 9 +++++++++ 1 file changed, 9 insertions(+)
diff --git a/fs/overlayfs/ovl_entry.h b/fs/overlayfs/ovl_entry.h index b208eba5d0b64..b58a0140d78d5 100644 --- a/fs/overlayfs/ovl_entry.h +++ b/fs/overlayfs/ovl_entry.h @@ -30,6 +30,7 @@ struct ovl_sb { };
struct ovl_layer { + /* ovl_free_fs() relies on @mnt being the first member! */ struct vfsmount *mnt; /* Trap in ovl inode cache */ struct inode *trap; @@ -40,6 +41,14 @@ struct ovl_layer { int fsid; };
+/* + * ovl_free_fs() relies on @mnt being the first member when unmounting + * the private mounts created for each layer. Let's check both the + * offset and type. + */ +static_assert(offsetof(struct ovl_layer, mnt) == 0); +static_assert(__same_type(typeof_member(struct ovl_layer, mnt), struct vfsmount *)); + struct ovl_path { const struct ovl_layer *layer; struct dentry *dentry;
From: Jan Kara jack@suse.cz
[ Upstream commit 028f6055c912588e6f72722d89c30b401bbcf013 ]
For filenames that begin with . and are between 2 and 5 characters long, UDF charset conversion code would read uninitialized memory in the output buffer. The only practical impact is that the name may be prepended a "unification hash" when it is not actually needed but still it is good to fix this.
Reported-by: syzbot+cd311b1e43cc25f90d18@syzkaller.appspotmail.com Link: https://lore.kernel.org/all/000000000000e2638a05fe9dc8f9@google.com Signed-off-by: Jan Kara jack@suse.cz Signed-off-by: Sasha Levin sashal@kernel.org --- fs/udf/unicode.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/fs/udf/unicode.c b/fs/udf/unicode.c index 622569007b530..2142cbd1dde24 100644 --- a/fs/udf/unicode.c +++ b/fs/udf/unicode.c @@ -247,7 +247,7 @@ static int udf_name_from_CS0(struct super_block *sb, }
if (translate) { - if (str_o_len <= 2 && str_o[0] == '.' && + if (str_o_len > 0 && str_o_len <= 2 && str_o[0] == '.' && (str_o_len == 1 || str_o[1] == '.')) needsCRC = 1; if (needsCRC) {
From: Yogesh yogi.kernel@gmail.com
[ Upstream commit 4e302336d5ca1767a06beee7596a72d3bdc8d983 ]
Syzkaller reported the following issue:
UBSAN: array-index-out-of-bounds in fs/jfs/jfs_dmap.c:1965:6 index -84 is out of range for type 's8[341]' (aka 'signed char[341]') CPU: 1 PID: 4995 Comm: syz-executor146 Not tainted 6.4.0-rc6-syzkaller-00037-gb6dad5178cea #0 Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 05/27/2023 Call Trace: <TASK> __dump_stack lib/dump_stack.c:88 [inline] dump_stack_lvl+0x1e7/0x2d0 lib/dump_stack.c:106 ubsan_epilogue lib/ubsan.c:217 [inline] __ubsan_handle_out_of_bounds+0x11c/0x150 lib/ubsan.c:348 dbAllocDmapLev+0x3e5/0x430 fs/jfs/jfs_dmap.c:1965 dbAllocCtl+0x113/0x920 fs/jfs/jfs_dmap.c:1809 dbAllocAG+0x28f/0x10b0 fs/jfs/jfs_dmap.c:1350 dbAlloc+0x658/0xca0 fs/jfs/jfs_dmap.c:874 dtSplitUp fs/jfs/jfs_dtree.c:974 [inline] dtInsert+0xda7/0x6b00 fs/jfs/jfs_dtree.c:863 jfs_create+0x7b6/0xbb0 fs/jfs/namei.c:137 lookup_open fs/namei.c:3492 [inline] open_last_lookups fs/namei.c:3560 [inline] path_openat+0x13df/0x3170 fs/namei.c:3788 do_filp_open+0x234/0x490 fs/namei.c:3818 do_sys_openat2+0x13f/0x500 fs/open.c:1356 do_sys_open fs/open.c:1372 [inline] __do_sys_openat fs/open.c:1388 [inline] __se_sys_openat fs/open.c:1383 [inline] __x64_sys_openat+0x247/0x290 fs/open.c:1383 do_syscall_x64 arch/x86/entry/common.c:50 [inline] do_syscall_64+0x41/0xc0 arch/x86/entry/common.c:80 entry_SYSCALL_64_after_hwframe+0x63/0xcd RIP: 0033:0x7f1f4e33f7e9 Code: 28 00 00 00 75 05 48 83 c4 28 c3 e8 51 14 00 00 90 48 89 f8 48 89 f7 48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 4c 24 08 0f 05 <48> 3d 01 f0 ff ff 73 01 c3 48 c7 c1 c0 ff ff ff f7 d8 64 89 01 48 RSP: 002b:00007ffc21129578 EFLAGS: 00000246 ORIG_RAX: 0000000000000101 RAX: ffffffffffffffda RBX: 0000000000000000 RCX: 00007f1f4e33f7e9 RDX: 000000000000275a RSI: 0000000020000040 RDI: 00000000ffffff9c RBP: 00007f1f4e2ff080 R08: 0000000000000000 R09: 0000000000000000 R10: 0000000000000000 R11: 0000000000000246 R12: 00007f1f4e2ff110 R13: 0000000000000000 R14: 0000000000000000 R15: 0000000000000000 </TASK>
The bug occurs when the dbAllocDmapLev()function attempts to access dp->tree.stree[leafidx + LEAFIND] while the leafidx value is negative.
To rectify this, the patch introduces a safeguard within the dbAllocDmapLev() function. A check has been added to verify if leafidx is negative. If it is, the function immediately returns an I/O error, preventing any further execution that could potentially cause harm.
Tested via syzbot.
Reported-by: syzbot+853a6f4dfa3cf37d3aea@syzkaller.appspotmail.com Link: https://syzkaller.appspot.com/bug?extid=ae2f5a27a07ae44b0f17 Signed-off-by: Yogesh yogi.kernel@gmail.com Signed-off-by: Dave Kleikamp dave.kleikamp@oracle.com Signed-off-by: Sasha Levin sashal@kernel.org --- fs/jfs/jfs_dmap.c | 3 +++ 1 file changed, 3 insertions(+)
diff --git a/fs/jfs/jfs_dmap.c b/fs/jfs/jfs_dmap.c index bd9af2be352fc..cef3303d94995 100644 --- a/fs/jfs/jfs_dmap.c +++ b/fs/jfs/jfs_dmap.c @@ -2027,6 +2027,9 @@ dbAllocDmapLev(struct bmap * bmp, if (dbFindLeaf((dmtree_t *) & dp->tree, l2nb, &leafidx)) return -ENOSPC;
+ if (leafidx < 0) + return -EIO; + /* determine the block number within the file system corresponding * to the leaf at which free space was found. */
From: Gustavo A. R. Silva gustavoars@kernel.org
[ Upstream commit 7b191b9b55df2a844bd32d1d380f47a7df1c2896 ]
Zero-length arrays are deprecated, and we are replacing them with flexible array members instead. So, replace zero-length array with flexible-array member in struct memmap.
Address the following warning found after building (with GCC-13) mips64 with decstation_64_defconfig: In function 'rex_setup_memory_region', inlined from 'prom_meminit' at arch/mips/dec/prom/memory.c:91:3: arch/mips/dec/prom/memory.c:72:31: error: array subscript i is outside array bounds of 'unsigned char[0]' [-Werror=array-bounds=] 72 | if (bm->bitmap[i] == 0xff) | ~~~~~~~~~~^~~ In file included from arch/mips/dec/prom/memory.c:16: ./arch/mips/include/asm/dec/prom.h: In function 'prom_meminit': ./arch/mips/include/asm/dec/prom.h:73:23: note: while referencing 'bitmap' 73 | unsigned char bitmap[0];
This helps with the ongoing efforts to globally enable -Warray-bounds.
This results in no differences in binary output.
Link: https://github.com/KSPP/linux/issues/79 Link: https://github.com/KSPP/linux/issues/323 Signed-off-by: Gustavo A. R. Silva gustavoars@kernel.org Signed-off-by: Thomas Bogendoerfer tsbogend@alpha.franken.de Signed-off-by: Sasha Levin sashal@kernel.org --- arch/mips/include/asm/dec/prom.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/arch/mips/include/asm/dec/prom.h b/arch/mips/include/asm/dec/prom.h index 1e1247add1cf8..908e96e3a3117 100644 --- a/arch/mips/include/asm/dec/prom.h +++ b/arch/mips/include/asm/dec/prom.h @@ -70,7 +70,7 @@ static inline bool prom_is_rex(u32 magic) */ typedef struct { int pagesize; - unsigned char bitmap[0]; + unsigned char bitmap[]; } memmap;
From: Immad Mir mirimmad17@gmail.com
[ Upstream commit 47cfdc338d674d38f4b2f22b7612cc6a2763ba27 ]
Syzkaller reported an issue where txBegin may be called on a superblock in a read-only mounted filesystem which leads to NULL pointer deref. This could be solved by checking if the filesystem is read-only before calling txBegin, and returning with appropiate error code.
Reported-By: syzbot+f1faa20eec55e0c8644c@syzkaller.appspotmail.com Link: https://syzkaller.appspot.com/bug?id=be7e52c50c5182cc09a09ea6fc456446b2039de...
Signed-off-by: Immad Mir mirimmad17@gmail.com Signed-off-by: Dave Kleikamp dave.kleikamp@oracle.com Signed-off-by: Sasha Levin sashal@kernel.org --- fs/jfs/namei.c | 5 +++++ 1 file changed, 5 insertions(+)
diff --git a/fs/jfs/namei.c b/fs/jfs/namei.c index 7a55d14cc1af0..f155ad6650bd4 100644 --- a/fs/jfs/namei.c +++ b/fs/jfs/namei.c @@ -798,6 +798,11 @@ static int jfs_link(struct dentry *old_dentry, if (rc) goto out;
+ if (isReadOnly(ip)) { + jfs_error(ip->i_sb, "read-only filesystem\n"); + return -EROFS; + } + tid = txBegin(ip->i_sb, 0);
mutex_lock_nested(&JFS_IP(dir)->commit_mutex, COMMIT_MUTEX_PARENT);
From: Immad Mir mirimmad17@gmail.com
[ Upstream commit 95e2b352c03b0a86c5717ba1d24ea20969abcacc ]
This patch adds a check for read-only mounted filesystem in txBegin before starting a transaction potentially saving from NULL pointer deref.
Signed-off-by: Immad Mir mirimmad17@gmail.com Signed-off-by: Dave Kleikamp dave.kleikamp@oracle.com Signed-off-by: Sasha Levin sashal@kernel.org --- fs/jfs/jfs_txnmgr.c | 5 +++++ 1 file changed, 5 insertions(+)
diff --git a/fs/jfs/jfs_txnmgr.c b/fs/jfs/jfs_txnmgr.c index c8ce7f1bc5942..6f6a5b9203d3f 100644 --- a/fs/jfs/jfs_txnmgr.c +++ b/fs/jfs/jfs_txnmgr.c @@ -354,6 +354,11 @@ tid_t txBegin(struct super_block *sb, int flag) jfs_info("txBegin: flag = 0x%x", flag); log = JFS_SBI(sb)->log;
+ if (!log) { + jfs_error(sb, "read-only filesystem\n"); + return 0; + } + TXN_LOCK();
INCREMENT(TxStat.txBegin);
From: Yunfei Dong yunfei.dong@mediatek.com
[ Upstream commit 56b5c3e67b0f9af3f45cf393be048ee8d8a92694 ]
Getting below error when using KCSAN to check the driver. Adding lock to protect parameter num_rdy when getting the value with function: v4l2_m2m_num_src_bufs_ready/v4l2_m2m_num_dst_bufs_ready.
kworker/u16:3: [name:report&]BUG: KCSAN: data-race in v4l2_m2m_buf_queue kworker/u16:3: [name:report&]
kworker/u16:3: [name:report&]read-write to 0xffffff8105f35b94 of 1 bytes by task 20865 on cpu 7: kworker/u16:3:Â v4l2_m2m_buf_queue+0xd8/0x10c
Signed-off-by: Pina Chen pina.chen@mediatek.com Signed-off-by: Yunfei Dong yunfei.dong@mediatek.com Signed-off-by: Hans Verkuil hverkuil-cisco@xs4all.nl Signed-off-by: Sasha Levin sashal@kernel.org --- include/media/v4l2-mem2mem.h | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-)
diff --git a/include/media/v4l2-mem2mem.h b/include/media/v4l2-mem2mem.h index 5a91b548ecc0c..8d52c4506762d 100644 --- a/include/media/v4l2-mem2mem.h +++ b/include/media/v4l2-mem2mem.h @@ -588,7 +588,14 @@ void v4l2_m2m_buf_queue(struct v4l2_m2m_ctx *m2m_ctx, static inline unsigned int v4l2_m2m_num_src_bufs_ready(struct v4l2_m2m_ctx *m2m_ctx) { - return m2m_ctx->out_q_ctx.num_rdy; + unsigned int num_buf_rdy; + unsigned long flags; + + spin_lock_irqsave(&m2m_ctx->out_q_ctx.rdy_spinlock, flags); + num_buf_rdy = m2m_ctx->out_q_ctx.num_rdy; + spin_unlock_irqrestore(&m2m_ctx->out_q_ctx.rdy_spinlock, flags); + + return num_buf_rdy; }
/** @@ -600,7 +607,14 @@ unsigned int v4l2_m2m_num_src_bufs_ready(struct v4l2_m2m_ctx *m2m_ctx) static inline unsigned int v4l2_m2m_num_dst_bufs_ready(struct v4l2_m2m_ctx *m2m_ctx) { - return m2m_ctx->cap_q_ctx.num_rdy; + unsigned int num_buf_rdy; + unsigned long flags; + + spin_lock_irqsave(&m2m_ctx->cap_q_ctx.rdy_spinlock, flags); + num_buf_rdy = m2m_ctx->cap_q_ctx.num_rdy; + spin_unlock_irqrestore(&m2m_ctx->cap_q_ctx.rdy_spinlock, flags); + + return num_buf_rdy; }
/**
From: Prashanth K quic_prashk@quicinc.com
[ Upstream commit e5990469943c711cb00bfde6338d2add6c6d0bfe ]
When serial console over USB is enabled, gs_console_connect queues gs_console_work, where it acquires the spinlock and queues the usb request, and this request goes to gadget layer. Now consider a situation where gadget layer prints something to dmesg, this will eventually call gs_console_write() which requires cons->lock. And this causes spinlock recursion. Avoid this by excluding usb_ep_queue from the spinlock.
spin_lock_irqsave //needs cons->lock gs_console_write . . _printk __warn_printk dev_warn/pr_err . . [USB Gadget Layer] . . usb_ep_queue gs_console_work __gs_console_push // acquires cons->lock process_one_work
Signed-off-by: Prashanth K quic_prashk@quicinc.com Link: https://lore.kernel.org/r/1683638872-6885-1-git-send-email-quic_prashk@quici... Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/usb/gadget/function/u_serial.c | 3 +++ 1 file changed, 3 insertions(+)
diff --git a/drivers/usb/gadget/function/u_serial.c b/drivers/usb/gadget/function/u_serial.c index 3b5a6430e2418..a717b53847a8e 100644 --- a/drivers/usb/gadget/function/u_serial.c +++ b/drivers/usb/gadget/function/u_serial.c @@ -917,8 +917,11 @@ static void __gs_console_push(struct gs_console *cons) }
req->length = size; + + spin_unlock_irq(&cons->lock); if (usb_ep_queue(ep, req, GFP_ATOMIC)) req->length = 0; + spin_lock_irq(&cons->lock); }
static void gs_console_work(struct work_struct *work)
From: Hans Verkuil hverkuil-cisco@xs4all.nl
[ Upstream commit 3df55cd773e8603b623425cc97b05e542854ad27 ]
If pdev is NULL, then it is still dereferenced.
This fixes this smatch warning:
drivers/media/platform/mediatek/vpu/mtk_vpu.c:570 vpu_load_firmware() warn: address of NULL pointer 'pdev'
Signed-off-by: Hans Verkuil hverkuil-cisco@xs4all.nl Cc: Yunfei Dong yunfei.dong@mediatek.com Signed-off-by: Mauro Carvalho Chehab mchehab@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/media/platform/mtk-vpu/mtk_vpu.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/drivers/media/platform/mtk-vpu/mtk_vpu.c b/drivers/media/platform/mtk-vpu/mtk_vpu.c index c62eb212cca92..e7c4b0dd588a9 100644 --- a/drivers/media/platform/mtk-vpu/mtk_vpu.c +++ b/drivers/media/platform/mtk-vpu/mtk_vpu.c @@ -539,15 +539,17 @@ static int load_requested_vpu(struct mtk_vpu *vpu, int vpu_load_firmware(struct platform_device *pdev) { struct mtk_vpu *vpu; - struct device *dev = &pdev->dev; + struct device *dev; struct vpu_run *run; int ret;
if (!pdev) { - dev_err(dev, "VPU platform device is invalid\n"); + pr_err("VPU platform device is invalid\n"); return -EINVAL; }
+ dev = &pdev->dev; + vpu = platform_get_drvdata(pdev); run = &vpu->run;
From: Xu Yang xu.yang_2@nxp.com
[ Upstream commit 9a070e8e208995a9d638b538ed7abf28bd6ea6f0 ]
Use dedicated imx8ulp usb compatible to remove QoS request since imx8ulp has no such limitation of imx7ulp: DMA will not work if system enters idle.
Signed-off-by: Xu Yang xu.yang_2@nxp.com Signed-off-by: Li Jun jun.li@nxp.com Acked-by: Peter Chen peter.chen@kernel.org Message-ID: 20230530104007.1294702-2-xu.yang_2@nxp.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/usb/chipidea/ci_hdrc_imx.c | 5 +++++ 1 file changed, 5 insertions(+)
diff --git a/drivers/usb/chipidea/ci_hdrc_imx.c b/drivers/usb/chipidea/ci_hdrc_imx.c index f798455942844..4d47fe89864d9 100644 --- a/drivers/usb/chipidea/ci_hdrc_imx.c +++ b/drivers/usb/chipidea/ci_hdrc_imx.c @@ -70,6 +70,10 @@ static const struct ci_hdrc_imx_platform_flag imx7ulp_usb_data = { CI_HDRC_PMQOS, };
+static const struct ci_hdrc_imx_platform_flag imx8ulp_usb_data = { + .flags = CI_HDRC_SUPPORTS_RUNTIME_PM, +}; + static const struct of_device_id ci_hdrc_imx_dt_ids[] = { { .compatible = "fsl,imx23-usb", .data = &imx23_usb_data}, { .compatible = "fsl,imx28-usb", .data = &imx28_usb_data}, @@ -80,6 +84,7 @@ static const struct of_device_id ci_hdrc_imx_dt_ids[] = { { .compatible = "fsl,imx6ul-usb", .data = &imx6ul_usb_data}, { .compatible = "fsl,imx7d-usb", .data = &imx7d_usb_data}, { .compatible = "fsl,imx7ulp-usb", .data = &imx7ulp_usb_data}, + { .compatible = "fsl,imx8ulp-usb", .data = &imx8ulp_usb_data}, { /* sentinel */ } }; MODULE_DEVICE_TABLE(of, ci_hdrc_imx_dt_ids);
From: Xu Yang xu.yang_2@nxp.com
[ Upstream commit 53d061c19dc4cb68409df6dc11c40389c8c42a75 ]
USB PHY DPDM wakeup bit is enabled by default, when USB wakeup is not required(/sys/.../wakeup is disabled), this bit should be disabled, otherwise we will have unexpected wakeup if do USB device connect/disconnect while system sleep. This bit can be enabled for both host and device mode.
Signed-off-by: Li Jun jun.li@nxp.com Signed-off-by: Xu Yang xu.yang_2@nxp.com Acked-by: Peter Chen peter.chen@kernel.org Message-ID: 20230517081907.3410465-3-xu.yang_2@nxp.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/usb/chipidea/usbmisc_imx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/usb/chipidea/usbmisc_imx.c b/drivers/usb/chipidea/usbmisc_imx.c index 425b29168b4d0..9b1d5c11dc340 100644 --- a/drivers/usb/chipidea/usbmisc_imx.c +++ b/drivers/usb/chipidea/usbmisc_imx.c @@ -135,7 +135,7 @@ #define TXVREFTUNE0_MASK (0xf << 20)
#define MX6_USB_OTG_WAKEUP_BITS (MX6_BM_WAKEUP_ENABLE | MX6_BM_VBUS_WAKEUP | \ - MX6_BM_ID_WAKEUP) + MX6_BM_ID_WAKEUP | MX6SX_BM_DPDM_WAKEUP_EN)
struct usbmisc_ops { /* It's called once when probe a usb device */
From: Tuo Li islituo@gmail.com
[ Upstream commit 6fa0a72cbbe45db4ed967a51f9e6f4e3afe61d20 ]
Some fields such as gt_logd_secs of the struct gfs2_tune are accessed without holding the lock gt_spin in gfs2_show_options():
val = sdp->sd_tune.gt_logd_secs; if (val != 30) seq_printf(s, ",commit=%d", val);
And thus can cause data races when gfs2_show_options() and other functions such as gfs2_reconfigure() are concurrently executed:
spin_lock(>->gt_spin); gt->gt_logd_secs = newargs->ar_commit;
To fix these possible data races, the lock sdp->sd_tune.gt_spin is acquired before accessing the fields of gfs2_tune and released after these accesses.
Further changes by Andreas:
- Don't hold the spin lock over the seq_printf operations.
Reported-by: BassCheck bass@buaa.edu.cn Signed-off-by: Tuo Li islituo@gmail.com Signed-off-by: Andreas Gruenbacher agruenba@redhat.com Signed-off-by: Sasha Levin sashal@kernel.org --- fs/gfs2/super.c | 26 +++++++++++++++----------- 1 file changed, 15 insertions(+), 11 deletions(-)
diff --git a/fs/gfs2/super.c b/fs/gfs2/super.c index e01b6a2d12d30..b61de8dab51a0 100644 --- a/fs/gfs2/super.c +++ b/fs/gfs2/super.c @@ -1017,7 +1017,14 @@ static int gfs2_show_options(struct seq_file *s, struct dentry *root) { struct gfs2_sbd *sdp = root->d_sb->s_fs_info; struct gfs2_args *args = &sdp->sd_args; - int val; + unsigned int logd_secs, statfs_slow, statfs_quantum, quota_quantum; + + spin_lock(&sdp->sd_tune.gt_spin); + logd_secs = sdp->sd_tune.gt_logd_secs; + quota_quantum = sdp->sd_tune.gt_quota_quantum; + statfs_quantum = sdp->sd_tune.gt_statfs_quantum; + statfs_slow = sdp->sd_tune.gt_statfs_slow; + spin_unlock(&sdp->sd_tune.gt_spin);
if (is_ancestor(root, sdp->sd_master_dir)) seq_puts(s, ",meta"); @@ -1072,17 +1079,14 @@ static int gfs2_show_options(struct seq_file *s, struct dentry *root) } if (args->ar_discard) seq_puts(s, ",discard"); - val = sdp->sd_tune.gt_logd_secs; - if (val != 30) - seq_printf(s, ",commit=%d", val); - val = sdp->sd_tune.gt_statfs_quantum; - if (val != 30) - seq_printf(s, ",statfs_quantum=%d", val); - else if (sdp->sd_tune.gt_statfs_slow) + if (logd_secs != 30) + seq_printf(s, ",commit=%d", logd_secs); + if (statfs_quantum != 30) + seq_printf(s, ",statfs_quantum=%d", statfs_quantum); + else if (statfs_slow) seq_puts(s, ",statfs_quantum=0"); - val = sdp->sd_tune.gt_quota_quantum; - if (val != 60) - seq_printf(s, ",quota_quantum=%d", val); + if (quota_quantum != 60) + seq_printf(s, ",quota_quantum=%d", quota_quantum); if (args->ar_statfs_percent) seq_printf(s, ",statfs_percent=%d", args->ar_statfs_percent); if (args->ar_errors != GFS2_ERRORS_DEFAULT) {
From: Armin Wolf W_Armin@gmx.de
[ Upstream commit c85fd9422fe0f5d667305efb27f56d09eab120b0 ]
When nonstatic_release_resource_db() frees all resources associated with an PCMCIA socket, it forgets to free socket_data too, causing a memory leak observable with kmemleak:
unreferenced object 0xc28d1000 (size 64): comm "systemd-udevd", pid 297, jiffies 4294898478 (age 194.484s) hex dump (first 32 bytes): 00 00 00 00 00 00 00 00 f0 85 0e c3 00 00 00 00 ................ 00 00 00 00 0c 10 8d c2 00 00 00 00 00 00 00 00 ................ backtrace: [<ffda4245>] __kmem_cache_alloc_node+0x2d7/0x4a0 [<7e51f0c8>] kmalloc_trace+0x31/0xa4 [<d52b4ca0>] nonstatic_init+0x24/0x1a4 [pcmcia_rsrc] [<a2f13e08>] pcmcia_register_socket+0x200/0x35c [pcmcia_core] [<a728be1b>] yenta_probe+0x4d8/0xa70 [yenta_socket] [<c48fac39>] pci_device_probe+0x99/0x194 [<84b7c690>] really_probe+0x181/0x45c [<8060fe6e>] __driver_probe_device+0x75/0x1f4 [<b9b76f43>] driver_probe_device+0x28/0xac [<648b766f>] __driver_attach+0xeb/0x1e4 [<6e9659eb>] bus_for_each_dev+0x61/0xb4 [<25a669f3>] driver_attach+0x1e/0x28 [<d8671d6b>] bus_add_driver+0x102/0x20c [<df0d323c>] driver_register+0x5b/0x120 [<942cd8a4>] __pci_register_driver+0x44/0x4c [<e536027e>] __UNIQUE_ID___addressable_cleanup_module188+0x1c/0xfffff000 [iTCO_vendor_support]
Fix this by freeing socket_data too.
Tested on a Acer Travelmate 4002WLMi by manually binding/unbinding the yenta_cardbus driver (yenta_socket).
Signed-off-by: Armin Wolf W_Armin@gmx.de Message-ID: 20230512184529.5094-1-W_Armin@gmx.de Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/pcmcia/rsrc_nonstatic.c | 2 ++ 1 file changed, 2 insertions(+)
diff --git a/drivers/pcmcia/rsrc_nonstatic.c b/drivers/pcmcia/rsrc_nonstatic.c index 69a6e9a5d6d26..6e90927e65769 100644 --- a/drivers/pcmcia/rsrc_nonstatic.c +++ b/drivers/pcmcia/rsrc_nonstatic.c @@ -1053,6 +1053,8 @@ static void nonstatic_release_resource_db(struct pcmcia_socket *s) q = p->next; kfree(p); } + + kfree(data); }
From: Zhengping Jiang jiangzp@google.com
[ Upstream commit f752a0b334bb95fe9b42ecb511e0864e2768046f ]
Fix potential use-after-free in l2cap_le_command_rej.
Signed-off-by: Zhengping Jiang jiangzp@google.com Signed-off-by: Luiz Augusto von Dentz luiz.von.dentz@intel.com Signed-off-by: Jakub Kicinski kuba@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- net/bluetooth/l2cap_core.c | 5 +++++ 1 file changed, 5 insertions(+)
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c index 568f0f072b3df..7b40e4737a2bb 100644 --- a/net/bluetooth/l2cap_core.c +++ b/net/bluetooth/l2cap_core.c @@ -6370,9 +6370,14 @@ static inline int l2cap_le_command_rej(struct l2cap_conn *conn, if (!chan) goto done;
+ chan = l2cap_chan_hold_unless_zero(chan); + if (!chan) + goto done; + l2cap_chan_lock(chan); l2cap_chan_del(chan, ECONNREFUSED); l2cap_chan_unlock(chan); + l2cap_chan_put(chan);
done: mutex_unlock(&conn->chan_lock);
From: Matthew Anderson ruinairas1992@gmail.com
[ Upstream commit fa01eba11f0e57c767a5eab5291c7a01407a00be ]
Adding the device ID from the Asus Ally gets the bluetooth working on the device.
Signed-off-by: Matthew Anderson ruinairas1992@gmail.com Signed-off-by: Luiz Augusto von Dentz luiz.von.dentz@intel.com Signed-off-by: Jakub Kicinski kuba@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/bluetooth/btusb.c | 3 +++ 1 file changed, 3 insertions(+)
diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c index 2695ece47eb0e..49d5375b04f40 100644 --- a/drivers/bluetooth/btusb.c +++ b/drivers/bluetooth/btusb.c @@ -432,6 +432,9 @@ static const struct usb_device_id blacklist_table[] = { { USB_DEVICE(0x0489, 0xe0d9), .driver_info = BTUSB_MEDIATEK | BTUSB_WIDEBAND_SPEECH | BTUSB_VALID_LE_STATES }, + { USB_DEVICE(0x0489, 0xe0f5), .driver_info = BTUSB_MEDIATEK | + BTUSB_WIDEBAND_SPEECH | + BTUSB_VALID_LE_STATES }, { USB_DEVICE(0x13d3, 0x3568), .driver_info = BTUSB_MEDIATEK | BTUSB_WIDEBAND_SPEECH | BTUSB_VALID_LE_STATES },
From: shanzhulig shanzhulig@gmail.com
[ Upstream commit 2e54154b9f27262efd0cb4f903cc7d5ad1fe9628 ]
fence Decrements the reference count before exiting. Avoid Race Vulnerabilities for fence use-after-free.
v2 (chk): actually fix the use after free and not just move it.
Signed-off-by: shanzhulig shanzhulig@gmail.com Signed-off-by: Christian König christian.koenig@amd.com Reviewed-by: Alex Deucher alexander.deucher@amd.com Signed-off-by: Alex Deucher alexander.deucher@amd.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c index ffd8f5601e28a..e25c3387bcf87 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c @@ -1517,15 +1517,15 @@ static int amdgpu_cs_wait_all_fences(struct amdgpu_device *adev, continue;
r = dma_fence_wait_timeout(fence, true, timeout); + if (r > 0 && fence->error) + r = fence->error; + dma_fence_put(fence); if (r < 0) return r;
if (r == 0) break; - - if (fence->error) - return fence->error; }
memset(wait, 0, sizeof(*wait));
From: dengxiang dengxiang@nfschina.com
[ Upstream commit 73f1c75d5e6bd8ce2a887ef493a66ad1b16ed704 ]
These models use NSIWAY amplifiers for internal speaker, but cannot put sound outside from these amplifiers. So eapd verbs are needed to initialize the amplifiers. They can be added during boot to get working sound out of internal speaker.
Signed-off-by: dengxiang dengxiang@nfschina.com Link: https://lore.kernel.org/r/20230703021751.2945750-1-dengxiang@nfschina.com Signed-off-by: Takashi Iwai tiwai@suse.de Signed-off-by: Sasha Levin sashal@kernel.org --- sound/pci/hda/patch_realtek.c | 9 +++++++++ 1 file changed, 9 insertions(+)
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index db8593d794315..09a9e21675341 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -10719,6 +10719,7 @@ enum { ALC897_FIXUP_HP_HSMIC_VERB, ALC897_FIXUP_LENOVO_HEADSET_MODE, ALC897_FIXUP_HEADSET_MIC_PIN2, + ALC897_FIXUP_UNIS_H3C_X500S, };
static const struct hda_fixup alc662_fixups[] = { @@ -11158,6 +11159,13 @@ static const struct hda_fixup alc662_fixups[] = { .chained = true, .chain_id = ALC897_FIXUP_LENOVO_HEADSET_MODE }, + [ALC897_FIXUP_UNIS_H3C_X500S] = { + .type = HDA_FIXUP_VERBS, + .v.verbs = (const struct hda_verb[]) { + { 0x14, AC_VERB_SET_EAPD_BTLENABLE, 0 }, + {} + }, + }, };
static const struct snd_pci_quirk alc662_fixup_tbl[] = { @@ -11319,6 +11327,7 @@ static const struct hda_model_fixup alc662_fixup_models[] = { {.id = ALC662_FIXUP_USI_HEADSET_MODE, .name = "usi-headset"}, {.id = ALC662_FIXUP_LENOVO_MULTI_CODECS, .name = "dual-codecs"}, {.id = ALC669_FIXUP_ACER_ASPIRE_ETHOS, .name = "aspire-ethos"}, + {.id = ALC897_FIXUP_UNIS_H3C_X500S, .name = "unis-h3c-x500s"}, {} };
From: Tuo Li islituo@gmail.com
[ Upstream commit 1f4a08fed450db87fbb5ff5105354158bdbe1a22 ]
The variable codec->regmap is often protected by the lock codec->regmap_lock when is accessed. However, it is accessed without holding the lock when is accessed in snd_hdac_regmap_sync():
if (codec->regmap)
In my opinion, this may be a harmful race, because if codec->regmap is set to NULL right after the condition is checked, a null-pointer dereference can occur in the called function regcache_sync():
map->lock(map->lock_arg); --> Line 360 in drivers/base/regmap/regcache.c
To fix this possible null-pointer dereference caused by data race, the mutex_lock coverage is extended to protect the if statement as well as the function call to regcache_sync().
[ Note: the lack of the regmap_lock itself is harmless for the current codec driver implementations, as snd_hdac_regmap_sync() is only for PM runtime resume that is prohibited during the codec probe. But the change makes the whole code more consistent, so it's merged as is -- tiwai ]
Reported-by: BassCheck bass@buaa.edu.cn Signed-off-by: Tuo Li islituo@gmail.com Link: https://lore.kernel.org/r/20230703031016.1184711-1-islituo@gmail.com Signed-off-by: Takashi Iwai tiwai@suse.de Signed-off-by: Sasha Levin sashal@kernel.org --- sound/hda/hdac_regmap.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-)
diff --git a/sound/hda/hdac_regmap.c b/sound/hda/hdac_regmap.c index d75f31eb9d78f..bf35acca5ea0e 100644 --- a/sound/hda/hdac_regmap.c +++ b/sound/hda/hdac_regmap.c @@ -597,10 +597,9 @@ EXPORT_SYMBOL_GPL(snd_hdac_regmap_update_raw_once); */ void snd_hdac_regmap_sync(struct hdac_device *codec) { - if (codec->regmap) { - mutex_lock(&codec->regmap_lock); + mutex_lock(&codec->regmap_lock); + if (codec->regmap) regcache_sync(codec->regmap); - mutex_unlock(&codec->regmap_lock); - } + mutex_unlock(&codec->regmap_lock); } EXPORT_SYMBOL_GPL(snd_hdac_regmap_sync);
From: Benjamin Gray bgray@linux.ibm.com
[ Upstream commit ccb381e1af1ace292153c88eb1fffa5683d16a20 ]
As per the generic KASAN code in mm/kasan, disable KCOV with KCOV_INSTRUMENT := n in the makefile.
This fixes a ppc64 boot hang when KCOV and KASAN are enabled. kasan_early_init() gets called before a PACA is initialised, but the KCOV hook expects a valid PACA.
Suggested-by: Christophe Leroy christophe.leroy@csgroup.eu Signed-off-by: Benjamin Gray bgray@linux.ibm.com Signed-off-by: Michael Ellerman mpe@ellerman.id.au Link: https://msgid.link/20230710044143.146840-1-bgray@linux.ibm.com Signed-off-by: Sasha Levin sashal@kernel.org --- arch/powerpc/mm/kasan/Makefile | 1 + 1 file changed, 1 insertion(+)
diff --git a/arch/powerpc/mm/kasan/Makefile b/arch/powerpc/mm/kasan/Makefile index bb1a5408b86b2..8636b17c6a20f 100644 --- a/arch/powerpc/mm/kasan/Makefile +++ b/arch/powerpc/mm/kasan/Makefile @@ -1,6 +1,7 @@ # SPDX-License-Identifier: GPL-2.0
KASAN_SANITIZE := n +KCOV_INSTRUMENT := n
obj-$(CONFIG_PPC32) += kasan_init_32.o obj-$(CONFIG_PPC_8xx) += 8xx.o
From: Chen Lin chen.lin5@zte.com.cn
[ Upstream commit 8a96c0288d0737ad77882024974c075345c72011 ]
When ring_buffer_swap_cpu was called during resize process, the cpu buffer was swapped in the middle, resulting in incorrect state. Continuing to run in the wrong state will result in oops.
This issue can be easily reproduced using the following two scripts: /tmp # cat test1.sh //#! /bin/sh for i in `seq 0 100000` do echo 2000 > /sys/kernel/debug/tracing/buffer_size_kb sleep 0.5 echo 5000 > /sys/kernel/debug/tracing/buffer_size_kb sleep 0.5 done /tmp # cat test2.sh //#! /bin/sh for i in `seq 0 100000` do echo irqsoff > /sys/kernel/debug/tracing/current_tracer sleep 1 echo nop > /sys/kernel/debug/tracing/current_tracer sleep 1 done /tmp # ./test1.sh & /tmp # ./test2.sh &
A typical oops log is as follows, sometimes with other different oops logs.
[ 231.711293] WARNING: CPU: 0 PID: 9 at kernel/trace/ring_buffer.c:2026 rb_update_pages+0x378/0x3f8 [ 231.713375] Modules linked in: [ 231.714735] CPU: 0 PID: 9 Comm: kworker/0:1 Tainted: G W 6.5.0-rc1-00276-g20edcec23f92 #15 [ 231.716750] Hardware name: linux,dummy-virt (DT) [ 231.718152] Workqueue: events update_pages_handler [ 231.719714] pstate: 60000005 (nZCv daif -PAN -UAO -TCO -DIT -SSBS BTYPE=--) [ 231.721171] pc : rb_update_pages+0x378/0x3f8 [ 231.722212] lr : rb_update_pages+0x25c/0x3f8 [ 231.723248] sp : ffff800082b9bd50 [ 231.724169] x29: ffff800082b9bd50 x28: ffff8000825f7000 x27: 0000000000000000 [ 231.726102] x26: 0000000000000001 x25: fffffffffffff010 x24: 0000000000000ff0 [ 231.728122] x23: ffff0000c3a0b600 x22: ffff0000c3a0b5c0 x21: fffffffffffffe0a [ 231.730203] x20: ffff0000c3a0b600 x19: ffff0000c0102400 x18: 0000000000000000 [ 231.732329] x17: 0000000000000000 x16: 0000000000000000 x15: 0000ffffe7aa8510 [ 231.734212] x14: 0000000000000000 x13: 0000000000000000 x12: 0000000000000002 [ 231.736291] x11: ffff8000826998a8 x10: ffff800082b9baf0 x9 : ffff800081137558 [ 231.738195] x8 : fffffc00030e82c8 x7 : 0000000000000000 x6 : 0000000000000001 [ 231.740192] x5 : ffff0000ffbafe00 x4 : 0000000000000000 x3 : 0000000000000000 [ 231.742118] x2 : 00000000000006aa x1 : 0000000000000001 x0 : ffff0000c0007208 [ 231.744196] Call trace: [ 231.744892] rb_update_pages+0x378/0x3f8 [ 231.745893] update_pages_handler+0x1c/0x38 [ 231.746893] process_one_work+0x1f0/0x468 [ 231.747852] worker_thread+0x54/0x410 [ 231.748737] kthread+0x124/0x138 [ 231.749549] ret_from_fork+0x10/0x20 [ 231.750434] ---[ end trace 0000000000000000 ]--- [ 233.720486] Unable to handle kernel NULL pointer dereference at virtual address 0000000000000000 [ 233.721696] Mem abort info: [ 233.721935] ESR = 0x0000000096000004 [ 233.722283] EC = 0x25: DABT (current EL), IL = 32 bits [ 233.722596] SET = 0, FnV = 0 [ 233.722805] EA = 0, S1PTW = 0 [ 233.723026] FSC = 0x04: level 0 translation fault [ 233.723458] Data abort info: [ 233.723734] ISV = 0, ISS = 0x00000004, ISS2 = 0x00000000 [ 233.724176] CM = 0, WnR = 0, TnD = 0, TagAccess = 0 [ 233.724589] GCS = 0, Overlay = 0, DirtyBit = 0, Xs = 0 [ 233.725075] user pgtable: 4k pages, 48-bit VAs, pgdp=0000000104943000 [ 233.725592] [0000000000000000] pgd=0000000000000000, p4d=0000000000000000 [ 233.726231] Internal error: Oops: 0000000096000004 [#1] PREEMPT SMP [ 233.726720] Modules linked in: [ 233.727007] CPU: 0 PID: 9 Comm: kworker/0:1 Tainted: G W 6.5.0-rc1-00276-g20edcec23f92 #15 [ 233.727777] Hardware name: linux,dummy-virt (DT) [ 233.728225] Workqueue: events update_pages_handler [ 233.728655] pstate: 200000c5 (nzCv daIF -PAN -UAO -TCO -DIT -SSBS BTYPE=--) [ 233.729054] pc : rb_update_pages+0x1a8/0x3f8 [ 233.729334] lr : rb_update_pages+0x154/0x3f8 [ 233.729592] sp : ffff800082b9bd50 [ 233.729792] x29: ffff800082b9bd50 x28: ffff8000825f7000 x27: 0000000000000000 [ 233.730220] x26: 0000000000000000 x25: ffff800082a8b840 x24: ffff0000c0102418 [ 233.730653] x23: 0000000000000000 x22: fffffc000304c880 x21: 0000000000000003 [ 233.731105] x20: 00000000000001f4 x19: ffff0000c0102400 x18: ffff800082fcbc58 [ 233.731727] x17: 0000000000000000 x16: 0000000000000001 x15: 0000000000000001 [ 233.732282] x14: ffff8000825fe0c8 x13: 0000000000000001 x12: 0000000000000000 [ 233.732709] x11: ffff8000826998a8 x10: 0000000000000ae0 x9 : ffff8000801b760c [ 233.733148] x8 : fefefefefefefeff x7 : 0000000000000018 x6 : ffff0000c03298c0 [ 233.733553] x5 : 0000000000000002 x4 : 0000000000000000 x3 : 0000000000000000 [ 233.733972] x2 : ffff0000c3a0b600 x1 : 0000000000000000 x0 : 0000000000000000 [ 233.734418] Call trace: [ 233.734593] rb_update_pages+0x1a8/0x3f8 [ 233.734853] update_pages_handler+0x1c/0x38 [ 233.735148] process_one_work+0x1f0/0x468 [ 233.735525] worker_thread+0x54/0x410 [ 233.735852] kthread+0x124/0x138 [ 233.736064] ret_from_fork+0x10/0x20 [ 233.736387] Code: 92400000 910006b5 aa000021 aa0303f7 (f9400060) [ 233.736959] ---[ end trace 0000000000000000 ]---
After analysis, the seq of the error is as follows [1-5]:
int ring_buffer_resize(struct trace_buffer *buffer, unsigned long size, int cpu_id) { for_each_buffer_cpu(buffer, cpu) { cpu_buffer = buffer->buffers[cpu]; //1. get cpu_buffer, aka cpu_buffer(A) ... ... schedule_work_on(cpu, &cpu_buffer->update_pages_work); //2. 'update_pages_work' is queue on 'cpu', cpu_buffer(A) is passed to // update_pages_handler, do the update process, set 'update_done' in // complete(&cpu_buffer->update_done) and to wakeup resize process. //----> //3. Just at this moment, ring_buffer_swap_cpu is triggered, //cpu_buffer(A) be swaped to cpu_buffer(B), the max_buffer. //ring_buffer_swap_cpu is called as the 'Call trace' below.
Call trace: dump_backtrace+0x0/0x2f8 show_stack+0x18/0x28 dump_stack+0x12c/0x188 ring_buffer_swap_cpu+0x2f8/0x328 update_max_tr_single+0x180/0x210 check_critical_timing+0x2b4/0x2c8 tracer_hardirqs_on+0x1c0/0x200 trace_hardirqs_on+0xec/0x378 el0_svc_common+0x64/0x260 do_el0_svc+0x90/0xf8 el0_svc+0x20/0x30 el0_sync_handler+0xb0/0xb8 el0_sync+0x180/0x1c0 //<----
/* wait for all the updates to complete */ for_each_buffer_cpu(buffer, cpu) { cpu_buffer = buffer->buffers[cpu]; //4. get cpu_buffer, cpu_buffer(B) is used in the following process, //the state of cpu_buffer(A) and cpu_buffer(B) is totally wrong. //for example, cpu_buffer(A)->update_done will leave be set 1, and will //not 'wait_for_completion' at the next resize round. if (!cpu_buffer->nr_pages_to_update) continue;
if (cpu_online(cpu)) wait_for_completion(&cpu_buffer->update_done); cpu_buffer->nr_pages_to_update = 0; } ... } //5. the state of cpu_buffer(A) and cpu_buffer(B) is totally wrong, //Continuing to run in the wrong state, then oops occurs.
Link: https://lore.kernel.org/linux-trace-kernel/202307191558478409990@zte.com.cn
Signed-off-by: Chen Lin chen.lin5@zte.com.cn Signed-off-by: Steven Rostedt (Google) rostedt@goodmis.org Signed-off-by: Sasha Levin sashal@kernel.org --- kernel/trace/ring_buffer.c | 14 +++++++++++++- kernel/trace/trace.c | 3 ++- 2 files changed, 15 insertions(+), 2 deletions(-)
diff --git a/kernel/trace/ring_buffer.c b/kernel/trace/ring_buffer.c index 3b8c53264441e..f8126fa0630e2 100644 --- a/kernel/trace/ring_buffer.c +++ b/kernel/trace/ring_buffer.c @@ -541,6 +541,7 @@ struct trace_buffer { unsigned flags; int cpus; atomic_t record_disabled; + atomic_t resizing; cpumask_var_t cpumask;
struct lock_class_key *reader_lock_key; @@ -2041,7 +2042,7 @@ int ring_buffer_resize(struct trace_buffer *buffer, unsigned long size,
/* prevent another thread from changing buffer sizes */ mutex_lock(&buffer->mutex); - + atomic_inc(&buffer->resizing);
if (cpu_id == RING_BUFFER_ALL_CPUS) { /* @@ -2184,6 +2185,7 @@ int ring_buffer_resize(struct trace_buffer *buffer, unsigned long size, atomic_dec(&buffer->record_disabled); }
+ atomic_dec(&buffer->resizing); mutex_unlock(&buffer->mutex); return 0;
@@ -2204,6 +2206,7 @@ int ring_buffer_resize(struct trace_buffer *buffer, unsigned long size, } } out_err_unlock: + atomic_dec(&buffer->resizing); mutex_unlock(&buffer->mutex); return err; } @@ -5253,6 +5256,15 @@ int ring_buffer_swap_cpu(struct trace_buffer *buffer_a, if (local_read(&cpu_buffer_b->committing)) goto out_dec;
+ /* + * When resize is in progress, we cannot swap it because + * it will mess the state of the cpu buffer. + */ + if (atomic_read(&buffer_a->resizing)) + goto out_dec; + if (atomic_read(&buffer_b->resizing)) + goto out_dec; + buffer_a->buffers[cpu] = cpu_buffer_b; buffer_b->buffers[cpu] = cpu_buffer_a;
diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c index 7e99319bd5365..167f2a19fd8a2 100644 --- a/kernel/trace/trace.c +++ b/kernel/trace/trace.c @@ -1882,9 +1882,10 @@ update_max_tr_single(struct trace_array *tr, struct task_struct *tsk, int cpu) * place on this CPU. We fail to record, but we reset * the max trace buffer (no one writes directly to it) * and flag that it failed. + * Another reason is resize is in progress. */ trace_array_printk_buf(tr->max_buffer.buffer, _THIS_IP_, - "Failed to swap buffers due to commit in progress\n"); + "Failed to swap buffers due to commit or resize in progress\n"); }
WARN_ON_ONCE(ret && ret != -EAGAIN && ret != -EBUSY);
From: Randy Dunlap rdunlap@infradead.org
[ Upstream commit 644f17412f5acf01a19af9d04a921937a2bc86c6 ]
UML supports HAS_IOMEM since 0bbadafdc49d (um: allow disabling NO_IOMEM).
Current IMA build on UML fails on allmodconfig (with TCG_TPM=m):
ld: security/integrity/ima/ima_queue.o: in function `ima_add_template_entry': ima_queue.c:(.text+0x2d9): undefined reference to `tpm_pcr_extend' ld: security/integrity/ima/ima_init.o: in function `ima_init': ima_init.c:(.init.text+0x43f): undefined reference to `tpm_default_chip' ld: security/integrity/ima/ima_crypto.o: in function `ima_calc_boot_aggregate_tfm': ima_crypto.c:(.text+0x1044): undefined reference to `tpm_pcr_read' ld: ima_crypto.c:(.text+0x10d8): undefined reference to `tpm_pcr_read'
Modify the IMA Kconfig entry so that it selects TCG_TPM if HAS_IOMEM is set, regardless of the UML Kconfig setting. This updates TCG_TPM from =m to =y and fixes the linker errors.
Fixes: f4a0391dfa91 ("ima: fix Kconfig dependencies") Cc: Stable stable@vger.kernel.org # v5.14+ Signed-off-by: Randy Dunlap rdunlap@infradead.org Cc: Fabio Estevam festevam@gmail.com Cc: Richard Weinberger richard@nod.at Cc: Anton Ivanov anton.ivanov@cambridgegreys.com Cc: Johannes Berg johannes@sipsolutions.net Cc: linux-um@lists.infradead.org Signed-off-by: Mimi Zohar zohar@linux.ibm.com Signed-off-by: Sasha Levin sashal@kernel.org --- security/integrity/ima/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/security/integrity/ima/Kconfig b/security/integrity/ima/Kconfig index 755af0b29e755..0a5ae1e8da47a 100644 --- a/security/integrity/ima/Kconfig +++ b/security/integrity/ima/Kconfig @@ -8,7 +8,7 @@ config IMA select CRYPTO_HMAC select CRYPTO_SHA1 select CRYPTO_HASH_INFO - select TCG_TPM if HAS_IOMEM && !UML + select TCG_TPM if HAS_IOMEM select TCG_TIS if TCG_TPM && X86 select TCG_CRB if TCG_TPM && ACPI select TCG_IBMVTPM if TCG_TPM && PPC_PSERIES
From: Cosmin Tanislav demonsingur@gmail.com
[ Upstream commit b62e2e1763cda3a6c494ed754317f19be1249297 ]
For IIO devices that expose both ADC and DAC functionality.
Signed-off-by: Cosmin Tanislav cosmin.tanislav@analog.com Link: https://lore.kernel.org/r/20211205114045.173612-2-cosmin.tanislav@analog.com Signed-off-by: Jonathan Cameron Jonathan.Cameron@huawei.com Stable-dep-of: 4f9b80aefb9e ("iio: addac: stx104: Fix race condition when converting analog-to-digital") Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/iio/Kconfig | 1 + drivers/iio/Makefile | 1 + drivers/iio/addac/Kconfig | 8 ++++++++ drivers/iio/addac/Makefile | 6 ++++++ 4 files changed, 16 insertions(+) create mode 100644 drivers/iio/addac/Kconfig create mode 100644 drivers/iio/addac/Makefile
diff --git a/drivers/iio/Kconfig b/drivers/iio/Kconfig index 267553386c710..2ed303aa7de3c 100644 --- a/drivers/iio/Kconfig +++ b/drivers/iio/Kconfig @@ -70,6 +70,7 @@ config IIO_TRIGGERED_EVENT
source "drivers/iio/accel/Kconfig" source "drivers/iio/adc/Kconfig" +source "drivers/iio/addac/Kconfig" source "drivers/iio/afe/Kconfig" source "drivers/iio/amplifiers/Kconfig" source "drivers/iio/chemical/Kconfig" diff --git a/drivers/iio/Makefile b/drivers/iio/Makefile index 1712011c0f4a1..d6690e449ccec 100644 --- a/drivers/iio/Makefile +++ b/drivers/iio/Makefile @@ -15,6 +15,7 @@ obj-$(CONFIG_IIO_TRIGGERED_EVENT) += industrialio-triggered-event.o
obj-y += accel/ obj-y += adc/ +obj-y += addac/ obj-y += afe/ obj-y += amplifiers/ obj-y += buffer/ diff --git a/drivers/iio/addac/Kconfig b/drivers/iio/addac/Kconfig new file mode 100644 index 0000000000000..2e64d7755d5ea --- /dev/null +++ b/drivers/iio/addac/Kconfig @@ -0,0 +1,8 @@ +# +# ADC DAC drivers +# +# When adding new entries keep the list in alphabetical order + +menu "Analog to digital and digital to analog converters" + +endmenu diff --git a/drivers/iio/addac/Makefile b/drivers/iio/addac/Makefile new file mode 100644 index 0000000000000..b888b9ee12da0 --- /dev/null +++ b/drivers/iio/addac/Makefile @@ -0,0 +1,6 @@ +# SPDX-License-Identifier: GPL-2.0 +# +# Makefile for industrial I/O ADDAC drivers +# + +# When adding new entries keep the list in alphabetical order
From: Cosmin Tanislav demonsingur@gmail.com
[ Upstream commit 3cf3cdea6fe3fdb7a1e4ac1372b80408e4f56b73 ]
The AD74412R and AD74413R are quad-channel, software configurable, input/output solutions for building and process control applications.
They contain functionality for analog output, analog input, digital input, resistance temperature detector, and thermocouple measurements integrated into a single chip solution with an SPI interface.
The devices feature a 16-bit ADC and four configurable 13-bit DACs to provide four configurable input/output channels and a suite of diagnostic functions.
The AD74413R differentiates itself from the AD74412R by being HART-compatible.
Signed-off-by: Cosmin Tanislav cosmin.tanislav@analog.com Reviewed-by: Rob Herring robh@kernel.org Reviewed-by: Linus Walleij linus.walleij@linaro.org Link: https://lore.kernel.org/r/20211205114045.173612-3-cosmin.tanislav@analog.com Signed-off-by: Jonathan Cameron Jonathan.Cameron@huawei.com Stable-dep-of: 4f9b80aefb9e ("iio: addac: stx104: Fix race condition when converting analog-to-digital") Signed-off-by: Sasha Levin sashal@kernel.org --- .../bindings/iio/addac/adi,ad74413r.yaml | 158 ++++++++++++++++++ include/dt-bindings/iio/addac/adi,ad74413r.h | 21 +++ 2 files changed, 179 insertions(+) create mode 100644 Documentation/devicetree/bindings/iio/addac/adi,ad74413r.yaml create mode 100644 include/dt-bindings/iio/addac/adi,ad74413r.h
diff --git a/Documentation/devicetree/bindings/iio/addac/adi,ad74413r.yaml b/Documentation/devicetree/bindings/iio/addac/adi,ad74413r.yaml new file mode 100644 index 0000000000000..baa65a521bad5 --- /dev/null +++ b/Documentation/devicetree/bindings/iio/addac/adi,ad74413r.yaml @@ -0,0 +1,158 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/iio/addac/adi,ad74413r.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Analog Devices AD74412R/AD74413R device + +maintainers: + - Cosmin Tanislav cosmin.tanislav@analog.com + +description: | + The AD74412R and AD74413R are quad-channel software configurable input/output + solutions for building and process control applications. They contain + functionality for analog output, analog input, digital input, resistance + temperature detector, and thermocouple measurements integrated + into a single chip solution with an SPI interface. + The devices feature a 16-bit ADC and four configurable 13-bit DACs to provide + four configurable input/output channels and a suite of diagnostic functions. + The AD74413R differentiates itself from the AD74412R by being HART-compatible. + https://www.analog.com/en/products/ad74412r.html + https://www.analog.com/en/products/ad74413r.html + +properties: + compatible: + enum: + - adi,ad74412r + - adi,ad74413r + + reg: + maxItems: 1 + + '#address-cells': + const: 1 + + '#size-cells': + const: 0 + + spi-max-frequency: + maximum: 1000000 + + spi-cpol: true + + interrupts: + maxItems: 1 + + refin-supply: true + + shunt-resistor-micro-ohms: + description: + Shunt (sense) resistor value in micro-Ohms. + default: 100000000 + +required: + - compatible + - reg + - spi-max-frequency + - spi-cpol + - refin-supply + +additionalProperties: false + +patternProperties: + "^channel@[0-3]$": + type: object + description: Represents the external channels which are connected to the device. + + properties: + reg: + description: | + The channel number. It can have up to 4 channels numbered from 0 to 3. + minimum: 0 + maximum: 3 + + adi,ch-func: + $ref: /schemas/types.yaml#/definitions/uint32 + description: | + Channel function. + HART functions are not supported on AD74412R. + 0 - CH_FUNC_HIGH_IMPEDANCE + 1 - CH_FUNC_VOLTAGE_OUTPUT + 2 - CH_FUNC_CURRENT_OUTPUT + 3 - CH_FUNC_VOLTAGE_INPUT + 4 - CH_FUNC_CURRENT_INPUT_EXT_POWER + 5 - CH_FUNC_CURRENT_INPUT_LOOP_POWER + 6 - CH_FUNC_RESISTANCE_INPUT + 7 - CH_FUNC_DIGITAL_INPUT_LOGIC + 8 - CH_FUNC_DIGITAL_INPUT_LOOP_POWER + 9 - CH_FUNC_CURRENT_INPUT_EXT_POWER_HART + 10 - CH_FUNC_CURRENT_INPUT_LOOP_POWER_HART + minimum: 0 + maximum: 10 + default: 0 + + adi,gpo-comparator: + type: boolean + description: | + Whether to configure GPO as a comparator or not. + When not configured as a comparator, the GPO will be treated as an + output-only GPIO. + + required: + - reg + +examples: + - | + #include <dt-bindings/gpio/gpio.h> + #include <dt-bindings/interrupt-controller/irq.h> + #include <dt-bindings/iio/addac/adi,ad74413r.h> + + spi { + #address-cells = <1>; + #size-cells = <0>; + + cs-gpios = <&gpio 17 GPIO_ACTIVE_LOW>; + status = "okay"; + + ad74413r@0 { + compatible = "adi,ad74413r"; + reg = <0>; + spi-max-frequency = <1000000>; + spi-cpol; + + #address-cells = <1>; + #size-cells = <0>; + + interrupt-parent = <&gpio>; + interrupts = <26 IRQ_TYPE_EDGE_FALLING>; + + refin-supply = <&ad74413r_refin>; + + channel@0 { + reg = <0>; + + adi,ch-func = <CH_FUNC_VOLTAGE_OUTPUT>; + }; + + channel@1 { + reg = <1>; + + adi,ch-func = <CH_FUNC_CURRENT_OUTPUT>; + }; + + channel@2 { + reg = <2>; + + adi,ch-func = <CH_FUNC_DIGITAL_INPUT_LOGIC>; + adi,gpo-comparator; + }; + + channel@3 { + reg = <3>; + + adi,ch-func = <CH_FUNC_CURRENT_INPUT_EXT_POWER>; + }; + }; + }; +... diff --git a/include/dt-bindings/iio/addac/adi,ad74413r.h b/include/dt-bindings/iio/addac/adi,ad74413r.h new file mode 100644 index 0000000000000..204f92bbd79f2 --- /dev/null +++ b/include/dt-bindings/iio/addac/adi,ad74413r.h @@ -0,0 +1,21 @@ +/* SPDX-License-Identifier: GPL-2.0 */ + +#ifndef _DT_BINDINGS_ADI_AD74413R_H +#define _DT_BINDINGS_ADI_AD74413R_H + +#define CH_FUNC_HIGH_IMPEDANCE 0x0 +#define CH_FUNC_VOLTAGE_OUTPUT 0x1 +#define CH_FUNC_CURRENT_OUTPUT 0x2 +#define CH_FUNC_VOLTAGE_INPUT 0x3 +#define CH_FUNC_CURRENT_INPUT_EXT_POWER 0x4 +#define CH_FUNC_CURRENT_INPUT_LOOP_POWER 0x5 +#define CH_FUNC_RESISTANCE_INPUT 0x6 +#define CH_FUNC_DIGITAL_INPUT_LOGIC 0x7 +#define CH_FUNC_DIGITAL_INPUT_LOOP_POWER 0x8 +#define CH_FUNC_CURRENT_INPUT_EXT_POWER_HART 0x9 +#define CH_FUNC_CURRENT_INPUT_LOOP_POWER_HART 0xA + +#define CH_FUNC_MIN CH_FUNC_HIGH_IMPEDANCE +#define CH_FUNC_MAX CH_FUNC_CURRENT_INPUT_LOOP_POWER_HART + +#endif /* _DT_BINDINGS_ADI_AD74413R_H */
From: William Breathitt Gray william.gray@linaro.org
[ Upstream commit 73b8390cc27e096ab157be261ccc4eaaa6db87af ]
This driver doesn't need to access I/O ports directly via inb()/outb() and friends. This patch abstracts such access by calling ioport_map() to enable the use of more typical ioread8()/iowrite8() I/O memory accessor calls.
Suggested-by: David Laight David.Laight@ACULAB.COM Signed-off-by: William Breathitt Gray william.gray@linaro.org Reviewed-by: Linus Walleij linus.walleij@linaro.org Link: https://lore.kernel.org/r/64673797df382c52fc32fce24348b25a0b05e73a.165220192... Signed-off-by: Jonathan Cameron Jonathan.Cameron@huawei.com Stable-dep-of: 4f9b80aefb9e ("iio: addac: stx104: Fix race condition when converting analog-to-digital") Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/iio/adc/stx104.c | 56 +++++++++++++++++++++------------------- 1 file changed, 29 insertions(+), 27 deletions(-)
diff --git a/drivers/iio/adc/stx104.c b/drivers/iio/adc/stx104.c index 55bd2dc514e93..7552351bfed9e 100644 --- a/drivers/iio/adc/stx104.c +++ b/drivers/iio/adc/stx104.c @@ -51,7 +51,7 @@ MODULE_PARM_DESC(base, "Apex Embedded Systems STX104 base addresses"); */ struct stx104_iio { unsigned int chan_out_states[STX104_NUM_OUT_CHAN]; - unsigned int base; + void __iomem *base; };
/** @@ -64,7 +64,7 @@ struct stx104_iio { struct stx104_gpio { struct gpio_chip chip; spinlock_t lock; - unsigned int base; + void __iomem *base; unsigned int out_state; };
@@ -79,7 +79,7 @@ static int stx104_read_raw(struct iio_dev *indio_dev, switch (mask) { case IIO_CHAN_INFO_HARDWAREGAIN: /* get gain configuration */ - adc_config = inb(priv->base + 11); + adc_config = ioread8(priv->base + 11); gain = adc_config & 0x3;
*val = 1 << gain; @@ -91,24 +91,24 @@ static int stx104_read_raw(struct iio_dev *indio_dev, }
/* select ADC channel */ - outb(chan->channel | (chan->channel << 4), priv->base + 2); + iowrite8(chan->channel | (chan->channel << 4), priv->base + 2);
/* trigger ADC sample capture and wait for completion */ - outb(0, priv->base); - while (inb(priv->base + 8) & BIT(7)); + iowrite8(0, priv->base); + while (ioread8(priv->base + 8) & BIT(7));
- *val = inw(priv->base); + *val = ioread16(priv->base); return IIO_VAL_INT; case IIO_CHAN_INFO_OFFSET: /* get ADC bipolar/unipolar configuration */ - adc_config = inb(priv->base + 11); + adc_config = ioread8(priv->base + 11); adbu = !(adc_config & BIT(2));
*val = -32768 * adbu; return IIO_VAL_INT; case IIO_CHAN_INFO_SCALE: /* get ADC bipolar/unipolar and gain configuration */ - adc_config = inb(priv->base + 11); + adc_config = ioread8(priv->base + 11); adbu = !(adc_config & BIT(2)); gain = adc_config & 0x3;
@@ -130,16 +130,16 @@ static int stx104_write_raw(struct iio_dev *indio_dev, /* Only four gain states (x1, x2, x4, x8) */ switch (val) { case 1: - outb(0, priv->base + 11); + iowrite8(0, priv->base + 11); break; case 2: - outb(1, priv->base + 11); + iowrite8(1, priv->base + 11); break; case 4: - outb(2, priv->base + 11); + iowrite8(2, priv->base + 11); break; case 8: - outb(3, priv->base + 11); + iowrite8(3, priv->base + 11); break; default: return -EINVAL; @@ -153,7 +153,7 @@ static int stx104_write_raw(struct iio_dev *indio_dev, return -EINVAL;
priv->chan_out_states[chan->channel] = val; - outw(val, priv->base + 4 + 2 * chan->channel); + iowrite16(val, priv->base + 4 + 2 * chan->channel);
return 0; } @@ -222,7 +222,7 @@ static int stx104_gpio_get(struct gpio_chip *chip, unsigned int offset) if (offset >= 4) return -EINVAL;
- return !!(inb(stx104gpio->base) & BIT(offset)); + return !!(ioread8(stx104gpio->base) & BIT(offset)); }
static int stx104_gpio_get_multiple(struct gpio_chip *chip, unsigned long *mask, @@ -230,7 +230,7 @@ static int stx104_gpio_get_multiple(struct gpio_chip *chip, unsigned long *mask, { struct stx104_gpio *const stx104gpio = gpiochip_get_data(chip);
- *bits = inb(stx104gpio->base); + *bits = ioread8(stx104gpio->base);
return 0; } @@ -252,7 +252,7 @@ static void stx104_gpio_set(struct gpio_chip *chip, unsigned int offset, else stx104gpio->out_state &= ~mask;
- outb(stx104gpio->out_state, stx104gpio->base); + iowrite8(stx104gpio->out_state, stx104gpio->base);
spin_unlock_irqrestore(&stx104gpio->lock, flags); } @@ -279,7 +279,7 @@ static void stx104_gpio_set_multiple(struct gpio_chip *chip,
stx104gpio->out_state &= ~*mask; stx104gpio->out_state |= *mask & *bits; - outb(stx104gpio->out_state, stx104gpio->base); + iowrite8(stx104gpio->out_state, stx104gpio->base);
spin_unlock_irqrestore(&stx104gpio->lock, flags); } @@ -306,11 +306,16 @@ static int stx104_probe(struct device *dev, unsigned int id) return -EBUSY; }
+ priv = iio_priv(indio_dev); + priv->base = devm_ioport_map(dev, base[id], STX104_EXTENT); + if (!priv->base) + return -ENOMEM; + indio_dev->info = &stx104_info; indio_dev->modes = INDIO_DIRECT_MODE;
/* determine if differential inputs */ - if (inb(base[id] + 8) & BIT(5)) { + if (ioread8(priv->base + 8) & BIT(5)) { indio_dev->num_channels = ARRAY_SIZE(stx104_channels_diff); indio_dev->channels = stx104_channels_diff; } else { @@ -320,18 +325,15 @@ static int stx104_probe(struct device *dev, unsigned int id)
indio_dev->name = dev_name(dev);
- priv = iio_priv(indio_dev); - priv->base = base[id]; - /* configure device for software trigger operation */ - outb(0, base[id] + 9); + iowrite8(0, priv->base + 9);
/* initialize gain setting to x1 */ - outb(0, base[id] + 11); + iowrite8(0, priv->base + 11);
/* initialize DAC output to 0V */ - outw(0, base[id] + 4); - outw(0, base[id] + 6); + iowrite16(0, priv->base + 4); + iowrite16(0, priv->base + 6);
stx104gpio->chip.label = dev_name(dev); stx104gpio->chip.parent = dev; @@ -346,7 +348,7 @@ static int stx104_probe(struct device *dev, unsigned int id) stx104gpio->chip.get_multiple = stx104_gpio_get_multiple; stx104gpio->chip.set = stx104_gpio_set; stx104gpio->chip.set_multiple = stx104_gpio_set_multiple; - stx104gpio->base = base[id] + 3; + stx104gpio->base = priv->base + 3; stx104gpio->out_state = 0x0;
spin_lock_init(&stx104gpio->lock);
From: William Breathitt Gray william.gray@linaro.org
[ Upstream commit 6cfd14c54b1f42f29097244c1b6208f8268d7d5b ]
Reduce magic numbers and improve code readability by implementing and utilizing named register data structures.
Tested-by: Fred Eckert Frede@cmslaser.com Signed-off-by: William Breathitt Gray william.gray@linaro.org Link: https://lore.kernel.org/r/8cb91d5b53e57b066120e42ea07000d6c7ef5543.165721374... Signed-off-by: Jonathan Cameron Jonathan.Cameron@huawei.com Stable-dep-of: 4f9b80aefb9e ("iio: addac: stx104: Fix race condition when converting analog-to-digital") Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/iio/adc/stx104.c | 74 +++++++++++++++++++++++++++------------- 1 file changed, 50 insertions(+), 24 deletions(-)
diff --git a/drivers/iio/adc/stx104.c b/drivers/iio/adc/stx104.c index 7552351bfed9e..48a91a95e597b 100644 --- a/drivers/iio/adc/stx104.c +++ b/drivers/iio/adc/stx104.c @@ -16,6 +16,7 @@ #include <linux/module.h> #include <linux/moduleparam.h> #include <linux/spinlock.h> +#include <linux/types.h>
#define STX104_OUT_CHAN(chan) { \ .type = IIO_VOLTAGE, \ @@ -44,14 +45,36 @@ static unsigned int num_stx104; module_param_hw_array(base, uint, ioport, &num_stx104, 0); MODULE_PARM_DESC(base, "Apex Embedded Systems STX104 base addresses");
+/** + * struct stx104_reg - device register structure + * @ssr_ad: Software Strobe Register and ADC Data + * @achan: ADC Channel + * @dio: Digital I/O + * @dac: DAC Channels + * @cir_asr: Clear Interrupts and ADC Status + * @acr: ADC Control + * @pccr_fsh: Pacer Clock Control and FIFO Status MSB + * @acfg: ADC Configuration + */ +struct stx104_reg { + u16 ssr_ad; + u8 achan; + u8 dio; + u16 dac[2]; + u8 cir_asr; + u8 acr; + u8 pccr_fsh; + u8 acfg; +}; + /** * struct stx104_iio - IIO device private data structure * @chan_out_states: channels' output states - * @base: base port address of the IIO device + * @reg: I/O address offset for the device registers */ struct stx104_iio { unsigned int chan_out_states[STX104_NUM_OUT_CHAN]; - void __iomem *base; + struct stx104_reg __iomem *reg; };
/** @@ -64,7 +87,7 @@ struct stx104_iio { struct stx104_gpio { struct gpio_chip chip; spinlock_t lock; - void __iomem *base; + u8 __iomem *base; unsigned int out_state; };
@@ -72,6 +95,7 @@ static int stx104_read_raw(struct iio_dev *indio_dev, struct iio_chan_spec const *chan, int *val, int *val2, long mask) { struct stx104_iio *const priv = iio_priv(indio_dev); + struct stx104_reg __iomem *const reg = priv->reg; unsigned int adc_config; int adbu; int gain; @@ -79,7 +103,7 @@ static int stx104_read_raw(struct iio_dev *indio_dev, switch (mask) { case IIO_CHAN_INFO_HARDWAREGAIN: /* get gain configuration */ - adc_config = ioread8(priv->base + 11); + adc_config = ioread8(®->acfg); gain = adc_config & 0x3;
*val = 1 << gain; @@ -91,24 +115,26 @@ static int stx104_read_raw(struct iio_dev *indio_dev, }
/* select ADC channel */ - iowrite8(chan->channel | (chan->channel << 4), priv->base + 2); + iowrite8(chan->channel | (chan->channel << 4), ®->achan);
- /* trigger ADC sample capture and wait for completion */ - iowrite8(0, priv->base); - while (ioread8(priv->base + 8) & BIT(7)); + /* trigger ADC sample capture by writing to the 8-bit + * Software Strobe Register and wait for completion + */ + iowrite8(0, ®->ssr_ad); + while (ioread8(®->cir_asr) & BIT(7));
- *val = ioread16(priv->base); + *val = ioread16(®->ssr_ad); return IIO_VAL_INT; case IIO_CHAN_INFO_OFFSET: /* get ADC bipolar/unipolar configuration */ - adc_config = ioread8(priv->base + 11); + adc_config = ioread8(®->acfg); adbu = !(adc_config & BIT(2));
*val = -32768 * adbu; return IIO_VAL_INT; case IIO_CHAN_INFO_SCALE: /* get ADC bipolar/unipolar and gain configuration */ - adc_config = ioread8(priv->base + 11); + adc_config = ioread8(®->acfg); adbu = !(adc_config & BIT(2)); gain = adc_config & 0x3;
@@ -130,16 +156,16 @@ static int stx104_write_raw(struct iio_dev *indio_dev, /* Only four gain states (x1, x2, x4, x8) */ switch (val) { case 1: - iowrite8(0, priv->base + 11); + iowrite8(0, &priv->reg->acfg); break; case 2: - iowrite8(1, priv->base + 11); + iowrite8(1, &priv->reg->acfg); break; case 4: - iowrite8(2, priv->base + 11); + iowrite8(2, &priv->reg->acfg); break; case 8: - iowrite8(3, priv->base + 11); + iowrite8(3, &priv->reg->acfg); break; default: return -EINVAL; @@ -153,7 +179,7 @@ static int stx104_write_raw(struct iio_dev *indio_dev, return -EINVAL;
priv->chan_out_states[chan->channel] = val; - iowrite16(val, priv->base + 4 + 2 * chan->channel); + iowrite16(val, &priv->reg->dac[chan->channel]);
return 0; } @@ -307,15 +333,15 @@ static int stx104_probe(struct device *dev, unsigned int id) }
priv = iio_priv(indio_dev); - priv->base = devm_ioport_map(dev, base[id], STX104_EXTENT); - if (!priv->base) + priv->reg = devm_ioport_map(dev, base[id], STX104_EXTENT); + if (!priv->reg) return -ENOMEM;
indio_dev->info = &stx104_info; indio_dev->modes = INDIO_DIRECT_MODE;
/* determine if differential inputs */ - if (ioread8(priv->base + 8) & BIT(5)) { + if (ioread8(&priv->reg->cir_asr) & BIT(5)) { indio_dev->num_channels = ARRAY_SIZE(stx104_channels_diff); indio_dev->channels = stx104_channels_diff; } else { @@ -326,14 +352,14 @@ static int stx104_probe(struct device *dev, unsigned int id) indio_dev->name = dev_name(dev);
/* configure device for software trigger operation */ - iowrite8(0, priv->base + 9); + iowrite8(0, &priv->reg->acr);
/* initialize gain setting to x1 */ - iowrite8(0, priv->base + 11); + iowrite8(0, &priv->reg->acfg);
/* initialize DAC output to 0V */ - iowrite16(0, priv->base + 4); - iowrite16(0, priv->base + 6); + iowrite16(0, &priv->reg->dac[0]); + iowrite16(0, &priv->reg->dac[1]);
stx104gpio->chip.label = dev_name(dev); stx104gpio->chip.parent = dev; @@ -348,7 +374,7 @@ static int stx104_probe(struct device *dev, unsigned int id) stx104gpio->chip.get_multiple = stx104_gpio_get_multiple; stx104gpio->chip.set = stx104_gpio_set; stx104gpio->chip.set_multiple = stx104_gpio_set_multiple; - stx104gpio->base = priv->base + 3; + stx104gpio->base = &priv->reg->dio; stx104gpio->out_state = 0x0;
spin_lock_init(&stx104gpio->lock);
From: William Breathitt Gray william.gray@linaro.org
[ Upstream commit 9740827468cea80c42db29e7171a50e99acf7328 ]
The priv->chan_out_states array and actual DAC value can become mismatched if stx104_write_raw() is called concurrently. Prevent such a race condition by utilizing a mutex.
Fixes: 97a445dad37a ("iio: Add IIO support for the DAC on the Apex Embedded Systems STX104") Signed-off-by: William Breathitt Gray william.gray@linaro.org Link: https://lore.kernel.org/r/c95c9a77fcef36b2a052282146950f23bbc1ebdc.168079058... Cc: Stable@vger.kernel.org Signed-off-by: Jonathan Cameron Jonathan.Cameron@huawei.com Stable-dep-of: 4f9b80aefb9e ("iio: addac: stx104: Fix race condition when converting analog-to-digital") Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/iio/adc/stx104.c | 8 ++++++++ 1 file changed, 8 insertions(+)
diff --git a/drivers/iio/adc/stx104.c b/drivers/iio/adc/stx104.c index 48a91a95e597b..e110a910235ff 100644 --- a/drivers/iio/adc/stx104.c +++ b/drivers/iio/adc/stx104.c @@ -15,6 +15,7 @@ #include <linux/kernel.h> #include <linux/module.h> #include <linux/moduleparam.h> +#include <linux/mutex.h> #include <linux/spinlock.h> #include <linux/types.h>
@@ -69,10 +70,12 @@ struct stx104_reg {
/** * struct stx104_iio - IIO device private data structure + * @lock: synchronization lock to prevent I/O race conditions * @chan_out_states: channels' output states * @reg: I/O address offset for the device registers */ struct stx104_iio { + struct mutex lock; unsigned int chan_out_states[STX104_NUM_OUT_CHAN]; struct stx104_reg __iomem *reg; }; @@ -178,9 +181,12 @@ static int stx104_write_raw(struct iio_dev *indio_dev, if ((unsigned int)val > 65535) return -EINVAL;
+ mutex_lock(&priv->lock); + priv->chan_out_states[chan->channel] = val; iowrite16(val, &priv->reg->dac[chan->channel]);
+ mutex_unlock(&priv->lock); return 0; } return -EINVAL; @@ -351,6 +357,8 @@ static int stx104_probe(struct device *dev, unsigned int id)
indio_dev->name = dev_name(dev);
+ mutex_init(&priv->lock); + /* configure device for software trigger operation */ iowrite8(0, &priv->reg->acr);
From: William Breathitt Gray william.gray@linaro.org
[ Upstream commit 4f9b80aefb9e2f542a49d9ec087cf5919730e1dd ]
The ADC conversion procedure requires several device I/O operations performed in a particular sequence. If stx104_read_raw() is called concurrently, the ADC conversion procedure could be clobbered. Prevent such a race condition by utilizing a mutex.
Fixes: 4075a283ae83 ("iio: stx104: Add IIO support for the ADC channels") Signed-off-by: William Breathitt Gray william.gray@linaro.org Link: https://lore.kernel.org/r/2ae5e40eed5006ca735e4c12181a9ff5ced65547.168079058... Cc: Stable@vger.kernel.org Signed-off-by: Jonathan Cameron Jonathan.Cameron@huawei.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/iio/adc/stx104.c | 4 ++++ 1 file changed, 4 insertions(+)
diff --git a/drivers/iio/adc/stx104.c b/drivers/iio/adc/stx104.c index e110a910235ff..b658a75d4e3a8 100644 --- a/drivers/iio/adc/stx104.c +++ b/drivers/iio/adc/stx104.c @@ -117,6 +117,8 @@ static int stx104_read_raw(struct iio_dev *indio_dev, return IIO_VAL_INT; }
+ mutex_lock(&priv->lock); + /* select ADC channel */ iowrite8(chan->channel | (chan->channel << 4), ®->achan);
@@ -127,6 +129,8 @@ static int stx104_read_raw(struct iio_dev *indio_dev, while (ioread8(®->cir_asr) & BIT(7));
*val = ioread16(®->ssr_ad); + + mutex_unlock(&priv->lock); return IIO_VAL_INT; case IIO_CHAN_INFO_OFFSET: /* get ADC bipolar/unipolar configuration */
From: Loic Poulain loic.poulain@linaro.org
[ Upstream commit 855a70c12021bdc5df60512f1d3f6d492dc715be ]
This is a generic MHI-over-PCI controller driver for MHI only devices such as QCOM modems. For now it supports registering of Qualcomm SDX55 based PCIe modules. The MHI channels have been extracted from mhi downstream driver.
This driver is for MHI-only devices which have all functionalities exposed through MHI channels and accessed by the corresponding MHI device drivers (no out-of-band communication).
Signed-off-by: Loic Poulain loic.poulain@linaro.org Reviewed-by: Bhaumik Bhatt bbhatt@codeaurora.org Reviewed-by: Hemant Kumar hemantk@codeaurora.org Reviewed-by: Manivannan Sadhasivam manivannan.sadhasivam@linaro.org [mani: fixed up the Makefile rule] Signed-off-by: Manivannan Sadhasivam manivannan.sadhasivam@linaro.org Stable-dep-of: 6a0c637bfee6 ("bus: mhi: host: Range check CHDBOFF and ERDBOFF") Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/bus/mhi/Kconfig | 9 + drivers/bus/mhi/Makefile | 4 + drivers/bus/mhi/pci_generic.c | 345 ++++++++++++++++++++++++++++++++++ 3 files changed, 358 insertions(+) create mode 100644 drivers/bus/mhi/pci_generic.c
diff --git a/drivers/bus/mhi/Kconfig b/drivers/bus/mhi/Kconfig index e841c1097fb4d..da5cd0c9fc620 100644 --- a/drivers/bus/mhi/Kconfig +++ b/drivers/bus/mhi/Kconfig @@ -20,3 +20,12 @@ config MHI_BUS_DEBUG Enable debugfs support for use with the MHI transport. Allows reading and/or modifying some values within the MHI controller for debug and test purposes. + +config MHI_BUS_PCI_GENERIC + tristate "MHI PCI controller driver" + depends on MHI_BUS + depends on PCI + help + This driver provides MHI PCI controller driver for devices such as + Qualcomm SDX55 based PCIe modems. + diff --git a/drivers/bus/mhi/Makefile b/drivers/bus/mhi/Makefile index 19e6443b72df4..0a2d778d6fb42 100644 --- a/drivers/bus/mhi/Makefile +++ b/drivers/bus/mhi/Makefile @@ -1,2 +1,6 @@ # core layer obj-y += core/ + +obj-$(CONFIG_MHI_BUS_PCI_GENERIC) += mhi_pci_generic.o +mhi_pci_generic-y += pci_generic.o + diff --git a/drivers/bus/mhi/pci_generic.c b/drivers/bus/mhi/pci_generic.c new file mode 100644 index 0000000000000..e3df838c3c80e --- /dev/null +++ b/drivers/bus/mhi/pci_generic.c @@ -0,0 +1,345 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * MHI PCI driver - MHI over PCI controller driver + * + * This module is a generic driver for registering MHI-over-PCI devices, + * such as PCIe QCOM modems. + * + * Copyright (C) 2020 Linaro Ltd loic.poulain@linaro.org + */ + +#include <linux/device.h> +#include <linux/mhi.h> +#include <linux/module.h> +#include <linux/pci.h> + +#define MHI_PCI_DEFAULT_BAR_NUM 0 + +/** + * struct mhi_pci_dev_info - MHI PCI device specific information + * @config: MHI controller configuration + * @name: name of the PCI module + * @fw: firmware path (if any) + * @edl: emergency download mode firmware path (if any) + * @bar_num: PCI base address register to use for MHI MMIO register space + * @dma_data_width: DMA transfer word size (32 or 64 bits) + */ +struct mhi_pci_dev_info { + const struct mhi_controller_config *config; + const char *name; + const char *fw; + const char *edl; + unsigned int bar_num; + unsigned int dma_data_width; +}; + +#define MHI_CHANNEL_CONFIG_UL(ch_num, ch_name, el_count, ev_ring) \ + { \ + .num = ch_num, \ + .name = ch_name, \ + .num_elements = el_count, \ + .event_ring = ev_ring, \ + .dir = DMA_TO_DEVICE, \ + .ee_mask = BIT(MHI_EE_AMSS), \ + .pollcfg = 0, \ + .doorbell = MHI_DB_BRST_DISABLE, \ + .lpm_notify = false, \ + .offload_channel = false, \ + .doorbell_mode_switch = false, \ + } \ + +#define MHI_CHANNEL_CONFIG_DL(ch_num, ch_name, el_count, ev_ring) \ + { \ + .num = ch_num, \ + .name = ch_name, \ + .num_elements = el_count, \ + .event_ring = ev_ring, \ + .dir = DMA_FROM_DEVICE, \ + .ee_mask = BIT(MHI_EE_AMSS), \ + .pollcfg = 0, \ + .doorbell = MHI_DB_BRST_DISABLE, \ + .lpm_notify = false, \ + .offload_channel = false, \ + .doorbell_mode_switch = false, \ + } + +#define MHI_EVENT_CONFIG_CTRL(ev_ring) \ + { \ + .num_elements = 64, \ + .irq_moderation_ms = 0, \ + .irq = (ev_ring) + 1, \ + .priority = 1, \ + .mode = MHI_DB_BRST_DISABLE, \ + .data_type = MHI_ER_CTRL, \ + .hardware_event = false, \ + .client_managed = false, \ + .offload_channel = false, \ + } + +#define MHI_EVENT_CONFIG_DATA(ev_ring) \ + { \ + .num_elements = 128, \ + .irq_moderation_ms = 5, \ + .irq = (ev_ring) + 1, \ + .priority = 1, \ + .mode = MHI_DB_BRST_DISABLE, \ + .data_type = MHI_ER_DATA, \ + .hardware_event = false, \ + .client_managed = false, \ + .offload_channel = false, \ + } + +#define MHI_EVENT_CONFIG_HW_DATA(ev_ring, ch_num) \ + { \ + .num_elements = 128, \ + .irq_moderation_ms = 5, \ + .irq = (ev_ring) + 1, \ + .priority = 1, \ + .mode = MHI_DB_BRST_DISABLE, \ + .data_type = MHI_ER_DATA, \ + .hardware_event = true, \ + .client_managed = false, \ + .offload_channel = false, \ + .channel = ch_num, \ + } + +static const struct mhi_channel_config modem_qcom_v1_mhi_channels[] = { + MHI_CHANNEL_CONFIG_UL(12, "MBIM", 4, 0), + MHI_CHANNEL_CONFIG_DL(13, "MBIM", 4, 0), + MHI_CHANNEL_CONFIG_UL(14, "QMI", 4, 0), + MHI_CHANNEL_CONFIG_DL(15, "QMI", 4, 0), + MHI_CHANNEL_CONFIG_UL(20, "IPCR", 8, 0), + MHI_CHANNEL_CONFIG_DL(21, "IPCR", 8, 0), + MHI_CHANNEL_CONFIG_UL(100, "IP_HW0", 128, 1), + MHI_CHANNEL_CONFIG_DL(101, "IP_HW0", 128, 2), +}; + +static const struct mhi_event_config modem_qcom_v1_mhi_events[] = { + /* first ring is control+data ring */ + MHI_EVENT_CONFIG_CTRL(0), + /* Hardware channels request dedicated hardware event rings */ + MHI_EVENT_CONFIG_HW_DATA(1, 100), + MHI_EVENT_CONFIG_HW_DATA(2, 101) +}; + +static const struct mhi_controller_config modem_qcom_v1_mhiv_config = { + .max_channels = 128, + .timeout_ms = 5000, + .num_channels = ARRAY_SIZE(modem_qcom_v1_mhi_channels), + .ch_cfg = modem_qcom_v1_mhi_channels, + .num_events = ARRAY_SIZE(modem_qcom_v1_mhi_events), + .event_cfg = modem_qcom_v1_mhi_events, +}; + +static const struct mhi_pci_dev_info mhi_qcom_sdx55_info = { + .name = "qcom-sdx55m", + .fw = "qcom/sdx55m/sbl1.mbn", + .edl = "qcom/sdx55m/edl.mbn", + .config = &modem_qcom_v1_mhiv_config, + .bar_num = MHI_PCI_DEFAULT_BAR_NUM, + .dma_data_width = 32 +}; + +static const struct pci_device_id mhi_pci_id_table[] = { + { PCI_DEVICE(PCI_VENDOR_ID_QCOM, 0x0306), + .driver_data = (kernel_ulong_t) &mhi_qcom_sdx55_info }, + { } +}; +MODULE_DEVICE_TABLE(pci, mhi_pci_id_table); + +static int mhi_pci_read_reg(struct mhi_controller *mhi_cntrl, + void __iomem *addr, u32 *out) +{ + *out = readl(addr); + return 0; +} + +static void mhi_pci_write_reg(struct mhi_controller *mhi_cntrl, + void __iomem *addr, u32 val) +{ + writel(val, addr); +} + +static void mhi_pci_status_cb(struct mhi_controller *mhi_cntrl, + enum mhi_callback cb) +{ + /* Nothing to do for now */ +} + +static int mhi_pci_claim(struct mhi_controller *mhi_cntrl, + unsigned int bar_num, u64 dma_mask) +{ + struct pci_dev *pdev = to_pci_dev(mhi_cntrl->cntrl_dev); + int err; + + err = pci_assign_resource(pdev, bar_num); + if (err) + return err; + + err = pcim_enable_device(pdev); + if (err) { + dev_err(&pdev->dev, "failed to enable pci device: %d\n", err); + return err; + } + + err = pcim_iomap_regions(pdev, 1 << bar_num, pci_name(pdev)); + if (err) { + dev_err(&pdev->dev, "failed to map pci region: %d\n", err); + return err; + } + mhi_cntrl->regs = pcim_iomap_table(pdev)[bar_num]; + + err = pci_set_dma_mask(pdev, dma_mask); + if (err) { + dev_err(&pdev->dev, "Cannot set proper DMA mask\n"); + return err; + } + + err = pci_set_consistent_dma_mask(pdev, dma_mask); + if (err) { + dev_err(&pdev->dev, "set consistent dma mask failed\n"); + return err; + } + + pci_set_master(pdev); + + return 0; +} + +static int mhi_pci_get_irqs(struct mhi_controller *mhi_cntrl, + const struct mhi_controller_config *mhi_cntrl_config) +{ + struct pci_dev *pdev = to_pci_dev(mhi_cntrl->cntrl_dev); + int nr_vectors, i; + int *irq; + + /* + * Alloc one MSI vector for BHI + one vector per event ring, ideally... + * No explicit pci_free_irq_vectors required, done by pcim_release. + */ + mhi_cntrl->nr_irqs = 1 + mhi_cntrl_config->num_events; + + nr_vectors = pci_alloc_irq_vectors(pdev, 1, mhi_cntrl->nr_irqs, PCI_IRQ_MSI); + if (nr_vectors < 0) { + dev_err(&pdev->dev, "Error allocating MSI vectors %d\n", + nr_vectors); + return nr_vectors; + } + + if (nr_vectors < mhi_cntrl->nr_irqs) { + dev_warn(&pdev->dev, "Not enough MSI vectors (%d/%d), use shared MSI\n", + nr_vectors, mhi_cntrl_config->num_events); + } + + irq = devm_kcalloc(&pdev->dev, mhi_cntrl->nr_irqs, sizeof(int), GFP_KERNEL); + if (!irq) + return -ENOMEM; + + for (i = 0; i < mhi_cntrl->nr_irqs; i++) { + int vector = i >= nr_vectors ? (nr_vectors - 1) : i; + + irq[i] = pci_irq_vector(pdev, vector); + } + + mhi_cntrl->irq = irq; + + return 0; +} + +static int mhi_pci_runtime_get(struct mhi_controller *mhi_cntrl) +{ + /* no PM for now */ + return 0; +} + +static void mhi_pci_runtime_put(struct mhi_controller *mhi_cntrl) +{ + /* no PM for now */ +} + +static int mhi_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) +{ + const struct mhi_pci_dev_info *info = (struct mhi_pci_dev_info *) id->driver_data; + const struct mhi_controller_config *mhi_cntrl_config; + struct mhi_controller *mhi_cntrl; + int err; + + dev_dbg(&pdev->dev, "MHI PCI device found: %s\n", info->name); + + mhi_cntrl = mhi_alloc_controller(); + if (!mhi_cntrl) + return -ENOMEM; + + mhi_cntrl_config = info->config; + mhi_cntrl->cntrl_dev = &pdev->dev; + mhi_cntrl->iova_start = 0; + mhi_cntrl->iova_stop = DMA_BIT_MASK(info->dma_data_width); + mhi_cntrl->fw_image = info->fw; + mhi_cntrl->edl_image = info->edl; + + mhi_cntrl->read_reg = mhi_pci_read_reg; + mhi_cntrl->write_reg = mhi_pci_write_reg; + mhi_cntrl->status_cb = mhi_pci_status_cb; + mhi_cntrl->runtime_get = mhi_pci_runtime_get; + mhi_cntrl->runtime_put = mhi_pci_runtime_put; + + err = mhi_pci_claim(mhi_cntrl, info->bar_num, DMA_BIT_MASK(info->dma_data_width)); + if (err) + goto err_release; + + err = mhi_pci_get_irqs(mhi_cntrl, mhi_cntrl_config); + if (err) + goto err_release; + + pci_set_drvdata(pdev, mhi_cntrl); + + err = mhi_register_controller(mhi_cntrl, mhi_cntrl_config); + if (err) + goto err_release; + + /* MHI bus does not power up the controller by default */ + err = mhi_prepare_for_power_up(mhi_cntrl); + if (err) { + dev_err(&pdev->dev, "failed to prepare MHI controller\n"); + goto err_unregister; + } + + err = mhi_sync_power_up(mhi_cntrl); + if (err) { + dev_err(&pdev->dev, "failed to power up MHI controller\n"); + goto err_unprepare; + } + + return 0; + +err_unprepare: + mhi_unprepare_after_power_down(mhi_cntrl); +err_unregister: + mhi_unregister_controller(mhi_cntrl); +err_release: + mhi_free_controller(mhi_cntrl); + + return err; +} + +static void mhi_pci_remove(struct pci_dev *pdev) +{ + struct mhi_controller *mhi_cntrl = pci_get_drvdata(pdev); + + mhi_power_down(mhi_cntrl, true); + mhi_unprepare_after_power_down(mhi_cntrl); + mhi_unregister_controller(mhi_cntrl); + mhi_free_controller(mhi_cntrl); +} + +static struct pci_driver mhi_pci_driver = { + .name = "mhi-pci-generic", + .id_table = mhi_pci_id_table, + .probe = mhi_pci_probe, + .remove = mhi_pci_remove +}; +module_pci_driver(mhi_pci_driver); + +MODULE_AUTHOR("Loic Poulain loic.poulain@linaro.org"); +MODULE_DESCRIPTION("Modem Host Interface (MHI) PCI controller driver"); +MODULE_LICENSE("GPL");
From: Bhaumik Bhatt bbhatt@codeaurora.org
[ Upstream commit baa7a08569358d9d16e71ce36f287c39a665d776 ]
Make controller driver specify the MMIO register region length for range checking of BHI or BHIe space. This can help validate that offsets are in acceptable memory region or not and avoid any boot-up issues due to BHI or BHIe memory accesses.
Link: https://lore.kernel.org/r/1620330705-40192-4-git-send-email-bbhatt@codeauror... Reviewed-by: Jeffrey Hugo quic_jhugo@quicinc.com Reviewed-by: Hemant Kumar hemantk@codeaurora.org Reviewed-by: Manivannan Sadhasivam manivannan.sadhasivam@linaro.org Signed-off-by: Bhaumik Bhatt bbhatt@codeaurora.org Signed-off-by: Manivannan Sadhasivam manivannan.sadhasivam@linaro.org Link: https://lore.kernel.org/r/20210802051255.5771-6-manivannan.sadhasivam@linaro... Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org Stable-dep-of: 6a0c637bfee6 ("bus: mhi: host: Range check CHDBOFF and ERDBOFF") Signed-off-by: Sasha Levin sashal@kernel.org --- include/linux/mhi.h | 2 ++ 1 file changed, 2 insertions(+)
diff --git a/include/linux/mhi.h b/include/linux/mhi.h index d4841e5a5f458..5d9f8c6f3d40f 100644 --- a/include/linux/mhi.h +++ b/include/linux/mhi.h @@ -303,6 +303,7 @@ struct mhi_controller_config { * @rddm_size: RAM dump size that host should allocate for debugging purpose * @sbl_size: SBL image size downloaded through BHIe (optional) * @seg_len: BHIe vector size (optional) + * @reg_len: Length of the MHI MMIO region (required) * @fbc_image: Points to firmware image buffer * @rddm_image: Points to RAM dump buffer * @mhi_chan: Points to the channel configuration table @@ -383,6 +384,7 @@ struct mhi_controller { size_t rddm_size; size_t sbl_size; size_t seg_len; + size_t reg_len; struct image_info *fbc_image; struct image_info *rddm_image; struct mhi_chan *mhi_chan;
From: Manivannan Sadhasivam manivannan.sadhasivam@linaro.org
[ Upstream commit a0f5a630668cb8b2ebf5204f08e957875e991780 ]
In preparation of the endpoint MHI support, let's move the host MHI code to its own "host" directory and adjust the toplevel MHI Kconfig & Makefile.
While at it, let's also move the "pci_generic" driver to "host" directory as it is a host MHI controller driver.
Reviewed-by: Hemant Kumar hemantk@codeaurora.org Reviewed-by: Alex Elder elder@linaro.org Signed-off-by: Manivannan Sadhasivam manivannan.sadhasivam@linaro.org Link: https://lore.kernel.org/r/20220301160308.107452-5-manivannan.sadhasivam@lina... Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org Stable-dep-of: 6a0c637bfee6 ("bus: mhi: host: Range check CHDBOFF and ERDBOFF") Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/bus/Makefile | 2 +- drivers/bus/mhi/Kconfig | 27 ++------------------ drivers/bus/mhi/Makefile | 8 ++---- drivers/bus/mhi/host/Kconfig | 31 +++++++++++++++++++++++ drivers/bus/mhi/{core => host}/Makefile | 4 ++- drivers/bus/mhi/{core => host}/boot.c | 0 drivers/bus/mhi/{core => host}/debugfs.c | 0 drivers/bus/mhi/{core => host}/init.c | 0 drivers/bus/mhi/{core => host}/internal.h | 0 drivers/bus/mhi/{core => host}/main.c | 0 drivers/bus/mhi/{ => host}/pci_generic.c | 0 drivers/bus/mhi/{core => host}/pm.c | 0 12 files changed, 39 insertions(+), 33 deletions(-) create mode 100644 drivers/bus/mhi/host/Kconfig rename drivers/bus/mhi/{core => host}/Makefile (54%) rename drivers/bus/mhi/{core => host}/boot.c (100%) rename drivers/bus/mhi/{core => host}/debugfs.c (100%) rename drivers/bus/mhi/{core => host}/init.c (100%) rename drivers/bus/mhi/{core => host}/internal.h (100%) rename drivers/bus/mhi/{core => host}/main.c (100%) rename drivers/bus/mhi/{ => host}/pci_generic.c (100%) rename drivers/bus/mhi/{core => host}/pm.c (100%)
diff --git a/drivers/bus/Makefile b/drivers/bus/Makefile index 397e35392bff8..16c47a0616ae4 100644 --- a/drivers/bus/Makefile +++ b/drivers/bus/Makefile @@ -38,4 +38,4 @@ obj-$(CONFIG_VEXPRESS_CONFIG) += vexpress-config.o obj-$(CONFIG_DA8XX_MSTPRI) += da8xx-mstpri.o
# MHI -obj-$(CONFIG_MHI_BUS) += mhi/ +obj-y += mhi/ diff --git a/drivers/bus/mhi/Kconfig b/drivers/bus/mhi/Kconfig index da5cd0c9fc620..4748df7f9cd58 100644 --- a/drivers/bus/mhi/Kconfig +++ b/drivers/bus/mhi/Kconfig @@ -2,30 +2,7 @@ # # MHI bus # -# Copyright (c) 2018-2020, The Linux Foundation. All rights reserved. +# Copyright (c) 2021, Linaro Ltd. #
-config MHI_BUS - tristate "Modem Host Interface (MHI) bus" - help - Bus driver for MHI protocol. Modem Host Interface (MHI) is a - communication protocol used by the host processors to control - and communicate with modem devices over a high speed peripheral - bus or shared memory. - -config MHI_BUS_DEBUG - bool "Debugfs support for the MHI bus" - depends on MHI_BUS && DEBUG_FS - help - Enable debugfs support for use with the MHI transport. Allows - reading and/or modifying some values within the MHI controller - for debug and test purposes. - -config MHI_BUS_PCI_GENERIC - tristate "MHI PCI controller driver" - depends on MHI_BUS - depends on PCI - help - This driver provides MHI PCI controller driver for devices such as - Qualcomm SDX55 based PCIe modems. - +source "drivers/bus/mhi/host/Kconfig" diff --git a/drivers/bus/mhi/Makefile b/drivers/bus/mhi/Makefile index 0a2d778d6fb42..5f5708a249f54 100644 --- a/drivers/bus/mhi/Makefile +++ b/drivers/bus/mhi/Makefile @@ -1,6 +1,2 @@ -# core layer -obj-y += core/ - -obj-$(CONFIG_MHI_BUS_PCI_GENERIC) += mhi_pci_generic.o -mhi_pci_generic-y += pci_generic.o - +# Host MHI stack +obj-y += host/ diff --git a/drivers/bus/mhi/host/Kconfig b/drivers/bus/mhi/host/Kconfig new file mode 100644 index 0000000000000..da5cd0c9fc620 --- /dev/null +++ b/drivers/bus/mhi/host/Kconfig @@ -0,0 +1,31 @@ +# SPDX-License-Identifier: GPL-2.0 +# +# MHI bus +# +# Copyright (c) 2018-2020, The Linux Foundation. All rights reserved. +# + +config MHI_BUS + tristate "Modem Host Interface (MHI) bus" + help + Bus driver for MHI protocol. Modem Host Interface (MHI) is a + communication protocol used by the host processors to control + and communicate with modem devices over a high speed peripheral + bus or shared memory. + +config MHI_BUS_DEBUG + bool "Debugfs support for the MHI bus" + depends on MHI_BUS && DEBUG_FS + help + Enable debugfs support for use with the MHI transport. Allows + reading and/or modifying some values within the MHI controller + for debug and test purposes. + +config MHI_BUS_PCI_GENERIC + tristate "MHI PCI controller driver" + depends on MHI_BUS + depends on PCI + help + This driver provides MHI PCI controller driver for devices such as + Qualcomm SDX55 based PCIe modems. + diff --git a/drivers/bus/mhi/core/Makefile b/drivers/bus/mhi/host/Makefile similarity index 54% rename from drivers/bus/mhi/core/Makefile rename to drivers/bus/mhi/host/Makefile index c3feb4130aa37..859c2f38451c6 100644 --- a/drivers/bus/mhi/core/Makefile +++ b/drivers/bus/mhi/host/Makefile @@ -1,4 +1,6 @@ obj-$(CONFIG_MHI_BUS) += mhi.o - mhi-y := init.o main.o pm.o boot.o mhi-$(CONFIG_MHI_BUS_DEBUG) += debugfs.o + +obj-$(CONFIG_MHI_BUS_PCI_GENERIC) += mhi_pci_generic.o +mhi_pci_generic-y += pci_generic.o diff --git a/drivers/bus/mhi/core/boot.c b/drivers/bus/mhi/host/boot.c similarity index 100% rename from drivers/bus/mhi/core/boot.c rename to drivers/bus/mhi/host/boot.c diff --git a/drivers/bus/mhi/core/debugfs.c b/drivers/bus/mhi/host/debugfs.c similarity index 100% rename from drivers/bus/mhi/core/debugfs.c rename to drivers/bus/mhi/host/debugfs.c diff --git a/drivers/bus/mhi/core/init.c b/drivers/bus/mhi/host/init.c similarity index 100% rename from drivers/bus/mhi/core/init.c rename to drivers/bus/mhi/host/init.c diff --git a/drivers/bus/mhi/core/internal.h b/drivers/bus/mhi/host/internal.h similarity index 100% rename from drivers/bus/mhi/core/internal.h rename to drivers/bus/mhi/host/internal.h diff --git a/drivers/bus/mhi/core/main.c b/drivers/bus/mhi/host/main.c similarity index 100% rename from drivers/bus/mhi/core/main.c rename to drivers/bus/mhi/host/main.c diff --git a/drivers/bus/mhi/pci_generic.c b/drivers/bus/mhi/host/pci_generic.c similarity index 100% rename from drivers/bus/mhi/pci_generic.c rename to drivers/bus/mhi/host/pci_generic.c diff --git a/drivers/bus/mhi/core/pm.c b/drivers/bus/mhi/host/pm.c similarity index 100% rename from drivers/bus/mhi/core/pm.c rename to drivers/bus/mhi/host/pm.c
From: Jeffrey Hugo quic_jhugo@quicinc.com
[ Upstream commit 6a0c637bfee69a74c104468544d9f2a6579626d0 ]
If the value read from the CHDBOFF and ERDBOFF registers is outside the range of the MHI register space then an invalid address might be computed which later causes a kernel panic. Range check the read value to prevent a crash due to bad data from the device.
Fixes: 6cd330ae76ff ("bus: mhi: core: Add support for ringing channel/event ring doorbells") Cc: stable@vger.kernel.org Signed-off-by: Jeffrey Hugo quic_jhugo@quicinc.com Reviewed-by: Pranjal Ramajor Asha Kanojiya quic_pkanojiy@quicinc.com Reviewed-by: Manivannan Sadhasivam mani@kernel.org Link: https://lore.kernel.org/r/1679674384-27209-1-git-send-email-quic_jhugo@quici... Signed-off-by: Manivannan Sadhasivam manivannan.sadhasivam@linaro.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/bus/mhi/host/init.c | 12 ++++++++++++ 1 file changed, 12 insertions(+)
diff --git a/drivers/bus/mhi/host/init.c b/drivers/bus/mhi/host/init.c index 0d0386f67ffe2..2cc48f96afdbc 100644 --- a/drivers/bus/mhi/host/init.c +++ b/drivers/bus/mhi/host/init.c @@ -498,6 +498,12 @@ int mhi_init_mmio(struct mhi_controller *mhi_cntrl) return -EIO; }
+ if (val >= mhi_cntrl->reg_len - (8 * MHI_DEV_WAKE_DB)) { + dev_err(dev, "CHDB offset: 0x%x is out of range: 0x%zx\n", + val, mhi_cntrl->reg_len - (8 * MHI_DEV_WAKE_DB)); + return -ERANGE; + } + /* Setup wake db */ mhi_cntrl->wake_db = base + val + (8 * MHI_DEV_WAKE_DB); mhi_write_reg(mhi_cntrl, mhi_cntrl->wake_db, 4, 0); @@ -517,6 +523,12 @@ int mhi_init_mmio(struct mhi_controller *mhi_cntrl) return -EIO; }
+ if (val >= mhi_cntrl->reg_len - (8 * mhi_cntrl->total_ev_rings)) { + dev_err(dev, "ERDB offset: 0x%x is out of range: 0x%zx\n", + val, mhi_cntrl->reg_len - (8 * mhi_cntrl->total_ev_rings)); + return -ERANGE; + } + /* Setup event db address for each ev_ring */ mhi_event = mhi_cntrl->mhi_event; for (i = 0; i < mhi_cntrl->total_ev_rings; i++, val += 8, mhi_event++) {
From: Marc Zyngier maz@kernel.org
[ Upstream commit dd098a0e031928cf88c89f7577d31821e1f0e6de ]
The MIPS GIC driver uses irq_cpu_online() to go and program the per-CPU interrupts. However, this method iterates over all IRQs in the system, despite only 3 per-CPU interrupts being of interest.
Let's be terribly bold and do the iteration ourselves. To ensure mutual exclusion, hold the gic_lock spinlock that is otherwise taken while dealing with these interrupts.
Signed-off-by: Marc Zyngier maz@kernel.org Reviewed-by: Serge Semin fancer.lancer@gmail.com Reviewed-by: Florian Fainelli f.fainelli@gmail.com Tested-by: Serge Semin fancer.lancer@gmail.com Link: https://lore.kernel.org/r/20211021170414.3341522-3-maz@kernel.org Stable-dep-of: 3d6a0e4197c0 ("irqchip/mips-gic: Use raw spinlock for gic_lock") Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/irqchip/irq-mips-gic.c | 37 ++++++++++++++++++++++++---------- 1 file changed, 26 insertions(+), 11 deletions(-)
diff --git a/drivers/irqchip/irq-mips-gic.c b/drivers/irqchip/irq-mips-gic.c index 8ada91bdbe4d0..7e4a9e75b49be 100644 --- a/drivers/irqchip/irq-mips-gic.c +++ b/drivers/irqchip/irq-mips-gic.c @@ -382,24 +382,35 @@ static void gic_unmask_local_irq_all_vpes(struct irq_data *d) spin_unlock_irqrestore(&gic_lock, flags); }
-static void gic_all_vpes_irq_cpu_online(struct irq_data *d) +static void gic_all_vpes_irq_cpu_online(void) { - struct gic_all_vpes_chip_data *cd; - unsigned int intr; + static const unsigned int local_intrs[] = { + GIC_LOCAL_INT_TIMER, + GIC_LOCAL_INT_PERFCTR, + GIC_LOCAL_INT_FDC, + }; + unsigned long flags; + int i;
- intr = GIC_HWIRQ_TO_LOCAL(d->hwirq); - cd = irq_data_get_irq_chip_data(d); + spin_lock_irqsave(&gic_lock, flags);
- write_gic_vl_map(mips_gic_vx_map_reg(intr), cd->map); - if (cd->mask) - write_gic_vl_smask(BIT(intr)); + for (i = 0; i < ARRAY_SIZE(local_intrs); i++) { + unsigned int intr = local_intrs[i]; + struct gic_all_vpes_chip_data *cd; + + cd = &gic_all_vpes_chip_data[intr]; + write_gic_vl_map(mips_gic_vx_map_reg(intr), cd->map); + if (cd->mask) + write_gic_vl_smask(BIT(intr)); + } + + spin_unlock_irqrestore(&gic_lock, flags); }
static struct irq_chip gic_all_vpes_local_irq_controller = { .name = "MIPS GIC Local", .irq_mask = gic_mask_local_irq_all_vpes, .irq_unmask = gic_unmask_local_irq_all_vpes, - .irq_cpu_online = gic_all_vpes_irq_cpu_online, };
static void __gic_irq_dispatch(void) @@ -480,6 +491,10 @@ static int gic_irq_domain_map(struct irq_domain *d, unsigned int virq, intr = GIC_HWIRQ_TO_LOCAL(hwirq); map = GIC_MAP_PIN_MAP_TO_PIN | gic_cpu_pin;
+ /* + * If adding support for more per-cpu interrupts, keep the the + * array in gic_all_vpes_irq_cpu_online() in sync. + */ switch (intr) { case GIC_LOCAL_INT_TIMER: /* CONFIG_MIPS_CMP workaround (see __gic_init) */ @@ -710,8 +725,8 @@ static int gic_cpu_startup(unsigned int cpu) /* Clear all local IRQ masks (ie. disable all local interrupts) */ write_gic_vl_rmask(~0);
- /* Invoke irq_cpu_online callbacks to enable desired interrupts */ - irq_cpu_online(); + /* Enable desired interrupts */ + gic_all_vpes_irq_cpu_online();
return 0; }
From: Jiaxun Yang jiaxun.yang@flygoat.com
[ Upstream commit 3d6a0e4197c04599d75d85a608c8bb16a630a38c ]
Since we may hold gic_lock in hardirq context, use raw spinlock makes more sense given that it is for low-level interrupt handling routine and the critical section is small.
Fixes BUG:
[ 0.426106] ============================= [ 0.426257] [ BUG: Invalid wait context ] [ 0.426422] 6.3.0-rc7-next-20230421-dirty #54 Not tainted [ 0.426638] ----------------------------- [ 0.426766] swapper/0/1 is trying to lock: [ 0.426954] ffffffff8104e7b8 (gic_lock){....}-{3:3}, at: gic_set_type+0x30/08
Fixes: 95150ae8b330 ("irqchip: mips-gic: Implement irq_set_type callback") Cc: stable@vger.kernel.org Signed-off-by: Jiaxun Yang jiaxun.yang@flygoat.com Reviewed-by: Serge Semin fancer.lancer@gmail.com Tested-by: Serge Semin fancer.lancer@gmail.com Signed-off-by: Marc Zyngier maz@kernel.org Link: https://lore.kernel.org/r/20230424103156.66753-3-jiaxun.yang@flygoat.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/irqchip/irq-mips-gic.c | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-)
diff --git a/drivers/irqchip/irq-mips-gic.c b/drivers/irqchip/irq-mips-gic.c index 7e4a9e75b49be..fc25b900cef71 100644 --- a/drivers/irqchip/irq-mips-gic.c +++ b/drivers/irqchip/irq-mips-gic.c @@ -48,7 +48,7 @@ void __iomem *mips_gic_base;
static DEFINE_PER_CPU_READ_MOSTLY(unsigned long[GIC_MAX_LONGS], pcpu_masks);
-static DEFINE_SPINLOCK(gic_lock); +static DEFINE_RAW_SPINLOCK(gic_lock); static struct irq_domain *gic_irq_domain; static int gic_shared_intrs; static unsigned int gic_cpu_pin; @@ -209,7 +209,7 @@ static int gic_set_type(struct irq_data *d, unsigned int type)
irq = GIC_HWIRQ_TO_SHARED(d->hwirq);
- spin_lock_irqsave(&gic_lock, flags); + raw_spin_lock_irqsave(&gic_lock, flags); switch (type & IRQ_TYPE_SENSE_MASK) { case IRQ_TYPE_EDGE_FALLING: pol = GIC_POL_FALLING_EDGE; @@ -249,7 +249,7 @@ static int gic_set_type(struct irq_data *d, unsigned int type) else irq_set_chip_handler_name_locked(d, &gic_level_irq_controller, handle_level_irq, NULL); - spin_unlock_irqrestore(&gic_lock, flags); + raw_spin_unlock_irqrestore(&gic_lock, flags);
return 0; } @@ -267,7 +267,7 @@ static int gic_set_affinity(struct irq_data *d, const struct cpumask *cpumask, return -EINVAL;
/* Assumption : cpumask refers to a single CPU */ - spin_lock_irqsave(&gic_lock, flags); + raw_spin_lock_irqsave(&gic_lock, flags);
/* Re-route this IRQ */ write_gic_map_vp(irq, BIT(mips_cm_vp_id(cpu))); @@ -278,7 +278,7 @@ static int gic_set_affinity(struct irq_data *d, const struct cpumask *cpumask, set_bit(irq, per_cpu_ptr(pcpu_masks, cpu));
irq_data_update_effective_affinity(d, cpumask_of(cpu)); - spin_unlock_irqrestore(&gic_lock, flags); + raw_spin_unlock_irqrestore(&gic_lock, flags);
return IRQ_SET_MASK_OK; } @@ -356,12 +356,12 @@ static void gic_mask_local_irq_all_vpes(struct irq_data *d) cd = irq_data_get_irq_chip_data(d); cd->mask = false;
- spin_lock_irqsave(&gic_lock, flags); + raw_spin_lock_irqsave(&gic_lock, flags); for_each_online_cpu(cpu) { write_gic_vl_other(mips_cm_vp_id(cpu)); write_gic_vo_rmask(BIT(intr)); } - spin_unlock_irqrestore(&gic_lock, flags); + raw_spin_unlock_irqrestore(&gic_lock, flags); }
static void gic_unmask_local_irq_all_vpes(struct irq_data *d) @@ -374,12 +374,12 @@ static void gic_unmask_local_irq_all_vpes(struct irq_data *d) cd = irq_data_get_irq_chip_data(d); cd->mask = true;
- spin_lock_irqsave(&gic_lock, flags); + raw_spin_lock_irqsave(&gic_lock, flags); for_each_online_cpu(cpu) { write_gic_vl_other(mips_cm_vp_id(cpu)); write_gic_vo_smask(BIT(intr)); } - spin_unlock_irqrestore(&gic_lock, flags); + raw_spin_unlock_irqrestore(&gic_lock, flags); }
static void gic_all_vpes_irq_cpu_online(void) @@ -392,7 +392,7 @@ static void gic_all_vpes_irq_cpu_online(void) unsigned long flags; int i;
- spin_lock_irqsave(&gic_lock, flags); + raw_spin_lock_irqsave(&gic_lock, flags);
for (i = 0; i < ARRAY_SIZE(local_intrs); i++) { unsigned int intr = local_intrs[i]; @@ -404,7 +404,7 @@ static void gic_all_vpes_irq_cpu_online(void) write_gic_vl_smask(BIT(intr)); }
- spin_unlock_irqrestore(&gic_lock, flags); + raw_spin_unlock_irqrestore(&gic_lock, flags); }
static struct irq_chip gic_all_vpes_local_irq_controller = { @@ -434,11 +434,11 @@ static int gic_shared_irq_domain_map(struct irq_domain *d, unsigned int virq,
data = irq_get_irq_data(virq);
- spin_lock_irqsave(&gic_lock, flags); + raw_spin_lock_irqsave(&gic_lock, flags); write_gic_map_pin(intr, GIC_MAP_PIN_MAP_TO_PIN | gic_cpu_pin); write_gic_map_vp(intr, BIT(mips_cm_vp_id(cpu))); irq_data_update_effective_affinity(data, cpumask_of(cpu)); - spin_unlock_irqrestore(&gic_lock, flags); + raw_spin_unlock_irqrestore(&gic_lock, flags);
return 0; } @@ -533,12 +533,12 @@ static int gic_irq_domain_map(struct irq_domain *d, unsigned int virq, if (!gic_local_irq_is_routable(intr)) return -EPERM;
- spin_lock_irqsave(&gic_lock, flags); + raw_spin_lock_irqsave(&gic_lock, flags); for_each_online_cpu(cpu) { write_gic_vl_other(mips_cm_vp_id(cpu)); write_gic_vo_map(mips_gic_vx_map_reg(intr), map); } - spin_unlock_irqrestore(&gic_lock, flags); + raw_spin_unlock_irqrestore(&gic_lock, flags);
return 0; }
From: Pawel Laszczak pawell@cadence.com
[ Upstream commit e93e58d2740282d32c0278fab283eb0ae158bb59 ]
Patch defines macros, registers and structures used by Device side driver.
Because the size of main patch is very big, I’ve decided to create separate patch for cdnsp-gadget.h. It should simplify reviewing the code.
Signed-off-by: Pawel Laszczak pawell@cadence.com Signed-off-by: Peter Chen peter.chen@nxp.com Stable-dep-of: dbe678f6192f ("usb: cdns3: fix NCM gadget RX speed 20x slow than expection at iMX8QM") Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/usb/cdns3/cdnsp-gadget.h | 1463 ++++++++++++++++++++++++++++++ 1 file changed, 1463 insertions(+) create mode 100644 drivers/usb/cdns3/cdnsp-gadget.h
diff --git a/drivers/usb/cdns3/cdnsp-gadget.h b/drivers/usb/cdns3/cdnsp-gadget.h new file mode 100644 index 0000000000000..93da1dcdad600 --- /dev/null +++ b/drivers/usb/cdns3/cdnsp-gadget.h @@ -0,0 +1,1463 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Cadence CDNSP DRD Driver. + * + * Copyright (C) 2020 Cadence. + * + * Author: Pawel Laszczak pawell@cadence.com + * + * Code based on Linux XHCI driver. + * Origin: Copyright (C) 2008 Intel Corp. + */ +#ifndef __LINUX_CDNSP_GADGET_H +#define __LINUX_CDNSP_GADGET_H + +#include <linux/io-64-nonatomic-lo-hi.h> +#include <linux/usb/gadget.h> +#include <linux/irq.h> + +/* Max number slots - only 1 is allowed. */ +#define CDNSP_DEV_MAX_SLOTS 1 + +#define CDNSP_EP0_SETUP_SIZE 512 + +/* One control and 15 for in and 15 for out endpoints. */ +#define CDNSP_ENDPOINTS_NUM 31 + +/* Best Effort Service Latency. */ +#define CDNSP_DEFAULT_BESL 0 + +/* Device Controller command default timeout value in us */ +#define CDNSP_CMD_TIMEOUT (15 * 1000) + +/* Up to 16 ms to halt an device controller */ +#define CDNSP_MAX_HALT_USEC (16 * 1000) + +#define CDNSP_CTX_SIZE 2112 + +/* + * Controller register interface. + */ + +/** + * struct cdnsp_cap_regs - CDNSP Registers. + * @hc_capbase: Length of the capabilities register and controller + * version number + * @hcs_params1: HCSPARAMS1 - Structural Parameters 1 + * @hcs_params2: HCSPARAMS2 - Structural Parameters 2 + * @hcs_params3: HCSPARAMS3 - Structural Parameters 3 + * @hcc_params: HCCPARAMS - Capability Parameters + * @db_off: DBOFF - Doorbell array offset + * @run_regs_off: RTSOFF - Runtime register space offset + * @hcc_params2: HCCPARAMS2 Capability Parameters 2, + */ +struct cdnsp_cap_regs { + __le32 hc_capbase; + __le32 hcs_params1; + __le32 hcs_params2; + __le32 hcs_params3; + __le32 hcc_params; + __le32 db_off; + __le32 run_regs_off; + __le32 hcc_params2; + /* Reserved up to (CAPLENGTH - 0x1C) */ +}; + +/* hc_capbase bitmasks. */ +/* bits 7:0 - how long is the Capabilities register. */ +#define HC_LENGTH(p) (((p) >> 00) & GENMASK(7, 0)) +/* bits 31:16 */ +#define HC_VERSION(p) (((p) >> 16) & GENMASK(15, 1)) + +/* HCSPARAMS1 - hcs_params1 - bitmasks */ +/* bits 0:7, Max Device Endpoints */ +#define HCS_ENDPOINTS_MASK GENMASK(7, 0) +#define HCS_ENDPOINTS(p) (((p) & HCS_ENDPOINTS_MASK) >> 0) + +/* HCCPARAMS offset from PCI base address */ +#define HCC_PARAMS_OFFSET 0x10 + +/* HCCPARAMS - hcc_params - bitmasks */ +/* 1: device controller can use 64-bit address pointers. */ +#define HCC_64BIT_ADDR(p) ((p) & BIT(0)) +/* 1: device controller uses 64-byte Device Context structures. */ +#define HCC_64BYTE_CONTEXT(p) ((p) & BIT(2)) +/* Max size for Primary Stream Arrays - 2^(n+1), where n is bits 12:15. */ +#define HCC_MAX_PSA(p) ((((p) >> 12) & 0xf) + 1) +/* Extended Capabilities pointer from PCI base. */ +#define HCC_EXT_CAPS(p) (((p) & GENMASK(31, 16)) >> 16) + +#define CTX_SIZE(_hcc) (HCC_64BYTE_CONTEXT(_hcc) ? 64 : 32) + +/* db_off bitmask - bits 0:1 reserved. */ +#define DBOFF_MASK GENMASK(31, 2) + +/* run_regs_off bitmask - bits 0:4 reserved. */ +#define RTSOFF_MASK GENMASK(31, 5) + +/** + * struct cdnsp_op_regs - Device Controller Operational Registers. + * @command: USBCMD - Controller command register. + * @status: USBSTS - Controller status register. + * @page_size: This indicates the page size that the device controller supports. + * If bit n is set, the controller supports a page size of 2^(n+12), + * up to a 128MB page size. 4K is the minimum page size. + * @dnctrl: DNCTRL - Device notification control register. + * @cmd_ring: CRP - 64-bit Command Ring Pointer. + * @dcbaa_ptr: DCBAAP - 64-bit Device Context Base Address Array Pointer. + * @config_reg: CONFIG - Configure Register + * @port_reg_base: PORTSCn - base address for Port Status and Control + * Each port has a Port Status and Control register, + * followed by a Port Power Management Status and Control + * register, a Port Link Info register, and a reserved + * register. + */ +struct cdnsp_op_regs { + __le32 command; + __le32 status; + __le32 page_size; + __le32 reserved1; + __le32 reserved2; + __le32 dnctrl; + __le64 cmd_ring; + /* rsvd: offset 0x20-2F. */ + __le32 reserved3[4]; + __le64 dcbaa_ptr; + __le32 config_reg; + /* rsvd: offset 0x3C-3FF. */ + __le32 reserved4[241]; + /* port 1 registers, which serve as a base address for other ports. */ + __le32 port_reg_base; +}; + +/* Number of registers per port. */ +#define NUM_PORT_REGS 4 + +/** + * struct cdnsp_port_regs - Port Registers. + * @portsc: PORTSC - Port Status and Control Register. + * @portpmsc: PORTPMSC - Port Power Managements Status and Control Register. + * @portli: PORTLI - Port Link Info register. + */ +struct cdnsp_port_regs { + __le32 portsc; + __le32 portpmsc; + __le32 portli; + __le32 reserved; +}; + +/* + * These bits are Read Only (RO) and should be saved and written to the + * registers: 0 (connect status) and 10:13 (port speed). + * These bits are also sticky - meaning they're in the AUX well and they aren't + * changed by a hot and warm. + */ +#define CDNSP_PORT_RO (PORT_CONNECT | DEV_SPEED_MASK) + +/* + * These bits are RW; writing a 0 clears the bit, writing a 1 sets the bit: + * bits 5:8 (link state), 25:26 ("wake on" enable state) + */ +#define CDNSP_PORT_RWS (PORT_PLS_MASK | PORT_WKCONN_E | PORT_WKDISC_E) + +/* + * These bits are RW; writing a 1 clears the bit, writing a 0 has no effect: + * bits 1 (port enable/disable), 17 ( connect changed), + * 21 (port reset changed) , 22 (Port Link State Change), + */ +#define CDNSP_PORT_RW1CS (PORT_PED | PORT_CSC | PORT_RC | PORT_PLC) + +/* USBCMD - USB command - bitmasks. */ +/* Run/Stop, controller execution - do not write unless controller is halted.*/ +#define CMD_R_S BIT(0) +/* + * Reset device controller - resets internal controller state machine and all + * registers (except PCI config regs). + */ +#define CMD_RESET BIT(1) +/* Event Interrupt Enable - a '1' allows interrupts from the controller. */ +#define CMD_INTE BIT(2) +/* + * Device System Error Interrupt Enable - get out-of-band signal for + * controller errors. + */ +#define CMD_DSEIE BIT(3) +/* device controller save/restore state. */ +#define CMD_CSS BIT(8) +#define CMD_CRS BIT(9) +/* + * Enable Wrap Event - '1' means device controller generates an event + * when MFINDEX wraps. + */ +#define CMD_EWE BIT(10) +/* 1: device enabled */ +#define CMD_DEVEN BIT(17) +/* bits 18:31 are reserved (and should be preserved on writes). */ + +/* Command register values to disable interrupts. */ +#define CDNSP_IRQS (CMD_INTE | CMD_DSEIE | CMD_EWE) + +/* USBSTS - USB status - bitmasks */ +/* controller not running - set to 1 when run/stop bit is cleared. */ +#define STS_HALT BIT(0) +/* + * serious error, e.g. PCI parity error. The controller will clear + * the run/stop bit. + */ +#define STS_FATAL BIT(2) +/* event interrupt - clear this prior to clearing any IP flags in IR set.*/ +#define STS_EINT BIT(3) +/* port change detect */ +#define STS_PCD BIT(4) +/* save state status - '1' means device controller is saving state. */ +#define STS_SSS BIT(8) +/* restore state status - '1' means controllers is restoring state. */ +#define STS_RSS BIT(9) +/* 1: save or restore error */ +#define STS_SRE BIT(10) +/* 1: device Not Ready to accept doorbell or op reg writes after reset. */ +#define STS_CNR BIT(11) +/* 1: internal Device Controller Error.*/ +#define STS_HCE BIT(12) + +/* CRCR - Command Ring Control Register - cmd_ring bitmasks. */ +/* bit 0 is the command ring cycle state. */ +#define CMD_RING_CS BIT(0) +/* stop ring immediately - abort the currently executing command. */ +#define CMD_RING_ABORT BIT(2) +/* + * Command Ring Busy. + * Set when Doorbell register is written with DB for command and cleared when + * the controller reached end of CR. + */ +#define CMD_RING_BUSY(p) ((p) & BIT(4)) +/* 1: command ring is running */ +#define CMD_RING_RUNNING BIT(3) +/* Command Ring pointer - bit mask for the lower 32 bits. */ +#define CMD_RING_RSVD_BITS GENMASK(5, 0) + +/* CONFIG - Configure Register - config_reg bitmasks. */ +/* bits 0:7 - maximum number of device slots enabled. */ +#define MAX_DEVS GENMASK(7, 0) +/* bit 8: U3 Entry Enabled, assert PLC when controller enters U3. */ +#define CONFIG_U3E BIT(8) + +/* PORTSC - Port Status and Control Register - port_reg_base bitmasks */ +/* 1: device connected. */ +#define PORT_CONNECT BIT(0) +/* 1: port enabled. */ +#define PORT_PED BIT(1) +/* 1: port reset signaling asserted. */ +#define PORT_RESET BIT(4) +/* + * Port Link State - bits 5:8 + * A read gives the current link PM state of the port, + * a write with Link State Write Strobe sets the link state. + */ +#define PORT_PLS_MASK GENMASK(8, 5) +#define XDEV_U0 (0x0 << 5) +#define XDEV_U1 (0x1 << 5) +#define XDEV_U2 (0x2 << 5) +#define XDEV_U3 (0x3 << 5) +#define XDEV_DISABLED (0x4 << 5) +#define XDEV_RXDETECT (0x5 << 5) +#define XDEV_INACTIVE (0x6 << 5) +#define XDEV_POLLING (0x7 << 5) +#define XDEV_RECOVERY (0x8 << 5) +#define XDEV_HOT_RESET (0x9 << 5) +#define XDEV_COMP_MODE (0xa << 5) +#define XDEV_TEST_MODE (0xb << 5) +#define XDEV_RESUME (0xf << 5) +/* 1: port has power. */ +#define PORT_POWER BIT(9) +/* + * bits 10:13 indicate device speed: + * 0 - undefined speed - port hasn't be initialized by a reset yet + * 1 - full speed + * 2 - Reserved (Low Speed not supported + * 3 - high speed + * 4 - super speed + * 5 - super speed + * 6-15 reserved + */ +#define DEV_SPEED_MASK GENMASK(13, 10) +#define XDEV_FS (0x1 << 10) +#define XDEV_HS (0x3 << 10) +#define XDEV_SS (0x4 << 10) +#define XDEV_SSP (0x5 << 10) +#define DEV_UNDEFSPEED(p) (((p) & DEV_SPEED_MASK) == (0x0 << 10)) +#define DEV_FULLSPEED(p) (((p) & DEV_SPEED_MASK) == XDEV_FS) +#define DEV_HIGHSPEED(p) (((p) & DEV_SPEED_MASK) == XDEV_HS) +#define DEV_SUPERSPEED(p) (((p) & DEV_SPEED_MASK) == XDEV_SS) +#define DEV_SUPERSPEEDPLUS(p) (((p) & DEV_SPEED_MASK) == XDEV_SSP) +#define DEV_SUPERSPEED_ANY(p) (((p) & DEV_SPEED_MASK) >= XDEV_SS) +#define DEV_PORT_SPEED(p) (((p) >> 10) & 0x0f) +/* Port Link State Write Strobe - set this when changing link state */ +#define PORT_LINK_STROBE BIT(16) +/* 1: connect status change */ +#define PORT_CSC BIT(17) +/* 1: warm reset for a USB 3.0 device is done. */ +#define PORT_WRC BIT(19) +/* 1: reset change - 1 to 0 transition of PORT_RESET */ +#define PORT_RC BIT(21) +/* + * port link status change - set on some port link state transitions: + * Transition Reason + * ---------------------------------------------------------------------------- + * - U3 to Resume Wakeup signaling from a device + * - Resume to Recovery to U0 USB 3.0 device resume + * - Resume to U0 USB 2.0 device resume + * - U3 to Recovery to U0 Software resume of USB 3.0 device complete + * - U3 to U0 Software resume of USB 2.0 device complete + * - U2 to U0 L1 resume of USB 2.1 device complete + * - U0 to U0 L1 entry rejection by USB 2.1 device + * - U0 to disabled L1 entry error with USB 2.1 device + * - Any state to inactive Error on USB 3.0 port + */ +#define PORT_PLC BIT(22) +/* Port configure error change - port failed to configure its link partner. */ +#define PORT_CEC BIT(23) +/* Wake on connect (enable). */ +#define PORT_WKCONN_E BIT(25) +/* Wake on disconnect (enable). */ +#define PORT_WKDISC_E BIT(26) +/* Indicates if Warm Reset is being received. */ +#define PORT_WR BIT(31) + +#define PORT_CHANGE_BITS (PORT_CSC | PORT_WRC | PORT_RC | PORT_PLC | PORT_CEC) + +/* PORTPMSCUSB3 - Port Power Management Status and Control - bitmasks. */ +/* Enables U1 entry. */ +#define PORT_U1_TIMEOUT_MASK GENMASK(7, 0) +#define PORT_U1_TIMEOUT(p) ((p) & PORT_U1_TIMEOUT_MASK) +/* Enables U2 entry .*/ +#define PORT_U2_TIMEOUT_MASK GENMASK(14, 8) +#define PORT_U2_TIMEOUT(p) (((p) << 8) & PORT_U2_TIMEOUT_MASK) + +/* PORTPMSCUSB2 - Port Power Management Status and Control - bitmasks. */ +#define PORT_L1S_MASK GENMASK(2, 0) +#define PORT_L1S(p) ((p) & PORT_L1S_MASK) +#define PORT_L1S_ACK PORT_L1S(1) +#define PORT_L1S_NYET PORT_L1S(2) +#define PORT_L1S_STALL PORT_L1S(3) +#define PORT_L1S_TIMEOUT PORT_L1S(4) +/* Remote Wake Enable. */ +#define PORT_RWE BIT(3) +/* Best Effort Service Latency (BESL). */ +#define PORT_BESL(p) (((p) << 4) & GENMASK(7, 4)) +/* Hardware LPM Enable (HLE). */ +#define PORT_HLE BIT(16) +/* Received Best Effort Service Latency (BESL). */ +#define PORT_RRBESL(p) (((p) & GENMASK(20, 17)) >> 17) +/* Port Test Control. */ +#define PORT_TEST_MODE_MASK GENMASK(31, 28) +#define PORT_TEST_MODE(p) (((p) << 28) & PORT_TEST_MODE_MASK) + +/** + * struct cdnsp_intr_reg - Interrupt Register Set. + * @irq_pending: IMAN - Interrupt Management Register. Used to enable + * interrupts and check for pending interrupts. + * @irq_control: IMOD - Interrupt Moderation Register. + * Used to throttle interrupts. + * @erst_size: Number of segments in the Event Ring Segment Table (ERST). + * @erst_base: ERST base address. + * @erst_dequeue: Event ring dequeue pointer. + * + * Each interrupter (defined by a MSI-X vector) has an event ring and an Event + * Ring Segment Table (ERST) associated with it. The event ring is comprised of + * multiple segments of the same size. The controller places events on the ring + * and "updates the Cycle bit in the TRBs to indicate to software the current + * position of the Enqueue Pointer." The driver processes those events and + * updates the dequeue pointer. + */ +struct cdnsp_intr_reg { + __le32 irq_pending; + __le32 irq_control; + __le32 erst_size; + __le32 rsvd; + __le64 erst_base; + __le64 erst_dequeue; +}; + +/* IMAN - Interrupt Management Register - irq_pending bitmasks l. */ +#define IMAN_IE BIT(1) +#define IMAN_IP BIT(0) +/* bits 2:31 need to be preserved */ +#define IMAN_IE_SET(p) (((p) & IMAN_IE) | 0x2) +#define IMAN_IE_CLEAR(p) (((p) & IMAN_IE) & ~(0x2)) + +/* IMOD - Interrupter Moderation Register - irq_control bitmasks. */ +/* + * Minimum interval between interrupts (in 250ns intervals). The interval + * between interrupts will be longer if there are no events on the event ring. + * Default is 4000 (1 ms). + */ +#define IMOD_INTERVAL_MASK GENMASK(15, 0) +/* Counter used to count down the time to the next interrupt - HW use only */ +#define IMOD_COUNTER_MASK GENMASK(31, 16) +#define IMOD_DEFAULT_INTERVAL 0 + +/* erst_size bitmasks. */ +/* Preserve bits 16:31 of erst_size. */ +#define ERST_SIZE_MASK GENMASK(31, 16) + +/* erst_dequeue bitmasks. */ +/* + * Dequeue ERST Segment Index (DESI) - Segment number (or alias) + * where the current dequeue pointer lies. This is an optional HW hint. + */ +#define ERST_DESI_MASK GENMASK(2, 0) +/* Event Handler Busy (EHB) - is the event ring scheduled to be serviced. */ +#define ERST_EHB BIT(3) +#define ERST_PTR_MASK GENMASK(3, 0) + +/** + * struct cdnsp_run_regs + * @microframe_index: MFINDEX - current microframe number. + * @ir_set: Array of Interrupter registers. + * + * Device Controller Runtime Registers: + * "Software should read and write these registers using only Dword (32 bit) + * or larger accesses" + */ +struct cdnsp_run_regs { + __le32 microframe_index; + __le32 rsvd[7]; + struct cdnsp_intr_reg ir_set[128]; +}; + +/** + * USB2.0 Port Peripheral Configuration Registers. + * @ext_cap: Header register for Extended Capability. + * @port_reg1: Timer Configuration Register. + * @port_reg2: Timer Configuration Register. + * @port_reg3: Timer Configuration Register. + * @port_reg4: Timer Configuration Register. + * @port_reg5: Timer Configuration Register. + * @port_reg6: Chicken bits for USB20PPP. + */ +struct cdnsp_20port_cap { + __le32 ext_cap; + __le32 port_reg1; + __le32 port_reg2; + __le32 port_reg3; + __le32 port_reg4; + __le32 port_reg5; + __le32 port_reg6; +}; + +/* Extended capability register fields */ +#define EXT_CAPS_ID(p) (((p) >> 0) & GENMASK(7, 0)) +#define EXT_CAPS_NEXT(p) (((p) >> 8) & GENMASK(7, 0)) +/* Extended capability IDs - ID 0 reserved */ +#define EXT_CAPS_PROTOCOL 2 + +/* USB 2.0 Port Peripheral Configuration Extended Capability */ +#define EXT_CAP_CFG_DEV_20PORT_CAP_ID 0xC1 +/* + * Setting this bit to '1' enables automatic wakeup from L1 state on transfer + * TRB prepared when USBSSP operates in USB2.0 mode. + */ +#define PORT_REG6_L1_L0_HW_EN BIT(1) +/* + * Setting this bit to '1' forces Full Speed when USBSSP operates in USB2.0 + * mode (disables High Speed). + */ +#define PORT_REG6_FORCE_FS BIT(0) + +/** + * USB3.x Port Peripheral Configuration Registers. + * @ext_cap: Header register for Extended Capability. + * @mode_addr: Miscellaneous 3xPORT operation mode configuration register. + * @mode_2: 3x Port Control Register 2. + */ +struct cdnsp_3xport_cap { + __le32 ext_cap; + __le32 mode_addr; + __le32 reserved[52]; + __le32 mode_2; +}; + +/* Extended Capability Header for 3XPort Configuration Registers. */ +#define D_XEC_CFG_3XPORT_CAP 0xC0 +#define CFG_3XPORT_SSP_SUPPORT BIT(31) +#define CFG_3XPORT_U1_PIPE_CLK_GATE_EN BIT(0) + +/* Revision Extended Capability ID */ +#define RTL_REV_CAP 0xC4 +#define RTL_REV_CAP_RX_BUFF_CMD_SIZE BITMASK(31, 24) +#define RTL_REV_CAP_RX_BUFF_SIZE BITMASK(15, 0) +#define RTL_REV_CAP_TX_BUFF_CMD_SIZE BITMASK(31, 24) +#define RTL_REV_CAP_TX_BUFF_SIZE BITMASK(15, 0) + +#define CDNSP_VER_1 0x00000000 +#define CDNSP_VER_2 0x10000000 + +#define CDNSP_IF_EP_EXIST(pdev, ep_num, dir) ((pdev)->rev_cap.ep_supported & \ + (BIT(ep_num) << ((dir) ? 0 : 16))) + +/** + * struct cdnsp_rev_cap - controller capabilities . + * @ext_cap: Header for RTL Revision Extended Capability. + * @rtl_revision: RTL revision. + * @rx_buff_size: Rx buffer sizes. + * @tx_buff_size: Tx buffer sizes. + * @ep_supported: Supported endpoints. + * @ctrl_revision: Controller revision ID. + */ +struct cdnsp_rev_cap { + __le32 ext_cap; + __le32 rtl_revision; + __le32 rx_buff_size; + __le32 tx_buff_size; + __le32 ep_supported; + __le32 ctrl_revision; +}; + +/* USB2.0 Port Peripheral Configuration Registers. */ +#define D_XEC_PRE_REGS_CAP 0xC8 +#define REG_CHICKEN_BITS_2_OFFSET 0x48 +#define CHICKEN_XDMA_2_TP_CACHE_DIS BIT(28) + +/* XBUF Extended Capability ID. */ +#define XBUF_CAP_ID 0xCB +#define XBUF_RX_TAG_MASK_0_OFFSET 0x1C +#define XBUF_RX_TAG_MASK_1_OFFSET 0x24 +#define XBUF_TX_CMD_OFFSET 0x2C + +/** + * struct cdnsp_doorbell_array. + * @cmd_db: Command ring doorbell register. + * @ep_db: Endpoint ring doorbell register. + * Bits 0 - 7: Endpoint target. + * Bits 8 - 15: RsvdZ. + * Bits 16 - 31: Stream ID. + */ +struct cdnsp_doorbell_array { + __le32 cmd_db; + __le32 ep_db; +}; + +#define DB_VALUE(ep, stream) ((((ep) + 1) & 0xff) | ((stream) << 16)) +#define DB_VALUE_EP0_OUT(ep, stream) ((ep) & 0xff) +#define DB_VALUE_CMD 0x00000000 + +/** + * struct cdnsp_container_ctx. + * @type: Type of context. Used to calculated offsets to contained contexts. + * @size: Size of the context data. + * @ctx_size: context data structure size - 64 or 32 bits. + * @dma: dma address of the bytes. + * @bytes: The raw context data given to HW. + * + * Represents either a Device or Input context. Holds a pointer to the raw + * memory used for the context (bytes) and dma address of it (dma). + */ +struct cdnsp_container_ctx { + unsigned int type; +#define CDNSP_CTX_TYPE_DEVICE 0x1 +#define CDNSP_CTX_TYPE_INPUT 0x2 + int size; + int ctx_size; + dma_addr_t dma; + u8 *bytes; +}; + +/** + * struct cdnsp_slot_ctx + * @dev_info: Device speed, and last valid endpoint. + * @dev_port: Device port number that is needed to access the USB device. + * @int_target: Interrupter target number. + * @dev_state: Slot state and device address. + * + * Slot Context - This assumes the controller uses 32-byte context + * structures. If the controller uses 64-byte contexts, there is an additional + * 32 bytes reserved at the end of the slot context for controller internal use. + */ +struct cdnsp_slot_ctx { + __le32 dev_info; + __le32 dev_port; + __le32 int_target; + __le32 dev_state; + /* offset 0x10 to 0x1f reserved for controller internal use. */ + __le32 reserved[4]; +}; + +/* Bits 20:23 in the Slot Context are the speed for the device. */ +#define SLOT_SPEED_FS (XDEV_FS << 10) +#define SLOT_SPEED_HS (XDEV_HS << 10) +#define SLOT_SPEED_SS (XDEV_SS << 10) +#define SLOT_SPEED_SSP (XDEV_SSP << 10) + +/* dev_info bitmasks. */ +/* Device speed - values defined by PORTSC Device Speed field - 20:23. */ +#define DEV_SPEED GENMASK(23, 20) +#define GET_DEV_SPEED(n) (((n) & DEV_SPEED) >> 20) +/* Index of the last valid endpoint context in this device context - 27:31. */ +#define LAST_CTX_MASK GENMASK(31, 27) +#define LAST_CTX(p) ((p) << 27) +#define LAST_CTX_TO_EP_NUM(p) (((p) >> 27) - 1) +#define SLOT_FLAG BIT(0) +#define EP0_FLAG BIT(1) + +/* dev_port bitmasks */ +/* Device port number that is needed to access the USB device. */ +#define DEV_PORT(p) (((p) & 0xff) << 16) + +/* dev_state bitmasks */ +/* USB device address - assigned by the controller. */ +#define DEV_ADDR_MASK GENMASK(7, 0) +/* Slot state */ +#define SLOT_STATE GENMASK(31, 27) +#define GET_SLOT_STATE(p) (((p) & SLOT_STATE) >> 27) + +#define SLOT_STATE_DISABLED 0 +#define SLOT_STATE_ENABLED SLOT_STATE_DISABLED +#define SLOT_STATE_DEFAULT 1 +#define SLOT_STATE_ADDRESSED 2 +#define SLOT_STATE_CONFIGURED 3 + +/** + * struct cdnsp_ep_ctx. + * @ep_info: Endpoint state, streams, mult, and interval information. + * @ep_info2: Information on endpoint type, max packet size, max burst size, + * error count, and whether the controller will force an event for + * all transactions. + * @deq: 64-bit ring dequeue pointer address. If the endpoint only + * defines one stream, this points to the endpoint transfer ring. + * Otherwise, it points to a stream context array, which has a + * ring pointer for each flow. + * @tx_info: Average TRB lengths for the endpoint ring and + * max payload within an Endpoint Service Interval Time (ESIT). + * + * Endpoint Context - This assumes the controller uses 32-byte context + * structures. If the controller uses 64-byte contexts, there is an additional + * 32 bytes reserved at the end of the endpoint context for controller internal + * use. + */ +struct cdnsp_ep_ctx { + __le32 ep_info; + __le32 ep_info2; + __le64 deq; + __le32 tx_info; + /* offset 0x14 - 0x1f reserved for controller internal use. */ + __le32 reserved[3]; +}; + +/* ep_info bitmasks. */ +/* + * Endpoint State - bits 0:2: + * 0 - disabled + * 1 - running + * 2 - halted due to halt condition + * 3 - stopped + * 4 - TRB error + * 5-7 - reserved + */ +#define EP_STATE_MASK GENMASK(3, 0) +#define EP_STATE_DISABLED 0 +#define EP_STATE_RUNNING 1 +#define EP_STATE_HALTED 2 +#define EP_STATE_STOPPED 3 +#define EP_STATE_ERROR 4 +#define GET_EP_CTX_STATE(ctx) (le32_to_cpu((ctx)->ep_info) & EP_STATE_MASK) + +/* Mult - Max number of burst within an interval, in EP companion desc. */ +#define EP_MULT(p) (((p) << 8) & GENMASK(9, 8)) +#define CTX_TO_EP_MULT(p) (((p) & GENMASK(9, 8)) >> 8) +/* bits 10:14 are Max Primary Streams. */ +/* bit 15 is Linear Stream Array. */ +/* Interval - period between requests to an endpoint - 125u increments. */ +#define EP_INTERVAL(p) (((p) << 16) & GENMASK(23, 16)) +#define EP_INTERVAL_TO_UFRAMES(p) (1 << (((p) & GENMASK(23, 16)) >> 16)) +#define CTX_TO_EP_INTERVAL(p) (((p) & GENMASK(23, 16)) >> 16) +#define EP_MAXPSTREAMS_MASK GENMASK(14, 10) +#define EP_MAXPSTREAMS(p) (((p) << 10) & EP_MAXPSTREAMS_MASK) +#define CTX_TO_EP_MAXPSTREAMS(p) (((p) & EP_MAXPSTREAMS_MASK) >> 10) +/* Endpoint is set up with a Linear Stream Array (vs. Secondary Stream Array) */ +#define EP_HAS_LSA BIT(15) + +/* ep_info2 bitmasks */ +#define ERROR_COUNT(p) (((p) & 0x3) << 1) +#define CTX_TO_EP_TYPE(p) (((p) >> 3) & 0x7) +#define EP_TYPE(p) ((p) << 3) +#define ISOC_OUT_EP 1 +#define BULK_OUT_EP 2 +#define INT_OUT_EP 3 +#define CTRL_EP 4 +#define ISOC_IN_EP 5 +#define BULK_IN_EP 6 +#define INT_IN_EP 7 +/* bit 6 reserved. */ +/* bit 7 is Device Initiate Disable - for disabling stream selection. */ +#define MAX_BURST(p) (((p) << 8) & GENMASK(15, 8)) +#define CTX_TO_MAX_BURST(p) (((p) & GENMASK(15, 8)) >> 8) +#define MAX_PACKET(p) (((p) << 16) & GENMASK(31, 16)) +#define MAX_PACKET_MASK GENMASK(31, 16) +#define MAX_PACKET_DECODED(p) (((p) & GENMASK(31, 16)) >> 16) + +/* tx_info bitmasks. */ +#define EP_AVG_TRB_LENGTH(p) ((p) & GENMASK(15, 0)) +#define EP_MAX_ESIT_PAYLOAD_LO(p) (((p) << 16) & GENMASK(31, 16)) +#define EP_MAX_ESIT_PAYLOAD_HI(p) ((((p) & GENMASK(23, 16)) >> 16) << 24) +#define CTX_TO_MAX_ESIT_PAYLOAD_LO(p) (((p) & GENMASK(31, 16)) >> 16) +#define CTX_TO_MAX_ESIT_PAYLOAD_HI(p) (((p) & GENMASK(31, 24)) >> 24) + +/* deq bitmasks. */ +#define EP_CTX_CYCLE_MASK BIT(0) +#define CTX_DEQ_MASK (~0xfL) + +/** + * struct cdnsp_input_control_context + * Input control context; + * + * @drop_context: Set the bit of the endpoint context you want to disable. + * @add_context: Set the bit of the endpoint context you want to enable. + */ +struct cdnsp_input_control_ctx { + __le32 drop_flags; + __le32 add_flags; + __le32 rsvd2[6]; +}; + +/** + * Represents everything that is needed to issue a command on the command ring. + * + * @in_ctx: Pointer to input context structure. + * @status: Command Completion Code for last command. + * @command_trb: Pointer to command TRB. + */ +struct cdnsp_command { + /* Input context for changing device state. */ + struct cdnsp_container_ctx *in_ctx; + u32 status; + union cdnsp_trb *command_trb; +}; + +/** + * Stream context structure. + * + * @stream_ring: 64-bit stream ring address, cycle state, and stream type. + * @reserved: offset 0x14 - 0x1f reserved for controller internal use. + */ +struct cdnsp_stream_ctx { + __le64 stream_ring; + __le32 reserved[2]; +}; + +/* Stream Context Types - bits 3:1 of stream ctx deq ptr. */ +#define SCT_FOR_CTX(p) (((p) << 1) & GENMASK(3, 1)) +/* Secondary stream array type, dequeue pointer is to a transfer ring. */ +#define SCT_SEC_TR 0 +/* Primary stream array type, dequeue pointer is to a transfer ring. */ +#define SCT_PRI_TR 1 + +/** + * struct cdnsp_stream_info: Representing everything that is needed to + * supports stream capable endpoints. + * @stream_rings: Array of pointers containing Transfer rings for all + * supported streams. + * @num_streams: Number of streams, including stream 0. + * @stream_ctx_array: The stream context array may be bigger than the number + * of streams the driver asked for. + * @num_stream_ctxs: Number of streams. + * @ctx_array_dma: Dma address of Context Stream Array. + * @trb_address_map: For mapping physical TRB addresses to segments in + * stream rings. + * @td_count: Number of TDs associated with endpoint. + * @first_prime_det: First PRIME packet detected. + * @drbls_count: Number of allowed doorbells. + */ +struct cdnsp_stream_info { + struct cdnsp_ring **stream_rings; + unsigned int num_streams; + struct cdnsp_stream_ctx *stream_ctx_array; + unsigned int num_stream_ctxs; + dma_addr_t ctx_array_dma; + struct radix_tree_root trb_address_map; + int td_count; + u8 first_prime_det; +#define STREAM_DRBL_FIFO_DEPTH 2 + u8 drbls_count; +}; + +#define STREAM_LOG_STREAMS 4 +#define STREAM_NUM_STREAMS BIT(STREAM_LOG_STREAMS) + +#if STREAM_LOG_STREAMS > 16 && STREAM_LOG_STREAMS < 1 +#error "Not suupported stream value" +#endif + +/** + * struct cdnsp_ep - extended device side representation of USB endpoint. + * @endpoint: usb endpoint + * @pending_req_list: List of requests queuing on transfer ring. + * @pdev: Device associated with this endpoint. + * @number: Endpoint number (1 - 15). + * idx: The device context index (DCI). + * interval: Interval between packets used for ISOC endpoint. + * @name: A human readable name e.g. ep1out. + * @direction: Endpoint direction. + * @buffering: Number of on-chip buffers related to endpoint. + * @buffering_period; Number of on-chip buffers related to periodic endpoint. + * @in_ctx: Pointer to input endpoint context structure. + * @out_ctx: Pointer to output endpoint context structure. + * @ring: Pointer to transfer ring. + * @stream_info: Hold stream information. + * @ep_state: Current state of endpoint. + * @skip: Sometimes the controller can not process isochronous endpoint ring + * quickly enough, and it will miss some isoc tds on the ring and + * generate Missed Service Error Event. + * Set skip flag when receive a Missed Service Error Event and + * process the missed tds on the endpoint ring. + */ +struct cdnsp_ep { + struct usb_ep endpoint; + struct list_head pending_list; + struct cdnsp_device *pdev; + u8 number; + u8 idx; + u32 interval; + char name[20]; + u8 direction; + u8 buffering; + u8 buffering_period; + struct cdnsp_ep_ctx *in_ctx; + struct cdnsp_ep_ctx *out_ctx; + struct cdnsp_ring *ring; + struct cdnsp_stream_info stream_info; + unsigned int ep_state; +#define EP_ENABLED BIT(0) +#define EP_DIS_IN_RROGRESS BIT(1) +#define EP_HALTED BIT(2) +#define EP_STOPPED BIT(3) +#define EP_WEDGE BIT(4) +#define EP0_HALTED_STATUS BIT(5) +#define EP_HAS_STREAMS BIT(6) + + bool skip; +}; + +/** + * struct cdnsp_device_context_array + * @dev_context_ptr: Array of 64-bit DMA addresses for device contexts. + * @dma: DMA address for device contexts structure. + */ +struct cdnsp_device_context_array { + __le64 dev_context_ptrs[CDNSP_DEV_MAX_SLOTS + 1]; + dma_addr_t dma; +}; + +/** + * struct cdnsp_transfer_event. + * @buffer: 64-bit buffer address, or immediate data. + * @transfer_len: Data length transferred. + * @flags: Field is interpreted differently based on the type of TRB. + */ +struct cdnsp_transfer_event { + __le64 buffer; + __le32 transfer_len; + __le32 flags; +}; + +/* Invalidate event after disabling endpoint. */ +#define TRB_EVENT_INVALIDATE 8 + +/* Transfer event TRB length bit mask. */ +/* bits 0:23 */ +#define EVENT_TRB_LEN(p) ((p) & GENMASK(23, 0)) +/* Completion Code - only applicable for some types of TRBs */ +#define COMP_CODE_MASK (0xff << 24) +#define GET_COMP_CODE(p) (((p) & COMP_CODE_MASK) >> 24) +#define COMP_INVALID 0 +#define COMP_SUCCESS 1 +#define COMP_DATA_BUFFER_ERROR 2 +#define COMP_BABBLE_DETECTED_ERROR 3 +#define COMP_TRB_ERROR 5 +#define COMP_RESOURCE_ERROR 7 +#define COMP_NO_SLOTS_AVAILABLE_ERROR 9 +#define COMP_INVALID_STREAM_TYPE_ERROR 10 +#define COMP_SLOT_NOT_ENABLED_ERROR 11 +#define COMP_ENDPOINT_NOT_ENABLED_ERROR 12 +#define COMP_SHORT_PACKET 13 +#define COMP_RING_UNDERRUN 14 +#define COMP_RING_OVERRUN 15 +#define COMP_VF_EVENT_RING_FULL_ERROR 16 +#define COMP_PARAMETER_ERROR 17 +#define COMP_CONTEXT_STATE_ERROR 19 +#define COMP_EVENT_RING_FULL_ERROR 21 +#define COMP_INCOMPATIBLE_DEVICE_ERROR 22 +#define COMP_MISSED_SERVICE_ERROR 23 +#define COMP_COMMAND_RING_STOPPED 24 +#define COMP_COMMAND_ABORTED 25 +#define COMP_STOPPED 26 +#define COMP_STOPPED_LENGTH_INVALID 27 +#define COMP_STOPPED_SHORT_PACKET 28 +#define COMP_MAX_EXIT_LATENCY_TOO_LARGE_ERROR 29 +#define COMP_ISOCH_BUFFER_OVERRUN 31 +#define COMP_EVENT_LOST_ERROR 32 +#define COMP_UNDEFINED_ERROR 33 +#define COMP_INVALID_STREAM_ID_ERROR 34 + +/*Transfer Event NRDY bit fields */ +#define TRB_TO_DEV_STREAM(p) ((p) & GENMASK(16, 0)) +#define TRB_TO_HOST_STREAM(p) ((p) & GENMASK(16, 0)) +#define STREAM_PRIME_ACK 0xFFFE +#define STREAM_REJECTED 0xFFFF + +/** Transfer Event bit fields **/ +#define TRB_TO_EP_ID(p) (((p) & GENMASK(20, 16)) >> 16) + +/** + * struct cdnsp_link_trb + * @segment_ptr: 64-bit segment pointer. + * @intr_target: Interrupter target. + * @control: Flags. + */ +struct cdnsp_link_trb { + __le64 segment_ptr; + __le32 intr_target; + __le32 control; +}; + +/* control bitfields */ +#define LINK_TOGGLE BIT(1) + +/** + * struct cdnsp_event_cmd - Command completion event TRB. + * cmd_trb: Pointer to command TRB, or the value passed by the event data trb + * status: Command completion parameters and error code. + * flags: Flags. + */ +struct cdnsp_event_cmd { + __le64 cmd_trb; + __le32 status; + __le32 flags; +}; + +/* flags bitmasks */ + +/* Address device - disable SetAddress. */ +#define TRB_BSR BIT(9) + +/* Configure Endpoint - Deconfigure. */ +#define TRB_DC BIT(9) + +/* Force Header */ +#define TRB_FH_TO_PACKET_TYPE(p) ((p) & GENMASK(4, 0)) +#define TRB_FH_TR_PACKET 0x4 +#define TRB_FH_TO_DEVICE_ADDRESS(p) (((p) << 25) & GENMASK(31, 25)) +#define TRB_FH_TR_PACKET_DEV_NOT 0x6 +#define TRB_FH_TO_NOT_TYPE(p) (((p) << 4) & GENMASK(7, 4)) +#define TRB_FH_TR_PACKET_FUNCTION_WAKE 0x1 +#define TRB_FH_TO_INTERFACE(p) (((p) << 8) & GENMASK(15, 8)) + +enum cdnsp_setup_dev { + SETUP_CONTEXT_ONLY, + SETUP_CONTEXT_ADDRESS, +}; + +/* bits 24:31 are the slot ID. */ +#define TRB_TO_SLOT_ID(p) (((p) & GENMASK(31, 24)) >> 24) +#define SLOT_ID_FOR_TRB(p) (((p) << 24) & GENMASK(31, 24)) + +/* Stop Endpoint TRB - ep_index to endpoint ID for this TRB. */ +#define TRB_TO_EP_INDEX(p) (((p) >> 16) & 0x1f) + +#define EP_ID_FOR_TRB(p) ((((p) + 1) << 16) & GENMASK(20, 16)) + +#define SUSPEND_PORT_FOR_TRB(p) (((p) & 1) << 23) +#define TRB_TO_SUSPEND_PORT(p) (((p) >> 23) & 0x1) +#define LAST_EP_INDEX 30 + +/* Set TR Dequeue Pointer command TRB fields. */ +#define TRB_TO_STREAM_ID(p) ((((p) & GENMASK(31, 16)) >> 16)) +#define STREAM_ID_FOR_TRB(p) ((((p)) << 16) & GENMASK(31, 16)) +#define SCT_FOR_TRB(p) (((p) << 1) & 0x7) + +/* Link TRB specific fields. */ +#define TRB_TC BIT(1) + +/* Port Status Change Event TRB fields. */ +/* Port ID - bits 31:24. */ +#define GET_PORT_ID(p) (((p) & GENMASK(31, 24)) >> 24) +#define SET_PORT_ID(p) (((p) << 24) & GENMASK(31, 24)) +#define EVENT_DATA BIT(2) + +/* Normal TRB fields. */ +/* transfer_len bitmasks - bits 0:16. */ +#define TRB_LEN(p) ((p) & GENMASK(16, 0)) +/* TD Size, packets remaining in this TD, bits 21:17 (5 bits, so max 31). */ +#define TRB_TD_SIZE(p) (min((p), (u32)31) << 17) +#define GET_TD_SIZE(p) (((p) & GENMASK(21, 17)) >> 17) +/* + * Controller uses the TD_SIZE field for TBC if Extended TBC + * is enabled (ETE). + */ +#define TRB_TD_SIZE_TBC(p) (min((p), (u32)31) << 17) +/* Interrupter Target - which MSI-X vector to target the completion event at. */ +#define TRB_INTR_TARGET(p) (((p) << 22) & GENMASK(31, 22)) +#define GET_INTR_TARGET(p) (((p) & GENMASK(31, 22)) >> 22) +/* + * Total burst count field, Rsvdz on controller with Extended TBC + * enabled (ETE). + */ +#define TRB_TBC(p) (((p) & 0x3) << 7) +#define TRB_TLBPC(p) (((p) & 0xf) << 16) + +/* Cycle bit - indicates TRB ownership by driver or driver.*/ +#define TRB_CYCLE BIT(0) +/* + * Force next event data TRB to be evaluated before task switch. + * Used to pass OS data back after a TD completes. + */ +#define TRB_ENT BIT(1) +/* Interrupt on short packet. */ +#define TRB_ISP BIT(2) +/* Set PCIe no snoop attribute. */ +#define TRB_NO_SNOOP BIT(3) +/* Chain multiple TRBs into a TD. */ +#define TRB_CHAIN BIT(4) +/* Interrupt on completion. */ +#define TRB_IOC BIT(5) +/* The buffer pointer contains immediate data. */ +#define TRB_IDT BIT(6) +/* 0 - NRDY during data stage, 1 - NRDY during status stage (only control). */ +#define TRB_STAT BIT(7) +/* Block Event Interrupt. */ +#define TRB_BEI BIT(9) + +/* Control transfer TRB specific fields. */ +#define TRB_DIR_IN BIT(16) + +/* TRB bit mask in Data Stage TRB */ +#define TRB_SETUPID_BITMASK GENMASK(9, 8) +#define TRB_SETUPID(p) ((p) << 8) +#define TRB_SETUPID_TO_TYPE(p) (((p) & TRB_SETUPID_BITMASK) >> 8) + +#define TRB_SETUP_SPEEDID_USB3 0x1 +#define TRB_SETUP_SPEEDID_USB2 0x0 +#define TRB_SETUP_SPEEDID(p) ((p) & (1 << 7)) + +#define TRB_SETUPSTAT_ACK 0x1 +#define TRB_SETUPSTAT_STALL 0x0 +#define TRB_SETUPSTAT(p) ((p) << 6) + +/* Isochronous TRB specific fields */ +#define TRB_SIA BIT(31) +#define TRB_FRAME_ID(p) (((p) << 20) & GENMASK(30, 20)) + +struct cdnsp_generic_trb { + __le32 field[4]; +}; + +union cdnsp_trb { + struct cdnsp_link_trb link; + struct cdnsp_transfer_event trans_event; + struct cdnsp_event_cmd event_cmd; + struct cdnsp_generic_trb generic; +}; + +/* TRB bit mask. */ +#define TRB_TYPE_BITMASK GENMASK(15, 10) +#define TRB_TYPE(p) ((p) << 10) +#define TRB_FIELD_TO_TYPE(p) (((p) & TRB_TYPE_BITMASK) >> 10) + +/* TRB type IDs. */ +/* bulk, interrupt, isoc scatter/gather, and control data stage. */ +#define TRB_NORMAL 1 +/* Setup Stage for control transfers. */ +#define TRB_SETUP 2 +/* Data Stage for control transfers. */ +#define TRB_DATA 3 +/* Status Stage for control transfers. */ +#define TRB_STATUS 4 +/* ISOC transfers. */ +#define TRB_ISOC 5 +/* TRB for linking ring segments. */ +#define TRB_LINK 6 +#define TRB_EVENT_DATA 7 +/* Transfer Ring No-op (not for the command ring). */ +#define TRB_TR_NOOP 8 + +/* Command TRBs */ +/* Enable Slot Command. */ +#define TRB_ENABLE_SLOT 9 +/* Disable Slot Command. */ +#define TRB_DISABLE_SLOT 10 +/* Address Device Command. */ +#define TRB_ADDR_DEV 11 +/* Configure Endpoint Command. */ +#define TRB_CONFIG_EP 12 +/* Evaluate Context Command. */ +#define TRB_EVAL_CONTEXT 13 +/* Reset Endpoint Command. */ +#define TRB_RESET_EP 14 +/* Stop Transfer Ring Command. */ +#define TRB_STOP_RING 15 +/* Set Transfer Ring Dequeue Pointer Command. */ +#define TRB_SET_DEQ 16 +/* Reset Device Command. */ +#define TRB_RESET_DEV 17 +/* Force Event Command (opt). */ +#define TRB_FORCE_EVENT 18 +/* Force Header Command - generate a transaction or link management packet. */ +#define TRB_FORCE_HEADER 22 +/* No-op Command - not for transfer rings. */ +#define TRB_CMD_NOOP 23 +/* TRB IDs 24-31 reserved. */ + +/* Event TRBS. */ +/* Transfer Event. */ +#define TRB_TRANSFER 32 +/* Command Completion Event. */ +#define TRB_COMPLETION 33 +/* Port Status Change Event. */ +#define TRB_PORT_STATUS 34 +/* Device Controller Event. */ +#define TRB_HC_EVENT 37 +/* MFINDEX Wrap Event - microframe counter wrapped. */ +#define TRB_MFINDEX_WRAP 39 +/* TRB IDs 40-47 reserved. */ +/* Endpoint Not Ready Event. */ +#define TRB_ENDPOINT_NRDY 48 +/* TRB IDs 49-53 reserved. */ +/* Halt Endpoint Command. */ +#define TRB_HALT_ENDPOINT 54 +/* Doorbell Overflow Event. */ +#define TRB_DRB_OVERFLOW 57 +/* Flush Endpoint Command. */ +#define TRB_FLUSH_ENDPOINT 58 + +#define TRB_TYPE_LINK(x) (((x) & TRB_TYPE_BITMASK) == TRB_TYPE(TRB_LINK)) +#define TRB_TYPE_LINK_LE32(x) (((x) & cpu_to_le32(TRB_TYPE_BITMASK)) == \ + cpu_to_le32(TRB_TYPE(TRB_LINK))) +#define TRB_TYPE_NOOP_LE32(x) (((x) & cpu_to_le32(TRB_TYPE_BITMASK)) == \ + cpu_to_le32(TRB_TYPE(TRB_TR_NOOP))) + +/* + * TRBS_PER_SEGMENT must be a multiple of 4. + * The command ring is 64-byte aligned, so it must also be greater than 16. + */ +#define TRBS_PER_SEGMENT 256 +#define TRBS_PER_EVENT_SEGMENT 256 +#define TRBS_PER_EV_DEQ_UPDATE 100 +#define TRB_SEGMENT_SIZE (TRBS_PER_SEGMENT * 16) +#define TRB_SEGMENT_SHIFT (ilog2(TRB_SEGMENT_SIZE)) +/* TRB buffer pointers can't cross 64KB boundaries. */ +#define TRB_MAX_BUFF_SHIFT 16 +#define TRB_MAX_BUFF_SIZE BIT(TRB_MAX_BUFF_SHIFT) +/* How much data is left before the 64KB boundary? */ +#define TRB_BUFF_LEN_UP_TO_BOUNDARY(addr) (TRB_MAX_BUFF_SIZE - \ + ((addr) & (TRB_MAX_BUFF_SIZE - 1))) + +/** + * struct cdnsp_segment - segment related data. + * @trbs: Array of Transfer Request Blocks. + * @next: Pointer to the next segment. + * @dma: DMA address of current segment. + * @bounce_dma: Bounce buffer DMA address . + * @bounce_buf: Bounce buffer virtual address. + * bounce_offs: Bounce buffer offset. + * bounce_len: Bounce buffer length. + */ +struct cdnsp_segment { + union cdnsp_trb *trbs; + struct cdnsp_segment *next; + dma_addr_t dma; + /* Max packet sized bounce buffer for td-fragmant alignment */ + dma_addr_t bounce_dma; + void *bounce_buf; + unsigned int bounce_offs; + unsigned int bounce_len; +}; + +/** + * struct cdnsp_td - Transfer Descriptor object. + * @td_list: Used for binding TD with ep_ring->td_list. + * @preq: Request associated with this TD + * @start_seg: Segment containing the first_trb in TD. + * @first_trb: First TRB for this TD. + * @last_trb: Last TRB related with TD. + * @bounce_seg: Bounce segment for this TD. + * @request_length_set: actual_length of the request has already been set. + * @drbl - TD has been added to HW scheduler - only for stream capable + * endpoints. + */ +struct cdnsp_td { + struct list_head td_list; + struct cdnsp_request *preq; + struct cdnsp_segment *start_seg; + union cdnsp_trb *first_trb; + union cdnsp_trb *last_trb; + struct cdnsp_segment *bounce_seg; + bool request_length_set; + bool drbl; +}; + +/** + * struct cdnsp_dequeue_state - New dequeue pointer for Transfer Ring. + * @new_deq_seg: New dequeue segment. + * @new_deq_ptr: New dequeue pointer. + * @new_cycle_state: New cycle state. + * @stream_id: stream id for which new dequeue pointer has been selected. + */ +struct cdnsp_dequeue_state { + struct cdnsp_segment *new_deq_seg; + union cdnsp_trb *new_deq_ptr; + int new_cycle_state; + unsigned int stream_id; +}; + +enum cdnsp_ring_type { + TYPE_CTRL = 0, + TYPE_ISOC, + TYPE_BULK, + TYPE_INTR, + TYPE_STREAM, + TYPE_COMMAND, + TYPE_EVENT, +}; + +/** + * struct cdnsp_ring - information describing transfer, command or event ring. + * @first_seg: First segment on transfer ring. + * @last_seg: Last segment on transfer ring. + * @enqueue: SW enqueue pointer address. + * @enq_seg: SW enqueue segment address. + * @dequeue: SW dequeue pointer address. + * @deq_seg: SW dequeue segment address. + * @td_list: transfer descriptor list associated with this ring. + * @cycle_state: Current cycle bit. Write the cycle state into the TRB cycle + * field to give ownership of the TRB to the device controller + * (if we are the producer) or to check if we own the TRB + * (if we are the consumer). + * @stream_id: Stream id + * @stream_active: Stream is active - PRIME packet has been detected. + * @stream_rejected: This ring has been rejected by host. + * @num_tds: Number of TDs associated with ring. + * @num_segs: Number of segments. + * @num_trbs_free: Number of free TRBs on the ring. + * @bounce_buf_len: Length of bounce buffer. + * @type: Ring type - event, transfer, or command ring. + * @last_td_was_short - TD is short TD. + * @trb_address_map: For mapping physical TRB addresses to segments in + * stream rings. + */ +struct cdnsp_ring { + struct cdnsp_segment *first_seg; + struct cdnsp_segment *last_seg; + union cdnsp_trb *enqueue; + struct cdnsp_segment *enq_seg; + union cdnsp_trb *dequeue; + struct cdnsp_segment *deq_seg; + struct list_head td_list; + u32 cycle_state; + unsigned int stream_id; + unsigned int stream_active; + unsigned int stream_rejected; + int num_tds; + unsigned int num_segs; + unsigned int num_trbs_free; + unsigned int bounce_buf_len; + enum cdnsp_ring_type type; + bool last_td_was_short; + struct radix_tree_root *trb_address_map; +}; + +/** + * struct cdnsp_erst_entry - even ring segment table entry object. + * @seg_addr: 64-bit event ring segment address. + * seg_size: Number of TRBs in segment.; + */ +struct cdnsp_erst_entry { + __le64 seg_addr; + __le32 seg_size; + /* Set to zero */ + __le32 rsvd; +}; + +/** + * struct cdnsp_erst - even ring segment table for event ring. + * @entries: Array of event ring segments + * @num_entries: Number of segments in entries array. + * @erst_dma_addr: DMA address for entries array. + */ +struct cdnsp_erst { + struct cdnsp_erst_entry *entries; + unsigned int num_entries; + dma_addr_t erst_dma_addr; +}; + +/** + * struct cdnsp_request - extended device side representation of usb_request + * object . + * @td: Transfer descriptor associated with this request. + * @request: Generic usb_request object describing single I/O request. + * @list: Used to adding request to endpoint pending_list. + * @pep: Extended representation of usb_ep object + * @epnum: Endpoint number associated with usb request. + * @direction: Endpoint direction for usb request. + */ +struct cdnsp_request { + struct cdnsp_td td; + struct usb_request request; + struct list_head list; + struct cdnsp_ep *pep; + u8 epnum; + unsigned direction:1; +}; + +#define ERST_NUM_SEGS 1 + +/* Stages used during enumeration process.*/ +enum cdnsp_ep0_stage { + CDNSP_SETUP_STAGE, + CDNSP_DATA_STAGE, + CDNSP_STATUS_STAGE, +}; + +/** + * struct cdnsp_port - holds information about detected ports. + * @port_num: Port number. + * @exist: Indicate if port exist. + * maj_rev: Major revision. + * min_rev: Minor revision. + */ +struct cdnsp_port { + struct cdnsp_port_regs __iomem *regs; + u8 port_num; + u8 exist; + u8 maj_rev; + u8 min_rev; +}; + +#define CDNSP_EXT_PORT_MAJOR(x) (((x) >> 24) & 0xff) +#define CDNSP_EXT_PORT_MINOR(x) (((x) >> 16) & 0xff) +#define CDNSP_EXT_PORT_OFF(x) ((x) & 0xff) +#define CDNSP_EXT_PORT_COUNT(x) (((x) >> 8) & 0xff) + +/** + * struct cdnsp_device - represent USB device. + * @dev: Pointer to device structure associated whit this controller. + * @gadget: Device side representation of the peripheral controller. + * @gadget_driver: Pointer to the gadget driver. + * @irq: IRQ line number used by device side. + * @regs:IO device memory. + * @cap_regs: Capability registers. + * @op_regs: Operational registers. + * @run_regs: Runtime registers. + * @dba: Device base address register. + * @ir_set: Current interrupter register set. + * @port20_regs: Port 2.0 Peripheral Configuration Registers. + * @port3x_regs: USB3.x Port Peripheral Configuration Registers. + * @hcs_params1: Cached register copies of read-only HCSPARAMS1 + * @hcc_params: Cached register copies of read-only HCCPARAMS1 + * @rev_cap: Controller capability. + * @setup: Temporary buffer for setup packet. + * @ep0_preq: Internal allocated request used during enumeration. + * @ep0_stage: ep0 stage during enumeration process. + * @three_stage_setup: Three state or two state setup. + * @ep0_expect_in: Data IN expected for control transfer. + * @setup_id: Setup identifier. + * @setup_speed - Speed detected for current SETUP packet. + * @setup_buf: Buffer for SETUP packet. + * @device_address: Current device address. + * @may_wakeup: remote wakeup enabled/disabled. + * @lock: Lock used in interrupt thread context. + * @hci_version: device controller version. + * @dcbaa: Device context base address array. + * @cmd_ring: Command ring. + * @cmd: Represent all what is needed to issue command on Command Ring. + * @event_ring: Event ring. + * @erst: Event Ring Segment table + * @slot_id: Current Slot ID. Should be 0 or 1. + * @out_ctx: Output context. + * @in_ctx: Input context. + * @eps: array of endpoints object associated with device. + * @usb2_hw_lpm_capable: hardware lpm is enabled; + * @u1_allowed: Allow device transition to U1 state. + * @u2_allowed: Allow device transition to U2 state + * @device_pool: DMA pool for allocating input and output context. + * @segment_pool: DMA pool for allocating new segments. + * @cdnsp_state: Current state of controller. + * @link_state: Current link state. + * @usb2_port - Port USB 2.0. + * @usb3_port - Port USB 3.0. + * @active_port - Current selected Port. + * @test_mode: selected Test Mode. + */ +struct cdnsp_device { + struct device *dev; + struct usb_gadget gadget; + struct usb_gadget_driver *gadget_driver; + unsigned int irq; + void __iomem *regs; + + /* Registers map */ + struct cdnsp_cap_regs __iomem *cap_regs; + struct cdnsp_op_regs __iomem *op_regs; + struct cdnsp_run_regs __iomem *run_regs; + struct cdnsp_doorbell_array __iomem *dba; + struct cdnsp_intr_reg __iomem *ir_set; + struct cdnsp_20port_cap __iomem *port20_regs; + struct cdnsp_3xport_cap __iomem *port3x_regs; + + /* Cached register copies of read-only CDNSP data */ + __u32 hcs_params1; + __u32 hcs_params3; + __u32 hcc_params; + struct cdnsp_rev_cap rev_cap; + /* Lock used in interrupt thread context. */ + spinlock_t lock; + struct usb_ctrlrequest setup; + struct cdnsp_request ep0_preq; + enum cdnsp_ep0_stage ep0_stage; + u8 three_stage_setup; + u8 ep0_expect_in; + u8 setup_id; + u8 setup_speed; + void *setup_buf; + u8 device_address; + int may_wakeup; + u16 hci_version; + + /* data structures */ + struct cdnsp_device_context_array *dcbaa; + struct cdnsp_ring *cmd_ring; + struct cdnsp_command cmd; + struct cdnsp_ring *event_ring; + struct cdnsp_erst erst; + int slot_id; + + /* + * Commands to the hardware are passed an "input context" that + * tells the hardware what to change in its data structures. + * The hardware will return changes in an "output context" that + * software must allocate for the hardware. . + */ + struct cdnsp_container_ctx out_ctx; + struct cdnsp_container_ctx in_ctx; + struct cdnsp_ep eps[CDNSP_ENDPOINTS_NUM]; + u8 usb2_hw_lpm_capable:1; + u8 u1_allowed:1; + u8 u2_allowed:1; + + /* DMA pools */ + struct dma_pool *device_pool; + struct dma_pool *segment_pool; + +#define CDNSP_STATE_HALTED BIT(1) +#define CDNSP_STATE_DYING BIT(2) +#define CDNSP_STATE_DISCONNECT_PENDING BIT(3) +#define CDNSP_WAKEUP_PENDING BIT(4) + unsigned int cdnsp_state; + unsigned int link_state; + + struct cdnsp_port usb2_port; + struct cdnsp_port usb3_port; + struct cdnsp_port *active_port; + u16 test_mode; +}; + +#endif /* __LINUX_CDNSP_GADGET_H */
From: Wesley Cheng wcheng@codeaurora.org
[ Upstream commit ce7d0008c2356626f69f37ef1afce8fbc83fe142 ]
Some UDCs may have constraints on how many high bandwidth endpoints it can support in a certain configuration. This API allows for the composite driver to pass down the total number of endpoints to the UDC so it can verify it has the required resources to support the configuration.
Signed-off-by: Wesley Cheng wcheng@codeaurora.org Link: https://lore.kernel.org/r/1625908395-5498-2-git-send-email-wcheng@codeaurora... Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org Stable-dep-of: dbe678f6192f ("usb: cdns3: fix NCM gadget RX speed 20x slow than expection at iMX8QM") Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/usb/gadget/udc/core.c | 19 +++++++++++++++++++ include/linux/usb/gadget.h | 4 ++++ 2 files changed, 23 insertions(+)
diff --git a/drivers/usb/gadget/udc/core.c b/drivers/usb/gadget/udc/core.c index 3a3b5a03dda75..14d9d1ee16fc4 100644 --- a/drivers/usb/gadget/udc/core.c +++ b/drivers/usb/gadget/udc/core.c @@ -1004,6 +1004,25 @@ int usb_gadget_ep_match_desc(struct usb_gadget *gadget, } EXPORT_SYMBOL_GPL(usb_gadget_ep_match_desc);
+/** + * usb_gadget_check_config - checks if the UDC can support the binded + * configuration + * @gadget: controller to check the USB configuration + * + * Ensure that a UDC is able to support the requested resources by a + * configuration, and that there are no resource limitations, such as + * internal memory allocated to all requested endpoints. + * + * Returns zero on success, else a negative errno. + */ +int usb_gadget_check_config(struct usb_gadget *gadget) +{ + if (gadget->ops->check_config) + return gadget->ops->check_config(gadget); + return 0; +} +EXPORT_SYMBOL_GPL(usb_gadget_check_config); + /* ------------------------------------------------------------------------- */
static void usb_gadget_state_work(struct work_struct *work) diff --git a/include/linux/usb/gadget.h b/include/linux/usb/gadget.h index e7351d64f11fa..11df3d5b40c6b 100644 --- a/include/linux/usb/gadget.h +++ b/include/linux/usb/gadget.h @@ -326,6 +326,7 @@ struct usb_gadget_ops { struct usb_ep *(*match_ep)(struct usb_gadget *, struct usb_endpoint_descriptor *, struct usb_ss_ep_comp_descriptor *); + int (*check_config)(struct usb_gadget *gadget); };
/** @@ -596,6 +597,7 @@ int usb_gadget_connect(struct usb_gadget *gadget); int usb_gadget_disconnect(struct usb_gadget *gadget); int usb_gadget_deactivate(struct usb_gadget *gadget); int usb_gadget_activate(struct usb_gadget *gadget); +int usb_gadget_check_config(struct usb_gadget *gadget); #else static inline int usb_gadget_frame_number(struct usb_gadget *gadget) { return 0; } @@ -619,6 +621,8 @@ static inline int usb_gadget_deactivate(struct usb_gadget *gadget) { return 0; } static inline int usb_gadget_activate(struct usb_gadget *gadget) { return 0; } +static inline int usb_gadget_check_config(struct usb_gadget *gadget) +{ return 0; } #endif /* CONFIG_USB_GADGET */
/*-------------------------------------------------------------------------*/
From: Frank Li Frank.Li@nxp.com
[ Upstream commit dce49449e04ff150838a31386ee65917beb9ebb5 ]
Some devices have USB compositions which may require multiple endpoints. To get better performance, need bigger CDNS3_EP_BUF_SIZE.
But bigger CDNS3_EP_BUF_SIZE may exceed total hardware FIFO size when multiple endpoints.
By introducing the check_config() callback, calculate CDNS3_EP_BUF_SIZE.
Move CDNS3_EP_BUF_SIZE into cnds3_device: ep_buf_size Combine CDNS3_EP_ISO_SS_BURST and CDNS3_EP_ISO_HS_MULT into cnds3_device:ep_iso_burst
Using a simple algorithm to calculate ep_buf_size. ep_buf_size = ep_iso_burst = (onchip_buffers - 2k) / (number of IN EP + 1).
Test at 8qxp:
Gadget ep_buf_size
RNDIS: 5 RNDIS+ACM: 3 Mass Storage + NCM + ACM 2
Previous CDNS3_EP_BUF_SIZE is 4, RNDIS + ACM will be failure because exceed FIFO memory.
Acked-by: Peter Chen peter.chen@kernel.org Signed-off-by: Frank Li Frank.Li@nxp.com Link: https://lore.kernel.org/r/20220509164055.1815081-1-Frank.Li@nxp.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org Stable-dep-of: dbe678f6192f ("usb: cdns3: fix NCM gadget RX speed 20x slow than expection at iMX8QM") Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/usb/cdns3/gadget.c | 47 ++++++++++++++++++++++++++++++++++---- drivers/usb/cdns3/gadget.h | 9 +++++--- 2 files changed, 49 insertions(+), 7 deletions(-)
diff --git a/drivers/usb/cdns3/gadget.c b/drivers/usb/cdns3/gadget.c index e3a8b6c71aa1d..24dab7006b823 100644 --- a/drivers/usb/cdns3/gadget.c +++ b/drivers/usb/cdns3/gadget.c @@ -2041,7 +2041,7 @@ int cdns3_ep_config(struct cdns3_endpoint *priv_ep, bool enable) u8 mult = 0; int ret;
- buffering = CDNS3_EP_BUF_SIZE - 1; + buffering = priv_dev->ep_buf_size - 1;
cdns3_configure_dmult(priv_dev, priv_ep);
@@ -2060,7 +2060,7 @@ int cdns3_ep_config(struct cdns3_endpoint *priv_ep, bool enable) break; default: ep_cfg = EP_CFG_EPTYPE(USB_ENDPOINT_XFER_ISOC); - mult = CDNS3_EP_ISO_HS_MULT - 1; + mult = priv_dev->ep_iso_burst - 1; buffering = mult + 1; }
@@ -2076,14 +2076,14 @@ int cdns3_ep_config(struct cdns3_endpoint *priv_ep, bool enable) mult = 0; max_packet_size = 1024; if (priv_ep->type == USB_ENDPOINT_XFER_ISOC) { - maxburst = CDNS3_EP_ISO_SS_BURST - 1; + maxburst = priv_dev->ep_iso_burst - 1; buffering = (mult + 1) * (maxburst + 1);
if (priv_ep->interval > 1) buffering++; } else { - maxburst = CDNS3_EP_BUF_SIZE - 1; + maxburst = priv_dev->ep_buf_size - 1; } break; default: @@ -2098,6 +2098,10 @@ int cdns3_ep_config(struct cdns3_endpoint *priv_ep, bool enable) else priv_ep->trb_burst_size = 16;
+ mult = min_t(u8, mult, EP_CFG_MULT_MAX); + buffering = min_t(u8, buffering, EP_CFG_BUFFERING_MAX); + maxburst = min_t(u8, maxburst, EP_CFG_MAXBURST_MAX); + /* onchip buffer is only allocated before configuration */ if (!priv_dev->hw_configured_flag) { ret = cdns3_ep_onchip_buffer_reserve(priv_dev, buffering + 1, @@ -2971,6 +2975,40 @@ static int cdns3_gadget_udc_stop(struct usb_gadget *gadget) return 0; }
+/** + * cdns3_gadget_check_config - ensure cdns3 can support the USB configuration + * @gadget: pointer to the USB gadget + * + * Used to record the maximum number of endpoints being used in a USB composite + * device. (across all configurations) This is to be used in the calculation + * of the TXFIFO sizes when resizing internal memory for individual endpoints. + * It will help ensured that the resizing logic reserves enough space for at + * least one max packet. + */ +static int cdns3_gadget_check_config(struct usb_gadget *gadget) +{ + struct cdns3_device *priv_dev = gadget_to_cdns3_device(gadget); + struct usb_ep *ep; + int n_in = 0; + int total; + + list_for_each_entry(ep, &gadget->ep_list, ep_list) { + if (ep->claimed && (ep->address & USB_DIR_IN)) + n_in++; + } + + /* 2KB are reserved for EP0, 1KB for out*/ + total = 2 + n_in + 1; + + if (total > priv_dev->onchip_buffers) + return -ENOMEM; + + priv_dev->ep_buf_size = priv_dev->ep_iso_burst = + (priv_dev->onchip_buffers - 2) / (n_in + 1); + + return 0; +} + static const struct usb_gadget_ops cdns3_gadget_ops = { .get_frame = cdns3_gadget_get_frame, .wakeup = cdns3_gadget_wakeup, @@ -2979,6 +3017,7 @@ static const struct usb_gadget_ops cdns3_gadget_ops = { .udc_start = cdns3_gadget_udc_start, .udc_stop = cdns3_gadget_udc_stop, .match_ep = cdns3_gadget_match_ep, + .check_config = cdns3_gadget_check_config, };
static void cdns3_free_all_eps(struct cdns3_device *priv_dev) diff --git a/drivers/usb/cdns3/gadget.h b/drivers/usb/cdns3/gadget.h index 21fa461c518ec..32825477edd3e 100644 --- a/drivers/usb/cdns3/gadget.h +++ b/drivers/usb/cdns3/gadget.h @@ -561,15 +561,18 @@ struct cdns3_usb_regs { /* Max burst size (used only in SS mode). */ #define EP_CFG_MAXBURST_MASK GENMASK(11, 8) #define EP_CFG_MAXBURST(p) (((p) << 8) & EP_CFG_MAXBURST_MASK) +#define EP_CFG_MAXBURST_MAX 15 /* ISO max burst. */ #define EP_CFG_MULT_MASK GENMASK(15, 14) #define EP_CFG_MULT(p) (((p) << 14) & EP_CFG_MULT_MASK) +#define EP_CFG_MULT_MAX 2 /* ISO max burst. */ #define EP_CFG_MAXPKTSIZE_MASK GENMASK(26, 16) #define EP_CFG_MAXPKTSIZE(p) (((p) << 16) & EP_CFG_MAXPKTSIZE_MASK) /* Max number of buffered packets. */ #define EP_CFG_BUFFERING_MASK GENMASK(31, 27) #define EP_CFG_BUFFERING(p) (((p) << 27) & EP_CFG_BUFFERING_MASK) +#define EP_CFG_BUFFERING_MAX 15
/* EP_CMD - bitmasks */ /* Endpoint reset. */ @@ -1093,9 +1096,6 @@ struct cdns3_trb { #define CDNS3_ENDPOINTS_MAX_COUNT 32 #define CDNS3_EP_ZLP_BUF_SIZE 1024
-#define CDNS3_EP_BUF_SIZE 4 /* KB */ -#define CDNS3_EP_ISO_HS_MULT 3 -#define CDNS3_EP_ISO_SS_BURST 3 #define CDNS3_MAX_NUM_DESCMISS_BUF 32 #define CDNS3_DESCMIS_BUF_SIZE 2048 /* Bytes */ #define CDNS3_WA2_NUM_BUFFERS 128 @@ -1330,6 +1330,9 @@ struct cdns3_device { /*in KB */ u16 onchip_buffers; u16 onchip_used_size; + + u16 ep_buf_size; + u16 ep_iso_burst; };
void cdns3_set_register_bit(void __iomem *ptr, u32 mask);
From: Frank Li Frank.Li@nxp.com
[ Upstream commit dbe678f6192f27879ac9ff6bc7a1036aad85aae9 ]
At iMX8QM platform, enable NCM gadget and run 'iperf3 -s'. At host, run 'iperf3 -V -c fe80::6863:98ff:feef:3e0%enxc6e147509498'
[ 5] 0.00-1.00 sec 1.55 MBytes 13.0 Mbits/sec 90 4.18 KBytes [ 5] 1.00-2.00 sec 1.44 MBytes 12.0 Mbits/sec 75 4.18 KBytes [ 5] 2.00-3.00 sec 1.48 MBytes 12.4 Mbits/sec 75 4.18 KBytes
Expected speed should be bigger than 300Mbits/sec.
The root cause of this performance drop was found to be data corruption happening at 4K borders in some Ethernet packets, leading to TCP checksum errors. This corruption occurs from the position (4K - (address & 0x7F)) to 4K. The u_ether function's allocation of skb_buff reserves 64B, meaning all RX addresses resemble 0xXXXX0040.
Force trb_burst_size to 16 can fix this problem.
Cc: stable@vger.kernel.org Fixes: 7733f6c32e36 ("usb: cdns3: Add Cadence USB3 DRD Driver") Signed-off-by: Frank Li Frank.Li@nxp.com Link: https://lore.kernel.org/r/20230518154946.3666662-1-Frank.Li@nxp.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/usb/cdns3/gadget.c | 13 +++++++++++++ 1 file changed, 13 insertions(+)
diff --git a/drivers/usb/cdns3/gadget.c b/drivers/usb/cdns3/gadget.c index 24dab7006b823..210c1d6150825 100644 --- a/drivers/usb/cdns3/gadget.c +++ b/drivers/usb/cdns3/gadget.c @@ -2098,6 +2098,19 @@ int cdns3_ep_config(struct cdns3_endpoint *priv_ep, bool enable) else priv_ep->trb_burst_size = 16;
+ /* + * In versions preceding DEV_VER_V2, for example, iMX8QM, there exit the bugs + * in the DMA. These bugs occur when the trb_burst_size exceeds 16 and the + * address is not aligned to 128 Bytes (which is a product of the 64-bit AXI + * and AXI maximum burst length of 16 or 0xF+1, dma_axi_ctrl0[3:0]). This + * results in data corruption when it crosses the 4K border. The corruption + * specifically occurs from the position (4K - (address & 0x7F)) to 4K. + * + * So force trb_burst_size to 16 at such platform. + */ + if (priv_dev->dev_ver < DEV_VER_V2) + priv_ep->trb_burst_size = 16; + mult = min_t(u8, mult, EP_CFG_MULT_MAX); buffering = min_t(u8, buffering, EP_CFG_BUFFERING_MAX); maxburst = min_t(u8, maxburst, EP_CFG_MAXBURST_MAX);
From: Johan Hovold johan+linaro@kernel.org
[ Upstream commit d2d69354226de0b333d4405981f3d9c41ba8430a ]
The Qualcomm dwc3 glue driver is currently accessing the driver data of the child core device during suspend and on wakeup interrupts. This is clearly a bad idea as the child may not have probed yet or could have been unbound from its driver.
The first such layering violation was part of the initial version of the driver, but this was later made worse when the hack that accesses the driver data of the grand child xhci device to configure the wakeup interrupts was added.
Fixing this properly is not that easily done, so add a sanity check to make sure that the child driver data is non-NULL before dereferencing it for now.
Note that this relies on subtleties like the fact that driver core is making sure that the parent is not suspended while the child is probing.
Reported-by: Manivannan Sadhasivam manivannan.sadhasivam@linaro.org Link: https://lore.kernel.org/all/20230325165217.31069-4-manivannan.sadhasivam@lin... Fixes: d9152161b4bf ("usb: dwc3: Add Qualcomm DWC3 glue layer driver") Fixes: 6895ea55c385 ("usb: dwc3: qcom: Configure wakeup interrupts during suspend") Cc: stable@vger.kernel.org # 3.18: a872ab303d5d: "usb: dwc3: qcom: fix use-after-free on runtime-PM wakeup" Cc: Sandeep Maheswaram quic_c_sanm@quicinc.com Cc: Krishna Kurapati quic_kriskura@quicinc.com Signed-off-by: Johan Hovold johan+linaro@kernel.org Acked-by: Thinh Nguyen Thinh.Nguyen@synopsys.com Reviewed-by: Manivannan Sadhasivam manivannan.sadhasivam@linaro.org Message-ID: 20230607100540.31045-2-johan+linaro@kernel.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/usb/dwc3/dwc3-qcom.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-)
diff --git a/drivers/usb/dwc3/dwc3-qcom.c b/drivers/usb/dwc3/dwc3-qcom.c index ec8c43231746e..3973f6c18857e 100644 --- a/drivers/usb/dwc3/dwc3-qcom.c +++ b/drivers/usb/dwc3/dwc3-qcom.c @@ -306,7 +306,16 @@ static void dwc3_qcom_interconnect_exit(struct dwc3_qcom *qcom) /* Only usable in contexts where the role can not change. */ static bool dwc3_qcom_is_host(struct dwc3_qcom *qcom) { - struct dwc3 *dwc = platform_get_drvdata(qcom->dwc3); + struct dwc3 *dwc; + + /* + * FIXME: Fix this layering violation. + */ + dwc = platform_get_drvdata(qcom->dwc3); + + /* Core driver may not have probed yet. */ + if (!dwc) + return false;
return dwc->xhci; }
From: Sergey Shtylyov s.shtylyov@omp.ru
[ Upstream commit 71150ac12558bcd9d75e6e24cf7c872c2efd80f3 ]
The driver overrides the error codes and IRQ0 returned by platform_get_irq() to -EINVAL, so if it returns -EPROBE_DEFER, the driver will fail the probe permanently instead of the deferred probing. Switch to propagating the error codes upstream. Since commit ce753ad1549c ("platform: finally disallow IRQ0 in platform_get_irq() and its ilk") IRQ0 is no longer returned by those APIs, so we now can safely ignore it...
Fixes: 660fc733bd74 ("mmc: bcm2835: Add new driver for the sdhost controller.") Cc: stable@vger.kernel.org # v5.19+ Signed-off-by: Sergey Shtylyov s.shtylyov@omp.ru Link: https://lore.kernel.org/r/20230617203622.6812-2-s.shtylyov@omp.ru Signed-off-by: Ulf Hansson ulf.hansson@linaro.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/mmc/host/bcm2835.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/mmc/host/bcm2835.c b/drivers/mmc/host/bcm2835.c index 8c2361e662774..985079943be76 100644 --- a/drivers/mmc/host/bcm2835.c +++ b/drivers/mmc/host/bcm2835.c @@ -1413,8 +1413,8 @@ static int bcm2835_probe(struct platform_device *pdev) host->max_clk = clk_get_rate(clk);
host->irq = platform_get_irq(pdev, 0); - if (host->irq <= 0) { - ret = -EINVAL; + if (host->irq < 0) { + ret = host->irq; goto err; }
On 8/24/23 5:50 PM, Greg Kroah-Hartman wrote:
From: Sergey Shtylyov s.shtylyov@omp.ru
[ Upstream commit 71150ac12558bcd9d75e6e24cf7c872c2efd80f3 ]
The driver overrides the error codes and IRQ0 returned by platform_get_irq() to -EINVAL, so if it returns -EPROBE_DEFER, the driver will fail the probe permanently instead of the deferred probing. Switch to propagating the error codes upstream. Since commit ce753ad1549c ("platform: finally disallow IRQ0 in platform_get_irq() and its ilk") IRQ0 is no longer returned by those APIs, so we now can safely ignore it...
Fixes: 660fc733bd74 ("mmc: bcm2835: Add new driver for the sdhost controller.") Cc: stable@vger.kernel.org # v5.19+
After a glance at the driver, the patch seems safe to be applied to 5.10.y, despite I tried to limit it to 5.19.y and newer...
Signed-off-by: Sergey Shtylyov s.shtylyov@omp.ru Link: https://lore.kernel.org/r/20230617203622.6812-2-s.shtylyov@omp.ru Signed-off-by: Ulf Hansson ulf.hansson@linaro.org Signed-off-by: Sasha Levin sashal@kernel.org
[...]
MBR, Sergey
From: Sergey Shtylyov s.shtylyov@omp.ru
[ Upstream commit c2df53c5806cfd746dae08e07bc8c4ad247c3b70 ]
The driver overrides the error codes and IRQ0 returned by platform_get_irq() to -EINVAL, so if it returns -EPROBE_DEFER, the driver will fail the probe permanently instead of the deferred probing. Switch to propagating the error codes upstream. Since commit ce753ad1549c ("platform: finally disallow IRQ0 in platform_get_irq() and its ilk") IRQ0 is no longer returned by those APIs, so we now can safely ignore it...
Fixes: 2408a08583d2 ("mmc: sunxi-mmc: Handle return value of platform_get_irq") Cc: stable@vger.kernel.org # v5.19+ Signed-off-by: Sergey Shtylyov s.shtylyov@omp.ru Reviewed-by: Jernej Skrabec jernej.skrabec@gmail.com Link: https://lore.kernel.org/r/20230617203622.6812-12-s.shtylyov@omp.ru Signed-off-by: Ulf Hansson ulf.hansson@linaro.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/mmc/host/sunxi-mmc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/mmc/host/sunxi-mmc.c b/drivers/mmc/host/sunxi-mmc.c index 9215069c61560..b834fde3f9eda 100644 --- a/drivers/mmc/host/sunxi-mmc.c +++ b/drivers/mmc/host/sunxi-mmc.c @@ -1317,8 +1317,8 @@ static int sunxi_mmc_resource_request(struct sunxi_mmc_host *host, return ret;
host->irq = platform_get_irq(pdev, 0); - if (host->irq <= 0) { - ret = -EINVAL; + if (host->irq < 0) { + ret = host->irq; goto error_disable_mmc; }
On 8/24/23 5:50 PM, Greg Kroah-Hartman wrote:
From: Sergey Shtylyov s.shtylyov@omp.ru
[ Upstream commit c2df53c5806cfd746dae08e07bc8c4ad247c3b70 ]
The driver overrides the error codes and IRQ0 returned by platform_get_irq() to -EINVAL, so if it returns -EPROBE_DEFER, the driver will fail the probe permanently instead of the deferred probing. Switch to propagating the error codes upstream. Since commit ce753ad1549c ("platform: finally disallow IRQ0 in platform_get_irq() and its ilk") IRQ0 is no longer returned by those APIs, so we now can safely ignore it...
Fixes: 2408a08583d2 ("mmc: sunxi-mmc: Handle return value of platform_get_irq") Cc: stable@vger.kernel.org # v5.19+
After a glance at the driver, the patch too seems safe to be applied to 5.10.y, despite I tried to limit it to 5.19.y and newer...
Signed-off-by: Sergey Shtylyov s.shtylyov@omp.ru Reviewed-by: Jernej Skrabec jernej.skrabec@gmail.com Link: https://lore.kernel.org/r/20230617203622.6812-12-s.shtylyov@omp.ru Signed-off-by: Ulf Hansson ulf.hansson@linaro.org Signed-off-by: Sasha Levin sashal@kernel.org
[...]
MBR, Sergey
From: Heiner Kallweit hkallweit1@gmail.com
[ Upstream commit 80df83c2c57e75cb482ccf0c639ce84703ab41a2 ]
Add a device-managed version of mmc_alloc_host().
The argument order is reversed compared to mmc_alloc_host() because device-managed functions typically have the device argument first.
Signed-off-by: Heiner Kallweit hkallweit1@gmail.com Link: https://lore.kernel.org/r/6d8f9fdc-7c9e-8e4f-e6ef-5470b971c74e@gmail.com Signed-off-by: Ulf Hansson ulf.hansson@linaro.org Stable-dep-of: b8ada54fa1b8 ("mmc: meson-gx: fix deferred probing") Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/mmc/core/host.c | 26 ++++++++++++++++++++++++++ include/linux/mmc/host.h | 1 + 2 files changed, 27 insertions(+)
diff --git a/drivers/mmc/core/host.c b/drivers/mmc/core/host.c index 03e2f965a96a8..1f46694b2e531 100644 --- a/drivers/mmc/core/host.c +++ b/drivers/mmc/core/host.c @@ -513,6 +513,32 @@ struct mmc_host *mmc_alloc_host(int extra, struct device *dev)
EXPORT_SYMBOL(mmc_alloc_host);
+static void devm_mmc_host_release(struct device *dev, void *res) +{ + mmc_free_host(*(struct mmc_host **)res); +} + +struct mmc_host *devm_mmc_alloc_host(struct device *dev, int extra) +{ + struct mmc_host **dr, *host; + + dr = devres_alloc(devm_mmc_host_release, sizeof(*dr), GFP_KERNEL); + if (!dr) + return ERR_PTR(-ENOMEM); + + host = mmc_alloc_host(extra, dev); + if (IS_ERR(host)) { + devres_free(dr); + return host; + } + + *dr = host; + devres_add(dev, dr); + + return host; +} +EXPORT_SYMBOL(devm_mmc_alloc_host); + static int mmc_validate_host_caps(struct mmc_host *host) { if (host->caps & MMC_CAP_SDIO_IRQ && !host->ops->enable_sdio_irq) { diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h index 40d7e98fc9902..fb294cbb9081d 100644 --- a/include/linux/mmc/host.h +++ b/include/linux/mmc/host.h @@ -477,6 +477,7 @@ struct mmc_host { struct device_node;
struct mmc_host *mmc_alloc_host(int extra, struct device *); +struct mmc_host *devm_mmc_alloc_host(struct device *dev, int extra); int mmc_add_host(struct mmc_host *); void mmc_remove_host(struct mmc_host *); void mmc_free_host(struct mmc_host *);
From: Heiner Kallweit hkallweit1@gmail.com
[ Upstream commit 418f7c2de1334b70fbee790911a1b46503230137 ]
Use new function devm_mmc_alloc_host() to simplify the code.
Signed-off-by: Heiner Kallweit hkallweit1@gmail.com Link: https://lore.kernel.org/r/728f159b-885f-c78a-1a3d-f55c245250e1@gmail.com Signed-off-by: Ulf Hansson ulf.hansson@linaro.org Stable-dep-of: b8ada54fa1b8 ("mmc: meson-gx: fix deferred probing") Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/mmc/host/meson-gx-mmc.c | 52 +++++++++++---------------------- 1 file changed, 17 insertions(+), 35 deletions(-)
diff --git a/drivers/mmc/host/meson-gx-mmc.c b/drivers/mmc/host/meson-gx-mmc.c index e89bd6f4b317c..8a345ee2e6cf5 100644 --- a/drivers/mmc/host/meson-gx-mmc.c +++ b/drivers/mmc/host/meson-gx-mmc.c @@ -1122,7 +1122,7 @@ static int meson_mmc_probe(struct platform_device *pdev) struct mmc_host *mmc; int ret;
- mmc = mmc_alloc_host(sizeof(struct meson_host), &pdev->dev); + mmc = devm_mmc_alloc_host(&pdev->dev, sizeof(struct meson_host)); if (!mmc) return -ENOMEM; host = mmc_priv(mmc); @@ -1138,46 +1138,33 @@ static int meson_mmc_probe(struct platform_device *pdev) host->vqmmc_enabled = false; ret = mmc_regulator_get_supply(mmc); if (ret) - goto free_host; + return ret;
ret = mmc_of_parse(mmc); - if (ret) { - if (ret != -EPROBE_DEFER) - dev_warn(&pdev->dev, "error parsing DT: %d\n", ret); - goto free_host; - } + if (ret) + return dev_err_probe(&pdev->dev, ret, "error parsing DT\n");
host->data = (struct meson_mmc_data *) of_device_get_match_data(&pdev->dev); - if (!host->data) { - ret = -EINVAL; - goto free_host; - } + if (!host->data) + return -EINVAL;
ret = device_reset_optional(&pdev->dev); - if (ret) { - dev_err_probe(&pdev->dev, ret, "device reset failed\n"); - goto free_host; - } + if (ret) + return dev_err_probe(&pdev->dev, ret, "device reset failed\n");
res = platform_get_resource(pdev, IORESOURCE_MEM, 0); host->regs = devm_ioremap_resource(&pdev->dev, res); - if (IS_ERR(host->regs)) { - ret = PTR_ERR(host->regs); - goto free_host; - } + if (IS_ERR(host->regs)) + return PTR_ERR(host->regs);
host->irq = platform_get_irq(pdev, 0); - if (host->irq <= 0) { - ret = -EINVAL; - goto free_host; - } + if (host->irq <= 0) + return -EINVAL;
host->pinctrl = devm_pinctrl_get(&pdev->dev); - if (IS_ERR(host->pinctrl)) { - ret = PTR_ERR(host->pinctrl); - goto free_host; - } + if (IS_ERR(host->pinctrl)) + return PTR_ERR(host->pinctrl);
host->pins_clk_gate = pinctrl_lookup_state(host->pinctrl, "clk-gate"); @@ -1188,14 +1175,12 @@ static int meson_mmc_probe(struct platform_device *pdev) }
host->core_clk = devm_clk_get(&pdev->dev, "core"); - if (IS_ERR(host->core_clk)) { - ret = PTR_ERR(host->core_clk); - goto free_host; - } + if (IS_ERR(host->core_clk)) + return PTR_ERR(host->core_clk);
ret = clk_prepare_enable(host->core_clk); if (ret) - goto free_host; + return ret;
ret = meson_mmc_clk_init(host); if (ret) @@ -1290,8 +1275,6 @@ static int meson_mmc_probe(struct platform_device *pdev) clk_disable_unprepare(host->mmc_clk); err_core_clk: clk_disable_unprepare(host->core_clk); -free_host: - mmc_free_host(mmc); return ret; }
@@ -1315,7 +1298,6 @@ static int meson_mmc_remove(struct platform_device *pdev) clk_disable_unprepare(host->mmc_clk); clk_disable_unprepare(host->core_clk);
- mmc_free_host(host->mmc); return 0; }
From: Sergey Shtylyov s.shtylyov@omp.ru
[ Upstream commit b8ada54fa1b83f3b6480d4cced71354301750153 ]
The driver overrides the error codes and IRQ0 returned by platform_get_irq() to -EINVAL, so if it returns -EPROBE_DEFER, the driver will fail the probe permanently instead of the deferred probing. Switch to propagating the error codes upstream. Since commit ce753ad1549c ("platform: finally disallow IRQ0 in platform_get_irq() and its ilk") IRQ0 is no longer returned by those APIs, so we now can safely ignore it...
Fixes: cbcaac6d7dd2 ("mmc: meson-gx-mmc: Fix platform_get_irq's error checking") Cc: stable@vger.kernel.org # v5.19+ Signed-off-by: Sergey Shtylyov s.shtylyov@omp.ru Reviewed-by: Neil Armstrong neil.armstrong@linaro.org Link: https://lore.kernel.org/r/20230617203622.6812-3-s.shtylyov@omp.ru Signed-off-by: Ulf Hansson ulf.hansson@linaro.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/mmc/host/meson-gx-mmc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/mmc/host/meson-gx-mmc.c b/drivers/mmc/host/meson-gx-mmc.c index 8a345ee2e6cf5..1992eea8b777e 100644 --- a/drivers/mmc/host/meson-gx-mmc.c +++ b/drivers/mmc/host/meson-gx-mmc.c @@ -1159,8 +1159,8 @@ static int meson_mmc_probe(struct platform_device *pdev) return PTR_ERR(host->regs);
host->irq = platform_get_irq(pdev, 0); - if (host->irq <= 0) - return -EINVAL; + if (host->irq < 0) + return host->irq;
host->pinctrl = devm_pinctrl_get(&pdev->dev); if (IS_ERR(host->pinctrl))
On 8/24/23 5:50 PM, Greg Kroah-Hartman wrote:
From: Sergey Shtylyov s.shtylyov@omp.ru
[ Upstream commit b8ada54fa1b83f3b6480d4cced71354301750153 ]
The driver overrides the error codes and IRQ0 returned by platform_get_irq() to -EINVAL, so if it returns -EPROBE_DEFER, the driver will fail the probe permanently instead of the deferred probing. Switch to propagating the error codes upstream. Since commit ce753ad1549c ("platform: finally disallow IRQ0 in platform_get_irq() and its ilk") IRQ0 is no longer returned by those APIs, so we now can safely ignore it...
Fixes: cbcaac6d7dd2 ("mmc: meson-gx-mmc: Fix platform_get_irq's error checking") Cc: stable@vger.kernel.org # v5.19+
After a glance at the driver, the patch too seems safe to be applied to 5.10.y, despite I tried to limit it to 5.19.y and newer...
Signed-off-by: Sergey Shtylyov s.shtylyov@omp.ru Reviewed-by: Neil Armstrong neil.armstrong@linaro.org Link: https://lore.kernel.org/r/20230617203622.6812-3-s.shtylyov@omp.ru Signed-off-by: Ulf Hansson ulf.hansson@linaro.org Signed-off-by: Sasha Levin sashal@kernel.org
[...]
MBR, Sergey
From: Steven Rostedt (VMware) rostedt@goodmis.org
[ Upstream commit 8565a45d0858078b63c7d84074a21a42ba9ebf01 ]
In preparation to allow event probes to use the process_fetch_insn() callback in trace_probe_tmpl.h, change the data passed to it from a pointer to pt_regs, as the event probe will not be using regs, and make it a void pointer instead.
Update the process_fetch_insn() callers for kprobe and uprobe events to have the regs defined in the function and just typecast the void pointer parameter.
Link: https://lkml.kernel.org/r/20210819041842.291622924@goodmis.org
Acked-by: Masami Hiramatsu mhiramat@kernel.org Signed-off-by: Steven Rostedt (VMware) rostedt@goodmis.org Stable-dep-of: e38e2c6a9efc ("tracing/probes: Fix to update dynamic data counter if fetcharg uses it") Signed-off-by: Sasha Levin sashal@kernel.org --- kernel/trace/trace_kprobe.c | 3 ++- kernel/trace/trace_probe_tmpl.h | 6 +++--- kernel/trace/trace_uprobe.c | 3 ++- 3 files changed, 7 insertions(+), 5 deletions(-)
diff --git a/kernel/trace/trace_kprobe.c b/kernel/trace/trace_kprobe.c index 41dd17390c732..b882c6519b035 100644 --- a/kernel/trace/trace_kprobe.c +++ b/kernel/trace/trace_kprobe.c @@ -1332,9 +1332,10 @@ probe_mem_read(void *dest, void *src, size_t size)
/* Note that we don't verify it, since the code does not come from user space */ static int -process_fetch_insn(struct fetch_insn *code, struct pt_regs *regs, void *dest, +process_fetch_insn(struct fetch_insn *code, void *rec, void *dest, void *base) { + struct pt_regs *regs = rec; unsigned long val;
retry: diff --git a/kernel/trace/trace_probe_tmpl.h b/kernel/trace/trace_probe_tmpl.h index 29348874ebde7..bbb479b3ba8fd 100644 --- a/kernel/trace/trace_probe_tmpl.h +++ b/kernel/trace/trace_probe_tmpl.h @@ -54,7 +54,7 @@ fetch_apply_bitfield(struct fetch_insn *code, void *buf) * If dest is NULL, don't store result and return required dynamic data size. */ static int -process_fetch_insn(struct fetch_insn *code, struct pt_regs *regs, +process_fetch_insn(struct fetch_insn *code, void *rec, void *dest, void *base); static nokprobe_inline int fetch_store_strlen(unsigned long addr); static nokprobe_inline int @@ -190,7 +190,7 @@ __get_data_size(struct trace_probe *tp, struct pt_regs *regs)
/* Store the value of each argument */ static nokprobe_inline void -store_trace_args(void *data, struct trace_probe *tp, struct pt_regs *regs, +store_trace_args(void *data, struct trace_probe *tp, void *rec, int header_size, int maxlen) { struct probe_arg *arg; @@ -205,7 +205,7 @@ store_trace_args(void *data, struct trace_probe *tp, struct pt_regs *regs, /* Point the dynamic data area if needed */ if (unlikely(arg->dynamic)) *dl = make_data_loc(maxlen, dyndata - base); - ret = process_fetch_insn(arg->code, regs, dl, base); + ret = process_fetch_insn(arg->code, rec, dl, base); if (unlikely(ret < 0 && arg->dynamic)) { *dl = make_data_loc(0, dyndata - base); } else { diff --git a/kernel/trace/trace_uprobe.c b/kernel/trace/trace_uprobe.c index 9900d4e3808cc..f6c47361c154e 100644 --- a/kernel/trace/trace_uprobe.c +++ b/kernel/trace/trace_uprobe.c @@ -217,9 +217,10 @@ static unsigned long translate_user_vaddr(unsigned long file_offset)
/* Note that we don't verify it, since the code does not come from user space */ static int -process_fetch_insn(struct fetch_insn *code, struct pt_regs *regs, void *dest, +process_fetch_insn(struct fetch_insn *code, void *rec, void *dest, void *base) { + struct pt_regs *regs = rec; unsigned long val;
/* 1st stage: get value from context */
From: Masami Hiramatsu (Google) mhiramat@kernel.org
[ Upstream commit e38e2c6a9efc435f9de344b7c91f7697e01b47d5 ]
Fix to update dynamic data counter ('dyndata') and max length ('maxlen') only if the fetcharg uses the dynamic data. Also get out arg->dynamic from unlikely(). This makes dynamic data address wrong if process_fetch_insn() returns error on !arg->dynamic case.
Link: https://lore.kernel.org/all/168908494781.123124.8160245359962103684.stgit@de...
Suggested-by: Steven Rostedt rostedt@goodmis.org Link: https://lore.kernel.org/all/20230710233400.5aaf024e@gandalf.local.home/ Fixes: 9178412ddf5a ("tracing: probeevent: Return consumed bytes of dynamic area") Cc: stable@vger.kernel.org Signed-off-by: Masami Hiramatsu (Google) mhiramat@kernel.org Reviewed-by: Steven Rostedt (Google) rostedt@goodmis.org Signed-off-by: Sasha Levin sashal@kernel.org --- kernel/trace/trace_probe_tmpl.h | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-)
diff --git a/kernel/trace/trace_probe_tmpl.h b/kernel/trace/trace_probe_tmpl.h index bbb479b3ba8fd..cf14a37dff8c8 100644 --- a/kernel/trace/trace_probe_tmpl.h +++ b/kernel/trace/trace_probe_tmpl.h @@ -206,11 +206,13 @@ store_trace_args(void *data, struct trace_probe *tp, void *rec, if (unlikely(arg->dynamic)) *dl = make_data_loc(maxlen, dyndata - base); ret = process_fetch_insn(arg->code, rec, dl, base); - if (unlikely(ret < 0 && arg->dynamic)) { - *dl = make_data_loc(0, dyndata - base); - } else { - dyndata += ret; - maxlen -= ret; + if (arg->dynamic) { + if (unlikely(ret < 0)) { + *dl = make_data_loc(0, dyndata - base); + } else { + dyndata += ret; + maxlen -= ret; + } } } }
From: Ivan Mikhaylov fr0st61te@gmail.com
[ Upstream commit 790071347a0a1a89e618eedcd51c687ea783aeb3 ]
Change ndo_set_mac_address to dev_set_mac_address because dev_set_mac_address provides a way to notify network layer about MAC change. In other case, services may not aware about MAC change and keep using old one which set from network adapter driver.
As example, DHCP client from systemd do not update MAC address without notification from net subsystem which leads to the problem with acquiring the right address from DHCP server.
Fixes: cb10c7c0dfd9e ("net/ncsi: Add NCSI Broadcom OEM command") Cc: stable@vger.kernel.org # v6.0+ 2f38e84 net/ncsi: make one oem_gma function for all mfr id Signed-off-by: Paul Fertser fercerpav@gmail.com Signed-off-by: Ivan Mikhaylov fr0st61te@gmail.com Reviewed-by: Simon Horman simon.horman@corigine.com Signed-off-by: David S. Miller davem@davemloft.net Signed-off-by: Sasha Levin sashal@kernel.org --- net/ncsi/ncsi-rsp.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/net/ncsi/ncsi-rsp.c b/net/ncsi/ncsi-rsp.c index 888ccc2d4e34b..47ffb790ff99f 100644 --- a/net/ncsi/ncsi-rsp.c +++ b/net/ncsi/ncsi-rsp.c @@ -616,7 +616,6 @@ static int ncsi_rsp_handler_oem_mlx_gma(struct ncsi_request *nr) { struct ncsi_dev_priv *ndp = nr->ndp; struct net_device *ndev = ndp->ndev.dev; - const struct net_device_ops *ops = ndev->netdev_ops; struct ncsi_rsp_oem_pkt *rsp; struct sockaddr saddr; int ret = 0; @@ -630,7 +629,9 @@ static int ncsi_rsp_handler_oem_mlx_gma(struct ncsi_request *nr) /* Set the flag for GMA command which should only be called once */ ndp->gma_flag = 1;
- ret = ops->ndo_set_mac_address(ndev, &saddr); + rtnl_lock(); + ret = dev_set_mac_address(ndev, &saddr, NULL); + rtnl_unlock(); if (ret < 0) netdev_warn(ndev, "NCSI: 'Writing mac address to device failed\n");
From: Tang Bin tangbin@cmss.chinamobile.com
[ Upstream commit da98b54d02981de5b07d8044b2a632bf6ba3ac45 ]
The file virtio_mmio.c has defined the function to_virtio_mmio_device, so use it instead of container_of() to simply code.
Signed-off-by: Tang Bin tangbin@cmss.chinamobile.com Link: https://lore.kernel.org/r/20210222055724.220-1-tangbin@cmss.chinamobile.com Signed-off-by: Michael S. Tsirkin mst@redhat.com Stable-dep-of: 55c91fedd03d ("virtio-mmio: don't break lifecycle of vm_dev") Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/virtio/virtio_mmio.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/drivers/virtio/virtio_mmio.c b/drivers/virtio/virtio_mmio.c index e8ef0c66e558f..844b949b45c96 100644 --- a/drivers/virtio/virtio_mmio.c +++ b/drivers/virtio/virtio_mmio.c @@ -571,8 +571,7 @@ static void virtio_mmio_release_dev(struct device *_d) { struct virtio_device *vdev = container_of(_d, struct virtio_device, dev); - struct virtio_mmio_device *vm_dev = - container_of(vdev, struct virtio_mmio_device, vdev); + struct virtio_mmio_device *vm_dev = to_virtio_mmio_device(vdev); struct platform_device *pdev = vm_dev->pdev;
devm_kfree(&pdev->dev, vm_dev);
From: Wolfram Sang wsa+renesas@sang-engineering.com
[ Upstream commit 55c91fedd03d7b9cf0c5199b2eb12b9b8e95281a ]
vm_dev has a separate lifecycle because it has a 'struct device' embedded. Thus, having a release callback for it is correct.
Allocating the vm_dev struct with devres totally breaks this protection, though. Instead of waiting for the vm_dev release callback, the memory is freed when the platform_device is removed. Resulting in a use-after-free when finally the callback is to be called.
To easily see the problem, compile the kernel with CONFIG_DEBUG_KOBJECT_RELEASE and unbind with sysfs.
The fix is easy, don't use devres in this case.
Found during my research about object lifetime problems.
Fixes: 7eb781b1bbb7 ("virtio_mmio: add cleanup for virtio_mmio_probe") Signed-off-by: Wolfram Sang wsa+renesas@sang-engineering.com Message-Id: 20230629120526.7184-1-wsa+renesas@sang-engineering.com Signed-off-by: Michael S. Tsirkin mst@redhat.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/virtio/virtio_mmio.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-)
diff --git a/drivers/virtio/virtio_mmio.c b/drivers/virtio/virtio_mmio.c index 844b949b45c96..136f90dbad831 100644 --- a/drivers/virtio/virtio_mmio.c +++ b/drivers/virtio/virtio_mmio.c @@ -572,9 +572,8 @@ static void virtio_mmio_release_dev(struct device *_d) struct virtio_device *vdev = container_of(_d, struct virtio_device, dev); struct virtio_mmio_device *vm_dev = to_virtio_mmio_device(vdev); - struct platform_device *pdev = vm_dev->pdev;
- devm_kfree(&pdev->dev, vm_dev); + kfree(vm_dev); }
/* Platform device */ @@ -585,7 +584,7 @@ static int virtio_mmio_probe(struct platform_device *pdev) unsigned long magic; int rc;
- vm_dev = devm_kzalloc(&pdev->dev, sizeof(*vm_dev), GFP_KERNEL); + vm_dev = kzalloc(sizeof(*vm_dev), GFP_KERNEL); if (!vm_dev) return -ENOMEM;
From: Chengfeng Ye dg573847474@gmail.com
commit 4caf4cb1eaed469742ef719f2cc024b1ec3fa9e6 upstream.
iproc_i2c_rd_reg() and iproc_i2c_wr_reg() are called from both interrupt context (e.g. bcm_iproc_i2c_isr) and process context (e.g. bcm_iproc_i2c_suspend). Therefore, interrupts should be disabled to avoid potential deadlock. To prevent this scenario, use spin_lock_irqsave().
Fixes: 9a1038728037 ("i2c: iproc: add NIC I2C support") Signed-off-by: Chengfeng Ye dg573847474@gmail.com Acked-by: Ray Jui ray.jui@broadcom.com Reviewed-by: Andi Shyti andi.shyti@kernel.org Signed-off-by: Wolfram Sang wsa@kernel.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/i2c/busses/i2c-bcm-iproc.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-)
--- a/drivers/i2c/busses/i2c-bcm-iproc.c +++ b/drivers/i2c/busses/i2c-bcm-iproc.c @@ -242,13 +242,14 @@ static inline u32 iproc_i2c_rd_reg(struc u32 offset) { u32 val; + unsigned long flags;
if (iproc_i2c->idm_base) { - spin_lock(&iproc_i2c->idm_lock); + spin_lock_irqsave(&iproc_i2c->idm_lock, flags); writel(iproc_i2c->ape_addr_mask, iproc_i2c->idm_base + IDM_CTRL_DIRECT_OFFSET); val = readl(iproc_i2c->base + offset); - spin_unlock(&iproc_i2c->idm_lock); + spin_unlock_irqrestore(&iproc_i2c->idm_lock, flags); } else { val = readl(iproc_i2c->base + offset); } @@ -259,12 +260,14 @@ static inline u32 iproc_i2c_rd_reg(struc static inline void iproc_i2c_wr_reg(struct bcm_iproc_i2c_dev *iproc_i2c, u32 offset, u32 val) { + unsigned long flags; + if (iproc_i2c->idm_base) { - spin_lock(&iproc_i2c->idm_lock); + spin_lock_irqsave(&iproc_i2c->idm_lock, flags); writel(iproc_i2c->ape_addr_mask, iproc_i2c->idm_base + IDM_CTRL_DIRECT_OFFSET); writel(val, iproc_i2c->base + offset); - spin_unlock(&iproc_i2c->idm_lock); + spin_unlock_irqrestore(&iproc_i2c->idm_lock, flags); } else { writel(val, iproc_i2c->base + offset); }
From: Yuanjun Gong ruc_gongyuanjun@163.com
commit 0872b2c0abc0e84ac82472959c8e14e35277549c upstream.
in mmphw_probe(), check the return value of clk_prepare_enable() and return the error code if clk_prepare_enable() returns an unexpected value.
Fixes: d63028c38905 ("video: mmp display controller support") Signed-off-by: Yuanjun Gong ruc_gongyuanjun@163.com Signed-off-by: Helge Deller deller@gmx.de Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/video/fbdev/mmp/hw/mmp_ctrl.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
--- a/drivers/video/fbdev/mmp/hw/mmp_ctrl.c +++ b/drivers/video/fbdev/mmp/hw/mmp_ctrl.c @@ -518,7 +518,9 @@ static int mmphw_probe(struct platform_d ret = -ENOENT; goto failed; } - clk_prepare_enable(ctrl->clk); + ret = clk_prepare_enable(ctrl->clk); + if (ret) + goto failed;
/* init global regs */ ctrl_set_default(ctrl);
From: Nathan Lynch nathanl@linux.ibm.com
commit 4f3175979e62de3b929bfa54a0db4b87d36257a7 upstream.
With hardened usercopy enabled (CONFIG_HARDENED_USERCOPY=y), using the /proc/powerpc/rtas/firmware_update interface to prepare a system firmware update yields a BUG():
kernel BUG at mm/usercopy.c:102! Oops: Exception in kernel mode, sig: 5 [#1] LE PAGE_SIZE=64K MMU=Hash SMP NR_CPUS=2048 NUMA pSeries Modules linked in: CPU: 0 PID: 2232 Comm: dd Not tainted 6.5.0-rc3+ #2 Hardware name: IBM,8408-E8E POWER8E (raw) 0x4b0201 0xf000004 of:IBM,FW860.50 (SV860_146) hv:phyp pSeries NIP: c0000000005991d0 LR: c0000000005991cc CTR: 0000000000000000 REGS: c0000000148c76a0 TRAP: 0700 Not tainted (6.5.0-rc3+) MSR: 8000000000029033 <SF,EE,ME,IR,DR,RI,LE> CR: 24002242 XER: 0000000c CFAR: c0000000001fbd34 IRQMASK: 0 [ ... GPRs omitted ... ] NIP usercopy_abort+0xa0/0xb0 LR usercopy_abort+0x9c/0xb0 Call Trace: usercopy_abort+0x9c/0xb0 (unreliable) __check_heap_object+0x1b4/0x1d0 __check_object_size+0x2d0/0x380 rtas_flash_write+0xe4/0x250 proc_reg_write+0xfc/0x160 vfs_write+0xfc/0x4e0 ksys_write+0x90/0x160 system_call_exception+0x178/0x320 system_call_common+0x160/0x2c4
The blocks of the firmware image are copied directly from user memory to objects allocated from flash_block_cache, so flash_block_cache must be created using kmem_cache_create_usercopy() to mark it safe for user access.
Fixes: 6d07d1cd300f ("usercopy: Restrict non-usercopy caches to size 0") Signed-off-by: Nathan Lynch nathanl@linux.ibm.com Reviewed-by: Kees Cook keescook@chromium.org [mpe: Trim and indent oops] Signed-off-by: Michael Ellerman mpe@ellerman.id.au Link: https://msgid.link/20230810-rtas-flash-vs-hardened-usercopy-v2-1-dcf63793a93... Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- arch/powerpc/kernel/rtas_flash.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
--- a/arch/powerpc/kernel/rtas_flash.c +++ b/arch/powerpc/kernel/rtas_flash.c @@ -710,9 +710,9 @@ static int __init rtas_flash_init(void) if (!rtas_validate_flash_data.buf) return -ENOMEM;
- flash_block_cache = kmem_cache_create("rtas_flash_cache", - RTAS_BLK_SIZE, RTAS_BLK_SIZE, 0, - NULL); + flash_block_cache = kmem_cache_create_usercopy("rtas_flash_cache", + RTAS_BLK_SIZE, RTAS_BLK_SIZE, + 0, 0, RTAS_BLK_SIZE, NULL); if (!flash_block_cache) { printk(KERN_ERR "%s: failed to create block cache\n", __func__);
From: Yi Yang yiyang13@huawei.com
commit 3c4f8333b582487a2d1e02171f1465531cde53e3 upstream.
In commit 9b9c8195f3f0 ("tty: n_gsm: fix UAF in gsm_cleanup_mux"), the UAF problem is not completely fixed. There is a race condition in gsm_cleanup_mux(), which caused this UAF.
The UAF problem is triggered by the following race: task[5046] task[5054] ----------------------- ----------------------- gsm_cleanup_mux(); dlci = gsm->dlci[0]; mutex_lock(&gsm->mutex); gsm_cleanup_mux(); dlci = gsm->dlci[0]; //Didn't take the lock gsm_dlci_release(gsm->dlci[i]); gsm->dlci[i] = NULL; mutex_unlock(&gsm->mutex); mutex_lock(&gsm->mutex); dlci->dead = true; //UAF
Fix it by assigning values after mutex_lock().
Link: https://syzkaller.appspot.com/text?tag=CrashReport&x=176188b5a80000 Cc: stable stable@kernel.org Fixes: 9b9c8195f3f0 ("tty: n_gsm: fix UAF in gsm_cleanup_mux") Fixes: aa371e96f05d ("tty: n_gsm: fix restart handling via CLD command") Signed-off-by: Yi Yang yiyang13@huawei.com Co-developed-by: Qiumiao Zhang zhangqiumiao1@huawei.com Signed-off-by: Qiumiao Zhang zhangqiumiao1@huawei.com Link: https://lore.kernel.org/r/20230811031121.153237-1-yiyang13@huawei.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/tty/n_gsm.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
--- a/drivers/tty/n_gsm.c +++ b/drivers/tty/n_gsm.c @@ -2159,12 +2159,13 @@ static void gsm_error(struct gsm_mux *gs static void gsm_cleanup_mux(struct gsm_mux *gsm, bool disc) { int i; - struct gsm_dlci *dlci = gsm->dlci[0]; + struct gsm_dlci *dlci; struct gsm_msg *txq, *ntxq;
gsm->dead = true; mutex_lock(&gsm->mutex);
+ dlci = gsm->dlci[0]; if (dlci) { if (disc && dlci->state != DLCI_CLOSED) { gsm_dlci_begin_close(dlci);
From: Sherry Sun sherry.sun@nxp.com
commit 282069845af388b08d622ad192b831dcd0549c62 upstream.
Do not read the data register to clear the error flags for lpuart32 platforms, the additional read may cause the receive FIFO underflow since the DMA has already read the data register. Actually all lpuart32 platforms support write 1 to clear those error bits, let's use this method to better clear the error flags.
Fixes: 42b68768e51b ("serial: fsl_lpuart: DMA support for 32-bit variant") Cc: stable stable@kernel.org Signed-off-by: Sherry Sun sherry.sun@nxp.com Link: https://lore.kernel.org/r/20230801022304.24251-1-sherry.sun@nxp.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/tty/serial/fsl_lpuart.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
--- a/drivers/tty/serial/fsl_lpuart.c +++ b/drivers/tty/serial/fsl_lpuart.c @@ -1062,8 +1062,8 @@ static void lpuart_copy_rx_to_tty(struct unsigned long sr = lpuart32_read(&sport->port, UARTSTAT);
if (sr & (UARTSTAT_PE | UARTSTAT_FE)) { - /* Read DR to clear the error flags */ - lpuart32_read(&sport->port, UARTDATA); + /* Clear the error flags */ + lpuart32_write(&sport->port, sr, UARTSTAT);
if (sr & UARTSTAT_PE) sport->port.icount.parity++;
From: xiaoshoukui xiaoshoukui@gmail.com
commit 29eefa6d0d07e185f7bfe9576f91e6dba98189c2 upstream.
Pausing and canceling balance can race to interrupt balance lead to BUG_ON panic in btrfs_cancel_balance. The BUG_ON condition in btrfs_cancel_balance does not take this race scenario into account.
However, the race condition has no other side effects. We can fix that.
Reproducing it with panic trace like this:
kernel BUG at fs/btrfs/volumes.c:4618! RIP: 0010:btrfs_cancel_balance+0x5cf/0x6a0 Call Trace: <TASK> ? do_nanosleep+0x60/0x120 ? hrtimer_nanosleep+0xb7/0x1a0 ? sched_core_clone_cookie+0x70/0x70 btrfs_ioctl_balance_ctl+0x55/0x70 btrfs_ioctl+0xa46/0xd20 __x64_sys_ioctl+0x7d/0xa0 do_syscall_64+0x38/0x80 entry_SYSCALL_64_after_hwframe+0x63/0xcd
Race scenario as follows:
mutex_unlock(&fs_info->balance_mutex);
.......issue pause and cancel req in another thread
ret = __btrfs_balance(fs_info);
mutex_lock(&fs_info->balance_mutex); if (ret == -ECANCELED && atomic_read(&fs_info->balance_pause_req)) { btrfs_info(fs_info, "balance: paused"); btrfs_exclop_balance(fs_info, BTRFS_EXCLOP_BALANCE_PAUSED); }
CC: stable@vger.kernel.org # 4.19+ Signed-off-by: xiaoshoukui xiaoshoukui@ruijie.com.cn 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/volumes.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-)
--- a/fs/btrfs/volumes.c +++ b/fs/btrfs/volumes.c @@ -4460,8 +4460,7 @@ int btrfs_cancel_balance(struct btrfs_fs } }
- BUG_ON(fs_info->balance_ctl || - test_bit(BTRFS_FS_BALANCE_RUNNING, &fs_info->flags)); + ASSERT(!test_bit(BTRFS_FS_BALANCE_RUNNING, &fs_info->flags)); atomic_dec(&fs_info->balance_cancel_req); mutex_unlock(&fs_info->balance_mutex); return 0;
From: Tam Nguyen tamnguyenchi@os.amperecomputing.com
commit 69f035c480d76f12bf061148ccfd578e1099e5fc upstream.
In the I2C_FUNC_SMBUS_BLOCK_DATA case, the invalid length byte value (outside of 1-32) of the SMBus block data response from the Slave device is not correctly handled by the I2C Designware driver.
In case IC_EMPTYFIFO_HOLD_MASTER_EN==1, which cannot be detected from the registers, the Master can be disabled only if the STOP bit is set. Without STOP bit set, the Master remains active, holding the bus until receiving a block data response length. This hangs the bus and is unrecoverable.
Avoid this by issuing another dump read to reach the stop condition when an invalid length byte is received.
Cc: stable@vger.kernel.org Signed-off-by: Tam Nguyen tamnguyenchi@os.amperecomputing.com Acked-by: Jarkko Nikula jarkko.nikula@linux.intel.com Link: https://lore.kernel.org/r/20230726080001.337353-3-tamnguyenchi@os.amperecomp... Reviewed-by: Andi Shyti andi.shyti@kernel.org Signed-off-by: Wolfram Sang wsa@kernel.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/i2c/busses/i2c-designware-master.c | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-)
--- a/drivers/i2c/busses/i2c-designware-master.c +++ b/drivers/i2c/busses/i2c-designware-master.c @@ -432,8 +432,19 @@ i2c_dw_read(struct dw_i2c_dev *dev)
regmap_read(dev->map, DW_IC_DATA_CMD, &tmp); /* Ensure length byte is a valid value */ - if (flags & I2C_M_RECV_LEN && - tmp <= I2C_SMBUS_BLOCK_MAX && tmp > 0) { + if (flags & I2C_M_RECV_LEN) { + /* + * if IC_EMPTYFIFO_HOLD_MASTER_EN is set, which cannot be + * detected from the registers, the controller can be + * disabled if the STOP bit is set. But it is only set + * after receiving block data response length in + * I2C_FUNC_SMBUS_BLOCK_DATA case. That needs to read + * another byte with STOP bit set when the block data + * response length is invalid to complete the transaction. + */ + if (!tmp || tmp > I2C_SMBUS_BLOCK_MAX) + tmp = 1; + len = i2c_dw_recv_len(dev, tmp); } *buf++ = tmp;
From: Lin Ma linma@zju.edu.cn
[ Upstream commit dfa73c17d55b921e1d4e154976de35317e43a93a ]
We found below OOB crash:
[ 44.211730] ================================================================== [ 44.212045] BUG: KASAN: slab-out-of-bounds in memcmp+0x8b/0xb0 [ 44.212045] Read of size 8 at addr ffff88800870f320 by task poc.xfrm/97 [ 44.212045] [ 44.212045] CPU: 0 PID: 97 Comm: poc.xfrm Not tainted 6.4.0-rc7-00072-gdad9774deaf1-dirty #4 [ 44.212045] Call Trace: [ 44.212045] <TASK> [ 44.212045] dump_stack_lvl+0x37/0x50 [ 44.212045] print_report+0xcc/0x620 [ 44.212045] ? __virt_addr_valid+0xf3/0x170 [ 44.212045] ? memcmp+0x8b/0xb0 [ 44.212045] kasan_report+0xb2/0xe0 [ 44.212045] ? memcmp+0x8b/0xb0 [ 44.212045] kasan_check_range+0x39/0x1c0 [ 44.212045] memcmp+0x8b/0xb0 [ 44.212045] xfrm_state_walk+0x21c/0x420 [ 44.212045] ? __pfx_dump_one_state+0x10/0x10 [ 44.212045] xfrm_dump_sa+0x1e2/0x290 [ 44.212045] ? __pfx_xfrm_dump_sa+0x10/0x10 [ 44.212045] ? __kernel_text_address+0xd/0x40 [ 44.212045] ? kasan_unpoison+0x27/0x60 [ 44.212045] ? mutex_lock+0x60/0xe0 [ 44.212045] ? __pfx_mutex_lock+0x10/0x10 [ 44.212045] ? kasan_save_stack+0x22/0x50 [ 44.212045] netlink_dump+0x322/0x6c0 [ 44.212045] ? __pfx_netlink_dump+0x10/0x10 [ 44.212045] ? mutex_unlock+0x7f/0xd0 [ 44.212045] ? __pfx_mutex_unlock+0x10/0x10 [ 44.212045] __netlink_dump_start+0x353/0x430 [ 44.212045] xfrm_user_rcv_msg+0x3a4/0x410 [ 44.212045] ? __pfx__raw_spin_lock_irqsave+0x10/0x10 [ 44.212045] ? __pfx_xfrm_user_rcv_msg+0x10/0x10 [ 44.212045] ? __pfx_xfrm_dump_sa+0x10/0x10 [ 44.212045] ? __pfx_xfrm_dump_sa_done+0x10/0x10 [ 44.212045] ? __stack_depot_save+0x382/0x4e0 [ 44.212045] ? filter_irq_stacks+0x1c/0x70 [ 44.212045] ? kasan_save_stack+0x32/0x50 [ 44.212045] ? kasan_save_stack+0x22/0x50 [ 44.212045] ? kasan_set_track+0x25/0x30 [ 44.212045] ? __kasan_slab_alloc+0x59/0x70 [ 44.212045] ? kmem_cache_alloc_node+0xf7/0x260 [ 44.212045] ? kmalloc_reserve+0xab/0x120 [ 44.212045] ? __alloc_skb+0xcf/0x210 [ 44.212045] ? netlink_sendmsg+0x509/0x700 [ 44.212045] ? sock_sendmsg+0xde/0xe0 [ 44.212045] ? __sys_sendto+0x18d/0x230 [ 44.212045] ? __x64_sys_sendto+0x71/0x90 [ 44.212045] ? do_syscall_64+0x3f/0x90 [ 44.212045] ? entry_SYSCALL_64_after_hwframe+0x72/0xdc [ 44.212045] ? netlink_sendmsg+0x509/0x700 [ 44.212045] ? sock_sendmsg+0xde/0xe0 [ 44.212045] ? __sys_sendto+0x18d/0x230 [ 44.212045] ? __x64_sys_sendto+0x71/0x90 [ 44.212045] ? do_syscall_64+0x3f/0x90 [ 44.212045] ? entry_SYSCALL_64_after_hwframe+0x72/0xdc [ 44.212045] ? kasan_save_stack+0x22/0x50 [ 44.212045] ? kasan_set_track+0x25/0x30 [ 44.212045] ? kasan_save_free_info+0x2e/0x50 [ 44.212045] ? __kasan_slab_free+0x10a/0x190 [ 44.212045] ? kmem_cache_free+0x9c/0x340 [ 44.212045] ? netlink_recvmsg+0x23c/0x660 [ 44.212045] ? sock_recvmsg+0xeb/0xf0 [ 44.212045] ? __sys_recvfrom+0x13c/0x1f0 [ 44.212045] ? __x64_sys_recvfrom+0x71/0x90 [ 44.212045] ? do_syscall_64+0x3f/0x90 [ 44.212045] ? entry_SYSCALL_64_after_hwframe+0x72/0xdc [ 44.212045] ? copyout+0x3e/0x50 [ 44.212045] netlink_rcv_skb+0xd6/0x210 [ 44.212045] ? __pfx_xfrm_user_rcv_msg+0x10/0x10 [ 44.212045] ? __pfx_netlink_rcv_skb+0x10/0x10 [ 44.212045] ? __pfx_sock_has_perm+0x10/0x10 [ 44.212045] ? mutex_lock+0x8d/0xe0 [ 44.212045] ? __pfx_mutex_lock+0x10/0x10 [ 44.212045] xfrm_netlink_rcv+0x44/0x50 [ 44.212045] netlink_unicast+0x36f/0x4c0 [ 44.212045] ? __pfx_netlink_unicast+0x10/0x10 [ 44.212045] ? netlink_recvmsg+0x500/0x660 [ 44.212045] netlink_sendmsg+0x3b7/0x700 [ 44.212045] ? __pfx_netlink_sendmsg+0x10/0x10 [ 44.212045] ? __pfx_netlink_sendmsg+0x10/0x10 [ 44.212045] sock_sendmsg+0xde/0xe0 [ 44.212045] __sys_sendto+0x18d/0x230 [ 44.212045] ? __pfx___sys_sendto+0x10/0x10 [ 44.212045] ? rcu_core+0x44a/0xe10 [ 44.212045] ? __rseq_handle_notify_resume+0x45b/0x740 [ 44.212045] ? _raw_spin_lock_irq+0x81/0xe0 [ 44.212045] ? __pfx___rseq_handle_notify_resume+0x10/0x10 [ 44.212045] ? __pfx_restore_fpregs_from_fpstate+0x10/0x10 [ 44.212045] ? __pfx_blkcg_maybe_throttle_current+0x10/0x10 [ 44.212045] ? __pfx_task_work_run+0x10/0x10 [ 44.212045] __x64_sys_sendto+0x71/0x90 [ 44.212045] do_syscall_64+0x3f/0x90 [ 44.212045] entry_SYSCALL_64_after_hwframe+0x72/0xdc [ 44.212045] RIP: 0033:0x44b7da [ 44.212045] RSP: 002b:00007ffdc8838548 EFLAGS: 00000246 ORIG_RAX: 000000000000002c [ 44.212045] RAX: ffffffffffffffda RBX: 00007ffdc8839978 RCX: 000000000044b7da [ 44.212045] RDX: 0000000000000038 RSI: 00007ffdc8838770 RDI: 0000000000000003 [ 44.212045] RBP: 00007ffdc88385b0 R08: 00007ffdc883858c R09: 000000000000000c [ 44.212045] R10: 0000000000000000 R11: 0000000000000246 R12: 0000000000000001 [ 44.212045] R13: 00007ffdc8839968 R14: 00000000004c37d0 R15: 0000000000000001 [ 44.212045] </TASK> [ 44.212045] [ 44.212045] Allocated by task 97: [ 44.212045] kasan_save_stack+0x22/0x50 [ 44.212045] kasan_set_track+0x25/0x30 [ 44.212045] __kasan_kmalloc+0x7f/0x90 [ 44.212045] __kmalloc_node_track_caller+0x5b/0x140 [ 44.212045] kmemdup+0x21/0x50 [ 44.212045] xfrm_dump_sa+0x17d/0x290 [ 44.212045] netlink_dump+0x322/0x6c0 [ 44.212045] __netlink_dump_start+0x353/0x430 [ 44.212045] xfrm_user_rcv_msg+0x3a4/0x410 [ 44.212045] netlink_rcv_skb+0xd6/0x210 [ 44.212045] xfrm_netlink_rcv+0x44/0x50 [ 44.212045] netlink_unicast+0x36f/0x4c0 [ 44.212045] netlink_sendmsg+0x3b7/0x700 [ 44.212045] sock_sendmsg+0xde/0xe0 [ 44.212045] __sys_sendto+0x18d/0x230 [ 44.212045] __x64_sys_sendto+0x71/0x90 [ 44.212045] do_syscall_64+0x3f/0x90 [ 44.212045] entry_SYSCALL_64_after_hwframe+0x72/0xdc [ 44.212045] [ 44.212045] The buggy address belongs to the object at ffff88800870f300 [ 44.212045] which belongs to the cache kmalloc-64 of size 64 [ 44.212045] The buggy address is located 32 bytes inside of [ 44.212045] allocated 36-byte region [ffff88800870f300, ffff88800870f324) [ 44.212045] [ 44.212045] The buggy address belongs to the physical page: [ 44.212045] page:00000000e4de16ee refcount:1 mapcount:0 mapping:000000000 ... [ 44.212045] flags: 0x100000000000200(slab|node=0|zone=1) [ 44.212045] page_type: 0xffffffff() [ 44.212045] raw: 0100000000000200 ffff888004c41640 dead000000000122 0000000000000000 [ 44.212045] raw: 0000000000000000 0000000080200020 00000001ffffffff 0000000000000000 [ 44.212045] page dumped because: kasan: bad access detected [ 44.212045] [ 44.212045] Memory state around the buggy address: [ 44.212045] ffff88800870f200: fa fb fb fb fb fb fb fb fc fc fc fc fc fc fc fc [ 44.212045] ffff88800870f280: 00 00 00 00 00 fc fc fc fc fc fc fc fc fc fc fc [ 44.212045] >ffff88800870f300: 00 00 00 00 04 fc fc fc fc fc fc fc fc fc fc fc [ 44.212045] ^ [ 44.212045] ffff88800870f380: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc [ 44.212045] ffff88800870f400: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc [ 44.212045] ==================================================================
By investigating the code, we find the root cause of this OOB is the lack of checks in xfrm_dump_sa(). The buggy code allows a malicious user to pass arbitrary value of filter->splen/dplen. Hence, with crafted xfrm states, the attacker can achieve 8 bytes heap OOB read, which causes info leak.
if (attrs[XFRMA_ADDRESS_FILTER]) { filter = kmemdup(nla_data(attrs[XFRMA_ADDRESS_FILTER]), sizeof(*filter), GFP_KERNEL); if (filter == NULL) return -ENOMEM; // NO MORE CHECKS HERE !!! }
This patch fixes the OOB by adding necessary boundary checks, just like the code in pfkey_dump() function.
Fixes: d3623099d350 ("ipsec: add support of limited SA dump") Signed-off-by: Lin Ma linma@zju.edu.cn Signed-off-by: Steffen Klassert steffen.klassert@secunet.com Signed-off-by: Sasha Levin sashal@kernel.org --- net/xfrm/xfrm_user.c | 9 +++++++++ 1 file changed, 9 insertions(+)
diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c index c6bf3898d1bf0..025401bfa3e1e 100644 --- a/net/xfrm/xfrm_user.c +++ b/net/xfrm/xfrm_user.c @@ -1062,6 +1062,15 @@ static int xfrm_dump_sa(struct sk_buff *skb, struct netlink_callback *cb) sizeof(*filter), GFP_KERNEL); if (filter == NULL) return -ENOMEM; + + /* see addr_match(), (prefix length >> 5) << 2 + * will be used to compare xfrm_address_t + */ + if (filter->splen > (sizeof(xfrm_address_t) << 3) || + filter->dplen > (sizeof(xfrm_address_t) << 3)) { + kfree(filter); + return -EINVAL; + } }
if (attrs[XFRMA_PROTO])
From: Lin Ma linma@zju.edu.cn
[ Upstream commit 75065a8929069bc93181848818e23f147a73f83a ]
When running xfrm_state_walk_init(), the xfrm_address_filter being used is okay to have a splen/dplen that equals to sizeof(xfrm_address_t)<<3. This commit replaces >= to > to make sure the boundary checking is correct.
Fixes: 37bd22420f85 ("af_key: pfkey_dump needs parameter validation") Signed-off-by: Lin Ma linma@zju.edu.cn Signed-off-by: Steffen Klassert steffen.klassert@secunet.com Signed-off-by: Sasha Levin sashal@kernel.org --- net/key/af_key.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/net/key/af_key.c b/net/key/af_key.c index fff2bd5f03e37..f42854973ba8d 100644 --- a/net/key/af_key.c +++ b/net/key/af_key.c @@ -1852,9 +1852,9 @@ static int pfkey_dump(struct sock *sk, struct sk_buff *skb, const struct sadb_ms if (ext_hdrs[SADB_X_EXT_FILTER - 1]) { struct sadb_x_filter *xfilter = ext_hdrs[SADB_X_EXT_FILTER - 1];
- if ((xfilter->sadb_x_filter_splen >= + if ((xfilter->sadb_x_filter_splen > (sizeof(xfrm_address_t) << 3)) || - (xfilter->sadb_x_filter_dplen >= + (xfilter->sadb_x_filter_dplen > (sizeof(xfrm_address_t) << 3))) { mutex_unlock(&pfk->dump_lock); return -EINVAL;
From: Lin Ma linma@zju.edu.cn
[ Upstream commit d1e0e61d617ba17aa516db707aa871387566bbf7 ]
According to all consumers code of attrs[XFRMA_SEC_CTX], like
* verify_sec_ctx_len(), convert to xfrm_user_sec_ctx* * xfrm_state_construct(), call security_xfrm_state_alloc whose prototype is int security_xfrm_state_alloc(.., struct xfrm_user_sec_ctx *sec_ctx); * copy_from_user_sec_ctx(), convert to xfrm_user_sec_ctx * ...
It seems that the expected parsing result for XFRMA_SEC_CTX should be structure xfrm_user_sec_ctx, and the current xfrm_sec_ctx is confusing and misleading (Luckily, they happen to have same size 8 bytes).
This commit amend the policy structure to xfrm_user_sec_ctx to avoid ambiguity.
Fixes: cf5cb79f6946 ("[XFRM] netlink: Establish an attribute policy") Signed-off-by: Lin Ma linma@zju.edu.cn Signed-off-by: Steffen Klassert steffen.klassert@secunet.com Signed-off-by: Sasha Levin sashal@kernel.org --- net/xfrm/xfrm_compat.c | 2 +- net/xfrm/xfrm_user.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/net/xfrm/xfrm_compat.c b/net/xfrm/xfrm_compat.c index 8cbf45a8bcdc2..655fe4ff86212 100644 --- a/net/xfrm/xfrm_compat.c +++ b/net/xfrm/xfrm_compat.c @@ -108,7 +108,7 @@ static const struct nla_policy compat_policy[XFRMA_MAX+1] = { [XFRMA_ALG_COMP] = { .len = sizeof(struct xfrm_algo) }, [XFRMA_ENCAP] = { .len = sizeof(struct xfrm_encap_tmpl) }, [XFRMA_TMPL] = { .len = sizeof(struct xfrm_user_tmpl) }, - [XFRMA_SEC_CTX] = { .len = sizeof(struct xfrm_sec_ctx) }, + [XFRMA_SEC_CTX] = { .len = sizeof(struct xfrm_user_sec_ctx) }, [XFRMA_LTIME_VAL] = { .len = sizeof(struct xfrm_lifetime_cur) }, [XFRMA_REPLAY_VAL] = { .len = sizeof(struct xfrm_replay_state) }, [XFRMA_REPLAY_THRESH] = { .type = NLA_U32 }, diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c index 025401bfa3e1e..0de7d0cf7be0f 100644 --- a/net/xfrm/xfrm_user.c +++ b/net/xfrm/xfrm_user.c @@ -2737,7 +2737,7 @@ const struct nla_policy xfrma_policy[XFRMA_MAX+1] = { [XFRMA_ALG_COMP] = { .len = sizeof(struct xfrm_algo) }, [XFRMA_ENCAP] = { .len = sizeof(struct xfrm_encap_tmpl) }, [XFRMA_TMPL] = { .len = sizeof(struct xfrm_user_tmpl) }, - [XFRMA_SEC_CTX] = { .len = sizeof(struct xfrm_sec_ctx) }, + [XFRMA_SEC_CTX] = { .len = sizeof(struct xfrm_user_sec_ctx) }, [XFRMA_LTIME_VAL] = { .len = sizeof(struct xfrm_lifetime_cur) }, [XFRMA_REPLAY_VAL] = { .len = sizeof(struct xfrm_replay_state) }, [XFRMA_REPLAY_THRESH] = { .type = NLA_U32 },
From: Zhengchao Shao shaozhengchao@huawei.com
[ Upstream commit 53223f2ed1ef5c90dad814daaaefea4e68a933c8 ]
When the xfrm device is set to the qdisc of the sfb type, the cb field of the sent skb may be modified during enqueuing. Then, slab-use-after-free may occur when the xfrm device sends IPv6 packets.
The stack information is as follows: BUG: KASAN: slab-use-after-free in decode_session6+0x103f/0x1890 Read of size 1 at addr ffff8881111458ef by task swapper/3/0 CPU: 3 PID: 0 Comm: swapper/3 Not tainted 6.4.0-next-20230707 #409 Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.14.0-1.fc33 04/01/2014 Call Trace: <IRQ> dump_stack_lvl+0xd9/0x150 print_address_description.constprop.0+0x2c/0x3c0 kasan_report+0x11d/0x130 decode_session6+0x103f/0x1890 __xfrm_decode_session+0x54/0xb0 xfrmi_xmit+0x173/0x1ca0 dev_hard_start_xmit+0x187/0x700 sch_direct_xmit+0x1a3/0xc30 __qdisc_run+0x510/0x17a0 __dev_queue_xmit+0x2215/0x3b10 neigh_connected_output+0x3c2/0x550 ip6_finish_output2+0x55a/0x1550 ip6_finish_output+0x6b9/0x1270 ip6_output+0x1f1/0x540 ndisc_send_skb+0xa63/0x1890 ndisc_send_rs+0x132/0x6f0 addrconf_rs_timer+0x3f1/0x870 call_timer_fn+0x1a0/0x580 expire_timers+0x29b/0x4b0 run_timer_softirq+0x326/0x910 __do_softirq+0x1d4/0x905 irq_exit_rcu+0xb7/0x120 sysvec_apic_timer_interrupt+0x97/0xc0 </IRQ> <TASK> asm_sysvec_apic_timer_interrupt+0x1a/0x20 RIP: 0010:intel_idle_hlt+0x23/0x30 Code: 1f 84 00 00 00 00 00 f3 0f 1e fa 41 54 41 89 d4 0f 1f 44 00 00 66 90 0f 1f 44 00 00 0f 00 2d c4 9f ab 00 0f 1f 44 00 00 fb f4 <fa> 44 89 e0 41 5c c3 66 0f 1f 44 00 00 f3 0f 1e fa 41 54 41 89 d4 RSP: 0018:ffffc90000197d78 EFLAGS: 00000246 RAX: 00000000000a83c3 RBX: ffffe8ffffd09c50 RCX: ffffffff8a22d8e5 RDX: 0000000000000001 RSI: ffffffff8d3f8080 RDI: ffffe8ffffd09c50 RBP: ffffffff8d3f8080 R08: 0000000000000001 R09: ffffed1026ba6d9d R10: ffff888135d36ceb R11: 0000000000000001 R12: 0000000000000001 R13: ffffffff8d3f8100 R14: 0000000000000001 R15: 0000000000000000 cpuidle_enter_state+0xd3/0x6f0 cpuidle_enter+0x4e/0xa0 do_idle+0x2fe/0x3c0 cpu_startup_entry+0x18/0x20 start_secondary+0x200/0x290 secondary_startup_64_no_verify+0x167/0x16b </TASK> Allocated by task 939: kasan_save_stack+0x22/0x40 kasan_set_track+0x25/0x30 __kasan_slab_alloc+0x7f/0x90 kmem_cache_alloc_node+0x1cd/0x410 kmalloc_reserve+0x165/0x270 __alloc_skb+0x129/0x330 inet6_ifa_notify+0x118/0x230 __ipv6_ifa_notify+0x177/0xbe0 addrconf_dad_completed+0x133/0xe00 addrconf_dad_work+0x764/0x1390 process_one_work+0xa32/0x16f0 worker_thread+0x67d/0x10c0 kthread+0x344/0x440 ret_from_fork+0x1f/0x30 The buggy address belongs to the object at ffff888111145800 which belongs to the cache skbuff_small_head of size 640 The buggy address is located 239 bytes inside of freed 640-byte region [ffff888111145800, ffff888111145a80)
As commit f855691975bb ("xfrm6: Fix the nexthdr offset in _decode_session6.") showed, xfrm_decode_session was originally intended only for the receive path. IP6CB(skb)->nhoff is not set during transmission. Therefore, set the cb field in the skb to 0 before sending packets.
Fixes: f855691975bb ("xfrm6: Fix the nexthdr offset in _decode_session6.") Signed-off-by: Zhengchao Shao shaozhengchao@huawei.com Signed-off-by: Steffen Klassert steffen.klassert@secunet.com Signed-off-by: Sasha Levin sashal@kernel.org --- net/xfrm/xfrm_interface_core.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/net/xfrm/xfrm_interface_core.c b/net/xfrm/xfrm_interface_core.c index e4f21a6924153..4eeec33675754 100644 --- a/net/xfrm/xfrm_interface_core.c +++ b/net/xfrm/xfrm_interface_core.c @@ -403,8 +403,8 @@ static netdev_tx_t xfrmi_xmit(struct sk_buff *skb, struct net_device *dev)
switch (skb->protocol) { case htons(ETH_P_IPV6): - xfrm_decode_session(skb, &fl, AF_INET6); memset(IP6CB(skb), 0, sizeof(*IP6CB(skb))); + xfrm_decode_session(skb, &fl, AF_INET6); if (!dst) { fl.u.ip6.flowi6_oif = dev->ifindex; fl.u.ip6.flowi6_flags |= FLOWI_FLAG_ANYSRC; @@ -418,8 +418,8 @@ static netdev_tx_t xfrmi_xmit(struct sk_buff *skb, struct net_device *dev) } break; case htons(ETH_P_IP): - xfrm_decode_session(skb, &fl, AF_INET); memset(IPCB(skb), 0, sizeof(*IPCB(skb))); + xfrm_decode_session(skb, &fl, AF_INET); if (!dst) { struct rtable *rt;
From: Zhengchao Shao shaozhengchao@huawei.com
[ Upstream commit 9fd41f1ba638938c9a1195d09bc6fa3be2712f25 ]
When ipv6_vti device is set to the qdisc of the sfb type, the cb field of the sent skb may be modified during enqueuing. Then, slab-use-after-free may occur when ipv6_vti device sends IPv6 packets.
The stack information is as follows: BUG: KASAN: slab-use-after-free in decode_session6+0x103f/0x1890 Read of size 1 at addr ffff88802e08edc2 by task swapper/0/0 CPU: 0 PID: 0 Comm: swapper/0 Not tainted 6.4.0-next-20230707-00001-g84e2cad7f979 #410 Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.14.0-1.fc33 04/01/2014 Call Trace: <IRQ> dump_stack_lvl+0xd9/0x150 print_address_description.constprop.0+0x2c/0x3c0 kasan_report+0x11d/0x130 decode_session6+0x103f/0x1890 __xfrm_decode_session+0x54/0xb0 vti6_tnl_xmit+0x3e6/0x1ee0 dev_hard_start_xmit+0x187/0x700 sch_direct_xmit+0x1a3/0xc30 __qdisc_run+0x510/0x17a0 __dev_queue_xmit+0x2215/0x3b10 neigh_connected_output+0x3c2/0x550 ip6_finish_output2+0x55a/0x1550 ip6_finish_output+0x6b9/0x1270 ip6_output+0x1f1/0x540 ndisc_send_skb+0xa63/0x1890 ndisc_send_rs+0x132/0x6f0 addrconf_rs_timer+0x3f1/0x870 call_timer_fn+0x1a0/0x580 expire_timers+0x29b/0x4b0 run_timer_softirq+0x326/0x910 __do_softirq+0x1d4/0x905 irq_exit_rcu+0xb7/0x120 sysvec_apic_timer_interrupt+0x97/0xc0 </IRQ> Allocated by task 9176: kasan_save_stack+0x22/0x40 kasan_set_track+0x25/0x30 __kasan_slab_alloc+0x7f/0x90 kmem_cache_alloc_node+0x1cd/0x410 kmalloc_reserve+0x165/0x270 __alloc_skb+0x129/0x330 netlink_sendmsg+0x9b1/0xe30 sock_sendmsg+0xde/0x190 ____sys_sendmsg+0x739/0x920 ___sys_sendmsg+0x110/0x1b0 __sys_sendmsg+0xf7/0x1c0 do_syscall_64+0x39/0xb0 entry_SYSCALL_64_after_hwframe+0x63/0xcd Freed by task 9176: kasan_save_stack+0x22/0x40 kasan_set_track+0x25/0x30 kasan_save_free_info+0x2b/0x40 ____kasan_slab_free+0x160/0x1c0 slab_free_freelist_hook+0x11b/0x220 kmem_cache_free+0xf0/0x490 skb_free_head+0x17f/0x1b0 skb_release_data+0x59c/0x850 consume_skb+0xd2/0x170 netlink_unicast+0x54f/0x7f0 netlink_sendmsg+0x926/0xe30 sock_sendmsg+0xde/0x190 ____sys_sendmsg+0x739/0x920 ___sys_sendmsg+0x110/0x1b0 __sys_sendmsg+0xf7/0x1c0 do_syscall_64+0x39/0xb0 entry_SYSCALL_64_after_hwframe+0x63/0xcd The buggy address belongs to the object at ffff88802e08ed00 which belongs to the cache skbuff_small_head of size 640 The buggy address is located 194 bytes inside of freed 640-byte region [ffff88802e08ed00, ffff88802e08ef80)
As commit f855691975bb ("xfrm6: Fix the nexthdr offset in _decode_session6.") showed, xfrm_decode_session was originally intended only for the receive path. IP6CB(skb)->nhoff is not set during transmission. Therefore, set the cb field in the skb to 0 before sending packets.
Fixes: f855691975bb ("xfrm6: Fix the nexthdr offset in _decode_session6.") Signed-off-by: Zhengchao Shao shaozhengchao@huawei.com Signed-off-by: Steffen Klassert steffen.klassert@secunet.com Signed-off-by: Sasha Levin sashal@kernel.org --- net/ipv6/ip6_vti.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/net/ipv6/ip6_vti.c b/net/ipv6/ip6_vti.c index 99f2dc802e366..162ba065d4764 100644 --- a/net/ipv6/ip6_vti.c +++ b/net/ipv6/ip6_vti.c @@ -567,12 +567,12 @@ vti6_tnl_xmit(struct sk_buff *skb, struct net_device *dev) vti6_addr_conflict(t, ipv6_hdr(skb))) goto tx_err;
- xfrm_decode_session(skb, &fl, AF_INET6); memset(IP6CB(skb), 0, sizeof(*IP6CB(skb))); + xfrm_decode_session(skb, &fl, AF_INET6); break; case htons(ETH_P_IP): - xfrm_decode_session(skb, &fl, AF_INET); memset(IPCB(skb), 0, sizeof(*IPCB(skb))); + xfrm_decode_session(skb, &fl, AF_INET); break; default: goto tx_err;
From: Zhengchao Shao shaozhengchao@huawei.com
[ Upstream commit 6018a266279b1a75143c7c0804dd08a5fc4c3e0b ]
When ip_vti device is set to the qdisc of the sfb type, the cb field of the sent skb may be modified during enqueuing. Then, slab-use-after-free may occur when ip_vti device sends IPv6 packets. As commit f855691975bb ("xfrm6: Fix the nexthdr offset in _decode_session6.") showed, xfrm_decode_session was originally intended only for the receive path. IP6CB(skb)->nhoff is not set during transmission. Therefore, set the cb field in the skb to 0 before sending packets.
Fixes: f855691975bb ("xfrm6: Fix the nexthdr offset in _decode_session6.") Signed-off-by: Zhengchao Shao shaozhengchao@huawei.com Signed-off-by: Steffen Klassert steffen.klassert@secunet.com Signed-off-by: Sasha Levin sashal@kernel.org --- net/ipv4/ip_vti.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/net/ipv4/ip_vti.c b/net/ipv4/ip_vti.c index 84a818b09beeb..90f349be4848d 100644 --- a/net/ipv4/ip_vti.c +++ b/net/ipv4/ip_vti.c @@ -285,12 +285,12 @@ static netdev_tx_t vti_tunnel_xmit(struct sk_buff *skb, struct net_device *dev)
switch (skb->protocol) { case htons(ETH_P_IP): - xfrm_decode_session(skb, &fl, AF_INET); memset(IPCB(skb), 0, sizeof(*IPCB(skb))); + xfrm_decode_session(skb, &fl, AF_INET); break; case htons(ETH_P_IPV6): - xfrm_decode_session(skb, &fl, AF_INET6); memset(IP6CB(skb), 0, sizeof(*IP6CB(skb))); + xfrm_decode_session(skb, &fl, AF_INET6); break; default: goto tx_err;
From: Lin Ma linma@zju.edu.cn
[ Upstream commit 00374d9b6d9f932802b55181be9831aa948e5b7c ]
Normally, x->replay_esn and x->preplay_esn should be allocated at xfrm_alloc_replay_state_esn(...) in xfrm_state_construct(...), hence the xfrm_update_ae_params(...) is okay to update them. However, the current implementation of xfrm_new_ae(...) allows a malicious user to directly dereference a NULL pointer and crash the kernel like below.
BUG: kernel NULL pointer dereference, address: 0000000000000000 PGD 8253067 P4D 8253067 PUD 8e0e067 PMD 0 Oops: 0002 [#1] PREEMPT SMP KASAN NOPTI CPU: 0 PID: 98 Comm: poc.npd Not tainted 6.4.0-rc7-00072-gdad9774deaf1 #8 Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS rel-1.16.0-0-gd239552ce722-prebuilt.qemu.o4 RIP: 0010:memcpy_orig+0xad/0x140 Code: e8 4c 89 5f e0 48 8d 7f e0 73 d2 83 c2 20 48 29 d6 48 29 d7 83 fa 10 72 34 4c 8b 06 4c 8b 4e 08 c RSP: 0018:ffff888008f57658 EFLAGS: 00000202 RAX: 0000000000000000 RBX: ffff888008bd0000 RCX: ffffffff8238e571 RDX: 0000000000000018 RSI: ffff888007f64844 RDI: 0000000000000000 RBP: 0000000000000000 R08: 0000000000000000 R09: 0000000000000000 R10: 0000000000000000 R11: 0000000000000000 R12: ffff888008f57818 R13: ffff888007f64aa4 R14: 0000000000000000 R15: 0000000000000000 FS: 00000000014013c0(0000) GS:ffff88806d600000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: 0000000000000000 CR3: 00000000054d8000 CR4: 00000000000006f0 Call Trace: <TASK> ? __die+0x1f/0x70 ? page_fault_oops+0x1e8/0x500 ? __pfx_is_prefetch.constprop.0+0x10/0x10 ? __pfx_page_fault_oops+0x10/0x10 ? _raw_spin_unlock_irqrestore+0x11/0x40 ? fixup_exception+0x36/0x460 ? _raw_spin_unlock_irqrestore+0x11/0x40 ? exc_page_fault+0x5e/0xc0 ? asm_exc_page_fault+0x26/0x30 ? xfrm_update_ae_params+0xd1/0x260 ? memcpy_orig+0xad/0x140 ? __pfx__raw_spin_lock_bh+0x10/0x10 xfrm_update_ae_params+0xe7/0x260 xfrm_new_ae+0x298/0x4e0 ? __pfx_xfrm_new_ae+0x10/0x10 ? __pfx_xfrm_new_ae+0x10/0x10 xfrm_user_rcv_msg+0x25a/0x410 ? __pfx_xfrm_user_rcv_msg+0x10/0x10 ? __alloc_skb+0xcf/0x210 ? stack_trace_save+0x90/0xd0 ? filter_irq_stacks+0x1c/0x70 ? __stack_depot_save+0x39/0x4e0 ? __kasan_slab_free+0x10a/0x190 ? kmem_cache_free+0x9c/0x340 ? netlink_recvmsg+0x23c/0x660 ? sock_recvmsg+0xeb/0xf0 ? __sys_recvfrom+0x13c/0x1f0 ? __x64_sys_recvfrom+0x71/0x90 ? do_syscall_64+0x3f/0x90 ? entry_SYSCALL_64_after_hwframe+0x72/0xdc ? copyout+0x3e/0x50 netlink_rcv_skb+0xd6/0x210 ? __pfx_xfrm_user_rcv_msg+0x10/0x10 ? __pfx_netlink_rcv_skb+0x10/0x10 ? __pfx_sock_has_perm+0x10/0x10 ? mutex_lock+0x8d/0xe0 ? __pfx_mutex_lock+0x10/0x10 xfrm_netlink_rcv+0x44/0x50 netlink_unicast+0x36f/0x4c0 ? __pfx_netlink_unicast+0x10/0x10 ? netlink_recvmsg+0x500/0x660 netlink_sendmsg+0x3b7/0x700
This Null-ptr-deref bug is assigned CVE-2023-3772. And this commit adds additional NULL check in xfrm_update_ae_params to fix the NPD.
Fixes: d8647b79c3b7 ("xfrm: Add user interface for esn and big anti-replay windows") Signed-off-by: Lin Ma linma@zju.edu.cn Reviewed-by: Leon Romanovsky leonro@nvidia.com Signed-off-by: Steffen Klassert steffen.klassert@secunet.com Signed-off-by: Sasha Levin sashal@kernel.org --- net/xfrm/xfrm_user.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c index 0de7d0cf7be0f..d093b4d684a61 100644 --- a/net/xfrm/xfrm_user.c +++ b/net/xfrm/xfrm_user.c @@ -527,7 +527,7 @@ static void xfrm_update_ae_params(struct xfrm_state *x, struct nlattr **attrs, struct nlattr *rt = attrs[XFRMA_REPLAY_THRESH]; struct nlattr *mt = attrs[XFRMA_MTIMER_THRESH];
- if (re) { + if (re && x->replay_esn && x->preplay_esn) { struct xfrm_replay_state_esn *replay_esn; replay_esn = nla_data(re); memcpy(x->replay_esn, replay_esn,
From: Lin Ma linma@zju.edu.cn
[ Upstream commit 5e2424708da7207087934c5c75211e8584d553a0 ]
The previous commit 4e484b3e969b ("xfrm: rate limit SA mapping change message to user space") added one additional attribute named XFRMA_MTIMER_THRESH and described its type at compat_policy (net/xfrm/xfrm_compat.c).
However, the author forgot to also describe the nla_policy at xfrma_policy (net/xfrm/xfrm_user.c). Hence, this suppose NLA_U32 (4 bytes) value can be faked as empty (0 bytes) by a malicious user, which leads to 4 bytes overflow read and heap information leak when parsing nlattrs.
To exploit this, one malicious user can spray the SLUB objects and then leverage this 4 bytes OOB read to leak the heap data into x->mapping_maxage (see xfrm_update_ae_params(...)), and leak it to userspace via copy_to_user_state_extra(...).
The above bug is assigned CVE-2023-3773. To fix it, this commit just completes the nla_policy description for XFRMA_MTIMER_THRESH, which enforces the length check and avoids such OOB read.
Fixes: 4e484b3e969b ("xfrm: rate limit SA mapping change message to user space") Signed-off-by: Lin Ma linma@zju.edu.cn Reviewed-by: Simon Horman simon.horman@corigine.com Reviewed-by: Leon Romanovsky leonro@nvidia.com Signed-off-by: Steffen Klassert steffen.klassert@secunet.com Signed-off-by: Sasha Levin sashal@kernel.org --- net/xfrm/xfrm_user.c | 1 + 1 file changed, 1 insertion(+)
diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c index d093b4d684a61..8fce2e93bb3b3 100644 --- a/net/xfrm/xfrm_user.c +++ b/net/xfrm/xfrm_user.c @@ -2757,6 +2757,7 @@ const struct nla_policy xfrma_policy[XFRMA_MAX+1] = { [XFRMA_SET_MARK] = { .type = NLA_U32 }, [XFRMA_SET_MARK_MASK] = { .type = NLA_U32 }, [XFRMA_IF_ID] = { .type = NLA_U32 }, + [XFRMA_MTIMER_THRESH] = { .type = NLA_U32 }, }; EXPORT_SYMBOL_GPL(xfrma_policy);
From: Petr Machata petrm@nvidia.com
[ Upstream commit 855067defa36b1f9effad8c219d9a85b655cf500 ]
This test verifies whether the encapsulated packets have the correct configured TTL. It does so by sending ICMP packets through the test topology and mirroring them to a gretap netdevice. On a busy host however, more than just the test ICMP packets may end up flowing through the topology, get mirrored, and counted. This leads to potential spurious failures as the test observes much more mirrored packets than the sent test packets, and assumes a bug.
Fix this by tightening up the mirror action match. Change it from matchall to a flower classifier matching on ICMP packets specifically.
Fixes: 45315673e0c5 ("selftests: forwarding: Test changes in mirror-to-gretap") Signed-off-by: Petr Machata petrm@nvidia.com Tested-by: Mirsad Todorovac mirsad.todorovac@alu.unizg.hr Reviewed-by: Ido Schimmel idosch@nvidia.com Reviewed-by: Simon Horman horms@kernel.org Signed-off-by: David S. Miller davem@davemloft.net Signed-off-by: Sasha Levin sashal@kernel.org --- tools/testing/selftests/net/forwarding/mirror_gre_changes.sh | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/tools/testing/selftests/net/forwarding/mirror_gre_changes.sh b/tools/testing/selftests/net/forwarding/mirror_gre_changes.sh index 472bd023e2a5f..b501b366367f7 100755 --- a/tools/testing/selftests/net/forwarding/mirror_gre_changes.sh +++ b/tools/testing/selftests/net/forwarding/mirror_gre_changes.sh @@ -72,7 +72,8 @@ test_span_gre_ttl()
RET=0
- mirror_install $swp1 ingress $tundev "matchall $tcflags" + mirror_install $swp1 ingress $tundev \ + "prot ip flower $tcflags ip_prot icmp" tc filter add dev $h3 ingress pref 77 prot $prot \ flower ip_ttl 50 action pass
From: Luca Ceresoli luca.ceresoli@bootlin.com
[ Upstream commit e8470c0a7bcaa82f78ad34282d662dd7bd9630c2 ]
Commit 03e909acd95a ("drm/panel: simple: Add support for AUO G121EAN01.4 panel") added support for this panel model, but the timings it implements are very different from what the datasheet describes. I checked both the G121EAN01.0 datasheet from [0] and the G121EAN01.4 one from [1] and they all have the same timings: for example the LVDS clock typical value is 74.4 MHz, not 66.7 MHz as implemented.
Replace the timings with the ones from the documentation. These timings have been tested and the clock frequencies verified with an oscilloscope to ensure they are correct.
Also use struct display_timing instead of struct drm_display_mode in order to also specify the minimum and maximum values.
[0] https://embedded.avnet.com/product/g121ean01-0/ [1] https://embedded.avnet.com/product/g121ean01-4/
Fixes: 03e909acd95a ("drm/panel: simple: Add support for AUO G121EAN01.4 panel") Signed-off-by: Luca Ceresoli luca.ceresoli@bootlin.com Reviewed-by: Neil Armstrong neil.armstrong@linaro.org Signed-off-by: Neil Armstrong neil.armstrong@linaro.org Link: https://patchwork.freedesktop.org/patch/msgid/20230804151239.835216-1-luca.c... Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/gpu/drm/panel/panel-simple.c | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-)
diff --git a/drivers/gpu/drm/panel/panel-simple.c b/drivers/gpu/drm/panel/panel-simple.c index 7b69f81444ebd..e40321d798981 100644 --- a/drivers/gpu/drm/panel/panel-simple.c +++ b/drivers/gpu/drm/panel/panel-simple.c @@ -1010,21 +1010,21 @@ static const struct panel_desc auo_g104sn02 = { }, };
-static const struct drm_display_mode auo_g121ean01_mode = { - .clock = 66700, - .hdisplay = 1280, - .hsync_start = 1280 + 58, - .hsync_end = 1280 + 58 + 8, - .htotal = 1280 + 58 + 8 + 70, - .vdisplay = 800, - .vsync_start = 800 + 6, - .vsync_end = 800 + 6 + 4, - .vtotal = 800 + 6 + 4 + 10, +static const struct display_timing auo_g121ean01_timing = { + .pixelclock = { 60000000, 74400000, 90000000 }, + .hactive = { 1280, 1280, 1280 }, + .hfront_porch = { 20, 50, 100 }, + .hback_porch = { 20, 50, 100 }, + .hsync_len = { 30, 100, 200 }, + .vactive = { 800, 800, 800 }, + .vfront_porch = { 2, 10, 25 }, + .vback_porch = { 2, 10, 25 }, + .vsync_len = { 4, 18, 50 }, };
static const struct panel_desc auo_g121ean01 = { - .modes = &auo_g121ean01_mode, - .num_modes = 1, + .timings = &auo_g121ean01_timing, + .num_timings = 1, .bpc = 8, .size = { .width = 261,
From: Sishuai Gong sishuai.system@gmail.com
[ Upstream commit 5310760af1d4fbea1452bfc77db5f9a680f7ae47 ]
When two threads run proc_do_sync_threshold() in parallel, data races could happen between the two memcpy():
Thread-1 Thread-2 memcpy(val, valp, sizeof(val)); memcpy(valp, val, sizeof(val));
This race might mess up the (struct ctl_table *) table->data, so we add a mutex lock to serialize them.
Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") Link: https://lore.kernel.org/netdev/B6988E90-0A1E-4B85-BF26-2DAF6D482433@gmail.co... Signed-off-by: Sishuai Gong sishuai.system@gmail.com Acked-by: Simon Horman horms@kernel.org Acked-by: Julian Anastasov ja@ssi.bg Signed-off-by: Florian Westphal fw@strlen.de Signed-off-by: Sasha Levin sashal@kernel.org --- net/netfilter/ipvs/ip_vs_ctl.c | 4 ++++ 1 file changed, 4 insertions(+)
diff --git a/net/netfilter/ipvs/ip_vs_ctl.c b/net/netfilter/ipvs/ip_vs_ctl.c index 29ec3ef63edc7..d0b64c36471d5 100644 --- a/net/netfilter/ipvs/ip_vs_ctl.c +++ b/net/netfilter/ipvs/ip_vs_ctl.c @@ -1802,6 +1802,7 @@ static int proc_do_sync_threshold(struct ctl_table *table, int write, void *buffer, size_t *lenp, loff_t *ppos) { + struct netns_ipvs *ipvs = table->extra2; int *valp = table->data; int val[2]; int rc; @@ -1811,6 +1812,7 @@ proc_do_sync_threshold(struct ctl_table *table, int write, .mode = table->mode, };
+ mutex_lock(&ipvs->sync_mutex); memcpy(val, valp, sizeof(val)); rc = proc_dointvec(&tmp, write, buffer, lenp, ppos); if (write) { @@ -1820,6 +1822,7 @@ proc_do_sync_threshold(struct ctl_table *table, int write, else memcpy(valp, val, sizeof(val)); } + mutex_unlock(&ipvs->sync_mutex); return rc; }
@@ -4077,6 +4080,7 @@ static int __net_init ip_vs_control_net_init_sysctl(struct netns_ipvs *ipvs) ipvs->sysctl_sync_threshold[0] = DEFAULT_SYNC_THRESHOLD; ipvs->sysctl_sync_threshold[1] = DEFAULT_SYNC_PERIOD; tbl[idx].data = &ipvs->sysctl_sync_threshold; + tbl[idx].extra2 = ipvs; tbl[idx++].maxlen = sizeof(ipvs->sysctl_sync_threshold); ipvs->sysctl_sync_refresh_period = DEFAULT_SYNC_REFRESH_PERIOD; tbl[idx++].data = &ipvs->sysctl_sync_refresh_period;
From: Pablo Neira Ayuso pablo@netfilter.org
[ Upstream commit 23185c6aed1ffb8fc44087880ba2767aba493779 ]
Do not allow to insert elements from datapath to objects maps.
Fixes: 8aeff920dcc9 ("netfilter: nf_tables: add stateful object reference to set elements") Signed-off-by: Pablo Neira Ayuso pablo@netfilter.org Signed-off-by: Florian Westphal fw@strlen.de Signed-off-by: Sasha Levin sashal@kernel.org --- net/netfilter/nft_dynset.c | 3 +++ 1 file changed, 3 insertions(+)
diff --git a/net/netfilter/nft_dynset.c b/net/netfilter/nft_dynset.c index 8d47782b778f1..408b7f5faa5e5 100644 --- a/net/netfilter/nft_dynset.c +++ b/net/netfilter/nft_dynset.c @@ -138,6 +138,9 @@ static int nft_dynset_init(const struct nft_ctx *ctx, if (IS_ERR(set)) return PTR_ERR(set);
+ if (set->flags & NFT_SET_OBJECT) + return -EOPNOTSUPP; + if (set->ops->update == NULL) return -EOPNOTSUPP;
From: Justin Chen justin.chen@broadcom.com
[ Upstream commit 096516d092d54604d590827d05b1022c8f326639 ]
The 54810 does not support c45. The mmd_phy_indirect accesses return arbirtary values leading to odd behavior like saying it supports EEE when it doesn't. We also see that reading/writing these non-existent MMD registers leads to phy instability in some cases.
Fixes: b14995ac2527 ("net: phy: broadcom: Add BCM54810 PHY entry") Signed-off-by: Justin Chen justin.chen@broadcom.com Reviewed-by: Florian Fainelli florian.fainelli@broadcom.com Link: https://lore.kernel.org/r/1691901708-28650-1-git-send-email-justin.chen@broa... Signed-off-by: Jakub Kicinski kuba@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/net/phy/broadcom.c | 13 +++++++++++++ 1 file changed, 13 insertions(+)
diff --git a/drivers/net/phy/broadcom.c b/drivers/net/phy/broadcom.c index 0cde17bd743f3..a664faa8f01f6 100644 --- a/drivers/net/phy/broadcom.c +++ b/drivers/net/phy/broadcom.c @@ -404,6 +404,17 @@ static int bcm54xx_resume(struct phy_device *phydev) return bcm54xx_config_init(phydev); }
+static int bcm54810_read_mmd(struct phy_device *phydev, int devnum, u16 regnum) +{ + return -EOPNOTSUPP; +} + +static int bcm54810_write_mmd(struct phy_device *phydev, int devnum, u16 regnum, + u16 val) +{ + return -EOPNOTSUPP; +} + static int bcm54811_config_init(struct phy_device *phydev) { int err, reg; @@ -841,6 +852,8 @@ static struct phy_driver broadcom_drivers[] = { .phy_id_mask = 0xfffffff0, .name = "Broadcom BCM54810", /* PHY_GBIT_FEATURES */ + .read_mmd = bcm54810_read_mmd, + .write_mmd = bcm54810_write_mmd, .config_init = bcm54xx_config_init, .config_aneg = bcm5481_config_aneg, .ack_interrupt = bcm_phy_ack_intr,
From: Ziyang Xuan william.xuanziyang@huawei.com
[ Upstream commit dafcbce07136d799edc4c67f04f9fd69ff1eac1f ]
Similar to commit 01f4fd270870 ("bonding: Fix incorrect deletion of ETH_P_8021AD protocol vid from slaves"), we can trigger BUG_ON(!vlan_info) in unregister_vlan_dev() with the following testcase:
# ip netns add ns1 # ip netns exec ns1 ip link add team1 type team # ip netns exec ns1 ip link add team_slave type veth peer veth2 # ip netns exec ns1 ip link set team_slave master team1 # ip netns exec ns1 ip link add link team_slave name team_slave.10 type vlan id 10 protocol 802.1ad # ip netns exec ns1 ip link add link team1 name team1.10 type vlan id 10 protocol 802.1ad # ip netns exec ns1 ip link set team_slave nomaster # ip netns del ns1
Add S-VLAN tag related features support to team driver. So the team driver will always propagate the VLAN info to its slaves.
Fixes: 8ad227ff89a7 ("net: vlan: add 802.1ad support") Suggested-by: Ido Schimmel idosch@idosch.org Signed-off-by: Ziyang Xuan william.xuanziyang@huawei.com Reviewed-by: Simon Horman horms@kernel.org Link: https://lore.kernel.org/r/20230814032301.2804971-1-william.xuanziyang@huawei... Signed-off-by: Jakub Kicinski kuba@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/net/team/team.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/drivers/net/team/team.c b/drivers/net/team/team.c index 36c7eae776d44..721b536ce8861 100644 --- a/drivers/net/team/team.c +++ b/drivers/net/team/team.c @@ -2195,7 +2195,9 @@ static void team_setup(struct net_device *dev)
dev->hw_features = TEAM_VLAN_FEATURES | NETIF_F_HW_VLAN_CTAG_RX | - NETIF_F_HW_VLAN_CTAG_FILTER; + NETIF_F_HW_VLAN_CTAG_FILTER | + NETIF_F_HW_VLAN_STAG_RX | + NETIF_F_HW_VLAN_STAG_FILTER;
dev->hw_features |= NETIF_F_GSO_ENCAP_ALL | NETIF_F_GSO_UDP_L4; dev->features |= dev->hw_features;
From: Andrii Staikov andrii.staikov@intel.com
[ Upstream commit 2f2beb8874cb0844e84ad26e990f05f4f13ff63f ]
Change "write" into the actual "read" word. Change parameters description.
Fixes: 7073f46e443e ("i40e: Add AQ commands for NVM Update for X722") Signed-off-by: Aleksandr Loktionov aleksandr.loktionov@intel.com Signed-off-by: Andrii Staikov andrii.staikov@intel.com Signed-off-by: Tony Nguyen anthony.l.nguyen@intel.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/net/ethernet/intel/i40e/i40e_nvm.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-)
diff --git a/drivers/net/ethernet/intel/i40e/i40e_nvm.c b/drivers/net/ethernet/intel/i40e/i40e_nvm.c index 7164f4ad81202..6b1996451a4bd 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_nvm.c +++ b/drivers/net/ethernet/intel/i40e/i40e_nvm.c @@ -210,11 +210,11 @@ static i40e_status i40e_read_nvm_word_srctl(struct i40e_hw *hw, u16 offset, * @hw: pointer to the HW structure. * @module_pointer: module pointer location in words from the NVM beginning * @offset: offset in words from module start - * @words: number of words to write - * @data: buffer with words to write to the Shadow RAM + * @words: number of words to read + * @data: buffer with words to read to the Shadow RAM * @last_command: tells the AdminQ that this is the last command * - * Writes a 16 bit words buffer to the Shadow RAM using the admin command. + * Reads a 16 bit words buffer to the Shadow RAM using the admin command. **/ static i40e_status i40e_read_nvm_aq(struct i40e_hw *hw, u8 module_pointer, u32 offset, @@ -234,18 +234,18 @@ static i40e_status i40e_read_nvm_aq(struct i40e_hw *hw, */ if ((offset + words) > hw->nvm.sr_size) i40e_debug(hw, I40E_DEBUG_NVM, - "NVM write error: offset %d beyond Shadow RAM limit %d\n", + "NVM read error: offset %d beyond Shadow RAM limit %d\n", (offset + words), hw->nvm.sr_size); else if (words > I40E_SR_SECTOR_SIZE_IN_WORDS) - /* We can write only up to 4KB (one sector), in one AQ write */ + /* We can read only up to 4KB (one sector), in one AQ write */ i40e_debug(hw, I40E_DEBUG_NVM, - "NVM write fail error: tried to write %d words, limit is %d.\n", + "NVM read fail error: tried to read %d words, limit is %d.\n", words, I40E_SR_SECTOR_SIZE_IN_WORDS); else if (((offset + (words - 1)) / I40E_SR_SECTOR_SIZE_IN_WORDS) != (offset / I40E_SR_SECTOR_SIZE_IN_WORDS)) - /* A single write cannot spread over two sectors */ + /* A single read cannot spread over two sectors */ i40e_debug(hw, I40E_DEBUG_NVM, - "NVM write error: cannot spread over two sectors in a single write offset=%d words=%d\n", + "NVM read error: cannot spread over two sectors in a single read offset=%d words=%d\n", offset, words); else ret_code = i40e_aq_read_nvm(hw, module_pointer,
From: Alfred Lee l00g33k@gmail.com
[ Upstream commit 23d775f12dcd23d052a4927195f15e970e27ab26 ]
If the switch is reset during active EEPROM transactions, as in just after an SoC reset after power up, the I2C bus transaction may be cut short leaving the EEPROM internal I2C state machine in the wrong state. When the switch is reset again, the bad state machine state may result in data being read from the wrong memory location causing the switch to enter unexpected mode rendering it inoperational.
Fixes: a3dcb3e7e70c ("net: dsa: mv88e6xxx: Wait for EEPROM done after HW reset") Signed-off-by: Alfred Lee l00g33k@gmail.com Reviewed-by: Andrew Lunn andrew@lunn.ch Link: https://lore.kernel.org/r/20230815001323.24739-1-l00g33k@gmail.com Signed-off-by: Jakub Kicinski kuba@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/net/dsa/mv88e6xxx/chip.c | 8 ++++++++ 1 file changed, 8 insertions(+)
diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c index 8b2c8546f4c99..177151298d72a 100644 --- a/drivers/net/dsa/mv88e6xxx/chip.c +++ b/drivers/net/dsa/mv88e6xxx/chip.c @@ -2310,6 +2310,14 @@ static void mv88e6xxx_hardware_reset(struct mv88e6xxx_chip *chip)
/* If there is a GPIO connected to the reset pin, toggle it */ if (gpiod) { + /* If the switch has just been reset and not yet completed + * loading EEPROM, the reset may interrupt the I2C transaction + * mid-byte, causing the first EEPROM read after the reset + * from the wrong location resulting in the switch booting + * to wrong mode and inoperable. + */ + mv88e6xxx_g1_wait_eeprom_done(chip); + gpiod_set_value_cansleep(gpiod, 1); usleep_range(10000, 20000); gpiod_set_value_cansleep(gpiod, 0);
From: Abel Wu wuyun.abel@bytedance.com
[ Upstream commit 2d0c88e84e483982067a82073f6125490ddf3614 ]
The status of global socket memory pressure is updated when:
a) __sk_mem_raise_allocated():
enter: sk_memory_allocated(sk) > sysctl_mem[1] leave: sk_memory_allocated(sk) <= sysctl_mem[0]
b) __sk_mem_reduce_allocated():
leave: sk_under_memory_pressure(sk) && sk_memory_allocated(sk) < sysctl_mem[0]
So the conditions of leaving global pressure are inconstant, which may lead to the situation that one pressured net-memcg prevents the global pressure from being cleared when there is indeed no global pressure, thus the global constrains are still in effect unexpectedly on the other sockets.
This patch fixes this by ignoring the net-memcg's pressure when deciding whether should leave global memory pressure.
Fixes: e1aab161e013 ("socket: initial cgroup code.") Signed-off-by: Abel Wu wuyun.abel@bytedance.com Acked-by: Shakeel Butt shakeelb@google.com Link: https://lore.kernel.org/r/20230816091226.1542-1-wuyun.abel@bytedance.com Signed-off-by: Jakub Kicinski kuba@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- include/net/sock.h | 6 ++++++ net/core/sock.c | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-)
diff --git a/include/net/sock.h b/include/net/sock.h index 1fb5c535537c1..665e388593752 100644 --- a/include/net/sock.h +++ b/include/net/sock.h @@ -1346,6 +1346,12 @@ static inline bool sk_has_memory_pressure(const struct sock *sk) return sk->sk_prot->memory_pressure != NULL; }
+static inline bool sk_under_global_memory_pressure(const struct sock *sk) +{ + return sk->sk_prot->memory_pressure && + !!*sk->sk_prot->memory_pressure; +} + static inline bool sk_under_memory_pressure(const struct sock *sk) { if (!sk->sk_prot->memory_pressure) diff --git a/net/core/sock.c b/net/core/sock.c index 98f4b4a80de42..742356cfd07c4 100644 --- a/net/core/sock.c +++ b/net/core/sock.c @@ -2724,7 +2724,7 @@ void __sk_mem_reduce_allocated(struct sock *sk, int amount) if (mem_cgroup_sockets_enabled && sk->sk_memcg) mem_cgroup_uncharge_skmem(sk->sk_memcg, amount);
- if (sk_under_memory_pressure(sk) && + if (sk_under_global_memory_pressure(sk) && (sk_memory_allocated(sk) < sk_prot_mem_limits(sk, 0))) sk_leave_memory_pressure(sk); }
From: Eric Dumazet edumazet@google.com
[ Upstream commit b616be6b97688f2f2bd7c4a47ab32f27f94fb2a9 ]
One missing check in virtio_net_hdr_to_skb() allowed syzbot to crash kernels again [1]
Do not allow gso_size to be set to GSO_BY_FRAGS (0xffff), because this magic value is used by the kernel.
[1] general protection fault, probably for non-canonical address 0xdffffc000000000e: 0000 [#1] PREEMPT SMP KASAN KASAN: null-ptr-deref in range [0x0000000000000070-0x0000000000000077] CPU: 0 PID: 5039 Comm: syz-executor401 Not tainted 6.5.0-rc5-next-20230809-syzkaller #0 Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 07/26/2023 RIP: 0010:skb_segment+0x1a52/0x3ef0 net/core/skbuff.c:4500 Code: 00 00 00 e9 ab eb ff ff e8 6b 96 5d f9 48 8b 84 24 00 01 00 00 48 8d 78 70 48 b8 00 00 00 00 00 fc ff df 48 89 fa 48 c1 ea 03 <0f> b6 04 02 84 c0 74 08 3c 03 0f 8e ea 21 00 00 48 8b 84 24 00 01 RSP: 0018:ffffc90003d3f1c8 EFLAGS: 00010202 RAX: dffffc0000000000 RBX: 000000000001fffe RCX: 0000000000000000 RDX: 000000000000000e RSI: ffffffff882a3115 RDI: 0000000000000070 RBP: ffffc90003d3f378 R08: 0000000000000005 R09: 000000000000ffff R10: 000000000000ffff R11: 5ee4a93e456187d6 R12: 000000000001ffc6 R13: dffffc0000000000 R14: 0000000000000008 R15: 000000000000ffff FS: 00005555563f2380(0000) GS:ffff8880b9800000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: 0000000020020000 CR3: 000000001626d000 CR4: 00000000003506f0 DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400 Call Trace: <TASK> udp6_ufo_fragment+0x9d2/0xd50 net/ipv6/udp_offload.c:109 ipv6_gso_segment+0x5c4/0x17b0 net/ipv6/ip6_offload.c:120 skb_mac_gso_segment+0x292/0x610 net/core/gso.c:53 __skb_gso_segment+0x339/0x710 net/core/gso.c:124 skb_gso_segment include/net/gso.h:83 [inline] validate_xmit_skb+0x3a5/0xf10 net/core/dev.c:3625 __dev_queue_xmit+0x8f0/0x3d60 net/core/dev.c:4329 dev_queue_xmit include/linux/netdevice.h:3082 [inline] packet_xmit+0x257/0x380 net/packet/af_packet.c:276 packet_snd net/packet/af_packet.c:3087 [inline] packet_sendmsg+0x24c7/0x5570 net/packet/af_packet.c:3119 sock_sendmsg_nosec net/socket.c:727 [inline] sock_sendmsg+0xd9/0x180 net/socket.c:750 ____sys_sendmsg+0x6ac/0x940 net/socket.c:2496 ___sys_sendmsg+0x135/0x1d0 net/socket.c:2550 __sys_sendmsg+0x117/0x1e0 net/socket.c:2579 do_syscall_x64 arch/x86/entry/common.c:50 [inline] do_syscall_64+0x38/0xb0 arch/x86/entry/common.c:80 entry_SYSCALL_64_after_hwframe+0x63/0xcd RIP: 0033:0x7ff27cdb34d9
Fixes: 3953c46c3ac7 ("sk_buff: allow segmenting based on frag sizes") Reported-by: syzbot syzkaller@googlegroups.com Signed-off-by: Eric Dumazet edumazet@google.com Cc: Xin Long lucien.xin@gmail.com Cc: "Michael S. Tsirkin" mst@redhat.com Cc: Jason Wang jasowang@redhat.com Reviewed-by: Willem de Bruijn willemb@google.com Reviewed-by: Marcelo Ricardo Leitner marcelo.leitner@gmail.com Reviewed-by: Xuan Zhuo xuanzhuo@linux.alibaba.com Link: https://lore.kernel.org/r/20230816142158.1779798-1-edumazet@google.com Signed-off-by: Jakub Kicinski kuba@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- include/linux/virtio_net.h | 4 ++++ 1 file changed, 4 insertions(+)
diff --git a/include/linux/virtio_net.h b/include/linux/virtio_net.h index a960de68ac69e..6047058d67037 100644 --- a/include/linux/virtio_net.h +++ b/include/linux/virtio_net.h @@ -148,6 +148,10 @@ static inline int virtio_net_hdr_to_skb(struct sk_buff *skb, if (gso_type & SKB_GSO_UDP) nh_off -= thlen;
+ /* Kernel has a special handling for GSO_BY_FRAGS. */ + if (gso_size == GSO_BY_FRAGS) + return -EINVAL; + /* Too small packets are not really GSO ones. */ if (skb->len - nh_off > gso_size) { shinfo->gso_size = gso_size;
From: Tony Lindgren tony@atomide.com
[ Upstream commit 34539b442b3bc7d5bf10164750302b60b91f18a7 ]
The am335x devices started producing boot errors for resetting musb module in because of subtle timing changes:
Unhandled fault: external abort on non-linefetch (0x1008) ... sysc_poll_reset_sysconfig from sysc_reset+0x109/0x12 sysc_reset from sysc_probe+0xa99/0xeb0 ...
The fix is to flush posted write after enable before reset during probe. Note that some devices also need to specify the delay after enable with ti,sysc-delay-us, but this is not needed for musb on am335x based on my tests.
Reported-by: kernelci.org bot bot@kernelci.org Closes: https://storage.kernelci.org/next/master/next-20230614/arm/multi_v7_defconfi... Fixes: 596e7955692b ("bus: ti-sysc: Add support for software reset") Signed-off-by: Tony Lindgren tony@atomide.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/bus/ti-sysc.c | 2 ++ 1 file changed, 2 insertions(+)
diff --git a/drivers/bus/ti-sysc.c b/drivers/bus/ti-sysc.c index 4b1641fe30dba..fcfe4d16cc149 100644 --- a/drivers/bus/ti-sysc.c +++ b/drivers/bus/ti-sysc.c @@ -2078,6 +2078,8 @@ static int sysc_reset(struct sysc *ddata) sysc_val = sysc_read_sysconfig(ddata); sysc_val |= sysc_mask; sysc_write(ddata, sysc_offset, sysc_val); + /* Flush posted write */ + sysc_val = sysc_read_sysconfig(ddata); }
if (ddata->cfg.srst_udelay)
From: Vicente Bergas vicencb@gmail.com
[ Upstream commit 328c6112787bf7562dbea638840366cd197868d6 ]
Based on the board schematics at https://dl.radxa.com/rockpi4/docs/hw/rockpi4/rockpi_4c_v12_sch_20200620.pdf on page 18: vcc_lan is not controllable by software, it is just an analog LC filter. Because of this, it can not be turned off-in-suspend.
and on page 17: vcc_cam and vcc_mipi are not voltage regulators, they are just switches. So, the voltage range is not applicable. This silences an error message about not being able to adjust the voltage.
Signed-off-by: Vicente Bergas vicencb@gmail.com Link: https://lore.kernel.org/r/20201201154132.1286-2-vicencb@gmail.com Signed-off-by: Heiko Stuebner heiko@sntech.de Stable-dep-of: cee572756aa2 ("arm64: dts: rockchip: Disable HS400 for eMMC on ROCK Pi 4") Signed-off-by: Sasha Levin sashal@kernel.org --- arch/arm64/boot/dts/rockchip/rk3399-rock-pi-4.dtsi | 8 -------- 1 file changed, 8 deletions(-)
diff --git a/arch/arm64/boot/dts/rockchip/rk3399-rock-pi-4.dtsi b/arch/arm64/boot/dts/rockchip/rk3399-rock-pi-4.dtsi index 64df643391194..98f52fac13535 100644 --- a/arch/arm64/boot/dts/rockchip/rk3399-rock-pi-4.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3399-rock-pi-4.dtsi @@ -111,10 +111,6 @@ regulator-boot-on; regulator-min-microvolt = <3300000>; regulator-max-microvolt = <3300000>; - - regulator-state-mem { - regulator-off-in-suspend; - }; };
vdd_log: vdd-log { @@ -362,8 +358,6 @@ regulator-name = "vcc_cam"; regulator-always-on; regulator-boot-on; - regulator-min-microvolt = <3300000>; - regulator-max-microvolt = <3300000>; regulator-state-mem { regulator-off-in-suspend; }; @@ -373,8 +367,6 @@ regulator-name = "vcc_mipi"; regulator-always-on; regulator-boot-on; - regulator-min-microvolt = <3300000>; - regulator-max-microvolt = <3300000>; regulator-state-mem { regulator-off-in-suspend; };
From: Vicente Bergas vicencb@gmail.com
[ Upstream commit e12f67fe83446432ef16704c22ec23bd1dbcd094 ]
Based on the board schematics at https://dl.radxa.com/rockpi4/docs/hw/rockpi4/rockpi_4c_v12_sch_20200620.pdf on page 19 there is an USB Type-A receptacle being used as an USB-OTG port.
But the Type-A connector is not valid for OTG operation, for this reason there is a switch to select host or device role. This is non-compliant and error prone because switching is manual. So, use host mode as it corresponds for a Type-A receptacle.
Signed-off-by: Vicente Bergas vicencb@gmail.com Link: https://lore.kernel.org/r/20201201154132.1286-4-vicencb@gmail.com Signed-off-by: Heiko Stuebner heiko@sntech.de Stable-dep-of: cee572756aa2 ("arm64: dts: rockchip: Disable HS400 for eMMC on ROCK Pi 4") Signed-off-by: Sasha Levin sashal@kernel.org --- arch/arm64/boot/dts/rockchip/rk3399-rock-pi-4.dtsi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/arch/arm64/boot/dts/rockchip/rk3399-rock-pi-4.dtsi b/arch/arm64/boot/dts/rockchip/rk3399-rock-pi-4.dtsi index 98f52fac13535..6dc6dee6c13e2 100644 --- a/arch/arm64/boot/dts/rockchip/rk3399-rock-pi-4.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3399-rock-pi-4.dtsi @@ -671,7 +671,7 @@
&usbdrd_dwc3_0 { status = "okay"; - dr_mode = "otg"; + dr_mode = "host"; };
&usbdrd3_1 {
From: Alex Bee knaerzche@gmail.com
[ Upstream commit 65bd2b8bdb3bddc37bea695789713916327e1c1f ]
ROCK Pi 4 boards have the codec connected to i2s0 and it is accessible via i2c1 address 0x11. Add an audio-graph-card for it.
Signed-off-by: Alex Bee knaerzche@gmail.com Link: https://lore.kernel.org/r/20210618181256.27992-5-knaerzche@gmail.com Signed-off-by: Heiko Stuebner heiko@sntech.de Stable-dep-of: cee572756aa2 ("arm64: dts: rockchip: Disable HS400 for eMMC on ROCK Pi 4") Signed-off-by: Sasha Levin sashal@kernel.org --- .../boot/dts/rockchip/rk3399-rock-pi-4.dtsi | 28 +++++++++++++++++++ 1 file changed, 28 insertions(+)
diff --git a/arch/arm64/boot/dts/rockchip/rk3399-rock-pi-4.dtsi b/arch/arm64/boot/dts/rockchip/rk3399-rock-pi-4.dtsi index 6dc6dee6c13e2..f80cdb021f7fc 100644 --- a/arch/arm64/boot/dts/rockchip/rk3399-rock-pi-4.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3399-rock-pi-4.dtsi @@ -31,6 +31,12 @@ reset-gpios = <&gpio0 RK_PB2 GPIO_ACTIVE_LOW>; };
+ sound { + compatible = "audio-graph-card"; + label = "Analog"; + dais = <&i2s0_p0>; + }; + vcc12v_dcin: dc-12v { compatible = "regulator-fixed"; regulator-name = "vcc12v_dcin"; @@ -417,6 +423,20 @@ i2c-scl-rising-time-ns = <300>; i2c-scl-falling-time-ns = <15>; status = "okay"; + + es8316: codec@11 { + compatible = "everest,es8316"; + reg = <0x11>; + clocks = <&cru SCLK_I2S_8CH_OUT>; + clock-names = "mclk"; + #sound-dai-cells = <0>; + + port { + es8316_p0_0: endpoint { + remote-endpoint = <&i2s0_p0_0>; + }; + }; + }; };
&i2c3 { @@ -435,6 +455,14 @@ rockchip,playback-channels = <8>; rockchip,capture-channels = <8>; status = "okay"; + + i2s0_p0: port { + i2s0_p0_0: endpoint { + dai-format = "i2s"; + mclk-fs = <256>; + remote-endpoint = <&es8316_p0_0>; + }; + }; };
&i2s1 {
From: Alex Bee knaerzche@gmail.com
[ Upstream commit 697dd494cb1cf56acfb764214a1e4788e4d1a983 ]
Add a SPDIF audio-graph-card to ROCK Pi 4 device tree.
It's not enabled by default since all dma channels are used by the (already) enabled i2s0/1/2 and the pin is muxed with GPIO4_C5 which might be in use already. If enabled SPDIF_TX will be available at pin #15.
Signed-off-by: Alex Bee knaerzche@gmail.com Link: https://lore.kernel.org/r/20210618181256.27992-6-knaerzche@gmail.com Signed-off-by: Heiko Stuebner heiko@sntech.de Stable-dep-of: cee572756aa2 ("arm64: dts: rockchip: Disable HS400 for eMMC on ROCK Pi 4") Signed-off-by: Sasha Levin sashal@kernel.org --- .../boot/dts/rockchip/rk3399-rock-pi-4.dtsi | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+)
diff --git a/arch/arm64/boot/dts/rockchip/rk3399-rock-pi-4.dtsi b/arch/arm64/boot/dts/rockchip/rk3399-rock-pi-4.dtsi index f80cdb021f7fc..fcd8eeabf53b6 100644 --- a/arch/arm64/boot/dts/rockchip/rk3399-rock-pi-4.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3399-rock-pi-4.dtsi @@ -37,6 +37,23 @@ dais = <&i2s0_p0>; };
+ sound-dit { + compatible = "audio-graph-card"; + label = "SPDIF"; + dais = <&spdif_p0>; + }; + + spdif-dit { + compatible = "linux,spdif-dit"; + #sound-dai-cells = <0>; + + port { + dit_p0_0: endpoint { + remote-endpoint = <&spdif_p0_0>; + }; + }; + }; + vcc12v_dcin: dc-12v { compatible = "regulator-fixed"; regulator-name = "vcc12v_dcin"; @@ -625,6 +642,15 @@ status = "okay"; };
+&spdif { + + spdif_p0: port { + spdif_p0_0: endpoint { + remote-endpoint = <&dit_p0_0>; + }; + }; +}; + &tcphy0 { status = "okay"; };
From: FUKAUMI Naoki naoki@radxa.com
[ Upstream commit 69448624b770aa88a71536a16900dd3cc6002919 ]
fix regulator name
ref: https://dl.radxa.com/rockpi4/docs/hw/rockpi4/rockpi4_v13_sch_20181112.pdf
Signed-off-by: FUKAUMI Naoki naoki@radxa.com Link: https://lore.kernel.org/r/20220909195006.127957-4-naoki@radxa.com Signed-off-by: Heiko Stuebner heiko@sntech.de Stable-dep-of: cee572756aa2 ("arm64: dts: rockchip: Disable HS400 for eMMC on ROCK Pi 4") Signed-off-by: Sasha Levin sashal@kernel.org --- .../boot/dts/rockchip/rk3399-rock-pi-4.dtsi | 25 ++++++++++--------- 1 file changed, 13 insertions(+), 12 deletions(-)
diff --git a/arch/arm64/boot/dts/rockchip/rk3399-rock-pi-4.dtsi b/arch/arm64/boot/dts/rockchip/rk3399-rock-pi-4.dtsi index fcd8eeabf53b6..4e1c1f970aba1 100644 --- a/arch/arm64/boot/dts/rockchip/rk3399-rock-pi-4.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3399-rock-pi-4.dtsi @@ -116,24 +116,25 @@ vin-supply = <&vcc5v0_sys>; };
- vcc5v0_typec: vcc5v0-typec-regulator { + vbus_typec: vbus-typec-regulator { compatible = "regulator-fixed"; enable-active-high; gpio = <&gpio1 RK_PA3 GPIO_ACTIVE_HIGH>; pinctrl-names = "default"; pinctrl-0 = <&vcc5v0_typec_en>; - regulator-name = "vcc5v0_typec"; + regulator-name = "vbus_typec"; regulator-always-on; vin-supply = <&vcc5v0_sys>; };
- vcc_lan: vcc3v3-phy-regulator { + vcc3v3_lan: vcc3v3-lan-regulator { compatible = "regulator-fixed"; - regulator-name = "vcc_lan"; + regulator-name = "vcc3v3_lan"; regulator-always-on; regulator-boot-on; regulator-min-microvolt = <3300000>; regulator-max-microvolt = <3300000>; + vin-supply = <&vcc3v3_sys>; };
vdd_log: vdd-log { @@ -180,7 +181,7 @@ assigned-clocks = <&cru SCLK_RMII_SRC>; assigned-clock-parents = <&clkin_gmac>; clock_in_out = "input"; - phy-supply = <&vcc_lan>; + phy-supply = <&vcc3v3_lan>; phy-mode = "rgmii"; pinctrl-names = "default"; pinctrl-0 = <&rgmii_pins>; @@ -285,8 +286,8 @@ }; };
- vcc1v8_codec: LDO_REG1 { - regulator-name = "vcc1v8_codec"; + vcca1v8_codec: LDO_REG1 { + regulator-name = "vcca1v8_codec"; regulator-always-on; regulator-boot-on; regulator-min-microvolt = <1800000>; @@ -296,8 +297,8 @@ }; };
- vcc1v8_hdmi: LDO_REG2 { - regulator-name = "vcc1v8_hdmi"; + vcca1v8_hdmi: LDO_REG2 { + regulator-name = "vcca1v8_hdmi"; regulator-always-on; regulator-boot-on; regulator-min-microvolt = <1800000>; @@ -354,8 +355,8 @@ }; };
- vcc0v9_hdmi: LDO_REG7 { - regulator-name = "vcc0v9_hdmi"; + vcca0v9_hdmi: LDO_REG7 { + regulator-name = "vcca0v9_hdmi"; regulator-always-on; regulator-boot-on; regulator-min-microvolt = <900000>; @@ -495,7 +496,7 @@ status = "okay";
bt656-supply = <&vcc_3v0>; - audio-supply = <&vcc1v8_codec>; + audio-supply = <&vcca1v8_codec>; sdmmc-supply = <&vcc_sdio>; gpio1830-supply = <&vcc_3v0>; };
From: FUKAUMI Naoki naoki@radxa.com
[ Upstream commit 06c5b5690a578514b3fe8f11a47a3c37d3af3696 ]
sort nodes/properties alphabetically
Signed-off-by: FUKAUMI Naoki naoki@radxa.com Link: https://lore.kernel.org/r/20220909195006.127957-5-naoki@radxa.com Signed-off-by: Heiko Stuebner heiko@sntech.de Stable-dep-of: cee572756aa2 ("arm64: dts: rockchip: Disable HS400 for eMMC on ROCK Pi 4") Signed-off-by: Sasha Levin sashal@kernel.org --- .../boot/dts/rockchip/rk3399-rock-pi-4.dtsi | 124 +++++++++--------- 1 file changed, 61 insertions(+), 63 deletions(-)
diff --git a/arch/arm64/boot/dts/rockchip/rk3399-rock-pi-4.dtsi b/arch/arm64/boot/dts/rockchip/rk3399-rock-pi-4.dtsi index 4e1c1f970aba1..360a31d2c56cc 100644 --- a/arch/arm64/boot/dts/rockchip/rk3399-rock-pi-4.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3399-rock-pi-4.dtsi @@ -54,32 +54,33 @@ }; };
- vcc12v_dcin: dc-12v { + vbus_typec: vbus-typec-regulator { compatible = "regulator-fixed"; - regulator-name = "vcc12v_dcin"; + enable-active-high; + gpio = <&gpio1 RK_PA3 GPIO_ACTIVE_HIGH>; + pinctrl-names = "default"; + pinctrl-0 = <&vcc5v0_typec_en>; + regulator-name = "vbus_typec"; regulator-always-on; - regulator-boot-on; - regulator-min-microvolt = <12000000>; - regulator-max-microvolt = <12000000>; + vin-supply = <&vcc5v0_sys>; };
- vcc5v0_sys: vcc-sys { + vcc12v_dcin: dc-12v { compatible = "regulator-fixed"; - regulator-name = "vcc5v0_sys"; + regulator-name = "vcc12v_dcin"; regulator-always-on; regulator-boot-on; - regulator-min-microvolt = <5000000>; - regulator-max-microvolt = <5000000>; - vin-supply = <&vcc12v_dcin>; + regulator-min-microvolt = <12000000>; + regulator-max-microvolt = <12000000>; };
- vcc_0v9: vcc-0v9 { + vcc3v3_lan: vcc3v3-lan-regulator { compatible = "regulator-fixed"; - regulator-name = "vcc_0v9"; + regulator-name = "vcc3v3_lan"; regulator-always-on; regulator-boot-on; - regulator-min-microvolt = <900000>; - regulator-max-microvolt = <900000>; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; vin-supply = <&vcc3v3_sys>; };
@@ -116,24 +117,23 @@ vin-supply = <&vcc5v0_sys>; };
- vbus_typec: vbus-typec-regulator { + vcc5v0_sys: vcc-sys { compatible = "regulator-fixed"; - enable-active-high; - gpio = <&gpio1 RK_PA3 GPIO_ACTIVE_HIGH>; - pinctrl-names = "default"; - pinctrl-0 = <&vcc5v0_typec_en>; - regulator-name = "vbus_typec"; + regulator-name = "vcc5v0_sys"; regulator-always-on; - vin-supply = <&vcc5v0_sys>; + regulator-boot-on; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + vin-supply = <&vcc12v_dcin>; };
- vcc3v3_lan: vcc3v3-lan-regulator { + vcc_0v9: vcc-0v9 { compatible = "regulator-fixed"; - regulator-name = "vcc3v3_lan"; + regulator-name = "vcc_0v9"; regulator-always-on; regulator-boot-on; - regulator-min-microvolt = <3300000>; - regulator-max-microvolt = <3300000>; + regulator-min-microvolt = <900000>; + regulator-max-microvolt = <900000>; vin-supply = <&vcc3v3_sys>; };
@@ -493,21 +493,10 @@ };
&io_domains { - status = "okay"; - - bt656-supply = <&vcc_3v0>; audio-supply = <&vcca1v8_codec>; - sdmmc-supply = <&vcc_sdio>; + bt656-supply = <&vcc_3v0>; gpio1830-supply = <&vcc_3v0>; -}; - -&pmu_io_domains { - status = "okay"; - - pmu1830-supply = <&vcc_3v0>; -}; - -&pcie_phy { + sdmmc-supply = <&vcc_sdio>; status = "okay"; };
@@ -523,6 +512,10 @@ status = "okay"; };
+&pcie_phy { + status = "okay"; +}; + &pinctrl { bt { bt_enable_h: bt-enable-h { @@ -544,6 +537,20 @@ }; };
+ pmic { + pmic_int_l: pmic-int-l { + rockchip,pins = <1 RK_PC5 RK_FUNC_GPIO &pcfg_pull_up>; + }; + + vsel1_pin: vsel1-pin { + rockchip,pins = <1 RK_PC1 RK_FUNC_GPIO &pcfg_pull_down>; + }; + + vsel2_pin: vsel2-pin { + rockchip,pins = <1 RK_PB6 RK_FUNC_GPIO &pcfg_pull_down>; + }; + }; + sdio0 { sdio0_bus4: sdio0-bus4 { rockchip,pins = <2 RK_PC4 1 &pcfg_pull_up_20ma>, @@ -561,20 +568,6 @@ }; };
- pmic { - pmic_int_l: pmic-int-l { - rockchip,pins = <1 RK_PC5 RK_FUNC_GPIO &pcfg_pull_up>; - }; - - vsel1_pin: vsel1-pin { - rockchip,pins = <1 RK_PC1 RK_FUNC_GPIO &pcfg_pull_down>; - }; - - vsel2_pin: vsel2-pin { - rockchip,pins = <1 RK_PB6 RK_FUNC_GPIO &pcfg_pull_down>; - }; - }; - usb-typec { vcc5v0_typec_en: vcc5v0-typec-en { rockchip,pins = <1 RK_PA3 RK_FUNC_GPIO &pcfg_pull_up>; @@ -598,6 +591,11 @@ }; };
+&pmu_io_domains { + pmu1830-supply = <&vcc_3v0>; + status = "okay"; +}; + &pwm2 { status = "okay"; }; @@ -608,6 +606,14 @@ vref-supply = <&vcc_1v8>; };
+&sdhci { + bus-width = <8>; + mmc-hs400-1_8v; + mmc-hs400-enhanced-strobe; + non-removable; + status = "okay"; +}; + &sdio0 { #address-cells = <1>; #size-cells = <0>; @@ -635,14 +641,6 @@ status = "okay"; };
-&sdhci { - bus-width = <8>; - mmc-hs400-1_8v; - mmc-hs400-enhanced-strobe; - non-removable; - status = "okay"; -}; - &spdif {
spdif_p0: port { @@ -724,13 +722,13 @@ status = "okay"; };
-&usbdrd_dwc3_0 { +&usbdrd3_1 { status = "okay"; - dr_mode = "host"; };
-&usbdrd3_1 { +&usbdrd_dwc3_0 { status = "okay"; + dr_mode = "host"; };
&usbdrd_dwc3_1 {
From: Christopher Obbard chris.obbard@collabora.com
[ Upstream commit cee572756aa2cb46e959e9797ad4b730b78a050b ]
There is some instablity with some eMMC modules on ROCK Pi 4 SBCs running in HS400 mode. This ends up resulting in some block errors after a while or after a "heavy" operation utilising the eMMC (e.g. resizing a filesystem). An example of these errors is as follows:
[ 289.171014] mmc1: running CQE recovery [ 290.048972] mmc1: running CQE recovery [ 290.054834] mmc1: running CQE recovery [ 290.060817] mmc1: running CQE recovery [ 290.061337] blk_update_request: I/O error, dev mmcblk1, sector 1411072 op 0x1:(WRITE) flags 0x800 phys_seg 36 prio class 0 [ 290.061370] EXT4-fs warning (device mmcblk1p1): ext4_end_bio:348: I/O error 10 writing to inode 29547 starting block 176466) [ 290.061484] Buffer I/O error on device mmcblk1p1, logical block 172288 [ 290.061531] Buffer I/O error on device mmcblk1p1, logical block 172289 [ 290.061551] Buffer I/O error on device mmcblk1p1, logical block 172290 [ 290.061574] Buffer I/O error on device mmcblk1p1, logical block 172291 [ 290.061592] Buffer I/O error on device mmcblk1p1, logical block 172292 [ 290.061615] Buffer I/O error on device mmcblk1p1, logical block 172293 [ 290.061632] Buffer I/O error on device mmcblk1p1, logical block 172294 [ 290.061654] Buffer I/O error on device mmcblk1p1, logical block 172295 [ 290.061673] Buffer I/O error on device mmcblk1p1, logical block 172296 [ 290.061695] Buffer I/O error on device mmcblk1p1, logical block 172297
Disabling the Command Queue seems to stop the CQE recovery from running, but doesn't seem to improve the I/O errors. Until this can be investigated further, disable HS400 mode on the ROCK Pi 4 SBCs to at least stop I/O errors from occurring.
While we are here, set the eMMC maximum clock frequency to 1.5MHz to follow the ROCK 4C+.
Fixes: 1b5715c602fd ("arm64: dts: rockchip: add ROCK Pi 4 DTS support") Signed-off-by: Christopher Obbard chris.obbard@collabora.com Tested-By: Folker Schwesinger dev@folker-schwesinger.de Link: https://lore.kernel.org/r/20230705144255.115299-2-chris.obbard@collabora.com Signed-off-by: Heiko Stuebner heiko@sntech.de Signed-off-by: Sasha Levin sashal@kernel.org --- arch/arm64/boot/dts/rockchip/rk3399-rock-pi-4.dtsi | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/arch/arm64/boot/dts/rockchip/rk3399-rock-pi-4.dtsi b/arch/arm64/boot/dts/rockchip/rk3399-rock-pi-4.dtsi index 360a31d2c56cc..2f52b91b72152 100644 --- a/arch/arm64/boot/dts/rockchip/rk3399-rock-pi-4.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3399-rock-pi-4.dtsi @@ -607,9 +607,9 @@ };
&sdhci { + max-frequency = <150000000>; bus-width = <8>; - mmc-hs400-1_8v; - mmc-hs400-enhanced-strobe; + mmc-hs200-1_8v; non-removable; status = "okay"; };
From: Zhang Shurong zhang_shurong@foxmail.com
[ Upstream commit c163108e706909570f8aa9aa5bcf6806e2b4c98c ]
The driver forgets to call regulator_bulk_disable()
Add the missed call to fix it.
Fixes: 33ada14a26c8 ("ASoC: add rt5665 codec driver") Signed-off-by: Zhang Shurong zhang_shurong@foxmail.com Link: https://lore.kernel.org/r/tencent_A560D01E3E0A00A85A12F137E4B5205B3508@qq.co... Signed-off-by: Mark Brown broonie@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- sound/soc/codecs/rt5665.c | 2 ++ 1 file changed, 2 insertions(+)
diff --git a/sound/soc/codecs/rt5665.c b/sound/soc/codecs/rt5665.c index 8a915cdce0fe9..8b73c2d7f1f10 100644 --- a/sound/soc/codecs/rt5665.c +++ b/sound/soc/codecs/rt5665.c @@ -4472,6 +4472,8 @@ static void rt5665_remove(struct snd_soc_component *component) struct rt5665_priv *rt5665 = snd_soc_component_get_drvdata(component);
regmap_write(rt5665->regmap, RT5665_RESET, 0); + + regulator_bulk_disable(ARRAY_SIZE(rt5665->supplies), rt5665->supplies); }
#ifdef CONFIG_PM
From: Jerome Brunet jbrunet@baylibre.com
[ Upstream commit c1f848f12103920ca165758aedb1c10904e193e1 ]
When the tdm lane mask is computed, the driver currently fills the 1st lane before moving on to the next. If the stream has less channels than the lanes can accommodate, slots will be disabled on the last lanes.
Unfortunately, the HW distribute channels in a different way. It distribute channels in pair on each lanes before moving on the next slots.
This difference leads to problems if a device has an interface with more than 1 lane and with more than 2 slots per lane.
For example: a playback interface with 2 lanes and 4 slots each (total 8 slots - zero based numbering) - Playing a 8ch stream: - All slots activated by the driver - channel #2 will be played on lane #1 - slot #0 following HW placement - Playing a 4ch stream: - Lane #1 disabled by the driver - channel #2 will be played on lane #0 - slot #2
This behaviour is obviously not desirable.
Change the way slots are activated on the TDM lanes to follow what the HW does and make sure each channel always get mapped to the same slot/lane.
Fixes: 1a11d88f499c ("ASoC: meson: add tdm formatter base driver") Signed-off-by: Jerome Brunet jbrunet@baylibre.com Link: https://lore.kernel.org/r/20230809171931.1244502-1-jbrunet@baylibre.com Signed-off-by: Mark Brown broonie@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- sound/soc/meson/axg-tdm-formatter.c | 42 ++++++++++++++++++----------- 1 file changed, 26 insertions(+), 16 deletions(-)
diff --git a/sound/soc/meson/axg-tdm-formatter.c b/sound/soc/meson/axg-tdm-formatter.c index cab7fa2851aa8..4834cfd163c03 100644 --- a/sound/soc/meson/axg-tdm-formatter.c +++ b/sound/soc/meson/axg-tdm-formatter.c @@ -30,27 +30,32 @@ int axg_tdm_formatter_set_channel_masks(struct regmap *map, struct axg_tdm_stream *ts, unsigned int offset) { - unsigned int val, ch = ts->channels; - unsigned long mask; - int i, j; + unsigned int ch = ts->channels; + u32 val[AXG_TDM_NUM_LANES]; + int i, j, k; + + /* + * We need to mimick the slot distribution used by the HW to keep the + * channel placement consistent regardless of the number of channel + * in the stream. This is why the odd algorithm below is used. + */ + memset(val, 0, sizeof(*val) * AXG_TDM_NUM_LANES);
/* * Distribute the channels of the stream over the available slots - * of each TDM lane + * of each TDM lane. We need to go over the 32 slots ... */ - for (i = 0; i < AXG_TDM_NUM_LANES; i++) { - val = 0; - mask = ts->mask[i]; - - for (j = find_first_bit(&mask, 32); - (j < 32) && ch; - j = find_next_bit(&mask, 32, j + 1)) { - val |= 1 << j; - ch -= 1; + for (i = 0; (i < 32) && ch; i += 2) { + /* ... of all the lanes ... */ + for (j = 0; j < AXG_TDM_NUM_LANES; j++) { + /* ... then distribute the channels in pairs */ + for (k = 0; k < 2; k++) { + if ((BIT(i + k) & ts->mask[j]) && ch) { + val[j] |= BIT(i + k); + ch -= 1; + } + } } - - regmap_write(map, offset, val); - offset += regmap_get_reg_stride(map); }
/* @@ -63,6 +68,11 @@ int axg_tdm_formatter_set_channel_masks(struct regmap *map, return -EINVAL; }
+ for (i = 0; i < AXG_TDM_NUM_LANES; i++) { + regmap_write(map, offset, val[i]); + offset += regmap_get_reg_stride(map); + } + return 0; } EXPORT_SYMBOL_GPL(axg_tdm_formatter_set_channel_masks);
From: Kailang Yang kailang@realtek.com
[ Upstream commit 46cdff2369cbdf8d78081a22526e77bd1323f563 ]
Set spec->en_3kpull_low default to true. Then fillback ALC236 and ALC257 to false.
Additional note: this addresses a regression caused by the previous fix 69ea4c9d02b7 ("ALSA: hda/realtek - remove 3k pull low procedure"). The previous workaround was applied too widely without necessity, which resulted in the pop noise at PM again. This patch corrects the condition and restores the old behavior for the devices that don't suffer from the original problem.
Fixes: 69ea4c9d02b7 ("ALSA: hda/realtek - remove 3k pull low procedure") Link: https://bugzilla.kernel.org/show_bug.cgi?id=217732 Link: https://lore.kernel.org/r/01e212a538fc407ca6edd10b81ff7b05@realtek.com Signed-off-by: Kailang Yang kailang@realtek.com Signed-off-by: Takashi Iwai tiwai@suse.de Signed-off-by: Sasha Levin sashal@kernel.org --- sound/pci/hda/patch_realtek.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-)
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 09a9e21675341..adfab80b8189d 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -10006,6 +10006,7 @@ static int patch_alc269(struct hda_codec *codec) spec = codec->spec; spec->gen.shared_mic_vref_pin = 0x18; codec->power_save_node = 0; + spec->en_3kpull_low = true;
#ifdef CONFIG_PM codec->patch_ops.suspend = alc269_suspend; @@ -10088,14 +10089,16 @@ static int patch_alc269(struct hda_codec *codec) spec->shutup = alc256_shutup; spec->init_hook = alc256_init; spec->gen.mixer_nid = 0; /* ALC256 does not have any loopback mixer path */ - if (codec->bus->pci->vendor == PCI_VENDOR_ID_AMD) - spec->en_3kpull_low = true; + if (codec->core.vendor_id == 0x10ec0236 && + codec->bus->pci->vendor != PCI_VENDOR_ID_AMD) + spec->en_3kpull_low = false; break; case 0x10ec0257: spec->codec_variant = ALC269_TYPE_ALC257; spec->shutup = alc256_shutup; spec->init_hook = alc256_init; spec->gen.mixer_nid = 0; + spec->en_3kpull_low = false; break; case 0x10ec0215: case 0x10ec0245:
From: Akira Tsukamoto akira.tsukamoto@gmail.com
[ Upstream commit ca6eaaa210deec0e41cbfc380bf89cf079203569 ]
This patch will reduce cpu usage dramatically in kernel space especially for application which use sys-call with large buffer size, such as network applications. The main reason behind this is that every unaligned memory access will raise exceptions and switch between s-mode and m-mode causing large overhead.
First copy in bytes until reaches the first word aligned boundary in destination memory address. This is the preparation before the bulk aligned word copy.
The destination address is aligned now, but oftentimes the source address is not in an aligned boundary. To reduce the unaligned memory access, it reads the data from source in aligned boundaries, which will cause the data to have an offset, and then combines the data in the next iteration by fixing offset with shifting before writing to destination. The majority of the improving copy speed comes from this shift copy.
In the lucky situation that the both source and destination address are on the aligned boundary, perform load and store with register size to copy the data. Without the unrolling, it will reduce the speed since the next store instruction for the same register using from the load will stall the pipeline.
At last, copying the remainder in one byte at a time.
Signed-off-by: Akira Tsukamoto akira.tsukamoto@gmail.com Signed-off-by: Palmer Dabbelt palmerdabbelt@google.com Stable-dep-of: 4b05b993900d ("riscv: uaccess: Return the number of bytes effectively not copied") Signed-off-by: Sasha Levin sashal@kernel.org --- arch/riscv/lib/uaccess.S | 181 +++++++++++++++++++++++++++++++-------- 1 file changed, 146 insertions(+), 35 deletions(-)
diff --git a/arch/riscv/lib/uaccess.S b/arch/riscv/lib/uaccess.S index fceaeb18cc640..bceb0629e440e 100644 --- a/arch/riscv/lib/uaccess.S +++ b/arch/riscv/lib/uaccess.S @@ -19,50 +19,161 @@ ENTRY(__asm_copy_from_user) li t6, SR_SUM csrs CSR_STATUS, t6
- add a3, a1, a2 - /* Use word-oriented copy only if low-order bits match */ - andi t0, a0, SZREG-1 - andi t1, a1, SZREG-1 - bne t0, t1, 2f + /* Save for return value */ + mv t5, a2
- addi t0, a1, SZREG-1 - andi t1, a3, ~(SZREG-1) - andi t0, t0, ~(SZREG-1) /* - * a3: terminal address of source region - * t0: lowest XLEN-aligned address in source - * t1: highest XLEN-aligned address in source + * Register allocation for code below: + * a0 - start of uncopied dst + * a1 - start of uncopied src + * a2 - size + * t0 - end of uncopied dst */ - bgeu t0, t1, 2f - bltu a1, t0, 4f + add t0, a0, a2 + bgtu a0, t0, 5f + + /* + * Use byte copy only if too small. + */ + li a3, 8*SZREG /* size must be larger than size in word_copy */ + bltu a2, a3, .Lbyte_copy_tail + + /* + * Copy first bytes until dst is align to word boundary. + * a0 - start of dst + * t1 - start of aligned dst + */ + addi t1, a0, SZREG-1 + andi t1, t1, ~(SZREG-1) + /* dst is already aligned, skip */ + beq a0, t1, .Lskip_first_bytes 1: - fixup REG_L, t2, (a1), 10f - fixup REG_S, t2, (a0), 10f - addi a1, a1, SZREG - addi a0, a0, SZREG - bltu a1, t1, 1b + /* a5 - one byte for copying data */ + fixup lb a5, 0(a1), 10f + addi a1, a1, 1 /* src */ + fixup sb a5, 0(a0), 10f + addi a0, a0, 1 /* dst */ + bltu a0, t1, 1b /* t1 - start of aligned dst */ + +.Lskip_first_bytes: + /* + * Now dst is aligned. + * Use shift-copy if src is misaligned. + * Use word-copy if both src and dst are aligned because + * can not use shift-copy which do not require shifting + */ + /* a1 - start of src */ + andi a3, a1, SZREG-1 + bnez a3, .Lshift_copy + +.Lword_copy: + /* + * Both src and dst are aligned, unrolled word copy + * + * a0 - start of aligned dst + * a1 - start of aligned src + * a3 - a1 & mask:(SZREG-1) + * t0 - end of aligned dst + */ + addi t0, t0, -(8*SZREG-1) /* not to over run */ 2: - bltu a1, a3, 5f + fixup REG_L a4, 0(a1), 10f + fixup REG_L a5, SZREG(a1), 10f + fixup REG_L a6, 2*SZREG(a1), 10f + fixup REG_L a7, 3*SZREG(a1), 10f + fixup REG_L t1, 4*SZREG(a1), 10f + fixup REG_L t2, 5*SZREG(a1), 10f + fixup REG_L t3, 6*SZREG(a1), 10f + fixup REG_L t4, 7*SZREG(a1), 10f + fixup REG_S a4, 0(a0), 10f + fixup REG_S a5, SZREG(a0), 10f + fixup REG_S a6, 2*SZREG(a0), 10f + fixup REG_S a7, 3*SZREG(a0), 10f + fixup REG_S t1, 4*SZREG(a0), 10f + fixup REG_S t2, 5*SZREG(a0), 10f + fixup REG_S t3, 6*SZREG(a0), 10f + fixup REG_S t4, 7*SZREG(a0), 10f + addi a0, a0, 8*SZREG + addi a1, a1, 8*SZREG + bltu a0, t0, 2b + + addi t0, t0, 8*SZREG-1 /* revert to original value */ + j .Lbyte_copy_tail + +.Lshift_copy: + + /* + * Word copy with shifting. + * For misaligned copy we still perform aligned word copy, but + * we need to use the value fetched from the previous iteration and + * do some shifts. + * This is safe because reading less than a word size. + * + * a0 - start of aligned dst + * a1 - start of src + * a3 - a1 & mask:(SZREG-1) + * t0 - end of uncopied dst + * t1 - end of aligned dst + */ + /* calculating aligned word boundary for dst */ + andi t1, t0, ~(SZREG-1) + /* Converting unaligned src to aligned arc */ + andi a1, a1, ~(SZREG-1) + + /* + * Calculate shifts + * t3 - prev shift + * t4 - current shift + */ + slli t3, a3, LGREG + li a5, SZREG*8 + sub t4, a5, t3 + + /* Load the first word to combine with seceond word */ + fixup REG_L a5, 0(a1), 10f
3: + /* Main shifting copy + * + * a0 - start of aligned dst + * a1 - start of aligned src + * t1 - end of aligned dst + */ + + /* At least one iteration will be executed */ + srl a4, a5, t3 + fixup REG_L a5, SZREG(a1), 10f + addi a1, a1, SZREG + sll a2, a5, t4 + or a2, a2, a4 + fixup REG_S a2, 0(a0), 10f + addi a0, a0, SZREG + bltu a0, t1, 3b + + /* Revert src to original unaligned value */ + add a1, a1, a3 + +.Lbyte_copy_tail: + /* + * Byte copy anything left. + * + * a0 - start of remaining dst + * a1 - start of remaining src + * t0 - end of remaining dst + */ + bgeu a0, t0, 5f +4: + fixup lb a5, 0(a1), 10f + addi a1, a1, 1 /* src */ + fixup sb a5, 0(a0), 10f + addi a0, a0, 1 /* dst */ + bltu a0, t0, 4b /* t0 - end of dst */ + +5: /* Disable access to user memory */ csrc CSR_STATUS, t6 - li a0, 0 + li a0, 0 ret -4: /* Edge case: unalignment */ - fixup lbu, t2, (a1), 10f - fixup sb, t2, (a0), 10f - addi a1, a1, 1 - addi a0, a0, 1 - bltu a1, t0, 4b - j 1b -5: /* Edge case: remainder */ - fixup lbu, t2, (a1), 10f - fixup sb, t2, (a0), 10f - addi a1, a1, 1 - addi a0, a0, 1 - bltu a1, a3, 5b - j 3b ENDPROC(__asm_copy_to_user) ENDPROC(__asm_copy_from_user) EXPORT_SYMBOL(__asm_copy_to_user) @@ -117,7 +228,7 @@ EXPORT_SYMBOL(__clear_user) 10: /* Disable access to user memory */ csrs CSR_STATUS, t6 - mv a0, a2 + mv a0, t5 ret 11: csrs CSR_STATUS, t6
From: Jisheng Zhang jszhang@kernel.org
[ Upstream commit 9d504f9aa5c1b76673018da9503e76b351a24b8c ]
uaccess functions such __asm_copy_to_user(), __arch_copy_from_user() and __clear_user() place their exception fixups in the `.fixup` section without any clear association with themselves. If we backtrace the fixup code, it will be symbolized as an offset from the nearest prior symbol.
Similar as arm64 does, we must move fixups into the body of the functions themselves, after the usual fast-path returns.
Signed-off-by: Jisheng Zhang jszhang@kernel.org Signed-off-by: Palmer Dabbelt palmer@rivosinc.com Stable-dep-of: 4b05b993900d ("riscv: uaccess: Return the number of bytes effectively not copied") Signed-off-by: Sasha Levin sashal@kernel.org --- arch/riscv/lib/uaccess.S | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-)
diff --git a/arch/riscv/lib/uaccess.S b/arch/riscv/lib/uaccess.S index bceb0629e440e..baddd6a0d0229 100644 --- a/arch/riscv/lib/uaccess.S +++ b/arch/riscv/lib/uaccess.S @@ -174,6 +174,13 @@ ENTRY(__asm_copy_from_user) csrc CSR_STATUS, t6 li a0, 0 ret + + /* Exception fixup code */ +10: + /* Disable access to user memory */ + csrs CSR_STATUS, t6 + mv a0, t5 + ret ENDPROC(__asm_copy_to_user) ENDPROC(__asm_copy_from_user) EXPORT_SYMBOL(__asm_copy_to_user) @@ -219,19 +226,12 @@ ENTRY(__clear_user) addi a0, a0, 1 bltu a0, a3, 5b j 3b -ENDPROC(__clear_user) -EXPORT_SYMBOL(__clear_user)
- .section .fixup,"ax" - .balign 4 - /* Fixup code for __copy_user(10) and __clear_user(11) */ -10: - /* Disable access to user memory */ - csrs CSR_STATUS, t6 - mv a0, t5 - ret + /* Exception fixup code */ 11: + /* Disable access to user memory */ csrs CSR_STATUS, t6 mv a0, a1 ret - .previous +ENDPROC(__clear_user) +EXPORT_SYMBOL(__clear_user)
From: Chen Lifu chenlifu@huawei.com
[ Upstream commit c08b4848f596fd95543197463b5162bd7bab2442 ]
Since commit 5d8544e2d007 ("RISC-V: Generic library routines and assembly") and commit ebcbd75e3962 ("riscv: Fix the bug in memory access fixup code"), if __clear_user and __copy_user return from an fixup branch, CSR_STATUS SR_SUM bit will be set, it is a vulnerability, so that S-mode memory accesses to pages that are accessible by U-mode will success. Disable S-mode access to U-mode memory should clear SR_SUM bit.
Fixes: 5d8544e2d007 ("RISC-V: Generic library routines and assembly") Fixes: ebcbd75e3962 ("riscv: Fix the bug in memory access fixup code") Signed-off-by: Chen Lifu chenlifu@huawei.com Reviewed-by: Ben Dooks ben.dooks@codethink.co.uk Link: https://lore.kernel.org/r/20220615014714.1650349-1-chenlifu@huawei.com Cc: stable@vger.kernel.org Signed-off-by: Palmer Dabbelt palmer@rivosinc.com Stable-dep-of: 4b05b993900d ("riscv: uaccess: Return the number of bytes effectively not copied") Signed-off-by: Sasha Levin sashal@kernel.org --- arch/riscv/lib/uaccess.S | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/arch/riscv/lib/uaccess.S b/arch/riscv/lib/uaccess.S index baddd6a0d0229..039050172d083 100644 --- a/arch/riscv/lib/uaccess.S +++ b/arch/riscv/lib/uaccess.S @@ -178,7 +178,7 @@ ENTRY(__asm_copy_from_user) /* Exception fixup code */ 10: /* Disable access to user memory */ - csrs CSR_STATUS, t6 + csrc CSR_STATUS, t6 mv a0, t5 ret ENDPROC(__asm_copy_to_user) @@ -230,7 +230,7 @@ ENTRY(__clear_user) /* Exception fixup code */ 11: /* Disable access to user memory */ - csrs CSR_STATUS, t6 + csrc CSR_STATUS, t6 mv a0, a1 ret ENDPROC(__clear_user)
From: Alexandre Ghiti alexghiti@rivosinc.com
[ Upstream commit 4b05b993900dd3eba0fc83ef5c5ddc7d65d786c6 ]
It was reported that the riscv kernel hangs while executing the test in [1].
Indeed, the test hangs when trying to write a buffer to a file. The problem is that the riscv implementation of raw_copy_from_user() does not return the correct number of bytes not written when an exception happens and is fixed up, instead it always returns the initial size to copy, even if some bytes were actually copied.
generic_perform_write() pre-faults the user pages and bails out if nothing can be written, otherwise it will access the userspace buffer: here the riscv implementation keeps returning it was not able to copy any byte though the pre-faulting indicates otherwise. So generic_perform_write() keeps retrying to access the user memory and ends up in an infinite loop.
Note that before the commit mentioned in [1] that introduced this regression, it worked because generic_perform_write() would bail out if only one byte could not be written.
So fix this by returning the number of bytes effectively not written in __asm_copy_[to|from]_user() and __clear_user(), as it is expected.
Link: https://lore.kernel.org/linux-riscv/20230309151841.bomov6hq3ybyp42a@debian/ [1] Fixes: ebcbd75e3962 ("riscv: Fix the bug in memory access fixup code") Reported-by: Bo YU tsu.yubo@gmail.com Closes: https://lore.kernel.org/linux-riscv/20230309151841.bomov6hq3ybyp42a@debian/#... Reported-by: Aurelien Jarno aurelien@aurel32.net Closes: https://lore.kernel.org/linux-riscv/ZNOnCakhwIeue3yr@aurel32.net/ Signed-off-by: Alexandre Ghiti alexghiti@rivosinc.com Reviewed-by: Björn Töpel bjorn@rivosinc.com Tested-by: Aurelien Jarno aurelien@aurel32.net Reviewed-by: Aurelien Jarno aurelien@aurel32.net Link: https://lore.kernel.org/r/20230811150604.1621784-1-alexghiti@rivosinc.com Signed-off-by: Palmer Dabbelt palmer@rivosinc.com Signed-off-by: Sasha Levin sashal@kernel.org --- arch/riscv/lib/uaccess.S | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-)
diff --git a/arch/riscv/lib/uaccess.S b/arch/riscv/lib/uaccess.S index 039050172d083..80866dea07418 100644 --- a/arch/riscv/lib/uaccess.S +++ b/arch/riscv/lib/uaccess.S @@ -19,8 +19,11 @@ ENTRY(__asm_copy_from_user) li t6, SR_SUM csrs CSR_STATUS, t6
- /* Save for return value */ - mv t5, a2 + /* + * Save the terminal address which will be used to compute the number + * of bytes copied in case of a fixup exception. + */ + add t5, a0, a2
/* * Register allocation for code below: @@ -179,7 +182,7 @@ ENTRY(__asm_copy_from_user) 10: /* Disable access to user memory */ csrc CSR_STATUS, t6 - mv a0, t5 + sub a0, t5, a0 ret ENDPROC(__asm_copy_to_user) ENDPROC(__asm_copy_from_user) @@ -231,7 +234,7 @@ ENTRY(__clear_user) 11: /* Disable access to user memory */ csrc CSR_STATUS, t6 - mv a0, a1 + sub a0, a3, a0 ret ENDPROC(__clear_user) EXPORT_SYMBOL(__clear_user)
From: Tony Lindgren tony@atomide.com
[ Upstream commit dfe2aeb226fd5e19b0ee795f4f6ed8bc494c1534 ]
Unloading a hardware specific 8250 driver can produce error "Unable to handle kernel paging request at virtual address" about ten seconds after unloading the driver. This happens on uart_hangup() calling uart_change_pm().
Turns out commit 04e82793f068 ("serial: 8250: Reinit port->pm on port specific driver unbind") was only a partial fix. If the hardware specific driver has initialized port->pm function, we need to clear port->pm too. Just reinitializing port->ops does not do this. Otherwise serial8250_pm() will call port->pm() instead of serial8250_do_pm().
Fixes: 04e82793f068 ("serial: 8250: Reinit port->pm on port specific driver unbind") Signed-off-by: Tony Lindgren tony@atomide.com Link: https://lore.kernel.org/r/20230804131553.52927-1-tony@atomide.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/tty/serial/8250/8250_port.c | 1 + 1 file changed, 1 insertion(+)
diff --git a/drivers/tty/serial/8250/8250_port.c b/drivers/tty/serial/8250/8250_port.c index 432a438929e64..7499954c9aa76 100644 --- a/drivers/tty/serial/8250/8250_port.c +++ b/drivers/tty/serial/8250/8250_port.c @@ -3231,6 +3231,7 @@ void serial8250_init_port(struct uart_8250_port *up) struct uart_port *port = &up->port;
spin_lock_init(&port->lock); + port->pm = NULL; port->ops = &serial8250_pops; port->has_sysrq = IS_ENABLED(CONFIG_SERIAL_8250_CONSOLE);
From: dengxiang dengxiang@nfschina.com
commit 788449ae57f4273111b779bbcaad552b67f517d5 upstream.
This patch adds a USB quirk for Mythware XA001AU USB interface.
Signed-off-by: dengxiang dengxiang@nfschina.com Cc: stable@vger.kernel.org Link: https://lore.kernel.org/r/20230803024437.370069-1-dengxiang@nfschina.com Signed-off-by: Takashi Iwai tiwai@suse.de Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- sound/usb/quirks-table.h | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+)
--- a/sound/usb/quirks-table.h +++ b/sound/usb/quirks-table.h @@ -3797,6 +3797,35 @@ AU0828_DEVICE(0x2040, 0x7270, "Hauppauge } } }, +{ + /* Advanced modes of the Mythware XA001AU. + * For the standard mode, Mythware XA001AU has ID ffad:a001 + */ + USB_DEVICE_VENDOR_SPEC(0xffad, 0xa001), + .driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) { + .vendor_name = "Mythware", + .product_name = "XA001AU", + .ifnum = QUIRK_ANY_INTERFACE, + .type = QUIRK_COMPOSITE, + .data = (const struct snd_usb_audio_quirk[]) { + { + .ifnum = 0, + .type = QUIRK_IGNORE_INTERFACE, + }, + { + .ifnum = 1, + .type = QUIRK_AUDIO_STANDARD_INTERFACE, + }, + { + .ifnum = 2, + .type = QUIRK_AUDIO_STANDARD_INTERFACE, + }, + { + .ifnum = -1 + } + } + } +},
#undef USB_DEVICE_VENDOR_SPEC #undef USB_AUDIO_DEVICE
From: Russell Harmon via samba-technical samba-technical@lists.samba.org
commit 69513dd669e243928f7450893190915a88f84a2b upstream.
Under the current code, when cifs_readpage_worker is called, the call contract is that the callee should unlock the page. This is documented in the read_folio section of Documentation/filesystems/vfs.rst as:
The filesystem should unlock the folio once the read has completed, whether it was successful or not.
Without this change, when fscache is in use and cache hit occurs during a read, the page lock is leaked, producing the following stack on subsequent reads (via mmap) to the page:
$ cat /proc/3890/task/12864/stack [<0>] folio_wait_bit_common+0x124/0x350 [<0>] filemap_read_folio+0xad/0xf0 [<0>] filemap_fault+0x8b1/0xab0 [<0>] __do_fault+0x39/0x150 [<0>] do_fault+0x25c/0x3e0 [<0>] __handle_mm_fault+0x6ca/0xc70 [<0>] handle_mm_fault+0xe9/0x350 [<0>] do_user_addr_fault+0x225/0x6c0 [<0>] exc_page_fault+0x84/0x1b0 [<0>] asm_exc_page_fault+0x27/0x30
This requires a reboot to resolve; it is a deadlock.
Note however that the call to cifs_readpage_from_fscache does mark the page clean, but does not free the folio lock. This happens in __cifs_readpage_from_fscache on success. Releasing the lock at that point however is not appropriate as cifs_readahead also calls cifs_readpage_from_fscache and *does* unconditionally release the lock after its return. This change therefore effectively makes cifs_readpage_worker work like cifs_readahead.
Signed-off-by: Russell Harmon russ@har.mn Acked-by: Paulo Alcantara (SUSE) pc@manguebit.com Reviewed-by: David Howells dhowells@redhat.com Cc: stable@vger.kernel.org Signed-off-by: Steve French stfrench@microsoft.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- fs/cifs/file.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
--- a/fs/cifs/file.c +++ b/fs/cifs/file.c @@ -4580,9 +4580,9 @@ static int cifs_readpage_worker(struct f
io_error: kunmap(page); - unlock_page(page);
read_complete: + unlock_page(page); return rc; }
From: Yang Yingliang yangyingliang@huawei.com
commit d83035433701919ac6db15f7737cbf554c36c1a6 upstream.
mmc_free_host() has already be called in wbsd_free_mmc(), remove the mmc_free_host() in error path in wbsd_init().
Fixes: dc5b9b50fc9d ("mmc: wbsd: fix return value check of mmc_add_host()") Signed-off-by: Yang Yingliang yangyingliang@huawei.com Cc: stable@vger.kernel.org Link: https://lore.kernel.org/r/20230807124443.3431366-1-yangyingliang@huawei.com Signed-off-by: Ulf Hansson ulf.hansson@linaro.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/mmc/host/wbsd.c | 2 -- 1 file changed, 2 deletions(-)
--- a/drivers/mmc/host/wbsd.c +++ b/drivers/mmc/host/wbsd.c @@ -1710,8 +1710,6 @@ static int wbsd_init(struct device *dev,
wbsd_release_resources(host); wbsd_free_mmc(dev); - - mmc_free_host(mmc); return ret; }
From: Yibin Ding yibin.ding@unisoc.com
commit 4b430d4ac99750ee2ae2f893f1055c7af1ec3dc5 upstream.
For a completed request, after the mmc_blk_mq_complete_rq(mq, req) function is executed, the bitmap_tags corresponding to the request will be cleared, that is, the request will be regarded as idle. If the request is acquired by a different type of process at this time, the issue_type of the request may change. It further caused the value of mq->in_flight[issue_type] to be abnormal, and a large number of requests could not be sent.
p1: p2: mmc_blk_mq_complete_rq blk_mq_free_request blk_mq_get_request blk_mq_rq_ctx_init mmc_blk_mq_dec_in_flight mmc_issue_type(mq, req)
This strategy can ensure the consistency of issue_type before and after executing mmc_blk_mq_complete_rq.
Fixes: 81196976ed94 ("mmc: block: Add blk-mq support") Cc: stable@vger.kernel.org Signed-off-by: Yibin Ding yibin.ding@unisoc.com Acked-by: Adrian Hunter adrian.hunter@intel.com Link: https://lore.kernel.org/r/20230802023023.1318134-1-yunlong.xing@unisoc.com Signed-off-by: Ulf Hansson ulf.hansson@linaro.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/mmc/core/block.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-)
--- a/drivers/mmc/core/block.c +++ b/drivers/mmc/core/block.c @@ -1980,14 +1980,14 @@ static void mmc_blk_mq_poll_completion(s mmc_blk_urgent_bkops(mq, mqrq); }
-static void mmc_blk_mq_dec_in_flight(struct mmc_queue *mq, struct request *req) +static void mmc_blk_mq_dec_in_flight(struct mmc_queue *mq, enum mmc_issue_type issue_type) { unsigned long flags; bool put_card;
spin_lock_irqsave(&mq->lock, flags);
- mq->in_flight[mmc_issue_type(mq, req)] -= 1; + mq->in_flight[issue_type] -= 1;
put_card = (mmc_tot_in_flight(mq) == 0);
@@ -1999,6 +1999,7 @@ static void mmc_blk_mq_dec_in_flight(str
static void mmc_blk_mq_post_req(struct mmc_queue *mq, struct request *req) { + enum mmc_issue_type issue_type = mmc_issue_type(mq, req); struct mmc_queue_req *mqrq = req_to_mmc_queue_req(req); struct mmc_request *mrq = &mqrq->brq.mrq; struct mmc_host *host = mq->card->host; @@ -2014,7 +2015,7 @@ static void mmc_blk_mq_post_req(struct m else if (likely(!blk_should_fake_timeout(req->q))) blk_mq_complete_request(req);
- mmc_blk_mq_dec_in_flight(mq, req); + mmc_blk_mq_dec_in_flight(mq, issue_type); }
void mmc_blk_mq_recovery(struct mmc_queue *mq)
From: Xin Long lucien.xin@gmail.com
commit 9bfab6d23a2865966a4f89a96536fbf23f83bc8c upstream.
In SCTP protocol, it is using the same timer (T2 timer) for SHUTDOWN and SHUTDOWN_ACK retransmission. However in sctp conntrack the default timeout value for SCTP_CONNTRACK_SHUTDOWN_ACK_SENT state is 3 secs while it's 300 msecs for SCTP_CONNTRACK_SHUTDOWN_SEND/RECV state.
As Paolo Valerio noticed, this might cause unwanted expiration of the ct entry. In my test, with 1s tc netem delay set on the NAT path, after the SHUTDOWN is sent, the sctp ct entry enters SCTP_CONNTRACK_SHUTDOWN_SEND state. However, due to 300ms (too short) delay, when the SHUTDOWN_ACK is sent back from the peer, the sctp ct entry has expired and been deleted, and then the SHUTDOWN_ACK has to be dropped.
Also, it is confusing these two sysctl options always show 0 due to all timeout values using sec as unit:
net.netfilter.nf_conntrack_sctp_timeout_shutdown_recd = 0 net.netfilter.nf_conntrack_sctp_timeout_shutdown_sent = 0
This patch fixes it by also using 3 secs for sctp shutdown send and recv state in sctp conntrack, which is also RTO.initial value in SCTP protocol.
Note that the very short time value for SCTP_CONNTRACK_SHUTDOWN_SEND/RECV was probably used for a rare scenario where SHUTDOWN is sent on 1st path but SHUTDOWN_ACK is replied on 2nd path, then a new connection started immediately on 1st path. So this patch also moves from SHUTDOWN_SEND/RECV to CLOSE when receiving INIT in the ORIGINAL direction.
Fixes: 9fb9cbb1082d ("[NETFILTER]: Add nf_conntrack subsystem.") Reported-by: Paolo Valerio pvalerio@redhat.com Signed-off-by: Xin Long lucien.xin@gmail.com Reviewed-by: Simon Horman horms@kernel.org Signed-off-by: Florian Westphal fw@strlen.de Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- net/netfilter/nf_conntrack_proto_sctp.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
--- a/net/netfilter/nf_conntrack_proto_sctp.c +++ b/net/netfilter/nf_conntrack_proto_sctp.c @@ -49,8 +49,8 @@ static const unsigned int sctp_timeouts[ [SCTP_CONNTRACK_COOKIE_WAIT] = 3 SECS, [SCTP_CONNTRACK_COOKIE_ECHOED] = 3 SECS, [SCTP_CONNTRACK_ESTABLISHED] = 210 SECS, - [SCTP_CONNTRACK_SHUTDOWN_SENT] = 300 SECS / 1000, - [SCTP_CONNTRACK_SHUTDOWN_RECD] = 300 SECS / 1000, + [SCTP_CONNTRACK_SHUTDOWN_SENT] = 3 SECS, + [SCTP_CONNTRACK_SHUTDOWN_RECD] = 3 SECS, [SCTP_CONNTRACK_SHUTDOWN_ACK_SENT] = 3 SECS, [SCTP_CONNTRACK_HEARTBEAT_SENT] = 30 SECS, }; @@ -105,7 +105,7 @@ static const u8 sctp_conntracks[2][11][S { /* ORIGINAL */ /* sNO, sCL, sCW, sCE, sES, sSS, sSR, sSA, sHS */ -/* init */ {sCL, sCL, sCW, sCE, sES, sSS, sSR, sSA, sCW}, +/* init */ {sCL, sCL, sCW, sCE, sES, sCL, sCL, sSA, sCW}, /* init_ack */ {sCL, sCL, sCW, sCE, sES, sSS, sSR, sSA, sCL}, /* abort */ {sCL, sCL, sCL, sCL, sCL, sCL, sCL, sCL, sCL}, /* shutdown */ {sCL, sCL, sCW, sCE, sSS, sSS, sSR, sSA, sCL},
From: Kuniyuki Iwashima kuniyu@amazon.com
Bing-Jhong Billy Jheng reported null-ptr-deref in unix_stream_sendpage() with detailed analysis and a nice repro.
unix_stream_sendpage() tries to add data to the last skb in the peer's recv queue without locking the queue.
If the peer's FD is passed to another socket and the socket's FD is passed to the peer, there is a loop between them. If we close both sockets without receiving FD, the sockets will be cleaned up by garbage collection.
The garbage collection iterates such sockets and unlinks skb with FD from the socket's receive queue under the queue's lock.
So, there is a race where unix_stream_sendpage() could access an skb locklessly that is being released by garbage collection, resulting in use-after-free.
To avoid the issue, unix_stream_sendpage() must lock the peer's recv queue.
Note the issue does not exist in 6.5+ thanks to the recent sendpage() refactoring.
This patch is originally written by Linus Torvalds.
BUG: unable to handle page fault for address: ffff988004dd6870 PF: supervisor read access in kernel mode PF: error_code(0x0000) - not-present page PGD 0 P4D 0 PREEMPT SMP PTI CPU: 4 PID: 297 Comm: garbage_uaf Not tainted 6.1.46 #1 Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS rel-1.16.0-0-gd239552ce722-prebuilt.qemu.org 04/01/2014 RIP: 0010:kmem_cache_alloc_node+0xa2/0x1e0 Code: c0 0f 84 32 01 00 00 41 83 fd ff 74 10 48 8b 00 48 c1 e8 3a 41 39 c5 0f 85 1c 01 00 00 41 8b 44 24 28 49 8b 3c 24 48 8d 4a 40 <49> 8b 1c 06 4c 89 f0 65 48 0f c7 0f 0f 94 c0 84 c0 74 a1 41 8b 44 RSP: 0018:ffffc9000079fac0 EFLAGS: 00000246 RAX: 0000000000000070 RBX: 0000000000000005 RCX: 000000000001a284 RDX: 000000000001a244 RSI: 0000000000400cc0 RDI: 000000000002eee0 RBP: 0000000000400cc0 R08: 0000000000400cc0 R09: 0000000000000003 R10: 0000000000000001 R11: 0000000000000000 R12: ffff888003970f00 R13: 00000000ffffffff R14: ffff988004dd6800 R15: 00000000000000e8 FS: 00007f174d6f3600(0000) GS:ffff88807db00000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: ffff988004dd6870 CR3: 00000000092be000 CR4: 00000000007506e0 PKRU: 55555554 Call Trace: <TASK> ? __die_body.cold+0x1a/0x1f ? page_fault_oops+0xa9/0x1e0 ? fixup_exception+0x1d/0x310 ? exc_page_fault+0xa8/0x150 ? asm_exc_page_fault+0x22/0x30 ? kmem_cache_alloc_node+0xa2/0x1e0 ? __alloc_skb+0x16c/0x1e0 __alloc_skb+0x16c/0x1e0 alloc_skb_with_frags+0x48/0x1e0 sock_alloc_send_pskb+0x234/0x270 unix_stream_sendmsg+0x1f5/0x690 sock_sendmsg+0x5d/0x60 ____sys_sendmsg+0x210/0x260 ___sys_sendmsg+0x83/0xd0 ? kmem_cache_alloc+0xc6/0x1c0 ? avc_disable+0x20/0x20 ? percpu_counter_add_batch+0x53/0xc0 ? alloc_empty_file+0x5d/0xb0 ? alloc_file+0x91/0x170 ? alloc_file_pseudo+0x94/0x100 ? __fget_light+0x9f/0x120 __sys_sendmsg+0x54/0xa0 do_syscall_64+0x3b/0x90 entry_SYSCALL_64_after_hwframe+0x69/0xd3 RIP: 0033:0x7f174d639a7d Code: 28 89 54 24 1c 48 89 74 24 10 89 7c 24 08 e8 8a c1 f4 ff 8b 54 24 1c 48 8b 74 24 10 41 89 c0 8b 7c 24 08 b8 2e 00 00 00 0f 05 <48> 3d 00 f0 ff ff 77 33 44 89 c7 48 89 44 24 08 e8 de c1 f4 ff 48 RSP: 002b:00007ffcb563ea50 EFLAGS: 00000293 ORIG_RAX: 000000000000002e RAX: ffffffffffffffda RBX: 0000000000000000 RCX: 00007f174d639a7d RDX: 0000000000000000 RSI: 00007ffcb563eab0 RDI: 0000000000000007 RBP: 00007ffcb563eb10 R08: 0000000000000000 R09: 00000000ffffffff R10: 00000000004040a0 R11: 0000000000000293 R12: 00007ffcb563ec28 R13: 0000000000401398 R14: 0000000000403e00 R15: 00007f174d72c000 </TASK>
Fixes: 869e7c62486e ("net: af_unix: implement stream sendpage support") Reported-by: Bing-Jhong Billy Jheng billy@starlabs.sg Reviewed-by: Bing-Jhong Billy Jheng billy@starlabs.sg Co-developed-by: Linus Torvalds torvalds@linux-foundation.org Signed-off-by: Linus Torvalds torvalds@linux-foundation.org Signed-off-by: Kuniyuki Iwashima kuniyu@amazon.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- net/unix/af_unix.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-)
--- a/net/unix/af_unix.c +++ b/net/unix/af_unix.c @@ -2008,6 +2008,7 @@ static ssize_t unix_stream_sendpage(stru
if (false) { alloc_skb: + spin_unlock(&other->sk_receive_queue.lock); unix_state_unlock(other); mutex_unlock(&unix_sk(other)->iolock); newskb = sock_alloc_send_pskb(sk, 0, 0, flags & MSG_DONTWAIT, @@ -2047,6 +2048,7 @@ alloc_skb: init_scm = false; }
+ spin_lock(&other->sk_receive_queue.lock); skb = skb_peek_tail(&other->sk_receive_queue); if (tail && tail == skb) { skb = newskb; @@ -2077,14 +2079,11 @@ alloc_skb: refcount_add(size, &sk->sk_wmem_alloc);
if (newskb) { - err = unix_scm_to_skb(&scm, skb, false); - if (err) - goto err_state_unlock; - spin_lock(&other->sk_receive_queue.lock); + unix_scm_to_skb(&scm, skb, false); __skb_queue_tail(&other->sk_receive_queue, newskb); - spin_unlock(&other->sk_receive_queue.lock); }
+ spin_unlock(&other->sk_receive_queue.lock); unix_state_unlock(other); mutex_unlock(&unix_sk(other)->iolock);
From: Jason Wang jasowang@redhat.com
commit 51b813176f098ff61bd2833f627f5319ead098a5 upstream.
Commit 25266128fe16 ("virtio-net: fix race between set queues and probe") tries to fix the race between set queues and probe by calling _virtnet_set_queues() before DRIVER_OK is set. This violates virtio spec. Fixing this by setting queues after virtio_device_ready().
Note that rtnl needs to be held for userspace requests to change the number of queues. So we are serialized in this way.
Fixes: 25266128fe16 ("virtio-net: fix race between set queues and probe") Reported-by: Dragos Tatulea dtatulea@nvidia.com Acked-by: Michael S. Tsirkin mst@redhat.com Signed-off-by: Jason Wang jasowang@redhat.com Signed-off-by: David S. Miller davem@davemloft.net Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/net/virtio_net.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
--- a/drivers/net/virtio_net.c +++ b/drivers/net/virtio_net.c @@ -3220,8 +3220,6 @@ static int virtnet_probe(struct virtio_d } }
- _virtnet_set_queues(vi, vi->curr_queue_pairs); - /* serialize netdev register + virtio_device_ready() with ndo_open() */ rtnl_lock();
@@ -3234,6 +3232,8 @@ static int virtnet_probe(struct virtio_d
virtio_device_ready(vdev);
+ _virtnet_set_queues(vi, vi->curr_queue_pairs); + rtnl_unlock();
err = virtnet_cpu_notif_add(vi);
From: Jason Xing kernelxing@tencent.com
commit e4dd0d3a2f64b8bd8029ec70f52bdbebd0644408 upstream.
In the real workload, I encountered an issue which could cause the RTO timer to retransmit the skb per 1ms with linear option enabled. The amount of lost-retransmitted skbs can go up to 1000+ instantly.
The root cause is that if the icsk_rto happens to be zero in the 6th round (which is the TCP_THIN_LINEAR_RETRIES value), then it will always be zero due to the changed calculation method in tcp_retransmit_timer() as follows:
icsk->icsk_rto = min(icsk->icsk_rto << 1, TCP_RTO_MAX);
Above line could be converted to icsk->icsk_rto = min(0 << 1, TCP_RTO_MAX) = 0
Therefore, the timer expires so quickly without any doubt.
I read through the RFC 6298 and found that the RTO value can be rounded up to a certain value, in Linux, say TCP_RTO_MIN as default, which is regarded as the lower bound in this patch as suggested by Eric.
Fixes: 36e31b0af587 ("net: TCP thin linear timeouts") Suggested-by: Eric Dumazet edumazet@google.com Signed-off-by: Jason Xing kernelxing@tencent.com Reviewed-by: Eric Dumazet edumazet@google.com Signed-off-by: David S. Miller davem@davemloft.net Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- net/ipv4/tcp_timer.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
--- a/net/ipv4/tcp_timer.c +++ b/net/ipv4/tcp_timer.c @@ -582,7 +582,9 @@ out_reset_timer: tcp_stream_is_thin(tp) && icsk->icsk_retransmits <= TCP_THIN_LINEAR_RETRIES) { icsk->icsk_backoff = 0; - icsk->icsk_rto = min(__tcp_set_rto(tp), TCP_RTO_MAX); + icsk->icsk_rto = clamp(__tcp_set_rto(tp), + tcp_rto_min(sk), + TCP_RTO_MAX); } else { /* Use normal (exponential) backoff */ icsk->icsk_rto = min(icsk->icsk_rto << 1, TCP_RTO_MAX);
From: Yangtao Li frank.li@vivo.com
commit 58abdd80b93b09023ca03007b608685c41e3a289 upstream.
The order of function calls in sdhci_f_sdh30_remove is wrong, let's call sdhci_pltfm_unregister first.
Cc: Uwe Kleine-König u.kleine-koenig@pengutronix.de Fixes: 5def5c1c15bf ("mmc: sdhci-f-sdh30: Replace with sdhci_pltfm") Signed-off-by: Yangtao Li frank.li@vivo.com Reported-by: Uwe Kleine-König u.kleine-koenig@pengutronix.de Acked-by: Uwe Kleine-König u.kleine-koenig@pengutronix.de Acked-by: Adrian Hunter adrian.hunter@intel.com Cc: stable@vger.kernel.org Link: https://lore.kernel.org/r/20230727070051.17778-62-frank.li@vivo.com Signed-off-by: Ulf Hansson ulf.hansson@linaro.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/mmc/host/sdhci_f_sdh30.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-)
--- a/drivers/mmc/host/sdhci_f_sdh30.c +++ b/drivers/mmc/host/sdhci_f_sdh30.c @@ -188,12 +188,14 @@ static int sdhci_f_sdh30_remove(struct p { struct sdhci_host *host = platform_get_drvdata(pdev); struct f_sdhost_priv *priv = sdhci_f_sdhost_priv(host); - - clk_disable_unprepare(priv->clk_iface); - clk_disable_unprepare(priv->clk); + struct clk *clk_iface = priv->clk_iface; + struct clk *clk = priv->clk;
sdhci_pltfm_unregister(pdev);
+ clk_disable_unprepare(clk_iface); + clk_disable_unprepare(clk); + return 0; }
From: Peter Zijlstra peterz@infradead.org
commit 77f67119004296a9b2503b377d610e08b08afc2a upstream.
Commit
fb3bd914b3ec ("x86/srso: Add a Speculative RAS Overflow mitigation")
reimplemented __x86_return_thunk with a mix of SYM_FUNC_START and SYM_CODE_END, this is not a sane combination.
Since nothing should ever actually 'CALL' this, make it consistently CODE.
Fixes: fb3bd914b3ec ("x86/srso: Add a Speculative RAS Overflow mitigation") Signed-off-by: Peter Zijlstra (Intel) peterz@infradead.org Signed-off-by: Borislav Petkov (AMD) bp@alien8.de Link: https://lore.kernel.org/r/20230814121148.571027074@infradead.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- arch/x86/lib/retpoline.S | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
--- a/arch/x86/lib/retpoline.S +++ b/arch/x86/lib/retpoline.S @@ -204,7 +204,9 @@ SYM_CODE_END(srso_safe_ret) SYM_FUNC_END(srso_untrain_ret) __EXPORT_THUNK(srso_untrain_ret)
-SYM_FUNC_START(__x86_return_thunk) +SYM_CODE_START(__x86_return_thunk) + UNWIND_HINT_FUNC + ANNOTATE_NOENDBR ALTERNATIVE_2 "jmp __ret", "call srso_safe_ret", X86_FEATURE_SRSO, \ "call srso_safe_ret_alias", X86_FEATURE_SRSO_ALIAS int3
From: Peter Zijlstra peterz@infradead.org
commit af023ef335f13c8b579298fc432daeef609a9e60 upstream.
vmlinux.o: warning: objtool: srso_untrain_ret() falls through to next function __x86_return_skl() vmlinux.o: warning: objtool: __x86_return_thunk() falls through to next function __x86_return_skl()
This is because these functions (can) end with CALL, which objtool does not consider a terminating instruction. Therefore, replace the INT3 instruction (which is a non-fatal trap) with UD2 (which is a fatal-trap).
This indicates execution will not continue past this point.
Fixes: fb3bd914b3ec ("x86/srso: Add a Speculative RAS Overflow mitigation") Signed-off-by: Peter Zijlstra (Intel) peterz@infradead.org Signed-off-by: Borislav Petkov (AMD) bp@alien8.de Link: https://lore.kernel.org/r/20230814121148.637802730@infradead.org Signed-off-by: Sasha Levin sashal@kernel.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- arch/x86/lib/retpoline.S | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
--- a/arch/x86/lib/retpoline.S +++ b/arch/x86/lib/retpoline.S @@ -199,7 +199,7 @@ SYM_INNER_LABEL(srso_safe_ret, SYM_L_GLO int3 lfence call srso_safe_ret - int3 + ud2 SYM_CODE_END(srso_safe_ret) SYM_FUNC_END(srso_untrain_ret) __EXPORT_THUNK(srso_untrain_ret) @@ -209,7 +209,7 @@ SYM_CODE_START(__x86_return_thunk) ANNOTATE_NOENDBR ALTERNATIVE_2 "jmp __ret", "call srso_safe_ret", X86_FEATURE_SRSO, \ "call srso_safe_ret_alias", X86_FEATURE_SRSO_ALIAS - int3 + ud2 SYM_CODE_END(__x86_return_thunk) EXPORT_SYMBOL(__x86_return_thunk)
From: Peter Zijlstra peterz@infradead.org
commit 095b8303f3835c68ac4a8b6d754ca1c3b6230711 upstream.
There is infrastructure to rewrite return thunks to point to any random thunk one desires, unwrap that from CALL_THUNKS, which up to now was the sole user of that.
[ bp: Make the thunks visible on 32-bit and add ifdeffery for the 32-bit builds. ]
Signed-off-by: Peter Zijlstra (Intel) peterz@infradead.org Signed-off-by: Borislav Petkov (AMD) bp@alien8.de Link: https://lore.kernel.org/r/20230814121148.775293785@infradead.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- arch/x86/include/asm/nospec-branch.h | 5 +++++ arch/x86/kernel/cpu/bugs.c | 2 ++ 2 files changed, 7 insertions(+)
--- a/arch/x86/include/asm/nospec-branch.h +++ b/arch/x86/include/asm/nospec-branch.h @@ -195,7 +195,12 @@ _ASM_PTR " 999b\n\t" \ ".popsection\n\t"
+#ifdef CONFIG_RETHUNK extern void __x86_return_thunk(void); +#else +static inline void __x86_return_thunk(void) {} +#endif + extern void zen_untrain_ret(void); extern void srso_untrain_ret(void); extern void srso_untrain_ret_alias(void); --- a/arch/x86/kernel/cpu/bugs.c +++ b/arch/x86/kernel/cpu/bugs.c @@ -61,6 +61,8 @@ EXPORT_SYMBOL_GPL(x86_pred_cmd);
static DEFINE_MUTEX(spec_ctrl_mutex);
+void (*x86_return_thunk)(void) __ro_after_init = &__x86_return_thunk; + /* Update SPEC_CTRL MSR and its cached copy unconditionally */ static void update_spec_ctrl(u64 val) {
From: Josh Poimboeuf jpoimboe@redhat.com
[ Upstream commit e028c4f7ac7ca8c96126fe46c54ab3d56ffe6a66 ]
Add a CONFIG_FRAME_POINTER-specific version of STACK_FRAME_NON_STANDARD() for the case where a function is intentionally missing frame pointer setup, but otherwise needs objtool/ORC coverage when frame pointers are disabled.
Link: https://lkml.kernel.org/r/163163047364.489837.17377799909553689661.stgit@dev...
Signed-off-by: Josh Poimboeuf jpoimboe@redhat.com Reviewed-by: Masami Hiramatsu mhiramat@kernel.org Tested-by: Masami Hiramatsu mhiramat@kernel.org Signed-off-by: Masami Hiramatsu mhiramat@kernel.org Signed-off-by: Steven Rostedt (VMware) rostedt@goodmis.org Stable-dep-of: c8c301abeae5 ("x86/ibt: Add ANNOTATE_NOENDBR") Signed-off-by: Sasha Levin sashal@kernel.org --- include/linux/objtool.h | 12 ++++++++++++ tools/include/linux/objtool.h | 12 ++++++++++++ 2 files changed, 24 insertions(+)
--- a/include/linux/objtool.h +++ b/include/linux/objtool.h @@ -71,6 +71,17 @@ struct unwind_hint { static void __used __section(".discard.func_stack_frame_non_standard") \ *__func_stack_frame_non_standard_##func = func
+/* + * STACK_FRAME_NON_STANDARD_FP() is a frame-pointer-specific function ignore + * for the case where a function is intentionally missing frame pointer setup, + * but otherwise needs objtool/ORC coverage when frame pointers are disabled. + */ +#ifdef CONFIG_FRAME_POINTER +#define STACK_FRAME_NON_STANDARD_FP(func) STACK_FRAME_NON_STANDARD(func) +#else +#define STACK_FRAME_NON_STANDARD_FP(func) +#endif + #else /* __ASSEMBLY__ */
/* @@ -126,6 +137,7 @@ struct unwind_hint { #define UNWIND_HINT(sp_reg, sp_offset, type, end) \ "\n\t" #define STACK_FRAME_NON_STANDARD(func) +#define STACK_FRAME_NON_STANDARD_FP(func) #else #define ANNOTATE_INTRA_FUNCTION_CALL .macro UNWIND_HINT type:req sp_reg=0 sp_offset=0 end=0 --- a/tools/include/linux/objtool.h +++ b/tools/include/linux/objtool.h @@ -71,6 +71,17 @@ struct unwind_hint { static void __used __section(".discard.func_stack_frame_non_standard") \ *__func_stack_frame_non_standard_##func = func
+/* + * STACK_FRAME_NON_STANDARD_FP() is a frame-pointer-specific function ignore + * for the case where a function is intentionally missing frame pointer setup, + * but otherwise needs objtool/ORC coverage when frame pointers are disabled. + */ +#ifdef CONFIG_FRAME_POINTER +#define STACK_FRAME_NON_STANDARD_FP(func) STACK_FRAME_NON_STANDARD(func) +#else +#define STACK_FRAME_NON_STANDARD_FP(func) +#endif + #else /* __ASSEMBLY__ */
/* @@ -126,6 +137,7 @@ struct unwind_hint { #define UNWIND_HINT(sp_reg, sp_offset, type, end) \ "\n\t" #define STACK_FRAME_NON_STANDARD(func) +#define STACK_FRAME_NON_STANDARD_FP(func) #else #define ANNOTATE_INTRA_FUNCTION_CALL .macro UNWIND_HINT type:req sp_reg=0 sp_offset=0 end=0
From: Peter Zijlstra peterz@infradead.org
[ Upstream commit c8c301abeae58ec756b8fcb2178a632bd3c9e284 ]
In order to have objtool warn about code references to !ENDBR instruction, we need an annotation to allow this for non-control-flow instances -- consider text range checks, text patching, or return trampolines etc.
Signed-off-by: Peter Zijlstra (Intel) peterz@infradead.org Reviewed-by: Kees Cook keescook@chromium.org Acked-by: Josh Poimboeuf jpoimboe@redhat.com Link: https://lore.kernel.org/r/20220308154317.578968224@infradead.org Signed-off-by: Sasha Levin sashal@kernel.org --- include/linux/objtool.h | 16 ++++++++++++++++ tools/include/linux/objtool.h | 16 ++++++++++++++++ 2 files changed, 32 insertions(+)
--- a/include/linux/objtool.h +++ b/include/linux/objtool.h @@ -82,6 +82,12 @@ struct unwind_hint { #define STACK_FRAME_NON_STANDARD_FP(func) #endif
+#define ANNOTATE_NOENDBR \ + "986: \n\t" \ + ".pushsection .discard.noendbr\n\t" \ + _ASM_PTR " 986b\n\t" \ + ".popsection\n\t" + #else /* __ASSEMBLY__ */
/* @@ -128,6 +134,13 @@ struct unwind_hint { .popsection .endm
+.macro ANNOTATE_NOENDBR +.Lhere_@: + .pushsection .discard.noendbr + .quad .Lhere_@ + .popsection +.endm + #endif /* __ASSEMBLY__ */
#else /* !CONFIG_STACK_VALIDATION */ @@ -138,10 +151,13 @@ struct unwind_hint { "\n\t" #define STACK_FRAME_NON_STANDARD(func) #define STACK_FRAME_NON_STANDARD_FP(func) +#define ANNOTATE_NOENDBR #else #define ANNOTATE_INTRA_FUNCTION_CALL .macro UNWIND_HINT type:req sp_reg=0 sp_offset=0 end=0 .endm +.macro ANNOTATE_NOENDBR +.endm #endif
#endif /* CONFIG_STACK_VALIDATION */ --- a/tools/include/linux/objtool.h +++ b/tools/include/linux/objtool.h @@ -82,6 +82,12 @@ struct unwind_hint { #define STACK_FRAME_NON_STANDARD_FP(func) #endif
+#define ANNOTATE_NOENDBR \ + "986: \n\t" \ + ".pushsection .discard.noendbr\n\t" \ + _ASM_PTR " 986b\n\t" \ + ".popsection\n\t" + #else /* __ASSEMBLY__ */
/* @@ -128,6 +134,13 @@ struct unwind_hint { .popsection .endm
+.macro ANNOTATE_NOENDBR +.Lhere_@: + .pushsection .discard.noendbr + .quad .Lhere_@ + .popsection +.endm + #endif /* __ASSEMBLY__ */
#else /* !CONFIG_STACK_VALIDATION */ @@ -138,10 +151,13 @@ struct unwind_hint { "\n\t" #define STACK_FRAME_NON_STANDARD(func) #define STACK_FRAME_NON_STANDARD_FP(func) +#define ANNOTATE_NOENDBR #else #define ANNOTATE_INTRA_FUNCTION_CALL .macro UNWIND_HINT type:req sp_reg=0 sp_offset=0 end=0 .endm +.macro ANNOTATE_NOENDBR +.endm #endif
#endif /* CONFIG_STACK_VALIDATION */
From: Peter Zijlstra peterz@infradead.org
commit d43490d0ab824023e11d0b57d0aeec17a6e0ca13 upstream.
Use the existing configurable return thunk. There is absolute no justification for having created this __x86_return_thunk alternative.
To clarify, the whole thing looks like:
Zen3/4 does:
srso_alias_untrain_ret: nop2 lfence jmp srso_alias_return_thunk int3
srso_alias_safe_ret: // aliasses srso_alias_untrain_ret just so add $8, %rsp ret int3
srso_alias_return_thunk: call srso_alias_safe_ret ud2
While Zen1/2 does:
srso_untrain_ret: movabs $foo, %rax lfence call srso_safe_ret (jmp srso_return_thunk ?) int3
srso_safe_ret: // embedded in movabs instruction add $8,%rsp ret int3
srso_return_thunk: call srso_safe_ret ud2
While retbleed does:
zen_untrain_ret: test $0xcc, %bl lfence jmp zen_return_thunk int3
zen_return_thunk: // embedded in the test instruction ret int3
Where Zen1/2 flush the BTB entry using the instruction decoder trick (test,movabs) Zen3/4 use BTB aliasing. SRSO adds a return sequence (srso_safe_ret()) which forces the function return instruction to speculate into a trap (UD2). This RET will then mispredict and execution will continue at the return site read from the top of the stack.
Pick one of three options at boot (evey function can only ever return once).
[ bp: Fixup commit message uarch details and add them in a comment in the code too. Add a comment about the srso_select_mitigation() dependency on retbleed_select_mitigation(). Add moar ifdeffery for 32-bit builds. Add a dummy srso_untrain_ret_alias() definition for 32-bit alternatives needing the symbol. ]
Fixes: fb3bd914b3ec ("x86/srso: Add a Speculative RAS Overflow mitigation") Signed-off-by: Peter Zijlstra (Intel) peterz@infradead.org Signed-off-by: Borislav Petkov (AMD) bp@alien8.de Link: https://lore.kernel.org/r/20230814121148.842775684@infradead.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- arch/x86/include/asm/nospec-branch.h | 5 +++ arch/x86/kernel/cpu/bugs.c | 17 ++++++++-- arch/x86/kernel/vmlinux.lds.S | 2 - arch/x86/lib/retpoline.S | 58 +++++++++++++++++++++++++---------- tools/objtool/arch/x86/decode.c | 2 - 5 files changed, 63 insertions(+), 21 deletions(-)
--- a/arch/x86/include/asm/nospec-branch.h +++ b/arch/x86/include/asm/nospec-branch.h @@ -201,9 +201,14 @@ extern void __x86_return_thunk(void); static inline void __x86_return_thunk(void) {} #endif
+extern void zen_return_thunk(void); +extern void srso_return_thunk(void); +extern void srso_alias_return_thunk(void); + extern void zen_untrain_ret(void); extern void srso_untrain_ret(void); extern void srso_untrain_ret_alias(void); + extern void entry_ibpb(void);
#ifdef CONFIG_RETPOLINE --- a/arch/x86/kernel/cpu/bugs.c +++ b/arch/x86/kernel/cpu/bugs.c @@ -157,8 +157,13 @@ void __init cpu_select_mitigations(void) l1tf_select_mitigation(); md_clear_select_mitigation(); srbds_select_mitigation(); - gds_select_mitigation(); + + /* + * srso_select_mitigation() depends and must run after + * retbleed_select_mitigation(). + */ srso_select_mitigation(); + gds_select_mitigation(); }
/* @@ -978,6 +983,9 @@ do_cmd_auto: setup_force_cpu_cap(X86_FEATURE_RETHUNK); setup_force_cpu_cap(X86_FEATURE_UNRET);
+ if (IS_ENABLED(CONFIG_RETHUNK)) + x86_return_thunk = zen_return_thunk; + if (boot_cpu_data.x86_vendor != X86_VENDOR_AMD && boot_cpu_data.x86_vendor != X86_VENDOR_HYGON) pr_err(RETBLEED_UNTRAIN_MSG); @@ -2352,10 +2360,13 @@ static void __init srso_select_mitigatio */ setup_force_cpu_cap(X86_FEATURE_RETHUNK);
- if (boot_cpu_data.x86 == 0x19) + if (boot_cpu_data.x86 == 0x19) { setup_force_cpu_cap(X86_FEATURE_SRSO_ALIAS); - else + x86_return_thunk = srso_alias_return_thunk; + } else { setup_force_cpu_cap(X86_FEATURE_SRSO); + x86_return_thunk = srso_return_thunk; + } srso_mitigation = SRSO_MITIGATION_SAFE_RET; } else { pr_err("WARNING: kernel not compiled with CPU_SRSO.\n"); --- a/arch/x86/kernel/vmlinux.lds.S +++ b/arch/x86/kernel/vmlinux.lds.S @@ -518,7 +518,7 @@ INIT_PER_CPU(irq_stack_backing_store); #endif
#ifdef CONFIG_RETHUNK -. = ASSERT((__ret & 0x3f) == 0, "__ret not cacheline-aligned"); +. = ASSERT((zen_return_thunk & 0x3f) == 0, "zen_return_thunk not cacheline-aligned"); . = ASSERT((srso_safe_ret & 0x3f) == 0, "srso_safe_ret not cacheline-aligned"); #endif
--- a/arch/x86/lib/retpoline.S +++ b/arch/x86/lib/retpoline.S @@ -93,21 +93,26 @@ SYM_CODE_END(__x86_indirect_thunk_array) .section .text.__x86.rethunk_untrain
SYM_START(srso_untrain_ret_alias, SYM_L_GLOBAL, SYM_A_NONE) + UNWIND_HINT_FUNC ASM_NOP2 lfence - jmp __x86_return_thunk + jmp srso_alias_return_thunk SYM_FUNC_END(srso_untrain_ret_alias) __EXPORT_THUNK(srso_untrain_ret_alias)
.section .text.__x86.rethunk_safe +#else +/* dummy definition for alternatives */ +SYM_START(srso_untrain_ret_alias, SYM_L_GLOBAL, SYM_A_NONE) + ANNOTATE_UNRET_SAFE + ret + int3 +SYM_FUNC_END(srso_untrain_ret_alias) #endif
-/* Needs a definition for the __x86_return_thunk alternative below. */ SYM_START(srso_safe_ret_alias, SYM_L_GLOBAL, SYM_A_NONE) -#ifdef CONFIG_CPU_SRSO add $8, %_ASM_SP UNWIND_HINT_FUNC -#endif ANNOTATE_UNRET_SAFE ret int3 @@ -115,9 +120,16 @@ SYM_FUNC_END(srso_safe_ret_alias)
.section .text.__x86.return_thunk
+SYM_CODE_START(srso_alias_return_thunk) + UNWIND_HINT_FUNC + ANNOTATE_NOENDBR + call srso_safe_ret_alias + ud2 +SYM_CODE_END(srso_alias_return_thunk) + /* * Safety details here pertain to the AMD Zen{1,2} microarchitecture: - * 1) The RET at __x86_return_thunk must be on a 64 byte boundary, for + * 1) The RET at zen_return_thunk must be on a 64 byte boundary, for * alignment within the BTB. * 2) The instruction at zen_untrain_ret must contain, and not * end with, the 0xc3 byte of the RET. @@ -125,7 +137,7 @@ SYM_FUNC_END(srso_safe_ret_alias) * from re-poisioning the BTB prediction. */ .align 64 - .skip 64 - (__ret - zen_untrain_ret), 0xcc + .skip 64 - (zen_return_thunk - zen_untrain_ret), 0xcc SYM_FUNC_START_NOALIGN(zen_untrain_ret);
/* @@ -133,16 +145,16 @@ SYM_FUNC_START_NOALIGN(zen_untrain_ret); * * TEST $0xcc, %bl * LFENCE - * JMP __x86_return_thunk + * JMP zen_return_thunk * * Executing the TEST instruction has a side effect of evicting any BTB * prediction (potentially attacker controlled) attached to the RET, as - * __x86_return_thunk + 1 isn't an instruction boundary at the moment. + * zen_return_thunk + 1 isn't an instruction boundary at the moment. */ .byte 0xf6
/* - * As executed from __x86_return_thunk, this is a plain RET. + * As executed from zen_return_thunk, this is a plain RET. * * As part of the TEST above, RET is the ModRM byte, and INT3 the imm8. * @@ -154,13 +166,13 @@ SYM_FUNC_START_NOALIGN(zen_untrain_ret); * With SMT enabled and STIBP active, a sibling thread cannot poison * RET's prediction to a type of its choice, but can evict the * prediction due to competitive sharing. If the prediction is - * evicted, __x86_return_thunk will suffer Straight Line Speculation + * evicted, zen_return_thunk will suffer Straight Line Speculation * which will be contained safely by the INT3. */ -SYM_INNER_LABEL(__ret, SYM_L_GLOBAL) +SYM_INNER_LABEL(zen_return_thunk, SYM_L_GLOBAL) ret int3 -SYM_CODE_END(__ret) +SYM_CODE_END(zen_return_thunk)
/* * Ensure the TEST decoding / BTB invalidation is complete. @@ -171,7 +183,7 @@ SYM_CODE_END(__ret) * Jump back and execute the RET in the middle of the TEST instruction. * INT3 is for SLS protection. */ - jmp __ret + jmp zen_return_thunk int3 SYM_FUNC_END(zen_untrain_ret) __EXPORT_THUNK(zen_untrain_ret) @@ -191,12 +203,19 @@ __EXPORT_THUNK(zen_untrain_ret) SYM_START(srso_untrain_ret, SYM_L_GLOBAL, SYM_A_NONE) .byte 0x48, 0xb8
+/* + * This forces the function return instruction to speculate into a trap + * (UD2 in srso_return_thunk() below). This RET will then mispredict + * and execution will continue at the return site read from the top of + * the stack. + */ SYM_INNER_LABEL(srso_safe_ret, SYM_L_GLOBAL) add $8, %_ASM_SP ret int3 int3 int3 + /* end of movabs */ lfence call srso_safe_ret ud2 @@ -204,12 +223,19 @@ SYM_CODE_END(srso_safe_ret) SYM_FUNC_END(srso_untrain_ret) __EXPORT_THUNK(srso_untrain_ret)
-SYM_CODE_START(__x86_return_thunk) +SYM_CODE_START(srso_return_thunk) UNWIND_HINT_FUNC ANNOTATE_NOENDBR - ALTERNATIVE_2 "jmp __ret", "call srso_safe_ret", X86_FEATURE_SRSO, \ - "call srso_safe_ret_alias", X86_FEATURE_SRSO_ALIAS + call srso_safe_ret ud2 +SYM_CODE_END(srso_return_thunk) + +SYM_CODE_START(__x86_return_thunk) + UNWIND_HINT_FUNC + ANNOTATE_NOENDBR + ANNOTATE_UNRET_SAFE + ret + int3 SYM_CODE_END(__x86_return_thunk) EXPORT_SYMBOL(__x86_return_thunk)
--- a/tools/objtool/arch/x86/decode.c +++ b/tools/objtool/arch/x86/decode.c @@ -655,5 +655,5 @@ bool arch_is_rethunk(struct symbol *sym) return !strcmp(sym->name, "__x86_return_thunk") || !strcmp(sym->name, "srso_untrain_ret") || !strcmp(sym->name, "srso_safe_ret") || - !strcmp(sym->name, "__ret"); + !strcmp(sym->name, "zen_return_thunk"); }
From: Peter Zijlstra peterz@infradead.org
commit d025b7bac07a6e90b6b98b487f88854ad9247c39 upstream.
Rename the original retbleed return thunk and untrain_ret to retbleed_return_thunk() and retbleed_untrain_ret().
No functional changes.
Suggested-by: Josh Poimboeuf jpoimboe@kernel.org Signed-off-by: Peter Zijlstra (Intel) peterz@infradead.org Signed-off-by: Borislav Petkov (AMD) bp@alien8.de Link: https://lore.kernel.org/r/20230814121148.909378169@infradead.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- arch/x86/include/asm/nospec-branch.h | 8 ++++---- arch/x86/kernel/cpu/bugs.c | 2 +- arch/x86/kernel/vmlinux.lds.S | 2 +- arch/x86/lib/retpoline.S | 30 +++++++++++++++--------------- tools/objtool/arch/x86/decode.c | 2 +- tools/objtool/check.c | 2 +- 6 files changed, 23 insertions(+), 23 deletions(-)
--- a/arch/x86/include/asm/nospec-branch.h +++ b/arch/x86/include/asm/nospec-branch.h @@ -156,7 +156,7 @@ .endm
#ifdef CONFIG_CPU_UNRET_ENTRY -#define CALL_ZEN_UNTRAIN_RET "call zen_untrain_ret" +#define CALL_ZEN_UNTRAIN_RET "call retbleed_untrain_ret" #else #define CALL_ZEN_UNTRAIN_RET "" #endif @@ -166,7 +166,7 @@ * return thunk isn't mapped into the userspace tables (then again, AMD * typically has NO_MELTDOWN). * - * While zen_untrain_ret() doesn't clobber anything but requires stack, + * While retbleed_untrain_ret() doesn't clobber anything but requires stack, * entry_ibpb() will clobber AX, CX, DX. * * As such, this must be placed after every *SWITCH_TO_KERNEL_CR3 at a point @@ -201,11 +201,11 @@ extern void __x86_return_thunk(void); static inline void __x86_return_thunk(void) {} #endif
-extern void zen_return_thunk(void); +extern void retbleed_return_thunk(void); extern void srso_return_thunk(void); extern void srso_alias_return_thunk(void);
-extern void zen_untrain_ret(void); +extern void retbleed_untrain_ret(void); extern void srso_untrain_ret(void); extern void srso_untrain_ret_alias(void);
--- a/arch/x86/kernel/cpu/bugs.c +++ b/arch/x86/kernel/cpu/bugs.c @@ -984,7 +984,7 @@ do_cmd_auto: setup_force_cpu_cap(X86_FEATURE_UNRET);
if (IS_ENABLED(CONFIG_RETHUNK)) - x86_return_thunk = zen_return_thunk; + x86_return_thunk = retbleed_return_thunk;
if (boot_cpu_data.x86_vendor != X86_VENDOR_AMD && boot_cpu_data.x86_vendor != X86_VENDOR_HYGON) --- a/arch/x86/kernel/vmlinux.lds.S +++ b/arch/x86/kernel/vmlinux.lds.S @@ -518,7 +518,7 @@ INIT_PER_CPU(irq_stack_backing_store); #endif
#ifdef CONFIG_RETHUNK -. = ASSERT((zen_return_thunk & 0x3f) == 0, "zen_return_thunk not cacheline-aligned"); +. = ASSERT((retbleed_return_thunk & 0x3f) == 0, "retbleed_return_thunk not cacheline-aligned"); . = ASSERT((srso_safe_ret & 0x3f) == 0, "srso_safe_ret not cacheline-aligned"); #endif
--- a/arch/x86/lib/retpoline.S +++ b/arch/x86/lib/retpoline.S @@ -129,32 +129,32 @@ SYM_CODE_END(srso_alias_return_thunk)
/* * Safety details here pertain to the AMD Zen{1,2} microarchitecture: - * 1) The RET at zen_return_thunk must be on a 64 byte boundary, for + * 1) The RET at retbleed_return_thunk must be on a 64 byte boundary, for * alignment within the BTB. - * 2) The instruction at zen_untrain_ret must contain, and not + * 2) The instruction at retbleed_untrain_ret must contain, and not * end with, the 0xc3 byte of the RET. * 3) STIBP must be enabled, or SMT disabled, to prevent the sibling thread * from re-poisioning the BTB prediction. */ .align 64 - .skip 64 - (zen_return_thunk - zen_untrain_ret), 0xcc -SYM_FUNC_START_NOALIGN(zen_untrain_ret); + .skip 64 - (retbleed_return_thunk - retbleed_untrain_ret), 0xcc +SYM_FUNC_START_NOALIGN(retbleed_untrain_ret);
/* - * As executed from zen_untrain_ret, this is: + * As executed from retbleed_untrain_ret, this is: * * TEST $0xcc, %bl * LFENCE - * JMP zen_return_thunk + * JMP retbleed_return_thunk * * Executing the TEST instruction has a side effect of evicting any BTB * prediction (potentially attacker controlled) attached to the RET, as - * zen_return_thunk + 1 isn't an instruction boundary at the moment. + * retbleed_return_thunk + 1 isn't an instruction boundary at the moment. */ .byte 0xf6
/* - * As executed from zen_return_thunk, this is a plain RET. + * As executed from retbleed_return_thunk, this is a plain RET. * * As part of the TEST above, RET is the ModRM byte, and INT3 the imm8. * @@ -166,13 +166,13 @@ SYM_FUNC_START_NOALIGN(zen_untrain_ret); * With SMT enabled and STIBP active, a sibling thread cannot poison * RET's prediction to a type of its choice, but can evict the * prediction due to competitive sharing. If the prediction is - * evicted, zen_return_thunk will suffer Straight Line Speculation + * evicted, retbleed_return_thunk will suffer Straight Line Speculation * which will be contained safely by the INT3. */ -SYM_INNER_LABEL(zen_return_thunk, SYM_L_GLOBAL) +SYM_INNER_LABEL(retbleed_return_thunk, SYM_L_GLOBAL) ret int3 -SYM_CODE_END(zen_return_thunk) +SYM_CODE_END(retbleed_return_thunk)
/* * Ensure the TEST decoding / BTB invalidation is complete. @@ -183,13 +183,13 @@ SYM_CODE_END(zen_return_thunk) * Jump back and execute the RET in the middle of the TEST instruction. * INT3 is for SLS protection. */ - jmp zen_return_thunk + jmp retbleed_return_thunk int3 -SYM_FUNC_END(zen_untrain_ret) -__EXPORT_THUNK(zen_untrain_ret) +SYM_FUNC_END(retbleed_untrain_ret) +__EXPORT_THUNK(retbleed_untrain_ret)
/* - * SRSO untraining sequence for Zen1/2, similar to zen_untrain_ret() + * SRSO untraining sequence for Zen1/2, similar to retbleed_untrain_ret() * above. On kernel entry, srso_untrain_ret() is executed which is a * * movabs $0xccccccc308c48348,%rax --- a/tools/objtool/arch/x86/decode.c +++ b/tools/objtool/arch/x86/decode.c @@ -655,5 +655,5 @@ bool arch_is_rethunk(struct symbol *sym) return !strcmp(sym->name, "__x86_return_thunk") || !strcmp(sym->name, "srso_untrain_ret") || !strcmp(sym->name, "srso_safe_ret") || - !strcmp(sym->name, "zen_return_thunk"); + !strcmp(sym->name, "retbleed_return_thunk"); } --- a/tools/objtool/check.c +++ b/tools/objtool/check.c @@ -1165,7 +1165,7 @@ static int add_jump_destinations(struct continue;
/* - * This is a special case for zen_untrain_ret(). + * This is a special case for retbleed_untrain_ret(). * It jumps to __x86_return_thunk(), but objtool * can't find the thunk's starting RET * instruction, because the RET is also in the
From: Peter Zijlstra peterz@infradead.org
commit 42be649dd1f2eee6b1fb185f1a231b9494cf095f upstream.
For a more consistent namespace.
[ bp: Fixup names in the doc too. ]
Signed-off-by: Peter Zijlstra (Intel) peterz@infradead.org Signed-off-by: Borislav Petkov (AMD) bp@alien8.de Link: https://lore.kernel.org/r/20230814121148.976236447@infradead.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- Documentation/admin-guide/hw-vuln/srso.rst | 4 ++-- arch/x86/include/asm/nospec-branch.h | 4 ++-- arch/x86/kernel/vmlinux.lds.S | 8 ++++---- arch/x86/lib/retpoline.S | 26 +++++++++++++------------- 4 files changed, 21 insertions(+), 21 deletions(-)
--- a/Documentation/admin-guide/hw-vuln/srso.rst +++ b/Documentation/admin-guide/hw-vuln/srso.rst @@ -124,8 +124,8 @@ sequence. To ensure the safety of this mitigation, the kernel must ensure that the safe return sequence is itself free from attacker interference. In Zen3 and Zen4, this is accomplished by creating a BTB alias between the -untraining function srso_untrain_ret_alias() and the safe return -function srso_safe_ret_alias() which results in evicting a potentially +untraining function srso_alias_untrain_ret() and the safe return +function srso_alias_safe_ret() which results in evicting a potentially poisoned BTB entry and using that safe one for all function returns.
In older Zen1 and Zen2, this is accomplished using a reinterpretation --- a/arch/x86/include/asm/nospec-branch.h +++ b/arch/x86/include/asm/nospec-branch.h @@ -183,7 +183,7 @@
#ifdef CONFIG_CPU_SRSO ALTERNATIVE_2 "", "call srso_untrain_ret", X86_FEATURE_SRSO, \ - "call srso_untrain_ret_alias", X86_FEATURE_SRSO_ALIAS + "call srso_alias_untrain_ret", X86_FEATURE_SRSO_ALIAS #endif .endm
@@ -207,7 +207,7 @@ extern void srso_alias_return_thunk(void
extern void retbleed_untrain_ret(void); extern void srso_untrain_ret(void); -extern void srso_untrain_ret_alias(void); +extern void srso_alias_untrain_ret(void);
extern void entry_ibpb(void);
--- a/arch/x86/kernel/vmlinux.lds.S +++ b/arch/x86/kernel/vmlinux.lds.S @@ -141,10 +141,10 @@ SECTIONS
#ifdef CONFIG_CPU_SRSO /* - * See the comment above srso_untrain_ret_alias()'s + * See the comment above srso_alias_untrain_ret()'s * definition. */ - . = srso_untrain_ret_alias | (1 << 2) | (1 << 8) | (1 << 14) | (1 << 20); + . = srso_alias_untrain_ret | (1 << 2) | (1 << 8) | (1 << 14) | (1 << 20); *(.text.__x86.rethunk_safe) #endif ALIGN_ENTRY_TEXT_END @@ -527,8 +527,8 @@ INIT_PER_CPU(irq_stack_backing_store); * GNU ld cannot do XOR so do: (A | B) - (A & B) in order to compute the XOR * of the two function addresses: */ -. = ASSERT(((srso_untrain_ret_alias | srso_safe_ret_alias) - - (srso_untrain_ret_alias & srso_safe_ret_alias)) == ((1 << 2) | (1 << 8) | (1 << 14) | (1 << 20)), +. = ASSERT(((ABSOLUTE(srso_alias_untrain_ret) | srso_alias_safe_ret) - + (ABSOLUTE(srso_alias_untrain_ret) & srso_alias_safe_ret)) == ((1 << 2) | (1 << 8) | (1 << 14) | (1 << 20)), "SRSO function pair won't alias"); #endif
--- a/arch/x86/lib/retpoline.S +++ b/arch/x86/lib/retpoline.S @@ -75,55 +75,55 @@ SYM_CODE_END(__x86_indirect_thunk_array) #ifdef CONFIG_RETHUNK
/* - * srso_untrain_ret_alias() and srso_safe_ret_alias() are placed at + * srso_alias_untrain_ret() and srso_alias_safe_ret() are placed at * special addresses: * - * - srso_untrain_ret_alias() is 2M aligned - * - srso_safe_ret_alias() is also in the same 2M page but bits 2, 8, 14 + * - srso_alias_untrain_ret() is 2M aligned + * - srso_alias_safe_ret() is also in the same 2M page but bits 2, 8, 14 * and 20 in its virtual address are set (while those bits in the - * srso_untrain_ret_alias() function are cleared). + * srso_alias_untrain_ret() function are cleared). * * This guarantees that those two addresses will alias in the branch * target buffer of Zen3/4 generations, leading to any potential * poisoned entries at that BTB slot to get evicted. * - * As a result, srso_safe_ret_alias() becomes a safe return. + * As a result, srso_alias_safe_ret() becomes a safe return. */ #ifdef CONFIG_CPU_SRSO .section .text.__x86.rethunk_untrain
-SYM_START(srso_untrain_ret_alias, SYM_L_GLOBAL, SYM_A_NONE) +SYM_START(srso_alias_untrain_ret, SYM_L_GLOBAL, SYM_A_NONE) UNWIND_HINT_FUNC ASM_NOP2 lfence jmp srso_alias_return_thunk -SYM_FUNC_END(srso_untrain_ret_alias) -__EXPORT_THUNK(srso_untrain_ret_alias) +SYM_FUNC_END(srso_alias_untrain_ret) +__EXPORT_THUNK(srso_alias_untrain_ret)
.section .text.__x86.rethunk_safe #else /* dummy definition for alternatives */ -SYM_START(srso_untrain_ret_alias, SYM_L_GLOBAL, SYM_A_NONE) +SYM_START(srso_alias_untrain_ret, SYM_L_GLOBAL, SYM_A_NONE) ANNOTATE_UNRET_SAFE ret int3 -SYM_FUNC_END(srso_untrain_ret_alias) +SYM_FUNC_END(srso_alias_untrain_ret) #endif
-SYM_START(srso_safe_ret_alias, SYM_L_GLOBAL, SYM_A_NONE) +SYM_START(srso_alias_safe_ret, SYM_L_GLOBAL, SYM_A_NONE) add $8, %_ASM_SP UNWIND_HINT_FUNC ANNOTATE_UNRET_SAFE ret int3 -SYM_FUNC_END(srso_safe_ret_alias) +SYM_FUNC_END(srso_alias_safe_ret)
.section .text.__x86.return_thunk
SYM_CODE_START(srso_alias_return_thunk) UNWIND_HINT_FUNC ANNOTATE_NOENDBR - call srso_safe_ret_alias + call srso_alias_safe_ret ud2 SYM_CODE_END(srso_alias_return_thunk)
From: Peter Zijlstra peterz@infradead.org
commit e7c25c441e9e0fa75b4c83e0b26306b702cfe90d upstream.
Since there can only be one active return_thunk, there only needs be one (matching) untrain_ret. It fundamentally doesn't make sense to allow multiple untrain_ret at the same time.
Fold all the 3 different untrain methods into a single (temporary) helper stub.
Fixes: fb3bd914b3ec ("x86/srso: Add a Speculative RAS Overflow mitigation") Signed-off-by: Peter Zijlstra (Intel) peterz@infradead.org Signed-off-by: Borislav Petkov (AMD) bp@alien8.de Link: https://lore.kernel.org/r/20230814121149.042774962@infradead.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- arch/x86/include/asm/nospec-branch.h | 12 ++++-------- arch/x86/kernel/cpu/bugs.c | 1 + arch/x86/lib/retpoline.S | 7 +++++++ 3 files changed, 12 insertions(+), 8 deletions(-)
--- a/arch/x86/include/asm/nospec-branch.h +++ b/arch/x86/include/asm/nospec-branch.h @@ -156,9 +156,9 @@ .endm
#ifdef CONFIG_CPU_UNRET_ENTRY -#define CALL_ZEN_UNTRAIN_RET "call retbleed_untrain_ret" +#define CALL_UNTRAIN_RET "call entry_untrain_ret" #else -#define CALL_ZEN_UNTRAIN_RET "" +#define CALL_UNTRAIN_RET "" #endif
/* @@ -177,14 +177,9 @@ defined(CONFIG_CPU_SRSO) ANNOTATE_UNRET_END ALTERNATIVE_2 "", \ - CALL_ZEN_UNTRAIN_RET, X86_FEATURE_UNRET, \ + CALL_UNTRAIN_RET, X86_FEATURE_UNRET, \ "call entry_ibpb", X86_FEATURE_ENTRY_IBPB #endif - -#ifdef CONFIG_CPU_SRSO - ALTERNATIVE_2 "", "call srso_untrain_ret", X86_FEATURE_SRSO, \ - "call srso_alias_untrain_ret", X86_FEATURE_SRSO_ALIAS -#endif .endm
#else /* __ASSEMBLY__ */ @@ -209,6 +204,7 @@ extern void retbleed_untrain_ret(void); extern void srso_untrain_ret(void); extern void srso_alias_untrain_ret(void);
+extern void entry_untrain_ret(void); extern void entry_ibpb(void);
#ifdef CONFIG_RETPOLINE --- a/arch/x86/kernel/cpu/bugs.c +++ b/arch/x86/kernel/cpu/bugs.c @@ -2359,6 +2359,7 @@ static void __init srso_select_mitigatio * like ftrace, static_call, etc. */ setup_force_cpu_cap(X86_FEATURE_RETHUNK); + setup_force_cpu_cap(X86_FEATURE_UNRET);
if (boot_cpu_data.x86 == 0x19) { setup_force_cpu_cap(X86_FEATURE_SRSO_ALIAS); --- a/arch/x86/lib/retpoline.S +++ b/arch/x86/lib/retpoline.S @@ -230,6 +230,13 @@ SYM_CODE_START(srso_return_thunk) ud2 SYM_CODE_END(srso_return_thunk)
+SYM_FUNC_START(entry_untrain_ret) + ALTERNATIVE_2 "jmp retbleed_untrain_ret", \ + "jmp srso_untrain_ret", X86_FEATURE_SRSO, \ + "jmp srso_alias_untrain_ret", X86_FEATURE_SRSO_ALIAS +SYM_FUNC_END(entry_untrain_ret) +__EXPORT_THUNK(entry_untrain_ret) + SYM_CODE_START(__x86_return_thunk) UNWIND_HINT_FUNC ANNOTATE_NOENDBR
From: Borislav Petkov (AMD) bp@alien8.de
commit 9dbd23e42ff0b10c9b02c9e649c76e5228241a8e upstream.
The goal is to eventually have a proper documentation about all this.
Signed-off-by: Borislav Petkov (AMD) bp@alien8.de Link: https://lore.kernel.org/r/20230814164447.GFZNpZ/64H4lENIe94@fat_crate.local Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- arch/x86/lib/retpoline.S | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+)
--- a/arch/x86/lib/retpoline.S +++ b/arch/x86/lib/retpoline.S @@ -128,6 +128,25 @@ SYM_CODE_START(srso_alias_return_thunk) SYM_CODE_END(srso_alias_return_thunk)
/* + * Some generic notes on the untraining sequences: + * + * They are interchangeable when it comes to flushing potentially wrong + * RET predictions from the BTB. + * + * The SRSO Zen1/2 (MOVABS) untraining sequence is longer than the + * Retbleed sequence because the return sequence done there + * (srso_safe_ret()) is longer and the return sequence must fully nest + * (end before) the untraining sequence. Therefore, the untraining + * sequence must fully overlap the return sequence. + * + * Regarding alignment - the instructions which need to be untrained, + * must all start at a cacheline boundary for Zen1/2 generations. That + * is, instruction sequences starting at srso_safe_ret() and + * the respective instruction sequences at retbleed_return_thunk() + * must start at a cacheline boundary. + */ + +/* * Safety details here pertain to the AMD Zen{1,2} microarchitecture: * 1) The RET at retbleed_return_thunk must be on a 64 byte boundary, for * alignment within the BTB.
From: Peter Zijlstra peterz@infradead.org
commit 54097309620ef0dc2d7083783dc521c6a5fef957 upstream.
Christian reported spurious module load crashes after some of Song's module memory layout patches.
Turns out that if the very last instruction on the very last page of the module is a 'JMP __x86_return_thunk' then __static_call_fixup() will trip a fault and die.
And while the module rework made this slightly more likely to happen, it's always been possible.
Fixes: ee88d363d156 ("x86,static_call: Use alternative RET encoding") Reported-by: Christian Bricart christian@bricart.de Signed-off-by: Peter Zijlstra (Intel) peterz@infradead.org Acked-by: Josh Poimboeuf jpoimboe@kernel.org Link: https://lkml.kernel.org/r/20230816104419.GA982867@hirez.programming.kicks-as... Signed-off-by: Sasha Levin sashal@kernel.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- arch/x86/kernel/static_call.c | 13 +++++++++++++ 1 file changed, 13 insertions(+)
--- a/arch/x86/kernel/static_call.c +++ b/arch/x86/kernel/static_call.c @@ -123,6 +123,19 @@ EXPORT_SYMBOL_GPL(arch_static_call_trans */ bool __static_call_fixup(void *tramp, u8 op, void *dest) { + unsigned long addr = (unsigned long)tramp; + /* + * Not all .return_sites are a static_call trampoline (most are not). + * Check if the 3 bytes after the return are still kernel text, if not, + * then this definitely is not a trampoline and we need not worry + * further. + * + * This avoids the memcmp() below tripping over pagefaults etc.. + */ + if (((addr >> PAGE_SHIFT) != ((addr + 7) >> PAGE_SHIFT)) && + !kernel_text_address(addr + 7)) + return false; + if (memcmp(tramp+5, tramp_ud, 3)) { /* Not a trampoline site, not our problem. */ return false;
From: Sean Christopherson seanjc@google.com
commit ba5ca5e5e6a1d55923e88b4a83da452166f5560e upstream.
Use LEA instead of ADD when adjusting %rsp in srso_safe_ret{,_alias}() so as to avoid clobbering flags. Drop one of the INT3 instructions to account for the LEA consuming one more byte than the ADD.
KVM's emulator makes indirect calls into a jump table of sorts, where the destination of each call is a small blob of code that performs fast emulation by executing the target instruction with fixed operands.
E.g. to emulate ADC, fastop() invokes adcb_al_dl():
adcb_al_dl: <+0>: adc %dl,%al <+2>: jmp <__x86_return_thunk>
A major motivation for doing fast emulation is to leverage the CPU to handle consumption and manipulation of arithmetic flags, i.e. RFLAGS is both an input and output to the target of the call. fastop() collects the RFLAGS result by pushing RFLAGS onto the stack and popping them back into a variable (held in %rdi in this case):
asm("push %[flags]; popf; " CALL_NOSPEC " ; pushf; pop %[flags]\n"
<+71>: mov 0xc0(%r8),%rdx <+78>: mov 0x100(%r8),%rcx <+85>: push %rdi <+86>: popf <+87>: call *%rsi <+89>: nop <+90>: nop <+91>: nop <+92>: pushf <+93>: pop %rdi
and then propagating the arithmetic flags into the vCPU's emulator state:
ctxt->eflags = (ctxt->eflags & ~EFLAGS_MASK) | (flags & EFLAGS_MASK);
<+64>: and $0xfffffffffffff72a,%r9 <+94>: and $0x8d5,%edi <+109>: or %rdi,%r9 <+122>: mov %r9,0x10(%r8)
The failures can be most easily reproduced by running the "emulator" test in KVM-Unit-Tests.
If you're feeling a bit of deja vu, see commit b63f20a778c8 ("x86/retpoline: Don't clobber RFLAGS during CALL_NOSPEC on i386").
In addition, this breaks booting of clang-compiled guest on a gcc-compiled host where the host contains the %rsp-modifying SRSO mitigations.
[ bp: Massage commit message, extend, remove addresses. ]
Fixes: fb3bd914b3ec ("x86/srso: Add a Speculative RAS Overflow mitigation") Closes: https://lore.kernel.org/all/de474347-122d-54cd-eabf-9dcc95ab9eae@amd.com Reported-by: Srikanth Aithal sraithal@amd.com Reported-by: Nathan Chancellor nathan@kernel.org Signed-off-by: Sean Christopherson seanjc@google.com Signed-off-by: Borislav Petkov (AMD) bp@alien8.de Tested-by: Nathan Chancellor nathan@kernel.org Cc: stable@vger.kernel.org Link: https://lore.kernel.org/20230810013334.GA5354@dev-arch.thelio-3990X/ Link: https://lore.kernel.org/r/20230811155255.250835-1-seanjc@google.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- arch/x86/lib/retpoline.S | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-)
--- a/arch/x86/lib/retpoline.S +++ b/arch/x86/lib/retpoline.S @@ -111,7 +111,7 @@ SYM_FUNC_END(srso_alias_untrain_ret) #endif
SYM_START(srso_alias_safe_ret, SYM_L_GLOBAL, SYM_A_NONE) - add $8, %_ASM_SP + lea 8(%_ASM_SP), %_ASM_SP UNWIND_HINT_FUNC ANNOTATE_UNRET_SAFE ret @@ -211,7 +211,7 @@ __EXPORT_THUNK(retbleed_untrain_ret) * SRSO untraining sequence for Zen1/2, similar to retbleed_untrain_ret() * above. On kernel entry, srso_untrain_ret() is executed which is a * - * movabs $0xccccccc308c48348,%rax + * movabs $0xccccc30824648d48,%rax * * and when the return thunk executes the inner label srso_safe_ret() * later, it is a stack manipulation and a RET which is mispredicted and @@ -229,11 +229,10 @@ SYM_START(srso_untrain_ret, SYM_L_GLOBAL * the stack. */ SYM_INNER_LABEL(srso_safe_ret, SYM_L_GLOBAL) - add $8, %_ASM_SP + lea 8(%_ASM_SP), %_ASM_SP ret int3 int3 - int3 /* end of movabs */ lfence call srso_safe_ret
From: Borislav Petkov (AMD) bp@alien8.de
commit f58d6fbcb7c848b7f2469be339bc571f2e9d245b upstream.
Initially, it was thought that doing an innocuous division in the #DE handler would take care to prevent any leaking of old data from the divider but by the time the fault is raised, the speculation has already advanced too far and such data could already have been used by younger operations.
Therefore, do the innocuous division on every exit to userspace so that userspace doesn't see any potentially old data from integer divisions in kernel space.
Do the same before VMRUN too, to protect host data from leaking into the guest too.
Fixes: 77245f1c3c64 ("x86/CPU/AMD: Do not leak quotient data after a division by 0") Signed-off-by: Borislav Petkov (AMD) bp@alien8.de Cc: stable@kernel.org Link: https://lore.kernel.org/r/20230811213824.10025-1-bp@alien8.de Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- arch/x86/include/asm/entry-common.h | 1 + arch/x86/kernel/cpu/amd.c | 1 + arch/x86/kernel/traps.c | 2 -- arch/x86/kvm/svm/svm.c | 1 + 4 files changed, 3 insertions(+), 2 deletions(-)
--- a/arch/x86/include/asm/entry-common.h +++ b/arch/x86/include/asm/entry-common.h @@ -78,6 +78,7 @@ static inline void arch_exit_to_user_mod static __always_inline void arch_exit_to_user_mode(void) { mds_user_clear_cpu_buffers(); + amd_clear_divider(); } #define arch_exit_to_user_mode arch_exit_to_user_mode
--- a/arch/x86/kernel/cpu/amd.c +++ b/arch/x86/kernel/cpu/amd.c @@ -1331,3 +1331,4 @@ void noinstr amd_clear_divider(void) asm volatile(ALTERNATIVE("", "div %2\n\t", X86_BUG_DIV0) :: "a" (0), "d" (0), "r" (1)); } +EXPORT_SYMBOL_GPL(amd_clear_divider); --- a/arch/x86/kernel/traps.c +++ b/arch/x86/kernel/traps.c @@ -198,8 +198,6 @@ DEFINE_IDTENTRY(exc_divide_error) { do_error_trap(regs, 0, "divide error", X86_TRAP_DE, SIGFPE, FPE_INTDIV, error_get_trap_addr(regs)); - - amd_clear_divider(); }
DEFINE_IDTENTRY(exc_overflow) --- a/arch/x86/kvm/svm/svm.c +++ b/arch/x86/kvm/svm/svm.c @@ -3376,6 +3376,7 @@ static void svm_flush_tlb_gva(struct kvm
static void svm_prepare_guest_switch(struct kvm_vcpu *vcpu) { + amd_clear_divider(); }
static inline void sync_cr8_to_lapic(struct kvm_vcpu *vcpu)
From: Borislav Petkov (AMD) bp@alien8.de
commit e9fbc47b818b964ddff5df5b2d5c0f5f32f4a147 upstream.
Skip the srso cmd line parsing which is not needed on Zen1/2 with SMT disabled and with the proper microcode applied (latter should be the case anyway) as those are not affected.
Fixes: 5a15d8348881 ("x86/srso: Tie SBPB bit setting to microcode patch detection") Signed-off-by: Borislav Petkov (AMD) bp@alien8.de Link: https://lore.kernel.org/r/20230813104517.3346-1-bp@alien8.de Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- arch/x86/kernel/cpu/bugs.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-)
--- a/arch/x86/kernel/cpu/bugs.c +++ b/arch/x86/kernel/cpu/bugs.c @@ -2329,8 +2329,10 @@ static void __init srso_select_mitigatio * IBPB microcode has been applied. */ if ((boot_cpu_data.x86 < 0x19) && - (!cpu_smt_possible() || (cpu_smt_control == CPU_SMT_DISABLED))) + (!cpu_smt_possible() || (cpu_smt_control == CPU_SMT_DISABLED))) { setup_force_cpu_cap(X86_FEATURE_SRSO_NO); + return; + } }
if (retbleed_mitigation == RETBLEED_MITIGATION_IBPB) { @@ -2616,6 +2618,9 @@ static ssize_t gds_show_state(char *buf)
static ssize_t srso_show_state(char *buf) { + if (boot_cpu_has(X86_FEATURE_SRSO_NO)) + return sysfs_emit(buf, "Not affected\n"); + return sysfs_emit(buf, "%s%s\n", srso_strings[srso_mitigation], (cpu_has_ibpb_brtype_microcode() ? "" : ", no microcode"));
From: Petr Pavlu petr.pavlu@suse.com
commit 79cd2a11224eab86d6673fe8a11d2046ae9d2757 upstream.
The linker script arch/x86/kernel/vmlinux.lds.S matches the thunk sections ".text.__x86.*" from arch/x86/lib/retpoline.S as follows:
.text { [...] TEXT_TEXT [...] __indirect_thunk_start = .; *(.text.__x86.*) __indirect_thunk_end = .; [...] }
Macro TEXT_TEXT references TEXT_MAIN which normally expands to only ".text". However, with CONFIG_LTO_CLANG, TEXT_MAIN becomes ".text .text.[0-9a-zA-Z_]*" which wrongly matches also the thunk sections. The output layout is then different than expected. For instance, the currently defined range [__indirect_thunk_start, __indirect_thunk_end] becomes empty.
Prevent the problem by using ".." as the first separator, for example, ".text..__x86.indirect_thunk". This pattern is utilized by other explicit section names which start with one of the standard prefixes, such as ".text" or ".data", and that need to be individually selected in the linker script.
[ nathan: Fix conflicts with SRSO and fold in fix issue brought up by Andrew Cooper in post-review: https://lore.kernel.org/20230803230323.1478869-1-andrew.cooper3@citrix.com ]
Fixes: dc5723b02e52 ("kbuild: add support for Clang LTO") Signed-off-by: Petr Pavlu petr.pavlu@suse.com Signed-off-by: Peter Zijlstra (Intel) peterz@infradead.org Signed-off-by: Nathan Chancellor nathan@kernel.org Signed-off-by: Borislav Petkov (AMD) bp@alien8.de Link: https://lore.kernel.org/r/20230711091952.27944-2-petr.pavlu@suse.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- arch/x86/kernel/vmlinux.lds.S | 8 ++++---- arch/x86/lib/retpoline.S | 8 ++++---- tools/objtool/check.c | 2 +- 3 files changed, 9 insertions(+), 9 deletions(-)
--- a/arch/x86/kernel/vmlinux.lds.S +++ b/arch/x86/kernel/vmlinux.lds.S @@ -134,7 +134,7 @@ SECTIONS KPROBES_TEXT ALIGN_ENTRY_TEXT_BEGIN #ifdef CONFIG_CPU_SRSO - *(.text.__x86.rethunk_untrain) + *(.text..__x86.rethunk_untrain) #endif
ENTRY_TEXT @@ -145,7 +145,7 @@ SECTIONS * definition. */ . = srso_alias_untrain_ret | (1 << 2) | (1 << 8) | (1 << 14) | (1 << 20); - *(.text.__x86.rethunk_safe) + *(.text..__x86.rethunk_safe) #endif ALIGN_ENTRY_TEXT_END SOFTIRQENTRY_TEXT @@ -155,8 +155,8 @@ SECTIONS
#ifdef CONFIG_RETPOLINE __indirect_thunk_start = .; - *(.text.__x86.indirect_thunk) - *(.text.__x86.return_thunk) + *(.text..__x86.indirect_thunk) + *(.text..__x86.return_thunk) __indirect_thunk_end = .; #endif } :text =0xcccc --- a/arch/x86/lib/retpoline.S +++ b/arch/x86/lib/retpoline.S @@ -11,7 +11,7 @@ #include <asm/frame.h> #include <asm/nops.h>
- .section .text.__x86.indirect_thunk + .section .text..__x86.indirect_thunk
.macro RETPOLINE reg ANNOTATE_INTRA_FUNCTION_CALL @@ -90,7 +90,7 @@ SYM_CODE_END(__x86_indirect_thunk_array) * As a result, srso_alias_safe_ret() becomes a safe return. */ #ifdef CONFIG_CPU_SRSO - .section .text.__x86.rethunk_untrain + .section .text..__x86.rethunk_untrain
SYM_START(srso_alias_untrain_ret, SYM_L_GLOBAL, SYM_A_NONE) UNWIND_HINT_FUNC @@ -100,7 +100,7 @@ SYM_START(srso_alias_untrain_ret, SYM_L_ SYM_FUNC_END(srso_alias_untrain_ret) __EXPORT_THUNK(srso_alias_untrain_ret)
- .section .text.__x86.rethunk_safe + .section .text..__x86.rethunk_safe #else /* dummy definition for alternatives */ SYM_START(srso_alias_untrain_ret, SYM_L_GLOBAL, SYM_A_NONE) @@ -118,7 +118,7 @@ SYM_START(srso_alias_safe_ret, SYM_L_GLO int3 SYM_FUNC_END(srso_alias_safe_ret)
- .section .text.__x86.return_thunk + .section .text..__x86.return_thunk
SYM_CODE_START(srso_alias_return_thunk) UNWIND_HINT_FUNC --- a/tools/objtool/check.c +++ b/tools/objtool/check.c @@ -369,7 +369,7 @@ static int decode_instructions(struct ob
if (!strcmp(sec->name, ".noinstr.text") || !strcmp(sec->name, ".entry.text") || - !strncmp(sec->name, ".text.__x86.", 12)) + !strncmp(sec->name, ".text..__x86.", 13)) sec->noinstr = true;
for (offset = 0; offset < sec->len; offset += insn->len) {
From: Peter Zijlstra peterz@infradead.org
commit dbf46008775516f7f25c95b7760041c286299783 upstream.
For stack-validation of a frame-pointer build, objtool validates that every CALL instruction is preceded by a frame-setup. The new SRSO return thunks violate this with their RSB stuffing trickery.
Extend the __fentry__ exception to also cover the embedded_insn case used for this. This cures:
vmlinux.o: warning: objtool: srso_untrain_ret+0xd: call without frame pointer save/setup
Fixes: 4ae68b26c3ab ("objtool/x86: Fix SRSO mess") Signed-off-by: Peter Zijlstra (Intel) peterz@infradead.org Signed-off-by: Borislav Petkov (AMD) bp@alien8.de Acked-by: Josh Poimboeuf jpoimboe@kernel.org Link: https://lore.kernel.org/r/20230816115921.GH980931@hirez.programming.kicks-as... Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- tools/objtool/check.c | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-)
--- a/tools/objtool/check.c +++ b/tools/objtool/check.c @@ -2079,12 +2079,17 @@ static int decode_sections(struct objtoo return 0; }
-static bool is_fentry_call(struct instruction *insn) +static bool is_special_call(struct instruction *insn) { - if (insn->type == INSN_CALL && - insn->call_dest && - insn->call_dest->fentry) - return true; + if (insn->type == INSN_CALL) { + struct symbol *dest = insn->call_dest; + + if (!dest) + return false; + + if (dest->fentry) + return true; + }
return false; } @@ -2958,7 +2963,7 @@ static int validate_branch(struct objtoo if (ret) return ret;
- if (!no_fp && func && !is_fentry_call(insn) && + if (!no_fp && func && !is_special_call(insn) && !has_valid_stack_frame(&state)) { WARN_FUNC("call without frame pointer save/setup", sec, insn->offset);
From: Borislav Petkov (AMD) bp@alien8.de
commit 6405b72e8d17bd1875a56ae52d23ec3cd51b9d66 upstream.
Specify how is SRSO mitigated when SMT is disabled. Also, correct the SMT check for that.
Fixes: e9fbc47b818b ("x86/srso: Disable the mitigation on unaffected configurations") Suggested-by: Josh Poimboeuf jpoimboe@kernel.org Signed-off-by: Borislav Petkov (AMD) bp@alien8.de Acked-by: Josh Poimboeuf jpoimboe@kernel.org Link: https://lore.kernel.org/r/20230814200813.p5czl47zssuej7nv@treble Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- arch/x86/kernel/cpu/bugs.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-)
--- a/arch/x86/kernel/cpu/bugs.c +++ b/arch/x86/kernel/cpu/bugs.c @@ -2328,8 +2328,7 @@ static void __init srso_select_mitigatio * Zen1/2 with SMT off aren't vulnerable after the right * IBPB microcode has been applied. */ - if ((boot_cpu_data.x86 < 0x19) && - (!cpu_smt_possible() || (cpu_smt_control == CPU_SMT_DISABLED))) { + if (boot_cpu_data.x86 < 0x19 && !cpu_smt_possible()) { setup_force_cpu_cap(X86_FEATURE_SRSO_NO); return; } @@ -2619,7 +2618,7 @@ static ssize_t gds_show_state(char *buf) static ssize_t srso_show_state(char *buf) { if (boot_cpu_has(X86_FEATURE_SRSO_NO)) - return sysfs_emit(buf, "Not affected\n"); + return sysfs_emit(buf, "Mitigation: SMT disabled\n");
return sysfs_emit(buf, "%s%s\n", srso_strings[srso_mitigation],
On Thu, Aug 24, 2023 at 07:05:35PM +0300, Alexey Khoroshilov wrote:
On 24.08.2023 17:49, Greg Kroah-Hartman wrote:
This is the start of the stable review cycle for the 5.10.191 release.
Do you mean 5.10.192 release?
Ah crap, this is what happens when I come back from a long trip where I was working on my laptop and I didn't fully sync my desktop.
Yes, you are right, I am behind a release here, let me go update my trees and push out a new -rc for this, thanks for catching it.
greg k-h
linux-stable-mirror@lists.linaro.org