[PATCH v8 2/8] hwtracing: hisi_ptt: Add trace function support for HiSilicon PCIe Tune and Trace device
Yicong Yang
yangyicong at huawei.com
Tue May 17 01:09:45 PDT 2022
On 2022/5/17 0:23, John Garry wrote:
> On 16/05/2022 13:52, Yicong Yang wrote:
>> 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 traffic and trace the TLP headers.
>>
>> Add the driver for the device to enable the trace function. Register PMU
>> device of PTT trace, then users can use trace through perf command. The
>> driver makes use of perf AUX trace function and support the following
>> events to configure the trace:
>>
>> - filter: select Root port or Endpoint to trace
>> - type: select the type of traced TLP headers
>> - direction: select the direction of traced TLP headers
>> - format: select the data format of the traced TLP headers
>>
>> This patch initially add a basic driver of PTT trace.
>
> Initially add basic trace support.
>
>>
>> Signed-off-by: Yicong Yang <yangyicong at hisilicon.com>
>
> Generally this looks ok, apart from nitpicking below, so, FWIW:
> Reviewed-by: John Garry <john.garry at huawei.com>
> >> ---
>> drivers/Makefile | 1 +
>> drivers/hwtracing/Kconfig | 2 +
>> drivers/hwtracing/ptt/Kconfig | 12 +
>> drivers/hwtracing/ptt/Makefile | 2 +
>> drivers/hwtracing/ptt/hisi_ptt.c | 964 +++++++++++++++++++++++++++++++
>> drivers/hwtracing/ptt/hisi_ptt.h | 178 ++++++
>> 6 files changed, 1159 insertions(+)
>> create mode 100644 drivers/hwtracing/ptt/Kconfig
>> create mode 100644 drivers/hwtracing/ptt/Makefile
>> create mode 100644 drivers/hwtracing/ptt/hisi_ptt.c
>> create mode 100644 drivers/hwtracing/ptt/hisi_ptt.h
>>
[...]
>> +static int hisi_ptt_cpu_teardown(unsigned int cpu, struct hlist_node *node)
>> +{
>> + struct hisi_ptt *hisi_ptt;
>> + int target, src;
>> +
>> + hisi_ptt = hlist_entry_safe(node, struct hisi_ptt, hotplug_node);
>> + src = hisi_ptt->trace_ctrl.on_cpu;
>> +
>> + if (!hisi_ptt->trace_ctrl.started || src != cpu)
>> + return 0;
>> +
>> + target = cpumask_any(cpumask_of_node(dev_to_node(&hisi_ptt->pdev->dev)));
>> + if (target < nr_cpumask_bits) {
>
> the comment for cpumask_any() hints to check against nr_cpu_ids - any specific reason to check against nr_cpumask_bits?
>
here should be:
if (target >= nr_cpumask_bits) {
will fix this up.
>> + dev_err(hisi_ptt->hisi_ptt_pmu.dev, "no available cpu for perf context migration\n");
>> + return 0;
>> + }
>> +
>> + perf_pmu_migrate_context(&hisi_ptt->hisi_ptt_pmu, src, target);
>> + WARN_ON(irq_set_affinity(pci_irq_vector(hisi_ptt->pdev, HISI_PTT_TRACE_DMA_IRQ),
>> + cpumask_of(cpu)));
>> + hisi_ptt->trace_ctrl.on_cpu = target;
>> +
>> + return 0;
>> +}
>> +
>> +static int __init hisi_ptt_init(void)
>> +{
>> + int ret;
>> +
>> + ret = cpuhp_setup_state_multi(CPUHP_AP_ONLINE_DYN, DRV_NAME, NULL,
>> + hisi_ptt_cpu_teardown);
>> + if (ret < 0)
>> + return ret;
>> + hisi_ptt_pmu_online = ret;
>> +
>> + ret = pci_register_driver(&hisi_ptt_driver);
>> + if (ret)
>> + cpuhp_remove_multi_state(hisi_ptt_pmu_online);
>> +
>> + return ret;
>> +}
>> +module_init(hisi_ptt_init);
>> +
>> +static void __exit hisi_ptt_exit(void)
>> +{
>> + pci_unregister_driver(&hisi_ptt_driver);
>> + cpuhp_remove_multi_state(hisi_ptt_pmu_online);
>> +}
>> +module_exit(hisi_ptt_exit);
>> +
>> +MODULE_LICENSE("GPL");
>> +MODULE_AUTHOR("Yicong Yang <yangyicong at hisilicon.com>");
>> +MODULE_DESCRIPTION("Driver for HiSilicon PCIe tune and trace device");
>> diff --git a/drivers/hwtracing/ptt/hisi_ptt.h b/drivers/hwtracing/ptt/hisi_ptt.h
>> new file mode 100644
>> index 000000000000..2344e4195648
>> --- /dev/null
>> +++ b/drivers/hwtracing/ptt/hisi_ptt.h
>> @@ -0,0 +1,178 @@
>> +/* 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 at hisilicon.com>
>> + */
>> +
>> +#ifndef _HISI_PTT_H
>> +#define _HISI_PTT_H
>> +
>> +#include <linux/bits.h>
>> +#include <linux/cpumask.h>
>> +#include <linux/list.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_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_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_TRACE_TIMEOUT_US 100UL
>> +#define HISI_PTT_WAIT_POLL_INTERVAL_US 10UL
>> +
>> +#define HISI_PCIE_CORE_PORT_ID(devfn) (PCI_FUNC(devfn) << 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_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
>> + * @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;
>> + 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 */
>
> .
More information about the linux-arm-kernel
mailing list