Skip to contentSkip to conversation

acpi_find_bmc() and acpi_get_table()

PATCH Len Brown 6 participants 26 messages Feb 11, 2007 – Jul 17, 2008

Subsystems (2)
lore
Share & tools
lore

Len Brown

author reviewer
#0 lore raw

Cory,
acpi_find_bmc() appears to be searching for
multiple SPMI tables in the RSDT and running
try_init_acpi() on each of them
until it doesn't find any more.

Is that the intent?

Are here systems with multiple SPMI tables?

static __devinit void acpi_find_bmc(void)

{
        acpi_status      status;
        struct SPMITable *spmi;
        int              i;

        if (acpi_disabled)
                return;

        if (acpi_failure)
                return;

        for (i = 0; ; i++) {
                status = acpi_get_table(ACPI_SIG_SPMI, i+1,
                                        (struct acpi_table_header **)&spmi);
                if (status != AE_OK)
                        return;

                try_init_acpi(spmi);
        }
}

I speculated recently that the only table signature
that is (supposed to be) repeated in the RSDT is an SSDT. Maybe that speculation is wrong if there can be multiple SPMI tables...

Bob, Alexey,
Also, one thing I'm not excited about is that acpi_get_table() treats instance number 0 and 1 as synonyms -- which is presumably why "i+1" is used above. I think it would make sense if instance 0 and instance 1 were different instances.

ie.

drivers/acpi/tables/tbxface.c +1 -1
@@ -397,7 +397,7 @@ acpi_get_table(char *signature,
                        continue;
                }
 
-               if (++j < instance) {
+               if (++j <= instance) {
                        continue;
                }
 

thanks,
-Len

#1 lore raw
Quoted 9 lines · Len Brown

Cory,
acpi_find_bmc() appears to be searching for multiple SPMI tables in the RSDT and running try_init_acpi() on each of them
until it doesn't find any more.

Is that the intent?

Are here systems with multiple SPMI tables?

I'm not sure about ACPI, but I know there are system with multiple SMBIOS table entries for management controllers, and I know there are system with multiple multiple management controller interfaces (and multiple management controllers with interfaces). The current table for SPMI can only support one interface, so I don't know how you could represent more than one..

Quoted 22 lines

static __devinit void acpi_find_bmc(void)

{
        acpi_status      status;
        struct SPMITable *spmi;
        int              i;

        if (acpi_disabled)
                return;

        if (acpi_failure)
                return;

        for (i = 0; ; i++) {
                status = acpi_get_table(ACPI_SIG_SPMI, i+1,
                                        (struct acpi_table_header **)&spmi);
                if (status != AE_OK)
                        return;

                try_init_acpi(spmi);
        }
}
Quoted 4 lines

I speculated recently that the only table signature
that is (supposed to be) repeated in the RSDT is an SSDT. Maybe that speculation is wrong if there can be multiple SPMI tables...

I don't know ACPI that well, but the IPMI spec states that in the case of multiple interfaces, a unique SPMI table should be provided for each of those interfaces. So the IPMI spec seems to require support more than one.

-Corey

author reviewer
#2 lore raw
Quoted 4 lines · Corey Minyard

...the IPMI spec states that in the case
of multiple interfaces, a unique SPMI table should be provided for each of those interfaces. So the IPMI spec seems to require support more than one.

okay, good to know.
If you have the dmesg or acpidump output from a box with multiple interfaces, we should then see multiple SPMI entries in the RSDT.

thanks,
-Len

#3 lore raw
In reply to Len Brown
Quoted 4 lines · Len Brown

acpi_find_bmc() appears to be searching for multiple SPMI tables in the RSDT and running try_init_acpi() on each of them
until it doesn't find any more.

I can't remember why we look at the SPMI table(s) rather than registering a normal ACPI (or even PNP) driver. Unless we need to poke the BMC very early, wouldn't it be better to rely on the device description in the namespace?

Bjorn

#4 lore raw
Quoted 7 lines · Bjorn Helgaas
Quoted 4 lines · Len Brown

acpi_find_bmc() appears to be searching for multiple SPMI tables in the RSDT and running try_init_acpi() on each of them
until it doesn't find any more.

Quoted 5 lines

I can't remember why we look at the SPMI table(s) rather than registering a normal ACPI (or even PNP) driver. Unless we need to poke the BMC very early, wouldn't it be better to rely on the device description in the namespace?

For some strange reason the normal ACPI information does not have all the information needed by the driver. It doesn't have register size or spacing information.

-Corey

#5 lore raw
Quoted 9 lines · Corey Minyard
Quoted 8 lines · Bjorn Helgaas
Quoted 5 lines · Len Brown

acpi_find_bmc() appears to be searching for multiple SPMI tables in the RSDT and running try_init_acpi() on each of them
until it doesn't find any more.

Quoted 8 lines
Quoted 5 lines

I can't remember why we look at the SPMI table(s) rather than registering a normal ACPI (or even PNP) driver. Unless we need to poke the BMC very early, wouldn't it be better to rely on the device description in the namespace?

For some strange reason the normal ACPI information does not have all the information needed by the driver. It doesn't have register size or spacing information.

I guess that would be a defect in the way ACPI is being used, wouldn't it? A PNP ID should define the device programming model, including things like register size and spacing. It sounds like somebody didn't define a new PNP ID when he should have. I wonder whether it's worth trying to fix this.

Bjorn

#6 lore raw
Quoted 23 lines · Bjorn Helgaas
Quoted 16 lines · Corey Minyard
Quoted 8 lines · Bjorn Helgaas
Quoted 5 lines · Len Brown

acpi_find_bmc() appears to be searching for multiple SPMI tables in the RSDT and running try_init_acpi() on each of them
until it doesn't find any more.

Quoted 6 lines

I can't remember why we look at the SPMI table(s) rather than registering a normal ACPI (or even PNP) driver. Unless we need to poke the BMC very early, wouldn't it be better to rely on the device description in the namespace?

Quoted 4 lines

For some strange reason the normal ACPI information does not have all the information needed by the driver. It doesn't have register size or spacing information.

Quoted 7 lines

I guess that would be a defect in the way ACPI is being used, wouldn't it? A PNP ID should define the device programming model, including things like register size and spacing. It sounds like somebody didn't define a new PNP ID when he should have. I wonder whether it's worth trying to fix this.

Yes, it is considered an ACPI fault. Could you please describe in detail, which registers miss the information? And probably your acpidump will help as well.

Quoted 3 lines

Bjorn
-

Thanks,
Alex.

#7 lore raw
Quoted 29 lines · Alexey Starikovskiy
Quoted 21 lines · Bjorn Helgaas
Quoted 9 lines · Corey Minyard
Quoted 7 lines · Bjorn Helgaas
Quoted 5 lines · Len Brown

acpi_find_bmc() appears to be searching for multiple SPMI tables in the RSDT and running
try_init_acpi() on each of them
until it doesn't find any more.

Quoted 9 lines
Quoted 5 lines

I can't remember why we look at the SPMI table(s) rather than registering a normal ACPI (or even PNP) driver. Unless we need to poke the BMC very early, wouldn't it be better to rely on the device description in the namespace?

For some strange reason the normal ACPI information does not have all the information needed by the driver. It doesn't have register size or spacing information.

Quoted 7 lines

I guess that would be a defect in the way ACPI is being used, wouldn't it? A PNP ID should define the device programming model, including things like register size and spacing. It sounds like somebody didn't define a new PNP ID when he should have. I wonder whether it's worth trying to fix this.

Quoted 3 lines

Yes, it is considered an ACPI fault. Could you please describe in detail, which registers miss the information? And probably your acpidump will help as well.

I don't have a machine with an ACPI description of the BMC. I'll copy the mailing list to see if anyone has an ACPI-described BMC.

I don't know that much about ACPI, so maybe that information is described somehow in a way the IPMI spec doesn't talk about directly, like in the _CRS object.

-Corey

-------------------------------------------------------------------------
Take Surveys. Earn Cash. Influence the Future of IT
Join SourceForge.net's Techsay panel and you'll get the chance to share your opinions on IT & business topics through brief surveys-and earn cash
http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV

#8 lore raw
Quoted 33 lines · Corey Minyard
Quoted 29 lines · Alexey Starikovskiy
Quoted 21 lines · Bjorn Helgaas
Quoted 9 lines · Corey Minyard
Quoted 7 lines · Bjorn Helgaas
Quoted 5 lines · Len Brown

acpi_find_bmc() appears to be searching for multiple SPMI tables in the RSDT and running
try_init_acpi() on each of them
until it doesn't find any more.

Quoted 9 lines
Quoted 5 lines

I can't remember why we look at the SPMI table(s) rather than registering a normal ACPI (or even PNP) driver. Unless we need to poke the BMC very early, wouldn't it be better to rely on the device description in the namespace?

For some strange reason the normal ACPI information does not have all the information needed by the driver. It doesn't have register size or spacing information.

Quoted 7 lines

I guess that would be a defect in the way ACPI is being used, wouldn't it? A PNP ID should define the device programming model, including things like register size and spacing. It sounds like somebody didn't define a new PNP ID when he should have. I wonder whether it's worth trying to fix this.

Quoted 3 lines

Yes, it is considered an ACPI fault. Could you please describe in detail, which registers miss the information? And probably your acpidump will help as well.

Quoted 6 lines

I don't have a machine with an ACPI description of the BMC. I'll copy the mailing list to see if anyone has an ACPI-described BMC.

I don't know that much about ACPI, so maybe that information is described somehow in a way the IPMI spec doesn't talk about directly, like in the _CRS object.

Let me copy my teammate Jordan Hargrave in on this, as he's been working with our BIOS team to implement discovery through an IPI0 object in the namespace, and thinks he can derive the register spacing and interrupt assignment (if any).

Signature · 10 lines
Matt Domsch
Software Architect
Dell Linux Solutions linux.dell.com & www.dell.com/linux
Linux on Dell mailing lists @ http://lists.us.dell.com

-------------------------------------------------------------------------
Take Surveys. Earn Cash. Influence the Future of IT
Join SourceForge.net's Techsay panel and you'll get the chance to share your
opinions on IT & business topics through brief surveys-and earn cash
http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV
#9 lore raw

Corey,

Here is the patch (RHEL5 base code) I've been testing that detects the ACPI namespace object.
The IPI0001 device doesn't contain the register spacing directly; it has a _CRS resource object that
(for KCS) has two I/O port entries. I save the first port in io.addr_data, then calculate the register spacing based on subtracting the 2nd port address and the 1st.

I'm thinking of changing the register spacing to using an array of port/memory addresses to make calculating interface addresses more generic.

eg.
static unsigned char port_inb(struct si_sm_io *io, unsigned int offset)

{
        unsigned int addr = io->addr_data;

        return inb(addr + (offset * io->regspacing));
}

would become something like:
static unsigned char port_inb(struct si_sm_io *io, unsigned int offset)

{
        unsigned int addr = io->addr_data[offset];

        return inb(addr);
}

--jordan hargrave
Dell Enterprise Linux Engineering

-----Original Message-----
From: Matt Domsch [mailto:[email protected]]
Sent: Sun 2/25/2007 3:59 PM
To: Corey Minyard; Hargrave, Jordan
Cc: Alexey Starikovskiy; [email protected]; openipmi; Len Brown; Bjorn Helgaas
Subject: Re: [Openipmi-developer] acpi_find_bmc() and acpi_get_table()

Quoted 33 lines · Corey Minyard
Quoted 29 lines · Alexey Starikovskiy
Quoted 21 lines · Bjorn Helgaas
Quoted 9 lines · Corey Minyard
Quoted 7 lines · Bjorn Helgaas
Quoted 5 lines · Len Brown

acpi_find_bmc() appears to be searching for multiple SPMI tables in the RSDT and running
try_init_acpi() on each of them
until it doesn't find any more.

Quoted 9 lines
Quoted 5 lines

I can't remember why we look at the SPMI table(s) rather than registering a normal ACPI (or even PNP) driver. Unless we need to poke the BMC very early, wouldn't it be better to rely on the device description in the namespace?

For some strange reason the normal ACPI information does not have all the information needed by the driver. It doesn't have register size or spacing information.

Quoted 7 lines

I guess that would be a defect in the way ACPI is being used, wouldn't it? A PNP ID should define the device programming model, including things like register size and spacing. It sounds like somebody didn't define a new PNP ID when he should have. I wonder whether it's worth trying to fix this.

Quoted 3 lines

Yes, it is considered an ACPI fault. Could you please describe in detail, which registers miss the information? And probably your acpidump will help as well.

Quoted 6 lines

I don't have a machine with an ACPI description of the BMC. I'll copy the mailing list to see if anyone has an ACPI-described BMC.

I don't know that much about ACPI, so maybe that information is described somehow in a way the IPMI spec doesn't talk about directly, like in the _CRS object.

Let me copy my teammate Jordan Hargrave in on this, as he's been working with our BIOS team to implement discovery through an IPI0 object in the namespace, and thinks he can derive the register spacing and interrupt assignment (if any).

Signature · 4 lines
Matt Domsch
Software Architect
Dell Linux Solutions linux.dell.com & www.dell.com/linux
Linux on Dell mailing lists @ http://lists.us.dell.com
ipmi_si_intf.c renamed from usr/src/redhat/BUILD/kernel-2.6.18/linux-2.6.18.x86_64/drivers/char/ipmi/ipmi_si_intf.c +124 -0
@@ -1371,6 +1371,58 @@ static __devinit void hardcode_find_bmc(
    through the tables sequentially.  Once we don't find a table, there
    are no more. */
 static int acpi_failure = 0;
+static acpi_handle acpi_ipmi_handle;
+
+#define ACPI_IPMI_DRIVER_NAME "ipmi"
+#define ACPI_IPMI_CLASS       "ipmi"
+#define ACPI_IPMI_HID         "IPI0001"
+
+static int acpi_ipmi_add(struct acpi_device *);
+static int acpi_ipmi_remove(struct acpi_device *, int);
+
+static struct acpi_driver acpi_ipmi_driver = {
+  .name = ACPI_IPMI_DRIVER_NAME,
+  .class = ACPI_IPMI_CLASS,
+  .ids = ACPI_IPMI_HID,
+  .ops = {
+    .add = acpi_ipmi_add,
+    .remove = acpi_ipmi_remove,
+  },
+};
+
+static acpi_status
+acpi_ipmi_getresource(struct acpi_resource *res, void *context)
+{
+	struct smi_info *info = context;
+	
+	if (res->type == ACPI_RESOURCE_TYPE_IO) {
+		struct acpi_resource_io *io_res = &res->data.io;
+		if (info->io.addr_data == 0) {
+			info->io.regshift = 0;
+			info->io.regsize = io_res->address_length;
+			info->io.addr_data = io_res->minimum;
+			info->io.addr_type = IPMI_IO_ADDR_SPACE;
+			info->io_setup = port_setup;
+		}
+		else {
+			/* Calculate regspacing based on previous register */
+			info->io.regspacing = io_res->minimum - info->io.addr_data;
+		}
+	}
+	return AE_OK;
+}
+
+int acpi_ipmi_add(struct acpi_device *device)
+{
+	if (device)
+		acpi_ipmi_handle = device->handle;
+	return 0;
+}
+
+int acpi_ipmi_remove(struct acpi_device *device, int type)
+{
+	return 0;
+}
 
 /* For GPE-type interrupts. */
 static u32 ipmi_acpi_gpe(void *context)
@@ -1478,6 +1530,72 @@ struct SPMITable {
 	s8      spmi_id[1]; /* A '\0' terminated array starts here. */
 };
 
+static __devinit int try_init_acpidev()
+{
+  	acpi_status status = AE_OK;
+	unsigned long sta, type, gpe;
+	struct smi_info  *info;
+
+	if (acpi_ipmi_handle == 0)
+	  	return -ENODEV;
+
+	info = kzalloc(sizeof(*info), GFP_KERNEL);
+	if (info == NULL) {
+		printk(KERN_ERR "ipmi_si: Could not allocate SI data (3)\n");
+	  	return -ENOMEM;
+	}
+
+	status = acpi_evaluate_integer(acpi_ipmi_handle, "_STA", NULL, &sta);
+	if (status != AE_OK || !(sta & ACPI_STA_DEVICE_PRESENT)) {
+		printk(KERN_ERR "ipmi_si: _STA not present\n");
+		kfree(info);
+		return -ENODEV;
+	}
+
+	status = acpi_evaluate_integer(acpi_ipmi_handle, "_IFT", NULL, &type);
+	if (status != AE_OK) {
+		printk(KERN_ERR "ipmi_si: Could not get _IFT interface type\n");
+		kfree(info);
+		return -ENODEV;
+	}
+	status = acpi_evaluate_integer(acpi_ipmi_handle, "_GPE", NULL, &gpe);
+	if (status == AE_OK) {
+		info->irq = gpe;
+		info->irq_setup = acpi_gpe_irq_setup;
+	}
+
+	info->addr_source = "ACPI";
+	switch (type) {
+	case 1:
+		info->si_type = SI_KCS;
+		break;
+	case 2:
+		info->si_type = SI_SMIC;
+		break;
+	case 3:
+		info->si_type = SI_BT;
+		break;
+	default:
+		printk(KERN_INFO "ipmi_si: Unknown ACPI/SPMI SI type %d\n",
+			type);
+		kfree(info);
+		return -EIO;
+	}
+	acpi_walk_resources(acpi_ipmi_handle, METHOD_NAME__CRS,
+			    acpi_ipmi_getresource, info);
+	if (info->io.regspacing == 0) {
+		printk(KERN_ERR "ipmi_si: Could not get register spacing!\n");
+		kfree(info);
+		return -ENODEV;
+	}
+	if (try_smi_init(info) == 0) {
+		printk(KERN_INFO "ipmi_si: Found ACPI IPMI device %s at %s address 0x%lx\n",
+			si_to_str[info->si_type], addr_space_to_str[info->io.addr_type],
+			info->io.addr_data);
+	}
+	return 0;
+}
+
 static __devinit int try_init_acpi(struct SPMITable *spmi)
 {
 	struct smi_info  *info;
@@ -1576,6 +1694,12 @@ static __devinit void acpi_find_bmc(void
 	if (acpi_failure)
 		return;
 
+	/* Really we only need to get the IPMI device handle here */
+	acpi_bus_register_driver(&acpi_ipmi_driver);
+	acpi_bus_unregister_driver(&acpi_ipmi_driver);
+	if (try_init_acpidev() == 0)
+		return;
+
 	for (i = 0; ; i++) {
 		status = acpi_get_firmware_table("SPMI", i+1,
 						 ACPI_LOGICAL_ADDRESSING,

-------------------------------------------------------------------------
Take Surveys. Earn Cash. Influence the Future of IT
Join SourceForge.net's Techsay panel and you'll get the chance to share your opinions on IT & business topics through brief surveys-and earn cash
http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV

_______________________________________________
Openipmi-developer mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/openipmi-developer

#10 lore raw
Quoted 2 lines · On Monday 26 February 2007 11:30, [email protected] wrote:

Here is the patch (RHEL5 base code) I've been testing that detects the ACPI namespace object.

I like this approach a lot.

Shouldn't acpi_ipmi_getresource() also look for IRQ descriptors? The existing code that looks at the SPMI table can handle either GPEs or regular IOxAPIC interrupts (i.e., a GSI).

You might also want to look for memory address ranges as well as IO ranges.

I wish you could use pnp_register_driver() instead of acpi_bus_register_driver(). That would let you get rid of all the _CRS parsing. But I forgot that IPMI devices often use GPEs instead of regular interrupts, and GPEs require a different path (acpi_install_gpe_handler() instead of request_irq(), etc), so I guess you're stuck with grubbing through _CRS by hand.

Plus, it looks like you need the _IFT thing to figure out what type of interface it is. It might have been nicer if there were separate PNP IDs for KCS vs SMIC vs BT. But that's water under the bridge.

Bjorn

#11 lore raw

Correct, the parseresource code really should look for IRQ/MEM, but I haven't yet seen any ACPI namespaces that use memory or IRQ resources with IPI0001 for testing. (I have a huge collection of DSDTs from my OpenBSD work).

--jordan hargrave
Dell Enterprise Linux Engineering

-----Original Message-----
From: Bjorn Helgaas [mailto:[email protected]]
Sent: Mon 2/26/2007 1:32 PM
To: Hargrave, Jordan
Cc: Domsch, Matt; [email protected]; [email protected]; [email protected]; [email protected]; [email protected]
Subject: Re: [Openipmi-developer] acpi_find_bmc() and acpi_get_table()

Quoted 2 lines · On Monday 26 February 2007 11:30, [email protected] wrote:

Here is the patch (RHEL5 base code) I've been testing that detects the ACPI namespace object.

I like this approach a lot.

Shouldn't acpi_ipmi_getresource() also look for IRQ descriptors? The existing code that looks at the SPMI table can handle either GPEs or regular IOxAPIC interrupts (i.e., a GSI).

You might also want to look for memory address ranges as well as IO ranges.

I wish you could use pnp_register_driver() instead of acpi_bus_register_driver(). That would let you get rid of all the _CRS parsing. But I forgot that IPMI devices often use GPEs instead of regular interrupts, and GPEs require a different path (acpi_install_gpe_handler() instead of request_irq(), etc), so I guess you're stuck with grubbing through _CRS by hand.

Plus, it looks like you need the _IFT thing to figure out what type of interface it is. It might have been nicer if there were separate PNP IDs for KCS vs SMIC vs BT. But that's water under the bridge.

Bjorn

#12 lore raw

[This bounced from the list because I attached too much stuff. If you want copies of the DSDTs I mentioned below, let me know and I can mail them to you individually.]

Quoted 4 lines · On Monday 26 February 2007 13:06, [email protected] wrote:

Correct, the parseresource code really should look for IRQ/MEM, but I haven't yet seen any ACPI namespaces that use memory or IRQ resources with IPI0001 for testing. (I have a huge collection of DSDTs from my OpenBSD work).

Here are a couple for your collection :-) These are from HP Itanium boxes. (Is that collection publicly available, by the way?)

These both use IRQ and MEM descriptors.

But they don't have _IFT or _SRV objects. They do have "TYPE" and "SPEC" methods. These are essentially the same, but they came from an internal HP document that looks like it eventually got incorporated into the IPMI spec (with the names being changed along the way).

Bjorn

#13 lore raw
In reply to [email protected]
Quoted 6 lines · [email protected] wrote:

Corey,

Here is the patch (RHEL5 base code) I've been testing that detects the ACPI namespace object.
The IPI0001 device doesn't contain the register spacing directly; it has a _CRS resource object that
(for KCS) has two I/O port entries. I save the first port in io.addr_data, then calculate the register spacing based on subtracting the 2nd port address and the 1st.

This patch looks pretty good, comments inline below.

Quoted 2 lines

I'm thinking of changing the register spacing to using an array of port/memory addresses to make calculating interface addresses more generic.

Ok, I'll wait until you are sure here. The changes below are fine, they neaten things up a little. It would probably need to be a separate patch.

Quoted 22 lines

eg.
static unsigned char port_inb(struct si_sm_io *io, unsigned int offset)

{
        unsigned int addr = io->addr_data;

        return inb(addr + (offset * io->regspacing));
}

would become something like:
static unsigned char port_inb(struct si_sm_io *io, unsigned int offset)

{
        unsigned int addr = io->addr_data[offset];

        return inb(addr);
}

--jordan hargrave
Dell Enterprise Linux Engineering

ipmi_si_intf.c static __devinit void hardcode_find_bmc( · line 1391

Quoted 10 lines
ipmi_si_intf.c renamed from usr/src/redhat/BUILD/kernel-2.6.18/linux-2.6.18.x86_64/drivers/char/ipmi/ipmi_si_intf.c +10 -0
+
+static struct acpi_driver acpi_ipmi_driver = {
+  .name = ACPI_IPMI_DRIVER_NAME,
+  .class = ACPI_IPMI_CLASS,
+  .ids = ACPI_IPMI_HID,
+  .ops = {
+    .add = acpi_ipmi_add,
+    .remove = acpi_ipmi_remove,
+  },
+};

Need to fix the indention above.

Also, we need to delete the old code, I think.

ipmi_si_intf.c static __devinit void acpi_find_bmc(void · line 1700

Quoted 8 lines
ipmi_si_intf.c renamed from usr/src/redhat/BUILD/kernel-2.6.18/linux-2.6.18.x86_64/drivers/char/ipmi/ipmi_si_intf.c +3 -0
@@ -1576,6 +1694,12 @@ static __devinit void acpi_find_bmc(void
 	if (acpi_failure)
 		return;
 
+	/* Really we only need to get the IPMI device handle here */
+	acpi_bus_register_driver(&acpi_ipmi_driver);
+	acpi_bus_unregister_driver(&acpi_ipmi_driver);
 

Again, I don't know ACPI, but the above code looks rather strange.

Thanks,

-Corey

#14 lore raw

The reason for the acpi_bus_register/unregister is to get the handle of the IPMI ACPI object. There isn't a way to get the device handle otherwise. Once it gets the handle it doesn't need the ACPI device anymore. It's not the best solution, but the current way that the SI driver initializes (at least with SLES and older RHEL3/4) doesn't match up well with the way that the ACPI drivers initialize. Actually for RHEL5 I could make this cleaner, moving the try_init_acpidev code into the acpi_ipmi_add; then set a global variable to show that it initialized properly to pass back to try_init_xxxx. For older OpenIPMI driver code this doesn't mesh so well as the try_init_xxx routines take a smi_info ** argument and we can't pass this to the ACPI add routine.

--jordan hargrave
Dell Enterprise Linux Engineering

-----Original Message-----
From: Corey Minyard [mailto:[email protected]]
Sent: Wed 2/28/2007 3:42 PM
To: Hargrave, Jordan
Cc: Domsch, Matt; [email protected]; [email protected]; [email protected]; [email protected]; [email protected]
Subject: Re: [Openipmi-developer] acpi_find_bmc() and acpi_get_table()

Quoted 6 lines · [email protected] wrote:

Corey,

Here is the patch (RHEL5 base code) I've been testing that detects the ACPI namespace object.
The IPI0001 device doesn't contain the register spacing directly; it has a _CRS resource object that
(for KCS) has two I/O port entries. I save the first port in io.addr_data, then calculate the register spacing based on subtracting the 2nd port address and the 1st.

This patch looks pretty good, comments inline below.

Quoted 2 lines

I'm thinking of changing the register spacing to using an array of port/memory addresses to make calculating interface addresses more generic.

Ok, I'll wait until you are sure here. The changes below are fine, they neaten things up a little. It would probably need to be a separate patch.

Quoted 22 lines

eg.
static unsigned char port_inb(struct si_sm_io *io, unsigned int offset)

{
        unsigned int addr = io->addr_data;

        return inb(addr + (offset * io->regspacing));
}

would become something like:
static unsigned char port_inb(struct si_sm_io *io, unsigned int offset)

{
        unsigned int addr = io->addr_data[offset];

        return inb(addr);
}

--jordan hargrave
Dell Enterprise Linux Engineering

ipmi_si_intf.c static __devinit void hardcode_find_bmc( · line 1391

Quoted 10 lines
ipmi_si_intf.c renamed from usr/src/redhat/BUILD/kernel-2.6.18/linux-2.6.18.x86_64/drivers/char/ipmi/ipmi_si_intf.c +10 -0
+
+static struct acpi_driver acpi_ipmi_driver = {
+  .name = ACPI_IPMI_DRIVER_NAME,
+  .class = ACPI_IPMI_CLASS,
+  .ids = ACPI_IPMI_HID,
+  .ops = {
+    .add = acpi_ipmi_add,
+    .remove = acpi_ipmi_remove,
+  },
+};

Need to fix the indention above.

Also, we need to delete the old code, I think.

ipmi_si_intf.c static __devinit void acpi_find_bmc(void · line 1700

Quoted 8 lines
ipmi_si_intf.c renamed from usr/src/redhat/BUILD/kernel-2.6.18/linux-2.6.18.x86_64/drivers/char/ipmi/ipmi_si_intf.c +3 -0
@@ -1576,6 +1694,12 @@ static __devinit void acpi_find_bmc(void
 	if (acpi_failure)
 		return;
 
+	/* Really we only need to get the IPMI device handle here */
+	acpi_bus_register_driver(&acpi_ipmi_driver);
+	acpi_bus_unregister_driver(&acpi_ipmi_driver);
 

Again, I don't know ACPI, but the above code looks rather strange.

Thanks,

-Corey

#15 lore raw
Quoted 4 lines · On Wednesday 28 February 2007 15:05, [email protected] wrote:

The reason for the acpi_bus_register/unregister is to get the handle of the IPMI ACPI object. There isn't a way to get the device handle otherwise. Once it gets the handle it doesn't need the ACPI device anymore.

Well, but in a world of truth and beauty, we should treat the interface as an ACPI device, and we really should only be using it after acpi_ipmi_add() and before acpi_ipmi_remove(). So that implies that we shouldn't call acpi_bus_unregister_driver() until we're ready to unload the driver.

I have no idea how multiple IPMI devices should be handled. But some HP systems have several, and I think they can be hot-added and removed.

Bjorn

#16 lore raw
Quoted 8 lines · Bjorn Helgaas
Quoted 5 lines · On Wednesday 28 February 2007 15:05, [email protected] wrote:

The reason for the acpi_bus_register/unregister is to get the handle of the IPMI ACPI object. There isn't a way to get the device handle otherwise. Once it gets the handle it doesn't need the ACPI device anymore.

Quoted 6 lines

Well, but in a world of truth and beauty, we should treat the interface as an ACPI device, and we really should only be using it after acpi_ipmi_add() and before acpi_ipmi_remove(). So that implies that we shouldn't call acpi_bus_unregister_driver() until we're ready to unload the driver.

yes, that sounds more reasonable to me.

Quoted 3 lines

I have no idea how multiple IPMI devices should be handled. But some HP systems have several, and I think they can be hot-added and removed.

The current IPMI driver can actually do hot add and remove, so if the low-level ACPI code does the add/remove, it will automagically work. I'd like to know how well that worked :).

-Corey

#17 lore raw
In reply to [email protected]
Quoted 3 lines · On Monday 26 February 2007 11:30, [email protected] wrote:

Here is the patch (RHEL5 base code) I've been testing that detects the ACPI namespace object.
The IPI0001 device doesn't contain the register spacing directly; it has a _CRS resource object that
(for KCS) has two I/O port entries. I save the first port in io.addr_data, then calculate the register spacing based on subtracting the 2nd port address and the 1st.

Whatever happened with this patch? I think we should pursue it, but I don't see it in -mm.

Bjorn

#18 lore raw
Quoted 7 lines · Bjorn Helgaas
Quoted 4 lines · On Monday 26 February 2007 11:30, [email protected] wrote:

Here is the patch (RHEL5 base code) I've been testing that detects the ACPI namespace object.
The IPI0001 device doesn't contain the register spacing directly; it has a _CRS resource object that
(for KCS) has two I/O port entries. I save the first port in io.addr_data, then calculate the register spacing based on subtracting the 2nd port address and the 1st.

Quoted 5 lines

Whatever happened with this patch? I think we should pursue it, but I don't see it in -mm.

Bjorn

Sorry, I was under the impression that more work was required here dealing with the irqs. Is that not the case?

-corey

-------------------------------------------------------------------------
This SF.net email is sponsored by DB2 Express
Download DB2 Express C - the FREE version of DB2 express and take control of your XML. No limits. Just data. Click to get it now.
http://sourceforge.net/powerbar/db2/

#19 lore raw
Quoted 8 lines · Corey Minyard
Quoted 7 lines · Bjorn Helgaas
Quoted 4 lines · On Monday 26 February 2007 11:30, [email protected] wrote:

Here is the patch (RHEL5 base code) I've been testing that detects the ACPI namespace object.
The IPI0001 device doesn't contain the register spacing directly; it has a _CRS resource object that
(for KCS) has two I/O port entries. I save the first port in io.addr_data, then calculate the register spacing based on subtracting the 2nd port address and the 1st.

Quoted 7 lines
Quoted 5 lines

Whatever happened with this patch? I think we should pursue it, but I don't see it in -mm.

Bjorn

Sorry, I was under the impression that more work was required here dealing with the irqs. Is that not the case?

I think there was a little more work required. I just didn't want it to be dropped altogether.

#20 lore raw
In reply to [email protected]

I've done some more investigating on this and found why this works in RHEL5 but not other releases (RHEL4/SLES9/SLES10).

The acpi motherboard driver is claiming all devices with _HID or _CID of PNP0C01. Our BIOS declares the IPI0001 with a _CID of PNP0C01, so the acpi motherboard driver normally claims it. When the IPMI driver loads it can't find the IPI0001 device as it is already claimed.

In RHEL5 there was a change made to the acpi motherboard driver to not attach if any of the _CRS values are not I/O ports. Well, the end-of-list (79 00) marker is passed into the _CRS iterator, so the acpi motherboard driver is not attaching for ANY PNP0C01 devices. This is why the IPI0001 driver is allowed to attach in RHEL5 but none of the other OS's.

Technically the only reason it is working in RHEL5 is due to the bug of the motherboard driver not attaching.

So using acpi_bus_register_driver looks like it won't work as a general solution. I'm investigating walking the whole namespace to detect the IPI0001 device.

--jordan hargrave
Dell Enterprise Linux Engineering

-----Original Message-----
From: Hargrave, Jordan
Sent: Mon 2/26/2007 12:30 PM
To: Matt Domsch; Corey Minyard
Cc: Alexey Starikovskiy; [email protected]; openipmi; Len Brown; Bjorn Helgaas
Subject: RE: [Openipmi-developer] acpi_find_bmc() and acpi_get_table()

Corey,

Here is the patch (RHEL5 base code) I've been testing that detects the ACPI namespace object.
The IPI0001 device doesn't contain the register spacing directly; it has a _CRS resource object that
(for KCS) has two I/O port entries. I save the first port in io.addr_data, then calculate the register spacing based on subtracting the 2nd port address and the 1st.

I'm thinking of changing the register spacing to using an array of port/memory addresses to make calculating interface addresses more generic.

eg.
static unsigned char port_inb(struct si_sm_io *io, unsigned int offset)

{
        unsigned int addr = io->addr_data;

        return inb(addr + (offset * io->regspacing));
}

would become something like:
static unsigned char port_inb(struct si_sm_io *io, unsigned int offset)

{
        unsigned int addr = io->addr_data[offset];

        return inb(addr);
}

--jordan hargrave
Dell Enterprise Linux Engineering

-----Original Message-----
From: Matt Domsch [mailto:[email protected]]
Sent: Sun 2/25/2007 3:59 PM
To: Corey Minyard; Hargrave, Jordan
Cc: Alexey Starikovskiy; [email protected]; openipmi; Len Brown; Bjorn Helgaas
Subject: Re: [Openipmi-developer] acpi_find_bmc() and acpi_get_table()

Quoted 33 lines · Corey Minyard
Quoted 29 lines · Alexey Starikovskiy
Quoted 21 lines · Bjorn Helgaas
Quoted 9 lines · Corey Minyard
Quoted 7 lines · Bjorn Helgaas
Quoted 5 lines · Len Brown

acpi_find_bmc() appears to be searching for multiple SPMI tables in the RSDT and running
try_init_acpi() on each of them
until it doesn't find any more.

Quoted 9 lines
Quoted 5 lines

I can't remember why we look at the SPMI table(s) rather than registering a normal ACPI (or even PNP) driver. Unless we need to poke the BMC very early, wouldn't it be better to rely on the device description in the namespace?

For some strange reason the normal ACPI information does not have all the information needed by the driver. It doesn't have register size or spacing information.

Quoted 7 lines

I guess that would be a defect in the way ACPI is being used, wouldn't it? A PNP ID should define the device programming model, including things like register size and spacing. It sounds like somebody didn't define a new PNP ID when he should have. I wonder whether it's worth trying to fix this.

Quoted 3 lines

Yes, it is considered an ACPI fault. Could you please describe in detail, which registers miss the information? And probably your acpidump will help as well.

Quoted 6 lines

I don't have a machine with an ACPI description of the BMC. I'll copy the mailing list to see if anyone has an ACPI-described BMC.

I don't know that much about ACPI, so maybe that information is described somehow in a way the IPMI spec doesn't talk about directly, like in the _CRS object.

Let me copy my teammate Jordan Hargrave in on this, as he's been working with our BIOS team to implement discovery through an IPI0 object in the namespace, and thinks he can derive the register spacing and interrupt assignment (if any).

Signature · 4 lines
Matt Domsch
Software Architect
Dell Linux Solutions linux.dell.com & www.dell.com/linux
Linux on Dell mailing lists @ http://lists.us.dell.com
#21 lore raw
Quoted 8 lines · On Wednesday 18 July 2007 10:49:58 am [email protected] wrote:

I've done some more investigating on this and found why this works in RHEL5 but not other releases (RHEL4/SLES9/SLES10).

The acpi motherboard driver is claiming all devices with _HID or _CID of PNP0C01. Our BIOS declares the IPI0001 with a _CID of PNP0C01, so the acpi motherboard driver normally claims it. When the IPMI driver loads it can't find the IPI0001 device as it is already claimed.

I think this is dumb. PNP0C01 is a generic "system board" identifier with no clear programming model that I can see. What good does it do to have a _CID of PNP0C01? The only useful thing that happens in Linux is that the "motherboard" driver claims PNP0C01 devices and reserves their resources. But PNP ought to reserve the resources of *all* active devices, even if no driver claims them.

So I think this sounds like a BIOS defect. Of course, I'm sure it's already in the field, so even if we agree that it's a BIOS problem, we'd have to work around it in Linux. What if we had some sort of quirk that removes that _CID?

Quoted 2 lines

In RHEL5 there was a change made to the acpi motherboard driver to not attach if any of the _CRS values are not I/O ports.

Yes. This is part of linux-2.6-x86_64-memory-hotplug.patch, and it apparently helps fix a bug:
https://bugzilla.redhat.com/bugzilla/show_bug.cgi?id=208445,
But I can't read the bugzilla, so I don't know exactly how. I suspect some hot-addable memory device also had a _CID of PNP0C01, and they had the same problem you now have with IPMI.

But making the motherboard driver ignore devices if they have any non-I/O port resources seems like the wrong fix.

Quoted 2 lines

Technically the only reason it is working in RHEL5 is due to the bug of the motherboard driver not attaching.

Right. I'm sure you've noticed that the ACPI motherboard driver has been removed completely upstream. It's been replaced by the PNP "system" driver, which claims all PNP0C01 and PNP0C02 devices regardless of what sort of resources they have.

Quoted 2 lines

So using acpi_bus_register_driver looks like it won't work as a general solution. I'm investigating walking the whole namespace to detect the IPI0001 device.

I think we should make acpi_bus_register_driver() work. It looks like we already have two cases (IPMI and memory hotplug), so I'd like to have a general solution rather than a collection of workarounds.

Bjorn

-------------------------------------------------------------------------
This SF.net email is sponsored by DB2 Express
Download DB2 Express C - the FREE version of DB2 express and take control of your XML. No limits. Just data. Click to get it now.
http://sourceforge.net/powerbar/db2/

#22 lore raw
Quoted 11 lines

From Bjorn:

Quoted 2 lines

In RHEL5 there was a change made to the acpi motherboard driver to not attach if any of the _CRS values are not I/O ports.

Yes. This is part of linux-2.6-x86_64-memory-hotplug.patch, and it apparently helps fix a bug:
https://bugzilla.redhat.com/bugzilla/show_bug.cgi?id=208445,
But I can't read the bugzilla, so I don't know exactly how. I suspect some hot-addable memory device also had a _CID of PNP0C01, and they had the same problem you now have with IPMI.

Quoted 2 lines

But making the motherboard driver ignore devices if they have any non-I/O port resources seems like the wrong fix.

Yeah but it gets even better, that bugfix has a bug itself.. the acpi_walk_resources function also passes the end-of-list (79 00) marker into the callback. This isn't a resource I/O type, so the motherboard object is failing to attach to any PNP0C01 device. This is why the IPMI driver can find the IPI0001 device on RHEL5 but not on RHEL4/SLES10/SLES9.

--jordan hargrave
Dell Enterprise Linux Engineering

-----Original Message-----
From: Bjorn Helgaas [mailto:[email protected]]
Sent: Wed 7/18/2007 2:19 PM
To: Hargrave, Jordan
Cc: Domsch, Matt; [email protected]; [email protected]; [email protected]; [email protected]; [email protected]
Subject: Re: [Openipmi-developer] acpi_find_bmc() and acpi_get_table()

Quoted 8 lines · On Wednesday 18 July 2007 10:49:58 am [email protected] wrote:

I've done some more investigating on this and found why this works in RHEL5 but not other releases (RHEL4/SLES9/SLES10).

The acpi motherboard driver is claiming all devices with _HID or _CID of PNP0C01. Our BIOS declares the IPI0001 with a _CID of PNP0C01, so the acpi motherboard driver normally claims it. When the IPMI driver loads it can't find the IPI0001 device as it is already claimed.

I think this is dumb. PNP0C01 is a generic "system board" identifier with no clear programming model that I can see. What good does it do to have a _CID of PNP0C01? The only useful thing that happens in Linux is that the "motherboard" driver claims PNP0C01 devices and reserves their resources. But PNP ought to reserve the resources of *all* active devices, even if no driver claims them.

So I think this sounds like a BIOS defect. Of course, I'm sure it's already in the field, so even if we agree that it's a BIOS problem, we'd have to work around it in Linux. What if we had some sort of quirk that removes that _CID?

Quoted 2 lines

In RHEL5 there was a change made to the acpi motherboard driver to not attach if any of the _CRS values are not I/O ports.

Yes. This is part of linux-2.6-x86_64-memory-hotplug.patch, and it apparently helps fix a bug:
https://bugzilla.redhat.com/bugzilla/show_bug.cgi?id=208445,
But I can't read the bugzilla, so I don't know exactly how. I suspect some hot-addable memory device also had a _CID of PNP0C01, and they had the same problem you now have with IPMI.

But making the motherboard driver ignore devices if they have any non-I/O port resources seems like the wrong fix.

Quoted 2 lines

Technically the only reason it is working in RHEL5 is due to the bug of the motherboard driver not attaching.

Right. I'm sure you've noticed that the ACPI motherboard driver has been removed completely upstream. It's been replaced by the PNP "system" driver, which claims all PNP0C01 and PNP0C02 devices regardless of what sort of resources they have.

Quoted 2 lines

So using acpi_bus_register_driver looks like it won't work as a general solution. I'm investigating walking the whole namespace to detect the IPI0001 device.

I think we should make acpi_bus_register_driver() work. It looks like we already have two cases (IPMI and memory hotplug), so I'd like to have a general solution rather than a collection of workarounds.

Bjorn

#23 lore raw
Quoted 11 lines · On Thursday 19 July 2007 10:32:11 am [email protected] wrote:

From Bjorn:

Quoted 9 lines
Quoted 2 lines

In RHEL5 there was a change made to the acpi motherboard driver to not attach if any of the _CRS values are not I/O ports.

Yes. This is part of linux-2.6-x86_64-memory-hotplug.patch, and it apparently helps fix a bug:
https://bugzilla.redhat.com/bugzilla/show_bug.cgi?id=208445,
But I can't read the bugzilla, so I don't know exactly how. I suspect some hot-addable memory device also had a _CID of PNP0C01, and they had the same problem you now have with IPMI.

Quoted 8 lines
Quoted 2 lines

But making the motherboard driver ignore devices if they have any non-I/O port resources seems like the wrong fix.

Yeah but it gets even better, that bugfix has a bug itself.. the acpi_walk_resources function also passes the end-of-list (79 00) marker into the callback. This isn't a resource I/O type, so the motherboard object is failing to attach to any PNP0C01 device. This is why the IPMI driver can find the IPI0001 device on RHEL5 but not on RHEL4/SLES10/SLES9.

Beginning with 2.6.16, acpi_walk_resources() passes the end tag to the callback. We had a little discussion about this in January, 2006:
http://www.mail-archive.com/linux-acpi%40vger.kernel.org/msg00117.html

The conclusion was that the callback must be able to handle any resource type (ignoring ones it doesn't know about), so it should be harmless and potentially useful to pass the end tag to the callback.

RHEL4/SLES10/SLES9 do this correctly (they ignore unknown resource types and claim PNP0C01 devices, which prevents the IPMI driver from claiming IPI0001 devices that have PNP0C01 _CIDs). RHEL5 is broken (bombs out on unknown resource types and fails to claim PNP0C01 devices, which happens to make the IPMI driver claim work).

Bjorn

-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft Defy all challenges. Microsoft(R) Visual Studio 2005.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/

#25 lore raw
In reply to Bjorn Helgaas

I"m not sure how close we are on this, but I'm getting ready to release the 2.6.22 version of the driver, and I'd really like to get this in for testing if possible. Jordan, do you have any idea on how long it will be before this is resolved?

-corey

Quoted 54 lines · Bjorn Helgaas
Quoted 9 lines · On Wednesday 18 July 2007 10:49:58 am [email protected] wrote:

I've done some more investigating on this and found why this works in RHEL5 but not other releases (RHEL4/SLES9/SLES10).

The acpi motherboard driver is claiming all devices with _HID or _CID of PNP0C01. Our BIOS declares the IPI0001 with a _CID of PNP0C01, so the acpi motherboard driver normally claims it. When the IPMI driver loads it can't find the IPI0001 device as it is already claimed.

I think this is dumb. PNP0C01 is a generic "system board" identifier with no clear programming model that I can see. What good does it do to have a _CID of PNP0C01? The only useful thing that happens in Linux is that the "motherboard" driver claims PNP0C01 devices and reserves their resources. But PNP ought to reserve the resources of *all* active devices, even if no driver claims them.

So I think this sounds like a BIOS defect. Of course, I'm sure it's already in the field, so even if we agree that it's a BIOS problem, we'd have to work around it in Linux. What if we had some sort of quirk that removes that _CID?

Quoted 3 lines

In RHEL5 there was a change made to the acpi motherboard driver to not attach if any of the _CRS values are not I/O ports.

Yes. This is part of linux-2.6-x86_64-memory-hotplug.patch, and it apparently helps fix a bug:
https://bugzilla.redhat.com/bugzilla/show_bug.cgi?id=208445,
But I can't read the bugzilla, so I don't know exactly how. I suspect some hot-addable memory device also had a _CID of PNP0C01, and they had the same problem you now have with IPMI.

But making the motherboard driver ignore devices if they have any non-I/O port resources seems like the wrong fix.

Quoted 3 lines

Technically the only reason it is working in RHEL5 is due to the bug of the motherboard driver not attaching.

Right. I'm sure you've noticed that the ACPI motherboard driver has been removed completely upstream. It's been replaced by the PNP "system" driver, which claims all PNP0C01 and PNP0C02 devices regardless of what sort of resources they have.

Quoted 3 lines

So using acpi_bus_register_driver looks like it won't work as a general solution. I'm investigating walking the whole namespace to detect the IPI0001 device.

Quoted 6 lines

I think we should make acpi_bus_register_driver() work. It looks like we already have two cases (IPMI and memory hotplug), so I'd like to have a general solution rather than a collection of workarounds.

Bjorn

-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft Defy all challenges. Microsoft(R) Visual Studio 2005.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/

#24 lore raw
In reply to [email protected]
Quoted 11 lines · On Thursday 19 July 2007 10:32:11 am [email protected] wrote:

From Bjorn:

Quoted 9 lines
Quoted 2 lines

In RHEL5 there was a change made to the acpi motherboard driver to not attach if any of the _CRS values are not I/O ports.

Yes. This is part of linux-2.6-x86_64-memory-hotplug.patch, and it apparently helps fix a bug:
https://bugzilla.redhat.com/bugzilla/show_bug.cgi?id=208445,
But I can't read the bugzilla, so I don't know exactly how. I suspect some hot-addable memory device also had a _CID of PNP0C01, and they had the same problem you now have with IPMI.

Quoted 8 lines
Quoted 2 lines

But making the motherboard driver ignore devices if they have any non-I/O port resources seems like the wrong fix.

Yeah but it gets even better, that bugfix has a bug itself.. the acpi_walk_resources function also passes the end-of-list (79 00) marker into the callback. This isn't a resource I/O type, so the motherboard object is failing to attach to any PNP0C01 device. This is why the IPMI driver can find the IPI0001 device on RHEL5 but not on RHEL4/SLES10/SLES9.

Hi Jordan,

This is ancient history now. But I've been doing some PNP work recently, and I'd like to resurrect your work towards making the IPMI driver a real PNP driver rather than relying on the static SPMI table as it does today.

What's the current status of your work? If you don't want to continue it yourself, I'd like to pick it up (unless there's some show-stopper reason why it can't ever work, of course). Do you have any work-in-progress that you could post?

Thanks,
Bjorn