Commit 4b63bd35 authored by Len Brown's avatar Len Brown

Merge branch 'ipmi' into release

parents 03b6e6e5 e92b297c
...@@ -533,6 +533,33 @@ completion during sending a panic event. ...@@ -533,6 +533,33 @@ completion during sending a panic event.
Other Pieces Other Pieces
------------ ------------
Get the detailed info related with the IPMI device
--------------------------------------------------
Some users need more detailed information about a device, like where
the address came from or the raw base device for the IPMI interface.
You can use the IPMI smi_watcher to catch the IPMI interfaces as they
come or go, and to grab the information, you can use the function
ipmi_get_smi_info(), which returns the following structure:
struct ipmi_smi_info {
enum ipmi_addr_src addr_src;
struct device *dev;
union {
struct {
void *acpi_handle;
} acpi_info;
} addr_info;
};
Currently special info for only for SI_ACPI address sources is
returned. Others may be added as necessary.
Note that the dev pointer is included in the above structure, and
assuming ipmi_smi_get_info returns success, you must call put_device
on the dev pointer.
Watchdog Watchdog
-------- --------
......
...@@ -207,6 +207,17 @@ config ACPI_PROCESSOR ...@@ -207,6 +207,17 @@ config ACPI_PROCESSOR
To compile this driver as a module, choose M here: To compile this driver as a module, choose M here:
the module will be called processor. the module will be called processor.
config ACPI_IPMI
tristate "IPMI"
depends on EXPERIMENTAL && IPMI_SI && IPMI_HANDLER
default n
help
This driver enables the ACPI to access the BMC controller. And it
uses the IPMI request/response message to communicate with BMC
controller, which can be found on on the server.
To compile this driver as a module, choose M here:
the module will be called as acpi_ipmi.
config ACPI_HOTPLUG_CPU config ACPI_HOTPLUG_CPU
bool bool
......
...@@ -69,5 +69,6 @@ processor-y += processor_idle.o processor_thermal.o ...@@ -69,5 +69,6 @@ processor-y += processor_idle.o processor_thermal.o
processor-$(CONFIG_CPU_FREQ) += processor_perflib.o processor-$(CONFIG_CPU_FREQ) += processor_perflib.o
obj-$(CONFIG_ACPI_PROCESSOR_AGGREGATOR) += acpi_pad.o obj-$(CONFIG_ACPI_PROCESSOR_AGGREGATOR) += acpi_pad.o
obj-$(CONFIG_ACPI_IPMI) += acpi_ipmi.o
obj-$(CONFIG_ACPI_APEI) += apei/ obj-$(CONFIG_ACPI_APEI) += apei/
This diff is collapsed.
...@@ -970,6 +970,33 @@ int ipmi_create_user(unsigned int if_num, ...@@ -970,6 +970,33 @@ int ipmi_create_user(unsigned int if_num,
} }
EXPORT_SYMBOL(ipmi_create_user); EXPORT_SYMBOL(ipmi_create_user);
int ipmi_get_smi_info(int if_num, struct ipmi_smi_info *data)
{
int rv = 0;
ipmi_smi_t intf;
struct ipmi_smi_handlers *handlers;
mutex_lock(&ipmi_interfaces_mutex);
list_for_each_entry_rcu(intf, &ipmi_interfaces, link) {
if (intf->intf_num == if_num)
goto found;
}
/* Not found, return an error */
rv = -EINVAL;
mutex_unlock(&ipmi_interfaces_mutex);
return rv;
found:
handlers = intf->handlers;
rv = -ENOSYS;
if (handlers->get_smi_info)
rv = handlers->get_smi_info(intf->send_info, data);
mutex_unlock(&ipmi_interfaces_mutex);
return rv;
}
EXPORT_SYMBOL(ipmi_get_smi_info);
static void free_user(struct kref *ref) static void free_user(struct kref *ref)
{ {
ipmi_user_t user = container_of(ref, struct ipmi_user, refcount); ipmi_user_t user = container_of(ref, struct ipmi_user, refcount);
......
...@@ -57,6 +57,7 @@ ...@@ -57,6 +57,7 @@
#include <asm/irq.h> #include <asm/irq.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/rcupdate.h> #include <linux/rcupdate.h>
#include <linux/ipmi.h>
#include <linux/ipmi_smi.h> #include <linux/ipmi_smi.h>
#include <asm/io.h> #include <asm/io.h>
#include "ipmi_si_sm.h" #include "ipmi_si_sm.h"
...@@ -107,10 +108,6 @@ enum si_type { ...@@ -107,10 +108,6 @@ enum si_type {
}; };
static char *si_to_str[] = { "kcs", "smic", "bt" }; static char *si_to_str[] = { "kcs", "smic", "bt" };
enum ipmi_addr_src {
SI_INVALID = 0, SI_HOTMOD, SI_HARDCODED, SI_SPMI, SI_ACPI, SI_SMBIOS,
SI_PCI, SI_DEVICETREE, SI_DEFAULT
};
static char *ipmi_addr_src_to_str[] = { NULL, "hotmod", "hardcoded", "SPMI", static char *ipmi_addr_src_to_str[] = { NULL, "hotmod", "hardcoded", "SPMI",
"ACPI", "SMBIOS", "PCI", "ACPI", "SMBIOS", "PCI",
"device-tree", "default" }; "device-tree", "default" };
...@@ -291,6 +288,7 @@ struct smi_info { ...@@ -291,6 +288,7 @@ struct smi_info {
struct task_struct *thread; struct task_struct *thread;
struct list_head link; struct list_head link;
union ipmi_smi_info_union addr_info;
}; };
#define smi_inc_stat(smi, stat) \ #define smi_inc_stat(smi, stat) \
...@@ -1186,6 +1184,18 @@ static int smi_start_processing(void *send_info, ...@@ -1186,6 +1184,18 @@ static int smi_start_processing(void *send_info,
return 0; return 0;
} }
static int get_smi_info(void *send_info, struct ipmi_smi_info *data)
{
struct smi_info *smi = send_info;
data->addr_src = smi->addr_source;
data->dev = smi->dev;
data->addr_info = smi->addr_info;
get_device(smi->dev);
return 0;
}
static void set_maintenance_mode(void *send_info, int enable) static void set_maintenance_mode(void *send_info, int enable)
{ {
struct smi_info *smi_info = send_info; struct smi_info *smi_info = send_info;
...@@ -1197,6 +1207,7 @@ static void set_maintenance_mode(void *send_info, int enable) ...@@ -1197,6 +1207,7 @@ static void set_maintenance_mode(void *send_info, int enable)
static struct ipmi_smi_handlers handlers = { static struct ipmi_smi_handlers handlers = {
.owner = THIS_MODULE, .owner = THIS_MODULE,
.start_processing = smi_start_processing, .start_processing = smi_start_processing,
.get_smi_info = get_smi_info,
.sender = sender, .sender = sender,
.request_events = request_events, .request_events = request_events,
.set_maintenance_mode = set_maintenance_mode, .set_maintenance_mode = set_maintenance_mode,
...@@ -2157,6 +2168,7 @@ static int __devinit ipmi_pnp_probe(struct pnp_dev *dev, ...@@ -2157,6 +2168,7 @@ static int __devinit ipmi_pnp_probe(struct pnp_dev *dev,
printk(KERN_INFO PFX "probing via ACPI\n"); printk(KERN_INFO PFX "probing via ACPI\n");
handle = acpi_dev->handle; handle = acpi_dev->handle;
info->addr_info.acpi_info.acpi_handle = handle;
/* _IFT tells us the interface type: KCS, BT, etc */ /* _IFT tells us the interface type: KCS, BT, etc */
status = acpi_evaluate_integer(handle, "_IFT", NULL, &tmp); status = acpi_evaluate_integer(handle, "_IFT", NULL, &tmp);
......
...@@ -454,6 +454,44 @@ unsigned int ipmi_addr_length(int addr_type); ...@@ -454,6 +454,44 @@ unsigned int ipmi_addr_length(int addr_type);
/* Validate that the given IPMI address is valid. */ /* Validate that the given IPMI address is valid. */
int ipmi_validate_addr(struct ipmi_addr *addr, int len); int ipmi_validate_addr(struct ipmi_addr *addr, int len);
/*
* How did the IPMI driver find out about the device?
*/
enum ipmi_addr_src {
SI_INVALID = 0, SI_HOTMOD, SI_HARDCODED, SI_SPMI, SI_ACPI, SI_SMBIOS,
SI_PCI, SI_DEVICETREE, SI_DEFAULT
};
union ipmi_smi_info_union {
/*
* the acpi_info element is defined for the SI_ACPI
* address type
*/
struct {
void *acpi_handle;
} acpi_info;
};
struct ipmi_smi_info {
enum ipmi_addr_src addr_src;
/*
* Base device for the interface. Don't forget to put this when
* you are done.
*/
struct device *dev;
/*
* The addr_info provides more detailed info for some IPMI
* devices, depending on the addr_src. Currently only SI_ACPI
* info is provided.
*/
union ipmi_smi_info_union addr_info;
};
/* This is to get the private info of ipmi_smi_t */
extern int ipmi_get_smi_info(int if_num, struct ipmi_smi_info *data);
#endif /* __KERNEL__ */ #endif /* __KERNEL__ */
......
...@@ -39,6 +39,7 @@ ...@@ -39,6 +39,7 @@
#include <linux/module.h> #include <linux/module.h>
#include <linux/device.h> #include <linux/device.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/ipmi.h>
/* This files describes the interface for IPMI system management interface /* This files describes the interface for IPMI system management interface
drivers to bind into the IPMI message handler. */ drivers to bind into the IPMI message handler. */
...@@ -86,6 +87,13 @@ struct ipmi_smi_handlers { ...@@ -86,6 +87,13 @@ struct ipmi_smi_handlers {
int (*start_processing)(void *send_info, int (*start_processing)(void *send_info,
ipmi_smi_t new_intf); ipmi_smi_t new_intf);
/*
* Get the detailed private info of the low level interface and store
* it into the structure of ipmi_smi_data. For example: the
* ACPI device handle will be returned for the pnp_acpi IPMI device.
*/
int (*get_smi_info)(void *send_info, struct ipmi_smi_info *data);
/* Called to enqueue an SMI message to be sent. This /* Called to enqueue an SMI message to be sent. This
operation is not allowed to fail. If an error occurs, it operation is not allowed to fail. If an error occurs, it
should report back the error in a received message. It may should report back the error in a received message. It may
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment