diff options
author | Jeremy Kerr <jk@ozlabs.org> | 2015-08-06 11:32:47 +0800 |
---|---|---|
committer | Stewart Smith <stewart@linux.vnet.ibm.com> | 2015-08-10 17:52:56 +1000 |
commit | eca1f2193fd0d7cbb4154055048e28b2f689c448 (patch) | |
tree | 259b87e89e8633608e8cdce5b71f31ec2da42bd1 /external/opal-prd/opal-prd.c | |
parent | f5a7c43a163f5484d2bd2b8b74814abc23f1e92d (diff) | |
download | skiboot-eca1f2193fd0d7cbb4154055048e28b2f689c448.zip skiboot-eca1f2193fd0d7cbb4154055048e28b2f689c448.tar.gz skiboot-eca1f2193fd0d7cbb4154055048e28b2f689c448.tar.bz2 |
external/opal-prd: Only map each PRD range once
Currently, opal-prd will create a new mapping (via mmap()) on every call
to get_reserved_mem().
HBRT may end up calling this many times for the same range, which will
consume virtual address space. There's no interface to unmap memory, so
we may fail after too many calls.
Instead, store the mapping in struct prd_range on first
get_reserved_mem. Subsequent calls will re-use the same mapping.
Signed-off-by: Jeremy Kerr <jk@ozlabs.org>
Signed-off-by: Stewart Smith <stewart@linux.vnet.ibm.com>
Diffstat (limited to 'external/opal-prd/opal-prd.c')
-rw-r--r-- | external/opal-prd/opal-prd.c | 35 |
1 files changed, 23 insertions, 12 deletions
diff --git a/external/opal-prd/opal-prd.c b/external/opal-prd/opal-prd.c index fcb8ee1..89d1be6 100644 --- a/external/opal-prd/opal-prd.c +++ b/external/opal-prd/opal-prd.c @@ -60,6 +60,7 @@ struct prd_range { const char *name; uint64_t physaddr; uint64_t size; + void *buf; }; struct opal_prd_ctx { @@ -275,9 +276,7 @@ int hservice_scom_write(uint64_t chip_id, uint64_t addr, uint64_t hservice_get_reserved_mem(const char *name) { - uint64_t align_physaddr, offset; struct prd_range *range; - void *addr; pr_debug("IMAGE: hservice_get_reserved_mem: %s", name); @@ -288,24 +287,35 @@ uint64_t hservice_get_reserved_mem(const char *name) return 0; } - pr_debug("IMAGE: Mapping 0x%016lx 0x%08lx %s", - range->physaddr, range->size, range->name); + if (!range->buf) { + uint64_t align_physaddr, offset; + + pr_debug("IMAGE: Mapping 0x%016lx 0x%08lx %s", + range->physaddr, range->size, range->name); - align_physaddr = range->physaddr & ~(ctx->page_size-1); - offset = range->physaddr & (ctx->page_size-1); - addr = mmap(NULL, range->size, PROT_WRITE | PROT_READ, - MAP_SHARED, ctx->fd, align_physaddr); + align_physaddr = range->physaddr & ~(ctx->page_size-1); + offset = range->physaddr & (ctx->page_size-1); + range->buf = mmap(NULL, range->size, PROT_WRITE | PROT_READ, + MAP_SHARED, ctx->fd, align_physaddr); - if (addr == MAP_FAILED) { - pr_log(LOG_ERR, "IMAGE: mmap of %s(0x%016lx) failed: %m", + if (range->buf == MAP_FAILED) + pr_log(LOG_ERR, + "IMAGE: mmap of %s(0x%016lx) failed: %m", name, range->physaddr); + else + range->buf += offset; + } + + if (range->buf == MAP_FAILED) { + pr_log(LOG_WARNING, "IMAGE: get_reserved_mem: %s has no vaddr", + name); return 0; } pr_debug("IMAGE: hservice_get_reserved_mem: %s(0x%016lx) address %p", - name, range->physaddr, addr); + name, range->physaddr, range->buf); - return (uint64_t)addr + offset; + return (uint64_t)range->buf; } void hservice_nanosleep(uint64_t i_seconds, uint64_t i_nano_seconds) @@ -808,6 +818,7 @@ static int prd_init_one_range(struct opal_prd_ctx *ctx, const char *path, range->name = strndup(label, label_len); range->physaddr = be64toh(reg[0]); range->size = be64toh(reg[1]); + range->buf = NULL; rc = 0; out_free: |