Merge remote-tracking branch 'torvalds/master' into perf-tools-next

To pick up fixes and get in sync with other tools/ libraries used by
perf.

Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
This commit is contained in:
Arnaldo Carvalho de Melo 2026-05-26 11:34:42 -03:00
commit 2aa8946ed9
537 changed files with 7895 additions and 2832 deletions

View File

@ -584,6 +584,8 @@ Mayuresh Janorkar <mayur@ti.com>
Md Sadre Alam <quic_mdalam@quicinc.com> <mdalam@codeaurora.org>
Miaoqing Pan <quic_miaoqing@quicinc.com> <miaoqing@codeaurora.org>
Michael Buesch <m@bues.ch>
Michal Grzeschik <mgr@kernel.org> <m.grzeschik@pengutronix.de>
Michal Grzeschik <mgr@kernel.org> <mgr@pengutronix.de>
Michael Riesch <michael.riesch@collabora.com> <michael.riesch@wolfvision.net>
Michal Simek <michal.simek@amd.com> <michal.simek@xilinx.com>
Michel Dänzer <michel@tungstengraphics.com>

View File

@ -786,6 +786,7 @@ networking/altera_tse networking/device_drivers/ethernet/altera/altera_tse
networking/bpf_flow_dissector bpf/prog_flow_dissector
networking/cxacru networking/device_drivers/atm/cxacru
networking/defza networking/device_drivers/fddi/defza
networking/device_drivers/3com/3c509 networking/device_drivers/ethernet/3com/3c509
networking/device_drivers/3com/vortex networking/device_drivers/ethernet/3com/vortex
networking/device_drivers/amazon/ena networking/device_drivers/ethernet/amazon/ena
networking/device_drivers/aquantia/atlantic networking/device_drivers/ethernet/aquantia/atlantic

View File

@ -43,6 +43,11 @@ Support for changing the platform performance mode is currently not implemented.
Battery Charging Control
------------------------
.. warning:: Some devices do not properly implement the charging threshold interface. Forcing
the driver to enable access to said interface on such devices might damage the
battery [1]_. Because of this the driver will not enable said feature even when
using the ``force`` module parameter.
The ``uniwill-laptop`` driver supports controlling the battery charge limit. This happens over
the standard ``charge_control_end_threshold`` power supply sysfs attribute. All values
between 1 and 100 percent are supported.
@ -70,3 +75,8 @@ The ``uniwill-laptop`` driver allows to set the configurable TGP for devices wit
allow it.
See Documentation/ABI/testing/sysfs-driver-uniwill-laptop for details.
References
==========
.. [1] https://www.reddit.com/r/XMG_gg/comments/ld9yyf/battery_limit_hidden_function_discovered_on/

View File

@ -358,9 +358,9 @@ Dynamic energy performance profile
The amd-pstate driver supports dynamically selecting the energy performance
profile based on whether the machine is running on AC or DC power.
Whether this behavior is enabled by default depends on the kernel
config option `CONFIG_X86_AMD_PSTATE_DYNAMIC_EPP`. This behavior can also be overridden
at runtime by the sysfs file ``/sys/devices/system/cpu/cpufreq/policyX/dynamic_epp``.
Whether this behavior is enabled by default depends on the kernel command line option
``amd_dynamic_epp`` is set. This behavior can also be overridden
at runtime by the sysfs file ``/sys/devices/system/cpu/amd_pstate/dynamic_epp``.
When set to enabled, the driver will select a different energy performance
profile when the machine is running on battery or AC power. The driver will
@ -485,9 +485,8 @@ kernel parameter ``amd_prefcore=disable``.
``amd_dynamic_epp``
When AMD pstate is in auto mode, dynamic EPP will control whether the kernel
autonomously changes the EPP mode. The default is configured by
``CONFIG_X86_AMD_PSTATE_DYNAMIC_EPP`` but can be explicitly enabled with
``amd_dynamic_epp=enable`` or disabled with ``amd_dynamic_epp=disable``.
autonomously changes the EPP mode. The default is disabled. It can be enabled
with the kernel parameter ``amd_dynamic_epp=enable``.
User Space Interface in ``sysfs`` - General
===========================================

View File

@ -355,11 +355,12 @@ HyperThreading (HT) in the context of Intel processors, is enabled on at least
one core, ``intel_pstate`` assigns performance-based priorities to CPUs. Namely,
the priority of a given CPU reflects its highest HWP performance level which
causes the CPU scheduler to generally prefer more performant CPUs, so the less
performant CPUs are used when the other ones are fully loaded. However, SMT
siblings (that is, logical CPUs sharing one physical core) are treated in a
special way such that if one of them is in use, the effective priority of the
other ones is lowered below the priorities of the CPUs located in the other
physical cores.
performant CPUs are used when the other ones are fully loaded. SMT siblings
(that is, logical CPUs sharing one physical core) are given the same priority.
The scheduler can pull tasks from lower-priority cores and place them on any
sibling. Since the scheduler spreads tasks among physical cores, tasks will be
placed on the SMT siblings of physical cores only after all physical cores are
busy.
This approach maximizes performance in the majority of cases, but unfortunately
it also leads to excessive energy usage in some important scenarios, like video

View File

@ -158,13 +158,22 @@ returned.
When a message has been received, the location and size of the data with the
message can be determined by calling::
void crypto_krb5_where_is_the_data(const struct krb5_enctype *krb5,
enum krb5_crypto_mode mode,
size_t *_offset, size_t *_len);
int crypto_krb5_where_is_the_data(const struct krb5_enctype *krb5,
enum krb5_crypto_mode mode,
size_t *_offset, size_t *_len);
The caller provides the offset and length of the message to the function, which
then alters those values to indicate the region containing the data (plus any
padding). It is up to the caller to determine how much padding there is.
padding). It is up to the caller to determine how much padding there is. The
function returns an error if the length is too small or if the mode is
unsupported. An additional function::
int crypto_krb5_check_data_len(const struct krb5_enctype *krb5,
enum krb5_crypto_mode mode,
size_t len, size_t min_content);
is provided to just do a basic check that the decrypted/verified message would
have a sufficient minimum payload.
Preparation Functions
---------------------

View File

@ -219,6 +219,7 @@ allOf:
- required:
- "#sound-dai-cells"
else:
$ref: /schemas/sound/dai-common.yaml#
properties:
aux-bus: false
required:
@ -243,7 +244,7 @@ allOf:
clocks:
minItems: 5
maxItems: 5
clocks-names:
clock-names:
minItems: 5
maxItems: 5
@ -264,7 +265,7 @@ allOf:
clocks:
minItems: 5
maxItems: 6
clocks-names:
clock-names:
minItems: 5
maxItems: 6
@ -277,7 +278,6 @@ allOf:
- qcom,sc8180x-dp
- qcom,sdm845-dp
- qcom,sm8350-dp
- qcom,sm8650-dp
then:
properties:
reg:
@ -286,6 +286,24 @@ allOf:
clocks:
minItems: 6
maxItems: 6
clock-names:
minItems: 6
maxItems: 6
- if:
properties:
compatible:
contains:
enum:
- qcom,sm8650-dp
then:
properties:
reg:
minItems: 5
maxItems: 9
clocks:
minItems: 6
maxItems: 6
clocks-names:
minItems: 6
maxItems: 6
@ -306,7 +324,7 @@ allOf:
clocks:
minItems: 6
maxItems: 8
clocks-names:
clock-names:
minItems: 6
maxItems: 8
@ -326,7 +344,7 @@ allOf:
clocks:
minItems: 5
maxItems: 6
clocks-names:
clock-names:
minItems: 5
maxItems: 6

View File

@ -119,7 +119,7 @@ examples:
mdss_mdp: display-controller@ae01000 {
compatible = "qcom,eliza-dpu";
reg = <0x0ae01000 0x93000>,
<0x0aeb0000 0x2008>;
<0x0aeb0000 0x3000>;
reg-names = "mdp",
"vbif";
@ -304,7 +304,7 @@ examples:
mdss_dsi0_phy: phy@ae95000 {
compatible = "qcom,eliza-dsi-phy-4nm", "qcom,sm8650-dsi-phy-4nm";
reg = <0x0ae95000 0x200>,
<0x0ae95200 0x280>,
<0x0ae95200 0x300>,
<0x0ae95500 0x400>;
reg-names = "dsi_phy",
"dsi_phy_lane",
@ -388,7 +388,7 @@ examples:
mdss_dsi1_phy: phy@ae97000 {
compatible = "qcom,eliza-dsi-phy-4nm", "qcom,sm8650-dsi-phy-4nm";
reg = <0x0ae97000 0x200>,
<0x0ae97200 0x280>,
<0x0ae97200 0x300>,
<0x0ae97500 0x400>;
reg-names = "dsi_phy",
"dsi_phy_lane",
@ -407,11 +407,15 @@ examples:
displayport-controller@af54000 {
compatible = "qcom,eliza-dp", "qcom,sm8650-dp";
reg = <0xaf54000 0x104>,
<0xaf54200 0xc0>,
<0xaf55000 0x770>,
<0xaf56000 0x9c>,
<0xaf57000 0x9c>;
reg = <0x0af54000 0x200>,
<0x0af54200 0x200>,
<0x0af55000 0xc00>,
<0x0af56000 0x400>,
<0x0af57000 0x400>,
<0x0af58000 0x400>,
<0x0af59000 0x400>,
<0x0af5a000 0x600>,
<0x0af5b000 0x600>;
interrupts-extended = <&mdss 12>;

View File

@ -70,7 +70,7 @@ examples:
display-controller@ae01000 {
compatible = "qcom,sm8650-dpu";
reg = <0x0ae01000 0x8f000>,
<0x0aeb0000 0x2008>;
<0x0aeb0000 0x3000>;
reg-names = "mdp", "vbif";
clocks = <&gcc_axi_clk>,

View File

@ -112,7 +112,7 @@ examples:
display-controller@ae01000 {
compatible = "qcom,sm8650-dpu";
reg = <0x0ae01000 0x8f000>,
<0x0aeb0000 0x2008>;
<0x0aeb0000 0x3000>;
reg-names = "mdp", "vbif";
clocks = <&gcc_axi_clk>,

View File

@ -117,7 +117,7 @@ examples:
display-controller@ae01000 {
compatible = "qcom,sm8750-dpu";
reg = <0x0ae01000 0x93000>,
<0x0aeb0000 0x2008>;
<0x0aeb0000 0x3000>;
reg-names = "mdp",
"vbif";
@ -389,11 +389,15 @@ examples:
displayport-controller@af54000 {
compatible = "qcom,sm8750-dp", "qcom,sm8650-dp";
reg = <0xaf54000 0x104>,
<0xaf54200 0xc0>,
<0xaf55000 0x770>,
<0xaf56000 0x9c>,
<0xaf57000 0x9c>;
reg = <0x0af54000 0x200>,
<0x0af54200 0x200>,
<0x0af55000 0xc00>,
<0x0af56000 0x400>,
<0x0af57000 0x400>,
<0x0af58000 0x400>,
<0x0af59000 0x400>,
<0x0af5a000 0x600>,
<0x0af5b000 0x600>;
interrupts-extended = <&mdss 12>;

View File

@ -73,6 +73,15 @@ properties:
HSP CSR is to control and get status of different high-speed peripherals
(such as Ethernet, USB, SATA, etc.) via register, which can tune
board-level's parameters of PHY, etc.
Additional background information about the High-Speed Subsystem
and the HSP CSR block is available in Chapter 10 ("High-Speed Interface")
of the EIC7700X SoC Technical Reference Manual, Part 4
(EIC7700X_SoC_Technical_Reference_Manual_Part4.pdf). The manual is
publicly available at
https://github.com/eswincomputing/EIC7700X-SoC-Technical-Reference-Manual/releases
This reference is provided for background information only.
$ref: /schemas/types.yaml#/definitions/phandle-array
items:
- items:
@ -82,6 +91,8 @@ properties:
- description: Offset of AXI clock controller Low-Power request
register
- description: Offset of register controlling TX/RX clock delay
- description: Optional offset of register controlling TXD delay
- description: Optional offset of register controlling RXD delay
required:
- compatible
@ -116,7 +127,7 @@ examples:
reset-names = "stmmaceth";
rx-internal-delay-ps = <200>;
tx-internal-delay-ps = <200>;
eswin,hsp-sp-csr = <&hsp_sp_csr 0x100 0x108 0x118>;
eswin,hsp-sp-csr = <&hsp_sp_csr 0x100 0x108 0x118 0x114 0x11c>;
snps,axi-config = <&stmmac_axi_setup>;
snps,aal;
snps,fixed-burst;

View File

@ -18,7 +18,9 @@ properties:
description: Phandles of rt5650 and rt5514 codecs
items:
- description: phandle of rt5650 codec
maxItems: 1
- description: phandle of rt5514 codec
maxItems: 1
mediatek,platform:
$ref: /schemas/types.yaml#/definitions/phandle

View File

@ -20,6 +20,9 @@ properties:
- fsl,ls1021a-qspi
- fsl,ls2080a-qspi
- spacemit,k1-qspi
- items:
- const: spacemit,k3-qspi
- const: spacemit,k1-qspi
- items:
- enum:
- fsl,ls1043a-qspi

View File

@ -0,0 +1,249 @@
.. SPDX-License-Identifier: GPL-2.0
=============================================================================
Linux and the 3Com EtherLink III Series Ethercards (driver v1.18c and higher)
=============================================================================
This file contains the instructions and caveats for v1.18c and higher versions
of the 3c509 driver. You should not use the driver without reading this file.
release 1.0
28 February 2002
Current maintainer (corrections to):
Maciej W. Rozycki <macro@orcam.me.uk>
Introduction
============
The following are notes and information on using the 3Com EtherLink III series
ethercards in Linux. These cards are commonly known by the most widely-used
card's 3Com model number, 3c509. They are all 10mb/s ISA-bus cards and shouldn't
be (but sometimes are) confused with the similarly-numbered PCI-bus "3c905"
(aka "Vortex" or "Boomerang") series. Kernel support for the 3c509 family is
provided by the module 3c509.c, which has code to support all of the following
models:
- 3c509 (original ISA card)
- 3c509B (later revision of the ISA card; supports full-duplex)
- 3c589 (PCMCIA)
- 3c589B (later revision of the 3c589; supports full-duplex)
- 3c579 (EISA)
Large portions of this documentation were heavily borrowed from the guide
written the original author of the 3c509 driver, Donald Becker. The master
copy of that document, which contains notes on older versions of the driver,
currently resides on Scyld web server: http://www.scyld.com/.
Special Driver Features
=======================
Overriding card settings
The driver allows boot- or load-time overriding of the card's detected IOADDR,
IRQ, and transceiver settings, although this capability shouldn't generally be
needed except to enable full-duplex mode (see below). An example of the syntax
for LILO parameters for doing this::
ether=10,0x310,3,0x3c509,eth0
This configures the first found 3c509 card for IRQ 10, base I/O 0x310, and
transceiver type 3 (10base2). The flag "0x3c509" must be set to avoid conflicts
with other card types when overriding the I/O address. When the driver is
loaded as a module, only the IRQ may be overridden. For example,
setting two cards to IRQ10 and IRQ11 is done by using the irq module
option::
options 3c509 irq=10,11
Full-duplex mode
================
The v1.18c driver added support for the 3c509B's full-duplex capabilities.
In order to enable and successfully use full-duplex mode, three conditions
must be met:
(a) You must have a Etherlink III card model whose hardware supports full-
duplex operations. Currently, the only members of the 3c509 family that are
positively known to support full-duplex are the 3c509B (ISA bus) and 3c589B
(PCMCIA) cards. Cards without the "B" model designation do *not* support
full-duplex mode; these include the original 3c509 (no "B"), the original
3c589, the 3c529 (MCA bus), and the 3c579 (EISA bus).
(b) You must be using your card's 10baseT transceiver (i.e., the RJ-45
connector), not its AUI (thick-net) or 10base2 (thin-net/coax) interfaces.
AUI and 10base2 network cabling is physically incapable of full-duplex
operation.
(c) Most importantly, your 3c509B must be connected to a link partner that is
itself full-duplex capable. This is almost certainly one of two things: a full-
duplex-capable Ethernet switch (*not* a hub), or a full-duplex-capable NIC on
another system that's connected directly to the 3c509B via a crossover cable.
Full-duplex mode can be enabled using 'ethtool'.
.. warning::
Extremely important caution concerning full-duplex mode
Understand that the 3c509B's hardware's full-duplex support is much more
limited than that provide by more modern network interface cards. Although
at the physical layer of the network it fully supports full-duplex operation,
the card was designed before the current Ethernet auto-negotiation (N-way)
spec was written. This means that the 3c509B family ***cannot and will not
auto-negotiate a full-duplex connection with its link partner under any
circumstances, no matter how it is initialized***. If the full-duplex mode
of the 3c509B is enabled, its link partner will very likely need to be
independently _forced_ into full-duplex mode as well; otherwise various nasty
failures will occur - at the very least, you'll see massive numbers of packet
collisions. This is one of very rare circumstances where disabling auto-
negotiation and forcing the duplex mode of a network interface card or switch
would ever be necessary or desirable.
Available Transceiver Types
===========================
For versions of the driver v1.18c and above, the available transceiver types are:
== =========================================================================
0 transceiver type from EEPROM config (normally 10baseT); force half-duplex
1 AUI (thick-net / DB15 connector)
2 (undefined)
3 10base2 (thin-net == coax / BNC connector)
4 10baseT (RJ-45 connector); force half-duplex mode
8 transceiver type and duplex mode taken from card's EEPROM config settings
12 10baseT (RJ-45 connector); force full-duplex mode
== =========================================================================
Prior to driver version 1.18c, only transceiver codes 0-4 were supported. Note
that the new transceiver codes 8 and 12 are the *only* ones that will enable
full-duplex mode, no matter what the card's detected EEPROM settings might be.
This insured that merely upgrading the driver from an earlier version would
never automatically enable full-duplex mode in an existing installation;
it must always be explicitly enabled via one of these code in order to be
activated.
The transceiver type can be changed using 'ethtool'.
Interpretation of error messages and common problems
----------------------------------------------------
Error Messages
^^^^^^^^^^^^^^
eth0: Infinite loop in interrupt, status 2011.
These are "mostly harmless" message indicating that the driver had too much
work during that interrupt cycle. With a status of 0x2011 you are receiving
packets faster than they can be removed from the card. This should be rare
or impossible in normal operation. Possible causes of this error report are:
- a "green" mode enabled that slows the processor down when there is no
keyboard activity.
- some other device or device driver hogging the bus or disabling interrupts.
Check /proc/interrupts for excessive interrupt counts. The timer tick
interrupt should always be incrementing faster than the others.
No received packets
^^^^^^^^^^^^^^^^^^^
If a 3c509, 3c562 or 3c589 can successfully transmit packets, but never
receives packets (as reported by /proc/net/dev or 'ifconfig') you likely
have an interrupt line problem. Check /proc/interrupts to verify that the
card is actually generating interrupts. If the interrupt count is not
increasing you likely have a physical conflict with two devices trying to
use the same ISA IRQ line. The common conflict is with a sound card on IRQ10
or IRQ5, and the easiest solution is to move the 3c509 to a different
interrupt line. If the device is receiving packets but 'ping' doesn't work,
you have a routing problem.
Tx Carrier Errors Reported in /proc/net/dev
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
If an EtherLink III appears to transmit packets, but the "Tx carrier errors"
field in /proc/net/dev increments as quickly as the Tx packet count, you
likely have an unterminated network or the incorrect media transceiver selected.
3c509B card is not detected on machines with an ISA PnP BIOS.
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
While the updated driver works with most PnP BIOS programs, it does not work
with all. This can be fixed by disabling PnP support using the 3Com-supplied
setup program.
3c509 card is not detected on overclocked machines
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Increase the delay time in id_read_eeprom() from the current value, 500,
to an absurdly high value, such as 5000.
Decoding Status and Error Messages
----------------------------------
The bits in the main status register are:
===== ======================================
value description
===== ======================================
0x01 Interrupt latch
0x02 Tx overrun, or Rx underrun
0x04 Tx complete
0x08 Tx FIFO room available
0x10 A complete Rx packet has arrived
0x20 A Rx packet has started to arrive
0x40 The driver has requested an interrupt
0x80 Statistics counter nearly full
===== ======================================
The bits in the transmit (Tx) status word are:
===== ============================================
value description
===== ============================================
0x02 Out-of-window collision.
0x04 Status stack overflow (normally impossible).
0x08 16 collisions.
0x10 Tx underrun (not enough PCI bus bandwidth).
0x20 Tx jabber.
0x40 Tx interrupt requested.
0x80 Status is valid (this should always be set).
===== ============================================
When a transmit error occurs the driver produces a status message such as::
eth0: Transmit error, Tx status register 82
The two values typically seen here are:
0x82
^^^^
Out of window collision. This typically occurs when some other Ethernet
host is incorrectly set to full duplex on a half duplex network.
0x88
^^^^
16 collisions. This typically occurs when the network is exceptionally busy
or when another host doesn't correctly back off after a collision. If this
error is mixed with 0x82 errors it is the result of a host incorrectly set
to full duplex (see above).
Both of these errors are the result of network problems that should be
corrected. They do not represent driver malfunction.
Revision history (this file)
============================
28Feb02 v1.0 DR New; major portions based on Becker original 3c509 docs

View File

@ -10,6 +10,7 @@ Contents:
.. toctree::
:maxdepth: 2
3com/3c509
3com/vortex
amazon/ena
altera/altera_tse

View File

@ -2064,7 +2064,7 @@ F: Documentation/devicetree/bindings/display/snps,arcpgu.txt
F: drivers/gpu/drm/tiny/arcpgu.c
ARCNET NETWORK LAYER
M: Michael Grzeschik <m.grzeschik@pengutronix.de>
M: Michael Grzeschik <mgr@kernel.org>
L: netdev@vger.kernel.org
S: Maintained
F: drivers/net/arcnet/
@ -12791,7 +12791,6 @@ M: Cezary Rojewski <cezary.rojewski@intel.com>
M: Liam Girdwood <liam.r.girdwood@linux.intel.com>
M: Peter Ujfalusi <peter.ujfalusi@linux.intel.com>
M: Bard Liao <yung-chuan.liao@linux.intel.com>
M: Ranjani Sridharan <ranjani.sridharan@linux.intel.com>
M: Kai Vehmanen <kai.vehmanen@linux.intel.com>
R: Pierre-Louis Bossart <pierre-louis.bossart@linux.dev>
L: linux-sound@vger.kernel.org
@ -18638,6 +18637,7 @@ F: tools/testing/selftests/net/
X: Documentation/networking/mac80211-injection.rst
X: Documentation/networking/mac80211_hwsim/
X: Documentation/networking/regulatory.rst
X: include/net/bluetooth/
X: include/net/cfg80211.h
X: include/net/ieee80211_radiotap.h
X: include/net/iw_handler.h
@ -18947,7 +18947,8 @@ F: drivers/hid/hid-nintendo*
NIOS2 ARCHITECTURE
M: Dinh Nguyen <dinguyen@kernel.org>
S: Maintained
M: Simon Schuster <schuster.simon@siemens-energy.com>
S: Supported
T: git git://git.kernel.org/pub/scm/linux/kernel/git/dinguyen/linux.git
F: arch/nios2/
@ -19461,7 +19462,6 @@ F: include/misc/ocxl*
F: include/uapi/misc/ocxl.h
OMAP AUDIO SUPPORT
M: Peter Ujfalusi <peter.ujfalusi@gmail.com>
M: Jarkko Nikula <jarkko.nikula@bitmer.com>
L: linux-sound@vger.kernel.org
L: linux-omap@vger.kernel.org
@ -20743,15 +20743,13 @@ F: Documentation/devicetree/bindings/pci/intel,keembay-pcie*
F: drivers/pci/controller/dwc/pcie-keembay.c
PCIE DRIVER FOR INTEL LGM GW SOC
M: Chuanhua Lei <lchuanhua@maxlinear.com>
L: linux-pci@vger.kernel.org
S: Maintained
S: Orphan
F: Documentation/devicetree/bindings/pci/intel-gw-pcie.yaml
F: drivers/pci/controller/dwc/pcie-intel-gw.c
PCIE DRIVER FOR MEDIATEK
M: Ryder Lee <ryder.lee@mediatek.com>
M: Jianjun Wang <jianjun.wang@mediatek.com>
L: linux-pci@vger.kernel.org
L: linux-mediatek@lists.infradead.org (moderated for non-subscribers)
S: Supported
@ -25071,7 +25069,6 @@ SOUND - SOUND OPEN FIRMWARE (SOF) DRIVERS
M: Liam Girdwood <lgirdwood@gmail.com>
M: Peter Ujfalusi <peter.ujfalusi@linux.intel.com>
M: Bard Liao <yung-chuan.liao@linux.intel.com>
M: Ranjani Sridharan <ranjani.sridharan@linux.intel.com>
M: Daniel Baluta <daniel.baluta@nxp.com>
R: Kai Vehmanen <kai.vehmanen@linux.intel.com>
R: Pierre-Louis Bossart <pierre-louis.bossart@linux.dev>
@ -26364,7 +26361,7 @@ F: arch/xtensa/
F: drivers/irqchip/irq-xtensa-*
TEXAS INSTRUMENTS ASoC DRIVERS
M: Peter Ujfalusi <peter.ujfalusi@gmail.com>
M: Sen Wang <sen@ti.com>
L: linux-sound@vger.kernel.org
S: Maintained
F: Documentation/devicetree/bindings/sound/davinci-mcasp-audio.yaml
@ -26866,12 +26863,6 @@ S: Maintained
F: Documentation/devicetree/bindings/iio/adc/ti,tsc2046.yaml
F: drivers/iio/adc/ti-tsc2046.c
TI TWL4030 SERIES SOC CODEC DRIVER
M: Peter Ujfalusi <peter.ujfalusi@gmail.com>
L: linux-sound@vger.kernel.org
S: Maintained
F: sound/soc/codecs/twl4030*
TI VPE/CAL DRIVERS
M: Yemike Abhilash Chandra <y-abhilashchandra@ti.com>
L: linux-media@vger.kernel.org

View File

@ -2,7 +2,7 @@
VERSION = 7
PATCHLEVEL = 1
SUBLEVEL = 0
EXTRAVERSION = -rc4
EXTRAVERSION = -rc5
NAME = Baby Opossum Posse
# *DOCUMENTATION*

View File

@ -5,4 +5,5 @@ generic-y += agp.h
generic-y += asm-offsets.h
generic-y += kvm_para.h
generic-y += mcs_spinlock.h
generic-y += ring_buffer.h
generic-y += text-patching.h

View File

@ -5,5 +5,6 @@ generic-y += extable.h
generic-y += kvm_para.h
generic-y += mcs_spinlock.h
generic-y += parport.h
generic-y += ring_buffer.h
generic-y += user.h
generic-y += text-patching.h

View File

@ -3,6 +3,7 @@ generic-y += early_ioremap.h
generic-y += extable.h
generic-y += flat.h
generic-y += parport.h
generic-y += ring_buffer.h
generated-y += mach-types.h
generated-y += unistd-nr.h

View File

@ -409,7 +409,7 @@ __AARCH64_INSN_FUNCS(cbz, 0x7F000000, 0x34000000)
__AARCH64_INSN_FUNCS(cbnz, 0x7F000000, 0x35000000)
__AARCH64_INSN_FUNCS(tbz, 0x7F000000, 0x36000000)
__AARCH64_INSN_FUNCS(tbnz, 0x7F000000, 0x37000000)
__AARCH64_INSN_FUNCS(bcond, 0xFF000010, 0x54000000)
__AARCH64_INSN_FUNCS(bcond, 0xFF000000, 0x54000000)
__AARCH64_INSN_FUNCS(svc, 0xFFE0001F, 0xD4000001)
__AARCH64_INSN_FUNCS(hvc, 0xFFE0001F, 0xD4000002)
__AARCH64_INSN_FUNCS(smc, 0xFFE0001F, 0xD4000003)

View File

@ -0,0 +1,10 @@
/* SPDX-License-Identifier: GPL-2.0-only */
#ifndef _ASM_ARM64_RING_BUFFER_H
#define _ASM_ARM64_RING_BUFFER_H
#include <asm/cacheflush.h>
/* Flush D-cache on persistent ring buffer */
#define arch_ring_buffer_flush_range(start, end) dcache_clean_pop(start, end)
#endif /* _ASM_ARM64_RING_BUFFER_H */

View File

@ -53,7 +53,8 @@ static inline int tlb_get_level(struct mmu_gather *tlb)
static inline void tlb_flush(struct mmu_gather *tlb)
{
struct vm_area_struct vma = TLB_FLUSH_VMA(tlb->mm, 0);
tlbf_t flags = tlb->freed_tables ? TLBF_NONE : TLBF_NOWALKCACHE;
tlbf_t flags = (tlb->freed_tables || tlb->unshared_tables) ?
TLBF_NONE : TLBF_NOWALKCACHE;
unsigned long stride = tlb_get_unmap_size(tlb);
int tlb_level = tlb_get_level(tlb);

View File

@ -555,8 +555,10 @@ int kvm_arch_vcpu_create(struct kvm_vcpu *vcpu)
kvm_destroy_mpidr_data(vcpu->kvm);
err = kvm_vgic_vcpu_init(vcpu);
if (err)
if (err) {
kvm_vgic_vcpu_destroy(vcpu);
return err;
}
err = kvm_share_hyp(vcpu, vcpu + 1);
if (err)

View File

@ -164,13 +164,16 @@ static int hyp_trace_buffer_load(struct hyp_trace_buffer *trace_buffer,
return ret;
}
static bool hyp_trace_desc_validate(struct hyp_trace_desc *desc, size_t desc_size)
static bool hyp_trace_desc_is_valid(struct hyp_trace_desc *desc, size_t desc_size)
{
struct ring_buffer_desc *rb_desc;
unsigned int cpu;
size_t nr_bpages;
void *desc_end;
if (!is_protected_kvm_enabled())
return true;
/*
* Both desc_size and bpages_backing_size are untrusted host-provided
* values. We rely on __pkvm_host_donate_hyp() to enforce their validity.
@ -212,8 +215,10 @@ int __tracing_load(unsigned long desc_hva, size_t desc_size)
if (ret)
return ret;
if (!hyp_trace_desc_validate(desc, desc_size))
if (!hyp_trace_desc_is_valid(desc, desc_size)) {
ret = -EINVAL;
goto err_release_desc;
}
hyp_spin_lock(&trace_buffer.lock);

View File

@ -2307,6 +2307,10 @@ static int vgic_its_restore_dte(struct vgic_its *its, u32 id,
/* dte entry is valid */
offset = (entry & KVM_ITS_DTE_NEXT_MASK) >> KVM_ITS_DTE_NEXT_SHIFT;
/* Mimic the MAPD behaviour and reject invalid EID bits. */
if (num_eventid_bits > VITS_TYPER_IDBITS)
return -EINVAL;
if (!vgic_its_check_id(its, baser, id, NULL))
return -EINVAL;

View File

@ -9,6 +9,7 @@ generic-y += qrwlock.h
generic-y += qrwlock_types.h
generic-y += qspinlock.h
generic-y += parport.h
generic-y += ring_buffer.h
generic-y += user.h
generic-y += vmlinux.lds.h
generic-y += text-patching.h

View File

@ -5,4 +5,5 @@ generic-y += extable.h
generic-y += iomap.h
generic-y += kvm_para.h
generic-y += mcs_spinlock.h
generic-y += ring_buffer.h
generic-y += text-patching.h

View File

@ -10,5 +10,6 @@ generic-y += qrwlock.h
generic-y += user.h
generic-y += ioctl.h
generic-y += mmzone.h
generic-y += ring_buffer.h
generic-y += statfs.h
generic-y += text-patching.h

View File

@ -30,6 +30,8 @@ static inline unsigned long efi_get_kimg_min_align(void)
return SZ_2M;
}
#define EFI_KIMG_PREFERRED_ADDRESS PHYSADDR(VMLINUX_LOAD_ADDRESS)
unsigned long efi_get_kimg_kaslr_address(void);
#define EFI_KIMG_PREFERRED_ADDRESS efi_get_kimg_kaslr_address()
#endif /* _ASM_LOONGARCH_EFI_H */

View File

@ -4,6 +4,12 @@
#ifdef CONFIG_PARAVIRT
#include <linux/jump_label.h>
DECLARE_STATIC_KEY_FALSE(virt_preempt_key);
DECLARE_STATIC_KEY_FALSE(virt_spin_lock_key);
DECLARE_PER_CPU(struct kvm_steal_time, steal_time);
int __init pv_ipi_init(void);
int __init pv_time_init(void);
int __init pv_spinlock_init(void);

View File

@ -3,12 +3,9 @@
#define _ASM_LOONGARCH_QSPINLOCK_H
#include <asm/kvm_para.h>
#include <linux/jump_label.h>
#include <asm/paravirt.h>
#ifdef CONFIG_PARAVIRT
DECLARE_STATIC_KEY_FALSE(virt_preempt_key);
DECLARE_STATIC_KEY_FALSE(virt_spin_lock_key);
DECLARE_PER_CPU(struct kvm_steal_time, steal_time);
#define virt_spin_lock virt_spin_lock

View File

@ -60,16 +60,18 @@ NOKPROBE_SYMBOL(arch_prepare_kprobe);
/* Install breakpoint in text */
void arch_arm_kprobe(struct kprobe *p)
{
*p->addr = KPROBE_BP_INSN;
flush_insn_slot(p);
u32 insn = KPROBE_BP_INSN;
larch_insn_text_copy(p->addr, &insn, LOONGARCH_INSN_SIZE);
}
NOKPROBE_SYMBOL(arch_arm_kprobe);
/* Remove breakpoint from text */
void arch_disarm_kprobe(struct kprobe *p)
{
*p->addr = p->opcode;
flush_insn_slot(p);
u32 insn = p->opcode;
larch_insn_text_copy(p->addr, &insn, LOONGARCH_INSN_SIZE);
}
NOKPROBE_SYMBOL(arch_disarm_kprobe);
@ -184,16 +186,16 @@ static bool reenter_kprobe(struct kprobe *p, struct pt_regs *regs,
struct kprobe_ctlblk *kcb)
{
switch (kcb->kprobe_status) {
case KPROBE_HIT_SS:
case KPROBE_HIT_SSDONE:
case KPROBE_HIT_ACTIVE:
kprobes_inc_nmissed_count(p);
setup_singlestep(p, regs, kcb, 1);
break;
case KPROBE_HIT_SS:
case KPROBE_REENTER:
pr_warn("Failed to recover from reentered kprobes.\n");
dump_kprobe(p);
WARN_ON_ONCE(1);
BUG();
break;
default:
WARN_ON(1);

View File

@ -134,11 +134,23 @@ early_param("nokaslr", nokaslr);
#define KASLR_DISABLED_MESSAGE "KASLR is disabled by %s in %s cmdline.\n"
/*
* Note: strictly-defined KASLR means the kernel's final runtime address
* has a random offset from the kernel's load address, which is implemented
* in relocate.c; broadly-defined KALSR means the kernel's final runtime
* address has a random offset from the kernel's link address (a.k.a.
* VMLINUX_LOAD_ADDRESS), which also include the efistlub implementation,
* kexec_file implementation and QEMU direct kernel boot. kaslr_disabled()
* return true only means strictly-defined KASLR is disabled.
*/
static inline __init bool kaslr_disabled(void)
{
char *str;
const char *builtin_cmdline = CONFIG_CMDLINE;
if (kaslr_offset())
return true; /* KASLR is performed during early boot. */
str = strstr(builtin_cmdline, "nokaslr");
if (str == builtin_cmdline || (str > builtin_cmdline && *(str - 1) == ' ')) {
pr_info(KASLR_DISABLED_MESSAGE, "\'nokaslr\'", "built-in");
@ -210,14 +222,52 @@ static inline void __init *determine_relocation_address(void)
return RELOCATED_KASLR(destination);
}
static unsigned long __init determine_initrd_address(unsigned long *size)
{
unsigned long start = 0;
unsigned long key_length;
char *p, *endp, *key = "initrd=";
key_length = strlen(key);
p = strstr(boot_command_line, key);
if (!p) {
key = "initrdmem=";
key_length = strlen(key);
p = strstr(boot_command_line, key);
}
if (p == boot_command_line || (p > boot_command_line && *(p - 1) == ' ')) {
p += key_length;
start = memparse(p, &endp);
if (*endp == ',')
*size = memparse(endp + 1, NULL);
}
return start;
}
static inline int __init relocation_addr_valid(void *location_new)
{
unsigned long kernel_start, kernel_size;
unsigned long initrd_start, initrd_size = 0;
if ((unsigned long)location_new & 0x00000ffff)
return 0; /* Inappropriately aligned new location */
if ((unsigned long)location_new < (unsigned long)_end)
return 0; /* New location overlaps original kernel */
initrd_start = determine_initrd_address(&initrd_size);
if (initrd_start && initrd_size) {
kernel_start = PHYSADDR(location_new);
kernel_size = (unsigned long)_end - (unsigned long)_text;
if (kernel_start < (initrd_start + initrd_size) &&
initrd_start < (kernel_start + kernel_size))
return 0; /* initrd/initramfs overlaps kernel */
}
return 1;
}
#endif

View File

@ -123,11 +123,7 @@ void arch_remove_memory(u64 start, u64 size, struct vmem_altmap *altmap)
{
unsigned long start_pfn = start >> PAGE_SHIFT;
unsigned long nr_pages = size >> PAGE_SHIFT;
struct page *page = pfn_to_page(start_pfn);
/* With altmap the first mapped page is offset from @start */
if (altmap)
page += vmem_altmap_offset(altmap);
__remove_pages(start_pfn, nr_pages, altmap);
}
#endif

View File

@ -3,5 +3,6 @@ generated-y += syscall_table.h
generic-y += extable.h
generic-y += kvm_para.h
generic-y += mcs_spinlock.h
generic-y += ring_buffer.h
generic-y += spinlock.h
generic-y += text-patching.h

View File

@ -5,6 +5,7 @@ generic-y += extable.h
generic-y += kvm_para.h
generic-y += mcs_spinlock.h
generic-y += parport.h
generic-y += ring_buffer.h
generic-y += syscalls.h
generic-y += tlb.h
generic-y += user.h

View File

@ -12,5 +12,6 @@ generic-y += mcs_spinlock.h
generic-y += parport.h
generic-y += qrwlock.h
generic-y += qspinlock.h
generic-y += ring_buffer.h
generic-y += user.h
generic-y += text-patching.h

View File

@ -5,6 +5,7 @@ generic-y += cmpxchg.h
generic-y += extable.h
generic-y += kvm_para.h
generic-y += mcs_spinlock.h
generic-y += ring_buffer.h
generic-y += spinlock.h
generic-y += user.h
generic-y += text-patching.h

View File

@ -12,4 +12,6 @@
#define __ALIGN .align 4
#define __ALIGN_STR ".align 4"
#define _THIS_IP_ ({ unsigned long __ip; asm volatile("nextpc %0" : "=r" (__ip)); __ip; })
#endif

View File

@ -8,4 +8,5 @@ generic-y += spinlock_types.h
generic-y += spinlock.h
generic-y += qrwlock_types.h
generic-y += qrwlock.h
generic-y += ring_buffer.h
generic-y += user.h

View File

@ -4,4 +4,5 @@ generated-y += syscall_table_64.h
generic-y += agp.h
generic-y += kvm_para.h
generic-y += mcs_spinlock.h
generic-y += ring_buffer.h
generic-y += user.h

View File

@ -393,6 +393,7 @@ CONFIG_NETCONSOLE=m
CONFIG_TUN=m
CONFIG_VETH=m
CONFIG_VIRTIO_NET=m
CONFIG_EL3=m
CONFIG_VORTEX=m
CONFIG_TYPHOON=m
CONFIG_ADAPTEC_STARFIRE=m

View File

@ -5,4 +5,5 @@ generated-y += syscall_table_spu.h
generic-y += agp.h
generic-y += mcs_spinlock.h
generic-y += qrwlock.h
generic-y += ring_buffer.h
generic-y += early_ioremap.h

View File

@ -14,5 +14,6 @@ generic-y += ticket_spinlock.h
generic-y += qrwlock.h
generic-y += qrwlock_types.h
generic-y += qspinlock.h
generic-y += ring_buffer.h
generic-y += user.h
generic-y += vmlinux.lds.h

View File

@ -415,7 +415,6 @@ int kvm_riscv_vcpu_mmio_load(struct kvm_vcpu *vcpu, struct kvm_run *run,
shift = 8 * (sizeof(ulong) - len);
} else if ((insn & INSN_MASK_LBU) == INSN_MATCH_LBU) {
len = 1;
shift = 8 * (sizeof(ulong) - len);
#ifdef CONFIG_64BIT
} else if ((insn & INSN_MASK_LD) == INSN_MATCH_LD) {
len = 8;
@ -649,22 +648,22 @@ int kvm_riscv_vcpu_mmio_return(struct kvm_vcpu *vcpu, struct kvm_run *run)
case 1:
data8 = *((u8 *)run->mmio.data);
SET_RD(insn, &vcpu->arch.guest_context,
(ulong)data8 << shift >> shift);
(long)((ulong)data8 << shift) >> shift);
break;
case 2:
data16 = *((u16 *)run->mmio.data);
SET_RD(insn, &vcpu->arch.guest_context,
(ulong)data16 << shift >> shift);
(long)((ulong)data16 << shift) >> shift);
break;
case 4:
data32 = *((u32 *)run->mmio.data);
SET_RD(insn, &vcpu->arch.guest_context,
(ulong)data32 << shift >> shift);
(long)((ulong)data32 << shift) >> shift);
break;
case 8:
data64 = *((u64 *)run->mmio.data);
SET_RD(insn, &vcpu->arch.guest_context,
(ulong)data64 << shift >> shift);
(long)((ulong)data64 << shift) >> shift);
break;
default:
return -EOPNOTSUPP;

View File

@ -453,8 +453,10 @@ int kvm_riscv_vcpu_pmu_snapshot_set_shmem(struct kvm_vcpu *vcpu, unsigned long s
}
kvpmu->sdata = kzalloc(snapshot_area_size, GFP_ATOMIC);
if (!kvpmu->sdata)
return -ENOMEM;
if (!kvpmu->sdata) {
sbiret = SBI_ERR_FAILURE;
goto out;
}
/* No need to check writable slot explicitly as kvm_vcpu_write_guest does it internally */
if (kvm_vcpu_write_guest(vcpu, saddr, kvpmu->sdata, snapshot_area_size)) {
@ -499,8 +501,10 @@ int kvm_riscv_vcpu_pmu_event_info(struct kvm_vcpu *vcpu, unsigned long saddr_low
}
einfo = kzalloc(shmem_size, GFP_KERNEL);
if (!einfo)
return -ENOMEM;
if (!einfo) {
ret = SBI_ERR_FAILURE;
goto out;
}
ret = kvm_vcpu_read_guest(vcpu, shmem, einfo, shmem_size);
if (ret) {

View File

@ -46,7 +46,7 @@ void kvm_riscv_vcpu_record_steal_time(struct kvm_vcpu *vcpu)
gfn = shmem >> PAGE_SHIFT;
hva = kvm_vcpu_gfn_to_hva(vcpu, gfn);
if (WARN_ON(kvm_is_error_hva(hva))) {
if (kvm_is_error_hva(hva)) {
vcpu->arch.sta.shmem = INVALID_GPA;
return;
}

View File

@ -55,6 +55,8 @@ static int kvm_sbi_ext_v01_handler(struct kvm_vcpu *vcpu, struct kvm_run *run,
for_each_set_bit(i, &hmask, BITS_PER_LONG) {
rvcpu = kvm_get_vcpu_by_id(vcpu->kvm, i);
if (!rvcpu)
continue;
ret = kvm_riscv_vcpu_set_interrupt(rvcpu, IRQ_VS_SOFT);
if (ret < 0)
break;

View File

@ -7,3 +7,4 @@ generated-y += unistd_nr.h
generic-y += asm-offsets.h
generic-y += mcs_spinlock.h
generic-y += mmzone.h
generic-y += ring_buffer.h

View File

@ -186,6 +186,13 @@ static u64 pai_getctr(unsigned long *page, int nr, unsigned long offset)
return page[nr];
}
static void pai_setctr(unsigned long *page, int nr, unsigned long offset, u64 v)
{
if (offset)
nr += offset / sizeof(*page);
page[nr] = v;
}
/* Read the counter values. Return value from location in CMP. For base
* event xxx_ALL sum up all events. Returns counter value.
*/
@ -551,6 +558,8 @@ static void paicrypt_del(struct perf_event *event, int flags)
/* Create raw data and save it in buffer. Calculate the delta for each
* counter between this invocation and the last invocation.
* Returns number of bytes copied.
* After reading from PAI counter page, save the read value to the old
* page to calculate PAI counter deltas.
* Saves only entries with positive counter difference of the form
* 2 bytes: Number of counter
* 8 bytes: Value of counter
@ -562,16 +571,22 @@ static size_t pai_copy(struct pai_userdata *userdata, unsigned long *page,
int i, outidx = 0;
for (i = 1; i <= pp->num_avail; i++) {
u64 val = 0, val_old = 0;
u64 val = 0, val_old = 0, val_k = 0, val_old_k = 0;
if (!exclude_kernel) {
val += pai_getctr(page, i, pp->kernel_offset);
val_old += pai_getctr(page_old, i, pp->kernel_offset);
val_k = pai_getctr(page, i, pp->kernel_offset);
val_old_k = pai_getctr(page_old, i, pp->kernel_offset);
if (val_k != val_old_k)
pai_setctr(page_old, i, pp->kernel_offset, val_k);
}
if (!exclude_user) {
val += pai_getctr(page, i, 0);
val_old += pai_getctr(page_old, i, 0);
val = pai_getctr(page, i, 0);
val_old = pai_getctr(page_old, i, 0);
if (val != val_old)
pai_setctr(page_old, i, 0, val);
}
val += val_k;
val_old += val_old_k;
if (val >= val_old)
val -= val_old;
else
@ -602,8 +617,6 @@ static size_t pai_copy(struct pai_userdata *userdata, unsigned long *page,
static int pai_push_sample(size_t rawsize, struct pai_map *cpump,
struct perf_event *event)
{
int idx = PAI_PMU_IDX(event);
struct pai_pmu *pp = &pai_pmu[idx];
struct perf_sample_data data;
struct perf_raw_record raw;
struct pt_regs regs;
@ -634,8 +647,6 @@ static int pai_push_sample(size_t rawsize, struct pai_map *cpump,
overflow = perf_event_overflow(event, &data, &regs);
perf_event_update_userpage(event);
/* Save crypto counter lowcore page after reading event data. */
memcpy((void *)PAI_SAVE_AREA(event), cpump->area, pp->area_size);
return overflow;
}
@ -651,7 +662,7 @@ static void pai_have_sample(struct perf_event *event, struct pai_map *cpump)
rawsize = pai_copy(cpump->save, cpump->area, pp,
(unsigned long *)PAI_SAVE_AREA(event),
event->attr.exclude_user,
event->attr.exclude_kernel);
!pp->kernel_offset ? true : event->attr.exclude_kernel);
if (rawsize) /* No incremented counters */
pai_push_sample(rawsize, cpump, event);
}

View File

@ -192,17 +192,21 @@ static void tl_to_masks(struct sysinfo_15_1_x *info)
end = (union topology_entry *)((unsigned long)info + info->length);
while (tle < end) {
switch (tle->nl) {
/*
* Adjust drawer_id, book_id, and socked_id so they match the
* numbering scheme of e.g. the hardware management console.
*/
case 3:
drawer = drawer->next;
drawer->id = tle->container.id;
drawer->id = tle->container.id - 1;
break;
case 2:
book = book->next;
book->id = tle->container.id;
book->id = tle->container.id - 1;
break;
case 1:
socket = socket->next;
socket->id = tle->container.id;
socket->id = tle->container.id - 1;
break;
case 0:
add_cpus_to_mask(&tle->cpu, drawer, book, socket);

View File

@ -267,6 +267,7 @@ static int dat_split_ste(struct kvm_s390_mmu_cache *mc, union pmd *pmdp, gfn_t g
/* No need to take locks as the page table is not installed yet. */
pgste_init.prefix_notif = old.s.fc1.prefix_notif;
pgste_init.vsie_notif = old.s.fc1.vsie_notif;
pgste_init.vsie_gmem = old.s.fc1.vsie_notif;
pgste_init.pcl = uses_skeys && init.h.i;
dat_init_pgstes(pt, pgste_init.val);
} else {

View File

@ -145,7 +145,8 @@ union pgste {
unsigned long cmma_d : 1; /* Dirty flag for CMMA bits */
unsigned long prefix_notif : 1; /* Guest prefix invalidation notification */
unsigned long vsie_notif : 1; /* Referenced in a shadow table */
unsigned long : 5;
unsigned long vsie_gmem : 1; /* Contains nested guest memory */
unsigned long : 4;
unsigned long : 8;
};
struct {

View File

@ -1445,6 +1445,7 @@ static int _do_shadow_pte(struct gmap *sg, gpa_t raddr, union pte *ptep_h, union
} else {
pgste = _gmap_ptep_xchg(sg->parent, ptep_h, newpte, pgste, f->gfn, false);
pgste.vsie_notif = 1;
pgste.vsie_gmem = 1;
}
pgste_set_unlock(ptep_h, pgste);
if (rc)

View File

@ -125,7 +125,7 @@ struct gmap *gmap_new_child(struct gmap *parent, gfn_t limit)
int gmap_set_limit(struct gmap *gmap, gfn_t limit)
{
struct kvm_s390_mmu_cache *mc;
struct kvm_s390_mmu_cache *mc __free(kvm_s390_mmu_cache) = NULL;
int rc, type;
type = gmap_limit_to_type(limit);
@ -142,7 +142,6 @@ int gmap_set_limit(struct gmap *gmap, gfn_t limit)
rc = dat_set_asce_limit(mc, &gmap->asce, type);
} while (rc == -ENOMEM);
kvm_s390_free_mmu_cache(mc);
return 0;
}
@ -822,8 +821,8 @@ int gmap_ucas_translate(struct kvm_s390_mmu_cache *mc, struct gmap *gmap, gpa_t
int gmap_ucas_map(struct gmap *gmap, gfn_t p_gfn, gfn_t c_gfn, unsigned long count)
{
struct kvm_s390_mmu_cache *mc;
int rc;
struct kvm_s390_mmu_cache *mc __free(kvm_s390_mmu_cache) = NULL;
int rc = 0;
mc = kvm_s390_new_mmu_cache();
if (!mc)
@ -1026,13 +1025,15 @@ int gmap_insert_rmap(struct gmap *sg, gfn_t p_gfn, gfn_t r_gfn, int level)
int gmap_protect_rmap(struct kvm_s390_mmu_cache *mc, struct gmap *sg, gfn_t p_gfn, gfn_t r_gfn,
kvm_pfn_t pfn, int level, bool wr)
{
unsigned long bitmask;
union crste *crstep;
union pgste pgste;
union pte *ptep;
union pte pte;
int flags, rc;
KVM_BUG_ON(!is_shadow(sg), sg->kvm);
if (KVM_BUG_ON(!is_shadow(sg) || level <= TABLE_TYPE_PAGE_TABLE, sg->kvm))
return -EINVAL;
lockdep_assert_held(&sg->parent->children_lock);
flags = DAT_WALK_SPLIT_ALLOC | (uses_skeys(sg->parent) ? DAT_WALK_USES_SKEYS : 0);
@ -1041,8 +1042,9 @@ int gmap_protect_rmap(struct kvm_s390_mmu_cache *mc, struct gmap *sg, gfn_t p_gf
if (rc)
return rc;
if (level <= TABLE_TYPE_REGION1) {
bitmask = -1UL << (8 + 11 * level);
scoped_guard(spinlock, &sg->host_to_rmap_lock)
rc = gmap_insert_rmap(sg, p_gfn, r_gfn, level);
rc = gmap_insert_rmap(sg, p_gfn, r_gfn & bitmask, level);
}
if (rc)
return rc;
@ -1143,8 +1145,10 @@ void _gmap_handle_vsie_unshadow_event(struct gmap *parent, gfn_t gfn)
}
scoped_guard(spinlock, &sg->host_to_rmap_lock)
head = radix_tree_delete(&sg->host_to_rmap, gfn);
gmap_for_each_rmap_safe(rmap, rnext, head)
gmap_for_each_rmap_safe(rmap, rnext, head) {
gmap_unshadow_level(sg, rmap->r_gfn, rmap->level);
kfree(rmap);
}
}
}

View File

@ -167,6 +167,36 @@ static inline bool gmap_unmap_prefix(struct gmap *gmap, gfn_t gfn, gfn_t end)
return _gmap_unmap_prefix(gmap, gfn, end, false);
}
/**
* pte_needs_unshadow() -- Check if the pte operations triggers unshadowing.
* @oldpte: the previous value for the guest pte.
* @newpte: the new pte being set.
* @pgste: the pgste for the pte entry.
*
* If the pgste.vsie_notif bit is not set, return false: the page is not
* involved in vsie and thus should not trigger an unshadow operation.
*
* If the pgste.vsie_gmem bit is set, this pte represents shadowed guest
* memory. The access rights on g3's memory should be synchronized with g1's
* and g2's. Therefore unshadowing is triggered if the new and old pte
* differ in protection, or if the new pte is invalid.
*
* If the pgste.vsie_gmem bit is not set, this pte maps the g2 dat tables
* for g3. If the entry becomes writable or absent, it becomes impossible to
* guarantee that the shadow mapping will match g2's mapping. In that case,
* trigger an unshadow event.
*
* Return: true if an unshadow event should be triggered, otherwise false.
*/
static inline bool pte_needs_unshadow(union pte oldpte, union pte newpte, union pgste pgste)
{
if (!pgste.vsie_notif)
return false;
if (pgste.vsie_gmem)
return (oldpte.h.p != newpte.h.p) || newpte.h.i;
return !newpte.h.p || !newpte.s.pr;
}
static inline union pgste _gmap_ptep_xchg(struct gmap *gmap, union pte *ptep, union pte newpte,
union pgste pgste, gfn_t gfn, bool needs_lock)
{
@ -180,8 +210,9 @@ static inline union pgste _gmap_ptep_xchg(struct gmap *gmap, union pte *ptep, un
pgste.prefix_notif = 0;
gmap_unmap_prefix(gmap, gfn, gfn + 1);
}
if (pgste.vsie_notif && (ptep->h.p != newpte.h.p || newpte.h.i)) {
if (pte_needs_unshadow(*ptep, newpte, pgste)) {
pgste.vsie_notif = 0;
pgste.vsie_gmem = 0;
if (needs_lock)
gmap_handle_vsie_unshadow_event(gmap, gfn);
else
@ -189,6 +220,7 @@ static inline union pgste _gmap_ptep_xchg(struct gmap *gmap, union pte *ptep, un
}
if (!ptep->s.d && newpte.s.d && !newpte.s.s)
SetPageDirty(pfn_to_page(newpte.h.pfra));
pgste.zero = 0;
return __dat_ptep_xchg(ptep, pgste, newpte, gfn, gmap->asce, uses_skeys(gmap));
}
@ -198,6 +230,30 @@ static inline union pgste gmap_ptep_xchg(struct gmap *gmap, union pte *ptep, uni
return _gmap_ptep_xchg(gmap, ptep, newpte, pgste, gfn, true);
}
/**
* crste_needs_unshadow() -- Check if the crste operations triggers unshadowing.
* @oldcrste: the previous value for the crste.
* @newcrste: the new value for the crste.
*
* If the old crste did not have the vsie_notif bit set, return false: the
* page is not involved in vsie and thus should not trigger an unshadow
* operation. Conversely, if the bit is set, it can only be g3 memory, since
* dat tables are never mapped using large pages.
*
* Similar to the pgste.vsie_gmem case of pte_needs_unshadow(), if the
* protection bit is changing or the new page is invalid, trigger an
* unshadow event. Also trigger an unshadow event if the new crste does not
* have the vsie_notif bit set.
*
* Return: true if an unshadow event should be triggered, otherwise false.
*/
static inline bool crste_needs_unshadow(union crste oldcrste, union crste newcrste)
{
if (!oldcrste.s.fc1.vsie_notif)
return false;
return (newcrste.h.p != oldcrste.h.p) || newcrste.h.i || !newcrste.s.fc1.vsie_notif;
}
static inline bool __must_check _gmap_crstep_xchg_atomic(struct gmap *gmap, union crste *crstep,
union crste oldcrste, union crste newcrste,
gfn_t gfn, bool needs_lock)
@ -216,8 +272,7 @@ static inline bool __must_check _gmap_crstep_xchg_atomic(struct gmap *gmap, unio
newcrste.s.fc1.prefix_notif = 0;
gmap_unmap_prefix(gmap, gfn, gfn + align);
}
if (crste_leaf(oldcrste) && oldcrste.s.fc1.vsie_notif &&
(newcrste.h.p || newcrste.h.i || !newcrste.s.fc1.vsie_notif)) {
if (crste_leaf(oldcrste) && crste_needs_unshadow(oldcrste, newcrste)) {
newcrste.s.fc1.vsie_notif = 0;
if (needs_lock)
gmap_handle_vsie_unshadow_event(gmap, gfn);

View File

@ -3,4 +3,5 @@ generated-y += syscall_table.h
generic-y += kvm_para.h
generic-y += mcs_spinlock.h
generic-y += parport.h
generic-y += ring_buffer.h
generic-y += text-patching.h

View File

@ -4,4 +4,5 @@ generated-y += syscall_table_64.h
generic-y += agp.h
generic-y += kvm_para.h
generic-y += mcs_spinlock.h
generic-y += ring_buffer.h
generic-y += text-patching.h

View File

@ -17,6 +17,7 @@ generic-y += module.lds.h
generic-y += parport.h
generic-y += percpu.h
generic-y += preempt.h
generic-y += ring_buffer.h
generic-y += runtime-const.h
generic-y += softirq_stack.h
generic-y += switch_to.h

View File

@ -13,7 +13,7 @@ CFLAGS_REMOVE_syscall_64.o = $(CC_FLAGS_FTRACE)
CFLAGS_syscall_32.o += -fno-stack-protector
CFLAGS_syscall_64.o += -fno-stack-protector
obj-y := entry.o entry_$(BITS).o syscall_$(BITS).o
obj-y := entry.o entry_$(BITS).o syscall_$(BITS).o common.o
obj-y += vdso/
obj-y += vsyscall/

61
arch/x86/entry/common.c Normal file
View File

@ -0,0 +1,61 @@
/* SPDX-License-Identifier: GPL-2.0 */
#include <linux/entry-common.h>
#include <linux/kvm_types.h>
#include <linux/hrtimer_rearm.h>
#include <asm/fred.h>
#include <asm/desc.h>
#if IS_ENABLED(CONFIG_KVM_INTEL)
/*
* On VMX, NMIs and IRQs (as configured by KVM) are acknowledged by hardware as
* part of the VM-Exit, i.e. the event itself is consumed as part the VM-Exit.
* x86_entry_from_kvm() is invoked by KVM to effectively forward NMIs and IRQs
* to the kernel for servicing. On SVM, a.k.a. AMD, the NMI/IRQ VM-Exit is
* purely a signal that an NMI/IRQ is pending, i.e. the event that triggered
* the VM-Exit is held pending until it's unblocked in the host.
*/
noinstr void x86_entry_from_kvm(unsigned int event_type, unsigned int vector)
{
if (event_type == EVENT_TYPE_EXTINT) {
#ifdef CONFIG_X86_64
/*
* Use FRED dispatch, even when running IDT. The dispatch
* tables are kept in sync between FRED and IDT, and the FRED
* dispatch works well with CFI.
*/
fred_entry_from_kvm(event_type, vector);
#else
idt_entry_from_kvm(vector);
#endif
/*
* Strictly speaking, only the NMI path requires noinstr.
*/
instrumentation_begin();
/*
* KVM/VMX will dispatch from IRQ-disabled but for a context
* that will have IRQs-enabled. This confuses the entry code
* and it will not have reprogrammed the timer. Do so now.
*/
hrtimer_rearm_deferred();
instrumentation_end();
return;
}
WARN_ON_ONCE(event_type != EVENT_TYPE_NMI);
#ifdef CONFIG_X86_64
if (cpu_feature_enabled(X86_FEATURE_FRED))
return fred_entry_from_kvm(event_type, vector);
#endif
/*
* Notably, we must use IDT dispatch for NMI when running in IDT mode.
* The FRED NMI context is significantly different and will not work
* right (specifically FRED fixed the NMI recursion issue).
*/
idt_entry_from_kvm(vector);
}
EXPORT_SYMBOL_FOR_KVM(x86_entry_from_kvm);
#endif

View File

@ -75,3 +75,49 @@ THUNK warn_thunk_thunk, __warn_thunk
#if defined(CONFIG_STACKPROTECTOR) && defined(CONFIG_SMP)
EXPORT_SYMBOL(__ref_stack_chk_guard);
#endif
#if IS_ENABLED(CONFIG_KVM_INTEL)
.macro IDT_DO_EVENT_IRQOFF call_insn call_target
/*
* Unconditionally create a stack frame, getting the correct RSP on the
* stack (for x86-64) would take two instructions anyways, and RBP can
* be used to restore RSP to make objtool happy (see below).
*/
push %_ASM_BP
mov %_ASM_SP, %_ASM_BP
#ifdef CONFIG_X86_64
/*
* Align RSP to a 16-byte boundary (to emulate CPU behavior) before
* creating the synthetic interrupt stack frame for the IRQ/NMI.
*/
and $-16, %rsp
push $__KERNEL_DS
push %rbp
#endif
pushf
push $__KERNEL_CS
\call_insn \call_target
/*
* "Restore" RSP from RBP, even though IRET has already unwound RSP to
* the correct value. objtool doesn't know the callee will IRET and,
* without the explicit restore, thinks the stack is getting walloped.
* Using an unwind hint is problematic due to x86-64's dynamic alignment.
*/
leave
RET
.endm
.pushsection .text, "ax"
SYM_FUNC_START(idt_do_interrupt_irqoff)
IDT_DO_EVENT_IRQOFF CALL_NOSPEC _ASM_ARG1
SYM_FUNC_END(idt_do_interrupt_irqoff)
.popsection
.pushsection .noinstr.text, "ax"
SYM_FUNC_START(idt_do_nmi_irqoff)
IDT_DO_EVENT_IRQOFF call asm_exc_nmi_kvm_vmx
SYM_FUNC_END(idt_do_nmi_irqoff)
.popsection
#endif

View File

@ -147,5 +147,4 @@ SYM_FUNC_START(asm_fred_entry_from_kvm)
RET
SYM_FUNC_END(asm_fred_entry_from_kvm)
EXPORT_SYMBOL_FOR_KVM(asm_fred_entry_from_kvm);
#endif

View File

@ -178,7 +178,7 @@ static int map_vdso(const struct vdso_image *image, unsigned long addr)
if (IS_ERR(vma)) {
ret = PTR_ERR(vma);
do_munmap(mm, text_start, image->size, NULL);
do_munmap(mm, addr, image->size, NULL);
do_munmap(mm, addr, VDSO_NR_PAGES * PAGE_SIZE, NULL);
goto up_fail;
}

View File

@ -14,3 +14,4 @@ generic-y += early_ioremap.h
generic-y += fprobe.h
generic-y += mcs_spinlock.h
generic-y += mmzone.h
generic-y += ring_buffer.h

View File

@ -438,6 +438,10 @@ extern void idt_setup_traps(void);
extern void idt_setup_apic_and_irq_gates(void);
extern bool idt_is_f00f_address(unsigned long address);
extern void idt_do_interrupt_irqoff(unsigned long address);
extern void idt_do_nmi_irqoff(void);
extern void idt_entry_from_kvm(unsigned int vector);
#ifdef CONFIG_X86_64
extern void idt_setup_early_pf(void);
#else

View File

@ -145,7 +145,7 @@ struct gate_struct {
typedef struct gate_struct gate_desc;
#ifndef _SETUP
static inline unsigned long gate_offset(const gate_desc *g)
static __always_inline unsigned long gate_offset(const gate_desc *g)
{
#ifdef CONFIG_X86_64
return g->offset_low | ((unsigned long)g->offset_middle << 16) |

View File

@ -97,4 +97,6 @@ static __always_inline void arch_exit_to_user_mode(void)
}
#define arch_exit_to_user_mode arch_exit_to_user_mode
extern void x86_entry_from_kvm(unsigned int entry_type, unsigned int vector);
#endif

View File

@ -110,7 +110,6 @@ static __always_inline unsigned long fred_event_data(struct pt_regs *regs) { ret
static inline void cpu_init_fred_exceptions(void) { }
static inline void cpu_init_fred_rsps(void) { }
static inline void fred_complete_exception_setup(void) { }
static inline void fred_entry_from_kvm(unsigned int type, unsigned int vector) { }
static inline void fred_sync_rsp0(unsigned long rsp0) { }
static inline void fred_update_rsp0(void) { }
#endif /* CONFIG_X86_FRED */

View File

@ -92,6 +92,7 @@ static const struct cpuid_dep cpuid_deps[] = {
{ X86_FEATURE_FRED, X86_FEATURE_LKGS },
{ X86_FEATURE_SPEC_CTRL_SSBD, X86_FEATURE_SPEC_CTRL },
{ X86_FEATURE_LASS, X86_FEATURE_SMAP },
{ X86_FEATURE_INVLPGB, X86_FEATURE_PCID },
{}
};

View File

@ -268,6 +268,21 @@ void __init idt_setup_early_pf(void)
}
#endif
#if IS_ENABLED(CONFIG_KVM_INTEL)
noinstr void idt_entry_from_kvm(unsigned int vector)
{
if (vector == NMI_VECTOR)
return idt_do_nmi_irqoff();
/*
* Only the NMI path requires noinstr.
*/
instrumentation_begin();
idt_do_interrupt_irqoff(gate_offset(idt_table + vector));
instrumentation_end();
}
#endif
static void __init idt_map_in_cea(void)
{
/*

View File

@ -614,7 +614,6 @@ DEFINE_IDTENTRY_RAW(exc_nmi_kvm_vmx)
{
exc_nmi(regs);
}
EXPORT_SYMBOL_FOR_KVM(asm_exc_nmi_kvm_vmx);
#endif
#ifdef CONFIG_NMI_CHECK_CPU

View File

@ -1300,12 +1300,14 @@ bool __init avic_hardware_setup(void)
}
/*
* Disable IPI virtualization for AMD Family 17h CPUs (Zen1 and Zen2)
* due to erratum 1235, which results in missed VM-Exits on the sender
* and thus missed wake events for blocking vCPUs due to the CPU
* failing to see a software update to clear IsRunning.
* Disable IPI virtualization for AMD Family 17h (Zen1 and Zen2) and
* Hygon Family 18h (derived from AMD Zen1) CPUs due to erratum 1235,
* which results in missed VM-Exits on the sender and thus missed wake
* events for blocking vCPUs due to the CPU failing to see a software
* update to clear IsRunning.
*/
enable_ipiv = enable_ipiv && boot_cpu_data.x86 != 0x17;
if (boot_cpu_data.x86 == 0x17 || boot_cpu_data.x86 == 0x18)
enable_ipiv = false;
amd_iommu_register_ga_log_notifier(&avic_ga_log_notifier);

View File

@ -31,38 +31,6 @@
#define VCPU_R15 __VCPU_REGS_R15 * WORD_SIZE
#endif
.macro VMX_DO_EVENT_IRQOFF call_insn call_target
/*
* Unconditionally create a stack frame, getting the correct RSP on the
* stack (for x86-64) would take two instructions anyways, and RBP can
* be used to restore RSP to make objtool happy (see below).
*/
push %_ASM_BP
mov %_ASM_SP, %_ASM_BP
#ifdef CONFIG_X86_64
/*
* Align RSP to a 16-byte boundary (to emulate CPU behavior) before
* creating the synthetic interrupt stack frame for the IRQ/NMI.
*/
and $-16, %rsp
push $__KERNEL_DS
push %rbp
#endif
pushf
push $__KERNEL_CS
\call_insn \call_target
/*
* "Restore" RSP from RBP, even though IRET has already unwound RSP to
* the correct value. objtool doesn't know the callee will IRET and,
* without the explicit restore, thinks the stack is getting walloped.
* Using an unwind hint is problematic due to x86-64's dynamic alignment.
*/
leave
RET
.endm
.section .noinstr.text, "ax"
/**
@ -320,10 +288,6 @@ SYM_INNER_LABEL_ALIGN(vmx_vmexit, SYM_L_GLOBAL)
SYM_FUNC_END(__vmx_vcpu_run)
SYM_FUNC_START(vmx_do_nmi_irqoff)
VMX_DO_EVENT_IRQOFF call asm_exc_nmi_kvm_vmx
SYM_FUNC_END(vmx_do_nmi_irqoff)
#ifndef CONFIG_CC_HAS_ASM_GOTO_OUTPUT
/**
@ -375,13 +339,3 @@ SYM_FUNC_START(vmread_error_trampoline)
RET
SYM_FUNC_END(vmread_error_trampoline)
#endif
.section .text, "ax"
#ifndef CONFIG_X86_FRED
SYM_FUNC_START(vmx_do_interrupt_irqoff)
VMX_DO_EVENT_IRQOFF CALL_NOSPEC _ASM_ARG1
SYM_FUNC_END(vmx_do_interrupt_irqoff)
#endif

View File

@ -7117,9 +7117,6 @@ void vmx_load_eoi_exitmap(struct kvm_vcpu *vcpu, u64 *eoi_exit_bitmap)
vmcs_write64(EOI_EXIT_BITMAP3, eoi_exit_bitmap[3]);
}
void vmx_do_interrupt_irqoff(unsigned long entry);
void vmx_do_nmi_irqoff(void);
static void handle_nm_fault_irqoff(struct kvm_vcpu *vcpu)
{
/*
@ -7161,17 +7158,8 @@ static void handle_external_interrupt_irqoff(struct kvm_vcpu *vcpu,
"unexpected VM-Exit interrupt info: 0x%x", intr_info))
return;
/*
* Invoke the kernel's IRQ handler for the vector. Use the FRED path
* when it's available even if FRED isn't fully enabled, e.g. even if
* FRED isn't supported in hardware, in order to avoid the indirect
* CALL in the non-FRED path.
*/
kvm_before_interrupt(vcpu, KVM_HANDLING_IRQ);
if (IS_ENABLED(CONFIG_X86_FRED))
fred_entry_from_kvm(EVENT_TYPE_EXTINT, vector);
else
vmx_do_interrupt_irqoff(gate_offset((gate_desc *)host_idt_base + vector));
x86_entry_from_kvm(EVENT_TYPE_EXTINT, vector);
kvm_after_interrupt(vcpu);
vcpu->arch.at_instruction_boundary = true;
@ -7481,10 +7469,7 @@ noinstr void vmx_handle_nmi(struct kvm_vcpu *vcpu)
return;
kvm_before_interrupt(vcpu, KVM_HANDLING_NMI);
if (cpu_feature_enabled(X86_FEATURE_FRED))
fred_entry_from_kvm(EVENT_TYPE_NMI, NMI_VECTOR);
else
vmx_do_nmi_irqoff();
x86_entry_from_kvm(EVENT_TYPE_NMI, NMI_VECTOR);
kvm_after_interrupt(vcpu);
}

View File

@ -4876,7 +4876,7 @@ int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext)
r = tdp_enabled;
break;
case KVM_CAP_X86_APIC_BUS_CYCLES_NS:
r = APIC_BUS_CYCLE_NS_DEFAULT;
r = kvm ? kvm->arch.apic_bus_cycle_ns : APIC_BUS_CYCLE_NS_DEFAULT;
break;
case KVM_CAP_EXIT_HYPERCALL:
r = KVM_EXIT_HYPERCALL_VALID_MASK;

View File

@ -6,5 +6,6 @@ generic-y += mcs_spinlock.h
generic-y += parport.h
generic-y += qrwlock.h
generic-y += qspinlock.h
generic-y += ring_buffer.h
generic-y += user.h
generic-y += text-patching.h

View File

@ -55,6 +55,10 @@ int fs_bio_integrity_verify(struct bio *bio, sector_t sector, unsigned int size)
{
struct blk_integrity *bi = blk_get_integrity(bio->bi_bdev->bd_disk);
struct bio_integrity_payload *bip = bio_integrity(bio);
struct bvec_iter data_iter = {
.bi_sector = sector,
.bi_size = size,
};
/*
* Reinitialize bip->bip_iter.
@ -65,7 +69,7 @@ int fs_bio_integrity_verify(struct bio *bio, sector_t sector, unsigned int size)
memset(&bip->bip_iter, 0, sizeof(bip->bip_iter));
bip->bip_iter.bi_sector = sector;
bip->bip_iter.bi_size = bio_integrity_bytes(bi, size >> SECTOR_SHIFT);
return blk_status_to_errno(bio_integrity_verify(bio, &bip->bip_iter));
return blk_status_to_errno(bio_integrity_verify(bio, &data_iter));
}
static int __init fs_bio_integrity_init(void)

View File

@ -2241,7 +2241,7 @@ void blk_cgroup_bio_start(struct bio *bio)
}
u64_stats_update_end_irqrestore(&bis->sync, flags);
css_rstat_updated(&blkcg->css, cpu);
__css_rstat_updated(&blkcg->css, cpu);
put_cpu();
}

View File

@ -3077,7 +3077,7 @@ static struct request *blk_mq_get_new_requests(struct request_queue *q,
/*
* Check if there is a suitable cached request and return it.
*/
static struct request *blk_mq_peek_cached_request(struct blk_plug *plug,
static struct request *blk_mq_get_cached_request(struct blk_plug *plug,
struct request_queue *q, blk_opf_t opf)
{
enum hctx_type type = blk_mq_get_hctx_type(opf);
@ -3093,27 +3093,10 @@ static struct request *blk_mq_peek_cached_request(struct blk_plug *plug,
return NULL;
if (op_is_flush(rq->cmd_flags) != op_is_flush(opf))
return NULL;
rq_list_pop(&plug->cached_rqs);
return rq;
}
static void blk_mq_use_cached_rq(struct request *rq, struct blk_plug *plug,
struct bio *bio)
{
if (rq_list_pop(&plug->cached_rqs) != rq)
WARN_ON_ONCE(1);
/*
* If any qos ->throttle() end up blocking, we will have flushed the
* plug and hence killed the cached_rq list as well. Pop this entry
* before we throttle.
*/
rq_qos_throttle(rq->q, bio);
blk_mq_rq_time_init(rq, blk_time_get_ns());
rq->cmd_flags = bio->bi_opf;
INIT_LIST_HEAD(&rq->queuelist);
}
static bool bio_unaligned(const struct bio *bio, struct request_queue *q)
{
unsigned int bs_mask = queue_logical_block_size(q) - 1;
@ -3152,7 +3135,7 @@ void blk_mq_submit_bio(struct bio *bio)
/*
* If the plug has a cached request for this queue, try to use it.
*/
rq = blk_mq_peek_cached_request(plug, q, bio->bi_opf);
rq = blk_mq_get_cached_request(plug, q, bio->bi_opf);
/*
* A BIO that was released from a zone write plug has already been
@ -3211,7 +3194,10 @@ void blk_mq_submit_bio(struct bio *bio)
new_request:
if (rq) {
blk_mq_use_cached_rq(rq, plug, bio);
rq_qos_throttle(rq->q, bio);
blk_mq_rq_time_init(rq, blk_time_get_ns());
rq->cmd_flags = bio->bi_opf;
INIT_LIST_HEAD(&rq->queuelist);
} else {
rq = blk_mq_get_new_requests(q, plug, bio);
if (unlikely(!rq)) {
@ -3257,12 +3243,10 @@ void blk_mq_submit_bio(struct bio *bio)
return;
queue_exit:
/*
* Don't drop the queue reference if we were trying to use a cached
* request and thus didn't acquire one.
*/
if (!rq)
blk_queue_exit(q);
else
blk_mq_free_request(rq);
}
#ifdef CONFIG_BLK_MQ_STACKING

View File

@ -2001,8 +2001,10 @@ static void disk_set_zones_cond_array(struct gendisk *disk, u8 *zones_cond)
void disk_free_zone_resources(struct gendisk *disk)
{
if (disk->zone_wplugs_worker)
if (disk->zone_wplugs_worker) {
kthread_stop(disk->zone_wplugs_worker);
disk->zone_wplugs_worker = NULL;
}
WARN_ON_ONCE(!list_empty(&disk->zone_wplugs_list));
if (disk->zone_wplugs_wq) {
@ -2135,9 +2137,6 @@ static int disk_update_zone_resources(struct gendisk *disk,
ret = queue_limits_commit_update(q, &lim);
unfreeze:
if (ret)
disk_free_zone_resources(disk);
blk_mq_unfreeze_queue(q, memflags);
return ret;

View File

@ -134,27 +134,69 @@ EXPORT_SYMBOL(crypto_krb5_how_much_data);
* Find the offset and size of the data in a secure message so that this
* information can be used in the metadata buffer which will get added to the
* digest by crypto_krb5_verify_mic().
*
* Return: 0 if successful, -EBADMSG if the message is too short or -EINVAL if
* the mode is unsupported.
*/
void crypto_krb5_where_is_the_data(const struct krb5_enctype *krb5,
enum krb5_crypto_mode mode,
size_t *_offset, size_t *_len)
int crypto_krb5_where_is_the_data(const struct krb5_enctype *krb5,
enum krb5_crypto_mode mode,
size_t *_offset, size_t *_len)
{
switch (mode) {
case KRB5_CHECKSUM_MODE:
if (*_len < krb5->cksum_len)
return -EBADMSG;
*_offset += krb5->cksum_len;
*_len -= krb5->cksum_len;
return;
return 0;
case KRB5_ENCRYPT_MODE:
if (*_len < krb5->conf_len + krb5->cksum_len)
return -EBADMSG;
*_offset += krb5->conf_len;
*_len -= krb5->conf_len + krb5->cksum_len;
return;
return 0;
default:
WARN_ON_ONCE(1);
return;
return -EINVAL;
}
}
EXPORT_SYMBOL(crypto_krb5_where_is_the_data);
/**
* crypto_krb5_check_data_len - Check a message is big enough
* @krb5: The encoding to use.
* @mode: Mode of operation.
* @len: The length of the secure blob.
* @min_content: Minimum length of the content inside the blob.
*
* Check that a message is large enough to hold whatever bits the encryption
* type wants to glue on (nonce, checksum) plus a minimum amount of content.
*
* Return: 0 if successful, -EBADMSG if the message is too short or -EINVAL if
* the mode is unsupported.
*/
int crypto_krb5_check_data_len(const struct krb5_enctype *krb5,
enum krb5_crypto_mode mode,
size_t len, size_t min_content)
{
switch (mode) {
case KRB5_CHECKSUM_MODE:
if (len < krb5->cksum_len ||
len - krb5->cksum_len < min_content)
return -EBADMSG;
return 0;
case KRB5_ENCRYPT_MODE:
if (len < krb5->conf_len + krb5->cksum_len ||
len - (krb5->conf_len + krb5->cksum_len) < min_content)
return -EBADMSG;
return 0;
default:
WARN_ON_ONCE(1);
return -EINVAL;
}
}
EXPORT_SYMBOL(crypto_krb5_check_data_len);
/*
* Prepare the encryption with derived key data.
*/

View File

@ -490,6 +490,9 @@ static struct dma_buf *amdxdna_gem_prime_export(struct drm_gem_object *gobj, int
struct amdxdna_gem_obj *abo = to_xdna_obj(gobj);
DEFINE_DMA_BUF_EXPORT_INFO(exp_info);
if (abo->private_buffer)
return ERR_PTR(-EOPNOTSUPP);
if (abo->dma_buf) {
get_dma_buf(abo->dma_buf);
return abo->dma_buf;
@ -685,6 +688,7 @@ amdxdna_gem_create_ubuf_object(struct drm_device *dev, struct amdxdna_drm_create
{
struct amdxdna_dev *xdna = to_xdna_dev(dev);
struct amdxdna_drm_va_tbl va_tbl;
struct amdxdna_gem_obj *abo;
struct drm_gem_object *gobj;
struct dma_buf *dma_buf;
@ -711,7 +715,10 @@ amdxdna_gem_create_ubuf_object(struct drm_device *dev, struct amdxdna_drm_create
dma_buf_put(dma_buf);
return to_xdna_obj(gobj);
abo = to_xdna_obj(gobj);
abo->private_buffer = true;
return abo;
}
struct drm_gem_object *

View File

@ -54,6 +54,8 @@ struct amdxdna_gem_obj {
/* True, if BO is managed by XRT, not application */
bool internal;
/* True, if BO is not exportable */
bool private_buffer;
};
#define to_gobj(obj) (&(obj)->base.base)

View File

@ -69,60 +69,10 @@ static void amdxdna_ubuf_release(struct dma_buf *dbuf)
kfree(ubuf);
}
static vm_fault_t amdxdna_ubuf_vm_fault(struct vm_fault *vmf)
{
struct vm_area_struct *vma = vmf->vma;
struct amdxdna_ubuf_priv *ubuf;
unsigned long pfn;
pgoff_t pgoff;
ubuf = vma->vm_private_data;
pgoff = (vmf->address - vma->vm_start) >> PAGE_SHIFT;
pfn = page_to_pfn(ubuf->pages[pgoff]);
return vmf_insert_pfn(vma, vmf->address, pfn);
}
static const struct vm_operations_struct amdxdna_ubuf_vm_ops = {
.fault = amdxdna_ubuf_vm_fault,
};
static int amdxdna_ubuf_mmap(struct dma_buf *dbuf, struct vm_area_struct *vma)
{
struct amdxdna_ubuf_priv *ubuf = dbuf->priv;
vma->vm_ops = &amdxdna_ubuf_vm_ops;
vma->vm_private_data = ubuf;
vm_flags_set(vma, VM_PFNMAP | VM_DONTEXPAND | VM_DONTDUMP);
return 0;
}
static int amdxdna_ubuf_vmap(struct dma_buf *dbuf, struct iosys_map *map)
{
struct amdxdna_ubuf_priv *ubuf = dbuf->priv;
void *kva;
kva = vmap(ubuf->pages, ubuf->nr_pages, VM_MAP, PAGE_KERNEL);
if (!kva)
return -EINVAL;
iosys_map_set_vaddr(map, kva);
return 0;
}
static void amdxdna_ubuf_vunmap(struct dma_buf *dbuf, struct iosys_map *map)
{
vunmap(map->vaddr);
}
static const struct dma_buf_ops amdxdna_ubuf_dmabuf_ops = {
.map_dma_buf = amdxdna_ubuf_map,
.unmap_dma_buf = amdxdna_ubuf_unmap,
.release = amdxdna_ubuf_release,
.mmap = amdxdna_ubuf_mmap,
.vmap = amdxdna_ubuf_vmap,
.vunmap = amdxdna_ubuf_vunmap,
};
struct dma_buf *amdxdna_get_ubuf(struct drm_device *dev,

View File

@ -94,6 +94,7 @@ struct acpi_battery {
struct power_supply *bat;
struct power_supply_desc bat_desc;
struct acpi_device *device;
struct device *phys_dev;
struct notifier_block pm_nb;
struct list_head list;
unsigned long update_time;
@ -1033,7 +1034,7 @@ static int acpi_battery_update(struct acpi_battery *battery, bool resume)
if ((battery->state & ACPI_BATTERY_STATE_CRITICAL) ||
(test_bit(ACPI_BATTERY_ALARM_PRESENT, &battery->flags) &&
(battery->capacity_now <= battery->alarm)))
acpi_pm_wakeup_event(&battery->device->dev);
acpi_pm_wakeup_event(battery->phys_dev);
return result;
}
@ -1231,6 +1232,7 @@ static int acpi_battery_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, battery);
battery->phys_dev = &pdev->dev;
battery->device = device;
result = devm_mutex_init(&pdev->dev, &battery->update_lock);

View File

@ -606,6 +606,12 @@ static void platform_device_release(struct device *dev)
kfree(pa);
}
static void platform_device_release_full(struct device *dev)
{
device_remove_software_node(dev);
platform_device_release(dev);
}
/**
* platform_device_alloc - create a platform device
* @name: base name of the device we're adding
@ -848,7 +854,13 @@ struct platform_device *platform_device_register_full(const struct platform_devi
int ret;
struct platform_device *pdev;
if (pdevinfo->swnode && pdevinfo->properties)
/*
* Only one software node per device is allowed. Make sure we don't
* accept or create two.
*/
if ((pdevinfo->swnode && pdevinfo->properties) ||
(pdevinfo->swnode && is_software_node(pdevinfo->fwnode)) ||
(pdevinfo->properties && is_software_node(pdevinfo->fwnode)))
return ERR_PTR(-EINVAL);
pdev = platform_device_alloc(pdevinfo->name, pdevinfo->id);
@ -878,6 +890,8 @@ struct platform_device *platform_device_register_full(const struct platform_devi
ret = device_add_software_node(&pdev->dev, pdevinfo->swnode);
if (ret)
goto err;
pdev->dev.release = platform_device_release_full;
} else if (pdevinfo->properties) {
ret = device_create_managed_software_node(&pdev->dev,
pdevinfo->properties, NULL);

View File

@ -4565,24 +4565,12 @@ static int rbd_register_watch(struct rbd_device *rbd_dev)
return ret;
}
static void cancel_tasks_sync(struct rbd_device *rbd_dev)
{
dout("%s rbd_dev %p\n", __func__, rbd_dev);
cancel_work_sync(&rbd_dev->acquired_lock_work);
cancel_work_sync(&rbd_dev->released_lock_work);
cancel_delayed_work_sync(&rbd_dev->lock_dwork);
cancel_work_sync(&rbd_dev->unlock_work);
}
/*
* header_rwsem must not be held to avoid a deadlock with
* rbd_dev_refresh() when flushing notifies.
*/
static void rbd_unregister_watch(struct rbd_device *rbd_dev)
{
cancel_tasks_sync(rbd_dev);
mutex_lock(&rbd_dev->watch_mutex);
if (rbd_dev->watch_state == RBD_WATCH_STATE_REGISTERED)
__rbd_unregister_watch(rbd_dev);
@ -6548,10 +6536,18 @@ static int rbd_add_parse_args(const char *buf,
static void rbd_dev_image_unlock(struct rbd_device *rbd_dev)
{
dout("%s rbd_dev %p\n", __func__, rbd_dev);
disable_delayed_work_sync(&rbd_dev->lock_dwork);
disable_work_sync(&rbd_dev->unlock_work);
down_write(&rbd_dev->lock_rwsem);
if (__rbd_is_lock_owner(rbd_dev))
__rbd_release_lock(rbd_dev);
up_write(&rbd_dev->lock_rwsem);
flush_work(&rbd_dev->acquired_lock_work);
flush_work(&rbd_dev->released_lock_work);
}
/*

View File

@ -582,12 +582,10 @@ static int btintel_pcie_get_mac_access(struct btintel_pcie_data *data)
reg = btintel_pcie_rd_reg32(data, BTINTEL_PCIE_CSR_FUNC_CTRL_REG);
reg |= BTINTEL_PCIE_CSR_FUNC_CTRL_STOP_MAC_ACCESS_DIS;
reg |= BTINTEL_PCIE_CSR_FUNC_CTRL_XTAL_CLK_REQ;
if ((reg & BTINTEL_PCIE_CSR_FUNC_CTRL_MAC_ACCESS_STS) == 0)
if (!(reg & BTINTEL_PCIE_CSR_FUNC_CTRL_MAC_ACCESS_REQ)) {
reg |= BTINTEL_PCIE_CSR_FUNC_CTRL_MAC_ACCESS_REQ;
btintel_pcie_wr_reg32(data, BTINTEL_PCIE_CSR_FUNC_CTRL_REG, reg);
btintel_pcie_wr_reg32(data, BTINTEL_PCIE_CSR_FUNC_CTRL_REG, reg);
}
do {
reg = btintel_pcie_rd_reg32(data, BTINTEL_PCIE_CSR_FUNC_CTRL_REG);
@ -607,16 +605,10 @@ static void btintel_pcie_release_mac_access(struct btintel_pcie_data *data)
reg = btintel_pcie_rd_reg32(data, BTINTEL_PCIE_CSR_FUNC_CTRL_REG);
if (reg & BTINTEL_PCIE_CSR_FUNC_CTRL_MAC_ACCESS_REQ)
if (reg & BTINTEL_PCIE_CSR_FUNC_CTRL_MAC_ACCESS_REQ) {
reg &= ~BTINTEL_PCIE_CSR_FUNC_CTRL_MAC_ACCESS_REQ;
if (reg & BTINTEL_PCIE_CSR_FUNC_CTRL_STOP_MAC_ACCESS_DIS)
reg &= ~BTINTEL_PCIE_CSR_FUNC_CTRL_STOP_MAC_ACCESS_DIS;
if (reg & BTINTEL_PCIE_CSR_FUNC_CTRL_XTAL_CLK_REQ)
reg &= ~BTINTEL_PCIE_CSR_FUNC_CTRL_XTAL_CLK_REQ;
btintel_pcie_wr_reg32(data, BTINTEL_PCIE_CSR_FUNC_CTRL_REG, reg);
btintel_pcie_wr_reg32(data, BTINTEL_PCIE_CSR_FUNC_CTRL_REG, reg);
}
}
static void *btintel_pcie_copy_tlv(void *dest, enum btintel_pcie_tlv_type type,

View File

@ -34,9 +34,6 @@
#define BTINTEL_PCIE_CSR_FUNC_CTRL_MAC_ACCESS_STS (BIT(20))
#define BTINTEL_PCIE_CSR_FUNC_CTRL_MAC_ACCESS_REQ (BIT(21))
/* Stop MAC Access disconnection request */
#define BTINTEL_PCIE_CSR_FUNC_CTRL_STOP_MAC_ACCESS_DIS (BIT(22))
#define BTINTEL_PCIE_CSR_FUNC_CTRL_XTAL_CLK_REQ (BIT(23))
#define BTINTEL_PCIE_CSR_FUNC_CTRL_BUS_MASTER_STS (BIT(28))
#define BTINTEL_PCIE_CSR_FUNC_CTRL_BUS_MASTER_DISCON (BIT(29))

View File

@ -537,6 +537,7 @@ static void btmtk_usb_wmt_recv(struct urb *urb)
return;
} else if (urb->status == -ENOENT) {
/* Avoid suspend failed when usb_kill_urb */
kfree(urb->setup_packet);
return;
}
@ -610,6 +611,7 @@ static int btmtk_usb_submit_wmt_recv_urb(struct hci_dev *hdev)
if (err != -EPERM && err != -ENODEV)
bt_dev_err(hdev, "urb %p submission failed (%d)",
urb, -err);
kfree(dr);
usb_unanchor_urb(urb);
}
@ -719,8 +721,8 @@ static int btmtk_usb_hci_wmt_sync(struct hci_dev *hdev,
case BTMTK_WMT_FUNC_CTRL:
if (!skb_pull_data(data->evt_skb,
sizeof(wmt_evt_funcc->status))) {
err = -EINVAL;
goto err_free_skb;
status = BTMTK_WMT_ON_UNDONE;
break;
}
wmt_evt_funcc = (struct btmtk_hci_wmt_evt_funcc *)wmt_evt;

View File

@ -194,7 +194,15 @@ void hci_uart_init_work(struct work_struct *work)
err = hci_register_dev(hu->hdev);
if (err < 0) {
BT_ERR("Can't register HCI device");
percpu_down_write(&hu->proto_lock);
clear_bit(HCI_UART_PROTO_READY, &hu->flags);
percpu_up_write(&hu->proto_lock);
/* Safely cancel work after clearing flags */
cancel_work_sync(&hu->write_work);
/* Close protocol before freeing hdev */
hu->proto->close(hu);
hdev = hu->hdev;
hu->hdev = NULL;
@ -263,8 +271,12 @@ static int hci_uart_open(struct hci_dev *hdev)
/* Close device */
static int hci_uart_close(struct hci_dev *hdev)
{
struct hci_uart *hu = hci_get_drvdata(hdev);
BT_DBG("hdev %p", hdev);
cancel_work_sync(&hu->write_work);
hci_uart_flush(hdev);
hdev->flush = NULL;
return 0;
@ -531,6 +543,7 @@ static void hci_uart_tty_close(struct tty_struct *tty)
{
struct hci_uart *hu = tty->disc_data;
struct hci_dev *hdev;
bool proto_ready;
BT_DBG("tty %p", tty);
@ -540,24 +553,38 @@ static void hci_uart_tty_close(struct tty_struct *tty)
if (!hu)
return;
hdev = hu->hdev;
if (hdev)
hci_uart_close(hdev);
/* Wait for init_ready to finish to prevent registration races */
cancel_work_sync(&hu->init_ready);
if (test_bit(HCI_UART_PROTO_READY, &hu->flags)) {
proto_ready = test_bit(HCI_UART_PROTO_READY, &hu->flags);
if (proto_ready) {
percpu_down_write(&hu->proto_lock);
clear_bit(HCI_UART_PROTO_READY, &hu->flags);
percpu_up_write(&hu->proto_lock);
}
cancel_work_sync(&hu->init_ready);
cancel_work_sync(&hu->write_work);
/*
* Unconditionally cancel write_work AFTER clearing PROTO_READY.
* This ensures that concurrent protocol timers cannot requeue
* write_work via hci_uart_tx_wakeup(), permanently preventing
* double-free races and UAFs.
*/
cancel_work_sync(&hu->write_work);
hdev = hu->hdev;
if (hdev)
hci_uart_close(hdev); /* proto->flush is safely skipped */
if (proto_ready) {
if (hdev) {
if (test_bit(HCI_UART_REGISTERED, &hu->flags))
hci_unregister_dev(hdev);
hci_free_dev(hdev);
}
/* Close protocol before freeing hdev (intrinsically purges queues) */
hu->proto->close(hu);
if (hdev)
hci_free_dev(hdev);
}
clear_bit(HCI_UART_PROTO_SET, &hu->flags);
@ -625,11 +652,12 @@ static void hci_uart_tty_receive(struct tty_struct *tty, const u8 *data,
* tty caller
*/
hu->proto->recv(hu, data, count);
percpu_up_read(&hu->proto_lock);
if (hu->hdev)
hu->hdev->stat.byte_rx += count;
percpu_up_read(&hu->proto_lock);
tty_unthrottle(tty);
}
@ -695,6 +723,10 @@ static int hci_uart_register_dev(struct hci_uart *hu)
percpu_down_write(&hu->proto_lock);
clear_bit(HCI_UART_PROTO_INIT, &hu->flags);
percpu_up_write(&hu->proto_lock);
/* Cancel work after clearing flags */
cancel_work_sync(&hu->write_work);
/* Close protocol before freeing hdev */
hu->proto->close(hu);
hu->hdev = NULL;
hci_free_dev(hdev);

View File

@ -48,13 +48,12 @@
#define HCI_MAX_IBS_SIZE 10
#define IBS_WAKE_RETRANS_TIMEOUT_MS 100
#define IBS_BTSOC_TX_IDLE_TIMEOUT_MS 200
#define IBS_BTSOC_TX_IDLE_TIMEOUT msecs_to_jiffies(200)
#define IBS_HOST_TX_IDLE_TIMEOUT_MS 2000
#define CMD_TRANS_TIMEOUT_MS 100
#define MEMDUMP_TIMEOUT_MS 8000
#define IBS_DISABLE_SSR_TIMEOUT_MS \
(MEMDUMP_TIMEOUT_MS + FW_DOWNLOAD_TIMEOUT_MS)
#define FW_DOWNLOAD_TIMEOUT_MS 3000
#define CMD_TRANS_TIMEOUT msecs_to_jiffies(100)
#define MEMDUMP_TIMEOUT msecs_to_jiffies(8000)
#define FW_DOWNLOAD_TIMEOUT msecs_to_jiffies(3000)
#define IBS_DISABLE_SSR_TIMEOUT (MEMDUMP_TIMEOUT + FW_DOWNLOAD_TIMEOUT)
/* susclk rate */
#define SUSCLK_RATE_32KHZ 32768
@ -1096,7 +1095,7 @@ static void qca_controller_memdump(struct work_struct *work)
queue_delayed_work(qca->workqueue,
&qca->ctrl_memdump_timeout,
msecs_to_jiffies(MEMDUMP_TIMEOUT_MS));
MEMDUMP_TIMEOUT);
skb_pull(skb, sizeof(qca_memdump->ram_dump_size));
qca_memdump->current_seq_no = 0;
qca_memdump->received_dump = 0;
@ -1369,7 +1368,7 @@ static int qca_set_baudrate(struct hci_dev *hdev, uint8_t baudrate)
if (hu->serdev)
serdev_device_wait_until_sent(hu->serdev,
msecs_to_jiffies(CMD_TRANS_TIMEOUT_MS));
CMD_TRANS_TIMEOUT);
/* Give the controller time to process the request */
switch (qca_soc_type(hu)) {
@ -1401,8 +1400,8 @@ static inline void host_set_baudrate(struct hci_uart *hu, unsigned int speed)
static int qca_send_power_pulse(struct hci_uart *hu, bool on)
{
int timeout = CMD_TRANS_TIMEOUT;
int ret;
int timeout = msecs_to_jiffies(CMD_TRANS_TIMEOUT_MS);
u8 cmd = on ? QCA_WCN3990_POWERON_PULSE : QCA_WCN3990_POWEROFF_PULSE;
/* These power pulses are single byte command which are sent
@ -1607,7 +1606,7 @@ static void qca_wait_for_dump_collection(struct hci_dev *hdev)
struct qca_data *qca = hu->priv;
wait_on_bit_timeout(&qca->flags, QCA_MEMDUMP_COLLECTION,
TASK_UNINTERRUPTIBLE, MEMDUMP_TIMEOUT_MS);
TASK_UNINTERRUPTIBLE, MEMDUMP_TIMEOUT);
clear_bit(QCA_MEMDUMP_COLLECTION, &qca->flags);
}
@ -2591,7 +2590,7 @@ static void qca_serdev_remove(struct serdev_device *serdev)
static void qca_serdev_shutdown(struct serdev_device *serdev)
{
int ret;
int timeout = msecs_to_jiffies(CMD_TRANS_TIMEOUT_MS);
int timeout = CMD_TRANS_TIMEOUT;
struct qca_serdev *qcadev = serdev_device_get_drvdata(serdev);
struct hci_uart *hu = &qcadev->serdev_hu;
struct hci_dev *hdev = hu->hdev;
@ -2648,7 +2647,7 @@ static int __maybe_unused qca_suspend(struct device *dev)
bool tx_pending = false;
int ret = 0;
u8 cmd;
u32 wait_timeout = 0;
unsigned long wait_timeout = 0;
set_bit(QCA_SUSPENDING, &qca->flags);
@ -2669,15 +2668,15 @@ static int __maybe_unused qca_suspend(struct device *dev)
if (test_bit(QCA_IBS_DISABLED, &qca->flags) ||
test_bit(QCA_SSR_TRIGGERED, &qca->flags)) {
wait_timeout = test_bit(QCA_SSR_TRIGGERED, &qca->flags) ?
IBS_DISABLE_SSR_TIMEOUT_MS :
FW_DOWNLOAD_TIMEOUT_MS;
IBS_DISABLE_SSR_TIMEOUT :
FW_DOWNLOAD_TIMEOUT;
/* QCA_IBS_DISABLED flag is set to true, During FW download
* and during memory dump collection. It is reset to false,
* After FW download complete.
*/
wait_on_bit_timeout(&qca->flags, QCA_IBS_DISABLED,
TASK_UNINTERRUPTIBLE, msecs_to_jiffies(wait_timeout));
TASK_UNINTERRUPTIBLE, wait_timeout);
if (test_bit(QCA_IBS_DISABLED, &qca->flags)) {
bt_dev_err(hu->hdev, "SSR or FW download time out");
@ -2729,7 +2728,7 @@ static int __maybe_unused qca_suspend(struct device *dev)
if (tx_pending) {
serdev_device_wait_until_sent(hu->serdev,
msecs_to_jiffies(CMD_TRANS_TIMEOUT_MS));
CMD_TRANS_TIMEOUT);
serial_clock_vote(HCI_IBS_TX_VOTE_CLOCK_OFF, hu);
}
@ -2738,7 +2737,7 @@ static int __maybe_unused qca_suspend(struct device *dev)
*/
ret = wait_event_interruptible_timeout(qca->suspend_wait_q,
qca->rx_ibs_state == HCI_IBS_RX_ASLEEP,
msecs_to_jiffies(IBS_BTSOC_TX_IDLE_TIMEOUT_MS));
IBS_BTSOC_TX_IDLE_TIMEOUT);
if (ret == 0) {
ret = -ETIMEDOUT;
goto error;

View File

@ -70,18 +70,6 @@ config X86_AMD_PSTATE_DEFAULT_MODE
For details, take a look at:
<file:Documentation/admin-guide/pm/amd-pstate.rst>.
config X86_AMD_PSTATE_DYNAMIC_EPP
bool "AMD Processor P-State dynamic EPP support"
depends on X86_AMD_PSTATE
default n
help
Allow the kernel to dynamically change the energy performance
value from events like ACPI platform profile and AC adapter plug
events.
This feature can also be changed at runtime, this configuration
option only sets the kernel default value behavior.
config X86_AMD_PSTATE_UT
tristate "selftest for AMD Processor P-State driver"
depends on X86 && ACPI_PROCESSOR

View File

@ -274,20 +274,21 @@ static int amd_pstate_set_mode(enum amd_pstate_mode mode)
static int amd_pstate_ut_epp(u32 index)
{
struct cpufreq_policy *policy __free(put_cpufreq_policy) = NULL;
char *buf __free(cleanup_page) = NULL;
static const char * const epp_strings[] = {
"performance",
"balance_performance",
"balance_power",
"power",
"balance_power",
"balance_performance",
"performance",
};
struct amd_cpudata *cpudata;
char *buf __free(cleanup_page) = NULL;
struct cpufreq_policy *policy = NULL;
enum amd_pstate_mode orig_mode;
struct amd_cpudata *cpudata;
unsigned long orig_policy;
bool orig_dynamic_epp;
int ret, cpu = 0;
int i;
u16 epp;
int i;
policy = cpufreq_cpu_get(cpu);
if (!policy)
@ -297,6 +298,10 @@ static int amd_pstate_ut_epp(u32 index)
orig_mode = amd_pstate_get_status();
orig_dynamic_epp = cpudata->dynamic_epp;
/* Drop reference before potential driver change. */
cpufreq_cpu_put(policy);
policy = NULL;
/* disable dynamic EPP before running test */
if (cpudata->dynamic_epp) {
pr_debug("Dynamic EPP is enabled, disabling it\n");
@ -311,6 +316,17 @@ static int amd_pstate_ut_epp(u32 index)
if (ret)
goto out;
policy = cpufreq_cpu_get(cpu);
if (!policy) {
ret = -ENODEV;
goto out;
}
down_write(&policy->rwsem);
cpudata = policy->driver_data;
orig_policy = cpudata->policy;
cpudata->policy = CPUFREQ_POLICY_POWERSAVE;
for (epp = 0; epp <= U8_MAX; epp++) {
u8 val;
@ -358,6 +374,12 @@ static int amd_pstate_ut_epp(u32 index)
ret = 0;
out:
if (policy) {
cpudata->policy = orig_policy;
up_write(&policy->rwsem);
cpufreq_cpu_put(policy);
}
if (orig_dynamic_epp) {
int ret2;

View File

@ -87,11 +87,7 @@ static struct cpufreq_driver amd_pstate_driver;
static struct cpufreq_driver amd_pstate_epp_driver;
static int cppc_state = AMD_PSTATE_UNDEFINED;
static bool amd_pstate_prefcore = true;
#ifdef CONFIG_X86_AMD_PSTATE_DYNAMIC_EPP
static bool dynamic_epp = CONFIG_X86_AMD_PSTATE_DYNAMIC_EPP;
#else
static bool dynamic_epp;
#endif
static struct quirk_entry *quirks;
/*
@ -1291,6 +1287,8 @@ static int amd_pstate_set_dynamic_epp(struct cpufreq_policy *policy)
return ret;
cpudata->profile_name = kasprintf(GFP_KERNEL, "amd-pstate-epp-cpu%d", cpudata->cpu);
if (!cpudata->profile_name)
return -ENOMEM;
cpudata->ppdev = platform_profile_register(get_cpu_device(policy->cpu),
cpudata->profile_name,
@ -1427,7 +1425,7 @@ ssize_t store_energy_performance_preference(struct cpufreq_policy *policy,
if (ret)
epp = epp_values[ret];
else
epp = amd_pstate_get_balanced_epp(policy);
epp = cpudata->epp_default_dc;
}
if (cpudata->policy == CPUFREQ_POLICY_PERFORMANCE) {
@ -1707,6 +1705,8 @@ static int amd_pstate_change_driver_mode(int mode)
{
int ret;
lockdep_assert_held(&amd_pstate_driver_lock);
ret = amd_pstate_unregister_driver(0);
if (ret)
return ret;
@ -1821,8 +1821,16 @@ static ssize_t dynamic_epp_store(struct device *a, struct device_attribute *b,
if (ret)
return ret;
if (dynamic_epp == enabled)
guard(mutex)(&amd_pstate_driver_lock);
if (cppc_state != AMD_PSTATE_ACTIVE) {
pr_debug("dynamic_epp can only be toggled in active mode\n");
return -EINVAL;
}
/* Nothing to do */
if (dynamic_epp == enabled)
return count;
/* reinitialize with desired dynamic EPP value */
dynamic_epp = enabled;
@ -1942,7 +1950,7 @@ static int amd_pstate_epp_cpu_init(struct cpufreq_policy *policy)
if (dynamic_epp)
ret = amd_pstate_set_dynamic_epp(policy);
else
ret = amd_pstate_set_epp(policy, amd_pstate_get_balanced_epp(policy));
ret = amd_pstate_set_epp(policy, cpudata->epp_default_dc);
if (ret)
goto free_cpudata1;
@ -1970,12 +1978,13 @@ static void amd_pstate_epp_cpu_exit(struct cpufreq_policy *policy)
if (cpudata) {
union perf_cached perf = READ_ONCE(cpudata->perf);
if (cpudata->dynamic_epp)
amd_pstate_clear_dynamic_epp(policy);
/* Reset CPPC_REQ MSR to the BIOS value */
amd_pstate_update_perf(policy, perf.bios_min_perf, 0U, 0U, 0U, false);
amd_pstate_set_floor_perf(policy, cpudata->bios_floor_perf);
if (cpudata->dynamic_epp)
amd_pstate_clear_dynamic_epp(policy);
kfree(cpudata);
policy->driver_data = NULL;
}

View File

@ -2279,7 +2279,7 @@ static int hwp_get_cpu_scaling(int cpu)
* Return the hybrid scaling factor for P-cores and use the
* default core scaling for E-cores.
*/
if (hybrid_get_cpu_type(cpu) == INTEL_CPU_TYPE_CORE)
if (hybrid_get_cpu_type(cpu) != INTEL_CPU_TYPE_ATOM)
return hybrid_scaling_factor;
return core_get_scaling();
@ -3734,6 +3734,7 @@ static const struct x86_cpu_id intel_hybrid_scaling_factor[] = {
X86_MATCH_VFM(INTEL_RAPTORLAKE, HYBRID_SCALING_FACTOR_ADL),
X86_MATCH_VFM(INTEL_RAPTORLAKE_P, HYBRID_SCALING_FACTOR_ADL),
X86_MATCH_VFM(INTEL_RAPTORLAKE_S, HYBRID_SCALING_FACTOR_ADL),
X86_MATCH_VFM(INTEL_BARTLETTLAKE, HYBRID_SCALING_FACTOR_ADL),
X86_MATCH_VFM(INTEL_METEORLAKE_L, HYBRID_SCALING_FACTOR_MTL),
X86_MATCH_VFM(INTEL_LUNARLAKE_M, HYBRID_SCALING_FACTOR_LNL),
{}

View File

@ -1394,8 +1394,8 @@ zl3073x_dpll_pin_register(struct zl3073x_dpll_pin *pin, u32 index)
err_register:
dpll_pin_put(pin->dpll_pin, &pin->tracker);
pin->dpll_pin = NULL;
err_pin_get:
pin->dpll_pin = NULL;
fwnode_handle_put(pin->fwnode);
pin->fwnode = NULL;
zl3073x_pin_props_put(props);
@ -1563,8 +1563,10 @@ zl3073x_dpll_pins_register(struct zl3073x_dpll *zldpll)
}
rc = zl3073x_dpll_pin_register(pin, index);
if (rc)
if (rc) {
zl3073x_dpll_pin_free(pin);
goto error;
}
list_add(&pin->list, &zldpll->pins);
}

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