mirror of
https://github.com/torvalds/linux.git
synced 2026-07-27 17:47:41 +02:00
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:
commit
2aa8946ed9
2
.mailmap
2
.mailmap
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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/
|
||||
|
|
|
|||
|
|
@ -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
|
||||
===========================================
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
---------------------
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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>;
|
||||
|
||||
|
|
|
|||
|
|
@ -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>,
|
||||
|
|
|
|||
|
|
@ -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>,
|
||||
|
|
|
|||
|
|
@ -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>;
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
249
Documentation/networking/device_drivers/ethernet/3com/3c509.rst
Normal file
249
Documentation/networking/device_drivers/ethernet/3com/3c509.rst
Normal 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
|
||||
|
||||
|
|
@ -10,6 +10,7 @@ Contents:
|
|||
.. toctree::
|
||||
:maxdepth: 2
|
||||
|
||||
3com/3c509
|
||||
3com/vortex
|
||||
amazon/ena
|
||||
altera/altera_tse
|
||||
|
|
|
|||
21
MAINTAINERS
21
MAINTAINERS
|
|
@ -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
|
||||
|
|
|
|||
2
Makefile
2
Makefile
|
|
@ -2,7 +2,7 @@
|
|||
VERSION = 7
|
||||
PATCHLEVEL = 1
|
||||
SUBLEVEL = 0
|
||||
EXTRAVERSION = -rc4
|
||||
EXTRAVERSION = -rc5
|
||||
NAME = Baby Opossum Posse
|
||||
|
||||
# *DOCUMENTATION*
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
10
arch/arm64/include/asm/ring_buffer.h
Normal file
10
arch/arm64/include/asm/ring_buffer.h
Normal 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 */
|
||||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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, ®s);
|
||||
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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
61
arch/x86/entry/common.c
Normal 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
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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) |
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
|
|
|||
|
|
@ -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 },
|
||||
{}
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
{
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -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 *
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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))
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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),
|
||||
{}
|
||||
|
|
|
|||
|
|
@ -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
Loading…
Reference in New Issue
Block a user