From nobody Sat May 9 05:34:50 2026 Received: from foss.arm.com (foss.arm.com [217.140.110.172]) by smtp.subspace.kernel.org (Postfix) with ESMTP id 9351C47ECF9; Tue, 5 May 2026 14:05:31 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=217.140.110.172 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1777989933; cv=none; b=U6pCs6v1AbDuOCrn3lQ0fH5OYlJxJ1cZszv6PxjCHTC5/5shVuTR8H50FnhIjE2z7Ws/ObgGTOg88NCtrI29SLzlnwyEQjMCOWsbWgVE8Pa1ln58WkIRC+VEHHreFd/WpaoDn+lKgpbFMcHOEaRRjHaPnXbuiGTLAemesxZgamA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1777989933; c=relaxed/simple; bh=KdjJokghEpzcHqn4wsyrc1a9I5jF3xtB5+lD//QPMcQ=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=qkwFVHNro2Pu8URYto9CZ052Lh8TxV2GiBnOFMZg4/xkVYhpfMGvqUlKrZIRA+YNU+o+JRmgi/cyTcomGYw4WrWDkn1nYDiasuFPX5Lj4ZbdRALNpf0aqM9kk6DOd3i1PWwBCR59Xoas5Sy7jplQwFvbF6jktwqyEaXwaNrTsPE= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=arm.com; spf=pass smtp.mailfrom=arm.com; dkim=pass (1024-bit key) header.d=arm.com header.i=@arm.com header.b=gbT5svfs; arc=none smtp.client-ip=217.140.110.172 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=arm.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=arm.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=arm.com header.i=@arm.com header.b="gbT5svfs" Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id A37843028; Tue, 5 May 2026 07:05:25 -0700 (PDT) Received: from e120398-lin.trondheim.arm.com (e120398-lin.trondheim.arm.com [10.42.46.160]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id 0ECEB3F763; Tue, 5 May 2026 07:05:25 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=arm.com; s=foss; t=1777989931; bh=KdjJokghEpzcHqn4wsyrc1a9I5jF3xtB5+lD//QPMcQ=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=gbT5svfs82uL8DSJ7EcBrAcKFt2ZUSB1ZoCcsr2K37gs1m8xIl5m9QiYUT3j+dktl 5YWsJG+sxkkYE00LR9+b4ZE4OJgCFhq+Mh74JCE0+CDE02fRXgoaEucmSA4F3tPC+v k9vg1+AfuVXFIU2H4AcBaShfPlRmMGkglThp6Who= From: Ketil Johnsen To: David Airlie , Simona Vetter , Maarten Lankhorst , Maxime Ripard , Thomas Zimmermann , Jonathan Corbet , Shuah Khan , Sumit Semwal , Benjamin Gaignard , Brian Starkey , John Stultz , "T.J. Mercier" , =?UTF-8?q?Christian=20K=C3=B6nig?= , Boris Brezillon , Steven Price , Liviu Dudau , Daniel Almeida , Alice Ryhl , Matthias Brugger , AngeloGioacchino Del Regno Cc: dri-devel@lists.freedesktop.org, linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org, linux-media@vger.kernel.org, linaro-mm-sig@lists.linaro.org, linux-arm-kernel@lists.infradead.org, linux-mediatek@lists.infradead.org, Yong Wu , Yunfei Dong , Florent Tomasin , Ketil Johnsen Subject: [PATCH 1/8] dma-heap: Add proper kref handling on dma-buf heaps Date: Tue, 5 May 2026 16:05:07 +0200 Message-ID: <20260505140516.1372388-2-ketil.johnsen@arm.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260505140516.1372388-1-ketil.johnsen@arm.com> References: <20260505140516.1372388-1-ketil.johnsen@arm.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: John Stultz Add proper reference counting on the dma_heap structure. While existing heaps are built-in, we may eventually have heaps loaded from modules, and we'll need to be able to properly handle the references to the heaps Signed-off-by: John Stultz Signed-off-by: T.J. Mercier Signed-off-by: Yong Wu [Yong: Just add comment for "minor" and "refcount"] Signed-off-by: Yunfei Dong [Yunfei: Change reviewer's comments] Signed-off-by: Florent Tomasin [Florent: Rebase] Signed-off-by: Ketil Johnsen [Ketil: Rebase] --- drivers/dma-buf/dma-heap.c | 29 +++++++++++++++++++++++++++++ include/linux/dma-heap.h | 2 ++ 2 files changed, 31 insertions(+) diff --git a/drivers/dma-buf/dma-heap.c b/drivers/dma-buf/dma-heap.c index ac5f8685a6494..9fd365ddbd517 100644 --- a/drivers/dma-buf/dma-heap.c +++ b/drivers/dma-buf/dma-heap.c @@ -12,6 +12,7 @@ #include #include #include +#include #include #include #include @@ -31,6 +32,7 @@ * @heap_devt: heap device node * @list: list head connecting to list of heaps * @heap_cdev: heap char device + * @refcount: reference counter for this heap device * * Represents a heap of memory from which buffers can be made. */ @@ -41,6 +43,7 @@ struct dma_heap { dev_t heap_devt; struct list_head list; struct cdev heap_cdev; + struct kref refcount; }; =20 static LIST_HEAD(heap_list); @@ -248,6 +251,7 @@ struct dma_heap *dma_heap_add(const struct dma_heap_exp= ort_info *exp_info) if (!heap) return ERR_PTR(-ENOMEM); =20 + kref_init(&heap->refcount); heap->name =3D exp_info->name; heap->ops =3D exp_info->ops; heap->priv =3D exp_info->priv; @@ -313,6 +317,31 @@ struct dma_heap *dma_heap_add(const struct dma_heap_ex= port_info *exp_info) } EXPORT_SYMBOL_NS_GPL(dma_heap_add, "DMA_BUF_HEAP"); =20 +static void dma_heap_release(struct kref *ref) +{ + struct dma_heap *heap =3D container_of(ref, struct dma_heap, refcount); + unsigned int minor =3D MINOR(heap->heap_devt); + + mutex_lock(&heap_list_lock); + list_del(&heap->list); + mutex_unlock(&heap_list_lock); + + device_destroy(dma_heap_class, heap->heap_devt); + cdev_del(&heap->heap_cdev); + xa_erase(&dma_heap_minors, minor); + + kfree(heap); +} + +/** + * dma_heap_put - drops a reference to a dmabuf heap, potentially freeing = it + * @heap: DMA-Heap whose reference count to decrement + */ +void dma_heap_put(struct dma_heap *heap) +{ + kref_put(&heap->refcount, dma_heap_release); +} + static char *dma_heap_devnode(const struct device *dev, umode_t *mode) { return kasprintf(GFP_KERNEL, "dma_heap/%s", dev_name(dev)); diff --git a/include/linux/dma-heap.h b/include/linux/dma-heap.h index 648328a64b27e..ff57741700f5f 100644 --- a/include/linux/dma-heap.h +++ b/include/linux/dma-heap.h @@ -46,6 +46,8 @@ const char *dma_heap_get_name(struct dma_heap *heap); =20 struct dma_heap *dma_heap_add(const struct dma_heap_export_info *exp_info); =20 +void dma_heap_put(struct dma_heap *heap); + extern bool mem_accounting; =20 #endif /* _DMA_HEAPS_H */ --=20 2.43.0 From nobody Sat May 9 05:34:50 2026 Received: from foss.arm.com (foss.arm.com [217.140.110.172]) by smtp.subspace.kernel.org (Postfix) with ESMTP id 20ABB29D260; Tue, 5 May 2026 14:05:36 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=217.140.110.172 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1777989938; cv=none; b=aPA2OW/2NDGelxptTvlT1T6rqSNM50YwGKU5zAs6cTYjv7sFg4+Z8pYehEmi3nD7VuenA3a2DWvFelwTKly6GxlR/YNf2oegAbOSwQxnhbg35V73boQto4Ha2JAXEMMNBsQJOaEqg/0kijIjLr6lvMQ8KMe9vahCZNQYmDn9+kE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1777989938; c=relaxed/simple; bh=knenjS6icqSk3YRJhYDzdkIS/YGlcoD/AJp0MB+GY40=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=ls7x00+mIQvCLQUX96QiLYwlQKI9S3lH/iLZyw7148SfhZ5kV1RHeDgtvF44DvhVXc0Vqw5SydNCQlHdjBD/QViGOGUZd1pS5z+6Nch6Dvthc/FG8dlWPHYUgzWg5RQwfpkWudCqZss+Rkxu4LmguhnFJJVdn9sMOJAhhFHCA/M= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=arm.com; spf=pass smtp.mailfrom=arm.com; dkim=pass (1024-bit key) header.d=arm.com header.i=@arm.com header.b=cW8emmly; arc=none smtp.client-ip=217.140.110.172 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=arm.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=arm.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=arm.com header.i=@arm.com header.b="cW8emmly" Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id 1787924C0; Tue, 5 May 2026 07:05:31 -0700 (PDT) Received: from e120398-lin.trondheim.arm.com (e120398-lin.trondheim.arm.com [10.42.46.160]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id 770E33F763; Tue, 5 May 2026 07:05:31 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=arm.com; s=foss; t=1777989936; bh=knenjS6icqSk3YRJhYDzdkIS/YGlcoD/AJp0MB+GY40=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=cW8emmly/iWCkM4Zgb9M2QLXsBVbQTUQISQA8G9vSVGTr6pfllLsjuzA0hQyI7W1W dNR1TgB+qSzwQOZcaJYjQnVP0oULO8NgArKEd8VRGzt8Y+ZHJAiellnat15kTvAun6 UODcQQwfFPRRbZWB5eWC2x19OixZ3PCB42MD4Z0I= From: Ketil Johnsen To: David Airlie , Simona Vetter , Maarten Lankhorst , Maxime Ripard , Thomas Zimmermann , Jonathan Corbet , Shuah Khan , Sumit Semwal , Benjamin Gaignard , Brian Starkey , John Stultz , "T.J. Mercier" , =?UTF-8?q?Christian=20K=C3=B6nig?= , Boris Brezillon , Steven Price , Liviu Dudau , Daniel Almeida , Alice Ryhl , Matthias Brugger , AngeloGioacchino Del Regno Cc: dri-devel@lists.freedesktop.org, linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org, linux-media@vger.kernel.org, linaro-mm-sig@lists.linaro.org, linux-arm-kernel@lists.infradead.org, linux-mediatek@lists.infradead.org, Yong Wu , Yunfei Dong , Florent Tomasin , Ketil Johnsen Subject: [PATCH 2/8] dma-heap: Provide accessors so that in-kernel drivers can allocate dmabufs from specific heaps Date: Tue, 5 May 2026 16:05:08 +0200 Message-ID: <20260505140516.1372388-3-ketil.johnsen@arm.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260505140516.1372388-1-ketil.johnsen@arm.com> References: <20260505140516.1372388-1-ketil.johnsen@arm.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: John Stultz This allows drivers who don't want to create their own DMA-BUF exporter to be able to allocate DMA-BUFs directly from existing DMA-BUF Heaps. There is some concern that the premise of DMA-BUF heaps is that userland knows better about what type of heap memory is needed for a pipeline, so it would likely be best for drivers to import and fill DMA-BUFs allocated by userland instead of allocating one themselves, but this is still up for debate. Signed-off-by: John Stultz Signed-off-by: T.J. Mercier Signed-off-by: Yong Wu [Yong: Fix the checkpatch alignment warning] Signed-off-by: Yunfei Dong Signed-off-by: Florent Tomasin [Florent: Rebase] Signed-off-by: Ketil Johnsen [Ketil: Rebase] --- drivers/dma-buf/dma-heap.c | 80 ++++++++++++++++++++++++++++++-------- include/linux/dma-heap.h | 6 +++ 2 files changed, 70 insertions(+), 16 deletions(-) diff --git a/drivers/dma-buf/dma-heap.c b/drivers/dma-buf/dma-heap.c index 9fd365ddbd517..854d40d789ff2 100644 --- a/drivers/dma-buf/dma-heap.c +++ b/drivers/dma-buf/dma-heap.c @@ -57,12 +57,24 @@ module_param(mem_accounting, bool, 0444); MODULE_PARM_DESC(mem_accounting, "Enable cgroup-based memory accounting for dma-buf heap allocations (de= fault=3Dfalse)."); =20 -static int dma_heap_buffer_alloc(struct dma_heap *heap, size_t len, - u32 fd_flags, - u64 heap_flags) +/** + * dma_heap_buffer_alloc - Allocate dma-buf from a dma_heap + * @heap: DMA-Heap to allocate from + * @len: size to allocate in bytes + * @fd_flags: flags to set on returned dma-buf fd + * @heap_flags: flags to pass to the dma heap + * + * This is for internal dma-buf allocations only. Free returned buffers wi= th dma_buf_put(). + */ +struct dma_buf *dma_heap_buffer_alloc(struct dma_heap *heap, size_t len, + u32 fd_flags, + u64 heap_flags) { - struct dma_buf *dmabuf; - int fd; + if (fd_flags & ~DMA_HEAP_VALID_FD_FLAGS) + return ERR_PTR(-EINVAL); + + if (heap_flags & ~DMA_HEAP_VALID_HEAP_FLAGS) + return ERR_PTR(-EINVAL); =20 /* * Allocations from all heaps have to begin @@ -70,9 +82,20 @@ static int dma_heap_buffer_alloc(struct dma_heap *heap, = size_t len, */ len =3D PAGE_ALIGN(len); if (!len) - return -EINVAL; + return ERR_PTR(-EINVAL); + + return heap->ops->allocate(heap, len, fd_flags, heap_flags); +} +EXPORT_SYMBOL_NS_GPL(dma_heap_buffer_alloc, "DMA_BUF_HEAP"); =20 - dmabuf =3D heap->ops->allocate(heap, len, fd_flags, heap_flags); +static int dma_heap_bufferfd_alloc(struct dma_heap *heap, size_t len, + u32 fd_flags, + u64 heap_flags) +{ + struct dma_buf *dmabuf; + int fd; + + dmabuf =3D dma_heap_buffer_alloc(heap, len, fd_flags, heap_flags); if (IS_ERR(dmabuf)) return PTR_ERR(dmabuf); =20 @@ -110,15 +133,9 @@ static long dma_heap_ioctl_allocate(struct file *file,= void *data) if (heap_allocation->fd) return -EINVAL; =20 - if (heap_allocation->fd_flags & ~DMA_HEAP_VALID_FD_FLAGS) - return -EINVAL; - - if (heap_allocation->heap_flags & ~DMA_HEAP_VALID_HEAP_FLAGS) - return -EINVAL; - - fd =3D dma_heap_buffer_alloc(heap, heap_allocation->len, - heap_allocation->fd_flags, - heap_allocation->heap_flags); + fd =3D dma_heap_bufferfd_alloc(heap, heap_allocation->len, + heap_allocation->fd_flags, + heap_allocation->heap_flags); if (fd < 0) return fd; =20 @@ -317,6 +334,36 @@ struct dma_heap *dma_heap_add(const struct dma_heap_ex= port_info *exp_info) } EXPORT_SYMBOL_NS_GPL(dma_heap_add, "DMA_BUF_HEAP"); =20 +/** + * dma_heap_find - get the heap registered with the specified name + * @name: Name of the DMA-Heap to find + * + * Returns: + * The DMA-Heap with the provided name. + * + * NOTE: DMA-Heaps returned from this function MUST be released using + * dma_heap_put() when the user is done to enable the heap to be unloaded. + */ +struct dma_heap *dma_heap_find(const char *name) +{ + struct dma_heap *h; + + mutex_lock(&heap_list_lock); + list_for_each_entry(h, &heap_list, list) { + if (!kref_get_unless_zero(&h->refcount)) + continue; + + if (!strcmp(h->name, name)) { + mutex_unlock(&heap_list_lock); + return h; + } + dma_heap_put(h); + } + mutex_unlock(&heap_list_lock); + return NULL; +} +EXPORT_SYMBOL_NS_GPL(dma_heap_find, "DMA_BUF_HEAP"); + static void dma_heap_release(struct kref *ref) { struct dma_heap *heap =3D container_of(ref, struct dma_heap, refcount); @@ -341,6 +388,7 @@ void dma_heap_put(struct dma_heap *heap) { kref_put(&heap->refcount, dma_heap_release); } +EXPORT_SYMBOL_NS_GPL(dma_heap_put, "DMA_BUF_HEAP"); =20 static char *dma_heap_devnode(const struct device *dev, umode_t *mode) { diff --git a/include/linux/dma-heap.h b/include/linux/dma-heap.h index ff57741700f5f..c3351f8a1f8cf 100644 --- a/include/linux/dma-heap.h +++ b/include/linux/dma-heap.h @@ -46,8 +46,14 @@ const char *dma_heap_get_name(struct dma_heap *heap); =20 struct dma_heap *dma_heap_add(const struct dma_heap_export_info *exp_info); =20 +struct dma_heap *dma_heap_find(const char *name); + void dma_heap_put(struct dma_heap *heap); =20 +struct dma_buf *dma_heap_buffer_alloc(struct dma_heap *heap, size_t len, + u32 fd_flags, + u64 heap_flags); + extern bool mem_accounting; =20 #endif /* _DMA_HEAPS_H */ --=20 2.43.0 From nobody Sat May 9 05:34:50 2026 Received: from foss.arm.com (foss.arm.com [217.140.110.172]) by smtp.subspace.kernel.org (Postfix) with ESMTP id 05F8C19A288; Tue, 5 May 2026 14:05:42 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=217.140.110.172 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1777989944; cv=none; b=GfKrDSVuL7ttnCmYvpyPBhnzUJKYfd9oWEAJdzjp15n8Z+tkrgBcQI8E+9qD3sVDUEpZvFZtVlm9wwi6gudNoxEFj5F5Z4PGuCLDvLdRqB3Fo84WN+b/ZHHNS9XRtCzwzL8cFqV9DonjDnly6X/lBgiLOmriHEQ/NTnu9c337X0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1777989944; c=relaxed/simple; bh=Lmg4UHVoceq5MLqHuT0Zw4zFdgj23nCiSgwMP/Dr5Vs=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=P5XNQ6vrUltJE7V3hC/A6UpzR2mSuSz97c+t+M4h7AI3PUbuWCASMLAJyWUPciYSEsrdbbO1BOMl8YwbFW/+iPa/tQBdZbkgKpW1lCHdDCe4r1n/RD4y3D+Brlw9QgjHUWTav98FC8qXGx/31bbqQP7a0G4BcKk3D34/pqPNv+U= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=arm.com; spf=pass smtp.mailfrom=arm.com; dkim=pass (1024-bit key) header.d=arm.com header.i=@arm.com header.b=Cf7NCzLW; arc=none smtp.client-ip=217.140.110.172 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=arm.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=arm.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=arm.com header.i=@arm.com header.b="Cf7NCzLW" Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id 0EB582681; Tue, 5 May 2026 07:05:36 -0700 (PDT) Received: from e120398-lin.trondheim.arm.com (e120398-lin.trondheim.arm.com [10.42.46.160]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id DEEC63F763; Tue, 5 May 2026 07:05:36 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=arm.com; s=foss; t=1777989941; bh=Lmg4UHVoceq5MLqHuT0Zw4zFdgj23nCiSgwMP/Dr5Vs=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=Cf7NCzLWa2JQFYrlx4a14dPfmo+PNOr9sAOCyiFWWizwWQYFN9afN9Vy2akEh41w4 9Ikx7gWRRtHmxmzEnc8LlioyXtZsAw9p7gnYqp5TZFZw5+/qLMlpCdQ5Xrq4bEiEZA twar6aISCUE5yhhR5v2NLdJo/Hldo+NllxndJ3N8= From: Ketil Johnsen To: David Airlie , Simona Vetter , Maarten Lankhorst , Maxime Ripard , Thomas Zimmermann , Jonathan Corbet , Shuah Khan , Sumit Semwal , Benjamin Gaignard , Brian Starkey , John Stultz , "T.J. Mercier" , =?UTF-8?q?Christian=20K=C3=B6nig?= , Boris Brezillon , Steven Price , Liviu Dudau , Daniel Almeida , Alice Ryhl , Matthias Brugger , AngeloGioacchino Del Regno Cc: dri-devel@lists.freedesktop.org, linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org, linux-media@vger.kernel.org, linaro-mm-sig@lists.linaro.org, linux-arm-kernel@lists.infradead.org, linux-mediatek@lists.infradead.org, Ketil Johnsen Subject: [PATCH 3/8] drm/panthor: De-duplicate FW memory section sync Date: Tue, 5 May 2026 16:05:09 +0200 Message-ID: <20260505140516.1372388-4-ketil.johnsen@arm.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260505140516.1372388-1-ketil.johnsen@arm.com> References: <20260505140516.1372388-1-ketil.johnsen@arm.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Handle the sync to device of FW memory sections inside panthor_fw_init_section_mem() so that the callers do not have to. This small improvement is also critical for protected FW sections, so we avoid issuing memory transactions to protected memory from CPU running in normal mode. Signed-off-by: Ketil Johnsen Reviewed-by: Boris Brezillon --- drivers/gpu/drm/panthor/panthor_fw.c | 22 ++++++---------------- 1 file changed, 6 insertions(+), 16 deletions(-) diff --git a/drivers/gpu/drm/panthor/panthor_fw.c b/drivers/gpu/drm/panthor= /panthor_fw.c index be0da5b1f3abf..0d07a133dc3af 100644 --- a/drivers/gpu/drm/panthor/panthor_fw.c +++ b/drivers/gpu/drm/panthor/panthor_fw.c @@ -446,6 +446,7 @@ static void panthor_fw_init_section_mem(struct panthor_= device *ptdev, struct panthor_fw_section *section) { bool was_mapped =3D !!section->mem->kmap; + struct sg_table *sgt; int ret; =20 if (!section->data.size && @@ -464,6 +465,11 @@ static void panthor_fw_init_section_mem(struct panthor= _device *ptdev, =20 if (!was_mapped) panthor_kernel_bo_vunmap(section->mem); + + /* An sgt should have been requested when the kernel BO was GPU-mapped. */ + sgt =3D to_panthor_bo(section->mem->obj)->dmap.sgt; + if (!drm_WARN_ON_ONCE(&ptdev->base, !sgt)) + dma_sync_sgtable_for_device(ptdev->base.dev, sgt, DMA_TO_DEVICE); } =20 /** @@ -626,7 +632,6 @@ static int panthor_fw_load_section_entry(struct panthor= _device *ptdev, section_size =3D hdr.va.end - hdr.va.start; if (section_size) { u32 cache_mode =3D hdr.flags & CSF_FW_BINARY_IFACE_ENTRY_CACHE_MODE_MASK; - struct panthor_gem_object *bo; u32 vm_map_flags =3D 0; u64 va =3D hdr.va.start; =20 @@ -663,14 +668,6 @@ static int panthor_fw_load_section_entry(struct pantho= r_device *ptdev, } =20 panthor_fw_init_section_mem(ptdev, section); - - bo =3D to_panthor_bo(section->mem->obj); - - /* An sgt should have been requested when the kernel BO was GPU-mapped. = */ - if (drm_WARN_ON_ONCE(&ptdev->base, !bo->dmap.sgt)) - return -EINVAL; - - dma_sync_sgtable_for_device(ptdev->base.dev, bo->dmap.sgt, DMA_TO_DEVICE= ); } =20 if (hdr.va.start =3D=3D CSF_MCU_SHARED_REGION_START) @@ -724,17 +721,10 @@ panthor_reload_fw_sections(struct panthor_device *ptd= ev, bool full_reload) struct panthor_fw_section *section; =20 list_for_each_entry(section, &ptdev->fw->sections, node) { - struct sg_table *sgt; - if (!full_reload && !(section->flags & CSF_FW_BINARY_IFACE_ENTRY_WR)) continue; =20 panthor_fw_init_section_mem(ptdev, section); - - /* An sgt should have been requested when the kernel BO was GPU-mapped. = */ - sgt =3D to_panthor_bo(section->mem->obj)->dmap.sgt; - if (!drm_WARN_ON_ONCE(&ptdev->base, !sgt)) - dma_sync_sgtable_for_device(ptdev->base.dev, sgt, DMA_TO_DEVICE); } } =20 --=20 2.43.0 From nobody Sat May 9 05:34:50 2026 Received: from foss.arm.com (foss.arm.com [217.140.110.172]) by smtp.subspace.kernel.org (Postfix) with ESMTP id 5D77547F2E5; Tue, 5 May 2026 14:05:47 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=217.140.110.172 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1777989949; cv=none; b=C5XI20DCldEf7nciCZdsN3tnNzOH2Diwn7Zqvju+viD7WHvhukfUW24+5T/yAABF7NDE6Y1IshcXt7c9xLi9yXGR24fULMuu1jwvTGqD7MViPQmjFjaNPGrrDFFz7QEW1ko4bafujICtgn03e46Q+XeCYlaXVKUCXIX1QMf2RAI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1777989949; c=relaxed/simple; bh=f3sCyiG5jjvWfmG4nNgmq7j6ZJAIiUvXUkRWvrwEHbQ=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=Amnl1uxOHoUdzYT10wS0wS/pg8lUPF94oWq+WYV27WlhQp6Wz+5chzhJIZzjWhVbOE8LuX+13DOmg5IUHGAaEnwLEaqgf1ZgjXCbeePrlVrukE+mvwA+FGenUhf5Df1Fx0vSuu46hqawWio6yED5LTV/dvwwzPjDZE0VNbKQ8nw= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=arm.com; spf=pass smtp.mailfrom=arm.com; dkim=pass (1024-bit key) header.d=arm.com header.i=@arm.com header.b=uoYnNmcO; arc=none smtp.client-ip=217.140.110.172 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=arm.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=arm.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=arm.com header.i=@arm.com header.b="uoYnNmcO" Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id 4F77424C0; Tue, 5 May 2026 07:05:41 -0700 (PDT) Received: from e120398-lin.trondheim.arm.com (e120398-lin.trondheim.arm.com [10.42.46.160]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id D78EC3F763; Tue, 5 May 2026 07:05:41 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=arm.com; s=foss; t=1777989946; bh=f3sCyiG5jjvWfmG4nNgmq7j6ZJAIiUvXUkRWvrwEHbQ=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=uoYnNmcOadLNqi1gWhiREDV0/WVOVV6FSHTufOoQPH2kFyRpj5XtdZKPRScOi0B6c UKdkyhQG1qof4b72B2F6vDf0IsMCMvbwN5i8ZW543P951NZPKiAcsjaTRd20f+0X4X Kdpe7NJlhEf71MGDEFnCCK1ZcGAjkPdzmPPuJCRc= From: Ketil Johnsen To: David Airlie , Simona Vetter , Maarten Lankhorst , Maxime Ripard , Thomas Zimmermann , Jonathan Corbet , Shuah Khan , Sumit Semwal , Benjamin Gaignard , Brian Starkey , John Stultz , "T.J. Mercier" , =?UTF-8?q?Christian=20K=C3=B6nig?= , Boris Brezillon , Steven Price , Liviu Dudau , Daniel Almeida , Alice Ryhl , Matthias Brugger , AngeloGioacchino Del Regno Cc: dri-devel@lists.freedesktop.org, linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org, linux-media@vger.kernel.org, linaro-mm-sig@lists.linaro.org, linux-arm-kernel@lists.infradead.org, linux-mediatek@lists.infradead.org, Florent Tomasin , Ketil Johnsen Subject: [PATCH 4/8] drm/panthor: Add support for protected memory allocation in panthor Date: Tue, 5 May 2026 16:05:10 +0200 Message-ID: <20260505140516.1372388-5-ketil.johnsen@arm.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260505140516.1372388-1-ketil.johnsen@arm.com> References: <20260505140516.1372388-1-ketil.johnsen@arm.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable From: Florent Tomasin This patch allows Panthor to allocate buffer objects from a protected heap. The Panthor driver should be seen as a consumer of the heap and not an exporter. Protected memory buffers needed by the Panthor driver: - On CSF FW load, the Panthor driver must allocate a protected buffer object to hold data to use by the FW when in protected mode. This protected buffer object is owned by the device and does not belong to a process. - On CSG creation, the Panthor driver must allocate a protected suspend buffer object for the FW to store data when suspending the CSG while in protected mode. The kernel owns this allocation and does not allow user space mapping. The format of the data in this buffer is only known by the FW and does not need to be shared with other entities. The driver will retrieve the protected heap using the name of the heap provided to the driver as module parameter. If the heap is not yet available, the panthor driver will defer the probe until created. It is an integration error to provide a heap name that does not exist or is never created. Panthor is calling the DMA heap allocation function and obtains a DMA buffer from it. This buffer is then registered to GEM and imported. Signed-off-by: Florent Tomasin Co-developed-by: Ketil Johnsen Signed-off-by: Ketil Johnsen --- Documentation/gpu/panthor.rst | 47 +++++++++++++++ drivers/gpu/drm/panthor/Kconfig | 1 + drivers/gpu/drm/panthor/panthor_device.c | 28 ++++++++- drivers/gpu/drm/panthor/panthor_device.h | 6 ++ drivers/gpu/drm/panthor/panthor_fw.c | 29 ++++++++- drivers/gpu/drm/panthor/panthor_fw.h | 2 + drivers/gpu/drm/panthor/panthor_gem.c | 77 ++++++++++++++++++++++-- drivers/gpu/drm/panthor/panthor_gem.h | 16 ++++- drivers/gpu/drm/panthor/panthor_heap.c | 2 + drivers/gpu/drm/panthor/panthor_sched.c | 11 +++- 10 files changed, 208 insertions(+), 11 deletions(-) diff --git a/Documentation/gpu/panthor.rst b/Documentation/gpu/panthor.rst index 7a841741278fb..be20eadea6dd5 100644 --- a/Documentation/gpu/panthor.rst +++ b/Documentation/gpu/panthor.rst @@ -54,3 +54,50 @@ sync object arrays and heap chunks. Because they are all= allocated and pinned at creation time, only `panthor-resident-memory` is necessary to tell us t= heir size. `panthor-active-memory` shows the size of kernel BO's associated with VM's and groups currently being scheduled for execution by the GPU. + +Panthor Protected Memory Integration +=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D + +Panthor requires the platform to provide a protected DMA HEAP. +This DMA heap must be identifiable via a string name. +The name is defined by the system integrator, it could be hard coded +in the heap driver, defined by a module parameter of the heap driver +or else. + +.. code-block:: none + + User + =E2=94=8C=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2= =94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94= =80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80= =E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=90 + | Application | + =E2=94=94=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2= =94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=96=B2=E2=94= =80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80= =E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=98 + | | | + | DMA-BUF | | Protected + | | | Job Submission + --------|---------|----------|--------- + Kernel | | | + | | | + | | DMA-BUF | + =E2=94=8C=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94= =80=E2=96=BC=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80= =E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=90 =E2=94= =8C=E2=94=80=E2=96=BC=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80= =E2=94=80=E2=94=90 + | DMA PROTECTED HEAP |=E2=97=84=E2=94=80=E2=94=80=E2=94=80| Panthor | + | (Vendor specific) | | | + =E2=94=94=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94= =80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80= =E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=98 =E2=94= =94=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80= =E2=94=80=E2=94=98 + | | + --------|--------------------|--------- + HW | | + | | + =E2=94=8C=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94= =80=E2=96=BC=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80= =E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2= =94=90 =E2=94=8C=E2=94=80=E2=96=BC=E2=94=80=E2=94=80=E2=94=80=E2=94=90 + | Trusted FW | | | + | Protected Memory =E2=97=84=E2=94=80=E2=94=80=E2=96=BA GPU | + =E2=94=94=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94= =80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80= =E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2= =94=98 =E2=94=94=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=98 + +To configure Panthor to use the protected memory heap, pass the protected = memory +heap string name as module parameter of the Panthor module. + +Example: + + .. code-block:: shell + + insmod panthor.ko protected_heap_name=3D=E2=80=9Cvendor_protected_= heap" + +If `protected_heap_name` module parameter is not provided, Panthor will no= t support +protected job execution. diff --git a/drivers/gpu/drm/panthor/Kconfig b/drivers/gpu/drm/panthor/Kcon= fig index 911e7f4810c39..fb0bad9a0fd2b 100644 --- a/drivers/gpu/drm/panthor/Kconfig +++ b/drivers/gpu/drm/panthor/Kconfig @@ -7,6 +7,7 @@ config DRM_PANTHOR depends on !GENERIC_ATOMIC64 # for IOMMU_IO_PGTABLE_LPAE depends on MMU select DEVFREQ_GOV_SIMPLE_ONDEMAND + select DMABUF_HEAPS select DRM_EXEC select DRM_GPUVM select DRM_SCHED diff --git a/drivers/gpu/drm/panthor/panthor_device.c b/drivers/gpu/drm/pan= thor/panthor_device.c index bc62a498a8a84..3a5cdfa99e5fe 100644 --- a/drivers/gpu/drm/panthor/panthor_device.c +++ b/drivers/gpu/drm/panthor/panthor_device.c @@ -5,7 +5,9 @@ /* Copyright 2025 ARM Limited. All rights reserved. */ =20 #include +#include #include +#include #include #include #include @@ -27,6 +29,10 @@ #include "panthor_regs.h" #include "panthor_sched.h" =20 +MODULE_PARM_DESC(protected_heap_name, "DMA heap name, from which to alloca= te protected buffers"); +static char *protected_heap_name; +module_param(protected_heap_name, charp, 0444); + static int panthor_gpu_coherency_init(struct panthor_device *ptdev) { BUILD_BUG_ON(GPU_COHERENCY_NONE !=3D DRM_PANTHOR_GPU_COHERENCY_NONE); @@ -127,6 +133,9 @@ void panthor_device_unplug(struct panthor_device *ptdev) panthor_gpu_unplug(ptdev); panthor_pwr_unplug(ptdev); =20 + if (ptdev->protm.heap) + dma_heap_put(ptdev->protm.heap); + pm_runtime_dont_use_autosuspend(ptdev->base.dev); pm_runtime_put_sync_suspend(ptdev->base.dev); =20 @@ -277,9 +286,21 @@ int panthor_device_init(struct panthor_device *ptdev) return ret; } =20 + /* If a protected heap name is specified but not found, defer the probe u= ntil created */ + if (protected_heap_name && strlen(protected_heap_name)) { + ptdev->protm.heap =3D dma_heap_find(protected_heap_name); + if (!ptdev->protm.heap) { + drm_warn(&ptdev->base, + "Protected heap \'%s\' not (yet) available - deferring probe", + protected_heap_name); + ret =3D -EPROBE_DEFER; + goto err_rpm_put; + } + } + ret =3D panthor_hw_init(ptdev); if (ret) - goto err_rpm_put; + goto err_dma_heap_put; =20 ret =3D panthor_pwr_init(ptdev); if (ret) @@ -343,6 +364,11 @@ int panthor_device_init(struct panthor_device *ptdev) =20 err_rpm_put: pm_runtime_put_sync_suspend(ptdev->base.dev); + +err_dma_heap_put: + if (ptdev->protm.heap) + dma_heap_put(ptdev->protm.heap); + return ret; } =20 diff --git a/drivers/gpu/drm/panthor/panthor_device.h b/drivers/gpu/drm/pan= thor/panthor_device.h index 5cba272f9b4de..d51fec97fc5fa 100644 --- a/drivers/gpu/drm/panthor/panthor_device.h +++ b/drivers/gpu/drm/panthor/panthor_device.h @@ -7,6 +7,7 @@ #define __PANTHOR_DEVICE_H__ =20 #include +#include #include #include #include @@ -329,6 +330,11 @@ struct panthor_device { struct list_head node; } gems; #endif + /** @protm: Protected mode related data. */ + struct { + /** @heap: Pointer to the protected heap */ + struct dma_heap *heap; + } protm; }; =20 struct panthor_gpu_usage { diff --git a/drivers/gpu/drm/panthor/panthor_fw.c b/drivers/gpu/drm/panthor= /panthor_fw.c index 0d07a133dc3af..1aba29b9779b6 100644 --- a/drivers/gpu/drm/panthor/panthor_fw.c +++ b/drivers/gpu/drm/panthor/panthor_fw.c @@ -500,6 +500,7 @@ panthor_fw_alloc_queue_iface_mem(struct panthor_device = *ptdev, =20 mem =3D panthor_kernel_bo_create(ptdev, ptdev->fw->vm, SZ_8K, DRM_PANTHOR_BO_NO_MMAP, + 0, DRM_PANTHOR_VM_BIND_OP_MAP_NOEXEC | DRM_PANTHOR_VM_BIND_OP_MAP_UNCACHED, PANTHOR_VM_KERNEL_AUTO_VA, @@ -534,6 +535,26 @@ panthor_fw_alloc_suspend_buf_mem(struct panthor_device= *ptdev, size_t size) { return panthor_kernel_bo_create(ptdev, panthor_fw_vm(ptdev), size, DRM_PANTHOR_BO_NO_MMAP, + 0, + DRM_PANTHOR_VM_BIND_OP_MAP_NOEXEC, + PANTHOR_VM_KERNEL_AUTO_VA, + "suspend_buf"); +} + +/** + * panthor_fw_alloc_protm_suspend_buf_mem() - Allocate a protm suspend buf= fer + * for a command stream group. + * @ptdev: Device. + * @size: Size of the protm suspend buffer. + * + * Return: A valid pointer in case of success, an ERR_PTR() otherwise. + */ +struct panthor_kernel_bo * +panthor_fw_alloc_protm_suspend_buf_mem(struct panthor_device *ptdev, size_= t size) +{ + return panthor_kernel_bo_create(ptdev, panthor_fw_vm(ptdev), size, + DRM_PANTHOR_BO_NO_MMAP, + DRM_PANTHOR_KBO_PROTECTED_HEAP, DRM_PANTHOR_VM_BIND_OP_MAP_NOEXEC, PANTHOR_VM_KERNEL_AUTO_VA, "FW suspend buffer"); @@ -547,6 +568,7 @@ static int panthor_fw_load_section_entry(struct panthor= _device *ptdev, ssize_t vm_pgsz =3D panthor_vm_page_size(ptdev->fw->vm); struct panthor_fw_binary_section_entry_hdr hdr; struct panthor_fw_section *section; + u32 kbo_flags =3D 0; u32 section_size; u32 name_len; int ret; @@ -585,10 +607,13 @@ static int panthor_fw_load_section_entry(struct panth= or_device *ptdev, return -EINVAL; } =20 - if (hdr.flags & CSF_FW_BINARY_IFACE_ENTRY_PROT) { + if ((hdr.flags & CSF_FW_BINARY_IFACE_ENTRY_PROT) && !ptdev->protm.heap) { drm_warn(&ptdev->base, "Firmware protected mode entry is not supported, ignoring"); return 0; + } else if ((hdr.flags & CSF_FW_BINARY_IFACE_ENTRY_PROT) && ptdev->protm.h= eap) { + drm_info(&ptdev->base, "Firmware protected mode entry supported"); + kbo_flags =3D DRM_PANTHOR_KBO_PROTECTED_HEAP; } =20 if (hdr.va.start =3D=3D CSF_MCU_SHARED_REGION_START && @@ -653,7 +678,7 @@ static int panthor_fw_load_section_entry(struct panthor= _device *ptdev, =20 section->mem =3D panthor_kernel_bo_create(ptdev, panthor_fw_vm(ptdev), section_size, - DRM_PANTHOR_BO_NO_MMAP, + DRM_PANTHOR_BO_NO_MMAP, kbo_flags, vm_map_flags, va, "FW section"); if (IS_ERR(section->mem)) return PTR_ERR(section->mem); diff --git a/drivers/gpu/drm/panthor/panthor_fw.h b/drivers/gpu/drm/panthor= /panthor_fw.h index fbdc21469ba32..0cf3761abf789 100644 --- a/drivers/gpu/drm/panthor/panthor_fw.h +++ b/drivers/gpu/drm/panthor/panthor_fw.h @@ -509,6 +509,8 @@ panthor_fw_alloc_queue_iface_mem(struct panthor_device = *ptdev, u32 *input_fw_va, u32 *output_fw_va); struct panthor_kernel_bo * panthor_fw_alloc_suspend_buf_mem(struct panthor_device *ptdev, size_t size= ); +struct panthor_kernel_bo * +panthor_fw_alloc_protm_suspend_buf_mem(struct panthor_device *ptdev, size_= t size); =20 struct panthor_vm *panthor_fw_vm(struct panthor_device *ptdev); =20 diff --git a/drivers/gpu/drm/panthor/panthor_gem.c b/drivers/gpu/drm/pantho= r/panthor_gem.c index 13295d7a593df..08fe4a5e43817 100644 --- a/drivers/gpu/drm/panthor/panthor_gem.c +++ b/drivers/gpu/drm/panthor/panthor_gem.c @@ -20,12 +20,17 @@ #include #include =20 +#include + #include "panthor_device.h" #include "panthor_drv.h" #include "panthor_fw.h" #include "panthor_gem.h" #include "panthor_mmu.h" =20 +MODULE_IMPORT_NS("DMA_BUF"); +MODULE_IMPORT_NS("DMA_BUF_HEAP"); + void panthor_gem_init(struct panthor_device *ptdev) { int err; @@ -466,7 +471,6 @@ static void panthor_gem_free_object(struct drm_gem_obje= ct *obj) } =20 drm_gem_object_release(obj); - kfree(bo); drm_gem_object_put(vm_root_gem); } @@ -1026,6 +1030,7 @@ panthor_gem_create(struct drm_device *dev, size_t siz= e, uint32_t flags, } =20 panthor_gem_debugfs_set_usage_flags(bo, usage_flags); + return bo; =20 err_put: @@ -1033,6 +1038,54 @@ panthor_gem_create(struct drm_device *dev, size_t si= ze, uint32_t flags, return ERR_PTR(ret); } =20 +static struct panthor_gem_object * +panthor_gem_create_protected(struct panthor_device *ptdev, size_t size, + uint32_t flags, struct panthor_vm *exclusive_vm, + u32 usage_flags) +{ + struct dma_buf *dma_bo =3D NULL; + struct drm_gem_object *gem_obj; + struct panthor_gem_object *bo; + int ret; + + if (!ptdev->protm.heap) + return ERR_PTR(-EINVAL); + + if (flags !=3D DRM_PANTHOR_BO_NO_MMAP) + return ERR_PTR(-EINVAL); + + if (!exclusive_vm) + return ERR_PTR(-EINVAL); + + dma_bo =3D dma_heap_buffer_alloc(ptdev->protm.heap, size, DMA_HEAP_VALID_= FD_FLAGS, + DMA_HEAP_VALID_HEAP_FLAGS); + if (IS_ERR(dma_bo)) + return ERR_PTR(PTR_ERR(dma_bo)); + + gem_obj =3D drm_gem_prime_import(&ptdev->base, dma_bo); + if (IS_ERR(gem_obj)) { + ret =3D PTR_ERR(gem_obj); + goto err_free_dma_bo; + } + + bo =3D to_panthor_bo(gem_obj); + bo->flags =3D flags; + + panthor_gem_debugfs_set_usage_flags(bo, usage_flags); + + bo->exclusive_vm_root_gem =3D panthor_vm_root_gem(exclusive_vm); + drm_gem_object_get(bo->exclusive_vm_root_gem); + bo->base.resv =3D bo->exclusive_vm_root_gem->resv; + + return bo; + +err_free_dma_bo: + if (dma_bo) + dma_buf_put(dma_bo); + + return ERR_PTR(ret); +} + struct drm_gem_object * panthor_gem_prime_import_sg_table(struct drm_device *dev, struct dma_buf_attachment *attach, @@ -1242,12 +1295,17 @@ void panthor_kernel_bo_destroy(struct panthor_kerne= l_bo *bo) { struct panthor_device *ptdev; struct panthor_vm *vm; + struct dma_buf *dma_bo =3D NULL; =20 if (IS_ERR_OR_NULL(bo)) return; =20 ptdev =3D container_of(bo->obj->dev, struct panthor_device, base); vm =3D bo->vm; + + if (bo->flags & DRM_PANTHOR_KBO_PROTECTED_HEAP) + dma_bo =3D bo->obj->import_attach->dmabuf; + panthor_kernel_bo_vunmap(bo); =20 drm_WARN_ON(bo->obj->dev, @@ -1257,6 +1315,10 @@ void panthor_kernel_bo_destroy(struct panthor_kernel= _bo *bo) if (vm =3D=3D panthor_fw_vm(ptdev)) panthor_gem_unpin(to_panthor_bo(bo->obj)); drm_gem_object_put(bo->obj); + + if (dma_bo) + dma_buf_put(dma_bo); + panthor_vm_put(vm); kfree(bo); } @@ -1267,6 +1329,7 @@ void panthor_kernel_bo_destroy(struct panthor_kernel_= bo *bo) * @vm: VM to map the GEM to. * @size: Size of the buffer object. * @bo_flags: Combination of drm_panthor_bo_flags flags. + * @kbo_flags: Combination of drm_panthor_kbo_flags flags. * @vm_map_flags: Combination of drm_panthor_vm_bind_op_flags (only those * that are related to map operations). * @gpu_va: GPU address assigned when mapping to the VM. @@ -1278,8 +1341,8 @@ void panthor_kernel_bo_destroy(struct panthor_kernel_= bo *bo) */ struct panthor_kernel_bo * panthor_kernel_bo_create(struct panthor_device *ptdev, struct panthor_vm *= vm, - size_t size, u32 bo_flags, u32 vm_map_flags, - u64 gpu_va, const char *name) + size_t size, u32 bo_flags, u32 kbo_flags, + u32 vm_map_flags, u64 gpu_va, const char *name) { struct panthor_kernel_bo *kbo; struct panthor_gem_object *bo; @@ -1296,13 +1359,19 @@ panthor_kernel_bo_create(struct panthor_device *ptd= ev, struct panthor_vm *vm, if (vm =3D=3D panthor_fw_vm(ptdev)) debug_flags |=3D PANTHOR_DEBUGFS_GEM_USAGE_FLAG_FW_MAPPED; =20 - bo =3D panthor_gem_create(&ptdev->base, size, bo_flags, vm, debug_flags); + if (kbo_flags & DRM_PANTHOR_KBO_PROTECTED_HEAP) { + bo =3D panthor_gem_create_protected(ptdev, size, bo_flags, vm, debug_fla= gs); + } else { + bo =3D panthor_gem_create(&ptdev->base, size, bo_flags, vm, debug_flags); + } + if (IS_ERR(bo)) { ret =3D PTR_ERR(bo); goto err_free_kbo; } =20 kbo->obj =3D &bo->base; + kbo->flags =3D kbo_flags; =20 if (vm =3D=3D panthor_fw_vm(ptdev)) { ret =3D panthor_gem_pin(bo); diff --git a/drivers/gpu/drm/panthor/panthor_gem.h b/drivers/gpu/drm/pantho= r/panthor_gem.h index ae0491d0b1216..b0eb5b465981a 100644 --- a/drivers/gpu/drm/panthor/panthor_gem.h +++ b/drivers/gpu/drm/panthor/panthor_gem.h @@ -153,6 +153,17 @@ enum panthor_gem_reclaim_state { PANTHOR_GEM_UNRECLAIMABLE, }; =20 +/** + * enum drm_panthor_kbo_flags - Kernel buffer object flags, passed at cre= ation time + */ +enum drm_panthor_kbo_flags { + /** + * @DRM_PANTHOR_KBO_PROTECTED_HEAP: The buffer object will be allocated + * from a DMA-Buf protected heap. + */ + DRM_PANTHOR_KBO_PROTECTED_HEAP =3D (1 << 0), +}; + /** * struct panthor_gem_object - Driver specific GEM object. */ @@ -233,6 +244,9 @@ struct panthor_kernel_bo { * @kmap: Kernel CPU mapping of @gem. */ void *kmap; + + /** @flags: Combination of drm_panthor_kbo_flags flags. */ + u32 flags; }; =20 #define to_panthor_bo(obj) container_of_const(obj, struct panthor_gem_obje= ct, base) @@ -310,7 +324,7 @@ panthor_kernel_bo_vunmap(struct panthor_kernel_bo *bo) =20 struct panthor_kernel_bo * panthor_kernel_bo_create(struct panthor_device *ptdev, struct panthor_vm *= vm, - size_t size, u32 bo_flags, u32 vm_map_flags, + size_t size, u32 bo_flags, u32 kbo_flags, u32 vm_map_flags, u64 gpu_va, const char *name); =20 void panthor_kernel_bo_destroy(struct panthor_kernel_bo *bo); diff --git a/drivers/gpu/drm/panthor/panthor_heap.c b/drivers/gpu/drm/panth= or/panthor_heap.c index 1ee30dc7066f7..3183c74451fb0 100644 --- a/drivers/gpu/drm/panthor/panthor_heap.c +++ b/drivers/gpu/drm/panthor/panthor_heap.c @@ -151,6 +151,7 @@ static int panthor_alloc_heap_chunk(struct panthor_heap= _pool *pool, =20 chunk->bo =3D panthor_kernel_bo_create(pool->ptdev, pool->vm, heap->chunk= _size, DRM_PANTHOR_BO_NO_MMAP, + 0, DRM_PANTHOR_VM_BIND_OP_MAP_NOEXEC, PANTHOR_VM_KERNEL_AUTO_VA, "Tiler heap chunk"); @@ -556,6 +557,7 @@ panthor_heap_pool_create(struct panthor_device *ptdev, = struct panthor_vm *vm) =20 pool->gpu_contexts =3D panthor_kernel_bo_create(ptdev, vm, bosize, DRM_PANTHOR_BO_NO_MMAP, + 0, DRM_PANTHOR_VM_BIND_OP_MAP_NOEXEC, PANTHOR_VM_KERNEL_AUTO_VA, "Heap pool"); diff --git a/drivers/gpu/drm/panthor/panthor_sched.c b/drivers/gpu/drm/pant= hor/panthor_sched.c index 41d6369fa9c05..5ee386338005c 100644 --- a/drivers/gpu/drm/panthor/panthor_sched.c +++ b/drivers/gpu/drm/panthor/panthor_sched.c @@ -3529,6 +3529,7 @@ group_create_queue(struct panthor_group *group, queue->ringbuf =3D panthor_kernel_bo_create(group->ptdev, group->vm, args->ringbuf_size, DRM_PANTHOR_BO_NO_MMAP, + 0, DRM_PANTHOR_VM_BIND_OP_MAP_NOEXEC | DRM_PANTHOR_VM_BIND_OP_MAP_UNCACHED, PANTHOR_VM_KERNEL_AUTO_VA, @@ -3560,6 +3561,7 @@ group_create_queue(struct panthor_group *group, queue->profiling.slot_count * sizeof(struct panthor_job_profiling_data), DRM_PANTHOR_BO_NO_MMAP, + 0, DRM_PANTHOR_VM_BIND_OP_MAP_NOEXEC | DRM_PANTHOR_VM_BIND_OP_MAP_UNCACHED, PANTHOR_VM_KERNEL_AUTO_VA, @@ -3618,9 +3620,11 @@ static void add_group_kbo_sizes(struct panthor_devic= e *ptdev, if (drm_WARN_ON(&ptdev->base, ptdev !=3D group->ptdev)) return; =20 - group->fdinfo.kbo_sizes +=3D group->suspend_buf->obj->size; - group->fdinfo.kbo_sizes +=3D group->protm_suspend_buf->obj->size; group->fdinfo.kbo_sizes +=3D group->syncobjs->obj->size; + group->fdinfo.kbo_sizes +=3D group->suspend_buf->obj->size; + + if (group->protm_suspend_buf) + group->fdinfo.kbo_sizes +=3D group->protm_suspend_buf->obj->size; =20 for (i =3D 0; i < group->queue_count; i++) { queue =3D group->queues[i]; @@ -3701,7 +3705,7 @@ int panthor_group_create(struct panthor_file *pfile, } =20 suspend_size =3D csg_iface->control->protm_suspend_size; - group->protm_suspend_buf =3D panthor_fw_alloc_suspend_buf_mem(ptdev, susp= end_size); + group->protm_suspend_buf =3D panthor_fw_alloc_protm_suspend_buf_mem(ptdev= , suspend_size); if (IS_ERR(group->protm_suspend_buf)) { ret =3D PTR_ERR(group->protm_suspend_buf); group->protm_suspend_buf =3D NULL; @@ -3712,6 +3716,7 @@ int panthor_group_create(struct panthor_file *pfile, group_args->queues.count * sizeof(struct panthor_syncobj_64b), DRM_PANTHOR_BO_NO_MMAP, + 0, DRM_PANTHOR_VM_BIND_OP_MAP_NOEXEC | DRM_PANTHOR_VM_BIND_OP_MAP_UNCACHED, PANTHOR_VM_KERNEL_AUTO_VA, --=20 2.43.0 From nobody Sat May 9 05:34:50 2026 Received: from foss.arm.com (foss.arm.com [217.140.110.172]) by smtp.subspace.kernel.org (Postfix) with ESMTP id 6AA1147F2D8; Tue, 5 May 2026 14:05:52 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=217.140.110.172 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1777989954; cv=none; b=ZFrk/sbaDcGpIKdbLmFkLhe5x5NDF1nl4uLMBXVXV2jPjJ6cOk6XuGe97RgkOB8mnPio20kr5rwX4cYgq7PrsrOoLPK0ynI74I7+b2yt9hNpcdl0thFk5/qnDVGtzZvIfXDRfge+lnzdPWAv9MfrEAQjj6CGqzy+5422n2uEtYI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1777989954; c=relaxed/simple; bh=zdJqmzSnp5+/bhjrJp/EGOi5xHyCf1RHTudbn1wRpjY=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=obyUkEXKGfmPS92+VidO/ao3S9xubYFNu8z2VOB1jxG5zFFKmqMwsSsy7xKdj+teSdeZWVDhZZ0GWjikZC+2kBc0dMqRmUyBhKf7qNUIlSm7xOcz4foW0pDKh3JZJImstM9sehIttVNnDQmZzzWRAGI4rxfMOe8x9InooSbdQQc= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=arm.com; spf=pass smtp.mailfrom=arm.com; dkim=pass (1024-bit key) header.d=arm.com header.i=@arm.com header.b=nLmzr7T/; arc=none smtp.client-ip=217.140.110.172 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=arm.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=arm.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=arm.com header.i=@arm.com header.b="nLmzr7T/" Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id 6B95B3027; Tue, 5 May 2026 07:05:46 -0700 (PDT) Received: from e120398-lin.trondheim.arm.com (e120398-lin.trondheim.arm.com [10.42.46.160]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id 24CA13F905; Tue, 5 May 2026 07:05:46 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=arm.com; s=foss; t=1777989951; bh=zdJqmzSnp5+/bhjrJp/EGOi5xHyCf1RHTudbn1wRpjY=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=nLmzr7T/TXYtOkfV3AGfj2YRmwWby8LeyYgsM8YDQVWSa2wp/XUbW/QeY6ikcJKL9 qYz1xBcxllN6WxUxw1fzHLoGg6DS9vnBO56bIOtt2aOsX87MZO1miHt/u09MPq2FCi 90nWbncH1wDLxkAvKwb5VB4+nJ99BUgO+VoHeRAo= From: Ketil Johnsen To: David Airlie , Simona Vetter , Maarten Lankhorst , Maxime Ripard , Thomas Zimmermann , Jonathan Corbet , Shuah Khan , Sumit Semwal , Benjamin Gaignard , Brian Starkey , John Stultz , "T.J. Mercier" , =?UTF-8?q?Christian=20K=C3=B6nig?= , Boris Brezillon , Steven Price , Liviu Dudau , Daniel Almeida , Alice Ryhl , Matthias Brugger , AngeloGioacchino Del Regno Cc: dri-devel@lists.freedesktop.org, linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org, linux-media@vger.kernel.org, linaro-mm-sig@lists.linaro.org, linux-arm-kernel@lists.infradead.org, linux-mediatek@lists.infradead.org, Florent Tomasin , Ketil Johnsen Subject: [PATCH 5/8] drm/panthor: Minor scheduler refactoring Date: Tue, 5 May 2026 16:05:11 +0200 Message-ID: <20260505140516.1372388-6-ketil.johnsen@arm.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260505140516.1372388-1-ketil.johnsen@arm.com> References: <20260505140516.1372388-1-ketil.johnsen@arm.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Florent Tomasin Refactor parts of the group scheduling logic into new helper functions. This will simplify addition of the protected mode feature. Remove redundant assignments of csg_slot. Signed-off-by: Florent Tomasin Co-developed-by: Ketil Johnsen Signed-off-by: Ketil Johnsen Reviewed-by: Boris Brezillon --- drivers/gpu/drm/panthor/panthor_sched.c | 135 +++++++++++++++--------- 1 file changed, 86 insertions(+), 49 deletions(-) diff --git a/drivers/gpu/drm/panthor/panthor_sched.c b/drivers/gpu/drm/pant= hor/panthor_sched.c index 5ee386338005c..987072bd867c4 100644 --- a/drivers/gpu/drm/panthor/panthor_sched.c +++ b/drivers/gpu/drm/panthor/panthor_sched.c @@ -1934,6 +1934,12 @@ static void csgs_upd_ctx_init(struct panthor_csg_slo= ts_upd_ctx *ctx) memset(ctx, 0, sizeof(*ctx)); } =20 +static void csgs_upd_ctx_ring_doorbell(struct panthor_csg_slots_upd_ctx *c= tx, + u32 csg_id) +{ + ctx->update_mask |=3D BIT(csg_id); +} + static void csgs_upd_ctx_queue_reqs(struct panthor_device *ptdev, struct panthor_csg_slots_upd_ctx *ctx, u32 csg_id, u32 value, u32 mask) @@ -1944,7 +1950,8 @@ static void csgs_upd_ctx_queue_reqs(struct panthor_de= vice *ptdev, =20 ctx->requests[csg_id].value =3D (ctx->requests[csg_id].value & ~mask) | (= value & mask); ctx->requests[csg_id].mask |=3D mask; - ctx->update_mask |=3D BIT(csg_id); + + csgs_upd_ctx_ring_doorbell(ctx, csg_id); } =20 static int csgs_upd_ctx_apply_locked(struct panthor_device *ptdev, @@ -1961,8 +1968,12 @@ static int csgs_upd_ctx_apply_locked(struct panthor_= device *ptdev, while (update_slots) { struct panthor_fw_csg_iface *csg_iface; u32 csg_id =3D ffs(update_slots) - 1; + u32 req_mask =3D ctx->requests[csg_id].mask; =20 update_slots &=3D ~BIT(csg_id); + if (!req_mask) + continue; + csg_iface =3D panthor_fw_get_csg_iface(ptdev, csg_id); panthor_fw_update_reqs(csg_iface, req, ctx->requests[csg_id].value, @@ -1979,6 +1990,9 @@ static int csgs_upd_ctx_apply_locked(struct panthor_d= evice *ptdev, int ret; =20 update_slots &=3D ~BIT(csg_id); + if (!req_mask) + continue; + csg_iface =3D panthor_fw_get_csg_iface(ptdev, csg_id); =20 ret =3D panthor_fw_csg_wait_acks(ptdev, csg_id, req_mask, &acked, 100); @@ -2266,12 +2280,76 @@ tick_ctx_cleanup(struct panthor_scheduler *sched, } } =20 +static void +tick_ctx_evict_group(struct panthor_scheduler *sched, + struct panthor_csg_slots_upd_ctx *upd_ctx, + struct panthor_group *group) +{ + struct panthor_device *ptdev =3D sched->ptdev; + + if (drm_WARN_ON(&ptdev->base, group->csg_id < 0)) + return; + + csgs_upd_ctx_queue_reqs(ptdev, upd_ctx, group->csg_id, + group_can_run(group) ? + CSG_STATE_SUSPEND : CSG_STATE_TERMINATE, + CSG_STATE_MASK); +} + + +static void +tick_ctx_reschedule_group(struct panthor_scheduler *sched, + struct panthor_csg_slots_upd_ctx *upd_ctx, + struct panthor_group *group, + int new_csg_prio) +{ + struct panthor_device *ptdev =3D sched->ptdev; + struct panthor_fw_csg_iface *csg_iface; + struct panthor_csg_slot *csg_slot; + + if (group->csg_id < 0) + return; + + csg_iface =3D panthor_fw_get_csg_iface(ptdev, group->csg_id); + csg_slot =3D &sched->csg_slots[group->csg_id]; + + if (csg_slot->priority !=3D new_csg_prio) { + panthor_fw_update_reqs(csg_iface, endpoint_req, + CSG_EP_REQ_PRIORITY(new_csg_prio), + CSG_EP_REQ_PRIORITY_MASK); + csgs_upd_ctx_queue_reqs(ptdev, upd_ctx, group->csg_id, + csg_iface->output->ack ^ CSG_ENDPOINT_CONFIG, + CSG_ENDPOINT_CONFIG); + } +} + +static void +tick_ctx_schedule_group(struct panthor_scheduler *sched, + struct panthor_sched_tick_ctx *ctx, + struct panthor_csg_slots_upd_ctx *upd_ctx, + struct panthor_group *group, + int csg_id, int csg_prio) +{ + struct panthor_device *ptdev =3D sched->ptdev; + struct panthor_fw_csg_iface *csg_iface =3D panthor_fw_get_csg_iface(ptdev= , csg_id); + + group_bind_locked(group, csg_id); + csg_slot_prog_locked(ptdev, csg_id, csg_prio); + + csgs_upd_ctx_queue_reqs(ptdev, upd_ctx, csg_id, + group->state =3D=3D PANTHOR_CS_GROUP_SUSPENDED ? + CSG_STATE_RESUME : CSG_STATE_START, + CSG_STATE_MASK); + csgs_upd_ctx_queue_reqs(ptdev, upd_ctx, csg_id, + csg_iface->output->ack ^ CSG_ENDPOINT_CONFIG, + CSG_ENDPOINT_CONFIG); +} + static void tick_ctx_apply(struct panthor_scheduler *sched, struct panthor_sched_tick_= ctx *ctx) { struct panthor_group *group, *tmp; struct panthor_device *ptdev =3D sched->ptdev; - struct panthor_csg_slot *csg_slot; int prio, new_csg_prio =3D MAX_CSG_PRIO, i; u32 free_csg_slots =3D 0; struct panthor_csg_slots_upd_ctx upd_ctx; @@ -2282,42 +2360,12 @@ tick_ctx_apply(struct panthor_scheduler *sched, str= uct panthor_sched_tick_ctx *c for (prio =3D PANTHOR_CSG_PRIORITY_COUNT - 1; prio >=3D 0; prio--) { /* Suspend or terminate evicted groups. */ list_for_each_entry(group, &ctx->old_groups[prio], run_node) { - bool term =3D !group_can_run(group); - int csg_id =3D group->csg_id; - - if (drm_WARN_ON(&ptdev->base, csg_id < 0)) - continue; - - csg_slot =3D &sched->csg_slots[csg_id]; - csgs_upd_ctx_queue_reqs(ptdev, &upd_ctx, csg_id, - term ? CSG_STATE_TERMINATE : CSG_STATE_SUSPEND, - CSG_STATE_MASK); + tick_ctx_evict_group(sched, &upd_ctx, group); } =20 /* Update priorities on already running groups. */ list_for_each_entry(group, &ctx->groups[prio], run_node) { - struct panthor_fw_csg_iface *csg_iface; - int csg_id =3D group->csg_id; - - if (csg_id < 0) { - new_csg_prio--; - continue; - } - - csg_slot =3D &sched->csg_slots[csg_id]; - csg_iface =3D panthor_fw_get_csg_iface(ptdev, csg_id); - if (csg_slot->priority =3D=3D new_csg_prio) { - new_csg_prio--; - continue; - } - - panthor_fw_csg_endpoint_req_update(ptdev, csg_iface, - CSG_EP_REQ_PRIORITY(new_csg_prio), - CSG_EP_REQ_PRIORITY_MASK); - csgs_upd_ctx_queue_reqs(ptdev, &upd_ctx, csg_id, - csg_iface->output->ack ^ CSG_ENDPOINT_CONFIG, - CSG_ENDPOINT_CONFIG); - new_csg_prio--; + tick_ctx_reschedule_group(sched, &upd_ctx, group, new_csg_prio--); } } =20 @@ -2354,28 +2402,17 @@ tick_ctx_apply(struct panthor_scheduler *sched, str= uct panthor_sched_tick_ctx *c for (prio =3D PANTHOR_CSG_PRIORITY_COUNT - 1; prio >=3D 0; prio--) { list_for_each_entry(group, &ctx->groups[prio], run_node) { int csg_id =3D group->csg_id; - struct panthor_fw_csg_iface *csg_iface; + int csg_prio =3D new_csg_prio--; =20 - if (csg_id >=3D 0) { - new_csg_prio--; + if (csg_id >=3D 0) continue; - } =20 csg_id =3D ffs(free_csg_slots) - 1; if (drm_WARN_ON(&ptdev->base, csg_id < 0)) break; =20 - csg_iface =3D panthor_fw_get_csg_iface(ptdev, csg_id); - csg_slot =3D &sched->csg_slots[csg_id]; - group_bind_locked(group, csg_id); - csg_slot_prog_locked(ptdev, csg_id, new_csg_prio--); - csgs_upd_ctx_queue_reqs(ptdev, &upd_ctx, csg_id, - group->state =3D=3D PANTHOR_CS_GROUP_SUSPENDED ? - CSG_STATE_RESUME : CSG_STATE_START, - CSG_STATE_MASK); - csgs_upd_ctx_queue_reqs(ptdev, &upd_ctx, csg_id, - csg_iface->output->ack ^ CSG_ENDPOINT_CONFIG, - CSG_ENDPOINT_CONFIG); + tick_ctx_schedule_group(sched, ctx, &upd_ctx, group, csg_id, csg_prio); + free_csg_slots &=3D ~BIT(csg_id); } } --=20 2.43.0 From nobody Sat May 9 05:34:50 2026 Received: from foss.arm.com (foss.arm.com [217.140.110.172]) by smtp.subspace.kernel.org (Postfix) with ESMTP id 62F3E47F2E5; Tue, 5 May 2026 14:05:57 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=217.140.110.172 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1777989963; cv=none; b=lceAlGPm6V3oWOuedumKgwomG835TRHcbl1AFlCOHrNkm7C6DzxnVuAUb+q7LAA+qvF/HL6ejjPKp0M+2emR7QisN9Gi3p2Qxk99UR7TusKHFfFJlonP0CqHTTqx+GZfWQO/zkjtBrETJMXTHlSklOyhwWm7OS5aP3WSYYcnsto= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1777989963; c=relaxed/simple; bh=C/HPVhAFNazZLtwqgmXIczamjt4yPbAq/jYAjnd19+Y=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=bSXoTIWEASVmGADgrgCOTZFN2oe8v3HYTBcXbkQakvUZyXRNFQY5BhlxC6915+DP4zRBr2gU+QEeLqZYawiGgL5NmLqugWSs81WGw8AancV1D4Tcvztfm4DCBTrATnlMZE2N3qu+bJun+dzVpuPzBKpg2HD6gzrg45as83NLXS0= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=arm.com; spf=pass smtp.mailfrom=arm.com; dkim=pass (1024-bit key) header.d=arm.com header.i=@arm.com header.b=ueNYOVD9; arc=none smtp.client-ip=217.140.110.172 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=arm.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=arm.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=arm.com header.i=@arm.com header.b="ueNYOVD9" Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id 61DEC24C0; Tue, 5 May 2026 07:05:51 -0700 (PDT) Received: from e120398-lin.trondheim.arm.com (e120398-lin.trondheim.arm.com [10.42.46.160]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id 40ACC3F763; Tue, 5 May 2026 07:05:52 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=arm.com; s=foss; t=1777989956; bh=C/HPVhAFNazZLtwqgmXIczamjt4yPbAq/jYAjnd19+Y=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=ueNYOVD9kubk4sYtRy9DR4f5wtZSWKw5rtSXMp4ZLjhwgwh+PGLr/5j+wnjkNYR0e 43fSiim7+DW2GxEZ1FFtajXYSiMT0yg41SnB/LR8RK/+ubBqvc+l6kVEdkRcAOU9d0 bL17Dwe0tuiIVK5IbFF8rMoz4zVG6E1olq+7461A= From: Ketil Johnsen To: David Airlie , Simona Vetter , Maarten Lankhorst , Maxime Ripard , Thomas Zimmermann , Jonathan Corbet , Shuah Khan , Sumit Semwal , Benjamin Gaignard , Brian Starkey , John Stultz , "T.J. Mercier" , =?UTF-8?q?Christian=20K=C3=B6nig?= , Boris Brezillon , Steven Price , Liviu Dudau , Daniel Almeida , Alice Ryhl , Matthias Brugger , AngeloGioacchino Del Regno Cc: dri-devel@lists.freedesktop.org, linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org, linux-media@vger.kernel.org, linaro-mm-sig@lists.linaro.org, linux-arm-kernel@lists.infradead.org, linux-mediatek@lists.infradead.org, Ketil Johnsen Subject: [PATCH 6/8] drm/panthor: Explicit expansion of locked VM region Date: Tue, 5 May 2026 16:05:12 +0200 Message-ID: <20260505140516.1372388-7-ketil.johnsen@arm.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260505140516.1372388-1-ketil.johnsen@arm.com> References: <20260505140516.1372388-1-ketil.johnsen@arm.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Currently the panthor_vm_lock_region() function will implicitly expand an already locked VM region. This can be problematic because the caller do not reliably know if it needs to call panthor_vm_unlock_region() or not. Worth noting, there is currently no known issues with this as the code is written today. This change introduces panthor_vm_expand_region() which will only work if there is already a locked VM region. This again means that the original lock and unlock functions can work as a pair. This pairing is needed for subsequent protected memory changes. Signed-off-by: Ketil Johnsen --- drivers/gpu/drm/panthor/panthor_mmu.c | 69 +++++++++++++++++++-------- 1 file changed, 50 insertions(+), 19 deletions(-) diff --git a/drivers/gpu/drm/panthor/panthor_mmu.c b/drivers/gpu/drm/pantho= r/panthor_mmu.c index fc930ee158a52..07f54176ec1bf 100644 --- a/drivers/gpu/drm/panthor/panthor_mmu.c +++ b/drivers/gpu/drm/panthor/panthor_mmu.c @@ -1701,15 +1701,36 @@ static int panthor_vm_lock_region(struct panthor_vm= *vm, u64 start, u64 size) struct panthor_device *ptdev =3D vm->ptdev; int ret =3D 0; =20 - /* sm_step_remap() can call panthor_vm_lock_region() to account for - * the wider unmap needed when doing a partial huge page unamp. We - * need to ignore the lock if it's already part of the locked region. - */ - if (start >=3D vm->locked_region.start && - start + size <=3D vm->locked_region.start + vm->locked_region.size) - return 0; + if (drm_WARN_ON(&ptdev->base, vm->locked_region.size)) + return -EINVAL; + + mutex_lock(&ptdev->mmu->as.slots_lock); + if (vm->as.id >=3D 0 && size) { + /* Lock the region that needs to be updated */ + gpu_write64(ptdev, AS_LOCKADDR(vm->as.id), + pack_region_range(ptdev, &start, &size)); + + /* If the lock succeeded, update the locked_region info. */ + ret =3D as_send_cmd_and_wait(ptdev, vm->as.id, AS_COMMAND_LOCK); + } =20 - /* sm_step_remap() may need a locked region that isn't a strict superset + if (!ret) { + vm->locked_region.start =3D start; + vm->locked_region.size =3D size; + } + mutex_unlock(&ptdev->mmu->as.slots_lock); + + return ret; +} + +static int panthor_vm_expand_region(struct panthor_vm *vm, u64 start, u64 = size) +{ + struct panthor_device *ptdev =3D vm->ptdev; + u64 end; + int ret =3D 0; + + /* This function is here to handle the following case: + * sm_step_remap() may need a locked region that isn't a strict superset * of the original one because of having to extend unmap boundaries beyond * it to deal with partial unmaps of transparent huge pages. What we want * in those cases is to lock the union of both regions. The new region mu= st @@ -1717,16 +1738,24 @@ static int panthor_vm_lock_region(struct panthor_vm= *vm, u64 start, u64 size) * boundaries in a remap operation can only shift up or down respectively, * but never otherwise. */ - if (vm->locked_region.size) { - u64 end =3D max(vm->locked_region.start + vm->locked_region.size, - start + size); =20 - drm_WARN_ON_ONCE(&vm->ptdev->base, (start + size <=3D vm->locked_region.= start) || - (start >=3D vm->locked_region.start + vm->locked_region.size)); + /* This function can only expand an already locked region */ + if (drm_WARN_ON(&ptdev->base, !vm->locked_region.size)) + return -EINVAL; =20 - start =3D min(start, vm->locked_region.start); - size =3D end - start; - } + /* Early out if requested range is already locked */ + if (start >=3D vm->locked_region.start && + start + size <=3D vm->locked_region.start + vm->locked_region.size) + return 0; + + end =3D max(vm->locked_region.start + vm->locked_region.size, + start + size); + + drm_WARN_ON_ONCE(&ptdev->base, (start + size <=3D vm->locked_region.start= ) || + (start >=3D vm->locked_region.start + vm->locked_region.size)); + + start =3D min(start, vm->locked_region.start); + size =3D end - start; =20 mutex_lock(&ptdev->mmu->as.slots_lock); if (vm->as.id >=3D 0 && size) { @@ -2252,11 +2281,13 @@ static int panthor_gpuva_sm_step_remap(struct drm_g= puva_op *op, unmap_hugepage_align(&op->remap, &unmap_start, &unmap_range); =20 /* If the range changed, we might have to lock a wider region to guarantee - * atomicity. panthor_vm_lock_region() bails out early if the new region - * is already part of the locked region, so no need to do this check here. + * atomicity. */ if (!unmap_vma->evicted) { - panthor_vm_lock_region(vm, unmap_start, unmap_range); + ret =3D panthor_vm_expand_region(vm, unmap_start, unmap_range); + if (ret) + return ret; + panthor_vm_unmap_pages(vm, unmap_start, unmap_range); } =20 --=20 2.43.0 From nobody Sat May 9 05:34:50 2026 Received: from foss.arm.com (foss.arm.com [217.140.110.172]) by smtp.subspace.kernel.org (Postfix) with ESMTP id 9C5E631F999; Tue, 5 May 2026 14:06:02 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=217.140.110.172 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1777989965; cv=none; b=tRkzIjXmIcqUlrxw0fvJ4jaA6eMA508hkArszJQZdcsd5Ye5SF6aJn9oOY/w+1NwDcyFLIseoFtjpTkiIPmuVr63s1IALPSfWasqYImRHCD+dTJ/jdM+DsAJoVzRwwcOOaNPcAUSEvF0SdffP+GIJRbpGJ+ZbBn/FgyiV1N2PFw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1777989965; c=relaxed/simple; bh=Zwi3WoIZECOgNRRwthXmM8rbKrBdCiBAc6flCCLl+ac=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=GI14xTeVWWcNVHlkYCLXZL41s4nZgaCnnUd4i/pPb7sMnlM6M6BvKZ+aFEiAOsRcZoSJKSh76hRHorCeOd6t5AJirF/o1ccTk2p54EQLHgEvlmqzNKFZxnteflwBesc9WJnhvWvkoCr5od2kcZRTm9IhSO61xY80/dja4Nwnpvc= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=arm.com; spf=pass smtp.mailfrom=arm.com; dkim=pass (1024-bit key) header.d=arm.com header.i=@arm.com header.b=PINFyNvo; arc=none smtp.client-ip=217.140.110.172 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=arm.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=arm.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=arm.com header.i=@arm.com header.b="PINFyNvo" Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id CD75C2681; Tue, 5 May 2026 07:05:56 -0700 (PDT) Received: from e120398-lin.trondheim.arm.com (e120398-lin.trondheim.arm.com [10.42.46.160]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id 392773F763; Tue, 5 May 2026 07:05:57 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=arm.com; s=foss; t=1777989962; bh=Zwi3WoIZECOgNRRwthXmM8rbKrBdCiBAc6flCCLl+ac=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=PINFyNvoT8+uh5kakncZS923wjjpuDPi8rzzahnzQE4FEKrBZcB1DxUJw067ICE4E +KMihhgO3w7qbq3CPe4XBqLFq8Kj6oVrEKE+ALOZHWRb8xyMY6YWJ07bFjb+WLWoG8 p6TeRjMJz7rWUj2t+XRSQOPFyPYtk6PgKK9LBAQ8= From: Ketil Johnsen To: David Airlie , Simona Vetter , Maarten Lankhorst , Maxime Ripard , Thomas Zimmermann , Jonathan Corbet , Shuah Khan , Sumit Semwal , Benjamin Gaignard , Brian Starkey , John Stultz , "T.J. Mercier" , =?UTF-8?q?Christian=20K=C3=B6nig?= , Boris Brezillon , Steven Price , Liviu Dudau , Daniel Almeida , Alice Ryhl , Matthias Brugger , AngeloGioacchino Del Regno Cc: dri-devel@lists.freedesktop.org, linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org, linux-media@vger.kernel.org, linaro-mm-sig@lists.linaro.org, linux-arm-kernel@lists.infradead.org, linux-mediatek@lists.infradead.org, Florent Tomasin , Paul Toadere , Samuel Percival , Ketil Johnsen Subject: [PATCH 7/8] drm/panthor: Add support for entering and exiting protected mode Date: Tue, 5 May 2026 16:05:13 +0200 Message-ID: <20260505140516.1372388-8-ketil.johnsen@arm.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260505140516.1372388-1-ketil.johnsen@arm.com> References: <20260505140516.1372388-1-ketil.johnsen@arm.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Florent Tomasin This patch modifies the Panthor driver code to allow handling of the GPU HW protected mode enter and exit. The logic added by this patch includes: - the mechanisms needed for entering and exiting protected mode. - the handling of protected mode IRQs and FW interactions. - the scheduler changes needed to decide when to enter protected mode based on CSG scheduling. Note that the submission of a protected mode jobs are done from the user space. The following is a summary of how protected mode is entered and exited: - When the GPU detects a protected mode job needs to be executed, an IRQ is sent to the CPU to notify the kernel driver that the job is blocked until the GPU has entered protected mode. The entering of protected mode is controlled by the kernel driver. - The Mali Panthor CSF driver will schedule a tick and evaluate which CS in the CSG to schedule on slot needs protected mode. If the priority of the CSG is not sufficiently high, the protected mode job will not progress until the CSG is scheduled at top priority. - The Panthor scheduler notifies the GPU that the blocked protected jobs will soon be able to progress. - Once all CSG and CS slots are updated, the scheduler requests the GPU to enter protected mode and waits for it to be acknowledged. - If successful, all protected mode jobs will resume execution while normal mode jobs block until the GPU exits protected mode, or the kernel driver rotates the CSGs and forces the GPU to exit protected mode. - If unsuccessful, the scheduler will request a GPU reset. - When a protected mode job is suspended as a result of the CSGs rotation, the GPU will send an IRQ to the CPU to notify that the protected mode job needs to resume. This sequence will continue so long the user space is submitting protected mode jobs. Signed-off-by: Florent Tomasin Co-developed-by: Paul Toadere Signed-off-by: Paul Toadere Co-developed-by: Samuel Percival Signed-off-by: Samuel Percival Co-developed-by: Ketil Johnsen Signed-off-by: Ketil Johnsen --- drivers/gpu/drm/panthor/panthor_device.c | 1 + drivers/gpu/drm/panthor/panthor_device.h | 9 + drivers/gpu/drm/panthor/panthor_fw.c | 86 ++++++++- drivers/gpu/drm/panthor/panthor_fw.h | 5 + drivers/gpu/drm/panthor/panthor_gpu.c | 14 +- drivers/gpu/drm/panthor/panthor_gpu.h | 6 + drivers/gpu/drm/panthor/panthor_mmu.c | 10 + drivers/gpu/drm/panthor/panthor_sched.c | 224 +++++++++++++++++++++-- 8 files changed, 339 insertions(+), 16 deletions(-) diff --git a/drivers/gpu/drm/panthor/panthor_device.c b/drivers/gpu/drm/pan= thor/panthor_device.c index 3a5cdfa99e5fe..449f17b0f4c5c 100644 --- a/drivers/gpu/drm/panthor/panthor_device.c +++ b/drivers/gpu/drm/panthor/panthor_device.c @@ -207,6 +207,7 @@ int panthor_device_init(struct panthor_device *ptdev) =20 ptdev->soc_data =3D of_device_get_match_data(ptdev->base.dev); =20 + init_rwsem(&ptdev->protm.lock); init_completion(&ptdev->unplug.done); ret =3D drmm_mutex_init(&ptdev->base, &ptdev->unplug.lock); if (ret) diff --git a/drivers/gpu/drm/panthor/panthor_device.h b/drivers/gpu/drm/pan= thor/panthor_device.h index d51fec97fc5fa..ebeec45cf60a1 100644 --- a/drivers/gpu/drm/panthor/panthor_device.h +++ b/drivers/gpu/drm/panthor/panthor_device.h @@ -334,6 +334,15 @@ struct panthor_device { struct { /** @heap: Pointer to the protected heap */ struct dma_heap *heap; + + /** + * @lock: Lock to prevent VM operations during protected mode. + * + * The MMU will not execute commands when the GPU is in + * protected mode, so we use this RW lock to sync access + * between VM_BIND and GPU protected mode. + */ + struct rw_semaphore lock; } protm; }; =20 diff --git a/drivers/gpu/drm/panthor/panthor_fw.c b/drivers/gpu/drm/panthor= /panthor_fw.c index 1aba29b9779b6..281556530ddab 100644 --- a/drivers/gpu/drm/panthor/panthor_fw.c +++ b/drivers/gpu/drm/panthor/panthor_fw.c @@ -1057,7 +1057,9 @@ static void panthor_fw_init_global_iface(struct panth= or_device *ptdev) GLB_CFG_PROGRESS_TIMER | GLB_CFG_POWEROFF_TIMER | GLB_IDLE_EN | - GLB_IDLE; + GLB_IDLE | + GLB_PROTM_ENTER | + GLB_PROTM_EXIT; =20 if (panthor_fw_has_glb_state(ptdev)) glb_iface->input->ack_irq_mask |=3D GLB_STATE_MASK; @@ -1456,6 +1458,88 @@ static void panthor_fw_ping_work(struct work_struct = *work) } } =20 +int panthor_fw_protm_enter(struct panthor_device *ptdev) +{ + struct panthor_fw_global_iface *glb_iface; + u32 acked; + u32 status; + int ret; + + down_write(&ptdev->protm.lock); + + glb_iface =3D panthor_fw_get_glb_iface(ptdev); + + panthor_fw_toggle_reqs(glb_iface, req, ack, GLB_PROTM_ENTER); + gpu_write(ptdev, CSF_DOORBELL(CSF_GLB_DOORBELL_ID), 1); + + ret =3D panthor_fw_glb_wait_acks(ptdev, GLB_PROTM_ENTER, &acked, 4000); + if (ret) { + drm_err(&ptdev->base, "Wait for FW protected mode acknowledge timed out"= ); + up_write(&ptdev->protm.lock); + return ret; + } + + /* Wait for the GPU to actually enter protected mode. + * There would be some time gap between FW sending the + * ACK for GLB_PROTM_ENTER and GPU entering protected mode. + */ + if (gpu_read_poll_timeout(ptdev, GPU_STATUS, status, + (status & GPU_STATUS_PROTM_ACTIVE) || + ((glb_iface->input->req ^ glb_iface->output->ack) & + GLB_PROTM_EXIT), + 10, 500000)) { + drm_err(&ptdev->base, "Wait for GPU protected mode enter timed out"); + ret =3D -ETIMEDOUT; + } + + up_write(&ptdev->protm.lock); + + return ret; +} + +void panthor_fw_protm_exit(struct panthor_device *ptdev) +{ + struct panthor_fw_global_iface *glb_iface =3D panthor_fw_get_glb_iface(pt= dev); + + /* Acknowledge the protm exit. */ + panthor_fw_update_reqs(glb_iface, req, glb_iface->output->ack, GLB_PROTM_= EXIT); +} + +int panthor_fw_protm_exit_wait_event_timeout(struct panthor_device *ptdev) +{ + struct panthor_fw_global_iface *glb_iface =3D panthor_fw_get_glb_iface(pt= dev); + int ret =3D 0; + + /* Send PING request to force an exit */ + panthor_fw_toggle_reqs(glb_iface, req, ack, GLB_PING); + gpu_write(ptdev, CSF_DOORBELL(CSF_GLB_DOORBELL_ID), 1); + + ret =3D wait_event_timeout(ptdev->fw->req_waitqueue, + !(gpu_read(ptdev, GPU_STATUS) & GPU_STATUS_PROTM_ACTIVE), + msecs_to_jiffies(500)); + + if (!ret) { + drm_err(&ptdev->base, "Wait for forced protected mode exit timed out"); + panthor_device_schedule_reset(ptdev); + return -ETIMEDOUT; + } + + return 0; +} + +void panthor_fw_protm_exit_sync(struct panthor_device *ptdev) +{ + u32 status; + + /* Busy-wait (5ms) for FW to exit protected mode on its own */ + if (!gpu_read_poll_timeout(ptdev, GPU_STATUS, status, + !(status & GPU_STATUS_PROTM_ACTIVE), 10, + 5000)) + return; + + panthor_fw_protm_exit_wait_event_timeout(ptdev); +} + /** * panthor_fw_init() - Initialize FW related data. * @ptdev: Device. diff --git a/drivers/gpu/drm/panthor/panthor_fw.h b/drivers/gpu/drm/panthor= /panthor_fw.h index 0cf3761abf789..cf6193eadea12 100644 --- a/drivers/gpu/drm/panthor/panthor_fw.h +++ b/drivers/gpu/drm/panthor/panthor_fw.h @@ -502,6 +502,11 @@ int panthor_fw_glb_wait_acks(struct panthor_device *pt= dev, u32 req_mask, u32 *ac =20 void panthor_fw_ring_csg_doorbells(struct panthor_device *ptdev, u32 csg_s= lot); =20 +int panthor_fw_protm_enter(struct panthor_device *ptdev); +void panthor_fw_protm_exit(struct panthor_device *ptdev); +void panthor_fw_protm_exit_sync(struct panthor_device *ptdev); +int panthor_fw_protm_exit_wait_event_timeout(struct panthor_device *ptdev); + struct panthor_kernel_bo * panthor_fw_alloc_queue_iface_mem(struct panthor_device *ptdev, struct panthor_fw_ringbuf_input_iface **input, diff --git a/drivers/gpu/drm/panthor/panthor_gpu.c b/drivers/gpu/drm/pantho= r/panthor_gpu.c index 2ab444ee8c710..e93042eaf3fc8 100644 --- a/drivers/gpu/drm/panthor/panthor_gpu.c +++ b/drivers/gpu/drm/panthor/panthor_gpu.c @@ -100,8 +100,11 @@ static void panthor_gpu_irq_handler(struct panthor_dev= ice *ptdev, u32 status) fault_status, panthor_exception_name(ptdev, fault_status & 0xFF), address); } - if (status & GPU_IRQ_PROTM_FAULT) + if (status & GPU_IRQ_PROTM_FAULT) { drm_warn(&ptdev->base, "GPU Fault in protected mode\n"); + panthor_gpu_disable_protm_fault_interrupt(ptdev); + panthor_device_schedule_reset(ptdev); + } =20 spin_lock(&ptdev->gpu->reqs_lock); if (status & ptdev->gpu->pending_reqs) { @@ -367,6 +370,10 @@ int panthor_gpu_soft_reset(struct panthor_device *ptde= v) unsigned long flags; =20 spin_lock_irqsave(&ptdev->gpu->reqs_lock, flags); + + /** Re-enable the protm_irq_fault when reset is complete */ + ptdev->gpu->irq.mask |=3D GPU_IRQ_PROTM_FAULT; + if (!drm_WARN_ON(&ptdev->base, ptdev->gpu->pending_reqs & GPU_IRQ_RESET_COMPLETED)) { ptdev->gpu->pending_reqs |=3D GPU_IRQ_RESET_COMPLETED; @@ -427,3 +434,8 @@ void panthor_gpu_resume(struct panthor_device *ptdev) panthor_hw_l2_power_on(ptdev); } =20 +void panthor_gpu_disable_protm_fault_interrupt(struct panthor_device *ptde= v) +{ + scoped_guard(spinlock_irqsave, &ptdev->gpu->reqs_lock) + ptdev->gpu->irq.mask &=3D ~GPU_IRQ_PROTM_FAULT; +} diff --git a/drivers/gpu/drm/panthor/panthor_gpu.h b/drivers/gpu/drm/pantho= r/panthor_gpu.h index 12c263a399281..ca66c73f543e6 100644 --- a/drivers/gpu/drm/panthor/panthor_gpu.h +++ b/drivers/gpu/drm/panthor/panthor_gpu.h @@ -54,4 +54,10 @@ int panthor_gpu_soft_reset(struct panthor_device *ptdev); void panthor_gpu_power_changed_off(struct panthor_device *ptdev); int panthor_gpu_power_changed_on(struct panthor_device *ptdev); =20 +/** + * panthor_gpu_disable_protm_fault_interrupt() - Disable GPU_PROTECTED_FAU= LT interrupt + * @ptdev: Device. + */ +void panthor_gpu_disable_protm_fault_interrupt(struct panthor_device *ptde= v); + #endif diff --git a/drivers/gpu/drm/panthor/panthor_mmu.c b/drivers/gpu/drm/pantho= r/panthor_mmu.c index 07f54176ec1bf..702f537905b56 100644 --- a/drivers/gpu/drm/panthor/panthor_mmu.c +++ b/drivers/gpu/drm/panthor/panthor_mmu.c @@ -31,6 +31,7 @@ #include =20 #include "panthor_device.h" +#include "panthor_fw.h" #include "panthor_gem.h" #include "panthor_gpu.h" #include "panthor_heap.h" @@ -1704,8 +1705,12 @@ static int panthor_vm_lock_region(struct panthor_vm = *vm, u64 start, u64 size) if (drm_WARN_ON(&ptdev->base, vm->locked_region.size)) return -EINVAL; =20 + down_read(&ptdev->protm.lock); + mutex_lock(&ptdev->mmu->as.slots_lock); if (vm->as.id >=3D 0 && size) { + panthor_fw_protm_exit_sync(ptdev); + /* Lock the region that needs to be updated */ gpu_write64(ptdev, AS_LOCKADDR(vm->as.id), pack_region_range(ptdev, &start, &size)); @@ -1720,6 +1725,9 @@ static int panthor_vm_lock_region(struct panthor_vm *= vm, u64 start, u64 size) } mutex_unlock(&ptdev->mmu->as.slots_lock); =20 + if (ret) + up_read(&ptdev->protm.lock); + return ret; } =20 @@ -1805,6 +1813,8 @@ static void panthor_vm_unlock_region(struct panthor_v= m *vm) vm->locked_region.start =3D 0; vm->locked_region.size =3D 0; mutex_unlock(&ptdev->mmu->as.slots_lock); + + up_read(&ptdev->protm.lock); } =20 static void panthor_mmu_irq_handler(struct panthor_device *ptdev, u32 stat= us) diff --git a/drivers/gpu/drm/panthor/panthor_sched.c b/drivers/gpu/drm/pant= hor/panthor_sched.c index 987072bd867c4..acb04250c7def 100644 --- a/drivers/gpu/drm/panthor/panthor_sched.c +++ b/drivers/gpu/drm/panthor/panthor_sched.c @@ -308,6 +308,15 @@ struct panthor_scheduler { */ struct list_head stopped_groups; } reset; + + /** @protm: Protected mode related fields. */ + struct { + /** @protected_mode: True if GPU is in protected mode. */ + bool protected_mode; + + /** @active_group: The active protected group. */ + struct panthor_group *active_group; + } protm; }; =20 /** @@ -570,6 +579,16 @@ struct panthor_group { /** @fatal_queues: Bitmask reflecting the queues that hit a fatal excepti= on. */ u32 fatal_queues; =20 + /** + * @protm_pending_queues: Bitmask reflecting the queues that are waiting + * on a CS_PROTM_PENDING. + * + * The GPU will set the bit associated to the queue pending protected mode + * when a PROT_REGION command is executing or when trying to resume previ= ously + * suspended protected mode jobs. + */ + u32 protm_pending_queues; + /** @tiler_oom: Mask of queues that have a tiler OOM event to process. */ atomic_t tiler_oom; =20 @@ -1176,6 +1195,7 @@ queue_resume_timeout(struct panthor_queue *queue) * @ptdev: Device. * @csg_id: Group slot ID. * @cs_id: Queue slot ID. + * @protm_ack: Acknowledge pending protected mode queues * * Program a queue slot with the queue information so things can start bei= ng * executed on this queue. @@ -1472,6 +1492,34 @@ csg_slot_prog_locked(struct panthor_device *ptdev, u= 32 csg_id, u32 priority) return 0; } =20 +static void +cs_slot_process_protm_pending_event_locked(struct panthor_device *ptdev, + u32 csg_id, u32 cs_id) +{ + struct panthor_scheduler *sched =3D ptdev->scheduler; + struct panthor_csg_slot *csg_slot =3D &sched->csg_slots[csg_id]; + struct panthor_group *group =3D csg_slot->group; + + lockdep_assert_held(&sched->lock); + + if (!group) + return; + + /* No protected memory heap, a user space program tried to + * submit a protected mode jobs resulting in the GPU raising + * a CS_PROTM_PENDING request. + * + * This scenario is invalid and the protected mode jobs must + * not be allowed to progress. + */ + if (!ptdev->protm.heap) + return; + + group->protm_pending_queues |=3D BIT(cs_id); + + sched_queue_delayed_work(sched, tick, 0); +} + static void cs_slot_process_fatal_event_locked(struct panthor_device *ptdev, u32 csg_id, u32 cs_id) @@ -1718,6 +1766,9 @@ static bool cs_slot_process_irq_locked(struct panthor= _device *ptdev, if (events & CS_TILER_OOM) cs_slot_process_tiler_oom_event_locked(ptdev, csg_id, cs_id); =20 + if (events & CS_PROTM_PENDING) + cs_slot_process_protm_pending_event_locked(ptdev, csg_id, cs_id); + /* We don't acknowledge the TILER_OOM event since its handling is * deferred to a separate work. */ @@ -1848,6 +1899,17 @@ static void sched_process_idle_event_locked(struct p= anthor_device *ptdev) sched_queue_delayed_work(ptdev->scheduler, tick, 0); } =20 +static void sched_process_protm_exit_event_locked(struct panthor_device *p= tdev) +{ + lockdep_assert_held(&ptdev->scheduler->lock); + + /* Acknowledge the protm exit and schedule a tick. */ + panthor_fw_protm_exit(ptdev); + sched_queue_delayed_work(ptdev->scheduler, tick, 0); + ptdev->scheduler->protm.protected_mode =3D false; + ptdev->scheduler->protm.active_group =3D NULL; +} + /** * sched_process_global_irq_locked() - Process the scheduling part of a gl= obal IRQ * @ptdev: Device. @@ -1863,6 +1925,9 @@ static void sched_process_global_irq_locked(struct pa= nthor_device *ptdev) ack =3D READ_ONCE(glb_iface->output->ack); evts =3D (req ^ ack) & GLB_EVT_MASK; =20 + if (evts & GLB_PROTM_EXIT) + sched_process_protm_exit_event_locked(ptdev); + if (evts & GLB_IDLE) sched_process_idle_event_locked(ptdev); } @@ -1872,23 +1937,71 @@ static void process_fw_events_work(struct work_stru= ct *work) struct panthor_scheduler *sched =3D container_of(work, struct panthor_sch= eduler, fw_events_work); u32 events =3D atomic_xchg(&sched->fw_events, 0); + u32 csg_events =3D events & ~JOB_INT_GLOBAL_IF; struct panthor_device *ptdev =3D sched->ptdev; =20 mutex_lock(&sched->lock); =20 + while (csg_events) { + u32 csg_id =3D ffs(csg_events) - 1; + + sched_process_csg_irq_locked(ptdev, csg_id); + csg_events &=3D ~BIT(csg_id); + } + if (events & JOB_INT_GLOBAL_IF) { sched_process_global_irq_locked(ptdev); events &=3D ~JOB_INT_GLOBAL_IF; } =20 - while (events) { - u32 csg_id =3D ffs(events) - 1; + mutex_unlock(&sched->lock); +} =20 - sched_process_csg_irq_locked(ptdev, csg_id); - events &=3D ~BIT(csg_id); +static void handle_protm_fault(struct panthor_device *ptdev) +{ + struct panthor_scheduler *sched =3D ptdev->scheduler; + u32 csg_id; + struct panthor_group *protm_group; + + guard(mutex)(&sched->lock); + + if (!sched->protm.protected_mode) + return; + + protm_group =3D sched->protm.active_group; + + if (drm_WARN_ON(&ptdev->base, !protm_group)) + return; + + /* Group will be terminated by the device reset */ + protm_group->fatal_queues |=3D GENMASK(protm_group->queue_count - 1, 0); + + if (!panthor_fw_protm_exit_wait_event_timeout(ptdev)) + goto cleanup_protm; + + /** + * GPU failed to exit protected mode. Mark all non-protected mode CSGs + * as suspended so that they are unaffected by the GPU reset. + */ + + for (csg_id =3D 0; csg_id < sched->csg_slot_count; csg_id++) { + struct panthor_group *group =3D sched->csg_slots[csg_id].group; + + if (!group || group =3D=3D protm_group) + continue; + + group->state =3D PANTHOR_CS_GROUP_SUSPENDED; + + group_unbind_locked(group); + + list_move(&group->run_node, group_is_idle(group) ? + &sched->groups.idle[group->priority] : + &sched->groups.runnable[group->priority]); } =20 - mutex_unlock(&sched->lock); +cleanup_protm: + sched->protm.protected_mode =3D false; + sched->protm.active_group =3D NULL; } =20 /** @@ -2029,6 +2142,7 @@ struct panthor_sched_tick_ctx { bool immediate_tick; bool stop_tick; u32 csg_upd_failed_mask; + struct panthor_group *protm_group; }; =20 static bool @@ -2299,6 +2413,7 @@ tick_ctx_evict_group(struct panthor_scheduler *sched, =20 static void tick_ctx_reschedule_group(struct panthor_scheduler *sched, + struct panthor_sched_tick_ctx *ctx, struct panthor_csg_slots_upd_ctx *upd_ctx, struct panthor_group *group, int new_csg_prio) @@ -2321,6 +2436,30 @@ tick_ctx_reschedule_group(struct panthor_scheduler *= sched, csg_iface->output->ack ^ CSG_ENDPOINT_CONFIG, CSG_ENDPOINT_CONFIG); } + + if (ctx->protm_group =3D=3D group) { + for (u32 q =3D 0; q < group->queue_count; q++) { + struct panthor_fw_cs_iface *cs_iface; + + if (!(group->protm_pending_queues & BIT(q))) + continue; + + cs_iface =3D panthor_fw_get_cs_iface(ptdev, group->csg_id, q); + panthor_fw_update_reqs(cs_iface, req, cs_iface->output->ack, + CS_PROTM_PENDING); + } + + panthor_fw_toggle_reqs(csg_iface, doorbell_req, doorbell_ack, + group->protm_pending_queues); + csgs_upd_ctx_ring_doorbell(upd_ctx, group->csg_id); + group->protm_pending_queues =3D 0; + + /* + * We only allow one protected group to run at same time, + * as it makes it easier to handle faults in protected mode. + */ + sched->protm.active_group =3D group; + } } =20 static void @@ -2336,6 +2475,17 @@ tick_ctx_schedule_group(struct panthor_scheduler *sc= hed, group_bind_locked(group, csg_id); csg_slot_prog_locked(ptdev, csg_id, csg_prio); =20 + /* If the group was waiting for protected mode before suspension, + * and the tick context enters this mode, it should be serviced + * immediately because the slot reset should have set the + * CS_PROTM_PENDING bit to zero, and cs_prog_slot_locked() sets it to + * zero too. + * It's not clear if we will get a new CS_PROTM_PENDING event in that + * case, but it should be safe either way. + */ + if (group->protm_pending_queues && ctx->protm_group) + group->protm_pending_queues =3D 0; + csgs_upd_ctx_queue_reqs(ptdev, upd_ctx, csg_id, group->state =3D=3D PANTHOR_CS_GROUP_SUSPENDED ? CSG_STATE_RESUME : CSG_STATE_START, @@ -2365,7 +2515,7 @@ tick_ctx_apply(struct panthor_scheduler *sched, struc= t panthor_sched_tick_ctx *c =20 /* Update priorities on already running groups. */ list_for_each_entry(group, &ctx->groups[prio], run_node) { - tick_ctx_reschedule_group(sched, &upd_ctx, group, new_csg_prio--); + tick_ctx_reschedule_group(sched, ctx, &upd_ctx, group, new_csg_prio--); } } =20 @@ -2457,6 +2607,15 @@ tick_ctx_apply(struct panthor_scheduler *sched, stru= ct panthor_sched_tick_ctx *c =20 sched->used_csg_slot_count =3D ctx->group_count; sched->might_have_idle_groups =3D ctx->idle_group_count > 0; + + if (ctx->protm_group) { + ret =3D panthor_fw_protm_enter(ptdev); + if (ret) { + panthor_device_schedule_reset(ptdev); + ctx->csg_upd_failed_mask =3D U32_MAX; + } + sched->protm.protected_mode =3D true; + } } =20 static u64 @@ -2490,7 +2649,7 @@ static void tick_work(struct work_struct *work) u64 resched_target =3D sched->resched_target; u64 remaining_jiffies =3D 0, resched_delay; u64 now =3D get_jiffies_64(); - int prio, ret, cookie; + int prio, protm_prio, ret, cookie; bool full_tick; =20 if (!drm_dev_enter(&ptdev->base, &cookie)) @@ -2564,14 +2723,49 @@ static void tick_work(struct work_struct *work) } } =20 + /* Check if the highest priority group want to switch to protected mode */ + for (protm_prio =3D PANTHOR_CSG_PRIORITY_COUNT - 1; protm_prio >=3D 0; pr= otm_prio--) { + struct panthor_group *group; + + group =3D list_first_entry_or_null(&ctx.groups[protm_prio], + struct panthor_group, + run_node); + if (group) { + ctx.protm_group =3D group; + break; + } + } + /* If we have free CSG slots left, pick idle groups */ - for (prio =3D PANTHOR_CSG_PRIORITY_COUNT - 1; - prio >=3D 0 && !tick_ctx_is_full(sched, &ctx); - prio--) { - /* Check the old_group queue first to avoid reprogramming the slots */ - tick_ctx_pick_groups_from_list(sched, &ctx, &ctx.old_groups[prio], false= , true); - tick_ctx_pick_groups_from_list(sched, &ctx, &sched->groups.idle[prio], - false, false); + if (ctx.protm_group) { + /* Pick only idle groups with equal or lower priority than the + * group triggering protected mode. Do not bother picking + * unscheduled idle groups. + */ + for (prio =3D protm_prio; + prio >=3D 0 && !tick_ctx_is_full(sched, &ctx); + prio--) + tick_ctx_pick_groups_from_list(sched, &ctx, + &ctx.old_groups[prio], + false, true); + } else { + /* No switch to protected, just pick any idle group according + * to priority + */ + for (prio =3D PANTHOR_CSG_PRIORITY_COUNT - 1; + prio >=3D 0 && !tick_ctx_is_full(sched, &ctx); + prio--) { + /* Check the old_group queue first to avoid + * reprogramming the slots + */ + tick_ctx_pick_groups_from_list(sched, &ctx, + &ctx.old_groups[prio], + false, true); + tick_ctx_pick_groups_from_list(sched, &ctx, + &sched->groups.idle[prio], + false, false); + } + } =20 tick_ctx_apply(sched, &ctx); @@ -2993,6 +3187,8 @@ void panthor_sched_pre_reset(struct panthor_device *p= tdev) cancel_work_sync(&sched->sync_upd_work); cancel_delayed_work_sync(&sched->tick_work); =20 + handle_protm_fault(ptdev); + panthor_sched_suspend(ptdev); =20 /* Stop all groups that might still accept jobs, so we don't get passed --=20 2.43.0 From nobody Sat May 9 05:34:50 2026 Received: from foss.arm.com (foss.arm.com [217.140.110.172]) by smtp.subspace.kernel.org (Postfix) with ESMTP id CFFDC47ECDF; Tue, 5 May 2026 14:06:07 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=217.140.110.172 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1777989969; cv=none; b=ott1SZnW9qGpfg/ATf3ABOiiGjTNuR91H8HFka2CCDbosHJQLAHyuAkF8tSEa1B3x0NHUF8Omqjm7aVq4vkXvSxTbz6uqOkMhO2RGLAGUA17OHdviHG/qKOWUTTZZzl8pkuWP6uHumxa13XqfdQQp+hKOdyOyosNZXU/6sWqnOI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1777989969; c=relaxed/simple; bh=RZvyoxTCxXRjVJaFXhiWOVuOJVHUHB2e/Xmp4YZCn8k=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=LoDjV2H2RHkBUC5JrSvgVCe7zy0a/f4YfLWCFuHIyWNxJpi4b5ktlxY2jMFVOd6/LGhYJF52okcOm1uDa7XwR2vFwOsj6xTMffNMwPepqaZquh+TVrWssW1ThAUkOA8KaPRk+DUpVTSqYK8N5Cj4412WMygNi8eemqjgacVO+Hg= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=arm.com; spf=pass smtp.mailfrom=arm.com; dkim=pass (1024-bit key) header.d=arm.com header.i=@arm.com header.b=Zo2NNC6U; arc=none smtp.client-ip=217.140.110.172 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=arm.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=arm.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=arm.com header.i=@arm.com header.b="Zo2NNC6U" Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id C37E224C0; Tue, 5 May 2026 07:06:01 -0700 (PDT) Received: from e120398-lin.trondheim.arm.com (e120398-lin.trondheim.arm.com [10.42.46.160]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id A00C33F763; Tue, 5 May 2026 07:06:02 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=arm.com; s=foss; t=1777989967; bh=RZvyoxTCxXRjVJaFXhiWOVuOJVHUHB2e/Xmp4YZCn8k=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=Zo2NNC6UTvAbVFwC6NXIU/sC+mHzAOIOZIxbnV5hedjZH7gPgueOaTT6IBChwbSgT 8sP3zf5Xj5vAbgFzjbYix1ygPjPiNZkPJUaOZtbJlizTjmDYwnYpJFvcu1+pSQ0b2c OOO9XZ8qMNcTPtyY4YyFteYVruZ33shx+qExV9uA= From: Ketil Johnsen To: David Airlie , Simona Vetter , Maarten Lankhorst , Maxime Ripard , Thomas Zimmermann , Jonathan Corbet , Shuah Khan , Sumit Semwal , Benjamin Gaignard , Brian Starkey , John Stultz , "T.J. Mercier" , =?UTF-8?q?Christian=20K=C3=B6nig?= , Boris Brezillon , Steven Price , Liviu Dudau , Daniel Almeida , Alice Ryhl , Matthias Brugger , AngeloGioacchino Del Regno Cc: dri-devel@lists.freedesktop.org, linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org, linux-media@vger.kernel.org, linaro-mm-sig@lists.linaro.org, linux-arm-kernel@lists.infradead.org, linux-mediatek@lists.infradead.org, Ketil Johnsen Subject: [PATCH 8/8] drm/panthor: Expose protected rendering features Date: Tue, 5 May 2026 16:05:14 +0200 Message-ID: <20260505140516.1372388-9-ketil.johnsen@arm.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260505140516.1372388-1-ketil.johnsen@arm.com> References: <20260505140516.1372388-1-ketil.johnsen@arm.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Add query for protected rendering capability. Add flag to group creation to specify need for protected rendering. Bump panthor version number. Signed-off-by: Ketil Johnsen --- drivers/gpu/drm/panthor/panthor_drv.c | 21 +++++++++++- drivers/gpu/drm/panthor/panthor_sched.c | 21 +++++++----- include/uapi/drm/panthor_drm.h | 45 +++++++++++++++++++++++-- 3 files changed, 76 insertions(+), 11 deletions(-) diff --git a/drivers/gpu/drm/panthor/panthor_drv.c b/drivers/gpu/drm/pantho= r/panthor_drv.c index 73fc983dc9b44..817df17f31f15 100644 --- a/drivers/gpu/drm/panthor/panthor_drv.c +++ b/drivers/gpu/drm/panthor/panthor_drv.c @@ -177,6 +177,7 @@ panthor_get_uobj_array(const struct drm_panthor_obj_arr= ay *in, u32 min_stride, PANTHOR_UOBJ_DECL(struct drm_panthor_csif_info, pad), \ PANTHOR_UOBJ_DECL(struct drm_panthor_timestamp_info, current_timestamp)= , \ PANTHOR_UOBJ_DECL(struct drm_panthor_group_priorities_info, pad), \ + PANTHOR_UOBJ_DECL(struct drm_panthor_protected_info, features), \ PANTHOR_UOBJ_DECL(struct drm_panthor_sync_op, timeline_value), \ PANTHOR_UOBJ_DECL(struct drm_panthor_queue_submit, syncs), \ PANTHOR_UOBJ_DECL(struct drm_panthor_queue_create, ringbuf_size), \ @@ -928,12 +929,20 @@ static void panthor_query_group_priorities_info(struc= t drm_file *file, } } =20 +static void panthor_query_protected_info(struct panthor_device *ptdev, + struct drm_panthor_protected_info *arg) +{ + arg->features =3D + ptdev->protm.heap ? DRM_PANTHOR_PROTECTED_FEATURE_BASIC : 0; +} + static int panthor_ioctl_dev_query(struct drm_device *ddev, void *data, st= ruct drm_file *file) { struct panthor_device *ptdev =3D container_of(ddev, struct panthor_device= , base); struct drm_panthor_dev_query *args =3D data; struct drm_panthor_timestamp_info timestamp_info; struct drm_panthor_group_priorities_info priorities_info; + struct drm_panthor_protected_info protected_info; int ret; =20 if (!args->pointer) { @@ -954,6 +963,10 @@ static int panthor_ioctl_dev_query(struct drm_device *= ddev, void *data, struct d args->size =3D sizeof(priorities_info); return 0; =20 + case DRM_PANTHOR_DEV_QUERY_PROTECTED_INFO: + args->size =3D sizeof(protected_info); + return 0; + default: return -EINVAL; } @@ -984,6 +997,11 @@ static int panthor_ioctl_dev_query(struct drm_device *= ddev, void *data, struct d panthor_query_group_priorities_info(file, &priorities_info); return PANTHOR_UOBJ_SET(args->pointer, args->size, priorities_info); =20 + case DRM_PANTHOR_DEV_QUERY_PROTECTED_INFO: + panthor_query_protected_info(ptdev, &protected_info); + return PANTHOR_UOBJ_SET(args->pointer, args->size, + protected_info); + default: return -EINVAL; } @@ -1779,6 +1797,7 @@ static void panthor_debugfs_init(struct drm_minor *mi= nor) * - adds DRM_IOCTL_PANTHOR_BO_QUERY_INFO ioctl * - adds drm_panthor_gpu_info::selected_coherency * - 1.8 - extends DEV_QUERY_TIMESTAMP_INFO with flags + * - 1.9 - adds DEV_QUERY_PROTECTED_INFO query */ static const struct drm_driver panthor_drm_driver =3D { .driver_features =3D DRIVER_RENDER | DRIVER_GEM | DRIVER_SYNCOBJ | @@ -1792,7 +1811,7 @@ static const struct drm_driver panthor_drm_driver =3D= { .name =3D "panthor", .desc =3D "Panthor DRM driver", .major =3D 1, - .minor =3D 8, + .minor =3D 9, =20 .gem_prime_import_sg_table =3D panthor_gem_prime_import_sg_table, .gem_prime_import =3D panthor_gem_prime_import, diff --git a/drivers/gpu/drm/panthor/panthor_sched.c b/drivers/gpu/drm/pant= hor/panthor_sched.c index acb04250c7def..0e8a1059de589 100644 --- a/drivers/gpu/drm/panthor/panthor_sched.c +++ b/drivers/gpu/drm/panthor/panthor_sched.c @@ -3868,6 +3868,7 @@ static void add_group_kbo_sizes(struct panthor_device= *ptdev, } =20 #define MAX_GROUPS_PER_POOL 128 +#define GROUP_CREATE_FLAGS DRM_PANTHOR_GROUP_CREATE_PROTECTED =20 int panthor_group_create(struct panthor_file *pfile, const struct drm_panthor_group_create *group_args, @@ -3882,10 +3883,10 @@ int panthor_group_create(struct panthor_file *pfile, u32 gid, i, suspend_size; int ret; =20 - if (group_args->pad) + if (group_args->priority >=3D PANTHOR_CSG_PRIORITY_COUNT) return -EINVAL; =20 - if (group_args->priority >=3D PANTHOR_CSG_PRIORITY_COUNT) + if (group_args->flags & ~GROUP_CREATE_FLAGS) return -EINVAL; =20 if ((group_args->compute_core_mask & ~ptdev->gpu_info.shader_present) || @@ -3937,12 +3938,16 @@ int panthor_group_create(struct panthor_file *pfile, goto err_put_group; } =20 - suspend_size =3D csg_iface->control->protm_suspend_size; - group->protm_suspend_buf =3D panthor_fw_alloc_protm_suspend_buf_mem(ptdev= , suspend_size); - if (IS_ERR(group->protm_suspend_buf)) { - ret =3D PTR_ERR(group->protm_suspend_buf); - group->protm_suspend_buf =3D NULL; - goto err_put_group; + if (group_args->flags & DRM_PANTHOR_GROUP_CREATE_PROTECTED) { + suspend_size =3D csg_iface->control->protm_suspend_size; + group->protm_suspend_buf =3D + panthor_fw_alloc_protm_suspend_buf_mem(ptdev, + suspend_size); + if (IS_ERR(group->protm_suspend_buf)) { + ret =3D PTR_ERR(group->protm_suspend_buf); + group->protm_suspend_buf =3D NULL; + goto err_put_group; + } } =20 group->syncobjs =3D panthor_kernel_bo_create(ptdev, group->vm, diff --git a/include/uapi/drm/panthor_drm.h b/include/uapi/drm/panthor_drm.h index 0e455d91e77d4..914110003bcd1 100644 --- a/include/uapi/drm/panthor_drm.h +++ b/include/uapi/drm/panthor_drm.h @@ -253,6 +253,11 @@ enum drm_panthor_dev_query_type { * @DRM_PANTHOR_DEV_QUERY_GROUP_PRIORITIES_INFO: Query allowed group prio= rities information. */ DRM_PANTHOR_DEV_QUERY_GROUP_PRIORITIES_INFO, + + /** + * @DRM_PANTHOR_DEV_QUERY_PROTECTED_INFO: Query supported protected rende= ring information. + */ + DRM_PANTHOR_DEV_QUERY_PROTECTED_INFO, }; =20 /** @@ -504,6 +509,28 @@ struct drm_panthor_group_priorities_info { __u8 pad[3]; }; =20 +/** + * enum drm_panthor_protected_feature_flags - Supported protected renderin= g features + * + * Place new types at the end, don't re-order, don't remove or replace. + */ +enum drm_panthor_protected_feature_flags { + /** @DRM_PANTHOR_PROTECTED_FEATURE_BASIC: Protected rendering available */ + DRM_PANTHOR_PROTECTED_FEATURE_BASIC =3D 1 << 0, +}; + +/** + * struct drm_panthor_protected_info - protected support information + * + * Structure grouping all queryable information relating to the allowed gr= oup priorities. + */ +struct drm_panthor_protected_info { + /** + * @features: Combination of enum drm_panthor_protected_feature_flags fla= gs. + */ + __u32 features; +}; + /** * struct drm_panthor_dev_query - Arguments passed to DRM_PANTHOR_IOCTL_DE= V_QUERY */ @@ -843,6 +870,18 @@ enum drm_panthor_group_priority { PANTHOR_GROUP_PRIORITY_REALTIME, }; =20 +/** + * enum drm_panthor_group_create_flags - Group create flags + */ +enum drm_panthor_group_create_flags { + /** + * @DRM_PANTHOR_GROUP_CREATE_PROTECTED: Support protected mode + * + * Enable protected rendering work to be executed on this group. + */ + DRM_PANTHOR_GROUP_CREATE_PROTECTED =3D 1 << 0, +}; + /** * struct drm_panthor_group_create - Arguments passed to DRM_IOCTL_PANTHOR= _GROUP_CREATE */ @@ -877,8 +916,10 @@ struct drm_panthor_group_create { /** @priority: Group priority (see enum drm_panthor_group_priority). */ __u8 priority; =20 - /** @pad: Padding field, MBZ. */ - __u32 pad; + /** + * @flags: Flags. Must be a combination of drm_panthor_group_create_flags= flags. + */ + __u32 flags; =20 /** * @compute_core_mask: Mask encoding cores that can be used for compute j= obs. --=20 2.43.0