Re: [PATCH v2 01/13] intel_gna: add driver module
Andy Shevchenko writes: > On Wed, Mar 24, 2021 at 8:38 PM Maciej Kwapulinski > wrote: >> >> diff --git a/include/uapi/misc/intel/gna.h b/include/uapi/misc/intel/gna.h >> new file mode 100644 >> index ..a7e435b74a0a >> --- /dev/null >> +++ b/include/uapi/misc/intel/gna.h >> @@ -0,0 +1,155 @@ >> +/* SPDX-License-Identifier: GPL-2.0-only WITH Linux-syscall-note */ >> +/* Copyright(c) 2017-2021 Intel Corporation */ >> + >> +#ifndef _UAPI_GNA_H_ >> +#define _UAPI_GNA_H_ >> + >> +#if defined(__cplusplus) >> +extern "C" { >> +#endif > >> +#include >> +#include >> +#include > > Ordered? > What do You mean? >> .. >> +struct gna_compute_cfg { >> + __u32 layer_base; >> + __u32 layer_count; >> + >> + /* List of GNA memory buffers */ >> + __u64 buffers_ptr; >> + __u64 buffer_count; >> + >> + __u8 active_list_on; >> + __u8 gna_mode; >> + __u8 hw_perf_encoding; >> + __u8 pad[5]; >> +}; >> + >> +union gna_parameter { >> + struct { >> + __u64 id; >> + } in; >> + >> + struct { >> + __u64 value; >> + } out; >> +}; >> + >> +union gna_memory_map { >> + struct { >> + __u64 address; >> + __u32 size; >> + __u32 pad; >> + } in; >> + >> + struct { >> + __u64 memory_id; >> + } out; >> +}; >> + >> +union gna_compute { >> + struct { >> + struct gna_compute_cfg config; >> + } in; >> + >> + struct { >> + __u64 request_id; >> + } out; >> +}; >> + >> +union gna_wait { >> + struct { >> + __u64 request_id; >> + __u32 timeout; >> + __u32 pad; >> + } in; >> + >> + struct { >> + __u32 hw_status; >> + __u32 pad; >> + struct gna_drv_perf drv_perf; >> + struct gna_hw_perf hw_perf; >> + } out; >> +}; > > For all unions: > How do you know which branch is used (out, in)? What field and where > in the ABI points to that? each of the unions above plays the role of in/out argument to its corresponding ioctl call. 'in' part is used when ioctl() is called by client (userland application) - data is written by app. 'out' part is read by app on exit from ioctl(), but only when ioctl() retuns 0. do You suggest adding the comment to gna.h for the above? > .
Re: [PATCH v2 02/13] intel_gna: add component of hardware operation
Andy Shevchenko writes: > On Wed, Mar 24, 2021 at 8:38 PM Maciej Kwapulinski > wrote: >> +#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 >> Andy, Thank You for all Your comments on these two patches. I'm starting to work with them. Just as with v1 patch series, I'll get back to You in case of any questions Regards, Maciej
[PATCH v2 12/13] intel_gna: add a 'misc' device
The new 'misc' device is the node for applications in user space to interact with the driver. Signed-off-by: Maciej Kwapulinski Tested-by: Savo Novakovic --- drivers/misc/intel/gna/gna_device.c | 69 ++-- drivers/misc/intel/gna/gna_device.h | 6 +++ drivers/misc/intel/gna/gna_driver.c | 2 + drivers/misc/intel/gna/gna_driver.h | 2 + drivers/misc/intel/gna/gna_hw.c | 28 +-- drivers/misc/intel/gna/gna_ioctl.c | 36 +++ drivers/misc/intel/gna/gna_mem.c | 32 ++--- drivers/misc/intel/gna/gna_request.c | 32 ++--- drivers/misc/intel/gna/gna_score.c | 28 +-- 9 files changed, 154 insertions(+), 81 deletions(-) diff --git a/drivers/misc/intel/gna/gna_device.c b/drivers/misc/intel/gna/gna_device.c index d8e1d4b8a9eb..3f7f4c07d1a1 100644 --- a/drivers/misc/intel/gna/gna_device.c +++ b/drivers/misc/intel/gna/gna_device.c @@ -91,9 +91,57 @@ const struct pci_device_id gna_pci_ids[] = { MODULE_DEVICE_TABLE(pci, gna_pci_ids); +static int gna_open(struct inode *inode, struct file *f) +{ + return -EPERM; +} + +static const struct file_operations gna_file_ops = { + .owner = THIS_MODULE, + .open = gna_open, +}; + +static void gna_dev_release(struct gna_private *gna_priv) +{ + misc_deregister(&gna_priv->misc); + kfree(gna_priv->misc.name); + gna_priv->misc.name = NULL; +} + +static int gna_dev_create(struct gna_private *gna_priv, char *gna_name) +{ + struct pci_dev *pcidev; + int ret; + + pcidev = gna_priv->pdev; + + gna_priv->misc.minor = MISC_DYNAMIC_MINOR; + gna_priv->misc.name = kasprintf(GFP_KERNEL, "%s", gna_name); + gna_priv->misc.fops = &gna_file_ops; + gna_priv->misc.parent = &pcidev->dev; + gna_priv->misc.mode = 0666; + + dev_dbg(&pcidev->dev, "registering device: %s\n", + gna_priv->misc.name); + + ret = misc_register(&gna_priv->misc); + if (ret) { + dev_err(&pcidev->dev, "misc_register %s failed: %d\n", + gna_name, ret); + misc_deregister(&gna_priv->misc); + kfree(gna_priv->misc.name); + gna_priv->misc.name = NULL; + } + + return ret; +} + + static int gna_dev_init(struct gna_private *gna_priv, struct pci_dev *pcidev, const struct pci_device_id *pci_id) { + // strlen(GNA_DV_NAME) + max minor number. + char gna_name[sizeof(GNA_DV_NAME) + sizeof("255") + 1]; u32 bld_reg; int ret; @@ -104,6 +152,8 @@ static int gna_dev_init(struct gna_private *gna_priv, struct pci_dev *pcidev, gna_priv->info = *(struct gna_drv_info *)pci_id->driver_data; gna_priv->drv_priv = &gna_drv_priv; + gna_priv->index = atomic_inc_return(&gna_priv->drv_priv->dev_last_idx); + bld_reg = gna_reg_read(gna_priv->bar0_base, GNA_MMIO_IBUFFS); gna_priv->hw_info.in_buf_s = bld_reg & GENMASK(7, 0); @@ -134,15 +184,26 @@ static int gna_dev_init(struct gna_private *gna_priv, struct pci_dev *pcidev, init_waitqueue_head(&gna_priv->dev_busy_waitq); - gna_priv->request_wq = create_singlethread_workqueue(GNA_DV_NAME); + snprintf(gna_name, sizeof(gna_name), "%s%d", GNA_DV_NAME, gna_priv->index); + + gna_priv->request_wq = create_singlethread_workqueue(gna_name); if (!gna_priv->request_wq) { - dev_err(&pcidev->dev, "could not create %s workqueue\n", GNA_DV_NAME); + dev_err(&pcidev->dev, "could not create %s workqueue\n", gna_name); ret = -EFAULT; goto err_pci_drvdata_unset; } + ret = gna_dev_create(gna_priv, gna_name); + if (ret) { + dev_err(&pcidev->dev, "could not create %s device\n", GNA_DV_NAME); + goto err_del_wq; + } + return 0; +err_del_wq: + destroy_workqueue(gna_priv->request_wq); + err_pci_drvdata_unset: pci_set_drvdata(pcidev, NULL); @@ -151,6 +212,8 @@ static int gna_dev_init(struct gna_private *gna_priv, struct pci_dev *pcidev, static void gna_dev_deinit(struct gna_private *gna_priv) { + gna_dev_release(gna_priv); + flush_workqueue(gna_priv->request_wq); destroy_workqueue(gna_priv->request_wq); @@ -300,7 +363,7 @@ int gna_getparam(struct gna_private *gna_priv, union gna_parameter *param) param->out.value = gna_device_type_by_hwid(gna_priv->info.hwid); break; default: - dev_err(&gna_priv->pdev->dev, "unknown parameter id %llu\n", param->in.id); + dev_err(gna_p
[PATCH v2 13/13] intel_gna: add file operations to a 'misc' device
From: Tomasz Jankowski Signed-off-by: Tomasz Jankowski Tested-by: Savo Novakovic Co-developed-by: Jianxun Zhang Signed-off-by: Jianxun Zhang Co-developed-by: Maciej Kwapulinski Signed-off-by: Maciej Kwapulinski --- drivers/misc/intel/gna/gna_device.c | 60 - 1 file changed, 59 insertions(+), 1 deletion(-) diff --git a/drivers/misc/intel/gna/gna_device.c b/drivers/misc/intel/gna/gna_device.c index 3f7f4c07d1a1..3f74a0a3bd30 100644 --- a/drivers/misc/intel/gna/gna_device.c +++ b/drivers/misc/intel/gna/gna_device.c @@ -93,12 +93,70 @@ MODULE_DEVICE_TABLE(pci, gna_pci_ids); static int gna_open(struct inode *inode, struct file *f) { - return -EPERM; + struct gna_file_private *file_priv; + struct gna_private *gna_priv; + + gna_priv = container_of(f->private_data, struct gna_private, misc); + + file_priv = kzalloc(sizeof(*file_priv), GFP_KERNEL); + if (!file_priv) + return -ENOMEM; + + file_priv->fd = f; + file_priv->gna_priv = gna_priv; + + mutex_init(&file_priv->memlist_lock); + INIT_LIST_HEAD(&file_priv->memory_list); + + mutex_lock(&gna_priv->flist_lock); + list_add_tail(&file_priv->flist, &gna_priv->file_list); + mutex_unlock(&gna_priv->flist_lock); + + f->private_data = file_priv; + + return 0; +} + +static int gna_release(struct inode *inode, struct file *f) +{ + struct gna_file_private *iter_file, *temp_file; + struct gna_memory_object *iter_mo, *temp_mo; + struct gna_file_private *file_priv; + struct gna_private *gna_priv; + + /* free all memory objects created by that file */ + file_priv = (struct gna_file_private *)f->private_data; + gna_priv = file_priv->gna_priv; + + mutex_lock(&file_priv->memlist_lock); + list_for_each_entry_safe(iter_mo, temp_mo, &file_priv->memory_list, file_mem_list) { + queue_work(gna_priv->request_wq, &iter_mo->work); + wait_event(iter_mo->waitq, true); + gna_memory_free(gna_priv, iter_mo); + } + mutex_unlock(&file_priv->memlist_lock); + + gna_delete_file_requests(f, gna_priv); + + mutex_lock(&gna_priv->flist_lock); + list_for_each_entry_safe(iter_file, temp_file, &gna_priv->file_list, flist) { + if (iter_file->fd == f) { + list_del(&iter_file->flist); + f->private_data = NULL; + kfree(iter_file); + break; + } + } + mutex_unlock(&gna_priv->flist_lock); + + return 0; } static const struct file_operations gna_file_ops = { .owner = THIS_MODULE, .open = gna_open, + .release= gna_release, + .unlocked_ioctl = gna_ioctl, }; static void gna_dev_release(struct gna_private *gna_priv) -- 2.28.0
[PATCH v2 09/13] intel_gna: add a work queue to process scoring requests
From: Tomasz Jankowski The new workqueue is responsible to process the list of requests in a FIFO manner. It waits for the hardware to complete on every request until it is woken up by an interrupt that will be addressed in following changes. Signed-off-by: Tomasz Jankowski Tested-by: Savo Novakovic Co-developed-by: Anisha Dattatraya Kulkarni Signed-off-by: Anisha Dattatraya Kulkarni Co-developed-by: Jianxun Zhang Signed-off-by: Jianxun Zhang Co-developed-by: Maciej Kwapulinski Signed-off-by: Maciej Kwapulinski --- drivers/misc/intel/gna/gna_device.c | 12 +++ drivers/misc/intel/gna/gna_device.h | 8 ++ drivers/misc/intel/gna/gna_request.c | 116 +++ drivers/misc/intel/gna/gna_request.h | 1 + 4 files changed, 137 insertions(+) diff --git a/drivers/misc/intel/gna/gna_device.c b/drivers/misc/intel/gna/gna_device.c index e1a1f3142684..47f238677bc9 100644 --- a/drivers/misc/intel/gna/gna_device.c +++ b/drivers/misc/intel/gna/gna_device.c @@ -127,6 +127,15 @@ static int gna_dev_init(struct gna_private *gna_priv, struct pci_dev *pcidev, mutex_init(&gna_priv->reqlist_lock); INIT_LIST_HEAD(&gna_priv->request_list); + init_waitqueue_head(&gna_priv->dev_busy_waitq); + + gna_priv->request_wq = create_singlethread_workqueue(GNA_DV_NAME); + if (!gna_priv->request_wq) { + dev_err(&pcidev->dev, "could not create %s workqueue\n", GNA_DV_NAME); + ret = -EFAULT; + goto err_pci_drvdata_unset; + } + return 0; err_pci_drvdata_unset: @@ -137,6 +146,9 @@ static int gna_dev_init(struct gna_private *gna_priv, struct pci_dev *pcidev, static void gna_dev_deinit(struct gna_private *gna_priv) { + flush_workqueue(gna_priv->request_wq); + destroy_workqueue(gna_priv->request_wq); + idr_destroy(&gna_priv->memory_idr); gna_mmu_free(gna_priv); } diff --git a/drivers/misc/intel/gna/gna_device.h b/drivers/misc/intel/gna/gna_device.h index 878a972ab5b3..23eae806f96d 100644 --- a/drivers/misc/intel/gna/gna_device.h +++ b/drivers/misc/intel/gna/gna_device.h @@ -14,6 +14,7 @@ #include "gna_mem.h" struct gna_driver_private; +struct workqueue_struct; struct device; struct gna_drv_info { @@ -42,6 +43,8 @@ struct gna_private { /* pdev->dev */ struct device *parent; + u32 hw_status; + /* device related resources */ void __iomem *bar0_base; struct gna_drv_info info; @@ -50,9 +53,14 @@ struct gna_private { struct gna_mmu_object mmu; struct mutex mmu_lock; + /* if true, then gna device is processing */ + bool dev_busy; + struct wait_queue_head dev_busy_waitq; + struct list_head request_list; /* protects request_list */ struct mutex reqlist_lock; + struct workqueue_struct *request_wq; atomic_t request_count; /* memory objects' store */ diff --git a/drivers/misc/intel/gna/gna_request.c b/drivers/misc/intel/gna/gna_request.c index 383871eaebab..ba9bac358270 100644 --- a/drivers/misc/intel/gna/gna_request.c +++ b/drivers/misc/intel/gna/gna_request.c @@ -8,7 +8,118 @@ #include "gna_device.h" #include "gna_driver.h" +#include "gna_hw.h" #include "gna_request.h" +#include "gna_score.h" + +static void gna_request_update_status(struct gna_request *score_request) +{ + struct gna_private *gna_priv = score_request->gna_priv; + void __iomem *addr = gna_priv->bar0_base; + /* The gna_priv's hw_status should be updated first */ + u32 hw_status = gna_priv->hw_status; + u32 stall_cycles; + u32 total_cycles; + + /* Technically, the time stamp can be a bit later than +* when the hw actually completed scoring. Here we just +* do our best in a deferred work, unless we want to +* tax isr for a more accurate record. +*/ + score_request->drv_perf.hw_completed = ktime_get_ns(); + + score_request->hw_status = hw_status; + + score_request->status = gna_parse_hw_status(gna_priv, hw_status); + + if (gna_hw_perf_enabled(gna_priv)) { + if (hw_status & GNA_STS_STATISTICS_VALID) { + total_cycles = gna_reg_read(addr, GNA_MMIO_PTC); + stall_cycles = gna_reg_read(addr, GNA_MMIO_PSC); + score_request->hw_perf.total = total_cycles; + score_request->hw_perf.stall = stall_cycles; + } else + dev_warn(&gna_priv->pdev->dev, "GNA statistics missing\n"); + } + if (unlikely(hw_status & GNA_ERROR)) + gna_print_error_status(gna_priv, hw_status); +} + +static void gna_request_process(struct work_struct *work) +{ + struct gna_request *score_
[PATCH v2 11/13] intel_gna: add ioctl handler
From: Tomasz Jankowski Add ioctl handler into GNA driver. The ioctl interface provides the ability to do the following: - Map and unmap memory buffers for GNA computation requests. - Retrieve capabilities of the underlying GNA IP. - Submit GNA computation requests. - Request notification of scoring completion. Signed-off-by: Tomasz Jankowski Tested-by: Savo Novakovic Co-developed-by: Jianxun Zhang Signed-off-by: Jianxun Zhang Co-developed-by: Maciej Kwapulinski Signed-off-by: Maciej Kwapulinski --- drivers/misc/intel/gna/Kbuild | 2 +- drivers/misc/intel/gna/gna_device.c | 44 + drivers/misc/intel/gna/gna_device.h | 3 + drivers/misc/intel/gna/gna_ioctl.c | 249 drivers/misc/intel/gna/gna_ioctl.h | 11 ++ 5 files changed, 308 insertions(+), 1 deletion(-) create mode 100644 drivers/misc/intel/gna/gna_ioctl.c create mode 100644 drivers/misc/intel/gna/gna_ioctl.h diff --git a/drivers/misc/intel/gna/Kbuild b/drivers/misc/intel/gna/Kbuild index 9dac467839c9..879cc76204c3 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 gna_mem.o gna_request.o gna_score.o gna_hw.o +intel_gna-y := gna_device.o gna_driver.o gna_mem.o gna_ioctl.o gna_request.o gna_score.o gna_hw.o obj-$(CONFIG_INTEL_GNA) += intel_gna.o diff --git a/drivers/misc/intel/gna/gna_device.c b/drivers/misc/intel/gna/gna_device.c index 67917106a262..d8e1d4b8a9eb 100644 --- a/drivers/misc/intel/gna/gna_device.c +++ b/drivers/misc/intel/gna/gna_device.c @@ -5,8 +5,12 @@ #include #include +#include + #include "gna_device.h" #include "gna_driver.h" +#include "gna_hw.h" +#include "gna_ioctl.h" #include "gna_request.h" #define GNA_DEV_HWID_CNL 0x5A11 @@ -262,3 +266,43 @@ void gna_remove(struct pci_dev *pcidev) pci_free_irq_vectors(pcidev); } + +static u32 gna_device_type_by_hwid(u32 hwid) +{ + switch (hwid) { + case GNA_DEV_HWID_CNL: + return GNA_DEV_TYPE_0_9; + case GNA_DEV_HWID_GLK: + case GNA_DEV_HWID_EHL: + case GNA_DEV_HWID_ICL: + return GNA_DEV_TYPE_1_0; + case GNA_DEV_HWID_JSL: + case GNA_DEV_HWID_TGL: + return GNA_DEV_TYPE_2_0; + default: + return 0; + } +} + +int gna_getparam(struct gna_private *gna_priv, union gna_parameter *param) +{ + switch (param->in.id) { + case GNA_PARAM_DEVICE_ID: + param->out.value = gna_priv->info.hwid; + break; + case GNA_PARAM_RECOVERY_TIMEOUT: + param->out.value = jiffies_to_msecs(gna_priv->drv_priv->recovery_timeout_jiffies) / 1000; + break; + case GNA_PARAM_INPUT_BUFFER_S: + param->out.value = gna_priv->hw_info.in_buf_s; + break; + case GNA_PARAM_DEVICE_TYPE: + param->out.value = gna_device_type_by_hwid(gna_priv->info.hwid); + break; + default: + dev_err(&gna_priv->pdev->dev, "unknown parameter id %llu\n", param->in.id); + return -EINVAL; + } + + return 0; +} diff --git a/drivers/misc/intel/gna/gna_device.h b/drivers/misc/intel/gna/gna_device.h index 7ba25f6f8492..aa7fadcf93b1 100644 --- a/drivers/misc/intel/gna/gna_device.h +++ b/drivers/misc/intel/gna/gna_device.h @@ -15,6 +15,7 @@ struct gna_driver_private; struct workqueue_struct; +union gna_parameter; struct device; struct gna_drv_info { @@ -77,4 +78,6 @@ int gna_probe(struct pci_dev *dev, const struct pci_device_id *id); void gna_remove(struct pci_dev *dev); +int gna_getparam(struct gna_private *gna_priv, union gna_parameter *param); + #endif /* __GNA_DEVICE_H__ */ diff --git a/drivers/misc/intel/gna/gna_ioctl.c b/drivers/misc/intel/gna/gna_ioctl.c new file mode 100644 index ..79ce3aeb27cf --- /dev/null +++ b/drivers/misc/intel/gna/gna_ioctl.c @@ -0,0 +1,249 @@ +// SPDX-License-Identifier: GPL-2.0-only +// Copyright(c) 2017-2021 Intel Corporation + +#include + +#include + +#include "gna_driver.h" +#include "gna_device.h" +#include "gna_ioctl.h" +#include "gna_mem.h" +#include "gna_request.h" +#include "gna_score.h" + +static int gna_ioctl_score(struct gna_file_private *file_priv, void __user *argptr) +{ + union gna_compute score_args; + struct gna_private *gna_priv; + u64 request_id; + int ret; + + gna_priv = file_priv->gna_priv; + + if (copy_from_user(&score_args, argptr, sizeof(score_args))) { + dev_err(&gna_priv->pdev->dev, "could not copy score ioctl config from user\n"); + return -EFAULT; + } + + ret = gna_validate_score_config(&sc
[PATCH v2 10/13] intel_gna: add interrupt handler
From: Tomasz Jankowski An interrupt is generated by the hardware when a scoring job is done. The interrupt handler wakes up the work queue to resume the processing on the current request. Signed-off-by: Tomasz Jankowski Tested-by: Savo Novakovic Co-developed-by: Jianxun Zhang Signed-off-by: Jianxun Zhang Co-developed-by: Maciej Kwapulinski Signed-off-by: Maciej Kwapulinski --- drivers/misc/intel/gna/gna_device.c | 45 - drivers/misc/intel/gna/gna_device.h | 2 ++ drivers/misc/intel/gna/gna_hw.h | 1 - 3 files changed, 46 insertions(+), 2 deletions(-) diff --git a/drivers/misc/intel/gna/gna_device.c b/drivers/misc/intel/gna/gna_device.c index 47f238677bc9..67917106a262 100644 --- a/drivers/misc/intel/gna/gna_device.c +++ b/drivers/misc/intel/gna/gna_device.c @@ -1,6 +1,7 @@ // SPDX-License-Identifier: GPL-2.0-only // Copyright(c) 2017-2021 Intel Corporation +#include #include #include @@ -153,6 +154,16 @@ static void gna_dev_deinit(struct gna_private *gna_priv) gna_mmu_free(gna_priv); } +static irqreturn_t gna_interrupt(int irq, void *priv) +{ + struct gna_private *gna_priv; + + gna_priv = (struct gna_private *)priv; + gna_priv->dev_busy = false; + wake_up(&gna_priv->dev_busy_waitq); + return IRQ_HANDLED; +} + int gna_probe(struct pci_dev *pcidev, const struct pci_device_id *pci_id) { struct gna_private *gna_priv; @@ -201,14 +212,42 @@ int gna_probe(struct pci_dev *pcidev, const struct pci_device_id *pci_id) pci_set_master(pcidev); + ret = pci_alloc_irq_vectors(pcidev, 1, 1, PCI_IRQ_ALL_TYPES); + if (ret < 0) + return ret; + + gna_priv->irq = pci_irq_vector(pcidev, 0); + if (unlikely(gna_priv->irq < 0)) { + dev_err(&pcidev->dev, "could not obtain irq number\n"); + ret = -EIO; + goto err_free_irq_vector; + } + + ret = request_irq(gna_priv->irq, gna_interrupt, + IRQF_SHARED, GNA_DV_NAME, gna_priv); + + if (ret) { + dev_err(&pcidev->dev, "could not register for interrupt\n"); + goto err_free_irq_vector; + } + + dev_dbg(&pcidev->dev, "irq num %d\n", gna_priv->irq); + ret = gna_dev_init(gna_priv, pcidev, pci_id); if (ret) { dev_err(&pcidev->dev, "could not initialize %s device\n", GNA_DV_NAME); - return ret; + goto err_free_irq; } return 0; + +err_free_irq: + free_irq(gna_priv->irq, gna_priv); +err_free_irq_vector: + pci_free_irq_vectors(pcidev); + + return ret; } void gna_remove(struct pci_dev *pcidev) @@ -217,5 +256,9 @@ void gna_remove(struct pci_dev *pcidev) gna_priv = pci_get_drvdata(pcidev); + free_irq(gna_priv->irq, gna_priv); + gna_dev_deinit(gna_priv); + + pci_free_irq_vectors(pcidev); } diff --git a/drivers/misc/intel/gna/gna_device.h b/drivers/misc/intel/gna/gna_device.h index 23eae806f96d..7ba25f6f8492 100644 --- a/drivers/misc/intel/gna/gna_device.h +++ b/drivers/misc/intel/gna/gna_device.h @@ -43,6 +43,8 @@ struct gna_private { /* pdev->dev */ struct device *parent; + int irq; + /* hardware status set by interrupt handler */ u32 hw_status; /* device related resources */ diff --git a/drivers/misc/intel/gna/gna_hw.h b/drivers/misc/intel/gna/gna_hw.h index dd682f95094e..904e551f4f17 100644 --- a/drivers/misc/intel/gna/gna_hw.h +++ b/drivers/misc/intel/gna/gna_hw.h @@ -6,7 +6,6 @@ #include #include -#include #include /* GNA MMIO registers */ -- 2.28.0
[PATCH v2 07/13] intel_gna: add request component
From: Tomasz Jankowski The scoring work submitted to the GNA driver is implemented as a list of requests that will be processed by the hardware. Signed-off-by: Tomasz Jankowski Tested-by: Savo Novakovic Co-developed-by: Anisha Dattatraya Kulkarni Signed-off-by: Anisha Dattatraya Kulkarni Co-developed-by: Jianxun Zhang Signed-off-by: Jianxun Zhang Co-developed-by: Maciej Kwapulinski Signed-off-by: Maciej Kwapulinski --- drivers/misc/intel/gna/Kbuild| 2 +- drivers/misc/intel/gna/gna_device.c | 6 + drivers/misc/intel/gna/gna_device.h | 6 + drivers/misc/intel/gna/gna_mem.c | 3 + drivers/misc/intel/gna/gna_request.c | 347 +++ drivers/misc/intel/gna/gna_request.h | 61 + 6 files changed, 424 insertions(+), 1 deletion(-) create mode 100644 drivers/misc/intel/gna/gna_request.c create mode 100644 drivers/misc/intel/gna/gna_request.h diff --git a/drivers/misc/intel/gna/Kbuild b/drivers/misc/intel/gna/Kbuild index e5cd953d83b2..5dbbd3f0a543 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 gna_mem.o gna_hw.o +intel_gna-y := gna_device.o gna_driver.o gna_mem.o gna_request.o gna_hw.o obj-$(CONFIG_INTEL_GNA) += intel_gna.o diff --git a/drivers/misc/intel/gna/gna_device.c b/drivers/misc/intel/gna/gna_device.c index 9838d003426f..14ce24fd18ff 100644 --- a/drivers/misc/intel/gna/gna_device.c +++ b/drivers/misc/intel/gna/gna_device.c @@ -6,6 +6,7 @@ #include "gna_device.h" #include "gna_driver.h" +#include "gna_request.h" #define GNA_DEV_HWID_CNL 0x5A11 #define GNA_DEV_HWID_EHL 0x4511 @@ -118,6 +119,11 @@ static int gna_dev_init(struct gna_private *gna_priv, struct pci_dev *pcidev, idr_init(&gna_priv->memory_idr); mutex_init(&gna_priv->memidr_lock); + atomic_set(&gna_priv->request_count, 0); + + mutex_init(&gna_priv->reqlist_lock); + INIT_LIST_HEAD(&gna_priv->request_list); + return 0; err_pci_drvdata_unset: diff --git a/drivers/misc/intel/gna/gna_device.h b/drivers/misc/intel/gna/gna_device.h index 799788d70033..b54d0ea9b9ef 100644 --- a/drivers/misc/intel/gna/gna_device.h +++ b/drivers/misc/intel/gna/gna_device.h @@ -6,6 +6,7 @@ #include #include +#include #include #include @@ -44,6 +45,11 @@ struct gna_private { struct gna_mmu_object mmu; struct mutex mmu_lock; + struct list_head request_list; + /* protects request_list */ + struct mutex reqlist_lock; + atomic_t request_count; + /* memory objects' store */ struct idr memory_idr; /* lock protecting memory_idr */ diff --git a/drivers/misc/intel/gna/gna_mem.c b/drivers/misc/intel/gna/gna_mem.c index f3828b503ff6..ce1691d68edb 100644 --- a/drivers/misc/intel/gna/gna_mem.c +++ b/drivers/misc/intel/gna/gna_mem.c @@ -17,6 +17,7 @@ #include "gna_device.h" #include "gna_driver.h" #include "gna_mem.h" +#include "gna_request.h" static void gna_mmu_init(struct gna_private *gna_priv) { @@ -392,6 +393,8 @@ static void gna_memory_release(struct work_struct *work) mo = container_of(work, struct gna_memory_object, work); + gna_delete_memory_requests(mo->memory_id, mo->gna_priv); + mo->user_ptr = NULL; wake_up_interruptible(&mo->waitq); diff --git a/drivers/misc/intel/gna/gna_request.c b/drivers/misc/intel/gna/gna_request.c new file mode 100644 index ..383871eaebab --- /dev/null +++ b/drivers/misc/intel/gna/gna_request.c @@ -0,0 +1,347 @@ +// SPDX-License-Identifier: GPL-2.0-only +// Copyright(c) 2017-2021 Intel Corporation + +#include +#include +#include +#include + +#include "gna_device.h" +#include "gna_driver.h" +#include "gna_request.h" + +static struct gna_request *gna_request_create(struct gna_file_private *file_priv, + struct gna_compute_cfg *compute_cfg) +{ + struct gna_request *score_request; + struct gna_private *gna_priv; + + gna_priv = file_priv->gna_priv; + if (IS_ERR(gna_priv)) + return NULL; + + score_request = kzalloc(sizeof(*score_request), GFP_KERNEL); + if (!score_request) + return NULL; + kref_init(&score_request->refcount); + + dev_dbg(&gna_priv->pdev->dev, "layer_base %d layer_count %d\n", + compute_cfg->layer_base, compute_cfg->layer_count); + + score_request->request_id = atomic_inc_return(&gna_priv->request_count); + score_request->compute_cfg = *compute_cfg; + score_request->fd = file_priv->fd; + score_request->gna_priv = gna_priv; + score_request->state = NEW; + init_waitqueue_he
[PATCH v2 06/13] intel_gna: add hardware ids
From: Tomasz Jankowski Add PCI ids of Intel(R) Gaussian & Neural Accelerator on supported platforms. Signed-off-by: Tomasz Jankowski Tested-by: Savo Novakovic Co-developed-by: Jianxun Zhang Signed-off-by: Jianxun Zhang Co-developed-by: Maciej Kwapulinski Signed-off-by: Maciej Kwapulinski --- drivers/misc/intel/gna/gna_device.c | 76 + drivers/misc/intel/gna/gna_device.h | 5 +- drivers/misc/intel/gna/gna_driver.c | 1 + 3 files changed, 80 insertions(+), 2 deletions(-) diff --git a/drivers/misc/intel/gna/gna_device.c b/drivers/misc/intel/gna/gna_device.c index 3d559f22ee93..9838d003426f 100644 --- a/drivers/misc/intel/gna/gna_device.c +++ b/drivers/misc/intel/gna/gna_device.c @@ -7,8 +7,84 @@ #include "gna_device.h" #include "gna_driver.h" +#define GNA_DEV_HWID_CNL 0x5A11 +#define GNA_DEV_HWID_EHL 0x4511 +#define GNA_DEV_HWID_GLK 0x3190 +#define GNA_DEV_HWID_ICL 0x8A11 +#define GNA_DEV_HWID_JSL 0x4E11 +#define GNA_DEV_HWID_TGL 0x9A11 + #define GNA_BAR0 0 +#define GNA_FEATURES \ + .max_hw_mem = 256 * 1024 * 1024, \ + .num_pagetables = 64, \ + .num_page_entries = PAGE_SIZE / sizeof(u32), \ + /* desc_info all in bytes */ \ + .desc_info = { \ + .rsvd_size = 256, \ + .cfg_size = 256, \ + .desc_size = 784, \ + .mmu_info = { \ + .vamax_size = 4, \ + .rsvd_size = 12, \ + .pd_size = 4 * 64, \ + }, \ + } + +#define GNA_GEN1_FEATURES \ + GNA_FEATURES, \ + .max_layer_count = 1024 + +#define GNA_GEN2_FEATURES \ + GNA_FEATURES, \ + .max_layer_count = 4096 + +static const struct gna_drv_info cnl_drv_info = { + .hwid = GNA_DEV_HWID_CNL, + GNA_GEN1_FEATURES +}; + +static const struct gna_drv_info glk_drv_info = { + .hwid = GNA_DEV_HWID_GLK, + GNA_GEN1_FEATURES +}; + +static const struct gna_drv_info ehl_drv_info = { + .hwid = GNA_DEV_HWID_EHL, + GNA_GEN1_FEATURES +}; + +static const struct gna_drv_info icl_drv_info = { + .hwid = GNA_DEV_HWID_ICL, + GNA_GEN1_FEATURES +}; + +static const struct gna_drv_info jsl_drv_info = { + .hwid = GNA_DEV_HWID_JSL, + GNA_GEN2_FEATURES +}; + +static const struct gna_drv_info tgl_drv_info = { + .hwid = GNA_DEV_HWID_TGL, + GNA_GEN2_FEATURES +}; + +#define INTEL_GNA_DEVICE(hwid, info) \ + { PCI_VDEVICE(INTEL, hwid), (kernel_ulong_t)(info) } + +const struct pci_device_id gna_pci_ids[] = { + INTEL_GNA_DEVICE(GNA_DEV_HWID_CNL, &cnl_drv_info), + INTEL_GNA_DEVICE(GNA_DEV_HWID_EHL, &ehl_drv_info), + INTEL_GNA_DEVICE(GNA_DEV_HWID_GLK, &glk_drv_info), + INTEL_GNA_DEVICE(GNA_DEV_HWID_ICL, &icl_drv_info), + INTEL_GNA_DEVICE(GNA_DEV_HWID_JSL, &jsl_drv_info), + INTEL_GNA_DEVICE(GNA_DEV_HWID_TGL, &tgl_drv_info), + { } +}; + +MODULE_DEVICE_TABLE(pci, gna_pci_ids); + static int gna_dev_init(struct gna_private *gna_priv, struct pci_dev *pcidev, const struct pci_device_id *pci_id) { diff --git a/drivers/misc/intel/gna/gna_device.h b/drivers/misc/intel/gna/gna_device.h index a5657ab9f62a..799788d70033 100644 --- a/drivers/misc/intel/gna/gna_device.h +++ b/drivers/misc/intel/gna/gna_device.h @@ -7,13 +7,12 @@ #include #include #include +#include #include "gna_hw.h" #include "gna_mem.h" struct gna_driver_private; -struct pci_device_id; -struct pci_dev; struct device; struct gna_drv_info { @@ -51,6 +50,8 @@ struct gna_private { struct mutex memidr_lock; }; +extern const struct pci_device_id gna_pci_ids[]; + int gna_probe(struct pci_dev *dev, const struct pci_device_id *id); void gna_remove(struct pci_dev *dev); diff --git a/drivers/misc/intel/gna/gna_driver.c b/drivers/misc/intel/gna/gna_driver.c index 79f4d8522bdc..a8f69a970f7a 100644 --- a/drivers/misc/intel/gna/gna_driver.c +++ b/drivers/misc/intel/gna/gna_driver.c @@ -16,6 +16,7 @@ struct gna_driver_private gna_drv_priv; static struct pci_driver gna_driver = { .name = GNA_DV_NAME, + .id_table = gna_pci_ids, .probe = gna_probe, .remove = gna_remove, }; -- 2.28.0
[PATCH v2 05/13] intel_gna: initialize mmu
From: Tomasz Jankowski Setup mmu in the driver with a new memory component. Signed-off-by: Tomasz Jankowski Tested-by: Savo Novakovic Co-Developed-by: Maciej Kwapulinski Signed-off-by: Maciej Kwapulinski --- drivers/misc/intel/gna/gna_device.c | 29 +++-- 1 file changed, 27 insertions(+), 2 deletions(-) diff --git a/drivers/misc/intel/gna/gna_device.c b/drivers/misc/intel/gna/gna_device.c index 25137d0ac519..3d559f22ee93 100644 --- a/drivers/misc/intel/gna/gna_device.c +++ b/drivers/misc/intel/gna/gna_device.c @@ -9,10 +9,11 @@ #define GNA_BAR0 0 -static void gna_dev_init(struct gna_private *gna_priv, struct pci_dev *pcidev, +static int gna_dev_init(struct gna_private *gna_priv, struct pci_dev *pcidev, const struct pci_device_id *pci_id) { u32 bld_reg; + int ret; pci_set_drvdata(pcidev, gna_priv); @@ -24,10 +25,29 @@ static void gna_dev_init(struct gna_private *gna_priv, struct pci_dev *pcidev, bld_reg = gna_reg_read(gna_priv->bar0_base, GNA_MMIO_IBUFFS); gna_priv->hw_info.in_buf_s = bld_reg & GENMASK(7, 0); + if (gna_mmu_alloc(gna_priv)) { + dev_err(&pcidev->dev, "mmu allocation failed\n"); + ret = -EFAULT; + goto err_pci_drvdata_unset; + + } + dev_dbg(&pcidev->dev, "maximum memory size %llu num pd %d\n", + gna_priv->info.max_hw_mem, gna_priv->info.num_pagetables); + dev_dbg(&pcidev->dev, "desc rsvd size %d mmu vamax size %d\n", + gna_priv->info.desc_info.rsvd_size, + gna_priv->info.desc_info.mmu_info.vamax_size); + mutex_init(&gna_priv->mmu_lock); idr_init(&gna_priv->memory_idr); mutex_init(&gna_priv->memidr_lock); + + return 0; + +err_pci_drvdata_unset: + pci_set_drvdata(pcidev, NULL); + + return ret; } static void gna_dev_deinit(struct gna_private *gna_priv) @@ -84,7 +104,12 @@ int gna_probe(struct pci_dev *pcidev, const struct pci_device_id *pci_id) pci_set_master(pcidev); - gna_dev_init(gna_priv, pcidev, pci_id); + ret = gna_dev_init(gna_priv, pcidev, pci_id); + if (ret) { + dev_err(&pcidev->dev, "could not initialize %s device\n", GNA_DV_NAME); + return ret; + } + return 0; } -- 2.28.0
[PATCH v2 08/13] intel_gna: implement scoring
From: Tomasz Jankowski Add a new component for scoring logic such as configuring and kicking off the hardware. Signed-off-by: Tomasz Jankowski Tested-by: Savo Novakovic Co-developed-by: Jianxun Zhang Signed-off-by: Jianxun Zhang Co-developed-by: Maciej Kwapulinski Signed-off-by: Maciej Kwapulinski --- drivers/misc/intel/gna/Kbuild | 2 +- drivers/misc/intel/gna/gna_device.c | 3 + drivers/misc/intel/gna/gna_device.h | 5 + drivers/misc/intel/gna/gna_score.c | 298 drivers/misc/intel/gna/gna_score.h | 18 ++ 5 files changed, 325 insertions(+), 1 deletion(-) create mode 100644 drivers/misc/intel/gna/gna_score.c create mode 100644 drivers/misc/intel/gna/gna_score.h diff --git a/drivers/misc/intel/gna/Kbuild b/drivers/misc/intel/gna/Kbuild index 5dbbd3f0a543..9dac467839c9 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 gna_mem.o gna_request.o gna_hw.o +intel_gna-y := gna_device.o gna_driver.o gna_mem.o gna_request.o gna_score.o gna_hw.o obj-$(CONFIG_INTEL_GNA) += intel_gna.o diff --git a/drivers/misc/intel/gna/gna_device.c b/drivers/misc/intel/gna/gna_device.c index 14ce24fd18ff..e1a1f3142684 100644 --- a/drivers/misc/intel/gna/gna_device.c +++ b/drivers/misc/intel/gna/gna_device.c @@ -119,6 +119,9 @@ static int gna_dev_init(struct gna_private *gna_priv, struct pci_dev *pcidev, idr_init(&gna_priv->memory_idr); mutex_init(&gna_priv->memidr_lock); + mutex_init(&gna_priv->flist_lock); + INIT_LIST_HEAD(&gna_priv->file_list); + atomic_set(&gna_priv->request_count, 0); mutex_init(&gna_priv->reqlist_lock); diff --git a/drivers/misc/intel/gna/gna_device.h b/drivers/misc/intel/gna/gna_device.h index b54d0ea9b9ef..878a972ab5b3 100644 --- a/drivers/misc/intel/gna/gna_device.h +++ b/drivers/misc/intel/gna/gna_device.h @@ -33,6 +33,11 @@ struct gna_hw_info { struct gna_private { struct gna_driver_private *drv_priv; + /* list of opened files */ + struct list_head file_list; + /* protects file_list */ + struct mutex flist_lock; + struct pci_dev *pdev; /* pdev->dev */ struct device *parent; diff --git a/drivers/misc/intel/gna/gna_score.c b/drivers/misc/intel/gna/gna_score.c new file mode 100644 index ..794039d2da43 --- /dev/null +++ b/drivers/misc/intel/gna/gna_score.c @@ -0,0 +1,298 @@ +// SPDX-License-Identifier: GPL-2.0-only +// Copyright(c) 2017-2021 Intel Corporation + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "gna_device.h" +#include "gna_driver.h" +#include "gna_request.h" +#include "gna_score.h" + +int gna_validate_score_config(struct gna_compute_cfg *compute_cfg, + struct gna_file_private *file_priv) +{ + struct gna_private *gna_priv; + size_t buffers_size; + + gna_priv = file_priv->gna_priv; + + if (compute_cfg->gna_mode > GNA_MODE_XNN) { + dev_err(&gna_priv->pdev->dev, "invalid mode\n"); + return -EINVAL; + } + + if (compute_cfg->layer_count > gna_priv->info.max_layer_count) { + dev_err(&gna_priv->pdev->dev, "max layer count exceeded\n"); + return -EINVAL; + } + + if (compute_cfg->buffer_count == 0) { + dev_err(&gna_priv->pdev->dev, "no buffers\n"); + return -EINVAL; + } + + buffers_size = sizeof(struct gna_buffer) * compute_cfg->buffer_count; + if (!access_ok(u64_to_user_ptr(compute_cfg->buffers_ptr), buffers_size)) { + dev_err(&gna_priv->pdev->dev, "invalid buffers pointer\n"); + return -EINVAL; + } + + return 0; +} + +static int gna_do_patch_memory(struct gna_private *gna_priv, struct gna_memory_object *mo, + struct gna_memory_patch *patch, void *vaddr) +{ + size_t size; + void *dest; + u64 value; + + value = patch->value; + size = patch->size; + dest = (u8 *)vaddr + patch->offset; + dev_dbg(&gna_priv->pdev->dev, "patch offset: %llu, size: %zu, value: %llu\n", + patch->offset, size, value); + + switch (size) { + case 0: + return -EFAULT; + case sizeof(u8): + *((u8 *)dest) = (u8)value; + break; + case sizeof(u16): + *((u16 *)dest) = (u16)value; + break; + case sizeof(u32): + *((u32 *)dest) = (u32)value; + break; + case sizeof(u64): +
[PATCH v2 04/13] intel_gna: add memory handling
From: Tomasz Jankowski Patch adds memory handling - mapping, DMA, pinning. The GNA driver maps and unmaps the physical pages for 64-byte aligned buffer allocated by user space program. The pages of mapped memory are being locked only during actual computation. Patch adds configuration of the DMA scatter gather list for physical pages and generation of page table and page directory to be programmed in the GNA HW at the time of scoring initiation. GNA’s MMU is being configured based on specific request memory usage. As the MMU can address up to 256MB a single scoring request is limited to this amount of memory being used. GNA Library can allocate any number of memory regions for GNA usage. Its number and total capacity are limited by the OSs’ resources. Due to GNA MMU restrictions, even when using multiple memory regions, the sum of all the memory regions used within a single inference request must be less than 256MB. At least a single GNA memory region is needed to be allocated (and can be shared by multiple models). At the other extreme, each GNA tensor (e.g., weights/biases/inputs/outputs) could use its own, separate GNA memory region. Signed-off-by: Tomasz Jankowski Tested-by: Savo Novakovic Co-developed-by: Jianxun Zhang Signed-off-by: Jianxun Zhang Co-developed-by: Maciej Kwapulinski Signed-off-by: Maciej Kwapulinski --- drivers/misc/intel/gna/Kbuild | 2 +- drivers/misc/intel/gna/gna_device.c | 20 ++ drivers/misc/intel/gna/gna_device.h | 13 + drivers/misc/intel/gna/gna_driver.c | 1 + drivers/misc/intel/gna/gna_driver.h | 16 + drivers/misc/intel/gna/gna_mem.c| 470 drivers/misc/intel/gna/gna_mem.h| 107 +++ 7 files changed, 628 insertions(+), 1 deletion(-) create mode 100644 drivers/misc/intel/gna/gna_mem.c create mode 100644 drivers/misc/intel/gna/gna_mem.h diff --git a/drivers/misc/intel/gna/Kbuild b/drivers/misc/intel/gna/Kbuild index 0cf083bb211a..e5cd953d83b2 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 gna_hw.o +intel_gna-y := gna_device.o gna_driver.o gna_mem.o gna_hw.o obj-$(CONFIG_INTEL_GNA) += intel_gna.o diff --git a/drivers/misc/intel/gna/gna_device.c b/drivers/misc/intel/gna/gna_device.c index 6bac481b2247..25137d0ac519 100644 --- a/drivers/misc/intel/gna/gna_device.c +++ b/drivers/misc/intel/gna/gna_device.c @@ -23,6 +23,17 @@ static void gna_dev_init(struct gna_private *gna_priv, struct pci_dev *pcidev, bld_reg = gna_reg_read(gna_priv->bar0_base, GNA_MMIO_IBUFFS); gna_priv->hw_info.in_buf_s = bld_reg & GENMASK(7, 0); + + mutex_init(&gna_priv->mmu_lock); + + idr_init(&gna_priv->memory_idr); + mutex_init(&gna_priv->memidr_lock); +} + +static void gna_dev_deinit(struct gna_private *gna_priv) +{ + idr_destroy(&gna_priv->memory_idr); + gna_mmu_free(gna_priv); } int gna_probe(struct pci_dev *pcidev, const struct pci_device_id *pci_id) @@ -77,3 +88,12 @@ int gna_probe(struct pci_dev *pcidev, const struct pci_device_id *pci_id) return 0; } + +void gna_remove(struct pci_dev *pcidev) +{ + struct gna_private *gna_priv; + + gna_priv = pci_get_drvdata(pcidev); + + gna_dev_deinit(gna_priv); +} diff --git a/drivers/misc/intel/gna/gna_device.h b/drivers/misc/intel/gna/gna_device.h index 7704eeda90f6..a5657ab9f62a 100644 --- a/drivers/misc/intel/gna/gna_device.h +++ b/drivers/misc/intel/gna/gna_device.h @@ -5,8 +5,11 @@ #define __GNA_DEVICE_H__ #include +#include +#include #include "gna_hw.h" +#include "gna_mem.h" struct gna_driver_private; struct pci_device_id; @@ -38,8 +41,18 @@ struct gna_private { void __iomem *bar0_base; struct gna_drv_info info; struct gna_hw_info hw_info; + + struct gna_mmu_object mmu; + struct mutex mmu_lock; + + /* memory objects' store */ + struct idr memory_idr; + /* lock protecting memory_idr */ + struct mutex memidr_lock; }; int gna_probe(struct pci_dev *dev, const struct pci_device_id *id); +void gna_remove(struct pci_dev *dev); + #endif /* __GNA_DEVICE_H__ */ diff --git a/drivers/misc/intel/gna/gna_driver.c b/drivers/misc/intel/gna/gna_driver.c index f4922a388be7..79f4d8522bdc 100644 --- a/drivers/misc/intel/gna/gna_driver.c +++ b/drivers/misc/intel/gna/gna_driver.c @@ -17,6 +17,7 @@ struct gna_driver_private gna_drv_priv; static struct pci_driver gna_driver = { .name = GNA_DV_NAME, .probe = gna_probe, + .remove = gna_remove, }; static int __init gna_drv_init(void) diff --git a/drivers/misc/intel/gna/gna_driver.h b/drivers/misc/intel/gna/gna_driver.h index ed507ea10866..69087317d668 100644 --- a/drivers/misc/intel/gna/gna_driver.h +++ b/drivers/misc/intel/gna/gna_driver.h @@ -4,12 +4,28 @@ #ifndef __
[PATCH v2 03/13] intel_gna: read hardware info in the driver
From: Tomasz Jankowski Get the hardware information from register MMIO_IBUFFS Signed-off-by: Tomasz Jankowski Tested-by: Savo Novakovic Co-developed-by: Jianxun Zhang Signed-off-by: Jianxun Zhang Co-developed-by: Maciej Kwapulinski Signed-off-by: Maciej Kwapulinski --- drivers/misc/intel/gna/gna_device.c | 5 + drivers/misc/intel/gna/gna_device.h | 5 + 2 files changed, 10 insertions(+) diff --git a/drivers/misc/intel/gna/gna_device.c b/drivers/misc/intel/gna/gna_device.c index 431113297879..6bac481b2247 100644 --- a/drivers/misc/intel/gna/gna_device.c +++ b/drivers/misc/intel/gna/gna_device.c @@ -12,12 +12,17 @@ static void gna_dev_init(struct gna_private *gna_priv, struct pci_dev *pcidev, const struct pci_device_id *pci_id) { + u32 bld_reg; + pci_set_drvdata(pcidev, gna_priv); gna_priv->parent = &pcidev->dev; gna_priv->pdev = pcidev; gna_priv->info = *(struct gna_drv_info *)pci_id->driver_data; gna_priv->drv_priv = &gna_drv_priv; + + bld_reg = gna_reg_read(gna_priv->bar0_base, GNA_MMIO_IBUFFS); + gna_priv->hw_info.in_buf_s = bld_reg & GENMASK(7, 0); } int gna_probe(struct pci_dev *pcidev, const struct pci_device_id *pci_id) diff --git a/drivers/misc/intel/gna/gna_device.h b/drivers/misc/intel/gna/gna_device.h index 39dc03d53feb..7704eeda90f6 100644 --- a/drivers/misc/intel/gna/gna_device.h +++ b/drivers/misc/intel/gna/gna_device.h @@ -23,6 +23,10 @@ struct gna_drv_info { struct gna_desc_info desc_info; }; +struct gna_hw_info { + u8 in_buf_s; +}; + struct gna_private { struct gna_driver_private *drv_priv; @@ -33,6 +37,7 @@ struct gna_private { /* device related resources */ void __iomem *bar0_base; struct gna_drv_info info; + struct gna_hw_info hw_info; }; int gna_probe(struct pci_dev *dev, const struct pci_device_id *id); -- 2.28.0
[PATCH v2 01/13] intel_gna: add driver module
From: Tomasz Jankowski Add a new PCI driver for Intel(R) Gaussian & Neural Accelerator with basic support like module loading and unloading. The full function of the driver will be added by further changes. Signed-off-by: Tomasz Jankowski Tested-by: Savo Novakovic Co-developed-by: Jianxun Zhang Signed-off-by: Jianxun Zhang Co-developed-by: Maciej Kwapulinski Signed-off-by: Maciej Kwapulinski --- Documentation/misc-devices/index.rst | 1 + Documentation/misc-devices/intel/gna.rst | 48 ++ .../userspace-api/ioctl/ioctl-number.rst | 1 + MAINTAINERS | 7 + drivers/misc/Kconfig | 1 + drivers/misc/Makefile | 1 + drivers/misc/intel/gna/Kbuild | 5 + drivers/misc/intel/gna/Kconfig| 13 ++ drivers/misc/intel/gna/gna_device.c | 74 + drivers/misc/intel/gna/gna_device.h | 36 drivers/misc/intel/gna/gna_driver.c | 39 + drivers/misc/intel/gna/gna_driver.h | 15 ++ include/uapi/misc/intel/gna.h | 155 ++ 13 files changed, 396 insertions(+) create mode 100644 Documentation/misc-devices/intel/gna.rst create mode 100644 drivers/misc/intel/gna/Kbuild create mode 100644 drivers/misc/intel/gna/Kconfig create mode 100644 drivers/misc/intel/gna/gna_device.c create mode 100644 drivers/misc/intel/gna/gna_device.h create mode 100644 drivers/misc/intel/gna/gna_driver.c create mode 100644 drivers/misc/intel/gna/gna_driver.h create mode 100644 include/uapi/misc/intel/gna.h diff --git a/Documentation/misc-devices/index.rst b/Documentation/misc-devices/index.rst index 64420b3314fe..1b187ee121b0 100644 --- a/Documentation/misc-devices/index.rst +++ b/Documentation/misc-devices/index.rst @@ -19,6 +19,7 @@ fit into other categories. bh1770glc eeprom c2port + intel/gna ibmvmc ics932s401 isl29003 diff --git a/Documentation/misc-devices/intel/gna.rst b/Documentation/misc-devices/intel/gna.rst new file mode 100644 index ..9baeec5ceb5c --- /dev/null +++ b/Documentation/misc-devices/intel/gna.rst @@ -0,0 +1,48 @@ +.. SPDX-License-Identifier: GPL-2.0-only + += +Intel(R) Gaussian & Neural Accelerator (Intel(R) GNA) += + +Acronyms + +GNA- Gaussian & Neural Accelerator +GMM- Gaussian Mixer Model +CNN- Convolutional Neural Network +RNN- Recurrent Neural Networks +DNN- Deep Neural Networks + +Introduction + +The Intel(R) GNA is an internal PCI fixed device available on several Intel platforms/SoCs. +Feature set depends on the Intel chipset SKU. + +Intel(R) GNA provides hardware accelerated computation for GMMs and Neural Networks. +It supports several layer types: affine, recurrent, and convolutional among others. +Hardware also provides helper layer types for copying and transposing matrices. + +Linux Driver + +The driver also registers a character device to expose file operations via dev node. + +The driver probes/removes PCI device, implements file operations, handles runtime +power management, and interacts with hardware through MMIO registers. + +Multiple processes can independently file many requests to the driver. These requests are +processed in a FIFO manner. The hardware can process one request at a time by using a FIFO +queue. + +IOCTL +- +Intel(R) GNA driver controls the device through IOCTL interfaces. +Following IOCTL commands are supported: + +GNA_IOCTL_PARAM_GET gets driver and device capabilities. + +GNA_IOCTL_MEMORY_MAP locks user pages and GNA MMU setups for DMA transfer. + +GNA_IOCTL_MEMORY_UNMAP unlocks user pages and releases GNA MMU structures. + +GNA_IOCTL_COMPUTE submits a request to the device queue. + +GNA_IOCTL_WAIT blocks and waits on the submitted request. diff --git a/Documentation/userspace-api/ioctl/ioctl-number.rst b/Documentation/userspace-api/ioctl/ioctl-number.rst index a4c75a28c839..9ec2b32f656a 100644 --- a/Documentation/userspace-api/ioctl/ioctl-number.rst +++ b/Documentation/userspace-api/ioctl/ioctl-number.rst @@ -115,6 +115,7 @@ Code Seq#Include File Comments 'B' C0-FF advanced bbus <mailto:maas...@uni-freiburg.de> 'C' alllinux/soundcard.h conflict! 'C' 01-2F linux/capi.hconflict! +'C' 01-5F uapi/misc/intel/gna.h conflict! 'C' F0-FF drivers/net/wan/cosa.h conflict! 'D' allarch/s390/include/asm/dasd.h 'D' 40-5F drivers/scsi/dpt/dtpi_ioctl.h diff --git a/MAINTAINERS b/MAINTAINERS index b
[PATCH v2 02/13] intel_gna: add component of hardware operation
From: Tomasz Jankowski Add definitions and utilities to interact with the hardware device. Signed-off-by: Tomasz Jankowski Tested-by: Savo Novakovic Co-developed-by: Jianxun Zhang Signed-off-by: Jianxun Zhang Co-developed-by: Maciej Kwapulinski Signed-off-by: Maciej Kwapulinski --- 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 +#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 ..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 + +#include + +#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; + + if (hw_status & GNA_ERROR) { + dev_dbg(&gna_priv->pdev->dev, "GNA completed with errors: %#x\n", hw_status); + status = -EIO; + } else if (hw_status & GNA_STS_SCORE_COMPLETED) { + 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; +} + +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); + + return FIELD_GET(GNA_CTRL_COMP_STATS_EN, ctrl) ? true : false; +} + +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_privat
[PATCH v2 00/13] Driver of Intel(R) Gaussian & Neural Accelerator
Dear kernel maintainers, This submission is a kernel driver to support Intel(R) Gaussian & Neural Accelerator (Intel(R) GNA). Intel(R) GNA is a PCI-based neural co-processor available on multiple Intel platforms. AI developers and users can offload continuous inference workloads to an Intel(R) GNA device in order to free processor resources and save power. Noise reduction and speech recognition are the examples of the workloads Intel(R) GNA deals with while its usage is not limited to the two. For a list of processors equipped with Intel(R) GNA device, please refer to this link: https://docs.openvinotoolkit.org/latest/openvino_docs_IE_DG_supported_plugins_GNA.html We think contributing this driver to the upstream kernel project is the best way for developers and users to get the latest Intel(R) GNA support in a Linux kernel, through the mainline to any Linux distributions installed on their systems. Upstreaming also enables contribution from developers around the world to the driver once it is merged. The driver works with Intel(R) libraries in user space. The Intel(R) driver exposes a few IOCTL interfaces for use by libraries in user space. The libraries are open sourced and are available at: https://github.com/intel/gna --- Changelogs: v1->v2: - driver's new layout: - driver name: gna -> intel_gna - module name: gna -> intel_gna - device file name: /dev/gnaN -> /dev/intel_gnaN - driver's source directory: drivers/misc/gna/ -> drivers/misc/intel/gna/ - UAPI: include/uapi/misc/gna.h -> include/uapi/misc/intel/gna.h - DOC: Documentation/misc-devices/gna.rst -> Documentation/misc-devices/intel/gna.rst - 'MISC' device framework used - fixes throughout GNA device's PCI management - header files' includes and forward declarations cleanup - ISR made static - unused comments cleanup - "_priv_" segment removed from function names - tested: v5.11-rc3 -> v5.11 - number of other/minor fixes --- Maciej Kwapulinski (1): intel_gna: add a 'misc' device Tomasz Jankowski (12): intel_gna: add driver module intel_gna: add component of hardware operation intel_gna: read hardware info in the driver intel_gna: add memory handling intel_gna: initialize mmu intel_gna: add hardware ids intel_gna: add request component intel_gna: implement scoring intel_gna: add a work queue to process scoring requests intel_gna: add interrupt handler intel_gna: add ioctl handler intel_gna: add file operations to a 'misc' device Documentation/misc-devices/index.rst | 1 + Documentation/misc-devices/intel/gna.rst | 48 ++ .../userspace-api/ioctl/ioctl-number.rst | 1 + MAINTAINERS | 7 + drivers/misc/Kconfig | 1 + drivers/misc/Makefile | 1 + drivers/misc/intel/gna/Kbuild | 5 + drivers/misc/intel/gna/Kconfig| 13 + drivers/misc/intel/gna/gna_device.c | 429 drivers/misc/intel/gna/gna_device.h | 89 drivers/misc/intel/gna/gna_driver.c | 43 ++ drivers/misc/intel/gna/gna_driver.h | 33 ++ drivers/misc/intel/gna/gna_hw.c | 125 + drivers/misc/intel/gna/gna_hw.h | 61 +++ drivers/misc/intel/gna/gna_ioctl.c| 249 + drivers/misc/intel/gna/gna_ioctl.h| 11 + drivers/misc/intel/gna/gna_mem.c | 473 ++ drivers/misc/intel/gna/gna_mem.h | 107 drivers/misc/intel/gna/gna_request.c | 463 + drivers/misc/intel/gna/gna_request.h | 62 +++ drivers/misc/intel/gna/gna_score.c| 298 +++ drivers/misc/intel/gna/gna_score.h| 18 + include/uapi/misc/intel/gna.h | 155 ++ 23 files changed, 2693 insertions(+) create mode 100644 Documentation/misc-devices/intel/gna.rst create mode 100644 drivers/misc/intel/gna/Kbuild create mode 100644 drivers/misc/intel/gna/Kconfig create mode 100644 drivers/misc/intel/gna/gna_device.c create mode 100644 drivers/misc/intel/gna/gna_device.h create mode 100644 drivers/misc/intel/gna/gna_driver.c create mode 100644 drivers/misc/intel/gna/gna_driver.h create mode 100644 drivers/misc/intel/gna/gna_hw.c create mode 100644 drivers/misc/intel/gna/gna_hw.h create mode 100644 drivers/misc/intel/gna/gna_ioctl.c create mode 100644 drivers/misc/intel/gna/gna_ioctl.h create mode 100644 drivers/misc/intel/gna/gna_mem.c create mode 100644 drivers/misc/intel/gna/gna_mem.h create mode 100644 drivers/misc/intel/gna/gna_request.c create mode 100644 drivers/misc/intel/gna/gna_request.h create mode 100644 drivers/misc/intel/gna/gna_score.c create mode 100644 drivers/misc/intel/gna/gna_score.h create mode 100644 include/uapi/misc/intel/gna.h -- 2.28.0
Re: [PATCH v1 01/12] gna: add driver module
Greg Kroah-Hartman writes: > On Fri, Feb 26, 2021 at 01:59:14PM +0100, Maciej Kwapulinski wrote: >> >> Greg Kroah-Hartman writes: >> >> > On Tue, Feb 16, 2021 at 05:05:14PM +0100, Maciej Kwapulinski wrote: >> >> >> --- /dev/null >> >> +++ b/drivers/misc/gna/gna_driver.h >> >> @@ -0,0 +1,41 @@ >> >> +/* SPDX-License-Identifier: GPL-2.0-only */ >> >> +/* Copyright(c) 2017-2021 Intel Corporation */ >> >> + >> >> +#ifndef __GNA_DRIVER_H__ >> >> +#define __GNA_DRIVER_H__ >> >> + >> >> +#include >> >> +#include >> >> +#include >> >> + >> >> +#define GNA_DRV_NAME "gna" >> > >> > Way too generic, no one knows what "gna" is. >> > >> >> "intel gna" is much more verbose in search engines. >> As we do not (plan to) have more "gna" drivers, is the following ok?: >> >> intel-gna >> >> the change would imply the following: >> >> prompt$ lspci -s 00:00.3 - >> 00:00.3 System peripheral: Intel Corporation Device 3190 (rev 03) >> Subsystem: Intel Corporation Device 2072 >> >> Kernel driver in use: intel-gna >> Kernel modules: gna >> >> is it ok? > > Why not intel-gna as the kernel module as well? > >> also, how about the interface to library (it's part of one of next patches)?: >> prompt$ file /dev/gna0 >> /dev/gna0: character special (235/0) >> >> can "gna" stay intact here? > > Again, I have no idea what "gna" is, so you might want to pick something > more descriptive? > >> I'm pointing this out, because gna exists on the market for a while and >> changing the above may have some impact we'd like to avoid. > > If it exists but Linux does not support it, how would anyone know about > it? :) > > Please use real terms where possible. > > thanks, > > greg k-h summarizing gna name justification topic, is the intel_gna.ko driver's following layout within kernel code OK for You?: 1. driver/module name: prompt$ lspci -s 00:00.3 - 00:00.3 System peripheral: Intel Corporation Device 3190 (rev 03) Kernel driver in use: intel_gna Kernel modules: intel_gna 2. mv drivers/misc/gna/* drivers/misc/intel_gna/ 3. prompt$ file /dev/intel_gna0 /dev/intel_gna0: character special (10/120) # ..., /dev/intel_gna1, /dev/intel_gna2 for subsequent devices
Re: [PATCH v1 01/12] gna: add driver module
Greg Kroah-Hartman writes: > On Mon, Mar 01, 2021 at 11:39:23AM +0100, Maciej Kwapulinski wrote: >> >> Maciej Kwapulinski writes: >> >> > Greg Kroah-Hartman writes: >> > >> >> On Mon, Mar 01, 2021 at 11:18:59AM +0100, Maciej Kwapulinski wrote: >> >>> >> >>> Andy Shevchenko writes: >> >>> >> >>> > On Tue, Feb 16, 2021 at 6:11 PM Maciej Kwapulinski >> >>> > wrote: >> >>> >> >> >>> >> >>> >> +static int __init gna_drv_init(void) >> >>> >> +{ >> >>> >> + int ret; >> >>> >> + >> >>> >> + mutex_init(&gna_drv_priv.lock); >> >>> >> + >> >>> >> + gna_class = class_create(THIS_MODULE, "gna"); >> >>> >> + if (IS_ERR(gna_class)) { >> >>> >> + pr_err("class device create failed\n"); >> >>> >> + return PTR_ERR(gna_class); >> >>> >> + } >> >>> >> + gna_class->devnode = gna_devnode; >> >>> >> + >> >>> >> + ret = pci_register_driver(&gna_driver); >> >>> > >> >>> > Is it possible to decouple a PCI glue driver from the class as many >> >>> > other existing examples are doing? >> >>> > >> >>> >> >>> I see many pci drivers (including staging) that do have it glued though. >> >>> >> >>> Examples are: >> >>> 1. "static int __init kp2000_pcie_init(void)" (commit on May 20 09:34:11 >> >>> 2019) >> >>> 2. "static int __init hl_init(void)" (commit on Mon Feb 18 09:46:43 2019) >> >>> >> >>> Please give me more details. >> >> >> >> Never use a staging driver for any type of example, _EXECPT_ for a bad >> >> one. There's a reason the code is in staging and not in the "real" part >> >> of the kernel. >> > >> > ok. >> > >> > another one (1) is not staging.. >> >> I meant "static int __init hl_init(void)" is not staging one > > Still doesn't mean it is a good thing to do. Again, why isn't this > driver just using the misc driver interface instead? It's much simpler > to use and should work just fine for this tiny driver, instead of having > to create a custom class just for it. > ok
Re: [PATCH v1 01/12] gna: add driver module
Maciej Kwapulinski writes: > Greg Kroah-Hartman writes: > >> On Mon, Mar 01, 2021 at 11:18:59AM +0100, Maciej Kwapulinski wrote: >>> >>> Andy Shevchenko writes: >>> >>> > On Tue, Feb 16, 2021 at 6:11 PM Maciej Kwapulinski >>> > wrote: >>> >> >>> >>> >> +static int __init gna_drv_init(void) >>> >> +{ >>> >> + int ret; >>> >> + >>> >> + mutex_init(&gna_drv_priv.lock); >>> >> + >>> >> + gna_class = class_create(THIS_MODULE, "gna"); >>> >> + if (IS_ERR(gna_class)) { >>> >> + pr_err("class device create failed\n"); >>> >> + return PTR_ERR(gna_class); >>> >> + } >>> >> + gna_class->devnode = gna_devnode; >>> >> + >>> >> + ret = pci_register_driver(&gna_driver); >>> > >>> > Is it possible to decouple a PCI glue driver from the class as many >>> > other existing examples are doing? >>> > >>> >>> I see many pci drivers (including staging) that do have it glued though. >>> >>> Examples are: >>> 1. "static int __init kp2000_pcie_init(void)" (commit on May 20 09:34:11 >>> 2019) >>> 2. "static int __init hl_init(void)" (commit on Mon Feb 18 09:46:43 2019) >>> >>> Please give me more details. >> >> Never use a staging driver for any type of example, _EXECPT_ for a bad >> one. There's a reason the code is in staging and not in the "real" part >> of the kernel. > > ok. > > another one (1) is not staging.. I meant "static int __init hl_init(void)" is not staging one
Re: [PATCH v1 01/12] gna: add driver module
Greg Kroah-Hartman writes: > On Mon, Mar 01, 2021 at 11:18:59AM +0100, Maciej Kwapulinski wrote: >> >> Andy Shevchenko writes: >> >> > On Tue, Feb 16, 2021 at 6:11 PM Maciej Kwapulinski >> > wrote: >> >> >> >> >> +static int __init gna_drv_init(void) >> >> +{ >> >> + int ret; >> >> + >> >> + mutex_init(&gna_drv_priv.lock); >> >> + >> >> + gna_class = class_create(THIS_MODULE, "gna"); >> >> + if (IS_ERR(gna_class)) { >> >> + pr_err("class device create failed\n"); >> >> + return PTR_ERR(gna_class); >> >> + } >> >> + gna_class->devnode = gna_devnode; >> >> + >> >> + ret = pci_register_driver(&gna_driver); >> > >> > Is it possible to decouple a PCI glue driver from the class as many >> > other existing examples are doing? >> > >> >> I see many pci drivers (including staging) that do have it glued though. >> >> Examples are: >> 1. "static int __init kp2000_pcie_init(void)" (commit on May 20 09:34:11 >> 2019) >> 2. "static int __init hl_init(void)" (commit on Mon Feb 18 09:46:43 2019) >> >> Please give me more details. > > Never use a staging driver for any type of example, _EXECPT_ for a bad > one. There's a reason the code is in staging and not in the "real" part > of the kernel. ok. another one (1) is not staging..
Re: [PATCH v1 01/12] gna: add driver module
Andy Shevchenko writes: > On Tue, Feb 16, 2021 at 6:11 PM Maciej Kwapulinski > wrote: >> >> +static int __init gna_drv_init(void) >> +{ >> + int ret; >> + >> + mutex_init(&gna_drv_priv.lock); >> + >> + gna_class = class_create(THIS_MODULE, "gna"); >> + if (IS_ERR(gna_class)) { >> + pr_err("class device create failed\n"); >> + return PTR_ERR(gna_class); >> + } >> + gna_class->devnode = gna_devnode; >> + >> + ret = pci_register_driver(&gna_driver); > > Is it possible to decouple a PCI glue driver from the class as many > other existing examples are doing? > I see many pci drivers (including staging) that do have it glued though. Examples are: 1. "static int __init kp2000_pcie_init(void)" (commit on May 20 09:34:11 2019) 2. "static int __init hl_init(void)" (commit on Mon Feb 18 09:46:43 2019) Please give me more details.
Re: [PATCH v1 01/12] gna: add driver module
Andy Shevchenko writes: > On Tue, Feb 16, 2021 at 6:11 PM Maciej Kwapulinski > wrote: >> >> +#define GNA_DRV_VER"1.2.0" > > Nowadays the version is the Git SHA sum. > right, "version" is present in about 7% of all modules do You mean version should be skipped over (automatically generated) srcversion field? or maybe You suggest any (better) technique?
Re: [PATCH v1 01/12] gna: add driver module
Greg Kroah-Hartman writes: > On Tue, Feb 16, 2021 at 05:05:14PM +0100, Maciej Kwapulinski wrote: >> --- /dev/null >> +++ b/drivers/misc/gna/gna_driver.h >> @@ -0,0 +1,41 @@ >> +/* SPDX-License-Identifier: GPL-2.0-only */ >> +/* Copyright(c) 2017-2021 Intel Corporation */ >> + >> +#ifndef __GNA_DRIVER_H__ >> +#define __GNA_DRIVER_H__ >> + >> +#include >> +#include >> +#include >> + >> +#define GNA_DRV_NAME"gna" > > Way too generic, no one knows what "gna" is. > "intel gna" is much more verbose in search engines. As we do not (plan to) have more "gna" drivers, is the following ok?: intel-gna the change would imply the following: prompt$ lspci -s 00:00.3 - 00:00.3 System peripheral: Intel Corporation Device 3190 (rev 03) Subsystem: Intel Corporation Device 2072 Kernel driver in use: intel-gna Kernel modules: gna is it ok? also, how about the interface to library (it's part of one of next patches)?: prompt$ file /dev/gna0 /dev/gna0: character special (235/0) can "gna" stay intact here? I'm pointing this out, because gna exists on the market for a while and changing the above may have some impact we'd like to avoid. >
Re: [PATCH v1 01/12] gna: add driver module
Andy Shevchenko writes: > On Tue, Feb 16, 2021 at 6:11 PM Maciej Kwapulinski > wrote: >> >> +err_clear_master: >> + pci_clear_master(pcidev); >> +err_release_regions: >> + pci_release_regions(pcidev); >> +end: >> + dev_err(&pcidev->dev, "gna probe failed with %d\n", ret); >> + return ret; > > These are all completely redundant. > following is refactor of gna_probe(), but without pci_release_regions(), smatch (v7fcfe259) produces warning: drivers/misc/gna/gna_device.c:78 gna_probe() warn: 'pcidev' not released on lines: 56,65. here's the code refactored: int gna_probe(struct pci_dev *pcidev, const struct pci_device_id *pci_id) { struct gna_private *gna_priv; int ret; ret = pcim_enable_device(pcidev); if (ret) { dev_err(&pcidev->dev, "pci device can't be enabled\n"); return ret; } ret = pci_request_regions(pcidev, GNA_DRV_NAME); if (ret) return ret; ret = pci_set_dma_mask(pcidev, DMA_BIT_MASK(64)); if (ret) { dev_err(&pcidev->dev, "pci_set_dma_mask returned error %d\n", ret); return ret; } pci_set_master(pcidev); /* init gna device */ gna_priv = devm_kzalloc(&pcidev->dev, sizeof(*gna_priv), GFP_KERNEL); if (!gna_priv) { //pci_release_regions(pcidev); return -ENOMEM; // line 56 } /* Map BAR0 */ gna_priv->bar0.iostart = pci_resource_start(pcidev, 0); gna_priv->bar0.iosize = pci_resource_len(pcidev, 0); gna_priv->bar0.mem_addr = pcim_iomap(pcidev, 0, 0); if (!gna_priv->bar0.mem_addr) { //pci_release_regions(pcidev); dev_err(&pcidev->dev, "could not map BAR 0\n"); return -EINVAL; // line 65 } dev_dbg(&pcidev->dev, "bar0 io start: 0x%llx\n", (unsigned long long)gna_priv->bar0.iostart); dev_dbg(&pcidev->dev, "bar0 io size: %llu\n", (unsigned long long)gna_priv->bar0.iosize); dev_dbg(&pcidev->dev, "bar0 memory address: %p\n", gna_priv->bar0.mem_addr); ret = gna_dev_init(gna_priv, pcidev, pci_id); if (ret) { dev_err(&pcidev->dev, "could not initialize gna private structure\n"); return ret; } return 0; } I've also added 'noinline' directive to pci_release_regions(), to see if it is called by the core code on "rmmod gna", but can't see the call. Is the smatch tool that causes problems here? Do You suggest other way to handle the problem?
Re: [PATCH v1 01/12] gna: add driver module
Greg Kroah-Hartman writes: > On Tue, Feb 16, 2021 at 05:05:14PM +0100, Maciej Kwapulinski wrote: >> --- /dev/null >> +++ b/drivers/misc/gna/gna_driver.c >> @@ -0,0 +1,65 @@ >> +// SPDX-License-Identifier: GPL-2.0-only >> +// Copyright(c) 2017-2021 Intel Corporation >> + >> +#define pr_fmt(fmt) KBUILD_MODNAME " " fmt > > You are a driver, you should never need a pr_* call, so this should not > be needed. You should always just use dev_* instead. > Hi Greg and all other Reviewers. Thank You for all the comments so far. I'm starting preparing PATCH v2 series based on them. I'll also answer comments individually where need arises. regards, Maciej
[PATCH v1 11/12] gna: add ioctl handler
From: Tomasz Jankowski Add ioctl handler into GNA driver. The ioctl interface provides the ability to do the following: - Map and unmap memory buffers for GNA computation requests. - Retrieve capabilities of the underlying GNA IP. - Submit GNA computation requests. - Request notification of scoring completion. Signed-off-by: Tomasz Jankowski Tested-by: Savo Novakovic Co-developed-by: Jianxun Zhang Signed-off-by: Jianxun Zhang Co-developed-by: Maciej Kwapulinski Signed-off-by: Maciej Kwapulinski --- drivers/misc/gna/Kbuild | 2 +- drivers/misc/gna/gna_device.c | 40 ++ drivers/misc/gna/gna_device.h | 2 + drivers/misc/gna/gna_ioctl.c | 249 ++ drivers/misc/gna/gna_ioctl.h | 11 ++ 5 files changed, 303 insertions(+), 1 deletion(-) create mode 100644 drivers/misc/gna/gna_ioctl.c create mode 100644 drivers/misc/gna/gna_ioctl.h diff --git a/drivers/misc/gna/Kbuild b/drivers/misc/gna/Kbuild index 049e142894aa..ea91603e59f2 100644 --- a/drivers/misc/gna/Kbuild +++ b/drivers/misc/gna/Kbuild @@ -1,5 +1,5 @@ # SPDX-License-Identifier: GPL-2.0-only -gna-y := gna_device.o gna_driver.o gna_mem.o gna_request.o gna_score.o gna_hw.o +gna-y := gna_device.o gna_driver.o gna_mem.o gna_ioctl.o gna_request.o gna_score.o gna_hw.o obj-$(CONFIG_INTEL_GNA) += gna.o diff --git a/drivers/misc/gna/gna_device.c b/drivers/misc/gna/gna_device.c index 5198326e8af4..9faf0456fee2 100644 --- a/drivers/misc/gna/gna_device.c +++ b/drivers/misc/gna/gna_device.c @@ -252,3 +252,43 @@ void gna_remove(struct pci_dev *pcidev) pci_clear_master(pcidev); pci_release_regions(pcidev); } + +static u32 gna_device_type_by_hwid(u32 hwid) +{ + switch (hwid) { + case GNA_DEV_HWID_CNL: + return GNA_DEV_TYPE_0_9; + case GNA_DEV_HWID_GLK: + case GNA_DEV_HWID_EHL: + case GNA_DEV_HWID_ICL: + return GNA_DEV_TYPE_1_0; + case GNA_DEV_HWID_JSL: + case GNA_DEV_HWID_TGL: + return GNA_DEV_TYPE_2_0; + default: + return 0; + } +} + +int gna_getparam(struct gna_private *gna_priv, union gna_parameter *param) +{ + switch (param->in.id) { + case GNA_PARAM_DEVICE_ID: + param->out.value = gna_priv->info.hwid; + break; + case GNA_PARAM_RECOVERY_TIMEOUT: + param->out.value = recovery_timeout; + break; + case GNA_PARAM_INPUT_BUFFER_S: + param->out.value = gna_priv->hw_info.in_buf_s; + break; + case GNA_PARAM_DEVICE_TYPE: + param->out.value = gna_device_type_by_hwid(gna_priv->info.hwid); + break; + default: + dev_err(&gna_priv->dev, "unknown parameter id %llu\n", param->in.id); + return -EINVAL; + } + + return 0; +} diff --git a/drivers/misc/gna/gna_device.h b/drivers/misc/gna/gna_device.h index 77cd1a458367..531e2b904d6a 100644 --- a/drivers/misc/gna/gna_device.h +++ b/drivers/misc/gna/gna_device.h @@ -82,4 +82,6 @@ int gna_probe(struct pci_dev *dev, const struct pci_device_id *id); void gna_remove(struct pci_dev *dev); +int gna_getparam(struct gna_private *gna_priv, union gna_parameter *param); + #endif /* __GNA_DEVICE_H__ */ diff --git a/drivers/misc/gna/gna_ioctl.c b/drivers/misc/gna/gna_ioctl.c new file mode 100644 index ..a408336d4b6c --- /dev/null +++ b/drivers/misc/gna/gna_ioctl.c @@ -0,0 +1,249 @@ +// SPDX-License-Identifier: GPL-2.0-only +// Copyright(c) 2017-2021 Intel Corporation + +#include + +#include + +#include "gna_driver.h" +#include "gna_device.h" +#include "gna_ioctl.h" +#include "gna_mem.h" +#include "gna_request.h" +#include "gna_score.h" + +static int gna_ioctl_score(struct gna_file_private *file_priv, void __user *argptr) +{ + union gna_compute score_args; + struct gna_private *gna_priv; + u64 request_id; + int ret; + + gna_priv = file_priv->gna_priv; + + if (copy_from_user(&score_args, argptr, sizeof(score_args))) { + dev_err(&gna_priv->dev, "could not copy score ioctl config from user\n"); + return -EFAULT; + } + + ret = gna_validate_score_config(&score_args.in.config, file_priv); + if (ret) { + dev_err(&gna_priv->dev, "request not valid\n"); + return ret; + } + + ret = gna_enqueue_request(&score_args.in.config, file_priv, &request_id); + if (ret) { + dev_err(&gna_priv->dev, "could not enqueue score request %d\n", ret); + return ret; + } + + score_args.out.request_id = request_id; + if (copy_to_user(argptr, &score_args, sizeof(score_args))) { + dev_err(&gna_priv->dev, "could
[PATCH v1 10/12] gna: add interrupt handler
From: Tomasz Jankowski An interrupt is generated by the hardware when a scoring job is done. The interrupt handler wakes up the work queue to resume the processing on the current request. Signed-off-by: Tomasz Jankowski Tested-by: Savo Novakovic Co-developed-by: Jianxun Zhang Signed-off-by: Jianxun Zhang Signed-off-by: Maciej Kwapulinski --- drivers/misc/gna/gna_device.c | 32 ++-- drivers/misc/gna/gna_device.h | 2 ++ drivers/misc/gna/gna_hw.c | 10 ++ drivers/misc/gna/gna_hw.h | 2 ++ 4 files changed, 44 insertions(+), 2 deletions(-) diff --git a/drivers/misc/gna/gna_device.c b/drivers/misc/gna/gna_device.c index a229f51fb17b..5198326e8af4 100644 --- a/drivers/misc/gna/gna_device.c +++ b/drivers/misc/gna/gna_device.c @@ -182,6 +182,27 @@ int gna_probe(struct pci_dev *pcidev, const struct pci_device_id *pci_id) goto err_clear_master; } + ret = pci_alloc_irq_vectors(pcidev, 1, 1, PCI_IRQ_ALL_TYPES); + if (ret < 0) + goto err_clear_master; + + gna_priv->irq = pci_irq_vector(pcidev, 0); + if (unlikely(gna_priv->irq < 0)) { + dev_err(&pcidev->dev, "could not obtain irq number\n"); + ret = -EIO; + goto err_free_irq_vector; + } + + ret = request_irq(gna_priv->irq, gna_interrupt, + IRQF_SHARED, GNA_DRV_NAME, gna_priv); + + if (ret) { + dev_err(&pcidev->dev, "could not register for interrupt\n"); + goto err_free_irq_vector; + } + + dev_dbg(&pcidev->dev, "irq num %d\n", gna_priv->irq); + /* Map BAR0 */ gna_priv->bar0.iostart = pci_resource_start(pcidev, 0); gna_priv->bar0.iosize = pci_resource_len(pcidev, 0); @@ -189,7 +210,7 @@ int gna_probe(struct pci_dev *pcidev, const struct pci_device_id *pci_id) if (!gna_priv->bar0.mem_addr) { dev_err(&pcidev->dev, "could not map BAR 0\n"); ret = -EINVAL; - goto err_clear_master; + goto err_free_irq; } dev_dbg(&pcidev->dev, "bar0 io start: 0x%llx\n", (unsigned long long)gna_priv->bar0.iostart); @@ -199,11 +220,15 @@ int gna_probe(struct pci_dev *pcidev, const struct pci_device_id *pci_id) ret = gna_dev_init(gna_priv, pcidev, pci_id); if (ret) { dev_err(&pcidev->dev, "could not initialize gna private structure\n"); - goto err_clear_master; + goto err_free_irq; } return 0; +err_free_irq: + free_irq(gna_priv->irq, gna_priv); +err_free_irq_vector: + pci_free_irq_vectors(pcidev); err_clear_master: pci_clear_master(pcidev); err_release_regions: @@ -219,7 +244,10 @@ void gna_remove(struct pci_dev *pcidev) gna_priv = pci_get_drvdata(pcidev); + free_irq(gna_priv->irq, gna_priv); + gna_dev_deinit(gna_priv); + pci_free_irq_vectors(pcidev); pci_clear_master(pcidev); pci_release_regions(pcidev); diff --git a/drivers/misc/gna/gna_device.h b/drivers/misc/gna/gna_device.h index 0855972cd085..77cd1a458367 100644 --- a/drivers/misc/gna/gna_device.h +++ b/drivers/misc/gna/gna_device.h @@ -46,12 +46,14 @@ struct gna_private { struct device dev; struct cdev cdev; + /* hardware status set by interrupt handler */ u32 hw_status; /* device related resources */ struct gna_pci_bar bar0; struct gna_drv_info info; struct gna_hw_info hw_info; + int irq; struct gna_mmu_object mmu; /* lock protecting mmu structure */ diff --git a/drivers/misc/gna/gna_hw.c b/drivers/misc/gna/gna_hw.c index 48e09e5f3ca8..6146cbd43004 100644 --- a/drivers/misc/gna/gna_hw.c +++ b/drivers/misc/gna/gna_hw.c @@ -124,3 +124,13 @@ void gna_abort_hw(struct gna_private *gna_priv) if (i == 0) dev_err(&gna_priv->dev, "abort did not complete\n"); } + +irqreturn_t gna_interrupt(int irq, void *priv) +{ + struct gna_private *gna_priv; + + gna_priv = (struct gna_private *)priv; + gna_priv->busy = false; + wake_up(&gna_priv->busy_waitq); + return IRQ_HANDLED; +} diff --git a/drivers/misc/gna/gna_hw.h b/drivers/misc/gna/gna_hw.h index 4da29870c4dc..4dfa05937943 100644 --- a/drivers/misc/gna/gna_hw.h +++ b/drivers/misc/gna/gna_hw.h @@ -6,6 +6,7 @@ #include #include +#include #include /* GNA MMIO registers */ @@ -70,6 +71,7 @@ struct gna_desc_info { struct gna_private; struct gna_compute_cfg; +irqreturn_t gna_interrupt(int irq, void *ctx); 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); -- 2.28.0
[PATCH v1 09/12] gna: add a work queue to process scoring requests
From: Tomasz Jankowski The new workqueue is responsible to process the list of requests in a FIFO manner. It waits for the hardware to complete on every request until it is woken up by an interrupt that will be addressed in following changes. Signed-off-by: Tomasz Jankowski Co-developed-by: Anisha Dattatraya Kulkarni Signed-off-by: Anisha Dattatraya Kulkarni Tested-by: Savo Novakovic Co-developed-by: Jianxun Zhang Signed-off-by: Jianxun Zhang Co-developed-by: Maciej Kwapulinski Signed-off-by: Maciej Kwapulinski --- drivers/misc/gna/gna_device.c | 21 +- drivers/misc/gna/gna_device.h | 8 +++ drivers/misc/gna/gna_driver.c | 5 ++ drivers/misc/gna/gna_hw.c | 8 +++ drivers/misc/gna/gna_hw.h | 1 + drivers/misc/gna/gna_request.c | 119 + drivers/misc/gna/gna_request.h | 1 + 7 files changed, 162 insertions(+), 1 deletion(-) diff --git a/drivers/misc/gna/gna_device.c b/drivers/misc/gna/gna_device.c index 7a124ea1..a229f51fb17b 100644 --- a/drivers/misc/gna/gna_device.c +++ b/drivers/misc/gna/gna_device.c @@ -89,6 +89,7 @@ static int gna_dev_init(struct gna_private *gna_priv, struct pci_dev *pcidev, const struct pci_device_id *pci_id) { u32 bld_reg; + int ret; pci_set_drvdata(pcidev, gna_priv); @@ -102,7 +103,9 @@ static int gna_dev_init(struct gna_private *gna_priv, struct pci_dev *pcidev, if (gna_mmu_alloc(gna_priv)) { dev_err(&gna_priv->dev, "gna mmu allocation failed\n"); - return -EFAULT; + ret = -EFAULT; + goto err_pci_drvdata_unset; + } dev_dbg(&pcidev->dev, "maximum memory size %llu num pd %d\n", gna_priv->info.max_hw_mem, gna_priv->info.num_pagetables); @@ -111,6 +114,7 @@ static int gna_dev_init(struct gna_private *gna_priv, struct pci_dev *pcidev, gna_priv->info.desc_info.mmu_info.vamax_size); mutex_init(&gna_priv->mmu_lock); + init_waitqueue_head(&gna_priv->busy_waitq); mutex_init(&gna_priv->filelist_lock); INIT_LIST_HEAD(&gna_priv->file_list); @@ -119,15 +123,30 @@ static int gna_dev_init(struct gna_private *gna_priv, struct pci_dev *pcidev, idr_init(&gna_priv->memory_idr); mutex_init(&gna_priv->memidr_lock); + + gna_priv->request_wq = create_singlethread_workqueue("gna_request_wq"); + if (!gna_priv->request_wq) { + dev_err(&pcidev->dev, "could not create wq for gna device\n"); + ret = -EFAULT; + goto err_pci_drvdata_unset; + } mutex_init(&gna_priv->reqlist_lock); INIT_LIST_HEAD(&gna_priv->request_list); return 0; + +err_pci_drvdata_unset: + pci_set_drvdata(pcidev, NULL); + + return ret; } /* Reverse gna_dev_init() */ static void gna_dev_deinit(struct gna_private *gna_priv) { + flush_workqueue(gna_priv->request_wq); + destroy_workqueue(gna_priv->request_wq); + idr_destroy(&gna_priv->memory_idr); gna_mmu_free(gna_priv); pci_set_drvdata(gna_priv->pdev, NULL); diff --git a/drivers/misc/gna/gna_device.h b/drivers/misc/gna/gna_device.h index 59b074704d1a..0855972cd085 100644 --- a/drivers/misc/gna/gna_device.h +++ b/drivers/misc/gna/gna_device.h @@ -46,6 +46,8 @@ struct gna_private { struct device dev; struct cdev cdev; + u32 hw_status; + /* device related resources */ struct gna_pci_bar bar0; struct gna_drv_info info; @@ -55,9 +57,15 @@ struct gna_private { /* lock protecting mmu structure */ struct mutex mmu_lock; + /* device busy indicator */ + bool busy; + + struct wait_queue_head busy_waitq; + /* requests */ struct list_head request_list; struct mutex reqlist_lock; /* protects request_list */ + struct workqueue_struct *request_wq; atomic_t request_count; /* memory objects */ diff --git a/drivers/misc/gna/gna_driver.c b/drivers/misc/gna/gna_driver.c index 80981c448f3a..cb638dfa81ac 100644 --- a/drivers/misc/gna/gna_driver.c +++ b/drivers/misc/gna/gna_driver.c @@ -9,6 +9,11 @@ #include "gna_device.h" #include "gna_driver.h" +/* recovery timeout in seconds */ +int recovery_timeout = 60; +module_param(recovery_timeout, int, 0644); +MODULE_PARM_DESC(recovery_timeout, "Recovery timeout"); + struct gna_driver_private gna_drv_priv; struct class *gna_class; diff --git a/drivers/misc/gna/gna_hw.c b/drivers/misc/gna/gna_hw.c index 3b85c4b75fd8..48e09e5f3ca8 100644 --- a/drivers/misc/gna/gna_hw.c +++ b/drivers/misc/gna/gna_hw.c @@ -49,6 +49,14 @@ void gna_print_error_status(struct gna_private *gna_priv, u32 hw_status) dev_dbg(&gna_p
[PATCH v1 08/12] gna: implement scoring
From: Tomasz Jankowski Add a new component for scoring logic such as configuring and kicking off the hardware. Signed-off-by: Tomasz Jankowski Tested-by: Savo Novakovic Co-developed-by: Jianxun Zhang Signed-off-by: Jianxun Zhang Co-developed-by: Maciej Kwapulinski Signed-off-by: Maciej Kwapulinski --- drivers/misc/gna/Kbuild | 2 +- drivers/misc/gna/gna_device.c | 3 + drivers/misc/gna/gna_device.h | 5 + drivers/misc/gna/gna_hw.h | 2 - drivers/misc/gna/gna_score.c | 299 ++ drivers/misc/gna/gna_score.h | 20 +++ 6 files changed, 328 insertions(+), 3 deletions(-) create mode 100644 drivers/misc/gna/gna_score.c create mode 100644 drivers/misc/gna/gna_score.h diff --git a/drivers/misc/gna/Kbuild b/drivers/misc/gna/Kbuild index f47775759a6e..049e142894aa 100644 --- a/drivers/misc/gna/Kbuild +++ b/drivers/misc/gna/Kbuild @@ -1,5 +1,5 @@ # SPDX-License-Identifier: GPL-2.0-only -gna-y := gna_device.o gna_driver.o gna_mem.o gna_request.o gna_hw.o +gna-y := gna_device.o gna_driver.o gna_mem.o gna_request.o gna_score.o gna_hw.o obj-$(CONFIG_INTEL_GNA) += gna.o diff --git a/drivers/misc/gna/gna_device.c b/drivers/misc/gna/gna_device.c index cd8ee86bbc58..7a124ea1 100644 --- a/drivers/misc/gna/gna_device.c +++ b/drivers/misc/gna/gna_device.c @@ -112,6 +112,9 @@ static int gna_dev_init(struct gna_private *gna_priv, struct pci_dev *pcidev, mutex_init(&gna_priv->mmu_lock); + mutex_init(&gna_priv->filelist_lock); + INIT_LIST_HEAD(&gna_priv->file_list); + atomic_set(&gna_priv->request_count, 0); idr_init(&gna_priv->memory_idr); diff --git a/drivers/misc/gna/gna_device.h b/drivers/misc/gna/gna_device.h index 445c81c698fb..59b074704d1a 100644 --- a/drivers/misc/gna/gna_device.h +++ b/drivers/misc/gna/gna_device.h @@ -35,6 +35,11 @@ struct gna_hw_info { struct gna_private { struct gna_driver_private *drv_priv; + /* list of opened files */ + struct list_head file_list; + /* lock protecting file_list */ + struct mutex filelist_lock; + /* device objects */ struct pci_dev *pdev; struct device *parent; /* pdev->dev */ diff --git a/drivers/misc/gna/gna_hw.h b/drivers/misc/gna/gna_hw.h index e09e562aae50..941f54b0f29a 100644 --- a/drivers/misc/gna/gna_hw.h +++ b/drivers/misc/gna/gna_hw.h @@ -33,8 +33,6 @@ /* minimum size of XNN layer descriptors in bytes (at least 1 layer) */ #define XNN_LYR_DSC_SIZE (128) -#define GMM_CFG_SIZE (128) - #define GNA_VAMAXADDR_OFFSET 0x200 #define GNA_PGDIRN_OFFSET 0x210 diff --git a/drivers/misc/gna/gna_score.c b/drivers/misc/gna/gna_score.c new file mode 100644 index ..e708e449e1ee --- /dev/null +++ b/drivers/misc/gna/gna_score.c @@ -0,0 +1,299 @@ +// SPDX-License-Identifier: GPL-2.0-only +// Copyright(c) 2017-2021 Intel Corporation + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "gna_device.h" +#include "gna_driver.h" +#include "gna_request.h" +#include "gna_score.h" + +int gna_validate_score_config(struct gna_compute_cfg *compute_cfg, + struct gna_file_private *file_priv) +{ + struct gna_private *gna_priv; + size_t buffers_size; + + gna_priv = file_priv->gna_priv; + + if (compute_cfg->gna_mode > GNA_MODE_XNN) { + dev_err(&gna_priv->dev, "gna mode invalid\n"); + return -EINVAL; + } + + if (compute_cfg->layer_count > gna_priv->info.max_layer_count) { + dev_err(&gna_priv->dev, "max layer count exceeded\n"); + return -EINVAL; + } + + if (compute_cfg->buffer_count == 0) { + dev_err(&gna_priv->dev, "no buffers\n"); + return -EINVAL; + } + + buffers_size = sizeof(struct gna_buffer) * compute_cfg->buffer_count; + if (!access_ok(u64_to_user_ptr(compute_cfg->buffers_ptr), buffers_size)) { + dev_err(&gna_priv->dev, "invalid buffers pointer\n"); + return -EINVAL; + } + + return 0; +} + +static int gna_do_patch_memory(struct gna_private *gna_priv, struct gna_memory_object *mo, + struct gna_memory_patch *patch, void *vaddr) +{ + size_t size; + void *dest; + u64 value; + + value = patch->value; + size = patch->size; + dest = (u8 *)vaddr + patch->offset; + dev_dbg(&gna_priv->dev, "patch offset: %llu, size: %zu, value: %llu\n", + patch->offset, size, value); + + switch (size) { + case 0: + return -EFAULT; +
[PATCH v1 07/12] gna: add request component
From: Tomasz Jankowski The scoring work submitted to the GNA driver is implemented as a list of requests that will be processed by the hardware. Signed-off-by: Tomasz Jankowski Co-developed-by: Anisha Dattatraya Kulkarni Signed-off-by: Anisha Dattatraya Kulkarni Tested-by: Savo Novakovic Co-developed-by: Jianxun Zhang Signed-off-by: Jianxun Zhang Co-developed-by: Maciej Kwapulinski Signed-off-by: Maciej Kwapulinski --- drivers/misc/gna/Kbuild| 2 +- drivers/misc/gna/gna_device.c | 5 + drivers/misc/gna/gna_device.h | 5 + drivers/misc/gna/gna_mem.c | 3 + drivers/misc/gna/gna_request.c | 347 + drivers/misc/gna/gna_request.h | 61 ++ 6 files changed, 422 insertions(+), 1 deletion(-) create mode 100644 drivers/misc/gna/gna_request.c create mode 100644 drivers/misc/gna/gna_request.h diff --git a/drivers/misc/gna/Kbuild b/drivers/misc/gna/Kbuild index 860b14c0e8d0..f47775759a6e 100644 --- a/drivers/misc/gna/Kbuild +++ b/drivers/misc/gna/Kbuild @@ -1,5 +1,5 @@ # SPDX-License-Identifier: GPL-2.0-only -gna-y := gna_device.o gna_driver.o gna_mem.o gna_hw.o +gna-y := gna_device.o gna_driver.o gna_mem.o gna_request.o gna_hw.o obj-$(CONFIG_INTEL_GNA) += gna.o diff --git a/drivers/misc/gna/gna_device.c b/drivers/misc/gna/gna_device.c index 7031a5d7c16c..cd8ee86bbc58 100644 --- a/drivers/misc/gna/gna_device.c +++ b/drivers/misc/gna/gna_device.c @@ -7,6 +7,7 @@ #include "gna_device.h" #include "gna_driver.h" #include "gna_hw.h" +#include "gna_request.h" #define GNA_DEV_HWID_CNL 0x5A11 #define GNA_DEV_HWID_EHL 0x4511 @@ -111,8 +112,12 @@ static int gna_dev_init(struct gna_private *gna_priv, struct pci_dev *pcidev, mutex_init(&gna_priv->mmu_lock); + atomic_set(&gna_priv->request_count, 0); + idr_init(&gna_priv->memory_idr); mutex_init(&gna_priv->memidr_lock); + mutex_init(&gna_priv->reqlist_lock); + INIT_LIST_HEAD(&gna_priv->request_list); return 0; } diff --git a/drivers/misc/gna/gna_device.h b/drivers/misc/gna/gna_device.h index 22c47f2c03ec..445c81c698fb 100644 --- a/drivers/misc/gna/gna_device.h +++ b/drivers/misc/gna/gna_device.h @@ -50,6 +50,11 @@ struct gna_private { /* lock protecting mmu structure */ struct mutex mmu_lock; + /* requests */ + struct list_head request_list; + struct mutex reqlist_lock; /* protects request_list */ + atomic_t request_count; + /* memory objects */ struct idr memory_idr; /* lock protecting memory_idr */ diff --git a/drivers/misc/gna/gna_mem.c b/drivers/misc/gna/gna_mem.c index a2ac3c31b4fb..09c4f401c3fa 100644 --- a/drivers/misc/gna/gna_mem.c +++ b/drivers/misc/gna/gna_mem.c @@ -19,6 +19,7 @@ #include "gna_device.h" #include "gna_driver.h" #include "gna_mem.h" +#include "gna_request.h" static void gna_mmu_init(struct gna_private *gna_priv) { @@ -391,6 +392,8 @@ static void gna_memory_release(struct work_struct *work) mo = container_of(work, struct gna_memory_object, work); + gna_delete_memory_requests(mo->memory_id, mo->gna_priv); + mo->user_ptr = NULL; wake_up_interruptible(&mo->waitq); diff --git a/drivers/misc/gna/gna_request.c b/drivers/misc/gna/gna_request.c new file mode 100644 index ..a7a55fe68eed --- /dev/null +++ b/drivers/misc/gna/gna_request.c @@ -0,0 +1,347 @@ +// SPDX-License-Identifier: GPL-2.0-only +// Copyright(c) 2017-2021 Intel Corporation + +#include +#include +#include +#include + +#include "gna_device.h" +#include "gna_driver.h" +#include "gna_request.h" + +static struct gna_request *gna_request_create(struct gna_file_private *file_priv, + struct gna_compute_cfg *compute_cfg) +{ + struct gna_request *score_request; + struct gna_private *gna_priv; + + gna_priv = file_priv->gna_priv; + if (IS_ERR(gna_priv)) + return NULL; + + score_request = kzalloc(sizeof(*score_request), GFP_KERNEL); + if (!score_request) + return NULL; + kref_init(&score_request->refcount); + + dev_dbg(&gna_priv->dev, "layer_base %d layer_count %d\n", + compute_cfg->layer_base, compute_cfg->layer_count); + + score_request->request_id = atomic_inc_return(&gna_priv->request_count); + score_request->compute_cfg = *compute_cfg; + score_request->fd = file_priv->fd; + score_request->gna_priv = gna_priv; + score_request->state = NEW; + init_waitqueue_head(&score_request->waitq); + + return score_request; +} + +/* + * returns true if [inner_offset, inner_size) is embraced by [0, outer_size). False otherwise. + */ +
[PATCH v1 06/12] gna: add hardware ids
From: Tomasz Jankowski Add PCI ids of Intel(R) Gaussian & Neural Accelerator on supported platforms. Signed-off-by: Tomasz Jankowski Tested-by: Savo Novakovic Co-developed-by: Jianxun Zhang Signed-off-by: Jianxun Zhang Signed-off-by: Maciej Kwapulinski --- drivers/misc/gna/gna_device.c | 76 +++ drivers/misc/gna/gna_device.h | 2 + drivers/misc/gna/gna_driver.c | 1 + 3 files changed, 79 insertions(+) diff --git a/drivers/misc/gna/gna_device.c b/drivers/misc/gna/gna_device.c index d6a6d3cab570..7031a5d7c16c 100644 --- a/drivers/misc/gna/gna_device.c +++ b/drivers/misc/gna/gna_device.c @@ -8,6 +8,82 @@ #include "gna_driver.h" #include "gna_hw.h" +#define GNA_DEV_HWID_CNL 0x5A11 +#define GNA_DEV_HWID_EHL 0x4511 +#define GNA_DEV_HWID_GLK 0x3190 +#define GNA_DEV_HWID_ICL 0x8A11 +#define GNA_DEV_HWID_JSL 0x4E11 +#define GNA_DEV_HWID_TGL 0x9A11 + +#define GNA_FEATURES \ + .max_hw_mem = 256 * 1024 * 1024, \ + .num_pagetables = 64, \ + .num_page_entries = PAGE_SIZE / sizeof(u32), \ + /* desc_info all in bytes */ \ + .desc_info = { \ + .rsvd_size = 256, \ + .cfg_size = 256, \ + .desc_size = 784, \ + .mmu_info = { \ + .vamax_size = 4, \ + .rsvd_size = 12, \ + .pd_size = 4 * 64, \ + }, \ + } + +#define GNA_GEN1_FEATURES \ + GNA_FEATURES, \ + .max_layer_count = 1024 + +#define GNA_GEN2_FEATURES \ + GNA_FEATURES, \ + .max_layer_count = 4096 + +static const struct gna_drv_info cnl_drv_info = { + .hwid = GNA_DEV_HWID_CNL, + GNA_GEN1_FEATURES +}; + +static const struct gna_drv_info glk_drv_info = { + .hwid = GNA_DEV_HWID_GLK, + GNA_GEN1_FEATURES +}; + +static const struct gna_drv_info ehl_drv_info = { + .hwid = GNA_DEV_HWID_EHL, + GNA_GEN1_FEATURES +}; + +static const struct gna_drv_info icl_drv_info = { + .hwid = GNA_DEV_HWID_ICL, + GNA_GEN1_FEATURES +}; + +static const struct gna_drv_info jsl_drv_info = { + .hwid = GNA_DEV_HWID_JSL, + GNA_GEN2_FEATURES +}; + +static const struct gna_drv_info tgl_drv_info = { + .hwid = GNA_DEV_HWID_TGL, + GNA_GEN2_FEATURES +}; + +#define INTEL_GNA_DEVICE(hwid, info) \ + { PCI_VDEVICE(INTEL, hwid), (kernel_ulong_t)(info) } + +const struct pci_device_id gna_pci_ids[] = { + INTEL_GNA_DEVICE(GNA_DEV_HWID_CNL, &cnl_drv_info), + INTEL_GNA_DEVICE(GNA_DEV_HWID_EHL, &ehl_drv_info), + INTEL_GNA_DEVICE(GNA_DEV_HWID_GLK, &glk_drv_info), + INTEL_GNA_DEVICE(GNA_DEV_HWID_ICL, &icl_drv_info), + INTEL_GNA_DEVICE(GNA_DEV_HWID_JSL, &jsl_drv_info), + INTEL_GNA_DEVICE(GNA_DEV_HWID_TGL, &tgl_drv_info), + { } +}; + +MODULE_DEVICE_TABLE(pci, gna_pci_ids); + static int gna_dev_init(struct gna_private *gna_priv, struct pci_dev *pcidev, const struct pci_device_id *pci_id) { diff --git a/drivers/misc/gna/gna_device.h b/drivers/misc/gna/gna_device.h index ee234e474d43..22c47f2c03ec 100644 --- a/drivers/misc/gna/gna_device.h +++ b/drivers/misc/gna/gna_device.h @@ -56,6 +56,8 @@ struct gna_private { struct mutex memidr_lock; }; +extern const struct pci_device_id gna_pci_ids[]; + int gna_probe(struct pci_dev *dev, const struct pci_device_id *id); void gna_remove(struct pci_dev *dev); diff --git a/drivers/misc/gna/gna_driver.c b/drivers/misc/gna/gna_driver.c index 81f0f003f377..80981c448f3a 100644 --- a/drivers/misc/gna/gna_driver.c +++ b/drivers/misc/gna/gna_driver.c @@ -15,6 +15,7 @@ struct class *gna_class; static struct pci_driver gna_driver = { .name = GNA_DRV_NAME, + .id_table = gna_pci_ids, .probe = gna_probe, .remove = gna_remove, }; -- 2.28.0
[PATCH v1 04/12] gna: add memory handling
From: Tomasz Jankowski Patch adds memory handling - mapping, DMA, pinning. The GNA driver maps and unmaps the physical pages for 64-byte aligned buffer allocated by user space program. The pages of mapped memory are being locked only during actual computation. Patch adds configuration of the DMA scatter gather list for physical pages and generation of page table and page directory to be programmed in the GNA HW at the time of scoring initiation. GNA’s MMU is being configured based on specific request memory usage. As the MMU can address up to 256MB a single scoring request is limited to this amount of memory being used. GNA Library can allocate any number of memory regions for GNA usage. Its number and total capacity are limited by the OSs’ resources. Due to GNA MMU restrictions, even when using multiple memory regions, the sum of all the memory regions used within a single inference request must be less than 256MB. At least a single GNA memory region is needed to be allocated (and can be shared by multiple models). At the other extreme, each GNA tensor (e.g., weights/biases/inputs/outputs) could use its own, separate GNA memory region. Signed-off-by: Tomasz Jankowski Tested-by: Savo Novakovic Co-developed-by: Jianxun Zhang Signed-off-by: Jianxun Zhang Co-developed-by: Maciej Kwapulinski Signed-off-by: Maciej Kwapulinski --- drivers/misc/gna/Kbuild | 2 +- drivers/misc/gna/gna_device.c | 6 + drivers/misc/gna/gna_device.h | 11 +- drivers/misc/gna/gna_mem.c| 469 ++ drivers/misc/gna/gna_mem.h| 107 5 files changed, 593 insertions(+), 2 deletions(-) create mode 100644 drivers/misc/gna/gna_mem.c create mode 100644 drivers/misc/gna/gna_mem.h diff --git a/drivers/misc/gna/Kbuild b/drivers/misc/gna/Kbuild index 8620d88588e5..860b14c0e8d0 100644 --- a/drivers/misc/gna/Kbuild +++ b/drivers/misc/gna/Kbuild @@ -1,5 +1,5 @@ # SPDX-License-Identifier: GPL-2.0-only -gna-y := gna_device.o gna_driver.o gna_hw.o +gna-y := gna_device.o gna_driver.o gna_mem.o gna_hw.o obj-$(CONFIG_INTEL_GNA) += gna.o diff --git a/drivers/misc/gna/gna_device.c b/drivers/misc/gna/gna_device.c index 869507594f9e..f962c7e1e5e9 100644 --- a/drivers/misc/gna/gna_device.c +++ b/drivers/misc/gna/gna_device.c @@ -23,12 +23,18 @@ static int gna_dev_init(struct gna_private *gna_priv, struct pci_dev *pcidev, bld_reg = gna_reg_read(gna_priv->bar0.mem_addr, GNA_MMIO_IBUFFS); gna_priv->hw_info.in_buf_s = bld_reg & GENMASK(7, 0); + mutex_init(&gna_priv->mmu_lock); + + idr_init(&gna_priv->memory_idr); + mutex_init(&gna_priv->memidr_lock); + return 0; } /* Reverse gna_dev_init() */ static void gna_dev_deinit(struct gna_private *gna_priv) { + idr_destroy(&gna_priv->memory_idr); pci_set_drvdata(gna_priv->pdev, NULL); } diff --git a/drivers/misc/gna/gna_device.h b/drivers/misc/gna/gna_device.h index add8088ffa28..ee234e474d43 100644 --- a/drivers/misc/gna/gna_device.h +++ b/drivers/misc/gna/gna_device.h @@ -10,7 +10,7 @@ #include -#include "gna_hw.h" +#include "gna_mem.h" struct gna_drv_info { u32 hwid; @@ -45,6 +45,15 @@ struct gna_private { struct gna_pci_bar bar0; struct gna_drv_info info; struct gna_hw_info hw_info; + + struct gna_mmu_object mmu; + /* lock protecting mmu structure */ + struct mutex mmu_lock; + + /* memory objects */ + struct idr memory_idr; + /* lock protecting memory_idr */ + struct mutex memidr_lock; }; int gna_probe(struct pci_dev *dev, const struct pci_device_id *id); diff --git a/drivers/misc/gna/gna_mem.c b/drivers/misc/gna/gna_mem.c new file mode 100644 index ..a2ac3c31b4fb --- /dev/null +++ b/drivers/misc/gna/gna_mem.c @@ -0,0 +1,469 @@ +// SPDX-License-Identifier: GPL-2.0-only +// Copyright(c) 2017-2021 Intel Corporation + +#define pr_fmt(fmt) KBUILD_MODNAME " " fmt + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "gna_device.h" +#include "gna_driver.h" +#include "gna_mem.h" + +static void gna_mmu_init(struct gna_private *gna_priv) +{ + struct gna_mmu_object *mmu; + dma_addr_t pagetable_dma; + u32 *pgdirn; + int i; + + mmu = &gna_priv->mmu; + + pgdirn = mmu->hwdesc->mmu.pagedir_n; + + for (i = 0; i < mmu->num_pagetables; i++) { + pagetable_dma = mmu->pagetables_dma[i]; + pgdirn[i] = pagetable_dma >> PAGE_SHIFT; + } + + for (; i < GNA_PGDIRN_LEN; i++) + pgdirn[i] = GNA_PGDIR_INVALID; +} + +/* descriptor and page tables allocation */ +int gna_mmu_alloc(struct gna_private *gna_priv) +{ + struct gna_mmu_object *mmu; + int desc_size; + int i; + + if (gn
[PATCH v1 05/12] gna: initialize mmu
From: Tomasz Jankowski Setup mmu in the driver with a new memory component. Signed-off-by: Tomasz Jankowski Tested-by: Savo Novakovic Signed-off-by: Maciej Kwapulinski --- drivers/misc/gna/gna_device.c | 11 +++ 1 file changed, 11 insertions(+) diff --git a/drivers/misc/gna/gna_device.c b/drivers/misc/gna/gna_device.c index f962c7e1e5e9..d6a6d3cab570 100644 --- a/drivers/misc/gna/gna_device.c +++ b/drivers/misc/gna/gna_device.c @@ -23,6 +23,16 @@ static int gna_dev_init(struct gna_private *gna_priv, struct pci_dev *pcidev, bld_reg = gna_reg_read(gna_priv->bar0.mem_addr, GNA_MMIO_IBUFFS); gna_priv->hw_info.in_buf_s = bld_reg & GENMASK(7, 0); + if (gna_mmu_alloc(gna_priv)) { + dev_err(&gna_priv->dev, "gna mmu allocation failed\n"); + return -EFAULT; + } + dev_dbg(&pcidev->dev, "maximum memory size %llu num pd %d\n", + gna_priv->info.max_hw_mem, gna_priv->info.num_pagetables); + dev_dbg(&pcidev->dev, "desc rsvd size %d mmu vamax size %d\n", + gna_priv->info.desc_info.rsvd_size, + gna_priv->info.desc_info.mmu_info.vamax_size); + mutex_init(&gna_priv->mmu_lock); idr_init(&gna_priv->memory_idr); @@ -35,6 +45,7 @@ static int gna_dev_init(struct gna_private *gna_priv, struct pci_dev *pcidev, static void gna_dev_deinit(struct gna_private *gna_priv) { idr_destroy(&gna_priv->memory_idr); + gna_mmu_free(gna_priv); pci_set_drvdata(gna_priv->pdev, NULL); } -- 2.28.0
[PATCH v1 03/12] gna: read hardware info in the driver
From: Tomasz Jankowski Get the hardware information from register MMIO_IBUFFS Signed-off-by: Tomasz Jankowski Tested-by: Savo Novakovic Co-developed-by: Jianxun Zhang Signed-off-by: Jianxun Zhang Signed-off-by: Maciej Kwapulinski --- drivers/misc/gna/gna_device.c | 6 ++ 1 file changed, 6 insertions(+) diff --git a/drivers/misc/gna/gna_device.c b/drivers/misc/gna/gna_device.c index a6ef7e790e9e..869507594f9e 100644 --- a/drivers/misc/gna/gna_device.c +++ b/drivers/misc/gna/gna_device.c @@ -6,10 +6,13 @@ #include "gna_device.h" #include "gna_driver.h" +#include "gna_hw.h" static int gna_dev_init(struct gna_private *gna_priv, struct pci_dev *pcidev, const struct pci_device_id *pci_id) { + u32 bld_reg; + pci_set_drvdata(pcidev, gna_priv); gna_priv->parent = &pcidev->dev; @@ -17,6 +20,9 @@ static int gna_dev_init(struct gna_private *gna_priv, struct pci_dev *pcidev, gna_priv->info = *(struct gna_drv_info *)pci_id->driver_data; gna_priv->drv_priv = &gna_drv_priv; + bld_reg = gna_reg_read(gna_priv->bar0.mem_addr, GNA_MMIO_IBUFFS); + gna_priv->hw_info.in_buf_s = bld_reg & GENMASK(7, 0); + return 0; } -- 2.28.0
[PATCH v1 02/12] gna: add component of hardware operation
From: Tomasz Jankowski Add definitions and utilities to interact with the hardware device. Signed-off-by: Tomasz Jankowski Tested-by: Savo Novakovic Co-developed-by: Jianxun Zhang Signed-off-by: Jianxun Zhang Co-developed-by: Maciej Kwapulinski Signed-off-by: Maciej Kwapulinski --- drivers/misc/gna/Kbuild | 2 +- drivers/misc/gna/gna_device.h | 4 ++ drivers/misc/gna/gna_hw.c | 118 ++ drivers/misc/gna/gna_hw.h | 84 4 files changed, 207 insertions(+), 1 deletion(-) create mode 100644 drivers/misc/gna/gna_hw.c create mode 100644 drivers/misc/gna/gna_hw.h diff --git a/drivers/misc/gna/Kbuild b/drivers/misc/gna/Kbuild index 863956d5761a..8620d88588e5 100644 --- a/drivers/misc/gna/Kbuild +++ b/drivers/misc/gna/Kbuild @@ -1,5 +1,5 @@ # SPDX-License-Identifier: GPL-2.0-only -gna-y := gna_device.o gna_driver.o +gna-y := gna_device.o gna_driver.o gna_hw.o obj-$(CONFIG_INTEL_GNA) += gna.o diff --git a/drivers/misc/gna/gna_device.h b/drivers/misc/gna/gna_device.h index 736bc5af5081..add8088ffa28 100644 --- a/drivers/misc/gna/gna_device.h +++ b/drivers/misc/gna/gna_device.h @@ -10,12 +10,16 @@ #include +#include "gna_hw.h" + struct gna_drv_info { u32 hwid; u32 num_pagetables; u32 num_page_entries; u32 max_layer_count; u64 max_hw_mem; + + struct gna_desc_info desc_info; }; struct gna_pci_bar { diff --git a/drivers/misc/gna/gna_hw.c b/drivers/misc/gna/gna_hw.c new file mode 100644 index ..3b85c4b75fd8 --- /dev/null +++ b/drivers/misc/gna/gna_hw.c @@ -0,0 +1,118 @@ +// SPDX-License-Identifier: GPL-2.0-only +// Copyright(c) 2017-2021 Intel Corporation + +#include +#include + +#include + +#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; + + if (hw_status & GNA_ERROR) { + dev_dbg(&gna_priv->dev, "GNA completed with errors: %#x\n", hw_status); + status = -EIO; + } else if (hw_status & GNA_STS_SCORE_COMPLETED) { + status = 0; + dev_dbg(&gna_priv->dev, "GNA completed successfully: %#x\n", hw_status); + } else { + dev_err(&gna_priv->dev, "GNA not completed, status: %#x\n", hw_status); + status = -ENODATA; + } + + return status; +} + +void gna_print_error_status(struct gna_private *gna_priv, u32 hw_status) +{ + if (hw_status & GNA_STS_PARAM_OOR) + dev_dbg(&gna_priv->dev, "GNA error: Param Out Range Error\n"); + + if (hw_status & GNA_STS_VA_OOR) + dev_dbg(&gna_priv->dev, "GNA error: VA Out of Range Error\n"); + + if (hw_status & GNA_STS_PCI_MMU_ERR) + dev_dbg(&gna_priv->dev, "GNA error: PCI MMU Error\n"); + + if (hw_status & GNA_STS_PCI_DMA_ERR) + dev_dbg(&gna_priv->dev, "GNA error: PCI MMU Error\n"); + + if (hw_status & GNA_STS_PCI_UNEXCOMPL_ERR) + dev_dbg(&gna_priv->dev, "GNA error: PCI Unexpected Completion Error\n"); + + if (hw_status & GNA_STS_SATURATE) + dev_dbg(&gna_priv->dev, "GNA error: Saturation Reached !\n"); +} + +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->dev, "scoring started...\n"); +} + +static void gna_clear_saturation(struct gna_private *gna_priv) +{ + void __iomem *addr = gna_priv->bar0.mem_addr; + u32 val; + + val = gna_reg_read(addr, GNA_MMIO_STS); + if (val & GNA_STS_SATURATE) { + dev_dbg(&gna_priv->dev, "saturation reached\n"); + dev_dbg(&gna_priv->dev, "gna status: %#x\n", val); + + val = val & GNA_STS_SATURATE; + gna_reg_write(addr, GNA_MMIO_STS, val); + } +
[PATCH v1 12/12] gna: add a char device
From: Tomasz Jankowski The new char device is the node for applications in user space to interact with the driver. Signed-off-by: Tomasz Jankowski Tested-by: Savo Novakovic Co-developed-by: Jianxun Zhang Signed-off-by: Jianxun Zhang Co-developed-by: Maciej Kwapulinski Signed-off-by: Maciej Kwapulinski --- drivers/misc/gna/gna_device.c | 157 ++ drivers/misc/gna/gna_driver.c | 23 - 2 files changed, 178 insertions(+), 2 deletions(-) diff --git a/drivers/misc/gna/gna_device.c b/drivers/misc/gna/gna_device.c index 9faf0456fee2..7b2d3b4f863b 100644 --- a/drivers/misc/gna/gna_device.c +++ b/drivers/misc/gna/gna_device.c @@ -1,12 +1,14 @@ // SPDX-License-Identifier: GPL-2.0-only // Copyright(c) 2017-2021 Intel Corporation +#include #include #include #include "gna_device.h" #include "gna_driver.h" #include "gna_hw.h" +#include "gna_ioctl.h" #include "gna_request.h" #define GNA_DEV_HWID_CNL 0x5A11 @@ -85,6 +87,150 @@ const struct pci_device_id gna_pci_ids[] = { MODULE_DEVICE_TABLE(pci, gna_pci_ids); +static inline struct gna_private *inode_to_gna(struct inode *inode) +{ + return container_of(inode->i_cdev, struct gna_private, cdev); +} + +static int gna_open(struct inode *inode, struct file *f) +{ + struct gna_file_private *file_priv; + struct gna_private *gna_priv; + + gna_priv = inode_to_gna(inode); + if (!gna_priv) + return -ENODEV; + + file_priv = kzalloc(sizeof(*file_priv), GFP_KERNEL); + if (!file_priv) + return -ENOMEM; + + file_priv->fd = f; + file_priv->gna_priv = gna_priv; + + mutex_init(&file_priv->memlist_lock); + INIT_LIST_HEAD(&file_priv->memory_list); + + mutex_lock(&gna_priv->filelist_lock); + list_add_tail(&file_priv->flist, &gna_priv->file_list); + mutex_unlock(&gna_priv->filelist_lock); + + f->private_data = file_priv; + + return 0; +} + +static int gna_release(struct inode *inode, struct file *f) +{ + struct gna_file_private *iter_file, *temp_file; + struct gna_memory_object *iter_mo, *temp_mo; + struct gna_file_private *file_priv; + struct gna_private *gna_priv; + + gna_priv = inode_to_gna(inode); + if (!gna_priv) + return -ENODEV; + + /* free all memory objects created by that file */ + file_priv = (struct gna_file_private *)f->private_data; + mutex_lock(&file_priv->memlist_lock); + list_for_each_entry_safe(iter_mo, temp_mo, &file_priv->memory_list, file_mem_list) { + queue_work(gna_priv->request_wq, &iter_mo->work); + wait_event(iter_mo->waitq, true); + gna_memory_free(gna_priv, iter_mo); + } + mutex_unlock(&file_priv->memlist_lock); + + gna_delete_file_requests(f, gna_priv); + + /* delete itself from device's file list */ + mutex_lock(&gna_priv->filelist_lock); + list_for_each_entry_safe(iter_file, temp_file, &gna_priv->file_list, flist) { + if (iter_file->fd == f) { + list_del(&iter_file->flist); + f->private_data = NULL; + kfree(iter_file); + break; + } + } + mutex_unlock(&gna_priv->filelist_lock); + + return 0; +} + +static const struct file_operations gna_file_ops = { + .owner = THIS_MODULE, + .open = gna_open, + .release= gna_release, + .unlocked_ioctl = gna_ioctl, +}; + +/* Reverse gna_dev_create() */ +static void gna_dev_release(struct gna_private *gna_priv) +{ + cdev_device_del(&gna_priv->cdev, &gna_priv->dev); + + mutex_lock(&gna_drv_priv.lock); + __clear_bit(MINOR(gna_priv->dev.devt), gna_drv_priv.dev_map); + mutex_unlock(&gna_drv_priv.lock); + + dev_set_drvdata(&gna_priv->dev, NULL); +} + +static int gna_dev_create(struct gna_private *gna_priv) +{ + struct pci_dev *pcidev; + struct device *dev; + dev_t gna_devt; + int dev_num; + int major; + int minor; + int ret; + + pcidev = gna_priv->pdev; + + mutex_lock(&gna_drv_priv.lock); + + dev_num = find_first_zero_bit(gna_drv_priv.dev_map, GNA_MAX_DEVICES); + if (dev_num == GNA_MAX_DEVICES) { + mutex_unlock(&gna_drv_priv.lock); + dev_err(&pcidev->dev, "number of gna devices reached maximum\n"); + return -ENODEV; + } + + set_bit(dev_num, gna_drv_priv.dev_map); + major = MAJOR(gna_drv_priv.devt); + minor = gna_drv_priv.minor++; + + mutex_unlock(&gna_drv_priv.lock); + + gna
[PATCH v1 01/12] gna: add driver module
From: Tomasz Jankowski Add a new PCI driver for Intel(R) Gaussian & Neural Accelerator with basic support like module loading and unloading. The full function of the driver will be added by further changes. Signed-off-by: Tomasz Jankowski Tested-by: Savo Novakovic Co-developed-by: Jianxun Zhang Signed-off-by: Jianxun Zhang Co-developed-by: Maciej Kwapulinski Signed-off-by: Maciej Kwapulinski --- Documentation/misc-devices/gna.rst| 48 ++ Documentation/misc-devices/index.rst | 1 + .../userspace-api/ioctl/ioctl-number.rst | 1 + MAINTAINERS | 7 + drivers/misc/Kconfig | 1 + drivers/misc/Makefile | 1 + drivers/misc/gna/Kbuild | 5 + drivers/misc/gna/Kconfig | 13 ++ drivers/misc/gna/gna_device.c | 100 +++ drivers/misc/gna/gna_device.h | 50 ++ drivers/misc/gna/gna_driver.c | 65 drivers/misc/gna/gna_driver.h | 41 + include/uapi/misc/gna.h | 155 ++ 13 files changed, 488 insertions(+) create mode 100644 Documentation/misc-devices/gna.rst create mode 100644 drivers/misc/gna/Kbuild create mode 100644 drivers/misc/gna/Kconfig create mode 100644 drivers/misc/gna/gna_device.c create mode 100644 drivers/misc/gna/gna_device.h create mode 100644 drivers/misc/gna/gna_driver.c create mode 100644 drivers/misc/gna/gna_driver.h create mode 100644 include/uapi/misc/gna.h diff --git a/Documentation/misc-devices/gna.rst b/Documentation/misc-devices/gna.rst new file mode 100644 index ..ed3d5a89271d --- /dev/null +++ b/Documentation/misc-devices/gna.rst @@ -0,0 +1,48 @@ +.. SPDX-License-Identifier: GPL-2.0-only + += +Intel(R) Gaussian & Neural Accelerator (Intel(R) GNA) += + +Acronyms + +GNA- Gaussian & Neural Accelerator +GMM- Gaussian Mixer Model +CNN- Convolutional Neural Network +RNN- Recurrent Neural Networks +DNN- Deep Neural Networks + +Introduction + +The Intel(R) GNA is an Internal PCI fixed device available on several Intel platforms/SoCs. +Feature set depends on the Intel Chipset SKU. + +Intel(R) GNA provides hardware accelerated computation for GMMs and Neural Networks. +It supports several layer types: affine, recurrent, and convolutional among others. +Hardware also provides helper layer types for copying and transposing matrices. + +Linux Driver + +Intel(R) GNA driver is a pci driver as Intel(R) GNA is a PCI device. +The driver also registers a character device to expose file operations via dev node. + +The driver probes/removes PCI device, implements file operations, handles runtime +power management, and interacts with hardware through MMIO registers. + +Multiple processes can independently file many requests to the driver. These requests are +processed in a FIFO manner. The hardware can process one request at a time by using a FIFO +queue. + +IOCTL +- +Intel(R) GNA driver controls the device through IOCTL interfaces. +Following IOCTL commands are supported: + GNA_IOCTL_PARAM_GET gets driver and device capabilities. + + GNA_IOCTL_MEMORY_MAP lock user pages and GNA MMU setups for DMA transfer. + + GNA_IOCTL_MEMORY_UNMAP unlocks user pages and releases GNA MMU structures. + + GNA_IOCTL_COMPUTE submits a request to the device queue. + + GNA_IOCTL_WAIT blocks and waits on the submitted request. diff --git a/Documentation/misc-devices/index.rst b/Documentation/misc-devices/index.rst index 64420b3314fe..8cc01280e555 100644 --- a/Documentation/misc-devices/index.rst +++ b/Documentation/misc-devices/index.rst @@ -19,6 +19,7 @@ fit into other categories. bh1770glc eeprom c2port + gna ibmvmc ics932s401 isl29003 diff --git a/Documentation/userspace-api/ioctl/ioctl-number.rst b/Documentation/userspace-api/ioctl/ioctl-number.rst index a4c75a28c839..9fad36a43f4a 100644 --- a/Documentation/userspace-api/ioctl/ioctl-number.rst +++ b/Documentation/userspace-api/ioctl/ioctl-number.rst @@ -115,6 +115,7 @@ Code Seq#Include File Comments 'B' C0-FF advanced bbus <mailto:maas...@uni-freiburg.de> 'C' alllinux/soundcard.h conflict! 'C' 01-2F linux/capi.hconflict! +'C' 01-5F uapi/misc/gna.h conflict! 'C' F0-FF drivers/net/wan/cosa.h conflict! 'D' allarch/s390/include/asm/dasd.h 'D' 40-5F drivers/scsi/dpt/dtpi_ioctl.h diff --git a/MAINTAINERS b
[PATCH v1 00/12] Driver of Intel(R) Gaussian & Neural Accelerator
Dear kernel maintainers, This submission is a kernel driver to support Intel(R) Gaussian & Neural Accelerator (Intel(R) GNA). Intel(R) GNA is a PCI-based neural co-processor available on multiple Intel platforms. AI developers and users can offload continuous inference workloads to an Intel(R) GNA device in order to free processor resources and save power. Noise reduction and speech recognition are the examples of the workloads Intel(R) GNA deals with while its usage is not limited to the two. For a list of processors equipped with Intel(R) GNA device, please refer to this link: https://docs.openvinotoolkit.org/latest/openvino_docs_IE_DG_supported_plugins_GNA.html We think contributing this driver to the upstream kernel project is the best way for developers and users to get the latest Intel(R) GNA support in a Linux kernel, through the mainline to any Linux distributions installed on their systems. Upstreaming also enables contribution from developers around the world to the driver once it is merged. The driver works with Intel(R) libraries in user space. The Intel(R) driver exposes a few IOCTL interfaces for use by libraries in user space. The libraries are open sourced and are available at: https://github.com/intel/gna Prior to the submission, these items were tested or examined against GNA driver patch series put on top of v5.11-rc3 tag of mainline kernel: Linux Kernel patch submission checklist https://www.kernel.org/doc/html/latest/process/submit-checklist.html?highlight=submit%20checklist 1. If you use a facility then #include the file that defines/declares that facility. Don’t depend on other header files pulling in ones that you use. (Checked) 2. Builds cleanly: with applicable or modified CONFIG options =y, =m, and =n. No gcc warnings/errors, no linker warnings/errors. Passes allnoconfig, allmodconfig Builds successfully when using O=builddir (Tested by building kernel with Intel(R) GNA driver config set to ‘m’, ‘y’, and ‘n’; allmodconfig, allnoconfig and O=builddir) 3. Builds on multiple CPU architectures by using local cross-compile tools or some other build farm. (x86_64 architecture tested - this is architecture where GNA is present and validated, please refer to drivers/misc/gna/Kconfig) 4. ppc64 is a good architecture for cross-compilation checking because it tends to use unsigned long for 64-bit quantities. (x86_64 architecture tested - this is architecture where GNA is present and validated, please refer to drivers/misc/gna/Kconfig) 5. Check your patch for general style as detailed in Documentation/process/coding-style.rst. Check for trivial violations with the patch style checker prior to submission (scripts/checkpatch.pl). You should be able to justify all violations that remain in your patch. (Checked. Some warnings were in the output. We checked them and feel they can be ignored.) 6. Any new or modified CONFIG options do not muck up the config menu and default to off unless they meet the exception criteria documented in Documentation/kbuild/kconfig-language.rst Menu attributes: default value. (No explicit default value is provided because Kbuild system sets it off by default.) 7. All new Kconfig options have help text. (Checked) 8. Has been carefully reviewed with respect to relevant Kconfig combinations. This is very hard to get right with testing – brainpower pays off here. (Checked) 10. Use make checkstack and fix any problems that it finds. Note checkstack does not point out problems explicitly, but any one function that uses more than 512 bytes on the stack is a candidate for change. (Checked) 11. Include kernel-doc to document global kernel APIs. (Not required for static functions, but OK there also.) Use make htmldocs or make pdfdocs to check the kernel-doc and fix any issues. (Addressed by adding new gna.rst in Documentation; tested with output from ‘make htmldocs’) 12. Has been tested with CONFIG_PREEMPT, CONFIG_DEBUG_PREEMPT, CONFIG_DEBUG_SLAB, CONFIG_DEBUG_PAGEALLOC, CONFIG_DEBUG_MUTEXES, CONFIG_DEBUG_SPINLOCK, CONFIG_DEBUG_ATOMIC_SLEEP, CONFIG_PROVE_RCU and CONFIG_DEBUG_OBJECTS_RCU_HEAD all simultaneously enabled. (Checked) 13. Has been build- and runtime tested with and without CONFIG_SMP and CONFIG_PREEMPT. (Checked) 15. All new /proc entries are documented under Documentation/. (The driver doesn’t introduce any new procs) 16. All new kernel boot parameters are documented in Documentation/admin-guide/kernel-parameters.rst. (The driver doesn’t add boot parameters) 17. All new module parameters are documented with MODULE_PARM_DESC(). (Checked) 21. Newly-added code has been compiled with gcc -W (use make EXTRA_CFLAGS=-W). This will generate lots of noise, but is good for finding bugs like “warning: comparison between signed. and unsigned”. (Checked) 24. If any ioctl’s are added by the patch, then also update Documentation/userspace-api/ioctl/ioctl-number.rst. (Updated) The above results