git: fe3822497726 - main - Implement bus_map_resource on arm64

Andrew Turner andrew at FreeBSD.org
Sun May 2 10:56:13 UTC 2021


The branch main has been updated by andrew:

URL: https://cgit.FreeBSD.org/src/commit/?id=fe3822497726ab84a1e3753be41e43e4d51aab0b

commit fe3822497726ab84a1e3753be41e43e4d51aab0b
Author:     Andrew Turner <andrew at FreeBSD.org>
AuthorDate: 2021-04-10 10:25:39 +0000
Commit:     Andrew Turner <andrew at FreeBSD.org>
CommitDate: 2021-05-02 07:35:16 +0000

    Implement bus_map_resource on arm64
    
    This will allow us to allocate an unmapped memory resource, then
    later map it with a specific memory attribute.
    
    This is also needed for virtio with the modern PCI attachment.
    
    Reviewed by:    kib (via D29723)
    Sponsored by:   Innovate UK
    Differential Revision:  https://reviews.freebsd.org/D29694
---
 sys/arm64/arm64/nexus.c | 77 ++++++++++++++++++++++++++++++++++++++++---------
 1 file changed, 63 insertions(+), 14 deletions(-)

diff --git a/sys/arm64/arm64/nexus.c b/sys/arm64/arm64/nexus.c
index 924496ec7f52..cc28d87f002b 100644
--- a/sys/arm64/arm64/nexus.c
+++ b/sys/arm64/arm64/nexus.c
@@ -106,6 +106,8 @@ static	struct resource *nexus_alloc_resource(device_t, device_t, int, int *,
     rman_res_t, rman_res_t, rman_res_t, u_int);
 static	int nexus_activate_resource(device_t, device_t, int, int,
     struct resource *);
+static	int nexus_map_resource(device_t, device_t, int, struct resource *,
+    struct resource_map_request *, struct resource_map *);
 static int nexus_config_intr(device_t dev, int irq, enum intr_trigger trig,
     enum intr_polarity pol);
 static struct resource_list *nexus_get_reslist(device_t, device_t);
@@ -135,6 +137,7 @@ static device_method_t nexus_methods[] = {
 	DEVMETHOD(bus_add_child,	nexus_add_child),
 	DEVMETHOD(bus_alloc_resource,	nexus_alloc_resource),
 	DEVMETHOD(bus_activate_resource,	nexus_activate_resource),
+	DEVMETHOD(bus_map_resource,	nexus_map_resource),
 	DEVMETHOD(bus_config_intr,	nexus_config_intr),
 	DEVMETHOD(bus_get_resource_list, nexus_get_reslist),
 	DEVMETHOD(bus_set_resource,	nexus_set_resource),
@@ -344,10 +347,8 @@ static int
 nexus_activate_resource(device_t bus, device_t child, int type, int rid,
     struct resource *r)
 {
+	struct resource_map map;
 	int err;
-	bus_addr_t paddr;
-	bus_size_t psize;
-	bus_space_handle_t vaddr;
 
 	if ((err = rman_activate_resource(r)) != 0)
 		return (err);
@@ -355,18 +356,21 @@ nexus_activate_resource(device_t bus, device_t child, int type, int rid,
 	/*
 	 * If this is a memory resource, map it into the kernel.
 	 */
-	if (type == SYS_RES_MEMORY || type == SYS_RES_IOPORT) {
-		paddr = (bus_addr_t)rman_get_start(r);
-		psize = (bus_size_t)rman_get_size(r);
-		err = bus_space_map(&memmap_bus, paddr, psize, 0, &vaddr);
-		if (err != 0) {
-			rman_deactivate_resource(r);
-			return (err);
+	switch (type) {
+	case SYS_RES_IOPORT:
+	case SYS_RES_MEMORY:
+		if ((rman_get_flags(r) & RF_UNMAPPED) == 0) {
+			err = nexus_map_resource(bus, child, type, r, NULL,
+			    &map);
+			if (err != 0) {
+				rman_deactivate_resource(r);
+				return (err);
+			}
+
+			rman_set_mapping(r, &map);
 		}
-		rman_set_bustag(r, &memmap_bus);
-		rman_set_virtual(r, (void *)vaddr);
-		rman_set_bushandle(r, vaddr);
-	} else if (type == SYS_RES_IRQ) {
+		break;
+	case SYS_RES_IRQ:
 		err = intr_activate_irq(child, r);
 		if (err != 0) {
 			rman_deactivate_resource(r);
@@ -420,6 +424,51 @@ nexus_deactivate_resource(device_t bus, device_t child, int type, int rid,
 	return (rman_deactivate_resource(r));
 }
 
+static int
+nexus_map_resource(device_t bus, device_t child, int type, struct resource *r,
+    struct resource_map_request *argsp, struct resource_map *map)
+{
+	struct resource_map_request args;
+	rman_res_t end, length, start;
+
+	/* Resources must be active to be mapped. */
+	if ((rman_get_flags(r) & RF_ACTIVE) == 0)
+		return (ENXIO);
+
+	/* Mappings are only supported on I/O and memory resources. */
+	switch (type) {
+	case SYS_RES_IOPORT:
+	case SYS_RES_MEMORY:
+		break;
+	default:
+		return (EINVAL);
+	}
+
+	resource_init_map_request(&args);
+	if (argsp != NULL)
+		bcopy(argsp, &args, imin(argsp->size, args.size));
+	start = rman_get_start(r) + args.offset;
+	if (args.length == 0)
+		length = rman_get_size(r);
+	else
+		length = args.length;
+	end = start + length - 1;
+	if (start > rman_get_end(r) || start < rman_get_start(r))
+		return (EINVAL);
+	if (end > rman_get_end(r) || end < start)
+		return (EINVAL);
+
+	map->r_vaddr = pmap_mapdev_attr(start, length, args.memattr);
+	map->r_bustag = &memmap_bus;
+	map->r_size = length;
+
+	/*
+	 * The handle is the virtual address.
+	 */
+	map->r_bushandle = (bus_space_handle_t)map->r_vaddr;
+	return (0);
+}
+
 #ifdef FDT
 static device_method_t nexus_fdt_methods[] = {
 	/* Device interface */


More information about the dev-commits-src-all mailing list