Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 235488
b: refs/heads/master
c: a3857a5
h: refs/heads/master
v: v3
  • Loading branch information
Mike Waychison authored and Greg Kroah-Hartman committed Feb 25, 2011
1 parent e5b6909 commit 00bf626
Show file tree
Hide file tree
Showing 2 changed files with 144 additions and 1 deletion.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 925a1da7477fc4ba5849c6f0243934fa5072493c
refs/heads/master: a3857a5c9893aa69d44be6e881927b0950b1d931
143 changes: 143 additions & 0 deletions trunk/drivers/firmware/dmi-sysfs.c
Original file line number Diff line number Diff line change
Expand Up @@ -312,6 +312,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;
Expand All @@ -325,6 +459,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;
Expand Down

0 comments on commit 00bf626

Please sign in to comment.