Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 235487
b: refs/heads/master
c: 925a1da
h: refs/heads/master
i:
  235485: a0bfe7a
  235483: 3b95914
  235479: 26a8439
  235471: a64623c
  235455: 8e6dbc4
v: v3
  • Loading branch information
Mike Waychison authored and Greg Kroah-Hartman committed Feb 25, 2011
1 parent ad3d581 commit e5b6909
Show file tree
Hide file tree
Showing 2 changed files with 160 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: 948af1f0bbc8526448e8cbe3f8d3bf211bdf5181
refs/heads/master: 925a1da7477fc4ba5849c6f0243934fa5072493c
159 changes: 159 additions & 0 deletions trunk/drivers/firmware/dmi-sysfs.c
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ struct dmi_sysfs_entry {
int instance;
int position;
struct list_head list;
struct kobject *child;
};

/*
Expand Down Expand Up @@ -77,6 +78,10 @@ struct dmi_sysfs_mapped_attribute dmi_sysfs_attr_##_entry##_##_name = { \
/*************************************************
* Generic DMI entry support.
*************************************************/
static void dmi_entry_free(struct kobject *kobj)
{
kfree(kobj);
}

static struct dmi_sysfs_entry *to_entry(struct kobject *kobj)
{
Expand Down Expand Up @@ -185,6 +190,146 @@ static size_t dmi_entry_length(const struct dmi_header *dh)
return 2 + p - (const char *)dh;
}

/*************************************************
* Support bits for specialized DMI entry support
*************************************************/
struct dmi_entry_attr_show_data {
struct attribute *attr;
char *buf;
};

static ssize_t dmi_entry_attr_show_helper(struct dmi_sysfs_entry *entry,
const struct dmi_header *dh,
void *_data)
{
struct dmi_entry_attr_show_data *data = _data;
struct dmi_sysfs_mapped_attribute *attr;

attr = container_of(data->attr,
struct dmi_sysfs_mapped_attribute, attr);
return attr->show(entry, dh, data->buf);
}

static ssize_t dmi_entry_attr_show(struct kobject *kobj,
struct attribute *attr,
char *buf)
{
struct dmi_entry_attr_show_data data = {
.attr = attr,
.buf = buf,
};
/* Find the entry according to our parent and call the
* normalized show method hanging off of the attribute */
return find_dmi_entry(to_entry(kobj->parent),
dmi_entry_attr_show_helper, &data);
}

static const struct sysfs_ops dmi_sysfs_specialize_attr_ops = {
.show = dmi_entry_attr_show,
};

/*************************************************
* Specialized DMI entry support.
*************************************************/

/*** Type 15 - System Event Table ***/

#define DMI_SEL_ACCESS_METHOD_IO8 0x00
#define DMI_SEL_ACCESS_METHOD_IO2x8 0x01
#define DMI_SEL_ACCESS_METHOD_IO16 0x02
#define DMI_SEL_ACCESS_METHOD_PHYS32 0x03
#define DMI_SEL_ACCESS_METHOD_GPNV 0x04

struct dmi_system_event_log {
struct dmi_header header;
u16 area_length;
u16 header_start_offset;
u16 data_start_offset;
u8 access_method;
u8 status;
u32 change_token;
union {
struct {
u16 index_addr;
u16 data_addr;
} io;
u32 phys_addr32;
u16 gpnv_handle;
u32 access_method_address;
};
u8 header_format;
u8 type_descriptors_supported_count;
u8 per_log_type_descriptor_length;
u8 supported_log_type_descriptos[0];
} __packed;

static const struct dmi_system_event_log *to_sel(const struct dmi_header *dh)
{
return (const struct dmi_system_event_log *)dh;
}

#define DMI_SYSFS_SEL_FIELD(_field) \
static ssize_t dmi_sysfs_sel_##_field(struct dmi_sysfs_entry *entry, \
const struct dmi_header *dh, \
char *buf) \
{ \
const struct dmi_system_event_log *sel = to_sel(dh); \
if (sizeof(*sel) > dmi_entry_length(dh)) \
return -EIO; \
return sprintf(buf, "%u\n", sel->_field); \
} \
static DMI_SYSFS_MAPPED_ATTR(sel, _field)

DMI_SYSFS_SEL_FIELD(area_length);
DMI_SYSFS_SEL_FIELD(header_start_offset);
DMI_SYSFS_SEL_FIELD(data_start_offset);
DMI_SYSFS_SEL_FIELD(access_method);
DMI_SYSFS_SEL_FIELD(status);
DMI_SYSFS_SEL_FIELD(change_token);
DMI_SYSFS_SEL_FIELD(access_method_address);
DMI_SYSFS_SEL_FIELD(header_format);
DMI_SYSFS_SEL_FIELD(type_descriptors_supported_count);
DMI_SYSFS_SEL_FIELD(per_log_type_descriptor_length);

static struct attribute *dmi_sysfs_sel_attrs[] = {
&dmi_sysfs_attr_sel_area_length.attr,
&dmi_sysfs_attr_sel_header_start_offset.attr,
&dmi_sysfs_attr_sel_data_start_offset.attr,
&dmi_sysfs_attr_sel_access_method.attr,
&dmi_sysfs_attr_sel_status.attr,
&dmi_sysfs_attr_sel_change_token.attr,
&dmi_sysfs_attr_sel_access_method_address.attr,
&dmi_sysfs_attr_sel_header_format.attr,
&dmi_sysfs_attr_sel_type_descriptors_supported_count.attr,
&dmi_sysfs_attr_sel_per_log_type_descriptor_length.attr,
NULL,
};


static struct kobj_type dmi_system_event_log_ktype = {
.release = dmi_entry_free,
.sysfs_ops = &dmi_sysfs_specialize_attr_ops,
.default_attrs = dmi_sysfs_sel_attrs,
};

static int dmi_system_event_log(struct dmi_sysfs_entry *entry)
{
int ret;

entry->child = kzalloc(sizeof(*entry->child), GFP_KERNEL);
if (!entry->child)
return -ENOMEM;
ret = kobject_init_and_add(entry->child,
&dmi_system_event_log_ktype,
&entry->kobj,
"system_event_log");
if (ret)
goto out_free;
out_free:
kfree(entry->child);
return ret;
}

/*************************************************
* Generic DMI entry support.
*************************************************/
Expand Down Expand Up @@ -325,13 +470,26 @@ static void __init dmi_sysfs_register_handle(const struct dmi_header *dh,
list_add_tail(&entry->list, &entry_list);
spin_unlock(&entry_list_lock);

/* Handle specializations by type */
switch (dh->type) {
case DMI_ENTRY_SYSTEM_EVENT_LOG:
*ret = dmi_system_event_log(entry);
break;
default:
/* No specialization */
break;
}
if (*ret)
goto out_err;

/* Create the raw binary file to access the entry */
*ret = sysfs_create_bin_file(&entry->kobj, &dmi_entry_raw_attr);
if (*ret)
goto out_err;

return;
out_err:
kobject_put(entry->child);
kobject_put(&entry->kobj);
return;
}
Expand All @@ -342,6 +500,7 @@ static void cleanup_entry_list(void)

/* No locks, we are on our way out */
list_for_each_entry_safe(entry, next, &entry_list, list) {
kobject_put(entry->child);
kobject_put(&entry->kobj);
}
}
Expand Down

0 comments on commit e5b6909

Please sign in to comment.