mirror of
https://github.com/torvalds/linux.git
synced 2026-08-01 20:22:08 +02:00
Merge branch 'master' into mm-stable
This commit is contained in:
commit
7191930894
|
|
@ -205,7 +205,7 @@ Description: Controls the idle timing of system, if there is no FS operation
|
|||
What: /sys/fs/f2fs/<disk>/discard_idle_interval
|
||||
Date: September 2018
|
||||
Contact: "Chao Yu" <yuchao0@huawei.com>
|
||||
Contact: "Sahitya Tummala" <stummala@codeaurora.org>
|
||||
Contact: "Sahitya Tummala" <quic_stummala@quicinc.com>
|
||||
Description: Controls the idle timing of discard thread given
|
||||
this time interval.
|
||||
Default is 5 secs.
|
||||
|
|
@ -213,7 +213,7 @@ Description: Controls the idle timing of discard thread given
|
|||
What: /sys/fs/f2fs/<disk>/gc_idle_interval
|
||||
Date: September 2018
|
||||
Contact: "Chao Yu" <yuchao0@huawei.com>
|
||||
Contact: "Sahitya Tummala" <stummala@codeaurora.org>
|
||||
Contact: "Sahitya Tummala" <quic_stummala@quicinc.com>
|
||||
Description: Controls the idle timing for gc path. Set to 5 seconds by default.
|
||||
|
||||
What: /sys/fs/f2fs/<disk>/iostat_enable
|
||||
|
|
@ -701,29 +701,31 @@ Description: Support configuring fault injection type, should be
|
|||
enabled with fault_injection option, fault type value
|
||||
is shown below, it supports single or combined type.
|
||||
|
||||
=================== ===========
|
||||
Type_Name Type_Value
|
||||
=================== ===========
|
||||
FAULT_KMALLOC 0x000000001
|
||||
FAULT_KVMALLOC 0x000000002
|
||||
FAULT_PAGE_ALLOC 0x000000004
|
||||
FAULT_PAGE_GET 0x000000008
|
||||
FAULT_ALLOC_BIO 0x000000010 (obsolete)
|
||||
FAULT_ALLOC_NID 0x000000020
|
||||
FAULT_ORPHAN 0x000000040
|
||||
FAULT_BLOCK 0x000000080
|
||||
FAULT_DIR_DEPTH 0x000000100
|
||||
FAULT_EVICT_INODE 0x000000200
|
||||
FAULT_TRUNCATE 0x000000400
|
||||
FAULT_READ_IO 0x000000800
|
||||
FAULT_CHECKPOINT 0x000001000
|
||||
FAULT_DISCARD 0x000002000
|
||||
FAULT_WRITE_IO 0x000004000
|
||||
FAULT_SLAB_ALLOC 0x000008000
|
||||
FAULT_DQUOT_INIT 0x000010000
|
||||
FAULT_LOCK_OP 0x000020000
|
||||
FAULT_BLKADDR 0x000040000
|
||||
=================== ===========
|
||||
=========================== ===========
|
||||
Type_Name Type_Value
|
||||
=========================== ===========
|
||||
FAULT_KMALLOC 0x000000001
|
||||
FAULT_KVMALLOC 0x000000002
|
||||
FAULT_PAGE_ALLOC 0x000000004
|
||||
FAULT_PAGE_GET 0x000000008
|
||||
FAULT_ALLOC_BIO 0x000000010 (obsolete)
|
||||
FAULT_ALLOC_NID 0x000000020
|
||||
FAULT_ORPHAN 0x000000040
|
||||
FAULT_BLOCK 0x000000080
|
||||
FAULT_DIR_DEPTH 0x000000100
|
||||
FAULT_EVICT_INODE 0x000000200
|
||||
FAULT_TRUNCATE 0x000000400
|
||||
FAULT_READ_IO 0x000000800
|
||||
FAULT_CHECKPOINT 0x000001000
|
||||
FAULT_DISCARD 0x000002000
|
||||
FAULT_WRITE_IO 0x000004000
|
||||
FAULT_SLAB_ALLOC 0x000008000
|
||||
FAULT_DQUOT_INIT 0x000010000
|
||||
FAULT_LOCK_OP 0x000020000
|
||||
FAULT_BLKADDR_VALIDITY 0x000040000
|
||||
FAULT_BLKADDR_CONSISTENCE 0x000080000
|
||||
FAULT_NO_SEGMENT 0x000100000
|
||||
=========================== ===========
|
||||
|
||||
What: /sys/fs/f2fs/<disk>/discard_io_aware_gran
|
||||
Date: January 2023
|
||||
|
|
|
|||
|
|
@ -1572,12 +1572,28 @@
|
|||
The above will cause the "foo" tracing instance to trigger
|
||||
a snapshot at the end of boot up.
|
||||
|
||||
ftrace_dump_on_oops[=orig_cpu]
|
||||
ftrace_dump_on_oops[=2(orig_cpu) | =<instance>][,<instance> |
|
||||
,<instance>=2(orig_cpu)]
|
||||
[FTRACE] will dump the trace buffers on oops.
|
||||
If no parameter is passed, ftrace will dump
|
||||
buffers of all CPUs, but if you pass orig_cpu, it will
|
||||
dump only the buffer of the CPU that triggered the
|
||||
oops.
|
||||
If no parameter is passed, ftrace will dump global
|
||||
buffers of all CPUs, if you pass 2 or orig_cpu, it
|
||||
will dump only the buffer of the CPU that triggered
|
||||
the oops, or the specific instance will be dumped if
|
||||
its name is passed. Multiple instance dump is also
|
||||
supported, and instances are separated by commas. Each
|
||||
instance supports only dump on CPU that triggered the
|
||||
oops by passing 2 or orig_cpu to it.
|
||||
|
||||
ftrace_dump_on_oops=foo=orig_cpu
|
||||
|
||||
The above will dump only the buffer of "foo" instance
|
||||
on CPU that triggered the oops.
|
||||
|
||||
ftrace_dump_on_oops,foo,bar=orig_cpu
|
||||
|
||||
The above will dump global buffer on all CPUs, the
|
||||
buffer of "foo" instance on all CPUs and the buffer
|
||||
of "bar" instance on CPU that triggered the oops.
|
||||
|
||||
ftrace_filter=[function-list]
|
||||
[FTRACE] Limit the functions traced by the function
|
||||
|
|
|
|||
|
|
@ -296,12 +296,30 @@ kernel panic). This will output the contents of the ftrace buffers to
|
|||
the console. This is very useful for capturing traces that lead to
|
||||
crashes and outputting them to a serial console.
|
||||
|
||||
= ===================================================
|
||||
0 Disabled (default).
|
||||
1 Dump buffers of all CPUs.
|
||||
2 Dump the buffer of the CPU that triggered the oops.
|
||||
= ===================================================
|
||||
======================= ===========================================
|
||||
0 Disabled (default).
|
||||
1 Dump buffers of all CPUs.
|
||||
2(orig_cpu) Dump the buffer of the CPU that triggered the
|
||||
oops.
|
||||
<instance> Dump the specific instance buffer on all CPUs.
|
||||
<instance>=2(orig_cpu) Dump the specific instance buffer on the CPU
|
||||
that triggered the oops.
|
||||
======================= ===========================================
|
||||
|
||||
Multiple instance dump is also supported, and instances are separated
|
||||
by commas. If global buffer also needs to be dumped, please specify
|
||||
the dump mode (1/2/orig_cpu) first for global buffer.
|
||||
|
||||
So for example to dump "foo" and "bar" instance buffer on all CPUs,
|
||||
user can::
|
||||
|
||||
echo "foo,bar" > /proc/sys/kernel/ftrace_dump_on_oops
|
||||
|
||||
To dump global buffer and "foo" instance buffer on all
|
||||
CPUs along with the "bar" instance buffer on CPU that triggered the
|
||||
oops, user can::
|
||||
|
||||
echo "1,foo,bar=2" > /proc/sys/kernel/ftrace_dump_on_oops
|
||||
|
||||
ftrace_enabled, stack_tracer_enabled
|
||||
====================================
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@ properties:
|
|||
- const: brcm,gisb-arb
|
||||
- items:
|
||||
- enum:
|
||||
- brcm,bcm74165-gisb-arb # for V7 new style 16nm chips
|
||||
- brcm,bcm7278-gisb-arb # for V7 28nm chips
|
||||
- brcm,bcm7435-gisb-arb # for newer 40nm chips
|
||||
- brcm,bcm7400-gisb-arb # for older 40nm chips and all 65nm chips
|
||||
|
|
|
|||
56
Documentation/devicetree/bindings/pwm/opencores,pwm.yaml
Normal file
56
Documentation/devicetree/bindings/pwm/opencores,pwm.yaml
Normal file
|
|
@ -0,0 +1,56 @@
|
|||
# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/pwm/opencores,pwm.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: OpenCores PWM controller
|
||||
|
||||
maintainers:
|
||||
- William Qiu <william.qiu@starfivetech.com>
|
||||
|
||||
description:
|
||||
The OpenCores PTC ip core contains a PWM controller. When operating in PWM
|
||||
mode, the PTC core generates binary signal with user-programmable low and
|
||||
high periods. All PTC counters and registers are 32-bit.
|
||||
|
||||
allOf:
|
||||
- $ref: pwm.yaml#
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
items:
|
||||
- enum:
|
||||
- starfive,jh7100-pwm
|
||||
- starfive,jh7110-pwm
|
||||
- starfive,jh8100-pwm
|
||||
- const: opencores,pwm-v1
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
clocks:
|
||||
maxItems: 1
|
||||
|
||||
resets:
|
||||
maxItems: 1
|
||||
|
||||
"#pwm-cells":
|
||||
const: 3
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- clocks
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
pwm@12490000 {
|
||||
compatible = "starfive,jh7110-pwm", "opencores,pwm-v1";
|
||||
reg = <0x12490000 0x10000>;
|
||||
clocks = <&clkgen 181>;
|
||||
resets = <&rstgen 109>;
|
||||
#pwm-cells = <3>;
|
||||
};
|
||||
|
|
@ -0,0 +1,35 @@
|
|||
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/reset/sophgo,sg2042-reset.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Sophgo SG2042 SoC Reset Controller
|
||||
|
||||
maintainers:
|
||||
- Chen Wang <unicorn_wang@outlook.com>
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: sophgo,sg2042-reset
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
"#reset-cells":
|
||||
const: 1
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- "#reset-cells"
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
rstgen: reset-controller@c00 {
|
||||
compatible = "sophgo,sg2042-reset";
|
||||
reg = <0xc00 0xc>;
|
||||
#reset-cells = <1>;
|
||||
};
|
||||
|
|
@ -75,6 +75,10 @@ properties:
|
|||
- riscv,sv57
|
||||
- riscv,none
|
||||
|
||||
reg:
|
||||
description:
|
||||
The hart ID of this CPU node.
|
||||
|
||||
riscv,cbom-block-size:
|
||||
$ref: /schemas/types.yaml#/definitions/uint32
|
||||
description:
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@ properties:
|
|||
- allwinner,sun50i-a100-ths
|
||||
- allwinner,sun50i-h5-ths
|
||||
- allwinner,sun50i-h6-ths
|
||||
- allwinner,sun50i-h616-ths
|
||||
|
||||
clocks:
|
||||
minItems: 1
|
||||
|
|
@ -50,6 +51,10 @@ properties:
|
|||
nvmem-cell-names:
|
||||
const: calibration
|
||||
|
||||
allwinner,sram:
|
||||
maxItems: 1
|
||||
description: phandle to device controlling temperate offset SYS_CFG register
|
||||
|
||||
# See Documentation/devicetree/bindings/thermal/thermal-sensor.yaml for details
|
||||
"#thermal-sensor-cells":
|
||||
enum:
|
||||
|
|
@ -65,6 +70,7 @@ allOf:
|
|||
- allwinner,sun20i-d1-ths
|
||||
- allwinner,sun50i-a100-ths
|
||||
- allwinner,sun50i-h6-ths
|
||||
- allwinner,sun50i-h616-ths
|
||||
|
||||
then:
|
||||
properties:
|
||||
|
|
@ -82,6 +88,17 @@ allOf:
|
|||
clock-names:
|
||||
minItems: 2
|
||||
|
||||
- if:
|
||||
not:
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
const: allwinner,sun50i-h616-ths
|
||||
|
||||
then:
|
||||
properties:
|
||||
allwinner,sram: false
|
||||
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
|
|
@ -101,17 +118,12 @@ allOf:
|
|||
const: 1
|
||||
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
enum:
|
||||
- allwinner,sun8i-h3-ths
|
||||
- allwinner,sun8i-r40-ths
|
||||
- allwinner,sun20i-d1-ths
|
||||
- allwinner,sun50i-a64-ths
|
||||
- allwinner,sun50i-a100-ths
|
||||
- allwinner,sun50i-h5-ths
|
||||
- allwinner,sun50i-h6-ths
|
||||
not:
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
enum:
|
||||
- allwinner,sun8i-a83t-ths
|
||||
|
||||
then:
|
||||
required:
|
||||
|
|
|
|||
|
|
@ -33,7 +33,8 @@ properties:
|
|||
description: |
|
||||
The values to be programmed into TTRnCR, as specified by the SoC
|
||||
reference manual. The first cell is TTR0CR, the second is TTR1CR, etc.
|
||||
maxItems: 4
|
||||
minItems: 2
|
||||
maxItems: 7
|
||||
|
||||
fsl,tmu-calibration:
|
||||
$ref: /schemas/types.yaml#/definitions/uint32-matrix
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@ properties:
|
|||
- renesas,r8a779a0-thermal # R-Car V3U
|
||||
- renesas,r8a779f0-thermal # R-Car S4-8
|
||||
- renesas,r8a779g0-thermal # R-Car V4H
|
||||
- renesas,r8a779h0-thermal # R-Car V4M
|
||||
|
||||
reg: true
|
||||
|
||||
|
|
@ -90,6 +91,7 @@ else:
|
|||
enum:
|
||||
- renesas,r8a779f0-thermal
|
||||
- renesas,r8a779g0-thermal
|
||||
- renesas,r8a779h0-thermal
|
||||
then:
|
||||
required:
|
||||
- interrupts
|
||||
|
|
|
|||
|
|
@ -228,8 +228,6 @@ patternProperties:
|
|||
additionalProperties: false
|
||||
|
||||
required:
|
||||
- polling-delay
|
||||
- polling-delay-passive
|
||||
- thermal-sensors
|
||||
- trips
|
||||
|
||||
|
|
|
|||
|
|
@ -126,9 +126,7 @@ norecovery Disable the roll-forward recovery routine, mounted read-
|
|||
discard/nodiscard Enable/disable real-time discard in f2fs, if discard is
|
||||
enabled, f2fs will issue discard/TRIM commands when a
|
||||
segment is cleaned.
|
||||
no_heap Disable heap-style segment allocation which finds free
|
||||
segments for data from the beginning of main area, while
|
||||
for node from the end of main area.
|
||||
heap/no_heap Deprecated.
|
||||
nouser_xattr Disable Extended User Attributes. Note: xattr is enabled
|
||||
by default if CONFIG_F2FS_FS_XATTR is selected.
|
||||
noacl Disable POSIX Access Control List. Note: acl is enabled
|
||||
|
|
@ -184,29 +182,31 @@ fault_type=%d Support configuring fault injection type, should be
|
|||
enabled with fault_injection option, fault type value
|
||||
is shown below, it supports single or combined type.
|
||||
|
||||
=================== ===========
|
||||
Type_Name Type_Value
|
||||
=================== ===========
|
||||
FAULT_KMALLOC 0x000000001
|
||||
FAULT_KVMALLOC 0x000000002
|
||||
FAULT_PAGE_ALLOC 0x000000004
|
||||
FAULT_PAGE_GET 0x000000008
|
||||
FAULT_ALLOC_BIO 0x000000010 (obsolete)
|
||||
FAULT_ALLOC_NID 0x000000020
|
||||
FAULT_ORPHAN 0x000000040
|
||||
FAULT_BLOCK 0x000000080
|
||||
FAULT_DIR_DEPTH 0x000000100
|
||||
FAULT_EVICT_INODE 0x000000200
|
||||
FAULT_TRUNCATE 0x000000400
|
||||
FAULT_READ_IO 0x000000800
|
||||
FAULT_CHECKPOINT 0x000001000
|
||||
FAULT_DISCARD 0x000002000
|
||||
FAULT_WRITE_IO 0x000004000
|
||||
FAULT_SLAB_ALLOC 0x000008000
|
||||
FAULT_DQUOT_INIT 0x000010000
|
||||
FAULT_LOCK_OP 0x000020000
|
||||
FAULT_BLKADDR 0x000040000
|
||||
=================== ===========
|
||||
=========================== ===========
|
||||
Type_Name Type_Value
|
||||
=========================== ===========
|
||||
FAULT_KMALLOC 0x000000001
|
||||
FAULT_KVMALLOC 0x000000002
|
||||
FAULT_PAGE_ALLOC 0x000000004
|
||||
FAULT_PAGE_GET 0x000000008
|
||||
FAULT_ALLOC_BIO 0x000000010 (obsolete)
|
||||
FAULT_ALLOC_NID 0x000000020
|
||||
FAULT_ORPHAN 0x000000040
|
||||
FAULT_BLOCK 0x000000080
|
||||
FAULT_DIR_DEPTH 0x000000100
|
||||
FAULT_EVICT_INODE 0x000000200
|
||||
FAULT_TRUNCATE 0x000000400
|
||||
FAULT_READ_IO 0x000000800
|
||||
FAULT_CHECKPOINT 0x000001000
|
||||
FAULT_DISCARD 0x000002000
|
||||
FAULT_WRITE_IO 0x000004000
|
||||
FAULT_SLAB_ALLOC 0x000008000
|
||||
FAULT_DQUOT_INIT 0x000010000
|
||||
FAULT_LOCK_OP 0x000020000
|
||||
FAULT_BLKADDR_VALIDITY 0x000040000
|
||||
FAULT_BLKADDR_CONSISTENCE 0x000080000
|
||||
FAULT_NO_SEGMENT 0x000100000
|
||||
=========================== ===========
|
||||
mode=%s Control block allocation mode which supports "adaptive"
|
||||
and "lfs". In "lfs" mode, there should be no random
|
||||
writes towards main area.
|
||||
|
|
@ -228,8 +228,6 @@ mode=%s Control block allocation mode which supports "adaptive"
|
|||
option for more randomness.
|
||||
Please, use these options for your experiments and we strongly
|
||||
recommend to re-format the filesystem after using these options.
|
||||
io_bits=%u Set the bit size of write IO requests. It should be set
|
||||
with "mode=lfs".
|
||||
usrquota Enable plain user disk quota accounting.
|
||||
grpquota Enable plain group disk quota accounting.
|
||||
prjquota Enable plain project quota accounting.
|
||||
|
|
|
|||
|
|
@ -595,7 +595,7 @@ bridges/switches of the board.
|
|||
|
||||
For example, let's assume we have a system with a PCIe serial port, an
|
||||
Exar XR17V3521, soldered on the main board. This UART chip also includes
|
||||
16 GPIOs and we want to add the property ``gpio-line-names`` [1] to these pins.
|
||||
16 GPIOs and we want to add the property ``gpio-line-names`` [1]_ to these pins.
|
||||
In this case, the ``lspci`` output for this component is::
|
||||
|
||||
07:00.0 Serial controller: Exar Corp. XR17V3521 Dual PCIe UART (rev 03)
|
||||
|
|
@ -637,7 +637,7 @@ of the chipset bridge (also called "root port") with address::
|
|||
Bus: 0 - Device: 14 - Function: 1
|
||||
|
||||
To find this information, it is necessary to disassemble the BIOS ACPI tables,
|
||||
in particular the DSDT (see also [2])::
|
||||
in particular the DSDT (see also [2]_)::
|
||||
|
||||
mkdir ~/tables/
|
||||
cd ~/tables/
|
||||
|
|
@ -667,7 +667,7 @@ device::
|
|||
}
|
||||
... other definitions follow ...
|
||||
|
||||
and the _ADR method [3] returns exactly the device/function couple that
|
||||
and the _ADR method [3]_ returns exactly the device/function couple that
|
||||
we are looking for. With this information and analyzing the above ``lspci``
|
||||
output (both the devices list and the devices tree), we can write the following
|
||||
ACPI description for the Exar PCIe UART, also adding the list of its GPIO line
|
||||
|
|
@ -724,10 +724,10 @@ created analyzing the position of the Exar UART in the PCI bus topology.
|
|||
References
|
||||
==========
|
||||
|
||||
[1] Documentation/firmware-guide/acpi/gpio-properties.rst
|
||||
.. [1] Documentation/firmware-guide/acpi/gpio-properties.rst
|
||||
|
||||
[2] Documentation/admin-guide/acpi/initrd_table_override.rst
|
||||
.. [2] Documentation/admin-guide/acpi/initrd_table_override.rst
|
||||
|
||||
[3] ACPI Specifications, Version 6.3 - Paragraph 6.1.1 _ADR Address)
|
||||
.. [3] ACPI Specifications, Version 6.3 - Paragraph 6.1.1 _ADR Address)
|
||||
https://uefi.org/sites/default/files/resources/ACPI_6_3_May16.pdf,
|
||||
referenced 2020-11-18
|
||||
|
|
|
|||
|
|
@ -78,7 +78,7 @@ handling the given IRQ as a system wakeup interrupt line and disable_irq_wake()
|
|||
turns that logic off.
|
||||
|
||||
Calling enable_irq_wake() causes suspend_device_irqs() to treat the given IRQ
|
||||
in a special way. Namely, the IRQ remains enabled, by on the first interrupt
|
||||
in a special way. Namely, the IRQ remains enabled, but on the first interrupt
|
||||
it will be disabled, marked as pending and "suspended" so that it will be
|
||||
re-enabled by resume_device_irqs() during the subsequent system resume. Also
|
||||
the PM core is notified about the event which causes the system suspend in
|
||||
|
|
|
|||
|
|
@ -92,6 +92,24 @@ The following flags are currently supported.
|
|||
process closes or unregisters the event. Requires CAP_PERFMON otherwise
|
||||
-EPERM is returned.
|
||||
|
||||
+ USER_EVENT_REG_MULTI_FORMAT: The event can contain multiple formats. This
|
||||
allows programs to prevent themselves from being blocked when their event
|
||||
format changes and they wish to use the same name. When this flag is used the
|
||||
tracepoint name will be in the new format of "name.unique_id" vs the older
|
||||
format of "name". A tracepoint will be created for each unique pair of name
|
||||
and format. This means if several processes use the same name and format,
|
||||
they will use the same tracepoint. If yet another process uses the same name,
|
||||
but a different format than the other processes, it will use a different
|
||||
tracepoint with a new unique id. Recording programs need to scan tracefs for
|
||||
the various different formats of the event name they are interested in
|
||||
recording. The system name of the tracepoint will also use "user_events_multi"
|
||||
instead of "user_events". This prevents single-format event names conflicting
|
||||
with any multi-format event names within tracefs. The unique_id is output as
|
||||
a hex string. Recording programs should ensure the tracepoint name starts with
|
||||
the event name they registered and has a suffix that starts with . and only
|
||||
has hex characters. For example to find all versions of the event "test" you
|
||||
can use the regex "^test\.[0-9a-fA-F]+$".
|
||||
|
||||
Upon successful registration the following is set.
|
||||
|
||||
+ write_index: The index to use for this file descriptor that represents this
|
||||
|
|
@ -106,6 +124,9 @@ or perf record -e user_events:[name] when attaching/recording.
|
|||
**NOTE:** The event subsystem name by default is "user_events". Callers should
|
||||
not assume it will always be "user_events". Operators reserve the right in the
|
||||
future to change the subsystem name per-process to accommodate event isolation.
|
||||
In addition if the USER_EVENT_REG_MULTI_FORMAT flag is used the tracepoint name
|
||||
will have a unique id appended to it and the system name will be
|
||||
"user_events_multi" as described above.
|
||||
|
||||
Command Format
|
||||
^^^^^^^^^^^^^^
|
||||
|
|
@ -156,7 +177,11 @@ to request deletes than the one used for registration due to this.
|
|||
to the event. If programs do not want auto-delete, they must use the
|
||||
USER_EVENT_REG_PERSIST flag when registering the event. Once that flag is used
|
||||
the event exists until DIAG_IOCSDEL is invoked. Both register and delete of an
|
||||
event that persists requires CAP_PERFMON, otherwise -EPERM is returned.
|
||||
event that persists requires CAP_PERFMON, otherwise -EPERM is returned. When
|
||||
there are multiple formats of the same event name, all events with the same
|
||||
name will be attempted to be deleted. If only a specific version is wanted to
|
||||
be deleted then the /sys/kernel/tracing/dynamic_events file should be used for
|
||||
that specific format of the event.
|
||||
|
||||
Unregistering
|
||||
-------------
|
||||
|
|
|
|||
|
|
@ -8987,6 +8987,11 @@ F: Documentation/i2c/muxes/i2c-mux-gpio.rst
|
|||
F: drivers/i2c/muxes/i2c-mux-gpio.c
|
||||
F: include/linux/platform_data/i2c-mux-gpio.h
|
||||
|
||||
GENERIC GPIO RESET DRIVER
|
||||
M: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
|
||||
S: Maintained
|
||||
F: drivers/reset/reset-gpio.c
|
||||
|
||||
GENERIC HDLC (WAN) DRIVERS
|
||||
M: Krzysztof Halasa <khc@pm.waw.pl>
|
||||
S: Maintained
|
||||
|
|
@ -16588,7 +16593,7 @@ M: Miklos Szeredi <miklos@szeredi.hu>
|
|||
M: Amir Goldstein <amir73il@gmail.com>
|
||||
L: linux-unionfs@vger.kernel.org
|
||||
S: Supported
|
||||
T: git git://git.kernel.org/pub/scm/linux/kernel/git/mszeredi/vfs.git
|
||||
T: git git://git.kernel.org/pub/scm/linux/kernel/git/overlayfs/vfs.git
|
||||
F: Documentation/filesystems/overlayfs.rst
|
||||
F: fs/overlayfs/
|
||||
|
||||
|
|
@ -17689,7 +17694,7 @@ M: Joel Granados <j.granados@samsung.com>
|
|||
L: linux-kernel@vger.kernel.org
|
||||
L: linux-fsdevel@vger.kernel.org
|
||||
S: Maintained
|
||||
T: git git://git.kernel.org/pub/scm/linux/kernel/git/mcgrof/linux.git sysctl-next
|
||||
T: git git://git.kernel.org/pub/scm/linux/kernel/git/sysctl/sysctl.git sysctl-next
|
||||
F: fs/proc/proc_sysctl.c
|
||||
F: include/linux/sysctl.h
|
||||
F: kernel/sysctl-test.c
|
||||
|
|
|
|||
|
|
@ -108,30 +108,31 @@ clock@664 {
|
|||
compatible = "ti,clksel";
|
||||
reg = <0x664>;
|
||||
#clock-cells = <2>;
|
||||
#address-cells = <0>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
ehrpwm0_tbclk: clock-ehrpwm0-tbclk {
|
||||
ehrpwm0_tbclk: clock-ehrpwm0-tbclk@0 {
|
||||
reg = <0>;
|
||||
#clock-cells = <0>;
|
||||
compatible = "ti,gate-clock";
|
||||
clock-output-names = "ehrpwm0_tbclk";
|
||||
clocks = <&l4ls_gclk>;
|
||||
ti,bit-shift = <0>;
|
||||
};
|
||||
|
||||
ehrpwm1_tbclk: clock-ehrpwm1-tbclk {
|
||||
ehrpwm1_tbclk: clock-ehrpwm1-tbclk@1 {
|
||||
reg = <1>;
|
||||
#clock-cells = <0>;
|
||||
compatible = "ti,gate-clock";
|
||||
clock-output-names = "ehrpwm1_tbclk";
|
||||
clocks = <&l4ls_gclk>;
|
||||
ti,bit-shift = <1>;
|
||||
};
|
||||
|
||||
ehrpwm2_tbclk: clock-ehrpwm2-tbclk {
|
||||
ehrpwm2_tbclk: clock-ehrpwm2-tbclk@2 {
|
||||
reg = <2>;
|
||||
#clock-cells = <0>;
|
||||
compatible = "ti,gate-clock";
|
||||
clock-output-names = "ehrpwm2_tbclk";
|
||||
clocks = <&l4ls_gclk>;
|
||||
ti,bit-shift = <2>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
|
@ -566,17 +567,19 @@ clock@52c {
|
|||
compatible = "ti,clksel";
|
||||
reg = <0x52c>;
|
||||
#clock-cells = <2>;
|
||||
#address-cells = <0>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
gfx_fclk_clksel_ck: clock-gfx-fclk-clksel {
|
||||
gfx_fclk_clksel_ck: clock-gfx-fclk-clksel@1 {
|
||||
reg = <1>;
|
||||
#clock-cells = <0>;
|
||||
compatible = "ti,mux-clock";
|
||||
clock-output-names = "gfx_fclk_clksel_ck";
|
||||
clocks = <&dpll_core_m4_ck>, <&dpll_per_m2_ck>;
|
||||
ti,bit-shift = <1>;
|
||||
};
|
||||
|
||||
gfx_fck_div_ck: clock-gfx-fck-div {
|
||||
gfx_fck_div_ck: clock-gfx-fck-div@0 {
|
||||
reg = <0>;
|
||||
#clock-cells = <0>;
|
||||
compatible = "ti,divider-clock";
|
||||
clock-output-names = "gfx_fck_div_ck";
|
||||
|
|
@ -589,30 +592,32 @@ clock@700 {
|
|||
compatible = "ti,clksel";
|
||||
reg = <0x700>;
|
||||
#clock-cells = <2>;
|
||||
#address-cells = <0>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
sysclkout_pre_ck: clock-sysclkout-pre {
|
||||
sysclkout_pre_ck: clock-sysclkout-pre@0 {
|
||||
reg = <0>;
|
||||
#clock-cells = <0>;
|
||||
compatible = "ti,mux-clock";
|
||||
clock-output-names = "sysclkout_pre_ck";
|
||||
clocks = <&clk_32768_ck>, <&l3_gclk>, <&dpll_ddr_m2_ck>, <&dpll_per_m2_ck>, <&lcd_gclk>;
|
||||
};
|
||||
|
||||
clkout2_div_ck: clock-clkout2-div {
|
||||
clkout2_div_ck: clock-clkout2-div@3 {
|
||||
reg = <3>;
|
||||
#clock-cells = <0>;
|
||||
compatible = "ti,divider-clock";
|
||||
clock-output-names = "clkout2_div_ck";
|
||||
clocks = <&sysclkout_pre_ck>;
|
||||
ti,bit-shift = <3>;
|
||||
ti,max-div = <8>;
|
||||
};
|
||||
|
||||
clkout2_ck: clock-clkout2 {
|
||||
clkout2_ck: clock-clkout2@7 {
|
||||
reg = <7>;
|
||||
#clock-cells = <0>;
|
||||
compatible = "ti,gate-clock";
|
||||
clock-output-names = "clkout2_ck";
|
||||
clocks = <&clkout2_div_ck>;
|
||||
ti,bit-shift = <7>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
|
|
|||
|
|
@ -66,22 +66,23 @@ clock@a10 {
|
|||
compatible = "ti,clksel";
|
||||
reg = <0xa10>;
|
||||
#clock-cells = <2>;
|
||||
#address-cells = <0>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
ipss_ick: clock-ipss-ick {
|
||||
ipss_ick: clock-ipss-ick@4 {
|
||||
reg = <4>;
|
||||
#clock-cells = <0>;
|
||||
compatible = "ti,am35xx-interface-clock";
|
||||
clock-output-names = "ipss_ick";
|
||||
clocks = <&core_l3_ick>;
|
||||
ti,bit-shift = <4>;
|
||||
};
|
||||
|
||||
uart4_ick_am35xx: clock-uart4-ick-am35xx {
|
||||
uart4_ick_am35xx: clock-uart4-ick-am35xx@23 {
|
||||
reg = <23>;
|
||||
#clock-cells = <0>;
|
||||
compatible = "ti,omap3-interface-clock";
|
||||
clock-output-names = "uart4_ick_am35xx";
|
||||
clocks = <&core_l4_ick>;
|
||||
ti,bit-shift = <23>;
|
||||
};
|
||||
};
|
||||
|
||||
|
|
@ -101,14 +102,15 @@ clock@a00 {
|
|||
compatible = "ti,clksel";
|
||||
reg = <0xa00>;
|
||||
#clock-cells = <2>;
|
||||
#address-cells = <0>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
uart4_fck_am35xx: clock-uart4-fck-am35xx {
|
||||
uart4_fck_am35xx: clock-uart4-fck-am35xx@23 {
|
||||
reg = <23>;
|
||||
#clock-cells = <0>;
|
||||
compatible = "ti,wait-gate-clock";
|
||||
clock-output-names = "uart4_fck_am35xx";
|
||||
clocks = <&core_48m_fck>;
|
||||
ti,bit-shift = <23>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
|
|
|||
|
|
@ -50,30 +50,31 @@ clock@a00 {
|
|||
compatible = "ti,clksel";
|
||||
reg = <0xa00>;
|
||||
#clock-cells = <2>;
|
||||
#address-cells = <0>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
d2d_26m_fck: clock-d2d-26m-fck {
|
||||
d2d_26m_fck: clock-d2d-26m-fck@3 {
|
||||
reg = <3>;
|
||||
#clock-cells = <0>;
|
||||
compatible = "ti,wait-gate-clock";
|
||||
clock-output-names = "d2d_26m_fck";
|
||||
clocks = <&sys_ck>;
|
||||
ti,bit-shift = <3>;
|
||||
};
|
||||
|
||||
fshostusb_fck: clock-fshostusb-fck {
|
||||
fshostusb_fck: clock-fshostusb-fck@5 {
|
||||
reg = <5>;
|
||||
#clock-cells = <0>;
|
||||
compatible = "ti,wait-gate-clock";
|
||||
clock-output-names = "fshostusb_fck";
|
||||
clocks = <&core_48m_fck>;
|
||||
ti,bit-shift = <5>;
|
||||
};
|
||||
|
||||
ssi_ssr_gate_fck_3430es1: clock-ssi-ssr-gate-fck-3430es1 {
|
||||
ssi_ssr_gate_fck_3430es1: clock-ssi-ssr-gate-fck-3430es1@0 {
|
||||
reg = <0>;
|
||||
#clock-cells = <0>;
|
||||
compatible = "ti,composite-no-wait-gate-clock";
|
||||
clock-output-names = "ssi_ssr_gate_fck_3430es1";
|
||||
clocks = <&corex2_fck>;
|
||||
ti,bit-shift = <0>;
|
||||
};
|
||||
};
|
||||
|
||||
|
|
@ -81,23 +82,24 @@ clock@a40 {
|
|||
compatible = "ti,clksel";
|
||||
reg = <0xa40>;
|
||||
#clock-cells = <2>;
|
||||
#address-cells = <0>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
ssi_ssr_div_fck_3430es1: clock-ssi-ssr-div-fck-3430es1 {
|
||||
ssi_ssr_div_fck_3430es1: clock-ssi-ssr-div-fck-3430es1@8 {
|
||||
reg = <8>;
|
||||
#clock-cells = <0>;
|
||||
compatible = "ti,composite-divider-clock";
|
||||
clock-output-names = "ssi_ssr_div_fck_3430es1";
|
||||
clocks = <&corex2_fck>;
|
||||
ti,bit-shift = <8>;
|
||||
ti,dividers = <0>, <1>, <2>, <3>, <4>, <0>, <6>, <0>, <8>;
|
||||
};
|
||||
|
||||
usb_l4_div_ick: clock-usb-l4-div-ick {
|
||||
usb_l4_div_ick: clock-usb-l4-div-ick@4 {
|
||||
reg = <4>;
|
||||
#clock-cells = <0>;
|
||||
compatible = "ti,composite-divider-clock";
|
||||
clock-output-names = "usb_l4_div_ick";
|
||||
clocks = <&l4_ick>;
|
||||
ti,bit-shift = <4>;
|
||||
ti,max-div = <1>;
|
||||
ti,index-starts-at-one;
|
||||
};
|
||||
|
|
@ -121,38 +123,39 @@ clock@a10 {
|
|||
compatible = "ti,clksel";
|
||||
reg = <0xa10>;
|
||||
#clock-cells = <2>;
|
||||
#address-cells = <0>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
hsotgusb_ick_3430es1: clock-hsotgusb-ick-3430es1 {
|
||||
hsotgusb_ick_3430es1: clock-hsotgusb-ick-3430es1@4 {
|
||||
reg = <4>;
|
||||
#clock-cells = <0>;
|
||||
compatible = "ti,omap3-no-wait-interface-clock";
|
||||
clock-output-names = "hsotgusb_ick_3430es1";
|
||||
clocks = <&core_l3_ick>;
|
||||
ti,bit-shift = <4>;
|
||||
};
|
||||
|
||||
fac_ick: clock-fac-ick {
|
||||
fac_ick: clock-fac-ick@8 {
|
||||
reg = <8>;
|
||||
#clock-cells = <0>;
|
||||
compatible = "ti,omap3-interface-clock";
|
||||
clock-output-names = "fac_ick";
|
||||
clocks = <&core_l4_ick>;
|
||||
ti,bit-shift = <8>;
|
||||
};
|
||||
|
||||
ssi_ick: clock-ssi-ick-3430es1 {
|
||||
ssi_ick: clock-ssi-ick-3430es1@0 {
|
||||
reg = <0>;
|
||||
#clock-cells = <0>;
|
||||
compatible = "ti,omap3-no-wait-interface-clock";
|
||||
clock-output-names = "ssi_ick_3430es1";
|
||||
clocks = <&ssi_l4_ick>;
|
||||
ti,bit-shift = <0>;
|
||||
};
|
||||
|
||||
usb_l4_gate_ick: clock-usb-l4-gate-ick {
|
||||
usb_l4_gate_ick: clock-usb-l4-gate-ick@5 {
|
||||
reg = <5>;
|
||||
#clock-cells = <0>;
|
||||
compatible = "ti,composite-interface-clock";
|
||||
clock-output-names = "usb_l4_gate_ick";
|
||||
clocks = <&l4_ick>;
|
||||
ti,bit-shift = <5>;
|
||||
};
|
||||
};
|
||||
|
||||
|
|
@ -174,14 +177,15 @@ clock@e00 {
|
|||
compatible = "ti,clksel";
|
||||
reg = <0xe00>;
|
||||
#clock-cells = <2>;
|
||||
#address-cells = <0>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
dss1_alwon_fck: clock-dss1-alwon-fck-3430es1 {
|
||||
dss1_alwon_fck: clock-dss1-alwon-fck-3430es1@0 {
|
||||
reg = <0>;
|
||||
#clock-cells = <0>;
|
||||
compatible = "ti,gate-clock";
|
||||
clock-output-names = "dss1_alwon_fck_3430es1";
|
||||
clocks = <&dpll4_m4x2_ck>;
|
||||
ti,bit-shift = <0>;
|
||||
ti,set-rate-parent;
|
||||
};
|
||||
};
|
||||
|
|
|
|||
|
|
@ -17,46 +17,47 @@ clock@a14 {
|
|||
compatible = "ti,clksel";
|
||||
reg = <0xa14>;
|
||||
#clock-cells = <2>;
|
||||
#address-cells = <0>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
aes1_ick: clock-aes1-ick {
|
||||
aes1_ick: clock-aes1-ick@3 {
|
||||
reg = <3>;
|
||||
#clock-cells = <0>;
|
||||
compatible = "ti,omap3-interface-clock";
|
||||
clock-output-names = "aes1_ick";
|
||||
clocks = <&security_l4_ick2>;
|
||||
ti,bit-shift = <3>;
|
||||
};
|
||||
|
||||
rng_ick: clock-rng-ick {
|
||||
rng_ick: clock-rng-ick@2 {
|
||||
reg = <2>;
|
||||
#clock-cells = <0>;
|
||||
compatible = "ti,omap3-interface-clock";
|
||||
clock-output-names = "rng_ick";
|
||||
clocks = <&security_l4_ick2>;
|
||||
ti,bit-shift = <2>;
|
||||
};
|
||||
|
||||
sha11_ick: clock-sha11-ick {
|
||||
sha11_ick: clock-sha11-ick@1 {
|
||||
reg = <1>;
|
||||
#clock-cells = <0>;
|
||||
compatible = "ti,omap3-interface-clock";
|
||||
clock-output-names = "sha11_ick";
|
||||
clocks = <&security_l4_ick2>;
|
||||
ti,bit-shift = <1>;
|
||||
};
|
||||
|
||||
des1_ick: clock-des1-ick {
|
||||
des1_ick: clock-des1-ick@0 {
|
||||
reg = <0>;
|
||||
#clock-cells = <0>;
|
||||
compatible = "ti,omap3-interface-clock";
|
||||
clock-output-names = "des1_ick";
|
||||
clocks = <&security_l4_ick2>;
|
||||
ti,bit-shift = <0>;
|
||||
};
|
||||
|
||||
pka_ick: clock-pka-ick {
|
||||
pka_ick: clock-pka-ick@4 {
|
||||
reg = <4>;
|
||||
#clock-cells = <0>;
|
||||
compatible = "ti,omap3-interface-clock";
|
||||
clock-output-names = "pka_ick";
|
||||
clocks = <&security_l3_ick>;
|
||||
ti,bit-shift = <4>;
|
||||
};
|
||||
};
|
||||
|
||||
|
|
@ -65,23 +66,24 @@ clock@f00 {
|
|||
compatible = "ti,clksel";
|
||||
reg = <0xf00>;
|
||||
#clock-cells = <2>;
|
||||
#address-cells = <0>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
cam_mclk: clock-cam-mclk {
|
||||
cam_mclk: clock-cam-mclk@0 {
|
||||
reg = <0>;
|
||||
#clock-cells = <0>;
|
||||
compatible = "ti,gate-clock";
|
||||
clock-output-names = "cam_mclk";
|
||||
clocks = <&dpll4_m5x2_ck>;
|
||||
ti,bit-shift = <0>;
|
||||
ti,set-rate-parent;
|
||||
};
|
||||
|
||||
csi2_96m_fck: clock-csi2-96m-fck {
|
||||
csi2_96m_fck: clock-csi2-96m-fck@1 {
|
||||
reg = <1>;
|
||||
#clock-cells = <0>;
|
||||
compatible = "ti,gate-clock";
|
||||
clock-output-names = "csi2_96m_fck";
|
||||
clocks = <&core_96m_fck>;
|
||||
ti,bit-shift = <1>;
|
||||
};
|
||||
};
|
||||
|
||||
|
|
@ -105,46 +107,47 @@ clock@a10 {
|
|||
compatible = "ti,clksel";
|
||||
reg = <0xa10>;
|
||||
#clock-cells = <2>;
|
||||
#address-cells = <0>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
icr_ick: clock-icr-ick {
|
||||
icr_ick: clock-icr-ick@29 {
|
||||
reg = <29>;
|
||||
#clock-cells = <0>;
|
||||
compatible = "ti,omap3-interface-clock";
|
||||
clock-output-names = "icr_ick";
|
||||
clocks = <&core_l4_ick>;
|
||||
ti,bit-shift = <29>;
|
||||
};
|
||||
|
||||
des2_ick: clock-des2-ick {
|
||||
des2_ick: clock-des2-ick@26 {
|
||||
reg = <26>;
|
||||
#clock-cells = <0>;
|
||||
compatible = "ti,omap3-interface-clock";
|
||||
clock-output-names = "des2_ick";
|
||||
clocks = <&core_l4_ick>;
|
||||
ti,bit-shift = <26>;
|
||||
};
|
||||
|
||||
mspro_ick: clock-mspro-ick {
|
||||
mspro_ick: clock-mspro-ick@23 {
|
||||
reg = <23>;
|
||||
#clock-cells = <0>;
|
||||
compatible = "ti,omap3-interface-clock";
|
||||
clock-output-names = "mspro_ick";
|
||||
clocks = <&core_l4_ick>;
|
||||
ti,bit-shift = <23>;
|
||||
};
|
||||
|
||||
mailboxes_ick: clock-mailboxes-ick {
|
||||
mailboxes_ick: clock-mailboxes-ick@7 {
|
||||
reg = <7>;
|
||||
#clock-cells = <0>;
|
||||
compatible = "ti,omap3-interface-clock";
|
||||
clock-output-names = "mailboxes_ick";
|
||||
clocks = <&core_l4_ick>;
|
||||
ti,bit-shift = <7>;
|
||||
};
|
||||
|
||||
sad2d_ick: clock-sad2d-ick {
|
||||
sad2d_ick: clock-sad2d-ick@3 {
|
||||
reg = <3>;
|
||||
#clock-cells = <0>;
|
||||
compatible = "ti,omap3-interface-clock";
|
||||
clock-output-names = "sad2d_ick";
|
||||
clocks = <&l3_ick>;
|
||||
ti,bit-shift = <3>;
|
||||
};
|
||||
};
|
||||
|
||||
|
|
@ -160,22 +163,23 @@ clock@c00 {
|
|||
compatible = "ti,clksel";
|
||||
reg = <0xc00>;
|
||||
#clock-cells = <2>;
|
||||
#address-cells = <0>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
sr1_fck: clock-sr1-fck {
|
||||
sr1_fck: clock-sr1-fck@6 {
|
||||
reg = <6>;
|
||||
#clock-cells = <0>;
|
||||
compatible = "ti,wait-gate-clock";
|
||||
clock-output-names = "sr1_fck";
|
||||
clocks = <&sys_ck>;
|
||||
ti,bit-shift = <6>;
|
||||
};
|
||||
|
||||
sr2_fck: clock-sr2-fck {
|
||||
sr2_fck: clock-sr2-fck@7 {
|
||||
reg = <7>;
|
||||
#clock-cells = <0>;
|
||||
compatible = "ti,wait-gate-clock";
|
||||
clock-output-names = "sr2_fck";
|
||||
clocks = <&sys_ck>;
|
||||
ti,bit-shift = <7>;
|
||||
};
|
||||
};
|
||||
|
||||
|
|
@ -228,22 +232,23 @@ clock@a00 {
|
|||
compatible = "ti,clksel";
|
||||
reg = <0xa00>;
|
||||
#clock-cells = <2>;
|
||||
#address-cells = <0>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
modem_fck: clock-modem-fck {
|
||||
modem_fck: clock-modem-fck@31 {
|
||||
reg = <31>;
|
||||
#clock-cells = <0>;
|
||||
compatible = "ti,omap3-interface-clock";
|
||||
clock-output-names = "modem_fck";
|
||||
clocks = <&sys_ck>;
|
||||
ti,bit-shift = <31>;
|
||||
};
|
||||
|
||||
mspro_fck: clock-mspro-fck {
|
||||
mspro_fck: clock-mspro-fck@23 {
|
||||
reg = <23>;
|
||||
#clock-cells = <0>;
|
||||
compatible = "ti,wait-gate-clock";
|
||||
clock-output-names = "mspro_fck";
|
||||
clocks = <&core_96m_fck>;
|
||||
ti,bit-shift = <23>;
|
||||
};
|
||||
};
|
||||
|
||||
|
|
@ -252,14 +257,15 @@ clock@a18 {
|
|||
compatible = "ti,clksel";
|
||||
reg = <0xa18>;
|
||||
#clock-cells = <2>;
|
||||
#address-cells = <0>;
|
||||
#address-cells = <1>;
|
||||
#ssize-cells = <0>;
|
||||
|
||||
mad2d_ick: clock-mad2d-ick {
|
||||
mad2d_ick: clock-mad2d-ick@3 {
|
||||
reg = <3>;
|
||||
#clock-cells = <0>;
|
||||
compatible = "ti,omap3-interface-clock";
|
||||
clock-output-names = "mad2d_ick";
|
||||
clocks = <&l3_ick>;
|
||||
ti,bit-shift = <3>;
|
||||
};
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -138,14 +138,15 @@ clock@a18 {
|
|||
compatible = "ti,clksel";
|
||||
reg = <0xa18>;
|
||||
#clock-cells = <2>;
|
||||
#address-cells = <0>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
usbtll_ick: clock-usbtll-ick {
|
||||
usbtll_ick: clock-usbtll-ick@2 {
|
||||
reg = <2>;
|
||||
#clock-cells = <0>;
|
||||
compatible = "ti,omap3-interface-clock";
|
||||
clock-output-names = "usbtll_ick";
|
||||
clocks = <&core_l4_ick>;
|
||||
ti,bit-shift = <2>;
|
||||
};
|
||||
};
|
||||
|
||||
|
|
@ -153,14 +154,15 @@ clock@a10 {
|
|||
compatible = "ti,clksel";
|
||||
reg = <0xa10>;
|
||||
#clock-cells = <2>;
|
||||
#address-cells = <0>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
mmchs3_ick: clock-mmchs3-ick {
|
||||
mmchs3_ick: clock-mmchs3-ick@30 {
|
||||
reg = <30>;
|
||||
#clock-cells = <0>;
|
||||
compatible = "ti,omap3-interface-clock";
|
||||
clock-output-names = "mmchs3_ick";
|
||||
clocks = <&core_l4_ick>;
|
||||
ti,bit-shift = <30>;
|
||||
};
|
||||
};
|
||||
|
||||
|
|
@ -168,14 +170,15 @@ clock@a00 {
|
|||
compatible = "ti,clksel";
|
||||
reg = <0xa00>;
|
||||
#clock-cells = <2>;
|
||||
#address-cells = <0>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
mmchs3_fck: clock-mmchs3-fck {
|
||||
mmchs3_fck: clock-mmchs3-fck@30 {
|
||||
reg = <30>;
|
||||
#clock-cells = <0>;
|
||||
compatible = "ti,wait-gate-clock";
|
||||
clock-output-names = "mmchs3_fck";
|
||||
clocks = <&core_96m_fck>;
|
||||
ti,bit-shift = <30>;
|
||||
};
|
||||
};
|
||||
|
||||
|
|
@ -183,14 +186,15 @@ clock@e00 {
|
|||
compatible = "ti,clksel";
|
||||
reg = <0xe00>;
|
||||
#clock-cells = <2>;
|
||||
#address-cells = <0>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
dss1_alwon_fck: clock-dss1-alwon-fck-3430es2 {
|
||||
dss1_alwon_fck: clock-dss1-alwon-fck-3430es2@0 {
|
||||
reg = <0>;
|
||||
#clock-cells = <0>;
|
||||
compatible = "ti,dss-gate-clock";
|
||||
clock-output-names = "dss1_alwon_fck_3430es2";
|
||||
clocks = <&dpll4_m4x2_ck>;
|
||||
ti,bit-shift = <0>;
|
||||
ti,set-rate-parent;
|
||||
};
|
||||
};
|
||||
|
|
|
|||
|
|
@ -62,14 +62,15 @@ clock@1000 {
|
|||
compatible = "ti,clksel";
|
||||
reg = <0x1000>;
|
||||
#clock-cells = <2>;
|
||||
#address-cells = <0>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
uart4_fck: clock-uart4-fck {
|
||||
uart4_fck: clock-uart4-fck@18 {
|
||||
reg = <18>;
|
||||
#clock-cells = <0>;
|
||||
compatible = "ti,wait-gate-clock";
|
||||
clock-output-names = "uart4_fck";
|
||||
clocks = <&per_48m_fck>;
|
||||
ti,bit-shift = <18>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
|
|
|||
|
|
@ -9,14 +9,15 @@ clock@a00 {
|
|||
compatible = "ti,clksel";
|
||||
reg = <0xa00>;
|
||||
#clock-cells = <2>;
|
||||
#address-cells = <0>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
ssi_ssr_gate_fck_3430es2: clock-ssi-ssr-gate-fck-3430es2 {
|
||||
ssi_ssr_gate_fck_3430es2: clock-ssi-ssr-gate-fck-3430es2@0 {
|
||||
reg = <0>;
|
||||
#clock-cells = <0>;
|
||||
compatible = "ti,composite-no-wait-gate-clock";
|
||||
clock-output-names = "ssi_ssr_gate_fck_3430es2";
|
||||
clocks = <&corex2_fck>;
|
||||
ti,bit-shift = <0>;
|
||||
};
|
||||
};
|
||||
|
||||
|
|
@ -24,14 +25,15 @@ clock@a40 {
|
|||
compatible = "ti,clksel";
|
||||
reg = <0xa40>;
|
||||
#clock-cells = <2>;
|
||||
#address-cells = <0>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
ssi_ssr_div_fck_3430es2: clock-ssi-ssr-div-fck-3430es2 {
|
||||
ssi_ssr_div_fck_3430es2: clock-ssi-ssr-div-fck-3430es2@8 {
|
||||
reg = <8>;
|
||||
#clock-cells = <0>;
|
||||
compatible = "ti,composite-divider-clock";
|
||||
clock-output-names = "ssi_ssr_div_fck_3430es2";
|
||||
clocks = <&corex2_fck>;
|
||||
ti,bit-shift = <8>;
|
||||
ti,dividers = <0>, <1>, <2>, <3>, <4>, <0>, <6>, <0>, <8>;
|
||||
};
|
||||
};
|
||||
|
|
@ -54,22 +56,23 @@ clock@a10 {
|
|||
compatible = "ti,clksel";
|
||||
reg = <0xa10>;
|
||||
#clock-cells = <2>;
|
||||
#address-cells = <0>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
hsotgusb_ick_3430es2: clock-hsotgusb-ick-3430es2 {
|
||||
hsotgusb_ick_3430es2: clock-hsotgusb-ick-3430es2@4 {
|
||||
reg = <4>;
|
||||
#clock-cells = <0>;
|
||||
compatible = "ti,omap3-hsotgusb-interface-clock";
|
||||
clock-output-names = "hsotgusb_ick_3430es2";
|
||||
clocks = <&core_l3_ick>;
|
||||
ti,bit-shift = <4>;
|
||||
};
|
||||
|
||||
ssi_ick: clock-ssi-ick-3430es2 {
|
||||
ssi_ick: clock-ssi-ick-3430es2@0 {
|
||||
reg = <0>;
|
||||
#clock-cells = <0>;
|
||||
compatible = "ti,omap3-ssi-interface-clock";
|
||||
clock-output-names = "ssi_ick_3430es2";
|
||||
clocks = <&ssi_l4_ick>;
|
||||
ti,bit-shift = <0>;
|
||||
};
|
||||
};
|
||||
|
||||
|
|
@ -85,14 +88,15 @@ clock@c00 {
|
|||
compatible = "ti,clksel";
|
||||
reg = <0xc00>;
|
||||
#clock-cells = <2>;
|
||||
#address-cells = <0>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
usim_gate_fck: clock-usim-gate-fck {
|
||||
usim_gate_fck: clock-usim-gate-fck@9 {
|
||||
reg = <9>;
|
||||
#clock-cells = <0>;
|
||||
compatible = "ti,composite-gate-clock";
|
||||
clock-output-names = "usim_gate_fck";
|
||||
clocks = <&omap_96m_fck>;
|
||||
ti,bit-shift = <9>;
|
||||
};
|
||||
};
|
||||
|
||||
|
|
@ -172,14 +176,15 @@ clock@c40 {
|
|||
compatible = "ti,clksel";
|
||||
reg = <0xc40>;
|
||||
#clock-cells = <2>;
|
||||
#address-cells = <0>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
usim_mux_fck: clock-usim-mux-fck {
|
||||
usim_mux_fck: clock-usim-mux-fck@3 {
|
||||
reg = <3>;
|
||||
#clock-cells = <0>;
|
||||
compatible = "ti,composite-mux-clock";
|
||||
clock-output-names = "usim_mux_fck";
|
||||
clocks = <&sys_ck>, <&sys_d2_ck>, <&omap_96m_d2_fck>, <&omap_96m_d4_fck>, <&omap_96m_d8_fck>, <&omap_96m_d10_fck>, <&dpll5_m2_d4_ck>, <&dpll5_m2_d8_ck>, <&dpll5_m2_d16_ck>, <&dpll5_m2_d20_ck>;
|
||||
ti,bit-shift = <3>;
|
||||
ti,index-starts-at-one;
|
||||
};
|
||||
};
|
||||
|
|
@ -194,14 +199,15 @@ clock@c10 {
|
|||
compatible = "ti,clksel";
|
||||
reg = <0xc10>;
|
||||
#clock-cells = <2>;
|
||||
#address-cells = <0>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
usim_ick: clock-usim-ick {
|
||||
usim_ick: clock-usim-ick@9 {
|
||||
reg = <9>;
|
||||
#clock-cells = <0>;
|
||||
compatible = "ti,omap3-interface-clock";
|
||||
clock-output-names = "usim_ick";
|
||||
clocks = <&wkup_l4_ick>;
|
||||
ti,bit-shift = <9>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
|
|
@ -27,6 +27,7 @@
|
|||
#define UARTA_72165 UARTA_7278
|
||||
#define UARTA_7364 REG_PHYS_ADDR(0x40b000)
|
||||
#define UARTA_7366 UARTA_7364
|
||||
#define UARTA_74165 UARTA_7278
|
||||
#define UARTA_74371 REG_PHYS_ADDR(0x406b00)
|
||||
#define UARTA_7439 REG_PHYS_ADDR(0x40a900)
|
||||
#define UARTA_7445 REG_PHYS_ADDR(0x40ab00)
|
||||
|
|
@ -88,9 +89,10 @@ ARM_BE8( rev \rv, \rv )
|
|||
30: checkuart(\rp, \rv, 0x72780000, 7278)
|
||||
31: checkuart(\rp, \rv, 0x73640000, 7364)
|
||||
32: checkuart(\rp, \rv, 0x73660000, 7366)
|
||||
33: checkuart(\rp, \rv, 0x07437100, 74371)
|
||||
34: checkuart(\rp, \rv, 0x74390000, 7439)
|
||||
35: checkuart(\rp, \rv, 0x74450000, 7445)
|
||||
33: checkuart(\rp, \rv, 0x07416500, 74165)
|
||||
34: checkuart(\rp, \rv, 0x07437100, 74371)
|
||||
35: checkuart(\rp, \rv, 0x74390000, 7439)
|
||||
36: checkuart(\rp, \rv, 0x74450000, 7445)
|
||||
|
||||
/* No valid UART found */
|
||||
90: mov \rp, #0
|
||||
|
|
|
|||
|
|
@ -93,7 +93,6 @@ config ARCH_BCM_MOBILE
|
|||
select ARM_ERRATA_775420
|
||||
select ARM_GIC
|
||||
select GPIO_BCM_KONA
|
||||
select TICK_ONESHOT
|
||||
select HAVE_ARM_ARCH_TIMER
|
||||
select PINCTRL
|
||||
select ARCH_BCM_MOBILE_SMP if SMP
|
||||
|
|
|
|||
|
|
@ -185,16 +185,17 @@ partitions {
|
|||
#size-cells = <1>;
|
||||
|
||||
partition@0 {
|
||||
compatible = "nvmem-cells";
|
||||
label = "cferom";
|
||||
reg = <0x0 0x100000>;
|
||||
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
ranges = <0 0x0 0x100000>;
|
||||
nvmem-layout {
|
||||
compatible = "fixed-layout";
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
|
||||
base_mac_addr: mac@106a0 {
|
||||
reg = <0x106a0 0x6>;
|
||||
base_mac_addr: mac@106a0 {
|
||||
reg = <0x106a0 0x6>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -227,9 +227,6 @@ ethernet-switch@0 {
|
|||
brcm,num-gphy = <5>;
|
||||
brcm,num-rgmii-ports = <2>;
|
||||
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
ports: ports {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
|
|
|||
|
|
@ -243,7 +243,7 @@ plic: interrupt-controller@c000000 {
|
|||
};
|
||||
|
||||
pdma: dma-controller@3000000 {
|
||||
compatible = "sifive,fu540-c000-pdma", "sifive,pdma0";
|
||||
compatible = "microchip,mpfs-pdma", "sifive,pdma0";
|
||||
reg = <0x0 0x3000000 0x0 0x8000>;
|
||||
interrupt-parent = <&plic>;
|
||||
interrupts = <5 6>, <7 8>, <9 10>, <11 12>;
|
||||
|
|
@ -422,7 +422,7 @@ i2c1: i2c@2010b000 {
|
|||
can0: can@2010c000 {
|
||||
compatible = "microchip,mpfs-can";
|
||||
reg = <0x0 0x2010c000 0x0 0x1000>;
|
||||
clocks = <&clkcfg CLK_CAN0>;
|
||||
clocks = <&clkcfg CLK_CAN0>, <&clkcfg CLK_MSSPLL3>;
|
||||
interrupt-parent = <&plic>;
|
||||
interrupts = <56>;
|
||||
status = "disabled";
|
||||
|
|
@ -431,7 +431,7 @@ can0: can@2010c000 {
|
|||
can1: can@2010d000 {
|
||||
compatible = "microchip,mpfs-can";
|
||||
reg = <0x0 0x2010d000 0x0 0x1000>;
|
||||
clocks = <&clkcfg CLK_CAN1>;
|
||||
clocks = <&clkcfg CLK_CAN1>, <&clkcfg CLK_MSSPLL3>;
|
||||
interrupt-parent = <&plic>;
|
||||
interrupts = <57>;
|
||||
status = "disabled";
|
||||
|
|
|
|||
|
|
@ -11,3 +11,14 @@ / {
|
|||
model = "BeagleV Starlight Beta";
|
||||
compatible = "beagle,beaglev-starlight-jh7100-r0", "starfive,jh7100";
|
||||
};
|
||||
|
||||
&gmac {
|
||||
phy-handle = <&phy>;
|
||||
};
|
||||
|
||||
&mdio {
|
||||
phy: ethernet-phy@7 {
|
||||
reg = <7>;
|
||||
reset-gpios = <&gpio 63 GPIO_ACTIVE_LOW>;
|
||||
};
|
||||
};
|
||||
|
|
|
|||
|
|
@ -72,7 +72,91 @@ wifi_pwrseq: wifi-pwrseq {
|
|||
};
|
||||
};
|
||||
|
||||
&gmac {
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&gmac_pins>;
|
||||
phy-mode = "rgmii-id";
|
||||
status = "okay";
|
||||
|
||||
mdio: mdio {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
compatible = "snps,dwmac-mdio";
|
||||
};
|
||||
};
|
||||
|
||||
&gpio {
|
||||
gmac_pins: gmac-0 {
|
||||
gtxclk-pins {
|
||||
pins = <PAD_FUNC_SHARE(115)>;
|
||||
bias-pull-up;
|
||||
drive-strength = <35>;
|
||||
input-enable;
|
||||
input-schmitt-enable;
|
||||
slew-rate = <0>;
|
||||
};
|
||||
miitxclk-pins {
|
||||
pins = <PAD_FUNC_SHARE(116)>;
|
||||
bias-pull-up;
|
||||
drive-strength = <14>;
|
||||
input-enable;
|
||||
input-schmitt-disable;
|
||||
slew-rate = <0>;
|
||||
};
|
||||
tx-pins {
|
||||
pins = <PAD_FUNC_SHARE(117)>,
|
||||
<PAD_FUNC_SHARE(119)>,
|
||||
<PAD_FUNC_SHARE(120)>,
|
||||
<PAD_FUNC_SHARE(121)>,
|
||||
<PAD_FUNC_SHARE(122)>,
|
||||
<PAD_FUNC_SHARE(123)>,
|
||||
<PAD_FUNC_SHARE(124)>,
|
||||
<PAD_FUNC_SHARE(125)>,
|
||||
<PAD_FUNC_SHARE(126)>;
|
||||
bias-pull-up;
|
||||
drive-strength = <35>;
|
||||
input-disable;
|
||||
input-schmitt-disable;
|
||||
slew-rate = <0>;
|
||||
};
|
||||
rxclk-pins {
|
||||
pins = <PAD_FUNC_SHARE(127)>;
|
||||
bias-pull-up;
|
||||
drive-strength = <14>;
|
||||
input-enable;
|
||||
input-schmitt-disable;
|
||||
slew-rate = <6>;
|
||||
};
|
||||
rxer-pins {
|
||||
pins = <PAD_FUNC_SHARE(129)>;
|
||||
bias-pull-up;
|
||||
drive-strength = <14>;
|
||||
input-enable;
|
||||
input-schmitt-disable;
|
||||
slew-rate = <0>;
|
||||
};
|
||||
rx-pins {
|
||||
pins = <PAD_FUNC_SHARE(128)>,
|
||||
<PAD_FUNC_SHARE(130)>,
|
||||
<PAD_FUNC_SHARE(131)>,
|
||||
<PAD_FUNC_SHARE(132)>,
|
||||
<PAD_FUNC_SHARE(133)>,
|
||||
<PAD_FUNC_SHARE(134)>,
|
||||
<PAD_FUNC_SHARE(135)>,
|
||||
<PAD_FUNC_SHARE(136)>,
|
||||
<PAD_FUNC_SHARE(137)>,
|
||||
<PAD_FUNC_SHARE(138)>,
|
||||
<PAD_FUNC_SHARE(139)>,
|
||||
<PAD_FUNC_SHARE(140)>,
|
||||
<PAD_FUNC_SHARE(141)>;
|
||||
bias-pull-up;
|
||||
drive-strength = <14>;
|
||||
input-enable;
|
||||
input-schmitt-enable;
|
||||
slew-rate = <0>;
|
||||
};
|
||||
};
|
||||
|
||||
i2c0_pins: i2c0-0 {
|
||||
i2c-pins {
|
||||
pinmux = <GPIOMUX(62, GPO_LOW,
|
||||
|
|
@ -115,6 +199,24 @@ GPO_I2C2_PAD_SDA_OEN,
|
|||
};
|
||||
};
|
||||
|
||||
pwm_pins: pwm-0 {
|
||||
pwm-pins {
|
||||
pinmux = <GPIOMUX(7,
|
||||
GPO_PWM_PAD_OUT_BIT0,
|
||||
GPO_PWM_PAD_OE_N_BIT0,
|
||||
GPI_NONE)>,
|
||||
<GPIOMUX(5,
|
||||
GPO_PWM_PAD_OUT_BIT1,
|
||||
GPO_PWM_PAD_OE_N_BIT1,
|
||||
GPI_NONE)>;
|
||||
bias-disable;
|
||||
drive-strength = <35>;
|
||||
input-disable;
|
||||
input-schmitt-disable;
|
||||
slew-rate = <0>;
|
||||
};
|
||||
};
|
||||
|
||||
sdio0_pins: sdio0-0 {
|
||||
clk-pins {
|
||||
pinmux = <GPIOMUX(54, GPO_SDIO0_PAD_CCLK_OUT,
|
||||
|
|
@ -257,6 +359,12 @@ &osc_aud {
|
|||
clock-frequency = <27000000>;
|
||||
};
|
||||
|
||||
&pwm {
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&pwm_pins>;
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&sdio0 {
|
||||
broken-cd;
|
||||
bus-width = <4>;
|
||||
|
|
|
|||
|
|
@ -6,7 +6,6 @@
|
|||
|
||||
/dts-v1/;
|
||||
#include "jh7100-common.dtsi"
|
||||
#include <dt-bindings/gpio/gpio.h>
|
||||
|
||||
/ {
|
||||
model = "StarFive VisionFive V1";
|
||||
|
|
@ -18,3 +17,24 @@ gpio-restart {
|
|||
priority = <224>;
|
||||
};
|
||||
};
|
||||
|
||||
&gmac {
|
||||
phy-handle = <&phy>;
|
||||
};
|
||||
|
||||
/*
|
||||
* The board uses a Motorcomm YT8521 PHY supporting RGMII-ID, but requires
|
||||
* manual adjustment of the RX internal delay to work properly. The default
|
||||
* RX delay provided by the driver (1.95ns) is too high, but applying a 50%
|
||||
* reduction seems to mitigate the issue.
|
||||
*
|
||||
* It is worth noting the adjustment is not necessary on BeagleV Starlight SBC,
|
||||
* which uses a Microchip PHY. Hence, most likely the Motorcomm PHY is the one
|
||||
* responsible for the misbehaviour, not the GMAC.
|
||||
*/
|
||||
&mdio {
|
||||
phy: ethernet-phy@0 {
|
||||
reg = <0>;
|
||||
rx-internal-delay-ps = <900>;
|
||||
};
|
||||
};
|
||||
|
|
|
|||
|
|
@ -208,6 +208,37 @@ sdio1: mmc@10010000 {
|
|||
status = "disabled";
|
||||
};
|
||||
|
||||
gmac: ethernet@10020000 {
|
||||
compatible = "starfive,jh7100-dwmac", "snps,dwmac";
|
||||
reg = <0x0 0x10020000 0x0 0x10000>;
|
||||
clocks = <&clkgen JH7100_CLK_GMAC_ROOT_DIV>,
|
||||
<&clkgen JH7100_CLK_GMAC_AHB>,
|
||||
<&clkgen JH7100_CLK_GMAC_PTP_REF>,
|
||||
<&clkgen JH7100_CLK_GMAC_TX_INV>,
|
||||
<&clkgen JH7100_CLK_GMAC_GTX>;
|
||||
clock-names = "stmmaceth", "pclk", "ptp_ref", "tx", "gtx";
|
||||
resets = <&rstgen JH7100_RSTN_GMAC_AHB>;
|
||||
reset-names = "ahb";
|
||||
interrupts = <6>, <7>;
|
||||
interrupt-names = "macirq", "eth_wake_irq";
|
||||
max-frame-size = <9000>;
|
||||
snps,multicast-filter-bins = <32>;
|
||||
snps,perfect-filter-entries = <128>;
|
||||
starfive,syscon = <&sysmain 0x70 0>;
|
||||
rx-fifo-depth = <32768>;
|
||||
tx-fifo-depth = <16384>;
|
||||
snps,axi-config = <&stmmac_axi_setup>;
|
||||
snps,fixed-burst;
|
||||
snps,force_thresh_dma_mode;
|
||||
status = "disabled";
|
||||
|
||||
stmmac_axi_setup: stmmac-axi-config {
|
||||
snps,wr_osr_lmt = <16>;
|
||||
snps,rd_osr_lmt = <16>;
|
||||
snps,blen = <256 128 64 32 0 0 0>;
|
||||
};
|
||||
};
|
||||
|
||||
clkgen: clock-controller@11800000 {
|
||||
compatible = "starfive,jh7100-clkgen";
|
||||
reg = <0x0 0x11800000 0x0 0x10000>;
|
||||
|
|
@ -222,6 +253,11 @@ rstgen: reset-controller@11840000 {
|
|||
#reset-cells = <1>;
|
||||
};
|
||||
|
||||
sysmain: syscon@11850000 {
|
||||
compatible = "starfive,jh7100-sysmain", "syscon";
|
||||
reg = <0x0 0x11850000 0x0 0x10000>;
|
||||
};
|
||||
|
||||
i2c0: i2c@118b0000 {
|
||||
compatible = "snps,designware-i2c";
|
||||
reg = <0x0 0x118b0000 0x0 0x10000>;
|
||||
|
|
@ -324,6 +360,15 @@ watchdog@12480000 {
|
|||
<&rstgen JH7100_RSTN_WDT>;
|
||||
};
|
||||
|
||||
pwm: pwm@12490000 {
|
||||
compatible = "starfive,jh7100-pwm", "opencores,pwm-v1";
|
||||
reg = <0x0 0x12490000 0x0 0x10000>;
|
||||
clocks = <&clkgen JH7100_CLK_PWM_APB>;
|
||||
resets = <&rstgen JH7100_RSTN_PWM_APB>;
|
||||
#pwm-cells = <3>;
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
sfctemp: temperature-sensor@124a0000 {
|
||||
compatible = "starfive,jh7100-temp";
|
||||
reg = <0x0 0x124a0000 0x0 0x10000>;
|
||||
|
|
|
|||
|
|
@ -125,6 +125,55 @@ &tdm_ext {
|
|||
clock-frequency = <49152000>;
|
||||
};
|
||||
|
||||
&camss {
|
||||
assigned-clocks = <&ispcrg JH7110_ISPCLK_DOM4_APB_FUNC>,
|
||||
<&ispcrg JH7110_ISPCLK_MIPI_RX0_PXL>;
|
||||
assigned-clock-rates = <49500000>, <198000000>;
|
||||
status = "okay";
|
||||
|
||||
ports {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
port@0 {
|
||||
reg = <0>;
|
||||
};
|
||||
|
||||
port@1 {
|
||||
reg = <1>;
|
||||
|
||||
camss_from_csi2rx: endpoint {
|
||||
remote-endpoint = <&csi2rx_to_camss>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
&csi2rx {
|
||||
assigned-clocks = <&ispcrg JH7110_ISPCLK_VIN_SYS>;
|
||||
assigned-clock-rates = <297000000>;
|
||||
status = "okay";
|
||||
|
||||
ports {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
port@0 {
|
||||
reg = <0>;
|
||||
|
||||
/* remote MIPI sensor endpoint */
|
||||
};
|
||||
|
||||
port@1 {
|
||||
reg = <1>;
|
||||
|
||||
csi2rx_to_camss: endpoint {
|
||||
remote-endpoint = <&camss_from_csi2rx>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
&gmac0 {
|
||||
phy-handle = <&phy0>;
|
||||
phy-mode = "rgmii-id";
|
||||
|
|
@ -323,6 +372,12 @@ reserved-data@600000 {
|
|||
};
|
||||
};
|
||||
|
||||
&pwm {
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&pwm_pins>;
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&spi0 {
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&spi0_pins>;
|
||||
|
|
@ -513,6 +568,22 @@ GPOEN_ENABLE,
|
|||
};
|
||||
};
|
||||
|
||||
pwm_pins: pwm-0 {
|
||||
pwm-pins {
|
||||
pinmux = <GPIOMUX(46, GPOUT_SYS_PWM_CHANNEL0,
|
||||
GPOEN_SYS_PWM0_CHANNEL0,
|
||||
GPI_NONE)>,
|
||||
<GPIOMUX(59, GPOUT_SYS_PWM_CHANNEL1,
|
||||
GPOEN_SYS_PWM0_CHANNEL1,
|
||||
GPI_NONE)>;
|
||||
bias-disable;
|
||||
drive-strength = <12>;
|
||||
input-disable;
|
||||
input-schmitt-disable;
|
||||
slew-rate = <0>;
|
||||
};
|
||||
};
|
||||
|
||||
spi0_pins: spi0-0 {
|
||||
mosi-pins {
|
||||
pinmux = <GPIOMUX(52, GPOUT_SYS_SPI0_TXD,
|
||||
|
|
|
|||
|
|
@ -829,6 +829,15 @@ i2stx1: i2s@120c0000 {
|
|||
status = "disabled";
|
||||
};
|
||||
|
||||
pwm: pwm@120d0000 {
|
||||
compatible = "starfive,jh7110-pwm", "opencores,pwm-v1";
|
||||
reg = <0x0 0x120d0000 0x0 0x10000>;
|
||||
clocks = <&syscrg JH7110_SYSCLK_PWM_APB>;
|
||||
resets = <&syscrg JH7110_SYSRST_PWM_APB>;
|
||||
#pwm-cells = <3>;
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
sfctemp: temperature-sensor@120e0000 {
|
||||
compatible = "starfive,jh7110-temp";
|
||||
reg = <0x0 0x120e0000 0x0 0x10000>;
|
||||
|
|
@ -1104,6 +1113,32 @@ pwrc: power-controller@17030000 {
|
|||
#power-domain-cells = <1>;
|
||||
};
|
||||
|
||||
csi2rx: csi@19800000 {
|
||||
compatible = "starfive,jh7110-csi2rx", "cdns,csi2rx";
|
||||
reg = <0x0 0x19800000 0x0 0x10000>;
|
||||
clocks = <&ispcrg JH7110_ISPCLK_VIN_SYS>,
|
||||
<&ispcrg JH7110_ISPCLK_VIN_APB>,
|
||||
<&ispcrg JH7110_ISPCLK_VIN_PIXEL_IF0>,
|
||||
<&ispcrg JH7110_ISPCLK_VIN_PIXEL_IF1>,
|
||||
<&ispcrg JH7110_ISPCLK_VIN_PIXEL_IF2>,
|
||||
<&ispcrg JH7110_ISPCLK_VIN_PIXEL_IF3>;
|
||||
clock-names = "sys_clk", "p_clk",
|
||||
"pixel_if0_clk", "pixel_if1_clk",
|
||||
"pixel_if2_clk", "pixel_if3_clk";
|
||||
resets = <&ispcrg JH7110_ISPRST_VIN_SYS>,
|
||||
<&ispcrg JH7110_ISPRST_VIN_APB>,
|
||||
<&ispcrg JH7110_ISPRST_VIN_PIXEL_IF0>,
|
||||
<&ispcrg JH7110_ISPRST_VIN_PIXEL_IF1>,
|
||||
<&ispcrg JH7110_ISPRST_VIN_PIXEL_IF2>,
|
||||
<&ispcrg JH7110_ISPRST_VIN_PIXEL_IF3>;
|
||||
reset-names = "sys", "reg_bank",
|
||||
"pixel_if0", "pixel_if1",
|
||||
"pixel_if2", "pixel_if3";
|
||||
phys = <&csi_phy>;
|
||||
phy-names = "dphy";
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
ispcrg: clock-controller@19810000 {
|
||||
compatible = "starfive,jh7110-ispcrg";
|
||||
reg = <0x0 0x19810000 0x0 0x10000>;
|
||||
|
|
@ -1121,6 +1156,47 @@ ispcrg: clock-controller@19810000 {
|
|||
power-domains = <&pwrc JH7110_PD_ISP>;
|
||||
};
|
||||
|
||||
csi_phy: phy@19820000 {
|
||||
compatible = "starfive,jh7110-dphy-rx";
|
||||
reg = <0x0 0x19820000 0x0 0x10000>;
|
||||
clocks = <&ispcrg JH7110_ISPCLK_M31DPHY_CFG_IN>,
|
||||
<&ispcrg JH7110_ISPCLK_M31DPHY_REF_IN>,
|
||||
<&ispcrg JH7110_ISPCLK_M31DPHY_TX_ESC_LAN0>;
|
||||
clock-names = "cfg", "ref", "tx";
|
||||
resets = <&ispcrg JH7110_ISPRST_M31DPHY_HW>,
|
||||
<&ispcrg JH7110_ISPRST_M31DPHY_B09_AON>;
|
||||
power-domains = <&aon_syscon JH7110_AON_PD_DPHY_RX>;
|
||||
#phy-cells = <0>;
|
||||
};
|
||||
|
||||
camss: isp@19840000 {
|
||||
compatible = "starfive,jh7110-camss";
|
||||
reg = <0x0 0x19840000 0x0 0x10000>,
|
||||
<0x0 0x19870000 0x0 0x30000>;
|
||||
reg-names = "syscon", "isp";
|
||||
clocks = <&ispcrg JH7110_ISPCLK_DOM4_APB_FUNC>,
|
||||
<&ispcrg JH7110_ISPCLK_ISPV2_TOP_WRAPPER_C>,
|
||||
<&ispcrg JH7110_ISPCLK_DVP_INV>,
|
||||
<&ispcrg JH7110_ISPCLK_VIN_P_AXI_WR>,
|
||||
<&ispcrg JH7110_ISPCLK_MIPI_RX0_PXL>,
|
||||
<&syscrg JH7110_SYSCLK_ISP_TOP_CORE>,
|
||||
<&syscrg JH7110_SYSCLK_ISP_TOP_AXI>;
|
||||
clock-names = "apb_func", "wrapper_clk_c", "dvp_inv",
|
||||
"axiwr", "mipi_rx0_pxl", "ispcore_2x",
|
||||
"isp_axi";
|
||||
resets = <&ispcrg JH7110_ISPRST_ISPV2_TOP_WRAPPER_P>,
|
||||
<&ispcrg JH7110_ISPRST_ISPV2_TOP_WRAPPER_C>,
|
||||
<&ispcrg JH7110_ISPRST_VIN_P_AXI_RD>,
|
||||
<&ispcrg JH7110_ISPRST_VIN_P_AXI_WR>,
|
||||
<&syscrg JH7110_SYSRST_ISP_TOP>,
|
||||
<&syscrg JH7110_SYSRST_ISP_TOP_AXI>;
|
||||
reset-names = "wrapper_p", "wrapper_c", "axird",
|
||||
"axiwr", "isp_top_n", "isp_top_axi";
|
||||
power-domains = <&pwrc JH7110_PD_ISP>;
|
||||
interrupts = <92>, <87>, <90>, <88>;
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
voutcrg: clock-controller@295c0000 {
|
||||
compatible = "starfive,jh7110-voutcrg";
|
||||
reg = <0x0 0x295c0000 0x0 0x10000>;
|
||||
|
|
|
|||
|
|
@ -63,6 +63,7 @@ config S390
|
|||
select ARCH_ENABLE_MEMORY_HOTREMOVE
|
||||
select ARCH_ENABLE_SPLIT_PMD_PTLOCK if PGTABLE_LEVELS > 2
|
||||
select ARCH_HAS_CURRENT_STACK_POINTER
|
||||
select ARCH_HAS_DEBUG_VIRTUAL
|
||||
select ARCH_HAS_DEBUG_VM_PGTABLE
|
||||
select ARCH_HAS_DEBUG_WX
|
||||
select ARCH_HAS_DEVMEM_IS_ALLOWED
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@ KBUILD_AFLAGS_DECOMPRESSOR += $(if $(CONFIG_DEBUG_INFO),$(aflags_dwarf))
|
|||
endif
|
||||
KBUILD_CFLAGS_DECOMPRESSOR := $(CLANG_FLAGS) -m64 -O2 -mpacked-stack
|
||||
KBUILD_CFLAGS_DECOMPRESSOR += -DDISABLE_BRANCH_PROFILING -D__NO_FORTIFY
|
||||
KBUILD_CFLAGS_DECOMPRESSOR += -D__DECOMPRESSOR
|
||||
KBUILD_CFLAGS_DECOMPRESSOR += -fno-delete-null-pointer-checks -msoft-float -mbackchain
|
||||
KBUILD_CFLAGS_DECOMPRESSOR += -fno-asynchronous-unwind-tables
|
||||
KBUILD_CFLAGS_DECOMPRESSOR += -ffreestanding
|
||||
|
|
|
|||
|
|
@ -810,6 +810,7 @@ CONFIG_DEBUG_OBJECTS_PERCPU_COUNTER=y
|
|||
CONFIG_DEBUG_STACK_USAGE=y
|
||||
CONFIG_DEBUG_VM=y
|
||||
CONFIG_DEBUG_VM_PGFLAGS=y
|
||||
CONFIG_DEBUG_VIRTUAL=y
|
||||
CONFIG_DEBUG_MEMORY_INIT=y
|
||||
CONFIG_MEMORY_NOTIFIER_ERROR_INJECT=m
|
||||
CONFIG_DEBUG_PER_CPU_MAPS=y
|
||||
|
|
|
|||
|
|
@ -217,7 +217,8 @@ extern void ccw_device_destroy_console(struct ccw_device *);
|
|||
extern int ccw_device_enable_console(struct ccw_device *);
|
||||
extern void ccw_device_wait_idle(struct ccw_device *);
|
||||
|
||||
extern void *ccw_device_dma_zalloc(struct ccw_device *cdev, size_t size);
|
||||
extern void *ccw_device_dma_zalloc(struct ccw_device *cdev, size_t size,
|
||||
dma32_t *dma_handle);
|
||||
extern void ccw_device_dma_free(struct ccw_device *cdev,
|
||||
void *cpu_addr, size_t size);
|
||||
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@
|
|||
|
||||
#include <linux/bitops.h>
|
||||
#include <linux/genalloc.h>
|
||||
#include <asm/dma-types.h>
|
||||
#include <asm/types.h>
|
||||
#include <asm/tpi.h>
|
||||
|
||||
|
|
@ -32,7 +33,7 @@ struct ccw1 {
|
|||
__u8 cmd_code;
|
||||
__u8 flags;
|
||||
__u16 count;
|
||||
__u32 cda;
|
||||
dma32_t cda;
|
||||
} __attribute__ ((packed,aligned(8)));
|
||||
|
||||
/**
|
||||
|
|
@ -152,8 +153,8 @@ struct sublog {
|
|||
struct esw0 {
|
||||
struct sublog sublog;
|
||||
struct erw erw;
|
||||
__u32 faddr[2];
|
||||
__u32 saddr;
|
||||
dma32_t faddr[2];
|
||||
dma32_t saddr;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
/**
|
||||
|
|
@ -364,6 +365,8 @@ extern struct device *cio_get_dma_css_dev(void);
|
|||
|
||||
void *cio_gp_dma_zalloc(struct gen_pool *gp_dma, struct device *dma_dev,
|
||||
size_t size);
|
||||
void *__cio_gp_dma_zalloc(struct gen_pool *gp_dma, struct device *dma_dev,
|
||||
size_t size, dma32_t *dma_handle);
|
||||
void cio_gp_dma_free(struct gen_pool *gp_dma, void *cpu_addr, size_t size);
|
||||
void cio_gp_dma_destroy(struct gen_pool *gp_dma, struct device *dma_dev);
|
||||
struct gen_pool *cio_gp_dma_create(struct device *dma_dev, int nr_pages);
|
||||
|
|
|
|||
103
arch/s390/include/asm/dma-types.h
Normal file
103
arch/s390/include/asm/dma-types.h
Normal file
|
|
@ -0,0 +1,103 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
|
||||
#ifndef _ASM_S390_DMA_TYPES_H_
|
||||
#define _ASM_S390_DMA_TYPES_H_
|
||||
|
||||
#include <linux/types.h>
|
||||
#include <linux/io.h>
|
||||
|
||||
/*
|
||||
* typedef dma32_t
|
||||
* Contains a 31 bit absolute address to a DMA capable piece of storage.
|
||||
*
|
||||
* For CIO, DMA addresses are always absolute addresses. These addresses tend
|
||||
* to be used in architectured memory blocks (like ORB, IDAW, MIDAW). Under
|
||||
* certain circumstances 31 bit wide addresses must be used because the
|
||||
* address must fit in 31 bits.
|
||||
*
|
||||
* This type is to be used when such fields can be modelled as 32 bit wide.
|
||||
*/
|
||||
typedef u32 __bitwise dma32_t;
|
||||
|
||||
/*
|
||||
* typedef dma64_t
|
||||
* Contains a 64 bit absolute address to a DMA capable piece of storage.
|
||||
*
|
||||
* For CIO, DMA addresses are always absolute addresses. These addresses tend
|
||||
* to be used in architectured memory blocks (like ORB, IDAW, MIDAW).
|
||||
*
|
||||
* This type is to be used to model such 64 bit wide fields.
|
||||
*/
|
||||
typedef u64 __bitwise dma64_t;
|
||||
|
||||
/*
|
||||
* Although DMA addresses should be obtained using the DMA API, in cases when
|
||||
* it is known that the first argument holds a virtual address that points to
|
||||
* DMA-able 31 bit addressable storage, then this function can be safely used.
|
||||
*/
|
||||
static inline dma32_t virt_to_dma32(void *ptr)
|
||||
{
|
||||
return (__force dma32_t)__pa32(ptr);
|
||||
}
|
||||
|
||||
static inline void *dma32_to_virt(dma32_t addr)
|
||||
{
|
||||
return __va((__force unsigned long)addr);
|
||||
}
|
||||
|
||||
static inline dma32_t u32_to_dma32(u32 addr)
|
||||
{
|
||||
return (__force dma32_t)addr;
|
||||
}
|
||||
|
||||
static inline u32 dma32_to_u32(dma32_t addr)
|
||||
{
|
||||
return (__force u32)addr;
|
||||
}
|
||||
|
||||
static inline dma32_t dma32_add(dma32_t a, u32 b)
|
||||
{
|
||||
return (__force dma32_t)((__force u32)a + b);
|
||||
}
|
||||
|
||||
static inline dma32_t dma32_and(dma32_t a, u32 b)
|
||||
{
|
||||
return (__force dma32_t)((__force u32)a & b);
|
||||
}
|
||||
|
||||
/*
|
||||
* Although DMA addresses should be obtained using the DMA API, in cases when
|
||||
* it is known that the first argument holds a virtual address that points to
|
||||
* DMA-able storage, then this function can be safely used.
|
||||
*/
|
||||
static inline dma64_t virt_to_dma64(void *ptr)
|
||||
{
|
||||
return (__force dma64_t)__pa(ptr);
|
||||
}
|
||||
|
||||
static inline void *dma64_to_virt(dma64_t addr)
|
||||
{
|
||||
return __va((__force unsigned long)addr);
|
||||
}
|
||||
|
||||
static inline dma64_t u64_to_dma64(u64 addr)
|
||||
{
|
||||
return (__force dma64_t)addr;
|
||||
}
|
||||
|
||||
static inline u64 dma64_to_u64(dma64_t addr)
|
||||
{
|
||||
return (__force u64)addr;
|
||||
}
|
||||
|
||||
static inline dma64_t dma64_add(dma64_t a, u64 b)
|
||||
{
|
||||
return (__force dma64_t)((__force u64)a + b);
|
||||
}
|
||||
|
||||
static inline dma64_t dma64_and(dma64_t a, u64 b)
|
||||
{
|
||||
return (__force dma64_t)((__force u64)a & b);
|
||||
}
|
||||
|
||||
#endif /* _ASM_S390_DMA_TYPES_H_ */
|
||||
|
|
@ -5,6 +5,7 @@
|
|||
#include <linux/types.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/blk_types.h>
|
||||
#include <asm/dma-types.h>
|
||||
|
||||
struct arqb {
|
||||
u64 data;
|
||||
|
|
@ -45,7 +46,7 @@ struct msb {
|
|||
u16:12;
|
||||
u16 bs:4;
|
||||
u32 blk_count;
|
||||
u64 data_addr;
|
||||
dma64_t data_addr;
|
||||
u64 scm_addr;
|
||||
u64:64;
|
||||
} __packed;
|
||||
|
|
@ -54,7 +55,7 @@ struct aidaw {
|
|||
u8 flags;
|
||||
u32 :24;
|
||||
u32 :32;
|
||||
u64 data_addr;
|
||||
dma64_t data_addr;
|
||||
} __packed;
|
||||
|
||||
#define MSB_OC_CLEAR 0
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@
|
|||
#define _ASM_S390_FCX_H
|
||||
|
||||
#include <linux/types.h>
|
||||
#include <asm/dma-types.h>
|
||||
|
||||
#define TCW_FORMAT_DEFAULT 0
|
||||
#define TCW_TIDAW_FORMAT_DEFAULT 0
|
||||
|
|
@ -43,16 +44,16 @@ struct tcw {
|
|||
u32 r:1;
|
||||
u32 w:1;
|
||||
u32 :16;
|
||||
u64 output;
|
||||
u64 input;
|
||||
u64 tsb;
|
||||
u64 tccb;
|
||||
dma64_t output;
|
||||
dma64_t input;
|
||||
dma64_t tsb;
|
||||
dma64_t tccb;
|
||||
u32 output_count;
|
||||
u32 input_count;
|
||||
u32 :32;
|
||||
u32 :32;
|
||||
u32 :32;
|
||||
u32 intrg;
|
||||
dma32_t intrg;
|
||||
} __attribute__ ((packed, aligned(64)));
|
||||
|
||||
#define TIDAW_FLAGS_LAST (1 << (7 - 0))
|
||||
|
|
@ -73,7 +74,7 @@ struct tidaw {
|
|||
u32 flags:8;
|
||||
u32 :24;
|
||||
u32 count;
|
||||
u64 addr;
|
||||
dma64_t addr;
|
||||
} __attribute__ ((packed, aligned(16)));
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
/*
|
||||
* Author(s)......: Holger Smolinski <Holger.Smolinski@de.ibm.com>
|
||||
* Martin Schwidefsky <schwidefsky@de.ibm.com>
|
||||
* Bugreports.to..: <Linux390@de.ibm.com>
|
||||
|
|
@ -17,32 +17,37 @@
|
|||
#include <linux/err.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/slab.h>
|
||||
#include <asm/cio.h>
|
||||
#include <linux/uaccess.h>
|
||||
#include <asm/dma-types.h>
|
||||
#include <asm/cio.h>
|
||||
|
||||
#define IDA_SIZE_LOG 12 /* 11 for 2k , 12 for 4k */
|
||||
#define IDA_BLOCK_SIZE (1L<<IDA_SIZE_LOG)
|
||||
#define IDA_SIZE_SHIFT 12
|
||||
#define IDA_BLOCK_SIZE (1UL << IDA_SIZE_SHIFT)
|
||||
|
||||
#define IDA_2K_SIZE_LOG 11
|
||||
#define IDA_2K_BLOCK_SIZE (1L << IDA_2K_SIZE_LOG)
|
||||
#define IDA_2K_SIZE_SHIFT 11
|
||||
#define IDA_2K_BLOCK_SIZE (1UL << IDA_2K_SIZE_SHIFT)
|
||||
|
||||
/*
|
||||
* Test if an address/length pair needs an idal list.
|
||||
*/
|
||||
static inline int
|
||||
idal_is_needed(void *vaddr, unsigned int length)
|
||||
static inline bool idal_is_needed(void *vaddr, unsigned int length)
|
||||
{
|
||||
return ((__pa(vaddr) + length - 1) >> 31) != 0;
|
||||
}
|
||||
dma64_t paddr = virt_to_dma64(vaddr);
|
||||
|
||||
return (((__force unsigned long)(paddr) + length - 1) >> 31) != 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return the number of idal words needed for an address/length pair.
|
||||
*/
|
||||
static inline unsigned int idal_nr_words(void *vaddr, unsigned int length)
|
||||
{
|
||||
return ((__pa(vaddr) & (IDA_BLOCK_SIZE-1)) + length +
|
||||
(IDA_BLOCK_SIZE-1)) >> IDA_SIZE_LOG;
|
||||
unsigned int cidaw;
|
||||
|
||||
cidaw = (unsigned long)vaddr & (IDA_BLOCK_SIZE - 1);
|
||||
cidaw += length + IDA_BLOCK_SIZE - 1;
|
||||
cidaw >>= IDA_SIZE_SHIFT;
|
||||
return cidaw;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -50,26 +55,27 @@ static inline unsigned int idal_nr_words(void *vaddr, unsigned int length)
|
|||
*/
|
||||
static inline unsigned int idal_2k_nr_words(void *vaddr, unsigned int length)
|
||||
{
|
||||
return ((__pa(vaddr) & (IDA_2K_BLOCK_SIZE - 1)) + length +
|
||||
(IDA_2K_BLOCK_SIZE - 1)) >> IDA_2K_SIZE_LOG;
|
||||
unsigned int cidaw;
|
||||
|
||||
cidaw = (unsigned long)vaddr & (IDA_2K_BLOCK_SIZE - 1);
|
||||
cidaw += length + IDA_2K_BLOCK_SIZE - 1;
|
||||
cidaw >>= IDA_2K_SIZE_SHIFT;
|
||||
return cidaw;
|
||||
}
|
||||
|
||||
/*
|
||||
* Create the list of idal words for an address/length pair.
|
||||
*/
|
||||
static inline unsigned long *idal_create_words(unsigned long *idaws,
|
||||
void *vaddr, unsigned int length)
|
||||
static inline dma64_t *idal_create_words(dma64_t *idaws, void *vaddr, unsigned int length)
|
||||
{
|
||||
unsigned long paddr;
|
||||
dma64_t paddr = virt_to_dma64(vaddr);
|
||||
unsigned int cidaw;
|
||||
|
||||
paddr = __pa(vaddr);
|
||||
cidaw = ((paddr & (IDA_BLOCK_SIZE-1)) + length +
|
||||
(IDA_BLOCK_SIZE-1)) >> IDA_SIZE_LOG;
|
||||
*idaws++ = paddr;
|
||||
paddr &= -IDA_BLOCK_SIZE;
|
||||
cidaw = idal_nr_words(vaddr, length);
|
||||
paddr = dma64_and(paddr, -IDA_BLOCK_SIZE);
|
||||
while (--cidaw > 0) {
|
||||
paddr += IDA_BLOCK_SIZE;
|
||||
paddr = dma64_add(paddr, IDA_BLOCK_SIZE);
|
||||
*idaws++ = paddr;
|
||||
}
|
||||
return idaws;
|
||||
|
|
@ -79,36 +85,33 @@ static inline unsigned long *idal_create_words(unsigned long *idaws,
|
|||
* Sets the address of the data in CCW.
|
||||
* If necessary it allocates an IDAL and sets the appropriate flags.
|
||||
*/
|
||||
static inline int
|
||||
set_normalized_cda(struct ccw1 * ccw, void *vaddr)
|
||||
static inline int set_normalized_cda(struct ccw1 *ccw, void *vaddr)
|
||||
{
|
||||
unsigned int nridaws;
|
||||
unsigned long *idal;
|
||||
dma64_t *idal;
|
||||
|
||||
if (ccw->flags & CCW_FLAG_IDA)
|
||||
return -EINVAL;
|
||||
nridaws = idal_nr_words(vaddr, ccw->count);
|
||||
if (nridaws > 0) {
|
||||
idal = kmalloc(nridaws * sizeof(unsigned long),
|
||||
GFP_ATOMIC | GFP_DMA );
|
||||
if (idal == NULL)
|
||||
idal = kcalloc(nridaws, sizeof(*idal), GFP_ATOMIC | GFP_DMA);
|
||||
if (!idal)
|
||||
return -ENOMEM;
|
||||
idal_create_words(idal, vaddr, ccw->count);
|
||||
ccw->flags |= CCW_FLAG_IDA;
|
||||
vaddr = idal;
|
||||
}
|
||||
ccw->cda = (__u32)(unsigned long) vaddr;
|
||||
ccw->cda = virt_to_dma32(vaddr);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Releases any allocated IDAL related to the CCW.
|
||||
*/
|
||||
static inline void
|
||||
clear_normalized_cda(struct ccw1 * ccw)
|
||||
static inline void clear_normalized_cda(struct ccw1 *ccw)
|
||||
{
|
||||
if (ccw->flags & CCW_FLAG_IDA) {
|
||||
kfree((void *)(unsigned long) ccw->cda);
|
||||
kfree(dma32_to_virt(ccw->cda));
|
||||
ccw->flags &= ~CCW_FLAG_IDA;
|
||||
}
|
||||
ccw->cda = 0;
|
||||
|
|
@ -120,125 +123,138 @@ clear_normalized_cda(struct ccw1 * ccw)
|
|||
struct idal_buffer {
|
||||
size_t size;
|
||||
size_t page_order;
|
||||
void *data[];
|
||||
dma64_t data[];
|
||||
};
|
||||
|
||||
/*
|
||||
* Allocate an idal buffer
|
||||
*/
|
||||
static inline struct idal_buffer *
|
||||
idal_buffer_alloc(size_t size, int page_order)
|
||||
static inline struct idal_buffer *idal_buffer_alloc(size_t size, int page_order)
|
||||
{
|
||||
struct idal_buffer *ib;
|
||||
int nr_chunks, nr_ptrs, i;
|
||||
struct idal_buffer *ib;
|
||||
void *vaddr;
|
||||
|
||||
nr_ptrs = (size + IDA_BLOCK_SIZE - 1) >> IDA_SIZE_LOG;
|
||||
nr_chunks = (4096 << page_order) >> IDA_SIZE_LOG;
|
||||
nr_ptrs = (size + IDA_BLOCK_SIZE - 1) >> IDA_SIZE_SHIFT;
|
||||
nr_chunks = (PAGE_SIZE << page_order) >> IDA_SIZE_SHIFT;
|
||||
ib = kmalloc(struct_size(ib, data, nr_ptrs), GFP_DMA | GFP_KERNEL);
|
||||
if (ib == NULL)
|
||||
if (!ib)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
ib->size = size;
|
||||
ib->page_order = page_order;
|
||||
for (i = 0; i < nr_ptrs; i++) {
|
||||
if ((i & (nr_chunks - 1)) != 0) {
|
||||
ib->data[i] = ib->data[i-1] + IDA_BLOCK_SIZE;
|
||||
if (i & (nr_chunks - 1)) {
|
||||
ib->data[i] = dma64_add(ib->data[i - 1], IDA_BLOCK_SIZE);
|
||||
continue;
|
||||
}
|
||||
ib->data[i] = (void *)
|
||||
__get_free_pages(GFP_KERNEL, page_order);
|
||||
if (ib->data[i] != NULL)
|
||||
continue;
|
||||
// Not enough memory
|
||||
while (i >= nr_chunks) {
|
||||
i -= nr_chunks;
|
||||
free_pages((unsigned long) ib->data[i],
|
||||
ib->page_order);
|
||||
}
|
||||
kfree(ib);
|
||||
return ERR_PTR(-ENOMEM);
|
||||
vaddr = (void *)__get_free_pages(GFP_KERNEL, page_order);
|
||||
if (!vaddr)
|
||||
goto error;
|
||||
ib->data[i] = virt_to_dma64(vaddr);
|
||||
}
|
||||
return ib;
|
||||
error:
|
||||
while (i >= nr_chunks) {
|
||||
i -= nr_chunks;
|
||||
vaddr = dma64_to_virt(ib->data[i]);
|
||||
free_pages((unsigned long)vaddr, ib->page_order);
|
||||
}
|
||||
kfree(ib);
|
||||
return ERR_PTR(-ENOMEM);
|
||||
}
|
||||
|
||||
/*
|
||||
* Free an idal buffer.
|
||||
*/
|
||||
static inline void
|
||||
idal_buffer_free(struct idal_buffer *ib)
|
||||
static inline void idal_buffer_free(struct idal_buffer *ib)
|
||||
{
|
||||
int nr_chunks, nr_ptrs, i;
|
||||
void *vaddr;
|
||||
|
||||
nr_ptrs = (ib->size + IDA_BLOCK_SIZE - 1) >> IDA_SIZE_LOG;
|
||||
nr_chunks = (4096 << ib->page_order) >> IDA_SIZE_LOG;
|
||||
for (i = 0; i < nr_ptrs; i += nr_chunks)
|
||||
free_pages((unsigned long) ib->data[i], ib->page_order);
|
||||
nr_ptrs = (ib->size + IDA_BLOCK_SIZE - 1) >> IDA_SIZE_SHIFT;
|
||||
nr_chunks = (PAGE_SIZE << ib->page_order) >> IDA_SIZE_SHIFT;
|
||||
for (i = 0; i < nr_ptrs; i += nr_chunks) {
|
||||
vaddr = dma64_to_virt(ib->data[i]);
|
||||
free_pages((unsigned long)vaddr, ib->page_order);
|
||||
}
|
||||
kfree(ib);
|
||||
}
|
||||
|
||||
/*
|
||||
* Test if a idal list is really needed.
|
||||
*/
|
||||
static inline int
|
||||
__idal_buffer_is_needed(struct idal_buffer *ib)
|
||||
static inline bool __idal_buffer_is_needed(struct idal_buffer *ib)
|
||||
{
|
||||
return ib->size > (4096ul << ib->page_order) ||
|
||||
idal_is_needed(ib->data[0], ib->size);
|
||||
if (ib->size > (PAGE_SIZE << ib->page_order))
|
||||
return true;
|
||||
return idal_is_needed(dma64_to_virt(ib->data[0]), ib->size);
|
||||
}
|
||||
|
||||
/*
|
||||
* Set channel data address to idal buffer.
|
||||
*/
|
||||
static inline void
|
||||
idal_buffer_set_cda(struct idal_buffer *ib, struct ccw1 *ccw)
|
||||
static inline void idal_buffer_set_cda(struct idal_buffer *ib, struct ccw1 *ccw)
|
||||
{
|
||||
void *vaddr;
|
||||
|
||||
if (__idal_buffer_is_needed(ib)) {
|
||||
// setup idals;
|
||||
ccw->cda = (u32)(addr_t) ib->data;
|
||||
/* Setup idals */
|
||||
ccw->cda = virt_to_dma32(ib->data);
|
||||
ccw->flags |= CCW_FLAG_IDA;
|
||||
} else
|
||||
// we do not need idals - use direct addressing
|
||||
ccw->cda = (u32)(addr_t) ib->data[0];
|
||||
} else {
|
||||
/*
|
||||
* No idals needed - use direct addressing. Convert from
|
||||
* dma64_t to virt and then to dma32_t only because of type
|
||||
* checking. The physical address is known to be below 2GB.
|
||||
*/
|
||||
vaddr = dma64_to_virt(ib->data[0]);
|
||||
ccw->cda = virt_to_dma32(vaddr);
|
||||
}
|
||||
ccw->count = ib->size;
|
||||
}
|
||||
|
||||
/*
|
||||
* Copy count bytes from an idal buffer to user memory
|
||||
*/
|
||||
static inline size_t
|
||||
idal_buffer_to_user(struct idal_buffer *ib, void __user *to, size_t count)
|
||||
static inline size_t idal_buffer_to_user(struct idal_buffer *ib, void __user *to, size_t count)
|
||||
{
|
||||
size_t left;
|
||||
void *vaddr;
|
||||
int i;
|
||||
|
||||
BUG_ON(count > ib->size);
|
||||
for (i = 0; count > IDA_BLOCK_SIZE; i++) {
|
||||
left = copy_to_user(to, ib->data[i], IDA_BLOCK_SIZE);
|
||||
vaddr = dma64_to_virt(ib->data[i]);
|
||||
left = copy_to_user(to, vaddr, IDA_BLOCK_SIZE);
|
||||
if (left)
|
||||
return left + count - IDA_BLOCK_SIZE;
|
||||
to = (void __user *) to + IDA_BLOCK_SIZE;
|
||||
to = (void __user *)to + IDA_BLOCK_SIZE;
|
||||
count -= IDA_BLOCK_SIZE;
|
||||
}
|
||||
return copy_to_user(to, ib->data[i], count);
|
||||
vaddr = dma64_to_virt(ib->data[i]);
|
||||
return copy_to_user(to, vaddr, count);
|
||||
}
|
||||
|
||||
/*
|
||||
* Copy count bytes from user memory to an idal buffer
|
||||
*/
|
||||
static inline size_t
|
||||
idal_buffer_from_user(struct idal_buffer *ib, const void __user *from, size_t count)
|
||||
static inline size_t idal_buffer_from_user(struct idal_buffer *ib, const void __user *from, size_t count)
|
||||
{
|
||||
size_t left;
|
||||
void *vaddr;
|
||||
int i;
|
||||
|
||||
BUG_ON(count > ib->size);
|
||||
for (i = 0; count > IDA_BLOCK_SIZE; i++) {
|
||||
left = copy_from_user(ib->data[i], from, IDA_BLOCK_SIZE);
|
||||
vaddr = dma64_to_virt(ib->data[i]);
|
||||
left = copy_from_user(vaddr, from, IDA_BLOCK_SIZE);
|
||||
if (left)
|
||||
return left + count - IDA_BLOCK_SIZE;
|
||||
from = (void __user *) from + IDA_BLOCK_SIZE;
|
||||
from = (void __user *)from + IDA_BLOCK_SIZE;
|
||||
count -= IDA_BLOCK_SIZE;
|
||||
}
|
||||
return copy_from_user(ib->data[i], from, count);
|
||||
vaddr = dma64_to_virt(ib->data[i]);
|
||||
return copy_from_user(vaddr, from, count);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -181,9 +181,35 @@ int arch_make_page_accessible(struct page *page);
|
|||
#define __PAGE_OFFSET 0x0UL
|
||||
#define PAGE_OFFSET 0x0UL
|
||||
|
||||
#define __pa(x) ((unsigned long)(x))
|
||||
#define __pa_nodebug(x) ((unsigned long)(x))
|
||||
|
||||
#ifdef __DECOMPRESSOR
|
||||
|
||||
#define __pa(x) __pa_nodebug(x)
|
||||
#define __pa32(x) __pa(x)
|
||||
#define __va(x) ((void *)(unsigned long)(x))
|
||||
|
||||
#else /* __DECOMPRESSOR */
|
||||
|
||||
#ifdef CONFIG_DEBUG_VIRTUAL
|
||||
|
||||
unsigned long __phys_addr(unsigned long x, bool is_31bit);
|
||||
|
||||
#else /* CONFIG_DEBUG_VIRTUAL */
|
||||
|
||||
static inline unsigned long __phys_addr(unsigned long x, bool is_31bit)
|
||||
{
|
||||
return __pa_nodebug(x);
|
||||
}
|
||||
|
||||
#endif /* CONFIG_DEBUG_VIRTUAL */
|
||||
|
||||
#define __pa(x) __phys_addr((unsigned long)(x), false)
|
||||
#define __pa32(x) __phys_addr((unsigned long)(x), true)
|
||||
#define __va(x) ((void *)(unsigned long)(x))
|
||||
|
||||
#endif /* __DECOMPRESSOR */
|
||||
|
||||
#define phys_to_pfn(phys) ((phys) >> PAGE_SHIFT)
|
||||
#define pfn_to_phys(pfn) ((pfn) << PAGE_SHIFT)
|
||||
|
||||
|
|
@ -205,7 +231,7 @@ static inline unsigned long virt_to_pfn(const void *kaddr)
|
|||
#define virt_to_page(kaddr) pfn_to_page(virt_to_pfn(kaddr))
|
||||
#define page_to_virt(page) pfn_to_virt(page_to_pfn(page))
|
||||
|
||||
#define virt_addr_valid(kaddr) pfn_valid(virt_to_pfn(kaddr))
|
||||
#define virt_addr_valid(kaddr) pfn_valid(phys_to_pfn(__pa_nodebug(kaddr)))
|
||||
|
||||
#define VM_DATA_DEFAULT_FLAGS VM_DATA_FLAGS_NON_EXEC
|
||||
|
||||
|
|
|
|||
|
|
@ -14,11 +14,13 @@
|
|||
|
||||
#include <linux/bits.h>
|
||||
|
||||
#define CIF_SIE 0 /* CPU needs SIE exit cleanup */
|
||||
#define CIF_NOHZ_DELAY 2 /* delay HZ disable for a tick */
|
||||
#define CIF_ENABLED_WAIT 5 /* in enabled wait state */
|
||||
#define CIF_MCCK_GUEST 6 /* machine check happening in guest */
|
||||
#define CIF_DEDICATED_CPU 7 /* this CPU is dedicated */
|
||||
|
||||
#define _CIF_SIE BIT(CIF_SIE)
|
||||
#define _CIF_NOHZ_DELAY BIT(CIF_NOHZ_DELAY)
|
||||
#define _CIF_ENABLED_WAIT BIT(CIF_ENABLED_WAIT)
|
||||
#define _CIF_MCCK_GUEST BIT(CIF_MCCK_GUEST)
|
||||
|
|
|
|||
|
|
@ -14,13 +14,11 @@
|
|||
#define PIF_SYSCALL 0 /* inside a system call */
|
||||
#define PIF_EXECVE_PGSTE_RESTART 1 /* restart execve for PGSTE binaries */
|
||||
#define PIF_SYSCALL_RET_SET 2 /* return value was set via ptrace */
|
||||
#define PIF_GUEST_FAULT 3 /* indicates program check in sie64a */
|
||||
#define PIF_FTRACE_FULL_REGS 4 /* all register contents valid (ftrace) */
|
||||
|
||||
#define _PIF_SYSCALL BIT(PIF_SYSCALL)
|
||||
#define _PIF_EXECVE_PGSTE_RESTART BIT(PIF_EXECVE_PGSTE_RESTART)
|
||||
#define _PIF_SYSCALL_RET_SET BIT(PIF_SYSCALL_RET_SET)
|
||||
#define _PIF_GUEST_FAULT BIT(PIF_GUEST_FAULT)
|
||||
#define _PIF_FTRACE_FULL_REGS BIT(PIF_FTRACE_FULL_REGS)
|
||||
|
||||
#define PSW32_MASK_PER _AC(0x40000000, UL)
|
||||
|
|
|
|||
|
|
@ -9,8 +9,9 @@
|
|||
#define __QDIO_H__
|
||||
|
||||
#include <linux/interrupt.h>
|
||||
#include <asm/cio.h>
|
||||
#include <asm/dma-types.h>
|
||||
#include <asm/ccwdev.h>
|
||||
#include <asm/cio.h>
|
||||
|
||||
/* only use 4 queues to save some cachelines */
|
||||
#define QDIO_MAX_QUEUES_PER_IRQ 4
|
||||
|
|
@ -34,9 +35,9 @@
|
|||
* @dkey: access key for SLSB
|
||||
*/
|
||||
struct qdesfmt0 {
|
||||
u64 sliba;
|
||||
u64 sla;
|
||||
u64 slsba;
|
||||
dma64_t sliba;
|
||||
dma64_t sla;
|
||||
dma64_t slsba;
|
||||
u32 : 32;
|
||||
u32 akey : 4;
|
||||
u32 bkey : 4;
|
||||
|
|
@ -74,7 +75,7 @@ struct qdr {
|
|||
/* private: */
|
||||
u32 res[9];
|
||||
/* public: */
|
||||
u64 qiba;
|
||||
dma64_t qiba;
|
||||
u32 : 32;
|
||||
u32 qkey : 4;
|
||||
u32 : 28;
|
||||
|
|
@ -146,7 +147,7 @@ struct qaob {
|
|||
u8 flags;
|
||||
u16 cbtbs;
|
||||
u8 sb_count;
|
||||
u64 sba[QDIO_MAX_ELEMENTS_PER_BUFFER];
|
||||
dma64_t sba[QDIO_MAX_ELEMENTS_PER_BUFFER];
|
||||
u16 dcount[QDIO_MAX_ELEMENTS_PER_BUFFER];
|
||||
u64 user0;
|
||||
u64 res4[2];
|
||||
|
|
@ -208,7 +209,7 @@ struct qdio_buffer_element {
|
|||
u8 scount;
|
||||
u8 sflags;
|
||||
u32 length;
|
||||
u64 addr;
|
||||
dma64_t addr;
|
||||
} __attribute__ ((packed, aligned(16)));
|
||||
|
||||
/**
|
||||
|
|
@ -224,7 +225,7 @@ struct qdio_buffer {
|
|||
* @sbal: absolute SBAL address
|
||||
*/
|
||||
struct sl_element {
|
||||
u64 sbal;
|
||||
dma64_t sbal;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@
|
|||
|
||||
#include <linux/types.h>
|
||||
#include <asm/css_chars.h>
|
||||
#include <asm/dma-types.h>
|
||||
#include <asm/cio.h>
|
||||
|
||||
/**
|
||||
|
|
@ -53,7 +54,7 @@ struct cmd_scsw {
|
|||
__u32 fctl : 3;
|
||||
__u32 actl : 7;
|
||||
__u32 stctl : 5;
|
||||
__u32 cpa;
|
||||
dma32_t cpa;
|
||||
__u32 dstat : 8;
|
||||
__u32 cstat : 8;
|
||||
__u32 count : 16;
|
||||
|
|
@ -93,7 +94,7 @@ struct tm_scsw {
|
|||
u32 fctl:3;
|
||||
u32 actl:7;
|
||||
u32 stctl:5;
|
||||
u32 tcw;
|
||||
dma32_t tcw;
|
||||
u32 dstat:8;
|
||||
u32 cstat:8;
|
||||
u32 fcxs:8;
|
||||
|
|
@ -125,7 +126,7 @@ struct eadm_scsw {
|
|||
u32 fctl:3;
|
||||
u32 actl:7;
|
||||
u32 stctl:5;
|
||||
u32 aob;
|
||||
dma32_t aob;
|
||||
u32 dstat:8;
|
||||
u32 cstat:8;
|
||||
u32:16;
|
||||
|
|
|
|||
|
|
@ -119,33 +119,11 @@ _LPP_OFFSET = __LC_LPP
|
|||
.endm
|
||||
|
||||
#if IS_ENABLED(CONFIG_KVM)
|
||||
/*
|
||||
* The OUTSIDE macro jumps to the provided label in case the value
|
||||
* in the provided register is outside of the provided range. The
|
||||
* macro is useful for checking whether a PSW stored in a register
|
||||
* pair points inside or outside of a block of instructions.
|
||||
* @reg: register to check
|
||||
* @start: start of the range
|
||||
* @end: end of the range
|
||||
* @outside_label: jump here if @reg is outside of [@start..@end)
|
||||
*/
|
||||
.macro OUTSIDE reg,start,end,outside_label
|
||||
lgr %r14,\reg
|
||||
larl %r13,\start
|
||||
slgr %r14,%r13
|
||||
clgfrl %r14,.Lrange_size\@
|
||||
jhe \outside_label
|
||||
.section .rodata, "a"
|
||||
.balign 4
|
||||
.Lrange_size\@:
|
||||
.long \end - \start
|
||||
.previous
|
||||
.endm
|
||||
|
||||
.macro SIEEXIT
|
||||
lg %r9,__SF_SIE_CONTROL(%r15) # get control block pointer
|
||||
.macro SIEEXIT sie_control
|
||||
lg %r9,\sie_control # get control block pointer
|
||||
ni __SIE_PROG0C+3(%r9),0xfe # no longer in SIE
|
||||
lctlg %c1,%c1,__LC_KERNEL_ASCE # load primary asce
|
||||
ni __LC_CPU_FLAGS+7,255-_CIF_SIE
|
||||
larl %r9,sie_exit # skip forward to sie_exit
|
||||
.endm
|
||||
#endif
|
||||
|
|
@ -214,6 +192,7 @@ SYM_FUNC_START(__sie64a)
|
|||
lg %r14,__LC_GMAP # get gmap pointer
|
||||
ltgr %r14,%r14
|
||||
jz .Lsie_gmap
|
||||
oi __LC_CPU_FLAGS+7,_CIF_SIE
|
||||
lctlg %c1,%c1,__GMAP_ASCE(%r14) # load primary asce
|
||||
.Lsie_gmap:
|
||||
lg %r14,__SF_SIE_CONTROL(%r15) # get control block pointer
|
||||
|
|
@ -234,7 +213,7 @@ SYM_FUNC_START(__sie64a)
|
|||
lg %r14,__SF_SIE_CONTROL(%r15) # get control block pointer
|
||||
ni __SIE_PROG0C+3(%r14),0xfe # no longer in SIE
|
||||
lctlg %c1,%c1,__LC_KERNEL_ASCE # load primary asce
|
||||
.Lsie_done:
|
||||
ni __LC_CPU_FLAGS+7,255-_CIF_SIE
|
||||
# some program checks are suppressing. C code (e.g. do_protection_exception)
|
||||
# will rewind the PSW by the ILC, which is often 4 bytes in case of SIE. There
|
||||
# are some corner cases (e.g. runtime instrumentation) where ILC is unpredictable.
|
||||
|
|
@ -337,20 +316,13 @@ SYM_CODE_START(pgm_check_handler)
|
|||
stpt __LC_SYS_ENTER_TIMER
|
||||
BPOFF
|
||||
stmg %r8,%r15,__LC_SAVE_AREA_SYNC
|
||||
lghi %r10,0
|
||||
lgr %r10,%r15
|
||||
lmg %r8,%r9,__LC_PGM_OLD_PSW
|
||||
tmhh %r8,0x0001 # coming from user space?
|
||||
jno .Lpgm_skip_asce
|
||||
lctlg %c1,%c1,__LC_KERNEL_ASCE
|
||||
j 3f # -> fault in user space
|
||||
.Lpgm_skip_asce:
|
||||
#if IS_ENABLED(CONFIG_KVM)
|
||||
# cleanup critical section for program checks in __sie64a
|
||||
OUTSIDE %r9,.Lsie_gmap,.Lsie_done,1f
|
||||
BPENTER __SF_SIE_FLAGS(%r15),_TIF_ISOLATE_BP_GUEST
|
||||
SIEEXIT
|
||||
lghi %r10,_PIF_GUEST_FAULT
|
||||
#endif
|
||||
1: tmhh %r8,0x4000 # PER bit set in old PSW ?
|
||||
jnz 2f # -> enabled, can't be a double fault
|
||||
tm __LC_PGM_ILC+3,0x80 # check for per exception
|
||||
|
|
@ -361,13 +333,20 @@ SYM_CODE_START(pgm_check_handler)
|
|||
CHECK_VMAP_STACK __LC_SAVE_AREA_SYNC,4f
|
||||
3: lg %r15,__LC_KERNEL_STACK
|
||||
4: la %r11,STACK_FRAME_OVERHEAD(%r15)
|
||||
stg %r10,__PT_FLAGS(%r11)
|
||||
xc __PT_FLAGS(8,%r11),__PT_FLAGS(%r11)
|
||||
xc __SF_BACKCHAIN(8,%r15),__SF_BACKCHAIN(%r15)
|
||||
stmg %r0,%r7,__PT_R0(%r11)
|
||||
mvc __PT_R8(64,%r11),__LC_SAVE_AREA_SYNC
|
||||
mvc __PT_LAST_BREAK(8,%r11),__LC_PGM_LAST_BREAK
|
||||
stmg %r8,%r9,__PT_PSW(%r11)
|
||||
|
||||
stctg %c1,%c1,__PT_CR1(%r11)
|
||||
#if IS_ENABLED(CONFIG_KVM)
|
||||
lg %r12,__LC_GMAP
|
||||
clc __GMAP_ASCE(8,%r12), __PT_CR1(%r11)
|
||||
jne 5f
|
||||
BPENTER __SF_SIE_FLAGS(%r10),_TIF_ISOLATE_BP_GUEST
|
||||
SIEEXIT __SF_SIE_CONTROL(%r10)
|
||||
#endif
|
||||
5: stmg %r8,%r9,__PT_PSW(%r11)
|
||||
# clear user controlled registers to prevent speculative use
|
||||
xgr %r0,%r0
|
||||
xgr %r1,%r1
|
||||
|
|
@ -416,9 +395,10 @@ SYM_CODE_START(\name)
|
|||
tmhh %r8,0x0001 # interrupting from user ?
|
||||
jnz 1f
|
||||
#if IS_ENABLED(CONFIG_KVM)
|
||||
OUTSIDE %r9,.Lsie_gmap,.Lsie_done,0f
|
||||
TSTMSK __LC_CPU_FLAGS,_CIF_SIE
|
||||
jz 0f
|
||||
BPENTER __SF_SIE_FLAGS(%r15),_TIF_ISOLATE_BP_GUEST
|
||||
SIEEXIT
|
||||
SIEEXIT __SF_SIE_CONTROL(%r15)
|
||||
#endif
|
||||
0: CHECK_STACK __LC_SAVE_AREA_ASYNC
|
||||
aghi %r15,-(STACK_FRAME_OVERHEAD + __PT_SIZE)
|
||||
|
|
@ -513,11 +493,20 @@ SYM_CODE_START(mcck_int_handler)
|
|||
TSTMSK __LC_MCCK_CODE,MCCK_CODE_PSW_IA_VALID
|
||||
jno .Lmcck_panic
|
||||
#if IS_ENABLED(CONFIG_KVM)
|
||||
OUTSIDE %r9,.Lsie_gmap,.Lsie_done,.Lmcck_user
|
||||
OUTSIDE %r9,.Lsie_entry,.Lsie_leave,4f
|
||||
TSTMSK __LC_CPU_FLAGS,_CIF_SIE
|
||||
jz .Lmcck_user
|
||||
# Need to compare the address instead of a CIF_SIE* flag.
|
||||
# Otherwise there would be a race between setting the flag
|
||||
# and entering SIE (or leaving and clearing the flag). This
|
||||
# would cause machine checks targeted at the guest to be
|
||||
# handled by the host.
|
||||
larl %r14,.Lsie_entry
|
||||
clgrjl %r9,%r14, 4f
|
||||
larl %r14,.Lsie_leave
|
||||
clgrjhe %r9,%r14, 4f
|
||||
oi __LC_CPU_FLAGS+7, _CIF_MCCK_GUEST
|
||||
4: BPENTER __SF_SIE_FLAGS(%r15),_TIF_ISOLATE_BP_GUEST
|
||||
SIEEXIT
|
||||
SIEEXIT __SF_SIE_CONTROL(%r15)
|
||||
#endif
|
||||
.Lmcck_user:
|
||||
lg %r15,__LC_MCCK_STACK
|
||||
|
|
|
|||
|
|
@ -397,7 +397,7 @@ static void service_level_vm_print(struct seq_file *m,
|
|||
{
|
||||
char *query_buffer, *str;
|
||||
|
||||
query_buffer = kmalloc(1024, GFP_KERNEL | GFP_DMA);
|
||||
query_buffer = kmalloc(1024, GFP_KERNEL);
|
||||
if (!query_buffer)
|
||||
return;
|
||||
cpcmd("QUERY CPLEVEL", query_buffer, 1024, NULL);
|
||||
|
|
|
|||
|
|
@ -210,13 +210,13 @@ void vtime_flush(struct task_struct *tsk)
|
|||
virt_timer_expire();
|
||||
|
||||
steal = S390_lowcore.steal_timer;
|
||||
avg_steal = S390_lowcore.avg_steal_timer / 2;
|
||||
avg_steal = S390_lowcore.avg_steal_timer;
|
||||
if ((s64) steal > 0) {
|
||||
S390_lowcore.steal_timer = 0;
|
||||
account_steal_time(cputime_to_nsecs(steal));
|
||||
avg_steal += steal;
|
||||
}
|
||||
S390_lowcore.avg_steal_timer = avg_steal;
|
||||
S390_lowcore.avg_steal_timer = avg_steal / 2;
|
||||
}
|
||||
|
||||
static u64 vtime_delta(void)
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ obj-y := init.o fault.o extmem.o mmap.o vmem.o maccess.o
|
|||
obj-y += page-states.o pageattr.o pgtable.o pgalloc.o extable.o
|
||||
|
||||
obj-$(CONFIG_CMM) += cmm.o
|
||||
obj-$(CONFIG_DEBUG_VIRTUAL) += physaddr.o
|
||||
obj-$(CONFIG_HUGETLB_PAGE) += hugetlbpage.o
|
||||
obj-$(CONFIG_PTDUMP_CORE) += dump_pagetables.o
|
||||
obj-$(CONFIG_PGSTE) += gmap.o
|
||||
|
|
|
|||
|
|
@ -67,13 +67,15 @@ early_initcall(fault_init);
|
|||
static enum fault_type get_fault_type(struct pt_regs *regs)
|
||||
{
|
||||
union teid teid = { .val = regs->int_parm_long };
|
||||
struct gmap *gmap;
|
||||
|
||||
if (likely(teid.as == PSW_BITS_AS_PRIMARY)) {
|
||||
if (user_mode(regs))
|
||||
return USER_FAULT;
|
||||
if (!IS_ENABLED(CONFIG_PGSTE))
|
||||
return KERNEL_FAULT;
|
||||
if (test_pt_regs_flag(regs, PIF_GUEST_FAULT))
|
||||
gmap = (struct gmap *)S390_lowcore.gmap;
|
||||
if (regs->cr1 == gmap->asce)
|
||||
return GMAP_FAULT;
|
||||
return KERNEL_FAULT;
|
||||
}
|
||||
|
|
|
|||
15
arch/s390/mm/physaddr.c
Normal file
15
arch/s390/mm/physaddr.c
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
// SPDX-License-Identifier: GPL-2.0
|
||||
#include <linux/mmdebug.h>
|
||||
#include <linux/export.h>
|
||||
#include <linux/mm.h>
|
||||
#include <asm/page.h>
|
||||
|
||||
unsigned long __phys_addr(unsigned long x, bool is_31bit)
|
||||
{
|
||||
VIRTUAL_BUG_ON(is_vmalloc_or_module_addr((void *)(x)));
|
||||
x = __pa_nodebug(x);
|
||||
if (is_31bit)
|
||||
VIRTUAL_BUG_ON(x >> 31);
|
||||
return x;
|
||||
}
|
||||
EXPORT_SYMBOL(__phys_addr);
|
||||
|
|
@ -62,6 +62,11 @@ void xen_arch_unregister_cpu(int num);
|
|||
#ifdef CONFIG_PVH
|
||||
void __init xen_pvh_init(struct boot_params *boot_params);
|
||||
void __init mem_map_via_hcall(struct boot_params *boot_params_p);
|
||||
#ifdef CONFIG_XEN_PVH
|
||||
void __init xen_reserve_extra_memory(struct boot_params *bootp);
|
||||
#else
|
||||
static inline void xen_reserve_extra_memory(struct boot_params *bootp) { }
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* Lazy mode for batching updates / context switch */
|
||||
|
|
|
|||
|
|
@ -75,6 +75,9 @@ static void __init init_pvh_bootparams(bool xen_guest)
|
|||
} else
|
||||
xen_raw_printk("Warning: Can fit ISA range into e820\n");
|
||||
|
||||
if (xen_guest)
|
||||
xen_reserve_extra_memory(&pvh_bootparams);
|
||||
|
||||
pvh_bootparams.hdr.cmd_line_ptr =
|
||||
pvh_start_info.cmdline_paddr;
|
||||
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@
|
|||
#include <linux/console.h>
|
||||
#include <linux/cpu.h>
|
||||
#include <linux/kexec.h>
|
||||
#include <linux/memblock.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/panic_notifier.h>
|
||||
|
||||
|
|
@ -350,3 +351,34 @@ void xen_arch_unregister_cpu(int num)
|
|||
}
|
||||
EXPORT_SYMBOL(xen_arch_unregister_cpu);
|
||||
#endif
|
||||
|
||||
/* Amount of extra memory space we add to the e820 ranges */
|
||||
struct xen_memory_region xen_extra_mem[XEN_EXTRA_MEM_MAX_REGIONS] __initdata;
|
||||
|
||||
void __init xen_add_extra_mem(unsigned long start_pfn, unsigned long n_pfns)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
/*
|
||||
* No need to check for zero size, should happen rarely and will only
|
||||
* write a new entry regarded to be unused due to zero size.
|
||||
*/
|
||||
for (i = 0; i < XEN_EXTRA_MEM_MAX_REGIONS; i++) {
|
||||
/* Add new region. */
|
||||
if (xen_extra_mem[i].n_pfns == 0) {
|
||||
xen_extra_mem[i].start_pfn = start_pfn;
|
||||
xen_extra_mem[i].n_pfns = n_pfns;
|
||||
break;
|
||||
}
|
||||
/* Append to existing region. */
|
||||
if (xen_extra_mem[i].start_pfn + xen_extra_mem[i].n_pfns ==
|
||||
start_pfn) {
|
||||
xen_extra_mem[i].n_pfns += n_pfns;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (i == XEN_EXTRA_MEM_MAX_REGIONS)
|
||||
printk(KERN_WARNING "Warning: not enough extra memory regions\n");
|
||||
|
||||
memblock_reserve(PFN_PHYS(start_pfn), PFN_PHYS(n_pfns));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
// SPDX-License-Identifier: GPL-2.0
|
||||
#include <linux/acpi.h>
|
||||
#include <linux/export.h>
|
||||
#include <linux/mm.h>
|
||||
|
||||
#include <xen/hvc-console.h>
|
||||
|
||||
|
|
@ -73,3 +74,70 @@ void __init mem_map_via_hcall(struct boot_params *boot_params_p)
|
|||
}
|
||||
boot_params_p->e820_entries = memmap.nr_entries;
|
||||
}
|
||||
|
||||
/*
|
||||
* Reserve e820 UNUSABLE regions to inflate the memory balloon.
|
||||
*
|
||||
* On PVH dom0 the host memory map is used, RAM regions available to dom0 are
|
||||
* located as the same place as in the native memory map, but since dom0 gets
|
||||
* less memory than the total amount of host RAM the ranges that can't be
|
||||
* populated are converted from RAM -> UNUSABLE. Use such regions (up to the
|
||||
* ratio signaled in EXTRA_MEM_RATIO) in order to inflate the balloon driver at
|
||||
* boot. Doing so prevents the guest (even if just temporary) from using holes
|
||||
* in the memory map in order to map grants or foreign addresses, and
|
||||
* hopefully limits the risk of a clash with a device MMIO region. Ideally the
|
||||
* hypervisor should notify us which memory ranges are suitable for creating
|
||||
* foreign mappings, but that's not yet implemented.
|
||||
*/
|
||||
void __init xen_reserve_extra_memory(struct boot_params *bootp)
|
||||
{
|
||||
unsigned int i, ram_pages = 0, extra_pages;
|
||||
|
||||
for (i = 0; i < bootp->e820_entries; i++) {
|
||||
struct boot_e820_entry *e = &bootp->e820_table[i];
|
||||
|
||||
if (e->type != E820_TYPE_RAM)
|
||||
continue;
|
||||
ram_pages += PFN_DOWN(e->addr + e->size) - PFN_UP(e->addr);
|
||||
}
|
||||
|
||||
/* Max amount of extra memory. */
|
||||
extra_pages = EXTRA_MEM_RATIO * ram_pages;
|
||||
|
||||
/*
|
||||
* Convert UNUSABLE ranges to RAM and reserve them for foreign mapping
|
||||
* purposes.
|
||||
*/
|
||||
for (i = 0; i < bootp->e820_entries && extra_pages; i++) {
|
||||
struct boot_e820_entry *e = &bootp->e820_table[i];
|
||||
unsigned long pages;
|
||||
|
||||
if (e->type != E820_TYPE_UNUSABLE)
|
||||
continue;
|
||||
|
||||
pages = min(extra_pages,
|
||||
PFN_DOWN(e->addr + e->size) - PFN_UP(e->addr));
|
||||
|
||||
if (pages != (PFN_DOWN(e->addr + e->size) - PFN_UP(e->addr))) {
|
||||
struct boot_e820_entry *next;
|
||||
|
||||
if (bootp->e820_entries ==
|
||||
ARRAY_SIZE(bootp->e820_table))
|
||||
/* No space left to split - skip region. */
|
||||
continue;
|
||||
|
||||
/* Split entry. */
|
||||
next = e + 1;
|
||||
memmove(next, e,
|
||||
(bootp->e820_entries - i) * sizeof(*e));
|
||||
bootp->e820_entries++;
|
||||
next->addr = PAGE_ALIGN(e->addr) + PFN_PHYS(pages);
|
||||
e->size = next->addr - e->addr;
|
||||
next->size -= e->size;
|
||||
}
|
||||
e->type = E820_TYPE_RAM;
|
||||
extra_pages -= pages;
|
||||
|
||||
xen_add_extra_mem(PFN_UP(e->addr), pages);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -38,9 +38,6 @@
|
|||
|
||||
#define GB(x) ((uint64_t)(x) * 1024 * 1024 * 1024)
|
||||
|
||||
/* Amount of extra memory space we add to the e820 ranges */
|
||||
struct xen_memory_region xen_extra_mem[XEN_EXTRA_MEM_MAX_REGIONS] __initdata;
|
||||
|
||||
/* Number of pages released from the initial allocation. */
|
||||
unsigned long xen_released_pages;
|
||||
|
||||
|
|
@ -64,18 +61,6 @@ static struct {
|
|||
} xen_remap_buf __initdata __aligned(PAGE_SIZE);
|
||||
static unsigned long xen_remap_mfn __initdata = INVALID_P2M_ENTRY;
|
||||
|
||||
/*
|
||||
* The maximum amount of extra memory compared to the base size. The
|
||||
* main scaling factor is the size of struct page. At extreme ratios
|
||||
* of base:extra, all the base memory can be filled with page
|
||||
* structures for the extra memory, leaving no space for anything
|
||||
* else.
|
||||
*
|
||||
* 10x seems like a reasonable balance between scaling flexibility and
|
||||
* leaving a practically usable system.
|
||||
*/
|
||||
#define EXTRA_MEM_RATIO (10)
|
||||
|
||||
static bool xen_512gb_limit __initdata = IS_ENABLED(CONFIG_XEN_512GB);
|
||||
|
||||
static void __init xen_parse_512gb(void)
|
||||
|
|
@ -96,35 +81,6 @@ static void __init xen_parse_512gb(void)
|
|||
xen_512gb_limit = val;
|
||||
}
|
||||
|
||||
static void __init xen_add_extra_mem(unsigned long start_pfn,
|
||||
unsigned long n_pfns)
|
||||
{
|
||||
int i;
|
||||
|
||||
/*
|
||||
* No need to check for zero size, should happen rarely and will only
|
||||
* write a new entry regarded to be unused due to zero size.
|
||||
*/
|
||||
for (i = 0; i < XEN_EXTRA_MEM_MAX_REGIONS; i++) {
|
||||
/* Add new region. */
|
||||
if (xen_extra_mem[i].n_pfns == 0) {
|
||||
xen_extra_mem[i].start_pfn = start_pfn;
|
||||
xen_extra_mem[i].n_pfns = n_pfns;
|
||||
break;
|
||||
}
|
||||
/* Append to existing region. */
|
||||
if (xen_extra_mem[i].start_pfn + xen_extra_mem[i].n_pfns ==
|
||||
start_pfn) {
|
||||
xen_extra_mem[i].n_pfns += n_pfns;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (i == XEN_EXTRA_MEM_MAX_REGIONS)
|
||||
printk(KERN_WARNING "Warning: not enough extra memory regions\n");
|
||||
|
||||
memblock_reserve(PFN_PHYS(start_pfn), PFN_PHYS(n_pfns));
|
||||
}
|
||||
|
||||
static void __init xen_del_extra_mem(unsigned long start_pfn,
|
||||
unsigned long n_pfns)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -163,4 +163,18 @@ void xen_hvm_post_suspend(int suspend_cancelled);
|
|||
static inline void xen_hvm_post_suspend(int suspend_cancelled) {}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* The maximum amount of extra memory compared to the base size. The
|
||||
* main scaling factor is the size of struct page. At extreme ratios
|
||||
* of base:extra, all the base memory can be filled with page
|
||||
* structures for the extra memory, leaving no space for anything
|
||||
* else.
|
||||
*
|
||||
* 10x seems like a reasonable balance between scaling flexibility and
|
||||
* leaving a practically usable system.
|
||||
*/
|
||||
#define EXTRA_MEM_RATIO (10)
|
||||
|
||||
void xen_add_extra_mem(unsigned long start_pfn, unsigned long n_pfns);
|
||||
|
||||
#endif /* XEN_OPS_H */
|
||||
|
|
|
|||
|
|
@ -583,6 +583,9 @@ static void bd_finish_claiming(struct block_device *bdev, void *holder,
|
|||
mutex_unlock(&bdev->bd_holder_lock);
|
||||
bd_clear_claiming(whole, holder);
|
||||
mutex_unlock(&bdev_lock);
|
||||
|
||||
if (hops && hops->get_holder)
|
||||
hops->get_holder(holder);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -605,6 +608,7 @@ EXPORT_SYMBOL(bd_abort_claiming);
|
|||
static void bd_end_claim(struct block_device *bdev, void *holder)
|
||||
{
|
||||
struct block_device *whole = bdev_whole(bdev);
|
||||
const struct blk_holder_ops *hops = bdev->bd_holder_ops;
|
||||
bool unblock = false;
|
||||
|
||||
/*
|
||||
|
|
@ -627,6 +631,9 @@ static void bd_end_claim(struct block_device *bdev, void *holder)
|
|||
whole->bd_holder = NULL;
|
||||
mutex_unlock(&bdev_lock);
|
||||
|
||||
if (hops && hops->put_holder)
|
||||
hops->put_holder(holder);
|
||||
|
||||
/*
|
||||
* If this was the last claim, remove holder link and unblock evpoll if
|
||||
* it was a write holder.
|
||||
|
|
|
|||
|
|
@ -380,6 +380,8 @@ static int dock_in_progress(struct dock_station *ds)
|
|||
|
||||
/**
|
||||
* handle_eject_request - handle an undock request checking for error conditions
|
||||
* @ds: The dock station to undock.
|
||||
* @event: The ACPI event number associated with the undock request.
|
||||
*
|
||||
* Check to make sure the dock device is still present, then undock and
|
||||
* hotremove all the devices that may need removing.
|
||||
|
|
|
|||
|
|
@ -502,6 +502,7 @@ static void acpi_pm_finish(void)
|
|||
|
||||
/**
|
||||
* acpi_pm_start - Start system PM transition.
|
||||
* @acpi_state: The target ACPI power state to transition to.
|
||||
*/
|
||||
static void acpi_pm_start(u32 acpi_state)
|
||||
{
|
||||
|
|
@ -540,8 +541,9 @@ static u32 acpi_suspend_states[] = {
|
|||
};
|
||||
|
||||
/**
|
||||
* acpi_suspend_begin - Set the target system sleep state to the state
|
||||
* associated with given @pm_state, if supported.
|
||||
* acpi_suspend_begin - Set the target system sleep state to the state
|
||||
* associated with given @pm_state, if supported.
|
||||
* @pm_state: The target system power management state.
|
||||
*/
|
||||
static int acpi_suspend_begin(suspend_state_t pm_state)
|
||||
{
|
||||
|
|
@ -671,10 +673,11 @@ static const struct platform_suspend_ops acpi_suspend_ops = {
|
|||
};
|
||||
|
||||
/**
|
||||
* acpi_suspend_begin_old - Set the target system sleep state to the
|
||||
* state associated with given @pm_state, if supported, and
|
||||
* execute the _PTS control method. This function is used if the
|
||||
* pre-ACPI 2.0 suspend ordering has been requested.
|
||||
* acpi_suspend_begin_old - Set the target system sleep state to the
|
||||
* state associated with given @pm_state, if supported, and
|
||||
* execute the _PTS control method. This function is used if the
|
||||
* pre-ACPI 2.0 suspend ordering has been requested.
|
||||
* @pm_state: The target suspend state for the system.
|
||||
*/
|
||||
static int acpi_suspend_begin_old(suspend_state_t pm_state)
|
||||
{
|
||||
|
|
@ -967,10 +970,11 @@ static const struct platform_hibernation_ops acpi_hibernation_ops = {
|
|||
};
|
||||
|
||||
/**
|
||||
* acpi_hibernation_begin_old - Set the target system sleep state to
|
||||
* ACPI_STATE_S4 and execute the _PTS control method. This
|
||||
* function is used if the pre-ACPI 2.0 suspend ordering has been
|
||||
* requested.
|
||||
* acpi_hibernation_begin_old - Set the target system sleep state to
|
||||
* ACPI_STATE_S4 and execute the _PTS control method. This
|
||||
* function is used if the pre-ACPI 2.0 suspend ordering has been
|
||||
* requested.
|
||||
* @stage: The power management event message.
|
||||
*/
|
||||
static int acpi_hibernation_begin_old(pm_message_t stage)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -669,19 +669,6 @@ MODULE_PARM_DESC(mobile_lpm_policy, "Default LPM policy for mobile chipsets");
|
|||
static void ahci_pci_save_initial_config(struct pci_dev *pdev,
|
||||
struct ahci_host_priv *hpriv)
|
||||
{
|
||||
if (pdev->vendor == PCI_VENDOR_ID_ASMEDIA) {
|
||||
switch (pdev->device) {
|
||||
case 0x1166:
|
||||
dev_info(&pdev->dev, "ASM1166 has only six ports\n");
|
||||
hpriv->saved_port_map = 0x3f;
|
||||
break;
|
||||
case 0x1064:
|
||||
dev_info(&pdev->dev, "ASM1064 has only four ports\n");
|
||||
hpriv->saved_port_map = 0xf;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (pdev->vendor == PCI_VENDOR_ID_JMICRON && pdev->device == 0x2361) {
|
||||
dev_info(&pdev->dev, "JMB361 has only one port\n");
|
||||
hpriv->saved_port_map = 1;
|
||||
|
|
|
|||
|
|
@ -96,6 +96,20 @@ static const int gisb_offsets_bcm7400[] = {
|
|||
[ARB_ERR_CAP_MASTER] = 0x0d8,
|
||||
};
|
||||
|
||||
static const int gisb_offsets_bcm74165[] = {
|
||||
[ARB_TIMER] = 0x008,
|
||||
[ARB_BP_CAP_CLR] = 0x044,
|
||||
[ARB_BP_CAP_HI_ADDR] = -1,
|
||||
[ARB_BP_CAP_ADDR] = 0x048,
|
||||
[ARB_BP_CAP_STATUS] = 0x058,
|
||||
[ARB_BP_CAP_MASTER] = 0x05c,
|
||||
[ARB_ERR_CAP_CLR] = 0x038,
|
||||
[ARB_ERR_CAP_HI_ADDR] = -1,
|
||||
[ARB_ERR_CAP_ADDR] = 0x020,
|
||||
[ARB_ERR_CAP_STATUS] = 0x030,
|
||||
[ARB_ERR_CAP_MASTER] = 0x034,
|
||||
};
|
||||
|
||||
static const int gisb_offsets_bcm7435[] = {
|
||||
[ARB_TIMER] = 0x00c,
|
||||
[ARB_BP_CAP_CLR] = 0x014,
|
||||
|
|
@ -393,6 +407,7 @@ static const struct of_device_id brcmstb_gisb_arb_of_match[] = {
|
|||
{ .compatible = "brcm,bcm7400-gisb-arb", .data = gisb_offsets_bcm7400 },
|
||||
{ .compatible = "brcm,bcm7278-gisb-arb", .data = gisb_offsets_bcm7278 },
|
||||
{ .compatible = "brcm,bcm7038-gisb-arb", .data = gisb_offsets_bcm7038 },
|
||||
{ .compatible = "brcm,bcm74165-gisb-arb", .data = gisb_offsets_bcm74165 },
|
||||
{ },
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -39,45 +39,39 @@ struct ts_nbus {
|
|||
/*
|
||||
* request all gpios required by the bus.
|
||||
*/
|
||||
static int ts_nbus_init_pdata(struct platform_device *pdev, struct ts_nbus
|
||||
*ts_nbus)
|
||||
static int ts_nbus_init_pdata(struct platform_device *pdev,
|
||||
struct ts_nbus *ts_nbus)
|
||||
{
|
||||
ts_nbus->data = devm_gpiod_get_array(&pdev->dev, "ts,data",
|
||||
GPIOD_OUT_HIGH);
|
||||
if (IS_ERR(ts_nbus->data)) {
|
||||
dev_err(&pdev->dev, "failed to retrieve ts,data-gpio from dts\n");
|
||||
return PTR_ERR(ts_nbus->data);
|
||||
}
|
||||
if (IS_ERR(ts_nbus->data))
|
||||
return dev_err_probe(&pdev->dev, PTR_ERR(ts_nbus->data),
|
||||
"failed to retrieve ts,data-gpio from dts\n");
|
||||
|
||||
ts_nbus->csn = devm_gpiod_get(&pdev->dev, "ts,csn", GPIOD_OUT_HIGH);
|
||||
if (IS_ERR(ts_nbus->csn)) {
|
||||
dev_err(&pdev->dev, "failed to retrieve ts,csn-gpio from dts\n");
|
||||
return PTR_ERR(ts_nbus->csn);
|
||||
}
|
||||
if (IS_ERR(ts_nbus->csn))
|
||||
return dev_err_probe(&pdev->dev, PTR_ERR(ts_nbus->csn),
|
||||
"failed to retrieve ts,csn-gpio from dts\n");
|
||||
|
||||
ts_nbus->txrx = devm_gpiod_get(&pdev->dev, "ts,txrx", GPIOD_OUT_HIGH);
|
||||
if (IS_ERR(ts_nbus->txrx)) {
|
||||
dev_err(&pdev->dev, "failed to retrieve ts,txrx-gpio from dts\n");
|
||||
return PTR_ERR(ts_nbus->txrx);
|
||||
}
|
||||
if (IS_ERR(ts_nbus->txrx))
|
||||
return dev_err_probe(&pdev->dev, PTR_ERR(ts_nbus->txrx),
|
||||
"failed to retrieve ts,txrx-gpio from dts\n");
|
||||
|
||||
ts_nbus->strobe = devm_gpiod_get(&pdev->dev, "ts,strobe", GPIOD_OUT_HIGH);
|
||||
if (IS_ERR(ts_nbus->strobe)) {
|
||||
dev_err(&pdev->dev, "failed to retrieve ts,strobe-gpio from dts\n");
|
||||
return PTR_ERR(ts_nbus->strobe);
|
||||
}
|
||||
if (IS_ERR(ts_nbus->strobe))
|
||||
return dev_err_probe(&pdev->dev, PTR_ERR(ts_nbus->strobe),
|
||||
"failed to retrieve ts,strobe-gpio from dts\n");
|
||||
|
||||
ts_nbus->ale = devm_gpiod_get(&pdev->dev, "ts,ale", GPIOD_OUT_HIGH);
|
||||
if (IS_ERR(ts_nbus->ale)) {
|
||||
dev_err(&pdev->dev, "failed to retrieve ts,ale-gpio from dts\n");
|
||||
return PTR_ERR(ts_nbus->ale);
|
||||
}
|
||||
if (IS_ERR(ts_nbus->ale))
|
||||
return dev_err_probe(&pdev->dev, PTR_ERR(ts_nbus->ale),
|
||||
"failed to retrieve ts,ale-gpio from dts\n");
|
||||
|
||||
ts_nbus->rdy = devm_gpiod_get(&pdev->dev, "ts,rdy", GPIOD_IN);
|
||||
if (IS_ERR(ts_nbus->rdy)) {
|
||||
dev_err(&pdev->dev, "failed to retrieve ts,rdy-gpio from dts\n");
|
||||
return PTR_ERR(ts_nbus->rdy);
|
||||
}
|
||||
if (IS_ERR(ts_nbus->rdy))
|
||||
return dev_err_probe(&pdev->dev, PTR_ERR(ts_nbus->rdy),
|
||||
"failed to retrieve ts,rdy-gpio from dts\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -273,7 +267,7 @@ EXPORT_SYMBOL_GPL(ts_nbus_write);
|
|||
static int ts_nbus_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct pwm_device *pwm;
|
||||
struct pwm_args pargs;
|
||||
struct pwm_state state;
|
||||
struct device *dev = &pdev->dev;
|
||||
struct ts_nbus *ts_nbus;
|
||||
int ret;
|
||||
|
|
@ -289,32 +283,24 @@ static int ts_nbus_probe(struct platform_device *pdev)
|
|||
return ret;
|
||||
|
||||
pwm = devm_pwm_get(dev, NULL);
|
||||
if (IS_ERR(pwm)) {
|
||||
ret = PTR_ERR(pwm);
|
||||
if (ret != -EPROBE_DEFER)
|
||||
dev_err(dev, "unable to request PWM\n");
|
||||
return ret;
|
||||
}
|
||||
if (IS_ERR(pwm))
|
||||
return dev_err_probe(dev, PTR_ERR(pwm),
|
||||
"unable to request PWM\n");
|
||||
|
||||
pwm_get_args(pwm, &pargs);
|
||||
if (!pargs.period) {
|
||||
dev_err(&pdev->dev, "invalid PWM period\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
pwm_init_state(pwm, &state);
|
||||
if (!state.period)
|
||||
return dev_err_probe(dev, -EINVAL, "invalid PWM period\n");
|
||||
|
||||
/*
|
||||
* FIXME: pwm_apply_args() should be removed when switching to
|
||||
* the atomic PWM API.
|
||||
*/
|
||||
pwm_apply_args(pwm);
|
||||
ret = pwm_config(pwm, pargs.period, pargs.period);
|
||||
state.duty_cycle = state.period;
|
||||
state.enabled = true;
|
||||
|
||||
ret = pwm_apply_state(pwm, &state);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
return dev_err_probe(dev, ret, "failed to configure PWM\n");
|
||||
|
||||
/*
|
||||
* we can now start the FPGA and populate the peripherals.
|
||||
*/
|
||||
pwm_enable(pwm);
|
||||
ts_nbus->pwm = pwm;
|
||||
|
||||
/*
|
||||
|
|
@ -324,7 +310,8 @@ static int ts_nbus_probe(struct platform_device *pdev)
|
|||
|
||||
ret = of_platform_populate(dev->of_node, NULL, NULL, dev);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
return dev_err_probe(dev, ret,
|
||||
"failed to populate platform devices on bus\n");
|
||||
|
||||
dev_info(dev, "initialized\n");
|
||||
|
||||
|
|
|
|||
|
|
@ -376,14 +376,9 @@ static void __init of_omap2_apll_setup(struct device_node *node)
|
|||
}
|
||||
clk_hw->fixed_rate = val;
|
||||
|
||||
if (of_property_read_u32(node, "ti,bit-shift", &val)) {
|
||||
pr_err("%pOFn missing bit-shift\n", node);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
clk_hw->enable_bit = val;
|
||||
ad->enable_mask = 0x3 << val;
|
||||
ad->autoidle_mask = 0x3 << val;
|
||||
clk_hw->enable_bit = ti_clk_get_legacy_bit_shift(node);
|
||||
ad->enable_mask = 0x3 << clk_hw->enable_bit;
|
||||
ad->autoidle_mask = 0x3 << clk_hw->enable_bit;
|
||||
|
||||
if (of_property_read_u32(node, "ti,idlest-shift", &val)) {
|
||||
pr_err("%pOFn missing idlest-shift\n", node);
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@
|
|||
* Tero Kristo <t-kristo@ti.com>
|
||||
*/
|
||||
|
||||
#include <linux/cleanup.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/clk-provider.h>
|
||||
#include <linux/clkdev.h>
|
||||
|
|
@ -15,6 +16,7 @@
|
|||
#include <linux/of.h>
|
||||
#include <linux/of_address.h>
|
||||
#include <linux/list.h>
|
||||
#include <linux/minmax.h>
|
||||
#include <linux/regmap.h>
|
||||
#include <linux/string_helpers.h>
|
||||
#include <linux/memblock.h>
|
||||
|
|
@ -114,20 +116,26 @@ int ti_clk_setup_ll_ops(struct ti_clk_ll_ops *ops)
|
|||
|
||||
/*
|
||||
* Eventually we could standardize to using '_' for clk-*.c files to follow the
|
||||
* TRM naming and leave out the tmp name here.
|
||||
* TRM naming.
|
||||
*/
|
||||
static struct device_node *ti_find_clock_provider(struct device_node *from,
|
||||
const char *name)
|
||||
{
|
||||
char *tmp __free(kfree) = NULL;
|
||||
struct device_node *np;
|
||||
bool found = false;
|
||||
const char *n;
|
||||
char *tmp;
|
||||
char *p;
|
||||
|
||||
tmp = kstrdup_and_replace(name, '-', '_', GFP_KERNEL);
|
||||
if (!tmp)
|
||||
return NULL;
|
||||
|
||||
/* Ignore a possible address for the node name */
|
||||
p = strchr(tmp, '@');
|
||||
if (p)
|
||||
*p = '\0';
|
||||
|
||||
/* Node named "clock" with "clock-output-names" */
|
||||
for_each_of_allnodes_from(from, np) {
|
||||
if (of_property_read_string_index(np, "clock-output-names",
|
||||
|
|
@ -140,7 +148,6 @@ static struct device_node *ti_find_clock_provider(struct device_node *from,
|
|||
break;
|
||||
}
|
||||
}
|
||||
kfree(tmp);
|
||||
|
||||
if (found) {
|
||||
of_node_put(from);
|
||||
|
|
@ -148,7 +155,7 @@ static struct device_node *ti_find_clock_provider(struct device_node *from,
|
|||
}
|
||||
|
||||
/* Fall back to using old node name base provider name */
|
||||
return of_find_node_by_name(from, name);
|
||||
return of_find_node_by_name(from, tmp);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -301,8 +308,9 @@ int __init ti_clk_retry_init(struct device_node *node, void *user,
|
|||
int ti_clk_get_reg_addr(struct device_node *node, int index,
|
||||
struct clk_omap_reg *reg)
|
||||
{
|
||||
u32 val;
|
||||
int i;
|
||||
u32 clksel_addr, val;
|
||||
bool is_clksel = false;
|
||||
int i, err;
|
||||
|
||||
for (i = 0; i < CLK_MAX_MEMMAPS; i++) {
|
||||
if (clocks_node_ptr[i] == node->parent)
|
||||
|
|
@ -318,21 +326,62 @@ int ti_clk_get_reg_addr(struct device_node *node, int index,
|
|||
|
||||
reg->index = i;
|
||||
|
||||
if (of_property_read_u32_index(node, "reg", index, &val)) {
|
||||
if (of_property_read_u32_index(node->parent, "reg",
|
||||
index, &val)) {
|
||||
pr_err("%pOFn or parent must have reg[%d]!\n",
|
||||
node, index);
|
||||
if (of_device_is_compatible(node->parent, "ti,clksel")) {
|
||||
err = of_property_read_u32_index(node->parent, "reg", index, &clksel_addr);
|
||||
if (err) {
|
||||
pr_err("%pOFn parent clksel must have reg[%d]!\n", node, index);
|
||||
return -EINVAL;
|
||||
}
|
||||
is_clksel = true;
|
||||
}
|
||||
|
||||
err = of_property_read_u32_index(node, "reg", index, &val);
|
||||
if (err && is_clksel) {
|
||||
/* Legacy clksel with no reg and a possible ti,bit-shift property */
|
||||
reg->offset = clksel_addr;
|
||||
reg->bit = ti_clk_get_legacy_bit_shift(node);
|
||||
reg->ptr = NULL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Updated clksel clock with a proper reg property */
|
||||
if (is_clksel) {
|
||||
reg->offset = clksel_addr;
|
||||
reg->bit = val;
|
||||
reg->ptr = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Other clocks that may or may not have ti,bit-shift property */
|
||||
reg->offset = val;
|
||||
reg->bit = ti_clk_get_legacy_bit_shift(node);
|
||||
reg->ptr = NULL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* ti_clk_get_legacy_bit_shift - get bit shift for a clock register
|
||||
* @node: device node for the clock
|
||||
*
|
||||
* Gets the clock register bit shift using the legacy ti,bit-shift
|
||||
* property. Only needed for legacy clock, and can be eventually
|
||||
* dropped once all the composite clocks use a clksel node with a
|
||||
* proper reg property.
|
||||
*/
|
||||
int ti_clk_get_legacy_bit_shift(struct device_node *node)
|
||||
{
|
||||
int err;
|
||||
u32 val;
|
||||
|
||||
err = of_property_read_u32(node, "ti,bit-shift", &val);
|
||||
if (!err && in_range(val, 0, 32))
|
||||
return val;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void ti_clk_latch(struct clk_omap_reg *reg, s8 shift)
|
||||
{
|
||||
u32 latch;
|
||||
|
|
|
|||
|
|
@ -216,6 +216,7 @@ int ti_clk_parse_divider_data(int *div_table, int num_dividers, int max_div,
|
|||
|
||||
int ti_clk_get_reg_addr(struct device_node *node, int index,
|
||||
struct clk_omap_reg *reg);
|
||||
int ti_clk_get_legacy_bit_shift(struct device_node *node);
|
||||
void ti_dt_clocks_register(struct ti_dt_clk *oclks);
|
||||
int ti_clk_retry_init(struct device_node *node, void *user,
|
||||
ti_of_clk_init_cb_t func);
|
||||
|
|
|
|||
|
|
@ -477,10 +477,7 @@ static int __init ti_clk_divider_populate(struct device_node *node,
|
|||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (!of_property_read_u32(node, "ti,bit-shift", &val))
|
||||
div->shift = val;
|
||||
else
|
||||
div->shift = 0;
|
||||
div->shift = div->reg.bit;
|
||||
|
||||
if (!of_property_read_u32(node, "ti,latch-bit", &val))
|
||||
div->latch = val;
|
||||
|
|
|
|||
|
|
@ -132,7 +132,6 @@ static void __init _of_ti_gate_clk_setup(struct device_node *node,
|
|||
struct clk_omap_reg reg;
|
||||
const char *name;
|
||||
u8 enable_bit = 0;
|
||||
u32 val;
|
||||
u32 flags = 0;
|
||||
u8 clk_gate_flags = 0;
|
||||
|
||||
|
|
@ -140,8 +139,7 @@ static void __init _of_ti_gate_clk_setup(struct device_node *node,
|
|||
if (ti_clk_get_reg_addr(node, 0, ®))
|
||||
return;
|
||||
|
||||
if (!of_property_read_u32(node, "ti,bit-shift", &val))
|
||||
enable_bit = val;
|
||||
enable_bit = reg.bit;
|
||||
}
|
||||
|
||||
if (of_clk_get_parent_count(node) != 1) {
|
||||
|
|
@ -170,7 +168,6 @@ _of_ti_composite_gate_clk_setup(struct device_node *node,
|
|||
const struct clk_hw_omap_ops *hw_ops)
|
||||
{
|
||||
struct clk_hw_omap *gate;
|
||||
u32 val = 0;
|
||||
|
||||
gate = kzalloc(sizeof(*gate), GFP_KERNEL);
|
||||
if (!gate)
|
||||
|
|
@ -179,9 +176,7 @@ _of_ti_composite_gate_clk_setup(struct device_node *node,
|
|||
if (ti_clk_get_reg_addr(node, 0, &gate->enable_reg))
|
||||
goto cleanup;
|
||||
|
||||
of_property_read_u32(node, "ti,bit-shift", &val);
|
||||
|
||||
gate->enable_bit = val;
|
||||
gate->enable_bit = gate->enable_reg.bit;
|
||||
gate->ops = hw_ops;
|
||||
|
||||
if (!ti_clk_add_component(node, &gate->hw, CLK_COMPONENT_TYPE_GATE))
|
||||
|
|
|
|||
|
|
@ -66,13 +66,11 @@ static void __init _of_ti_interface_clk_setup(struct device_node *node,
|
|||
struct clk_omap_reg reg;
|
||||
u8 enable_bit = 0;
|
||||
const char *name;
|
||||
u32 val;
|
||||
|
||||
if (ti_clk_get_reg_addr(node, 0, ®))
|
||||
return;
|
||||
|
||||
if (!of_property_read_u32(node, "ti,bit-shift", &val))
|
||||
enable_bit = val;
|
||||
enable_bit = reg.bit;
|
||||
|
||||
parent_name = of_clk_get_parent_name(node, 0);
|
||||
if (!parent_name) {
|
||||
|
|
|
|||
|
|
@ -189,7 +189,7 @@ static void of_mux_clk_setup(struct device_node *node)
|
|||
if (ti_clk_get_reg_addr(node, 0, ®))
|
||||
goto cleanup;
|
||||
|
||||
of_property_read_u32(node, "ti,bit-shift", &shift);
|
||||
shift = reg.bit;
|
||||
|
||||
of_property_read_u32(node, "ti,latch-bit", &latch);
|
||||
|
||||
|
|
@ -252,7 +252,6 @@ static void __init of_ti_composite_mux_clk_setup(struct device_node *node)
|
|||
{
|
||||
struct clk_omap_mux *mux;
|
||||
unsigned int num_parents;
|
||||
u32 val;
|
||||
|
||||
mux = kzalloc(sizeof(*mux), GFP_KERNEL);
|
||||
if (!mux)
|
||||
|
|
@ -261,8 +260,7 @@ static void __init of_ti_composite_mux_clk_setup(struct device_node *node)
|
|||
if (ti_clk_get_reg_addr(node, 0, &mux->reg))
|
||||
goto cleanup;
|
||||
|
||||
if (!of_property_read_u32(node, "ti,bit-shift", &val))
|
||||
mux->shift = val;
|
||||
mux->shift = mux->reg.bit;
|
||||
|
||||
if (of_property_read_bool(node, "ti,index-starts-at-one"))
|
||||
mux->flags |= CLK_MUX_INDEX_ONE;
|
||||
|
|
|
|||
|
|
@ -208,7 +208,7 @@ static int dt_cpufreq_early_init(struct device *dev, int cpu)
|
|||
if (!priv)
|
||||
return -ENOMEM;
|
||||
|
||||
if (!alloc_cpumask_var(&priv->cpus, GFP_KERNEL))
|
||||
if (!zalloc_cpumask_var(&priv->cpus, GFP_KERNEL))
|
||||
return -ENOMEM;
|
||||
|
||||
cpumask_set_cpu(cpu, priv->cpus);
|
||||
|
|
|
|||
|
|
@ -653,14 +653,16 @@ static ssize_t store_local_boost(struct cpufreq_policy *policy,
|
|||
if (policy->boost_enabled == enable)
|
||||
return count;
|
||||
|
||||
policy->boost_enabled = enable;
|
||||
|
||||
cpus_read_lock();
|
||||
ret = cpufreq_driver->set_boost(policy, enable);
|
||||
cpus_read_unlock();
|
||||
|
||||
if (ret)
|
||||
if (ret) {
|
||||
policy->boost_enabled = !policy->boost_enabled;
|
||||
return ret;
|
||||
|
||||
policy->boost_enabled = enable;
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
|
@ -1428,6 +1430,9 @@ static int cpufreq_online(unsigned int cpu)
|
|||
goto out_free_policy;
|
||||
}
|
||||
|
||||
/* Let the per-policy boost flag mirror the cpufreq_driver boost during init */
|
||||
policy->boost_enabled = cpufreq_boost_enabled() && policy_has_boost_freq(policy);
|
||||
|
||||
/*
|
||||
* The initialization has succeeded and the policy is online.
|
||||
* If there is a problem with its frequency table, take it
|
||||
|
|
@ -2769,11 +2774,12 @@ int cpufreq_boost_trigger_state(int state)
|
|||
|
||||
cpus_read_lock();
|
||||
for_each_active_policy(policy) {
|
||||
ret = cpufreq_driver->set_boost(policy, state);
|
||||
if (ret)
|
||||
goto err_reset_state;
|
||||
|
||||
policy->boost_enabled = state;
|
||||
ret = cpufreq_driver->set_boost(policy, state);
|
||||
if (ret) {
|
||||
policy->boost_enabled = !policy->boost_enabled;
|
||||
goto err_reset_state;
|
||||
}
|
||||
}
|
||||
cpus_read_unlock();
|
||||
|
||||
|
|
|
|||
|
|
@ -40,7 +40,7 @@ int cpufreq_frequency_table_cpuinfo(struct cpufreq_policy *policy,
|
|||
cpufreq_for_each_valid_entry(pos, table) {
|
||||
freq = pos->frequency;
|
||||
|
||||
if (!cpufreq_boost_enabled()
|
||||
if ((!cpufreq_boost_enabled() || !policy->boost_enabled)
|
||||
&& (pos->flags & CPUFREQ_BOOST_FREQ))
|
||||
continue;
|
||||
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@ struct scmi_data {
|
|||
|
||||
static struct scmi_protocol_handle *ph;
|
||||
static const struct scmi_perf_proto_ops *perf_ops;
|
||||
static struct cpufreq_driver scmi_cpufreq_driver;
|
||||
|
||||
static unsigned int scmi_cpufreq_get_rate(unsigned int cpu)
|
||||
{
|
||||
|
|
@ -167,6 +168,12 @@ scmi_get_rate_limit(u32 domain, bool has_fast_switch)
|
|||
return rate_limit;
|
||||
}
|
||||
|
||||
static struct freq_attr *scmi_cpufreq_hw_attr[] = {
|
||||
&cpufreq_freq_attr_scaling_available_freqs,
|
||||
NULL,
|
||||
NULL,
|
||||
};
|
||||
|
||||
static int scmi_cpufreq_init(struct cpufreq_policy *policy)
|
||||
{
|
||||
int ret, nr_opp, domain;
|
||||
|
|
@ -276,6 +283,17 @@ static int scmi_cpufreq_init(struct cpufreq_policy *policy)
|
|||
policy->transition_delay_us =
|
||||
scmi_get_rate_limit(domain, policy->fast_switch_possible);
|
||||
|
||||
if (policy_has_boost_freq(policy)) {
|
||||
ret = cpufreq_enable_boost_support();
|
||||
if (ret) {
|
||||
dev_warn(cpu_dev, "failed to enable boost: %d\n", ret);
|
||||
goto out_free_opp;
|
||||
} else {
|
||||
scmi_cpufreq_hw_attr[1] = &cpufreq_freq_attr_scaling_boost_freqs;
|
||||
scmi_cpufreq_driver.boost_enabled = true;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
out_free_opp:
|
||||
|
|
@ -334,7 +352,7 @@ static struct cpufreq_driver scmi_cpufreq_driver = {
|
|||
CPUFREQ_NEED_INITIAL_FREQ_CHECK |
|
||||
CPUFREQ_IS_COOLING_DEV,
|
||||
.verify = cpufreq_generic_frequency_table_verify,
|
||||
.attr = cpufreq_generic_attr,
|
||||
.attr = scmi_cpufreq_hw_attr,
|
||||
.target_index = scmi_cpufreq_set_target,
|
||||
.fast_switch = scmi_cpufreq_fast_switch,
|
||||
.get = scmi_cpufreq_get_rate,
|
||||
|
|
|
|||
|
|
@ -646,18 +646,18 @@ u64 cxl_trace_hpa(struct cxl_region *cxlr, struct cxl_memdev *memdev, u64 dpa);
|
|||
|
||||
TRACE_EVENT(cxl_poison,
|
||||
|
||||
TP_PROTO(struct cxl_memdev *cxlmd, struct cxl_region *region,
|
||||
TP_PROTO(struct cxl_memdev *cxlmd, struct cxl_region *cxlr,
|
||||
const struct cxl_poison_record *record, u8 flags,
|
||||
__le64 overflow_ts, enum cxl_poison_trace_type trace_type),
|
||||
|
||||
TP_ARGS(cxlmd, region, record, flags, overflow_ts, trace_type),
|
||||
TP_ARGS(cxlmd, cxlr, record, flags, overflow_ts, trace_type),
|
||||
|
||||
TP_STRUCT__entry(
|
||||
__string(memdev, dev_name(&cxlmd->dev))
|
||||
__string(host, dev_name(cxlmd->dev.parent))
|
||||
__field(u64, serial)
|
||||
__field(u8, trace_type)
|
||||
__string(region, region)
|
||||
__string(region, cxlr ? dev_name(&cxlr->dev) : "")
|
||||
__field(u64, overflow_ts)
|
||||
__field(u64, hpa)
|
||||
__field(u64, dpa)
|
||||
|
|
@ -677,10 +677,10 @@ TRACE_EVENT(cxl_poison,
|
|||
__entry->source = cxl_poison_record_source(record);
|
||||
__entry->trace_type = trace_type;
|
||||
__entry->flags = flags;
|
||||
if (region) {
|
||||
__assign_str(region, dev_name(®ion->dev));
|
||||
memcpy(__entry->uuid, ®ion->params.uuid, 16);
|
||||
__entry->hpa = cxl_trace_hpa(region, cxlmd,
|
||||
if (cxlr) {
|
||||
__assign_str(region, dev_name(&cxlr->dev));
|
||||
memcpy(__entry->uuid, &cxlr->params.uuid, 16);
|
||||
__entry->hpa = cxl_trace_hpa(cxlr, cxlmd,
|
||||
__entry->dpa);
|
||||
} else {
|
||||
__assign_str(region, "");
|
||||
|
|
|
|||
|
|
@ -871,6 +871,9 @@ static int scmi_dvfs_device_opps_add(const struct scmi_protocol_handle *ph,
|
|||
else
|
||||
freq = dom->opp[idx].indicative_freq * dom->mult_factor;
|
||||
|
||||
/* All OPPs above the sustained frequency are treated as turbo */
|
||||
data.turbo = freq > dom->sustained_freq_khz * 1000;
|
||||
|
||||
data.level = dom->opp[idx].perf;
|
||||
data.freq = freq;
|
||||
|
||||
|
|
|
|||
|
|
@ -411,7 +411,7 @@ TRACE_EVENT(intel_fbc_activate,
|
|||
struct intel_crtc *crtc = intel_crtc_for_pipe(to_i915(plane->base.dev),
|
||||
plane->pipe);
|
||||
__assign_str(dev, __dev_name_kms(plane));
|
||||
__assign_str(name, plane->base.name)
|
||||
__assign_str(name, plane->base.name);
|
||||
__entry->pipe = crtc->pipe;
|
||||
__entry->frame = intel_crtc_get_vblank_counter(crtc);
|
||||
__entry->scanline = intel_get_crtc_scanline(crtc);
|
||||
|
|
@ -438,7 +438,7 @@ TRACE_EVENT(intel_fbc_deactivate,
|
|||
struct intel_crtc *crtc = intel_crtc_for_pipe(to_i915(plane->base.dev),
|
||||
plane->pipe);
|
||||
__assign_str(dev, __dev_name_kms(plane));
|
||||
__assign_str(name, plane->base.name)
|
||||
__assign_str(name, plane->base.name);
|
||||
__entry->pipe = crtc->pipe;
|
||||
__entry->frame = intel_crtc_get_vblank_counter(crtc);
|
||||
__entry->scanline = intel_get_crtc_scanline(crtc);
|
||||
|
|
@ -465,7 +465,7 @@ TRACE_EVENT(intel_fbc_nuke,
|
|||
struct intel_crtc *crtc = intel_crtc_for_pipe(to_i915(plane->base.dev),
|
||||
plane->pipe);
|
||||
__assign_str(dev, __dev_name_kms(plane));
|
||||
__assign_str(name, plane->base.name)
|
||||
__assign_str(name, plane->base.name);
|
||||
__entry->pipe = crtc->pipe;
|
||||
__entry->frame = intel_crtc_get_vblank_counter(crtc);
|
||||
__entry->scanline = intel_get_crtc_scanline(crtc);
|
||||
|
|
|
|||
|
|
@ -34,6 +34,7 @@ MODULE_AUTHOR("Sean Hefty");
|
|||
MODULE_DESCRIPTION("InfiniBand CM");
|
||||
MODULE_LICENSE("Dual BSD/GPL");
|
||||
|
||||
#define CM_DESTROY_ID_WAIT_TIMEOUT 10000 /* msecs */
|
||||
static const char * const ibcm_rej_reason_strs[] = {
|
||||
[IB_CM_REJ_NO_QP] = "no QP",
|
||||
[IB_CM_REJ_NO_EEC] = "no EEC",
|
||||
|
|
@ -1025,10 +1026,20 @@ static void cm_reset_to_idle(struct cm_id_private *cm_id_priv)
|
|||
}
|
||||
}
|
||||
|
||||
static noinline void cm_destroy_id_wait_timeout(struct ib_cm_id *cm_id)
|
||||
{
|
||||
struct cm_id_private *cm_id_priv;
|
||||
|
||||
cm_id_priv = container_of(cm_id, struct cm_id_private, id);
|
||||
pr_err("%s: cm_id=%p timed out. state=%d refcnt=%d\n", __func__,
|
||||
cm_id, cm_id->state, refcount_read(&cm_id_priv->refcount));
|
||||
}
|
||||
|
||||
static void cm_destroy_id(struct ib_cm_id *cm_id, int err)
|
||||
{
|
||||
struct cm_id_private *cm_id_priv;
|
||||
struct cm_work *work;
|
||||
int ret;
|
||||
|
||||
cm_id_priv = container_of(cm_id, struct cm_id_private, id);
|
||||
spin_lock_irq(&cm_id_priv->lock);
|
||||
|
|
@ -1135,7 +1146,14 @@ static void cm_destroy_id(struct ib_cm_id *cm_id, int err)
|
|||
|
||||
xa_erase(&cm.local_id_table, cm_local_id(cm_id->local_id));
|
||||
cm_deref_id(cm_id_priv);
|
||||
wait_for_completion(&cm_id_priv->comp);
|
||||
do {
|
||||
ret = wait_for_completion_timeout(&cm_id_priv->comp,
|
||||
msecs_to_jiffies(
|
||||
CM_DESTROY_ID_WAIT_TIMEOUT));
|
||||
if (!ret) /* timeout happened */
|
||||
cm_destroy_id_wait_timeout(cm_id);
|
||||
} while (!ret);
|
||||
|
||||
while ((work = cm_dequeue_work(cm_id_priv)) != NULL)
|
||||
cm_free_work(work);
|
||||
|
||||
|
|
|
|||
|
|
@ -1730,7 +1730,7 @@ static int assign_client_id(struct ib_client *client)
|
|||
{
|
||||
int ret;
|
||||
|
||||
down_write(&clients_rwsem);
|
||||
lockdep_assert_held(&clients_rwsem);
|
||||
/*
|
||||
* The add/remove callbacks must be called in FIFO/LIFO order. To
|
||||
* achieve this we assign client_ids so they are sorted in
|
||||
|
|
@ -1739,14 +1739,11 @@ static int assign_client_id(struct ib_client *client)
|
|||
client->client_id = highest_client_id;
|
||||
ret = xa_insert(&clients, client->client_id, client, GFP_KERNEL);
|
||||
if (ret)
|
||||
goto out;
|
||||
return ret;
|
||||
|
||||
highest_client_id++;
|
||||
xa_set_mark(&clients, client->client_id, CLIENT_REGISTERED);
|
||||
|
||||
out:
|
||||
up_write(&clients_rwsem);
|
||||
return ret;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void remove_client_id(struct ib_client *client)
|
||||
|
|
@ -1776,25 +1773,35 @@ int ib_register_client(struct ib_client *client)
|
|||
{
|
||||
struct ib_device *device;
|
||||
unsigned long index;
|
||||
bool need_unreg = false;
|
||||
int ret;
|
||||
|
||||
refcount_set(&client->uses, 1);
|
||||
init_completion(&client->uses_zero);
|
||||
|
||||
/*
|
||||
* The devices_rwsem is held in write mode to ensure that a racing
|
||||
* ib_register_device() sees a consisent view of clients and devices.
|
||||
*/
|
||||
down_write(&devices_rwsem);
|
||||
down_write(&clients_rwsem);
|
||||
ret = assign_client_id(client);
|
||||
if (ret)
|
||||
return ret;
|
||||
goto out;
|
||||
|
||||
down_read(&devices_rwsem);
|
||||
need_unreg = true;
|
||||
xa_for_each_marked (&devices, index, device, DEVICE_REGISTERED) {
|
||||
ret = add_client_context(device, client);
|
||||
if (ret) {
|
||||
up_read(&devices_rwsem);
|
||||
ib_unregister_client(client);
|
||||
return ret;
|
||||
}
|
||||
if (ret)
|
||||
goto out;
|
||||
}
|
||||
up_read(&devices_rwsem);
|
||||
return 0;
|
||||
ret = 0;
|
||||
out:
|
||||
up_write(&clients_rwsem);
|
||||
up_write(&devices_rwsem);
|
||||
if (need_unreg && ret)
|
||||
ib_unregister_client(client);
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(ib_register_client);
|
||||
|
||||
|
|
|
|||
|
|
@ -2737,7 +2737,7 @@ int ib_uverbs_kern_spec_to_ib_spec_filter(enum ib_flow_spec_type type,
|
|||
|
||||
switch (ib_spec->type & ~IB_FLOW_SPEC_INNER) {
|
||||
case IB_FLOW_SPEC_ETH:
|
||||
ib_filter_sz = offsetof(struct ib_flow_eth_filter, real_sz);
|
||||
ib_filter_sz = sizeof(struct ib_flow_eth_filter);
|
||||
actual_filter_sz = spec_filter_size(kern_spec_mask,
|
||||
kern_filter_sz,
|
||||
ib_filter_sz);
|
||||
|
|
@ -2748,7 +2748,7 @@ int ib_uverbs_kern_spec_to_ib_spec_filter(enum ib_flow_spec_type type,
|
|||
memcpy(&ib_spec->eth.mask, kern_spec_mask, actual_filter_sz);
|
||||
break;
|
||||
case IB_FLOW_SPEC_IPV4:
|
||||
ib_filter_sz = offsetof(struct ib_flow_ipv4_filter, real_sz);
|
||||
ib_filter_sz = sizeof(struct ib_flow_ipv4_filter);
|
||||
actual_filter_sz = spec_filter_size(kern_spec_mask,
|
||||
kern_filter_sz,
|
||||
ib_filter_sz);
|
||||
|
|
@ -2759,7 +2759,7 @@ int ib_uverbs_kern_spec_to_ib_spec_filter(enum ib_flow_spec_type type,
|
|||
memcpy(&ib_spec->ipv4.mask, kern_spec_mask, actual_filter_sz);
|
||||
break;
|
||||
case IB_FLOW_SPEC_IPV6:
|
||||
ib_filter_sz = offsetof(struct ib_flow_ipv6_filter, real_sz);
|
||||
ib_filter_sz = sizeof(struct ib_flow_ipv6_filter);
|
||||
actual_filter_sz = spec_filter_size(kern_spec_mask,
|
||||
kern_filter_sz,
|
||||
ib_filter_sz);
|
||||
|
|
@ -2775,7 +2775,7 @@ int ib_uverbs_kern_spec_to_ib_spec_filter(enum ib_flow_spec_type type,
|
|||
break;
|
||||
case IB_FLOW_SPEC_TCP:
|
||||
case IB_FLOW_SPEC_UDP:
|
||||
ib_filter_sz = offsetof(struct ib_flow_tcp_udp_filter, real_sz);
|
||||
ib_filter_sz = sizeof(struct ib_flow_tcp_udp_filter);
|
||||
actual_filter_sz = spec_filter_size(kern_spec_mask,
|
||||
kern_filter_sz,
|
||||
ib_filter_sz);
|
||||
|
|
@ -2786,7 +2786,7 @@ int ib_uverbs_kern_spec_to_ib_spec_filter(enum ib_flow_spec_type type,
|
|||
memcpy(&ib_spec->tcp_udp.mask, kern_spec_mask, actual_filter_sz);
|
||||
break;
|
||||
case IB_FLOW_SPEC_VXLAN_TUNNEL:
|
||||
ib_filter_sz = offsetof(struct ib_flow_tunnel_filter, real_sz);
|
||||
ib_filter_sz = sizeof(struct ib_flow_tunnel_filter);
|
||||
actual_filter_sz = spec_filter_size(kern_spec_mask,
|
||||
kern_filter_sz,
|
||||
ib_filter_sz);
|
||||
|
|
@ -2801,7 +2801,7 @@ int ib_uverbs_kern_spec_to_ib_spec_filter(enum ib_flow_spec_type type,
|
|||
return -EINVAL;
|
||||
break;
|
||||
case IB_FLOW_SPEC_ESP:
|
||||
ib_filter_sz = offsetof(struct ib_flow_esp_filter, real_sz);
|
||||
ib_filter_sz = sizeof(struct ib_flow_esp_filter);
|
||||
actual_filter_sz = spec_filter_size(kern_spec_mask,
|
||||
kern_filter_sz,
|
||||
ib_filter_sz);
|
||||
|
|
@ -2812,7 +2812,7 @@ int ib_uverbs_kern_spec_to_ib_spec_filter(enum ib_flow_spec_type type,
|
|||
memcpy(&ib_spec->esp.mask, kern_spec_mask, actual_filter_sz);
|
||||
break;
|
||||
case IB_FLOW_SPEC_GRE:
|
||||
ib_filter_sz = offsetof(struct ib_flow_gre_filter, real_sz);
|
||||
ib_filter_sz = sizeof(struct ib_flow_gre_filter);
|
||||
actual_filter_sz = spec_filter_size(kern_spec_mask,
|
||||
kern_filter_sz,
|
||||
ib_filter_sz);
|
||||
|
|
@ -2823,7 +2823,7 @@ int ib_uverbs_kern_spec_to_ib_spec_filter(enum ib_flow_spec_type type,
|
|||
memcpy(&ib_spec->gre.mask, kern_spec_mask, actual_filter_sz);
|
||||
break;
|
||||
case IB_FLOW_SPEC_MPLS:
|
||||
ib_filter_sz = offsetof(struct ib_flow_mpls_filter, real_sz);
|
||||
ib_filter_sz = sizeof(struct ib_flow_mpls_filter);
|
||||
actual_filter_sz = spec_filter_size(kern_spec_mask,
|
||||
kern_filter_sz,
|
||||
ib_filter_sz);
|
||||
|
|
|
|||
|
|
@ -36,13 +36,15 @@
|
|||
#include "uverbs.h"
|
||||
|
||||
struct bundle_alloc_head {
|
||||
struct bundle_alloc_head *next;
|
||||
struct_group_tagged(bundle_alloc_head_hdr, hdr,
|
||||
struct bundle_alloc_head *next;
|
||||
);
|
||||
u8 data[];
|
||||
};
|
||||
|
||||
struct bundle_priv {
|
||||
/* Must be first */
|
||||
struct bundle_alloc_head alloc_head;
|
||||
struct bundle_alloc_head_hdr alloc_head;
|
||||
struct bundle_alloc_head *allocated_mem;
|
||||
size_t internal_avail;
|
||||
size_t internal_used;
|
||||
|
|
@ -64,7 +66,7 @@ struct bundle_priv {
|
|||
* Must be last. bundle ends in a flex array which overlaps
|
||||
* internal_buffer.
|
||||
*/
|
||||
struct uverbs_attr_bundle bundle;
|
||||
struct uverbs_attr_bundle_hdr bundle;
|
||||
u64 internal_buffer[32];
|
||||
};
|
||||
|
||||
|
|
@ -77,9 +79,10 @@ void uapi_compute_bundle_size(struct uverbs_api_ioctl_method *method_elm,
|
|||
unsigned int num_attrs)
|
||||
{
|
||||
struct bundle_priv *pbundle;
|
||||
struct uverbs_attr_bundle *bundle;
|
||||
size_t bundle_size =
|
||||
offsetof(struct bundle_priv, internal_buffer) +
|
||||
sizeof(*pbundle->bundle.attrs) * method_elm->key_bitmap_len +
|
||||
sizeof(*bundle->attrs) * method_elm->key_bitmap_len +
|
||||
sizeof(*pbundle->uattrs) * num_attrs;
|
||||
|
||||
method_elm->use_stack = bundle_size <= sizeof(*pbundle);
|
||||
|
|
@ -107,7 +110,7 @@ __malloc void *_uverbs_alloc(struct uverbs_attr_bundle *bundle, size_t size,
|
|||
gfp_t flags)
|
||||
{
|
||||
struct bundle_priv *pbundle =
|
||||
container_of(bundle, struct bundle_priv, bundle);
|
||||
container_of(&bundle->hdr, struct bundle_priv, bundle);
|
||||
size_t new_used;
|
||||
void *res;
|
||||
|
||||
|
|
@ -149,7 +152,7 @@ static int uverbs_set_output(const struct uverbs_attr_bundle *bundle,
|
|||
const struct uverbs_attr *attr)
|
||||
{
|
||||
struct bundle_priv *pbundle =
|
||||
container_of(bundle, struct bundle_priv, bundle);
|
||||
container_of(&bundle->hdr, struct bundle_priv, bundle);
|
||||
u16 flags;
|
||||
|
||||
flags = pbundle->uattrs[attr->ptr_attr.uattr_idx].flags |
|
||||
|
|
@ -166,6 +169,8 @@ static int uverbs_process_idrs_array(struct bundle_priv *pbundle,
|
|||
struct ib_uverbs_attr *uattr,
|
||||
u32 attr_bkey)
|
||||
{
|
||||
struct uverbs_attr_bundle *bundle =
|
||||
container_of(&pbundle->bundle, struct uverbs_attr_bundle, hdr);
|
||||
const struct uverbs_attr_spec *spec = &attr_uapi->spec;
|
||||
size_t array_len;
|
||||
u32 *idr_vals;
|
||||
|
|
@ -184,7 +189,7 @@ static int uverbs_process_idrs_array(struct bundle_priv *pbundle,
|
|||
return -EINVAL;
|
||||
|
||||
attr->uobjects =
|
||||
uverbs_alloc(&pbundle->bundle,
|
||||
uverbs_alloc(bundle,
|
||||
array_size(array_len, sizeof(*attr->uobjects)));
|
||||
if (IS_ERR(attr->uobjects))
|
||||
return PTR_ERR(attr->uobjects);
|
||||
|
|
@ -209,7 +214,7 @@ static int uverbs_process_idrs_array(struct bundle_priv *pbundle,
|
|||
for (i = 0; i != array_len; i++) {
|
||||
attr->uobjects[i] = uverbs_get_uobject_from_file(
|
||||
spec->u2.objs_arr.obj_type, spec->u2.objs_arr.access,
|
||||
idr_vals[i], &pbundle->bundle);
|
||||
idr_vals[i], bundle);
|
||||
if (IS_ERR(attr->uobjects[i])) {
|
||||
ret = PTR_ERR(attr->uobjects[i]);
|
||||
break;
|
||||
|
|
@ -240,7 +245,9 @@ static int uverbs_process_attr(struct bundle_priv *pbundle,
|
|||
struct ib_uverbs_attr *uattr, u32 attr_bkey)
|
||||
{
|
||||
const struct uverbs_attr_spec *spec = &attr_uapi->spec;
|
||||
struct uverbs_attr *e = &pbundle->bundle.attrs[attr_bkey];
|
||||
struct uverbs_attr_bundle *bundle =
|
||||
container_of(&pbundle->bundle, struct uverbs_attr_bundle, hdr);
|
||||
struct uverbs_attr *e = &bundle->attrs[attr_bkey];
|
||||
const struct uverbs_attr_spec *val_spec = spec;
|
||||
struct uverbs_obj_attr *o_attr;
|
||||
|
||||
|
|
@ -288,7 +295,7 @@ static int uverbs_process_attr(struct bundle_priv *pbundle,
|
|||
if (val_spec->alloc_and_copy && !uverbs_attr_ptr_is_inline(e)) {
|
||||
void *p;
|
||||
|
||||
p = uverbs_alloc(&pbundle->bundle, uattr->len);
|
||||
p = uverbs_alloc(bundle, uattr->len);
|
||||
if (IS_ERR(p))
|
||||
return PTR_ERR(p);
|
||||
|
||||
|
|
@ -321,7 +328,7 @@ static int uverbs_process_attr(struct bundle_priv *pbundle,
|
|||
*/
|
||||
o_attr->uobject = uverbs_get_uobject_from_file(
|
||||
spec->u.obj.obj_type, spec->u.obj.access,
|
||||
uattr->data_s64, &pbundle->bundle);
|
||||
uattr->data_s64, bundle);
|
||||
if (IS_ERR(o_attr->uobject))
|
||||
return PTR_ERR(o_attr->uobject);
|
||||
__set_bit(attr_bkey, pbundle->uobj_finalize);
|
||||
|
|
@ -422,6 +429,8 @@ static int ib_uverbs_run_method(struct bundle_priv *pbundle,
|
|||
unsigned int num_attrs)
|
||||
{
|
||||
int (*handler)(struct uverbs_attr_bundle *attrs);
|
||||
struct uverbs_attr_bundle *bundle =
|
||||
container_of(&pbundle->bundle, struct uverbs_attr_bundle, hdr);
|
||||
size_t uattrs_size = array_size(sizeof(*pbundle->uattrs), num_attrs);
|
||||
unsigned int destroy_bkey = pbundle->method_elm->destroy_bkey;
|
||||
unsigned int i;
|
||||
|
|
@ -434,7 +443,7 @@ static int ib_uverbs_run_method(struct bundle_priv *pbundle,
|
|||
if (!handler)
|
||||
return -EIO;
|
||||
|
||||
pbundle->uattrs = uverbs_alloc(&pbundle->bundle, uattrs_size);
|
||||
pbundle->uattrs = uverbs_alloc(bundle, uattrs_size);
|
||||
if (IS_ERR(pbundle->uattrs))
|
||||
return PTR_ERR(pbundle->uattrs);
|
||||
if (copy_from_user(pbundle->uattrs, pbundle->user_attrs, uattrs_size))
|
||||
|
|
@ -453,25 +462,23 @@ static int ib_uverbs_run_method(struct bundle_priv *pbundle,
|
|||
return -EINVAL;
|
||||
|
||||
if (pbundle->method_elm->has_udata)
|
||||
uverbs_fill_udata(&pbundle->bundle,
|
||||
&pbundle->bundle.driver_udata,
|
||||
uverbs_fill_udata(bundle, &pbundle->bundle.driver_udata,
|
||||
UVERBS_ATTR_UHW_IN, UVERBS_ATTR_UHW_OUT);
|
||||
else
|
||||
pbundle->bundle.driver_udata = (struct ib_udata){};
|
||||
|
||||
if (destroy_bkey != UVERBS_API_ATTR_BKEY_LEN) {
|
||||
struct uverbs_obj_attr *destroy_attr =
|
||||
&pbundle->bundle.attrs[destroy_bkey].obj_attr;
|
||||
struct uverbs_obj_attr *destroy_attr = &bundle->attrs[destroy_bkey].obj_attr;
|
||||
|
||||
ret = uobj_destroy(destroy_attr->uobject, &pbundle->bundle);
|
||||
ret = uobj_destroy(destroy_attr->uobject, bundle);
|
||||
if (ret)
|
||||
return ret;
|
||||
__clear_bit(destroy_bkey, pbundle->uobj_finalize);
|
||||
|
||||
ret = handler(&pbundle->bundle);
|
||||
ret = handler(bundle);
|
||||
uobj_put_destroy(destroy_attr->uobject);
|
||||
} else {
|
||||
ret = handler(&pbundle->bundle);
|
||||
ret = handler(bundle);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -481,10 +488,10 @@ static int ib_uverbs_run_method(struct bundle_priv *pbundle,
|
|||
*/
|
||||
if (!ret && pbundle->method_elm->has_udata) {
|
||||
const struct uverbs_attr *attr =
|
||||
uverbs_attr_get(&pbundle->bundle, UVERBS_ATTR_UHW_OUT);
|
||||
uverbs_attr_get(bundle, UVERBS_ATTR_UHW_OUT);
|
||||
|
||||
if (!IS_ERR(attr))
|
||||
ret = uverbs_set_output(&pbundle->bundle, attr);
|
||||
ret = uverbs_set_output(bundle, attr);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -501,6 +508,8 @@ static int ib_uverbs_run_method(struct bundle_priv *pbundle,
|
|||
static void bundle_destroy(struct bundle_priv *pbundle, bool commit)
|
||||
{
|
||||
unsigned int key_bitmap_len = pbundle->method_elm->key_bitmap_len;
|
||||
struct uverbs_attr_bundle *bundle =
|
||||
container_of(&pbundle->bundle, struct uverbs_attr_bundle, hdr);
|
||||
struct bundle_alloc_head *memblock;
|
||||
unsigned int i;
|
||||
|
||||
|
|
@ -508,20 +517,19 @@ static void bundle_destroy(struct bundle_priv *pbundle, bool commit)
|
|||
i = -1;
|
||||
while ((i = find_next_bit(pbundle->uobj_finalize, key_bitmap_len,
|
||||
i + 1)) < key_bitmap_len) {
|
||||
struct uverbs_attr *attr = &pbundle->bundle.attrs[i];
|
||||
struct uverbs_attr *attr = &bundle->attrs[i];
|
||||
|
||||
uverbs_finalize_object(
|
||||
attr->obj_attr.uobject,
|
||||
attr->obj_attr.attr_elm->spec.u.obj.access,
|
||||
test_bit(i, pbundle->uobj_hw_obj_valid),
|
||||
commit,
|
||||
&pbundle->bundle);
|
||||
commit, bundle);
|
||||
}
|
||||
|
||||
i = -1;
|
||||
while ((i = find_next_bit(pbundle->spec_finalize, key_bitmap_len,
|
||||
i + 1)) < key_bitmap_len) {
|
||||
struct uverbs_attr *attr = &pbundle->bundle.attrs[i];
|
||||
struct uverbs_attr *attr = &bundle->attrs[i];
|
||||
const struct uverbs_api_attr *attr_uapi;
|
||||
void __rcu **slot;
|
||||
|
||||
|
|
@ -535,7 +543,7 @@ static void bundle_destroy(struct bundle_priv *pbundle, bool commit)
|
|||
|
||||
if (attr_uapi->spec.type == UVERBS_ATTR_TYPE_IDRS_ARRAY) {
|
||||
uverbs_free_idrs_array(attr_uapi, &attr->objs_arr_attr,
|
||||
commit, &pbundle->bundle);
|
||||
commit, bundle);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -578,7 +586,8 @@ static int ib_uverbs_cmd_verbs(struct ib_uverbs_file *ufile,
|
|||
method_elm->bundle_size -
|
||||
offsetof(struct bundle_priv, internal_buffer);
|
||||
pbundle->alloc_head.next = NULL;
|
||||
pbundle->allocated_mem = &pbundle->alloc_head;
|
||||
pbundle->allocated_mem = container_of(&pbundle->alloc_head,
|
||||
struct bundle_alloc_head, hdr);
|
||||
} else {
|
||||
pbundle = &onstack;
|
||||
pbundle->internal_avail = sizeof(pbundle->internal_buffer);
|
||||
|
|
@ -596,8 +605,9 @@ static int ib_uverbs_cmd_verbs(struct ib_uverbs_file *ufile,
|
|||
pbundle->user_attrs = user_attrs;
|
||||
|
||||
pbundle->internal_used = ALIGN(pbundle->method_elm->key_bitmap_len *
|
||||
sizeof(*pbundle->bundle.attrs),
|
||||
sizeof(*pbundle->internal_buffer));
|
||||
sizeof(*container_of(&pbundle->bundle,
|
||||
struct uverbs_attr_bundle, hdr)->attrs),
|
||||
sizeof(*pbundle->internal_buffer));
|
||||
memset(pbundle->bundle.attr_present, 0,
|
||||
sizeof(pbundle->bundle.attr_present));
|
||||
memset(pbundle->uobj_finalize, 0, sizeof(pbundle->uobj_finalize));
|
||||
|
|
@ -700,11 +710,13 @@ void uverbs_fill_udata(struct uverbs_attr_bundle *bundle,
|
|||
unsigned int attr_out)
|
||||
{
|
||||
struct bundle_priv *pbundle =
|
||||
container_of(bundle, struct bundle_priv, bundle);
|
||||
container_of(&bundle->hdr, struct bundle_priv, bundle);
|
||||
struct uverbs_attr_bundle *bundle_aux =
|
||||
container_of(&pbundle->bundle, struct uverbs_attr_bundle, hdr);
|
||||
const struct uverbs_attr *in =
|
||||
uverbs_attr_get(&pbundle->bundle, attr_in);
|
||||
uverbs_attr_get(bundle_aux, attr_in);
|
||||
const struct uverbs_attr *out =
|
||||
uverbs_attr_get(&pbundle->bundle, attr_out);
|
||||
uverbs_attr_get(bundle_aux, attr_out);
|
||||
|
||||
if (!IS_ERR(in)) {
|
||||
udata->inlen = in->ptr_attr.len;
|
||||
|
|
@ -829,7 +841,7 @@ void uverbs_finalize_uobj_create(const struct uverbs_attr_bundle *bundle,
|
|||
u16 idx)
|
||||
{
|
||||
struct bundle_priv *pbundle =
|
||||
container_of(bundle, struct bundle_priv, bundle);
|
||||
container_of(&bundle->hdr, struct bundle_priv, bundle);
|
||||
|
||||
__set_bit(uapi_bkey_attr(uapi_key_attr(idx)),
|
||||
pbundle->uobj_hw_obj_valid);
|
||||
|
|
|
|||
|
|
@ -930,8 +930,6 @@ void c4iw_id_table_free(struct c4iw_id_table *alloc);
|
|||
|
||||
typedef int (*c4iw_handler_func)(struct c4iw_dev *dev, struct sk_buff *skb);
|
||||
|
||||
int c4iw_ep_redirect(void *ctx, struct dst_entry *old, struct dst_entry *new,
|
||||
struct l2t_entry *l2t);
|
||||
void c4iw_put_qpid(struct c4iw_rdev *rdev, u32 qpid,
|
||||
struct c4iw_dev_ucontext *uctx);
|
||||
u32 c4iw_get_resource(struct c4iw_id_table *id_table);
|
||||
|
|
|
|||
|
|
@ -57,6 +57,7 @@ struct efa_dev {
|
|||
u64 db_bar_addr;
|
||||
u64 db_bar_len;
|
||||
|
||||
unsigned int num_irq_vectors;
|
||||
int admin_msix_vector_idx;
|
||||
struct efa_irq admin_irq;
|
||||
|
||||
|
|
|
|||
|
|
@ -322,7 +322,9 @@ static int efa_create_eqs(struct efa_dev *dev)
|
|||
int err;
|
||||
int i;
|
||||
|
||||
neqs = min_t(unsigned int, neqs, num_online_cpus());
|
||||
neqs = min_t(unsigned int, neqs,
|
||||
dev->num_irq_vectors - EFA_COMP_EQS_VEC_BASE);
|
||||
|
||||
dev->neqs = neqs;
|
||||
dev->eqs = kcalloc(neqs, sizeof(*dev->eqs), GFP_KERNEL);
|
||||
if (!dev->eqs)
|
||||
|
|
@ -468,34 +470,30 @@ static void efa_disable_msix(struct efa_dev *dev)
|
|||
|
||||
static int efa_enable_msix(struct efa_dev *dev)
|
||||
{
|
||||
int msix_vecs, irq_num;
|
||||
int max_vecs, num_vecs;
|
||||
|
||||
/*
|
||||
* Reserve the max msix vectors we might need, one vector is reserved
|
||||
* for admin.
|
||||
*/
|
||||
msix_vecs = min_t(int, pci_msix_vec_count(dev->pdev),
|
||||
num_online_cpus() + 1);
|
||||
max_vecs = min_t(int, pci_msix_vec_count(dev->pdev),
|
||||
num_online_cpus() + 1);
|
||||
dev_dbg(&dev->pdev->dev, "Trying to enable MSI-X, vectors %d\n",
|
||||
msix_vecs);
|
||||
max_vecs);
|
||||
|
||||
dev->admin_msix_vector_idx = EFA_MGMNT_MSIX_VEC_IDX;
|
||||
irq_num = pci_alloc_irq_vectors(dev->pdev, msix_vecs,
|
||||
msix_vecs, PCI_IRQ_MSIX);
|
||||
num_vecs = pci_alloc_irq_vectors(dev->pdev, 1,
|
||||
max_vecs, PCI_IRQ_MSIX);
|
||||
|
||||
if (irq_num < 0) {
|
||||
dev_err(&dev->pdev->dev, "Failed to enable MSI-X. irq_num %d\n",
|
||||
irq_num);
|
||||
if (num_vecs < 0) {
|
||||
dev_err(&dev->pdev->dev, "Failed to enable MSI-X. error %d\n",
|
||||
num_vecs);
|
||||
return -ENOSPC;
|
||||
}
|
||||
|
||||
if (irq_num != msix_vecs) {
|
||||
efa_disable_msix(dev);
|
||||
dev_err(&dev->pdev->dev,
|
||||
"Allocated %d MSI-X (out of %d requested)\n",
|
||||
irq_num, msix_vecs);
|
||||
return -ENOSPC;
|
||||
}
|
||||
dev_dbg(&dev->pdev->dev, "Allocated %d MSI-X vectors\n", num_vecs);
|
||||
|
||||
dev->num_irq_vectors = num_vecs;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -315,7 +315,7 @@ int hfi1_kern_exp_rcv_init(struct hfi1_ctxtdata *rcd, int reinit)
|
|||
* This routine returns the receive context associated
|
||||
* with a a qp's qpn.
|
||||
*
|
||||
* Returns the context.
|
||||
* Return: the context.
|
||||
*/
|
||||
static struct hfi1_ctxtdata *qp_to_rcd(struct rvt_dev_info *rdi,
|
||||
struct rvt_qp *qp)
|
||||
|
|
@ -710,7 +710,7 @@ void hfi1_tid_rdma_flush_wait(struct rvt_qp *qp)
|
|||
* The exp_lock must be held.
|
||||
*
|
||||
* Return:
|
||||
* On success: a value postive value between 0 and RXE_NUM_TID_FLOWS - 1
|
||||
* On success: a value positive value between 0 and RXE_NUM_TID_FLOWS - 1
|
||||
* On failure: -EAGAIN
|
||||
*/
|
||||
static int kern_reserve_flow(struct hfi1_ctxtdata *rcd, int last)
|
||||
|
|
@ -1007,7 +1007,7 @@ static u32 tid_flush_pages(struct tid_rdma_pageset *list,
|
|||
* pages are tested two at a time, i, i + 1 for contiguous
|
||||
* pages and i - 1 and i contiguous pages.
|
||||
*
|
||||
* If any condition is false, any accumlated pages are flushed and
|
||||
* If any condition is false, any accumulated pages are flushed and
|
||||
* v0,v1 are emitted as separate PAGE_SIZE pagesets
|
||||
*
|
||||
* Otherwise, the current 8k is totaled for a future flush.
|
||||
|
|
@ -1434,7 +1434,7 @@ static void kern_program_rcvarray(struct tid_rdma_flow *flow)
|
|||
* (5) computes a tidarray with formatted TID entries which can be sent
|
||||
* to the sender
|
||||
* (6) Reserves and programs HW flows.
|
||||
* (7) It also manages queing the QP when TID/flow resources are not
|
||||
* (7) It also manages queueing the QP when TID/flow resources are not
|
||||
* available.
|
||||
*
|
||||
* @req points to struct tid_rdma_request of which the segments are a part. The
|
||||
|
|
@ -1604,7 +1604,7 @@ void hfi1_kern_exp_rcv_clear_all(struct tid_rdma_request *req)
|
|||
}
|
||||
|
||||
/**
|
||||
* hfi1_kern_exp_rcv_free_flows - free priviously allocated flow information
|
||||
* hfi1_kern_exp_rcv_free_flows - free previously allocated flow information
|
||||
* @req: the tid rdma request to be cleaned
|
||||
*/
|
||||
static void hfi1_kern_exp_rcv_free_flows(struct tid_rdma_request *req)
|
||||
|
|
@ -2055,7 +2055,7 @@ static int tid_rdma_rcv_error(struct hfi1_packet *packet,
|
|||
* req->clear_tail is advanced). However, when an earlier
|
||||
* request is received, this request will not be complete any
|
||||
* more (qp->s_tail_ack_queue is moved back, see below).
|
||||
* Consequently, we need to update the TID flow info everytime
|
||||
* Consequently, we need to update the TID flow info every time
|
||||
* a duplicate request is received.
|
||||
*/
|
||||
bth0 = be32_to_cpu(ohdr->bth[0]);
|
||||
|
|
@ -2219,7 +2219,7 @@ void hfi1_rc_rcv_tid_rdma_read_req(struct hfi1_packet *packet)
|
|||
/*
|
||||
* 1. Verify TID RDMA READ REQ as per IB_OPCODE_RC_RDMA_READ
|
||||
* (see hfi1_rc_rcv())
|
||||
* 2. Put TID RDMA READ REQ into the response queueu (s_ack_queue)
|
||||
* 2. Put TID RDMA READ REQ into the response queue (s_ack_queue)
|
||||
* - Setup struct tid_rdma_req with request info
|
||||
* - Initialize struct tid_rdma_flow info;
|
||||
* - Copy TID entries;
|
||||
|
|
@ -2439,7 +2439,7 @@ find_tid_request(struct rvt_qp *qp, u32 psn, enum ib_wr_opcode opcode)
|
|||
|
||||
void hfi1_rc_rcv_tid_rdma_read_resp(struct hfi1_packet *packet)
|
||||
{
|
||||
/* HANDLER FOR TID RDMA READ RESPONSE packet (Requestor side */
|
||||
/* HANDLER FOR TID RDMA READ RESPONSE packet (Requester side) */
|
||||
|
||||
/*
|
||||
* 1. Find matching SWQE
|
||||
|
|
@ -3649,7 +3649,7 @@ void hfi1_rc_rcv_tid_rdma_write_req(struct hfi1_packet *packet)
|
|||
* 1. Verify TID RDMA WRITE REQ as per IB_OPCODE_RC_RDMA_WRITE_FIRST
|
||||
* (see hfi1_rc_rcv())
|
||||
* - Don't allow 0-length requests.
|
||||
* 2. Put TID RDMA WRITE REQ into the response queueu (s_ack_queue)
|
||||
* 2. Put TID RDMA WRITE REQ into the response queue (s_ack_queue)
|
||||
* - Setup struct tid_rdma_req with request info
|
||||
* - Prepare struct tid_rdma_flow array?
|
||||
* 3. Set the qp->s_ack_state as state diagram in design doc.
|
||||
|
|
@ -4026,7 +4026,7 @@ static void hfi1_tid_timeout(struct timer_list *t)
|
|||
|
||||
void hfi1_rc_rcv_tid_rdma_write_resp(struct hfi1_packet *packet)
|
||||
{
|
||||
/* HANDLER FOR TID RDMA WRITE RESPONSE packet (Requestor side */
|
||||
/* HANDLER FOR TID RDMA WRITE RESPONSE packet (Requester side) */
|
||||
|
||||
/*
|
||||
* 1. Find matching SWQE
|
||||
|
|
@ -5440,8 +5440,9 @@ static bool _hfi1_schedule_tid_send(struct rvt_qp *qp)
|
|||
* the two state machines can step on each other with respect to the
|
||||
* RVT_S_BUSY flag.
|
||||
* Therefore, a modified test is used.
|
||||
* @return true if the second leg is scheduled;
|
||||
* false if the second leg is not scheduled.
|
||||
*
|
||||
* Return: %true if the second leg is scheduled;
|
||||
* %false if the second leg is not scheduled.
|
||||
*/
|
||||
bool hfi1_schedule_tid_send(struct rvt_qp *qp)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -108,6 +108,9 @@ enum {
|
|||
HNS_ROCE_CMD_QUERY_CEQC = 0x92,
|
||||
HNS_ROCE_CMD_DESTROY_CEQC = 0x93,
|
||||
|
||||
/* SCC CTX commands */
|
||||
HNS_ROCE_CMD_QUERY_SCCC = 0xa2,
|
||||
|
||||
/* SCC CTX BT commands */
|
||||
HNS_ROCE_CMD_READ_SCCC_BT0 = 0xa4,
|
||||
HNS_ROCE_CMD_WRITE_SCCC_BT0 = 0xa5,
|
||||
|
|
|
|||
|
|
@ -133,14 +133,12 @@ static int alloc_cqc(struct hns_roce_dev *hr_dev, struct hns_roce_cq *hr_cq)
|
|||
struct hns_roce_cq_table *cq_table = &hr_dev->cq_table;
|
||||
struct ib_device *ibdev = &hr_dev->ib_dev;
|
||||
u64 mtts[MTT_MIN_COUNT] = {};
|
||||
dma_addr_t dma_handle;
|
||||
int ret;
|
||||
|
||||
ret = hns_roce_mtr_find(hr_dev, &hr_cq->mtr, 0, mtts, ARRAY_SIZE(mtts),
|
||||
&dma_handle);
|
||||
if (!ret) {
|
||||
ret = hns_roce_mtr_find(hr_dev, &hr_cq->mtr, 0, mtts, ARRAY_SIZE(mtts));
|
||||
if (ret) {
|
||||
ibdev_err(ibdev, "failed to find CQ mtr, ret = %d.\n", ret);
|
||||
return -EINVAL;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Get CQC memory HEM(Hardware Entry Memory) table */
|
||||
|
|
@ -157,7 +155,8 @@ static int alloc_cqc(struct hns_roce_dev *hr_dev, struct hns_roce_cq *hr_cq)
|
|||
goto err_put;
|
||||
}
|
||||
|
||||
ret = hns_roce_create_cqc(hr_dev, hr_cq, mtts, dma_handle);
|
||||
ret = hns_roce_create_cqc(hr_dev, hr_cq, mtts,
|
||||
hns_roce_get_mtr_ba(&hr_cq->mtr));
|
||||
if (ret)
|
||||
goto err_xa;
|
||||
|
||||
|
|
|
|||
|
|
@ -179,6 +179,7 @@ enum {
|
|||
|
||||
#define HNS_ROCE_CMD_SUCCESS 1
|
||||
|
||||
#define HNS_ROCE_MAX_HOP_NUM 3
|
||||
/* The minimum page size is 4K for hardware */
|
||||
#define HNS_HW_PAGE_SHIFT 12
|
||||
#define HNS_HW_PAGE_SIZE (1 << HNS_HW_PAGE_SHIFT)
|
||||
|
|
@ -269,6 +270,11 @@ struct hns_roce_hem_list {
|
|||
dma_addr_t root_ba; /* pointer to the root ba table */
|
||||
};
|
||||
|
||||
enum mtr_type {
|
||||
MTR_DEFAULT = 0,
|
||||
MTR_PBL,
|
||||
};
|
||||
|
||||
struct hns_roce_buf_attr {
|
||||
struct {
|
||||
size_t size; /* region size */
|
||||
|
|
@ -277,7 +283,10 @@ struct hns_roce_buf_attr {
|
|||
unsigned int region_count; /* valid region count */
|
||||
unsigned int page_shift; /* buffer page shift */
|
||||
unsigned int user_access; /* umem access flag */
|
||||
u64 iova;
|
||||
enum mtr_type type;
|
||||
bool mtt_only; /* only alloc buffer-required MTT memory */
|
||||
bool adaptive; /* adaptive for page_shift and hopnum */
|
||||
};
|
||||
|
||||
struct hns_roce_hem_cfg {
|
||||
|
|
@ -585,6 +594,13 @@ struct hns_roce_work {
|
|||
u32 queue_num;
|
||||
};
|
||||
|
||||
enum hns_roce_cong_type {
|
||||
CONG_TYPE_DCQCN,
|
||||
CONG_TYPE_LDCP,
|
||||
CONG_TYPE_HC3,
|
||||
CONG_TYPE_DIP,
|
||||
};
|
||||
|
||||
struct hns_roce_qp {
|
||||
struct ib_qp ibqp;
|
||||
struct hns_roce_wq rq;
|
||||
|
|
@ -628,6 +644,7 @@ struct hns_roce_qp {
|
|||
struct list_head sq_node; /* all send qps are on a list */
|
||||
struct hns_user_mmap_entry *dwqe_mmap_entry;
|
||||
u32 config;
|
||||
enum hns_roce_cong_type cong_type;
|
||||
};
|
||||
|
||||
struct hns_roce_ib_iboe {
|
||||
|
|
@ -699,13 +716,6 @@ struct hns_roce_eq_table {
|
|||
struct hns_roce_eq *eq;
|
||||
};
|
||||
|
||||
enum cong_type {
|
||||
CONG_TYPE_DCQCN,
|
||||
CONG_TYPE_LDCP,
|
||||
CONG_TYPE_HC3,
|
||||
CONG_TYPE_DIP,
|
||||
};
|
||||
|
||||
struct hns_roce_caps {
|
||||
u64 fw_ver;
|
||||
u8 num_ports;
|
||||
|
|
@ -835,7 +845,8 @@ struct hns_roce_caps {
|
|||
u16 default_aeq_period;
|
||||
u16 default_aeq_arm_st;
|
||||
u16 default_ceq_arm_st;
|
||||
enum cong_type cong_type;
|
||||
u8 cong_cap;
|
||||
enum hns_roce_cong_type default_cong_type;
|
||||
};
|
||||
|
||||
enum hns_roce_device_state {
|
||||
|
|
@ -936,6 +947,7 @@ struct hns_roce_hw {
|
|||
int (*query_qpc)(struct hns_roce_dev *hr_dev, u32 qpn, void *buffer);
|
||||
int (*query_mpt)(struct hns_roce_dev *hr_dev, u32 key, void *buffer);
|
||||
int (*query_srqc)(struct hns_roce_dev *hr_dev, u32 srqn, void *buffer);
|
||||
int (*query_sccc)(struct hns_roce_dev *hr_dev, u32 qpn, void *buffer);
|
||||
int (*query_hw_counter)(struct hns_roce_dev *hr_dev,
|
||||
u64 *stats, u32 port, int *hw_counters);
|
||||
const struct ib_device_ops *hns_roce_dev_ops;
|
||||
|
|
@ -1152,8 +1164,13 @@ void hns_roce_cmd_use_polling(struct hns_roce_dev *hr_dev);
|
|||
|
||||
/* hns roce hw need current block and next block addr from mtt */
|
||||
#define MTT_MIN_COUNT 2
|
||||
static inline dma_addr_t hns_roce_get_mtr_ba(struct hns_roce_mtr *mtr)
|
||||
{
|
||||
return mtr->hem_cfg.root_ba;
|
||||
}
|
||||
|
||||
int hns_roce_mtr_find(struct hns_roce_dev *hr_dev, struct hns_roce_mtr *mtr,
|
||||
u32 offset, u64 *mtt_buf, int mtt_max, u64 *base_addr);
|
||||
u32 offset, u64 *mtt_buf, int mtt_max);
|
||||
int hns_roce_mtr_create(struct hns_roce_dev *hr_dev, struct hns_roce_mtr *mtr,
|
||||
struct hns_roce_buf_attr *buf_attr,
|
||||
unsigned int page_shift, struct ib_udata *udata,
|
||||
|
|
|
|||
|
|
@ -249,61 +249,34 @@ int hns_roce_calc_hem_mhop(struct hns_roce_dev *hr_dev,
|
|||
}
|
||||
|
||||
static struct hns_roce_hem *hns_roce_alloc_hem(struct hns_roce_dev *hr_dev,
|
||||
int npages,
|
||||
unsigned long hem_alloc_size,
|
||||
gfp_t gfp_mask)
|
||||
{
|
||||
struct hns_roce_hem_chunk *chunk = NULL;
|
||||
struct hns_roce_hem *hem;
|
||||
struct scatterlist *mem;
|
||||
int order;
|
||||
void *buf;
|
||||
|
||||
WARN_ON(gfp_mask & __GFP_HIGHMEM);
|
||||
|
||||
order = get_order(hem_alloc_size);
|
||||
if (PAGE_SIZE << order != hem_alloc_size) {
|
||||
dev_err(hr_dev->dev, "invalid hem_alloc_size: %lu!\n",
|
||||
hem_alloc_size);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
hem = kmalloc(sizeof(*hem),
|
||||
gfp_mask & ~(__GFP_HIGHMEM | __GFP_NOWARN));
|
||||
if (!hem)
|
||||
return NULL;
|
||||
|
||||
INIT_LIST_HEAD(&hem->chunk_list);
|
||||
buf = dma_alloc_coherent(hr_dev->dev, hem_alloc_size,
|
||||
&hem->dma, gfp_mask);
|
||||
if (!buf)
|
||||
goto fail;
|
||||
|
||||
order = get_order(hem_alloc_size);
|
||||
|
||||
while (npages > 0) {
|
||||
if (!chunk) {
|
||||
chunk = kmalloc(sizeof(*chunk),
|
||||
gfp_mask & ~(__GFP_HIGHMEM | __GFP_NOWARN));
|
||||
if (!chunk)
|
||||
goto fail;
|
||||
|
||||
sg_init_table(chunk->mem, HNS_ROCE_HEM_CHUNK_LEN);
|
||||
chunk->npages = 0;
|
||||
chunk->nsg = 0;
|
||||
memset(chunk->buf, 0, sizeof(chunk->buf));
|
||||
list_add_tail(&chunk->list, &hem->chunk_list);
|
||||
}
|
||||
|
||||
while (1 << order > npages)
|
||||
--order;
|
||||
|
||||
/*
|
||||
* Alloc memory one time. If failed, don't alloc small block
|
||||
* memory, directly return fail.
|
||||
*/
|
||||
mem = &chunk->mem[chunk->npages];
|
||||
buf = dma_alloc_coherent(hr_dev->dev, PAGE_SIZE << order,
|
||||
&sg_dma_address(mem), gfp_mask);
|
||||
if (!buf)
|
||||
goto fail;
|
||||
|
||||
chunk->buf[chunk->npages] = buf;
|
||||
sg_dma_len(mem) = PAGE_SIZE << order;
|
||||
|
||||
++chunk->npages;
|
||||
++chunk->nsg;
|
||||
npages -= 1 << order;
|
||||
}
|
||||
hem->buf = buf;
|
||||
hem->size = hem_alloc_size;
|
||||
|
||||
return hem;
|
||||
|
||||
|
|
@ -314,20 +287,10 @@ static struct hns_roce_hem *hns_roce_alloc_hem(struct hns_roce_dev *hr_dev,
|
|||
|
||||
void hns_roce_free_hem(struct hns_roce_dev *hr_dev, struct hns_roce_hem *hem)
|
||||
{
|
||||
struct hns_roce_hem_chunk *chunk, *tmp;
|
||||
int i;
|
||||
|
||||
if (!hem)
|
||||
return;
|
||||
|
||||
list_for_each_entry_safe(chunk, tmp, &hem->chunk_list, list) {
|
||||
for (i = 0; i < chunk->npages; ++i)
|
||||
dma_free_coherent(hr_dev->dev,
|
||||
sg_dma_len(&chunk->mem[i]),
|
||||
chunk->buf[i],
|
||||
sg_dma_address(&chunk->mem[i]));
|
||||
kfree(chunk);
|
||||
}
|
||||
dma_free_coherent(hr_dev->dev, hem->size, hem->buf, hem->dma);
|
||||
|
||||
kfree(hem);
|
||||
}
|
||||
|
|
@ -415,7 +378,6 @@ static int alloc_mhop_hem(struct hns_roce_dev *hr_dev,
|
|||
{
|
||||
u32 bt_size = mhop->bt_chunk_size;
|
||||
struct device *dev = hr_dev->dev;
|
||||
struct hns_roce_hem_iter iter;
|
||||
gfp_t flag;
|
||||
u64 bt_ba;
|
||||
u32 size;
|
||||
|
|
@ -456,16 +418,15 @@ static int alloc_mhop_hem(struct hns_roce_dev *hr_dev,
|
|||
*/
|
||||
size = table->type < HEM_TYPE_MTT ? mhop->buf_chunk_size : bt_size;
|
||||
flag = GFP_KERNEL | __GFP_NOWARN;
|
||||
table->hem[index->buf] = hns_roce_alloc_hem(hr_dev, size >> PAGE_SHIFT,
|
||||
size, flag);
|
||||
table->hem[index->buf] = hns_roce_alloc_hem(hr_dev, size, flag);
|
||||
if (!table->hem[index->buf]) {
|
||||
ret = -ENOMEM;
|
||||
goto err_alloc_hem;
|
||||
}
|
||||
|
||||
index->inited |= HEM_INDEX_BUF;
|
||||
hns_roce_hem_first(table->hem[index->buf], &iter);
|
||||
bt_ba = hns_roce_hem_addr(&iter);
|
||||
bt_ba = table->hem[index->buf]->dma;
|
||||
|
||||
if (table->type < HEM_TYPE_MTT) {
|
||||
if (mhop->hop_num == 2)
|
||||
*(table->bt_l1[index->l1] + mhop->l2_idx) = bt_ba;
|
||||
|
|
@ -586,7 +547,6 @@ int hns_roce_table_get(struct hns_roce_dev *hr_dev,
|
|||
}
|
||||
|
||||
table->hem[i] = hns_roce_alloc_hem(hr_dev,
|
||||
table->table_chunk_size >> PAGE_SHIFT,
|
||||
table->table_chunk_size,
|
||||
GFP_KERNEL | __GFP_NOWARN);
|
||||
if (!table->hem[i]) {
|
||||
|
|
@ -725,7 +685,6 @@ void *hns_roce_table_find(struct hns_roce_dev *hr_dev,
|
|||
struct hns_roce_hem_table *table,
|
||||
unsigned long obj, dma_addr_t *dma_handle)
|
||||
{
|
||||
struct hns_roce_hem_chunk *chunk;
|
||||
struct hns_roce_hem_mhop mhop;
|
||||
struct hns_roce_hem *hem;
|
||||
unsigned long mhop_obj = obj;
|
||||
|
|
@ -734,7 +693,6 @@ void *hns_roce_table_find(struct hns_roce_dev *hr_dev,
|
|||
int offset, dma_offset;
|
||||
void *addr = NULL;
|
||||
u32 hem_idx = 0;
|
||||
int length;
|
||||
int i, j;
|
||||
|
||||
mutex_lock(&table->mutex);
|
||||
|
|
@ -767,23 +725,8 @@ void *hns_roce_table_find(struct hns_roce_dev *hr_dev,
|
|||
if (!hem)
|
||||
goto out;
|
||||
|
||||
list_for_each_entry(chunk, &hem->chunk_list, list) {
|
||||
for (i = 0; i < chunk->npages; ++i) {
|
||||
length = sg_dma_len(&chunk->mem[i]);
|
||||
if (dma_handle && dma_offset >= 0) {
|
||||
if (length > (u32)dma_offset)
|
||||
*dma_handle = sg_dma_address(
|
||||
&chunk->mem[i]) + dma_offset;
|
||||
dma_offset -= length;
|
||||
}
|
||||
|
||||
if (length > (u32)offset) {
|
||||
addr = chunk->buf[i] + offset;
|
||||
goto out;
|
||||
}
|
||||
offset -= length;
|
||||
}
|
||||
}
|
||||
*dma_handle = hem->dma + dma_offset;
|
||||
addr = hem->buf + offset;
|
||||
|
||||
out:
|
||||
mutex_unlock(&table->mutex);
|
||||
|
|
|
|||
|
|
@ -56,10 +56,6 @@ enum {
|
|||
HEM_TYPE_TRRL,
|
||||
};
|
||||
|
||||
#define HNS_ROCE_HEM_CHUNK_LEN \
|
||||
((256 - sizeof(struct list_head) - 2 * sizeof(int)) / \
|
||||
(sizeof(struct scatterlist) + sizeof(void *)))
|
||||
|
||||
#define check_whether_bt_num_3(type, hop_num) \
|
||||
(type < HEM_TYPE_MTT && hop_num == 2)
|
||||
|
||||
|
|
@ -72,25 +68,13 @@ enum {
|
|||
(type >= HEM_TYPE_MTT && hop_num == 1) || \
|
||||
(type >= HEM_TYPE_MTT && hop_num == HNS_ROCE_HOP_NUM_0))
|
||||
|
||||
struct hns_roce_hem_chunk {
|
||||
struct list_head list;
|
||||
int npages;
|
||||
int nsg;
|
||||
struct scatterlist mem[HNS_ROCE_HEM_CHUNK_LEN];
|
||||
void *buf[HNS_ROCE_HEM_CHUNK_LEN];
|
||||
};
|
||||
|
||||
struct hns_roce_hem {
|
||||
struct list_head chunk_list;
|
||||
void *buf;
|
||||
dma_addr_t dma;
|
||||
unsigned long size;
|
||||
refcount_t refcount;
|
||||
};
|
||||
|
||||
struct hns_roce_hem_iter {
|
||||
struct hns_roce_hem *hem;
|
||||
struct hns_roce_hem_chunk *chunk;
|
||||
int page_idx;
|
||||
};
|
||||
|
||||
struct hns_roce_hem_mhop {
|
||||
u32 hop_num;
|
||||
u32 buf_chunk_size;
|
||||
|
|
@ -133,38 +117,4 @@ void *hns_roce_hem_list_find_mtt(struct hns_roce_dev *hr_dev,
|
|||
struct hns_roce_hem_list *hem_list,
|
||||
int offset, int *mtt_cnt);
|
||||
|
||||
static inline void hns_roce_hem_first(struct hns_roce_hem *hem,
|
||||
struct hns_roce_hem_iter *iter)
|
||||
{
|
||||
iter->hem = hem;
|
||||
iter->chunk = list_empty(&hem->chunk_list) ? NULL :
|
||||
list_entry(hem->chunk_list.next,
|
||||
struct hns_roce_hem_chunk, list);
|
||||
iter->page_idx = 0;
|
||||
}
|
||||
|
||||
static inline int hns_roce_hem_last(struct hns_roce_hem_iter *iter)
|
||||
{
|
||||
return !iter->chunk;
|
||||
}
|
||||
|
||||
static inline void hns_roce_hem_next(struct hns_roce_hem_iter *iter)
|
||||
{
|
||||
if (++iter->page_idx >= iter->chunk->nsg) {
|
||||
if (iter->chunk->list.next == &iter->hem->chunk_list) {
|
||||
iter->chunk = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
iter->chunk = list_entry(iter->chunk->list.next,
|
||||
struct hns_roce_hem_chunk, list);
|
||||
iter->page_idx = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static inline dma_addr_t hns_roce_hem_addr(struct hns_roce_hem_iter *iter)
|
||||
{
|
||||
return sg_dma_address(&iter->chunk->mem[iter->page_idx]);
|
||||
}
|
||||
|
||||
#endif /* _HNS_ROCE_HEM_H */
|
||||
|
|
|
|||
|
|
@ -2209,11 +2209,12 @@ static int hns_roce_query_caps(struct hns_roce_dev *hr_dev)
|
|||
caps->max_wqes = 1 << le16_to_cpu(resp_c->sq_depth);
|
||||
|
||||
caps->num_srqs = 1 << hr_reg_read(resp_d, PF_CAPS_D_NUM_SRQS);
|
||||
caps->cong_type = hr_reg_read(resp_d, PF_CAPS_D_CONG_TYPE);
|
||||
caps->cong_cap = hr_reg_read(resp_d, PF_CAPS_D_CONG_CAP);
|
||||
caps->max_srq_wrs = 1 << le16_to_cpu(resp_d->srq_depth);
|
||||
caps->ceqe_depth = 1 << hr_reg_read(resp_d, PF_CAPS_D_CEQ_DEPTH);
|
||||
caps->num_comp_vectors = hr_reg_read(resp_d, PF_CAPS_D_NUM_CEQS);
|
||||
caps->aeqe_depth = 1 << hr_reg_read(resp_d, PF_CAPS_D_AEQ_DEPTH);
|
||||
caps->default_cong_type = hr_reg_read(resp_d, PF_CAPS_D_DEFAULT_ALG);
|
||||
caps->reserved_pds = hr_reg_read(resp_d, PF_CAPS_D_RSV_PDS);
|
||||
caps->num_uars = 1 << hr_reg_read(resp_d, PF_CAPS_D_NUM_UARS);
|
||||
caps->reserved_qps = hr_reg_read(resp_d, PF_CAPS_D_RSV_QPS);
|
||||
|
|
@ -3195,21 +3196,22 @@ static int set_mtpt_pbl(struct hns_roce_dev *hr_dev,
|
|||
u64 pages[HNS_ROCE_V2_MAX_INNER_MTPT_NUM] = { 0 };
|
||||
struct ib_device *ibdev = &hr_dev->ib_dev;
|
||||
dma_addr_t pbl_ba;
|
||||
int i, count;
|
||||
int ret;
|
||||
int i;
|
||||
|
||||
count = hns_roce_mtr_find(hr_dev, &mr->pbl_mtr, 0, pages,
|
||||
min_t(int, ARRAY_SIZE(pages), mr->npages),
|
||||
&pbl_ba);
|
||||
if (count < 1) {
|
||||
ibdev_err(ibdev, "failed to find PBL mtr, count = %d.\n",
|
||||
count);
|
||||
return -ENOBUFS;
|
||||
ret = hns_roce_mtr_find(hr_dev, &mr->pbl_mtr, 0, pages,
|
||||
min_t(int, ARRAY_SIZE(pages), mr->npages));
|
||||
if (ret) {
|
||||
ibdev_err(ibdev, "failed to find PBL mtr, ret = %d.\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Aligned to the hardware address access unit */
|
||||
for (i = 0; i < count; i++)
|
||||
for (i = 0; i < ARRAY_SIZE(pages); i++)
|
||||
pages[i] >>= 6;
|
||||
|
||||
pbl_ba = hns_roce_get_mtr_ba(&mr->pbl_mtr);
|
||||
|
||||
mpt_entry->pbl_size = cpu_to_le32(mr->npages);
|
||||
mpt_entry->pbl_ba_l = cpu_to_le32(pbl_ba >> 3);
|
||||
hr_reg_write(mpt_entry, MPT_PBL_BA_H, upper_32_bits(pbl_ba >> 3));
|
||||
|
|
@ -3308,18 +3310,12 @@ static int hns_roce_v2_rereg_write_mtpt(struct hns_roce_dev *hr_dev,
|
|||
static int hns_roce_v2_frmr_write_mtpt(struct hns_roce_dev *hr_dev,
|
||||
void *mb_buf, struct hns_roce_mr *mr)
|
||||
{
|
||||
struct ib_device *ibdev = &hr_dev->ib_dev;
|
||||
dma_addr_t pbl_ba = hns_roce_get_mtr_ba(&mr->pbl_mtr);
|
||||
struct hns_roce_v2_mpt_entry *mpt_entry;
|
||||
dma_addr_t pbl_ba = 0;
|
||||
|
||||
mpt_entry = mb_buf;
|
||||
memset(mpt_entry, 0, sizeof(*mpt_entry));
|
||||
|
||||
if (hns_roce_mtr_find(hr_dev, &mr->pbl_mtr, 0, NULL, 0, &pbl_ba) < 0) {
|
||||
ibdev_err(ibdev, "failed to find frmr mtr.\n");
|
||||
return -ENOBUFS;
|
||||
}
|
||||
|
||||
hr_reg_write(mpt_entry, MPT_ST, V2_MPT_ST_FREE);
|
||||
hr_reg_write(mpt_entry, MPT_PD, mr->pd);
|
||||
|
||||
|
|
@ -4063,7 +4059,6 @@ static int hns_roce_v2_set_hem(struct hns_roce_dev *hr_dev,
|
|||
struct hns_roce_hem_table *table, int obj,
|
||||
u32 step_idx)
|
||||
{
|
||||
struct hns_roce_hem_iter iter;
|
||||
struct hns_roce_hem_mhop mhop;
|
||||
struct hns_roce_hem *hem;
|
||||
unsigned long mhop_obj = obj;
|
||||
|
|
@ -4100,12 +4095,8 @@ static int hns_roce_v2_set_hem(struct hns_roce_dev *hr_dev,
|
|||
|
||||
if (check_whether_last_step(hop_num, step_idx)) {
|
||||
hem = table->hem[hem_idx];
|
||||
for (hns_roce_hem_first(hem, &iter);
|
||||
!hns_roce_hem_last(&iter); hns_roce_hem_next(&iter)) {
|
||||
bt_ba = hns_roce_hem_addr(&iter);
|
||||
ret = set_hem_to_hw(hr_dev, obj, bt_ba, table->type,
|
||||
step_idx);
|
||||
}
|
||||
|
||||
ret = set_hem_to_hw(hr_dev, obj, hem->dma, table->type, step_idx);
|
||||
} else {
|
||||
if (step_idx == 0)
|
||||
bt_ba = table->bt_l0_dma_addr[i];
|
||||
|
|
@ -4346,17 +4337,20 @@ static int config_qp_rq_buf(struct hns_roce_dev *hr_dev,
|
|||
{
|
||||
u64 mtts[MTT_MIN_COUNT] = { 0 };
|
||||
u64 wqe_sge_ba;
|
||||
int count;
|
||||
int ret;
|
||||
|
||||
/* Search qp buf's mtts */
|
||||
count = hns_roce_mtr_find(hr_dev, &hr_qp->mtr, hr_qp->rq.offset, mtts,
|
||||
MTT_MIN_COUNT, &wqe_sge_ba);
|
||||
if (hr_qp->rq.wqe_cnt && count < 1) {
|
||||
ret = hns_roce_mtr_find(hr_dev, &hr_qp->mtr, hr_qp->rq.offset, mtts,
|
||||
MTT_MIN_COUNT);
|
||||
if (hr_qp->rq.wqe_cnt && ret) {
|
||||
ibdev_err(&hr_dev->ib_dev,
|
||||
"failed to find RQ WQE, QPN = 0x%lx.\n", hr_qp->qpn);
|
||||
return -EINVAL;
|
||||
"failed to find QP(0x%lx) RQ WQE buf, ret = %d.\n",
|
||||
hr_qp->qpn, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
wqe_sge_ba = hns_roce_get_mtr_ba(&hr_qp->mtr);
|
||||
|
||||
context->wqe_sge_ba = cpu_to_le32(wqe_sge_ba >> 3);
|
||||
qpc_mask->wqe_sge_ba = 0;
|
||||
|
||||
|
|
@ -4418,23 +4412,23 @@ static int config_qp_sq_buf(struct hns_roce_dev *hr_dev,
|
|||
struct ib_device *ibdev = &hr_dev->ib_dev;
|
||||
u64 sge_cur_blk = 0;
|
||||
u64 sq_cur_blk = 0;
|
||||
int count;
|
||||
int ret;
|
||||
|
||||
/* search qp buf's mtts */
|
||||
count = hns_roce_mtr_find(hr_dev, &hr_qp->mtr, 0, &sq_cur_blk, 1, NULL);
|
||||
if (count < 1) {
|
||||
ibdev_err(ibdev, "failed to find QP(0x%lx) SQ buf.\n",
|
||||
hr_qp->qpn);
|
||||
return -EINVAL;
|
||||
ret = hns_roce_mtr_find(hr_dev, &hr_qp->mtr, hr_qp->sq.offset,
|
||||
&sq_cur_blk, 1);
|
||||
if (ret) {
|
||||
ibdev_err(ibdev, "failed to find QP(0x%lx) SQ WQE buf, ret = %d.\n",
|
||||
hr_qp->qpn, ret);
|
||||
return ret;
|
||||
}
|
||||
if (hr_qp->sge.sge_cnt > 0) {
|
||||
count = hns_roce_mtr_find(hr_dev, &hr_qp->mtr,
|
||||
hr_qp->sge.offset,
|
||||
&sge_cur_blk, 1, NULL);
|
||||
if (count < 1) {
|
||||
ibdev_err(ibdev, "failed to find QP(0x%lx) SGE buf.\n",
|
||||
hr_qp->qpn);
|
||||
return -EINVAL;
|
||||
ret = hns_roce_mtr_find(hr_dev, &hr_qp->mtr,
|
||||
hr_qp->sge.offset, &sge_cur_blk, 1);
|
||||
if (ret) {
|
||||
ibdev_err(ibdev, "failed to find QP(0x%lx) SGE buf, ret = %d.\n",
|
||||
hr_qp->qpn, ret);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -4744,13 +4738,10 @@ enum {
|
|||
static int check_cong_type(struct ib_qp *ibqp,
|
||||
struct hns_roce_congestion_algorithm *cong_alg)
|
||||
{
|
||||
struct hns_roce_dev *hr_dev = to_hr_dev(ibqp->device);
|
||||
|
||||
if (ibqp->qp_type == IB_QPT_UD)
|
||||
hr_dev->caps.cong_type = CONG_TYPE_DCQCN;
|
||||
struct hns_roce_qp *hr_qp = to_hr_qp(ibqp);
|
||||
|
||||
/* different congestion types match different configurations */
|
||||
switch (hr_dev->caps.cong_type) {
|
||||
switch (hr_qp->cong_type) {
|
||||
case CONG_TYPE_DCQCN:
|
||||
cong_alg->alg_sel = CONG_DCQCN;
|
||||
cong_alg->alg_sub_sel = UNSUPPORT_CONG_LEVEL;
|
||||
|
|
@ -4776,10 +4767,7 @@ static int check_cong_type(struct ib_qp *ibqp,
|
|||
cong_alg->wnd_mode_sel = WND_LIMIT;
|
||||
break;
|
||||
default:
|
||||
ibdev_warn(&hr_dev->ib_dev,
|
||||
"invalid type(%u) for congestion selection.\n",
|
||||
hr_dev->caps.cong_type);
|
||||
hr_dev->caps.cong_type = CONG_TYPE_DCQCN;
|
||||
hr_qp->cong_type = CONG_TYPE_DCQCN;
|
||||
cong_alg->alg_sel = CONG_DCQCN;
|
||||
cong_alg->alg_sub_sel = UNSUPPORT_CONG_LEVEL;
|
||||
cong_alg->dip_vld = DIP_INVALID;
|
||||
|
|
@ -4798,6 +4786,7 @@ static int fill_cong_field(struct ib_qp *ibqp, const struct ib_qp_attr *attr,
|
|||
struct hns_roce_congestion_algorithm cong_field;
|
||||
struct ib_device *ibdev = ibqp->device;
|
||||
struct hns_roce_dev *hr_dev = to_hr_dev(ibdev);
|
||||
struct hns_roce_qp *hr_qp = to_hr_qp(ibqp);
|
||||
u32 dip_idx = 0;
|
||||
int ret;
|
||||
|
||||
|
|
@ -4810,7 +4799,7 @@ static int fill_cong_field(struct ib_qp *ibqp, const struct ib_qp_attr *attr,
|
|||
return ret;
|
||||
|
||||
hr_reg_write(context, QPC_CONG_ALGO_TMPL_ID, hr_dev->cong_algo_tmpl_id +
|
||||
hr_dev->caps.cong_type * HNS_ROCE_CONG_SIZE);
|
||||
hr_qp->cong_type * HNS_ROCE_CONG_SIZE);
|
||||
hr_reg_clear(qpc_mask, QPC_CONG_ALGO_TMPL_ID);
|
||||
hr_reg_write(&context->ext, QPCEX_CONG_ALG_SEL, cong_field.alg_sel);
|
||||
hr_reg_clear(&qpc_mask->ext, QPCEX_CONG_ALG_SEL);
|
||||
|
|
@ -5328,6 +5317,30 @@ static int hns_roce_v2_query_srqc(struct hns_roce_dev *hr_dev, u32 srqn,
|
|||
return ret;
|
||||
}
|
||||
|
||||
static int hns_roce_v2_query_sccc(struct hns_roce_dev *hr_dev, u32 qpn,
|
||||
void *buffer)
|
||||
{
|
||||
struct hns_roce_v2_scc_context *context;
|
||||
struct hns_roce_cmd_mailbox *mailbox;
|
||||
int ret;
|
||||
|
||||
mailbox = hns_roce_alloc_cmd_mailbox(hr_dev);
|
||||
if (IS_ERR(mailbox))
|
||||
return PTR_ERR(mailbox);
|
||||
|
||||
ret = hns_roce_cmd_mbox(hr_dev, 0, mailbox->dma, HNS_ROCE_CMD_QUERY_SCCC,
|
||||
qpn);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
context = mailbox->buf;
|
||||
memcpy(buffer, context, sizeof(*context));
|
||||
|
||||
out:
|
||||
hns_roce_free_cmd_mailbox(hr_dev, mailbox);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static u8 get_qp_timeout_attr(struct hns_roce_dev *hr_dev,
|
||||
struct hns_roce_v2_qp_context *context)
|
||||
{
|
||||
|
|
@ -5581,18 +5594,20 @@ static int hns_roce_v2_write_srqc_index_queue(struct hns_roce_srq *srq,
|
|||
struct ib_device *ibdev = srq->ibsrq.device;
|
||||
struct hns_roce_dev *hr_dev = to_hr_dev(ibdev);
|
||||
u64 mtts_idx[MTT_MIN_COUNT] = {};
|
||||
dma_addr_t dma_handle_idx = 0;
|
||||
dma_addr_t dma_handle_idx;
|
||||
int ret;
|
||||
|
||||
/* Get physical address of idx que buf */
|
||||
ret = hns_roce_mtr_find(hr_dev, &idx_que->mtr, 0, mtts_idx,
|
||||
ARRAY_SIZE(mtts_idx), &dma_handle_idx);
|
||||
if (ret < 1) {
|
||||
ARRAY_SIZE(mtts_idx));
|
||||
if (ret) {
|
||||
ibdev_err(ibdev, "failed to find mtr for SRQ idx, ret = %d.\n",
|
||||
ret);
|
||||
return -ENOBUFS;
|
||||
return ret;
|
||||
}
|
||||
|
||||
dma_handle_idx = hns_roce_get_mtr_ba(&idx_que->mtr);
|
||||
|
||||
hr_reg_write(ctx, SRQC_IDX_HOP_NUM,
|
||||
to_hr_hem_hopnum(hr_dev->caps.idx_hop_num, srq->wqe_cnt));
|
||||
|
||||
|
|
@ -5624,20 +5639,22 @@ static int hns_roce_v2_write_srqc(struct hns_roce_srq *srq, void *mb_buf)
|
|||
struct hns_roce_dev *hr_dev = to_hr_dev(ibdev);
|
||||
struct hns_roce_srq_context *ctx = mb_buf;
|
||||
u64 mtts_wqe[MTT_MIN_COUNT] = {};
|
||||
dma_addr_t dma_handle_wqe = 0;
|
||||
dma_addr_t dma_handle_wqe;
|
||||
int ret;
|
||||
|
||||
memset(ctx, 0, sizeof(*ctx));
|
||||
|
||||
/* Get the physical address of srq buf */
|
||||
ret = hns_roce_mtr_find(hr_dev, &srq->buf_mtr, 0, mtts_wqe,
|
||||
ARRAY_SIZE(mtts_wqe), &dma_handle_wqe);
|
||||
if (ret < 1) {
|
||||
ARRAY_SIZE(mtts_wqe));
|
||||
if (ret) {
|
||||
ibdev_err(ibdev, "failed to find mtr for SRQ WQE, ret = %d.\n",
|
||||
ret);
|
||||
return -ENOBUFS;
|
||||
return ret;
|
||||
}
|
||||
|
||||
dma_handle_wqe = hns_roce_get_mtr_ba(&srq->buf_mtr);
|
||||
|
||||
hr_reg_write(ctx, SRQC_SRQ_ST, 1);
|
||||
hr_reg_write_bool(ctx, SRQC_SRQ_TYPE,
|
||||
srq->ibsrq.srq_type == IB_SRQT_XRC);
|
||||
|
|
@ -6353,7 +6370,7 @@ static int config_eqc(struct hns_roce_dev *hr_dev, struct hns_roce_eq *eq,
|
|||
u64 eqe_ba[MTT_MIN_COUNT] = { 0 };
|
||||
struct hns_roce_eq_context *eqc;
|
||||
u64 bt_ba = 0;
|
||||
int count;
|
||||
int ret;
|
||||
|
||||
eqc = mb_buf;
|
||||
memset(eqc, 0, sizeof(struct hns_roce_eq_context));
|
||||
|
|
@ -6361,13 +6378,15 @@ static int config_eqc(struct hns_roce_dev *hr_dev, struct hns_roce_eq *eq,
|
|||
init_eq_config(hr_dev, eq);
|
||||
|
||||
/* if not multi-hop, eqe buffer only use one trunk */
|
||||
count = hns_roce_mtr_find(hr_dev, &eq->mtr, 0, eqe_ba, MTT_MIN_COUNT,
|
||||
&bt_ba);
|
||||
if (count < 1) {
|
||||
dev_err(hr_dev->dev, "failed to find EQE mtr\n");
|
||||
return -ENOBUFS;
|
||||
ret = hns_roce_mtr_find(hr_dev, &eq->mtr, 0, eqe_ba,
|
||||
ARRAY_SIZE(eqe_ba));
|
||||
if (ret) {
|
||||
dev_err(hr_dev->dev, "failed to find EQE mtr, ret = %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
bt_ba = hns_roce_get_mtr_ba(&eq->mtr);
|
||||
|
||||
hr_reg_write(eqc, EQC_EQ_ST, HNS_ROCE_V2_EQ_STATE_VALID);
|
||||
hr_reg_write(eqc, EQC_EQE_HOP_NUM, eq->hop_num);
|
||||
hr_reg_write(eqc, EQC_OVER_IGNORE, eq->over_ignore);
|
||||
|
|
@ -6714,6 +6733,7 @@ static const struct hns_roce_hw hns_roce_hw_v2 = {
|
|||
.query_qpc = hns_roce_v2_query_qpc,
|
||||
.query_mpt = hns_roce_v2_query_mpt,
|
||||
.query_srqc = hns_roce_v2_query_srqc,
|
||||
.query_sccc = hns_roce_v2_query_sccc,
|
||||
.query_hw_counter = hns_roce_hw_v2_query_counter,
|
||||
.hns_roce_dev_ops = &hns_roce_v2_dev_ops,
|
||||
.hns_roce_dev_srq_ops = &hns_roce_v2_dev_srq_ops,
|
||||
|
|
|
|||
|
|
@ -646,6 +646,12 @@ struct hns_roce_v2_qp_context {
|
|||
#define QPCEX_SQ_RQ_NOT_FORBID_EN QPCEX_FIELD_LOC(23, 23)
|
||||
#define QPCEX_STASH QPCEX_FIELD_LOC(82, 82)
|
||||
|
||||
#define SCC_CONTEXT_SIZE 16
|
||||
|
||||
struct hns_roce_v2_scc_context {
|
||||
__le32 data[SCC_CONTEXT_SIZE];
|
||||
};
|
||||
|
||||
#define V2_QP_RWE_S 1 /* rdma write enable */
|
||||
#define V2_QP_RRE_S 2 /* rdma read enable */
|
||||
#define V2_QP_ATE_S 3 /* rdma atomic enable */
|
||||
|
|
@ -1214,12 +1220,13 @@ struct hns_roce_query_pf_caps_d {
|
|||
#define PF_CAPS_D_RQWQE_HOP_NUM PF_CAPS_D_FIELD_LOC(21, 20)
|
||||
#define PF_CAPS_D_EX_SGE_HOP_NUM PF_CAPS_D_FIELD_LOC(23, 22)
|
||||
#define PF_CAPS_D_SQWQE_HOP_NUM PF_CAPS_D_FIELD_LOC(25, 24)
|
||||
#define PF_CAPS_D_CONG_TYPE PF_CAPS_D_FIELD_LOC(29, 26)
|
||||
#define PF_CAPS_D_CONG_CAP PF_CAPS_D_FIELD_LOC(29, 26)
|
||||
#define PF_CAPS_D_CEQ_DEPTH PF_CAPS_D_FIELD_LOC(85, 64)
|
||||
#define PF_CAPS_D_NUM_CEQS PF_CAPS_D_FIELD_LOC(95, 86)
|
||||
#define PF_CAPS_D_AEQ_DEPTH PF_CAPS_D_FIELD_LOC(117, 96)
|
||||
#define PF_CAPS_D_AEQ_ARM_ST PF_CAPS_D_FIELD_LOC(119, 118)
|
||||
#define PF_CAPS_D_CEQ_ARM_ST PF_CAPS_D_FIELD_LOC(121, 120)
|
||||
#define PF_CAPS_D_DEFAULT_ALG PF_CAPS_D_FIELD_LOC(127, 122)
|
||||
#define PF_CAPS_D_RSV_PDS PF_CAPS_D_FIELD_LOC(147, 128)
|
||||
#define PF_CAPS_D_NUM_UARS PF_CAPS_D_FIELD_LOC(155, 148)
|
||||
#define PF_CAPS_D_RSV_QPS PF_CAPS_D_FIELD_LOC(179, 160)
|
||||
|
|
|
|||
|
|
@ -394,6 +394,9 @@ static int hns_roce_alloc_ucontext(struct ib_ucontext *uctx,
|
|||
resp.config |= HNS_ROCE_RSP_CQE_INLINE_FLAGS;
|
||||
}
|
||||
|
||||
if (hr_dev->pci_dev->revision >= PCI_REVISION_ID_HIP09)
|
||||
resp.congest_type = hr_dev->caps.cong_cap;
|
||||
|
||||
ret = hns_roce_uar_alloc(hr_dev, &context->uar);
|
||||
if (ret)
|
||||
goto error_out;
|
||||
|
|
|
|||
|
|
@ -32,6 +32,7 @@
|
|||
*/
|
||||
|
||||
#include <linux/vmalloc.h>
|
||||
#include <linux/count_zeros.h>
|
||||
#include <rdma/ib_umem.h>
|
||||
#include <linux/math.h>
|
||||
#include "hns_roce_device.h"
|
||||
|
|
@ -103,14 +104,21 @@ static int alloc_mr_pbl(struct hns_roce_dev *hr_dev, struct hns_roce_mr *mr,
|
|||
buf_attr.user_access = mr->access;
|
||||
/* fast MR's buffer is alloced before mapping, not at creation */
|
||||
buf_attr.mtt_only = is_fast;
|
||||
buf_attr.iova = mr->iova;
|
||||
/* pagesize and hopnum is fixed for fast MR */
|
||||
buf_attr.adaptive = !is_fast;
|
||||
buf_attr.type = MTR_PBL;
|
||||
|
||||
err = hns_roce_mtr_create(hr_dev, &mr->pbl_mtr, &buf_attr,
|
||||
hr_dev->caps.pbl_ba_pg_sz + PAGE_SHIFT,
|
||||
udata, start);
|
||||
if (err)
|
||||
if (err) {
|
||||
ibdev_err(ibdev, "failed to alloc pbl mtr, ret = %d.\n", err);
|
||||
else
|
||||
mr->npages = mr->pbl_mtr.hem_cfg.buf_pg_count;
|
||||
return err;
|
||||
}
|
||||
|
||||
mr->npages = mr->pbl_mtr.hem_cfg.buf_pg_count;
|
||||
mr->pbl_hop_num = buf_attr.region[0].hopnum;
|
||||
|
||||
return err;
|
||||
}
|
||||
|
|
@ -695,7 +703,7 @@ static int mtr_alloc_bufs(struct hns_roce_dev *hr_dev, struct hns_roce_mtr *mtr,
|
|||
mtr->umem = NULL;
|
||||
mtr->kmem = hns_roce_buf_alloc(hr_dev, total_size,
|
||||
buf_attr->page_shift,
|
||||
mtr->hem_cfg.is_direct ?
|
||||
!mtr_has_mtt(buf_attr) ?
|
||||
HNS_ROCE_BUF_DIRECT : 0);
|
||||
if (IS_ERR(mtr->kmem)) {
|
||||
ibdev_err(ibdev, "failed to alloc kmem, ret = %ld.\n",
|
||||
|
|
@ -707,14 +715,41 @@ static int mtr_alloc_bufs(struct hns_roce_dev *hr_dev, struct hns_roce_mtr *mtr,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int mtr_map_bufs(struct hns_roce_dev *hr_dev, struct hns_roce_mtr *mtr,
|
||||
int page_count, unsigned int page_shift)
|
||||
static int cal_mtr_pg_cnt(struct hns_roce_mtr *mtr)
|
||||
{
|
||||
struct hns_roce_buf_region *region;
|
||||
int page_cnt = 0;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < mtr->hem_cfg.region_count; i++) {
|
||||
region = &mtr->hem_cfg.region[i];
|
||||
page_cnt += region->count;
|
||||
}
|
||||
|
||||
return page_cnt;
|
||||
}
|
||||
|
||||
static bool need_split_huge_page(struct hns_roce_mtr *mtr)
|
||||
{
|
||||
/* When HEM buffer uses 0-level addressing, the page size is
|
||||
* equal to the whole buffer size. If the current MTR has multiple
|
||||
* regions, we split the buffer into small pages(4k, required by hns
|
||||
* ROCEE). These pages will be used in multiple regions.
|
||||
*/
|
||||
return mtr->hem_cfg.is_direct && mtr->hem_cfg.region_count > 1;
|
||||
}
|
||||
|
||||
static int mtr_map_bufs(struct hns_roce_dev *hr_dev, struct hns_roce_mtr *mtr)
|
||||
{
|
||||
struct ib_device *ibdev = &hr_dev->ib_dev;
|
||||
int page_count = cal_mtr_pg_cnt(mtr);
|
||||
unsigned int page_shift;
|
||||
dma_addr_t *pages;
|
||||
int npage;
|
||||
int ret;
|
||||
|
||||
page_shift = need_split_huge_page(mtr) ? HNS_HW_PAGE_SHIFT :
|
||||
mtr->hem_cfg.buf_pg_shift;
|
||||
/* alloc a tmp array to store buffer's dma address */
|
||||
pages = kvcalloc(page_count, sizeof(dma_addr_t), GFP_KERNEL);
|
||||
if (!pages)
|
||||
|
|
@ -734,7 +769,7 @@ static int mtr_map_bufs(struct hns_roce_dev *hr_dev, struct hns_roce_mtr *mtr,
|
|||
goto err_alloc_list;
|
||||
}
|
||||
|
||||
if (mtr->hem_cfg.is_direct && npage > 1) {
|
||||
if (need_split_huge_page(mtr) && npage > 1) {
|
||||
ret = mtr_check_direct_pages(pages, npage, page_shift);
|
||||
if (ret) {
|
||||
ibdev_err(ibdev, "failed to check %s page: %d / %d.\n",
|
||||
|
|
@ -809,47 +844,53 @@ int hns_roce_mtr_map(struct hns_roce_dev *hr_dev, struct hns_roce_mtr *mtr,
|
|||
return ret;
|
||||
}
|
||||
|
||||
int hns_roce_mtr_find(struct hns_roce_dev *hr_dev, struct hns_roce_mtr *mtr,
|
||||
u32 offset, u64 *mtt_buf, int mtt_max, u64 *base_addr)
|
||||
static int hns_roce_get_direct_addr_mtt(struct hns_roce_hem_cfg *cfg,
|
||||
u32 start_index, u64 *mtt_buf,
|
||||
int mtt_cnt)
|
||||
{
|
||||
struct hns_roce_hem_cfg *cfg = &mtr->hem_cfg;
|
||||
int mtt_count, left;
|
||||
u32 start_index;
|
||||
int mtt_count;
|
||||
int total = 0;
|
||||
__le64 *mtts;
|
||||
u32 npage;
|
||||
u64 addr;
|
||||
|
||||
if (!mtt_buf || mtt_max < 1)
|
||||
goto done;
|
||||
if (mtt_cnt > cfg->region_count)
|
||||
return -EINVAL;
|
||||
|
||||
/* no mtt memory in direct mode, so just return the buffer address */
|
||||
if (cfg->is_direct) {
|
||||
start_index = offset >> HNS_HW_PAGE_SHIFT;
|
||||
for (mtt_count = 0; mtt_count < cfg->region_count &&
|
||||
total < mtt_max; mtt_count++) {
|
||||
npage = cfg->region[mtt_count].offset;
|
||||
if (npage < start_index)
|
||||
continue;
|
||||
for (mtt_count = 0; mtt_count < cfg->region_count && total < mtt_cnt;
|
||||
mtt_count++) {
|
||||
npage = cfg->region[mtt_count].offset;
|
||||
if (npage < start_index)
|
||||
continue;
|
||||
|
||||
addr = cfg->root_ba + (npage << HNS_HW_PAGE_SHIFT);
|
||||
mtt_buf[total] = addr;
|
||||
addr = cfg->root_ba + (npage << HNS_HW_PAGE_SHIFT);
|
||||
mtt_buf[total] = addr;
|
||||
|
||||
total++;
|
||||
}
|
||||
|
||||
goto done;
|
||||
total++;
|
||||
}
|
||||
|
||||
start_index = offset >> cfg->buf_pg_shift;
|
||||
left = mtt_max;
|
||||
if (!total)
|
||||
return -ENOENT;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int hns_roce_get_mhop_mtt(struct hns_roce_dev *hr_dev,
|
||||
struct hns_roce_mtr *mtr, u32 start_index,
|
||||
u64 *mtt_buf, int mtt_cnt)
|
||||
{
|
||||
int left = mtt_cnt;
|
||||
int total = 0;
|
||||
int mtt_count;
|
||||
__le64 *mtts;
|
||||
u32 npage;
|
||||
|
||||
while (left > 0) {
|
||||
mtt_count = 0;
|
||||
mtts = hns_roce_hem_list_find_mtt(hr_dev, &mtr->hem_list,
|
||||
start_index + total,
|
||||
&mtt_count);
|
||||
if (!mtts || !mtt_count)
|
||||
goto done;
|
||||
break;
|
||||
|
||||
npage = min(mtt_count, left);
|
||||
left -= npage;
|
||||
|
|
@ -857,69 +898,165 @@ int hns_roce_mtr_find(struct hns_roce_dev *hr_dev, struct hns_roce_mtr *mtr,
|
|||
mtt_buf[total++] = le64_to_cpu(mtts[mtt_count]);
|
||||
}
|
||||
|
||||
done:
|
||||
if (base_addr)
|
||||
*base_addr = cfg->root_ba;
|
||||
if (!total)
|
||||
return -ENOENT;
|
||||
|
||||
return total;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int hns_roce_mtr_find(struct hns_roce_dev *hr_dev, struct hns_roce_mtr *mtr,
|
||||
u32 offset, u64 *mtt_buf, int mtt_max)
|
||||
{
|
||||
struct hns_roce_hem_cfg *cfg = &mtr->hem_cfg;
|
||||
u32 start_index;
|
||||
int ret;
|
||||
|
||||
if (!mtt_buf || mtt_max < 1)
|
||||
return -EINVAL;
|
||||
|
||||
/* no mtt memory in direct mode, so just return the buffer address */
|
||||
if (cfg->is_direct) {
|
||||
start_index = offset >> HNS_HW_PAGE_SHIFT;
|
||||
ret = hns_roce_get_direct_addr_mtt(cfg, start_index,
|
||||
mtt_buf, mtt_max);
|
||||
} else {
|
||||
start_index = offset >> cfg->buf_pg_shift;
|
||||
ret = hns_roce_get_mhop_mtt(hr_dev, mtr, start_index,
|
||||
mtt_buf, mtt_max);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int get_best_page_shift(struct hns_roce_dev *hr_dev,
|
||||
struct hns_roce_mtr *mtr,
|
||||
struct hns_roce_buf_attr *buf_attr)
|
||||
{
|
||||
unsigned int page_sz;
|
||||
|
||||
if (!buf_attr->adaptive || buf_attr->type != MTR_PBL || !mtr->umem)
|
||||
return 0;
|
||||
|
||||
page_sz = ib_umem_find_best_pgsz(mtr->umem,
|
||||
hr_dev->caps.page_size_cap,
|
||||
buf_attr->iova);
|
||||
if (!page_sz)
|
||||
return -EINVAL;
|
||||
|
||||
buf_attr->page_shift = order_base_2(page_sz);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int get_best_hop_num(struct hns_roce_dev *hr_dev,
|
||||
struct hns_roce_mtr *mtr,
|
||||
struct hns_roce_buf_attr *buf_attr,
|
||||
unsigned int ba_pg_shift)
|
||||
{
|
||||
#define INVALID_HOPNUM -1
|
||||
#define MIN_BA_CNT 1
|
||||
size_t buf_pg_sz = 1 << buf_attr->page_shift;
|
||||
struct ib_device *ibdev = &hr_dev->ib_dev;
|
||||
size_t ba_pg_sz = 1 << ba_pg_shift;
|
||||
int hop_num = INVALID_HOPNUM;
|
||||
size_t unit = MIN_BA_CNT;
|
||||
size_t ba_cnt;
|
||||
int j;
|
||||
|
||||
if (!buf_attr->adaptive || buf_attr->type != MTR_PBL)
|
||||
return 0;
|
||||
|
||||
/* Caculating the number of buf pages, each buf page need a BA */
|
||||
if (mtr->umem)
|
||||
ba_cnt = ib_umem_num_dma_blocks(mtr->umem, buf_pg_sz);
|
||||
else
|
||||
ba_cnt = DIV_ROUND_UP(buf_attr->region[0].size, buf_pg_sz);
|
||||
|
||||
for (j = 0; j <= HNS_ROCE_MAX_HOP_NUM; j++) {
|
||||
if (ba_cnt <= unit) {
|
||||
hop_num = j;
|
||||
break;
|
||||
}
|
||||
/* Number of BAs can be represented at per hop */
|
||||
unit *= ba_pg_sz / BA_BYTE_LEN;
|
||||
}
|
||||
|
||||
if (hop_num < 0) {
|
||||
ibdev_err(ibdev,
|
||||
"failed to calculate a valid hopnum.\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
buf_attr->region[0].hopnum = hop_num;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool is_buf_attr_valid(struct hns_roce_dev *hr_dev,
|
||||
struct hns_roce_buf_attr *attr)
|
||||
{
|
||||
struct ib_device *ibdev = &hr_dev->ib_dev;
|
||||
|
||||
if (attr->region_count > ARRAY_SIZE(attr->region) ||
|
||||
attr->region_count < 1 || attr->page_shift < HNS_HW_PAGE_SHIFT) {
|
||||
ibdev_err(ibdev,
|
||||
"invalid buf attr, region count %d, page shift %u.\n",
|
||||
attr->region_count, attr->page_shift);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static int mtr_init_buf_cfg(struct hns_roce_dev *hr_dev,
|
||||
struct hns_roce_buf_attr *attr,
|
||||
struct hns_roce_hem_cfg *cfg,
|
||||
unsigned int *buf_page_shift, u64 unalinged_size)
|
||||
struct hns_roce_mtr *mtr,
|
||||
struct hns_roce_buf_attr *attr)
|
||||
{
|
||||
struct hns_roce_hem_cfg *cfg = &mtr->hem_cfg;
|
||||
struct hns_roce_buf_region *r;
|
||||
u64 first_region_padding;
|
||||
int page_cnt, region_cnt;
|
||||
unsigned int page_shift;
|
||||
size_t buf_pg_sz;
|
||||
size_t buf_size;
|
||||
int page_cnt, i;
|
||||
u64 pgoff = 0;
|
||||
|
||||
if (!is_buf_attr_valid(hr_dev, attr))
|
||||
return -EINVAL;
|
||||
|
||||
/* If mtt is disabled, all pages must be within a continuous range */
|
||||
cfg->is_direct = !mtr_has_mtt(attr);
|
||||
cfg->region_count = attr->region_count;
|
||||
buf_size = mtr_bufs_size(attr);
|
||||
if (cfg->is_direct) {
|
||||
/* When HEM buffer uses 0-level addressing, the page size is
|
||||
* equal to the whole buffer size, and we split the buffer into
|
||||
* small pages which is used to check whether the adjacent
|
||||
* units are in the continuous space and its size is fixed to
|
||||
* 4K based on hns ROCEE's requirement.
|
||||
*/
|
||||
page_shift = HNS_HW_PAGE_SHIFT;
|
||||
|
||||
/* The ROCEE requires the page size to be 4K * 2 ^ N. */
|
||||
if (need_split_huge_page(mtr)) {
|
||||
buf_pg_sz = HNS_HW_PAGE_SIZE;
|
||||
cfg->buf_pg_count = 1;
|
||||
/* The ROCEE requires the page size to be 4K * 2 ^ N. */
|
||||
cfg->buf_pg_shift = HNS_HW_PAGE_SHIFT +
|
||||
order_base_2(DIV_ROUND_UP(buf_size, HNS_HW_PAGE_SIZE));
|
||||
first_region_padding = 0;
|
||||
} else {
|
||||
page_shift = attr->page_shift;
|
||||
cfg->buf_pg_count = DIV_ROUND_UP(buf_size + unalinged_size,
|
||||
1 << page_shift);
|
||||
cfg->buf_pg_shift = page_shift;
|
||||
first_region_padding = unalinged_size;
|
||||
buf_pg_sz = 1 << attr->page_shift;
|
||||
cfg->buf_pg_count = mtr->umem ?
|
||||
ib_umem_num_dma_blocks(mtr->umem, buf_pg_sz) :
|
||||
DIV_ROUND_UP(buf_size, buf_pg_sz);
|
||||
cfg->buf_pg_shift = attr->page_shift;
|
||||
pgoff = mtr->umem ? mtr->umem->address & ~PAGE_MASK : 0;
|
||||
}
|
||||
|
||||
/* Convert buffer size to page index and page count for each region and
|
||||
* the buffer's offset needs to be appended to the first region.
|
||||
*/
|
||||
for (page_cnt = 0, region_cnt = 0; region_cnt < attr->region_count &&
|
||||
region_cnt < ARRAY_SIZE(cfg->region); region_cnt++) {
|
||||
r = &cfg->region[region_cnt];
|
||||
for (page_cnt = 0, i = 0; i < attr->region_count; i++) {
|
||||
r = &cfg->region[i];
|
||||
r->offset = page_cnt;
|
||||
buf_size = hr_hw_page_align(attr->region[region_cnt].size +
|
||||
first_region_padding);
|
||||
r->count = DIV_ROUND_UP(buf_size, 1 << page_shift);
|
||||
first_region_padding = 0;
|
||||
buf_size = hr_hw_page_align(attr->region[i].size + pgoff);
|
||||
if (attr->type == MTR_PBL && mtr->umem)
|
||||
r->count = ib_umem_num_dma_blocks(mtr->umem, buf_pg_sz);
|
||||
else
|
||||
r->count = DIV_ROUND_UP(buf_size, buf_pg_sz);
|
||||
|
||||
pgoff = 0;
|
||||
page_cnt += r->count;
|
||||
r->hopnum = to_hr_hem_hopnum(attr->region[region_cnt].hopnum,
|
||||
r->count);
|
||||
r->hopnum = to_hr_hem_hopnum(attr->region[i].hopnum, r->count);
|
||||
}
|
||||
|
||||
cfg->region_count = region_cnt;
|
||||
*buf_page_shift = page_shift;
|
||||
|
||||
return page_cnt;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static u64 cal_pages_per_l1ba(unsigned int ba_per_bt, unsigned int hopnum)
|
||||
|
|
@ -1007,50 +1144,58 @@ int hns_roce_mtr_create(struct hns_roce_dev *hr_dev, struct hns_roce_mtr *mtr,
|
|||
unsigned long user_addr)
|
||||
{
|
||||
struct ib_device *ibdev = &hr_dev->ib_dev;
|
||||
unsigned int buf_page_shift = 0;
|
||||
int buf_page_cnt;
|
||||
int ret;
|
||||
|
||||
buf_page_cnt = mtr_init_buf_cfg(hr_dev, buf_attr, &mtr->hem_cfg,
|
||||
&buf_page_shift,
|
||||
udata ? user_addr & ~PAGE_MASK : 0);
|
||||
if (buf_page_cnt < 1 || buf_page_shift < HNS_HW_PAGE_SHIFT) {
|
||||
ibdev_err(ibdev, "failed to init mtr cfg, count %d shift %u.\n",
|
||||
buf_page_cnt, buf_page_shift);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ret = mtr_alloc_mtt(hr_dev, mtr, ba_page_shift);
|
||||
if (ret) {
|
||||
ibdev_err(ibdev, "failed to alloc mtr mtt, ret = %d.\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* The caller has its own buffer list and invokes the hns_roce_mtr_map()
|
||||
* to finish the MTT configuration.
|
||||
*/
|
||||
if (buf_attr->mtt_only) {
|
||||
mtr->umem = NULL;
|
||||
mtr->kmem = NULL;
|
||||
return 0;
|
||||
} else {
|
||||
ret = mtr_alloc_bufs(hr_dev, mtr, buf_attr, udata, user_addr);
|
||||
if (ret) {
|
||||
ibdev_err(ibdev,
|
||||
"failed to alloc mtr bufs, ret = %d.\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = get_best_page_shift(hr_dev, mtr, buf_attr);
|
||||
if (ret)
|
||||
goto err_init_buf;
|
||||
|
||||
ret = get_best_hop_num(hr_dev, mtr, buf_attr, ba_page_shift);
|
||||
if (ret)
|
||||
goto err_init_buf;
|
||||
}
|
||||
|
||||
ret = mtr_alloc_bufs(hr_dev, mtr, buf_attr, udata, user_addr);
|
||||
ret = mtr_init_buf_cfg(hr_dev, mtr, buf_attr);
|
||||
if (ret)
|
||||
goto err_init_buf;
|
||||
|
||||
ret = mtr_alloc_mtt(hr_dev, mtr, ba_page_shift);
|
||||
if (ret) {
|
||||
ibdev_err(ibdev, "failed to alloc mtr bufs, ret = %d.\n", ret);
|
||||
ibdev_err(ibdev, "failed to alloc mtr mtt, ret = %d.\n", ret);
|
||||
goto err_init_buf;
|
||||
}
|
||||
|
||||
if (buf_attr->mtt_only)
|
||||
return 0;
|
||||
|
||||
/* Write buffer's dma address to MTT */
|
||||
ret = mtr_map_bufs(hr_dev, mtr);
|
||||
if (ret) {
|
||||
ibdev_err(ibdev, "failed to map mtr bufs, ret = %d.\n", ret);
|
||||
goto err_alloc_mtt;
|
||||
}
|
||||
|
||||
/* Write buffer's dma address to MTT */
|
||||
ret = mtr_map_bufs(hr_dev, mtr, buf_page_cnt, buf_page_shift);
|
||||
if (ret)
|
||||
ibdev_err(ibdev, "failed to map mtr bufs, ret = %d.\n", ret);
|
||||
else
|
||||
return 0;
|
||||
return 0;
|
||||
|
||||
mtr_free_bufs(hr_dev, mtr);
|
||||
err_alloc_mtt:
|
||||
mtr_free_mtt(hr_dev, mtr);
|
||||
err_init_buf:
|
||||
mtr_free_bufs(hr_dev, mtr);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1004,6 +1004,60 @@ static void free_kernel_wrid(struct hns_roce_qp *hr_qp)
|
|||
kfree(hr_qp->sq.wrid);
|
||||
}
|
||||
|
||||
static void default_congest_type(struct hns_roce_dev *hr_dev,
|
||||
struct hns_roce_qp *hr_qp)
|
||||
{
|
||||
if (hr_qp->ibqp.qp_type == IB_QPT_UD ||
|
||||
hr_qp->ibqp.qp_type == IB_QPT_GSI)
|
||||
hr_qp->cong_type = CONG_TYPE_DCQCN;
|
||||
else
|
||||
hr_qp->cong_type = hr_dev->caps.default_cong_type;
|
||||
}
|
||||
|
||||
static int set_congest_type(struct hns_roce_qp *hr_qp,
|
||||
struct hns_roce_ib_create_qp *ucmd)
|
||||
{
|
||||
struct hns_roce_dev *hr_dev = to_hr_dev(hr_qp->ibqp.device);
|
||||
|
||||
switch (ucmd->cong_type_flags) {
|
||||
case HNS_ROCE_CREATE_QP_FLAGS_DCQCN:
|
||||
hr_qp->cong_type = CONG_TYPE_DCQCN;
|
||||
break;
|
||||
case HNS_ROCE_CREATE_QP_FLAGS_LDCP:
|
||||
hr_qp->cong_type = CONG_TYPE_LDCP;
|
||||
break;
|
||||
case HNS_ROCE_CREATE_QP_FLAGS_HC3:
|
||||
hr_qp->cong_type = CONG_TYPE_HC3;
|
||||
break;
|
||||
case HNS_ROCE_CREATE_QP_FLAGS_DIP:
|
||||
hr_qp->cong_type = CONG_TYPE_DIP;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (!test_bit(hr_qp->cong_type, (unsigned long *)&hr_dev->caps.cong_cap))
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
if (hr_qp->ibqp.qp_type == IB_QPT_UD &&
|
||||
hr_qp->cong_type != CONG_TYPE_DCQCN)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int set_congest_param(struct hns_roce_dev *hr_dev,
|
||||
struct hns_roce_qp *hr_qp,
|
||||
struct hns_roce_ib_create_qp *ucmd)
|
||||
{
|
||||
if (ucmd->comp_mask & HNS_ROCE_CREATE_QP_MASK_CONGEST_TYPE)
|
||||
return set_congest_type(hr_qp, ucmd);
|
||||
|
||||
default_congest_type(hr_dev, hr_qp);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int set_qp_param(struct hns_roce_dev *hr_dev, struct hns_roce_qp *hr_qp,
|
||||
struct ib_qp_init_attr *init_attr,
|
||||
struct ib_udata *udata,
|
||||
|
|
@ -1043,6 +1097,10 @@ static int set_qp_param(struct hns_roce_dev *hr_dev, struct hns_roce_qp *hr_qp,
|
|||
ibdev_err(ibdev,
|
||||
"failed to set user SQ size, ret = %d.\n",
|
||||
ret);
|
||||
|
||||
ret = set_congest_param(hr_dev, hr_qp, ucmd);
|
||||
if (ret)
|
||||
return ret;
|
||||
} else {
|
||||
if (hr_dev->pci_dev->revision >= PCI_REVISION_ID_HIP09)
|
||||
hr_qp->config = HNS_ROCE_EXSGE_FLAGS;
|
||||
|
|
@ -1051,6 +1109,8 @@ static int set_qp_param(struct hns_roce_dev *hr_dev, struct hns_roce_qp *hr_qp,
|
|||
ibdev_err(ibdev,
|
||||
"failed to set kernel SQ size, ret = %d.\n",
|
||||
ret);
|
||||
|
||||
default_congest_type(hr_dev, hr_qp);
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
|
|
|||
|
|
@ -97,16 +97,33 @@ int hns_roce_fill_res_qp_entry_raw(struct sk_buff *msg, struct ib_qp *ib_qp)
|
|||
{
|
||||
struct hns_roce_dev *hr_dev = to_hr_dev(ib_qp->device);
|
||||
struct hns_roce_qp *hr_qp = to_hr_qp(ib_qp);
|
||||
struct hns_roce_v2_qp_context context;
|
||||
struct hns_roce_full_qp_ctx {
|
||||
struct hns_roce_v2_qp_context qpc;
|
||||
struct hns_roce_v2_scc_context sccc;
|
||||
} context = {};
|
||||
int ret;
|
||||
|
||||
if (!hr_dev->hw->query_qpc)
|
||||
return -EINVAL;
|
||||
|
||||
ret = hr_dev->hw->query_qpc(hr_dev, hr_qp->qpn, &context);
|
||||
ret = hr_dev->hw->query_qpc(hr_dev, hr_qp->qpn, &context.qpc);
|
||||
if (ret)
|
||||
return -EINVAL;
|
||||
return ret;
|
||||
|
||||
/* If SCC is disabled or the query fails, the queried SCCC will
|
||||
* be all 0.
|
||||
*/
|
||||
if (!(hr_dev->caps.flags & HNS_ROCE_CAP_FLAG_QP_FLOW_CTRL) ||
|
||||
!hr_dev->hw->query_sccc)
|
||||
goto out;
|
||||
|
||||
ret = hr_dev->hw->query_sccc(hr_dev, hr_qp->qpn, &context.sccc);
|
||||
if (ret)
|
||||
ibdev_warn_ratelimited(&hr_dev->ib_dev,
|
||||
"failed to query SCCC, ret = %d.\n",
|
||||
ret);
|
||||
|
||||
out:
|
||||
ret = nla_put(msg, RDMA_NLDEV_ATTR_RES_RAW, sizeof(context), &context);
|
||||
|
||||
return ret;
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user