blob: 5288d554c77c313576d8c2088879a6a5d82e181d [file] [log] [blame]
// SPDX-License-Identifier: GPL-2.0-only
// Copyright(c) 2017-2021 Intel Corporation
#include <linux/bitfield.h>
#include <linux/device.h>
#include <linux/iopoll.h>
#include <uapi/misc/intel/gna.h>
#include "device.h"
#include "hw.h"
int gna_parse_hw_status(struct gna_private *gna_priv, u32 hw_status)
{
if (hw_status & GNA_ERROR) {
dev_dbg(gna_dev(gna_priv), "GNA completed with errors: %#x\n", hw_status);
return -EIO;
}
if (hw_status & GNA_STS_SCORE_COMPLETED) {
dev_dbg(gna_dev(gna_priv), "GNA completed successfully: %#x\n", hw_status);
return 0;
}
dev_err(gna_dev(gna_priv), "GNA not completed, status: %#x\n", hw_status);
return -ENODATA;
}
void gna_print_error_status(struct gna_private *gna_priv, u32 hw_status)
{
if (hw_status & GNA_STS_PARAM_OOR)
dev_dbg(gna_dev(gna_priv), "GNA error: Param Out Range Error\n");
if (hw_status & GNA_STS_VA_OOR)
dev_dbg(gna_dev(gna_priv), "GNA error: VA Out of Range Error\n");
if (hw_status & GNA_STS_PCI_MMU_ERR)
dev_dbg(gna_dev(gna_priv), "GNA error: PCI MMU Error\n");
if (hw_status & GNA_STS_PCI_DMA_ERR)
dev_dbg(gna_dev(gna_priv), "GNA error: PCI MMU Error\n");
if (hw_status & GNA_STS_PCI_UNEXCOMPL_ERR)
dev_dbg(gna_dev(gna_priv), "GNA error: PCI Unexpected Completion Error\n");
if (hw_status & GNA_STS_SATURATE)
dev_dbg(gna_dev(gna_priv), "GNA error: Saturation Reached !\n");
}
bool gna_hw_perf_enabled(struct gna_private *gna_priv)
{
u32 ctrl = gna_reg_read(gna_priv, GNA_MMIO_CTRL);
return !!FIELD_GET(GNA_CTRL_COMP_STATS_EN, ctrl);
}
void gna_start_scoring(struct gna_private *gna_priv,
struct gna_compute_cfg *compute_cfg)
{
u32 ctrl = gna_reg_read(gna_priv, GNA_MMIO_CTRL);
ctrl |= GNA_CTRL_START_ACCEL | GNA_CTRL_COMP_INT_EN | GNA_CTRL_ERR_INT_EN;
ctrl &= ~GNA_CTRL_COMP_STATS_EN;
ctrl |= FIELD_PREP(GNA_CTRL_COMP_STATS_EN,
compute_cfg->hw_perf_encoding & FIELD_MAX(GNA_CTRL_COMP_STATS_EN));
ctrl &= ~GNA_CTRL_ACTIVE_LIST_EN;
ctrl |= FIELD_PREP(GNA_CTRL_ACTIVE_LIST_EN,
compute_cfg->active_list_on & FIELD_MAX(GNA_CTRL_ACTIVE_LIST_EN));
ctrl &= ~GNA_CTRL_OP_MODE;
ctrl |= FIELD_PREP(GNA_CTRL_OP_MODE,
compute_cfg->gna_mode & FIELD_MAX(GNA_CTRL_OP_MODE));
gna_reg_write(gna_priv, GNA_MMIO_CTRL, ctrl);
dev_dbg(gna_dev(gna_priv), "scoring started...\n");
}
static void gna_clear_saturation(struct gna_private *gna_priv)
{
u32 val;
val = gna_reg_read(gna_priv, GNA_MMIO_STS);
if (val & GNA_STS_SATURATE) {
dev_dbg(gna_dev(gna_priv), "saturation reached\n");
dev_dbg(gna_dev(gna_priv), "status: %#x\n", val);
val = val & GNA_STS_SATURATE;
gna_reg_write(gna_priv, GNA_MMIO_STS, val);
}
}
void gna_abort_hw(struct gna_private *gna_priv)
{
u32 val;
int ret;
/* saturation bit in the GNA status register needs
* to be explicitly cleared.
*/
gna_clear_saturation(gna_priv);
val = gna_reg_read(gna_priv, GNA_MMIO_STS);
dev_dbg(gna_dev(gna_priv), "status before abort: %#x\n", val);
val = gna_reg_read(gna_priv, GNA_MMIO_CTRL);
val |= GNA_CTRL_ABORT_CLR_ACCEL;
gna_reg_write(gna_priv, GNA_MMIO_CTRL, val);
ret = readl_poll_timeout(gna_priv->iobase + GNA_MMIO_STS, val,
!(val & 0x1),
0, 1000);
if (ret)
dev_err(gna_dev(gna_priv), "abort did not complete\n");
}