aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJeremy Kerr <jk@ozlabs.org>2015-08-06 11:32:47 +0800
committerStewart Smith <stewart@linux.vnet.ibm.com>2015-08-10 17:52:56 +1000
commiteca1f2193fd0d7cbb4154055048e28b2f689c448 (patch)
tree259b87e89e8633608e8cdce5b71f31ec2da42bd1
parentf5a7c43a163f5484d2bd2b8b74814abc23f1e92d (diff)
downloadskiboot-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>
-rw-r--r--external/opal-prd/opal-prd.c35
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: