Skip to content

Commit

Permalink
ipmi: Make the DMI probe into a generic platform probe
Browse files Browse the repository at this point in the history
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: Corey Minyard <cminyard@mvista.com>
  • Loading branch information
Corey Minyard committed Sep 28, 2017
1 parent 55f91cb commit 95e300c
Show file tree
Hide file tree
Showing 8 changed files with 104 additions and 95 deletions.
70 changes: 49 additions & 21 deletions drivers/char/ipmi/ipmi_dmi.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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,
Expand All @@ -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";
Expand All @@ -62,28 +64,53 @@ 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");
return;
}
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));

Expand Down Expand Up @@ -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;
Expand Down
8 changes: 2 additions & 6 deletions drivers/char/ipmi/ipmi_dmi.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
2 changes: 1 addition & 1 deletion drivers/char/ipmi/ipmi_msghandler.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
2 changes: 1 addition & 1 deletion drivers/char/ipmi/ipmi_si_intf.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down
101 changes: 46 additions & 55 deletions drivers/char/ipmi/ipmi_si_platform.c
Original file line number Diff line number Diff line change
Expand Up @@ -6,34 +6,43 @@
*/
#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: "

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"
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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;

if (!si_trydmi)
return -ENODEV;
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;
Expand All @@ -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[] = {
Expand All @@ -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);
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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)
Expand All @@ -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);
}
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)
Expand Down
2 changes: 1 addition & 1 deletion drivers/char/ipmi/ipmi_si_sm.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@
struct si_sm_data;

enum si_type {
SI_KCS, SI_SMIC, SI_BT
SI_TYPE_INVALID, SI_KCS, SI_SMIC, SI_BT
};

/*
Expand Down
Loading

0 comments on commit 95e300c

Please sign in to comment.