linux-acpi.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [RFC PATCH 2/4] IPMI: Remove the redundant definition of ipmi_addr_src
  2010-10-12  7:47 ` [RFC PATCH 1/4] IPMI: Add one interface to get more info of low-level IPMI device yakui.zhao
@ 2010-10-12  7:47   ` yakui.zhao
  0 siblings, 0 replies; 11+ messages in thread
From: yakui.zhao @ 2010-10-12  7:47 UTC (permalink / raw)
  To: openipmi-developer, linux-acpi; +Cc: minyard, lenb, Zhao Yakui

From: Zhao Yakui <yakui.zhao@intel.com>

The ipmi_addr_src is defined twice. One is in ipmi_smi_info and the other
is in generic smi_info. Remove the redunant definition in smi_info.

Signed-off-by: Zhao Yakui <yakui.zhao@intel.com>
---
 drivers/char/ipmi/ipmi_si_intf.c |   36 +++++++++++++++++-------------------
 1 files changed, 17 insertions(+), 19 deletions(-)

diff --git a/drivers/char/ipmi/ipmi_si_intf.c b/drivers/char/ipmi/ipmi_si_intf.c
index 4885709..996a62a 100644
--- a/drivers/char/ipmi/ipmi_si_intf.c
+++ b/drivers/char/ipmi/ipmi_si_intf.c
@@ -193,7 +193,6 @@ struct smi_info {
 	int (*irq_setup)(struct smi_info *info);
 	void (*irq_cleanup)(struct smi_info *info);
 	unsigned int io_size;
-	enum ipmi_addr_src addr_source; /* ACPI, PCI, SMBIOS, hardcode, etc. */
 	void (*addr_source_cleanup)(struct smi_info *info);
 	void *addr_source_data;
 
@@ -1191,12 +1190,11 @@ static int get_smi_info(void *send_info,
 	struct smi_info *new_smi = send_info;
 	struct ipmi_smi_info *smi_data = &new_smi->smi_data;
 
-	if (new_smi->addr_source != type)
+	if (smi_data->addr_src != type)
 		return -EINVAL;
 
 	get_device(new_smi->dev);
 	memcpy(data, smi_data, sizeof(*smi_data));
-	smi_data->addr_src = type;
 	smi_data->dev = new_smi->dev;
 
 	return 0;
@@ -1810,7 +1808,7 @@ static int hotmod_handler(const char *val, struct kernel_param *kp)
 				goto out;
 			}
 
-			info->addr_source = SI_HOTMOD;
+			info->smi_data.addr_src = SI_HOTMOD;
 			info->si_type = si_type;
 			info->io.addr_data = addr;
 			info->io.addr_type = addr_space;
@@ -1873,7 +1871,7 @@ static __devinit void hardcode_find_bmc(void)
 		if (!info)
 			return;
 
-		info->addr_source = SI_HARDCODED;
+		info->smi_data.addr_src = SI_HARDCODED;
 		printk(KERN_INFO PFX "probing via hardcoded address\n");
 
 		if (!si_type[i] || strcmp(si_type[i], "kcs") == 0) {
@@ -2059,7 +2057,7 @@ static __devinit int try_init_spmi(struct SPMITable *spmi)
 		return -ENOMEM;
 	}
 
-	info->addr_source = SI_SPMI;
+	info->smi_data.addr_src = SI_SPMI;
 	printk(KERN_INFO PFX "probing via SPMI\n");
 
 	/* Figure out the interface type. */
@@ -2167,7 +2165,7 @@ static int __devinit ipmi_pnp_probe(struct pnp_dev *dev,
 	if (!info)
 		return -ENOMEM;
 
-	info->addr_source = SI_ACPI;
+	info->smi_data.addr_src = SI_ACPI;
 	info->smi_data.smi_info.acpi_info.acpi_handle =
 				acpi_dev->handle;
 	printk(KERN_INFO PFX "probing via ACPI\n");
@@ -2352,7 +2350,7 @@ static __devinit void try_init_dmi(struct dmi_ipmi_data *ipmi_data)
 		return;
 	}
 
-	info->addr_source = SI_SMBIOS;
+	info->smi_data.addr_src = SI_SMBIOS;
 	printk(KERN_INFO PFX "probing via SMBIOS\n");
 
 	switch (ipmi_data->type) {
@@ -2457,7 +2455,7 @@ static int __devinit ipmi_pci_probe(struct pci_dev *pdev,
 	if (!info)
 		return -ENOMEM;
 
-	info->addr_source = SI_PCI;
+	info->smi_data.addr_src = SI_PCI;
 	dev_info(&pdev->dev, "probing via PCI");
 
 	switch (class_type) {
@@ -2603,7 +2601,7 @@ static int __devinit ipmi_of_probe(struct platform_device *dev,
 	}
 
 	info->si_type		= (enum si_type) match->data;
-	info->addr_source	= SI_DEVICETREE;
+	info->smi_data.addr_src	= SI_DEVICETREE;
 	info->irq_setup		= std_irq_setup;
 
 	if (resource.flags & IORESOURCE_IO) {
@@ -3045,7 +3043,7 @@ static __devinit void default_find_bmc(void)
 		if (!info)
 			return;
 
-		info->addr_source = SI_DEFAULT;
+		info->smi_data.addr_src = SI_DEFAULT;
 
 		info->si_type = ipmi_defaults[i].type;
 		info->io_setup = port_setup;
@@ -3092,7 +3090,7 @@ static int add_smi(struct smi_info *new_smi)
 	int rv = 0;
 
 	printk(KERN_INFO PFX "Adding %s-specified %s state machine",
-			ipmi_addr_src_to_str[new_smi->addr_source],
+			ipmi_addr_src_to_str[new_smi->smi_data.addr_src],
 			si_to_str[new_smi->si_type]);
 	mutex_lock(&smi_infos_lock);
 	if (!is_new_interface(new_smi)) {
@@ -3123,7 +3121,7 @@ static int try_smi_init(struct smi_info *new_smi)
 	printk(KERN_INFO PFX "Trying %s-specified %s state"
 	       " machine at %s address 0x%lx, slave address 0x%x,"
 	       " irq %d\n",
-	       ipmi_addr_src_to_str[new_smi->addr_source],
+	       ipmi_addr_src_to_str[new_smi->smi_data.addr_src],
 	       si_to_str[new_smi->si_type],
 	       addr_space_to_str[new_smi->io.addr_type],
 	       new_smi->io.addr_data,
@@ -3171,7 +3169,7 @@ static int try_smi_init(struct smi_info *new_smi)
 
 	/* Do low-level detection first. */
 	if (new_smi->handlers->detect(new_smi->si_sm)) {
-		if (new_smi->addr_source)
+		if (new_smi->smi_data.addr_src)
 			printk(KERN_INFO PFX "Interface detection failed\n");
 		rv = -ENODEV;
 		goto out_err;
@@ -3183,7 +3181,7 @@ static int try_smi_init(struct smi_info *new_smi)
 	 */
 	rv = try_get_dev_id(new_smi);
 	if (rv) {
-		if (new_smi->addr_source)
+		if (new_smi->smi_data.addr_src)
 			printk(KERN_INFO PFX "There appears to be no BMC"
 			       " at this location\n");
 		goto out_err;
@@ -3415,9 +3413,9 @@ static __devinit int init_ipmi_si(void)
 		/* Try to register a device if it has an IRQ and we either
 		   haven't successfully registered a device yet or this
 		   device has the same type as one we successfully registered */
-		if (e->irq && (!type || e->addr_source == type)) {
+		if (e->irq && (!type || e->smi_data.addr_src == type)) {
 			if (!try_smi_init(e)) {
-				type = e->addr_source;
+				type = e->smi_data.addr_src;
 			}
 		}
 	}
@@ -3431,9 +3429,9 @@ static __devinit int init_ipmi_si(void)
 	/* Fall back to the preferred device */
 
 	list_for_each_entry(e, &smi_infos, link) {
-		if (!e->irq && (!type || e->addr_source == type)) {
+		if (!e->irq && (!type || e->smi_data.addr_src == type)) {
 			if (!try_smi_init(e)) {
-				type = e->addr_source;
+				type = e->smi_data.addr_src;
 			}
 		}
 	}
-- 
1.5.4.5


^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [RFC PATCH 0/4_v11] IPMI/ACPI: Install the ACPI IPMI opregion
@ 2010-10-22  9:10 yakui.zhao
  2010-10-22  9:10 ` [RFC PATCH 1/4] IPMI: Add one interface to get more info of low-level IPMI device yakui.zhao
  0 siblings, 1 reply; 11+ messages in thread
From: yakui.zhao @ 2010-10-22  9:10 UTC (permalink / raw)
  To: openipmi-developer, linux-acpi; +Cc: minyard, lenb, Zhao Yakui

From: Zhao Yakui <yakui.zhao@intel.com>

Hi, 
	
    ACPI 4.0 spec adds the ACPI IPMI opregion, which means that the ACPI AML
code can also communicate with the BMC controller. This patch set is to
install the ACPI IPMI opregion space handler and enable the ACPI to access
the BMC controller through the IPMI message.

[RFC Patch 01/04]: Add one interface to get more info of low-level interface
	It will return the corresponding info of low-level interface based 
	on the expected type(For example: SI_ACPI, SI_PCI and so on.)

[RFC Patch 02/04]: Remove the redudant definition of ipmi_addr_src type

[RFC Patch 03/04]: Add the document description about how to use the function
of ipmi_get_smi_info

[RFC Patch 04/04]: Install the IPMI space handler to enable ACPI to access the BMC
controller

V10->V11: Delete the incorrect refcount in V10. At the same time the function of
ipmi_get_smi_info will return the reference pointer to avoid the memory copy.

V9-V10: Redefine the interface function to get more info of low-level IPMI
device. And add the document description about how to use it. 

V8-V9: This patch set is based on the mechanism that 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. Then the second patch will use the added interface
to check whether the IPMI device is what ACPI wanted to communicated with in the
new_smi callback function of smi_watcher. If it is, we will install the IPMI
opregion handler and enable ACPI to communicate with BMC.

V7->V8: Based on Bjorn's comment, use acpi ipmi notifier hook function to
avoid the discovery of ACPI pnp IPMI device again. Then in course of binding
/unbinding ipmi pnp driver with the corresponding device, the notifier chain
function will be called to install/uninstall the ACPI IPMI opregion space
handler. 

V6->V7: Based on Corey Minyard's comments, the IPMI opregion handler is put
into the separate file again as it only uses the API interface provided
by IPMI system. Now it is put into the ACPI subsystem.

V5->V6: Adjust the patch order and refresh the patch set.

V4->V5: According to Bjorn's comment, remove the unnecessary comment.
The debug info will be printed by using dev_err/dev_warn instead of by
using printk directly.

V3->V4: According to Bjorn's comment, delete the meaningless variable
initialization and check. We also do some cleanup. 

V2->V3: According to Bjorn's comment, this IPMI opregion code is put into
the IPMI subsystem(ipmi_si_intf.c). In such case the part of IPMI opregion
code  will be installed automatically when IPMI detection module is loaded.
When the IPMI system interface is detected by loading PNP device driver, we
will record every IPMI system interface defined in ACPI namespace and then
install the corresponding IPMI opregion space handler, which is used to enable
ACPI AML code to access the BMC controller.

V1->V2: According to Bjorn's comment, we won't install the IPMI space handler
by loading an ACPI device driver. Instead we will enumerate the ACPI IPMI
device directly in ACPI device tree and then install the IPMI space handler.
Then ACPI AML code and access the BMC controller through the IPMI space
handler.

Best regards.
   Yakui


^ permalink raw reply	[flat|nested] 11+ messages in thread

* [RFC PATCH 1/4] IPMI: Add one interface to get more info of low-level IPMI device
  2010-10-22  9:10 [RFC PATCH 0/4_v11] IPMI/ACPI: Install the ACPI IPMI opregion yakui.zhao
@ 2010-10-22  9:10 ` yakui.zhao
  2010-10-22  9:10   ` [RFC PATCH 2/4] IPMI: Remove the redundant definition of ipmi_addr_src yakui.zhao
                     ` (2 more replies)
  0 siblings, 3 replies; 11+ messages in thread
From: yakui.zhao @ 2010-10-22  9:10 UTC (permalink / raw)
  To: openipmi-developer, linux-acpi; +Cc: minyard, lenb, Zhao Yakui

From: Zhao Yakui <yakui.zhao@intel.com>

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>
---
In this patch only the info of pnp_acpi IPMI is provided. If the detailed info
is also required for other mechanism, please add them in the structure of
ipmi_smi_info.

 drivers/char/ipmi/ipmi_msghandler.c |   26 ++++++++++++++++++++++++++
 drivers/char/ipmi/ipmi_si_intf.c    |   28 ++++++++++++++++++++++++----
 include/linux/ipmi.h                |   23 +++++++++++++++++++++++
 include/linux/ipmi_smi.h            |   11 +++++++++++
 4 files changed, 84 insertions(+), 4 deletions(-)

diff --git a/drivers/char/ipmi/ipmi_msghandler.c b/drivers/char/ipmi/ipmi_msghandler.c
index 4f3f8c9..6f4da59 100644
--- a/drivers/char/ipmi/ipmi_msghandler.c
+++ b/drivers/char/ipmi/ipmi_msghandler.c
@@ -970,6 +970,32 @@ out_kfree:
 }
 EXPORT_SYMBOL(ipmi_create_user);
 
+int ipmi_get_smi_info(int if_num, enum ipmi_addr_src type,
+			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 = handlers->get_smi_info(intf->send_info, type, data);
+	mutex_unlock(&ipmi_interfaces_mutex);
+
+	return rv;
+}
+EXPORT_SYMBOL(ipmi_get_smi_info);
+
 static void free_user(struct kref *ref)
 {
 	ipmi_user_t user = container_of(ref, struct ipmi_user, refcount);
diff --git a/drivers/char/ipmi/ipmi_si_intf.c b/drivers/char/ipmi/ipmi_si_intf.c
index 7bd7c45..73b1c82 100644
--- a/drivers/char/ipmi/ipmi_si_intf.c
+++ b/drivers/char/ipmi/ipmi_si_intf.c
@@ -57,6 +57,7 @@
 #include <asm/irq.h>
 #include <linux/interrupt.h>
 #include <linux/rcupdate.h>
+#include <linux/ipmi.h>
 #include <linux/ipmi_smi.h>
 #include <asm/io.h>
 #include "ipmi_si_sm.h"
@@ -107,10 +108,6 @@ enum si_type {
 };
 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",
 					"ACPI", "SMBIOS", "PCI",
 					"device-tree", "default" };
@@ -291,6 +288,7 @@ struct smi_info {
 	struct task_struct *thread;
 
 	struct list_head link;
+	struct ipmi_smi_info smi_data;
 };
 
 #define smi_inc_stat(smi, stat) \
@@ -1186,6 +1184,22 @@ static int smi_start_processing(void       *send_info,
 	return 0;
 }
 
+static int get_smi_info(void *send_info,
+			enum ipmi_addr_src type,
+			struct ipmi_smi_info **data)
+{
+	struct smi_info *new_smi = send_info;
+	struct ipmi_smi_info *smi_data = &new_smi->smi_data;
+
+	if (new_smi->addr_source != type)
+		return -EINVAL;
+
+	smi_data->addr_src = type;
+
+	*data = smi_data;
+	return 0;
+}
+
 static void set_maintenance_mode(void *send_info, int enable)
 {
 	struct smi_info   *smi_info = send_info;
@@ -1197,6 +1211,7 @@ static void set_maintenance_mode(void *send_info, int enable)
 static struct ipmi_smi_handlers handlers = {
 	.owner                  = THIS_MODULE,
 	.start_processing       = smi_start_processing,
+	.get_smi_info		= get_smi_info,
 	.sender			= sender,
 	.request_events		= request_events,
 	.set_maintenance_mode   = set_maintenance_mode,
@@ -2143,6 +2158,8 @@ static int __devinit ipmi_pnp_probe(struct pnp_dev *dev,
 		return -ENOMEM;
 
 	info->addr_source = SI_ACPI;
+	info->smi_data.smi_info.acpi_info.acpi_handle =
+				acpi_dev->handle;
 	printk(KERN_INFO PFX "probing via ACPI\n");
 
 	handle = acpi_dev->handle;
@@ -3092,6 +3109,7 @@ static int try_smi_init(struct smi_info *new_smi)
 {
 	int rv = 0;
 	int i;
+	struct ipmi_smi_info *smi_data = &new_smi->smi_data;
 
 	printk(KERN_INFO PFX "Trying %s-specified %s state"
 	       " machine at %s address 0x%lx, slave address 0x%x,"
@@ -3217,6 +3235,8 @@ static int try_smi_init(struct smi_info *new_smi)
 		new_smi->dev_registered = 1;
 	}
 
+	smi_data->dev = new_smi->dev;
+
 	rv = ipmi_register_smi(&handlers,
 			       new_smi,
 			       &new_smi->device_id,
diff --git a/include/linux/ipmi.h b/include/linux/ipmi.h
index 65aae34..1ce428f 100644
--- a/include/linux/ipmi.h
+++ b/include/linux/ipmi.h
@@ -454,6 +454,29 @@ unsigned int ipmi_addr_length(int addr_type);
 /* Validate that the given IPMI address is valid. */
 int ipmi_validate_addr(struct ipmi_addr *addr, int len);
 
+enum ipmi_addr_src {
+	SI_INVALID = 0, SI_HOTMOD, SI_HARDCODED, SI_SPMI, SI_ACPI, SI_SMBIOS,
+	SI_PCI,	SI_DEVICETREE, SI_DEFAULT
+};
+struct ipmi_smi_info{
+	enum ipmi_addr_src addr_src;
+	struct device *dev;
+	union {
+		/*
+		 * Now only SI_ACPI info is provided. If the info is required
+		 * for other type, please add it
+		 */
+#ifdef CONFIG_ACPI
+		struct {
+			void *acpi_handle;
+		} acpi_info;
+#endif
+	} smi_info;
+};
+
+/* This is to get the private info of ipmi_smi_t. The pointer is returned */
+extern int ipmi_get_smi_info(int if_num, enum ipmi_addr_src type,
+		struct ipmi_smi_info **data);
 #endif /* __KERNEL__ */
 
 
diff --git a/include/linux/ipmi_smi.h b/include/linux/ipmi_smi.h
index 4b48318..bfa8f40 100644
--- a/include/linux/ipmi_smi.h
+++ b/include/linux/ipmi_smi.h
@@ -86,6 +86,17 @@ struct ipmi_smi_handlers {
 	int (*start_processing)(void       *send_info,
 				ipmi_smi_t new_intf);
 
+	/*
+	 * Get the detailed private info of the low level interface and return
+	 * the corresponding pointer.
+	 * For example: the ACPI device handle will be returned for the
+	 * pnp_acpi IPMI device. Of course it will firstly compare the
+	 * interface type of low-level interface(Hardcoded type, DMI,
+	 * ACPI and so on). If the type doesn't match, it will return -EINVAL.
+	 */
+	int (*get_smi_info)(void *send_info, enum ipmi_addr_src type,
+				struct ipmi_smi_info **data);
+
 	/* Called to enqueue an SMI message to be sent.  This
 	   operation is not allowed to fail.  If an error occurs, it
 	   should report back the error in a received message.  It may
-- 
1.5.4.5


^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [RFC PATCH 2/4] IPMI: Remove the redundant definition of ipmi_addr_src
  2010-10-22  9:10 ` [RFC PATCH 1/4] IPMI: Add one interface to get more info of low-level IPMI device yakui.zhao
@ 2010-10-22  9:10   ` yakui.zhao
  2010-10-22  9:10     ` [RFC PATCH 3/4] IPMI: Add the document description of ipmi_get_smi_info yakui.zhao
  2010-10-25  1:19   ` [RFC PATCH 1/4] IPMI: Add one interface to get more info of low-level IPMI device ykzhao
  2010-10-25  3:25   ` Corey Minyard
  2 siblings, 1 reply; 11+ messages in thread
From: yakui.zhao @ 2010-10-22  9:10 UTC (permalink / raw)
  To: openipmi-developer, linux-acpi; +Cc: minyard, lenb, Zhao Yakui

From: Zhao Yakui <yakui.zhao@intel.com>

The ipmi_addr_src is defined twice. One is in ipmi_smi_info and the other
is in generic smi_info. Remove the redunant definition in smi_info.

Signed-off-by: Zhao Yakui <yakui.zhao@intel.com>
---
 drivers/char/ipmi/ipmi_si_intf.c |   37 +++++++++++++++++--------------------
 1 files changed, 17 insertions(+), 20 deletions(-)

diff --git a/drivers/char/ipmi/ipmi_si_intf.c b/drivers/char/ipmi/ipmi_si_intf.c
index 73b1c82..44f6b9e 100644
--- a/drivers/char/ipmi/ipmi_si_intf.c
+++ b/drivers/char/ipmi/ipmi_si_intf.c
@@ -193,7 +193,6 @@ struct smi_info {
 	int (*irq_setup)(struct smi_info *info);
 	void (*irq_cleanup)(struct smi_info *info);
 	unsigned int io_size;
-	enum ipmi_addr_src addr_source; /* ACPI, PCI, SMBIOS, hardcode, etc. */
 	void (*addr_source_cleanup)(struct smi_info *info);
 	void *addr_source_data;
 
@@ -1191,11 +1190,9 @@ static int get_smi_info(void *send_info,
 	struct smi_info *new_smi = send_info;
 	struct ipmi_smi_info *smi_data = &new_smi->smi_data;
 
-	if (new_smi->addr_source != type)
+	if (smi_data->addr_src != type)
 		return -EINVAL;
 
-	smi_data->addr_src = type;
-
 	*data = smi_data;
 	return 0;
 }
@@ -1800,7 +1797,7 @@ static int hotmod_handler(const char *val, struct kernel_param *kp)
 				goto out;
 			}
 
-			info->addr_source = SI_HOTMOD;
+			info->smi_data.addr_src = SI_HOTMOD;
 			info->si_type = si_type;
 			info->io.addr_data = addr;
 			info->io.addr_type = addr_space;
@@ -1863,7 +1860,7 @@ static __devinit void hardcode_find_bmc(void)
 		if (!info)
 			return;
 
-		info->addr_source = SI_HARDCODED;
+		info->smi_data.addr_src = SI_HARDCODED;
 		printk(KERN_INFO PFX "probing via hardcoded address\n");
 
 		if (!si_type[i] || strcmp(si_type[i], "kcs") == 0) {
@@ -2049,7 +2046,7 @@ static __devinit int try_init_spmi(struct SPMITable *spmi)
 		return -ENOMEM;
 	}
 
-	info->addr_source = SI_SPMI;
+	info->smi_data.addr_src = SI_SPMI;
 	printk(KERN_INFO PFX "probing via SPMI\n");
 
 	/* Figure out the interface type. */
@@ -2157,7 +2154,7 @@ static int __devinit ipmi_pnp_probe(struct pnp_dev *dev,
 	if (!info)
 		return -ENOMEM;
 
-	info->addr_source = SI_ACPI;
+	info->smi_data.addr_src = SI_ACPI;
 	info->smi_data.smi_info.acpi_info.acpi_handle =
 				acpi_dev->handle;
 	printk(KERN_INFO PFX "probing via ACPI\n");
@@ -2342,7 +2339,7 @@ static __devinit void try_init_dmi(struct dmi_ipmi_data *ipmi_data)
 		return;
 	}
 
-	info->addr_source = SI_SMBIOS;
+	info->smi_data.addr_src = SI_SMBIOS;
 	printk(KERN_INFO PFX "probing via SMBIOS\n");
 
 	switch (ipmi_data->type) {
@@ -2447,7 +2444,7 @@ static int __devinit ipmi_pci_probe(struct pci_dev *pdev,
 	if (!info)
 		return -ENOMEM;
 
-	info->addr_source = SI_PCI;
+	info->smi_data.addr_src = SI_PCI;
 	dev_info(&pdev->dev, "probing via PCI");
 
 	switch (class_type) {
@@ -2593,7 +2590,7 @@ static int __devinit ipmi_of_probe(struct platform_device *dev,
 	}
 
 	info->si_type		= (enum si_type) match->data;
-	info->addr_source	= SI_DEVICETREE;
+	info->smi_data.addr_src	= SI_DEVICETREE;
 	info->irq_setup		= std_irq_setup;
 
 	if (resource.flags & IORESOURCE_IO) {
@@ -3035,7 +3032,7 @@ static __devinit void default_find_bmc(void)
 		if (!info)
 			return;
 
-		info->addr_source = SI_DEFAULT;
+		info->smi_data.addr_src = SI_DEFAULT;
 
 		info->si_type = ipmi_defaults[i].type;
 		info->io_setup = port_setup;
@@ -3082,7 +3079,7 @@ static int add_smi(struct smi_info *new_smi)
 	int rv = 0;
 
 	printk(KERN_INFO PFX "Adding %s-specified %s state machine",
-			ipmi_addr_src_to_str[new_smi->addr_source],
+			ipmi_addr_src_to_str[new_smi->smi_data.addr_src],
 			si_to_str[new_smi->si_type]);
 	mutex_lock(&smi_infos_lock);
 	if (!is_new_interface(new_smi)) {
@@ -3114,7 +3111,7 @@ static int try_smi_init(struct smi_info *new_smi)
 	printk(KERN_INFO PFX "Trying %s-specified %s state"
 	       " machine at %s address 0x%lx, slave address 0x%x,"
 	       " irq %d\n",
-	       ipmi_addr_src_to_str[new_smi->addr_source],
+	       ipmi_addr_src_to_str[new_smi->smi_data.addr_src],
 	       si_to_str[new_smi->si_type],
 	       addr_space_to_str[new_smi->io.addr_type],
 	       new_smi->io.addr_data,
@@ -3162,7 +3159,7 @@ static int try_smi_init(struct smi_info *new_smi)
 
 	/* Do low-level detection first. */
 	if (new_smi->handlers->detect(new_smi->si_sm)) {
-		if (new_smi->addr_source)
+		if (new_smi->smi_data.addr_src)
 			printk(KERN_INFO PFX "Interface detection failed\n");
 		rv = -ENODEV;
 		goto out_err;
@@ -3174,7 +3171,7 @@ static int try_smi_init(struct smi_info *new_smi)
 	 */
 	rv = try_get_dev_id(new_smi);
 	if (rv) {
-		if (new_smi->addr_source)
+		if (new_smi->smi_data.addr_src)
 			printk(KERN_INFO PFX "There appears to be no BMC"
 			       " at this location\n");
 		goto out_err;
@@ -3408,9 +3405,9 @@ static __devinit int init_ipmi_si(void)
 		/* Try to register a device if it has an IRQ and we either
 		   haven't successfully registered a device yet or this
 		   device has the same type as one we successfully registered */
-		if (e->irq && (!type || e->addr_source == type)) {
+		if (e->irq && (!type || e->smi_data.addr_src == type)) {
 			if (!try_smi_init(e)) {
-				type = e->addr_source;
+				type = e->smi_data.addr_src;
 			}
 		}
 	}
@@ -3424,9 +3421,9 @@ static __devinit int init_ipmi_si(void)
 	/* Fall back to the preferred device */
 
 	list_for_each_entry(e, &smi_infos, link) {
-		if (!e->irq && (!type || e->addr_source == type)) {
+		if (!e->irq && (!type || e->smi_data.addr_src == type)) {
 			if (!try_smi_init(e)) {
-				type = e->addr_source;
+				type = e->smi_data.addr_src;
 			}
 		}
 	}
-- 
1.5.4.5


^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [RFC PATCH 3/4] IPMI: Add the document description of ipmi_get_smi_info
  2010-10-22  9:10   ` [RFC PATCH 2/4] IPMI: Remove the redundant definition of ipmi_addr_src yakui.zhao
@ 2010-10-22  9:10     ` yakui.zhao
  2010-10-22  9:10       ` [RFC PATCH 04/4] IPMI/ACPI: Add the IPMI opregion driver to enable ACPI to access BMC controller yakui.zhao
  0 siblings, 1 reply; 11+ messages in thread
From: yakui.zhao @ 2010-10-22  9:10 UTC (permalink / raw)
  To: openipmi-developer, linux-acpi; +Cc: minyard, lenb, Zhao Yakui

From: Zhao Yakui <yakui.zhao@intel.com>

Add the document description about how to use ipmi_get_smi_info.

Signed-off-by: Zhao Yakui <yakui.zhao@intel.com>
---
 Documentation/IPMI.txt |   37 +++++++++++++++++++++++++++++++++++++
 1 files changed, 37 insertions(+), 0 deletions(-)

diff --git a/Documentation/IPMI.txt b/Documentation/IPMI.txt
index 69dd29e..0b8aecc 100644
--- a/Documentation/IPMI.txt
+++ b/Documentation/IPMI.txt
@@ -533,6 +533,43 @@ completion during sending a panic event.
 Other Pieces
 ------------
 
+Get the detailed info related with the 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).
+    The function of ipmi_get_smi_info is added to get the
+detailed info of IPMI device. The following is the struct definition of
+ipmi_smi_info(Now only ACPI info is defined. If the info is required for
+other IPMI device type, please add it) .
+     struct ipmi_smi_info{
+        enum ipmi_addr_src addr_src;
+        struct device *dev;
+        union {
+                /*
+                 * Now only SI_ACPI info is provided. If the info is required
+                 * for other type, please add it
+                 */
+#ifdef CONFIG_ACPI
+                struct {
+                        void *acpi_handle;
+                } acpi_info;
+#endif
+        } smi_info;
+};
+
+	The following is the definition of ipmi_get_smi_info.
+	extern int ipmi_get_smi_info(int if_num, enum ipmi_addr_src type,
+		struct ipmi_smi_info **data);
+	It is noted that the returned smi_data is not the dynamically
+allocated memory. It is only the pointer of the corresponding info stored
+in IPMI device. In such case the caller don't try to free the corresponding
+memory.
+
 Watchdog
 --------
 
-- 
1.5.4.5


^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [RFC PATCH 04/4] IPMI/ACPI: Add the IPMI opregion driver to enable ACPI to access BMC controller
  2010-10-22  9:10     ` [RFC PATCH 3/4] IPMI: Add the document description of ipmi_get_smi_info yakui.zhao
@ 2010-10-22  9:10       ` yakui.zhao
  0 siblings, 0 replies; 11+ messages in thread
From: yakui.zhao @ 2010-10-22  9:10 UTC (permalink / raw)
  To: openipmi-developer, linux-acpi; +Cc: minyard, lenb, Zhao Yakui, Bjorn Helgaas

From: Zhao Yakui <yakui.zhao@intel.com>

ACPI 4.0 spec adds the ACPI IPMI opregion, which means that the ACPI AML
code can also communicate with the BMC controller. This is to install
the ACPI IPMI opregion and enable the ACPI to access the BMC controller
through the IPMI message.

     It will create IPMI user interface for every IPMI device detected
in ACPI namespace and install the corresponding IPMI opregion space handler.
Then it can enable ACPI to access the BMC controller through the IPMI
message.

The following describes how to process the IPMI request in IPMI space handler:
    1. format the IPMI message based on the request in AML code.
    IPMI system address. Now the address type is SYSTEM_INTERFACE_ADDR_TYPE
    IPMI net function & command
    IPMI message payload
    2. send the IPMI message by using the function of ipmi_request_settime
    3. wait for the completion of IPMI message. It can be done in different
routes: One is in handled in IPMI user recv callback function. Another is
handled in timeout function.
    4. format the IPMI response and return it to ACPI AML code.

At the same time it also addes the module dependency. The ACPI IPMI opregion
will depend on the IPMI subsystem.

Signed-off-by: Zhao Yakui <yakui.zhao@intel.com>
cc: Bjorn Helgaas <bjorn.helgaas@hp.com>
---
 drivers/acpi/Kconfig     |   12 +
 drivers/acpi/Makefile    |    1 +
 drivers/acpi/acpi_ipmi.c |  510 ++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 523 insertions(+), 0 deletions(-)
 create mode 100644 drivers/acpi/acpi_ipmi.c

diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig
index 3f3489c..9359824 100644
--- a/drivers/acpi/Kconfig
+++ b/drivers/acpi/Kconfig
@@ -210,6 +210,18 @@ config ACPI_PROCESSOR
 	  To compile this driver as a module, choose M here:
 	  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
 	bool
 	depends on ACPI_PROCESSOR && HOTPLUG_CPU
diff --git a/drivers/acpi/Makefile b/drivers/acpi/Makefile
index 3d031d0..df4c4f0 100644
--- a/drivers/acpi/Makefile
+++ b/drivers/acpi/Makefile
@@ -69,5 +69,6 @@ processor-y			+= processor_idle.o processor_thermal.o
 processor-$(CONFIG_CPU_FREQ)	+= processor_perflib.o
 
 obj-$(CONFIG_ACPI_PROCESSOR_AGGREGATOR) += acpi_pad.o
+obj-$(CONFIG_ACPI_IPMI)		+= acpi_ipmi.o
 
 obj-$(CONFIG_ACPI_APEI)		+= apei/
diff --git a/drivers/acpi/acpi_ipmi.c b/drivers/acpi/acpi_ipmi.c
new file mode 100644
index 0000000..9d0b263
--- /dev/null
+++ b/drivers/acpi/acpi_ipmi.c
@@ -0,0 +1,510 @@
+/*
+ *  acpi_ipmi.c - ACPI IPMI opregion
+ *
+ *  Copyright (C) 2010 Intel Corporation
+ *  Copyright (C) 2010 Zhao Yakui <yakui.zhao@intel.com>
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or (at
+ *  your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful, but
+ *  WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/delay.h>
+#include <linux/proc_fs.h>
+#include <linux/seq_file.h>
+#include <linux/interrupt.h>
+#include <linux/list.h>
+#include <linux/spinlock.h>
+#include <linux/io.h>
+#include <acpi/acpi_bus.h>
+#include <acpi/acpi_drivers.h>
+#include <linux/ipmi.h>
+#include <linux/device.h>
+#include <linux/pnp.h>
+
+MODULE_AUTHOR("Zhao Yakui");
+MODULE_DESCRIPTION("ACPI IPMI Opregion driver");
+MODULE_LICENSE("GPL");
+
+#define IPMI_FLAGS_HANDLER_INSTALL	0
+
+#define ACPI_IPMI_OK			0
+#define ACPI_IPMI_TIMEOUT		0x10
+#define ACPI_IPMI_UNKNOWN		0x07
+/* the IPMI timeout is 5s */
+#define IPMI_TIMEOUT			(5 * HZ)
+
+struct acpi_ipmi_device {
+	/* the device list attached to driver_data.ipmi_devices */
+	struct list_head head;
+	/* the IPMI request message list */
+	struct list_head tx_msg_list;
+	acpi_handle handle;
+	struct pnp_dev *pnp_dev;
+	ipmi_user_t	user_interface;
+	struct mutex	mutex_lock;
+	int ipmi_ifnum; /* IPMI interface number */
+	long curr_msgid;
+	unsigned long flags;
+};
+
+struct ipmi_driver_data {
+	struct list_head	ipmi_devices;
+	struct ipmi_smi_watcher	bmc_events;
+	struct ipmi_user_hndl	ipmi_hndlrs;
+};
+
+struct acpi_ipmi_msg {
+	struct list_head head;
+	/*
+	 * General speaking the addr type should be SI_ADDR_TYPE. And
+	 * the addr channel should be BMC.
+	 * In fact it can also be IPMB type. But we will have to
+	 * parse it from the Netfn command buffer. It is so complex
+	 * that it is skipped.
+	 */
+	struct ipmi_addr addr;
+	long tx_msgid;
+	/* it is used to track whether the IPMI message is finished */
+	struct completion tx_complete;
+	struct kernel_ipmi_msg tx_message;
+	int	msg_done;
+	/* tx data . And copy it from ACPI object buffer */
+	u8	tx_data[64];
+	int	tx_len;
+	u8	rx_data[64];
+	int	rx_len;
+	struct acpi_ipmi_device *device;
+};
+
+/* IPMI request/response buffer per ACPI 4.0, sec 5.5.2.4.3.2 */
+struct acpi_ipmi_buffer {
+	u8 status;
+	u8 length;
+	u8 data[64];
+};
+
+static void ipmi_register_bmc(int iface, struct device *dev);
+static void ipmi_bmc_gone(int iface);
+static void ipmi_msg_handler(struct ipmi_recv_msg *msg, void *user_msg_data);
+static void acpi_add_ipmi_device(struct acpi_ipmi_device *ipmi_device);
+static void acpi_remove_ipmi_device(struct acpi_ipmi_device *ipmi_device);
+
+static struct ipmi_driver_data driver_data = {
+	.ipmi_devices = LIST_HEAD_INIT(driver_data.ipmi_devices),
+	.bmc_events = {
+		.owner = THIS_MODULE,
+		.new_smi = ipmi_register_bmc,
+		.smi_gone = ipmi_bmc_gone,
+	},
+	.ipmi_hndlrs = {
+		.ipmi_recv_hndl = ipmi_msg_handler,
+	},
+};
+
+static struct acpi_ipmi_msg *acpi_alloc_ipmi_msg(struct acpi_ipmi_device *ipmi)
+{
+	struct acpi_ipmi_msg *ipmi_msg;
+	struct pnp_dev *pnp_dev = ipmi->pnp_dev;
+
+	ipmi_msg = kzalloc(sizeof(struct acpi_ipmi_msg), GFP_KERNEL);
+	if (!ipmi_msg)	{
+		dev_warn(&pnp_dev->dev, "Can't allocate memory for ipmi_msg\n");
+		return NULL;
+	}
+	init_completion(&ipmi_msg->tx_complete);
+	INIT_LIST_HEAD(&ipmi_msg->head);
+	ipmi_msg->device = ipmi;
+	return ipmi_msg;
+}
+
+#define		IPMI_OP_RGN_NETFN(offset)	((offset >> 8) & 0xff)
+#define		IPMI_OP_RGN_CMD(offset)		(offset & 0xff)
+static void acpi_format_ipmi_msg(struct acpi_ipmi_msg *tx_msg,
+				acpi_physical_address address,
+				acpi_integer *value)
+{
+	struct kernel_ipmi_msg *msg;
+	struct acpi_ipmi_buffer *buffer;
+	struct acpi_ipmi_device *device;
+
+	msg = &tx_msg->tx_message;
+	/*
+	 * IPMI network function and command are encoded in the address
+	 * within the IPMI OpRegion; see ACPI 4.0, sec 5.5.2.4.3.
+	 */
+	msg->netfn = IPMI_OP_RGN_NETFN(address);
+	msg->cmd = IPMI_OP_RGN_CMD(address);
+	msg->data = tx_msg->tx_data;
+	/*
+	 * value is the parameter passed by the IPMI opregion space handler.
+	 * It points to the IPMI request message buffer
+	 */
+	buffer = (struct acpi_ipmi_buffer *)value;
+	/* copy the tx message data */
+	msg->data_len = buffer->length;
+	memcpy(tx_msg->tx_data, buffer->data, msg->data_len);
+	/*
+	 * now the default type is SYSTEM_INTERFACE and channel type is BMC.
+	 * If the netfn is APP_REQUEST and the cmd is SEND_MESSAGE,
+	 * the addr type should be changed to IPMB. Then we will have to parse
+	 * the IPMI request message buffer to get the IPMB address.
+	 * If so, please fix me.
+	 */
+	tx_msg->addr.addr_type = IPMI_SYSTEM_INTERFACE_ADDR_TYPE;
+	tx_msg->addr.channel = IPMI_BMC_CHANNEL;
+	tx_msg->addr.data[0] = 0;
+
+	/* Get the msgid */
+	device = tx_msg->device;
+	mutex_lock(&device->mutex_lock);
+	device->curr_msgid++;
+	tx_msg->tx_msgid = device->curr_msgid;
+	mutex_unlock(&device->mutex_lock);
+}
+
+static void acpi_format_ipmi_response(struct acpi_ipmi_msg *msg,
+		acpi_integer *value, int rem_time)
+{
+	struct acpi_ipmi_buffer *buffer;
+
+	/*
+	 * value is also used as output parameter. It represents the response
+	 * IPMI message returned by IPMI command.
+	 */
+	buffer = (struct acpi_ipmi_buffer *)value;
+	if (!rem_time && !msg->msg_done) {
+		buffer->status = ACPI_IPMI_TIMEOUT;
+		return;
+	}
+	/*
+	 * If the flag of msg_done is not set or the recv length is zero, it
+	 * means that the IPMI command is not executed correctly.
+	 * The status code will be ACPI_IPMI_UNKNOWN.
+	 */
+	if (!msg->msg_done || !msg->rx_len) {
+		buffer->status = ACPI_IPMI_UNKNOWN;
+		return;
+	}
+	/*
+	 * If the IPMI response message is obtained correctly, the status code
+	 * will be ACPI_IPMI_OK
+	 */
+	buffer->status = ACPI_IPMI_OK;
+	buffer->length = msg->rx_len;
+	memcpy(buffer->data, msg->rx_data, msg->rx_len);
+}
+
+static void ipmi_flush_tx_msg(struct acpi_ipmi_device *ipmi)
+{
+	struct acpi_ipmi_msg *tx_msg, *temp;
+	int count = HZ / 10;
+	struct pnp_dev *pnp_dev = ipmi->pnp_dev;
+
+	list_for_each_entry_safe(tx_msg, temp, &ipmi->tx_msg_list, head) {
+		/* wake up the sleep thread on the Tx msg */
+		complete(&tx_msg->tx_complete);
+	}
+
+	/* wait for about 100ms to flush the tx message list */
+	while (count--) {
+		if (list_empty(&ipmi->tx_msg_list))
+			break;
+		schedule_timeout(1);
+	}
+	if (!list_empty(&ipmi->tx_msg_list))
+		dev_warn(&pnp_dev->dev, "tx msg list is not NULL\n");
+}
+
+static void ipmi_msg_handler(struct ipmi_recv_msg *msg, void *user_msg_data)
+{
+	struct acpi_ipmi_device *ipmi_device = user_msg_data;
+	int msg_found = 0;
+	struct acpi_ipmi_msg *tx_msg;
+	struct pnp_dev *pnp_dev = ipmi_device->pnp_dev;
+
+	if (msg->user != ipmi_device->user_interface) {
+		dev_warn(&pnp_dev->dev, "Unexpected response is returned. "
+			"returned user %p, expected user %p\n",
+			msg->user, ipmi_device->user_interface);
+		ipmi_free_recv_msg(msg);
+		return;
+	}
+	mutex_lock(&ipmi_device->mutex_lock);
+	list_for_each_entry(tx_msg, &ipmi_device->tx_msg_list, head) {
+		if (msg->msgid == tx_msg->tx_msgid) {
+			msg_found = 1;
+			break;
+		}
+	}
+
+	mutex_unlock(&ipmi_device->mutex_lock);
+	if (!msg_found) {
+		dev_warn(&pnp_dev->dev, "Unexpected response (msg id %ld) is "
+			"returned.\n", msg->msgid);
+		ipmi_free_recv_msg(msg);
+		return;
+	}
+
+	if (msg->msg.data_len) {
+		/* copy the response data to Rx_data buffer */
+		memcpy(tx_msg->rx_data, msg->msg_data, msg->msg.data_len);
+		tx_msg->rx_len = msg->msg.data_len;
+		tx_msg->msg_done = 1;
+	}
+	complete(&tx_msg->tx_complete);
+	ipmi_free_recv_msg(msg);
+};
+
+static void ipmi_register_bmc(int iface, struct device *dev)
+{
+	struct acpi_ipmi_device *ipmi_device, *temp;
+	struct pnp_dev *pnp_dev;
+	ipmi_user_t		user;
+	int err;
+	struct ipmi_smi_info *smi_data;
+	acpi_handle handle;
+
+	err = ipmi_get_smi_info(iface, SI_ACPI, &smi_data);
+
+	if (err)
+		return;
+
+	handle = smi_data->smi_info.acpi_info.acpi_handle;
+
+	list_for_each_entry(temp, &driver_data.ipmi_devices, head) {
+		/*
+		 * if the corresponding ACPI handle is already added
+		 * to the device list, don't add it again.
+		 */
+		if (temp->handle == handle)
+			goto out;
+	}
+
+	ipmi_device = kzalloc(sizeof(*ipmi_device), GFP_KERNEL);
+
+	if (!ipmi_device)
+		goto out;
+
+	pnp_dev = to_pnp_dev(smi_data->dev);
+	ipmi_device->handle = handle;
+	ipmi_device->pnp_dev = pnp_dev;
+
+	err = ipmi_create_user(iface, &driver_data.ipmi_hndlrs,
+					ipmi_device, &user);
+	if (err) {
+		dev_warn(&pnp_dev->dev, "Can't create IPMI user interface\n");
+		kfree(ipmi_device);
+		goto out;
+	}
+	acpi_add_ipmi_device(ipmi_device);
+	ipmi_device->user_interface = user;
+	ipmi_device->ipmi_ifnum = iface;
+	return;
+
+out:
+	return;
+}
+
+static void ipmi_bmc_gone(int iface)
+{
+	struct acpi_ipmi_device *ipmi_device, *temp;
+
+	list_for_each_entry_safe(ipmi_device, temp,
+				&driver_data.ipmi_devices, head) {
+		if (ipmi_device->ipmi_ifnum != iface)
+			continue;
+
+		if (ipmi_device->user_interface) {
+			ipmi_destroy_user(ipmi_device->user_interface);
+			ipmi_device->user_interface = NULL;
+			ipmi_flush_tx_msg(ipmi_device);
+		}
+		acpi_remove_ipmi_device(ipmi_device);
+		kfree(ipmi_device);
+
+		break;
+	}
+}
+/* --------------------------------------------------------------------------
+ *			Address Space Management
+ * -------------------------------------------------------------------------- */
+/*
+ * This is the IPMI opregion space handler.
+ * @function: indicates the read/write. In fact as the IPMI message is driven
+ * by command, only write is meaningful.
+ * @address: This contains the netfn/command of IPMI request message.
+ * @bits   : not used.
+ * @value  : it is an in/out parameter. It points to the IPMI message buffer.
+ *	     Before the IPMI message is sent, it represents the actual request
+ *	     IPMI message. After the IPMI message is finished, it represents
+ *	     the response IPMI message returned by IPMI command.
+ * @handler_context: IPMI device context.
+ */
+
+static acpi_status
+acpi_ipmi_space_handler(u32 function, acpi_physical_address address,
+		      u32 bits, acpi_integer *value,
+		      void *handler_context, void *region_context)
+{
+	struct acpi_ipmi_msg *tx_msg;
+	struct acpi_ipmi_device *ipmi_device = handler_context;
+	int err, rem_time;
+	acpi_status status;
+	/*
+	 * IPMI opregion message.
+	 * IPMI message is firstly written to the BMC and system software
+	 * can get the respsonse. So it is unmeaningful for the read access
+	 * of IPMI opregion.
+	 */
+	if ((function & ACPI_IO_MASK) == ACPI_READ)
+		return AE_TYPE;
+
+	if (!ipmi_device->user_interface)
+		return AE_NOT_EXIST;
+
+	tx_msg = acpi_alloc_ipmi_msg(ipmi_device);
+	if (!tx_msg)
+		return AE_NO_MEMORY;
+
+	acpi_format_ipmi_msg(tx_msg, address, value);
+	mutex_lock(&ipmi_device->mutex_lock);
+	list_add_tail(&tx_msg->head, &ipmi_device->tx_msg_list);
+	mutex_unlock(&ipmi_device->mutex_lock);
+	err = ipmi_request_settime(ipmi_device->user_interface,
+					&tx_msg->addr,
+					tx_msg->tx_msgid,
+					&tx_msg->tx_message,
+					NULL, 0, 0, 0);
+	if (err) {
+		status = AE_ERROR;
+		goto end_label;
+	}
+	rem_time = wait_for_completion_timeout(&tx_msg->tx_complete,
+					IPMI_TIMEOUT);
+	acpi_format_ipmi_response(tx_msg, value, rem_time);
+	status = AE_OK;
+
+end_label:
+	mutex_lock(&ipmi_device->mutex_lock);
+	list_del(&tx_msg->head);
+	mutex_unlock(&ipmi_device->mutex_lock);
+	kfree(tx_msg);
+	return status;
+}
+
+static void ipmi_remove_space_handler(struct acpi_ipmi_device *ipmi)
+{
+	if (!test_bit(IPMI_FLAGS_HANDLER_INSTALL, &ipmi->flags))
+		return;
+
+	acpi_remove_address_space_handler(ipmi->handle,
+				ACPI_ADR_SPACE_IPMI, &acpi_ipmi_space_handler);
+
+	clear_bit(IPMI_FLAGS_HANDLER_INSTALL, &ipmi->flags);
+}
+
+static int ipmi_install_space_handler(struct acpi_ipmi_device *ipmi)
+{
+	acpi_status status;
+
+	if (test_bit(IPMI_FLAGS_HANDLER_INSTALL, &ipmi->flags))
+		return 0;
+
+	status = acpi_install_address_space_handler(ipmi->handle,
+						    ACPI_ADR_SPACE_IPMI,
+						    &acpi_ipmi_space_handler,
+						    NULL, ipmi);
+	if (ACPI_FAILURE(status)) {
+		struct pnp_dev *pnp_dev = ipmi->pnp_dev;
+		dev_warn(&pnp_dev->dev, "Can't register IPMI opregion space "
+			"handle\n");
+		return -EINVAL;
+	}
+	set_bit(IPMI_FLAGS_HANDLER_INSTALL, &ipmi->flags);
+	return 0;
+}
+
+static void acpi_add_ipmi_device(struct acpi_ipmi_device *ipmi_device)
+{
+
+	INIT_LIST_HEAD(&ipmi_device->head);
+	list_add_tail(&ipmi_device->head, &driver_data.ipmi_devices);
+
+	mutex_init(&ipmi_device->mutex_lock);
+	INIT_LIST_HEAD(&ipmi_device->tx_msg_list);
+	ipmi_install_space_handler(ipmi_device);
+}
+
+static void acpi_remove_ipmi_device(struct acpi_ipmi_device *ipmi_device)
+{
+	/*
+	 * If the IPMI user interface is created, it should be
+	 * destroyed.
+	 */
+	if (ipmi_device->user_interface) {
+		ipmi_destroy_user(ipmi_device->user_interface);
+		ipmi_device->user_interface = NULL;
+	}
+	/* flush the Tx_msg list */
+	if (!list_empty(&ipmi_device->tx_msg_list))
+		ipmi_flush_tx_msg(ipmi_device);
+
+	list_del(&ipmi_device->head);
+	ipmi_remove_space_handler(ipmi_device);
+}
+
+static int __init acpi_ipmi_init(void)
+{
+	int result = 0;
+
+	if (acpi_disabled)
+		return result;
+
+	result = ipmi_smi_watcher_register(&driver_data.bmc_events);
+
+	return result;
+}
+
+static void __exit acpi_ipmi_exit(void)
+{
+	struct acpi_ipmi_device *ipmi_device, *temp;
+
+	if (acpi_disabled)
+		return;
+
+	ipmi_smi_watcher_unregister(&driver_data.bmc_events);
+
+	/*
+	 * When one smi_watcher is unregistered, it is only deleted
+	 * from the smi_watcher list. But the smi_gone callback function
+	 * is not called. So explicitly uninstall the ACPI IPMI oregion
+	 * handler and free it.
+	 */
+	list_for_each_entry_safe(ipmi_device, temp,
+				&driver_data.ipmi_devices, head) {
+		acpi_remove_ipmi_device(ipmi_device);
+		kfree(ipmi_device);
+	}
+}
+
+module_init(acpi_ipmi_init);
+module_exit(acpi_ipmi_exit);
-- 
1.5.4.5


^ permalink raw reply related	[flat|nested] 11+ messages in thread

* Re: [RFC PATCH 1/4] IPMI: Add one interface to get more info of low-level IPMI device
  2010-10-22  9:10 ` [RFC PATCH 1/4] IPMI: Add one interface to get more info of low-level IPMI device yakui.zhao
  2010-10-22  9:10   ` [RFC PATCH 2/4] IPMI: Remove the redundant definition of ipmi_addr_src yakui.zhao
@ 2010-10-25  1:19   ` ykzhao
  2010-10-25  3:25   ` Corey Minyard
  2 siblings, 0 replies; 11+ messages in thread
From: ykzhao @ 2010-10-25  1:19 UTC (permalink / raw)
  To: openipmi-developer@lists.sourceforge.net
  Cc: linux-acpi@vger.kernel.org, minyard@acm.org, lenb@kernel.org

On Fri, 2010-10-22 at 17:10 +0800, Zhao, Yakui wrote:
> From: Zhao Yakui <yakui.zhao@intel.com>
> 
> 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.

Hi, Corey
    Does this patch set make sense?
    In this patch set the reference pointer is returned instead of
memory copy.

Thanks.
    Yakui
> 
> Signed-off-by: Zhao Yakui <yakui.zhao@intel.com>
> ---
> In this patch only the info of pnp_acpi IPMI is provided. If the detailed info
> is also required for other mechanism, please add them in the structure of
> ipmi_smi_info.
> 
>  drivers/char/ipmi/ipmi_msghandler.c |   26 ++++++++++++++++++++++++++
>  drivers/char/ipmi/ipmi_si_intf.c    |   28 ++++++++++++++++++++++++----
>  include/linux/ipmi.h                |   23 +++++++++++++++++++++++
>  include/linux/ipmi_smi.h            |   11 +++++++++++
>  4 files changed, 84 insertions(+), 4 deletions(-)
> 
> diff --git a/drivers/char/ipmi/ipmi_msghandler.c b/drivers/char/ipmi/ipmi_msghandler.c
> index 4f3f8c9..6f4da59 100644
> --- a/drivers/char/ipmi/ipmi_msghandler.c
> +++ b/drivers/char/ipmi/ipmi_msghandler.c
> @@ -970,6 +970,32 @@ out_kfree:
>  }
>  EXPORT_SYMBOL(ipmi_create_user);
>  
> +int ipmi_get_smi_info(int if_num, enum ipmi_addr_src type,
> +			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 = handlers->get_smi_info(intf->send_info, type, data);
> +	mutex_unlock(&ipmi_interfaces_mutex);
> +
> +	return rv;
> +}
> +EXPORT_SYMBOL(ipmi_get_smi_info);
> +
>  static void free_user(struct kref *ref)
>  {
>  	ipmi_user_t user = container_of(ref, struct ipmi_user, refcount);
> diff --git a/drivers/char/ipmi/ipmi_si_intf.c b/drivers/char/ipmi/ipmi_si_intf.c
> index 7bd7c45..73b1c82 100644
> --- a/drivers/char/ipmi/ipmi_si_intf.c
> +++ b/drivers/char/ipmi/ipmi_si_intf.c
> @@ -57,6 +57,7 @@
>  #include <asm/irq.h>
>  #include <linux/interrupt.h>
>  #include <linux/rcupdate.h>
> +#include <linux/ipmi.h>
>  #include <linux/ipmi_smi.h>
>  #include <asm/io.h>
>  #include "ipmi_si_sm.h"
> @@ -107,10 +108,6 @@ enum si_type {
>  };
>  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",
>  					"ACPI", "SMBIOS", "PCI",
>  					"device-tree", "default" };
> @@ -291,6 +288,7 @@ struct smi_info {
>  	struct task_struct *thread;
>  
>  	struct list_head link;
> +	struct ipmi_smi_info smi_data;
>  };
>  
>  #define smi_inc_stat(smi, stat) \
> @@ -1186,6 +1184,22 @@ static int smi_start_processing(void       *send_info,
>  	return 0;
>  }
>  
> +static int get_smi_info(void *send_info,
> +			enum ipmi_addr_src type,
> +			struct ipmi_smi_info **data)
> +{
> +	struct smi_info *new_smi = send_info;
> +	struct ipmi_smi_info *smi_data = &new_smi->smi_data;
> +
> +	if (new_smi->addr_source != type)
> +		return -EINVAL;
> +
> +	smi_data->addr_src = type;
> +
> +	*data = smi_data;
> +	return 0;
> +}
> +
>  static void set_maintenance_mode(void *send_info, int enable)
>  {
>  	struct smi_info   *smi_info = send_info;
> @@ -1197,6 +1211,7 @@ static void set_maintenance_mode(void *send_info, int enable)
>  static struct ipmi_smi_handlers handlers = {
>  	.owner                  = THIS_MODULE,
>  	.start_processing       = smi_start_processing,
> +	.get_smi_info		= get_smi_info,
>  	.sender			= sender,
>  	.request_events		= request_events,
>  	.set_maintenance_mode   = set_maintenance_mode,
> @@ -2143,6 +2158,8 @@ static int __devinit ipmi_pnp_probe(struct pnp_dev *dev,
>  		return -ENOMEM;
>  
>  	info->addr_source = SI_ACPI;
> +	info->smi_data.smi_info.acpi_info.acpi_handle =
> +				acpi_dev->handle;
>  	printk(KERN_INFO PFX "probing via ACPI\n");
>  
>  	handle = acpi_dev->handle;
> @@ -3092,6 +3109,7 @@ static int try_smi_init(struct smi_info *new_smi)
>  {
>  	int rv = 0;
>  	int i;
> +	struct ipmi_smi_info *smi_data = &new_smi->smi_data;
>  
>  	printk(KERN_INFO PFX "Trying %s-specified %s state"
>  	       " machine at %s address 0x%lx, slave address 0x%x,"
> @@ -3217,6 +3235,8 @@ static int try_smi_init(struct smi_info *new_smi)
>  		new_smi->dev_registered = 1;
>  	}
>  
> +	smi_data->dev = new_smi->dev;
> +
>  	rv = ipmi_register_smi(&handlers,
>  			       new_smi,
>  			       &new_smi->device_id,
> diff --git a/include/linux/ipmi.h b/include/linux/ipmi.h
> index 65aae34..1ce428f 100644
> --- a/include/linux/ipmi.h
> +++ b/include/linux/ipmi.h
> @@ -454,6 +454,29 @@ unsigned int ipmi_addr_length(int addr_type);
>  /* Validate that the given IPMI address is valid. */
>  int ipmi_validate_addr(struct ipmi_addr *addr, int len);
>  
> +enum ipmi_addr_src {
> +	SI_INVALID = 0, SI_HOTMOD, SI_HARDCODED, SI_SPMI, SI_ACPI, SI_SMBIOS,
> +	SI_PCI,	SI_DEVICETREE, SI_DEFAULT
> +};
> +struct ipmi_smi_info{
> +	enum ipmi_addr_src addr_src;
> +	struct device *dev;
> +	union {
> +		/*
> +		 * Now only SI_ACPI info is provided. If the info is required
> +		 * for other type, please add it
> +		 */
> +#ifdef CONFIG_ACPI
> +		struct {
> +			void *acpi_handle;
> +		} acpi_info;
> +#endif
> +	} smi_info;
> +};
> +
> +/* This is to get the private info of ipmi_smi_t. The pointer is returned */
> +extern int ipmi_get_smi_info(int if_num, enum ipmi_addr_src type,
> +		struct ipmi_smi_info **data);
>  #endif /* __KERNEL__ */
>  
> 
> diff --git a/include/linux/ipmi_smi.h b/include/linux/ipmi_smi.h
> index 4b48318..bfa8f40 100644
> --- a/include/linux/ipmi_smi.h
> +++ b/include/linux/ipmi_smi.h
> @@ -86,6 +86,17 @@ struct ipmi_smi_handlers {
>  	int (*start_processing)(void       *send_info,
>  				ipmi_smi_t new_intf);
>  
> +	/*
> +	 * Get the detailed private info of the low level interface and return
> +	 * the corresponding pointer.
> +	 * For example: the ACPI device handle will be returned for the
> +	 * pnp_acpi IPMI device. Of course it will firstly compare the
> +	 * interface type of low-level interface(Hardcoded type, DMI,
> +	 * ACPI and so on). If the type doesn't match, it will return -EINVAL.
> +	 */
> +	int (*get_smi_info)(void *send_info, enum ipmi_addr_src type,
> +				struct ipmi_smi_info **data);
> +
>  	/* Called to enqueue an SMI message to be sent.  This
>  	   operation is not allowed to fail.  If an error occurs, it
>  	   should report back the error in a received message.  It may


^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [RFC PATCH 1/4] IPMI: Add one interface to get more info of low-level IPMI device
  2010-10-22  9:10 ` [RFC PATCH 1/4] IPMI: Add one interface to get more info of low-level IPMI device yakui.zhao
  2010-10-22  9:10   ` [RFC PATCH 2/4] IPMI: Remove the redundant definition of ipmi_addr_src yakui.zhao
  2010-10-25  1:19   ` [RFC PATCH 1/4] IPMI: Add one interface to get more info of low-level IPMI device ykzhao
@ 2010-10-25  3:25   ` Corey Minyard
  2010-10-25  7:00     ` ykzhao
  2 siblings, 1 reply; 11+ messages in thread
From: Corey Minyard @ 2010-10-25  3:25 UTC (permalink / raw)
  To: yakui.zhao; +Cc: openipmi-developer, linux-acpi, lenb

Well, no, you are returning a pointer to something that is in the smi 
data structure.  For that you would need a refcount, because that 
structure can cease to exist asynchronously to your code.  Instead, just 
pass in the structure you want to fill in.  Like:

int ipmi_get_smi_info(int if_num, struct ipmi_smi_info *data)
{
	/* checks here */

	handlers = intf->handlers;
	rv = handlers->get_smi_info(intf->send_info, data);
}

static int get_smi_info(void *send_info,
			struct ipmi_smi_info *data)
{
	struct smi_info *new_smi = send_info;

	data->smi_info.dev = new_smi->dev;
	data->addr_src = new_smi->addr_source;
	data->smi_info.addr_info = new_smi->addr_info;

	return 0;
}



Why are you passing an address type in to the function?  That means you 
would have to know the address type to get anything out of if.  It would 
be better to just return the info and let the user do the comparison.  
That way, if something wanted to fetch the info to get the device, or 
some other info, you don't have to try every address type.

Speaking of the device, that is a refcounted structure.  You can't just 
pass it back without doing refcounts on it.

Can you rename the union addr_info, and comment that which union 
structure is used depends on the address type?

Also, I don't know anything about this ACPI handle, but is that a 
permanent structure?  Can you just grab it like you do and pass it 
around?  I would guess not.

-corey

On 10/22/2010 04:10 AM, yakui.zhao@intel.com wrote:
> From: Zhao Yakui<yakui.zhao@intel.com>
>
> 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>
> ---
> In this patch only the info of pnp_acpi IPMI is provided. If the detailed info
> is also required for other mechanism, please add them in the structure of
> ipmi_smi_info.
>
>   drivers/char/ipmi/ipmi_msghandler.c |   26 ++++++++++++++++++++++++++
>   drivers/char/ipmi/ipmi_si_intf.c    |   28 ++++++++++++++++++++++++----
>   include/linux/ipmi.h                |   23 +++++++++++++++++++++++
>   include/linux/ipmi_smi.h            |   11 +++++++++++
>   4 files changed, 84 insertions(+), 4 deletions(-)
>
> diff --git a/drivers/char/ipmi/ipmi_msghandler.c b/drivers/char/ipmi/ipmi_msghandler.c
> index 4f3f8c9..6f4da59 100644
> --- a/drivers/char/ipmi/ipmi_msghandler.c
> +++ b/drivers/char/ipmi/ipmi_msghandler.c
> @@ -970,6 +970,32 @@ out_kfree:
>   }
>   EXPORT_SYMBOL(ipmi_create_user);
>
> +int ipmi_get_smi_info(int if_num, enum ipmi_addr_src type,
> +			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 = handlers->get_smi_info(intf->send_info, type, data);
> +	mutex_unlock(&ipmi_interfaces_mutex);
> +
> +	return rv;
> +}
> +EXPORT_SYMBOL(ipmi_get_smi_info);
> +
>   static void free_user(struct kref *ref)
>   {
>   	ipmi_user_t user = container_of(ref, struct ipmi_user, refcount);
> diff --git a/drivers/char/ipmi/ipmi_si_intf.c b/drivers/char/ipmi/ipmi_si_intf.c
> index 7bd7c45..73b1c82 100644
> --- a/drivers/char/ipmi/ipmi_si_intf.c
> +++ b/drivers/char/ipmi/ipmi_si_intf.c
> @@ -57,6 +57,7 @@
>   #include<asm/irq.h>
>   #include<linux/interrupt.h>
>   #include<linux/rcupdate.h>
> +#include<linux/ipmi.h>
>   #include<linux/ipmi_smi.h>
>   #include<asm/io.h>
>   #include "ipmi_si_sm.h"
> @@ -107,10 +108,6 @@ enum si_type {
>   };
>   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",
>   					"ACPI", "SMBIOS", "PCI",
>   					"device-tree", "default" };
> @@ -291,6 +288,7 @@ struct smi_info {
>   	struct task_struct *thread;
>
>   	struct list_head link;
> +	struct ipmi_smi_info smi_data;
>   };
>
>   #define smi_inc_stat(smi, stat) \
> @@ -1186,6 +1184,22 @@ static int smi_start_processing(void       *send_info,
>   	return 0;
>   }
>
> +static int get_smi_info(void *send_info,
> +			enum ipmi_addr_src type,
> +			struct ipmi_smi_info **data)
> +{
> +	struct smi_info *new_smi = send_info;
> +	struct ipmi_smi_info *smi_data =&new_smi->smi_data;
> +
> +	if (new_smi->addr_source != type)
> +		return -EINVAL;
> +
> +	smi_data->addr_src = type;
> +
> +	*data = smi_data;
> +	return 0;
> +}
> +
>   static void set_maintenance_mode(void *send_info, int enable)
>   {
>   	struct smi_info   *smi_info = send_info;
> @@ -1197,6 +1211,7 @@ static void set_maintenance_mode(void *send_info, int enable)
>   static struct ipmi_smi_handlers handlers = {
>   	.owner                  = THIS_MODULE,
>   	.start_processing       = smi_start_processing,
> +	.get_smi_info		= get_smi_info,
>   	.sender			= sender,
>   	.request_events		= request_events,
>   	.set_maintenance_mode   = set_maintenance_mode,
> @@ -2143,6 +2158,8 @@ static int __devinit ipmi_pnp_probe(struct pnp_dev *dev,
>   		return -ENOMEM;
>
>   	info->addr_source = SI_ACPI;
> +	info->smi_data.smi_info.acpi_info.acpi_handle =
> +				acpi_dev->handle;
>   	printk(KERN_INFO PFX "probing via ACPI\n");
>
>   	handle = acpi_dev->handle;
> @@ -3092,6 +3109,7 @@ static int try_smi_init(struct smi_info *new_smi)
>   {
>   	int rv = 0;
>   	int i;
> +	struct ipmi_smi_info *smi_data =&new_smi->smi_data;
>
>   	printk(KERN_INFO PFX "Trying %s-specified %s state"
>   	       " machine at %s address 0x%lx, slave address 0x%x,"
> @@ -3217,6 +3235,8 @@ static int try_smi_init(struct smi_info *new_smi)
>   		new_smi->dev_registered = 1;
>   	}
>
> +	smi_data->dev = new_smi->dev;
> +
>   	rv = ipmi_register_smi(&handlers,
>   			       new_smi,
>   			&new_smi->device_id,
> diff --git a/include/linux/ipmi.h b/include/linux/ipmi.h
> index 65aae34..1ce428f 100644
> --- a/include/linux/ipmi.h
> +++ b/include/linux/ipmi.h
> @@ -454,6 +454,29 @@ unsigned int ipmi_addr_length(int addr_type);
>   /* Validate that the given IPMI address is valid. */
>   int ipmi_validate_addr(struct ipmi_addr *addr, int len);
>
> +enum ipmi_addr_src {
> +	SI_INVALID = 0, SI_HOTMOD, SI_HARDCODED, SI_SPMI, SI_ACPI, SI_SMBIOS,
> +	SI_PCI,	SI_DEVICETREE, SI_DEFAULT
> +};
> +struct ipmi_smi_info{
> +	enum ipmi_addr_src addr_src;
> +	struct device *dev;
> +	union {
> +		/*
> +		 * Now only SI_ACPI info is provided. If the info is required
> +		 * for other type, please add it
> +		 */
> +#ifdef CONFIG_ACPI
> +		struct {
> +			void *acpi_handle;
> +		} acpi_info;
> +#endif
> +	} smi_info;
> +};
> +
> +/* This is to get the private info of ipmi_smi_t. The pointer is returned */
> +extern int ipmi_get_smi_info(int if_num, enum ipmi_addr_src type,
> +		struct ipmi_smi_info **data);
>   #endif /* __KERNEL__ */
>
>
> diff --git a/include/linux/ipmi_smi.h b/include/linux/ipmi_smi.h
> index 4b48318..bfa8f40 100644
> --- a/include/linux/ipmi_smi.h
> +++ b/include/linux/ipmi_smi.h
> @@ -86,6 +86,17 @@ struct ipmi_smi_handlers {
>   	int (*start_processing)(void       *send_info,
>   				ipmi_smi_t new_intf);
>
> +	/*
> +	 * Get the detailed private info of the low level interface and return
> +	 * the corresponding pointer.
> +	 * For example: the ACPI device handle will be returned for the
> +	 * pnp_acpi IPMI device. Of course it will firstly compare the
> +	 * interface type of low-level interface(Hardcoded type, DMI,
> +	 * ACPI and so on). If the type doesn't match, it will return -EINVAL.
> +	 */
> +	int (*get_smi_info)(void *send_info, enum ipmi_addr_src type,
> +				struct ipmi_smi_info **data);
> +
>   	/* Called to enqueue an SMI message to be sent.  This
>   	   operation is not allowed to fail.  If an error occurs, it
>   	   should report back the error in a received message.  It may
>    


^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [RFC PATCH 1/4] IPMI: Add one interface to get more info of low-level IPMI device
  2010-10-25  3:25   ` Corey Minyard
@ 2010-10-25  7:00     ` ykzhao
  0 siblings, 0 replies; 11+ messages in thread
From: ykzhao @ 2010-10-25  7:00 UTC (permalink / raw)
  To: Corey Minyard
  Cc: openipmi-developer@lists.sourceforge.net,
	linux-acpi@vger.kernel.org, lenb@kernel.org

On Mon, 2010-10-25 at 11:25 +0800, Corey Minyard wrote: 
> Well, no, you are returning a pointer to something that is in the smi 
> data structure.  For that you would need a refcount, because that 
> structure can cease to exist asynchronously to your code.  Instead, just 
> pass in the structure you want to fill in.  Like:
> 
> int ipmi_get_smi_info(int if_num, struct ipmi_smi_info *data)
> {
> 	/* checks here */
> 
> 	handlers = intf->handlers;
> 	rv = handlers->get_smi_info(intf->send_info, data);
> }
> 
> static int get_smi_info(void *send_info,
> 			struct ipmi_smi_info *data)
> {
> 	struct smi_info *new_smi = send_info;
> 
> 	data->smi_info.dev = new_smi->dev;
> 	data->addr_src = new_smi->addr_source;
> 	data->smi_info.addr_info = new_smi->addr_info;
> 
> 	return 0;
> }
> 

You are right. In theory the refcount should be added if it returns the
pointer of ipmi_smi_info. But as it resides in the smi_info, it will
always exist before the smi_info is released.

OK. To make the thing simpler, I will use the mechanism you recommended.

> 
> 
> Why are you passing an address type in to the function?  That means you 
> would have to know the address type to get anything out of if.  It would 
> be better to just return the info and let the user do the comparison.  
> That way, if something wanted to fetch the info to get the device, or 
> some other info, you don't have to try every address type.

OK. I will remove the argument of address type. 

> 
> Speaking of the device, that is a refcounted structure.  You can't just 
> pass it back without doing refcounts on it.

Yes. In the previous-version patch set, the refcount of dev is increased
when the ipmi_get_smi_info is called.  And it is decreased when the
ipmi_put_smi_info. But after the discussion, it seems that I
misunderstand the refcount and then I remove it in this version. 
Ok, I will call it back. 

> 
> Can you rename the union addr_info, and comment that which union 
> structure is used depends on the address type?
> 
> Also, I don't know anything about this ACPI handle, but is that a 
> permanent structure?  Can you just grab it like you do and pass it 
> around?  I would guess not.

Sorry that I don't know the requirement for other address type when defining the
structure of ipmi_smi_info. But for the ACPI address type, the acpi handle is very 
important. So it is defined in the union structure.


> 
> -corey
> 
> On 10/22/2010 04:10 AM, yakui.zhao@intel.com wrote:
> > From: Zhao Yakui<yakui.zhao@intel.com>
> >
> > 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>
> > ---
> > In this patch only the info of pnp_acpi IPMI is provided. If the detailed info
> > is also required for other mechanism, please add them in the structure of
> > ipmi_smi_info.
> >
> >   drivers/char/ipmi/ipmi_msghandler.c |   26 ++++++++++++++++++++++++++
> >   drivers/char/ipmi/ipmi_si_intf.c    |   28 ++++++++++++++++++++++++----
> >   include/linux/ipmi.h                |   23 +++++++++++++++++++++++
> >   include/linux/ipmi_smi.h            |   11 +++++++++++
> >   4 files changed, 84 insertions(+), 4 deletions(-)
> >
> > diff --git a/drivers/char/ipmi/ipmi_msghandler.c b/drivers/char/ipmi/ipmi_msghandler.c
> > index 4f3f8c9..6f4da59 100644
> > --- a/drivers/char/ipmi/ipmi_msghandler.c
> > +++ b/drivers/char/ipmi/ipmi_msghandler.c
> > @@ -970,6 +970,32 @@ out_kfree:
> >   }
> >   EXPORT_SYMBOL(ipmi_create_user);
> >
> > +int ipmi_get_smi_info(int if_num, enum ipmi_addr_src type,
> > +			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 = handlers->get_smi_info(intf->send_info, type, data);
> > +	mutex_unlock(&ipmi_interfaces_mutex);
> > +
> > +	return rv;
> > +}
> > +EXPORT_SYMBOL(ipmi_get_smi_info);
> > +
> >   static void free_user(struct kref *ref)
> >   {
> >   	ipmi_user_t user = container_of(ref, struct ipmi_user, refcount);
> > diff --git a/drivers/char/ipmi/ipmi_si_intf.c b/drivers/char/ipmi/ipmi_si_intf.c
> > index 7bd7c45..73b1c82 100644
> > --- a/drivers/char/ipmi/ipmi_si_intf.c
> > +++ b/drivers/char/ipmi/ipmi_si_intf.c
> > @@ -57,6 +57,7 @@
> >   #include<asm/irq.h>
> >   #include<linux/interrupt.h>
> >   #include<linux/rcupdate.h>
> > +#include<linux/ipmi.h>
> >   #include<linux/ipmi_smi.h>
> >   #include<asm/io.h>
> >   #include "ipmi_si_sm.h"
> > @@ -107,10 +108,6 @@ enum si_type {
> >   };
> >   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",
> >   					"ACPI", "SMBIOS", "PCI",
> >   					"device-tree", "default" };
> > @@ -291,6 +288,7 @@ struct smi_info {
> >   	struct task_struct *thread;
> >
> >   	struct list_head link;
> > +	struct ipmi_smi_info smi_data;
> >   };
> >
> >   #define smi_inc_stat(smi, stat) \
> > @@ -1186,6 +1184,22 @@ static int smi_start_processing(void       *send_info,
> >   	return 0;
> >   }
> >
> > +static int get_smi_info(void *send_info,
> > +			enum ipmi_addr_src type,
> > +			struct ipmi_smi_info **data)
> > +{
> > +	struct smi_info *new_smi = send_info;
> > +	struct ipmi_smi_info *smi_data =&new_smi->smi_data;
> > +
> > +	if (new_smi->addr_source != type)
> > +		return -EINVAL;
> > +
> > +	smi_data->addr_src = type;
> > +
> > +	*data = smi_data;
> > +	return 0;
> > +}
> > +
> >   static void set_maintenance_mode(void *send_info, int enable)
> >   {
> >   	struct smi_info   *smi_info = send_info;
> > @@ -1197,6 +1211,7 @@ static void set_maintenance_mode(void *send_info, int enable)
> >   static struct ipmi_smi_handlers handlers = {
> >   	.owner                  = THIS_MODULE,
> >   	.start_processing       = smi_start_processing,
> > +	.get_smi_info		= get_smi_info,
> >   	.sender			= sender,
> >   	.request_events		= request_events,
> >   	.set_maintenance_mode   = set_maintenance_mode,
> > @@ -2143,6 +2158,8 @@ static int __devinit ipmi_pnp_probe(struct pnp_dev *dev,
> >   		return -ENOMEM;
> >
> >   	info->addr_source = SI_ACPI;
> > +	info->smi_data.smi_info.acpi_info.acpi_handle =
> > +				acpi_dev->handle;
> >   	printk(KERN_INFO PFX "probing via ACPI\n");
> >
> >   	handle = acpi_dev->handle;
> > @@ -3092,6 +3109,7 @@ static int try_smi_init(struct smi_info *new_smi)
> >   {
> >   	int rv = 0;
> >   	int i;
> > +	struct ipmi_smi_info *smi_data =&new_smi->smi_data;
> >
> >   	printk(KERN_INFO PFX "Trying %s-specified %s state"
> >   	       " machine at %s address 0x%lx, slave address 0x%x,"
> > @@ -3217,6 +3235,8 @@ static int try_smi_init(struct smi_info *new_smi)
> >   		new_smi->dev_registered = 1;
> >   	}
> >
> > +	smi_data->dev = new_smi->dev;
> > +
> >   	rv = ipmi_register_smi(&handlers,
> >   			       new_smi,
> >   			&new_smi->device_id,
> > diff --git a/include/linux/ipmi.h b/include/linux/ipmi.h
> > index 65aae34..1ce428f 100644
> > --- a/include/linux/ipmi.h
> > +++ b/include/linux/ipmi.h
> > @@ -454,6 +454,29 @@ unsigned int ipmi_addr_length(int addr_type);
> >   /* Validate that the given IPMI address is valid. */
> >   int ipmi_validate_addr(struct ipmi_addr *addr, int len);
> >
> > +enum ipmi_addr_src {
> > +	SI_INVALID = 0, SI_HOTMOD, SI_HARDCODED, SI_SPMI, SI_ACPI, SI_SMBIOS,
> > +	SI_PCI,	SI_DEVICETREE, SI_DEFAULT
> > +};
> > +struct ipmi_smi_info{
> > +	enum ipmi_addr_src addr_src;
> > +	struct device *dev;
> > +	union {
> > +		/*
> > +		 * Now only SI_ACPI info is provided. If the info is required
> > +		 * for other type, please add it
> > +		 */
> > +#ifdef CONFIG_ACPI
> > +		struct {
> > +			void *acpi_handle;
> > +		} acpi_info;
> > +#endif
> > +	} smi_info;
> > +};
> > +
> > +/* This is to get the private info of ipmi_smi_t. The pointer is returned */
> > +extern int ipmi_get_smi_info(int if_num, enum ipmi_addr_src type,
> > +		struct ipmi_smi_info **data);
> >   #endif /* __KERNEL__ */
> >
> >
> > diff --git a/include/linux/ipmi_smi.h b/include/linux/ipmi_smi.h
> > index 4b48318..bfa8f40 100644
> > --- a/include/linux/ipmi_smi.h
> > +++ b/include/linux/ipmi_smi.h
> > @@ -86,6 +86,17 @@ struct ipmi_smi_handlers {
> >   	int (*start_processing)(void       *send_info,
> >   				ipmi_smi_t new_intf);
> >
> > +	/*
> > +	 * Get the detailed private info of the low level interface and return
> > +	 * the corresponding pointer.
> > +	 * For example: the ACPI device handle will be returned for the
> > +	 * pnp_acpi IPMI device. Of course it will firstly compare the
> > +	 * interface type of low-level interface(Hardcoded type, DMI,
> > +	 * ACPI and so on). If the type doesn't match, it will return -EINVAL.
> > +	 */
> > +	int (*get_smi_info)(void *send_info, enum ipmi_addr_src type,
> > +				struct ipmi_smi_info **data);
> > +
> >   	/* Called to enqueue an SMI message to be sent.  This
> >   	   operation is not allowed to fail.  If an error occurs, it
> >   	   should report back the error in a received message.  It may
> >    
> 


^ permalink raw reply	[flat|nested] 11+ messages in thread

* [RFC PATCH 2/4] IPMI: Remove the redundant definition of ipmi_addr_src
  2010-10-26  9:14 ` [RFC PATCH 1/4] IPMI: Add one interface to get more info of low-level IPMI device yakui.zhao
@ 2010-10-26  9:14   ` yakui.zhao
  0 siblings, 0 replies; 11+ messages in thread
From: yakui.zhao @ 2010-10-26  9:14 UTC (permalink / raw)
  To: openipmi-developer, linux-acpi; +Cc: minyard, lenb, Zhao Yakui

From: Zhao Yakui <yakui.zhao@intel.com>

The ipmi_addr_src is defined twice. One is in ipmi_smi_info and the other
is in generic smi_info. Remove the redunant definition in smi_info.

Signed-off-by: Zhao Yakui <yakui.zhao@intel.com>
---
 drivers/char/ipmi/ipmi_si_intf.c |   34 ++++++++++++++++------------------
 1 files changed, 16 insertions(+), 18 deletions(-)

diff --git a/drivers/char/ipmi/ipmi_si_intf.c b/drivers/char/ipmi/ipmi_si_intf.c
index d313018..14732a4 100644
--- a/drivers/char/ipmi/ipmi_si_intf.c
+++ b/drivers/char/ipmi/ipmi_si_intf.c
@@ -193,7 +193,6 @@ struct smi_info {
 	int (*irq_setup)(struct smi_info *info);
 	void (*irq_cleanup)(struct smi_info *info);
 	unsigned int io_size;
-	enum ipmi_addr_src addr_source; /* ACPI, PCI, SMBIOS, hardcode, etc. */
 	void (*addr_source_cleanup)(struct smi_info *info);
 	void *addr_source_data;
 
@@ -1196,7 +1195,6 @@ static int get_smi_info(void *send_info, struct ipmi_smi_info *data)
 
 	get_device(new_smi->dev);
 	memcpy(data, smi_data, sizeof(*smi_data));
-	smi_data->addr_src = new_smi->addr_source;
 	atomic_inc(&new_smi->smi_info_ref);
 
 	return 0;
@@ -1811,7 +1809,7 @@ static int hotmod_handler(const char *val, struct kernel_param *kp)
 				goto out;
 			}
 
-			info->addr_source = SI_HOTMOD;
+			info->smi_data.addr_src = SI_HOTMOD;
 			info->si_type = si_type;
 			info->io.addr_data = addr;
 			info->io.addr_type = addr_space;
@@ -1874,7 +1872,7 @@ static __devinit void hardcode_find_bmc(void)
 		if (!info)
 			return;
 
-		info->addr_source = SI_HARDCODED;
+		info->smi_data.addr_src = SI_HARDCODED;
 		printk(KERN_INFO PFX "probing via hardcoded address\n");
 
 		if (!si_type[i] || strcmp(si_type[i], "kcs") == 0) {
@@ -2060,7 +2058,7 @@ static __devinit int try_init_spmi(struct SPMITable *spmi)
 		return -ENOMEM;
 	}
 
-	info->addr_source = SI_SPMI;
+	info->smi_data.addr_src = SI_SPMI;
 	printk(KERN_INFO PFX "probing via SPMI\n");
 
 	/* Figure out the interface type. */
@@ -2168,7 +2166,7 @@ static int __devinit ipmi_pnp_probe(struct pnp_dev *dev,
 	if (!info)
 		return -ENOMEM;
 
-	info->addr_source = SI_ACPI;
+	info->smi_data.addr_src = SI_ACPI;
 	info->smi_data.addr_info.acpi_info.acpi_handle =
 				acpi_dev->handle;
 	printk(KERN_INFO PFX "probing via ACPI\n");
@@ -2353,7 +2351,7 @@ static __devinit void try_init_dmi(struct dmi_ipmi_data *ipmi_data)
 		return;
 	}
 
-	info->addr_source = SI_SMBIOS;
+	info->smi_data.addr_src = SI_SMBIOS;
 	printk(KERN_INFO PFX "probing via SMBIOS\n");
 
 	switch (ipmi_data->type) {
@@ -2458,7 +2456,7 @@ static int __devinit ipmi_pci_probe(struct pci_dev *pdev,
 	if (!info)
 		return -ENOMEM;
 
-	info->addr_source = SI_PCI;
+	info->smi_data.addr_src = SI_PCI;
 	dev_info(&pdev->dev, "probing via PCI");
 
 	switch (class_type) {
@@ -2604,7 +2602,7 @@ static int __devinit ipmi_of_probe(struct platform_device *dev,
 	}
 
 	info->si_type		= (enum si_type) match->data;
-	info->addr_source	= SI_DEVICETREE;
+	info->smi_data.addr_src	= SI_DEVICETREE;
 	info->irq_setup		= std_irq_setup;
 
 	if (resource.flags & IORESOURCE_IO) {
@@ -3046,7 +3044,7 @@ static __devinit void default_find_bmc(void)
 		if (!info)
 			return;
 
-		info->addr_source = SI_DEFAULT;
+		info->smi_data.addr_src = SI_DEFAULT;
 
 		info->si_type = ipmi_defaults[i].type;
 		info->io_setup = port_setup;
@@ -3093,7 +3091,7 @@ static int add_smi(struct smi_info *new_smi)
 	int rv = 0;
 
 	printk(KERN_INFO PFX "Adding %s-specified %s state machine",
-			ipmi_addr_src_to_str[new_smi->addr_source],
+			ipmi_addr_src_to_str[new_smi->smi_data.addr_src],
 			si_to_str[new_smi->si_type]);
 	mutex_lock(&smi_infos_lock);
 	if (!is_new_interface(new_smi)) {
@@ -3125,7 +3123,7 @@ static int try_smi_init(struct smi_info *new_smi)
 	printk(KERN_INFO PFX "Trying %s-specified %s state"
 	       " machine at %s address 0x%lx, slave address 0x%x,"
 	       " irq %d\n",
-	       ipmi_addr_src_to_str[new_smi->addr_source],
+	       ipmi_addr_src_to_str[new_smi->smi_data.addr_src],
 	       si_to_str[new_smi->si_type],
 	       addr_space_to_str[new_smi->io.addr_type],
 	       new_smi->io.addr_data,
@@ -3173,7 +3171,7 @@ static int try_smi_init(struct smi_info *new_smi)
 
 	/* Do low-level detection first. */
 	if (new_smi->handlers->detect(new_smi->si_sm)) {
-		if (new_smi->addr_source)
+		if (new_smi->smi_data.addr_src)
 			printk(KERN_INFO PFX "Interface detection failed\n");
 		rv = -ENODEV;
 		goto out_err;
@@ -3185,7 +3183,7 @@ static int try_smi_init(struct smi_info *new_smi)
 	 */
 	rv = try_get_dev_id(new_smi);
 	if (rv) {
-		if (new_smi->addr_source)
+		if (new_smi->smi_data.addr_src)
 			printk(KERN_INFO PFX "There appears to be no BMC"
 			       " at this location\n");
 		goto out_err;
@@ -3420,9 +3418,9 @@ static __devinit int init_ipmi_si(void)
 		/* Try to register a device if it has an IRQ and we either
 		   haven't successfully registered a device yet or this
 		   device has the same type as one we successfully registered */
-		if (e->irq && (!type || e->addr_source == type)) {
+		if (e->irq && (!type || e->smi_data.addr_src == type)) {
 			if (!try_smi_init(e)) {
-				type = e->addr_source;
+				type = e->smi_data.addr_src;
 			}
 		}
 	}
@@ -3436,9 +3434,9 @@ static __devinit int init_ipmi_si(void)
 	/* Fall back to the preferred device */
 
 	list_for_each_entry(e, &smi_infos, link) {
-		if (!e->irq && (!type || e->addr_source == type)) {
+		if (!e->irq && (!type || e->smi_data.addr_src == type)) {
 			if (!try_smi_init(e)) {
-				type = e->addr_source;
+				type = e->smi_data.addr_src;
 			}
 		}
 	}
-- 
1.5.4.5


^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [RFC PATCH 2/4] IPMI: Remove the redundant definition of ipmi_addr_src
  2010-11-30  0:26 ` [RFC PATCH 1/4] IPMI: Add one interface to get more info of low-level IPMI device yakui.zhao
@ 2010-11-30  0:26   ` yakui.zhao
  0 siblings, 0 replies; 11+ messages in thread
From: yakui.zhao @ 2010-11-30  0:26 UTC (permalink / raw)
  To: minyard; +Cc: openipmi-developer, lenb, linux-acpi, Zhao Yakui

From: Zhao Yakui <yakui.zhao@intel.com>

The ipmi_addr_src is defined twice. One is in ipmi_smi_info and the other
is in generic smi_info. Remove the redunant definition in smi_info.

Signed-off-by: Zhao Yakui <yakui.zhao@intel.com>
---
 drivers/char/ipmi/ipmi_si_intf.c |   34 ++++++++++++++++------------------
 1 files changed, 16 insertions(+), 18 deletions(-)

diff --git a/drivers/char/ipmi/ipmi_si_intf.c b/drivers/char/ipmi/ipmi_si_intf.c
index a41afca..dc9d593 100644
--- a/drivers/char/ipmi/ipmi_si_intf.c
+++ b/drivers/char/ipmi/ipmi_si_intf.c
@@ -193,7 +193,6 @@ struct smi_info {
 	int (*irq_setup)(struct smi_info *info);
 	void (*irq_cleanup)(struct smi_info *info);
 	unsigned int io_size;
-	enum ipmi_addr_src addr_source; /* ACPI, PCI, SMBIOS, hardcode, etc. */
 	void (*addr_source_cleanup)(struct smi_info *info);
 	void *addr_source_data;
 
@@ -1190,7 +1189,6 @@ static int get_smi_info(void *send_info, struct ipmi_smi_info *data)
 	struct ipmi_smi_info *smi_data = &new_smi->smi_data;
 
 	memcpy(data, smi_data, sizeof(*smi_data));
-	data->addr_src = new_smi->addr_source;
 	get_device(new_smi->dev);
 
 	return 0;
@@ -1807,7 +1805,7 @@ static int hotmod_handler(const char *val, struct kernel_param *kp)
 				goto out;
 			}
 
-			info->addr_source = SI_HOTMOD;
+			info->smi_data.addr_src = SI_HOTMOD;
 			info->si_type = si_type;
 			info->io.addr_data = addr;
 			info->io.addr_type = addr_space;
@@ -1870,7 +1868,7 @@ static void __devinit hardcode_find_bmc(void)
 		if (!info)
 			return;
 
-		info->addr_source = SI_HARDCODED;
+		info->smi_data.addr_src = SI_HARDCODED;
 		printk(KERN_INFO PFX "probing via hardcoded address\n");
 
 		if (!si_type[i] || strcmp(si_type[i], "kcs") == 0) {
@@ -2055,7 +2053,7 @@ static int __devinit try_init_spmi(struct SPMITable *spmi)
 		return -ENOMEM;
 	}
 
-	info->addr_source = SI_SPMI;
+	info->smi_data.addr_src = SI_SPMI;
 	printk(KERN_INFO PFX "probing via SPMI\n");
 
 	/* Figure out the interface type. */
@@ -2163,7 +2161,7 @@ static int __devinit ipmi_pnp_probe(struct pnp_dev *dev,
 	if (!info)
 		return -ENOMEM;
 
-	info->addr_source = SI_ACPI;
+	info->smi_data.addr_src = SI_ACPI;
 	info->smi_data.addr_info.acpi_info.acpi_handle =
 				acpi_dev->handle;
 	printk(KERN_INFO PFX "probing via ACPI\n");
@@ -2348,7 +2346,7 @@ static void __devinit try_init_dmi(struct dmi_ipmi_data *ipmi_data)
 		return;
 	}
 
-	info->addr_source = SI_SMBIOS;
+	info->smi_data.addr_src = SI_SMBIOS;
 	printk(KERN_INFO PFX "probing via SMBIOS\n");
 
 	switch (ipmi_data->type) {
@@ -2453,7 +2451,7 @@ static int __devinit ipmi_pci_probe(struct pci_dev *pdev,
 	if (!info)
 		return -ENOMEM;
 
-	info->addr_source = SI_PCI;
+	info->smi_data.addr_src = SI_PCI;
 	dev_info(&pdev->dev, "probing via PCI");
 
 	switch (class_type) {
@@ -2599,7 +2597,7 @@ static int __devinit ipmi_of_probe(struct platform_device *dev,
 	}
 
 	info->si_type		= (enum si_type) match->data;
-	info->addr_source	= SI_DEVICETREE;
+	info->smi_data.addr_src	= SI_DEVICETREE;
 	info->irq_setup		= std_irq_setup;
 
 	if (resource.flags & IORESOURCE_IO) {
@@ -3041,7 +3039,7 @@ static void __devinit default_find_bmc(void)
 		if (!info)
 			return;
 
-		info->addr_source = SI_DEFAULT;
+		info->smi_data.addr_src = SI_DEFAULT;
 
 		info->si_type = ipmi_defaults[i].type;
 		info->io_setup = port_setup;
@@ -3088,7 +3086,7 @@ static int add_smi(struct smi_info *new_smi)
 	int rv = 0;
 
 	printk(KERN_INFO PFX "Adding %s-specified %s state machine",
-			ipmi_addr_src_to_str[new_smi->addr_source],
+			ipmi_addr_src_to_str[new_smi->smi_data.addr_src],
 			si_to_str[new_smi->si_type]);
 	mutex_lock(&smi_infos_lock);
 	if (!is_new_interface(new_smi)) {
@@ -3120,7 +3118,7 @@ static int try_smi_init(struct smi_info *new_smi)
 	printk(KERN_INFO PFX "Trying %s-specified %s state"
 	       " machine at %s address 0x%lx, slave address 0x%x,"
 	       " irq %d\n",
-	       ipmi_addr_src_to_str[new_smi->addr_source],
+	       ipmi_addr_src_to_str[new_smi->smi_data.addr_src],
 	       si_to_str[new_smi->si_type],
 	       addr_space_to_str[new_smi->io.addr_type],
 	       new_smi->io.addr_data,
@@ -3165,7 +3163,7 @@ static int try_smi_init(struct smi_info *new_smi)
 
 	/* Do low-level detection first. */
 	if (new_smi->handlers->detect(new_smi->si_sm)) {
-		if (new_smi->addr_source)
+		if (new_smi->smi_data.addr_src)
 			printk(KERN_INFO PFX "Interface detection failed\n");
 		rv = -ENODEV;
 		goto out_err;
@@ -3177,7 +3175,7 @@ static int try_smi_init(struct smi_info *new_smi)
 	 */
 	rv = try_get_dev_id(new_smi);
 	if (rv) {
-		if (new_smi->addr_source)
+		if (new_smi->smi_data.addr_src)
 			printk(KERN_INFO PFX "There appears to be no BMC"
 			       " at this location\n");
 		goto out_err;
@@ -3411,9 +3409,9 @@ static int __devinit init_ipmi_si(void)
 		/* Try to register a device if it has an IRQ and we either
 		   haven't successfully registered a device yet or this
 		   device has the same type as one we successfully registered */
-		if (e->irq && (!type || e->addr_source == type)) {
+		if (e->irq && (!type || e->smi_data.addr_src == type)) {
 			if (!try_smi_init(e)) {
-				type = e->addr_source;
+				type = e->smi_data.addr_src;
 			}
 		}
 	}
@@ -3427,9 +3425,9 @@ static int __devinit init_ipmi_si(void)
 	/* Fall back to the preferred device */
 
 	list_for_each_entry(e, &smi_infos, link) {
-		if (!e->irq && (!type || e->addr_source == type)) {
+		if (!e->irq && (!type || e->smi_data.addr_src == type)) {
 			if (!try_smi_init(e)) {
-				type = e->addr_source;
+				type = e->smi_data.addr_src;
 			}
 		}
 	}
-- 
1.5.4.5


^ permalink raw reply related	[flat|nested] 11+ messages in thread

end of thread, other threads:[~2010-11-30  0:32 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2010-10-22  9:10 [RFC PATCH 0/4_v11] IPMI/ACPI: Install the ACPI IPMI opregion yakui.zhao
2010-10-22  9:10 ` [RFC PATCH 1/4] IPMI: Add one interface to get more info of low-level IPMI device yakui.zhao
2010-10-22  9:10   ` [RFC PATCH 2/4] IPMI: Remove the redundant definition of ipmi_addr_src yakui.zhao
2010-10-22  9:10     ` [RFC PATCH 3/4] IPMI: Add the document description of ipmi_get_smi_info yakui.zhao
2010-10-22  9:10       ` [RFC PATCH 04/4] IPMI/ACPI: Add the IPMI opregion driver to enable ACPI to access BMC controller yakui.zhao
2010-10-25  1:19   ` [RFC PATCH 1/4] IPMI: Add one interface to get more info of low-level IPMI device ykzhao
2010-10-25  3:25   ` Corey Minyard
2010-10-25  7:00     ` ykzhao
  -- strict thread matches above, loose matches on Subject: below --
2010-11-30  0:26 [RFC PATCH 0/4_v13] IPMI/ACPI: Install the ACPI IPMI opregion yakui.zhao
2010-11-30  0:26 ` [RFC PATCH 1/4] IPMI: Add one interface to get more info of low-level IPMI device yakui.zhao
2010-11-30  0:26   ` [RFC PATCH 2/4] IPMI: Remove the redundant definition of ipmi_addr_src yakui.zhao
2010-10-26  9:14 [RFC PATCH 0/4_v11] IPMI/ACPI: Install the ACPI IPMI opregion yakui.zhao
2010-10-26  9:14 ` [RFC PATCH 1/4] IPMI: Add one interface to get more info of low-level IPMI device yakui.zhao
2010-10-26  9:14   ` [RFC PATCH 2/4] IPMI: Remove the redundant definition of ipmi_addr_src yakui.zhao
2010-10-12  7:47 [RFC PATCH 0/4_v10] IPMI/ACPI: Install the ACPI IPMI opregion yakui.zhao
2010-10-12  7:47 ` [RFC PATCH 1/4] IPMI: Add one interface to get more info of low-level IPMI device yakui.zhao
2010-10-12  7:47   ` [RFC PATCH 2/4] IPMI: Remove the redundant definition of ipmi_addr_src yakui.zhao

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).