pmi: initial version
cover pmi: initial version
This patch adds a driver for the=20
"Platform Management Interrupt" interface.
PMI is basically yet another way to communicate with the BMC. It provides small latency and thus can be used=20 to request frequency changes from the BMC.
PMI allows bidirectional communication.=20
The cpufreq driver can be notified about a new limit for=20 frequency changes for instance.
PMI can be found on future IBM products.
--=20
Mit freundlichen Gr=FCssen,
kind regards,
Christian Krafft
IBM Systems & Technology Group,=20
Linux Kernel Development
IT Specialist
This patch adds driver code for the PMI device found in future IBM products. PMI stands for "Platform Management Interrupt" and is a way to communicate with the BMC. It provides bidirectional communication with a low latency.
arch/powerpc/Kconfig +9 -0
@@ -524,6 +524,7 @@ config PPC_IBM_CELL_BLADE select MMIO_NVRAM select PPC_UDBG_16550 select UDBG_RTAS_CONSOLE +# select PPC_PMI config PPC_PS3 bool "Sony PS3 (incomplete)"
@@ -577,6 +578,14 @@ config RTAS_FLASH tristate "Firmware flash interface" depends on PPC64 && RTAS_PROC +config PPC_PMI + tristate "Support for PMI" + depends PPC_IBM_CELL_BLADE + help + PMI is a way to communicate with the board mangement controller. + It is used in some IBM Cell blades. + default m + config MMIO_NVRAM bool default n
arch/powerpc/sysdev/Makefile +1 -0
@@ -7,6 +7,7 @@ obj-$(CONFIG_PPC_INDIRECT_PCI) += indire obj-$(CONFIG_PPC_MPC106) += grackle.o obj-$(CONFIG_PPC_DCR) += dcr.o obj-$(CONFIG_PPC_DCR_NATIVE) += dcr-low.o +obj-$(CONFIG_PPC_PMI) += pmi.o obj-$(CONFIG_U3_DART) += dart_iommu.o obj-$(CONFIG_MMIO_NVRAM) += mmio_nvram.o obj-$(CONFIG_FSL_SOC) += fsl_soc.o
arch/powerpc/sysdev/pmi.c new file +275 -0
275 lines not on this page · raw message
include/asm-powerpc/pmi.h new file +63 -0
63 lines not on this page · raw message
Hi Christian-
Some minor comments.
Quoted 11 lines · Christian Krafft
This patch adds driver code for the PMI device found in future IBM products. PMI stands for "Platform Management Interrupt" and is a way to communicate with the BMC. It provides bidirectional communication with a low latency.
Signed-off-by Christian Krafft <[email protected]>Index: linux/arch/powerpc/Kconfig
===================================================================
arch/powerpc/Kconfig config PPC_IBM_CELL_BLADE · line 527
Quoted 4 lines
arch/powerpc/Kconfig +1
-0@@ -524,6 +524,7 @@ config PPC_IBM_CELL_BLADE select MMIO_NVRAM select PPC_UDBG_16550 select UDBG_RTAS_CONSOLE +# select PPC_PMI
Did you mean for this to be commented out?
<snip>
arch/powerpc/Kconfig config PPC_IBM_CELL_BLADE
Quoted 9 lines
arch/powerpc/Kconfig +9
-0+static void __iomem *of_iomap(struct device_node *np) +{ + struct resource res; + + if (of_address_to_resource(np, 0, &res)) + return NULL; + + pr_debug("Resource start: 0x%lx\n", res.start); + pr_debug("Resource end: 0x%lx\n", res.end);
You need a tab instead of spaces.
arch/powerpc/Kconfig
Quoted 13 lines
arch/powerpc/Kconfig +13
-0+ + return ioremap(res.start, 1 + res.end - res.start); +} + +static int pmi_irq_handler(int irq, void *dev_id) +{ + struct pmi_data *data; + int type; + struct pmi_handler *handler; + + data = dev_id; + + BUG_ON(!data);
Not necessary, you'll oops in two lines anyway if data is NULL.
Quoted 7 lines
arch/powerpc/Kconfig +7
-0+ + pr_debug("pmi: got a PMI message\n"); + + spin_lock(&data->pmi_spinlock); + type = ioread8(data->pmi_reg + PMI_READ_TYPE); + spin_unlock(&data->pmi_spinlock); +
arch/powerpc/Kconfig
Quoted 10 lines
arch/powerpc/Kconfig +10
-0+ pr_debug("pmi: message type is %d\n", type); + + if (type & PMI_ACK) { + BUG_ON(!data->msg); + BUG_ON(!data->completion); + pr_debug("pmi: got an ACK\n"); + data->msg->type = type; + data->msg->data0 = ioread8(data->pmi_reg + PMI_READ_DATA0); + data->msg->data1 = ioread8(data->pmi_reg + PMI_READ_DATA1); + data->msg->data2 = ioread8(data->pmi_reg + PMI_READ_DATA2);
Should these accesses to data->pmi_reg be performed while holding data->pmi_spinlock as well?
Quoted 29 lines
arch/powerpc/Kconfig +29
-0+ complete(data->completion); + return IRQ_HANDLED; + } + + spin_lock(&data->handler_spinlock); + list_for_each_entry(handler, &data->handler, node) { + pr_debug("pmi: notifying handlers\n"); + if (handler->type == type) { + pr_debug("pmi: notify handler %p\n", handler); + handler->handle_pmi_message(data->dev, data->msg); + } + } + spin_unlock(&data->handler_spinlock); + + return IRQ_HANDLED; +} + + +static struct of_device_id pmi_match[] = { + { .type = "ibm,pmi", .name = "pmi" }, + {}, +}; + +MODULE_DEVICE_TABLE(of, pmi_match); + +static int pmi_of_probe(struct of_device *dev, + const struct of_device_id *match) +{ + DEFINE_SPINLOCK(handler_spinlock);
arch/powerpc/Kconfig
Quoted 10 lines
arch/powerpc/Kconfig +10
-0+ DEFINE_SPINLOCK(pmi_spinlock); + + struct device_node *np = dev->node; + struct pmi_data *data; + int rc; + + data = kzalloc(sizeof(struct pmi_data), GFP_KERNEL); + if (!data) { + printk(KERN_ERR "pmi: could not allocate memory.\n"); + return -EFAULT;
-ENOMEM is the appropriate error code here.
Quoted 20 lines
arch/powerpc/Kconfig +20
-0+ } + + data->pmi_reg = of_iomap(np); + + if (!data->pmi_reg) { + printk(KERN_ERR "pmi: invalid register address.\n"); + kfree(data); + return -EFAULT; + } + + INIT_LIST_HEAD(&data->handler); + + data->irq = irq_of_parse_and_map(np, 0); + if (data->irq == NO_IRQ) { + printk(KERN_ERR "pmi: invalid interrupt.\n"); + iounmap(data->pmi_reg); + kfree(data); + return -EFAULT; + } +
arch/powerpc/Kconfig
Quoted 10 lines
arch/powerpc/Kconfig +10
-0+ data->handler_spinlock = handler_spinlock; + data->pmi_spinlock = pmi_spinlock; + + rc = request_irq(data->irq, pmi_irq_handler, + IRQF_SHARED, "pmi", data); + if (rc) { + printk(KERN_ERR "pmi: can't request IRQ %d: returned %d\n", + data->irq, rc); + iounmap(data->pmi_reg); + kfree(data);
Consider using goto to reduce duplication of the iounmap, kfree sequence.
arch/powerpc/Kconfig
Quoted 1 line
arch/powerpc/Kconfig +1
-0+ return -EFAULT;
Just return rc; request_irq returns standard error codes.
<snip>
arch/powerpc/Kconfig
Quoted 7 lines
arch/powerpc/Kconfig +7
-0+void pmi_send_message(struct of_device *device, struct pmi_message *msg) +{ + struct pmi_data *data; + unsigned long flags; + DECLARE_COMPLETION_ONSTACK(completion); + + BUG_ON(!device || !msg);
This BUG_ON is also unnecessary, and could actually make debugging more difficult since it wouldn't be immediately apparent which condition triggered it.
Quoted 29 lines
arch/powerpc/Kconfig +29
-0+ + data = device->dev.driver_data; + pr_debug("pmi_send_message: data is %p\n", data); + + mutex_lock(&data->msg_mutex); + + data->msg = msg; + + pr_debug("pmi_send_message: msg is %p\n", msg); + + data->completion = &completion; + + spin_lock_irqsave(&data->pmi_spinlock, flags); + iowrite8(msg->data0, data->pmi_reg + PMI_WRITE_DATA0); + iowrite8(msg->data1, data->pmi_reg + PMI_WRITE_DATA1); + iowrite8(msg->data2, data->pmi_reg + PMI_WRITE_DATA2); + iowrite8(msg->type, data->pmi_reg + PMI_WRITE_TYPE); + spin_unlock_irqrestore(&data->pmi_spinlock, flags); + + pr_debug(KERN_INFO "pmi_send_message: wait for completion %p\n", data->completion); + + wait_for_completion_interruptible_timeout(data->completion, PMI_TIMEOUT); + + data->msg = NULL; + data->completion = NULL; + + mutex_unlock(&data->msg_mutex); +} +EXPORT_SYMBOL_GPL(pmi_send_message);
...
Quoted 1 line
+EXPORT_SYMBOL_GPL(pmi_register_handler);
...
Quoted 1 line
+EXPORT_SYMBOL_GPL(pmi_unregister_handler);
Are the symbol exports necessary?
<snip>
arch/powerpc/Kconfig
Quoted 4 lines
arch/powerpc/Kconfig +4
-0+void pmi_register_handler(struct of_device *, struct pmi_handler *); +void pmi_unregister_handler(struct of_device *, struct pmi_handler *); + +void pmi_send_message(struct of_device *, struct pmi_message *);
Are there users of these functions?
Hi Nathan,
thanks for your comments.
Will send an updated version.
Quoted 6 lines · On Fri, 9 Feb 2007 16:29:56 -0600 Nathan Lynch <[email protected]> wrote:
Hi Christian-
=20
Some minor comments.
=20Quoted 1 line · Christian Krafft
This patch adds driver code for the PMI device found in future IBM prod=
ucts.
Quoted 1 line
Quoted 1 line
PMI stands for "Platform Management Interrupt" and is a way to communic=
ate
Quoted 1 line
Quoted 1 line
with the BMC. It provides bidirectional communication with a low latenc=
y.
Quoted 5 lines
Quoted 5 lines
=20
Signed-off-by Christian Krafft <[email protected]>=20
Index: linux/arch/powerpc/Kconfig =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
Quoted 9 lines
arch/powerpc/Kconfig config PPC_IBM_CELL_BLADE · line 527
Quoted 7 lines
arch/powerpc/Kconfig +1
-0@@ -524,6 +524,7 @@ config PPC_IBM_CELL_BLADE select MMIO_NVRAM select PPC_UDBG_16550 select UDBG_RTAS_CONSOLE +# select PPC_PMI=20
Did you mean for this to be commented out?
no, good point ;-)
Quoted 14 lines
=20
<snip>
=20arch/powerpc/Kconfig config PPC_IBM_CELL_BLADE
Quoted 9 lines
arch/powerpc/Kconfig +9
-0+static void __iomem *of_iomap(struct device_node *np) +{ + struct resource res; + + if (of_address_to_resource(np, 0, &res)) + return NULL; + + pr_debug("Resource start: 0x%lx\n", res.start); + pr_debug("Resource end: 0x%lx\n", res.end);=20
You need a tab instead of spaces.
copy and past bug,
Quoted 17 lines
=20
=20arch/powerpc/Kconfig
Quoted 13 lines
arch/powerpc/Kconfig +13
-0+ + return ioremap(res.start, 1 + res.end - res.start); +} + +static int pmi_irq_handler(int irq, void *dev_id) +{ + struct pmi_data *data; + int type; + struct pmi_handler *handler; + + data =3D dev_id; + + BUG_ON(!data);=20
Not necessary, you'll oops in two lines anyway if data is NULL.
ok,
Quoted 14 lines
=20
=20Quoted 12 lines
arch/powerpc/Kconfig +12
-0+ + pr_debug("pmi: got a PMI message\n"); + + spin_lock(&data->pmi_spinlock); + type =3D ioread8(data->pmi_reg + PMI_READ_TYPE); + spin_unlock(&data->pmi_spinlock); + + pr_debug("pmi: message type is %d\n", type); + + if (type & PMI_ACK) { + BUG_ON(!data->msg); + BUG_ON(!data->completion);
Quoted 8 lines
arch/powerpc/Kconfig
Quoted 5 lines
arch/powerpc/Kconfig +5
-0+ pr_debug("pmi: got an ACK\n"); + data->msg->type =3D type; + data->msg->data0 =3D ioread8(data->pmi_reg + PMI_READ_DATA0); + data->msg->data1 =3D ioread8(data->pmi_reg + PMI_READ_DATA1); + data->msg->data2 =3D ioread8(data->pmi_reg + PMI_READ_DATA2);=20
Should these accesses todata->pmi_regbe performed while holdingdata->pmi_spinlockas well?
yep, good catch.
Quoted 35 lines
=20
=20Quoted 33 lines
arch/powerpc/Kconfig +33
-0+ complete(data->completion); + return IRQ_HANDLED; + } + + spin_lock(&data->handler_spinlock); + list_for_each_entry(handler, &data->handler, node) { + pr_debug("pmi: notifying handlers\n"); + if (handler->type =3D=3D type) { + pr_debug("pmi: notify handler %p\n", handler); + handler->handle_pmi_message(data->dev, data->msg); + } + } + spin_unlock(&data->handler_spinlock); + + return IRQ_HANDLED; +} + + +static struct of_device_id pmi_match[] =3D { + { .type =3D "ibm,pmi", .name =3D "pmi" }, + {}, +}; + +MODULE_DEVICE_TABLE(of, pmi_match); + +static int pmi_of_probe(struct of_device *dev, + const struct of_device_id *match) +{ + DEFINE_SPINLOCK(handler_spinlock); + DEFINE_SPINLOCK(pmi_spinlock); + + struct device_node *np =3D dev->node; + struct pmi_data *data;
Quoted 8 lines
arch/powerpc/Kconfig
Quoted 6 lines
arch/powerpc/Kconfig +6
-0+ int rc; + + data =3D kzalloc(sizeof(struct pmi_data), GFP_KERNEL); + if (!data) { + printk(KERN_ERR "pmi: could not allocate memory.\n"); + return -EFAULT;=20
-ENOMEMis the appropriate error code here.
will be updated.
Quoted 35 lines
=20
=20Quoted 20 lines
arch/powerpc/Kconfig +20
-0+ } + + data->pmi_reg =3D of_iomap(np); + + if (!data->pmi_reg) { + printk(KERN_ERR "pmi: invalid register address.\n"); + kfree(data); + return -EFAULT; + } + + INIT_LIST_HEAD(&data->handler); + + data->irq =3D irq_of_parse_and_map(np, 0); + if (data->irq =3D=3D NO_IRQ) { + printk(KERN_ERR "pmi: invalid interrupt.\n"); + iounmap(data->pmi_reg); + kfree(data); + return -EFAULT; + } +arch/powerpc/Kconfig
Quoted 10 lines
arch/powerpc/Kconfig +10
-0+ data->handler_spinlock =3D handler_spinlock; + data->pmi_spinlock =3D pmi_spinlock; + + rc =3D request_irq(data->irq, pmi_irq_handler, + IRQF_SHARED, "pmi", data); + if (rc) { + printk(KERN_ERR "pmi: can't request IRQ %d: returned %d\n", + data->irq, rc); + iounmap(data->pmi_reg); + kfree(data);=20
Consider using goto to reduce duplication of the iounmap, kfree sequence. =20
Quoted 3 lines
arch/powerpc/Kconfig
Quoted 1 line
arch/powerpc/Kconfig +1
-0+ return -EFAULT;=20
Just return rc;request_irqreturns standard error codes.
ok,
Quoted 4 lines
=20
<snip>
=20Quoted 1 line
+void pmi_send_message(struct
of_device*device, structpmi_message*ms=
g)
Quoted 10 lines
arch/powerpc/Kconfig
Quoted 6 lines
arch/powerpc/Kconfig +6
-0+{ + struct pmi_data *data; + unsigned long flags; + DECLARE_COMPLETION_ONSTACK(completion); + + BUG_ON(!device || !msg);=20
ThisBUG_ONis also unnecessary, and could actually make debugging more difficult since it wouldn't be immediately apparent which condition triggered it.
right,
Quoted 13 lines
=20
Quoted 12 lines
arch/powerpc/Kconfig +12
-0+ + data =3D device->dev.driver_data; + pr_debug("pmi_send_message: data is %p\n", data); + + mutex_lock(&data->msg_mutex); + + data->msg =3D msg; + + pr_debug("pmi_send_message: msg is %p\n", msg); + + data->completion =3D &completion; +
Quoted 8 lines
arch/powerpc/Kconfig
Quoted 8 lines
arch/powerpc/Kconfig +8
-0+ spin_lock_irqsave(&data->pmi_spinlock, flags); + iowrite8(msg->data0, data->pmi_reg + PMI_WRITE_DATA0); + iowrite8(msg->data1, data->pmi_reg + PMI_WRITE_DATA1); + iowrite8(msg->data2, data->pmi_reg + PMI_WRITE_DATA2); + iowrite8(msg->type, data->pmi_reg + PMI_WRITE_TYPE); + spin_unlock_irqrestore(&data->pmi_spinlock, flags); + + pr_debug(KERN_INFO "pmi_send_message: wait for completion %p\n", data=
->completion);
Quoted 2 lines
arch/powerpc/Kconfig
Quoted 2 lines
arch/powerpc/Kconfig +2
-0+ + wait_for_completion_interruptible_timeout(data->completion, PMI_TIMEO=
UT);
Quoted 16 lines
Quoted 7 lines
arch/powerpc/Kconfig +7
-0+ + data->msg =3D NULL; + data->completion =3D NULL; + + mutex_unlock(&data->msg_mutex); +} +EXPORT_SYMBOL_GPL(pmi_send_message);...
Quoted 1 line
+EXPORT_SYMBOL_GPL(pmi_register_handler);
...
Quoted 1 line
+EXPORT_SYMBOL_GPL(pmi_unregister_handler);
=20
Are the symbol exports necessary?
=20
<snip>
=20
Quoted 7 lines
arch/powerpc/Kconfig
Quoted 4 lines
arch/powerpc/Kconfig +4
-0+void pmi_register_handler(struct of_device *, struct pmi_handler *); +void pmi_unregister_handler(struct of_device *, struct pmi_handler *); + +void pmi_send_message(struct of_device *, struct pmi_message *);=20
Are there users of these functions?
=20
yes, they will be used by the cbe_cpufreq driver.
I will send a patch for it, as soon as i was able to test it, hopefully today or tomorrow.
--=20
Mit freundlichen Gr=FCssen,
kind regards,
Christian Krafft
IBM Systems & Technology Group,=20
Linux Kernel Development
IT Specialist
Subject: powerpc: add PMI driver for cell blade
From: Christian Krafft <[email protected]>
This patch adds driver code for the PMI device found in future IBM products. PMI stands for "Platform Management Interrupt" and is a way to communicate with the BMC. It provides bidirectional communication with a low latency.
---
Index: linux/arch/powerpc/Kconfig =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
arch/powerpc/Kconfig +0 -0
@@ -577,6 +577,14 @@ config RTAS_FLASH tristate "Firmware flash interface" depends on PPC64 && RTAS_PROC
=20
+config PPC_PMI
+ tristate "Support for PMI"
+ depends PPC_IBM_CELL_BLADE
+ help
+ PMI is a way to communicate with the board mangement controller.
+ It is used in some IBM Cell blades.
+ default m
+
config MMIO_NVRAM
bool
default n
Index: linux/arch/powerpc/sysdev/Makefile =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
arch/powerpc/sysdev/Makefile +1 -0
@@ -7,6 +7,7 @@ obj-$(CONFIG_PPC_INDIRECT_PCI) +=3D indire obj-$(CONFIG_PPC_MPC106) +=3D grackle.o obj-$(CONFIG_PPC_DCR) +=3D dcr.o obj-$(CONFIG_PPC_DCR_NATIVE) +=3D dcr-low.o +obj-$(CONFIG_PPC_PMI) +=3D pmi.o obj-$(CONFIG_U3_DART) +=3D dart_iommu.o obj-$(CONFIG_MMIO_NVRAM) +=3D mmio_nvram.o obj-$(CONFIG_FSL_SOC) +=3D fsl_soc.o
Index: linux/arch/powerpc/sysdev/pmi.c =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
arch/powerpc/sysdev/pmi.c new file +291 -0
291 lines not on this page · raw message
Index: linux/include/asm-powerpc/pmi.h =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
include/asm-powerpc/pmi.h new file +63 -0
63 lines not on this page · raw message
Index: linux/arch/powerpc/configs/cell_defconfig =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
arch/powerpc/configs/cell_defconfig +1 -0
@@ -147,6 +147,7 @@ CONFIG_PPC_RTAS=3Dy # CONFIG_RTAS_ERROR_LOGGING is not set CONFIG_RTAS_PROC=3Dy CONFIG_RTAS_FLASH=3Dy +CONFIG_PPC_PMI=3Dm CONFIG_MMIO_NVRAM=3Dy # CONFIG_PPC_MPC106 is not set # CONFIG_PPC_970_NAP is not set
--=20
Mit freundlichen Gr=FCssen,
kind regards,
Christian Krafft
IBM Systems & Technology Group,=20
Linux Kernel Development
IT Specialist
Hi,
sorry for resending this patch again.
I added a work queue to the interrupt handler to shorten the time we run with interrupts off.
Cheers,
ck
Re: [Cbe-oss-dev] [patch v3] powerpc: add PMI driver for cell blade
Subject: powerpc: add PMI driver for cell blade
From: Christian Krafft <[email protected]>
This patch adds driver code for the PMI device found in future IBM products. PMI stands for "Platform Management Interrupt" and is a way to communicate with the BMC. It provides bidirectional communication with a low latency.
---
arch/powerpc/Kconfig +8 -0
@@ -577,6 +577,14 @@ config RTAS_FLASH tristate "Firmware flash interface" depends on PPC64 && RTAS_PROC +config PPC_PMI + tristate "Support for PMI" + depends PPC_IBM_CELL_BLADE + help + PMI is a way to communicate with the board mangement controller. + It is used in some IBM Cell blades. + default m + config MMIO_NVRAM bool default n
arch/powerpc/sysdev/Makefile +1 -0
@@ -7,6 +7,7 @@ obj-$(CONFIG_PPC_INDIRECT_PCI) += indire obj-$(CONFIG_PPC_MPC106) += grackle.o obj-$(CONFIG_PPC_DCR) += dcr.o obj-$(CONFIG_PPC_DCR_NATIVE) += dcr-low.o +obj-$(CONFIG_PPC_PMI) += pmi.o obj-$(CONFIG_U3_DART) += dart_iommu.o obj-$(CONFIG_MMIO_NVRAM) += mmio_nvram.o obj-$(CONFIG_FSL_SOC) += fsl_soc.o
arch/powerpc/sysdev/pmi.c new file +312 -0
312 lines not on this page · raw message
include/asm-powerpc/pmi.h new file +63 -0
63 lines not on this page · raw message
arch/powerpc/configs/cell_defconfig +1 -0
@@ -147,6 +147,7 @@ CONFIG_PPC_RTAS=y # CONFIG_RTAS_ERROR_LOGGING is not set CONFIG_RTAS_PROC=y CONFIG_RTAS_FLASH=y +CONFIG_PPC_PMI=m CONFIG_MMIO_NVRAM=y # CONFIG_PPC_MPC106 is not set # CONFIG_PPC_970_NAP is not set
Re: [Cbe-oss-dev] [patch v3] powerpc: add PMI driver for cell blade
arch/powerpc/sysdev/pmi.c line 171
Quoted 4 lines · On Tue, 13 Feb 2007 19:48:06 +0100 Christian Krafft <[email protected]> wrote:
arch/powerpc/sysdev/pmi.c new file +4
-0+ + data->work_queue =3D create_workqueue("pmi"); +INIT_WORK (&data->work, pmi_notify_handlers); +
That's not what I wanted!
Will send an update.
--=20
Mit freundlichen Gr=FCssen,
kind regards,
Christian Krafft
IBM Systems & Technology Group,=20
Linux Kernel Development
IT Specialist
Re: [Cbe-oss-dev] [patch v3] powerpc: add PMI driver for cell blade
In reply to Christian KrafftSubject: powerpc: add PMI driver for cell blade
From: Christian Krafft <[email protected]>
This patch adds driver code for the PMI device found in future IBM products. PMI stands for "Platform Management Interrupt" and is a way to communicate with the BMC. It provides bidirectional communication with a low latency.
---
arch/powerpc/Kconfig +8 -0
@@ -577,6 +577,14 @@ config RTAS_FLASH tristate "Firmware flash interface" depends on PPC64 && RTAS_PROC +config PPC_PMI + tristate "Support for PMI" + depends PPC_IBM_CELL_BLADE + help + PMI is a way to communicate with the board mangement controller. + It is used in some IBM Cell blades. + default m + config MMIO_NVRAM bool default n
arch/powerpc/sysdev/Makefile +1 -0
@@ -7,6 +7,7 @@ obj-$(CONFIG_PPC_INDIRECT_PCI) += indire obj-$(CONFIG_PPC_MPC106) += grackle.o obj-$(CONFIG_PPC_DCR) += dcr.o obj-$(CONFIG_PPC_DCR_NATIVE) += dcr-low.o +obj-$(CONFIG_PPC_PMI) += pmi.o obj-$(CONFIG_U3_DART) += dart_iommu.o obj-$(CONFIG_MMIO_NVRAM) += mmio_nvram.o obj-$(CONFIG_FSL_SOC) += fsl_soc.o
arch/powerpc/sysdev/pmi.c new file +307 -0
307 lines not on this page · raw message
include/asm-powerpc/pmi.h new file +63 -0
63 lines not on this page · raw message
arch/powerpc/configs/cell_defconfig +1 -0
@@ -147,6 +147,7 @@ CONFIG_PPC_RTAS=y # CONFIG_RTAS_ERROR_LOGGING is not set CONFIG_RTAS_PROC=y CONFIG_RTAS_FLASH=y +CONFIG_PPC_PMI=m CONFIG_MMIO_NVRAM=y # CONFIG_PPC_MPC106 is not set # CONFIG_PPC_970_NAP is not set
Re: [Cbe-oss-dev] [patch v3] powerpc: add PMI driver for cell blade
Quoted 4 lines · Christian Krafft
From: Christian Krafft <[email protected]>
This patch adds driver code for the PMI device found in future IBM products. PMI stands for "Platform Management Interrupt" and is a way to communicate with the BMC. It provides bidirectional communication with a low latency.
Thanks for telling us what PMI is, but what's a BMC?
Paul.
Re: [Cbe-oss-dev] [patch v3] powerpc: add PMI driver for cell blade
Quoted 4 lines · On Wed, 14 Feb 2007 11:30:51 +1100 Paul Mackerras <[email protected]> wrote:
Christian Krafft writes:
=20Quoted 2 lines
From: Christian Krafft <[email protected]>
This patch adds driver code for the PMI device found in future IBM prod=
ucts.
Quoted 1 line
Quoted 1 line
PMI stands for "Platform Management Interrupt" and is a way to communic=
ate
Quoted 1 line
Quoted 1 line
with the BMC. It provides bidirectional communication with a low latenc=
y.
Quoted 4 lines
=20
Thanks for telling us what PMI is, but what's a BMC? =20
Paul.
BMC stands for Baseboard Management Controller:
http://en.wikipedia.org/wiki/Baseboard_management_controller
--=20
Mit freundlichen Gr=FCssen,
kind regards,
Christian Krafft
IBM Systems & Technology Group,=20
Linux Kernel Development
IT Specialist
Re: [Cbe-oss-dev] [patch v3] powerpc: add PMI driver for cell blade
Quoted 2 lines · Christian Krafft
BMC stands for Baseboard Management Controller:
http://en.wikipedia.org/wiki/Baseboard_management_controller
Thanks.
I was actually hinting that it would be good to explain that acronym as well as PMI in the description of the patch. I should have said so explicitly.
Paul.
Re: [Cbe-oss-dev] [patch v3] powerpc: add PMI driver for cell blade
Quoted 4 lines · On Wed, 14 Feb 2007 21:22:16 +1100 Paul Mackerras <[email protected]> wrote:
Christian Krafft writes:
=20Quoted 2 lines
BMC stands for Baseboard Management Controller:
http://en.wikipedia.org/wiki/Baseboard_management_controller
Quoted 8 lines
=20
Thanks.
=20
I was actually hinting that it would be good to explain that acronym as well as PMI in the description of the patch. I should have said so explicitly.
=20
Paul.
No need to, I also don't like TLA's ;-)
Will send an update.=20
--=20
Mit freundlichen Gr=FCssen,
kind regards,
Christian Krafft
IBM Systems & Technology Group,=20
Linux Kernel Development
IT Specialist
Re: [Cbe-oss-dev] [patch v3] powerpc: add PMI driver for cell blade
Subject: powerpc: add PMI driver for cell blade
From: Christian Krafft <[email protected]>
This patch adds driver code for the PMI device found in future IBM products. PMI stands for "Platform Management Interrupt" and is a way to communicate with the BMC (Baseboard Management Controller).
It provides bidirectional communication with a low latency.
---
arch/powerpc/sysdev/pmi.c new file +305 -0
@@ -0,0 +1,305 @@ +/* +* pmi driver +* +* (C) Copyright IBM Deutschland Entwicklung GmbH 2005 +* +* PMI (Platform Management Interrupt) is a way to communicate +* with the BMC (Baseboard Management Controller) via interrupts. +* Unlike IPMI it is bidirectional and has a low latency. +* +* Author: Christian Krafft <[email protected]> +* +* 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, 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., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include <linux/interrupt.h> +#include <linux/completion.h> +#include <linux/spinlock.h> +#include <linux/workqueue.h> + +#include <asm/of_device.h> +#include <asm/of_platform.h> +#include <asm/io.h> +#include <asm/pmi.h> + + +struct pmi_data { +struct list_head handler; +spinlock_t handler_spinlock; +spinlock_t pmi_spinlock; +struct mutex msg_mutex; +pmi_message_t msg; +struct completion *completion; +struct of_device *dev; +int irq; +u8 __iomem *pmi_reg; +struct work_struct work; +}; + + + +static void __iomem *of_iomap (struct device_node *np) +{ +struct resource res; + +if (of_address_to_resource (np,0 , &res)) +return NULL ; + +pr_debug ("Resource start: 0x%lx\n" , res.start); +pr_debug ("Resource end: 0x%lx\n" , res.end); + +return ioremap (res.start,1 + res.end - res.start); +} + + +static int pmi_irq_handler (int irq,void *dev_id) +{ +struct pmi_data *data; +u8 type; +int rc; + + data = dev_id; + +spin_lock (&data->pmi_spinlock); + + type =ioread8 (data->pmi_reg +PMI_READ_TYPE ); +pr_debug ("pmi: got message of type %d\n" , type); + +if (type &PMI_ACK && !data->completion) { +printk (KERN_WARNING "pmi: got unexpected ACK message.\n" ); + rc = -EIO ; + goto unlock; + } + +if (data->completion && !(type &PMI_ACK )) { +printk (KERN_WARNING "pmi: expected ACK, but got %d\n" , type); + rc = -EIO ; + goto unlock; + } + + data->msg.type = type; + data->msg.data0 =ioread8 (data->pmi_reg +PMI_READ_DATA0 ); + data->msg.data1 =ioread8 (data->pmi_reg +PMI_READ_DATA1 ); + data->msg.data2 =ioread8 (data->pmi_reg +PMI_READ_DATA2 ); + rc =0 ; +unlock: +spin_unlock (&data->pmi_spinlock); + +if (rc == -EIO ) { + rc =IRQ_HANDLED ; + goto out; + } + +if (data->msg.type &PMI_ACK ) { +complete (data->completion); + rc =IRQ_HANDLED ; + goto out; + } + +schedule_work (&data->work); + + rc =IRQ_HANDLED ; +out: +return rc; +} + + +static struct of_device_id pmi_match[] = { + { .type ="ibm,pmi" , .name ="ibm,pmi" }, + {}, +}; + +MODULE_DEVICE_TABLE (of, pmi_match); + +static void pmi_notify_handlers (struct work_struct *work) +{ +struct pmi_data *data; +struct pmi_handler *handler; + + data = container_of(work, struct pmi_data, work); + +spin_lock (&data->handler_spinlock); +list_for_each_entry (handler, &data->handler, node) { +pr_debug (KERN_INFO "pmi: notifying handler %p\n" , handler); +if (handler->type == data->msg.type) + handler->handle_pmi_message (data->dev, data->msg); + } +spin_unlock (&data->handler_spinlock); +} + +static int pmi_of_probe (struct of_device *dev, +const struct of_device_id *match) +{ +struct device_node *np = dev->node; +struct pmi_data *data; +int rc; + + data =kzalloc (sizeof (struct pmi_data ),GFP_KERNEL ); +if (!data) { +printk (KERN_ERR "pmi: could not allocate memory.\n" ); + rc = -ENOMEM ; + goto out; + } + + data->pmi_reg =of_iomap (np); +if (!data->pmi_reg) { +printk (KERN_ERR "pmi: invalid register address.\n" ); + rc = -EFAULT ; + goto error_cleanup_data; + } + +INIT_LIST_HEAD (&data->handler); + +mutex_init (&data->msg_mutex); +spin_lock_init (&data->pmi_spinlock); +spin_lock_init (&data->handler_spinlock); + +INIT_WORK (&data->work, pmi_notify_handlers); + + dev->dev.driver_data = data; + data->dev = dev; + + data->irq =irq_of_parse_and_map (np,0 ); +if (data->irq ==NO_IRQ ) { +printk (KERN_ERR "pmi: invalid interrupt.\n" ); + rc = -EFAULT ; + goto error_cleanup_iomap; + } + + rc =request_irq (data->irq, pmi_irq_handler,0 ,"pmi" , data); +if (rc) { +printk (KERN_ERR "pmi: can't request IRQ %d: returned %d\n" , + data->irq, rc); + goto error_cleanup_iomap; + } + +printk (KERN_INFO "pmi: found pmi device at addr %p.\n" , data->pmi_reg); + + goto out; + +error_cleanup_iomap: +iounmap (data->pmi_reg); + +error_cleanup_data: +kfree (data); + +out: +return rc; +} + +static int pmi_of_remove (struct of_device *dev) +{ +struct pmi_data *data; +struct pmi_handler *handler, *tmp; + + data = dev->dev.driver_data; + +free_irq (data->irq, data); +iounmap (data->pmi_reg); + +spin_lock (&data->handler_spinlock); + +list_for_each_entry_safe (handler, tmp, &data->handler, node) +list_del (&handler->node); + +spin_unlock (&data->handler_spinlock); + +kfree (dev->dev.driver_data); + +return 0 ; +} + +static struct of_platform_driver pmi_of_platform_driver = { + .name ="pmi" , + .match_table = pmi_match, + .probe = pmi_of_probe, + .remove = pmi_of_remove +}; + +static int __init pmi_module_init (void ) +{ +return of_register_platform_driver (&pmi_of_platform_driver); +} +module_init (pmi_module_init); + +static void __exit pmi_module_exit(void) +{ +of_unregister_platform_driver (&pmi_of_platform_driver); +} +module_exit (pmi_module_exit); + +void pmi_send_message (struct of_device *device,pmi_message_t msg) +{ +struct pmi_data *data; +unsigned long flags; +DECLARE_COMPLETION_ONSTACK (completion); + + data = device->dev.driver_data; + +mutex_lock (&data->msg_mutex); + + data->msg = msg; +pr_debug ("pmi_send_message: msg is %08x\n" , *(u32 *)&msg); + + data->completion = &completion; + +spin_lock_irqsave (&data->pmi_spinlock, flags); +iowrite8 (msg.data0, data->pmi_reg +PMI_WRITE_DATA0 ); +iowrite8 (msg.data1, data->pmi_reg +PMI_WRITE_DATA1 ); +iowrite8 (msg.data2, data->pmi_reg +PMI_WRITE_DATA2 ); +iowrite8 (msg.type, data->pmi_reg +PMI_WRITE_TYPE ); +spin_unlock_irqrestore (&data->pmi_spinlock, flags); + +pr_debug ("pmi_send_message: wait for completion\n" ); + +wait_for_completion_interruptible_timeout (data->completion, +PMI_TIMEOUT ); + + data->completion =NULL ; + +mutex_unlock (&data->msg_mutex); +} +EXPORT_SYMBOL_GPL (pmi_send_message); + +void pmi_register_handler (struct of_device *device, +struct pmi_handler *handler) +{ +struct pmi_data *data; + data = device->dev.driver_data; + +spin_lock (&data->handler_spinlock); +list_add_tail (&handler->node, &data->handler); +spin_unlock (&data->handler_spinlock); +} +EXPORT_SYMBOL_GPL (pmi_register_handler); + +void pmi_unregister_handler (struct of_device *device, +struct pmi_handler *handler) +{ +struct pmi_data *data; + +pr_debug ("pmi: unregistering handler %p\n" , handler); + + data = device->dev.driver_data; + +spin_lock (&data->handler_spinlock); +list_del (&handler->node); +spin_unlock (&data->handler_spinlock); +} +EXPORT_SYMBOL_GPL (pmi_unregister_handler); + +MODULE_LICENSE ("GPL" ); +MODULE_AUTHOR ("Christian Krafft <[email protected]>" ); +MODULE_DESCRIPTION ("IBM Platform Management Interrupt driver" );
include/asm-powerpc/pmi.h new file +67 -0
67 lines not on this page · raw message
arch/powerpc/Kconfig +9 -0
@@ -577,6 +577,15 @@ config RTAS_FLASH tristate "Firmware flash interface" depends on PPC64 && RTAS_PROC +config PPC_PMI + tristate "Support for PMI" + depends PPC_IBM_CELL_BLADE + help + PMI (Platform Management Interrupt) is a way to + communicate with the BMC (Baseboard Mangement Controller). + It is used in some IBM Cell blades. + default m + config MMIO_NVRAM bool default n
arch/powerpc/configs/cell_defconfig +1 -0
@@ -147,6 +147,7 @@ CONFIG_PPC_RTAS=y # CONFIG_RTAS_ERROR_LOGGING is not set CONFIG_RTAS_PROC=y CONFIG_RTAS_FLASH=y +CONFIG_PPC_PMI=m CONFIG_MMIO_NVRAM=y # CONFIG_PPC_MPC106 is not set # CONFIG_PPC_970_NAP is not set
arch/powerpc/sysdev/Makefile +1 -0
@@ -7,6 +7,7 @@ obj-$(CONFIG_PPC_INDIRECT_PCI) += indire obj-$(CONFIG_PPC_MPC106) += grackle.o obj-$(CONFIG_PPC_DCR) += dcr.o obj-$(CONFIG_PPC_DCR_NATIVE) += dcr-low.o +obj-$(CONFIG_PPC_PMI) += pmi.o obj-$(CONFIG_U3_DART) += dart_iommu.o obj-$(CONFIG_MMIO_NVRAM) += mmio_nvram.o obj-$(CONFIG_FSL_SOC) += fsl_soc.o
Heiko J Schick
Acked-byRe: [Cbe-oss-dev] [patch v3] powerpc: add PMI driver for cell blade
Hello Christian,
arch/powerpc/sysdev/pmi.c line 120
Quoted 1 line · Christian Krafft
arch/powerpc/sysdev/pmi.c new file +1
-0+ { .type = "ibm,pmi", .name = "ibm,pmi" },
In the FW the device name is still "pmi" - only the type is "ibm,pmi".
I think it is better to rename it to "ibm,pmi", since PMI is a quite common abbreviation.
Beside this:
Regards,
Heiko
Re: [Cbe-oss-dev] [patch v3] powerpc: add PMI driver for cell blade
Quoted 10 lines · Heiko J Schick
Hello Christian,
arch/powerpc/sysdev/pmi.c line 120
Quoted 1 line · Christian Krafft
arch/powerpc/sysdev/pmi.c new file +1
-0+ { .type = "ibm,pmi", .name = "ibm,pmi" },In the FW the device name is still "pmi" - only the type is "ibm,pmi".
I think it is better to rename it to "ibm,pmi", since PMI is a quite common abbreviation.
Nah, the name doesn't matter that much as long as it's unique at a given level, just keep it to "pmi"
Ben.
Re: [Cbe-oss-dev] [patch v3] powerpc: add PMI driver for cell blade
Quoted 7 lines
Quoted 4 lines
In the FW the device name is still "pmi" - only the type is "ibm,pmi".
I think it is better to rename it to "ibm,pmi", since PMI is a quite common abbreviation.
Nah, the name doesn't matter that much as long as it's unique at a given level, just keep it to "pmi"
It doesn't have to be unique either, not even unique among siblings.
Segher