Message ID | 20220621151022.1416300-5-cyndis@kapsi.fi (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | Host1x context isolation support | expand |
Hi Mikko, Thank you for the patch! Yet something to improve: [auto build test ERROR on drm/drm-next] [also build test ERROR on tegra/for-next linus/master v5.19-rc3] [cannot apply to tegra-drm/drm/tegra/for-next next-20220621] [If your patch is applied to the wrong git tree, kindly drop us a note. And when submitting patch, we suggest to use '--base' as documented in https://git-scm.com/docs/git-format-patch] url: https://github.com/intel-lab-lkp/linux/commits/Mikko-Perttunen/Host1x-context-isolation-support/20220621-231339 base: git://anongit.freedesktop.org/drm/drm drm-next config: arm64-randconfig-r021-20220622 (https://download.01.org/0day-ci/archive/20220622/202206221557.laES8yNQ-lkp@intel.com/config) compiler: clang version 15.0.0 (https://github.com/llvm/llvm-project 8b8d126598ce7bd5243da7f94f69fa1104288bee) reproduce (this is a W=1 build): wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross chmod +x ~/bin/make.cross # install arm64 cross compiling tool for clang build # apt-get install binutils-aarch64-linux-gnu # https://github.com/intel-lab-lkp/linux/commit/2501beeae7469b805f9f624049fd56643cf6e18e git remote add linux-review https://github.com/intel-lab-lkp/linux git fetch --no-tags linux-review Mikko-Perttunen/Host1x-context-isolation-support/20220621-231339 git checkout 2501beeae7469b805f9f624049fd56643cf6e18e # save the config file mkdir build_dir && cp config build_dir/.config COMPILER_INSTALL_PATH=$HOME/0day COMPILER=clang make.cross W=1 O=build_dir ARCH=arm64 SHELL=/bin/bash drivers/gpu/host1x/ If you fix the issue, kindly add following tag where applicable Reported-by: kernel test robot <lkp@intel.com> All errors (new ones prefixed by >>): >> drivers/gpu/host1x/context.c:80:28: error: no member named 'ids' in 'struct iommu_fwspec' ctx->stream_id = fwspec->ids[0] & 0xffff; ~~~~~~ ^ 1 error generated. vim +80 drivers/gpu/host1x/context.c 15 16 int host1x_memory_context_list_init(struct host1x *host1x) 17 { 18 struct host1x_memory_context_list *cdl = &host1x->context_list; 19 struct device_node *node = host1x->dev->of_node; 20 struct host1x_memory_context *ctx; 21 unsigned int i; 22 int err; 23 24 cdl->devs = NULL; 25 cdl->len = 0; 26 mutex_init(&cdl->lock); 27 28 err = of_property_count_u32_elems(node, "iommu-map"); 29 if (err < 0) 30 return 0; 31 32 cdl->devs = kcalloc(err, sizeof(*cdl->devs), GFP_KERNEL); 33 if (!cdl->devs) 34 return -ENOMEM; 35 cdl->len = err / 4; 36 37 for (i = 0; i < cdl->len; i++) { 38 struct iommu_fwspec *fwspec; 39 40 ctx = &cdl->devs[i]; 41 42 ctx->host = host1x; 43 44 device_initialize(&ctx->dev); 45 46 /* 47 * Due to an issue with T194 NVENC, only 38 bits can be used. 48 * Anyway, 256GiB of IOVA ought to be enough for anyone. 49 */ 50 ctx->dma_mask = DMA_BIT_MASK(38); 51 ctx->dev.dma_mask = &ctx->dma_mask; 52 ctx->dev.coherent_dma_mask = ctx->dma_mask; 53 dev_set_name(&ctx->dev, "host1x-ctx.%d", i); 54 ctx->dev.bus = &host1x_context_device_bus_type; 55 ctx->dev.parent = host1x->dev; 56 57 dma_set_max_seg_size(&ctx->dev, UINT_MAX); 58 59 err = device_add(&ctx->dev); 60 if (err) { 61 dev_err(host1x->dev, "could not add context device %d: %d\n", i, err); 62 goto del_devices; 63 } 64 65 err = of_dma_configure_id(&ctx->dev, node, true, &i); 66 if (err) { 67 dev_err(host1x->dev, "IOMMU configuration failed for context device %d: %d\n", 68 i, err); 69 device_del(&ctx->dev); 70 goto del_devices; 71 } 72 73 fwspec = dev_iommu_fwspec_get(&ctx->dev); 74 if (!fwspec) { 75 dev_err(host1x->dev, "Context device %d has no IOMMU!\n", i); 76 device_del(&ctx->dev); 77 goto del_devices; 78 } 79 > 80 ctx->stream_id = fwspec->ids[0] & 0xffff; 81 } 82 83 return 0; 84 85 del_devices: 86 while (i--) 87 device_del(&cdl->devs[i].dev); 88 89 kfree(cdl->devs); 90 cdl->len = 0; 91 92 return err; 93 } 94
Hi Mikko, Thank you for the patch! Yet something to improve: [auto build test ERROR on drm/drm-next] [also build test ERROR on tegra/for-next linus/master v5.19-rc5] [cannot apply to tegra-drm/drm/tegra/for-next next-20220704] [If your patch is applied to the wrong git tree, kindly drop us a note. And when submitting patch, we suggest to use '--base' as documented in https://git-scm.com/docs/git-format-patch] url: https://github.com/intel-lab-lkp/linux/commits/Mikko-Perttunen/Host1x-context-isolation-support/20220621-231339 base: git://anongit.freedesktop.org/drm/drm drm-next config: arm-randconfig-r005-20220703 (https://download.01.org/0day-ci/archive/20220705/202207051045.JWeVR4tW-lkp@intel.com/config) compiler: arm-linux-gnueabi-gcc (GCC) 11.3.0 reproduce (this is a W=1 build): wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross chmod +x ~/bin/make.cross # https://github.com/intel-lab-lkp/linux/commit/2501beeae7469b805f9f624049fd56643cf6e18e git remote add linux-review https://github.com/intel-lab-lkp/linux git fetch --no-tags linux-review Mikko-Perttunen/Host1x-context-isolation-support/20220621-231339 git checkout 2501beeae7469b805f9f624049fd56643cf6e18e # save the config file mkdir build_dir && cp config build_dir/.config COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-11.3.0 make.cross W=1 O=build_dir ARCH=arm SHELL=/bin/bash If you fix the issue, kindly add following tag where applicable Reported-by: kernel test robot <lkp@intel.com> All errors (new ones prefixed by >>): drivers/gpu/host1x/context.c: In function 'host1x_memory_context_list_init': >> drivers/gpu/host1x/context.c:80:40: error: 'struct iommu_fwspec' has no member named 'ids' 80 | ctx->stream_id = fwspec->ids[0] & 0xffff; | ^~ vim +80 drivers/gpu/host1x/context.c 15 16 int host1x_memory_context_list_init(struct host1x *host1x) 17 { 18 struct host1x_memory_context_list *cdl = &host1x->context_list; 19 struct device_node *node = host1x->dev->of_node; 20 struct host1x_memory_context *ctx; 21 unsigned int i; 22 int err; 23 24 cdl->devs = NULL; 25 cdl->len = 0; 26 mutex_init(&cdl->lock); 27 28 err = of_property_count_u32_elems(node, "iommu-map"); 29 if (err < 0) 30 return 0; 31 32 cdl->devs = kcalloc(err, sizeof(*cdl->devs), GFP_KERNEL); 33 if (!cdl->devs) 34 return -ENOMEM; 35 cdl->len = err / 4; 36 37 for (i = 0; i < cdl->len; i++) { 38 struct iommu_fwspec *fwspec; 39 40 ctx = &cdl->devs[i]; 41 42 ctx->host = host1x; 43 44 device_initialize(&ctx->dev); 45 46 /* 47 * Due to an issue with T194 NVENC, only 38 bits can be used. 48 * Anyway, 256GiB of IOVA ought to be enough for anyone. 49 */ 50 ctx->dma_mask = DMA_BIT_MASK(38); 51 ctx->dev.dma_mask = &ctx->dma_mask; 52 ctx->dev.coherent_dma_mask = ctx->dma_mask; 53 dev_set_name(&ctx->dev, "host1x-ctx.%d", i); 54 ctx->dev.bus = &host1x_context_device_bus_type; 55 ctx->dev.parent = host1x->dev; 56 57 dma_set_max_seg_size(&ctx->dev, UINT_MAX); 58 59 err = device_add(&ctx->dev); 60 if (err) { 61 dev_err(host1x->dev, "could not add context device %d: %d\n", i, err); 62 goto del_devices; 63 } 64 65 err = of_dma_configure_id(&ctx->dev, node, true, &i); 66 if (err) { 67 dev_err(host1x->dev, "IOMMU configuration failed for context device %d: %d\n", 68 i, err); 69 device_del(&ctx->dev); 70 goto del_devices; 71 } 72 73 fwspec = dev_iommu_fwspec_get(&ctx->dev); 74 if (!fwspec) { 75 dev_err(host1x->dev, "Context device %d has no IOMMU!\n", i); 76 device_del(&ctx->dev); 77 goto del_devices; 78 } 79 > 80 ctx->stream_id = fwspec->ids[0] & 0xffff; 81 } 82 83 return 0; 84 85 del_devices: 86 while (i--) 87 device_del(&cdl->devs[i].dev); 88 89 kfree(cdl->devs); 90 cdl->len = 0; 91 92 return err; 93 } 94
diff --git a/drivers/gpu/host1x/Makefile b/drivers/gpu/host1x/Makefile index c891a3e33844..8a65e13d113a 100644 --- a/drivers/gpu/host1x/Makefile +++ b/drivers/gpu/host1x/Makefile @@ -10,6 +10,7 @@ host1x-y = \ debug.o \ mipi.o \ fence.o \ + context.o \ hw/host1x01.o \ hw/host1x02.o \ hw/host1x04.o \ diff --git a/drivers/gpu/host1x/context.c b/drivers/gpu/host1x/context.c new file mode 100644 index 000000000000..d7d95b69a72a --- /dev/null +++ b/drivers/gpu/host1x/context.c @@ -0,0 +1,160 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2021, NVIDIA Corporation. + */ + +#include <linux/device.h> +#include <linux/kref.h> +#include <linux/of.h> +#include <linux/of_platform.h> +#include <linux/pid.h> +#include <linux/slab.h> + +#include "context.h" +#include "dev.h" + +int host1x_memory_context_list_init(struct host1x *host1x) +{ + struct host1x_memory_context_list *cdl = &host1x->context_list; + struct device_node *node = host1x->dev->of_node; + struct host1x_memory_context *ctx; + unsigned int i; + int err; + + cdl->devs = NULL; + cdl->len = 0; + mutex_init(&cdl->lock); + + err = of_property_count_u32_elems(node, "iommu-map"); + if (err < 0) + return 0; + + cdl->devs = kcalloc(err, sizeof(*cdl->devs), GFP_KERNEL); + if (!cdl->devs) + return -ENOMEM; + cdl->len = err / 4; + + for (i = 0; i < cdl->len; i++) { + struct iommu_fwspec *fwspec; + + ctx = &cdl->devs[i]; + + ctx->host = host1x; + + device_initialize(&ctx->dev); + + /* + * Due to an issue with T194 NVENC, only 38 bits can be used. + * Anyway, 256GiB of IOVA ought to be enough for anyone. + */ + ctx->dma_mask = DMA_BIT_MASK(38); + ctx->dev.dma_mask = &ctx->dma_mask; + ctx->dev.coherent_dma_mask = ctx->dma_mask; + dev_set_name(&ctx->dev, "host1x-ctx.%d", i); + ctx->dev.bus = &host1x_context_device_bus_type; + ctx->dev.parent = host1x->dev; + + dma_set_max_seg_size(&ctx->dev, UINT_MAX); + + err = device_add(&ctx->dev); + if (err) { + dev_err(host1x->dev, "could not add context device %d: %d\n", i, err); + goto del_devices; + } + + err = of_dma_configure_id(&ctx->dev, node, true, &i); + if (err) { + dev_err(host1x->dev, "IOMMU configuration failed for context device %d: %d\n", + i, err); + device_del(&ctx->dev); + goto del_devices; + } + + fwspec = dev_iommu_fwspec_get(&ctx->dev); + if (!fwspec) { + dev_err(host1x->dev, "Context device %d has no IOMMU!\n", i); + device_del(&ctx->dev); + goto del_devices; + } + + ctx->stream_id = fwspec->ids[0] & 0xffff; + } + + return 0; + +del_devices: + while (i--) + device_del(&cdl->devs[i].dev); + + kfree(cdl->devs); + cdl->len = 0; + + return err; +} + +void host1x_memory_context_list_free(struct host1x_memory_context_list *cdl) +{ + unsigned int i; + + for (i = 0; i < cdl->len; i++) + device_del(&cdl->devs[i].dev); + + kfree(cdl->devs); + cdl->len = 0; +} + +struct host1x_memory_context *host1x_memory_context_alloc(struct host1x *host1x, + struct pid *pid) +{ + struct host1x_memory_context_list *cdl = &host1x->context_list; + struct host1x_memory_context *free = NULL; + int i; + + if (!cdl->len) + return ERR_PTR(-EOPNOTSUPP); + + mutex_lock(&cdl->lock); + + for (i = 0; i < cdl->len; i++) { + struct host1x_memory_context *cd = &cdl->devs[i]; + + if (cd->owner == pid) { + refcount_inc(&cd->ref); + mutex_unlock(&cdl->lock); + return cd; + } else if (!cd->owner && !free) { + free = cd; + } + } + + if (!free) { + mutex_unlock(&cdl->lock); + return ERR_PTR(-EBUSY); + } + + refcount_set(&free->ref, 1); + free->owner = get_pid(pid); + + mutex_unlock(&cdl->lock); + + return free; +} +EXPORT_SYMBOL_GPL(host1x_memory_context_alloc); + +void host1x_memory_context_get(struct host1x_memory_context *cd) +{ + refcount_inc(&cd->ref); +} +EXPORT_SYMBOL_GPL(host1x_memory_context_get); + +void host1x_memory_context_put(struct host1x_memory_context *cd) +{ + struct host1x_memory_context_list *cdl = &cd->host->context_list; + + if (refcount_dec_and_mutex_lock(&cd->ref, &cdl->lock)) { + put_pid(cd->owner); + cd->owner = NULL; + mutex_unlock(&cdl->lock); + } +} +EXPORT_SYMBOL_GPL(host1x_memory_context_put); diff --git a/drivers/gpu/host1x/context.h b/drivers/gpu/host1x/context.h new file mode 100644 index 000000000000..db8ff0a1f4f3 --- /dev/null +++ b/drivers/gpu/host1x/context.h @@ -0,0 +1,27 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Host1x context devices + * + * Copyright (c) 2020, NVIDIA Corporation. + */ + +#ifndef __HOST1X_CONTEXT_H +#define __HOST1X_CONTEXT_H + +#include <linux/mutex.h> +#include <linux/refcount.h> + +struct host1x; + +extern struct bus_type host1x_context_device_bus_type; + +struct host1x_memory_context_list { + struct mutex lock; + struct host1x_memory_context *devs; + unsigned int len; +}; + +int host1x_memory_context_list_init(struct host1x *host1x); +void host1x_memory_context_list_free(struct host1x_memory_context_list *cdl); + +#endif diff --git a/drivers/gpu/host1x/dev.c b/drivers/gpu/host1x/dev.c index 80c685ab3e30..89cc79a48eab 100644 --- a/drivers/gpu/host1x/dev.c +++ b/drivers/gpu/host1x/dev.c @@ -28,6 +28,7 @@ #include "bus.h" #include "channel.h" +#include "context.h" #include "debug.h" #include "dev.h" #include "intr.h" @@ -503,10 +504,16 @@ static int host1x_probe(struct platform_device *pdev) goto iommu_exit; } + err = host1x_memory_context_list_init(host); + if (err) { + dev_err(&pdev->dev, "failed to initialize context list\n"); + goto free_channels; + } + err = host1x_syncpt_init(host); if (err) { dev_err(&pdev->dev, "failed to initialize syncpts\n"); - goto free_channels; + goto free_contexts; } err = host1x_intr_init(host, syncpt_irq); @@ -550,6 +557,8 @@ static int host1x_probe(struct platform_device *pdev) host1x_intr_deinit(host); deinit_syncpt: host1x_syncpt_deinit(host); +free_contexts: + host1x_memory_context_list_free(&host->context_list); free_channels: host1x_channel_list_free(&host->channel_list); iommu_exit: @@ -571,6 +580,7 @@ static int host1x_remove(struct platform_device *pdev) host1x_intr_deinit(host); host1x_syncpt_deinit(host); + host1x_memory_context_list_free(&host->context_list); host1x_channel_list_free(&host->channel_list); host1x_iommu_exit(host); host1x_bo_cache_destroy(&host->cache); diff --git a/drivers/gpu/host1x/dev.h b/drivers/gpu/host1x/dev.h index ca4b082f0cd4..7552a4554534 100644 --- a/drivers/gpu/host1x/dev.h +++ b/drivers/gpu/host1x/dev.h @@ -14,6 +14,7 @@ #include "cdma.h" #include "channel.h" +#include "context.h" #include "intr.h" #include "job.h" #include "syncpt.h" @@ -141,6 +142,7 @@ struct host1x { struct mutex syncpt_mutex; struct host1x_channel_list channel_list; + struct host1x_memory_context_list context_list; struct dentry *debugfs; diff --git a/include/linux/host1x.h b/include/linux/host1x.h index c0bf4e581fe9..3f368fdb8445 100644 --- a/include/linux/host1x.h +++ b/include/linux/host1x.h @@ -446,4 +446,22 @@ int tegra_mipi_disable(struct tegra_mipi_device *device); int tegra_mipi_start_calibration(struct tegra_mipi_device *device); int tegra_mipi_finish_calibration(struct tegra_mipi_device *device); +/* host1x memory contexts */ + +struct host1x_memory_context { + struct host1x *host; + + refcount_t ref; + struct pid *owner; + + struct device dev; + u64 dma_mask; + u32 stream_id; +}; + +struct host1x_memory_context *host1x_memory_context_alloc(struct host1x *host1x, + struct pid *pid); +void host1x_memory_context_get(struct host1x_memory_context *cd); +void host1x_memory_context_put(struct host1x_memory_context *cd); + #endif