Thanks, a bunch Greg!
On 09:19 Sun 14 Jul , Greg KH wrote:
diff --git a/Documentation/admin-guide/hw-vuln/index.rst b/Documentation/admin-guide/hw-vuln/index.rst index ffc064c1ec68..49311f3da6f2 100644 --- a/Documentation/admin-guide/hw-vuln/index.rst +++ b/Documentation/admin-guide/hw-vuln/index.rst @@ -9,5 +9,6 @@ are configurable at compile, boot or run time. .. toctree:: :maxdepth: 1
- spectre l1tf mds
diff --git a/Documentation/admin-guide/hw-vuln/spectre.rst b/Documentation/admin-guide/hw-vuln/spectre.rst new file mode 100644 index 000000000000..25f3b2532198 --- /dev/null +++ b/Documentation/admin-guide/hw-vuln/spectre.rst @@ -0,0 +1,697 @@ +.. SPDX-License-Identifier: GPL-2.0
+Spectre Side Channels +=====================
+Spectre is a class of side channel attacks that exploit branch prediction +and speculative execution on modern CPUs to read memory, possibly +bypassing access controls. Speculative execution side channel exploits +do not modify memory but attempt to infer privileged data in the memory.
+This document covers Spectre variant 1 and Spectre variant 2.
+Affected processors +-------------------
+Speculative execution side channel methods affect a wide range of modern +high performance processors, since most modern high speed processors +use branch prediction and speculative execution.
+The following CPUs are vulnerable:
- Intel Core, Atom, Pentium, and Xeon processors
- AMD Phenom, EPYC, and Zen processors
- IBM POWER and zSeries processors
- Higher end ARM processors
- Apple CPUs
- Higher end MIPS CPUs
- Likely most other high performance CPUs. Contact your CPU vendor for details.
+Whether a processor is affected or not can be read out from the Spectre +vulnerability files in sysfs. See :ref:`spectre_sys_info`.
+Related CVEs +------------
+The following CVE entries describe Spectre variants:
- ============= ======================= =================
- CVE-2017-5753 Bounds check bypass Spectre variant 1
- CVE-2017-5715 Branch target injection Spectre variant 2
- ============= ======================= =================
+Problem +-------
+CPUs use speculative operations to improve performance. That may leave +traces of memory accesses or computations in the processor's caches, +buffers, and branch predictors. Malicious software may be able to +influence the speculative execution paths, and then use the side effects +of the speculative execution in the CPUs' caches and buffers to infer +privileged data touched during the speculative execution.
+Spectre variant 1 attacks take advantage of speculative execution of +conditional branches, while Spectre variant 2 attacks use speculative +execution of indirect branches to leak privileged memory. +See :ref:`[1] <spec_ref1>` :ref:`[5] <spec_ref5>` :ref:`[7] <spec_ref7>` +:ref:`[10] <spec_ref10>` :ref:`[11] <spec_ref11>`.
+Spectre variant 1 (Bounds Check Bypass) +---------------------------------------
+The bounds check bypass attack :ref:`[2] <spec_ref2>` takes advantage +of speculative execution that bypasses conditional branch instructions +used for memory access bounds check (e.g. checking if the index of an +array results in memory access within a valid range). This results in +memory accesses to invalid memory (with out-of-bound index) that are +done speculatively before validation checks resolve. Such speculative +memory accesses can leave side effects, creating side channels which +leak information to the attacker.
+There are some extensions of Spectre variant 1 attacks for reading data +over the network, see :ref:`[12] <spec_ref12>`. However such attacks +are difficult, low bandwidth, fragile, and are considered low risk.
+Spectre variant 2 (Branch Target Injection) +-------------------------------------------
+The branch target injection attack takes advantage of speculative +execution of indirect branches :ref:`[3] <spec_ref3>`. The indirect +branch predictors inside the processor used to guess the target of +indirect branches can be influenced by an attacker, causing gadget code +to be speculatively executed, thus exposing sensitive data touched by +the victim. The side effects left in the CPU's caches during speculative +execution can be measured to infer data values.
+.. _poison_btb:
+In Spectre variant 2 attacks, the attacker can steer speculative indirect +branches in the victim to gadget code by poisoning the branch target +buffer of a CPU used for predicting indirect branch addresses. Such +poisoning could be done by indirect branching into existing code, +with the address offset of the indirect branch under the attacker's +control. Since the branch prediction on impacted hardware does not +fully disambiguate branch address and uses the offset for prediction, +this could cause privileged code's indirect branch to jump to a gadget +code with the same offset.
+The most useful gadgets take an attacker-controlled input parameter (such +as a register value) so that the memory read can be controlled. Gadgets +without input parameters might be possible, but the attacker would have +very little control over what memory can be read, reducing the risk of +the attack revealing useful data.
+One other variant 2 attack vector is for the attacker to poison the +return stack buffer (RSB) :ref:`[13] <spec_ref13>` to cause speculative +subroutine return instruction execution to go to a gadget. An attacker's +imbalanced subroutine call instructions might "poison" entries in the +return stack buffer which are later consumed by a victim's subroutine +return instructions. This attack can be mitigated by flushing the return +stack buffer on context switch, or virtual machine (VM) exit.
+On systems with simultaneous multi-threading (SMT), attacks are possible +from the sibling thread, as level 1 cache and branch target buffer +(BTB) may be shared between hardware threads in a CPU core. A malicious +program running on the sibling thread may influence its peer's BTB to +steer its indirect branch speculations to gadget code, and measure the +speculative execution's side effects left in level 1 cache to infer the +victim's data.
+Attack scenarios +----------------
+The following list of attack scenarios have been anticipated, but may +not cover all possible attack vectors.
+1. A user process attacking the kernel +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- The attacker passes a parameter to the kernel via a register or
- via a known address in memory during a syscall. Such parameter may
- be used later by the kernel as an index to an array or to derive
- a pointer for a Spectre variant 1 attack. The index or pointer
- is invalid, but bound checks are bypassed in the code branch taken
- for speculative execution. This could cause privileged memory to be
- accessed and leaked.
- For kernel code that has been identified where data pointers could
- potentially be influenced for Spectre attacks, new "nospec" accessor
- macros are used to prevent speculative loading of data.
- Spectre variant 2 attacker can :ref:`poison <poison_btb>` the branch
- target buffer (BTB) before issuing syscall to launch an attack.
- After entering the kernel, the kernel could use the poisoned branch
- target buffer on indirect jump and jump to gadget code in speculative
- execution.
- If an attacker tries to control the memory addresses leaked during
- speculative execution, he would also need to pass a parameter to the
- gadget, either through a register or a known address in memory. After
- the gadget has executed, he can measure the side effect.
- The kernel can protect itself against consuming poisoned branch
- target buffer entries by using return trampolines (also known as
- "retpoline") :ref:`[3] <spec_ref3>` :ref:`[9] <spec_ref9>` for all
- indirect branches. Return trampolines trap speculative execution paths
- to prevent jumping to gadget code during speculative execution.
- x86 CPUs with Enhanced Indirect Branch Restricted Speculation
- (Enhanced IBRS) available in hardware should use the feature to
- mitigate Spectre variant 2 instead of retpoline. Enhanced IBRS is
- more efficient than retpoline.
- There may be gadget code in firmware which could be exploited with
- Spectre variant 2 attack by a rogue user process. To mitigate such
- attacks on x86, Indirect Branch Restricted Speculation (IBRS) feature
- is turned on before the kernel invokes any firmware code.
+2. A user process attacking another user process +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- A malicious user process can try to attack another user process,
- either via a context switch on the same hardware thread, or from the
- sibling hyperthread sharing a physical processor core on simultaneous
- multi-threading (SMT) system.
- Spectre variant 1 attacks generally require passing parameters
- between the processes, which needs a data passing relationship, such
- as remote procedure calls (RPC). Those parameters are used in gadget
- code to derive invalid data pointers accessing privileged memory in
- the attacked process.
- Spectre variant 2 attacks can be launched from a rogue process by
- :ref:`poisoning <poison_btb>` the branch target buffer. This can
- influence the indirect branch targets for a victim process that either
- runs later on the same hardware thread, or running concurrently on
- a sibling hardware thread sharing the same physical core.
- A user process can protect itself against Spectre variant 2 attacks
- by using the prctl() syscall to disable indirect branch speculation
- for itself. An administrator can also cordon off an unsafe process
- from polluting the branch target buffer by disabling the process's
- indirect branch speculation. This comes with a performance cost
- from not using indirect branch speculation and clearing the branch
- target buffer. When SMT is enabled on x86, for a process that has
- indirect branch speculation disabled, Single Threaded Indirect Branch
- Predictors (STIBP) :ref:`[4] <spec_ref4>` are turned on to prevent the
- sibling thread from controlling branch target buffer. In addition,
- the Indirect Branch Prediction Barrier (IBPB) is issued to clear the
- branch target buffer when context switching to and from such process.
- On x86, the return stack buffer is stuffed on context switch.
- This prevents the branch target buffer from being used for branch
- prediction when the return stack buffer underflows while switching to
- a deeper call stack. Any poisoned entries in the return stack buffer
- left by the previous process will also be cleared.
- User programs should use address space randomization to make attacks
- more difficult (Set /proc/sys/kernel/randomize_va_space = 1 or 2).
+3. A virtualized guest attacking the host +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- The attack mechanism is similar to how user processes attack the
- kernel. The kernel is entered via hyper-calls or other virtualization
- exit paths.
- For Spectre variant 1 attacks, rogue guests can pass parameters
- (e.g. in registers) via hyper-calls to derive invalid pointers to
- speculate into privileged memory after entering the kernel. For places
- where such kernel code has been identified, nospec accessor macros
- are used to stop speculative memory access.
- For Spectre variant 2 attacks, rogue guests can :ref:`poison
- <poison_btb>` the branch target buffer or return stack buffer, causing
- the kernel to jump to gadget code in the speculative execution paths.
- To mitigate variant 2, the host kernel can use return trampolines
- for indirect branches to bypass the poisoned branch target buffer,
- and flushing the return stack buffer on VM exit. This prevents rogue
- guests from affecting indirect branching in the host kernel.
- To protect host processes from rogue guests, host processes can have
- indirect branch speculation disabled via prctl(). The branch target
- buffer is cleared before context switching to such processes.
+4. A virtualized guest attacking other guest +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- A rogue guest may attack another guest to get data accessible by the
- other guest.
- Spectre variant 1 attacks are possible if parameters can be passed
- between guests. This may be done via mechanisms such as shared memory
- or message passing. Such parameters could be used to derive data
- pointers to privileged data in guest. The privileged data could be
- accessed by gadget code in the victim's speculation paths.
- Spectre variant 2 attacks can be launched from a rogue guest by
- :ref:`poisoning <poison_btb>` the branch target buffer or the return
- stack buffer. Such poisoned entries could be used to influence
- speculation execution paths in the victim guest.
- Linux kernel mitigates attacks to other guests running in the same
- CPU hardware thread by flushing the return stack buffer on VM exit,
- and clearing the branch target buffer before switching to a new guest.
- If SMT is used, Spectre variant 2 attacks from an untrusted guest
- in the sibling hyperthread can be mitigated by the administrator,
- by turning off the unsafe guest's indirect branch speculation via
- prctl(). A guest can also protect itself by turning on microcode
- based mitigations (such as IBPB or STIBP on x86) within the guest.
+.. _spectre_sys_info:
+Spectre system information +--------------------------
+The Linux kernel provides a sysfs interface to enumerate the current +mitigation status of the system for Spectre: whether the system is +vulnerable, and which mitigations are active.
+The sysfs file showing Spectre variant 1 mitigation status is:
- /sys/devices/system/cpu/vulnerabilities/spectre_v1
+The possible values in this file are:
- ======================================= =================================
- 'Mitigation: __user pointer sanitation' Protection in kernel on a case by
case base with explicit pointer
sanitation.
- ======================================= =================================
+However, the protections are put in place on a case by case basis, +and there is no guarantee that all possible attack vectors for Spectre +variant 1 are covered.
+The spectre_v2 kernel file reports if the kernel has been compiled with +retpoline mitigation or if the CPU has hardware mitigation, and if the +CPU has support for additional process-specific mitigation.
+This file also reports CPU features enabled by microcode to mitigate +attack between user processes:
+1. Indirect Branch Prediction Barrier (IBPB) to add additional
- isolation between processes of different users.
+2. Single Thread Indirect Branch Predictors (STIBP) to add additional
- isolation between CPU threads running on the same core.
+These CPU features may impact performance when used and can be enabled +per process on a case-by-case base.
+The sysfs file showing Spectre variant 2 mitigation status is:
- /sys/devices/system/cpu/vulnerabilities/spectre_v2
+The possible values in this file are:
- Kernel status:
- ==================================== =================================
- 'Not affected' The processor is not vulnerable
- 'Vulnerable' Vulnerable, no mitigation
- 'Mitigation: Full generic retpoline' Software-focused mitigation
- 'Mitigation: Full AMD retpoline' AMD-specific software mitigation
- 'Mitigation: Enhanced IBRS' Hardware-focused mitigation
- ==================================== =================================
- Firmware status: Show if Indirect Branch Restricted Speculation (IBRS) is
- used to protect against Spectre variant 2 attacks when calling firmware (x86 only).
- ========== =============================================================
- 'IBRS_FW' Protection against user program attacks when calling firmware
- ========== =============================================================
- Indirect branch prediction barrier (IBPB) status for protection between
- processes of different users. This feature can be controlled through
- prctl() per process, or through kernel command line options. This is
- an x86 only feature. For more details see below.
- =================== ========================================================
- 'IBPB: disabled' IBPB unused
- 'IBPB: always-on' Use IBPB on all tasks
- 'IBPB: conditional' Use IBPB on SECCOMP or indirect branch restricted tasks
- =================== ========================================================
- Single threaded indirect branch prediction (STIBP) status for protection
- between different hyper threads. This feature can be controlled through
- prctl per process, or through kernel command line options. This is x86
- only feature. For more details see below.
- ==================== ========================================================
- 'STIBP: disabled' STIBP unused
- 'STIBP: forced' Use STIBP on all tasks
- 'STIBP: conditional' Use STIBP on SECCOMP or indirect branch restricted tasks
- ==================== ========================================================
- Return stack buffer (RSB) protection status:
- ============= ===========================================
- 'RSB filling' Protection of RSB on context switch enabled
- ============= ===========================================
+Full mitigation might require a microcode update from the CPU +vendor. When the necessary microcode is not available, the kernel will +report vulnerability.
+Turning on mitigation for Spectre variant 1 and Spectre variant 2 +-----------------------------------------------------------------
+1. Kernel mitigation +^^^^^^^^^^^^^^^^^^^^
- For the Spectre variant 1, vulnerable kernel code (as determined
- by code audit or scanning tools) is annotated on a case by case
- basis to use nospec accessor macros for bounds clipping :ref:`[2]
- <spec_ref2>` to avoid any usable disclosure gadgets. However, it may
- not cover all attack vectors for Spectre variant 1.
- For Spectre variant 2 mitigation, the compiler turns indirect calls or
- jumps in the kernel into equivalent return trampolines (retpolines)
- :ref:`[3] <spec_ref3>` :ref:`[9] <spec_ref9>` to go to the target
- addresses. Speculative execution paths under retpolines are trapped
- in an infinite loop to prevent any speculative execution jumping to
- a gadget.
- To turn on retpoline mitigation on a vulnerable CPU, the kernel
- needs to be compiled with a gcc compiler that supports the
- -mindirect-branch=thunk-extern -mindirect-branch-register options.
- If the kernel is compiled with a Clang compiler, the compiler needs
- to support -mretpoline-external-thunk option. The kernel config
- CONFIG_RETPOLINE needs to be turned on, and the CPU needs to run with
- the latest updated microcode.
- On Intel Skylake-era systems the mitigation covers most, but not all,
- cases. See :ref:`[3] <spec_ref3>` for more details.
- On CPUs with hardware mitigation for Spectre variant 2 (e.g. Enhanced
- IBRS on x86), retpoline is automatically disabled at run time.
- The retpoline mitigation is turned on by default on vulnerable
- CPUs. It can be forced on or off by the administrator
- via the kernel command line and sysfs control files. See
- :ref:`spectre_mitigation_control_command_line`.
- On x86, indirect branch restricted speculation is turned on by default
- before invoking any firmware code to prevent Spectre variant 2 exploits
- using the firmware.
- Using kernel address space randomization (CONFIG_RANDOMIZE_SLAB=y
- and CONFIG_SLAB_FREELIST_RANDOM=y in the kernel configuration) makes
- attacks on the kernel generally more difficult.
+2. User program mitigation +^^^^^^^^^^^^^^^^^^^^^^^^^^
- User programs can mitigate Spectre variant 1 using LFENCE or "bounds
- clipping". For more details see :ref:`[2] <spec_ref2>`.
- For Spectre variant 2 mitigation, individual user programs
- can be compiled with return trampolines for indirect branches.
- This protects them from consuming poisoned entries in the branch
- target buffer left by malicious software. Alternatively, the
- programs can disable their indirect branch speculation via prctl()
- (See :ref:`Documentation/userspace-api/spec_ctrl.rst <set_spec_ctrl>`).
- On x86, this will turn on STIBP to guard against attacks from the
- sibling thread when the user program is running, and use IBPB to
- flush the branch target buffer when switching to/from the program.
- Restricting indirect branch speculation on a user program will
- also prevent the program from launching a variant 2 attack
- on x86. All sand-boxed SECCOMP programs have indirect branch
- speculation restricted by default. Administrators can change
- that behavior via the kernel command line and sysfs control files.
- See :ref:`spectre_mitigation_control_command_line`.
- Programs that disable their indirect branch speculation will have
- more overhead and run slower.
- User programs should use address space randomization
- (/proc/sys/kernel/randomize_va_space = 1 or 2) to make attacks more
- difficult.
+3. VM mitigation +^^^^^^^^^^^^^^^^
- Within the kernel, Spectre variant 1 attacks from rogue guests are
- mitigated on a case by case basis in VM exit paths. Vulnerable code
- uses nospec accessor macros for "bounds clipping", to avoid any
- usable disclosure gadgets. However, this may not cover all variant
- 1 attack vectors.
- For Spectre variant 2 attacks from rogue guests to the kernel, the
- Linux kernel uses retpoline or Enhanced IBRS to prevent consumption of
- poisoned entries in branch target buffer left by rogue guests. It also
- flushes the return stack buffer on every VM exit to prevent a return
- stack buffer underflow so poisoned branch target buffer could be used,
- or attacker guests leaving poisoned entries in the return stack buffer.
- To mitigate guest-to-guest attacks in the same CPU hardware thread,
- the branch target buffer is sanitized by flushing before switching
- to a new guest on a CPU.
- The above mitigations are turned on by default on vulnerable CPUs.
- To mitigate guest-to-guest attacks from sibling thread when SMT is
- in use, an untrusted guest running in the sibling thread can have
- its indirect branch speculation disabled by administrator via prctl().
- The kernel also allows guests to use any microcode based mitigation
- they choose to use (such as IBPB or STIBP on x86) to protect themselves.
+.. _spectre_mitigation_control_command_line:
+Mitigation control on the kernel command line +---------------------------------------------
+Spectre variant 2 mitigation can be disabled or force enabled at the +kernel command line.
- nospectre_v2
[X86] Disable all mitigations for the Spectre variant 2
(indirect branch prediction) vulnerability. System may
allow data leaks with this option, which is equivalent
to spectre_v2=off.
spectre_v2=
[X86] Control mitigation of Spectre variant 2
(indirect branch speculation) vulnerability.
The default operation protects the kernel from
user space attacks.
on
unconditionally enable, implies
spectre_v2_user=on
off
unconditionally disable, implies
spectre_v2_user=off
auto
kernel detects whether your CPU model is
vulnerable
Selecting 'on' will, and 'auto' may, choose a
mitigation method at run time according to the
CPU, the available microcode, the setting of the
CONFIG_RETPOLINE configuration option, and the
compiler with which the kernel was built.
Selecting 'on' will also enable the mitigation
against user space to user space task attacks.
Selecting 'off' will disable both the kernel and
the user space protections.
Specific mitigations can also be selected manually:
retpoline
replace indirect branches
retpoline,generic
google's original retpoline
retpoline,amd
AMD-specific minimal thunk
Not specifying this option is equivalent to
spectre_v2=auto.
+For user space mitigation:
spectre_v2_user=
[X86] Control mitigation of Spectre variant 2
(indirect branch speculation) vulnerability between
user space tasks
on
Unconditionally enable mitigations. Is
enforced by spectre_v2=on
off
Unconditionally disable mitigations. Is
enforced by spectre_v2=off
prctl
Indirect branch speculation is enabled,
but mitigation can be enabled via prctl
per thread. The mitigation control state
is inherited on fork.
prctl,ibpb
Like "prctl" above, but only STIBP is
controlled per thread. IBPB is issued
always when switching between different user
space processes.
seccomp
Same as "prctl" above, but all seccomp
threads will enable the mitigation unless
they explicitly opt out.
seccomp,ibpb
Like "seccomp" above, but only STIBP is
controlled per thread. IBPB is issued
always when switching between different
user space processes.
auto
Kernel selects the mitigation depending on
the available CPU features and vulnerability.
Default mitigation:
If CONFIG_SECCOMP=y then "seccomp", otherwise "prctl"
Not specifying this option is equivalent to
spectre_v2_user=auto.
In general the kernel by default selects
reasonable mitigations for the current CPU. To
disable Spectre variant 2 mitigations, boot with
spectre_v2=off. Spectre variant 1 mitigations
cannot be disabled.
+Mitigation selection guide +--------------------------
+1. Trusted userspace +^^^^^^^^^^^^^^^^^^^^
- If all userspace applications are from trusted sources and do not
- execute externally supplied untrusted code, then the mitigations can
- be disabled.
+2. Protect sensitive programs +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- For security-sensitive programs that have secrets (e.g. crypto
- keys), protection against Spectre variant 2 can be put in place by
- disabling indirect branch speculation when the program is running
- (See :ref:`Documentation/userspace-api/spec_ctrl.rst <set_spec_ctrl>`).
+3. Sandbox untrusted programs +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- Untrusted programs that could be a source of attacks can be cordoned
- off by disabling their indirect branch speculation when they are run
- (See :ref:`Documentation/userspace-api/spec_ctrl.rst <set_spec_ctrl>`).
- This prevents untrusted programs from polluting the branch target
- buffer. All programs running in SECCOMP sandboxes have indirect
- branch speculation restricted by default. This behavior can be
- changed via the kernel command line and sysfs control files. See
- :ref:`spectre_mitigation_control_command_line`.
+3. High security mode +^^^^^^^^^^^^^^^^^^^^^
- All Spectre variant 2 mitigations can be forced on
- at boot time for all programs (See the "on" option in
- :ref:`spectre_mitigation_control_command_line`). This will add
- overhead as indirect branch speculations for all programs will be
- restricted.
- On x86, branch target buffer will be flushed with IBPB when switching
- to a new program. STIBP is left on all the time to protect programs
- against variant 2 attacks originating from programs running on
- sibling threads.
- Alternatively, STIBP can be used only when running programs
- whose indirect branch speculation is explicitly disabled,
- while IBPB is still used all the time when switching to a new
- program to clear the branch target buffer (See "ibpb" option in
- :ref:`spectre_mitigation_control_command_line`). This "ibpb" option
- has less performance cost than the "on" option, which leaves STIBP
- on all the time.
+References on Spectre +---------------------
+Intel white papers:
+.. _spec_ref1:
+[1] `Intel analysis of speculative execution side channels https://newsroom.intel.com/wp-content/uploads/sites/11/2018/01/Intel-Analysis-of-Speculative-Execution-Side-Channels.pdf`_.
+.. _spec_ref2:
+[2] `Bounds check bypass https://software.intel.com/security-software-guidance/software-guidance/bounds-check-bypass`_.
+.. _spec_ref3:
+[3] `Deep dive: Retpoline: A branch target injection mitigation https://software.intel.com/security-software-guidance/insights/deep-dive-retpoline-branch-target-injection-mitigation`_.
+.. _spec_ref4:
+[4] `Deep Dive: Single Thread Indirect Branch Predictors https://software.intel.com/security-software-guidance/insights/deep-dive-single-thread-indirect-branch-predictors`_.
+AMD white papers:
+.. _spec_ref5:
+[5] `AMD64 technology indirect branch control extension https://developer.amd.com/wp-content/resources/Architecture_Guidelines_Update_Indirect_Branch_Control.pdf`_.
+.. _spec_ref6:
+[6] `Software techniques for managing speculation on AMD processors https://developer.amd.com/wp-content/resources/90343-B_SoftwareTechniquesforManagingSpeculation_WP_7-18Update_FNL.pdf`_.
+ARM white papers:
+.. _spec_ref7:
+[7] `Cache speculation side-channels https://developer.arm.com/support/arm-security-updates/speculative-processor-vulnerability/download-the-whitepaper`_.
+.. _spec_ref8:
+[8] `Cache speculation issues update https://developer.arm.com/support/arm-security-updates/speculative-processor-vulnerability/latest-updates/cache-speculation-issues-update`_.
+Google white paper:
+.. _spec_ref9:
+[9] `Retpoline: a software construct for preventing branch-target-injection https://support.google.com/faqs/answer/7625886`_.
+MIPS white paper:
+.. _spec_ref10:
+[10] `MIPS: response on speculative execution and side channel vulnerabilities https://www.mips.com/blog/mips-response-on-speculative-execution-and-side-channel-vulnerabilities/`_.
+Academic papers:
+.. _spec_ref11:
+[11] `Spectre Attacks: Exploiting Speculative Execution https://spectreattack.com/spectre.pdf`_.
+.. _spec_ref12:
+[12] `NetSpectre: Read Arbitrary Memory over Network https://arxiv.org/abs/1807.10535`_.
+.. _spec_ref13:
+[13] `Spectre Returns! Speculation Attacks using the Return Stack Buffer https://www.usenix.org/system/files/conference/woot18/woot18-paper-koruyeh.pdf`_. diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt index 138f6664b2e2..0082d1e56999 100644 --- a/Documentation/admin-guide/kernel-parameters.txt +++ b/Documentation/admin-guide/kernel-parameters.txt @@ -5102,12 +5102,6 @@ emulate [default] Vsyscalls turn into traps and are emulated reasonably safely.
native Vsyscalls are native syscall instructions.
This is a little bit faster than trapping
and makes a few dynamic recompilers work
better than they would in emulation mode.
It also makes exploits much easier to write.
none Vsyscalls don't work at all. This makes them quite hard to use for exploits but might break your system.
diff --git a/Documentation/userspace-api/spec_ctrl.rst b/Documentation/userspace-api/spec_ctrl.rst index 1129c7550a48..7ddd8f667459 100644 --- a/Documentation/userspace-api/spec_ctrl.rst +++ b/Documentation/userspace-api/spec_ctrl.rst @@ -49,6 +49,8 @@ If PR_SPEC_PRCTL is set, then the per-task control of the mitigation is available. If not set, prctl(PR_SET_SPECULATION_CTRL) for the speculation misfeature will fail.
+.. _set_spec_ctrl:
PR_SET_SPECULATION_CTRL
diff --git a/Makefile b/Makefile index 3e4868a6498b..d8f5dbfd6b76 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ # SPDX-License-Identifier: GPL-2.0 VERSION = 5 PATCHLEVEL = 2 -SUBLEVEL = 0 +SUBLEVEL = 1 EXTRAVERSION = NAME = Bobtail Squid
diff --git a/arch/x86/kernel/ptrace.c b/arch/x86/kernel/ptrace.c index a166c960bc9e..e9d0bc3a5e88 100644 --- a/arch/x86/kernel/ptrace.c +++ b/arch/x86/kernel/ptrace.c @@ -25,6 +25,7 @@ #include <linux/rcupdate.h> #include <linux/export.h> #include <linux/context_tracking.h> +#include <linux/nospec.h>
#include <linux/uaccess.h> #include <asm/pgtable.h> @@ -643,9 +644,11 @@ static unsigned long ptrace_get_debugreg(struct task_struct *tsk, int n) { struct thread_struct *thread = &tsk->thread; unsigned long val = 0;
int index = n;
if (n < HBP_NUM) {
struct perf_event *bp = thread->ptrace_bps[n];
struct perf_event *bp = thread->ptrace_bps[index];
index = array_index_nospec(index, HBP_NUM);
if (bp) val = bp->hw.info.address;
diff --git a/arch/x86/kernel/tls.c b/arch/x86/kernel/tls.c index a5b802a12212..71d3fef1edc9 100644 --- a/arch/x86/kernel/tls.c +++ b/arch/x86/kernel/tls.c @@ -5,6 +5,7 @@ #include <linux/user.h> #include <linux/regset.h> #include <linux/syscalls.h> +#include <linux/nospec.h>
#include <linux/uaccess.h> #include <asm/desc.h> @@ -220,6 +221,7 @@ int do_get_thread_area(struct task_struct *p, int idx, struct user_desc __user *u_info) { struct user_desc info;
int index;
if (idx == -1 && get_user(idx, &u_info->entry_number)) return -EFAULT;
@@ -227,8 +229,11 @@ int do_get_thread_area(struct task_struct *p, int idx, if (idx < GDT_ENTRY_TLS_MIN || idx > GDT_ENTRY_TLS_MAX) return -EINVAL;
- fill_user_desc(&info, idx,
&p->thread.tls_array[idx - GDT_ENTRY_TLS_MIN]);
index = idx - GDT_ENTRY_TLS_MIN;
index = array_index_nospec(index,
GDT_ENTRY_TLS_MAX - GDT_ENTRY_TLS_MIN + 1);
fill_user_desc(&info, idx, &p->thread.tls_array[index]);
if (copy_to_user(u_info, &info, sizeof(info))) return -EFAULT;
diff --git a/arch/x86/kernel/vmlinux.lds.S b/arch/x86/kernel/vmlinux.lds.S index 0850b5149345..4d1517022a14 100644 --- a/arch/x86/kernel/vmlinux.lds.S +++ b/arch/x86/kernel/vmlinux.lds.S @@ -141,10 +141,10 @@ SECTIONS *(.text.__x86.indirect_thunk) __indirect_thunk_end = .; #endif
} :text = 0x9090
/* End of text section */
_etext = .;
/* End of text section */
_etext = .;
} :text = 0x9090
NOTES :text :note
diff --git a/block/bfq-iosched.c b/block/bfq-iosched.c index f9269ae6da9c..e5db3856b194 100644 --- a/block/bfq-iosched.c +++ b/block/bfq-iosched.c @@ -4584,6 +4584,7 @@ static void bfq_exit_icq_bfqq(struct bfq_io_cq *bic, bool is_sync) unsigned long flags;
spin_lock_irqsave(&bfqd->lock, flags);
bfq_exit_bfqq(bfqd, bfqq); bic_set_bfqq(bic, NULL, is_sync); spin_unlock_irqrestore(&bfqd->lock, flags);bfqq->bic = NULL;
diff --git a/block/bio.c b/block/bio.c index ce797d73bb43..67bba12d273b 100644 --- a/block/bio.c +++ b/block/bio.c @@ -731,7 +731,7 @@ static int __bio_add_pc_page(struct request_queue *q, struct bio *bio, } }
- if (bio_full(bio))
if (bio_full(bio, len)) return 0;
if (bio->bi_phys_segments >= queue_max_segments(q))
@@ -807,7 +807,7 @@ void __bio_add_page(struct bio *bio, struct page *page, struct bio_vec *bv = &bio->bi_io_vec[bio->bi_vcnt];
WARN_ON_ONCE(bio_flagged(bio, BIO_CLONED));
- WARN_ON_ONCE(bio_full(bio));
WARN_ON_ONCE(bio_full(bio, len));
bv->bv_page = page; bv->bv_offset = off;
@@ -834,7 +834,7 @@ int bio_add_page(struct bio *bio, struct page *page, bool same_page = false;
if (!__bio_try_merge_page(bio, page, len, offset, &same_page)) {
if (bio_full(bio))
__bio_add_page(bio, page, len, offset); }if (bio_full(bio, len)) return 0;
@@ -922,7 +922,7 @@ static int __bio_iov_iter_get_pages(struct bio *bio, struct iov_iter *iter) if (same_page) put_page(page); } else {
if (WARN_ON_ONCE(bio_full(bio)))
}if (WARN_ON_ONCE(bio_full(bio, len))) return -EINVAL; __bio_add_page(bio, page, len, offset);
@@ -966,7 +966,7 @@ int bio_iov_iter_get_pages(struct bio *bio, struct iov_iter *iter) ret = __bio_iov_bvec_add_pages(bio, iter); else ret = __bio_iov_iter_get_pages(bio, iter);
- } while (!ret && iov_iter_count(iter) && !bio_full(bio));
} while (!ret && iov_iter_count(iter) && !bio_full(bio, 0));
if (iov_iter_bvec_no_ref(iter)) bio_set_flag(bio, BIO_NO_PAGE_REF);
diff --git a/crypto/lrw.c b/crypto/lrw.c index 58009cf63a6e..be829f6afc8e 100644 --- a/crypto/lrw.c +++ b/crypto/lrw.c @@ -384,7 +384,7 @@ static int create(struct crypto_template *tmpl, struct rtattr **tb) inst->alg.base.cra_priority = alg->base.cra_priority; inst->alg.base.cra_blocksize = LRW_BLOCK_SIZE; inst->alg.base.cra_alignmask = alg->base.cra_alignmask |
(__alignof__(__be32) - 1);
(__alignof__(be128) - 1);
inst->alg.ivsize = LRW_BLOCK_SIZE; inst->alg.min_keysize = crypto_skcipher_alg_min_keysize(alg) +
diff --git a/drivers/android/binder.c b/drivers/android/binder.c index bc26b5511f0a..38a59a630cd4 100644 --- a/drivers/android/binder.c +++ b/drivers/android/binder.c @@ -2059,10 +2059,9 @@ static size_t binder_get_object(struct binder_proc *proc,
read_size = min_t(size_t, sizeof(*object), buffer->data_size - offset); if (offset > buffer->data_size || read_size < sizeof(*hdr) ||
!IS_ALIGNED(offset, sizeof(u32)))
binder_alloc_copy_from_buffer(&proc->alloc, object, buffer,
return 0;offset, read_size))
binder_alloc_copy_from_buffer(&proc->alloc, object, buffer,
offset, read_size);
/* Ok, now see if we read a complete object. */ hdr = &object->hdr;
@@ -2131,8 +2130,10 @@ static struct binder_buffer_object *binder_validate_ptr( return NULL;
buffer_offset = start_offset + sizeof(binder_size_t) * index;
- binder_alloc_copy_from_buffer(&proc->alloc, &object_offset,
b, buffer_offset, sizeof(object_offset));
- if (binder_alloc_copy_from_buffer(&proc->alloc, &object_offset,
b, buffer_offset,
sizeof(object_offset)))
object_size = binder_get_object(proc, b, object_offset, object); if (!object_size || object->hdr.type != BINDER_TYPE_PTR) return NULL;return NULL;
@@ -2212,10 +2213,12 @@ static bool binder_validate_fixup(struct binder_proc *proc, return false; last_min_offset = last_bbo->parent_offset + sizeof(uintptr_t); buffer_offset = objects_start_offset +
sizeof(binder_size_t) * last_bbo->parent,
binder_alloc_copy_from_buffer(&proc->alloc, &last_obj_offset,
b, buffer_offset,
sizeof(last_obj_offset));
sizeof(binder_size_t) * last_bbo->parent;
if (binder_alloc_copy_from_buffer(&proc->alloc,
&last_obj_offset,
b, buffer_offset,
sizeof(last_obj_offset)))
} return (fixup_offset >= last_min_offset);return false;
} @@ -2301,15 +2304,15 @@ static void binder_transaction_buffer_release(struct binder_proc *proc, for (buffer_offset = off_start_offset; buffer_offset < off_end_offset; buffer_offset += sizeof(binder_size_t)) { struct binder_object_header *hdr;
size_t object_size;
struct binder_object object; binder_size_t object_offset;size_t object_size = 0;
binder_alloc_copy_from_buffer(&proc->alloc, &object_offset,
buffer, buffer_offset,
sizeof(object_offset));
object_size = binder_get_object(proc, buffer,
object_offset, &object);
if (!binder_alloc_copy_from_buffer(&proc->alloc, &object_offset,
buffer, buffer_offset,
sizeof(object_offset)))
object_size = binder_get_object(proc, buffer,
if (object_size == 0) { pr_err("transaction release %d bad object at offset %lld, size %zd\n", debug_id, (u64)object_offset, buffer->data_size);object_offset, &object);
@@ -2432,15 +2435,16 @@ static void binder_transaction_buffer_release(struct binder_proc *proc, for (fd_index = 0; fd_index < fda->num_fds; fd_index++) { u32 fd;
int err; binder_size_t offset = fda_offset + fd_index * sizeof(fd);
binder_alloc_copy_from_buffer(&proc->alloc,
&fd,
buffer,
offset,
sizeof(fd));
binder_deferred_fd_close(fd);
err = binder_alloc_copy_from_buffer(
&proc->alloc, &fd, buffer,
offset, sizeof(fd));
WARN_ON(err);
if (!err)
} break; default:binder_deferred_fd_close(fd); }
@@ -2683,11 +2687,12 @@ static int binder_translate_fd_array(struct binder_fd_array_object *fda, int ret; binder_size_t offset = fda_offset + fdi * sizeof(fd);
binder_alloc_copy_from_buffer(&target_proc->alloc,
&fd, t->buffer,
offset, sizeof(fd));
ret = binder_translate_fd(fd, offset, t, thread,
in_reply_to);
ret = binder_alloc_copy_from_buffer(&target_proc->alloc,
&fd, t->buffer,
offset, sizeof(fd));
if (!ret)
ret = binder_translate_fd(fd, offset, t, thread,
if (ret < 0) return ret; }in_reply_to);
@@ -2740,8 +2745,12 @@ static int binder_fixup_parent(struct binder_transaction *t, } buffer_offset = bp->parent_offset + (uintptr_t)parent->buffer - (uintptr_t)b->user_data;
- binder_alloc_copy_to_buffer(&target_proc->alloc, b, buffer_offset,
&bp->buffer, sizeof(bp->buffer));
if (binder_alloc_copy_to_buffer(&target_proc->alloc, b, buffer_offset,
&bp->buffer, sizeof(bp->buffer))) {
binder_user_error("%d:%d got transaction with invalid parent offset\n",
proc->pid, thread->pid);
return -EINVAL;
}
return 0;
} @@ -3160,15 +3169,20 @@ static void binder_transaction(struct binder_proc *proc, goto err_binder_alloc_buf_failed; } if (secctx) {
int err;
size_t buf_offset = ALIGN(tr->data_size, sizeof(void *)) + ALIGN(tr->offsets_size, sizeof(void *)) + ALIGN(extra_buffers_size, sizeof(void *)) - ALIGN(secctx_sz, sizeof(u64));
t->security_ctx = (uintptr_t)t->buffer->user_data + buf_offset;
binder_alloc_copy_to_buffer(&target_proc->alloc,
t->buffer, buf_offset,
secctx, secctx_sz);
err = binder_alloc_copy_to_buffer(&target_proc->alloc,
t->buffer, buf_offset,
secctx, secctx_sz);
if (err) {
t->security_ctx = 0;
WARN_ON(1);
security_release_secctx(secctx, secctx_sz); secctx = NULL; }}
@@ -3234,11 +3248,16 @@ static void binder_transaction(struct binder_proc *proc, struct binder_object object; binder_size_t object_offset;
binder_alloc_copy_from_buffer(&target_proc->alloc,
&object_offset,
t->buffer,
buffer_offset,
sizeof(object_offset));
if (binder_alloc_copy_from_buffer(&target_proc->alloc,
&object_offset,
t->buffer,
buffer_offset,
sizeof(object_offset))) {
return_error = BR_FAILED_REPLY;
return_error_param = -EINVAL;
return_error_line = __LINE__;
goto err_bad_offset;
object_size = binder_get_object(target_proc, t->buffer, object_offset, &object); if (object_size == 0 || object_offset < off_min) {}
@@ -3262,15 +3281,17 @@ static void binder_transaction(struct binder_proc *proc,
fp = to_flat_binder_object(hdr); ret = binder_translate_binder(fp, t, thread);
if (ret < 0) {
if (ret < 0 ||
binder_alloc_copy_to_buffer(&target_proc->alloc,
t->buffer,
object_offset,
fp, sizeof(*fp))) { return_error = BR_FAILED_REPLY; return_error_param = ret; return_error_line = __LINE__; goto err_translate_failed; }
binder_alloc_copy_to_buffer(&target_proc->alloc,
t->buffer, object_offset,
} break; case BINDER_TYPE_HANDLE: case BINDER_TYPE_WEAK_HANDLE: {fp, sizeof(*fp));
@@ -3278,15 +3299,16 @@ static void binder_transaction(struct binder_proc *proc,
fp = to_flat_binder_object(hdr); ret = binder_translate_handle(fp, t, thread);
if (ret < 0) {
if (ret < 0 ||
binder_alloc_copy_to_buffer(&target_proc->alloc,
t->buffer,
object_offset,
fp, sizeof(*fp))) { return_error = BR_FAILED_REPLY; return_error_param = ret; return_error_line = __LINE__; goto err_translate_failed; }
binder_alloc_copy_to_buffer(&target_proc->alloc,
t->buffer, object_offset,
fp, sizeof(*fp));
} break;
case BINDER_TYPE_FD: {
@@ -3296,16 +3318,17 @@ static void binder_transaction(struct binder_proc *proc, int ret = binder_translate_fd(fp->fd, fd_offset, t, thread, in_reply_to);
if (ret < 0) {
fp->pad_binder = 0;
if (ret < 0 ||
binder_alloc_copy_to_buffer(&target_proc->alloc,
t->buffer,
object_offset,
fp, sizeof(*fp))) { return_error = BR_FAILED_REPLY; return_error_param = ret; return_error_line = __LINE__; goto err_translate_failed; }
fp->pad_binder = 0;
binder_alloc_copy_to_buffer(&target_proc->alloc,
t->buffer, object_offset,
} break; case BINDER_TYPE_FDA: { struct binder_object ptr_object;fp, sizeof(*fp));
@@ -3393,15 +3416,16 @@ static void binder_transaction(struct binder_proc *proc, num_valid, last_fixup_obj_off, last_fixup_min_off);
if (ret < 0) {
if (ret < 0 ||
binder_alloc_copy_to_buffer(&target_proc->alloc,
t->buffer,
object_offset,
bp, sizeof(*bp))) { return_error = BR_FAILED_REPLY; return_error_param = ret; return_error_line = __LINE__; goto err_translate_failed; }
binder_alloc_copy_to_buffer(&target_proc->alloc,
t->buffer, object_offset,
} break;bp, sizeof(*bp)); last_fixup_obj_off = object_offset; last_fixup_min_off = 0;
@@ -4140,20 +4164,27 @@ static int binder_apply_fd_fixups(struct binder_proc *proc, trace_binder_transaction_fd_recv(t, fd, fixup->offset); fd_install(fd, fixup->file); fixup->file = NULL;
binder_alloc_copy_to_buffer(&proc->alloc, t->buffer,
fixup->offset, &fd,
sizeof(u32));
if (binder_alloc_copy_to_buffer(&proc->alloc, t->buffer,
fixup->offset, &fd,
sizeof(u32))) {
ret = -EINVAL;
break;
} list_for_each_entry_safe(fixup, tmp, &t->fd_fixups, fixup_entry) { if (fixup->file) { fput(fixup->file); } else if (ret) { u32 fd;}
binder_alloc_copy_from_buffer(&proc->alloc, &fd,
t->buffer, fixup->offset,
sizeof(fd));
binder_deferred_fd_close(fd);
int err;
err = binder_alloc_copy_from_buffer(&proc->alloc, &fd,
t->buffer,
fixup->offset,
sizeof(fd));
WARN_ON(err);
if (!err)
} list_del(&fixup->fixup_entry); kfree(fixup);binder_deferred_fd_close(fd);
@@ -4268,6 +4299,8 @@ static int binder_thread_read(struct binder_proc *proc, case BINDER_WORK_TRANSACTION_COMPLETE: { binder_inner_proc_unlock(proc); cmd = BR_TRANSACTION_COMPLETE;
kfree(w);
binder_stats_deleted(BINDER_STAT_TRANSACTION_COMPLETE); if (put_user(cmd, (uint32_t __user *)ptr)) return -EFAULT; ptr += sizeof(uint32_t);
@@ -4276,8 +4309,6 @@ static int binder_thread_read(struct binder_proc *proc, binder_debug(BINDER_DEBUG_TRANSACTION_COMPLETE, "%d:%d BR_TRANSACTION_COMPLETE\n", proc->pid, thread->pid);
kfree(w);
} break; case BINDER_WORK_NODE: { struct binder_node *node = container_of(w, struct binder_node, work);binder_stats_deleted(BINDER_STAT_TRANSACTION_COMPLETE);
diff --git a/drivers/android/binder_alloc.c b/drivers/android/binder_alloc.c index ce5603c2291c..6d79a1b0d446 100644 --- a/drivers/android/binder_alloc.c +++ b/drivers/android/binder_alloc.c @@ -1119,15 +1119,16 @@ binder_alloc_copy_user_to_buffer(struct binder_alloc *alloc, return 0; }
-static void binder_alloc_do_buffer_copy(struct binder_alloc *alloc,
bool to_buffer,
struct binder_buffer *buffer,
binder_size_t buffer_offset,
void *ptr,
size_t bytes)
+static int binder_alloc_do_buffer_copy(struct binder_alloc *alloc,
bool to_buffer,
struct binder_buffer *buffer,
binder_size_t buffer_offset,
void *ptr,
size_t bytes)
{ /* All copies must be 32-bit aligned and 32-bit size */
- BUG_ON(!check_buffer(alloc, buffer, buffer_offset, bytes));
if (!check_buffer(alloc, buffer, buffer_offset, bytes))
return -EINVAL;
while (bytes) { unsigned long size;
@@ -1155,25 +1156,26 @@ static void binder_alloc_do_buffer_copy(struct binder_alloc *alloc, ptr = ptr + size; buffer_offset += size; }
- return 0;
}
-void binder_alloc_copy_to_buffer(struct binder_alloc *alloc,
struct binder_buffer *buffer,
binder_size_t buffer_offset,
void *src,
size_t bytes)
+int binder_alloc_copy_to_buffer(struct binder_alloc *alloc,
struct binder_buffer *buffer,
binder_size_t buffer_offset,
void *src,
size_t bytes)
{
- binder_alloc_do_buffer_copy(alloc, true, buffer, buffer_offset,
src, bytes);
- return binder_alloc_do_buffer_copy(alloc, true, buffer, buffer_offset,
src, bytes);
}
-void binder_alloc_copy_from_buffer(struct binder_alloc *alloc,
void *dest,
struct binder_buffer *buffer,
binder_size_t buffer_offset,
size_t bytes)
+int binder_alloc_copy_from_buffer(struct binder_alloc *alloc,
void *dest,
struct binder_buffer *buffer,
binder_size_t buffer_offset,
size_t bytes)
{
- binder_alloc_do_buffer_copy(alloc, false, buffer, buffer_offset,
dest, bytes);
- return binder_alloc_do_buffer_copy(alloc, false, buffer, buffer_offset,
dest, bytes);
}
diff --git a/drivers/android/binder_alloc.h b/drivers/android/binder_alloc.h index 71bfa95f8e09..db9c1b984695 100644 --- a/drivers/android/binder_alloc.h +++ b/drivers/android/binder_alloc.h @@ -159,17 +159,17 @@ binder_alloc_copy_user_to_buffer(struct binder_alloc *alloc, const void __user *from, size_t bytes);
-void binder_alloc_copy_to_buffer(struct binder_alloc *alloc,
struct binder_buffer *buffer,
binder_size_t buffer_offset,
void *src,
size_t bytes);
-void binder_alloc_copy_from_buffer(struct binder_alloc *alloc,
void *dest,
struct binder_buffer *buffer,
binder_size_t buffer_offset,
size_t bytes);
+int binder_alloc_copy_to_buffer(struct binder_alloc *alloc,
struct binder_buffer *buffer,
binder_size_t buffer_offset,
void *src,
size_t bytes);
+int binder_alloc_copy_from_buffer(struct binder_alloc *alloc,
void *dest,
struct binder_buffer *buffer,
binder_size_t buffer_offset,
size_t bytes);
#endif /* _LINUX_BINDER_ALLOC_H */
diff --git a/drivers/char/tpm/tpm-chip.c b/drivers/char/tpm/tpm-chip.c index 90325e1749fb..d47ad10a35fe 100644 --- a/drivers/char/tpm/tpm-chip.c +++ b/drivers/char/tpm/tpm-chip.c @@ -289,15 +289,15 @@ static int tpm_class_shutdown(struct device *dev) { struct tpm_chip *chip = container_of(dev, struct tpm_chip, dev);
- down_write(&chip->ops_sem); if (chip->flags & TPM_CHIP_FLAG_TPM2) {
if (!tpm_chip_start(chip)) { tpm2_shutdown(chip, TPM2_SU_CLEAR); tpm_chip_stop(chip); }down_write(&chip->ops_sem);
chip->ops = NULL;
}up_write(&chip->ops_sem);
chip->ops = NULL;
up_write(&chip->ops_sem);
return 0;
} diff --git a/drivers/char/tpm/tpm1-cmd.c b/drivers/char/tpm/tpm1-cmd.c index 85dcf2654d11..faacbe1ffa1a 100644 --- a/drivers/char/tpm/tpm1-cmd.c +++ b/drivers/char/tpm/tpm1-cmd.c @@ -510,7 +510,7 @@ struct tpm1_get_random_out {
- Return:
- number of bytes read
- -errno or a TPM return code otherwise
- -errno (positive TPM return codes are masked to -EIO)
*/ int tpm1_get_random(struct tpm_chip *chip, u8 *dest, size_t max) { @@ -531,8 +531,11 @@ int tpm1_get_random(struct tpm_chip *chip, u8 *dest, size_t max)
rc = tpm_transmit_cmd(chip, &buf, sizeof(out->rng_data_len), "attempting get random");
if (rc)
if (rc) {
if (rc > 0)
rc = -EIO; goto out;
}
out = (struct tpm1_get_random_out *)&buf.data[TPM_HEADER_SIZE];
diff --git a/drivers/char/tpm/tpm2-cmd.c b/drivers/char/tpm/tpm2-cmd.c index 4de49924cfc4..d103545e4055 100644 --- a/drivers/char/tpm/tpm2-cmd.c +++ b/drivers/char/tpm/tpm2-cmd.c @@ -297,7 +297,7 @@ struct tpm2_get_random_out {
- Return:
- size of the buffer on success,
- -errno otherwise
- -errno otherwise (positive TPM return codes are masked to -EIO)
*/ int tpm2_get_random(struct tpm_chip *chip, u8 *dest, size_t max) { @@ -324,8 +324,11 @@ int tpm2_get_random(struct tpm_chip *chip, u8 *dest, size_t max) offsetof(struct tpm2_get_random_out, buffer), "attempting get random");
if (err)
if (err) {
if (err > 0)
err = -EIO; goto out;
}
out = (struct tpm2_get_random_out *) &buf.data[TPM_HEADER_SIZE];
diff --git a/drivers/crypto/talitos.c b/drivers/crypto/talitos.c index fbc7bf9d7380..427c78d4d948 100644 --- a/drivers/crypto/talitos.c +++ b/drivers/crypto/talitos.c @@ -2339,7 +2339,7 @@ static struct talitos_alg_template driver_algs[] = { .base = { .cra_name = "authenc(hmac(sha1),cbc(aes))", .cra_driver_name = "authenc-hmac-sha1-"
"cbc-aes-talitos",
"cbc-aes-talitos-hsna", .cra_blocksize = AES_BLOCK_SIZE, .cra_flags = CRYPTO_ALG_ASYNC, },
@@ -2384,7 +2384,7 @@ static struct talitos_alg_template driver_algs[] = { .cra_name = "authenc(hmac(sha1)," "cbc(des3_ede))", .cra_driver_name = "authenc-hmac-sha1-"
"cbc-3des-talitos",
"cbc-3des-talitos-hsna", .cra_blocksize = DES3_EDE_BLOCK_SIZE, .cra_flags = CRYPTO_ALG_ASYNC, },
@@ -2427,7 +2427,7 @@ static struct talitos_alg_template driver_algs[] = { .base = { .cra_name = "authenc(hmac(sha224),cbc(aes))", .cra_driver_name = "authenc-hmac-sha224-"
"cbc-aes-talitos",
"cbc-aes-talitos-hsna", .cra_blocksize = AES_BLOCK_SIZE, .cra_flags = CRYPTO_ALG_ASYNC, },
@@ -2472,7 +2472,7 @@ static struct talitos_alg_template driver_algs[] = { .cra_name = "authenc(hmac(sha224)," "cbc(des3_ede))", .cra_driver_name = "authenc-hmac-sha224-"
"cbc-3des-talitos",
"cbc-3des-talitos-hsna", .cra_blocksize = DES3_EDE_BLOCK_SIZE, .cra_flags = CRYPTO_ALG_ASYNC, },
@@ -2515,7 +2515,7 @@ static struct talitos_alg_template driver_algs[] = { .base = { .cra_name = "authenc(hmac(sha256),cbc(aes))", .cra_driver_name = "authenc-hmac-sha256-"
"cbc-aes-talitos",
"cbc-aes-talitos-hsna", .cra_blocksize = AES_BLOCK_SIZE, .cra_flags = CRYPTO_ALG_ASYNC, },
@@ -2560,7 +2560,7 @@ static struct talitos_alg_template driver_algs[] = { .cra_name = "authenc(hmac(sha256)," "cbc(des3_ede))", .cra_driver_name = "authenc-hmac-sha256-"
"cbc-3des-talitos",
"cbc-3des-talitos-hsna", .cra_blocksize = DES3_EDE_BLOCK_SIZE, .cra_flags = CRYPTO_ALG_ASYNC, },
@@ -2689,7 +2689,7 @@ static struct talitos_alg_template driver_algs[] = { .base = { .cra_name = "authenc(hmac(md5),cbc(aes))", .cra_driver_name = "authenc-hmac-md5-"
"cbc-aes-talitos",
"cbc-aes-talitos-hsna", .cra_blocksize = AES_BLOCK_SIZE, .cra_flags = CRYPTO_ALG_ASYNC, },
@@ -2732,7 +2732,7 @@ static struct talitos_alg_template driver_algs[] = { .base = { .cra_name = "authenc(hmac(md5),cbc(des3_ede))", .cra_driver_name = "authenc-hmac-md5-"
"cbc-3des-talitos",
"cbc-3des-talitos-hsna", .cra_blocksize = DES3_EDE_BLOCK_SIZE, .cra_flags = CRYPTO_ALG_ASYNC, },
diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h index b032d3899fa3..bfc584ada4eb 100644 --- a/drivers/hid/hid-ids.h +++ b/drivers/hid/hid-ids.h @@ -1241,6 +1241,7 @@ #define USB_DEVICE_ID_PRIMAX_KEYBOARD 0x4e05 #define USB_DEVICE_ID_PRIMAX_REZEL 0x4e72 #define USB_DEVICE_ID_PRIMAX_PIXART_MOUSE_4D0F 0x4d0f +#define USB_DEVICE_ID_PRIMAX_PIXART_MOUSE_4D65 0x4d65 #define USB_DEVICE_ID_PRIMAX_PIXART_MOUSE_4E22 0x4e22
diff --git a/drivers/hid/hid-quirks.c b/drivers/hid/hid-quirks.c index 671a285724f9..1549c7a2f04c 100644 --- a/drivers/hid/hid-quirks.c +++ b/drivers/hid/hid-quirks.c @@ -130,6 +130,7 @@ static const struct hid_device_id hid_quirks[] = { { HID_USB_DEVICE(USB_VENDOR_ID_PIXART, USB_DEVICE_ID_PIXART_USB_OPTICAL_MOUSE), HID_QUIRK_ALWAYS_POLL }, { HID_USB_DEVICE(USB_VENDOR_ID_PRIMAX, USB_DEVICE_ID_PRIMAX_MOUSE_4D22), HID_QUIRK_ALWAYS_POLL }, { HID_USB_DEVICE(USB_VENDOR_ID_PRIMAX, USB_DEVICE_ID_PRIMAX_PIXART_MOUSE_4D0F), HID_QUIRK_ALWAYS_POLL },
- { HID_USB_DEVICE(USB_VENDOR_ID_PRIMAX, USB_DEVICE_ID_PRIMAX_PIXART_MOUSE_4D65), HID_QUIRK_ALWAYS_POLL }, { HID_USB_DEVICE(USB_VENDOR_ID_PRIMAX, USB_DEVICE_ID_PRIMAX_PIXART_MOUSE_4E22), HID_QUIRK_ALWAYS_POLL }, { HID_USB_DEVICE(USB_VENDOR_ID_PRODIGE, USB_DEVICE_ID_PRODIGE_CORDLESS), HID_QUIRK_NOGET }, { HID_USB_DEVICE(USB_VENDOR_ID_QUANTA, USB_DEVICE_ID_QUANTA_OPTICAL_TOUCH_3001), HID_QUIRK_NOGET },
diff --git a/drivers/hwtracing/coresight/coresight-etb10.c b/drivers/hwtracing/coresight/coresight-etb10.c index 4ee4c80a4354..543cc3d36e1d 100644 --- a/drivers/hwtracing/coresight/coresight-etb10.c +++ b/drivers/hwtracing/coresight/coresight-etb10.c @@ -373,12 +373,10 @@ static void *etb_alloc_buffer(struct coresight_device *csdev, struct perf_event *event, void **pages, int nr_pages, bool overwrite) {
- int node, cpu = event->cpu;
- int node; struct cs_buffers *buf;
- if (cpu == -1)
cpu = smp_processor_id();
- node = cpu_to_node(cpu);
node = (event->cpu == -1) ? NUMA_NO_NODE : cpu_to_node(event->cpu);
buf = kzalloc_node(sizeof(struct cs_buffers), GFP_KERNEL, node); if (!buf)
diff --git a/drivers/hwtracing/coresight/coresight-funnel.c b/drivers/hwtracing/coresight/coresight-funnel.c index 16b0c0e1e43a..ad6e16c96263 100644 --- a/drivers/hwtracing/coresight/coresight-funnel.c +++ b/drivers/hwtracing/coresight/coresight-funnel.c @@ -241,6 +241,7 @@ static int funnel_probe(struct device *dev, struct resource *res) }
pm_runtime_put(dev);
- ret = 0;
out_disable_clk: if (ret && !IS_ERR_OR_NULL(drvdata->atclk)) diff --git a/drivers/hwtracing/coresight/coresight-tmc-etf.c b/drivers/hwtracing/coresight/coresight-tmc-etf.c index 2527b5d3b65e..8de109de171f 100644 --- a/drivers/hwtracing/coresight/coresight-tmc-etf.c +++ b/drivers/hwtracing/coresight/coresight-tmc-etf.c @@ -378,12 +378,10 @@ static void *tmc_alloc_etf_buffer(struct coresight_device *csdev, struct perf_event *event, void **pages, int nr_pages, bool overwrite) {
- int node, cpu = event->cpu;
- int node; struct cs_buffers *buf;
- if (cpu == -1)
cpu = smp_processor_id();
- node = cpu_to_node(cpu);
node = (event->cpu == -1) ? NUMA_NO_NODE : cpu_to_node(event->cpu);
/* Allocate memory structure for interaction with Perf */ buf = kzalloc_node(sizeof(struct cs_buffers), GFP_KERNEL, node);
diff --git a/drivers/hwtracing/coresight/coresight-tmc-etr.c b/drivers/hwtracing/coresight/coresight-tmc-etr.c index df6e4b0b84e9..9f293b9dce8c 100644 --- a/drivers/hwtracing/coresight/coresight-tmc-etr.c +++ b/drivers/hwtracing/coresight/coresight-tmc-etr.c @@ -1178,14 +1178,11 @@ static struct etr_buf * alloc_etr_buf(struct tmc_drvdata *drvdata, struct perf_event *event, int nr_pages, void **pages, bool snapshot) {
- int node, cpu = event->cpu;
- int node; struct etr_buf *etr_buf; unsigned long size;
- if (cpu == -1)
cpu = smp_processor_id();
- node = cpu_to_node(cpu);
- node = (event->cpu == -1) ? NUMA_NO_NODE : cpu_to_node(event->cpu); /*
- Try to match the perf ring buffer size if it is larger
- than the size requested via sysfs.
@@ -1317,13 +1314,11 @@ static struct etr_perf_buffer * tmc_etr_setup_perf_buf(struct tmc_drvdata *drvdata, struct perf_event *event, int nr_pages, void **pages, bool snapshot) {
- int node, cpu = event->cpu;
- int node; struct etr_buf *etr_buf; struct etr_perf_buffer *etr_perf;
- if (cpu == -1)
cpu = smp_processor_id();
- node = cpu_to_node(cpu);
node = (event->cpu == -1) ? NUMA_NO_NODE : cpu_to_node(event->cpu);
etr_perf = kzalloc_node(sizeof(*etr_perf), GFP_KERNEL, node); if (!etr_perf)
diff --git a/drivers/iio/adc/stm32-adc-core.c b/drivers/iio/adc/stm32-adc-core.c index 2327ec18b40c..1f7ce5186dfc 100644 --- a/drivers/iio/adc/stm32-adc-core.c +++ b/drivers/iio/adc/stm32-adc-core.c @@ -87,6 +87,7 @@ struct stm32_adc_priv_cfg {
- @domain: irq domain reference
- @aclk: clock reference for the analog circuitry
- @bclk: bus clock common for all ADCs, depends on part used
- @vdda: vdda analog supply reference
- @vref: regulator reference
- @cfg: compatible configuration data
- @common: common data for all ADC instances
@@ -97,6 +98,7 @@ struct stm32_adc_priv { struct irq_domain *domain; struct clk *aclk; struct clk *bclk;
- struct regulator *vdda; struct regulator *vref; const struct stm32_adc_priv_cfg *cfg; struct stm32_adc_common common;
@@ -394,10 +396,16 @@ static int stm32_adc_core_hw_start(struct device *dev) struct stm32_adc_priv *priv = to_stm32_adc_priv(common); int ret;
- ret = regulator_enable(priv->vdda);
- if (ret < 0) {
dev_err(dev, "vdda enable failed %d\n", ret);
return ret;
- }
- ret = regulator_enable(priv->vref); if (ret < 0) { dev_err(dev, "vref enable failed\n");
return ret;
goto err_vdda_disable;
}
if (priv->bclk) {
@@ -425,6 +433,8 @@ static int stm32_adc_core_hw_start(struct device *dev) clk_disable_unprepare(priv->bclk); err_regulator_disable: regulator_disable(priv->vref); +err_vdda_disable:
regulator_disable(priv->vdda);
return ret;
} @@ -441,6 +451,7 @@ static void stm32_adc_core_hw_stop(struct device *dev) if (priv->bclk) clk_disable_unprepare(priv->bclk); regulator_disable(priv->vref);
- regulator_disable(priv->vdda);
}
static int stm32_adc_probe(struct platform_device *pdev) @@ -468,6 +479,14 @@ static int stm32_adc_probe(struct platform_device *pdev) return PTR_ERR(priv->common.base); priv->common.phys_base = res->start;
- priv->vdda = devm_regulator_get(&pdev->dev, "vdda");
- if (IS_ERR(priv->vdda)) {
ret = PTR_ERR(priv->vdda);
if (ret != -EPROBE_DEFER)
dev_err(&pdev->dev, "vdda get failed, %d\n", ret);
return ret;
- }
- priv->vref = devm_regulator_get(&pdev->dev, "vref"); if (IS_ERR(priv->vref)) { ret = PTR_ERR(priv->vref);
diff --git a/drivers/media/dvb-frontends/stv0297.c b/drivers/media/dvb-frontends/stv0297.c index dac396c95a59..6d5962d5697a 100644 --- a/drivers/media/dvb-frontends/stv0297.c +++ b/drivers/media/dvb-frontends/stv0297.c @@ -682,7 +682,7 @@ static const struct dvb_frontend_ops stv0297_ops = { .delsys = { SYS_DVBC_ANNEX_A }, .info = { .name = "ST STV0297 DVB-C",
.frequency_min_hz = 470 * MHz,
.frequency_max_hz = 862 * MHz, .frequency_stepsize_hz = 62500, .symbol_rate_min = 870000,.frequency_min_hz = 47 * MHz,
diff --git a/drivers/misc/lkdtm/Makefile b/drivers/misc/lkdtm/Makefile index 951c984de61a..fb10eafe9bde 100644 --- a/drivers/misc/lkdtm/Makefile +++ b/drivers/misc/lkdtm/Makefile @@ -15,8 +15,7 @@ KCOV_INSTRUMENT_rodata.o := n
OBJCOPYFLAGS := OBJCOPYFLAGS_rodata_objcopy.o := \
--set-section-flags .text=alloc,readonly \
--rename-section .text=.rodata
--rename-section .text=.rodata,alloc,readonly,load
targets += rodata.o rodata_objcopy.o $(obj)/rodata_objcopy.o: $(obj)/rodata.o FORCE $(call if_changed,objcopy) diff --git a/drivers/misc/vmw_vmci/vmci_context.c b/drivers/misc/vmw_vmci/vmci_context.c index 300ed69fe2c7..16695366ec92 100644 --- a/drivers/misc/vmw_vmci/vmci_context.c +++ b/drivers/misc/vmw_vmci/vmci_context.c @@ -21,6 +21,9 @@ #include "vmci_driver.h" #include "vmci_event.h"
+/* Use a wide upper bound for the maximum contexts. */ +#define VMCI_MAX_CONTEXTS 2000
/*
- List of current VMCI contexts. Contexts can be added by
- vmci_ctx_create() and removed via vmci_ctx_destroy().
@@ -117,19 +120,22 @@ struct vmci_ctx *vmci_ctx_create(u32 cid, u32 priv_flags, /* Initialize host-specific VMCI context. */ init_waitqueue_head(&context->host_context.wait_queue);
- context->queue_pair_array = vmci_handle_arr_create(0);
- context->queue_pair_array =
if (!context->queue_pair_array) { error = -ENOMEM; goto err_free_ctx; }vmci_handle_arr_create(0, VMCI_MAX_GUEST_QP_COUNT);
- context->doorbell_array = vmci_handle_arr_create(0);
- context->doorbell_array =
if (!context->doorbell_array) { error = -ENOMEM; goto err_free_qp_array; }vmci_handle_arr_create(0, VMCI_MAX_GUEST_DOORBELL_COUNT);
- context->pending_doorbell_array = vmci_handle_arr_create(0);
- context->pending_doorbell_array =
if (!context->pending_doorbell_array) { error = -ENOMEM; goto err_free_db_array;vmci_handle_arr_create(0, VMCI_MAX_GUEST_DOORBELL_COUNT);
@@ -204,7 +210,7 @@ static int ctx_fire_notification(u32 context_id, u32 priv_flags) * We create an array to hold the subscribers we find when * scanning through all contexts. */
- subscriber_array = vmci_handle_arr_create(0);
- subscriber_array = vmci_handle_arr_create(0, VMCI_MAX_CONTEXTS); if (subscriber_array == NULL) return VMCI_ERROR_NO_MEM;
@@ -623,20 +629,26 @@ int vmci_ctx_add_notification(u32 context_id, u32 remote_cid)
spin_lock(&context->lock);
- list_for_each_entry(n, &context->notifier_list, node) {
if (vmci_handle_is_equal(n->handle, notifier->handle)) {
exists = true;
break;
- if (context->n_notifiers < VMCI_MAX_CONTEXTS) {
list_for_each_entry(n, &context->notifier_list, node) {
if (vmci_handle_is_equal(n->handle, notifier->handle)) {
exists = true;
break;
}}
}
if (exists) {
kfree(notifier);
result = VMCI_ERROR_ALREADY_EXISTS;
if (exists) {
kfree(notifier);
result = VMCI_ERROR_ALREADY_EXISTS;
} else {
list_add_tail_rcu(¬ifier->node,
&context->notifier_list);
context->n_notifiers++;
result = VMCI_SUCCESS;
} else {}
list_add_tail_rcu(¬ifier->node, &context->notifier_list);
context->n_notifiers++;
result = VMCI_SUCCESS;
kfree(notifier);
result = VMCI_ERROR_NO_MEM;
}
spin_unlock(&context->lock);
@@ -721,8 +733,7 @@ static int vmci_ctx_get_chkpt_doorbells(struct vmci_ctx *context, u32 *buf_size, void **pbuf) { struct dbell_cpt_state *dbells;
- size_t n_doorbells;
- int i;
u32 i, n_doorbells;
n_doorbells = vmci_handle_arr_get_size(context->doorbell_array); if (n_doorbells > 0) {
@@ -860,7 +871,8 @@ int vmci_ctx_rcv_notifications_get(u32 context_id, spin_lock(&context->lock);
*db_handle_array = context->pending_doorbell_array;
- context->pending_doorbell_array = vmci_handle_arr_create(0);
- context->pending_doorbell_array =
if (!context->pending_doorbell_array) { context->pending_doorbell_array = *db_handle_array; *db_handle_array = NULL;vmci_handle_arr_create(0, VMCI_MAX_GUEST_DOORBELL_COUNT);
@@ -942,12 +954,11 @@ int vmci_ctx_dbell_create(u32 context_id, struct vmci_handle handle) return VMCI_ERROR_NOT_FOUND;
spin_lock(&context->lock);
- if (!vmci_handle_arr_has_entry(context->doorbell_array, handle)) {
vmci_handle_arr_append_entry(&context->doorbell_array, handle);
result = VMCI_SUCCESS;
- } else {
- if (!vmci_handle_arr_has_entry(context->doorbell_array, handle))
result = vmci_handle_arr_append_entry(&context->doorbell_array,
handle);
- else result = VMCI_ERROR_DUPLICATE_ENTRY;
}
spin_unlock(&context->lock); vmci_ctx_put(context);
@@ -1083,15 +1094,16 @@ int vmci_ctx_notify_dbell(u32 src_cid, if (!vmci_handle_arr_has_entry( dst_context->pending_doorbell_array, handle)) {
vmci_handle_arr_append_entry(
result = vmci_handle_arr_append_entry( &dst_context->pending_doorbell_array, handle);
ctx_signal_notify(dst_context);
wake_up(&dst_context->host_context.wait_queue);
if (result == VMCI_SUCCESS) {
ctx_signal_notify(dst_context);
wake_up(&dst_context->host_context.wait_queue);
}
} else {
result = VMCI_SUCCESS; }
} spin_unlock(&dst_context->lock); }result = VMCI_SUCCESS;
@@ -1118,13 +1130,11 @@ int vmci_ctx_qp_create(struct vmci_ctx *context, struct vmci_handle handle) if (context == NULL || vmci_handle_is_invalid(handle)) return VMCI_ERROR_INVALID_ARGS;
- if (!vmci_handle_arr_has_entry(context->queue_pair_array, handle)) {
vmci_handle_arr_append_entry(&context->queue_pair_array,
handle);
result = VMCI_SUCCESS;
- } else {
- if (!vmci_handle_arr_has_entry(context->queue_pair_array, handle))
result = vmci_handle_arr_append_entry(
&context->queue_pair_array, handle);
- else result = VMCI_ERROR_DUPLICATE_ENTRY;
}
return result;
} diff --git a/drivers/misc/vmw_vmci/vmci_handle_array.c b/drivers/misc/vmw_vmci/vmci_handle_array.c index c527388f5d7b..de7fee7ead1b 100644 --- a/drivers/misc/vmw_vmci/vmci_handle_array.c +++ b/drivers/misc/vmw_vmci/vmci_handle_array.c @@ -8,24 +8,29 @@ #include <linux/slab.h> #include "vmci_handle_array.h"
-static size_t handle_arr_calc_size(size_t capacity) +static size_t handle_arr_calc_size(u32 capacity) {
- return sizeof(struct vmci_handle_arr) +
- return VMCI_HANDLE_ARRAY_HEADER_SIZE + capacity * sizeof(struct vmci_handle);
}
-struct vmci_handle_arr *vmci_handle_arr_create(size_t capacity) +struct vmci_handle_arr *vmci_handle_arr_create(u32 capacity, u32 max_capacity) { struct vmci_handle_arr *array;
- if (max_capacity == 0 || capacity > max_capacity)
return NULL;
- if (capacity == 0)
capacity = VMCI_HANDLE_ARRAY_DEFAULT_SIZE;
capacity = min((u32)VMCI_HANDLE_ARRAY_DEFAULT_CAPACITY,
max_capacity);
array = kmalloc(handle_arr_calc_size(capacity), GFP_ATOMIC); if (!array) return NULL;
array->capacity = capacity;
array->max_capacity = max_capacity; array->size = 0;
return array;
@@ -36,27 +41,34 @@ void vmci_handle_arr_destroy(struct vmci_handle_arr *array) kfree(array); }
-void vmci_handle_arr_append_entry(struct vmci_handle_arr **array_ptr,
struct vmci_handle handle)
+int vmci_handle_arr_append_entry(struct vmci_handle_arr **array_ptr,
struct vmci_handle handle)
{ struct vmci_handle_arr *array = *array_ptr;
if (unlikely(array->size >= array->capacity)) { /* reallocate. */ struct vmci_handle_arr *new_array;
size_t new_capacity = array->capacity * VMCI_ARR_CAP_MULT;
size_t new_size = handle_arr_calc_size(new_capacity);
u32 capacity_bump = min(array->max_capacity - array->capacity,
array->capacity);
size_t new_size = handle_arr_calc_size(array->capacity +
capacity_bump);
if (array->size >= array->max_capacity)
return VMCI_ERROR_NO_MEM;
new_array = krealloc(array, new_size, GFP_ATOMIC); if (!new_array)
return;
return VMCI_ERROR_NO_MEM;
new_array->capacity = new_capacity;
new_array->capacity += capacity_bump;
*array_ptr = array = new_array; }
array->entries[array->size] = handle; array->size++;
return VMCI_SUCCESS;
}
/* @@ -66,7 +78,7 @@ struct vmci_handle vmci_handle_arr_remove_entry(struct vmci_handle_arr *array, struct vmci_handle entry_handle) { struct vmci_handle handle = VMCI_INVALID_HANDLE;
- size_t i;
u32 i;
for (i = 0; i < array->size; i++) { if (vmci_handle_is_equal(array->entries[i], entry_handle)) {
@@ -101,7 +113,7 @@ struct vmci_handle vmci_handle_arr_remove_tail(struct vmci_handle_arr *array)
- Handle at given index, VMCI_INVALID_HANDLE if invalid index.
*/ struct vmci_handle -vmci_handle_arr_get_entry(const struct vmci_handle_arr *array, size_t index) +vmci_handle_arr_get_entry(const struct vmci_handle_arr *array, u32 index) { if (unlikely(index >= array->size)) return VMCI_INVALID_HANDLE; @@ -112,7 +124,7 @@ vmci_handle_arr_get_entry(const struct vmci_handle_arr *array, size_t index) bool vmci_handle_arr_has_entry(const struct vmci_handle_arr *array, struct vmci_handle entry_handle) {
- size_t i;
u32 i;
for (i = 0; i < array->size; i++) if (vmci_handle_is_equal(array->entries[i], entry_handle))
diff --git a/drivers/misc/vmw_vmci/vmci_handle_array.h b/drivers/misc/vmw_vmci/vmci_handle_array.h index bd1559a548e9..96193f85be5b 100644 --- a/drivers/misc/vmw_vmci/vmci_handle_array.h +++ b/drivers/misc/vmw_vmci/vmci_handle_array.h @@ -9,32 +9,41 @@ #define _VMCI_HANDLE_ARRAY_H_
#include <linux/vmw_vmci_defs.h> +#include <linux/limits.h> #include <linux/types.h>
-#define VMCI_HANDLE_ARRAY_DEFAULT_SIZE 4 -#define VMCI_ARR_CAP_MULT 2 /* Array capacity multiplier */
struct vmci_handle_arr {
- size_t capacity;
- size_t size;
- u32 capacity;
- u32 max_capacity;
- u32 size;
- u32 pad; struct vmci_handle entries[];
};
-struct vmci_handle_arr *vmci_handle_arr_create(size_t capacity); +#define VMCI_HANDLE_ARRAY_HEADER_SIZE \
- offsetof(struct vmci_handle_arr, entries)
+/* Select a default capacity that results in a 64 byte sized array */ +#define VMCI_HANDLE_ARRAY_DEFAULT_CAPACITY 6 +/* Make sure that the max array size can be expressed by a u32 */ +#define VMCI_HANDLE_ARRAY_MAX_CAPACITY \
- ((U32_MAX - VMCI_HANDLE_ARRAY_HEADER_SIZE - 1) / \
- sizeof(struct vmci_handle))
+struct vmci_handle_arr *vmci_handle_arr_create(u32 capacity, u32 max_capacity); void vmci_handle_arr_destroy(struct vmci_handle_arr *array); -void vmci_handle_arr_append_entry(struct vmci_handle_arr **array_ptr,
struct vmci_handle handle);
+int vmci_handle_arr_append_entry(struct vmci_handle_arr **array_ptr,
struct vmci_handle handle);
struct vmci_handle vmci_handle_arr_remove_entry(struct vmci_handle_arr *array, struct vmci_handle entry_handle); struct vmci_handle vmci_handle_arr_remove_tail(struct vmci_handle_arr *array); struct vmci_handle -vmci_handle_arr_get_entry(const struct vmci_handle_arr *array, size_t index); +vmci_handle_arr_get_entry(const struct vmci_handle_arr *array, u32 index); bool vmci_handle_arr_has_entry(const struct vmci_handle_arr *array, struct vmci_handle entry_handle); struct vmci_handle *vmci_handle_arr_get_handles(struct vmci_handle_arr *array);
-static inline size_t vmci_handle_arr_get_size( +static inline u32 vmci_handle_arr_get_size( const struct vmci_handle_arr *array) { return array->size; diff --git a/drivers/net/wireless/ath/carl9170/usb.c b/drivers/net/wireless/ath/carl9170/usb.c index e7c3f3b8457d..99f1897a775d 100644 --- a/drivers/net/wireless/ath/carl9170/usb.c +++ b/drivers/net/wireless/ath/carl9170/usb.c @@ -128,6 +128,8 @@ static const struct usb_device_id carl9170_usb_ids[] = { }; MODULE_DEVICE_TABLE(usb, carl9170_usb_ids);
+static struct usb_driver carl9170_driver;
static void carl9170_usb_submit_data_urb(struct ar9170 *ar) { struct urb *urb; @@ -966,32 +968,28 @@ static int carl9170_usb_init_device(struct ar9170 *ar)
static void carl9170_usb_firmware_failed(struct ar9170 *ar) {
- struct device *parent = ar->udev->dev.parent;
- struct usb_device *udev;
- /*
* Store a copy of the usb_device pointer locally.
* This is because device_release_driver initiates
* carl9170_usb_disconnect, which in turn frees our
* driver context (ar).
- /* Store a copies of the usb_interface and usb_device pointer locally.
* This is because release_driver initiates carl9170_usb_disconnect,
*/* which in turn frees our driver context (ar).
- udev = ar->udev;
struct usb_interface *intf = ar->intf;
struct usb_device *udev = ar->udev;
complete(&ar->fw_load_wait);
/* at this point 'ar' could be already freed. Don't use it anymore */
ar = NULL;
/* unbind anything failed */
- if (parent)
device_lock(parent);
- device_release_driver(&udev->dev);
- if (parent)
device_unlock(parent);
- usb_lock_device(udev);
- usb_driver_release_interface(&carl9170_driver, intf);
- usb_unlock_device(udev);
- usb_put_dev(udev);
- usb_put_intf(intf);
}
static void carl9170_usb_firmware_finish(struct ar9170 *ar) {
struct usb_interface *intf = ar->intf; int err;
err = carl9170_parse_firmware(ar);
@@ -1009,7 +1007,7 @@ static void carl9170_usb_firmware_finish(struct ar9170 *ar) goto err_unrx;
complete(&ar->fw_load_wait);
- usb_put_dev(ar->udev);
- usb_put_intf(intf); return;
err_unrx: @@ -1052,7 +1050,6 @@ static int carl9170_usb_probe(struct usb_interface *intf, return PTR_ERR(ar);
udev = interface_to_usbdev(intf);
- usb_get_dev(udev); ar->udev = udev; ar->intf = intf; ar->features = id->driver_info;
@@ -1094,15 +1091,14 @@ static int carl9170_usb_probe(struct usb_interface *intf, atomic_set(&ar->rx_anch_urbs, 0); atomic_set(&ar->rx_pool_urbs, 0);
- usb_get_dev(ar->udev);
usb_get_intf(intf);
carl9170_set_state(ar, CARL9170_STOPPED);
err = request_firmware_nowait(THIS_MODULE, 1, CARL9170FW_NAME, &ar->udev->dev, GFP_KERNEL, ar, carl9170_usb_firmware_step2); if (err) {
usb_put_dev(udev);
usb_put_dev(udev);
carl9170_free(ar); } return err;usb_put_intf(intf);
@@ -1131,7 +1127,6 @@ static void carl9170_usb_disconnect(struct usb_interface *intf)
carl9170_release_firmware(ar); carl9170_free(ar);
- usb_put_dev(udev);
}
#ifdef CONFIG_PM diff --git a/drivers/net/wireless/intersil/p54/p54usb.c b/drivers/net/wireless/intersil/p54/p54usb.c index f937815f0f2c..b94764c88750 100644 --- a/drivers/net/wireless/intersil/p54/p54usb.c +++ b/drivers/net/wireless/intersil/p54/p54usb.c @@ -30,6 +30,8 @@ MODULE_ALIAS("prism54usb"); MODULE_FIRMWARE("isl3886usb"); MODULE_FIRMWARE("isl3887usb");
+static struct usb_driver p54u_driver;
/*
- Note:
@@ -918,9 +920,9 @@ static void p54u_load_firmware_cb(const struct firmware *firmware, { struct p54u_priv *priv = context; struct usb_device *udev = priv->udev;
- struct usb_interface *intf = priv->intf; int err;
- complete(&priv->fw_wait_load); if (firmware) { priv->fw = firmware; err = p54u_start_ops(priv);
@@ -929,26 +931,22 @@ static void p54u_load_firmware_cb(const struct firmware *firmware, dev_err(&udev->dev, "Firmware not found.\n"); }
- if (err) {
struct device *parent = priv->udev->dev.parent;
dev_err(&udev->dev, "failed to initialize device (%d)\n", err);
if (parent)
device_lock(parent);
- complete(&priv->fw_wait_load);
- /*
* At this point p54u_disconnect may have already freed
* the "priv" context. Do not use it anymore!
*/
- priv = NULL;
device_release_driver(&udev->dev);
/*
* At this point p54u_disconnect has already freed
* the "priv" context. Do not use it anymore!
*/
priv = NULL;
- if (err) {
dev_err(&intf->dev, "failed to initialize device (%d)\n", err);
if (parent)
device_unlock(parent);
usb_lock_device(udev);
usb_driver_release_interface(&p54u_driver, intf);
}usb_unlock_device(udev);
- usb_put_dev(udev);
- usb_put_intf(intf);
}
static int p54u_load_firmware(struct ieee80211_hw *dev, @@ -969,14 +967,14 @@ static int p54u_load_firmware(struct ieee80211_hw *dev, dev_info(&priv->udev->dev, "Loading firmware file %s\n", p54u_fwlist[i].fw);
- usb_get_dev(udev);
- usb_get_intf(intf); err = request_firmware_nowait(THIS_MODULE, 1, p54u_fwlist[i].fw, device, GFP_KERNEL, priv, p54u_load_firmware_cb); if (err) { dev_err(&priv->udev->dev, "(p54usb) cannot load firmware %s " "(%d)!\n", p54u_fwlist[i].fw, err);
usb_put_dev(udev);
usb_put_intf(intf);
}
return err;
@@ -1008,8 +1006,6 @@ static int p54u_probe(struct usb_interface *intf, skb_queue_head_init(&priv->rx_queue); init_usb_anchor(&priv->submitted);
- usb_get_dev(udev);
- /* really lazy and simple way of figuring out if we're a 3887 */ /* TODO: should just stick the identification in the device table */ i = intf->altsetting->desc.bNumEndpoints;
@@ -1050,10 +1046,8 @@ static int p54u_probe(struct usb_interface *intf, priv->upload_fw = p54u_upload_firmware_net2280; } err = p54u_load_firmware(dev, intf);
- if (err) {
usb_put_dev(udev);
- if (err) p54_free_common(dev);
- } return err;
}
@@ -1069,7 +1063,6 @@ static void p54u_disconnect(struct usb_interface *intf) wait_for_completion(&priv->fw_wait_load); p54_unregister_common(dev);
- usb_put_dev(interface_to_usbdev(intf)); release_firmware(priv->fw); p54_free_common(dev);
} diff --git a/drivers/net/wireless/intersil/p54/txrx.c b/drivers/net/wireless/intersil/p54/txrx.c index ff9acd1563f4..5892898f8853 100644 --- a/drivers/net/wireless/intersil/p54/txrx.c +++ b/drivers/net/wireless/intersil/p54/txrx.c @@ -139,7 +139,10 @@ static int p54_assign_address(struct p54_common *priv, struct sk_buff *skb) unlikely(GET_HW_QUEUE(skb) == P54_QUEUE_BEACON)) priv->beacon_req_id = data->req_id;
- __skb_queue_after(&priv->tx_queue, target_skb, skb);
- if (target_skb)
__skb_queue_after(&priv->tx_queue, target_skb, skb);
- else
spin_unlock_irqrestore(&priv->tx_queue.lock, flags); return 0;__skb_queue_head(&priv->tx_queue, skb);
} diff --git a/drivers/net/wireless/marvell/mwifiex/fw.h b/drivers/net/wireless/marvell/mwifiex/fw.h index b73f99dc5a72..1fb76d2f5d3f 100644 --- a/drivers/net/wireless/marvell/mwifiex/fw.h +++ b/drivers/net/wireless/marvell/mwifiex/fw.h @@ -1759,9 +1759,10 @@ struct mwifiex_ie_types_wmm_queue_status { struct ieee_types_vendor_header { u8 element_id; u8 len;
- u8 oui[4]; /* 0~2: oui, 3: oui_type */
- u8 oui_subtype;
- u8 version;
- struct {
u8 oui[3];
u8 oui_type;
- } __packed oui;
} __packed;
struct ieee_types_wmm_parameter { @@ -1775,6 +1776,9 @@ struct ieee_types_wmm_parameter { * Version [1] */ struct ieee_types_vendor_header vend_hdr;
- u8 oui_subtype;
- u8 version;
- u8 qos_info_bitmap; u8 reserved; struct ieee_types_wmm_ac_parameters ac_params[IEEE80211_NUM_ACS];
@@ -1792,6 +1796,8 @@ struct ieee_types_wmm_info { * Version [1] */ struct ieee_types_vendor_header vend_hdr;
u8 oui_subtype;
u8 version;
u8 qos_info_bitmap;
} __packed; diff --git a/drivers/net/wireless/marvell/mwifiex/scan.c b/drivers/net/wireless/marvell/mwifiex/scan.c index c269a0de9413..e2786ab612ca 100644 --- a/drivers/net/wireless/marvell/mwifiex/scan.c +++ b/drivers/net/wireless/marvell/mwifiex/scan.c @@ -1361,21 +1361,25 @@ int mwifiex_update_bss_desc_with_ie(struct mwifiex_adapter *adapter, break;
case WLAN_EID_VENDOR_SPECIFIC:
if (element_len + 2 < sizeof(vendor_ie->vend_hdr))
return -EINVAL;
vendor_ie = (struct ieee_types_vendor_specific *) current_ptr;
if (!memcmp
(vendor_ie->vend_hdr.oui, wpa_oui,
sizeof(wpa_oui))) {
/* 802.11 requires at least 3-byte OUI. */
if (element_len < sizeof(vendor_ie->vend_hdr.oui.oui))
return -EINVAL;
/* Not long enough for a match? Skip it. */
if (element_len < sizeof(wpa_oui))
break;
if (!memcmp(&vendor_ie->vend_hdr.oui, wpa_oui,
sizeof(wpa_oui))) { bss_entry->bcn_wpa_ie = (struct ieee_types_vendor_specific *) current_ptr; bss_entry->wpa_offset = (u16) (current_ptr - bss_entry->beacon_buf);
} else if (!memcmp(vendor_ie->vend_hdr.oui, wmm_oui,
} else if (!memcmp(&vendor_ie->vend_hdr.oui, wmm_oui, sizeof(wmm_oui))) { if (total_ie_len == sizeof(struct ieee_types_wmm_parameter) ||
diff --git a/drivers/net/wireless/marvell/mwifiex/sta_ioctl.c b/drivers/net/wireless/marvell/mwifiex/sta_ioctl.c index ebc0e41e5d3b..74e50566db1f 100644 --- a/drivers/net/wireless/marvell/mwifiex/sta_ioctl.c +++ b/drivers/net/wireless/marvell/mwifiex/sta_ioctl.c @@ -1351,7 +1351,7 @@ mwifiex_set_gen_ie_helper(struct mwifiex_private *priv, u8 *ie_data_ptr, /* Test to see if it is a WPA IE, if not, then * it is a gen IE */
if (!memcmp(pvendor_ie->oui, wpa_oui,
if (!memcmp(&pvendor_ie->oui, wpa_oui, sizeof(wpa_oui))) { /* IE is a WPA/WPA2 IE so call set_wpa function */
@@ -1361,7 +1361,7 @@ mwifiex_set_gen_ie_helper(struct mwifiex_private *priv, u8 *ie_data_ptr, goto next_ie; }
if (!memcmp(pvendor_ie->oui, wps_oui,
if (!memcmp(&pvendor_ie->oui, wps_oui, sizeof(wps_oui))) { /* Test to see if it is a WPS IE, * if so, enable wps session flag
diff --git a/drivers/net/wireless/marvell/mwifiex/wmm.c b/drivers/net/wireless/marvell/mwifiex/wmm.c index 407b9932ca4d..64916ba15df5 100644 --- a/drivers/net/wireless/marvell/mwifiex/wmm.c +++ b/drivers/net/wireless/marvell/mwifiex/wmm.c @@ -240,7 +240,7 @@ mwifiex_wmm_setup_queue_priorities(struct mwifiex_private *priv, mwifiex_dbg(priv->adapter, INFO, "info: WMM Parameter IE: version=%d,\t" "qos_info Parameter Set Count=%d, Reserved=%#x\n",
wmm_ie->vend_hdr.version, wmm_ie->qos_info_bitmap &
IEEE80211_WMM_IE_AP_QOSINFO_PARAM_SET_CNT_MASK, wmm_ie->reserved);wmm_ie->version, wmm_ie->qos_info_bitmap &
diff --git a/drivers/staging/comedi/drivers/amplc_pci230.c b/drivers/staging/comedi/drivers/amplc_pci230.c index 65f60c2b702a..f7e673121864 100644 --- a/drivers/staging/comedi/drivers/amplc_pci230.c +++ b/drivers/staging/comedi/drivers/amplc_pci230.c @@ -2330,7 +2330,8 @@ static irqreturn_t pci230_interrupt(int irq, void *d) devpriv->intr_running = false; spin_unlock_irqrestore(&devpriv->isr_spinlock, irqflags);
- comedi_handle_events(dev, s_ao);
if (s_ao)
comedi_handle_events(dev, s_ao);
comedi_handle_events(dev, s_ai);
return IRQ_HANDLED;
diff --git a/drivers/staging/comedi/drivers/dt282x.c b/drivers/staging/comedi/drivers/dt282x.c index 3be927f1d3a9..e15e33ed94ae 100644 --- a/drivers/staging/comedi/drivers/dt282x.c +++ b/drivers/staging/comedi/drivers/dt282x.c @@ -557,7 +557,8 @@ static irqreturn_t dt282x_interrupt(int irq, void *d) } #endif comedi_handle_events(dev, s);
- comedi_handle_events(dev, s_ao);
if (s_ao)
comedi_handle_events(dev, s_ao);
return IRQ_RETVAL(handled);
} diff --git a/drivers/staging/fsl-dpaa2/ethsw/ethsw.c b/drivers/staging/fsl-dpaa2/ethsw/ethsw.c index e3c3e427309a..f73edaf6ce87 100644 --- a/drivers/staging/fsl-dpaa2/ethsw/ethsw.c +++ b/drivers/staging/fsl-dpaa2/ethsw/ethsw.c @@ -1086,6 +1086,7 @@ static int port_switchdev_event(struct notifier_block *unused, dev_hold(dev); break; default:
return NOTIFY_DONE; }kfree(switchdev_work);
diff --git a/drivers/staging/mt7621-pci/pci-mt7621.c b/drivers/staging/mt7621-pci/pci-mt7621.c index 03d919a94552..93763d40e3a1 100644 --- a/drivers/staging/mt7621-pci/pci-mt7621.c +++ b/drivers/staging/mt7621-pci/pci-mt7621.c @@ -40,7 +40,7 @@ /* MediaTek specific configuration registers */ #define PCIE_FTS_NUM 0x70c #define PCIE_FTS_NUM_MASK GENMASK(15, 8) -#define PCIE_FTS_NUM_L0(x) ((x) & 0xff << 8) +#define PCIE_FTS_NUM_L0(x) (((x) & 0xff) << 8)
/* rt_sysc_membase relative registers */ #define RALINK_PCIE_CLK_GEN 0x7c diff --git a/drivers/staging/rtl8712/rtl871x_ioctl_linux.c b/drivers/staging/rtl8712/rtl871x_ioctl_linux.c index a7230c0c7b23..8f5a8ac1b010 100644 --- a/drivers/staging/rtl8712/rtl871x_ioctl_linux.c +++ b/drivers/staging/rtl8712/rtl871x_ioctl_linux.c @@ -124,10 +124,91 @@ static inline void handle_group_key(struct ieee_param *param, } }
-static noinline_for_stack char *translate_scan(struct _adapter *padapter,
struct iw_request_info *info,
struct wlan_network *pnetwork,
char *start, char *stop)
+static noinline_for_stack char *translate_scan_wpa(struct iw_request_info *info,
struct wlan_network *pnetwork,
struct iw_event *iwe,
char *start, char *stop)
+{
- /* parsing WPA/WPA2 IE */
- u8 buf[MAX_WPA_IE_LEN];
- u8 wpa_ie[255], rsn_ie[255];
- u16 wpa_len = 0, rsn_len = 0;
- int n, i;
- r8712_get_sec_ie(pnetwork->network.IEs,
pnetwork->network.IELength, rsn_ie, &rsn_len,
wpa_ie, &wpa_len);
- if (wpa_len > 0) {
memset(buf, 0, MAX_WPA_IE_LEN);
n = sprintf(buf, "wpa_ie=");
for (i = 0; i < wpa_len; i++) {
n += snprintf(buf + n, MAX_WPA_IE_LEN - n,
"%02x", wpa_ie[i]);
if (n >= MAX_WPA_IE_LEN)
break;
}
memset(iwe, 0, sizeof(*iwe));
iwe->cmd = IWEVCUSTOM;
iwe->u.data.length = (u16)strlen(buf);
start = iwe_stream_add_point(info, start, stop,
iwe, buf);
memset(iwe, 0, sizeof(*iwe));
iwe->cmd = IWEVGENIE;
iwe->u.data.length = (u16)wpa_len;
start = iwe_stream_add_point(info, start, stop,
iwe, wpa_ie);
- }
- if (rsn_len > 0) {
memset(buf, 0, MAX_WPA_IE_LEN);
n = sprintf(buf, "rsn_ie=");
for (i = 0; i < rsn_len; i++) {
n += snprintf(buf + n, MAX_WPA_IE_LEN - n,
"%02x", rsn_ie[i]);
if (n >= MAX_WPA_IE_LEN)
break;
}
memset(iwe, 0, sizeof(*iwe));
iwe->cmd = IWEVCUSTOM;
iwe->u.data.length = strlen(buf);
start = iwe_stream_add_point(info, start, stop,
iwe, buf);
memset(iwe, 0, sizeof(*iwe));
iwe->cmd = IWEVGENIE;
iwe->u.data.length = rsn_len;
start = iwe_stream_add_point(info, start, stop, iwe,
rsn_ie);
- }
- return start;
+}
+static noinline_for_stack char *translate_scan_wps(struct iw_request_info *info,
struct wlan_network *pnetwork,
struct iw_event *iwe,
char *start, char *stop)
+{
- /* parsing WPS IE */
- u8 wps_ie[512];
- uint wps_ielen;
- if (r8712_get_wps_ie(pnetwork->network.IEs,
pnetwork->network.IELength,
wps_ie, &wps_ielen)) {
if (wps_ielen > 2) {
iwe->cmd = IWEVGENIE;
iwe->u.data.length = (u16)wps_ielen;
start = iwe_stream_add_point(info, start, stop,
iwe, wps_ie);
}
- }
- return start;
+}
+static char *translate_scan(struct _adapter *padapter,
struct iw_request_info *info,
struct wlan_network *pnetwork,
char *start, char *stop)
{ struct iw_event iwe; struct ieee80211_ht_cap *pht_capie; @@ -240,73 +321,11 @@ static noinline_for_stack char *translate_scan(struct _adapter *padapter, /* Check if we added any event */ if ((current_val - start) > iwe_stream_lcp_len(info)) start = current_val;
/* parsing WPA/WPA2 IE */
{
u8 buf[MAX_WPA_IE_LEN];
u8 wpa_ie[255], rsn_ie[255];
u16 wpa_len = 0, rsn_len = 0;
int n;
r8712_get_sec_ie(pnetwork->network.IEs,
pnetwork->network.IELength, rsn_ie, &rsn_len,
wpa_ie, &wpa_len);
if (wpa_len > 0) {
memset(buf, 0, MAX_WPA_IE_LEN);
n = sprintf(buf, "wpa_ie=");
for (i = 0; i < wpa_len; i++) {
n += snprintf(buf + n, MAX_WPA_IE_LEN - n,
"%02x", wpa_ie[i]);
if (n >= MAX_WPA_IE_LEN)
break;
}
memset(&iwe, 0, sizeof(iwe));
iwe.cmd = IWEVCUSTOM;
iwe.u.data.length = (u16)strlen(buf);
start = iwe_stream_add_point(info, start, stop,
&iwe, buf);
memset(&iwe, 0, sizeof(iwe));
iwe.cmd = IWEVGENIE;
iwe.u.data.length = (u16)wpa_len;
start = iwe_stream_add_point(info, start, stop,
&iwe, wpa_ie);
}
if (rsn_len > 0) {
memset(buf, 0, MAX_WPA_IE_LEN);
n = sprintf(buf, "rsn_ie=");
for (i = 0; i < rsn_len; i++) {
n += snprintf(buf + n, MAX_WPA_IE_LEN - n,
"%02x", rsn_ie[i]);
if (n >= MAX_WPA_IE_LEN)
break;
}
memset(&iwe, 0, sizeof(iwe));
iwe.cmd = IWEVCUSTOM;
iwe.u.data.length = strlen(buf);
start = iwe_stream_add_point(info, start, stop,
&iwe, buf);
memset(&iwe, 0, sizeof(iwe));
iwe.cmd = IWEVGENIE;
iwe.u.data.length = rsn_len;
start = iwe_stream_add_point(info, start, stop, &iwe,
rsn_ie);
}
}
{ /* parsing WPS IE */
u8 wps_ie[512];
uint wps_ielen;
- start = translate_scan_wpa(info, pnetwork, &iwe, start, stop);
- start = translate_scan_wps(info, pnetwork, &iwe, start, stop);
if (r8712_get_wps_ie(pnetwork->network.IEs,
pnetwork->network.IELength,
wps_ie, &wps_ielen)) {
if (wps_ielen > 2) {
iwe.cmd = IWEVGENIE;
iwe.u.data.length = (u16)wps_ielen;
start = iwe_stream_add_point(info, start, stop,
&iwe, wps_ie);
}
}
- } /* Add quality statistics */ iwe.cmd = IWEVQUAL; rssi = r8712_signal_scale_mapping(pnetwork->network.Rssi);
diff --git a/drivers/staging/vc04_services/bcm2835-camera/bcm2835-camera.c b/drivers/staging/vc04_services/bcm2835-camera/bcm2835-camera.c index 68f08dc18da9..5e9187edeef4 100644 --- a/drivers/staging/vc04_services/bcm2835-camera/bcm2835-camera.c +++ b/drivers/staging/vc04_services/bcm2835-camera/bcm2835-camera.c @@ -336,16 +336,13 @@ static void buffer_cb(struct vchiq_mmal_instance *instance, return; } else if (length == 0) { /* stream ended */
if (buf) {
/* this should only ever happen if the port is
* disabled and there are buffers still queued
if (dev->capture.frame_count) {
/* empty buffer whilst capturing - expected to be an
* EOS, so grab another frame */
vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR);
pr_debug("Empty buffer");
} else if (dev->capture.frame_count) {
/* grab another frame */ if (is_capturing(dev)) {
pr_debug("Grab another frame");
v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev,
"Grab another frame"); vchiq_mmal_port_parameter_set( instance, dev->capture.camera_port,
@@ -353,8 +350,14 @@ static void buffer_cb(struct vchiq_mmal_instance *instance, &dev->capture.frame_count, sizeof(dev->capture.frame_count)); }
if (vchiq_mmal_submit_buffer(instance, port, buf))
v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev,
} else {"Failed to return EOS buffer");
/* signal frame completion */
/* stopping streaming.
* return buffer, and signal frame completion
*/
} } else {vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR); complete(&dev->capture.frame_cmplt);
@@ -576,6 +579,7 @@ static void stop_streaming(struct vb2_queue *vq) int ret; unsigned long timeout; struct bm2835_mmal_dev *dev = vb2_get_drv_priv(vq);
struct vchiq_mmal_port *port = dev->capture.port;
v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev, "%s: dev:%p\n", __func__, dev);
@@ -599,12 +603,6 @@ static void stop_streaming(struct vb2_queue *vq) &dev->capture.frame_count, sizeof(dev->capture.frame_count));
- /* wait for last frame to complete */
- timeout = wait_for_completion_timeout(&dev->capture.frame_cmplt, HZ);
- if (timeout == 0)
v4l2_err(&dev->v4l2_dev,
"timed out waiting for frame completion\n");
- v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev, "disabling connection\n");
@@ -619,6 +617,21 @@ static void stop_streaming(struct vb2_queue *vq) ret); }
- /* wait for all buffers to be returned */
- while (atomic_read(&port->buffers_with_vpu)) {
v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev,
"%s: Waiting for buffers to be returned - %d outstanding\n",
__func__, atomic_read(&port->buffers_with_vpu));
timeout = wait_for_completion_timeout(&dev->capture.frame_cmplt,
HZ);
if (timeout == 0) {
v4l2_err(&dev->v4l2_dev, "%s: Timeout waiting for buffers to be returned - %d outstanding\n",
__func__,
atomic_read(&port->buffers_with_vpu));
break;
}
- }
- if (disable_camera(dev) < 0) v4l2_err(&dev->v4l2_dev, "Failed to disable camera\n");
} diff --git a/drivers/staging/vc04_services/bcm2835-camera/controls.c b/drivers/staging/vc04_services/bcm2835-camera/controls.c index dade79738a29..12ac3ef61fe6 100644 --- a/drivers/staging/vc04_services/bcm2835-camera/controls.c +++ b/drivers/staging/vc04_services/bcm2835-camera/controls.c @@ -603,15 +603,28 @@ static int ctrl_set_bitrate(struct bm2835_mmal_dev *dev, struct v4l2_ctrl *ctrl, const struct bm2835_mmal_v4l2_ctrl *mmal_ctrl) {
int ret; struct vchiq_mmal_port *encoder_out;
dev->capture.encode_bitrate = ctrl->val;
encoder_out = &dev->component[MMAL_COMPONENT_VIDEO_ENCODE]->output[0];
- return vchiq_mmal_port_parameter_set(dev->instance, encoder_out,
mmal_ctrl->mmal_id, &ctrl->val,
sizeof(ctrl->val));
- ret = vchiq_mmal_port_parameter_set(dev->instance, encoder_out,
mmal_ctrl->mmal_id, &ctrl->val,
sizeof(ctrl->val));
- v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev,
"%s: After: mmal_ctrl:%p ctrl id:0x%x ctrl val:%d ret %d(%d)\n",
__func__, mmal_ctrl, ctrl->id, ctrl->val, ret,
(ret == 0 ? 0 : -EINVAL));
- /*
* Older firmware versions (pre July 2019) have a bug in handling
* MMAL_PARAMETER_VIDEO_BIT_RATE that result in the call
* returning -MMAL_MSG_STATUS_EINVAL. So ignore errors from this call.
*/
- return 0;
}
static int ctrl_set_bitrate_mode(struct bm2835_mmal_dev *dev, diff --git a/drivers/staging/vc04_services/bcm2835-camera/mmal-vchiq.c b/drivers/staging/vc04_services/bcm2835-camera/mmal-vchiq.c index 16af735af5c3..29761f6c3b55 100644 --- a/drivers/staging/vc04_services/bcm2835-camera/mmal-vchiq.c +++ b/drivers/staging/vc04_services/bcm2835-camera/mmal-vchiq.c @@ -161,7 +161,8 @@ struct vchiq_mmal_instance { void *bulk_scratch;
struct idr context_map;
- spinlock_t context_map_lock;
/* protect accesses to context_map */
struct mutex context_map_lock;
/* component to use next */ int component_idx;
@@ -184,10 +185,10 @@ get_msg_context(struct vchiq_mmal_instance *instance) * that when we service the VCHI reply, we can look up what * message is being replied to. */
- spin_lock(&instance->context_map_lock);
- mutex_lock(&instance->context_map_lock); handle = idr_alloc(&instance->context_map, msg_context, 0, 0, GFP_KERNEL);
- spin_unlock(&instance->context_map_lock);
mutex_unlock(&instance->context_map_lock);
if (handle < 0) { kfree(msg_context);
@@ -211,9 +212,9 @@ release_msg_context(struct mmal_msg_context *msg_context) { struct vchiq_mmal_instance *instance = msg_context->instance;
- spin_lock(&instance->context_map_lock);
- mutex_lock(&instance->context_map_lock); idr_remove(&instance->context_map, msg_context->handle);
- spin_unlock(&instance->context_map_lock);
- mutex_unlock(&instance->context_map_lock); kfree(msg_context);
}
@@ -239,6 +240,8 @@ static void buffer_work_cb(struct work_struct *work) struct mmal_msg_context *msg_context = container_of(work, struct mmal_msg_context, u.bulk.work);
- atomic_dec(&msg_context->u.bulk.port->buffers_with_vpu);
- msg_context->u.bulk.port->buffer_cb(msg_context->u.bulk.instance, msg_context->u.bulk.port, msg_context->u.bulk.status,
@@ -287,8 +290,6 @@ static int bulk_receive(struct vchiq_mmal_instance *instance,
/* store length */ msg_context->u.bulk.buffer_used = rd_len;
- msg_context->u.bulk.mmal_flags =
msg_context->u.bulk.dts = msg->u.buffer_from_host.buffer_header.dts; msg_context->u.bulk.pts = msg->u.buffer_from_host.buffer_header.pts;msg->u.buffer_from_host.buffer_header.flags;
@@ -379,6 +380,8 @@ buffer_from_host(struct vchiq_mmal_instance *instance, /* initialise work structure ready to schedule callback */ INIT_WORK(&msg_context->u.bulk.work, buffer_work_cb);
- atomic_inc(&port->buffers_with_vpu);
- /* prep the buffer from host message */ memset(&m, 0xbc, sizeof(m)); /* just to make debug clearer */
@@ -447,6 +450,9 @@ static void buffer_to_host_cb(struct vchiq_mmal_instance *instance, return; }
- msg_context->u.bulk.mmal_flags =
msg->u.buffer_from_host.buffer_header.flags;
- if (msg->h.status != MMAL_MSG_STATUS_SUCCESS) { /* message reception had an error */ pr_warn("error %d in reply\n", msg->h.status);
@@ -1323,16 +1329,6 @@ static int port_enable(struct vchiq_mmal_instance *instance, if (port->enabled) return 0;
- /* ensure there are enough buffers queued to cover the buffer headers */
- if (port->buffer_cb) {
hdr_count = 0;
list_for_each(buf_head, &port->buffers) {
hdr_count++;
}
if (hdr_count < port->current_buffer.num)
return -ENOSPC;
- }
- ret = port_action_port(instance, port, MMAL_MSG_PORT_ACTION_TYPE_ENABLE); if (ret)
@@ -1849,7 +1845,7 @@ int vchiq_mmal_init(struct vchiq_mmal_instance **out_instance)
instance->bulk_scratch = vmalloc(PAGE_SIZE);
- spin_lock_init(&instance->context_map_lock);
mutex_init(&instance->context_map_lock); idr_init_base(&instance->context_map, 1);
params.callback_param = instance;
diff --git a/drivers/staging/vc04_services/bcm2835-camera/mmal-vchiq.h b/drivers/staging/vc04_services/bcm2835-camera/mmal-vchiq.h index 22b839ecd5f0..b0ee1716525b 100644 --- a/drivers/staging/vc04_services/bcm2835-camera/mmal-vchiq.h +++ b/drivers/staging/vc04_services/bcm2835-camera/mmal-vchiq.h @@ -71,6 +71,9 @@ struct vchiq_mmal_port { struct list_head buffers; /* lock to serialise adding and removing buffers from list */ spinlock_t slock;
- /* Count of buffers the VPU has yet to return */
- atomic_t buffers_with_vpu; /* callback on buffer completion */ vchiq_mmal_buffer_cb buffer_cb; /* callback context */
diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_2835_arm.c b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_2835_arm.c index c557c9953724..aa20fcaefa9d 100644 --- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_2835_arm.c +++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_2835_arm.c @@ -523,7 +523,7 @@ create_pagelist(char __user *buf, size_t count, unsigned short type) (g_cache_line_size - 1)))) { char *fragments;
if (down_killable(&g_free_fragments_sema)) {
}if (down_interruptible(&g_free_fragments_sema) != 0) { cleanup_pagelistinfo(pagelistinfo); return NULL;
diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c index ab7d6a0ce94c..62d8f599e765 100644 --- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c +++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c @@ -532,7 +532,8 @@ add_completion(VCHIQ_INSTANCE_T instance, VCHIQ_REASON_T reason, vchiq_log_trace(vchiq_arm_log_level, "%s - completion queue full", __func__); DEBUG_COUNT(COMPLETION_QUEUE_FULL_COUNT);
if (wait_for_completion_killable(&instance->remove_event)) {
if (wait_for_completion_interruptible(
&instance->remove_event)) { vchiq_log_info(vchiq_arm_log_level, "service_callback interrupted"); return VCHIQ_RETRY;
@@ -643,7 +644,7 @@ service_callback(VCHIQ_REASON_T reason, struct vchiq_header *header, }
DEBUG_TRACE(SERVICE_CALLBACK_LINE);
if (wait_for_completion_killable(
if (wait_for_completion_interruptible( &user_service->remove_event) != 0) { vchiq_log_info(vchiq_arm_log_level,
@@ -978,7 +979,7 @@ vchiq_ioctl(struct file *file, unsigned int cmd, unsigned long arg) has been closed until the client library calls the CLOSE_DELIVERED ioctl, signalling close_event. */ if (user_service->close_pending &&
wait_for_completion_killable(
break;wait_for_completion_interruptible( &user_service->close_event)) status = VCHIQ_RETRY;
@@ -1154,7 +1155,7 @@ vchiq_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
DEBUG_TRACE(AWAIT_COMPLETION_LINE); mutex_unlock(&instance->completion_mutex);
rc = wait_for_completion_killable(
rc = wait_for_completion_interruptible( &instance->insert_event); mutex_lock(&instance->completion_mutex); if (rc != 0) {
@@ -1324,7 +1325,7 @@ vchiq_ioctl(struct file *file, unsigned int cmd, unsigned long arg) do { spin_unlock(&msg_queue_spinlock); DEBUG_TRACE(DEQUEUE_MESSAGE_LINE);
if (wait_for_completion_killable(
if (wait_for_completion_interruptible( &user_service->insert_event)) { vchiq_log_info(vchiq_arm_log_level, "DEQUEUE_MESSAGE interrupted");
@@ -2328,7 +2329,7 @@ vchiq_keepalive_thread_func(void *v) while (1) { long rc = 0, uc = 0;
if (wait_for_completion_killable(&arm_state->ka_evt)
if (wait_for_completion_interruptible(&arm_state->ka_evt) != 0) { vchiq_log_error(vchiq_susp_log_level, "%s interrupted", __func__);
@@ -2579,7 +2580,7 @@ block_resume(struct vchiq_arm_state *arm_state) write_unlock_bh(&arm_state->susp_res_lock); vchiq_log_info(vchiq_susp_log_level, "%s wait for previously " "blocked clients", __func__);
if (wait_for_completion_killable_timeout(
if (wait_for_completion_interruptible_timeout( &arm_state->blocked_blocker, timeout_val) <= 0) { vchiq_log_error(vchiq_susp_log_level, "%s wait for "
@@ -2605,7 +2606,7 @@ block_resume(struct vchiq_arm_state *arm_state) write_unlock_bh(&arm_state->susp_res_lock); vchiq_log_info(vchiq_susp_log_level, "%s wait for resume", __func__);
if (wait_for_completion_killable_timeout(
if (wait_for_completion_interruptible_timeout( &arm_state->vc_resume_complete, timeout_val) <= 0) { vchiq_log_error(vchiq_susp_log_level, "%s wait for "
@@ -2812,7 +2813,7 @@ vchiq_arm_force_suspend(struct vchiq_state *state) do { write_unlock_bh(&arm_state->susp_res_lock);
rc = wait_for_completion_killable_timeout(
rc = wait_for_completion_interruptible_timeout( &arm_state->vc_suspend_complete, msecs_to_jiffies(FORCE_SUSPEND_TIMEOUT_MS));
@@ -2908,7 +2909,7 @@ vchiq_arm_allow_resume(struct vchiq_state *state) write_unlock_bh(&arm_state->susp_res_lock);
if (resume) {
if (wait_for_completion_killable(
if (wait_for_completion_interruptible( &arm_state->vc_resume_complete) < 0) { vchiq_log_error(vchiq_susp_log_level, "%s interrupted", __func__);
diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.c b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.c index 0c387b6473a5..44bfa890e0e5 100644 --- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.c +++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.c @@ -395,13 +395,21 @@ remote_event_create(wait_queue_head_t *wq, struct remote_event *event) init_waitqueue_head(wq); }
+/*
- All the event waiting routines in VCHIQ used a custom semaphore
- implementation that filtered most signals. This achieved a behaviour similar
- to the "killable" family of functions. While cleaning up this code all the
- routines where switched to the "interruptible" family of functions, as the
- former was deemed unjustified and the use "killable" set all VCHIQ's
- threads in D state.
- */
static inline int remote_event_wait(wait_queue_head_t *wq, struct remote_event *event) { if (!event->fired) { event->armed = 1; dsb(sy);
if (wait_event_killable(*wq, event->fired)) {
}if (wait_event_interruptible(*wq, event->fired)) { event->armed = 0; return 0;
@@ -560,7 +568,7 @@ reserve_space(struct vchiq_state *state, size_t space, int is_blocking) remote_event_signal(&state->remote->trigger);
if (!is_blocking ||
(wait_for_completion_killable(
}(wait_for_completion_interruptible( &state->slot_available_event))) return NULL; /* No space available */
@@ -830,7 +838,7 @@ queue_message(struct vchiq_state *state, struct vchiq_service *service, spin_unlock("a_spinlock); mutex_unlock(&state->slot_mutex);
if (wait_for_completion_killable(
if (wait_for_completion_interruptible( &state->data_quota_event)) return VCHIQ_RETRY;
@@ -861,7 +869,7 @@ queue_message(struct vchiq_state *state, struct vchiq_service *service, service_quota->slot_use_count); VCHIQ_SERVICE_STATS_INC(service, quota_stalls); mutex_unlock(&state->slot_mutex);
if (wait_for_completion_killable(
if (wait_for_completion_interruptible( &service_quota->quota_event)) return VCHIQ_RETRY; if (service->closing)
@@ -1710,7 +1718,8 @@ parse_rx_slots(struct vchiq_state *state) &service->bulk_rx : &service->bulk_tx;
DEBUG_TRACE(PARSE_LINE);
if (mutex_lock_killable(&service->bulk_mutex)) {
if (mutex_lock_killable(
&service->bulk_mutex) != 0) { DEBUG_TRACE(PARSE_LINE); goto bail_not_ready; }
@@ -2428,7 +2437,7 @@ vchiq_open_service_internal(struct vchiq_service *service, int client_id) QMFLAGS_IS_BLOCKING); if (status == VCHIQ_SUCCESS) { /* Wait for the ACK/NAK */
if (wait_for_completion_killable(&service->remove_event)) {
} else if ((service->srvstate != VCHIQ_SRVSTATE_OPEN) &&if (wait_for_completion_interruptible(&service->remove_event)) { status = VCHIQ_RETRY; vchiq_release_service_internal(service);
@@ -2795,7 +2804,7 @@ vchiq_connect_internal(struct vchiq_state *state, VCHIQ_INSTANCE_T instance) }
if (state->conn_state == VCHIQ_CONNSTATE_CONNECTING) {
if (wait_for_completion_killable(&state->connect))
if (wait_for_completion_interruptible(&state->connect)) return VCHIQ_RETRY;
vchiq_set_conn_state(state, VCHIQ_CONNSTATE_CONNECTED);
@@ -2894,7 +2903,7 @@ vchiq_close_service(VCHIQ_SERVICE_HANDLE_T handle) }
while (1) {
if (wait_for_completion_killable(&service->remove_event)) {
}if (wait_for_completion_interruptible(&service->remove_event)) { status = VCHIQ_RETRY; break;
@@ -2955,7 +2964,7 @@ vchiq_remove_service(VCHIQ_SERVICE_HANDLE_T handle) request_poll(service->state, service, VCHIQ_POLL_REMOVE); } while (1) {
if (wait_for_completion_killable(&service->remove_event)) {
}if (wait_for_completion_interruptible(&service->remove_event)) { status = VCHIQ_RETRY; break;
@@ -3038,7 +3047,7 @@ VCHIQ_STATUS_T vchiq_bulk_transfer(VCHIQ_SERVICE_HANDLE_T handle, VCHIQ_SERVICE_STATS_INC(service, bulk_stalls); do { mutex_unlock(&service->bulk_mutex);
if (wait_for_completion_killable(
if (wait_for_completion_interruptible( &service->bulk_remove_event)) { status = VCHIQ_RETRY; goto error_exit;
@@ -3115,7 +3124,7 @@ VCHIQ_STATUS_T vchiq_bulk_transfer(VCHIQ_SERVICE_HANDLE_T handle,
if (bulk_waiter) { bulk_waiter->bulk = bulk;
if (wait_for_completion_killable(&bulk_waiter->event))
else if (bulk_waiter->actual == VCHIQ_BULK_ACTUAL_ABORTED) status = VCHIQ_ERROR;if (wait_for_completion_interruptible(&bulk_waiter->event)) status = VCHIQ_RETRY;
diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_util.c b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_util.c index 6c519d8e48cb..8ee85c5e6f77 100644 --- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_util.c +++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_util.c @@ -50,7 +50,7 @@ void vchiu_queue_push(struct vchiu_queue *queue, struct vchiq_header *header) return;
while (queue->write == queue->read + queue->size) {
if (wait_for_completion_killable(&queue->pop))
}if (wait_for_completion_interruptible(&queue->pop)) flush_signals(current);
@@ -63,7 +63,7 @@ void vchiu_queue_push(struct vchiu_queue *queue, struct vchiq_header *header) struct vchiq_header *vchiu_queue_peek(struct vchiu_queue *queue) { while (queue->write == queue->read) {
if (wait_for_completion_killable(&queue->push))
}if (wait_for_completion_interruptible(&queue->push)) flush_signals(current);
@@ -77,7 +77,7 @@ struct vchiq_header *vchiu_queue_pop(struct vchiu_queue *queue) struct vchiq_header *header;
while (queue->write == queue->read) {
if (wait_for_completion_killable(&queue->push))
}if (wait_for_completion_interruptible(&queue->push)) flush_signals(current);
diff --git a/drivers/staging/wilc1000/wilc_netdev.c b/drivers/staging/wilc1000/wilc_netdev.c index ba78c08a17f1..5338d7d2b248 100644 --- a/drivers/staging/wilc1000/wilc_netdev.c +++ b/drivers/staging/wilc1000/wilc_netdev.c @@ -530,17 +530,17 @@ static int wilc_wlan_initialize(struct net_device *dev, struct wilc_vif *vif) goto fail_locks; }
if (wl->gpio_irq && init_irq(dev)) {
ret = -EIO;
goto fail_locks;
}
- ret = wlan_initialize_threads(dev); if (ret < 0) { ret = -EIO; goto fail_wilc_wlan; }
if (wl->gpio_irq && init_irq(dev)) {
ret = -EIO;
goto fail_threads;
}
- if (!wl->dev_irq_num && wl->hif_func->enable_interrupt && wl->hif_func->enable_interrupt(wl)) {
@@ -596,7 +596,7 @@ static int wilc_wlan_initialize(struct net_device *dev, struct wilc_vif *vif) fail_irq_init: if (wl->dev_irq_num) deinit_irq(dev);
+fail_threads: wlan_deinitialize_threads(dev); fail_wilc_wlan: wilc_wlan_cleanup(dev); diff --git a/drivers/tty/serial/8250/8250_port.c b/drivers/tty/serial/8250/8250_port.c index d2f3310abe54..682300713be4 100644 --- a/drivers/tty/serial/8250/8250_port.c +++ b/drivers/tty/serial/8250/8250_port.c @@ -1869,8 +1869,7 @@ int serial8250_handle_irq(struct uart_port *port, unsigned int iir)
status = serial_port_in(port, UART_LSR);
- if (status & (UART_LSR_DR | UART_LSR_BI) &&
iir & UART_IIR_RDI) {
- if (status & (UART_LSR_DR | UART_LSR_BI)) { if (!up->dma || handle_rx_dma(up, iir)) status = serial8250_rx_chars(up, status); }
diff --git a/drivers/usb/dwc2/core.c b/drivers/usb/dwc2/core.c index 8b499d643461..8e41d70fd298 100644 --- a/drivers/usb/dwc2/core.c +++ b/drivers/usb/dwc2/core.c @@ -531,7 +531,7 @@ int dwc2_core_reset(struct dwc2_hsotg *hsotg, bool skip_wait) }
/* Wait for AHB master IDLE state */
- if (dwc2_hsotg_wait_bit_set(hsotg, GRSTCTL, GRSTCTL_AHBIDLE, 50)) {
- if (dwc2_hsotg_wait_bit_set(hsotg, GRSTCTL, GRSTCTL_AHBIDLE, 10000)) { dev_warn(hsotg->dev, "%s: HANG! AHB Idle timeout GRSTCTL GRSTCTL_AHBIDLE\n", __func__); return -EBUSY;
diff --git a/drivers/usb/gadget/function/f_fs.c b/drivers/usb/gadget/function/f_fs.c index 47be961f1bf3..c7ed90084d1a 100644 --- a/drivers/usb/gadget/function/f_fs.c +++ b/drivers/usb/gadget/function/f_fs.c @@ -997,7 +997,6 @@ static ssize_t ffs_epfile_io(struct file *file, struct ffs_io_data *io_data) * earlier */ gadget = epfile->ffs->gadget;
io_data->use_sg = gadget->sg_supported && data_len > PAGE_SIZE;
spin_lock_irq(&epfile->ffs->eps_lock); /* In the meantime, endpoint got disabled or changed. */
@@ -1012,6 +1011,8 @@ static ssize_t ffs_epfile_io(struct file *file, struct ffs_io_data *io_data) */ if (io_data->read) data_len = usb_ep_align_maybe(gadget, ep->ep, data_len);
io_data->use_sg = gadget->sg_supported && data_len > PAGE_SIZE;
spin_unlock_irq(&epfile->ffs->eps_lock);
data = ffs_alloc_buffer(io_data, data_len);
diff --git a/drivers/usb/gadget/function/u_ether.c b/drivers/usb/gadget/function/u_ether.c index 737bd77a575d..2929bb47a618 100644 --- a/drivers/usb/gadget/function/u_ether.c +++ b/drivers/usb/gadget/function/u_ether.c @@ -186,11 +186,12 @@ rx_submit(struct eth_dev *dev, struct usb_request *req, gfp_t gfp_flags) out = dev->port_usb->out_ep; else out = NULL;
spin_unlock_irqrestore(&dev->lock, flags);
if (!out)
- {
return -ENOTCONN;spin_unlock_irqrestore(&dev->lock, flags);
}
/* Padding up to RX_EXTRA handles minor disagreements with host.
- Normally we use the USB "terminate on short read" convention;
@@ -214,6 +215,7 @@ rx_submit(struct eth_dev *dev, struct usb_request *req, gfp_t gfp_flags)
if (dev->port_usb->is_fixed) size = max_t(size_t, size, dev->port_usb->fixed_out_len);
spin_unlock_irqrestore(&dev->lock, flags);
skb = __netdev_alloc_skb(dev->net, size + NET_IP_ALIGN, gfp_flags); if (skb == NULL) {
diff --git a/drivers/usb/renesas_usbhs/fifo.c b/drivers/usb/renesas_usbhs/fifo.c index 39fa2fc1b8b7..6036cbae8c78 100644 --- a/drivers/usb/renesas_usbhs/fifo.c +++ b/drivers/usb/renesas_usbhs/fifo.c @@ -802,9 +802,8 @@ static int __usbhsf_dma_map_ctrl(struct usbhs_pkt *pkt, int map) }
static void usbhsf_dma_complete(void *arg); -static void xfer_work(struct work_struct *work) +static void usbhsf_dma_xfer_preparing(struct usbhs_pkt *pkt) {
- struct usbhs_pkt *pkt = container_of(work, struct usbhs_pkt, work); struct usbhs_pipe *pipe = pkt->pipe; struct usbhs_fifo *fifo; struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe);
@@ -812,12 +811,10 @@ static void xfer_work(struct work_struct *work) struct dma_chan *chan; struct device *dev = usbhs_priv_to_dev(priv); enum dma_transfer_direction dir;
unsigned long flags;
usbhs_lock(priv, flags); fifo = usbhs_pipe_to_fifo(pipe); if (!fifo)
goto xfer_work_end;
return;
chan = usbhsf_dma_chan_get(fifo, pkt); dir = usbhs_pipe_is_dir_in(pipe) ? DMA_DEV_TO_MEM : DMA_MEM_TO_DEV;
@@ -826,7 +823,7 @@ static void xfer_work(struct work_struct *work) pkt->trans, dir, DMA_PREP_INTERRUPT | DMA_CTRL_ACK); if (!desc)
goto xfer_work_end;
return;
desc->callback = usbhsf_dma_complete; desc->callback_param = pipe;
@@ -834,7 +831,7 @@ static void xfer_work(struct work_struct *work) pkt->cookie = dmaengine_submit(desc); if (pkt->cookie < 0) { dev_err(dev, "Failed to submit dma descriptor\n");
goto xfer_work_end;
return;
}
dev_dbg(dev, " %s %d (%d/ %d)\n",
@@ -845,8 +842,17 @@ static void xfer_work(struct work_struct *work) dma_async_issue_pending(chan); usbhsf_dma_start(pipe, fifo); usbhs_pipe_enable(pipe); +}
+static void xfer_work(struct work_struct *work) +{
- struct usbhs_pkt *pkt = container_of(work, struct usbhs_pkt, work);
- struct usbhs_pipe *pipe = pkt->pipe;
- struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe);
- unsigned long flags;
-xfer_work_end:
- usbhs_lock(priv, flags);
- usbhsf_dma_xfer_preparing(pkt); usbhs_unlock(priv, flags);
}
@@ -899,8 +905,13 @@ static int usbhsf_dma_prepare_push(struct usbhs_pkt *pkt, int *is_done) pkt->trans = len;
usbhsf_tx_irq_ctrl(pipe, 0);
- INIT_WORK(&pkt->work, xfer_work);
- schedule_work(&pkt->work);
/* FIXME: Workaound for usb dmac that driver can be used in atomic */
if (usbhs_get_dparam(priv, has_usb_dmac)) {
usbhsf_dma_xfer_preparing(pkt);
} else {
INIT_WORK(&pkt->work, xfer_work);
schedule_work(&pkt->work);
}
return 0;
@@ -1006,8 +1017,7 @@ static int usbhsf_dma_prepare_pop_with_usb_dmac(struct usbhs_pkt *pkt,
pkt->trans = pkt->length;
- INIT_WORK(&pkt->work, xfer_work);
- schedule_work(&pkt->work);
usbhsf_dma_xfer_preparing(pkt);
return 0;
diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index 1d8461ae2c34..23669a584bae 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c @@ -1029,6 +1029,7 @@ static const struct usb_device_id id_table_combined[] = { { USB_DEVICE(AIRBUS_DS_VID, AIRBUS_DS_P8GR) }, /* EZPrototypes devices */ { USB_DEVICE(EZPROTOTYPES_VID, HJELMSLUND_USB485_ISO_PID) },
- { USB_DEVICE_INTERFACE_NUMBER(UNJO_VID, UNJO_ISODEBUG_V1_PID, 1) }, { } /* Terminating entry */
};
diff --git a/drivers/usb/serial/ftdi_sio_ids.h b/drivers/usb/serial/ftdi_sio_ids.h index 5755f0df0025..f12d806220b4 100644 --- a/drivers/usb/serial/ftdi_sio_ids.h +++ b/drivers/usb/serial/ftdi_sio_ids.h @@ -1543,3 +1543,9 @@ #define CHETCO_SEASMART_DISPLAY_PID 0xA5AD /* SeaSmart NMEA2000 Display */ #define CHETCO_SEASMART_LITE_PID 0xA5AE /* SeaSmart Lite USB Adapter */ #define CHETCO_SEASMART_ANALOG_PID 0xA5AF /* SeaSmart Analog Adapter */
+/*
- Unjo AB
- */
+#define UNJO_VID 0x22B7 +#define UNJO_ISODEBUG_V1_PID 0x150D diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c index a0aaf0635359..c1582fbd1150 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c @@ -1343,6 +1343,7 @@ static const struct usb_device_id option_ids[] = { .driver_info = RSVD(4) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0414, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0417, 0xff, 0xff, 0xff) },
- { USB_DEVICE_INTERFACE_CLASS(ZTE_VENDOR_ID, 0x0601, 0xff) }, /* GosunCn ZTE WeLink ME3630 (RNDIS mode) */ { USB_DEVICE_INTERFACE_CLASS(ZTE_VENDOR_ID, 0x0602, 0xff) }, /* GosunCn ZTE WeLink ME3630 (MBIM mode) */ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1008, 0xff, 0xff, 0xff), .driver_info = RSVD(4) },
diff --git a/drivers/usb/typec/tps6598x.c b/drivers/usb/typec/tps6598x.c index c674abe3cf99..a38d1409f15b 100644 --- a/drivers/usb/typec/tps6598x.c +++ b/drivers/usb/typec/tps6598x.c @@ -41,7 +41,7 @@ #define TPS_STATUS_VCONN(s) (!!((s) & BIT(7)))
/* TPS_REG_SYSTEM_CONF bits */ -#define TPS_SYSCONF_PORTINFO(c) ((c) & 3) +#define TPS_SYSCONF_PORTINFO(c) ((c) & 7)
enum { TPS_PORTINFO_SINK, @@ -127,7 +127,7 @@ tps6598x_block_read(struct tps6598x *tps, u8 reg, void *val, size_t len) }
static int tps6598x_block_write(struct tps6598x *tps, u8 reg,
void *val, size_t len)
const void *val, size_t len)
{ u8 data[TPS_MAX_LEN + 1];
@@ -173,7 +173,7 @@ static inline int tps6598x_write64(struct tps6598x *tps, u8 reg, u64 val) static inline int tps6598x_write_4cc(struct tps6598x *tps, u8 reg, const char *val) {
- return tps6598x_block_write(tps, reg, &val, sizeof(u32));
- return tps6598x_block_write(tps, reg, val, 4);
}
static int tps6598x_read_partner_identity(struct tps6598x *tps) diff --git a/fs/crypto/policy.c b/fs/crypto/policy.c index d536889ac31b..4941fe8471ce 100644 --- a/fs/crypto/policy.c +++ b/fs/crypto/policy.c @@ -81,6 +81,8 @@ int fscrypt_ioctl_set_policy(struct file *filp, const void __user *arg) if (ret == -ENODATA) { if (!S_ISDIR(inode->i_mode)) ret = -ENOTDIR;
else if (IS_DEADDIR(inode))
else if (!inode->i_sb->s_cop->empty_dir(inode)) ret = -ENOTEMPTY; elseret = -ENOENT;
diff --git a/fs/iomap.c b/fs/iomap.c index 12654c2e78f8..da961fca3180 100644 --- a/fs/iomap.c +++ b/fs/iomap.c @@ -333,7 +333,7 @@ iomap_readpage_actor(struct inode *inode, loff_t pos, loff_t length, void *data, if (iop) atomic_inc(&iop->read_count);
- if (!ctx->bio || !is_contig || bio_full(ctx->bio)) {
- if (!ctx->bio || !is_contig || bio_full(ctx->bio, plen)) { gfp_t gfp = mapping_gfp_constraint(page->mapping, GFP_KERNEL); int nr_vecs = (length + PAGE_SIZE - 1) >> PAGE_SHIFT;
diff --git a/fs/udf/inode.c b/fs/udf/inode.c index e7276932e433..9bb18311a22f 100644 --- a/fs/udf/inode.c +++ b/fs/udf/inode.c @@ -470,13 +470,15 @@ static struct buffer_head *udf_getblk(struct inode *inode, udf_pblk_t block, return NULL; }
-/* Extend the file by 'blocks' blocks, return the number of extents added */ +/* Extend the file with new blocks totaling 'new_block_bytes',
- return the number of extents added
- */
static int udf_do_extend_file(struct inode *inode, struct extent_position *last_pos, struct kernel_long_ad *last_ext,
sector_t blocks)
loff_t new_block_bytes)
{
- sector_t add;
- uint32_t add; int count = 0, fake = !(last_ext->extLength & UDF_EXTENT_LENGTH_MASK); struct super_block *sb = inode->i_sb; struct kernel_lb_addr prealloc_loc = {};
@@ -486,7 +488,7 @@ static int udf_do_extend_file(struct inode *inode,
/* The previous extent is fake and we should not extend by anything * - there's nothing to do... */
- if (!blocks && fake)
if (!new_block_bytes && fake) return 0;
iinfo = UDF_I(inode);
@@ -517,13 +519,12 @@ static int udf_do_extend_file(struct inode *inode, /* Can we merge with the previous extent? */ if ((last_ext->extLength & UDF_EXTENT_FLAG_MASK) == EXT_NOT_RECORDED_NOT_ALLOCATED) {
add = ((1 << 30) - sb->s_blocksize -
(last_ext->extLength & UDF_EXTENT_LENGTH_MASK)) >>
sb->s_blocksize_bits;
if (add > blocks)
add = blocks;
blocks -= add;
last_ext->extLength += add << sb->s_blocksize_bits;
add = (1 << 30) - sb->s_blocksize -
(last_ext->extLength & UDF_EXTENT_LENGTH_MASK);
if (add > new_block_bytes)
add = new_block_bytes;
new_block_bytes -= add;
last_ext->extLength += add;
}
if (fake) {
@@ -544,28 +545,27 @@ static int udf_do_extend_file(struct inode *inode, }
/* Managed to do everything necessary? */
- if (!blocks)
if (!new_block_bytes) goto out;
/* All further extents will be NOT_RECORDED_NOT_ALLOCATED */ last_ext->extLocation.logicalBlockNum = 0; last_ext->extLocation.partitionReferenceNum = 0;
- add = (1 << (30-sb->s_blocksize_bits)) - 1;
- last_ext->extLength = EXT_NOT_RECORDED_NOT_ALLOCATED |
(add << sb->s_blocksize_bits);
add = (1 << 30) - sb->s_blocksize;
last_ext->extLength = EXT_NOT_RECORDED_NOT_ALLOCATED | add;
/* Create enough extents to cover the whole hole */
- while (blocks > add) {
blocks -= add;
- while (new_block_bytes > add) {
err = udf_add_aext(inode, last_pos, &last_ext->extLocation, last_ext->extLength, 1); if (err) return err; count++; }new_block_bytes -= add;
- if (blocks) {
- if (new_block_bytes) { last_ext->extLength = EXT_NOT_RECORDED_NOT_ALLOCATED |
(blocks << sb->s_blocksize_bits);
err = udf_add_aext(inode, last_pos, &last_ext->extLocation, last_ext->extLength, 1); if (err)new_block_bytes;
@@ -596,6 +596,24 @@ static int udf_do_extend_file(struct inode *inode, return count; }
+/* Extend the final block of the file to final_block_len bytes */ +static void udf_do_extend_final_block(struct inode *inode,
struct extent_position *last_pos,
struct kernel_long_ad *last_ext,
uint32_t final_block_len)
+{
- struct super_block *sb = inode->i_sb;
- uint32_t added_bytes;
- added_bytes = final_block_len -
(last_ext->extLength & (sb->s_blocksize - 1));
- last_ext->extLength += added_bytes;
- UDF_I(inode)->i_lenExtents += added_bytes;
- udf_write_aext(inode, last_pos, &last_ext->extLocation,
last_ext->extLength, 1);
+}
static int udf_extend_file(struct inode *inode, loff_t newsize) {
@@ -605,10 +623,12 @@ static int udf_extend_file(struct inode *inode, loff_t newsize) int8_t etype; struct super_block *sb = inode->i_sb; sector_t first_block = newsize >> sb->s_blocksize_bits, offset;
- unsigned long partial_final_block; int adsize; struct udf_inode_info *iinfo = UDF_I(inode); struct kernel_long_ad extent;
- int err;
int err = 0;
int within_final_block;
if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_SHORT) adsize = sizeof(struct short_ad);
@@ -618,18 +638,8 @@ static int udf_extend_file(struct inode *inode, loff_t newsize) BUG();
etype = inode_bmap(inode, first_block, &epos, &eloc, &elen, &offset);
- within_final_block = (etype != -1);
- /* File has extent covering the new size (could happen when extending
* inside a block)? */
- if (etype != -1)
return 0;
- if (newsize & (sb->s_blocksize - 1))
offset++;
- /* Extended file just to the boundary of the last file block? */
- if (offset == 0)
return 0;
- /* Truncate is extending the file by 'offset' blocks */ if ((!epos.bh && epos.offset == udf_file_entry_alloc_offset(inode)) || (epos.bh && epos.offset == sizeof(struct allocExtDesc))) { /* File has no extents at all or has empty last
@@ -643,7 +653,22 @@ static int udf_extend_file(struct inode *inode, loff_t newsize) &extent.extLength, 0); extent.extLength |= etype << 30; }
- err = udf_do_extend_file(inode, &epos, &extent, offset);
- partial_final_block = newsize & (sb->s_blocksize - 1);
- /* File has extent covering the new size (could happen when extending
* inside a block)?
*/
- if (within_final_block) {
/* Extending file within the last file block */
udf_do_extend_final_block(inode, &epos, &extent,
partial_final_block);
- } else {
loff_t add = ((loff_t)offset << sb->s_blocksize_bits) |
partial_final_block;
err = udf_do_extend_file(inode, &epos, &extent, add);
- }
- if (err < 0) goto out; err = 0;
@@ -745,6 +770,7 @@ static sector_t inode_getblk(struct inode *inode, sector_t block, /* Are we beyond EOF? */ if (etype == -1) { int ret;
isBeyondEOF = true; if (count) { if (c)loff_t hole_len;
@@ -760,7 +786,8 @@ static sector_t inode_getblk(struct inode *inode, sector_t block, startnum = (offset > 0); } /* Create extents for the hole between EOF and offset */
ret = udf_do_extend_file(inode, &prev_epos, laarr, offset);
hole_len = (loff_t)offset << inode->i_blkbits;
if (ret < 0) { *err = ret; newblock = 0;ret = udf_do_extend_file(inode, &prev_epos, laarr, hole_len);
diff --git a/fs/xfs/xfs_aops.c b/fs/xfs/xfs_aops.c index 8da5e6637771..11f703d4a605 100644 --- a/fs/xfs/xfs_aops.c +++ b/fs/xfs/xfs_aops.c @@ -782,7 +782,7 @@ xfs_add_to_ioend( atomic_inc(&iop->write_count);
if (!merged) {
if (bio_full(wpc->ioend->io_bio))
bio_add_page(wpc->ioend->io_bio, page, len, poff); }if (bio_full(wpc->ioend->io_bio, len)) xfs_chain_bio(wpc->ioend, wbc, bdev, sector);
diff --git a/include/linux/bio.h b/include/linux/bio.h index f87abaa898f0..e36b8fc1b1c3 100644 --- a/include/linux/bio.h +++ b/include/linux/bio.h @@ -102,9 +102,23 @@ static inline void *bio_data(struct bio *bio) return NULL; }
-static inline bool bio_full(struct bio *bio) +/**
- bio_full - check if the bio is full
- @bio: bio to check
- @len: length of one segment to be added
- Return true if @bio is full and one segment with @len bytes can't be
- added to the bio, otherwise return false
- */
+static inline bool bio_full(struct bio *bio, unsigned len) {
- return bio->bi_vcnt >= bio->bi_max_vecs;
- if (bio->bi_vcnt >= bio->bi_max_vecs)
return true;
- if (bio->bi_iter.bi_size > UINT_MAX - len)
return true;
- return false;
}
static inline bool bio_next_segment(const struct bio *bio, diff --git a/include/linux/vmw_vmci_defs.h b/include/linux/vmw_vmci_defs.h index 77ac9c7b9483..762f793e92f6 100644 --- a/include/linux/vmw_vmci_defs.h +++ b/include/linux/vmw_vmci_defs.h @@ -62,9 +62,18 @@ enum {
/*
- A single VMCI device has an upper limit of 128MB on the amount of
- memory that can be used for queue pairs.
- memory that can be used for queue pairs. Since each queue pair
- consists of at least two pages, the memory limit also dictates the
- number of queue pairs a guest can create.
*/ #define VMCI_MAX_GUEST_QP_MEMORY (128 * 1024 * 1024) +#define VMCI_MAX_GUEST_QP_COUNT (VMCI_MAX_GUEST_QP_MEMORY / PAGE_SIZE / 2)
+/*
- There can be at most PAGE_SIZE doorbells since there is one doorbell
- per byte in the doorbell bitmap page.
- */
+#define VMCI_MAX_GUEST_DOORBELL_COUNT PAGE_SIZE
/*
- Queues with pre-mapped data pages must be small, so that we don't pin
diff --git a/include/uapi/linux/usb/audio.h b/include/uapi/linux/usb/audio.h index ddc5396800aa..76b7c3f6cd0d 100644 --- a/include/uapi/linux/usb/audio.h +++ b/include/uapi/linux/usb/audio.h @@ -450,6 +450,43 @@ static inline __u8 *uac_processing_unit_specific(struct uac_processing_unit_desc } }
+/*
- Extension Unit (XU) has almost compatible layout with Processing Unit, but
- on UAC2, it has a different bmControls size (bControlSize); it's 1 byte for
- XU while 2 bytes for PU. The last iExtension field is a one-byte index as
- well as iProcessing field of PU.
- */
+static inline __u8 uac_extension_unit_bControlSize(struct uac_processing_unit_descriptor *desc,
int protocol)
+{
- switch (protocol) {
- case UAC_VERSION_1:
return desc->baSourceID[desc->bNrInPins + 4];
- case UAC_VERSION_2:
return 1; /* in UAC2, this value is constant */
- case UAC_VERSION_3:
return 4; /* in UAC3, this value is constant */
- default:
return 1;
- }
+}
+static inline __u8 uac_extension_unit_iExtension(struct uac_processing_unit_descriptor *desc,
int protocol)
+{
- __u8 control_size = uac_extension_unit_bControlSize(desc, protocol);
- switch (protocol) {
- case UAC_VERSION_1:
- case UAC_VERSION_2:
- default:
return *(uac_processing_unit_bmControls(desc, protocol)
+ control_size);
- case UAC_VERSION_3:
return 0; /* UAC3 does not have this field */
- }
+}
/* 4.5.2 Class-Specific AS Interface Descriptor */ struct uac1_as_header_descriptor { __u8 bLength; /* in bytes: 7 */ diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 6f3a35949cdd..f24a757f8239 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -3255,6 +3255,7 @@ static void alc256_init(struct hda_codec *codec) alc_update_coefex_idx(codec, 0x57, 0x04, 0x0007, 0x4); /* Hight power */ alc_update_coefex_idx(codec, 0x53, 0x02, 0x8000, 1 << 15); /* Clear bit */ alc_update_coefex_idx(codec, 0x53, 0x02, 0x8000, 0 << 15);
- alc_update_coef_idx(codec, 0x36, 1 << 13, 1 << 5); /* Switch pcbeep path to Line in path*/
}
static void alc256_shutup(struct hda_codec *codec) @@ -7825,7 +7826,6 @@ static int patch_alc269(struct hda_codec *codec) spec->shutup = alc256_shutup; spec->init_hook = alc256_init; spec->gen.mixer_nid = 0; /* ALC256 does not have any loopback mixer path */
break; case 0x10ec0257: spec->codec_variant = ALC269_TYPE_ALC257;alc_update_coef_idx(codec, 0x36, 1 << 13, 1 << 5); /* Switch pcbeep path to Line in path*/
diff --git a/sound/usb/mixer.c b/sound/usb/mixer.c index c703f8534b07..7498b5191b68 100644 --- a/sound/usb/mixer.c +++ b/sound/usb/mixer.c @@ -2303,7 +2303,7 @@ static struct procunit_info extunits[] = { */ static int build_audio_procunit(struct mixer_build *state, int unitid, void *raw_desc, struct procunit_info *list,
char *name)
bool extension_unit)
{ struct uac_processing_unit_descriptor *desc = raw_desc; int num_ins; @@ -2320,6 +2320,8 @@ static int build_audio_procunit(struct mixer_build *state, int unitid, static struct procunit_info default_info = { 0, NULL, default_value_info };
const char *name = extension_unit ?
"Extension Unit" : "Processing Unit";
if (desc->bLength < 13) { usb_audio_err(state->chip, "invalid %s descriptor (id %d)\n", name, unitid);
@@ -2433,7 +2435,10 @@ static int build_audio_procunit(struct mixer_build *state, int unitid, } else if (info->name) { strlcpy(kctl->id.name, info->name, sizeof(kctl->id.name)); } else {
nameid = uac_processing_unit_iProcessing(desc, state->mixer->protocol);
if (extension_unit)
nameid = uac_extension_unit_iExtension(desc, state->mixer->protocol);
else
nameid = uac_processing_unit_iProcessing(desc, state->mixer->protocol); len = 0; if (nameid) len = snd_usb_copy_string_desc(state->chip,
@@ -2466,10 +2471,10 @@ static int parse_audio_processing_unit(struct mixer_build *state, int unitid, case UAC_VERSION_2: default: return build_audio_procunit(state, unitid, raw_desc,
procunits, "Processing Unit");
case UAC_VERSION_3: return build_audio_procunit(state, unitid, raw_desc,procunits, false);
uac3_procunits, "Processing Unit");
}uac3_procunits, false);
}
@@ -2480,8 +2485,7 @@ static int parse_audio_extension_unit(struct mixer_build *state, int unitid, * Note that we parse extension units with processing unit descriptors. * That's ok as the layout is the same. */
- return build_audio_procunit(state, unitid, raw_desc,
extunits, "Extension Unit");
- return build_audio_procunit(state, unitid, raw_desc, extunits, true);
}
/* diff --git a/tools/perf/Documentation/intel-pt.txt b/tools/perf/Documentation/intel-pt.txt index 115eaacc455f..60d99e5e7921 100644 --- a/tools/perf/Documentation/intel-pt.txt +++ b/tools/perf/Documentation/intel-pt.txt @@ -88,16 +88,16 @@ smaller.
To represent software control flow, "branches" samples are produced. By default a branch sample is synthesized for every single branch. To get an idea what -data is available you can use the 'perf script' tool with no parameters, which -will list all the samples. +data is available you can use the 'perf script' tool with all itrace sampling +options, which will list all the samples.
perf record -e intel_pt//u ls
- perf script
- perf script --itrace=ibxwpe
An interesting field that is not printed by default is 'flags' which can be displayed as follows:
- perf script -Fcomm,tid,pid,time,cpu,event,trace,ip,sym,dso,addr,symoff,flags
- perf script --itrace=ibxwpe -F+flags
The flags are "bcrosyiABEx" which stand for branch, call, return, conditional, system, asynchronous, interrupt, transaction abort, trace begin, trace end, and @@ -713,7 +713,7 @@ Having no option is the same as
which, in turn, is the same as
- --itrace=ibxwpe
- --itrace=cepwx
The letters are:
diff --git a/tools/perf/util/auxtrace.c b/tools/perf/util/auxtrace.c index 66e82bd0683e..cfdbf65f1e02 100644 --- a/tools/perf/util/auxtrace.c +++ b/tools/perf/util/auxtrace.c @@ -1001,7 +1001,8 @@ int itrace_parse_synth_opts(const struct option *opt, const char *str, }
if (!str) {
itrace_synth_opts__set_default(synth_opts, false);
itrace_synth_opts__set_default(synth_opts,
return 0; }synth_opts->default_no_sample);
diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c index 847ae51a524b..fb0aa661644b 100644 --- a/tools/perf/util/header.c +++ b/tools/perf/util/header.c @@ -3602,6 +3602,7 @@ int perf_event__synthesize_features(struct perf_tool *tool, return -ENOMEM;
ff.size = sz - sz_hdr;
ff.ph = &session->header;
for_each_set_bit(feat, header->adds_features, HEADER_FEAT_BITS) { if (!feat_ops[feat].synthesize) {
diff --git a/tools/perf/util/intel-pt.c b/tools/perf/util/intel-pt.c index d6f1b2a03f9b..f7dd4657535d 100644 --- a/tools/perf/util/intel-pt.c +++ b/tools/perf/util/intel-pt.c @@ -2579,7 +2579,8 @@ int intel_pt_process_auxtrace_info(union perf_event *event, } else { itrace_synth_opts__set_default(&pt->synth_opts, session->itrace_synth_opts->default_no_sample);
if (use_browser != -1) {
if (!session->itrace_synth_opts->default_no_sample &&
}!session->itrace_synth_opts->inject) { pt->synth_opts.branches = false; pt->synth_opts.callchain = true;
diff --git a/tools/perf/util/pmu.c b/tools/perf/util/pmu.c index e0429f4ef335..faa8eb231e1b 100644 --- a/tools/perf/util/pmu.c +++ b/tools/perf/util/pmu.c @@ -709,9 +709,7 @@ static void pmu_add_cpu_aliases(struct list_head *head, struct perf_pmu *pmu) { int i; struct pmu_events_map *map;
struct pmu_event *pe; const char *name = pmu->name;
const char *pname;
map = perf_pmu__find_map(pmu); if (!map)
@@ -722,28 +720,26 @@ static void pmu_add_cpu_aliases(struct list_head *head, struct perf_pmu *pmu) */ i = 0; while (1) {
const char *cpu_name = is_arm_pmu_core(name) ? name : "cpu";
struct pmu_event *pe = &map->table[i++];
const char *pname = pe->pmu ? pe->pmu : cpu_name;
pe = &map->table[i++];
if (!pe->name) { if (pe->metric_group || pe->metric_name) continue; break; }
if (!is_arm_pmu_core(name)) {
pname = pe->pmu ? pe->pmu : "cpu";
/*
* uncore alias may be from different PMU
* with common prefix
*/
if (pmu_is_uncore(name) &&
!strncmp(pname, name, strlen(pname)))
goto new_alias;
/*
* uncore alias may be from different PMU
* with common prefix
*/
if (pmu_is_uncore(name) &&
!strncmp(pname, name, strlen(pname)))
goto new_alias;
if (strcmp(pname, name))
continue;
}
if (strcmp(pname, name))
continue;
new_alias: /* need type casts to override 'const' */ diff --git a/tools/perf/util/thread-stack.c b/tools/perf/util/thread-stack.c index 4ba9e866b076..60c9d955c4d7 100644 --- a/tools/perf/util/thread-stack.c +++ b/tools/perf/util/thread-stack.c @@ -616,6 +616,23 @@ static int thread_stack__bottom(struct thread_stack *ts, true, false); }
+static int thread_stack__pop_ks(struct thread *thread, struct thread_stack *ts,
struct perf_sample *sample, u64 ref)
+{
- u64 tm = sample->time;
- int err;
- /* Return to userspace, so pop all kernel addresses */
- while (thread_stack__in_kernel(ts)) {
err = thread_stack__call_return(thread, ts, --ts->cnt,
tm, ref, true);
if (err)
return err;
- }
- return 0;
+}
static int thread_stack__no_call_return(struct thread *thread, struct thread_stack *ts, struct perf_sample *sample, @@ -896,7 +913,18 @@ int thread_stack__process(struct thread *thread, struct comm *comm, ts->rstate = X86_RETPOLINE_DETECTED;
} else if (sample->flags & PERF_IP_FLAG_RETURN) {
if (!sample->ip || !sample->addr)
if (!sample->addr) {
u32 return_from_kernel = PERF_IP_FLAG_SYSCALLRET |
PERF_IP_FLAG_INTERRUPT;
if (!(sample->flags & return_from_kernel))
return 0;
/* Pop kernel stack */
return thread_stack__pop_ks(thread, ts, sample, ref);
}
if (!sample->ip) return 0;
/* x86 retpoline 'return' doesn't match the stack */