[PATCH 2/4] dmi: Add a DMI firmware node and handling

From: minyard
Date: Fri Jan 29 2016 - 18:44:05 EST


From: Corey Minyard <cminyard@xxxxxxxxxx>

This is so that an IPMI platform device can be created from a
DMI firmware entry.

Signed-off-by: Corey Minyard <cminyard@xxxxxxxxxx>
Cc: Jean Delvare <jdelvare@xxxxxxx>
Cc: Andy Lutomirski <luto@xxxxxxxxxx>
---
drivers/firmware/dmi_scan.c | 34 ++++++++++++++++++++++++----------
include/linux/dmi.h | 24 ++++++++++++++++++++++++
include/linux/fwnode.h | 1 +
3 files changed, 49 insertions(+), 10 deletions(-)

diff --git a/drivers/firmware/dmi_scan.c b/drivers/firmware/dmi_scan.c
index da471b2..13d9bca 100644
--- a/drivers/firmware/dmi_scan.c
+++ b/drivers/firmware/dmi_scan.c
@@ -41,6 +41,16 @@ static struct dmi_memdev_info {
} *dmi_memdev;
static int dmi_memdev_nr;

+static void *dmi_zalloc(unsigned len)
+{
+ void *ret = dmi_alloc(len);
+
+ if (ret)
+ memset(ret, 0, len);
+
+ return ret;
+}
+
static const char * __init dmi_string_nosave(const struct dmi_header *dm, u8 s)
{
const u8 *bp = ((u8 *) dm) + dm->length;
@@ -242,6 +252,12 @@ static void __init dmi_save_type(const struct dmi_header *dm, int slot,
dmi_ident[slot] = s;
}

+static void __init dmi_devices_list_add(struct dmi_device *dev)
+{
+ dev->fwnode.type = FWNODE_DMI;
+ list_add(&dev->list, &dmi_devices);
+}
+
static void __init dmi_save_one_device(int type, const char *name)
{
struct dmi_device *dev;
@@ -250,15 +266,14 @@ static void __init dmi_save_one_device(int type, const char *name)
if (dmi_find_device(type, name, NULL))
return;

- dev = dmi_alloc(sizeof(*dev) + strlen(name) + 1);
+ dev = dmi_zalloc(sizeof(*dev) + strlen(name) + 1);
if (!dev)
return;

dev->type = type;
strcpy((char *)(dev + 1), name);
dev->name = (char *)(dev + 1);
- dev->device_data = NULL;
- list_add(&dev->list, &dmi_devices);
+ dmi_devices_list_add(dev);
}

static void __init dmi_save_devices(const struct dmi_header *dm)
@@ -287,15 +302,14 @@ static void __init dmi_save_oem_strings_devices(const struct dmi_header *dm)
if (devname == dmi_empty_string)
continue;

- dev = dmi_alloc(sizeof(*dev));
+ dev = dmi_zalloc(sizeof(*dev));
if (!dev)
break;

dev->type = DMI_DEV_TYPE_OEM_STRING;
dev->name = devname;
- dev->device_data = NULL;

- list_add(&dev->list, &dmi_devices);
+ dmi_devices_list_add(dev);
}
}

@@ -310,7 +324,7 @@ static void __init dmi_save_ipmi_device(const struct dmi_header *dm)

memcpy(data, dm, dm->length);

- dev = dmi_alloc(sizeof(*dev));
+ dev = dmi_zalloc(sizeof(*dev));
if (!dev)
return;

@@ -318,7 +332,7 @@ static void __init dmi_save_ipmi_device(const struct dmi_header *dm)
dev->name = "IPMI controller";
dev->device_data = data;

- list_add_tail(&dev->list, &dmi_devices);
+ dmi_devices_list_add(dev);
}

static void __init dmi_save_dev_pciaddr(int instance, int segment, int bus,
@@ -331,7 +345,7 @@ static void __init dmi_save_dev_pciaddr(int instance, int segment, int bus,
segment == 0xFFFF && bus == 0xFF && devfn == 0xFF)
return;

- dev = dmi_alloc(sizeof(*dev) + strlen(name) + 1);
+ dev = dmi_zalloc(sizeof(*dev) + strlen(name) + 1);
if (!dev)
return;

@@ -345,7 +359,7 @@ static void __init dmi_save_dev_pciaddr(int instance, int segment, int bus,
dev->dev.name = (char *)&dev[1];
dev->dev.device_data = dev;

- list_add(&dev->dev.list, &dmi_devices);
+ dmi_devices_list_add(&dev->dev);
}

static void __init dmi_save_extended_devices(const struct dmi_header *dm)
diff --git a/include/linux/dmi.h b/include/linux/dmi.h
index a930a4d..e130c38 100644
--- a/include/linux/dmi.h
+++ b/include/linux/dmi.h
@@ -4,6 +4,7 @@
#include <linux/list.h>
#include <linux/kobject.h>
#include <linux/mod_devicetable.h>
+#include <linux/fwnode.h>

/* enum dmi_field is in mod_devicetable.h */

@@ -80,6 +81,7 @@ struct dmi_header {

struct dmi_device {
struct list_head list;
+ struct fwnode_handle fwnode;
int type;
const char *name;
void *device_data; /* Type specific data */
@@ -113,6 +115,18 @@ extern int dmi_walk(void (*decode)(const struct dmi_header *, void *),
extern bool dmi_match(enum dmi_field f, const char *str);
extern void dmi_memdev_name(u16 handle, const char **bank, const char **device);

+static inline bool is_dmi_fwnode(struct fwnode_handle *fwnode)
+{
+ return fwnode && fwnode->type == FWNODE_DMI;
+}
+
+static inline struct dmi_device *to_dmi_device(struct fwnode_handle *fwnode)
+{
+ if (is_dmi_fwnode(fwnode))
+ return container_of(fwnode, struct dmi_device, fwnode);
+ return NULL;
+}
+
#else

static inline int dmi_check_system(const struct dmi_system_id *list) { return 0; }
@@ -144,6 +158,16 @@ static inline void dmi_memdev_name(u16 handle, const char **bank,
static inline const struct dmi_system_id *
dmi_first_match(const struct dmi_system_id *list) { return NULL; }

+static inline bool is_dmi_fwnode(struct fwnode_handle *fwnode)
+{
+ return false
+}
+
+static inline struct dmi_fwnode *to_dmi_device(struct fwnode_handle *fwnode)
+{
+ return NULL;
+}
+
#endif

#endif /* __DMI_H__ */
diff --git a/include/linux/fwnode.h b/include/linux/fwnode.h
index 8516717..8690de2 100644
--- a/include/linux/fwnode.h
+++ b/include/linux/fwnode.h
@@ -19,6 +19,7 @@ enum fwnode_type {
FWNODE_ACPI_DATA,
FWNODE_PDATA,
FWNODE_IRQCHIP,
+ FWNODE_DMI,
};

struct fwnode_handle {
--
2.5.0