From patchwork Fri Sep 17 12:59:42 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alexandre Bailon X-Patchwork-Id: 12502015 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-17.1 required=3.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER, INCLUDES_PATCH,MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED, USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id B4EB8C433F5 for ; Fri, 17 Sep 2021 12:58:39 +0000 (UTC) Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 7C384610C7 for ; Fri, 17 Sep 2021 12:58:39 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.4.1 mail.kernel.org 7C384610C7 Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=baylibre.com Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=lists.infradead.org DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender: Content-Transfer-Encoding:Content-Type:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To: Message-Id:Date:Subject:Cc:To:From:Reply-To:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Owner; bh=rsPrStI5ziXt4LEmA5clofewKWOi5wpXLM4Hqv+OPUU=; b=dviE+CBV8gfKU7 ChGLnpzggY8O/TKAhGu1bgOuAc9K130lfDTWgekE+Wf0GcKgSBtZ6hZaJyjl9SRfjFHK2cBdv34Vw P6M1vafON4QY6scMnUeZr0m8f03zAv2F8zcgGg+7vKxH3bqH3apmhXWXtUfbMh57QY/4XhbnoKO6n oDxfOwpKNtN1QAu9uhzEM9jm2wKHvvDmiz1evheAIENiSFSimVbyhx9kXRCl/QpouzKFt/RmxvdfW 3cCeu4BUqU6Rx1MecD6zNSVRManTlBiv3vmi7Tv5gpvg3MwgnhdNYTsr3UL89iH34xm1Z2+EVLBFt JyJdjqy1Ekw3axc0m3QQ==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.94.2 #2 (Red Hat Linux)) id 1mRDRj-00EDGk-7k; Fri, 17 Sep 2021 12:58:27 +0000 Received: from mail-wm1-x330.google.com ([2a00:1450:4864:20::330]) by bombadil.infradead.org with esmtps (Exim 4.94.2 #2 (Red Hat Linux)) id 1mRDRF-00ED2m-9x for linux-mediatek@lists.infradead.org; Fri, 17 Sep 2021 12:58:01 +0000 Received: by mail-wm1-x330.google.com with SMTP id a194-20020a1c98cb000000b0030b41ac389fso2098262wme.2 for ; Fri, 17 Sep 2021 05:57:56 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=baylibre-com.20210112.gappssmtp.com; s=20210112; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=iFUWw1a7QUKqKqitz2aLpXkNS/Ii3+Zh8E8PhFDc+ws=; b=0aPjARok8/bfyOykh5nmswrCWnnajZ9Af1BN4K/pxHOLzmexwy5ZSttA5vuhF+CteC jK/VKVic+QznbXHckMZV+vyrkKEAOQV7FSpYqgsPyImc+0nDdIL+qapHkvFD9hfn9HFw c/8hYl7aD9GYrpTdiOGoleERAwIz4yRWaXhAqFXEQIjTEGeDm+TB2s2hoa4RiHeDXozX pzaSQup9ftlw3Sx/54iPCDZsQgq2EZOGF+jmVIoVQGpaxuo//v/vIH52vpw7CcX59/Bj LK5trF/UjX8E5Z4bjl9Je4k96vrzzjCw6+zQWuNfbaMWusngmJzUb40pYixCah6EoQ6p uGQg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=iFUWw1a7QUKqKqitz2aLpXkNS/Ii3+Zh8E8PhFDc+ws=; b=t+XjtmZ21YKUn+ry1T5Qo+FxLn7V/eo/IJCdRUX1DIxN8HSgz732wArHaAIlnDAjzj X+nqPykFwgijKqXRhGx0WAplZQ4k0MrKqKtyXpjKE7TBPlZJDgOZ89JnjH/0BX/YBLNl Hb2UWI48WXvvmS1Pny9yg2Mkg8IZsxt4R4QQ2Xk78AqNCADOpUztcfs7jo+/mwfakhUH 02FxtA9jMAeoLu04RmcwRH4bD9C8AG1bPiOE8bxLtx5237r/NvrQVhxb0YZgSPqqZKSx 2qxssHZ2T4EIKa8hs+aQfu80KW3HjHZ5B6OC9y3Fc5Rg45WoBV7vmsK9Y6UqMWQ+G0Xb bdfg== X-Gm-Message-State: AOAM532SvsgQFDZYy/rPTwubtgF+pMq58zO9450rtAmLiLIoU/WamqMj Jc2mLbiA0qhpPWp1w+Mnp9nfnHbK6YS+Bg== X-Google-Smtp-Source: ABdhPJxWy0XCmee8O9AAHX/X1X4XNYljnsvUJuOMbUQaDzoewnSPgl2VT0nmiywxBLNmsxTlY3hzgQ== X-Received: by 2002:a05:600c:3ba3:: with SMTP id n35mr10075940wms.166.1631883475858; Fri, 17 Sep 2021 05:57:55 -0700 (PDT) Received: from localhost.baylibre.local (laubervilliers-658-1-213-31.w90-63.abo.wanadoo.fr. [90.63.244.31]) by smtp.gmail.com with ESMTPSA id f3sm6358636wmj.28.2021.09.17.05.57.54 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 17 Sep 2021 05:57:55 -0700 (PDT) From: Alexandre Bailon To: airlied@linux.ie, daniel@ffwll.ch, robh+dt@kernel.org, matthias.bgg@gmail.com, maarten.lankhorst@linux.intel.com, mripard@kernel.org, tzimmermann@suse.de, ohad@wizery.com, bjorn.andersson@linaro.org, mathieu.poirier@linaro.org, sumit.semwal@linaro.org Cc: christian.koenig@amd.com, dri-devel@lists.freedesktop.org, devicetree@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-mediatek@lists.infradead.org, linux-kernel@vger.kernel.org, linux-remoteproc@vger.kernel.org, linux-media@vger.kernel.org, linaro-mm-sig@lists.linaro.org, khilman@baylibre.com, gpain@baylibre.com, Alexandre Bailon Subject: [RFC PATCH 1/4] dt-bindings: Add bidings for mtk,apu-drm Date: Fri, 17 Sep 2021 14:59:42 +0200 Message-Id: <20210917125945.620097-2-abailon@baylibre.com> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20210917125945.620097-1-abailon@baylibre.com> References: <20210917125945.620097-1-abailon@baylibre.com> MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20210917_055757_387785_2558F52D X-CRM114-Status: GOOD ( 12.38 ) X-BeenThere: linux-mediatek@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "Linux-mediatek" Errors-To: linux-mediatek-bounces+linux-mediatek=archiver.kernel.org@lists.infradead.org This adds the device tree bindings for the APU DRM driver. Signed-off-by: Alexandre Bailon --- .../devicetree/bindings/gpu/mtk,apu-drm.yaml | 38 +++++++++++++++++++ 1 file changed, 38 insertions(+) create mode 100644 Documentation/devicetree/bindings/gpu/mtk,apu-drm.yaml diff --git a/Documentation/devicetree/bindings/gpu/mtk,apu-drm.yaml b/Documentation/devicetree/bindings/gpu/mtk,apu-drm.yaml new file mode 100644 index 0000000000000..6f432d3ea478c --- /dev/null +++ b/Documentation/devicetree/bindings/gpu/mtk,apu-drm.yaml @@ -0,0 +1,38 @@ +# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/gpu/mediatek,apu-drm.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: AI Processor Unit DRM + +properties: + compatible: + const: mediatek,apu-drm + + remoteproc: + maxItems: 2 + description: + Handle to remoteproc devices controlling the APU + + iova: + maxItems: 1 + description: + Address and size of virtual memory that could used by the APU + +required: + - compatible + - remoteproc + - iova + +additionalProperties: false + +examples: + - | + apu@0 { + compatible = "mediatek,apu-drm"; + remoteproc = <&vpu0>, <&vpu1>; + iova = <0 0x60000000 0 0x10000000>; + }; + +... From patchwork Fri Sep 17 12:59:43 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alexandre Bailon X-Patchwork-Id: 12502043 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-17.1 required=3.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER, INCLUDES_PATCH,MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED, USER_AGENT_GIT autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id C8D00C433EF for ; Fri, 17 Sep 2021 12:59:07 +0000 (UTC) Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 8F2C761130 for ; Fri, 17 Sep 2021 12:59:07 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.4.1 mail.kernel.org 8F2C761130 Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=baylibre.com Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=lists.infradead.org DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender: Content-Transfer-Encoding:Content-Type:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To: Message-Id:Date:Subject:Cc:To:From:Reply-To:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Owner; bh=RAtZ9hnpDy7M4hcs3fhvABRZg0Ey0G+GJ7YNKCBgvpw=; b=uSpc+4FG8Mfyrt zsFAAsc29ureM/wceQjmtACju8kc3nnFKUn2S6NIruSN1QzAN8BgiXUh9AgES37X+inIuD1YhNb4b Sui/oFtkPnjBAQrASgZb1LRzlwBZew6z5xSE6sC2/zLmQeF6nQKLwQUjzaHLBnwebYICr0AVADj+m b9Rndu67LT9dRAw5Ox2iH62hj6HySVzzgulBwut3eCHztz314jf4Bnu/R1a6MOWrWpX3Y3j6DEixQ Gw8yO/Sr/velUkVnJpDjQ1WRebZTqMKZW0lzj/JpIP3EsRCEJ2LqAndmdaX5idhTlx31cVv4h1DMw wB7SDO5ETEZ2fq7x5DTg==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.94.2 #2 (Red Hat Linux)) id 1mRDS7-00EDSP-SR; Fri, 17 Sep 2021 12:58:51 +0000 Received: from mail-wm1-x32f.google.com ([2a00:1450:4864:20::32f]) by bombadil.infradead.org with esmtps (Exim 4.94.2 #2 (Red Hat Linux)) id 1mRDRH-00ED3n-I1 for linux-mediatek@lists.infradead.org; Fri, 17 Sep 2021 12:58:05 +0000 Received: by mail-wm1-x32f.google.com with SMTP id f62-20020a1c1f41000000b0030b42643f72so1827416wmf.3 for ; Fri, 17 Sep 2021 05:57:59 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=baylibre-com.20210112.gappssmtp.com; s=20210112; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=kveOhsYdfcJGM7hWZYWGj9xAFDOT8yCCjJMc15hxR3E=; b=gmoH5MRBAIPsqFg4scp3ximcPls0Zz60KgnOCyiy17oQXlewYk7aLXSiloSnFp6aiR J6/wFkELg/duwNxRK3C2DBJsAwtXypryBFTpd0XnHDrTOvaRrul4sLBmOGdm12vZjV1s LoRihepH16yf6AefIbvS5ExqnQaI7yCiJmh7Hbmzaio5Vm1Jciv646S4oV+nbA+2cUhl tbJJYulBBiSqZu2U3qhugn2E8eXES1NcRTiJJ4PnyxgdVB3McxyHAPBl/RPoVUmCeB+c kxiIxiEaGDw6PTYuzwH0ZsSjlydeas6uUTO6BaWcKzfhE7CuQonU4zuRx6KMkaf+21Ik 2OIw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=kveOhsYdfcJGM7hWZYWGj9xAFDOT8yCCjJMc15hxR3E=; b=bJJegG3pr1eksKSrCDIA7HXN/qa0lchHUNq9JLIK4vgyz97GSsEjq0MKzjPUpY60Iy +sAizt+deTs50CwVPnIPhVaSXu5d2CCGwC4GT26e5bABIdJed9O/ERX/sa2sz7T/Kd0V KAq3VmUaBvKVc8VRyA4+j5mWeY8+1vdPCX+1Yp0x2gPhMomxgpHA8AacMQyhViX3zZJQ mQcmsT1CGC/RLQ9ytIBRPZINlEnbg28V0XLDpkR5s/T/E0jR9QKEWpBQm5SO7r3QrMr0 gmv6EPibJattt3tMqxdhfm40RHiibz46alt0ulPdtDsvYxC6JvNI2nBO7Fu8TRAOR8sc 5wIw== X-Gm-Message-State: AOAM533XxaL9ALDgeerk0ADFyGX4zQbiqriAnefkjzhMtJYu0KxK8wI0 rO7RnGiPJuTjCSqobd5TuIdRhA== X-Google-Smtp-Source: ABdhPJzc+CE1ZuQk0hv+TyHYZ3w8badxvqjTtmMVEdAuwEbC5vK3pcLl/B/JLUTnk0U78dBaKrC91A== X-Received: by 2002:a05:600c:4f95:: with SMTP id n21mr14849827wmq.22.1631883477885; Fri, 17 Sep 2021 05:57:57 -0700 (PDT) Received: from localhost.baylibre.local (laubervilliers-658-1-213-31.w90-63.abo.wanadoo.fr. [90.63.244.31]) by smtp.gmail.com with ESMTPSA id f3sm6358636wmj.28.2021.09.17.05.57.55 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 17 Sep 2021 05:57:56 -0700 (PDT) From: Alexandre Bailon To: airlied@linux.ie, daniel@ffwll.ch, robh+dt@kernel.org, matthias.bgg@gmail.com, maarten.lankhorst@linux.intel.com, mripard@kernel.org, tzimmermann@suse.de, ohad@wizery.com, bjorn.andersson@linaro.org, mathieu.poirier@linaro.org, sumit.semwal@linaro.org Cc: christian.koenig@amd.com, dri-devel@lists.freedesktop.org, devicetree@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-mediatek@lists.infradead.org, linux-kernel@vger.kernel.org, linux-remoteproc@vger.kernel.org, linux-media@vger.kernel.org, linaro-mm-sig@lists.linaro.org, khilman@baylibre.com, gpain@baylibre.com, Alexandre Bailon Subject: [RFC PATCH 2/4] DRM: Add support of AI Processor Unit (APU) Date: Fri, 17 Sep 2021 14:59:43 +0200 Message-Id: <20210917125945.620097-3-abailon@baylibre.com> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20210917125945.620097-1-abailon@baylibre.com> References: <20210917125945.620097-1-abailon@baylibre.com> MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20210917_055759_738827_0B4FCF29 X-CRM114-Status: GOOD ( 27.04 ) X-BeenThere: linux-mediatek@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "Linux-mediatek" Errors-To: linux-mediatek-bounces+linux-mediatek=archiver.kernel.org@lists.infradead.org Some Mediatek SoC provides hardware accelerator for AI / ML. This driver provides the infrastructure to manage memory shared between host CPU and the accelerator, and to submit jobs to the accelerator. The APU itself is managed by remoteproc so this drivers relies on remoteproc to found the APU and get some important data from it. But, the driver is quite generic and it should possible to manage accelerator using another ways. This driver doesn't manage itself the data transmitions. It must be registered by another driver implementing the transmitions. Signed-off-by: Alexandre Bailon --- drivers/gpu/drm/Kconfig | 2 + drivers/gpu/drm/Makefile | 1 + drivers/gpu/drm/apu/Kconfig | 10 + drivers/gpu/drm/apu/Makefile | 7 + drivers/gpu/drm/apu/apu_drm_drv.c | 238 +++++++++++ drivers/gpu/drm/apu/apu_gem.c | 232 +++++++++++ drivers/gpu/drm/apu/apu_internal.h | 89 ++++ drivers/gpu/drm/apu/apu_sched.c | 634 +++++++++++++++++++++++++++++ include/drm/apu_drm.h | 59 +++ include/uapi/drm/apu_drm.h | 106 +++++ 10 files changed, 1378 insertions(+) create mode 100644 drivers/gpu/drm/apu/Kconfig create mode 100644 drivers/gpu/drm/apu/Makefile create mode 100644 drivers/gpu/drm/apu/apu_drm_drv.c create mode 100644 drivers/gpu/drm/apu/apu_gem.c create mode 100644 drivers/gpu/drm/apu/apu_internal.h create mode 100644 drivers/gpu/drm/apu/apu_sched.c create mode 100644 include/drm/apu_drm.h create mode 100644 include/uapi/drm/apu_drm.h diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig index 8fc40317f2b77..bcdca35c9eda5 100644 --- a/drivers/gpu/drm/Kconfig +++ b/drivers/gpu/drm/Kconfig @@ -382,6 +382,8 @@ source "drivers/gpu/drm/xlnx/Kconfig" source "drivers/gpu/drm/gud/Kconfig" +source "drivers/gpu/drm/apu/Kconfig" + config DRM_HYPERV tristate "DRM Support for Hyper-V synthetic video device" depends on DRM && PCI && MMU && HYPERV diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile index ad11121548983..f3d8432976558 100644 --- a/drivers/gpu/drm/Makefile +++ b/drivers/gpu/drm/Makefile @@ -127,4 +127,5 @@ obj-$(CONFIG_DRM_MCDE) += mcde/ obj-$(CONFIG_DRM_TIDSS) += tidss/ obj-y += xlnx/ obj-y += gud/ +obj-$(CONFIG_DRM_APU) += apu/ obj-$(CONFIG_DRM_HYPERV) += hyperv/ diff --git a/drivers/gpu/drm/apu/Kconfig b/drivers/gpu/drm/apu/Kconfig new file mode 100644 index 0000000000000..c8471309a0351 --- /dev/null +++ b/drivers/gpu/drm/apu/Kconfig @@ -0,0 +1,10 @@ +# SPDX-License-Identifier: GPL-2.0-only +# + +config DRM_APU + tristate "APU (AI Processor Unit)" + select REMOTEPROC + select DRM_SCHED + help + This provides a DRM driver that provides some facilities to + communicate with an accelerated processing unit (APU). diff --git a/drivers/gpu/drm/apu/Makefile b/drivers/gpu/drm/apu/Makefile new file mode 100644 index 0000000000000..3e97846b091c9 --- /dev/null +++ b/drivers/gpu/drm/apu/Makefile @@ -0,0 +1,7 @@ +# SPDX-License-Identifier: GPL-2.0 + +apu_drm-y += apu_drm_drv.o +apu_drm-y += apu_sched.o +apu_drm-y += apu_gem.o + +obj-$(CONFIG_DRM_APU) += apu_drm.o diff --git a/drivers/gpu/drm/apu/apu_drm_drv.c b/drivers/gpu/drm/apu/apu_drm_drv.c new file mode 100644 index 0000000000000..91d8c99e373c0 --- /dev/null +++ b/drivers/gpu/drm/apu/apu_drm_drv.c @@ -0,0 +1,238 @@ +// SPDX-License-Identifier: GPL-2.0 +// +// Copyright 2020 BayLibre SAS + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include + +#include "apu_internal.h" + +static LIST_HEAD(apu_devices); + +static const struct drm_ioctl_desc ioctls[] = { + DRM_IOCTL_DEF_DRV(APU_GEM_NEW, ioctl_gem_new, + DRM_RENDER_ALLOW), + DRM_IOCTL_DEF_DRV(APU_GEM_QUEUE, ioctl_gem_queue, + DRM_RENDER_ALLOW), + DRM_IOCTL_DEF_DRV(APU_GEM_DEQUEUE, ioctl_gem_dequeue, + DRM_RENDER_ALLOW), + DRM_IOCTL_DEF_DRV(APU_GEM_IOMMU_MAP, ioctl_gem_iommu_map, + DRM_RENDER_ALLOW), + DRM_IOCTL_DEF_DRV(APU_GEM_IOMMU_UNMAP, ioctl_gem_iommu_unmap, + DRM_RENDER_ALLOW), + DRM_IOCTL_DEF_DRV(APU_STATE, ioctl_apu_state, + DRM_RENDER_ALLOW), +}; + +DEFINE_DRM_GEM_CMA_FOPS(apu_drm_ops); + +static struct drm_driver apu_drm_driver = { + .driver_features = DRIVER_GEM | DRIVER_SYNCOBJ, + .name = "drm_apu", + .desc = "APU DRM driver", + .date = "20210319", + .major = 1, + .minor = 0, + .patchlevel = 0, + .ioctls = ioctls, + .num_ioctls = ARRAY_SIZE(ioctls), + .fops = &apu_drm_ops, + DRM_GEM_CMA_DRIVER_OPS_WITH_DUMB_CREATE(drm_gem_cma_dumb_create), +}; + +void *apu_drm_priv(struct apu_core *apu_core) +{ + return apu_core->priv; +} +EXPORT_SYMBOL_GPL(apu_drm_priv); + +int apu_drm_reserve_iova(struct apu_core *apu_core, u64 start, u64 size) +{ + struct apu_drm *apu_drm = apu_core->apu_drm; + struct iova *iova; + + iova = reserve_iova(&apu_drm->iovad, PHYS_PFN(start), + PHYS_PFN(start + size)); + if (!iova) + return -ENOMEM; + + return 0; +} +EXPORT_SYMBOL_GPL(apu_drm_reserve_iova); + +static int apu_drm_init_first_core(struct apu_drm *apu_drm, + struct apu_core *apu_core) +{ + struct drm_device *drm; + struct device *parent; + u64 mask; + + drm = apu_drm->drm; + parent = apu_core->rproc->dev.parent; + drm->dev->iommu_group = parent->iommu_group; + apu_drm->domain = iommu_get_domain_for_dev(parent); + set_dma_ops(drm->dev, get_dma_ops(parent)); + mask = dma_get_mask(parent); + return dma_coerce_mask_and_coherent(drm->dev, mask); +} + +struct apu_core *apu_drm_register_core(struct rproc *rproc, + struct apu_drm_ops *ops, void *priv) +{ + struct apu_drm *apu_drm; + struct apu_core *apu_core; + int ret; + + list_for_each_entry(apu_drm, &apu_devices, node) { + list_for_each_entry(apu_core, &apu_drm->apu_cores, node) { + if (apu_core->rproc == rproc) { + ret = + apu_drm_init_first_core(apu_drm, apu_core); + apu_core->dev = &rproc->dev; + apu_core->priv = priv; + apu_core->ops = ops; + + ret = apu_drm_job_init(apu_core); + if (ret) + return NULL; + + return apu_core; + } + } + } + + return NULL; +} +EXPORT_SYMBOL_GPL(apu_drm_register_core); + +int apu_drm_unregister_core(void *priv) +{ + struct apu_drm *apu_drm; + struct apu_core *apu_core; + + list_for_each_entry(apu_drm, &apu_devices, node) { + list_for_each_entry(apu_core, &apu_drm->apu_cores, node) { + if (apu_core->priv == priv) { + apu_sched_fini(apu_core); + apu_core->priv = NULL; + apu_core->ops = NULL; + } + } + } + + return 0; +} +EXPORT_SYMBOL_GPL(apu_drm_unregister_core); + +#ifdef CONFIG_OF +static const struct of_device_id apu_platform_of_match[] = { + { .compatible = "mediatek,apu-drm", }, + { }, +}; + +MODULE_DEVICE_TABLE(of, apu_platform_of_match); +#endif + +static int apu_platform_probe(struct platform_device *pdev) +{ + struct drm_device *drm; + struct apu_drm *apu_drm; + struct of_phandle_iterator it; + int index = 0; + u64 iova[2]; + int ret; + + apu_drm = devm_kzalloc(&pdev->dev, sizeof(*apu_drm), GFP_KERNEL); + if (!apu_drm) + return -ENOMEM; + INIT_LIST_HEAD(&apu_drm->apu_cores); + + of_phandle_iterator_init(&it, pdev->dev.of_node, "remoteproc", NULL, 0); + while (of_phandle_iterator_next(&it) == 0) { + struct rproc *rproc = rproc_get_by_phandle(it.phandle); + struct apu_core *apu_core; + + if (!rproc) + return -EPROBE_DEFER; + + apu_core = devm_kzalloc(&pdev->dev, sizeof(*apu_core), + GFP_KERNEL); + if (!apu_core) + return -ENOMEM; + + apu_core->rproc = rproc; + apu_core->device_id = index++; + apu_core->apu_drm = apu_drm; + spin_lock_init(&apu_core->ctx_lock); + INIT_LIST_HEAD(&apu_core->requests); + list_add(&apu_core->node, &apu_drm->apu_cores); + } + + if (of_property_read_variable_u64_array(pdev->dev.of_node, "iova", + iova, ARRAY_SIZE(iova), + ARRAY_SIZE(iova)) != + ARRAY_SIZE(iova)) + return -EINVAL; + + init_iova_domain(&apu_drm->iovad, PAGE_SIZE, PHYS_PFN(iova[0])); + apu_drm->iova_limit_pfn = PHYS_PFN(iova[0] + iova[1]) - 1; + + drm = drm_dev_alloc(&apu_drm_driver, &pdev->dev); + if (IS_ERR(drm)) { + ret = PTR_ERR(drm); + return ret; + } + + ret = drm_dev_register(drm, 0); + if (ret) { + drm_dev_put(drm); + return ret; + } + + drm->dev_private = apu_drm; + apu_drm->drm = drm; + apu_drm->dev = &pdev->dev; + + platform_set_drvdata(pdev, drm); + + list_add(&apu_drm->node, &apu_devices); + + return 0; +} + +static int apu_platform_remove(struct platform_device *pdev) +{ + struct drm_device *drm; + + drm = platform_get_drvdata(pdev); + + drm_dev_unregister(drm); + drm_dev_put(drm); + + return 0; +} + +static struct platform_driver apu_platform_driver = { + .probe = apu_platform_probe, + .remove = apu_platform_remove, + .driver = { + .name = "apu_drm", + .of_match_table = of_match_ptr(apu_platform_of_match), + }, +}; + +module_platform_driver(apu_platform_driver); diff --git a/drivers/gpu/drm/apu/apu_gem.c b/drivers/gpu/drm/apu/apu_gem.c new file mode 100644 index 0000000000000..c867143dab436 --- /dev/null +++ b/drivers/gpu/drm/apu/apu_gem.c @@ -0,0 +1,232 @@ +// SPDX-License-Identifier: GPL-2.0 +// +// Copyright 2020 BayLibre SAS + +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include + +#include "apu_internal.h" + +struct drm_gem_object *apu_gem_create_object(struct drm_device *dev, + size_t size) +{ + struct drm_gem_cma_object *cma_obj; + + cma_obj = drm_gem_cma_create(dev, size); + if (!cma_obj) + return NULL; + + return &cma_obj->base; +} + +int ioctl_gem_new(struct drm_device *dev, void *data, + struct drm_file *file_priv) +{ + struct drm_apu_gem_new *args = data; + struct drm_gem_cma_object *cma_obj; + struct apu_gem_object *apu_obj; + struct drm_gem_object *gem_obj; + int ret; + + cma_obj = drm_gem_cma_create(dev, args->size); + if (IS_ERR(cma_obj)) + return PTR_ERR(cma_obj); + + gem_obj = &cma_obj->base; + apu_obj = to_apu_bo(gem_obj); + + /* + * Save the size of buffer expected by application instead of the + * aligned one. + */ + apu_obj->size = args->size; + apu_obj->offset = 0; + apu_obj->iommu_refcount = 0; + mutex_init(&apu_obj->mutex); + + ret = drm_gem_handle_create(file_priv, gem_obj, &args->handle); + drm_gem_object_put(gem_obj); + if (ret) { + drm_gem_cma_free_object(gem_obj); + return ret; + } + args->offset = drm_vma_node_offset_addr(&gem_obj->vma_node); + + return 0; +} + +void apu_bo_iommu_unmap(struct apu_drm *apu_drm, struct apu_gem_object *obj) +{ + int iova_pfn; + int i; + + if (!obj->iommu_sgt) + return; + + mutex_lock(&obj->mutex); + obj->iommu_refcount--; + if (obj->iommu_refcount) { + mutex_unlock(&obj->mutex); + return; + } + + iova_pfn = PHYS_PFN(obj->iova); + for (i = 0; i < obj->iommu_sgt->nents; i++) { + iommu_unmap(apu_drm->domain, PFN_PHYS(iova_pfn), + PAGE_ALIGN(obj->iommu_sgt->sgl[i].length)); + iova_pfn += PHYS_PFN(PAGE_ALIGN(obj->iommu_sgt->sgl[i].length)); + } + + sg_free_table(obj->iommu_sgt); + kfree(obj->iommu_sgt); + + free_iova(&apu_drm->iovad, PHYS_PFN(obj->iova)); + mutex_unlock(&obj->mutex); +} + +static struct sg_table *apu_get_sg_table(struct drm_gem_object *obj) +{ + if (obj->funcs) + return obj->funcs->get_sg_table(obj); + return NULL; +} + +int apu_bo_iommu_map(struct apu_drm *apu_drm, struct drm_gem_object *obj) +{ + struct apu_gem_object *apu_obj = to_apu_bo(obj); + struct scatterlist *sgl; + phys_addr_t phys; + int total_buf_space; + int iova_pfn; + int iova; + int ret; + int i; + + mutex_lock(&apu_obj->mutex); + apu_obj->iommu_refcount++; + if (apu_obj->iommu_refcount != 1) { + mutex_unlock(&apu_obj->mutex); + return 0; + } + + apu_obj->iommu_sgt = apu_get_sg_table(obj); + if (IS_ERR(apu_obj->iommu_sgt)) { + mutex_unlock(&apu_obj->mutex); + return PTR_ERR(apu_obj->iommu_sgt); + } + + total_buf_space = obj->size; + iova_pfn = alloc_iova_fast(&apu_drm->iovad, + total_buf_space >> PAGE_SHIFT, + apu_drm->iova_limit_pfn, true); + apu_obj->iova = PFN_PHYS(iova_pfn); + + if (!iova_pfn) { + dev_err(apu_drm->dev, "Failed to allocate iova address\n"); + mutex_unlock(&apu_obj->mutex); + return -ENOMEM; + } + + iova = apu_obj->iova; + sgl = apu_obj->iommu_sgt->sgl; + for (i = 0; i < apu_obj->iommu_sgt->nents; i++) { + phys = page_to_phys(sg_page(&sgl[i])); + ret = + iommu_map(apu_drm->domain, PFN_PHYS(iova_pfn), phys, + PAGE_ALIGN(sgl[i].length), + IOMMU_READ | IOMMU_WRITE); + if (ret) { + dev_err(apu_drm->dev, "Failed to iommu map\n"); + free_iova(&apu_drm->iovad, iova_pfn); + mutex_unlock(&apu_obj->mutex); + return ret; + } + iova += sgl[i].offset + sgl[i].length; + iova_pfn += PHYS_PFN(PAGE_ALIGN(sgl[i].length)); + } + mutex_unlock(&apu_obj->mutex); + + return 0; +} + +int ioctl_gem_iommu_map(struct drm_device *dev, void *data, + struct drm_file *file_priv) +{ + struct apu_drm *apu_drm = dev->dev_private; + struct drm_apu_gem_iommu_map *args = data; + struct drm_gem_object **bos; + void __user *bo_handles; + int ret; + int i; + + u64 *das = kvmalloc_array(args->bo_handle_count, + sizeof(u64), GFP_KERNEL); + if (!das) + return -ENOMEM; + + bo_handles = (void __user *)(uintptr_t) args->bo_handles; + ret = drm_gem_objects_lookup(file_priv, bo_handles, + args->bo_handle_count, &bos); + if (ret) { + kvfree(das); + return ret; + } + + for (i = 0; i < args->bo_handle_count; i++) { + ret = apu_bo_iommu_map(apu_drm, bos[i]); + if (ret) { + /* TODO: handle error */ + break; + } + das[i] = to_apu_bo(bos[i])->iova + to_apu_bo(bos[i])->offset; + } + + if (copy_to_user((void *)args->bo_device_addresses, das, + args->bo_handle_count * sizeof(u64))) { + ret = -EFAULT; + DRM_DEBUG("Failed to copy device addresses\n"); + goto out; + } + +out: + kvfree(das); + kvfree(bos); + + return 0; +} + +int ioctl_gem_iommu_unmap(struct drm_device *dev, void *data, + struct drm_file *file_priv) +{ + struct apu_drm *apu_drm = dev->dev_private; + struct drm_apu_gem_iommu_map *args = data; + struct drm_gem_object **bos; + void __user *bo_handles; + int ret; + int i; + + bo_handles = (void __user *)(uintptr_t) args->bo_handles; + ret = drm_gem_objects_lookup(file_priv, bo_handles, + args->bo_handle_count, &bos); + if (ret) + return ret; + + for (i = 0; i < args->bo_handle_count; i++) + apu_bo_iommu_unmap(apu_drm, to_apu_bo(bos[i])); + + kvfree(bos); + + return 0; +} diff --git a/drivers/gpu/drm/apu/apu_internal.h b/drivers/gpu/drm/apu/apu_internal.h new file mode 100644 index 0000000000000..b789b2f3ad9c6 --- /dev/null +++ b/drivers/gpu/drm/apu/apu_internal.h @@ -0,0 +1,89 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef __APU_INTERNAL_H__ +#define __APU_INTERNAL_H__ + +#include + +#include +#include +#include + +struct apu_gem_object { + struct drm_gem_cma_object base; + struct mutex mutex; + struct sg_table *iommu_sgt; + int iommu_refcount; + size_t size; + u32 iova; + u32 offset; +}; + +struct apu_sched; +struct apu_core { + int device_id; + struct device *dev; + struct rproc *rproc; + struct apu_drm_ops *ops; + struct apu_drm *apu_drm; + + spinlock_t ctx_lock; + struct list_head requests; + + struct list_head node; + void *priv; + + struct apu_sched *sched; + u32 flags; +}; + +struct apu_drm { + struct device *dev; + struct drm_device *drm; + + struct iommu_domain *domain; + struct iova_domain iovad; + int iova_limit_pfn; + + struct list_head apu_cores; + struct list_head node; +}; + +static inline struct apu_gem_object *to_apu_bo(struct drm_gem_object *obj) +{ + return container_of(to_drm_gem_cma_obj(obj), struct apu_gem_object, + base); +} + +struct apu_gem_object *to_apu_bo(struct drm_gem_object *obj); +struct drm_gem_object *apu_gem_create_object(struct drm_device *dev, + size_t size); + +int apu_bo_iommu_map(struct apu_drm *apu_drm, struct drm_gem_object *obj); +void apu_bo_iommu_unmap(struct apu_drm *apu_drm, struct apu_gem_object *obj); +struct drm_gem_object *apu_gem_create_object(struct drm_device *dev, + size_t size); +int ioctl_gem_new(struct drm_device *dev, void *data, + struct drm_file *file_priv); +int ioctl_gem_user_new(struct drm_device *dev, void *data, + struct drm_file *file_priv); +int ioctl_gem_iommu_map(struct drm_device *dev, void *data, + struct drm_file *file_priv); +int ioctl_gem_iommu_unmap(struct drm_device *dev, void *data, + struct drm_file *file_priv); +int ioctl_gem_queue(struct drm_device *dev, void *data, + struct drm_file *file_priv); +int ioctl_gem_dequeue(struct drm_device *dev, void *data, + struct drm_file *file_priv); +int ioctl_apu_state(struct drm_device *dev, void *data, + struct drm_file *file_priv); +struct dma_buf *apu_gem_prime_export(struct drm_gem_object *gem, + int flags); + +struct apu_job; + +int apu_drm_job_init(struct apu_core *core); +void apu_sched_fini(struct apu_core *core); +int apu_job_push(struct apu_job *job); +void apu_job_put(struct apu_job *job); + +#endif /* __APU_INTERNAL_H__ */ diff --git a/drivers/gpu/drm/apu/apu_sched.c b/drivers/gpu/drm/apu/apu_sched.c new file mode 100644 index 0000000000000..cebb0155c7783 --- /dev/null +++ b/drivers/gpu/drm/apu/apu_sched.c @@ -0,0 +1,634 @@ +// SPDX-License-Identifier: GPL-2.0 +// +// Copyright 2020 BayLibre SAS + +#include +#include +#include +#include +#include + +#include + +#include "apu_internal.h" + +struct apu_queue_state { + struct drm_gpu_scheduler sched; + + u64 fence_context; + u64 seqno; +}; + +struct apu_request { + struct list_head node; + void *job; +}; + +struct apu_sched { + struct apu_queue_state apu_queue; + spinlock_t job_lock; + struct drm_sched_entity sched_entity; +}; + +struct apu_event { + struct drm_pending_event pending_event; + union { + struct drm_event base; + struct apu_job_event job_event; + }; +}; + +struct apu_job { + struct drm_sched_job base; + + struct kref refcount; + + struct apu_core *apu_core; + struct apu_drm *apu_drm; + + /* Fence to be signaled by IRQ handler when the job is complete. */ + struct dma_fence *done_fence; + + __u32 cmd; + + /* Exclusive fences we have taken from the BOs to wait for */ + struct dma_fence **implicit_fences; + struct drm_gem_object **bos; + u32 bo_count; + + /* Fence to be signaled by drm-sched once its done with the job */ + struct dma_fence *render_done_fence; + + void *data_in; + uint16_t size_in; + void *data_out; + uint16_t size_out; + uint16_t result; + uint16_t id; + + struct list_head node; + struct drm_syncobj *sync_out; + + struct apu_event *event; +}; + +static DEFINE_IDA(req_ida); +static LIST_HEAD(complete_node); + +int apu_drm_callback(struct apu_core *apu_core, void *data, int len) +{ + struct apu_request *apu_req, *tmp; + struct apu_dev_request *hdr = data; + unsigned long flags; + + spin_lock_irqsave(&apu_core->ctx_lock, flags); + list_for_each_entry_safe(apu_req, tmp, &apu_core->requests, node) { + struct apu_job *job = apu_req->job; + + if (job && hdr->id == job->id) { + kref_get(&job->refcount); + job->result = hdr->result; + if (job->size_out) + memcpy(job->data_out, hdr->data + job->size_in, + min(job->size_out, hdr->size_out)); + job->size_out = hdr->size_out; + list_add(&job->node, &complete_node); + list_del(&apu_req->node); + ida_simple_remove(&req_ida, hdr->id); + kfree(apu_req); + drm_send_event(job->apu_drm->drm, + &job->event->pending_event); + dma_fence_signal_locked(job->done_fence); + } + } + spin_unlock_irqrestore(&apu_core->ctx_lock, flags); + + return 0; +} + +void apu_sched_fini(struct apu_core *core) +{ + drm_sched_fini(&core->sched->apu_queue.sched); + devm_kfree(core->dev, core->sched); + core->flags &= ~APU_ONLINE; + core->sched = NULL; +} + +static void apu_job_cleanup(struct kref *ref) +{ + struct apu_job *job = container_of(ref, struct apu_job, + refcount); + unsigned int i; + + if (job->implicit_fences) { + for (i = 0; i < job->bo_count; i++) + dma_fence_put(job->implicit_fences[i]); + kvfree(job->implicit_fences); + } + dma_fence_put(job->done_fence); + dma_fence_put(job->render_done_fence); + + if (job->bos) { + for (i = 0; i < job->bo_count; i++) { + struct apu_gem_object *apu_obj; + + apu_obj = to_apu_bo(job->bos[i]); + apu_bo_iommu_unmap(job->apu_drm, apu_obj); + drm_gem_object_put(job->bos[i]); + } + + kvfree(job->bos); + } + + kfree(job->data_out); + kfree(job->data_in); + kfree(job); +} + +void apu_job_put(struct apu_job *job) +{ + kref_put(&job->refcount, apu_job_cleanup); +} + +static void apu_acquire_object_fences(struct drm_gem_object **bos, + int bo_count, + struct dma_fence **implicit_fences) +{ + int i; + + for (i = 0; i < bo_count; i++) + implicit_fences[i] = dma_resv_get_excl_unlocked(bos[i]->resv); +} + +static void apu_attach_object_fences(struct drm_gem_object **bos, + int bo_count, struct dma_fence *fence) +{ + int i; + + for (i = 0; i < bo_count; i++) + dma_resv_add_excl_fence(bos[i]->resv, fence); +} + +int apu_job_push(struct apu_job *job) +{ + struct drm_sched_entity *entity = &job->apu_core->sched->sched_entity; + struct ww_acquire_ctx acquire_ctx; + int ret = 0; + + ret = drm_gem_lock_reservations(job->bos, job->bo_count, &acquire_ctx); + if (ret) + return ret; + + ret = drm_sched_job_init(&job->base, entity, NULL); + if (ret) + goto unlock; + + job->render_done_fence = dma_fence_get(&job->base.s_fence->finished); + + kref_get(&job->refcount); /* put by scheduler job completion */ + + apu_acquire_object_fences(job->bos, job->bo_count, + job->implicit_fences); + + drm_sched_entity_push_job(&job->base, entity); + + apu_attach_object_fences(job->bos, job->bo_count, + job->render_done_fence); + +unlock: + drm_gem_unlock_reservations(job->bos, job->bo_count, &acquire_ctx); + + return ret; +} + +static const char *apu_fence_get_driver_name(struct dma_fence *fence) +{ + return "apu"; +} + +static const char *apu_fence_get_timeline_name(struct dma_fence *fence) +{ + return "apu-0"; +} + +static void apu_fence_release(struct dma_fence *f) +{ + kfree(f); +} + +static const struct dma_fence_ops apu_fence_ops = { + .get_driver_name = apu_fence_get_driver_name, + .get_timeline_name = apu_fence_get_timeline_name, + .release = apu_fence_release, +}; + +static struct dma_fence *apu_fence_create(struct apu_sched *sched) +{ + struct dma_fence *fence; + struct apu_queue_state *apu_queue = &sched->apu_queue; + + fence = kzalloc(sizeof(*fence), GFP_KERNEL); + if (!fence) + return ERR_PTR(-ENOMEM); + + dma_fence_init(fence, &apu_fence_ops, &sched->job_lock, + apu_queue->fence_context, apu_queue->seqno++); + + return fence; +} + +static struct apu_job *to_apu_job(struct drm_sched_job *sched_job) +{ + return container_of(sched_job, struct apu_job, base); +} + +static struct dma_fence *apu_job_dependency(struct drm_sched_job *sched_job, + struct drm_sched_entity *s_entity) +{ + struct apu_job *job = to_apu_job(sched_job); + struct dma_fence *fence; + unsigned int i; + + /* Implicit fences, max. one per BO */ + for (i = 0; i < job->bo_count; i++) { + if (job->implicit_fences[i]) { + fence = job->implicit_fences[i]; + job->implicit_fences[i] = NULL; + return fence; + } + } + + return NULL; +} + +static int apu_job_hw_submit(struct apu_job *job) +{ + int ret; + struct apu_core *apu_core = job->apu_core; + struct apu_dev_request *dev_req; + struct apu_request *apu_req; + unsigned long flags; + + int size = sizeof(*dev_req) + sizeof(u32) * job->bo_count * 2; + u32 *dev_req_da; + u32 *dev_req_buffer_size; + int i; + + dev_req = kmalloc(size + job->size_in + job->size_out, GFP_KERNEL); + if (!dev_req) + return -ENOMEM; + + dev_req->cmd = job->cmd; + dev_req->size_in = job->size_in; + dev_req->size_out = job->size_out; + dev_req->count = job->bo_count; + dev_req_da = + (u32 *) (dev_req->data + dev_req->size_in + dev_req->size_out); + dev_req_buffer_size = (u32 *) (dev_req_da + dev_req->count); + memcpy(dev_req->data, job->data_in, job->size_in); + + apu_req = kzalloc(sizeof(*apu_req), GFP_KERNEL); + if (!apu_req) + return -ENOMEM; + + for (i = 0; i < job->bo_count; i++) { + struct apu_gem_object *obj = to_apu_bo(job->bos[i]); + + dev_req_da[i] = obj->iova + obj->offset; + dev_req_buffer_size[i] = obj->size; + } + + ret = ida_simple_get(&req_ida, 0, 0xffff, GFP_KERNEL); + if (ret < 0) + goto err_free_memory; + + dev_req->id = ret; + + job->id = dev_req->id; + apu_req->job = job; + spin_lock_irqsave(&apu_core->ctx_lock, flags); + list_add(&apu_req->node, &apu_core->requests); + spin_unlock_irqrestore(&apu_core->ctx_lock, flags); + ret = + apu_core->ops->send(apu_core, dev_req, + size + dev_req->size_in + dev_req->size_out); + if (ret < 0) + goto err; + kfree(dev_req); + + return 0; + +err: + list_del(&apu_req->node); + ida_simple_remove(&req_ida, dev_req->id); +err_free_memory: + kfree(apu_req); + kfree(dev_req); + + return ret; +} + +static struct dma_fence *apu_job_run(struct drm_sched_job *sched_job) +{ + struct apu_job *job = to_apu_job(sched_job); + struct dma_fence *fence = NULL; + + if (unlikely(job->base.s_fence->finished.error)) + return NULL; + + fence = apu_fence_create(job->apu_core->sched); + if (IS_ERR(fence)) + return NULL; + + job->done_fence = dma_fence_get(fence); + + apu_job_hw_submit(job); + + return fence; +} + +static void apu_update_rpoc_state(struct apu_core *core) +{ + if (core->rproc) { + if (core->rproc->state == RPROC_CRASHED) + core->flags |= APU_CRASHED; + if (core->rproc->state == RPROC_OFFLINE) + core->flags &= ~APU_ONLINE; + } +} + +static enum drm_gpu_sched_stat apu_job_timedout(struct drm_sched_job *sched_job) +{ + struct apu_request *apu_req, *tmp; + struct apu_job *job = to_apu_job(sched_job); + + if (dma_fence_is_signaled(job->done_fence)) + return DRM_GPU_SCHED_STAT_NOMINAL; + + list_for_each_entry_safe(apu_req, tmp, &job->apu_core->requests, node) { + /* Remove the request and notify user about timeout */ + if (apu_req->job == job) { + kref_get(&job->refcount); + job->apu_core->flags |= APU_TIMEDOUT; + apu_update_rpoc_state(job->apu_core); + job->result = ETIMEDOUT; + list_add(&job->node, &complete_node); + list_del(&apu_req->node); + ida_simple_remove(&req_ida, job->id); + kfree(apu_req); + drm_send_event(job->apu_drm->drm, + &job->event->pending_event); + dma_fence_signal_locked(job->done_fence); + } + } + + return DRM_GPU_SCHED_STAT_NOMINAL; +} + +static void apu_job_free(struct drm_sched_job *sched_job) +{ + struct apu_job *job = to_apu_job(sched_job); + + drm_sched_job_cleanup(sched_job); + + apu_job_put(job); +} + +static const struct drm_sched_backend_ops apu_sched_ops = { + .dependency = apu_job_dependency, + .run_job = apu_job_run, + .timedout_job = apu_job_timedout, + .free_job = apu_job_free +}; + +int apu_drm_job_init(struct apu_core *core) +{ + int ret; + struct apu_sched *apu_sched; + struct drm_gpu_scheduler *sched; + + apu_sched = devm_kzalloc(core->dev, sizeof(*apu_sched), GFP_KERNEL); + if (!apu_sched) + return -ENOMEM; + + sched = &apu_sched->apu_queue.sched; + apu_sched->apu_queue.fence_context = dma_fence_context_alloc(1); + ret = drm_sched_init(sched, &apu_sched_ops, + 1, 0, msecs_to_jiffies(500), + NULL, NULL, "apu_js"); + if (ret) { + dev_err(core->dev, "Failed to create scheduler: %d.", ret); + return ret; + } + + ret = drm_sched_entity_init(&apu_sched->sched_entity, + DRM_SCHED_PRIORITY_NORMAL, + &sched, 1, NULL); + + core->sched = apu_sched; + core->flags = APU_ONLINE; + + return ret; +} + +static struct apu_core *get_apu_core(struct apu_drm *apu_drm, int device_id) +{ + struct apu_core *apu_core; + + list_for_each_entry(apu_core, &apu_drm->apu_cores, node) { + if (apu_core->device_id == device_id) + return apu_core; + } + + return NULL; +} + +static int apu_core_is_running(struct apu_core *core) +{ + return core->ops && core->priv && core->sched; +} + +static int +apu_lookup_bos(struct drm_device *dev, + struct drm_file *file_priv, + struct drm_apu_gem_queue *args, struct apu_job *job) +{ + void __user *bo_handles; + unsigned int i; + int ret; + + job->bo_count = args->bo_handle_count; + + if (!job->bo_count) + return 0; + + job->implicit_fences = kvmalloc_array(job->bo_count, + sizeof(struct dma_fence *), + GFP_KERNEL | __GFP_ZERO); + if (!job->implicit_fences) + return -ENOMEM; + + bo_handles = (void __user *)(uintptr_t) args->bo_handles; + ret = drm_gem_objects_lookup(file_priv, bo_handles, + job->bo_count, &job->bos); + if (ret) + return ret; + + for (i = 0; i < job->bo_count; i++) { + ret = apu_bo_iommu_map(job->apu_drm, job->bos[i]); + if (ret) { + /* TODO: handle error */ + break; + } + } + + return ret; +} + +int ioctl_gem_queue(struct drm_device *dev, void *data, + struct drm_file *file_priv) +{ + struct apu_drm *apu_drm = dev->dev_private; + struct drm_apu_gem_queue *args = data; + struct apu_event *event; + struct apu_core *core; + struct drm_syncobj *sync_out = NULL; + struct apu_job *job; + int ret = 0; + + core = get_apu_core(apu_drm, args->device); + if (!apu_core_is_running(core)) + return -ENODEV; + + if (args->out_sync > 0) { + sync_out = drm_syncobj_find(file_priv, args->out_sync); + if (!sync_out) + return -ENODEV; + } + + job = kzalloc(sizeof(*job), GFP_KERNEL); + if (!job) { + ret = -ENOMEM; + goto fail_out_sync; + } + + kref_init(&job->refcount); + + job->apu_drm = apu_drm; + job->apu_core = core; + job->cmd = args->cmd; + job->size_in = args->size_in; + job->size_out = args->size_out; + job->sync_out = sync_out; + if (job->size_in) { + job->data_in = kmalloc(job->size_in, GFP_KERNEL); + if (!job->data_in) { + ret = -ENOMEM; + goto fail_job; + } + + ret = + copy_from_user(job->data_in, + (void __user *)(uintptr_t) args->data, + job->size_in); + if (ret) + goto fail_job; + } + + if (job->size_out) { + job->data_out = kmalloc(job->size_out, GFP_KERNEL); + if (!job->data_out) { + ret = -ENOMEM; + goto fail_job; + } + } + + ret = apu_lookup_bos(dev, file_priv, args, job); + if (ret) + goto fail_job; + + event = kzalloc(sizeof(*event), GFP_KERNEL); + event->base.length = sizeof(struct apu_job_event); + event->base.type = APU_JOB_COMPLETED; + event->job_event.out_sync = args->out_sync; + job->event = event; + ret = drm_event_reserve_init(dev, file_priv, &job->event->pending_event, + &job->event->base); + if (ret) + goto fail_job; + + ret = apu_job_push(job); + if (ret) { + drm_event_cancel_free(dev, &job->event->pending_event); + goto fail_job; + } + + /* Update the return sync object for the job */ + if (sync_out) + drm_syncobj_replace_fence(sync_out, job->render_done_fence); + +fail_job: + apu_job_put(job); +fail_out_sync: + if (sync_out) + drm_syncobj_put(sync_out); + + return ret; +} + +int ioctl_gem_dequeue(struct drm_device *dev, void *data, + struct drm_file *file_priv) +{ + struct drm_apu_gem_dequeue *args = data; + struct drm_syncobj *sync_out = NULL; + struct apu_job *job; + int ret = 0; + + if (args->out_sync > 0) { + sync_out = drm_syncobj_find(file_priv, args->out_sync); + if (!sync_out) + return -ENODEV; + } + + list_for_each_entry(job, &complete_node, node) { + if (job->sync_out == sync_out) { + if (job->data_out) { + ret = copy_to_user((void __user *)(uintptr_t) + args->data, job->data_out, + job->size_out); + args->size = job->size_out; + } + args->result = job->result; + list_del(&job->node); + apu_job_put(job); + drm_syncobj_put(sync_out); + + return ret; + } + } + + if (sync_out) + drm_syncobj_put(sync_out); + + return 0; +} + +int ioctl_apu_state(struct drm_device *dev, void *data, + struct drm_file *file_priv) +{ + struct apu_drm *apu_drm = dev->dev_private; + struct drm_apu_state *args = data; + struct apu_core *core; + + args->flags = 0; + + core = get_apu_core(apu_drm, args->device); + if (!core) + return -ENODEV; + args->flags |= core->flags; + + /* Reset APU flags */ + core->flags &= ~(APU_TIMEDOUT | APU_CRASHED); + + return 0; +} diff --git a/include/drm/apu_drm.h b/include/drm/apu_drm.h new file mode 100644 index 0000000000000..f044ed0427fdd --- /dev/null +++ b/include/drm/apu_drm.h @@ -0,0 +1,59 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef __APU_DRM_H__ +#define __APU_DRM_H__ + +#include +#include + +struct apu_core; +struct apu_drm; + +struct apu_drm_ops { + int (*send)(struct apu_core *apu_core, void *data, int len); + int (*callback)(struct apu_core *apu_core, void *data, int len); +}; + +#ifdef CONFIG_DRM_APU + +struct apu_core *apu_drm_register_core(struct rproc *rproc, + struct apu_drm_ops *ops, void *priv); +int apu_drm_reserve_iova(struct apu_core *apu_core, u64 start, u64 size); +int apu_drm_unregister_core(void *priv); +int apu_drm_callback(struct apu_core *apu_core, void *data, int len); +void *apu_drm_priv(struct apu_core *apu_core); + +#else /* CONFIG_DRM_APU */ + +static inline +struct apu_core *apu_drm_register_core(struct rproc *rproc, + struct apu_drm_ops *ops, void *priv) +{ + return NULL; +} + +static inline +int apu_drm_reserve_iova(struct apu_core *apu_core, u64 start, u64 size) +{ + return -ENOMEM; +} + +static inline +int apu_drm_uregister_core(void *priv) +{ + return -ENODEV; +} + +static inline +int apu_drm_callback(struct apu_core *apu_core, void *data, int len) +{ + return -ENODEV; +} + +static inline void *apu_drm_priv(struct apu_core *apu_core) +{ + return NULL; +} +#endif /* CONFIG_DRM_APU */ + + +#endif /* __APU_DRM_H__ */ diff --git a/include/uapi/drm/apu_drm.h b/include/uapi/drm/apu_drm.h new file mode 100644 index 0000000000000..c52e187bb0599 --- /dev/null +++ b/include/uapi/drm/apu_drm.h @@ -0,0 +1,106 @@ +/* SPDX-License-Identifier: GPL-2.0 */ + +#ifndef __UAPI_APU_DRM_H__ +#define __UAPI_APU_DRM_H__ + +#include "drm.h" + +#if defined(__cplusplus) +extern "C" { +#endif + +#define APU_JOB_COMPLETED 0x80000000 + +/* + * Please note that modifications to all structs defined here are + * subject to backwards-compatibility constraints. + */ + +/* + * Firmware request, must be aligned with the one defined in firmware. + * @id: Request id, used in the case of reply, to find the pending request + * @cmd: The command id to execute in the firmware + * @result: The result of the command executed on the firmware + * @size: The size of the data available in this request + * @count: The number of shared buffer + * @data: Contains the data attached with the request if size is greater than + * zero, and the addresses of shared buffers if count is greater than + * zero. Both the data and the shared buffer could be read and write + * by the APU. + */ +struct apu_dev_request { + u16 id; + u16 cmd; + u16 result; + u16 size_in; + u16 size_out; + u16 count; + u8 data[0]; +} __packed; + +struct drm_apu_gem_new { + __u32 size; /* in */ + __u32 flags; /* in */ + __u32 handle; /* out */ + __u64 offset; /* out */ +}; + +struct drm_apu_gem_queue { + __u32 device; + __u32 cmd; + __u32 out_sync; + __u64 bo_handles; + __u32 bo_handle_count; + __u16 size_in; + __u16 size_out; + __u64 data; +}; + +struct drm_apu_gem_dequeue { + __u32 out_sync; + __u16 result; + __u16 size; + __u64 data; +}; + +struct drm_apu_gem_iommu_map { + __u64 bo_handles; + __u32 bo_handle_count; + __u64 bo_device_addresses; +}; + +struct apu_job_event { + struct drm_event base; + __u32 out_sync; +}; + +#define APU_ONLINE BIT(0) +#define APU_CRASHED BIT(1) +#define APU_TIMEDOUT BIT(2) + +struct drm_apu_state { + __u32 device; + __u32 flags; +}; + +#define DRM_APU_GEM_NEW 0x00 +#define DRM_APU_GEM_QUEUE 0x01 +#define DRM_APU_GEM_DEQUEUE 0x02 +#define DRM_APU_GEM_IOMMU_MAP 0x03 +#define DRM_APU_GEM_IOMMU_UNMAP 0x04 +#define DRM_APU_STATE 0x05 +#define DRM_APU_NUM_IOCTLS 0x06 + +#define DRM_IOCTL_APU_GEM_NEW DRM_IOWR(DRM_COMMAND_BASE + DRM_APU_GEM_NEW, struct drm_apu_gem_new) +#define DRM_IOCTL_APU_GEM_USER_NEW DRM_IOWR(DRM_COMMAND_BASE + DRM_APU_GEM_USER_NEW, struct drm_apu_gem_user_new) +#define DRM_IOCTL_APU_GEM_QUEUE DRM_IOWR(DRM_COMMAND_BASE + DRM_APU_GEM_QUEUE, struct drm_apu_gem_queue) +#define DRM_IOCTL_APU_GEM_DEQUEUE DRM_IOWR(DRM_COMMAND_BASE + DRM_APU_GEM_DEQUEUE, struct drm_apu_gem_dequeue) +#define DRM_IOCTL_APU_GEM_IOMMU_MAP DRM_IOWR(DRM_COMMAND_BASE + DRM_APU_GEM_IOMMU_MAP, struct drm_apu_gem_iommu_map) +#define DRM_IOCTL_APU_GEM_IOMMU_UNMAP DRM_IOWR(DRM_COMMAND_BASE + DRM_APU_GEM_IOMMU_UNMAP, struct drm_apu_gem_iommu_map) +#define DRM_IOCTL_APU_STATE DRM_IOWR(DRM_COMMAND_BASE + DRM_APU_STATE, struct drm_apu_state) + +#if defined(__cplusplus) +} +#endif + +#endif /* __UAPI_APU_DRM_H__ */ From patchwork Fri Sep 17 12:59:44 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alexandre Bailon X-Patchwork-Id: 12502017 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-17.1 required=3.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER, INCLUDES_PATCH,MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED, USER_AGENT_GIT autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 59CAEC433F5 for ; Fri, 17 Sep 2021 12:58:44 +0000 (UTC) Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 2E5EB610C7 for ; Fri, 17 Sep 2021 12:58:44 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.4.1 mail.kernel.org 2E5EB610C7 Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=baylibre.com Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=lists.infradead.org DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender: Content-Transfer-Encoding:Content-Type:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To: Message-Id:Date:Subject:Cc:To:From:Reply-To:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Owner; bh=xwoxPERdKBvB8JgU5S5ihjQ8PuJfjA97yxba3iRcs/M=; b=u/mn2qC5GJ54/s mGJ98pKExUhmL0gj4LJXgg1s3YQtpbTBT9j9IXq7cCSt5RahQmAs8zvqB1dbfhRGzXYilHqjF/5uZ v2QU71cH64xlaD8DBat968qsc5OPFezZ259mD2L2uy4kAXnpdPxxOm5BqPNDcqDdX4Pw0NBRA968B I3m7x/GjpCR6KISZuzxa8T4q9Y5GALWYG9N9329NKAdfsd5imvs4fR89C6BE53CQyKVCoO5j2b4C8 6ocvCMmZuNRlSWr5aKTBD0YXS3HSBGX3xuBYT2TbgNoZIPsQJQYmcNdkx62nn++Vcq81AziuLY5Cs 3rLZcytXhfKV4kG7BifQ==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.94.2 #2 (Red Hat Linux)) id 1mRDRk-00EDHD-4m; Fri, 17 Sep 2021 12:58:28 +0000 Received: from mail-wm1-x336.google.com ([2a00:1450:4864:20::336]) by bombadil.infradead.org with esmtps (Exim 4.94.2 #2 (Red Hat Linux)) id 1mRDRI-00ED4Y-T9 for linux-mediatek@lists.infradead.org; Fri, 17 Sep 2021 12:58:03 +0000 Received: by mail-wm1-x336.google.com with SMTP id c8-20020a7bc008000000b002e6e462e95fso9920218wmb.2 for ; Fri, 17 Sep 2021 05:58:00 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=baylibre-com.20210112.gappssmtp.com; s=20210112; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=u5OvK6rAM51FXadQ9HCCAo1nDCyjKMMChivM3w7j7uc=; b=eGbAxd0RK5cxQWiBRoDzRjyFcyMn7M/eBSrwbZMorRDrBHyNh4tqr35S8hZL1zQklf RBiPTeB08MrRxL0kav7kVnBYC3mvabfvI50ICHvrgiqYvzsX/4onFFutFzvjeFkCVdQ/ bVgUFe6XzFBkePmRam+R2PSqjEnY479IeT5wuX4i7pF177s7lzDdWvdm5igsQEoKSM1f S4f7zns2RaZg65Lmn7EyKCY2aKpI4tD0Mq83PlI9Gf7ke9lJp8JalDULeU/ctPjGweOR /H5SXb9HXeusY/cT0l2DURVOcyUTmg6ggcaQ4N8iw5rDeLFJm7NE699FYbhO/1WEHEEI bZww== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=u5OvK6rAM51FXadQ9HCCAo1nDCyjKMMChivM3w7j7uc=; b=gJfNwgyBGUxA/Dx0AxhfRo7v5jOwPLFVVH6gaOdZ4RjL20wqtnwumEbzYZwrm9qTJU EuOR4xeMj4BjxEzx5y6ZMMLmRF5D4BtTRw0+jlS1q+eckYtj6v+yGVy1gJjI3AL821bg ucQMEIYdIu2IHXgfACFQpVKhzRWyzvH7gJvXIjf0eNmzXK+XTg4kqDJR1cJFLJaTQ940 5/xZN25W9hWJgbwWaUydn0elSTsStwDa9OM1mCRER4lDCu7xXSNh5XHwT7PDhHsYkn+X 5DxewdrNMstfkoVZRYvyESMe7963kWWqUHBIQ1A04A4IE6buLO+JVrdUm/379UYhRiIh LZrQ== X-Gm-Message-State: AOAM532O7w2lZ9nMhmaDo+jQchLa44mqBxee1+RdJICfnOSp21tbFHEk YgeVaPKK6V87hSoh3uhPEg8E7w== X-Google-Smtp-Source: ABdhPJwiH/6gX7ZX2P33uYpMlaxknnvLf6Knho3tfcfF2fd3161qyj87sKWlfvIfg6IfLTt4G9AEdg== X-Received: by 2002:a05:600c:3392:: with SMTP id o18mr14906465wmp.92.1631883479342; Fri, 17 Sep 2021 05:57:59 -0700 (PDT) Received: from localhost.baylibre.local (laubervilliers-658-1-213-31.w90-63.abo.wanadoo.fr. [90.63.244.31]) by smtp.gmail.com with ESMTPSA id f3sm6358636wmj.28.2021.09.17.05.57.57 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 17 Sep 2021 05:57:58 -0700 (PDT) From: Alexandre Bailon To: airlied@linux.ie, daniel@ffwll.ch, robh+dt@kernel.org, matthias.bgg@gmail.com, maarten.lankhorst@linux.intel.com, mripard@kernel.org, tzimmermann@suse.de, ohad@wizery.com, bjorn.andersson@linaro.org, mathieu.poirier@linaro.org, sumit.semwal@linaro.org Cc: christian.koenig@amd.com, dri-devel@lists.freedesktop.org, devicetree@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-mediatek@lists.infradead.org, linux-kernel@vger.kernel.org, linux-remoteproc@vger.kernel.org, linux-media@vger.kernel.org, linaro-mm-sig@lists.linaro.org, khilman@baylibre.com, gpain@baylibre.com, Alexandre Bailon Subject: [RFC PATCH 3/4] rpmsg: Add support of AI Processor Unit (APU) Date: Fri, 17 Sep 2021 14:59:44 +0200 Message-Id: <20210917125945.620097-4-abailon@baylibre.com> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20210917125945.620097-1-abailon@baylibre.com> References: <20210917125945.620097-1-abailon@baylibre.com> MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20210917_055800_973237_AEBD32C3 X-CRM114-Status: GOOD ( 22.76 ) X-BeenThere: linux-mediatek@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "Linux-mediatek" Errors-To: linux-mediatek-bounces+linux-mediatek=archiver.kernel.org@lists.infradead.org Some Mediatek SoC provides hardware accelerator for AI / ML. This driver use the DRM driver to manage the shared memory, and use rpmsg to execute jobs on the APU. Signed-off-by: Alexandre Bailon --- drivers/rpmsg/Kconfig | 10 +++ drivers/rpmsg/Makefile | 1 + drivers/rpmsg/apu_rpmsg.c | 184 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 195 insertions(+) create mode 100644 drivers/rpmsg/apu_rpmsg.c diff --git a/drivers/rpmsg/Kconfig b/drivers/rpmsg/Kconfig index 0b4407abdf138..fc1668f795004 100644 --- a/drivers/rpmsg/Kconfig +++ b/drivers/rpmsg/Kconfig @@ -73,4 +73,14 @@ config RPMSG_VIRTIO select RPMSG_NS select VIRTIO +config RPMSG_APU + tristate "APU RPMSG driver" + select REMOTEPROC + select RPMSG_VIRTIO + select DRM_APU + help + This provides a RPMSG driver that provides some facilities to + communicate with an accelerated processing unit (APU). + This Uses the APU DRM driver to manage memory and job scheduling. + endmenu diff --git a/drivers/rpmsg/Makefile b/drivers/rpmsg/Makefile index 8d452656f0ee3..8b336b9a817c1 100644 --- a/drivers/rpmsg/Makefile +++ b/drivers/rpmsg/Makefile @@ -9,3 +9,4 @@ obj-$(CONFIG_RPMSG_QCOM_GLINK_RPM) += qcom_glink_rpm.o obj-$(CONFIG_RPMSG_QCOM_GLINK_SMEM) += qcom_glink_smem.o obj-$(CONFIG_RPMSG_QCOM_SMD) += qcom_smd.o obj-$(CONFIG_RPMSG_VIRTIO) += virtio_rpmsg_bus.o +obj-$(CONFIG_RPMSG_APU) += apu_rpmsg.o diff --git a/drivers/rpmsg/apu_rpmsg.c b/drivers/rpmsg/apu_rpmsg.c new file mode 100644 index 0000000000000..7e504bd176a4d --- /dev/null +++ b/drivers/rpmsg/apu_rpmsg.c @@ -0,0 +1,184 @@ +// SPDX-License-Identifier: GPL-2.0 +// +// Copyright 2020 BayLibre SAS + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "rpmsg_internal.h" + +#define APU_RPMSG_SERVICE_MT8183 "rpmsg-mt8183-apu0" + +struct rpmsg_apu { + struct apu_core *core; + struct rpmsg_device *rpdev; +}; + +static int apu_rpmsg_callback(struct rpmsg_device *rpdev, void *data, int count, + void *priv, u32 addr) +{ + struct rpmsg_apu *apu = dev_get_drvdata(&rpdev->dev); + struct apu_core *apu_core = apu->core; + + return apu_drm_callback(apu_core, data, count); +} + +static int apu_rpmsg_send(struct apu_core *apu_core, void *data, int len) +{ + struct rpmsg_apu *apu = apu_drm_priv(apu_core); + struct rpmsg_device *rpdev = apu->rpdev; + + return rpmsg_send(rpdev->ept, data, len); +} + +static struct apu_drm_ops apu_rpmsg_ops = { + .send = apu_rpmsg_send, +}; + +static int apu_init_iovad(struct rproc *rproc, struct rpmsg_apu *apu) +{ + struct resource_table *table; + struct fw_rsc_carveout *rsc; + int i; + + if (!rproc->table_ptr) { + dev_err(&apu->rpdev->dev, + "No resource_table: has the firmware been loaded ?\n"); + return -ENODEV; + } + + table = rproc->table_ptr; + for (i = 0; i < table->num; i++) { + int offset = table->offset[i]; + struct fw_rsc_hdr *hdr = (void *)table + offset; + + if (hdr->type != RSC_CARVEOUT) + continue; + + rsc = (void *)hdr + sizeof(*hdr); + if (apu_drm_reserve_iova(apu->core, rsc->da, rsc->len)) { + dev_err(&apu->rpdev->dev, + "failed to reserve iova\n"); + return -ENOMEM; + } + } + + return 0; +} + +static struct rproc *apu_get_rproc(struct rpmsg_device *rpdev) +{ + /* + * To work, the APU RPMsg driver need to get the rproc device. + * Currently, we only use virtio so we could use that to find the + * remoteproc parent. + */ + if (!rpdev->dev.parent && rpdev->dev.parent->bus) { + dev_err(&rpdev->dev, "invalid rpmsg device\n"); + return ERR_PTR(-EINVAL); + } + + if (strcmp(rpdev->dev.parent->bus->name, "virtio")) { + dev_err(&rpdev->dev, "unsupported bus\n"); + return ERR_PTR(-EINVAL); + } + + return vdev_to_rproc(dev_to_virtio(rpdev->dev.parent)); +} + +static int apu_rpmsg_probe(struct rpmsg_device *rpdev) +{ + struct rpmsg_apu *apu; + struct rproc *rproc; + int ret; + + apu = devm_kzalloc(&rpdev->dev, sizeof(*apu), GFP_KERNEL); + if (!apu) + return -ENOMEM; + apu->rpdev = rpdev; + + rproc = apu_get_rproc(rpdev); + if (IS_ERR_OR_NULL(rproc)) + return PTR_ERR(rproc); + + /* Make device dma capable by inheriting from parent's capabilities */ + set_dma_ops(&rpdev->dev, get_dma_ops(rproc->dev.parent)); + + ret = dma_coerce_mask_and_coherent(&rpdev->dev, + dma_get_mask(rproc->dev.parent)); + if (ret) + goto err_put_device; + + rpdev->dev.iommu_group = rproc->dev.parent->iommu_group; + + apu->core = apu_drm_register_core(rproc, &apu_rpmsg_ops, apu); + if (!apu->core) { + ret = -ENODEV; + goto err_put_device; + } + + ret = apu_init_iovad(rproc, apu); + + dev_set_drvdata(&rpdev->dev, apu); + + return ret; + +err_put_device: + devm_kfree(&rpdev->dev, apu); + + return ret; +} + +static void apu_rpmsg_remove(struct rpmsg_device *rpdev) +{ + struct rpmsg_apu *apu = dev_get_drvdata(&rpdev->dev); + + apu_drm_unregister_core(apu); + devm_kfree(&rpdev->dev, apu); +} + +static const struct rpmsg_device_id apu_rpmsg_match[] = { + { APU_RPMSG_SERVICE_MT8183 }, + {} +}; + +static struct rpmsg_driver apu_rpmsg_driver = { + .probe = apu_rpmsg_probe, + .remove = apu_rpmsg_remove, + .callback = apu_rpmsg_callback, + .id_table = apu_rpmsg_match, + .drv = { + .name = "apu_rpmsg", + }, +}; + +static int __init apu_rpmsg_init(void) +{ + return register_rpmsg_driver(&apu_rpmsg_driver); +} +arch_initcall(apu_rpmsg_init); + +static void __exit apu_rpmsg_exit(void) +{ + unregister_rpmsg_driver(&apu_rpmsg_driver); +} +module_exit(apu_rpmsg_exit); + +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("APU RPMSG driver"); From patchwork Fri Sep 17 12:59:45 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alexandre Bailon X-Patchwork-Id: 12502041 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-17.1 required=3.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER, INCLUDES_PATCH,MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED, USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 42F96C433F5 for ; Fri, 17 Sep 2021 12:59:04 +0000 (UTC) Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 09AEA61130 for ; Fri, 17 Sep 2021 12:59:04 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.4.1 mail.kernel.org 09AEA61130 Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=baylibre.com Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=lists.infradead.org DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender: Content-Transfer-Encoding:Content-Type:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To: Message-Id:Date:Subject:Cc:To:From:Reply-To:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Owner; bh=8PJZZ+TAnPh5pjPf+tIRVcjWEuNXG855t5493Y1r8Fk=; b=oeq4tG4OHWCd1h yKeK+zzCMK7ydV1/urxXOJCSNK8x15YvFTf2JJ40/BTx9BTM239m+QufwnipJG7n22eJYYbAmRptZ GgSuUrWOJ8Pfov4zFWoGNk0dqszkUYspN1I0lL8A2cL9aiQ7Ssf79CU2f5NRLPOENLLjw3n+z7fIa czgx/n/AgX1xohQ/KTVMCLhssBG5sCIEIXNrAj3X3ZKVAcXculnw73OgzEWfKo7xWniOHuTfz3+NJ yJj9XbewF5+iwOWgFLIGfCHIQXipM5U12SqPpu/PhWGdtNVK0xo99jyVb1wDZrZLSLH3p8SHqA2eW kmsdM3XTA4Yoi6LrQ/2w==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.94.2 #2 (Red Hat Linux)) id 1mRDS8-00EDSw-SN; Fri, 17 Sep 2021 12:58:52 +0000 Received: from mail-wm1-x32d.google.com ([2a00:1450:4864:20::32d]) by bombadil.infradead.org with esmtps (Exim 4.94.2 #2 (Red Hat Linux)) id 1mRDRK-00ED5K-3U for linux-mediatek@lists.infradead.org; Fri, 17 Sep 2021 12:58:05 +0000 Received: by mail-wm1-x32d.google.com with SMTP id b21-20020a1c8015000000b003049690d882so9886984wmd.5 for ; Fri, 17 Sep 2021 05:58:01 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=baylibre-com.20210112.gappssmtp.com; s=20210112; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=plrOrvIZM2TLyxiMQcIWBN+4lREuMv3pRG/Sh7a1xC8=; b=A1XyPdxcOquLxN0aX50A1ZFpsIYqi3fOAj7lTpkAapmpB6s0I7t5BtLQBntoT5o/gC LTk3U5iGqZXV00d7UWu1zJeHwNQUIaZQXm49I9GxJIR/4y18GU6Nvyoikkh2w2l4zgcp B3UYoAnqDqm9GVkUY9hqfwcQPouBjXs+iZX47NO/QJ/t4wb1kggMVtkvmAtzd4qzJFRW 7nWbDttoNJXmYKodYdihre5foSUAr0yPacNcyWtLspR5zCXh9y8npouXY1dRxKM6UQcn WZ3a9DrYMmZAVwaW7QgPnDaW9jP4k2Ex3PG5EKtnNHZgrO8bzEd2qcrTOZ99BSIM62Lu 8eYQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=plrOrvIZM2TLyxiMQcIWBN+4lREuMv3pRG/Sh7a1xC8=; b=8EqqSJ48id2cLFCZ4sKTPoJSyyVuOxN4PA9flqYiqns2VrYHULZUWr+3I+fDqhgwYP gS+xUaGFyRksVqH63nU/zmwDpbdkN3Ny4yWu+5ylrjbBYfoE1Qjw4wqoiDuChjI1nHj+ 7HYX6F6U0kMQy5tteN+a15i43q8NChMDs+G88PhfXNA8LDb7t8Cv5O0NS6EMm2ZuxhjL V1qy1JCDZ1YN8E+ehDKKacABnHMeQrIJXFs+eGawXe5YveIHkPkIC1kyJo0tsXBvx2ZJ wdTmG9VsptoXuvgHAcFSQVHufQv5LidzpQ5mz2HD0Y8azp8pk9Rpx+4mlz/OrqWigg5d XNSA== X-Gm-Message-State: AOAM532m3c/KMqesOWY7ggvddfjThXIISWg2/4PsfCUItIQviCnzD1za uDxEbZxlqc8j80TSCOfuUF/j8A== X-Google-Smtp-Source: ABdhPJxTbG15Mr23ALcQTVgBRPbbO7jTynJgRBVrKM9JKm3YI/iNB4vjrE9aSV9fhOwwMUSmYbl5Hw== X-Received: by 2002:a7b:c086:: with SMTP id r6mr10257667wmh.46.1631883480653; Fri, 17 Sep 2021 05:58:00 -0700 (PDT) Received: from localhost.baylibre.local (laubervilliers-658-1-213-31.w90-63.abo.wanadoo.fr. [90.63.244.31]) by smtp.gmail.com with ESMTPSA id f3sm6358636wmj.28.2021.09.17.05.57.59 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 17 Sep 2021 05:58:00 -0700 (PDT) From: Alexandre Bailon To: airlied@linux.ie, daniel@ffwll.ch, robh+dt@kernel.org, matthias.bgg@gmail.com, maarten.lankhorst@linux.intel.com, mripard@kernel.org, tzimmermann@suse.de, ohad@wizery.com, bjorn.andersson@linaro.org, mathieu.poirier@linaro.org, sumit.semwal@linaro.org Cc: christian.koenig@amd.com, dri-devel@lists.freedesktop.org, devicetree@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-mediatek@lists.infradead.org, linux-kernel@vger.kernel.org, linux-remoteproc@vger.kernel.org, linux-media@vger.kernel.org, linaro-mm-sig@lists.linaro.org, khilman@baylibre.com, gpain@baylibre.com, Alexandre Bailon Subject: [RFC PATCH 4/4] ARM64: mt8183-pumpkin: Add the APU DRM device Date: Fri, 17 Sep 2021 14:59:45 +0200 Message-Id: <20210917125945.620097-5-abailon@baylibre.com> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20210917125945.620097-1-abailon@baylibre.com> References: <20210917125945.620097-1-abailon@baylibre.com> MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20210917_055802_202141_713F3165 X-CRM114-Status: UNSURE ( 8.20 ) X-CRM114-Notice: Please train this message. X-BeenThere: linux-mediatek@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "Linux-mediatek" Errors-To: linux-mediatek-bounces+linux-mediatek=archiver.kernel.org@lists.infradead.org This add the APU DRM device to pumkpin. Signed-off-by: Alexandre Bailon --- arch/arm64/boot/dts/mediatek/mt8183-pumpkin.dts | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/arch/arm64/boot/dts/mediatek/mt8183-pumpkin.dts b/arch/arm64/boot/dts/mediatek/mt8183-pumpkin.dts index 7fbed2b7bc6f8..c540dbfe30151 100644 --- a/arch/arm64/boot/dts/mediatek/mt8183-pumpkin.dts +++ b/arch/arm64/boot/dts/mediatek/mt8183-pumpkin.dts @@ -98,6 +98,12 @@ ntc { pulldown-ohm = <0>; io-channels = <&auxadc 0>; }; + + apu_drm@0 { + compatible = "mediatek,apu-drm"; + remoteproc = <&apu0>, <&apu1>; + iova = <0 0x60000000 0 0x10000000>; + }; }; &auxadc {