diff options
| -rw-r--r-- | drivers/video/tegra/host/chip_support.h | 2 | ||||
| -rw-r--r-- | drivers/video/tegra/host/host1x/host1x_vm_t186.c | 4 | ||||
| -rw-r--r-- | drivers/video/tegra/host/iommu_context_dev.c | 51 | ||||
| -rw-r--r-- | drivers/video/tegra/host/iommu_context_dev.h | 2 | ||||
| -rw-r--r-- | drivers/video/tegra/host/nvhost_vm.c | 2 |
5 files changed, 51 insertions, 10 deletions
diff --git a/drivers/video/tegra/host/chip_support.h b/drivers/video/tegra/host/chip_support.h index 23fcf6f39..1fcd53c15 100644 --- a/drivers/video/tegra/host/chip_support.h +++ b/drivers/video/tegra/host/chip_support.h | |||
| @@ -65,7 +65,7 @@ struct nvhost_cdma_ops { | |||
| 65 | }; | 65 | }; |
| 66 | 66 | ||
| 67 | struct nvhost_vm_ops { | 67 | struct nvhost_vm_ops { |
| 68 | int (*init)(struct nvhost_vm *vm); | 68 | int (*init)(struct nvhost_vm *vm, void *identifier); |
| 69 | void (*deinit)(struct nvhost_vm *vm); | 69 | void (*deinit)(struct nvhost_vm *vm); |
| 70 | int (*pin_static_buffer)(struct platform_device *pdev, | 70 | int (*pin_static_buffer)(struct platform_device *pdev, |
| 71 | void *vaddr, dma_addr_t paddr, | 71 | void *vaddr, dma_addr_t paddr, |
diff --git a/drivers/video/tegra/host/host1x/host1x_vm_t186.c b/drivers/video/tegra/host/host1x/host1x_vm_t186.c index 65f0742c6..c198ec84e 100644 --- a/drivers/video/tegra/host/host1x/host1x_vm_t186.c +++ b/drivers/video/tegra/host/host1x/host1x_vm_t186.c | |||
| @@ -27,14 +27,14 @@ | |||
| 27 | /* 5 second timeout */ | 27 | /* 5 second timeout */ |
| 28 | #define NVHOST_VM_WAIT_TIMEOUT (5000) | 28 | #define NVHOST_VM_WAIT_TIMEOUT (5000) |
| 29 | 29 | ||
| 30 | static int host1x_vm_init(struct nvhost_vm *vm) | 30 | static int host1x_vm_init(struct nvhost_vm *vm, void *identifier) |
| 31 | { | 31 | { |
| 32 | struct platform_device *pdev; | 32 | struct platform_device *pdev; |
| 33 | unsigned int i = 0; | 33 | unsigned int i = 0; |
| 34 | 34 | ||
| 35 | /* wait until we have a context device */ | 35 | /* wait until we have a context device */ |
| 36 | do { | 36 | do { |
| 37 | pdev = iommu_context_dev_allocate(); | 37 | pdev = iommu_context_dev_allocate(identifier); |
| 38 | if (!pdev) { | 38 | if (!pdev) { |
| 39 | ++i; | 39 | ++i; |
| 40 | mdelay(1); | 40 | mdelay(1); |
diff --git a/drivers/video/tegra/host/iommu_context_dev.c b/drivers/video/tegra/host/iommu_context_dev.c index ead02e9dd..af9de61f3 100644 --- a/drivers/video/tegra/host/iommu_context_dev.c +++ b/drivers/video/tegra/host/iommu_context_dev.c | |||
| @@ -47,24 +47,65 @@ struct iommu_ctx { | |||
| 47 | struct list_head list; | 47 | struct list_head list; |
| 48 | struct device_dma_parameters dma_parms; | 48 | struct device_dma_parameters dma_parms; |
| 49 | bool allocated; | 49 | bool allocated; |
| 50 | void *prev_identifier; | ||
| 50 | }; | 51 | }; |
| 51 | 52 | ||
| 52 | static LIST_HEAD(iommu_ctx_list); | 53 | static LIST_HEAD(iommu_ctx_list); |
| 53 | static LIST_HEAD(iommu_static_mappings_list); | 54 | static LIST_HEAD(iommu_static_mappings_list); |
| 54 | static DEFINE_MUTEX(iommu_ctx_list_mutex); | 55 | static DEFINE_MUTEX(iommu_ctx_list_mutex); |
| 55 | 56 | ||
| 56 | struct platform_device *iommu_context_dev_allocate(void) | 57 | struct platform_device *iommu_context_dev_allocate(void *identifier) |
| 57 | { | 58 | { |
| 58 | struct iommu_ctx *ctx; | 59 | struct iommu_ctx *ctx, *ctx_new = NULL; |
| 60 | bool dirty = false; | ||
| 59 | 61 | ||
| 60 | mutex_lock(&iommu_ctx_list_mutex); | 62 | mutex_lock(&iommu_ctx_list_mutex); |
| 63 | /* | ||
| 64 | * First check if we have same identifier stashed into | ||
| 65 | * some context device | ||
| 66 | * If yes, use that context device since it will have all | ||
| 67 | * the mappings stashed too | ||
| 68 | */ | ||
| 61 | list_for_each_entry(ctx, &iommu_ctx_list, list) { | 69 | list_for_each_entry(ctx, &iommu_ctx_list, list) { |
| 62 | if (!ctx->allocated) { | 70 | if (!ctx->allocated && identifier == ctx->prev_identifier) { |
| 63 | ctx->allocated = true; | 71 | ctx->allocated = true; |
| 64 | mutex_unlock(&iommu_ctx_list_mutex); | 72 | mutex_unlock(&iommu_ctx_list_mutex); |
| 65 | return ctx->pdev; | 73 | return ctx->pdev; |
| 66 | } | 74 | } |
| 67 | } | 75 | } |
| 76 | |||
| 77 | /* | ||
| 78 | * Otherwise, find a device which does not have any identifier stashed | ||
| 79 | * If there is no device left without identifier stashed, use any of | ||
| 80 | * the free device and explicitly remove all the stashings from it | ||
| 81 | */ | ||
| 82 | list_for_each_entry(ctx, &iommu_ctx_list, list) { | ||
| 83 | if (!ctx->allocated && !ctx_new) { | ||
| 84 | ctx_new = ctx; | ||
| 85 | dirty = true; | ||
| 86 | } | ||
| 87 | if (!ctx->allocated && !ctx->prev_identifier) { | ||
| 88 | ctx_new = ctx; | ||
| 89 | dirty = false; | ||
| 90 | break; | ||
| 91 | } | ||
| 92 | } | ||
| 93 | |||
| 94 | if (ctx_new) { | ||
| 95 | if (dirty) { | ||
| 96 | /* | ||
| 97 | * Ensure that all stashed mappings are removed from this context device | ||
| 98 | * before this context device gets reassigned to some other process | ||
| 99 | */ | ||
| 100 | dma_buf_release_stash(&ctx_new->pdev->dev); | ||
| 101 | } | ||
| 102 | |||
| 103 | ctx_new->prev_identifier = identifier; | ||
| 104 | ctx_new->allocated = true; | ||
| 105 | mutex_unlock(&iommu_ctx_list_mutex); | ||
| 106 | return ctx_new->pdev; | ||
| 107 | } | ||
| 108 | |||
| 68 | mutex_unlock(&iommu_ctx_list_mutex); | 109 | mutex_unlock(&iommu_ctx_list_mutex); |
| 69 | 110 | ||
| 70 | return NULL; | 111 | return NULL; |
| @@ -200,8 +241,8 @@ static int iommu_context_dev_probe(struct platform_device *pdev) | |||
| 200 | pdev->dev.dma_parms = &ctx->dma_parms; | 241 | pdev->dev.dma_parms = &ctx->dma_parms; |
| 201 | dma_set_max_seg_size(&pdev->dev, UINT_MAX); | 242 | dma_set_max_seg_size(&pdev->dev, UINT_MAX); |
| 202 | 243 | ||
| 203 | /* disable lazy unmapping for context devices */ | 244 | /* flag required to handle stashings in context devices */ |
| 204 | dma_buf_disable_lazy_unmapping(&pdev->dev); | 245 | pdev->dev.context_dev = true; |
| 205 | 246 | ||
| 206 | dev_info(&pdev->dev, "initialized (streamid=%d)", | 247 | dev_info(&pdev->dev, "initialized (streamid=%d)", |
| 207 | iommu_get_hwid(pdev->dev.archdata.iommu, &pdev->dev, 0)); | 248 | iommu_get_hwid(pdev->dev.archdata.iommu, &pdev->dev, 0)); |
diff --git a/drivers/video/tegra/host/iommu_context_dev.h b/drivers/video/tegra/host/iommu_context_dev.h index e219265c2..9f0f40519 100644 --- a/drivers/video/tegra/host/iommu_context_dev.h +++ b/drivers/video/tegra/host/iommu_context_dev.h | |||
| @@ -19,7 +19,7 @@ | |||
| 19 | #ifndef IOMMU_CONTEXT_DEV_H | 19 | #ifndef IOMMU_CONTEXT_DEV_H |
| 20 | #define IOMMU_CONTEXT_DEV_H | 20 | #define IOMMU_CONTEXT_DEV_H |
| 21 | 21 | ||
| 22 | struct platform_device *iommu_context_dev_allocate(void); | 22 | struct platform_device *iommu_context_dev_allocate(void *identifier); |
| 23 | void iommu_context_dev_release(struct platform_device *pdev); | 23 | void iommu_context_dev_release(struct platform_device *pdev); |
| 24 | int iommu_context_dev_get_streamid(struct platform_device *pdev); | 24 | int iommu_context_dev_get_streamid(struct platform_device *pdev); |
| 25 | int iommu_context_dev_map_static(void *vaddr, dma_addr_t paddr, size_t size); | 25 | int iommu_context_dev_map_static(void *vaddr, dma_addr_t paddr, size_t size); |
diff --git a/drivers/video/tegra/host/nvhost_vm.c b/drivers/video/tegra/host/nvhost_vm.c index aaa03eb9b..979bb31fd 100644 --- a/drivers/video/tegra/host/nvhost_vm.c +++ b/drivers/video/tegra/host/nvhost_vm.c | |||
| @@ -224,7 +224,7 @@ struct nvhost_vm *nvhost_vm_allocate(struct platform_device *pdev, | |||
| 224 | mutex_unlock(&host->vm_mutex); | 224 | mutex_unlock(&host->vm_mutex); |
| 225 | 225 | ||
| 226 | if (vm_op().init && vm->enable_hw) { | 226 | if (vm_op().init && vm->enable_hw) { |
| 227 | err = vm_op().init(vm); | 227 | err = vm_op().init(vm, identifier); |
| 228 | if (err) | 228 | if (err) |
| 229 | goto err_init; | 229 | goto err_init; |
| 230 | } | 230 | } |
