coresight: Changes for v6.1
Coresight trace subsystem updates for v6.1 includes: - Support for HiSilicon PTT trace - Coresight cleanup of sysfs accessor functions, reduced code size. - Expose coresight timestamp source for ETMv4+ - DT binding updates to include missing properties - Minor documentation, Kconfig text fixes. Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com> -----BEGIN PGP SIGNATURE----- iQIzBAABCAAdFiEEuFy0byloRoXZHaWBxcXRZPKyBqEFAmMpf/UACgkQxcXRZPKy BqE58g//cxM7TR4QNsI0IQxHxfDjFxWyiDVLfLxpZK8HHQYbpWZSMq/8Da+BJMNC UtxaDIPdpMJy1oPcNuLE6tyvhlpK+Mp1BII934LpqvQp14YIjaghWCikYyHy0Awi Fz1UG46bjcq3L8VA2kg3ShzUmW/SJH4/Lh5yGvnGmQPGP/Kc4Fr/PdY1NNcE+wC4 HeIRCla5rt6LXvNMGWL747pYPwwrG6moIb9JfYiebeD/vmAG1tTubSZFkvEKYTzE zZRHWJVQaKEAvrP4Ra4/m3ZavvQ6lqrs8GiuwZNsiVvIL+CThIg7/uJDxrJt9X+9 J0qoPP8UmSQYTbFOAfGerrTkRGjk+eb+CAtY3vIN99TMsCVsDCfUN0sOLLKNmHKD JAO7od8hgPMON4V/B3bKUKU1j66Ufw4v3G3T0QkjGfspMxOfUA7fbr7XXxQ6Dtxf 608OgOG8T2Xww+k5XJMTBXJchM5/SH3gSQwmqoMe5oq6YYN2DNjzf+/M6+uSwQFi Yy7ONu6mm7OU6XrCvccYQgc33ZY6kUkELKqH3/zPqObx5xLl9zKjX4tFBcy1/CWe D7tk0+ofPRuistyMV6ECCaIAVj5pWv8hiW7FDfI4okbSM5ah5spONrcaM6lwddPF B1kVRcYCjZBmVhANsqtMmLxARX2qXgRnHJ6h5TH13C/hmEnoEls= =rg+8 -----END PGP SIGNATURE----- Merge tag 'coresight-next-v6.1' of git://git.kernel.org/pub/scm/linux/kernel/git/coresight/linux into char-misc-next Suzuki writes: "coresight: Changes for v6.1 Coresight trace subsystem updates for v6.1 includes: - Support for HiSilicon PTT trace - Coresight cleanup of sysfs accessor functions, reduced code size. - Expose coresight timestamp source for ETMv4+ - DT binding updates to include missing properties - Minor documentation, Kconfig text fixes. Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>" * tag 'coresight-next-v6.1' of git://git.kernel.org/pub/scm/linux/kernel/git/coresight/linux: hwtracing: hisi_ptt: Fix up for "iommu/dma: Make header private" MAINTAINERS: Add maintainer for HiSilicon PTT driver docs: trace: Add HiSilicon PTT device driver documentation hwtracing: hisi_ptt: Add tune function support for HiSilicon PCIe Tune and Trace device hwtracing: hisi_ptt: Add trace function support for HiSilicon PCIe Tune and Trace device iommu/arm-smmu-v3: Make default domain type of HiSilicon PTT device to identity coresight: cti-sysfs: Mark coresight_cti_reg_store() as __maybe_unused coresight: Make new csdev_access offsets unsigned coresight: cti-sysfs: Re-use same functions for similar sysfs register accessors coresight: Re-use same function for similar sysfs register accessors coresight: Simplify sysfs accessors by using csdev_access abstraction coresight: Remove unused function parameter coresight: etm4x: docs: Add documentation for 'ts_source' sysfs interface coresight: etm4x: Expose default timestamp source in sysfs dt-bindings: arm: coresight-tmc: Add 'iommu' property dt-bindings: arm: coresight: Add 'power-domains' property coresight: docs: Fix a broken reference coresight: trbe: fix Kconfig "its" grammar
This commit is contained in:
commit
8be7dfc6a8
|
@ -516,3 +516,11 @@ Contact: Mathieu Poirier <mathieu.poirier@linaro.org>
|
|||
Description: (Read) Returns the number of special conditional P1 right-hand keys
|
||||
that the trace unit can use (0x194). The value is taken
|
||||
directly from the HW.
|
||||
|
||||
What: /sys/bus/coresight/devices/etm<N>/ts_source
|
||||
Date: October 2022
|
||||
KernelVersion: 6.1
|
||||
Contact: Mathieu Poirier <mathieu.poirier@linaro.org> or Suzuki K Poulose <suzuki.poulose@arm.com>
|
||||
Description: (Read) When FEAT_TRF is implemented, value of TRFCR_ELx.TS used for
|
||||
trace session. Otherwise -1 indicates an unknown time source. Check
|
||||
trcidr0.tssize to see if a global timestamp is available.
|
||||
|
|
|
@ -0,0 +1,61 @@
|
|||
What: /sys/devices/hisi_ptt<sicl_id>_<core_id>/tune
|
||||
Date: October 2022
|
||||
KernelVersion: 6.1
|
||||
Contact: Yicong Yang <yangyicong@hisilicon.com>
|
||||
Description: This directory contains files for tuning the PCIe link
|
||||
parameters(events). Each file is named after the event
|
||||
of the PCIe link.
|
||||
|
||||
See Documentation/trace/hisi-ptt.rst for more information.
|
||||
|
||||
What: /sys/devices/hisi_ptt<sicl_id>_<core_id>/tune/qos_tx_cpl
|
||||
Date: October 2022
|
||||
KernelVersion: 6.1
|
||||
Contact: Yicong Yang <yangyicong@hisilicon.com>
|
||||
Description: (RW) Controls the weight of Tx completion TLPs, which influence
|
||||
the proportion of outbound completion TLPs on the PCIe link.
|
||||
The available tune data is [0, 1, 2]. Writing a negative value
|
||||
will return an error, and out of range values will be converted
|
||||
to 2. The value indicates a probable level of the event.
|
||||
|
||||
What: /sys/devices/hisi_ptt<sicl_id>_<core_id>/tune/qos_tx_np
|
||||
Date: October 2022
|
||||
KernelVersion: 6.1
|
||||
Contact: Yicong Yang <yangyicong@hisilicon.com>
|
||||
Description: (RW) Controls the weight of Tx non-posted TLPs, which influence
|
||||
the proportion of outbound non-posted TLPs on the PCIe link.
|
||||
The available tune data is [0, 1, 2]. Writing a negative value
|
||||
will return an error, and out of range values will be converted
|
||||
to 2. The value indicates a probable level of the event.
|
||||
|
||||
What: /sys/devices/hisi_ptt<sicl_id>_<core_id>/tune/qos_tx_p
|
||||
Date: October 2022
|
||||
KernelVersion: 6.1
|
||||
Contact: Yicong Yang <yangyicong@hisilicon.com>
|
||||
Description: (RW) Controls the weight of Tx posted TLPs, which influence the
|
||||
proportion of outbound posted TLPs on the PCIe link.
|
||||
The available tune data is [0, 1, 2]. Writing a negative value
|
||||
will return an error, and out of range values will be converted
|
||||
to 2. The value indicates a probable level of the event.
|
||||
|
||||
What: /sys/devices/hisi_ptt<sicl_id>_<core_id>/tune/rx_alloc_buf_level
|
||||
Date: October 2022
|
||||
KernelVersion: 6.1
|
||||
Contact: Yicong Yang <yangyicong@hisilicon.com>
|
||||
Description: (RW) Control the allocated buffer watermark for inbound packets.
|
||||
The packets will be stored in the buffer first and then transmitted
|
||||
either when the watermark reached or when timed out.
|
||||
The available tune data is [0, 1, 2]. Writing a negative value
|
||||
will return an error, and out of range values will be converted
|
||||
to 2. The value indicates a probable level of the event.
|
||||
|
||||
What: /sys/devices/hisi_ptt<sicl_id>_<core_id>/tune/tx_alloc_buf_level
|
||||
Date: October 2022
|
||||
KernelVersion: 6.1
|
||||
Contact: Yicong Yang <yangyicong@hisilicon.com>
|
||||
Description: (RW) Control the allocated buffer watermark of outbound packets.
|
||||
The packets will be stored in the buffer first and then transmitted
|
||||
either when the watermark reached or when timed out.
|
||||
The available tune data is [0, 1, 2]. Writing a negative value
|
||||
will return an error, and out of range values will be converted
|
||||
to 2. The value indicates a probable level of the event.
|
|
@ -61,6 +61,9 @@ properties:
|
|||
maxItems: 1
|
||||
description: Address translation error interrupt
|
||||
|
||||
power-domains:
|
||||
maxItems: 1
|
||||
|
||||
in-ports:
|
||||
$ref: /schemas/graph.yaml#/properties/ports
|
||||
additionalProperties: false
|
||||
|
|
|
@ -98,6 +98,9 @@ properties:
|
|||
base cti node if compatible string arm,coresight-cti-v8-arch is used,
|
||||
or may appear in a trig-conns child node when appropriate.
|
||||
|
||||
power-domains:
|
||||
maxItems: 1
|
||||
|
||||
arm,cti-ctm-id:
|
||||
$ref: /schemas/types.yaml#/definitions/uint32
|
||||
description:
|
||||
|
|
|
@ -54,6 +54,9 @@ properties:
|
|||
- const: apb_pclk
|
||||
- const: atclk
|
||||
|
||||
power-domains:
|
||||
maxItems: 1
|
||||
|
||||
in-ports:
|
||||
$ref: /schemas/graph.yaml#/properties/ports
|
||||
|
||||
|
|
|
@ -54,6 +54,9 @@ properties:
|
|||
- const: apb_pclk
|
||||
- const: atclk
|
||||
|
||||
power-domains:
|
||||
maxItems: 1
|
||||
|
||||
qcom,replicator-loses-context:
|
||||
type: boolean
|
||||
description:
|
||||
|
|
|
@ -54,6 +54,9 @@ properties:
|
|||
- const: apb_pclk
|
||||
- const: atclk
|
||||
|
||||
power-domains:
|
||||
maxItems: 1
|
||||
|
||||
in-ports:
|
||||
$ref: /schemas/graph.yaml#/properties/ports
|
||||
additionalProperties: false
|
||||
|
|
|
@ -73,6 +73,9 @@ properties:
|
|||
- const: apb_pclk
|
||||
- const: atclk
|
||||
|
||||
power-domains:
|
||||
maxItems: 1
|
||||
|
||||
arm,coresight-loses-context-with-cpu:
|
||||
type: boolean
|
||||
description:
|
||||
|
|
|
@ -27,6 +27,9 @@ properties:
|
|||
compatible:
|
||||
const: arm,coresight-static-funnel
|
||||
|
||||
power-domains:
|
||||
maxItems: 1
|
||||
|
||||
in-ports:
|
||||
$ref: /schemas/graph.yaml#/properties/ports
|
||||
|
||||
|
|
|
@ -27,6 +27,9 @@ properties:
|
|||
compatible:
|
||||
const: arm,coresight-static-replicator
|
||||
|
||||
power-domains:
|
||||
maxItems: 1
|
||||
|
||||
in-ports:
|
||||
$ref: /schemas/graph.yaml#/properties/ports
|
||||
additionalProperties: false
|
||||
|
|
|
@ -61,6 +61,9 @@ properties:
|
|||
- const: apb_pclk
|
||||
- const: atclk
|
||||
|
||||
power-domains:
|
||||
maxItems: 1
|
||||
|
||||
out-ports:
|
||||
$ref: /schemas/graph.yaml#/properties/ports
|
||||
additionalProperties: false
|
||||
|
|
|
@ -55,6 +55,12 @@ properties:
|
|||
- const: apb_pclk
|
||||
- const: atclk
|
||||
|
||||
iommus:
|
||||
maxItems: 1
|
||||
|
||||
power-domains:
|
||||
maxItems: 1
|
||||
|
||||
arm,buffer-size:
|
||||
$ref: /schemas/types.yaml#/definitions/uint32
|
||||
deprecated: true
|
||||
|
|
|
@ -54,6 +54,9 @@ properties:
|
|||
- const: apb_pclk
|
||||
- const: atclk
|
||||
|
||||
power-domains:
|
||||
maxItems: 1
|
||||
|
||||
in-ports:
|
||||
$ref: /schemas/graph.yaml#/properties/ports
|
||||
additionalProperties: false
|
||||
|
|
|
@ -33,6 +33,9 @@ properties:
|
|||
Handle to the cpu this ETE is bound to.
|
||||
$ref: /schemas/types.yaml#/definitions/phandle
|
||||
|
||||
power-domains:
|
||||
maxItems: 1
|
||||
|
||||
out-ports:
|
||||
description: |
|
||||
Output connections from the ETE to legacy CoreSight trace bus.
|
||||
|
|
|
@ -117,7 +117,8 @@ divide into below cases:
|
|||
Device Tree Bindings
|
||||
--------------------
|
||||
|
||||
See Documentation/devicetree/bindings/arm/coresight-cpu-debug.txt for details.
|
||||
See Documentation/devicetree/bindings/arm/arm,coresight-cpu-debug.yaml for
|
||||
details.
|
||||
|
||||
|
||||
How to use the module
|
||||
|
|
|
@ -71,6 +71,20 @@ the ‘TRC’ prefix.
|
|||
|
||||
----
|
||||
|
||||
:File: ``ts_source`` (ro)
|
||||
:Trace Registers: None.
|
||||
:Notes:
|
||||
When FEAT_TRF is implemented, value of TRFCR_ELx.TS used for trace session. Otherwise -1
|
||||
indicates an unknown time source. Check trcidr0.tssize to see if a global timestamp is
|
||||
available.
|
||||
|
||||
:Example:
|
||||
``$> cat ts_source``
|
||||
|
||||
``$> 1``
|
||||
|
||||
----
|
||||
|
||||
:File: ``addr_idx`` (rw)
|
||||
:Trace Registers: None.
|
||||
:Notes:
|
||||
|
|
|
@ -0,0 +1,298 @@
|
|||
.. SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
======================================
|
||||
HiSilicon PCIe Tune and Trace device
|
||||
======================================
|
||||
|
||||
Introduction
|
||||
============
|
||||
|
||||
HiSilicon PCIe tune and trace device (PTT) is a PCIe Root Complex
|
||||
integrated Endpoint (RCiEP) device, providing the capability
|
||||
to dynamically monitor and tune the PCIe link's events (tune),
|
||||
and trace the TLP headers (trace). The two functions are independent,
|
||||
but is recommended to use them together to analyze and enhance the
|
||||
PCIe link's performance.
|
||||
|
||||
On Kunpeng 930 SoC, the PCIe Root Complex is composed of several
|
||||
PCIe cores. Each PCIe core includes several Root Ports and a PTT
|
||||
RCiEP, like below. The PTT device is capable of tuning and
|
||||
tracing the links of the PCIe core.
|
||||
::
|
||||
|
||||
+--------------Core 0-------+
|
||||
| | [ PTT ] |
|
||||
| | [Root Port]---[Endpoint]
|
||||
| | [Root Port]---[Endpoint]
|
||||
| | [Root Port]---[Endpoint]
|
||||
Root Complex |------Core 1-------+
|
||||
| | [ PTT ] |
|
||||
| | [Root Port]---[ Switch ]---[Endpoint]
|
||||
| | [Root Port]---[Endpoint] `-[Endpoint]
|
||||
| | [Root Port]---[Endpoint]
|
||||
+---------------------------+
|
||||
|
||||
The PTT device driver registers one PMU device for each PTT device.
|
||||
The name of each PTT device is composed of 'hisi_ptt' prefix with
|
||||
the id of the SICL and the Core where it locates. The Kunpeng 930
|
||||
SoC encapsulates multiple CPU dies (SCCL, Super CPU Cluster) and
|
||||
IO dies (SICL, Super I/O Cluster), where there's one PCIe Root
|
||||
Complex for each SICL.
|
||||
::
|
||||
|
||||
/sys/devices/hisi_ptt<sicl_id>_<core_id>
|
||||
|
||||
Tune
|
||||
====
|
||||
|
||||
PTT tune is designed for monitoring and adjusting PCIe link parameters (events).
|
||||
Currently we support events in 2 classes. The scope of the events
|
||||
covers the PCIe core to which the PTT device belongs.
|
||||
|
||||
Each event is presented as a file under $(PTT PMU dir)/tune, and
|
||||
a simple open/read/write/close cycle will be used to tune the event.
|
||||
::
|
||||
|
||||
$ cd /sys/devices/hisi_ptt<sicl_id>_<core_id>/tune
|
||||
$ ls
|
||||
qos_tx_cpl qos_tx_np qos_tx_p
|
||||
tx_path_rx_req_alloc_buf_level
|
||||
tx_path_tx_req_alloc_buf_level
|
||||
$ cat qos_tx_dp
|
||||
1
|
||||
$ echo 2 > qos_tx_dp
|
||||
$ cat qos_tx_dp
|
||||
2
|
||||
|
||||
Current value (numerical value) of the event can be simply read
|
||||
from the file, and the desired value written to the file to tune.
|
||||
|
||||
1. Tx Path QoS Control
|
||||
------------------------
|
||||
|
||||
The following files are provided to tune the QoS of the tx path of
|
||||
the PCIe core.
|
||||
|
||||
- qos_tx_cpl: weight of Tx completion TLPs
|
||||
- qos_tx_np: weight of Tx non-posted TLPs
|
||||
- qos_tx_p: weight of Tx posted TLPs
|
||||
|
||||
The weight influences the proportion of certain packets on the PCIe link.
|
||||
For example, for the storage scenario, increase the proportion
|
||||
of the completion packets on the link to enhance the performance as
|
||||
more completions are consumed.
|
||||
|
||||
The available tune data of these events is [0, 1, 2].
|
||||
Writing a negative value will return an error, and out of range
|
||||
values will be converted to 2. Note that the event value just
|
||||
indicates a probable level, but is not precise.
|
||||
|
||||
2. Tx Path Buffer Control
|
||||
-------------------------
|
||||
|
||||
Following files are provided to tune the buffer of tx path of the PCIe core.
|
||||
|
||||
- rx_alloc_buf_level: watermark of Rx requested
|
||||
- tx_alloc_buf_level: watermark of Tx requested
|
||||
|
||||
These events influence the watermark of the buffer allocated for each
|
||||
type. Rx means the inbound while Tx means outbound. The packets will
|
||||
be stored in the buffer first and then transmitted either when the
|
||||
watermark reached or when timed out. For a busy direction, you should
|
||||
increase the related buffer watermark to avoid frequently posting and
|
||||
thus enhance the performance. In most cases just keep the default value.
|
||||
|
||||
The available tune data of above events is [0, 1, 2].
|
||||
Writing a negative value will return an error, and out of range
|
||||
values will be converted to 2. Note that the event value just
|
||||
indicates a probable level, but is not precise.
|
||||
|
||||
Trace
|
||||
=====
|
||||
|
||||
PTT trace is designed for dumping the TLP headers to the memory, which
|
||||
can be used to analyze the transactions and usage condition of the PCIe
|
||||
Link. You can choose to filter the traced headers by either Requester ID,
|
||||
or those downstream of a set of Root Ports on the same core of the PTT
|
||||
device. It's also supported to trace the headers of certain type and of
|
||||
certain direction.
|
||||
|
||||
You can use the perf command `perf record` to set the parameters, start
|
||||
trace and get the data. It's also supported to decode the trace
|
||||
data with `perf report`. The control parameters for trace is inputted
|
||||
as event code for each events, which will be further illustrated later.
|
||||
An example usage is like
|
||||
::
|
||||
|
||||
$ perf record -e hisi_ptt0_2/filter=0x80001,type=1,direction=1,
|
||||
format=1/ -- sleep 5
|
||||
|
||||
This will trace the TLP headers downstream root port 0000:00:10.1 (event
|
||||
code for event 'filter' is 0x80001) with type of posted TLP requests,
|
||||
direction of inbound and traced data format of 8DW.
|
||||
|
||||
1. Filter
|
||||
---------
|
||||
|
||||
The TLP headers to trace can be filtered by the Root Ports or the Requester ID
|
||||
of the Endpoint, which are located on the same core of the PTT device. You can
|
||||
set the filter by specifying the `filter` parameter which is required to start
|
||||
the trace. The parameter value is 20 bit. Bit 19 indicates the filter type.
|
||||
1 for Root Port filter and 0 for Requester filter. Bit[15:0] indicates the
|
||||
filter value. The value for a Root Port is a mask of the core port id which is
|
||||
calculated from its PCI Slot ID as (slotid & 7) * 2. The value for a Requester
|
||||
is the Requester ID (Device ID of the PCIe function). Bit[18:16] is currently
|
||||
reserved for extension.
|
||||
|
||||
For example, if the desired filter is Endpoint function 0000:01:00.1 the filter
|
||||
value will be 0x00101. If the desired filter is Root Port 0000:00:10.0 then
|
||||
then filter value is calculated as 0x80001.
|
||||
|
||||
Note that multiple Root Ports can be specified at one time, but only one
|
||||
Endpoint function can be specified in one trace. Specifying both Root Port
|
||||
and function at the same time is not supported. Driver maintains a list of
|
||||
available filters and will check the invalid inputs.
|
||||
|
||||
Currently the available filters are detected in driver's probe. If the supported
|
||||
devices are removed/added after probe, you may need to reload the driver to update
|
||||
the filters.
|
||||
|
||||
2. Type
|
||||
-------
|
||||
|
||||
You can trace the TLP headers of certain types by specifying the `type`
|
||||
parameter, which is required to start the trace. The parameter value is
|
||||
8 bit. Current supported types and related values are shown below:
|
||||
|
||||
- 8'b00000001: posted requests (P)
|
||||
- 8'b00000010: non-posted requests (NP)
|
||||
- 8'b00000100: completions (CPL)
|
||||
|
||||
You can specify multiple types when tracing inbound TLP headers, but can only
|
||||
specify one when tracing outbound TLP headers.
|
||||
|
||||
3. Direction
|
||||
------------
|
||||
|
||||
You can trace the TLP headers from certain direction, which is relative
|
||||
to the Root Port or the PCIe core, by specifying the `direction` parameter.
|
||||
This is optional and the default parameter is inbound. The parameter value
|
||||
is 4 bit. When the desired format is 4DW, directions and related values
|
||||
supported are shown below:
|
||||
|
||||
- 4'b0000: inbound TLPs (P, NP, CPL)
|
||||
- 4'b0001: outbound TLPs (P, NP, CPL)
|
||||
- 4'b0010: outbound TLPs (P, NP, CPL) and inbound TLPs (P, NP, CPL B)
|
||||
- 4'b0011: outbound TLPs (P, NP, CPL) and inbound TLPs (CPL A)
|
||||
|
||||
When the desired format is 8DW, directions and related values supported are
|
||||
shown below:
|
||||
|
||||
- 4'b0000: reserved
|
||||
- 4'b0001: outbound TLPs (P, NP, CPL)
|
||||
- 4'b0010: inbound TLPs (P, NP, CPL B)
|
||||
- 4'b0011: inbound TLPs (CPL A)
|
||||
|
||||
Inbound completions are classified into two types:
|
||||
|
||||
- completion A (CPL A): completion of CHI/DMA/Native non-posted requests, except for CPL B
|
||||
- completion B (CPL B): completion of DMA remote2local and P2P non-posted requests
|
||||
|
||||
4. Format
|
||||
--------------
|
||||
|
||||
You can change the format of the traced TLP headers by specifying the
|
||||
`format` parameter. The default format is 4DW. The parameter value is 4 bit.
|
||||
Current supported formats and related values are shown below:
|
||||
|
||||
- 4'b0000: 4DW length per TLP header
|
||||
- 4'b0001: 8DW length per TLP header
|
||||
|
||||
The traced TLP header format is different from the PCIe standard.
|
||||
|
||||
When using the 8DW data format, the entire TLP header is logged
|
||||
(Header DW0-3 shown below). For example, the TLP header for Memory
|
||||
Reads with 64-bit addresses is shown in PCIe r5.0, Figure 2-17;
|
||||
the header for Configuration Requests is shown in Figure 2.20, etc.
|
||||
|
||||
In addition, 8DW trace buffer entries contain a timestamp and
|
||||
possibly a prefix for a PASID TLP prefix (see Figure 6-20, PCIe r5.0).
|
||||
Otherwise this field will be all 0.
|
||||
|
||||
The bit[31:11] of DW0 is always 0x1fffff, which can be
|
||||
used to distinguish the data format. 8DW format is like
|
||||
::
|
||||
|
||||
bits [ 31:11 ][ 10:0 ]
|
||||
|---------------------------------------|-------------------|
|
||||
DW0 [ 0x1fffff ][ Reserved (0x7ff) ]
|
||||
DW1 [ Prefix ]
|
||||
DW2 [ Header DW0 ]
|
||||
DW3 [ Header DW1 ]
|
||||
DW4 [ Header DW2 ]
|
||||
DW5 [ Header DW3 ]
|
||||
DW6 [ Reserved (0x0) ]
|
||||
DW7 [ Time ]
|
||||
|
||||
When using the 4DW data format, DW0 of the trace buffer entry
|
||||
contains selected fields of DW0 of the TLP, together with a
|
||||
timestamp. DW1-DW3 of the trace buffer entry contain DW1-DW3
|
||||
directly from the TLP header.
|
||||
|
||||
4DW format is like
|
||||
::
|
||||
|
||||
bits [31:30] [ 29:25 ][24][23][22][21][ 20:11 ][ 10:0 ]
|
||||
|-----|---------|---|---|---|---|-------------|-------------|
|
||||
DW0 [ Fmt ][ Type ][T9][T8][TH][SO][ Length ][ Time ]
|
||||
DW1 [ Header DW1 ]
|
||||
DW2 [ Header DW2 ]
|
||||
DW3 [ Header DW3 ]
|
||||
|
||||
5. Memory Management
|
||||
--------------------
|
||||
|
||||
The traced TLP headers will be written to the memory allocated
|
||||
by the driver. The hardware accepts 4 DMA address with same size,
|
||||
and writes the buffer sequentially like below. If DMA addr 3 is
|
||||
finished and the trace is still on, it will return to addr 0.
|
||||
::
|
||||
|
||||
+->[DMA addr 0]->[DMA addr 1]->[DMA addr 2]->[DMA addr 3]-+
|
||||
+---------------------------------------------------------+
|
||||
|
||||
Driver will allocate each DMA buffer of 4MiB. The finished buffer
|
||||
will be copied to the perf AUX buffer allocated by the perf core.
|
||||
Once the AUX buffer is full while the trace is still on, driver
|
||||
will commit the AUX buffer first and then apply for a new one with
|
||||
the same size. The size of AUX buffer is default to 16MiB. User can
|
||||
adjust the size by specifying the `-m` parameter of the perf command.
|
||||
|
||||
6. Decoding
|
||||
-----------
|
||||
|
||||
You can decode the traced data with `perf report -D` command (currently
|
||||
only support to dump the raw trace data). The traced data will be decoded
|
||||
according to the format described previously (take 8DW as an example):
|
||||
::
|
||||
|
||||
[...perf headers and other information]
|
||||
. ... HISI PTT data: size 4194304 bytes
|
||||
. 00000000: 00 00 00 00 Prefix
|
||||
. 00000004: 01 00 00 60 Header DW0
|
||||
. 00000008: 0f 1e 00 01 Header DW1
|
||||
. 0000000c: 04 00 00 00 Header DW2
|
||||
. 00000010: 40 00 81 02 Header DW3
|
||||
. 00000014: 33 c0 04 00 Time
|
||||
. 00000020: 00 00 00 00 Prefix
|
||||
. 00000024: 01 00 00 60 Header DW0
|
||||
. 00000028: 0f 1e 00 01 Header DW1
|
||||
. 0000002c: 04 00 00 00 Header DW2
|
||||
. 00000030: 40 00 81 02 Header DW3
|
||||
. 00000034: 02 00 00 00 Time
|
||||
. 00000040: 00 00 00 00 Prefix
|
||||
. 00000044: 01 00 00 60 Header DW0
|
||||
. 00000048: 0f 1e 00 01 Header DW1
|
||||
. 0000004c: 04 00 00 00 Header DW2
|
||||
. 00000050: 40 00 81 02 Header DW3
|
||||
[...]
|
|
@ -33,3 +33,4 @@ Linux Tracing Technologies
|
|||
coresight/index
|
||||
user_events
|
||||
rv/index
|
||||
hisi-ptt
|
||||
|
|
|
@ -9180,6 +9180,14 @@ S: Supported
|
|||
F: Documentation/admin-guide/perf/hns3-pmu.rst
|
||||
F: drivers/perf/hisilicon/hns3_pmu.c
|
||||
|
||||
HISILICON PTT DRIVER
|
||||
M: Yicong Yang <yangyicong@hisilicon.com>
|
||||
L: linux-kernel@vger.kernel.org
|
||||
S: Maintained
|
||||
F: Documentation/ABI/testing/sysfs-devices-hisi_ptt
|
||||
F: Documentation/trace/hisi-ptt.rst
|
||||
F: drivers/hwtracing/ptt/
|
||||
|
||||
HISILICON QM DRIVER
|
||||
M: Weili Qian <qianweili@huawei.com>
|
||||
M: Zhou Wang <wangzhou1@hisilicon.com>
|
||||
|
|
|
@ -1021,6 +1021,7 @@
|
|||
#define SYS_MPIDR_SAFE_VAL (BIT(31))
|
||||
|
||||
#define TRFCR_ELx_TS_SHIFT 5
|
||||
#define TRFCR_ELx_TS_MASK ((0x3UL) << TRFCR_ELx_TS_SHIFT)
|
||||
#define TRFCR_ELx_TS_VIRTUAL ((0x1UL) << TRFCR_ELx_TS_SHIFT)
|
||||
#define TRFCR_ELx_TS_GUEST_PHYSICAL ((0x2UL) << TRFCR_ELx_TS_SHIFT)
|
||||
#define TRFCR_ELx_TS_PHYSICAL ((0x3UL) << TRFCR_ELx_TS_SHIFT)
|
||||
|
|
|
@ -175,6 +175,7 @@ obj-$(CONFIG_USB4) += thunderbolt/
|
|||
obj-$(CONFIG_CORESIGHT) += hwtracing/coresight/
|
||||
obj-y += hwtracing/intel_th/
|
||||
obj-$(CONFIG_STM) += hwtracing/stm/
|
||||
obj-$(CONFIG_HISI_PTT) += hwtracing/ptt/
|
||||
obj-y += android/
|
||||
obj-$(CONFIG_NVMEM) += nvmem/
|
||||
obj-$(CONFIG_FPGA) += fpga/
|
||||
|
|
|
@ -5,4 +5,6 @@ source "drivers/hwtracing/stm/Kconfig"
|
|||
|
||||
source "drivers/hwtracing/intel_th/Kconfig"
|
||||
|
||||
source "drivers/hwtracing/ptt/Kconfig"
|
||||
|
||||
endmenu
|
||||
|
|
|
@ -193,10 +193,10 @@ config CORESIGHT_TRBE
|
|||
depends on ARM64 && CORESIGHT_SOURCE_ETM4X
|
||||
help
|
||||
This driver provides support for percpu Trace Buffer Extension (TRBE).
|
||||
TRBE always needs to be used along with it's corresponding percpu ETE
|
||||
TRBE always needs to be used along with its corresponding percpu ETE
|
||||
component. ETE generates trace data which is then captured with TRBE.
|
||||
Unlike traditional sink devices, TRBE is a CPU feature accessible via
|
||||
system registers. But it's explicit dependency with trace unit (ETE)
|
||||
system registers. But its explicit dependency with trace unit (ETE)
|
||||
requires it to be plugged in as a coresight sink device.
|
||||
|
||||
To compile this driver as a module, choose M here: the module will be
|
||||
|
|
|
@ -365,26 +365,15 @@ static const struct etr_buf_operations etr_catu_buf_ops = {
|
|||
.get_data = catu_get_data_etr_buf,
|
||||
};
|
||||
|
||||
coresight_simple_reg32(struct catu_drvdata, devid, CORESIGHT_DEVID);
|
||||
coresight_simple_reg32(struct catu_drvdata, control, CATU_CONTROL);
|
||||
coresight_simple_reg32(struct catu_drvdata, status, CATU_STATUS);
|
||||
coresight_simple_reg32(struct catu_drvdata, mode, CATU_MODE);
|
||||
coresight_simple_reg32(struct catu_drvdata, axictrl, CATU_AXICTRL);
|
||||
coresight_simple_reg32(struct catu_drvdata, irqen, CATU_IRQEN);
|
||||
coresight_simple_reg64(struct catu_drvdata, sladdr,
|
||||
CATU_SLADDRLO, CATU_SLADDRHI);
|
||||
coresight_simple_reg64(struct catu_drvdata, inaddr,
|
||||
CATU_INADDRLO, CATU_INADDRHI);
|
||||
|
||||
static struct attribute *catu_mgmt_attrs[] = {
|
||||
&dev_attr_devid.attr,
|
||||
&dev_attr_control.attr,
|
||||
&dev_attr_status.attr,
|
||||
&dev_attr_mode.attr,
|
||||
&dev_attr_axictrl.attr,
|
||||
&dev_attr_irqen.attr,
|
||||
&dev_attr_sladdr.attr,
|
||||
&dev_attr_inaddr.attr,
|
||||
coresight_simple_reg32(devid, CORESIGHT_DEVID),
|
||||
coresight_simple_reg32(control, CATU_CONTROL),
|
||||
coresight_simple_reg32(status, CATU_STATUS),
|
||||
coresight_simple_reg32(mode, CATU_MODE),
|
||||
coresight_simple_reg32(axictrl, CATU_AXICTRL),
|
||||
coresight_simple_reg32(irqen, CATU_IRQEN),
|
||||
coresight_simple_reg64(sladdr, CATU_SLADDRLO, CATU_SLADDRHI),
|
||||
coresight_simple_reg64(inaddr, CATU_INADDRLO, CATU_INADDRHI),
|
||||
NULL,
|
||||
};
|
||||
|
||||
|
|
|
@ -70,24 +70,24 @@ struct catu_drvdata {
|
|||
static inline u32 \
|
||||
catu_read_##name(struct catu_drvdata *drvdata) \
|
||||
{ \
|
||||
return coresight_read_reg_pair(drvdata->base, offset, -1); \
|
||||
return csdev_access_relaxed_read32(&drvdata->csdev->access, offset); \
|
||||
} \
|
||||
static inline void \
|
||||
catu_write_##name(struct catu_drvdata *drvdata, u32 val) \
|
||||
{ \
|
||||
coresight_write_reg_pair(drvdata->base, val, offset, -1); \
|
||||
csdev_access_relaxed_write32(&drvdata->csdev->access, val, offset); \
|
||||
}
|
||||
|
||||
#define CATU_REG_PAIR(name, lo_off, hi_off) \
|
||||
static inline u64 \
|
||||
catu_read_##name(struct catu_drvdata *drvdata) \
|
||||
{ \
|
||||
return coresight_read_reg_pair(drvdata->base, lo_off, hi_off); \
|
||||
return csdev_access_relaxed_read_pair(&drvdata->csdev->access, lo_off, hi_off); \
|
||||
} \
|
||||
static inline void \
|
||||
catu_write_##name(struct catu_drvdata *drvdata, u64 val) \
|
||||
{ \
|
||||
coresight_write_reg_pair(drvdata->base, val, lo_off, hi_off); \
|
||||
csdev_access_relaxed_write_pair(&drvdata->csdev->access, val, lo_off, hi_off); \
|
||||
}
|
||||
|
||||
CATU_REG32(control, CATU_CONTROL);
|
||||
|
|
|
@ -60,6 +60,34 @@ EXPORT_SYMBOL_GPL(coresight_barrier_pkt);
|
|||
|
||||
static const struct cti_assoc_op *cti_assoc_ops;
|
||||
|
||||
ssize_t coresight_simple_show_pair(struct device *_dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct coresight_device *csdev = container_of(_dev, struct coresight_device, dev);
|
||||
struct cs_pair_attribute *cs_attr = container_of(attr, struct cs_pair_attribute, attr);
|
||||
u64 val;
|
||||
|
||||
pm_runtime_get_sync(_dev->parent);
|
||||
val = csdev_access_relaxed_read_pair(&csdev->access, cs_attr->lo_off, cs_attr->hi_off);
|
||||
pm_runtime_put_sync(_dev->parent);
|
||||
return sysfs_emit(buf, "0x%llx\n", val);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(coresight_simple_show_pair);
|
||||
|
||||
ssize_t coresight_simple_show32(struct device *_dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct coresight_device *csdev = container_of(_dev, struct coresight_device, dev);
|
||||
struct cs_off_attribute *cs_attr = container_of(attr, struct cs_off_attribute, attr);
|
||||
u64 val;
|
||||
|
||||
pm_runtime_get_sync(_dev->parent);
|
||||
val = csdev_access_relaxed_read32(&csdev->access, cs_attr->off);
|
||||
pm_runtime_put_sync(_dev->parent);
|
||||
return sysfs_emit(buf, "0x%llx\n", val);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(coresight_simple_show32);
|
||||
|
||||
void coresight_set_cti_ops(const struct cti_assoc_op *cti_op)
|
||||
{
|
||||
cti_assoc_ops = cti_op;
|
||||
|
|
|
@ -163,48 +163,82 @@ static struct attribute *coresight_cti_attrs[] = {
|
|||
|
||||
/* register based attributes */
|
||||
|
||||
/* macro to access RO registers with power check only (no enable check). */
|
||||
#define coresight_cti_reg(name, offset) \
|
||||
static ssize_t name##_show(struct device *dev, \
|
||||
struct device_attribute *attr, char *buf) \
|
||||
{ \
|
||||
struct cti_drvdata *drvdata = dev_get_drvdata(dev->parent); \
|
||||
u32 val = 0; \
|
||||
pm_runtime_get_sync(dev->parent); \
|
||||
spin_lock(&drvdata->spinlock); \
|
||||
if (drvdata->config.hw_powered) \
|
||||
val = readl_relaxed(drvdata->base + offset); \
|
||||
spin_unlock(&drvdata->spinlock); \
|
||||
pm_runtime_put_sync(dev->parent); \
|
||||
return sprintf(buf, "0x%x\n", val); \
|
||||
} \
|
||||
static DEVICE_ATTR_RO(name)
|
||||
/* Read registers with power check only (no enable check). */
|
||||
static ssize_t coresight_cti_reg_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct cti_drvdata *drvdata = dev_get_drvdata(dev->parent);
|
||||
struct cs_off_attribute *cti_attr = container_of(attr, struct cs_off_attribute, attr);
|
||||
u32 val = 0;
|
||||
|
||||
pm_runtime_get_sync(dev->parent);
|
||||
spin_lock(&drvdata->spinlock);
|
||||
if (drvdata->config.hw_powered)
|
||||
val = readl_relaxed(drvdata->base + cti_attr->off);
|
||||
spin_unlock(&drvdata->spinlock);
|
||||
pm_runtime_put_sync(dev->parent);
|
||||
return sysfs_emit(buf, "0x%x\n", val);
|
||||
}
|
||||
|
||||
/* Write registers with power check only (no enable check). */
|
||||
static __maybe_unused ssize_t coresight_cti_reg_store(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
const char *buf, size_t size)
|
||||
{
|
||||
struct cti_drvdata *drvdata = dev_get_drvdata(dev->parent);
|
||||
struct cs_off_attribute *cti_attr = container_of(attr, struct cs_off_attribute, attr);
|
||||
unsigned long val = 0;
|
||||
|
||||
if (kstrtoul(buf, 0, &val))
|
||||
return -EINVAL;
|
||||
|
||||
pm_runtime_get_sync(dev->parent);
|
||||
spin_lock(&drvdata->spinlock);
|
||||
if (drvdata->config.hw_powered)
|
||||
cti_write_single_reg(drvdata, cti_attr->off, val);
|
||||
spin_unlock(&drvdata->spinlock);
|
||||
pm_runtime_put_sync(dev->parent);
|
||||
return size;
|
||||
}
|
||||
|
||||
#define coresight_cti_reg(name, offset) \
|
||||
(&((struct cs_off_attribute[]) { \
|
||||
{ \
|
||||
__ATTR(name, 0444, coresight_cti_reg_show, NULL), \
|
||||
offset \
|
||||
} \
|
||||
})[0].attr.attr)
|
||||
|
||||
#define coresight_cti_reg_rw(name, offset) \
|
||||
(&((struct cs_off_attribute[]) { \
|
||||
{ \
|
||||
__ATTR(name, 0644, coresight_cti_reg_show, \
|
||||
coresight_cti_reg_store), \
|
||||
offset \
|
||||
} \
|
||||
})[0].attr.attr)
|
||||
|
||||
#define coresight_cti_reg_wo(name, offset) \
|
||||
(&((struct cs_off_attribute[]) { \
|
||||
{ \
|
||||
__ATTR(name, 0200, NULL, coresight_cti_reg_store), \
|
||||
offset \
|
||||
} \
|
||||
})[0].attr.attr)
|
||||
|
||||
/* coresight management registers */
|
||||
coresight_cti_reg(devaff0, CTIDEVAFF0);
|
||||
coresight_cti_reg(devaff1, CTIDEVAFF1);
|
||||
coresight_cti_reg(authstatus, CORESIGHT_AUTHSTATUS);
|
||||
coresight_cti_reg(devarch, CORESIGHT_DEVARCH);
|
||||
coresight_cti_reg(devid, CORESIGHT_DEVID);
|
||||
coresight_cti_reg(devtype, CORESIGHT_DEVTYPE);
|
||||
coresight_cti_reg(pidr0, CORESIGHT_PERIPHIDR0);
|
||||
coresight_cti_reg(pidr1, CORESIGHT_PERIPHIDR1);
|
||||
coresight_cti_reg(pidr2, CORESIGHT_PERIPHIDR2);
|
||||
coresight_cti_reg(pidr3, CORESIGHT_PERIPHIDR3);
|
||||
coresight_cti_reg(pidr4, CORESIGHT_PERIPHIDR4);
|
||||
|
||||
static struct attribute *coresight_cti_mgmt_attrs[] = {
|
||||
&dev_attr_devaff0.attr,
|
||||
&dev_attr_devaff1.attr,
|
||||
&dev_attr_authstatus.attr,
|
||||
&dev_attr_devarch.attr,
|
||||
&dev_attr_devid.attr,
|
||||
&dev_attr_devtype.attr,
|
||||
&dev_attr_pidr0.attr,
|
||||
&dev_attr_pidr1.attr,
|
||||
&dev_attr_pidr2.attr,
|
||||
&dev_attr_pidr3.attr,
|
||||
&dev_attr_pidr4.attr,
|
||||
coresight_cti_reg(devaff0, CTIDEVAFF0),
|
||||
coresight_cti_reg(devaff1, CTIDEVAFF1),
|
||||
coresight_cti_reg(authstatus, CORESIGHT_AUTHSTATUS),
|
||||
coresight_cti_reg(devarch, CORESIGHT_DEVARCH),
|
||||
coresight_cti_reg(devid, CORESIGHT_DEVID),
|
||||
coresight_cti_reg(devtype, CORESIGHT_DEVTYPE),
|
||||
coresight_cti_reg(pidr0, CORESIGHT_PERIPHIDR0),
|
||||
coresight_cti_reg(pidr1, CORESIGHT_PERIPHIDR1),
|
||||
coresight_cti_reg(pidr2, CORESIGHT_PERIPHIDR2),
|
||||
coresight_cti_reg(pidr3, CORESIGHT_PERIPHIDR3),
|
||||
coresight_cti_reg(pidr4, CORESIGHT_PERIPHIDR4),
|
||||
NULL,
|
||||
};
|
||||
|
||||
|
@ -454,86 +488,11 @@ static ssize_t apppulse_store(struct device *dev,
|
|||
}
|
||||
static DEVICE_ATTR_WO(apppulse);
|
||||
|
||||
coresight_cti_reg(triginstatus, CTITRIGINSTATUS);
|
||||
coresight_cti_reg(trigoutstatus, CTITRIGOUTSTATUS);
|
||||
coresight_cti_reg(chinstatus, CTICHINSTATUS);
|
||||
coresight_cti_reg(choutstatus, CTICHOUTSTATUS);
|
||||
|
||||
/*
|
||||
* Define CONFIG_CORESIGHT_CTI_INTEGRATION_REGS to enable the access to the
|
||||
* integration control registers. Normally only used to investigate connection
|
||||
* data.
|
||||
*/
|
||||
#ifdef CONFIG_CORESIGHT_CTI_INTEGRATION_REGS
|
||||
|
||||
/* macro to access RW registers with power check only (no enable check). */
|
||||
#define coresight_cti_reg_rw(name, offset) \
|
||||
static ssize_t name##_show(struct device *dev, \
|
||||
struct device_attribute *attr, char *buf) \
|
||||
{ \
|
||||
struct cti_drvdata *drvdata = dev_get_drvdata(dev->parent); \
|
||||
u32 val = 0; \
|
||||
pm_runtime_get_sync(dev->parent); \
|
||||
spin_lock(&drvdata->spinlock); \
|
||||
if (drvdata->config.hw_powered) \
|
||||
val = readl_relaxed(drvdata->base + offset); \
|
||||
spin_unlock(&drvdata->spinlock); \
|
||||
pm_runtime_put_sync(dev->parent); \
|
||||
return sprintf(buf, "0x%x\n", val); \
|
||||
} \
|
||||
\
|
||||
static ssize_t name##_store(struct device *dev, \
|
||||
struct device_attribute *attr, \
|
||||
const char *buf, size_t size) \
|
||||
{ \
|
||||
struct cti_drvdata *drvdata = dev_get_drvdata(dev->parent); \
|
||||
unsigned long val = 0; \
|
||||
if (kstrtoul(buf, 0, &val)) \
|
||||
return -EINVAL; \
|
||||
\
|
||||
pm_runtime_get_sync(dev->parent); \
|
||||
spin_lock(&drvdata->spinlock); \
|
||||
if (drvdata->config.hw_powered) \
|
||||
cti_write_single_reg(drvdata, offset, val); \
|
||||
spin_unlock(&drvdata->spinlock); \
|
||||
pm_runtime_put_sync(dev->parent); \
|
||||
return size; \
|
||||
} \
|
||||
static DEVICE_ATTR_RW(name)
|
||||
|
||||
/* macro to access WO registers with power check only (no enable check). */
|
||||
#define coresight_cti_reg_wo(name, offset) \
|
||||
static ssize_t name##_store(struct device *dev, \
|
||||
struct device_attribute *attr, \
|
||||
const char *buf, size_t size) \
|
||||
{ \
|
||||
struct cti_drvdata *drvdata = dev_get_drvdata(dev->parent); \
|
||||
unsigned long val = 0; \
|
||||
if (kstrtoul(buf, 0, &val)) \
|
||||
return -EINVAL; \
|
||||
\
|
||||
pm_runtime_get_sync(dev->parent); \
|
||||
spin_lock(&drvdata->spinlock); \
|
||||
if (drvdata->config.hw_powered) \
|
||||
cti_write_single_reg(drvdata, offset, val); \
|
||||
spin_unlock(&drvdata->spinlock); \
|
||||
pm_runtime_put_sync(dev->parent); \
|
||||
return size; \
|
||||
} \
|
||||
static DEVICE_ATTR_WO(name)
|
||||
|
||||
coresight_cti_reg_rw(itchout, ITCHOUT);
|
||||
coresight_cti_reg_rw(ittrigout, ITTRIGOUT);
|
||||
coresight_cti_reg_rw(itctrl, CORESIGHT_ITCTRL);
|
||||
coresight_cti_reg_wo(itchinack, ITCHINACK);
|
||||
coresight_cti_reg_wo(ittriginack, ITTRIGINACK);
|
||||
coresight_cti_reg(ittrigin, ITTRIGIN);
|
||||
coresight_cti_reg(itchin, ITCHIN);
|
||||
coresight_cti_reg(itchoutack, ITCHOUTACK);
|
||||
coresight_cti_reg(ittrigoutack, ITTRIGOUTACK);
|
||||
|
||||
#endif /* CORESIGHT_CTI_INTEGRATION_REGS */
|
||||
|
||||
static struct attribute *coresight_cti_regs_attrs[] = {
|
||||
&dev_attr_inout_sel.attr,
|
||||
&dev_attr_inen.attr,
|
||||
|
@ -544,20 +503,20 @@ static struct attribute *coresight_cti_regs_attrs[] = {
|
|||
&dev_attr_appset.attr,
|
||||
&dev_attr_appclear.attr,
|
||||
&dev_attr_apppulse.attr,
|
||||
&dev_attr_triginstatus.attr,
|
||||
&dev_attr_trigoutstatus.attr,
|
||||
&dev_attr_chinstatus.attr,
|
||||
&dev_attr_choutstatus.attr,
|
||||
coresight_cti_reg(triginstatus, CTITRIGINSTATUS),
|
||||
coresight_cti_reg(trigoutstatus, CTITRIGOUTSTATUS),
|
||||
coresight_cti_reg(chinstatus, CTICHINSTATUS),
|
||||
coresight_cti_reg(choutstatus, CTICHOUTSTATUS),
|
||||
#ifdef CONFIG_CORESIGHT_CTI_INTEGRATION_REGS
|
||||
&dev_attr_itctrl.attr,
|
||||
&dev_attr_ittrigin.attr,
|
||||
&dev_attr_itchin.attr,
|
||||
&dev_attr_ittrigout.attr,
|
||||
&dev_attr_itchout.attr,
|
||||
&dev_attr_itchoutack.attr,
|
||||
&dev_attr_ittrigoutack.attr,
|
||||
&dev_attr_ittriginack.attr,
|
||||
&dev_attr_itchinack.attr,
|
||||
coresight_cti_reg_rw(itctrl, CORESIGHT_ITCTRL),
|
||||
coresight_cti_reg(ittrigin, ITTRIGIN),
|
||||
coresight_cti_reg(itchin, ITCHIN),
|
||||
coresight_cti_reg_rw(ittrigout, ITTRIGOUT),
|
||||
coresight_cti_reg_rw(itchout, ITCHOUT),
|
||||
coresight_cti_reg(itchoutack, ITCHOUTACK),
|
||||
coresight_cti_reg(ittrigoutack, ITTRIGOUTACK),
|
||||
coresight_cti_reg_wo(ittriginack, ITTRIGINACK),
|
||||
coresight_cti_reg_wo(itchinack, ITCHINACK),
|
||||
#endif
|
||||
NULL,
|
||||
};
|
||||
|
|
|
@ -655,27 +655,15 @@ static const struct file_operations etb_fops = {
|
|||
.llseek = no_llseek,
|
||||
};
|
||||
|
||||
#define coresight_etb10_reg(name, offset) \
|
||||
coresight_simple_reg32(struct etb_drvdata, name, offset)
|
||||
|
||||
coresight_etb10_reg(rdp, ETB_RAM_DEPTH_REG);
|
||||
coresight_etb10_reg(sts, ETB_STATUS_REG);
|
||||
coresight_etb10_reg(rrp, ETB_RAM_READ_POINTER);
|
||||
coresight_etb10_reg(rwp, ETB_RAM_WRITE_POINTER);
|
||||
coresight_etb10_reg(trg, ETB_TRG);
|
||||
coresight_etb10_reg(ctl, ETB_CTL_REG);
|
||||
coresight_etb10_reg(ffsr, ETB_FFSR);
|
||||
coresight_etb10_reg(ffcr, ETB_FFCR);
|
||||
|
||||
static struct attribute *coresight_etb_mgmt_attrs[] = {
|
||||
&dev_attr_rdp.attr,
|
||||
&dev_attr_sts.attr,
|
||||
&dev_attr_rrp.attr,
|
||||
&dev_attr_rwp.attr,
|
||||
&dev_attr_trg.attr,
|
||||
&dev_attr_ctl.attr,
|
||||
&dev_attr_ffsr.attr,
|
||||
&dev_attr_ffcr.attr,
|
||||
coresight_simple_reg32(rdp, ETB_RAM_DEPTH_REG),
|
||||
coresight_simple_reg32(sts, ETB_STATUS_REG),
|
||||
coresight_simple_reg32(rrp, ETB_RAM_READ_POINTER),
|
||||
coresight_simple_reg32(rwp, ETB_RAM_WRITE_POINTER),
|
||||
coresight_simple_reg32(trg, ETB_TRG),
|
||||
coresight_simple_reg32(ctl, ETB_CTL_REG),
|
||||
coresight_simple_reg32(ffsr, ETB_FFSR),
|
||||
coresight_simple_reg32(ffcr, ETB_FFCR),
|
||||
NULL,
|
||||
};
|
||||
|
||||
|
|
|
@ -1252,31 +1252,17 @@ static struct attribute *coresight_etm_attrs[] = {
|
|||
NULL,
|
||||
};
|
||||
|
||||
#define coresight_etm3x_reg(name, offset) \
|
||||
coresight_simple_reg32(struct etm_drvdata, name, offset)
|
||||
|
||||
coresight_etm3x_reg(etmccr, ETMCCR);
|
||||
coresight_etm3x_reg(etmccer, ETMCCER);
|
||||
coresight_etm3x_reg(etmscr, ETMSCR);
|
||||
coresight_etm3x_reg(etmidr, ETMIDR);
|
||||
coresight_etm3x_reg(etmcr, ETMCR);
|
||||
coresight_etm3x_reg(etmtraceidr, ETMTRACEIDR);
|
||||
coresight_etm3x_reg(etmteevr, ETMTEEVR);
|
||||
coresight_etm3x_reg(etmtssvr, ETMTSSCR);
|
||||
coresight_etm3x_reg(etmtecr1, ETMTECR1);
|
||||
coresight_etm3x_reg(etmtecr2, ETMTECR2);
|
||||
|
||||
static struct attribute *coresight_etm_mgmt_attrs[] = {
|
||||
&dev_attr_etmccr.attr,
|
||||
&dev_attr_etmccer.attr,
|
||||
&dev_attr_etmscr.attr,
|
||||
&dev_attr_etmidr.attr,
|
||||
&dev_attr_etmcr.attr,
|
||||
&dev_attr_etmtraceidr.attr,
|
||||
&dev_attr_etmteevr.attr,
|
||||
&dev_attr_etmtssvr.attr,
|
||||
&dev_attr_etmtecr1.attr,
|
||||
&dev_attr_etmtecr2.attr,
|
||||
coresight_simple_reg32(etmccr, ETMCCR),
|
||||
coresight_simple_reg32(etmccer, ETMCCER),
|
||||
coresight_simple_reg32(etmscr, ETMSCR),
|
||||
coresight_simple_reg32(etmidr, ETMIDR),
|
||||
coresight_simple_reg32(etmcr, ETMCR),
|
||||
coresight_simple_reg32(etmtraceidr, ETMTRACEIDR),
|
||||
coresight_simple_reg32(etmteevr, ETMTEEVR),
|
||||
coresight_simple_reg32(etmtssvr, ETMTSSCR),
|
||||
coresight_simple_reg32(etmtecr1, ETMTECR1),
|
||||
coresight_simple_reg32(etmtecr2, ETMTECR2),
|
||||
NULL,
|
||||
};
|
||||
|
||||
|
|
|
@ -2306,6 +2306,34 @@ static ssize_t cpu_show(struct device *dev,
|
|||
}
|
||||
static DEVICE_ATTR_RO(cpu);
|
||||
|
||||
static ssize_t ts_source_show(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
int val;
|
||||
struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
|
||||
|
||||
if (!drvdata->trfcr) {
|
||||
val = -1;
|
||||
goto out;
|
||||
}
|
||||
|
||||
switch (drvdata->trfcr & TRFCR_ELx_TS_MASK) {
|
||||
case TRFCR_ELx_TS_VIRTUAL:
|
||||
case TRFCR_ELx_TS_GUEST_PHYSICAL:
|
||||
case TRFCR_ELx_TS_PHYSICAL:
|
||||
val = FIELD_GET(TRFCR_ELx_TS_MASK, drvdata->trfcr);
|
||||
break;
|
||||
default:
|
||||
val = -1;
|
||||
break;
|
||||
}
|
||||
|
||||
out:
|
||||
return sysfs_emit(buf, "%d\n", val);
|
||||
}
|
||||
static DEVICE_ATTR_RO(ts_source);
|
||||
|
||||
static struct attribute *coresight_etmv4_attrs[] = {
|
||||
&dev_attr_nr_pe_cmp.attr,
|
||||
&dev_attr_nr_addr_cmp.attr,
|
||||
|
@ -2360,6 +2388,7 @@ static struct attribute *coresight_etmv4_attrs[] = {
|
|||
&dev_attr_vmid_val.attr,
|
||||
&dev_attr_vmid_masks.attr,
|
||||
&dev_attr_cpu.attr,
|
||||
&dev_attr_ts_source.attr,
|
||||
NULL,
|
||||
};
|
||||
|
||||
|
|
|
@ -39,32 +39,37 @@
|
|||
|
||||
#define ETM_MODE_EXCL_KERN BIT(30)
|
||||
#define ETM_MODE_EXCL_USER BIT(31)
|
||||
struct cs_pair_attribute {
|
||||
struct device_attribute attr;
|
||||
u32 lo_off;
|
||||
u32 hi_off;
|
||||
};
|
||||
|
||||
typedef u32 (*coresight_read_fn)(const struct device *, u32 offset);
|
||||
#define __coresight_simple_func(type, func, name, lo_off, hi_off) \
|
||||
static ssize_t name##_show(struct device *_dev, \
|
||||
struct device_attribute *attr, char *buf) \
|
||||
{ \
|
||||
type *drvdata = dev_get_drvdata(_dev->parent); \
|
||||
coresight_read_fn fn = func; \
|
||||
u64 val; \
|
||||
pm_runtime_get_sync(_dev->parent); \
|
||||
if (fn) \
|
||||
val = (u64)fn(_dev->parent, lo_off); \
|
||||
else \
|
||||
val = coresight_read_reg_pair(drvdata->base, \
|
||||
lo_off, hi_off); \
|
||||
pm_runtime_put_sync(_dev->parent); \
|
||||
return scnprintf(buf, PAGE_SIZE, "0x%llx\n", val); \
|
||||
} \
|
||||
static DEVICE_ATTR_RO(name)
|
||||
struct cs_off_attribute {
|
||||
struct device_attribute attr;
|
||||
u32 off;
|
||||
};
|
||||
|
||||
#define coresight_simple_func(type, func, name, offset) \
|
||||
__coresight_simple_func(type, func, name, offset, -1)
|
||||
#define coresight_simple_reg32(type, name, offset) \
|
||||
__coresight_simple_func(type, NULL, name, offset, -1)
|
||||
#define coresight_simple_reg64(type, name, lo_off, hi_off) \
|
||||
__coresight_simple_func(type, NULL, name, lo_off, hi_off)
|
||||
extern ssize_t coresight_simple_show32(struct device *_dev,
|
||||
struct device_attribute *attr, char *buf);
|
||||
extern ssize_t coresight_simple_show_pair(struct device *_dev,
|
||||
struct device_attribute *attr, char *buf);
|
||||
|
||||
#define coresight_simple_reg32(name, offset) \
|
||||
(&((struct cs_off_attribute[]) { \
|
||||
{ \
|
||||
__ATTR(name, 0444, coresight_simple_show32, NULL), \
|
||||
offset \
|
||||
} \
|
||||
})[0].attr.attr)
|
||||
|
||||
#define coresight_simple_reg64(name, lo_off, hi_off) \
|
||||
(&((struct cs_pair_attribute[]) { \
|
||||
{ \
|
||||
__ATTR(name, 0444, coresight_simple_show_pair, NULL), \
|
||||
lo_off, hi_off \
|
||||
} \
|
||||
})[0].attr.attr)
|
||||
|
||||
extern const u32 coresight_barrier_pkt[4];
|
||||
#define CORESIGHT_BARRIER_PKT_SIZE (sizeof(coresight_barrier_pkt))
|
||||
|
@ -127,25 +132,6 @@ static inline void CS_UNLOCK(void __iomem *addr)
|
|||
} while (0);
|
||||
}
|
||||
|
||||
static inline u64
|
||||
coresight_read_reg_pair(void __iomem *addr, s32 lo_offset, s32 hi_offset)
|
||||
{
|
||||
u64 val;
|
||||
|
||||
val = readl_relaxed(addr + lo_offset);
|
||||
val |= (hi_offset < 0) ? 0 :
|
||||
(u64)readl_relaxed(addr + hi_offset) << 32;
|
||||
return val;
|
||||
}
|
||||
|
||||
static inline void coresight_write_reg_pair(void __iomem *addr, u64 val,
|
||||
s32 lo_offset, s32 hi_offset)
|
||||
{
|
||||
writel_relaxed((u32)val, addr + lo_offset);
|
||||
if (hi_offset >= 0)
|
||||
writel_relaxed((u32)(val >> 32), addr + hi_offset);
|
||||
}
|
||||
|
||||
void coresight_disable_path(struct list_head *path);
|
||||
int coresight_enable_path(struct list_head *path, u32 mode, void *sink_data);
|
||||
struct coresight_device *coresight_get_sink(struct list_head *path);
|
||||
|
|
|
@ -196,15 +196,9 @@ static const struct coresight_ops replicator_cs_ops = {
|
|||
.link_ops = &replicator_link_ops,
|
||||
};
|
||||
|
||||
#define coresight_replicator_reg(name, offset) \
|
||||
coresight_simple_reg32(struct replicator_drvdata, name, offset)
|
||||
|
||||
coresight_replicator_reg(idfilter0, REPLICATOR_IDFILTER0);
|
||||
coresight_replicator_reg(idfilter1, REPLICATOR_IDFILTER1);
|
||||
|
||||
static struct attribute *replicator_mgmt_attrs[] = {
|
||||
&dev_attr_idfilter0.attr,
|
||||
&dev_attr_idfilter1.attr,
|
||||
coresight_simple_reg32(idfilter0, REPLICATOR_IDFILTER0),
|
||||
coresight_simple_reg32(idfilter1, REPLICATOR_IDFILTER1),
|
||||
NULL,
|
||||
};
|
||||
|
||||
|
|
|
@ -634,22 +634,6 @@ static ssize_t traceid_store(struct device *dev,
|
|||
}
|
||||
static DEVICE_ATTR_RW(traceid);
|
||||
|
||||
#define coresight_stm_reg(name, offset) \
|
||||
coresight_simple_reg32(struct stm_drvdata, name, offset)
|
||||
|
||||
coresight_stm_reg(tcsr, STMTCSR);
|
||||
coresight_stm_reg(tsfreqr, STMTSFREQR);
|
||||
coresight_stm_reg(syncr, STMSYNCR);
|
||||
coresight_stm_reg(sper, STMSPER);
|
||||
coresight_stm_reg(spter, STMSPTER);
|
||||
coresight_stm_reg(privmaskr, STMPRIVMASKR);
|
||||
coresight_stm_reg(spscr, STMSPSCR);
|
||||
coresight_stm_reg(spmscr, STMSPMSCR);
|
||||
coresight_stm_reg(spfeat1r, STMSPFEAT1R);
|
||||
coresight_stm_reg(spfeat2r, STMSPFEAT2R);
|
||||
coresight_stm_reg(spfeat3r, STMSPFEAT3R);
|
||||
coresight_stm_reg(devid, CORESIGHT_DEVID);
|
||||
|
||||
static struct attribute *coresight_stm_attrs[] = {
|
||||
&dev_attr_hwevent_enable.attr,
|
||||
&dev_attr_hwevent_select.attr,
|
||||
|
@ -660,18 +644,18 @@ static struct attribute *coresight_stm_attrs[] = {
|
|||
};
|
||||
|
||||
static struct attribute *coresight_stm_mgmt_attrs[] = {
|
||||
&dev_attr_tcsr.attr,
|
||||
&dev_attr_tsfreqr.attr,
|
||||
&dev_attr_syncr.attr,
|
||||
&dev_attr_sper.attr,
|
||||
&dev_attr_spter.attr,
|
||||
&dev_attr_privmaskr.attr,
|
||||
&dev_attr_spscr.attr,
|
||||
&dev_attr_spmscr.attr,
|
||||
&dev_attr_spfeat1r.attr,
|
||||
&dev_attr_spfeat2r.attr,
|
||||
&dev_attr_spfeat3r.attr,
|
||||
&dev_attr_devid.attr,
|
||||
coresight_simple_reg32(tcsr, STMTCSR),
|
||||
coresight_simple_reg32(tsfreqr, STMTSFREQR),
|
||||
coresight_simple_reg32(syncr, STMSYNCR),
|
||||
coresight_simple_reg32(sper, STMSPER),
|
||||
coresight_simple_reg32(spter, STMSPTER),
|
||||
coresight_simple_reg32(privmaskr, STMPRIVMASKR),
|
||||
coresight_simple_reg32(spscr, STMSPSCR),
|
||||
coresight_simple_reg32(spmscr, STMSPMSCR),
|
||||
coresight_simple_reg32(spfeat1r, STMSPFEAT1R),
|
||||
coresight_simple_reg32(spfeat2r, STMSPFEAT2R),
|
||||
coresight_simple_reg32(spfeat3r, STMSPFEAT3R),
|
||||
coresight_simple_reg32(devid, CORESIGHT_DEVID),
|
||||
NULL,
|
||||
};
|
||||
|
||||
|
|
|
@ -251,41 +251,21 @@ static enum tmc_mem_intf_width tmc_get_memwidth(u32 devid)
|
|||
return memwidth;
|
||||
}
|
||||
|
||||
#define coresight_tmc_reg(name, offset) \
|
||||
coresight_simple_reg32(struct tmc_drvdata, name, offset)
|
||||
#define coresight_tmc_reg64(name, lo_off, hi_off) \
|
||||
coresight_simple_reg64(struct tmc_drvdata, name, lo_off, hi_off)
|
||||
|
||||
coresight_tmc_reg(rsz, TMC_RSZ);
|
||||
coresight_tmc_reg(sts, TMC_STS);
|
||||
coresight_tmc_reg(trg, TMC_TRG);
|
||||
coresight_tmc_reg(ctl, TMC_CTL);
|
||||
coresight_tmc_reg(ffsr, TMC_FFSR);
|
||||
coresight_tmc_reg(ffcr, TMC_FFCR);
|
||||
coresight_tmc_reg(mode, TMC_MODE);
|
||||
coresight_tmc_reg(pscr, TMC_PSCR);
|
||||
coresight_tmc_reg(axictl, TMC_AXICTL);
|
||||
coresight_tmc_reg(authstatus, TMC_AUTHSTATUS);
|
||||
coresight_tmc_reg(devid, CORESIGHT_DEVID);
|
||||
coresight_tmc_reg64(rrp, TMC_RRP, TMC_RRPHI);
|
||||
coresight_tmc_reg64(rwp, TMC_RWP, TMC_RWPHI);
|
||||
coresight_tmc_reg64(dba, TMC_DBALO, TMC_DBAHI);
|
||||
|
||||
static struct attribute *coresight_tmc_mgmt_attrs[] = {
|
||||
&dev_attr_rsz.attr,
|
||||
&dev_attr_sts.attr,
|
||||
&dev_attr_rrp.attr,
|
||||
&dev_attr_rwp.attr,
|
||||
&dev_attr_trg.attr,
|
||||
&dev_attr_ctl.attr,
|
||||
&dev_attr_ffsr.attr,
|
||||
&dev_attr_ffcr.attr,
|
||||
&dev_attr_mode.attr,
|
||||
&dev_attr_pscr.attr,
|
||||
&dev_attr_devid.attr,
|
||||
&dev_attr_dba.attr,
|
||||
&dev_attr_axictl.attr,
|
||||
&dev_attr_authstatus.attr,
|
||||
coresight_simple_reg32(rsz, TMC_RSZ),
|
||||
coresight_simple_reg32(sts, TMC_STS),
|
||||
coresight_simple_reg64(rrp, TMC_RRP, TMC_RRPHI),
|
||||
coresight_simple_reg64(rwp, TMC_RWP, TMC_RWPHI),
|
||||
coresight_simple_reg32(trg, TMC_TRG),
|
||||
coresight_simple_reg32(ctl, TMC_CTL),
|
||||
coresight_simple_reg32(ffsr, TMC_FFSR),
|
||||
coresight_simple_reg32(ffcr, TMC_FFCR),
|
||||
coresight_simple_reg32(mode, TMC_MODE),
|
||||
coresight_simple_reg32(pscr, TMC_PSCR),
|
||||
coresight_simple_reg32(devid, CORESIGHT_DEVID),
|
||||
coresight_simple_reg64(dba, TMC_DBALO, TMC_DBAHI),
|
||||
coresight_simple_reg32(axictl, TMC_AXICTL),
|
||||
coresight_simple_reg32(authstatus, TMC_AUTHSTATUS),
|
||||
NULL,
|
||||
};
|
||||
|
||||
|
|
|
@ -282,12 +282,12 @@ ssize_t tmc_etr_get_sysfs_trace(struct tmc_drvdata *drvdata,
|
|||
static inline u64 \
|
||||
tmc_read_##name(struct tmc_drvdata *drvdata) \
|
||||
{ \
|
||||
return coresight_read_reg_pair(drvdata->base, lo_off, hi_off); \
|
||||
return csdev_access_relaxed_read_pair(&drvdata->csdev->access, lo_off, hi_off); \
|
||||
} \
|
||||
static inline void \
|
||||
tmc_write_##name(struct tmc_drvdata *drvdata, u64 val) \
|
||||
{ \
|
||||
coresight_write_reg_pair(drvdata->base, val, lo_off, hi_off); \
|
||||
csdev_access_relaxed_write_pair(&drvdata->csdev->access, val, lo_off, hi_off); \
|
||||
}
|
||||
|
||||
TMC_REG_PAIR(rrp, TMC_RRP, TMC_RRPHI)
|
||||
|
|
|
@ -0,0 +1,12 @@
|
|||
# SPDX-License-Identifier: GPL-2.0-only
|
||||
config HISI_PTT
|
||||
tristate "HiSilicon PCIe Tune and Trace Device"
|
||||
depends on ARM64 || (COMPILE_TEST && 64BIT)
|
||||
depends on PCI && HAS_DMA && HAS_IOMEM && PERF_EVENTS
|
||||
help
|
||||
HiSilicon PCIe Tune and Trace device exists as a PCIe RCiEP
|
||||
device, and it provides support for PCIe traffic tuning and
|
||||
tracing TLP headers to the memory.
|
||||
|
||||
This driver can also be built as a module. If so, the module
|
||||
will be called hisi_ptt.
|
|
@ -0,0 +1,2 @@
|
|||
# SPDX-License-Identifier: GPL-2.0
|
||||
obj-$(CONFIG_HISI_PTT) += hisi_ptt.o
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,200 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* Driver for HiSilicon PCIe tune and trace device
|
||||
*
|
||||
* Copyright (c) 2022 HiSilicon Technologies Co., Ltd.
|
||||
* Author: Yicong Yang <yangyicong@hisilicon.com>
|
||||
*/
|
||||
|
||||
#ifndef _HISI_PTT_H
|
||||
#define _HISI_PTT_H
|
||||
|
||||
#include <linux/bits.h>
|
||||
#include <linux/cpumask.h>
|
||||
#include <linux/list.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/perf_event.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/types.h>
|
||||
|
||||
#define DRV_NAME "hisi_ptt"
|
||||
|
||||
/*
|
||||
* The definition of the device registers and register fields.
|
||||
*/
|
||||
#define HISI_PTT_TUNING_CTRL 0x0000
|
||||
#define HISI_PTT_TUNING_CTRL_CODE GENMASK(15, 0)
|
||||
#define HISI_PTT_TUNING_CTRL_SUB GENMASK(23, 16)
|
||||
#define HISI_PTT_TUNING_DATA 0x0004
|
||||
#define HISI_PTT_TUNING_DATA_VAL_MASK GENMASK(15, 0)
|
||||
#define HISI_PTT_TRACE_ADDR_SIZE 0x0800
|
||||
#define HISI_PTT_TRACE_ADDR_BASE_LO_0 0x0810
|
||||
#define HISI_PTT_TRACE_ADDR_BASE_HI_0 0x0814
|
||||
#define HISI_PTT_TRACE_ADDR_STRIDE 0x8
|
||||
#define HISI_PTT_TRACE_CTRL 0x0850
|
||||
#define HISI_PTT_TRACE_CTRL_EN BIT(0)
|
||||
#define HISI_PTT_TRACE_CTRL_RST BIT(1)
|
||||
#define HISI_PTT_TRACE_CTRL_RXTX_SEL GENMASK(3, 2)
|
||||
#define HISI_PTT_TRACE_CTRL_TYPE_SEL GENMASK(7, 4)
|
||||
#define HISI_PTT_TRACE_CTRL_DATA_FORMAT BIT(14)
|
||||
#define HISI_PTT_TRACE_CTRL_FILTER_MODE BIT(15)
|
||||
#define HISI_PTT_TRACE_CTRL_TARGET_SEL GENMASK(31, 16)
|
||||
#define HISI_PTT_TRACE_INT_STAT 0x0890
|
||||
#define HISI_PTT_TRACE_INT_STAT_MASK GENMASK(3, 0)
|
||||
#define HISI_PTT_TRACE_INT_MASK 0x0894
|
||||
#define HISI_PTT_TUNING_INT_STAT 0x0898
|
||||
#define HISI_PTT_TUNING_INT_STAT_MASK BIT(0)
|
||||
#define HISI_PTT_TRACE_WR_STS 0x08a0
|
||||
#define HISI_PTT_TRACE_WR_STS_WRITE GENMASK(27, 0)
|
||||
#define HISI_PTT_TRACE_WR_STS_BUFFER GENMASK(29, 28)
|
||||
#define HISI_PTT_TRACE_STS 0x08b0
|
||||
#define HISI_PTT_TRACE_IDLE BIT(0)
|
||||
#define HISI_PTT_DEVICE_RANGE 0x0fe0
|
||||
#define HISI_PTT_DEVICE_RANGE_UPPER GENMASK(31, 16)
|
||||
#define HISI_PTT_DEVICE_RANGE_LOWER GENMASK(15, 0)
|
||||
#define HISI_PTT_LOCATION 0x0fe8
|
||||
#define HISI_PTT_CORE_ID GENMASK(15, 0)
|
||||
#define HISI_PTT_SICL_ID GENMASK(31, 16)
|
||||
|
||||
/* Parameters of PTT trace DMA part. */
|
||||
#define HISI_PTT_TRACE_DMA_IRQ 0
|
||||
#define HISI_PTT_TRACE_BUF_CNT 4
|
||||
#define HISI_PTT_TRACE_BUF_SIZE SZ_4M
|
||||
#define HISI_PTT_TRACE_TOTAL_BUF_SIZE (HISI_PTT_TRACE_BUF_SIZE * \
|
||||
HISI_PTT_TRACE_BUF_CNT)
|
||||
/* Wait time for hardware DMA to reset */
|
||||
#define HISI_PTT_RESET_TIMEOUT_US 10UL
|
||||
#define HISI_PTT_RESET_POLL_INTERVAL_US 1UL
|
||||
/* Poll timeout and interval for waiting hardware work to finish */
|
||||
#define HISI_PTT_WAIT_TUNE_TIMEOUT_US 1000000UL
|
||||
#define HISI_PTT_WAIT_TRACE_TIMEOUT_US 100UL
|
||||
#define HISI_PTT_WAIT_POLL_INTERVAL_US 10UL
|
||||
|
||||
#define HISI_PCIE_CORE_PORT_ID(devfn) ((PCI_SLOT(devfn) & 0x7) << 1)
|
||||
|
||||
/* Definition of the PMU configs */
|
||||
#define HISI_PTT_PMU_FILTER_IS_PORT BIT(19)
|
||||
#define HISI_PTT_PMU_FILTER_VAL_MASK GENMASK(15, 0)
|
||||
#define HISI_PTT_PMU_DIRECTION_MASK GENMASK(23, 20)
|
||||
#define HISI_PTT_PMU_TYPE_MASK GENMASK(31, 24)
|
||||
#define HISI_PTT_PMU_FORMAT_MASK GENMASK(35, 32)
|
||||
|
||||
/**
|
||||
* struct hisi_ptt_tune_desc - Describe tune event for PTT tune
|
||||
* @hisi_ptt: PTT device this tune event belongs to
|
||||
* @name: name of this event
|
||||
* @event_code: code of the event
|
||||
*/
|
||||
struct hisi_ptt_tune_desc {
|
||||
struct hisi_ptt *hisi_ptt;
|
||||
const char *name;
|
||||
u32 event_code;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct hisi_ptt_dma_buffer - Describe a single trace buffer of PTT trace.
|
||||
* The detail of the data format is described
|
||||
* in the documentation of PTT device.
|
||||
* @dma: DMA address of this buffer visible to the device
|
||||
* @addr: virtual address of this buffer visible to the cpu
|
||||
*/
|
||||
struct hisi_ptt_dma_buffer {
|
||||
dma_addr_t dma;
|
||||
void *addr;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct hisi_ptt_trace_ctrl - Control and status of PTT trace
|
||||
* @trace_buf: array of the trace buffers for holding the trace data.
|
||||
* the length will be HISI_PTT_TRACE_BUF_CNT.
|
||||
* @handle: perf output handle of current trace session
|
||||
* @buf_index: the index of current using trace buffer
|
||||
* @on_cpu: current tracing cpu
|
||||
* @started: current trace status, true for started
|
||||
* @is_port: whether we're tracing root port or not
|
||||
* @direction: direction of the TLP headers to trace
|
||||
* @filter: filter value for tracing the TLP headers
|
||||
* @format: format of the TLP headers to trace
|
||||
* @type: type of the TLP headers to trace
|
||||
*/
|
||||
struct hisi_ptt_trace_ctrl {
|
||||
struct hisi_ptt_dma_buffer *trace_buf;
|
||||
struct perf_output_handle handle;
|
||||
u32 buf_index;
|
||||
int on_cpu;
|
||||
bool started;
|
||||
bool is_port;
|
||||
u32 direction:2;
|
||||
u32 filter:16;
|
||||
u32 format:1;
|
||||
u32 type:4;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct hisi_ptt_filter_desc - Descriptor of the PTT trace filter
|
||||
* @list: entry of this descriptor in the filter list
|
||||
* @is_port: the PCI device of the filter is a Root Port or not
|
||||
* @devid: the PCI device's devid of the filter
|
||||
*/
|
||||
struct hisi_ptt_filter_desc {
|
||||
struct list_head list;
|
||||
bool is_port;
|
||||
u16 devid;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct hisi_ptt_pmu_buf - Descriptor of the AUX buffer of PTT trace
|
||||
* @length: size of the AUX buffer
|
||||
* @nr_pages: number of pages of the AUX buffer
|
||||
* @base: start address of AUX buffer
|
||||
* @pos: position in the AUX buffer to commit traced data
|
||||
*/
|
||||
struct hisi_ptt_pmu_buf {
|
||||
size_t length;
|
||||
int nr_pages;
|
||||
void *base;
|
||||
long pos;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct hisi_ptt - Per PTT device data
|
||||
* @trace_ctrl: the control information of PTT trace
|
||||
* @hotplug_node: node for register cpu hotplug event
|
||||
* @hisi_ptt_pmu: the pum device of trace
|
||||
* @iobase: base IO address of the device
|
||||
* @pdev: pci_dev of this PTT device
|
||||
* @tune_lock: lock to serialize the tune process
|
||||
* @pmu_lock: lock to serialize the perf process
|
||||
* @upper_bdf: the upper BDF range of the PCI devices managed by this PTT device
|
||||
* @lower_bdf: the lower BDF range of the PCI devices managed by this PTT device
|
||||
* @port_filters: the filter list of root ports
|
||||
* @req_filters: the filter list of requester ID
|
||||
* @port_mask: port mask of the managed root ports
|
||||
*/
|
||||
struct hisi_ptt {
|
||||
struct hisi_ptt_trace_ctrl trace_ctrl;
|
||||
struct hlist_node hotplug_node;
|
||||
struct pmu hisi_ptt_pmu;
|
||||
void __iomem *iobase;
|
||||
struct pci_dev *pdev;
|
||||
struct mutex tune_lock;
|
||||
spinlock_t pmu_lock;
|
||||
u32 upper_bdf;
|
||||
u32 lower_bdf;
|
||||
|
||||
/*
|
||||
* The trace TLP headers can either be filtered by certain
|
||||
* root port, or by the requester ID. Organize the filters
|
||||
* by @port_filters and @req_filters here. The mask of all
|
||||
* the valid ports is also cached for doing sanity check
|
||||
* of user input.
|
||||
*/
|
||||
struct list_head port_filters;
|
||||
struct list_head req_filters;
|
||||
u16 port_mask;
|
||||
};
|
||||
|
||||
#define to_hisi_ptt(pmu) container_of(pmu, struct hisi_ptt, hisi_ptt_pmu)
|
||||
|
||||
#endif /* _HISI_PTT_H */
|
|
@ -2817,6 +2817,26 @@ static int arm_smmu_dev_disable_feature(struct device *dev,
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* HiSilicon PCIe tune and trace device can be used to trace TLP headers on the
|
||||
* PCIe link and save the data to memory by DMA. The hardware is restricted to
|
||||
* use identity mapping only.
|
||||
*/
|
||||
#define IS_HISI_PTT_DEVICE(pdev) ((pdev)->vendor == PCI_VENDOR_ID_HUAWEI && \
|
||||
(pdev)->device == 0xa12e)
|
||||
|
||||
static int arm_smmu_def_domain_type(struct device *dev)
|
||||
{
|
||||
if (dev_is_pci(dev)) {
|
||||
struct pci_dev *pdev = to_pci_dev(dev);
|
||||
|
||||
if (IS_HISI_PTT_DEVICE(pdev))
|
||||
return IOMMU_DOMAIN_IDENTITY;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct iommu_ops arm_smmu_ops = {
|
||||
.capable = arm_smmu_capable,
|
||||
.domain_alloc = arm_smmu_domain_alloc,
|
||||
|
@ -2831,6 +2851,7 @@ static struct iommu_ops arm_smmu_ops = {
|
|||
.sva_unbind = arm_smmu_sva_unbind,
|
||||
.sva_get_pasid = arm_smmu_sva_get_pasid,
|
||||
.page_response = arm_smmu_page_response,
|
||||
.def_domain_type = arm_smmu_def_domain_type,
|
||||
.pgsize_bitmap = -1UL, /* Restricted during device attach */
|
||||
.owner = THIS_MODULE,
|
||||
.default_domain_ops = &(const struct iommu_domain_ops) {
|
||||
|
|
|
@ -372,6 +372,29 @@ static inline u32 csdev_access_relaxed_read32(struct csdev_access *csa,
|
|||
return csa->read(offset, true, false);
|
||||
}
|
||||
|
||||
static inline u64 csdev_access_relaxed_read_pair(struct csdev_access *csa,
|
||||
u32 lo_offset, u32 hi_offset)
|
||||
{
|
||||
if (likely(csa->io_mem)) {
|
||||
return readl_relaxed(csa->base + lo_offset) |
|
||||
((u64)readl_relaxed(csa->base + hi_offset) << 32);
|
||||
}
|
||||
|
||||
return csa->read(lo_offset, true, false) | (csa->read(hi_offset, true, false) << 32);
|
||||
}
|
||||
|
||||
static inline void csdev_access_relaxed_write_pair(struct csdev_access *csa, u64 val,
|
||||
u32 lo_offset, u32 hi_offset)
|
||||
{
|
||||
if (likely(csa->io_mem)) {
|
||||
writel_relaxed((u32)val, csa->base + lo_offset);
|
||||
writel_relaxed((u32)(val >> 32), csa->base + hi_offset);
|
||||
} else {
|
||||
csa->write((u32)val, lo_offset, true, false);
|
||||
csa->write((u32)(val >> 32), hi_offset, true, false);
|
||||
}
|
||||
}
|
||||
|
||||
static inline u32 csdev_access_read32(struct csdev_access *csa, u32 offset)
|
||||
{
|
||||
if (likely(csa->io_mem))
|
||||
|
|
Loading…
Reference in New Issue