Commit 16f4232ce4d6855361b4eb56262f4a202295c978

Authored by Zhao Yakui
Committed by Len Brown
1 parent cf7d7e5a19

IPMI: Add one interface to get more info of low-level IPMI device

The IPMI smi_watcher will be used to catch the IPMI interface as they
come or go.  In order to communicate with the correct IPMI device, it
should be confirmed whether it is what we wanted especially on the
system with multiple IPMI devices. But the new_smi callback function
of smi_watcher provides very limited info(only the interface number
and dev pointer) and there is no detailed info about the low level
interface. For example: which mechansim registers the IPMI
interface(ACPI, PCI, DMI and so on).

This is to add one interface that can get more info of low-level IPMI
device. For example: the ACPI device handle will be returned for the
pnp_acpi IPMI device.

Signed-off-by: Zhao Yakui <yakui.zhao@intel.com>
Signed-off-by: Corey Minyard <cminyard@mvista.com>
Signed-off-by: Len Brown <len.brown@intel.com>

Showing 4 changed files with 89 additions and 4 deletions Side-by-side Diff

drivers/char/ipmi/ipmi_msghandler.c
... ... @@ -970,6 +970,33 @@
970 970 }
971 971 EXPORT_SYMBOL(ipmi_create_user);
972 972  
  973 +int ipmi_get_smi_info(int if_num, struct ipmi_smi_info *data)
  974 +{
  975 + int rv = 0;
  976 + ipmi_smi_t intf;
  977 + struct ipmi_smi_handlers *handlers;
  978 +
  979 + mutex_lock(&ipmi_interfaces_mutex);
  980 + list_for_each_entry_rcu(intf, &ipmi_interfaces, link) {
  981 + if (intf->intf_num == if_num)
  982 + goto found;
  983 + }
  984 + /* Not found, return an error */
  985 + rv = -EINVAL;
  986 + mutex_unlock(&ipmi_interfaces_mutex);
  987 + return rv;
  988 +
  989 +found:
  990 + handlers = intf->handlers;
  991 + rv = -ENOSYS;
  992 + if (handlers->get_smi_info)
  993 + rv = handlers->get_smi_info(intf->send_info, data);
  994 + mutex_unlock(&ipmi_interfaces_mutex);
  995 +
  996 + return rv;
  997 +}
  998 +EXPORT_SYMBOL(ipmi_get_smi_info);
  999 +
973 1000 static void free_user(struct kref *ref)
974 1001 {
975 1002 ipmi_user_t user = container_of(ref, struct ipmi_user, refcount);
drivers/char/ipmi/ipmi_si_intf.c
... ... @@ -57,6 +57,7 @@
57 57 #include <asm/irq.h>
58 58 #include <linux/interrupt.h>
59 59 #include <linux/rcupdate.h>
  60 +#include <linux/ipmi.h>
60 61 #include <linux/ipmi_smi.h>
61 62 #include <asm/io.h>
62 63 #include "ipmi_si_sm.h"
... ... @@ -107,10 +108,6 @@
107 108 };
108 109 static char *si_to_str[] = { "kcs", "smic", "bt" };
109 110  
110   -enum ipmi_addr_src {
111   - SI_INVALID = 0, SI_HOTMOD, SI_HARDCODED, SI_SPMI, SI_ACPI, SI_SMBIOS,
112   - SI_PCI, SI_DEVICETREE, SI_DEFAULT
113   -};
114 111 static char *ipmi_addr_src_to_str[] = { NULL, "hotmod", "hardcoded", "SPMI",
115 112 "ACPI", "SMBIOS", "PCI",
116 113 "device-tree", "default" };
... ... @@ -291,6 +288,7 @@
291 288 struct task_struct *thread;
292 289  
293 290 struct list_head link;
  291 + union ipmi_smi_info_union addr_info;
294 292 };
295 293  
296 294 #define smi_inc_stat(smi, stat) \
... ... @@ -1186,6 +1184,18 @@
1186 1184 return 0;
1187 1185 }
1188 1186  
  1187 +static int get_smi_info(void *send_info, struct ipmi_smi_info *data)
  1188 +{
  1189 + struct smi_info *smi = send_info;
  1190 +
  1191 + data->addr_src = smi->addr_source;
  1192 + data->dev = smi->dev;
  1193 + data->addr_info = smi->addr_info;
  1194 + get_device(smi->dev);
  1195 +
  1196 + return 0;
  1197 +}
  1198 +
1189 1199 static void set_maintenance_mode(void *send_info, int enable)
1190 1200 {
1191 1201 struct smi_info *smi_info = send_info;
... ... @@ -1197,6 +1207,7 @@
1197 1207 static struct ipmi_smi_handlers handlers = {
1198 1208 .owner = THIS_MODULE,
1199 1209 .start_processing = smi_start_processing,
  1210 + .get_smi_info = get_smi_info,
1200 1211 .sender = sender,
1201 1212 .request_events = request_events,
1202 1213 .set_maintenance_mode = set_maintenance_mode,
... ... @@ -2156,6 +2167,7 @@
2156 2167 printk(KERN_INFO PFX "probing via ACPI\n");
2157 2168  
2158 2169 handle = acpi_dev->handle;
  2170 + info->addr_info.acpi_info.acpi_handle = handle;
2159 2171  
2160 2172 /* _IFT tells us the interface type: KCS, BT, etc */
2161 2173 status = acpi_evaluate_integer(handle, "_IFT", NULL, &tmp);
include/linux/ipmi.h
... ... @@ -454,6 +454,44 @@
454 454 /* Validate that the given IPMI address is valid. */
455 455 int ipmi_validate_addr(struct ipmi_addr *addr, int len);
456 456  
  457 +/*
  458 + * How did the IPMI driver find out about the device?
  459 + */
  460 +enum ipmi_addr_src {
  461 + SI_INVALID = 0, SI_HOTMOD, SI_HARDCODED, SI_SPMI, SI_ACPI, SI_SMBIOS,
  462 + SI_PCI, SI_DEVICETREE, SI_DEFAULT
  463 +};
  464 +
  465 +union ipmi_smi_info_union {
  466 + /*
  467 + * the acpi_info element is defined for the SI_ACPI
  468 + * address type
  469 + */
  470 + struct {
  471 + void *acpi_handle;
  472 + } acpi_info;
  473 +};
  474 +
  475 +struct ipmi_smi_info {
  476 + enum ipmi_addr_src addr_src;
  477 +
  478 + /*
  479 + * Base device for the interface. Don't forget to put this when
  480 + * you are done.
  481 + */
  482 + struct device *dev;
  483 +
  484 + /*
  485 + * The addr_info provides more detailed info for some IPMI
  486 + * devices, depending on the addr_src. Currently only SI_ACPI
  487 + * info is provided.
  488 + */
  489 + union ipmi_smi_info_union addr_info;
  490 +};
  491 +
  492 +/* This is to get the private info of ipmi_smi_t */
  493 +extern int ipmi_get_smi_info(int if_num, struct ipmi_smi_info *data);
  494 +
457 495 #endif /* __KERNEL__ */
458 496  
459 497  
include/linux/ipmi_smi.h
... ... @@ -39,6 +39,7 @@
39 39 #include <linux/module.h>
40 40 #include <linux/device.h>
41 41 #include <linux/platform_device.h>
  42 +#include <linux/ipmi.h>
42 43  
43 44 /* This files describes the interface for IPMI system management interface
44 45 drivers to bind into the IPMI message handler. */
... ... @@ -85,6 +86,13 @@
85 86 this call. */
86 87 int (*start_processing)(void *send_info,
87 88 ipmi_smi_t new_intf);
  89 +
  90 + /*
  91 + * Get the detailed private info of the low level interface and store
  92 + * it into the structure of ipmi_smi_data. For example: the
  93 + * ACPI device handle will be returned for the pnp_acpi IPMI device.
  94 + */
  95 + int (*get_smi_info)(void *send_info, struct ipmi_smi_info *data);
88 96  
89 97 /* Called to enqueue an SMI message to be sent. This
90 98 operation is not allowed to fail. If an error occurs, it