-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
intel_th: msu-sink: An example msu buffer "sink"
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: Alexander Shishkin <alexander.shishkin@linux.intel.com> Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com> Link: https://lore.kernel.org/r/20190705141425.19894-3-alexander.shishkin@linux.intel.com Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
- Loading branch information
Alexander Shishkin
authored and
Greg Kroah-Hartman
committed
Jul 25, 2019
1 parent
615c164
commit f220df6
Showing
2 changed files
with
119 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,116 @@ | ||
// 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"); |