---
arch/powerpc/platforms/powernv/opal-msglog.c | 81 ++++++++++++++++++----------
1 file changed, 54 insertions(+), 27 deletions(-)
diff --git a/arch/powerpc/platforms/powernv/opal-msglog.c
b/arch/powerpc/platforms/powernv/opal-msglog.c
index 7a9cde0..0f2167f 100644
--- a/arch/powerpc/platforms/powernv/opal-msglog.c
+++ b/arch/powerpc/platforms/powernv/opal-msglog.c
@@ -18,38 +18,46 @@
/* OPAL in-memory console. Defined in OPAL source at core/console.c */
struct memcons {
- __be64 magic;
+ unsigned long magic;
#define MEMCONS_MAGIC 0x6630696567726173L
- __be64 obuf_phys;
- __be64 ibuf_phys;
- __be32 obuf_size;
- __be32 ibuf_size;
- __be32 out_pos;
+ unsigned long obuf_phys;
+ unsigned long ibuf_phys;
+ unsigned int obuf_size;
+ unsigned int ibuf_size;
+ unsigned int out_pos;
#define MEMCONS_OUT_POS_WRAP 0x80000000u
#define MEMCONS_OUT_POS_MASK 0x00ffffffu
- __be32 in_prod;
- __be32 in_cons;
+ unsigned int in_prod;
+ unsigned int in_cons;
};
-static struct memcons *opal_memcons = NULL;
+static struct memcons opal_memcons;
+static void __iomem *opal_memcons_virt;
+static void __iomem *opal_memcons_obuf;
+
+#define OPAL_MEMCONS_GET_FIELD(field, accessor, converter, tmp) \
+ tmp = accessor(opal_memcons_virt + \
+ offsetof(struct memcons, field)); \
+ opal_memcons.field = converter(tmp)
ssize_t opal_msglog_copy(char *to, loff_t pos, size_t count)
{
- const char *conbuf;
+ char *conbuf;
ssize_t ret;
size_t first_read = 0;
- uint32_t out_pos, avail;
+ uint32_t out_pos, avail, val32;
- if (!opal_memcons)
+ if (!opal_memcons_obuf)
return -ENODEV;
- out_pos = be32_to_cpu(ACCESS_ONCE(opal_memcons->out_pos));
+ OPAL_MEMCONS_GET_FIELD(out_pos, __raw_readl, be32_to_cpu, val32);
+ out_pos = opal_memcons.out_pos;
/* Now we've read out_pos, put a barrier in before reading the new
* data it points to in conbuf. */
smp_rmb();
- conbuf = phys_to_virt(be64_to_cpu(opal_memcons->obuf_phys));
+ conbuf = opal_memcons_obuf;
/* When the buffer has wrapped, read from the out_pos marker to the end
* of the buffer, and then read the remaining data as in the un-wrapped
@@ -57,7 +65,7 @@ ssize_t opal_msglog_copy(char *to, loff_t pos, size_t count)
if (out_pos & MEMCONS_OUT_POS_WRAP) {
out_pos &= MEMCONS_OUT_POS_MASK;
- avail = be32_to_cpu(opal_memcons->obuf_size) - out_pos;
+ avail = opal_memcons.obuf_size - out_pos;
ret = memory_read_from_buffer(to, count, &pos,
conbuf + out_pos, avail);
@@ -75,7 +83,7 @@ ssize_t opal_msglog_copy(char *to, loff_t pos, size_t count)
}
/* Sanity check. The firmware should not do this to us. */
- if (out_pos > be32_to_cpu(opal_memcons->obuf_size)) {
+ if (out_pos > opal_memcons.obuf_size) {
pr_err("OPAL: memory console corruption. Aborting read.\n");
return -EINVAL;
}
@@ -104,35 +112,54 @@ static struct bin_attribute opal_msglog_attr = {
void __init opal_msglog_init(void)
{
- u64 mcaddr;
- struct memcons *mc;
+ u64 val64;
+ u32 val32;
- if (of_property_read_u64(opal_node, "ibm,opal-memcons", &mcaddr)) {
+ if (of_property_read_u64(opal_node, "ibm,opal-memcons", &val64)) {
pr_warn("OPAL: Property ibm,opal-memcons not found, no message
log\n");
return;
}
- mc = phys_to_virt(mcaddr);
- if (!mc) {
+ opal_memcons_virt = ioremap_prot(val64, sizeof(opal_memcons),
+ (_PAGE_BASE | _PAGE_KERNEL_RO));
+ if (!opal_memcons_virt) {
pr_warn("OPAL: memory console address is invalid\n");
return;
}
- if (be64_to_cpu(mc->magic) != MEMCONS_MAGIC) {
+ OPAL_MEMCONS_GET_FIELD(magic, __raw_readq, be64_to_cpu, val64);
+ OPAL_MEMCONS_GET_FIELD(obuf_phys, __raw_readq, be64_to_cpu, val64);
+ OPAL_MEMCONS_GET_FIELD(ibuf_phys, __raw_readq, be64_to_cpu, val64);
+ OPAL_MEMCONS_GET_FIELD(obuf_size, __raw_readl, be32_to_cpu, val64);
+ OPAL_MEMCONS_GET_FIELD(ibuf_size, __raw_readl, be32_to_cpu, val32);
+ OPAL_MEMCONS_GET_FIELD(out_pos, __raw_readl, be32_to_cpu, val32);
+ OPAL_MEMCONS_GET_FIELD(in_prod, __raw_readl, be32_to_cpu, val32);
+ OPAL_MEMCONS_GET_FIELD(in_cons, __raw_readl, be32_to_cpu, val32);
+
+ if (opal_memcons.magic != MEMCONS_MAGIC) {
pr_warn("OPAL: memory console version is invalid\n");
+ iounmap(opal_memcons_virt);
return;
}
- /* Report maximum size */
- opal_msglog_attr.size = be32_to_cpu(mc->ibuf_size) +
- be32_to_cpu(mc->obuf_size);
+ opal_memcons_obuf = ioremap_prot(opal_memcons.obuf_phys,
+ opal_memcons.obuf_size,
+ (_PAGE_BASE | _PAGE_KERNEL_RO));
+ if (!opal_memcons_obuf) {
+ pr_warn("OPAL: Fail mapping output buffer (0x%lx, 0x%x)\n",
+ opal_memcons.obuf_phys, opal_memcons.obuf_size);
+ iounmap(opal_memcons_virt);
+ return;
+ }
- opal_memcons = mc;
+ /* Report maximum size */
+ opal_msglog_attr.size = opal_memcons.ibuf_size +
+ opal_memcons.obuf_size;
}
void __init opal_msglog_sysfs_init(void)
{
- if (!opal_memcons) {
+ if (!opal_memcons_obuf) {
pr_warn("OPAL: message log initialisation failed, not creating sysfs
entry\n");
return;
}