From 7328f572804c9535845f62b027063aeaf10e402a Mon Sep 17 00:00:00 2001 From: Aingara Paramakuru Date: Mon, 21 Apr 2014 20:44:50 -0400 Subject: [PATCH 01/21] video: tegra: virt: add virtualization interfaces Tegra graphics virtualization (host1x syncpoint and gpu) is now exposed to client drivers (nvhost and nvgpu). These interfaces rely on a communication framework to communicate with the server driver that actually implements the back-end routines. Bug 1509608 Change-Id: I5277f4b024953772a2215d33afa178162f5f9232 Reviewed-on: http://git-master/r/440120 Reviewed-on: http://git-master/r/1198193 Signed-off-by: Aniruddha Banerjee Reviewed-on: http://git-master/r/1314828 GVS: Gerrit_Virtual_Submit Reviewed-by: Timo Alho --- drivers/video/tegra/virt/Makefile | 1 + drivers/video/tegra/virt/tegra_gr_comm.c | 531 +++++++++++++++++++++++ 2 files changed, 532 insertions(+) create mode 100644 drivers/video/tegra/virt/Makefile create mode 100644 drivers/video/tegra/virt/tegra_gr_comm.c diff --git a/drivers/video/tegra/virt/Makefile b/drivers/video/tegra/virt/Makefile new file mode 100644 index 00000000..ccf4b29c --- /dev/null +++ b/drivers/video/tegra/virt/Makefile @@ -0,0 +1 @@ +obj-$(CONFIG_TEGRA_GR_VIRTUALIZATION) += tegra_gr_comm.o diff --git a/drivers/video/tegra/virt/tegra_gr_comm.c b/drivers/video/tegra/virt/tegra_gr_comm.c new file mode 100644 index 00000000..ff78c093 --- /dev/null +++ b/drivers/video/tegra/virt/tegra_gr_comm.c @@ -0,0 +1,531 @@ +/* + * Tegra Graphics Virtualization Communication Framework + * + * Copyright (c) 2013-2014, 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, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define NUM_QUEUES 4 +#define NUM_CONTEXTS 2 + +#define ID_SHIFT 11 +#define ID_MASK 1 +#define ID0_PEER_ID_SHIFT 4 +#define ID0_QUEUE_ID_SHIFT 1 +#define ID0_QUEUE_ID_MASK 7 +#define ID0_VCTX_SHIFT 0 +#define ID0_VCTX_MASK 1 +#define ID1_IRQ_SHIFT 0 + +#define GEN_ID0(vctx, queue_id, peer_id) \ + ((peer_id << ID0_PEER_ID_SHIFT) | \ + (queue_id << ID0_QUEUE_ID_SHIFT) | \ + (vctx << ID0_VCTX_SHIFT) | \ + (0 << ID_SHIFT)) +#define GEN_ID1(irq) \ + ((irq << ID1_IRQ_SHIFT) | \ + (1 << ID_SHIFT)) +#define IS_ID1(id) ((id >> ID_SHIFT) & ID_MASK) +#define VCTX_FROM_ID0(id) ((id >> ID0_VCTX_SHIFT) & ID0_VCTX_MASK) +#define QUEUE_ID_FROM_ID0(id) ((id >> ID0_QUEUE_ID_SHIFT) & ID0_QUEUE_ID_MASK) + +enum { + IVC_DIR_TX = 0, + IVC_DIR_RX, + NUM_IVC_DIR +}; + +struct gr_comm_ivc_context { + u32 peer; + wait_queue_head_t wq[NUM_IVC_DIR]; + struct tegra_hv_ivc_cookie *cookie; + struct gr_comm_queue *queue; + struct task_struct *rx_thread; + struct platform_device *pdev; +}; + +struct gr_comm_element { + u32 sender; + size_t size; + void *data; + struct list_head list; + struct gr_comm_queue *queue; +}; + +struct gr_comm_queue { + struct semaphore sem; + struct mutex lock; + struct mutex resp_lock; + struct list_head pending; + struct list_head free; + size_t size; + struct kmem_cache *element_cache; + bool valid; +}; + +struct gr_comm_context { + struct gr_comm_queue queue[NUM_QUEUES]; +}; + +enum { + PROP_IVC_NODE = 0, + PROP_IVC_INST, + NUM_PROP +}; + +static struct gr_comm_context contexts[NUM_CONTEXTS]; +static DEFINE_IDR(ivc_ctx_idr); +static u32 server_vmid; + +u32 tegra_gr_comm_get_server_vmid(void) +{ + return server_vmid; +} + +static void free_ivc(u32 virt_ctx, u32 queue_start, u32 queue_end) +{ + struct gr_comm_ivc_context *tmp; + int id; + + idr_for_each_entry(&ivc_ctx_idr, tmp, id) { + if (VCTX_FROM_ID0(id) == virt_ctx && + QUEUE_ID_FROM_ID0(id) >= queue_start && + QUEUE_ID_FROM_ID0(id) < queue_end) { + idr_remove(&ivc_ctx_idr, id); + if (tmp->rx_thread) + kthread_stop(tmp->rx_thread); + + if (tmp->cookie) { + idr_remove(&ivc_ctx_idr, + GEN_ID1(tmp->cookie->irq)); + tegra_hv_ivc_unreserve(tmp->cookie); + } + kfree(tmp); + } + } +} + +static void ivc_rx(struct tegra_hv_ivc_cookie *ivck) +{ + struct gr_comm_ivc_context *ctx = + idr_find(&ivc_ctx_idr, GEN_ID1(ivck->irq)); + + if (!ctx) + return; + + wake_up(&ctx->wq[IVC_DIR_RX]); +} + +static void ivc_tx(struct tegra_hv_ivc_cookie *ivck) +{ + struct gr_comm_ivc_context *ctx = + idr_find(&ivc_ctx_idr, GEN_ID1(ivck->irq)); + + if (!ctx) + return; + + wake_up(&ctx->wq[IVC_DIR_TX]); +} + +static const struct tegra_hv_ivc_ops ivc_ops = { ivc_rx, ivc_tx }; + +static int queue_add(struct gr_comm_queue *queue, const char *data, + u32 peer, struct tegra_hv_ivc_cookie *ivck) +{ + struct gr_comm_element *element; + + mutex_lock(&queue->lock); + if (list_empty(&queue->free)) { + element = kmem_cache_alloc(queue->element_cache, + GFP_KERNEL); + if (!element) { + mutex_unlock(&queue->lock); + return -ENOMEM; + } + element->data = (char *)element + sizeof(*element); + element->queue = queue; + } else { + element = list_first_entry(&queue->free, + struct gr_comm_element, list); + list_del(&element->list); + } + + element->sender = peer; + element->size = queue->size; + if (ivck) { + int ret = tegra_hv_ivc_read(ivck, element->data, element->size); + if (ret != element->size) { + list_add(&element->list, &queue->free); + mutex_unlock(&queue->lock); + return -ENOMEM; + } + } else + memcpy(element->data, data, element->size); + list_add_tail(&element->list, &queue->pending); + mutex_unlock(&queue->lock); + up(&queue->sem); + return 0; +} + +static int ivc_rx_thread(void *arg) +{ + struct gr_comm_ivc_context *ctx = (struct gr_comm_ivc_context *)arg; + struct device *dev = &ctx->pdev->dev; + int ret; + + while (!kthread_should_stop()) { + if (!tegra_hv_ivc_can_read(ctx->cookie)) { + ret = wait_event_timeout(ctx->wq[IVC_DIR_RX], + tegra_hv_ivc_can_read(ctx->cookie) || + kthread_should_stop(), + msecs_to_jiffies(250)); + + if (kthread_should_stop()) + break; + else if (!ret) + continue; + } + + if (queue_add(ctx->queue, NULL, ctx->peer, ctx->cookie)) { + dev_err(dev, "%s cannot add to queue\n", __func__); + continue; + } + } + + return 0; +} + +static int setup_ivc(u32 virt_ctx, struct platform_device *pdev, + u32 queue_start, u32 queue_end) +{ + struct device *dev = &pdev->dev; + int i, j, ret = -EINVAL; + + for (i = queue_start; i < queue_end; ++i) { + char name[20]; + u32 inst; + + snprintf(name, sizeof(name), "ivc-queue%d", i); + for (j = 0; + of_property_read_u32_index(dev->of_node, name, + j * NUM_PROP + PROP_IVC_INST, &inst) == 0; + j++) { + struct device_node *hv_dn; + struct gr_comm_ivc_context *ctx; + struct gr_comm_queue *queue = + &contexts[virt_ctx].queue[i]; + char thread_name[30]; + int id, err; + + hv_dn = of_parse_phandle(dev->of_node, name, + j * NUM_PROP + PROP_IVC_NODE); + if (!hv_dn) + goto fail; + + ctx = kzalloc(sizeof(*ctx), GFP_KERNEL); + if (!ctx) { + ret = -ENOMEM; + goto fail; + } + + ctx->pdev = pdev; + ctx->queue = queue; + init_waitqueue_head(&ctx->wq[IVC_DIR_TX]); + init_waitqueue_head(&ctx->wq[IVC_DIR_RX]); + + ctx->cookie = + tegra_hv_ivc_reserve(hv_dn, inst, &ivc_ops); + if (IS_ERR_OR_NULL(ctx->cookie)) { + ret = PTR_ERR(ctx->cookie); + kfree(ctx); + goto fail; + } + + if (ctx->cookie->frame_size < queue->size) { + ret = -ENOMEM; + tegra_hv_ivc_unreserve(ctx->cookie); + kfree(ctx); + goto fail; + } + + ctx->peer = ctx->cookie->peer_vmid; + + id = GEN_ID0(virt_ctx, i, ctx->peer); + err = idr_alloc(&ivc_ctx_idr, ctx, id, id + 1, + GFP_KERNEL); + if (err != id) { + tegra_hv_ivc_unreserve(ctx->cookie); + kfree(ctx); + goto fail; + } + + id = GEN_ID1(ctx->cookie->irq); + err = idr_alloc(&ivc_ctx_idr, ctx, id, id + 1, + GFP_KERNEL); + if (err != id) + goto fail; + + server_vmid = ctx->peer; + snprintf(thread_name, sizeof(thread_name), + "gr-virt-thr-%d-%d-%d", virt_ctx, i, ctx->peer); + ctx->rx_thread = + kthread_run(ivc_rx_thread, ctx, thread_name); + if (IS_ERR(ctx->rx_thread)) + goto fail; + } + if (j == 0) + goto fail; + } + + return 0; + +fail: + free_ivc(virt_ctx, queue_start, queue_end); + return ret; +} + +int tegra_gr_comm_init(struct platform_device *pdev, u32 virt_ctx, u32 elems, + const size_t *queue_sizes, u32 queue_start, u32 num_queues) +{ + struct gr_comm_context *ctx; + int i = 0, j; + int ret = 0; + struct device *dev = &pdev->dev; + u32 queue_end = queue_start + num_queues; + + if (virt_ctx >= NUM_CONTEXTS || queue_end > NUM_QUEUES) + return -EINVAL; + + ctx = &contexts[virt_ctx]; + for (i = queue_start; i < queue_end; ++i) { + char name[30]; + size_t size = queue_sizes[i - queue_start]; + struct gr_comm_queue *queue = &ctx->queue[i]; + + if (queue->valid) + return -EEXIST; + + snprintf(name, sizeof(name), "gr-virt-comm-%d-%d", virt_ctx, i); + queue->element_cache = + kmem_cache_create(name, + sizeof(struct gr_comm_element) + size, 0, + SLAB_RECLAIM_ACCOUNT | SLAB_MEM_SPREAD, NULL); + + if (!queue->element_cache) { + ret = -ENOMEM; + goto fail; + } + + sema_init(&queue->sem, 0); + mutex_init(&queue->lock); + mutex_init(&queue->resp_lock); + INIT_LIST_HEAD(&queue->free); + INIT_LIST_HEAD(&queue->pending); + queue->size = size; + + for (j = 0; j < elems; ++j) { + struct gr_comm_element *element = + kmem_cache_alloc(queue->element_cache, + GFP_KERNEL); + + if (!element) { + ret = -ENOMEM; + goto fail; + } + element->data = (char *)element + sizeof(*element); + element->queue = queue; + list_add(&element->list, &queue->free); + } + + queue->valid = true; + } + + ret = setup_ivc(virt_ctx, pdev, queue_start, queue_end); + if (ret) { + dev_err(dev, "invalid IVC DT data\n"); + goto fail; + } + + return 0; + +fail: + while (i >= 0) { + struct gr_comm_element *tmp, *next; + struct gr_comm_queue *queue = &ctx->queue[i]; + + if (queue->element_cache) { + list_for_each_entry_safe(tmp, next, &queue->free, + list) { + list_del(&tmp->list); + kmem_cache_free(queue->element_cache, tmp); + } + } + kmem_cache_destroy(queue->element_cache); + --i; + } + + free_ivc(virt_ctx, queue_start, queue_end); + dev_err(dev, "%s insufficient memory\n", __func__); + return ret; +} + +void tegra_gr_comm_deinit(u32 virt_ctx, u32 queue_start, u32 num_queues) +{ + struct gr_comm_context *ctx; + struct gr_comm_element *tmp, *next; + u32 queue_end = queue_start + num_queues; + int i; + + if (virt_ctx >= NUM_CONTEXTS || queue_end > NUM_QUEUES) + return; + + ctx = &contexts[virt_ctx]; + + for (i = queue_start; i < queue_end; ++i) { + struct gr_comm_queue *queue = &ctx->queue[i]; + + if (!queue->valid) + continue; + + list_for_each_entry_safe(tmp, next, &queue->free, list) { + list_del(&tmp->list); + kmem_cache_free(queue->element_cache, tmp); + } + + list_for_each_entry_safe(tmp, next, &queue->pending, list) { + list_del(&tmp->list); + kmem_cache_free(queue->element_cache, tmp); + } + kmem_cache_destroy(queue->element_cache); + queue->valid = false; + } + free_ivc(virt_ctx, queue_start, queue_end); +} + +int tegra_gr_comm_send(u32 virt_ctx, u32 peer, u32 index, void *data, + size_t size) +{ + struct gr_comm_context *ctx; + struct gr_comm_ivc_context *ivc_ctx; + int ret; + + if (virt_ctx >= NUM_CONTEXTS || index >= NUM_QUEUES) + return -EINVAL; + + ctx = &contexts[virt_ctx]; + if (!ctx->queue[index].valid) + return -EINVAL; + + if (peer == TEGRA_GR_COMM_ID_SELF) + return queue_add(&ctx->queue[index], data, peer, NULL); + + ivc_ctx = idr_find(&ivc_ctx_idr, GEN_ID0(virt_ctx, index, peer)); + if (!ivc_ctx) + return -EINVAL; + + if (!tegra_hv_ivc_can_write(ivc_ctx->cookie)) { + ret = wait_event_timeout(ivc_ctx->wq[IVC_DIR_TX], + tegra_hv_ivc_can_write(ivc_ctx->cookie), + msecs_to_jiffies(250)); + if (!ret) { + dev_err(&ivc_ctx->pdev->dev, + "%s timeout waiting for buffer\n", __func__); + return -ENOMEM; + } + } + + ret = tegra_hv_ivc_write(ivc_ctx->cookie, data, size); + return (ret != size) ? -ENOMEM : 0; +} + +int tegra_gr_comm_recv(u32 virt_ctx, u32 index, void **handle, void **data, + size_t *size, u32 *sender) +{ + struct gr_comm_context *ctx; + struct gr_comm_queue *queue; + struct gr_comm_element *element; + + if (virt_ctx >= NUM_CONTEXTS || index >= NUM_QUEUES) + return -EINVAL; + + ctx = &contexts[virt_ctx]; + if (!ctx->queue[index].valid) + return -EINVAL; + + queue = &ctx->queue[index]; + down(&queue->sem); + mutex_lock(&queue->lock); + element = list_first_entry(&queue->pending, + struct gr_comm_element, list); + list_del(&element->list); + mutex_unlock(&queue->lock); + *handle = element; + *data = element->data; + *size = element->size; + if (sender) + *sender = element->sender; + return 0; +} + +int tegra_gr_comm_sendrecv(u32 virt_ctx, u32 peer, u32 index, void **handle, + void **data, size_t *size) +{ + struct gr_comm_context *ctx; + struct gr_comm_queue *queue; + int err = 0; + + if (virt_ctx >= NUM_CONTEXTS || index >= NUM_QUEUES) + return -EINVAL; + + ctx = &contexts[virt_ctx]; + if (!ctx->queue[index].valid) + return -EINVAL; + + queue = &ctx->queue[index]; + mutex_lock(&queue->resp_lock); + err = tegra_gr_comm_send(virt_ctx, peer, index, *data, *size); + if (err) + goto fail; + err = tegra_gr_comm_recv(virt_ctx, index, handle, data, size, NULL); +fail: + mutex_unlock(&queue->resp_lock); + return err; +} + + +void tegra_gr_comm_release(void *handle) +{ + struct gr_comm_element *element = + (struct gr_comm_element *)handle; + + mutex_lock(&element->queue->lock); + list_add(&element->list, &element->queue->free); + mutex_unlock(&element->queue->lock); +} From 0181342c83cca3262ca5124745cfd38c2f688f36 Mon Sep 17 00:00:00 2001 From: Aingara Paramakuru Date: Fri, 31 Oct 2014 16:15:42 -0400 Subject: [PATCH 02/21] video: tegra: virt: fix crash in tegra_gr_comm_init The clean-up code did not iterate over the correct queue elements, resulting in a kernel crash. Change-Id: I48b3d901ad2cddca77a259c628aced65aa262069 Signed-off-by: Aingara Paramakuru Reviewed-on: http://git-master/r/592208 Reviewed-on: http://git-master/r/1198194 Reviewed-on: http://git-master/r/1314829 GVS: Gerrit_Virtual_Submit Reviewed-by: Aniruddha Banerjee Tested-by: Aniruddha Banerjee Reviewed-by: Timo Alho --- drivers/video/tegra/virt/tegra_gr_comm.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/video/tegra/virt/tegra_gr_comm.c b/drivers/video/tegra/virt/tegra_gr_comm.c index ff78c093..4c1a7f4b 100644 --- a/drivers/video/tegra/virt/tegra_gr_comm.c +++ b/drivers/video/tegra/virt/tegra_gr_comm.c @@ -376,7 +376,7 @@ int tegra_gr_comm_init(struct platform_device *pdev, u32 virt_ctx, u32 elems, return 0; fail: - while (i >= 0) { + for (i = queue_start; i < queue_end; ++i) { struct gr_comm_element *tmp, *next; struct gr_comm_queue *queue = &ctx->queue[i]; @@ -386,9 +386,8 @@ fail: list_del(&tmp->list); kmem_cache_free(queue->element_cache, tmp); } + kmem_cache_destroy(queue->element_cache); } - kmem_cache_destroy(queue->element_cache); - --i; } free_ivc(virt_ctx, queue_start, queue_end); From 983d45ff7158b5ff7f296b95a727b3bb49641f85 Mon Sep 17 00:00:00 2001 From: Aingara Paramakuru Date: Tue, 6 Jan 2015 16:22:52 -0500 Subject: [PATCH 03/21] video: tegra: virt: switch to IVC IRQ Handling IVC notifications using the callback method is problematic when trying to handle the IVC reset protocol. The comm framework now handles IVC IRQs locally. Bug 1566409 Change-Id: I969500dd5599efb15a49ee44a79a7872ecc48e58 Signed-off-by: Aingara Paramakuru Reviewed-on: http://git-master/r/671865 Reviewed-on: http://git-master/r/1198216 Reviewed-on: http://git-master/r/1314830 GVS: Gerrit_Virtual_Submit Reviewed-by: Aniruddha Banerjee Tested-by: Aniruddha Banerjee Reviewed-by: Timo Alho --- drivers/video/tegra/virt/tegra_gr_comm.c | 144 ++++++++--------------- 1 file changed, 47 insertions(+), 97 deletions(-) diff --git a/drivers/video/tegra/virt/tegra_gr_comm.c b/drivers/video/tegra/virt/tegra_gr_comm.c index 4c1a7f4b..c98b2046 100644 --- a/drivers/video/tegra/virt/tegra_gr_comm.c +++ b/drivers/video/tegra/virt/tegra_gr_comm.c @@ -1,7 +1,7 @@ /* * Tegra Graphics Virtualization Communication Framework * - * Copyright (c) 2013-2014, NVIDIA Corporation. All rights reserved. + * Copyright (c) 2013-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, @@ -29,46 +29,33 @@ #include #include #include +#include #include #include #define NUM_QUEUES 4 #define NUM_CONTEXTS 2 -#define ID_SHIFT 11 -#define ID_MASK 1 -#define ID0_PEER_ID_SHIFT 4 -#define ID0_QUEUE_ID_SHIFT 1 -#define ID0_QUEUE_ID_MASK 7 -#define ID0_VCTX_SHIFT 0 -#define ID0_VCTX_MASK 1 -#define ID1_IRQ_SHIFT 0 +#define ID_PEER_ID_SHIFT 4 +#define ID_QUEUE_ID_SHIFT 1 +#define ID_QUEUE_ID_MASK 7 +#define ID_VCTX_SHIFT 0 +#define ID_VCTX_MASK 1 -#define GEN_ID0(vctx, queue_id, peer_id) \ - ((peer_id << ID0_PEER_ID_SHIFT) | \ - (queue_id << ID0_QUEUE_ID_SHIFT) | \ - (vctx << ID0_VCTX_SHIFT) | \ - (0 << ID_SHIFT)) -#define GEN_ID1(irq) \ - ((irq << ID1_IRQ_SHIFT) | \ - (1 << ID_SHIFT)) -#define IS_ID1(id) ((id >> ID_SHIFT) & ID_MASK) -#define VCTX_FROM_ID0(id) ((id >> ID0_VCTX_SHIFT) & ID0_VCTX_MASK) -#define QUEUE_ID_FROM_ID0(id) ((id >> ID0_QUEUE_ID_SHIFT) & ID0_QUEUE_ID_MASK) - -enum { - IVC_DIR_TX = 0, - IVC_DIR_RX, - NUM_IVC_DIR -}; +#define GEN_ID(vctx, queue_id, peer_id) \ + ((peer_id << ID_PEER_ID_SHIFT) | \ + (queue_id << ID_QUEUE_ID_SHIFT) | \ + (vctx << ID_VCTX_SHIFT)) +#define VCTX_FROM_ID(id) ((id >> ID_VCTX_SHIFT) & ID_VCTX_MASK) +#define QUEUE_ID_FROM_ID(id) ((id >> ID_QUEUE_ID_SHIFT) & ID_QUEUE_ID_MASK) struct gr_comm_ivc_context { u32 peer; - wait_queue_head_t wq[NUM_IVC_DIR]; + wait_queue_head_t wq; struct tegra_hv_ivc_cookie *cookie; struct gr_comm_queue *queue; - struct task_struct *rx_thread; struct platform_device *pdev; + bool irq_requested; }; struct gr_comm_element { @@ -115,47 +102,20 @@ static void free_ivc(u32 virt_ctx, u32 queue_start, u32 queue_end) int id; idr_for_each_entry(&ivc_ctx_idr, tmp, id) { - if (VCTX_FROM_ID0(id) == virt_ctx && - QUEUE_ID_FROM_ID0(id) >= queue_start && - QUEUE_ID_FROM_ID0(id) < queue_end) { + if (VCTX_FROM_ID(id) == virt_ctx && + QUEUE_ID_FROM_ID(id) >= queue_start && + QUEUE_ID_FROM_ID(id) < queue_end) { idr_remove(&ivc_ctx_idr, id); - if (tmp->rx_thread) - kthread_stop(tmp->rx_thread); + if (tmp->irq_requested) + free_irq(tmp->cookie->irq, tmp); - if (tmp->cookie) { - idr_remove(&ivc_ctx_idr, - GEN_ID1(tmp->cookie->irq)); + if (tmp->cookie) tegra_hv_ivc_unreserve(tmp->cookie); - } kfree(tmp); } } } -static void ivc_rx(struct tegra_hv_ivc_cookie *ivck) -{ - struct gr_comm_ivc_context *ctx = - idr_find(&ivc_ctx_idr, GEN_ID1(ivck->irq)); - - if (!ctx) - return; - - wake_up(&ctx->wq[IVC_DIR_RX]); -} - -static void ivc_tx(struct tegra_hv_ivc_cookie *ivck) -{ - struct gr_comm_ivc_context *ctx = - idr_find(&ivc_ctx_idr, GEN_ID1(ivck->irq)); - - if (!ctx) - return; - - wake_up(&ctx->wq[IVC_DIR_TX]); -} - -static const struct tegra_hv_ivc_ops ivc_ops = { ivc_rx, ivc_tx }; - static int queue_add(struct gr_comm_queue *queue, const char *data, u32 peer, struct tegra_hv_ivc_cookie *ivck) { @@ -194,32 +154,27 @@ static int queue_add(struct gr_comm_queue *queue, const char *data, return 0; } -static int ivc_rx_thread(void *arg) +static irqreturn_t ivc_intr_isr(int irq, void *dev_id) { - struct gr_comm_ivc_context *ctx = (struct gr_comm_ivc_context *)arg; + return IRQ_WAKE_THREAD; +} + +static irqreturn_t ivc_intr_thread(int irq, void *dev_id) +{ + struct gr_comm_ivc_context *ctx = dev_id; struct device *dev = &ctx->pdev->dev; - int ret; - - while (!kthread_should_stop()) { - if (!tegra_hv_ivc_can_read(ctx->cookie)) { - ret = wait_event_timeout(ctx->wq[IVC_DIR_RX], - tegra_hv_ivc_can_read(ctx->cookie) || - kthread_should_stop(), - msecs_to_jiffies(250)); - - if (kthread_should_stop()) - break; - else if (!ret) - continue; - } + while (tegra_hv_ivc_can_read(ctx->cookie)) { if (queue_add(ctx->queue, NULL, ctx->peer, ctx->cookie)) { dev_err(dev, "%s cannot add to queue\n", __func__); - continue; + break; } } - return 0; + if (tegra_hv_ivc_can_write(ctx->cookie)) + wake_up(&ctx->wq); + + return IRQ_HANDLED; } static int setup_ivc(u32 virt_ctx, struct platform_device *pdev, @@ -241,7 +196,6 @@ static int setup_ivc(u32 virt_ctx, struct platform_device *pdev, struct gr_comm_ivc_context *ctx; struct gr_comm_queue *queue = &contexts[virt_ctx].queue[i]; - char thread_name[30]; int id, err; hv_dn = of_parse_phandle(dev->of_node, name, @@ -257,11 +211,10 @@ static int setup_ivc(u32 virt_ctx, struct platform_device *pdev, ctx->pdev = pdev; ctx->queue = queue; - init_waitqueue_head(&ctx->wq[IVC_DIR_TX]); - init_waitqueue_head(&ctx->wq[IVC_DIR_RX]); + init_waitqueue_head(&ctx->wq); ctx->cookie = - tegra_hv_ivc_reserve(hv_dn, inst, &ivc_ops); + tegra_hv_ivc_reserve(hv_dn, inst, NULL); if (IS_ERR_OR_NULL(ctx->cookie)) { ret = PTR_ERR(ctx->cookie); kfree(ctx); @@ -277,7 +230,7 @@ static int setup_ivc(u32 virt_ctx, struct platform_device *pdev, ctx->peer = ctx->cookie->peer_vmid; - id = GEN_ID0(virt_ctx, i, ctx->peer); + id = GEN_ID(virt_ctx, i, ctx->peer); err = idr_alloc(&ivc_ctx_idr, ctx, id, id + 1, GFP_KERNEL); if (err != id) { @@ -286,19 +239,16 @@ static int setup_ivc(u32 virt_ctx, struct platform_device *pdev, goto fail; } - id = GEN_ID1(ctx->cookie->irq); - err = idr_alloc(&ivc_ctx_idr, ctx, id, id + 1, - GFP_KERNEL); - if (err != id) - goto fail; - server_vmid = ctx->peer; - snprintf(thread_name, sizeof(thread_name), - "gr-virt-thr-%d-%d-%d", virt_ctx, i, ctx->peer); - ctx->rx_thread = - kthread_run(ivc_rx_thread, ctx, thread_name); - if (IS_ERR(ctx->rx_thread)) + err = request_threaded_irq(ctx->cookie->irq, + ivc_intr_isr, + ivc_intr_thread, + 0, "gr-virt", ctx); + if (err) { + ret = -ENOMEM; goto fail; + } + ctx->irq_requested = true; } if (j == 0) goto fail; @@ -445,12 +395,12 @@ int tegra_gr_comm_send(u32 virt_ctx, u32 peer, u32 index, void *data, if (peer == TEGRA_GR_COMM_ID_SELF) return queue_add(&ctx->queue[index], data, peer, NULL); - ivc_ctx = idr_find(&ivc_ctx_idr, GEN_ID0(virt_ctx, index, peer)); + ivc_ctx = idr_find(&ivc_ctx_idr, GEN_ID(virt_ctx, index, peer)); if (!ivc_ctx) return -EINVAL; if (!tegra_hv_ivc_can_write(ivc_ctx->cookie)) { - ret = wait_event_timeout(ivc_ctx->wq[IVC_DIR_TX], + ret = wait_event_timeout(ivc_ctx->wq, tegra_hv_ivc_can_write(ivc_ctx->cookie), msecs_to_jiffies(250)); if (!ret) { From 90d91c94627d221d281f82a6c7ee1d589658f9ec Mon Sep 17 00:00:00 2001 From: Aingara Paramakuru Date: Mon, 12 Jan 2015 19:53:23 -0500 Subject: [PATCH 04/21] video: tegra: virt: support IVC reset protocol As part of the IVC reset protocol, IVC channels need to be invalidated during init and the interrupt handler should always handle IVC state changes first. Bug 1597830 Change-Id: I58807f03c393c7ff0c1140e9180854e2c64c7e24 Signed-off-by: Aingara Paramakuru Reviewed-on: http://git-master/r/671866 Reviewed-on: http://git-master/r/1198217 Reviewed-on: http://git-master/r/1314831 GVS: Gerrit_Virtual_Submit Reviewed-by: Aniruddha Banerjee Tested-by: Aniruddha Banerjee Reviewed-by: Timo Alho --- drivers/video/tegra/virt/tegra_gr_comm.c | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/drivers/video/tegra/virt/tegra_gr_comm.c b/drivers/video/tegra/virt/tegra_gr_comm.c index c98b2046..06db4914 100644 --- a/drivers/video/tegra/virt/tegra_gr_comm.c +++ b/drivers/video/tegra/virt/tegra_gr_comm.c @@ -42,6 +42,7 @@ #define ID_VCTX_SHIFT 0 #define ID_VCTX_MASK 1 +/* used to generate an id for id -> ivc-context lookups */ #define GEN_ID(vctx, queue_id, peer_id) \ ((peer_id << ID_PEER_ID_SHIFT) | \ (queue_id << ID_QUEUE_ID_SHIFT) | \ @@ -146,8 +147,10 @@ static int queue_add(struct gr_comm_queue *queue, const char *data, mutex_unlock(&queue->lock); return -ENOMEM; } - } else + } else { + /* local msg */ memcpy(element->data, data, element->size); + } list_add_tail(&element->list, &queue->pending); mutex_unlock(&queue->lock); up(&queue->sem); @@ -164,6 +167,10 @@ static irqreturn_t ivc_intr_thread(int irq, void *dev_id) struct gr_comm_ivc_context *ctx = dev_id; struct device *dev = &ctx->pdev->dev; + /* handle ivc state changes -- MUST BE FIRST */ + if (tegra_hv_ivc_channel_notified(ctx->cookie)) + return IRQ_HANDLED; + while (tegra_hv_ivc_can_read(ctx->cookie)) { if (queue_add(ctx->queue, NULL, ctx->peer, ctx->cookie)) { dev_err(dev, "%s cannot add to queue\n", __func__); @@ -239,17 +246,25 @@ static int setup_ivc(u32 virt_ctx, struct platform_device *pdev, goto fail; } + /* ctx->peer will have same value for all queues */ server_vmid = ctx->peer; + + /* set ivc channel to invalid state */ + tegra_hv_ivc_channel_reset(ctx->cookie); + err = request_threaded_irq(ctx->cookie->irq, ivc_intr_isr, ivc_intr_thread, 0, "gr-virt", ctx); if (err) { ret = -ENOMEM; + /* ivc context is on list, so free_ivc() + * will take care of clean-up */ goto fail; } ctx->irq_requested = true; } + /* no entries in DT? */ if (j == 0) goto fail; } @@ -309,6 +324,7 @@ int tegra_gr_comm_init(struct platform_device *pdev, u32 virt_ctx, u32 elems, ret = -ENOMEM; goto fail; } + /* data is placed at end of element */ element->data = (char *)element + sizeof(*element); element->queue = queue; list_add(&element->list, &queue->free); @@ -392,6 +408,7 @@ int tegra_gr_comm_send(u32 virt_ctx, u32 peer, u32 index, void *data, if (!ctx->queue[index].valid) return -EINVAL; + /* local msg is enqueued directly */ if (peer == TEGRA_GR_COMM_ID_SELF) return queue_add(&ctx->queue[index], data, peer, NULL); @@ -443,6 +460,7 @@ int tegra_gr_comm_recv(u32 virt_ctx, u32 index, void **handle, void **data, return 0; } +/* NOTE: tegra_gr_comm_recv() should not be running concurrently */ int tegra_gr_comm_sendrecv(u32 virt_ctx, u32 peer, u32 index, void **handle, void **data, size_t *size) { @@ -468,7 +486,6 @@ fail: return err; } - void tegra_gr_comm_release(void *handle) { struct gr_comm_element *element = From 413331cd4c2f0d8c520b381b593a68639db763b6 Mon Sep 17 00:00:00 2001 From: Peter Daifuku Date: Tue, 25 Nov 2014 11:48:00 -0800 Subject: [PATCH 05/21] host1x virtualization: basic support - Adds a new host1x pushbuffer queue - Includes support for virtualized VIC Bug 1509609 (cherry-picked from commit 5589b0ffdaa4b31e7900d23e5d82d8430c710039) Change-Id: Ie9b604dc8d8e43166dedb13953c4edac813da18b Signed-off-by: Peter Daifuku Reviewed-on: http://git-master/r/1198218 Reviewed-on: http://git-master/r/1314832 GVS: Gerrit_Virtual_Submit Reviewed-by: Aniruddha Banerjee Tested-by: Aniruddha Banerjee Reviewed-by: Timo Alho --- drivers/video/tegra/virt/tegra_gr_comm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/video/tegra/virt/tegra_gr_comm.c b/drivers/video/tegra/virt/tegra_gr_comm.c index 06db4914..f847890e 100644 --- a/drivers/video/tegra/virt/tegra_gr_comm.c +++ b/drivers/video/tegra/virt/tegra_gr_comm.c @@ -33,7 +33,7 @@ #include #include -#define NUM_QUEUES 4 +#define NUM_QUEUES 5 #define NUM_CONTEXTS 2 #define ID_PEER_ID_SHIFT 4 From e33f9d13f492c88ad950bc1b9f14c213ab64a8f4 Mon Sep 17 00:00:00 2001 From: Aingara Paramakuru Date: Wed, 26 Aug 2015 13:34:52 -0400 Subject: [PATCH 06/21] video: tegra: virt: update comm framework The following changes have been made: - remove support for multiple IVC contexts per queue - add support for mempools (OOB data support) JIRA VFND-689 Change-Id: I3a1b8b3d204b579b3a5604858e62283df65b4cb3 Signed-off-by: Aingara Paramakuru Reviewed-on: http://git-master/r/1198248 Reviewed-on: http://git-master/r/1314833 GVS: Gerrit_Virtual_Submit Reviewed-by: Aniruddha Banerjee Tested-by: Aniruddha Banerjee Reviewed-by: Timo Alho --- drivers/video/tegra/virt/tegra_gr_comm.c | 226 +++++++++++++++++------ 1 file changed, 168 insertions(+), 58 deletions(-) diff --git a/drivers/video/tegra/virt/tegra_gr_comm.c b/drivers/video/tegra/virt/tegra_gr_comm.c index f847890e..910f3e73 100644 --- a/drivers/video/tegra/virt/tegra_gr_comm.c +++ b/drivers/video/tegra/virt/tegra_gr_comm.c @@ -27,28 +27,13 @@ #include #include #include -#include -#include +#include #include #include #include #define NUM_QUEUES 5 -#define NUM_CONTEXTS 2 - -#define ID_PEER_ID_SHIFT 4 -#define ID_QUEUE_ID_SHIFT 1 -#define ID_QUEUE_ID_MASK 7 -#define ID_VCTX_SHIFT 0 -#define ID_VCTX_MASK 1 - -/* used to generate an id for id -> ivc-context lookups */ -#define GEN_ID(vctx, queue_id, peer_id) \ - ((peer_id << ID_PEER_ID_SHIFT) | \ - (queue_id << ID_QUEUE_ID_SHIFT) | \ - (vctx << ID_VCTX_SHIFT)) -#define VCTX_FROM_ID(id) ((id >> ID_VCTX_SHIFT) & ID_VCTX_MASK) -#define QUEUE_ID_FROM_ID(id) ((id >> ID_QUEUE_ID_SHIFT) & ID_QUEUE_ID_MASK) +#define NUM_CONTEXTS 1 struct gr_comm_ivc_context { u32 peer; @@ -59,6 +44,11 @@ struct gr_comm_ivc_context { bool irq_requested; }; +struct gr_comm_mempool_context { + struct tegra_hv_ivm_cookie *cookie; + void *ptr; +}; + struct gr_comm_element { u32 sender; size_t size; @@ -71,9 +61,12 @@ struct gr_comm_queue { struct semaphore sem; struct mutex lock; struct mutex resp_lock; + struct mutex mempool_lock; struct list_head pending; struct list_head free; size_t size; + struct gr_comm_ivc_context *ivc_ctx; + struct gr_comm_mempool_context *mempool_ctx; struct kmem_cache *element_cache; bool valid; }; @@ -88,8 +81,13 @@ enum { NUM_PROP }; +enum { + PROP_MEMPOOL_NODE = 0, + PROP_MEMPOOL_INST, + NUM_MEMPOOL_PROP +}; + static struct gr_comm_context contexts[NUM_CONTEXTS]; -static DEFINE_IDR(ivc_ctx_idr); static u32 server_vmid; u32 tegra_gr_comm_get_server_vmid(void) @@ -97,23 +95,48 @@ u32 tegra_gr_comm_get_server_vmid(void) return server_vmid; } +static void free_mempool(u32 virt_ctx, u32 queue_start, u32 queue_end) +{ + int i; + + for (i = queue_start; i < queue_end; ++i) { + struct gr_comm_queue *queue = + &contexts[virt_ctx].queue[i]; + struct gr_comm_mempool_context *tmp = queue->mempool_ctx; + + if (!tmp) + continue; + + if (tmp->ptr) + iounmap(tmp->ptr); + + if (tmp->cookie) + tegra_hv_mempool_unreserve(tmp->cookie); + + kfree(tmp); + queue->mempool_ctx = NULL; + } +} + static void free_ivc(u32 virt_ctx, u32 queue_start, u32 queue_end) { - struct gr_comm_ivc_context *tmp; - int id; + int i; - idr_for_each_entry(&ivc_ctx_idr, tmp, id) { - if (VCTX_FROM_ID(id) == virt_ctx && - QUEUE_ID_FROM_ID(id) >= queue_start && - QUEUE_ID_FROM_ID(id) < queue_end) { - idr_remove(&ivc_ctx_idr, id); - if (tmp->irq_requested) - free_irq(tmp->cookie->irq, tmp); + for (i = queue_start; i < queue_end; ++i) { + struct gr_comm_queue *queue = + &contexts[virt_ctx].queue[i]; + struct gr_comm_ivc_context *tmp = queue->ivc_ctx; - if (tmp->cookie) - tegra_hv_ivc_unreserve(tmp->cookie); - kfree(tmp); - } + if (!tmp) + continue; + + if (tmp->irq_requested) + free_irq(tmp->cookie->irq, tmp); + + if (tmp->cookie) + tegra_hv_ivc_unreserve(tmp->cookie); + kfree(tmp); + queue->ivc_ctx = NULL; } } @@ -184,29 +207,83 @@ static irqreturn_t ivc_intr_thread(int irq, void *dev_id) return IRQ_HANDLED; } +static int setup_mempool(u32 virt_ctx, struct platform_device *pdev, + u32 queue_start, u32 queue_end) +{ + struct device *dev = &pdev->dev; + int i, ret = -EINVAL; + + for (i = queue_start; i < queue_end; ++i) { + char name[20]; + u32 inst; + + snprintf(name, sizeof(name), "mempool%d", i); + if (of_property_read_u32_index(dev->of_node, name, + PROP_MEMPOOL_INST, &inst) == 0) { + struct device_node *hv_dn; + struct gr_comm_mempool_context *ctx; + struct gr_comm_queue *queue = + &contexts[virt_ctx].queue[i]; + + hv_dn = of_parse_phandle(dev->of_node, name, + PROP_MEMPOOL_NODE); + if (!hv_dn) + goto fail; + + ctx = kzalloc(sizeof(*ctx), GFP_KERNEL); + if (!ctx) { + ret = -ENOMEM; + goto fail; + } + + ctx->cookie = + tegra_hv_mempool_reserve(hv_dn, inst); + if (IS_ERR_OR_NULL(ctx->cookie)) { + ret = PTR_ERR(ctx->cookie); + kfree(ctx); + goto fail; + } + + queue->mempool_ctx = ctx; + ctx->ptr = ioremap_cached(ctx->cookie->ipa, + ctx->cookie->size); + if (!ctx->ptr) { + ret = -ENOMEM; + /* free_mempool will take care of + clean-up */ + goto fail; + } + } + } + + return 0; + +fail: + free_mempool(virt_ctx, queue_start, queue_end); + return ret; +} + static int setup_ivc(u32 virt_ctx, struct platform_device *pdev, u32 queue_start, u32 queue_end) { struct device *dev = &pdev->dev; - int i, j, ret = -EINVAL; + int i, ret = -EINVAL; for (i = queue_start; i < queue_end; ++i) { char name[20]; u32 inst; snprintf(name, sizeof(name), "ivc-queue%d", i); - for (j = 0; - of_property_read_u32_index(dev->of_node, name, - j * NUM_PROP + PROP_IVC_INST, &inst) == 0; - j++) { + if (of_property_read_u32_index(dev->of_node, name, + PROP_IVC_INST, &inst) == 0) { struct device_node *hv_dn; struct gr_comm_ivc_context *ctx; struct gr_comm_queue *queue = &contexts[virt_ctx].queue[i]; - int id, err; + int err; hv_dn = of_parse_phandle(dev->of_node, name, - j * NUM_PROP + PROP_IVC_NODE); + PROP_IVC_NODE); if (!hv_dn) goto fail; @@ -236,15 +313,7 @@ static int setup_ivc(u32 virt_ctx, struct platform_device *pdev, } ctx->peer = ctx->cookie->peer_vmid; - - id = GEN_ID(virt_ctx, i, ctx->peer); - err = idr_alloc(&ivc_ctx_idr, ctx, id, id + 1, - GFP_KERNEL); - if (err != id) { - tegra_hv_ivc_unreserve(ctx->cookie); - kfree(ctx); - goto fail; - } + queue->ivc_ctx = ctx; /* ctx->peer will have same value for all queues */ server_vmid = ctx->peer; @@ -263,10 +332,10 @@ static int setup_ivc(u32 virt_ctx, struct platform_device *pdev, goto fail; } ctx->irq_requested = true; - } - /* no entries in DT? */ - if (j == 0) + } else { + /* no entry in DT? */ goto fail; + } } return 0; @@ -311,6 +380,7 @@ int tegra_gr_comm_init(struct platform_device *pdev, u32 virt_ctx, u32 elems, sema_init(&queue->sem, 0); mutex_init(&queue->lock); mutex_init(&queue->resp_lock); + mutex_init(&queue->mempool_lock); INIT_LIST_HEAD(&queue->free); INIT_LIST_HEAD(&queue->pending); queue->size = size; @@ -339,6 +409,12 @@ int tegra_gr_comm_init(struct platform_device *pdev, u32 virt_ctx, u32 elems, goto fail; } + ret = setup_mempool(virt_ctx, pdev, queue_start, queue_end); + if (ret) { + dev_err(dev, "mempool setup failed\n"); + goto fail; + } + return 0; fail: @@ -357,6 +433,7 @@ fail: } free_ivc(virt_ctx, queue_start, queue_end); + free_mempool(virt_ctx, queue_start, queue_end); dev_err(dev, "%s insufficient memory\n", __func__); return ret; } @@ -392,6 +469,7 @@ void tegra_gr_comm_deinit(u32 virt_ctx, u32 queue_start, u32 num_queues) queue->valid = false; } free_ivc(virt_ctx, queue_start, queue_end); + free_mempool(virt_ctx, queue_start, queue_end); } int tegra_gr_comm_send(u32 virt_ctx, u32 peer, u32 index, void *data, @@ -399,21 +477,23 @@ int tegra_gr_comm_send(u32 virt_ctx, u32 peer, u32 index, void *data, { struct gr_comm_context *ctx; struct gr_comm_ivc_context *ivc_ctx; + struct gr_comm_queue *queue; int ret; if (virt_ctx >= NUM_CONTEXTS || index >= NUM_QUEUES) return -EINVAL; ctx = &contexts[virt_ctx]; - if (!ctx->queue[index].valid) + queue = &ctx->queue[index]; + if (!queue->valid) return -EINVAL; /* local msg is enqueued directly */ if (peer == TEGRA_GR_COMM_ID_SELF) - return queue_add(&ctx->queue[index], data, peer, NULL); + return queue_add(queue, data, peer, NULL); - ivc_ctx = idr_find(&ivc_ctx_idr, GEN_ID(virt_ctx, index, peer)); - if (!ivc_ctx) + ivc_ctx = queue->ivc_ctx; + if (!ivc_ctx || ivc_ctx->peer != peer) return -EINVAL; if (!tegra_hv_ivc_can_write(ivc_ctx->cookie)) { @@ -442,10 +522,10 @@ int tegra_gr_comm_recv(u32 virt_ctx, u32 index, void **handle, void **data, return -EINVAL; ctx = &contexts[virt_ctx]; - if (!ctx->queue[index].valid) + queue = &ctx->queue[index]; + if (!queue->valid) return -EINVAL; - queue = &ctx->queue[index]; down(&queue->sem); mutex_lock(&queue->lock); element = list_first_entry(&queue->pending, @@ -472,10 +552,10 @@ int tegra_gr_comm_sendrecv(u32 virt_ctx, u32 peer, u32 index, void **handle, return -EINVAL; ctx = &contexts[virt_ctx]; - if (!ctx->queue[index].valid) + queue = &ctx->queue[index]; + if (!queue->valid) return -EINVAL; - queue = &ctx->queue[index]; mutex_lock(&queue->resp_lock); err = tegra_gr_comm_send(virt_ctx, peer, index, *data, *size); if (err) @@ -495,3 +575,33 @@ void tegra_gr_comm_release(void *handle) list_add(&element->list, &element->queue->free); mutex_unlock(&element->queue->lock); } + +void *tegra_gr_comm_oob_get_ptr(u32 virt_ctx, u32 peer, u32 index, + void **ptr, size_t *size) +{ + struct gr_comm_mempool_context *mempool_ctx; + struct gr_comm_queue *queue; + + if (virt_ctx >= NUM_CONTEXTS || index >= NUM_QUEUES) + return NULL; + + queue = &contexts[virt_ctx].queue[index]; + if (!queue->valid) + return NULL; + + mempool_ctx = queue->mempool_ctx; + if (!mempool_ctx || mempool_ctx->cookie->peer_vmid != peer) + return NULL; + + mutex_lock(&queue->mempool_lock); + *size = mempool_ctx->cookie->size; + *ptr = mempool_ctx->ptr; + return queue; +} + +void tegra_gr_comm_oob_put_ptr(void *handle) +{ + struct gr_comm_queue *queue = (struct gr_comm_queue *)handle; + + mutex_unlock(&queue->mempool_lock); +} From 27d4ef0964aed423e5307c354e02de0435dd6a75 Mon Sep 17 00:00:00 2001 From: Bharat Nihalani Date: Thu, 8 Oct 2015 12:08:12 +0530 Subject: [PATCH 07/21] video: tegra: virt: fix typo replace ioremap_cached to ioremap_cache. This should fix the build break seen due to this symbol. Change-Id: I574b568493f278aef2afb9c0704ae55b8c60affd Signed-off-by: Bharat Nihalani Reviewed-on: http://git-master/r/1198249 Reviewed-on: http://git-master/r/1314834 GVS: Gerrit_Virtual_Submit Reviewed-by: Aniruddha Banerjee Tested-by: Aniruddha Banerjee Reviewed-by: Timo Alho --- drivers/video/tegra/virt/tegra_gr_comm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/video/tegra/virt/tegra_gr_comm.c b/drivers/video/tegra/virt/tegra_gr_comm.c index 910f3e73..4d576e6e 100644 --- a/drivers/video/tegra/virt/tegra_gr_comm.c +++ b/drivers/video/tegra/virt/tegra_gr_comm.c @@ -245,7 +245,7 @@ static int setup_mempool(u32 virt_ctx, struct platform_device *pdev, } queue->mempool_ctx = ctx; - ctx->ptr = ioremap_cached(ctx->cookie->ipa, + ctx->ptr = ioremap_cache(ctx->cookie->ipa, ctx->cookie->size); if (!ctx->ptr) { ret = -ENOMEM; From 97c0fccbcc775faf272f378521d1bdb4a51893c7 Mon Sep 17 00:00:00 2001 From: Richard Zhao Date: Thu, 11 Feb 2016 14:20:18 -0800 Subject: [PATCH 08/21] video: tegra: virt: fix hung task warnings add timeout for tegra_gr_comm_recv and fix warnings: INFO: task gk20a:1085 blocked for more than 120 seconds. Tainted: G W 3.18.21-tegra #9 "echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this message. gk20a D ffffffc000085df8 0 1085 2 0x00000000 Call trace: [] __switch_to+0x94/0xa8 [] __schedule+0x2ac/0x7d0 [] schedule+0x24/0x74 [] schedule_timeout+0x15c/0x258 [] __down+0x60/0xa4 [] down+0x44/0x60 [] tegra_gr_comm_recv+0x5c/0x100 [] vgpu_intr_thread+0x5c/0x10c [] kthread+0xf8/0x110 Bug 1728199 (cherry-picked from commit b9af225268aa6ee42d2bf41df8f6b63f55ddffd2) Change-Id: Ia07f16a50b226824625131d03e8d677382215315 Signed-off-by: Richard Zhao Reviewed-on: http://git-master/r/1198256 Reviewed-on: http://git-master/r/1314836 GVS: Gerrit_Virtual_Submit Reviewed-by: Aniruddha Banerjee Tested-by: Aniruddha Banerjee Reviewed-by: Timo Alho --- drivers/video/tegra/virt/tegra_gr_comm.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/drivers/video/tegra/virt/tegra_gr_comm.c b/drivers/video/tegra/virt/tegra_gr_comm.c index 4d576e6e..bc5f52d6 100644 --- a/drivers/video/tegra/virt/tegra_gr_comm.c +++ b/drivers/video/tegra/virt/tegra_gr_comm.c @@ -517,6 +517,7 @@ int tegra_gr_comm_recv(u32 virt_ctx, u32 index, void **handle, void **data, struct gr_comm_context *ctx; struct gr_comm_queue *queue; struct gr_comm_element *element; + int err; if (virt_ctx >= NUM_CONTEXTS || index >= NUM_QUEUES) return -EINVAL; @@ -526,7 +527,9 @@ int tegra_gr_comm_recv(u32 virt_ctx, u32 index, void **handle, void **data, if (!queue->valid) return -EINVAL; - down(&queue->sem); + err = down_timeout(&queue->sem, 10 * HZ); + if (unlikely(err)) + return err; mutex_lock(&queue->lock); element = list_first_entry(&queue->pending, struct gr_comm_element, list); @@ -537,7 +540,7 @@ int tegra_gr_comm_recv(u32 virt_ctx, u32 index, void **handle, void **data, *size = element->size; if (sender) *sender = element->sender; - return 0; + return err; } /* NOTE: tegra_gr_comm_recv() should not be running concurrently */ @@ -561,6 +564,9 @@ int tegra_gr_comm_sendrecv(u32 virt_ctx, u32 peer, u32 index, void **handle, if (err) goto fail; err = tegra_gr_comm_recv(virt_ctx, index, handle, data, size, NULL); + if (unlikely(err)) + dev_err(&queue->ivc_ctx->pdev->dev, + "tegra_gr_comm_recv: timeout for response!\n"); fail: mutex_unlock(&queue->resp_lock); return err; From a9442ce5b8023f944f906960a2a7a27f3eb6569e Mon Sep 17 00:00:00 2001 From: Terje Bergstrom Date: Tue, 8 Mar 2016 10:53:05 -0800 Subject: [PATCH 09/21] video: tegra: virt: Export functions used by nvgpu Export functions used by nvgpu so that nvgpu could be built as a module. Change-Id: I7cf9162a17c3aaf736d20af8eb0ce623d168ff1d Signed-off-by: Terje Bergstrom Reviewed-on: http://git-master/r/1028350 Reviewed-on: http://git-master/r/1198258 Reviewed-on: http://git-master/r/1314837 GVS: Gerrit_Virtual_Submit Reviewed-by: Aniruddha Banerjee Tested-by: Aniruddha Banerjee Reviewed-by: Timo Alho --- drivers/video/tegra/virt/tegra_gr_comm.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/drivers/video/tegra/virt/tegra_gr_comm.c b/drivers/video/tegra/virt/tegra_gr_comm.c index bc5f52d6..e56b2c38 100644 --- a/drivers/video/tegra/virt/tegra_gr_comm.c +++ b/drivers/video/tegra/virt/tegra_gr_comm.c @@ -31,6 +31,7 @@ #include #include #include +#include #define NUM_QUEUES 5 #define NUM_CONTEXTS 1 @@ -94,6 +95,7 @@ u32 tegra_gr_comm_get_server_vmid(void) { return server_vmid; } +EXPORT_SYMBOL(tegra_gr_comm_get_server_vmid); static void free_mempool(u32 virt_ctx, u32 queue_start, u32 queue_end) { @@ -437,6 +439,7 @@ fail: dev_err(dev, "%s insufficient memory\n", __func__); return ret; } +EXPORT_SYMBOL(tegra_gr_comm_init); void tegra_gr_comm_deinit(u32 virt_ctx, u32 queue_start, u32 num_queues) { @@ -471,6 +474,7 @@ void tegra_gr_comm_deinit(u32 virt_ctx, u32 queue_start, u32 num_queues) free_ivc(virt_ctx, queue_start, queue_end); free_mempool(virt_ctx, queue_start, queue_end); } +EXPORT_SYMBOL(tegra_gr_comm_deinit); int tegra_gr_comm_send(u32 virt_ctx, u32 peer, u32 index, void *data, size_t size) @@ -510,6 +514,7 @@ int tegra_gr_comm_send(u32 virt_ctx, u32 peer, u32 index, void *data, ret = tegra_hv_ivc_write(ivc_ctx->cookie, data, size); return (ret != size) ? -ENOMEM : 0; } +EXPORT_SYMBOL(tegra_gr_comm_send); int tegra_gr_comm_recv(u32 virt_ctx, u32 index, void **handle, void **data, size_t *size, u32 *sender) @@ -542,6 +547,7 @@ int tegra_gr_comm_recv(u32 virt_ctx, u32 index, void **handle, void **data, *sender = element->sender; return err; } +EXPORT_SYMBOL(tegra_gr_comm_recv); /* NOTE: tegra_gr_comm_recv() should not be running concurrently */ int tegra_gr_comm_sendrecv(u32 virt_ctx, u32 peer, u32 index, void **handle, @@ -571,6 +577,7 @@ fail: mutex_unlock(&queue->resp_lock); return err; } +EXPORT_SYMBOL(tegra_gr_comm_sendrecv); void tegra_gr_comm_release(void *handle) { @@ -581,6 +588,7 @@ void tegra_gr_comm_release(void *handle) list_add(&element->list, &element->queue->free); mutex_unlock(&element->queue->lock); } +EXPORT_SYMBOL(tegra_gr_comm_release); void *tegra_gr_comm_oob_get_ptr(u32 virt_ctx, u32 peer, u32 index, void **ptr, size_t *size) @@ -604,6 +612,7 @@ void *tegra_gr_comm_oob_get_ptr(u32 virt_ctx, u32 peer, u32 index, *ptr = mempool_ctx->ptr; return queue; } +EXPORT_SYMBOL(tegra_gr_comm_oob_get_ptr); void tegra_gr_comm_oob_put_ptr(void *handle) { @@ -611,3 +620,4 @@ void tegra_gr_comm_oob_put_ptr(void *handle) mutex_unlock(&queue->mempool_lock); } +EXPORT_SYMBOL(tegra_gr_comm_oob_put_ptr); From 98755f63cae84cb481ff628ff337c9e3fa5ffa35 Mon Sep 17 00:00:00 2001 From: Aniruddha Banerjee Date: Sat, 1 Apr 2017 01:27:56 +0530 Subject: [PATCH 10/21] video: tegra: increase wait_event_timout to 500ms This patch increases the timeout for the wait_event from 250ms to 500ms. Bug 1653184 Bug 1653182 Change-Id: I339f9d2eef20dcec8cd0a240900ab8af5c710c59 Signed-off-by: Aniruddha Banerjee Reviewed-on: http://git-master/r/1462093 Reviewed-by: Nitin Sehgal GVS: Gerrit_Virtual_Submit Reviewed-by: Timo Alho --- drivers/video/tegra/virt/tegra_gr_comm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/video/tegra/virt/tegra_gr_comm.c b/drivers/video/tegra/virt/tegra_gr_comm.c index e56b2c38..901bbe60 100644 --- a/drivers/video/tegra/virt/tegra_gr_comm.c +++ b/drivers/video/tegra/virt/tegra_gr_comm.c @@ -503,7 +503,7 @@ int tegra_gr_comm_send(u32 virt_ctx, u32 peer, u32 index, void *data, if (!tegra_hv_ivc_can_write(ivc_ctx->cookie)) { ret = wait_event_timeout(ivc_ctx->wq, tegra_hv_ivc_can_write(ivc_ctx->cookie), - msecs_to_jiffies(250)); + msecs_to_jiffies(500)); if (!ret) { dev_err(&ivc_ctx->pdev->dev, "%s timeout waiting for buffer\n", __func__); From 94f2fb429ff0fae6cd2681948fc0e9ec9df06106 Mon Sep 17 00:00:00 2001 From: Richard Zhao Date: Thu, 25 Jan 2018 11:17:10 -0800 Subject: [PATCH 11/21] video: tegra: virt: remove virt_ctx from tegra_gr_comm queue index can already index the queues. It also help make the api more common. Jira EVLR-2364 Change-Id: I5ba8f03bf8ae9cc8d1a51a6d5c48eef969276ed0 Signed-off-by: Richard Zhao Reviewed-on: https://git-master.nvidia.com/r/1646195 Reviewed-by: Damian Halas Reviewed-by: svc-mobile-coverity Reviewed-by: Aingara Paramakuru GVS: Gerrit_Virtual_Submit Reviewed-by: Nirav Patel Reviewed-by: mobile promotions Tested-by: mobile promotions --- drivers/video/tegra/virt/tegra_gr_comm.c | 91 +++++++++++------------- 1 file changed, 40 insertions(+), 51 deletions(-) diff --git a/drivers/video/tegra/virt/tegra_gr_comm.c b/drivers/video/tegra/virt/tegra_gr_comm.c index 901bbe60..955f0373 100644 --- a/drivers/video/tegra/virt/tegra_gr_comm.c +++ b/drivers/video/tegra/virt/tegra_gr_comm.c @@ -1,7 +1,7 @@ /* * Tegra Graphics Virtualization Communication Framework * - * Copyright (c) 2013-2015, NVIDIA Corporation. All rights reserved. + * Copyright (c) 2013-2018, 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, @@ -88,7 +88,7 @@ enum { NUM_MEMPOOL_PROP }; -static struct gr_comm_context contexts[NUM_CONTEXTS]; +static struct gr_comm_context comm_context; static u32 server_vmid; u32 tegra_gr_comm_get_server_vmid(void) @@ -97,13 +97,13 @@ u32 tegra_gr_comm_get_server_vmid(void) } EXPORT_SYMBOL(tegra_gr_comm_get_server_vmid); -static void free_mempool(u32 virt_ctx, u32 queue_start, u32 queue_end) +static void free_mempool(u32 queue_start, u32 queue_end) { int i; for (i = queue_start; i < queue_end; ++i) { struct gr_comm_queue *queue = - &contexts[virt_ctx].queue[i]; + &comm_context.queue[i]; struct gr_comm_mempool_context *tmp = queue->mempool_ctx; if (!tmp) @@ -120,13 +120,13 @@ static void free_mempool(u32 virt_ctx, u32 queue_start, u32 queue_end) } } -static void free_ivc(u32 virt_ctx, u32 queue_start, u32 queue_end) +static void free_ivc(u32 queue_start, u32 queue_end) { int i; for (i = queue_start; i < queue_end; ++i) { struct gr_comm_queue *queue = - &contexts[virt_ctx].queue[i]; + &comm_context.queue[i]; struct gr_comm_ivc_context *tmp = queue->ivc_ctx; if (!tmp) @@ -209,7 +209,7 @@ static irqreturn_t ivc_intr_thread(int irq, void *dev_id) return IRQ_HANDLED; } -static int setup_mempool(u32 virt_ctx, struct platform_device *pdev, +static int setup_mempool(struct platform_device *pdev, u32 queue_start, u32 queue_end) { struct device *dev = &pdev->dev; @@ -225,7 +225,7 @@ static int setup_mempool(u32 virt_ctx, struct platform_device *pdev, struct device_node *hv_dn; struct gr_comm_mempool_context *ctx; struct gr_comm_queue *queue = - &contexts[virt_ctx].queue[i]; + &comm_context.queue[i]; hv_dn = of_parse_phandle(dev->of_node, name, PROP_MEMPOOL_NODE); @@ -261,11 +261,11 @@ static int setup_mempool(u32 virt_ctx, struct platform_device *pdev, return 0; fail: - free_mempool(virt_ctx, queue_start, queue_end); + free_mempool(queue_start, queue_end); return ret; } -static int setup_ivc(u32 virt_ctx, struct platform_device *pdev, +static int setup_ivc(struct platform_device *pdev, u32 queue_start, u32 queue_end) { struct device *dev = &pdev->dev; @@ -281,7 +281,7 @@ static int setup_ivc(u32 virt_ctx, struct platform_device *pdev, struct device_node *hv_dn; struct gr_comm_ivc_context *ctx; struct gr_comm_queue *queue = - &contexts[virt_ctx].queue[i]; + &comm_context.queue[i]; int err; hv_dn = of_parse_phandle(dev->of_node, name, @@ -343,32 +343,30 @@ static int setup_ivc(u32 virt_ctx, struct platform_device *pdev, return 0; fail: - free_ivc(virt_ctx, queue_start, queue_end); + free_ivc(queue_start, queue_end); return ret; } -int tegra_gr_comm_init(struct platform_device *pdev, u32 virt_ctx, u32 elems, +int tegra_gr_comm_init(struct platform_device *pdev, u32 elems, const size_t *queue_sizes, u32 queue_start, u32 num_queues) { - struct gr_comm_context *ctx; int i = 0, j; int ret = 0; struct device *dev = &pdev->dev; u32 queue_end = queue_start + num_queues; - if (virt_ctx >= NUM_CONTEXTS || queue_end > NUM_QUEUES) + if (queue_end > NUM_QUEUES) return -EINVAL; - ctx = &contexts[virt_ctx]; for (i = queue_start; i < queue_end; ++i) { char name[30]; size_t size = queue_sizes[i - queue_start]; - struct gr_comm_queue *queue = &ctx->queue[i]; + struct gr_comm_queue *queue = &comm_context.queue[i]; if (queue->valid) return -EEXIST; - snprintf(name, sizeof(name), "gr-virt-comm-%d-%d", virt_ctx, i); + snprintf(name, sizeof(name), "gr-virt-comm-%d", i); queue->element_cache = kmem_cache_create(name, sizeof(struct gr_comm_element) + size, 0, @@ -405,13 +403,13 @@ int tegra_gr_comm_init(struct platform_device *pdev, u32 virt_ctx, u32 elems, queue->valid = true; } - ret = setup_ivc(virt_ctx, pdev, queue_start, queue_end); + ret = setup_ivc(pdev, queue_start, queue_end); if (ret) { dev_err(dev, "invalid IVC DT data\n"); goto fail; } - ret = setup_mempool(virt_ctx, pdev, queue_start, queue_end); + ret = setup_mempool(pdev, queue_start, queue_end); if (ret) { dev_err(dev, "mempool setup failed\n"); goto fail; @@ -422,7 +420,7 @@ int tegra_gr_comm_init(struct platform_device *pdev, u32 virt_ctx, u32 elems, fail: for (i = queue_start; i < queue_end; ++i) { struct gr_comm_element *tmp, *next; - struct gr_comm_queue *queue = &ctx->queue[i]; + struct gr_comm_queue *queue = &comm_context.queue[i]; if (queue->element_cache) { list_for_each_entry_safe(tmp, next, &queue->free, @@ -434,27 +432,24 @@ fail: } } - free_ivc(virt_ctx, queue_start, queue_end); - free_mempool(virt_ctx, queue_start, queue_end); + free_ivc(queue_start, queue_end); + free_mempool(queue_start, queue_end); dev_err(dev, "%s insufficient memory\n", __func__); return ret; } EXPORT_SYMBOL(tegra_gr_comm_init); -void tegra_gr_comm_deinit(u32 virt_ctx, u32 queue_start, u32 num_queues) +void tegra_gr_comm_deinit(u32 queue_start, u32 num_queues) { - struct gr_comm_context *ctx; struct gr_comm_element *tmp, *next; u32 queue_end = queue_start + num_queues; int i; - if (virt_ctx >= NUM_CONTEXTS || queue_end > NUM_QUEUES) + if (queue_end > NUM_QUEUES) return; - ctx = &contexts[virt_ctx]; - for (i = queue_start; i < queue_end; ++i) { - struct gr_comm_queue *queue = &ctx->queue[i]; + struct gr_comm_queue *queue = &comm_context.queue[i]; if (!queue->valid) continue; @@ -471,24 +466,22 @@ void tegra_gr_comm_deinit(u32 virt_ctx, u32 queue_start, u32 num_queues) kmem_cache_destroy(queue->element_cache); queue->valid = false; } - free_ivc(virt_ctx, queue_start, queue_end); - free_mempool(virt_ctx, queue_start, queue_end); + free_ivc(queue_start, queue_end); + free_mempool(queue_start, queue_end); } EXPORT_SYMBOL(tegra_gr_comm_deinit); -int tegra_gr_comm_send(u32 virt_ctx, u32 peer, u32 index, void *data, +int tegra_gr_comm_send(u32 peer, u32 index, void *data, size_t size) { - struct gr_comm_context *ctx; struct gr_comm_ivc_context *ivc_ctx; struct gr_comm_queue *queue; int ret; - if (virt_ctx >= NUM_CONTEXTS || index >= NUM_QUEUES) + if (index >= NUM_QUEUES) return -EINVAL; - ctx = &contexts[virt_ctx]; - queue = &ctx->queue[index]; + queue = &comm_context.queue[index]; if (!queue->valid) return -EINVAL; @@ -516,19 +509,17 @@ int tegra_gr_comm_send(u32 virt_ctx, u32 peer, u32 index, void *data, } EXPORT_SYMBOL(tegra_gr_comm_send); -int tegra_gr_comm_recv(u32 virt_ctx, u32 index, void **handle, void **data, +int tegra_gr_comm_recv(u32 index, void **handle, void **data, size_t *size, u32 *sender) { - struct gr_comm_context *ctx; struct gr_comm_queue *queue; struct gr_comm_element *element; int err; - if (virt_ctx >= NUM_CONTEXTS || index >= NUM_QUEUES) + if (index >= NUM_QUEUES) return -EINVAL; - ctx = &contexts[virt_ctx]; - queue = &ctx->queue[index]; + queue = &comm_context.queue[index]; if (!queue->valid) return -EINVAL; @@ -550,26 +541,24 @@ int tegra_gr_comm_recv(u32 virt_ctx, u32 index, void **handle, void **data, EXPORT_SYMBOL(tegra_gr_comm_recv); /* NOTE: tegra_gr_comm_recv() should not be running concurrently */ -int tegra_gr_comm_sendrecv(u32 virt_ctx, u32 peer, u32 index, void **handle, +int tegra_gr_comm_sendrecv(u32 peer, u32 index, void **handle, void **data, size_t *size) { - struct gr_comm_context *ctx; struct gr_comm_queue *queue; int err = 0; - if (virt_ctx >= NUM_CONTEXTS || index >= NUM_QUEUES) + if (index >= NUM_QUEUES) return -EINVAL; - ctx = &contexts[virt_ctx]; - queue = &ctx->queue[index]; + queue = &comm_context.queue[index]; if (!queue->valid) return -EINVAL; mutex_lock(&queue->resp_lock); - err = tegra_gr_comm_send(virt_ctx, peer, index, *data, *size); + err = tegra_gr_comm_send(peer, index, *data, *size); if (err) goto fail; - err = tegra_gr_comm_recv(virt_ctx, index, handle, data, size, NULL); + err = tegra_gr_comm_recv(index, handle, data, size, NULL); if (unlikely(err)) dev_err(&queue->ivc_ctx->pdev->dev, "tegra_gr_comm_recv: timeout for response!\n"); @@ -590,16 +579,16 @@ void tegra_gr_comm_release(void *handle) } EXPORT_SYMBOL(tegra_gr_comm_release); -void *tegra_gr_comm_oob_get_ptr(u32 virt_ctx, u32 peer, u32 index, +void *tegra_gr_comm_oob_get_ptr(u32 peer, u32 index, void **ptr, size_t *size) { struct gr_comm_mempool_context *mempool_ctx; struct gr_comm_queue *queue; - if (virt_ctx >= NUM_CONTEXTS || index >= NUM_QUEUES) + if (index >= NUM_QUEUES) return NULL; - queue = &contexts[virt_ctx].queue[index]; + queue = &comm_context.queue[index]; if (!queue->valid) return NULL; From bc2c2bcde6547b12626b97629df928f41118d517 Mon Sep 17 00:00:00 2001 From: Richard Zhao Date: Fri, 26 Jan 2018 16:21:59 -0800 Subject: [PATCH 12/21] virt: tegra_hv: remove parameter dn from tegra_hv_mempool_reserve() Device tree node was not used by the function, so remove it to make the function more common. Jira EVLR-2364 Change-Id: I0888773fa584eac2c2133c73d9385b700899fdf7 Signed-off-by: Richard Zhao Reviewed-on: https://git-master.nvidia.com/r/1647029 Reviewed-by: svc-mobile-coverity GVS: Gerrit_Virtual_Submit Reviewed-by: Dennis Kou Reviewed-by: Nirav Patel Reviewed-by: mobile promotions Tested-by: mobile promotions --- drivers/video/tegra/virt/tegra_gr_comm.c | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/drivers/video/tegra/virt/tegra_gr_comm.c b/drivers/video/tegra/virt/tegra_gr_comm.c index 955f0373..b3950f47 100644 --- a/drivers/video/tegra/virt/tegra_gr_comm.c +++ b/drivers/video/tegra/virt/tegra_gr_comm.c @@ -222,24 +222,17 @@ static int setup_mempool(struct platform_device *pdev, snprintf(name, sizeof(name), "mempool%d", i); if (of_property_read_u32_index(dev->of_node, name, PROP_MEMPOOL_INST, &inst) == 0) { - struct device_node *hv_dn; struct gr_comm_mempool_context *ctx; struct gr_comm_queue *queue = &comm_context.queue[i]; - hv_dn = of_parse_phandle(dev->of_node, name, - PROP_MEMPOOL_NODE); - if (!hv_dn) - goto fail; - ctx = kzalloc(sizeof(*ctx), GFP_KERNEL); if (!ctx) { ret = -ENOMEM; goto fail; } - ctx->cookie = - tegra_hv_mempool_reserve(hv_dn, inst); + ctx->cookie = tegra_hv_mempool_reserve(inst); if (IS_ERR_OR_NULL(ctx->cookie)) { ret = PTR_ERR(ctx->cookie); kfree(ctx); From e651d2e8dd9f9a3d7edac778b399b1905983ff2c Mon Sep 17 00:00:00 2001 From: Shridhar Rasal Date: Sun, 17 Apr 2016 10:13:36 +0530 Subject: [PATCH 13/21] video: tegra: virt: add virt include file This copies virtualization interface include file in kernel-next [b99549f] video: tegra: virt: update comm framework [e0c27a2] video: tegra: virt: add virtualization interfaces Change-Id: Ie51931ff2fd5c80d430591bba057d123d10c8b7b Signed-off-by: Shridhar Rasal Reviewed-on: http://git-master/r/1127824 (cherry picked from commit 39df7d7844fba18e69a317628235570d9b8ed4a5) Signed-off-by: Konsta Holtta Reviewed-on: http://git-master/r/1314848 Reviewed-by: Mikko Perttunen --- include/linux/tegra_gr_comm.h | 95 +++++++++++++++++++++++++++++++++++ 1 file changed, 95 insertions(+) create mode 100644 include/linux/tegra_gr_comm.h diff --git a/include/linux/tegra_gr_comm.h b/include/linux/tegra_gr_comm.h new file mode 100644 index 00000000..4c53ed68 --- /dev/null +++ b/include/linux/tegra_gr_comm.h @@ -0,0 +1,95 @@ +/* + * Tegra Graphics Virtualization Communication Framework + * + * Copyright (c) 2013-2014, 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, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef __TEGRA_GR_COMM_H +#define __TEGRA_GR_COMM_H + +#include + +enum { + TEGRA_GR_COMM_CTX_CLIENT = 0, + TEGRA_GR_COMM_CTX_SERVER +}; + +#define TEGRA_GR_COMM_ID_SELF (0xFF) + +#ifdef CONFIG_TEGRA_GR_VIRTUALIZATION +int tegra_gr_comm_init(struct platform_device *pdev, u32 virt_ctx, u32 elems, + const size_t *queue_sizes, u32 queue_start, u32 num_queues); +void tegra_gr_comm_deinit(u32 virt_ctx, u32 queue_start, u32 num_queues); +int tegra_gr_comm_send(u32 virt_ctx, u32 peer, u32 index, void *data, + size_t size); +int tegra_gr_comm_recv(u32 virt_ctx, u32 index, void **handle, void **data, + size_t *size, u32 *sender); +int tegra_gr_comm_sendrecv(u32 virt_ctx, u32 peer, u32 index, void **handle, + void **data, size_t *size); +void tegra_gr_comm_release(void *handle); +u32 tegra_gr_comm_get_server_vmid(void); +void *tegra_gr_comm_oob_get_ptr(u32 virt_ctx, u32 peer, u32 index, + void **ptr, size_t *size); +void tegra_gr_comm_oob_put_ptr(void *handle); +#else +static inline int tegra_gr_comm_init(struct platform_device *pdev, + u32 virt_ctx, u32 elems, + const size_t *queue_sizes, u32 queue_start, + u32 num_queues) +{ + return -ENOSYS; +} + +static inline void tegra_gr_comm_deinit(u32 virt_ctx, u32 queue_start, + u32 num_queues) +{ +} + +static inline int tegra_gr_comm_send(u32 virt_ctx, u32 peer, u32 index, + void *data, size_t size) +{ + return -ENOSYS; +} + +static inline int tegra_gr_comm_recv(u32 virt_ctx, u32 index, void **handle, + void **data, size_t *size, u32 *sender) +{ + return -ENOSYS; +} + +static inline int tegra_gr_comm_sendrecv(u32 virt_ctx, u32 peer, u32 index, + void **handle, void **data, + size_t *size) +{ + return -ENOSYS; +} + +static inline void tegra_gr_comm_release(void *handle) {} + +static inline u32 tegra_gr_comm_get_server_vmid(void) +{ + return 0; +} + +static inline void *tegra_gr_comm_oob_get_ptr(u32 virt_ctx, u32 peer, + u32 index, void **ptr, size_t *size) +{ + return NULL; +} + +static inline void tegra_gr_comm_oob_put_ptr(void *handle) {} +#endif + +#endif From 5fb49dd72ab2a0ed717cdba0a6c14f5ee8eed5ca Mon Sep 17 00:00:00 2001 From: Richard Zhao Date: Thu, 25 Jan 2018 11:17:10 -0800 Subject: [PATCH 14/21] video: tegra: virt: remove virt_ctx from tegra_gr_comm queue index can already index the queues. It also help make the api more common. Jira EVLR-2364 Change-Id: I5ba8f03bf8ae9cc8d1a51a6d5c48eef969276ed0 Signed-off-by: Richard Zhao Reviewed-on: https://git-master.nvidia.com/r/1646195 Reviewed-by: Damian Halas Reviewed-by: svc-mobile-coverity Reviewed-by: Aingara Paramakuru GVS: Gerrit_Virtual_Submit Reviewed-by: Nirav Patel Reviewed-by: mobile promotions Tested-by: mobile promotions --- include/linux/tegra_gr_comm.h | 31 +++++++++++++------------------ 1 file changed, 13 insertions(+), 18 deletions(-) diff --git a/include/linux/tegra_gr_comm.h b/include/linux/tegra_gr_comm.h index 4c53ed68..f1de97f4 100644 --- a/include/linux/tegra_gr_comm.h +++ b/include/linux/tegra_gr_comm.h @@ -1,7 +1,7 @@ /* * Tegra Graphics Virtualization Communication Framework * - * Copyright (c) 2013-2014, NVIDIA Corporation. All rights reserved. + * Copyright (c) 2013-2018, 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, @@ -21,55 +21,50 @@ #include -enum { - TEGRA_GR_COMM_CTX_CLIENT = 0, - TEGRA_GR_COMM_CTX_SERVER -}; - #define TEGRA_GR_COMM_ID_SELF (0xFF) #ifdef CONFIG_TEGRA_GR_VIRTUALIZATION -int tegra_gr_comm_init(struct platform_device *pdev, u32 virt_ctx, u32 elems, +int tegra_gr_comm_init(struct platform_device *pdev, u32 elems, const size_t *queue_sizes, u32 queue_start, u32 num_queues); -void tegra_gr_comm_deinit(u32 virt_ctx, u32 queue_start, u32 num_queues); -int tegra_gr_comm_send(u32 virt_ctx, u32 peer, u32 index, void *data, +void tegra_gr_comm_deinit(u32 queue_start, u32 num_queues); +int tegra_gr_comm_send(u32 peer, u32 index, void *data, size_t size); -int tegra_gr_comm_recv(u32 virt_ctx, u32 index, void **handle, void **data, +int tegra_gr_comm_recv(u32 index, void **handle, void **data, size_t *size, u32 *sender); -int tegra_gr_comm_sendrecv(u32 virt_ctx, u32 peer, u32 index, void **handle, +int tegra_gr_comm_sendrecv(u32 peer, u32 index, void **handle, void **data, size_t *size); void tegra_gr_comm_release(void *handle); u32 tegra_gr_comm_get_server_vmid(void); -void *tegra_gr_comm_oob_get_ptr(u32 virt_ctx, u32 peer, u32 index, +void *tegra_gr_comm_oob_get_ptr(u32 peer, u32 index, void **ptr, size_t *size); void tegra_gr_comm_oob_put_ptr(void *handle); #else static inline int tegra_gr_comm_init(struct platform_device *pdev, - u32 virt_ctx, u32 elems, + u32 elems, const size_t *queue_sizes, u32 queue_start, u32 num_queues) { return -ENOSYS; } -static inline void tegra_gr_comm_deinit(u32 virt_ctx, u32 queue_start, +static inline void tegra_gr_comm_deinit(u32 queue_start, u32 num_queues) { } -static inline int tegra_gr_comm_send(u32 virt_ctx, u32 peer, u32 index, +static inline int tegra_gr_comm_send(u32 peer, u32 index, void *data, size_t size) { return -ENOSYS; } -static inline int tegra_gr_comm_recv(u32 virt_ctx, u32 index, void **handle, +static inline int tegra_gr_comm_recv(u32 index, void **handle, void **data, size_t *size, u32 *sender) { return -ENOSYS; } -static inline int tegra_gr_comm_sendrecv(u32 virt_ctx, u32 peer, u32 index, +static inline int tegra_gr_comm_sendrecv(u32 peer, u32 index, void **handle, void **data, size_t *size) { @@ -83,7 +78,7 @@ static inline u32 tegra_gr_comm_get_server_vmid(void) return 0; } -static inline void *tegra_gr_comm_oob_get_ptr(u32 virt_ctx, u32 peer, +static inline void *tegra_gr_comm_oob_get_ptr(u32 peer, u32 index, void **ptr, size_t *size) { return NULL; From 7fa087bc721baeea2edfa0c76b24ff6e09589cce Mon Sep 17 00:00:00 2001 From: Ketan Patil Date: Thu, 27 Sep 2018 09:16:08 +0530 Subject: [PATCH 15/21] virt: tegra_gr_comm: fix pointer type Change the type of ptr to void __iomem * from void * as ioremap_cache expects the return type to be __iomem * This fixes the following sparse warning: tegra_gr_comm.c:243:34: warning: incorrect type in assignment (different address spaces) Bug 200434802 Change-Id: I296cc8048da649e84961239cb37bcd99ffe153a7 Signed-off-by: Ketan Patil Reviewed-on: https://git-master.nvidia.com/r/1848879 GVS: Gerrit_Virtual_Submit Reviewed-by: Sachin Nikam Reviewed-by: Automatic_Commit_Validation_User Reviewed-by: mobile promotions Tested-by: mobile promotions --- drivers/video/tegra/virt/tegra_gr_comm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/video/tegra/virt/tegra_gr_comm.c b/drivers/video/tegra/virt/tegra_gr_comm.c index b3950f47..e9ac6a07 100644 --- a/drivers/video/tegra/virt/tegra_gr_comm.c +++ b/drivers/video/tegra/virt/tegra_gr_comm.c @@ -47,7 +47,7 @@ struct gr_comm_ivc_context { struct gr_comm_mempool_context { struct tegra_hv_ivm_cookie *cookie; - void *ptr; + void __iomem *ptr; }; struct gr_comm_element { From 85c398692015fa59ca084167635132680870b73f Mon Sep 17 00:00:00 2001 From: Haley Teng Date: Wed, 25 Dec 2019 00:08:28 +0800 Subject: [PATCH 16/21] tegra_gr_comm: retry if tegra_gr_comm_send timeout Bug 2779333 Change-Id: I337ed034258d298f1c46673be6c2ca4006967e6b Signed-off-by: Haley Teng Reviewed-on: https://git-master.nvidia.com/r/c/linux-nvidia/+/2268246 Reviewed-by: Automatic_Commit_Validation_User Reviewed-by: Mikko Perttunen GVS: Gerrit_Virtual_Submit Reviewed-by: mobile promotions Tested-by: mobile promotions --- drivers/video/tegra/virt/tegra_gr_comm.c | 28 ++++++++++++++++-------- 1 file changed, 19 insertions(+), 9 deletions(-) diff --git a/drivers/video/tegra/virt/tegra_gr_comm.c b/drivers/video/tegra/virt/tegra_gr_comm.c index e9ac6a07..0388cfc2 100644 --- a/drivers/video/tegra/virt/tegra_gr_comm.c +++ b/drivers/video/tegra/virt/tegra_gr_comm.c @@ -1,7 +1,7 @@ /* * Tegra Graphics Virtualization Communication Framework * - * Copyright (c) 2013-2018, NVIDIA Corporation. All rights reserved. + * Copyright (c) 2013-2019, 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, @@ -469,6 +469,7 @@ int tegra_gr_comm_send(u32 peer, u32 index, void *data, { struct gr_comm_ivc_context *ivc_ctx; struct gr_comm_queue *queue; + int retries = 10; int ret; if (index >= NUM_QUEUES) @@ -487,14 +488,23 @@ int tegra_gr_comm_send(u32 peer, u32 index, void *data, return -EINVAL; if (!tegra_hv_ivc_can_write(ivc_ctx->cookie)) { - ret = wait_event_timeout(ivc_ctx->wq, - tegra_hv_ivc_can_write(ivc_ctx->cookie), - msecs_to_jiffies(500)); - if (!ret) { - dev_err(&ivc_ctx->pdev->dev, - "%s timeout waiting for buffer\n", __func__); - return -ENOMEM; - } + do { + ret = wait_event_timeout(ivc_ctx->wq, + tegra_hv_ivc_can_write(ivc_ctx->cookie), + msecs_to_jiffies(500)); + if (!ret) { + if (retries > 0) { + dev_warn(&ivc_ctx->pdev->dev, + "%s retrying (remaining %d times)\n", + __func__, retries--); + } else { + dev_err(&ivc_ctx->pdev->dev, + "%s timeout waiting for buffer\n", + __func__); + return -ENOMEM; + } + } + } while (!ret); } ret = tegra_hv_ivc_write(ivc_ctx->cookie, data, size); From 33c3cfdf1fce55d56b41fababacc7cbd9b5c74e8 Mon Sep 17 00:00:00 2001 From: kdendukuri Date: Tue, 19 May 2020 12:31:40 +0530 Subject: [PATCH 17/21] virt: tegra_gr_comm: increase waittime to 20 seconds as we are receiving "tegra_gr_comm_recv: timeout for response!", increase the waittime to 20 ticks as a WAR. Bug 2983318 Change-Id: If4e26027e6aba737f6dc3f063eb699b2620f4e62 Signed-off-by: kdendukuri Reviewed-on: https://git-master.nvidia.com/r/c/linux-nvidia/+/2346682 Reviewed-by: automaticguardword Reviewed-by: Vipin Kumar Reviewed-by: Richard Zhao Reviewed-by: Haley Teng GVS: Gerrit_Virtual_Submit --- drivers/video/tegra/virt/tegra_gr_comm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/video/tegra/virt/tegra_gr_comm.c b/drivers/video/tegra/virt/tegra_gr_comm.c index 0388cfc2..56b22196 100644 --- a/drivers/video/tegra/virt/tegra_gr_comm.c +++ b/drivers/video/tegra/virt/tegra_gr_comm.c @@ -526,7 +526,7 @@ int tegra_gr_comm_recv(u32 index, void **handle, void **data, if (!queue->valid) return -EINVAL; - err = down_timeout(&queue->sem, 10 * HZ); + err = down_timeout(&queue->sem, 20 * HZ); if (unlikely(err)) return err; mutex_lock(&queue->lock); From d9d3a5e42c56ceefc29bd8cde308272d952dc630 Mon Sep 17 00:00:00 2001 From: Antony Clince Alex Date: Fri, 1 Oct 2021 15:35:46 +0000 Subject: [PATCH 18/21] virt: tegra_gr_comm: increase waittime to 40 secs At present, the timeouts are not handled gracefully and it results in system crash, therefore increase the timetout to 40 as a WAR. Bug 200775880 Change-Id: I6ea999d0ae59df5f2c995dd0669149e598bb6e9d Signed-off-by: Antony Clince Alex Reviewed-on: https://git-master.nvidia.com/r/c/linux-nvidia/+/2604011 Reviewed-by: svcacv Reviewed-by: svc_kernel_abi Reviewed-by: Haley Teng Reviewed-by: Aparna Das Reviewed-by: mobile promotions Tested-by: mobile promotions GVS: Gerrit_Virtual_Submit --- drivers/video/tegra/virt/tegra_gr_comm.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/video/tegra/virt/tegra_gr_comm.c b/drivers/video/tegra/virt/tegra_gr_comm.c index 56b22196..b4e3f61d 100644 --- a/drivers/video/tegra/virt/tegra_gr_comm.c +++ b/drivers/video/tegra/virt/tegra_gr_comm.c @@ -1,7 +1,7 @@ /* * Tegra Graphics Virtualization Communication Framework * - * Copyright (c) 2013-2019, NVIDIA Corporation. All rights reserved. + * Copyright (c) 2013-2021, 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, @@ -526,7 +526,7 @@ int tegra_gr_comm_recv(u32 index, void **handle, void **data, if (!queue->valid) return -EINVAL; - err = down_timeout(&queue->sem, 20 * HZ); + err = down_timeout(&queue->sem, 40 * HZ); if (unlikely(err)) return err; mutex_lock(&queue->lock); From 15ef43911c8053934d53ed48119ccd1ac90d4a5c Mon Sep 17 00:00:00 2001 From: Manish Bhardwaj Date: Wed, 2 Mar 2022 05:44:47 +0000 Subject: [PATCH 19/21] tegra: virt: fix sparse warnings in nvidia repo 1. kernel/nvidia/drivers/video/tegra/virt/tegra_gr_comm.c:604:14: warning: incorrect type in assignment (different address spaces) 2. kernel/nvidia/drivers/virt/tegra/hvc_sysfs.c:154:17: warning: cast removes address space '__iomem' of expression 3. kernel/nvidia/drivers/virt/tegra/hvc_sysfs.c:189:17: warning: incorrect type in argument 1 (different address spaces) 4. kernel/nvidia/drivers/virt/tegra/ivc-cdev.c:330:27: warning: incorrect type in initializer (different base types) 5. kernel/nvidia/drivers/virt/tegra/tegra_hv.c:378:42: warning: incorrect type in argument 1 (different address spaces) 6. kernel/nvidia/drivers/virt/tegra/tegra_hv.c:386:26: warning: incorrect type in argument 1 (different address spaces) 7. kernel/nvidia/drivers/virt/tegra/tegra_hv.c:444:22: warning: cast removes address space '__iomem' of expression 8. kernel/nvidia/drivers/virt/tegra/tegra_hv.c:543:58: warning: incorrect type in assignment (different base types) 9. kernel/nvidia/drivers/virt/tegra/tegra_hv.c:544:62: warning: incorrect type in assignment (different base types) 10. kernel/nvidia/drivers/virt/tegra/tegra_hv.c:547:62: warning: incorrect type in assignment (different base types) 11. kernel/nvidia/drivers/virt/tegra/tegra_hv.c:823:10: warning: symbol 'tegra_hv_ivc_tx_frames_available' was not declared. Should it be static? 12. kernel/nvidia/drivers/virt/tegra/tegra_hv_pm_ctl.c:330:57: warning: incorrect type in initializer (different base types) 13. kernel/nvidia/drivers/virt/tegra/tegra_hv_pm_ctl.c:389:27: warning: incorrect type in initializer (different base types) To fix above sparse warnings we are making below changes :- 1. use the __poll_t data type when we are using polling framework. 2. pass __iomem type pointer to io framework. Bug 3528414 Jira ESLC-6572 Signed-off-by: Manish Bhardwaj Change-Id: I371e0bdc435d60623bc1405a9383bf45b6274f90 Reviewed-on: https://git-master.nvidia.com/r/c/linux-nvidia/+/2673587 Reviewed-by: svc-mobile-coverity Reviewed-by: svc-mobile-cert Reviewed-by: svc_kernel_abi Reviewed-by: Ketan Patil Reviewed-by: Sachin Nikam GVS: Gerrit_Virtual_Submit --- drivers/video/tegra/virt/tegra_gr_comm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/video/tegra/virt/tegra_gr_comm.c b/drivers/video/tegra/virt/tegra_gr_comm.c index b4e3f61d..95435c56 100644 --- a/drivers/video/tegra/virt/tegra_gr_comm.c +++ b/drivers/video/tegra/virt/tegra_gr_comm.c @@ -601,7 +601,7 @@ void *tegra_gr_comm_oob_get_ptr(u32 peer, u32 index, mutex_lock(&queue->mempool_lock); *size = mempool_ctx->cookie->size; - *ptr = mempool_ctx->ptr; + *ptr = (__force void *)mempool_ctx->ptr; return queue; } EXPORT_SYMBOL(tegra_gr_comm_oob_get_ptr); From 4636d2781ea7ba39d7fe377fa31c791f74bb155f Mon Sep 17 00:00:00 2001 From: Manish Bhardwaj Date: Wed, 2 Mar 2022 08:12:04 +0000 Subject: [PATCH 20/21] kernel: nvidia: fix cert warnings Using this patch we are fixing below cert warnings :- 1. cert_err33_c_violation: The error status of function call snprintf(name, 20UL, "ivc-queue%d", i) is not checked. 2. cert_err33_c_violation: The error status of function call snprintf(name, 30UL, "gr-virt-comm-%d", i) is not checked. 3. cert_err33_c_violation: The error status of function call snprintf(name, 20UL, "mempool%d", i) is not checked. Below changes has been done to fix above cert warnings:- 1. check the return value to snprintf function and handle return error gracefully. Bug 3512545 Signed-off-by: Manish Bhardwaj Change-Id: Ia41ab89e3759387b36489dca5f57652f7389f328 Reviewed-on: https://git-master.nvidia.com/r/c/linux-nvidia/+/2676650 Tested-by: mobile promotions Reviewed-by: mobile promotions --- drivers/video/tegra/virt/tegra_gr_comm.c | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/drivers/video/tegra/virt/tegra_gr_comm.c b/drivers/video/tegra/virt/tegra_gr_comm.c index 95435c56..9e931dac 100644 --- a/drivers/video/tegra/virt/tegra_gr_comm.c +++ b/drivers/video/tegra/virt/tegra_gr_comm.c @@ -1,7 +1,7 @@ /* * Tegra Graphics Virtualization Communication Framework * - * Copyright (c) 2013-2021, NVIDIA Corporation. All rights reserved. + * Copyright (c) 2013-2022, 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, @@ -219,7 +219,11 @@ static int setup_mempool(struct platform_device *pdev, char name[20]; u32 inst; - snprintf(name, sizeof(name), "mempool%d", i); + if (snprintf(name, sizeof(name), "mempool%d", i) < 0) { + ret = -ENOMEM; + goto fail; + } + if (of_property_read_u32_index(dev->of_node, name, PROP_MEMPOOL_INST, &inst) == 0) { struct gr_comm_mempool_context *ctx; @@ -268,7 +272,11 @@ static int setup_ivc(struct platform_device *pdev, char name[20]; u32 inst; - snprintf(name, sizeof(name), "ivc-queue%d", i); + if (snprintf(name, sizeof(name), "ivc-queue%d", i) < 0) { + ret = -ENOMEM; + goto fail; + } + if (of_property_read_u32_index(dev->of_node, name, PROP_IVC_INST, &inst) == 0) { struct device_node *hv_dn; @@ -359,7 +367,11 @@ int tegra_gr_comm_init(struct platform_device *pdev, u32 elems, if (queue->valid) return -EEXIST; - snprintf(name, sizeof(name), "gr-virt-comm-%d", i); + if (snprintf(name, sizeof(name), "gr-virt-comm-%d", i) < 0) { + ret = -ENOMEM; + goto fail; + } + queue->element_cache = kmem_cache_create(name, sizeof(struct gr_comm_element) + size, 0, From 7a0ea85184fd40e96bc9c7ae745df738601d0799 Mon Sep 17 00:00:00 2001 From: Richard Zhao Date: Sun, 5 Mar 2023 18:28:00 -0800 Subject: [PATCH 21/21] video: tegra: virt: enable gr_comm for oot kernel - enable config for oot - add GPL license - include different tegra hv header for oot Jira GVSCI-16046 Change-Id: I8358b15cec33fbd5fd98265adc9152d8e335511d Signed-off-by: Richard Zhao Reviewed-on: https://git-master.nvidia.com/r/c/linux-nvidia/+/2866154 Reviewed-by: svcacv Reviewed-by: svc-mobile-coverity Reviewed-by: svc-mobile-cert Reviewed-by: svc_kernel_abi Reviewed-by: Sagar Kamble Reviewed-by: Aparna Das Reviewed-by: Manish Bhardwaj GVS: Gerrit_Virtual_Submit --- drivers/video/tegra/virt/Makefile | 5 +++++ drivers/video/tegra/virt/tegra_gr_comm.c | 11 +++++++++-- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/drivers/video/tegra/virt/Makefile b/drivers/video/tegra/virt/Makefile index ccf4b29c..426d0412 100644 --- a/drivers/video/tegra/virt/Makefile +++ b/drivers/video/tegra/virt/Makefile @@ -1 +1,6 @@ +ifeq ($(CONFIG_TEGRA_OOT_MODULE),m) +ccflags-y += -DCONFIG_TEGRA_GR_VIRTUALIZATION -DCONFIG_TEGRA_OOT_MODULE +obj-m = tegra_gr_comm.o +else obj-$(CONFIG_TEGRA_GR_VIRTUALIZATION) += tegra_gr_comm.o +endif diff --git a/drivers/video/tegra/virt/tegra_gr_comm.c b/drivers/video/tegra/virt/tegra_gr_comm.c index 9e931dac..8df04fc6 100644 --- a/drivers/video/tegra/virt/tegra_gr_comm.c +++ b/drivers/video/tegra/virt/tegra_gr_comm.c @@ -1,7 +1,7 @@ /* * Tegra Graphics Virtualization Communication Framework * - * Copyright (c) 2013-2022, NVIDIA Corporation. All rights reserved. + * Copyright (c) 2013-2023, 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, @@ -29,10 +29,15 @@ #include #include #include -#include #include #include +#ifdef CONFIG_TEGRA_OOT_MODULE +#include +#else +#include +#endif + #define NUM_QUEUES 5 #define NUM_CONTEXTS 1 @@ -625,3 +630,5 @@ void tegra_gr_comm_oob_put_ptr(void *handle) mutex_unlock(&queue->mempool_lock); } EXPORT_SYMBOL(tegra_gr_comm_oob_put_ptr); + +MODULE_LICENSE("GPL v2");