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: 12502035 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 882E1C433EF for ; Fri, 17 Sep 2021 13:01:06 +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 52ECF611C3 for ; Fri, 17 Sep 2021 13:01:06 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.4.1 mail.kernel.org 52ECF611C3 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=FmtJISGkSbuSLUK1ohTV+dAR3jA4g+A0AAU5WxYTiNA=; b=dcwpnDNzGgwiNL xbgIhEhtczfbRhICqtG7T0lZHyaAvnQzLs+zuiAmMe/iNycRqE0rrBwW+uMpEOmd1KgQYOWtCWMAo qAbsELOvQqnNwPbtzx+aZhW4BDCt1tJiDDuYpohEh4bSEYWtsX5+H46jZbtgy296g1h99nl9mZzeH EJTZ4ryv0Kk/buC4HNv8c8P43uM2y/SHNOmnvZNsKomCPXEagOYOXoGRY68Dg6ux8Po+0479CY+JP sy+CUpHBNs+p/pMlsbTvG4xYX3PJnXFV6AK5w9LEE3QmIzm4za0sprtrnaDJNv/AdQa5mHVv5DA7B 4HQce/sTsoWRLWjKbdIg==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.94.2 #2 (Red Hat Linux)) id 1mRDRY-00EDBh-3Y; Fri, 17 Sep 2021 12:58:16 +0000 Received: from mail-wm1-x332.google.com ([2a00:1450:4864:20::332]) by bombadil.infradead.org with esmtps (Exim 4.94.2 #2 (Red Hat Linux)) id 1mRDRF-00ED2n-Ba for linux-arm-kernel@lists.infradead.org; Fri, 17 Sep 2021 12:58:01 +0000 Received: by mail-wm1-x332.google.com with SMTP id c190-20020a1c9ac7000000b0030b459ea869so1342901wme.4 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=OV7QdfF/lsDR3FYKUdiJVS5jPzYQHN8pGKEAsTPyS8Zm+VSTrZSNkbAIrEcJfCPCWj /5ghVpxMZ9OZUb9BUAJcQKLzfKY3nGwuyfoU7ogHSms3CdUy4aJwJw2/sMrztvvEXu2W 3MTg5P759SLqNVpTtAdFepAswzldAItZMo/GWAfyCInO3pSTTTIFH1xyegUV1qJJT13S hq5MsEo+avyNQi07P3qOXUMT80jAS90nvUOFzzMMt+2zC7TGCopW8dp+jUsA11NGNevA m1JQB6Fmd6vf2LIiVMS8nF95F1+B/lRdA21SahW1gSvXP85OWq00NcRsfrMsBoEOoS8L E1uw== X-Gm-Message-State: AOAM532HRe91rgjJ9B0Ca24qJRJe3XkqfcVJnn7bUTrEaRzz8s9vVATg DOnDfaDUiEijwY8Uwds+b0ioEA== 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_423389_A3E9250A X-CRM114-Status: GOOD ( 13.48 ) X-BeenThere: linux-arm-kernel@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-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=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: 12502031 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 76D0FC433F5 for ; Fri, 17 Sep 2021 13:00:37 +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 41CD661130 for ; Fri, 17 Sep 2021 13:00:37 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.4.1 mail.kernel.org 41CD661130 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=e13HKaBnfQlIcREppyOYX3D9moLBaZNZ9H5FQ0RZ3FI=; b=QwPUMrxW+LuV9d Vp5Lcrbb9mc/WYoe2dcGC4UTwI6wSN1EFyO6d2yTVktnjl+oTxQ0G+QPPZuH5B3tt2Bjdgjo/KsHz SQG+2cEKdTvd3o0DmGGXYbbCcIWWuk8YKolvwbyW2VYzpKH0gj2R+ughFHFF8iHiNrdGvUZKBgTN2 pZCkb9GWtgwIUgJP92SFnYcukMGX0qL3m2tS+S3ye2lvoCXf+cRsPQUZyfMStqtpTHgTbdK336sJG ZOSLmRwytIZMD/C0TTKPAGhDkSNhfGTkXwkbhEE4szPiEarQwDid+rgCDLzplKNMyUeqxwBOEMwx5 GeY3Jd2yVRY3f8qb+KkQ==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.94.2 #2 (Red Hat Linux)) id 1mRDSC-00EDTg-9J; Fri, 17 Sep 2021 12:58:56 +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 1mRDRH-00ED3m-85 for linux-arm-kernel@lists.infradead.org; Fri, 17 Sep 2021 12:58:05 +0000 Received: by mail-wm1-x330.google.com with SMTP id 70so4334405wme.5 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=TatjA/ZIizBpz46SoUzyQhAncHqZUX1sBEX7aY2qgCiy+IaACLhuIlpIGsp76KYFGQ /Wph03pTEaeFypWmQ5da143A+etTNzmBYu6VNOUKtVmxv6SfmyrBDkeC1c5m5o7J9ZzO G10R+LXBHzPobhmd5dtoNVoFLz4x5SLJc36g0kxWei9f2Xa0haE8oxBlN/Csf4v0n0l0 2hwbjuWHdf4N+mrziwtUBythJHDkX4CyyWUHcALgIpDgD0FK2d+QQl/0uBAUZopOc2Xg /E7PumyDthtprYc1JUukfs0Vmy7h2NMwrR9llCXsNatTfO+6wJ5Zw/hpc6EjQbn0NWF/ JHyg== X-Gm-Message-State: AOAM533lP3CX0LsihnWTMeYdHQ2hitojbnMdLtATt4CIpRqhKKkd8TTc PDDPf/jx1wc0mUOOxVHjx3+FlQ== 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_644453_96FE852F X-CRM114-Status: GOOD ( 28.25 ) X-BeenThere: linux-arm-kernel@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-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=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: 12502029 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 4E417C433EF for ; Fri, 17 Sep 2021 13:00:17 +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 1C37D610C7 for ; Fri, 17 Sep 2021 13:00:17 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.4.1 mail.kernel.org 1C37D610C7 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=8a28Ndq3ph2m1I3UnKHkv/7/dk4dQufj+Jdw5G3NgE8=; b=fB7w06ZIzoEW5/ O27dK+651fs743oOm53WBuxpeovKHW6OmB2DT0SZ8ULf2HOeznWoMLlNdvtSSAQJeXyo1a30VQeOC rSJ73LA2pVHR8017A8qR0/joqTM9bkkU+vTLfecRmfgMe8a5hssxSpGRBslBpNjdKGw7bU1cO02fS 9nEa25ssKs6K7Gfywr7nW6NNUd8OfXfEfQ2JR9+T7LZwZCnpopfhLSzVKt1DHzywhlDzDQ/+67JgK Jd/rKZ43J9G3UCngS9oJXLGF9NSL1lAcjE1FG/4tYKBz35j77l8iyBfNNfrvnai1PflCd0eZ0JjMp i6wPlLBubD4Yh8LKK2xA==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.94.2 #2 (Red Hat Linux)) id 1mRDRx-00EDLv-4o; Fri, 17 Sep 2021 12:58:41 +0000 Received: from mail-wm1-x32e.google.com ([2a00:1450:4864:20::32e]) by bombadil.infradead.org with esmtps (Exim 4.94.2 #2 (Red Hat Linux)) id 1mRDRI-00ED4X-Rs for linux-arm-kernel@lists.infradead.org; Fri, 17 Sep 2021 12:58:03 +0000 Received: by mail-wm1-x32e.google.com with SMTP id z184-20020a1c7ec1000000b003065f0bc631so9930149wmc.0 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=giA1Kz8kwkEvoqA9KNpIf3eXrmd/7wgxeAu0w2hgoLN2ThXDpkqmCnKMSPEbelUgZy MjrPDXp4BICh7/2fMajl0eof/L2BgxjuCdZmrTMTq4DHlIt44O4BrE/f+/ejVNVUykdY OUHHYGVl7sakfUnrSi5hcFBkSh3qLlR7Eyvig4XXdT6bSpmy1qIVt0Kt+bR5nyDtLhO+ 6ogs8sMdVXSBk4OWqFwnTJrXa+i5tOoweLf3rGPiF85klMSAg3Qlph4+oqCPhjkZ7Hzh SRBKX9pNGodx1bvNhvm/Q6HJ+J0dzYb5dyv0HAhd+5OTsz4/CW3eRO3fUpmarZwtTTO6 lvMQ== X-Gm-Message-State: AOAM530SwVJEk1m3tRY57fwOI//vI/CUEq+8Zh6aKkczVTJjtZmQ2q7J plWgO+THFZIrsVgBBAVFmAJQ+Q== 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_953450_36284E8A X-CRM114-Status: GOOD ( 23.86 ) X-BeenThere: linux-arm-kernel@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-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=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: 12502037 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 B6322C433FE for ; Fri, 17 Sep 2021 13:01:17 +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 86BFB61130 for ; Fri, 17 Sep 2021 13:01:17 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.4.1 mail.kernel.org 86BFB61130 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=EJG5b1EYdrdIg6Kr8c2joIlzBRBqhc3kxOmoPWGyXFE=; b=nj5+eOXvWDpqMi M1GDs04r0Fi1mzofxKruRROJnI3BuLLqnrt7fJOBzd02LOwNrZqOtTwgqz4Lha8aKZPW73zonWLJa ieaZ/C26qBe9FUGFg1WNJ+H7n6ePDTLc6vHtx1b1GU6lWuZRO+HaYKpUwMmqf8mpSD4UTpF+Cd+Y/ Uy6vipbzFSC6WB7SPowrPsaKS+qksvSr98/DNFjA90zYYQu3cAYXTFBdOkqt5zGflFCR/pjPp+f4z +PyCyazhKVMa95V0u1oQrK0AujMQdRobTnUNykEkzURlyQgfKwe7jSNtv9i/zzZeZK0hlXi+ZkG67 mWKPmxITVJ/bSjsOq4ng==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.94.2 #2 (Red Hat Linux)) id 1mRDRm-00EDHg-AC; Fri, 17 Sep 2021 12:58:30 +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 1mRDRJ-00ED5J-QF for linux-arm-kernel@lists.infradead.org; Fri, 17 Sep 2021 12:58:03 +0000 Received: by mail-wm1-x336.google.com with SMTP id d207-20020a1c1dd8000000b00307e2d1ec1aso6811259wmd.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=I4pe0q91LMFI33VKWgTfRZRbhgKfYPzdd+6Ut/b9sb1u/Zi2Oq/RcbJPWWhfb8GrRX xdpqP3suzNYuDJiH2qe3GSFi17uK2B9szA9VGRnVV8L/jm8ryCN/Ye1kyXNwpfE4gZh3 3dvmYFgW4JR8mxojgLnwGpTa0GS+tW0N+WMa9cjo935O7WqhMDMDnZDOvKYg3vLRdDZK iWd1vjyc2aj9QUDXH11DhHgxvDhkRshaqgUST7Xmo+kq3fc+BtYyFgBS/PQVTdneBSLF /WXYbM6YePfHTeygJAd7dLybPJtN4Idd9c7pX//xxlsRcPcgMBohVxGsyHVPsc7wmF76 3nqw== X-Gm-Message-State: AOAM530l8AUqwNlZb8D2WFZE4AVjTswQRC/bAMWq6IMJV8Z1KclVy7bA XeIidvcEQYqVq3vVdV9ZG9yB7A== 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_055801_945859_8D06D9A7 X-CRM114-Status: UNSURE ( 9.31 ) X-CRM114-Notice: Please train this message. X-BeenThere: linux-arm-kernel@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-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=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 {