]> rtime.felk.cvut.cz Git - sojka/nv-tegra/linux-3.10.git/commitdiff
video: tegra: host: Support static mappings
authorArto Merilainen <amerilainen@nvidia.com>
Sun, 7 Dec 2014 18:31:46 +0000 (20:31 +0200)
committerArto Merilainen <amerilainen@nvidia.com>
Tue, 6 Jan 2015 18:15:54 +0000 (10:15 -0800)
This patch adds support to make permanent mappings to all address
spaces. This feature can be used to map firmwares in case we need
to support multiple address spaces per engine.

Bug 1243060

Change-Id: I32378e810984382d48c489172f5eac1bc2c8da6f
Signed-off-by: Arto Merilainen <amerilainen@nvidia.com>
Reviewed-on: http://git-master/r/663633
Reviewed-by: Automatic_Commit_Validation_User
GVS: Gerrit_Virtual_Submit
Reviewed-by: Shridhar Rasal <srasal@nvidia.com>
drivers/video/tegra/host/bus_client.c
drivers/video/tegra/host/chip_support.h
drivers/video/tegra/host/host1x/host1x.c
drivers/video/tegra/host/host1x/host1x.h
drivers/video/tegra/host/nvhost_vm.c
drivers/video/tegra/host/nvhost_vm.h

index a7802435c875f2bad68eda0d99208f6869ebb272..568c2a30be6fba0f39f9cc84ce5231ea24259e76 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Tegra Graphics Host Client Module
  *
- * Copyright (c) 2010-2014, NVIDIA Corporation. All rights reserved.
+ * Copyright (c) 2010-2015, NVIDIA Corporation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms and conditions of the GNU General Public License,
@@ -324,11 +324,14 @@ static int __nvhost_channelopen(struct inode *inode,
                priv->timeout = 0;
 
        priv->vm = nvhost_vm_allocate(pdev);
+       if (!priv->vm)
+               goto fail_alloc_vm;
 
        mutex_unlock(&channel_lock);
 
        return 0;
 
+fail_alloc_vm:
 fail_power_on:
 fail_add_client:
        kfree(priv);
index 128f2a9754dc8f72a462be9a37229f38491bb51d..1a5a763502ea5287d65121234e80aff25cc87cce 100644 (file)
@@ -46,6 +46,7 @@ struct platform_device;
 struct host1x_actmon;
 struct nvhost_vm;
 struct nvhost_vm_buffer;
+struct nvhost_vm_static_buffer;
 
 struct nvhost_cdma_ops {
        void (*start)(struct nvhost_cdma *);
@@ -68,6 +69,8 @@ struct nvhost_vm_ops {
                          struct nvhost_vm_buffer *buffer);
        void (*unpin_buffer)(struct nvhost_vm *vm,
                             struct nvhost_vm_buffer *buffer);
+       int (*pin_static_buffer)(struct nvhost_vm *vm,
+                                struct nvhost_vm_static_buffer *sbuffer);
 };
 
 struct nvhost_pushbuffer_ops {
index 82c2248a4632a6ba8f716350142bd0e5af679ad6..1e8367cc649ccb9fcfd30387662bf4526929d09b 100644 (file)
@@ -3,7 +3,7 @@
  *
  * Tegra Graphics Host Driver Entrypoint
  *
- * Copyright (c) 2010-2014, NVIDIA Corporation. All rights reserved.
+ * Copyright (c) 2010-2015, NVIDIA Corporation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms and conditions of the GNU General Public License,
@@ -883,6 +883,9 @@ static int nvhost_probe(struct platform_device *dev)
        nvhost = host;
 
        host->dev = dev;
+       INIT_LIST_HEAD(&host->static_mappings_list);
+       INIT_LIST_HEAD(&host->vm_list);
+       mutex_init(&host->vm_mutex);
        mutex_init(&pdata->lock);
 
        /* Copy host1x parameters. The private_data gets replaced
index 9aecf7804abe582326be0e3eef68fe60e47109b4..0ca122730144479aba67b09c160e2f07dce4a196 100644 (file)
@@ -3,7 +3,7 @@
  *
  * Tegra Graphics Host Driver Entrypoint
  *
- * Copyright (c) 2010-2014, NVIDIA Corporation. All rights reserved.
+ * Copyright (c) 2010-2015, NVIDIA Corporation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms and conditions of the GNU General Public License,
@@ -85,7 +85,11 @@ struct nvhost_master {
        struct nvhost_channel **chlist; /* channel list */
        struct mutex chlist_mutex;      /* mutex for channel list */
        unsigned long allocated_channels;
-       unsigned long next_free_ch;
+
+       /* nvhost vm specific structures */
+       struct list_head static_mappings_list;
+       struct list_head vm_list;
+       struct mutex vm_mutex;
 };
 
 extern struct nvhost_master *nvhost;
index b6a8d8315a9ced8f012eab8576365de2300115b7..7cffd71a8a7468ed7ebe3191c36176cb7f259970 100644 (file)
@@ -31,6 +31,46 @@ struct nvhost_vm_pin {
        unsigned int num_buffers;
 };
 
+int nvhost_vm_map_static(struct platform_device *pdev,
+                        void *vaddr, dma_addr_t paddr,
+                        size_t size)
+{
+       struct nvhost_vm_static_buffer *sbuffer;
+       struct nvhost_master *host = nvhost_get_host(pdev);
+       struct nvhost_vm *vm;
+
+       /* if static mappings are not supported, exit */
+       if (!vm_op().pin_static_buffer)
+               return 0;
+
+       sbuffer = kzalloc(sizeof(*sbuffer), GFP_KERNEL);
+       if (!sbuffer)
+               return -ENOMEM;
+
+       sbuffer->paddr = paddr;
+       sbuffer->vaddr = vaddr;
+       sbuffer->size = size;
+       INIT_LIST_HEAD(&sbuffer->list);
+
+       /* take global vm mutex */
+       mutex_lock(&host->vm_mutex);
+
+       /* add this buffer into list of static mappings */
+       list_add_tail(&sbuffer->list, &host->static_mappings_list);
+
+       /* add the static mapping to all existing vms */
+       list_for_each_entry(vm, &host->vm_list, vm_list) {
+               int err = vm_op().pin_static_buffer(vm, sbuffer);
+               /* this is irreversible; just warn of failed mapping */
+               WARN_ON(err);
+       }
+
+       /* release the vm mutex */
+       mutex_unlock(&host->vm_mutex);
+
+       return 0;
+}
+
 static struct nvhost_vm_buffer *nvhost_vm_find_buffer(struct rb_root *root,
                                                      struct dma_buf *dmabuf)
 {
@@ -322,9 +362,15 @@ err_alloc_pin:
 static void nvhost_vm_deinit(struct kref *kref)
 {
        struct nvhost_vm *vm = container_of(kref, struct nvhost_vm, kref);
+       struct nvhost_master *host = nvhost_get_host(vm->pdev);
        struct nvhost_vm_buffer *buffer;
        struct rb_node *node;
 
+       /* remove this vm from the vms list */
+       mutex_lock(&host->vm_mutex);
+       list_del(&vm->vm_list);
+       mutex_unlock(&host->vm_mutex);
+
        mutex_lock(&vm->mutex);
 
        /* go through all remaining buffers (if any) and free them here */
@@ -358,6 +404,8 @@ void nvhost_vm_get(struct nvhost_vm *vm)
 
 struct nvhost_vm *nvhost_vm_allocate(struct platform_device *pdev)
 {
+       struct nvhost_vm_static_buffer *sbuffer;
+       struct nvhost_master *host = nvhost_get_host(pdev);
        struct nvhost_vm *vm;
 
        /* get room to keep vm */
@@ -376,8 +424,31 @@ struct nvhost_vm *nvhost_vm_allocate(struct platform_device *pdev)
                        goto err_init_vm;
        }
 
+       /* take global vm mutex */
+       mutex_lock(&host->vm_mutex);
+
+       /* add this vm into list of vms */
+       list_add_tail(&vm->vm_list, &host->vm_list);
+
+       /* map all statically mapped buffers to this vm */
+       if (vm_op().pin_static_buffer) {
+               list_for_each_entry(sbuffer,
+                                   &host->static_mappings_list,
+                                   list) {
+                       int err = vm_op().pin_static_buffer(vm, sbuffer);
+                       if (err)
+                               goto err_pin_static_buffers;
+               }
+       }
+
+       /* release the vm mutex */
+       mutex_unlock(&host->vm_mutex);
+
        return vm;
 
+err_pin_static_buffers:
+       mutex_unlock(&host->vm_mutex);
+       vm_op().deinit(vm);
 err_init_vm:
        kfree(vm);
 err_alloc_vm:
index ac4f1b2e3bf2dd0ba7f66cf31665637621fb3f28..ee8e83bfabb2e904497cdb28b64d5ca0400391de 100644 (file)
@@ -41,6 +41,9 @@ struct nvhost_vm {
 
        /* used by hardware layer */
        void *private_data;
+
+       /* to track all vms in the system */
+       struct list_head vm_list;
 };
 
 struct nvhost_vm_buffer {
@@ -66,6 +69,37 @@ struct nvhost_vm_buffer {
        void *private_data;
 };
 
+struct nvhost_vm_static_buffer {
+       struct sg_table *sgt;
+
+       void *vaddr;
+       dma_addr_t paddr;
+       size_t size;
+
+       /* list of all statically mapped buffers */
+       struct list_head list;
+};
+
+/**
+ * nvhost_vm_map_static - map allocated area to iova
+ *     @pdev: pointer to host1x or host1x client device
+ *     @vaddr: kernel virtual address
+ *     @paddr: desired physical address for this buffer
+ *     @size: size of the buffer (in bytes)
+ *
+ * This call maps given area to all existing (and future) address spaces.
+ * The mapping is permanent and cannot be removed. User of this API is
+ * responsible to ensure that the backing memory is not released at any
+ * point.
+ *
+ * Return 0 on succcess, error otherwise. Base address is returned
+ * in address pointer.
+ *
+ */
+int nvhost_vm_map_static(struct platform_device *pdev,
+                        void *vaddr, dma_addr_t paddr,
+                        size_t size);
+
 /**
  * nvhost_vm_pin_buffers - Pin mapped buffers to the hardware
  *     @vm: Pointer to nvhost_vm structure