Received: by 2002:a05:6a10:9afc:0:0:0:0 with SMTP id t28csp4101869pxm; Tue, 1 Mar 2022 11:15:04 -0800 (PST) X-Google-Smtp-Source: ABdhPJyE/FawE9QnNfMQIlOc13j9c0qcn7vVCM5jRrcgADzUIOjx0Isrp2nOYH3R/vG/9zubkZfZ X-Received: by 2002:a17:907:7e92:b0:6d7:bc6:aecb with SMTP id qb18-20020a1709077e9200b006d70bc6aecbmr2266585ejc.599.1646162104048; Tue, 01 Mar 2022 11:15:04 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1646162104; cv=none; d=google.com; s=arc-20160816; b=DEwGtqHi72YljF2phTNi1N/FO7uMOxzcPBtv9rYGhJ0r5K6RfSzTQaK4j63CdMEZyn gCAzoyqbdph2BfXouA6lNPPNnAG7DAKiLIpO84Vn3wv4QLXnErtMkicoUVW1nr+LKLfU ZqTLviRvZPI4CRoS+7uFoOXf/OvDlMdjvTBeL97RKlzxKCy+g1LcRdX7PoCeqQMwwnqA JMnMnC9LBtI0uHKkPFbQuku8UkmrZxJ47WVX5Tg1yeAhYzvmEaPHurzpdj9EPd4ggpg+ Bh3hZ0gJAS48c1NecsEvH9L5V/c+02IDn4sI38YI6TSnT61Qc8BjUYvBp8JCLZnsIWTs EFYw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :references:in-reply-to:message-id:date:subject:cc:to:from :dkim-signature; bh=6OJiMNq4xXSwhQjWakj+XiedN7LRKxKK1btq8hnzu0w=; b=S+Nlea+MYk4GU6GQq7+b3jdNRkp1F+OJB4ByCyZpel6dHvnFSe9ObSURv0wZ0wDXtE 3TDWSDESoJjsW3y+dPr8TYjBXfyICjXqGvgnSqXMk86ahOEbnqGJyBtwQI20Fh4GuN64 an/pjiop9fg/XZ347fz6zuhVuF2J7zYYoFq7VUotEWv2gWH3mSZwgAmQMVDxzTI9g7or Cp3LoSSueaauvMUq+z8UW27Gpunb15bcXZee9P0eRrZ9hCes8HLUvhecQj5ugV/CBVqq SDxbt7uzMauqMkzQvp6JDSgN72Uy8ify0V+0SZHSA7LCyrcbndH+HlSaHEXlOfnPt7NH hQaw== ARC-Authentication-Results: i=1; mx.google.com; dkim=fail header.i=@kapsi.fi header.s=20161220 header.b=vqTTyNt3; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id k24-20020aa7d2d8000000b004134f26020bsi9322136edr.237.2022.03.01.11.14.40; Tue, 01 Mar 2022 11:15:04 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; dkim=fail header.i=@kapsi.fi header.s=20161220 header.b=vqTTyNt3; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S236181AbiCAQQ7 (ORCPT + 99 others); Tue, 1 Mar 2022 11:16:59 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:42096 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S236084AbiCAQQT (ORCPT ); Tue, 1 Mar 2022 11:16:19 -0500 Received: from mail.kapsi.fi (mail.kapsi.fi [IPv6:2001:67c:1be8::25]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 62A919682A; Tue, 1 Mar 2022 08:15:37 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=kapsi.fi; s=20161220; h=Content-Transfer-Encoding:MIME-Version:References:In-Reply-To: Message-Id:Date:Subject:Cc:To:From:Sender:Reply-To:Content-Type:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:List-Id:List-Help:List-Unsubscribe:List-Subscribe: List-Post:List-Owner:List-Archive; bh=6OJiMNq4xXSwhQjWakj+XiedN7LRKxKK1btq8hnzu0w=; b=vqTTyNt3FiealCrzcS5BgHTfOF IWeuwI9Y7t3J7WeCJxbMd4PaRCKwrV6zcffOF7hefyB9naDxGNVUBAs9DBwatzqUCazmUZypS9Q9K 16jakxSHgulj5MLVbvjMiIYGUL4bkZkWa804QYXdCKVSyWZEdn4s4ouGFIYxv6qi/u5EAu05iiwdp lAgZjgCffe7ou54CmHzJo6XVrcJrzasWFiStzbM4G91+bhDv4vt2YqqQXL0/oGPhTJe7y12PTCs5Z aISwNYt5u5lxUCMHiUUv59xlYJdP2RzVYz4t9A57E2BAgusnvkDhj5epKFlYr08b/0z6cPUsUd+fP IoKeJg5w==; Received: from 91-158-25-70.elisa-laajakaista.fi ([91.158.25.70] helo=toshino.localdomain) by mail.kapsi.fi with esmtpsa (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.89) (envelope-from ) id 1nP59q-0003Z8-PE; Tue, 01 Mar 2022 18:15:26 +0200 From: cyndis@kapsi.fi To: thierry.reding@gmail.com, jonathanh@nvidia.com, joro@8bytes.org, will@kernel.org, robin.murphy@arm.com, robh+dt@kernel.org, krzysztof.kozlowski@canonical.com Cc: linux-tegra@vger.kernel.org, dri-devel@lists.freedesktop.org, iommu@lists.linux-foundation.org, linux-kernel@vger.kernel.org, devicetree@vger.kernel.org, linux-arm-kernel@lists.infradead.org, Mikko Perttunen Subject: [PATCH v4 3/9] gpu: host1x: Add context device management code Date: Tue, 1 Mar 2022 18:14:49 +0200 Message-Id: <20220301161455.4037062-4-cyndis@kapsi.fi> X-Mailer: git-send-email 2.35.0 In-Reply-To: <20220301161455.4037062-1-cyndis@kapsi.fi> References: <20220301161455.4037062-1-cyndis@kapsi.fi> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-SA-Exim-Connect-IP: 91.158.25.70 X-SA-Exim-Mail-From: cyndis@kapsi.fi X-SA-Exim-Scanned: No (on mail.kapsi.fi); SAEximRunCond expanded to false X-Spam-Status: No, score=-2.1 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,SPF_HELO_NONE,SPF_PASS, T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Mikko Perttunen Add code to register context devices from device tree, allocate them out and manage their refcounts. Signed-off-by: Mikko Perttunen --- v2: * Directly set DMA mask instead of inheriting from Host1x. * Use iommu-map instead of custom DT property. v4: * Use u64 instead of dma_addr_t for DMA mask * Use unsigned ints for indexes and adjust error handling flow * Parse iommu-map property at top level host1x DT node * Use separate DMA mask per device * Export symbols as GPL --- drivers/gpu/host1x/Makefile | 1 + drivers/gpu/host1x/context.c | 160 +++++++++++++++++++++++++++++++++++ drivers/gpu/host1x/context.h | 27 ++++++ drivers/gpu/host1x/dev.c | 12 ++- drivers/gpu/host1x/dev.h | 2 + include/linux/host1x.h | 18 ++++ 6 files changed, 219 insertions(+), 1 deletion(-) create mode 100644 drivers/gpu/host1x/context.c create mode 100644 drivers/gpu/host1x/context.h diff --git a/drivers/gpu/host1x/Makefile b/drivers/gpu/host1x/Makefile index c891a3e33844..8a65e13d113a 100644 --- a/drivers/gpu/host1x/Makefile +++ b/drivers/gpu/host1x/Makefile @@ -10,6 +10,7 @@ host1x-y = \ debug.o \ mipi.o \ fence.o \ + context.o \ hw/host1x01.o \ hw/host1x02.o \ hw/host1x04.o \ diff --git a/drivers/gpu/host1x/context.c b/drivers/gpu/host1x/context.c new file mode 100644 index 000000000000..c5889be64634 --- /dev/null +++ b/drivers/gpu/host1x/context.c @@ -0,0 +1,160 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2021, NVIDIA Corporation. + */ + +#include +#include +#include +#include +#include +#include + +#include "context.h" +#include "dev.h" + +int host1x_context_list_init(struct host1x *host1x) +{ + struct host1x_context_list *cdl = &host1x->context_list; + struct device_node *node = host1x->dev->of_node; + struct host1x_context *ctx; + unsigned int i; + int err; + + cdl->devs = NULL; + cdl->len = 0; + mutex_init(&cdl->lock); + + err = of_property_count_u32_elems(node, "iommu-map"); + if (err < 0) + return 0; + + cdl->devs = kcalloc(err, sizeof(*cdl->devs), GFP_KERNEL); + if (!cdl->devs) + return -ENOMEM; + cdl->len = err / 4; + + for (i = 0; i < cdl->len; i++) { + struct iommu_fwspec *fwspec; + + ctx = &cdl->devs[i]; + + ctx->host = host1x; + + device_initialize(&ctx->dev); + + /* + * Due to an issue with T194 NVENC, only 38 bits can be used. + * Anyway, 256GiB of IOVA ought to be enough for anyone. + */ + ctx->dma_mask = DMA_BIT_MASK(38); + ctx->dev.dma_mask = &ctx->dma_mask; + ctx->dev.coherent_dma_mask = ctx->dma_mask; + dev_set_name(&ctx->dev, "host1x-ctx.%d", i); + ctx->dev.bus = &host1x_context_device_bus_type; + ctx->dev.parent = host1x->dev; + + dma_set_max_seg_size(&ctx->dev, UINT_MAX); + + err = device_add(&ctx->dev); + if (err) { + dev_err(host1x->dev, "could not add context device %d: %d\n", i, err); + goto del_devices; + } + + err = of_dma_configure_id(&ctx->dev, node, true, &i); + if (err) { + dev_err(host1x->dev, "IOMMU configuration failed for context device %d: %d\n", + i, err); + device_del(&ctx->dev); + goto del_devices; + } + + fwspec = dev_iommu_fwspec_get(&ctx->dev); + if (!fwspec) { + dev_err(host1x->dev, "Context device %d has no IOMMU!\n", i); + device_del(&ctx->dev); + goto del_devices; + } + + ctx->stream_id = fwspec->ids[0] & 0xffff; + } + + return 0; + +del_devices: + while (i--) + device_del(&cdl->devs[i].dev); + + kfree(cdl->devs); + cdl->len = 0; + + return err; +} + +void host1x_context_list_free(struct host1x_context_list *cdl) +{ + unsigned int i; + + for (i = 0; i < cdl->len; i++) + device_del(&cdl->devs[i].dev); + + kfree(cdl->devs); + cdl->len = 0; +} + +struct host1x_context *host1x_context_alloc(struct host1x *host1x, + struct pid *pid) +{ + struct host1x_context_list *cdl = &host1x->context_list; + struct host1x_context *free = NULL; + int i; + + if (!cdl->len) + return ERR_PTR(-EOPNOTSUPP); + + mutex_lock(&cdl->lock); + + for (i = 0; i < cdl->len; i++) { + struct host1x_context *cd = &cdl->devs[i]; + + if (cd->owner == pid) { + refcount_inc(&cd->ref); + mutex_unlock(&cdl->lock); + return cd; + } else if (!cd->owner && !free) { + free = cd; + } + } + + if (!free) { + mutex_unlock(&cdl->lock); + return ERR_PTR(-EBUSY); + } + + refcount_set(&free->ref, 1); + free->owner = get_pid(pid); + + mutex_unlock(&cdl->lock); + + return free; +} +EXPORT_SYMBOL_GPL(host1x_context_alloc); + +void host1x_context_get(struct host1x_context *cd) +{ + refcount_inc(&cd->ref); +} +EXPORT_SYMBOL_GPL(host1x_context_get); + +void host1x_context_put(struct host1x_context *cd) +{ + struct host1x_context_list *cdl = &cd->host->context_list; + + if (refcount_dec_and_mutex_lock(&cd->ref, &cdl->lock)) { + put_pid(cd->owner); + cd->owner = NULL; + mutex_unlock(&cdl->lock); + } +} +EXPORT_SYMBOL_GPL(host1x_context_put); diff --git a/drivers/gpu/host1x/context.h b/drivers/gpu/host1x/context.h new file mode 100644 index 000000000000..268ecdf6b1bb --- /dev/null +++ b/drivers/gpu/host1x/context.h @@ -0,0 +1,27 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Host1x context devices + * + * Copyright (c) 2020, NVIDIA Corporation. + */ + +#ifndef __HOST1X_CONTEXT_H +#define __HOST1X_CONTEXT_H + +#include +#include + +struct host1x; + +extern struct bus_type host1x_context_device_bus_type; + +struct host1x_context_list { + struct mutex lock; + struct host1x_context *devs; + unsigned int len; +}; + +int host1x_context_list_init(struct host1x *host1x); +void host1x_context_list_free(struct host1x_context_list *cdl); + +#endif diff --git a/drivers/gpu/host1x/dev.c b/drivers/gpu/host1x/dev.c index 6994f8c0e02e..40f64efd5865 100644 --- a/drivers/gpu/host1x/dev.c +++ b/drivers/gpu/host1x/dev.c @@ -28,6 +28,7 @@ #include "bus.h" #include "channel.h" +#include "context.h" #include "debug.h" #include "dev.h" #include "intr.h" @@ -502,10 +503,16 @@ static int host1x_probe(struct platform_device *pdev) goto iommu_exit; } + err = host1x_context_list_init(host); + if (err) { + dev_err(&pdev->dev, "failed to initialize context list\n"); + goto free_channels; + } + err = host1x_syncpt_init(host); if (err) { dev_err(&pdev->dev, "failed to initialize syncpts\n"); - goto free_channels; + goto free_contexts; } err = host1x_intr_init(host, syncpt_irq); @@ -549,6 +556,8 @@ static int host1x_probe(struct platform_device *pdev) host1x_intr_deinit(host); deinit_syncpt: host1x_syncpt_deinit(host); +free_contexts: + host1x_context_list_free(&host->context_list); free_channels: host1x_channel_list_free(&host->channel_list); iommu_exit: @@ -568,6 +577,7 @@ static int host1x_remove(struct platform_device *pdev) host1x_intr_deinit(host); host1x_syncpt_deinit(host); + host1x_context_list_free(&host->context_list); host1x_iommu_exit(host); host1x_bo_cache_destroy(&host->cache); diff --git a/drivers/gpu/host1x/dev.h b/drivers/gpu/host1x/dev.h index ca4b082f0cd4..92f4804d8b70 100644 --- a/drivers/gpu/host1x/dev.h +++ b/drivers/gpu/host1x/dev.h @@ -14,6 +14,7 @@ #include "cdma.h" #include "channel.h" +#include "context.h" #include "intr.h" #include "job.h" #include "syncpt.h" @@ -141,6 +142,7 @@ struct host1x { struct mutex syncpt_mutex; struct host1x_channel_list channel_list; + struct host1x_context_list context_list; struct dentry *debugfs; diff --git a/include/linux/host1x.h b/include/linux/host1x.h index e8dc5bc41f79..9dbdc4b0bb82 100644 --- a/include/linux/host1x.h +++ b/include/linux/host1x.h @@ -440,4 +440,22 @@ int tegra_mipi_disable(struct tegra_mipi_device *device); int tegra_mipi_start_calibration(struct tegra_mipi_device *device); int tegra_mipi_finish_calibration(struct tegra_mipi_device *device); +/* host1x context devices */ + +struct host1x_context { + struct host1x *host; + + refcount_t ref; + struct pid *owner; + + struct device dev; + u64 dma_mask; + u32 stream_id; +}; + +struct host1x_context *host1x_context_alloc(struct host1x *host1x, + struct pid *pid); +void host1x_context_get(struct host1x_context *cd); +void host1x_context_put(struct host1x_context *cd); + #endif -- 2.35.0