Compare commits
103 Commits
develop-5.10
...
v5.1.3
| Author | SHA1 | Date | |
|---|---|---|---|
| 7cb9c5d341 | |||
| dabb99e0a8 | |||
| d82e3d5b18 | |||
| 5c36f4347d | |||
| 91425cbebb | |||
| 037ca76579 | |||
| 665c4bdd57 | |||
| 2f855814e7 | |||
| 6aa7a9ea94 | |||
| 85ee20811e | |||
| 41771de5af | |||
| de2dec852a | |||
| e106991b22 | |||
| b58df9d780 | |||
| 0f852d10a0 | |||
| 6e1d1a3a33 | |||
| ee0d666d5d | |||
| 4e03133855 | |||
| 5338e8ff22 | |||
| 17617cd555 | |||
| 7ad0ccae4b | |||
| be0e51d77a | |||
| abda892dda | |||
| 5f80c82f30 | |||
| a344dc5cd3 | |||
| 2cb6d28ba5 | |||
| 353b3fd8e2 | |||
| e83a63de80 | |||
| e996c41bb1 | |||
| 73082d240f | |||
| 9035a94182 | |||
| 57e60bc8f7 | |||
| 4c72b658be | |||
| b856e1fb89 | |||
| 9952ff2838 | |||
| 6fd04652aa | |||
| 777d3fa587 | |||
| 7b2c4e6de6 | |||
| af6a4f3ccd | |||
| d4173b7588 | |||
| 214e40a558 | |||
| e2bc9bc6ee | |||
| 59190fff6b | |||
| 67acc44d45 | |||
| eb5d65a82f | |||
| 31422a6888 | |||
| a1466018d2 | |||
| f937f9cbb0 | |||
| 3c01673ec7 | |||
| 72a36b7b6d | |||
| efd0d8e77f | |||
| b2a4f56ae9 | |||
| 4f4925c6b5 | |||
| dc34d771d9 | |||
| b93150b852 | |||
| 4d1a2e9196 | |||
| 4d902d90b6 | |||
| 56c4c99cc9 | |||
| 563a2e3936 | |||
| 39a02bd9b4 | |||
| 6e38d5ba36 | |||
| a287e16c15 | |||
| 8ed0c139ba | |||
| 7014e3277e | |||
| 42a9740922 | |||
| 186fcd64f1 | |||
| 5048b39b36 | |||
| 744212bffe | |||
| e30a0ae078 | |||
| ffbf567169 | |||
| 06c3719786 | |||
| 48d1bb18e3 | |||
| b724e93564 | |||
| 022ccef6d1 | |||
| 325d0a18d3 | |||
| 3ae39e99e5 | |||
| b8f93c2735 | |||
| 7fc35c756b | |||
| d00686df16 | |||
| a324fa5054 | |||
| 07e38998a1 | |||
| 4d4cafccc6 | |||
| 435885bdb0 | |||
| 63ec822488 | |||
| 7065a70d69 | |||
| 1119e98d0e | |||
| 4fb84183e0 | |||
| cebdbdda48 | |||
| f6ad5c7d15 | |||
| 3a8fc4fad9 | |||
| 1b1dbf7068 | |||
| 1f0f5b3ed6 | |||
| 03bc265244 | |||
| 57a65a3140 | |||
| b27d939957 | |||
| a1ab43c370 | |||
| 5928706ff1 | |||
| 6643e2610a | |||
| d0e289e4a6 | |||
| 651832db87 | |||
| f40de00d49 | |||
| d222de4c7d | |||
| 6637557e4e |
@@ -484,6 +484,7 @@ What: /sys/devices/system/cpu/vulnerabilities
|
||||
/sys/devices/system/cpu/vulnerabilities/spectre_v2
|
||||
/sys/devices/system/cpu/vulnerabilities/spec_store_bypass
|
||||
/sys/devices/system/cpu/vulnerabilities/l1tf
|
||||
/sys/devices/system/cpu/vulnerabilities/mds
|
||||
Date: January 2018
|
||||
Contact: Linux kernel mailing list <linux-kernel@vger.kernel.org>
|
||||
Description: Information about CPU vulnerabilities
|
||||
@@ -496,8 +497,7 @@ Description: Information about CPU vulnerabilities
|
||||
"Vulnerable" CPU is affected and no mitigation in effect
|
||||
"Mitigation: $M" CPU is affected and mitigation $M is in effect
|
||||
|
||||
Details about the l1tf file can be found in
|
||||
Documentation/admin-guide/l1tf.rst
|
||||
See also: Documentation/admin-guide/hw-vuln/index.rst
|
||||
|
||||
What: /sys/devices/system/cpu/smt
|
||||
/sys/devices/system/cpu/smt/active
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
========================
|
||||
Hardware vulnerabilities
|
||||
========================
|
||||
|
||||
This section describes CPU vulnerabilities and provides an overview of the
|
||||
possible mitigations along with guidance for selecting mitigations if they
|
||||
are configurable at compile, boot or run time.
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
|
||||
l1tf
|
||||
mds
|
||||
@@ -445,6 +445,7 @@ The default is 'cond'. If 'l1tf=full,force' is given on the kernel command
|
||||
line, then 'always' is enforced and the kvm-intel.vmentry_l1d_flush
|
||||
module parameter is ignored and writes to the sysfs file are rejected.
|
||||
|
||||
.. _mitigation_selection:
|
||||
|
||||
Mitigation selection guide
|
||||
--------------------------
|
||||
@@ -0,0 +1,308 @@
|
||||
MDS - Microarchitectural Data Sampling
|
||||
======================================
|
||||
|
||||
Microarchitectural Data Sampling is a hardware vulnerability which allows
|
||||
unprivileged speculative access to data which is available in various CPU
|
||||
internal buffers.
|
||||
|
||||
Affected processors
|
||||
-------------------
|
||||
|
||||
This vulnerability affects a wide range of Intel processors. The
|
||||
vulnerability is not present on:
|
||||
|
||||
- Processors from AMD, Centaur and other non Intel vendors
|
||||
|
||||
- Older processor models, where the CPU family is < 6
|
||||
|
||||
- Some Atoms (Bonnell, Saltwell, Goldmont, GoldmontPlus)
|
||||
|
||||
- Intel processors which have the ARCH_CAP_MDS_NO bit set in the
|
||||
IA32_ARCH_CAPABILITIES MSR.
|
||||
|
||||
Whether a processor is affected or not can be read out from the MDS
|
||||
vulnerability file in sysfs. See :ref:`mds_sys_info`.
|
||||
|
||||
Not all processors are affected by all variants of MDS, but the mitigation
|
||||
is identical for all of them so the kernel treats them as a single
|
||||
vulnerability.
|
||||
|
||||
Related CVEs
|
||||
------------
|
||||
|
||||
The following CVE entries are related to the MDS vulnerability:
|
||||
|
||||
============== ===== ===================================================
|
||||
CVE-2018-12126 MSBDS Microarchitectural Store Buffer Data Sampling
|
||||
CVE-2018-12130 MFBDS Microarchitectural Fill Buffer Data Sampling
|
||||
CVE-2018-12127 MLPDS Microarchitectural Load Port Data Sampling
|
||||
CVE-2019-11091 MDSUM Microarchitectural Data Sampling Uncacheable Memory
|
||||
============== ===== ===================================================
|
||||
|
||||
Problem
|
||||
-------
|
||||
|
||||
When performing store, load, L1 refill operations, processors write data
|
||||
into temporary microarchitectural structures (buffers). The data in the
|
||||
buffer can be forwarded to load operations as an optimization.
|
||||
|
||||
Under certain conditions, usually a fault/assist caused by a load
|
||||
operation, data unrelated to the load memory address can be speculatively
|
||||
forwarded from the buffers. Because the load operation causes a fault or
|
||||
assist and its result will be discarded, the forwarded data will not cause
|
||||
incorrect program execution or state changes. But a malicious operation
|
||||
may be able to forward this speculative data to a disclosure gadget which
|
||||
allows in turn to infer the value via a cache side channel attack.
|
||||
|
||||
Because the buffers are potentially shared between Hyper-Threads cross
|
||||
Hyper-Thread attacks are possible.
|
||||
|
||||
Deeper technical information is available in the MDS specific x86
|
||||
architecture section: :ref:`Documentation/x86/mds.rst <mds>`.
|
||||
|
||||
|
||||
Attack scenarios
|
||||
----------------
|
||||
|
||||
Attacks against the MDS vulnerabilities can be mounted from malicious non
|
||||
priviledged user space applications running on hosts or guest. Malicious
|
||||
guest OSes can obviously mount attacks as well.
|
||||
|
||||
Contrary to other speculation based vulnerabilities the MDS vulnerability
|
||||
does not allow the attacker to control the memory target address. As a
|
||||
consequence the attacks are purely sampling based, but as demonstrated with
|
||||
the TLBleed attack samples can be postprocessed successfully.
|
||||
|
||||
Web-Browsers
|
||||
^^^^^^^^^^^^
|
||||
|
||||
It's unclear whether attacks through Web-Browsers are possible at
|
||||
all. The exploitation through Java-Script is considered very unlikely,
|
||||
but other widely used web technologies like Webassembly could possibly be
|
||||
abused.
|
||||
|
||||
|
||||
.. _mds_sys_info:
|
||||
|
||||
MDS system information
|
||||
-----------------------
|
||||
|
||||
The Linux kernel provides a sysfs interface to enumerate the current MDS
|
||||
status of the system: whether the system is vulnerable, and which
|
||||
mitigations are active. The relevant sysfs file is:
|
||||
|
||||
/sys/devices/system/cpu/vulnerabilities/mds
|
||||
|
||||
The possible values in this file are:
|
||||
|
||||
.. list-table::
|
||||
|
||||
* - 'Not affected'
|
||||
- The processor is not vulnerable
|
||||
* - 'Vulnerable'
|
||||
- The processor is vulnerable, but no mitigation enabled
|
||||
* - 'Vulnerable: Clear CPU buffers attempted, no microcode'
|
||||
- The processor is vulnerable but microcode is not updated.
|
||||
|
||||
The mitigation is enabled on a best effort basis. See :ref:`vmwerv`
|
||||
* - 'Mitigation: Clear CPU buffers'
|
||||
- The processor is vulnerable and the CPU buffer clearing mitigation is
|
||||
enabled.
|
||||
|
||||
If the processor is vulnerable then the following information is appended
|
||||
to the above information:
|
||||
|
||||
======================== ============================================
|
||||
'SMT vulnerable' SMT is enabled
|
||||
'SMT mitigated' SMT is enabled and mitigated
|
||||
'SMT disabled' SMT is disabled
|
||||
'SMT Host state unknown' Kernel runs in a VM, Host SMT state unknown
|
||||
======================== ============================================
|
||||
|
||||
.. _vmwerv:
|
||||
|
||||
Best effort mitigation mode
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
If the processor is vulnerable, but the availability of the microcode based
|
||||
mitigation mechanism is not advertised via CPUID the kernel selects a best
|
||||
effort mitigation mode. This mode invokes the mitigation instructions
|
||||
without a guarantee that they clear the CPU buffers.
|
||||
|
||||
This is done to address virtualization scenarios where the host has the
|
||||
microcode update applied, but the hypervisor is not yet updated to expose
|
||||
the CPUID to the guest. If the host has updated microcode the protection
|
||||
takes effect otherwise a few cpu cycles are wasted pointlessly.
|
||||
|
||||
The state in the mds sysfs file reflects this situation accordingly.
|
||||
|
||||
|
||||
Mitigation mechanism
|
||||
-------------------------
|
||||
|
||||
The kernel detects the affected CPUs and the presence of the microcode
|
||||
which is required.
|
||||
|
||||
If a CPU is affected and the microcode is available, then the kernel
|
||||
enables the mitigation by default. The mitigation can be controlled at boot
|
||||
time via a kernel command line option. See
|
||||
:ref:`mds_mitigation_control_command_line`.
|
||||
|
||||
.. _cpu_buffer_clear:
|
||||
|
||||
CPU buffer clearing
|
||||
^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
The mitigation for MDS clears the affected CPU buffers on return to user
|
||||
space and when entering a guest.
|
||||
|
||||
If SMT is enabled it also clears the buffers on idle entry when the CPU
|
||||
is only affected by MSBDS and not any other MDS variant, because the
|
||||
other variants cannot be protected against cross Hyper-Thread attacks.
|
||||
|
||||
For CPUs which are only affected by MSBDS the user space, guest and idle
|
||||
transition mitigations are sufficient and SMT is not affected.
|
||||
|
||||
.. _virt_mechanism:
|
||||
|
||||
Virtualization mitigation
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
The protection for host to guest transition depends on the L1TF
|
||||
vulnerability of the CPU:
|
||||
|
||||
- CPU is affected by L1TF:
|
||||
|
||||
If the L1D flush mitigation is enabled and up to date microcode is
|
||||
available, the L1D flush mitigation is automatically protecting the
|
||||
guest transition.
|
||||
|
||||
If the L1D flush mitigation is disabled then the MDS mitigation is
|
||||
invoked explicit when the host MDS mitigation is enabled.
|
||||
|
||||
For details on L1TF and virtualization see:
|
||||
:ref:`Documentation/admin-guide/hw-vuln//l1tf.rst <mitigation_control_kvm>`.
|
||||
|
||||
- CPU is not affected by L1TF:
|
||||
|
||||
CPU buffers are flushed before entering the guest when the host MDS
|
||||
mitigation is enabled.
|
||||
|
||||
The resulting MDS protection matrix for the host to guest transition:
|
||||
|
||||
============ ===== ============= ============ =================
|
||||
L1TF MDS VMX-L1FLUSH Host MDS MDS-State
|
||||
|
||||
Don't care No Don't care N/A Not affected
|
||||
|
||||
Yes Yes Disabled Off Vulnerable
|
||||
|
||||
Yes Yes Disabled Full Mitigated
|
||||
|
||||
Yes Yes Enabled Don't care Mitigated
|
||||
|
||||
No Yes N/A Off Vulnerable
|
||||
|
||||
No Yes N/A Full Mitigated
|
||||
============ ===== ============= ============ =================
|
||||
|
||||
This only covers the host to guest transition, i.e. prevents leakage from
|
||||
host to guest, but does not protect the guest internally. Guests need to
|
||||
have their own protections.
|
||||
|
||||
.. _xeon_phi:
|
||||
|
||||
XEON PHI specific considerations
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
The XEON PHI processor family is affected by MSBDS which can be exploited
|
||||
cross Hyper-Threads when entering idle states. Some XEON PHI variants allow
|
||||
to use MWAIT in user space (Ring 3) which opens an potential attack vector
|
||||
for malicious user space. The exposure can be disabled on the kernel
|
||||
command line with the 'ring3mwait=disable' command line option.
|
||||
|
||||
XEON PHI is not affected by the other MDS variants and MSBDS is mitigated
|
||||
before the CPU enters a idle state. As XEON PHI is not affected by L1TF
|
||||
either disabling SMT is not required for full protection.
|
||||
|
||||
.. _mds_smt_control:
|
||||
|
||||
SMT control
|
||||
^^^^^^^^^^^
|
||||
|
||||
All MDS variants except MSBDS can be attacked cross Hyper-Threads. That
|
||||
means on CPUs which are affected by MFBDS or MLPDS it is necessary to
|
||||
disable SMT for full protection. These are most of the affected CPUs; the
|
||||
exception is XEON PHI, see :ref:`xeon_phi`.
|
||||
|
||||
Disabling SMT can have a significant performance impact, but the impact
|
||||
depends on the type of workloads.
|
||||
|
||||
See the relevant chapter in the L1TF mitigation documentation for details:
|
||||
:ref:`Documentation/admin-guide/hw-vuln/l1tf.rst <smt_control>`.
|
||||
|
||||
|
||||
.. _mds_mitigation_control_command_line:
|
||||
|
||||
Mitigation control on the kernel command line
|
||||
---------------------------------------------
|
||||
|
||||
The kernel command line allows to control the MDS mitigations at boot
|
||||
time with the option "mds=". The valid arguments for this option are:
|
||||
|
||||
============ =============================================================
|
||||
full If the CPU is vulnerable, enable all available mitigations
|
||||
for the MDS vulnerability, CPU buffer clearing on exit to
|
||||
userspace and when entering a VM. Idle transitions are
|
||||
protected as well if SMT is enabled.
|
||||
|
||||
It does not automatically disable SMT.
|
||||
|
||||
full,nosmt The same as mds=full, with SMT disabled on vulnerable
|
||||
CPUs. This is the complete mitigation.
|
||||
|
||||
off Disables MDS mitigations completely.
|
||||
|
||||
============ =============================================================
|
||||
|
||||
Not specifying this option is equivalent to "mds=full".
|
||||
|
||||
|
||||
Mitigation selection guide
|
||||
--------------------------
|
||||
|
||||
1. Trusted userspace
|
||||
^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
If all userspace applications are from a trusted source and do not
|
||||
execute untrusted code which is supplied externally, then the mitigation
|
||||
can be disabled.
|
||||
|
||||
|
||||
2. Virtualization with trusted guests
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
The same considerations as above versus trusted user space apply.
|
||||
|
||||
3. Virtualization with untrusted guests
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
The protection depends on the state of the L1TF mitigations.
|
||||
See :ref:`virt_mechanism`.
|
||||
|
||||
If the MDS mitigation is enabled and SMT is disabled, guest to host and
|
||||
guest to guest attacks are prevented.
|
||||
|
||||
.. _mds_default_mitigations:
|
||||
|
||||
Default mitigations
|
||||
-------------------
|
||||
|
||||
The kernel default mitigations for vulnerable processors are:
|
||||
|
||||
- Enable CPU buffer clearing
|
||||
|
||||
The kernel does not by default enforce the disabling of SMT, which leaves
|
||||
SMT systems vulnerable when running untrusted code. The same rationale as
|
||||
for L1TF applies.
|
||||
See :ref:`Documentation/admin-guide/hw-vuln//l1tf.rst <default_mitigations>`.
|
||||
@@ -17,14 +17,12 @@ etc.
|
||||
kernel-parameters
|
||||
devices
|
||||
|
||||
This section describes CPU vulnerabilities and provides an overview of the
|
||||
possible mitigations along with guidance for selecting mitigations if they
|
||||
are configurable at compile, boot or run time.
|
||||
This section describes CPU vulnerabilities and their mitigations.
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
|
||||
l1tf
|
||||
hw-vuln/index
|
||||
|
||||
Here is a set of documents aimed at users who are trying to track down
|
||||
problems and bugs in particular.
|
||||
|
||||
@@ -2141,7 +2141,7 @@
|
||||
|
||||
Default is 'flush'.
|
||||
|
||||
For details see: Documentation/admin-guide/l1tf.rst
|
||||
For details see: Documentation/admin-guide/hw-vuln/l1tf.rst
|
||||
|
||||
l2cr= [PPC]
|
||||
|
||||
@@ -2387,6 +2387,32 @@
|
||||
Format: <first>,<last>
|
||||
Specifies range of consoles to be captured by the MDA.
|
||||
|
||||
mds= [X86,INTEL]
|
||||
Control mitigation for the Micro-architectural Data
|
||||
Sampling (MDS) vulnerability.
|
||||
|
||||
Certain CPUs are vulnerable to an exploit against CPU
|
||||
internal buffers which can forward information to a
|
||||
disclosure gadget under certain conditions.
|
||||
|
||||
In vulnerable processors, the speculatively
|
||||
forwarded data can be used in a cache side channel
|
||||
attack, to access data to which the attacker does
|
||||
not have direct access.
|
||||
|
||||
This parameter controls the MDS mitigation. The
|
||||
options are:
|
||||
|
||||
full - Enable MDS mitigation on vulnerable CPUs
|
||||
full,nosmt - Enable MDS mitigation and disable
|
||||
SMT on vulnerable CPUs
|
||||
off - Unconditionally disable MDS mitigation
|
||||
|
||||
Not specifying this option is equivalent to
|
||||
mds=full.
|
||||
|
||||
For details see: Documentation/admin-guide/hw-vuln/mds.rst
|
||||
|
||||
mem=nn[KMG] [KNL,BOOT] Force usage of a specific amount of memory
|
||||
Amount of memory to be used when the kernel is not able
|
||||
to see the whole system memory or for test.
|
||||
@@ -2544,6 +2570,40 @@
|
||||
in the "bleeding edge" mini2440 support kernel at
|
||||
http://repo.or.cz/w/linux-2.6/mini2440.git
|
||||
|
||||
mitigations=
|
||||
[X86,PPC,S390] Control optional mitigations for CPU
|
||||
vulnerabilities. This is a set of curated,
|
||||
arch-independent options, each of which is an
|
||||
aggregation of existing arch-specific options.
|
||||
|
||||
off
|
||||
Disable all optional CPU mitigations. This
|
||||
improves system performance, but it may also
|
||||
expose users to several CPU vulnerabilities.
|
||||
Equivalent to: nopti [X86,PPC]
|
||||
nospectre_v1 [PPC]
|
||||
nobp=0 [S390]
|
||||
nospectre_v2 [X86,PPC,S390]
|
||||
spectre_v2_user=off [X86]
|
||||
spec_store_bypass_disable=off [X86,PPC]
|
||||
l1tf=off [X86]
|
||||
mds=off [X86]
|
||||
|
||||
auto (default)
|
||||
Mitigate all CPU vulnerabilities, but leave SMT
|
||||
enabled, even if it's vulnerable. This is for
|
||||
users who don't want to be surprised by SMT
|
||||
getting disabled across kernel upgrades, or who
|
||||
have other ways of avoiding SMT-based attacks.
|
||||
Equivalent to: (default behavior)
|
||||
|
||||
auto,nosmt
|
||||
Mitigate all CPU vulnerabilities, disabling SMT
|
||||
if needed. This is for users who always want to
|
||||
be fully mitigated, even if it means losing SMT.
|
||||
Equivalent to: l1tf=flush,nosmt [X86]
|
||||
mds=full,nosmt [X86]
|
||||
|
||||
mminit_loglevel=
|
||||
[KNL] When CONFIG_DEBUG_MEMORY_INIT is set, this
|
||||
parameter allows control of the logging verbosity for
|
||||
|
||||
@@ -102,6 +102,7 @@ implementation.
|
||||
:maxdepth: 2
|
||||
|
||||
sh/index
|
||||
x86/index
|
||||
|
||||
Filesystem Documentation
|
||||
------------------------
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
# -*- coding: utf-8; mode: python -*-
|
||||
|
||||
project = "X86 architecture specific documentation"
|
||||
|
||||
tags.add("subproject")
|
||||
|
||||
latex_documents = [
|
||||
('index', 'x86.tex', project,
|
||||
'The kernel development community', 'manual'),
|
||||
]
|
||||
@@ -0,0 +1,8 @@
|
||||
==========================
|
||||
x86 architecture specifics
|
||||
==========================
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
|
||||
mds
|
||||
@@ -0,0 +1,225 @@
|
||||
Microarchitectural Data Sampling (MDS) mitigation
|
||||
=================================================
|
||||
|
||||
.. _mds:
|
||||
|
||||
Overview
|
||||
--------
|
||||
|
||||
Microarchitectural Data Sampling (MDS) is a family of side channel attacks
|
||||
on internal buffers in Intel CPUs. The variants are:
|
||||
|
||||
- Microarchitectural Store Buffer Data Sampling (MSBDS) (CVE-2018-12126)
|
||||
- Microarchitectural Fill Buffer Data Sampling (MFBDS) (CVE-2018-12130)
|
||||
- Microarchitectural Load Port Data Sampling (MLPDS) (CVE-2018-12127)
|
||||
- Microarchitectural Data Sampling Uncacheable Memory (MDSUM) (CVE-2019-11091)
|
||||
|
||||
MSBDS leaks Store Buffer Entries which can be speculatively forwarded to a
|
||||
dependent load (store-to-load forwarding) as an optimization. The forward
|
||||
can also happen to a faulting or assisting load operation for a different
|
||||
memory address, which can be exploited under certain conditions. Store
|
||||
buffers are partitioned between Hyper-Threads so cross thread forwarding is
|
||||
not possible. But if a thread enters or exits a sleep state the store
|
||||
buffer is repartitioned which can expose data from one thread to the other.
|
||||
|
||||
MFBDS leaks Fill Buffer Entries. Fill buffers are used internally to manage
|
||||
L1 miss situations and to hold data which is returned or sent in response
|
||||
to a memory or I/O operation. Fill buffers can forward data to a load
|
||||
operation and also write data to the cache. When the fill buffer is
|
||||
deallocated it can retain the stale data of the preceding operations which
|
||||
can then be forwarded to a faulting or assisting load operation, which can
|
||||
be exploited under certain conditions. Fill buffers are shared between
|
||||
Hyper-Threads so cross thread leakage is possible.
|
||||
|
||||
MLPDS leaks Load Port Data. Load ports are used to perform load operations
|
||||
from memory or I/O. The received data is then forwarded to the register
|
||||
file or a subsequent operation. In some implementations the Load Port can
|
||||
contain stale data from a previous operation which can be forwarded to
|
||||
faulting or assisting loads under certain conditions, which again can be
|
||||
exploited eventually. Load ports are shared between Hyper-Threads so cross
|
||||
thread leakage is possible.
|
||||
|
||||
MDSUM is a special case of MSBDS, MFBDS and MLPDS. An uncacheable load from
|
||||
memory that takes a fault or assist can leave data in a microarchitectural
|
||||
structure that may later be observed using one of the same methods used by
|
||||
MSBDS, MFBDS or MLPDS.
|
||||
|
||||
Exposure assumptions
|
||||
--------------------
|
||||
|
||||
It is assumed that attack code resides in user space or in a guest with one
|
||||
exception. The rationale behind this assumption is that the code construct
|
||||
needed for exploiting MDS requires:
|
||||
|
||||
- to control the load to trigger a fault or assist
|
||||
|
||||
- to have a disclosure gadget which exposes the speculatively accessed
|
||||
data for consumption through a side channel.
|
||||
|
||||
- to control the pointer through which the disclosure gadget exposes the
|
||||
data
|
||||
|
||||
The existence of such a construct in the kernel cannot be excluded with
|
||||
100% certainty, but the complexity involved makes it extremly unlikely.
|
||||
|
||||
There is one exception, which is untrusted BPF. The functionality of
|
||||
untrusted BPF is limited, but it needs to be thoroughly investigated
|
||||
whether it can be used to create such a construct.
|
||||
|
||||
|
||||
Mitigation strategy
|
||||
-------------------
|
||||
|
||||
All variants have the same mitigation strategy at least for the single CPU
|
||||
thread case (SMT off): Force the CPU to clear the affected buffers.
|
||||
|
||||
This is achieved by using the otherwise unused and obsolete VERW
|
||||
instruction in combination with a microcode update. The microcode clears
|
||||
the affected CPU buffers when the VERW instruction is executed.
|
||||
|
||||
For virtualization there are two ways to achieve CPU buffer
|
||||
clearing. Either the modified VERW instruction or via the L1D Flush
|
||||
command. The latter is issued when L1TF mitigation is enabled so the extra
|
||||
VERW can be avoided. If the CPU is not affected by L1TF then VERW needs to
|
||||
be issued.
|
||||
|
||||
If the VERW instruction with the supplied segment selector argument is
|
||||
executed on a CPU without the microcode update there is no side effect
|
||||
other than a small number of pointlessly wasted CPU cycles.
|
||||
|
||||
This does not protect against cross Hyper-Thread attacks except for MSBDS
|
||||
which is only exploitable cross Hyper-thread when one of the Hyper-Threads
|
||||
enters a C-state.
|
||||
|
||||
The kernel provides a function to invoke the buffer clearing:
|
||||
|
||||
mds_clear_cpu_buffers()
|
||||
|
||||
The mitigation is invoked on kernel/userspace, hypervisor/guest and C-state
|
||||
(idle) transitions.
|
||||
|
||||
As a special quirk to address virtualization scenarios where the host has
|
||||
the microcode updated, but the hypervisor does not (yet) expose the
|
||||
MD_CLEAR CPUID bit to guests, the kernel issues the VERW instruction in the
|
||||
hope that it might actually clear the buffers. The state is reflected
|
||||
accordingly.
|
||||
|
||||
According to current knowledge additional mitigations inside the kernel
|
||||
itself are not required because the necessary gadgets to expose the leaked
|
||||
data cannot be controlled in a way which allows exploitation from malicious
|
||||
user space or VM guests.
|
||||
|
||||
Kernel internal mitigation modes
|
||||
--------------------------------
|
||||
|
||||
======= ============================================================
|
||||
off Mitigation is disabled. Either the CPU is not affected or
|
||||
mds=off is supplied on the kernel command line
|
||||
|
||||
full Mitigation is enabled. CPU is affected and MD_CLEAR is
|
||||
advertised in CPUID.
|
||||
|
||||
vmwerv Mitigation is enabled. CPU is affected and MD_CLEAR is not
|
||||
advertised in CPUID. That is mainly for virtualization
|
||||
scenarios where the host has the updated microcode but the
|
||||
hypervisor does not expose MD_CLEAR in CPUID. It's a best
|
||||
effort approach without guarantee.
|
||||
======= ============================================================
|
||||
|
||||
If the CPU is affected and mds=off is not supplied on the kernel command
|
||||
line then the kernel selects the appropriate mitigation mode depending on
|
||||
the availability of the MD_CLEAR CPUID bit.
|
||||
|
||||
Mitigation points
|
||||
-----------------
|
||||
|
||||
1. Return to user space
|
||||
^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
When transitioning from kernel to user space the CPU buffers are flushed
|
||||
on affected CPUs when the mitigation is not disabled on the kernel
|
||||
command line. The migitation is enabled through the static key
|
||||
mds_user_clear.
|
||||
|
||||
The mitigation is invoked in prepare_exit_to_usermode() which covers
|
||||
most of the kernel to user space transitions. There are a few exceptions
|
||||
which are not invoking prepare_exit_to_usermode() on return to user
|
||||
space. These exceptions use the paranoid exit code.
|
||||
|
||||
- Non Maskable Interrupt (NMI):
|
||||
|
||||
Access to sensible data like keys, credentials in the NMI context is
|
||||
mostly theoretical: The CPU can do prefetching or execute a
|
||||
misspeculated code path and thereby fetching data which might end up
|
||||
leaking through a buffer.
|
||||
|
||||
But for mounting other attacks the kernel stack address of the task is
|
||||
already valuable information. So in full mitigation mode, the NMI is
|
||||
mitigated on the return from do_nmi() to provide almost complete
|
||||
coverage.
|
||||
|
||||
- Double fault (#DF):
|
||||
|
||||
A double fault is usually fatal, but the ESPFIX workaround, which can
|
||||
be triggered from user space through modify_ldt(2) is a recoverable
|
||||
double fault. #DF uses the paranoid exit path, so explicit mitigation
|
||||
in the double fault handler is required.
|
||||
|
||||
- Machine Check Exception (#MC):
|
||||
|
||||
Another corner case is a #MC which hits between the CPU buffer clear
|
||||
invocation and the actual return to user. As this still is in kernel
|
||||
space it takes the paranoid exit path which does not clear the CPU
|
||||
buffers. So the #MC handler repopulates the buffers to some
|
||||
extent. Machine checks are not reliably controllable and the window is
|
||||
extremly small so mitigation would just tick a checkbox that this
|
||||
theoretical corner case is covered. To keep the amount of special
|
||||
cases small, ignore #MC.
|
||||
|
||||
- Debug Exception (#DB):
|
||||
|
||||
This takes the paranoid exit path only when the INT1 breakpoint is in
|
||||
kernel space. #DB on a user space address takes the regular exit path,
|
||||
so no extra mitigation required.
|
||||
|
||||
|
||||
2. C-State transition
|
||||
^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
When a CPU goes idle and enters a C-State the CPU buffers need to be
|
||||
cleared on affected CPUs when SMT is active. This addresses the
|
||||
repartitioning of the store buffer when one of the Hyper-Threads enters
|
||||
a C-State.
|
||||
|
||||
When SMT is inactive, i.e. either the CPU does not support it or all
|
||||
sibling threads are offline CPU buffer clearing is not required.
|
||||
|
||||
The idle clearing is enabled on CPUs which are only affected by MSBDS
|
||||
and not by any other MDS variant. The other MDS variants cannot be
|
||||
protected against cross Hyper-Thread attacks because the Fill Buffer and
|
||||
the Load Ports are shared. So on CPUs affected by other variants, the
|
||||
idle clearing would be a window dressing exercise and is therefore not
|
||||
activated.
|
||||
|
||||
The invocation is controlled by the static key mds_idle_clear which is
|
||||
switched depending on the chosen mitigation mode and the SMT state of
|
||||
the system.
|
||||
|
||||
The buffer clear is only invoked before entering the C-State to prevent
|
||||
that stale data from the idling CPU from spilling to the Hyper-Thread
|
||||
sibling after the store buffer got repartitioned and all entries are
|
||||
available to the non idle sibling.
|
||||
|
||||
When coming out of idle the store buffer is partitioned again so each
|
||||
sibling has half of it available. The back from idle CPU could be then
|
||||
speculatively exposed to contents of the sibling. The buffers are
|
||||
flushed either on exit to user space or on VMENTER so malicious code
|
||||
in user space or the guest cannot speculatively access them.
|
||||
|
||||
The mitigation is hooked into all variants of halt()/mwait(), but does
|
||||
not cover the legacy ACPI IO-Port mechanism because the ACPI idle driver
|
||||
has been superseded by the intel_idle driver around 2010 and is
|
||||
preferred on all affected CPUs which are expected to gain the MD_CLEAR
|
||||
functionality in microcode. Aside of that the IO-Port mechanism is a
|
||||
legacy interface which is only used on older systems which are either
|
||||
not affected or do not receive microcode updates anymore.
|
||||
@@ -1,7 +1,7 @@
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
VERSION = 5
|
||||
PATCHLEVEL = 1
|
||||
SUBLEVEL = 0
|
||||
SUBLEVEL = 3
|
||||
EXTRAVERSION =
|
||||
NAME = Shy Crocodile
|
||||
|
||||
|
||||
@@ -23,26 +23,34 @@
|
||||
|
||||
#include <asm/errno.h>
|
||||
|
||||
#define FUTEX_MAX_LOOPS 128 /* What's the largest number you can think of? */
|
||||
|
||||
#define __futex_atomic_op(insn, ret, oldval, uaddr, tmp, oparg) \
|
||||
do { \
|
||||
unsigned int loops = FUTEX_MAX_LOOPS; \
|
||||
\
|
||||
uaccess_enable(); \
|
||||
asm volatile( \
|
||||
" prfm pstl1strm, %2\n" \
|
||||
"1: ldxr %w1, %2\n" \
|
||||
insn "\n" \
|
||||
"2: stlxr %w0, %w3, %2\n" \
|
||||
" cbnz %w0, 1b\n" \
|
||||
" dmb ish\n" \
|
||||
" cbz %w0, 3f\n" \
|
||||
" sub %w4, %w4, %w0\n" \
|
||||
" cbnz %w4, 1b\n" \
|
||||
" mov %w0, %w7\n" \
|
||||
"3:\n" \
|
||||
" dmb ish\n" \
|
||||
" .pushsection .fixup,\"ax\"\n" \
|
||||
" .align 2\n" \
|
||||
"4: mov %w0, %w5\n" \
|
||||
"4: mov %w0, %w6\n" \
|
||||
" b 3b\n" \
|
||||
" .popsection\n" \
|
||||
_ASM_EXTABLE(1b, 4b) \
|
||||
_ASM_EXTABLE(2b, 4b) \
|
||||
: "=&r" (ret), "=&r" (oldval), "+Q" (*uaddr), "=&r" (tmp) \
|
||||
: "r" (oparg), "Ir" (-EFAULT) \
|
||||
: "=&r" (ret), "=&r" (oldval), "+Q" (*uaddr), "=&r" (tmp), \
|
||||
"+r" (loops) \
|
||||
: "r" (oparg), "Ir" (-EFAULT), "Ir" (-EAGAIN) \
|
||||
: "memory"); \
|
||||
uaccess_disable(); \
|
||||
} while (0)
|
||||
@@ -57,23 +65,23 @@ arch_futex_atomic_op_inuser(int op, int oparg, int *oval, u32 __user *_uaddr)
|
||||
|
||||
switch (op) {
|
||||
case FUTEX_OP_SET:
|
||||
__futex_atomic_op("mov %w3, %w4",
|
||||
__futex_atomic_op("mov %w3, %w5",
|
||||
ret, oldval, uaddr, tmp, oparg);
|
||||
break;
|
||||
case FUTEX_OP_ADD:
|
||||
__futex_atomic_op("add %w3, %w1, %w4",
|
||||
__futex_atomic_op("add %w3, %w1, %w5",
|
||||
ret, oldval, uaddr, tmp, oparg);
|
||||
break;
|
||||
case FUTEX_OP_OR:
|
||||
__futex_atomic_op("orr %w3, %w1, %w4",
|
||||
__futex_atomic_op("orr %w3, %w1, %w5",
|
||||
ret, oldval, uaddr, tmp, oparg);
|
||||
break;
|
||||
case FUTEX_OP_ANDN:
|
||||
__futex_atomic_op("and %w3, %w1, %w4",
|
||||
__futex_atomic_op("and %w3, %w1, %w5",
|
||||
ret, oldval, uaddr, tmp, ~oparg);
|
||||
break;
|
||||
case FUTEX_OP_XOR:
|
||||
__futex_atomic_op("eor %w3, %w1, %w4",
|
||||
__futex_atomic_op("eor %w3, %w1, %w5",
|
||||
ret, oldval, uaddr, tmp, oparg);
|
||||
break;
|
||||
default:
|
||||
@@ -93,6 +101,7 @@ futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *_uaddr,
|
||||
u32 oldval, u32 newval)
|
||||
{
|
||||
int ret = 0;
|
||||
unsigned int loops = FUTEX_MAX_LOOPS;
|
||||
u32 val, tmp;
|
||||
u32 __user *uaddr;
|
||||
|
||||
@@ -104,20 +113,24 @@ futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *_uaddr,
|
||||
asm volatile("// futex_atomic_cmpxchg_inatomic\n"
|
||||
" prfm pstl1strm, %2\n"
|
||||
"1: ldxr %w1, %2\n"
|
||||
" sub %w3, %w1, %w4\n"
|
||||
" cbnz %w3, 3f\n"
|
||||
"2: stlxr %w3, %w5, %2\n"
|
||||
" cbnz %w3, 1b\n"
|
||||
" dmb ish\n"
|
||||
" sub %w3, %w1, %w5\n"
|
||||
" cbnz %w3, 4f\n"
|
||||
"2: stlxr %w3, %w6, %2\n"
|
||||
" cbz %w3, 3f\n"
|
||||
" sub %w4, %w4, %w3\n"
|
||||
" cbnz %w4, 1b\n"
|
||||
" mov %w0, %w8\n"
|
||||
"3:\n"
|
||||
" dmb ish\n"
|
||||
"4:\n"
|
||||
" .pushsection .fixup,\"ax\"\n"
|
||||
"4: mov %w0, %w6\n"
|
||||
" b 3b\n"
|
||||
"5: mov %w0, %w7\n"
|
||||
" b 4b\n"
|
||||
" .popsection\n"
|
||||
_ASM_EXTABLE(1b, 4b)
|
||||
_ASM_EXTABLE(2b, 4b)
|
||||
: "+r" (ret), "=&r" (val), "+Q" (*uaddr), "=&r" (tmp)
|
||||
: "r" (oldval), "r" (newval), "Ir" (-EFAULT)
|
||||
_ASM_EXTABLE(1b, 5b)
|
||||
_ASM_EXTABLE(2b, 5b)
|
||||
: "+r" (ret), "=&r" (val), "+Q" (*uaddr), "=&r" (tmp), "+r" (loops)
|
||||
: "r" (oldval), "r" (newval), "Ir" (-EFAULT), "Ir" (-EAGAIN)
|
||||
: "memory");
|
||||
uaccess_disable();
|
||||
|
||||
|
||||
@@ -81,6 +81,9 @@ static inline pgd_t *pgd_alloc(struct mm_struct *mm)
|
||||
|
||||
pgd = kmem_cache_alloc(PGT_CACHE(PGD_INDEX_SIZE),
|
||||
pgtable_gfp_flags(mm, GFP_KERNEL));
|
||||
if (unlikely(!pgd))
|
||||
return pgd;
|
||||
|
||||
/*
|
||||
* Don't scan the PGD for pointers, it contains references to PUDs but
|
||||
* those references are not full pointers and so can't be recognised by
|
||||
|
||||
@@ -41,7 +41,7 @@
|
||||
#if defined(CONFIG_PPC_BOOK3E_64)
|
||||
#define MSR_64BIT MSR_CM
|
||||
|
||||
#define MSR_ (MSR_ME | MSR_CE)
|
||||
#define MSR_ (MSR_ME | MSR_RI | MSR_CE)
|
||||
#define MSR_KERNEL (MSR_ | MSR_64BIT)
|
||||
#define MSR_USER32 (MSR_ | MSR_PR | MSR_EE)
|
||||
#define MSR_USER64 (MSR_USER32 | MSR_64BIT)
|
||||
|
||||
@@ -170,6 +170,9 @@ core_idle_lock_held:
|
||||
bne- core_idle_lock_held
|
||||
blr
|
||||
|
||||
/* Reuse an unused pt_regs slot for IAMR */
|
||||
#define PNV_POWERSAVE_IAMR _DAR
|
||||
|
||||
/*
|
||||
* Pass requested state in r3:
|
||||
* r3 - PNV_THREAD_NAP/SLEEP/WINKLE in POWER8
|
||||
@@ -200,6 +203,12 @@ pnv_powersave_common:
|
||||
/* Continue saving state */
|
||||
SAVE_GPR(2, r1)
|
||||
SAVE_NVGPRS(r1)
|
||||
|
||||
BEGIN_FTR_SECTION
|
||||
mfspr r5, SPRN_IAMR
|
||||
std r5, PNV_POWERSAVE_IAMR(r1)
|
||||
END_FTR_SECTION_IFSET(CPU_FTR_ARCH_207S)
|
||||
|
||||
mfcr r5
|
||||
std r5,_CCR(r1)
|
||||
std r1,PACAR1(r13)
|
||||
@@ -924,6 +933,17 @@ BEGIN_FTR_SECTION
|
||||
END_FTR_SECTION_IFSET(CPU_FTR_HVMODE)
|
||||
REST_NVGPRS(r1)
|
||||
REST_GPR(2, r1)
|
||||
|
||||
BEGIN_FTR_SECTION
|
||||
/* IAMR was saved in pnv_powersave_common() */
|
||||
ld r5, PNV_POWERSAVE_IAMR(r1)
|
||||
mtspr SPRN_IAMR, r5
|
||||
/*
|
||||
* We don't need an isync here because the upcoming mtmsrd is
|
||||
* execution synchronizing.
|
||||
*/
|
||||
END_FTR_SECTION_IFSET(CPU_FTR_ARCH_207S)
|
||||
|
||||
ld r4,PACAKMSR(r13)
|
||||
ld r5,_LINK(r1)
|
||||
ld r6,_CCR(r1)
|
||||
|
||||
@@ -57,7 +57,7 @@ void setup_barrier_nospec(void)
|
||||
enable = security_ftr_enabled(SEC_FTR_FAVOUR_SECURITY) &&
|
||||
security_ftr_enabled(SEC_FTR_BNDS_CHK_SPEC_BAR);
|
||||
|
||||
if (!no_nospec)
|
||||
if (!no_nospec && !cpu_mitigations_off())
|
||||
enable_barrier_nospec(enable);
|
||||
}
|
||||
|
||||
@@ -116,7 +116,7 @@ static int __init handle_nospectre_v2(char *p)
|
||||
early_param("nospectre_v2", handle_nospectre_v2);
|
||||
void setup_spectre_v2(void)
|
||||
{
|
||||
if (no_spectrev2)
|
||||
if (no_spectrev2 || cpu_mitigations_off())
|
||||
do_btb_flush_fixups();
|
||||
else
|
||||
btb_flush_enabled = true;
|
||||
@@ -300,7 +300,7 @@ void setup_stf_barrier(void)
|
||||
|
||||
stf_enabled_flush_types = type;
|
||||
|
||||
if (!no_stf_barrier)
|
||||
if (!no_stf_barrier && !cpu_mitigations_off())
|
||||
stf_barrier_enable(enable);
|
||||
}
|
||||
|
||||
|
||||
@@ -932,7 +932,7 @@ void setup_rfi_flush(enum l1d_flush_type types, bool enable)
|
||||
|
||||
enabled_flush_types = types;
|
||||
|
||||
if (!no_rfi_flush)
|
||||
if (!no_rfi_flush && !cpu_mitigations_off())
|
||||
rfi_flush_enable(enable);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
#include <linux/module.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/cpu.h>
|
||||
#include <asm/nospec-branch.h>
|
||||
|
||||
static int __init nobp_setup_early(char *str)
|
||||
@@ -58,7 +59,7 @@ early_param("nospectre_v2", nospectre_v2_setup_early);
|
||||
|
||||
void __init nospec_auto_detect(void)
|
||||
{
|
||||
if (test_facility(156)) {
|
||||
if (test_facility(156) || cpu_mitigations_off()) {
|
||||
/*
|
||||
* The machine supports etokens.
|
||||
* Disable expolines and disable nobp.
|
||||
|
||||
@@ -31,6 +31,7 @@
|
||||
#include <asm/vdso.h>
|
||||
#include <linux/uaccess.h>
|
||||
#include <asm/cpufeature.h>
|
||||
#include <asm/nospec-branch.h>
|
||||
|
||||
#define CREATE_TRACE_POINTS
|
||||
#include <trace/events/syscalls.h>
|
||||
@@ -212,6 +213,8 @@ __visible inline void prepare_exit_to_usermode(struct pt_regs *regs)
|
||||
#endif
|
||||
|
||||
user_enter_irqoff();
|
||||
|
||||
mds_user_clear_cpu_buffers();
|
||||
}
|
||||
|
||||
#define SYSCALL_EXIT_WORK_FLAGS \
|
||||
|
||||
@@ -344,6 +344,7 @@
|
||||
/* Intel-defined CPU features, CPUID level 0x00000007:0 (EDX), word 18 */
|
||||
#define X86_FEATURE_AVX512_4VNNIW (18*32+ 2) /* AVX-512 Neural Network Instructions */
|
||||
#define X86_FEATURE_AVX512_4FMAPS (18*32+ 3) /* AVX-512 Multiply Accumulation Single precision */
|
||||
#define X86_FEATURE_MD_CLEAR (18*32+10) /* VERW clears CPU buffers */
|
||||
#define X86_FEATURE_TSX_FORCE_ABORT (18*32+13) /* "" TSX_FORCE_ABORT */
|
||||
#define X86_FEATURE_PCONFIG (18*32+18) /* Intel PCONFIG */
|
||||
#define X86_FEATURE_SPEC_CTRL (18*32+26) /* "" Speculation Control (IBRS + IBPB) */
|
||||
@@ -382,5 +383,7 @@
|
||||
#define X86_BUG_SPECTRE_V2 X86_BUG(16) /* CPU is affected by Spectre variant 2 attack with indirect branches */
|
||||
#define X86_BUG_SPEC_STORE_BYPASS X86_BUG(17) /* CPU is affected by speculative store bypass attack */
|
||||
#define X86_BUG_L1TF X86_BUG(18) /* CPU is affected by L1 Terminal Fault */
|
||||
#define X86_BUG_MDS X86_BUG(19) /* CPU is affected by Microarchitectural data sampling */
|
||||
#define X86_BUG_MSBDS_ONLY X86_BUG(20) /* CPU is only affected by the MSDBS variant of BUG_MDS */
|
||||
|
||||
#endif /* _ASM_X86_CPUFEATURES_H */
|
||||
|
||||
@@ -6,6 +6,8 @@
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
|
||||
#include <asm/nospec-branch.h>
|
||||
|
||||
/* Provide __cpuidle; we can't safely include <linux/cpu.h> */
|
||||
#define __cpuidle __attribute__((__section__(".cpuidle.text")))
|
||||
|
||||
@@ -54,11 +56,13 @@ static inline void native_irq_enable(void)
|
||||
|
||||
static inline __cpuidle void native_safe_halt(void)
|
||||
{
|
||||
mds_idle_clear_cpu_buffers();
|
||||
asm volatile("sti; hlt": : :"memory");
|
||||
}
|
||||
|
||||
static inline __cpuidle void native_halt(void)
|
||||
{
|
||||
mds_idle_clear_cpu_buffers();
|
||||
asm volatile("hlt": : :"memory");
|
||||
}
|
||||
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
#ifndef _ASM_X86_MSR_INDEX_H
|
||||
#define _ASM_X86_MSR_INDEX_H
|
||||
|
||||
#include <linux/bits.h>
|
||||
|
||||
/*
|
||||
* CPU model specific register (MSR) numbers.
|
||||
*
|
||||
@@ -40,14 +42,14 @@
|
||||
/* Intel MSRs. Some also available on other CPUs */
|
||||
|
||||
#define MSR_IA32_SPEC_CTRL 0x00000048 /* Speculation Control */
|
||||
#define SPEC_CTRL_IBRS (1 << 0) /* Indirect Branch Restricted Speculation */
|
||||
#define SPEC_CTRL_IBRS BIT(0) /* Indirect Branch Restricted Speculation */
|
||||
#define SPEC_CTRL_STIBP_SHIFT 1 /* Single Thread Indirect Branch Predictor (STIBP) bit */
|
||||
#define SPEC_CTRL_STIBP (1 << SPEC_CTRL_STIBP_SHIFT) /* STIBP mask */
|
||||
#define SPEC_CTRL_STIBP BIT(SPEC_CTRL_STIBP_SHIFT) /* STIBP mask */
|
||||
#define SPEC_CTRL_SSBD_SHIFT 2 /* Speculative Store Bypass Disable bit */
|
||||
#define SPEC_CTRL_SSBD (1 << SPEC_CTRL_SSBD_SHIFT) /* Speculative Store Bypass Disable */
|
||||
#define SPEC_CTRL_SSBD BIT(SPEC_CTRL_SSBD_SHIFT) /* Speculative Store Bypass Disable */
|
||||
|
||||
#define MSR_IA32_PRED_CMD 0x00000049 /* Prediction Command */
|
||||
#define PRED_CMD_IBPB (1 << 0) /* Indirect Branch Prediction Barrier */
|
||||
#define PRED_CMD_IBPB BIT(0) /* Indirect Branch Prediction Barrier */
|
||||
|
||||
#define MSR_PPIN_CTL 0x0000004e
|
||||
#define MSR_PPIN 0x0000004f
|
||||
@@ -69,20 +71,25 @@
|
||||
#define MSR_MTRRcap 0x000000fe
|
||||
|
||||
#define MSR_IA32_ARCH_CAPABILITIES 0x0000010a
|
||||
#define ARCH_CAP_RDCL_NO (1 << 0) /* Not susceptible to Meltdown */
|
||||
#define ARCH_CAP_IBRS_ALL (1 << 1) /* Enhanced IBRS support */
|
||||
#define ARCH_CAP_SKIP_VMENTRY_L1DFLUSH (1 << 3) /* Skip L1D flush on vmentry */
|
||||
#define ARCH_CAP_SSB_NO (1 << 4) /*
|
||||
* Not susceptible to Speculative Store Bypass
|
||||
* attack, so no Speculative Store Bypass
|
||||
* control required.
|
||||
*/
|
||||
#define ARCH_CAP_RDCL_NO BIT(0) /* Not susceptible to Meltdown */
|
||||
#define ARCH_CAP_IBRS_ALL BIT(1) /* Enhanced IBRS support */
|
||||
#define ARCH_CAP_SKIP_VMENTRY_L1DFLUSH BIT(3) /* Skip L1D flush on vmentry */
|
||||
#define ARCH_CAP_SSB_NO BIT(4) /*
|
||||
* Not susceptible to Speculative Store Bypass
|
||||
* attack, so no Speculative Store Bypass
|
||||
* control required.
|
||||
*/
|
||||
#define ARCH_CAP_MDS_NO BIT(5) /*
|
||||
* Not susceptible to
|
||||
* Microarchitectural Data
|
||||
* Sampling (MDS) vulnerabilities.
|
||||
*/
|
||||
|
||||
#define MSR_IA32_FLUSH_CMD 0x0000010b
|
||||
#define L1D_FLUSH (1 << 0) /*
|
||||
* Writeback and invalidate the
|
||||
* L1 data cache.
|
||||
*/
|
||||
#define L1D_FLUSH BIT(0) /*
|
||||
* Writeback and invalidate the
|
||||
* L1 data cache.
|
||||
*/
|
||||
|
||||
#define MSR_IA32_BBL_CR_CTL 0x00000119
|
||||
#define MSR_IA32_BBL_CR_CTL3 0x0000011e
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
#include <linux/sched/idle.h>
|
||||
|
||||
#include <asm/cpufeature.h>
|
||||
#include <asm/nospec-branch.h>
|
||||
|
||||
#define MWAIT_SUBSTATE_MASK 0xf
|
||||
#define MWAIT_CSTATE_MASK 0xf
|
||||
@@ -40,6 +41,8 @@ static inline void __monitorx(const void *eax, unsigned long ecx,
|
||||
|
||||
static inline void __mwait(unsigned long eax, unsigned long ecx)
|
||||
{
|
||||
mds_idle_clear_cpu_buffers();
|
||||
|
||||
/* "mwait %eax, %ecx;" */
|
||||
asm volatile(".byte 0x0f, 0x01, 0xc9;"
|
||||
:: "a" (eax), "c" (ecx));
|
||||
@@ -74,6 +77,8 @@ static inline void __mwait(unsigned long eax, unsigned long ecx)
|
||||
static inline void __mwaitx(unsigned long eax, unsigned long ebx,
|
||||
unsigned long ecx)
|
||||
{
|
||||
/* No MDS buffer clear as this is AMD/HYGON only */
|
||||
|
||||
/* "mwaitx %eax, %ebx, %ecx;" */
|
||||
asm volatile(".byte 0x0f, 0x01, 0xfb;"
|
||||
:: "a" (eax), "b" (ebx), "c" (ecx));
|
||||
@@ -81,6 +86,8 @@ static inline void __mwaitx(unsigned long eax, unsigned long ebx,
|
||||
|
||||
static inline void __sti_mwait(unsigned long eax, unsigned long ecx)
|
||||
{
|
||||
mds_idle_clear_cpu_buffers();
|
||||
|
||||
trace_hardirqs_on();
|
||||
/* "mwait %eax, %ecx;" */
|
||||
asm volatile("sti; .byte 0x0f, 0x01, 0xc9;"
|
||||
|
||||
@@ -318,6 +318,56 @@ DECLARE_STATIC_KEY_FALSE(switch_to_cond_stibp);
|
||||
DECLARE_STATIC_KEY_FALSE(switch_mm_cond_ibpb);
|
||||
DECLARE_STATIC_KEY_FALSE(switch_mm_always_ibpb);
|
||||
|
||||
DECLARE_STATIC_KEY_FALSE(mds_user_clear);
|
||||
DECLARE_STATIC_KEY_FALSE(mds_idle_clear);
|
||||
|
||||
#include <asm/segment.h>
|
||||
|
||||
/**
|
||||
* mds_clear_cpu_buffers - Mitigation for MDS vulnerability
|
||||
*
|
||||
* This uses the otherwise unused and obsolete VERW instruction in
|
||||
* combination with microcode which triggers a CPU buffer flush when the
|
||||
* instruction is executed.
|
||||
*/
|
||||
static inline void mds_clear_cpu_buffers(void)
|
||||
{
|
||||
static const u16 ds = __KERNEL_DS;
|
||||
|
||||
/*
|
||||
* Has to be the memory-operand variant because only that
|
||||
* guarantees the CPU buffer flush functionality according to
|
||||
* documentation. The register-operand variant does not.
|
||||
* Works with any segment selector, but a valid writable
|
||||
* data segment is the fastest variant.
|
||||
*
|
||||
* "cc" clobber is required because VERW modifies ZF.
|
||||
*/
|
||||
asm volatile("verw %[ds]" : : [ds] "m" (ds) : "cc");
|
||||
}
|
||||
|
||||
/**
|
||||
* mds_user_clear_cpu_buffers - Mitigation for MDS vulnerability
|
||||
*
|
||||
* Clear CPU buffers if the corresponding static key is enabled
|
||||
*/
|
||||
static inline void mds_user_clear_cpu_buffers(void)
|
||||
{
|
||||
if (static_branch_likely(&mds_user_clear))
|
||||
mds_clear_cpu_buffers();
|
||||
}
|
||||
|
||||
/**
|
||||
* mds_idle_clear_cpu_buffers - Mitigation for MDS vulnerability
|
||||
*
|
||||
* Clear CPU buffers if the corresponding static key is enabled
|
||||
*/
|
||||
static inline void mds_idle_clear_cpu_buffers(void)
|
||||
{
|
||||
if (static_branch_likely(&mds_idle_clear))
|
||||
mds_clear_cpu_buffers();
|
||||
}
|
||||
|
||||
#endif /* __ASSEMBLY__ */
|
||||
|
||||
/*
|
||||
|
||||
@@ -991,4 +991,10 @@ enum l1tf_mitigations {
|
||||
|
||||
extern enum l1tf_mitigations l1tf_mitigation;
|
||||
|
||||
enum mds_mitigations {
|
||||
MDS_MITIGATION_OFF,
|
||||
MDS_MITIGATION_FULL,
|
||||
MDS_MITIGATION_VMWERV,
|
||||
};
|
||||
|
||||
#endif /* _ASM_X86_PROCESSOR_H */
|
||||
|
||||
+140
-6
@@ -37,6 +37,7 @@
|
||||
static void __init spectre_v2_select_mitigation(void);
|
||||
static void __init ssb_select_mitigation(void);
|
||||
static void __init l1tf_select_mitigation(void);
|
||||
static void __init mds_select_mitigation(void);
|
||||
|
||||
/* The base value of the SPEC_CTRL MSR that always has to be preserved. */
|
||||
u64 x86_spec_ctrl_base;
|
||||
@@ -63,6 +64,13 @@ DEFINE_STATIC_KEY_FALSE(switch_mm_cond_ibpb);
|
||||
/* Control unconditional IBPB in switch_mm() */
|
||||
DEFINE_STATIC_KEY_FALSE(switch_mm_always_ibpb);
|
||||
|
||||
/* Control MDS CPU buffer clear before returning to user space */
|
||||
DEFINE_STATIC_KEY_FALSE(mds_user_clear);
|
||||
EXPORT_SYMBOL_GPL(mds_user_clear);
|
||||
/* Control MDS CPU buffer clear before idling (halt, mwait) */
|
||||
DEFINE_STATIC_KEY_FALSE(mds_idle_clear);
|
||||
EXPORT_SYMBOL_GPL(mds_idle_clear);
|
||||
|
||||
void __init check_bugs(void)
|
||||
{
|
||||
identify_boot_cpu();
|
||||
@@ -101,6 +109,10 @@ void __init check_bugs(void)
|
||||
|
||||
l1tf_select_mitigation();
|
||||
|
||||
mds_select_mitigation();
|
||||
|
||||
arch_smt_update();
|
||||
|
||||
#ifdef CONFIG_X86_32
|
||||
/*
|
||||
* Check whether we are able to run this kernel safely on SMP.
|
||||
@@ -206,6 +218,61 @@ static void x86_amd_ssb_disable(void)
|
||||
wrmsrl(MSR_AMD64_LS_CFG, msrval);
|
||||
}
|
||||
|
||||
#undef pr_fmt
|
||||
#define pr_fmt(fmt) "MDS: " fmt
|
||||
|
||||
/* Default mitigation for MDS-affected CPUs */
|
||||
static enum mds_mitigations mds_mitigation __ro_after_init = MDS_MITIGATION_FULL;
|
||||
static bool mds_nosmt __ro_after_init = false;
|
||||
|
||||
static const char * const mds_strings[] = {
|
||||
[MDS_MITIGATION_OFF] = "Vulnerable",
|
||||
[MDS_MITIGATION_FULL] = "Mitigation: Clear CPU buffers",
|
||||
[MDS_MITIGATION_VMWERV] = "Vulnerable: Clear CPU buffers attempted, no microcode",
|
||||
};
|
||||
|
||||
static void __init mds_select_mitigation(void)
|
||||
{
|
||||
if (!boot_cpu_has_bug(X86_BUG_MDS) || cpu_mitigations_off()) {
|
||||
mds_mitigation = MDS_MITIGATION_OFF;
|
||||
return;
|
||||
}
|
||||
|
||||
if (mds_mitigation == MDS_MITIGATION_FULL) {
|
||||
if (!boot_cpu_has(X86_FEATURE_MD_CLEAR))
|
||||
mds_mitigation = MDS_MITIGATION_VMWERV;
|
||||
|
||||
static_branch_enable(&mds_user_clear);
|
||||
|
||||
if (!boot_cpu_has(X86_BUG_MSBDS_ONLY) &&
|
||||
(mds_nosmt || cpu_mitigations_auto_nosmt()))
|
||||
cpu_smt_disable(false);
|
||||
}
|
||||
|
||||
pr_info("%s\n", mds_strings[mds_mitigation]);
|
||||
}
|
||||
|
||||
static int __init mds_cmdline(char *str)
|
||||
{
|
||||
if (!boot_cpu_has_bug(X86_BUG_MDS))
|
||||
return 0;
|
||||
|
||||
if (!str)
|
||||
return -EINVAL;
|
||||
|
||||
if (!strcmp(str, "off"))
|
||||
mds_mitigation = MDS_MITIGATION_OFF;
|
||||
else if (!strcmp(str, "full"))
|
||||
mds_mitigation = MDS_MITIGATION_FULL;
|
||||
else if (!strcmp(str, "full,nosmt")) {
|
||||
mds_mitigation = MDS_MITIGATION_FULL;
|
||||
mds_nosmt = true;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
early_param("mds", mds_cmdline);
|
||||
|
||||
#undef pr_fmt
|
||||
#define pr_fmt(fmt) "Spectre V2 : " fmt
|
||||
|
||||
@@ -440,7 +507,8 @@ static enum spectre_v2_mitigation_cmd __init spectre_v2_parse_cmdline(void)
|
||||
char arg[20];
|
||||
int ret, i;
|
||||
|
||||
if (cmdline_find_option_bool(boot_command_line, "nospectre_v2"))
|
||||
if (cmdline_find_option_bool(boot_command_line, "nospectre_v2") ||
|
||||
cpu_mitigations_off())
|
||||
return SPECTRE_V2_CMD_NONE;
|
||||
|
||||
ret = cmdline_find_option(boot_command_line, "spectre_v2", arg, sizeof(arg));
|
||||
@@ -574,9 +642,6 @@ specv2_set_mode:
|
||||
|
||||
/* Set up IBPB and STIBP depending on the general spectre V2 command */
|
||||
spectre_v2_user_select_mitigation(cmd);
|
||||
|
||||
/* Enable STIBP if appropriate */
|
||||
arch_smt_update();
|
||||
}
|
||||
|
||||
static void update_stibp_msr(void * __unused)
|
||||
@@ -610,6 +675,31 @@ static void update_indir_branch_cond(void)
|
||||
static_branch_disable(&switch_to_cond_stibp);
|
||||
}
|
||||
|
||||
#undef pr_fmt
|
||||
#define pr_fmt(fmt) fmt
|
||||
|
||||
/* Update the static key controlling the MDS CPU buffer clear in idle */
|
||||
static void update_mds_branch_idle(void)
|
||||
{
|
||||
/*
|
||||
* Enable the idle clearing if SMT is active on CPUs which are
|
||||
* affected only by MSBDS and not any other MDS variant.
|
||||
*
|
||||
* The other variants cannot be mitigated when SMT is enabled, so
|
||||
* clearing the buffers on idle just to prevent the Store Buffer
|
||||
* repartitioning leak would be a window dressing exercise.
|
||||
*/
|
||||
if (!boot_cpu_has_bug(X86_BUG_MSBDS_ONLY))
|
||||
return;
|
||||
|
||||
if (sched_smt_active())
|
||||
static_branch_enable(&mds_idle_clear);
|
||||
else
|
||||
static_branch_disable(&mds_idle_clear);
|
||||
}
|
||||
|
||||
#define MDS_MSG_SMT "MDS CPU bug present and SMT on, data leak possible. See https://www.kernel.org/doc/html/latest/admin-guide/hw-vuln/mds.html for more details.\n"
|
||||
|
||||
void arch_smt_update(void)
|
||||
{
|
||||
/* Enhanced IBRS implies STIBP. No update required. */
|
||||
@@ -631,6 +721,17 @@ void arch_smt_update(void)
|
||||
break;
|
||||
}
|
||||
|
||||
switch (mds_mitigation) {
|
||||
case MDS_MITIGATION_FULL:
|
||||
case MDS_MITIGATION_VMWERV:
|
||||
if (sched_smt_active() && !boot_cpu_has(X86_BUG_MSBDS_ONLY))
|
||||
pr_warn_once(MDS_MSG_SMT);
|
||||
update_mds_branch_idle();
|
||||
break;
|
||||
case MDS_MITIGATION_OFF:
|
||||
break;
|
||||
}
|
||||
|
||||
mutex_unlock(&spec_ctrl_mutex);
|
||||
}
|
||||
|
||||
@@ -672,7 +773,8 @@ static enum ssb_mitigation_cmd __init ssb_parse_cmdline(void)
|
||||
char arg[20];
|
||||
int ret, i;
|
||||
|
||||
if (cmdline_find_option_bool(boot_command_line, "nospec_store_bypass_disable")) {
|
||||
if (cmdline_find_option_bool(boot_command_line, "nospec_store_bypass_disable") ||
|
||||
cpu_mitigations_off()) {
|
||||
return SPEC_STORE_BYPASS_CMD_NONE;
|
||||
} else {
|
||||
ret = cmdline_find_option(boot_command_line, "spec_store_bypass_disable",
|
||||
@@ -1008,6 +1110,11 @@ static void __init l1tf_select_mitigation(void)
|
||||
if (!boot_cpu_has_bug(X86_BUG_L1TF))
|
||||
return;
|
||||
|
||||
if (cpu_mitigations_off())
|
||||
l1tf_mitigation = L1TF_MITIGATION_OFF;
|
||||
else if (cpu_mitigations_auto_nosmt())
|
||||
l1tf_mitigation = L1TF_MITIGATION_FLUSH_NOSMT;
|
||||
|
||||
override_cache_bits(&boot_cpu_data);
|
||||
|
||||
switch (l1tf_mitigation) {
|
||||
@@ -1036,7 +1143,7 @@ static void __init l1tf_select_mitigation(void)
|
||||
pr_info("You may make it effective by booting the kernel with mem=%llu parameter.\n",
|
||||
half_pa);
|
||||
pr_info("However, doing so will make a part of your RAM unusable.\n");
|
||||
pr_info("Reading https://www.kernel.org/doc/html/latest/admin-guide/l1tf.html might help you decide.\n");
|
||||
pr_info("Reading https://www.kernel.org/doc/html/latest/admin-guide/hw-vuln/l1tf.html might help you decide.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1069,6 +1176,7 @@ static int __init l1tf_cmdline(char *str)
|
||||
early_param("l1tf", l1tf_cmdline);
|
||||
|
||||
#undef pr_fmt
|
||||
#define pr_fmt(fmt) fmt
|
||||
|
||||
#ifdef CONFIG_SYSFS
|
||||
|
||||
@@ -1107,6 +1215,23 @@ static ssize_t l1tf_show_state(char *buf)
|
||||
}
|
||||
#endif
|
||||
|
||||
static ssize_t mds_show_state(char *buf)
|
||||
{
|
||||
if (!hypervisor_is_type(X86_HYPER_NATIVE)) {
|
||||
return sprintf(buf, "%s; SMT Host state unknown\n",
|
||||
mds_strings[mds_mitigation]);
|
||||
}
|
||||
|
||||
if (boot_cpu_has(X86_BUG_MSBDS_ONLY)) {
|
||||
return sprintf(buf, "%s; SMT %s\n", mds_strings[mds_mitigation],
|
||||
(mds_mitigation == MDS_MITIGATION_OFF ? "vulnerable" :
|
||||
sched_smt_active() ? "mitigated" : "disabled"));
|
||||
}
|
||||
|
||||
return sprintf(buf, "%s; SMT %s\n", mds_strings[mds_mitigation],
|
||||
sched_smt_active() ? "vulnerable" : "disabled");
|
||||
}
|
||||
|
||||
static char *stibp_state(void)
|
||||
{
|
||||
if (spectre_v2_enabled == SPECTRE_V2_IBRS_ENHANCED)
|
||||
@@ -1173,6 +1298,10 @@ static ssize_t cpu_show_common(struct device *dev, struct device_attribute *attr
|
||||
if (boot_cpu_has(X86_FEATURE_L1TF_PTEINV))
|
||||
return l1tf_show_state(buf);
|
||||
break;
|
||||
|
||||
case X86_BUG_MDS:
|
||||
return mds_show_state(buf);
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -1204,4 +1333,9 @@ ssize_t cpu_show_l1tf(struct device *dev, struct device_attribute *attr, char *b
|
||||
{
|
||||
return cpu_show_common(dev, attr, buf, X86_BUG_L1TF);
|
||||
}
|
||||
|
||||
ssize_t cpu_show_mds(struct device *dev, struct device_attribute *attr, char *buf)
|
||||
{
|
||||
return cpu_show_common(dev, attr, buf, X86_BUG_MDS);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -948,61 +948,77 @@ static void identify_cpu_without_cpuid(struct cpuinfo_x86 *c)
|
||||
#endif
|
||||
}
|
||||
|
||||
static const __initconst struct x86_cpu_id cpu_no_speculation[] = {
|
||||
{ X86_VENDOR_INTEL, 6, INTEL_FAM6_ATOM_SALTWELL, X86_FEATURE_ANY },
|
||||
{ X86_VENDOR_INTEL, 6, INTEL_FAM6_ATOM_SALTWELL_TABLET, X86_FEATURE_ANY },
|
||||
{ X86_VENDOR_INTEL, 6, INTEL_FAM6_ATOM_BONNELL_MID, X86_FEATURE_ANY },
|
||||
{ X86_VENDOR_INTEL, 6, INTEL_FAM6_ATOM_SALTWELL_MID, X86_FEATURE_ANY },
|
||||
{ X86_VENDOR_INTEL, 6, INTEL_FAM6_ATOM_BONNELL, X86_FEATURE_ANY },
|
||||
{ X86_VENDOR_CENTAUR, 5 },
|
||||
{ X86_VENDOR_INTEL, 5 },
|
||||
{ X86_VENDOR_NSC, 5 },
|
||||
{ X86_VENDOR_ANY, 4 },
|
||||
#define NO_SPECULATION BIT(0)
|
||||
#define NO_MELTDOWN BIT(1)
|
||||
#define NO_SSB BIT(2)
|
||||
#define NO_L1TF BIT(3)
|
||||
#define NO_MDS BIT(4)
|
||||
#define MSBDS_ONLY BIT(5)
|
||||
|
||||
#define VULNWL(_vendor, _family, _model, _whitelist) \
|
||||
{ X86_VENDOR_##_vendor, _family, _model, X86_FEATURE_ANY, _whitelist }
|
||||
|
||||
#define VULNWL_INTEL(model, whitelist) \
|
||||
VULNWL(INTEL, 6, INTEL_FAM6_##model, whitelist)
|
||||
|
||||
#define VULNWL_AMD(family, whitelist) \
|
||||
VULNWL(AMD, family, X86_MODEL_ANY, whitelist)
|
||||
|
||||
#define VULNWL_HYGON(family, whitelist) \
|
||||
VULNWL(HYGON, family, X86_MODEL_ANY, whitelist)
|
||||
|
||||
static const __initconst struct x86_cpu_id cpu_vuln_whitelist[] = {
|
||||
VULNWL(ANY, 4, X86_MODEL_ANY, NO_SPECULATION),
|
||||
VULNWL(CENTAUR, 5, X86_MODEL_ANY, NO_SPECULATION),
|
||||
VULNWL(INTEL, 5, X86_MODEL_ANY, NO_SPECULATION),
|
||||
VULNWL(NSC, 5, X86_MODEL_ANY, NO_SPECULATION),
|
||||
|
||||
/* Intel Family 6 */
|
||||
VULNWL_INTEL(ATOM_SALTWELL, NO_SPECULATION),
|
||||
VULNWL_INTEL(ATOM_SALTWELL_TABLET, NO_SPECULATION),
|
||||
VULNWL_INTEL(ATOM_SALTWELL_MID, NO_SPECULATION),
|
||||
VULNWL_INTEL(ATOM_BONNELL, NO_SPECULATION),
|
||||
VULNWL_INTEL(ATOM_BONNELL_MID, NO_SPECULATION),
|
||||
|
||||
VULNWL_INTEL(ATOM_SILVERMONT, NO_SSB | NO_L1TF | MSBDS_ONLY),
|
||||
VULNWL_INTEL(ATOM_SILVERMONT_X, NO_SSB | NO_L1TF | MSBDS_ONLY),
|
||||
VULNWL_INTEL(ATOM_SILVERMONT_MID, NO_SSB | NO_L1TF | MSBDS_ONLY),
|
||||
VULNWL_INTEL(ATOM_AIRMONT, NO_SSB | NO_L1TF | MSBDS_ONLY),
|
||||
VULNWL_INTEL(XEON_PHI_KNL, NO_SSB | NO_L1TF | MSBDS_ONLY),
|
||||
VULNWL_INTEL(XEON_PHI_KNM, NO_SSB | NO_L1TF | MSBDS_ONLY),
|
||||
|
||||
VULNWL_INTEL(CORE_YONAH, NO_SSB),
|
||||
|
||||
VULNWL_INTEL(ATOM_AIRMONT_MID, NO_L1TF | MSBDS_ONLY),
|
||||
|
||||
VULNWL_INTEL(ATOM_GOLDMONT, NO_MDS | NO_L1TF),
|
||||
VULNWL_INTEL(ATOM_GOLDMONT_X, NO_MDS | NO_L1TF),
|
||||
VULNWL_INTEL(ATOM_GOLDMONT_PLUS, NO_MDS | NO_L1TF),
|
||||
|
||||
/* AMD Family 0xf - 0x12 */
|
||||
VULNWL_AMD(0x0f, NO_MELTDOWN | NO_SSB | NO_L1TF | NO_MDS),
|
||||
VULNWL_AMD(0x10, NO_MELTDOWN | NO_SSB | NO_L1TF | NO_MDS),
|
||||
VULNWL_AMD(0x11, NO_MELTDOWN | NO_SSB | NO_L1TF | NO_MDS),
|
||||
VULNWL_AMD(0x12, NO_MELTDOWN | NO_SSB | NO_L1TF | NO_MDS),
|
||||
|
||||
/* FAMILY_ANY must be last, otherwise 0x0f - 0x12 matches won't work */
|
||||
VULNWL_AMD(X86_FAMILY_ANY, NO_MELTDOWN | NO_L1TF | NO_MDS),
|
||||
VULNWL_HYGON(X86_FAMILY_ANY, NO_MELTDOWN | NO_L1TF | NO_MDS),
|
||||
{}
|
||||
};
|
||||
|
||||
static const __initconst struct x86_cpu_id cpu_no_meltdown[] = {
|
||||
{ X86_VENDOR_AMD },
|
||||
{ X86_VENDOR_HYGON },
|
||||
{}
|
||||
};
|
||||
static bool __init cpu_matches(unsigned long which)
|
||||
{
|
||||
const struct x86_cpu_id *m = x86_match_cpu(cpu_vuln_whitelist);
|
||||
|
||||
/* Only list CPUs which speculate but are non susceptible to SSB */
|
||||
static const __initconst struct x86_cpu_id cpu_no_spec_store_bypass[] = {
|
||||
{ X86_VENDOR_INTEL, 6, INTEL_FAM6_ATOM_SILVERMONT },
|
||||
{ X86_VENDOR_INTEL, 6, INTEL_FAM6_ATOM_AIRMONT },
|
||||
{ X86_VENDOR_INTEL, 6, INTEL_FAM6_ATOM_SILVERMONT_X },
|
||||
{ X86_VENDOR_INTEL, 6, INTEL_FAM6_ATOM_SILVERMONT_MID },
|
||||
{ X86_VENDOR_INTEL, 6, INTEL_FAM6_CORE_YONAH },
|
||||
{ X86_VENDOR_INTEL, 6, INTEL_FAM6_XEON_PHI_KNL },
|
||||
{ X86_VENDOR_INTEL, 6, INTEL_FAM6_XEON_PHI_KNM },
|
||||
{ X86_VENDOR_AMD, 0x12, },
|
||||
{ X86_VENDOR_AMD, 0x11, },
|
||||
{ X86_VENDOR_AMD, 0x10, },
|
||||
{ X86_VENDOR_AMD, 0xf, },
|
||||
{}
|
||||
};
|
||||
|
||||
static const __initconst struct x86_cpu_id cpu_no_l1tf[] = {
|
||||
/* in addition to cpu_no_speculation */
|
||||
{ X86_VENDOR_INTEL, 6, INTEL_FAM6_ATOM_SILVERMONT },
|
||||
{ X86_VENDOR_INTEL, 6, INTEL_FAM6_ATOM_SILVERMONT_X },
|
||||
{ X86_VENDOR_INTEL, 6, INTEL_FAM6_ATOM_AIRMONT },
|
||||
{ X86_VENDOR_INTEL, 6, INTEL_FAM6_ATOM_SILVERMONT_MID },
|
||||
{ X86_VENDOR_INTEL, 6, INTEL_FAM6_ATOM_AIRMONT_MID },
|
||||
{ X86_VENDOR_INTEL, 6, INTEL_FAM6_ATOM_GOLDMONT },
|
||||
{ X86_VENDOR_INTEL, 6, INTEL_FAM6_ATOM_GOLDMONT_X },
|
||||
{ X86_VENDOR_INTEL, 6, INTEL_FAM6_ATOM_GOLDMONT_PLUS },
|
||||
{ X86_VENDOR_INTEL, 6, INTEL_FAM6_XEON_PHI_KNL },
|
||||
{ X86_VENDOR_INTEL, 6, INTEL_FAM6_XEON_PHI_KNM },
|
||||
{}
|
||||
};
|
||||
return m && !!(m->driver_data & which);
|
||||
}
|
||||
|
||||
static void __init cpu_set_bug_bits(struct cpuinfo_x86 *c)
|
||||
{
|
||||
u64 ia32_cap = 0;
|
||||
|
||||
if (x86_match_cpu(cpu_no_speculation))
|
||||
if (cpu_matches(NO_SPECULATION))
|
||||
return;
|
||||
|
||||
setup_force_cpu_bug(X86_BUG_SPECTRE_V1);
|
||||
@@ -1011,15 +1027,20 @@ static void __init cpu_set_bug_bits(struct cpuinfo_x86 *c)
|
||||
if (cpu_has(c, X86_FEATURE_ARCH_CAPABILITIES))
|
||||
rdmsrl(MSR_IA32_ARCH_CAPABILITIES, ia32_cap);
|
||||
|
||||
if (!x86_match_cpu(cpu_no_spec_store_bypass) &&
|
||||
!(ia32_cap & ARCH_CAP_SSB_NO) &&
|
||||
if (!cpu_matches(NO_SSB) && !(ia32_cap & ARCH_CAP_SSB_NO) &&
|
||||
!cpu_has(c, X86_FEATURE_AMD_SSB_NO))
|
||||
setup_force_cpu_bug(X86_BUG_SPEC_STORE_BYPASS);
|
||||
|
||||
if (ia32_cap & ARCH_CAP_IBRS_ALL)
|
||||
setup_force_cpu_cap(X86_FEATURE_IBRS_ENHANCED);
|
||||
|
||||
if (x86_match_cpu(cpu_no_meltdown))
|
||||
if (!cpu_matches(NO_MDS) && !(ia32_cap & ARCH_CAP_MDS_NO)) {
|
||||
setup_force_cpu_bug(X86_BUG_MDS);
|
||||
if (cpu_matches(MSBDS_ONLY))
|
||||
setup_force_cpu_bug(X86_BUG_MSBDS_ONLY);
|
||||
}
|
||||
|
||||
if (cpu_matches(NO_MELTDOWN))
|
||||
return;
|
||||
|
||||
/* Rogue Data Cache Load? No! */
|
||||
@@ -1028,7 +1049,7 @@ static void __init cpu_set_bug_bits(struct cpuinfo_x86 *c)
|
||||
|
||||
setup_force_cpu_bug(X86_BUG_CPU_MELTDOWN);
|
||||
|
||||
if (x86_match_cpu(cpu_no_l1tf))
|
||||
if (cpu_matches(NO_L1TF))
|
||||
return;
|
||||
|
||||
setup_force_cpu_bug(X86_BUG_L1TF);
|
||||
|
||||
@@ -34,6 +34,7 @@
|
||||
#include <asm/x86_init.h>
|
||||
#include <asm/reboot.h>
|
||||
#include <asm/cache.h>
|
||||
#include <asm/nospec-branch.h>
|
||||
|
||||
#define CREATE_TRACE_POINTS
|
||||
#include <trace/events/nmi.h>
|
||||
@@ -533,6 +534,9 @@ nmi_restart:
|
||||
write_cr2(this_cpu_read(nmi_cr2));
|
||||
if (this_cpu_dec_return(nmi_state))
|
||||
goto nmi_restart;
|
||||
|
||||
if (user_mode(regs))
|
||||
mds_user_clear_cpu_buffers();
|
||||
}
|
||||
NOKPROBE_SYMBOL(do_nmi);
|
||||
|
||||
|
||||
@@ -58,6 +58,7 @@
|
||||
#include <asm/alternative.h>
|
||||
#include <asm/fpu/xstate.h>
|
||||
#include <asm/trace/mpx.h>
|
||||
#include <asm/nospec-branch.h>
|
||||
#include <asm/mpx.h>
|
||||
#include <asm/vm86.h>
|
||||
#include <asm/umip.h>
|
||||
@@ -367,6 +368,13 @@ dotraplinkage void do_double_fault(struct pt_regs *regs, long error_code)
|
||||
regs->ip = (unsigned long)general_protection;
|
||||
regs->sp = (unsigned long)&gpregs->orig_ax;
|
||||
|
||||
/*
|
||||
* This situation can be triggered by userspace via
|
||||
* modify_ldt(2) and the return does not take the regular
|
||||
* user space exit, so a CPU buffer clear is required when
|
||||
* MDS mitigation is enabled.
|
||||
*/
|
||||
mds_user_clear_cpu_buffers();
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -410,7 +410,8 @@ static inline int __do_cpuid_ent(struct kvm_cpuid_entry2 *entry, u32 function,
|
||||
/* cpuid 7.0.edx*/
|
||||
const u32 kvm_cpuid_7_0_edx_x86_features =
|
||||
F(AVX512_4VNNIW) | F(AVX512_4FMAPS) | F(SPEC_CTRL) |
|
||||
F(SPEC_CTRL_SSBD) | F(ARCH_CAPABILITIES) | F(INTEL_STIBP);
|
||||
F(SPEC_CTRL_SSBD) | F(ARCH_CAPABILITIES) | F(INTEL_STIBP) |
|
||||
F(MD_CLEAR);
|
||||
|
||||
/* all calls to cpuid_count() should be made on the same cpu */
|
||||
get_cpu();
|
||||
|
||||
@@ -6431,8 +6431,11 @@ static void vmx_vcpu_run(struct kvm_vcpu *vcpu)
|
||||
*/
|
||||
x86_spec_ctrl_set_guest(vmx->spec_ctrl, 0);
|
||||
|
||||
/* L1D Flush includes CPU buffer clear to mitigate MDS */
|
||||
if (static_branch_unlikely(&vmx_l1d_should_flush))
|
||||
vmx_l1d_flush(vcpu);
|
||||
else if (static_branch_unlikely(&mds_user_clear))
|
||||
mds_clear_cpu_buffers();
|
||||
|
||||
if (vcpu->arch.cr2 != read_cr2())
|
||||
write_cr2(vcpu->arch.cr2);
|
||||
@@ -6668,8 +6671,8 @@ free_partial_vcpu:
|
||||
return ERR_PTR(err);
|
||||
}
|
||||
|
||||
#define L1TF_MSG_SMT "L1TF CPU bug present and SMT on, data leak possible. See CVE-2018-3646 and https://www.kernel.org/doc/html/latest/admin-guide/l1tf.html for details.\n"
|
||||
#define L1TF_MSG_L1D "L1TF CPU bug present and virtualization mitigation disabled, data leak possible. See CVE-2018-3646 and https://www.kernel.org/doc/html/latest/admin-guide/l1tf.html for details.\n"
|
||||
#define L1TF_MSG_SMT "L1TF CPU bug present and SMT on, data leak possible. See CVE-2018-3646 and https://www.kernel.org/doc/html/latest/admin-guide/hw-vuln/l1tf.html for details.\n"
|
||||
#define L1TF_MSG_L1D "L1TF CPU bug present and virtualization mitigation disabled, data leak possible. See CVE-2018-3646 and https://www.kernel.org/doc/html/latest/admin-guide/hw-vuln/l1tf.html for details.\n"
|
||||
|
||||
static int vmx_vm_init(struct kvm *kvm)
|
||||
{
|
||||
|
||||
+3
-1
@@ -35,6 +35,7 @@
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/uaccess.h>
|
||||
#include <linux/cpu.h>
|
||||
|
||||
#include <asm/cpufeature.h>
|
||||
#include <asm/hypervisor.h>
|
||||
@@ -115,7 +116,8 @@ void __init pti_check_boottime_disable(void)
|
||||
}
|
||||
}
|
||||
|
||||
if (cmdline_find_option_bool(boot_command_line, "nopti")) {
|
||||
if (cmdline_find_option_bool(boot_command_line, "nopti") ||
|
||||
cpu_mitigations_off()) {
|
||||
pti_mode = PTI_FORCE_OFF;
|
||||
pti_print_if_insecure("disabled on command line.");
|
||||
return;
|
||||
|
||||
@@ -1142,8 +1142,8 @@ static struct dev_pm_domain acpi_lpss_pm_domain = {
|
||||
.thaw_noirq = acpi_subsys_thaw_noirq,
|
||||
.poweroff = acpi_subsys_suspend,
|
||||
.poweroff_late = acpi_lpss_suspend_late,
|
||||
.poweroff_noirq = acpi_subsys_suspend_noirq,
|
||||
.restore_noirq = acpi_subsys_resume_noirq,
|
||||
.poweroff_noirq = acpi_lpss_suspend_noirq,
|
||||
.restore_noirq = acpi_lpss_resume_noirq,
|
||||
.restore_early = acpi_lpss_resume_early,
|
||||
#endif
|
||||
.runtime_suspend = acpi_lpss_runtime_suspend,
|
||||
|
||||
@@ -548,11 +548,18 @@ ssize_t __weak cpu_show_l1tf(struct device *dev,
|
||||
return sprintf(buf, "Not affected\n");
|
||||
}
|
||||
|
||||
ssize_t __weak cpu_show_mds(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
return sprintf(buf, "Not affected\n");
|
||||
}
|
||||
|
||||
static DEVICE_ATTR(meltdown, 0444, cpu_show_meltdown, NULL);
|
||||
static DEVICE_ATTR(spectre_v1, 0444, cpu_show_spectre_v1, NULL);
|
||||
static DEVICE_ATTR(spectre_v2, 0444, cpu_show_spectre_v2, NULL);
|
||||
static DEVICE_ATTR(spec_store_bypass, 0444, cpu_show_spec_store_bypass, NULL);
|
||||
static DEVICE_ATTR(l1tf, 0444, cpu_show_l1tf, NULL);
|
||||
static DEVICE_ATTR(mds, 0444, cpu_show_mds, NULL);
|
||||
|
||||
static struct attribute *cpu_root_vulnerabilities_attrs[] = {
|
||||
&dev_attr_meltdown.attr,
|
||||
@@ -560,6 +567,7 @@ static struct attribute *cpu_root_vulnerabilities_attrs[] = {
|
||||
&dev_attr_spectre_v2.attr,
|
||||
&dev_attr_spec_store_bypass.attr,
|
||||
&dev_attr_l1tf.attr,
|
||||
&dev_attr_mds.attr,
|
||||
NULL
|
||||
};
|
||||
|
||||
|
||||
@@ -228,9 +228,15 @@ static int bcm_gpio_set_power(struct bcm_device *dev, bool powered)
|
||||
int err;
|
||||
|
||||
if (powered && !dev->res_enabled) {
|
||||
err = regulator_bulk_enable(BCM_NUM_SUPPLIES, dev->supplies);
|
||||
if (err)
|
||||
return err;
|
||||
/* Intel Macs use bcm_apple_get_resources() and don't
|
||||
* have regulator supplies configured.
|
||||
*/
|
||||
if (dev->supplies[0].supply) {
|
||||
err = regulator_bulk_enable(BCM_NUM_SUPPLIES,
|
||||
dev->supplies);
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
|
||||
/* LPO clock needs to be 32.768 kHz */
|
||||
err = clk_set_rate(dev->lpo_clk, 32768);
|
||||
@@ -259,7 +265,13 @@ static int bcm_gpio_set_power(struct bcm_device *dev, bool powered)
|
||||
if (!powered && dev->res_enabled) {
|
||||
clk_disable_unprepare(dev->txco_clk);
|
||||
clk_disable_unprepare(dev->lpo_clk);
|
||||
regulator_bulk_disable(BCM_NUM_SUPPLIES, dev->supplies);
|
||||
|
||||
/* Intel Macs use bcm_apple_get_resources() and don't
|
||||
* have regulator supplies configured.
|
||||
*/
|
||||
if (dev->supplies[0].supply)
|
||||
regulator_bulk_disable(BCM_NUM_SUPPLIES,
|
||||
dev->supplies);
|
||||
}
|
||||
|
||||
/* wait for device to power on and come out of reset */
|
||||
|
||||
@@ -359,11 +359,11 @@ static int __init armada37xx_cpufreq_driver_init(void)
|
||||
struct armada_37xx_dvfs *dvfs;
|
||||
struct platform_device *pdev;
|
||||
unsigned long freq;
|
||||
unsigned int cur_frequency;
|
||||
unsigned int cur_frequency, base_frequency;
|
||||
struct regmap *nb_pm_base, *avs_base;
|
||||
struct device *cpu_dev;
|
||||
int load_lvl, ret;
|
||||
struct clk *clk;
|
||||
struct clk *clk, *parent;
|
||||
|
||||
nb_pm_base =
|
||||
syscon_regmap_lookup_by_compatible("marvell,armada-3700-nb-pm");
|
||||
@@ -399,6 +399,22 @@ static int __init armada37xx_cpufreq_driver_init(void)
|
||||
return PTR_ERR(clk);
|
||||
}
|
||||
|
||||
parent = clk_get_parent(clk);
|
||||
if (IS_ERR(parent)) {
|
||||
dev_err(cpu_dev, "Cannot get parent clock for CPU0\n");
|
||||
clk_put(clk);
|
||||
return PTR_ERR(parent);
|
||||
}
|
||||
|
||||
/* Get parent CPU frequency */
|
||||
base_frequency = clk_get_rate(parent);
|
||||
|
||||
if (!base_frequency) {
|
||||
dev_err(cpu_dev, "Failed to get parent clock rate for CPU\n");
|
||||
clk_put(clk);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Get nominal (current) CPU frequency */
|
||||
cur_frequency = clk_get_rate(clk);
|
||||
if (!cur_frequency) {
|
||||
@@ -431,7 +447,7 @@ static int __init armada37xx_cpufreq_driver_init(void)
|
||||
for (load_lvl = ARMADA_37XX_DVFS_LOAD_0; load_lvl < LOAD_LEVEL_NR;
|
||||
load_lvl++) {
|
||||
unsigned long u_volt = avs_map[dvfs->avs[load_lvl]] * 1000;
|
||||
freq = cur_frequency / dvfs->divider[load_lvl];
|
||||
freq = base_frequency / dvfs->divider[load_lvl];
|
||||
ret = dev_pm_opp_add(cpu_dev, freq, u_volt);
|
||||
if (ret)
|
||||
goto remove_opp;
|
||||
|
||||
@@ -408,7 +408,6 @@ int hv_synic_cleanup(unsigned int cpu)
|
||||
|
||||
clockevents_unbind_device(hv_cpu->clk_evt, cpu);
|
||||
hv_ce_shutdown(hv_cpu->clk_evt);
|
||||
put_cpu_ptr(hv_cpu);
|
||||
}
|
||||
|
||||
hv_get_synint_state(VMBUS_MESSAGE_SINT, shared_sint.as_uint64);
|
||||
|
||||
@@ -42,16 +42,16 @@ static ssize_t occ_sysfs_show(struct device *dev,
|
||||
val = !!(header->status & OCC_STAT_ACTIVE);
|
||||
break;
|
||||
case 2:
|
||||
val = !!(header->status & OCC_EXT_STAT_DVFS_OT);
|
||||
val = !!(header->ext_status & OCC_EXT_STAT_DVFS_OT);
|
||||
break;
|
||||
case 3:
|
||||
val = !!(header->status & OCC_EXT_STAT_DVFS_POWER);
|
||||
val = !!(header->ext_status & OCC_EXT_STAT_DVFS_POWER);
|
||||
break;
|
||||
case 4:
|
||||
val = !!(header->status & OCC_EXT_STAT_MEM_THROTTLE);
|
||||
val = !!(header->ext_status & OCC_EXT_STAT_MEM_THROTTLE);
|
||||
break;
|
||||
case 5:
|
||||
val = !!(header->status & OCC_EXT_STAT_QUICK_DROP);
|
||||
val = !!(header->ext_status & OCC_EXT_STAT_QUICK_DROP);
|
||||
break;
|
||||
case 6:
|
||||
val = header->occ_state;
|
||||
|
||||
@@ -271,7 +271,7 @@ static int pwm_fan_probe(struct platform_device *pdev)
|
||||
|
||||
ret = pwm_fan_of_get_cooling_data(&pdev->dev, ctx);
|
||||
if (ret)
|
||||
return ret;
|
||||
goto err_pwm_disable;
|
||||
|
||||
ctx->pwm_fan_state = ctx->pwm_fan_max_state;
|
||||
if (IS_ENABLED(CONFIG_THERMAL)) {
|
||||
|
||||
@@ -165,6 +165,11 @@ static const struct pci_device_id intel_th_pci_id_table[] = {
|
||||
PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x34a6),
|
||||
.driver_data = (kernel_ulong_t)&intel_th_2x,
|
||||
},
|
||||
{
|
||||
/* Comet Lake */
|
||||
PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x02a6),
|
||||
.driver_data = (kernel_ulong_t)&intel_th_2x,
|
||||
},
|
||||
{ 0 },
|
||||
};
|
||||
|
||||
|
||||
@@ -1871,8 +1871,11 @@ int __i2c_transfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
|
||||
|
||||
if (WARN_ON(!msgs || num < 1))
|
||||
return -EINVAL;
|
||||
if (WARN_ON(test_bit(I2C_ALF_IS_SUSPENDED, &adap->locked_flags)))
|
||||
if (test_bit(I2C_ALF_IS_SUSPENDED, &adap->locked_flags)) {
|
||||
if (!test_and_set_bit(I2C_ALF_SUSPEND_REPORTED, &adap->locked_flags))
|
||||
dev_WARN(&adap->dev, "Transfer while suspended\n");
|
||||
return -ESHUTDOWN;
|
||||
}
|
||||
|
||||
if (adap->quirks && i2c_check_for_quirks(adap, msgs, num))
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
@@ -385,8 +385,9 @@ static void i3c_bus_set_addr_slot_status(struct i3c_bus *bus, u16 addr,
|
||||
return;
|
||||
|
||||
ptr = bus->addrslots + (bitpos / BITS_PER_LONG);
|
||||
*ptr &= ~(I3C_ADDR_SLOT_STATUS_MASK << (bitpos % BITS_PER_LONG));
|
||||
*ptr |= status << (bitpos % BITS_PER_LONG);
|
||||
*ptr &= ~((unsigned long)I3C_ADDR_SLOT_STATUS_MASK <<
|
||||
(bitpos % BITS_PER_LONG));
|
||||
*ptr |= (unsigned long)status << (bitpos % BITS_PER_LONG);
|
||||
}
|
||||
|
||||
static bool i3c_bus_dev_addr_is_avail(struct i3c_bus *bus, u8 addr)
|
||||
|
||||
@@ -664,6 +664,7 @@ static const struct of_device_id adc5_match_table[] = {
|
||||
},
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, adc5_match_table);
|
||||
|
||||
static int adc5_get_dt_data(struct adc5_chip *adc, struct device_node *node)
|
||||
{
|
||||
|
||||
@@ -958,6 +958,7 @@ static void write_iso_callback(struct urb *urb)
|
||||
*/
|
||||
static int starturbs(struct bc_state *bcs)
|
||||
{
|
||||
struct usb_device *udev = bcs->cs->hw.bas->udev;
|
||||
struct bas_bc_state *ubc = bcs->hw.bas;
|
||||
struct urb *urb;
|
||||
int j, k;
|
||||
@@ -975,8 +976,8 @@ static int starturbs(struct bc_state *bcs)
|
||||
rc = -EFAULT;
|
||||
goto error;
|
||||
}
|
||||
usb_fill_int_urb(urb, bcs->cs->hw.bas->udev,
|
||||
usb_rcvisocpipe(urb->dev, 3 + 2 * bcs->channel),
|
||||
usb_fill_int_urb(urb, udev,
|
||||
usb_rcvisocpipe(udev, 3 + 2 * bcs->channel),
|
||||
ubc->isoinbuf + k * BAS_INBUFSIZE,
|
||||
BAS_INBUFSIZE, read_iso_callback, bcs,
|
||||
BAS_FRAMETIME);
|
||||
@@ -1006,8 +1007,8 @@ static int starturbs(struct bc_state *bcs)
|
||||
rc = -EFAULT;
|
||||
goto error;
|
||||
}
|
||||
usb_fill_int_urb(urb, bcs->cs->hw.bas->udev,
|
||||
usb_sndisocpipe(urb->dev, 4 + 2 * bcs->channel),
|
||||
usb_fill_int_urb(urb, udev,
|
||||
usb_sndisocpipe(udev, 4 + 2 * bcs->channel),
|
||||
ubc->isooutbuf->data,
|
||||
sizeof(ubc->isooutbuf->data),
|
||||
write_iso_callback, &ubc->isoouturbs[k],
|
||||
|
||||
+4
-15
@@ -4223,26 +4223,15 @@ static void handle_parity_checks6(struct r5conf *conf, struct stripe_head *sh,
|
||||
case check_state_check_result:
|
||||
sh->check_state = check_state_idle;
|
||||
|
||||
if (s->failed > 1)
|
||||
break;
|
||||
/* handle a successful check operation, if parity is correct
|
||||
* we are done. Otherwise update the mismatch count and repair
|
||||
* parity if !MD_RECOVERY_CHECK
|
||||
*/
|
||||
if (sh->ops.zero_sum_result == 0) {
|
||||
/* both parities are correct */
|
||||
if (!s->failed)
|
||||
set_bit(STRIPE_INSYNC, &sh->state);
|
||||
else {
|
||||
/* in contrast to the raid5 case we can validate
|
||||
* parity, but still have a failure to write
|
||||
* back
|
||||
*/
|
||||
sh->check_state = check_state_compute_result;
|
||||
/* Returning at this point means that we may go
|
||||
* off and bring p and/or q uptodate again so
|
||||
* we make sure to check zero_sum_result again
|
||||
* to verify if p or q need writeback
|
||||
*/
|
||||
}
|
||||
/* Any parity checked was correct */
|
||||
set_bit(STRIPE_INSYNC, &sh->state);
|
||||
} else {
|
||||
atomic64_add(STRIPE_SECTORS, &conf->mddev->resync_mismatches);
|
||||
if (test_bit(MD_RECOVERY_CHECK, &conf->mddev->recovery)) {
|
||||
|
||||
@@ -1098,13 +1098,6 @@ static int bond_option_arp_validate_set(struct bonding *bond,
|
||||
{
|
||||
netdev_dbg(bond->dev, "Setting arp_validate to %s (%llu)\n",
|
||||
newval->string, newval->value);
|
||||
|
||||
if (bond->dev->flags & IFF_UP) {
|
||||
if (!newval->value)
|
||||
bond->recv_probe = NULL;
|
||||
else if (bond->params.arp_interval)
|
||||
bond->recv_probe = bond_arp_rcv;
|
||||
}
|
||||
bond->params.arp_validate = newval->value;
|
||||
|
||||
return 0;
|
||||
|
||||
@@ -2461,12 +2461,12 @@ static int macb_open(struct net_device *dev)
|
||||
goto pm_exit;
|
||||
}
|
||||
|
||||
bp->macbgem_ops.mog_init_rings(bp);
|
||||
macb_init_hw(bp);
|
||||
|
||||
for (q = 0, queue = bp->queues; q < bp->num_queues; ++q, ++queue)
|
||||
napi_enable(&queue->napi);
|
||||
|
||||
bp->macbgem_ops.mog_init_rings(bp);
|
||||
macb_init_hw(bp);
|
||||
|
||||
/* schedule a link state check */
|
||||
phy_start(dev->phydev);
|
||||
|
||||
|
||||
@@ -1648,7 +1648,7 @@ static struct sk_buff *dpaa_cleanup_tx_fd(const struct dpaa_priv *priv,
|
||||
qm_sg_entry_get_len(&sgt[0]), dma_dir);
|
||||
|
||||
/* remaining pages were mapped with skb_frag_dma_map() */
|
||||
for (i = 1; i < nr_frags; i++) {
|
||||
for (i = 1; i <= nr_frags; i++) {
|
||||
WARN_ON(qm_sg_entry_is_ext(&sgt[i]));
|
||||
|
||||
dma_unmap_page(dev, qm_sg_addr(&sgt[i]),
|
||||
|
||||
@@ -252,14 +252,12 @@ uec_set_ringparam(struct net_device *netdev,
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (netif_running(netdev))
|
||||
return -EBUSY;
|
||||
|
||||
ug_info->bdRingLenRx[queue] = ring->rx_pending;
|
||||
ug_info->bdRingLenTx[queue] = ring->tx_pending;
|
||||
|
||||
if (netif_running(netdev)) {
|
||||
/* FIXME: restart automatically */
|
||||
netdev_info(netdev, "Please re-open the interface\n");
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
@@ -735,6 +735,7 @@ static int sgiseeq_probe(struct platform_device *pdev)
|
||||
}
|
||||
|
||||
platform_set_drvdata(pdev, dev);
|
||||
SET_NETDEV_DEV(dev, &pdev->dev);
|
||||
sp = netdev_priv(dev);
|
||||
|
||||
/* Make private data page aligned */
|
||||
|
||||
@@ -1015,6 +1015,8 @@ static struct mac_device_info *sun8i_dwmac_setup(void *ppriv)
|
||||
mac->mac = &sun8i_dwmac_ops;
|
||||
mac->dma = &sun8i_dwmac_dma_ops;
|
||||
|
||||
priv->dev->priv_flags |= IFF_UNICAST_FLT;
|
||||
|
||||
/* The loopback bit seems to be re-set when link change
|
||||
* Simply mask it each time
|
||||
* Speed 10/100/1000 are set in BIT(2)/BIT(3)
|
||||
|
||||
@@ -2044,11 +2044,14 @@ bool phy_validate_pause(struct phy_device *phydev,
|
||||
struct ethtool_pauseparam *pp)
|
||||
{
|
||||
if (!linkmode_test_bit(ETHTOOL_LINK_MODE_Pause_BIT,
|
||||
phydev->supported) ||
|
||||
(!linkmode_test_bit(ETHTOOL_LINK_MODE_Asym_Pause_BIT,
|
||||
phydev->supported) &&
|
||||
pp->rx_pause != pp->tx_pause))
|
||||
phydev->supported) && pp->rx_pause)
|
||||
return false;
|
||||
|
||||
if (!linkmode_test_bit(ETHTOOL_LINK_MODE_Asym_Pause_BIT,
|
||||
phydev->supported) &&
|
||||
pp->rx_pause != pp->tx_pause)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
EXPORT_SYMBOL(phy_validate_pause);
|
||||
|
||||
+12
-2
@@ -596,13 +596,18 @@ static u16 tun_automq_select_queue(struct tun_struct *tun, struct sk_buff *skb)
|
||||
static u16 tun_ebpf_select_queue(struct tun_struct *tun, struct sk_buff *skb)
|
||||
{
|
||||
struct tun_prog *prog;
|
||||
u32 numqueues;
|
||||
u16 ret = 0;
|
||||
|
||||
numqueues = READ_ONCE(tun->numqueues);
|
||||
if (!numqueues)
|
||||
return 0;
|
||||
|
||||
prog = rcu_dereference(tun->steering_prog);
|
||||
if (prog)
|
||||
ret = bpf_prog_run_clear_cb(prog->prog, skb);
|
||||
|
||||
return ret % tun->numqueues;
|
||||
return ret % numqueues;
|
||||
}
|
||||
|
||||
static u16 tun_select_queue(struct net_device *dev, struct sk_buff *skb,
|
||||
@@ -700,6 +705,8 @@ static void __tun_detach(struct tun_file *tfile, bool clean)
|
||||
tun->tfiles[tun->numqueues - 1]);
|
||||
ntfile = rtnl_dereference(tun->tfiles[index]);
|
||||
ntfile->queue_index = index;
|
||||
rcu_assign_pointer(tun->tfiles[tun->numqueues - 1],
|
||||
NULL);
|
||||
|
||||
--tun->numqueues;
|
||||
if (clean) {
|
||||
@@ -1082,7 +1089,7 @@ static netdev_tx_t tun_net_xmit(struct sk_buff *skb, struct net_device *dev)
|
||||
tfile = rcu_dereference(tun->tfiles[txq]);
|
||||
|
||||
/* Drop packet if interface is not attached */
|
||||
if (txq >= tun->numqueues)
|
||||
if (!tfile)
|
||||
goto drop;
|
||||
|
||||
if (!rcu_dereference(tun->steering_prog))
|
||||
@@ -1305,6 +1312,7 @@ static int tun_xdp_xmit(struct net_device *dev, int n,
|
||||
|
||||
rcu_read_lock();
|
||||
|
||||
resample:
|
||||
numqueues = READ_ONCE(tun->numqueues);
|
||||
if (!numqueues) {
|
||||
rcu_read_unlock();
|
||||
@@ -1313,6 +1321,8 @@ static int tun_xdp_xmit(struct net_device *dev, int n,
|
||||
|
||||
tfile = rcu_dereference(tun->tfiles[smp_processor_id() %
|
||||
numqueues]);
|
||||
if (unlikely(!tfile))
|
||||
goto resample;
|
||||
|
||||
spin_lock(&tfile->tx_ring.producer_lock);
|
||||
for (i = 0; i < n; i++) {
|
||||
|
||||
@@ -441,6 +441,9 @@ static const struct ieee80211_rate mwl8k_rates_50[] = {
|
||||
#define MWL8K_CMD_UPDATE_STADB 0x1123
|
||||
#define MWL8K_CMD_BASTREAM 0x1125
|
||||
|
||||
#define MWL8K_LEGACY_5G_RATE_OFFSET \
|
||||
(ARRAY_SIZE(mwl8k_rates_24) - ARRAY_SIZE(mwl8k_rates_50))
|
||||
|
||||
static const char *mwl8k_cmd_name(__le16 cmd, char *buf, int bufsize)
|
||||
{
|
||||
u16 command = le16_to_cpu(cmd);
|
||||
@@ -1016,8 +1019,9 @@ mwl8k_rxd_ap_process(void *_rxd, struct ieee80211_rx_status *status,
|
||||
|
||||
if (rxd->channel > 14) {
|
||||
status->band = NL80211_BAND_5GHZ;
|
||||
if (!(status->encoding == RX_ENC_HT))
|
||||
status->rate_idx -= 5;
|
||||
if (!(status->encoding == RX_ENC_HT) &&
|
||||
status->rate_idx >= MWL8K_LEGACY_5G_RATE_OFFSET)
|
||||
status->rate_idx -= MWL8K_LEGACY_5G_RATE_OFFSET;
|
||||
} else {
|
||||
status->band = NL80211_BAND_2GHZ;
|
||||
}
|
||||
@@ -1124,8 +1128,9 @@ mwl8k_rxd_sta_process(void *_rxd, struct ieee80211_rx_status *status,
|
||||
|
||||
if (rxd->channel > 14) {
|
||||
status->band = NL80211_BAND_5GHZ;
|
||||
if (!(status->encoding == RX_ENC_HT))
|
||||
status->rate_idx -= 5;
|
||||
if (!(status->encoding == RX_ENC_HT) &&
|
||||
status->rate_idx >= MWL8K_LEGACY_5G_RATE_OFFSET)
|
||||
status->rate_idx -= MWL8K_LEGACY_5G_RATE_OFFSET;
|
||||
} else {
|
||||
status->band = NL80211_BAND_2GHZ;
|
||||
}
|
||||
|
||||
@@ -1675,6 +1675,7 @@ static void _rtl8723e_read_adapter_info(struct ieee80211_hw *hw,
|
||||
rtlhal->oem_id = RT_CID_819X_LENOVO;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 0x1025:
|
||||
rtlhal->oem_id = RT_CID_819X_ACER;
|
||||
break;
|
||||
|
||||
@@ -1486,6 +1486,21 @@ static void hv_pci_assign_slots(struct hv_pcibus_device *hbus)
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Remove entries in sysfs pci slot directory.
|
||||
*/
|
||||
static void hv_pci_remove_slots(struct hv_pcibus_device *hbus)
|
||||
{
|
||||
struct hv_pci_dev *hpdev;
|
||||
|
||||
list_for_each_entry(hpdev, &hbus->children, list_entry) {
|
||||
if (!hpdev->pci_slot)
|
||||
continue;
|
||||
pci_destroy_slot(hpdev->pci_slot);
|
||||
hpdev->pci_slot = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* create_root_hv_pci_bus() - Expose a new root PCI bus
|
||||
* @hbus: Root PCI bus, as understood by this driver
|
||||
@@ -1761,6 +1776,10 @@ static void pci_devices_present_work(struct work_struct *work)
|
||||
hpdev = list_first_entry(&removed, struct hv_pci_dev,
|
||||
list_entry);
|
||||
list_del(&hpdev->list_entry);
|
||||
|
||||
if (hpdev->pci_slot)
|
||||
pci_destroy_slot(hpdev->pci_slot);
|
||||
|
||||
put_pcichild(hpdev);
|
||||
}
|
||||
|
||||
@@ -1900,6 +1919,9 @@ static void hv_eject_device_work(struct work_struct *work)
|
||||
sizeof(*ejct_pkt), (unsigned long)&ctxt.pkt,
|
||||
VM_PKT_DATA_INBAND, 0);
|
||||
|
||||
/* For the get_pcichild() in hv_pci_eject_device() */
|
||||
put_pcichild(hpdev);
|
||||
/* For the two refs got in new_pcichild_device() */
|
||||
put_pcichild(hpdev);
|
||||
put_pcichild(hpdev);
|
||||
put_hvpcibus(hpdev->hbus);
|
||||
@@ -2677,6 +2699,7 @@ static int hv_pci_remove(struct hv_device *hdev)
|
||||
pci_lock_rescan_remove();
|
||||
pci_stop_root_bus(hbus->pci_bus);
|
||||
pci_remove_root_bus(hbus->pci_bus);
|
||||
hv_pci_remove_slots(hbus);
|
||||
pci_unlock_rescan_remove();
|
||||
hbus->state = hv_pcibus_removed;
|
||||
}
|
||||
|
||||
@@ -531,7 +531,7 @@ static void dell_rfkill_query(struct rfkill *rfkill, void *data)
|
||||
return;
|
||||
}
|
||||
|
||||
dell_fill_request(&buffer, 0, 0x2, 0, 0);
|
||||
dell_fill_request(&buffer, 0x2, 0, 0, 0);
|
||||
ret = dell_send_request(&buffer, CLASS_INFO, SELECT_RFKILL);
|
||||
hwswitch = buffer.output[1];
|
||||
|
||||
@@ -562,7 +562,7 @@ static int dell_debugfs_show(struct seq_file *s, void *data)
|
||||
return ret;
|
||||
status = buffer.output[1];
|
||||
|
||||
dell_fill_request(&buffer, 0, 0x2, 0, 0);
|
||||
dell_fill_request(&buffer, 0x2, 0, 0, 0);
|
||||
hwswitch_ret = dell_send_request(&buffer, CLASS_INFO, SELECT_RFKILL);
|
||||
if (hwswitch_ret)
|
||||
return hwswitch_ret;
|
||||
@@ -647,7 +647,7 @@ static void dell_update_rfkill(struct work_struct *ignored)
|
||||
if (ret != 0)
|
||||
return;
|
||||
|
||||
dell_fill_request(&buffer, 0, 0x2, 0, 0);
|
||||
dell_fill_request(&buffer, 0x2, 0, 0, 0);
|
||||
ret = dell_send_request(&buffer, CLASS_INFO, SELECT_RFKILL);
|
||||
|
||||
if (ret == 0 && (status & BIT(0)))
|
||||
|
||||
@@ -4424,14 +4424,16 @@ sony_pic_read_possible_resource(struct acpi_resource *resource, void *context)
|
||||
}
|
||||
return AE_OK;
|
||||
}
|
||||
default:
|
||||
dprintk("Resource %d isn't an IRQ nor an IO port\n",
|
||||
resource->type);
|
||||
|
||||
case ACPI_RESOURCE_TYPE_END_TAG:
|
||||
return AE_OK;
|
||||
|
||||
default:
|
||||
dprintk("Resource %d isn't an IRQ nor an IO port\n",
|
||||
resource->type);
|
||||
return AE_CTRL_TERMINATE;
|
||||
|
||||
}
|
||||
return AE_CTRL_TERMINATE;
|
||||
}
|
||||
|
||||
static int sony_pic_possible_resources(struct acpi_device *device)
|
||||
|
||||
@@ -79,7 +79,7 @@
|
||||
#include <linux/jiffies.h>
|
||||
#include <linux/workqueue.h>
|
||||
#include <linux/acpi.h>
|
||||
#include <linux/pci_ids.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/power_supply.h>
|
||||
#include <sound/core.h>
|
||||
#include <sound/control.h>
|
||||
@@ -4501,6 +4501,74 @@ static void bluetooth_exit(void)
|
||||
bluetooth_shutdown();
|
||||
}
|
||||
|
||||
static const struct dmi_system_id bt_fwbug_list[] __initconst = {
|
||||
{
|
||||
.ident = "ThinkPad E485",
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
|
||||
DMI_MATCH(DMI_BOARD_NAME, "20KU"),
|
||||
},
|
||||
},
|
||||
{
|
||||
.ident = "ThinkPad E585",
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
|
||||
DMI_MATCH(DMI_BOARD_NAME, "20KV"),
|
||||
},
|
||||
},
|
||||
{
|
||||
.ident = "ThinkPad A285 - 20MW",
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
|
||||
DMI_MATCH(DMI_BOARD_NAME, "20MW"),
|
||||
},
|
||||
},
|
||||
{
|
||||
.ident = "ThinkPad A285 - 20MX",
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
|
||||
DMI_MATCH(DMI_BOARD_NAME, "20MX"),
|
||||
},
|
||||
},
|
||||
{
|
||||
.ident = "ThinkPad A485 - 20MU",
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
|
||||
DMI_MATCH(DMI_BOARD_NAME, "20MU"),
|
||||
},
|
||||
},
|
||||
{
|
||||
.ident = "ThinkPad A485 - 20MV",
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
|
||||
DMI_MATCH(DMI_BOARD_NAME, "20MV"),
|
||||
},
|
||||
},
|
||||
{}
|
||||
};
|
||||
|
||||
static const struct pci_device_id fwbug_cards_ids[] __initconst = {
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x24F3) },
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x24FD) },
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x2526) },
|
||||
{}
|
||||
};
|
||||
|
||||
|
||||
static int __init have_bt_fwbug(void)
|
||||
{
|
||||
/*
|
||||
* Some AMD based ThinkPads have a firmware bug that calling
|
||||
* "GBDC" will cause bluetooth on Intel wireless cards blocked
|
||||
*/
|
||||
if (dmi_check_system(bt_fwbug_list) && pci_dev_present(fwbug_cards_ids)) {
|
||||
vdbg_printk(TPACPI_DBG_INIT | TPACPI_DBG_RFKILL,
|
||||
FW_BUG "disable bluetooth subdriver for Intel cards\n");
|
||||
return 1;
|
||||
} else
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __init bluetooth_init(struct ibm_init_struct *iibm)
|
||||
{
|
||||
int res;
|
||||
@@ -4513,7 +4581,7 @@ static int __init bluetooth_init(struct ibm_init_struct *iibm)
|
||||
|
||||
/* bluetooth not supported on 570, 600e/x, 770e, 770x, A21e, A2xm/p,
|
||||
G4x, R30, R31, R40e, R50e, T20-22, X20-21 */
|
||||
tp_features.bluetooth = hkey_handle &&
|
||||
tp_features.bluetooth = !have_bt_fwbug() && hkey_handle &&
|
||||
acpi_evalf(hkey_handle, &status, "GBDC", "qd");
|
||||
|
||||
vdbg_printk(TPACPI_DBG_INIT | TPACPI_DBG_RFKILL,
|
||||
|
||||
+100
-96
@@ -114,7 +114,7 @@ static ssize_t
|
||||
lpfc_drvr_version_show(struct device *dev, struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
return snprintf(buf, PAGE_SIZE, LPFC_MODULE_DESC "\n");
|
||||
return scnprintf(buf, PAGE_SIZE, LPFC_MODULE_DESC "\n");
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -134,9 +134,9 @@ lpfc_enable_fip_show(struct device *dev, struct device_attribute *attr,
|
||||
struct lpfc_hba *phba = vport->phba;
|
||||
|
||||
if (phba->hba_flag & HBA_FIP_SUPPORT)
|
||||
return snprintf(buf, PAGE_SIZE, "1\n");
|
||||
return scnprintf(buf, PAGE_SIZE, "1\n");
|
||||
else
|
||||
return snprintf(buf, PAGE_SIZE, "0\n");
|
||||
return scnprintf(buf, PAGE_SIZE, "0\n");
|
||||
}
|
||||
|
||||
static ssize_t
|
||||
@@ -564,14 +564,15 @@ lpfc_bg_info_show(struct device *dev, struct device_attribute *attr,
|
||||
struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
|
||||
struct lpfc_hba *phba = vport->phba;
|
||||
|
||||
if (phba->cfg_enable_bg)
|
||||
if (phba->cfg_enable_bg) {
|
||||
if (phba->sli3_options & LPFC_SLI3_BG_ENABLED)
|
||||
return snprintf(buf, PAGE_SIZE, "BlockGuard Enabled\n");
|
||||
return scnprintf(buf, PAGE_SIZE,
|
||||
"BlockGuard Enabled\n");
|
||||
else
|
||||
return snprintf(buf, PAGE_SIZE,
|
||||
return scnprintf(buf, PAGE_SIZE,
|
||||
"BlockGuard Not Supported\n");
|
||||
else
|
||||
return snprintf(buf, PAGE_SIZE,
|
||||
} else
|
||||
return scnprintf(buf, PAGE_SIZE,
|
||||
"BlockGuard Disabled\n");
|
||||
}
|
||||
|
||||
@@ -583,7 +584,7 @@ lpfc_bg_guard_err_show(struct device *dev, struct device_attribute *attr,
|
||||
struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
|
||||
struct lpfc_hba *phba = vport->phba;
|
||||
|
||||
return snprintf(buf, PAGE_SIZE, "%llu\n",
|
||||
return scnprintf(buf, PAGE_SIZE, "%llu\n",
|
||||
(unsigned long long)phba->bg_guard_err_cnt);
|
||||
}
|
||||
|
||||
@@ -595,7 +596,7 @@ lpfc_bg_apptag_err_show(struct device *dev, struct device_attribute *attr,
|
||||
struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
|
||||
struct lpfc_hba *phba = vport->phba;
|
||||
|
||||
return snprintf(buf, PAGE_SIZE, "%llu\n",
|
||||
return scnprintf(buf, PAGE_SIZE, "%llu\n",
|
||||
(unsigned long long)phba->bg_apptag_err_cnt);
|
||||
}
|
||||
|
||||
@@ -607,7 +608,7 @@ lpfc_bg_reftag_err_show(struct device *dev, struct device_attribute *attr,
|
||||
struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
|
||||
struct lpfc_hba *phba = vport->phba;
|
||||
|
||||
return snprintf(buf, PAGE_SIZE, "%llu\n",
|
||||
return scnprintf(buf, PAGE_SIZE, "%llu\n",
|
||||
(unsigned long long)phba->bg_reftag_err_cnt);
|
||||
}
|
||||
|
||||
@@ -625,7 +626,7 @@ lpfc_info_show(struct device *dev, struct device_attribute *attr,
|
||||
{
|
||||
struct Scsi_Host *host = class_to_shost(dev);
|
||||
|
||||
return snprintf(buf, PAGE_SIZE, "%s\n",lpfc_info(host));
|
||||
return scnprintf(buf, PAGE_SIZE, "%s\n", lpfc_info(host));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -644,7 +645,7 @@ lpfc_serialnum_show(struct device *dev, struct device_attribute *attr,
|
||||
struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
|
||||
struct lpfc_hba *phba = vport->phba;
|
||||
|
||||
return snprintf(buf, PAGE_SIZE, "%s\n",phba->SerialNumber);
|
||||
return scnprintf(buf, PAGE_SIZE, "%s\n", phba->SerialNumber);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -666,7 +667,7 @@ lpfc_temp_sensor_show(struct device *dev, struct device_attribute *attr,
|
||||
struct Scsi_Host *shost = class_to_shost(dev);
|
||||
struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
|
||||
struct lpfc_hba *phba = vport->phba;
|
||||
return snprintf(buf, PAGE_SIZE, "%d\n",phba->temp_sensor_support);
|
||||
return scnprintf(buf, PAGE_SIZE, "%d\n", phba->temp_sensor_support);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -685,7 +686,7 @@ lpfc_modeldesc_show(struct device *dev, struct device_attribute *attr,
|
||||
struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
|
||||
struct lpfc_hba *phba = vport->phba;
|
||||
|
||||
return snprintf(buf, PAGE_SIZE, "%s\n",phba->ModelDesc);
|
||||
return scnprintf(buf, PAGE_SIZE, "%s\n", phba->ModelDesc);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -704,7 +705,7 @@ lpfc_modelname_show(struct device *dev, struct device_attribute *attr,
|
||||
struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
|
||||
struct lpfc_hba *phba = vport->phba;
|
||||
|
||||
return snprintf(buf, PAGE_SIZE, "%s\n",phba->ModelName);
|
||||
return scnprintf(buf, PAGE_SIZE, "%s\n", phba->ModelName);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -723,7 +724,7 @@ lpfc_programtype_show(struct device *dev, struct device_attribute *attr,
|
||||
struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
|
||||
struct lpfc_hba *phba = vport->phba;
|
||||
|
||||
return snprintf(buf, PAGE_SIZE, "%s\n",phba->ProgramType);
|
||||
return scnprintf(buf, PAGE_SIZE, "%s\n", phba->ProgramType);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -741,7 +742,7 @@ lpfc_mlomgmt_show(struct device *dev, struct device_attribute *attr, char *buf)
|
||||
struct lpfc_vport *vport = (struct lpfc_vport *)shost->hostdata;
|
||||
struct lpfc_hba *phba = vport->phba;
|
||||
|
||||
return snprintf(buf, PAGE_SIZE, "%d\n",
|
||||
return scnprintf(buf, PAGE_SIZE, "%d\n",
|
||||
(phba->sli.sli_flag & LPFC_MENLO_MAINT));
|
||||
}
|
||||
|
||||
@@ -761,7 +762,7 @@ lpfc_vportnum_show(struct device *dev, struct device_attribute *attr,
|
||||
struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
|
||||
struct lpfc_hba *phba = vport->phba;
|
||||
|
||||
return snprintf(buf, PAGE_SIZE, "%s\n",phba->Port);
|
||||
return scnprintf(buf, PAGE_SIZE, "%s\n", phba->Port);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -789,10 +790,10 @@ lpfc_fwrev_show(struct device *dev, struct device_attribute *attr,
|
||||
sli_family = phba->sli4_hba.pc_sli4_params.sli_family;
|
||||
|
||||
if (phba->sli_rev < LPFC_SLI_REV4)
|
||||
len = snprintf(buf, PAGE_SIZE, "%s, sli-%d\n",
|
||||
len = scnprintf(buf, PAGE_SIZE, "%s, sli-%d\n",
|
||||
fwrev, phba->sli_rev);
|
||||
else
|
||||
len = snprintf(buf, PAGE_SIZE, "%s, sli-%d:%d:%x\n",
|
||||
len = scnprintf(buf, PAGE_SIZE, "%s, sli-%d:%d:%x\n",
|
||||
fwrev, phba->sli_rev, if_type, sli_family);
|
||||
|
||||
return len;
|
||||
@@ -816,7 +817,7 @@ lpfc_hdw_show(struct device *dev, struct device_attribute *attr, char *buf)
|
||||
lpfc_vpd_t *vp = &phba->vpd;
|
||||
|
||||
lpfc_jedec_to_ascii(vp->rev.biuRev, hdw);
|
||||
return snprintf(buf, PAGE_SIZE, "%s\n", hdw);
|
||||
return scnprintf(buf, PAGE_SIZE, "%s\n", hdw);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -837,10 +838,11 @@ lpfc_option_rom_version_show(struct device *dev, struct device_attribute *attr,
|
||||
char fwrev[FW_REV_STR_SIZE];
|
||||
|
||||
if (phba->sli_rev < LPFC_SLI_REV4)
|
||||
return snprintf(buf, PAGE_SIZE, "%s\n", phba->OptionROMVersion);
|
||||
return scnprintf(buf, PAGE_SIZE, "%s\n",
|
||||
phba->OptionROMVersion);
|
||||
|
||||
lpfc_decode_firmware_rev(phba, fwrev, 1);
|
||||
return snprintf(buf, PAGE_SIZE, "%s\n", fwrev);
|
||||
return scnprintf(buf, PAGE_SIZE, "%s\n", fwrev);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -871,20 +873,20 @@ lpfc_link_state_show(struct device *dev, struct device_attribute *attr,
|
||||
case LPFC_LINK_DOWN:
|
||||
case LPFC_HBA_ERROR:
|
||||
if (phba->hba_flag & LINK_DISABLED)
|
||||
len += snprintf(buf + len, PAGE_SIZE-len,
|
||||
len += scnprintf(buf + len, PAGE_SIZE-len,
|
||||
"Link Down - User disabled\n");
|
||||
else
|
||||
len += snprintf(buf + len, PAGE_SIZE-len,
|
||||
len += scnprintf(buf + len, PAGE_SIZE-len,
|
||||
"Link Down\n");
|
||||
break;
|
||||
case LPFC_LINK_UP:
|
||||
case LPFC_CLEAR_LA:
|
||||
case LPFC_HBA_READY:
|
||||
len += snprintf(buf + len, PAGE_SIZE-len, "Link Up - ");
|
||||
len += scnprintf(buf + len, PAGE_SIZE-len, "Link Up - ");
|
||||
|
||||
switch (vport->port_state) {
|
||||
case LPFC_LOCAL_CFG_LINK:
|
||||
len += snprintf(buf + len, PAGE_SIZE-len,
|
||||
len += scnprintf(buf + len, PAGE_SIZE-len,
|
||||
"Configuring Link\n");
|
||||
break;
|
||||
case LPFC_FDISC:
|
||||
@@ -894,38 +896,40 @@ lpfc_link_state_show(struct device *dev, struct device_attribute *attr,
|
||||
case LPFC_NS_QRY:
|
||||
case LPFC_BUILD_DISC_LIST:
|
||||
case LPFC_DISC_AUTH:
|
||||
len += snprintf(buf + len, PAGE_SIZE - len,
|
||||
len += scnprintf(buf + len, PAGE_SIZE - len,
|
||||
"Discovery\n");
|
||||
break;
|
||||
case LPFC_VPORT_READY:
|
||||
len += snprintf(buf + len, PAGE_SIZE - len, "Ready\n");
|
||||
len += scnprintf(buf + len, PAGE_SIZE - len,
|
||||
"Ready\n");
|
||||
break;
|
||||
|
||||
case LPFC_VPORT_FAILED:
|
||||
len += snprintf(buf + len, PAGE_SIZE - len, "Failed\n");
|
||||
len += scnprintf(buf + len, PAGE_SIZE - len,
|
||||
"Failed\n");
|
||||
break;
|
||||
|
||||
case LPFC_VPORT_UNKNOWN:
|
||||
len += snprintf(buf + len, PAGE_SIZE - len,
|
||||
len += scnprintf(buf + len, PAGE_SIZE - len,
|
||||
"Unknown\n");
|
||||
break;
|
||||
}
|
||||
if (phba->sli.sli_flag & LPFC_MENLO_MAINT)
|
||||
len += snprintf(buf + len, PAGE_SIZE-len,
|
||||
len += scnprintf(buf + len, PAGE_SIZE-len,
|
||||
" Menlo Maint Mode\n");
|
||||
else if (phba->fc_topology == LPFC_TOPOLOGY_LOOP) {
|
||||
if (vport->fc_flag & FC_PUBLIC_LOOP)
|
||||
len += snprintf(buf + len, PAGE_SIZE-len,
|
||||
len += scnprintf(buf + len, PAGE_SIZE-len,
|
||||
" Public Loop\n");
|
||||
else
|
||||
len += snprintf(buf + len, PAGE_SIZE-len,
|
||||
len += scnprintf(buf + len, PAGE_SIZE-len,
|
||||
" Private Loop\n");
|
||||
} else {
|
||||
if (vport->fc_flag & FC_FABRIC)
|
||||
len += snprintf(buf + len, PAGE_SIZE-len,
|
||||
len += scnprintf(buf + len, PAGE_SIZE-len,
|
||||
" Fabric\n");
|
||||
else
|
||||
len += snprintf(buf + len, PAGE_SIZE-len,
|
||||
len += scnprintf(buf + len, PAGE_SIZE-len,
|
||||
" Point-2-Point\n");
|
||||
}
|
||||
}
|
||||
@@ -937,28 +941,28 @@ lpfc_link_state_show(struct device *dev, struct device_attribute *attr,
|
||||
struct lpfc_trunk_link link = phba->trunk_link;
|
||||
|
||||
if (bf_get(lpfc_conf_trunk_port0, &phba->sli4_hba))
|
||||
len += snprintf(buf + len, PAGE_SIZE - len,
|
||||
len += scnprintf(buf + len, PAGE_SIZE - len,
|
||||
"Trunk port 0: Link %s %s\n",
|
||||
(link.link0.state == LPFC_LINK_UP) ?
|
||||
"Up" : "Down. ",
|
||||
trunk_errmsg[link.link0.fault]);
|
||||
|
||||
if (bf_get(lpfc_conf_trunk_port1, &phba->sli4_hba))
|
||||
len += snprintf(buf + len, PAGE_SIZE - len,
|
||||
len += scnprintf(buf + len, PAGE_SIZE - len,
|
||||
"Trunk port 1: Link %s %s\n",
|
||||
(link.link1.state == LPFC_LINK_UP) ?
|
||||
"Up" : "Down. ",
|
||||
trunk_errmsg[link.link1.fault]);
|
||||
|
||||
if (bf_get(lpfc_conf_trunk_port2, &phba->sli4_hba))
|
||||
len += snprintf(buf + len, PAGE_SIZE - len,
|
||||
len += scnprintf(buf + len, PAGE_SIZE - len,
|
||||
"Trunk port 2: Link %s %s\n",
|
||||
(link.link2.state == LPFC_LINK_UP) ?
|
||||
"Up" : "Down. ",
|
||||
trunk_errmsg[link.link2.fault]);
|
||||
|
||||
if (bf_get(lpfc_conf_trunk_port3, &phba->sli4_hba))
|
||||
len += snprintf(buf + len, PAGE_SIZE - len,
|
||||
len += scnprintf(buf + len, PAGE_SIZE - len,
|
||||
"Trunk port 3: Link %s %s\n",
|
||||
(link.link3.state == LPFC_LINK_UP) ?
|
||||
"Up" : "Down. ",
|
||||
@@ -986,15 +990,15 @@ lpfc_sli4_protocol_show(struct device *dev, struct device_attribute *attr,
|
||||
struct lpfc_hba *phba = vport->phba;
|
||||
|
||||
if (phba->sli_rev < LPFC_SLI_REV4)
|
||||
return snprintf(buf, PAGE_SIZE, "fc\n");
|
||||
return scnprintf(buf, PAGE_SIZE, "fc\n");
|
||||
|
||||
if (phba->sli4_hba.lnk_info.lnk_dv == LPFC_LNK_DAT_VAL) {
|
||||
if (phba->sli4_hba.lnk_info.lnk_tp == LPFC_LNK_TYPE_GE)
|
||||
return snprintf(buf, PAGE_SIZE, "fcoe\n");
|
||||
return scnprintf(buf, PAGE_SIZE, "fcoe\n");
|
||||
if (phba->sli4_hba.lnk_info.lnk_tp == LPFC_LNK_TYPE_FC)
|
||||
return snprintf(buf, PAGE_SIZE, "fc\n");
|
||||
return scnprintf(buf, PAGE_SIZE, "fc\n");
|
||||
}
|
||||
return snprintf(buf, PAGE_SIZE, "unknown\n");
|
||||
return scnprintf(buf, PAGE_SIZE, "unknown\n");
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1014,7 +1018,7 @@ lpfc_oas_supported_show(struct device *dev, struct device_attribute *attr,
|
||||
struct lpfc_vport *vport = (struct lpfc_vport *)shost->hostdata;
|
||||
struct lpfc_hba *phba = vport->phba;
|
||||
|
||||
return snprintf(buf, PAGE_SIZE, "%d\n",
|
||||
return scnprintf(buf, PAGE_SIZE, "%d\n",
|
||||
phba->sli4_hba.pc_sli4_params.oas_supported);
|
||||
}
|
||||
|
||||
@@ -1072,7 +1076,7 @@ lpfc_num_discovered_ports_show(struct device *dev,
|
||||
struct Scsi_Host *shost = class_to_shost(dev);
|
||||
struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
|
||||
|
||||
return snprintf(buf, PAGE_SIZE, "%d\n",
|
||||
return scnprintf(buf, PAGE_SIZE, "%d\n",
|
||||
vport->fc_map_cnt + vport->fc_unmap_cnt);
|
||||
}
|
||||
|
||||
@@ -1586,7 +1590,7 @@ lpfc_nport_evt_cnt_show(struct device *dev, struct device_attribute *attr,
|
||||
struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
|
||||
struct lpfc_hba *phba = vport->phba;
|
||||
|
||||
return snprintf(buf, PAGE_SIZE, "%d\n", phba->nport_event_cnt);
|
||||
return scnprintf(buf, PAGE_SIZE, "%d\n", phba->nport_event_cnt);
|
||||
}
|
||||
|
||||
int
|
||||
@@ -1675,7 +1679,7 @@ lpfc_board_mode_show(struct device *dev, struct device_attribute *attr,
|
||||
else
|
||||
state = "online";
|
||||
|
||||
return snprintf(buf, PAGE_SIZE, "%s\n", state);
|
||||
return scnprintf(buf, PAGE_SIZE, "%s\n", state);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1901,8 +1905,8 @@ lpfc_max_rpi_show(struct device *dev, struct device_attribute *attr,
|
||||
uint32_t cnt;
|
||||
|
||||
if (lpfc_get_hba_info(phba, NULL, NULL, &cnt, NULL, NULL, NULL))
|
||||
return snprintf(buf, PAGE_SIZE, "%d\n", cnt);
|
||||
return snprintf(buf, PAGE_SIZE, "Unknown\n");
|
||||
return scnprintf(buf, PAGE_SIZE, "%d\n", cnt);
|
||||
return scnprintf(buf, PAGE_SIZE, "Unknown\n");
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1929,8 +1933,8 @@ lpfc_used_rpi_show(struct device *dev, struct device_attribute *attr,
|
||||
uint32_t cnt, acnt;
|
||||
|
||||
if (lpfc_get_hba_info(phba, NULL, NULL, &cnt, &acnt, NULL, NULL))
|
||||
return snprintf(buf, PAGE_SIZE, "%d\n", (cnt - acnt));
|
||||
return snprintf(buf, PAGE_SIZE, "Unknown\n");
|
||||
return scnprintf(buf, PAGE_SIZE, "%d\n", (cnt - acnt));
|
||||
return scnprintf(buf, PAGE_SIZE, "Unknown\n");
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1957,8 +1961,8 @@ lpfc_max_xri_show(struct device *dev, struct device_attribute *attr,
|
||||
uint32_t cnt;
|
||||
|
||||
if (lpfc_get_hba_info(phba, &cnt, NULL, NULL, NULL, NULL, NULL))
|
||||
return snprintf(buf, PAGE_SIZE, "%d\n", cnt);
|
||||
return snprintf(buf, PAGE_SIZE, "Unknown\n");
|
||||
return scnprintf(buf, PAGE_SIZE, "%d\n", cnt);
|
||||
return scnprintf(buf, PAGE_SIZE, "Unknown\n");
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1985,8 +1989,8 @@ lpfc_used_xri_show(struct device *dev, struct device_attribute *attr,
|
||||
uint32_t cnt, acnt;
|
||||
|
||||
if (lpfc_get_hba_info(phba, &cnt, &acnt, NULL, NULL, NULL, NULL))
|
||||
return snprintf(buf, PAGE_SIZE, "%d\n", (cnt - acnt));
|
||||
return snprintf(buf, PAGE_SIZE, "Unknown\n");
|
||||
return scnprintf(buf, PAGE_SIZE, "%d\n", (cnt - acnt));
|
||||
return scnprintf(buf, PAGE_SIZE, "Unknown\n");
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2013,8 +2017,8 @@ lpfc_max_vpi_show(struct device *dev, struct device_attribute *attr,
|
||||
uint32_t cnt;
|
||||
|
||||
if (lpfc_get_hba_info(phba, NULL, NULL, NULL, NULL, &cnt, NULL))
|
||||
return snprintf(buf, PAGE_SIZE, "%d\n", cnt);
|
||||
return snprintf(buf, PAGE_SIZE, "Unknown\n");
|
||||
return scnprintf(buf, PAGE_SIZE, "%d\n", cnt);
|
||||
return scnprintf(buf, PAGE_SIZE, "Unknown\n");
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2041,8 +2045,8 @@ lpfc_used_vpi_show(struct device *dev, struct device_attribute *attr,
|
||||
uint32_t cnt, acnt;
|
||||
|
||||
if (lpfc_get_hba_info(phba, NULL, NULL, NULL, NULL, &cnt, &acnt))
|
||||
return snprintf(buf, PAGE_SIZE, "%d\n", (cnt - acnt));
|
||||
return snprintf(buf, PAGE_SIZE, "Unknown\n");
|
||||
return scnprintf(buf, PAGE_SIZE, "%d\n", (cnt - acnt));
|
||||
return scnprintf(buf, PAGE_SIZE, "Unknown\n");
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2067,10 +2071,10 @@ lpfc_npiv_info_show(struct device *dev, struct device_attribute *attr,
|
||||
struct lpfc_hba *phba = vport->phba;
|
||||
|
||||
if (!(phba->max_vpi))
|
||||
return snprintf(buf, PAGE_SIZE, "NPIV Not Supported\n");
|
||||
return scnprintf(buf, PAGE_SIZE, "NPIV Not Supported\n");
|
||||
if (vport->port_type == LPFC_PHYSICAL_PORT)
|
||||
return snprintf(buf, PAGE_SIZE, "NPIV Physical\n");
|
||||
return snprintf(buf, PAGE_SIZE, "NPIV Virtual (VPI %d)\n", vport->vpi);
|
||||
return scnprintf(buf, PAGE_SIZE, "NPIV Physical\n");
|
||||
return scnprintf(buf, PAGE_SIZE, "NPIV Virtual (VPI %d)\n", vport->vpi);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2092,7 +2096,7 @@ lpfc_poll_show(struct device *dev, struct device_attribute *attr,
|
||||
struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
|
||||
struct lpfc_hba *phba = vport->phba;
|
||||
|
||||
return snprintf(buf, PAGE_SIZE, "%#x\n", phba->cfg_poll);
|
||||
return scnprintf(buf, PAGE_SIZE, "%#x\n", phba->cfg_poll);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2196,7 +2200,7 @@ lpfc_fips_level_show(struct device *dev, struct device_attribute *attr,
|
||||
struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
|
||||
struct lpfc_hba *phba = vport->phba;
|
||||
|
||||
return snprintf(buf, PAGE_SIZE, "%d\n", phba->fips_level);
|
||||
return scnprintf(buf, PAGE_SIZE, "%d\n", phba->fips_level);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2215,7 +2219,7 @@ lpfc_fips_rev_show(struct device *dev, struct device_attribute *attr,
|
||||
struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
|
||||
struct lpfc_hba *phba = vport->phba;
|
||||
|
||||
return snprintf(buf, PAGE_SIZE, "%d\n", phba->fips_spec_rev);
|
||||
return scnprintf(buf, PAGE_SIZE, "%d\n", phba->fips_spec_rev);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2234,7 +2238,7 @@ lpfc_dss_show(struct device *dev, struct device_attribute *attr,
|
||||
struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
|
||||
struct lpfc_hba *phba = vport->phba;
|
||||
|
||||
return snprintf(buf, PAGE_SIZE, "%s - %sOperational\n",
|
||||
return scnprintf(buf, PAGE_SIZE, "%s - %sOperational\n",
|
||||
(phba->cfg_enable_dss) ? "Enabled" : "Disabled",
|
||||
(phba->sli3_options & LPFC_SLI3_DSS_ENABLED) ?
|
||||
"" : "Not ");
|
||||
@@ -2263,7 +2267,7 @@ lpfc_sriov_hw_max_virtfn_show(struct device *dev,
|
||||
uint16_t max_nr_virtfn;
|
||||
|
||||
max_nr_virtfn = lpfc_sli_sriov_nr_virtfn_get(phba);
|
||||
return snprintf(buf, PAGE_SIZE, "%d\n", max_nr_virtfn);
|
||||
return scnprintf(buf, PAGE_SIZE, "%d\n", max_nr_virtfn);
|
||||
}
|
||||
|
||||
static inline bool lpfc_rangecheck(uint val, uint min, uint max)
|
||||
@@ -2323,7 +2327,7 @@ lpfc_##attr##_show(struct device *dev, struct device_attribute *attr, \
|
||||
struct Scsi_Host *shost = class_to_shost(dev);\
|
||||
struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;\
|
||||
struct lpfc_hba *phba = vport->phba;\
|
||||
return snprintf(buf, PAGE_SIZE, "%d\n",\
|
||||
return scnprintf(buf, PAGE_SIZE, "%d\n",\
|
||||
phba->cfg_##attr);\
|
||||
}
|
||||
|
||||
@@ -2351,7 +2355,7 @@ lpfc_##attr##_show(struct device *dev, struct device_attribute *attr, \
|
||||
struct lpfc_hba *phba = vport->phba;\
|
||||
uint val = 0;\
|
||||
val = phba->cfg_##attr;\
|
||||
return snprintf(buf, PAGE_SIZE, "%#x\n",\
|
||||
return scnprintf(buf, PAGE_SIZE, "%#x\n",\
|
||||
phba->cfg_##attr);\
|
||||
}
|
||||
|
||||
@@ -2487,7 +2491,7 @@ lpfc_##attr##_show(struct device *dev, struct device_attribute *attr, \
|
||||
{ \
|
||||
struct Scsi_Host *shost = class_to_shost(dev);\
|
||||
struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;\
|
||||
return snprintf(buf, PAGE_SIZE, "%d\n", vport->cfg_##attr);\
|
||||
return scnprintf(buf, PAGE_SIZE, "%d\n", vport->cfg_##attr);\
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2512,7 +2516,7 @@ lpfc_##attr##_show(struct device *dev, struct device_attribute *attr, \
|
||||
{ \
|
||||
struct Scsi_Host *shost = class_to_shost(dev);\
|
||||
struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;\
|
||||
return snprintf(buf, PAGE_SIZE, "%#x\n", vport->cfg_##attr);\
|
||||
return scnprintf(buf, PAGE_SIZE, "%#x\n", vport->cfg_##attr);\
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2784,7 +2788,7 @@ lpfc_soft_wwpn_show(struct device *dev, struct device_attribute *attr,
|
||||
struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
|
||||
struct lpfc_hba *phba = vport->phba;
|
||||
|
||||
return snprintf(buf, PAGE_SIZE, "0x%llx\n",
|
||||
return scnprintf(buf, PAGE_SIZE, "0x%llx\n",
|
||||
(unsigned long long)phba->cfg_soft_wwpn);
|
||||
}
|
||||
|
||||
@@ -2881,7 +2885,7 @@ lpfc_soft_wwnn_show(struct device *dev, struct device_attribute *attr,
|
||||
{
|
||||
struct Scsi_Host *shost = class_to_shost(dev);
|
||||
struct lpfc_hba *phba = ((struct lpfc_vport *)shost->hostdata)->phba;
|
||||
return snprintf(buf, PAGE_SIZE, "0x%llx\n",
|
||||
return scnprintf(buf, PAGE_SIZE, "0x%llx\n",
|
||||
(unsigned long long)phba->cfg_soft_wwnn);
|
||||
}
|
||||
|
||||
@@ -2947,7 +2951,7 @@ lpfc_oas_tgt_show(struct device *dev, struct device_attribute *attr,
|
||||
struct Scsi_Host *shost = class_to_shost(dev);
|
||||
struct lpfc_hba *phba = ((struct lpfc_vport *)shost->hostdata)->phba;
|
||||
|
||||
return snprintf(buf, PAGE_SIZE, "0x%llx\n",
|
||||
return scnprintf(buf, PAGE_SIZE, "0x%llx\n",
|
||||
wwn_to_u64(phba->cfg_oas_tgt_wwpn));
|
||||
}
|
||||
|
||||
@@ -3015,7 +3019,7 @@ lpfc_oas_priority_show(struct device *dev, struct device_attribute *attr,
|
||||
struct Scsi_Host *shost = class_to_shost(dev);
|
||||
struct lpfc_hba *phba = ((struct lpfc_vport *)shost->hostdata)->phba;
|
||||
|
||||
return snprintf(buf, PAGE_SIZE, "%d\n", phba->cfg_oas_priority);
|
||||
return scnprintf(buf, PAGE_SIZE, "%d\n", phba->cfg_oas_priority);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -3078,7 +3082,7 @@ lpfc_oas_vpt_show(struct device *dev, struct device_attribute *attr,
|
||||
struct Scsi_Host *shost = class_to_shost(dev);
|
||||
struct lpfc_hba *phba = ((struct lpfc_vport *)shost->hostdata)->phba;
|
||||
|
||||
return snprintf(buf, PAGE_SIZE, "0x%llx\n",
|
||||
return scnprintf(buf, PAGE_SIZE, "0x%llx\n",
|
||||
wwn_to_u64(phba->cfg_oas_vpt_wwpn));
|
||||
}
|
||||
|
||||
@@ -3149,7 +3153,7 @@ lpfc_oas_lun_state_show(struct device *dev, struct device_attribute *attr,
|
||||
struct Scsi_Host *shost = class_to_shost(dev);
|
||||
struct lpfc_hba *phba = ((struct lpfc_vport *)shost->hostdata)->phba;
|
||||
|
||||
return snprintf(buf, PAGE_SIZE, "%d\n", phba->cfg_oas_lun_state);
|
||||
return scnprintf(buf, PAGE_SIZE, "%d\n", phba->cfg_oas_lun_state);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -3213,7 +3217,7 @@ lpfc_oas_lun_status_show(struct device *dev, struct device_attribute *attr,
|
||||
if (!(phba->cfg_oas_flags & OAS_LUN_VALID))
|
||||
return -EFAULT;
|
||||
|
||||
return snprintf(buf, PAGE_SIZE, "%d\n", phba->cfg_oas_lun_status);
|
||||
return scnprintf(buf, PAGE_SIZE, "%d\n", phba->cfg_oas_lun_status);
|
||||
}
|
||||
static DEVICE_ATTR(lpfc_xlane_lun_status, S_IRUGO,
|
||||
lpfc_oas_lun_status_show, NULL);
|
||||
@@ -3365,7 +3369,7 @@ lpfc_oas_lun_show(struct device *dev, struct device_attribute *attr,
|
||||
if (oas_lun != NOT_OAS_ENABLED_LUN)
|
||||
phba->cfg_oas_flags |= OAS_LUN_VALID;
|
||||
|
||||
len += snprintf(buf + len, PAGE_SIZE-len, "0x%llx", oas_lun);
|
||||
len += scnprintf(buf + len, PAGE_SIZE-len, "0x%llx", oas_lun);
|
||||
|
||||
return len;
|
||||
}
|
||||
@@ -3499,7 +3503,7 @@ lpfc_iocb_hw_show(struct device *dev, struct device_attribute *attr, char *buf)
|
||||
struct Scsi_Host *shost = class_to_shost(dev);
|
||||
struct lpfc_hba *phba = ((struct lpfc_vport *) shost->hostdata)->phba;
|
||||
|
||||
return snprintf(buf, PAGE_SIZE, "%d\n", phba->iocb_max);
|
||||
return scnprintf(buf, PAGE_SIZE, "%d\n", phba->iocb_max);
|
||||
}
|
||||
|
||||
static DEVICE_ATTR(iocb_hw, S_IRUGO,
|
||||
@@ -3511,7 +3515,7 @@ lpfc_txq_hw_show(struct device *dev, struct device_attribute *attr, char *buf)
|
||||
struct lpfc_hba *phba = ((struct lpfc_vport *) shost->hostdata)->phba;
|
||||
struct lpfc_sli_ring *pring = lpfc_phba_elsring(phba);
|
||||
|
||||
return snprintf(buf, PAGE_SIZE, "%d\n",
|
||||
return scnprintf(buf, PAGE_SIZE, "%d\n",
|
||||
pring ? pring->txq_max : 0);
|
||||
}
|
||||
|
||||
@@ -3525,7 +3529,7 @@ lpfc_txcmplq_hw_show(struct device *dev, struct device_attribute *attr,
|
||||
struct lpfc_hba *phba = ((struct lpfc_vport *) shost->hostdata)->phba;
|
||||
struct lpfc_sli_ring *pring = lpfc_phba_elsring(phba);
|
||||
|
||||
return snprintf(buf, PAGE_SIZE, "%d\n",
|
||||
return scnprintf(buf, PAGE_SIZE, "%d\n",
|
||||
pring ? pring->txcmplq_max : 0);
|
||||
}
|
||||
|
||||
@@ -3561,7 +3565,7 @@ lpfc_nodev_tmo_show(struct device *dev, struct device_attribute *attr,
|
||||
struct Scsi_Host *shost = class_to_shost(dev);
|
||||
struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
|
||||
|
||||
return snprintf(buf, PAGE_SIZE, "%d\n", vport->cfg_devloss_tmo);
|
||||
return scnprintf(buf, PAGE_SIZE, "%d\n", vport->cfg_devloss_tmo);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -5169,12 +5173,12 @@ lpfc_fcp_cpu_map_show(struct device *dev, struct device_attribute *attr,
|
||||
|
||||
switch (phba->cfg_fcp_cpu_map) {
|
||||
case 0:
|
||||
len += snprintf(buf + len, PAGE_SIZE-len,
|
||||
len += scnprintf(buf + len, PAGE_SIZE-len,
|
||||
"fcp_cpu_map: No mapping (%d)\n",
|
||||
phba->cfg_fcp_cpu_map);
|
||||
return len;
|
||||
case 1:
|
||||
len += snprintf(buf + len, PAGE_SIZE-len,
|
||||
len += scnprintf(buf + len, PAGE_SIZE-len,
|
||||
"fcp_cpu_map: HBA centric mapping (%d): "
|
||||
"%d of %d CPUs online from %d possible CPUs\n",
|
||||
phba->cfg_fcp_cpu_map, num_online_cpus(),
|
||||
@@ -5188,12 +5192,12 @@ lpfc_fcp_cpu_map_show(struct device *dev, struct device_attribute *attr,
|
||||
cpup = &phba->sli4_hba.cpu_map[phba->sli4_hba.curr_disp_cpu];
|
||||
|
||||
if (!cpu_present(phba->sli4_hba.curr_disp_cpu))
|
||||
len += snprintf(buf + len, PAGE_SIZE - len,
|
||||
len += scnprintf(buf + len, PAGE_SIZE - len,
|
||||
"CPU %02d not present\n",
|
||||
phba->sli4_hba.curr_disp_cpu);
|
||||
else if (cpup->irq == LPFC_VECTOR_MAP_EMPTY) {
|
||||
if (cpup->hdwq == LPFC_VECTOR_MAP_EMPTY)
|
||||
len += snprintf(
|
||||
len += scnprintf(
|
||||
buf + len, PAGE_SIZE - len,
|
||||
"CPU %02d hdwq None "
|
||||
"physid %d coreid %d ht %d\n",
|
||||
@@ -5201,7 +5205,7 @@ lpfc_fcp_cpu_map_show(struct device *dev, struct device_attribute *attr,
|
||||
cpup->phys_id,
|
||||
cpup->core_id, cpup->hyper);
|
||||
else
|
||||
len += snprintf(
|
||||
len += scnprintf(
|
||||
buf + len, PAGE_SIZE - len,
|
||||
"CPU %02d EQ %04d hdwq %04d "
|
||||
"physid %d coreid %d ht %d\n",
|
||||
@@ -5210,7 +5214,7 @@ lpfc_fcp_cpu_map_show(struct device *dev, struct device_attribute *attr,
|
||||
cpup->core_id, cpup->hyper);
|
||||
} else {
|
||||
if (cpup->hdwq == LPFC_VECTOR_MAP_EMPTY)
|
||||
len += snprintf(
|
||||
len += scnprintf(
|
||||
buf + len, PAGE_SIZE - len,
|
||||
"CPU %02d hdwq None "
|
||||
"physid %d coreid %d ht %d IRQ %d\n",
|
||||
@@ -5218,7 +5222,7 @@ lpfc_fcp_cpu_map_show(struct device *dev, struct device_attribute *attr,
|
||||
cpup->phys_id,
|
||||
cpup->core_id, cpup->hyper, cpup->irq);
|
||||
else
|
||||
len += snprintf(
|
||||
len += scnprintf(
|
||||
buf + len, PAGE_SIZE - len,
|
||||
"CPU %02d EQ %04d hdwq %04d "
|
||||
"physid %d coreid %d ht %d IRQ %d\n",
|
||||
@@ -5233,7 +5237,7 @@ lpfc_fcp_cpu_map_show(struct device *dev, struct device_attribute *attr,
|
||||
if (phba->sli4_hba.curr_disp_cpu <
|
||||
phba->sli4_hba.num_possible_cpu &&
|
||||
(len >= (PAGE_SIZE - 64))) {
|
||||
len += snprintf(buf + len,
|
||||
len += scnprintf(buf + len,
|
||||
PAGE_SIZE - len, "more...\n");
|
||||
break;
|
||||
}
|
||||
@@ -5753,10 +5757,10 @@ lpfc_sg_seg_cnt_show(struct device *dev, struct device_attribute *attr,
|
||||
struct lpfc_hba *phba = vport->phba;
|
||||
int len;
|
||||
|
||||
len = snprintf(buf, PAGE_SIZE, "SGL sz: %d total SGEs: %d\n",
|
||||
len = scnprintf(buf, PAGE_SIZE, "SGL sz: %d total SGEs: %d\n",
|
||||
phba->cfg_sg_dma_buf_size, phba->cfg_total_seg_cnt);
|
||||
|
||||
len += snprintf(buf + len, PAGE_SIZE, "Cfg: %d SCSI: %d NVME: %d\n",
|
||||
len += scnprintf(buf + len, PAGE_SIZE, "Cfg: %d SCSI: %d NVME: %d\n",
|
||||
phba->cfg_sg_seg_cnt, phba->cfg_scsi_seg_cnt,
|
||||
phba->cfg_nvme_seg_cnt);
|
||||
return len;
|
||||
@@ -6755,7 +6759,7 @@ lpfc_show_rport_##field (struct device *dev, \
|
||||
{ \
|
||||
struct fc_rport *rport = transport_class_to_rport(dev); \
|
||||
struct lpfc_rport_data *rdata = rport->hostdata; \
|
||||
return snprintf(buf, sz, format_string, \
|
||||
return scnprintf(buf, sz, format_string, \
|
||||
(rdata->target) ? cast rdata->target->field : 0); \
|
||||
}
|
||||
|
||||
|
||||
@@ -1430,7 +1430,7 @@ lpfc_vport_symbolic_port_name(struct lpfc_vport *vport, char *symbol,
|
||||
* Name object. NPIV is not in play so this integer
|
||||
* value is sufficient and unique per FC-ID.
|
||||
*/
|
||||
n = snprintf(symbol, size, "%d", vport->phba->brd_no);
|
||||
n = scnprintf(symbol, size, "%d", vport->phba->brd_no);
|
||||
return n;
|
||||
}
|
||||
|
||||
@@ -1444,26 +1444,26 @@ lpfc_vport_symbolic_node_name(struct lpfc_vport *vport, char *symbol,
|
||||
|
||||
lpfc_decode_firmware_rev(vport->phba, fwrev, 0);
|
||||
|
||||
n = snprintf(symbol, size, "Emulex %s", vport->phba->ModelName);
|
||||
n = scnprintf(symbol, size, "Emulex %s", vport->phba->ModelName);
|
||||
if (size < n)
|
||||
return n;
|
||||
|
||||
n += snprintf(symbol + n, size - n, " FV%s", fwrev);
|
||||
n += scnprintf(symbol + n, size - n, " FV%s", fwrev);
|
||||
if (size < n)
|
||||
return n;
|
||||
|
||||
n += snprintf(symbol + n, size - n, " DV%s.",
|
||||
n += scnprintf(symbol + n, size - n, " DV%s.",
|
||||
lpfc_release_version);
|
||||
if (size < n)
|
||||
return n;
|
||||
|
||||
n += snprintf(symbol + n, size - n, " HN:%s.",
|
||||
n += scnprintf(symbol + n, size - n, " HN:%s.",
|
||||
init_utsname()->nodename);
|
||||
if (size < n)
|
||||
return n;
|
||||
|
||||
/* Note :- OS name is "Linux" */
|
||||
n += snprintf(symbol + n, size - n, " OS:%s\n",
|
||||
n += scnprintf(symbol + n, size - n, " OS:%s\n",
|
||||
init_utsname()->sysname);
|
||||
return n;
|
||||
}
|
||||
|
||||
+240
-234
File diff suppressed because it is too large
Load Diff
@@ -348,7 +348,7 @@ lpfc_debug_dump_qe(struct lpfc_queue *q, uint32_t idx)
|
||||
pword = q->qe[idx].address;
|
||||
|
||||
len = 0;
|
||||
len += snprintf(line_buf+len, LPFC_LBUF_SZ-len, "QE[%04d]: ", idx);
|
||||
len += scnprintf(line_buf+len, LPFC_LBUF_SZ-len, "QE[%04d]: ", idx);
|
||||
if (qe_word_cnt > 8)
|
||||
printk(KERN_ERR "%s\n", line_buf);
|
||||
|
||||
@@ -359,11 +359,11 @@ lpfc_debug_dump_qe(struct lpfc_queue *q, uint32_t idx)
|
||||
if (qe_word_cnt > 8) {
|
||||
len = 0;
|
||||
memset(line_buf, 0, LPFC_LBUF_SZ);
|
||||
len += snprintf(line_buf+len, LPFC_LBUF_SZ-len,
|
||||
len += scnprintf(line_buf+len, LPFC_LBUF_SZ-len,
|
||||
"%03d: ", i);
|
||||
}
|
||||
}
|
||||
len += snprintf(line_buf+len, LPFC_LBUF_SZ-len, "%08x ",
|
||||
len += scnprintf(line_buf+len, LPFC_LBUF_SZ-len, "%08x ",
|
||||
((uint32_t)*pword) & 0xffffffff);
|
||||
pword++;
|
||||
}
|
||||
|
||||
@@ -364,7 +364,7 @@ qla2x00_sysfs_write_optrom_ctl(struct file *filp, struct kobject *kobj,
|
||||
}
|
||||
|
||||
ha->optrom_region_start = start;
|
||||
ha->optrom_region_size = start + size;
|
||||
ha->optrom_region_size = size;
|
||||
|
||||
ha->optrom_state = QLA_SREADING;
|
||||
ha->optrom_buffer = vmalloc(ha->optrom_region_size);
|
||||
@@ -437,7 +437,7 @@ qla2x00_sysfs_write_optrom_ctl(struct file *filp, struct kobject *kobj,
|
||||
}
|
||||
|
||||
ha->optrom_region_start = start;
|
||||
ha->optrom_region_size = start + size;
|
||||
ha->optrom_region_size = size;
|
||||
|
||||
ha->optrom_state = QLA_SWRITING;
|
||||
ha->optrom_buffer = vmalloc(ha->optrom_region_size);
|
||||
|
||||
@@ -615,7 +615,6 @@ static void qla_nvme_unregister_remote_port(struct work_struct *work)
|
||||
struct fc_port *fcport = container_of(work, struct fc_port,
|
||||
nvme_del_work);
|
||||
struct qla_nvme_rport *qla_rport, *trport;
|
||||
scsi_qla_host_t *base_vha;
|
||||
|
||||
if (!IS_ENABLED(CONFIG_NVME_FC))
|
||||
return;
|
||||
@@ -623,23 +622,19 @@ static void qla_nvme_unregister_remote_port(struct work_struct *work)
|
||||
ql_log(ql_log_warn, NULL, 0x2112,
|
||||
"%s: unregister remoteport on %p\n",__func__, fcport);
|
||||
|
||||
base_vha = pci_get_drvdata(fcport->vha->hw->pdev);
|
||||
if (test_bit(PFLG_DRIVER_REMOVING, &base_vha->pci_flags)) {
|
||||
ql_dbg(ql_dbg_disc, fcport->vha, 0x2114,
|
||||
"%s: Notify FC-NVMe transport, set devloss=0\n",
|
||||
__func__);
|
||||
|
||||
nvme_fc_set_remoteport_devloss(fcport->nvme_remote_port, 0);
|
||||
}
|
||||
|
||||
list_for_each_entry_safe(qla_rport, trport,
|
||||
&fcport->vha->nvme_rport_list, list) {
|
||||
if (qla_rport->fcport == fcport) {
|
||||
ql_log(ql_log_info, fcport->vha, 0x2113,
|
||||
"%s: fcport=%p\n", __func__, fcport);
|
||||
nvme_fc_set_remoteport_devloss
|
||||
(fcport->nvme_remote_port, 0);
|
||||
init_completion(&fcport->nvme_del_done);
|
||||
nvme_fc_unregister_remoteport(
|
||||
fcport->nvme_remote_port);
|
||||
if (nvme_fc_unregister_remoteport
|
||||
(fcport->nvme_remote_port))
|
||||
ql_log(ql_log_info, fcport->vha, 0x2114,
|
||||
"%s: Failed to unregister nvme_remote_port\n",
|
||||
__func__);
|
||||
wait_for_completion(&fcport->nvme_del_done);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -980,6 +980,8 @@ void qlt_free_session_done(struct work_struct *work)
|
||||
sess->send_els_logo);
|
||||
|
||||
if (!IS_SW_RESV_ADDR(sess->d_id)) {
|
||||
qla2x00_mark_device_lost(vha, sess, 0, 0);
|
||||
|
||||
if (sess->send_els_logo) {
|
||||
qlt_port_logo_t logo;
|
||||
|
||||
@@ -1160,8 +1162,6 @@ void qlt_unreg_sess(struct fc_port *sess)
|
||||
if (sess->se_sess)
|
||||
vha->hw->tgt.tgt_ops->clear_nacl_from_fcport_map(sess);
|
||||
|
||||
qla2x00_mark_device_lost(vha, sess, 0, 0);
|
||||
|
||||
sess->deleted = QLA_SESS_DELETION_IN_PROGRESS;
|
||||
sess->disc_state = DSC_DELETE_PEND;
|
||||
sess->last_rscn_gen = sess->rscn_gen;
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
config SUNXI_SRAM
|
||||
bool
|
||||
default ARCH_SUNXI
|
||||
select REGMAP_MMIO
|
||||
help
|
||||
Say y here to enable the SRAM controller support. This
|
||||
device is responsible on mapping the SRAM in the sunXi SoCs
|
||||
|
||||
@@ -520,7 +520,7 @@ static int gb_power_supply_prop_descriptors_get(struct gb_power_supply *gbpsy)
|
||||
|
||||
op = gb_operation_create(connection,
|
||||
GB_POWER_SUPPLY_TYPE_GET_PROP_DESCRIPTORS,
|
||||
sizeof(req), sizeof(*resp) + props_count *
|
||||
sizeof(*req), sizeof(*resp) + props_count *
|
||||
sizeof(struct gb_power_supply_props_desc),
|
||||
GFP_KERNEL);
|
||||
if (!op)
|
||||
|
||||
@@ -549,7 +549,7 @@ static void __exit mod_exit(void)
|
||||
destroy_cdev(c);
|
||||
destroy_channel(c);
|
||||
}
|
||||
unregister_chrdev_region(comp.devno, 1);
|
||||
unregister_chrdev_region(comp.devno, CHRDEV_REGION_SIZE);
|
||||
ida_destroy(&comp.minor_id);
|
||||
class_destroy(comp.class);
|
||||
}
|
||||
|
||||
@@ -622,7 +622,7 @@ static int audio_probe_channel(struct most_interface *iface, int channel_id,
|
||||
INIT_LIST_HEAD(&adpt->dev_list);
|
||||
iface->priv = adpt;
|
||||
list_add_tail(&adpt->list, &adpt_list);
|
||||
ret = snd_card_new(&iface->dev, -1, "INIC", THIS_MODULE,
|
||||
ret = snd_card_new(iface->driver_dev, -1, "INIC", THIS_MODULE,
|
||||
sizeof(*channel), &adpt->card);
|
||||
if (ret < 0)
|
||||
goto err_free_adpt;
|
||||
|
||||
@@ -708,7 +708,7 @@ static void wilc_set_multicast_list(struct net_device *dev)
|
||||
return;
|
||||
}
|
||||
|
||||
mc_list = kmalloc_array(dev->mc.count, ETH_ALEN, GFP_KERNEL);
|
||||
mc_list = kmalloc_array(dev->mc.count, ETH_ALEN, GFP_ATOMIC);
|
||||
if (!mc_list)
|
||||
return;
|
||||
|
||||
|
||||
@@ -470,12 +470,12 @@ static void acm_read_bulk_callback(struct urb *urb)
|
||||
struct acm *acm = rb->instance;
|
||||
unsigned long flags;
|
||||
int status = urb->status;
|
||||
bool stopped = false;
|
||||
bool stalled = false;
|
||||
|
||||
dev_vdbg(&acm->data->dev, "got urb %d, len %d, status %d\n",
|
||||
rb->index, urb->actual_length, status);
|
||||
|
||||
set_bit(rb->index, &acm->read_urbs_free);
|
||||
|
||||
if (!acm->dev) {
|
||||
dev_dbg(&acm->data->dev, "%s - disconnected\n", __func__);
|
||||
return;
|
||||
@@ -488,15 +488,16 @@ static void acm_read_bulk_callback(struct urb *urb)
|
||||
break;
|
||||
case -EPIPE:
|
||||
set_bit(EVENT_RX_STALL, &acm->flags);
|
||||
schedule_work(&acm->work);
|
||||
return;
|
||||
stalled = true;
|
||||
break;
|
||||
case -ENOENT:
|
||||
case -ECONNRESET:
|
||||
case -ESHUTDOWN:
|
||||
dev_dbg(&acm->data->dev,
|
||||
"%s - urb shutting down with status: %d\n",
|
||||
__func__, status);
|
||||
return;
|
||||
stopped = true;
|
||||
break;
|
||||
default:
|
||||
dev_dbg(&acm->data->dev,
|
||||
"%s - nonzero urb status received: %d\n",
|
||||
@@ -505,10 +506,24 @@ static void acm_read_bulk_callback(struct urb *urb)
|
||||
}
|
||||
|
||||
/*
|
||||
* Unthrottle may run on another CPU which needs to see events
|
||||
* in the same order. Submission has an implict barrier
|
||||
* Make sure URB processing is done before marking as free to avoid
|
||||
* racing with unthrottle() on another CPU. Matches the barriers
|
||||
* implied by the test_and_clear_bit() in acm_submit_read_urb().
|
||||
*/
|
||||
smp_mb__before_atomic();
|
||||
set_bit(rb->index, &acm->read_urbs_free);
|
||||
/*
|
||||
* Make sure URB is marked as free before checking the throttled flag
|
||||
* to avoid racing with unthrottle() on another CPU. Matches the
|
||||
* smp_mb() in unthrottle().
|
||||
*/
|
||||
smp_mb__after_atomic();
|
||||
|
||||
if (stopped || stalled) {
|
||||
if (stalled)
|
||||
schedule_work(&acm->work);
|
||||
return;
|
||||
}
|
||||
|
||||
/* throttle device if requested by tty */
|
||||
spin_lock_irqsave(&acm->read_lock, flags);
|
||||
@@ -842,6 +857,9 @@ static void acm_tty_unthrottle(struct tty_struct *tty)
|
||||
acm->throttle_req = 0;
|
||||
spin_unlock_irq(&acm->read_lock);
|
||||
|
||||
/* Matches the smp_mb__after_atomic() in acm_read_bulk_callback(). */
|
||||
smp_mb();
|
||||
|
||||
if (was_throttled)
|
||||
acm_submit_read_urbs(acm, GFP_KERNEL);
|
||||
}
|
||||
|
||||
@@ -54,7 +54,8 @@ comment "Platform Glue Driver Support"
|
||||
|
||||
config USB_DWC3_OMAP
|
||||
tristate "Texas Instruments OMAP5 and similar Platforms"
|
||||
depends on EXTCON && (ARCH_OMAP2PLUS || COMPILE_TEST)
|
||||
depends on ARCH_OMAP2PLUS || COMPILE_TEST
|
||||
depends on EXTCON || !EXTCON
|
||||
depends on OF
|
||||
default USB_DWC3
|
||||
help
|
||||
@@ -115,7 +116,8 @@ config USB_DWC3_ST
|
||||
|
||||
config USB_DWC3_QCOM
|
||||
tristate "Qualcomm Platform"
|
||||
depends on EXTCON && (ARCH_QCOM || COMPILE_TEST)
|
||||
depends on ARCH_QCOM || COMPILE_TEST
|
||||
depends on EXTCON || !EXTCON
|
||||
depends on OF
|
||||
default USB_DWC3
|
||||
help
|
||||
|
||||
@@ -1218,7 +1218,7 @@ static void dwc3_get_properties(struct dwc3 *dwc)
|
||||
u8 tx_max_burst_prd;
|
||||
|
||||
/* default to highest possible threshold */
|
||||
lpm_nyet_threshold = 0xff;
|
||||
lpm_nyet_threshold = 0xf;
|
||||
|
||||
/* default to -3.5dB de-emphasis */
|
||||
tx_de_emphasis = 1;
|
||||
|
||||
@@ -67,7 +67,7 @@ config USB_MUSB_SUNXI
|
||||
depends on NOP_USB_XCEIV
|
||||
depends on PHY_SUN4I_USB
|
||||
depends on EXTCON
|
||||
depends on GENERIC_PHY
|
||||
select GENERIC_PHY
|
||||
select SUNXI_SRAM
|
||||
|
||||
config USB_MUSB_DAVINCI
|
||||
|
||||
@@ -556,9 +556,12 @@ static int f81232_open(struct tty_struct *tty, struct usb_serial_port *port)
|
||||
|
||||
static void f81232_close(struct usb_serial_port *port)
|
||||
{
|
||||
struct f81232_private *port_priv = usb_get_serial_port_data(port);
|
||||
|
||||
f81232_port_disable(port);
|
||||
usb_serial_generic_close(port);
|
||||
usb_kill_urb(port->interrupt_in_urb);
|
||||
flush_work(&port_priv->interrupt_work);
|
||||
}
|
||||
|
||||
static void f81232_dtr_rts(struct usb_serial_port *port, int on)
|
||||
@@ -632,6 +635,40 @@ static int f81232_port_remove(struct usb_serial_port *port)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int f81232_suspend(struct usb_serial *serial, pm_message_t message)
|
||||
{
|
||||
struct usb_serial_port *port = serial->port[0];
|
||||
struct f81232_private *port_priv = usb_get_serial_port_data(port);
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(port->read_urbs); ++i)
|
||||
usb_kill_urb(port->read_urbs[i]);
|
||||
|
||||
usb_kill_urb(port->interrupt_in_urb);
|
||||
|
||||
if (port_priv)
|
||||
flush_work(&port_priv->interrupt_work);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int f81232_resume(struct usb_serial *serial)
|
||||
{
|
||||
struct usb_serial_port *port = serial->port[0];
|
||||
int result;
|
||||
|
||||
if (tty_port_initialized(&port->port)) {
|
||||
result = usb_submit_urb(port->interrupt_in_urb, GFP_NOIO);
|
||||
if (result) {
|
||||
dev_err(&port->dev, "submit interrupt urb failed: %d\n",
|
||||
result);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
return usb_serial_generic_resume(serial);
|
||||
}
|
||||
|
||||
static struct usb_serial_driver f81232_device = {
|
||||
.driver = {
|
||||
.owner = THIS_MODULE,
|
||||
@@ -655,6 +692,8 @@ static struct usb_serial_driver f81232_device = {
|
||||
.read_int_callback = f81232_read_int_callback,
|
||||
.port_probe = f81232_port_probe,
|
||||
.port_remove = f81232_port_remove,
|
||||
.suspend = f81232_suspend,
|
||||
.resume = f81232_resume,
|
||||
};
|
||||
|
||||
static struct usb_serial_driver * const serial_drivers[] = {
|
||||
|
||||
@@ -376,6 +376,7 @@ void usb_serial_generic_read_bulk_callback(struct urb *urb)
|
||||
struct usb_serial_port *port = urb->context;
|
||||
unsigned char *data = urb->transfer_buffer;
|
||||
unsigned long flags;
|
||||
bool stopped = false;
|
||||
int status = urb->status;
|
||||
int i;
|
||||
|
||||
@@ -383,33 +384,51 @@ void usb_serial_generic_read_bulk_callback(struct urb *urb)
|
||||
if (urb == port->read_urbs[i])
|
||||
break;
|
||||
}
|
||||
set_bit(i, &port->read_urbs_free);
|
||||
|
||||
dev_dbg(&port->dev, "%s - urb %d, len %d\n", __func__, i,
|
||||
urb->actual_length);
|
||||
switch (status) {
|
||||
case 0:
|
||||
usb_serial_debug_data(&port->dev, __func__, urb->actual_length,
|
||||
data);
|
||||
port->serial->type->process_read_urb(urb);
|
||||
break;
|
||||
case -ENOENT:
|
||||
case -ECONNRESET:
|
||||
case -ESHUTDOWN:
|
||||
dev_dbg(&port->dev, "%s - urb stopped: %d\n",
|
||||
__func__, status);
|
||||
return;
|
||||
stopped = true;
|
||||
break;
|
||||
case -EPIPE:
|
||||
dev_err(&port->dev, "%s - urb stopped: %d\n",
|
||||
__func__, status);
|
||||
return;
|
||||
stopped = true;
|
||||
break;
|
||||
default:
|
||||
dev_dbg(&port->dev, "%s - nonzero urb status: %d\n",
|
||||
__func__, status);
|
||||
goto resubmit;
|
||||
break;
|
||||
}
|
||||
|
||||
usb_serial_debug_data(&port->dev, __func__, urb->actual_length, data);
|
||||
port->serial->type->process_read_urb(urb);
|
||||
/*
|
||||
* Make sure URB processing is done before marking as free to avoid
|
||||
* racing with unthrottle() on another CPU. Matches the barriers
|
||||
* implied by the test_and_clear_bit() in
|
||||
* usb_serial_generic_submit_read_urb().
|
||||
*/
|
||||
smp_mb__before_atomic();
|
||||
set_bit(i, &port->read_urbs_free);
|
||||
/*
|
||||
* Make sure URB is marked as free before checking the throttled flag
|
||||
* to avoid racing with unthrottle() on another CPU. Matches the
|
||||
* smp_mb() in unthrottle().
|
||||
*/
|
||||
smp_mb__after_atomic();
|
||||
|
||||
if (stopped)
|
||||
return;
|
||||
|
||||
resubmit:
|
||||
/* Throttle the device if requested by tty */
|
||||
spin_lock_irqsave(&port->lock, flags);
|
||||
port->throttled = port->throttle_req;
|
||||
@@ -484,6 +503,12 @@ void usb_serial_generic_unthrottle(struct tty_struct *tty)
|
||||
port->throttled = port->throttle_req = 0;
|
||||
spin_unlock_irq(&port->lock);
|
||||
|
||||
/*
|
||||
* Matches the smp_mb__after_atomic() in
|
||||
* usb_serial_generic_read_bulk_callback().
|
||||
*/
|
||||
smp_mb();
|
||||
|
||||
if (was_throttled)
|
||||
usb_serial_generic_submit_read_urbs(port, GFP_KERNEL);
|
||||
}
|
||||
|
||||
@@ -65,6 +65,7 @@ static const char* host_info(struct Scsi_Host *host)
|
||||
static int slave_alloc (struct scsi_device *sdev)
|
||||
{
|
||||
struct us_data *us = host_to_us(sdev->host);
|
||||
int maxp;
|
||||
|
||||
/*
|
||||
* Set the INQUIRY transfer length to 36. We don't use any of
|
||||
@@ -74,20 +75,17 @@ static int slave_alloc (struct scsi_device *sdev)
|
||||
sdev->inquiry_len = 36;
|
||||
|
||||
/*
|
||||
* USB has unusual DMA-alignment requirements: Although the
|
||||
* starting address of each scatter-gather element doesn't matter,
|
||||
* the length of each element except the last must be divisible
|
||||
* by the Bulk maxpacket value. There's currently no way to
|
||||
* express this by block-layer constraints, so we'll cop out
|
||||
* and simply require addresses to be aligned at 512-byte
|
||||
* boundaries. This is okay since most block I/O involves
|
||||
* hardware sectors that are multiples of 512 bytes in length,
|
||||
* and since host controllers up through USB 2.0 have maxpacket
|
||||
* values no larger than 512.
|
||||
*
|
||||
* But it doesn't suffice for Wireless USB, where Bulk maxpacket
|
||||
* values can be as large as 2048. To make that work properly
|
||||
* will require changes to the block layer.
|
||||
* USB has unusual scatter-gather requirements: the length of each
|
||||
* scatterlist element except the last must be divisible by the
|
||||
* Bulk maxpacket value. Fortunately this value is always a
|
||||
* power of 2. Inform the block layer about this requirement.
|
||||
*/
|
||||
maxp = usb_maxpacket(us->pusb_dev, us->recv_bulk_pipe, 0);
|
||||
blk_queue_virt_boundary(sdev->request_queue, maxp - 1);
|
||||
|
||||
/*
|
||||
* Some host controllers may have alignment requirements.
|
||||
* We'll play it safe by requiring 512-byte alignment always.
|
||||
*/
|
||||
blk_queue_update_dma_alignment(sdev->request_queue, (512 - 1));
|
||||
|
||||
|
||||
+22
-13
@@ -789,24 +789,33 @@ static int uas_slave_alloc(struct scsi_device *sdev)
|
||||
{
|
||||
struct uas_dev_info *devinfo =
|
||||
(struct uas_dev_info *)sdev->host->hostdata;
|
||||
int maxp;
|
||||
|
||||
sdev->hostdata = devinfo;
|
||||
|
||||
/*
|
||||
* USB has unusual DMA-alignment requirements: Although the
|
||||
* starting address of each scatter-gather element doesn't matter,
|
||||
* the length of each element except the last must be divisible
|
||||
* by the Bulk maxpacket value. There's currently no way to
|
||||
* express this by block-layer constraints, so we'll cop out
|
||||
* and simply require addresses to be aligned at 512-byte
|
||||
* boundaries. This is okay since most block I/O involves
|
||||
* hardware sectors that are multiples of 512 bytes in length,
|
||||
* and since host controllers up through USB 2.0 have maxpacket
|
||||
* values no larger than 512.
|
||||
* We have two requirements here. We must satisfy the requirements
|
||||
* of the physical HC and the demands of the protocol, as we
|
||||
* definitely want no additional memory allocation in this path
|
||||
* ruling out using bounce buffers.
|
||||
*
|
||||
* But it doesn't suffice for Wireless USB, where Bulk maxpacket
|
||||
* values can be as large as 2048. To make that work properly
|
||||
* will require changes to the block layer.
|
||||
* For a transmission on USB to continue we must never send
|
||||
* a package that is smaller than maxpacket. Hence the length of each
|
||||
* scatterlist element except the last must be divisible by the
|
||||
* Bulk maxpacket value.
|
||||
* If the HC does not ensure that through SG,
|
||||
* the upper layer must do that. We must assume nothing
|
||||
* about the capabilities off the HC, so we use the most
|
||||
* pessimistic requirement.
|
||||
*/
|
||||
|
||||
maxp = usb_maxpacket(devinfo->udev, devinfo->data_in_pipe, 0);
|
||||
blk_queue_virt_boundary(sdev->request_queue, maxp - 1);
|
||||
|
||||
/*
|
||||
* The protocol has no requirements on alignment in the strict sense.
|
||||
* Controllers may or may not have alignment restrictions.
|
||||
* As this is not exported, we use an extremely conservative guess.
|
||||
*/
|
||||
blk_queue_update_dma_alignment(sdev->request_queue, (512 - 1));
|
||||
|
||||
|
||||
@@ -215,6 +215,9 @@ static long ioctl_memcpy(struct fsl_hv_ioctl_memcpy __user *p)
|
||||
* hypervisor.
|
||||
*/
|
||||
lb_offset = param.local_vaddr & (PAGE_SIZE - 1);
|
||||
if (param.count == 0 ||
|
||||
param.count > U64_MAX - lb_offset - PAGE_SIZE + 1)
|
||||
return -EINVAL;
|
||||
num_pages = (param.count + lb_offset + PAGE_SIZE - 1) >> PAGE_SHIFT;
|
||||
|
||||
/* Allocate the buffers we need */
|
||||
@@ -331,8 +334,8 @@ static long ioctl_dtprop(struct fsl_hv_ioctl_prop __user *p, int set)
|
||||
struct fsl_hv_ioctl_prop param;
|
||||
char __user *upath, *upropname;
|
||||
void __user *upropval;
|
||||
char *path = NULL, *propname = NULL;
|
||||
void *propval = NULL;
|
||||
char *path, *propname;
|
||||
void *propval;
|
||||
int ret = 0;
|
||||
|
||||
/* Get the parameters from the user. */
|
||||
@@ -344,32 +347,30 @@ static long ioctl_dtprop(struct fsl_hv_ioctl_prop __user *p, int set)
|
||||
upropval = (void __user *)(uintptr_t)param.propval;
|
||||
|
||||
path = strndup_user(upath, FH_DTPROP_MAX_PATHLEN);
|
||||
if (IS_ERR(path)) {
|
||||
ret = PTR_ERR(path);
|
||||
goto out;
|
||||
}
|
||||
if (IS_ERR(path))
|
||||
return PTR_ERR(path);
|
||||
|
||||
propname = strndup_user(upropname, FH_DTPROP_MAX_PATHLEN);
|
||||
if (IS_ERR(propname)) {
|
||||
ret = PTR_ERR(propname);
|
||||
goto out;
|
||||
goto err_free_path;
|
||||
}
|
||||
|
||||
if (param.proplen > FH_DTPROP_MAX_PROPLEN) {
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
goto err_free_propname;
|
||||
}
|
||||
|
||||
propval = kmalloc(param.proplen, GFP_KERNEL);
|
||||
if (!propval) {
|
||||
ret = -ENOMEM;
|
||||
goto out;
|
||||
goto err_free_propname;
|
||||
}
|
||||
|
||||
if (set) {
|
||||
if (copy_from_user(propval, upropval, param.proplen)) {
|
||||
ret = -EFAULT;
|
||||
goto out;
|
||||
goto err_free_propval;
|
||||
}
|
||||
|
||||
param.ret = fh_partition_set_dtprop(param.handle,
|
||||
@@ -388,7 +389,7 @@ static long ioctl_dtprop(struct fsl_hv_ioctl_prop __user *p, int set)
|
||||
if (copy_to_user(upropval, propval, param.proplen) ||
|
||||
put_user(param.proplen, &p->proplen)) {
|
||||
ret = -EFAULT;
|
||||
goto out;
|
||||
goto err_free_propval;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -396,10 +397,12 @@ static long ioctl_dtprop(struct fsl_hv_ioctl_prop __user *p, int set)
|
||||
if (put_user(param.ret, &p->ret))
|
||||
ret = -EFAULT;
|
||||
|
||||
out:
|
||||
kfree(path);
|
||||
err_free_propval:
|
||||
kfree(propval);
|
||||
err_free_propname:
|
||||
kfree(propname);
|
||||
err_free_path:
|
||||
kfree(path);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -1298,6 +1298,20 @@ static int vbg_ioctl_hgcm_disconnect(struct vbg_dev *gdev,
|
||||
return ret;
|
||||
}
|
||||
|
||||
static bool vbg_param_valid(enum vmmdev_hgcm_function_parameter_type type)
|
||||
{
|
||||
switch (type) {
|
||||
case VMMDEV_HGCM_PARM_TYPE_32BIT:
|
||||
case VMMDEV_HGCM_PARM_TYPE_64BIT:
|
||||
case VMMDEV_HGCM_PARM_TYPE_LINADDR:
|
||||
case VMMDEV_HGCM_PARM_TYPE_LINADDR_IN:
|
||||
case VMMDEV_HGCM_PARM_TYPE_LINADDR_OUT:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static int vbg_ioctl_hgcm_call(struct vbg_dev *gdev,
|
||||
struct vbg_session *session, bool f32bit,
|
||||
struct vbg_ioctl_hgcm_call *call)
|
||||
@@ -1333,6 +1347,23 @@ static int vbg_ioctl_hgcm_call(struct vbg_dev *gdev,
|
||||
}
|
||||
call->hdr.size_out = actual_size;
|
||||
|
||||
/* Validate parameter types */
|
||||
if (f32bit) {
|
||||
struct vmmdev_hgcm_function_parameter32 *parm =
|
||||
VBG_IOCTL_HGCM_CALL_PARMS32(call);
|
||||
|
||||
for (i = 0; i < call->parm_count; i++)
|
||||
if (!vbg_param_valid(parm[i].type))
|
||||
return -EINVAL;
|
||||
} else {
|
||||
struct vmmdev_hgcm_function_parameter *parm =
|
||||
VBG_IOCTL_HGCM_CALL_PARMS(call);
|
||||
|
||||
for (i = 0; i < call->parm_count; i++)
|
||||
if (!vbg_param_valid(parm[i].type))
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Validate the client id.
|
||||
*/
|
||||
|
||||
@@ -1004,6 +1004,7 @@ static int virtqueue_add_indirect_packed(struct vring_virtqueue *vq,
|
||||
|
||||
if (unlikely(vq->vq.num_free < 1)) {
|
||||
pr_debug("Can't add buf len 1 - avail = 0\n");
|
||||
kfree(desc);
|
||||
END_USE(vq);
|
||||
return -ENOSPC;
|
||||
}
|
||||
|
||||
+11
-6
@@ -220,12 +220,14 @@ struct block_device *f2fs_target_device(struct f2fs_sb_info *sbi,
|
||||
struct block_device *bdev = sbi->sb->s_bdev;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < sbi->s_ndevs; i++) {
|
||||
if (FDEV(i).start_blk <= blk_addr &&
|
||||
FDEV(i).end_blk >= blk_addr) {
|
||||
blk_addr -= FDEV(i).start_blk;
|
||||
bdev = FDEV(i).bdev;
|
||||
break;
|
||||
if (f2fs_is_multi_device(sbi)) {
|
||||
for (i = 0; i < sbi->s_ndevs; i++) {
|
||||
if (FDEV(i).start_blk <= blk_addr &&
|
||||
FDEV(i).end_blk >= blk_addr) {
|
||||
blk_addr -= FDEV(i).start_blk;
|
||||
bdev = FDEV(i).bdev;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (bio) {
|
||||
@@ -239,6 +241,9 @@ int f2fs_target_device_index(struct f2fs_sb_info *sbi, block_t blkaddr)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (!f2fs_is_multi_device(sbi))
|
||||
return 0;
|
||||
|
||||
for (i = 0; i < sbi->s_ndevs; i++)
|
||||
if (FDEV(i).start_blk <= blkaddr && FDEV(i).end_blk >= blkaddr)
|
||||
return i;
|
||||
|
||||
+12
-1
@@ -1366,6 +1366,17 @@ static inline bool time_to_inject(struct f2fs_sb_info *sbi, int type)
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Test if the mounted volume is a multi-device volume.
|
||||
* - For a single regular disk volume, sbi->s_ndevs is 0.
|
||||
* - For a single zoned disk volume, sbi->s_ndevs is 1.
|
||||
* - For a multi-device volume, sbi->s_ndevs is always 2 or more.
|
||||
*/
|
||||
static inline bool f2fs_is_multi_device(struct f2fs_sb_info *sbi)
|
||||
{
|
||||
return sbi->s_ndevs > 1;
|
||||
}
|
||||
|
||||
/* For write statistics. Suppose sector size is 512 bytes,
|
||||
* and the return value is in kbytes. s is of struct f2fs_sb_info.
|
||||
*/
|
||||
@@ -3615,7 +3626,7 @@ static inline bool f2fs_force_buffered_io(struct inode *inode,
|
||||
|
||||
if (f2fs_post_read_required(inode))
|
||||
return true;
|
||||
if (sbi->s_ndevs)
|
||||
if (f2fs_is_multi_device(sbi))
|
||||
return true;
|
||||
/*
|
||||
* for blkzoned device, fallback direct IO to buffered IO, so
|
||||
|
||||
+1
-1
@@ -2573,7 +2573,7 @@ static int f2fs_ioc_flush_device(struct file *filp, unsigned long arg)
|
||||
sizeof(range)))
|
||||
return -EFAULT;
|
||||
|
||||
if (sbi->s_ndevs <= 1 || sbi->s_ndevs - 1 <= range.dev_num ||
|
||||
if (!f2fs_is_multi_device(sbi) || sbi->s_ndevs - 1 <= range.dev_num ||
|
||||
__is_large_section(sbi)) {
|
||||
f2fs_msg(sbi->sb, KERN_WARNING,
|
||||
"Can't flush %u in %d for segs_per_sec %u != 1\n",
|
||||
|
||||
+1
-1
@@ -1346,7 +1346,7 @@ void f2fs_build_gc_manager(struct f2fs_sb_info *sbi)
|
||||
sbi->gc_pin_file_threshold = DEF_GC_FAILED_PINNED_FILES;
|
||||
|
||||
/* give warm/cold data area from slower device */
|
||||
if (sbi->s_ndevs && !__is_large_section(sbi))
|
||||
if (f2fs_is_multi_device(sbi) && !__is_large_section(sbi))
|
||||
SIT_I(sbi)->last_victim[ALLOC_NEXT] =
|
||||
GET_SEGNO(sbi, FDEV(0).end_blk) + 1;
|
||||
}
|
||||
|
||||
+7
-6
@@ -580,7 +580,7 @@ static int submit_flush_wait(struct f2fs_sb_info *sbi, nid_t ino)
|
||||
int ret = 0;
|
||||
int i;
|
||||
|
||||
if (!sbi->s_ndevs)
|
||||
if (!f2fs_is_multi_device(sbi))
|
||||
return __submit_flush_wait(sbi, sbi->sb->s_bdev);
|
||||
|
||||
for (i = 0; i < sbi->s_ndevs; i++) {
|
||||
@@ -648,7 +648,8 @@ int f2fs_issue_flush(struct f2fs_sb_info *sbi, nid_t ino)
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (atomic_inc_return(&fcc->queued_flush) == 1 || sbi->s_ndevs > 1) {
|
||||
if (atomic_inc_return(&fcc->queued_flush) == 1 ||
|
||||
f2fs_is_multi_device(sbi)) {
|
||||
ret = submit_flush_wait(sbi, ino);
|
||||
atomic_dec(&fcc->queued_flush);
|
||||
|
||||
@@ -754,7 +755,7 @@ int f2fs_flush_device_cache(struct f2fs_sb_info *sbi)
|
||||
{
|
||||
int ret = 0, i;
|
||||
|
||||
if (!sbi->s_ndevs)
|
||||
if (!f2fs_is_multi_device(sbi))
|
||||
return 0;
|
||||
|
||||
for (i = 1; i < sbi->s_ndevs; i++) {
|
||||
@@ -1369,7 +1370,7 @@ static int __queue_discard_cmd(struct f2fs_sb_info *sbi,
|
||||
|
||||
trace_f2fs_queue_discard(bdev, blkstart, blklen);
|
||||
|
||||
if (sbi->s_ndevs) {
|
||||
if (f2fs_is_multi_device(sbi)) {
|
||||
int devi = f2fs_target_device_index(sbi, blkstart);
|
||||
|
||||
blkstart -= FDEV(devi).start_blk;
|
||||
@@ -1732,7 +1733,7 @@ static int __f2fs_issue_discard_zone(struct f2fs_sb_info *sbi,
|
||||
block_t lblkstart = blkstart;
|
||||
int devi = 0;
|
||||
|
||||
if (sbi->s_ndevs) {
|
||||
if (f2fs_is_multi_device(sbi)) {
|
||||
devi = f2fs_target_device_index(sbi, blkstart);
|
||||
blkstart -= FDEV(devi).start_blk;
|
||||
}
|
||||
@@ -3089,7 +3090,7 @@ static void update_device_state(struct f2fs_io_info *fio)
|
||||
struct f2fs_sb_info *sbi = fio->sbi;
|
||||
unsigned int devidx;
|
||||
|
||||
if (!sbi->s_ndevs)
|
||||
if (!f2fs_is_multi_device(sbi))
|
||||
return;
|
||||
|
||||
devidx = f2fs_target_device_index(sbi, fio->new_blkaddr);
|
||||
|
||||
+2
-3
@@ -650,11 +650,10 @@ static struct kernfs_node *__kernfs_new_node(struct kernfs_root *root,
|
||||
kn->id.generation = gen;
|
||||
|
||||
/*
|
||||
* set ino first. This barrier is paired with atomic_inc_not_zero in
|
||||
* set ino first. This RELEASE is paired with atomic_inc_not_zero in
|
||||
* kernfs_find_and_get_node_by_ino
|
||||
*/
|
||||
smp_mb__before_atomic();
|
||||
atomic_set(&kn->count, 1);
|
||||
atomic_set_release(&kn->count, 1);
|
||||
atomic_set(&kn->active, KN_DEACTIVATED_BIAS);
|
||||
RB_CLEAR_NODE(&kn->rb);
|
||||
|
||||
|
||||
@@ -57,6 +57,8 @@ extern ssize_t cpu_show_spec_store_bypass(struct device *dev,
|
||||
struct device_attribute *attr, char *buf);
|
||||
extern ssize_t cpu_show_l1tf(struct device *dev,
|
||||
struct device_attribute *attr, char *buf);
|
||||
extern ssize_t cpu_show_mds(struct device *dev,
|
||||
struct device_attribute *attr, char *buf);
|
||||
|
||||
extern __printf(4, 5)
|
||||
struct device *cpu_device_create(struct device *parent, void *drvdata,
|
||||
@@ -187,4 +189,28 @@ static inline void cpu_smt_disable(bool force) { }
|
||||
static inline void cpu_smt_check_topology(void) { }
|
||||
#endif
|
||||
|
||||
/*
|
||||
* These are used for a global "mitigations=" cmdline option for toggling
|
||||
* optional CPU mitigations.
|
||||
*/
|
||||
enum cpu_mitigations {
|
||||
CPU_MITIGATIONS_OFF,
|
||||
CPU_MITIGATIONS_AUTO,
|
||||
CPU_MITIGATIONS_AUTO_NOSMT,
|
||||
};
|
||||
|
||||
extern enum cpu_mitigations cpu_mitigations;
|
||||
|
||||
/* mitigations=off */
|
||||
static inline bool cpu_mitigations_off(void)
|
||||
{
|
||||
return cpu_mitigations == CPU_MITIGATIONS_OFF;
|
||||
}
|
||||
|
||||
/* mitigations=auto,nosmt */
|
||||
static inline bool cpu_mitigations_auto_nosmt(void)
|
||||
{
|
||||
return cpu_mitigations == CPU_MITIGATIONS_AUTO_NOSMT;
|
||||
}
|
||||
|
||||
#endif /* _LINUX_CPU_H_ */
|
||||
|
||||
+2
-1
@@ -682,7 +682,8 @@ struct i2c_adapter {
|
||||
int retries;
|
||||
struct device dev; /* the adapter device */
|
||||
unsigned long locked_flags; /* owned by the I2C core */
|
||||
#define I2C_ALF_IS_SUSPENDED 0
|
||||
#define I2C_ALF_IS_SUSPENDED 0
|
||||
#define I2C_ALF_SUSPEND_REPORTED 1
|
||||
|
||||
int nr;
|
||||
char name[48];
|
||||
|
||||
@@ -190,6 +190,9 @@ struct adv_info {
|
||||
|
||||
#define HCI_MAX_SHORT_NAME_LENGTH 10
|
||||
|
||||
/* Min encryption key size to match with SMP */
|
||||
#define HCI_MIN_ENC_KEY_SIZE 7
|
||||
|
||||
/* Default LE RPA expiry time, 15 minutes */
|
||||
#define HCI_DEFAULT_RPA_TIMEOUT (15 * 60)
|
||||
|
||||
|
||||
@@ -2304,3 +2304,18 @@ void __init boot_cpu_hotplug_init(void)
|
||||
#endif
|
||||
this_cpu_write(cpuhp_state.state, CPUHP_ONLINE);
|
||||
}
|
||||
|
||||
enum cpu_mitigations cpu_mitigations __ro_after_init = CPU_MITIGATIONS_AUTO;
|
||||
|
||||
static int __init mitigations_parse_cmdline(char *arg)
|
||||
{
|
||||
if (!strcmp(arg, "off"))
|
||||
cpu_mitigations = CPU_MITIGATIONS_OFF;
|
||||
else if (!strcmp(arg, "auto"))
|
||||
cpu_mitigations = CPU_MITIGATIONS_AUTO;
|
||||
else if (!strcmp(arg, "auto,nosmt"))
|
||||
cpu_mitigations = CPU_MITIGATIONS_AUTO_NOSMT;
|
||||
|
||||
return 0;
|
||||
}
|
||||
early_param("mitigations", mitigations_parse_cmdline);
|
||||
|
||||
+117
-71
@@ -1311,13 +1311,15 @@ static int lookup_pi_state(u32 __user *uaddr, u32 uval,
|
||||
|
||||
static int lock_pi_update_atomic(u32 __user *uaddr, u32 uval, u32 newval)
|
||||
{
|
||||
int err;
|
||||
u32 uninitialized_var(curval);
|
||||
|
||||
if (unlikely(should_fail_futex(true)))
|
||||
return -EFAULT;
|
||||
|
||||
if (unlikely(cmpxchg_futex_value_locked(&curval, uaddr, uval, newval)))
|
||||
return -EFAULT;
|
||||
err = cmpxchg_futex_value_locked(&curval, uaddr, uval, newval);
|
||||
if (unlikely(err))
|
||||
return err;
|
||||
|
||||
/* If user space value changed, let the caller retry */
|
||||
return curval != uval ? -EAGAIN : 0;
|
||||
@@ -1502,10 +1504,8 @@ static int wake_futex_pi(u32 __user *uaddr, u32 uval, struct futex_pi_state *pi_
|
||||
if (unlikely(should_fail_futex(true)))
|
||||
ret = -EFAULT;
|
||||
|
||||
if (cmpxchg_futex_value_locked(&curval, uaddr, uval, newval)) {
|
||||
ret = -EFAULT;
|
||||
|
||||
} else if (curval != uval) {
|
||||
ret = cmpxchg_futex_value_locked(&curval, uaddr, uval, newval);
|
||||
if (!ret && (curval != uval)) {
|
||||
/*
|
||||
* If a unconditional UNLOCK_PI operation (user space did not
|
||||
* try the TID->0 transition) raced with a waiter setting the
|
||||
@@ -1700,32 +1700,32 @@ retry_private:
|
||||
double_lock_hb(hb1, hb2);
|
||||
op_ret = futex_atomic_op_inuser(op, uaddr2);
|
||||
if (unlikely(op_ret < 0)) {
|
||||
|
||||
double_unlock_hb(hb1, hb2);
|
||||
|
||||
#ifndef CONFIG_MMU
|
||||
/*
|
||||
* we don't get EFAULT from MMU faults if we don't have an MMU,
|
||||
* but we might get them from range checking
|
||||
*/
|
||||
ret = op_ret;
|
||||
goto out_put_keys;
|
||||
#endif
|
||||
|
||||
if (unlikely(op_ret != -EFAULT)) {
|
||||
if (!IS_ENABLED(CONFIG_MMU) ||
|
||||
unlikely(op_ret != -EFAULT && op_ret != -EAGAIN)) {
|
||||
/*
|
||||
* we don't get EFAULT from MMU faults if we don't have
|
||||
* an MMU, but we might get them from range checking
|
||||
*/
|
||||
ret = op_ret;
|
||||
goto out_put_keys;
|
||||
}
|
||||
|
||||
ret = fault_in_user_writeable(uaddr2);
|
||||
if (ret)
|
||||
goto out_put_keys;
|
||||
if (op_ret == -EFAULT) {
|
||||
ret = fault_in_user_writeable(uaddr2);
|
||||
if (ret)
|
||||
goto out_put_keys;
|
||||
}
|
||||
|
||||
if (!(flags & FLAGS_SHARED))
|
||||
if (!(flags & FLAGS_SHARED)) {
|
||||
cond_resched();
|
||||
goto retry_private;
|
||||
}
|
||||
|
||||
put_futex_key(&key2);
|
||||
put_futex_key(&key1);
|
||||
cond_resched();
|
||||
goto retry;
|
||||
}
|
||||
|
||||
@@ -2350,7 +2350,7 @@ static int fixup_pi_state_owner(u32 __user *uaddr, struct futex_q *q,
|
||||
u32 uval, uninitialized_var(curval), newval;
|
||||
struct task_struct *oldowner, *newowner;
|
||||
u32 newtid;
|
||||
int ret;
|
||||
int ret, err = 0;
|
||||
|
||||
lockdep_assert_held(q->lock_ptr);
|
||||
|
||||
@@ -2421,14 +2421,17 @@ retry:
|
||||
if (!pi_state->owner)
|
||||
newtid |= FUTEX_OWNER_DIED;
|
||||
|
||||
if (get_futex_value_locked(&uval, uaddr))
|
||||
goto handle_fault;
|
||||
err = get_futex_value_locked(&uval, uaddr);
|
||||
if (err)
|
||||
goto handle_err;
|
||||
|
||||
for (;;) {
|
||||
newval = (uval & FUTEX_OWNER_DIED) | newtid;
|
||||
|
||||
if (cmpxchg_futex_value_locked(&curval, uaddr, uval, newval))
|
||||
goto handle_fault;
|
||||
err = cmpxchg_futex_value_locked(&curval, uaddr, uval, newval);
|
||||
if (err)
|
||||
goto handle_err;
|
||||
|
||||
if (curval == uval)
|
||||
break;
|
||||
uval = curval;
|
||||
@@ -2456,23 +2459,37 @@ retry:
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* To handle the page fault we need to drop the locks here. That gives
|
||||
* the other task (either the highest priority waiter itself or the
|
||||
* task which stole the rtmutex) the chance to try the fixup of the
|
||||
* pi_state. So once we are back from handling the fault we need to
|
||||
* check the pi_state after reacquiring the locks and before trying to
|
||||
* do another fixup. When the fixup has been done already we simply
|
||||
* return.
|
||||
* In order to reschedule or handle a page fault, we need to drop the
|
||||
* locks here. In the case of a fault, this gives the other task
|
||||
* (either the highest priority waiter itself or the task which stole
|
||||
* the rtmutex) the chance to try the fixup of the pi_state. So once we
|
||||
* are back from handling the fault we need to check the pi_state after
|
||||
* reacquiring the locks and before trying to do another fixup. When
|
||||
* the fixup has been done already we simply return.
|
||||
*
|
||||
* Note: we hold both hb->lock and pi_mutex->wait_lock. We can safely
|
||||
* drop hb->lock since the caller owns the hb -> futex_q relation.
|
||||
* Dropping the pi_mutex->wait_lock requires the state revalidate.
|
||||
*/
|
||||
handle_fault:
|
||||
handle_err:
|
||||
raw_spin_unlock_irq(&pi_state->pi_mutex.wait_lock);
|
||||
spin_unlock(q->lock_ptr);
|
||||
|
||||
ret = fault_in_user_writeable(uaddr);
|
||||
switch (err) {
|
||||
case -EFAULT:
|
||||
ret = fault_in_user_writeable(uaddr);
|
||||
break;
|
||||
|
||||
case -EAGAIN:
|
||||
cond_resched();
|
||||
ret = 0;
|
||||
break;
|
||||
|
||||
default:
|
||||
WARN_ON_ONCE(1);
|
||||
ret = err;
|
||||
break;
|
||||
}
|
||||
|
||||
spin_lock(q->lock_ptr);
|
||||
raw_spin_lock_irq(&pi_state->pi_mutex.wait_lock);
|
||||
@@ -3041,10 +3058,8 @@ retry:
|
||||
* A unconditional UNLOCK_PI op raced against a waiter
|
||||
* setting the FUTEX_WAITERS bit. Try again.
|
||||
*/
|
||||
if (ret == -EAGAIN) {
|
||||
put_futex_key(&key);
|
||||
goto retry;
|
||||
}
|
||||
if (ret == -EAGAIN)
|
||||
goto pi_retry;
|
||||
/*
|
||||
* wake_futex_pi has detected invalid state. Tell user
|
||||
* space.
|
||||
@@ -3059,9 +3074,19 @@ retry:
|
||||
* preserve the WAITERS bit not the OWNER_DIED one. We are the
|
||||
* owner.
|
||||
*/
|
||||
if (cmpxchg_futex_value_locked(&curval, uaddr, uval, 0)) {
|
||||
if ((ret = cmpxchg_futex_value_locked(&curval, uaddr, uval, 0))) {
|
||||
spin_unlock(&hb->lock);
|
||||
goto pi_faulted;
|
||||
switch (ret) {
|
||||
case -EFAULT:
|
||||
goto pi_faulted;
|
||||
|
||||
case -EAGAIN:
|
||||
goto pi_retry;
|
||||
|
||||
default:
|
||||
WARN_ON_ONCE(1);
|
||||
goto out_putkey;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -3075,6 +3100,11 @@ out_putkey:
|
||||
put_futex_key(&key);
|
||||
return ret;
|
||||
|
||||
pi_retry:
|
||||
put_futex_key(&key);
|
||||
cond_resched();
|
||||
goto retry;
|
||||
|
||||
pi_faulted:
|
||||
put_futex_key(&key);
|
||||
|
||||
@@ -3435,6 +3465,7 @@ err_unlock:
|
||||
static int handle_futex_death(u32 __user *uaddr, struct task_struct *curr, int pi)
|
||||
{
|
||||
u32 uval, uninitialized_var(nval), mval;
|
||||
int err;
|
||||
|
||||
/* Futex address must be 32bit aligned */
|
||||
if ((((unsigned long)uaddr) % sizeof(*uaddr)) != 0)
|
||||
@@ -3444,42 +3475,57 @@ retry:
|
||||
if (get_user(uval, uaddr))
|
||||
return -1;
|
||||
|
||||
if ((uval & FUTEX_TID_MASK) == task_pid_vnr(curr)) {
|
||||
/*
|
||||
* Ok, this dying thread is truly holding a futex
|
||||
* of interest. Set the OWNER_DIED bit atomically
|
||||
* via cmpxchg, and if the value had FUTEX_WAITERS
|
||||
* set, wake up a waiter (if any). (We have to do a
|
||||
* futex_wake() even if OWNER_DIED is already set -
|
||||
* to handle the rare but possible case of recursive
|
||||
* thread-death.) The rest of the cleanup is done in
|
||||
* userspace.
|
||||
*/
|
||||
mval = (uval & FUTEX_WAITERS) | FUTEX_OWNER_DIED;
|
||||
/*
|
||||
* We are not holding a lock here, but we want to have
|
||||
* the pagefault_disable/enable() protection because
|
||||
* we want to handle the fault gracefully. If the
|
||||
* access fails we try to fault in the futex with R/W
|
||||
* verification via get_user_pages. get_user() above
|
||||
* does not guarantee R/W access. If that fails we
|
||||
* give up and leave the futex locked.
|
||||
*/
|
||||
if (cmpxchg_futex_value_locked(&nval, uaddr, uval, mval)) {
|
||||
if ((uval & FUTEX_TID_MASK) != task_pid_vnr(curr))
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* Ok, this dying thread is truly holding a futex
|
||||
* of interest. Set the OWNER_DIED bit atomically
|
||||
* via cmpxchg, and if the value had FUTEX_WAITERS
|
||||
* set, wake up a waiter (if any). (We have to do a
|
||||
* futex_wake() even if OWNER_DIED is already set -
|
||||
* to handle the rare but possible case of recursive
|
||||
* thread-death.) The rest of the cleanup is done in
|
||||
* userspace.
|
||||
*/
|
||||
mval = (uval & FUTEX_WAITERS) | FUTEX_OWNER_DIED;
|
||||
|
||||
/*
|
||||
* We are not holding a lock here, but we want to have
|
||||
* the pagefault_disable/enable() protection because
|
||||
* we want to handle the fault gracefully. If the
|
||||
* access fails we try to fault in the futex with R/W
|
||||
* verification via get_user_pages. get_user() above
|
||||
* does not guarantee R/W access. If that fails we
|
||||
* give up and leave the futex locked.
|
||||
*/
|
||||
if ((err = cmpxchg_futex_value_locked(&nval, uaddr, uval, mval))) {
|
||||
switch (err) {
|
||||
case -EFAULT:
|
||||
if (fault_in_user_writeable(uaddr))
|
||||
return -1;
|
||||
goto retry;
|
||||
}
|
||||
if (nval != uval)
|
||||
|
||||
case -EAGAIN:
|
||||
cond_resched();
|
||||
goto retry;
|
||||
|
||||
/*
|
||||
* Wake robust non-PI futexes here. The wakeup of
|
||||
* PI futexes happens in exit_pi_state():
|
||||
*/
|
||||
if (!pi && (uval & FUTEX_WAITERS))
|
||||
futex_wake(uaddr, 1, 1, FUTEX_BITSET_MATCH_ANY);
|
||||
default:
|
||||
WARN_ON_ONCE(1);
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
if (nval != uval)
|
||||
goto retry;
|
||||
|
||||
/*
|
||||
* Wake robust non-PI futexes here. The wakeup of
|
||||
* PI futexes happens in exit_pi_state():
|
||||
*/
|
||||
if (!pi && (uval & FUTEX_WAITERS))
|
||||
futex_wake(uaddr, 1, 1, FUTEX_BITSET_MATCH_ANY);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
+3
-1
@@ -357,8 +357,10 @@ irq_set_affinity_notifier(unsigned int irq, struct irq_affinity_notify *notify)
|
||||
desc->affinity_notify = notify;
|
||||
raw_spin_unlock_irqrestore(&desc->lock, flags);
|
||||
|
||||
if (old_notify)
|
||||
if (old_notify) {
|
||||
cancel_work_sync(&old_notify->work);
|
||||
kref_put(&old_notify->kref, old_notify->release);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
+23
-26
@@ -86,11 +86,13 @@ static bool is_inline_int(struct type_descriptor *type)
|
||||
return bits <= inline_bits;
|
||||
}
|
||||
|
||||
static s_max get_signed_val(struct type_descriptor *type, unsigned long val)
|
||||
static s_max get_signed_val(struct type_descriptor *type, void *val)
|
||||
{
|
||||
if (is_inline_int(type)) {
|
||||
unsigned extra_bits = sizeof(s_max)*8 - type_bit_width(type);
|
||||
return ((s_max)val) << extra_bits >> extra_bits;
|
||||
unsigned long ulong_val = (unsigned long)val;
|
||||
|
||||
return ((s_max)ulong_val) << extra_bits >> extra_bits;
|
||||
}
|
||||
|
||||
if (type_bit_width(type) == 64)
|
||||
@@ -99,15 +101,15 @@ static s_max get_signed_val(struct type_descriptor *type, unsigned long val)
|
||||
return *(s_max *)val;
|
||||
}
|
||||
|
||||
static bool val_is_negative(struct type_descriptor *type, unsigned long val)
|
||||
static bool val_is_negative(struct type_descriptor *type, void *val)
|
||||
{
|
||||
return type_is_signed(type) && get_signed_val(type, val) < 0;
|
||||
}
|
||||
|
||||
static u_max get_unsigned_val(struct type_descriptor *type, unsigned long val)
|
||||
static u_max get_unsigned_val(struct type_descriptor *type, void *val)
|
||||
{
|
||||
if (is_inline_int(type))
|
||||
return val;
|
||||
return (unsigned long)val;
|
||||
|
||||
if (type_bit_width(type) == 64)
|
||||
return *(u64 *)val;
|
||||
@@ -116,7 +118,7 @@ static u_max get_unsigned_val(struct type_descriptor *type, unsigned long val)
|
||||
}
|
||||
|
||||
static void val_to_string(char *str, size_t size, struct type_descriptor *type,
|
||||
unsigned long value)
|
||||
void *value)
|
||||
{
|
||||
if (type_is_int(type)) {
|
||||
if (type_bit_width(type) == 128) {
|
||||
@@ -163,8 +165,8 @@ static void ubsan_epilogue(unsigned long *flags)
|
||||
current->in_ubsan--;
|
||||
}
|
||||
|
||||
static void handle_overflow(struct overflow_data *data, unsigned long lhs,
|
||||
unsigned long rhs, char op)
|
||||
static void handle_overflow(struct overflow_data *data, void *lhs,
|
||||
void *rhs, char op)
|
||||
{
|
||||
|
||||
struct type_descriptor *type = data->type;
|
||||
@@ -191,8 +193,7 @@ static void handle_overflow(struct overflow_data *data, unsigned long lhs,
|
||||
}
|
||||
|
||||
void __ubsan_handle_add_overflow(struct overflow_data *data,
|
||||
unsigned long lhs,
|
||||
unsigned long rhs)
|
||||
void *lhs, void *rhs)
|
||||
{
|
||||
|
||||
handle_overflow(data, lhs, rhs, '+');
|
||||
@@ -200,23 +201,21 @@ void __ubsan_handle_add_overflow(struct overflow_data *data,
|
||||
EXPORT_SYMBOL(__ubsan_handle_add_overflow);
|
||||
|
||||
void __ubsan_handle_sub_overflow(struct overflow_data *data,
|
||||
unsigned long lhs,
|
||||
unsigned long rhs)
|
||||
void *lhs, void *rhs)
|
||||
{
|
||||
handle_overflow(data, lhs, rhs, '-');
|
||||
}
|
||||
EXPORT_SYMBOL(__ubsan_handle_sub_overflow);
|
||||
|
||||
void __ubsan_handle_mul_overflow(struct overflow_data *data,
|
||||
unsigned long lhs,
|
||||
unsigned long rhs)
|
||||
void *lhs, void *rhs)
|
||||
{
|
||||
handle_overflow(data, lhs, rhs, '*');
|
||||
}
|
||||
EXPORT_SYMBOL(__ubsan_handle_mul_overflow);
|
||||
|
||||
void __ubsan_handle_negate_overflow(struct overflow_data *data,
|
||||
unsigned long old_val)
|
||||
void *old_val)
|
||||
{
|
||||
unsigned long flags;
|
||||
char old_val_str[VALUE_LENGTH];
|
||||
@@ -237,8 +236,7 @@ EXPORT_SYMBOL(__ubsan_handle_negate_overflow);
|
||||
|
||||
|
||||
void __ubsan_handle_divrem_overflow(struct overflow_data *data,
|
||||
unsigned long lhs,
|
||||
unsigned long rhs)
|
||||
void *lhs, void *rhs)
|
||||
{
|
||||
unsigned long flags;
|
||||
char rhs_val_str[VALUE_LENGTH];
|
||||
@@ -323,7 +321,7 @@ static void ubsan_type_mismatch_common(struct type_mismatch_data_common *data,
|
||||
}
|
||||
|
||||
void __ubsan_handle_type_mismatch(struct type_mismatch_data *data,
|
||||
unsigned long ptr)
|
||||
void *ptr)
|
||||
{
|
||||
struct type_mismatch_data_common common_data = {
|
||||
.location = &data->location,
|
||||
@@ -332,12 +330,12 @@ void __ubsan_handle_type_mismatch(struct type_mismatch_data *data,
|
||||
.type_check_kind = data->type_check_kind
|
||||
};
|
||||
|
||||
ubsan_type_mismatch_common(&common_data, ptr);
|
||||
ubsan_type_mismatch_common(&common_data, (unsigned long)ptr);
|
||||
}
|
||||
EXPORT_SYMBOL(__ubsan_handle_type_mismatch);
|
||||
|
||||
void __ubsan_handle_type_mismatch_v1(struct type_mismatch_data_v1 *data,
|
||||
unsigned long ptr)
|
||||
void *ptr)
|
||||
{
|
||||
|
||||
struct type_mismatch_data_common common_data = {
|
||||
@@ -347,12 +345,12 @@ void __ubsan_handle_type_mismatch_v1(struct type_mismatch_data_v1 *data,
|
||||
.type_check_kind = data->type_check_kind
|
||||
};
|
||||
|
||||
ubsan_type_mismatch_common(&common_data, ptr);
|
||||
ubsan_type_mismatch_common(&common_data, (unsigned long)ptr);
|
||||
}
|
||||
EXPORT_SYMBOL(__ubsan_handle_type_mismatch_v1);
|
||||
|
||||
void __ubsan_handle_vla_bound_not_positive(struct vla_bound_data *data,
|
||||
unsigned long bound)
|
||||
void *bound)
|
||||
{
|
||||
unsigned long flags;
|
||||
char bound_str[VALUE_LENGTH];
|
||||
@@ -369,8 +367,7 @@ void __ubsan_handle_vla_bound_not_positive(struct vla_bound_data *data,
|
||||
}
|
||||
EXPORT_SYMBOL(__ubsan_handle_vla_bound_not_positive);
|
||||
|
||||
void __ubsan_handle_out_of_bounds(struct out_of_bounds_data *data,
|
||||
unsigned long index)
|
||||
void __ubsan_handle_out_of_bounds(struct out_of_bounds_data *data, void *index)
|
||||
{
|
||||
unsigned long flags;
|
||||
char index_str[VALUE_LENGTH];
|
||||
@@ -388,7 +385,7 @@ void __ubsan_handle_out_of_bounds(struct out_of_bounds_data *data,
|
||||
EXPORT_SYMBOL(__ubsan_handle_out_of_bounds);
|
||||
|
||||
void __ubsan_handle_shift_out_of_bounds(struct shift_out_of_bounds_data *data,
|
||||
unsigned long lhs, unsigned long rhs)
|
||||
void *lhs, void *rhs)
|
||||
{
|
||||
unsigned long flags;
|
||||
struct type_descriptor *rhs_type = data->rhs_type;
|
||||
@@ -439,7 +436,7 @@ void __ubsan_handle_builtin_unreachable(struct unreachable_data *data)
|
||||
EXPORT_SYMBOL(__ubsan_handle_builtin_unreachable);
|
||||
|
||||
void __ubsan_handle_load_invalid_value(struct invalid_value_data *data,
|
||||
unsigned long val)
|
||||
void *val)
|
||||
{
|
||||
unsigned long flags;
|
||||
char val_str[VALUE_LENGTH];
|
||||
|
||||
@@ -367,10 +367,12 @@ static int vlan_dev_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
|
||||
ifrr.ifr_ifru = ifr->ifr_ifru;
|
||||
|
||||
switch (cmd) {
|
||||
case SIOCSHWTSTAMP:
|
||||
if (!net_eq(dev_net(dev), &init_net))
|
||||
break;
|
||||
case SIOCGMIIPHY:
|
||||
case SIOCGMIIREG:
|
||||
case SIOCSMIIREG:
|
||||
case SIOCSHWTSTAMP:
|
||||
case SIOCGHWTSTAMP:
|
||||
if (netif_device_present(real_dev) && ops->ndo_do_ioctl)
|
||||
err = ops->ndo_do_ioctl(real_dev, &ifrr, cmd);
|
||||
|
||||
@@ -1276,6 +1276,14 @@ int hci_conn_check_link_mode(struct hci_conn *conn)
|
||||
!test_bit(HCI_CONN_ENCRYPT, &conn->flags))
|
||||
return 0;
|
||||
|
||||
/* The minimum encryption key size needs to be enforced by the
|
||||
* host stack before establishing any L2CAP connections. The
|
||||
* specification in theory allows a minimum of 1, but to align
|
||||
* BR/EDR and LE transports, a minimum of 7 is chosen.
|
||||
*/
|
||||
if (conn->enc_key_size < HCI_MIN_ENC_KEY_SIZE)
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
@@ -75,6 +75,7 @@ static int do_hidp_sock_ioctl(struct socket *sock, unsigned int cmd, void __user
|
||||
sockfd_put(csock);
|
||||
return err;
|
||||
}
|
||||
ca.name[sizeof(ca.name)-1] = 0;
|
||||
|
||||
err = hidp_connection_add(&ca, csock, isock);
|
||||
if (!err && copy_to_user(argp, &ca, sizeof(ca)))
|
||||
|
||||
@@ -510,12 +510,12 @@ void l2cap_chan_set_defaults(struct l2cap_chan *chan)
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(l2cap_chan_set_defaults);
|
||||
|
||||
static void l2cap_le_flowctl_init(struct l2cap_chan *chan)
|
||||
static void l2cap_le_flowctl_init(struct l2cap_chan *chan, u16 tx_credits)
|
||||
{
|
||||
chan->sdu = NULL;
|
||||
chan->sdu_last_frag = NULL;
|
||||
chan->sdu_len = 0;
|
||||
chan->tx_credits = 0;
|
||||
chan->tx_credits = tx_credits;
|
||||
/* Derive MPS from connection MTU to stop HCI fragmentation */
|
||||
chan->mps = min_t(u16, chan->imtu, chan->conn->mtu - L2CAP_HDR_SIZE);
|
||||
/* Give enough credits for a full packet */
|
||||
@@ -1281,7 +1281,7 @@ static void l2cap_le_connect(struct l2cap_chan *chan)
|
||||
if (test_and_set_bit(FLAG_LE_CONN_REQ_SENT, &chan->flags))
|
||||
return;
|
||||
|
||||
l2cap_le_flowctl_init(chan);
|
||||
l2cap_le_flowctl_init(chan, 0);
|
||||
|
||||
req.psm = chan->psm;
|
||||
req.scid = cpu_to_le16(chan->scid);
|
||||
@@ -5532,11 +5532,10 @@ static int l2cap_le_connect_req(struct l2cap_conn *conn,
|
||||
chan->dcid = scid;
|
||||
chan->omtu = mtu;
|
||||
chan->remote_mps = mps;
|
||||
chan->tx_credits = __le16_to_cpu(req->credits);
|
||||
|
||||
__l2cap_chan_add(conn, chan);
|
||||
|
||||
l2cap_le_flowctl_init(chan);
|
||||
l2cap_le_flowctl_init(chan, __le16_to_cpu(req->credits));
|
||||
|
||||
dcid = chan->scid;
|
||||
credits = chan->rx_credits;
|
||||
|
||||
+6
-7
@@ -602,13 +602,15 @@ int br_add_if(struct net_bridge *br, struct net_device *dev,
|
||||
call_netdevice_notifiers(NETDEV_JOIN, dev);
|
||||
|
||||
err = dev_set_allmulti(dev, 1);
|
||||
if (err)
|
||||
goto put_back;
|
||||
if (err) {
|
||||
kfree(p); /* kobject not yet init'd, manually free */
|
||||
goto err1;
|
||||
}
|
||||
|
||||
err = kobject_init_and_add(&p->kobj, &brport_ktype, &(dev->dev.kobj),
|
||||
SYSFS_BRIDGE_PORT_ATTR);
|
||||
if (err)
|
||||
goto err1;
|
||||
goto err2;
|
||||
|
||||
err = br_sysfs_addif(p);
|
||||
if (err)
|
||||
@@ -700,12 +702,9 @@ err3:
|
||||
sysfs_remove_link(br->ifobj, p->dev->name);
|
||||
err2:
|
||||
kobject_put(&p->kobj);
|
||||
p = NULL; /* kobject_put frees */
|
||||
err1:
|
||||
dev_set_allmulti(dev, -1);
|
||||
put_back:
|
||||
err1:
|
||||
dev_put(dev);
|
||||
kfree(p);
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user