summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.mailmap4
-rw-r--r--Documentation/ABI/testing/sysfs-class-tsm10
-rw-r--r--Documentation/admin-guide/kernel-parameters.txt5
-rw-r--r--Documentation/devicetree/bindings/sound/ti,tlv320aic3x.yaml1
-rw-r--r--MAINTAINERS53
-rw-r--r--arch/arm/include/asm/string.h5
-rw-r--r--arch/x86/include/asm/kfence.h7
-rw-r--r--arch/x86/kvm/irq.c3
-rw-r--r--arch/x86/kvm/svm/avic.c4
-rw-r--r--arch/x86/kvm/svm/svm.c2
-rw-r--r--arch/x86/kvm/vmx/vmx.c2
-rw-r--r--arch/x86/kvm/x86.c30
-rw-r--r--arch/x86/kvm/x86.h2
-rw-r--r--drivers/android/binder/rust_binderfs.c9
-rw-r--r--drivers/block/loop.c45
-rw-r--r--drivers/crypto/ccp/sev-dev-tsm.c15
-rw-r--r--drivers/firmware/cirrus/cs_dsp.c37
-rw-r--r--drivers/firmware/cirrus/cs_dsp.h18
-rw-r--r--drivers/firmware/cirrus/test/cs_dsp_test_bin.c22
-rw-r--r--drivers/firmware/cirrus/test/cs_dsp_test_bin_error.c24
-rw-r--r--drivers/firmware/cirrus/test/cs_dsp_test_wmfw.c26
-rw-r--r--drivers/firmware/cirrus/test/cs_dsp_test_wmfw_error.c24
-rw-r--r--drivers/firmware/cirrus/test/cs_dsp_tests.c1
-rw-r--r--drivers/gpio/gpio-loongson-64bit.c2
-rw-r--r--drivers/gpio/gpiolib-acpi-core.c1
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c14
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c3
-rw-r--r--drivers/gpu/drm/amd/amdgpu/mes_v11_0.c2
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn30/dcn30_cm_common.c37
-rw-r--r--drivers/gpu/drm/amd/display/dc/dwb/dcn30/dcn30_cm_common.h2
-rw-r--r--drivers/gpu/drm/amd/display/dc/hwss/dcn30/dcn30_hwseq.c9
-rw-r--r--drivers/gpu/drm/amd/display/dc/hwss/dcn32/dcn32_hwseq.c18
-rw-r--r--drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.c16
-rw-r--r--drivers/gpu/drm/bridge/imx/imx8mp-hdmi-pai.c15
-rw-r--r--drivers/gpu/drm/gma500/psb_irq.c36
-rw-r--r--drivers/gpu/drm/mgag200/mgag200_bmc.c31
-rw-r--r--drivers/gpu/drm/mgag200/mgag200_drv.h6
-rw-r--r--drivers/gpu/drm/nouveau/include/nvif/client.h2
-rw-r--r--drivers/gpu/drm/nouveau/include/nvif/driver.h2
-rw-r--r--drivers/gpu/drm/nouveau/include/nvkm/core/device.h3
-rw-r--r--drivers/gpu/drm/nouveau/include/nvkm/core/engine.h2
-rw-r--r--drivers/gpu/drm/nouveau/include/nvkm/core/object.h5
-rw-r--r--drivers/gpu/drm/nouveau/include/nvkm/core/oproxy.h2
-rw-r--r--drivers/gpu/drm/nouveau/include/nvkm/core/subdev.h4
-rw-r--r--drivers/gpu/drm/nouveau/include/nvkm/core/suspend_state.h11
-rw-r--r--drivers/gpu/drm/nouveau/include/nvkm/subdev/gsp.h6
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_display.c2
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_drm.c2
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_nvif.c10
-rw-r--r--drivers/gpu/drm/nouveau/nvif/client.c4
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/core/engine.c4
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/core/ioctl.c4
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/core/object.c20
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/core/oproxy.c2
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/core/subdev.c18
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/core/uevent.c2
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/ce/ga100.c2
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/ce/priv.h2
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/device/base.c22
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/device/pci.c4
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/device/priv.h2
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/device/user.c2
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/base.c4
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/chan.c2
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/falcon.c4
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/fifo/base.c2
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/fifo/uchan.c6
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/gr/base.c4
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c2
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/gr/nv04.c2
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/gr/nv10.c2
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/gr/nv20.c2
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/gr/nv20.h2
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/gr/nv40.c4
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/mpeg/nv44.c2
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/sec2/base.c2
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/xtensa.c4
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/acr/base.c2
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/bar/base.c2
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/clk/base.c2
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/devinit/base.c4
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/fault/base.c2
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/fault/user.c2
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/gpio/base.c2
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/gsp/base.c2
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/gsp/gh100.c2
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/gsp/priv.h8
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/gsp/rm/r535/fbsr.c2
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/gsp/rm/r535/gsp.c8
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/gsp/rm/r535/rpc.c6
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/gsp/rm/r570/fbsr.c8
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/gsp/rm/r570/gsp.c2
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/gsp/rm/rm.h2
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/gsp/tu102.c2
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/i2c/base.c2
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/instmem/base.c2
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/pci/base.c2
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/pmu/base.c2
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/therm/base.c6
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/timer/base.c2
-rw-r--r--drivers/gpu/drm/xe/xe_guc.c6
-rw-r--r--drivers/gpu/drm/xe/xe_guc.h2
-rw-r--r--drivers/gpu/drm/xe/xe_migrate.c2
-rw-r--r--drivers/gpu/drm/xe/xe_pm.c13
-rw-r--r--drivers/gpu/drm/xe/xe_query.c2
-rw-r--r--drivers/gpu/drm/xe/xe_tlb_inval.c2
-rw-r--r--drivers/gpu/drm/xe/xe_tlb_inval_job.c2
-rw-r--r--drivers/hwmon/acpi_power_meter.c17
-rw-r--r--drivers/hwmon/dell-smm-hwmon.c8
-rw-r--r--drivers/hwmon/gpio-fan.c6
-rw-r--r--drivers/hwmon/occ/common.c1
-rw-r--r--drivers/iommu/intel/pasid.h2
-rw-r--r--drivers/net/ethernet/adi/adin1110.c3
-rw-r--r--drivers/net/ethernet/cavium/liquidio/lio_main.c39
-rw-r--r--drivers/net/ethernet/cavium/liquidio/lio_vf_main.c4
-rw-r--r--drivers/net/ethernet/freescale/dpaa2/dpaa2-switch.c10
-rw-r--r--drivers/net/ethernet/freescale/enetc/enetc.c11
-rw-r--r--drivers/net/ethernet/freescale/enetc/enetc4_pf.c6
-rw-r--r--drivers/net/ethernet/freescale/enetc/enetc_cbdr.c4
-rw-r--r--drivers/net/ethernet/freescale/enetc/enetc_hw.h17
-rw-r--r--drivers/net/ethernet/google/gve/gve_ethtool.c77
-rw-r--r--drivers/net/ethernet/google/gve/gve_main.c4
-rw-r--r--drivers/net/ethernet/intel/i40e/i40e_main.c1
-rw-r--r--drivers/net/ethernet/intel/ice/ice_main.c26
-rw-r--r--drivers/net/ethernet/intel/ice/ice_ptp.c179
-rw-r--r--drivers/net/ethernet/intel/ice/ice_ptp.h18
-rw-r--r--drivers/net/ethernet/spacemit/k1_emac.c21
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/stmmac_main.c3
-rw-r--r--drivers/net/ethernet/ti/cpsw.c41
-rw-r--r--drivers/net/ethernet/ti/cpsw_new.c34
-rw-r--r--drivers/net/ethernet/ti/cpsw_priv.h1
-rw-r--r--drivers/net/macvlan.c5
-rw-r--r--drivers/net/phy/sfp.c2
-rw-r--r--drivers/net/usb/r8152.c29
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mld/iface.c2
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mld/mac80211.c2
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/d3.c6
-rw-r--r--drivers/nvme/host/pci.c45
-rw-r--r--drivers/nvme/target/tcp.c17
-rw-r--r--drivers/pci/ide.c10
-rw-r--r--drivers/platform/x86/amd/pmc/pmc-quirks.c7
-rw-r--r--drivers/platform/x86/classmate-laptop.c32
-rw-r--r--drivers/platform/x86/hp/hp-bioscfg/bioscfg.c5
-rw-r--r--drivers/platform/x86/intel/plr_tpmi.c2
-rw-r--r--drivers/platform/x86/intel/telemetry/debugfs.c4
-rw-r--r--drivers/platform/x86/intel/telemetry/pltdrv.c2
-rw-r--r--drivers/platform/x86/intel/vsec.c2
-rw-r--r--drivers/platform/x86/lg-laptop.c11
-rw-r--r--drivers/platform/x86/panasonic-laptop.c4
-rw-r--r--drivers/platform/x86/toshiba_haps.c2
-rw-r--r--drivers/pmdomain/imx/gpcv2.c8
-rw-r--r--drivers/pmdomain/imx/imx8m-blk-ctrl.c2
-rw-r--r--drivers/pmdomain/imx/imx8mp-blk-ctrl.c30
-rw-r--r--drivers/pmdomain/qcom/rpmpd.c2
-rw-r--r--drivers/soc/qcom/smem.c5
-rw-r--r--drivers/usb/gadget/function/f_fs.c108
-rw-r--r--drivers/usb/gadget/function/u_fs.h2
-rw-r--r--drivers/virt/coco/tsm-core.c30
-rw-r--r--fs/btrfs/raid56.c1
-rw-r--r--fs/smb/client/cifstransport.c4
-rw-r--r--fs/smb/client/smb2file.c1
-rw-r--r--include/linux/pci-ide.h4
-rw-r--r--include/linux/skbuff.h12
-rw-r--r--include/linux/tsm.h3
-rw-r--r--include/trace/events/dma.h25
-rw-r--r--io_uring/fdinfo.c13
-rw-r--r--io_uring/zcrx.c9
-rw-r--r--kernel/cgroup/dmem.c70
-rw-r--r--kernel/dma/contiguous.c10
-rw-r--r--kernel/liveupdate/luo_file.c2
-rw-r--r--kernel/sched/ext.c48
-rw-r--r--mm/shmem.c23
-rw-r--r--mm/slub.c6
-rw-r--r--net/core/filter.c8
-rw-r--r--net/core/gro.c2
-rw-r--r--net/core/link_watch.c20
-rw-r--r--net/core/net-procfs.c50
-rw-r--r--net/ethtool/common.c3
-rw-r--r--net/ethtool/rss.c9
-rw-r--r--net/ipv6/ip6_fib.c3
-rw-r--r--net/netfilter/nf_tables_api.c2
-rw-r--r--net/sched/cls_u32.c13
-rw-r--r--net/tipc/crypto.c4
-rw-r--r--security/lsm.h9
-rw-r--r--security/lsm_init.c7
-rw-r--r--security/min_addr.c5
-rw-r--r--sound/drivers/aloop.c62
-rw-r--r--sound/hda/codecs/realtek/alc269.c1
-rw-r--r--sound/soc/amd/renoir/acp3x-pdm-dma.c2
-rw-r--r--sound/soc/amd/yc/acp6x-mach.c7
-rw-r--r--sound/soc/codecs/cs42l43-jack.c37
-rw-r--r--sound/soc/codecs/rt1320-sdw.c2
-rw-r--r--sound/soc/fsl/fsl_xcvr.c3
-rw-r--r--sound/soc/intel/boards/sof_es8336.c9
-rw-r--r--sound/soc/sof/intel/hda.c5
-rw-r--r--sound/usb/mixer_quirks.c9
-rw-r--r--tools/testing/selftests/kvm/Makefile.kvm1
-rwxr-xr-xtools/testing/selftests/net/udpgro_fwd.sh64
-rw-r--r--virt/kvm/eventfd.c44
199 files changed, 1552 insertions, 796 deletions
diff --git a/.mailmap b/.mailmap
index 22db8cfc18fc..da4afd2b2415 100644
--- a/.mailmap
+++ b/.mailmap
@@ -34,6 +34,7 @@ Alexander Lobakin <alobakin@pm.me> <alobakin@marvell.com>
Alexander Lobakin <alobakin@pm.me> <bloodyreaper@yandex.ru>
Alexander Mikhalitsyn <alexander@mihalicyn.com> <alexander.mikhalitsyn@virtuozzo.com>
Alexander Mikhalitsyn <alexander@mihalicyn.com> <aleksandr.mikhalitsyn@canonical.com>
+Alexander Mikhalitsyn <alexander@mihalicyn.com> <aleksandr.mikhalitsyn@futurfusion.io>
Alexander Sverdlin <alexander.sverdlin@gmail.com> <alexander.sverdlin.ext@nsn.com>
Alexander Sverdlin <alexander.sverdlin@gmail.com> <alexander.sverdlin@gmx.de>
Alexander Sverdlin <alexander.sverdlin@gmail.com> <alexander.sverdlin@nokia.com>
@@ -786,7 +787,8 @@ Subash Abhinov Kasiviswanathan <quic_subashab@quicinc.com> <subashab@codeaurora.
Subbaraman Narayanamurthy <quic_subbaram@quicinc.com> <subbaram@codeaurora.org>
Subhash Jadavani <subhashj@codeaurora.org>
Sudarshan Rajagopalan <quic_sudaraja@quicinc.com> <sudaraja@codeaurora.org>
-Sudeep Holla <sudeep.holla@arm.com> Sudeep KarkadaNagesha <sudeep.karkadanagesha@arm.com>
+Sudeep Holla <sudeep.holla@kernel.org> Sudeep KarkadaNagesha <sudeep.karkadanagesha@arm.com>
+Sudeep Holla <sudeep.holla@kernel.org> <sudeep.holla@arm.com>
Sumit Garg <sumit.garg@kernel.org> <sumit.garg@linaro.org>
Sumit Semwal <sumit.semwal@ti.com>
Surabhi Vishnoi <quic_svishnoi@quicinc.com> <svishnoi@codeaurora.org>
diff --git a/Documentation/ABI/testing/sysfs-class-tsm b/Documentation/ABI/testing/sysfs-class-tsm
index 6fc1a5ac6da1..2949468deaf7 100644
--- a/Documentation/ABI/testing/sysfs-class-tsm
+++ b/Documentation/ABI/testing/sysfs-class-tsm
@@ -7,13 +7,3 @@ Description:
signals when the PCI layer is able to support establishment of
link encryption and other device-security features coordinated
through a platform tsm.
-
-What: /sys/class/tsm/tsmN/streamH.R.E
-Contact: linux-pci@vger.kernel.org
-Description:
- (RO) When a host bridge has established a secure connection via
- the platform TSM, symlink appears. The primary function of this
- is have a system global review of TSM resource consumption
- across host bridges. The link points to the endpoint PCI device
- and matches the same link published by the host bridge. See
- Documentation/ABI/testing/sysfs-devices-pci-host-bridge.
diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt
index 1058f2a6d6a8..aa0031108bc1 100644
--- a/Documentation/admin-guide/kernel-parameters.txt
+++ b/Documentation/admin-guide/kernel-parameters.txt
@@ -3472,6 +3472,11 @@ Kernel parameters
If there are multiple matching configurations changing
the same attribute, the last one is used.
+ liveupdate= [KNL,EARLY]
+ Format: <bool>
+ Enable Live Update Orchestrator (LUO).
+ Default: off.
+
load_ramdisk= [RAM] [Deprecated]
lockd.nlm_grace_period=P [NFS] Assign grace period.
diff --git a/Documentation/devicetree/bindings/sound/ti,tlv320aic3x.yaml b/Documentation/devicetree/bindings/sound/ti,tlv320aic3x.yaml
index 206f6d61e362..50088698adac 100644
--- a/Documentation/devicetree/bindings/sound/ti,tlv320aic3x.yaml
+++ b/Documentation/devicetree/bindings/sound/ti,tlv320aic3x.yaml
@@ -46,6 +46,7 @@ maintainers:
properties:
compatible:
enum:
+ - ti,tlv320aic23
- ti,tlv320aic3x
- ti,tlv320aic33
- ti,tlv320aic3007
diff --git a/MAINTAINERS b/MAINTAINERS
index 0efa8cc6775b..e08767323763 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -335,7 +335,7 @@ F: tools/power/acpi/
ACPI FOR ARM64 (ACPI/arm64)
M: Lorenzo Pieralisi <lpieralisi@kernel.org>
M: Hanjun Guo <guohanjun@huawei.com>
-M: Sudeep Holla <sudeep.holla@arm.com>
+M: Sudeep Holla <sudeep.holla@kernel.org>
L: linux-acpi@vger.kernel.org
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
S: Maintained
@@ -351,7 +351,7 @@ F: drivers/acpi/riscv/
F: include/linux/acpi_rimt.h
ACPI PCC(Platform Communication Channel) MAILBOX DRIVER
-M: Sudeep Holla <sudeep.holla@arm.com>
+M: Sudeep Holla <sudeep.holla@kernel.org>
L: linux-acpi@vger.kernel.org
S: Supported
F: drivers/mailbox/pcc.c
@@ -2747,14 +2747,14 @@ F: arch/arm/include/asm/hardware/dec21285.h
F: arch/arm/mach-footbridge/
ARM/FREESCALE IMX / MXC ARM ARCHITECTURE
-M: Shawn Guo <shawnguo@kernel.org>
+M: Frank Li <Frank.Li@nxp.com>
M: Sascha Hauer <s.hauer@pengutronix.de>
R: Pengutronix Kernel Team <kernel@pengutronix.de>
R: Fabio Estevam <festevam@gmail.com>
L: imx@lists.linux.dev
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
S: Maintained
-T: git git://git.kernel.org/pub/scm/linux/kernel/git/shawnguo/linux.git
+T: git git://git.kernel.org/pub/scm/linux/kernel/git/frank.li/linux.git
F: Documentation/devicetree/bindings/firmware/fsl*
F: Documentation/devicetree/bindings/firmware/nxp*
F: arch/arm/boot/dts/nxp/imx/
@@ -2769,22 +2769,22 @@ N: mxs
N: \bmxc[^\d]
ARM/FREESCALE LAYERSCAPE ARM ARCHITECTURE
-M: Shawn Guo <shawnguo@kernel.org>
+M: Frank Li <Frank.Li@nxp.com>
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
S: Maintained
-T: git git://git.kernel.org/pub/scm/linux/kernel/git/shawnguo/linux.git
+T: git git://git.kernel.org/pub/scm/linux/kernel/git/frank.li/linux.git
F: arch/arm/boot/dts/nxp/ls/
F: arch/arm64/boot/dts/freescale/fsl-*
F: arch/arm64/boot/dts/freescale/qoriq-*
ARM/FREESCALE VYBRID ARM ARCHITECTURE
-M: Shawn Guo <shawnguo@kernel.org>
+M: Frank Li <Frank.Li@nxp.com>
M: Sascha Hauer <s.hauer@pengutronix.de>
R: Pengutronix Kernel Team <kernel@pengutronix.de>
R: Stefan Agner <stefan@agner.ch>
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
S: Maintained
-T: git git://git.kernel.org/pub/scm/linux/kernel/git/shawnguo/linux.git
+T: git git://git.kernel.org/pub/scm/linux/kernel/git/frank.li/linux.git
F: arch/arm/boot/dts/nxp/vf/
F: arch/arm/mach-imx/*vf610*
@@ -3681,7 +3681,7 @@ N: uniphier
ARM/VERSATILE EXPRESS PLATFORM
M: Liviu Dudau <liviu.dudau@arm.com>
-M: Sudeep Holla <sudeep.holla@arm.com>
+M: Sudeep Holla <sudeep.holla@kernel.org>
M: Lorenzo Pieralisi <lpieralisi@kernel.org>
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
S: Maintained
@@ -6513,7 +6513,7 @@ F: drivers/i2c/busses/i2c-cp2615.c
CPU FREQUENCY DRIVERS - VEXPRESS SPC ARM BIG LITTLE
M: Viresh Kumar <viresh.kumar@linaro.org>
-M: Sudeep Holla <sudeep.holla@arm.com>
+M: Sudeep Holla <sudeep.holla@kernel.org>
L: linux-pm@vger.kernel.org
S: Maintained
W: http://www.arm.com/products/processors/technologies/biglittleprocessing.php
@@ -6609,7 +6609,7 @@ F: include/linux/platform_data/cpuidle-exynos.h
CPUIDLE DRIVER - ARM PSCI
M: Lorenzo Pieralisi <lpieralisi@kernel.org>
-M: Sudeep Holla <sudeep.holla@arm.com>
+M: Sudeep Holla <sudeep.holla@kernel.org>
M: Ulf Hansson <ulf.hansson@linaro.org>
L: linux-pm@vger.kernel.org
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
@@ -9815,7 +9815,7 @@ F: include/uapi/linux/firewire*.h
F: tools/firewire/
FIRMWARE FRAMEWORK FOR ARMV8-A
-M: Sudeep Holla <sudeep.holla@arm.com>
+M: Sudeep Holla <sudeep.holla@kernel.org>
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
S: Maintained
F: drivers/firmware/arm_ffa/
@@ -10513,7 +10513,7 @@ S: Maintained
F: scripts/gendwarfksyms/
GENERIC ARCHITECTURE TOPOLOGY
-M: Sudeep Holla <sudeep.holla@arm.com>
+M: Sudeep Holla <sudeep.holla@kernel.org>
L: linux-kernel@vger.kernel.org
S: Maintained
F: drivers/base/arch_topology.c
@@ -11375,6 +11375,11 @@ F: Documentation/ABI/testing/sysfs-devices-platform-kunpeng_hccs
F: drivers/soc/hisilicon/kunpeng_hccs.c
F: drivers/soc/hisilicon/kunpeng_hccs.h
+HISILICON SOC HHA DRIVER
+M: Yushan Wang <wangyushan12@huawei.com>
+S: Maintained
+F: drivers/cache/hisi_soc_hha.c
+
HISILICON LPC BUS DRIVER
M: Jay Fang <f.fangjian@huawei.com>
S: Maintained
@@ -15100,7 +15105,7 @@ F: drivers/mailbox/arm_mhuv2.c
F: include/linux/mailbox/arm_mhuv2_message.h
MAILBOX ARM MHUv3
-M: Sudeep Holla <sudeep.holla@arm.com>
+M: Sudeep Holla <sudeep.holla@kernel.org>
M: Cristian Marussi <cristian.marussi@arm.com>
L: linux-kernel@vger.kernel.org
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
@@ -20577,7 +20582,7 @@ F: drivers/pinctrl/pinctrl-amd.c
PIN CONTROLLER - FREESCALE
M: Dong Aisheng <aisheng.dong@nxp.com>
M: Fabio Estevam <festevam@gmail.com>
-M: Shawn Guo <shawnguo@kernel.org>
+M: Frank Li <Frank.Li@nxp.com>
M: Jacky Bai <ping.bai@nxp.com>
R: Pengutronix Kernel Team <kernel@pengutronix.de>
R: NXP S32 Linux Team <s32@nxp.com>
@@ -20973,6 +20978,18 @@ F: Documentation/devicetree/bindings/net/pse-pd/
F: drivers/net/pse-pd/
F: net/ethtool/pse-pd.c
+PSP SECURITY PROTOCOL
+M: Daniel Zahka <daniel.zahka@gmail.com>
+M: Jakub Kicinski <kuba@kernel.org>
+M: Willem de Bruijn <willemdebruijn.kernel@gmail.com>
+F: Documentation/netlink/specs/psp.yaml
+F: Documentation/networking/psp.rst
+F: include/net/psp/
+F: include/net/psp.h
+F: include/uapi/linux/psp.h
+F: net/psp/
+K: struct\ psp(_assoc|_dev|hdr)\b
+
PSTORE FILESYSTEM
M: Kees Cook <kees@kernel.org>
R: Tony Luck <tony.luck@intel.com>
@@ -23630,7 +23647,7 @@ F: include/uapi/linux/sed*
SECURE MONITOR CALL(SMC) CALLING CONVENTION (SMCCC)
M: Mark Rutland <mark.rutland@arm.com>
M: Lorenzo Pieralisi <lpieralisi@kernel.org>
-M: Sudeep Holla <sudeep.holla@arm.com>
+M: Sudeep Holla <sudeep.holla@kernel.org>
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
S: Maintained
F: drivers/firmware/smccc/
@@ -25394,7 +25411,7 @@ T: git git://git.kernel.org/pub/scm/linux/kernel/git/lee/mfd.git
F: drivers/mfd/syscon.c
SYSTEM CONTROL & POWER/MANAGEMENT INTERFACE (SCPI/SCMI) Message Protocol drivers
-M: Sudeep Holla <sudeep.holla@arm.com>
+M: Sudeep Holla <sudeep.holla@kernel.org>
R: Cristian Marussi <cristian.marussi@arm.com>
L: arm-scmi@vger.kernel.org
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
@@ -26546,7 +26563,7 @@ F: samples/tsm-mr/
TRUSTED SERVICES TEE DRIVER
M: Balint Dobszay <balint.dobszay@arm.com>
-M: Sudeep Holla <sudeep.holla@arm.com>
+M: Sudeep Holla <sudeep.holla@kernel.org>
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
L: trusted-services@lists.trustedfirmware.org
S: Maintained
diff --git a/arch/arm/include/asm/string.h b/arch/arm/include/asm/string.h
index 6c607c68f3ad..c35250c4991b 100644
--- a/arch/arm/include/asm/string.h
+++ b/arch/arm/include/asm/string.h
@@ -42,7 +42,10 @@ static inline void *memset32(uint32_t *p, uint32_t v, __kernel_size_t n)
extern void *__memset64(uint64_t *, uint32_t low, __kernel_size_t, uint32_t hi);
static inline void *memset64(uint64_t *p, uint64_t v, __kernel_size_t n)
{
- return __memset64(p, v, n * 8, v >> 32);
+ if (IS_ENABLED(CONFIG_CPU_LITTLE_ENDIAN))
+ return __memset64(p, v, n * 8, v >> 32);
+ else
+ return __memset64(p, v >> 32, n * 8, v);
}
/*
diff --git a/arch/x86/include/asm/kfence.h b/arch/x86/include/asm/kfence.h
index acf9ffa1a171..dfd5c74ba41a 100644
--- a/arch/x86/include/asm/kfence.h
+++ b/arch/x86/include/asm/kfence.h
@@ -42,7 +42,7 @@ static inline bool kfence_protect_page(unsigned long addr, bool protect)
{
unsigned int level;
pte_t *pte = lookup_address(addr, &level);
- pteval_t val;
+ pteval_t val, new;
if (WARN_ON(!pte || level != PG_LEVEL_4K))
return false;
@@ -57,11 +57,12 @@ static inline bool kfence_protect_page(unsigned long addr, bool protect)
return true;
/*
- * Otherwise, invert the entire PTE. This avoids writing out an
+ * Otherwise, flip the Present bit, taking care to avoid writing an
* L1TF-vulnerable PTE (not present, without the high address bits
* set).
*/
- set_pte(pte, __pte(~val));
+ new = val ^ _PAGE_PRESENT;
+ set_pte(pte, __pte(flip_protnone_guard(val, new, PTE_PFN_MASK)));
/*
* If the page was protected (non-present) and we're making it
diff --git a/arch/x86/kvm/irq.c b/arch/x86/kvm/irq.c
index 7cc8950005b6..4c7688670c2d 100644
--- a/arch/x86/kvm/irq.c
+++ b/arch/x86/kvm/irq.c
@@ -514,7 +514,8 @@ void kvm_arch_irq_bypass_del_producer(struct irq_bypass_consumer *cons,
*/
spin_lock_irq(&kvm->irqfds.lock);
- if (irqfd->irq_entry.type == KVM_IRQ_ROUTING_MSI) {
+ if (irqfd->irq_entry.type == KVM_IRQ_ROUTING_MSI ||
+ WARN_ON_ONCE(irqfd->irq_bypass_vcpu)) {
ret = kvm_pi_update_irte(irqfd, NULL);
if (ret)
pr_info("irq bypass consumer (eventfd %p) unregistration fails: %d\n",
diff --git a/arch/x86/kvm/svm/avic.c b/arch/x86/kvm/svm/avic.c
index 6b77b2033208..0f6c8596719b 100644
--- a/arch/x86/kvm/svm/avic.c
+++ b/arch/x86/kvm/svm/avic.c
@@ -376,6 +376,7 @@ void avic_init_vmcb(struct vcpu_svm *svm, struct vmcb *vmcb)
static int avic_init_backing_page(struct kvm_vcpu *vcpu)
{
+ u32 max_id = x2avic_enabled ? x2avic_max_physical_id : AVIC_MAX_PHYSICAL_ID;
struct kvm_svm *kvm_svm = to_kvm_svm(vcpu->kvm);
struct vcpu_svm *svm = to_svm(vcpu);
u32 id = vcpu->vcpu_id;
@@ -388,8 +389,7 @@ static int avic_init_backing_page(struct kvm_vcpu *vcpu)
* avic_vcpu_load() expects to be called if and only if the vCPU has
* fully initialized AVIC.
*/
- if ((!x2avic_enabled && id > AVIC_MAX_PHYSICAL_ID) ||
- (id > x2avic_max_physical_id)) {
+ if (id > max_id) {
kvm_set_apicv_inhibit(vcpu->kvm, APICV_INHIBIT_REASON_PHYSICAL_ID_TOO_BIG);
vcpu->arch.apic->apicv_active = false;
return 0;
diff --git a/arch/x86/kvm/svm/svm.c b/arch/x86/kvm/svm/svm.c
index 24d59ccfa40d..4394be40fe78 100644
--- a/arch/x86/kvm/svm/svm.c
+++ b/arch/x86/kvm/svm/svm.c
@@ -5284,6 +5284,8 @@ static __init void svm_set_cpu_caps(void)
*/
kvm_cpu_cap_clear(X86_FEATURE_BUS_LOCK_DETECT);
kvm_cpu_cap_clear(X86_FEATURE_MSR_IMM);
+
+ kvm_setup_xss_caps();
}
static __init int svm_hardware_setup(void)
diff --git a/arch/x86/kvm/vmx/vmx.c b/arch/x86/kvm/vmx/vmx.c
index 6b96f7aea20b..8c94241fbcca 100644
--- a/arch/x86/kvm/vmx/vmx.c
+++ b/arch/x86/kvm/vmx/vmx.c
@@ -8051,6 +8051,8 @@ static __init void vmx_set_cpu_caps(void)
kvm_cpu_cap_clear(X86_FEATURE_SHSTK);
kvm_cpu_cap_clear(X86_FEATURE_IBT);
}
+
+ kvm_setup_xss_caps();
}
static bool vmx_is_io_intercepted(struct kvm_vcpu *vcpu,
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index 63afdb6bb078..72d37c8930ad 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -9953,6 +9953,23 @@ static struct notifier_block pvclock_gtod_notifier = {
};
#endif
+void kvm_setup_xss_caps(void)
+{
+ if (!kvm_cpu_cap_has(X86_FEATURE_XSAVES))
+ kvm_caps.supported_xss = 0;
+
+ if (!kvm_cpu_cap_has(X86_FEATURE_SHSTK) &&
+ !kvm_cpu_cap_has(X86_FEATURE_IBT))
+ kvm_caps.supported_xss &= ~XFEATURE_MASK_CET_ALL;
+
+ if ((kvm_caps.supported_xss & XFEATURE_MASK_CET_ALL) != XFEATURE_MASK_CET_ALL) {
+ kvm_cpu_cap_clear(X86_FEATURE_SHSTK);
+ kvm_cpu_cap_clear(X86_FEATURE_IBT);
+ kvm_caps.supported_xss &= ~XFEATURE_MASK_CET_ALL;
+ }
+}
+EXPORT_SYMBOL_FOR_KVM_INTERNAL(kvm_setup_xss_caps);
+
static inline void kvm_ops_update(struct kvm_x86_init_ops *ops)
{
memcpy(&kvm_x86_ops, ops->runtime_ops, sizeof(kvm_x86_ops));
@@ -10125,19 +10142,6 @@ int kvm_x86_vendor_init(struct kvm_x86_init_ops *ops)
if (!tdp_enabled)
kvm_caps.supported_quirks &= ~KVM_X86_QUIRK_IGNORE_GUEST_PAT;
- if (!kvm_cpu_cap_has(X86_FEATURE_XSAVES))
- kvm_caps.supported_xss = 0;
-
- if (!kvm_cpu_cap_has(X86_FEATURE_SHSTK) &&
- !kvm_cpu_cap_has(X86_FEATURE_IBT))
- kvm_caps.supported_xss &= ~XFEATURE_MASK_CET_ALL;
-
- if ((kvm_caps.supported_xss & XFEATURE_MASK_CET_ALL) != XFEATURE_MASK_CET_ALL) {
- kvm_cpu_cap_clear(X86_FEATURE_SHSTK);
- kvm_cpu_cap_clear(X86_FEATURE_IBT);
- kvm_caps.supported_xss &= ~XFEATURE_MASK_CET_ALL;
- }
-
if (kvm_caps.has_tsc_control) {
/*
* Make sure the user can only configure tsc_khz values that
diff --git a/arch/x86/kvm/x86.h b/arch/x86/kvm/x86.h
index fdab0ad49098..00de24f55b1f 100644
--- a/arch/x86/kvm/x86.h
+++ b/arch/x86/kvm/x86.h
@@ -471,6 +471,8 @@ extern struct kvm_host_values kvm_host;
extern bool enable_pmu;
+void kvm_setup_xss_caps(void);
+
/*
* Get a filtered version of KVM's supported XCR0 that strips out dynamic
* features for which the current process doesn't (yet) have permission to use.
diff --git a/drivers/android/binder/rust_binderfs.c b/drivers/android/binder/rust_binderfs.c
index c69026df775c..e36011e89116 100644
--- a/drivers/android/binder/rust_binderfs.c
+++ b/drivers/android/binder/rust_binderfs.c
@@ -391,12 +391,6 @@ static int binderfs_binder_ctl_create(struct super_block *sb)
if (!device)
return -ENOMEM;
- /* If we have already created a binder-control node, return. */
- if (info->control_dentry) {
- ret = 0;
- goto out;
- }
-
ret = -ENOMEM;
inode = new_inode(sb);
if (!inode)
@@ -431,7 +425,8 @@ static int binderfs_binder_ctl_create(struct super_block *sb)
inode->i_private = device;
info->control_dentry = dentry;
- d_add(dentry, inode);
+ d_make_persistent(dentry, inode);
+ dput(dentry);
return 0;
diff --git a/drivers/block/loop.c b/drivers/block/loop.c
index bd59c0e9508b..32a3a5b13802 100644
--- a/drivers/block/loop.c
+++ b/drivers/block/loop.c
@@ -1225,28 +1225,16 @@ static int loop_clr_fd(struct loop_device *lo)
}
static int
-loop_set_status(struct loop_device *lo, blk_mode_t mode,
- struct block_device *bdev, const struct loop_info64 *info)
+loop_set_status(struct loop_device *lo, const struct loop_info64 *info)
{
int err;
bool partscan = false;
bool size_changed = false;
unsigned int memflags;
- /*
- * If we don't hold exclusive handle for the device, upgrade to it
- * here to avoid changing device under exclusive owner.
- */
- if (!(mode & BLK_OPEN_EXCL)) {
- err = bd_prepare_to_claim(bdev, loop_set_status, NULL);
- if (err)
- goto out_reread_partitions;
- }
-
err = mutex_lock_killable(&lo->lo_mutex);
if (err)
- goto out_abort_claiming;
-
+ return err;
if (lo->lo_state != Lo_bound) {
err = -ENXIO;
goto out_unlock;
@@ -1285,10 +1273,6 @@ out_unfreeze:
}
out_unlock:
mutex_unlock(&lo->lo_mutex);
-out_abort_claiming:
- if (!(mode & BLK_OPEN_EXCL))
- bd_abort_claiming(bdev, loop_set_status);
-out_reread_partitions:
if (partscan)
loop_reread_partitions(lo);
@@ -1368,9 +1352,7 @@ loop_info64_to_old(const struct loop_info64 *info64, struct loop_info *info)
}
static int
-loop_set_status_old(struct loop_device *lo, blk_mode_t mode,
- struct block_device *bdev,
- const struct loop_info __user *arg)
+loop_set_status_old(struct loop_device *lo, const struct loop_info __user *arg)
{
struct loop_info info;
struct loop_info64 info64;
@@ -1378,19 +1360,17 @@ loop_set_status_old(struct loop_device *lo, blk_mode_t mode,
if (copy_from_user(&info, arg, sizeof (struct loop_info)))
return -EFAULT;
loop_info64_from_old(&info, &info64);
- return loop_set_status(lo, mode, bdev, &info64);
+ return loop_set_status(lo, &info64);
}
static int
-loop_set_status64(struct loop_device *lo, blk_mode_t mode,
- struct block_device *bdev,
- const struct loop_info64 __user *arg)
+loop_set_status64(struct loop_device *lo, const struct loop_info64 __user *arg)
{
struct loop_info64 info64;
if (copy_from_user(&info64, arg, sizeof (struct loop_info64)))
return -EFAULT;
- return loop_set_status(lo, mode, bdev, &info64);
+ return loop_set_status(lo, &info64);
}
static int
@@ -1569,14 +1549,14 @@ static int lo_ioctl(struct block_device *bdev, blk_mode_t mode,
case LOOP_SET_STATUS:
err = -EPERM;
if ((mode & BLK_OPEN_WRITE) || capable(CAP_SYS_ADMIN))
- err = loop_set_status_old(lo, mode, bdev, argp);
+ err = loop_set_status_old(lo, argp);
break;
case LOOP_GET_STATUS:
return loop_get_status_old(lo, argp);
case LOOP_SET_STATUS64:
err = -EPERM;
if ((mode & BLK_OPEN_WRITE) || capable(CAP_SYS_ADMIN))
- err = loop_set_status64(lo, mode, bdev, argp);
+ err = loop_set_status64(lo, argp);
break;
case LOOP_GET_STATUS64:
return loop_get_status64(lo, argp);
@@ -1670,9 +1650,8 @@ loop_info64_to_compat(const struct loop_info64 *info64,
}
static int
-loop_set_status_compat(struct loop_device *lo, blk_mode_t mode,
- struct block_device *bdev,
- const struct compat_loop_info __user *arg)
+loop_set_status_compat(struct loop_device *lo,
+ const struct compat_loop_info __user *arg)
{
struct loop_info64 info64;
int ret;
@@ -1680,7 +1659,7 @@ loop_set_status_compat(struct loop_device *lo, blk_mode_t mode,
ret = loop_info64_from_compat(arg, &info64);
if (ret < 0)
return ret;
- return loop_set_status(lo, mode, bdev, &info64);
+ return loop_set_status(lo, &info64);
}
static int
@@ -1706,7 +1685,7 @@ static int lo_compat_ioctl(struct block_device *bdev, blk_mode_t mode,
switch(cmd) {
case LOOP_SET_STATUS:
- err = loop_set_status_compat(lo, mode, bdev,
+ err = loop_set_status_compat(lo,
(const struct compat_loop_info __user *)arg);
break;
case LOOP_GET_STATUS:
diff --git a/drivers/crypto/ccp/sev-dev-tsm.c b/drivers/crypto/ccp/sev-dev-tsm.c
index ea29cd5d0ff9..40d02adaf3f6 100644
--- a/drivers/crypto/ccp/sev-dev-tsm.c
+++ b/drivers/crypto/ccp/sev-dev-tsm.c
@@ -19,12 +19,6 @@
MODULE_IMPORT_NS("PCI_IDE");
-#define TIO_DEFAULT_NR_IDE_STREAMS 1
-
-static uint nr_ide_streams = TIO_DEFAULT_NR_IDE_STREAMS;
-module_param_named(ide_nr, nr_ide_streams, uint, 0644);
-MODULE_PARM_DESC(ide_nr, "Set the maximum number of IDE streams per PHB");
-
#define dev_to_sp(dev) ((struct sp_device *)dev_get_drvdata(dev))
#define dev_to_psp(dev) ((struct psp_device *)(dev_to_sp(dev)->psp_data))
#define dev_to_sev(dev) ((struct sev_device *)(dev_to_psp(dev)->sev_data))
@@ -193,7 +187,6 @@ static void streams_teardown(struct pci_ide **ide)
static int stream_alloc(struct pci_dev *pdev, struct pci_ide **ide,
unsigned int tc)
{
- struct pci_dev *rp = pcie_find_root_port(pdev);
struct pci_ide *ide1;
if (ide[tc]) {
@@ -201,17 +194,11 @@ static int stream_alloc(struct pci_dev *pdev, struct pci_ide **ide,
return -EBUSY;
}
- /* FIXME: find a better way */
- if (nr_ide_streams != TIO_DEFAULT_NR_IDE_STREAMS)
- pci_notice(pdev, "Enable non-default %d streams", nr_ide_streams);
- pci_ide_set_nr_streams(to_pci_host_bridge(rp->bus->bridge), nr_ide_streams);
-
ide1 = pci_ide_stream_alloc(pdev);
if (!ide1)
return -EFAULT;
- /* Blindly assign streamid=0 to TC=0, and so on */
- ide1->stream_id = tc;
+ ide1->stream_id = ide1->host_bridge_stream;
ide[tc] = ide1;
diff --git a/drivers/firmware/cirrus/cs_dsp.c b/drivers/firmware/cirrus/cs_dsp.c
index 525ac0f0a75d..73d201e7d992 100644
--- a/drivers/firmware/cirrus/cs_dsp.c
+++ b/drivers/firmware/cirrus/cs_dsp.c
@@ -9,6 +9,7 @@
* Cirrus Logic International Semiconductor Ltd.
*/
+#include <kunit/visibility.h>
#include <linux/cleanup.h>
#include <linux/ctype.h>
#include <linux/debugfs.h>
@@ -24,6 +25,41 @@
#include <linux/firmware/cirrus/cs_dsp.h>
#include <linux/firmware/cirrus/wmfw.h>
+#include "cs_dsp.h"
+
+/*
+ * When the KUnit test is running the error-case tests will cause a lot
+ * of messages. Rate-limit to prevent overflowing the kernel log buffer
+ * during KUnit test runs.
+ */
+#if IS_ENABLED(CONFIG_FW_CS_DSP_KUNIT_TEST)
+bool cs_dsp_suppress_err_messages;
+EXPORT_SYMBOL_IF_KUNIT(cs_dsp_suppress_err_messages);
+
+bool cs_dsp_suppress_warn_messages;
+EXPORT_SYMBOL_IF_KUNIT(cs_dsp_suppress_warn_messages);
+
+bool cs_dsp_suppress_info_messages;
+EXPORT_SYMBOL_IF_KUNIT(cs_dsp_suppress_info_messages);
+
+#define cs_dsp_err(_dsp, fmt, ...) \
+ do { \
+ if (!cs_dsp_suppress_err_messages) \
+ dev_err_ratelimited(_dsp->dev, "%s: " fmt, _dsp->name, ##__VA_ARGS__); \
+ } while (false)
+#define cs_dsp_warn(_dsp, fmt, ...) \
+ do { \
+ if (!cs_dsp_suppress_warn_messages) \
+ dev_warn_ratelimited(_dsp->dev, "%s: " fmt, _dsp->name, ##__VA_ARGS__); \
+ } while (false)
+#define cs_dsp_info(_dsp, fmt, ...) \
+ do { \
+ if (!cs_dsp_suppress_info_messages) \
+ dev_info_ratelimited(_dsp->dev, "%s: " fmt, _dsp->name, ##__VA_ARGS__); \
+ } while (false)
+#define cs_dsp_dbg(_dsp, fmt, ...) \
+ dev_dbg_ratelimited(_dsp->dev, "%s: " fmt, _dsp->name, ##__VA_ARGS__)
+#else
#define cs_dsp_err(_dsp, fmt, ...) \
dev_err(_dsp->dev, "%s: " fmt, _dsp->name, ##__VA_ARGS__)
#define cs_dsp_warn(_dsp, fmt, ...) \
@@ -32,6 +68,7 @@
dev_info(_dsp->dev, "%s: " fmt, _dsp->name, ##__VA_ARGS__)
#define cs_dsp_dbg(_dsp, fmt, ...) \
dev_dbg(_dsp->dev, "%s: " fmt, _dsp->name, ##__VA_ARGS__)
+#endif
#define ADSP1_CONTROL_1 0x00
#define ADSP1_CONTROL_2 0x02
diff --git a/drivers/firmware/cirrus/cs_dsp.h b/drivers/firmware/cirrus/cs_dsp.h
new file mode 100644
index 000000000000..adf543004aea
--- /dev/null
+++ b/drivers/firmware/cirrus/cs_dsp.h
@@ -0,0 +1,18 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * cs_dsp.h -- Private header for cs_dsp driver.
+ *
+ * Copyright (C) 2026 Cirrus Logic, Inc. and
+ * Cirrus Logic International Semiconductor Ltd.
+ */
+
+#ifndef FW_CS_DSP_H
+#define FW_CS_DSP_H
+
+#if IS_ENABLED(CONFIG_KUNIT)
+extern bool cs_dsp_suppress_err_messages;
+extern bool cs_dsp_suppress_warn_messages;
+extern bool cs_dsp_suppress_info_messages;
+#endif
+
+#endif /* ifndef FW_CS_DSP_H */
diff --git a/drivers/firmware/cirrus/test/cs_dsp_test_bin.c b/drivers/firmware/cirrus/test/cs_dsp_test_bin.c
index 163b7faecff4..2c6486fa9575 100644
--- a/drivers/firmware/cirrus/test/cs_dsp_test_bin.c
+++ b/drivers/firmware/cirrus/test/cs_dsp_test_bin.c
@@ -17,6 +17,8 @@
#include <linux/random.h>
#include <linux/regmap.h>
+#include "../cs_dsp.h"
+
/*
* Test method is:
*
@@ -2224,7 +2226,22 @@ static int cs_dsp_bin_test_common_init(struct kunit *test, struct cs_dsp *dsp)
return ret;
/* Automatically call cs_dsp_remove() when test case ends */
- return kunit_add_action_or_reset(priv->test, _cs_dsp_remove_wrapper, dsp);
+ ret = kunit_add_action_or_reset(priv->test, _cs_dsp_remove_wrapper, dsp);
+ if (ret)
+ return ret;
+
+ /*
+ * The large number of test cases will cause an unusually large amount
+ * of dev_info() messages from cs_dsp, so suppress these.
+ */
+ cs_dsp_suppress_info_messages = true;
+
+ return 0;
+}
+
+static void cs_dsp_bin_test_exit(struct kunit *test)
+{
+ cs_dsp_suppress_info_messages = false;
}
static int cs_dsp_bin_test_halo_init(struct kunit *test)
@@ -2536,18 +2553,21 @@ static struct kunit_case cs_dsp_bin_test_cases_adsp2[] = {
static struct kunit_suite cs_dsp_bin_test_halo = {
.name = "cs_dsp_bin_halo",
.init = cs_dsp_bin_test_halo_init,
+ .exit = cs_dsp_bin_test_exit,
.test_cases = cs_dsp_bin_test_cases_halo,
};
static struct kunit_suite cs_dsp_bin_test_adsp2_32bit = {
.name = "cs_dsp_bin_adsp2_32bit",
.init = cs_dsp_bin_test_adsp2_32bit_init,
+ .exit = cs_dsp_bin_test_exit,
.test_cases = cs_dsp_bin_test_cases_adsp2,
};
static struct kunit_suite cs_dsp_bin_test_adsp2_16bit = {
.name = "cs_dsp_bin_adsp2_16bit",
.init = cs_dsp_bin_test_adsp2_16bit_init,
+ .exit = cs_dsp_bin_test_exit,
.test_cases = cs_dsp_bin_test_cases_adsp2,
};
diff --git a/drivers/firmware/cirrus/test/cs_dsp_test_bin_error.c b/drivers/firmware/cirrus/test/cs_dsp_test_bin_error.c
index a7ec956d2724..631b9cb9eb25 100644
--- a/drivers/firmware/cirrus/test/cs_dsp_test_bin_error.c
+++ b/drivers/firmware/cirrus/test/cs_dsp_test_bin_error.c
@@ -18,6 +18,8 @@
#include <linux/string.h>
#include <linux/vmalloc.h>
+#include "../cs_dsp.h"
+
KUNIT_DEFINE_ACTION_WRAPPER(_put_device_wrapper, put_device, struct device *);
KUNIT_DEFINE_ACTION_WRAPPER(_cs_dsp_remove_wrapper, cs_dsp_remove, struct cs_dsp *);
@@ -380,11 +382,9 @@ static void bin_block_payload_len_garbage(struct kunit *test)
static void cs_dsp_bin_err_test_exit(struct kunit *test)
{
- /*
- * Testing error conditions can produce a lot of log output
- * from cs_dsp error messages, so rate limit the test cases.
- */
- usleep_range(200, 500);
+ cs_dsp_suppress_err_messages = false;
+ cs_dsp_suppress_warn_messages = false;
+ cs_dsp_suppress_info_messages = false;
}
static int cs_dsp_bin_err_test_common_init(struct kunit *test, struct cs_dsp *dsp,
@@ -474,7 +474,19 @@ static int cs_dsp_bin_err_test_common_init(struct kunit *test, struct cs_dsp *ds
return ret;
/* Automatically call cs_dsp_remove() when test case ends */
- return kunit_add_action_or_reset(priv->test, _cs_dsp_remove_wrapper, dsp);
+ ret = kunit_add_action_or_reset(priv->test, _cs_dsp_remove_wrapper, dsp);
+ if (ret)
+ return ret;
+
+ /*
+ * Testing error conditions can produce a lot of log output
+ * from cs_dsp error messages, so suppress messages.
+ */
+ cs_dsp_suppress_err_messages = true;
+ cs_dsp_suppress_warn_messages = true;
+ cs_dsp_suppress_info_messages = true;
+
+ return 0;
}
static int cs_dsp_bin_err_test_halo_init(struct kunit *test)
diff --git a/drivers/firmware/cirrus/test/cs_dsp_test_wmfw.c b/drivers/firmware/cirrus/test/cs_dsp_test_wmfw.c
index 9e997c4ee2d6..f02cb6cf7638 100644
--- a/drivers/firmware/cirrus/test/cs_dsp_test_wmfw.c
+++ b/drivers/firmware/cirrus/test/cs_dsp_test_wmfw.c
@@ -18,6 +18,8 @@
#include <linux/string.h>
#include <linux/vmalloc.h>
+#include "../cs_dsp.h"
+
/*
* Test method is:
*
@@ -1853,7 +1855,22 @@ static int cs_dsp_wmfw_test_common_init(struct kunit *test, struct cs_dsp *dsp,
return ret;
/* Automatically call cs_dsp_remove() when test case ends */
- return kunit_add_action_or_reset(priv->test, _cs_dsp_remove_wrapper, dsp);
+ ret = kunit_add_action_or_reset(priv->test, _cs_dsp_remove_wrapper, dsp);
+ if (ret)
+ return ret;
+
+ /*
+ * The large number of test cases will cause an unusually large amount
+ * of dev_info() messages from cs_dsp, so suppress these.
+ */
+ cs_dsp_suppress_info_messages = true;
+
+ return 0;
+}
+
+static void cs_dsp_wmfw_test_exit(struct kunit *test)
+{
+ cs_dsp_suppress_info_messages = false;
}
static int cs_dsp_wmfw_test_halo_init(struct kunit *test)
@@ -2163,42 +2180,49 @@ static struct kunit_case cs_dsp_wmfw_test_cases_adsp2[] = {
static struct kunit_suite cs_dsp_wmfw_test_halo = {
.name = "cs_dsp_wmfwV3_halo",
.init = cs_dsp_wmfw_test_halo_init,
+ .exit = cs_dsp_wmfw_test_exit,
.test_cases = cs_dsp_wmfw_test_cases_halo,
};
static struct kunit_suite cs_dsp_wmfw_test_adsp2_32bit_wmfw0 = {
.name = "cs_dsp_wmfwV0_adsp2_32bit",
.init = cs_dsp_wmfw_test_adsp2_32bit_wmfw0_init,
+ .exit = cs_dsp_wmfw_test_exit,
.test_cases = cs_dsp_wmfw_test_cases_adsp2,
};
static struct kunit_suite cs_dsp_wmfw_test_adsp2_32bit_wmfw1 = {
.name = "cs_dsp_wmfwV1_adsp2_32bit",
.init = cs_dsp_wmfw_test_adsp2_32bit_wmfw1_init,
+ .exit = cs_dsp_wmfw_test_exit,
.test_cases = cs_dsp_wmfw_test_cases_adsp2,
};
static struct kunit_suite cs_dsp_wmfw_test_adsp2_32bit_wmfw2 = {
.name = "cs_dsp_wmfwV2_adsp2_32bit",
.init = cs_dsp_wmfw_test_adsp2_32bit_wmfw2_init,
+ .exit = cs_dsp_wmfw_test_exit,
.test_cases = cs_dsp_wmfw_test_cases_adsp2,
};
static struct kunit_suite cs_dsp_wmfw_test_adsp2_16bit_wmfw0 = {
.name = "cs_dsp_wmfwV0_adsp2_16bit",
.init = cs_dsp_wmfw_test_adsp2_16bit_wmfw0_init,
+ .exit = cs_dsp_wmfw_test_exit,
.test_cases = cs_dsp_wmfw_test_cases_adsp2,
};
static struct kunit_suite cs_dsp_wmfw_test_adsp2_16bit_wmfw1 = {
.name = "cs_dsp_wmfwV1_adsp2_16bit",
.init = cs_dsp_wmfw_test_adsp2_16bit_wmfw1_init,
+ .exit = cs_dsp_wmfw_test_exit,
.test_cases = cs_dsp_wmfw_test_cases_adsp2,
};
static struct kunit_suite cs_dsp_wmfw_test_adsp2_16bit_wmfw2 = {
.name = "cs_dsp_wmfwV2_adsp2_16bit",
.init = cs_dsp_wmfw_test_adsp2_16bit_wmfw2_init,
+ .exit = cs_dsp_wmfw_test_exit,
.test_cases = cs_dsp_wmfw_test_cases_adsp2,
};
diff --git a/drivers/firmware/cirrus/test/cs_dsp_test_wmfw_error.c b/drivers/firmware/cirrus/test/cs_dsp_test_wmfw_error.c
index c309843261d7..37162d12e2fa 100644
--- a/drivers/firmware/cirrus/test/cs_dsp_test_wmfw_error.c
+++ b/drivers/firmware/cirrus/test/cs_dsp_test_wmfw_error.c
@@ -18,6 +18,8 @@
#include <linux/string.h>
#include <linux/vmalloc.h>
+#include "../cs_dsp.h"
+
KUNIT_DEFINE_ACTION_WRAPPER(_put_device_wrapper, put_device, struct device *);
KUNIT_DEFINE_ACTION_WRAPPER(_cs_dsp_remove_wrapper, cs_dsp_remove, struct cs_dsp *);
@@ -989,11 +991,9 @@ static void wmfw_v2_coeff_description_exceeds_block(struct kunit *test)
static void cs_dsp_wmfw_err_test_exit(struct kunit *test)
{
- /*
- * Testing error conditions can produce a lot of log output
- * from cs_dsp error messages, so rate limit the test cases.
- */
- usleep_range(200, 500);
+ cs_dsp_suppress_err_messages = false;
+ cs_dsp_suppress_warn_messages = false;
+ cs_dsp_suppress_info_messages = false;
}
static int cs_dsp_wmfw_err_test_common_init(struct kunit *test, struct cs_dsp *dsp,
@@ -1072,7 +1072,19 @@ static int cs_dsp_wmfw_err_test_common_init(struct kunit *test, struct cs_dsp *d
return ret;
/* Automatically call cs_dsp_remove() when test case ends */
- return kunit_add_action_or_reset(priv->test, _cs_dsp_remove_wrapper, dsp);
+ ret = kunit_add_action_or_reset(priv->test, _cs_dsp_remove_wrapper, dsp);
+ if (ret)
+ return ret;
+
+ /*
+ * Testing error conditions can produce a lot of log output
+ * from cs_dsp error messages, so suppress messages.
+ */
+ cs_dsp_suppress_err_messages = true;
+ cs_dsp_suppress_warn_messages = true;
+ cs_dsp_suppress_info_messages = true;
+
+ return 0;
}
static int cs_dsp_wmfw_err_test_halo_init(struct kunit *test)
diff --git a/drivers/firmware/cirrus/test/cs_dsp_tests.c b/drivers/firmware/cirrus/test/cs_dsp_tests.c
index 7b829a03ca52..288675fdbdc5 100644
--- a/drivers/firmware/cirrus/test/cs_dsp_tests.c
+++ b/drivers/firmware/cirrus/test/cs_dsp_tests.c
@@ -12,3 +12,4 @@ MODULE_AUTHOR("Richard Fitzgerald <rf@opensource.cirrus.com>");
MODULE_LICENSE("GPL");
MODULE_IMPORT_NS("FW_CS_DSP");
MODULE_IMPORT_NS("FW_CS_DSP_KUNIT_TEST_UTILS");
+MODULE_IMPORT_NS("EXPORTED_FOR_KUNIT_TESTING");
diff --git a/drivers/gpio/gpio-loongson-64bit.c b/drivers/gpio/gpio-loongson-64bit.c
index 77d07e31366f..0fdf15faa344 100644
--- a/drivers/gpio/gpio-loongson-64bit.c
+++ b/drivers/gpio/gpio-loongson-64bit.c
@@ -263,7 +263,7 @@ static int loongson_gpio_init_irqchip(struct platform_device *pdev,
chip->irq.num_parents = data->intr_num;
chip->irq.parents = devm_kcalloc(&pdev->dev, data->intr_num,
sizeof(*chip->irq.parents), GFP_KERNEL);
- if (!chip->parent)
+ if (!chip->irq.parents)
return -ENOMEM;
for (i = 0; i < data->intr_num; i++) {
diff --git a/drivers/gpio/gpiolib-acpi-core.c b/drivers/gpio/gpiolib-acpi-core.c
index 9627b3a9c7f3..5e709ba35ec2 100644
--- a/drivers/gpio/gpiolib-acpi-core.c
+++ b/drivers/gpio/gpiolib-acpi-core.c
@@ -1359,6 +1359,7 @@ static int acpi_gpio_package_count(const union acpi_object *obj)
while (element < end) {
switch (element->type) {
case ACPI_TYPE_LOCAL_REFERENCE:
+ case ACPI_TYPE_STRING:
element += 3;
fallthrough;
case ACPI_TYPE_INTEGER:
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c
index b1c24c8fa686..a51e76623bad 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c
@@ -1920,21 +1920,21 @@ int amdgpu_amdkfd_gpuvm_free_memory_of_gpu(
/* Make sure restore workers don't access the BO any more */
mutex_lock(&process_info->lock);
- list_del(&mem->validate_list);
+ if (!list_empty(&mem->validate_list))
+ list_del_init(&mem->validate_list);
mutex_unlock(&process_info->lock);
+ ret = reserve_bo_and_cond_vms(mem, NULL, BO_VM_ALL, &ctx);
+ if (unlikely(ret))
+ return ret;
+
/* Cleanup user pages and MMU notifiers */
if (amdgpu_ttm_tt_get_usermm(mem->bo->tbo.ttm)) {
amdgpu_hmm_unregister(mem->bo);
- mutex_lock(&process_info->notifier_lock);
amdgpu_hmm_range_free(mem->range);
- mutex_unlock(&process_info->notifier_lock);
+ mem->range = NULL;
}
- ret = reserve_bo_and_cond_vms(mem, NULL, BO_VM_ALL, &ctx);
- if (unlikely(ret))
- return ret;
-
amdgpu_amdkfd_remove_eviction_fence(mem->bo,
process_info->eviction_fence);
pr_debug("Release VA 0x%llx - 0x%llx\n", mem->va,
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
index 6ccb80e2d7c9..39387da8586b 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
@@ -2405,9 +2405,6 @@ static int amdgpu_pci_probe(struct pci_dev *pdev,
return -ENODEV;
}
- if (amdgpu_aspm == -1 && !pcie_aspm_enabled(pdev))
- amdgpu_aspm = 0;
-
if (amdgpu_virtual_display ||
amdgpu_device_asic_has_dc_support(pdev, flags & AMD_ASIC_MASK))
supports_atomic = true;
diff --git a/drivers/gpu/drm/amd/amdgpu/mes_v11_0.c b/drivers/gpu/drm/amd/amdgpu/mes_v11_0.c
index 3a52754b5cad..ceddc953785f 100644
--- a/drivers/gpu/drm/amd/amdgpu/mes_v11_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/mes_v11_0.c
@@ -1671,7 +1671,7 @@ static int mes_v11_0_hw_init(struct amdgpu_ip_block *ip_block)
if (r)
goto failure;
- if ((adev->mes.sched_version & AMDGPU_MES_VERSION_MASK) >= 0x50) {
+ if ((adev->mes.sched_version & AMDGPU_MES_VERSION_MASK) >= 0x52) {
r = mes_v11_0_set_hw_resources_1(&adev->mes);
if (r) {
DRM_ERROR("failed mes_v11_0_set_hw_resources_1, r=%d\n", r);
diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_cm_common.c b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_cm_common.c
index 0690c346f2c5..227aa8672d17 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_cm_common.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_cm_common.c
@@ -105,9 +105,12 @@ void cm_helper_program_gamcor_xfer_func(
#define NUMBER_REGIONS 32
#define NUMBER_SW_SEGMENTS 16
-bool cm3_helper_translate_curve_to_hw_format(
- const struct dc_transfer_func *output_tf,
- struct pwl_params *lut_params, bool fixpoint)
+#define DC_LOGGER \
+ ctx->logger
+
+bool cm3_helper_translate_curve_to_hw_format(struct dc_context *ctx,
+ const struct dc_transfer_func *output_tf,
+ struct pwl_params *lut_params, bool fixpoint)
{
struct curve_points3 *corner_points;
struct pwl_result_data *rgb_resulted;
@@ -163,6 +166,11 @@ bool cm3_helper_translate_curve_to_hw_format(
hw_points += (1 << seg_distr[k]);
}
+ // DCN3+ have 257 pts in lieu of no separate slope registers
+ // Prior HW had 256 base+slope pairs
+ // Shaper LUT (i.e. fixpoint == true) is still 256 bases and 256 deltas
+ hw_points = fixpoint ? (hw_points - 1) : hw_points;
+
j = 0;
for (k = 0; k < (region_end - region_start); k++) {
increment = NUMBER_SW_SEGMENTS / (1 << seg_distr[k]);
@@ -223,8 +231,6 @@ bool cm3_helper_translate_curve_to_hw_format(
corner_points[1].green.slope = dc_fixpt_zero;
corner_points[1].blue.slope = dc_fixpt_zero;
- // DCN3+ have 257 pts in lieu of no separate slope registers
- // Prior HW had 256 base+slope pairs
lut_params->hw_points_num = hw_points + 1;
k = 0;
@@ -248,6 +254,10 @@ bool cm3_helper_translate_curve_to_hw_format(
if (fixpoint == true) {
i = 1;
while (i != hw_points + 2) {
+ uint32_t red_clamp;
+ uint32_t green_clamp;
+ uint32_t blue_clamp;
+
if (i >= hw_points) {
if (dc_fixpt_lt(rgb_plus_1->red, rgb->red))
rgb_plus_1->red = dc_fixpt_add(rgb->red,
@@ -260,9 +270,20 @@ bool cm3_helper_translate_curve_to_hw_format(
rgb_minus_1->delta_blue);
}
- rgb->delta_red_reg = dc_fixpt_clamp_u0d10(rgb->delta_red);
- rgb->delta_green_reg = dc_fixpt_clamp_u0d10(rgb->delta_green);
- rgb->delta_blue_reg = dc_fixpt_clamp_u0d10(rgb->delta_blue);
+ rgb->delta_red = dc_fixpt_sub(rgb_plus_1->red, rgb->red);
+ rgb->delta_green = dc_fixpt_sub(rgb_plus_1->green, rgb->green);
+ rgb->delta_blue = dc_fixpt_sub(rgb_plus_1->blue, rgb->blue);
+
+ red_clamp = dc_fixpt_clamp_u0d14(rgb->delta_red);
+ green_clamp = dc_fixpt_clamp_u0d14(rgb->delta_green);
+ blue_clamp = dc_fixpt_clamp_u0d14(rgb->delta_blue);
+
+ if (red_clamp >> 10 || green_clamp >> 10 || blue_clamp >> 10)
+ DC_LOG_ERROR("Losing delta precision while programming shaper LUT.");
+
+ rgb->delta_red_reg = red_clamp & 0x3ff;
+ rgb->delta_green_reg = green_clamp & 0x3ff;
+ rgb->delta_blue_reg = blue_clamp & 0x3ff;
rgb->red_reg = dc_fixpt_clamp_u0d14(rgb->red);
rgb->green_reg = dc_fixpt_clamp_u0d14(rgb->green);
rgb->blue_reg = dc_fixpt_clamp_u0d14(rgb->blue);
diff --git a/drivers/gpu/drm/amd/display/dc/dwb/dcn30/dcn30_cm_common.h b/drivers/gpu/drm/amd/display/dc/dwb/dcn30/dcn30_cm_common.h
index b86347c9b038..95f9318a54ef 100644
--- a/drivers/gpu/drm/amd/display/dc/dwb/dcn30/dcn30_cm_common.h
+++ b/drivers/gpu/drm/amd/display/dc/dwb/dcn30/dcn30_cm_common.h
@@ -59,7 +59,7 @@ void cm_helper_program_gamcor_xfer_func(
const struct pwl_params *params,
const struct dcn3_xfer_func_reg *reg);
-bool cm3_helper_translate_curve_to_hw_format(
+bool cm3_helper_translate_curve_to_hw_format(struct dc_context *ctx,
const struct dc_transfer_func *output_tf,
struct pwl_params *lut_params, bool fixpoint);
diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn30/dcn30_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn30/dcn30_hwseq.c
index 81bcadf5e57e..f2d4cd527874 100644
--- a/drivers/gpu/drm/amd/display/dc/hwss/dcn30/dcn30_hwseq.c
+++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn30/dcn30_hwseq.c
@@ -239,7 +239,7 @@ bool dcn30_set_blend_lut(
if (plane_state->blend_tf.type == TF_TYPE_HWPWL)
blend_lut = &plane_state->blend_tf.pwl;
else if (plane_state->blend_tf.type == TF_TYPE_DISTRIBUTED_POINTS) {
- result = cm3_helper_translate_curve_to_hw_format(
+ result = cm3_helper_translate_curve_to_hw_format(plane_state->ctx,
&plane_state->blend_tf, &dpp_base->regamma_params, false);
if (!result)
return result;
@@ -334,8 +334,9 @@ bool dcn30_set_input_transfer_func(struct dc *dc,
if (plane_state->in_transfer_func.type == TF_TYPE_HWPWL)
params = &plane_state->in_transfer_func.pwl;
else if (plane_state->in_transfer_func.type == TF_TYPE_DISTRIBUTED_POINTS &&
- cm3_helper_translate_curve_to_hw_format(&plane_state->in_transfer_func,
- &dpp_base->degamma_params, false))
+ cm3_helper_translate_curve_to_hw_format(plane_state->ctx,
+ &plane_state->in_transfer_func,
+ &dpp_base->degamma_params, false))
params = &dpp_base->degamma_params;
result = dpp_base->funcs->dpp_program_gamcor_lut(dpp_base, params);
@@ -406,7 +407,7 @@ bool dcn30_set_output_transfer_func(struct dc *dc,
params = &stream->out_transfer_func.pwl;
else if (pipe_ctx->stream->out_transfer_func.type ==
TF_TYPE_DISTRIBUTED_POINTS &&
- cm3_helper_translate_curve_to_hw_format(
+ cm3_helper_translate_curve_to_hw_format(stream->ctx,
&stream->out_transfer_func,
&mpc->blender_params, false))
params = &mpc->blender_params;
diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn32/dcn32_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn32/dcn32_hwseq.c
index bf19ba65d09a..be1f3caf4096 100644
--- a/drivers/gpu/drm/amd/display/dc/hwss/dcn32/dcn32_hwseq.c
+++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn32/dcn32_hwseq.c
@@ -486,8 +486,9 @@ bool dcn32_set_mcm_luts(
if (plane_state->blend_tf.type == TF_TYPE_HWPWL)
lut_params = &plane_state->blend_tf.pwl;
else if (plane_state->blend_tf.type == TF_TYPE_DISTRIBUTED_POINTS) {
- result = cm3_helper_translate_curve_to_hw_format(&plane_state->blend_tf,
- &dpp_base->regamma_params, false);
+ result = cm3_helper_translate_curve_to_hw_format(plane_state->ctx,
+ &plane_state->blend_tf,
+ &dpp_base->regamma_params, false);
if (!result)
return result;
@@ -501,9 +502,9 @@ bool dcn32_set_mcm_luts(
lut_params = &plane_state->in_shaper_func.pwl;
else if (plane_state->in_shaper_func.type == TF_TYPE_DISTRIBUTED_POINTS) {
// TODO: dpp_base replace
- ASSERT(false);
- cm3_helper_translate_curve_to_hw_format(&plane_state->in_shaper_func,
- &dpp_base->shaper_params, true);
+ cm3_helper_translate_curve_to_hw_format(plane_state->ctx,
+ &plane_state->in_shaper_func,
+ &dpp_base->shaper_params, true);
lut_params = &dpp_base->shaper_params;
}
@@ -543,8 +544,9 @@ bool dcn32_set_input_transfer_func(struct dc *dc,
if (plane_state->in_transfer_func.type == TF_TYPE_HWPWL)
params = &plane_state->in_transfer_func.pwl;
else if (plane_state->in_transfer_func.type == TF_TYPE_DISTRIBUTED_POINTS &&
- cm3_helper_translate_curve_to_hw_format(&plane_state->in_transfer_func,
- &dpp_base->degamma_params, false))
+ cm3_helper_translate_curve_to_hw_format(plane_state->ctx,
+ &plane_state->in_transfer_func,
+ &dpp_base->degamma_params, false))
params = &dpp_base->degamma_params;
dpp_base->funcs->dpp_program_gamcor_lut(dpp_base, params);
@@ -575,7 +577,7 @@ bool dcn32_set_output_transfer_func(struct dc *dc,
params = &stream->out_transfer_func.pwl;
else if (pipe_ctx->stream->out_transfer_func.type ==
TF_TYPE_DISTRIBUTED_POINTS &&
- cm3_helper_translate_curve_to_hw_format(
+ cm3_helper_translate_curve_to_hw_format(stream->ctx,
&stream->out_transfer_func,
&mpc->blender_params, false))
params = &mpc->blender_params;
diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.c
index 2fbc22afb89c..5eda7648d0d2 100644
--- a/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.c
+++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.c
@@ -430,7 +430,7 @@ void dcn401_populate_mcm_luts(struct dc *dc,
if (mcm_luts.lut1d_func->type == TF_TYPE_HWPWL)
m_lut_params.pwl = &mcm_luts.lut1d_func->pwl;
else if (mcm_luts.lut1d_func->type == TF_TYPE_DISTRIBUTED_POINTS) {
- rval = cm3_helper_translate_curve_to_hw_format(
+ rval = cm3_helper_translate_curve_to_hw_format(mpc->ctx,
mcm_luts.lut1d_func,
&dpp_base->regamma_params, false);
m_lut_params.pwl = rval ? &dpp_base->regamma_params : NULL;
@@ -450,7 +450,7 @@ void dcn401_populate_mcm_luts(struct dc *dc,
m_lut_params.pwl = &mcm_luts.shaper->pwl;
else if (mcm_luts.shaper->type == TF_TYPE_DISTRIBUTED_POINTS) {
ASSERT(false);
- rval = cm3_helper_translate_curve_to_hw_format(
+ rval = cm3_helper_translate_curve_to_hw_format(mpc->ctx,
mcm_luts.shaper,
&dpp_base->regamma_params, true);
m_lut_params.pwl = rval ? &dpp_base->regamma_params : NULL;
@@ -627,8 +627,9 @@ bool dcn401_set_mcm_luts(struct pipe_ctx *pipe_ctx,
if (plane_state->blend_tf.type == TF_TYPE_HWPWL)
lut_params = &plane_state->blend_tf.pwl;
else if (plane_state->blend_tf.type == TF_TYPE_DISTRIBUTED_POINTS) {
- rval = cm3_helper_translate_curve_to_hw_format(&plane_state->blend_tf,
- &dpp_base->regamma_params, false);
+ rval = cm3_helper_translate_curve_to_hw_format(plane_state->ctx,
+ &plane_state->blend_tf,
+ &dpp_base->regamma_params, false);
lut_params = rval ? &dpp_base->regamma_params : NULL;
}
result = mpc->funcs->program_1dlut(mpc, lut_params, mpcc_id);
@@ -639,8 +640,9 @@ bool dcn401_set_mcm_luts(struct pipe_ctx *pipe_ctx,
lut_params = &plane_state->in_shaper_func.pwl;
else if (plane_state->in_shaper_func.type == TF_TYPE_DISTRIBUTED_POINTS) {
// TODO: dpp_base replace
- rval = cm3_helper_translate_curve_to_hw_format(&plane_state->in_shaper_func,
- &dpp_base->shaper_params, true);
+ rval = cm3_helper_translate_curve_to_hw_format(plane_state->ctx,
+ &plane_state->in_shaper_func,
+ &dpp_base->shaper_params, true);
lut_params = rval ? &dpp_base->shaper_params : NULL;
}
result &= mpc->funcs->program_shaper(mpc, lut_params, mpcc_id);
@@ -674,7 +676,7 @@ bool dcn401_set_output_transfer_func(struct dc *dc,
params = &stream->out_transfer_func.pwl;
else if (pipe_ctx->stream->out_transfer_func.type ==
TF_TYPE_DISTRIBUTED_POINTS &&
- cm3_helper_translate_curve_to_hw_format(
+ cm3_helper_translate_curve_to_hw_format(stream->ctx,
&stream->out_transfer_func,
&mpc->blender_params, false))
params = &mpc->blender_params;
diff --git a/drivers/gpu/drm/bridge/imx/imx8mp-hdmi-pai.c b/drivers/gpu/drm/bridge/imx/imx8mp-hdmi-pai.c
index 8d13a35b206a..cc221483ef0d 100644
--- a/drivers/gpu/drm/bridge/imx/imx8mp-hdmi-pai.c
+++ b/drivers/gpu/drm/bridge/imx/imx8mp-hdmi-pai.c
@@ -8,6 +8,7 @@
#include <linux/module.h>
#include <linux/of_platform.h>
#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
#include <linux/regmap.h>
#include <drm/bridge/dw_hdmi.h>
#include <sound/asoundef.h>
@@ -33,6 +34,7 @@
struct imx8mp_hdmi_pai {
struct regmap *regmap;
+ struct device *dev;
};
static void imx8mp_hdmi_pai_enable(struct dw_hdmi *dw_hdmi, int channel,
@@ -43,6 +45,9 @@ static void imx8mp_hdmi_pai_enable(struct dw_hdmi *dw_hdmi, int channel,
struct imx8mp_hdmi_pai *hdmi_pai = pdata->priv_audio;
int val;
+ if (pm_runtime_resume_and_get(hdmi_pai->dev) < 0)
+ return;
+
/* PAI set control extended */
val = WTMK_HIGH(3) | WTMK_LOW(3);
val |= NUM_CH(channel);
@@ -85,6 +90,8 @@ static void imx8mp_hdmi_pai_disable(struct dw_hdmi *dw_hdmi)
/* Stop PAI */
regmap_write(hdmi_pai->regmap, HTX_PAI_CTRL, 0);
+
+ pm_runtime_put_sync(hdmi_pai->dev);
}
static const struct regmap_config imx8mp_hdmi_pai_regmap_config = {
@@ -101,6 +108,7 @@ static int imx8mp_hdmi_pai_bind(struct device *dev, struct device *master, void
struct imx8mp_hdmi_pai *hdmi_pai;
struct resource *res;
void __iomem *base;
+ int ret;
hdmi_pai = devm_kzalloc(dev, sizeof(*hdmi_pai), GFP_KERNEL);
if (!hdmi_pai)
@@ -121,6 +129,13 @@ static int imx8mp_hdmi_pai_bind(struct device *dev, struct device *master, void
plat_data->disable_audio = imx8mp_hdmi_pai_disable;
plat_data->priv_audio = hdmi_pai;
+ hdmi_pai->dev = dev;
+ ret = devm_pm_runtime_enable(dev);
+ if (ret < 0) {
+ dev_err(dev, "failed to enable PM runtime: %d\n", ret);
+ return ret;
+ }
+
return 0;
}
diff --git a/drivers/gpu/drm/gma500/psb_irq.c b/drivers/gpu/drm/gma500/psb_irq.c
index 3a946b472064..c224c7ff353c 100644
--- a/drivers/gpu/drm/gma500/psb_irq.c
+++ b/drivers/gpu/drm/gma500/psb_irq.c
@@ -250,7 +250,6 @@ static irqreturn_t gma_irq_handler(int irq, void *arg)
void gma_irq_preinstall(struct drm_device *dev)
{
struct drm_psb_private *dev_priv = to_drm_psb_private(dev);
- struct drm_crtc *crtc;
unsigned long irqflags;
spin_lock_irqsave(&dev_priv->irqmask_lock, irqflags);
@@ -261,15 +260,10 @@ void gma_irq_preinstall(struct drm_device *dev)
PSB_WSGX32(0x00000000, PSB_CR_EVENT_HOST_ENABLE);
PSB_RSGX32(PSB_CR_EVENT_HOST_ENABLE);
- drm_for_each_crtc(crtc, dev) {
- struct drm_vblank_crtc *vblank = drm_crtc_vblank_crtc(crtc);
-
- if (vblank->enabled) {
- u32 mask = drm_crtc_index(crtc) ? _PSB_VSYNC_PIPEB_FLAG :
- _PSB_VSYNC_PIPEA_FLAG;
- dev_priv->vdc_irq_mask |= mask;
- }
- }
+ if (dev->vblank[0].enabled)
+ dev_priv->vdc_irq_mask |= _PSB_VSYNC_PIPEA_FLAG;
+ if (dev->vblank[1].enabled)
+ dev_priv->vdc_irq_mask |= _PSB_VSYNC_PIPEB_FLAG;
/* Revisit this area - want per device masks ? */
if (dev_priv->ops->hotplug)
@@ -284,8 +278,8 @@ void gma_irq_preinstall(struct drm_device *dev)
void gma_irq_postinstall(struct drm_device *dev)
{
struct drm_psb_private *dev_priv = to_drm_psb_private(dev);
- struct drm_crtc *crtc;
unsigned long irqflags;
+ unsigned int i;
spin_lock_irqsave(&dev_priv->irqmask_lock, irqflags);
@@ -298,13 +292,11 @@ void gma_irq_postinstall(struct drm_device *dev)
PSB_WVDC32(dev_priv->vdc_irq_mask, PSB_INT_ENABLE_R);
PSB_WVDC32(0xFFFFFFFF, PSB_HWSTAM);
- drm_for_each_crtc(crtc, dev) {
- struct drm_vblank_crtc *vblank = drm_crtc_vblank_crtc(crtc);
-
- if (vblank->enabled)
- gma_enable_pipestat(dev_priv, drm_crtc_index(crtc), PIPE_VBLANK_INTERRUPT_ENABLE);
+ for (i = 0; i < dev->num_crtcs; ++i) {
+ if (dev->vblank[i].enabled)
+ gma_enable_pipestat(dev_priv, i, PIPE_VBLANK_INTERRUPT_ENABLE);
else
- gma_disable_pipestat(dev_priv, drm_crtc_index(crtc), PIPE_VBLANK_INTERRUPT_ENABLE);
+ gma_disable_pipestat(dev_priv, i, PIPE_VBLANK_INTERRUPT_ENABLE);
}
if (dev_priv->ops->hotplug_enable)
@@ -345,8 +337,8 @@ void gma_irq_uninstall(struct drm_device *dev)
{
struct drm_psb_private *dev_priv = to_drm_psb_private(dev);
struct pci_dev *pdev = to_pci_dev(dev->dev);
- struct drm_crtc *crtc;
unsigned long irqflags;
+ unsigned int i;
if (!dev_priv->irq_enabled)
return;
@@ -358,11 +350,9 @@ void gma_irq_uninstall(struct drm_device *dev)
PSB_WVDC32(0xFFFFFFFF, PSB_HWSTAM);
- drm_for_each_crtc(crtc, dev) {
- struct drm_vblank_crtc *vblank = drm_crtc_vblank_crtc(crtc);
-
- if (vblank->enabled)
- gma_disable_pipestat(dev_priv, drm_crtc_index(crtc), PIPE_VBLANK_INTERRUPT_ENABLE);
+ for (i = 0; i < dev->num_crtcs; ++i) {
+ if (dev->vblank[i].enabled)
+ gma_disable_pipestat(dev_priv, i, PIPE_VBLANK_INTERRUPT_ENABLE);
}
dev_priv->vdc_irq_mask &= _PSB_IRQ_SGX_FLAG |
diff --git a/drivers/gpu/drm/mgag200/mgag200_bmc.c b/drivers/gpu/drm/mgag200/mgag200_bmc.c
index a689c71ff165..bbdeb791c5b3 100644
--- a/drivers/gpu/drm/mgag200/mgag200_bmc.c
+++ b/drivers/gpu/drm/mgag200/mgag200_bmc.c
@@ -1,6 +1,7 @@
// SPDX-License-Identifier: GPL-2.0-only
#include <linux/delay.h>
+#include <linux/iopoll.h>
#include <drm/drm_atomic_helper.h>
#include <drm/drm_edid.h>
@@ -12,7 +13,7 @@
void mgag200_bmc_stop_scanout(struct mga_device *mdev)
{
u8 tmp;
- int iter_max;
+ int ret;
/*
* 1 - The first step is to inform the BMC of an upcoming mode
@@ -42,30 +43,22 @@ void mgag200_bmc_stop_scanout(struct mga_device *mdev)
/*
* 3a- The third step is to verify if there is an active scan.
- * We are waiting for a 0 on remhsyncsts <XSPAREREG<0>).
+ * We are waiting for a 0 on remhsyncsts (<XSPAREREG<0>).
*/
- iter_max = 300;
- while (!(tmp & 0x1) && iter_max) {
- WREG8(DAC_INDEX, MGA1064_SPAREREG);
- tmp = RREG8(DAC_DATA);
- udelay(1000);
- iter_max--;
- }
+ ret = read_poll_timeout(RREG_DAC, tmp, !(tmp & 0x1),
+ 1000, 300000, false,
+ MGA1064_SPAREREG);
+ if (ret == -ETIMEDOUT)
+ return;
/*
- * 3b- This step occurs only if the remove is actually
+ * 3b- This step occurs only if the remote BMC is actually
* scanning. We are waiting for the end of the frame which is
* a 1 on remvsyncsts (XSPAREREG<1>)
*/
- if (iter_max) {
- iter_max = 300;
- while ((tmp & 0x2) && iter_max) {
- WREG8(DAC_INDEX, MGA1064_SPAREREG);
- tmp = RREG8(DAC_DATA);
- udelay(1000);
- iter_max--;
- }
- }
+ (void)read_poll_timeout(RREG_DAC, tmp, (tmp & 0x2),
+ 1000, 300000, false,
+ MGA1064_SPAREREG);
}
void mgag200_bmc_start_scanout(struct mga_device *mdev)
diff --git a/drivers/gpu/drm/mgag200/mgag200_drv.h b/drivers/gpu/drm/mgag200/mgag200_drv.h
index f4bf40cd7c88..a875c4bf8cbe 100644
--- a/drivers/gpu/drm/mgag200/mgag200_drv.h
+++ b/drivers/gpu/drm/mgag200/mgag200_drv.h
@@ -111,6 +111,12 @@
#define DAC_INDEX 0x3c00
#define DAC_DATA 0x3c0a
+#define RREG_DAC(reg) \
+ ({ \
+ WREG8(DAC_INDEX, reg); \
+ RREG8(DAC_DATA); \
+ }) \
+
#define WREG_DAC(reg, v) \
do { \
WREG8(DAC_INDEX, reg); \
diff --git a/drivers/gpu/drm/nouveau/include/nvif/client.h b/drivers/gpu/drm/nouveau/include/nvif/client.h
index 03f1d564eb12..b698c74306f8 100644
--- a/drivers/gpu/drm/nouveau/include/nvif/client.h
+++ b/drivers/gpu/drm/nouveau/include/nvif/client.h
@@ -11,7 +11,7 @@ struct nvif_client {
int nvif_client_ctor(struct nvif_client *parent, const char *name, struct nvif_client *);
void nvif_client_dtor(struct nvif_client *);
-int nvif_client_suspend(struct nvif_client *);
+int nvif_client_suspend(struct nvif_client *, bool);
int nvif_client_resume(struct nvif_client *);
/*XXX*/
diff --git a/drivers/gpu/drm/nouveau/include/nvif/driver.h b/drivers/gpu/drm/nouveau/include/nvif/driver.h
index 7b08ff769039..61c8a177b28f 100644
--- a/drivers/gpu/drm/nouveau/include/nvif/driver.h
+++ b/drivers/gpu/drm/nouveau/include/nvif/driver.h
@@ -8,7 +8,7 @@ struct nvif_driver {
const char *name;
int (*init)(const char *name, u64 device, const char *cfg,
const char *dbg, void **priv);
- int (*suspend)(void *priv);
+ int (*suspend)(void *priv, bool runtime);
int (*resume)(void *priv);
int (*ioctl)(void *priv, void *data, u32 size, void **hack);
void __iomem *(*map)(void *priv, u64 handle, u32 size);
diff --git a/drivers/gpu/drm/nouveau/include/nvkm/core/device.h b/drivers/gpu/drm/nouveau/include/nvkm/core/device.h
index 99579e7b9376..954a89d43bad 100644
--- a/drivers/gpu/drm/nouveau/include/nvkm/core/device.h
+++ b/drivers/gpu/drm/nouveau/include/nvkm/core/device.h
@@ -2,6 +2,7 @@
#ifndef __NVKM_DEVICE_H__
#define __NVKM_DEVICE_H__
#include <core/oclass.h>
+#include <core/suspend_state.h>
#include <core/intr.h>
enum nvkm_subdev_type;
@@ -93,7 +94,7 @@ struct nvkm_device_func {
void *(*dtor)(struct nvkm_device *);
int (*preinit)(struct nvkm_device *);
int (*init)(struct nvkm_device *);
- void (*fini)(struct nvkm_device *, bool suspend);
+ void (*fini)(struct nvkm_device *, enum nvkm_suspend_state suspend);
int (*irq)(struct nvkm_device *);
resource_size_t (*resource_addr)(struct nvkm_device *, enum nvkm_bar_id);
resource_size_t (*resource_size)(struct nvkm_device *, enum nvkm_bar_id);
diff --git a/drivers/gpu/drm/nouveau/include/nvkm/core/engine.h b/drivers/gpu/drm/nouveau/include/nvkm/core/engine.h
index 738899fcf30b..1e97be6c6564 100644
--- a/drivers/gpu/drm/nouveau/include/nvkm/core/engine.h
+++ b/drivers/gpu/drm/nouveau/include/nvkm/core/engine.h
@@ -20,7 +20,7 @@ struct nvkm_engine_func {
int (*oneinit)(struct nvkm_engine *);
int (*info)(struct nvkm_engine *, u64 mthd, u64 *data);
int (*init)(struct nvkm_engine *);
- int (*fini)(struct nvkm_engine *, bool suspend);
+ int (*fini)(struct nvkm_engine *, enum nvkm_suspend_state suspend);
int (*reset)(struct nvkm_engine *);
int (*nonstall)(struct nvkm_engine *);
void (*intr)(struct nvkm_engine *);
diff --git a/drivers/gpu/drm/nouveau/include/nvkm/core/object.h b/drivers/gpu/drm/nouveau/include/nvkm/core/object.h
index 10107ef3ca49..54d356154274 100644
--- a/drivers/gpu/drm/nouveau/include/nvkm/core/object.h
+++ b/drivers/gpu/drm/nouveau/include/nvkm/core/object.h
@@ -2,6 +2,7 @@
#ifndef __NVKM_OBJECT_H__
#define __NVKM_OBJECT_H__
#include <core/oclass.h>
+#include <core/suspend_state.h>
struct nvkm_event;
struct nvkm_gpuobj;
struct nvkm_uevent;
@@ -27,7 +28,7 @@ enum nvkm_object_map {
struct nvkm_object_func {
void *(*dtor)(struct nvkm_object *);
int (*init)(struct nvkm_object *);
- int (*fini)(struct nvkm_object *, bool suspend);
+ int (*fini)(struct nvkm_object *, enum nvkm_suspend_state suspend);
int (*mthd)(struct nvkm_object *, u32 mthd, void *data, u32 size);
int (*ntfy)(struct nvkm_object *, u32 mthd, struct nvkm_event **);
int (*map)(struct nvkm_object *, void *argv, u32 argc,
@@ -49,7 +50,7 @@ int nvkm_object_new(const struct nvkm_oclass *, void *data, u32 size,
void nvkm_object_del(struct nvkm_object **);
void *nvkm_object_dtor(struct nvkm_object *);
int nvkm_object_init(struct nvkm_object *);
-int nvkm_object_fini(struct nvkm_object *, bool suspend);
+int nvkm_object_fini(struct nvkm_object *, enum nvkm_suspend_state);
int nvkm_object_mthd(struct nvkm_object *, u32 mthd, void *data, u32 size);
int nvkm_object_ntfy(struct nvkm_object *, u32 mthd, struct nvkm_event **);
int nvkm_object_map(struct nvkm_object *, void *argv, u32 argc,
diff --git a/drivers/gpu/drm/nouveau/include/nvkm/core/oproxy.h b/drivers/gpu/drm/nouveau/include/nvkm/core/oproxy.h
index 0e70a9afba33..cf66aee4d111 100644
--- a/drivers/gpu/drm/nouveau/include/nvkm/core/oproxy.h
+++ b/drivers/gpu/drm/nouveau/include/nvkm/core/oproxy.h
@@ -13,7 +13,7 @@ struct nvkm_oproxy {
struct nvkm_oproxy_func {
void (*dtor[2])(struct nvkm_oproxy *);
int (*init[2])(struct nvkm_oproxy *);
- int (*fini[2])(struct nvkm_oproxy *, bool suspend);
+ int (*fini[2])(struct nvkm_oproxy *, enum nvkm_suspend_state suspend);
};
void nvkm_oproxy_ctor(const struct nvkm_oproxy_func *,
diff --git a/drivers/gpu/drm/nouveau/include/nvkm/core/subdev.h b/drivers/gpu/drm/nouveau/include/nvkm/core/subdev.h
index bce6e1ba09ea..bd6b1b658e40 100644
--- a/drivers/gpu/drm/nouveau/include/nvkm/core/subdev.h
+++ b/drivers/gpu/drm/nouveau/include/nvkm/core/subdev.h
@@ -40,7 +40,7 @@ struct nvkm_subdev_func {
int (*oneinit)(struct nvkm_subdev *);
int (*info)(struct nvkm_subdev *, u64 mthd, u64 *data);
int (*init)(struct nvkm_subdev *);
- int (*fini)(struct nvkm_subdev *, bool suspend);
+ int (*fini)(struct nvkm_subdev *, enum nvkm_suspend_state suspend);
void (*intr)(struct nvkm_subdev *);
};
@@ -65,7 +65,7 @@ void nvkm_subdev_unref(struct nvkm_subdev *);
int nvkm_subdev_preinit(struct nvkm_subdev *);
int nvkm_subdev_oneinit(struct nvkm_subdev *);
int nvkm_subdev_init(struct nvkm_subdev *);
-int nvkm_subdev_fini(struct nvkm_subdev *, bool suspend);
+int nvkm_subdev_fini(struct nvkm_subdev *, enum nvkm_suspend_state suspend);
int nvkm_subdev_info(struct nvkm_subdev *, u64, u64 *);
void nvkm_subdev_intr(struct nvkm_subdev *);
diff --git a/drivers/gpu/drm/nouveau/include/nvkm/core/suspend_state.h b/drivers/gpu/drm/nouveau/include/nvkm/core/suspend_state.h
new file mode 100644
index 000000000000..134120fb71f4
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/include/nvkm/core/suspend_state.h
@@ -0,0 +1,11 @@
+/* SPDX-License-Identifier: MIT */
+#ifndef __NVKM_SUSPEND_STATE_H__
+#define __NVKM_SUSPEND_STATE_H__
+
+enum nvkm_suspend_state {
+ NVKM_POWEROFF,
+ NVKM_SUSPEND,
+ NVKM_RUNTIME_SUSPEND,
+};
+
+#endif
diff --git a/drivers/gpu/drm/nouveau/include/nvkm/subdev/gsp.h b/drivers/gpu/drm/nouveau/include/nvkm/subdev/gsp.h
index b8b97e10ae83..64fed208e4cf 100644
--- a/drivers/gpu/drm/nouveau/include/nvkm/subdev/gsp.h
+++ b/drivers/gpu/drm/nouveau/include/nvkm/subdev/gsp.h
@@ -44,6 +44,9 @@ typedef void (*nvkm_gsp_event_func)(struct nvkm_gsp_event *, void *repv, u32 rep
* NVKM_GSP_RPC_REPLY_NOWAIT - If specified, immediately return to the
* caller after the GSP RPC command is issued.
*
+ * NVKM_GSP_RPC_REPLY_NOSEQ - If specified, exactly like NOWAIT
+ * but don't emit RPC sequence number.
+ *
* NVKM_GSP_RPC_REPLY_RECV - If specified, wait and receive the entire GSP
* RPC message after the GSP RPC command is issued.
*
@@ -53,6 +56,7 @@ typedef void (*nvkm_gsp_event_func)(struct nvkm_gsp_event *, void *repv, u32 rep
*/
enum nvkm_gsp_rpc_reply_policy {
NVKM_GSP_RPC_REPLY_NOWAIT = 0,
+ NVKM_GSP_RPC_REPLY_NOSEQ,
NVKM_GSP_RPC_REPLY_RECV,
NVKM_GSP_RPC_REPLY_POLL,
};
@@ -242,6 +246,8 @@ struct nvkm_gsp {
/* The size of the registry RPC */
size_t registry_rpc_size;
+ u32 rpc_seq;
+
#ifdef CONFIG_DEBUG_FS
/*
* Logging buffers in debugfs. The wrapper objects need to remain
diff --git a/drivers/gpu/drm/nouveau/nouveau_display.c b/drivers/gpu/drm/nouveau/nouveau_display.c
index 829c2b573971..00515623a2cc 100644
--- a/drivers/gpu/drm/nouveau/nouveau_display.c
+++ b/drivers/gpu/drm/nouveau/nouveau_display.c
@@ -352,8 +352,6 @@ nouveau_user_framebuffer_create(struct drm_device *dev,
static const struct drm_mode_config_funcs nouveau_mode_config_funcs = {
.fb_create = nouveau_user_framebuffer_create,
- .atomic_commit = drm_atomic_helper_commit,
- .atomic_check = drm_atomic_helper_check,
};
diff --git a/drivers/gpu/drm/nouveau/nouveau_drm.c b/drivers/gpu/drm/nouveau/nouveau_drm.c
index 1527b801f013..dc469e571c0a 100644
--- a/drivers/gpu/drm/nouveau/nouveau_drm.c
+++ b/drivers/gpu/drm/nouveau/nouveau_drm.c
@@ -983,7 +983,7 @@ nouveau_do_suspend(struct nouveau_drm *drm, bool runtime)
}
NV_DEBUG(drm, "suspending object tree...\n");
- ret = nvif_client_suspend(&drm->_client);
+ ret = nvif_client_suspend(&drm->_client, runtime);
if (ret)
goto fail_client;
diff --git a/drivers/gpu/drm/nouveau/nouveau_nvif.c b/drivers/gpu/drm/nouveau/nouveau_nvif.c
index adb802421fda..eeb4ebbc16bf 100644
--- a/drivers/gpu/drm/nouveau/nouveau_nvif.c
+++ b/drivers/gpu/drm/nouveau/nouveau_nvif.c
@@ -62,10 +62,16 @@ nvkm_client_resume(void *priv)
}
static int
-nvkm_client_suspend(void *priv)
+nvkm_client_suspend(void *priv, bool runtime)
{
struct nvkm_client *client = priv;
- return nvkm_object_fini(&client->object, true);
+ enum nvkm_suspend_state state;
+
+ if (runtime)
+ state = NVKM_RUNTIME_SUSPEND;
+ else
+ state = NVKM_SUSPEND;
+ return nvkm_object_fini(&client->object, state);
}
static int
diff --git a/drivers/gpu/drm/nouveau/nvif/client.c b/drivers/gpu/drm/nouveau/nvif/client.c
index fdf5054ed7d8..36d3c99786bd 100644
--- a/drivers/gpu/drm/nouveau/nvif/client.c
+++ b/drivers/gpu/drm/nouveau/nvif/client.c
@@ -30,9 +30,9 @@
#include <nvif/if0000.h>
int
-nvif_client_suspend(struct nvif_client *client)
+nvif_client_suspend(struct nvif_client *client, bool runtime)
{
- return client->driver->suspend(client->object.priv);
+ return client->driver->suspend(client->object.priv, runtime);
}
int
diff --git a/drivers/gpu/drm/nouveau/nvkm/core/engine.c b/drivers/gpu/drm/nouveau/nvkm/core/engine.c
index 36a31e9eea22..5bf62940d7be 100644
--- a/drivers/gpu/drm/nouveau/nvkm/core/engine.c
+++ b/drivers/gpu/drm/nouveau/nvkm/core/engine.c
@@ -41,7 +41,7 @@ nvkm_engine_reset(struct nvkm_engine *engine)
if (engine->func->reset)
return engine->func->reset(engine);
- nvkm_subdev_fini(&engine->subdev, false);
+ nvkm_subdev_fini(&engine->subdev, NVKM_POWEROFF);
return nvkm_subdev_init(&engine->subdev);
}
@@ -98,7 +98,7 @@ nvkm_engine_info(struct nvkm_subdev *subdev, u64 mthd, u64 *data)
}
static int
-nvkm_engine_fini(struct nvkm_subdev *subdev, bool suspend)
+nvkm_engine_fini(struct nvkm_subdev *subdev, enum nvkm_suspend_state suspend)
{
struct nvkm_engine *engine = nvkm_engine(subdev);
if (engine->func->fini)
diff --git a/drivers/gpu/drm/nouveau/nvkm/core/ioctl.c b/drivers/gpu/drm/nouveau/nvkm/core/ioctl.c
index 45051a1249da..b8fc9be67851 100644
--- a/drivers/gpu/drm/nouveau/nvkm/core/ioctl.c
+++ b/drivers/gpu/drm/nouveau/nvkm/core/ioctl.c
@@ -141,7 +141,7 @@ nvkm_ioctl_new(struct nvkm_client *client,
}
ret = -EEXIST;
}
- nvkm_object_fini(object, false);
+ nvkm_object_fini(object, NVKM_POWEROFF);
}
nvkm_object_del(&object);
@@ -160,7 +160,7 @@ nvkm_ioctl_del(struct nvkm_client *client,
nvif_ioctl(object, "delete size %d\n", size);
if (!(ret = nvif_unvers(ret, &data, &size, args->none))) {
nvif_ioctl(object, "delete\n");
- nvkm_object_fini(object, false);
+ nvkm_object_fini(object, NVKM_POWEROFF);
nvkm_object_del(&object);
}
diff --git a/drivers/gpu/drm/nouveau/nvkm/core/object.c b/drivers/gpu/drm/nouveau/nvkm/core/object.c
index 390c265cf8af..af9f00f74c28 100644
--- a/drivers/gpu/drm/nouveau/nvkm/core/object.c
+++ b/drivers/gpu/drm/nouveau/nvkm/core/object.c
@@ -142,13 +142,25 @@ nvkm_object_bind(struct nvkm_object *object, struct nvkm_gpuobj *gpuobj,
}
int
-nvkm_object_fini(struct nvkm_object *object, bool suspend)
+nvkm_object_fini(struct nvkm_object *object, enum nvkm_suspend_state suspend)
{
- const char *action = suspend ? "suspend" : "fini";
+ const char *action;
struct nvkm_object *child;
s64 time;
int ret;
+ switch (suspend) {
+ case NVKM_POWEROFF:
+ default:
+ action = "fini";
+ break;
+ case NVKM_SUSPEND:
+ action = "suspend";
+ break;
+ case NVKM_RUNTIME_SUSPEND:
+ action = "runtime";
+ break;
+ }
nvif_debug(object, "%s children...\n", action);
time = ktime_to_us(ktime_get());
list_for_each_entry_reverse(child, &object->tree, head) {
@@ -212,11 +224,11 @@ nvkm_object_init(struct nvkm_object *object)
fail_child:
list_for_each_entry_continue_reverse(child, &object->tree, head)
- nvkm_object_fini(child, false);
+ nvkm_object_fini(child, NVKM_POWEROFF);
fail:
nvif_error(object, "init failed with %d\n", ret);
if (object->func->fini)
- object->func->fini(object, false);
+ object->func->fini(object, NVKM_POWEROFF);
return ret;
}
diff --git a/drivers/gpu/drm/nouveau/nvkm/core/oproxy.c b/drivers/gpu/drm/nouveau/nvkm/core/oproxy.c
index 5db80d1780f0..7c9edf752768 100644
--- a/drivers/gpu/drm/nouveau/nvkm/core/oproxy.c
+++ b/drivers/gpu/drm/nouveau/nvkm/core/oproxy.c
@@ -87,7 +87,7 @@ nvkm_oproxy_uevent(struct nvkm_object *object, void *argv, u32 argc,
}
static int
-nvkm_oproxy_fini(struct nvkm_object *object, bool suspend)
+nvkm_oproxy_fini(struct nvkm_object *object, enum nvkm_suspend_state suspend)
{
struct nvkm_oproxy *oproxy = nvkm_oproxy(object);
int ret;
diff --git a/drivers/gpu/drm/nouveau/nvkm/core/subdev.c b/drivers/gpu/drm/nouveau/nvkm/core/subdev.c
index 6c20e827a069..b7045d1c8415 100644
--- a/drivers/gpu/drm/nouveau/nvkm/core/subdev.c
+++ b/drivers/gpu/drm/nouveau/nvkm/core/subdev.c
@@ -51,12 +51,24 @@ nvkm_subdev_info(struct nvkm_subdev *subdev, u64 mthd, u64 *data)
}
int
-nvkm_subdev_fini(struct nvkm_subdev *subdev, bool suspend)
+nvkm_subdev_fini(struct nvkm_subdev *subdev, enum nvkm_suspend_state suspend)
{
struct nvkm_device *device = subdev->device;
- const char *action = suspend ? "suspend" : subdev->use.enabled ? "fini" : "reset";
+ const char *action;
s64 time;
+ switch (suspend) {
+ case NVKM_POWEROFF:
+ default:
+ action = subdev->use.enabled ? "fini" : "reset";
+ break;
+ case NVKM_SUSPEND:
+ action = "suspend";
+ break;
+ case NVKM_RUNTIME_SUSPEND:
+ action = "runtime";
+ break;
+ }
nvkm_trace(subdev, "%s running...\n", action);
time = ktime_to_us(ktime_get());
@@ -186,7 +198,7 @@ void
nvkm_subdev_unref(struct nvkm_subdev *subdev)
{
if (refcount_dec_and_mutex_lock(&subdev->use.refcount, &subdev->use.mutex)) {
- nvkm_subdev_fini(subdev, false);
+ nvkm_subdev_fini(subdev, NVKM_POWEROFF);
mutex_unlock(&subdev->use.mutex);
}
}
diff --git a/drivers/gpu/drm/nouveau/nvkm/core/uevent.c b/drivers/gpu/drm/nouveau/nvkm/core/uevent.c
index cc254c390a57..46beb6e470ee 100644
--- a/drivers/gpu/drm/nouveau/nvkm/core/uevent.c
+++ b/drivers/gpu/drm/nouveau/nvkm/core/uevent.c
@@ -73,7 +73,7 @@ nvkm_uevent_mthd(struct nvkm_object *object, u32 mthd, void *argv, u32 argc)
}
static int
-nvkm_uevent_fini(struct nvkm_object *object, bool suspend)
+nvkm_uevent_fini(struct nvkm_object *object, enum nvkm_suspend_state suspend)
{
struct nvkm_uevent *uevent = nvkm_uevent(object);
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/ce/ga100.c b/drivers/gpu/drm/nouveau/nvkm/engine/ce/ga100.c
index 1c0c60138706..1a3caf697608 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/ce/ga100.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/ce/ga100.c
@@ -46,7 +46,7 @@ ga100_ce_nonstall(struct nvkm_engine *engine)
}
int
-ga100_ce_fini(struct nvkm_engine *engine, bool suspend)
+ga100_ce_fini(struct nvkm_engine *engine, enum nvkm_suspend_state suspend)
{
nvkm_inth_block(&engine->subdev.inth);
return 0;
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/ce/priv.h b/drivers/gpu/drm/nouveau/nvkm/engine/ce/priv.h
index 34fd2657134b..f07b45853310 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/ce/priv.h
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/ce/priv.h
@@ -14,7 +14,7 @@ extern const struct nvkm_object_func gv100_ce_cclass;
int ga100_ce_oneinit(struct nvkm_engine *);
int ga100_ce_init(struct nvkm_engine *);
-int ga100_ce_fini(struct nvkm_engine *, bool);
+int ga100_ce_fini(struct nvkm_engine *, enum nvkm_suspend_state);
int ga100_ce_nonstall(struct nvkm_engine *);
u32 gb202_ce_grce_mask(struct nvkm_device *);
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c b/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c
index 2517b65d8faa..b101e14f841e 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c
@@ -2936,13 +2936,25 @@ nvkm_device_engine(struct nvkm_device *device, int type, int inst)
}
int
-nvkm_device_fini(struct nvkm_device *device, bool suspend)
+nvkm_device_fini(struct nvkm_device *device, enum nvkm_suspend_state suspend)
{
- const char *action = suspend ? "suspend" : "fini";
+ const char *action;
struct nvkm_subdev *subdev;
int ret;
s64 time;
+ switch (suspend) {
+ case NVKM_POWEROFF:
+ default:
+ action = "fini";
+ break;
+ case NVKM_SUSPEND:
+ action = "suspend";
+ break;
+ case NVKM_RUNTIME_SUSPEND:
+ action = "runtime";
+ break;
+ }
nvdev_trace(device, "%s running...\n", action);
time = ktime_to_us(ktime_get());
@@ -3032,7 +3044,7 @@ nvkm_device_init(struct nvkm_device *device)
if (ret)
return ret;
- nvkm_device_fini(device, false);
+ nvkm_device_fini(device, NVKM_POWEROFF);
nvdev_trace(device, "init running...\n");
time = ktime_to_us(ktime_get());
@@ -3060,9 +3072,9 @@ nvkm_device_init(struct nvkm_device *device)
fail_subdev:
list_for_each_entry_from(subdev, &device->subdev, head)
- nvkm_subdev_fini(subdev, false);
+ nvkm_subdev_fini(subdev, NVKM_POWEROFF);
fail:
- nvkm_device_fini(device, false);
+ nvkm_device_fini(device, NVKM_POWEROFF);
nvdev_error(device, "init failed with %d\n", ret);
return ret;
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/device/pci.c b/drivers/gpu/drm/nouveau/nvkm/engine/device/pci.c
index 8f0261a0d618..4c29b60460d4 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/device/pci.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/device/pci.c
@@ -1605,10 +1605,10 @@ nvkm_device_pci_irq(struct nvkm_device *device)
}
static void
-nvkm_device_pci_fini(struct nvkm_device *device, bool suspend)
+nvkm_device_pci_fini(struct nvkm_device *device, enum nvkm_suspend_state suspend)
{
struct nvkm_device_pci *pdev = nvkm_device_pci(device);
- if (suspend) {
+ if (suspend != NVKM_POWEROFF) {
pci_disable_device(pdev->pdev);
pdev->suspend = true;
}
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/device/priv.h b/drivers/gpu/drm/nouveau/nvkm/engine/device/priv.h
index 75ee7506d443..d0c40f034244 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/device/priv.h
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/device/priv.h
@@ -56,5 +56,5 @@ int nvkm_device_ctor(const struct nvkm_device_func *,
const char *name, const char *cfg, const char *dbg,
struct nvkm_device *);
int nvkm_device_init(struct nvkm_device *);
-int nvkm_device_fini(struct nvkm_device *, bool suspend);
+int nvkm_device_fini(struct nvkm_device *, enum nvkm_suspend_state suspend);
#endif
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/device/user.c b/drivers/gpu/drm/nouveau/nvkm/engine/device/user.c
index 58191b7a0494..32ff3181f47b 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/device/user.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/device/user.c
@@ -218,7 +218,7 @@ nvkm_udevice_map(struct nvkm_object *object, void *argv, u32 argc,
}
static int
-nvkm_udevice_fini(struct nvkm_object *object, bool suspend)
+nvkm_udevice_fini(struct nvkm_object *object, enum nvkm_suspend_state suspend)
{
struct nvkm_udevice *udev = nvkm_udevice(object);
struct nvkm_device *device = udev->device;
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/base.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/base.c
index b24eb1e560bc..84745f60912e 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/base.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/base.c
@@ -99,13 +99,13 @@ nvkm_disp_intr(struct nvkm_engine *engine)
}
static int
-nvkm_disp_fini(struct nvkm_engine *engine, bool suspend)
+nvkm_disp_fini(struct nvkm_engine *engine, enum nvkm_suspend_state suspend)
{
struct nvkm_disp *disp = nvkm_disp(engine);
struct nvkm_outp *outp;
if (disp->func->fini)
- disp->func->fini(disp, suspend);
+ disp->func->fini(disp, suspend != NVKM_POWEROFF);
list_for_each_entry(outp, &disp->outps, head) {
if (outp->func->fini)
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/chan.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/chan.c
index 9b84e357d354..57a62a2de7c7 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/chan.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/chan.c
@@ -128,7 +128,7 @@ nvkm_disp_chan_child_get(struct nvkm_object *object, int index, struct nvkm_ocla
}
static int
-nvkm_disp_chan_fini(struct nvkm_object *object, bool suspend)
+nvkm_disp_chan_fini(struct nvkm_object *object, enum nvkm_suspend_state suspend)
{
struct nvkm_disp_chan *chan = nvkm_disp_chan(object);
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/falcon.c b/drivers/gpu/drm/nouveau/nvkm/engine/falcon.c
index fd5ee9f0af36..cf8e356867b4 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/falcon.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/falcon.c
@@ -93,13 +93,13 @@ nvkm_falcon_intr(struct nvkm_engine *engine)
}
static int
-nvkm_falcon_fini(struct nvkm_engine *engine, bool suspend)
+nvkm_falcon_fini(struct nvkm_engine *engine, enum nvkm_suspend_state suspend)
{
struct nvkm_falcon *falcon = nvkm_falcon(engine);
struct nvkm_device *device = falcon->engine.subdev.device;
const u32 base = falcon->addr;
- if (!suspend) {
+ if (suspend == NVKM_POWEROFF) {
nvkm_memory_unref(&falcon->core);
if (falcon->external) {
vfree(falcon->data.data);
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/base.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/base.c
index 6fd4e60634fb..1561287a32f2 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/base.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/base.c
@@ -122,7 +122,7 @@ nvkm_fifo_class_get(struct nvkm_oclass *oclass, int index, const struct nvkm_dev
}
static int
-nvkm_fifo_fini(struct nvkm_engine *engine, bool suspend)
+nvkm_fifo_fini(struct nvkm_engine *engine, enum nvkm_suspend_state suspend)
{
struct nvkm_fifo *fifo = nvkm_fifo(engine);
struct nvkm_runl *runl;
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/uchan.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/uchan.c
index 52420a1edca5..c978b97e10c6 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/uchan.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/uchan.c
@@ -72,7 +72,7 @@ struct nvkm_uobj {
};
static int
-nvkm_uchan_object_fini_1(struct nvkm_oproxy *oproxy, bool suspend)
+nvkm_uchan_object_fini_1(struct nvkm_oproxy *oproxy, enum nvkm_suspend_state suspend)
{
struct nvkm_uobj *uobj = container_of(oproxy, typeof(*uobj), oproxy);
struct nvkm_chan *chan = uobj->chan;
@@ -87,7 +87,7 @@ nvkm_uchan_object_fini_1(struct nvkm_oproxy *oproxy, bool suspend)
nvkm_chan_cctx_bind(chan, ectx->engn, NULL);
if (refcount_dec_and_test(&ectx->uses))
- nvkm_object_fini(ectx->object, false);
+ nvkm_object_fini(ectx->object, NVKM_POWEROFF);
mutex_unlock(&chan->cgrp->mutex);
}
@@ -269,7 +269,7 @@ nvkm_uchan_map(struct nvkm_object *object, void *argv, u32 argc,
}
static int
-nvkm_uchan_fini(struct nvkm_object *object, bool suspend)
+nvkm_uchan_fini(struct nvkm_object *object, enum nvkm_suspend_state suspend)
{
struct nvkm_chan *chan = nvkm_uchan(object)->chan;
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/base.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/base.c
index f5e68f09df76..cd4908b1b4df 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/base.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/base.c
@@ -168,11 +168,11 @@ nvkm_gr_init(struct nvkm_engine *engine)
}
static int
-nvkm_gr_fini(struct nvkm_engine *engine, bool suspend)
+nvkm_gr_fini(struct nvkm_engine *engine, enum nvkm_suspend_state suspend)
{
struct nvkm_gr *gr = nvkm_gr(engine);
if (gr->func->fini)
- return gr->func->fini(gr, suspend);
+ return gr->func->fini(gr, suspend != NVKM_POWEROFF);
return 0;
}
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c
index 3ea447f6a45b..3608215f0f11 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c
@@ -2330,7 +2330,7 @@ gf100_gr_reset(struct nvkm_gr *base)
WARN_ON(gf100_gr_fecs_halt_pipeline(gr));
- subdev->func->fini(subdev, false);
+ subdev->func->fini(subdev, NVKM_POWEROFF);
nvkm_mc_disable(device, subdev->type, subdev->inst);
if (gr->func->gpccs.reset)
gr->func->gpccs.reset(gr);
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv04.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv04.c
index ca822f07b63e..82937df8b8c0 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv04.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv04.c
@@ -1158,7 +1158,7 @@ nv04_gr_chan_dtor(struct nvkm_object *object)
}
static int
-nv04_gr_chan_fini(struct nvkm_object *object, bool suspend)
+nv04_gr_chan_fini(struct nvkm_object *object, enum nvkm_suspend_state suspend)
{
struct nv04_gr_chan *chan = nv04_gr_chan(object);
struct nv04_gr *gr = chan->gr;
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv10.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv10.c
index 92ef7c9b2910..fcb4e4fce83f 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv10.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv10.c
@@ -951,7 +951,7 @@ nv10_gr_context_switch(struct nv10_gr *gr)
}
static int
-nv10_gr_chan_fini(struct nvkm_object *object, bool suspend)
+nv10_gr_chan_fini(struct nvkm_object *object, enum nvkm_suspend_state suspend)
{
struct nv10_gr_chan *chan = nv10_gr_chan(object);
struct nv10_gr *gr = chan->gr;
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv20.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv20.c
index 13407fafe947..ab57b3b40228 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv20.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv20.c
@@ -27,7 +27,7 @@ nv20_gr_chan_init(struct nvkm_object *object)
}
int
-nv20_gr_chan_fini(struct nvkm_object *object, bool suspend)
+nv20_gr_chan_fini(struct nvkm_object *object, enum nvkm_suspend_state suspend)
{
struct nv20_gr_chan *chan = nv20_gr_chan(object);
struct nv20_gr *gr = chan->gr;
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv20.h b/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv20.h
index c0d2be53413e..786c7832f7ac 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv20.h
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv20.h
@@ -31,5 +31,5 @@ struct nv20_gr_chan {
void *nv20_gr_chan_dtor(struct nvkm_object *);
int nv20_gr_chan_init(struct nvkm_object *);
-int nv20_gr_chan_fini(struct nvkm_object *, bool);
+int nv20_gr_chan_fini(struct nvkm_object *, enum nvkm_suspend_state);
#endif
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv40.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv40.c
index b609b0150ba1..e3e797cf3034 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv40.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv40.c
@@ -89,7 +89,7 @@ nv40_gr_chan_bind(struct nvkm_object *object, struct nvkm_gpuobj *parent,
}
static int
-nv40_gr_chan_fini(struct nvkm_object *object, bool suspend)
+nv40_gr_chan_fini(struct nvkm_object *object, enum nvkm_suspend_state suspend)
{
struct nv40_gr_chan *chan = nv40_gr_chan(object);
struct nv40_gr *gr = chan->gr;
@@ -101,7 +101,7 @@ nv40_gr_chan_fini(struct nvkm_object *object, bool suspend)
nvkm_mask(device, 0x400720, 0x00000001, 0x00000000);
if (nvkm_rd32(device, 0x40032c) == inst) {
- if (suspend) {
+ if (suspend != NVKM_POWEROFF) {
nvkm_wr32(device, 0x400720, 0x00000000);
nvkm_wr32(device, 0x400784, inst);
nvkm_mask(device, 0x400310, 0x00000020, 0x00000020);
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/mpeg/nv44.c b/drivers/gpu/drm/nouveau/nvkm/engine/mpeg/nv44.c
index 4b1374adbda3..38146f9cc81c 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/mpeg/nv44.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/mpeg/nv44.c
@@ -65,7 +65,7 @@ nv44_mpeg_chan_bind(struct nvkm_object *object, struct nvkm_gpuobj *parent,
}
static int
-nv44_mpeg_chan_fini(struct nvkm_object *object, bool suspend)
+nv44_mpeg_chan_fini(struct nvkm_object *object, enum nvkm_suspend_state suspend)
{
struct nv44_mpeg_chan *chan = nv44_mpeg_chan(object);
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/sec2/base.c b/drivers/gpu/drm/nouveau/nvkm/engine/sec2/base.c
index f2c60da5d1e8..3e4d6a680ee9 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/sec2/base.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/sec2/base.c
@@ -37,7 +37,7 @@ nvkm_sec2_finimsg(void *priv, struct nvfw_falcon_msg *hdr)
}
static int
-nvkm_sec2_fini(struct nvkm_engine *engine, bool suspend)
+nvkm_sec2_fini(struct nvkm_engine *engine, enum nvkm_suspend_state suspend)
{
struct nvkm_sec2 *sec2 = nvkm_sec2(engine);
struct nvkm_subdev *subdev = &sec2->engine.subdev;
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/xtensa.c b/drivers/gpu/drm/nouveau/nvkm/engine/xtensa.c
index f7d3ba0afb55..910a5bb2d191 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/xtensa.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/xtensa.c
@@ -76,7 +76,7 @@ nvkm_xtensa_intr(struct nvkm_engine *engine)
}
static int
-nvkm_xtensa_fini(struct nvkm_engine *engine, bool suspend)
+nvkm_xtensa_fini(struct nvkm_engine *engine, enum nvkm_suspend_state suspend)
{
struct nvkm_xtensa *xtensa = nvkm_xtensa(engine);
struct nvkm_device *device = xtensa->engine.subdev.device;
@@ -85,7 +85,7 @@ nvkm_xtensa_fini(struct nvkm_engine *engine, bool suspend)
nvkm_wr32(device, base + 0xd84, 0); /* INTR_EN */
nvkm_wr32(device, base + 0xd94, 0); /* FIFO_CTRL */
- if (!suspend)
+ if (suspend == NVKM_POWEROFF)
nvkm_memory_unref(&xtensa->gpu_fw);
return 0;
}
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/acr/base.c b/drivers/gpu/drm/nouveau/nvkm/subdev/acr/base.c
index 9b8ca4e898f9..13d829593180 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/acr/base.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/acr/base.c
@@ -182,7 +182,7 @@ nvkm_acr_managed_falcon(struct nvkm_device *device, enum nvkm_acr_lsf_id id)
}
static int
-nvkm_acr_fini(struct nvkm_subdev *subdev, bool suspend)
+nvkm_acr_fini(struct nvkm_subdev *subdev, enum nvkm_suspend_state suspend)
{
if (!subdev->use.enabled)
return 0;
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/bar/base.c b/drivers/gpu/drm/nouveau/nvkm/subdev/bar/base.c
index 91bc53be97ff..7dee55bf9ada 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/bar/base.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/bar/base.c
@@ -90,7 +90,7 @@ nvkm_bar_bar2_init(struct nvkm_device *device)
}
static int
-nvkm_bar_fini(struct nvkm_subdev *subdev, bool suspend)
+nvkm_bar_fini(struct nvkm_subdev *subdev, enum nvkm_suspend_state suspend)
{
struct nvkm_bar *bar = nvkm_bar(subdev);
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/clk/base.c b/drivers/gpu/drm/nouveau/nvkm/subdev/clk/base.c
index 178dc56909c2..71420f81714b 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/clk/base.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/clk/base.c
@@ -577,7 +577,7 @@ nvkm_clk_read(struct nvkm_clk *clk, enum nv_clk_src src)
}
static int
-nvkm_clk_fini(struct nvkm_subdev *subdev, bool suspend)
+nvkm_clk_fini(struct nvkm_subdev *subdev, enum nvkm_suspend_state suspend)
{
struct nvkm_clk *clk = nvkm_clk(subdev);
flush_work(&clk->work);
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/devinit/base.c b/drivers/gpu/drm/nouveau/nvkm/subdev/devinit/base.c
index 3d9319c319c6..ad5ec9ee1294 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/devinit/base.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/devinit/base.c
@@ -67,11 +67,11 @@ nvkm_devinit_post(struct nvkm_devinit *init)
}
static int
-nvkm_devinit_fini(struct nvkm_subdev *subdev, bool suspend)
+nvkm_devinit_fini(struct nvkm_subdev *subdev, enum nvkm_suspend_state suspend)
{
struct nvkm_devinit *init = nvkm_devinit(subdev);
/* force full reinit on resume */
- if (suspend)
+ if (suspend != NVKM_POWEROFF)
init->post = true;
return 0;
}
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fault/base.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fault/base.c
index b53ac9a2552f..d8d32bb5bcd9 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/fault/base.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fault/base.c
@@ -51,7 +51,7 @@ nvkm_fault_intr(struct nvkm_subdev *subdev)
}
static int
-nvkm_fault_fini(struct nvkm_subdev *subdev, bool suspend)
+nvkm_fault_fini(struct nvkm_subdev *subdev, enum nvkm_suspend_state suspend)
{
struct nvkm_fault *fault = nvkm_fault(subdev);
if (fault->func->fini)
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fault/user.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fault/user.c
index cd2fbc0472d8..8ab052d18e5d 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/fault/user.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fault/user.c
@@ -56,7 +56,7 @@ nvkm_ufault_map(struct nvkm_object *object, void *argv, u32 argc,
}
static int
-nvkm_ufault_fini(struct nvkm_object *object, bool suspend)
+nvkm_ufault_fini(struct nvkm_object *object, enum nvkm_suspend_state suspend)
{
struct nvkm_fault_buffer *buffer = nvkm_fault_buffer(object);
buffer->fault->func->buffer.fini(buffer);
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/gpio/base.c b/drivers/gpu/drm/nouveau/nvkm/subdev/gpio/base.c
index b196baa376dc..b2c34878a68f 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/gpio/base.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/gpio/base.c
@@ -144,7 +144,7 @@ nvkm_gpio_intr(struct nvkm_subdev *subdev)
}
static int
-nvkm_gpio_fini(struct nvkm_subdev *subdev, bool suspend)
+nvkm_gpio_fini(struct nvkm_subdev *subdev, enum nvkm_suspend_state suspend)
{
struct nvkm_gpio *gpio = nvkm_gpio(subdev);
u32 mask = (1ULL << gpio->func->lines) - 1;
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/base.c b/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/base.c
index 7ccb41761066..30cb843ba35c 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/base.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/base.c
@@ -48,7 +48,7 @@ nvkm_gsp_intr_stall(struct nvkm_gsp *gsp, enum nvkm_subdev_type type, int inst)
}
static int
-nvkm_gsp_fini(struct nvkm_subdev *subdev, bool suspend)
+nvkm_gsp_fini(struct nvkm_subdev *subdev, enum nvkm_suspend_state suspend)
{
struct nvkm_gsp *gsp = nvkm_gsp(subdev);
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/gh100.c b/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/gh100.c
index b0dd5fce7bad..88436a264177 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/gh100.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/gh100.c
@@ -17,7 +17,7 @@
#include <nvhw/ref/gh100/dev_riscv_pri.h>
int
-gh100_gsp_fini(struct nvkm_gsp *gsp, bool suspend)
+gh100_gsp_fini(struct nvkm_gsp *gsp, enum nvkm_suspend_state suspend)
{
struct nvkm_falcon *falcon = &gsp->falcon;
int ret, time = 4000;
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/priv.h b/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/priv.h
index 9dd66a2e3801..71b7203bef50 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/priv.h
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/priv.h
@@ -59,7 +59,7 @@ struct nvkm_gsp_func {
void (*dtor)(struct nvkm_gsp *);
int (*oneinit)(struct nvkm_gsp *);
int (*init)(struct nvkm_gsp *);
- int (*fini)(struct nvkm_gsp *, bool suspend);
+ int (*fini)(struct nvkm_gsp *, enum nvkm_suspend_state suspend);
int (*reset)(struct nvkm_gsp *);
struct {
@@ -75,7 +75,7 @@ int tu102_gsp_fwsec_sb_ctor(struct nvkm_gsp *);
void tu102_gsp_fwsec_sb_dtor(struct nvkm_gsp *);
int tu102_gsp_oneinit(struct nvkm_gsp *);
int tu102_gsp_init(struct nvkm_gsp *);
-int tu102_gsp_fini(struct nvkm_gsp *, bool suspend);
+int tu102_gsp_fini(struct nvkm_gsp *, enum nvkm_suspend_state suspend);
int tu102_gsp_reset(struct nvkm_gsp *);
u64 tu102_gsp_wpr_heap_size(struct nvkm_gsp *);
@@ -87,12 +87,12 @@ int ga102_gsp_reset(struct nvkm_gsp *);
int gh100_gsp_oneinit(struct nvkm_gsp *);
int gh100_gsp_init(struct nvkm_gsp *);
-int gh100_gsp_fini(struct nvkm_gsp *, bool suspend);
+int gh100_gsp_fini(struct nvkm_gsp *, enum nvkm_suspend_state suspend);
void r535_gsp_dtor(struct nvkm_gsp *);
int r535_gsp_oneinit(struct nvkm_gsp *);
int r535_gsp_init(struct nvkm_gsp *);
-int r535_gsp_fini(struct nvkm_gsp *, bool suspend);
+int r535_gsp_fini(struct nvkm_gsp *, enum nvkm_suspend_state suspend);
int nvkm_gsp_new_(const struct nvkm_gsp_fwif *, struct nvkm_device *, enum nvkm_subdev_type, int,
struct nvkm_gsp **);
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/rm/r535/fbsr.c b/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/rm/r535/fbsr.c
index 150e22fde2ac..e962d0e8f837 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/rm/r535/fbsr.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/rm/r535/fbsr.c
@@ -208,7 +208,7 @@ r535_fbsr_resume(struct nvkm_gsp *gsp)
}
static int
-r535_fbsr_suspend(struct nvkm_gsp *gsp)
+r535_fbsr_suspend(struct nvkm_gsp *gsp, bool runtime)
{
struct nvkm_subdev *subdev = &gsp->subdev;
struct nvkm_device *device = subdev->device;
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/rm/r535/gsp.c b/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/rm/r535/gsp.c
index 2a7e80c6d70f..7fb13434c051 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/rm/r535/gsp.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/rm/r535/gsp.c
@@ -704,7 +704,7 @@ r535_gsp_rpc_set_registry(struct nvkm_gsp *gsp)
build_registry(gsp, rpc);
- return nvkm_gsp_rpc_wr(gsp, rpc, NVKM_GSP_RPC_REPLY_NOWAIT);
+ return nvkm_gsp_rpc_wr(gsp, rpc, NVKM_GSP_RPC_REPLY_NOSEQ);
fail:
clean_registry(gsp);
@@ -921,7 +921,7 @@ r535_gsp_set_system_info(struct nvkm_gsp *gsp)
info->pciConfigMirrorSize = device->pci->func->cfg.size;
r535_gsp_acpi_info(gsp, &info->acpiMethodData);
- return nvkm_gsp_rpc_wr(gsp, info, NVKM_GSP_RPC_REPLY_NOWAIT);
+ return nvkm_gsp_rpc_wr(gsp, info, NVKM_GSP_RPC_REPLY_NOSEQ);
}
static int
@@ -1721,7 +1721,7 @@ r535_gsp_sr_data_size(struct nvkm_gsp *gsp)
}
int
-r535_gsp_fini(struct nvkm_gsp *gsp, bool suspend)
+r535_gsp_fini(struct nvkm_gsp *gsp, enum nvkm_suspend_state suspend)
{
struct nvkm_rm *rm = gsp->rm;
int ret;
@@ -1748,7 +1748,7 @@ r535_gsp_fini(struct nvkm_gsp *gsp, bool suspend)
sr->sysmemAddrOfSuspendResumeData = gsp->sr.radix3.lvl0.addr;
sr->sizeOfSuspendResumeData = len;
- ret = rm->api->fbsr->suspend(gsp);
+ ret = rm->api->fbsr->suspend(gsp, suspend == NVKM_RUNTIME_SUSPEND);
if (ret) {
nvkm_gsp_mem_dtor(&gsp->sr.meta);
nvkm_gsp_radix3_dtor(gsp, &gsp->sr.radix3);
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/rm/r535/rpc.c b/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/rm/r535/rpc.c
index 0dc4782df8c0..3ca3de8f4340 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/rm/r535/rpc.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/rm/r535/rpc.c
@@ -557,6 +557,7 @@ r535_gsp_rpc_handle_reply(struct nvkm_gsp *gsp, u32 fn,
switch (policy) {
case NVKM_GSP_RPC_REPLY_NOWAIT:
+ case NVKM_GSP_RPC_REPLY_NOSEQ:
break;
case NVKM_GSP_RPC_REPLY_RECV:
reply = r535_gsp_msg_recv(gsp, fn, gsp_rpc_len);
@@ -588,6 +589,11 @@ r535_gsp_rpc_send(struct nvkm_gsp *gsp, void *payload,
rpc->data, rpc->length - sizeof(*rpc), true);
}
+ if (policy == NVKM_GSP_RPC_REPLY_NOSEQ)
+ rpc->sequence = 0;
+ else
+ rpc->sequence = gsp->rpc_seq++;
+
ret = r535_gsp_cmdq_push(gsp, rpc);
if (ret)
return ERR_PTR(ret);
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/rm/r570/fbsr.c b/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/rm/r570/fbsr.c
index 2945d5b4e570..8ef8b4f65588 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/rm/r570/fbsr.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/rm/r570/fbsr.c
@@ -62,7 +62,7 @@ r570_fbsr_resume(struct nvkm_gsp *gsp)
}
static int
-r570_fbsr_init(struct nvkm_gsp *gsp, struct sg_table *sgt, u64 size)
+r570_fbsr_init(struct nvkm_gsp *gsp, struct sg_table *sgt, u64 size, bool runtime)
{
NV2080_CTRL_INTERNAL_FBSR_INIT_PARAMS *ctrl;
struct nvkm_gsp_object memlist;
@@ -81,7 +81,7 @@ r570_fbsr_init(struct nvkm_gsp *gsp, struct sg_table *sgt, u64 size)
ctrl->hClient = gsp->internal.client.object.handle;
ctrl->hSysMem = memlist.handle;
ctrl->sysmemAddrOfSuspendResumeData = gsp->sr.meta.addr;
- ctrl->bEnteringGcoffState = 1;
+ ctrl->bEnteringGcoffState = runtime ? 1 : 0;
ret = nvkm_gsp_rm_ctrl_wr(&gsp->internal.device.subdevice, ctrl);
if (ret)
@@ -92,7 +92,7 @@ r570_fbsr_init(struct nvkm_gsp *gsp, struct sg_table *sgt, u64 size)
}
static int
-r570_fbsr_suspend(struct nvkm_gsp *gsp)
+r570_fbsr_suspend(struct nvkm_gsp *gsp, bool runtime)
{
struct nvkm_subdev *subdev = &gsp->subdev;
struct nvkm_device *device = subdev->device;
@@ -133,7 +133,7 @@ r570_fbsr_suspend(struct nvkm_gsp *gsp)
return ret;
/* Initialise FBSR on RM. */
- ret = r570_fbsr_init(gsp, &gsp->sr.fbsr, size);
+ ret = r570_fbsr_init(gsp, &gsp->sr.fbsr, size, runtime);
if (ret) {
nvkm_gsp_sg_free(device, &gsp->sr.fbsr);
return ret;
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/rm/r570/gsp.c b/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/rm/r570/gsp.c
index 9d2fa4e66d59..996941c668ba 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/rm/r570/gsp.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/rm/r570/gsp.c
@@ -176,7 +176,7 @@ r570_gsp_set_system_info(struct nvkm_gsp *gsp)
info->bIsPrimary = video_is_primary_device(device->dev);
info->bPreserveVideoMemoryAllocations = false;
- return nvkm_gsp_rpc_wr(gsp, info, NVKM_GSP_RPC_REPLY_NOWAIT);
+ return nvkm_gsp_rpc_wr(gsp, info, NVKM_GSP_RPC_REPLY_NOSEQ);
}
static void
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/rm/rm.h b/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/rm/rm.h
index 393ea775941f..4f0ae6cc085c 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/rm/rm.h
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/rm/rm.h
@@ -78,7 +78,7 @@ struct nvkm_rm_api {
} *device;
const struct nvkm_rm_api_fbsr {
- int (*suspend)(struct nvkm_gsp *);
+ int (*suspend)(struct nvkm_gsp *, bool runtime);
void (*resume)(struct nvkm_gsp *);
} *fbsr;
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/tu102.c b/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/tu102.c
index 04b642a1f730..19cb269e7a26 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/tu102.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/tu102.c
@@ -161,7 +161,7 @@ tu102_gsp_reset(struct nvkm_gsp *gsp)
}
int
-tu102_gsp_fini(struct nvkm_gsp *gsp, bool suspend)
+tu102_gsp_fini(struct nvkm_gsp *gsp, enum nvkm_suspend_state suspend)
{
u32 mbox0 = 0xff, mbox1 = 0xff;
int ret;
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/base.c b/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/base.c
index 7ec17e8435a1..454bb21815a2 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/base.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/base.c
@@ -135,7 +135,7 @@ nvkm_i2c_intr(struct nvkm_subdev *subdev)
}
static int
-nvkm_i2c_fini(struct nvkm_subdev *subdev, bool suspend)
+nvkm_i2c_fini(struct nvkm_subdev *subdev, enum nvkm_suspend_state suspend)
{
struct nvkm_i2c *i2c = nvkm_i2c(subdev);
struct nvkm_i2c_pad *pad;
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/instmem/base.c b/drivers/gpu/drm/nouveau/nvkm/subdev/instmem/base.c
index 2f55bab8e132..6b9ed61684a0 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/instmem/base.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/instmem/base.c
@@ -176,7 +176,7 @@ nvkm_instmem_boot(struct nvkm_instmem *imem)
}
static int
-nvkm_instmem_fini(struct nvkm_subdev *subdev, bool suspend)
+nvkm_instmem_fini(struct nvkm_subdev *subdev, enum nvkm_suspend_state suspend)
{
struct nvkm_instmem *imem = nvkm_instmem(subdev);
int ret;
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/pci/base.c b/drivers/gpu/drm/nouveau/nvkm/subdev/pci/base.c
index 6867934256a7..0f3e0d324a52 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/pci/base.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/pci/base.c
@@ -74,7 +74,7 @@ nvkm_pci_rom_shadow(struct nvkm_pci *pci, bool shadow)
}
static int
-nvkm_pci_fini(struct nvkm_subdev *subdev, bool suspend)
+nvkm_pci_fini(struct nvkm_subdev *subdev, enum nvkm_suspend_state suspend)
{
struct nvkm_pci *pci = nvkm_pci(subdev);
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/base.c b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/base.c
index 8f2f50ad4ded..9e9004ec4588 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/base.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/base.c
@@ -77,7 +77,7 @@ nvkm_pmu_intr(struct nvkm_subdev *subdev)
}
static int
-nvkm_pmu_fini(struct nvkm_subdev *subdev, bool suspend)
+nvkm_pmu_fini(struct nvkm_subdev *subdev, enum nvkm_suspend_state suspend)
{
struct nvkm_pmu *pmu = nvkm_pmu(subdev);
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/therm/base.c b/drivers/gpu/drm/nouveau/nvkm/subdev/therm/base.c
index fc5ee118e910..1510aba33956 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/therm/base.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/therm/base.c
@@ -341,15 +341,15 @@ nvkm_therm_intr(struct nvkm_subdev *subdev)
}
static int
-nvkm_therm_fini(struct nvkm_subdev *subdev, bool suspend)
+nvkm_therm_fini(struct nvkm_subdev *subdev, enum nvkm_suspend_state suspend)
{
struct nvkm_therm *therm = nvkm_therm(subdev);
if (therm->func->fini)
therm->func->fini(therm);
- nvkm_therm_fan_fini(therm, suspend);
- nvkm_therm_sensor_fini(therm, suspend);
+ nvkm_therm_fan_fini(therm, suspend != NVKM_POWEROFF);
+ nvkm_therm_sensor_fini(therm, suspend != NVKM_POWEROFF);
if (suspend) {
therm->suspend = therm->mode;
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/timer/base.c b/drivers/gpu/drm/nouveau/nvkm/subdev/timer/base.c
index 8b0da0c06268..a5c3c282b5d0 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/timer/base.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/timer/base.c
@@ -149,7 +149,7 @@ nvkm_timer_intr(struct nvkm_subdev *subdev)
}
static int
-nvkm_timer_fini(struct nvkm_subdev *subdev, bool suspend)
+nvkm_timer_fini(struct nvkm_subdev *subdev, enum nvkm_suspend_state suspend)
{
struct nvkm_timer *tmr = nvkm_timer(subdev);
tmr->func->alarm_fini(tmr);
diff --git a/drivers/gpu/drm/xe/xe_guc.c b/drivers/gpu/drm/xe/xe_guc.c
index a686b04879d6..edb939f26268 100644
--- a/drivers/gpu/drm/xe/xe_guc.c
+++ b/drivers/gpu/drm/xe/xe_guc.c
@@ -1618,7 +1618,7 @@ int xe_guc_start(struct xe_guc *guc)
return xe_guc_submit_start(guc);
}
-void xe_guc_print_info(struct xe_guc *guc, struct drm_printer *p)
+int xe_guc_print_info(struct xe_guc *guc, struct drm_printer *p)
{
struct xe_gt *gt = guc_to_gt(guc);
unsigned int fw_ref;
@@ -1630,7 +1630,7 @@ void xe_guc_print_info(struct xe_guc *guc, struct drm_printer *p)
if (!IS_SRIOV_VF(gt_to_xe(gt))) {
fw_ref = xe_force_wake_get(gt_to_fw(gt), XE_FW_GT);
if (!fw_ref)
- return;
+ return -EIO;
status = xe_mmio_read32(&gt->mmio, GUC_STATUS);
@@ -1658,6 +1658,8 @@ void xe_guc_print_info(struct xe_guc *guc, struct drm_printer *p)
drm_puts(p, "\n");
xe_guc_submit_print(guc, p);
+
+ return 0;
}
/**
diff --git a/drivers/gpu/drm/xe/xe_guc.h b/drivers/gpu/drm/xe/xe_guc.h
index e2d4c5f44ae3..61226ab81669 100644
--- a/drivers/gpu/drm/xe/xe_guc.h
+++ b/drivers/gpu/drm/xe/xe_guc.h
@@ -45,7 +45,7 @@ int xe_guc_self_cfg32(struct xe_guc *guc, u16 key, u32 val);
int xe_guc_self_cfg64(struct xe_guc *guc, u16 key, u64 val);
void xe_guc_irq_handler(struct xe_guc *guc, const u16 iir);
void xe_guc_sanitize(struct xe_guc *guc);
-void xe_guc_print_info(struct xe_guc *guc, struct drm_printer *p);
+int xe_guc_print_info(struct xe_guc *guc, struct drm_printer *p);
int xe_guc_reset_prepare(struct xe_guc *guc);
void xe_guc_reset_wait(struct xe_guc *guc);
void xe_guc_stop_prepare(struct xe_guc *guc);
diff --git a/drivers/gpu/drm/xe/xe_migrate.c b/drivers/gpu/drm/xe/xe_migrate.c
index d8ee76aab4e4..9d7329cef910 100644
--- a/drivers/gpu/drm/xe/xe_migrate.c
+++ b/drivers/gpu/drm/xe/xe_migrate.c
@@ -1201,7 +1201,7 @@ err_ret:
}
/**
- * xe_get_migrate_exec_queue() - Get the execution queue from migrate context.
+ * xe_migrate_exec_queue() - Get the execution queue from migrate context.
* @migrate: Migrate context.
*
* Return: Pointer to execution queue on success, error on failure
diff --git a/drivers/gpu/drm/xe/xe_pm.c b/drivers/gpu/drm/xe/xe_pm.c
index 766922530265..51eb6d005331 100644
--- a/drivers/gpu/drm/xe/xe_pm.c
+++ b/drivers/gpu/drm/xe/xe_pm.c
@@ -8,6 +8,7 @@
#include <linux/fault-inject.h>
#include <linux/pm_runtime.h>
#include <linux/suspend.h>
+#include <linux/dmi.h>
#include <drm/drm_managed.h>
#include <drm/ttm/ttm_placement.h>
@@ -357,9 +358,15 @@ ALLOW_ERROR_INJECTION(xe_pm_init_early, ERRNO); /* See xe_pci_probe() */
static u32 vram_threshold_value(struct xe_device *xe)
{
- /* FIXME: D3Cold temporarily disabled by default on BMG */
- if (xe->info.platform == XE_BATTLEMAGE)
- return 0;
+ if (xe->info.platform == XE_BATTLEMAGE) {
+ const char *product_name;
+
+ product_name = dmi_get_system_info(DMI_PRODUCT_NAME);
+ if (product_name && strstr(product_name, "NUC13RNG")) {
+ drm_warn(&xe->drm, "BMG + D3Cold not supported on this platform\n");
+ return 0;
+ }
+ }
return DEFAULT_VRAM_THRESHOLD;
}
diff --git a/drivers/gpu/drm/xe/xe_query.c b/drivers/gpu/drm/xe/xe_query.c
index 1c0915e2cc16..fde36280e14d 100644
--- a/drivers/gpu/drm/xe/xe_query.c
+++ b/drivers/gpu/drm/xe/xe_query.c
@@ -491,7 +491,7 @@ static int copy_mask(void __user **ptr,
if (copy_to_user(*ptr, topo, sizeof(*topo)))
return -EFAULT;
- *ptr += sizeof(topo);
+ *ptr += sizeof(*topo);
if (copy_to_user(*ptr, mask, mask_size))
return -EFAULT;
diff --git a/drivers/gpu/drm/xe/xe_tlb_inval.c b/drivers/gpu/drm/xe/xe_tlb_inval.c
index 918a59e686ea..1b7ac31a37ca 100644
--- a/drivers/gpu/drm/xe/xe_tlb_inval.c
+++ b/drivers/gpu/drm/xe/xe_tlb_inval.c
@@ -115,7 +115,7 @@ static void tlb_inval_fini(struct drm_device *drm, void *arg)
}
/**
- * xe_gt_tlb_inval_init - Initialize TLB invalidation state
+ * xe_gt_tlb_inval_init_early() - Initialize TLB invalidation state
* @gt: GT structure
*
* Initialize TLB invalidation state, purely software initialization, should
diff --git a/drivers/gpu/drm/xe/xe_tlb_inval_job.c b/drivers/gpu/drm/xe/xe_tlb_inval_job.c
index 1ae0dec2cf31..1ec9c0f5f0b6 100644
--- a/drivers/gpu/drm/xe/xe_tlb_inval_job.c
+++ b/drivers/gpu/drm/xe/xe_tlb_inval_job.c
@@ -164,7 +164,7 @@ static void xe_tlb_inval_job_destroy(struct kref *ref)
}
/**
- * xe_tlb_inval_alloc_dep() - TLB invalidation job alloc dependency
+ * xe_tlb_inval_job_alloc_dep() - TLB invalidation job alloc dependency
* @job: TLB invalidation job to alloc dependency for
*
* Allocate storage for a dependency in the TLB invalidation fence. This
diff --git a/drivers/hwmon/acpi_power_meter.c b/drivers/hwmon/acpi_power_meter.c
index 29ccdc2fb7ff..de408df0c4d7 100644
--- a/drivers/hwmon/acpi_power_meter.c
+++ b/drivers/hwmon/acpi_power_meter.c
@@ -47,6 +47,8 @@
static int cap_in_hardware;
static bool force_cap_on;
+static DEFINE_MUTEX(acpi_notify_lock);
+
static int can_cap_in_hardware(void)
{
return force_cap_on || cap_in_hardware;
@@ -823,18 +825,26 @@ static void acpi_power_meter_notify(struct acpi_device *device, u32 event)
resource = acpi_driver_data(device);
+ guard(mutex)(&acpi_notify_lock);
+
switch (event) {
case METER_NOTIFY_CONFIG:
+ if (!IS_ERR(resource->hwmon_dev))
+ hwmon_device_unregister(resource->hwmon_dev);
+
mutex_lock(&resource->lock);
+
free_capabilities(resource);
remove_domain_devices(resource);
- hwmon_device_unregister(resource->hwmon_dev);
res = read_capabilities(resource);
if (res)
dev_err_once(&device->dev, "read capabilities failed.\n");
res = read_domain_devices(resource);
if (res && res != -ENODEV)
dev_err_once(&device->dev, "read domain devices failed.\n");
+
+ mutex_unlock(&resource->lock);
+
resource->hwmon_dev =
hwmon_device_register_with_info(&device->dev,
ACPI_POWER_METER_NAME,
@@ -843,7 +853,7 @@ static void acpi_power_meter_notify(struct acpi_device *device, u32 event)
power_extra_groups);
if (IS_ERR(resource->hwmon_dev))
dev_err_once(&device->dev, "register hwmon device failed.\n");
- mutex_unlock(&resource->lock);
+
break;
case METER_NOTIFY_TRIP:
sysfs_notify(&device->dev.kobj, NULL, POWER_AVERAGE_NAME);
@@ -953,7 +963,8 @@ static void acpi_power_meter_remove(struct acpi_device *device)
return;
resource = acpi_driver_data(device);
- hwmon_device_unregister(resource->hwmon_dev);
+ if (!IS_ERR(resource->hwmon_dev))
+ hwmon_device_unregister(resource->hwmon_dev);
remove_domain_devices(resource);
free_capabilities(resource);
diff --git a/drivers/hwmon/dell-smm-hwmon.c b/drivers/hwmon/dell-smm-hwmon.c
index 6040a8940674..93143cfc157c 100644
--- a/drivers/hwmon/dell-smm-hwmon.c
+++ b/drivers/hwmon/dell-smm-hwmon.c
@@ -1640,6 +1640,14 @@ static const struct dmi_system_id i8k_whitelist_fan_control[] __initconst = {
.driver_data = (void *)&i8k_fan_control_data[I8K_FAN_30A3_31A3],
},
{
+ .ident = "Dell G15 5510",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
+ DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "Dell G15 5510"),
+ },
+ .driver_data = (void *)&i8k_fan_control_data[I8K_FAN_30A3_31A3],
+ },
+ {
.ident = "Dell G15 5511",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
diff --git a/drivers/hwmon/gpio-fan.c b/drivers/hwmon/gpio-fan.c
index 516c34bb61c9..a8892ced1e54 100644
--- a/drivers/hwmon/gpio-fan.c
+++ b/drivers/hwmon/gpio-fan.c
@@ -148,7 +148,7 @@ static int set_fan_speed(struct gpio_fan_data *fan_data, int speed_index)
int ret;
ret = pm_runtime_put_sync(fan_data->dev);
- if (ret < 0)
+ if (ret < 0 && ret != -ENOSYS)
return ret;
}
@@ -291,7 +291,7 @@ static ssize_t set_rpm(struct device *dev, struct device_attribute *attr,
{
struct gpio_fan_data *fan_data = dev_get_drvdata(dev);
unsigned long rpm;
- int ret = count;
+ int ret;
if (kstrtoul(buf, 10, &rpm))
return -EINVAL;
@@ -308,7 +308,7 @@ static ssize_t set_rpm(struct device *dev, struct device_attribute *attr,
exit_unlock:
mutex_unlock(&fan_data->lock);
- return ret;
+ return ret ? ret : count;
}
static DEVICE_ATTR_RW(pwm1);
diff --git a/drivers/hwmon/occ/common.c b/drivers/hwmon/occ/common.c
index b3694a4209b9..89928d38831b 100644
--- a/drivers/hwmon/occ/common.c
+++ b/drivers/hwmon/occ/common.c
@@ -749,6 +749,7 @@ static ssize_t occ_show_extended(struct device *dev,
* are dynamically allocated, we cannot use the existing kernel macros which
* stringify the name argument.
*/
+__printf(7, 8)
static void occ_init_attribute(struct occ_attribute *attr, int mode,
ssize_t (*show)(struct device *dev, struct device_attribute *attr, char *buf),
ssize_t (*store)(struct device *dev, struct device_attribute *attr,
diff --git a/drivers/iommu/intel/pasid.h b/drivers/iommu/intel/pasid.h
index b4c85242dc79..3809793e0259 100644
--- a/drivers/iommu/intel/pasid.h
+++ b/drivers/iommu/intel/pasid.h
@@ -24,7 +24,7 @@
#define PASID_FLAG_NESTED BIT(1)
#define PASID_FLAG_PAGE_SNOOP BIT(2)
-#define PASID_FLAG_PWSNP BIT(2)
+#define PASID_FLAG_PWSNP BIT(3)
/*
* The PASID_FLAG_FL5LP flag Indicates using 5-level paging for first-
diff --git a/drivers/net/ethernet/adi/adin1110.c b/drivers/net/ethernet/adi/adin1110.c
index 30f9d271e595..71a2397edf2b 100644
--- a/drivers/net/ethernet/adi/adin1110.c
+++ b/drivers/net/ethernet/adi/adin1110.c
@@ -1089,6 +1089,9 @@ static int adin1110_check_spi(struct adin1110_priv *priv)
reset_gpio = devm_gpiod_get_optional(&priv->spidev->dev, "reset",
GPIOD_OUT_LOW);
+ if (IS_ERR(reset_gpio))
+ return dev_err_probe(&priv->spidev->dev, PTR_ERR(reset_gpio),
+ "failed to get reset gpio\n");
if (reset_gpio) {
/* MISO pin is used for internal configuration, can't have
* anyone else disturbing the SDO line.
diff --git a/drivers/net/ethernet/cavium/liquidio/lio_main.c b/drivers/net/ethernet/cavium/liquidio/lio_main.c
index 0732440eeacd..c1a3df225254 100644
--- a/drivers/net/ethernet/cavium/liquidio/lio_main.c
+++ b/drivers/net/ethernet/cavium/liquidio/lio_main.c
@@ -3505,6 +3505,23 @@ static int setup_nic_devices(struct octeon_device *octeon_dev)
*/
netdev->netdev_ops = &lionetdevops;
+ lio = GET_LIO(netdev);
+
+ memset(lio, 0, sizeof(struct lio));
+
+ lio->ifidx = ifidx_or_pfnum;
+
+ props = &octeon_dev->props[i];
+ props->gmxport = resp->cfg_info.linfo.gmxport;
+ props->netdev = netdev;
+
+ /* Point to the properties for octeon device to which this
+ * interface belongs.
+ */
+ lio->oct_dev = octeon_dev;
+ lio->octprops = props;
+ lio->netdev = netdev;
+
retval = netif_set_real_num_rx_queues(netdev, num_oqueues);
if (retval) {
dev_err(&octeon_dev->pci_dev->dev,
@@ -3521,16 +3538,6 @@ static int setup_nic_devices(struct octeon_device *octeon_dev)
goto setup_nic_dev_free;
}
- lio = GET_LIO(netdev);
-
- memset(lio, 0, sizeof(struct lio));
-
- lio->ifidx = ifidx_or_pfnum;
-
- props = &octeon_dev->props[i];
- props->gmxport = resp->cfg_info.linfo.gmxport;
- props->netdev = netdev;
-
lio->linfo.num_rxpciq = num_oqueues;
lio->linfo.num_txpciq = num_iqueues;
for (j = 0; j < num_oqueues; j++) {
@@ -3596,13 +3603,6 @@ static int setup_nic_devices(struct octeon_device *octeon_dev)
netdev->min_mtu = LIO_MIN_MTU_SIZE;
netdev->max_mtu = LIO_MAX_MTU_SIZE;
- /* Point to the properties for octeon device to which this
- * interface belongs.
- */
- lio->oct_dev = octeon_dev;
- lio->octprops = props;
- lio->netdev = netdev;
-
dev_dbg(&octeon_dev->pci_dev->dev,
"if%d gmx: %d hw_addr: 0x%llx\n", i,
lio->linfo.gmxport, CVM_CAST64(lio->linfo.hw_addr));
@@ -3750,6 +3750,7 @@ static int setup_nic_devices(struct octeon_device *octeon_dev)
if (!devlink) {
device_unlock(&octeon_dev->pci_dev->dev);
dev_err(&octeon_dev->pci_dev->dev, "devlink alloc failed\n");
+ i--;
goto setup_nic_dev_free;
}
@@ -3765,11 +3766,11 @@ static int setup_nic_devices(struct octeon_device *octeon_dev)
setup_nic_dev_free:
- while (i--) {
+ do {
dev_err(&octeon_dev->pci_dev->dev,
"NIC ifidx:%d Setup failed\n", i);
liquidio_destroy_nic_device(octeon_dev, i);
- }
+ } while (i--);
setup_nic_dev_done:
diff --git a/drivers/net/ethernet/cavium/liquidio/lio_vf_main.c b/drivers/net/ethernet/cavium/liquidio/lio_vf_main.c
index e02942dbbcce..43c595f3b84e 100644
--- a/drivers/net/ethernet/cavium/liquidio/lio_vf_main.c
+++ b/drivers/net/ethernet/cavium/liquidio/lio_vf_main.c
@@ -2212,11 +2212,11 @@ static int setup_nic_devices(struct octeon_device *octeon_dev)
setup_nic_dev_free:
- while (i--) {
+ do {
dev_err(&octeon_dev->pci_dev->dev,
"NIC ifidx:%d Setup failed\n", i);
liquidio_destroy_nic_device(octeon_dev, i);
- }
+ } while (i--);
setup_nic_dev_done:
diff --git a/drivers/net/ethernet/freescale/dpaa2/dpaa2-switch.c b/drivers/net/ethernet/freescale/dpaa2/dpaa2-switch.c
index b1e1ad9e4b48..66240c340492 100644
--- a/drivers/net/ethernet/freescale/dpaa2/dpaa2-switch.c
+++ b/drivers/net/ethernet/freescale/dpaa2/dpaa2-switch.c
@@ -1531,6 +1531,10 @@ static irqreturn_t dpaa2_switch_irq0_handler_thread(int irq_num, void *arg)
}
if_id = (status & 0xFFFF0000) >> 16;
+ if (if_id >= ethsw->sw_attr.num_ifs) {
+ dev_err(dev, "Invalid if_id %d in IRQ status\n", if_id);
+ goto out;
+ }
port_priv = ethsw->ports[if_id];
if (status & DPSW_IRQ_EVENT_LINK_CHANGED)
@@ -3024,6 +3028,12 @@ static int dpaa2_switch_init(struct fsl_mc_device *sw_dev)
goto err_close;
}
+ if (!ethsw->sw_attr.num_ifs) {
+ dev_err(dev, "DPSW device has no interfaces\n");
+ err = -ENODEV;
+ goto err_close;
+ }
+
err = dpsw_get_api_version(ethsw->mc_io, 0,
&ethsw->major,
&ethsw->minor);
diff --git a/drivers/net/ethernet/freescale/enetc/enetc.c b/drivers/net/ethernet/freescale/enetc/enetc.c
index 53b26cece16a..e380a4f39855 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc.c
@@ -2512,10 +2512,13 @@ int enetc_configure_si(struct enetc_ndev_priv *priv)
struct enetc_hw *hw = &si->hw;
int err;
- /* set SI cache attributes */
- enetc_wr(hw, ENETC_SICAR0,
- ENETC_SICAR_RD_COHERENT | ENETC_SICAR_WR_COHERENT);
- enetc_wr(hw, ENETC_SICAR1, ENETC_SICAR_MSI);
+ if (is_enetc_rev1(si)) {
+ /* set SI cache attributes */
+ enetc_wr(hw, ENETC_SICAR0,
+ ENETC_SICAR_RD_COHERENT | ENETC_SICAR_WR_COHERENT);
+ enetc_wr(hw, ENETC_SICAR1, ENETC_SICAR_MSI);
+ }
+
/* enable SI */
enetc_wr(hw, ENETC_SIMR, ENETC_SIMR_EN);
diff --git a/drivers/net/ethernet/freescale/enetc/enetc4_pf.c b/drivers/net/ethernet/freescale/enetc/enetc4_pf.c
index 498346dd996a..5850540634b0 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc4_pf.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc4_pf.c
@@ -59,10 +59,10 @@ static void enetc4_pf_set_si_primary_mac(struct enetc_hw *hw, int si,
if (si != 0) {
__raw_writel(upper, hw->port + ENETC4_PSIPMAR0(si));
- __raw_writew(lower, hw->port + ENETC4_PSIPMAR1(si));
+ __raw_writel(lower, hw->port + ENETC4_PSIPMAR1(si));
} else {
__raw_writel(upper, hw->port + ENETC4_PMAR0);
- __raw_writew(lower, hw->port + ENETC4_PMAR1);
+ __raw_writel(lower, hw->port + ENETC4_PMAR1);
}
}
@@ -73,7 +73,7 @@ static void enetc4_pf_get_si_primary_mac(struct enetc_hw *hw, int si,
u16 lower;
upper = __raw_readl(hw->port + ENETC4_PSIPMAR0(si));
- lower = __raw_readw(hw->port + ENETC4_PSIPMAR1(si));
+ lower = __raw_readl(hw->port + ENETC4_PSIPMAR1(si));
put_unaligned_le32(upper, addr);
put_unaligned_le16(lower, addr + 4);
diff --git a/drivers/net/ethernet/freescale/enetc/enetc_cbdr.c b/drivers/net/ethernet/freescale/enetc/enetc_cbdr.c
index 3d5f31879d5c..a635bfdc30af 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc_cbdr.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc_cbdr.c
@@ -74,10 +74,6 @@ int enetc4_setup_cbdr(struct enetc_si *si)
if (!user->ring)
return -ENOMEM;
- /* set CBDR cache attributes */
- enetc_wr(hw, ENETC_SICAR2,
- ENETC_SICAR_RD_COHERENT | ENETC_SICAR_WR_COHERENT);
-
regs.pir = hw->reg + ENETC_SICBDRPIR;
regs.cir = hw->reg + ENETC_SICBDRCIR;
regs.mr = hw->reg + ENETC_SICBDRMR;
diff --git a/drivers/net/ethernet/freescale/enetc/enetc_hw.h b/drivers/net/ethernet/freescale/enetc/enetc_hw.h
index 7b882b8921fe..662e4fbafb74 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc_hw.h
+++ b/drivers/net/ethernet/freescale/enetc/enetc_hw.h
@@ -708,13 +708,24 @@ struct enetc_cmd_rfse {
#define ENETC_RFSE_EN BIT(15)
#define ENETC_RFSE_MODE_BD 2
+static inline void enetc_get_primary_mac_addr(struct enetc_hw *hw, u8 *addr)
+{
+ u32 upper;
+ u16 lower;
+
+ upper = __raw_readl(hw->reg + ENETC_SIPMAR0);
+ lower = __raw_readl(hw->reg + ENETC_SIPMAR1);
+
+ put_unaligned_le32(upper, addr);
+ put_unaligned_le16(lower, addr + 4);
+}
+
static inline void enetc_load_primary_mac_addr(struct enetc_hw *hw,
struct net_device *ndev)
{
- u8 addr[ETH_ALEN] __aligned(4);
+ u8 addr[ETH_ALEN];
- *(u32 *)addr = __raw_readl(hw->reg + ENETC_SIPMAR0);
- *(u16 *)(addr + 4) = __raw_readw(hw->reg + ENETC_SIPMAR1);
+ enetc_get_primary_mac_addr(hw, addr);
eth_hw_addr_set(ndev, addr);
}
diff --git a/drivers/net/ethernet/google/gve/gve_ethtool.c b/drivers/net/ethernet/google/gve/gve_ethtool.c
index 311b106160b2..66ddc4413f8d 100644
--- a/drivers/net/ethernet/google/gve/gve_ethtool.c
+++ b/drivers/net/ethernet/google/gve/gve_ethtool.c
@@ -152,11 +152,13 @@ gve_get_ethtool_stats(struct net_device *netdev,
u64 tmp_rx_pkts, tmp_rx_hsplit_pkt, tmp_rx_bytes, tmp_rx_hsplit_bytes,
tmp_rx_skb_alloc_fail, tmp_rx_buf_alloc_fail,
tmp_rx_desc_err_dropped_pkt, tmp_rx_hsplit_unsplit_pkt,
- tmp_tx_pkts, tmp_tx_bytes;
+ tmp_tx_pkts, tmp_tx_bytes,
+ tmp_xdp_tx_errors, tmp_xdp_redirect_errors;
u64 rx_buf_alloc_fail, rx_desc_err_dropped_pkt, rx_hsplit_unsplit_pkt,
rx_pkts, rx_hsplit_pkt, rx_skb_alloc_fail, rx_bytes, tx_pkts, tx_bytes,
- tx_dropped;
- int stats_idx, base_stats_idx, max_stats_idx;
+ tx_dropped, xdp_tx_errors, xdp_redirect_errors;
+ int rx_base_stats_idx, max_rx_stats_idx, max_tx_stats_idx;
+ int stats_idx, stats_region_len, nic_stats_len;
struct stats *report_stats;
int *rx_qid_to_stats_idx;
int *tx_qid_to_stats_idx;
@@ -198,6 +200,7 @@ gve_get_ethtool_stats(struct net_device *netdev,
for (rx_pkts = 0, rx_bytes = 0, rx_hsplit_pkt = 0,
rx_skb_alloc_fail = 0, rx_buf_alloc_fail = 0,
rx_desc_err_dropped_pkt = 0, rx_hsplit_unsplit_pkt = 0,
+ xdp_tx_errors = 0, xdp_redirect_errors = 0,
ring = 0;
ring < priv->rx_cfg.num_queues; ring++) {
if (priv->rx) {
@@ -215,6 +218,9 @@ gve_get_ethtool_stats(struct net_device *netdev,
rx->rx_desc_err_dropped_pkt;
tmp_rx_hsplit_unsplit_pkt =
rx->rx_hsplit_unsplit_pkt;
+ tmp_xdp_tx_errors = rx->xdp_tx_errors;
+ tmp_xdp_redirect_errors =
+ rx->xdp_redirect_errors;
} while (u64_stats_fetch_retry(&priv->rx[ring].statss,
start));
rx_pkts += tmp_rx_pkts;
@@ -224,6 +230,8 @@ gve_get_ethtool_stats(struct net_device *netdev,
rx_buf_alloc_fail += tmp_rx_buf_alloc_fail;
rx_desc_err_dropped_pkt += tmp_rx_desc_err_dropped_pkt;
rx_hsplit_unsplit_pkt += tmp_rx_hsplit_unsplit_pkt;
+ xdp_tx_errors += tmp_xdp_tx_errors;
+ xdp_redirect_errors += tmp_xdp_redirect_errors;
}
}
for (tx_pkts = 0, tx_bytes = 0, tx_dropped = 0, ring = 0;
@@ -249,8 +257,8 @@ gve_get_ethtool_stats(struct net_device *netdev,
data[i++] = rx_bytes;
data[i++] = tx_bytes;
/* total rx dropped packets */
- data[i++] = rx_skb_alloc_fail + rx_buf_alloc_fail +
- rx_desc_err_dropped_pkt;
+ data[i++] = rx_skb_alloc_fail + rx_desc_err_dropped_pkt +
+ xdp_tx_errors + xdp_redirect_errors;
data[i++] = tx_dropped;
data[i++] = priv->tx_timeo_cnt;
data[i++] = rx_skb_alloc_fail;
@@ -265,20 +273,38 @@ gve_get_ethtool_stats(struct net_device *netdev,
data[i++] = priv->stats_report_trigger_cnt;
i = GVE_MAIN_STATS_LEN;
- /* For rx cross-reporting stats, start from nic rx stats in report */
- base_stats_idx = GVE_TX_STATS_REPORT_NUM * num_tx_queues +
- GVE_RX_STATS_REPORT_NUM * priv->rx_cfg.num_queues;
- /* The boundary between driver stats and NIC stats shifts if there are
- * stopped queues.
- */
- base_stats_idx += NIC_RX_STATS_REPORT_NUM * num_stopped_rxqs +
- NIC_TX_STATS_REPORT_NUM * num_stopped_txqs;
- max_stats_idx = NIC_RX_STATS_REPORT_NUM *
- (priv->rx_cfg.num_queues - num_stopped_rxqs) +
- base_stats_idx;
+ rx_base_stats_idx = 0;
+ max_rx_stats_idx = 0;
+ max_tx_stats_idx = 0;
+ stats_region_len = priv->stats_report_len -
+ sizeof(struct gve_stats_report);
+ nic_stats_len = (NIC_RX_STATS_REPORT_NUM * priv->rx_cfg.num_queues +
+ NIC_TX_STATS_REPORT_NUM * num_tx_queues) * sizeof(struct stats);
+ if (unlikely((stats_region_len -
+ nic_stats_len) % sizeof(struct stats))) {
+ net_err_ratelimited("Starting index of NIC stats should be multiple of stats size");
+ } else {
+ /* For rx cross-reporting stats,
+ * start from nic rx stats in report
+ */
+ rx_base_stats_idx = (stats_region_len - nic_stats_len) /
+ sizeof(struct stats);
+ /* The boundary between driver stats and NIC stats
+ * shifts if there are stopped queues
+ */
+ rx_base_stats_idx += NIC_RX_STATS_REPORT_NUM *
+ num_stopped_rxqs + NIC_TX_STATS_REPORT_NUM *
+ num_stopped_txqs;
+ max_rx_stats_idx = NIC_RX_STATS_REPORT_NUM *
+ (priv->rx_cfg.num_queues - num_stopped_rxqs) +
+ rx_base_stats_idx;
+ max_tx_stats_idx = NIC_TX_STATS_REPORT_NUM *
+ (num_tx_queues - num_stopped_txqs) +
+ max_rx_stats_idx;
+ }
/* Preprocess the stats report for rx, map queue id to start index */
skip_nic_stats = false;
- for (stats_idx = base_stats_idx; stats_idx < max_stats_idx;
+ for (stats_idx = rx_base_stats_idx; stats_idx < max_rx_stats_idx;
stats_idx += NIC_RX_STATS_REPORT_NUM) {
u32 stat_name = be32_to_cpu(report_stats[stats_idx].stat_name);
u32 queue_id = be32_to_cpu(report_stats[stats_idx].queue_id);
@@ -311,6 +337,9 @@ gve_get_ethtool_stats(struct net_device *netdev,
tmp_rx_buf_alloc_fail = rx->rx_buf_alloc_fail;
tmp_rx_desc_err_dropped_pkt =
rx->rx_desc_err_dropped_pkt;
+ tmp_xdp_tx_errors = rx->xdp_tx_errors;
+ tmp_xdp_redirect_errors =
+ rx->xdp_redirect_errors;
} while (u64_stats_fetch_retry(&priv->rx[ring].statss,
start));
data[i++] = tmp_rx_bytes;
@@ -321,8 +350,9 @@ gve_get_ethtool_stats(struct net_device *netdev,
data[i++] = rx->rx_frag_alloc_cnt;
/* rx dropped packets */
data[i++] = tmp_rx_skb_alloc_fail +
- tmp_rx_buf_alloc_fail +
- tmp_rx_desc_err_dropped_pkt;
+ tmp_rx_desc_err_dropped_pkt +
+ tmp_xdp_tx_errors +
+ tmp_xdp_redirect_errors;
data[i++] = rx->rx_copybreak_pkt;
data[i++] = rx->rx_copied_pkt;
/* stats from NIC */
@@ -354,14 +384,9 @@ gve_get_ethtool_stats(struct net_device *netdev,
i += priv->rx_cfg.num_queues * NUM_GVE_RX_CNTS;
}
- /* For tx cross-reporting stats, start from nic tx stats in report */
- base_stats_idx = max_stats_idx;
- max_stats_idx = NIC_TX_STATS_REPORT_NUM *
- (num_tx_queues - num_stopped_txqs) +
- max_stats_idx;
- /* Preprocess the stats report for tx, map queue id to start index */
skip_nic_stats = false;
- for (stats_idx = base_stats_idx; stats_idx < max_stats_idx;
+ /* NIC TX stats start right after NIC RX stats */
+ for (stats_idx = max_rx_stats_idx; stats_idx < max_tx_stats_idx;
stats_idx += NIC_TX_STATS_REPORT_NUM) {
u32 stat_name = be32_to_cpu(report_stats[stats_idx].stat_name);
u32 queue_id = be32_to_cpu(report_stats[stats_idx].queue_id);
diff --git a/drivers/net/ethernet/google/gve/gve_main.c b/drivers/net/ethernet/google/gve/gve_main.c
index 52c5e4942cd4..dbc84de39b70 100644
--- a/drivers/net/ethernet/google/gve/gve_main.c
+++ b/drivers/net/ethernet/google/gve/gve_main.c
@@ -283,9 +283,9 @@ static int gve_alloc_stats_report(struct gve_priv *priv)
int tx_stats_num, rx_stats_num;
tx_stats_num = (GVE_TX_STATS_REPORT_NUM + NIC_TX_STATS_REPORT_NUM) *
- gve_num_tx_queues(priv);
+ priv->tx_cfg.max_queues;
rx_stats_num = (GVE_RX_STATS_REPORT_NUM + NIC_RX_STATS_REPORT_NUM) *
- priv->rx_cfg.num_queues;
+ priv->rx_cfg.max_queues;
priv->stats_report_len = struct_size(priv->stats_report, stats,
size_add(tx_stats_num, rx_stats_num));
priv->stats_report =
diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c
index 0b1cc0481027..d3bc3207054f 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_main.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_main.c
@@ -9030,7 +9030,6 @@ int i40e_open(struct net_device *netdev)
TCP_FLAG_FIN |
TCP_FLAG_CWR) >> 16);
wr32(&pf->hw, I40E_GLLAN_TSOMSK_L, be32_to_cpu(TCP_FLAG_CWR) >> 16);
- udp_tunnel_get_rx_info(netdev);
return 0;
}
diff --git a/drivers/net/ethernet/intel/ice/ice_main.c b/drivers/net/ethernet/intel/ice/ice_main.c
index 71c6d53b461e..d04605d3e61a 100644
--- a/drivers/net/ethernet/intel/ice/ice_main.c
+++ b/drivers/net/ethernet/intel/ice/ice_main.c
@@ -3314,18 +3314,20 @@ static irqreturn_t ice_misc_intr_thread_fn(int __always_unused irq, void *data)
if (ice_is_reset_in_progress(pf->state))
goto skip_irq;
- if (test_and_clear_bit(ICE_MISC_THREAD_TX_TSTAMP, pf->misc_thread)) {
- /* Process outstanding Tx timestamps. If there is more work,
- * re-arm the interrupt to trigger again.
- */
- if (ice_ptp_process_ts(pf) == ICE_TX_TSTAMP_WORK_PENDING) {
- wr32(hw, PFINT_OICR, PFINT_OICR_TSYN_TX_M);
- ice_flush(hw);
- }
- }
+ if (test_and_clear_bit(ICE_MISC_THREAD_TX_TSTAMP, pf->misc_thread))
+ ice_ptp_process_ts(pf);
skip_irq:
ice_irq_dynamic_ena(hw, NULL, NULL);
+ ice_flush(hw);
+
+ if (ice_ptp_tx_tstamps_pending(pf)) {
+ /* If any new Tx timestamps happened while in interrupt,
+ * re-arm the interrupt to trigger it again.
+ */
+ wr32(hw, PFINT_OICR, PFINT_OICR_TSYN_TX_M);
+ ice_flush(hw);
+ }
return IRQ_HANDLED;
}
@@ -7807,6 +7809,9 @@ static void ice_rebuild(struct ice_pf *pf, enum ice_reset_req reset_type)
/* Restore timestamp mode settings after VSI rebuild */
ice_ptp_restore_timestamp_mode(pf);
+
+ /* Start PTP periodic work after VSI is fully rebuilt */
+ ice_ptp_queue_work(pf);
return;
err_vsi_rebuild:
@@ -9657,9 +9662,6 @@ int ice_open_internal(struct net_device *netdev)
netdev_err(netdev, "Failed to open VSI 0x%04X on switch 0x%04X\n",
vsi->vsi_num, vsi->vsw->sw_id);
- /* Update existing tunnels information */
- udp_tunnel_get_rx_info(netdev);
-
return err;
}
diff --git a/drivers/net/ethernet/intel/ice/ice_ptp.c b/drivers/net/ethernet/intel/ice/ice_ptp.c
index 4c8d20f2d2c0..272683001476 100644
--- a/drivers/net/ethernet/intel/ice/ice_ptp.c
+++ b/drivers/net/ethernet/intel/ice/ice_ptp.c
@@ -573,6 +573,9 @@ static void ice_ptp_process_tx_tstamp(struct ice_ptp_tx *tx)
pf = ptp_port_to_pf(ptp_port);
hw = &pf->hw;
+ if (!tx->init)
+ return;
+
/* Read the Tx ready status first */
if (tx->has_ready_bitmap) {
err = ice_get_phy_tx_tstamp_ready(hw, tx->block, &tstamp_ready);
@@ -674,14 +677,9 @@ skip_ts_read:
pf->ptp.tx_hwtstamp_good += tstamp_good;
}
-/**
- * ice_ptp_tx_tstamp_owner - Process Tx timestamps for all ports on the device
- * @pf: Board private structure
- */
-static enum ice_tx_tstamp_work ice_ptp_tx_tstamp_owner(struct ice_pf *pf)
+static void ice_ptp_tx_tstamp_owner(struct ice_pf *pf)
{
struct ice_ptp_port *port;
- unsigned int i;
mutex_lock(&pf->adapter->ports.lock);
list_for_each_entry(port, &pf->adapter->ports.ports, list_node) {
@@ -693,49 +691,6 @@ static enum ice_tx_tstamp_work ice_ptp_tx_tstamp_owner(struct ice_pf *pf)
ice_ptp_process_tx_tstamp(tx);
}
mutex_unlock(&pf->adapter->ports.lock);
-
- for (i = 0; i < ICE_GET_QUAD_NUM(pf->hw.ptp.num_lports); i++) {
- u64 tstamp_ready;
- int err;
-
- /* Read the Tx ready status first */
- err = ice_get_phy_tx_tstamp_ready(&pf->hw, i, &tstamp_ready);
- if (err)
- break;
- else if (tstamp_ready)
- return ICE_TX_TSTAMP_WORK_PENDING;
- }
-
- return ICE_TX_TSTAMP_WORK_DONE;
-}
-
-/**
- * ice_ptp_tx_tstamp - Process Tx timestamps for this function.
- * @tx: Tx tracking structure to initialize
- *
- * Returns: ICE_TX_TSTAMP_WORK_PENDING if there are any outstanding incomplete
- * Tx timestamps, or ICE_TX_TSTAMP_WORK_DONE otherwise.
- */
-static enum ice_tx_tstamp_work ice_ptp_tx_tstamp(struct ice_ptp_tx *tx)
-{
- bool more_timestamps;
- unsigned long flags;
-
- if (!tx->init)
- return ICE_TX_TSTAMP_WORK_DONE;
-
- /* Process the Tx timestamp tracker */
- ice_ptp_process_tx_tstamp(tx);
-
- /* Check if there are outstanding Tx timestamps */
- spin_lock_irqsave(&tx->lock, flags);
- more_timestamps = tx->init && !bitmap_empty(tx->in_use, tx->len);
- spin_unlock_irqrestore(&tx->lock, flags);
-
- if (more_timestamps)
- return ICE_TX_TSTAMP_WORK_PENDING;
-
- return ICE_TX_TSTAMP_WORK_DONE;
}
/**
@@ -1347,9 +1302,12 @@ void ice_ptp_link_change(struct ice_pf *pf, bool linkup)
/* Do not reconfigure E810 or E830 PHY */
return;
case ICE_MAC_GENERIC:
- case ICE_MAC_GENERIC_3K_E825:
ice_ptp_port_phy_restart(ptp_port);
return;
+ case ICE_MAC_GENERIC_3K_E825:
+ if (linkup)
+ ice_ptp_port_phy_restart(ptp_port);
+ return;
default:
dev_warn(ice_pf_to_dev(pf), "%s: Unknown PHY type\n", __func__);
}
@@ -2663,30 +2621,92 @@ s8 ice_ptp_request_ts(struct ice_ptp_tx *tx, struct sk_buff *skb)
return idx + tx->offset;
}
-/**
- * ice_ptp_process_ts - Process the PTP Tx timestamps
- * @pf: Board private structure
- *
- * Returns: ICE_TX_TSTAMP_WORK_PENDING if there are any outstanding Tx
- * timestamps that need processing, and ICE_TX_TSTAMP_WORK_DONE otherwise.
- */
-enum ice_tx_tstamp_work ice_ptp_process_ts(struct ice_pf *pf)
+void ice_ptp_process_ts(struct ice_pf *pf)
{
switch (pf->ptp.tx_interrupt_mode) {
case ICE_PTP_TX_INTERRUPT_NONE:
/* This device has the clock owner handle timestamps for it */
- return ICE_TX_TSTAMP_WORK_DONE;
+ return;
case ICE_PTP_TX_INTERRUPT_SELF:
/* This device handles its own timestamps */
- return ice_ptp_tx_tstamp(&pf->ptp.port.tx);
+ ice_ptp_process_tx_tstamp(&pf->ptp.port.tx);
+ return;
case ICE_PTP_TX_INTERRUPT_ALL:
/* This device handles timestamps for all ports */
- return ice_ptp_tx_tstamp_owner(pf);
+ ice_ptp_tx_tstamp_owner(pf);
+ return;
+ default:
+ WARN_ONCE(1, "Unexpected Tx timestamp interrupt mode %u\n",
+ pf->ptp.tx_interrupt_mode);
+ return;
+ }
+}
+
+static bool ice_port_has_timestamps(struct ice_ptp_tx *tx)
+{
+ bool more_timestamps;
+
+ scoped_guard(spinlock_irqsave, &tx->lock) {
+ if (!tx->init)
+ return false;
+
+ more_timestamps = !bitmap_empty(tx->in_use, tx->len);
+ }
+
+ return more_timestamps;
+}
+
+static bool ice_any_port_has_timestamps(struct ice_pf *pf)
+{
+ struct ice_ptp_port *port;
+
+ scoped_guard(mutex, &pf->adapter->ports.lock) {
+ list_for_each_entry(port, &pf->adapter->ports.ports,
+ list_node) {
+ struct ice_ptp_tx *tx = &port->tx;
+
+ if (ice_port_has_timestamps(tx))
+ return true;
+ }
+ }
+
+ return false;
+}
+
+bool ice_ptp_tx_tstamps_pending(struct ice_pf *pf)
+{
+ struct ice_hw *hw = &pf->hw;
+ unsigned int i;
+
+ /* Check software indicator */
+ switch (pf->ptp.tx_interrupt_mode) {
+ case ICE_PTP_TX_INTERRUPT_NONE:
+ return false;
+ case ICE_PTP_TX_INTERRUPT_SELF:
+ if (ice_port_has_timestamps(&pf->ptp.port.tx))
+ return true;
+ break;
+ case ICE_PTP_TX_INTERRUPT_ALL:
+ if (ice_any_port_has_timestamps(pf))
+ return true;
+ break;
default:
WARN_ONCE(1, "Unexpected Tx timestamp interrupt mode %u\n",
pf->ptp.tx_interrupt_mode);
- return ICE_TX_TSTAMP_WORK_DONE;
+ break;
+ }
+
+ /* Check hardware indicator */
+ for (i = 0; i < ICE_GET_QUAD_NUM(hw->ptp.num_lports); i++) {
+ u64 tstamp_ready = 0;
+ int err;
+
+ err = ice_get_phy_tx_tstamp_ready(&pf->hw, i, &tstamp_ready);
+ if (err || tstamp_ready)
+ return true;
}
+
+ return false;
}
/**
@@ -2738,7 +2758,9 @@ irqreturn_t ice_ptp_ts_irq(struct ice_pf *pf)
return IRQ_WAKE_THREAD;
case ICE_MAC_E830:
/* E830 can read timestamps in the top half using rd32() */
- if (ice_ptp_process_ts(pf) == ICE_TX_TSTAMP_WORK_PENDING) {
+ ice_ptp_process_ts(pf);
+
+ if (ice_ptp_tx_tstamps_pending(pf)) {
/* Process outstanding Tx timestamps. If there
* is more work, re-arm the interrupt to trigger again.
*/
@@ -2818,6 +2840,20 @@ static void ice_ptp_periodic_work(struct kthread_work *work)
}
/**
+ * ice_ptp_queue_work - Queue PTP periodic work for a PF
+ * @pf: Board private structure
+ *
+ * Helper function to queue PTP periodic work after VSI rebuild completes.
+ * This ensures that PTP work only runs when VSI structures are ready.
+ */
+void ice_ptp_queue_work(struct ice_pf *pf)
+{
+ if (test_bit(ICE_FLAG_PTP_SUPPORTED, pf->flags) &&
+ pf->ptp.state == ICE_PTP_READY)
+ kthread_queue_delayed_work(pf->ptp.kworker, &pf->ptp.work, 0);
+}
+
+/**
* ice_ptp_prepare_rebuild_sec - Prepare second NAC for PTP reset or rebuild
* @pf: Board private structure
* @rebuild: rebuild if true, prepare if false
@@ -2835,10 +2871,15 @@ static void ice_ptp_prepare_rebuild_sec(struct ice_pf *pf, bool rebuild,
struct ice_pf *peer_pf = ptp_port_to_pf(port);
if (!ice_is_primary(&peer_pf->hw)) {
- if (rebuild)
+ if (rebuild) {
+ /* TODO: When implementing rebuild=true:
+ * 1. Ensure secondary PFs' VSIs are rebuilt
+ * 2. Call ice_ptp_queue_work(peer_pf) after VSI rebuild
+ */
ice_ptp_rebuild(peer_pf, reset_type);
- else
+ } else {
ice_ptp_prepare_for_reset(peer_pf, reset_type);
+ }
}
}
}
@@ -2984,9 +3025,6 @@ void ice_ptp_rebuild(struct ice_pf *pf, enum ice_reset_req reset_type)
ptp->state = ICE_PTP_READY;
- /* Start periodic work going */
- kthread_queue_delayed_work(ptp->kworker, &ptp->work, 0);
-
dev_info(ice_pf_to_dev(pf), "PTP reset successful\n");
return;
@@ -3191,8 +3229,9 @@ static void ice_ptp_init_tx_interrupt_mode(struct ice_pf *pf)
{
switch (pf->hw.mac_type) {
case ICE_MAC_GENERIC:
- /* E822 based PHY has the clock owner process the interrupt
- * for all ports.
+ case ICE_MAC_GENERIC_3K_E825:
+ /* E82x hardware has the clock owner process timestamps for
+ * all ports.
*/
if (ice_pf_src_tmr_owned(pf))
pf->ptp.tx_interrupt_mode = ICE_PTP_TX_INTERRUPT_ALL;
diff --git a/drivers/net/ethernet/intel/ice/ice_ptp.h b/drivers/net/ethernet/intel/ice/ice_ptp.h
index 27016aac4f1e..8c44bd758a4f 100644
--- a/drivers/net/ethernet/intel/ice/ice_ptp.h
+++ b/drivers/net/ethernet/intel/ice/ice_ptp.h
@@ -304,8 +304,9 @@ void ice_ptp_extts_event(struct ice_pf *pf);
s8 ice_ptp_request_ts(struct ice_ptp_tx *tx, struct sk_buff *skb);
void ice_ptp_req_tx_single_tstamp(struct ice_ptp_tx *tx, u8 idx);
void ice_ptp_complete_tx_single_tstamp(struct ice_ptp_tx *tx);
-enum ice_tx_tstamp_work ice_ptp_process_ts(struct ice_pf *pf);
+void ice_ptp_process_ts(struct ice_pf *pf);
irqreturn_t ice_ptp_ts_irq(struct ice_pf *pf);
+bool ice_ptp_tx_tstamps_pending(struct ice_pf *pf);
u64 ice_ptp_read_src_clk_reg(struct ice_pf *pf,
struct ptp_system_timestamp *sts);
@@ -317,6 +318,7 @@ void ice_ptp_prepare_for_reset(struct ice_pf *pf,
void ice_ptp_init(struct ice_pf *pf);
void ice_ptp_release(struct ice_pf *pf);
void ice_ptp_link_change(struct ice_pf *pf, bool linkup);
+void ice_ptp_queue_work(struct ice_pf *pf);
#else /* IS_ENABLED(CONFIG_PTP_1588_CLOCK) */
static inline int ice_ptp_hwtstamp_get(struct net_device *netdev,
@@ -345,16 +347,18 @@ static inline void ice_ptp_req_tx_single_tstamp(struct ice_ptp_tx *tx, u8 idx)
static inline void ice_ptp_complete_tx_single_tstamp(struct ice_ptp_tx *tx) { }
-static inline bool ice_ptp_process_ts(struct ice_pf *pf)
-{
- return true;
-}
+static inline void ice_ptp_process_ts(struct ice_pf *pf) { }
static inline irqreturn_t ice_ptp_ts_irq(struct ice_pf *pf)
{
return IRQ_HANDLED;
}
+static inline bool ice_ptp_tx_tstamps_pending(struct ice_pf *pf)
+{
+ return false;
+}
+
static inline u64 ice_ptp_read_src_clk_reg(struct ice_pf *pf,
struct ptp_system_timestamp *sts)
{
@@ -383,6 +387,10 @@ static inline void ice_ptp_link_change(struct ice_pf *pf, bool linkup)
{
}
+static inline void ice_ptp_queue_work(struct ice_pf *pf)
+{
+}
+
static inline int ice_ptp_clock_index(struct ice_pf *pf)
{
return -1;
diff --git a/drivers/net/ethernet/spacemit/k1_emac.c b/drivers/net/ethernet/spacemit/k1_emac.c
index 88e9424d2d51..b49c4708bf9e 100644
--- a/drivers/net/ethernet/spacemit/k1_emac.c
+++ b/drivers/net/ethernet/spacemit/k1_emac.c
@@ -12,6 +12,7 @@
#include <linux/dma-mapping.h>
#include <linux/etherdevice.h>
#include <linux/ethtool.h>
+#include <linux/if_vlan.h>
#include <linux/interrupt.h>
#include <linux/io.h>
#include <linux/iopoll.h>
@@ -38,7 +39,7 @@
#define EMAC_DEFAULT_BUFSIZE 1536
#define EMAC_RX_BUF_2K 2048
-#define EMAC_RX_BUF_4K 4096
+#define EMAC_RX_BUF_MAX FIELD_MAX(RX_DESC_1_BUFFER_SIZE_1_MASK)
/* Tuning parameters from SpacemiT */
#define EMAC_TX_FRAMES 64
@@ -202,8 +203,7 @@ static void emac_init_hw(struct emac_priv *priv)
{
/* Destination address for 802.3x Ethernet flow control */
u8 fc_dest_addr[ETH_ALEN] = { 0x01, 0x80, 0xc2, 0x00, 0x00, 0x01 };
-
- u32 rxirq = 0, dma = 0;
+ u32 rxirq = 0, dma = 0, frame_sz;
regmap_set_bits(priv->regmap_apmu,
priv->regmap_apmu_offset + APMU_EMAC_CTRL_REG,
@@ -228,6 +228,15 @@ static void emac_init_hw(struct emac_priv *priv)
DEFAULT_TX_THRESHOLD);
emac_wr(priv, MAC_RECEIVE_PACKET_START_THRESHOLD, DEFAULT_RX_THRESHOLD);
+ /* Set maximum frame size and jabber size based on configured MTU,
+ * accounting for Ethernet header, double VLAN tags, and FCS.
+ */
+ frame_sz = priv->ndev->mtu + ETH_HLEN + 2 * VLAN_HLEN + ETH_FCS_LEN;
+
+ emac_wr(priv, MAC_MAXIMUM_FRAME_SIZE, frame_sz);
+ emac_wr(priv, MAC_TRANSMIT_JABBER_SIZE, frame_sz);
+ emac_wr(priv, MAC_RECEIVE_JABBER_SIZE, frame_sz);
+
/* Configure flow control (enabled in emac_adjust_link() later) */
emac_set_mac_addr_reg(priv, fc_dest_addr, MAC_FC_SOURCE_ADDRESS_HIGH);
emac_wr(priv, MAC_FC_PAUSE_HIGH_THRESHOLD, DEFAULT_FC_FIFO_HIGH);
@@ -924,14 +933,14 @@ static int emac_change_mtu(struct net_device *ndev, int mtu)
return -EBUSY;
}
- frame_len = mtu + ETH_HLEN + ETH_FCS_LEN;
+ frame_len = mtu + ETH_HLEN + 2 * VLAN_HLEN + ETH_FCS_LEN;
if (frame_len <= EMAC_DEFAULT_BUFSIZE)
priv->dma_buf_sz = EMAC_DEFAULT_BUFSIZE;
else if (frame_len <= EMAC_RX_BUF_2K)
priv->dma_buf_sz = EMAC_RX_BUF_2K;
else
- priv->dma_buf_sz = EMAC_RX_BUF_4K;
+ priv->dma_buf_sz = EMAC_RX_BUF_MAX;
ndev->mtu = mtu;
@@ -2025,7 +2034,7 @@ static int emac_probe(struct platform_device *pdev)
ndev->hw_features = NETIF_F_SG;
ndev->features |= ndev->hw_features;
- ndev->max_mtu = EMAC_RX_BUF_4K - (ETH_HLEN + ETH_FCS_LEN);
+ ndev->max_mtu = EMAC_RX_BUF_MAX - (ETH_HLEN + 2 * VLAN_HLEN + ETH_FCS_LEN);
ndev->pcpu_stat_type = NETDEV_PCPU_STAT_DSTATS;
priv = netdev_priv(ndev);
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
index 3f42843cd9ed..a379221b96a3 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
@@ -8042,7 +8042,7 @@ int stmmac_suspend(struct device *dev)
u32 chan;
if (!ndev || !netif_running(ndev))
- return 0;
+ goto suspend_bsp;
mutex_lock(&priv->lock);
@@ -8082,6 +8082,7 @@ int stmmac_suspend(struct device *dev)
if (stmmac_fpe_supported(priv))
ethtool_mmsv_stop(&priv->fpe_cfg.mmsv);
+suspend_bsp:
if (priv->plat->suspend)
return priv->plat->suspend(dev, priv->plat->bsp_priv);
diff --git a/drivers/net/ethernet/ti/cpsw.c b/drivers/net/ethernet/ti/cpsw.c
index 54c24cd3d3be..b0e18bdc2c85 100644
--- a/drivers/net/ethernet/ti/cpsw.c
+++ b/drivers/net/ethernet/ti/cpsw.c
@@ -305,12 +305,19 @@ static int cpsw_purge_all_mc(struct net_device *ndev, const u8 *addr, int num)
return 0;
}
-static void cpsw_ndo_set_rx_mode(struct net_device *ndev)
+static void cpsw_ndo_set_rx_mode_work(struct work_struct *work)
{
- struct cpsw_priv *priv = netdev_priv(ndev);
+ struct cpsw_priv *priv = container_of(work, struct cpsw_priv, rx_mode_work);
struct cpsw_common *cpsw = priv->cpsw;
+ struct net_device *ndev = priv->ndev;
int slave_port = -1;
+ rtnl_lock();
+ if (!netif_running(ndev))
+ goto unlock_rtnl;
+
+ netif_addr_lock_bh(ndev);
+
if (cpsw->data.dual_emac)
slave_port = priv->emac_port + 1;
@@ -318,7 +325,7 @@ static void cpsw_ndo_set_rx_mode(struct net_device *ndev)
/* Enable promiscuous mode */
cpsw_set_promiscious(ndev, true);
cpsw_ale_set_allmulti(cpsw->ale, IFF_ALLMULTI, slave_port);
- return;
+ goto unlock_addr;
} else {
/* Disable promiscuous mode */
cpsw_set_promiscious(ndev, false);
@@ -331,6 +338,18 @@ static void cpsw_ndo_set_rx_mode(struct net_device *ndev)
/* add/remove mcast address either for real netdev or for vlan */
__hw_addr_ref_sync_dev(&ndev->mc, ndev, cpsw_add_mc_addr,
cpsw_del_mc_addr);
+
+unlock_addr:
+ netif_addr_unlock_bh(ndev);
+unlock_rtnl:
+ rtnl_unlock();
+}
+
+static void cpsw_ndo_set_rx_mode(struct net_device *ndev)
+{
+ struct cpsw_priv *priv = netdev_priv(ndev);
+
+ schedule_work(&priv->rx_mode_work);
}
static unsigned int cpsw_rxbuf_total_len(unsigned int len)
@@ -1472,6 +1491,7 @@ static int cpsw_probe_dual_emac(struct cpsw_priv *priv)
priv_sl2->ndev = ndev;
priv_sl2->dev = &ndev->dev;
priv_sl2->msg_enable = netif_msg_init(debug_level, CPSW_DEBUG);
+ INIT_WORK(&priv_sl2->rx_mode_work, cpsw_ndo_set_rx_mode_work);
if (is_valid_ether_addr(data->slave_data[1].mac_addr)) {
memcpy(priv_sl2->mac_addr, data->slave_data[1].mac_addr,
@@ -1653,6 +1673,7 @@ static int cpsw_probe(struct platform_device *pdev)
priv->dev = dev;
priv->msg_enable = netif_msg_init(debug_level, CPSW_DEBUG);
priv->emac_port = 0;
+ INIT_WORK(&priv->rx_mode_work, cpsw_ndo_set_rx_mode_work);
if (is_valid_ether_addr(data->slave_data[0].mac_addr)) {
memcpy(priv->mac_addr, data->slave_data[0].mac_addr, ETH_ALEN);
@@ -1758,6 +1779,8 @@ clean_runtime_disable_ret:
static void cpsw_remove(struct platform_device *pdev)
{
struct cpsw_common *cpsw = platform_get_drvdata(pdev);
+ struct net_device *ndev;
+ struct cpsw_priv *priv;
int i, ret;
ret = pm_runtime_resume_and_get(&pdev->dev);
@@ -1770,9 +1793,15 @@ static void cpsw_remove(struct platform_device *pdev)
return;
}
- for (i = 0; i < cpsw->data.slaves; i++)
- if (cpsw->slaves[i].ndev)
- unregister_netdev(cpsw->slaves[i].ndev);
+ for (i = 0; i < cpsw->data.slaves; i++) {
+ ndev = cpsw->slaves[i].ndev;
+ if (!ndev)
+ continue;
+
+ priv = netdev_priv(ndev);
+ unregister_netdev(ndev);
+ disable_work_sync(&priv->rx_mode_work);
+ }
cpts_release(cpsw->cpts);
cpdma_ctlr_destroy(cpsw->dma);
diff --git a/drivers/net/ethernet/ti/cpsw_new.c b/drivers/net/ethernet/ti/cpsw_new.c
index ab88d4c02cbd..21af0a10626a 100644
--- a/drivers/net/ethernet/ti/cpsw_new.c
+++ b/drivers/net/ethernet/ti/cpsw_new.c
@@ -248,16 +248,22 @@ static int cpsw_purge_all_mc(struct net_device *ndev, const u8 *addr, int num)
return 0;
}
-static void cpsw_ndo_set_rx_mode(struct net_device *ndev)
+static void cpsw_ndo_set_rx_mode_work(struct work_struct *work)
{
- struct cpsw_priv *priv = netdev_priv(ndev);
+ struct cpsw_priv *priv = container_of(work, struct cpsw_priv, rx_mode_work);
struct cpsw_common *cpsw = priv->cpsw;
+ struct net_device *ndev = priv->ndev;
+ rtnl_lock();
+ if (!netif_running(ndev))
+ goto unlock_rtnl;
+
+ netif_addr_lock_bh(ndev);
if (ndev->flags & IFF_PROMISC) {
/* Enable promiscuous mode */
cpsw_set_promiscious(ndev, true);
cpsw_ale_set_allmulti(cpsw->ale, IFF_ALLMULTI, priv->emac_port);
- return;
+ goto unlock_addr;
}
/* Disable promiscuous mode */
@@ -270,6 +276,18 @@ static void cpsw_ndo_set_rx_mode(struct net_device *ndev)
/* add/remove mcast address either for real netdev or for vlan */
__hw_addr_ref_sync_dev(&ndev->mc, ndev, cpsw_add_mc_addr,
cpsw_del_mc_addr);
+
+unlock_addr:
+ netif_addr_unlock_bh(ndev);
+unlock_rtnl:
+ rtnl_unlock();
+}
+
+static void cpsw_ndo_set_rx_mode(struct net_device *ndev)
+{
+ struct cpsw_priv *priv = netdev_priv(ndev);
+
+ schedule_work(&priv->rx_mode_work);
}
static unsigned int cpsw_rxbuf_total_len(unsigned int len)
@@ -1398,6 +1416,7 @@ static int cpsw_create_ports(struct cpsw_common *cpsw)
priv->msg_enable = netif_msg_init(debug_level, CPSW_DEBUG);
priv->emac_port = i + 1;
priv->tx_packet_min = CPSW_MIN_PACKET_SIZE;
+ INIT_WORK(&priv->rx_mode_work, cpsw_ndo_set_rx_mode_work);
if (is_valid_ether_addr(slave_data->mac_addr)) {
ether_addr_copy(priv->mac_addr, slave_data->mac_addr);
@@ -1447,13 +1466,18 @@ static int cpsw_create_ports(struct cpsw_common *cpsw)
static void cpsw_unregister_ports(struct cpsw_common *cpsw)
{
+ struct net_device *ndev;
+ struct cpsw_priv *priv;
int i = 0;
for (i = 0; i < cpsw->data.slaves; i++) {
- if (!cpsw->slaves[i].ndev)
+ ndev = cpsw->slaves[i].ndev;
+ if (!ndev)
continue;
- unregister_netdev(cpsw->slaves[i].ndev);
+ priv = netdev_priv(ndev);
+ unregister_netdev(ndev);
+ disable_work_sync(&priv->rx_mode_work);
}
}
diff --git a/drivers/net/ethernet/ti/cpsw_priv.h b/drivers/net/ethernet/ti/cpsw_priv.h
index 91add8925e23..acb6181c5c9e 100644
--- a/drivers/net/ethernet/ti/cpsw_priv.h
+++ b/drivers/net/ethernet/ti/cpsw_priv.h
@@ -391,6 +391,7 @@ struct cpsw_priv {
u32 tx_packet_min;
struct cpsw_ale_ratelimit ale_bc_ratelimit;
struct cpsw_ale_ratelimit ale_mc_ratelimit;
+ struct work_struct rx_mode_work;
};
#define ndev_to_cpsw(ndev) (((struct cpsw_priv *)netdev_priv(ndev))->cpsw)
diff --git a/drivers/net/macvlan.c b/drivers/net/macvlan.c
index b4df7e184791..c509228be84d 100644
--- a/drivers/net/macvlan.c
+++ b/drivers/net/macvlan.c
@@ -1567,9 +1567,10 @@ destroy_macvlan_port:
/* the macvlan port may be freed by macvlan_uninit when fail to register.
* so we destroy the macvlan port only when it's valid.
*/
- if (create && macvlan_port_get_rtnl(lowerdev)) {
+ if (macvlan_port_get_rtnl(lowerdev)) {
macvlan_flush_sources(port, vlan);
- macvlan_port_destroy(port->dev);
+ if (create)
+ macvlan_port_destroy(port->dev);
}
return err;
}
diff --git a/drivers/net/phy/sfp.c b/drivers/net/phy/sfp.c
index 47f095bd91ce..3e023723887c 100644
--- a/drivers/net/phy/sfp.c
+++ b/drivers/net/phy/sfp.c
@@ -479,6 +479,8 @@ static void sfp_quirk_ubnt_uf_instant(const struct sfp_eeprom_id *id,
linkmode_zero(caps->link_modes);
linkmode_set_bit(ETHTOOL_LINK_MODE_1000baseX_Full_BIT,
caps->link_modes);
+ phy_interface_zero(caps->interfaces);
+ __set_bit(PHY_INTERFACE_MODE_1000BASEX, caps->interfaces);
}
#define SFP_QUIRK(_v, _p, _s, _f) \
diff --git a/drivers/net/usb/r8152.c b/drivers/net/usb/r8152.c
index fa5192583860..2f3baa5f6e9c 100644
--- a/drivers/net/usb/r8152.c
+++ b/drivers/net/usb/r8152.c
@@ -8535,19 +8535,6 @@ static int rtl8152_system_resume(struct r8152 *tp)
usb_submit_urb(tp->intr_urb, GFP_NOIO);
}
- /* If the device is RTL8152_INACCESSIBLE here then we should do a
- * reset. This is important because the usb_lock_device_for_reset()
- * that happens as a result of usb_queue_reset_device() will silently
- * fail if the device was suspended or if too much time passed.
- *
- * NOTE: The device is locked here so we can directly do the reset.
- * We don't need usb_lock_device_for_reset() because that's just a
- * wrapper over device_lock() and device_resume() (which calls us)
- * does that for us.
- */
- if (test_bit(RTL8152_INACCESSIBLE, &tp->flags))
- usb_reset_device(tp->udev);
-
return 0;
}
@@ -8658,19 +8645,33 @@ static int rtl8152_suspend(struct usb_interface *intf, pm_message_t message)
static int rtl8152_resume(struct usb_interface *intf)
{
struct r8152 *tp = usb_get_intfdata(intf);
+ bool runtime_resume = test_bit(SELECTIVE_SUSPEND, &tp->flags);
int ret;
mutex_lock(&tp->control);
rtl_reset_ocp_base(tp);
- if (test_bit(SELECTIVE_SUSPEND, &tp->flags))
+ if (runtime_resume)
ret = rtl8152_runtime_resume(tp);
else
ret = rtl8152_system_resume(tp);
mutex_unlock(&tp->control);
+ /* If the device is RTL8152_INACCESSIBLE here then we should do a
+ * reset. This is important because the usb_lock_device_for_reset()
+ * that happens as a result of usb_queue_reset_device() will silently
+ * fail if the device was suspended or if too much time passed.
+ *
+ * NOTE: The device is locked here so we can directly do the reset.
+ * We don't need usb_lock_device_for_reset() because that's just a
+ * wrapper over device_lock() and device_resume() (which calls us)
+ * does that for us.
+ */
+ if (!runtime_resume && test_bit(RTL8152_INACCESSIBLE, &tp->flags))
+ usb_reset_device(tp->udev);
+
return ret;
}
diff --git a/drivers/net/wireless/intel/iwlwifi/mld/iface.c b/drivers/net/wireless/intel/iwlwifi/mld/iface.c
index a5ececfc13e4..f15d1f5d1bf5 100644
--- a/drivers/net/wireless/intel/iwlwifi/mld/iface.c
+++ b/drivers/net/wireless/intel/iwlwifi/mld/iface.c
@@ -55,8 +55,6 @@ void iwl_mld_cleanup_vif(void *data, u8 *mac, struct ieee80211_vif *vif)
ieee80211_iter_keys(mld->hw, vif, iwl_mld_cleanup_keys_iter, NULL);
- wiphy_delayed_work_cancel(mld->wiphy, &mld_vif->mlo_scan_start_wk);
-
CLEANUP_STRUCT(mld_vif);
}
diff --git a/drivers/net/wireless/intel/iwlwifi/mld/mac80211.c b/drivers/net/wireless/intel/iwlwifi/mld/mac80211.c
index 55b484c16280..cd0dce8de856 100644
--- a/drivers/net/wireless/intel/iwlwifi/mld/mac80211.c
+++ b/drivers/net/wireless/intel/iwlwifi/mld/mac80211.c
@@ -1759,6 +1759,8 @@ static int iwl_mld_move_sta_state_down(struct iwl_mld *mld,
wiphy_work_cancel(mld->wiphy, &mld_vif->emlsr.unblock_tpt_wk);
wiphy_delayed_work_cancel(mld->wiphy,
&mld_vif->emlsr.check_tpt_wk);
+ wiphy_delayed_work_cancel(mld->wiphy,
+ &mld_vif->mlo_scan_start_wk);
iwl_mld_reset_cca_40mhz_workaround(mld, vif);
iwl_mld_smps_workaround(mld, vif, true);
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/d3.c b/drivers/net/wireless/intel/iwlwifi/mvm/d3.c
index 07f1a84c274e..af1a45845999 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/d3.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/d3.c
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
/*
- * Copyright (C) 2012-2014, 2018-2025 Intel Corporation
+ * Copyright (C) 2012-2014, 2018-2026 Intel Corporation
* Copyright (C) 2013-2015 Intel Mobile Communications GmbH
* Copyright (C) 2016-2017 Intel Deutschland GmbH
*/
@@ -3239,6 +3239,8 @@ void iwl_mvm_fast_suspend(struct iwl_mvm *mvm)
IWL_DEBUG_WOWLAN(mvm, "Starting fast suspend flow\n");
+ iwl_mvm_pause_tcm(mvm, true);
+
mvm->fast_resume = true;
set_bit(IWL_MVM_STATUS_IN_D3, &mvm->status);
@@ -3295,6 +3297,8 @@ int iwl_mvm_fast_resume(struct iwl_mvm *mvm)
mvm->trans->state = IWL_TRANS_NO_FW;
}
+ iwl_mvm_resume_tcm(mvm);
+
out:
clear_bit(IWL_MVM_STATUS_IN_D3, &mvm->status);
mvm->fast_resume = false;
diff --git a/drivers/nvme/host/pci.c b/drivers/nvme/host/pci.c
index c2bee32332fe..d86f2565a92c 100644
--- a/drivers/nvme/host/pci.c
+++ b/drivers/nvme/host/pci.c
@@ -816,6 +816,32 @@ static void nvme_unmap_data(struct request *req)
nvme_free_descriptors(req);
}
+static bool nvme_pci_prp_save_mapping(struct request *req,
+ struct device *dma_dev,
+ struct blk_dma_iter *iter)
+{
+ struct nvme_iod *iod = blk_mq_rq_to_pdu(req);
+
+ if (dma_use_iova(&iod->dma_state) || !dma_need_unmap(dma_dev))
+ return true;
+
+ if (!iod->nr_dma_vecs) {
+ struct nvme_queue *nvmeq = req->mq_hctx->driver_data;
+
+ iod->dma_vecs = mempool_alloc(nvmeq->dev->dmavec_mempool,
+ GFP_ATOMIC);
+ if (!iod->dma_vecs) {
+ iter->status = BLK_STS_RESOURCE;
+ return false;
+ }
+ }
+
+ iod->dma_vecs[iod->nr_dma_vecs].addr = iter->addr;
+ iod->dma_vecs[iod->nr_dma_vecs].len = iter->len;
+ iod->nr_dma_vecs++;
+ return true;
+}
+
static bool nvme_pci_prp_iter_next(struct request *req, struct device *dma_dev,
struct blk_dma_iter *iter)
{
@@ -825,12 +851,7 @@ static bool nvme_pci_prp_iter_next(struct request *req, struct device *dma_dev,
return true;
if (!blk_rq_dma_map_iter_next(req, dma_dev, &iod->dma_state, iter))
return false;
- if (!dma_use_iova(&iod->dma_state) && dma_need_unmap(dma_dev)) {
- iod->dma_vecs[iod->nr_dma_vecs].addr = iter->addr;
- iod->dma_vecs[iod->nr_dma_vecs].len = iter->len;
- iod->nr_dma_vecs++;
- }
- return true;
+ return nvme_pci_prp_save_mapping(req, dma_dev, iter);
}
static blk_status_t nvme_pci_setup_data_prp(struct request *req,
@@ -843,15 +864,8 @@ static blk_status_t nvme_pci_setup_data_prp(struct request *req,
unsigned int prp_len, i;
__le64 *prp_list;
- if (!dma_use_iova(&iod->dma_state) && dma_need_unmap(nvmeq->dev->dev)) {
- iod->dma_vecs = mempool_alloc(nvmeq->dev->dmavec_mempool,
- GFP_ATOMIC);
- if (!iod->dma_vecs)
- return BLK_STS_RESOURCE;
- iod->dma_vecs[0].addr = iter->addr;
- iod->dma_vecs[0].len = iter->len;
- iod->nr_dma_vecs = 1;
- }
+ if (!nvme_pci_prp_save_mapping(req, nvmeq->dev->dev, iter))
+ return iter->status;
/*
* PRP1 always points to the start of the DMA transfers.
@@ -1219,6 +1233,7 @@ static blk_status_t nvme_prep_rq(struct request *req)
iod->nr_descriptors = 0;
iod->total_len = 0;
iod->meta_total_len = 0;
+ iod->nr_dma_vecs = 0;
ret = nvme_setup_cmd(req->q->queuedata, req);
if (ret)
diff --git a/drivers/nvme/target/tcp.c b/drivers/nvme/target/tcp.c
index 549a4786d1c3..bda816d66846 100644
--- a/drivers/nvme/target/tcp.c
+++ b/drivers/nvme/target/tcp.c
@@ -349,11 +349,14 @@ static void nvmet_tcp_free_cmd_buffers(struct nvmet_tcp_cmd *cmd)
cmd->req.sg = NULL;
}
+static void nvmet_tcp_fatal_error(struct nvmet_tcp_queue *queue);
+
static void nvmet_tcp_build_pdu_iovec(struct nvmet_tcp_cmd *cmd)
{
struct bio_vec *iov = cmd->iov;
struct scatterlist *sg;
u32 length, offset, sg_offset;
+ unsigned int sg_remaining;
int nr_pages;
length = cmd->pdu_len;
@@ -361,9 +364,22 @@ static void nvmet_tcp_build_pdu_iovec(struct nvmet_tcp_cmd *cmd)
offset = cmd->rbytes_done;
cmd->sg_idx = offset / PAGE_SIZE;
sg_offset = offset % PAGE_SIZE;
+ if (!cmd->req.sg_cnt || cmd->sg_idx >= cmd->req.sg_cnt) {
+ nvmet_tcp_fatal_error(cmd->queue);
+ return;
+ }
sg = &cmd->req.sg[cmd->sg_idx];
+ sg_remaining = cmd->req.sg_cnt - cmd->sg_idx;
while (length) {
+ if (!sg_remaining) {
+ nvmet_tcp_fatal_error(cmd->queue);
+ return;
+ }
+ if (!sg->length || sg->length <= sg_offset) {
+ nvmet_tcp_fatal_error(cmd->queue);
+ return;
+ }
u32 iov_len = min_t(u32, length, sg->length - sg_offset);
bvec_set_page(iov, sg_page(sg), iov_len,
@@ -371,6 +387,7 @@ static void nvmet_tcp_build_pdu_iovec(struct nvmet_tcp_cmd *cmd)
length -= iov_len;
sg = sg_next(sg);
+ sg_remaining--;
iov++;
sg_offset = 0;
}
diff --git a/drivers/pci/ide.c b/drivers/pci/ide.c
index f0ef474e1a0d..23f554490539 100644
--- a/drivers/pci/ide.c
+++ b/drivers/pci/ide.c
@@ -11,7 +11,6 @@
#include <linux/pci_regs.h>
#include <linux/slab.h>
#include <linux/sysfs.h>
-#include <linux/tsm.h>
#include "pci.h"
@@ -168,7 +167,7 @@ void pci_ide_init(struct pci_dev *pdev)
for (u16 i = 0; i < nr_streams; i++) {
int pos = __sel_ide_offset(ide_cap, nr_link_ide, i, nr_ide_mem);
- pci_read_config_dword(pdev, pos + PCI_IDE_SEL_CAP, &val);
+ pci_read_config_dword(pdev, pos + PCI_IDE_SEL_CTL, &val);
if (val & PCI_IDE_SEL_CTL_EN)
continue;
val &= ~PCI_IDE_SEL_CTL_ID;
@@ -283,8 +282,8 @@ struct pci_ide *pci_ide_stream_alloc(struct pci_dev *pdev)
/* for SR-IOV case, cover all VFs */
num_vf = pci_num_vf(pdev);
if (num_vf)
- rid_end = PCI_DEVID(pci_iov_virtfn_bus(pdev, num_vf),
- pci_iov_virtfn_devfn(pdev, num_vf));
+ rid_end = PCI_DEVID(pci_iov_virtfn_bus(pdev, num_vf - 1),
+ pci_iov_virtfn_devfn(pdev, num_vf - 1));
else
rid_end = pci_dev_id(pdev);
@@ -373,9 +372,6 @@ void pci_ide_stream_release(struct pci_ide *ide)
if (ide->partner[PCI_IDE_EP].enable)
pci_ide_stream_disable(pdev, ide);
- if (ide->tsm_dev)
- tsm_ide_stream_unregister(ide);
-
if (ide->partner[PCI_IDE_RP].setup)
pci_ide_stream_teardown(rp, ide);
diff --git a/drivers/platform/x86/amd/pmc/pmc-quirks.c b/drivers/platform/x86/amd/pmc/pmc-quirks.c
index 404e62ad293a..ed285afaf9b0 100644
--- a/drivers/platform/x86/amd/pmc/pmc-quirks.c
+++ b/drivers/platform/x86/amd/pmc/pmc-quirks.c
@@ -302,6 +302,13 @@ static const struct dmi_system_id fwbug_list[] = {
DMI_MATCH(DMI_BOARD_NAME, "XxKK4NAx_XxSP4NAx"),
}
},
+ {
+ .ident = "MECHREVO Wujie 15X Pro",
+ .driver_data = &quirk_spurious_8042,
+ .matches = {
+ DMI_MATCH(DMI_BOARD_NAME, "WUJIE Series-X5SP4NAG"),
+ }
+ },
{}
};
diff --git a/drivers/platform/x86/classmate-laptop.c b/drivers/platform/x86/classmate-laptop.c
index 6b1b8e444e24..74d3eb83f56a 100644
--- a/drivers/platform/x86/classmate-laptop.c
+++ b/drivers/platform/x86/classmate-laptop.c
@@ -207,7 +207,12 @@ static ssize_t cmpc_accel_sensitivity_show_v4(struct device *dev,
acpi = to_acpi_device(dev);
inputdev = dev_get_drvdata(&acpi->dev);
+ if (!inputdev)
+ return -ENXIO;
+
accel = dev_get_drvdata(&inputdev->dev);
+ if (!accel)
+ return -ENXIO;
return sysfs_emit(buf, "%d\n", accel->sensitivity);
}
@@ -224,7 +229,12 @@ static ssize_t cmpc_accel_sensitivity_store_v4(struct device *dev,
acpi = to_acpi_device(dev);
inputdev = dev_get_drvdata(&acpi->dev);
+ if (!inputdev)
+ return -ENXIO;
+
accel = dev_get_drvdata(&inputdev->dev);
+ if (!accel)
+ return -ENXIO;
r = kstrtoul(buf, 0, &sensitivity);
if (r)
@@ -256,7 +266,12 @@ static ssize_t cmpc_accel_g_select_show_v4(struct device *dev,
acpi = to_acpi_device(dev);
inputdev = dev_get_drvdata(&acpi->dev);
+ if (!inputdev)
+ return -ENXIO;
+
accel = dev_get_drvdata(&inputdev->dev);
+ if (!accel)
+ return -ENXIO;
return sysfs_emit(buf, "%d\n", accel->g_select);
}
@@ -273,7 +288,12 @@ static ssize_t cmpc_accel_g_select_store_v4(struct device *dev,
acpi = to_acpi_device(dev);
inputdev = dev_get_drvdata(&acpi->dev);
+ if (!inputdev)
+ return -ENXIO;
+
accel = dev_get_drvdata(&inputdev->dev);
+ if (!accel)
+ return -ENXIO;
r = kstrtoul(buf, 0, &g_select);
if (r)
@@ -302,6 +322,8 @@ static int cmpc_accel_open_v4(struct input_dev *input)
acpi = to_acpi_device(input->dev.parent);
accel = dev_get_drvdata(&input->dev);
+ if (!accel)
+ return -ENXIO;
cmpc_accel_set_sensitivity_v4(acpi->handle, accel->sensitivity);
cmpc_accel_set_g_select_v4(acpi->handle, accel->g_select);
@@ -549,7 +571,12 @@ static ssize_t cmpc_accel_sensitivity_show(struct device *dev,
acpi = to_acpi_device(dev);
inputdev = dev_get_drvdata(&acpi->dev);
+ if (!inputdev)
+ return -ENXIO;
+
accel = dev_get_drvdata(&inputdev->dev);
+ if (!accel)
+ return -ENXIO;
return sysfs_emit(buf, "%d\n", accel->sensitivity);
}
@@ -566,7 +593,12 @@ static ssize_t cmpc_accel_sensitivity_store(struct device *dev,
acpi = to_acpi_device(dev);
inputdev = dev_get_drvdata(&acpi->dev);
+ if (!inputdev)
+ return -ENXIO;
+
accel = dev_get_drvdata(&inputdev->dev);
+ if (!accel)
+ return -ENXIO;
r = kstrtoul(buf, 0, &sensitivity);
if (r)
diff --git a/drivers/platform/x86/hp/hp-bioscfg/bioscfg.c b/drivers/platform/x86/hp/hp-bioscfg/bioscfg.c
index dbe096eefa75..51e8977d3eb4 100644
--- a/drivers/platform/x86/hp/hp-bioscfg/bioscfg.c
+++ b/drivers/platform/x86/hp/hp-bioscfg/bioscfg.c
@@ -696,6 +696,11 @@ static int hp_init_bios_package_attribute(enum hp_wmi_data_type attr_type,
return ret;
}
+ if (!str_value || !str_value[0]) {
+ pr_debug("Ignoring attribute with empty name\n");
+ goto pack_attr_exit;
+ }
+
/* All duplicate attributes found are ignored */
duplicate = kset_find_obj(temp_kset, str_value);
if (duplicate) {
diff --git a/drivers/platform/x86/intel/plr_tpmi.c b/drivers/platform/x86/intel/plr_tpmi.c
index 58132da47745..05727169f49c 100644
--- a/drivers/platform/x86/intel/plr_tpmi.c
+++ b/drivers/platform/x86/intel/plr_tpmi.c
@@ -316,7 +316,7 @@ static int intel_plr_probe(struct auxiliary_device *auxdev, const struct auxilia
snprintf(name, sizeof(name), "domain%d", i);
dentry = debugfs_create_dir(name, plr->dbgfs_dir);
- debugfs_create_file("status", 0444, dentry, &plr->die_info[i],
+ debugfs_create_file("status", 0644, dentry, &plr->die_info[i],
&plr_status_fops);
}
diff --git a/drivers/platform/x86/intel/telemetry/debugfs.c b/drivers/platform/x86/intel/telemetry/debugfs.c
index 70e5736c44c7..189c61ff7ff0 100644
--- a/drivers/platform/x86/intel/telemetry/debugfs.c
+++ b/drivers/platform/x86/intel/telemetry/debugfs.c
@@ -449,7 +449,7 @@ static int telem_pss_states_show(struct seq_file *s, void *unused)
for (index = 0; index < debugfs_conf->pss_ltr_evts; index++) {
seq_printf(s, "%-32s\t%u\n",
debugfs_conf->pss_ltr_data[index].name,
- pss_s0ix_wakeup[index]);
+ pss_ltr_blkd[index]);
}
seq_puts(s, "\n--------------------------------------\n");
@@ -459,7 +459,7 @@ static int telem_pss_states_show(struct seq_file *s, void *unused)
for (index = 0; index < debugfs_conf->pss_wakeup_evts; index++) {
seq_printf(s, "%-32s\t%u\n",
debugfs_conf->pss_wakeup[index].name,
- pss_ltr_blkd[index]);
+ pss_s0ix_wakeup[index]);
}
return 0;
diff --git a/drivers/platform/x86/intel/telemetry/pltdrv.c b/drivers/platform/x86/intel/telemetry/pltdrv.c
index f23c170a55dc..d9aa349f81e4 100644
--- a/drivers/platform/x86/intel/telemetry/pltdrv.c
+++ b/drivers/platform/x86/intel/telemetry/pltdrv.c
@@ -610,7 +610,7 @@ static int telemetry_setup(struct platform_device *pdev)
/* Get telemetry Info */
events = (read_buf & TELEM_INFO_SRAMEVTS_MASK) >>
TELEM_INFO_SRAMEVTS_SHIFT;
- event_regs = read_buf & TELEM_INFO_SRAMEVTS_MASK;
+ event_regs = read_buf & TELEM_INFO_NENABLES_MASK;
if ((events < TELEM_MAX_EVENTS_SRAM) ||
(event_regs < TELEM_MAX_EVENTS_SRAM)) {
dev_err(&pdev->dev, "PSS:Insufficient Space for SRAM Trace\n");
diff --git a/drivers/platform/x86/intel/vsec.c b/drivers/platform/x86/intel/vsec.c
index ecfc7703f201..012d87878afd 100644
--- a/drivers/platform/x86/intel/vsec.c
+++ b/drivers/platform/x86/intel/vsec.c
@@ -766,6 +766,7 @@ static const struct intel_vsec_platform_info lnl_info = {
#define PCI_DEVICE_ID_INTEL_VSEC_LNL_M 0x647d
#define PCI_DEVICE_ID_INTEL_VSEC_PTL 0xb07d
#define PCI_DEVICE_ID_INTEL_VSEC_WCL 0xfd7d
+#define PCI_DEVICE_ID_INTEL_VSEC_NVL 0xd70d
static const struct pci_device_id intel_vsec_pci_ids[] = {
{ PCI_DEVICE_DATA(INTEL, VSEC_ADL, &tgl_info) },
{ PCI_DEVICE_DATA(INTEL, VSEC_DG1, &dg1_info) },
@@ -778,6 +779,7 @@ static const struct pci_device_id intel_vsec_pci_ids[] = {
{ PCI_DEVICE_DATA(INTEL, VSEC_LNL_M, &lnl_info) },
{ PCI_DEVICE_DATA(INTEL, VSEC_PTL, &mtl_info) },
{ PCI_DEVICE_DATA(INTEL, VSEC_WCL, &mtl_info) },
+ { PCI_DEVICE_DATA(INTEL, VSEC_NVL, &mtl_info) },
{ }
};
MODULE_DEVICE_TABLE(pci, intel_vsec_pci_ids);
diff --git a/drivers/platform/x86/lg-laptop.c b/drivers/platform/x86/lg-laptop.c
index f92e89c75db9..61ef7a218a80 100644
--- a/drivers/platform/x86/lg-laptop.c
+++ b/drivers/platform/x86/lg-laptop.c
@@ -838,8 +838,17 @@ static int acpi_add(struct acpi_device *device)
case 'P':
year = 2021;
break;
- default:
+ case 'Q':
year = 2022;
+ break;
+ case 'R':
+ year = 2023;
+ break;
+ case 'S':
+ year = 2024;
+ break;
+ default:
+ year = 2025;
}
break;
default:
diff --git a/drivers/platform/x86/panasonic-laptop.c b/drivers/platform/x86/panasonic-laptop.c
index 255317e6fec8..937f1a5b78ed 100644
--- a/drivers/platform/x86/panasonic-laptop.c
+++ b/drivers/platform/x86/panasonic-laptop.c
@@ -1089,7 +1089,7 @@ static int acpi_pcc_hotkey_add(struct acpi_device *device)
PLATFORM_DEVID_NONE, NULL, 0);
if (IS_ERR(pcc->platform)) {
result = PTR_ERR(pcc->platform);
- goto out_backlight;
+ goto out_sysfs;
}
result = device_create_file(&pcc->platform->dev,
&dev_attr_cdpower);
@@ -1105,6 +1105,8 @@ static int acpi_pcc_hotkey_add(struct acpi_device *device)
out_platform:
platform_device_unregister(pcc->platform);
+out_sysfs:
+ sysfs_remove_group(&device->dev.kobj, &pcc_attr_group);
out_backlight:
backlight_device_unregister(pcc->backlight);
out_input:
diff --git a/drivers/platform/x86/toshiba_haps.c b/drivers/platform/x86/toshiba_haps.c
index 03dfddeee0c0..e9324bf16aea 100644
--- a/drivers/platform/x86/toshiba_haps.c
+++ b/drivers/platform/x86/toshiba_haps.c
@@ -183,7 +183,7 @@ static int toshiba_haps_add(struct acpi_device *acpi_dev)
pr_info("Toshiba HDD Active Protection Sensor device\n");
- haps = kzalloc(sizeof(struct toshiba_haps_dev), GFP_KERNEL);
+ haps = devm_kzalloc(&acpi_dev->dev, sizeof(*haps), GFP_KERNEL);
if (!haps)
return -ENOMEM;
diff --git a/drivers/pmdomain/imx/gpcv2.c b/drivers/pmdomain/imx/gpcv2.c
index 105fcaf13a34..cff738e4d546 100644
--- a/drivers/pmdomain/imx/gpcv2.c
+++ b/drivers/pmdomain/imx/gpcv2.c
@@ -165,13 +165,11 @@
#define IMX8M_VPU_HSK_PWRDNREQN BIT(5)
#define IMX8M_DISP_HSK_PWRDNREQN BIT(4)
-#define IMX8MM_GPUMIX_HSK_PWRDNACKN BIT(29)
-#define IMX8MM_GPU_HSK_PWRDNACKN (BIT(27) | BIT(28))
+#define IMX8MM_GPU_HSK_PWRDNACKN GENMASK(29, 27)
#define IMX8MM_VPUMIX_HSK_PWRDNACKN BIT(26)
#define IMX8MM_DISPMIX_HSK_PWRDNACKN BIT(25)
#define IMX8MM_HSIO_HSK_PWRDNACKN (BIT(23) | BIT(24))
-#define IMX8MM_GPUMIX_HSK_PWRDNREQN BIT(11)
-#define IMX8MM_GPU_HSK_PWRDNREQN (BIT(9) | BIT(10))
+#define IMX8MM_GPU_HSK_PWRDNREQN GENMASK(11, 9)
#define IMX8MM_VPUMIX_HSK_PWRDNREQN BIT(8)
#define IMX8MM_DISPMIX_HSK_PWRDNREQN BIT(7)
#define IMX8MM_HSIO_HSK_PWRDNREQN (BIT(5) | BIT(6))
@@ -794,8 +792,6 @@ static const struct imx_pgc_domain imx8mm_pgc_domains[] = {
.bits = {
.pxx = IMX8MM_GPUMIX_SW_Pxx_REQ,
.map = IMX8MM_GPUMIX_A53_DOMAIN,
- .hskreq = IMX8MM_GPUMIX_HSK_PWRDNREQN,
- .hskack = IMX8MM_GPUMIX_HSK_PWRDNACKN,
},
.pgc = BIT(IMX8MM_PGC_GPUMIX),
.keep_clocks = true,
diff --git a/drivers/pmdomain/imx/imx8m-blk-ctrl.c b/drivers/pmdomain/imx/imx8m-blk-ctrl.c
index 74bf4936991d..19e992d2ee3b 100644
--- a/drivers/pmdomain/imx/imx8m-blk-ctrl.c
+++ b/drivers/pmdomain/imx/imx8m-blk-ctrl.c
@@ -340,7 +340,7 @@ static void imx8m_blk_ctrl_remove(struct platform_device *pdev)
of_genpd_del_provider(pdev->dev.of_node);
- for (i = 0; bc->onecell_data.num_domains; i++) {
+ for (i = 0; i < bc->onecell_data.num_domains; i++) {
struct imx8m_blk_ctrl_domain *domain = &bc->domains[i];
pm_genpd_remove(&domain->genpd);
diff --git a/drivers/pmdomain/imx/imx8mp-blk-ctrl.c b/drivers/pmdomain/imx/imx8mp-blk-ctrl.c
index 34576be606e3..8fc79f9723f0 100644
--- a/drivers/pmdomain/imx/imx8mp-blk-ctrl.c
+++ b/drivers/pmdomain/imx/imx8mp-blk-ctrl.c
@@ -53,6 +53,7 @@ struct imx8mp_blk_ctrl_domain_data {
const char * const *path_names;
int num_paths;
const char *gpc_name;
+ const unsigned int flags;
};
#define DOMAIN_MAX_CLKS 3
@@ -65,6 +66,7 @@ struct imx8mp_blk_ctrl_domain {
struct icc_bulk_data paths[DOMAIN_MAX_PATHS];
struct device *power_dev;
struct imx8mp_blk_ctrl *bc;
+ struct notifier_block power_nb;
int num_paths;
int id;
};
@@ -264,10 +266,12 @@ static const struct imx8mp_blk_ctrl_domain_data imx8mp_hsio_domain_data[] = {
[IMX8MP_HSIOBLK_PD_USB_PHY1] = {
.name = "hsioblk-usb-phy1",
.gpc_name = "usb-phy1",
+ .flags = GENPD_FLAG_ACTIVE_WAKEUP,
},
[IMX8MP_HSIOBLK_PD_USB_PHY2] = {
.name = "hsioblk-usb-phy2",
.gpc_name = "usb-phy2",
+ .flags = GENPD_FLAG_ACTIVE_WAKEUP,
},
[IMX8MP_HSIOBLK_PD_PCIE] = {
.name = "hsioblk-pcie",
@@ -594,6 +598,20 @@ static int imx8mp_blk_ctrl_power_off(struct generic_pm_domain *genpd)
return 0;
}
+static int imx8mp_blk_ctrl_gpc_notifier(struct notifier_block *nb,
+ unsigned long action, void *data)
+{
+ struct imx8mp_blk_ctrl_domain *domain =
+ container_of(nb, struct imx8mp_blk_ctrl_domain, power_nb);
+
+ if (action == GENPD_NOTIFY_PRE_OFF) {
+ if (domain->genpd.status == GENPD_STATE_ON)
+ return NOTIFY_BAD;
+ }
+
+ return NOTIFY_OK;
+}
+
static struct lock_class_key blk_ctrl_genpd_lock_class;
static int imx8mp_blk_ctrl_probe(struct platform_device *pdev)
@@ -698,15 +716,25 @@ static int imx8mp_blk_ctrl_probe(struct platform_device *pdev)
goto cleanup_pds;
}
+ domain->power_nb.notifier_call = imx8mp_blk_ctrl_gpc_notifier;
+ ret = dev_pm_genpd_add_notifier(domain->power_dev, &domain->power_nb);
+ if (ret) {
+ dev_err_probe(dev, ret, "failed to add power notifier\n");
+ dev_pm_domain_detach(domain->power_dev, true);
+ goto cleanup_pds;
+ }
+
domain->genpd.name = data->name;
domain->genpd.power_on = imx8mp_blk_ctrl_power_on;
domain->genpd.power_off = imx8mp_blk_ctrl_power_off;
+ domain->genpd.flags = data->flags;
domain->bc = bc;
domain->id = i;
ret = pm_genpd_init(&domain->genpd, NULL, true);
if (ret) {
dev_err_probe(dev, ret, "failed to init power domain\n");
+ dev_pm_genpd_remove_notifier(domain->power_dev);
dev_pm_domain_detach(domain->power_dev, true);
goto cleanup_pds;
}
@@ -755,6 +783,7 @@ cleanup_provider:
cleanup_pds:
for (i--; i >= 0; i--) {
pm_genpd_remove(&bc->domains[i].genpd);
+ dev_pm_genpd_remove_notifier(bc->domains[i].power_dev);
dev_pm_domain_detach(bc->domains[i].power_dev, true);
}
@@ -774,6 +803,7 @@ static void imx8mp_blk_ctrl_remove(struct platform_device *pdev)
struct imx8mp_blk_ctrl_domain *domain = &bc->domains[i];
pm_genpd_remove(&domain->genpd);
+ dev_pm_genpd_remove_notifier(domain->power_dev);
dev_pm_domain_detach(domain->power_dev, true);
}
diff --git a/drivers/pmdomain/qcom/rpmpd.c b/drivers/pmdomain/qcom/rpmpd.c
index f8580ec0f737..98ab4f9ea9bf 100644
--- a/drivers/pmdomain/qcom/rpmpd.c
+++ b/drivers/pmdomain/qcom/rpmpd.c
@@ -1001,7 +1001,7 @@ static int rpmpd_aggregate_corner(struct rpmpd *pd)
/* Clamp to the highest corner/level if sync_state isn't done yet */
if (!pd->state_synced)
- this_active_corner = this_sleep_corner = pd->max_state - 1;
+ this_active_corner = this_sleep_corner = pd->max_state;
else
to_active_sleep(pd, pd->corner, &this_active_corner, &this_sleep_corner);
diff --git a/drivers/soc/qcom/smem.c b/drivers/soc/qcom/smem.c
index fef840b54574..c18a0c946f76 100644
--- a/drivers/soc/qcom/smem.c
+++ b/drivers/soc/qcom/smem.c
@@ -396,7 +396,7 @@ EXPORT_SYMBOL_GPL(qcom_smem_bust_hwspin_lock_by_host);
*/
bool qcom_smem_is_available(void)
{
- return !!__smem;
+ return !IS_ERR(__smem);
}
EXPORT_SYMBOL_GPL(qcom_smem_is_available);
@@ -1247,7 +1247,8 @@ static void qcom_smem_remove(struct platform_device *pdev)
{
platform_device_unregister(__smem->socinfo);
- __smem = NULL;
+ /* Set to -EPROBE_DEFER to signal unprobed state */
+ __smem = ERR_PTR(-EPROBE_DEFER);
}
static const struct of_device_id qcom_smem_of_match[] = {
diff --git a/drivers/usb/gadget/function/f_fs.c b/drivers/usb/gadget/function/f_fs.c
index 05c6750702b6..fa467a40949d 100644
--- a/drivers/usb/gadget/function/f_fs.c
+++ b/drivers/usb/gadget/function/f_fs.c
@@ -59,7 +59,6 @@ static struct ffs_data *__must_check ffs_data_new(const char *dev_name)
__attribute__((malloc));
/* Opened counter handling. */
-static void ffs_data_opened(struct ffs_data *ffs);
static void ffs_data_closed(struct ffs_data *ffs);
/* Called with ffs->mutex held; take over ownership of data. */
@@ -636,23 +635,25 @@ done_mutex:
return ret;
}
+
+static void ffs_data_reset(struct ffs_data *ffs);
+
static int ffs_ep0_open(struct inode *inode, struct file *file)
{
struct ffs_data *ffs = inode->i_sb->s_fs_info;
- int ret;
- /* Acquire mutex */
- ret = ffs_mutex_lock(&ffs->mutex, file->f_flags & O_NONBLOCK);
- if (ret < 0)
- return ret;
-
- ffs_data_opened(ffs);
+ spin_lock_irq(&ffs->eps_lock);
if (ffs->state == FFS_CLOSING) {
- ffs_data_closed(ffs);
- mutex_unlock(&ffs->mutex);
+ spin_unlock_irq(&ffs->eps_lock);
return -EBUSY;
}
- mutex_unlock(&ffs->mutex);
+ if (!ffs->opened++ && ffs->state == FFS_DEACTIVATED) {
+ ffs->state = FFS_CLOSING;
+ spin_unlock_irq(&ffs->eps_lock);
+ ffs_data_reset(ffs);
+ } else {
+ spin_unlock_irq(&ffs->eps_lock);
+ }
file->private_data = ffs;
return stream_open(inode, file);
@@ -1202,15 +1203,10 @@ ffs_epfile_open(struct inode *inode, struct file *file)
{
struct ffs_data *ffs = inode->i_sb->s_fs_info;
struct ffs_epfile *epfile;
- int ret;
-
- /* Acquire mutex */
- ret = ffs_mutex_lock(&ffs->mutex, file->f_flags & O_NONBLOCK);
- if (ret < 0)
- return ret;
- if (!atomic_inc_not_zero(&ffs->opened)) {
- mutex_unlock(&ffs->mutex);
+ spin_lock_irq(&ffs->eps_lock);
+ if (!ffs->opened) {
+ spin_unlock_irq(&ffs->eps_lock);
return -ENODEV;
}
/*
@@ -1220,11 +1216,11 @@ ffs_epfile_open(struct inode *inode, struct file *file)
*/
epfile = smp_load_acquire(&inode->i_private);
if (unlikely(ffs->state != FFS_ACTIVE || !epfile)) {
- mutex_unlock(&ffs->mutex);
- ffs_data_closed(ffs);
+ spin_unlock_irq(&ffs->eps_lock);
return -ENODEV;
}
- mutex_unlock(&ffs->mutex);
+ ffs->opened++;
+ spin_unlock_irq(&ffs->eps_lock);
file->private_data = epfile;
return stream_open(inode, file);
@@ -2092,8 +2088,6 @@ static int ffs_fs_init_fs_context(struct fs_context *fc)
return 0;
}
-static void ffs_data_reset(struct ffs_data *ffs);
-
static void
ffs_fs_kill_sb(struct super_block *sb)
{
@@ -2150,15 +2144,6 @@ static void ffs_data_get(struct ffs_data *ffs)
refcount_inc(&ffs->ref);
}
-static void ffs_data_opened(struct ffs_data *ffs)
-{
- if (atomic_add_return(1, &ffs->opened) == 1 &&
- ffs->state == FFS_DEACTIVATED) {
- ffs->state = FFS_CLOSING;
- ffs_data_reset(ffs);
- }
-}
-
static void ffs_data_put(struct ffs_data *ffs)
{
if (refcount_dec_and_test(&ffs->ref)) {
@@ -2176,28 +2161,29 @@ static void ffs_data_put(struct ffs_data *ffs)
static void ffs_data_closed(struct ffs_data *ffs)
{
- if (atomic_dec_and_test(&ffs->opened)) {
- if (ffs->no_disconnect) {
- struct ffs_epfile *epfiles;
- unsigned long flags;
-
- ffs->state = FFS_DEACTIVATED;
- spin_lock_irqsave(&ffs->eps_lock, flags);
- epfiles = ffs->epfiles;
- ffs->epfiles = NULL;
- spin_unlock_irqrestore(&ffs->eps_lock,
- flags);
-
- if (epfiles)
- ffs_epfiles_destroy(ffs->sb, epfiles,
- ffs->eps_count);
-
- if (ffs->setup_state == FFS_SETUP_PENDING)
- __ffs_ep0_stall(ffs);
- } else {
- ffs->state = FFS_CLOSING;
- ffs_data_reset(ffs);
- }
+ spin_lock_irq(&ffs->eps_lock);
+ if (--ffs->opened) { // not the last opener?
+ spin_unlock_irq(&ffs->eps_lock);
+ return;
+ }
+ if (ffs->no_disconnect) {
+ struct ffs_epfile *epfiles;
+
+ ffs->state = FFS_DEACTIVATED;
+ epfiles = ffs->epfiles;
+ ffs->epfiles = NULL;
+ spin_unlock_irq(&ffs->eps_lock);
+
+ if (epfiles)
+ ffs_epfiles_destroy(ffs->sb, epfiles,
+ ffs->eps_count);
+
+ if (ffs->setup_state == FFS_SETUP_PENDING)
+ __ffs_ep0_stall(ffs);
+ } else {
+ ffs->state = FFS_CLOSING;
+ spin_unlock_irq(&ffs->eps_lock);
+ ffs_data_reset(ffs);
}
}
@@ -2214,7 +2200,7 @@ static struct ffs_data *ffs_data_new(const char *dev_name)
}
refcount_set(&ffs->ref, 1);
- atomic_set(&ffs->opened, 0);
+ ffs->opened = 0;
ffs->state = FFS_READ_DESCRIPTORS;
mutex_init(&ffs->mutex);
spin_lock_init(&ffs->eps_lock);
@@ -2266,6 +2252,7 @@ static void ffs_data_reset(struct ffs_data *ffs)
{
ffs_data_clear(ffs);
+ spin_lock_irq(&ffs->eps_lock);
ffs->raw_descs_data = NULL;
ffs->raw_descs = NULL;
ffs->raw_strings = NULL;
@@ -2289,6 +2276,7 @@ static void ffs_data_reset(struct ffs_data *ffs)
ffs->ms_os_descs_ext_prop_count = 0;
ffs->ms_os_descs_ext_prop_name_len = 0;
ffs->ms_os_descs_ext_prop_data_len = 0;
+ spin_unlock_irq(&ffs->eps_lock);
}
@@ -3756,6 +3744,7 @@ static int ffs_func_set_alt(struct usb_function *f,
{
struct ffs_function *func = ffs_func_from_usb(f);
struct ffs_data *ffs = func->ffs;
+ unsigned long flags;
int ret = 0, intf;
if (alt > MAX_ALT_SETTINGS)
@@ -3768,12 +3757,15 @@ static int ffs_func_set_alt(struct usb_function *f,
if (ffs->func)
ffs_func_eps_disable(ffs->func);
+ spin_lock_irqsave(&ffs->eps_lock, flags);
if (ffs->state == FFS_DEACTIVATED) {
ffs->state = FFS_CLOSING;
+ spin_unlock_irqrestore(&ffs->eps_lock, flags);
INIT_WORK(&ffs->reset_work, ffs_reset_work);
schedule_work(&ffs->reset_work);
return -ENODEV;
}
+ spin_unlock_irqrestore(&ffs->eps_lock, flags);
if (ffs->state != FFS_ACTIVE)
return -ENODEV;
@@ -3791,16 +3783,20 @@ static void ffs_func_disable(struct usb_function *f)
{
struct ffs_function *func = ffs_func_from_usb(f);
struct ffs_data *ffs = func->ffs;
+ unsigned long flags;
if (ffs->func)
ffs_func_eps_disable(ffs->func);
+ spin_lock_irqsave(&ffs->eps_lock, flags);
if (ffs->state == FFS_DEACTIVATED) {
ffs->state = FFS_CLOSING;
+ spin_unlock_irqrestore(&ffs->eps_lock, flags);
INIT_WORK(&ffs->reset_work, ffs_reset_work);
schedule_work(&ffs->reset_work);
return;
}
+ spin_unlock_irqrestore(&ffs->eps_lock, flags);
if (ffs->state == FFS_ACTIVE) {
ffs->func = NULL;
diff --git a/drivers/usb/gadget/function/u_fs.h b/drivers/usb/gadget/function/u_fs.h
index 4b3365f23fd7..6a80182aadd7 100644
--- a/drivers/usb/gadget/function/u_fs.h
+++ b/drivers/usb/gadget/function/u_fs.h
@@ -176,7 +176,7 @@ struct ffs_data {
/* reference counter */
refcount_t ref;
/* how many files are opened (EP0 and others) */
- atomic_t opened;
+ int opened;
/* EP0 state */
enum ffs_state state;
diff --git a/drivers/virt/coco/tsm-core.c b/drivers/virt/coco/tsm-core.c
index f027876a2f19..8712df8596a1 100644
--- a/drivers/virt/coco/tsm-core.c
+++ b/drivers/virt/coco/tsm-core.c
@@ -4,16 +4,12 @@
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#include <linux/tsm.h>
-#include <linux/pci.h>
-#include <linux/rwsem.h>
#include <linux/device.h>
#include <linux/module.h>
#include <linux/cleanup.h>
#include <linux/pci-tsm.h>
-#include <linux/pci-ide.h>
static struct class *tsm_class;
-static DECLARE_RWSEM(tsm_rwsem);
static DEFINE_IDA(tsm_ida);
static int match_id(struct device *dev, const void *data)
@@ -108,32 +104,6 @@ void tsm_unregister(struct tsm_dev *tsm_dev)
}
EXPORT_SYMBOL_GPL(tsm_unregister);
-/* must be invoked between tsm_register / tsm_unregister */
-int tsm_ide_stream_register(struct pci_ide *ide)
-{
- struct pci_dev *pdev = ide->pdev;
- struct pci_tsm *tsm = pdev->tsm;
- struct tsm_dev *tsm_dev = tsm->tsm_dev;
- int rc;
-
- rc = sysfs_create_link(&tsm_dev->dev.kobj, &pdev->dev.kobj, ide->name);
- if (rc)
- return rc;
-
- ide->tsm_dev = tsm_dev;
- return 0;
-}
-EXPORT_SYMBOL_GPL(tsm_ide_stream_register);
-
-void tsm_ide_stream_unregister(struct pci_ide *ide)
-{
- struct tsm_dev *tsm_dev = ide->tsm_dev;
-
- ide->tsm_dev = NULL;
- sysfs_remove_link(&tsm_dev->dev.kobj, ide->name);
-}
-EXPORT_SYMBOL_GPL(tsm_ide_stream_unregister);
-
static void tsm_release(struct device *dev)
{
struct tsm_dev *tsm_dev = container_of(dev, typeof(*tsm_dev), dev);
diff --git a/fs/btrfs/raid56.c b/fs/btrfs/raid56.c
index f38d8305e46d..baadaaa189c0 100644
--- a/fs/btrfs/raid56.c
+++ b/fs/btrfs/raid56.c
@@ -150,6 +150,7 @@ static void scrub_rbio_work_locked(struct work_struct *work);
static void free_raid_bio_pointers(struct btrfs_raid_bio *rbio)
{
bitmap_free(rbio->error_bitmap);
+ bitmap_free(rbio->stripe_uptodate_bitmap);
kfree(rbio->stripe_pages);
kfree(rbio->bio_paddrs);
kfree(rbio->stripe_paddrs);
diff --git a/fs/smb/client/cifstransport.c b/fs/smb/client/cifstransport.c
index 28d1cee90625..98287132626e 100644
--- a/fs/smb/client/cifstransport.c
+++ b/fs/smb/client/cifstransport.c
@@ -251,13 +251,15 @@ SendReceive(const unsigned int xid, struct cifs_ses *ses,
rc = cifs_send_recv(xid, ses, ses->server,
&rqst, &resp_buf_type, flags, &resp_iov);
if (rc < 0)
- return rc;
+ goto out;
if (out_buf) {
*pbytes_returned = resp_iov.iov_len;
if (resp_iov.iov_len)
memcpy(out_buf, resp_iov.iov_base, resp_iov.iov_len);
}
+
+out:
free_rsp_buf(resp_buf_type, resp_iov.iov_base);
return rc;
}
diff --git a/fs/smb/client/smb2file.c b/fs/smb/client/smb2file.c
index 7f11ae6bb785..2dd08388ea87 100644
--- a/fs/smb/client/smb2file.c
+++ b/fs/smb/client/smb2file.c
@@ -178,6 +178,7 @@ int smb2_open_file(const unsigned int xid, struct cifs_open_parms *oparms,
rc = SMB2_open(xid, oparms, smb2_path, &smb2_oplock, smb2_data, NULL, &err_iov,
&err_buftype);
if (rc == -EACCES && retry_without_read_attributes) {
+ free_rsp_buf(err_buftype, err_iov.iov_base);
oparms->desired_access &= ~FILE_READ_ATTRIBUTES;
rc = SMB2_open(xid, oparms, smb2_path, &smb2_oplock, smb2_data, NULL, &err_iov,
&err_buftype);
diff --git a/include/linux/pci-ide.h b/include/linux/pci-ide.h
index 37a1ad9501b0..ae07d9f699c0 100644
--- a/include/linux/pci-ide.h
+++ b/include/linux/pci-ide.h
@@ -26,7 +26,7 @@ enum pci_ide_partner_select {
/**
* struct pci_ide_partner - Per port pair Selective IDE Stream settings
* @rid_start: Partner Port Requester ID range start
- * @rid_end: Partner Port Requester ID range end
+ * @rid_end: Partner Port Requester ID range end (inclusive)
* @stream_index: Selective IDE Stream Register Block selection
* @mem_assoc: PCI bus memory address association for targeting peer partner
* @pref_assoc: PCI bus prefetchable memory address association for
@@ -82,7 +82,6 @@ struct pci_ide_regs {
* @host_bridge_stream: allocated from host bridge @ide_stream_ida pool
* @stream_id: unique Stream ID (within Partner Port pairing)
* @name: name of the established Selective IDE Stream in sysfs
- * @tsm_dev: For TSM established IDE, the TSM device context
*
* Negative @stream_id values indicate "uninitialized" on the
* expectation that with TSM established IDE the TSM owns the stream_id
@@ -94,7 +93,6 @@ struct pci_ide {
u8 host_bridge_stream;
int stream_id;
const char *name;
- struct tsm_dev *tsm_dev;
};
/*
diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
index 86737076101d..112e48970338 100644
--- a/include/linux/skbuff.h
+++ b/include/linux/skbuff.h
@@ -4301,6 +4301,18 @@ skb_header_pointer(const struct sk_buff *skb, int offset, int len, void *buffer)
skb_headlen(skb), buffer);
}
+/* Variant of skb_header_pointer() where @offset is user-controlled
+ * and potentially negative.
+ */
+static inline void * __must_check
+skb_header_pointer_careful(const struct sk_buff *skb, int offset,
+ int len, void *buffer)
+{
+ if (unlikely(offset < 0 && -offset > skb_headroom(skb)))
+ return NULL;
+ return skb_header_pointer(skb, offset, len, buffer);
+}
+
static inline void * __must_check
skb_pointer_if_linear(const struct sk_buff *skb, int offset, int len)
{
diff --git a/include/linux/tsm.h b/include/linux/tsm.h
index a3b7ab668eff..22e05b2aac69 100644
--- a/include/linux/tsm.h
+++ b/include/linux/tsm.h
@@ -123,7 +123,4 @@ int tsm_report_unregister(const struct tsm_report_ops *ops);
struct tsm_dev *tsm_register(struct device *parent, struct pci_tsm_ops *ops);
void tsm_unregister(struct tsm_dev *tsm_dev);
struct tsm_dev *find_tsm_dev(int id);
-struct pci_ide;
-int tsm_ide_stream_register(struct pci_ide *ide);
-void tsm_ide_stream_unregister(struct pci_ide *ide);
#endif /* __TSM_H */
diff --git a/include/trace/events/dma.h b/include/trace/events/dma.h
index b3fef140ae15..33e99e792f1a 100644
--- a/include/trace/events/dma.h
+++ b/include/trace/events/dma.h
@@ -275,6 +275,8 @@ TRACE_EVENT(dma_free_sgt,
sizeof(u64), sizeof(u64)))
);
+#define DMA_TRACE_MAX_ENTRIES 128
+
TRACE_EVENT(dma_map_sg,
TP_PROTO(struct device *dev, struct scatterlist *sgl, int nents,
int ents, enum dma_data_direction dir, unsigned long attrs),
@@ -282,9 +284,12 @@ TRACE_EVENT(dma_map_sg,
TP_STRUCT__entry(
__string(device, dev_name(dev))
- __dynamic_array(u64, phys_addrs, nents)
- __dynamic_array(u64, dma_addrs, ents)
- __dynamic_array(unsigned int, lengths, ents)
+ __field(int, full_nents)
+ __field(int, full_ents)
+ __field(bool, truncated)
+ __dynamic_array(u64, phys_addrs, min(nents, DMA_TRACE_MAX_ENTRIES))
+ __dynamic_array(u64, dma_addrs, min(ents, DMA_TRACE_MAX_ENTRIES))
+ __dynamic_array(unsigned int, lengths, min(ents, DMA_TRACE_MAX_ENTRIES))
__field(enum dma_data_direction, dir)
__field(unsigned long, attrs)
),
@@ -292,11 +297,16 @@ TRACE_EVENT(dma_map_sg,
TP_fast_assign(
struct scatterlist *sg;
int i;
+ int traced_nents = min_t(int, nents, DMA_TRACE_MAX_ENTRIES);
+ int traced_ents = min_t(int, ents, DMA_TRACE_MAX_ENTRIES);
__assign_str(device);
- for_each_sg(sgl, sg, nents, i)
+ __entry->full_nents = nents;
+ __entry->full_ents = ents;
+ __entry->truncated = (nents > DMA_TRACE_MAX_ENTRIES) || (ents > DMA_TRACE_MAX_ENTRIES);
+ for_each_sg(sgl, sg, traced_nents, i)
((u64 *)__get_dynamic_array(phys_addrs))[i] = sg_phys(sg);
- for_each_sg(sgl, sg, ents, i) {
+ for_each_sg(sgl, sg, traced_ents, i) {
((u64 *)__get_dynamic_array(dma_addrs))[i] =
sg_dma_address(sg);
((unsigned int *)__get_dynamic_array(lengths))[i] =
@@ -306,9 +316,12 @@ TRACE_EVENT(dma_map_sg,
__entry->attrs = attrs;
),
- TP_printk("%s dir=%s dma_addrs=%s sizes=%s phys_addrs=%s attrs=%s",
+ TP_printk("%s dir=%s nents=%d/%d ents=%d/%d%s dma_addrs=%s sizes=%s phys_addrs=%s attrs=%s",
__get_str(device),
decode_dma_data_direction(__entry->dir),
+ min_t(int, __entry->full_nents, DMA_TRACE_MAX_ENTRIES), __entry->full_nents,
+ min_t(int, __entry->full_ents, DMA_TRACE_MAX_ENTRIES), __entry->full_ents,
+ __entry->truncated ? " [TRUNCATED]" : "",
__print_array(__get_dynamic_array(dma_addrs),
__get_dynamic_array_len(dma_addrs) /
sizeof(u64), sizeof(u64)),
diff --git a/io_uring/fdinfo.c b/io_uring/fdinfo.c
index a87d4e26eee8..80178b69e05a 100644
--- a/io_uring/fdinfo.c
+++ b/io_uring/fdinfo.c
@@ -67,7 +67,7 @@ static void __io_uring_show_fdinfo(struct io_ring_ctx *ctx, struct seq_file *m)
unsigned int cq_head = READ_ONCE(r->cq.head);
unsigned int cq_tail = READ_ONCE(r->cq.tail);
unsigned int sq_shift = 0;
- unsigned int sq_entries;
+ unsigned int cq_entries, sq_entries;
int sq_pid = -1, sq_cpu = -1;
u64 sq_total_time = 0, sq_work_time = 0;
unsigned int i;
@@ -146,9 +146,11 @@ static void __io_uring_show_fdinfo(struct io_ring_ctx *ctx, struct seq_file *m)
}
}
seq_printf(m, "\n");
+ cond_resched();
}
seq_printf(m, "CQEs:\t%u\n", cq_tail - cq_head);
- while (cq_head < cq_tail) {
+ cq_entries = min(cq_tail - cq_head, ctx->cq_entries);
+ for (i = 0; i < cq_entries; i++) {
struct io_uring_cqe *cqe;
bool cqe32 = false;
@@ -159,12 +161,15 @@ static void __io_uring_show_fdinfo(struct io_ring_ctx *ctx, struct seq_file *m)
cq_head & cq_mask, cqe->user_data, cqe->res,
cqe->flags);
if (cqe32)
- seq_printf(m, ", extra1:%llu, extra2:%llu\n",
+ seq_printf(m, ", extra1:%llu, extra2:%llu",
cqe->big_cqe[0], cqe->big_cqe[1]);
seq_printf(m, "\n");
cq_head++;
- if (cqe32)
+ if (cqe32) {
cq_head++;
+ i++;
+ }
+ cond_resched();
}
if (ctx->flags & IORING_SETUP_SQPOLL) {
diff --git a/io_uring/zcrx.c b/io_uring/zcrx.c
index b99cf2c6670a..3d398283cf34 100644
--- a/io_uring/zcrx.c
+++ b/io_uring/zcrx.c
@@ -197,6 +197,7 @@ static int io_import_umem(struct io_zcrx_ifq *ifq,
GFP_KERNEL_ACCOUNT);
if (ret) {
unpin_user_pages(pages, nr_pages);
+ kvfree(pages);
return ret;
}
@@ -1068,8 +1069,6 @@ static unsigned zcrx_parse_rq(netmem_ref *netmem_array, unsigned nr,
unsigned int mask = zcrx->rq_entries - 1;
unsigned int i;
- guard(spinlock_bh)(&zcrx->rq_lock);
-
nr = min(nr, io_zcrx_rqring_entries(zcrx));
for (i = 0; i < nr; i++) {
struct io_uring_zcrx_rqe *rqe = io_zcrx_get_rqe(zcrx, mask);
@@ -1114,9 +1113,11 @@ static int zcrx_flush_rq(struct io_ring_ctx *ctx, struct io_zcrx_ifq *zcrx,
return -EINVAL;
do {
- nr = zcrx_parse_rq(netmems, ZCRX_FLUSH_BATCH, zcrx);
+ scoped_guard(spinlock_bh, &zcrx->rq_lock) {
+ nr = zcrx_parse_rq(netmems, ZCRX_FLUSH_BATCH, zcrx);
+ zcrx_return_buffers(netmems, nr);
+ }
- zcrx_return_buffers(netmems, nr);
total += nr;
if (fatal_signal_pending(current))
diff --git a/kernel/cgroup/dmem.c b/kernel/cgroup/dmem.c
index e12b946278b6..1ea6afffa985 100644
--- a/kernel/cgroup/dmem.c
+++ b/kernel/cgroup/dmem.c
@@ -14,6 +14,7 @@
#include <linux/mutex.h>
#include <linux/page_counter.h>
#include <linux/parser.h>
+#include <linux/refcount.h>
#include <linux/rculist.h>
#include <linux/slab.h>
@@ -71,7 +72,9 @@ struct dmem_cgroup_pool_state {
struct rcu_head rcu;
struct page_counter cnt;
+ struct dmem_cgroup_pool_state *parent;
+ refcount_t ref;
bool inited;
};
@@ -88,6 +91,9 @@ struct dmem_cgroup_pool_state {
static DEFINE_SPINLOCK(dmemcg_lock);
static LIST_HEAD(dmem_cgroup_regions);
+static void dmemcg_free_region(struct kref *ref);
+static void dmemcg_pool_free_rcu(struct rcu_head *rcu);
+
static inline struct dmemcg_state *
css_to_dmemcs(struct cgroup_subsys_state *css)
{
@@ -104,10 +110,38 @@ static struct dmemcg_state *parent_dmemcs(struct dmemcg_state *cg)
return cg->css.parent ? css_to_dmemcs(cg->css.parent) : NULL;
}
+static void dmemcg_pool_get(struct dmem_cgroup_pool_state *pool)
+{
+ refcount_inc(&pool->ref);
+}
+
+static bool dmemcg_pool_tryget(struct dmem_cgroup_pool_state *pool)
+{
+ return refcount_inc_not_zero(&pool->ref);
+}
+
+static void dmemcg_pool_put(struct dmem_cgroup_pool_state *pool)
+{
+ if (!refcount_dec_and_test(&pool->ref))
+ return;
+
+ call_rcu(&pool->rcu, dmemcg_pool_free_rcu);
+}
+
+static void dmemcg_pool_free_rcu(struct rcu_head *rcu)
+{
+ struct dmem_cgroup_pool_state *pool = container_of(rcu, typeof(*pool), rcu);
+
+ if (pool->parent)
+ dmemcg_pool_put(pool->parent);
+ kref_put(&pool->region->ref, dmemcg_free_region);
+ kfree(pool);
+}
+
static void free_cg_pool(struct dmem_cgroup_pool_state *pool)
{
list_del(&pool->region_node);
- kfree(pool);
+ dmemcg_pool_put(pool);
}
static void
@@ -342,6 +376,12 @@ alloc_pool_single(struct dmemcg_state *dmemcs, struct dmem_cgroup_region *region
page_counter_init(&pool->cnt,
ppool ? &ppool->cnt : NULL, true);
reset_all_resource_limits(pool);
+ refcount_set(&pool->ref, 1);
+ kref_get(&region->ref);
+ if (ppool && !pool->parent) {
+ pool->parent = ppool;
+ dmemcg_pool_get(ppool);
+ }
list_add_tail_rcu(&pool->css_node, &dmemcs->pools);
list_add_tail(&pool->region_node, &region->pools);
@@ -389,6 +429,10 @@ get_cg_pool_locked(struct dmemcg_state *dmemcs, struct dmem_cgroup_region *regio
/* Fix up parent links, mark as inited. */
pool->cnt.parent = &ppool->cnt;
+ if (ppool && !pool->parent) {
+ pool->parent = ppool;
+ dmemcg_pool_get(ppool);
+ }
pool->inited = true;
pool = ppool;
@@ -423,7 +467,7 @@ static void dmemcg_free_region(struct kref *ref)
*/
void dmem_cgroup_unregister_region(struct dmem_cgroup_region *region)
{
- struct list_head *entry;
+ struct dmem_cgroup_pool_state *pool, *next;
if (!region)
return;
@@ -433,11 +477,10 @@ void dmem_cgroup_unregister_region(struct dmem_cgroup_region *region)
/* Remove from global region list */
list_del_rcu(&region->region_node);
- list_for_each_rcu(entry, &region->pools) {
- struct dmem_cgroup_pool_state *pool =
- container_of(entry, typeof(*pool), region_node);
-
+ list_for_each_entry_safe(pool, next, &region->pools, region_node) {
list_del_rcu(&pool->css_node);
+ list_del(&pool->region_node);
+ dmemcg_pool_put(pool);
}
/*
@@ -518,8 +561,10 @@ static struct dmem_cgroup_region *dmemcg_get_region_by_name(const char *name)
*/
void dmem_cgroup_pool_state_put(struct dmem_cgroup_pool_state *pool)
{
- if (pool)
+ if (pool) {
css_put(&pool->cs->css);
+ dmemcg_pool_put(pool);
+ }
}
EXPORT_SYMBOL_GPL(dmem_cgroup_pool_state_put);
@@ -533,6 +578,8 @@ get_cg_pool_unlocked(struct dmemcg_state *cg, struct dmem_cgroup_region *region)
pool = find_cg_pool_locked(cg, region);
if (pool && !READ_ONCE(pool->inited))
pool = NULL;
+ if (pool && !dmemcg_pool_tryget(pool))
+ pool = NULL;
rcu_read_unlock();
while (!pool) {
@@ -541,6 +588,8 @@ get_cg_pool_unlocked(struct dmemcg_state *cg, struct dmem_cgroup_region *region)
pool = get_cg_pool_locked(cg, region, &allocpool);
else
pool = ERR_PTR(-ENODEV);
+ if (!IS_ERR(pool))
+ dmemcg_pool_get(pool);
spin_unlock(&dmemcg_lock);
if (pool == ERR_PTR(-ENOMEM)) {
@@ -576,6 +625,7 @@ void dmem_cgroup_uncharge(struct dmem_cgroup_pool_state *pool, u64 size)
page_counter_uncharge(&pool->cnt, size);
css_put(&pool->cs->css);
+ dmemcg_pool_put(pool);
}
EXPORT_SYMBOL_GPL(dmem_cgroup_uncharge);
@@ -627,7 +677,9 @@ int dmem_cgroup_try_charge(struct dmem_cgroup_region *region, u64 size,
if (ret_limit_pool) {
*ret_limit_pool = container_of(fail, struct dmem_cgroup_pool_state, cnt);
css_get(&(*ret_limit_pool)->cs->css);
+ dmemcg_pool_get(*ret_limit_pool);
}
+ dmemcg_pool_put(pool);
ret = -EAGAIN;
goto err;
}
@@ -700,6 +752,9 @@ static ssize_t dmemcg_limit_write(struct kernfs_open_file *of,
if (!region_name[0])
continue;
+ if (!options || !*options)
+ return -EINVAL;
+
rcu_read_lock();
region = dmemcg_get_region_by_name(region_name);
rcu_read_unlock();
@@ -719,6 +774,7 @@ static ssize_t dmemcg_limit_write(struct kernfs_open_file *of,
/* And commit */
apply(pool, new_limit);
+ dmemcg_pool_put(pool);
out_put:
kref_put(&region->ref, dmemcg_free_region);
diff --git a/kernel/dma/contiguous.c b/kernel/dma/contiguous.c
index 0e266979728b..c56004d314dc 100644
--- a/kernel/dma/contiguous.c
+++ b/kernel/dma/contiguous.c
@@ -257,10 +257,12 @@ void __init dma_contiguous_reserve(phys_addr_t limit)
pr_debug("%s: reserving %ld MiB for global area\n", __func__,
(unsigned long)selected_size / SZ_1M);
- dma_contiguous_reserve_area(selected_size, selected_base,
- selected_limit,
- &dma_contiguous_default_area,
- fixed);
+ ret = dma_contiguous_reserve_area(selected_size, selected_base,
+ selected_limit,
+ &dma_contiguous_default_area,
+ fixed);
+ if (ret)
+ return;
ret = dma_heap_cma_register_heap(dma_contiguous_default_area);
if (ret)
diff --git a/kernel/liveupdate/luo_file.c b/kernel/liveupdate/luo_file.c
index a32a777f6df8..9f7283379ebc 100644
--- a/kernel/liveupdate/luo_file.c
+++ b/kernel/liveupdate/luo_file.c
@@ -402,8 +402,6 @@ static void luo_file_unfreeze_one(struct luo_file_set *file_set,
luo_file->fh->ops->unfreeze(&args);
}
-
- luo_file->serialized_data = 0;
}
static void __luo_file_unfreeze(struct luo_file_set *file_set,
diff --git a/kernel/sched/ext.c b/kernel/sched/ext.c
index afe28c04d5aa..0bb8fa927e9e 100644
--- a/kernel/sched/ext.c
+++ b/kernel/sched/ext.c
@@ -194,6 +194,7 @@ MODULE_PARM_DESC(bypass_lb_intv_us, "bypass load balance interval in microsecond
#include <trace/events/sched_ext.h>
static void process_ddsp_deferred_locals(struct rq *rq);
+static bool task_dead_and_done(struct task_struct *p);
static u32 reenq_local(struct rq *rq);
static void scx_kick_cpu(struct scx_sched *sch, s32 cpu, u64 flags);
static bool scx_vexit(struct scx_sched *sch, enum scx_exit_kind kind,
@@ -2619,6 +2620,9 @@ static void set_cpus_allowed_scx(struct task_struct *p,
set_cpus_allowed_common(p, ac);
+ if (task_dead_and_done(p))
+ return;
+
/*
* The effective cpumask is stored in @p->cpus_ptr which may temporarily
* differ from the configured one in @p->cpus_mask. Always tell the bpf
@@ -3034,10 +3038,45 @@ void scx_cancel_fork(struct task_struct *p)
percpu_up_read(&scx_fork_rwsem);
}
+/**
+ * task_dead_and_done - Is a task dead and done running?
+ * @p: target task
+ *
+ * Once sched_ext_dead() removes the dead task from scx_tasks and exits it, the
+ * task no longer exists from SCX's POV. However, certain sched_class ops may be
+ * invoked on these dead tasks leading to failures - e.g. sched_setscheduler()
+ * may try to switch a task which finished sched_ext_dead() back into SCX
+ * triggering invalid SCX task state transitions and worse.
+ *
+ * Once a task has finished the final switch, sched_ext_dead() is the only thing
+ * that needs to happen on the task. Use this test to short-circuit sched_class
+ * operations which may be called on dead tasks.
+ */
+static bool task_dead_and_done(struct task_struct *p)
+{
+ struct rq *rq = task_rq(p);
+
+ lockdep_assert_rq_held(rq);
+
+ /*
+ * In do_task_dead(), a dying task sets %TASK_DEAD with preemption
+ * disabled and __schedule(). If @p has %TASK_DEAD set and off CPU, @p
+ * won't ever run again.
+ */
+ return unlikely(READ_ONCE(p->__state) == TASK_DEAD) &&
+ !task_on_cpu(rq, p);
+}
+
void sched_ext_dead(struct task_struct *p)
{
unsigned long flags;
+ /*
+ * By the time control reaches here, @p has %TASK_DEAD set, switched out
+ * for the last time and then dropped the rq lock - task_dead_and_done()
+ * should be returning %true nullifying the straggling sched_class ops.
+ * Remove from scx_tasks and exit @p.
+ */
raw_spin_lock_irqsave(&scx_tasks_lock, flags);
list_del_init(&p->scx.tasks_node);
raw_spin_unlock_irqrestore(&scx_tasks_lock, flags);
@@ -3063,6 +3102,9 @@ static void reweight_task_scx(struct rq *rq, struct task_struct *p,
lockdep_assert_rq_held(task_rq(p));
+ if (task_dead_and_done(p))
+ return;
+
p->scx.weight = sched_weight_to_cgroup(scale_load_down(lw->weight));
if (SCX_HAS_OP(sch, set_weight))
SCX_CALL_OP_TASK(sch, SCX_KF_REST, set_weight, rq,
@@ -3077,6 +3119,9 @@ static void switching_to_scx(struct rq *rq, struct task_struct *p)
{
struct scx_sched *sch = scx_root;
+ if (task_dead_and_done(p))
+ return;
+
scx_enable_task(p);
/*
@@ -3090,6 +3135,9 @@ static void switching_to_scx(struct rq *rq, struct task_struct *p)
static void switched_from_scx(struct rq *rq, struct task_struct *p)
{
+ if (task_dead_and_done(p))
+ return;
+
scx_disable_task(p);
}
diff --git a/mm/shmem.c b/mm/shmem.c
index 6c3485d24d66..79af5f9f8b90 100644
--- a/mm/shmem.c
+++ b/mm/shmem.c
@@ -1211,17 +1211,22 @@ whole_folios:
swaps_freed = shmem_free_swap(mapping, indices[i],
end - 1, folio);
if (!swaps_freed) {
- /*
- * If found a large swap entry cross the end border,
- * skip it as the truncate_inode_partial_folio above
- * should have at least zerod its content once.
- */
+ pgoff_t base = indices[i];
+
order = shmem_confirm_swap(mapping, indices[i],
radix_to_swp_entry(folio));
- if (order > 0 && indices[i] + (1 << order) > end)
- continue;
- /* Swap was replaced by page: retry */
- index = indices[i];
+ /*
+ * If found a large swap entry cross the end or start
+ * border, skip it as the truncate_inode_partial_folio
+ * above should have at least zerod its content once.
+ */
+ if (order > 0) {
+ base = round_down(base, 1 << order);
+ if (base < start || base + (1 << order) > end)
+ continue;
+ }
+ /* Swap was replaced by page or extended, retry */
+ index = base;
break;
}
nr_swaps_freed += swaps_freed;
diff --git a/mm/slub.c b/mm/slub.c
index f77b7407c51b..cdc1e652ec52 100644
--- a/mm/slub.c
+++ b/mm/slub.c
@@ -6689,8 +6689,12 @@ void slab_free(struct kmem_cache *s, struct slab *slab, void *object,
static noinline
void memcg_alloc_abort_single(struct kmem_cache *s, void *object)
{
+ struct slab *slab = virt_to_slab(object);
+
+ alloc_tagging_slab_free_hook(s, slab, &object, 1);
+
if (likely(slab_free_hook(s, object, slab_want_init_on_free(s), false)))
- do_slab_free(s, virt_to_slab(object), object, object, 1, _RET_IP_);
+ do_slab_free(s, slab, object, object, 1, _RET_IP_);
}
#endif
diff --git a/net/core/filter.c b/net/core/filter.c
index bcd73d9bd764..029e560e32ce 100644
--- a/net/core/filter.c
+++ b/net/core/filter.c
@@ -2289,12 +2289,12 @@ static int __bpf_redirect_neigh_v6(struct sk_buff *skb, struct net_device *dev,
err = bpf_out_neigh_v6(net, skb, dev, nh);
if (unlikely(net_xmit_eval(err)))
- DEV_STATS_INC(dev, tx_errors);
+ dev_core_stats_tx_dropped_inc(dev);
else
ret = NET_XMIT_SUCCESS;
goto out_xmit;
out_drop:
- DEV_STATS_INC(dev, tx_errors);
+ dev_core_stats_tx_dropped_inc(dev);
kfree_skb(skb);
out_xmit:
return ret;
@@ -2396,12 +2396,12 @@ static int __bpf_redirect_neigh_v4(struct sk_buff *skb, struct net_device *dev,
err = bpf_out_neigh_v4(net, skb, dev, nh);
if (unlikely(net_xmit_eval(err)))
- DEV_STATS_INC(dev, tx_errors);
+ dev_core_stats_tx_dropped_inc(dev);
else
ret = NET_XMIT_SUCCESS;
goto out_xmit;
out_drop:
- DEV_STATS_INC(dev, tx_errors);
+ dev_core_stats_tx_dropped_inc(dev);
kfree_skb(skb);
out_xmit:
return ret;
diff --git a/net/core/gro.c b/net/core/gro.c
index 76f9c3712422..482fa7d7f598 100644
--- a/net/core/gro.c
+++ b/net/core/gro.c
@@ -265,6 +265,8 @@ static void gro_complete(struct gro_node *gro, struct sk_buff *skb)
goto out;
}
+ /* NICs can feed encapsulated packets into GRO */
+ skb->encapsulation = 0;
rcu_read_lock();
list_for_each_entry_rcu(ptype, head, list) {
if (ptype->type != type || !ptype->callbacks.gro_complete)
diff --git a/net/core/link_watch.c b/net/core/link_watch.c
index 212cde35affa..25c455c10a01 100644
--- a/net/core/link_watch.c
+++ b/net/core/link_watch.c
@@ -185,10 +185,6 @@ static void linkwatch_do_dev(struct net_device *dev)
netif_state_change(dev);
}
- /* Note: our callers are responsible for calling netdev_tracker_free().
- * This is the reason we use __dev_put() instead of dev_put().
- */
- __dev_put(dev);
}
static void __linkwatch_run_queue(int urgent_only)
@@ -243,6 +239,11 @@ static void __linkwatch_run_queue(int urgent_only)
netdev_lock_ops(dev);
linkwatch_do_dev(dev);
netdev_unlock_ops(dev);
+ /* Use __dev_put() because netdev_tracker_free() was already
+ * called above. Must be after netdev_unlock_ops() to prevent
+ * netdev_run_todo() from freeing the device while still in use.
+ */
+ __dev_put(dev);
do_dev--;
spin_lock_irq(&lweventlist_lock);
}
@@ -278,8 +279,13 @@ void __linkwatch_sync_dev(struct net_device *dev)
{
netdev_ops_assert_locked(dev);
- if (linkwatch_clean_dev(dev))
+ if (linkwatch_clean_dev(dev)) {
linkwatch_do_dev(dev);
+ /* Use __dev_put() because netdev_tracker_free() was already
+ * called inside linkwatch_clean_dev().
+ */
+ __dev_put(dev);
+ }
}
void linkwatch_sync_dev(struct net_device *dev)
@@ -288,6 +294,10 @@ void linkwatch_sync_dev(struct net_device *dev)
netdev_lock_ops(dev);
linkwatch_do_dev(dev);
netdev_unlock_ops(dev);
+ /* Use __dev_put() because netdev_tracker_free() was already
+ * called inside linkwatch_clean_dev().
+ */
+ __dev_put(dev);
}
}
diff --git a/net/core/net-procfs.c b/net/core/net-procfs.c
index 70e0e9a3b650..7dbfa6109f0b 100644
--- a/net/core/net-procfs.c
+++ b/net/core/net-procfs.c
@@ -170,8 +170,14 @@ static const struct seq_operations softnet_seq_ops = {
.show = softnet_seq_show,
};
+struct ptype_iter_state {
+ struct seq_net_private p;
+ struct net_device *dev;
+};
+
static void *ptype_get_idx(struct seq_file *seq, loff_t pos)
{
+ struct ptype_iter_state *iter = seq->private;
struct list_head *ptype_list = NULL;
struct packet_type *pt = NULL;
struct net_device *dev;
@@ -181,12 +187,16 @@ static void *ptype_get_idx(struct seq_file *seq, loff_t pos)
for_each_netdev_rcu(seq_file_net(seq), dev) {
ptype_list = &dev->ptype_all;
list_for_each_entry_rcu(pt, ptype_list, list) {
- if (i == pos)
+ if (i == pos) {
+ iter->dev = dev;
return pt;
+ }
++i;
}
}
+ iter->dev = NULL;
+
list_for_each_entry_rcu(pt, &seq_file_net(seq)->ptype_all, list) {
if (i == pos)
return pt;
@@ -218,6 +228,7 @@ static void *ptype_seq_start(struct seq_file *seq, loff_t *pos)
static void *ptype_seq_next(struct seq_file *seq, void *v, loff_t *pos)
{
+ struct ptype_iter_state *iter = seq->private;
struct net *net = seq_file_net(seq);
struct net_device *dev;
struct packet_type *pt;
@@ -229,19 +240,21 @@ static void *ptype_seq_next(struct seq_file *seq, void *v, loff_t *pos)
return ptype_get_idx(seq, 0);
pt = v;
- nxt = pt->list.next;
- if (pt->dev) {
- if (nxt != &pt->dev->ptype_all)
+ nxt = READ_ONCE(pt->list.next);
+ dev = iter->dev;
+ if (dev) {
+ if (nxt != &dev->ptype_all)
goto found;
- dev = pt->dev;
for_each_netdev_continue_rcu(seq_file_net(seq), dev) {
- if (!list_empty(&dev->ptype_all)) {
- nxt = dev->ptype_all.next;
+ nxt = READ_ONCE(dev->ptype_all.next);
+ if (nxt != &dev->ptype_all) {
+ iter->dev = dev;
goto found;
}
}
- nxt = net->ptype_all.next;
+ iter->dev = NULL;
+ nxt = READ_ONCE(net->ptype_all.next);
goto net_ptype_all;
}
@@ -252,20 +265,20 @@ net_ptype_all:
if (nxt == &net->ptype_all) {
/* continue with ->ptype_specific if it's not empty */
- nxt = net->ptype_specific.next;
+ nxt = READ_ONCE(net->ptype_specific.next);
if (nxt != &net->ptype_specific)
goto found;
}
hash = 0;
- nxt = ptype_base[0].next;
+ nxt = READ_ONCE(ptype_base[0].next);
} else
hash = ntohs(pt->type) & PTYPE_HASH_MASK;
while (nxt == &ptype_base[hash]) {
if (++hash >= PTYPE_HASH_SIZE)
return NULL;
- nxt = ptype_base[hash].next;
+ nxt = READ_ONCE(ptype_base[hash].next);
}
found:
return list_entry(nxt, struct packet_type, list);
@@ -279,19 +292,24 @@ static void ptype_seq_stop(struct seq_file *seq, void *v)
static int ptype_seq_show(struct seq_file *seq, void *v)
{
+ struct ptype_iter_state *iter = seq->private;
struct packet_type *pt = v;
+ struct net_device *dev;
- if (v == SEQ_START_TOKEN)
+ if (v == SEQ_START_TOKEN) {
seq_puts(seq, "Type Device Function\n");
- else if ((!pt->af_packet_net || net_eq(pt->af_packet_net, seq_file_net(seq))) &&
- (!pt->dev || net_eq(dev_net(pt->dev), seq_file_net(seq)))) {
+ return 0;
+ }
+ dev = iter->dev;
+ if ((!pt->af_packet_net || net_eq(pt->af_packet_net, seq_file_net(seq))) &&
+ (!dev || net_eq(dev_net(dev), seq_file_net(seq)))) {
if (pt->type == htons(ETH_P_ALL))
seq_puts(seq, "ALL ");
else
seq_printf(seq, "%04x", ntohs(pt->type));
seq_printf(seq, " %-8s %ps\n",
- pt->dev ? pt->dev->name : "", pt->func);
+ dev ? dev->name : "", pt->func);
}
return 0;
@@ -315,7 +333,7 @@ static int __net_init dev_proc_net_init(struct net *net)
&softnet_seq_ops))
goto out_dev;
if (!proc_create_net("ptype", 0444, net->proc_net, &ptype_seq_ops,
- sizeof(struct seq_net_private)))
+ sizeof(struct ptype_iter_state)))
goto out_softnet;
if (wext_proc_init(net))
diff --git a/net/ethtool/common.c b/net/ethtool/common.c
index 369c05cf8163..d47a279eb8b9 100644
--- a/net/ethtool/common.c
+++ b/net/ethtool/common.c
@@ -862,9 +862,6 @@ ethtool_rxfh_ctx_alloc(const struct ethtool_ops *ops,
ctx->key_off = key_off;
ctx->priv_size = ops->rxfh_priv_size;
- ctx->hfunc = ETH_RSS_HASH_NO_CHANGE;
- ctx->input_xfrm = RXH_XFRM_NO_CHANGE;
-
return ctx;
}
diff --git a/net/ethtool/rss.c b/net/ethtool/rss.c
index 4dced53be4b3..da5934cceb07 100644
--- a/net/ethtool/rss.c
+++ b/net/ethtool/rss.c
@@ -824,8 +824,8 @@ rss_set_ctx_update(struct ethtool_rxfh_context *ctx, struct nlattr **tb,
static int
ethnl_rss_set(struct ethnl_req_info *req_info, struct genl_info *info)
{
- bool indir_reset = false, indir_mod, xfrm_sym = false;
struct rss_req_info *request = RSS_REQINFO(req_info);
+ bool indir_reset = false, indir_mod, xfrm_sym;
struct ethtool_rxfh_context *ctx = NULL;
struct net_device *dev = req_info->dev;
bool mod = false, fields_mod = false;
@@ -860,12 +860,7 @@ ethnl_rss_set(struct ethnl_req_info *req_info, struct genl_info *info)
rxfh.input_xfrm = data.input_xfrm;
ethnl_update_u8(&rxfh.input_xfrm, tb[ETHTOOL_A_RSS_INPUT_XFRM], &mod);
- /* For drivers which don't support input_xfrm it will be set to 0xff
- * in the RSS context info. In all other case input_xfrm != 0 means
- * symmetric hashing is requested.
- */
- if (!request->rss_context || ops->rxfh_per_ctx_key)
- xfrm_sym = rxfh.input_xfrm || data.input_xfrm;
+ xfrm_sym = rxfh.input_xfrm || data.input_xfrm;
if (rxfh.input_xfrm == data.input_xfrm)
rxfh.input_xfrm = RXH_XFRM_NO_CHANGE;
diff --git a/net/ipv6/ip6_fib.c b/net/ipv6/ip6_fib.c
index 2111af022d94..c6439e30e892 100644
--- a/net/ipv6/ip6_fib.c
+++ b/net/ipv6/ip6_fib.c
@@ -1138,7 +1138,8 @@ static int fib6_add_rt2node(struct fib6_node *fn, struct fib6_info *rt,
fib6_set_expires(iter, rt->expires);
fib6_add_gc_list(iter);
}
- if (!(rt->fib6_flags & (RTF_ADDRCONF | RTF_PREFIX_RT))) {
+ if (!(rt->fib6_flags & (RTF_ADDRCONF | RTF_PREFIX_RT)) &&
+ !iter->fib6_nh->fib_nh_gw_family) {
iter->fib6_flags &= ~RTF_ADDRCONF;
iter->fib6_flags &= ~RTF_PREFIX_RT;
}
diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c
index 729a92781a1a..be92750e2af3 100644
--- a/net/netfilter/nf_tables_api.c
+++ b/net/netfilter/nf_tables_api.c
@@ -5914,7 +5914,7 @@ static void nft_map_catchall_activate(const struct nft_ctx *ctx,
list_for_each_entry(catchall, &set->catchall_list, list) {
ext = nft_set_elem_ext(set, catchall->elem);
- if (!nft_set_elem_active(ext, genmask))
+ if (nft_set_elem_active(ext, genmask))
continue;
nft_clear(ctx->net, ext);
diff --git a/net/sched/cls_u32.c b/net/sched/cls_u32.c
index 2a1c00048fd6..58e849c0acf4 100644
--- a/net/sched/cls_u32.c
+++ b/net/sched/cls_u32.c
@@ -161,10 +161,8 @@ next_knode:
int toff = off + key->off + (off2 & key->offmask);
__be32 *data, hdata;
- if (skb_headroom(skb) + toff > INT_MAX)
- goto out;
-
- data = skb_header_pointer(skb, toff, 4, &hdata);
+ data = skb_header_pointer_careful(skb, toff, 4,
+ &hdata);
if (!data)
goto out;
if ((*data ^ key->val) & key->mask) {
@@ -214,8 +212,9 @@ check_terminal:
if (ht->divisor) {
__be32 *data, hdata;
- data = skb_header_pointer(skb, off + n->sel.hoff, 4,
- &hdata);
+ data = skb_header_pointer_careful(skb,
+ off + n->sel.hoff,
+ 4, &hdata);
if (!data)
goto out;
sel = ht->divisor & u32_hash_fold(*data, &n->sel,
@@ -229,7 +228,7 @@ check_terminal:
if (n->sel.flags & TC_U32_VAROFFSET) {
__be16 *data, hdata;
- data = skb_header_pointer(skb,
+ data = skb_header_pointer_careful(skb,
off + n->sel.offoff,
2, &hdata);
if (!data)
diff --git a/net/tipc/crypto.c b/net/tipc/crypto.c
index 751904f10aab..970db62bd029 100644
--- a/net/tipc/crypto.c
+++ b/net/tipc/crypto.c
@@ -1219,7 +1219,7 @@ void tipc_crypto_key_flush(struct tipc_crypto *c)
rx = c;
tx = tipc_net(rx->net)->crypto_tx;
if (cancel_delayed_work(&rx->work)) {
- kfree(rx->skey);
+ kfree_sensitive(rx->skey);
rx->skey = NULL;
atomic_xchg(&rx->key_distr, 0);
tipc_node_put(rx->node);
@@ -2394,7 +2394,7 @@ static void tipc_crypto_work_rx(struct work_struct *work)
break;
default:
synchronize_rcu();
- kfree(rx->skey);
+ kfree_sensitive(rx->skey);
rx->skey = NULL;
break;
}
diff --git a/security/lsm.h b/security/lsm.h
index 81aadbc61685..db77cc83e158 100644
--- a/security/lsm.h
+++ b/security/lsm.h
@@ -37,15 +37,6 @@ int lsm_task_alloc(struct task_struct *task);
/* LSM framework initializers */
-#ifdef CONFIG_MMU
-int min_addr_init(void);
-#else
-static inline int min_addr_init(void)
-{
- return 0;
-}
-#endif /* CONFIG_MMU */
-
#ifdef CONFIG_SECURITYFS
int securityfs_init(void);
#else
diff --git a/security/lsm_init.c b/security/lsm_init.c
index 05bd52e6b1f2..573e2a7250c4 100644
--- a/security/lsm_init.c
+++ b/security/lsm_init.c
@@ -489,12 +489,7 @@ int __init security_init(void)
*/
static int __init security_initcall_pure(void)
{
- int rc_adr, rc_lsm;
-
- rc_adr = min_addr_init();
- rc_lsm = lsm_initcall(pure);
-
- return (rc_adr ? rc_adr : rc_lsm);
+ return lsm_initcall(pure);
}
pure_initcall(security_initcall_pure);
diff --git a/security/min_addr.c b/security/min_addr.c
index 0fde5ec9abc8..56e4f9d25929 100644
--- a/security/min_addr.c
+++ b/security/min_addr.c
@@ -5,8 +5,6 @@
#include <linux/sysctl.h>
#include <linux/minmax.h>
-#include "lsm.h"
-
/* amount of vm to protect from userspace access by both DAC and the LSM*/
unsigned long mmap_min_addr;
/* amount of vm to protect from userspace using CAP_SYS_RAWIO (DAC) */
@@ -54,10 +52,11 @@ static const struct ctl_table min_addr_sysctl_table[] = {
},
};
-int __init min_addr_init(void)
+static int __init mmap_min_addr_init(void)
{
register_sysctl_init("vm", min_addr_sysctl_table);
update_mmap_min_addr();
return 0;
}
+pure_initcall(mmap_min_addr_init);
diff --git a/sound/drivers/aloop.c b/sound/drivers/aloop.c
index 64ef03b2d579..aa0d2fcb1a18 100644
--- a/sound/drivers/aloop.c
+++ b/sound/drivers/aloop.c
@@ -336,37 +336,43 @@ static bool is_access_interleaved(snd_pcm_access_t access)
static int loopback_check_format(struct loopback_cable *cable, int stream)
{
+ struct loopback_pcm *dpcm_play, *dpcm_capt;
struct snd_pcm_runtime *runtime, *cruntime;
struct loopback_setup *setup;
struct snd_card *card;
+ bool stop_capture = false;
int check;
- if (cable->valid != CABLE_VALID_BOTH) {
- if (stream == SNDRV_PCM_STREAM_PLAYBACK)
- goto __notify;
- return 0;
- }
- runtime = cable->streams[SNDRV_PCM_STREAM_PLAYBACK]->
- substream->runtime;
- cruntime = cable->streams[SNDRV_PCM_STREAM_CAPTURE]->
- substream->runtime;
- check = runtime->format != cruntime->format ||
- runtime->rate != cruntime->rate ||
- runtime->channels != cruntime->channels ||
- is_access_interleaved(runtime->access) !=
- is_access_interleaved(cruntime->access);
- if (!check)
- return 0;
- if (stream == SNDRV_PCM_STREAM_CAPTURE) {
- return -EIO;
- } else {
- snd_pcm_stop(cable->streams[SNDRV_PCM_STREAM_CAPTURE]->
- substream, SNDRV_PCM_STATE_DRAINING);
- __notify:
- runtime = cable->streams[SNDRV_PCM_STREAM_PLAYBACK]->
- substream->runtime;
- setup = get_setup(cable->streams[SNDRV_PCM_STREAM_PLAYBACK]);
- card = cable->streams[SNDRV_PCM_STREAM_PLAYBACK]->loopback->card;
+ scoped_guard(spinlock_irqsave, &cable->lock) {
+ dpcm_play = cable->streams[SNDRV_PCM_STREAM_PLAYBACK];
+ dpcm_capt = cable->streams[SNDRV_PCM_STREAM_CAPTURE];
+
+ if (cable->valid != CABLE_VALID_BOTH) {
+ if (stream == SNDRV_PCM_STREAM_CAPTURE || !dpcm_play)
+ return 0;
+ } else {
+ if (!dpcm_play || !dpcm_capt)
+ return -EIO;
+ runtime = dpcm_play->substream->runtime;
+ cruntime = dpcm_capt->substream->runtime;
+ if (!runtime || !cruntime)
+ return -EIO;
+ check = runtime->format != cruntime->format ||
+ runtime->rate != cruntime->rate ||
+ runtime->channels != cruntime->channels ||
+ is_access_interleaved(runtime->access) !=
+ is_access_interleaved(cruntime->access);
+ if (!check)
+ return 0;
+ if (stream == SNDRV_PCM_STREAM_CAPTURE)
+ return -EIO;
+ else if (cruntime->state == SNDRV_PCM_STATE_RUNNING)
+ stop_capture = true;
+ }
+
+ setup = get_setup(dpcm_play);
+ card = dpcm_play->loopback->card;
+ runtime = dpcm_play->substream->runtime;
if (setup->format != runtime->format) {
snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE,
&setup->format_id);
@@ -389,6 +395,10 @@ static int loopback_check_format(struct loopback_cable *cable, int stream)
setup->access = runtime->access;
}
}
+
+ if (stop_capture)
+ snd_pcm_stop(dpcm_capt->substream, SNDRV_PCM_STATE_DRAINING);
+
return 0;
}
diff --git a/sound/hda/codecs/realtek/alc269.c b/sound/hda/codecs/realtek/alc269.c
index 0a0496deb9c8..b66965a52107 100644
--- a/sound/hda/codecs/realtek/alc269.c
+++ b/sound/hda/codecs/realtek/alc269.c
@@ -6353,6 +6353,7 @@ static const struct hda_quirk alc269_fixup_tbl[] = {
SND_PCI_QUIRK(0x1025, 0x1430, "Acer TravelMate B311R-31", ALC256_FIXUP_ACER_MIC_NO_PRESENCE),
SND_PCI_QUIRK(0x1025, 0x1466, "Acer Aspire A515-56", ALC255_FIXUP_ACER_HEADPHONE_AND_MIC),
SND_PCI_QUIRK(0x1025, 0x1534, "Acer Predator PH315-54", ALC255_FIXUP_ACER_MIC_NO_PRESENCE),
+ SND_PCI_QUIRK(0x1025, 0x1539, "Acer Nitro 5 AN515-57", ALC2XX_FIXUP_HEADSET_MIC),
SND_PCI_QUIRK(0x1025, 0x159c, "Acer Nitro 5 AN515-58", ALC2XX_FIXUP_HEADSET_MIC),
SND_PCI_QUIRK(0x1025, 0x1597, "Acer Nitro 5 AN517-55", ALC2XX_FIXUP_HEADSET_MIC),
SND_PCI_QUIRK(0x1025, 0x169a, "Acer Swift SFG16", ALC256_FIXUP_ACER_SFG16_MICMUTE_LED),
diff --git a/sound/soc/amd/renoir/acp3x-pdm-dma.c b/sound/soc/amd/renoir/acp3x-pdm-dma.c
index 95ac8c680037..a560d06097d5 100644
--- a/sound/soc/amd/renoir/acp3x-pdm-dma.c
+++ b/sound/soc/amd/renoir/acp3x-pdm-dma.c
@@ -301,9 +301,11 @@ static int acp_pdm_dma_close(struct snd_soc_component *component,
struct snd_pcm_substream *substream)
{
struct pdm_dev_data *adata = dev_get_drvdata(component->dev);
+ struct pdm_stream_instance *rtd = substream->runtime->private_data;
disable_pdm_interrupts(adata->acp_base);
adata->capture_stream = NULL;
+ kfree(rtd);
return 0;
}
diff --git a/sound/soc/amd/yc/acp6x-mach.c b/sound/soc/amd/yc/acp6x-mach.c
index c18da0915baa..67f2fee19398 100644
--- a/sound/soc/amd/yc/acp6x-mach.c
+++ b/sound/soc/amd/yc/acp6x-mach.c
@@ -643,6 +643,13 @@ static const struct dmi_system_id yc_acp_quirk_table[] = {
{
.driver_data = &acp6x_card,
.matches = {
+ DMI_MATCH(DMI_BOARD_VENDOR, "HP"),
+ DMI_MATCH(DMI_BOARD_NAME, "8EE4"),
+ }
+ },
+ {
+ .driver_data = &acp6x_card,
+ .matches = {
DMI_MATCH(DMI_BOARD_VENDOR, "MECHREVO"),
DMI_MATCH(DMI_BOARD_NAME, "MRID6"),
}
diff --git a/sound/soc/codecs/cs42l43-jack.c b/sound/soc/codecs/cs42l43-jack.c
index b719d62635a0..b83bc4de1301 100644
--- a/sound/soc/codecs/cs42l43-jack.c
+++ b/sound/soc/codecs/cs42l43-jack.c
@@ -496,7 +496,23 @@ void cs42l43_bias_sense_timeout(struct work_struct *work)
pm_runtime_put_autosuspend(priv->dev);
}
-static void cs42l43_start_load_detect(struct cs42l43_codec *priv)
+static const struct reg_sequence cs42l43_3pole_patch[] = {
+ { 0x4000, 0x00000055 },
+ { 0x4000, 0x000000AA },
+ { 0x17420, 0x8500F300 },
+ { 0x17424, 0x36003E00 },
+ { 0x4000, 0x00000000 },
+};
+
+static const struct reg_sequence cs42l43_4pole_patch[] = {
+ { 0x4000, 0x00000055 },
+ { 0x4000, 0x000000AA },
+ { 0x17420, 0x7800E600 },
+ { 0x17424, 0x36003800 },
+ { 0x4000, 0x00000000 },
+};
+
+static void cs42l43_start_load_detect(struct cs42l43_codec *priv, bool mic)
{
struct cs42l43 *cs42l43 = priv->core;
@@ -520,6 +536,15 @@ static void cs42l43_start_load_detect(struct cs42l43_codec *priv)
dev_err(priv->dev, "Load detect HP power down timed out\n");
}
+ if (mic)
+ regmap_multi_reg_write_bypassed(cs42l43->regmap,
+ cs42l43_4pole_patch,
+ ARRAY_SIZE(cs42l43_4pole_patch));
+ else
+ regmap_multi_reg_write_bypassed(cs42l43->regmap,
+ cs42l43_3pole_patch,
+ ARRAY_SIZE(cs42l43_3pole_patch));
+
regmap_update_bits(cs42l43->regmap, CS42L43_BLOCK_EN3,
CS42L43_ADC1_EN_MASK | CS42L43_ADC2_EN_MASK, 0);
regmap_update_bits(cs42l43->regmap, CS42L43_DACCNFG2, CS42L43_HP_HPF_EN_MASK, 0);
@@ -598,7 +623,7 @@ static int cs42l43_run_load_detect(struct cs42l43_codec *priv, bool mic)
reinit_completion(&priv->load_detect);
- cs42l43_start_load_detect(priv);
+ cs42l43_start_load_detect(priv, mic);
time_left = wait_for_completion_timeout(&priv->load_detect,
msecs_to_jiffies(CS42L43_LOAD_TIMEOUT_MS));
cs42l43_stop_load_detect(priv);
@@ -622,11 +647,11 @@ static int cs42l43_run_load_detect(struct cs42l43_codec *priv, bool mic)
}
switch (val & CS42L43_AMP3_RES_DET_MASK) {
- case 0x0: // low impedance
- case 0x1: // high impedance
+ case 0x0: // < 22 Ohm impedance
+ case 0x1: // < 150 Ohm impedance
+ case 0x2: // < 1000 Ohm impedance
return CS42L43_JACK_HEADPHONE;
- case 0x2: // lineout
- case 0x3: // Open circuit
+ case 0x3: // > 1000 Ohm impedance
return CS42L43_JACK_LINEOUT;
default:
return -EINVAL;
diff --git a/sound/soc/codecs/rt1320-sdw.c b/sound/soc/codecs/rt1320-sdw.c
index feecef258b65..e6142645b903 100644
--- a/sound/soc/codecs/rt1320-sdw.c
+++ b/sound/soc/codecs/rt1320-sdw.c
@@ -203,6 +203,7 @@ static const struct reg_sequence rt1320_vc_blind_write[] = {
{ 0x3fc2bfc2, 0x00 },
{ 0x3fc2bfc1, 0x00 },
{ 0x3fc2bfc0, 0x07 },
+ { 0x1000cc46, 0x00 },
{ 0x0000d486, 0x43 },
{ SDW_SDCA_CTL(FUNC_NUM_AMP, RT1320_SDCA_ENT_PDE23, RT1320_SDCA_CTL_REQ_POWER_STATE, 0), 0x00 },
{ 0x1000db00, 0x07 },
@@ -354,6 +355,7 @@ static const struct reg_sequence rt1321_blind_write[] = {
{ 0x0000d73d, 0xd7 },
{ 0x0000d73e, 0x00 },
{ 0x0000d73f, 0x10 },
+ { 0x1000cd56, 0x00 },
{ 0x3fc2dfc3, 0x00 },
{ 0x3fc2dfc2, 0x00 },
{ 0x3fc2dfc1, 0x00 },
diff --git a/sound/soc/fsl/fsl_xcvr.c b/sound/soc/fsl/fsl_xcvr.c
index a268fb81a2f8..5de93f458b56 100644
--- a/sound/soc/fsl/fsl_xcvr.c
+++ b/sound/soc/fsl/fsl_xcvr.c
@@ -223,10 +223,13 @@ static int fsl_xcvr_mode_put(struct snd_kcontrol *kcontrol,
xcvr->mode = snd_soc_enum_item_to_val(e, item[0]);
+ down_read(&card->snd_card->controls_rwsem);
fsl_xcvr_activate_ctl(dai, fsl_xcvr_arc_mode_kctl.name,
(xcvr->mode == FSL_XCVR_MODE_ARC));
fsl_xcvr_activate_ctl(dai, fsl_xcvr_earc_capds_kctl.name,
(xcvr->mode == FSL_XCVR_MODE_EARC));
+ up_read(&card->snd_card->controls_rwsem);
+
/* Allow playback for SPDIF only */
rtd = snd_soc_get_pcm_runtime(card, card->dai_link);
rtd->pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream_count =
diff --git a/sound/soc/intel/boards/sof_es8336.c b/sound/soc/intel/boards/sof_es8336.c
index fce50fd9f093..e9ee752d5ec3 100644
--- a/sound/soc/intel/boards/sof_es8336.c
+++ b/sound/soc/intel/boards/sof_es8336.c
@@ -337,6 +337,15 @@ static const struct dmi_system_id sof_es8336_quirk_table[] = {
{
.callback = sof_es8336_quirk_cb,
.matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "HUAWEI"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "BOD-WXX9"),
+ },
+ .driver_data = (void *)(SOF_ES8336_HEADPHONE_GPIO |
+ SOF_ES8336_ENABLE_DMIC)
+ },
+ {
+ .callback = sof_es8336_quirk_cb,
+ .matches = {
DMI_MATCH(DMI_SYS_VENDOR, "IP3 tech"),
DMI_MATCH(DMI_BOARD_NAME, "WN1"),
},
diff --git a/sound/soc/sof/intel/hda.c b/sound/soc/sof/intel/hda.c
index 0bb85f92e106..686ecc040867 100644
--- a/sound/soc/sof/intel/hda.c
+++ b/sound/soc/sof/intel/hda.c
@@ -1304,9 +1304,8 @@ static struct snd_soc_acpi_mach *hda_sdw_machine_select(struct snd_sof_dev *sdev
int i;
hdev = pdata->hw_pdata;
- link_mask = hdev->info.link_mask;
- if (!link_mask) {
+ if (!hdev->info.link_mask) {
dev_info(sdev->dev, "SoundWire links not enabled\n");
return NULL;
}
@@ -1337,7 +1336,7 @@ static struct snd_soc_acpi_mach *hda_sdw_machine_select(struct snd_sof_dev *sdev
* link_mask supported by hw and then go on searching
* link_adr
*/
- if (~link_mask & mach->link_mask)
+ if (~hdev->info.link_mask & mach->link_mask)
continue;
/* No need to match adr if there is no links defined */
diff --git a/sound/usb/mixer_quirks.c b/sound/usb/mixer_quirks.c
index f8eccb1c58da..cf4ccf467cb6 100644
--- a/sound/usb/mixer_quirks.c
+++ b/sound/usb/mixer_quirks.c
@@ -311,13 +311,8 @@ static int snd_audigy2nx_led_update(struct usb_mixer_interface *mixer,
if (pm.err < 0)
return pm.err;
- if (chip->usb_id == USB_ID(0x041e, 0x3042))
- err = snd_usb_ctl_msg(chip->dev,
- usb_sndctrlpipe(chip->dev, 0), 0x24,
- USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_OTHER,
- !value, 0, NULL, 0);
- /* USB X-Fi S51 Pro */
- if (chip->usb_id == USB_ID(0x041e, 0x30df))
+ if (chip->usb_id == USB_ID(0x041e, 0x3042) || /* USB X-Fi S51 */
+ chip->usb_id == USB_ID(0x041e, 0x30df)) /* USB X-Fi S51 Pro */
err = snd_usb_ctl_msg(chip->dev,
usb_sndctrlpipe(chip->dev, 0), 0x24,
USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_OTHER,
diff --git a/tools/testing/selftests/kvm/Makefile.kvm b/tools/testing/selftests/kvm/Makefile.kvm
index ba5c2b643efa..d45bf4ccb3bf 100644
--- a/tools/testing/selftests/kvm/Makefile.kvm
+++ b/tools/testing/selftests/kvm/Makefile.kvm
@@ -251,6 +251,7 @@ LINUX_TOOL_INCLUDE = $(top_srcdir)/tools/include
LINUX_TOOL_ARCH_INCLUDE = $(top_srcdir)/tools/arch/$(ARCH)/include
CFLAGS += -Wall -Wstrict-prototypes -Wuninitialized -O2 -g -std=gnu99 \
-Wno-gnu-variable-sized-type-not-at-end -MD -MP -DCONFIG_64BIT \
+ -U_FORTIFY_SOURCE \
-fno-builtin-memcmp -fno-builtin-memcpy \
-fno-builtin-memset -fno-builtin-strnlen \
-fno-stack-protector -fno-PIE -fno-strict-aliasing \
diff --git a/tools/testing/selftests/net/udpgro_fwd.sh b/tools/testing/selftests/net/udpgro_fwd.sh
index a39fdc4aa2ff..9b722c1e4b0f 100755
--- a/tools/testing/selftests/net/udpgro_fwd.sh
+++ b/tools/testing/selftests/net/udpgro_fwd.sh
@@ -162,6 +162,39 @@ run_test() {
echo " ok"
}
+run_test_csum() {
+ local -r msg="$1"
+ local -r dst="$2"
+ local csum_error_filter=UdpInCsumErrors
+ local csum_errors
+
+ printf "%-40s" "$msg"
+
+ is_ipv6 "$dst" && csum_error_filter=Udp6InCsumErrors
+
+ ip netns exec "$NS_DST" iperf3 -s -1 >/dev/null &
+ wait_local_port_listen "$NS_DST" 5201 tcp
+ local spid="$!"
+ ip netns exec "$NS_SRC" iperf3 -c "$dst" -t 2 >/dev/null
+ local retc="$?"
+ wait "$spid"
+ local rets="$?"
+ if [ "$rets" -ne 0 ] || [ "$retc" -ne 0 ]; then
+ echo " fail client exit code $retc, server $rets"
+ ret=1
+ return
+ fi
+
+ csum_errors=$(ip netns exec "$NS_DST" nstat -as "$csum_error_filter" |
+ grep "$csum_error_filter" | awk '{print $2}')
+ if [ -n "$csum_errors" ] && [ "$csum_errors" -gt 0 ]; then
+ echo " fail - csum error on receive $csum_errors, expected 0"
+ ret=1
+ return
+ fi
+ echo " ok"
+}
+
run_bench() {
local -r msg=$1
local -r dst=$2
@@ -260,6 +293,37 @@ for family in 4 6; do
ip netns exec $NS_SRC $PING -q -c 1 $OL_NET$DST_NAT >/dev/null
run_test "GRO fwd over UDP tunnel" $OL_NET$DST_NAT 10 10 $OL_NET$DST
cleanup
+
+ # force segmentation and re-aggregation
+ create_vxlan_pair
+ ip netns exec "$NS_DST" ethtool -K veth"$DST" generic-receive-offload on
+ ip netns exec "$NS_SRC" ethtool -K veth"$SRC" tso off
+ ip -n "$NS_SRC" link set dev veth"$SRC" mtu 1430
+
+ # forward to a 2nd veth pair
+ ip -n "$NS_DST" link add br0 type bridge
+ ip -n "$NS_DST" link set dev veth"$DST" master br0
+
+ # segment the aggregated TSO packet, without csum offload
+ ip -n "$NS_DST" link add veth_segment type veth peer veth_rx
+ for FEATURE in tso tx-udp-segmentation tx-checksumming; do
+ ip netns exec "$NS_DST" ethtool -K veth_segment "$FEATURE" off
+ done
+ ip -n "$NS_DST" link set dev veth_segment master br0 up
+ ip -n "$NS_DST" link set dev br0 up
+ ip -n "$NS_DST" link set dev veth_rx up
+
+ # move the lower layer IP in the last added veth
+ for ADDR in "$BM_NET_V4$DST/24" "$BM_NET_V6$DST/64"; do
+ # the dad argument will let iproute emit a unharmful warning
+ # with ipv4 addresses
+ ip -n "$NS_DST" addr del dev veth"$DST" "$ADDR"
+ ip -n "$NS_DST" addr add dev veth_rx "$ADDR" \
+ nodad 2>/dev/null
+ done
+
+ run_test_csum "GSO after GRO" "$OL_NET$DST"
+ cleanup
done
exit $ret
diff --git a/virt/kvm/eventfd.c b/virt/kvm/eventfd.c
index 0e8b5277be3b..a369b20d47f0 100644
--- a/virt/kvm/eventfd.c
+++ b/virt/kvm/eventfd.c
@@ -157,21 +157,28 @@ irqfd_shutdown(struct work_struct *work)
}
-/* assumes kvm->irqfds.lock is held */
-static bool
-irqfd_is_active(struct kvm_kernel_irqfd *irqfd)
+static bool irqfd_is_active(struct kvm_kernel_irqfd *irqfd)
{
+ /*
+ * Assert that either irqfds.lock or SRCU is held, as irqfds.lock must
+ * be held to prevent false positives (on the irqfd being active), and
+ * while false negatives are impossible as irqfds are never added back
+ * to the list once they're deactivated, the caller must at least hold
+ * SRCU to guard against routing changes if the irqfd is deactivated.
+ */
+ lockdep_assert_once(lockdep_is_held(&irqfd->kvm->irqfds.lock) ||
+ srcu_read_lock_held(&irqfd->kvm->irq_srcu));
+
return list_empty(&irqfd->list) ? false : true;
}
/*
* Mark the irqfd as inactive and schedule it for removal
- *
- * assumes kvm->irqfds.lock is held
*/
-static void
-irqfd_deactivate(struct kvm_kernel_irqfd *irqfd)
+static void irqfd_deactivate(struct kvm_kernel_irqfd *irqfd)
{
+ lockdep_assert_held(&irqfd->kvm->irqfds.lock);
+
BUG_ON(!irqfd_is_active(irqfd));
list_del_init(&irqfd->list);
@@ -217,8 +224,15 @@ irqfd_wakeup(wait_queue_entry_t *wait, unsigned mode, int sync, void *key)
seq = read_seqcount_begin(&irqfd->irq_entry_sc);
irq = irqfd->irq_entry;
} while (read_seqcount_retry(&irqfd->irq_entry_sc, seq));
- /* An event has been signaled, inject an interrupt */
- if (kvm_arch_set_irq_inatomic(&irq, kvm,
+
+ /*
+ * An event has been signaled, inject an interrupt unless the
+ * irqfd is being deassigned (isn't active), in which case the
+ * routing information may be stale (once the irqfd is removed
+ * from the list, it will stop receiving routing updates).
+ */
+ if (unlikely(!irqfd_is_active(irqfd)) ||
+ kvm_arch_set_irq_inatomic(&irq, kvm,
KVM_USERSPACE_IRQ_SOURCE_ID, 1,
false) == -EWOULDBLOCK)
schedule_work(&irqfd->inject);
@@ -585,18 +599,8 @@ kvm_irqfd_deassign(struct kvm *kvm, struct kvm_irqfd *args)
spin_lock_irq(&kvm->irqfds.lock);
list_for_each_entry_safe(irqfd, tmp, &kvm->irqfds.items, list) {
- if (irqfd->eventfd == eventfd && irqfd->gsi == args->gsi) {
- /*
- * This clearing of irq_entry.type is needed for when
- * another thread calls kvm_irq_routing_update before
- * we flush workqueue below (we synchronize with
- * kvm_irq_routing_update using irqfds.lock).
- */
- write_seqcount_begin(&irqfd->irq_entry_sc);
- irqfd->irq_entry.type = 0;
- write_seqcount_end(&irqfd->irq_entry_sc);
+ if (irqfd->eventfd == eventfd && irqfd->gsi == args->gsi)
irqfd_deactivate(irqfd);
- }
}
spin_unlock_irq(&kvm->irqfds.lock);