ASoC: Fixes for v7.2

This set of fixes is bulked out quite a bit by the inclusion of a lot of
 quirks for various x86 platforms, though there are a few driver specific
 fixes in here too.  Nothing here is terribly critical, we should be fine
 waiting for the merge window if it's too much.
 -----BEGIN PGP SIGNATURE-----
 
 iQEzBAABCgAdFiEEreZoqmdXGLWf4p/qJNaLcl1Uh9AFAmp9tZ0ACgkQJNaLcl1U
 h9DXYAf/R1QWsCP/mXjOb7M5A2KNRvOR4uIUDtbQYYRF3jibOEWgcq8eRUH40w/P
 wHKuCQVKGLyFv7g3yiGjfMccHn/CAcOtUBMarnjFWL9c465LLwNkydJAcEe3K7Vf
 XUNIMEzj7qq4rbCVouWRm3UuPOQXoPwbJxtsDIjKApPD2ml5dmmL7E5e7aC3m4hf
 RgVzWn4KUvWvr30EdiCUj/5LleysY+OgEDl8MkDm4ZJb1hcZ2wswkGkx1rILVkjR
 2ZsqUl2/HYGhYbMerhsuIfTGN9SSMYgPJ4qAWoPhAmfhZHNCwGYGvMg/1Uo3JjB+
 /Wmk4NA0yoW9msrCqmFu9ZNDfAQ54A==
 =3J8V
 -----END PGP SIGNATURE-----

Merge tag 'asoc-fix-v7.2-rc7' of https://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound into for-linus

ASoC: Fixes for v7.2

This set of fixes is bulked out quite a bit by the inclusion of a lot of
quirks for various x86 platforms, though there are a few driver specific
fixes in here too.  Nothing here is terribly critical, we should be fine
waiting for the merge window if it's too much.
This commit is contained in:
Takashi Iwai 2026-08-13 15:32:36 +02:00
commit a92ee0d248
401 changed files with 5983 additions and 1967 deletions

View File

@ -171,6 +171,7 @@ Boris Brezillon <bbrezillon@kernel.org> <b.brezillon@overkiz.com>
Boris Brezillon <bbrezillon@kernel.org> <boris.brezillon@bootlin.com>
Boris Brezillon <bbrezillon@kernel.org> <boris.brezillon@free-electrons.com>
Brendan Higgins <brendan.higgins@linux.dev> <brendanhiggins@google.com>
Brendan Jackman <brendan.jackman@linux.dev> <jackmanb@google.com>
Brian Avery <b.avery@hp.com>
Brian Cain <bcain@kernel.org> <brian.cain@oss.qualcomm.com>
Brian Cain <bcain@kernel.org> <bcain@quicinc.com>
@ -233,6 +234,8 @@ Daniel Lezcano <daniel.lezcano@kernel.org> <daniel.lezcano@linexp.org>
Daniel Lezcano <daniel.lezcano@kernel.org> <dlezcano@fr.ibm.com>
Daniel Thompson <danielt@kernel.org> <daniel.thompson@linaro.org>
Daniele Alessandrelli <daniele.alessandrelli@gmail.com> <daniele.alessandrelli@intel.com>
Danila Tikhonov <danila@mainlining.org> <danila@jiaxyga.com>
Danila Tikhonov <danila@mainlining.org> <JIaxyga@protonmail.com>
Danilo Krummrich <dakr@kernel.org> <dakr@redhat.com>
David Brownell <david-b@pacbell.net>
David Collins <quic_collinsd@quicinc.com> <collinsd@codeaurora.org>

View File

@ -2239,9 +2239,12 @@ IO Latency
~~~~~~~~~~
This is a cgroup v2 controller for IO workload protection. You provide a group
with a latency target, and if the average latency exceeds that target the
controller will throttle any peers that have a lower latency target than the
protected workload.
with a latency target, and if the group misses its target the controller will
throttle any peers that have a lower latency target than the protected
workload. How a miss is detected depends on the device: on rotational devices
the average latency over the window must exceed the target, while on
non-rotational devices a miss is counted once enough of the IOs in the window
individually exceed the target.
The limits are only applied at the peer level in the hierarchy. This means that
in the diagram below, only groups A, B, and C will influence each other, and
@ -2258,10 +2261,12 @@ So the ideal way to configure this is to set io.latency in groups A, B, and C.
Generally you do not want to set a value lower than the latency your device
supports. Experiment to find the value that works best for your workload.
Start at higher than the expected latency for your device and, with
blkcg_debug_stats enabled, watch the avg_lat value in io.stat for your
workload group to get an idea of the latency you see during normal operation.
Use the avg_lat value as a basis for your real setting, setting at 10-15%
higher than the value in io.stat.
blkcg_debug_stats enabled, observe io.stat for your workload group to get an
idea of the latency you see during normal operation. On rotational devices,
use the avg_lat value as a basis for your real setting, setting it 10-15%
higher. On non-rotational devices io.stat reports no average latency; set
the target based on your device and use the missed/total fields to verify it
is being met.
How IO Latency Throttling Works
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@ -2303,19 +2308,36 @@ IO Latency Interface Files
the blkcg_debug_stats module parameter is enabled (it is disabled by
default).
The reported latency fields depend on the device. Rotational devices
report avg_lat and win; non-rotational devices report missed and total
instead. missed and total are live counters for the current window and
may change between reads.
depth
This is the current queue depth for the group.
avg_lat
This is an exponential moving average with a decay rate of 1/exp
bound by the sampling interval. The decay rate interval can be
calculated by multiplying the win value in io.stat by the
corresponding number of samples based on the win value.
(Rotational devices only.) This is an exponential moving
average with a decay rate of 1/exp bound by the sampling
interval. The decay rate interval can be calculated by
multiplying the win value in io.stat by the corresponding number
of samples based on the win value.
win
The sampling window size in milliseconds. This is the minimum
duration of time between evaluation events. Windows only elapse
with IO activity. Idle periods extend the most recent window.
(Rotational devices only.) The sampling window size in
milliseconds. This is the minimum duration of time between
evaluation events. Windows only elapse with IO activity. Idle
periods extend the most recent window.
missed
(Non-rotational devices only.) The number of IOs in the
current window whose latency exceeded the target. A group is
considered to be missing its target once missed reaches a
certain ratio of total.
total
(Non-rotational devices only.) The total number of IOs
accounted in the current window.
IO Priority
~~~~~~~~~~~

View File

@ -8169,6 +8169,11 @@ Kernel parameters
q = USB_QUIRK_FORCE_ONE_CONFIG (Device
claims zero configurations,
forcing to 1);
r = USB_QUIRK_WINDOWS_CONFIG_REQ_SIZE (Device
fails during initialization when asked for
9-bytes configuration descriptor request.
Ask for 255-bytes request instead to mirror
Windows' behavior);
Example: quirks=0781:5580:bk,0a5c:5834:gij
usbhid.mousepoll=

View File

@ -118,12 +118,16 @@ attribute-sets:
doc: >-
The number of seconds after which a keep alive message is sent to the
peer
checks:
max: 86400
-
name: keepalive-timeout
type: u32
doc: >-
The number of seconds from the last activity after which the peer is
assumed dead
checks:
max: 86400
-
name: del-reason
type: u32

View File

@ -57,3 +57,40 @@ Basic development tools (git, gcc, make, editors) should not be listed.
Example::
Assisted-by: Claude:claude-3-opus coccinelle sparse
Procedure for finding and fixing bugs
=====================================
When an AI assistant is used to find and fix bugs, it **MUST** follow at least
these steps:
1. Before starting, read the whole process documentation listed above, as well
as any other document mentioned in the request. Do not rely on isolated
parts found by keyword search.
2. Note the commit ID and Locate a bug as instructed.
3. For any bug found that is not trivial, verify that it looks real by
attempting to create a reproducer to demonstrate it. Lacking it may cause
the report to be ignored, as many unverified bug reports sent to maintainers
happen to be invalid. Stop here if it finally looks wrong.
4. Write a fix for the bug. This part is not optional: except in a few very
rare cases, an AI assistant able to find a bug is able to fix it. Note that
fixes written in the same session as used to find the bug will generally
lead to better and more accurate fixes as the LLM's reasoning context
remains present.
5. Build and verify that the fix works either using the reproducer or by
re-running a complete analysis; drop any fix that doesn't work and try
another one. The fix must not add build warnings and must pass the
checkpatch.pl checks (see submitting-patches.rst).
6. Commit the working fix with a detailed message describing the problem, the
solution and a Fixes tag. Do not add a Signed-off-by tag, and add an
Assisted-by tag, as described above.
7. Identify the maintainers and lists using scripts/get_maintainer.pl.
Documentation/process/security-bugs.rst shows how to do that.
8. Indicate what could not be done. If the fix could not be built or tested, or
if no reproducer could be produced, say so explicitly: maintainers currently
waste too much time analyzing unverified reports and untested fixes.
9. Read Documentation/process/threat-model.rst to determine whether the bug is
a vulnerability or a regular bug, and leave the result to the reporter for
review (the assistant must never send anything itself). Regular bugs are
submitted as described in Documentation/process/submitting-patches.rst,
vulnerabilities as described in Documentation/process/security-bugs.rst.

View File

@ -18,6 +18,10 @@ information is helpful. The following information are absolutely necessary in
**any** security bug report:
* **affected kernel version range**: with no version indication, your report
will not be processed. Note that a time-dependent version such as "latest
mainline" is not acceptable. A stable identifier such as a commit ID or an
exact version is required. Versions designating kernels not coming from
kernel.org (such as distro kernels) are meaningless to maintainers and
will not be processed. A significant part of reports are for bugs that
have already been fixed, so it is extremely important that vulnerabilities
are verified on recent versions (development tree or latest stable
@ -225,6 +229,28 @@ there is no need to consume a maintainer's time with an unimportant report. If
the issue is clearly trivial and publicly discoverable, you should report it
directly to the public mailing lists.
At the very least, when using an AI assistant to find and report bugs, make the
assistant read this file and threat-model.rst before proceeding, and have it
follow the procedure described in coding-assistants.rst: work on an up-to-date
mainline tree and note the commit ID, verify the bug is real, write a fix,
build it warning-free and checkpatch-clean, commit it with a Fixes tag, and
identify the maintainers with get_maintainer.pl.
On top of that procedure, the AI assistant **MUST**:
1. Prepare a plain-text report explaining the problem. It must contain the
four items listed at the top of this file as absolutely necessary: the
affected version or commit ID noted while following the procedure above,
the description of the problem, the reproducer or its status, and the
triggering conditions.
2. Start the report with a temporary section listing the recipients' addresses
(maintainers+list for the patch, maintainers only for the report and
reproducer), and with instructions reminding the reporter to check that
their email client is properly setup (see email-clients.rst), and leave it
to the reporter to remove that temporary section.
A more detailed process is covered at https://github.com/masoncl/kres.git.
Sending the report
------------------

View File

@ -98,11 +98,11 @@ measures whose purpose is to avoid crossing a security boundary when certain
classes of bugs are found, but a failure of these extra protections do not
constitute a vulnerability alone.
What does not constitute a security bug
---------------------------------------
What classes of problems are not considered vulnerabilities
-----------------------------------------------------------
In the Linux kernel's threat model, the following classes of problems are
**NOT** considered as Linux Kernel security bugs. However, when it is believed
**NOT** considered Linux Kernel vulnerabilities. However, when it is believed
that the kernel could do better, they should be reported, so that they can be
reviewed and fixed where reasonably possible, but they will be handled as any
regular bug:
@ -111,8 +111,8 @@ regular bug:
* outdated kernels and particularly end-of-life branches are out of the scope
of the kernel's threat model: administrators are responsible for keeping
their system up to date. For a bug to qualify as a security bug, it must be
demonstrated that it affects actively maintained versions.
their system up to date. For a bug to qualify as a vulnerability, it must
be demonstrated that it affects actively maintained versions.
* build-level: changes to the kernel configuration that are explicitly
documented as lowering the security level (e.g. ``CONFIG_NOMMU``), or
@ -178,9 +178,6 @@ regular bug:
involving tens of millions of threads, tens of thousands of CPUs,
unrealistic CPU frequencies, RAM sizes or disk capacities, network speeds).
* issues whose reproduction requires hardware modification or emulation,
including fake USB devices that pretend to be another one.
* as well as issues that can be triggered at a cost that is orders of
magnitude higher than the expected benefits (e.g. fully functional keyboard
emulator only to retrieve 7 uninitialized bytes in a structure, or
@ -208,19 +205,27 @@ regular bug:
messages.
* Leaks of kernel memory addresses/pointers do not constitute an immediately
exploitable vector and are not security bugs, though they must be reported
and fixed.
exploitable vector and are not vulnerabilities, though they must be
reported and fixed.
* **Crafted file system images**:
* **Non-conforming devices and media**:
Drivers are implemented against a specification. When a device or a storage
medium violates the specification its driver was written against, the
resulting misbehaviour is a regular bug to be fixed, not a vulnerability,
unless the driver is specifically documented as being hardened against
hostile inputs. The following are therefore not considered vulnerabilities:
* bugs triggered by mounting a corrupted or maliciously crafted file system
image are generally not security bugs, as the kernel assumes the underlying
storage media is under the administrator's control, unless the filesystem
driver is specifically documented as being hardened against untrusted media.
* issues that are resolved, mitigated, or detected by running a filesystem
image: mounting a block device is a privileged operation (see above), and
the administrator is responsible for the media they mount. This includes
issues that are resolved, mitigated, or detected by running a filesystem
consistency check (fsck) on the image prior to mounting.
* bugs whose reproduction requires hardware modification or emulation,
including fake USB devices that pretend to be another one, or devices
reporting values outside their documented ranges.
* **Physical access**:
Issues that require physical access to the machine, hardware modification, or
@ -232,4 +237,4 @@ regular bug:
* **Functional and performance regressions**:
Any issue that can be mitigated by setting proper permissions and limits
doesn't qualify as a security bug.
doesn't qualify as a vulnerability.

View File

@ -2676,6 +2676,8 @@ F: drivers/irqchip/irq-aspeed-i2c-ic.c
ARM/ASPEED MACHINE SUPPORT
M: Joel Stanley <joel@jms.id.au>
M: Andrew Jeffery <andrew@codeconstruct.com.au>
R: Ryan Chen <ryan_chen@aspeedtech.com>
R: Billy Tsai <billy_tsai@aspeedtech.com>
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
L: linux-aspeed@lists.ozlabs.org (moderated for non-subscribers)
S: Supported
@ -2881,7 +2883,7 @@ W: http://www.armlinux.org.uk/
F: arch/arm/include/asm/hardware/dec21285.h
F: arch/arm/mach-footbridge/
ARM/FREESCALE IMX / MXC ARM ARCHITECTURE
ARM/FREESCALE IMX / MXC / LAYERSCAPE ARM ARCHITECTURE
M: Frank Li <Frank.Li@nxp.com>
M: Sascha Hauer <s.hauer@pengutronix.de>
R: Pengutronix Kernel Team <kernel@pengutronix.de>
@ -2895,22 +2897,11 @@ F: Documentation/devicetree/bindings/firmware/nxp*
F: arch/arm/boot/dts/nxp/
F: arch/arm64/boot/dts/freescale/
X: Documentation/devicetree/bindings/media/i2c/
X: arch/arm64/boot/dts/freescale/fsl-*
X: arch/arm64/boot/dts/freescale/qoriq-*
X: drivers/media/i2c/
N: imx
N: mxs
N: \bmxc[^\d]
ARM/FREESCALE LAYERSCAPE ARM ARCHITECTURE
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/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: Frank Li <Frank.Li@nxp.com>
M: Sascha Hauer <s.hauer@pengutronix.de>
@ -10134,6 +10125,11 @@ F: drivers/base/firmware_loader/
F: rust/kernel/firmware.rs
F: include/linux/firmware.h
FIXED-LAYOUT NVMEM LAYOUT DRIVER
M: Mathieu Dubois-Briand <mathieu.dubois-briand@bootlin.com>
S: Maintained
F: drivers/nvmem/layouts/fixed-layout.c
FLEXTIMER FTM-QUADDEC DRIVER
M: Patrick Havelange <patrick.havelange@essensium.com>
L: linux-iio@vger.kernel.org
@ -11743,6 +11739,7 @@ F: drivers/net/ethernet/hisilicon/hibmcge/
HISILICON NETWORK SUBSYSTEM DRIVER
M: Jian Shen <shenjian15@huawei.com>
M: Jijie Shao <shaojijie@huawei.com>
L: netdev@vger.kernel.org
S: Maintained
W: http://www.hisilicon.com
@ -17160,7 +17157,7 @@ M: Andrew Morton <akpm@linux-foundation.org>
M: Vlastimil Babka <vbabka@kernel.org>
R: Suren Baghdasaryan <surenb@google.com>
R: Michal Hocko <mhocko@suse.com>
R: Brendan Jackman <jackmanb@google.com>
R: Brendan Jackman <brendan.jackman@linux.dev>
R: Johannes Weiner <hannes@cmpxchg.org>
R: Zi Yan <ziy@nvidia.com>
L: linux-mm@kvack.org
@ -17846,7 +17843,7 @@ F: drivers/net/wireless/microchip/
MICROCHIP ZL3073X DRIVER
M: Ivan Vecera <ivecera@redhat.com>
M: Prathosh Satish <Prathosh.Satish@microchip.com>
M: Min Li <min.li@microchip.com>
L: netdev@vger.kernel.org
S: Supported
F: Documentation/devicetree/bindings/dpll/microchip,zl30731.yaml

View File

@ -2,7 +2,7 @@
VERSION = 7
PATCHLEVEL = 2
SUBLEVEL = 0
EXTRAVERSION = -rc6
EXTRAVERSION = -rc7
NAME = Baby Opossum Posse
# *DOCUMENTATION*

View File

@ -141,7 +141,7 @@ axi@18000000 {
/* PCIe Controller 2 */
<0x00014000 0 &gic GIC_SPI 138 IRQ_TYPE_LEVEL_HIGH>,
<0x00014000 1 &gic GIC_SPI 138 IRQ_TYPE_LEVEL_HIGH>,
<0x00014000 1 &gic GIC_SPI 139 IRQ_TYPE_LEVEL_HIGH>,
<0x00014000 2 &gic GIC_SPI 140 IRQ_TYPE_LEVEL_HIGH>,
<0x00014000 3 &gic GIC_SPI 141 IRQ_TYPE_LEVEL_HIGH>,
<0x00014000 4 &gic GIC_SPI 142 IRQ_TYPE_LEVEL_HIGH>,

View File

@ -26,7 +26,7 @@ memory@0 {
nvram@1c080000 {
compatible = "brcm,nvram";
reg = <0x1c080000 0x180000>;
reg = <0x1c080000 0x100000>;
et2macaddr: et2macaddr {
#nvmem-cell-cells = <1>;

View File

@ -32,6 +32,7 @@ static int npcm7xx_smp_boot_secondary(unsigned int cpu,
goto out;
}
gcr_base = of_iomap(gcr_np, 0);
of_node_put(gcr_np);
if (!gcr_base) {
pr_err("could not iomap gcr");
ret = -ENOMEM;
@ -60,6 +61,7 @@ static void __init npcm7xx_smp_prepare_cpus(unsigned int max_cpus)
return;
}
scu_base = of_iomap(scu_np, 0);
of_node_put(scu_np);
if (!scu_base) {
pr_err("could not iomap scu");
return;

View File

@ -678,8 +678,6 @@ IRQ_TYPE_LEVEL_LOW)>,
<GIC_PPI 11 (GIC_CPU_MASK_SIMPLE(4) |
IRQ_TYPE_LEVEL_LOW)>,
<GIC_PPI 10 (GIC_CPU_MASK_SIMPLE(4) |
IRQ_TYPE_LEVEL_LOW)>,
<GIC_PPI 12 (GIC_CPU_MASK_SIMPLE(4) |
IRQ_TYPE_LEVEL_LOW)>;
};

View File

@ -2559,7 +2559,7 @@ mdss_dsi1_phy: phy@ae97000 {
"dsi_pll";
clocks = <&dispcc DISP_CC_MDSS_AHB_CLK>,
<&rpmhcc RPMH_CXO_CLK>;
<&bi_tcxo_div2>;
clock-names = "iface",
"ref";

View File

@ -1876,7 +1876,7 @@ &config_noc SLAVE_QUP_0 QCOM_ICC_TAG_ALWAYS>,
spi0: spi@b80000 {
compatible = "qcom,geni-spi";
reg = <0x0 0x00b80000 0x0 0x4000>;
interrupts = <GIC_SPI 1052 IRQ_TYPE_LEVEL_HIGH>;
interrupts = <GIC_ESPI 92 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&gcc GCC_QUPV3_WRAP0_S0_CLK>;
clock-names = "se";
interconnects = <&clk_virt MASTER_QUP_CORE_0 QCOM_ICC_TAG_ALWAYS
@ -1903,7 +1903,7 @@ &config_noc SLAVE_QUP_0 QCOM_ICC_TAG_ALWAYS>,
i2c1: i2c@b84000 {
compatible = "qcom,geni-i2c";
reg = <0x0 0x00b84000 0x0 0x4000>;
interrupts = <GIC_SPI 1053 IRQ_TYPE_LEVEL_HIGH>;
interrupts = <GIC_ESPI 93 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&gcc GCC_QUPV3_WRAP0_S1_CLK>;
clock-names = "se";
interconnects = <&clk_virt MASTER_QUP_CORE_0 QCOM_ICC_TAG_ALWAYS
@ -1930,7 +1930,7 @@ &config_noc SLAVE_QUP_0 QCOM_ICC_TAG_ALWAYS>,
spi1: spi@b84000 {
compatible = "qcom,geni-spi";
reg = <0x0 0x00b84000 0x0 0x4000>;
interrupts = <GIC_SPI 1053 IRQ_TYPE_LEVEL_HIGH>;
interrupts = <GIC_ESPI 93 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&gcc GCC_QUPV3_WRAP0_S1_CLK>;
clock-names = "se";
interconnects = <&clk_virt MASTER_QUP_CORE_0 QCOM_ICC_TAG_ALWAYS
@ -1957,7 +1957,7 @@ &config_noc SLAVE_QUP_0 QCOM_ICC_TAG_ALWAYS>,
i2c2: i2c@b88000 {
compatible = "qcom,geni-i2c";
reg = <0x0 0x00b88000 0x0 0x4000>;
interrupts = <GIC_SPI 1054 IRQ_TYPE_LEVEL_HIGH>;
interrupts = <GIC_ESPI 94 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&gcc GCC_QUPV3_WRAP0_S2_CLK>;
clock-names = "se";
interconnects = <&clk_virt MASTER_QUP_CORE_0 QCOM_ICC_TAG_ALWAYS
@ -1984,7 +1984,7 @@ &config_noc SLAVE_QUP_0 QCOM_ICC_TAG_ALWAYS>,
spi2: spi@b88000 {
compatible = "qcom,geni-spi";
reg = <0x0 0x00b88000 0x0 0x4000>;
interrupts = <GIC_SPI 1054 IRQ_TYPE_LEVEL_HIGH>;
interrupts = <GIC_ESPI 94 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&gcc GCC_QUPV3_WRAP0_S2_CLK>;
clock-names = "se";
interconnects = <&clk_virt MASTER_QUP_CORE_0 QCOM_ICC_TAG_ALWAYS
@ -2011,7 +2011,7 @@ &config_noc SLAVE_QUP_0 QCOM_ICC_TAG_ALWAYS>,
uart2: serial@b88000 {
compatible = "qcom,geni-uart";
reg = <0x0 0x00b88000 0x0 0x4000>;
interrupts = <GIC_SPI 1054 IRQ_TYPE_LEVEL_HIGH>;
interrupts = <GIC_ESPI 94 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&gcc GCC_QUPV3_WRAP0_S2_CLK>;
clock-names = "se";
interconnects = <&clk_virt MASTER_QUP_CORE_0 QCOM_ICC_TAG_ALWAYS
@ -2056,7 +2056,7 @@ &config_noc SLAVE_QUP_0 QCOM_ICC_TAG_ALWAYS>,
spi3: spi@b8c000 {
compatible = "qcom,geni-spi";
reg = <0x0 0x00b8c000 0x0 0x4000>;
interrupts = <GIC_SPI 1055 IRQ_TYPE_LEVEL_HIGH>;
interrupts = <GIC_ESPI 95 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&gcc GCC_QUPV3_WRAP0_S3_CLK>;
clock-names = "se";
interconnects = <&clk_virt MASTER_QUP_CORE_0 QCOM_ICC_TAG_ALWAYS
@ -2110,7 +2110,7 @@ &config_noc SLAVE_QUP_0 QCOM_ICC_TAG_ALWAYS>,
spi4: spi@b90000 {
compatible = "qcom,geni-spi";
reg = <0x0 0x00b90000 0x0 0x4000>;
interrupts = <GIC_SPI 1056 IRQ_TYPE_LEVEL_HIGH>;
interrupts = <GIC_ESPI 96 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&gcc GCC_QUPV3_WRAP0_S4_CLK>;
clock-names = "se";
interconnects = <&clk_virt MASTER_QUP_CORE_0 QCOM_ICC_TAG_ALWAYS
@ -2164,7 +2164,7 @@ &config_noc SLAVE_QUP_0 QCOM_ICC_TAG_ALWAYS>,
spi5: spi@b94000 {
compatible = "qcom,geni-spi";
reg = <0x0 0x00b94000 0x0 0x4000>;
interrupts = <GIC_SPI 1057 IRQ_TYPE_LEVEL_HIGH>;
interrupts = <GIC_ESPI 97 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&gcc GCC_QUPV3_WRAP0_S5_CLK>;
clock-names = "se";
interconnects = <&clk_virt MASTER_QUP_CORE_0 QCOM_ICC_TAG_ALWAYS
@ -2191,7 +2191,7 @@ &config_noc SLAVE_QUP_0 QCOM_ICC_TAG_ALWAYS>,
i2c6: i2c@b98000 {
compatible = "qcom,geni-i2c";
reg = <0x0 0x00b98000 0x0 0x4000>;
interrupts = <GIC_SPI 1058 IRQ_TYPE_LEVEL_HIGH>;
interrupts = <GIC_ESPI 98 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&gcc GCC_QUPV3_WRAP0_S6_CLK>;
clock-names = "se";
interconnects = <&clk_virt MASTER_QUP_CORE_0 QCOM_ICC_TAG_ALWAYS
@ -2218,7 +2218,7 @@ &config_noc SLAVE_QUP_0 QCOM_ICC_TAG_ALWAYS>,
spi6: spi@b98000 {
compatible = "qcom,geni-spi";
reg = <0x0 0x00b98000 0x0 0x4000>;
interrupts = <GIC_SPI 1058 IRQ_TYPE_LEVEL_HIGH>;
interrupts = <GIC_ESPI 98 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&gcc GCC_QUPV3_WRAP0_S6_CLK>;
clock-names = "se";
interconnects = <&clk_virt MASTER_QUP_CORE_0 QCOM_ICC_TAG_ALWAYS
@ -2245,7 +2245,7 @@ &config_noc SLAVE_QUP_0 QCOM_ICC_TAG_ALWAYS>,
i2c7: i2c@b9c000 {
compatible = "qcom,geni-i2c";
reg = <0x0 0x00b9c000 0x0 0x4000>;
interrupts = <GIC_SPI 1059 IRQ_TYPE_LEVEL_HIGH>;
interrupts = <GIC_ESPI 99 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&gcc GCC_QUPV3_WRAP0_S7_CLK>;
clock-names = "se";
interconnects = <&clk_virt MASTER_QUP_CORE_0 QCOM_ICC_TAG_ALWAYS
@ -2272,7 +2272,7 @@ &config_noc SLAVE_QUP_0 QCOM_ICC_TAG_ALWAYS>,
spi7: spi@b9c000 {
compatible = "qcom,geni-spi";
reg = <0x0 0x00b9c000 0x0 0x4000>;
interrupts = <GIC_SPI 1059 IRQ_TYPE_LEVEL_HIGH>;
interrupts = <GIC_ESPI 99 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&gcc GCC_QUPV3_WRAP0_S7_CLK>;
clock-names = "se";
interconnects = <&clk_virt MASTER_QUP_CORE_0 QCOM_ICC_TAG_ALWAYS
@ -6874,9 +6874,9 @@ apps_smmu: iommu@15000000 {
pcie_smmu: iommu@15480000 {
compatible = "arm,smmu-v3";
reg = <0x0 0x15480000 0x0 0x20000>;
interrupts = <GIC_SPI 964 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 962 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 960 IRQ_TYPE_LEVEL_HIGH>;
interrupts = <GIC_ESPI 4 IRQ_TYPE_LEVEL_HIGH>,
<GIC_ESPI 2 IRQ_TYPE_LEVEL_HIGH>,
<GIC_ESPI 0 IRQ_TYPE_LEVEL_HIGH>;
interrupt-names = "eventq", "cmdq-sync", "gerror";
dma-coherent;
#iommu-cells = <1>;

View File

@ -7384,6 +7384,7 @@ intc: interrupt-controller@17a00000 {
interrupt-controller;
#redistributor-regions = <1>;
redistributor-stride = <0x0 0x20000>;
#address-cells = <0>;
};
watchdog@17c10000 {

View File

@ -47,6 +47,8 @@ &gmu {
&gpu {
compatible = "qcom,adreno-43030c00", "qcom,adreno";
iommus = <&adreno_smmu 0 0x0>;
nvmem-cells = <&gpu_speed_bin>;
nvmem-cell-names = "speed_bin";

View File

@ -637,7 +637,7 @@ embedded-controller@38 {
compatible = "huawei,gaokun3-ec";
reg = <0x38>;
interrupts-extended = <&tlmm 107 IRQ_TYPE_LEVEL_LOW>;
interrupts-extended = <&tlmm 103 IRQ_TYPE_LEVEL_LOW>;
#address-cells = <1>;
#size-cells = <0>;

View File

@ -5356,7 +5356,7 @@ pdc: interrupt-controller@b220000 {
<211 699 1>,
<212 705 1>,
<213 450 1>,
<214 643 1>,
<214 643 2>,
<216 646 5>,
<221 390 5>,
<226 700 3>,
@ -5379,7 +5379,7 @@ pdc: interrupt-controller@b220000 {
<252 798 1>,
<253 765 1>,
<254 763 1>,
<255 454 1>,
<255 454 3>,
<258 139 1>,
<259 786 2>,
<261 370 2>,

View File

@ -347,6 +347,10 @@ &cdsp_pas {
status = "okay";
};
&cluster_sleep_0 {
arm,psci-suspend-param = <0x41008244>;
};
&gcc {
protected-clocks = <GCC_QSPI_CORE_CLK>,
<GCC_QSPI_CORE_CLK_SRC>,

View File

@ -7091,8 +7091,8 @@ sram@14680000 {
ranges = <0 0 0x14680000 0x2c000>;
ipa_modem_tables: modem-tables@8000 {
reg = <0x8000 0x2000>;
ipa_modem_tables: modem-tables@3000 {
reg = <0x3000 0x2000>;
};
};

View File

@ -7,8 +7,6 @@
#include <linux/ptdump.h>
DECLARE_STATIC_KEY_FALSE(arm64_ptdump_lock_key);
#ifdef CONFIG_PTDUMP
#include <linux/mm_types.h>

View File

@ -49,8 +49,6 @@
#define NO_CONT_MAPPINGS BIT(1)
#define NO_EXEC_MAPPINGS BIT(2) /* assumes FEAT_HPDS is not used */
DEFINE_STATIC_KEY_FALSE(arm64_ptdump_lock_key);
u64 kimage_voffset __ro_after_init;
EXPORT_SYMBOL(kimage_voffset);
@ -1864,8 +1862,7 @@ int pmd_clear_huge(pmd_t *pmdp)
return 1;
}
static int __pmd_free_pte_page(pmd_t *pmdp, unsigned long addr,
bool acquire_mmap_lock)
int pmd_free_pte_page(pmd_t *pmdp, unsigned long addr)
{
pte_t *table;
pmd_t pmd;
@ -1877,25 +1874,13 @@ static int __pmd_free_pte_page(pmd_t *pmdp, unsigned long addr,
return 1;
}
/* See comment in pud_free_pmd_page for static key logic */
table = pte_offset_kernel(pmdp, addr);
pmd_clear(pmdp);
__flush_tlb_kernel_pgtable(addr);
if (static_branch_unlikely(&arm64_ptdump_lock_key) && acquire_mmap_lock) {
mmap_read_lock(&init_mm);
mmap_read_unlock(&init_mm);
}
pte_free_kernel(NULL, table);
return 1;
}
int pmd_free_pte_page(pmd_t *pmdp, unsigned long addr)
{
/* If ptdump is walking the pagetables, acquire init_mm.mmap_lock */
return __pmd_free_pte_page(pmdp, addr, /* acquire_mmap_lock = */ true);
}
int pud_free_pmd_page(pud_t *pudp, unsigned long addr)
{
pmd_t *table;
@ -1911,36 +1896,16 @@ int pud_free_pmd_page(pud_t *pudp, unsigned long addr)
}
table = pmd_offset(pudp, addr);
/*
* Our objective is to prevent ptdump from reading a PMD table which has
* been freed. In this race, if pud_free_pmd_page observes the key on
* (which got flipped by ptdump) then the mmap lock sequence here will,
* as a result of the mmap write lock/unlock sequence in ptdump, give
* us the correct synchronization. If not, this means that ptdump has
* yet not started walking the pagetables - the sequence of barriers
* issued by __flush_tlb_kernel_pgtable() guarantees that ptdump will
* observe an empty PUD.
*/
pud_clear(pudp);
__flush_tlb_kernel_pgtable(addr);
if (static_branch_unlikely(&arm64_ptdump_lock_key)) {
mmap_read_lock(&init_mm);
mmap_read_unlock(&init_mm);
}
pmdp = table;
next = addr;
end = addr + PUD_SIZE;
do {
if (pmd_present(pmdp_get(pmdp)))
/*
* PMD has been isolated, so ptdump won't see it. No
* need to acquire init_mm.mmap_lock.
*/
__pmd_free_pte_page(pmdp, next, /* acquire_mmap_lock = */ false);
pmd_free_pte_page(pmdp, next);
} while (pmdp++, next += PMD_SIZE, next != end);
pud_clear(pudp);
__flush_tlb_kernel_pgtable(addr);
pmd_free(NULL, table);
return 1;
}

View File

@ -283,13 +283,6 @@ void note_page_flush(struct ptdump_state *pt_st)
note_page(pt_st, 0, -1, pte_val(pte_zero));
}
static void arm64_ptdump_walk_pgd(struct ptdump_state *st, struct mm_struct *mm)
{
static_branch_inc(&arm64_ptdump_lock_key);
ptdump_walk_pgd(st, mm, NULL);
static_branch_dec(&arm64_ptdump_lock_key);
}
void ptdump_walk(struct seq_file *s, struct ptdump_info *info)
{
unsigned long end = ~0UL;
@ -318,7 +311,7 @@ void ptdump_walk(struct seq_file *s, struct ptdump_info *info)
}
};
arm64_ptdump_walk_pgd(&st.ptdump, info->mm);
ptdump_walk_pgd(&st.ptdump, info->mm, NULL);
}
static void __init ptdump_initialize(void)
@ -360,7 +353,7 @@ bool ptdump_check_wx(void)
}
};
arm64_ptdump_walk_pgd(&st.ptdump, &init_mm);
ptdump_walk_pgd(&st.ptdump, &init_mm, NULL);
if (st.wx_pages || st.uxn_pages) {
pr_warn("Checked W+X mappings: FAILED, %lu W+X pages found, %lu non-UXN pages found\n",

View File

@ -39,6 +39,8 @@
#include <asm/processor.h>
.section .data
/* The MMU requires a page aligned page directory. */
.align 12
.global swapper_pg_dir
swapper_pg_dir:
.space PAGE_SIZE

View File

@ -699,7 +699,7 @@ static ssize_t lparcfg_write(struct file *file, const char __user * buf,
if (!firmware_has_feature(FW_FEATURE_SPLPAR))
return -EINVAL;
if (count > sizeof(kbuf))
if (count == 0 || count > sizeof(kbuf))
return -EINVAL;
if (copy_from_user(kbuf, buf, count))

View File

@ -230,10 +230,17 @@ static long papr_phy_attest_create_handle(struct papr_phy_attest_io_block __user
return -ENOMEM;
if (copy_from_user(&params->cmd, ulc,
sizeof(struct papr_phy_attest_io_block)))
sizeof(struct papr_phy_attest_io_block))) {
kfree(params);
return -EFAULT;
}
params->cmd_len = be32_to_cpu(params->cmd.length);
if (params->cmd_len == 0 || params->cmd_len > sizeof(params->cmd)) {
kfree(params);
return -EINVAL;
}
seq = (struct papr_rtas_sequence) {
.begin = phy_attest_sequence_begin,
.end = phy_attest_sequence_end,
@ -246,6 +253,9 @@ static long papr_phy_attest_create_handle(struct papr_phy_attest_io_block __user
&papr_phy_attest_handle_ops,
"[papr-physical-attestation]");
if (fd < 0)
kfree(params);
return fd;
}

View File

@ -132,7 +132,7 @@ static int pseries_pci_sriov_enable(struct pci_dev *pdev, u16 num_vfs)
/* First integer stores max config */
max_config_vfs = of_read_number(&max_vfs[0], 1);
if (max_config_vfs < num_vfs && num_vfs > MAX_VFS_FOR_MAP_PE) {
if (max_config_vfs < num_vfs || num_vfs > MAX_VFS_FOR_MAP_PE) {
dev_err(&pdev->dev,
"Num VFs %x > %x Configurable VFs\n",
num_vfs, (num_vfs > MAX_VFS_FOR_MAP_PE) ?

View File

@ -440,6 +440,7 @@ struct kvm_vcpu_arch {
bool skey_enabled;
/* Indicator if the access registers have been loaded from guest */
bool acrs_loaded;
bool initialized;
struct kvm_s390_pv_vcpu pv;
union diag318_info diag318_info;
struct kvm_s390_mmu_cache *mc;

View File

@ -755,13 +755,15 @@ int dat_cond_set_storage_key(struct kvm_s390_mmu_cache *mmc, union asce asce, gf
return rc;
}
int dat_reset_reference_bit(union asce asce, gfn_t gfn)
int dat_reset_reference_bit(union asce asce, gfn_t gfn, union skey *skey)
{
union pgste pgste, old;
union crste *crstep;
union pte *ptep;
int rc;
skey->skey = 0;
rc = dat_entry_walk(NULL, gfn, asce, DAT_WALK_ANY, TABLE_TYPE_PAGE_TABLE, &crstep, &ptep);
if (rc)
return rc;
@ -771,21 +773,23 @@ int dat_reset_reference_bit(union asce asce, gfn_t gfn)
if (!crste.h.fc || !crste.s.fc1.pr)
return 0;
return page_reset_referenced(large_crste_to_phys(*crstep, gfn));
skey->skey = page_reset_referenced(large_crste_to_phys(*crstep, gfn)) << 1;
return 0;
}
old = pgste_get_lock(ptep);
pgste = old;
if (!ptep->h.i) {
rc = page_reset_referenced(pte_origin(*ptep));
pgste.hr = rc >> 1;
skey->skey = page_reset_referenced(pte_origin(*ptep)) << 1;
pgste.hr = skey->r;
}
rc |= (pgste.gr << 1) | pgste.gc;
skey->r |= pgste.gr;
skey->c |= pgste.gc;
pgste.gr = 0;
dat_update_ptep_sd(old, pgste, ptep);
pgste_set_unlock(ptep, pgste);
return rc;
return 0;
}
static long dat_reset_skeys_pte(union pte *ptep, gfn_t gfn, gfn_t next, struct dat_walk *walk)
@ -846,6 +850,7 @@ static long _dat_slot_pte(union pte *ptep, gfn_t gfn, gfn_t next, struct dat_wal
struct slot_priv *p = walk->priv;
union crste dummy = { .val = p->token };
union pte new_pte, pte = READ_ONCE(*ptep);
union pgste pgste;
new_pte = _PTE_TOK(dummy.tok.type, dummy.tok.par);
@ -853,7 +858,11 @@ static long _dat_slot_pte(union pte *ptep, gfn_t gfn, gfn_t next, struct dat_wal
if (pte.val == new_pte.val)
return 0;
dat_ptep_xchg(ptep, new_pte, gfn, walk->asce, false);
pgste = pgste_get_lock(ptep);
pgste = __dat_ptep_xchg(ptep, pgste, new_pte, gfn, walk->asce, false);
pgste.cmma_d = 0;
pgste_set_unlock(ptep, pgste);
return 0;
}

View File

@ -537,7 +537,7 @@ int dat_set_storage_key(struct kvm_s390_mmu_cache *mc, union asce asce, gfn_t gf
union skey skey, bool nq);
int dat_cond_set_storage_key(struct kvm_s390_mmu_cache *mmc, union asce asce, gfn_t gfn,
union skey skey, union skey *oldkey, bool nq, bool mr, bool mc);
int dat_reset_reference_bit(union asce asce, gfn_t gfn);
int dat_reset_reference_bit(union asce asce, gfn_t gfn, union skey *skey);
long dat_reset_skeys(union asce asce, gfn_t start);
unsigned long dat_get_ptval(struct page_table *table, struct ptval_param param);

View File

@ -91,9 +91,9 @@ int kvm_s390_faultin_gfn(struct kvm_vcpu *vcpu, struct kvm *kvm, struct guest_fa
/* Access outside memory, addressing exception. */
if (is_noslot_pfn(f->pfn))
return PGM_ADDRESSING;
/* Signal pending: try again. */
if (f->pfn == KVM_PFN_ERR_SIGPENDING)
return -EAGAIN;
/* Fatal signal pending: bail out. */
if (is_sigpending_pfn(f->pfn))
return -EINTR;
/* Check if it's read-only memory; don't try to actually handle that case. */
if (f->pfn == KVM_PFN_ERR_RO_FAULT)
return -EOPNOTSUPP;

View File

@ -45,13 +45,16 @@ static struct kvm_s390_gib *gib;
static int sca_ext_call_pending(struct kvm_vcpu *vcpu, int *src_id)
{
struct esca_block *sca = vcpu->kvm->arch.sca;
union esca_sigp_ctrl sigp_ctrl = sca->cpu[vcpu->vcpu_id].sigp_ctrl;
union esca_sigp_ctrl sigp_ctrl;
if (!kvm_s390_test_cpuflags(vcpu, CPUSTAT_ECALL_PEND))
return 0;
if (kvm_is_ucontrol(vcpu->kvm))
return 0;
BUG_ON(!kvm_s390_use_sca_entries());
sigp_ctrl = sca->cpu[vcpu->vcpu_id].sigp_ctrl;
if (src_id)
*src_id = sigp_ctrl.scn;
@ -60,13 +63,16 @@ static int sca_ext_call_pending(struct kvm_vcpu *vcpu, int *src_id)
static int sca_inject_ext_call(struct kvm_vcpu *vcpu, int src_id)
{
struct esca_block *sca = vcpu->kvm->arch.sca;
union esca_sigp_ctrl *sigp_ctrl = &sca->cpu[vcpu->vcpu_id].sigp_ctrl;
union esca_sigp_ctrl old_val, new_val = {.scn = src_id, .c = 1};
struct esca_block *sca = vcpu->kvm->arch.sca;
union esca_sigp_ctrl *sigp_ctrl;
int expect, rc;
BUG_ON(!kvm_s390_use_sca_entries());
if (kvm_is_ucontrol(vcpu->kvm))
return -EINVAL;
sigp_ctrl = &sca->cpu[vcpu->vcpu_id].sigp_ctrl;
old_val = READ_ONCE(*sigp_ctrl);
old_val.c = 0;
@ -84,10 +90,13 @@ static int sca_inject_ext_call(struct kvm_vcpu *vcpu, int src_id)
static void sca_clear_ext_call(struct kvm_vcpu *vcpu)
{
struct esca_block *sca = vcpu->kvm->arch.sca;
union esca_sigp_ctrl *sigp_ctrl = &sca->cpu[vcpu->vcpu_id].sigp_ctrl;
union esca_sigp_ctrl *sigp_ctrl;
if (!kvm_s390_use_sca_entries())
if (!kvm_s390_use_sca_entries() || !vcpu->arch.initialized || kvm_is_ucontrol(vcpu->kvm))
return;
/* Initialize after the above check, to prevent going out of bounds */
sigp_ctrl = &sca->cpu[vcpu->vcpu_id].sigp_ctrl;
kvm_s390_clear_cpuflags(vcpu, CPUSTAT_ECALL_PEND);
WRITE_ONCE(sigp_ctrl->value, 0);

View File

@ -571,7 +571,7 @@ static int kvm_s390_keyop(struct kvm_s390_mmu_cache *mc, struct kvm *kvm, int op
switch (op) {
case KVM_S390_KEYOP_SSKE:
r = dat_cond_set_storage_key(mc, asce, gfn, skey, &skey, 0, 0, 0);
if (r >= 0)
if (r == 0 || r == 1)
return skey.skey;
break;
case KVM_S390_KEYOP_ISKE:
@ -580,14 +580,14 @@ static int kvm_s390_keyop(struct kvm_s390_mmu_cache *mc, struct kvm *kvm, int op
return skey.skey;
break;
case KVM_S390_KEYOP_RRBE:
r = dat_reset_reference_bit(asce, gfn);
if (r > 0)
return r << 1;
r = dat_reset_reference_bit(asce, gfn, &skey);
if (!r)
return skey.skey;
break;
default:
return -EINVAL;
}
return r;
return r > 0 ? -EFAULT : r;
}
/* Section: device related */
@ -1219,8 +1219,8 @@ static void kvm_s390_sync_request_broadcast(struct kvm *kvm, int req)
/*
* Must be called with kvm->srcu held to avoid races on memslots, and with
* kvm->slots_lock to avoid races with ourselves, kvm_s390_vm_stop_migration(),
* and kvm_s390_get_cmma_bits().
* kvm->slots_arch_lock to avoid races with ourselves,
* kvm_s390_vm_stop_migration(), and kvm_s390_get_cmma_bits().
*/
static int kvm_s390_vm_start_migration(struct kvm *kvm)
{
@ -1265,7 +1265,7 @@ static int kvm_s390_vm_start_migration(struct kvm *kvm)
}
/*
* Must be called with kvm->slots_lock to avoid races with ourselves,
* Must be called with kvm->slots_arch_lock to avoid races with ourselves,
* kvm_s390_vm_start_migration() and kvm_s390_get_cmma_bits().
*/
static int kvm_s390_vm_stop_migration(struct kvm *kvm)
@ -1300,7 +1300,9 @@ static int kvm_s390_vm_set_migration(struct kvm *kvm,
{
int res = -ENXIO;
mutex_lock(&kvm->slots_lock);
guard(srcu)(&kvm->srcu);
guard(mutex)(&kvm->slots_arch_lock);
switch (attr->attr) {
case KVM_S390_VM_MIGRATION_START:
res = kvm_s390_vm_start_migration(kvm);
@ -1311,7 +1313,6 @@ static int kvm_s390_vm_set_migration(struct kvm *kvm,
default:
break;
}
mutex_unlock(&kvm->slots_lock);
return res;
}
@ -2214,7 +2215,7 @@ static int kvm_s390_get_skeys(struct kvm *kvm, struct kvm_s390_skeys *args)
}
kvfree(keys);
return r;
return r <= 0 ? r : -EFAULT;
}
static int kvm_s390_set_skeys(struct kvm *kvm, struct kvm_s390_skeys *args)
@ -2276,7 +2277,7 @@ static int kvm_s390_set_skeys(struct kvm *kvm, struct kvm_s390_skeys *args)
kvm_s390_free_mmu_cache(mc);
out:
kvfree(keys);
return r;
return r <= 0 ? r : -EFAULT;
}
/*
@ -2386,7 +2387,7 @@ static int kvm_s390_set_cmma_bits(struct kvm *kvm,
set_bit(GMAP_FLAG_USES_CMM, &kvm->arch.gmap->flags);
return r;
return r <= 0 ? r : -EFAULT;
}
/**
@ -2934,6 +2935,9 @@ int kvm_arch_vm_ioctl(struct file *filp, unsigned int ioctl, unsigned long arg)
case KVM_S390_INTERRUPT: {
struct kvm_s390_interrupt s390int;
r = -EINVAL;
if (kvm_is_ucontrol(kvm))
break;
r = -EFAULT;
if (copy_from_user(&s390int, argp, sizeof(s390int)))
break;
@ -2998,9 +3002,8 @@ int kvm_arch_vm_ioctl(struct file *filp, unsigned int ioctl, unsigned long arg)
r = -EFAULT;
if (copy_from_user(&args, argp, sizeof(args)))
break;
mutex_lock(&kvm->slots_lock);
r = kvm_s390_get_cmma_bits(kvm, &args);
mutex_unlock(&kvm->slots_lock);
scoped_guard(mutex, &kvm->slots_arch_lock)
r = kvm_s390_get_cmma_bits(kvm, &args);
if (!r) {
r = copy_to_user(argp, &args, sizeof(args));
if (r)
@ -3014,9 +3017,9 @@ int kvm_arch_vm_ioctl(struct file *filp, unsigned int ioctl, unsigned long arg)
r = -EFAULT;
if (copy_from_user(&args, argp, sizeof(args)))
break;
mutex_lock(&kvm->slots_lock);
mutex_lock(&kvm->slots_arch_lock);
r = kvm_s390_set_cmma_bits(kvm, &args);
mutex_unlock(&kvm->slots_lock);
mutex_unlock(&kvm->slots_arch_lock);
break;
}
case KVM_S390_PV_COMMAND: {
@ -3247,7 +3250,8 @@ static void kvm_s390_crypto_init(struct kvm *kvm)
static void sca_dispose(struct kvm *kvm)
{
free_pages_exact(kvm->arch.sca, sizeof(*kvm->arch.sca));
if (kvm->arch.sca)
free_pages_exact(kvm->arch.sca, sizeof(*kvm->arch.sca));
kvm->arch.sca = NULL;
}
@ -3461,7 +3465,7 @@ static void sca_del_vcpu(struct kvm_vcpu *vcpu)
{
struct esca_block *sca = vcpu->kvm->arch.sca;
if (!kvm_s390_use_sca_entries())
if (!kvm_s390_use_sca_entries() || !vcpu->arch.initialized)
return;
clear_bit_inv(vcpu->vcpu_id, (unsigned long *)sca->mcn);
@ -3481,8 +3485,8 @@ static void sca_add_vcpu(struct kvm_vcpu *vcpu)
if (!kvm_s390_use_sca_entries())
return;
WRITE_ONCE(sca->cpu[vcpu->vcpu_id].sda, virt_to_phys(vcpu->arch.sie_block));
set_bit_inv(vcpu->vcpu_id, (unsigned long *)sca->mcn);
sca->cpu[vcpu->vcpu_id].sda = virt_to_phys(vcpu->arch.sie_block);
}
static int sca_can_add_vcpu(struct kvm *kvm, unsigned int id)
@ -3613,6 +3617,9 @@ void kvm_arch_vcpu_postcreate(struct kvm_vcpu *vcpu)
if (test_kvm_facility(vcpu->kvm, 74) || vcpu->kvm->arch.user_instr0 ||
vcpu->kvm->arch.user_operexec)
vcpu->arch.sie_block->ictl |= ICTL_OPEREXC;
/* Pairs with smp_load_acquire() in kvm_arch_vcpu_ioctl_run() and kvm_arch_vcpu_ioctl() */
smp_store_release(&vcpu->arch.initialized, true);
}
static bool kvm_has_pckmo_subfunc(struct kvm *kvm, unsigned long nr)
@ -3674,7 +3681,8 @@ static void kvm_s390_vcpu_crypto_setup(struct kvm_vcpu *vcpu)
void kvm_s390_vcpu_unsetup_cmma(struct kvm_vcpu *vcpu)
{
free_page((unsigned long)phys_to_virt(vcpu->arch.sie_block->cbrlo));
if (vcpu->arch.sie_block->cbrlo)
free_page((unsigned long)phys_to_virt(vcpu->arch.sie_block->cbrlo));
vcpu->arch.sie_block->cbrlo = 0;
}
@ -3792,21 +3800,21 @@ int kvm_arch_vcpu_precreate(struct kvm *kvm, unsigned int id)
return 0;
}
DEFINE_FREE(sie_page, struct sie_page *, if (_T) free_page((unsigned long)(_T)))
int kvm_arch_vcpu_create(struct kvm_vcpu *vcpu)
{
struct sie_page *sie_page;
struct kvm_s390_mmu_cache *mc __free(kvm_s390_mmu_cache) = NULL;
struct sie_page *sie_page __free(sie_page) = NULL;
int rc;
BUILD_BUG_ON(sizeof(struct sie_page) != 4096);
vcpu->arch.mc = kvm_s390_new_mmu_cache();
if (!vcpu->arch.mc)
mc = kvm_s390_new_mmu_cache();
if (!mc)
return -ENOMEM;
sie_page = (struct sie_page *) get_zeroed_page(GFP_KERNEL_ACCOUNT);
if (!sie_page) {
kvm_s390_free_mmu_cache(vcpu->arch.mc);
vcpu->arch.mc = NULL;
if (!sie_page)
return -ENOMEM;
}
vcpu->arch.sie_block = &sie_page->sie_block;
vcpu->arch.sie_block->itdba = virt_to_phys(&sie_page->itdb);
@ -3848,10 +3856,9 @@ int kvm_arch_vcpu_create(struct kvm_vcpu *vcpu)
vcpu->run->kvm_valid_regs |= KVM_SYNC_FPRS;
if (kvm_is_ucontrol(vcpu->kvm)) {
rc = -ENOMEM;
vcpu->arch.gmap = gmap_new_child(vcpu->kvm->arch.gmap, -1UL);
if (!vcpu->arch.gmap)
goto out_free_sie_block;
return -ENOMEM;
}
VM_EVENT(vcpu->kvm, 3, "create cpu %d at 0x%p, sie block at 0x%p",
@ -3859,20 +3866,19 @@ int kvm_arch_vcpu_create(struct kvm_vcpu *vcpu)
trace_kvm_s390_create_vcpu(vcpu->vcpu_id, vcpu, vcpu->arch.sie_block);
rc = kvm_s390_vcpu_setup(vcpu);
if (rc)
goto out_ucontrol_uninit;
if (rc) {
if (kvm_is_ucontrol(vcpu->kvm)) {
scoped_guard(spinlock, &vcpu->kvm->arch.gmap->children_lock)
gmap_remove_child(vcpu->arch.gmap);
vcpu->arch.gmap = gmap_put(vcpu->arch.gmap);
}
return rc;
}
vcpu->arch.mc = no_free_ptr(mc);
sie_page = NULL;
kvm_s390_update_topology_change_report(vcpu->kvm, 1);
return 0;
out_ucontrol_uninit:
if (kvm_is_ucontrol(vcpu->kvm)) {
gmap_remove_child(vcpu->arch.gmap);
vcpu->arch.gmap = gmap_put(vcpu->arch.gmap);
}
out_free_sie_block:
free_page((unsigned long)(vcpu->arch.sie_block));
return rc;
}
int kvm_arch_vcpu_runnable(struct kvm_vcpu *vcpu)
@ -5039,6 +5045,10 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu)
kvm_run->kvm_dirty_regs & ~KVM_SYNC_S390_VALID_FIELDS)
return -EINVAL;
/* Pairs with smp_store_release() in kvm_arch_vcpu_postcreate() */
if (!smp_load_acquire(&vcpu->arch.initialized))
return -EINVAL;
vcpu_load(vcpu);
if (guestdbg_exit_pending(vcpu)) {
@ -5447,6 +5457,8 @@ long kvm_arch_vcpu_unlocked_ioctl(struct file *filp, unsigned int ioctl,
struct kvm_s390_interrupt s390int;
struct kvm_s390_irq s390irq = {};
if (kvm_is_ucontrol(vcpu->kvm))
return -EINVAL;
if (copy_from_user(&s390int, argp, sizeof(s390int)))
return -EFAULT;
if (s390int_to_s390irq(&s390int, &s390irq))
@ -5523,6 +5535,10 @@ long kvm_arch_vcpu_ioctl(struct file *filp,
long r;
u16 rc, rrc;
/* Pairs with smp_store_release() in kvm_arch_vcpu_postcreate() */
if (!smp_load_acquire(&vcpu->arch.initialized))
return -EINVAL;
vcpu_load(vcpu);
switch (ioctl) {
@ -5794,14 +5810,30 @@ int kvm_arch_prepare_memory_region(struct kvm *kvm,
return 0;
}
static long cmma_d_count_pte(union pte *ptep, gfn_t gfn, gfn_t next, struct dat_walk *walk)
{
union pgste pgste;
pgste = pgste_get_lock(ptep);
if (pgste.cmma_d) {
pgste.cmma_d = 0;
atomic64_dec(walk->priv);
}
pgste_set_unlock(ptep, pgste);
return 0;
}
void kvm_arch_commit_memory_region(struct kvm *kvm,
struct kvm_memory_slot *old,
const struct kvm_memory_slot *new,
enum kvm_mr_change change)
{
struct kvm_s390_mmu_cache *mc = NULL;
const struct dat_walk_ops ops = { .pte_entry = cmma_d_count_pte, };
struct kvm_s390_mmu_cache *mc __free(kvm_s390_mmu_cache) = NULL;
int rc = 0;
guard(mutex)(&kvm->slots_arch_lock);
if (change == KVM_MR_FLAGS_ONLY)
return;
@ -5812,6 +5844,12 @@ void kvm_arch_commit_memory_region(struct kvm *kvm,
}
scoped_guard(write_lock, &kvm->mmu_lock) {
if (kvm->arch.migration_mode && kvm->arch.use_cmma && old) {
_dat_walk_gfn_range(old->base_gfn, old->base_gfn + old->npages,
kvm->arch.gmap->asce, &ops, DAT_WALK_IGN_HOLES,
&kvm->arch.cmma_dirty_pages);
}
switch (change) {
case KVM_MR_DELETE:
rc = dat_delete_slot(mc, kvm->arch.gmap->asce, old->base_gfn, old->npages);
@ -5833,7 +5871,6 @@ void kvm_arch_commit_memory_region(struct kvm *kvm,
out:
if (rc)
pr_warn("failed to commit memory region\n");
kvm_s390_free_mmu_cache(mc);
return;
}

View File

@ -289,6 +289,7 @@ static int handle_iske(struct kvm_vcpu *vcpu)
static int handle_rrbe(struct kvm_vcpu *vcpu)
{
unsigned long gaddr;
union skey skey;
int reg1, reg2;
int rc;
@ -307,12 +308,12 @@ static int handle_rrbe(struct kvm_vcpu *vcpu)
gaddr = kvm_s390_logical_to_effective(vcpu, gaddr);
gaddr = kvm_s390_real_to_abs(vcpu, gaddr);
scoped_guard(read_lock, &vcpu->kvm->mmu_lock)
rc = dat_reset_reference_bit(vcpu->arch.gmap->asce, gpa_to_gfn(gaddr));
rc = dat_reset_reference_bit(vcpu->arch.gmap->asce, gpa_to_gfn(gaddr), &skey);
if (rc > 0)
return kvm_s390_inject_program_int(vcpu, rc);
if (rc < 0)
return rc;
kvm_s390_set_psw_cc(vcpu, rc);
kvm_s390_set_psw_cc(vcpu, (skey.skey >> 1) & 3);
return 0;
}
@ -1260,8 +1261,9 @@ static int handle_essa(struct kvm_vcpu *vcpu)
/* Retry the ESSA instruction */
kvm_s390_retry_instr(vcpu);
} else {
scoped_guard(read_lock, &vcpu->kvm->mmu_lock)
i = __do_essa(vcpu, orc);
scoped_guard(mutex, &vcpu->kvm->slots_arch_lock)
scoped_guard(read_lock, &vcpu->kvm->mmu_lock)
i = __do_essa(vcpu, orc);
if (i < 0)
return i;
/* Account for the possible extra cbrl entry */

View File

@ -244,6 +244,24 @@ static void kvm_s390_clear_pv_state(struct kvm *kvm)
kvm->arch.pv.stor_var = NULL;
}
static void kvm_s390_pv_dispose_cpu(struct kvm_vcpu *vcpu, bool free_stor_base)
{
if (free_stor_base)
free_pages(vcpu->arch.pv.stor_base, get_order(uv_info.guest_cpu_stor_len));
free_page((unsigned long)sida_addr(vcpu->arch.sie_block));
vcpu->arch.sie_block->pv_handle_cpu = 0;
vcpu->arch.sie_block->pv_handle_config = 0;
memset(&vcpu->arch.pv, 0, sizeof(vcpu->arch.pv));
vcpu->arch.sie_block->sdf = 0;
/*
* The sidad field (for sdf == 2) is now the gbea field (for sdf == 0).
* Use the reset value of gbea to avoid leaking the kernel pointer of
* the just freed sida.
*/
vcpu->arch.sie_block->gbea = 1;
kvm_make_request(KVM_REQ_TLB_FLUSH, vcpu);
}
int kvm_s390_pv_destroy_cpu(struct kvm_vcpu *vcpu, u16 *rc, u16 *rrc)
{
int cc;
@ -258,24 +276,9 @@ int kvm_s390_pv_destroy_cpu(struct kvm_vcpu *vcpu, u16 *rc, u16 *rrc)
WARN_ONCE(cc, "protvirt destroy cpu failed rc %x rrc %x", *rc, *rrc);
/* Intended memory leak for something that should never happen. */
if (!cc)
free_pages(vcpu->arch.pv.stor_base,
get_order(uv_info.guest_cpu_stor_len));
kvm_s390_pv_dispose_cpu(vcpu, !cc);
free_page((unsigned long)sida_addr(vcpu->arch.sie_block));
vcpu->arch.sie_block->pv_handle_cpu = 0;
vcpu->arch.sie_block->pv_handle_config = 0;
memset(&vcpu->arch.pv, 0, sizeof(vcpu->arch.pv));
vcpu->arch.sie_block->sdf = 0;
/*
* The sidad field (for sdf == 2) is now the gbea field (for sdf == 0).
* Use the reset value of gbea to avoid leaking the kernel pointer of
* the just freed sida.
*/
vcpu->arch.sie_block->gbea = 1;
kvm_make_request(KVM_REQ_TLB_FLUSH, vcpu);
return cc ? EIO : 0;
return cc ? -EIO : 0;
}
int kvm_s390_pv_create_cpu(struct kvm_vcpu *vcpu, u16 *rc, u16 *rrc)
@ -319,9 +322,7 @@ int kvm_s390_pv_create_cpu(struct kvm_vcpu *vcpu, u16 *rc, u16 *rrc)
uvcb.header.rrc);
if (cc) {
u16 dummy;
kvm_s390_pv_destroy_cpu(vcpu, &dummy, &dummy);
kvm_s390_pv_dispose_cpu(vcpu, true);
return -EIO;
}
@ -809,7 +810,7 @@ static int unpack_one(struct kvm *kvm, unsigned long addr, u64 tweak,
return -EAGAIN;
}
if (ret && ret != -EAGAIN)
if (ret && ret != -EAGAIN && ret != -EINTR)
KVM_UV_EVENT(kvm, 3, "PROTVIRT VM UNPACK: failed addr %llx with rc %x rrc %x",
uvcb.gaddr, *rc, *rrc);
return ret;

View File

@ -937,6 +937,8 @@ SYM_CODE_START(paranoid_entry)
IBRS_ENTER save_reg=%r15
UNTRAIN_RET_FROM_CALL
HANDLE_INTR_SAFERET 8(%rsp)
RET
SYM_CODE_END(paranoid_entry)
@ -1039,6 +1041,11 @@ SYM_CODE_START(error_entry)
movl %ecx, %eax /* zero extend */
cmpq %rax, RIP+8(%rsp)
je .Lbstep_iret
VALIDATE_UNRET_END
HANDLE_INTR_SAFERET 8(%rsp)
cmpq $.Lgs_change, RIP+8(%rsp)
jne .Lerror_entry_done_lfence
@ -1057,7 +1064,6 @@ SYM_CODE_START(error_entry)
FENCE_SWAPGS_KERNEL_ENTRY
CALL_DEPTH_ACCOUNT
leaq 8(%rsp), %rax /* return pt_regs pointer */
VALIDATE_UNRET_END
RET
.Lbstep_iret:

View File

@ -1858,7 +1858,7 @@ struct kvm_x86_ops {
* Can potentially get non-canonical addresses through INVLPGs, which
* the implementation may choose to ignore if appropriate.
*/
void (*flush_tlb_gva)(struct kvm_vcpu *vcpu, gva_t addr);
void (*flush_tlb_gva)(struct kvm_vcpu *vcpu, gva_t addr, bool *full);
/*
* Flush any TLB entries created by the guest. Like tlb_flush_gva(),

View File

@ -12,6 +12,7 @@
#include <asm/msr-index.h>
#include <asm/unwind_hints.h>
#include <asm/percpu.h>
#include <asm/ptrace-abi.h>
/*
* Call depth tracking for Intel SKL CPUs to address the RSB underflow
@ -176,6 +177,50 @@
add $(BITS_PER_LONG/8), %_ASM_SP; \
lfence;
/*
* Helper for detecting if an interrupt occurred at an unsafe location within
* Safe-RET. If Safe-RET is interrupted after the CALL or LEA the RSB may get
* poisoned by the interrupt handler.
*
* The Safe-RET sequence is:
*
* CALL
* LEA 8(%RSP), %RSP
* RET
*
* The two CMPs below check whether RIP points to after the CALL or after the
* LEA.
*
* The LFENCE below is to address this particular speculation case:
*
* 1. Userspace runs and poisons the BTB around the safe-RET routine
*
* 2. Userspace triggers some kind of exception
*
* 3. Kernel executes error_entry() and mis-speculates the branch into thinking
* it actually came from kernel space
*
* 4. The kernel then further mis-speculates that the exception occurred due
* to an interrupted safe-RET
*
* 5. The handle_interrupted_saferet() routine speculatively executes and
* speculatively does a safe-RET. But this is unsafe since it was never
* untrained.
*
* The LFENCE fixes this by ensuring step 5 is never reached speculatively.
* Note that this LFENCE only occurs if safe-RET was actually interrupted (so
* it's outside of the normal path).
*/
#define __HANDLE_INTR_SAFERET(name, pt_regs) \
cmpq $(name), RIP+pt_regs; \
jb 1f; \
cmpq $(name)+5, RIP+pt_regs; \
ja 1f; \
lfence; \
leaq pt_regs, %rdi; \
call handle_interrupted_saferet; \
1:
#ifdef __ASSEMBLER__
/*
@ -293,6 +338,14 @@
#define UNTRAIN_RET_FROM_CALL \
__UNTRAIN_RET X86_FEATURE_ENTRY_IBPB, __stringify(RESET_CALL_DEPTH_FROM_CALL)
.macro HANDLE_INTR_SAFERET pt_regs
#ifdef CONFIG_MITIGATION_SRSO
ALTERNATIVE_2 "", \
__stringify(__HANDLE_INTR_SAFERET(srso_safe_ret, \pt_regs)), X86_FEATURE_SRSO, \
__stringify(__HANDLE_INTR_SAFERET(srso_alias_safe_ret, \pt_regs)), X86_FEATURE_SRSO_ALIAS
#endif
.endm
.macro CALL_DEPTH_ACCOUNT
#ifdef CONFIG_MITIGATION_CALL_DEPTH_TRACKING
@ -625,6 +678,10 @@ static __always_inline void x86_idle_clear_cpu_buffers(void)
x86_clear_cpu_buffers();
}
void srso_safe_ret(void);
void srso_alias_safe_ret(void);
void handle_interrupted_saferet(struct pt_regs *regs);
#endif /* __ASSEMBLER__ */
#endif /* _ASM_X86_NOSPEC_BRANCH_H_ */

View File

@ -3775,3 +3775,42 @@ void __warn_thunk(void)
{
WARN_ONCE(1, "Unpatched return thunk in use. This should not happen!\n");
}
#ifdef CONFIG_MITIGATION_SRSO
/*
* Called during exception/interrupt entry if interrupted during the
* safe-RET sequence. The safe-RET sequence consists of 3 instructions:
*
* CALL
* LEA 8(%RSP), %RSP
* RET
*
* An interrupt after the CALL or after the LEA could potentially lead
* to branch predictor poisoning and results in the sequence not being
* able to be safely resumed.
*
* Therefore, modify the regs state as if the remaining part of the
* safe-RET sequence executed so the interrupt returns back to the
* desired return target, instead of the to the safe-RET sequence.
*/
void noinstr handle_interrupted_saferet(struct pt_regs *regs)
{
unsigned long rip = regs->ip;
if (rip == (unsigned long) srso_safe_ret ||
rip == (unsigned long) srso_alias_safe_ret) {
/* Modify stack pointer as if LEA executed: */
regs->sp += 8;
}
/*
* Adjust registers as if RET executed:
*
* 1. Read the return address off the stack and into rIP:
*/
regs->ip = *(unsigned long *)(regs->sp);
/* 2. Pop rIP off the stack: */
regs->sp += 8;
}
#endif /* CONFIG_MITIGATION_SRSO */

View File

@ -2266,10 +2266,10 @@ void mcheck_cpu_init(struct cpuinfo_x86 *c)
mca_cfg.initialized = 1;
__mcheck_cpu_setup_timer();
__mcheck_cpu_init_generic();
__mcheck_cpu_init_vendor(c);
__mcheck_cpu_init_prepare_banks();
__mcheck_cpu_setup_timer();
cr4_set_bits(X86_CR4_MCE);
}

View File

@ -1974,6 +1974,7 @@ int kvm_hv_vcpu_flush_tlb(struct kvm_vcpu *vcpu)
u64 entries[KVM_HV_TLB_FLUSH_FIFO_SIZE];
int i, j, count;
gva_t gva;
bool full = false;
if (!tdp_enabled || !hv_vcpu)
return -EINVAL;
@ -1982,7 +1983,7 @@ int kvm_hv_vcpu_flush_tlb(struct kvm_vcpu *vcpu)
count = kfifo_out(&tlb_flush_fifo->entries, entries, KVM_HV_TLB_FLUSH_FIFO_SIZE);
for (i = 0; i < count; i++) {
for (i = 0; i < count && !full; i++) {
if (entries[i] == KVM_HV_TLB_FLUSHALL_ENTRY)
goto out_flush_all;
@ -1991,11 +1992,11 @@ int kvm_hv_vcpu_flush_tlb(struct kvm_vcpu *vcpu)
* pages to flush.
*/
gva = entries[i] & PAGE_MASK;
for (j = 0; j < (entries[i] & ~PAGE_MASK) + 1; j++) {
for (j = 0; j < (entries[i] & ~PAGE_MASK) + 1 && !full; j++) {
if (is_noncanonical_invlpg_address(gva + j * PAGE_SIZE, vcpu))
continue;
kvm_x86_call(flush_tlb_gva)(vcpu, gva + j * PAGE_SIZE);
kvm_x86_call(flush_tlb_gva)(vcpu, gva + j * PAGE_SIZE, &full);
}
++vcpu->stat.tlb_flush;

View File

@ -2442,6 +2442,9 @@ static union kvm_mmu_page_role kvm_mmu_child_role(u64 *sptep, bool direct,
role.direct = direct;
role.passthrough = 0;
WARN_ON_ONCE(role.invalid);
role.invalid = 0;
/*
* If the guest has 4-byte PTEs then that means it's using 32-bit,
* 2-level, non-PAE paging. KVM shadows such guests with PAE paging
@ -6652,7 +6655,7 @@ void kvm_mmu_invalidate_addr(struct kvm_vcpu *vcpu, struct kvm_mmu *mmu,
if (is_noncanonical_invlpg_address(addr, vcpu))
return;
kvm_x86_call(flush_tlb_gva)(vcpu, addr);
kvm_x86_call(flush_tlb_gva)(vcpu, addr, NULL);
}
if (!mmu->sync_spte)

View File

@ -97,6 +97,8 @@ static u64 sev_supported_vmsa_features __ro_after_init;
static u8 sev_enc_bit;
static DECLARE_RWSEM(sev_deactivate_lock);
static DEFINE_MUTEX(sev_bitmap_lock);
/* Protects kvm_sev_info's enc_context_owner, mirror_vms and mirror_entry. */
static DEFINE_MUTEX(sev_mirror_lock);
unsigned int max_sev_asid;
static unsigned int min_sev_asid;
static unsigned int max_sev_es_asid;
@ -2018,7 +2020,6 @@ static void sev_migrate_from(struct kvm *dst_kvm, struct kvm *src_kvm)
dst->asid = src->asid;
dst->handle = src->handle;
dst->pages_locked = src->pages_locked;
dst->enc_context_owner = src->enc_context_owner;
dst->es_active = src->es_active;
dst->vmsa_features = src->vmsa_features;
@ -2026,11 +2027,12 @@ static void sev_migrate_from(struct kvm *dst_kvm, struct kvm *src_kvm)
src->active = false;
src->handle = 0;
src->pages_locked = 0;
src->enc_context_owner = NULL;
src->es_active = false;
list_cut_before(&dst->regions_list, &src->regions_list, &src->regions_list);
mutex_lock(&sev_mirror_lock);
/*
* If this VM has mirrors, "transfer" each mirror's refcount of the
* source to the destination (this KVM). The caller holds a reference
@ -2047,12 +2049,15 @@ static void sev_migrate_from(struct kvm *dst_kvm, struct kvm *src_kvm)
* If this VM is a mirror, remove the old mirror from the owners list
* and add the new mirror to the list.
*/
if (is_mirroring_enc_context(dst_kvm)) {
struct kvm_sev_info *owner_sev_info = to_kvm_sev_info(dst->enc_context_owner);
if (is_mirroring_enc_context(src_kvm)) {
struct kvm_sev_info *owner_sev_info = to_kvm_sev_info(src->enc_context_owner);
dst->enc_context_owner = src->enc_context_owner;
src->enc_context_owner = NULL;
list_del(&src->mirror_entry);
list_add_tail(&dst->mirror_entry, &owner_sev_info->mirror_vms);
}
mutex_unlock(&sev_mirror_lock);
kvm_for_each_vcpu(i, dst_vcpu, dst_kvm) {
dst_svm = to_svm(dst_vcpu);
@ -2871,11 +2876,14 @@ int sev_vm_copy_enc_context_from(struct kvm *kvm, unsigned int source_fd)
* disappear until we're done with it
*/
source_sev = to_kvm_sev_info(source_kvm);
kvm_get_kvm(source_kvm);
list_add_tail(&mirror_sev->mirror_entry, &source_sev->mirror_vms);
/* Set enc_context_owner and copy its encryption context over */
mutex_lock(&sev_mirror_lock);
kvm_get_kvm(source_kvm);
list_add_tail(&mirror_sev->mirror_entry, &source_sev->mirror_vms);
mirror_sev->enc_context_owner = source_kvm;
mutex_unlock(&sev_mirror_lock);
mirror_sev->active = true;
mirror_sev->asid = source_sev->asid;
mirror_sev->fd = source_sev->fd;
@ -2963,11 +2971,19 @@ void sev_vm_destroy(struct kvm *kvm)
* Note, mirror VMs don't support registering encrypted regions.
*/
if (is_mirroring_enc_context(kvm)) {
struct kvm *owner_kvm = sev->enc_context_owner;
struct kvm *owner_kvm;
mutex_lock(&owner_kvm->lock);
mutex_lock(&sev_mirror_lock);
owner_kvm = sev->enc_context_owner;
list_del(&sev->mirror_entry);
mutex_unlock(&owner_kvm->lock);
sev->enc_context_owner = NULL;
/*
* The reference to owner_kvm cannot move after sev_mirror_lock is
* released. Release it before kvm_put_kvm() so that owner_kvm is
* never destroyed inside sev_mirror_lock.
*/
mutex_unlock(&sev_mirror_lock);
kvm_put_kvm(owner_kvm);
return;
}

View File

@ -4227,13 +4227,6 @@ static void svm_flush_tlb_all(struct kvm_vcpu *vcpu)
svm_flush_tlb_asid(vcpu);
}
static void svm_flush_tlb_gva(struct kvm_vcpu *vcpu, gva_t gva)
{
struct vcpu_svm *svm = to_svm(vcpu);
invlpga(gva, svm->vmcb->control.asid);
}
static void svm_flush_tlb_guest(struct kvm_vcpu *vcpu)
{
kvm_register_mark_dirty(vcpu, VCPU_REG_ERAPS);
@ -4241,6 +4234,26 @@ static void svm_flush_tlb_guest(struct kvm_vcpu *vcpu)
svm_flush_tlb_asid(vcpu);
}
static void svm_flush_tlb_gva(struct kvm_vcpu *vcpu, gva_t gva, bool *full)
{
struct vcpu_svm *svm = to_svm(vcpu);
/*
* INVLPGA has had errata on Genoa and Turin, and even on older
* generations there were reports of Windows BSODs if INVLPGA
* was used for Hyper-V tlbflush. Use it only for shadow paging
* where it seems to be okay.
*/
if (!npt_enabled) {
invlpga(gva, svm->vmcb->control.asid);
return;
}
svm_flush_tlb_guest(vcpu);
if (full)
*full = true;
}
static inline void sync_cr8_to_lapic(struct kvm_vcpu *vcpu)
{
struct vcpu_svm *svm = to_svm(vcpu);

View File

@ -109,6 +109,7 @@ struct kvm_sev_info {
u64 ap_jump_table; /* SEV-ES AP Jump Table address */
u64 vmsa_features;
u16 ghcb_version; /* Highest guest GHCB protocol version allowed */
/* The three fields below are protected by sev_mirror_lock */
struct kvm *enc_context_owner; /* Owner of copied encryption context */
struct list_head mirror_vms; /* List of VMs mirroring */
struct list_head mirror_entry; /* Use as a list entry of mirrors */

View File

@ -535,12 +535,12 @@ static void vt_flush_tlb_current(struct kvm_vcpu *vcpu)
vmx_flush_tlb_current(vcpu);
}
static void vt_flush_tlb_gva(struct kvm_vcpu *vcpu, gva_t addr)
static void vt_flush_tlb_gva(struct kvm_vcpu *vcpu, gva_t addr, bool *full)
{
if (is_td_vcpu(vcpu))
return;
vmx_flush_tlb_gva(vcpu, addr);
vmx_flush_tlb_gva(vcpu, addr, full);
}
static void vt_flush_tlb_guest(struct kvm_vcpu *vcpu)

View File

@ -3361,7 +3361,7 @@ void vmx_flush_tlb_current(struct kvm_vcpu *vcpu)
vpid_sync_context(vmx_get_current_vpid(vcpu));
}
void vmx_flush_tlb_gva(struct kvm_vcpu *vcpu, gva_t addr)
void vmx_flush_tlb_gva(struct kvm_vcpu *vcpu, gva_t addr, bool *full)
{
/*
* vpid_sync_vcpu_addr() is a nop if vpid==0, see the comment in

View File

@ -82,7 +82,7 @@ void vmx_set_rflags(struct kvm_vcpu *vcpu, unsigned long rflags);
bool vmx_get_if_flag(struct kvm_vcpu *vcpu);
void vmx_flush_tlb_all(struct kvm_vcpu *vcpu);
void vmx_flush_tlb_current(struct kvm_vcpu *vcpu);
void vmx_flush_tlb_gva(struct kvm_vcpu *vcpu, gva_t addr);
void vmx_flush_tlb_gva(struct kvm_vcpu *vcpu, gva_t addr, bool *full);
void vmx_flush_tlb_guest(struct kvm_vcpu *vcpu);
void vmx_set_interrupt_shadow(struct kvm_vcpu *vcpu, int mask);
u32 vmx_get_interrupt_shadow(struct kvm_vcpu *vcpu);

View File

@ -207,10 +207,24 @@ __EXPORT_THUNK(srso_alias_untrain_ret)
.pushsection .text..__x86.rethunk_safe
SYM_CODE_START_NOALIGN(srso_alias_safe_ret)
/*
* Tell objtool that those are not function pointers referenced by
* __HANDLE_INTR_SAFERET(). Below too.
*/
ANNOTATE_NOENDBR
/*
* Safe-RET sequence. If you need to change it, adjust
* handle_interrupted_saferet() too.
*/
lea 8(%_ASM_SP), %_ASM_SP
UNWIND_HINT_FUNC
ANNOTATE_NOENDBR
ANNOTATE_UNRET_SAFE
ret
/* End of Safe-RET sequence */
int3
SYM_FUNC_END(srso_alias_safe_ret)
@ -245,8 +259,14 @@ SYM_CODE_START_LOCAL_NOALIGN(srso_untrain_ret)
* the stack.
*/
SYM_INNER_LABEL(srso_safe_ret, SYM_L_GLOBAL)
/*
* Safe-RET sequence. If you need to change it, adjust
* handle_interrupted_saferet() too.
*/
lea 8(%_ASM_SP), %_ASM_SP
ret
/* End of Safe-RET sequence */
int3
int3
/* end of movabs */

View File

@ -436,6 +436,23 @@ static void amdxdna_gem_dev_obj_free(struct drm_gem_object *gobj)
amdxdna_gem_destroy_obj(abo);
}
static void amdxdna_mark_mapp_invalid(struct amdxdna_gem_obj *abo,
struct vm_area_struct *vma)
{
struct amdxdna_dev *xdna = to_xdna_dev(to_gobj(abo)->dev);
struct amdxdna_umap *mapp;
down_write(&xdna->notifier_lock);
abo->mem.map_invalid = true;
list_for_each_entry(mapp, &abo->mem.umap_list, node) {
if (compare_range(mapp, vma->vm_mm, vma->vm_start, vma->vm_end)) {
mapp->invalid = true;
break;
}
}
up_write(&xdna->notifier_lock);
}
static int amdxdna_insert_pages(struct amdxdna_gem_obj *abo,
struct vm_area_struct *vma)
{
@ -450,26 +467,17 @@ static int amdxdna_insert_pages(struct amdxdna_gem_obj *abo,
XDNA_ERR(xdna, "Failed shmem mmap %d", ret);
return ret;
}
/* The buffer is based on memory pages. Fix the flag. */
vm_flags_mod(vma, VM_MIXEDMAP, VM_PFNMAP);
ret = vm_insert_pages(vma, vma->vm_start, abo->base.pages,
&num_pages);
} else {
vma->vm_private_data = NULL;
vma->vm_ops = NULL;
ret = dma_buf_mmap(abo->dma_buf, vma, 0);
if (ret) {
XDNA_ERR(xdna, "Failed insert pages %d", ret);
vma->vm_ops->close(vma);
XDNA_ERR(xdna, "Failed to mmap dma buf %d", ret);
return ret;
}
return 0;
}
vma->vm_private_data = NULL;
vma->vm_ops = NULL;
ret = dma_buf_mmap(abo->dma_buf, vma, 0);
if (ret) {
XDNA_ERR(xdna, "Failed to mmap dma buf %d", ret);
return ret;
/* Drop the reference drm_gem_mmap_obj() acquired.*/
drm_gem_object_put(to_gobj(abo));
}
do {
@ -478,17 +486,14 @@ static int amdxdna_insert_pages(struct amdxdna_gem_obj *abo,
fault_ret = handle_mm_fault(vma, vma->vm_start + offset,
FAULT_FLAG_WRITE, NULL);
if (fault_ret & VM_FAULT_ERROR) {
vma->vm_ops->close(vma);
XDNA_ERR(xdna, "Fault in page failed");
return -EFAULT;
amdxdna_mark_mapp_invalid(abo, vma);
break;
}
offset += PAGE_SIZE;
} while (--num_pages);
/* Drop the reference drm_gem_mmap_obj() acquired.*/
drm_gem_object_put(to_gobj(abo));
return 0;
}

View File

@ -1586,6 +1586,10 @@ fn ioctl_write_only(
cmd: u32,
reader: &mut UserSliceReader,
) -> Result {
if cmd == uapi::BINDER_FREEZE {
return ioctl_freeze(reader);
}
let thread = this.get_current_thread()?;
match cmd {
uapi::BINDER_SET_MAX_THREADS => this.set_max_threads(reader.read()?),
@ -1597,7 +1601,6 @@ fn ioctl_write_only(
uapi::BINDER_ENABLE_ONEWAY_SPAM_DETECTION => {
this.set_oneway_spam_detection_enabled(reader.read()?)
}
uapi::BINDER_FREEZE => ioctl_freeze(reader)?,
_ => return Err(EINVAL),
}
Ok(())
@ -1612,15 +1615,16 @@ fn ioctl_write_read(
cmd: u32,
data: UserSlice,
) -> Result {
let thread = this.get_current_thread()?;
let blocking = (file.flags() & file::flags::O_NONBLOCK) == 0;
match cmd {
uapi::BINDER_WRITE_READ => thread.write_read(data, blocking)?,
uapi::BINDER_WRITE_READ => this.get_current_thread()?.write_read(data, blocking)?,
uapi::BINDER_GET_NODE_DEBUG_INFO => this.get_node_debug_info(data)?,
uapi::BINDER_GET_NODE_INFO_FOR_REF => this.get_node_info_from_ref(data)?,
uapi::BINDER_VERSION => this.version(data)?,
uapi::BINDER_GET_FROZEN_INFO => get_frozen_status(data)?,
uapi::BINDER_GET_EXTENDED_ERROR => thread.get_extended_error(data)?,
uapi::BINDER_GET_EXTENDED_ERROR => {
this.get_current_thread()?.get_extended_error(data)?
}
_ => return Err(EINVAL),
}
Ok(())

View File

@ -4420,6 +4420,7 @@ static const struct ata_dev_quirks_entry __ata_dev_quirks[] = {
*/
{ "WDC WD100EFGX-68CPLN0", NULL, ATA_QUIRK_NOLPM },
{ "WDC WD102KFBX-68M95N0", NULL, ATA_QUIRK_NOLPM },
{ "WDC WD141KFGX-68FH9N0", NULL, ATA_QUIRK_NOLPM },
{ "WD Green 2.5 480GB", NULL, ATA_QUIRK_NOLPM },
/*

View File

@ -264,6 +264,7 @@ static struct ata_port_operations sl82c105_port_ops = {
static int sl82c105_bridge_revision(struct pci_dev *pdev)
{
struct pci_dev *bridge;
u8 revision;
/*
* The bridge should be part of the same device, but function 0.
@ -285,8 +286,9 @@ static int sl82c105_bridge_revision(struct pci_dev *pdev)
/*
* We need to find function 0's revision, not function 1
*/
revision = bridge->revision;
pci_dev_put(bridge);
return bridge->revision;
return revision;
}
static void sl82c105_fixup(struct pci_dev *pdev)

View File

@ -483,7 +483,7 @@ static int mchp_tc_probe(struct platform_device *pdev)
char clk_name[7];
struct regmap *regmap;
struct clk *clk[3];
int channel;
u32 channel;
int ret, i;
counter = devm_counter_alloc(&pdev->dev, sizeof(*priv));
@ -517,7 +517,7 @@ static int mchp_tc_probe(struct platform_device *pdev)
priv->channel[i] = channel;
snprintf(clk_name, sizeof(clk_name), "t%d_clk", channel);
snprintf(clk_name, sizeof(clk_name), "t%u_clk", channel);
clk[i] = of_clk_get_by_name(np->parent, clk_name);
if (IS_ERR(clk[i])) {

View File

@ -138,6 +138,7 @@ struct dibs_dev *dibs_dev_alloc(void)
dibs = kzalloc_obj(*dibs);
if (!dibs)
return dibs;
spin_lock_init(&dibs->lock);
dibs->dev.release = dibs_dev_release;
dibs->dev.class = &dibs_class;
device_initialize(&dibs->dev);
@ -186,7 +187,6 @@ int dibs_dev_add(struct dibs_dev *dibs)
int i, ret;
max_dmbs = dibs->ops->max_dmbs();
spin_lock_init(&dibs->lock);
dibs->dmb_clientid_arr = kzalloc(max_dmbs, GFP_KERNEL);
if (!dibs->dmb_clientid_arr)
return -ENOMEM;

View File

@ -42,6 +42,26 @@
#include "amdgpu_ras.h"
#include "amdgpu_hmm.h"
/*
* Maximum IB length (dwords) for rings whose emit_ib packet format
* documents a 20-bit size field.
*/
#define AMDGPU_GFX_SDMA_IB_PACKET_SIZE_MAX_DW 0xFFFFF
#define AMDGPU_MM_IB_PACKET_SIZE_MAX_DW 0x7FFFF0
static u32 amdgpu_cs_ib_packet_size_max_dw(enum amdgpu_ring_type type)
{
switch (type) {
case AMDGPU_RING_TYPE_GFX:
case AMDGPU_RING_TYPE_COMPUTE:
case AMDGPU_RING_TYPE_SDMA:
case AMDGPU_RING_TYPE_VPE:
return AMDGPU_GFX_SDMA_IB_PACKET_SIZE_MAX_DW;
default:
return AMDGPU_MM_IB_PACKET_SIZE_MAX_DW;
}
}
static int amdgpu_cs_parser_init(struct amdgpu_cs_parser *p,
struct amdgpu_device *adev,
struct drm_file *filp,
@ -345,7 +365,6 @@ static int amdgpu_cs_p2_ib(struct amdgpu_cs_parser *p,
job = p->jobs[r];
ring = amdgpu_job_ring(job);
ib = &job->ibs[job->num_ibs++];
/* submissions to kernel queues are disabled */
if (ring->no_user_submission)
@ -374,6 +393,12 @@ static int amdgpu_cs_p2_ib(struct amdgpu_cs_parser *p,
return -EINVAL;
}
if (chunk_ib->ib_bytes / 4 >
amdgpu_cs_ib_packet_size_max_dw(ring->funcs->type))
return -EINVAL;
ib = &job->ibs[job->num_ibs++];
if (chunk_ib->flags & AMDGPU_IB_FLAG_PREAMBLE)
job->preamble_status |= AMDGPU_PREAMBLE_IB_PRESENT;

View File

@ -342,7 +342,7 @@ amdgpu_devcoredump_format(char *buffer, size_t count, struct amdgpu_coredump_inf
struct amdgpu_ip_block *ip_block;
struct amdgpu_ring *ring;
int ver, i, j;
u32 ring_idx, off;
u32 ring_idx;
bool sizing_pass;
sizing_pass = buffer == NULL;
@ -442,7 +442,6 @@ amdgpu_devcoredump_format(char *buffer, size_t count, struct amdgpu_coredump_inf
for (i = 0; i < coredump->num_rings; i++) {
ring_idx = coredump->rings[i].ring_index;
ring = coredump->adev->rings[ring_idx];
off = coredump->rings[i].offset;
drm_printf(&p, "ring name: %s\n", ring->name);
drm_printf(&p, "Rptr: 0x%llx Wptr: 0x%llx RB mask: %x\n",
@ -451,12 +450,18 @@ amdgpu_devcoredump_format(char *buffer, size_t count, struct amdgpu_coredump_inf
ring->buf_mask);
drm_printf(&p, "Ring size in dwords: %d\n",
ring->ring_size / 4);
if (!coredump->rings[i].ring_dw) {
drm_printf(&p, "Ring contents unavailable\n");
continue;
}
drm_printf(&p, "Ring contents\n");
drm_printf(&p, "Offset \t Value\n");
for (j = 0; j < ring->ring_size; j += 4)
drm_printf(&p, "0x%x \t 0x%x\n", j,
coredump->rings_dw[off + j / 4]);
coredump->rings[i].ring_dw[j / 4]);
}
}
@ -497,10 +502,12 @@ amdgpu_devcoredump_read(char *buffer, loff_t offset, size_t count,
static void amdgpu_devcoredump_free(void *data)
{
struct amdgpu_coredump_info *coredump = data;
u32 i;
kvfree(coredump->formatted);
for (i = 0; i < coredump->num_rings; i++)
kvfree(coredump->rings[i].ring_dw);
kvfree(coredump->rings);
kvfree(coredump->rings_dw);
kvfree(data);
}
@ -542,9 +549,9 @@ void amdgpu_coredump(struct amdgpu_device *adev, bool skip_vram_check,
struct amdgpu_coredump_info *coredump;
size_t size = sizeof(*coredump);
struct drm_sched_job *s_job;
u64 total_ring_size, ring_count;
u64 ring_count;
struct amdgpu_ring *ring;
int i, off, idx;
int i, idx;
/* No need to generate a new coredump if there's one in progress already. */
if (work_busy(&adev->coredump_work))
@ -553,7 +560,7 @@ void amdgpu_coredump(struct amdgpu_device *adev, bool skip_vram_check,
if (job && job->pasid)
size += sizeof(struct amdgpu_coredump_ib_info) * job->num_ibs;
coredump = kzalloc(size, GFP_NOWAIT);
coredump = kvzalloc(size, GFP_NOWAIT);
if (!coredump)
return;
@ -584,7 +591,6 @@ void amdgpu_coredump(struct amdgpu_device *adev, bool skip_vram_check,
/* Dump ring content if memory allocation succeeds. */
ring_count = 0;
total_ring_size = 0;
for (i = 0; i < adev->num_rings; i++) {
ring = adev->rings[i];
@ -593,34 +599,34 @@ void amdgpu_coredump(struct amdgpu_device *adev, bool skip_vram_check,
coredump->ring != ring)
continue;
total_ring_size += ring->ring_size;
ring_count++;
}
coredump->rings_dw = kzalloc(total_ring_size, GFP_NOWAIT);
coredump->rings = kcalloc(ring_count, sizeof(struct amdgpu_coredump_ring), GFP_NOWAIT);
if (coredump->rings && coredump->rings_dw) {
for (i = 0, off = 0, idx = 0; i < adev->num_rings && idx < ring_count; i++) {
if (ring_count)
coredump->rings = kvcalloc(ring_count,
sizeof(struct amdgpu_coredump_ring),
GFP_NOWAIT);
if (coredump->rings) {
for (i = 0, idx = 0; i < adev->num_rings && idx < ring_count; i++) {
struct amdgpu_coredump_ring *cdump_ring;
ring = adev->rings[i];
if (atomic_read(&ring->fence_drv.last_seq) == ring->fence_drv.sync_seq &&
coredump->ring != ring)
continue;
coredump->rings[idx].ring_index = ring->idx;
coredump->rings[idx].rptr = amdgpu_ring_get_rptr(ring);
coredump->rings[idx].wptr = amdgpu_ring_get_wptr(ring);
coredump->rings[idx].offset = off;
cdump_ring = &coredump->rings[idx];
memcpy(&coredump->rings_dw[off], ring->ring, ring->ring_size);
off += ring->ring_size / 4;
cdump_ring->ring_dw = kvzalloc(ring->ring_size, GFP_NOWAIT);
if (cdump_ring->ring_dw)
memcpy(cdump_ring->ring_dw, ring->ring, ring->ring_size);
cdump_ring->ring_index = ring->idx;
cdump_ring->rptr = amdgpu_ring_get_rptr(ring);
cdump_ring->wptr = amdgpu_ring_get_wptr(ring);
idx++;
}
coredump->num_rings = idx;
} else {
kvfree(coredump->rings_dw);
kvfree(coredump->rings);
coredump->rings_dw = NULL;
coredump->rings = NULL;
}
coredump->adev = adev;

View File

@ -34,8 +34,8 @@
struct amdgpu_coredump_ring {
u64 rptr;
u64 wptr;
u32 *ring_dw;
u32 ring_index;
u32 offset;
};
struct amdgpu_coredump_ib_info {
@ -53,7 +53,6 @@ struct amdgpu_coredump_info {
struct amdgpu_ring *ring;
struct amdgpu_coredump_ring *rings;
u32 *rings_dw;
u32 num_rings;
/* Readable form of coredevdump, generate once to speed up

View File

@ -4194,6 +4194,8 @@ static void amdgpu_device_unmap_mmio(struct amdgpu_device *adev)
iounmap(adev->rmmio);
adev->rmmio = NULL;
if (adev->mman.aper_base_kaddr)
iounmap(adev->mman.aper_base_kaddr);
adev->mman.aper_base_kaddr = NULL;
/* Memory manager related */

View File

@ -135,6 +135,21 @@ int amdgpu_lockdep_init(void)
lockdep_set_class(&locks->srbm_mutex, &amdgpu_srbm_lock_key);
lockdep_set_class(&locks->grbm_idx_mutex, &amdgpu_grbm_lock_key);
lockdep_set_class(&locks->mmio_idx_lock, &amdgpu_mmio_lock_key);
/*
* Register fs_reclaim lock class FIRST, before taking any locks.
*
* This acquire/release pair does NOT create a static lockdep edge
* (no locks are held between acquire and release). It only registers
* the fs_reclaim lock class with lockdep.
*
* The actual fs_reclaim -> notifier_lock dependency is established at
* RUNTIME when memory reclaim invokes MMU notifiers:
* fs_reclaim (held by reclaim) -> notifier_lock (acquired in callback)
*/
fs_reclaim_acquire(GFP_KERNEL);
fs_reclaim_release(GFP_KERNEL);
/*
* Take locks in the correct order to train lockdep.
* This establishes the dependency chain.
@ -154,11 +169,6 @@ int amdgpu_lockdep_init(void)
/* Level 6: Reset control lock */
mutex_lock(&locks->reset_lock);
/*
* Mark potential memory reclaim boundary.
* GPU operations might trigger memory allocation/reclaim.
*/
fs_reclaim_acquire(GFP_KERNEL);
/* Level 7: SRBM register access */
mutex_lock(&locks->srbm_mutex);
@ -176,7 +186,6 @@ int amdgpu_lockdep_init(void)
spin_unlock_irqrestore(&locks->mmio_idx_lock, flags);
mutex_unlock(&locks->grbm_idx_mutex);
mutex_unlock(&locks->srbm_mutex);
fs_reclaim_release(GFP_KERNEL);
mutex_unlock(&locks->reset_lock);
up_read(&reset_domain->sem);

View File

@ -2120,23 +2120,17 @@ int amdgpu_ttm_init(struct amdgpu_device *adev)
/* Change the size here instead of the init above so only lpfn is affected */
amdgpu_ttm_disable_buffer_funcs(adev);
#ifdef CONFIG_64BIT
if (adev->gmc.xgmi.connected_to_cpu) {
void *kaddr = devm_memremap(adev->dev, adev->gmc.aper_base,
adev->gmc.visible_vram_size,
MEMREMAP_WB);
if (IS_ERR(kaddr))
return PTR_ERR(kaddr);
adev->mman.aper_base_kaddr = (__force void __iomem *)kaddr;
} else if (adev->gmc.is_app_apu) {
#ifdef CONFIG_X86
if (adev->gmc.xgmi.connected_to_cpu)
adev->mman.aper_base_kaddr = ioremap_cache(adev->gmc.aper_base,
adev->gmc.visible_vram_size);
else if (adev->gmc.is_app_apu)
DRM_DEBUG_DRIVER(
"No need to ioremap when real vram size is 0\n");
} else {
adev->mman.aper_base_kaddr = devm_ioremap_wc(adev->dev,
adev->gmc.aper_base,
adev->gmc.visible_vram_size);
if (!adev->mman.aper_base_kaddr)
return -ENOMEM;
}
else
#endif
adev->mman.aper_base_kaddr = ioremap_wc(adev->gmc.aper_base,
adev->gmc.visible_vram_size);
#endif
amdgpu_ttm_init_vram_resv_regions(adev);
@ -2287,7 +2281,10 @@ void amdgpu_ttm_fini(struct amdgpu_device *adev)
amdgpu_ttm_unmark_vram_reserved(adev, AMDGPU_RESV_FW_VRAM_USAGE);
amdgpu_ttm_unmark_vram_reserved(adev, AMDGPU_RESV_DRV_VRAM_USAGE);
adev->mman.aper_base_kaddr = NULL;
if (adev->mman.aper_base_kaddr) {
iounmap(adev->mman.aper_base_kaddr);
adev->mman.aper_base_kaddr = NULL;
}
if (!adev->gmc.is_app_apu)
amdgpu_vram_mgr_fini(adev);

View File

@ -700,7 +700,12 @@ amdgpu_userq_create(struct drm_file *filp, union drm_amdgpu_userq *args)
if (!adev->userq_halt_for_enforce_isolation ||
((queue->queue_type != AMDGPU_HW_IP_GFX) &&
(queue->queue_type != AMDGPU_HW_IP_COMPUTE))) {
/* Serialize the map against an in-progress GPU reset (MES is
* unresponsive during recovery), matching amdgpu_userq_cleanup().
*/
down_read(&adev->reset_domain->sem);
r = amdgpu_userq_map_helper(queue);
up_read(&adev->reset_domain->sem);
if (r) {
drm_file_err(uq_mgr->file, "Failed to map Queue\n");
mutex_unlock(&uq_mgr->userq_mutex);

View File

@ -1823,6 +1823,11 @@ static void gfx_v12_0_constants_init(struct amdgpu_device *adev)
gfx_v12_0_get_tcc_info(adev);
adev->gfx.config.pa_sc_tile_steering_override = 0;
/* Set whether texture coordinate truncation is conformant. */
tmp = RREG32_SOC15(GC, 0, regTA_CNTL2);
adev->gfx.config.ta_cntl2_truncate_coord_mode =
REG_GET_FIELD(tmp, TA_CNTL2, TRUNCATE_COORD_MODE);
/* XXX SH_MEM regs */
/* where to put LDS, scratch, GPUVM in FSA64 space */
mutex_lock(&adev->srbm_mutex);

View File

@ -267,9 +267,24 @@ static bool gmc_v12_1_get_vmid_pasid_mapping_info(struct amdgpu_device *adev,
* by the amdgpu vm/hsa code.
*/
/**
* gmc_v12_1_use_invalidate_semaphore - judge whether to use semaphore
*
* @adev: amdgpu_device pointer
* @vmhub: vmhub type
*
*/
static bool gmc_v12_1_use_invalidate_semaphore(struct amdgpu_device *adev,
uint32_t vmhub)
{
return ((!AMDGPU_IS_GFXHUB(vmhub)) &&
(!amdgpu_sriov_vf(adev)));
}
static void gmc_v12_1_flush_vm_hub(struct amdgpu_device *adev, uint32_t vmid,
unsigned int vmhub, uint32_t flush_type)
{
bool use_semaphore = gmc_v12_1_use_invalidate_semaphore(adev, vmhub);
struct amdgpu_vmhub *hub = &adev->vmhub[vmhub];
u32 inv_req = hub->vmhub_funcs->get_invalidate_req(vmid, flush_type);
u32 tmp;
@ -283,6 +298,19 @@ static void gmc_v12_1_flush_vm_hub(struct amdgpu_device *adev, uint32_t vmid,
spin_lock(&adev->gmc.invalidate_lock);
if (use_semaphore) {
for (i = 0; i < adev->usec_timeout; i++) {
/* a read return value of 1 means semaphore acuqire */
tmp = RREG32_RLC_NO_KIQ(hub->vm_inv_eng0_sem + hub->eng_distance * eng, hub_ip);
if (tmp & 0x1)
break;
udelay(1);
}
if (i >= adev->usec_timeout)
DRM_ERROR("Timeout waiting for sem acquire in VM flush!\n");
}
WREG32_RLC_NO_KIQ(hub->vm_inv_eng0_req + hub->eng_distance * eng, inv_req, hub_ip);
/* Wait for ACK with a delay.*/
@ -296,6 +324,9 @@ static void gmc_v12_1_flush_vm_hub(struct amdgpu_device *adev, uint32_t vmid,
udelay(1);
}
if (use_semaphore)
WREG32_RLC_NO_KIQ(hub->vm_inv_eng0_sem + hub->eng_distance * eng, 0, hub_ip);
/* Issue additional private vm invalidation to MMHUB */
if (!AMDGPU_IS_GFXHUB(vmhub) &&
(hub->vm_l2_bank_select_reserved_cid2) &&
@ -396,7 +427,7 @@ static void gmc_v12_1_flush_gpu_tlb_pasid(struct amdgpu_device *adev,
if (all_hub) {
/* invalidate mm_hub */
if (test_bit(AMDGPU_MMHUB1(0), adev->vmhubs_mask)) {
if (test_bit(AMDGPU_MMHUB0(0), adev->vmhubs_mask)) {
input.hub_id = AMDGPU_MMHUB0(0);
adev->mes.funcs->invalidate_tlbs_pasid(&adev->mes, &input);
}
@ -431,10 +462,17 @@ static void gmc_v12_1_flush_gpu_tlb_pasid(struct amdgpu_device *adev,
static uint64_t gmc_v12_1_emit_flush_gpu_tlb(struct amdgpu_ring *ring,
unsigned vmid, uint64_t pd_addr)
{
bool use_semaphore = gmc_v12_1_use_invalidate_semaphore(ring->adev, ring->vm_hub);
struct amdgpu_vmhub *hub = &ring->adev->vmhub[ring->vm_hub];
uint32_t req = hub->vmhub_funcs->get_invalidate_req(vmid, 0);
unsigned eng = ring->vm_inv_eng;
if (use_semaphore)
/* a read return value of 1 means semaphore acuqire */
amdgpu_ring_emit_reg_wait(ring,
hub->vm_inv_eng0_sem +
hub->eng_distance * eng, 0x1, 0x1);
amdgpu_ring_emit_wreg(ring, hub->ctx0_ptb_addr_lo32 +
(hub->ctx_addr_distance * vmid),
lower_32_bits(pd_addr));
@ -449,6 +487,14 @@ static uint64_t gmc_v12_1_emit_flush_gpu_tlb(struct amdgpu_ring *ring,
hub->eng_distance * eng,
req, 1 << vmid);
if (use_semaphore)
/*
* add semaphore release after invalidation,
* write with 0 means semaphore release
*/
amdgpu_ring_emit_wreg(ring, hub->vm_inv_eng0_sem +
hub->eng_distance * eng, 0);
return pd_addr;
}

View File

@ -772,15 +772,28 @@ static int jpeg_v4_0_5_ring_reset(struct amdgpu_ring *ring,
unsigned int vmid,
struct amdgpu_fence *timedout_fence)
{
struct amdgpu_device *adev = ring->adev;
u32 pg_flags = adev->pg_flags;
int r;
amdgpu_ring_reset_helper_begin(ring, timedout_fence);
r = jpeg_v4_0_5_stop(ring->adev);
if (r)
return r;
r = jpeg_v4_0_5_start(ring->adev);
/*
* The DPG stop path only clears the JPEG_PG_MODE bit and never resets a
* hung JRBC, so the post-reset ring test times out and the driver falls
* back to a full MODE1 reset. Temporarily force the static power-gating
* path so the stop/start sequence actually power-cycles the JPEG block
* (JMI soft reset + static power off/on), matching the working jpeg_v4_0
* reset.
*/
adev->pg_flags &= ~AMD_PG_SUPPORT_JPEG_DPG;
r = jpeg_v4_0_5_stop(adev);
if (!r)
r = jpeg_v4_0_5_start(adev);
adev->pg_flags = pg_flags;
if (r)
return r;
return amdgpu_ring_reset_helper_end(ring, timedout_fence);
}

View File

@ -648,15 +648,28 @@ static int jpeg_v5_0_0_ring_reset(struct amdgpu_ring *ring,
unsigned int vmid,
struct amdgpu_fence *timedout_fence)
{
struct amdgpu_device *adev = ring->adev;
u32 pg_flags = adev->pg_flags;
int r;
amdgpu_ring_reset_helper_begin(ring, timedout_fence);
r = jpeg_v5_0_0_stop(ring->adev);
if (r)
return r;
r = jpeg_v5_0_0_start(ring->adev);
/*
* The DPG stop path only clears the JPEG_PG_MODE bit and never resets a
* hung JRBC, so the post-reset ring test times out and the driver falls
* back to a full MODE1 reset. Temporarily force the static power-gating
* path so the stop/start sequence actually power-cycles the JPEG block
* (JMI soft reset + ONO1 power off/on), matching the working jpeg_v4_0
* reset.
*/
adev->pg_flags &= ~AMD_PG_SUPPORT_JPEG_DPG;
r = jpeg_v5_0_0_stop(adev);
if (!r)
r = jpeg_v5_0_0_start(adev);
adev->pg_flags = pg_flags;
if (r)
return r;
return amdgpu_ring_reset_helper_end(ring, timedout_fence);
}

View File

@ -655,15 +655,28 @@ static int jpeg_v5_3_0_ring_reset(struct amdgpu_ring *ring,
unsigned int vmid,
struct amdgpu_fence *timedout_fence)
{
struct amdgpu_device *adev = ring->adev;
u32 pg_flags = adev->pg_flags;
int r;
amdgpu_ring_reset_helper_begin(ring, timedout_fence);
r = jpeg_v5_3_0_stop(ring->adev);
if (r)
return r;
r = jpeg_v5_3_0_start(ring->adev);
/*
* The DPG stop path only clears the JPEG_PG_MODE bit and never resets a
* hung JRBC, so the post-reset ring test times out and the driver falls
* back to a full MODE1 reset. Temporarily force the static power-gating
* path so the stop/start sequence actually power-cycles the JPEG block
* (JMI soft reset + static power off/on), matching the working jpeg_v4_0
* reset.
*/
adev->pg_flags &= ~AMD_PG_SUPPORT_JPEG_DPG;
r = jpeg_v5_3_0_stop(adev);
if (!r)
r = jpeg_v5_3_0_start(adev);
adev->pg_flags = pg_flags;
if (r)
return r;
return amdgpu_ring_reset_helper_end(ring, timedout_fence);
}

View File

@ -2189,6 +2189,11 @@ static int amdgpu_dm_init(struct amdgpu_device *adev)
init_data.flags.unify_link_enc_assignment = true;
init_data.flags.usb4_bw_alloc_support = true;
}
/* DCN201 audio desyncs using DP SS */
if (adev->apu_flags & AMD_APU_IS_CYAN_SKILLFISH2)
init_data.flags.ignore_dpref_ss = true;
retrieve_dmi_info(&adev->dm);
if (adev->dm.edp0_on_dp1_quirk)
init_data.flags.support_edp0_on_dp1 = true;

View File

@ -119,7 +119,11 @@ void amdgpu_dm_crtc_set_static_screen_optimze(
struct dc_link *link = stream->link;
bool set_vsync_event = !sso_enable;
if (!allow_sr_entry)
/*
* allow_sr_entry gates only entry. A disable request must still set
* the vsync events to force Replay and PSR1 out and keep them blocked.
*/
if (sso_enable && !allow_sr_entry)
return;
amdgpu_dm_replay_set_event(dm, stream,

View File

@ -1348,7 +1348,10 @@ void dce110_set_avmute(struct pipe_ctx *pipe_ctx, bool enable)
* process the mute state, especially after link re-establishment
* with HDMI 2.0 scrambling enabled.
*/
if (enable && pipe_ctx->stream_res.tg->funcs->is_tg_enabled(pipe_ctx->stream_res.tg)) {
if (enable && pipe_ctx->stream_res.tg &&
pipe_ctx->stream_res.tg->funcs->is_tg_enabled &&
pipe_ctx->stream_res.tg->funcs->wait_for_state &&
pipe_ctx->stream_res.tg->funcs->is_tg_enabled(pipe_ctx->stream_res.tg)) {
int i;
pipe_ctx->stream_res.tg->funcs->wait_for_state(pipe_ctx->stream_res.tg, CRTC_STATE_VACTIVE);

View File

@ -257,8 +257,14 @@ static ssize_t ps8640_aux_transfer_msg(struct drm_dp_aux *aux,
addr_len[PAGE0_SWAUX_LENGTH - base] = (len == 0) ? SWAUX_NO_PAYLOAD :
((len - 1) & SWAUX_LENGTH_MASK);
regmap_bulk_write(map, PAGE0_SWAUX_ADDR_7_0, addr_len,
ARRAY_SIZE(addr_len));
ret = regmap_bulk_write(map, PAGE0_SWAUX_ADDR_7_0, addr_len,
ARRAY_SIZE(addr_len));
if (ret) {
DRM_DEV_ERROR(dev,
"failed to write AUX address %#x, len %zu: %d\n",
msg->address, len, ret);
return ret;
}
if (len && (request == DP_AUX_NATIVE_WRITE ||
request == DP_AUX_I2C_WRITE)) {
@ -274,13 +280,22 @@ static ssize_t ps8640_aux_transfer_msg(struct drm_dp_aux *aux,
}
}
regmap_write(map, PAGE0_SWAUX_CTRL, SWAUX_SEND);
ret = regmap_write(map, PAGE0_SWAUX_CTRL, SWAUX_SEND);
if (ret) {
DRM_DEV_ERROR(dev, "failed to start AUX transfer: %d\n", ret);
return ret;
}
/* Zero delay loop because i2c transactions are slow already */
regmap_read_poll_timeout(map, PAGE0_SWAUX_CTRL, data,
!(data & SWAUX_SEND), 0, 50 * 1000);
ret = regmap_read_poll_timeout(map, PAGE0_SWAUX_CTRL, data,
!(data & SWAUX_SEND), 0, 50 * 1000);
if (ret) {
DRM_DEV_ERROR(dev, "failed to complete AUX transfer: %d\n",
ret);
return ret;
}
regmap_read(map, PAGE0_SWAUX_STATUS, &data);
ret = regmap_read(map, PAGE0_SWAUX_STATUS, &data);
if (ret) {
DRM_DEV_ERROR(dev, "failed to read PAGE0_SWAUX_STATUS: %d\n",
ret);

View File

@ -597,9 +597,13 @@ static vm_fault_t try_insert_pfn(struct vm_fault *vmf, unsigned int order,
#ifdef CONFIG_ARCH_SUPPORTS_PMD_PFNMAP
} else if (order == PMD_ORDER) {
unsigned long paddr = pfn << PAGE_SHIFT;
struct vm_area_struct *vma = vmf->vma;
unsigned long start = ALIGN_DOWN(vmf->address, PMD_SIZE);
unsigned long end = start + PMD_SIZE;
bool in_range = vma->vm_start <= start && end <= vma->vm_end;
bool aligned = (vmf->address & ~PMD_MASK) == (paddr & ~PMD_MASK);
if (aligned &&
if (aligned && in_range &&
folio_test_pmd_mappable(page_folio(pfn_to_page(pfn)))) {
vm_fault_t ret;

View File

@ -603,6 +603,9 @@ static int panthor_fw_load_section_entry(struct panthor_device *ptdev,
return -EINVAL;
}
if (!section_size)
return 0;
name_len = iter->size - iter->offset;
section = drmm_kzalloc(&ptdev->base, sizeof(*section), GFP_KERNEL);

View File

@ -802,9 +802,13 @@ static vm_fault_t insert_page(struct vm_fault *vmf, unsigned int order, struct p
} else if (order == PMD_ORDER) {
unsigned long pfn = page_to_pfn(page);
unsigned long paddr = pfn << PAGE_SHIFT;
struct vm_area_struct *vma = vmf->vma;
unsigned long start = ALIGN_DOWN(vmf->address, PMD_SIZE);
unsigned long end = start + PMD_SIZE;
bool in_range = vma->vm_start <= start && end <= vma->vm_end;
bool aligned = (vmf->address & ~PMD_MASK) == (paddr & ~PMD_MASK);
if (aligned &&
if (aligned && in_range &&
folio_test_pmd_mappable(page_folio(page))) {
pfn &= PMD_MASK >> PAGE_SHIFT;
return vmf_insert_pfn_pmd(vmf, pfn, vmf->flags & FAULT_FLAG_WRITE);

View File

@ -360,6 +360,13 @@ static bool radeon_fence_is_signaled(struct dma_fence *f)
if (atomic64_read(&rdev->fence_drv[ring].last_seq) >= seq)
return true;
if (down_read_trylock(&rdev->exclusive_lock)) {
radeon_fence_activity(rdev, ring);
up_read(&rdev->exclusive_lock);
if (atomic64_read(&rdev->fence_drv[ring].last_seq) >= seq)
return true;
}
return false;
}

View File

@ -182,6 +182,12 @@ struct v3d_dev {
*/
struct mutex reset_lock;
/* Ordered workqueue shared by every queue's scheduler timeout work.
* V3D reset is global to all queues, so the timeout handlers must not
* run concurrently.
*/
struct workqueue_struct *reset_wq;
/* Lock taken when creating and pushing the GPU scheduler
* jobs, to keep the sched-fence seqnos in order.
*/

View File

@ -837,6 +837,7 @@ v3d_queue_sched_init(struct v3d_dev *v3d, const struct drm_sched_backend_ops *op
struct drm_sched_init_args args = {
.credit_limit = 1,
.timeout = msecs_to_jiffies(500),
.timeout_wq = v3d->reset_wq,
.dev = v3d->drm.dev,
};
@ -851,9 +852,13 @@ v3d_sched_init(struct v3d_dev *v3d)
{
int ret;
v3d->reset_wq = alloc_ordered_workqueue("v3d_reset", 0);
if (!v3d->reset_wq)
return -ENOMEM;
ret = v3d_queue_sched_init(v3d, &v3d_bin_sched_ops, V3D_BIN, "v3d_bin");
if (ret)
return ret;
goto fail;
ret = v3d_queue_sched_init(v3d, &v3d_render_sched_ops, V3D_RENDER,
"v3d_render");
@ -896,4 +901,6 @@ v3d_sched_fini(struct v3d_dev *v3d)
if (v3d->queue[q].sched.ready)
drm_sched_fini(&v3d->queue[q].sched);
}
destroy_workqueue(v3d->reset_wq);
}

View File

@ -805,6 +805,9 @@ static int exec_queue_set_hang_replay_state(struct xe_device *xe,
u64 __user *address = u64_to_user_ptr(value);
void *ptr;
if (q->replay_state)
return -EINVAL;
ptr = vmemdup_user(address, size);
if (XE_IOCTL_DBG(xe, IS_ERR(ptr)))
return PTR_ERR(ptr);

View File

@ -15,6 +15,7 @@
#include "xe_guc_pc.h"
#include "xe_guc_rc.h"
#include "xe_guc_engine_activity.h"
#include "xe_guc_submit.h"
#include "xe_huc.h"
#include "xe_sriov.h"
#include "xe_wopcm.h"
@ -159,12 +160,14 @@ static int vf_uc_load_hw(struct xe_uc *uc)
if (err)
return err;
uc->guc.submission_state.enabled = true;
err = xe_guc_opt_in_features_enable(&uc->guc);
if (err)
return err;
err = xe_guc_submit_enable(&uc->guc);
if (err)
return err;
err = xe_gt_record_default_lrcs(uc_to_gt(uc));
if (err)
return err;

View File

@ -106,12 +106,11 @@ static int ads7828_probe(struct i2c_client *client)
struct ads7828_data *data;
struct device *hwmon_dev;
unsigned int vref_mv = ADS7828_INT_VREF_MV;
unsigned int vref_uv;
int vref_uv;
bool diff_input = false;
bool ext_vref = false;
unsigned int regval;
enum ads7828_chips chip;
struct regulator *reg;
data = devm_kzalloc(dev, sizeof(struct ads7828_data), GFP_KERNEL);
if (!data)
@ -125,9 +124,11 @@ static int ads7828_probe(struct i2c_client *client)
} else if (dev->of_node) {
diff_input = of_property_read_bool(dev->of_node,
"ti,differential-input");
reg = devm_regulator_get_optional(dev, "vref");
if (!IS_ERR(reg)) {
vref_uv = regulator_get_voltage(reg);
vref_uv = devm_regulator_get_enable_read_voltage(dev, "vref");
if (vref_uv < 0) {
if (vref_uv != -ENODEV)
return vref_uv;
} else {
vref_mv = DIV_ROUND_CLOSEST(vref_uv, 1000);
if (vref_mv < ADS7828_EXT_VREF_MV_MIN ||
vref_mv > ADS7828_EXT_VREF_MV_MAX)

View File

@ -137,13 +137,18 @@ struct corsairpsu_data {
};
/* some values are SMBus LINEAR11 data which need a conversion */
static int corsairpsu_linear11_to_int(const u16 val, const int scale)
static long corsairpsu_linear11_to_long(const u16 val, const int scale)
{
const int exp = ((s16)val) >> 11;
const int mant = (((s16)(val & 0x7ff)) << 5) >> 5;
const int result = mant * scale;
const int mant = ((s16)((val & 0x7ff) << 5)) >> 5;
s64 result = mant * scale;
return (exp >= 0) ? (result << exp) : (result >> -exp);
if (exp >= 0)
result *= (int)(1UL << exp);
else
result >>= -exp;
return clamp(result, LONG_MIN, LONG_MAX);
}
/* the micro-controller uses percentage values to control pwm */
@ -263,13 +268,13 @@ static int corsairpsu_get_value(struct corsairpsu_data *priv, u8 cmd, u8 rail, l
case PSU_CMD_RAIL_AMPS:
case PSU_CMD_TEMP0:
case PSU_CMD_TEMP1:
*val = corsairpsu_linear11_to_int(tmp & 0xFFFF, 1000);
*val = corsairpsu_linear11_to_long(tmp & 0xFFFF, 1000);
break;
case PSU_CMD_FAN:
*val = corsairpsu_linear11_to_int(tmp & 0xFFFF, 1);
*val = corsairpsu_linear11_to_long(tmp & 0xFFFF, 1);
break;
case PSU_CMD_FAN_PWM_ENABLE:
*val = corsairpsu_linear11_to_int(tmp & 0xFFFF, 1);
*val = corsairpsu_linear11_to_long(tmp & 0xFFFF, 1);
/*
* 0 = automatic mode, means the micro-controller controls the fan using a plan
* which can be modified, but changing this plan is not supported by this
@ -283,12 +288,12 @@ static int corsairpsu_get_value(struct corsairpsu_data *priv, u8 cmd, u8 rail, l
*val = 2;
break;
case PSU_CMD_FAN_PWM:
*val = corsairpsu_linear11_to_int(tmp & 0xFFFF, 1);
*val = corsairpsu_linear11_to_long(tmp & 0xFFFF, 1);
*val = corsairpsu_dutycycle_to_pwm(*val);
break;
case PSU_CMD_RAIL_WATTS:
case PSU_CMD_TOTAL_WATTS:
*val = corsairpsu_linear11_to_int(tmp & 0xFFFF, 1000000);
*val = corsairpsu_linear11_to_long(tmp & 0xFFFF, 1000000);
break;
case PSU_CMD_TOTAL_UPTIME:
case PSU_CMD_UPTIME:
@ -664,6 +669,8 @@ static void print_uptime(struct seq_file *seqf, u8 cmd)
long val;
int ret;
guard(hwmon_lock)(priv->hwmon_dev);
ret = corsairpsu_get_value(priv, cmd, 0, &val);
if (ret < 0) {
seq_puts(seqf, "N/A\n");
@ -701,7 +708,7 @@ static int vendor_show(struct seq_file *seqf, void *unused)
{
struct corsairpsu_data *priv = seqf->private;
seq_printf(seqf, "%s\n", priv->vendor);
seq_printf(seqf, "%.*s\n", REPLY_SIZE, priv->vendor);
return 0;
}
@ -711,7 +718,7 @@ static int product_show(struct seq_file *seqf, void *unused)
{
struct corsairpsu_data *priv = seqf->private;
seq_printf(seqf, "%s\n", priv->product);
seq_printf(seqf, "%.*s\n", REPLY_SIZE, priv->product);
return 0;
}
@ -723,6 +730,8 @@ static int ocpmode_show(struct seq_file *seqf, void *unused)
long val;
int ret;
guard(hwmon_lock)(priv->hwmon_dev);
/*
* The rail mode is switchable on the fly. The RAW interface can be used for this. But it
* will not be included here, because I consider it somewhat dangerous for the health of the

View File

@ -1083,7 +1083,6 @@ EXPORT_SYMBOL_GPL(hwmon_device_register_with_info);
* @dev: the parent device
* @name: hwmon name attribute
* @drvdata: driver data to attach to created device
* @extra_groups: pointer to list of additional non-standard attribute groups
*
* The use of this function is restricted. It is provided for legacy reasons
* and must only be called from the thermal subsystem.
@ -1095,13 +1094,12 @@ EXPORT_SYMBOL_GPL(hwmon_device_register_with_info);
*/
struct device *
hwmon_device_register_for_thermal(struct device *dev, const char *name,
void *drvdata,
const struct attribute_group **extra_groups)
void *drvdata)
{
if (!name || !dev)
return ERR_PTR(-EINVAL);
return __hwmon_device_register(dev, name, drvdata, NULL, extra_groups);
return __hwmon_device_register(dev, name, drvdata, NULL, NULL);
}
EXPORT_SYMBOL_NS_GPL(hwmon_device_register_for_thermal, "HWMON_THERMAL");

View File

@ -14,6 +14,7 @@
#include <linux/hwmon.h>
#include <linux/i2c.h>
#include <linux/math.h>
#include <linux/math64.h>
#include <linux/minmax.h>
#include <linux/module.h>
#include <linux/regmap.h>
@ -137,7 +138,7 @@ struct ltc4282_state {
*/
struct ltc4282_cache in0_1_cache[LTC4282_CHAN_VGPIO];
u32 vsense_max;
long power_max;
s64 power_max;
u32 rsense;
u16 vdd;
u16 vfs_out;
@ -613,13 +614,12 @@ static int ltc4282_read(struct device *dev, enum hwmon_sensor_types type,
}
static int ltc4282_write_power_byte(const struct ltc4282_state *st, u32 reg,
long val)
s64 val)
{
u32 power;
u64 temp;
if (val > st->power_max)
val = st->power_max;
val = clamp(val, 0, st->power_max);
temp = val * int_pow(U8_MAX, 2) * st->rsense;
power = DIV64_U64_ROUND_CLOSEST(temp,
@ -629,7 +629,7 @@ static int ltc4282_write_power_byte(const struct ltc4282_state *st, u32 reg,
}
static int ltc4282_write_power_word(const struct ltc4282_state *st, u32 reg,
long val)
u64 val)
{
u64 temp = int_pow(U16_MAX, 2) * st->rsense, temp_2;
__be16 __raw;
@ -930,8 +930,11 @@ static int ltc4282_curr_reset_hist(struct ltc4282_state *st)
static int ltc4282_write_curr(struct ltc4282_state *st, u32 attr,
long val)
{
s32 ulimit = min_t(u64, INT_MAX,
div_u64((u64)INT_MAX * DECA * MICRO, st->rsense));
u64 val64 = clamp(val, 0, ulimit);
/* need to pass it in millivolt */
u32 in = DIV_ROUND_CLOSEST_ULL((u64)val * st->rsense, DECA * MICRO);
u32 in = DIV_ROUND_CLOSEST_ULL(val64 * st->rsense, DECA * MICRO);
switch (attr) {
case hwmon_curr_max:
@ -1222,7 +1225,8 @@ static int ltc4282_set_max_limits(struct ltc4282_state *st)
return ret;
/* Power is given by ISENSE * Vout. */
st->power_max = DIV_ROUND_CLOSEST(st->vsense_max * DECA * MILLI, st->rsense) * st->vfs_out;
st->power_max = DIV_ROUND_CLOSEST_ULL((u64)st->vsense_max * DECA * MILLI,
st->rsense) * st->vfs_out;
ret = ltc4282_write_power_byte(st, LTC4282_POWER_MAX, st->power_max);
if (ret)
return ret;
@ -1390,7 +1394,7 @@ static int ltc4282_setup(struct ltc4282_state *st, struct device *dev)
if (!ret) {
int reg_val;
switch (val) {
switch (st->vsense_max) {
case 12500:
reg_val = 0;
break;

View File

@ -754,7 +754,11 @@ static int nzxt_smart2_hid_probe(struct hid_device *hdev,
hid_device_io_start(hdev);
init_device(drvdata, UPDATE_INTERVAL_DEFAULT_MS);
ret = init_device(drvdata, UPDATE_INTERVAL_DEFAULT_MS);
if (ret) {
dev_err(&hdev->dev, "init_device failed: %d\n", ret);
goto out_hw_close;
}
drvdata->hwmon =
hwmon_device_register_with_info(&hdev->dev, "nzxtsmart2", drvdata,

View File

@ -14,6 +14,7 @@
#include <linux/slab.h>
#include <linux/i2c.h>
#include <linux/log2.h>
#include <linux/math.h>
#include <linux/of.h>
#include "pmbus.h"
@ -542,8 +543,8 @@ static int lm25066_probe(struct i2c_client *client)
if (of_property_read_u32(client->dev.of_node, "shunt-resistor-micro-ohms", &shunt))
shunt = 1000;
info->m[PSC_CURRENT_IN] = info->m[PSC_CURRENT_IN] * shunt / 1000;
info->m[PSC_POWER] = info->m[PSC_POWER] * shunt / 1000;
info->m[PSC_CURRENT_IN] = DIV_ROUND_CLOSEST_ULL((u64)info->m[PSC_CURRENT_IN] * shunt, 1000);
info->m[PSC_POWER] = DIV_ROUND_CLOSEST_ULL((u64)info->m[PSC_POWER] * shunt, 1000);
#if IS_ENABLED(CONFIG_SENSORS_LM25066_REGULATOR)
/* LM25056 doesn't support OPERATION */

View File

@ -45,7 +45,7 @@ module_param(wp, int, 0444);
struct pmbus_sensor {
struct pmbus_sensor *next;
char name[PMBUS_NAME_SIZE]; /* sysfs sensor name */
struct device_attribute attribute;
struct sensor_device_attribute attribute;
u8 page; /* page number */
u8 phase; /* phase number, 0xff for all phases */
u16 reg; /* register */
@ -68,7 +68,7 @@ struct pmbus_boolean {
struct pmbus_label {
char name[PMBUS_NAME_SIZE]; /* sysfs label name */
struct device_attribute attribute;
struct sensor_device_attribute attribute;
char label[PMBUS_NAME_SIZE]; /* label */
};
#define to_pmbus_label(_attr) \
@ -1241,7 +1241,8 @@ static ssize_t pmbus_show_sensor(struct device *dev,
struct device_attribute *devattr, char *buf)
{
struct i2c_client *client = to_i2c_client(dev->parent);
struct pmbus_sensor *sensor = to_pmbus_sensor(devattr);
struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
struct pmbus_sensor *sensor = to_pmbus_sensor(attr);
struct pmbus_data *data = i2c_get_clientdata(client);
s64 val;
@ -1261,7 +1262,8 @@ static ssize_t pmbus_set_sensor(struct device *dev,
{
struct i2c_client *client = to_i2c_client(dev->parent);
struct pmbus_data *data = i2c_get_clientdata(client);
struct pmbus_sensor *sensor = to_pmbus_sensor(devattr);
struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
struct pmbus_sensor *sensor = to_pmbus_sensor(attr);
s64 val;
int ret;
u16 regval;
@ -1283,7 +1285,8 @@ static ssize_t pmbus_set_sensor(struct device *dev,
static ssize_t pmbus_show_label(struct device *dev,
struct device_attribute *da, char *buf)
{
struct pmbus_label *label = to_pmbus_label(da);
struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
struct pmbus_label *label = to_pmbus_label(attr);
return sysfs_emit(buf, "%s\n", label->label);
}
@ -1436,8 +1439,8 @@ static struct pmbus_sensor *pmbus_add_sensor(struct pmbus_data *data,
bool update, bool readonly,
bool writeonly, bool convert)
{
struct sensor_device_attribute *a;
struct pmbus_sensor *sensor;
struct device_attribute *a;
sensor = devm_kzalloc(data->dev, sizeof(*sensor), GFP_KERNEL);
if (!sensor)
@ -1461,12 +1464,11 @@ static struct pmbus_sensor *pmbus_add_sensor(struct pmbus_data *data,
sensor->update = update;
sensor->convert = convert;
sensor->data = -ENODATA;
pmbus_dev_attr_init(a, sensor->name,
readonly ? 0444 : 0644,
writeonly ? pmbus_show_zero : pmbus_show_sensor,
pmbus_set_sensor);
pmbus_attr_init(a, sensor->name, readonly ? 0444 : 0644,
writeonly ? pmbus_show_zero : pmbus_show_sensor,
pmbus_set_sensor, -1);
if (pmbus_add_attribute(data, &a->attr))
if (pmbus_add_attribute(data, &a->dev_attr.attr))
return NULL;
sensor->next = data->sensors;
@ -1483,8 +1485,8 @@ static int pmbus_add_label(struct pmbus_data *data,
const char *name, int seq,
const char *lstring, int index, int phase)
{
struct sensor_device_attribute *a;
struct pmbus_label *label;
struct device_attribute *a;
label = devm_kzalloc(data->dev, sizeof(*label), GFP_KERNEL);
if (!label)
@ -1508,8 +1510,8 @@ static int pmbus_add_label(struct pmbus_data *data,
lstring, index, phase);
}
pmbus_dev_attr_init(a, label->name, 0444, pmbus_show_label, NULL);
return pmbus_add_attribute(data, &a->attr);
pmbus_attr_init(a, label->name, 0444, pmbus_show_label, NULL, -1);
return pmbus_add_attribute(data, &a->dev_attr.attr);
}
/*
@ -2397,7 +2399,7 @@ struct pmbus_samples_attr {
struct pmbus_samples_reg {
int page;
struct pmbus_samples_attr *attr;
struct device_attribute dev_attr;
struct sensor_device_attribute attribute;
};
static struct pmbus_samples_attr pmbus_samples_registers[] = {
@ -2419,14 +2421,15 @@ static struct pmbus_samples_attr pmbus_samples_registers[] = {
}
};
#define to_samples_reg(x) container_of(x, struct pmbus_samples_reg, dev_attr)
#define to_samples_reg(x) container_of(x, struct pmbus_samples_reg, attribute)
static ssize_t pmbus_show_samples(struct device *dev,
struct device_attribute *devattr, char *buf)
{
int val;
struct i2c_client *client = to_i2c_client(dev->parent);
struct pmbus_samples_reg *reg = to_samples_reg(devattr);
struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
struct pmbus_samples_reg *reg = to_samples_reg(attr);
scoped_guard(pmbus_lock, client) {
val = _pmbus_read_word_data(client, reg->page, 0xff, reg->attr->reg);
@ -2444,7 +2447,8 @@ static ssize_t pmbus_set_samples(struct device *dev,
int ret;
long val;
struct i2c_client *client = to_i2c_client(dev->parent);
struct pmbus_samples_reg *reg = to_samples_reg(devattr);
struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
struct pmbus_samples_reg *reg = to_samples_reg(attr);
if (kstrtol(buf, 0, &val) < 0)
return -EINVAL;
@ -2459,6 +2463,7 @@ static ssize_t pmbus_set_samples(struct device *dev,
static int pmbus_add_samples_attr(struct pmbus_data *data, int page,
struct pmbus_samples_attr *attr)
{
struct sensor_device_attribute *a;
struct pmbus_samples_reg *reg;
reg = devm_kzalloc(data->dev, sizeof(*reg), GFP_KERNEL);
@ -2468,10 +2473,12 @@ static int pmbus_add_samples_attr(struct pmbus_data *data, int page,
reg->attr = attr;
reg->page = page;
pmbus_dev_attr_init(&reg->dev_attr, attr->name, 0644,
pmbus_show_samples, pmbus_set_samples);
a = &reg->attribute;
return pmbus_add_attribute(data, &reg->dev_attr.attr);
pmbus_attr_init(a, attr->name, 0644,
pmbus_show_samples, pmbus_set_samples, -1);
return pmbus_add_attribute(data, &a->dev_attr.attr);
}
static int pmbus_add_samples_attributes(struct i2c_client *client,
@ -2979,9 +2986,15 @@ static void pmbus_notify(struct pmbus_data *data, int page, int reg, int flags)
struct device_attribute *da = to_dev_attr(data->group.attrs[i]);
struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
int index = attr->index;
u16 smask = pb_index_to_mask(index);
u8 spage = pb_index_to_page(index);
u16 sreg = pb_index_to_reg(index);
u16 smask, sreg;
u8 spage;
if (index == -1)
continue;
smask = pb_index_to_mask(index);
spage = pb_index_to_page(index);
sreg = pb_index_to_reg(index);
if (reg == sreg && page == spage && (smask & flags)) {
dev_dbg(data->dev, "sysfs notify: %s", da->attr.name);
@ -3427,6 +3440,8 @@ static int pmbus_write_smbalert_mask(struct i2c_client *client, u8 page, u8 reg,
{
int ret;
guard(pmbus_lock)(client);
ret = _pmbus_write_word_data(client, page, PMBUS_SMBALERT_MASK, reg | (val << 8));
/*
@ -3662,6 +3677,8 @@ static void pmbus_init_debugfs(struct i2c_client *client,
if (!entries)
return;
guard(pmbus_lock)(client);
/*
* Add device-specific entries.
* Please note that the PMBUS standard allows all registers to be

View File

@ -21,6 +21,7 @@
#include <linux/init.h>
#include <linux/input/mt.h>
#include <linux/major.h>
#include <linux/nospec.h>
#include <linux/device.h>
#include <linux/cdev.h>
#include "input-compat.h"
@ -67,8 +68,10 @@ static size_t evdev_get_mask_cnt(unsigned int type)
[EV_SND] = SND_CNT,
[EV_FF] = FF_CNT,
};
unsigned long mask = array_index_mask_nospec(type, EV_CNT);
return (type < EV_CNT) ? counts[type] : 0;
/* Returns 0 for out-of-bounds types, including speculatively */
return counts[type & mask] & mask;
}
/* requires the buffer lock to be held */
@ -146,11 +149,11 @@ static void __evdev_queue_syn_dropped(struct evdev_client *client)
struct timespec64 ts = ktime_to_timespec64(ev_time[client->clk_type]);
struct input_event ev;
memset(&ev, 0, sizeof(ev));
ev.input_event_sec = ts.tv_sec;
ev.input_event_usec = ts.tv_nsec / NSEC_PER_USEC;
ev.type = EV_SYN;
ev.code = SYN_DROPPED;
ev.value = 0;
client->buffer[client->head++] = ev;
client->head &= client->bufsize - 1;
@ -218,20 +221,20 @@ static void __pass_event(struct evdev_client *client,
client->head &= client->bufsize - 1;
if (unlikely(client->head == client->tail)) {
struct input_event ev;
memset(&ev, 0, sizeof(ev));
ev.input_event_sec = event->input_event_sec;
ev.input_event_usec = event->input_event_usec;
ev.type = EV_SYN;
ev.code = SYN_DROPPED;
/*
* This effectively "drops" all unconsumed events, leaving
* EV_SYN/SYN_DROPPED plus the newest event in the queue.
*/
client->tail = (client->head - 2) & (client->bufsize - 1);
client->buffer[client->tail] = (struct input_event) {
.input_event_sec = event->input_event_sec,
.input_event_usec = event->input_event_usec,
.type = EV_SYN,
.code = SYN_DROPPED,
.value = 0,
};
client->buffer[client->tail] = ev;
client->packet_head = client->tail;
}
@ -253,6 +256,8 @@ static void evdev_pass_values(struct evdev_client *client,
if (client->revoked)
return;
memset(&event, 0, sizeof(event));
ts = ktime_to_timespec64(ev_time[client->clk_type]);
event.input_event_sec = ts.tv_sec;
event.input_event_usec = ts.tv_nsec / NSEC_PER_USEC;

View File

@ -155,6 +155,9 @@ void iforce_process_packet(struct iforce *iforce,
switch (packet_id) {
case 0x01: /* joystick position data */
if (len < 7)
break;
input_report_abs(dev, ABS_X,
(__s16) get_unaligned_le16(data));
input_report_abs(dev, ABS_Y,
@ -170,6 +173,9 @@ void iforce_process_packet(struct iforce *iforce,
break;
case 0x03: /* wheel position data */
if (len < 7)
break;
input_report_abs(dev, ABS_WHEEL,
(__s16) get_unaligned_le16(data));
input_report_abs(dev, ABS_GAS, 255 - data[2]);
@ -181,6 +187,9 @@ void iforce_process_packet(struct iforce *iforce,
break;
case 0x02: /* status report */
if (len < 2)
break;
input_report_key(dev, BTN_DEAD, data[0] & 0x02);
input_sync(dev);
@ -200,7 +209,7 @@ void iforce_process_packet(struct iforce *iforce,
}
}
for (j = 3; j < len; j += 2)
for (j = 3; j + sizeof(u16) <= len; j += sizeof(u16))
mark_core_as_ready(iforce, get_unaligned_le16(data + j));
break;

View File

@ -158,6 +158,9 @@ static void iforce_usb_irq(struct urb *urb)
goto exit;
}
if (!urb->actual_length)
goto exit;
iforce_process_packet(iforce, iforce_usb->data_in[0],
iforce_usb->data_in + 1, urb->actual_length - 1);

View File

@ -373,6 +373,7 @@ static int psxpad_spi_probe(struct spi_device *spi)
return err;
}
spi_set_drvdata(spi, pad);
pm_runtime_enable(&spi->dev);
return 0;

View File

@ -394,6 +394,7 @@ static const struct xpad_device {
{ 0x3285, 0x0646, "Nacon Pro Compact", 0, XTYPE_XBOXONE },
{ 0x3285, 0x0662, "Nacon Revolution5 Pro", 0, XTYPE_XBOX360 },
{ 0x3285, 0x0663, "Nacon Evol-X", 0, XTYPE_XBOXONE },
{ 0x3507, 0x000b, "ZENAIM LEVERLESS", 0, XTYPE_XBOX360 },
{ 0x3537, 0x1004, "GameSir T4 Kaleid", 0, XTYPE_XBOX360 },
{ 0x3537, 0x100f, "GameSir Nova 2 Lite", 0, XTYPE_XBOX360 },
{ 0x3537, 0x1010, "GameSir G7 SE", 0, XTYPE_XBOXONE },
@ -557,6 +558,7 @@ static const struct usb_device_id xpad_table[] = {
XPAD_XBOX360_VENDOR(0x31e3), /* Wooting Keyboards */
XPAD_XBOX360_VENDOR(0x3285), /* Nacon GC-100 */
XPAD_XBOXONE_VENDOR(0x3285), /* Nacon Evol-X */
XPAD_XBOX360_VENDOR(0x3507), /* ZENAIM Controllers */
XPAD_XBOX360_VENDOR(0x3537), /* GameSir Controllers */
XPAD_XBOXONE_VENDOR(0x3537), /* GameSir Controllers */
XPAD_XBOX360_VENDOR(0x3651), /* CRKD Controllers */

View File

@ -1916,6 +1916,13 @@ static const struct dmi_system_id atkbd_dmi_quirk_table[] __initconst = {
},
.callback = atkbd_deactivate_fixup,
},
{
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "HONOR"),
DMI_MATCH(DMI_PRODUCT_NAME, "BCC-N"),
},
.callback = atkbd_deactivate_fixup,
},
{
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "HONOR"),
@ -1923,6 +1930,14 @@ static const struct dmi_system_id atkbd_dmi_quirk_table[] __initconst = {
},
.callback = atkbd_deactivate_fixup,
},
{
/* HONOR MagicBook Pro 14 2026 */
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "HONOR"),
DMI_MATCH(DMI_PRODUCT_NAME, "ZQC-P"),
},
.callback = atkbd_deactivate_fixup,
},
{
/* Lenovo Yoga Air 14 (83QK) */
.matches = {
@ -1932,9 +1947,10 @@ static const struct dmi_system_id atkbd_dmi_quirk_table[] __initconst = {
.callback = atkbd_deactivate_fixup,
},
{
/* Xiaomi Book Pro 14 (TM2424) */
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "HONOR"),
DMI_MATCH(DMI_PRODUCT_NAME, "BCC-N"),
DMI_MATCH(DMI_SYS_VENDOR, "XIAOMI"),
DMI_MATCH(DMI_PRODUCT_NAME, "Xiaomi Book Pro 14"),
},
.callback = atkbd_deactivate_fixup,
},

View File

@ -139,10 +139,10 @@ static struct cs40l50_effect *cs40l50_find_effect(int id, struct list_head *effe
static int cs40l50_effect_bank_set(struct cs40l50_work *work_data,
struct cs40l50_effect *effect)
{
s16 bank_type = work_data->custom_data[0] & CS40L50_CUSTOM_DATA_MASK;
u32 bank_type = work_data->custom_data[0] & CS40L50_CUSTOM_DATA_MASK;
if (bank_type >= CS40L50_WVFRM_BANK_NUM) {
dev_err(work_data->vib->dev, "Invalid bank (%d)\n", bank_type);
dev_err(work_data->vib->dev, "Invalid bank (%u)\n", bank_type);
return -EINVAL;
}
@ -326,6 +326,12 @@ static int cs40l50_add(struct input_dev *dev, struct ff_effect *effect,
return -EINVAL;
}
if (periodic->custom_len < CS40L50_OWT_CUSTOM_DATA_SIZE) {
dev_err(vib->dev, "Invalid custom data length (%u)\n",
periodic->custom_len);
return -EINVAL;
}
work_data.custom_data = memdup_array_user(effect->u.periodic.custom_data,
effect->u.periodic.custom_len,
sizeof(s16));

View File

@ -423,7 +423,7 @@ static void byd_disconnect(struct psmouse *psmouse)
struct byd_data *priv = psmouse->private;
if (priv) {
timer_delete(&priv->timer);
timer_shutdown_sync(&priv->timer);
kfree(psmouse->private);
psmouse->private = NULL;
}

View File

@ -197,7 +197,7 @@ static void focaltech_process_rel_packet(struct psmouse *psmouse,
{
struct focaltech_data *priv = psmouse->private;
struct focaltech_hw_state *state = &priv->state;
int finger1, finger2;
unsigned int finger1, finger2;
state->pressed = packet[0] >> 7;
finger1 = ((packet[0] >> 4) & 0x7) - 1;

View File

@ -104,7 +104,9 @@ struct f54_data {
enum rmi_f54_report_type report_type;
u8 *report_data;
size_t max_report_size;
int report_size;
int report_error;
bool is_busy;
struct mutex status_mutex;
@ -339,6 +341,12 @@ static void rmi_f54_buffer_queue(struct vb2_buffer *vb)
mutex_lock(&f54->data_mutex);
}
if (f54->report_error) {
dev_err(&f54->fn->dev, "Error acquiring report: %d\n", f54->report_error);
state = VB2_BUF_STATE_ERROR;
goto data_done;
}
ptr = vb2_plane_vaddr(vb, 0);
if (!ptr) {
dev_err(&f54->fn->dev, "Error acquiring frame ptr\n");
@ -444,7 +452,12 @@ static int rmi_f54_set_input(struct f54_data *f54, unsigned int i)
static int rmi_f54_vidioc_s_input(struct file *file, void *priv, unsigned int i)
{
return rmi_f54_set_input(video_drvdata(file), i);
struct f54_data *f54 = video_drvdata(file);
if (vb2_is_busy(&f54->queue))
return -EBUSY;
return rmi_f54_set_input(f54, i);
}
static int rmi_f54_vidioc_g_input(struct file *file, void *priv,
@ -545,7 +558,14 @@ static void rmi_f54_work(struct work_struct *work)
dev_err(&fn->dev, "Bad report size, report type=%d\n",
f54->report_type);
error = -EINVAL;
goto error; /* retry won't help */
goto out; /* retry won't help */
}
if (report_size > f54->max_report_size) {
dev_err(&fn->dev, "Report size %d exceeds buffer size %zu\n",
report_size, f54->max_report_size);
error = -EINVAL;
goto out;
}
/*
@ -556,7 +576,7 @@ static void rmi_f54_work(struct work_struct *work)
&command);
if (error) {
dev_err(&fn->dev, "Failed to read back command\n");
goto error;
goto out;
}
if (command & F54_GET_REPORT) {
if (time_after(jiffies, f54->timeout)) {
@ -564,7 +584,7 @@ static void rmi_f54_work(struct work_struct *work)
error = -ETIMEDOUT;
}
report_size = 0;
goto error;
goto out;
}
rmi_dbg(RMI_DEBUG_FN, &fn->dev, "Get report command completed, reading data\n");
@ -579,7 +599,7 @@ static void rmi_f54_work(struct work_struct *work)
fifo, sizeof(fifo));
if (error) {
dev_err(&fn->dev, "Failed to set fifo start offset\n");
goto abort;
goto out;
}
error = rmi_read_block(fn->rmi_dev, fn->fd.data_base_addr +
@ -588,16 +608,17 @@ static void rmi_f54_work(struct work_struct *work)
if (error) {
dev_err(&fn->dev, "%s: read [%d bytes] returned %d\n",
__func__, size, error);
goto abort;
goto out;
}
}
abort:
f54->report_size = error ? 0 : report_size;
error:
out:
if (error)
report_size = 0;
f54->report_size = report_size;
f54->report_error = error;
if (report_size == 0 && !error) {
queue_delayed_work(f54->workqueue, &f54->work,
msecs_to_jiffies(1));
@ -678,8 +699,8 @@ static int rmi_f54_probe(struct rmi_function *fn)
rx = f54->num_rx_electrodes;
tx = f54->num_tx_electrodes;
f54->report_data = devm_kzalloc(&fn->dev,
array3_size(tx, rx, sizeof(u16)),
f54->max_report_size = array3_size(tx, rx, sizeof(u16));
f54->report_data = devm_kzalloc(&fn->dev, f54->max_report_size,
GFP_KERNEL);
if (f54->report_data == NULL)
return -ENOMEM;

View File

@ -54,10 +54,10 @@ static int rmi_f55_detect(struct rmi_function *fn)
f55->num_tx_electrodes = f55->qry[F55_NUM_TX_OFFSET];
f55->cfg_num_rx_electrodes = f55->num_rx_electrodes;
f55->cfg_num_tx_electrodes = f55->num_rx_electrodes;
f55->cfg_num_tx_electrodes = f55->num_tx_electrodes;
drv_data->num_rx_electrodes = f55->cfg_num_rx_electrodes;
drv_data->num_tx_electrodes = f55->cfg_num_rx_electrodes;
drv_data->num_tx_electrodes = f55->cfg_num_tx_electrodes;
if (f55->qry[F55_PHYS_CHAR_OFFSET] & F55_CAP_SENSOR_ASSIGN) {
int i, total;

View File

@ -331,6 +331,8 @@ static irqreturn_t edt_ft5x06_ts_isr(int irq, void *dev_id)
swap(x, y);
id = (buf[2] >> 4) & 0x0f;
if (id >= tsdata->max_support_points)
continue;
input_mt_slot(tsdata->input, id);
if (input_mt_report_slot_state(tsdata->input, MT_TOOL_FINGER,

View File

@ -312,6 +312,12 @@ static void cst3xx_touch_report(struct i2c_client *client)
return;
touch_cnt = buf[5] & CST3XX_TOUCH_COUNT_MASK;
if (touch_cnt > ts_data->chip->max_touch_num) {
dev_err(&client->dev, "cst3xx invalid touch count (%d vs %d max)\n",
touch_cnt, ts_data->chip->max_touch_num);
return;
}
/*
* Check the check bit of the last touch slot. The check bit is
* always present after touch point 1 for valid data, and then
@ -334,9 +340,10 @@ static void cst3xx_touch_report(struct i2c_client *client)
finger_id = (buf[idx] >> 4) & 0x0f;
/* Sanity check we don't have more fingers than we expect */
if (ts_data->chip->max_touch_num < finger_id) {
dev_err(&client->dev, "cst3xx touch read failure\n");
break;
if (finger_id >= ts_data->chip->max_touch_num) {
dev_err(&client->dev,
"cst3xx invalid finger id %d\n", finger_id);
return;
}
/* sw value of 0 means no touch, 0x03 means touch */

Some files were not shown because too many files have changed in this diff Show More