Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 95e300c0 authored by Corey Minyard's avatar Corey Minyard
Browse files

ipmi: Make the DMI probe into a generic platform probe



Rework the DMI probe function to be a generic platform probe, and
then rework the DMI code (and a few other things) to use the more
generic information.  This is so other things can declare platform
IPMI devices.

Signed-off-by: default avatarCorey Minyard <cminyard@mvista.com>
parent 55f91cb6
Loading
Loading
Loading
Loading
+49 −21
Original line number Diff line number Diff line
@@ -8,10 +8,16 @@
#include <linux/dmi.h>
#include <linux/platform_device.h>
#include <linux/property.h>
#include "ipmi_si_sm.h"
#include "ipmi_dmi.h"

#define IPMI_DMI_TYPE_KCS	0x01
#define IPMI_DMI_TYPE_SMIC	0x02
#define IPMI_DMI_TYPE_BT	0x03
#define IPMI_DMI_TYPE_SSIF	0x04

struct ipmi_dmi_info {
	int type;
	enum si_type si_type;
	u32 flags;
	unsigned long addr;
	u8 slave_addr;
@@ -22,6 +28,15 @@ static struct ipmi_dmi_info *ipmi_dmi_infos;

static int ipmi_dmi_nr __initdata;

#define set_prop_entry(_p_, _name_, type, val)	\
do {					\
	struct property_entry *_p = &_p_;	\
	_p->name = _name_;			\
	_p->length = sizeof(type);		\
	_p->is_string = false;			\
	_p->value.type##_data = val;		\
} while(0)

static void __init dmi_add_platform_ipmi(unsigned long base_addr,
					 u32 flags,
					 u8 slave_addr,
@@ -32,27 +47,14 @@ static void __init dmi_add_platform_ipmi(unsigned long base_addr,
	struct platform_device *pdev;
	struct resource r[4];
	unsigned int num_r = 1, size;
	struct property_entry p[4] = {
		PROPERTY_ENTRY_U8("slave-addr", slave_addr),
		PROPERTY_ENTRY_U8("ipmi-type", type),
		PROPERTY_ENTRY_U16("i2c-addr", base_addr),
		{ }
	};
	struct property_entry p[5];
	unsigned int pidx = 0;
	char *name, *override;
	int rv;
	enum si_type si_type;
	struct ipmi_dmi_info *info;

	info = kmalloc(sizeof(*info), GFP_KERNEL);
	if (!info) {
		pr_warn("ipmi:dmi: Could not allocate dmi info\n");
	} else {
		info->type = type;
		info->flags = flags;
		info->addr = base_addr;
		info->slave_addr = slave_addr;
		info->next = ipmi_dmi_infos;
		ipmi_dmi_infos = info;
	}
	memset(p, 0, sizeof(p));

	name = "dmi-ipmi-si";
	override = "ipmi_si";
@@ -62,19 +64,42 @@ static void __init dmi_add_platform_ipmi(unsigned long base_addr,
		override = "ipmi_ssif";
		offset = 1;
		size = 1;
		si_type = SI_TYPE_INVALID;
		break;
	case IPMI_DMI_TYPE_BT:
		size = 3;
		si_type = SI_BT;
		break;
	case IPMI_DMI_TYPE_KCS:
		size = 2;
		si_type = SI_KCS;
		break;
	case IPMI_DMI_TYPE_SMIC:
		size = 2;
		si_type = SI_SMIC;
		break;
	default:
		pr_err("ipmi:dmi: Invalid IPMI type: %d", type);
		return;
	}

	if (si_type != SI_TYPE_INVALID)
		set_prop_entry(p[pidx++], "ipmi-type", u8, si_type);
	set_prop_entry(p[pidx++], "slave-addr", u8, slave_addr);
	set_prop_entry(p[pidx++], "addr-source", u8, SI_SMBIOS);

	info = kmalloc(sizeof(*info), GFP_KERNEL);
	if (!info) {
		pr_warn("ipmi:dmi: Could not allocate dmi info\n");
	} else {
		info->si_type = si_type;
		info->flags = flags;
		info->addr = base_addr;
		info->slave_addr = slave_addr;
		info->next = ipmi_dmi_infos;
		ipmi_dmi_infos = info;
	}

	pdev = platform_device_alloc(name, ipmi_dmi_nr);
	if (!pdev) {
		pr_err("ipmi:dmi: Error allocation IPMI platform device");
@@ -82,8 +107,10 @@ static void __init dmi_add_platform_ipmi(unsigned long base_addr,
	}
	pdev->driver_override = override;

	if (type == IPMI_DMI_TYPE_SSIF)
	if (type == IPMI_DMI_TYPE_SSIF) {
		set_prop_entry(p[pidx++], "i2c-addr", u16, base_addr);
		goto add_properties;
	}

	memset(r, 0, sizeof(r));

@@ -151,12 +178,13 @@ static void __init dmi_add_platform_ipmi(unsigned long base_addr,
 * This function allows an ACPI-specified IPMI device to look up the
 * slave address from the DMI table.
 */
int ipmi_dmi_get_slave_addr(int type, u32 flags, unsigned long base_addr)
int ipmi_dmi_get_slave_addr(enum si_type si_type, u32 flags,
			    unsigned long base_addr)
{
	struct ipmi_dmi_info *info = ipmi_dmi_infos;

	while (info) {
		if (info->type == type &&
		if (info->si_type == si_type &&
		    info->flags == flags &&
		    info->addr == base_addr)
			return info->slave_addr;
+2 −6
Original line number Diff line number Diff line
@@ -2,11 +2,7 @@
 * DMI defines for use by IPMI
 */

#define IPMI_DMI_TYPE_KCS	0x01
#define IPMI_DMI_TYPE_SMIC	0x02
#define IPMI_DMI_TYPE_BT	0x03
#define IPMI_DMI_TYPE_SSIF	0x04

#ifdef CONFIG_IPMI_DMI_DECODE
int ipmi_dmi_get_slave_addr(int type, u32 flags, unsigned long base_addr);
int ipmi_dmi_get_slave_addr(enum si_type si_type, u32 flags,
			    unsigned long base_addr);
#endif
+1 −1
Original line number Diff line number Diff line
@@ -594,7 +594,7 @@ static DEFINE_MUTEX(smi_watchers_mutex);

static const char * const addr_src_to_str[] = {
	"invalid", "hotmod", "hardcoded", "SPMI", "ACPI", "SMBIOS", "PCI",
	"device-tree"
	"device-tree", "platform"
};

const char *ipmi_addr_src_to_str(enum ipmi_addr_src src)
+1 −1
Original line number Diff line number Diff line
@@ -89,7 +89,7 @@ enum si_intf_state {
#define IPMI_BT_INTMASK_CLEAR_IRQ_BIT	2
#define IPMI_BT_INTMASK_ENABLE_IRQ_BIT	1

static const char * const si_to_str[] = { "kcs", "smic", "bt" };
static const char * const si_to_str[] = { "invalid", "kcs", "smic", "bt" };

static int initialized;

+46 −55
Original line number Diff line number Diff line
@@ -6,14 +6,13 @@
 */
#include <linux/types.h>
#include <linux/module.h>
#include "ipmi_dmi.h"
#include <linux/dmi.h>
#include <linux/of_device.h>
#include <linux/of_platform.h>
#include <linux/of_address.h>
#include <linux/of_irq.h>
#include <linux/acpi.h>
#include "ipmi_si.h"
#include "ipmi_dmi.h"

#define PFX "ipmi_platform: "

@@ -21,19 +20,29 @@ static bool si_tryplatform = true;
#ifdef CONFIG_ACPI
static bool          si_tryacpi = true;
#endif
#ifdef CONFIG_OF
static bool          si_tryopenfirmware = true;
#endif
#ifdef CONFIG_DMI
static bool          si_trydmi = true;
#else
static bool          si_trydmi = false;
#endif

module_param_named(tryplatform, si_tryplatform, bool, 0);
MODULE_PARM_DESC(tryplatform, "Setting this to zero will disable the"
		 " default scan of the interfaces identified via platform"
		 " interfaces like openfirmware");
		 " interfaces besides ACPI, OpenFirmware, and DMI");
#ifdef CONFIG_ACPI
module_param_named(tryacpi, si_tryacpi, bool, 0);
MODULE_PARM_DESC(tryacpi, "Setting this to zero will disable the"
		 " default scan of the interfaces identified via ACPI");
#endif
#ifdef CONFIG_OF
module_param_named(tryopenfirmware, si_tryopenfirmware, bool, 0);
MODULE_PARM_DESC(tryacpi, "Setting this to zero will disable the"
		 " default scan of the interfaces identified via OpenFirmware");
#endif
#ifdef CONFIG_DMI
module_param_named(trydmi, si_trydmi, bool, 0);
MODULE_PARM_DESC(trydmi, "Setting this to zero will disable the"
@@ -235,7 +244,6 @@ static void spmi_find_bmc(void)
}
#endif

#if defined(CONFIG_DMI) || defined(CONFIG_ACPI)
static struct resource *
ipmi_get_info_from_resources(struct platform_device *pdev,
			     struct si_sm_io *io)
@@ -271,48 +279,52 @@ ipmi_get_info_from_resources(struct platform_device *pdev,
	return res;
}

#endif

#ifdef CONFIG_DMI
static int dmi_ipmi_probe(struct platform_device *pdev)
static int platform_ipmi_probe(struct platform_device *pdev)
{
	struct si_sm_io io;
	u8 type, slave_addr;
	u8 type, slave_addr, addr_source;
	int rv;

	rv = device_property_read_u8(&pdev->dev, "addr-source", &addr_source);
	if (rv)
		addr_source = SI_PLATFORM;
	if (addr_source >= SI_LAST)
		return -EINVAL;

	if (addr_source == SI_SMBIOS) {
		if (!si_trydmi)
			return -ENODEV;
	} else {
		if (!si_tryplatform)
			return -ENODEV;
	}

	rv = device_property_read_u8(&pdev->dev, "ipmi-type", &type);
	if (rv)
		return -ENODEV;

	memset(&io, 0, sizeof(io));
	io.addr_source = SI_SMBIOS;
	pr_info(PFX "probing via SMBIOS\n");
	io.addr_source = addr_source;
	dev_info(&pdev->dev, PFX "probing via %s\n",
		 ipmi_addr_src_to_str(addr_source));

	switch (type) {
	case IPMI_DMI_TYPE_KCS:
		io.si_type = SI_KCS;
		break;
	case IPMI_DMI_TYPE_SMIC:
		io.si_type = SI_SMIC;
		break;
	case IPMI_DMI_TYPE_BT:
		io.si_type = SI_BT;
	case SI_KCS:
	case SI_SMIC:
	case SI_BT:
		io.si_type = type;
		break;
	default:
		dev_err(&pdev->dev, "ipmi-type property is invalid\n");
		return -EINVAL;
	}

	if (!ipmi_get_info_from_resources(pdev, &io)) {
		rv = -EINVAL;
		goto err_free;
	}
	if (!ipmi_get_info_from_resources(pdev, &io))
		return -EINVAL;

	rv = device_property_read_u8(&pdev->dev, "slave-addr", &slave_addr);
	if (rv) {
		dev_warn(&pdev->dev, "device has no slave-addr property");
		dev_warn(&pdev->dev, "device has no slave-addr property\n");
		io.slave_addr = 0x20;
	} else {
		io.slave_addr = slave_addr;
@@ -333,16 +345,7 @@ static int dmi_ipmi_probe(struct platform_device *pdev)
	ipmi_si_add_smi(&io);

	return 0;

err_free:
	return rv;
}
#else
static int dmi_ipmi_probe(struct platform_device *pdev)
{
	return -ENODEV;
}
#endif /* CONFIG_DMI */

#ifdef CONFIG_OF
static const struct of_device_id of_ipmi_match[] = {
@@ -366,6 +369,9 @@ static int of_ipmi_probe(struct platform_device *pdev)
	int ret;
	int proplen;

	if (!si_tryopenfirmware)
		return -ENODEV;

	dev_info(&pdev->dev, "probing via device tree\n");

	match = of_match_device(of_ipmi_match, &pdev->dev);
@@ -436,25 +442,12 @@ static int find_slave_address(struct si_sm_io *io, int slave_addr)
{
#ifdef CONFIG_IPMI_DMI_DECODE
	if (!slave_addr) {
		int type = -1;
		u32 flags = IORESOURCE_IO;

		switch (io->si_type) {
		case SI_KCS:
			type = IPMI_DMI_TYPE_KCS;
			break;
		case SI_BT:
			type = IPMI_DMI_TYPE_BT;
			break;
		case SI_SMIC:
			type = IPMI_DMI_TYPE_SMIC;
			break;
		}

		if (io->addr_type == IPMI_MEM_ADDR_SPACE)
			flags = IORESOURCE_MEM;

		slave_addr = ipmi_dmi_get_slave_addr(type, flags,
		slave_addr = ipmi_dmi_get_slave_addr(io->si_type, flags,
						     io->addr_data);
	}
#endif
@@ -563,7 +556,7 @@ static int ipmi_probe(struct platform_device *pdev)
	if (acpi_ipmi_probe(pdev) == 0)
		return 0;

	return dmi_ipmi_probe(pdev);
	return platform_ipmi_probe(pdev);
}

static int ipmi_remove(struct platform_device *pdev)
@@ -583,11 +576,9 @@ struct platform_driver ipmi_platform_driver = {

void ipmi_si_platform_init(void)
{
	if (si_tryplatform) {
	int rv = platform_driver_register(&ipmi_platform_driver);
	if (rv)
		pr_err(PFX "Unable to register driver: %d\n", rv);
	}

#ifdef CONFIG_ACPI
	if (si_tryacpi)
Loading