On Wed, Mar 24, 2021 at 8:38 PM Maciej Kwapulinski <maciej.kwapulinski@xxxxxxxxxxxxxxx> wrote: > > From: Tomasz Jankowski <tomasz1.jankowski@xxxxxxxxx> > > Add definitions and utilities to interact with the hardware > device. > > Signed-off-by: Tomasz Jankowski <tomasz1.jankowski@xxxxxxxxx> > Tested-by: Savo Novakovic <savox.novakovic@xxxxxxxxx> > Co-developed-by: Jianxun Zhang <jianxun.zhang@xxxxxxxxxxxxxxx> > Signed-off-by: Jianxun Zhang <jianxun.zhang@xxxxxxxxxxxxxxx> > Co-developed-by: Maciej Kwapulinski <maciej.kwapulinski@xxxxxxxxxxxxxxx> > Signed-off-by: Maciej Kwapulinski <maciej.kwapulinski@xxxxxxxxxxxxxxx> > --- > drivers/misc/intel/gna/Kbuild | 2 +- > drivers/misc/intel/gna/gna_device.h | 4 + > drivers/misc/intel/gna/gna_hw.c | 125 ++++++++++++++++++++++++++++ > drivers/misc/intel/gna/gna_hw.h | 62 ++++++++++++++ > 4 files changed, 192 insertions(+), 1 deletion(-) > create mode 100644 drivers/misc/intel/gna/gna_hw.c > create mode 100644 drivers/misc/intel/gna/gna_hw.h > > diff --git a/drivers/misc/intel/gna/Kbuild b/drivers/misc/intel/gna/Kbuild > index 5d3becc71683..0cf083bb211a 100644 > --- a/drivers/misc/intel/gna/Kbuild > +++ b/drivers/misc/intel/gna/Kbuild > @@ -1,5 +1,5 @@ > # SPDX-License-Identifier: GPL-2.0-only > > -intel_gna-y := gna_device.o gna_driver.o > +intel_gna-y := gna_device.o gna_driver.o gna_hw.o > > obj-$(CONFIG_INTEL_GNA) += intel_gna.o > diff --git a/drivers/misc/intel/gna/gna_device.h b/drivers/misc/intel/gna/gna_device.h > index d0b47f75f47f..39dc03d53feb 100644 > --- a/drivers/misc/intel/gna/gna_device.h > +++ b/drivers/misc/intel/gna/gna_device.h > @@ -6,6 +6,8 @@ > > #include <linux/types.h> > > +#include "gna_hw.h" > + > struct gna_driver_private; > struct pci_device_id; > struct pci_dev; > @@ -17,6 +19,8 @@ struct gna_drv_info { > u32 num_page_entries; > u32 max_layer_count; > u64 max_hw_mem; > + > + struct gna_desc_info desc_info; > }; > > struct gna_private { > diff --git a/drivers/misc/intel/gna/gna_hw.c b/drivers/misc/intel/gna/gna_hw.c > new file mode 100644 > index 000000000000..7d2f4ef00136 > --- /dev/null > +++ b/drivers/misc/intel/gna/gna_hw.c > @@ -0,0 +1,125 @@ > +// SPDX-License-Identifier: GPL-2.0-only > +// Copyright(c) 2017-2021 Intel Corporation > + > +#include <linux/pci.h> > + > +#include <uapi/misc/intel/gna.h> > + > +#include "gna_device.h" > +#include "gna_driver.h" > +#include "gna_hw.h" > + > +int gna_parse_hw_status(struct gna_private *gna_priv, u32 hw_status) > +{ > + int status; Redundant. See below. > + > + if (hw_status & GNA_ERROR) { > + dev_dbg(&gna_priv->pdev->dev, "GNA completed with errors: %#x\n", hw_status); Exactly my point, you need only one struct device, w/o these tricks. > + status = -EIO; return -EIO; > + } else if (hw_status & GNA_STS_SCORE_COMPLETED) { ...drop else > + status = 0; > + dev_dbg(&gna_priv->pdev->dev, "GNA completed successfully: %#x\n", hw_status); > + } else { > + dev_err(&gna_priv->pdev->dev, "GNA not completed, status: %#x\n", hw_status); > + status = -ENODATA; > + } > + > + return status; As above. > +} > + > +void gna_print_error_status(struct gna_private *gna_priv, u32 hw_status) > +{ > + if (hw_status & GNA_STS_PARAM_OOR) > + dev_dbg(&gna_priv->pdev->dev, "GNA error: Param Out Range Error\n"); > + > + if (hw_status & GNA_STS_VA_OOR) > + dev_dbg(&gna_priv->pdev->dev, "GNA error: VA Out of Range Error\n"); > + > + if (hw_status & GNA_STS_PCI_MMU_ERR) > + dev_dbg(&gna_priv->pdev->dev, "GNA error: PCI MMU Error\n"); > + > + if (hw_status & GNA_STS_PCI_DMA_ERR) > + dev_dbg(&gna_priv->pdev->dev, "GNA error: PCI MMU Error\n"); > + > + if (hw_status & GNA_STS_PCI_UNEXCOMPL_ERR) > + dev_dbg(&gna_priv->pdev->dev, "GNA error: PCI Unexpected Completion Error\n"); > + > + if (hw_status & GNA_STS_SATURATE) > + dev_dbg(&gna_priv->pdev->dev, "GNA error: Saturation Reached !\n"); > +} > + > +bool gna_hw_perf_enabled(struct gna_private *gna_priv) > +{ > + void __iomem *addr = gna_priv->bar0_base; > + u32 ctrl = gna_reg_read(addr, GNA_MMIO_CTRL); If you want to have better helpers, supply priv directly to them. Look into other (recent enough) drivers in the kernel how they do it. Ditto for all cases. > + return FIELD_GET(GNA_CTRL_COMP_STATS_EN, ctrl) ? true : false; Missed bitfield.h. Redundant ternary. Use !! > +} > + > +void gna_start_scoring(struct gna_private *gna_priv, void __iomem *addr, > + struct gna_compute_cfg *compute_cfg) > +{ > + u32 ctrl = gna_reg_read(addr, 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(addr, GNA_MMIO_CTRL, ctrl); > + > + dev_dbg(&gna_priv->pdev->dev, "scoring started...\n"); > +} > + > +static void gna_clear_saturation(struct gna_private *gna_priv) > +{ > + void __iomem *addr = gna_priv->bar0_base; > + u32 val; > + > + val = gna_reg_read(addr, GNA_MMIO_STS); > + if (val & GNA_STS_SATURATE) { > + dev_dbg(&gna_priv->pdev->dev, "saturation reached\n"); > + dev_dbg(&gna_priv->pdev->dev, "status: %#x\n", val); > + > + val = val & GNA_STS_SATURATE; > + gna_reg_write(addr, GNA_MMIO_STS, val); > + } > +} > + > +void gna_abort_hw(struct gna_private *gna_priv) > +{ > + void __iomem *addr = gna_priv->bar0_base; > + u32 val; > + int i; unsigned. > + /* saturation bit in the GNA status register needs > + * to be explicitly cleared. > + */ > + gna_clear_saturation(gna_priv); > + > + val = gna_reg_read(addr, GNA_MMIO_STS); > + dev_dbg(&gna_priv->pdev->dev, "status before abort: %#x\n", val); > + > + val = gna_reg_read(addr, GNA_MMIO_CTRL); > + val |= GNA_CTRL_ABORT_CLR_ACCEL; > + gna_reg_write(addr, GNA_MMIO_CTRL, val); > + > + i = 100; > + do { > + val = gna_reg_read(addr, GNA_MMIO_STS); > + if ((val & 0x1) == 0) > + break; > + } while (--i); NIH or readx_poll_timeout() from iopoll.h. > + if (i == 0) > + dev_err(&gna_priv->pdev->dev, "abort did not complete\n"); > +} > diff --git a/drivers/misc/intel/gna/gna_hw.h b/drivers/misc/intel/gna/gna_hw.h > new file mode 100644 > index 000000000000..dd682f95094e > --- /dev/null > +++ b/drivers/misc/intel/gna/gna_hw.h > @@ -0,0 +1,62 @@ > +/* SPDX-License-Identifier: GPL-2.0-only */ > +/* Copyright(c) 2017-2021 Intel Corporation */ > + > +#ifndef __GNA_HW_H__ > +#define __GNA_HW_H__ > + > +#include <linux/bits.h> > +#include <linux/bitfield.h> No user of it here. > +#include <linux/interrupt.h> Ditto. > +#include <linux/io.h> > +/* GNA MMIO registers */ > +#define GNA_MMIO_STS 0x80 > +#define GNA_MMIO_CTRL 0x84 > +#define GNA_MMIO_PTC 0x8C > +#define GNA_MMIO_PSC 0x90 > +#define GNA_MMIO_DESBASE 0xB0 > +#define GNA_MMIO_IBUFFS 0xB4 > + > +#define GNA_PT_ENTRY_SIZE 4 > +/* there are up to 1024 32-bit pointers in one page in Page Table (L1) */ > +#define GNA_PT_LENGTH (PAGE_SIZE / GNA_PT_ENTRY_SIZE) Missed header for PAGE_SIZE. > +#define GNA_PGDIRN_LEN 64 > +#define GNA_PGDIR_ENTRIES 1024 /* 32-bit page addresses */ > +#define GNA_PGDIR_INVALID 1 > + > +#define GNA_CTRL_START_ACCEL BIT(0) > +#define GNA_CTRL_ACTIVE_LIST_EN BIT(1) > +#define GNA_CTRL_ABORT_CLR_ACCEL BIT(2) > +#define GNA_CTRL_OP_MODE GENMASK(6, 5) > +#define GNA_CTRL_COMP_INT_EN BIT(8) > +#define GNA_CTRL_ERR_INT_EN BIT(10) > +#define GNA_CTRL_COMP_STATS_EN GENMASK(15, 12) > + > +struct gna_mmu_info { > + u32 vamax_size; > + u32 rsvd_size; > + u32 pd_size; > +}; Missed types.h. > +struct gna_desc_info { > + u32 rsvd_size; > + u32 cfg_size; > + u32 desc_size; > + struct gna_mmu_info mmu_info; > +}; > + > +struct gna_private; > +struct gna_compute_cfg; > + > +void gna_abort_hw(struct gna_private *gna_priv); > +bool gna_hw_perf_enabled(struct gna_private *gna_priv); > +int gna_parse_hw_status(struct gna_private *gna_priv, u32 hw_status); > +void gna_print_error_status(struct gna_private *gna_priv, u32 hw_status); > +void gna_start_scoring(struct gna_private *gna_priv, void __iomem *addr, Missed header for __iomem (but I guess it's guaranteed to be included by types.h, double check this). > + struct gna_compute_cfg *compute_cfg); > + > +#define gna_reg_read(addr, offset) readl((addr) + (offset)) > +#define gna_reg_write(addr, offset, value) writel((value), (addr) + (offset)) No point And make them functions, not macros. > + > +#endif // __GNA_HW_H__ > -- > 2.28.0 > -- With Best Regards, Andy Shevchenko