2022-08-16 19:44:11 +08:00
/* 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>
2023-06-21 17:28:02 +08:00
# include <linux/device.h>
2023-06-21 17:28:01 +08:00
# include <linux/kfifo.h>
2022-08-16 19:44:11 +08:00
# include <linux/list.h>
2022-08-16 19:44:12 +08:00
# include <linux/mutex.h>
2023-06-21 17:28:01 +08:00
# include <linux/notifier.h>
2022-08-16 19:44:11 +08:00
# include <linux/pci.h>
# include <linux/perf_event.h>
# include <linux/spinlock.h>
# include <linux/types.h>
2023-06-21 17:28:01 +08:00
# include <linux/workqueue.h>
2022-08-16 19:44:11 +08:00
# define DRV_NAME "hisi_ptt"
/*
* The definition of the device registers and register fields .
*/
2022-08-16 19:44:12 +08:00
# 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)
2022-08-16 19:44:11 +08:00
# 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
2022-08-16 19:44:12 +08:00
# define HISI_PTT_TUNING_INT_STAT 0x0898
# define HISI_PTT_TUNING_INT_STAT_MASK BIT(0)
2022-08-16 19:44:11 +08:00
# 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 */
2022-08-16 19:44:12 +08:00
# define HISI_PTT_WAIT_TUNE_TIMEOUT_US 1000000UL
2022-08-16 19:44:11 +08:00
# define HISI_PTT_WAIT_TRACE_TIMEOUT_US 100UL
# define HISI_PTT_WAIT_POLL_INTERVAL_US 10UL
2023-06-21 17:28:01 +08:00
/* FIFO size for dynamically updating the PTT trace filter list. */
# define HISI_PTT_FILTER_UPDATE_FIFO_SIZE 16
/* Delay time for filter updating work */
# define HISI_PTT_WORK_DELAY_MS 100UL
2022-08-16 19:44:11 +08:00
# 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)
2022-08-16 19:44:12 +08:00
/**
* 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 ;
} ;
2022-08-16 19:44:11 +08:00
/**
* 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 ;
} ;
2023-06-21 17:28:02 +08:00
/*
* sysfs attribute group name for root port filters and requester filters :
* / sys / devices / hisi_ptt < sicl_id > _ < core_id > / root_port_filters
* and
* / sys / devices / hisi_ptt < sicl_id > _ < core_id > / requester_filters
*/
# define HISI_PTT_RP_FILTERS_GRP_NAME "root_port_filters"
# define HISI_PTT_REQ_FILTERS_GRP_NAME "requester_filters"
2022-08-16 19:44:11 +08:00
/**
* struct hisi_ptt_filter_desc - Descriptor of the PTT trace filter
2023-06-21 17:28:02 +08:00
* @ attr : sysfs attribute of this filter
2022-08-16 19:44:11 +08:00
* @ list : entry of this descriptor in the filter list
* @ is_port : the PCI device of the filter is a Root Port or not
2023-06-21 17:28:01 +08:00
* @ name : name of this filter , same as the name of the related PCI device
2022-08-16 19:44:11 +08:00
* @ devid : the PCI device ' s devid of the filter
*/
struct hisi_ptt_filter_desc {
2023-06-21 17:28:02 +08:00
struct device_attribute attr ;
2022-08-16 19:44:11 +08:00
struct list_head list ;
bool is_port ;
2023-06-21 17:28:01 +08:00
char * name ;
u16 devid ;
} ;
/**
* struct hisi_ptt_filter_update_info - Information for PTT filter updating
* @ is_port : the PCI device to update is a Root Port or not
* @ is_add : adding to the filter or not
* @ devid : the PCI device ' s devid of the filter
*/
struct hisi_ptt_filter_update_info {
bool is_port ;
bool is_add ;
2022-08-16 19:44:11 +08:00
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
2023-06-21 17:28:01 +08:00
* @ hisi_ptt_nb : dynamic filter update notifier
2022-08-16 19:44:11 +08:00
* @ 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
2022-08-16 19:44:12 +08:00
* @ tune_lock : lock to serialize the tune process
2022-08-16 19:44:11 +08:00
* @ pmu_lock : lock to serialize the perf process
2023-06-21 17:28:04 +08:00
* @ trace_irq : interrupt number used by trace
2022-08-16 19:44:11 +08:00
* @ 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
2023-06-21 17:28:01 +08:00
* @ filter_lock : lock to protect the filters
2023-06-21 17:28:02 +08:00
* @ sysfs_inited : whether the filters ' sysfs entries has been initialized
2022-08-16 19:44:11 +08:00
* @ port_mask : port mask of the managed root ports
2023-06-21 17:28:01 +08:00
* @ work : delayed work for filter updating
* @ filter_update_lock : spinlock to protect the filter update fifo
* @ filter_update_fifo : fifo of the filters waiting to update the filter list
2022-08-16 19:44:11 +08:00
*/
struct hisi_ptt {
struct hisi_ptt_trace_ctrl trace_ctrl ;
2023-06-21 17:28:01 +08:00
struct notifier_block hisi_ptt_nb ;
2022-08-16 19:44:11 +08:00
struct hlist_node hotplug_node ;
struct pmu hisi_ptt_pmu ;
void __iomem * iobase ;
struct pci_dev * pdev ;
2022-08-16 19:44:12 +08:00
struct mutex tune_lock ;
2022-08-16 19:44:11 +08:00
spinlock_t pmu_lock ;
2023-06-21 17:28:04 +08:00
int trace_irq ;
2022-08-16 19:44:11 +08:00
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 ;
2023-06-21 17:28:01 +08:00
struct mutex filter_lock ;
2023-06-21 17:28:02 +08:00
bool sysfs_inited ;
2022-08-16 19:44:11 +08:00
u16 port_mask ;
2023-06-21 17:28:01 +08:00
/*
* We use a delayed work here to avoid indefinitely waiting for
* the hisi_ptt - > mutex which protecting the filter list . The
* work will be delayed only if the mutex can not be held ,
* otherwise no delay will be applied .
*/
struct delayed_work work ;
spinlock_t filter_update_lock ;
DECLARE_KFIFO ( filter_update_kfifo , struct hisi_ptt_filter_update_info ,
HISI_PTT_FILTER_UPDATE_FIFO_SIZE ) ;
2022-08-16 19:44:11 +08:00
} ;
# define to_hisi_ptt(pmu) container_of(pmu, struct hisi_ptt, hisi_ptt_pmu)
# endif /* _HISI_PTT_H */