LinuxPPC-Dev Archive on lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 2/4 v2] net: mvmdio: rename base register cookie from smireg to regs
From: Florian Fainelli @ 2013-03-14 18:08 UTC (permalink / raw)
  To: davem
  Cc: Thomas Petazzoni, Andrew Lunn, Russell King, Jason Cooper,
	linux-doc, devicetree-discuss, linux-kernel, Rob Herring, netdev,
	Paul Mackerras, linux-arm-kernel, Rob Landley, Greg Kroah-Hartman,
	linuxppc-dev, Florian Fainelli, Lennert Buytenhek
In-Reply-To: <1363284515-9865-1-git-send-email-florian@openwrt.org>

This patch renames the base register cookie in the mvmdio drive from
"smireg" to "regs" since a subsequent patch is going to use an ioremap()
cookie whose size is larger than a single register of 4 bytes. No
functionnal code change introduced.

Acked-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
Signed-off-by: Florian Fainelli <florian@openwrt.org>
---
Changes since v1:
- added Thomas Acked-by tag

 drivers/net/ethernet/marvell/mvmdio.c |   14 +++++++-------
 1 file changed, 7 insertions(+), 7 deletions(-)

diff --git a/drivers/net/ethernet/marvell/mvmdio.c b/drivers/net/ethernet/marvell/mvmdio.c
index 8a182f1..595deea 100644
--- a/drivers/net/ethernet/marvell/mvmdio.c
+++ b/drivers/net/ethernet/marvell/mvmdio.c
@@ -38,7 +38,7 @@
 
 struct orion_mdio_dev {
 	struct mutex lock;
-	void __iomem *smireg;
+	void __iomem *regs;
 };
 
 /* Wait for the SMI unit to be ready for another operation
@@ -51,7 +51,7 @@ static int orion_mdio_wait_ready(struct mii_bus *bus)
 
 	count = 0;
 	while (1) {
-		val = readl(dev->smireg);
+		val = readl(dev->regs);
 		if (!(val & MVMDIO_SMI_BUSY))
 			break;
 
@@ -86,12 +86,12 @@ static int orion_mdio_read(struct mii_bus *bus, int mii_id,
 	writel(((mii_id << MVMDIO_SMI_PHY_ADDR_SHIFT) |
 		(regnum << MVMDIO_SMI_PHY_REG_SHIFT)  |
 		MVMDIO_SMI_READ_OPERATION),
-	       dev->smireg);
+	       dev->regs);
 
 	/* Wait for the value to become available */
 	count = 0;
 	while (1) {
-		val = readl(dev->smireg);
+		val = readl(dev->regs);
 		if (val & MVMDIO_SMI_READ_VALID)
 			break;
 
@@ -128,7 +128,7 @@ static int orion_mdio_write(struct mii_bus *bus, int mii_id,
 		(regnum << MVMDIO_SMI_PHY_REG_SHIFT)  |
 		MVMDIO_SMI_WRITE_OPERATION            |
 		(value << MVMDIO_SMI_DATA_SHIFT)),
-	       dev->smireg);
+	       dev->regs);
 
 	mutex_unlock(&dev->lock);
 
@@ -177,8 +177,8 @@ static int orion_mdio_probe(struct platform_device *pdev)
 		bus->irq[i] = PHY_POLL;
 
 	dev = bus->priv;
-	dev->smireg = devm_ioremap(&pdev->dev, r->start, resource_size(r));
-	if (!dev->smireg) {
+	dev->regs = devm_ioremap(&pdev->dev, r->start, resource_size(r));
+	if (!dev->regs) {
 		dev_err(&pdev->dev, "Unable to remap SMI register\n");
 		kfree(bus->irq);
 		mdiobus_free(bus);
-- 
1.7.10.4

^ permalink raw reply related

* [PATCH 3/4 v2] net: mvmdio: enhance driver to support SMI error/done interrupts
From: Florian Fainelli @ 2013-03-14 18:08 UTC (permalink / raw)
  To: davem
  Cc: Thomas Petazzoni, Andrew Lunn, Russell King, Jason Cooper,
	linux-doc, devicetree-discuss, linux-kernel, Rob Herring, netdev,
	Paul Mackerras, linux-arm-kernel, Rob Landley, Greg Kroah-Hartman,
	linuxppc-dev, Florian Fainelli, Lennert Buytenhek
In-Reply-To: <1363284515-9865-1-git-send-email-florian@openwrt.org>

This patch enhances the "mvmdio" to support a SMI error/done interrupt
line which can be used along with a wait queue instead of doing
busy-waiting on the registers. This is a feature which is available in
the mv643xx_eth SMI code and thus reduces again the gap between the two.

Signed-off-by: Florian Fainelli <florian@openwrt.org>
---
Chances since v1:
- always use orion_smi_is_done() helper
- make interrupt/non-interrupt code path entirely independant

 .../devicetree/bindings/net/marvell-orion-mdio.txt |    3 +
 drivers/net/ethernet/marvell/mvmdio.c              |   83 +++++++++++++++++---
 2 files changed, 74 insertions(+), 12 deletions(-)

diff --git a/Documentation/devicetree/bindings/net/marvell-orion-mdio.txt b/Documentation/devicetree/bindings/net/marvell-orion-mdio.txt
index 34e7aaf..052b5f2 100644
--- a/Documentation/devicetree/bindings/net/marvell-orion-mdio.txt
+++ b/Documentation/devicetree/bindings/net/marvell-orion-mdio.txt
@@ -9,6 +9,9 @@ Required properties:
 - compatible: "marvell,orion-mdio"
 - reg: address and length of the SMI register
 
+Optional properties:
+- interrupts: interrupt line number for the SMI error/done interrupt
+
 The child nodes of the MDIO driver are the individual PHY devices
 connected to this MDIO bus. They must have a "reg" property given the
 PHY address on the MDIO bus.
diff --git a/drivers/net/ethernet/marvell/mvmdio.c b/drivers/net/ethernet/marvell/mvmdio.c
index 595deea..7ac83de 100644
--- a/drivers/net/ethernet/marvell/mvmdio.c
+++ b/drivers/net/ethernet/marvell/mvmdio.c
@@ -24,9 +24,12 @@
 #include <linux/module.h>
 #include <linux/mutex.h>
 #include <linux/phy.h>
+#include <linux/interrupt.h>
 #include <linux/platform_device.h>
 #include <linux/delay.h>
 #include <linux/io.h>
+#include <linux/sched.h>
+#include <linux/wait.h>
 
 #define MVMDIO_SMI_DATA_SHIFT              0
 #define MVMDIO_SMI_PHY_ADDR_SHIFT          16
@@ -35,33 +38,58 @@
 #define MVMDIO_SMI_WRITE_OPERATION         0
 #define MVMDIO_SMI_READ_VALID              BIT(27)
 #define MVMDIO_SMI_BUSY                    BIT(28)
+#define MVMDIO_ERR_INT_CAUSE		   0x007C
+#define  MVMDIO_ERR_INT_SMI_DONE	   0x00000010
+#define MVMDIO_ERR_INT_MASK		   0x0080
 
 struct orion_mdio_dev {
 	struct mutex lock;
 	void __iomem *regs;
+	/*
+	 * If we have access to the error interrupt pin (which is
+	 * somewhat misnamed as it not only reflects internal errors
+	 * but also reflects SMI completion), use that to wait for
+	 * SMI access completion instead of polling the SMI busy bit.
+	 */
+	int err_interrupt;
+	wait_queue_head_t smi_busy_wait;
 };
 
+static int orion_mdio_smi_is_done(struct orion_mdio_dev *dev)
+{
+	return !(readl(dev->regs) & MVMDIO_SMI_BUSY);
+}
+
 /* Wait for the SMI unit to be ready for another operation
  */
 static int orion_mdio_wait_ready(struct mii_bus *bus)
 {
 	struct orion_mdio_dev *dev = bus->priv;
 	int count;
-	u32 val;
 
-	count = 0;
-	while (1) {
-		val = readl(dev->regs);
-		if (!(val & MVMDIO_SMI_BUSY))
-			break;
+	if (dev->err_interrupt == NO_IRQ) {
+		count = 0;
+		while (1) {
+			if (orion_mdio_smi_is_done(dev))
+				break;
 
-		if (count > 100) {
-			dev_err(bus->parent, "Timeout: SMI busy for too long\n");
-			return -ETIMEDOUT;
-		}
+			if (count > 100) {
+				dev_err(bus->parent,
+					"Timeout: SMI busy for too long\n");
+				return -ETIMEDOUT;
+			}
 
-		udelay(10);
-		count++;
+			udelay(10);
+			count++;
+		}
+	} else {
+		if (!orion_mdio_smi_is_done(dev)) {
+			wait_event_timeout(dev->smi_busy_wait,
+				orion_mdio_smi_is_done(dev),
+				msecs_to_jiffies(100));
+			if (!orion_mdio_smi_is_done(dev))
+				return -ETIMEDOUT;
+		}
 	}
 
 	return 0;
@@ -140,6 +168,21 @@ static int orion_mdio_reset(struct mii_bus *bus)
 	return 0;
 }
 
+static irqreturn_t orion_mdio_err_irq(int irq, void *dev_id)
+{
+	struct orion_mdio_dev *dev = dev_id;
+
+	if (readl(dev->regs + MVMDIO_ERR_INT_CAUSE) &
+			MVMDIO_ERR_INT_SMI_DONE) {
+		writel(~MVMDIO_ERR_INT_SMI_DONE,
+				dev->regs + MVMDIO_ERR_INT_CAUSE);
+		wake_up(&dev->smi_busy_wait);
+		return IRQ_HANDLED;
+	}
+
+	return IRQ_NONE;
+}
+
 static int orion_mdio_probe(struct platform_device *pdev)
 {
 	struct resource *r;
@@ -185,6 +228,19 @@ static int orion_mdio_probe(struct platform_device *pdev)
 		return -ENODEV;
 	}
 
+	init_waitqueue_head(&dev->smi_busy_wait);
+
+	dev->err_interrupt = platform_get_irq(pdev, 0);
+	if (dev->err_interrupt != -ENXIO) {
+		ret = devm_request_irq(&pdev->dev, dev->err_interrupt,
+					orion_mdio_err_irq,
+					IRQF_SHARED, pdev->name, dev);
+		if (!ret)
+			writel(MVMDIO_ERR_INT_SMI_DONE,
+					dev->regs + MVMDIO_ERR_INT_MASK);
+	} else
+		dev->err_interrupt = NO_IRQ;
+
 	mutex_init(&dev->lock);
 
 	ret = mdiobus_register(bus);
@@ -203,6 +259,9 @@ static int orion_mdio_probe(struct platform_device *pdev)
 static int orion_mdio_remove(struct platform_device *pdev)
 {
 	struct mii_bus *bus = platform_get_drvdata(pdev);
+	struct orion_mdio_dev *dev = bus->priv;
+
+	writel(0, dev->regs + MVMDIO_ERR_INT_MASK);
 	mdiobus_unregister(bus);
 	kfree(bus->irq);
 	mdiobus_free(bus);
-- 
1.7.10.4

^ permalink raw reply related

* [PATCH 4/4 v2] mv643xx_eth: convert to use the Marvell Orion MDIO driver
From: Florian Fainelli @ 2013-03-14 18:08 UTC (permalink / raw)
  To: davem
  Cc: Thomas Petazzoni, Andrew Lunn, Russell King, Jason Cooper,
	linux-doc, devicetree-discuss, linux-kernel, Rob Herring, netdev,
	Paul Mackerras, linux-arm-kernel, Rob Landley, Greg Kroah-Hartman,
	linuxppc-dev, Florian Fainelli, Lennert Buytenhek
In-Reply-To: <1363284515-9865-1-git-send-email-florian@openwrt.org>

This patch converts the Marvell MV643XX ethernet driver to use the
Marvell Orion MDIO driver. As a result, PowerPC and ARM platforms
registering the Marvell MV643XX ethernet driver are also updated to
register a Marvell Orion MDIO driver. This driver voluntarily overlaps
with the Marvell Ethernet shared registers because it will use a subset
of this shared register (shared_base + 0x4 - shared_base + 0x84). The
Ethernet driver is also updated to look up for a PHY device using the
Orion MDIO bus driver.

Signed-off-by: Florian Fainelli <florian@openwrt.org>
---
Changes since v1:
- removed one too many mdio bus registration for Orion5x/Kirkwood

 arch/arm/plat-orion/common.c               |   97 +++++++++++----
 arch/powerpc/platforms/chrp/pegasos_eth.c  |   20 +++
 arch/powerpc/sysdev/mv64x60_dev.c          |   14 ++-
 drivers/net/ethernet/marvell/Kconfig       |    1 +
 drivers/net/ethernet/marvell/mv643xx_eth.c |  186 ++--------------------------
 include/linux/mv643xx_eth.h                |    1 -
 6 files changed, 117 insertions(+), 202 deletions(-)

diff --git a/arch/arm/plat-orion/common.c b/arch/arm/plat-orion/common.c
index 2d4b641..dc4345e 100644
--- a/arch/arm/plat-orion/common.c
+++ b/arch/arm/plat-orion/common.c
@@ -238,6 +238,7 @@ static __init void ge_complete(
 	struct mv643xx_eth_shared_platform_data *orion_ge_shared_data,
 	struct resource *orion_ge_resource, unsigned long irq,
 	struct platform_device *orion_ge_shared,
+	struct platform_device *orion_ge_mvmdio,
 	struct mv643xx_eth_platform_data *eth_data,
 	struct platform_device *orion_ge)
 {
@@ -247,6 +248,8 @@ static __init void ge_complete(
 	orion_ge->dev.platform_data = eth_data;
 
 	platform_device_register(orion_ge_shared);
+	if (orion_ge_mvmdio)
+		platform_device_register(orion_ge_mvmdio);
 	platform_device_register(orion_ge);
 }
 
@@ -258,8 +261,6 @@ struct mv643xx_eth_shared_platform_data orion_ge00_shared_data;
 static struct resource orion_ge00_shared_resources[] = {
 	{
 		.name	= "ge00 base",
-	}, {
-		.name	= "ge00 err irq",
 	},
 };
 
@@ -271,6 +272,19 @@ static struct platform_device orion_ge00_shared = {
 	},
 };
 
+static struct resource orion_ge00_mvmdio_resources[] = {
+	{
+		.name	= "ge00 mvmdio base",
+	}, {
+		.name	= "ge00 mvmdio irr irq",
+	},
+};
+
+static struct platform_device orion_ge00_mvmdio = {
+	.name		= "orion-mdio",
+	.id		= 0,
+};
+
 static struct resource orion_ge00_resources[] = {
 	{
 		.name	= "ge00 irq",
@@ -295,26 +309,25 @@ void __init orion_ge00_init(struct mv643xx_eth_platform_data *eth_data,
 			    unsigned int tx_csum_limit)
 {
 	fill_resources(&orion_ge00_shared, orion_ge00_shared_resources,
-		       mapbase + 0x2000, SZ_16K - 1, irq_err);
+		       mapbase + 0x2000, SZ_16K - 1, NO_IRQ);
+	fill_resources(&orion_ge00_mvmdio, orion_ge00_mvmdio_resources,
+			mapbase + 0x2004, 0x84 - 1, irq_err);
 	orion_ge00_shared_data.tx_csum_limit = tx_csum_limit;
 	ge_complete(&orion_ge00_shared_data,
 		    orion_ge00_resources, irq, &orion_ge00_shared,
+		    &orion_ge00_mvmdio,
 		    eth_data, &orion_ge00);
 }
 
 /*****************************************************************************
  * GE01
  ****************************************************************************/
-struct mv643xx_eth_shared_platform_data orion_ge01_shared_data = {
-	.shared_smi	= &orion_ge00_shared,
-};
+struct mv643xx_eth_shared_platform_data orion_ge01_shared_data;
 
 static struct resource orion_ge01_shared_resources[] = {
 	{
 		.name	= "ge01 base",
-	}, {
-		.name	= "ge01 err irq",
-	},
+	}
 };
 
 static struct platform_device orion_ge01_shared = {
@@ -325,6 +338,19 @@ static struct platform_device orion_ge01_shared = {
 	},
 };
 
+static struct resource orion_ge01_mvmdio_resources[] = {
+	{
+		.name	= "ge01 mdio base",
+	}, {
+		.name	= "ge01 mdio err irq",
+	},
+};
+
+static struct platform_device orion_ge01_mvmdio = {
+	.name		= "orion-mdio",
+	.id		= 1,
+};
+
 static struct resource orion_ge01_resources[] = {
 	{
 		.name	= "ge01 irq",
@@ -349,26 +375,25 @@ void __init orion_ge01_init(struct mv643xx_eth_platform_data *eth_data,
 			    unsigned int tx_csum_limit)
 {
 	fill_resources(&orion_ge01_shared, orion_ge01_shared_resources,
-		       mapbase + 0x2000, SZ_16K - 1, irq_err);
+		       mapbase + 0x2000, SZ_16K - 1, NO_IRQ);
+	fill_resources(&orion_ge01_mvmdio, orion_ge01_mvmdio_resources,
+			mapbase + 0x2004, 0x84 - 1, irq_err);
 	orion_ge01_shared_data.tx_csum_limit = tx_csum_limit;
 	ge_complete(&orion_ge01_shared_data,
 		    orion_ge01_resources, irq, &orion_ge01_shared,
+		    NULL,
 		    eth_data, &orion_ge01);
 }
 
 /*****************************************************************************
  * GE10
  ****************************************************************************/
-struct mv643xx_eth_shared_platform_data orion_ge10_shared_data = {
-	.shared_smi	= &orion_ge00_shared,
-};
+struct mv643xx_eth_shared_platform_data orion_ge10_shared_data;
 
 static struct resource orion_ge10_shared_resources[] = {
 	{
 		.name	= "ge10 base",
-	}, {
-		.name	= "ge10 err irq",
-	},
+	}
 };
 
 static struct platform_device orion_ge10_shared = {
@@ -379,6 +404,19 @@ static struct platform_device orion_ge10_shared = {
 	},
 };
 
+static struct resource orion_ge10_mvmdio_resources[] = {
+	{
+		.name	= "ge10 mvmdio base",
+	}, {
+		.name	= "ge10 mvmdio err irq",
+	},
+};
+
+static struct platform_device orion_ge10_mvmdio = {
+	.name		= "orion-mdio",
+	.id		= 1,
+};
+
 static struct resource orion_ge10_resources[] = {
 	{
 		.name	= "ge10 irq",
@@ -403,23 +441,22 @@ void __init orion_ge10_init(struct mv643xx_eth_platform_data *eth_data,
 {
 	fill_resources(&orion_ge10_shared, orion_ge10_shared_resources,
 		       mapbase + 0x2000, SZ_16K - 1, irq_err);
+	fill_resources(&orion_ge10_mvmdio, orion_ge10_mvmdio_resources,
+		       mapbase + 0x2004, 0x84 - 1, irq_err);
 	ge_complete(&orion_ge10_shared_data,
 		    orion_ge10_resources, irq, &orion_ge10_shared,
+		    &orion_ge10_mvmdio,
 		    eth_data, &orion_ge10);
 }
 
 /*****************************************************************************
  * GE11
  ****************************************************************************/
-struct mv643xx_eth_shared_platform_data orion_ge11_shared_data = {
-	.shared_smi	= &orion_ge00_shared,
-};
+struct mv643xx_eth_shared_platform_data orion_ge11_shared_data;
 
 static struct resource orion_ge11_shared_resources[] = {
 	{
 		.name	= "ge11 base",
-	}, {
-		.name	= "ge11 err irq",
 	},
 };
 
@@ -431,6 +468,19 @@ static struct platform_device orion_ge11_shared = {
 	},
 };
 
+static struct resource orion_ge11_mvmdio_resources[] = {
+	{
+		.name	= "ge11 mvmdio base",
+	}, {
+		.name	= "ge11 mvmdio err irq",
+	},
+};
+
+static struct platform_device orion_ge11_mvmdio = {
+	.name		= "orion-mdio",
+	.id		= 1,
+};
+
 static struct resource orion_ge11_resources[] = {
 	{
 		.name	= "ge11 irq",
@@ -454,9 +504,12 @@ void __init orion_ge11_init(struct mv643xx_eth_platform_data *eth_data,
 			    unsigned long irq_err)
 {
 	fill_resources(&orion_ge11_shared, orion_ge11_shared_resources,
-		       mapbase + 0x2000, SZ_16K - 1, irq_err);
+		       mapbase + 0x2000, SZ_16K - 1, NO_IRQ);
+	fill_resources(&orion_ge11_mvmdio, orion_ge11_mvmdio_resources,
+		       mapbase + 0x2004, 0x84 - 1, irq_err);
 	ge_complete(&orion_ge11_shared_data,
 		    orion_ge11_resources, irq, &orion_ge11_shared,
+		    NULL,
 		    eth_data, &orion_ge11);
 }
 
diff --git a/arch/powerpc/platforms/chrp/pegasos_eth.c b/arch/powerpc/platforms/chrp/pegasos_eth.c
index 039fc8e..a671508 100644
--- a/arch/powerpc/platforms/chrp/pegasos_eth.c
+++ b/arch/powerpc/platforms/chrp/pegasos_eth.c
@@ -47,6 +47,25 @@ static struct platform_device mv643xx_eth_shared_device = {
 	.resource	= mv643xx_eth_shared_resources,
 };
 
+/*
+ * The orion mdio driver only covers shared + 0x4 up to shared + 0x84 - 1
+ */
+static struct resource mv643xx_eth_mvmdio_resources[] = {
+	[0] = {
+		.name	= "ethernet mdio base",
+		.start	= 0xf1000000 + MV643XX_ETH_SHARED_REGS + 0x4,
+		.end	= 0xf1000000 + MV643XX_ETH_SHARED_REGS + 0x83,
+		.flags	= IORESOURCE_MEM,
+	},
+};
+
+static struct platform_device mv643xx_eth_mvmdio_device = {
+	.name		= "orion-mdio",
+	.id		= 0,
+	.num_resources	= ARRAY_SIZE(mv643xx_eth_mvmdio_resources),
+	.resource	= mv643xx_eth_shared_resources,
+};
+
 static struct resource mv643xx_eth_port1_resources[] = {
 	[0] = {
 		.name	= "eth port1 irq",
@@ -82,6 +101,7 @@ static struct platform_device eth_port1_device = {
 
 static struct platform_device *mv643xx_eth_pd_devs[] __initdata = {
 	&mv643xx_eth_shared_device,
+	&mv643xx_eth_mvmdio_device,
 	&eth_port1_device,
 };
 
diff --git a/arch/powerpc/sysdev/mv64x60_dev.c b/arch/powerpc/sysdev/mv64x60_dev.c
index 0f6af41..630cea3 100644
--- a/arch/powerpc/sysdev/mv64x60_dev.c
+++ b/arch/powerpc/sysdev/mv64x60_dev.c
@@ -214,15 +214,25 @@ static struct platform_device * __init mv64x60_eth_register_shared_pdev(
 						struct device_node *np, int id)
 {
 	struct platform_device *pdev;
-	struct resource r[1];
+	struct resource r[2];
 	int err;
 
 	err = of_address_to_resource(np, 0, &r[0]);
 	if (err)
 		return ERR_PTR(err);
 
+	/* register an orion mdio bus driver */
+	r[1].start = r[0].start + 0x4;
+	r[1].end = r[0].start + 0x84 - 1;
+	r[1].flags = IORESOURCE_MEM;
+
+	pdev = platform_device_register_simple("orion-mdio", id, &r[1], 1);
+	if (!pdev)
+		return pdev;
+
 	pdev = platform_device_register_simple(MV643XX_ETH_SHARED_NAME, id,
-					       r, 1);
+					       &r[0], 1);
+
 	return pdev;
 }
 
diff --git a/drivers/net/ethernet/marvell/Kconfig b/drivers/net/ethernet/marvell/Kconfig
index edfba93..df06061 100644
--- a/drivers/net/ethernet/marvell/Kconfig
+++ b/drivers/net/ethernet/marvell/Kconfig
@@ -23,6 +23,7 @@ config MV643XX_ETH
 	depends on (MV64X60 || PPC32 || PLAT_ORION) && INET
 	select INET_LRO
 	select PHYLIB
+	select MVMDIO
 	---help---
 	  This driver supports the gigabit ethernet MACs in the
 	  Marvell Discovery PPC/MIPS chipset family (MV643XX) and
diff --git a/drivers/net/ethernet/marvell/mv643xx_eth.c b/drivers/net/ethernet/marvell/mv643xx_eth.c
index d1ecf4b..df04bee 100644
--- a/drivers/net/ethernet/marvell/mv643xx_eth.c
+++ b/drivers/net/ethernet/marvell/mv643xx_eth.c
@@ -69,14 +69,6 @@ static char mv643xx_eth_driver_version[] = "1.4";
  * Registers shared between all ports.
  */
 #define PHY_ADDR			0x0000
-#define SMI_REG				0x0004
-#define  SMI_BUSY			0x10000000
-#define  SMI_READ_VALID			0x08000000
-#define  SMI_OPCODE_READ		0x04000000
-#define  SMI_OPCODE_WRITE		0x00000000
-#define ERR_INT_CAUSE			0x0080
-#define  ERR_INT_SMI_DONE		0x00000010
-#define ERR_INT_MASK			0x0084
 #define WINDOW_BASE(w)			(0x0200 + ((w) << 3))
 #define WINDOW_SIZE(w)			(0x0204 + ((w) << 3))
 #define WINDOW_REMAP_HIGH(w)		(0x0280 + ((w) << 2))
@@ -266,25 +258,6 @@ struct mv643xx_eth_shared_private {
 	void __iomem *base;
 
 	/*
-	 * Points at the right SMI instance to use.
-	 */
-	struct mv643xx_eth_shared_private *smi;
-
-	/*
-	 * Provides access to local SMI interface.
-	 */
-	struct mii_bus *smi_bus;
-
-	/*
-	 * If we have access to the error interrupt pin (which is
-	 * somewhat misnamed as it not only reflects internal errors
-	 * but also reflects SMI completion), use that to wait for
-	 * SMI access completion instead of polling the SMI busy bit.
-	 */
-	int err_interrupt;
-	wait_queue_head_t smi_busy_wait;
-
-	/*
 	 * Per-port MBUS window access register value.
 	 */
 	u32 win_protect;
@@ -1122,97 +1095,6 @@ out_write:
 	wrlp(mp, PORT_SERIAL_CONTROL, pscr);
 }
 
-static irqreturn_t mv643xx_eth_err_irq(int irq, void *dev_id)
-{
-	struct mv643xx_eth_shared_private *msp = dev_id;
-
-	if (readl(msp->base + ERR_INT_CAUSE) & ERR_INT_SMI_DONE) {
-		writel(~ERR_INT_SMI_DONE, msp->base + ERR_INT_CAUSE);
-		wake_up(&msp->smi_busy_wait);
-		return IRQ_HANDLED;
-	}
-
-	return IRQ_NONE;
-}
-
-static int smi_is_done(struct mv643xx_eth_shared_private *msp)
-{
-	return !(readl(msp->base + SMI_REG) & SMI_BUSY);
-}
-
-static int smi_wait_ready(struct mv643xx_eth_shared_private *msp)
-{
-	if (msp->err_interrupt == NO_IRQ) {
-		int i;
-
-		for (i = 0; !smi_is_done(msp); i++) {
-			if (i == 10)
-				return -ETIMEDOUT;
-			msleep(10);
-		}
-
-		return 0;
-	}
-
-	if (!smi_is_done(msp)) {
-		wait_event_timeout(msp->smi_busy_wait, smi_is_done(msp),
-				   msecs_to_jiffies(100));
-		if (!smi_is_done(msp))
-			return -ETIMEDOUT;
-	}
-
-	return 0;
-}
-
-static int smi_bus_read(struct mii_bus *bus, int addr, int reg)
-{
-	struct mv643xx_eth_shared_private *msp = bus->priv;
-	void __iomem *smi_reg = msp->base + SMI_REG;
-	int ret;
-
-	if (smi_wait_ready(msp)) {
-		pr_warn("SMI bus busy timeout\n");
-		return -ETIMEDOUT;
-	}
-
-	writel(SMI_OPCODE_READ | (reg << 21) | (addr << 16), smi_reg);
-
-	if (smi_wait_ready(msp)) {
-		pr_warn("SMI bus busy timeout\n");
-		return -ETIMEDOUT;
-	}
-
-	ret = readl(smi_reg);
-	if (!(ret & SMI_READ_VALID)) {
-		pr_warn("SMI bus read not valid\n");
-		return -ENODEV;
-	}
-
-	return ret & 0xffff;
-}
-
-static int smi_bus_write(struct mii_bus *bus, int addr, int reg, u16 val)
-{
-	struct mv643xx_eth_shared_private *msp = bus->priv;
-	void __iomem *smi_reg = msp->base + SMI_REG;
-
-	if (smi_wait_ready(msp)) {
-		pr_warn("SMI bus busy timeout\n");
-		return -ETIMEDOUT;
-	}
-
-	writel(SMI_OPCODE_WRITE | (reg << 21) |
-		(addr << 16) | (val & 0xffff), smi_reg);
-
-	if (smi_wait_ready(msp)) {
-		pr_warn("SMI bus busy timeout\n");
-		return -ETIMEDOUT;
-	}
-
-	return 0;
-}
-
-
 /* statistics ***************************************************************/
 static struct net_device_stats *mv643xx_eth_get_stats(struct net_device *dev)
 {
@@ -2688,47 +2570,6 @@ static int mv643xx_eth_shared_probe(struct platform_device *pdev)
 		goto out_free;
 
 	/*
-	 * Set up and register SMI bus.
-	 */
-	if (pd == NULL || pd->shared_smi == NULL) {
-		msp->smi_bus = mdiobus_alloc();
-		if (msp->smi_bus == NULL)
-			goto out_unmap;
-
-		msp->smi_bus->priv = msp;
-		msp->smi_bus->name = "mv643xx_eth smi";
-		msp->smi_bus->read = smi_bus_read;
-		msp->smi_bus->write = smi_bus_write,
-		snprintf(msp->smi_bus->id, MII_BUS_ID_SIZE, "%s-%d",
-			pdev->name, pdev->id);
-		msp->smi_bus->parent = &pdev->dev;
-		msp->smi_bus->phy_mask = 0xffffffff;
-		if (mdiobus_register(msp->smi_bus) < 0)
-			goto out_free_mii_bus;
-		msp->smi = msp;
-	} else {
-		msp->smi = platform_get_drvdata(pd->shared_smi);
-	}
-
-	msp->err_interrupt = NO_IRQ;
-	init_waitqueue_head(&msp->smi_busy_wait);
-
-	/*
-	 * Check whether the error interrupt is hooked up.
-	 */
-	res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
-	if (res != NULL) {
-		int err;
-
-		err = request_irq(res->start, mv643xx_eth_err_irq,
-				  IRQF_SHARED, "mv643xx_eth", msp);
-		if (!err) {
-			writel(ERR_INT_SMI_DONE, msp->base + ERR_INT_MASK);
-			msp->err_interrupt = res->start;
-		}
-	}
-
-	/*
 	 * (Re-)program MBUS remapping windows if we are asked to.
 	 */
 	dram = mv_mbus_dram_info();
@@ -2743,10 +2584,6 @@ static int mv643xx_eth_shared_probe(struct platform_device *pdev)
 
 	return 0;
 
-out_free_mii_bus:
-	mdiobus_free(msp->smi_bus);
-out_unmap:
-	iounmap(msp->base);
 out_free:
 	kfree(msp);
 out:
@@ -2756,14 +2593,7 @@ out:
 static int mv643xx_eth_shared_remove(struct platform_device *pdev)
 {
 	struct mv643xx_eth_shared_private *msp = platform_get_drvdata(pdev);
-	struct mv643xx_eth_shared_platform_data *pd = pdev->dev.platform_data;
 
-	if (pd == NULL || pd->shared_smi == NULL) {
-		mdiobus_unregister(msp->smi_bus);
-		mdiobus_free(msp->smi_bus);
-	}
-	if (msp->err_interrupt != NO_IRQ)
-		free_irq(msp->err_interrupt, msp);
 	iounmap(msp->base);
 	kfree(msp);
 
@@ -2829,11 +2659,11 @@ static void set_params(struct mv643xx_eth_private *mp,
 static struct phy_device *phy_scan(struct mv643xx_eth_private *mp,
 				   int phy_addr)
 {
-	struct mii_bus *bus = mp->shared->smi->smi_bus;
 	struct phy_device *phydev;
 	int start;
 	int num;
 	int i;
+	char phy_id[MII_BUS_ID_SIZE + 3];
 
 	if (phy_addr == MV643XX_ETH_PHY_ADDR_DEFAULT) {
 		start = phy_addr_get(mp) & 0x1f;
@@ -2843,17 +2673,19 @@ static struct phy_device *phy_scan(struct mv643xx_eth_private *mp,
 		num = 1;
 	}
 
+	/* Attempt to connect to the PHY using orion-mdio */
 	phydev = NULL;
 	for (i = 0; i < num; i++) {
 		int addr = (start + i) & 0x1f;
 
-		if (bus->phy_map[addr] == NULL)
-			mdiobus_scan(bus, addr);
+		snprintf(phy_id, sizeof(phy_id), PHY_ID_FMT,
+				"orion-mdio-mii", addr);
 
-		if (phydev == NULL) {
-			phydev = bus->phy_map[addr];
-			if (phydev != NULL)
-				phy_addr_set(mp, addr);
+		phydev = phy_connect(mp->dev, phy_id, NULL,
+				PHY_INTERFACE_MODE_GMII);
+		if (!IS_ERR(phydev)) {
+			phy_addr_set(mp, addr);
+			break;
 		}
 	}
 
diff --git a/include/linux/mv643xx_eth.h b/include/linux/mv643xx_eth.h
index 49258e0..141d395 100644
--- a/include/linux/mv643xx_eth.h
+++ b/include/linux/mv643xx_eth.h
@@ -19,7 +19,6 @@
 
 struct mv643xx_eth_shared_platform_data {
 	struct mbus_dram_target_info	*dram;
-	struct platform_device	*shared_smi;
 	/*
 	 * Max packet size for Tx IP/Layer 4 checksum, when set to 0, default
 	 * limit of 9KiB will be used.
-- 
1.7.10.4

^ permalink raw reply related

* Re: [PATCH 0/5] mv643xx_eth: use mvmdio MDIO bus driver
From: Florian Fainelli @ 2013-03-14 18:09 UTC (permalink / raw)
  To: Jason Cooper
  Cc: Thomas Petazzoni, Andrew Lunn, Russell King, linux-doc,
	devicetree-discuss, linux-kernel, Rob Herring, Greg Kroah-Hartman,
	Paul Mackerras, Lennert Buytenhek, Rob Landley, netdev,
	linuxppc-dev, davem, linux-arm-kernel
In-Reply-To: <20130314172544.GT12700@titan.lakedaemon.net>

Hello Jason,

Le 03/14/13 18:25, Jason Cooper a écrit :
> Florian,
>
> Any word on version 2 of this series?  I'd like to base the conversion
> of kirkwood to DT based ethernet init on it.

Just sent them out for review, thanks for reminder, they were sitting in 
my tree for a couple days already.
--
Florian

^ permalink raw reply

* [PATCH 1/4 v2] net: mvmdio: allow platform device style registration
From: Florian Fainelli @ 2013-03-14 18:11 UTC (permalink / raw)
  To: davem
  Cc: Thomas Petazzoni, Andrew Lunn, Russell King, Jason Cooper,
	linux-doc, devicetree-discuss, linux-kernel, Rob Herring, netdev,
	Paul Mackerras, linux-arm-kernel, Rob Landley, Greg Kroah-Hartman,
	linuxppc-dev, Florian Fainelli, Lennert Buytenhek
In-Reply-To: <1363284515-9865-1-git-send-email-florian@openwrt.org>

This patch changes the mvmdio driver not to use device tree
helper functions such as of_mdiobus_register() and of_iomap() so we can
instantiate this driver using a classic platform_device approach. Use
the device manager helper to ioremap() the base register cookie so we
get automatic freeing upon error and removal. This change is harmless
for Device Tree platforms because they will get the driver be registered
the same way as it was before.

Signed-off-by: Florian Fainelli <florian@openwrt.org>
---
Changes since v1:
- use device managed helpers to fix an ioremap leak in remove function
- remove the use of Device Tree specific helpers to allow platform-style
  registration

 drivers/net/ethernet/marvell/mvmdio.c |   18 +++++++++++-------
 1 file changed, 11 insertions(+), 7 deletions(-)

diff --git a/drivers/net/ethernet/marvell/mvmdio.c b/drivers/net/ethernet/marvell/mvmdio.c
index 77b7c80..8a182f1 100644
--- a/drivers/net/ethernet/marvell/mvmdio.c
+++ b/drivers/net/ethernet/marvell/mvmdio.c
@@ -24,10 +24,9 @@
 #include <linux/module.h>
 #include <linux/mutex.h>
 #include <linux/phy.h>
-#include <linux/of_address.h>
-#include <linux/of_mdio.h>
 #include <linux/platform_device.h>
 #include <linux/delay.h>
+#include <linux/io.h>
 
 #define MVMDIO_SMI_DATA_SHIFT              0
 #define MVMDIO_SMI_PHY_ADDR_SHIFT          16
@@ -143,11 +142,17 @@ static int orion_mdio_reset(struct mii_bus *bus)
 
 static int orion_mdio_probe(struct platform_device *pdev)
 {
-	struct device_node *np = pdev->dev.of_node;
+	struct resource *r;
 	struct mii_bus *bus;
 	struct orion_mdio_dev *dev;
 	int i, ret;
 
+	r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!r) {
+		dev_err(&pdev->dev, "No SMI register address given\n");
+		return -ENODEV;
+	}
+
 	bus = mdiobus_alloc_size(sizeof(struct orion_mdio_dev));
 	if (!bus) {
 		dev_err(&pdev->dev, "Cannot allocate MDIO bus\n");
@@ -172,9 +177,9 @@ static int orion_mdio_probe(struct platform_device *pdev)
 		bus->irq[i] = PHY_POLL;
 
 	dev = bus->priv;
-	dev->smireg = of_iomap(pdev->dev.of_node, 0);
+	dev->smireg = devm_ioremap(&pdev->dev, r->start, resource_size(r));
 	if (!dev->smireg) {
-		dev_err(&pdev->dev, "No SMI register address given in DT\n");
+		dev_err(&pdev->dev, "Unable to remap SMI register\n");
 		kfree(bus->irq);
 		mdiobus_free(bus);
 		return -ENODEV;
@@ -182,10 +187,9 @@ static int orion_mdio_probe(struct platform_device *pdev)
 
 	mutex_init(&dev->lock);
 
-	ret = of_mdiobus_register(bus, np);
+	ret = mdiobus_register(bus);
 	if (ret < 0) {
 		dev_err(&pdev->dev, "Cannot register MDIO bus (%d)\n", ret);
-		iounmap(dev->smireg);
 		kfree(bus->irq);
 		mdiobus_free(bus);
 		return ret;
-- 
1.7.10.4

^ permalink raw reply related

* Re: [PATCH 0/5] mv643xx_eth: use mvmdio MDIO bus driver
From: Jason Cooper @ 2013-03-14 18:16 UTC (permalink / raw)
  To: Florian Fainelli
  Cc: Thomas Petazzoni, Andrew Lunn, Russell King, linux-doc,
	devicetree-discuss, linux-kernel, Rob Herring, Greg Kroah-Hartman,
	Paul Mackerras, Lennert Buytenhek, Rob Landley, netdev,
	linuxppc-dev, davem, linux-arm-kernel
In-Reply-To: <5142124E.7050909@openwrt.org>

On Thu, Mar 14, 2013 at 07:09:18PM +0100, Florian Fainelli wrote:
> Hello Jason,
>=20
> Le 03/14/13 18:25, Jason Cooper a =E9crit :
> >Florian,
> >
> >Any word on version 2 of this series?  I'd like to base the conversion
> >of kirkwood to DT based ethernet init on it.
>=20
> Just sent them out for review, thanks for reminder, they were
> sitting in my tree for a couple days already.

Great!  I'll give this a spin.

thx,

Jason.

^ permalink raw reply

* Re: [PATCH 2/2] ppc64: Add arch-specific pcie_get_speed_cap_mask
From: Thadeu Lima de Souza Cascardo @ 2013-03-14 18:52 UTC (permalink / raw)
  To: lucaskt
  Cc: linux-pci, linuxppc-dev, dri-devel, brking, Alex Deucher,
	Bjorn Helgaas
In-Reply-To: <1363283147-8852-3-git-send-email-lucaskt@linux.vnet.ibm.com>

On Thu, Mar 14, 2013 at 02:45:47PM -0300, lucaskt@linux.vnet.ibm.com wrote:
> From: Lucas Kannebley Tavares <lucaskt@linux.vnet.ibm.com>
> 
> Betters support for gen2 speed detections on PCI buses on ppc64
> architectures.
> 
> Signed-off-by: Lucas Kannebley Tavares <lucaskt@linux.vnet.ibm.com>
> ---
>  arch/powerpc/platforms/pseries/pci.c |   32 ++++++++++++++++++++++++++++++++
>  1 files changed, 32 insertions(+), 0 deletions(-)
> 
> diff --git a/arch/powerpc/platforms/pseries/pci.c b/arch/powerpc/platforms/pseries/pci.c
> index 0b580f4..58469fe 100644
> --- a/arch/powerpc/platforms/pseries/pci.c
> +++ b/arch/powerpc/platforms/pseries/pci.c
> @@ -24,6 +24,7 @@
>  #include <linux/kernel.h>
>  #include <linux/pci.h>
>  #include <linux/string.h>
> +#include <linux/device.h>
> 
>  #include <asm/eeh.h>
>  #include <asm/pci-bridge.h>
> @@ -108,3 +109,34 @@ static void fixup_winbond_82c105(struct pci_dev* dev)
>  }
>  DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_WINBOND, PCI_DEVICE_ID_WINBOND_82C105,
>  			 fixup_winbond_82c105);
> +
> +int pcibios_get_speed_cap_mask(struct pci_dev *dev, u32 *mask)
> +{
> +	struct device_node *dn, *pdn;
> +	const uint32_t *pcie_link_speed_stats = NULL;
> +
> +	*mask = 0;
> +	dn = pci_bus_to_OF_node(dev->bus);
> +
> +	/* Find nearest ibm,pcie-link-speed-stats, walking up the device tree */
> +	for (pdn = dn; pdn != NULL; pdn = pdn->parent) {
> +		pcie_link_speed_stats = (const uint32_t *) of_get_property(pdn,
> +			"ibm,pcie-link-speed-stats", NULL);
> +		if (pcie_link_speed_stats != NULL)
> +			break;
> +	}
> +
> +	if (pcie_link_speed_stats == NULL) {
> +		dev_info(&dev->dev, "no ibm,pcie-link-speed-stats property\n");
> +		return -EINVAL;
> +	}
> +
> +	switch (pcie_link_speed_stats[0]) {
> +		case 0x02:
> +		*mask |= PCIE_SPEED_50;
> +		case 0x01:
> +		*mask |= PCIE_SPEED_25;
> +	}

I recall seeing this returns 0x00 as well. Maybe you should include both
0x00 and a default case and return EINVAL.

Regards.
Cascardo.

> +
> +	return 0;
> +}
> -- 
> 1.7.4.4
> 

^ permalink raw reply

* Re: [PATCH] mv643xx_eth: convert to use the Marvell Orion MDIO driver
From: Jason Cooper @ 2013-03-14 19:02 UTC (permalink / raw)
  To: Florian Fainelli
  Cc: Thomas Petazzoni, Andrew Lunn, Russell King, linux-doc,
	devicetree-discuss, linux-kernel, Rob Herring, Greg Kroah-Hartman,
	Paul Mackerras, Lennert Buytenhek, Rob Landley, netdev,
	linuxppc-dev, davem, linux-arm-kernel
In-Reply-To: <1363284515-9865-2-git-send-email-florian@openwrt.org>

Florian,

On Thu, Mar 14, 2013 at 07:08:32PM +0100, Florian Fainelli wrote:
> This patch converts the Marvell MV643XX ethernet driver to use the
> Marvell Orion MDIO driver. As a result, PowerPC and ARM platforms
> registering the Marvell MV643XX ethernet driver are also updated to
> register a Marvell Orion MDIO driver. This driver voluntarily overlaps
> with the Marvell Ethernet shared registers because it will use a subset
> of this shared register (shared_base + 0x4 - shared_base + 0x84). The
> Ethernet driver is also updated to look up for a PHY device using the
> Orion MDIO bus driver.
> 
> Signed-off-by: Florian Fainelli <florian@openwrt.org>
> ---
>  arch/arm/plat-orion/common.c               |   97 +++++++++++----
>  arch/powerpc/platforms/chrp/pegasos_eth.c  |   20 +++
>  arch/powerpc/sysdev/mv64x60_dev.c          |   14 ++-
>  drivers/net/ethernet/marvell/Kconfig       |    1 +
>  drivers/net/ethernet/marvell/mv643xx_eth.c |  186 ++--------------------------
>  include/linux/mv643xx_eth.h                |    1 -
>  6 files changed, 117 insertions(+), 202 deletions(-)

Isn't this the old version of 4/4 ?

thx,

Jason.

> 
> diff --git a/arch/arm/plat-orion/common.c b/arch/arm/plat-orion/common.c
> index 2d4b641..dc4345e 100644
> --- a/arch/arm/plat-orion/common.c
> +++ b/arch/arm/plat-orion/common.c
> @@ -238,6 +238,7 @@ static __init void ge_complete(
>  	struct mv643xx_eth_shared_platform_data *orion_ge_shared_data,
>  	struct resource *orion_ge_resource, unsigned long irq,
>  	struct platform_device *orion_ge_shared,
> +	struct platform_device *orion_ge_mvmdio,
>  	struct mv643xx_eth_platform_data *eth_data,
>  	struct platform_device *orion_ge)
>  {
> @@ -247,6 +248,8 @@ static __init void ge_complete(
>  	orion_ge->dev.platform_data = eth_data;
>  
>  	platform_device_register(orion_ge_shared);
> +	if (orion_ge_mvmdio)
> +		platform_device_register(orion_ge_mvmdio);
>  	platform_device_register(orion_ge);
>  }
>  
> @@ -258,8 +261,6 @@ struct mv643xx_eth_shared_platform_data orion_ge00_shared_data;
>  static struct resource orion_ge00_shared_resources[] = {
>  	{
>  		.name	= "ge00 base",
> -	}, {
> -		.name	= "ge00 err irq",
>  	},
>  };
>  
> @@ -271,6 +272,19 @@ static struct platform_device orion_ge00_shared = {
>  	},
>  };
>  
> +static struct resource orion_ge00_mvmdio_resources[] = {
> +	{
> +		.name	= "ge00 mvmdio base",
> +	}, {
> +		.name	= "ge00 mvmdio irr irq",
> +	},
> +};
> +
> +static struct platform_device orion_ge00_mvmdio = {
> +	.name		= "orion-mdio",
> +	.id		= 0,
> +};
> +
>  static struct resource orion_ge00_resources[] = {
>  	{
>  		.name	= "ge00 irq",
> @@ -295,26 +309,25 @@ void __init orion_ge00_init(struct mv643xx_eth_platform_data *eth_data,
>  			    unsigned int tx_csum_limit)
>  {
>  	fill_resources(&orion_ge00_shared, orion_ge00_shared_resources,
> -		       mapbase + 0x2000, SZ_16K - 1, irq_err);
> +		       mapbase + 0x2000, SZ_16K - 1, NO_IRQ);
> +	fill_resources(&orion_ge00_mvmdio, orion_ge00_mvmdio_resources,
> +			mapbase + 0x2004, 0x84 - 1, irq_err);
>  	orion_ge00_shared_data.tx_csum_limit = tx_csum_limit;
>  	ge_complete(&orion_ge00_shared_data,
>  		    orion_ge00_resources, irq, &orion_ge00_shared,
> +		    &orion_ge00_mvmdio,
>  		    eth_data, &orion_ge00);
>  }
>  
>  /*****************************************************************************
>   * GE01
>   ****************************************************************************/
> -struct mv643xx_eth_shared_platform_data orion_ge01_shared_data = {
> -	.shared_smi	= &orion_ge00_shared,
> -};
> +struct mv643xx_eth_shared_platform_data orion_ge01_shared_data;
>  
>  static struct resource orion_ge01_shared_resources[] = {
>  	{
>  		.name	= "ge01 base",
> -	}, {
> -		.name	= "ge01 err irq",
> -	},
> +	}
>  };
>  
>  static struct platform_device orion_ge01_shared = {
> @@ -325,6 +338,19 @@ static struct platform_device orion_ge01_shared = {
>  	},
>  };
>  
> +static struct resource orion_ge01_mvmdio_resources[] = {
> +	{
> +		.name	= "ge01 mdio base",
> +	}, {
> +		.name	= "ge01 mdio err irq",
> +	},
> +};
> +
> +static struct platform_device orion_ge01_mvmdio = {
> +	.name		= "orion-mdio",
> +	.id		= 1,
> +};
> +
>  static struct resource orion_ge01_resources[] = {
>  	{
>  		.name	= "ge01 irq",
> @@ -349,26 +375,25 @@ void __init orion_ge01_init(struct mv643xx_eth_platform_data *eth_data,
>  			    unsigned int tx_csum_limit)
>  {
>  	fill_resources(&orion_ge01_shared, orion_ge01_shared_resources,
> -		       mapbase + 0x2000, SZ_16K - 1, irq_err);
> +		       mapbase + 0x2000, SZ_16K - 1, NO_IRQ);
> +	fill_resources(&orion_ge01_mvmdio, orion_ge01_mvmdio_resources,
> +			mapbase + 0x2004, 0x84 - 1, irq_err);
>  	orion_ge01_shared_data.tx_csum_limit = tx_csum_limit;
>  	ge_complete(&orion_ge01_shared_data,
>  		    orion_ge01_resources, irq, &orion_ge01_shared,
> +		    NULL,
>  		    eth_data, &orion_ge01);
>  }
>  
>  /*****************************************************************************
>   * GE10
>   ****************************************************************************/
> -struct mv643xx_eth_shared_platform_data orion_ge10_shared_data = {
> -	.shared_smi	= &orion_ge00_shared,
> -};
> +struct mv643xx_eth_shared_platform_data orion_ge10_shared_data;
>  
>  static struct resource orion_ge10_shared_resources[] = {
>  	{
>  		.name	= "ge10 base",
> -	}, {
> -		.name	= "ge10 err irq",
> -	},
> +	}
>  };
>  
>  static struct platform_device orion_ge10_shared = {
> @@ -379,6 +404,19 @@ static struct platform_device orion_ge10_shared = {
>  	},
>  };
>  
> +static struct resource orion_ge10_mvmdio_resources[] = {
> +	{
> +		.name	= "ge10 mvmdio base",
> +	}, {
> +		.name	= "ge10 mvmdio err irq",
> +	},
> +};
> +
> +static struct platform_device orion_ge10_mvmdio = {
> +	.name		= "orion-mdio",
> +	.id		= 1,
> +};
> +
>  static struct resource orion_ge10_resources[] = {
>  	{
>  		.name	= "ge10 irq",
> @@ -403,23 +441,22 @@ void __init orion_ge10_init(struct mv643xx_eth_platform_data *eth_data,
>  {
>  	fill_resources(&orion_ge10_shared, orion_ge10_shared_resources,
>  		       mapbase + 0x2000, SZ_16K - 1, irq_err);
> +	fill_resources(&orion_ge10_mvmdio, orion_ge10_mvmdio_resources,
> +		       mapbase + 0x2004, 0x84 - 1, irq_err);
>  	ge_complete(&orion_ge10_shared_data,
>  		    orion_ge10_resources, irq, &orion_ge10_shared,
> +		    &orion_ge10_mvmdio,
>  		    eth_data, &orion_ge10);
>  }
>  
>  /*****************************************************************************
>   * GE11
>   ****************************************************************************/
> -struct mv643xx_eth_shared_platform_data orion_ge11_shared_data = {
> -	.shared_smi	= &orion_ge00_shared,
> -};
> +struct mv643xx_eth_shared_platform_data orion_ge11_shared_data;
>  
>  static struct resource orion_ge11_shared_resources[] = {
>  	{
>  		.name	= "ge11 base",
> -	}, {
> -		.name	= "ge11 err irq",
>  	},
>  };
>  
> @@ -431,6 +468,19 @@ static struct platform_device orion_ge11_shared = {
>  	},
>  };
>  
> +static struct resource orion_ge11_mvmdio_resources[] = {
> +	{
> +		.name	= "ge11 mvmdio base",
> +	}, {
> +		.name	= "ge11 mvmdio err irq",
> +	},
> +};
> +
> +static struct platform_device orion_ge11_mvmdio = {
> +	.name		= "orion-mdio",
> +	.id		= 1,
> +};
> +
>  static struct resource orion_ge11_resources[] = {
>  	{
>  		.name	= "ge11 irq",
> @@ -454,9 +504,12 @@ void __init orion_ge11_init(struct mv643xx_eth_platform_data *eth_data,
>  			    unsigned long irq_err)
>  {
>  	fill_resources(&orion_ge11_shared, orion_ge11_shared_resources,
> -		       mapbase + 0x2000, SZ_16K - 1, irq_err);
> +		       mapbase + 0x2000, SZ_16K - 1, NO_IRQ);
> +	fill_resources(&orion_ge11_mvmdio, orion_ge11_mvmdio_resources,
> +		       mapbase + 0x2004, 0x84 - 1, irq_err);
>  	ge_complete(&orion_ge11_shared_data,
>  		    orion_ge11_resources, irq, &orion_ge11_shared,
> +		    NULL,
>  		    eth_data, &orion_ge11);
>  }
>  
> diff --git a/arch/powerpc/platforms/chrp/pegasos_eth.c b/arch/powerpc/platforms/chrp/pegasos_eth.c
> index 039fc8e..a671508 100644
> --- a/arch/powerpc/platforms/chrp/pegasos_eth.c
> +++ b/arch/powerpc/platforms/chrp/pegasos_eth.c
> @@ -47,6 +47,25 @@ static struct platform_device mv643xx_eth_shared_device = {
>  	.resource	= mv643xx_eth_shared_resources,
>  };
>  
> +/*
> + * The orion mdio driver only covers shared + 0x4 up to shared + 0x84 - 1
> + */
> +static struct resource mv643xx_eth_mvmdio_resources[] = {
> +	[0] = {
> +		.name	= "ethernet mdio base",
> +		.start	= 0xf1000000 + MV643XX_ETH_SHARED_REGS + 0x4,
> +		.end	= 0xf1000000 + MV643XX_ETH_SHARED_REGS + 0x83,
> +		.flags	= IORESOURCE_MEM,
> +	},
> +};
> +
> +static struct platform_device mv643xx_eth_mvmdio_device = {
> +	.name		= "orion-mdio",
> +	.id		= 0,
> +	.num_resources	= ARRAY_SIZE(mv643xx_eth_mvmdio_resources),
> +	.resource	= mv643xx_eth_shared_resources,
> +};
> +
>  static struct resource mv643xx_eth_port1_resources[] = {
>  	[0] = {
>  		.name	= "eth port1 irq",
> @@ -82,6 +101,7 @@ static struct platform_device eth_port1_device = {
>  
>  static struct platform_device *mv643xx_eth_pd_devs[] __initdata = {
>  	&mv643xx_eth_shared_device,
> +	&mv643xx_eth_mvmdio_device,
>  	&eth_port1_device,
>  };
>  
> diff --git a/arch/powerpc/sysdev/mv64x60_dev.c b/arch/powerpc/sysdev/mv64x60_dev.c
> index 0f6af41..630cea3 100644
> --- a/arch/powerpc/sysdev/mv64x60_dev.c
> +++ b/arch/powerpc/sysdev/mv64x60_dev.c
> @@ -214,15 +214,25 @@ static struct platform_device * __init mv64x60_eth_register_shared_pdev(
>  						struct device_node *np, int id)
>  {
>  	struct platform_device *pdev;
> -	struct resource r[1];
> +	struct resource r[2];
>  	int err;
>  
>  	err = of_address_to_resource(np, 0, &r[0]);
>  	if (err)
>  		return ERR_PTR(err);
>  
> +	/* register an orion mdio bus driver */
> +	r[1].start = r[0].start + 0x4;
> +	r[1].end = r[0].start + 0x84 - 1;
> +	r[1].flags = IORESOURCE_MEM;
> +
> +	pdev = platform_device_register_simple("orion-mdio", id, &r[1], 1);
> +	if (!pdev)
> +		return pdev;
> +
>  	pdev = platform_device_register_simple(MV643XX_ETH_SHARED_NAME, id,
> -					       r, 1);
> +					       &r[0], 1);
> +
>  	return pdev;
>  }
>  
> diff --git a/drivers/net/ethernet/marvell/Kconfig b/drivers/net/ethernet/marvell/Kconfig
> index edfba93..df06061 100644
> --- a/drivers/net/ethernet/marvell/Kconfig
> +++ b/drivers/net/ethernet/marvell/Kconfig
> @@ -23,6 +23,7 @@ config MV643XX_ETH
>  	depends on (MV64X60 || PPC32 || PLAT_ORION) && INET
>  	select INET_LRO
>  	select PHYLIB
> +	select MVMDIO
>  	---help---
>  	  This driver supports the gigabit ethernet MACs in the
>  	  Marvell Discovery PPC/MIPS chipset family (MV643XX) and
> diff --git a/drivers/net/ethernet/marvell/mv643xx_eth.c b/drivers/net/ethernet/marvell/mv643xx_eth.c
> index d1ecf4b..df04bee 100644
> --- a/drivers/net/ethernet/marvell/mv643xx_eth.c
> +++ b/drivers/net/ethernet/marvell/mv643xx_eth.c
> @@ -69,14 +69,6 @@ static char mv643xx_eth_driver_version[] = "1.4";
>   * Registers shared between all ports.
>   */
>  #define PHY_ADDR			0x0000
> -#define SMI_REG				0x0004
> -#define  SMI_BUSY			0x10000000
> -#define  SMI_READ_VALID			0x08000000
> -#define  SMI_OPCODE_READ		0x04000000
> -#define  SMI_OPCODE_WRITE		0x00000000
> -#define ERR_INT_CAUSE			0x0080
> -#define  ERR_INT_SMI_DONE		0x00000010
> -#define ERR_INT_MASK			0x0084
>  #define WINDOW_BASE(w)			(0x0200 + ((w) << 3))
>  #define WINDOW_SIZE(w)			(0x0204 + ((w) << 3))
>  #define WINDOW_REMAP_HIGH(w)		(0x0280 + ((w) << 2))
> @@ -266,25 +258,6 @@ struct mv643xx_eth_shared_private {
>  	void __iomem *base;
>  
>  	/*
> -	 * Points at the right SMI instance to use.
> -	 */
> -	struct mv643xx_eth_shared_private *smi;
> -
> -	/*
> -	 * Provides access to local SMI interface.
> -	 */
> -	struct mii_bus *smi_bus;
> -
> -	/*
> -	 * If we have access to the error interrupt pin (which is
> -	 * somewhat misnamed as it not only reflects internal errors
> -	 * but also reflects SMI completion), use that to wait for
> -	 * SMI access completion instead of polling the SMI busy bit.
> -	 */
> -	int err_interrupt;
> -	wait_queue_head_t smi_busy_wait;
> -
> -	/*
>  	 * Per-port MBUS window access register value.
>  	 */
>  	u32 win_protect;
> @@ -1122,97 +1095,6 @@ out_write:
>  	wrlp(mp, PORT_SERIAL_CONTROL, pscr);
>  }
>  
> -static irqreturn_t mv643xx_eth_err_irq(int irq, void *dev_id)
> -{
> -	struct mv643xx_eth_shared_private *msp = dev_id;
> -
> -	if (readl(msp->base + ERR_INT_CAUSE) & ERR_INT_SMI_DONE) {
> -		writel(~ERR_INT_SMI_DONE, msp->base + ERR_INT_CAUSE);
> -		wake_up(&msp->smi_busy_wait);
> -		return IRQ_HANDLED;
> -	}
> -
> -	return IRQ_NONE;
> -}
> -
> -static int smi_is_done(struct mv643xx_eth_shared_private *msp)
> -{
> -	return !(readl(msp->base + SMI_REG) & SMI_BUSY);
> -}
> -
> -static int smi_wait_ready(struct mv643xx_eth_shared_private *msp)
> -{
> -	if (msp->err_interrupt == NO_IRQ) {
> -		int i;
> -
> -		for (i = 0; !smi_is_done(msp); i++) {
> -			if (i == 10)
> -				return -ETIMEDOUT;
> -			msleep(10);
> -		}
> -
> -		return 0;
> -	}
> -
> -	if (!smi_is_done(msp)) {
> -		wait_event_timeout(msp->smi_busy_wait, smi_is_done(msp),
> -				   msecs_to_jiffies(100));
> -		if (!smi_is_done(msp))
> -			return -ETIMEDOUT;
> -	}
> -
> -	return 0;
> -}
> -
> -static int smi_bus_read(struct mii_bus *bus, int addr, int reg)
> -{
> -	struct mv643xx_eth_shared_private *msp = bus->priv;
> -	void __iomem *smi_reg = msp->base + SMI_REG;
> -	int ret;
> -
> -	if (smi_wait_ready(msp)) {
> -		pr_warn("SMI bus busy timeout\n");
> -		return -ETIMEDOUT;
> -	}
> -
> -	writel(SMI_OPCODE_READ | (reg << 21) | (addr << 16), smi_reg);
> -
> -	if (smi_wait_ready(msp)) {
> -		pr_warn("SMI bus busy timeout\n");
> -		return -ETIMEDOUT;
> -	}
> -
> -	ret = readl(smi_reg);
> -	if (!(ret & SMI_READ_VALID)) {
> -		pr_warn("SMI bus read not valid\n");
> -		return -ENODEV;
> -	}
> -
> -	return ret & 0xffff;
> -}
> -
> -static int smi_bus_write(struct mii_bus *bus, int addr, int reg, u16 val)
> -{
> -	struct mv643xx_eth_shared_private *msp = bus->priv;
> -	void __iomem *smi_reg = msp->base + SMI_REG;
> -
> -	if (smi_wait_ready(msp)) {
> -		pr_warn("SMI bus busy timeout\n");
> -		return -ETIMEDOUT;
> -	}
> -
> -	writel(SMI_OPCODE_WRITE | (reg << 21) |
> -		(addr << 16) | (val & 0xffff), smi_reg);
> -
> -	if (smi_wait_ready(msp)) {
> -		pr_warn("SMI bus busy timeout\n");
> -		return -ETIMEDOUT;
> -	}
> -
> -	return 0;
> -}
> -
> -
>  /* statistics ***************************************************************/
>  static struct net_device_stats *mv643xx_eth_get_stats(struct net_device *dev)
>  {
> @@ -2688,47 +2570,6 @@ static int mv643xx_eth_shared_probe(struct platform_device *pdev)
>  		goto out_free;
>  
>  	/*
> -	 * Set up and register SMI bus.
> -	 */
> -	if (pd == NULL || pd->shared_smi == NULL) {
> -		msp->smi_bus = mdiobus_alloc();
> -		if (msp->smi_bus == NULL)
> -			goto out_unmap;
> -
> -		msp->smi_bus->priv = msp;
> -		msp->smi_bus->name = "mv643xx_eth smi";
> -		msp->smi_bus->read = smi_bus_read;
> -		msp->smi_bus->write = smi_bus_write,
> -		snprintf(msp->smi_bus->id, MII_BUS_ID_SIZE, "%s-%d",
> -			pdev->name, pdev->id);
> -		msp->smi_bus->parent = &pdev->dev;
> -		msp->smi_bus->phy_mask = 0xffffffff;
> -		if (mdiobus_register(msp->smi_bus) < 0)
> -			goto out_free_mii_bus;
> -		msp->smi = msp;
> -	} else {
> -		msp->smi = platform_get_drvdata(pd->shared_smi);
> -	}
> -
> -	msp->err_interrupt = NO_IRQ;
> -	init_waitqueue_head(&msp->smi_busy_wait);
> -
> -	/*
> -	 * Check whether the error interrupt is hooked up.
> -	 */
> -	res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
> -	if (res != NULL) {
> -		int err;
> -
> -		err = request_irq(res->start, mv643xx_eth_err_irq,
> -				  IRQF_SHARED, "mv643xx_eth", msp);
> -		if (!err) {
> -			writel(ERR_INT_SMI_DONE, msp->base + ERR_INT_MASK);
> -			msp->err_interrupt = res->start;
> -		}
> -	}
> -
> -	/*
>  	 * (Re-)program MBUS remapping windows if we are asked to.
>  	 */
>  	dram = mv_mbus_dram_info();
> @@ -2743,10 +2584,6 @@ static int mv643xx_eth_shared_probe(struct platform_device *pdev)
>  
>  	return 0;
>  
> -out_free_mii_bus:
> -	mdiobus_free(msp->smi_bus);
> -out_unmap:
> -	iounmap(msp->base);
>  out_free:
>  	kfree(msp);
>  out:
> @@ -2756,14 +2593,7 @@ out:
>  static int mv643xx_eth_shared_remove(struct platform_device *pdev)
>  {
>  	struct mv643xx_eth_shared_private *msp = platform_get_drvdata(pdev);
> -	struct mv643xx_eth_shared_platform_data *pd = pdev->dev.platform_data;
>  
> -	if (pd == NULL || pd->shared_smi == NULL) {
> -		mdiobus_unregister(msp->smi_bus);
> -		mdiobus_free(msp->smi_bus);
> -	}
> -	if (msp->err_interrupt != NO_IRQ)
> -		free_irq(msp->err_interrupt, msp);
>  	iounmap(msp->base);
>  	kfree(msp);
>  
> @@ -2829,11 +2659,11 @@ static void set_params(struct mv643xx_eth_private *mp,
>  static struct phy_device *phy_scan(struct mv643xx_eth_private *mp,
>  				   int phy_addr)
>  {
> -	struct mii_bus *bus = mp->shared->smi->smi_bus;
>  	struct phy_device *phydev;
>  	int start;
>  	int num;
>  	int i;
> +	char phy_id[MII_BUS_ID_SIZE + 3];
>  
>  	if (phy_addr == MV643XX_ETH_PHY_ADDR_DEFAULT) {
>  		start = phy_addr_get(mp) & 0x1f;
> @@ -2843,17 +2673,19 @@ static struct phy_device *phy_scan(struct mv643xx_eth_private *mp,
>  		num = 1;
>  	}
>  
> +	/* Attempt to connect to the PHY using orion-mdio */
>  	phydev = NULL;
>  	for (i = 0; i < num; i++) {
>  		int addr = (start + i) & 0x1f;
>  
> -		if (bus->phy_map[addr] == NULL)
> -			mdiobus_scan(bus, addr);
> +		snprintf(phy_id, sizeof(phy_id), PHY_ID_FMT,
> +				"orion-mdio-mii", addr);
>  
> -		if (phydev == NULL) {
> -			phydev = bus->phy_map[addr];
> -			if (phydev != NULL)
> -				phy_addr_set(mp, addr);
> +		phydev = phy_connect(mp->dev, phy_id, NULL,
> +				PHY_INTERFACE_MODE_GMII);
> +		if (!IS_ERR(phydev)) {
> +			phy_addr_set(mp, addr);
> +			break;
>  		}
>  	}
>  
> diff --git a/include/linux/mv643xx_eth.h b/include/linux/mv643xx_eth.h
> index 49258e0..141d395 100644
> --- a/include/linux/mv643xx_eth.h
> +++ b/include/linux/mv643xx_eth.h
> @@ -19,7 +19,6 @@
>  
>  struct mv643xx_eth_shared_platform_data {
>  	struct mbus_dram_target_info	*dram;
> -	struct platform_device	*shared_smi;
>  	/*
>  	 * Max packet size for Tx IP/Layer 4 checksum, when set to 0, default
>  	 * limit of 9KiB will be used.
> -- 
> 1.7.10.4
> 
> 
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel@lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply

* Re: [PATCH] mv643xx_eth: convert to use the Marvell Orion MDIO driver
From: Florian Fainelli @ 2013-03-14 19:32 UTC (permalink / raw)
  To: Jason Cooper
  Cc: Thomas Petazzoni, Andrew Lunn, Russell King, linux-doc,
	devicetree-discuss, linux-kernel, Rob Herring, Greg Kroah-Hartman,
	Paul Mackerras, Lennert Buytenhek, Rob Landley, netdev,
	linuxppc-dev, davem, linux-arm-kernel
In-Reply-To: <20130314190235.GW12700@titan.lakedaemon.net>

Hello Jason,

Le 14/03/2013 20:02, Jason Cooper a écrit :
> Florian,
>
> On Thu, Mar 14, 2013 at 07:08:32PM +0100, Florian Fainelli wrote:
>> This patch converts the Marvell MV643XX ethernet driver to use the
>> Marvell Orion MDIO driver. As a result, PowerPC and ARM platforms
>> registering the Marvell MV643XX ethernet driver are also updated to
>> register a Marvell Orion MDIO driver. This driver voluntarily overlaps
>> with the Marvell Ethernet shared registers because it will use a subset
>> of this shared register (shared_base + 0x4 - shared_base + 0x84). The
>> Ethernet driver is also updated to look up for a PHY device using the
>> Orion MDIO bus driver.
>>
>> Signed-off-by: Florian Fainelli <florian@openwrt.org>
>> ---
>>   arch/arm/plat-orion/common.c               |   97 +++++++++++----
>>   arch/powerpc/platforms/chrp/pegasos_eth.c  |   20 +++
>>   arch/powerpc/sysdev/mv64x60_dev.c          |   14 ++-
>>   drivers/net/ethernet/marvell/Kconfig       |    1 +
>>   drivers/net/ethernet/marvell/mv643xx_eth.c |  186 ++--------------------------
>>   include/linux/mv643xx_eth.h                |    1 -
>>   6 files changed, 117 insertions(+), 202 deletions(-)
>
> Isn't this the old version of 4/4 ?

No this really is v2, but I reformatted just that one and sent it 
without the v2 changelog, you should have received the proper version a 
couple minutes later once I realized my mistake.
--
Florian

^ permalink raw reply

* Re: [PATCH 0/5] mv643xx_eth: use mvmdio MDIO bus driver
From: Jason Cooper @ 2013-03-14 17:25 UTC (permalink / raw)
  To: Florian Fainelli
  Cc: Thomas Petazzoni, Andrew Lunn, Russell King, linux-doc,
	devicetree-discuss, linux-kernel, Rob Herring, Greg Kroah-Hartman,
	Paul Mackerras, Lennert Buytenhek, Rob Landley, netdev,
	linuxppc-dev, davem, linux-arm-kernel
In-Reply-To: <1359473048-26551-1-git-send-email-florian@openwrt.org>

Florian,

Any word on version 2 of this series?  I'd like to base the conversion
of kirkwood to DT based ethernet init on it.

thx,

Jason.

On Tue, Jan 29, 2013 at 04:24:03PM +0100, Florian Fainelli wrote:
> Hi all,
> 
> This patch converts the mv643xx_eth driver to use the mvmdio MDIO bus driver
> instead of rolling its own implementation. As a result, all users of this
> mv643xx_eth driver are converted to register an "orion-mdio" platform_device.
> The mvmdio driver is also updated to support an interrupt line which reports
> SMI error/completion, and to allow traditionnal platform device registration
> instead of just device tree.
> 
> David, I think it makes sense for you to merge all of this, since we do
> not want the architecture files to be desynchronized from the mv643xx_eth to
> avoid runtime breakage. The potential for merge conflicts should be very small.
> 
> You can probably safely merge patches 1 to 4 if Thomas agrees, and we will
> see what kind of feeback I get on patch 5.
> 
> Florian Fainelli (5):
>   net: mvmdio: unmap base register address at driver removal
>   net: mvmdio: rename base register cookie from smireg to regs
>   net: mvmdio: enhance driver to support SMI error/done interrupts
>   net: mvmdio: allow Device Tree and platform device to coexist
>   mv643xx_eth: convert to use the Marvell Orion MDIO driver
> 
>  .../devicetree/bindings/net/marvell-orion-mdio.txt |    3 +
>  arch/arm/plat-orion/common.c                       |   84 +++++++--
>  arch/powerpc/platforms/chrp/pegasos_eth.c          |   20 +++
>  arch/powerpc/sysdev/mv64x60_dev.c                  |   14 +-
>  drivers/net/ethernet/marvell/Kconfig               |    1 +
>  drivers/net/ethernet/marvell/mv643xx_eth.c         |  187 +-------------------
>  drivers/net/ethernet/marvell/mvmdio.c              |  136 +++++++++++---
>  7 files changed, 226 insertions(+), 219 deletions(-)
> 
> -- 
> 1.7.10.4
> 
> 
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel@lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply

* Re: [PATCH V2] powerpc/85xx: workaround for chips with MSI hardware errata
From: Kumar Gala @ 2013-03-14 20:04 UTC (permalink / raw)
  To: Jia Hongtao; +Cc: B07421, linuxppc-dev, b38951
In-Reply-To: <1363257323-2801-1-git-send-email-hongtao.jia@freescale.com>


On Mar 14, 2013, at 5:35 AM, Jia Hongtao wrote:

> The MPIC version 2.0 has a MSI errata (errata PIC1 of mpc8544), It =
causes
> that neither MSI nor MSI-X can work fine. This is a workaround to =
allow
> MSI-X to function properly.
>=20
> Signed-off-by: Liu Shuo <soniccat.liu@gmail.com>
> Signed-off-by: Li Yang <leoli@freescale.com>
> Signed-off-by: Jia Hongtao <hongtao.jia@freescale.com>
> ---
> Changes for V2:
> - Address almost all the comments from Michael Ellerman for V1.
>  Here is the link:
>  http://patchwork.ozlabs.org/patch/226833/
>=20
> arch/powerpc/sysdev/fsl_msi.c | 65 =
+++++++++++++++++++++++++++++++++++++++++--
> arch/powerpc/sysdev/fsl_msi.h |  2 ++
> 2 files changed, 64 insertions(+), 3 deletions(-)
>=20
> diff --git a/arch/powerpc/sysdev/fsl_msi.c =
b/arch/powerpc/sysdev/fsl_msi.c
> index 178c994..54cb83e 100644
> --- a/arch/powerpc/sysdev/fsl_msi.c
> +++ b/arch/powerpc/sysdev/fsl_msi.c
> @@ -98,8 +98,18 @@ static int fsl_msi_init_allocator(struct fsl_msi =
*msi_data)
>=20
> static int fsl_msi_check_device(struct pci_dev *pdev, int nvec, int =
type)
> {
> -	if (type =3D=3D PCI_CAP_ID_MSIX)
> -		pr_debug("fslmsi: MSI-X untested, trying anyway.\n");
> +	struct fsl_msi *msi;
> +
> +	if (type =3D=3D PCI_CAP_ID_MSI) {
> +		/*
> +		 * MPIC version 2.0 has erratum PIC1. For now MSI
> +		 * could not work. So check to prevent MSI from
> +		 * being used on the board with this erratum.
> +		 */
> +		list_for_each_entry(msi, &msi_head, list)
> +			if (msi->feature & MSI_HW_ERRATA_ENDIAN)
> +				return -EINVAL;
> +	}
>=20
> 	return 0;
> }
> @@ -142,7 +152,17 @@ static void fsl_compose_msi_msg(struct pci_dev =
*pdev, int hwirq,
> 	msg->address_lo =3D lower_32_bits(address);
> 	msg->address_hi =3D upper_32_bits(address);
>=20
> -	msg->data =3D hwirq;
> +	/*
> +	 * MPIC version 2.0 has erratum PIC1. It causes
> +	 * that neither MSI nor MSI-X can work fine.
> +	 * This is a workaround to allow MSI-X to function
> +	 * properly. It only works for MSI-X, we prevent
> +	 * MSI on buggy chips in fsl_msi_check_device().
> +	 */
> +	if (msi_data->feature & MSI_HW_ERRATA_ENDIAN)
> +		msg->data =3D __swab32(hwirq);
> +	else
> +		msg->data =3D hwirq;
>=20
> 	pr_debug("%s: allocated srs: %d, ibs: %d\n",
> 		__func__, hwirq / IRQS_PER_MSI_REG, hwirq % =
IRQS_PER_MSI_REG);
> @@ -361,6 +381,35 @@ static int fsl_msi_setup_hwirq(struct fsl_msi =
*msi, struct platform_device *dev,
> 	return 0;
> }
>=20
> +/* MPIC version 2.0 has erratum PIC1 */
> +static int mpic_has_errata(struct platform_device *dev)
> +{
> +	struct device_node *mpic_node;
> +
> +	mpic_node =3D of_irq_find_parent(dev->dev.of_node);
> +	if (mpic_node) {
> +		u32 *reg_base, brr1 =3D 0;
> +		/* Get the PIC reg base */
> +		reg_base =3D of_iomap(mpic_node, 0);
> +		of_node_put(mpic_node);
> +		if (!reg_base) {
> +			dev_err(&dev->dev, "ioremap problem failed.\n");
> +			return -EIO;
> +		}
> +
> +		/* Get the mpic version from block revision register 1 =
*/
> +		brr1 =3D in_be32(reg_base + MPIC_FSL_BRR1);
> +		iounmap(reg_base);
> +		if ((brr1 & MPIC_FSL_BRR1_VER) =3D=3D 0x0200)
> +			return 1;
> +	} else {
> +		dev_err(&dev->dev, "MSI can't find his parent mpic =
node.\n");
> +		return -ENODEV;
> +	}
> +
> +	return 0;
> +}
> +
> static const struct of_device_id fsl_of_msi_ids[];
> static int fsl_of_msi_probe(struct platform_device *dev)
> {
> @@ -423,6 +472,16 @@ static int fsl_of_msi_probe(struct =
platform_device *dev)
>=20
> 	msi->feature =3D features->fsl_pic_ip;
>=20
> +	if ((features->fsl_pic_ip & FSL_PIC_IP_MASK) =3D=3D =
FSL_PIC_IP_MPIC) {
> +		rc =3D mpic_has_errata(dev);
> +		if (rc > 0) {
> +			msi->feature |=3D MSI_HW_ERRATA_ENDIAN;
> +		} else if (rc < 0) {
> +			err =3D rc;
> +			goto error_out;
> +		}
> +	}
> +
> 	/*
> 	 * Remember the phandle, so that we can match with any PCI nodes
> 	 * that have an "fsl,msi" property.
> diff --git a/arch/powerpc/sysdev/fsl_msi.h =
b/arch/powerpc/sysdev/fsl_msi.h
> index 8225f86..7389e8e 100644
> --- a/arch/powerpc/sysdev/fsl_msi.h
> +++ b/arch/powerpc/sysdev/fsl_msi.h
> @@ -25,6 +25,8 @@
> #define FSL_PIC_IP_IPIC   0x00000002
> #define FSL_PIC_IP_VMPIC  0x00000003
>=20
> +#define MSI_HW_ERRATA_ENDIAN 0x00000010
> +

Is there any reason to put this in fsl_msi.h rather than just in =
fsl_msi.c itself?

- k

> struct fsl_msi {
> 	struct irq_domain *irqhost;
>=20
> --=20
> 1.8.0
>=20

^ permalink raw reply

* Re: [PATCH 5/5 v9] iommu/fsl: Freescale PAMU driver and iommu implementation.
From: Kumar Gala @ 2013-03-14 20:20 UTC (permalink / raw)
  To: Varun Sethi
  Cc: joro, linux-kernel, stuart.yoder, iommu, scottwood, linuxppc-dev
In-Reply-To: <1363200580-11623-1-git-send-email-Varun.Sethi@freescale.com>


On Mar 13, 2013, at 1:49 PM, Varun Sethi wrote:

> +/*
> + * Table of SVRs and the corresponding PORT_ID values.
> + *
> + * All future CoreNet-enabled SOCs will have this erratum fixed, so =
this table
> + * should never need to be updated.  SVRs are guaranteed to be =
unique, so
> + * there is no worry that a future SOC will inadvertently have one of =
these
> + * values.
> + */

Maybe add to the comment about what port_id represents

> +static const struct {
> +	u32 svr;
> +	u32 port_id;
> +} port_id_map[] =3D {
> +	{0x82100010, 0xFF000000},	/* P2040 1.0 */
> +	{0x82100011, 0xFF000000},	/* P2040 1.1 */
> +	{0x82100110, 0xFF000000},	/* P2041 1.0 */
> +	{0x82100111, 0xFF000000},	/* P2041 1.1 */
> +	{0x82110310, 0xFF000000},	/* P3041 1.0 */
> +	{0x82110311, 0xFF000000},	/* P3041 1.1 */
> +	{0x82010020, 0xFFF80000},	/* P4040 2.0 */
> +	{0x82000020, 0xFFF80000},	/* P4080 2.0 */
> +	{0x82210010, 0xFC000000},       /* P5010 1.0 */
> +	{0x82210020, 0xFC000000},       /* P5010 2.0 */
> +	{0x82200010, 0xFC000000},	/* P5020 1.0 */
> +	{0x82050010, 0xFF800000},	/* P5021 1.0 */
> +	{0x82040010, 0xFF800000},	/* P5040 1.0 */
> +};
> +
> +#define SVR_SECURITY	0x80000	/* The Security (E) bit */
> +
> +static int __init fsl_pamu_probe(struct platform_device *pdev)
> +{
> +	void __iomem *pamu_regs =3D NULL;
> +	struct ccsr_guts __iomem *guts_regs =3D NULL;
> +	u32 pamubypenr, pamu_counter;
> +	unsigned long pamu_reg_off;
> +	unsigned long pamu_reg_base;
> +	struct pamu_isr_data *data;
> +	struct device_node *guts_node;
> +	u64 size;
> +	struct page *p;
> +	int ret =3D 0;
> +	int irq;
> +	phys_addr_t ppaact_phys;
> +	phys_addr_t spaact_phys;
> +	phys_addr_t omt_phys;
> +	size_t mem_size =3D 0;
> +	unsigned int order =3D 0;
> +	u32 csd_port_id =3D 0;
> +	unsigned i;
> +	/*
> +	 * enumerate all PAMUs and allocate and setup PAMU tables
> +	 * for each of them,
> +	 * NOTE : All PAMUs share the same LIODN tables.
> +	 */
> +
> +	pamu_regs =3D of_iomap(pdev->dev.of_node, 0);
> +	if (!pamu_regs) {
> +		dev_err(&pdev->dev, "ioremap of PAMU node failed\n");
> +		return -ENOMEM;
> +	}
> +	of_get_address(pdev->dev.of_node, 0, &size, NULL);
> +
> +	irq =3D irq_of_parse_and_map(pdev->dev.of_node, 0);
> +	if (irq =3D=3D NO_IRQ) {
> +		dev_warn(&pdev->dev, "no interrupts listed in PAMU =
node\n");
> +		goto error;
> +	}
> +
> +	data =3D kzalloc(sizeof(struct pamu_isr_data), GFP_KERNEL);
> +	if (!data) {
> +		iounmap(pamu_regs);
> +		return -ENOMEM;
> +	}
> +	data->pamu_reg_base =3D pamu_regs;
> +	data->count =3D size / PAMU_OFFSET;
> +
> +	/* The ISR needs access to the regs, so we won't iounmap them */
> +	ret =3D request_irq(irq, pamu_av_isr, 0, "pamu", data);
> +	if (ret < 0) {
> +		dev_err(&pdev->dev, "error %i installing ISR for irq =
%i\n",
> +			ret, irq);
> +		goto error;
> +	}
> +
> +	guts_node =3D of_find_compatible_node(NULL, NULL,
> +			"fsl,qoriq-device-config-1.0");

This doesn't work for T4 or B4 device trees.

> +	if (!guts_node) {
> +		dev_err(&pdev->dev, "could not find GUTS node %s\n",
> +			pdev->dev.of_node->full_name);
> +		ret =3D -ENODEV;
> +		goto error;
> +	}
> +
> +	guts_regs =3D of_iomap(guts_node, 0);
> +	of_node_put(guts_node);
> +	if (!guts_regs) {
> +		dev_err(&pdev->dev, "ioremap of GUTS node failed\n");
> +		ret =3D -ENODEV;
> +		goto error;
> +	}
> +
> +	/* read in the PAMU capability registers */
> +	get_pamu_cap_values((unsigned long)pamu_regs);
> +	/*
> +	 * To simplify the allocation of a coherency domain, we allocate =
the
> +	 * PAACT and the OMT in the same memory buffer.  Unfortunately, =
this
> +	 * wastes more memory compared to allocating the buffers =
separately.
> +	 */
> +	/* Determine how much memory we need */
> +	mem_size =3D (PAGE_SIZE << get_order(PAACT_SIZE)) +
> +		(PAGE_SIZE << get_order(SPAACT_SIZE)) +
> +		(PAGE_SIZE << get_order(OMT_SIZE));
> +	order =3D get_order(mem_size);
> +
> +	p =3D alloc_pages(GFP_KERNEL | __GFP_ZERO, order);
> +	if (!p) {
> +		dev_err(&pdev->dev, "unable to allocate PAACT/SPAACT/OMT =
block\n");
> +		ret =3D -ENOMEM;
> +		goto error;
> +	}
> +
> +	ppaact =3D page_address(p);
> +	ppaact_phys =3D page_to_phys(p);
> +
> +	/* Make sure the memory is naturally aligned */
> +	if (ppaact_phys & ((PAGE_SIZE << order) - 1)) {
> +		dev_err(&pdev->dev, "PAACT/OMT block is unaligned\n");
> +		ret =3D -ENOMEM;
> +		goto error;
> +	}
> +
> +	spaact =3D (void *)ppaact + (PAGE_SIZE << =
get_order(PAACT_SIZE));
> +	omt =3D (void *)spaact + (PAGE_SIZE << get_order(SPAACT_SIZE));
> +
> +	dev_dbg(&pdev->dev, "ppaact virt=3D%p phys=3D0x%llx\n", ppaact,
> +		(unsigned long long) ppaact_phys);
> +
> +	/* Check to see if we need to implement the work-around on this =
SOC */
> +
> +	/* Determine the Port ID for our coherence subdomain */
> +	for (i =3D 0; i < ARRAY_SIZE(port_id_map); i++) {
> +		if (port_id_map[i].svr =3D=3D (mfspr(SPRN_SVR) & =
~SVR_SECURITY)) {
> +			csd_port_id =3D port_id_map[i].port_id;
> +			dev_dbg(&pdev->dev, "found matching SVR %08x\n",
> +				port_id_map[i].svr);
> +			break;
> +		}
> +	}
> +
> +	if (csd_port_id) {
> +		dev_dbg(&pdev->dev, "creating coherency subdomain at =
address "
> +			"0x%llx, size %zu, port id 0x%08x", ppaact_phys,
> +			mem_size, csd_port_id);
> +
> +		ret =3D create_csd(ppaact_phys, mem_size, csd_port_id);
> +		if (ret) {
> +			dev_err(&pdev->dev, "could not create coherence =
"
> +				"subdomain\n");
> +			return ret;
> +		}
> +	}
> +
> +	spaact_phys =3D virt_to_phys(spaact);
> +	omt_phys =3D virt_to_phys(omt);
> +
> +	spaace_pool =3D gen_pool_create(ilog2(sizeof(struct paace)), =
-1);
> +	if (!spaace_pool) {
> +		ret =3D -ENOMEM;
> +		dev_err(&pdev->dev, "PAMU : failed to allocate spaace =
gen pool\n");
> +		goto error;
> +	}
> +
> +	ret =3D gen_pool_add(spaace_pool, (unsigned long)spaact, =
SPAACT_SIZE, -1);
> +	if (ret)
> +		goto error_genpool;
> +
> +	pamubypenr =3D in_be32(&guts_regs->pamubypenr);
> +
> +	for (pamu_reg_off =3D 0, pamu_counter =3D 0x80000000; =
pamu_reg_off < size;
> +	     pamu_reg_off +=3D PAMU_OFFSET, pamu_counter >>=3D 1) {
> +
> +		pamu_reg_base =3D (unsigned long) pamu_regs + =
pamu_reg_off;
> +		setup_one_pamu(pamu_reg_base, pamu_reg_off, ppaact_phys,
> +				 spaact_phys, omt_phys);
> +		/* Disable PAMU bypass for this PAMU */
> +		pamubypenr &=3D ~pamu_counter;
> +	}
> +
> +	setup_omt(omt);
> +
> +	/* Enable all relevant PAMU(s) */
> +	out_be32(&guts_regs->pamubypenr, pamubypenr);
> +
> +	iounmap(guts_regs);
> +
> +	/* Enable DMA for the LIODNs in the device tree*/
> +
> +	setup_liodns();
> +
> +	return 0;
> +
> +error_genpool:
> +	gen_pool_destroy(spaace_pool);
> +
> +error:
> +	if (irq !=3D NO_IRQ)
> +		free_irq(irq, 0);

Should be:

free_irq(irq, data);

> +
> +	if (pamu_regs)
> +		iounmap(pamu_regs);
> +
> +	if (guts_regs)
> +		iounmap(guts_regs);
> +
> +	if (ppaact)
> +		free_pages((unsigned long)ppaact, order);
> +
> +	ppaact =3D NULL;
> +

you alloc data, shouldn't you free it ?

> +	return ret;
> +}
> +
> +

^ permalink raw reply

* Re: [PATCH 5/5 v9] iommu/fsl: Freescale PAMU driver and iommu implementation.
From: Kumar Gala @ 2013-03-14 20:22 UTC (permalink / raw)
  To: Varun Sethi
  Cc: joro, linux-kernel, stuart.yoder, iommu, scottwood, linuxppc-dev
In-Reply-To: <0080B56D-8417-41B9-8341-665457D04DE6@kernel.crashing.org>


On Mar 14, 2013, at 3:20 PM, Kumar Gala wrote:

>=20
> On Mar 13, 2013, at 1:49 PM, Varun Sethi wrote:
>=20
>> +/*
>> + * Table of SVRs and the corresponding PORT_ID values.
>> + *
>> + * All future CoreNet-enabled SOCs will have this erratum fixed, so =
this table
>> + * should never need to be updated.  SVRs are guaranteed to be =
unique, so
>> + * there is no worry that a future SOC will inadvertently have one =
of these
>> + * values.
>> + */
>=20
> Maybe add to the comment about what port_id represents

also, add reference to the erratum #/id/name

>=20
>> +static const struct {
>> +	u32 svr;
>> +	u32 port_id;
>> +} port_id_map[] =3D {
>> +	{0x82100010, 0xFF000000},	/* P2040 1.0 */
>> +	{0x82100011, 0xFF000000},	/* P2040 1.1 */
>> +	{0x82100110, 0xFF000000},	/* P2041 1.0 */
>> +	{0x82100111, 0xFF000000},	/* P2041 1.1 */
>> +	{0x82110310, 0xFF000000},	/* P3041 1.0 */
>> +	{0x82110311, 0xFF000000},	/* P3041 1.1 */
>> +	{0x82010020, 0xFFF80000},	/* P4040 2.0 */
>> +	{0x82000020, 0xFFF80000},	/* P4080 2.0 */
>> +	{0x82210010, 0xFC000000},       /* P5010 1.0 */
>> +	{0x82210020, 0xFC000000},       /* P5010 2.0 */
>> +	{0x82200010, 0xFC000000},	/* P5020 1.0 */
>> +	{0x82050010, 0xFF800000},	/* P5021 1.0 */
>> +	{0x82040010, 0xFF800000},	/* P5040 1.0 */
>> +};
>> +
>> +#define SVR_SECURITY	0x80000	/* The Security (E) bit */
>> +
>> +static int __init fsl_pamu_probe(struct platform_device *pdev)
>> +{
>> +	void __iomem *pamu_regs =3D NULL;
>> +	struct ccsr_guts __iomem *guts_regs =3D NULL;
>> +	u32 pamubypenr, pamu_counter;
>> +	unsigned long pamu_reg_off;
>> +	unsigned long pamu_reg_base;
>> +	struct pamu_isr_data *data;
>> +	struct device_node *guts_node;
>> +	u64 size;
>> +	struct page *p;
>> +	int ret =3D 0;
>> +	int irq;
>> +	phys_addr_t ppaact_phys;
>> +	phys_addr_t spaact_phys;
>> +	phys_addr_t omt_phys;
>> +	size_t mem_size =3D 0;
>> +	unsigned int order =3D 0;
>> +	u32 csd_port_id =3D 0;
>> +	unsigned i;
>> +	/*
>> +	 * enumerate all PAMUs and allocate and setup PAMU tables
>> +	 * for each of them,
>> +	 * NOTE : All PAMUs share the same LIODN tables.
>> +	 */
>> +
>> +	pamu_regs =3D of_iomap(pdev->dev.of_node, 0);
>> +	if (!pamu_regs) {
>> +		dev_err(&pdev->dev, "ioremap of PAMU node failed\n");
>> +		return -ENOMEM;
>> +	}
>> +	of_get_address(pdev->dev.of_node, 0, &size, NULL);
>> +
>> +	irq =3D irq_of_parse_and_map(pdev->dev.of_node, 0);
>> +	if (irq =3D=3D NO_IRQ) {
>> +		dev_warn(&pdev->dev, "no interrupts listed in PAMU =
node\n");
>> +		goto error;
>> +	}
>> +
>> +	data =3D kzalloc(sizeof(struct pamu_isr_data), GFP_KERNEL);
>> +	if (!data) {
>> +		iounmap(pamu_regs);
>> +		return -ENOMEM;
>> +	}
>> +	data->pamu_reg_base =3D pamu_regs;
>> +	data->count =3D size / PAMU_OFFSET;
>> +
>> +	/* The ISR needs access to the regs, so we won't iounmap them */
>> +	ret =3D request_irq(irq, pamu_av_isr, 0, "pamu", data);
>> +	if (ret < 0) {
>> +		dev_err(&pdev->dev, "error %i installing ISR for irq =
%i\n",
>> +			ret, irq);
>> +		goto error;
>> +	}
>> +
>> +	guts_node =3D of_find_compatible_node(NULL, NULL,
>> +			"fsl,qoriq-device-config-1.0");
>=20
> This doesn't work for T4 or B4 device trees.
>=20
>> +	if (!guts_node) {
>> +		dev_err(&pdev->dev, "could not find GUTS node %s\n",
>> +			pdev->dev.of_node->full_name);
>> +		ret =3D -ENODEV;
>> +		goto error;
>> +	}
>> +
>> +	guts_regs =3D of_iomap(guts_node, 0);
>> +	of_node_put(guts_node);
>> +	if (!guts_regs) {
>> +		dev_err(&pdev->dev, "ioremap of GUTS node failed\n");
>> +		ret =3D -ENODEV;
>> +		goto error;
>> +	}
>> +
>> +	/* read in the PAMU capability registers */
>> +	get_pamu_cap_values((unsigned long)pamu_regs);
>> +	/*
>> +	 * To simplify the allocation of a coherency domain, we allocate =
the
>> +	 * PAACT and the OMT in the same memory buffer.  Unfortunately, =
this
>> +	 * wastes more memory compared to allocating the buffers =
separately.
>> +	 */
>> +	/* Determine how much memory we need */
>> +	mem_size =3D (PAGE_SIZE << get_order(PAACT_SIZE)) +
>> +		(PAGE_SIZE << get_order(SPAACT_SIZE)) +
>> +		(PAGE_SIZE << get_order(OMT_SIZE));
>> +	order =3D get_order(mem_size);
>> +
>> +	p =3D alloc_pages(GFP_KERNEL | __GFP_ZERO, order);
>> +	if (!p) {
>> +		dev_err(&pdev->dev, "unable to allocate PAACT/SPAACT/OMT =
block\n");
>> +		ret =3D -ENOMEM;
>> +		goto error;
>> +	}
>> +
>> +	ppaact =3D page_address(p);
>> +	ppaact_phys =3D page_to_phys(p);
>> +
>> +	/* Make sure the memory is naturally aligned */
>> +	if (ppaact_phys & ((PAGE_SIZE << order) - 1)) {
>> +		dev_err(&pdev->dev, "PAACT/OMT block is unaligned\n");
>> +		ret =3D -ENOMEM;
>> +		goto error;
>> +	}
>> +
>> +	spaact =3D (void *)ppaact + (PAGE_SIZE << =
get_order(PAACT_SIZE));
>> +	omt =3D (void *)spaact + (PAGE_SIZE << get_order(SPAACT_SIZE));
>> +
>> +	dev_dbg(&pdev->dev, "ppaact virt=3D%p phys=3D0x%llx\n", ppaact,
>> +		(unsigned long long) ppaact_phys);
>> +
>> +	/* Check to see if we need to implement the work-around on this =
SOC */
>> +
>> +	/* Determine the Port ID for our coherence subdomain */
>> +	for (i =3D 0; i < ARRAY_SIZE(port_id_map); i++) {
>> +		if (port_id_map[i].svr =3D=3D (mfspr(SPRN_SVR) & =
~SVR_SECURITY)) {
>> +			csd_port_id =3D port_id_map[i].port_id;
>> +			dev_dbg(&pdev->dev, "found matching SVR %08x\n",
>> +				port_id_map[i].svr);
>> +			break;
>> +		}
>> +	}
>> +
>> +	if (csd_port_id) {
>> +		dev_dbg(&pdev->dev, "creating coherency subdomain at =
address "
>> +			"0x%llx, size %zu, port id 0x%08x", ppaact_phys,
>> +			mem_size, csd_port_id);
>> +
>> +		ret =3D create_csd(ppaact_phys, mem_size, csd_port_id);
>> +		if (ret) {
>> +			dev_err(&pdev->dev, "could not create coherence =
"
>> +				"subdomain\n");
>> +			return ret;
>> +		}
>> +	}
>> +
>> +	spaact_phys =3D virt_to_phys(spaact);
>> +	omt_phys =3D virt_to_phys(omt);
>> +
>> +	spaace_pool =3D gen_pool_create(ilog2(sizeof(struct paace)), =
-1);
>> +	if (!spaace_pool) {
>> +		ret =3D -ENOMEM;
>> +		dev_err(&pdev->dev, "PAMU : failed to allocate spaace =
gen pool\n");
>> +		goto error;
>> +	}
>> +
>> +	ret =3D gen_pool_add(spaace_pool, (unsigned long)spaact, =
SPAACT_SIZE, -1);
>> +	if (ret)
>> +		goto error_genpool;
>> +
>> +	pamubypenr =3D in_be32(&guts_regs->pamubypenr);
>> +
>> +	for (pamu_reg_off =3D 0, pamu_counter =3D 0x80000000; =
pamu_reg_off < size;
>> +	     pamu_reg_off +=3D PAMU_OFFSET, pamu_counter >>=3D 1) {
>> +
>> +		pamu_reg_base =3D (unsigned long) pamu_regs + =
pamu_reg_off;
>> +		setup_one_pamu(pamu_reg_base, pamu_reg_off, ppaact_phys,
>> +				 spaact_phys, omt_phys);
>> +		/* Disable PAMU bypass for this PAMU */
>> +		pamubypenr &=3D ~pamu_counter;
>> +	}
>> +
>> +	setup_omt(omt);
>> +
>> +	/* Enable all relevant PAMU(s) */
>> +	out_be32(&guts_regs->pamubypenr, pamubypenr);
>> +
>> +	iounmap(guts_regs);
>> +
>> +	/* Enable DMA for the LIODNs in the device tree*/
>> +
>> +	setup_liodns();
>> +
>> +	return 0;
>> +
>> +error_genpool:
>> +	gen_pool_destroy(spaace_pool);
>> +
>> +error:
>> +	if (irq !=3D NO_IRQ)
>> +		free_irq(irq, 0);
>=20
> Should be:
>=20
> free_irq(irq, data);
>=20
>> +
>> +	if (pamu_regs)
>> +		iounmap(pamu_regs);
>> +
>> +	if (guts_regs)
>> +		iounmap(guts_regs);
>> +
>> +	if (ppaact)
>> +		free_pages((unsigned long)ppaact, order);
>> +
>> +	ppaact =3D NULL;
>> +
>=20
> you alloc data, shouldn't you free it ?
>=20
>> +	return ret;
>> +}
>> +
>> +
>=20
> _______________________________________________
> Linuxppc-dev mailing list
> Linuxppc-dev@lists.ozlabs.org
> https://lists.ozlabs.org/listinfo/linuxppc-dev

^ permalink raw reply

* Re: [RFC][PATCH 2/2] powerpc/fsl-pci Make PCIe hotplug work with Freescale
From: Kumar Gala @ 2013-03-14 20:35 UTC (permalink / raw)
  To: Rojhalat Ibrahim; +Cc: linuxppc-dev
In-Reply-To: <4166754.n4Zsp0OSQ4@pcimr>


On Mar 14, 2013, at 4:43 AM, Rojhalat Ibrahim wrote:

> On Wednesday 13 March 2013 14:07:16 Kumar Gala wrote:
>> diff --git a/arch/powerpc/sysdev/fsl_pci.c =
b/arch/powerpc/sysdev/fsl_pci.c
>> index 41bbcc4..b18c377 100644
>> --- a/arch/powerpc/sysdev/fsl_pci.c
>> +++ b/arch/powerpc/sysdev/fsl_pci.c
>> @@ -74,6 +74,35 @@ static int __init fsl_pcie_check_link(struct
>> pci_controller *hose) return 0;
>> }
>>=20
>> +static int fsl_indirect_read_config(struct pci_bus *bus, unsigned =
int
>> devfn, +				    int offset, int len, u32 =
*val)
>> +{
>> +	struct pci_controller *hose =3D pci_bus_to_host(bus);
>> +
>> +	/* check the link status */
>> +	if ((bus->number =3D=3D hose->first_busno) && (devfn =3D=3D 0)) =
{
>> +		if (fsl_pcie_check_link(hose))
>> +			hose->indirect_type |=3D =
PPC_INDIRECT_TYPE_NO_PCIE_LINK;
>> +		else
>> +			hose->indirect_type &=3D =
~PPC_INDIRECT_TYPE_NO_PCIE_LINK;
>> +	}
>> +	return indirect_read_config(bus, devfn, offset, len, val);
>> +}
>> +
>=20
> This does not work because fsl_indirect_read_config calls =
fsl_pcie_check_link which calls early_read_config_dword which eventually =
calls fsl_indirect_read_config, so the kernel hangs in a recursion loop. =
Below is a modified patch that does work.

ok, that makes sense, but I guess now its making me question the =
following statement:

> if ((bus->number =3D=3D hose->first_busno) && (devfn =3D=3D 0)) {

Why do we have this conditional?

- k=

^ permalink raw reply

* Re: [PATCH] mv643xx_eth: convert to use the Marvell Orion MDIO driver
From: Jason Cooper @ 2013-03-14 20:36 UTC (permalink / raw)
  To: Florian Fainelli
  Cc: Thomas Petazzoni, Andrew Lunn, Russell King, linux-doc,
	devicetree-discuss, linux-kernel, Rob Herring, Greg Kroah-Hartman,
	Paul Mackerras, Lennert Buytenhek, Rob Landley, netdev,
	linuxppc-dev, davem, linux-arm-kernel
In-Reply-To: <514225E9.9060902@openwrt.org>

On Thu, Mar 14, 2013 at 08:32:57PM +0100, Florian Fainelli wrote:
> Hello Jason,
>=20
> Le 14/03/2013 20:02, Jason Cooper a =E9crit :
> >Florian,
> >
> >On Thu, Mar 14, 2013 at 07:08:32PM +0100, Florian Fainelli wrote:
> >>This patch converts the Marvell MV643XX ethernet driver to use the
> >>Marvell Orion MDIO driver. As a result, PowerPC and ARM platforms
> >>registering the Marvell MV643XX ethernet driver are also updated to
> >>register a Marvell Orion MDIO driver. This driver voluntarily overlap=
s
> >>with the Marvell Ethernet shared registers because it will use a subs=
et
> >>of this shared register (shared_base + 0x4 - shared_base + 0x84). The
> >>Ethernet driver is also updated to look up for a PHY device using the
> >>Orion MDIO bus driver.
> >>
> >>Signed-off-by: Florian Fainelli <florian@openwrt.org>
> >>---
> >>  arch/arm/plat-orion/common.c               |   97 +++++++++++----
> >>  arch/powerpc/platforms/chrp/pegasos_eth.c  |   20 +++
> >>  arch/powerpc/sysdev/mv64x60_dev.c          |   14 ++-
> >>  drivers/net/ethernet/marvell/Kconfig       |    1 +
> >>  drivers/net/ethernet/marvell/mv643xx_eth.c |  186 ++---------------=
-----------
> >>  include/linux/mv643xx_eth.h                |    1 -
> >>  6 files changed, 117 insertions(+), 202 deletions(-)
> >
> >Isn't this the old version of 4/4 ?
>=20
> No this really is v2, but I reformatted just that one and sent it
> without the v2 changelog, you should have received the proper
> version a couple minutes later once I realized my mistake.

Yes, I received both, just making sure.

thx,

Jason.

^ permalink raw reply

* RE: [PATCH 5/5 v9] iommu/fsl: Freescale PAMU driver and iommu implementation.
From: Yoder Stuart-B08248 @ 2013-03-14 21:14 UTC (permalink / raw)
  To: Kumar Gala, Sethi Varun-B16395
  Cc: Wood Scott-B07421, joro@8bytes.org, linux-kernel@vger.kernel.org,
	iommu@lists.linux-foundation.org, linuxppc-dev@lists.ozlabs.org
In-Reply-To: <0080B56D-8417-41B9-8341-665457D04DE6@kernel.crashing.org>



> -----Original Message-----
> From: Kumar Gala [mailto:galak@kernel.crashing.org]
> Sent: Thursday, March 14, 2013 3:20 PM
> To: Sethi Varun-B16395
> Cc: joro@8bytes.org; iommu@lists.linux-foundation.org; linuxppc-dev@lists=
.ozlabs.org; linux-
> kernel@vger.kernel.org; benh@kernel.crashing.org; Wood Scott-B07421; Yode=
r Stuart-B08248
> Subject: Re: [PATCH 5/5 v9] iommu/fsl: Freescale PAMU driver and iommu im=
plementation.
>=20
>=20
> On Mar 13, 2013, at 1:49 PM, Varun Sethi wrote:
>=20
> > +/*
> > + * Table of SVRs and the corresponding PORT_ID values.
> > + *
> > + * All future CoreNet-enabled SOCs will have this erratum fixed, so th=
is table
> > + * should never need to be updated.  SVRs are guaranteed to be unique,=
 so
> > + * there is no worry that a future SOC will inadvertently have one of =
these
> > + * values.
> > + */
>=20
> Maybe add to the comment about what port_id represents

When you update the comment, I would also suggest identifying the specific
errata here (A-004510) so that it's easy to reference back to the specific
issue this code is fixing.

Stuart

^ permalink raw reply

* RE: [PATCH V2] powerpc/85xx: workaround for chips with MSI hardware errata
From: Jia Hongtao-B38951 @ 2013-03-15  2:00 UTC (permalink / raw)
  To: Kumar Gala
  Cc: Wood Scott-B07421, linuxppc-dev@lists.ozlabs.org, Li Yang-R58472
In-Reply-To: <6844A08B-8711-47AE-ACF1-9FAC23460710@kernel.crashing.org>



> -----Original Message-----
> From: Kumar Gala [mailto:galak@kernel.crashing.org]
> Sent: Friday, March 15, 2013 4:05 AM
> To: Jia Hongtao-B38951
> Cc: linuxppc-dev@lists.ozlabs.org; Wood Scott-B07421;
> michael@ellerman.id.au; Li Yang-R58472; Jia Hongtao-B38951
> Subject: Re: [PATCH V2] powerpc/85xx: workaround for chips with MSI
> hardware errata
>=20
>=20
> On Mar 14, 2013, at 5:35 AM, Jia Hongtao wrote:
>=20
> > The MPIC version 2.0 has a MSI errata (errata PIC1 of mpc8544), It
> > causes that neither MSI nor MSI-X can work fine. This is a workaround
> > to allow MSI-X to function properly.
> >
> > Signed-off-by: Liu Shuo <soniccat.liu@gmail.com>
> > Signed-off-by: Li Yang <leoli@freescale.com>
> > Signed-off-by: Jia Hongtao <hongtao.jia@freescale.com>
> > ---
> > Changes for V2:
> > - Address almost all the comments from Michael Ellerman for V1.
> >  Here is the link:
> >  http://patchwork.ozlabs.org/patch/226833/
> >
> > arch/powerpc/sysdev/fsl_msi.c | 65
> > +++++++++++++++++++++++++++++++++++++++++--
> > arch/powerpc/sysdev/fsl_msi.h |  2 ++
> > 2 files changed, 64 insertions(+), 3 deletions(-)
> >
> > diff --git a/arch/powerpc/sysdev/fsl_msi.c
> > b/arch/powerpc/sysdev/fsl_msi.c index 178c994..54cb83e 100644
> > --- a/arch/powerpc/sysdev/fsl_msi.c
> > +++ b/arch/powerpc/sysdev/fsl_msi.c
> > @@ -98,8 +98,18 @@ static int fsl_msi_init_allocator(struct fsl_msi
> > *msi_data)
> >
> > static int fsl_msi_check_device(struct pci_dev *pdev, int nvec, int
> > type) {
> > -	if (type =3D=3D PCI_CAP_ID_MSIX)
> > -		pr_debug("fslmsi: MSI-X untested, trying anyway.\n");
> > +	struct fsl_msi *msi;
> > +
> > +	if (type =3D=3D PCI_CAP_ID_MSI) {
> > +		/*
> > +		 * MPIC version 2.0 has erratum PIC1. For now MSI
> > +		 * could not work. So check to prevent MSI from
> > +		 * being used on the board with this erratum.
> > +		 */
> > +		list_for_each_entry(msi, &msi_head, list)
> > +			if (msi->feature & MSI_HW_ERRATA_ENDIAN)
> > +				return -EINVAL;
> > +	}
> >
> > 	return 0;
> > }
> > @@ -142,7 +152,17 @@ static void fsl_compose_msi_msg(struct pci_dev
> *pdev, int hwirq,
> > 	msg->address_lo =3D lower_32_bits(address);
> > 	msg->address_hi =3D upper_32_bits(address);
> >
> > -	msg->data =3D hwirq;
> > +	/*
> > +	 * MPIC version 2.0 has erratum PIC1. It causes
> > +	 * that neither MSI nor MSI-X can work fine.
> > +	 * This is a workaround to allow MSI-X to function
> > +	 * properly. It only works for MSI-X, we prevent
> > +	 * MSI on buggy chips in fsl_msi_check_device().
> > +	 */
> > +	if (msi_data->feature & MSI_HW_ERRATA_ENDIAN)
> > +		msg->data =3D __swab32(hwirq);
> > +	else
> > +		msg->data =3D hwirq;
> >
> > 	pr_debug("%s: allocated srs: %d, ibs: %d\n",
> > 		__func__, hwirq / IRQS_PER_MSI_REG, hwirq % IRQS_PER_MSI_REG);
> @@
> > -361,6 +381,35 @@ static int fsl_msi_setup_hwirq(struct fsl_msi *msi,
> struct platform_device *dev,
> > 	return 0;
> > }
> >
> > +/* MPIC version 2.0 has erratum PIC1 */ static int
> > +mpic_has_errata(struct platform_device *dev) {
> > +	struct device_node *mpic_node;
> > +
> > +	mpic_node =3D of_irq_find_parent(dev->dev.of_node);
> > +	if (mpic_node) {
> > +		u32 *reg_base, brr1 =3D 0;
> > +		/* Get the PIC reg base */
> > +		reg_base =3D of_iomap(mpic_node, 0);
> > +		of_node_put(mpic_node);
> > +		if (!reg_base) {
> > +			dev_err(&dev->dev, "ioremap problem failed.\n");
> > +			return -EIO;
> > +		}
> > +
> > +		/* Get the mpic version from block revision register 1 */
> > +		brr1 =3D in_be32(reg_base + MPIC_FSL_BRR1);
> > +		iounmap(reg_base);
> > +		if ((brr1 & MPIC_FSL_BRR1_VER) =3D=3D 0x0200)
> > +			return 1;
> > +	} else {
> > +		dev_err(&dev->dev, "MSI can't find his parent mpic node.\n");
> > +		return -ENODEV;
> > +	}
> > +
> > +	return 0;
> > +}
> > +
> > static const struct of_device_id fsl_of_msi_ids[]; static int
> > fsl_of_msi_probe(struct platform_device *dev) { @@ -423,6 +472,16 @@
> > static int fsl_of_msi_probe(struct platform_device *dev)
> >
> > 	msi->feature =3D features->fsl_pic_ip;
> >
> > +	if ((features->fsl_pic_ip & FSL_PIC_IP_MASK) =3D=3D FSL_PIC_IP_MPIC) =
{
> > +		rc =3D mpic_has_errata(dev);
> > +		if (rc > 0) {
> > +			msi->feature |=3D MSI_HW_ERRATA_ENDIAN;
> > +		} else if (rc < 0) {
> > +			err =3D rc;
> > +			goto error_out;
> > +		}
> > +	}
> > +
> > 	/*
> > 	 * Remember the phandle, so that we can match with any PCI nodes
> > 	 * that have an "fsl,msi" property.
> > diff --git a/arch/powerpc/sysdev/fsl_msi.h
> > b/arch/powerpc/sysdev/fsl_msi.h index 8225f86..7389e8e 100644
> > --- a/arch/powerpc/sysdev/fsl_msi.h
> > +++ b/arch/powerpc/sysdev/fsl_msi.h
> > @@ -25,6 +25,8 @@
> > #define FSL_PIC_IP_IPIC   0x00000002
> > #define FSL_PIC_IP_VMPIC  0x00000003
> >
> > +#define MSI_HW_ERRATA_ENDIAN 0x00000010
> > +
>=20
> Is there any reason to put this in fsl_msi.h rather than just in
> fsl_msi.c itself?
>=20
> - k

Actually no. This micro is only used by fsl_msi.c.
Will move it to fsl_msi.c.

Thanks.
-Hongtao.

>=20
> > struct fsl_msi {
> > 	struct irq_domain *irqhost;
> >
> > --
> > 1.8.0
> >
>=20

^ permalink raw reply

* RE: [PATCH V4] powerpc/85xx: Add machine check handler to fix PCIe erratum on mpc85xx
From: Jia Hongtao-B38951 @ 2013-03-15  2:47 UTC (permalink / raw)
  To: Wood Scott-B07421, David Laight
  Cc: linuxppc-dev@lists.ozlabs.org, Stuart Yoder
In-Reply-To: <1363192659.8945.1@snotra>


> -----Original Message-----
> From: Wood Scott-B07421
> Sent: Thursday, March 14, 2013 12:38 AM
> To: David Laight
> Cc: Jia Hongtao-B38951; Wood Scott-B07421; linuxppc-dev@lists.ozlabs.org;
> Stuart Yoder
> Subject: Re: [PATCH V4] powerpc/85xx: Add machine check handler to fix
> PCIe erratum on mpc85xx
>=20
> On 03/13/2013 04:40:40 AM, David Laight wrote:
> > > Hmm, seems there's no probe_user_address() -- for userspace we
> > > basically want the same thing minus the KERNEL_DS.  See
> > > arch/powerpc/perf/callchain.c for an example.
> >
> > Isn't that just copy_from_user() ?
>=20
> Plus pagefault_disable/enable().
>=20
> -Scott

pagefault_disable() is identical to preempt_disable(). So I think this
could not avoid other cpu to swap out the instruction we want to read back.
probe_kernel_address() also have the same issue.

Does this mean we can't just use pagefault_disable() to prevent from gettin=
g
the wrong instruction?

-Hongtao.

^ permalink raw reply

* [Suggestion] PowerPC: kernel: cross compiling issue with allmodconfig
From: Chen Gang @ 2013-03-15  2:50 UTC (permalink / raw)
  To: Benjamin Herrenschmidt, paulus@samba.org, mikey, matt, imunsie
  Cc: linuxppc-dev, linux-kernel@vger.kernel.org

Hello Maintainers:

  do next-* tree support powerpc POWER7 with allmodconfig ?

  I met an issue, can we bear it (or I need additional trying) ?


Compiling:
  make V=1 EXTRA_CFLAGS=-W ARCH=powerpc allmodconfig
    set cpu type POWER7 in menuconfig.
    set cross-compiler in menuconfig.
      under Fedora 16 x86_64 laptop
      /usr/bin/powerpc64-linux-gnu-gcc -v
        gcc version 4.7.1 20120606 (Red Hat 4.7.1-0.1.20120606) (GCC)

Issue:
  error:
    /android/public-kernel/linux-next/arch/powerpc/kernel/exceptions-64s.S: Assembler messages:
    /android/public-kernel/linux-next/arch/powerpc/kernel/exceptions-64s.S:1304: Error: attempt to move .org backwards

  command:
    powerpc64-linux-gnu-gcc -m64 -Wp,-MD,arch/powerpc/kernel/.head_64.o.d  -nostdinc -isystem /usr/lib/gcc/powerpc64-linux-gnu/4.7.1/include -I/android/public-kernel/linux-next/arch/powerpc/include -Iarch/powerpc/include/generated  -I/android/public-kernel/linux-next/include -Iinclude -I/android/public-kernel/linux-next/arch/powerpc/include/uapi -Iarch/powerpc/include/generated/uapi -I/android/public-kernel/linux-next/include/uapi -Iinclude/generated/uapi -include /android/public-kernel/linux-next/include/linux/kconfig.h -D__KERNEL__  -I/android/public-kernel/linux-next/arch/powerpc -Iarch/powerpc -D__ASSEMBLY__  -I/android/public-kernel/linux-next/arch/powerpc -Iarch/powerpc -Wa,-maltivec -gdwarf-2   -c -o arch/powerpc/kernel/head_64.o /android/public-kernel/linux-next/arch/powerpc/kernel/head_64.S

  (head_64.S includes exceptions-64.S)


  thanks.

-- 
Chen Gang

Asianux Corporation

^ permalink raw reply

* Re: [Suggestion] PowerPC: kernel: cross compiling issue with allmodconfig
From: Michael Neuling @ 2013-03-15  4:52 UTC (permalink / raw)
  To: Chen Gang, sfr
  Cc: matt, linux-kernel@vger.kernel.org, paulus@samba.org, imunsie,
	linuxppc-dev
In-Reply-To: <51428C81.6000204@asianux.com>

>   do next-* tree support powerpc POWER7 with allmodconfig ?
> 
>   I met an issue, can we bear it (or I need additional trying) ?
> 
> 
> Compiling:
>   make V=1 EXTRA_CFLAGS=-W ARCH=powerpc allmodconfig
>     set cpu type POWER7 in menuconfig.
>     set cross-compiler in menuconfig.
>       under Fedora 16 x86_64 laptop
>       /usr/bin/powerpc64-linux-gnu-gcc -v
>         gcc version 4.7.1 20120606 (Red Hat 4.7.1-0.1.20120606) (GCC)
> 
> Issue:
>   error:
>     /android/public-kernel/linux-next/arch/powerpc/kernel/exceptions-64s.S: Assembler messages:
>     /android/public-kernel/linux-next/arch/powerpc/kernel/exceptions-64s.S:1304: Error: attempt to move .org backwards
> 
>   command:
>     powerpc64-linux-gnu-gcc -m64 -Wp,-MD,arch/powerpc/kernel/.head_64.o.d  -nostdinc -isystem /usr/lib/gcc/powerpc64-linux-gnu/4.7.1/include -I/android/public-kernel/linux-next/arch/powerpc/include -Iarch/powerpc/include/generated  -I/android/public-kernel/linux-next/include -Iinclude -I/android/public-kernel/linux-next/arch/powerpc/include/uapi -Iarch/powerpc/include/generated/uapi -I/android/public-kernel/linux-next/include/uapi -Iinclude/generated/uapi -include /android/public-kernel/linux-next/include/linux/kconfig.h -D__KERNEL__  -I/android/public-kernel/linux-next/arch/powerpc -Iarch/powerpc -D__ASSEMBLY__  -I/android/public-kernel/linux-next/arch/powerpc -Iarch/powerpc -Wa,-maltivec -gdwarf-2   -c -o arch/powerpc/kernel/head_64.o /android/public-kernel/linux-next/arch/powerpc/kernel/head_64.S
> 
>   (head_64.S includes exceptions-64.S)

Yep it's a known problem but no one has bothered to fix it since it
doesn't happen in a config that anyone cares about like
pseries_defconfig and ppc64_defconfig.  We've been moving code around in
this area a lot recently hence the breakage.

It should be fixed though.  Patches welcome. :-)

Mikey

^ permalink raw reply

* Re: [Suggestion] PowerPC: kernel: cross compiling issue with allmodconfig
From: Chen Gang @ 2013-03-15  5:14 UTC (permalink / raw)
  To: Michael Neuling
  Cc: sfr, matt, linux-kernel@vger.kernel.org, paulus@samba.org,
	imunsie, linuxppc-dev
In-Reply-To: <25841.1363323174@ale.ozlabs.ibm.com>

于 2013年03月15日 12:52, Michael Neuling 写道:
> Yep it's a known problem but no one has bothered to fix it since it
> doesn't happen in a config that anyone cares about like
> pseries_defconfig and ppc64_defconfig.  We've been moving code around in
> this area a lot recently hence the breakage.
> 
> It should be fixed though.  Patches welcome. :-)

  thanks, and I should try, and very glad to try.

  :-)  :-)

  excuse me, I try to provide related patch within this month (2013-03-31), is it ok ?
  the reason is:
    I am not familiar with ppc assembly code, neither ppc kernel,
    so need additional time resource.
      (originally, I worked for x86(_64) core dump analysing for kernel and user programs)

  thanks.

-- 
Chen Gang

Asianux Corporation

^ permalink raw reply

* RE: [PATCH] powerpc/85xx: Add platform_device declaration to fsl_pci.h
From: Jia Hongtao-B38951 @ 2013-03-15  6:15 UTC (permalink / raw)
  To: Kumar Gala
  Cc: Wood Scott-B07421, linuxppc-dev@lists.ozlabs.org, Li Yang-R58472
In-Reply-To: <1A66AF08-B77F-419C-B742-87EE61DBB11F@kernel.crashing.org>



> -----Original Message-----
> From: Kumar Gala [mailto:galak@kernel.crashing.org]
> Sent: Wednesday, March 13, 2013 4:46 AM
> To: Jia Hongtao-B38951
> Cc: linuxppc-dev@lists.ozlabs.org; Wood Scott-B07421; Li Yang-R58472
> Subject: Re: [PATCH] powerpc/85xx: Add platform_device declaration to
> fsl_pci.h
>=20
>=20
> On Mar 10, 2013, at 9:36 PM, Jia Hongtao-B38951 wrote:
>=20
> >
> >
> >> -----Original Message-----
> >> From: Kumar Gala [mailto:galak@kernel.crashing.org]
> >> Sent: Saturday, March 09, 2013 4:38 AM
> >> To: Jia Hongtao-B38951
> >> Cc: linuxppc-dev@lists.ozlabs.org; Wood Scott-B07421; Li Yang-R58472
> >> Subject: Re: [PATCH] powerpc/85xx: Add platform_device declaration to
> >> fsl_pci.h
> >>
> >>
> >> On Mar 4, 2013, at 2:40 AM, Jia Hongtao wrote:
> >>
> >>> mpc85xx_pci_err_probe(struct platform_device *op) need
> platform_device
> >>> declaration for definition. Otherwise, it will cause compile error if
> >>> any files including fsl_pci.h without declaration of platform_device.
> >>>
> >>> Signed-off-by: Jia Hongtao <B38951@freescale.com>
> >>> ---
> >>> arch/powerpc/sysdev/fsl_pci.h |    2 ++
> >>> 1 files changed, 2 insertions(+), 0 deletions(-)
> >>>
> >>
> >> Where does the compile error show up?
> >>
> >> - k
> >
> > The function mpc85xx_pci_err_probe(struct platform_device *op) need
> > *platform_device* declaration so <linux/platform_device.h> must be
> > included.
> >
> > For now there is no compile error occurred just because the file that
> > need fsl_pci.h happened to include <linux/platform_device.h> already.
> >
> > If not the compile error log will be like this:
> > "
> > In file included from arch/powerpc/kernel/traps.c:62:0:
> > arch/powerpc/sysdev/fsl_pci.h:108:34: error: 'struct platform_device'
> declared inside parameter list
> > arch/powerpc/sysdev/fsl_pci.h:108:34: error: its scope is only this
> definition or declaration, which is probably not what you want
> > "
> >
> > You mean I have to show the compile error log in patch description?
>=20
> Not necessarily, I'm just trying to decide if we should include
> <linux/platform_device.h> or just do:
>=20
> struct platform_device;
>=20
> near the top of fsl_pci.h.

Actually just add "struct platform_device;" works too.
Only mpc85xx_edac.c use mpc85xx_pci_err_probe(struct platform_device *op)
and <linux/platform_device.h> has already included there.

I will update and send the new patch.

-Hongtao.=20

>=20
> >
> > Thanks.
> > -Hongtao.
> >
> >>
> >>> diff --git a/arch/powerpc/sysdev/fsl_pci.h
> >>> b/arch/powerpc/sysdev/fsl_pci.h index c495c00..df66721 100644
> >>> --- a/arch/powerpc/sysdev/fsl_pci.h
> >>> +++ b/arch/powerpc/sysdev/fsl_pci.h
> >>> @@ -14,6 +14,8 @@
> >>> #ifndef __POWERPC_FSL_PCI_H
> >>> #define __POWERPC_FSL_PCI_H
> >>>
> >>> +#include <linux/platform_device.h>
> >>> +
> >>> #define PCIE_LTSSM	0x0404		/* PCIE Link Training and
> >> Status */
> >>> #define PCIE_LTSSM_L0	0x16		/* L0 state */
> >>> #define PCIE_IP_REV_2_2		0x02080202 /* PCIE IP block version
> >> Rev2.2 */
> >>> --
> >>> 1.7.5.1
> >>>
> >>
> >
>=20

^ permalink raw reply

* [PATCH V2] powerpc/85xx: Add platform_device declaration to fsl_pci.h
From: Jia Hongtao @ 2013-03-15  6:14 UTC (permalink / raw)
  To: linuxppc-dev, galak; +Cc: B07421, b38951

mpc85xx_pci_err_probe(struct platform_device *op) need platform_device
declaration for definition. Otherwise, it will cause compile error if any
files including fsl_pci.h without declaration of platform_device.

Signed-off-by: Jia Hongtao <hongtao.jia@freescale.com>
---
Changes for V2:
- Just declare platform_device instead of including <linux/platform_device.h>

 arch/powerpc/sysdev/fsl_pci.h | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/arch/powerpc/sysdev/fsl_pci.h b/arch/powerpc/sysdev/fsl_pci.h
index c495c00..851dd56 100644
--- a/arch/powerpc/sysdev/fsl_pci.h
+++ b/arch/powerpc/sysdev/fsl_pci.h
@@ -14,6 +14,8 @@
 #ifndef __POWERPC_FSL_PCI_H
 #define __POWERPC_FSL_PCI_H
 
+struct platform_device;
+
 #define PCIE_LTSSM	0x0404		/* PCIE Link Training and Status */
 #define PCIE_LTSSM_L0	0x16		/* L0 state */
 #define PCIE_IP_REV_2_2		0x02080202 /* PCIE IP block version Rev2.2 */
-- 
1.8.0

^ permalink raw reply related

* [PATCH 0/3] VFIO change for EEH support
From: Gavin Shan @ 2013-03-15  7:26 UTC (permalink / raw)
  To: kvm, linuxppc-dev; +Cc: aik, alex.williamson, Gavin Shan

The EEH (Enhanced Error Handling) is one of RAS features on IBM Power
machines. In order to support EEH, the VFIO needs some modification
as the patchset addresses. Firstly, the address (domain:bus:slot:function)
of passed PCI devices looks quite different from host and guest perspectives.
So we have to mantain the address mapping in host so that the EEH could
direct the EEH errors from guest to proper PCI device. Unfortunately, it
seems that the VFIO implementation doesn't include the mechanism yet. On
the other hand, it's totally business of individual platforms. So I introduced
some weak functions in VFIO driver and individual platforms can override
that to figure out more information that platform needs. Apart from that,
the last patch [3/3] is changing the current behavior of accessing uncoverred
config space for specific PCI device.

The patchset is expected to be applied after Alexy's patchset (supporting
VFIO on PowerNV platform). Besides, there're patchset based on it queued
in my personal tree for EEH core to support PowerKVM guest. With all of
them (Alexy's patchset, this patchset, EEH core patchset), I can sucessfully
pass PCI device to guest and recover it from EEH errors.

drivers/vfio/pci/vfio_pci.c        |   42 ++++++++++++++++++++++++++++++------
drivers/vfio/pci/vfio_pci_config.c |   31 +++++++++++++++++---------
include/linux/vfio.h               |    7 +++++-
include/uapi/linux/vfio.h          |   16 +++++++++++++
4 files changed, 77 insertions(+), 19 deletions(-)

Thanks,
Gavin

^ permalink raw reply

* [PATCH 1/3] VFIO: Architecture dependent VFIO device operations
From: Gavin Shan @ 2013-03-15  7:26 UTC (permalink / raw)
  To: kvm, linuxppc-dev; +Cc: aik, alex.williamson, Gavin Shan
In-Reply-To: <1363332390-12754-1-git-send-email-shangw@linux.vnet.ibm.com>

Some architectures like PPC, especailly PowerNV platform, need to
do additional operations while adding or removing VFIO devices to
or from VFIO bus. The patch adds weak functions while to open,
release or ioctl for the specific VFIO device. Those functions could
be overrided by individual architectures if necessary.

Signed-off-by: Gavin Shan <shangw@linux.vnet.ibm.com>
---
 drivers/vfio/pci/vfio_pci.c |   42 +++++++++++++++++++++++++++++++++++-------
 include/linux/vfio.h        |    7 ++++++-
 2 files changed, 41 insertions(+), 8 deletions(-)

diff --git a/drivers/vfio/pci/vfio_pci.c b/drivers/vfio/pci/vfio_pci.c
index 8189cb6..1a53e77 100644
--- a/drivers/vfio/pci/vfio_pci.c
+++ b/drivers/vfio/pci/vfio_pci.c
@@ -143,32 +143,51 @@ static void vfio_pci_disable(struct vfio_pci_device *vdev)
 	pci_restore_state(pdev);
 }
 
+void __weak vfio_pci_arch_release(struct pci_dev *pdev)
+{
+	return;
+}
+
 static void vfio_pci_release(void *device_data)
 {
 	struct vfio_pci_device *vdev = device_data;
 
-	if (atomic_dec_and_test(&vdev->refcnt))
+	if (atomic_dec_and_test(&vdev->refcnt)) {
+		vfio_pci_arch_release(vdev->pdev);
+
 		vfio_pci_disable(vdev);
+	}
 
 	module_put(THIS_MODULE);
 }
 
+int __weak vfio_pci_arch_open(struct pci_dev *pdev)
+{
+	return 0;
+}
+
 static int vfio_pci_open(void *device_data)
 {
 	struct vfio_pci_device *vdev = device_data;
+	int ret;
 
 	if (!try_module_get(THIS_MODULE))
 		return -ENODEV;
 
 	if (atomic_inc_return(&vdev->refcnt) == 1) {
-		int ret = vfio_pci_enable(vdev);
-		if (ret) {
-			module_put(THIS_MODULE);
-			return ret;
-		}
+		ret = vfio_pci_arch_open(vdev->pdev);
+		if (ret)
+			goto fail;
+
+		ret = vfio_pci_enable(vdev);
+		if (ret)
+			goto fail;
 	}
 
 	return 0;
+fail:
+	module_put(THIS_MODULE);
+	return ret;
 }
 
 static int vfio_pci_get_irq_count(struct vfio_pci_device *vdev, int irq_type)
@@ -206,6 +225,12 @@ static int vfio_pci_get_irq_count(struct vfio_pci_device *vdev, int irq_type)
 	return 0;
 }
 
+long __weak vfio_pci_arch_ioctl(struct pci_dev *pdev,
+				unsigned int cmd, unsigned long arg)
+{
+	return -ENOTTY;
+}
+
 static long vfio_pci_ioctl(void *device_data,
 			   unsigned int cmd, unsigned long arg)
 {
@@ -374,9 +399,12 @@ static long vfio_pci_ioctl(void *device_data,
 
 		return ret;
 
-	} else if (cmd == VFIO_DEVICE_RESET)
+	} else if (cmd == VFIO_DEVICE_RESET) {
 		return vdev->reset_works ?
 			pci_reset_function(vdev->pdev) : -EINVAL;
+	} else {
+		return vfio_pci_arch_ioctl(vdev->pdev, cmd, arg);
+	}
 
 	return -ENOTTY;
 }
diff --git a/include/linux/vfio.h b/include/linux/vfio.h
index ab9e862..a991c39 100644
--- a/include/linux/vfio.h
+++ b/include/linux/vfio.h
@@ -11,9 +11,9 @@
 #ifndef VFIO_H
 #define VFIO_H
 
-
 #include <linux/iommu.h>
 #include <linux/mm.h>
+#include <linux/pci.h>
 #include <uapi/linux/vfio.h>
 
 /**
@@ -40,6 +40,11 @@ struct vfio_device_ops {
 	int	(*mmap)(void *device_data, struct vm_area_struct *vma);
 };
 
+extern int vfio_pci_arch_open(struct pci_dev *pdev);
+extern long vfio_pci_arch_ioctl(struct pci_dev *pdev,
+				unsigned int cmd,
+				unsigned long arg);
+extern void vfio_pci_arch_release(struct pci_dev *pdev);
 extern int vfio_add_group_dev(struct device *dev,
 			      const struct vfio_device_ops *ops,
 			      void *device_data);
-- 
1.7.5.4

^ permalink raw reply related


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox