intel_th: Add Memory Storage Unit driver
Memory Storage Unit (MSU) is a trace output device that collects trace data to system memory. It consists of 2 independent Memory Storage Controllers (MSCs). This driver provides userspace interfaces to configure in-memory tracing parameters, such as contiguous (high-order allocation) buffer or multiblock (scatter list) buffer mode, wrapping (data overwrite) and number and sizes of windows in multiblock mode. Userspace can read the buffers via mmap()ing or read()ing of the corresponding device node. Signed-off-by: Laurent Fert <laurent.fert@intel.com> Signed-off-by: Alexander Shishkin <alexander.shishkin@linux.intel.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
parent
f04e449fc7
commit
ba82664c13
|
@ -0,0 +1,33 @@
|
|||
What: /sys/bus/intel_th/devices/<intel_th_id>-msc<msc-id>/wrap
|
||||
Date: June 2015
|
||||
KernelVersion: 4.3
|
||||
Contact: Alexander Shishkin <alexander.shishkin@linux.intel.com>
|
||||
Description: (RW) Configure MSC buffer wrapping. 1 == wrapping enabled.
|
||||
|
||||
What: /sys/bus/intel_th/devices/<intel_th_id>-msc<msc-id>/mode
|
||||
Date: June 2015
|
||||
KernelVersion: 4.3
|
||||
Contact: Alexander Shishkin <alexander.shishkin@linux.intel.com>
|
||||
Description: (RW) Configure MSC operating mode:
|
||||
- "single", for contiguous buffer mode (high-order alloc);
|
||||
- "multi", for multiblock mode;
|
||||
- "ExI", for DCI handler mode;
|
||||
- "debug", for debug mode.
|
||||
If operating mode changes, existing buffer is deallocated,
|
||||
provided there are no active users and tracing is not enabled,
|
||||
otherwise the write will fail.
|
||||
|
||||
What: /sys/bus/intel_th/devices/<intel_th_id>-msc<msc-id>/nr_pages
|
||||
Date: June 2015
|
||||
KernelVersion: 4.3
|
||||
Contact: Alexander Shishkin <alexander.shishkin@linux.intel.com>
|
||||
Description: (RW) Configure MSC buffer size for "single" or "multi" modes.
|
||||
In single mode, this is a single number of pages, has to be
|
||||
power of 2. In multiblock mode, this is a comma-separated list
|
||||
of numbers of pages for each window to be allocated. Number of
|
||||
windows is not limited.
|
||||
Writing to this file deallocates existing buffer (provided
|
||||
there are no active users and tracing is not enabled) and then
|
||||
allocates a new one.
|
||||
|
||||
|
|
@ -44,6 +44,16 @@ config INTEL_TH_STH
|
|||
|
||||
Say Y here to enable STH subdevice of Intel(R) Trace Hub.
|
||||
|
||||
config INTEL_TH_MSU
|
||||
tristate "Intel(R) Trace Hub Memory Storage Unit"
|
||||
help
|
||||
Memory Storage Unit (MSU) trace output device enables
|
||||
storing STP traces to system memory. It supports single
|
||||
and multiblock modes of operation and provides read()
|
||||
and mmap() access to the collected data.
|
||||
|
||||
Say Y here to enable MSU output device for Intel TH.
|
||||
|
||||
config INTEL_TH_DEBUG
|
||||
bool "Intel(R) Trace Hub debugging"
|
||||
depends on DEBUG_FS
|
||||
|
|
|
@ -10,3 +10,6 @@ intel_th_gth-y := gth.o
|
|||
|
||||
obj-$(CONFIG_INTEL_TH_STH) += intel_th_sth.o
|
||||
intel_th_sth-y := sth.o
|
||||
|
||||
obj-$(CONFIG_INTEL_TH_MSU) += intel_th_msu.o
|
||||
intel_th_msu-y := msu.o
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,116 @@
|
|||
/*
|
||||
* Intel(R) Trace Hub Memory Storage Unit (MSU) data structures
|
||||
*
|
||||
* Copyright (C) 2014-2015 Intel Corporation.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
* version 2, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*/
|
||||
|
||||
#ifndef __INTEL_TH_MSU_H__
|
||||
#define __INTEL_TH_MSU_H__
|
||||
|
||||
enum {
|
||||
REG_MSU_MSUPARAMS = 0x0000,
|
||||
REG_MSU_MSUSTS = 0x0008,
|
||||
REG_MSU_MSC0CTL = 0x0100, /* MSC0 control */
|
||||
REG_MSU_MSC0STS = 0x0104, /* MSC0 status */
|
||||
REG_MSU_MSC0BAR = 0x0108, /* MSC0 output base address */
|
||||
REG_MSU_MSC0SIZE = 0x010c, /* MSC0 output size */
|
||||
REG_MSU_MSC0MWP = 0x0110, /* MSC0 write pointer */
|
||||
REG_MSU_MSC0NWSA = 0x011c, /* MSC0 next window start address */
|
||||
|
||||
REG_MSU_MSC1CTL = 0x0200, /* MSC1 control */
|
||||
REG_MSU_MSC1STS = 0x0204, /* MSC1 status */
|
||||
REG_MSU_MSC1BAR = 0x0208, /* MSC1 output base address */
|
||||
REG_MSU_MSC1SIZE = 0x020c, /* MSC1 output size */
|
||||
REG_MSU_MSC1MWP = 0x0210, /* MSC1 write pointer */
|
||||
REG_MSU_MSC1NWSA = 0x021c, /* MSC1 next window start address */
|
||||
};
|
||||
|
||||
/* MSUSTS bits */
|
||||
#define MSUSTS_MSU_INT BIT(0)
|
||||
|
||||
/* MSCnCTL bits */
|
||||
#define MSC_EN BIT(0)
|
||||
#define MSC_WRAPEN BIT(1)
|
||||
#define MSC_RD_HDR_OVRD BIT(2)
|
||||
#define MSC_MODE (BIT(4) | BIT(5))
|
||||
#define MSC_LEN (BIT(8) | BIT(9) | BIT(10))
|
||||
|
||||
/* MSC operating modes (MSC_MODE) */
|
||||
enum {
|
||||
MSC_MODE_SINGLE = 0,
|
||||
MSC_MODE_MULTI,
|
||||
MSC_MODE_EXI,
|
||||
MSC_MODE_DEBUG,
|
||||
};
|
||||
|
||||
/* MSCnSTS bits */
|
||||
#define MSCSTS_WRAPSTAT BIT(1) /* Wrap occurred */
|
||||
#define MSCSTS_PLE BIT(2) /* Pipeline Empty */
|
||||
|
||||
/*
|
||||
* Multiblock/multiwindow block descriptor
|
||||
*/
|
||||
struct msc_block_desc {
|
||||
u32 sw_tag;
|
||||
u32 block_sz;
|
||||
u32 next_blk;
|
||||
u32 next_win;
|
||||
u32 res0[4];
|
||||
u32 hw_tag;
|
||||
u32 valid_dw;
|
||||
u32 ts_low;
|
||||
u32 ts_high;
|
||||
u32 res1[4];
|
||||
} __packed;
|
||||
|
||||
#define MSC_BDESC sizeof(struct msc_block_desc)
|
||||
#define DATA_IN_PAGE (PAGE_SIZE - MSC_BDESC)
|
||||
|
||||
/* MSC multiblock sw tag bits */
|
||||
#define MSC_SW_TAG_LASTBLK BIT(0)
|
||||
#define MSC_SW_TAG_LASTWIN BIT(1)
|
||||
|
||||
/* MSC multiblock hw tag bits */
|
||||
#define MSC_HW_TAG_TRIGGER BIT(0)
|
||||
#define MSC_HW_TAG_BLOCKWRAP BIT(1)
|
||||
#define MSC_HW_TAG_WINWRAP BIT(2)
|
||||
#define MSC_HW_TAG_ENDBIT BIT(3)
|
||||
|
||||
static inline unsigned long msc_data_sz(struct msc_block_desc *bdesc)
|
||||
{
|
||||
if (!bdesc->valid_dw)
|
||||
return 0;
|
||||
|
||||
return bdesc->valid_dw * 4 - MSC_BDESC;
|
||||
}
|
||||
|
||||
static inline bool msc_block_wrapped(struct msc_block_desc *bdesc)
|
||||
{
|
||||
if (bdesc->hw_tag & MSC_HW_TAG_BLOCKWRAP)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static inline bool msc_block_last_written(struct msc_block_desc *bdesc)
|
||||
{
|
||||
if ((bdesc->hw_tag & MSC_HW_TAG_ENDBIT) ||
|
||||
(msc_data_sz(bdesc) != DATA_IN_PAGE))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/* waiting for Pipeline Empty bit(s) to assert for MSC */
|
||||
#define MSC_PLE_WAITLOOP_DEPTH 10000
|
||||
|
||||
#endif /* __INTEL_TH_MSU_H__ */
|
Loading…
Reference in New Issue