linuxppc-dev.lists.ozlabs.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 4/4] Avoid DMA exception when using axon_msi with IOMMU
  2008-01-22 11:04 Michael Ellerman
@ 2008-01-22 11:04 ` Michael Ellerman
  0 siblings, 0 replies; 9+ messages in thread
From: Michael Ellerman @ 2008-01-22 11:04 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: cbe-oss-dev

There's a brown-paper-bag bug in axon_msi, we pass the address of our
FIFO directly to the hardware, without DMA mapping it. This leads to
DMA exceptions if you enable MSI & the IOMMU.

The fix is to correctly DMA map the fifo, dma_alloc_coherent() does
what we want - and we need to track the virt & phys addresses.

Signed-off-by: Michael Ellerman <michael@ellerman.id.au>
---
 arch/powerpc/platforms/cell/axon_msi.c |   21 ++++++++++-----------
 1 files changed, 10 insertions(+), 11 deletions(-)

diff --git a/arch/powerpc/platforms/cell/axon_msi.c b/arch/powerpc/platforms/cell/axon_msi.c
index 8de3d23..c546879 100644
--- a/arch/powerpc/platforms/cell/axon_msi.c
+++ b/arch/powerpc/platforms/cell/axon_msi.c
@@ -65,7 +65,8 @@
 
 struct axon_msic {
 	struct irq_host *irq_host;
-	__le32 *fifo;
+	__le32 *fifo_virt;
+	dma_addr_t fifo_phys;
 	dcr_host_t dcr_host;
 	u32 read_offset;
 };
@@ -91,7 +92,7 @@ static void axon_msi_cascade(unsigned int irq, struct irq_desc *desc)
 
 	while (msic->read_offset != write_offset) {
 		idx  = msic->read_offset / sizeof(__le32);
-		msi  = le32_to_cpu(msic->fifo[idx]);
+		msi  = le32_to_cpu(msic->fifo_virt[idx]);
 		msi &= 0xFFFF;
 
 		pr_debug("axon_msi: woff %x roff %x msi %x\n",
@@ -306,7 +307,6 @@ static int axon_msi_shutdown(struct of_device *device)
 static int axon_msi_probe(struct of_device *device,
 			  const struct of_device_id *device_id)
 {
-	struct page *page;
 	struct device_node *dn = device->node;
 	struct axon_msic *msic;
 	unsigned int virq;
@@ -338,16 +338,14 @@ static int axon_msi_probe(struct of_device *device,
 		goto out_free_msic;
 	}
 
-	page = alloc_pages_node(of_node_to_nid(dn), GFP_KERNEL,
-				get_order(MSIC_FIFO_SIZE_BYTES));
-	if (!page) {
+	msic->fifo_virt = dma_alloc_coherent(&device->dev, MSIC_FIFO_SIZE_BYTES,
+					     &msic->fifo_phys, GFP_KERNEL);
+	if (!msic->fifo_virt) {
 		printk(KERN_ERR "axon_msi: couldn't allocate fifo for %s\n",
 		       dn->full_name);
 		goto out_free_msic;
 	}
 
-	msic->fifo = page_address(page);
-
 	msic->irq_host = irq_alloc_host(of_node_get(dn), IRQ_HOST_MAP_NOMAP,
 					NR_IRQS, &msic_host_ops, 0);
 	if (!msic->irq_host) {
@@ -370,9 +368,9 @@ static int axon_msi_probe(struct of_device *device,
 	pr_debug("axon_msi: irq 0x%x setup for axon_msi\n", virq);
 
 	/* Enable the MSIC hardware */
-	msic_dcr_write(msic, MSIC_BASE_ADDR_HI_REG, (u64)msic->fifo >> 32);
+	msic_dcr_write(msic, MSIC_BASE_ADDR_HI_REG, msic->fifo_phys >> 32);
 	msic_dcr_write(msic, MSIC_BASE_ADDR_LO_REG,
-				  (u64)msic->fifo & 0xFFFFFFFF);
+				  msic->fifo_phys & 0xFFFFFFFF);
 	msic_dcr_write(msic, MSIC_CTRL_REG,
 			MSIC_CTRL_IRQ_ENABLE | MSIC_CTRL_ENABLE |
 			MSIC_CTRL_FIFO_SIZE);
@@ -390,7 +388,8 @@ static int axon_msi_probe(struct of_device *device,
 out_free_host:
 	kfree(msic->irq_host);
 out_free_fifo:
-	__free_pages(virt_to_page(msic->fifo), get_order(MSIC_FIFO_SIZE_BYTES));
+	dma_free_coherent(&device->dev, MSIC_FIFO_SIZE_BYTES, msic->fifo_virt,
+			  msic->fifo_phys);
 out_free_msic:
 	kfree(msic);
 out:
-- 
1.5.2.rc1.1884.g59b20

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

* [PATCH 1/4] Search for and publish cell OF platform devices earlier
@ 2008-01-25  5:59 Michael Ellerman
  2008-01-25  5:59 ` [PATCH 2/4] Create and hook up of_platform_device_shutdown Michael Ellerman
                   ` (3 more replies)
  0 siblings, 4 replies; 9+ messages in thread
From: Michael Ellerman @ 2008-01-25  5:59 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: cbe-oss-dev

Currently cell publishes OF devices at device_initcall() time, which
means the earliest a driver can bind to a device is also device_initcall()
time. We have a driver we want to register before other devices, so
publish the devices at subsys_initcall() time.

This should not cause any behaviour change for existing drivers, as they
are still bound at device_initcall() time.

Signed-off-by: Michael Ellerman <michael@ellerman.id.au>
---
 arch/powerpc/platforms/cell/setup.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/arch/powerpc/platforms/cell/setup.c b/arch/powerpc/platforms/cell/setup.c
index e6534b5..a7f609b 100644
--- a/arch/powerpc/platforms/cell/setup.c
+++ b/arch/powerpc/platforms/cell/setup.c
@@ -98,7 +98,7 @@ static int __init cell_publish_devices(void)
 	}
 	return 0;
 }
-machine_device_initcall(cell, cell_publish_devices);
+machine_subsys_initcall(cell, cell_publish_devices);
 
 static void cell_mpic_cascade(unsigned int irq, struct irq_desc *desc)
 {
-- 
1.5.2.rc1.1884.g59b20

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

* [PATCH 2/4] Create and hook up of_platform_device_shutdown
  2008-01-25  5:59 [PATCH 1/4] Search for and publish cell OF platform devices earlier Michael Ellerman
@ 2008-01-25  5:59 ` Michael Ellerman
  2008-02-05  0:19   ` Benjamin Herrenschmidt
  2008-01-25  5:59 ` [PATCH 3/4] Convert axon_msi to an of_platform driver Michael Ellerman
                   ` (2 subsequent siblings)
  3 siblings, 1 reply; 9+ messages in thread
From: Michael Ellerman @ 2008-01-25  5:59 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: sparclinux, tnt, cbe-oss-dev, m8, davem

Although of_platform_device's can have a shutdown routine, at the moment
the bus code doesn't actually call it. So add the required glue to
hook the shutdown routine.

Signed-off-by: Michael Ellerman <michael@ellerman.id.au>
---
 drivers/of/platform.c |   10 ++++++++++
 1 files changed, 10 insertions(+), 0 deletions(-)


CC various folks who've written/touched of_platform_drivers which already
have shutdown routines. These routines have never been called so they're
about to get their first testing.

diff --git a/drivers/of/platform.c b/drivers/of/platform.c
index b47bb2d..ca09a63 100644
--- a/drivers/of/platform.c
+++ b/drivers/of/platform.c
@@ -85,6 +85,15 @@ static int of_platform_device_resume(struct device * dev)
 	return error;
 }
 
+static void of_platform_device_shutdown(struct device *dev)
+{
+	struct of_device *of_dev = to_of_device(dev);
+	struct of_platform_driver *drv = to_of_platform_driver(dev->driver);
+
+	if (dev->driver && drv->shutdown)
+		drv->shutdown(of_dev);
+}
+
 int of_bus_type_init(struct bus_type *bus, const char *name)
 {
 	bus->name = name;
@@ -93,6 +102,7 @@ int of_bus_type_init(struct bus_type *bus, const char *name)
 	bus->remove = of_platform_device_remove;
 	bus->suspend = of_platform_device_suspend;
 	bus->resume = of_platform_device_resume;
+	bus->shutdown = of_platform_device_shutdown;
 	return bus_register(bus);
 }
 
-- 
1.5.2.rc1.1884.g59b20

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

* [PATCH 3/4] Convert axon_msi to an of_platform driver
  2008-01-25  5:59 [PATCH 1/4] Search for and publish cell OF platform devices earlier Michael Ellerman
  2008-01-25  5:59 ` [PATCH 2/4] Create and hook up of_platform_device_shutdown Michael Ellerman
@ 2008-01-25  5:59 ` Michael Ellerman
  2008-02-05  0:20   ` Benjamin Herrenschmidt
  2008-01-25  5:59 ` [PATCH 4/4] Avoid DMA exception when using axon_msi with IOMMU Michael Ellerman
  2008-02-05  0:19 ` [PATCH 1/4] Search for and publish cell OF platform devices earlier Benjamin Herrenschmidt
  3 siblings, 1 reply; 9+ messages in thread
From: Michael Ellerman @ 2008-01-25  5:59 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: cbe-oss-dev

Now that we create of_platform devices earlier on cell, we can make the
axon_msi driver an of_platform driver. This makes the code cleaner in
several ways, and most importantly means we have a struct device.

Signed-off-by: Michael Ellerman <michael@ellerman.id.au>
---
 arch/powerpc/platforms/cell/axon_msi.c |   76 ++++++++++++++-----------------
 1 files changed, 34 insertions(+), 42 deletions(-)

diff --git a/arch/powerpc/platforms/cell/axon_msi.c b/arch/powerpc/platforms/cell/axon_msi.c
index 095988f..ea3dc8c 100644
--- a/arch/powerpc/platforms/cell/axon_msi.c
+++ b/arch/powerpc/platforms/cell/axon_msi.c
@@ -13,7 +13,7 @@
 #include <linux/kernel.h>
 #include <linux/pci.h>
 #include <linux/msi.h>
-#include <linux/reboot.h>
+#include <linux/of_platform.h>
 
 #include <asm/dcr.h>
 #include <asm/machdep.h>
@@ -67,12 +67,9 @@ struct axon_msic {
 	struct irq_host *irq_host;
 	__le32 *fifo;
 	dcr_host_t dcr_host;
-	struct list_head list;
 	u32 read_offset;
 };
 
-static LIST_HEAD(axon_msic_list);
-
 static void msic_dcr_write(struct axon_msic *msic, unsigned int dcr_n, u32 val)
 {
 	pr_debug("axon_msi: dcr_write(0x%x, 0x%x)\n", val, dcr_n);
@@ -292,30 +289,25 @@ static struct irq_host_ops msic_host_ops = {
 	.map	= msic_host_map,
 };
 
-static int axon_msi_notify_reboot(struct notifier_block *nb,
-				  unsigned long code, void *data)
+static int axon_msi_shutdown(struct of_device *device)
 {
-	struct axon_msic *msic;
+	struct axon_msic *msic = device->dev.platform_data;
 	u32 tmp;
 
-	list_for_each_entry(msic, &axon_msic_list, list) {
-		pr_debug("axon_msi: disabling %s\n",
-			  msic->irq_host->of_node->full_name);
-		tmp  = dcr_read(msic->dcr_host, MSIC_CTRL_REG);
-		tmp &= ~MSIC_CTRL_ENABLE & ~MSIC_CTRL_IRQ_ENABLE;
-		msic_dcr_write(msic, MSIC_CTRL_REG, tmp);
-	}
+	pr_debug("axon_msi: disabling %s\n",
+		  msic->irq_host->of_node->full_name);
+	tmp  = dcr_read(msic->dcr_host, MSIC_CTRL_REG);
+	tmp &= ~MSIC_CTRL_ENABLE & ~MSIC_CTRL_IRQ_ENABLE;
+	msic_dcr_write(msic, MSIC_CTRL_REG, tmp);
 
 	return 0;
 }
 
-static struct notifier_block axon_msi_reboot_notifier = {
-	.notifier_call = axon_msi_notify_reboot
-};
-
-static int axon_msi_setup_one(struct device_node *dn)
+static int axon_msi_probe(struct of_device *device,
+			  const struct of_device_id *device_id)
 {
 	struct page *page;
+	struct device_node *dn = device->node;
 	struct axon_msic *msic;
 	unsigned int virq;
 	int dcr_base, dcr_len;
@@ -385,7 +377,11 @@ static int axon_msi_setup_one(struct device_node *dn)
 			MSIC_CTRL_IRQ_ENABLE | MSIC_CTRL_ENABLE |
 			MSIC_CTRL_FIFO_SIZE);
 
-	list_add(&msic->list, &axon_msic_list);
+	device->dev.platform_data = msic;
+
+	ppc_md.setup_msi_irqs = axon_msi_setup_msi_irqs;
+	ppc_md.teardown_msi_irqs = axon_msi_teardown_msi_irqs;
+	ppc_md.msi_check_device = axon_msi_check_device;
 
 	printk(KERN_DEBUG "axon_msi: setup MSIC on %s\n", dn->full_name);
 
@@ -402,28 +398,24 @@ out:
 	return -1;
 }
 
-static int axon_msi_init(void)
-{
-	struct device_node *dn;
-	int found = 0;
-
-	pr_debug("axon_msi: initialising ...\n");
-
-	for_each_compatible_node(dn, NULL, "ibm,axon-msic") {
-		if (axon_msi_setup_one(dn) == 0)
-			found++;
-	}
-
-	if (found) {
-		ppc_md.setup_msi_irqs = axon_msi_setup_msi_irqs;
-		ppc_md.teardown_msi_irqs = axon_msi_teardown_msi_irqs;
-		ppc_md.msi_check_device = axon_msi_check_device;
-
-		register_reboot_notifier(&axon_msi_reboot_notifier);
+static const struct of_device_id axon_msi_device_id[] = {
+	{
+		.compatible	= "ibm,axon-msic"
+	},
+	{}
+};
 
-		pr_debug("axon_msi: registered callbacks!\n");
-	}
+static struct of_platform_driver axon_msi_driver = {
+	.match_table	= axon_msi_device_id,
+	.probe		= axon_msi_probe,
+	.shutdown	= axon_msi_shutdown,
+	.driver		= {
+		.name	= "axon-msi"
+	},
+};
 
-	return 0;
+static int __init axon_msi_init(void)
+{
+	return of_register_platform_driver(&axon_msi_driver);
 }
-arch_initcall(axon_msi_init);
+subsys_initcall(axon_msi_init);
-- 
1.5.2.rc1.1884.g59b20

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

* [PATCH 4/4] Avoid DMA exception when using axon_msi with IOMMU
  2008-01-25  5:59 [PATCH 1/4] Search for and publish cell OF platform devices earlier Michael Ellerman
  2008-01-25  5:59 ` [PATCH 2/4] Create and hook up of_platform_device_shutdown Michael Ellerman
  2008-01-25  5:59 ` [PATCH 3/4] Convert axon_msi to an of_platform driver Michael Ellerman
@ 2008-01-25  5:59 ` Michael Ellerman
  2008-02-05  0:21   ` Benjamin Herrenschmidt
  2008-02-05  0:19 ` [PATCH 1/4] Search for and publish cell OF platform devices earlier Benjamin Herrenschmidt
  3 siblings, 1 reply; 9+ messages in thread
From: Michael Ellerman @ 2008-01-25  5:59 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: cbe-oss-dev

There's a brown-paper-bag bug in axon_msi, we pass the address of our
FIFO directly to the hardware, without DMA mapping it. This leads to
DMA exceptions if you enable MSI & the IOMMU.

The fix is to correctly DMA map the fifo, dma_alloc_coherent() does
what we want - and we need to track the virt & phys addresses.

Signed-off-by: Michael Ellerman <michael@ellerman.id.au>
---
 arch/powerpc/platforms/cell/axon_msi.c |   21 ++++++++++-----------
 1 files changed, 10 insertions(+), 11 deletions(-)

diff --git a/arch/powerpc/platforms/cell/axon_msi.c b/arch/powerpc/platforms/cell/axon_msi.c
index ea3dc8c..b9a97c4 100644
--- a/arch/powerpc/platforms/cell/axon_msi.c
+++ b/arch/powerpc/platforms/cell/axon_msi.c
@@ -65,7 +65,8 @@
 
 struct axon_msic {
 	struct irq_host *irq_host;
-	__le32 *fifo;
+	__le32 *fifo_virt;
+	dma_addr_t fifo_phys;
 	dcr_host_t dcr_host;
 	u32 read_offset;
 };
@@ -91,7 +92,7 @@ static void axon_msi_cascade(unsigned int irq, struct irq_desc *desc)
 
 	while (msic->read_offset != write_offset) {
 		idx  = msic->read_offset / sizeof(__le32);
-		msi  = le32_to_cpu(msic->fifo[idx]);
+		msi  = le32_to_cpu(msic->fifo_virt[idx]);
 		msi &= 0xFFFF;
 
 		pr_debug("axon_msi: woff %x roff %x msi %x\n",
@@ -306,7 +307,6 @@ static int axon_msi_shutdown(struct of_device *device)
 static int axon_msi_probe(struct of_device *device,
 			  const struct of_device_id *device_id)
 {
-	struct page *page;
 	struct device_node *dn = device->node;
 	struct axon_msic *msic;
 	unsigned int virq;
@@ -338,16 +338,14 @@ static int axon_msi_probe(struct of_device *device,
 		goto out_free_msic;
 	}
 
-	page = alloc_pages_node(of_node_to_nid(dn), GFP_KERNEL,
-				get_order(MSIC_FIFO_SIZE_BYTES));
-	if (!page) {
+	msic->fifo_virt = dma_alloc_coherent(&device->dev, MSIC_FIFO_SIZE_BYTES,
+					     &msic->fifo_phys, GFP_KERNEL);
+	if (!msic->fifo_virt) {
 		printk(KERN_ERR "axon_msi: couldn't allocate fifo for %s\n",
 		       dn->full_name);
 		goto out_free_msic;
 	}
 
-	msic->fifo = page_address(page);
-
 	msic->irq_host = irq_alloc_host(of_node_get(dn), IRQ_HOST_MAP_NOMAP,
 					NR_IRQS, &msic_host_ops, 0);
 	if (!msic->irq_host) {
@@ -370,9 +368,9 @@ static int axon_msi_probe(struct of_device *device,
 	pr_debug("axon_msi: irq 0x%x setup for axon_msi\n", virq);
 
 	/* Enable the MSIC hardware */
-	msic_dcr_write(msic, MSIC_BASE_ADDR_HI_REG, (u64)msic->fifo >> 32);
+	msic_dcr_write(msic, MSIC_BASE_ADDR_HI_REG, msic->fifo_phys >> 32);
 	msic_dcr_write(msic, MSIC_BASE_ADDR_LO_REG,
-				  (u64)msic->fifo & 0xFFFFFFFF);
+				  msic->fifo_phys & 0xFFFFFFFF);
 	msic_dcr_write(msic, MSIC_CTRL_REG,
 			MSIC_CTRL_IRQ_ENABLE | MSIC_CTRL_ENABLE |
 			MSIC_CTRL_FIFO_SIZE);
@@ -390,7 +388,8 @@ static int axon_msi_probe(struct of_device *device,
 out_free_host:
 	kfree(msic->irq_host);
 out_free_fifo:
-	__free_pages(virt_to_page(msic->fifo), get_order(MSIC_FIFO_SIZE_BYTES));
+	dma_free_coherent(&device->dev, MSIC_FIFO_SIZE_BYTES, msic->fifo_virt,
+			  msic->fifo_phys);
 out_free_msic:
 	kfree(msic);
 out:
-- 
1.5.2.rc1.1884.g59b20

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

* Re: [PATCH 1/4] Search for and publish cell OF platform devices earlier
  2008-01-25  5:59 [PATCH 1/4] Search for and publish cell OF platform devices earlier Michael Ellerman
                   ` (2 preceding siblings ...)
  2008-01-25  5:59 ` [PATCH 4/4] Avoid DMA exception when using axon_msi with IOMMU Michael Ellerman
@ 2008-02-05  0:19 ` Benjamin Herrenschmidt
  3 siblings, 0 replies; 9+ messages in thread
From: Benjamin Herrenschmidt @ 2008-02-05  0:19 UTC (permalink / raw)
  To: Michael Ellerman; +Cc: linuxppc-dev, cbe-oss-dev


On Fri, 2008-01-25 at 16:59 +1100, Michael Ellerman wrote:
> Currently cell publishes OF devices at device_initcall() time, which
> means the earliest a driver can bind to a device is also device_initcall()
> time. We have a driver we want to register before other devices, so
> publish the devices at subsys_initcall() time.
> 
> This should not cause any behaviour change for existing drivers, as they
> are still bound at device_initcall() time.
> 
> Signed-off-by: Michael Ellerman <michael@ellerman.id.au>

Acked-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>

> ---
>  arch/powerpc/platforms/cell/setup.c |    2 +-
>  1 files changed, 1 insertions(+), 1 deletions(-)
> 
> diff --git a/arch/powerpc/platforms/cell/setup.c b/arch/powerpc/platforms/cell/setup.c
> index e6534b5..a7f609b 100644
> --- a/arch/powerpc/platforms/cell/setup.c
> +++ b/arch/powerpc/platforms/cell/setup.c
> @@ -98,7 +98,7 @@ static int __init cell_publish_devices(void)
>  	}
>  	return 0;
>  }
> -machine_device_initcall(cell, cell_publish_devices);
> +machine_subsys_initcall(cell, cell_publish_devices);
>  
>  static void cell_mpic_cascade(unsigned int irq, struct irq_desc *desc)
>  {

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

* Re: [PATCH 2/4] Create and hook up of_platform_device_shutdown
  2008-01-25  5:59 ` [PATCH 2/4] Create and hook up of_platform_device_shutdown Michael Ellerman
@ 2008-02-05  0:19   ` Benjamin Herrenschmidt
  0 siblings, 0 replies; 9+ messages in thread
From: Benjamin Herrenschmidt @ 2008-02-05  0:19 UTC (permalink / raw)
  To: Michael Ellerman; +Cc: tnt, davem, linuxppc-dev, sparclinux, cbe-oss-dev, m8


On Fri, 2008-01-25 at 16:59 +1100, Michael Ellerman wrote:
> Although of_platform_device's can have a shutdown routine, at the moment
> the bus code doesn't actually call it. So add the required glue to
> hook the shutdown routine.
> 
> Signed-off-by: Michael Ellerman <michael@ellerman.id.au>

Acked-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>

> ---
>  drivers/of/platform.c |   10 ++++++++++
>  1 files changed, 10 insertions(+), 0 deletions(-)
> 
> 
> CC various folks who've written/touched of_platform_drivers which already
> have shutdown routines. These routines have never been called so they're
> about to get their first testing.
> 
> diff --git a/drivers/of/platform.c b/drivers/of/platform.c
> index b47bb2d..ca09a63 100644
> --- a/drivers/of/platform.c
> +++ b/drivers/of/platform.c
> @@ -85,6 +85,15 @@ static int of_platform_device_resume(struct device * dev)
>  	return error;
>  }
>  
> +static void of_platform_device_shutdown(struct device *dev)
> +{
> +	struct of_device *of_dev = to_of_device(dev);
> +	struct of_platform_driver *drv = to_of_platform_driver(dev->driver);
> +
> +	if (dev->driver && drv->shutdown)
> +		drv->shutdown(of_dev);
> +}
> +
>  int of_bus_type_init(struct bus_type *bus, const char *name)
>  {
>  	bus->name = name;
> @@ -93,6 +102,7 @@ int of_bus_type_init(struct bus_type *bus, const char *name)
>  	bus->remove = of_platform_device_remove;
>  	bus->suspend = of_platform_device_suspend;
>  	bus->resume = of_platform_device_resume;
> +	bus->shutdown = of_platform_device_shutdown;
>  	return bus_register(bus);
>  }
>  

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

* Re: [PATCH 3/4] Convert axon_msi to an of_platform driver
  2008-01-25  5:59 ` [PATCH 3/4] Convert axon_msi to an of_platform driver Michael Ellerman
@ 2008-02-05  0:20   ` Benjamin Herrenschmidt
  0 siblings, 0 replies; 9+ messages in thread
From: Benjamin Herrenschmidt @ 2008-02-05  0:20 UTC (permalink / raw)
  To: Michael Ellerman; +Cc: linuxppc-dev, cbe-oss-dev


On Fri, 2008-01-25 at 16:59 +1100, Michael Ellerman wrote:
> Now that we create of_platform devices earlier on cell, we can make the
> axon_msi driver an of_platform driver. This makes the code cleaner in
> several ways, and most importantly means we have a struct device.
> 
> Signed-off-by: Michael Ellerman <michael@ellerman.id.au>

Acked-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>

> ---
>  arch/powerpc/platforms/cell/axon_msi.c |   76 ++++++++++++++-----------------
>  1 files changed, 34 insertions(+), 42 deletions(-)
> 
> diff --git a/arch/powerpc/platforms/cell/axon_msi.c b/arch/powerpc/platforms/cell/axon_msi.c
> index 095988f..ea3dc8c 100644
> --- a/arch/powerpc/platforms/cell/axon_msi.c
> +++ b/arch/powerpc/platforms/cell/axon_msi.c
> @@ -13,7 +13,7 @@
>  #include <linux/kernel.h>
>  #include <linux/pci.h>
>  #include <linux/msi.h>
> -#include <linux/reboot.h>
> +#include <linux/of_platform.h>
>  
>  #include <asm/dcr.h>
>  #include <asm/machdep.h>
> @@ -67,12 +67,9 @@ struct axon_msic {
>  	struct irq_host *irq_host;
>  	__le32 *fifo;
>  	dcr_host_t dcr_host;
> -	struct list_head list;
>  	u32 read_offset;
>  };
>  
> -static LIST_HEAD(axon_msic_list);
> -
>  static void msic_dcr_write(struct axon_msic *msic, unsigned int dcr_n, u32 val)
>  {
>  	pr_debug("axon_msi: dcr_write(0x%x, 0x%x)\n", val, dcr_n);
> @@ -292,30 +289,25 @@ static struct irq_host_ops msic_host_ops = {
>  	.map	= msic_host_map,
>  };
>  
> -static int axon_msi_notify_reboot(struct notifier_block *nb,
> -				  unsigned long code, void *data)
> +static int axon_msi_shutdown(struct of_device *device)
>  {
> -	struct axon_msic *msic;
> +	struct axon_msic *msic = device->dev.platform_data;
>  	u32 tmp;
>  
> -	list_for_each_entry(msic, &axon_msic_list, list) {
> -		pr_debug("axon_msi: disabling %s\n",
> -			  msic->irq_host->of_node->full_name);
> -		tmp  = dcr_read(msic->dcr_host, MSIC_CTRL_REG);
> -		tmp &= ~MSIC_CTRL_ENABLE & ~MSIC_CTRL_IRQ_ENABLE;
> -		msic_dcr_write(msic, MSIC_CTRL_REG, tmp);
> -	}
> +	pr_debug("axon_msi: disabling %s\n",
> +		  msic->irq_host->of_node->full_name);
> +	tmp  = dcr_read(msic->dcr_host, MSIC_CTRL_REG);
> +	tmp &= ~MSIC_CTRL_ENABLE & ~MSIC_CTRL_IRQ_ENABLE;
> +	msic_dcr_write(msic, MSIC_CTRL_REG, tmp);
>  
>  	return 0;
>  }
>  
> -static struct notifier_block axon_msi_reboot_notifier = {
> -	.notifier_call = axon_msi_notify_reboot
> -};
> -
> -static int axon_msi_setup_one(struct device_node *dn)
> +static int axon_msi_probe(struct of_device *device,
> +			  const struct of_device_id *device_id)
>  {
>  	struct page *page;
> +	struct device_node *dn = device->node;
>  	struct axon_msic *msic;
>  	unsigned int virq;
>  	int dcr_base, dcr_len;
> @@ -385,7 +377,11 @@ static int axon_msi_setup_one(struct device_node *dn)
>  			MSIC_CTRL_IRQ_ENABLE | MSIC_CTRL_ENABLE |
>  			MSIC_CTRL_FIFO_SIZE);
>  
> -	list_add(&msic->list, &axon_msic_list);
> +	device->dev.platform_data = msic;
> +
> +	ppc_md.setup_msi_irqs = axon_msi_setup_msi_irqs;
> +	ppc_md.teardown_msi_irqs = axon_msi_teardown_msi_irqs;
> +	ppc_md.msi_check_device = axon_msi_check_device;
>  
>  	printk(KERN_DEBUG "axon_msi: setup MSIC on %s\n", dn->full_name);
>  
> @@ -402,28 +398,24 @@ out:
>  	return -1;
>  }
>  
> -static int axon_msi_init(void)
> -{
> -	struct device_node *dn;
> -	int found = 0;
> -
> -	pr_debug("axon_msi: initialising ...\n");
> -
> -	for_each_compatible_node(dn, NULL, "ibm,axon-msic") {
> -		if (axon_msi_setup_one(dn) == 0)
> -			found++;
> -	}
> -
> -	if (found) {
> -		ppc_md.setup_msi_irqs = axon_msi_setup_msi_irqs;
> -		ppc_md.teardown_msi_irqs = axon_msi_teardown_msi_irqs;
> -		ppc_md.msi_check_device = axon_msi_check_device;
> -
> -		register_reboot_notifier(&axon_msi_reboot_notifier);
> +static const struct of_device_id axon_msi_device_id[] = {
> +	{
> +		.compatible	= "ibm,axon-msic"
> +	},
> +	{}
> +};
>  
> -		pr_debug("axon_msi: registered callbacks!\n");
> -	}
> +static struct of_platform_driver axon_msi_driver = {
> +	.match_table	= axon_msi_device_id,
> +	.probe		= axon_msi_probe,
> +	.shutdown	= axon_msi_shutdown,
> +	.driver		= {
> +		.name	= "axon-msi"
> +	},
> +};
>  
> -	return 0;
> +static int __init axon_msi_init(void)
> +{
> +	return of_register_platform_driver(&axon_msi_driver);
>  }
> -arch_initcall(axon_msi_init);
> +subsys_initcall(axon_msi_init);
> -- 
> 1.5.2.rc1.1884.g59b20
> 
> _______________________________________________
> Linuxppc-dev mailing list
> Linuxppc-dev@ozlabs.org
> https://ozlabs.org/mailman/listinfo/linuxppc-dev

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

* Re: [PATCH 4/4] Avoid DMA exception when using axon_msi with IOMMU
  2008-01-25  5:59 ` [PATCH 4/4] Avoid DMA exception when using axon_msi with IOMMU Michael Ellerman
@ 2008-02-05  0:21   ` Benjamin Herrenschmidt
  0 siblings, 0 replies; 9+ messages in thread
From: Benjamin Herrenschmidt @ 2008-02-05  0:21 UTC (permalink / raw)
  To: Michael Ellerman; +Cc: linuxppc-dev, cbe-oss-dev


On Fri, 2008-01-25 at 16:59 +1100, Michael Ellerman wrote:
> There's a brown-paper-bag bug in axon_msi, we pass the address of our
> FIFO directly to the hardware, without DMA mapping it. This leads to
> DMA exceptions if you enable MSI & the IOMMU.
> 
> The fix is to correctly DMA map the fifo, dma_alloc_coherent() does
> what we want - and we need to track the virt & phys addresses.
> 
> Signed-off-by: Michael Ellerman <michael@ellerman.id.au>

Acked-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>

> ---
>  arch/powerpc/platforms/cell/axon_msi.c |   21 ++++++++++-----------
>  1 files changed, 10 insertions(+), 11 deletions(-)
> 
> diff --git a/arch/powerpc/platforms/cell/axon_msi.c b/arch/powerpc/platforms/cell/axon_msi.c
> index ea3dc8c..b9a97c4 100644
> --- a/arch/powerpc/platforms/cell/axon_msi.c
> +++ b/arch/powerpc/platforms/cell/axon_msi.c
> @@ -65,7 +65,8 @@
>  
>  struct axon_msic {
>  	struct irq_host *irq_host;
> -	__le32 *fifo;
> +	__le32 *fifo_virt;
> +	dma_addr_t fifo_phys;
>  	dcr_host_t dcr_host;
>  	u32 read_offset;
>  };
> @@ -91,7 +92,7 @@ static void axon_msi_cascade(unsigned int irq, struct irq_desc *desc)
>  
>  	while (msic->read_offset != write_offset) {
>  		idx  = msic->read_offset / sizeof(__le32);
> -		msi  = le32_to_cpu(msic->fifo[idx]);
> +		msi  = le32_to_cpu(msic->fifo_virt[idx]);
>  		msi &= 0xFFFF;
>  
>  		pr_debug("axon_msi: woff %x roff %x msi %x\n",
> @@ -306,7 +307,6 @@ static int axon_msi_shutdown(struct of_device *device)
>  static int axon_msi_probe(struct of_device *device,
>  			  const struct of_device_id *device_id)
>  {
> -	struct page *page;
>  	struct device_node *dn = device->node;
>  	struct axon_msic *msic;
>  	unsigned int virq;
> @@ -338,16 +338,14 @@ static int axon_msi_probe(struct of_device *device,
>  		goto out_free_msic;
>  	}
>  
> -	page = alloc_pages_node(of_node_to_nid(dn), GFP_KERNEL,
> -				get_order(MSIC_FIFO_SIZE_BYTES));
> -	if (!page) {
> +	msic->fifo_virt = dma_alloc_coherent(&device->dev, MSIC_FIFO_SIZE_BYTES,
> +					     &msic->fifo_phys, GFP_KERNEL);
> +	if (!msic->fifo_virt) {
>  		printk(KERN_ERR "axon_msi: couldn't allocate fifo for %s\n",
>  		       dn->full_name);
>  		goto out_free_msic;
>  	}
>  
> -	msic->fifo = page_address(page);
> -
>  	msic->irq_host = irq_alloc_host(of_node_get(dn), IRQ_HOST_MAP_NOMAP,
>  					NR_IRQS, &msic_host_ops, 0);
>  	if (!msic->irq_host) {
> @@ -370,9 +368,9 @@ static int axon_msi_probe(struct of_device *device,
>  	pr_debug("axon_msi: irq 0x%x setup for axon_msi\n", virq);
>  
>  	/* Enable the MSIC hardware */
> -	msic_dcr_write(msic, MSIC_BASE_ADDR_HI_REG, (u64)msic->fifo >> 32);
> +	msic_dcr_write(msic, MSIC_BASE_ADDR_HI_REG, msic->fifo_phys >> 32);
>  	msic_dcr_write(msic, MSIC_BASE_ADDR_LO_REG,
> -				  (u64)msic->fifo & 0xFFFFFFFF);
> +				  msic->fifo_phys & 0xFFFFFFFF);
>  	msic_dcr_write(msic, MSIC_CTRL_REG,
>  			MSIC_CTRL_IRQ_ENABLE | MSIC_CTRL_ENABLE |
>  			MSIC_CTRL_FIFO_SIZE);
> @@ -390,7 +388,8 @@ static int axon_msi_probe(struct of_device *device,
>  out_free_host:
>  	kfree(msic->irq_host);
>  out_free_fifo:
> -	__free_pages(virt_to_page(msic->fifo), get_order(MSIC_FIFO_SIZE_BYTES));
> +	dma_free_coherent(&device->dev, MSIC_FIFO_SIZE_BYTES, msic->fifo_virt,
> +			  msic->fifo_phys);
>  out_free_msic:
>  	kfree(msic);
>  out:

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

end of thread, other threads:[~2008-02-05  0:21 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2008-01-25  5:59 [PATCH 1/4] Search for and publish cell OF platform devices earlier Michael Ellerman
2008-01-25  5:59 ` [PATCH 2/4] Create and hook up of_platform_device_shutdown Michael Ellerman
2008-02-05  0:19   ` Benjamin Herrenschmidt
2008-01-25  5:59 ` [PATCH 3/4] Convert axon_msi to an of_platform driver Michael Ellerman
2008-02-05  0:20   ` Benjamin Herrenschmidt
2008-01-25  5:59 ` [PATCH 4/4] Avoid DMA exception when using axon_msi with IOMMU Michael Ellerman
2008-02-05  0:21   ` Benjamin Herrenschmidt
2008-02-05  0:19 ` [PATCH 1/4] Search for and publish cell OF platform devices earlier Benjamin Herrenschmidt
  -- strict thread matches above, loose matches on Subject: below --
2008-01-22 11:04 Michael Ellerman
2008-01-22 11:04 ` [PATCH 4/4] Avoid DMA exception when using axon_msi with IOMMU Michael Ellerman

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).