Module Name:    src
Committed By:   riastradh
Date:           Tue Feb 15 22:51:03 UTC 2022

Modified Files:
        src/sys/external/bsd/drm2/linux: linux_dma_resv.c

Log Message:
drm: Use KM_SLEEP to allocate reservation fence arrays.

Except as a fast path in an RCU reader.

The array sizes appear to be reasonably small and not trivially
controlled by userland, from what I can tell, so if my impression is
accurate, it is reasonable to sleep for allocation here.


To generate a diff of this commit:
cvs rdiff -u -r1.21 -r1.22 src/sys/external/bsd/drm2/linux/linux_dma_resv.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/external/bsd/drm2/linux/linux_dma_resv.c
diff -u src/sys/external/bsd/drm2/linux/linux_dma_resv.c:1.21 src/sys/external/bsd/drm2/linux/linux_dma_resv.c:1.22
--- src/sys/external/bsd/drm2/linux/linux_dma_resv.c:1.21	Sun Dec 19 12:36:02 2021
+++ src/sys/external/bsd/drm2/linux/linux_dma_resv.c	Tue Feb 15 22:51:03 2022
@@ -1,4 +1,4 @@
-/*	$NetBSD: linux_dma_resv.c,v 1.21 2021/12/19 12:36:02 riastradh Exp $	*/
+/*	$NetBSD: linux_dma_resv.c,v 1.22 2022/02/15 22:51:03 riastradh Exp $	*/
 
 /*-
  * Copyright (c) 2018 The NetBSD Foundation, Inc.
@@ -30,7 +30,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: linux_dma_resv.c,v 1.21 2021/12/19 12:36:02 riastradh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: linux_dma_resv.c,v 1.22 2022/02/15 22:51:03 riastradh Exp $");
 
 #include <sys/param.h>
 #include <sys/poll.h>
@@ -56,6 +56,17 @@ objlist_tryalloc(uint32_t n)
 	return list;
 }
 
+static struct dma_resv_list *
+objlist_alloc(uint32_t n)
+{
+	struct dma_resv_list *list;
+
+	list = kmem_alloc(offsetof(typeof(*list), shared[n]), KM_SLEEP);
+	list->shared_max = n;
+
+	return list;
+}
+
 static void
 objlist_free(struct dma_resv_list *list)
 {
@@ -346,9 +357,7 @@ dma_resv_reserve_shared(struct dma_resv 
 
 		/* Try to double its capacity.  */
 		nalloc = n > UINT32_MAX/2 ? UINT32_MAX : 2*n;
-		prealloc = objlist_tryalloc(nalloc);
-		if (prealloc == NULL)
-			return -ENOMEM;
+		prealloc = objlist_alloc(nalloc);
 
 		/* Swap the new preallocated list and free the old one.  */
 		objlist_free(robj->robj_prealloc);
@@ -356,9 +365,8 @@ dma_resv_reserve_shared(struct dma_resv 
 	} else {
 		/* Start with some spare.  */
 		nalloc = n > UINT32_MAX/2 ? UINT32_MAX : MAX(2*n, 4);
-		prealloc = objlist_tryalloc(nalloc);
-		if (prealloc == NULL)
-			return -ENOMEM;
+		prealloc = objlist_alloc(nalloc);
+
 		/* Save the new preallocated list.  */
 		robj->robj_prealloc = prealloc;
 	}
@@ -689,8 +697,10 @@ dma_resv_add_shared_fence(struct dma_res
 		prealloc->shared_count = shared_count;
 
 		/* If we didn't find one, add it at the end.  */
-		if (replace == NULL)
+		if (replace == NULL) {
+			KASSERT(prealloc->shared_count < prealloc->shared_max);
 			prealloc->shared[prealloc->shared_count++] = fence;
+		}
 
 		/*
 		 * Now ready to replace the list.  Begin an update.
@@ -919,11 +929,20 @@ top:	KASSERT(fence == NULL);
 	if (!dma_resv_get_shared_reader(src_robj, &src_list, &shared_count,
 		&read_ticket))
 		goto restart;
-	if (src_list != NULL) {
-		/* Allocate a new list.  */
-		dst_list = objlist_tryalloc(shared_count);
+	if (src_list) {
+		/* Allocate a new list, if necessary.  */
 		if (dst_list == NULL)
-			return -ENOMEM;
+			dst_list = objlist_tryalloc(shared_count);
+		if (dst_list == NULL || dst_list->shared_max < shared_count) {
+			rcu_read_unlock();
+			if (dst_list) {
+				objlist_free(dst_list);
+				dst_list = NULL;
+			}
+			dst_list = objlist_alloc(shared_count);
+			dst_list->shared_count = 0; /* paranoia */
+			goto top;
+		}
 
 		/* Copy over all fences that are not yet signalled.  */
 		dst_list->shared_count = 0;
@@ -1005,8 +1024,7 @@ restart:
 			dma_fence_put(dst_list->shared[i]);
 			dst_list->shared[i] = NULL; /* paranoia */
 		}
-		objlist_free(dst_list);
-		dst_list = NULL;
+		/* reuse dst_list allocation for the next attempt */
 	}
 	goto top;
 }

Reply via email to