Commit 615c164d authored by Alexander Shishkin's avatar Alexander Shishkin Committed by Greg Kroah-Hartman

intel_th: msu: Introduce buffer interface

Introduces a concept of external buffers, which is a mechanism for creating
trace sinks that would receive trace data from MSC buffers and transfer it
elsewhere.

A external buffer can implement its own window allocation/deallocation if
it has to. It must provide a callback that's used to notify it when a
window fills up, so that it can then start a DMA transaction from that
window 'elsewhere'. This window remains in a 'locked' state and won't be
used for storing new trace data until the buffer 'unlocks' it with a
provided API call, at which point the window can be used again for storing
trace data.

This relies on a functional "last block" interrupt, so not all versions of
Trace Hub can use this feature, which does not reflect on existing users.
Signed-off-by: default avatarAlexander Shishkin <alexander.shishkin@linux.intel.com>
Reviewed-by: default avatarAndy Shevchenko <andriy.shevchenko@linux.intel.com>
Link: https://lore.kernel.org/r/20190705141425.19894-2-alexander.shishkin@linux.intel.comSigned-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent db4ad308
......@@ -12,7 +12,8 @@ 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.
- "debug", for debug mode;
- any of the currently loaded buffer sinks.
If operating mode changes, existing buffer is deallocated,
provided there are no active users and tracing is not enabled,
otherwise the write will fail.
......
......@@ -8360,6 +8360,7 @@ M: Alexander Shishkin <alexander.shishkin@linux.intel.com>
S: Supported
F: Documentation/trace/intel_th.rst
F: drivers/hwtracing/intel_th/
F: include/linux/intel_th.h
INTEL(R) TRUSTED EXECUTION TECHNOLOGY (TXT)
M: Ning Sun <ning.sun@intel.com>
......
This diff is collapsed.
......@@ -44,14 +44,6 @@ enum {
#define M0BLIE BIT(16)
#define M1BLIE BIT(24)
/* 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 */
......@@ -93,6 +85,16 @@ static inline unsigned long msc_data_sz(struct msc_block_desc *bdesc)
return bdesc->valid_dw * 4 - MSC_BDESC;
}
static inline unsigned long msc_total_sz(struct msc_block_desc *bdesc)
{
return bdesc->valid_dw * 4;
}
static inline unsigned long msc_block_sz(struct msc_block_desc *bdesc)
{
return bdesc->block_sz * 64 - MSC_BDESC;
}
static inline bool msc_block_wrapped(struct msc_block_desc *bdesc)
{
if (bdesc->hw_tag & (MSC_HW_TAG_BLOCKWRAP | MSC_HW_TAG_WINWRAP))
......@@ -104,7 +106,7 @@ static inline bool msc_block_wrapped(struct msc_block_desc *bdesc)
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))
(msc_data_sz(bdesc) != msc_block_sz(bdesc)))
return true;
return false;
......
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Intel(R) Trace Hub data structures for implementing buffer sinks.
*
* Copyright (C) 2019 Intel Corporation.
*/
#ifndef _INTEL_TH_H_
#define _INTEL_TH_H_
#include <linux/scatterlist.h>
/* MSC operating modes (MSC_MODE) */
enum {
MSC_MODE_SINGLE = 0,
MSC_MODE_MULTI,
MSC_MODE_EXI,
MSC_MODE_DEBUG,
};
struct msu_buffer {
const char *name;
/*
* ->assign() called when buffer 'mode' is set to this driver
* (aka mode_store())
* @device: struct device * of the msc
* @mode: allows the driver to set HW mode (see the enum above)
* Returns: a pointer to a private structure associated with this
* msc or NULL in case of error. This private structure
* will then be passed into all other callbacks.
*/
void *(*assign)(struct device *dev, int *mode);
/* ->unassign(): some other mode is selected, clean up */
void (*unassign)(void *priv);
/*
* ->alloc_window(): allocate memory for the window of a given
* size
* @sgt: pointer to sg_table, can be overridden by the buffer
* driver, or kept intact
* Returns: number of sg table entries <= number of pages;
* 0 is treated as an allocation failure.
*/
int (*alloc_window)(void *priv, struct sg_table **sgt,
size_t size);
void (*free_window)(void *priv, struct sg_table *sgt);
/* ->activate(): trace has started */
void (*activate)(void *priv);
/* ->deactivate(): trace is about to stop */
void (*deactivate)(void *priv);
/*
* ->ready(): window @sgt is filled up to the last block OR
* tracing is stopped by the user; this window contains
* @bytes data. The window in question transitions into
* the "LOCKED" state, indicating that it can't be used
* by hardware. To clear this state and make the window
* available to the hardware again, call
* intel_th_msc_window_unlock().
*/
int (*ready)(void *priv, struct sg_table *sgt, size_t bytes);
};
int intel_th_msu_buffer_register(const struct msu_buffer *mbuf,
struct module *owner);
void intel_th_msu_buffer_unregister(const struct msu_buffer *mbuf);
void intel_th_msc_window_unlock(struct device *dev, struct sg_table *sgt);
#define module_intel_th_msu_buffer(__buffer) \
static int __init __buffer##_init(void) \
{ \
return intel_th_msu_buffer_register(&(__buffer), THIS_MODULE); \
} \
module_init(__buffer##_init); \
static void __exit __buffer##_exit(void) \
{ \
intel_th_msu_buffer_unregister(&(__buffer)); \
} \
module_exit(__buffer##_exit);
#endif /* _INTEL_TH_H_ */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment