From: Mike Waychison <mikew@google.com>
To: Greg KH <greg@kroah.com>, Olof Johansson <olofj@chromium.org>,
Andi Kleen <andi@firstfloor.org>,
Alan Cox <alan@lxorguk.ukuu.org.uk>,
Robert Lippert <rlippert@google.com>
Cc: Jon Mayer <jonmayer@google.com>,
Duncan Laurie <dlaurie@google.com>,
Aaron Durbin <adurbin@google.com>,
linux-kernel@vger.kernel.org, Tim Hockin <thockin@google.com>,
David Hendrix <dhendrix@chromium.org>,
linux-api@vger.kernel.org
Subject: [PATCH v1 4/5] firmware: Expose DMI type 15 System Event Log
Date: Thu, 17 Feb 2011 13:28:16 -0800 [thread overview]
Message-ID: <20110217212816.3967.923.stgit@mike.mtv.corp.google.com> (raw)
In-Reply-To: <20110217212754.3967.98648.stgit@mike.mtv.corp.google.com>
The System Event Log described by DMI entry type 15 may be backed by
either memory or may be indirectly accessed via an IO index/data
register pair.
In order to get read access to this log, expose it in the
"system_event_log" sub-directory of type 15 DMI entries, ie:
/sys/firmware/dmi/entries/15-0/system_event_log/raw_event_log.
This commit handles both IO accessed and memory access system event
logs. OEM specific access and GPNV support is explicitly not handled
and we error out in the logs when we do not recognize the access method.
Signed-off-by: Mike Waychison <mikew@google.com>
---
drivers/firmware/dmi-sysfs.c | 143 ++++++++++++++++++++++++++++++++++++++++++
1 files changed, 143 insertions(+), 0 deletions(-)
diff --git a/drivers/firmware/dmi-sysfs.c b/drivers/firmware/dmi-sysfs.c
index 3f49042..51462fe 100644
--- a/drivers/firmware/dmi-sysfs.c
+++ b/drivers/firmware/dmi-sysfs.c
@@ -305,6 +305,140 @@ static struct kobj_type dmi_system_event_log_ktype = {
.default_attrs = dmi_sysfs_sel_attrs,
};
+typedef u8 (*sel_io_reader)(const struct dmi_system_event_log *sel,
+ loff_t offset);
+
+static DEFINE_MUTEX(io_port_lock);
+
+static u8 read_sel_8bit_indexed_io(const struct dmi_system_event_log *sel,
+ loff_t offset)
+{
+ u8 ret;
+
+ mutex_lock(&io_port_lock);
+ outb((u8)offset, sel->io.index_addr);
+ ret = inb(sel->io.data_addr);
+ mutex_unlock(&io_port_lock);
+ return ret;
+}
+
+static u8 read_sel_2x8bit_indexed_io(const struct dmi_system_event_log *sel,
+ loff_t offset)
+{
+ u8 ret;
+
+ mutex_lock(&io_port_lock);
+ outb((u8)offset, sel->io.index_addr);
+ outb((u8)(offset >> 8), sel->io.index_addr + 1);
+ ret = inb(sel->io.data_addr);
+ mutex_unlock(&io_port_lock);
+ return ret;
+}
+
+static u8 read_sel_16bit_indexed_io(const struct dmi_system_event_log *sel,
+ loff_t offset)
+{
+ u8 ret;
+
+ mutex_lock(&io_port_lock);
+ outw((u16)offset, sel->io.index_addr);
+ ret = inb(sel->io.data_addr);
+ mutex_unlock(&io_port_lock);
+ return ret;
+}
+
+static sel_io_reader sel_io_readers[] = {
+ [DMI_SEL_ACCESS_METHOD_IO8] = read_sel_8bit_indexed_io,
+ [DMI_SEL_ACCESS_METHOD_IO2x8] = read_sel_2x8bit_indexed_io,
+ [DMI_SEL_ACCESS_METHOD_IO16] = read_sel_16bit_indexed_io,
+};
+
+static ssize_t dmi_sel_raw_read_io(struct dmi_sysfs_entry *entry,
+ const struct dmi_system_event_log *sel,
+ char *buf, loff_t pos, size_t count)
+{
+ ssize_t wrote = 0;
+
+ sel_io_reader io_reader = sel_io_readers[sel->access_method];
+
+ while (count && pos < sel->area_length) {
+ count--;
+ *(buf++) = io_reader(sel, pos++);
+ wrote++;
+ }
+
+ return wrote;
+}
+
+static ssize_t dmi_sel_raw_read_phys32(struct dmi_sysfs_entry *entry,
+ const struct dmi_system_event_log *sel,
+ char *buf, loff_t pos, size_t count)
+{
+ u8 __iomem *mapped;
+ ssize_t wrote = 0;
+
+ mapped = ioremap(sel->access_method_address, sel->area_length);
+ if (!mapped)
+ return -EIO;
+
+ while (count && pos < sel->area_length) {
+ count--;
+ *(buf++) = readb(mapped + pos++);
+ wrote++;
+ }
+
+ iounmap(mapped);
+ return wrote;
+}
+
+static ssize_t dmi_sel_raw_read_helper(struct dmi_sysfs_entry *entry,
+ const struct dmi_header *dh,
+ void *_state)
+{
+ struct dmi_read_state *state = _state;
+ const struct dmi_system_event_log *sel = to_sel(dh);
+
+ if (sizeof(*sel) > dmi_entry_length(dh))
+ return -EIO;
+
+ switch (sel->access_method) {
+ case DMI_SEL_ACCESS_METHOD_IO8:
+ case DMI_SEL_ACCESS_METHOD_IO2x8:
+ case DMI_SEL_ACCESS_METHOD_IO16:
+ return dmi_sel_raw_read_io(entry, sel, state->buf,
+ state->pos, state->count);
+ case DMI_SEL_ACCESS_METHOD_PHYS32:
+ return dmi_sel_raw_read_phys32(entry, sel, state->buf,
+ state->pos, state->count);
+ case DMI_SEL_ACCESS_METHOD_GPNV:
+ pr_info("dmi-sysfs: GPNV support missing.\n");
+ return -EIO;
+ default:
+ pr_info("dmi-sysfs: Unknown access method %02x\n",
+ sel->access_method);
+ return -EIO;
+ }
+}
+
+static ssize_t dmi_sel_raw_read(struct file *filp, struct kobject *kobj,
+ struct bin_attribute *bin_attr,
+ char *buf, loff_t pos, size_t count)
+{
+ struct dmi_sysfs_entry *entry = to_entry(kobj->parent);
+ struct dmi_read_state state = {
+ .buf = buf,
+ .pos = pos,
+ .count = count,
+ };
+
+ return find_dmi_entry(entry, dmi_sel_raw_read_helper, &state);
+}
+
+static struct bin_attribute dmi_sel_raw_attr = {
+ .attr = {.name = "raw_event_log", .mode = 0400},
+ .read = dmi_sel_raw_read,
+};
+
static int dmi_system_event_log(struct dmi_sysfs_entry *entry)
{
int ret;
@@ -318,6 +452,15 @@ static int dmi_system_event_log(struct dmi_sysfs_entry *entry)
"system_event_log");
if (ret)
goto out_free;
+
+ ret = sysfs_create_bin_file(entry->child, &dmi_sel_raw_attr);
+ if (ret)
+ goto out_del;
+
+ return 0;
+
+out_del:
+ kobject_del(entry->child);
out_free:
kfree(entry->child);
return ret;
next prev parent reply other threads:[~2011-02-17 21:29 UTC|newest]
Thread overview: 13+ messages / expand[flat|nested] mbox.gz Atom feed top
2011-02-17 21:27 [PATCH v1 0/5] Exporting DMI entries via syfs Mike Waychison
2011-02-17 21:28 ` [PATCH v1 1/5] firmware: Add DMI entry types to the headers Mike Waychison
2011-02-17 21:28 ` [PATCH v1 2/5] firmware: Basic dmi-sysfs support Mike Waychison
2011-02-17 21:42 ` Tim Hockin
2011-02-17 21:56 ` Greg KH
2011-02-22 23:31 ` Mike Waychison
2011-02-23 0:07 ` Luck, Tony
2011-02-22 23:49 ` Rob Lippert
2011-02-22 23:58 ` Mike Waychison
2011-02-17 21:28 ` [PATCH v1 3/5] firmware: Break out system_event_log in dmi-sysfs Mike Waychison
2011-02-17 21:28 ` Mike Waychison [this message]
2011-02-17 21:28 ` [PATCH v1 5/5] firmware: Add documentation for /sys/firmware/dmi Mike Waychison
2011-02-17 21:50 ` Tim Hockin
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20110217212816.3967.923.stgit@mike.mtv.corp.google.com \
--to=mikew@google.com \
--cc=adurbin@google.com \
--cc=alan@lxorguk.ukuu.org.uk \
--cc=andi@firstfloor.org \
--cc=dhendrix@chromium.org \
--cc=dlaurie@google.com \
--cc=greg@kroah.com \
--cc=jonmayer@google.com \
--cc=linux-api@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=olofj@chromium.org \
--cc=rlippert@google.com \
--cc=thockin@google.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
Powered by JetHome