mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-08-25 02:09:42 +00:00
intel_th: msu: Add current window tracking
Now that we have a way to switch between MSC buffer windows, add code to track the current window. The hardware register NWSA that contains the address of the next window is unfortunately not always usable, and since the driver has full control of the window switching, there is no reason not to keep this on the software side. 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
6cac7866c2
commit
aad14ad3cf
1 changed files with 49 additions and 30 deletions
|
@ -75,6 +75,7 @@ struct msc_iter {
|
||||||
* @thdev: intel_th_device pointer
|
* @thdev: intel_th_device pointer
|
||||||
* @win_list: list of windows in multiblock mode
|
* @win_list: list of windows in multiblock mode
|
||||||
* @single_sgt: single mode buffer
|
* @single_sgt: single mode buffer
|
||||||
|
* @cur_win: current window
|
||||||
* @nr_pages: total number of pages allocated for this buffer
|
* @nr_pages: total number of pages allocated for this buffer
|
||||||
* @single_sz: amount of data in single mode
|
* @single_sz: amount of data in single mode
|
||||||
* @single_wrap: single mode wrap occurred
|
* @single_wrap: single mode wrap occurred
|
||||||
|
@ -97,6 +98,7 @@ struct msc {
|
||||||
|
|
||||||
struct list_head win_list;
|
struct list_head win_list;
|
||||||
struct sg_table single_sgt;
|
struct sg_table single_sgt;
|
||||||
|
struct msc_window *cur_win;
|
||||||
unsigned long nr_pages;
|
unsigned long nr_pages;
|
||||||
unsigned long single_sz;
|
unsigned long single_sz;
|
||||||
unsigned int single_wrap : 1;
|
unsigned int single_wrap : 1;
|
||||||
|
@ -151,6 +153,31 @@ msc_win_bpfn(struct msc_window *win, unsigned int block)
|
||||||
return msc_win_baddr(win, block) >> PAGE_SHIFT;
|
return msc_win_baddr(win, block) >> PAGE_SHIFT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* msc_is_last_win() - check if a window is the last one for a given MSC
|
||||||
|
* @win: window
|
||||||
|
* Return: true if @win is the last window in MSC's multiblock buffer
|
||||||
|
*/
|
||||||
|
static inline bool msc_is_last_win(struct msc_window *win)
|
||||||
|
{
|
||||||
|
return win->entry.next == &win->msc->win_list;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* msc_next_window() - return next window in the multiblock buffer
|
||||||
|
* @win: current window
|
||||||
|
*
|
||||||
|
* Return: window following the current one
|
||||||
|
*/
|
||||||
|
static struct msc_window *msc_next_window(struct msc_window *win)
|
||||||
|
{
|
||||||
|
if (msc_is_last_win(win))
|
||||||
|
return list_first_entry(&win->msc->win_list, struct msc_window,
|
||||||
|
entry);
|
||||||
|
|
||||||
|
return list_next_entry(win, entry);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* msc_oldest_window() - locate the window with oldest data
|
* msc_oldest_window() - locate the window with oldest data
|
||||||
* @msc: MSC device
|
* @msc: MSC device
|
||||||
|
@ -162,9 +189,7 @@ msc_win_bpfn(struct msc_window *win, unsigned int block)
|
||||||
*/
|
*/
|
||||||
static struct msc_window *msc_oldest_window(struct msc *msc)
|
static struct msc_window *msc_oldest_window(struct msc *msc)
|
||||||
{
|
{
|
||||||
struct msc_window *win;
|
struct msc_window *win, *next = msc_next_window(msc->cur_win);
|
||||||
u32 reg = ioread32(msc->reg_base + REG_MSU_MSC0NWSA);
|
|
||||||
unsigned long win_addr = (unsigned long)reg << PAGE_SHIFT;
|
|
||||||
unsigned int found = 0;
|
unsigned int found = 0;
|
||||||
|
|
||||||
if (list_empty(&msc->win_list))
|
if (list_empty(&msc->win_list))
|
||||||
|
@ -176,7 +201,7 @@ static struct msc_window *msc_oldest_window(struct msc *msc)
|
||||||
* something like 2, in which case we're good
|
* something like 2, in which case we're good
|
||||||
*/
|
*/
|
||||||
list_for_each_entry(win, &msc->win_list, entry) {
|
list_for_each_entry(win, &msc->win_list, entry) {
|
||||||
if (sg_dma_address(win->sgt.sgl) == win_addr)
|
if (win == next)
|
||||||
found++;
|
found++;
|
||||||
|
|
||||||
/* skip the empty ones */
|
/* skip the empty ones */
|
||||||
|
@ -219,31 +244,6 @@ static unsigned int msc_win_oldest_block(struct msc_window *win)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* msc_is_last_win() - check if a window is the last one for a given MSC
|
|
||||||
* @win: window
|
|
||||||
* Return: true if @win is the last window in MSC's multiblock buffer
|
|
||||||
*/
|
|
||||||
static inline bool msc_is_last_win(struct msc_window *win)
|
|
||||||
{
|
|
||||||
return win->entry.next == &win->msc->win_list;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* msc_next_window() - return next window in the multiblock buffer
|
|
||||||
* @win: current window
|
|
||||||
*
|
|
||||||
* Return: window following the current one
|
|
||||||
*/
|
|
||||||
static struct msc_window *msc_next_window(struct msc_window *win)
|
|
||||||
{
|
|
||||||
if (msc_is_last_win(win))
|
|
||||||
return list_first_entry(&win->msc->win_list, struct msc_window,
|
|
||||||
entry);
|
|
||||||
|
|
||||||
return list_next_entry(win, entry);
|
|
||||||
}
|
|
||||||
|
|
||||||
static struct msc_block_desc *msc_iter_bdesc(struct msc_iter *iter)
|
static struct msc_block_desc *msc_iter_bdesc(struct msc_iter *iter)
|
||||||
{
|
{
|
||||||
return msc_win_block(iter->win, iter->block);
|
return msc_win_block(iter->win, iter->block);
|
||||||
|
@ -822,6 +822,7 @@ static int msc_buffer_win_alloc(struct msc *msc, unsigned int nr_blocks)
|
||||||
if (list_empty(&msc->win_list)) {
|
if (list_empty(&msc->win_list)) {
|
||||||
msc->base = msc_win_block(win, 0);
|
msc->base = msc_win_block(win, 0);
|
||||||
msc->base_addr = msc_win_baddr(win, 0);
|
msc->base_addr = msc_win_baddr(win, 0);
|
||||||
|
msc->cur_win = win;
|
||||||
}
|
}
|
||||||
|
|
||||||
list_add_tail(&win->entry, &msc->win_list);
|
list_add_tail(&win->entry, &msc->win_list);
|
||||||
|
@ -1383,6 +1384,24 @@ static int intel_th_msc_init(struct msc *msc)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void msc_win_switch(struct msc *msc)
|
||||||
|
{
|
||||||
|
struct msc_window *last, *first;
|
||||||
|
|
||||||
|
first = list_first_entry(&msc->win_list, struct msc_window, entry);
|
||||||
|
last = list_last_entry(&msc->win_list, struct msc_window, entry);
|
||||||
|
|
||||||
|
if (msc_is_last_win(msc->cur_win))
|
||||||
|
msc->cur_win = first;
|
||||||
|
else
|
||||||
|
msc->cur_win = list_next_entry(msc->cur_win, entry);
|
||||||
|
|
||||||
|
msc->base = msc_win_block(msc->cur_win, 0);
|
||||||
|
msc->base_addr = msc_win_baddr(msc->cur_win, 0);
|
||||||
|
|
||||||
|
intel_th_trace_switch(msc->thdev);
|
||||||
|
}
|
||||||
|
|
||||||
static irqreturn_t intel_th_msc_interrupt(struct intel_th_device *thdev)
|
static irqreturn_t intel_th_msc_interrupt(struct intel_th_device *thdev)
|
||||||
{
|
{
|
||||||
struct msc *msc = dev_get_drvdata(&thdev->dev);
|
struct msc *msc = dev_get_drvdata(&thdev->dev);
|
||||||
|
@ -1591,7 +1610,7 @@ win_switch_store(struct device *dev, struct device_attribute *attr,
|
||||||
if (msc->mode != MSC_MODE_MULTI)
|
if (msc->mode != MSC_MODE_MULTI)
|
||||||
ret = -ENOTSUPP;
|
ret = -ENOTSUPP;
|
||||||
else
|
else
|
||||||
ret = intel_th_trace_switch(msc->thdev);
|
msc_win_switch(msc);
|
||||||
mutex_unlock(&msc->buf_mutex);
|
mutex_unlock(&msc->buf_mutex);
|
||||||
|
|
||||||
return ret ? ret : size;
|
return ret ? ret : size;
|
||||||
|
|
Loading…
Reference in a new issue