Module Name:    src
Committed By:   jmcneill
Date:           Wed Nov 28 22:54:11 UTC 2018

Modified Files:
        src/sys/arch/arm/cortex: gicv3_its.c gicv3_its.h

Log Message:
Allow non-power of 2 counts, and support alloc/release/alloc patterns for a 
device as long as the ITT size is sufficient


To generate a diff of this commit:
cvs rdiff -u -r1.8 -r1.9 src/sys/arch/arm/cortex/gicv3_its.c
cvs rdiff -u -r1.3 -r1.4 src/sys/arch/arm/cortex/gicv3_its.h

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

Modified files:

Index: src/sys/arch/arm/cortex/gicv3_its.c
diff -u src/sys/arch/arm/cortex/gicv3_its.c:1.8 src/sys/arch/arm/cortex/gicv3_its.c:1.9
--- src/sys/arch/arm/cortex/gicv3_its.c:1.8	Sat Nov 24 15:40:57 2018
+++ src/sys/arch/arm/cortex/gicv3_its.c	Wed Nov 28 22:54:11 2018
@@ -1,4 +1,4 @@
-/* $NetBSD: gicv3_its.c,v 1.8 2018/11/24 15:40:57 skrll Exp $ */
+/* $NetBSD: gicv3_its.c,v 1.9 2018/11/28 22:54:11 jmcneill Exp $ */
 
 /*-
  * Copyright (c) 2018 The NetBSD Foundation, Inc.
@@ -32,7 +32,7 @@
 #define _INTR_PRIVATE
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: gicv3_its.c,v 1.8 2018/11/24 15:40:57 skrll Exp $");
+__KERNEL_RCSID(0, "$NetBSD: gicv3_its.c,v 1.9 2018/11/28 22:54:11 jmcneill Exp $");
 
 #include <sys/param.h>
 #include <sys/kmem.h>
@@ -293,22 +293,25 @@ static int
 gicv3_its_device_map(struct gicv3_its *its, uint32_t devid, u_int count)
 {
 	struct gicv3_its_device *dev;
+	u_int vectors;
 
-	LIST_FOREACH(dev, &its->its_devices, dev_list)
-		if (dev->dev_id == devid)
-			return EEXIST;
-
-	const u_int vectors = MAX(2, count);
-	if (!powerof2(vectors))
-		return EINVAL;
+	vectors = MAX(2, count);
+	while (!powerof2(vectors))
+		vectors++;
 
 	const uint64_t typer = gits_read_8(its, GITS_TYPER);
 	const u_int id_bits = __SHIFTOUT(typer, GITS_TYPER_ID_bits) + 1;
 	const u_int itt_entry_size = __SHIFTOUT(typer, GITS_TYPER_ITT_entry_size) + 1;
 	const u_int itt_size = roundup(vectors * itt_entry_size, GITS_ITT_ALIGN);
 
+	LIST_FOREACH(dev, &its->its_devices, dev_list)
+		if (dev->dev_id == devid) {
+			return itt_size <= dev->dev_size ? 0 : EEXIST;
+		}
+
 	dev = kmem_alloc(sizeof(*dev), KM_SLEEP);
 	dev->dev_id = devid;
+	dev->dev_size = itt_size;
 	gicv3_dma_alloc(its->its_gic, &dev->dev_itt, itt_size, GITS_ITT_ALIGN);
 	LIST_INSERT_HEAD(&its->its_devices, dev, dev_list);
 

Index: src/sys/arch/arm/cortex/gicv3_its.h
diff -u src/sys/arch/arm/cortex/gicv3_its.h:1.3 src/sys/arch/arm/cortex/gicv3_its.h:1.4
--- src/sys/arch/arm/cortex/gicv3_its.h:1.3	Sat Nov 24 22:08:53 2018
+++ src/sys/arch/arm/cortex/gicv3_its.h	Wed Nov 28 22:54:11 2018
@@ -1,4 +1,4 @@
-/* $NetBSD: gicv3_its.h,v 1.3 2018/11/24 22:08:53 jakllsch Exp $ */
+/* $NetBSD: gicv3_its.h,v 1.4 2018/11/28 22:54:11 jmcneill Exp $ */
 
 /*-
  * Copyright (c) 2018 The NetBSD Foundation, Inc.
@@ -40,6 +40,7 @@
 
 struct gicv3_its_device {
 	uint32_t		dev_id;
+	u_int			dev_size;
 	struct gicv3_dma	dev_itt;
 
 	LIST_ENTRY(gicv3_its_device) dev_list;

Reply via email to