提交 4d516770 编写于 作者: A Alexander Shishkin 提交者: Yang Yingliang

intel_th: msu-sink: An example msu buffer "sink"

mainline inclusion
from mainline-v5.4-rc1
commit f220df66
category: feature
bugzilla: https://gitee.com/openeuler/kernel/issues/I47H3V
CVE: NA

--------------------------------

This patch adds an example MSU buffer "sink", which consumes trace
data from MSC buffers.

Functionally, it acts similarly to "multi" mode with automatic window
switching.
Signed-off-by: NAlexander Shishkin <alexander.shishkin@linux.intel.com>
Reviewed-by: NAndy Shevchenko <andriy.shevchenko@linux.intel.com>
Link: https://lore.kernel.org/r/20190705141425.19894-3-alexander.shishkin@linux.intel.comSigned-off-by: NGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: NJackie Liu <liuyun01@kylinos.cn>
Signed-off-by: NZheng Zengkai <zhengzengkai@huawei.com>
Reviewed-by: NXie XiuQi <xiexiuqi@huawei.com>
Signed-off-by: NYang Yingliang <yangyingliang@huawei.com>
上级 cfbd697d
......@@ -20,3 +20,6 @@ intel_th_msu-y := msu.o
obj-$(CONFIG_INTEL_TH_PTI) += intel_th_pti.o
intel_th_pti-y := pti.o
obj-$(CONFIG_INTEL_TH_MSU) += intel_th_msu_sink.o
intel_th_msu_sink-y := msu-sink.o
// SPDX-License-Identifier: GPL-2.0
/*
* An example software sink buffer for Intel TH MSU.
*
* Copyright (C) 2019 Intel Corporation.
*/
#include <linux/intel_th.h>
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/device.h>
#include <linux/dma-mapping.h>
#define MAX_SGTS 16
struct msu_sink_private {
struct device *dev;
struct sg_table **sgts;
unsigned int nr_sgts;
};
static void *msu_sink_assign(struct device *dev, int *mode)
{
struct msu_sink_private *priv;
priv = kzalloc(sizeof(*priv), GFP_KERNEL);
if (!priv)
return NULL;
priv->sgts = kcalloc(MAX_SGTS, sizeof(void *), GFP_KERNEL);
if (!priv->sgts) {
kfree(priv);
return NULL;
}
priv->dev = dev;
*mode = MSC_MODE_MULTI;
return priv;
}
static void msu_sink_unassign(void *data)
{
struct msu_sink_private *priv = data;
kfree(priv->sgts);
kfree(priv);
}
/* See also: msc.c: __msc_buffer_win_alloc() */
static int msu_sink_alloc_window(void *data, struct sg_table **sgt, size_t size)
{
struct msu_sink_private *priv = data;
unsigned int nents;
struct scatterlist *sg_ptr;
void *block;
int ret, i;
if (priv->nr_sgts == MAX_SGTS)
return -ENOMEM;
nents = DIV_ROUND_UP(size, PAGE_SIZE);
ret = sg_alloc_table(*sgt, nents, GFP_KERNEL);
if (ret)
return -ENOMEM;
priv->sgts[priv->nr_sgts++] = *sgt;
for_each_sg((*sgt)->sgl, sg_ptr, nents, i) {
block = dma_alloc_coherent(priv->dev->parent->parent,
PAGE_SIZE, &sg_dma_address(sg_ptr),
GFP_KERNEL);
sg_set_buf(sg_ptr, block, PAGE_SIZE);
}
return nents;
}
/* See also: msc.c: __msc_buffer_win_free() */
static void msu_sink_free_window(void *data, struct sg_table *sgt)
{
struct msu_sink_private *priv = data;
struct scatterlist *sg_ptr;
int i;
for_each_sg(sgt->sgl, sg_ptr, sgt->nents, i) {
dma_free_coherent(priv->dev->parent->parent, PAGE_SIZE,
sg_virt(sg_ptr), sg_dma_address(sg_ptr));
}
sg_free_table(sgt);
priv->nr_sgts--;
}
static int msu_sink_ready(void *data, struct sg_table *sgt, size_t bytes)
{
struct msu_sink_private *priv = data;
intel_th_msc_window_unlock(priv->dev, sgt);
return 0;
}
static const struct msu_buffer sink_mbuf = {
.name = "sink",
.assign = msu_sink_assign,
.unassign = msu_sink_unassign,
.alloc_window = msu_sink_alloc_window,
.free_window = msu_sink_free_window,
.ready = msu_sink_ready,
};
module_intel_th_msu_buffer(sink_mbuf);
MODULE_LICENSE("GPL v2");
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册