Merge 087aa69a9f ("Merge tag 'arm64-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux") into android-mainline
Steps on the way to 6.0-rc5 Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> Change-Id: Id10d98a4f06618350adb4a594838c45519264c9e
This commit is contained in:
@@ -48,7 +48,6 @@ required:
|
||||
- compatible
|
||||
- reg
|
||||
- reg-names
|
||||
- intel,vm-map
|
||||
- clocks
|
||||
- resets
|
||||
- "#thermal-sensor-cells"
|
||||
|
||||
@@ -60,6 +60,9 @@ properties:
|
||||
power-domains:
|
||||
maxItems: 1
|
||||
|
||||
resets:
|
||||
maxItems: 1
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
|
||||
@@ -17,9 +17,6 @@ description:
|
||||
acts as directory-based coherency manager.
|
||||
All the properties in ePAPR/DeviceTree specification applies for this platform.
|
||||
|
||||
allOf:
|
||||
- $ref: /schemas/cache-controller.yaml#
|
||||
|
||||
select:
|
||||
properties:
|
||||
compatible:
|
||||
@@ -33,11 +30,16 @@ select:
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
items:
|
||||
- enum:
|
||||
- sifive,fu540-c000-ccache
|
||||
- sifive,fu740-c000-ccache
|
||||
- const: cache
|
||||
oneOf:
|
||||
- items:
|
||||
- enum:
|
||||
- sifive,fu540-c000-ccache
|
||||
- sifive,fu740-c000-ccache
|
||||
- const: cache
|
||||
- items:
|
||||
- const: microchip,mpfs-ccache
|
||||
- const: sifive,fu540-c000-ccache
|
||||
- const: cache
|
||||
|
||||
cache-block-size:
|
||||
const: 64
|
||||
@@ -72,29 +74,46 @@ properties:
|
||||
The reference to the reserved-memory for the L2 Loosely Integrated Memory region.
|
||||
The reserved memory node should be defined as per the bindings in reserved-memory.txt.
|
||||
|
||||
if:
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
const: sifive,fu540-c000-ccache
|
||||
allOf:
|
||||
- $ref: /schemas/cache-controller.yaml#
|
||||
|
||||
then:
|
||||
properties:
|
||||
interrupts:
|
||||
description: |
|
||||
Must contain entries for DirError, DataError and DataFail signals.
|
||||
maxItems: 3
|
||||
cache-sets:
|
||||
const: 1024
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
enum:
|
||||
- sifive,fu740-c000-ccache
|
||||
- microchip,mpfs-ccache
|
||||
|
||||
else:
|
||||
properties:
|
||||
interrupts:
|
||||
description: |
|
||||
Must contain entries for DirError, DataError, DataFail, DirFail signals.
|
||||
minItems: 4
|
||||
cache-sets:
|
||||
const: 2048
|
||||
then:
|
||||
properties:
|
||||
interrupts:
|
||||
description: |
|
||||
Must contain entries for DirError, DataError, DataFail, DirFail signals.
|
||||
minItems: 4
|
||||
|
||||
else:
|
||||
properties:
|
||||
interrupts:
|
||||
description: |
|
||||
Must contain entries for DirError, DataError and DataFail signals.
|
||||
maxItems: 3
|
||||
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
const: sifive,fu740-c000-ccache
|
||||
|
||||
then:
|
||||
properties:
|
||||
cache-sets:
|
||||
const: 2048
|
||||
|
||||
else:
|
||||
properties:
|
||||
cache-sets:
|
||||
const: 1024
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
|
||||
@@ -64,7 +64,7 @@ correct address for this module, you could get in big trouble (read:
|
||||
crashes, data corruption, etc.). Try this only as a last resort (try BIOS
|
||||
updates first, for example), and backup first! An even more dangerous
|
||||
option is 'force_addr=<IOPORT>'. This will not only enable the PIIX4 like
|
||||
'force' foes, but it will also set a new base I/O port address. The SMBus
|
||||
'force' does, but it will also set a new base I/O port address. The SMBus
|
||||
parts of the PIIX4 needs a range of 8 of these addresses to function
|
||||
correctly. If these addresses are already reserved by some other device,
|
||||
you will get into big trouble! DON'T USE THIS IF YOU ARE NOT VERY SURE
|
||||
@@ -86,15 +86,15 @@ If you own Force CPCI735 motherboard or other OSB4 based systems you may need
|
||||
to change the SMBus Interrupt Select register so the SMBus controller uses
|
||||
the SMI mode.
|
||||
|
||||
1) Use lspci command and locate the PCI device with the SMBus controller:
|
||||
1) Use ``lspci`` command and locate the PCI device with the SMBus controller:
|
||||
00:0f.0 ISA bridge: ServerWorks OSB4 South Bridge (rev 4f)
|
||||
The line may vary for different chipsets. Please consult the driver source
|
||||
for all possible PCI ids (and lspci -n to match them). Lets assume the
|
||||
for all possible PCI ids (and ``lspci -n`` to match them). Let's assume the
|
||||
device is located at 00:0f.0.
|
||||
2) Now you just need to change the value in 0xD2 register. Get it first with
|
||||
command: lspci -xxx -s 00:0f.0
|
||||
command: ``lspci -xxx -s 00:0f.0``
|
||||
If the value is 0x3 then you need to change it to 0x1:
|
||||
setpci -s 00:0f.0 d2.b=1
|
||||
``setpci -s 00:0f.0 d2.b=1``
|
||||
|
||||
Please note that you don't need to do that in all cases, just when the SMBus is
|
||||
not working properly.
|
||||
@@ -109,6 +109,3 @@ which can easily get corrupted due to a state machine bug. These are mostly
|
||||
Thinkpad laptops, but desktop systems may also be affected. We have no list
|
||||
of all affected systems, so the only safe solution was to prevent access to
|
||||
the SMBus on all IBM systems (detected using DMI data.)
|
||||
|
||||
For additional information, read:
|
||||
http://www.lm-sensors.org/browser/lm-sensors/trunk/README
|
||||
|
||||
@@ -5,6 +5,8 @@ I2C muxes and complex topologies
|
||||
There are a couple of reasons for building more complex I2C topologies
|
||||
than a straight-forward I2C bus with one adapter and one or more devices.
|
||||
|
||||
Some example use cases are:
|
||||
|
||||
1. A mux may be needed on the bus to prevent address collisions.
|
||||
|
||||
2. The bus may be accessible from some external bus master, and arbitration
|
||||
@@ -14,10 +16,10 @@ than a straight-forward I2C bus with one adapter and one or more devices.
|
||||
from the I2C bus, at least most of the time, and sits behind a gate
|
||||
that has to be operated before the device can be accessed.
|
||||
|
||||
Etc
|
||||
===
|
||||
Several types of hardware components such as I2C muxes, I2C gates and I2C
|
||||
arbitrators allow to handle such needs.
|
||||
|
||||
These constructs are represented as I2C adapter trees by Linux, where
|
||||
These components are represented as I2C adapter trees by Linux, where
|
||||
each adapter has a parent adapter (except the root adapter) and zero or
|
||||
more child adapters. The root adapter is the actual adapter that issues
|
||||
I2C transfers, and all adapters with a parent are part of an "i2c-mux"
|
||||
@@ -35,46 +37,7 @@ Locking
|
||||
=======
|
||||
|
||||
There are two variants of locking available to I2C muxes, they can be
|
||||
mux-locked or parent-locked muxes. As is evident from below, it can be
|
||||
useful to know if a mux is mux-locked or if it is parent-locked. The
|
||||
following list was correct at the time of writing:
|
||||
|
||||
In drivers/i2c/muxes/:
|
||||
|
||||
====================== =============================================
|
||||
i2c-arb-gpio-challenge Parent-locked
|
||||
i2c-mux-gpio Normally parent-locked, mux-locked iff
|
||||
all involved gpio pins are controlled by the
|
||||
same I2C root adapter that they mux.
|
||||
i2c-mux-gpmux Normally parent-locked, mux-locked iff
|
||||
specified in device-tree.
|
||||
i2c-mux-ltc4306 Mux-locked
|
||||
i2c-mux-mlxcpld Parent-locked
|
||||
i2c-mux-pca9541 Parent-locked
|
||||
i2c-mux-pca954x Parent-locked
|
||||
i2c-mux-pinctrl Normally parent-locked, mux-locked iff
|
||||
all involved pinctrl devices are controlled
|
||||
by the same I2C root adapter that they mux.
|
||||
i2c-mux-reg Parent-locked
|
||||
====================== =============================================
|
||||
|
||||
In drivers/iio/:
|
||||
|
||||
====================== =============================================
|
||||
gyro/mpu3050 Mux-locked
|
||||
imu/inv_mpu6050/ Mux-locked
|
||||
====================== =============================================
|
||||
|
||||
In drivers/media/:
|
||||
|
||||
======================= =============================================
|
||||
dvb-frontends/lgdt3306a Mux-locked
|
||||
dvb-frontends/m88ds3103 Parent-locked
|
||||
dvb-frontends/rtl2830 Parent-locked
|
||||
dvb-frontends/rtl2832 Mux-locked
|
||||
dvb-frontends/si2168 Mux-locked
|
||||
usb/cx231xx/ Parent-locked
|
||||
======================= =============================================
|
||||
mux-locked or parent-locked muxes.
|
||||
|
||||
|
||||
Mux-locked muxes
|
||||
@@ -89,40 +52,8 @@ full transaction, unrelated I2C transfers may interleave the different
|
||||
stages of the transaction. This has the benefit that the mux driver
|
||||
may be easier and cleaner to implement, but it has some caveats.
|
||||
|
||||
==== =====================================================================
|
||||
ML1. If you build a topology with a mux-locked mux being the parent
|
||||
of a parent-locked mux, this might break the expectation from the
|
||||
parent-locked mux that the root adapter is locked during the
|
||||
transaction.
|
||||
|
||||
ML2. It is not safe to build arbitrary topologies with two (or more)
|
||||
mux-locked muxes that are not siblings, when there are address
|
||||
collisions between the devices on the child adapters of these
|
||||
non-sibling muxes.
|
||||
|
||||
I.e. the select-transfer-deselect transaction targeting e.g. device
|
||||
address 0x42 behind mux-one may be interleaved with a similar
|
||||
operation targeting device address 0x42 behind mux-two. The
|
||||
intension with such a topology would in this hypothetical example
|
||||
be that mux-one and mux-two should not be selected simultaneously,
|
||||
but mux-locked muxes do not guarantee that in all topologies.
|
||||
|
||||
ML3. A mux-locked mux cannot be used by a driver for auto-closing
|
||||
gates/muxes, i.e. something that closes automatically after a given
|
||||
number (one, in most cases) of I2C transfers. Unrelated I2C transfers
|
||||
may creep in and close prematurely.
|
||||
|
||||
ML4. If any non-I2C operation in the mux driver changes the I2C mux state,
|
||||
the driver has to lock the root adapter during that operation.
|
||||
Otherwise garbage may appear on the bus as seen from devices
|
||||
behind the mux, when an unrelated I2C transfer is in flight during
|
||||
the non-I2C mux-changing operation.
|
||||
==== =====================================================================
|
||||
|
||||
|
||||
Mux-locked Example
|
||||
------------------
|
||||
|
||||
~~~~~~~~~~~~~~~~~~
|
||||
|
||||
::
|
||||
|
||||
@@ -153,6 +84,43 @@ This means that accesses to D2 are lockout out for the full duration
|
||||
of the entire operation. But accesses to D3 are possibly interleaved
|
||||
at any point.
|
||||
|
||||
Mux-locked caveats
|
||||
~~~~~~~~~~~~~~~~~~
|
||||
|
||||
When using a mux-locked mux, be aware of the following restrictions:
|
||||
|
||||
[ML1]
|
||||
If you build a topology with a mux-locked mux being the parent
|
||||
of a parent-locked mux, this might break the expectation from the
|
||||
parent-locked mux that the root adapter is locked during the
|
||||
transaction.
|
||||
|
||||
[ML2]
|
||||
It is not safe to build arbitrary topologies with two (or more)
|
||||
mux-locked muxes that are not siblings, when there are address
|
||||
collisions between the devices on the child adapters of these
|
||||
non-sibling muxes.
|
||||
|
||||
I.e. the select-transfer-deselect transaction targeting e.g. device
|
||||
address 0x42 behind mux-one may be interleaved with a similar
|
||||
operation targeting device address 0x42 behind mux-two. The
|
||||
intent with such a topology would in this hypothetical example
|
||||
be that mux-one and mux-two should not be selected simultaneously,
|
||||
but mux-locked muxes do not guarantee that in all topologies.
|
||||
|
||||
[ML3]
|
||||
A mux-locked mux cannot be used by a driver for auto-closing
|
||||
gates/muxes, i.e. something that closes automatically after a given
|
||||
number (one, in most cases) of I2C transfers. Unrelated I2C transfers
|
||||
may creep in and close prematurely.
|
||||
|
||||
[ML4]
|
||||
If any non-I2C operation in the mux driver changes the I2C mux state,
|
||||
the driver has to lock the root adapter during that operation.
|
||||
Otherwise garbage may appear on the bus as seen from devices
|
||||
behind the mux, when an unrelated I2C transfer is in flight during
|
||||
the non-I2C mux-changing operation.
|
||||
|
||||
|
||||
Parent-locked muxes
|
||||
-------------------
|
||||
@@ -161,28 +129,10 @@ Parent-locked muxes lock the parent adapter during the full select-
|
||||
transfer-deselect transaction. The implication is that the mux driver
|
||||
has to ensure that any and all I2C transfers through that parent
|
||||
adapter during the transaction are unlocked I2C transfers (using e.g.
|
||||
__i2c_transfer), or a deadlock will follow. There are a couple of
|
||||
caveats.
|
||||
|
||||
==== ====================================================================
|
||||
PL1. If you build a topology with a parent-locked mux being the child
|
||||
of another mux, this might break a possible assumption from the
|
||||
child mux that the root adapter is unused between its select op
|
||||
and the actual transfer (e.g. if the child mux is auto-closing
|
||||
and the parent mux issues I2C transfers as part of its select).
|
||||
This is especially the case if the parent mux is mux-locked, but
|
||||
it may also happen if the parent mux is parent-locked.
|
||||
|
||||
PL2. If select/deselect calls out to other subsystems such as gpio,
|
||||
pinctrl, regmap or iio, it is essential that any I2C transfers
|
||||
caused by these subsystems are unlocked. This can be convoluted to
|
||||
accomplish, maybe even impossible if an acceptably clean solution
|
||||
is sought.
|
||||
==== ====================================================================
|
||||
|
||||
__i2c_transfer), or a deadlock will follow.
|
||||
|
||||
Parent-locked Example
|
||||
---------------------
|
||||
~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
::
|
||||
|
||||
@@ -212,10 +162,30 @@ When there is an access to D1, this happens:
|
||||
9. M1 unlocks its parent adapter.
|
||||
10. M1 unlocks muxes on its parent.
|
||||
|
||||
|
||||
This means that accesses to both D2 and D3 are locked out for the full
|
||||
duration of the entire operation.
|
||||
|
||||
Parent-locked Caveats
|
||||
~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
When using a parent-locked mux, be aware of the following restrictions:
|
||||
|
||||
[PL1]
|
||||
If you build a topology with a parent-locked mux being the child
|
||||
of another mux, this might break a possible assumption from the
|
||||
child mux that the root adapter is unused between its select op
|
||||
and the actual transfer (e.g. if the child mux is auto-closing
|
||||
and the parent mux issues I2C transfers as part of its select).
|
||||
This is especially the case if the parent mux is mux-locked, but
|
||||
it may also happen if the parent mux is parent-locked.
|
||||
|
||||
[PL2]
|
||||
If select/deselect calls out to other subsystems such as gpio,
|
||||
pinctrl, regmap or iio, it is essential that any I2C transfers
|
||||
caused by these subsystems are unlocked. This can be convoluted to
|
||||
accomplish, maybe even impossible if an acceptably clean solution
|
||||
is sought.
|
||||
|
||||
|
||||
Complex Examples
|
||||
================
|
||||
@@ -261,8 +231,10 @@ This is a good topology::
|
||||
When device D1 is accessed, accesses to D2 are locked out for the
|
||||
full duration of the operation (muxes on the top child adapter of M1
|
||||
are locked). But accesses to D3 and D4 are possibly interleaved at
|
||||
any point. Accesses to D3 locks out D1 and D2, but accesses to D4
|
||||
are still possibly interleaved.
|
||||
any point.
|
||||
|
||||
Accesses to D3 locks out D1 and D2, but accesses to D4 are still possibly
|
||||
interleaved.
|
||||
|
||||
|
||||
Mux-locked mux as parent of parent-locked mux
|
||||
@@ -394,3 +366,47 @@ This is a good topology::
|
||||
When D1 or D2 are accessed, accesses to D3 and D4 are locked out while
|
||||
accesses to D5 may interleave. When D3 or D4 are accessed, accesses to
|
||||
all other devices are locked out.
|
||||
|
||||
|
||||
Mux type of existing device drivers
|
||||
===================================
|
||||
|
||||
Whether a device is mux-locked or parent-locked depends on its
|
||||
implementation. The following list was correct at the time of writing:
|
||||
|
||||
In drivers/i2c/muxes/:
|
||||
|
||||
====================== =============================================
|
||||
i2c-arb-gpio-challenge Parent-locked
|
||||
i2c-mux-gpio Normally parent-locked, mux-locked iff
|
||||
all involved gpio pins are controlled by the
|
||||
same I2C root adapter that they mux.
|
||||
i2c-mux-gpmux Normally parent-locked, mux-locked iff
|
||||
specified in device-tree.
|
||||
i2c-mux-ltc4306 Mux-locked
|
||||
i2c-mux-mlxcpld Parent-locked
|
||||
i2c-mux-pca9541 Parent-locked
|
||||
i2c-mux-pca954x Parent-locked
|
||||
i2c-mux-pinctrl Normally parent-locked, mux-locked iff
|
||||
all involved pinctrl devices are controlled
|
||||
by the same I2C root adapter that they mux.
|
||||
i2c-mux-reg Parent-locked
|
||||
====================== =============================================
|
||||
|
||||
In drivers/iio/:
|
||||
|
||||
====================== =============================================
|
||||
gyro/mpu3050 Mux-locked
|
||||
imu/inv_mpu6050/ Mux-locked
|
||||
====================== =============================================
|
||||
|
||||
In drivers/media/:
|
||||
|
||||
======================= =============================================
|
||||
dvb-frontends/lgdt3306a Mux-locked
|
||||
dvb-frontends/m88ds3103 Parent-locked
|
||||
dvb-frontends/rtl2830 Parent-locked
|
||||
dvb-frontends/rtl2832 Mux-locked
|
||||
dvb-frontends/si2168 Mux-locked
|
||||
usb/cx231xx/ Parent-locked
|
||||
======================= =============================================
|
||||
|
||||
+13
-1
@@ -9208,8 +9208,8 @@ F: Documentation/ABI/testing/debugfs-hisi-zip
|
||||
F: drivers/crypto/hisilicon/zip/
|
||||
|
||||
HISILICON ROCE DRIVER
|
||||
M: Haoyue Xu <xuhaoyue1@hisilicon.com>
|
||||
M: Wenpeng Liang <liangwenpeng@huawei.com>
|
||||
M: Weihang Li <liweihang@huawei.com>
|
||||
L: linux-rdma@vger.kernel.org
|
||||
S: Maintained
|
||||
F: Documentation/devicetree/bindings/infiniband/hisilicon-hns-roce.txt
|
||||
@@ -17752,6 +17752,17 @@ L: linux-rdma@vger.kernel.org
|
||||
S: Maintained
|
||||
F: drivers/infiniband/ulp/rtrs/
|
||||
|
||||
RUNTIME VERIFICATION (RV)
|
||||
M: Daniel Bristot de Oliveira <bristot@kernel.org>
|
||||
M: Steven Rostedt <rostedt@goodmis.org>
|
||||
L: linux-trace-devel@vger.kernel.org
|
||||
S: Maintained
|
||||
F: Documentation/trace/rv/
|
||||
F: include/linux/rv.h
|
||||
F: include/rv/
|
||||
F: kernel/trace/rv/
|
||||
F: tools/verification/
|
||||
|
||||
RXRPC SOCKETS (AF_RXRPC)
|
||||
M: David Howells <dhowells@redhat.com>
|
||||
M: Marc Dionne <marc.dionne@auristor.com>
|
||||
@@ -20618,6 +20629,7 @@ F: include/*/ftrace.h
|
||||
F: include/linux/trace*.h
|
||||
F: include/trace/
|
||||
F: kernel/trace/
|
||||
F: scripts/tracing/
|
||||
F: tools/testing/selftests/ftrace/
|
||||
|
||||
TRACING MMIO ACCESSES (MMIOTRACE)
|
||||
|
||||
@@ -923,6 +923,9 @@ config HAVE_SOFTIRQ_ON_OWN_STACK
|
||||
Architecture provides a function to run __do_softirq() on a
|
||||
separate stack.
|
||||
|
||||
config SOFTIRQ_ON_OWN_STACK
|
||||
def_bool HAVE_SOFTIRQ_ON_OWN_STACK && !PREEMPT_RT
|
||||
|
||||
config ALTERNATE_USER_ADDRESS_SPACE
|
||||
bool
|
||||
help
|
||||
|
||||
@@ -70,7 +70,7 @@ static void __init init_irq_stacks(void)
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef CONFIG_PREEMPT_RT
|
||||
#ifdef CONFIG_SOFTIRQ_ON_OWN_STACK
|
||||
static void ____do_softirq(void *arg)
|
||||
{
|
||||
__do_softirq();
|
||||
|
||||
@@ -1887,6 +1887,8 @@ config ARM64_BTI_KERNEL
|
||||
depends on CC_HAS_BRANCH_PROT_PAC_RET_BTI
|
||||
# https://gcc.gnu.org/bugzilla/show_bug.cgi?id=94697
|
||||
depends on !CC_IS_GCC || GCC_VERSION >= 100100
|
||||
# https://gcc.gnu.org/bugzilla/show_bug.cgi?id=106671
|
||||
depends on !CC_IS_GCC
|
||||
# https://github.com/llvm/llvm-project/commit/a88c722e687e6780dcd6a58718350dc76fcc4cc9
|
||||
depends on !CC_IS_CLANG || CLANG_VERSION >= 120000
|
||||
depends on (!FUNCTION_GRAPH_TRACER || DYNAMIC_FTRACE_WITH_REGS)
|
||||
|
||||
@@ -1084,7 +1084,6 @@ static int za_set(struct task_struct *target,
|
||||
if (!target->thread.sve_state) {
|
||||
sve_alloc(target, false);
|
||||
if (!target->thread.sve_state) {
|
||||
clear_thread_flag(TIF_SME);
|
||||
ret = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
@@ -1094,7 +1093,6 @@ static int za_set(struct task_struct *target,
|
||||
sme_alloc(target);
|
||||
if (!target->thread.za_state) {
|
||||
ret = -ENOMEM;
|
||||
clear_tsk_thread_flag(target, TIF_SME);
|
||||
goto out;
|
||||
}
|
||||
|
||||
|
||||
@@ -101,6 +101,9 @@ SYM_FUNC_END(__cpu_suspend_enter)
|
||||
SYM_CODE_START(cpu_resume)
|
||||
bl init_kernel_el
|
||||
bl finalise_el2
|
||||
#if VA_BITS > 48
|
||||
ldr_l x0, vabits_actual
|
||||
#endif
|
||||
bl __cpu_setup
|
||||
/* enable the MMU early - so we can access sleep_save_stash by va */
|
||||
adrp x1, swapper_pg_dir
|
||||
|
||||
@@ -2669,7 +2669,6 @@ config ARCH_FLATMEM_ENABLE
|
||||
|
||||
config ARCH_SPARSEMEM_ENABLE
|
||||
bool
|
||||
select SPARSEMEM_STATIC if !SGI_IP27
|
||||
|
||||
config NUMA
|
||||
bool "NUMA Support"
|
||||
|
||||
@@ -57,14 +57,11 @@ EXPORT_SYMBOL_GPL(__cvmx_cmd_queue_state_ptr);
|
||||
static cvmx_cmd_queue_result_t __cvmx_cmd_queue_init_state_ptr(void)
|
||||
{
|
||||
char *alloc_name = "cvmx_cmd_queues";
|
||||
#if defined(CONFIG_CAVIUM_RESERVE32) && CONFIG_CAVIUM_RESERVE32
|
||||
extern uint64_t octeon_reserve32_memory;
|
||||
#endif
|
||||
|
||||
if (likely(__cvmx_cmd_queue_state_ptr))
|
||||
return CVMX_CMD_QUEUE_SUCCESS;
|
||||
|
||||
#if defined(CONFIG_CAVIUM_RESERVE32) && CONFIG_CAVIUM_RESERVE32
|
||||
if (octeon_reserve32_memory)
|
||||
__cvmx_cmd_queue_state_ptr =
|
||||
cvmx_bootmem_alloc_named_range(sizeof(*__cvmx_cmd_queue_state_ptr),
|
||||
@@ -73,7 +70,6 @@ static cvmx_cmd_queue_result_t __cvmx_cmd_queue_init_state_ptr(void)
|
||||
(CONFIG_CAVIUM_RESERVE32 <<
|
||||
20) - 1, 128, alloc_name);
|
||||
else
|
||||
#endif
|
||||
__cvmx_cmd_queue_state_ptr =
|
||||
cvmx_bootmem_alloc_named(sizeof(*__cvmx_cmd_queue_state_ptr),
|
||||
128,
|
||||
|
||||
@@ -127,6 +127,16 @@ static void octeon_irq_free_cd(struct irq_domain *d, unsigned int irq)
|
||||
static int octeon_irq_force_ciu_mapping(struct irq_domain *domain,
|
||||
int irq, int line, int bit)
|
||||
{
|
||||
struct device_node *of_node;
|
||||
int ret;
|
||||
|
||||
of_node = irq_domain_get_of_node(domain);
|
||||
if (!of_node)
|
||||
return -EINVAL;
|
||||
ret = irq_alloc_desc_at(irq, of_node_to_nid(of_node));
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
return irq_domain_associate(domain, irq, line << 6 | bit);
|
||||
}
|
||||
|
||||
|
||||
@@ -284,10 +284,8 @@ void octeon_crash_smp_send_stop(void)
|
||||
|
||||
#endif /* CONFIG_KEXEC */
|
||||
|
||||
#ifdef CONFIG_CAVIUM_RESERVE32
|
||||
uint64_t octeon_reserve32_memory;
|
||||
EXPORT_SYMBOL(octeon_reserve32_memory);
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_KEXEC
|
||||
/* crashkernel cmdline parameter is parsed _after_ memory setup
|
||||
@@ -666,9 +664,6 @@ void __init prom_init(void)
|
||||
int i;
|
||||
u64 t;
|
||||
int argc;
|
||||
#ifdef CONFIG_CAVIUM_RESERVE32
|
||||
int64_t addr = -1;
|
||||
#endif
|
||||
/*
|
||||
* The bootloader passes a pointer to the boot descriptor in
|
||||
* $a3, this is available as fw_arg3.
|
||||
@@ -783,7 +778,7 @@ void __init prom_init(void)
|
||||
cvmx_write_csr(CVMX_LED_UDD_DATX(1), 0);
|
||||
cvmx_write_csr(CVMX_LED_EN, 1);
|
||||
}
|
||||
#ifdef CONFIG_CAVIUM_RESERVE32
|
||||
|
||||
/*
|
||||
* We need to temporarily allocate all memory in the reserve32
|
||||
* region. This makes sure the kernel doesn't allocate this
|
||||
@@ -794,14 +789,16 @@ void __init prom_init(void)
|
||||
* Allocate memory for RESERVED32 aligned on 2MB boundary. This
|
||||
* is in case we later use hugetlb entries with it.
|
||||
*/
|
||||
addr = cvmx_bootmem_phy_named_block_alloc(CONFIG_CAVIUM_RESERVE32 << 20,
|
||||
0, 0, 2 << 20,
|
||||
"CAVIUM_RESERVE32", 0);
|
||||
if (addr < 0)
|
||||
pr_err("Failed to allocate CAVIUM_RESERVE32 memory area\n");
|
||||
else
|
||||
octeon_reserve32_memory = addr;
|
||||
#endif
|
||||
if (CONFIG_CAVIUM_RESERVE32) {
|
||||
int64_t addr =
|
||||
cvmx_bootmem_phy_named_block_alloc(CONFIG_CAVIUM_RESERVE32 << 20,
|
||||
0, 0, 2 << 20,
|
||||
"CAVIUM_RESERVE32", 0);
|
||||
if (addr < 0)
|
||||
pr_err("Failed to allocate CAVIUM_RESERVE32 memory area\n");
|
||||
else
|
||||
octeon_reserve32_memory = addr;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_CAVIUM_OCTEON_LOCK_L2
|
||||
if (cvmx_read_csr(CVMX_L2D_FUS3) & (3ull << 34)) {
|
||||
@@ -1079,7 +1076,6 @@ void __init plat_mem_setup(void)
|
||||
cvmx_bootmem_unlock();
|
||||
#endif /* CONFIG_CRASH_DUMP */
|
||||
|
||||
#ifdef CONFIG_CAVIUM_RESERVE32
|
||||
/*
|
||||
* Now that we've allocated the kernel memory it is safe to
|
||||
* free the reserved region. We free it here so that builtin
|
||||
@@ -1087,7 +1083,6 @@ void __init plat_mem_setup(void)
|
||||
*/
|
||||
if (octeon_reserve32_memory)
|
||||
cvmx_bootmem_free_named("CAVIUM_RESERVE32");
|
||||
#endif /* CONFIG_CAVIUM_RESERVE32 */
|
||||
|
||||
if (total == 0)
|
||||
panic("Unable to allocate memory from "
|
||||
|
||||
@@ -15,7 +15,6 @@ static struct platform_device *ls1c_platform_devices[] __initdata = {
|
||||
static int __init ls1c_platform_init(void)
|
||||
{
|
||||
ls1x_serial_set_uartclk(&ls1x_uart_pdev);
|
||||
ls1x_rtc_set_extclk(&ls1x_rtc_pdev);
|
||||
|
||||
return platform_add_devices(ls1c_platform_devices,
|
||||
ARRAY_SIZE(ls1c_platform_devices));
|
||||
|
||||
@@ -480,7 +480,7 @@ static void execute_on_irq_stack(void *func, unsigned long param1)
|
||||
*irq_stack_in_use = 1;
|
||||
}
|
||||
|
||||
#ifndef CONFIG_PREEMPT_RT
|
||||
#ifdef CONFIG_SOFTIRQ_ON_OWN_STACK
|
||||
void do_softirq_own_stack(void)
|
||||
{
|
||||
execute_on_irq_stack(__do_softirq, 0);
|
||||
|
||||
@@ -199,7 +199,7 @@ static inline void check_stack_overflow(unsigned long sp)
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef CONFIG_PREEMPT_RT
|
||||
#ifdef CONFIG_SOFTIRQ_ON_OWN_STACK
|
||||
static __always_inline void call_do_softirq(const void *sp)
|
||||
{
|
||||
/* Temporarily switch r1 to sp, call __do_softirq() then restore r1. */
|
||||
@@ -335,7 +335,7 @@ void *mcheckirq_ctx[NR_CPUS] __read_mostly;
|
||||
void *softirq_ctx[NR_CPUS] __read_mostly;
|
||||
void *hardirq_ctx[NR_CPUS] __read_mostly;
|
||||
|
||||
#ifndef CONFIG_PREEMPT_RT
|
||||
#ifdef CONFIG_SOFTIRQ_ON_OWN_STACK
|
||||
void do_softirq_own_stack(void)
|
||||
{
|
||||
call_do_softirq(softirq_ctx[smp_processor_id()]);
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
#include <linux/string.h>
|
||||
#include <linux/types.h>
|
||||
#include <asm/hvcall.h>
|
||||
#include <asm/machdep.h>
|
||||
|
||||
#include "plpks.h"
|
||||
|
||||
@@ -457,4 +458,4 @@ static __init int pseries_plpks_init(void)
|
||||
|
||||
return rc;
|
||||
}
|
||||
arch_initcall(pseries_plpks_init);
|
||||
machine_arch_initcall(pseries, pseries_plpks_init);
|
||||
|
||||
@@ -185,7 +185,7 @@
|
||||
ranges;
|
||||
|
||||
cctrllr: cache-controller@2010000 {
|
||||
compatible = "sifive,fu540-c000-ccache", "cache";
|
||||
compatible = "microchip,mpfs-ccache", "sifive,fu540-c000-ccache", "cache";
|
||||
reg = <0x0 0x2010000 0x0 0x1000>;
|
||||
cache-block-size = <64>;
|
||||
cache-level = <2>;
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
#include <asm/lowcore.h>
|
||||
#include <asm/stacktrace.h>
|
||||
|
||||
#ifndef CONFIG_PREEMPT_RT
|
||||
#ifdef CONFIG_SOFTIRQ_ON_OWN_STACK
|
||||
static inline void do_softirq_own_stack(void)
|
||||
{
|
||||
call_on_stack(0, S390_lowcore.async_stack, void, __do_softirq);
|
||||
|
||||
@@ -64,7 +64,7 @@ static inline unsigned long nmi_get_mcesa_size(void)
|
||||
* structure. The structure is required for machine check happening
|
||||
* early in the boot process.
|
||||
*/
|
||||
static struct mcesa boot_mcesa __initdata __aligned(MCESA_MAX_SIZE);
|
||||
static struct mcesa boot_mcesa __aligned(MCESA_MAX_SIZE);
|
||||
|
||||
void __init nmi_alloc_mcesa_early(u64 *mcesad)
|
||||
{
|
||||
|
||||
@@ -479,6 +479,7 @@ static void __init setup_lowcore_dat_off(void)
|
||||
put_abs_lowcore(restart_data, lc->restart_data);
|
||||
put_abs_lowcore(restart_source, lc->restart_source);
|
||||
put_abs_lowcore(restart_psw, lc->restart_psw);
|
||||
put_abs_lowcore(mcesad, lc->mcesad);
|
||||
|
||||
mcck_stack = (unsigned long)memblock_alloc(THREAD_SIZE, THREAD_SIZE);
|
||||
if (!mcck_stack)
|
||||
@@ -507,8 +508,8 @@ static void __init setup_lowcore_dat_on(void)
|
||||
S390_lowcore.svc_new_psw.mask |= PSW_MASK_DAT;
|
||||
S390_lowcore.program_new_psw.mask |= PSW_MASK_DAT;
|
||||
S390_lowcore.io_new_psw.mask |= PSW_MASK_DAT;
|
||||
__ctl_store(S390_lowcore.cregs_save_area, 0, 15);
|
||||
__ctl_set_bit(0, 28);
|
||||
__ctl_store(S390_lowcore.cregs_save_area, 0, 15);
|
||||
put_abs_lowcore(restart_flags, RESTART_FLAG_CTLREGS);
|
||||
put_abs_lowcore(program_new_psw, lc->program_new_psw);
|
||||
for (cr = 0; cr < ARRAY_SIZE(lc->cregs_save_area); cr++)
|
||||
|
||||
@@ -149,7 +149,7 @@ void irq_ctx_exit(int cpu)
|
||||
hardirq_ctx[cpu] = NULL;
|
||||
}
|
||||
|
||||
#ifndef CONFIG_PREEMPT_RT
|
||||
#ifdef CONFIG_SOFTIRQ_ON_OWN_STACK
|
||||
void do_softirq_own_stack(void)
|
||||
{
|
||||
struct thread_info *curctx;
|
||||
|
||||
@@ -855,7 +855,7 @@ void __irq_entry handler_irq(int pil, struct pt_regs *regs)
|
||||
set_irq_regs(old_regs);
|
||||
}
|
||||
|
||||
#ifndef CONFIG_PREEMPT_RT
|
||||
#ifdef CONFIG_SOFTIRQ_ON_OWN_STACK
|
||||
void do_softirq_own_stack(void)
|
||||
{
|
||||
void *orig_sp, *sp = softirq_stack[smp_processor_id()];
|
||||
|
||||
@@ -203,7 +203,7 @@
|
||||
IRQ_CONSTRAINTS, regs, vector); \
|
||||
}
|
||||
|
||||
#ifndef CONFIG_PREEMPT_RT
|
||||
#ifdef CONFIG_SOFTIRQ_ON_OWN_STACK
|
||||
/*
|
||||
* Macro to invoke __do_softirq on the irq stack. This is only called from
|
||||
* task context when bottom halves are about to be reenabled and soft
|
||||
|
||||
@@ -132,7 +132,7 @@ int irq_init_percpu_irqstack(unsigned int cpu)
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifndef CONFIG_PREEMPT_RT
|
||||
#ifdef CONFIG_SOFTIRQ_ON_OWN_STACK
|
||||
void do_softirq_own_stack(void)
|
||||
{
|
||||
struct irq_stack *irqstk;
|
||||
|
||||
@@ -283,7 +283,9 @@ static const char *const rqf_name[] = {
|
||||
RQF_NAME(SPECIAL_PAYLOAD),
|
||||
RQF_NAME(ZONE_WRITE_LOCKED),
|
||||
RQF_NAME(MQ_POLL_SLEPT),
|
||||
RQF_NAME(TIMED_OUT),
|
||||
RQF_NAME(ELV),
|
||||
RQF_NAME(RESV),
|
||||
};
|
||||
#undef RQF_NAME
|
||||
|
||||
|
||||
@@ -596,6 +596,9 @@ static int blk_add_partitions(struct gendisk *disk)
|
||||
if (disk->flags & GENHD_FL_NO_PART)
|
||||
return 0;
|
||||
|
||||
if (test_bit(GD_SUPPRESS_PART_SCAN, &disk->state))
|
||||
return 0;
|
||||
|
||||
state = check_partition(disk);
|
||||
if (!state)
|
||||
return 0;
|
||||
|
||||
@@ -724,7 +724,7 @@ const struct cpumask *cpu_clustergroup_mask(int cpu)
|
||||
*/
|
||||
if (cpumask_subset(cpu_coregroup_mask(cpu),
|
||||
&cpu_topology[cpu].cluster_sibling))
|
||||
return get_cpu_mask(cpu);
|
||||
return topology_sibling_cpumask(cpu);
|
||||
|
||||
return &cpu_topology[cpu].cluster_sibling;
|
||||
}
|
||||
|
||||
@@ -63,6 +63,12 @@ int driver_set_override(struct device *dev, const char **override,
|
||||
if (len >= (PAGE_SIZE - 1))
|
||||
return -EINVAL;
|
||||
|
||||
/*
|
||||
* Compute the real length of the string in case userspace sends us a
|
||||
* bunch of \0 characters like python likes to do.
|
||||
*/
|
||||
len = strlen(s);
|
||||
|
||||
if (!len) {
|
||||
/* Empty string passed - clear override */
|
||||
device_lock(dev);
|
||||
|
||||
@@ -1728,7 +1728,7 @@ int amdgpu_amdkfd_gpuvm_alloc_memory_of_gpu(
|
||||
add_kgd_mem_to_kfd_bo_list(*mem, avm->process_info, user_addr);
|
||||
|
||||
if (user_addr) {
|
||||
pr_debug("creating userptr BO for user_addr = %llu\n", user_addr);
|
||||
pr_debug("creating userptr BO for user_addr = %llx\n", user_addr);
|
||||
ret = init_user_pages(*mem, user_addr, criu_resume);
|
||||
if (ret)
|
||||
goto allocate_init_user_pages_failed;
|
||||
|
||||
@@ -486,11 +486,14 @@ static int psp_sw_fini(void *handle)
|
||||
release_firmware(psp->ta_fw);
|
||||
psp->ta_fw = NULL;
|
||||
}
|
||||
if (adev->psp.cap_fw) {
|
||||
if (psp->cap_fw) {
|
||||
release_firmware(psp->cap_fw);
|
||||
psp->cap_fw = NULL;
|
||||
}
|
||||
|
||||
if (psp->toc_fw) {
|
||||
release_firmware(psp->toc_fw);
|
||||
psp->toc_fw = NULL;
|
||||
}
|
||||
if (adev->ip_versions[MP0_HWIP][0] == IP_VERSION(11, 0, 0) ||
|
||||
adev->ip_versions[MP0_HWIP][0] == IP_VERSION(11, 0, 7))
|
||||
psp_sysfs_fini(adev);
|
||||
|
||||
@@ -390,6 +390,7 @@ union amdgpu_firmware_header {
|
||||
struct rlc_firmware_header_v2_1 rlc_v2_1;
|
||||
struct rlc_firmware_header_v2_2 rlc_v2_2;
|
||||
struct rlc_firmware_header_v2_3 rlc_v2_3;
|
||||
struct rlc_firmware_header_v2_4 rlc_v2_4;
|
||||
struct sdma_firmware_header_v1_0 sdma;
|
||||
struct sdma_firmware_header_v1_1 sdma_v1_1;
|
||||
struct sdma_firmware_header_v2_0 sdma_v2_0;
|
||||
|
||||
@@ -68,12 +68,6 @@ static void nbio_v7_7_sdma_doorbell_range(struct amdgpu_device *adev, int instan
|
||||
doorbell_range = REG_SET_FIELD(doorbell_range,
|
||||
GDC0_BIF_CSDMA_DOORBELL_RANGE,
|
||||
SIZE, doorbell_size);
|
||||
doorbell_range = REG_SET_FIELD(doorbell_range,
|
||||
GDC0_BIF_SDMA0_DOORBELL_RANGE,
|
||||
OFFSET, doorbell_index);
|
||||
doorbell_range = REG_SET_FIELD(doorbell_range,
|
||||
GDC0_BIF_SDMA0_DOORBELL_RANGE,
|
||||
SIZE, doorbell_size);
|
||||
} else {
|
||||
doorbell_range = REG_SET_FIELD(doorbell_range,
|
||||
GDC0_BIF_SDMA0_DOORBELL_RANGE,
|
||||
|
||||
@@ -3288,6 +3288,7 @@ void crtc_debugfs_init(struct drm_crtc *crtc)
|
||||
&crc_win_y_end_fops);
|
||||
debugfs_create_file_unsafe("crc_win_update", 0644, dir, crtc,
|
||||
&crc_win_update_fops);
|
||||
dput(dir);
|
||||
#endif
|
||||
debugfs_create_file("amdgpu_current_bpc", 0644, crtc->debugfs_entry,
|
||||
crtc, &amdgpu_current_bpc_fops);
|
||||
|
||||
@@ -120,6 +120,7 @@ static struct cmn2asic_msg_mapping smu_v13_0_7_message_map[SMU_MSG_MAX_COUNT] =
|
||||
MSG_MAP(DisallowGfxOff, PPSMC_MSG_DisallowGfxOff, 0),
|
||||
MSG_MAP(Mode1Reset, PPSMC_MSG_Mode1Reset, 0),
|
||||
MSG_MAP(PrepareMp1ForUnload, PPSMC_MSG_PrepareMp1ForUnload, 0),
|
||||
MSG_MAP(SetMGpuFanBoostLimitRpm, PPSMC_MSG_SetMGpuFanBoostLimitRpm, 0),
|
||||
};
|
||||
|
||||
static struct cmn2asic_mapping smu_v13_0_7_clk_map[SMU_CLK_COUNT] = {
|
||||
|
||||
@@ -377,8 +377,8 @@ static int vrr_range_show(struct seq_file *m, void *data)
|
||||
if (connector->status != connector_status_connected)
|
||||
return -ENODEV;
|
||||
|
||||
seq_printf(m, "Min: %u\n", (u8)connector->display_info.monitor_range.min_vfreq);
|
||||
seq_printf(m, "Max: %u\n", (u8)connector->display_info.monitor_range.max_vfreq);
|
||||
seq_printf(m, "Min: %u\n", connector->display_info.monitor_range.min_vfreq);
|
||||
seq_printf(m, "Max: %u\n", connector->display_info.monitor_range.max_vfreq);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -5971,12 +5971,14 @@ static void drm_parse_cea_ext(struct drm_connector *connector,
|
||||
}
|
||||
|
||||
static
|
||||
void get_monitor_range(const struct detailed_timing *timing,
|
||||
void *info_monitor_range)
|
||||
void get_monitor_range(const struct detailed_timing *timing, void *c)
|
||||
{
|
||||
struct drm_monitor_range_info *monitor_range = info_monitor_range;
|
||||
struct detailed_mode_closure *closure = c;
|
||||
struct drm_display_info *info = &closure->connector->display_info;
|
||||
struct drm_monitor_range_info *monitor_range = &info->monitor_range;
|
||||
const struct detailed_non_pixel *data = &timing->data.other_data;
|
||||
const struct detailed_data_monitor_range *range = &data->data.range;
|
||||
const struct edid *edid = closure->drm_edid->edid;
|
||||
|
||||
if (!is_display_descriptor(timing, EDID_DETAIL_MONITOR_RANGE))
|
||||
return;
|
||||
@@ -5992,18 +5994,28 @@ void get_monitor_range(const struct detailed_timing *timing,
|
||||
|
||||
monitor_range->min_vfreq = range->min_vfreq;
|
||||
monitor_range->max_vfreq = range->max_vfreq;
|
||||
|
||||
if (edid->revision >= 4) {
|
||||
if (data->pad2 & DRM_EDID_RANGE_OFFSET_MIN_VFREQ)
|
||||
monitor_range->min_vfreq += 255;
|
||||
if (data->pad2 & DRM_EDID_RANGE_OFFSET_MAX_VFREQ)
|
||||
monitor_range->max_vfreq += 255;
|
||||
}
|
||||
}
|
||||
|
||||
static void drm_get_monitor_range(struct drm_connector *connector,
|
||||
const struct drm_edid *drm_edid)
|
||||
{
|
||||
struct drm_display_info *info = &connector->display_info;
|
||||
const struct drm_display_info *info = &connector->display_info;
|
||||
struct detailed_mode_closure closure = {
|
||||
.connector = connector,
|
||||
.drm_edid = drm_edid,
|
||||
};
|
||||
|
||||
if (!version_greater(drm_edid, 1, 1))
|
||||
return;
|
||||
|
||||
drm_for_each_detailed_block(drm_edid, get_monitor_range,
|
||||
&info->monitor_range);
|
||||
drm_for_each_detailed_block(drm_edid, get_monitor_range, &closure);
|
||||
|
||||
DRM_DEBUG_KMS("Supported Monitor Refresh rate range is %d Hz - %d Hz\n",
|
||||
info->monitor_range.min_vfreq,
|
||||
|
||||
@@ -479,6 +479,13 @@ init_bdb_block(struct drm_i915_private *i915,
|
||||
|
||||
block_size = get_blocksize(block);
|
||||
|
||||
/*
|
||||
* Version number and new block size are considered
|
||||
* part of the header for MIPI sequenece block v3+.
|
||||
*/
|
||||
if (section_id == BDB_MIPI_SEQUENCE && *(const u8 *)block >= 3)
|
||||
block_size += 5;
|
||||
|
||||
entry = kzalloc(struct_size(entry, data, max(min_size, block_size) + 3),
|
||||
GFP_KERNEL);
|
||||
if (!entry) {
|
||||
|
||||
@@ -671,6 +671,28 @@ intel_dp_prepare_link_train(struct intel_dp *intel_dp,
|
||||
intel_dp_compute_rate(intel_dp, crtc_state->port_clock,
|
||||
&link_bw, &rate_select);
|
||||
|
||||
/*
|
||||
* WaEdpLinkRateDataReload
|
||||
*
|
||||
* Parade PS8461E MUX (used on varius TGL+ laptops) needs
|
||||
* to snoop the link rates reported by the sink when we
|
||||
* use LINK_RATE_SET in order to operate in jitter cleaning
|
||||
* mode (as opposed to redriver mode). Unfortunately it
|
||||
* loses track of the snooped link rates when powered down,
|
||||
* so we need to make it re-snoop often. Without this high
|
||||
* link rates are not stable.
|
||||
*/
|
||||
if (!link_bw) {
|
||||
struct intel_connector *connector = intel_dp->attached_connector;
|
||||
__le16 sink_rates[DP_MAX_SUPPORTED_RATES];
|
||||
|
||||
drm_dbg_kms(&i915->drm, "[CONNECTOR:%d:%s] Reloading eDP link rates\n",
|
||||
connector->base.base.id, connector->base.name);
|
||||
|
||||
drm_dp_dpcd_read(&intel_dp->aux, DP_SUPPORTED_LINK_RATES,
|
||||
sink_rates, sizeof(sink_rates));
|
||||
}
|
||||
|
||||
if (link_bw)
|
||||
drm_dbg_kms(&i915->drm,
|
||||
"[ENCODER:%d:%s] Using LINK_BW_SET value %02x\n",
|
||||
|
||||
@@ -723,6 +723,9 @@ bool i915_gem_object_needs_ccs_pages(struct drm_i915_gem_object *obj)
|
||||
bool lmem_placement = false;
|
||||
int i;
|
||||
|
||||
if (!HAS_FLAT_CCS(to_i915(obj->base.dev)))
|
||||
return false;
|
||||
|
||||
for (i = 0; i < obj->mm.n_placements; i++) {
|
||||
/* Compression is not allowed for the objects with smem placement */
|
||||
if (obj->mm.placements[i]->type == INTEL_MEMORY_SYSTEM)
|
||||
|
||||
@@ -297,7 +297,7 @@ static struct ttm_tt *i915_ttm_tt_create(struct ttm_buffer_object *bo,
|
||||
i915_tt->is_shmem = true;
|
||||
}
|
||||
|
||||
if (HAS_FLAT_CCS(i915) && i915_gem_object_needs_ccs_pages(obj))
|
||||
if (i915_gem_object_needs_ccs_pages(obj))
|
||||
ccs_pages = DIV_ROUND_UP(DIV_ROUND_UP(bo->base.size,
|
||||
NUM_BYTES_PER_CCS_BYTE),
|
||||
PAGE_SIZE);
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
#include "intel_llc.h"
|
||||
#include "intel_mchbar_regs.h"
|
||||
#include "intel_pcode.h"
|
||||
#include "intel_rps.h"
|
||||
|
||||
struct ia_constants {
|
||||
unsigned int min_gpu_freq;
|
||||
@@ -55,9 +56,6 @@ static bool get_ia_constants(struct intel_llc *llc,
|
||||
if (!HAS_LLC(i915) || IS_DGFX(i915))
|
||||
return false;
|
||||
|
||||
if (rps->max_freq <= rps->min_freq)
|
||||
return false;
|
||||
|
||||
consts->max_ia_freq = cpu_max_MHz();
|
||||
|
||||
consts->min_ring_freq =
|
||||
@@ -65,13 +63,8 @@ static bool get_ia_constants(struct intel_llc *llc,
|
||||
/* convert DDR frequency from units of 266.6MHz to bandwidth */
|
||||
consts->min_ring_freq = mult_frac(consts->min_ring_freq, 8, 3);
|
||||
|
||||
consts->min_gpu_freq = rps->min_freq;
|
||||
consts->max_gpu_freq = rps->max_freq;
|
||||
if (GRAPHICS_VER(i915) >= 9) {
|
||||
/* Convert GT frequency to 50 HZ units */
|
||||
consts->min_gpu_freq /= GEN9_FREQ_SCALER;
|
||||
consts->max_gpu_freq /= GEN9_FREQ_SCALER;
|
||||
}
|
||||
consts->min_gpu_freq = intel_rps_get_min_raw_freq(rps);
|
||||
consts->max_gpu_freq = intel_rps_get_max_raw_freq(rps);
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -130,6 +123,12 @@ static void gen6_update_ring_freq(struct intel_llc *llc)
|
||||
if (!get_ia_constants(llc, &consts))
|
||||
return;
|
||||
|
||||
/*
|
||||
* Although this is unlikely on any platform during initialization,
|
||||
* let's ensure we don't get accidentally into infinite loop
|
||||
*/
|
||||
if (consts.max_gpu_freq <= consts.min_gpu_freq)
|
||||
return;
|
||||
/*
|
||||
* For each potential GPU frequency, load a ring frequency we'd like
|
||||
* to use for memory access. We do this by specifying the IA frequency
|
||||
|
||||
@@ -2126,6 +2126,31 @@ u32 intel_rps_get_max_frequency(struct intel_rps *rps)
|
||||
return intel_gpu_freq(rps, rps->max_freq_softlimit);
|
||||
}
|
||||
|
||||
/**
|
||||
* intel_rps_get_max_raw_freq - returns the max frequency in some raw format.
|
||||
* @rps: the intel_rps structure
|
||||
*
|
||||
* Returns the max frequency in a raw format. In newer platforms raw is in
|
||||
* units of 50 MHz.
|
||||
*/
|
||||
u32 intel_rps_get_max_raw_freq(struct intel_rps *rps)
|
||||
{
|
||||
struct intel_guc_slpc *slpc = rps_to_slpc(rps);
|
||||
u32 freq;
|
||||
|
||||
if (rps_uses_slpc(rps)) {
|
||||
return DIV_ROUND_CLOSEST(slpc->rp0_freq,
|
||||
GT_FREQUENCY_MULTIPLIER);
|
||||
} else {
|
||||
freq = rps->max_freq;
|
||||
if (GRAPHICS_VER(rps_to_i915(rps)) >= 9) {
|
||||
/* Convert GT frequency to 50 MHz units */
|
||||
freq /= GEN9_FREQ_SCALER;
|
||||
}
|
||||
return freq;
|
||||
}
|
||||
}
|
||||
|
||||
u32 intel_rps_get_rp0_frequency(struct intel_rps *rps)
|
||||
{
|
||||
struct intel_guc_slpc *slpc = rps_to_slpc(rps);
|
||||
@@ -2214,6 +2239,31 @@ u32 intel_rps_get_min_frequency(struct intel_rps *rps)
|
||||
return intel_gpu_freq(rps, rps->min_freq_softlimit);
|
||||
}
|
||||
|
||||
/**
|
||||
* intel_rps_get_min_raw_freq - returns the min frequency in some raw format.
|
||||
* @rps: the intel_rps structure
|
||||
*
|
||||
* Returns the min frequency in a raw format. In newer platforms raw is in
|
||||
* units of 50 MHz.
|
||||
*/
|
||||
u32 intel_rps_get_min_raw_freq(struct intel_rps *rps)
|
||||
{
|
||||
struct intel_guc_slpc *slpc = rps_to_slpc(rps);
|
||||
u32 freq;
|
||||
|
||||
if (rps_uses_slpc(rps)) {
|
||||
return DIV_ROUND_CLOSEST(slpc->min_freq,
|
||||
GT_FREQUENCY_MULTIPLIER);
|
||||
} else {
|
||||
freq = rps->min_freq;
|
||||
if (GRAPHICS_VER(rps_to_i915(rps)) >= 9) {
|
||||
/* Convert GT frequency to 50 MHz units */
|
||||
freq /= GEN9_FREQ_SCALER;
|
||||
}
|
||||
return freq;
|
||||
}
|
||||
}
|
||||
|
||||
static int set_min_freq(struct intel_rps *rps, u32 val)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
@@ -37,8 +37,10 @@ u32 intel_rps_get_cagf(struct intel_rps *rps, u32 rpstat1);
|
||||
u32 intel_rps_read_actual_frequency(struct intel_rps *rps);
|
||||
u32 intel_rps_get_requested_frequency(struct intel_rps *rps);
|
||||
u32 intel_rps_get_min_frequency(struct intel_rps *rps);
|
||||
u32 intel_rps_get_min_raw_freq(struct intel_rps *rps);
|
||||
int intel_rps_set_min_frequency(struct intel_rps *rps, u32 val);
|
||||
u32 intel_rps_get_max_frequency(struct intel_rps *rps);
|
||||
u32 intel_rps_get_max_raw_freq(struct intel_rps *rps);
|
||||
int intel_rps_set_max_frequency(struct intel_rps *rps, u32 val);
|
||||
u32 intel_rps_get_rp0_frequency(struct intel_rps *rps);
|
||||
u32 intel_rps_get_rp1_frequency(struct intel_rps *rps);
|
||||
|
||||
@@ -131,6 +131,17 @@ int panfrost_devfreq_init(struct panfrost_device *pfdev)
|
||||
return PTR_ERR(opp);
|
||||
|
||||
panfrost_devfreq_profile.initial_freq = cur_freq;
|
||||
|
||||
/*
|
||||
* Set the recommend OPP this will enable and configure the regulator
|
||||
* if any and will avoid a switch off by regulator_late_cleanup()
|
||||
*/
|
||||
ret = dev_pm_opp_set_opp(dev, opp);
|
||||
if (ret) {
|
||||
DRM_DEV_ERROR(dev, "Couldn't set recommended OPP\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
dev_pm_opp_put(opp);
|
||||
|
||||
/*
|
||||
|
||||
@@ -236,16 +236,19 @@ static int ttm_buffer_object_transfer(struct ttm_buffer_object *bo,
|
||||
if (bo->type != ttm_bo_type_sg)
|
||||
fbo->base.base.resv = &fbo->base.base._resv;
|
||||
|
||||
if (fbo->base.resource) {
|
||||
ttm_resource_set_bo(fbo->base.resource, &fbo->base);
|
||||
bo->resource = NULL;
|
||||
}
|
||||
|
||||
dma_resv_init(&fbo->base.base._resv);
|
||||
fbo->base.base.dev = NULL;
|
||||
ret = dma_resv_trylock(&fbo->base.base._resv);
|
||||
WARN_ON(!ret);
|
||||
|
||||
if (fbo->base.resource) {
|
||||
ttm_resource_set_bo(fbo->base.resource, &fbo->base);
|
||||
bo->resource = NULL;
|
||||
ttm_bo_set_bulk_move(&fbo->base, NULL);
|
||||
} else {
|
||||
fbo->base.bulk_move = NULL;
|
||||
}
|
||||
|
||||
ret = dma_resv_reserve_fences(&fbo->base.base._resv, 1);
|
||||
if (ret) {
|
||||
kfree(fbo);
|
||||
|
||||
+222
-186
@@ -266,9 +266,7 @@ static const struct ec_sensor_info sensors_family_intel_600[] = {
|
||||
#define SENSOR_SET_WATER_BLOCK \
|
||||
(SENSOR_TEMP_WATER_BLOCK_IN | SENSOR_TEMP_WATER_BLOCK_OUT)
|
||||
|
||||
|
||||
struct ec_board_info {
|
||||
const char *board_names[MAX_IDENTICAL_BOARD_VARIATIONS];
|
||||
unsigned long sensors;
|
||||
/*
|
||||
* Defines which mutex to use for guarding access to the state and the
|
||||
@@ -281,152 +279,194 @@ struct ec_board_info {
|
||||
enum board_family family;
|
||||
};
|
||||
|
||||
static const struct ec_board_info board_info[] = {
|
||||
{
|
||||
.board_names = {"PRIME X470-PRO"},
|
||||
.sensors = SENSOR_SET_TEMP_CHIPSET_CPU_MB |
|
||||
SENSOR_TEMP_T_SENSOR | SENSOR_TEMP_VRM |
|
||||
SENSOR_FAN_CPU_OPT |
|
||||
SENSOR_CURR_CPU | SENSOR_IN_CPU_CORE,
|
||||
.mutex_path = ACPI_GLOBAL_LOCK_PSEUDO_PATH,
|
||||
.family = family_amd_400_series,
|
||||
},
|
||||
{
|
||||
.board_names = {"PRIME X570-PRO"},
|
||||
.sensors = SENSOR_SET_TEMP_CHIPSET_CPU_MB | SENSOR_TEMP_VRM |
|
||||
SENSOR_TEMP_T_SENSOR | SENSOR_FAN_CHIPSET,
|
||||
.mutex_path = ASUS_HW_ACCESS_MUTEX_ASMX,
|
||||
.family = family_amd_500_series,
|
||||
},
|
||||
{
|
||||
.board_names = {"ProArt X570-CREATOR WIFI"},
|
||||
.sensors = SENSOR_SET_TEMP_CHIPSET_CPU_MB | SENSOR_TEMP_VRM |
|
||||
SENSOR_TEMP_T_SENSOR | SENSOR_FAN_CPU_OPT |
|
||||
SENSOR_CURR_CPU | SENSOR_IN_CPU_CORE,
|
||||
},
|
||||
{
|
||||
.board_names = {"Pro WS X570-ACE"},
|
||||
.sensors = SENSOR_SET_TEMP_CHIPSET_CPU_MB | SENSOR_TEMP_VRM |
|
||||
SENSOR_TEMP_T_SENSOR | SENSOR_FAN_CHIPSET |
|
||||
SENSOR_CURR_CPU | SENSOR_IN_CPU_CORE,
|
||||
.mutex_path = ASUS_HW_ACCESS_MUTEX_ASMX,
|
||||
.family = family_amd_500_series,
|
||||
},
|
||||
{
|
||||
.board_names = {"ROG CROSSHAIR VIII DARK HERO"},
|
||||
.sensors = SENSOR_SET_TEMP_CHIPSET_CPU_MB |
|
||||
SENSOR_TEMP_T_SENSOR |
|
||||
SENSOR_TEMP_VRM | SENSOR_SET_TEMP_WATER |
|
||||
SENSOR_FAN_CPU_OPT | SENSOR_FAN_WATER_FLOW |
|
||||
SENSOR_CURR_CPU | SENSOR_IN_CPU_CORE,
|
||||
.mutex_path = ASUS_HW_ACCESS_MUTEX_ASMX,
|
||||
.family = family_amd_500_series,
|
||||
},
|
||||
{
|
||||
.board_names = {
|
||||
"ROG CROSSHAIR VIII FORMULA",
|
||||
"ROG CROSSHAIR VIII HERO",
|
||||
"ROG CROSSHAIR VIII HERO (WI-FI)",
|
||||
},
|
||||
.sensors = SENSOR_SET_TEMP_CHIPSET_CPU_MB |
|
||||
SENSOR_TEMP_T_SENSOR |
|
||||
SENSOR_TEMP_VRM | SENSOR_SET_TEMP_WATER |
|
||||
SENSOR_FAN_CPU_OPT | SENSOR_FAN_CHIPSET |
|
||||
SENSOR_FAN_WATER_FLOW | SENSOR_CURR_CPU |
|
||||
SENSOR_IN_CPU_CORE,
|
||||
.mutex_path = ASUS_HW_ACCESS_MUTEX_ASMX,
|
||||
.family = family_amd_500_series,
|
||||
},
|
||||
{
|
||||
.board_names = {
|
||||
"ROG MAXIMUS XI HERO",
|
||||
"ROG MAXIMUS XI HERO (WI-FI)",
|
||||
},
|
||||
.sensors = SENSOR_SET_TEMP_CHIPSET_CPU_MB |
|
||||
SENSOR_TEMP_T_SENSOR |
|
||||
SENSOR_TEMP_VRM | SENSOR_SET_TEMP_WATER |
|
||||
SENSOR_FAN_CPU_OPT | SENSOR_FAN_WATER_FLOW,
|
||||
.mutex_path = ASUS_HW_ACCESS_MUTEX_ASMX,
|
||||
.family = family_intel_300_series,
|
||||
},
|
||||
{
|
||||
.board_names = {"ROG CROSSHAIR VIII IMPACT"},
|
||||
.sensors = SENSOR_SET_TEMP_CHIPSET_CPU_MB |
|
||||
SENSOR_TEMP_T_SENSOR | SENSOR_TEMP_VRM |
|
||||
SENSOR_FAN_CHIPSET | SENSOR_CURR_CPU |
|
||||
SENSOR_IN_CPU_CORE,
|
||||
.mutex_path = ASUS_HW_ACCESS_MUTEX_ASMX,
|
||||
.family = family_amd_500_series,
|
||||
},
|
||||
{
|
||||
.board_names = {"ROG STRIX B550-E GAMING"},
|
||||
.sensors = SENSOR_SET_TEMP_CHIPSET_CPU_MB |
|
||||
SENSOR_TEMP_T_SENSOR | SENSOR_TEMP_VRM |
|
||||
SENSOR_FAN_CPU_OPT,
|
||||
.mutex_path = ASUS_HW_ACCESS_MUTEX_ASMX,
|
||||
.family = family_amd_500_series,
|
||||
},
|
||||
{
|
||||
.board_names = {"ROG STRIX B550-I GAMING"},
|
||||
.sensors = SENSOR_SET_TEMP_CHIPSET_CPU_MB |
|
||||
SENSOR_TEMP_T_SENSOR | SENSOR_TEMP_VRM |
|
||||
SENSOR_FAN_VRM_HS | SENSOR_CURR_CPU |
|
||||
SENSOR_IN_CPU_CORE,
|
||||
.mutex_path = ASUS_HW_ACCESS_MUTEX_ASMX,
|
||||
.family = family_amd_500_series,
|
||||
},
|
||||
{
|
||||
.board_names = {"ROG STRIX X570-E GAMING"},
|
||||
.sensors = SENSOR_SET_TEMP_CHIPSET_CPU_MB |
|
||||
SENSOR_TEMP_T_SENSOR | SENSOR_TEMP_VRM |
|
||||
SENSOR_FAN_CHIPSET | SENSOR_CURR_CPU |
|
||||
SENSOR_IN_CPU_CORE,
|
||||
.mutex_path = ASUS_HW_ACCESS_MUTEX_ASMX,
|
||||
.family = family_amd_500_series,
|
||||
},
|
||||
{
|
||||
.board_names = {"ROG STRIX X570-E GAMING WIFI II"},
|
||||
.sensors = SENSOR_SET_TEMP_CHIPSET_CPU_MB |
|
||||
SENSOR_TEMP_T_SENSOR | SENSOR_CURR_CPU |
|
||||
SENSOR_IN_CPU_CORE,
|
||||
.mutex_path = ASUS_HW_ACCESS_MUTEX_ASMX,
|
||||
.family = family_amd_500_series,
|
||||
},
|
||||
{
|
||||
.board_names = {"ROG STRIX X570-F GAMING"},
|
||||
.sensors = SENSOR_SET_TEMP_CHIPSET_CPU_MB |
|
||||
SENSOR_TEMP_T_SENSOR | SENSOR_FAN_CHIPSET,
|
||||
.mutex_path = ASUS_HW_ACCESS_MUTEX_ASMX,
|
||||
.family = family_amd_500_series,
|
||||
},
|
||||
{
|
||||
.board_names = {"ROG STRIX X570-I GAMING"},
|
||||
.sensors = SENSOR_TEMP_CHIPSET | SENSOR_TEMP_VRM |
|
||||
SENSOR_TEMP_T_SENSOR |
|
||||
SENSOR_FAN_VRM_HS | SENSOR_FAN_CHIPSET |
|
||||
SENSOR_CURR_CPU | SENSOR_IN_CPU_CORE,
|
||||
.mutex_path = ASUS_HW_ACCESS_MUTEX_ASMX,
|
||||
.family = family_amd_500_series,
|
||||
},
|
||||
{
|
||||
.board_names = {"ROG STRIX Z690-A GAMING WIFI D4"},
|
||||
.sensors = SENSOR_TEMP_T_SENSOR | SENSOR_TEMP_VRM,
|
||||
.mutex_path = ASUS_HW_ACCESS_MUTEX_RMTW_ASMX,
|
||||
.family = family_intel_600_series,
|
||||
},
|
||||
{
|
||||
.board_names = {"ROG ZENITH II EXTREME"},
|
||||
.sensors = SENSOR_SET_TEMP_CHIPSET_CPU_MB | SENSOR_TEMP_T_SENSOR |
|
||||
SENSOR_TEMP_VRM | SENSOR_SET_TEMP_WATER |
|
||||
SENSOR_FAN_CPU_OPT | SENSOR_FAN_CHIPSET | SENSOR_FAN_VRM_HS |
|
||||
SENSOR_FAN_WATER_FLOW | SENSOR_CURR_CPU | SENSOR_IN_CPU_CORE |
|
||||
SENSOR_SET_WATER_BLOCK |
|
||||
SENSOR_TEMP_T_SENSOR_2 | SENSOR_TEMP_SENSOR_EXTRA_1 |
|
||||
SENSOR_TEMP_SENSOR_EXTRA_2 | SENSOR_TEMP_SENSOR_EXTRA_3,
|
||||
.mutex_path = ASUS_HW_ACCESS_MUTEX_SB_PCI0_SBRG_SIO1_MUT0,
|
||||
.family = family_amd_500_series,
|
||||
},
|
||||
{}
|
||||
static const struct ec_board_info board_info_prime_x470_pro = {
|
||||
.sensors = SENSOR_SET_TEMP_CHIPSET_CPU_MB |
|
||||
SENSOR_TEMP_T_SENSOR | SENSOR_TEMP_VRM |
|
||||
SENSOR_FAN_CPU_OPT |
|
||||
SENSOR_CURR_CPU | SENSOR_IN_CPU_CORE,
|
||||
.mutex_path = ACPI_GLOBAL_LOCK_PSEUDO_PATH,
|
||||
.family = family_amd_400_series,
|
||||
};
|
||||
|
||||
static const struct ec_board_info board_info_prime_x570_pro = {
|
||||
.sensors = SENSOR_SET_TEMP_CHIPSET_CPU_MB | SENSOR_TEMP_VRM |
|
||||
SENSOR_TEMP_T_SENSOR | SENSOR_FAN_CHIPSET,
|
||||
.mutex_path = ASUS_HW_ACCESS_MUTEX_ASMX,
|
||||
.family = family_amd_500_series,
|
||||
};
|
||||
|
||||
static const struct ec_board_info board_info_pro_art_x570_creator_wifi = {
|
||||
.sensors = SENSOR_SET_TEMP_CHIPSET_CPU_MB | SENSOR_TEMP_VRM |
|
||||
SENSOR_TEMP_T_SENSOR | SENSOR_FAN_CPU_OPT |
|
||||
SENSOR_CURR_CPU | SENSOR_IN_CPU_CORE,
|
||||
.family = family_amd_500_series,
|
||||
};
|
||||
|
||||
static const struct ec_board_info board_info_pro_ws_x570_ace = {
|
||||
.sensors = SENSOR_SET_TEMP_CHIPSET_CPU_MB | SENSOR_TEMP_VRM |
|
||||
SENSOR_TEMP_T_SENSOR | SENSOR_FAN_CHIPSET |
|
||||
SENSOR_CURR_CPU | SENSOR_IN_CPU_CORE,
|
||||
.mutex_path = ASUS_HW_ACCESS_MUTEX_ASMX,
|
||||
.family = family_amd_500_series,
|
||||
};
|
||||
|
||||
static const struct ec_board_info board_info_crosshair_viii_dark_hero = {
|
||||
.sensors = SENSOR_SET_TEMP_CHIPSET_CPU_MB |
|
||||
SENSOR_TEMP_T_SENSOR |
|
||||
SENSOR_TEMP_VRM | SENSOR_SET_TEMP_WATER |
|
||||
SENSOR_FAN_CPU_OPT | SENSOR_FAN_WATER_FLOW |
|
||||
SENSOR_CURR_CPU | SENSOR_IN_CPU_CORE,
|
||||
.mutex_path = ASUS_HW_ACCESS_MUTEX_ASMX,
|
||||
.family = family_amd_500_series,
|
||||
};
|
||||
|
||||
static const struct ec_board_info board_info_crosshair_viii_hero = {
|
||||
.sensors = SENSOR_SET_TEMP_CHIPSET_CPU_MB |
|
||||
SENSOR_TEMP_T_SENSOR |
|
||||
SENSOR_TEMP_VRM | SENSOR_SET_TEMP_WATER |
|
||||
SENSOR_FAN_CPU_OPT | SENSOR_FAN_CHIPSET |
|
||||
SENSOR_FAN_WATER_FLOW | SENSOR_CURR_CPU |
|
||||
SENSOR_IN_CPU_CORE,
|
||||
.mutex_path = ASUS_HW_ACCESS_MUTEX_ASMX,
|
||||
.family = family_amd_500_series,
|
||||
};
|
||||
|
||||
static const struct ec_board_info board_info_maximus_xi_hero = {
|
||||
.sensors = SENSOR_SET_TEMP_CHIPSET_CPU_MB |
|
||||
SENSOR_TEMP_T_SENSOR |
|
||||
SENSOR_TEMP_VRM | SENSOR_SET_TEMP_WATER |
|
||||
SENSOR_FAN_CPU_OPT | SENSOR_FAN_WATER_FLOW,
|
||||
.mutex_path = ASUS_HW_ACCESS_MUTEX_ASMX,
|
||||
.family = family_intel_300_series,
|
||||
};
|
||||
|
||||
static const struct ec_board_info board_info_crosshair_viii_impact = {
|
||||
.sensors = SENSOR_SET_TEMP_CHIPSET_CPU_MB |
|
||||
SENSOR_TEMP_T_SENSOR | SENSOR_TEMP_VRM |
|
||||
SENSOR_FAN_CHIPSET | SENSOR_CURR_CPU |
|
||||
SENSOR_IN_CPU_CORE,
|
||||
.mutex_path = ASUS_HW_ACCESS_MUTEX_ASMX,
|
||||
.family = family_amd_500_series,
|
||||
};
|
||||
|
||||
static const struct ec_board_info board_info_strix_b550_e_gaming = {
|
||||
.sensors = SENSOR_SET_TEMP_CHIPSET_CPU_MB |
|
||||
SENSOR_TEMP_T_SENSOR | SENSOR_TEMP_VRM |
|
||||
SENSOR_FAN_CPU_OPT,
|
||||
.mutex_path = ASUS_HW_ACCESS_MUTEX_ASMX,
|
||||
.family = family_amd_500_series,
|
||||
};
|
||||
|
||||
static const struct ec_board_info board_info_strix_b550_i_gaming = {
|
||||
.sensors = SENSOR_SET_TEMP_CHIPSET_CPU_MB |
|
||||
SENSOR_TEMP_T_SENSOR | SENSOR_TEMP_VRM |
|
||||
SENSOR_FAN_VRM_HS | SENSOR_CURR_CPU |
|
||||
SENSOR_IN_CPU_CORE,
|
||||
.mutex_path = ASUS_HW_ACCESS_MUTEX_ASMX,
|
||||
.family = family_amd_500_series,
|
||||
};
|
||||
|
||||
static const struct ec_board_info board_info_strix_x570_e_gaming = {
|
||||
.sensors = SENSOR_SET_TEMP_CHIPSET_CPU_MB |
|
||||
SENSOR_TEMP_T_SENSOR | SENSOR_TEMP_VRM |
|
||||
SENSOR_FAN_CHIPSET | SENSOR_CURR_CPU |
|
||||
SENSOR_IN_CPU_CORE,
|
||||
.mutex_path = ASUS_HW_ACCESS_MUTEX_ASMX,
|
||||
.family = family_amd_500_series,
|
||||
};
|
||||
|
||||
static const struct ec_board_info board_info_strix_x570_e_gaming_wifi_ii = {
|
||||
.sensors = SENSOR_SET_TEMP_CHIPSET_CPU_MB |
|
||||
SENSOR_TEMP_T_SENSOR | SENSOR_CURR_CPU |
|
||||
SENSOR_IN_CPU_CORE,
|
||||
.mutex_path = ASUS_HW_ACCESS_MUTEX_ASMX,
|
||||
.family = family_amd_500_series,
|
||||
};
|
||||
|
||||
static const struct ec_board_info board_info_strix_x570_f_gaming = {
|
||||
.sensors = SENSOR_SET_TEMP_CHIPSET_CPU_MB |
|
||||
SENSOR_TEMP_T_SENSOR | SENSOR_FAN_CHIPSET,
|
||||
.mutex_path = ASUS_HW_ACCESS_MUTEX_ASMX,
|
||||
.family = family_amd_500_series,
|
||||
};
|
||||
|
||||
static const struct ec_board_info board_info_strix_x570_i_gaming = {
|
||||
.sensors = SENSOR_TEMP_CHIPSET | SENSOR_TEMP_VRM |
|
||||
SENSOR_TEMP_T_SENSOR |
|
||||
SENSOR_FAN_VRM_HS | SENSOR_FAN_CHIPSET |
|
||||
SENSOR_CURR_CPU | SENSOR_IN_CPU_CORE,
|
||||
.mutex_path = ASUS_HW_ACCESS_MUTEX_ASMX,
|
||||
.family = family_amd_500_series,
|
||||
};
|
||||
|
||||
static const struct ec_board_info board_info_strix_z690_a_gaming_wifi_d4 = {
|
||||
.sensors = SENSOR_TEMP_T_SENSOR | SENSOR_TEMP_VRM,
|
||||
.mutex_path = ASUS_HW_ACCESS_MUTEX_RMTW_ASMX,
|
||||
.family = family_intel_600_series,
|
||||
};
|
||||
|
||||
static const struct ec_board_info board_info_zenith_ii_extreme = {
|
||||
.sensors = SENSOR_SET_TEMP_CHIPSET_CPU_MB | SENSOR_TEMP_T_SENSOR |
|
||||
SENSOR_TEMP_VRM | SENSOR_SET_TEMP_WATER |
|
||||
SENSOR_FAN_CPU_OPT | SENSOR_FAN_CHIPSET | SENSOR_FAN_VRM_HS |
|
||||
SENSOR_FAN_WATER_FLOW | SENSOR_CURR_CPU | SENSOR_IN_CPU_CORE |
|
||||
SENSOR_SET_WATER_BLOCK |
|
||||
SENSOR_TEMP_T_SENSOR_2 | SENSOR_TEMP_SENSOR_EXTRA_1 |
|
||||
SENSOR_TEMP_SENSOR_EXTRA_2 | SENSOR_TEMP_SENSOR_EXTRA_3,
|
||||
.mutex_path = ASUS_HW_ACCESS_MUTEX_SB_PCI0_SBRG_SIO1_MUT0,
|
||||
.family = family_amd_500_series,
|
||||
};
|
||||
|
||||
#define DMI_EXACT_MATCH_ASUS_BOARD_NAME(name, board_info) \
|
||||
{ \
|
||||
.matches = { \
|
||||
DMI_EXACT_MATCH(DMI_BOARD_VENDOR, \
|
||||
"ASUSTeK COMPUTER INC."), \
|
||||
DMI_EXACT_MATCH(DMI_BOARD_NAME, name), \
|
||||
}, \
|
||||
.driver_data = (void *)board_info, \
|
||||
}
|
||||
|
||||
static const struct dmi_system_id dmi_table[] = {
|
||||
DMI_EXACT_MATCH_ASUS_BOARD_NAME("PRIME X470-PRO",
|
||||
&board_info_prime_x470_pro),
|
||||
DMI_EXACT_MATCH_ASUS_BOARD_NAME("PRIME X570-PRO",
|
||||
&board_info_prime_x570_pro),
|
||||
DMI_EXACT_MATCH_ASUS_BOARD_NAME("ProArt X570-CREATOR WIFI",
|
||||
&board_info_pro_art_x570_creator_wifi),
|
||||
DMI_EXACT_MATCH_ASUS_BOARD_NAME("Pro WS X570-ACE",
|
||||
&board_info_pro_ws_x570_ace),
|
||||
DMI_EXACT_MATCH_ASUS_BOARD_NAME("ROG CROSSHAIR VIII DARK HERO",
|
||||
&board_info_crosshair_viii_dark_hero),
|
||||
DMI_EXACT_MATCH_ASUS_BOARD_NAME("ROG CROSSHAIR VIII FORMULA",
|
||||
&board_info_crosshair_viii_hero),
|
||||
DMI_EXACT_MATCH_ASUS_BOARD_NAME("ROG CROSSHAIR VIII HERO",
|
||||
&board_info_crosshair_viii_hero),
|
||||
DMI_EXACT_MATCH_ASUS_BOARD_NAME("ROG CROSSHAIR VIII HERO (WI-FI)",
|
||||
&board_info_crosshair_viii_hero),
|
||||
DMI_EXACT_MATCH_ASUS_BOARD_NAME("ROG MAXIMUS XI HERO",
|
||||
&board_info_maximus_xi_hero),
|
||||
DMI_EXACT_MATCH_ASUS_BOARD_NAME("ROG MAXIMUS XI HERO (WI-FI)",
|
||||
&board_info_maximus_xi_hero),
|
||||
DMI_EXACT_MATCH_ASUS_BOARD_NAME("ROG CROSSHAIR VIII IMPACT",
|
||||
&board_info_crosshair_viii_impact),
|
||||
DMI_EXACT_MATCH_ASUS_BOARD_NAME("ROG STRIX B550-E GAMING",
|
||||
&board_info_strix_b550_e_gaming),
|
||||
DMI_EXACT_MATCH_ASUS_BOARD_NAME("ROG STRIX B550-I GAMING",
|
||||
&board_info_strix_b550_i_gaming),
|
||||
DMI_EXACT_MATCH_ASUS_BOARD_NAME("ROG STRIX X570-E GAMING",
|
||||
&board_info_strix_x570_e_gaming),
|
||||
DMI_EXACT_MATCH_ASUS_BOARD_NAME("ROG STRIX X570-E GAMING WIFI II",
|
||||
&board_info_strix_x570_e_gaming_wifi_ii),
|
||||
DMI_EXACT_MATCH_ASUS_BOARD_NAME("ROG STRIX X570-F GAMING",
|
||||
&board_info_strix_x570_f_gaming),
|
||||
DMI_EXACT_MATCH_ASUS_BOARD_NAME("ROG STRIX X570-I GAMING",
|
||||
&board_info_strix_x570_i_gaming),
|
||||
DMI_EXACT_MATCH_ASUS_BOARD_NAME("ROG STRIX Z690-A GAMING WIFI D4",
|
||||
&board_info_strix_z690_a_gaming_wifi_d4),
|
||||
DMI_EXACT_MATCH_ASUS_BOARD_NAME("ROG ZENITH II EXTREME",
|
||||
&board_info_zenith_ii_extreme),
|
||||
{},
|
||||
};
|
||||
|
||||
struct ec_sensor {
|
||||
@@ -537,12 +577,12 @@ static int find_ec_sensor_index(const struct ec_sensors_data *ec,
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
static int __init bank_compare(const void *a, const void *b)
|
||||
static int bank_compare(const void *a, const void *b)
|
||||
{
|
||||
return *((const s8 *)a) - *((const s8 *)b);
|
||||
}
|
||||
|
||||
static void __init setup_sensor_data(struct ec_sensors_data *ec)
|
||||
static void setup_sensor_data(struct ec_sensors_data *ec)
|
||||
{
|
||||
struct ec_sensor *s = ec->sensors;
|
||||
bool bank_found;
|
||||
@@ -574,7 +614,7 @@ static void __init setup_sensor_data(struct ec_sensors_data *ec)
|
||||
sort(ec->banks, ec->nr_banks, 1, bank_compare, NULL);
|
||||
}
|
||||
|
||||
static void __init fill_ec_registers(struct ec_sensors_data *ec)
|
||||
static void fill_ec_registers(struct ec_sensors_data *ec)
|
||||
{
|
||||
const struct ec_sensor_info *si;
|
||||
unsigned int i, j, register_idx = 0;
|
||||
@@ -589,7 +629,7 @@ static void __init fill_ec_registers(struct ec_sensors_data *ec)
|
||||
}
|
||||
}
|
||||
|
||||
static int __init setup_lock_data(struct device *dev)
|
||||
static int setup_lock_data(struct device *dev)
|
||||
{
|
||||
const char *mutex_path;
|
||||
int status;
|
||||
@@ -812,7 +852,7 @@ static umode_t asus_ec_hwmon_is_visible(const void *drvdata,
|
||||
return find_ec_sensor_index(state, type, channel) >= 0 ? S_IRUGO : 0;
|
||||
}
|
||||
|
||||
static int __init
|
||||
static int
|
||||
asus_ec_hwmon_add_chan_info(struct hwmon_channel_info *asus_ec_hwmon_chan,
|
||||
struct device *dev, int num,
|
||||
enum hwmon_sensor_types type, u32 config)
|
||||
@@ -841,27 +881,15 @@ static struct hwmon_chip_info asus_ec_chip_info = {
|
||||
.ops = &asus_ec_hwmon_ops,
|
||||
};
|
||||
|
||||
static const struct ec_board_info * __init get_board_info(void)
|
||||
static const struct ec_board_info *get_board_info(void)
|
||||
{
|
||||
const char *dmi_board_vendor = dmi_get_system_info(DMI_BOARD_VENDOR);
|
||||
const char *dmi_board_name = dmi_get_system_info(DMI_BOARD_NAME);
|
||||
const struct ec_board_info *board;
|
||||
const struct dmi_system_id *dmi_entry;
|
||||
|
||||
if (!dmi_board_vendor || !dmi_board_name ||
|
||||
strcasecmp(dmi_board_vendor, "ASUSTeK COMPUTER INC."))
|
||||
return NULL;
|
||||
|
||||
for (board = board_info; board->sensors; board++) {
|
||||
if (match_string(board->board_names,
|
||||
MAX_IDENTICAL_BOARD_VARIATIONS,
|
||||
dmi_board_name) >= 0)
|
||||
return board;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
dmi_entry = dmi_first_match(dmi_table);
|
||||
return dmi_entry ? dmi_entry->driver_data : NULL;
|
||||
}
|
||||
|
||||
static int __init asus_ec_probe(struct platform_device *pdev)
|
||||
static int asus_ec_probe(struct platform_device *pdev)
|
||||
{
|
||||
const struct hwmon_channel_info **ptr_asus_ec_ci;
|
||||
int nr_count[hwmon_max] = { 0 }, nr_types = 0;
|
||||
@@ -970,29 +998,37 @@ static int __init asus_ec_probe(struct platform_device *pdev)
|
||||
return PTR_ERR_OR_ZERO(hwdev);
|
||||
}
|
||||
|
||||
|
||||
static const struct acpi_device_id acpi_ec_ids[] = {
|
||||
/* Embedded Controller Device */
|
||||
{ "PNP0C09", 0 },
|
||||
{}
|
||||
};
|
||||
MODULE_DEVICE_TABLE(dmi, dmi_table);
|
||||
|
||||
static struct platform_driver asus_ec_sensors_platform_driver = {
|
||||
.driver = {
|
||||
.name = "asus-ec-sensors",
|
||||
.acpi_match_table = acpi_ec_ids,
|
||||
},
|
||||
.probe = asus_ec_probe,
|
||||
};
|
||||
|
||||
MODULE_DEVICE_TABLE(acpi, acpi_ec_ids);
|
||||
/*
|
||||
* we use module_platform_driver_probe() rather than module_platform_driver()
|
||||
* because the probe function (and its dependants) are marked with __init, which
|
||||
* means we can't put it into the .probe member of the platform_driver struct
|
||||
* above, and we can't mark the asus_ec_sensors_platform_driver object as __init
|
||||
* because the object is referenced from the module exit code.
|
||||
*/
|
||||
module_platform_driver_probe(asus_ec_sensors_platform_driver, asus_ec_probe);
|
||||
static struct platform_device *asus_ec_sensors_platform_device;
|
||||
|
||||
static int __init asus_ec_init(void)
|
||||
{
|
||||
asus_ec_sensors_platform_device =
|
||||
platform_create_bundle(&asus_ec_sensors_platform_driver,
|
||||
asus_ec_probe, NULL, 0, NULL, 0);
|
||||
|
||||
if (IS_ERR(asus_ec_sensors_platform_device))
|
||||
return PTR_ERR(asus_ec_sensors_platform_device);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void __exit asus_ec_exit(void)
|
||||
{
|
||||
platform_device_unregister(asus_ec_sensors_platform_device);
|
||||
platform_driver_unregister(&asus_ec_sensors_platform_driver);
|
||||
}
|
||||
|
||||
module_init(asus_ec_init);
|
||||
module_exit(asus_ec_exit);
|
||||
|
||||
module_param_named(mutex_path, mutex_path_override, charp, 0);
|
||||
MODULE_PARM_DESC(mutex_path,
|
||||
|
||||
+50
-22
@@ -68,8 +68,9 @@
|
||||
|
||||
/* VM Individual Macro Register */
|
||||
#define VM_COM_REG_SIZE 0x200
|
||||
#define VM_SDIF_DONE(n) (VM_COM_REG_SIZE + 0x34 + 0x200 * (n))
|
||||
#define VM_SDIF_DATA(n) (VM_COM_REG_SIZE + 0x40 + 0x200 * (n))
|
||||
#define VM_SDIF_DONE(vm) (VM_COM_REG_SIZE + 0x34 + 0x200 * (vm))
|
||||
#define VM_SDIF_DATA(vm, ch) \
|
||||
(VM_COM_REG_SIZE + 0x40 + 0x200 * (vm) + 0x4 * (ch))
|
||||
|
||||
/* SDA Slave Register */
|
||||
#define IP_CTRL 0x00
|
||||
@@ -115,6 +116,7 @@ struct pvt_device {
|
||||
u32 t_num;
|
||||
u32 p_num;
|
||||
u32 v_num;
|
||||
u32 c_num;
|
||||
u32 ip_freq;
|
||||
u8 *vm_idx;
|
||||
};
|
||||
@@ -178,14 +180,15 @@ static int pvt_read_in(struct device *dev, u32 attr, int channel, long *val)
|
||||
{
|
||||
struct pvt_device *pvt = dev_get_drvdata(dev);
|
||||
struct regmap *v_map = pvt->v_map;
|
||||
u8 vm_idx, ch_idx;
|
||||
u32 n, stat;
|
||||
u8 vm_idx;
|
||||
int ret;
|
||||
|
||||
if (channel >= pvt->v_num)
|
||||
if (channel >= pvt->v_num * pvt->c_num)
|
||||
return -EINVAL;
|
||||
|
||||
vm_idx = pvt->vm_idx[channel];
|
||||
vm_idx = pvt->vm_idx[channel / pvt->c_num];
|
||||
ch_idx = channel % pvt->c_num;
|
||||
|
||||
switch (attr) {
|
||||
case hwmon_in_input:
|
||||
@@ -196,13 +199,23 @@ static int pvt_read_in(struct device *dev, u32 attr, int channel, long *val)
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = regmap_read(v_map, VM_SDIF_DATA(vm_idx), &n);
|
||||
ret = regmap_read(v_map, VM_SDIF_DATA(vm_idx, ch_idx), &n);
|
||||
if(ret < 0)
|
||||
return ret;
|
||||
|
||||
n &= SAMPLE_DATA_MSK;
|
||||
/* Convert the N bitstream count into voltage */
|
||||
*val = (PVT_N_CONST * n - PVT_R_CONST) >> PVT_CONV_BITS;
|
||||
/*
|
||||
* Convert the N bitstream count into voltage.
|
||||
* To support negative voltage calculation for 64bit machines
|
||||
* n must be cast to long, since n and *val differ both in
|
||||
* signedness and in size.
|
||||
* Division is used instead of right shift, because for signed
|
||||
* numbers, the sign bit is used to fill the vacated bit
|
||||
* positions, and if the number is negative, 1 is used.
|
||||
* BIT(x) may not be used instead of (1 << x) because it's
|
||||
* unsigned.
|
||||
*/
|
||||
*val = (PVT_N_CONST * (long)n - PVT_R_CONST) / (1 << PVT_CONV_BITS);
|
||||
|
||||
return 0;
|
||||
default:
|
||||
@@ -375,6 +388,19 @@ static int pvt_init(struct pvt_device *pvt)
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
val = (BIT(pvt->c_num) - 1) | VM_CH_INIT |
|
||||
IP_POLL << SDIF_ADDR_SFT | SDIF_WRN_W | SDIF_PROG;
|
||||
ret = regmap_write(v_map, SDIF_W, val);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = regmap_read_poll_timeout(v_map, SDIF_STAT,
|
||||
val, !(val & SDIF_BUSY),
|
||||
PVT_POLL_DELAY_US,
|
||||
PVT_POLL_TIMEOUT_US);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
val = CFG1_VOL_MEAS_MODE | CFG1_PARALLEL_OUT |
|
||||
CFG1_14_BIT | IP_CFG << SDIF_ADDR_SFT |
|
||||
SDIF_WRN_W | SDIF_PROG;
|
||||
@@ -489,8 +515,8 @@ static int pvt_reset_control_deassert(struct device *dev, struct pvt_device *pvt
|
||||
|
||||
static int mr75203_probe(struct platform_device *pdev)
|
||||
{
|
||||
u32 ts_num, vm_num, pd_num, ch_num, val, index, i;
|
||||
const struct hwmon_channel_info **pvt_info;
|
||||
u32 ts_num, vm_num, pd_num, val, index, i;
|
||||
struct device *dev = &pdev->dev;
|
||||
u32 *temp_config, *in_config;
|
||||
struct device *hwmon_dev;
|
||||
@@ -531,9 +557,11 @@ static int mr75203_probe(struct platform_device *pdev)
|
||||
ts_num = (val & TS_NUM_MSK) >> TS_NUM_SFT;
|
||||
pd_num = (val & PD_NUM_MSK) >> PD_NUM_SFT;
|
||||
vm_num = (val & VM_NUM_MSK) >> VM_NUM_SFT;
|
||||
ch_num = (val & CH_NUM_MSK) >> CH_NUM_SFT;
|
||||
pvt->t_num = ts_num;
|
||||
pvt->p_num = pd_num;
|
||||
pvt->v_num = vm_num;
|
||||
pvt->c_num = ch_num;
|
||||
val = 0;
|
||||
if (ts_num)
|
||||
val++;
|
||||
@@ -570,7 +598,7 @@ static int mr75203_probe(struct platform_device *pdev)
|
||||
}
|
||||
|
||||
if (vm_num) {
|
||||
u32 num = vm_num;
|
||||
u32 total_ch;
|
||||
|
||||
ret = pvt_get_regmap(pdev, "vm", pvt);
|
||||
if (ret)
|
||||
@@ -584,30 +612,30 @@ static int mr75203_probe(struct platform_device *pdev)
|
||||
ret = device_property_read_u8_array(dev, "intel,vm-map",
|
||||
pvt->vm_idx, vm_num);
|
||||
if (ret) {
|
||||
num = 0;
|
||||
/*
|
||||
* Incase intel,vm-map property is not defined, we
|
||||
* assume incremental channel numbers.
|
||||
*/
|
||||
for (i = 0; i < vm_num; i++)
|
||||
pvt->vm_idx[i] = i;
|
||||
} else {
|
||||
for (i = 0; i < vm_num; i++)
|
||||
if (pvt->vm_idx[i] >= vm_num ||
|
||||
pvt->vm_idx[i] == 0xff) {
|
||||
num = i;
|
||||
pvt->v_num = i;
|
||||
vm_num = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Incase intel,vm-map property is not defined, we assume
|
||||
* incremental channel numbers.
|
||||
*/
|
||||
for (i = num; i < vm_num; i++)
|
||||
pvt->vm_idx[i] = i;
|
||||
|
||||
in_config = devm_kcalloc(dev, num + 1,
|
||||
total_ch = ch_num * vm_num;
|
||||
in_config = devm_kcalloc(dev, total_ch + 1,
|
||||
sizeof(*in_config), GFP_KERNEL);
|
||||
if (!in_config)
|
||||
return -ENOMEM;
|
||||
|
||||
memset32(in_config, HWMON_I_INPUT, num);
|
||||
in_config[num] = 0;
|
||||
memset32(in_config, HWMON_I_INPUT, total_ch);
|
||||
in_config[total_ch] = 0;
|
||||
pvt_in.config = in_config;
|
||||
|
||||
pvt_info[index++] = &pvt_in;
|
||||
|
||||
@@ -493,18 +493,20 @@ static char *tps23861_port_poe_plus_status(struct tps23861_data *data, int port)
|
||||
|
||||
static int tps23861_port_resistance(struct tps23861_data *data, int port)
|
||||
{
|
||||
u16 regval;
|
||||
unsigned int raw_val;
|
||||
__le16 regval;
|
||||
|
||||
regmap_bulk_read(data->regmap,
|
||||
PORT_1_RESISTANCE_LSB + PORT_N_RESISTANCE_LSB_OFFSET * (port - 1),
|
||||
®val,
|
||||
2);
|
||||
|
||||
switch (FIELD_GET(PORT_RESISTANCE_RSN_MASK, regval)) {
|
||||
raw_val = le16_to_cpu(regval);
|
||||
switch (FIELD_GET(PORT_RESISTANCE_RSN_MASK, raw_val)) {
|
||||
case PORT_RESISTANCE_RSN_OTHER:
|
||||
return (FIELD_GET(PORT_RESISTANCE_MASK, regval) * RESISTANCE_LSB) / 10000;
|
||||
return (FIELD_GET(PORT_RESISTANCE_MASK, raw_val) * RESISTANCE_LSB) / 10000;
|
||||
case PORT_RESISTANCE_RSN_LOW:
|
||||
return (FIELD_GET(PORT_RESISTANCE_MASK, regval) * RESISTANCE_LSB_LOW) / 10000;
|
||||
return (FIELD_GET(PORT_RESISTANCE_MASK, raw_val) * RESISTANCE_LSB_LOW) / 10000;
|
||||
case PORT_RESISTANCE_RSN_SHORT:
|
||||
case PORT_RESISTANCE_RSN_OPEN:
|
||||
default:
|
||||
|
||||
@@ -1841,8 +1841,8 @@ cma_ib_id_from_event(struct ib_cm_id *cm_id,
|
||||
}
|
||||
|
||||
if (!validate_net_dev(*net_dev,
|
||||
(struct sockaddr *)&req->listen_addr_storage,
|
||||
(struct sockaddr *)&req->src_addr_storage)) {
|
||||
(struct sockaddr *)&req->src_addr_storage,
|
||||
(struct sockaddr *)&req->listen_addr_storage)) {
|
||||
id_priv = ERR_PTR(-EHOSTUNREACH);
|
||||
goto err;
|
||||
}
|
||||
|
||||
@@ -462,7 +462,7 @@ retry:
|
||||
mutex_unlock(&umem_odp->umem_mutex);
|
||||
|
||||
out_put_mm:
|
||||
mmput(owning_mm);
|
||||
mmput_async(owning_mm);
|
||||
out_put_task:
|
||||
if (owning_process)
|
||||
put_task_struct(owning_process);
|
||||
|
||||
@@ -730,7 +730,6 @@ struct hns_roce_caps {
|
||||
u32 num_qps;
|
||||
u32 num_pi_qps;
|
||||
u32 reserved_qps;
|
||||
int num_qpc_timer;
|
||||
u32 num_srqs;
|
||||
u32 max_wqes;
|
||||
u32 max_srq_wrs;
|
||||
|
||||
@@ -1977,7 +1977,7 @@ static void set_default_caps(struct hns_roce_dev *hr_dev)
|
||||
|
||||
caps->num_mtpts = HNS_ROCE_V2_MAX_MTPT_NUM;
|
||||
caps->num_pds = HNS_ROCE_V2_MAX_PD_NUM;
|
||||
caps->num_qpc_timer = HNS_ROCE_V2_MAX_QPC_TIMER_NUM;
|
||||
caps->qpc_timer_bt_num = HNS_ROCE_V2_MAX_QPC_TIMER_BT_NUM;
|
||||
caps->cqc_timer_bt_num = HNS_ROCE_V2_MAX_CQC_TIMER_BT_NUM;
|
||||
|
||||
caps->max_qp_init_rdma = HNS_ROCE_V2_MAX_QP_INIT_RDMA;
|
||||
@@ -2273,7 +2273,6 @@ static int hns_roce_query_pf_caps(struct hns_roce_dev *hr_dev)
|
||||
caps->max_rq_sg = le16_to_cpu(resp_a->max_rq_sg);
|
||||
caps->max_rq_sg = roundup_pow_of_two(caps->max_rq_sg);
|
||||
caps->max_extend_sg = le32_to_cpu(resp_a->max_extend_sg);
|
||||
caps->num_qpc_timer = le16_to_cpu(resp_a->num_qpc_timer);
|
||||
caps->max_srq_sges = le16_to_cpu(resp_a->max_srq_sges);
|
||||
caps->max_srq_sges = roundup_pow_of_two(caps->max_srq_sges);
|
||||
caps->num_aeq_vectors = resp_a->num_aeq_vectors;
|
||||
|
||||
@@ -36,11 +36,11 @@
|
||||
#include <linux/bitops.h>
|
||||
|
||||
#define HNS_ROCE_V2_MAX_QP_NUM 0x1000
|
||||
#define HNS_ROCE_V2_MAX_QPC_TIMER_NUM 0x200
|
||||
#define HNS_ROCE_V2_MAX_WQE_NUM 0x8000
|
||||
#define HNS_ROCE_V2_MAX_SRQ_WR 0x8000
|
||||
#define HNS_ROCE_V2_MAX_SRQ_SGE 64
|
||||
#define HNS_ROCE_V2_MAX_CQ_NUM 0x100000
|
||||
#define HNS_ROCE_V2_MAX_QPC_TIMER_BT_NUM 0x100
|
||||
#define HNS_ROCE_V2_MAX_CQC_TIMER_BT_NUM 0x100
|
||||
#define HNS_ROCE_V2_MAX_SRQ_NUM 0x100000
|
||||
#define HNS_ROCE_V2_MAX_CQE_NUM 0x400000
|
||||
@@ -83,7 +83,7 @@
|
||||
|
||||
#define HNS_ROCE_V2_QPC_TIMER_ENTRY_SZ PAGE_SIZE
|
||||
#define HNS_ROCE_V2_CQC_TIMER_ENTRY_SZ PAGE_SIZE
|
||||
#define HNS_ROCE_V2_PAGE_SIZE_SUPPORTED 0xFFFFF000
|
||||
#define HNS_ROCE_V2_PAGE_SIZE_SUPPORTED 0xFFFF000
|
||||
#define HNS_ROCE_V2_MAX_INNER_MTPT_NUM 2
|
||||
#define HNS_ROCE_INVALID_LKEY 0x0
|
||||
#define HNS_ROCE_INVALID_SGE_LENGTH 0x80000000
|
||||
|
||||
@@ -725,7 +725,7 @@ static int hns_roce_init_hem(struct hns_roce_dev *hr_dev)
|
||||
ret = hns_roce_init_hem_table(hr_dev, &hr_dev->qpc_timer_table,
|
||||
HEM_TYPE_QPC_TIMER,
|
||||
hr_dev->caps.qpc_timer_entry_sz,
|
||||
hr_dev->caps.num_qpc_timer, 1);
|
||||
hr_dev->caps.qpc_timer_bt_num, 1);
|
||||
if (ret) {
|
||||
dev_err(dev,
|
||||
"Failed to init QPC timer memory, aborting.\n");
|
||||
|
||||
@@ -462,11 +462,8 @@ static int set_rq_size(struct hns_roce_dev *hr_dev, struct ib_qp_cap *cap,
|
||||
hr_qp->rq.max_gs = roundup_pow_of_two(max(1U, cap->max_recv_sge) +
|
||||
hr_qp->rq.rsv_sge);
|
||||
|
||||
if (hr_dev->caps.max_rq_sg <= HNS_ROCE_SGE_IN_WQE)
|
||||
hr_qp->rq.wqe_shift = ilog2(hr_dev->caps.max_rq_desc_sz);
|
||||
else
|
||||
hr_qp->rq.wqe_shift = ilog2(hr_dev->caps.max_rq_desc_sz *
|
||||
hr_qp->rq.max_gs);
|
||||
hr_qp->rq.wqe_shift = ilog2(hr_dev->caps.max_rq_desc_sz *
|
||||
hr_qp->rq.max_gs);
|
||||
|
||||
hr_qp->rq.wqe_cnt = cnt;
|
||||
if (hr_dev->caps.flags & HNS_ROCE_CAP_FLAG_RQ_INLINE &&
|
||||
|
||||
@@ -497,7 +497,8 @@ int irdma_uk_send(struct irdma_qp_uk *qp, struct irdma_post_sq_info *info,
|
||||
FIELD_PREP(IRDMAQPSQ_IMMDATA, info->imm_data));
|
||||
i = 0;
|
||||
} else {
|
||||
qp->wqe_ops.iw_set_fragment(wqe, 0, op_info->sg_list,
|
||||
qp->wqe_ops.iw_set_fragment(wqe, 0,
|
||||
frag_cnt ? op_info->sg_list : NULL,
|
||||
qp->swqe_polarity);
|
||||
i = 1;
|
||||
}
|
||||
@@ -1005,6 +1006,7 @@ int irdma_uk_cq_poll_cmpl(struct irdma_cq_uk *cq,
|
||||
int ret_code;
|
||||
bool move_cq_head = true;
|
||||
u8 polarity;
|
||||
u8 op_type;
|
||||
bool ext_valid;
|
||||
__le64 *ext_cqe;
|
||||
|
||||
@@ -1187,7 +1189,6 @@ int irdma_uk_cq_poll_cmpl(struct irdma_cq_uk *cq,
|
||||
do {
|
||||
__le64 *sw_wqe;
|
||||
u64 wqe_qword;
|
||||
u8 op_type;
|
||||
u32 tail;
|
||||
|
||||
tail = qp->sq_ring.tail;
|
||||
@@ -1204,6 +1205,8 @@ int irdma_uk_cq_poll_cmpl(struct irdma_cq_uk *cq,
|
||||
break;
|
||||
}
|
||||
} while (1);
|
||||
if (op_type == IRDMA_OP_TYPE_BIND_MW && info->minor_err == FLUSH_PROT_ERR)
|
||||
info->minor_err = FLUSH_MW_BIND_ERR;
|
||||
qp->sq_flush_seen = true;
|
||||
if (!IRDMA_RING_MORE_WORK(qp->sq_ring))
|
||||
qp->sq_flush_complete = true;
|
||||
|
||||
@@ -590,11 +590,14 @@ static int irdma_wait_event(struct irdma_pci_f *rf,
|
||||
cqp_error = cqp_request->compl_info.error;
|
||||
if (cqp_error) {
|
||||
err_code = -EIO;
|
||||
if (cqp_request->compl_info.maj_err_code == 0xFFFF &&
|
||||
cqp_request->compl_info.min_err_code == 0x8029) {
|
||||
if (!rf->reset) {
|
||||
rf->reset = true;
|
||||
rf->gen_ops.request_reset(rf);
|
||||
if (cqp_request->compl_info.maj_err_code == 0xFFFF) {
|
||||
if (cqp_request->compl_info.min_err_code == 0x8002)
|
||||
err_code = -EBUSY;
|
||||
else if (cqp_request->compl_info.min_err_code == 0x8029) {
|
||||
if (!rf->reset) {
|
||||
rf->reset = true;
|
||||
rf->gen_ops.request_reset(rf);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2598,7 +2601,7 @@ void irdma_generate_flush_completions(struct irdma_qp *iwqp)
|
||||
spin_unlock_irqrestore(&iwqp->lock, flags2);
|
||||
spin_unlock_irqrestore(&iwqp->iwscq->lock, flags1);
|
||||
if (compl_generated)
|
||||
irdma_comp_handler(iwqp->iwrcq);
|
||||
irdma_comp_handler(iwqp->iwscq);
|
||||
} else {
|
||||
spin_unlock_irqrestore(&iwqp->iwscq->lock, flags1);
|
||||
mod_delayed_work(iwqp->iwdev->cleanup_wq, &iwqp->dwork_flush,
|
||||
|
||||
@@ -39,15 +39,18 @@ static int irdma_query_device(struct ib_device *ibdev,
|
||||
props->max_send_sge = hw_attrs->uk_attrs.max_hw_wq_frags;
|
||||
props->max_recv_sge = hw_attrs->uk_attrs.max_hw_wq_frags;
|
||||
props->max_cq = rf->max_cq - rf->used_cqs;
|
||||
props->max_cqe = rf->max_cqe;
|
||||
props->max_cqe = rf->max_cqe - 1;
|
||||
props->max_mr = rf->max_mr - rf->used_mrs;
|
||||
props->max_mw = props->max_mr;
|
||||
props->max_pd = rf->max_pd - rf->used_pds;
|
||||
props->max_sge_rd = hw_attrs->uk_attrs.max_hw_read_sges;
|
||||
props->max_qp_rd_atom = hw_attrs->max_hw_ird;
|
||||
props->max_qp_init_rd_atom = hw_attrs->max_hw_ord;
|
||||
if (rdma_protocol_roce(ibdev, 1))
|
||||
if (rdma_protocol_roce(ibdev, 1)) {
|
||||
props->device_cap_flags |= IB_DEVICE_RC_RNR_NAK_GEN;
|
||||
props->max_pkeys = IRDMA_PKEY_TBL_SZ;
|
||||
}
|
||||
|
||||
props->max_ah = rf->max_ah;
|
||||
props->max_mcast_grp = rf->max_mcg;
|
||||
props->max_mcast_qp_attach = IRDMA_MAX_MGS_PER_CTX;
|
||||
@@ -3009,6 +3012,7 @@ static int irdma_dereg_mr(struct ib_mr *ib_mr, struct ib_udata *udata)
|
||||
struct irdma_pble_alloc *palloc = &iwpbl->pble_alloc;
|
||||
struct irdma_cqp_request *cqp_request;
|
||||
struct cqp_cmds_info *cqp_info;
|
||||
int status;
|
||||
|
||||
if (iwmr->type != IRDMA_MEMREG_TYPE_MEM) {
|
||||
if (iwmr->region) {
|
||||
@@ -3039,8 +3043,11 @@ static int irdma_dereg_mr(struct ib_mr *ib_mr, struct ib_udata *udata)
|
||||
cqp_info->post_sq = 1;
|
||||
cqp_info->in.u.dealloc_stag.dev = &iwdev->rf->sc_dev;
|
||||
cqp_info->in.u.dealloc_stag.scratch = (uintptr_t)cqp_request;
|
||||
irdma_handle_cqp_op(iwdev->rf, cqp_request);
|
||||
status = irdma_handle_cqp_op(iwdev->rf, cqp_request);
|
||||
irdma_put_cqp_request(&iwdev->rf->cqp, cqp_request);
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
irdma_free_stag(iwdev, iwmr->stag);
|
||||
done:
|
||||
if (iwpbl->pbl_allocated)
|
||||
|
||||
@@ -166,6 +166,12 @@ static int process_pma_cmd(struct mlx5_ib_dev *dev, u32 port_num,
|
||||
mdev = dev->mdev;
|
||||
mdev_port_num = 1;
|
||||
}
|
||||
if (MLX5_CAP_GEN(dev->mdev, num_ports) == 1) {
|
||||
/* set local port to one for Function-Per-Port HCA. */
|
||||
mdev = dev->mdev;
|
||||
mdev_port_num = 1;
|
||||
}
|
||||
|
||||
/* Declaring support of extended counters */
|
||||
if (in_mad->mad_hdr.attr_id == IB_PMA_CLASS_PORT_INFO) {
|
||||
struct ib_class_port_info cpi = {};
|
||||
|
||||
@@ -4336,7 +4336,7 @@ static int mlx5r_probe(struct auxiliary_device *adev,
|
||||
dev->mdev = mdev;
|
||||
dev->num_ports = num_ports;
|
||||
|
||||
if (ll == IB_LINK_LAYER_ETHERNET && !mlx5_is_roce_init_enabled(mdev))
|
||||
if (ll == IB_LINK_LAYER_ETHERNET && !mlx5_get_roce_state(mdev))
|
||||
profile = &raw_eth_profile;
|
||||
else
|
||||
profile = &pf_profile;
|
||||
|
||||
@@ -708,6 +708,7 @@ struct mlx5_ib_umr_context {
|
||||
};
|
||||
|
||||
enum {
|
||||
MLX5_UMR_STATE_UNINIT,
|
||||
MLX5_UMR_STATE_ACTIVE,
|
||||
MLX5_UMR_STATE_RECOVER,
|
||||
MLX5_UMR_STATE_ERR,
|
||||
|
||||
@@ -177,6 +177,7 @@ int mlx5r_umr_resource_init(struct mlx5_ib_dev *dev)
|
||||
|
||||
sema_init(&dev->umrc.sem, MAX_UMR_WR);
|
||||
mutex_init(&dev->umrc.lock);
|
||||
dev->umrc.state = MLX5_UMR_STATE_ACTIVE;
|
||||
|
||||
return 0;
|
||||
|
||||
@@ -191,6 +192,8 @@ destroy_pd:
|
||||
|
||||
void mlx5r_umr_resource_cleanup(struct mlx5_ib_dev *dev)
|
||||
{
|
||||
if (dev->umrc.state == MLX5_UMR_STATE_UNINIT)
|
||||
return;
|
||||
ib_destroy_qp(dev->umrc.qp);
|
||||
ib_free_cq(dev->umrc.cq);
|
||||
ib_dealloc_pd(dev->umrc.pd);
|
||||
|
||||
@@ -29,7 +29,7 @@ static struct page *siw_get_pblpage(struct siw_mem *mem, u64 addr, int *idx)
|
||||
dma_addr_t paddr = siw_pbl_get_buffer(pbl, offset, NULL, idx);
|
||||
|
||||
if (paddr)
|
||||
return virt_to_page(paddr);
|
||||
return virt_to_page((void *)paddr);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
@@ -533,13 +533,23 @@ static int siw_tx_hdt(struct siw_iwarp_tx *c_tx, struct socket *s)
|
||||
kunmap_local(kaddr);
|
||||
}
|
||||
} else {
|
||||
u64 va = sge->laddr + sge_off;
|
||||
/*
|
||||
* Cast to an uintptr_t to preserve all 64 bits
|
||||
* in sge->laddr.
|
||||
*/
|
||||
uintptr_t va = (uintptr_t)(sge->laddr + sge_off);
|
||||
|
||||
page_array[seg] = virt_to_page(va & PAGE_MASK);
|
||||
/*
|
||||
* virt_to_page() takes a (void *) pointer
|
||||
* so cast to a (void *) meaning it will be 64
|
||||
* bits on a 64 bit platform and 32 bits on a
|
||||
* 32 bit platform.
|
||||
*/
|
||||
page_array[seg] = virt_to_page((void *)(va & PAGE_MASK));
|
||||
if (do_crc)
|
||||
crypto_shash_update(
|
||||
c_tx->mpa_crc_hd,
|
||||
(void *)(uintptr_t)va,
|
||||
(void *)va,
|
||||
plen);
|
||||
}
|
||||
|
||||
|
||||
@@ -1004,7 +1004,8 @@ rtrs_clt_get_copy_req(struct rtrs_clt_path *alive_path,
|
||||
static int rtrs_post_rdma_write_sg(struct rtrs_clt_con *con,
|
||||
struct rtrs_clt_io_req *req,
|
||||
struct rtrs_rbuf *rbuf, bool fr_en,
|
||||
u32 size, u32 imm, struct ib_send_wr *wr,
|
||||
u32 count, u32 size, u32 imm,
|
||||
struct ib_send_wr *wr,
|
||||
struct ib_send_wr *tail)
|
||||
{
|
||||
struct rtrs_clt_path *clt_path = to_clt_path(con->c.path);
|
||||
@@ -1024,12 +1025,12 @@ static int rtrs_post_rdma_write_sg(struct rtrs_clt_con *con,
|
||||
num_sge = 2;
|
||||
ptail = tail;
|
||||
} else {
|
||||
for_each_sg(req->sglist, sg, req->sg_cnt, i) {
|
||||
for_each_sg(req->sglist, sg, count, i) {
|
||||
sge[i].addr = sg_dma_address(sg);
|
||||
sge[i].length = sg_dma_len(sg);
|
||||
sge[i].lkey = clt_path->s.dev->ib_pd->local_dma_lkey;
|
||||
}
|
||||
num_sge = 1 + req->sg_cnt;
|
||||
num_sge = 1 + count;
|
||||
}
|
||||
sge[i].addr = req->iu->dma_addr;
|
||||
sge[i].length = size;
|
||||
@@ -1142,7 +1143,7 @@ static int rtrs_clt_write_req(struct rtrs_clt_io_req *req)
|
||||
*/
|
||||
rtrs_clt_update_all_stats(req, WRITE);
|
||||
|
||||
ret = rtrs_post_rdma_write_sg(req->con, req, rbuf, fr_en,
|
||||
ret = rtrs_post_rdma_write_sg(req->con, req, rbuf, fr_en, count,
|
||||
req->usr_len + sizeof(*msg),
|
||||
imm, wr, &inv_wr);
|
||||
if (ret) {
|
||||
|
||||
@@ -595,7 +595,7 @@ static int map_cont_bufs(struct rtrs_srv_path *srv_path)
|
||||
struct sg_table *sgt = &srv_mr->sgt;
|
||||
struct scatterlist *s;
|
||||
struct ib_mr *mr;
|
||||
int nr, chunks;
|
||||
int nr, nr_sgt, chunks;
|
||||
|
||||
chunks = chunks_per_mr * mri;
|
||||
if (!always_invalidate)
|
||||
@@ -610,19 +610,19 @@ static int map_cont_bufs(struct rtrs_srv_path *srv_path)
|
||||
sg_set_page(s, srv->chunks[chunks + i],
|
||||
max_chunk_size, 0);
|
||||
|
||||
nr = ib_dma_map_sg(srv_path->s.dev->ib_dev, sgt->sgl,
|
||||
nr_sgt = ib_dma_map_sg(srv_path->s.dev->ib_dev, sgt->sgl,
|
||||
sgt->nents, DMA_BIDIRECTIONAL);
|
||||
if (nr < sgt->nents) {
|
||||
err = nr < 0 ? nr : -EINVAL;
|
||||
if (!nr_sgt) {
|
||||
err = -EINVAL;
|
||||
goto free_sg;
|
||||
}
|
||||
mr = ib_alloc_mr(srv_path->s.dev->ib_pd, IB_MR_TYPE_MEM_REG,
|
||||
sgt->nents);
|
||||
nr_sgt);
|
||||
if (IS_ERR(mr)) {
|
||||
err = PTR_ERR(mr);
|
||||
goto unmap_sg;
|
||||
}
|
||||
nr = ib_map_mr_sg(mr, sgt->sgl, sgt->nents,
|
||||
nr = ib_map_mr_sg(mr, sgt->sgl, nr_sgt,
|
||||
NULL, max_chunk_size);
|
||||
if (nr < 0 || nr < sgt->nents) {
|
||||
err = nr < 0 ? nr : -EINVAL;
|
||||
@@ -641,7 +641,7 @@ static int map_cont_bufs(struct rtrs_srv_path *srv_path)
|
||||
}
|
||||
}
|
||||
/* Eventually dma addr for each chunk can be cached */
|
||||
for_each_sg(sgt->sgl, s, sgt->orig_nents, i)
|
||||
for_each_sg(sgt->sgl, s, nr_sgt, i)
|
||||
srv_path->dma_addr[chunks + i] = sg_dma_address(s);
|
||||
|
||||
ib_update_fast_reg_key(mr, ib_inc_rkey(mr->rkey));
|
||||
|
||||
@@ -1961,7 +1961,8 @@ static void srp_process_rsp(struct srp_rdma_ch *ch, struct srp_rsp *rsp)
|
||||
if (scmnd) {
|
||||
req = scsi_cmd_priv(scmnd);
|
||||
scmnd = srp_claim_req(ch, req, NULL, scmnd);
|
||||
} else {
|
||||
}
|
||||
if (!scmnd) {
|
||||
shost_printk(KERN_ERR, target->scsi_host,
|
||||
"Null scmnd for RSP w/tag %#016llx received on ch %td / QP %#x\n",
|
||||
rsp->tag, ch - target->ch, ch->qp->qp_num);
|
||||
|
||||
@@ -939,7 +939,8 @@ static void build_completion_wait(struct iommu_cmd *cmd,
|
||||
memset(cmd, 0, sizeof(*cmd));
|
||||
cmd->data[0] = lower_32_bits(paddr) | CMD_COMPL_WAIT_STORE_MASK;
|
||||
cmd->data[1] = upper_32_bits(paddr);
|
||||
cmd->data[2] = data;
|
||||
cmd->data[2] = lower_32_bits(data);
|
||||
cmd->data[3] = upper_32_bits(data);
|
||||
CMD_SET_TYPE(cmd, CMD_COMPL_WAIT);
|
||||
}
|
||||
|
||||
|
||||
@@ -777,6 +777,8 @@ int amd_iommu_init_device(struct pci_dev *pdev, int pasids)
|
||||
if (dev_state->domain == NULL)
|
||||
goto out_free_states;
|
||||
|
||||
/* See iommu_is_default_domain() */
|
||||
dev_state->domain->type = IOMMU_DOMAIN_IDENTITY;
|
||||
amd_iommu_domain_direct_map(dev_state->domain);
|
||||
|
||||
ret = amd_iommu_domain_enable_v2(dev_state->domain, pasids);
|
||||
|
||||
@@ -2349,6 +2349,13 @@ static int dmar_device_hotplug(acpi_handle handle, bool insert)
|
||||
if (!dmar_in_use())
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* It's unlikely that any I/O board is hot added before the IOMMU
|
||||
* subsystem is initialized.
|
||||
*/
|
||||
if (IS_ENABLED(CONFIG_INTEL_IOMMU) && !intel_iommu_enabled)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
if (dmar_detect_dsm(handle, DMAR_DSM_FUNC_DRHD)) {
|
||||
tmp = handle;
|
||||
} else {
|
||||
|
||||
+113
-128
@@ -163,38 +163,6 @@ static phys_addr_t root_entry_uctp(struct root_entry *re)
|
||||
return re->hi & VTD_PAGE_MASK;
|
||||
}
|
||||
|
||||
static inline void context_clear_pasid_enable(struct context_entry *context)
|
||||
{
|
||||
context->lo &= ~(1ULL << 11);
|
||||
}
|
||||
|
||||
static inline bool context_pasid_enabled(struct context_entry *context)
|
||||
{
|
||||
return !!(context->lo & (1ULL << 11));
|
||||
}
|
||||
|
||||
static inline void context_set_copied(struct context_entry *context)
|
||||
{
|
||||
context->hi |= (1ull << 3);
|
||||
}
|
||||
|
||||
static inline bool context_copied(struct context_entry *context)
|
||||
{
|
||||
return !!(context->hi & (1ULL << 3));
|
||||
}
|
||||
|
||||
static inline bool __context_present(struct context_entry *context)
|
||||
{
|
||||
return (context->lo & 1);
|
||||
}
|
||||
|
||||
bool context_present(struct context_entry *context)
|
||||
{
|
||||
return context_pasid_enabled(context) ?
|
||||
__context_present(context) :
|
||||
__context_present(context) && !context_copied(context);
|
||||
}
|
||||
|
||||
static inline void context_set_present(struct context_entry *context)
|
||||
{
|
||||
context->lo |= 1;
|
||||
@@ -242,6 +210,26 @@ static inline void context_clear_entry(struct context_entry *context)
|
||||
context->hi = 0;
|
||||
}
|
||||
|
||||
static inline bool context_copied(struct intel_iommu *iommu, u8 bus, u8 devfn)
|
||||
{
|
||||
if (!iommu->copied_tables)
|
||||
return false;
|
||||
|
||||
return test_bit(((long)bus << 8) | devfn, iommu->copied_tables);
|
||||
}
|
||||
|
||||
static inline void
|
||||
set_context_copied(struct intel_iommu *iommu, u8 bus, u8 devfn)
|
||||
{
|
||||
set_bit(((long)bus << 8) | devfn, iommu->copied_tables);
|
||||
}
|
||||
|
||||
static inline void
|
||||
clear_context_copied(struct intel_iommu *iommu, u8 bus, u8 devfn)
|
||||
{
|
||||
clear_bit(((long)bus << 8) | devfn, iommu->copied_tables);
|
||||
}
|
||||
|
||||
/*
|
||||
* This domain is a statically identity mapping domain.
|
||||
* 1. This domain creats a static 1:1 mapping to all usable memory.
|
||||
@@ -402,14 +390,36 @@ static inline int domain_pfn_supported(struct dmar_domain *domain,
|
||||
return !(addr_width < BITS_PER_LONG && pfn >> addr_width);
|
||||
}
|
||||
|
||||
/*
|
||||
* Calculate the Supported Adjusted Guest Address Widths of an IOMMU.
|
||||
* Refer to 11.4.2 of the VT-d spec for the encoding of each bit of
|
||||
* the returned SAGAW.
|
||||
*/
|
||||
static unsigned long __iommu_calculate_sagaw(struct intel_iommu *iommu)
|
||||
{
|
||||
unsigned long fl_sagaw, sl_sagaw;
|
||||
|
||||
fl_sagaw = BIT(2) | (cap_fl1gp_support(iommu->cap) ? BIT(3) : 0);
|
||||
sl_sagaw = cap_sagaw(iommu->cap);
|
||||
|
||||
/* Second level only. */
|
||||
if (!sm_supported(iommu) || !ecap_flts(iommu->ecap))
|
||||
return sl_sagaw;
|
||||
|
||||
/* First level only. */
|
||||
if (!ecap_slts(iommu->ecap))
|
||||
return fl_sagaw;
|
||||
|
||||
return fl_sagaw & sl_sagaw;
|
||||
}
|
||||
|
||||
static int __iommu_calculate_agaw(struct intel_iommu *iommu, int max_gaw)
|
||||
{
|
||||
unsigned long sagaw;
|
||||
int agaw;
|
||||
|
||||
sagaw = cap_sagaw(iommu->cap);
|
||||
for (agaw = width_to_agaw(max_gaw);
|
||||
agaw >= 0; agaw--) {
|
||||
sagaw = __iommu_calculate_sagaw(iommu);
|
||||
for (agaw = width_to_agaw(max_gaw); agaw >= 0; agaw--) {
|
||||
if (test_bit(agaw, &sagaw))
|
||||
break;
|
||||
}
|
||||
@@ -505,8 +515,9 @@ static int domain_update_device_node(struct dmar_domain *domain)
|
||||
{
|
||||
struct device_domain_info *info;
|
||||
int nid = NUMA_NO_NODE;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock(&domain->lock);
|
||||
spin_lock_irqsave(&domain->lock, flags);
|
||||
list_for_each_entry(info, &domain->devices, link) {
|
||||
/*
|
||||
* There could possibly be multiple device numa nodes as devices
|
||||
@@ -518,7 +529,7 @@ static int domain_update_device_node(struct dmar_domain *domain)
|
||||
if (nid != NUMA_NO_NODE)
|
||||
break;
|
||||
}
|
||||
spin_unlock(&domain->lock);
|
||||
spin_unlock_irqrestore(&domain->lock, flags);
|
||||
|
||||
return nid;
|
||||
}
|
||||
@@ -578,6 +589,13 @@ struct context_entry *iommu_context_addr(struct intel_iommu *iommu, u8 bus,
|
||||
struct context_entry *context;
|
||||
u64 *entry;
|
||||
|
||||
/*
|
||||
* Except that the caller requested to allocate a new entry,
|
||||
* returning a copied context entry makes no sense.
|
||||
*/
|
||||
if (!alloc && context_copied(iommu, bus, devfn))
|
||||
return NULL;
|
||||
|
||||
entry = &root->lo;
|
||||
if (sm_supported(iommu)) {
|
||||
if (devfn >= 0x80) {
|
||||
@@ -795,32 +813,11 @@ static void free_context_table(struct intel_iommu *iommu)
|
||||
}
|
||||
|
||||
#ifdef CONFIG_DMAR_DEBUG
|
||||
static void pgtable_walk(struct intel_iommu *iommu, unsigned long pfn, u8 bus, u8 devfn)
|
||||
static void pgtable_walk(struct intel_iommu *iommu, unsigned long pfn,
|
||||
u8 bus, u8 devfn, struct dma_pte *parent, int level)
|
||||
{
|
||||
struct device_domain_info *info;
|
||||
struct dma_pte *parent, *pte;
|
||||
struct dmar_domain *domain;
|
||||
struct pci_dev *pdev;
|
||||
int offset, level;
|
||||
|
||||
pdev = pci_get_domain_bus_and_slot(iommu->segment, bus, devfn);
|
||||
if (!pdev)
|
||||
return;
|
||||
|
||||
info = dev_iommu_priv_get(&pdev->dev);
|
||||
if (!info || !info->domain) {
|
||||
pr_info("device [%02x:%02x.%d] not probed\n",
|
||||
bus, PCI_SLOT(devfn), PCI_FUNC(devfn));
|
||||
return;
|
||||
}
|
||||
|
||||
domain = info->domain;
|
||||
level = agaw_to_level(domain->agaw);
|
||||
parent = domain->pgd;
|
||||
if (!parent) {
|
||||
pr_info("no page table setup\n");
|
||||
return;
|
||||
}
|
||||
struct dma_pte *pte;
|
||||
int offset;
|
||||
|
||||
while (1) {
|
||||
offset = pfn_level_offset(pfn, level);
|
||||
@@ -847,9 +844,10 @@ void dmar_fault_dump_ptes(struct intel_iommu *iommu, u16 source_id,
|
||||
struct pasid_entry *entries, *pte;
|
||||
struct context_entry *ctx_entry;
|
||||
struct root_entry *rt_entry;
|
||||
int i, dir_index, index, level;
|
||||
u8 devfn = source_id & 0xff;
|
||||
u8 bus = source_id >> 8;
|
||||
int i, dir_index, index;
|
||||
struct dma_pte *pgtable;
|
||||
|
||||
pr_info("Dump %s table entries for IOVA 0x%llx\n", iommu->name, addr);
|
||||
|
||||
@@ -877,8 +875,11 @@ void dmar_fault_dump_ptes(struct intel_iommu *iommu, u16 source_id,
|
||||
ctx_entry->hi, ctx_entry->lo);
|
||||
|
||||
/* legacy mode does not require PASID entries */
|
||||
if (!sm_supported(iommu))
|
||||
if (!sm_supported(iommu)) {
|
||||
level = agaw_to_level(ctx_entry->hi & 7);
|
||||
pgtable = phys_to_virt(ctx_entry->lo & VTD_PAGE_MASK);
|
||||
goto pgtable_walk;
|
||||
}
|
||||
|
||||
/* get the pointer to pasid directory entry */
|
||||
dir = phys_to_virt(ctx_entry->lo & VTD_PAGE_MASK);
|
||||
@@ -905,8 +906,16 @@ void dmar_fault_dump_ptes(struct intel_iommu *iommu, u16 source_id,
|
||||
for (i = 0; i < ARRAY_SIZE(pte->val); i++)
|
||||
pr_info("pasid table entry[%d]: 0x%016llx\n", i, pte->val[i]);
|
||||
|
||||
if (pasid_pte_get_pgtt(pte) == PASID_ENTRY_PGTT_FL_ONLY) {
|
||||
level = pte->val[2] & BIT_ULL(2) ? 5 : 4;
|
||||
pgtable = phys_to_virt(pte->val[2] & VTD_PAGE_MASK);
|
||||
} else {
|
||||
level = agaw_to_level((pte->val[0] >> 2) & 0x7);
|
||||
pgtable = phys_to_virt(pte->val[0] & VTD_PAGE_MASK);
|
||||
}
|
||||
|
||||
pgtable_walk:
|
||||
pgtable_walk(iommu, addr >> VTD_PAGE_SHIFT, bus, devfn);
|
||||
pgtable_walk(iommu, addr >> VTD_PAGE_SHIFT, bus, devfn, pgtable, level);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -1345,19 +1354,20 @@ iommu_support_dev_iotlb(struct dmar_domain *domain, struct intel_iommu *iommu,
|
||||
u8 bus, u8 devfn)
|
||||
{
|
||||
struct device_domain_info *info;
|
||||
unsigned long flags;
|
||||
|
||||
if (!iommu->qi)
|
||||
return NULL;
|
||||
|
||||
spin_lock(&domain->lock);
|
||||
spin_lock_irqsave(&domain->lock, flags);
|
||||
list_for_each_entry(info, &domain->devices, link) {
|
||||
if (info->iommu == iommu && info->bus == bus &&
|
||||
info->devfn == devfn) {
|
||||
spin_unlock(&domain->lock);
|
||||
spin_unlock_irqrestore(&domain->lock, flags);
|
||||
return info->ats_supported ? info : NULL;
|
||||
}
|
||||
}
|
||||
spin_unlock(&domain->lock);
|
||||
spin_unlock_irqrestore(&domain->lock, flags);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
@@ -1366,8 +1376,9 @@ static void domain_update_iotlb(struct dmar_domain *domain)
|
||||
{
|
||||
struct device_domain_info *info;
|
||||
bool has_iotlb_device = false;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock(&domain->lock);
|
||||
spin_lock_irqsave(&domain->lock, flags);
|
||||
list_for_each_entry(info, &domain->devices, link) {
|
||||
if (info->ats_enabled) {
|
||||
has_iotlb_device = true;
|
||||
@@ -1375,7 +1386,7 @@ static void domain_update_iotlb(struct dmar_domain *domain)
|
||||
}
|
||||
}
|
||||
domain->has_iotlb_device = has_iotlb_device;
|
||||
spin_unlock(&domain->lock);
|
||||
spin_unlock_irqrestore(&domain->lock, flags);
|
||||
}
|
||||
|
||||
static void iommu_enable_dev_iotlb(struct device_domain_info *info)
|
||||
@@ -1467,14 +1478,15 @@ static void iommu_flush_dev_iotlb(struct dmar_domain *domain,
|
||||
u64 addr, unsigned mask)
|
||||
{
|
||||
struct device_domain_info *info;
|
||||
unsigned long flags;
|
||||
|
||||
if (!domain->has_iotlb_device)
|
||||
return;
|
||||
|
||||
spin_lock(&domain->lock);
|
||||
spin_lock_irqsave(&domain->lock, flags);
|
||||
list_for_each_entry(info, &domain->devices, link)
|
||||
__iommu_flush_dev_iotlb(info, addr, mask);
|
||||
spin_unlock(&domain->lock);
|
||||
spin_unlock_irqrestore(&domain->lock, flags);
|
||||
}
|
||||
|
||||
static void iommu_flush_iotlb_psi(struct intel_iommu *iommu,
|
||||
@@ -1688,6 +1700,11 @@ static void free_dmar_iommu(struct intel_iommu *iommu)
|
||||
iommu->domain_ids = NULL;
|
||||
}
|
||||
|
||||
if (iommu->copied_tables) {
|
||||
bitmap_free(iommu->copied_tables);
|
||||
iommu->copied_tables = NULL;
|
||||
}
|
||||
|
||||
/* free context mapping */
|
||||
free_context_table(iommu);
|
||||
|
||||
@@ -1913,7 +1930,7 @@ static int domain_context_mapping_one(struct dmar_domain *domain,
|
||||
goto out_unlock;
|
||||
|
||||
ret = 0;
|
||||
if (context_present(context))
|
||||
if (context_present(context) && !context_copied(iommu, bus, devfn))
|
||||
goto out_unlock;
|
||||
|
||||
/*
|
||||
@@ -1925,7 +1942,7 @@ static int domain_context_mapping_one(struct dmar_domain *domain,
|
||||
* in-flight DMA will exist, and we don't need to worry anymore
|
||||
* hereafter.
|
||||
*/
|
||||
if (context_copied(context)) {
|
||||
if (context_copied(iommu, bus, devfn)) {
|
||||
u16 did_old = context_domain_id(context);
|
||||
|
||||
if (did_old < cap_ndoms(iommu->cap)) {
|
||||
@@ -1936,6 +1953,8 @@ static int domain_context_mapping_one(struct dmar_domain *domain,
|
||||
iommu->flush.flush_iotlb(iommu, did_old, 0, 0,
|
||||
DMA_TLB_DSI_FLUSH);
|
||||
}
|
||||
|
||||
clear_context_copied(iommu, bus, devfn);
|
||||
}
|
||||
|
||||
context_clear_entry(context);
|
||||
@@ -2429,6 +2448,7 @@ static int domain_add_dev_info(struct dmar_domain *domain, struct device *dev)
|
||||
{
|
||||
struct device_domain_info *info = dev_iommu_priv_get(dev);
|
||||
struct intel_iommu *iommu;
|
||||
unsigned long flags;
|
||||
u8 bus, devfn;
|
||||
int ret;
|
||||
|
||||
@@ -2440,9 +2460,9 @@ static int domain_add_dev_info(struct dmar_domain *domain, struct device *dev)
|
||||
if (ret)
|
||||
return ret;
|
||||
info->domain = domain;
|
||||
spin_lock(&domain->lock);
|
||||
spin_lock_irqsave(&domain->lock, flags);
|
||||
list_add(&info->link, &domain->devices);
|
||||
spin_unlock(&domain->lock);
|
||||
spin_unlock_irqrestore(&domain->lock, flags);
|
||||
|
||||
/* PASID table is mandatory for a PCI device in scalable mode. */
|
||||
if (sm_supported(iommu) && !dev_is_real_dma_subdevice(dev)) {
|
||||
@@ -2684,32 +2704,14 @@ static int copy_context_table(struct intel_iommu *iommu,
|
||||
/* Now copy the context entry */
|
||||
memcpy(&ce, old_ce + idx, sizeof(ce));
|
||||
|
||||
if (!__context_present(&ce))
|
||||
if (!context_present(&ce))
|
||||
continue;
|
||||
|
||||
did = context_domain_id(&ce);
|
||||
if (did >= 0 && did < cap_ndoms(iommu->cap))
|
||||
set_bit(did, iommu->domain_ids);
|
||||
|
||||
/*
|
||||
* We need a marker for copied context entries. This
|
||||
* marker needs to work for the old format as well as
|
||||
* for extended context entries.
|
||||
*
|
||||
* Bit 67 of the context entry is used. In the old
|
||||
* format this bit is available to software, in the
|
||||
* extended format it is the PGE bit, but PGE is ignored
|
||||
* by HW if PASIDs are disabled (and thus still
|
||||
* available).
|
||||
*
|
||||
* So disable PASIDs first and then mark the entry
|
||||
* copied. This means that we don't copy PASID
|
||||
* translations from the old kernel, but this is fine as
|
||||
* faults there are not fatal.
|
||||
*/
|
||||
context_clear_pasid_enable(&ce);
|
||||
context_set_copied(&ce);
|
||||
|
||||
set_context_copied(iommu, bus, devfn);
|
||||
new_ce[idx] = ce;
|
||||
}
|
||||
|
||||
@@ -2735,8 +2737,8 @@ static int copy_translation_tables(struct intel_iommu *iommu)
|
||||
bool new_ext, ext;
|
||||
|
||||
rtaddr_reg = dmar_readq(iommu->reg + DMAR_RTADDR_REG);
|
||||
ext = !!(rtaddr_reg & DMA_RTADDR_RTT);
|
||||
new_ext = !!ecap_ecs(iommu->ecap);
|
||||
ext = !!(rtaddr_reg & DMA_RTADDR_SMT);
|
||||
new_ext = !!sm_supported(iommu);
|
||||
|
||||
/*
|
||||
* The RTT bit can only be changed when translation is disabled,
|
||||
@@ -2747,6 +2749,10 @@ static int copy_translation_tables(struct intel_iommu *iommu)
|
||||
if (new_ext != ext)
|
||||
return -EINVAL;
|
||||
|
||||
iommu->copied_tables = bitmap_zalloc(BIT_ULL(16), GFP_KERNEL);
|
||||
if (!iommu->copied_tables)
|
||||
return -ENOMEM;
|
||||
|
||||
old_rt_phys = rtaddr_reg & VTD_PAGE_MASK;
|
||||
if (!old_rt_phys)
|
||||
return -EINVAL;
|
||||
@@ -3013,13 +3019,7 @@ static int __init init_dmars(void)
|
||||
|
||||
#ifdef CONFIG_INTEL_IOMMU_SVM
|
||||
if (pasid_supported(iommu) && ecap_prs(iommu->ecap)) {
|
||||
/*
|
||||
* Call dmar_alloc_hwirq() with dmar_global_lock held,
|
||||
* could cause possible lock race condition.
|
||||
*/
|
||||
up_write(&dmar_global_lock);
|
||||
ret = intel_svm_enable_prq(iommu);
|
||||
down_write(&dmar_global_lock);
|
||||
if (ret)
|
||||
goto free_iommu;
|
||||
}
|
||||
@@ -3932,7 +3932,6 @@ int __init intel_iommu_init(void)
|
||||
force_on = (!intel_iommu_tboot_noforce && tboot_force_iommu()) ||
|
||||
platform_optin_force_iommu();
|
||||
|
||||
down_write(&dmar_global_lock);
|
||||
if (dmar_table_init()) {
|
||||
if (force_on)
|
||||
panic("tboot: Failed to initialize DMAR table\n");
|
||||
@@ -3945,16 +3944,6 @@ int __init intel_iommu_init(void)
|
||||
goto out_free_dmar;
|
||||
}
|
||||
|
||||
up_write(&dmar_global_lock);
|
||||
|
||||
/*
|
||||
* The bus notifier takes the dmar_global_lock, so lockdep will
|
||||
* complain later when we register it under the lock.
|
||||
*/
|
||||
dmar_register_bus_notifier();
|
||||
|
||||
down_write(&dmar_global_lock);
|
||||
|
||||
if (!no_iommu)
|
||||
intel_iommu_debugfs_init();
|
||||
|
||||
@@ -3999,11 +3988,9 @@ int __init intel_iommu_init(void)
|
||||
pr_err("Initialization failed\n");
|
||||
goto out_free_dmar;
|
||||
}
|
||||
up_write(&dmar_global_lock);
|
||||
|
||||
init_iommu_pm_ops();
|
||||
|
||||
down_read(&dmar_global_lock);
|
||||
for_each_active_iommu(iommu, drhd) {
|
||||
/*
|
||||
* The flush queue implementation does not perform
|
||||
@@ -4021,13 +4008,11 @@ int __init intel_iommu_init(void)
|
||||
"%s", iommu->name);
|
||||
iommu_device_register(&iommu->iommu, &intel_iommu_ops, NULL);
|
||||
}
|
||||
up_read(&dmar_global_lock);
|
||||
|
||||
bus_set_iommu(&pci_bus_type, &intel_iommu_ops);
|
||||
if (si_domain && !hw_pass_through)
|
||||
register_memory_notifier(&intel_iommu_memory_nb);
|
||||
|
||||
down_read(&dmar_global_lock);
|
||||
if (probe_acpi_namespace_devices())
|
||||
pr_warn("ACPI name space devices didn't probe correctly\n");
|
||||
|
||||
@@ -4038,17 +4023,15 @@ int __init intel_iommu_init(void)
|
||||
|
||||
iommu_disable_protect_mem_regions(iommu);
|
||||
}
|
||||
up_read(&dmar_global_lock);
|
||||
|
||||
pr_info("Intel(R) Virtualization Technology for Directed I/O\n");
|
||||
|
||||
intel_iommu_enabled = 1;
|
||||
dmar_register_bus_notifier();
|
||||
pr_info("Intel(R) Virtualization Technology for Directed I/O\n");
|
||||
|
||||
return 0;
|
||||
|
||||
out_free_dmar:
|
||||
intel_iommu_free_dmars();
|
||||
up_write(&dmar_global_lock);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -4080,6 +4063,7 @@ static void dmar_remove_one_dev_info(struct device *dev)
|
||||
struct device_domain_info *info = dev_iommu_priv_get(dev);
|
||||
struct dmar_domain *domain = info->domain;
|
||||
struct intel_iommu *iommu = info->iommu;
|
||||
unsigned long flags;
|
||||
|
||||
if (!dev_is_real_dma_subdevice(info->dev)) {
|
||||
if (dev_is_pci(info->dev) && sm_supported(iommu))
|
||||
@@ -4091,9 +4075,9 @@ static void dmar_remove_one_dev_info(struct device *dev)
|
||||
intel_pasid_free_table(info->dev);
|
||||
}
|
||||
|
||||
spin_lock(&domain->lock);
|
||||
spin_lock_irqsave(&domain->lock, flags);
|
||||
list_del(&info->link);
|
||||
spin_unlock(&domain->lock);
|
||||
spin_unlock_irqrestore(&domain->lock, flags);
|
||||
|
||||
domain_detach_iommu(domain, iommu);
|
||||
info->domain = NULL;
|
||||
@@ -4412,19 +4396,20 @@ static void domain_set_force_snooping(struct dmar_domain *domain)
|
||||
static bool intel_iommu_enforce_cache_coherency(struct iommu_domain *domain)
|
||||
{
|
||||
struct dmar_domain *dmar_domain = to_dmar_domain(domain);
|
||||
unsigned long flags;
|
||||
|
||||
if (dmar_domain->force_snooping)
|
||||
return true;
|
||||
|
||||
spin_lock(&dmar_domain->lock);
|
||||
spin_lock_irqsave(&dmar_domain->lock, flags);
|
||||
if (!domain_support_force_snooping(dmar_domain)) {
|
||||
spin_unlock(&dmar_domain->lock);
|
||||
spin_unlock_irqrestore(&dmar_domain->lock, flags);
|
||||
return false;
|
||||
}
|
||||
|
||||
domain_set_force_snooping(dmar_domain);
|
||||
dmar_domain->force_snooping = true;
|
||||
spin_unlock(&dmar_domain->lock);
|
||||
spin_unlock_irqrestore(&dmar_domain->lock, flags);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -197,7 +197,6 @@
|
||||
#define ecap_dis(e) (((e) >> 27) & 0x1)
|
||||
#define ecap_nest(e) (((e) >> 26) & 0x1)
|
||||
#define ecap_mts(e) (((e) >> 25) & 0x1)
|
||||
#define ecap_ecs(e) (((e) >> 24) & 0x1)
|
||||
#define ecap_iotlb_offset(e) ((((e) >> 8) & 0x3ff) * 16)
|
||||
#define ecap_max_iotlb_offset(e) (ecap_iotlb_offset(e) + 16)
|
||||
#define ecap_coherent(e) ((e) & 0x1)
|
||||
@@ -265,7 +264,6 @@
|
||||
#define DMA_GSTS_CFIS (((u32)1) << 23)
|
||||
|
||||
/* DMA_RTADDR_REG */
|
||||
#define DMA_RTADDR_RTT (((u64)1) << 11)
|
||||
#define DMA_RTADDR_SMT (((u64)1) << 10)
|
||||
|
||||
/* CCMD_REG */
|
||||
@@ -579,6 +577,7 @@ struct intel_iommu {
|
||||
|
||||
#ifdef CONFIG_INTEL_IOMMU
|
||||
unsigned long *domain_ids; /* bitmap of domains */
|
||||
unsigned long *copied_tables; /* bitmap of copied tables */
|
||||
spinlock_t lock; /* protect context, domain ids */
|
||||
struct root_entry *root_entry; /* virtual address */
|
||||
|
||||
@@ -701,6 +700,11 @@ static inline int nr_pte_to_next_page(struct dma_pte *pte)
|
||||
(struct dma_pte *)ALIGN((unsigned long)pte, VTD_PAGE_SIZE) - pte;
|
||||
}
|
||||
|
||||
static inline bool context_present(struct context_entry *context)
|
||||
{
|
||||
return (context->lo & 1);
|
||||
}
|
||||
|
||||
extern struct dmar_drhd_unit * dmar_find_matched_drhd_unit(struct pci_dev *dev);
|
||||
|
||||
extern int dmar_enable_qi(struct intel_iommu *iommu);
|
||||
@@ -784,7 +788,6 @@ static inline void intel_iommu_debugfs_init(void) {}
|
||||
#endif /* CONFIG_INTEL_IOMMU_DEBUGFS */
|
||||
|
||||
extern const struct attribute_group *intel_iommu_groups[];
|
||||
bool context_present(struct context_entry *context);
|
||||
struct context_entry *iommu_context_addr(struct intel_iommu *iommu, u8 bus,
|
||||
u8 devfn, int alloc);
|
||||
|
||||
|
||||
+19
-2
@@ -3076,6 +3076,24 @@ out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static bool iommu_is_default_domain(struct iommu_group *group)
|
||||
{
|
||||
if (group->domain == group->default_domain)
|
||||
return true;
|
||||
|
||||
/*
|
||||
* If the default domain was set to identity and it is still an identity
|
||||
* domain then we consider this a pass. This happens because of
|
||||
* amd_iommu_init_device() replacing the default idenytity domain with an
|
||||
* identity domain that has a different configuration for AMDGPU.
|
||||
*/
|
||||
if (group->default_domain &&
|
||||
group->default_domain->type == IOMMU_DOMAIN_IDENTITY &&
|
||||
group->domain && group->domain->type == IOMMU_DOMAIN_IDENTITY)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* iommu_device_use_default_domain() - Device driver wants to handle device
|
||||
* DMA through the kernel DMA API.
|
||||
@@ -3094,8 +3112,7 @@ int iommu_device_use_default_domain(struct device *dev)
|
||||
|
||||
mutex_lock(&group->mutex);
|
||||
if (group->owner_cnt) {
|
||||
if (group->domain != group->default_domain ||
|
||||
group->owner) {
|
||||
if (group->owner || !iommu_is_default_domain(group)) {
|
||||
ret = -EBUSY;
|
||||
goto unlock_out;
|
||||
}
|
||||
|
||||
@@ -1006,7 +1006,18 @@ static int viommu_of_xlate(struct device *dev, struct of_phandle_args *args)
|
||||
return iommu_fwspec_add_ids(dev, args->args, 1);
|
||||
}
|
||||
|
||||
static bool viommu_capable(enum iommu_cap cap)
|
||||
{
|
||||
switch (cap) {
|
||||
case IOMMU_CAP_CACHE_COHERENCY:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static struct iommu_ops viommu_ops = {
|
||||
.capable = viommu_capable,
|
||||
.domain_alloc = viommu_domain_alloc,
|
||||
.probe_device = viommu_probe_device,
|
||||
.probe_finalize = viommu_probe_finalize,
|
||||
|
||||
@@ -494,6 +494,24 @@ static int max_uc_list_get_devlink_param(struct mlx5_core_dev *dev)
|
||||
return err;
|
||||
}
|
||||
|
||||
bool mlx5_is_roce_on(struct mlx5_core_dev *dev)
|
||||
{
|
||||
struct devlink *devlink = priv_to_devlink(dev);
|
||||
union devlink_param_value val;
|
||||
int err;
|
||||
|
||||
err = devlink_param_driverinit_value_get(devlink,
|
||||
DEVLINK_PARAM_GENERIC_ID_ENABLE_ROCE,
|
||||
&val);
|
||||
|
||||
if (!err)
|
||||
return val.vbool;
|
||||
|
||||
mlx5_core_dbg(dev, "Failed to get param. err = %d\n", err);
|
||||
return MLX5_CAP_GEN(dev, roce);
|
||||
}
|
||||
EXPORT_SYMBOL(mlx5_is_roce_on);
|
||||
|
||||
static int handle_hca_cap_2(struct mlx5_core_dev *dev, void *set_ctx)
|
||||
{
|
||||
void *set_hca_cap;
|
||||
@@ -597,7 +615,8 @@ static int handle_hca_cap(struct mlx5_core_dev *dev, void *set_ctx)
|
||||
MLX5_CAP_GEN_MAX(dev, num_total_dynamic_vf_msix));
|
||||
|
||||
if (MLX5_CAP_GEN(dev, roce_rw_supported))
|
||||
MLX5_SET(cmd_hca_cap, set_hca_cap, roce, mlx5_is_roce_init_enabled(dev));
|
||||
MLX5_SET(cmd_hca_cap, set_hca_cap, roce,
|
||||
mlx5_is_roce_on(dev));
|
||||
|
||||
max_uc_list = max_uc_list_get_devlink_param(dev);
|
||||
if (max_uc_list > 0)
|
||||
@@ -623,7 +642,7 @@ static int handle_hca_cap(struct mlx5_core_dev *dev, void *set_ctx)
|
||||
*/
|
||||
static bool is_roce_fw_disabled(struct mlx5_core_dev *dev)
|
||||
{
|
||||
return (MLX5_CAP_GEN(dev, roce_rw_supported) && !mlx5_is_roce_init_enabled(dev)) ||
|
||||
return (MLX5_CAP_GEN(dev, roce_rw_supported) && !mlx5_is_roce_on(dev)) ||
|
||||
(!MLX5_CAP_GEN(dev, roce_rw_supported) && !MLX5_CAP_GEN(dev, roce));
|
||||
}
|
||||
|
||||
|
||||
@@ -4703,6 +4703,8 @@ static void nvme_fw_act_work(struct work_struct *work)
|
||||
nvme_start_queues(ctrl);
|
||||
/* read FW slot information to clear the AER */
|
||||
nvme_get_fw_slot_info(ctrl);
|
||||
|
||||
queue_work(nvme_wq, &ctrl->async_event_work);
|
||||
}
|
||||
|
||||
static u32 nvme_aer_type(u32 result)
|
||||
@@ -4715,9 +4717,10 @@ static u32 nvme_aer_subtype(u32 result)
|
||||
return (result & 0xff00) >> 8;
|
||||
}
|
||||
|
||||
static void nvme_handle_aen_notice(struct nvme_ctrl *ctrl, u32 result)
|
||||
static bool nvme_handle_aen_notice(struct nvme_ctrl *ctrl, u32 result)
|
||||
{
|
||||
u32 aer_notice_type = nvme_aer_subtype(result);
|
||||
bool requeue = true;
|
||||
|
||||
trace_nvme_async_event(ctrl, aer_notice_type);
|
||||
|
||||
@@ -4734,6 +4737,7 @@ static void nvme_handle_aen_notice(struct nvme_ctrl *ctrl, u32 result)
|
||||
*/
|
||||
if (nvme_change_ctrl_state(ctrl, NVME_CTRL_RESETTING)) {
|
||||
nvme_auth_stop(ctrl);
|
||||
requeue = false;
|
||||
queue_work(nvme_wq, &ctrl->fw_act_work);
|
||||
}
|
||||
break;
|
||||
@@ -4750,6 +4754,7 @@ static void nvme_handle_aen_notice(struct nvme_ctrl *ctrl, u32 result)
|
||||
default:
|
||||
dev_warn(ctrl->device, "async event result %08x\n", result);
|
||||
}
|
||||
return requeue;
|
||||
}
|
||||
|
||||
static void nvme_handle_aer_persistent_error(struct nvme_ctrl *ctrl)
|
||||
@@ -4765,13 +4770,14 @@ void nvme_complete_async_event(struct nvme_ctrl *ctrl, __le16 status,
|
||||
u32 result = le32_to_cpu(res->u32);
|
||||
u32 aer_type = nvme_aer_type(result);
|
||||
u32 aer_subtype = nvme_aer_subtype(result);
|
||||
bool requeue = true;
|
||||
|
||||
if (le16_to_cpu(status) >> 1 != NVME_SC_SUCCESS)
|
||||
return;
|
||||
|
||||
switch (aer_type) {
|
||||
case NVME_AER_NOTICE:
|
||||
nvme_handle_aen_notice(ctrl, result);
|
||||
requeue = nvme_handle_aen_notice(ctrl, result);
|
||||
break;
|
||||
case NVME_AER_ERROR:
|
||||
/*
|
||||
@@ -4792,7 +4798,9 @@ void nvme_complete_async_event(struct nvme_ctrl *ctrl, __le16 status,
|
||||
default:
|
||||
break;
|
||||
}
|
||||
queue_work(nvme_wq, &ctrl->async_event_work);
|
||||
|
||||
if (requeue)
|
||||
queue_work(nvme_wq, &ctrl->async_event_work);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(nvme_complete_async_event);
|
||||
|
||||
|
||||
@@ -121,7 +121,6 @@ struct nvme_tcp_queue {
|
||||
struct mutex send_mutex;
|
||||
struct llist_head req_list;
|
||||
struct list_head send_list;
|
||||
bool more_requests;
|
||||
|
||||
/* recv state */
|
||||
void *pdu;
|
||||
@@ -320,7 +319,7 @@ static inline void nvme_tcp_send_all(struct nvme_tcp_queue *queue)
|
||||
static inline bool nvme_tcp_queue_more(struct nvme_tcp_queue *queue)
|
||||
{
|
||||
return !list_empty(&queue->send_list) ||
|
||||
!llist_empty(&queue->req_list) || queue->more_requests;
|
||||
!llist_empty(&queue->req_list);
|
||||
}
|
||||
|
||||
static inline void nvme_tcp_queue_request(struct nvme_tcp_request *req,
|
||||
@@ -339,9 +338,7 @@ static inline void nvme_tcp_queue_request(struct nvme_tcp_request *req,
|
||||
*/
|
||||
if (queue->io_cpu == raw_smp_processor_id() &&
|
||||
sync && empty && mutex_trylock(&queue->send_mutex)) {
|
||||
queue->more_requests = !last;
|
||||
nvme_tcp_send_all(queue);
|
||||
queue->more_requests = false;
|
||||
mutex_unlock(&queue->send_mutex);
|
||||
}
|
||||
|
||||
@@ -1229,7 +1226,7 @@ static void nvme_tcp_io_work(struct work_struct *w)
|
||||
else if (unlikely(result < 0))
|
||||
return;
|
||||
|
||||
if (!pending)
|
||||
if (!pending || !queue->rd_enabled)
|
||||
return;
|
||||
|
||||
} while (!time_after(jiffies, deadline)); /* quota is exhausted */
|
||||
|
||||
@@ -735,6 +735,8 @@ static void nvmet_set_error(struct nvmet_req *req, u16 status)
|
||||
|
||||
static void __nvmet_req_complete(struct nvmet_req *req, u16 status)
|
||||
{
|
||||
struct nvmet_ns *ns = req->ns;
|
||||
|
||||
if (!req->sq->sqhd_disabled)
|
||||
nvmet_update_sq_head(req);
|
||||
req->cqe->sq_id = cpu_to_le16(req->sq->qid);
|
||||
@@ -745,9 +747,9 @@ static void __nvmet_req_complete(struct nvmet_req *req, u16 status)
|
||||
|
||||
trace_nvmet_req_complete(req);
|
||||
|
||||
if (req->ns)
|
||||
nvmet_put_namespace(req->ns);
|
||||
req->ops->queue_response(req);
|
||||
if (ns)
|
||||
nvmet_put_namespace(ns);
|
||||
}
|
||||
|
||||
void nvmet_req_complete(struct nvmet_req *req, u16 status)
|
||||
|
||||
@@ -100,6 +100,7 @@ void nvmet_execute_identify_cns_cs_ns(struct nvmet_req *req)
|
||||
struct nvme_id_ns_zns *id_zns;
|
||||
u64 zsze;
|
||||
u16 status;
|
||||
u32 mar, mor;
|
||||
|
||||
if (le32_to_cpu(req->cmd->identify.nsid) == NVME_NSID_ALL) {
|
||||
req->error_loc = offsetof(struct nvme_identify, nsid);
|
||||
@@ -130,8 +131,20 @@ void nvmet_execute_identify_cns_cs_ns(struct nvmet_req *req)
|
||||
zsze = (bdev_zone_sectors(req->ns->bdev) << 9) >>
|
||||
req->ns->blksize_shift;
|
||||
id_zns->lbafe[0].zsze = cpu_to_le64(zsze);
|
||||
id_zns->mor = cpu_to_le32(bdev_max_open_zones(req->ns->bdev));
|
||||
id_zns->mar = cpu_to_le32(bdev_max_active_zones(req->ns->bdev));
|
||||
|
||||
mor = bdev_max_open_zones(req->ns->bdev);
|
||||
if (!mor)
|
||||
mor = U32_MAX;
|
||||
else
|
||||
mor--;
|
||||
id_zns->mor = cpu_to_le32(mor);
|
||||
|
||||
mar = bdev_max_active_zones(req->ns->bdev);
|
||||
if (!mar)
|
||||
mar = U32_MAX;
|
||||
else
|
||||
mar--;
|
||||
id_zns->mar = cpu_to_le32(mar);
|
||||
|
||||
done:
|
||||
status = nvmet_copy_to_sgl(req, 0, id_zns, sizeof(*id_zns));
|
||||
|
||||
@@ -473,7 +473,7 @@ static int pmu_sbi_get_ctrinfo(int nctr)
|
||||
if (!pmu_ctr_list)
|
||||
return -ENOMEM;
|
||||
|
||||
for (i = 0; i <= nctr; i++) {
|
||||
for (i = 0; i < nctr; i++) {
|
||||
ret = sbi_ecall(SBI_EXT_PMU, SBI_EXT_PMU_COUNTER_GET_INFO, i, 0, 0, 0, 0, 0);
|
||||
if (ret.error)
|
||||
/* The logical counter ids are not expected to be contiguous */
|
||||
|
||||
+15
-13
@@ -182,6 +182,15 @@ void scsi_remove_host(struct Scsi_Host *shost)
|
||||
mutex_unlock(&shost->scan_mutex);
|
||||
scsi_proc_host_rm(shost);
|
||||
|
||||
/*
|
||||
* New SCSI devices cannot be attached anymore because of the SCSI host
|
||||
* state so drop the tag set refcnt. Wait until the tag set refcnt drops
|
||||
* to zero because .exit_cmd_priv implementations may need the host
|
||||
* pointer.
|
||||
*/
|
||||
kref_put(&shost->tagset_refcnt, scsi_mq_free_tags);
|
||||
wait_for_completion(&shost->tagset_freed);
|
||||
|
||||
spin_lock_irqsave(shost->host_lock, flags);
|
||||
if (scsi_host_set_state(shost, SHOST_DEL))
|
||||
BUG_ON(scsi_host_set_state(shost, SHOST_DEL_RECOVERY));
|
||||
@@ -190,15 +199,6 @@ void scsi_remove_host(struct Scsi_Host *shost)
|
||||
transport_unregister_device(&shost->shost_gendev);
|
||||
device_unregister(&shost->shost_dev);
|
||||
device_del(&shost->shost_gendev);
|
||||
|
||||
/*
|
||||
* After scsi_remove_host() has returned the scsi LLD module can be
|
||||
* unloaded and/or the host resources can be released. Hence wait until
|
||||
* the dependent SCSI targets and devices are gone before returning.
|
||||
*/
|
||||
wait_event(shost->targets_wq, atomic_read(&shost->target_count) == 0);
|
||||
|
||||
scsi_mq_destroy_tags(shost);
|
||||
}
|
||||
EXPORT_SYMBOL(scsi_remove_host);
|
||||
|
||||
@@ -254,6 +254,9 @@ int scsi_add_host_with_dma(struct Scsi_Host *shost, struct device *dev,
|
||||
if (error)
|
||||
goto fail;
|
||||
|
||||
kref_init(&shost->tagset_refcnt);
|
||||
init_completion(&shost->tagset_freed);
|
||||
|
||||
/*
|
||||
* Increase usage count temporarily here so that calling
|
||||
* scsi_autopm_put_host() will trigger runtime idle if there is
|
||||
@@ -309,8 +312,8 @@ int scsi_add_host_with_dma(struct Scsi_Host *shost, struct device *dev,
|
||||
return error;
|
||||
|
||||
/*
|
||||
* Any resources associated with the SCSI host in this function except
|
||||
* the tag set will be freed by scsi_host_dev_release().
|
||||
* Any host allocation in this function will be freed in
|
||||
* scsi_host_dev_release().
|
||||
*/
|
||||
out_del_dev:
|
||||
device_del(&shost->shost_dev);
|
||||
@@ -326,7 +329,7 @@ int scsi_add_host_with_dma(struct Scsi_Host *shost, struct device *dev,
|
||||
pm_runtime_disable(&shost->shost_gendev);
|
||||
pm_runtime_set_suspended(&shost->shost_gendev);
|
||||
pm_runtime_put_noidle(&shost->shost_gendev);
|
||||
scsi_mq_destroy_tags(shost);
|
||||
kref_put(&shost->tagset_refcnt, scsi_mq_free_tags);
|
||||
fail:
|
||||
return error;
|
||||
}
|
||||
@@ -406,7 +409,6 @@ struct Scsi_Host *scsi_host_alloc(struct scsi_host_template *sht, int privsize)
|
||||
INIT_LIST_HEAD(&shost->starved_list);
|
||||
init_waitqueue_head(&shost->host_wait);
|
||||
mutex_init(&shost->scan_mutex);
|
||||
init_waitqueue_head(&shost->targets_wq);
|
||||
|
||||
index = ida_alloc(&host_index_ida, GFP_KERNEL);
|
||||
if (index < 0) {
|
||||
|
||||
@@ -8053,7 +8053,7 @@ lpfc_sli4_driver_resource_setup(struct lpfc_hba *phba)
|
||||
/* Allocate device driver memory */
|
||||
rc = lpfc_mem_alloc(phba, SGL_ALIGN_SZ);
|
||||
if (rc)
|
||||
return -ENOMEM;
|
||||
goto out_destroy_workqueue;
|
||||
|
||||
/* IF Type 2 ports get initialized now. */
|
||||
if (bf_get(lpfc_sli_intf_if_type, &phba->sli4_hba.sli_intf) >=
|
||||
@@ -8481,6 +8481,9 @@ out_free_bsmbx:
|
||||
lpfc_destroy_bootstrap_mbox(phba);
|
||||
out_free_mem:
|
||||
lpfc_mem_free(phba);
|
||||
out_destroy_workqueue:
|
||||
destroy_workqueue(phba->wq);
|
||||
phba->wq = NULL;
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
@@ -4272,7 +4272,7 @@ lpfc_fcp_io_cmd_wqe_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pwqeIn,
|
||||
lpfc_cmd->result == IOERR_ABORT_REQUESTED ||
|
||||
lpfc_cmd->result == IOERR_RPI_SUSPENDED ||
|
||||
lpfc_cmd->result == IOERR_SLER_CMD_RCV_FAILURE) {
|
||||
cmd->result = DID_REQUEUE << 16;
|
||||
cmd->result = DID_TRANSPORT_DISRUPTED << 16;
|
||||
break;
|
||||
}
|
||||
if ((lpfc_cmd->result == IOERR_RX_DMA_FAILED ||
|
||||
@@ -4562,7 +4562,7 @@ lpfc_scsi_cmd_iocb_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pIocbIn,
|
||||
lpfc_cmd->result == IOERR_NO_RESOURCES ||
|
||||
lpfc_cmd->result == IOERR_ABORT_REQUESTED ||
|
||||
lpfc_cmd->result == IOERR_SLER_CMD_RCV_FAILURE) {
|
||||
cmd->result = DID_REQUEUE << 16;
|
||||
cmd->result = DID_TRANSPORT_DISRUPTED << 16;
|
||||
break;
|
||||
}
|
||||
if ((lpfc_cmd->result == IOERR_RX_DMA_FAILED ||
|
||||
|
||||
@@ -3670,6 +3670,7 @@ static struct fw_event_work *dequeue_next_fw_event(struct MPT3SAS_ADAPTER *ioc)
|
||||
fw_event = list_first_entry(&ioc->fw_event_list,
|
||||
struct fw_event_work, list);
|
||||
list_del_init(&fw_event->list);
|
||||
fw_event_work_put(fw_event);
|
||||
}
|
||||
spin_unlock_irqrestore(&ioc->fw_event_lock, flags);
|
||||
|
||||
@@ -3751,7 +3752,6 @@ _scsih_fw_event_cleanup_queue(struct MPT3SAS_ADAPTER *ioc)
|
||||
if (cancel_work_sync(&fw_event->work))
|
||||
fw_event_work_put(fw_event);
|
||||
|
||||
fw_event_work_put(fw_event);
|
||||
}
|
||||
ioc->fw_events_cleanup = 0;
|
||||
}
|
||||
|
||||
+3
-6
@@ -586,13 +586,10 @@ EXPORT_SYMBOL(scsi_device_get);
|
||||
*/
|
||||
void scsi_device_put(struct scsi_device *sdev)
|
||||
{
|
||||
/*
|
||||
* Decreasing the module reference count before the device reference
|
||||
* count is safe since scsi_remove_host() only returns after all
|
||||
* devices have been removed.
|
||||
*/
|
||||
module_put(sdev->host->hostt->module);
|
||||
struct module *mod = sdev->host->hostt->module;
|
||||
|
||||
put_device(&sdev->sdev_gendev);
|
||||
module_put(mod);
|
||||
}
|
||||
EXPORT_SYMBOL(scsi_device_put);
|
||||
|
||||
|
||||
@@ -1983,9 +1983,13 @@ int scsi_mq_setup_tags(struct Scsi_Host *shost)
|
||||
return blk_mq_alloc_tag_set(tag_set);
|
||||
}
|
||||
|
||||
void scsi_mq_destroy_tags(struct Scsi_Host *shost)
|
||||
void scsi_mq_free_tags(struct kref *kref)
|
||||
{
|
||||
struct Scsi_Host *shost = container_of(kref, typeof(*shost),
|
||||
tagset_refcnt);
|
||||
|
||||
blk_mq_free_tag_set(&shost->tag_set);
|
||||
complete(&shost->tagset_freed);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -94,7 +94,7 @@ extern void scsi_run_host_queues(struct Scsi_Host *shost);
|
||||
extern void scsi_requeue_run_queue(struct work_struct *work);
|
||||
extern void scsi_start_queue(struct scsi_device *sdev);
|
||||
extern int scsi_mq_setup_tags(struct Scsi_Host *shost);
|
||||
extern void scsi_mq_destroy_tags(struct Scsi_Host *shost);
|
||||
extern void scsi_mq_free_tags(struct kref *kref);
|
||||
extern void scsi_exit_queue(void);
|
||||
extern void scsi_evt_thread(struct work_struct *work);
|
||||
|
||||
|
||||
@@ -340,6 +340,7 @@ static struct scsi_device *scsi_alloc_sdev(struct scsi_target *starget,
|
||||
kfree(sdev);
|
||||
goto out;
|
||||
}
|
||||
kref_get(&sdev->host->tagset_refcnt);
|
||||
sdev->request_queue = q;
|
||||
q->queuedata = sdev;
|
||||
__scsi_init_queue(sdev->host, q);
|
||||
@@ -406,14 +407,9 @@ static void scsi_target_destroy(struct scsi_target *starget)
|
||||
static void scsi_target_dev_release(struct device *dev)
|
||||
{
|
||||
struct device *parent = dev->parent;
|
||||
struct Scsi_Host *shost = dev_to_shost(parent);
|
||||
struct scsi_target *starget = to_scsi_target(dev);
|
||||
|
||||
kfree(starget);
|
||||
|
||||
if (atomic_dec_return(&shost->target_count) == 0)
|
||||
wake_up(&shost->targets_wq);
|
||||
|
||||
put_device(parent);
|
||||
}
|
||||
|
||||
@@ -526,10 +522,6 @@ static struct scsi_target *scsi_alloc_target(struct device *parent,
|
||||
starget->state = STARGET_CREATED;
|
||||
starget->scsi_level = SCSI_2;
|
||||
starget->max_target_blocked = SCSI_DEFAULT_TARGET_BLOCKED;
|
||||
init_waitqueue_head(&starget->sdev_wq);
|
||||
|
||||
atomic_inc(&shost->target_count);
|
||||
|
||||
retry:
|
||||
spin_lock_irqsave(shost->host_lock, flags);
|
||||
|
||||
|
||||
+13
-17
@@ -443,15 +443,18 @@ static void scsi_device_cls_release(struct device *class_dev)
|
||||
|
||||
static void scsi_device_dev_release_usercontext(struct work_struct *work)
|
||||
{
|
||||
struct scsi_device *sdev = container_of(work, struct scsi_device,
|
||||
ew.work);
|
||||
struct scsi_target *starget = sdev->sdev_target;
|
||||
struct scsi_device *sdev;
|
||||
struct device *parent;
|
||||
struct list_head *this, *tmp;
|
||||
struct scsi_vpd *vpd_pg80 = NULL, *vpd_pg83 = NULL;
|
||||
struct scsi_vpd *vpd_pg0 = NULL, *vpd_pg89 = NULL;
|
||||
struct scsi_vpd *vpd_pgb0 = NULL, *vpd_pgb1 = NULL, *vpd_pgb2 = NULL;
|
||||
unsigned long flags;
|
||||
struct module *mod;
|
||||
|
||||
sdev = container_of(work, struct scsi_device, ew.work);
|
||||
|
||||
mod = sdev->host->hostt->module;
|
||||
|
||||
scsi_dh_release_device(sdev);
|
||||
|
||||
@@ -513,16 +516,19 @@ static void scsi_device_dev_release_usercontext(struct work_struct *work)
|
||||
kfree(sdev->inquiry);
|
||||
kfree(sdev);
|
||||
|
||||
if (starget && atomic_dec_return(&starget->sdev_count) == 0)
|
||||
wake_up(&starget->sdev_wq);
|
||||
|
||||
if (parent)
|
||||
put_device(parent);
|
||||
module_put(mod);
|
||||
}
|
||||
|
||||
static void scsi_device_dev_release(struct device *dev)
|
||||
{
|
||||
struct scsi_device *sdp = to_scsi_device(dev);
|
||||
|
||||
/* Set module pointer as NULL in case of module unloading */
|
||||
if (!try_module_get(sdp->host->hostt->module))
|
||||
sdp->host->hostt->module = NULL;
|
||||
|
||||
execute_in_process_context(scsi_device_dev_release_usercontext,
|
||||
&sdp->ew);
|
||||
}
|
||||
@@ -1470,6 +1476,7 @@ void __scsi_remove_device(struct scsi_device *sdev)
|
||||
mutex_unlock(&sdev->state_mutex);
|
||||
|
||||
blk_mq_destroy_queue(sdev->request_queue);
|
||||
kref_put(&sdev->host->tagset_refcnt, scsi_mq_free_tags);
|
||||
cancel_work_sync(&sdev->requeue_work);
|
||||
|
||||
if (sdev->host->hostt->slave_destroy)
|
||||
@@ -1529,14 +1536,6 @@ static void __scsi_remove_target(struct scsi_target *starget)
|
||||
goto restart;
|
||||
}
|
||||
spin_unlock_irqrestore(shost->host_lock, flags);
|
||||
|
||||
/*
|
||||
* After scsi_remove_target() returns its caller can remove resources
|
||||
* associated with @starget, e.g. an rport or session. Wait until all
|
||||
* devices associated with @starget have been removed to prevent that
|
||||
* a SCSI error handling callback function triggers a use-after-free.
|
||||
*/
|
||||
wait_event(starget->sdev_wq, atomic_read(&starget->sdev_count) == 0);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1647,9 +1646,6 @@ void scsi_sysfs_device_initialize(struct scsi_device *sdev)
|
||||
list_add_tail(&sdev->same_target_siblings, &starget->devices);
|
||||
list_add_tail(&sdev->siblings, &shost->__devices);
|
||||
spin_unlock_irqrestore(shost->host_lock, flags);
|
||||
|
||||
atomic_inc(&starget->sdev_count);
|
||||
|
||||
/*
|
||||
* device can now only be removed via __scsi_remove_device() so hold
|
||||
* the target. Target will be held in CREATED state until something
|
||||
|
||||
@@ -29,8 +29,7 @@ config USB4_DEBUGFS_WRITE
|
||||
|
||||
config USB4_KUNIT_TEST
|
||||
bool "KUnit tests" if !KUNIT_ALL_TESTS
|
||||
depends on (USB4=m || KUNIT=y)
|
||||
depends on KUNIT
|
||||
depends on USB4 && KUNIT=y
|
||||
default KUNIT_ALL_TESTS
|
||||
|
||||
config USB4_DMA_TEST
|
||||
|
||||
@@ -558,6 +558,18 @@ static int vaddr_get_pfns(struct mm_struct *mm, unsigned long vaddr,
|
||||
ret = pin_user_pages_remote(mm, vaddr, npages, flags | FOLL_LONGTERM,
|
||||
pages, NULL, NULL);
|
||||
if (ret > 0) {
|
||||
int i;
|
||||
|
||||
/*
|
||||
* The zero page is always resident, we don't need to pin it
|
||||
* and it falls into our invalid/reserved test so we don't
|
||||
* unpin in put_pfn(). Unpin all zero pages in the batch here.
|
||||
*/
|
||||
for (i = 0 ; i < ret; i++) {
|
||||
if (unlikely(is_zero_pfn(page_to_pfn(pages[i]))))
|
||||
unpin_user_page(pages[i]);
|
||||
}
|
||||
|
||||
*pfn = page_to_pfn(pages[0]);
|
||||
goto done;
|
||||
}
|
||||
|
||||
@@ -17,7 +17,7 @@ config NITRO_ENCLAVES
|
||||
|
||||
config NITRO_ENCLAVES_MISC_DEV_TEST
|
||||
bool "Tests for the misc device functionality of the Nitro Enclaves" if !KUNIT_ALL_TESTS
|
||||
depends on NITRO_ENCLAVES && KUNIT
|
||||
depends on NITRO_ENCLAVES && KUNIT=y
|
||||
default KUNIT_ALL_TESTS
|
||||
help
|
||||
Enable KUnit tests for the misc device functionality of the Nitro
|
||||
|
||||
@@ -1088,8 +1088,6 @@ struct btrfs_fs_info {
|
||||
|
||||
spinlock_t zone_active_bgs_lock;
|
||||
struct list_head zone_active_bgs;
|
||||
/* Waiters when BTRFS_FS_NEED_ZONE_FINISH is set */
|
||||
wait_queue_head_t zone_finish_wait;
|
||||
|
||||
/* Updates are not protected by any lock */
|
||||
struct btrfs_commit_stats commit_stats;
|
||||
|
||||
@@ -3068,7 +3068,6 @@ void btrfs_init_fs_info(struct btrfs_fs_info *fs_info)
|
||||
init_waitqueue_head(&fs_info->transaction_blocked_wait);
|
||||
init_waitqueue_head(&fs_info->async_submit_wait);
|
||||
init_waitqueue_head(&fs_info->delayed_iputs_wait);
|
||||
init_waitqueue_head(&fs_info->zone_finish_wait);
|
||||
|
||||
/* Usable values until the real ones are cached from the superblock */
|
||||
fs_info->nodesize = 4096;
|
||||
|
||||
+3
-4
@@ -1644,10 +1644,9 @@ static noinline int run_delalloc_zoned(struct btrfs_inode *inode,
|
||||
done_offset = end;
|
||||
|
||||
if (done_offset == start) {
|
||||
struct btrfs_fs_info *info = inode->root->fs_info;
|
||||
|
||||
wait_var_event(&info->zone_finish_wait,
|
||||
!test_bit(BTRFS_FS_NEED_ZONE_FINISH, &info->flags));
|
||||
wait_on_bit_io(&inode->root->fs_info->flags,
|
||||
BTRFS_FS_NEED_ZONE_FINISH,
|
||||
TASK_UNINTERRUPTIBLE);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
@@ -199,7 +199,7 @@ static u64 calc_chunk_size(const struct btrfs_fs_info *fs_info, u64 flags)
|
||||
ASSERT(flags & BTRFS_BLOCK_GROUP_TYPE_MASK);
|
||||
|
||||
if (flags & BTRFS_BLOCK_GROUP_DATA)
|
||||
return SZ_1G;
|
||||
return BTRFS_MAX_DATA_CHUNK_SIZE;
|
||||
else if (flags & BTRFS_BLOCK_GROUP_SYSTEM)
|
||||
return SZ_32M;
|
||||
|
||||
|
||||
@@ -5267,6 +5267,9 @@ static int decide_stripe_size_regular(struct alloc_chunk_ctl *ctl,
|
||||
ctl->stripe_size);
|
||||
}
|
||||
|
||||
/* Stripe size should not go beyond 1G. */
|
||||
ctl->stripe_size = min_t(u64, ctl->stripe_size, SZ_1G);
|
||||
|
||||
/* Align to BTRFS_STRIPE_LEN */
|
||||
ctl->stripe_size = round_down(ctl->stripe_size, BTRFS_STRIPE_LEN);
|
||||
ctl->chunk_size = ctl->stripe_size * data_stripes;
|
||||
|
||||
+53
-46
@@ -421,10 +421,19 @@ int btrfs_get_dev_zone_info(struct btrfs_device *device, bool populate_cache)
|
||||
* since btrfs adds the pages one by one to a bio, and btrfs cannot
|
||||
* increase the metadata reservation even if it increases the number of
|
||||
* extents, it is safe to stick with the limit.
|
||||
*
|
||||
* With the zoned emulation, we can have non-zoned device on the zoned
|
||||
* mode. In this case, we don't have a valid max zone append size. So,
|
||||
* use max_segments * PAGE_SIZE as the pseudo max_zone_append_size.
|
||||
*/
|
||||
zone_info->max_zone_append_size =
|
||||
min_t(u64, (u64)bdev_max_zone_append_sectors(bdev) << SECTOR_SHIFT,
|
||||
(u64)bdev_max_segments(bdev) << PAGE_SHIFT);
|
||||
if (bdev_is_zoned(bdev)) {
|
||||
zone_info->max_zone_append_size = min_t(u64,
|
||||
(u64)bdev_max_zone_append_sectors(bdev) << SECTOR_SHIFT,
|
||||
(u64)bdev_max_segments(bdev) << PAGE_SHIFT);
|
||||
} else {
|
||||
zone_info->max_zone_append_size =
|
||||
(u64)bdev_max_segments(bdev) << PAGE_SHIFT;
|
||||
}
|
||||
if (!IS_ALIGNED(nr_sectors, zone_sectors))
|
||||
zone_info->nr_zones++;
|
||||
|
||||
@@ -1178,7 +1187,7 @@ int btrfs_ensure_empty_zones(struct btrfs_device *device, u64 start, u64 size)
|
||||
* offset.
|
||||
*/
|
||||
static int calculate_alloc_pointer(struct btrfs_block_group *cache,
|
||||
u64 *offset_ret)
|
||||
u64 *offset_ret, bool new)
|
||||
{
|
||||
struct btrfs_fs_info *fs_info = cache->fs_info;
|
||||
struct btrfs_root *root;
|
||||
@@ -1188,6 +1197,21 @@ static int calculate_alloc_pointer(struct btrfs_block_group *cache,
|
||||
int ret;
|
||||
u64 length;
|
||||
|
||||
/*
|
||||
* Avoid tree lookups for a new block group, there's no use for it.
|
||||
* It must always be 0.
|
||||
*
|
||||
* Also, we have a lock chain of extent buffer lock -> chunk mutex.
|
||||
* For new a block group, this function is called from
|
||||
* btrfs_make_block_group() which is already taking the chunk mutex.
|
||||
* Thus, we cannot call calculate_alloc_pointer() which takes extent
|
||||
* buffer locks to avoid deadlock.
|
||||
*/
|
||||
if (new) {
|
||||
*offset_ret = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
path = btrfs_alloc_path();
|
||||
if (!path)
|
||||
return -ENOMEM;
|
||||
@@ -1323,6 +1347,13 @@ int btrfs_load_block_group_zone_info(struct btrfs_block_group *cache, bool new)
|
||||
else
|
||||
num_conventional++;
|
||||
|
||||
/*
|
||||
* Consider a zone as active if we can allow any number of
|
||||
* active zones.
|
||||
*/
|
||||
if (!device->zone_info->max_active_zones)
|
||||
__set_bit(i, active);
|
||||
|
||||
if (!is_sequential) {
|
||||
alloc_offsets[i] = WP_CONVENTIONAL;
|
||||
continue;
|
||||
@@ -1389,45 +1420,23 @@ int btrfs_load_block_group_zone_info(struct btrfs_block_group *cache, bool new)
|
||||
__set_bit(i, active);
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* Consider a zone as active if we can allow any number of
|
||||
* active zones.
|
||||
*/
|
||||
if (!device->zone_info->max_active_zones)
|
||||
__set_bit(i, active);
|
||||
}
|
||||
|
||||
if (num_sequential > 0)
|
||||
cache->seq_zone = true;
|
||||
|
||||
if (num_conventional > 0) {
|
||||
/*
|
||||
* Avoid calling calculate_alloc_pointer() for new BG. It
|
||||
* is no use for new BG. It must be always 0.
|
||||
*
|
||||
* Also, we have a lock chain of extent buffer lock ->
|
||||
* chunk mutex. For new BG, this function is called from
|
||||
* btrfs_make_block_group() which is already taking the
|
||||
* chunk mutex. Thus, we cannot call
|
||||
* calculate_alloc_pointer() which takes extent buffer
|
||||
* locks to avoid deadlock.
|
||||
*/
|
||||
|
||||
/* Zone capacity is always zone size in emulation */
|
||||
cache->zone_capacity = cache->length;
|
||||
if (new) {
|
||||
cache->alloc_offset = 0;
|
||||
goto out;
|
||||
}
|
||||
ret = calculate_alloc_pointer(cache, &last_alloc);
|
||||
if (ret || map->num_stripes == num_conventional) {
|
||||
if (!ret)
|
||||
cache->alloc_offset = last_alloc;
|
||||
else
|
||||
btrfs_err(fs_info,
|
||||
ret = calculate_alloc_pointer(cache, &last_alloc, new);
|
||||
if (ret) {
|
||||
btrfs_err(fs_info,
|
||||
"zoned: failed to determine allocation offset of bg %llu",
|
||||
cache->start);
|
||||
cache->start);
|
||||
goto out;
|
||||
} else if (map->num_stripes == num_conventional) {
|
||||
cache->alloc_offset = last_alloc;
|
||||
cache->zone_is_active = 1;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
@@ -1495,13 +1504,6 @@ int btrfs_load_block_group_zone_info(struct btrfs_block_group *cache, bool new)
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (cache->zone_is_active) {
|
||||
btrfs_get_block_group(cache);
|
||||
spin_lock(&fs_info->zone_active_bgs_lock);
|
||||
list_add_tail(&cache->active_bg_list, &fs_info->zone_active_bgs);
|
||||
spin_unlock(&fs_info->zone_active_bgs_lock);
|
||||
}
|
||||
|
||||
out:
|
||||
if (cache->alloc_offset > fs_info->zone_size) {
|
||||
btrfs_err(fs_info,
|
||||
@@ -1526,10 +1528,16 @@ out:
|
||||
ret = -EIO;
|
||||
}
|
||||
|
||||
if (!ret)
|
||||
if (!ret) {
|
||||
cache->meta_write_pointer = cache->alloc_offset + cache->start;
|
||||
|
||||
if (ret) {
|
||||
if (cache->zone_is_active) {
|
||||
btrfs_get_block_group(cache);
|
||||
spin_lock(&fs_info->zone_active_bgs_lock);
|
||||
list_add_tail(&cache->active_bg_list,
|
||||
&fs_info->zone_active_bgs);
|
||||
spin_unlock(&fs_info->zone_active_bgs_lock);
|
||||
}
|
||||
} else {
|
||||
kfree(cache->physical_map);
|
||||
cache->physical_map = NULL;
|
||||
}
|
||||
@@ -2007,8 +2015,7 @@ static int do_zone_finish(struct btrfs_block_group *block_group, bool fully_writ
|
||||
/* For active_bg_list */
|
||||
btrfs_put_block_group(block_group);
|
||||
|
||||
clear_bit(BTRFS_FS_NEED_ZONE_FINISH, &fs_info->flags);
|
||||
wake_up_all(&fs_info->zone_finish_wait);
|
||||
clear_and_wake_up_bit(BTRFS_FS_NEED_ZONE_FINISH, &fs_info->flags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user