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-main
mailing list