* P2010 External HW IRQ number?
From: Joakim Tjernlund @ 2012-06-08 11:06 UTC (permalink / raw)
To: linuxppc-dev
I have been trying to figure out what irq number to use for external IRQs for
the P2010. There are no HW IRQ numbers in the ref manual and I cannot find
any examples in the kernel either.
How do specify irq numbers in my dts for external IRQs?
What do I use with request_irq(?,....)?
Jocke
^ permalink raw reply
* need support for PCI driver
From: Mohan @ 2012-06-08 10:38 UTC (permalink / raw)
To: linuxppc-dev
[-- Attachment #1: Type: text/plain, Size: 1729 bytes --]
Sir,
Using PMC -PCI Adapter card ,i have interfaced my PowerPC MPC8280 (which is
configured as PCI bridge) as agent to personal computer. when this setup
having MPC8280 card with powered ON and connected to PC .PC is getting
hanged while system is booting up. I am finding problem when this card is
powered ON state before system is boot up. But if this MPC8280(PCI Bridge)
card with powered ON is connected to PMC carrier adapter after PC has
booted up, it is getting identified by system and able to watch my device
details (configuration space) using "PCI Explorer Software". But using this
software, it is showing this single PCI device as 31 different devices. Why
this is showing as 31 PCI devices? Also why PC is not getting Booted, after
this PCI Bridge in power ON state is connected to PMC -PCI Adapter card that
already in PCI slot of my PC? I am unable to solve this problem.
I am finding the same issue even I am using this set up on Linux based host
.
I approached Freescale support for this issue by sending my PCI card
schematics. They analyzed and came up with small changes, but still we could
not able to solve this problem. So we wanted to start tracing the problem
from software side. That's why I wanted to install my PCI card into Linux
based host. To do this whether I need to write /include any driver code
into my Linux host .If I need to write driver code how to start & where
exactly needs changes/inclusions of code stuff in linux code.
Already I am studying kernel documentation and drivers code under source
code. Referring Linux device Driver 3rd edition O'reilly s book.
I am new to linux.
Please help me in getting through this problem.
Thanks & regards
V mohan rao
[-- Attachment #2: Type: text/html, Size: 4012 bytes --]
^ permalink raw reply
* RE: [PATCH 0/6] Description for PCI patches using platform driver
From: Bhushan Bharat-R65777 @ 2012-06-08 10:47 UTC (permalink / raw)
To: Jia Hongtao-B38951, linuxppc-dev@lists.ozlabs.org,
galak@kernel.crashing.org
Cc: Li Yang-R58472, Wood Scott-B07421
In-Reply-To: <1339148527-16911-1-git-send-email-B38951@freescale.com>
> -----Original Message-----
> From: Jia Hongtao-B38951
> Sent: Friday, June 08, 2012 3:12 PM
> To: linuxppc-dev@lists.ozlabs.org; galak@kernel.crashing.org
> Cc: Li Yang-R58472; benh@kernel.crashing.org; Wood Scott-B07421; Bhushan =
Bharat-
> R65777; Jia Hongtao-B38951
> Subject: [PATCH 0/6] Description for PCI patches using platform driver
>=20
> This series of patches are to unify pci initialization code and add PM su=
pport
> for all 85xx/86xx powerpc boards. But two side effects are introduced by =
this
> mechanism which listed below:
>=20
> 1. of_platform_bus_probe() will be called twice but in some cases duplica=
tion
> warning occured. We fix this in [PATCH 5/6].
>=20
> 2. Edac driver failed to register pci nodes as platform devices. We fix t=
his
> in [PATCH 6/6].
With these patches will not the SWIOTLB will not be initialized even if PCI=
/PCIe demanded?
Thanks
-Bharat
>=20
> These patches are against 'next' branch on:
> http://git.kernel.org/?p=3Dlinux/kernel/git/galak/powerpc.git
^ permalink raw reply
* [GIT PULL] Please pull powerpc fixes
From: Paul Mackerras @ 2012-06-08 10:32 UTC (permalink / raw)
To: Linus Torvalds; +Cc: linuxppc-dev
Linus,
Two small fixes for powerpc:
* a fix for a regression since 3.2 that causes 4-second (or longer) pauses
* a fix for a potential oops when loading kernel modules on
32-bit embedded systems.
Please pull (Ben is still off duty).
BTW, should I be using a signed tag for this?
Thanks,
Paul.
The following changes since commit f8f5701bdaf9134b1f90e5044a82c66324d2073f:
Linux 3.5-rc1 (2012-06-02 18:29:26 -0700)
are available in the git repository at:
git://git.kernel.org/pub/scm/linux/kernel/git/paulus/powerpc.git merge
for you to fetch changes up to 3c75296562f43e6fbc6cddd3de948a7b3e4e9bcf:
powerpc: Fix kernel panic during kernel module load (2012-06-08 19:59:08 +1000)
----------------------------------------------------------------
Paul Mackerras (1):
powerpc/time: Sanity check of decrementer expiration is necessary
Steffen Rumler (1):
powerpc: Fix kernel panic during kernel module load
arch/powerpc/kernel/module_32.c | 11 +++++------
arch/powerpc/kernel/time.c | 14 +++++++++++---
2 files changed, 16 insertions(+), 9 deletions(-)
^ permalink raw reply
* [PATCH V3 4/6] powerpc/fsl-pci: Add pci inbound/outbound PM support
From: Jia Hongtao @ 2012-06-08 9:42 UTC (permalink / raw)
To: linuxppc-dev, galak; +Cc: R65777, b38951, B07421
In-Reply-To: <1339148527-16911-1-git-send-email-B38951@freescale.com>
Power supply for PCI inbound/outbound window registers is off when system
go to deep-sleep state. We save the values of registers before suspend
and restore to registers after resume.
Signed-off-by: Jiang Yutang <b14898@freescale.com>
Signed-off-by: Jia Hongtao <B38951@freescale.com>
Signed-off-by: Li Yang <leoli@freescale.com>
---
arch/powerpc/include/asm/pci-bridge.h | 2 +-
arch/powerpc/sysdev/fsl_pci.c | 121 +++++++++++++++++++++++++++++++++
arch/powerpc/sysdev/fsl_pci.h | 10 +++
3 files changed, 132 insertions(+), 1 deletions(-)
diff --git a/arch/powerpc/include/asm/pci-bridge.h b/arch/powerpc/include/asm/pci-bridge.h
index ac39e6a..823e000 100644
--- a/arch/powerpc/include/asm/pci-bridge.h
+++ b/arch/powerpc/include/asm/pci-bridge.h
@@ -89,9 +89,9 @@ struct pci_controller {
#ifdef CONFIG_PPC64
unsigned long buid;
+#endif /* CONFIG_PPC64 */
void *private_data;
-#endif /* CONFIG_PPC64 */
};
/* These are used for config access before all the PCI probing
diff --git a/arch/powerpc/sysdev/fsl_pci.c b/arch/powerpc/sysdev/fsl_pci.c
index a5e573c..287e630 100644
--- a/arch/powerpc/sysdev/fsl_pci.c
+++ b/arch/powerpc/sysdev/fsl_pci.c
@@ -857,12 +857,133 @@ static int __devinit fsl_pci_probe(struct platform_device *pdev)
return 0;
}
+#ifdef CONFIG_SUSPEND
+
+#define PCI_POW_PIW_OFFSET 0xc00
+#define PCI_POW_PIW_SIZE 0x200
+#define PCI_POW_NUMBER 5
+
+static int fsl_pci_suspend(struct platform_device *pdev, pm_message_t state)
+{
+ struct pci_controller *hose;
+ struct pci_outbound_window_regs *pci_saved_pow;
+ struct pci_inbound_window_regs *pci_saved_piw, *temp_piw;
+ struct resource pci_rsrc;
+ unsigned int i;
+ struct fsl_pci_private_data *sus_info;
+
+ hose = pci_find_hose_for_OF_device(pdev->dev.of_node);
+ of_address_to_resource(pdev->dev.of_node, 0, &pci_rsrc);
+
+ sus_info = kmalloc(
+ sizeof(struct fsl_pci_private_data), GFP_KERNEL);
+ if (!sus_info)
+ return -ENOMEM;
+
+ hose->private_data = sus_info;
+
+ sus_info->pci_pow = ioremap(pci_rsrc.start + PCI_POW_PIW_OFFSET,
+ PCI_POW_PIW_SIZE);
+ if (!sus_info->pci_pow) {
+ dev_err(&pdev->dev, "pci outbound/inbound windows ioremap error!\n");
+ goto err1;
+ }
+
+ sus_info->pci_piw = (struct pci_inbound_window_regs *)
+ ((void *)sus_info->pci_pow + PCI_POW_PIW_SIZE) - 1;
+
+ if (of_device_is_compatible(pdev->dev.of_node, "fsl,qoriq-pcie-v2.2"))
+ sus_info->inbound_num = 4;
+ else
+ sus_info->inbound_num = 3;
+
+ sus_info->saved_regs = kmalloc(
+ sizeof(struct pci_outbound_window_regs) * PCI_POW_NUMBER +
+ sizeof(struct pci_inbound_window_regs) * sus_info->inbound_num,
+ GFP_KERNEL);
+ if (!sus_info->saved_regs)
+ goto err2;
+
+ pci_saved_pow = sus_info->saved_regs;
+ for (i = 0; i < PCI_POW_NUMBER; i++) {
+ pci_saved_pow[i].potar = in_be32(&sus_info->pci_pow[i].potar);
+ pci_saved_pow[i].potear = in_be32(&sus_info->pci_pow[i].potear);
+ pci_saved_pow[i].powbar = in_be32(&sus_info->pci_pow[i].powbar);
+ pci_saved_pow[i].powar = in_be32(&sus_info->pci_pow[i].powar);
+ }
+
+ pci_saved_piw = (struct pci_inbound_window_regs *)
+ (pci_saved_pow + PCI_POW_NUMBER);
+ temp_piw = sus_info->pci_piw;
+ for (i = 0; i < sus_info->inbound_num; i++, temp_piw--) {
+ pci_saved_piw[i].pitar = in_be32(&temp_piw->pitar);
+ pci_saved_piw[i].piwbar = in_be32(&temp_piw->piwbar);
+ pci_saved_piw[i].piwbear = in_be32(&temp_piw->piwbear);
+ pci_saved_piw[i].piwar = in_be32(&temp_piw->piwar);
+ }
+
+ return 0;
+
+err2:
+ iounmap(sus_info->pci_pow);
+
+err1:
+ kfree(sus_info);
+ return -ENOMEM;
+}
+
+static int fsl_pci_resume(struct platform_device *pdev)
+{
+ struct pci_controller *hose;
+ struct pci_outbound_window_regs *pci_saved_pow;
+ struct pci_inbound_window_regs *pci_saved_piw, *temp_piw;
+ unsigned int i;
+ struct fsl_pci_private_data *sus_info;
+
+ hose = pci_find_hose_for_OF_device(pdev->dev.of_node);
+ sus_info = (struct fsl_pci_private_data *)hose->private_data;
+
+ if (!sus_info->pci_pow || !sus_info->pci_piw || !sus_info->saved_regs)
+ return 0;
+
+ pci_saved_pow = sus_info->saved_regs;
+ for (i = 0; i < PCI_POW_NUMBER; i++) {
+ out_be32(&sus_info->pci_pow[i].potar, pci_saved_pow[i].potar);
+ out_be32(&sus_info->pci_pow[i].potear, pci_saved_pow[i].potear);
+ out_be32(&sus_info->pci_pow[i].powbar, pci_saved_pow[i].powbar);
+ out_be32(&sus_info->pci_pow[i].powar, pci_saved_pow[i].powar);
+ }
+
+ pci_saved_piw = (struct pci_inbound_window_regs *)
+ (pci_saved_pow + PCI_POW_NUMBER);
+ temp_piw = sus_info->pci_piw;
+ for (i = 0; i < sus_info->inbound_num; i++, temp_piw--) {
+ out_be32(&temp_piw->pitar, pci_saved_piw[i].pitar);
+ out_be32(&temp_piw->piwbar, pci_saved_piw[i].piwbar);
+ out_be32(&temp_piw->piwbear, pci_saved_piw[i].piwbear);
+ out_be32(&temp_piw->piwar, pci_saved_piw[i].piwar);
+ }
+ iounmap(sus_info->pci_pow);
+ kfree(sus_info->saved_regs);
+ sus_info->saved_regs = NULL;
+ kfree(sus_info);
+ sus_info = NULL;
+ hose->private_data = NULL;
+
+ return 0;
+}
+#endif
+
static struct platform_driver fsl_pci_driver = {
.driver = {
.name = "fsl-pci",
.of_match_table = pci_ids,
},
.probe = fsl_pci_probe,
+#ifdef CONFIG_SUSPEND
+ .suspend = fsl_pci_suspend,
+ .resume = fsl_pci_resume,
+#endif
};
static int __init fsl_pci_init(void)
diff --git a/arch/powerpc/sysdev/fsl_pci.h b/arch/powerpc/sysdev/fsl_pci.h
index df9fc44..1093e24 100644
--- a/arch/powerpc/sysdev/fsl_pci.h
+++ b/arch/powerpc/sysdev/fsl_pci.h
@@ -88,6 +88,16 @@ struct ccsr_pci {
__be32 pex_err_cap_r3; /* 0x.e34 - PCIE error capture register 0 */
};
+
+#ifdef CONFIG_SUSPEND
+struct fsl_pci_private_data {
+ int inbound_num;
+ struct pci_outbound_window_regs __iomem *pci_pow;
+ struct pci_inbound_window_regs __iomem *pci_piw;
+ void *saved_regs;
+};
+#endif
+
extern int primary_phb_addr;
extern int fsl_add_bridge(struct device_node *dev, int is_primary);
extern void fsl_pcibios_fixup_bus(struct pci_bus *bus);
--
1.7.5.1
^ permalink raw reply related
* [PATCH V3 6/6] Edac/85xx: Register mpc85xx_pci_err_driver by fsl_pci_driver
From: Jia Hongtao @ 2012-06-08 9:42 UTC (permalink / raw)
To: linuxppc-dev, galak; +Cc: R65777, b38951, B07421
In-Reply-To: <1339148527-16911-1-git-send-email-B38951@freescale.com>
Now we registered pci controllers as platform devices. It will make edac
driver failed to register pci nodes as platform devices too. So we combine
two initialization code as one platform driver.
Signed-off-by: Chunhe Lan <Chunhe.Lan@freescale.com>
Signed-off-by: Li Yang <leoli@freescale.com>
Signed-off-by: Jia Hongtao <B38951@freescale.com>
---
arch/powerpc/sysdev/fsl_pci.c | 4 +++
arch/powerpc/sysdev/fsl_pci.h | 4 +++
drivers/edac/mpc85xx_edac.c | 43 +++++++++++-----------------------------
3 files changed, 20 insertions(+), 31 deletions(-)
diff --git a/arch/powerpc/sysdev/fsl_pci.c b/arch/powerpc/sysdev/fsl_pci.c
index 287e630..1012bf7 100644
--- a/arch/powerpc/sysdev/fsl_pci.c
+++ b/arch/powerpc/sysdev/fsl_pci.c
@@ -854,6 +854,10 @@ static int __devinit fsl_pci_probe(struct platform_device *pdev)
#endif
}
+#ifdef CONFIG_EDAC_MPC85XX
+ mpc85xx_pci_err_probe(pdev);
+#endif
+
return 0;
}
diff --git a/arch/powerpc/sysdev/fsl_pci.h b/arch/powerpc/sysdev/fsl_pci.h
index 1093e24..ea2e025 100644
--- a/arch/powerpc/sysdev/fsl_pci.h
+++ b/arch/powerpc/sysdev/fsl_pci.h
@@ -104,5 +104,9 @@ extern void fsl_pcibios_fixup_bus(struct pci_bus *bus);
extern int mpc83xx_add_bridge(struct device_node *dev);
u64 fsl_pci_immrbar_base(struct pci_controller *hose);
+#ifdef CONFIG_EDAC_MPC85XX
+extern int mpc85xx_pci_err_probe(struct platform_device *op);
+#endif
+
#endif /* __POWERPC_FSL_PCI_H */
#endif /* __KERNEL__ */
diff --git a/drivers/edac/mpc85xx_edac.c b/drivers/edac/mpc85xx_edac.c
index 73464a6..aec880b 100644
--- a/drivers/edac/mpc85xx_edac.c
+++ b/drivers/edac/mpc85xx_edac.c
@@ -200,7 +200,7 @@ static irqreturn_t mpc85xx_pci_isr(int irq, void *dev_id)
return IRQ_HANDLED;
}
-static int __devinit mpc85xx_pci_err_probe(struct platform_device *op)
+int __devinit mpc85xx_pci_err_probe(struct platform_device *op)
{
struct edac_pci_ctl_info *pci;
struct mpc85xx_pci_pdata *pdata;
@@ -214,6 +214,16 @@ static int __devinit mpc85xx_pci_err_probe(struct platform_device *op)
if (!pci)
return -ENOMEM;
+ /* make sure error reporting method is sane */
+ switch (edac_op_state) {
+ case EDAC_OPSTATE_POLL:
+ case EDAC_OPSTATE_INT:
+ break;
+ default:
+ edac_op_state = EDAC_OPSTATE_INT;
+ break;
+ }
+
pdata = pci->pvt_info;
pdata->name = "mpc85xx_pci_err";
pdata->irq = NO_IRQ;
@@ -303,6 +313,7 @@ err:
devres_release_group(&op->dev, mpc85xx_pci_err_probe);
return res;
}
+EXPORT_SYMBOL(mpc85xx_pci_err_probe);
static int mpc85xx_pci_err_remove(struct platform_device *op)
{
@@ -326,27 +337,6 @@ static int mpc85xx_pci_err_remove(struct platform_device *op)
return 0;
}
-static struct of_device_id mpc85xx_pci_err_of_match[] = {
- {
- .compatible = "fsl,mpc8540-pcix",
- },
- {
- .compatible = "fsl,mpc8540-pci",
- },
- {},
-};
-MODULE_DEVICE_TABLE(of, mpc85xx_pci_err_of_match);
-
-static struct platform_driver mpc85xx_pci_err_driver = {
- .probe = mpc85xx_pci_err_probe,
- .remove = __devexit_p(mpc85xx_pci_err_remove),
- .driver = {
- .name = "mpc85xx_pci_err",
- .owner = THIS_MODULE,
- .of_match_table = mpc85xx_pci_err_of_match,
- },
-};
-
#endif /* CONFIG_PCI */
/**************************** L2 Err device ***************************/
@@ -1177,12 +1167,6 @@ static int __init mpc85xx_mc_init(void)
if (res)
printk(KERN_WARNING EDAC_MOD_STR "L2 fails to register\n");
-#ifdef CONFIG_PCI
- res = platform_driver_register(&mpc85xx_pci_err_driver);
- if (res)
- printk(KERN_WARNING EDAC_MOD_STR "PCI fails to register\n");
-#endif
-
#ifdef CONFIG_FSL_SOC_BOOKE
pvr = mfspr(SPRN_PVR);
@@ -1219,9 +1203,6 @@ static void __exit mpc85xx_mc_exit(void)
on_each_cpu(mpc85xx_mc_restore_hid1, NULL, 0);
}
#endif
-#ifdef CONFIG_PCI
- platform_driver_unregister(&mpc85xx_pci_err_driver);
-#endif
platform_driver_unregister(&mpc85xx_l2_err_driver);
platform_driver_unregister(&mpc85xx_mc_err_driver);
}
--
1.7.5.1
^ permalink raw reply related
* [PATCH V3 5/6] Avoid duplicate probe for of platform devices
From: Jia Hongtao @ 2012-06-08 9:42 UTC (permalink / raw)
To: linuxppc-dev, galak; +Cc: R65777, b38951, B07421
In-Reply-To: <1339148527-16911-1-git-send-email-B38951@freescale.com>
We changed the pcie controller driver to platform driver so that the PCI
of platform devices need to be created earlier in the arch_initcall stage
according to the original timing of calling fsl_add_bridge(). So we do PCI
probing separately from other devices. But probing more than once could
cause duplication warning. We add check if the devices have already probed
before probing any devices to avoid duplication warning.
Signed-off-by: Jia Hongtao <B38951@freescale.com>
Signed-off-by: Li Yang <leoli@freescale.com>
---
drivers/of/platform.c | 18 ++++++++++++------
1 files changed, 12 insertions(+), 6 deletions(-)
diff --git a/drivers/of/platform.c b/drivers/of/platform.c
index a37330e..3aab01f 100644
--- a/drivers/of/platform.c
+++ b/drivers/of/platform.c
@@ -139,6 +139,18 @@ struct platform_device *of_device_alloc(struct device_node *np,
if (!dev)
return NULL;
+ dev->dev.of_node = of_node_get(np);
+ if (bus_id)
+ dev_set_name(&dev->dev, "%s", bus_id);
+ else
+ of_device_make_bus_id(&dev->dev);
+
+ if (kset_find_obj(dev->dev.kobj.kset, kobject_name(&dev->dev.kobj))) {
+ kfree(dev);
+ of_node_put(np);
+ return NULL;
+ }
+
/* count the io and irq resources */
while (of_address_to_resource(np, num_reg, &temp_res) == 0)
num_reg++;
@@ -161,17 +173,11 @@ struct platform_device *of_device_alloc(struct device_node *np,
WARN_ON(of_irq_to_resource_table(np, res, num_irq) != num_irq);
}
- dev->dev.of_node = of_node_get(np);
#if defined(CONFIG_MICROBLAZE)
dev->dev.dma_mask = &dev->archdata.dma_mask;
#endif
dev->dev.parent = parent;
- if (bus_id)
- dev_set_name(&dev->dev, "%s", bus_id);
- else
- of_device_make_bus_id(&dev->dev);
-
return dev;
}
EXPORT_SYMBOL(of_device_alloc);
--
1.7.5.1
^ permalink raw reply related
* [PATCH V3 3/6] powerpc/fsl-pci: Only scan PCI bus if configured as a host
From: Jia Hongtao @ 2012-06-08 9:42 UTC (permalink / raw)
To: linuxppc-dev, galak; +Cc: R65777, b38951, B07421
In-Reply-To: <1339148527-16911-1-git-send-email-B38951@freescale.com>
If we're an agent/end-point or fsl_add_bridge doesn't succeed due to some
resource failure we should not scan the PCI bus. We change fsl_add_bridge()
to return -ENODEV in the case we're an agent/end-point.
Signed-off-by: Jia Hongtao <B38951@freescale.com>
Signed-off-by: Li Yang <leoli@freescale.com>
---
arch/powerpc/sysdev/fsl_pci.c | 27 +++++++++++++++------------
1 files changed, 15 insertions(+), 12 deletions(-)
diff --git a/arch/powerpc/sysdev/fsl_pci.c b/arch/powerpc/sysdev/fsl_pci.c
index 4c3d130..a5e573c 100644
--- a/arch/powerpc/sysdev/fsl_pci.c
+++ b/arch/powerpc/sysdev/fsl_pci.c
@@ -465,7 +465,7 @@ int __init fsl_add_bridge(struct device_node *dev, int is_primary)
iounmap(hose->cfg_data);
iounmap(hose->cfg_addr);
pcibios_free_controller(hose);
- return 0;
+ return -ENODEV;
}
setup_pci_cmd(hose);
@@ -836,17 +836,20 @@ static int __devinit fsl_pci_probe(struct platform_device *pdev)
ret = fsl_add_bridge(pdev->dev.of_node, is_primary);
#ifdef CONFIG_SWIOTLB
- hose = pci_find_hose_for_OF_device(pdev->dev.of_node);
- /*
- * if we couldn't map all of DRAM via the dma windows
- * we need SWIOTLB to handle buffers located outside of
- * dma capable memory region
- */
- if (memblock_end_of_DRAM() > hose->dma_window_base_cur
- + hose->dma_window_size) {
- ppc_swiotlb_enable = 1;
- set_pci_dma_ops(&swiotlb_dma_ops);
- ppc_md.pci_dma_dev_setup = pci_dma_dev_setup_swiotlb;
+ if (ret == 0) {
+ hose = pci_find_hose_for_OF_device(pdev->dev.of_node);
+ /*
+ * if we couldn't map all of DRAM via the dma windows
+ * we need SWIOTLB to handle buffers located outside of
+ * dma capable memory region
+ */
+ if (memblock_end_of_DRAM() > hose->dma_window_base_cur
+ + hose->dma_window_size) {
+ ppc_swiotlb_enable = 1;
+ set_pci_dma_ops(&swiotlb_dma_ops);
+ ppc_md.pci_dma_dev_setup =
+ pci_dma_dev_setup_swiotlb;
+ }
}
#endif
}
--
1.7.5.1
^ permalink raw reply related
* [PATCH V3 2/6] powerpc/fsl-pci: Using common pci/pcie initialization for all boards
From: Jia Hongtao @ 2012-06-08 9:42 UTC (permalink / raw)
To: linuxppc-dev, galak; +Cc: R65777, b38951, B07421
In-Reply-To: <1339148527-16911-1-git-send-email-B38951@freescale.com>
Including all 85xx and 86xx platforms.
Signed-off-by: Jia Hongtao <B38951@freescale.com>
Signed-off-by: Li Yang <leoli@freescale.com>
---
arch/powerpc/platforms/85xx/common.c | 28 ++++++++++++
arch/powerpc/platforms/85xx/corenet_ds.c | 27 +------------
arch/powerpc/platforms/85xx/corenet_ds.h | 1 +
arch/powerpc/platforms/85xx/ge_imp3a.c | 34 +--------------
arch/powerpc/platforms/85xx/mpc8536_ds.c | 40 ++++-------------
arch/powerpc/platforms/85xx/mpc85xx.h | 1 +
arch/powerpc/platforms/85xx/mpc85xx_ads.c | 17 ++++----
arch/powerpc/platforms/85xx/mpc85xx_cds.c | 24 ++++------
arch/powerpc/platforms/85xx/mpc85xx_ds.c | 33 ++------------
arch/powerpc/platforms/85xx/mpc85xx_mds.c | 62 +++++++++++++--------------
arch/powerpc/platforms/85xx/mpc85xx_rdb.c | 13 ++----
arch/powerpc/platforms/85xx/p1010rdb.c | 13 +-----
arch/powerpc/platforms/85xx/p1022_ds.c | 29 +------------
arch/powerpc/platforms/85xx/p1023_rds.c | 6 +--
arch/powerpc/platforms/85xx/p2041_rdb.c | 1 +
arch/powerpc/platforms/85xx/p3041_ds.c | 1 +
arch/powerpc/platforms/85xx/p3060_qds.c | 1 +
arch/powerpc/platforms/85xx/p4080_ds.c | 1 +
arch/powerpc/platforms/85xx/p5020_ds.c | 1 +
arch/powerpc/platforms/85xx/sbc8548.c | 27 ++++--------
arch/powerpc/platforms/85xx/sbc8560.c | 19 ++++----
arch/powerpc/platforms/85xx/socrates.c | 16 +++----
arch/powerpc/platforms/85xx/stx_gp3.c | 19 ++++----
arch/powerpc/platforms/85xx/tqm85xx.c | 29 ++++---------
arch/powerpc/platforms/85xx/xes_mpc85xx.c | 25 ++---------
arch/powerpc/platforms/86xx/gef_ppc9a.c | 34 ++++++++++++----
arch/powerpc/platforms/86xx/gef_sbc310.c | 34 ++++++++++++----
arch/powerpc/platforms/86xx/gef_sbc610.c | 34 ++++++++++++----
arch/powerpc/platforms/86xx/mpc8610_hpcd.c | 41 ++++++++++++-------
arch/powerpc/platforms/86xx/mpc86xx_hpcn.c | 55 ++++++++++++-------------
arch/powerpc/platforms/86xx/sbc8641d.c | 30 +++++++++----
drivers/of/platform.c | 3 +-
include/linux/of_platform.h | 4 ++
33 files changed, 313 insertions(+), 390 deletions(-)
diff --git a/arch/powerpc/platforms/85xx/common.c b/arch/powerpc/platforms/85xx/common.c
index 9fef530..ae162ae 100644
--- a/arch/powerpc/platforms/85xx/common.c
+++ b/arch/powerpc/platforms/85xx/common.c
@@ -28,6 +28,34 @@ int __init mpc85xx_common_publish_devices(void)
{
return of_platform_bus_probe(NULL, mpc85xx_common_ids, NULL);
}
+
+static struct of_device_id __initdata mpc85xx_pci_ids[] = {
+ { .compatible = "fsl,mpc8540-pci", },
+ { .compatible = "fsl,mpc8548-pcie", },
+ { .compatible = "fsl,p1022-pcie", },
+ { .compatible = "fsl,p1010-pcie", },
+ { .compatible = "fsl,p1023-pcie", },
+ { .compatible = "fsl,p4080-pcie", },
+ { .compatible = "fsl,qoriq-pcie-v2.3", },
+ { .compatible = "fsl,qoriq-pcie-v2.2", },
+ {},
+};
+
+int __init mpc85xx_pci_publish_devices(void)
+{
+ struct device_node *np;
+ int rc = 0;
+
+ for_each_matching_node(np, mpc85xx_pci_ids) {
+ rc = of_platform_bus_create(np, mpc85xx_pci_ids, NULL,
+ NULL, true);
+ if (rc)
+ break;
+ }
+
+ return rc;
+}
+
#ifdef CONFIG_CPM2
static void cpm2_cascade(unsigned int irq, struct irq_desc *desc)
{
diff --git a/arch/powerpc/platforms/85xx/corenet_ds.c b/arch/powerpc/platforms/85xx/corenet_ds.c
index df69e99..a21a075 100644
--- a/arch/powerpc/platforms/85xx/corenet_ds.c
+++ b/arch/powerpc/platforms/85xx/corenet_ds.c
@@ -53,36 +53,17 @@ void __init corenet_ds_pic_init(void)
*/
void __init corenet_ds_setup_arch(void)
{
-#ifdef CONFIG_PCI
- struct device_node *np;
- struct pci_controller *hose;
-#endif
- dma_addr_t max = 0xffffffff;
-
mpc85xx_smp_init();
#ifdef CONFIG_PCI
- for_each_node_by_type(np, "pci") {
- if (of_device_is_compatible(np, "fsl,p4080-pcie") ||
- of_device_is_compatible(np, "fsl,qoriq-pcie-v2.2")) {
- fsl_add_bridge(np, 0);
- hose = pci_find_hose_for_OF_device(np);
- max = min(max, hose->dma_window_base_cur +
- hose->dma_window_size);
- }
- }
-
#ifdef CONFIG_PPC64
pci_devs_phb_init();
#endif
#endif
#ifdef CONFIG_SWIOTLB
- if (memblock_end_of_DRAM() > max) {
+ if (memblock_end_of_DRAM() > 0xffffffff)
ppc_swiotlb_enable = 1;
- set_pci_dma_ops(&swiotlb_dma_ops);
- ppc_md.pci_dma_dev_setup = pci_dma_dev_setup_swiotlb;
- }
#endif
pr_info("%s board from Freescale Semiconductor\n", ppc_md.name);
}
@@ -94,12 +75,6 @@ static const struct of_device_id of_device_ids[] __devinitconst = {
{
.compatible = "fsl,srio",
},
- {
- .compatible = "fsl,p4080-pcie",
- },
- {
- .compatible = "fsl,qoriq-pcie-v2.2",
- },
/* The following two are for the Freescale hypervisor */
{
.name = "hypervisor",
diff --git a/arch/powerpc/platforms/85xx/corenet_ds.h b/arch/powerpc/platforms/85xx/corenet_ds.h
index ddd700b..89700e6 100644
--- a/arch/powerpc/platforms/85xx/corenet_ds.h
+++ b/arch/powerpc/platforms/85xx/corenet_ds.h
@@ -15,5 +15,6 @@
extern void __init corenet_ds_pic_init(void);
extern void __init corenet_ds_setup_arch(void);
extern int __init corenet_ds_publish_devices(void);
+extern int __init mpc85xx_pci_publish_devices(void);
#endif
diff --git a/arch/powerpc/platforms/85xx/ge_imp3a.c b/arch/powerpc/platforms/85xx/ge_imp3a.c
index d50056f..43f7142 100644
--- a/arch/powerpc/platforms/85xx/ge_imp3a.c
+++ b/arch/powerpc/platforms/85xx/ge_imp3a.c
@@ -85,52 +85,21 @@ void __init ge_imp3a_pic_init(void)
of_node_put(cascade_node);
}
-#ifdef CONFIG_PCI
-static int primary_phb_addr;
-#endif /* CONFIG_PCI */
-
/*
* Setup the architecture
*/
static void __init ge_imp3a_setup_arch(void)
{
struct device_node *regs;
-#ifdef CONFIG_PCI
- struct device_node *np;
- struct pci_controller *hose;
-#endif
- dma_addr_t max = 0xffffffff;
if (ppc_md.progress)
ppc_md.progress("ge_imp3a_setup_arch()", 0);
-#ifdef CONFIG_PCI
- for_each_node_by_type(np, "pci") {
- if (of_device_is_compatible(np, "fsl,mpc8540-pci") ||
- of_device_is_compatible(np, "fsl,mpc8548-pcie") ||
- of_device_is_compatible(np, "fsl,p2020-pcie")) {
- struct resource rsrc;
- of_address_to_resource(np, 0, &rsrc);
- if ((rsrc.start & 0xfffff) == primary_phb_addr)
- fsl_add_bridge(np, 1);
- else
- fsl_add_bridge(np, 0);
-
- hose = pci_find_hose_for_OF_device(np);
- max = min(max, hose->dma_window_base_cur +
- hose->dma_window_size);
- }
- }
-#endif
-
mpc85xx_smp_init();
#ifdef CONFIG_SWIOTLB
- if (memblock_end_of_DRAM() > max) {
+ if (memblock_end_of_DRAM() > 0xffffffff)
ppc_swiotlb_enable = 1;
- set_pci_dma_ops(&swiotlb_dma_ops);
- ppc_md.pci_dma_dev_setup = pci_dma_dev_setup_swiotlb;
- }
#endif
/* Remap basic board registers */
@@ -226,6 +195,7 @@ static int __init ge_imp3a_probe(void)
return 0;
}
+machine_arch_initcall(p1022_ds, mpc85xx_pci_publish_devices);
machine_device_initcall(ge_imp3a, mpc85xx_common_publish_devices);
machine_arch_initcall(ge_imp3a, swiotlb_setup_bus_notifier);
diff --git a/arch/powerpc/platforms/85xx/mpc8536_ds.c b/arch/powerpc/platforms/85xx/mpc8536_ds.c
index f588726..e9fc274 100644
--- a/arch/powerpc/platforms/85xx/mpc8536_ds.c
+++ b/arch/powerpc/platforms/85xx/mpc8536_ds.c
@@ -47,40 +47,12 @@ void __init mpc8536_ds_pic_init(void)
*/
static void __init mpc8536_ds_setup_arch(void)
{
-#ifdef CONFIG_PCI
- struct device_node *np;
- struct pci_controller *hose;
-#endif
- dma_addr_t max = 0xffffffff;
-
if (ppc_md.progress)
ppc_md.progress("mpc8536_ds_setup_arch()", 0);
-#ifdef CONFIG_PCI
- for_each_node_by_type(np, "pci") {
- if (of_device_is_compatible(np, "fsl,mpc8540-pci") ||
- of_device_is_compatible(np, "fsl,mpc8548-pcie")) {
- struct resource rsrc;
- of_address_to_resource(np, 0, &rsrc);
- if ((rsrc.start & 0xfffff) == 0x8000)
- fsl_add_bridge(np, 1);
- else
- fsl_add_bridge(np, 0);
-
- hose = pci_find_hose_for_OF_device(np);
- max = min(max, hose->dma_window_base_cur +
- hose->dma_window_size);
- }
- }
-
-#endif
-
#ifdef CONFIG_SWIOTLB
- if (memblock_end_of_DRAM() > max) {
+ if (memblock_end_of_DRAM() > 0xffffffff)
ppc_swiotlb_enable = 1;
- set_pci_dma_ops(&swiotlb_dma_ops);
- ppc_md.pci_dma_dev_setup = pci_dma_dev_setup_swiotlb;
- }
#endif
printk("MPC8536 DS board from Freescale Semiconductor\n");
@@ -88,6 +60,7 @@ static void __init mpc8536_ds_setup_arch(void)
machine_device_initcall(mpc8536_ds, mpc85xx_common_publish_devices);
+machine_arch_initcall(mpc8536_ds, mpc85xx_pci_publish_devices);
machine_arch_initcall(mpc8536_ds, swiotlb_setup_bus_notifier);
/*
@@ -97,7 +70,14 @@ static int __init mpc8536_ds_probe(void)
{
unsigned long root = of_get_flat_dt_root();
- return of_flat_dt_is_compatible(root, "fsl,mpc8536ds");
+ if (of_flat_dt_is_compatible(root, "fsl,mpc8536ds")) {
+#ifdef CONFIG_PCI
+ primary_phb_addr = 0x8000;
+#endif
+ return 1;
+ }
+
+ return 0;
}
define_machine(mpc8536_ds) {
diff --git a/arch/powerpc/platforms/85xx/mpc85xx.h b/arch/powerpc/platforms/85xx/mpc85xx.h
index 2aa7c5d..4ebdbb7 100644
--- a/arch/powerpc/platforms/85xx/mpc85xx.h
+++ b/arch/powerpc/platforms/85xx/mpc85xx.h
@@ -1,6 +1,7 @@
#ifndef MPC85xx_H
#define MPC85xx_H
extern int mpc85xx_common_publish_devices(void);
+extern int mpc85xx_pci_publish_devices(void);
#ifdef CONFIG_CPM2
extern void mpc85xx_cpm2_pic_init(void);
diff --git a/arch/powerpc/platforms/85xx/mpc85xx_ads.c b/arch/powerpc/platforms/85xx/mpc85xx_ads.c
index d19f675..f590df8 100644
--- a/arch/powerpc/platforms/85xx/mpc85xx_ads.c
+++ b/arch/powerpc/platforms/85xx/mpc85xx_ads.c
@@ -138,10 +138,6 @@ static void __init init_ioports(void)
static void __init mpc85xx_ads_setup_arch(void)
{
-#ifdef CONFIG_PCI
- struct device_node *np;
-#endif
-
if (ppc_md.progress)
ppc_md.progress("mpc85xx_ads_setup_arch()", 0);
@@ -151,9 +147,6 @@ static void __init mpc85xx_ads_setup_arch(void)
#endif
#ifdef CONFIG_PCI
- for_each_compatible_node(np, "pci", "fsl,mpc8540-pci")
- fsl_add_bridge(np, 1);
-
ppc_md.pci_exclude_device = mpc85xx_exclude_device;
#endif
}
@@ -174,6 +167,7 @@ static void mpc85xx_ads_show_cpuinfo(struct seq_file *m)
seq_printf(m, "PLL setting\t: 0x%x\n", ((phid1 >> 24) & 0x3f));
}
+machine_arch_initcall(mpc85xx_ads, mpc85xx_pci_publish_devices);
machine_device_initcall(mpc85xx_ads, mpc85xx_common_publish_devices);
/*
@@ -183,7 +177,14 @@ static int __init mpc85xx_ads_probe(void)
{
unsigned long root = of_get_flat_dt_root();
- return of_flat_dt_is_compatible(root, "MPC85xxADS");
+ if (of_flat_dt_is_compatible(root, "MPC85xxADS")) {
+#ifdef CONFIG_PCI
+ primary_phb_addr = 0x8000;
+#endif
+ return 1;
+ }
+
+ return 0;
}
define_machine(mpc85xx_ads) {
diff --git a/arch/powerpc/platforms/85xx/mpc85xx_cds.c b/arch/powerpc/platforms/85xx/mpc85xx_cds.c
index ab5f0bf1..2bb6b9c 100644
--- a/arch/powerpc/platforms/85xx/mpc85xx_cds.c
+++ b/arch/powerpc/platforms/85xx/mpc85xx_cds.c
@@ -310,18 +310,6 @@ static void __init mpc85xx_cds_setup_arch(void)
}
#ifdef CONFIG_PCI
- for_each_node_by_type(np, "pci") {
- if (of_device_is_compatible(np, "fsl,mpc8540-pci") ||
- of_device_is_compatible(np, "fsl,mpc8548-pcie")) {
- struct resource rsrc;
- of_address_to_resource(np, 0, &rsrc);
- if ((rsrc.start & 0xfffff) == 0x8000)
- fsl_add_bridge(np, 1);
- else
- fsl_add_bridge(np, 0);
- }
- }
-
ppc_md.pci_irq_fixup = mpc85xx_cds_pci_irq_fixup;
ppc_md.pci_exclude_device = mpc85xx_exclude_device;
#endif
@@ -351,12 +339,20 @@ static void mpc85xx_cds_show_cpuinfo(struct seq_file *m)
*/
static int __init mpc85xx_cds_probe(void)
{
- unsigned long root = of_get_flat_dt_root();
+ unsigned long root = of_get_flat_dt_root();
- return of_flat_dt_is_compatible(root, "MPC85xxCDS");
+ if (of_flat_dt_is_compatible(root, "MPC85xxCDS")) {
+#ifdef CONFIG_PCI
+ primary_phb_addr = 0x8000;
+#endif
+ return 1;
+ }
+
+ return 0;
}
machine_device_initcall(mpc85xx_cds, mpc85xx_common_publish_devices);
+machine_arch_initcall(mpc85xx_cds, mpc85xx_pci_publish_devices);
define_machine(mpc85xx_cds) {
.name = "MPC85xx CDS",
diff --git a/arch/powerpc/platforms/85xx/mpc85xx_ds.c b/arch/powerpc/platforms/85xx/mpc85xx_ds.c
index 6e23e3e..e33a8cf 100644
--- a/arch/powerpc/platforms/85xx/mpc85xx_ds.c
+++ b/arch/powerpc/platforms/85xx/mpc85xx_ds.c
@@ -115,7 +115,6 @@ void __init mpc85xx_ds_pic_init(void)
}
#ifdef CONFIG_PCI
-static int primary_phb_addr;
extern int uli_exclude_device(struct pci_controller *hose,
u_char bus, u_char devfn);
@@ -141,44 +140,18 @@ static int mpc85xx_exclude_device(struct pci_controller *hose,
*/
static void __init mpc85xx_ds_setup_arch(void)
{
-#ifdef CONFIG_PCI
- struct device_node *np;
- struct pci_controller *hose;
-#endif
- dma_addr_t max = 0xffffffff;
-
if (ppc_md.progress)
ppc_md.progress("mpc85xx_ds_setup_arch()", 0);
#ifdef CONFIG_PCI
- for_each_node_by_type(np, "pci") {
- if (of_device_is_compatible(np, "fsl,mpc8540-pci") ||
- of_device_is_compatible(np, "fsl,mpc8548-pcie") ||
- of_device_is_compatible(np, "fsl,p2020-pcie")) {
- struct resource rsrc;
- of_address_to_resource(np, 0, &rsrc);
- if ((rsrc.start & 0xfffff) == primary_phb_addr)
- fsl_add_bridge(np, 1);
- else
- fsl_add_bridge(np, 0);
-
- hose = pci_find_hose_for_OF_device(np);
- max = min(max, hose->dma_window_base_cur +
- hose->dma_window_size);
- }
- }
-
ppc_md.pci_exclude_device = mpc85xx_exclude_device;
#endif
mpc85xx_smp_init();
#ifdef CONFIG_SWIOTLB
- if (memblock_end_of_DRAM() > max) {
+ if (memblock_end_of_DRAM() > 0xffffffff)
ppc_swiotlb_enable = 1;
- set_pci_dma_ops(&swiotlb_dma_ops);
- ppc_md.pci_dma_dev_setup = pci_dma_dev_setup_swiotlb;
- }
#endif
printk("MPC85xx DS board from Freescale Semiconductor\n");
@@ -205,6 +178,10 @@ machine_device_initcall(mpc8544_ds, mpc85xx_common_publish_devices);
machine_device_initcall(mpc8572_ds, mpc85xx_common_publish_devices);
machine_device_initcall(p2020_ds, mpc85xx_common_publish_devices);
+machine_arch_initcall(mpc8544_ds, mpc85xx_pci_publish_devices);
+machine_arch_initcall(mpc8572_ds, mpc85xx_pci_publish_devices);
+machine_arch_initcall(p2020_ds, mpc85xx_pci_publish_devices);
+
machine_arch_initcall(mpc8544_ds, swiotlb_setup_bus_notifier);
machine_arch_initcall(mpc8572_ds, swiotlb_setup_bus_notifier);
machine_arch_initcall(p2020_ds, swiotlb_setup_bus_notifier);
diff --git a/arch/powerpc/platforms/85xx/mpc85xx_mds.c b/arch/powerpc/platforms/85xx/mpc85xx_mds.c
index e82f06f..6170d5f 100644
--- a/arch/powerpc/platforms/85xx/mpc85xx_mds.c
+++ b/arch/powerpc/platforms/85xx/mpc85xx_mds.c
@@ -328,43 +328,16 @@ static void __init mpc85xx_mds_qeic_init(void) { }
static void __init mpc85xx_mds_setup_arch(void)
{
-#ifdef CONFIG_PCI
- struct pci_controller *hose;
- struct device_node *np;
-#endif
- dma_addr_t max = 0xffffffff;
-
if (ppc_md.progress)
ppc_md.progress("mpc85xx_mds_setup_arch()", 0);
-#ifdef CONFIG_PCI
- for_each_node_by_type(np, "pci") {
- if (of_device_is_compatible(np, "fsl,mpc8540-pci") ||
- of_device_is_compatible(np, "fsl,mpc8548-pcie")) {
- struct resource rsrc;
- of_address_to_resource(np, 0, &rsrc);
- if ((rsrc.start & 0xfffff) == 0x8000)
- fsl_add_bridge(np, 1);
- else
- fsl_add_bridge(np, 0);
-
- hose = pci_find_hose_for_OF_device(np);
- max = min(max, hose->dma_window_base_cur +
- hose->dma_window_size);
- }
- }
-#endif
-
mpc85xx_smp_init();
mpc85xx_mds_qe_init();
#ifdef CONFIG_SWIOTLB
- if (memblock_end_of_DRAM() > max) {
+ if (memblock_end_of_DRAM() > 0xffffffff)
ppc_swiotlb_enable = 1;
- set_pci_dma_ops(&swiotlb_dma_ops);
- ppc_md.pci_dma_dev_setup = pci_dma_dev_setup_swiotlb;
- }
#endif
}
@@ -423,6 +396,10 @@ machine_device_initcall(mpc8568_mds, mpc85xx_publish_devices);
machine_device_initcall(mpc8569_mds, mpc85xx_publish_devices);
machine_device_initcall(p1021_mds, mpc85xx_common_publish_devices);
+machine_arch_initcall(mpc8568_mds, mpc85xx_pci_publish_devices);
+machine_arch_initcall(mpc8569_mds, mpc85xx_pci_publish_devices);
+machine_arch_initcall(p1021_mds, mpc85xx_pci_publish_devices);
+
machine_arch_initcall(mpc8568_mds, swiotlb_setup_bus_notifier);
machine_arch_initcall(mpc8569_mds, swiotlb_setup_bus_notifier);
machine_arch_initcall(p1021_mds, swiotlb_setup_bus_notifier);
@@ -440,9 +417,16 @@ static void __init mpc85xx_mds_pic_init(void)
static int __init mpc85xx_mds_probe(void)
{
- unsigned long root = of_get_flat_dt_root();
+ unsigned long root = of_get_flat_dt_root();
- return of_flat_dt_is_compatible(root, "MPC85xxMDS");
+ if (of_flat_dt_is_compatible(root, "MPC85xxMDS")) {
+#ifdef CONFIG_PCI
+ primary_phb_addr = 0x8000;
+#endif
+ return 1;
+ }
+
+ return 0;
}
define_machine(mpc8568_mds) {
@@ -463,7 +447,14 @@ static int __init mpc8569_mds_probe(void)
{
unsigned long root = of_get_flat_dt_root();
- return of_flat_dt_is_compatible(root, "fsl,MPC8569EMDS");
+ if (of_flat_dt_is_compatible(root, "fsl,MPC8569EMDS")) {
+#ifdef CONFIG_PCI
+ primary_phb_addr = 0x8000;
+#endif
+ return 1;
+ }
+
+ return 0;
}
define_machine(mpc8569_mds) {
@@ -484,7 +475,14 @@ static int __init p1021_mds_probe(void)
{
unsigned long root = of_get_flat_dt_root();
- return of_flat_dt_is_compatible(root, "fsl,P1021MDS");
+ if (of_flat_dt_is_compatible(root, "fsl,P1021MDS")) {
+#ifdef CONFIG_PCI
+ primary_phb_addr = 0x8000;
+#endif
+ return 1;
+ }
+
+ return 0;
}
diff --git a/arch/powerpc/platforms/85xx/mpc85xx_rdb.c b/arch/powerpc/platforms/85xx/mpc85xx_rdb.c
index 1a66c3d..453a935 100644
--- a/arch/powerpc/platforms/85xx/mpc85xx_rdb.c
+++ b/arch/powerpc/platforms/85xx/mpc85xx_rdb.c
@@ -87,21 +87,13 @@ void __init mpc85xx_rdb_pic_init(void)
*/
static void __init mpc85xx_rdb_setup_arch(void)
{
-#if defined(CONFIG_PCI) || defined(CONFIG_QUICC_ENGINE)
+#ifdef CONFIG_QUICC_ENGINE
struct device_node *np;
#endif
if (ppc_md.progress)
ppc_md.progress("mpc85xx_rdb_setup_arch()", 0);
-#ifdef CONFIG_PCI
- for_each_node_by_type(np, "pci") {
- if (of_device_is_compatible(np, "fsl,mpc8548-pcie"))
- fsl_add_bridge(np, 0);
- }
-
-#endif
-
mpc85xx_smp_init();
#ifdef CONFIG_QUICC_ENGINE
@@ -171,6 +163,9 @@ machine_device_initcall(p1020_utm_pc, mpc85xx_common_publish_devices);
machine_device_initcall(p1021_rdb_pc, mpc85xx_common_publish_devices);
machine_device_initcall(p1025_rdb, mpc85xx_common_publish_devices);
+machine_arch_initcall(p2020_rdb, mpc85xx_pci_publish_devices);
+machine_arch_initcall(p1020_rdb, mpc85xx_pci_publish_devices);
+
/*
* Called very early, device-tree isn't unflattened
*/
diff --git a/arch/powerpc/platforms/85xx/p1010rdb.c b/arch/powerpc/platforms/85xx/p1010rdb.c
index d8bd656..ad9987c 100644
--- a/arch/powerpc/platforms/85xx/p1010rdb.c
+++ b/arch/powerpc/platforms/85xx/p1010rdb.c
@@ -47,25 +47,14 @@ void __init p1010_rdb_pic_init(void)
*/
static void __init p1010_rdb_setup_arch(void)
{
-#ifdef CONFIG_PCI
- struct device_node *np;
-#endif
-
if (ppc_md.progress)
ppc_md.progress("p1010_rdb_setup_arch()", 0);
-#ifdef CONFIG_PCI
- for_each_node_by_type(np, "pci") {
- if (of_device_is_compatible(np, "fsl,p1010-pcie"))
- fsl_add_bridge(np, 0);
- }
-
-#endif
-
printk(KERN_INFO "P1010 RDB board from Freescale Semiconductor\n");
}
machine_device_initcall(p1010_rdb, mpc85xx_common_publish_devices);
+machine_arch_initcall(p1010_rdb, mpc85xx_pci_publish_devices);
machine_arch_initcall(p1010_rdb, swiotlb_setup_bus_notifier);
/*
diff --git a/arch/powerpc/platforms/85xx/p1022_ds.c b/arch/powerpc/platforms/85xx/p1022_ds.c
index e74b7cd..a8c4118 100644
--- a/arch/powerpc/platforms/85xx/p1022_ds.c
+++ b/arch/powerpc/platforms/85xx/p1022_ds.c
@@ -385,32 +385,9 @@ early_param("video", early_video_setup);
*/
static void __init p1022_ds_setup_arch(void)
{
-#ifdef CONFIG_PCI
- struct device_node *np;
-#endif
- dma_addr_t max = 0xffffffff;
-
if (ppc_md.progress)
ppc_md.progress("p1022_ds_setup_arch()", 0);
-#ifdef CONFIG_PCI
- for_each_compatible_node(np, "pci", "fsl,p1022-pcie") {
- struct resource rsrc;
- struct pci_controller *hose;
-
- of_address_to_resource(np, 0, &rsrc);
-
- if ((rsrc.start & 0xfffff) == 0x8000)
- fsl_add_bridge(np, 1);
- else
- fsl_add_bridge(np, 0);
-
- hose = pci_find_hose_for_OF_device(np);
- max = min(max, hose->dma_window_base_cur +
- hose->dma_window_size);
- }
-#endif
-
#if defined(CONFIG_FB_FSL_DIU) || defined(CONFIG_FB_FSL_DIU_MODULE)
diu_ops.get_pixel_format = p1022ds_get_pixel_format;
diu_ops.set_gamma_table = p1022ds_set_gamma_table;
@@ -450,11 +427,8 @@ static void __init p1022_ds_setup_arch(void)
mpc85xx_smp_init();
#ifdef CONFIG_SWIOTLB
- if (memblock_end_of_DRAM() > max) {
+ if (memblock_end_of_DRAM() > 0xffffffff)
ppc_swiotlb_enable = 1;
- set_pci_dma_ops(&swiotlb_dma_ops);
- ppc_md.pci_dma_dev_setup = pci_dma_dev_setup_swiotlb;
- }
#endif
pr_info("Freescale P1022 DS reference board\n");
@@ -473,6 +447,7 @@ static int __init p1022_ds_publish_devices(void)
}
machine_device_initcall(p1022_ds, p1022_ds_publish_devices);
+machine_arch_initcall(p1022_ds, mpc85xx_pci_publish_devices);
machine_arch_initcall(p1022_ds, swiotlb_setup_bus_notifier);
/*
diff --git a/arch/powerpc/platforms/85xx/p1023_rds.c b/arch/powerpc/platforms/85xx/p1023_rds.c
index 6b07398..c62303c 100644
--- a/arch/powerpc/platforms/85xx/p1023_rds.c
+++ b/arch/powerpc/platforms/85xx/p1023_rds.c
@@ -81,15 +81,11 @@ static void __init mpc85xx_rds_setup_arch(void)
}
}
-#ifdef CONFIG_PCI
- for_each_compatible_node(np, "pci", "fsl,p1023-pcie")
- fsl_add_bridge(np, 0);
-#endif
-
mpc85xx_smp_init();
}
machine_device_initcall(p1023_rds, mpc85xx_common_publish_devices);
+machine_arch_initcall(p1023_rds, mpc85xx_pci_publish_devices);
static void __init mpc85xx_rds_pic_init(void)
{
diff --git a/arch/powerpc/platforms/85xx/p2041_rdb.c b/arch/powerpc/platforms/85xx/p2041_rdb.c
index eda6ed5..5123400 100644
--- a/arch/powerpc/platforms/85xx/p2041_rdb.c
+++ b/arch/powerpc/platforms/85xx/p2041_rdb.c
@@ -81,6 +81,7 @@ define_machine(p2041_rdb) {
.power_save = e500_idle,
};
+machine_arch_initcall(p2041_rdb, mpc85xx_pci_publish_devices);
machine_device_initcall(p2041_rdb, corenet_ds_publish_devices);
#ifdef CONFIG_SWIOTLB
diff --git a/arch/powerpc/platforms/85xx/p3041_ds.c b/arch/powerpc/platforms/85xx/p3041_ds.c
index 96d99a3..aa0dd29 100644
--- a/arch/powerpc/platforms/85xx/p3041_ds.c
+++ b/arch/powerpc/platforms/85xx/p3041_ds.c
@@ -83,6 +83,7 @@ define_machine(p3041_ds) {
.power_save = e500_idle,
};
+machine_arch_initcall(p3041_ds, mpc85xx_pci_publish_devices);
machine_device_initcall(p3041_ds, corenet_ds_publish_devices);
#ifdef CONFIG_SWIOTLB
diff --git a/arch/powerpc/platforms/85xx/p3060_qds.c b/arch/powerpc/platforms/85xx/p3060_qds.c
index 081cf4a..51aece5 100644
--- a/arch/powerpc/platforms/85xx/p3060_qds.c
+++ b/arch/powerpc/platforms/85xx/p3060_qds.c
@@ -70,6 +70,7 @@ define_machine(p3060_qds) {
.power_save = e500_idle,
};
+machine_arch_initcall(p3060_qds, mpc85xx_pci_publish_devices);
machine_device_initcall(p3060_qds, corenet_ds_publish_devices);
#ifdef CONFIG_SWIOTLB
diff --git a/arch/powerpc/platforms/85xx/p4080_ds.c b/arch/powerpc/platforms/85xx/p4080_ds.c
index d1b21d7..e6b52e8 100644
--- a/arch/powerpc/platforms/85xx/p4080_ds.c
+++ b/arch/powerpc/platforms/85xx/p4080_ds.c
@@ -82,6 +82,7 @@ define_machine(p4080_ds) {
.power_save = e500_idle,
};
+machine_arch_initcall(p4080_ds, mpc85xx_pci_publish_devices);
machine_device_initcall(p4080_ds, corenet_ds_publish_devices);
#ifdef CONFIG_SWIOTLB
machine_arch_initcall(p4080_ds, swiotlb_setup_bus_notifier);
diff --git a/arch/powerpc/platforms/85xx/p5020_ds.c b/arch/powerpc/platforms/85xx/p5020_ds.c
index e8cba50..77953cc 100644
--- a/arch/powerpc/platforms/85xx/p5020_ds.c
+++ b/arch/powerpc/platforms/85xx/p5020_ds.c
@@ -92,6 +92,7 @@ define_machine(p5020_ds) {
#endif
};
+machine_arch_initcall(p5020_ds, mpc85xx_pci_publish_devices);
machine_device_initcall(p5020_ds, corenet_ds_publish_devices);
#ifdef CONFIG_SWIOTLB
diff --git a/arch/powerpc/platforms/85xx/sbc8548.c b/arch/powerpc/platforms/85xx/sbc8548.c
index 1677b8a..9049994 100644
--- a/arch/powerpc/platforms/85xx/sbc8548.c
+++ b/arch/powerpc/platforms/85xx/sbc8548.c
@@ -89,26 +89,9 @@ static int __init sbc8548_hw_rev(void)
*/
static void __init sbc8548_setup_arch(void)
{
-#ifdef CONFIG_PCI
- struct device_node *np;
-#endif
-
if (ppc_md.progress)
ppc_md.progress("sbc8548_setup_arch()", 0);
-#ifdef CONFIG_PCI
- for_each_node_by_type(np, "pci") {
- if (of_device_is_compatible(np, "fsl,mpc8540-pci") ||
- of_device_is_compatible(np, "fsl,mpc8548-pcie")) {
- struct resource rsrc;
- of_address_to_resource(np, 0, &rsrc);
- if ((rsrc.start & 0xfffff) == 0x8000)
- fsl_add_bridge(np, 1);
- else
- fsl_add_bridge(np, 0);
- }
- }
-#endif
sbc_rev = sbc8548_hw_rev();
}
@@ -129,6 +112,7 @@ static void sbc8548_show_cpuinfo(struct seq_file *m)
seq_printf(m, "PLL setting\t: 0x%x\n", ((phid1 >> 24) & 0x3f));
}
+machine_arch_initcall(sbc8548, mpc85xx_pci_publish_devices);
machine_device_initcall(sbc8548, mpc85xx_common_publish_devices);
/*
@@ -138,7 +122,14 @@ static int __init sbc8548_probe(void)
{
unsigned long root = of_get_flat_dt_root();
- return of_flat_dt_is_compatible(root, "SBC8548");
+ if (of_flat_dt_is_compatible(root, "SBC8548")) {
+#ifdef CONFIG_PCI
+ primary_phb_addr = 0x8000;
+#endif
+ return 1;
+ }
+
+ return 0;
}
define_machine(sbc8548) {
diff --git a/arch/powerpc/platforms/85xx/sbc8560.c b/arch/powerpc/platforms/85xx/sbc8560.c
index 3c3bbcc..c62692d 100644
--- a/arch/powerpc/platforms/85xx/sbc8560.c
+++ b/arch/powerpc/platforms/85xx/sbc8560.c
@@ -127,10 +127,6 @@ static void __init init_ioports(void)
static void __init sbc8560_setup_arch(void)
{
-#ifdef CONFIG_PCI
- struct device_node *np;
-#endif
-
if (ppc_md.progress)
ppc_md.progress("sbc8560_setup_arch()", 0);
@@ -138,11 +134,6 @@ static void __init sbc8560_setup_arch(void)
cpm2_reset();
init_ioports();
#endif
-
-#ifdef CONFIG_PCI
- for_each_compatible_node(np, "pci", "fsl,mpc8540-pci")
- fsl_add_bridge(np, 1);
-#endif
}
static void sbc8560_show_cpuinfo(struct seq_file *m)
@@ -161,6 +152,7 @@ static void sbc8560_show_cpuinfo(struct seq_file *m)
seq_printf(m, "PLL setting\t: 0x%x\n", ((phid1 >> 24) & 0x3f));
}
+machine_arch_initcall(sbc8560, mpc85xx_pci_publish_devices);
machine_device_initcall(sbc8560, mpc85xx_common_publish_devices);
/*
@@ -170,7 +162,14 @@ static int __init sbc8560_probe(void)
{
unsigned long root = of_get_flat_dt_root();
- return of_flat_dt_is_compatible(root, "SBC8560");
+ if (of_flat_dt_is_compatible(root, "SBC8560")) {
+#ifdef CONFIG_PCI
+ primary_phb_addr = 0x8000;
+#endif
+ return 1;
+ }
+
+ return 0;
}
#ifdef CONFIG_RTC_DRV_M48T59
diff --git a/arch/powerpc/platforms/85xx/socrates.c b/arch/powerpc/platforms/85xx/socrates.c
index b719192..eb94e586 100644
--- a/arch/powerpc/platforms/85xx/socrates.c
+++ b/arch/powerpc/platforms/85xx/socrates.c
@@ -67,19 +67,11 @@ static void __init socrates_pic_init(void)
*/
static void __init socrates_setup_arch(void)
{
-#ifdef CONFIG_PCI
- struct device_node *np;
-#endif
-
if (ppc_md.progress)
ppc_md.progress("socrates_setup_arch()", 0);
-
-#ifdef CONFIG_PCI
- for_each_compatible_node(np, "pci", "fsl,mpc8540-pci")
- fsl_add_bridge(np, 1);
-#endif
}
+machine_arch_initcall(socrates, mpc85xx_pci_publish_devices);
machine_device_initcall(socrates, mpc85xx_common_publish_devices);
/*
@@ -89,8 +81,12 @@ static int __init socrates_probe(void)
{
unsigned long root = of_get_flat_dt_root();
- if (of_flat_dt_is_compatible(root, "abb,socrates"))
+ if (of_flat_dt_is_compatible(root, "abb,socrates")) {
+#ifdef CONFIG_PCI
+ primary_phb_addr = 0x8000;
+#endif
return 1;
+ }
return 0;
}
diff --git a/arch/powerpc/platforms/85xx/stx_gp3.c b/arch/powerpc/platforms/85xx/stx_gp3.c
index 27ca3a7..92d2c3b 100644
--- a/arch/powerpc/platforms/85xx/stx_gp3.c
+++ b/arch/powerpc/platforms/85xx/stx_gp3.c
@@ -61,21 +61,12 @@ static void __init stx_gp3_pic_init(void)
*/
static void __init stx_gp3_setup_arch(void)
{
-#ifdef CONFIG_PCI
- struct device_node *np;
-#endif
-
if (ppc_md.progress)
ppc_md.progress("stx_gp3_setup_arch()", 0);
#ifdef CONFIG_CPM2
cpm2_reset();
#endif
-
-#ifdef CONFIG_PCI
- for_each_compatible_node(np, "pci", "fsl,mpc8540-pci")
- fsl_add_bridge(np, 1);
-#endif
}
static void stx_gp3_show_cpuinfo(struct seq_file *m)
@@ -94,6 +85,7 @@ static void stx_gp3_show_cpuinfo(struct seq_file *m)
seq_printf(m, "PLL setting\t: 0x%x\n", ((phid1 >> 24) & 0x3f));
}
+machine_arch_initcall(stx_gp3, mpc85xx_pci_publish_devices);
machine_device_initcall(stx_gp3, mpc85xx_common_publish_devices);
/*
@@ -103,7 +95,14 @@ static int __init stx_gp3_probe(void)
{
unsigned long root = of_get_flat_dt_root();
- return of_flat_dt_is_compatible(root, "stx,gp3-8560");
+ if (of_flat_dt_is_compatible(root, "stx,gp3-8560")) {
+#ifdef CONFIG_PCI
+ primary_phb_addr = 0x8000;
+#endif
+ return 1;
+ }
+
+ return 0;
}
define_machine(stx_gp3) {
diff --git a/arch/powerpc/platforms/85xx/tqm85xx.c b/arch/powerpc/platforms/85xx/tqm85xx.c
index d7504ce..c8e2599 100644
--- a/arch/powerpc/platforms/85xx/tqm85xx.c
+++ b/arch/powerpc/platforms/85xx/tqm85xx.c
@@ -60,31 +60,12 @@ static void __init tqm85xx_pic_init(void)
*/
static void __init tqm85xx_setup_arch(void)
{
-#ifdef CONFIG_PCI
- struct device_node *np;
-#endif
-
if (ppc_md.progress)
ppc_md.progress("tqm85xx_setup_arch()", 0);
#ifdef CONFIG_CPM2
cpm2_reset();
#endif
-
-#ifdef CONFIG_PCI
- for_each_node_by_type(np, "pci") {
- if (of_device_is_compatible(np, "fsl,mpc8540-pci") ||
- of_device_is_compatible(np, "fsl,mpc8548-pcie")) {
- struct resource rsrc;
- if (!of_address_to_resource(np, 0, &rsrc)) {
- if ((rsrc.start & 0xfffff) == 0x8000)
- fsl_add_bridge(np, 1);
- else
- fsl_add_bridge(np, 0);
- }
- }
- }
-#endif
}
static void tqm85xx_show_cpuinfo(struct seq_file *m)
@@ -124,6 +105,7 @@ static void __init tqm85xx_ti1520_fixup(struct pci_dev *pdev)
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_1520,
tqm85xx_ti1520_fixup);
+machine_arch_initcall(tqm85xx, mpc85xx_pci_publish_devices);
machine_device_initcall(tqm85xx, mpc85xx_common_publish_devices);
static const char *board[] __initdata = {
@@ -140,7 +122,14 @@ static const char *board[] __initdata = {
*/
static int __init tqm85xx_probe(void)
{
- return of_flat_dt_match(of_get_flat_dt_root(), board);
+ if (of_flat_dt_match(of_get_flat_dt_root(), board)) {
+#ifdef CONFIG_PCI
+ primary_phb_addr = 0x8000;
+#endif
+ return 1;
+ }
+
+ return 0;
}
define_machine(tqm85xx) {
diff --git a/arch/powerpc/platforms/85xx/xes_mpc85xx.c b/arch/powerpc/platforms/85xx/xes_mpc85xx.c
index 503c215..f5ef6b5 100644
--- a/arch/powerpc/platforms/85xx/xes_mpc85xx.c
+++ b/arch/powerpc/platforms/85xx/xes_mpc85xx.c
@@ -112,18 +112,11 @@ static void xes_mpc85xx_fixups(void)
}
}
-#ifdef CONFIG_PCI
-static int primary_phb_addr;
-#endif
-
/*
* Setup the architecture
*/
static void __init xes_mpc85xx_setup_arch(void)
{
-#ifdef CONFIG_PCI
- struct device_node *np;
-#endif
struct device_node *root;
const char *model = "Unknown";
@@ -138,20 +131,6 @@ static void __init xes_mpc85xx_setup_arch(void)
xes_mpc85xx_fixups();
-#ifdef CONFIG_PCI
- for_each_node_by_type(np, "pci") {
- if (of_device_is_compatible(np, "fsl,mpc8540-pci") ||
- of_device_is_compatible(np, "fsl,mpc8548-pcie")) {
- struct resource rsrc;
- of_address_to_resource(np, 0, &rsrc);
- if ((rsrc.start & 0xfffff) == primary_phb_addr)
- fsl_add_bridge(np, 1);
- else
- fsl_add_bridge(np, 0);
- }
- }
-#endif
-
mpc85xx_smp_init();
}
@@ -159,6 +138,10 @@ machine_device_initcall(xes_mpc8572, mpc85xx_common_publish_devices);
machine_device_initcall(xes_mpc8548, mpc85xx_common_publish_devices);
machine_device_initcall(xes_mpc8540, mpc85xx_common_publish_devices);
+machine_arch_initcall(xes_mpc8572, mpc85xx_pci_publish_devices);
+machine_arch_initcall(xes_mpc8548, mpc85xx_pci_publish_devices);
+machine_arch_initcall(xes_mpc8540, mpc85xx_pci_publish_devices);
+
/*
* Called very early, device-tree isn't unflattened
*/
diff --git a/arch/powerpc/platforms/86xx/gef_ppc9a.c b/arch/powerpc/platforms/86xx/gef_ppc9a.c
index ed58b6c..4f75816 100644
--- a/arch/powerpc/platforms/86xx/gef_ppc9a.c
+++ b/arch/powerpc/platforms/86xx/gef_ppc9a.c
@@ -74,13 +74,6 @@ static void __init gef_ppc9a_init_irq(void)
static void __init gef_ppc9a_setup_arch(void)
{
struct device_node *regs;
-#ifdef CONFIG_PCI
- struct device_node *np;
-
- for_each_compatible_node(np, "pci", "fsl,mpc8641-pcie") {
- fsl_add_bridge(np, 1);
- }
-#endif
printk(KERN_INFO "GE Intelligent Platforms PPC9A 6U VME SBC\n");
@@ -197,8 +190,12 @@ static int __init gef_ppc9a_probe(void)
{
unsigned long root = of_get_flat_dt_root();
- if (of_flat_dt_is_compatible(root, "gef,ppc9a"))
+ if (of_flat_dt_is_compatible(root, "gef,ppc9a")) {
+#ifdef CONFIG_PCI
+ primary_phb_addr = 0x8000;
+#endif
return 1;
+ }
return 0;
}
@@ -219,6 +216,27 @@ static long __init mpc86xx_time_init(void)
return 0;
}
+static struct of_device_id __initdata gef_ppc9a_pci_ids[] = {
+ { .compatible = "fsl,mpc8641-pcie", },
+ {},
+};
+
+static int __init gef_ppc9a_publish_pci_device(void)
+{
+ struct device_node *np;
+ int rc = 0;
+
+ for_each_matching_node(np, gef_ppc9a_pci_ids) {
+ rc = of_platform_bus_create(np, gef_ppc9a_pci_ids, NULL,
+ NULL, true);
+ if (rc)
+ break;
+ }
+
+ return rc;
+}
+machine_arch_initcall(gef_ppc9a, gef_ppc9a_publish_pci_device);
+
static __initdata struct of_device_id of_bus_ids[] = {
{ .compatible = "simple-bus", },
{ .compatible = "gianfar", },
diff --git a/arch/powerpc/platforms/86xx/gef_sbc310.c b/arch/powerpc/platforms/86xx/gef_sbc310.c
index 710db69..6be455b 100644
--- a/arch/powerpc/platforms/86xx/gef_sbc310.c
+++ b/arch/powerpc/platforms/86xx/gef_sbc310.c
@@ -74,13 +74,6 @@ static void __init gef_sbc310_init_irq(void)
static void __init gef_sbc310_setup_arch(void)
{
struct device_node *regs;
-#ifdef CONFIG_PCI
- struct device_node *np;
-
- for_each_compatible_node(np, "pci", "fsl,mpc8641-pcie") {
- fsl_add_bridge(np, 1);
- }
-#endif
printk(KERN_INFO "GE Intelligent Platforms SBC310 6U VPX SBC\n");
@@ -185,8 +178,12 @@ static int __init gef_sbc310_probe(void)
{
unsigned long root = of_get_flat_dt_root();
- if (of_flat_dt_is_compatible(root, "gef,sbc310"))
+ if (of_flat_dt_is_compatible(root, "gef,sbc310")) {
+#ifdef CONFIG_PCI
+ primary_phb_addr = 0x8000;
+#endif
return 1;
+ }
return 0;
}
@@ -207,6 +204,27 @@ static long __init mpc86xx_time_init(void)
return 0;
}
+static struct of_device_id __initdata gef_sbc310_pci_ids[] = {
+ { .compatible = "fsl,mpc8641-pcie", },
+ {},
+};
+
+static int __init gef_sbc310_publish_pci_device(void)
+{
+ struct device_node *np;
+ int rc = 0;
+
+ for_each_matching_node(np, gef_sbc310_pci_ids) {
+ rc = of_platform_bus_create(np, gef_sbc310_pci_ids, NULL,
+ NULL, true);
+ if (rc)
+ break;
+ }
+
+ return rc;
+}
+machine_arch_initcall(gef_sbc310, gef_sbc310_publish_pci_device);
+
static __initdata struct of_device_id of_bus_ids[] = {
{ .compatible = "simple-bus", },
{ .compatible = "gianfar", },
diff --git a/arch/powerpc/platforms/86xx/gef_sbc610.c b/arch/powerpc/platforms/86xx/gef_sbc610.c
index 4a13d2f..93e0f8d 100644
--- a/arch/powerpc/platforms/86xx/gef_sbc610.c
+++ b/arch/powerpc/platforms/86xx/gef_sbc610.c
@@ -74,13 +74,6 @@ static void __init gef_sbc610_init_irq(void)
static void __init gef_sbc610_setup_arch(void)
{
struct device_node *regs;
-#ifdef CONFIG_PCI
- struct device_node *np;
-
- for_each_compatible_node(np, "pci", "fsl,mpc8641-pcie") {
- fsl_add_bridge(np, 1);
- }
-#endif
printk(KERN_INFO "GE Intelligent Platforms SBC610 6U VPX SBC\n");
@@ -174,8 +167,12 @@ static int __init gef_sbc610_probe(void)
{
unsigned long root = of_get_flat_dt_root();
- if (of_flat_dt_is_compatible(root, "gef,sbc610"))
+ if (of_flat_dt_is_compatible(root, "gef,sbc610")) {
+#ifdef CONFIG_PCI
+ primary_phb_addr = 0x8000;
+#endif
return 1;
+ }
return 0;
}
@@ -196,6 +193,27 @@ static long __init mpc86xx_time_init(void)
return 0;
}
+static struct of_device_id __initdata gef_sbc610_pci_ids[] = {
+ { .compatible = "fsl,mpc8641-pcie", },
+ {},
+};
+
+static int __init gef_sbc610_publish_pci_device(void)
+{
+ struct device_node *np;
+ int rc = 0;
+
+ for_each_matching_node(np, gef_sbc610_pci_ids) {
+ rc = of_platform_bus_create(np, gef_sbc610_pci_ids, NULL,
+ NULL, true);
+ if (rc)
+ break;
+ }
+
+ return rc;
+}
+machine_arch_initcall(gef_sbc610, gef_sbc610_publish_pci_device);
+
static __initdata struct of_device_id of_bus_ids[] = {
{ .compatible = "simple-bus", },
{ .compatible = "gianfar", },
diff --git a/arch/powerpc/platforms/86xx/mpc8610_hpcd.c b/arch/powerpc/platforms/86xx/mpc8610_hpcd.c
index b8b1f33..a072145 100644
--- a/arch/powerpc/platforms/86xx/mpc8610_hpcd.c
+++ b/arch/powerpc/platforms/86xx/mpc8610_hpcd.c
@@ -86,6 +86,27 @@ static void __init mpc8610_suspend_init(void)
static inline void mpc8610_suspend_init(void) { }
#endif /* CONFIG_SUSPEND */
+static struct of_device_id __initdata mpc86xx_hpcd_pci_ids[] = {
+ { .compatible = "fsl,mpc8641-pcie", },
+ {},
+};
+
+static int __init mpc86xx_hpcd_publish_pci_device(void)
+{
+ struct device_node *np;
+ int rc = 0;
+
+ for_each_matching_node(np, mpc86xx_hpcd_pci_ids) {
+ rc = of_platform_bus_create(np, mpc86xx_hpcd_pci_ids, NULL,
+ NULL, true);
+ if (rc)
+ break;
+ }
+
+ return rc;
+}
+machine_arch_initcall(mpc86xx_hpcd, mpc86xx_hpcd_publish_pci_device);
+
static struct of_device_id __initdata mpc8610_ids[] = {
{ .compatible = "fsl,mpc8610-immr", },
{ .compatible = "fsl,mpc8610-guts", },
@@ -279,25 +300,11 @@ mpc8610hpcd_valid_monitor_port(enum fsl_diu_monitor_port port)
static void __init mpc86xx_hpcd_setup_arch(void)
{
struct resource r;
- struct device_node *np;
unsigned char *pixis;
if (ppc_md.progress)
ppc_md.progress("mpc86xx_hpcd_setup_arch()", 0);
-#ifdef CONFIG_PCI
- for_each_node_by_type(np, "pci") {
- if (of_device_is_compatible(np, "fsl,mpc8610-pci")
- || of_device_is_compatible(np, "fsl,mpc8641-pcie")) {
- struct resource rsrc;
- of_address_to_resource(np, 0, &rsrc);
- if ((rsrc.start & 0xfffff) == 0xa000)
- fsl_add_bridge(np, 1);
- else
- fsl_add_bridge(np, 0);
- }
- }
-#endif
#if defined(CONFIG_FB_FSL_DIU) || defined(CONFIG_FB_FSL_DIU_MODULE)
diu_ops.get_pixel_format = mpc8610hpcd_get_pixel_format;
diu_ops.set_gamma_table = mpc8610hpcd_set_gamma_table;
@@ -331,8 +338,12 @@ static int __init mpc86xx_hpcd_probe(void)
{
unsigned long root = of_get_flat_dt_root();
- if (of_flat_dt_is_compatible(root, "fsl,MPC8610HPCD"))
+ if (of_flat_dt_is_compatible(root, "fsl,MPC8610HPCD")) {
+#ifdef CONFIG_PCI
+ primary_phb_addr = 0xa000;
+#endif
return 1; /* Looks good */
+ }
return 0;
}
diff --git a/arch/powerpc/platforms/86xx/mpc86xx_hpcn.c b/arch/powerpc/platforms/86xx/mpc86xx_hpcn.c
index 569262c..2f44eb4 100644
--- a/arch/powerpc/platforms/86xx/mpc86xx_hpcn.c
+++ b/arch/powerpc/platforms/86xx/mpc86xx_hpcn.c
@@ -70,30 +70,11 @@ static int mpc86xx_exclude_device(struct pci_controller *hose,
static void __init
mpc86xx_hpcn_setup_arch(void)
{
-#ifdef CONFIG_PCI
- struct device_node *np;
- struct pci_controller *hose;
-#endif
- dma_addr_t max = 0xffffffff;
-
if (ppc_md.progress)
ppc_md.progress("mpc86xx_hpcn_setup_arch()", 0);
#ifdef CONFIG_PCI
- for_each_compatible_node(np, "pci", "fsl,mpc8641-pcie") {
- struct resource rsrc;
- of_address_to_resource(np, 0, &rsrc);
- if ((rsrc.start & 0xfffff) == 0x8000)
- fsl_add_bridge(np, 1);
- else
- fsl_add_bridge(np, 0);
- hose = pci_find_hose_for_OF_device(np);
- max = min(max, hose->dma_window_base_cur +
- hose->dma_window_size);
- }
-
ppc_md.pci_exclude_device = mpc86xx_exclude_device;
-
#endif
printk("MPC86xx HPCN board from Freescale Semiconductor\n");
@@ -103,11 +84,8 @@ mpc86xx_hpcn_setup_arch(void)
#endif
#ifdef CONFIG_SWIOTLB
- if (memblock_end_of_DRAM() > max) {
+ if (memblock_end_of_DRAM() > 0xffffffff)
ppc_swiotlb_enable = 1;
- set_pci_dma_ops(&swiotlb_dma_ops);
- ppc_md.pci_dma_dev_setup = pci_dma_dev_setup_swiotlb;
- }
#endif
}
@@ -130,12 +108,10 @@ static int __init mpc86xx_hpcn_probe(void)
{
unsigned long root = of_get_flat_dt_root();
- if (of_flat_dt_is_compatible(root, "fsl,mpc8641hpcn"))
- return 1; /* Looks good */
-
- /* Be nice and don't give silent boot death. Delete this in 2.6.27 */
- if (of_flat_dt_is_compatible(root, "mpc86xx")) {
- pr_warning("WARNING: your dts/dtb is old. You must update before the next kernel release\n");
+ if (of_flat_dt_is_compatible(root, "fsl,mpc8641hpcn")) {
+#ifdef CONFIG_PCI
+ primary_phb_addr = 0x8000;
+#endif
return 1;
}
@@ -159,6 +135,27 @@ mpc86xx_time_init(void)
return 0;
}
+static struct of_device_id __initdata mpc86xx_hpcn_pci_ids[] = {
+ { .compatible = "fsl,mpc8641-pcie", },
+ {},
+};
+
+static int __init mpc86xx_hpcn_publish_pci_device(void)
+{
+ struct device_node *np;
+ int rc = 0;
+
+ for_each_matching_node(np, mpc86xx_hpcn_pci_ids) {
+ rc = of_platform_bus_create(np, mpc86xx_hpcn_pci_ids, NULL,
+ NULL, true);
+ if (rc)
+ break;
+ }
+
+ return rc;
+}
+machine_arch_initcall(mpc86xx_hpcn, mpc86xx_hpcn_publish_pci_device);
+
static __initdata struct of_device_id of_bus_ids[] = {
{ .compatible = "simple-bus", },
{ .compatible = "fsl,srio", },
diff --git a/arch/powerpc/platforms/86xx/sbc8641d.c b/arch/powerpc/platforms/86xx/sbc8641d.c
index 51c8f33..7cffe8c 100644
--- a/arch/powerpc/platforms/86xx/sbc8641d.c
+++ b/arch/powerpc/platforms/86xx/sbc8641d.c
@@ -39,18 +39,9 @@
static void __init
sbc8641_setup_arch(void)
{
-#ifdef CONFIG_PCI
- struct device_node *np;
-#endif
-
if (ppc_md.progress)
ppc_md.progress("sbc8641_setup_arch()", 0);
-#ifdef CONFIG_PCI
- for_each_compatible_node(np, "pci", "fsl,mpc8641-pcie")
- fsl_add_bridge(np, 0);
-#endif
-
printk("SBC8641 board from Wind River\n");
#ifdef CONFIG_SMP
@@ -100,6 +91,27 @@ mpc86xx_time_init(void)
return 0;
}
+static struct of_device_id __initdata sbc8641_pci_ids[] = {
+ { .compatible = "fsl,mpc8641-pcie", },
+ {},
+};
+
+static int __init sbc8641_publish_pci_device(void)
+{
+ struct device_node *np;
+ int rc = 0;
+
+ for_each_matching_node(np, sbc8641_pci_ids) {
+ rc = of_platform_bus_create(np, sbc8641_pci_ids, NULL,
+ NULL, true);
+ if (rc)
+ break;
+ }
+
+ return rc;
+}
+machine_arch_initcall(sbc8641, sbc8641_publish_pci_device);
+
static __initdata struct of_device_id of_bus_ids[] = {
{ .compatible = "simple-bus", },
{ .compatible = "gianfar", },
diff --git a/drivers/of/platform.c b/drivers/of/platform.c
index 343ad29..a37330e 100644
--- a/drivers/of/platform.c
+++ b/drivers/of/platform.c
@@ -339,7 +339,7 @@ static const struct of_dev_auxdata *of_dev_lookup(const struct of_dev_auxdata *l
* Creates a platform_device for the provided device_node, and optionally
* recursively create devices for all the child nodes.
*/
-static int of_platform_bus_create(struct device_node *bus,
+int of_platform_bus_create(struct device_node *bus,
const struct of_device_id *matches,
const struct of_dev_auxdata *lookup,
struct device *parent, bool strict)
@@ -383,6 +383,7 @@ static int of_platform_bus_create(struct device_node *bus,
}
return rc;
}
+EXPORT_SYMBOL(of_platform_bus_create);
/**
* of_platform_bus_probe() - Probe the device-tree for platform buses
diff --git a/include/linux/of_platform.h b/include/linux/of_platform.h
index b47d204..680e48d 100644
--- a/include/linux/of_platform.h
+++ b/include/linux/of_platform.h
@@ -94,6 +94,10 @@ extern int of_platform_populate(struct device_node *root,
const struct of_device_id *matches,
const struct of_dev_auxdata *lookup,
struct device *parent);
+extern int of_platform_bus_create(struct device_node *bus,
+ const struct of_device_id *matches,
+ const struct of_dev_auxdata *lookup,
+ struct device *parent, bool strict);
#endif /* CONFIG_OF_ADDRESS */
#endif /* CONFIG_OF_DEVICE */
--
1.7.5.1
^ permalink raw reply related
* [PATCH V3 1/6] powerpc/fsl-pci: Unify pci/pcie initialization code
From: Jia Hongtao @ 2012-06-08 9:42 UTC (permalink / raw)
To: linuxppc-dev, galak; +Cc: R65777, b38951, B07421
In-Reply-To: <1339148527-16911-1-git-send-email-B38951@freescale.com>
We unified the Freescale pci/pcie initialization by changing the fsl_pci
to a platform driver.
In previous version pci/pcie initialization is in platform code which
Initialize pci bridge base on EP/RC or host/agent settings.
Signed-off-by: Jia Hongtao <B38951@freescale.com>
Signed-off-by: Li Yang <leoli@freescale.com>
---
arch/powerpc/sysdev/fsl_pci.c | 61 +++++++++++++++++++++++++++++++++++++++++
arch/powerpc/sysdev/fsl_pci.h | 1 +
2 files changed, 62 insertions(+), 0 deletions(-)
diff --git a/arch/powerpc/sysdev/fsl_pci.c b/arch/powerpc/sysdev/fsl_pci.c
index 6073288..4c3d130 100644
--- a/arch/powerpc/sysdev/fsl_pci.c
+++ b/arch/powerpc/sysdev/fsl_pci.c
@@ -807,3 +807,64 @@ u64 fsl_pci_immrbar_base(struct pci_controller *hose)
return 0;
}
+
+#if defined(CONFIG_FSL_SOC_BOOKE) || defined(CONFIG_PPC_86xx)
+static const struct of_device_id pci_ids[] = {
+ { .compatible = "fsl,mpc8540-pci", },
+ { .compatible = "fsl,mpc8548-pcie", },
+ { .compatible = "fsl,mpc8641-pcie", },
+ { .compatible = "fsl,p1022-pcie", },
+ { .compatible = "fsl,p1010-pcie", },
+ { .compatible = "fsl,p1023-pcie", },
+ { .compatible = "fsl,p4080-pcie", },
+ { .compatible = "fsl,qoriq-pcie-v2.3", },
+ { .compatible = "fsl,qoriq-pcie-v2.2", },
+ {},
+};
+
+int primary_phb_addr;
+static int __devinit fsl_pci_probe(struct platform_device *pdev)
+{
+ struct pci_controller *hose;
+ int ret;
+ bool is_primary;
+
+ if (of_match_node(pci_ids, pdev->dev.of_node)) {
+ struct resource rsrc;
+ of_address_to_resource(pdev->dev.of_node, 0, &rsrc);
+ is_primary = ((rsrc.start & 0xfffff) == primary_phb_addr);
+ ret = fsl_add_bridge(pdev->dev.of_node, is_primary);
+
+#ifdef CONFIG_SWIOTLB
+ hose = pci_find_hose_for_OF_device(pdev->dev.of_node);
+ /*
+ * if we couldn't map all of DRAM via the dma windows
+ * we need SWIOTLB to handle buffers located outside of
+ * dma capable memory region
+ */
+ if (memblock_end_of_DRAM() > hose->dma_window_base_cur
+ + hose->dma_window_size) {
+ ppc_swiotlb_enable = 1;
+ set_pci_dma_ops(&swiotlb_dma_ops);
+ ppc_md.pci_dma_dev_setup = pci_dma_dev_setup_swiotlb;
+ }
+#endif
+ }
+
+ return 0;
+}
+
+static struct platform_driver fsl_pci_driver = {
+ .driver = {
+ .name = "fsl-pci",
+ .of_match_table = pci_ids,
+ },
+ .probe = fsl_pci_probe,
+};
+
+static int __init fsl_pci_init(void)
+{
+ return platform_driver_register(&fsl_pci_driver);
+}
+arch_initcall(fsl_pci_init);
+#endif
diff --git a/arch/powerpc/sysdev/fsl_pci.h b/arch/powerpc/sysdev/fsl_pci.h
index a39ed5c..df9fc44 100644
--- a/arch/powerpc/sysdev/fsl_pci.h
+++ b/arch/powerpc/sysdev/fsl_pci.h
@@ -88,6 +88,7 @@ struct ccsr_pci {
__be32 pex_err_cap_r3; /* 0x.e34 - PCIE error capture register 0 */
};
+extern int primary_phb_addr;
extern int fsl_add_bridge(struct device_node *dev, int is_primary);
extern void fsl_pcibios_fixup_bus(struct pci_bus *bus);
extern int mpc83xx_add_bridge(struct device_node *dev);
--
1.7.5.1
^ permalink raw reply related
* [PATCH 0/6] Description for PCI patches using platform driver
From: Jia Hongtao @ 2012-06-08 9:42 UTC (permalink / raw)
To: linuxppc-dev, galak; +Cc: R65777, b38951, B07421
This series of patches are to unify pci initialization code and add PM support
for all 85xx/86xx powerpc boards. But two side effects are introduced by this
mechanism which listed below:
1. of_platform_bus_probe() will be called twice but in some cases duplication
warning occured. We fix this in [PATCH 5/6].
2. Edac driver failed to register pci nodes as platform devices. We fix this
in [PATCH 6/6].
These patches are against 'next' branch on:
http://git.kernel.org/?p=linux/kernel/git/galak/powerpc.git
^ permalink raw reply
* [PATCH v2 2/2] [POWERPC] uprobes: powerpc port
From: Ananth N Mavinakayanahalli @ 2012-06-08 9:34 UTC (permalink / raw)
To: linuxppc-dev, lkml
Cc: Srikar Dronamraju, peterz, antonb, oleg, michael, Jim Keniston,
Paul Mackerras, Ingo Molnar
In-Reply-To: <20120608093257.GG13409@in.ibm.com>
From: Ananth N Mavinakayanahalli <ananth@in.ibm.com>
This is the port of uprobes to powerpc. Usage is similar to x86.
One TODO in this port compared to x86 is the uprobe abort_xol() logic.
x86 depends on the thread_struct.trap_nr (absent in powerpc) to determine
if a signal was caused when the uprobed instruction was single-stepped/
emulated, in which case, we reset the instruction pointer to the probed
address and retry the probe again.
Tested on POWER6; I don't see anything here that should stop it from
working on a ppc32; since I don't have access to a ppc32 machine, it
would be good if somoene could verify that part.
[root@xxxx ~]# ./bin/perf probe -x /lib64/libc.so.6 malloc
Added new event:
probe_libc:malloc (on 0xb4860)
You can now use it in all perf tools, such as:
perf record -e probe_libc:malloc -aR sleep 1
[root@xxxx ~]# ./bin/perf record -e probe_libc:malloc -aR sleep 20
[ perf record: Woken up 22 times to write data ]
[ perf record: Captured and wrote 5.843 MB perf.data (~255302 samples) ]
[root@xxxx ~]# ./bin/perf report --stdio
# ========
# captured on: Mon Jun 4 05:26:31 2012
# hostname : xxxx.ibm.com
# os release : 3.4.0-uprobe
# perf version : 3.4.0
# arch : ppc64
# nrcpus online : 4
# nrcpus avail : 4
# cpudesc : POWER6 (raw), altivec supported
# cpuid : 62,769
# total memory : 7310528 kB
# cmdline : /root/bin/perf record -e probe_libc:malloc -aR sleep 20
# event : name = probe_libc:malloc, type = 2, config = 0x124, config1 = 0x0, con
# HEADER_CPU_TOPOLOGY info available, use -I to display
# HEADER_NUMA_TOPOLOGY info available, use -I to display
# ========
#
# Samples: 83K of event 'probe_libc:malloc'
# Event count (approx.): 83484
#
# Overhead Command Shared Object Symbol
# ........ ............ ............. ..........
#
69.05% tar libc-2.12.so [.] malloc
28.57% rm libc-2.12.so [.] malloc
1.32% avahi-daemon libc-2.12.so [.] malloc
0.58% bash libc-2.12.so [.] malloc
0.28% sshd libc-2.12.so [.] malloc
0.08% irqbalance libc-2.12.so [.] malloc
0.05% bzip2 libc-2.12.so [.] malloc
0.04% sleep libc-2.12.so [.] malloc
0.03% multipathd libc-2.12.so [.] malloc
0.01% sendmail libc-2.12.so [.] malloc
0.01% automount libc-2.12.so [.] malloc
V2:
a. arch_uprobe_analyze_insn() now gets unsigned long addr.
b. Verified that mtmsr[d] and rfi[d] are handled correctly by
emulate_step() (no changes to this patch).
Signed-off-by: Ananth N Mavinakayanahalli <ananth@in.ibm.com>
---
arch/powerpc/Kconfig | 3
arch/powerpc/include/asm/thread_info.h | 4
arch/powerpc/include/asm/uprobes.h | 49 +++++++++
arch/powerpc/kernel/Makefile | 1
arch/powerpc/kernel/signal.c | 6 +
arch/powerpc/kernel/uprobes.c | 164 +++++++++++++++++++++++++++++++++
6 files changed, 226 insertions(+), 1 deletion(-)
Index: linux-3.5-rc1/arch/powerpc/include/asm/thread_info.h
===================================================================
--- linux-3.5-rc1.orig/arch/powerpc/include/asm/thread_info.h
+++ linux-3.5-rc1/arch/powerpc/include/asm/thread_info.h
@@ -96,6 +96,7 @@ static inline struct thread_info *curren
#define TIF_RESTOREALL 11 /* Restore all regs (implies NOERROR) */
#define TIF_NOERROR 12 /* Force successful syscall return */
#define TIF_NOTIFY_RESUME 13 /* callback before returning to user */
+#define TIF_UPROBE 14 /* breakpointed or single-stepping */
#define TIF_SYSCALL_TRACEPOINT 15 /* syscall tracepoint instrumentation */
/* as above, but as bit values */
@@ -112,12 +113,13 @@ static inline struct thread_info *curren
#define _TIF_RESTOREALL (1<<TIF_RESTOREALL)
#define _TIF_NOERROR (1<<TIF_NOERROR)
#define _TIF_NOTIFY_RESUME (1<<TIF_NOTIFY_RESUME)
+#define _TIF_UPROBE (1<<TIF_UPROBE)
#define _TIF_SYSCALL_TRACEPOINT (1<<TIF_SYSCALL_TRACEPOINT)
#define _TIF_SYSCALL_T_OR_A (_TIF_SYSCALL_TRACE | _TIF_SYSCALL_AUDIT | \
_TIF_SECCOMP | _TIF_SYSCALL_TRACEPOINT)
#define _TIF_USER_WORK_MASK (_TIF_SIGPENDING | _TIF_NEED_RESCHED | \
- _TIF_NOTIFY_RESUME)
+ _TIF_NOTIFY_RESUME | _TIF_UPROBE)
#define _TIF_PERSYSCALL_MASK (_TIF_RESTOREALL|_TIF_NOERROR)
/* Bits in local_flags */
Index: linux-3.5-rc1/arch/powerpc/include/asm/uprobes.h
===================================================================
--- /dev/null
+++ linux-3.5-rc1/arch/powerpc/include/asm/uprobes.h
@@ -0,0 +1,49 @@
+#ifndef _ASM_UPROBES_H
+#define _ASM_UPROBES_H
+/*
+ * User-space Probes (UProbes) for powerpc
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Copyright (C) IBM Corporation, 2007-2012
+ *
+ * Adapted from the x86 port by Ananth N Mavinakayanahalli <ananth@in.ibm.com>
+ */
+
+#include <linux/notifier.h>
+
+typedef unsigned int uprobe_opcode_t;
+
+#define MAX_UINSN_BYTES 4
+#define UPROBE_XOL_SLOT_BYTES (MAX_UINSN_BYTES)
+
+#define UPROBE_SWBP_INSN 0x7fe00008
+#define UPROBE_SWBP_INSN_SIZE 4 /* swbp insn size in bytes */
+
+struct arch_uprobe {
+ u8 insn[MAX_UINSN_BYTES];
+};
+
+struct arch_uprobe_task {
+};
+
+extern int arch_uprobe_analyze_insn(struct arch_uprobe *aup, struct mm_struct *mm, unsigned long addr);
+extern unsigned long uprobe_get_swbp_addr(struct pt_regs *regs);
+extern int arch_uprobe_pre_xol(struct arch_uprobe *aup, struct pt_regs *regs);
+extern int arch_uprobe_post_xol(struct arch_uprobe *aup, struct pt_regs *regs);
+extern bool arch_uprobe_xol_was_trapped(struct task_struct *tsk);
+extern int arch_uprobe_exception_notify(struct notifier_block *self, unsigned long val, void *data);
+extern void arch_uprobe_abort_xol(struct arch_uprobe *aup, struct pt_regs *regs);
+#endif /* _ASM_UPROBES_H */
Index: linux-3.5-rc1/arch/powerpc/kernel/Makefile
===================================================================
--- linux-3.5-rc1.orig/arch/powerpc/kernel/Makefile
+++ linux-3.5-rc1/arch/powerpc/kernel/Makefile
@@ -96,6 +96,7 @@ obj-$(CONFIG_MODULES) += ppc_ksyms.o
obj-$(CONFIG_BOOTX_TEXT) += btext.o
obj-$(CONFIG_SMP) += smp.o
obj-$(CONFIG_KPROBES) += kprobes.o
+obj-$(CONFIG_UPROBES) += uprobes.o
obj-$(CONFIG_PPC_UDBG_16550) += legacy_serial.o udbg_16550.o
obj-$(CONFIG_STACKTRACE) += stacktrace.o
obj-$(CONFIG_SWIOTLB) += dma-swiotlb.o
Index: linux-3.5-rc1/arch/powerpc/kernel/signal.c
===================================================================
--- linux-3.5-rc1.orig/arch/powerpc/kernel/signal.c
+++ linux-3.5-rc1/arch/powerpc/kernel/signal.c
@@ -11,6 +11,7 @@
#include <linux/tracehook.h>
#include <linux/signal.h>
+#include <linux/uprobes.h>
#include <linux/key.h>
#include <asm/hw_breakpoint.h>
#include <asm/uaccess.h>
@@ -157,6 +158,11 @@ static int do_signal(struct pt_regs *reg
void do_notify_resume(struct pt_regs *regs, unsigned long thread_info_flags)
{
+ if (thread_info_flags & _TIF_UPROBE) {
+ clear_thread_flag(TIF_UPROBE);
+ uprobe_notify_resume(regs);
+ }
+
if (thread_info_flags & _TIF_SIGPENDING)
do_signal(regs);
Index: linux-3.5-rc1/arch/powerpc/kernel/uprobes.c
===================================================================
--- /dev/null
+++ linux-3.5-rc1/arch/powerpc/kernel/uprobes.c
@@ -0,0 +1,164 @@
+/*
+ * User-space Probes (UProbes) for powerpc
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Copyright (C) IBM Corporation, 2007-2012
+ *
+ * Adapted from the x86 port by Ananth N Mavinakayanahalli <ananth@in.ibm.com>
+ */
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/ptrace.h>
+#include <linux/uprobes.h>
+#include <linux/uaccess.h>
+
+#include <linux/kdebug.h>
+#include <asm/sstep.h>
+
+/**
+ * arch_uprobe_analyze_insn
+ * @mm: the probed address space.
+ * @arch_uprobe: the probepoint information.
+ * @addr: vaddr to probe.
+ * Return 0 on success or a -ve number on error.
+ */
+int arch_uprobe_analyze_insn(struct arch_uprobe *auprobe, struct mm_struct *mm, unsigned long addr)
+{
+ if (addr & 0x03)
+ return -EINVAL;
+ return 0;
+}
+
+/*
+ * arch_uprobe_pre_xol - prepare to execute out of line.
+ * @auprobe: the probepoint information.
+ * @regs: reflects the saved user state of current task.
+ */
+int arch_uprobe_pre_xol(struct arch_uprobe *auprobe, struct pt_regs *regs)
+{
+ /* FIXME: We don't support abort_xol on powerpc for now */
+ regs->nip = current->utask->xol_vaddr;
+ return 0;
+}
+
+/**
+ * uprobe_get_swbp_addr - compute address of swbp given post-swbp regs
+ * @regs: Reflects the saved state of the task after it has hit a breakpoint
+ * instruction.
+ * Return the address of the breakpoint instruction.
+ */
+unsigned long uprobe_get_swbp_addr(struct pt_regs *regs)
+{
+ return instruction_pointer(regs);
+}
+
+/*
+ * If xol insn itself traps and generates a signal (SIGILL/SIGSEGV/etc),
+ * then detect the case where a singlestepped instruction jumps back to its
+ * own address. It is assumed that anything like do_page_fault/do_trap/etc
+ * sets thread.trap_nr != -1.
+ *
+ * FIXME: powerpc however doesn't have thread.trap_nr yet.
+ *
+ * arch_uprobe_pre_xol/arch_uprobe_post_xol save/restore thread.trap_nr,
+ * arch_uprobe_xol_was_trapped() simply checks that ->trap_nr is not equal to
+ * UPROBE_TRAP_NR == -1 set by arch_uprobe_pre_xol().
+ */
+bool arch_uprobe_xol_was_trapped(struct task_struct *t)
+{
+ /* FIXME: We don't support abort_xol on powerpc for now */
+ return false;
+}
+
+/*
+ * Called after single-stepping. To avoid the SMP problems that can
+ * occur when we temporarily put back the original opcode to
+ * single-step, we single-stepped a copy of the instruction.
+ *
+ * This function prepares to resume execution after the single-step.
+ */
+int arch_uprobe_post_xol(struct arch_uprobe *auprobe, struct pt_regs *regs)
+{
+ /* FIXME: We don't support abort_xol on powerpc for now */
+
+ /*
+ * On powerpc, except for loads and stores, most instructions
+ * including ones that alter code flow (branches, calls, returns)
+ * are emulated in the kernel. We get here only if the emulation
+ * support doesn't exist and have to fix-up the next instruction
+ * to be executed.
+ */
+ regs->nip = current->utask->vaddr + MAX_UINSN_BYTES;
+ return 0;
+}
+
+/* callback routine for handling exceptions. */
+int arch_uprobe_exception_notify(struct notifier_block *self, unsigned long val, void *data)
+{
+ struct die_args *args = data;
+ struct pt_regs *regs = args->regs;
+ int ret = NOTIFY_DONE;
+
+ /* We are only interested in userspace traps */
+ if (regs && !user_mode(regs))
+ return NOTIFY_DONE;
+
+ switch (val) {
+ case DIE_BPT:
+ if (uprobe_pre_sstep_notifier(regs))
+ ret = NOTIFY_STOP;
+ break;
+ case DIE_SSTEP:
+ if (uprobe_post_sstep_notifier(regs))
+ ret = NOTIFY_STOP;
+ default:
+ break;
+ }
+ return ret;
+}
+
+/*
+ * This function gets called when XOL instruction either gets trapped or
+ * the thread has a fatal signal, so reset the instruction pointer to its
+ * probed address.
+ */
+void arch_uprobe_abort_xol(struct arch_uprobe *auprobe, struct pt_regs *regs)
+{
+ /* FIXME: We don't support abort_xol on powerpc for now */
+ return;
+}
+
+/*
+ * See if the instruction can be emulated.
+ * Returns true if instruction was emulated, false otherwise.
+ */
+bool arch_uprobe_skip_sstep(struct arch_uprobe *auprobe, struct pt_regs *regs)
+{
+ int ret;
+ unsigned int insn;
+
+ memcpy(&insn, auprobe->insn, MAX_UINSN_BYTES);
+
+ /*
+ * emulate_step() returns 1 if the insn was successfully emulated.
+ * For all other cases, we need to single-step in hardware.
+ */
+ ret = emulate_step(regs, insn);
+ if (ret > 0)
+ return true;
+
+ return false;
+}
Index: linux-3.5-rc1/arch/powerpc/Kconfig
===================================================================
--- linux-3.5-rc1.orig/arch/powerpc/Kconfig
+++ linux-3.5-rc1/arch/powerpc/Kconfig
@@ -237,6 +237,9 @@ config PPC_OF_PLATFORM_PCI
config ARCH_SUPPORTS_DEBUG_PAGEALLOC
def_bool y
+config ARCH_SUPPORTS_UPROBES
+ def_bool y
+
config PPC_ADV_DEBUG_REGS
bool
depends on 40x || BOOKE
^ permalink raw reply
* [PATCH v2 1/2] uprobes: Pass probed vaddr to arch_uprobe_analyze_insn()
From: Ananth N Mavinakayanahalli @ 2012-06-08 9:32 UTC (permalink / raw)
To: linuxppc-dev, lkml
Cc: Srikar Dronamraju, peterz, antonb, oleg, michael, Jim Keniston,
Paul Mackerras, Ingo Molnar
From: Ananth N Mavinakayanahalli <ananth@in.ibm.com>
On RISC architectures like powerpc, instructions are fixed size.
Instruction analysis on such platforms is just a matter of (insn % 4).
Pass the vaddr at which the uprobe is to be inserted so that
arch_uprobe_analyze_insn() can flag misaligned registration requests.
Changes in V2:
Pass (unsigned long)addr instead of (loff_t)vaddr to
arch_uprobe_analyze_insn(). We need the loff_t vaddr to take care of
the offset of inode:offset pair for large file sizes on 32bit.
Signed-off-by: Ananth N Mavinakaynahalli <ananth@in.ibm.com>
---
arch/x86/include/asm/uprobes.h | 2 +-
arch/x86/kernel/uprobes.c | 3 ++-
kernel/events/uprobes.c | 2 +-
3 files changed, 4 insertions(+), 3 deletions(-)
Index: linux-3.5-rc1/arch/x86/include/asm/uprobes.h
===================================================================
--- linux-3.5-rc1.orig/arch/x86/include/asm/uprobes.h
+++ linux-3.5-rc1/arch/x86/include/asm/uprobes.h
@@ -48,7 +48,7 @@ struct arch_uprobe_task {
#endif
};
-extern int arch_uprobe_analyze_insn(struct arch_uprobe *aup, struct mm_struct *mm);
+extern int arch_uprobe_analyze_insn(struct arch_uprobe *aup, struct mm_struct *mm, unsigned long addr);
extern int arch_uprobe_pre_xol(struct arch_uprobe *aup, struct pt_regs *regs);
extern int arch_uprobe_post_xol(struct arch_uprobe *aup, struct pt_regs *regs);
extern bool arch_uprobe_xol_was_trapped(struct task_struct *tsk);
Index: linux-3.5-rc1/arch/x86/kernel/uprobes.c
===================================================================
--- linux-3.5-rc1.orig/arch/x86/kernel/uprobes.c
+++ linux-3.5-rc1/arch/x86/kernel/uprobes.c
@@ -409,9 +409,10 @@ static int validate_insn_bits(struct arc
* arch_uprobe_analyze_insn - instruction analysis including validity and fixups.
* @mm: the probed address space.
* @arch_uprobe: the probepoint information.
+ * @addr: virtual address at which to install the probepoint
* Return 0 on success or a -ve number on error.
*/
-int arch_uprobe_analyze_insn(struct arch_uprobe *auprobe, struct mm_struct *mm)
+int arch_uprobe_analyze_insn(struct arch_uprobe *auprobe, struct mm_struct *mm, unsigned long addr)
{
int ret;
struct insn insn;
Index: linux-3.5-rc1/kernel/events/uprobes.c
===================================================================
--- linux-3.5-rc1.orig/kernel/events/uprobes.c
+++ linux-3.5-rc1/kernel/events/uprobes.c
@@ -697,7 +697,7 @@ install_breakpoint(struct uprobe *uprobe
if (is_swbp_insn((uprobe_opcode_t *)uprobe->arch.insn))
return -EEXIST;
- ret = arch_uprobe_analyze_insn(&uprobe->arch, mm);
+ ret = arch_uprobe_analyze_insn(&uprobe->arch, mm, addr);
if (ret)
return ret;
^ permalink raw reply
* Re: [PATCH 2/2] [POWERPC] uprobes: powerpc port
From: Ananth N Mavinakayanahalli @ 2012-06-08 9:21 UTC (permalink / raw)
To: Michael Ellerman
Cc: Jim Keniston, Srikar Dronamraju, Peter Zijlstra, lkml, oleg,
Paul Mackerras, Anton Blanchard, Ingo Molnar, linuxppc-dev
In-Reply-To: <1339137497.25573.9.camel@concordia>
On Fri, Jun 08, 2012 at 04:38:17PM +1000, Michael Ellerman wrote:
> On Fri, 2012-06-08 at 11:49 +0530, Ananth N Mavinakayanahalli wrote:
> > On Fri, Jun 08, 2012 at 04:17:44PM +1000, Michael Ellerman wrote:
> > > On Fri, 2012-06-08 at 11:31 +0530, Ananth N Mavinakayanahalli wrote:
> > > > On Fri, Jun 08, 2012 at 03:51:54PM +1000, Michael Ellerman wrote:
> > > > > On Fri, 2012-06-08 at 10:06 +0530, Ananth N Mavinakayanahalli wrote:
> > > >
> > > > But MSR_PR=1 and hence emulate_step() will return -1 and hence we will
> > > > end up single-stepping using user_enable_single_step(). Same with rfid.
> > >
> > > Right. But that was exactly Jim's point, you may be asked to emulate
> > > those instructions even though you wouldn't expect to see them in
> > > userspace code, so you need to handle it.
> > >
> > > Luckily it looks like emulate_step() will do the right thing for you.
> > > It'd be good to test it to make 100% sure.
> >
> > Sure. Will add that check and send v2.
>
> Sorry I didn't mean add a test in the code, I meant construct a test
> case to confirm that it works as expected.
Michael,
I just hand-coded the instr to emulate_step() and here are the results:
MSR_PR is set
insn = 7c600124, ret = 0 /* mtmsr */
insn = 7c600164, ret = 0 /* mtmsrd */
insn = 4c000024, ret = -1 /* rfid */
insn = 4c000064, ret = 0 /* rfi */
Also verified that standalone programs with those instructions in inline
asm will die with a SIGILL.
So, for mtmsr, mtmsrd and rfi, we have to single-step them which will
result in a SIGILL in turn.
Ananth
^ permalink raw reply
* Re: [PATCH] powerpc: Optimise the 64bit optimised __clear_user
From: Andreas Schwab @ 2012-06-08 7:34 UTC (permalink / raw)
To: Scott Wood
Cc: mikey, michael, Paul Mackerras, Anton Blanchard, olof,
linuxppc-dev
In-Reply-To: <4FD0EA08.7040903@freescale.com>
Scott Wood <scottwood@freescale.com> writes:
> and that objdump decodes it as "dcbz r0,r3" rather than "dcbz 0,r3".
<http://permalink.gmane.org/gmane.comp.gnu.binutils/57870>
Andreas.
--
Andreas Schwab, schwab@linux-m68k.org
GPG Key fingerprint = 58CA 54C7 6D53 942B 1756 01D3 44D5 214B 8276 4ED5
"And now for something completely different."
^ permalink raw reply
* Re: [PATCH 2/2] [POWERPC] uprobes: powerpc port
From: Michael Ellerman @ 2012-06-08 6:38 UTC (permalink / raw)
To: ananth
Cc: Jim Keniston, Srikar Dronamraju, Peter Zijlstra, lkml, oleg,
Paul Mackerras, Anton Blanchard, Ingo Molnar, linuxppc-dev
In-Reply-To: <20120608061954.GE13409@in.ibm.com>
On Fri, 2012-06-08 at 11:49 +0530, Ananth N Mavinakayanahalli wrote:
> On Fri, Jun 08, 2012 at 04:17:44PM +1000, Michael Ellerman wrote:
> > On Fri, 2012-06-08 at 11:31 +0530, Ananth N Mavinakayanahalli wrote:
> > > On Fri, Jun 08, 2012 at 03:51:54PM +1000, Michael Ellerman wrote:
> > > > On Fri, 2012-06-08 at 10:06 +0530, Ananth N Mavinakayanahalli wrote:
> > >
> > > But MSR_PR=1 and hence emulate_step() will return -1 and hence we will
> > > end up single-stepping using user_enable_single_step(). Same with rfid.
> >
> > Right. But that was exactly Jim's point, you may be asked to emulate
> > those instructions even though you wouldn't expect to see them in
> > userspace code, so you need to handle it.
> >
> > Luckily it looks like emulate_step() will do the right thing for you.
> > It'd be good to test it to make 100% sure.
>
> Sure. Will add that check and send v2.
Sorry I didn't mean add a test in the code, I meant construct a test
case to confirm that it works as expected.
cheers
^ permalink raw reply
* Re: [PATCH 2/2] [POWERPC] uprobes: powerpc port
From: Ananth N Mavinakayanahalli @ 2012-06-08 6:19 UTC (permalink / raw)
To: Michael Ellerman
Cc: Jim Keniston, Srikar Dronamraju, Peter Zijlstra, oleg, lkml,
Paul Mackerras, Anton Blanchard, Ingo Molnar, linuxppc-dev
In-Reply-To: <1339136264.25573.7.camel@concordia>
On Fri, Jun 08, 2012 at 04:17:44PM +1000, Michael Ellerman wrote:
> On Fri, 2012-06-08 at 11:31 +0530, Ananth N Mavinakayanahalli wrote:
> > On Fri, Jun 08, 2012 at 03:51:54PM +1000, Michael Ellerman wrote:
> > > On Fri, 2012-06-08 at 10:06 +0530, Ananth N Mavinakayanahalli wrote:
> > > > On Wed, Jun 06, 2012 at 11:08:04AM -0700, Jim Keniston wrote:
> > > > > On Wed, 2012-06-06 at 15:05 +0530, Ananth N Mavinakayanahalli wrote:
> > > > > > On Wed, Jun 06, 2012 at 11:27:02AM +0200, Peter Zijlstra wrote:
> > > > > > > On Wed, 2012-06-06 at 14:51 +0530, Ananth N Mavinakayanahalli wrote:
> > > >
> > > > ...
> > > >
> > > > > > For the kernel, the only ones that are off limits are rfi (return from
> > > > > > interrupt), mtmsr (move to msr). All other instructions can be probed.
> > > > > >
> > > > > > Both those instructions are supervisor level, so we won't see them in
> > > > > > userspace at all; so we should be able to probe all user level
> > > > > > instructions.
> > > > >
> > > > > Presumably rfi or mtmsr could show up in the instruction stream via an
> > > > > erroneous or mischievous asm statement. It'd be good to verify that you
> > > > > handle that gracefully.
> > > >
> > > > That'd be flagged elsewhere, by the architecture itself -- you'd get a
> > > > privileged instruciton exception if you try execute any instruction not
> > > > part of the UISA. I therefore don't think its a necessary check in the
> > > > uprobes code.
> > >
> > > But you're not executing the instruction, you're passing it to
> > > emulate_step(). Or am I missing something?
> >
> > But MSR_PR=1 and hence emulate_step() will return -1 and hence we will
> > end up single-stepping using user_enable_single_step(). Same with rfid.
>
> Right. But that was exactly Jim's point, you may be asked to emulate
> those instructions even though you wouldn't expect to see them in
> userspace code, so you need to handle it.
>
> Luckily it looks like emulate_step() will do the right thing for you.
> It'd be good to test it to make 100% sure.
Sure. Will add that check and send v2.
Ananth
^ permalink raw reply
* Re: [PATCH 2/2] [POWERPC] uprobes: powerpc port
From: Michael Ellerman @ 2012-06-08 6:17 UTC (permalink / raw)
To: ananth
Cc: Jim Keniston, Srikar Dronamraju, Peter Zijlstra, oleg, lkml,
Paul Mackerras, Anton Blanchard, Ingo Molnar, linuxppc-dev
In-Reply-To: <20120608060104.GD13409@in.ibm.com>
On Fri, 2012-06-08 at 11:31 +0530, Ananth N Mavinakayanahalli wrote:
> On Fri, Jun 08, 2012 at 03:51:54PM +1000, Michael Ellerman wrote:
> > On Fri, 2012-06-08 at 10:06 +0530, Ananth N Mavinakayanahalli wrote:
> > > On Wed, Jun 06, 2012 at 11:08:04AM -0700, Jim Keniston wrote:
> > > > On Wed, 2012-06-06 at 15:05 +0530, Ananth N Mavinakayanahalli wrote:
> > > > > On Wed, Jun 06, 2012 at 11:27:02AM +0200, Peter Zijlstra wrote:
> > > > > > On Wed, 2012-06-06 at 14:51 +0530, Ananth N Mavinakayanahalli wrote:
> > >
> > > ...
> > >
> > > > > For the kernel, the only ones that are off limits are rfi (return from
> > > > > interrupt), mtmsr (move to msr). All other instructions can be probed.
> > > > >
> > > > > Both those instructions are supervisor level, so we won't see them in
> > > > > userspace at all; so we should be able to probe all user level
> > > > > instructions.
> > > >
> > > > Presumably rfi or mtmsr could show up in the instruction stream via an
> > > > erroneous or mischievous asm statement. It'd be good to verify that you
> > > > handle that gracefully.
> > >
> > > That'd be flagged elsewhere, by the architecture itself -- you'd get a
> > > privileged instruciton exception if you try execute any instruction not
> > > part of the UISA. I therefore don't think its a necessary check in the
> > > uprobes code.
> >
> > But you're not executing the instruction, you're passing it to
> > emulate_step(). Or am I missing something?
>
> But MSR_PR=1 and hence emulate_step() will return -1 and hence we will
> end up single-stepping using user_enable_single_step(). Same with rfid.
Right. But that was exactly Jim's point, you may be asked to emulate
those instructions even though you wouldn't expect to see them in
userspace code, so you need to handle it.
Luckily it looks like emulate_step() will do the right thing for you.
It'd be good to test it to make 100% sure.
cheers
^ permalink raw reply
* Re: [PATCH 2/2] [POWERPC] uprobes: powerpc port
From: Ananth N Mavinakayanahalli @ 2012-06-08 6:01 UTC (permalink / raw)
To: Michael Ellerman
Cc: Jim Keniston, Srikar Dronamraju, Peter Zijlstra, lkml, oleg,
Paul Mackerras, Anton Blanchard, Ingo Molnar, linuxppc-dev
In-Reply-To: <1339134714.25573.4.camel@concordia>
On Fri, Jun 08, 2012 at 03:51:54PM +1000, Michael Ellerman wrote:
> On Fri, 2012-06-08 at 10:06 +0530, Ananth N Mavinakayanahalli wrote:
> > On Wed, Jun 06, 2012 at 11:08:04AM -0700, Jim Keniston wrote:
> > > On Wed, 2012-06-06 at 15:05 +0530, Ananth N Mavinakayanahalli wrote:
> > > > On Wed, Jun 06, 2012 at 11:27:02AM +0200, Peter Zijlstra wrote:
> > > > > On Wed, 2012-06-06 at 14:51 +0530, Ananth N Mavinakayanahalli wrote:
> >
> > ...
> >
> > > > For the kernel, the only ones that are off limits are rfi (return from
> > > > interrupt), mtmsr (move to msr). All other instructions can be probed.
> > > >
> > > > Both those instructions are supervisor level, so we won't see them in
> > > > userspace at all; so we should be able to probe all user level
> > > > instructions.
> > >
> > > Presumably rfi or mtmsr could show up in the instruction stream via an
> > > erroneous or mischievous asm statement. It'd be good to verify that you
> > > handle that gracefully.
> >
> > That'd be flagged elsewhere, by the architecture itself -- you'd get a
> > privileged instruciton exception if you try execute any instruction not
> > part of the UISA. I therefore don't think its a necessary check in the
> > uprobes code.
>
> But you're not executing the instruction, you're passing it to
> emulate_step(). Or am I missing something?
But MSR_PR=1 and hence emulate_step() will return -1 and hence we will
end up single-stepping using user_enable_single_step(). Same with rfid.
Ananth
^ permalink raw reply
* Re: [PATCH 2/2] [POWERPC] uprobes: powerpc port
From: Michael Ellerman @ 2012-06-08 5:51 UTC (permalink / raw)
To: ananth
Cc: Jim Keniston, Srikar Dronamraju, Peter Zijlstra, lkml, oleg,
Paul Mackerras, Anton Blanchard, Ingo Molnar, linuxppc-dev
In-Reply-To: <20120608043605.GB13409@in.ibm.com>
On Fri, 2012-06-08 at 10:06 +0530, Ananth N Mavinakayanahalli wrote:
> On Wed, Jun 06, 2012 at 11:08:04AM -0700, Jim Keniston wrote:
> > On Wed, 2012-06-06 at 15:05 +0530, Ananth N Mavinakayanahalli wrote:
> > > On Wed, Jun 06, 2012 at 11:27:02AM +0200, Peter Zijlstra wrote:
> > > > On Wed, 2012-06-06 at 14:51 +0530, Ananth N Mavinakayanahalli wrote:
>
> ...
>
> > > For the kernel, the only ones that are off limits are rfi (return from
> > > interrupt), mtmsr (move to msr). All other instructions can be probed.
> > >
> > > Both those instructions are supervisor level, so we won't see them in
> > > userspace at all; so we should be able to probe all user level
> > > instructions.
> >
> > Presumably rfi or mtmsr could show up in the instruction stream via an
> > erroneous or mischievous asm statement. It'd be good to verify that you
> > handle that gracefully.
>
> That'd be flagged elsewhere, by the architecture itself -- you'd get a
> privileged instruciton exception if you try execute any instruction not
> part of the UISA. I therefore don't think its a necessary check in the
> uprobes code.
But you're not executing the instruction, you're passing it to
emulate_step(). Or am I missing something?
cheers
^ permalink raw reply
* Re: [PATCH 2/2] [POWERPC] uprobes: powerpc port
From: Ananth N Mavinakayanahalli @ 2012-06-08 4:36 UTC (permalink / raw)
To: Jim Keniston
Cc: Srikar Dronamraju, Peter Zijlstra, oleg, lkml, Paul Mackerras,
Anton Blanchard, Ingo Molnar, linuxppc-dev
In-Reply-To: <1339006084.3458.25.camel@localhost>
On Wed, Jun 06, 2012 at 11:08:04AM -0700, Jim Keniston wrote:
> On Wed, 2012-06-06 at 15:05 +0530, Ananth N Mavinakayanahalli wrote:
> > On Wed, Jun 06, 2012 at 11:27:02AM +0200, Peter Zijlstra wrote:
> > > On Wed, 2012-06-06 at 14:51 +0530, Ananth N Mavinakayanahalli wrote:
...
> > For the kernel, the only ones that are off limits are rfi (return from
> > interrupt), mtmsr (move to msr). All other instructions can be probed.
> >
> > Both those instructions are supervisor level, so we won't see them in
> > userspace at all; so we should be able to probe all user level
> > instructions.
>
> Presumably rfi or mtmsr could show up in the instruction stream via an
> erroneous or mischievous asm statement. It'd be good to verify that you
> handle that gracefully.
That'd be flagged elsewhere, by the architecture itself -- you'd get a
privileged instruciton exception if you try execute any instruction not
part of the UISA. I therefore don't think its a necessary check in the
uprobes code.
Ananth
^ permalink raw reply
* Re: [PATCH 1/2] uprobes: Pass probed vaddr to arch_uprobe_analyze_insn()
From: Ananth N Mavinakayanahalli @ 2012-06-08 4:33 UTC (permalink / raw)
To: Srikar Dronamraju
Cc: Peter Zijlstra, lkml, oleg, Paul Mackerras, Anton Blanchard,
Ingo Molnar, linuxppc-dev, Ingo Molnar
In-Reply-To: <20120606114423.GA32094@linux.vnet.ibm.com>
On Wed, Jun 06, 2012 at 05:14:23PM +0530, Srikar Dronamraju wrote:
> * Ingo Molnar <mingo@kernel.org> [2012-06-06 11:40:15]:
>
> >
> > * Ananth N Mavinakayanahalli <ananth@in.ibm.com> wrote:
> >
> > > On Wed, Jun 06, 2012 at 11:23:52AM +0200, Peter Zijlstra wrote:
> > > > On Wed, 2012-06-06 at 14:49 +0530, Ananth N Mavinakayanahalli wrote:
> > > > > +int arch_uprobe_analyze_insn(struct arch_uprobe *auprobe, struct mm_struct *mm, loff_t vaddr)
> > > >
> > > > Don't we traditionally use unsigned long to pass vaddrs?
> > >
> > > Right. But the vaddr we pass here is vma_info->vaddr which is loff_t.
> > > I guess I should've made that clear in the patch description.
> >
> > Why not fix struct vma_info's vaddr type?
> >
>
> Calculating and comparing vaddr results either uses variables of type loff_t.
> To avoid typecasting and avoid overflow at each of these places, we used
> loff_t.
>
> Ananth, install_breakpoint() already has a variable of type addr of type
> unsigned long. Why dont you use addr instead of vaddr.
Ok, makes sense. I'll change it in v2.
Ananth
^ permalink raw reply
* [PATCH 5/5] powerpc: iommu: Implement IOMMU pools to improve multiqueue adapter performance
From: Anton Blanchard @ 2012-06-08 4:14 UTC (permalink / raw)
To: Michael Ellerman; +Cc: olof, paulus, linuxppc-dev
In-Reply-To: <1339123423.3330.5.camel@concordia>
At the moment all queues in a multiqueue adapter will serialise
against the IOMMU table lock. This is proving to be a big issue,
especially with 10Gbit ethernet.
This patch creates 4 pools and tries to spread the load across
them. If the table is under 1GB in size we revert back to the
original behaviour of 1 pool and 1 largealloc pool.
We create a hash to map CPUs to pools. Since we prefer interrupts to
be affinitised to primary CPUs, without some form of hashing we are
very likely to end up using the same pool. As an example, POWER7
has 4 way SMT and with 4 pools all primary threads will map to the
same pool.
The largealloc pool is reduced from 1/2 to 1/4 of the space to
partially offset the overhead of breaking the table up into pools.
Some performance numbers were obtained with a Chelsio T3 adapter on
two POWER7 boxes, running a 100 session TCP round robin test.
Performance improved 69% with this patch applied.
Signed-off-by: Anton Blanchard <anton@samba.org>
---
All patches combined improve performance by 178%
v2.0: Fix cell build, noticed by mpe.
Index: linux-build/arch/powerpc/kernel/iommu.c
===================================================================
--- linux-build.orig/arch/powerpc/kernel/iommu.c 2012-06-08 14:02:46.229104320 +1000
+++ linux-build/arch/powerpc/kernel/iommu.c 2012-06-08 14:02:46.861113517 +1000
@@ -33,6 +33,7 @@
#include <linux/bitmap.h>
#include <linux/iommu-helper.h>
#include <linux/crash_dump.h>
+#include <linux/hash.h>
#include <asm/io.h>
#include <asm/prom.h>
#include <asm/iommu.h>
@@ -58,6 +59,26 @@ static int __init setup_iommu(char *str)
__setup("iommu=", setup_iommu);
+static DEFINE_PER_CPU(unsigned int, iommu_pool_hash);
+
+/*
+ * We precalculate the hash to avoid doing it on every allocation.
+ *
+ * The hash is important to spread CPUs across all the pools. For example,
+ * on a POWER7 with 4 way SMT we want interrupts on the primary threads and
+ * with 4 pools all primary threads would map to the same pool.
+ */
+static int __init setup_iommu_pool_hash(void)
+{
+ unsigned int i;
+
+ for_each_possible_cpu(i)
+ per_cpu(iommu_pool_hash, i) = hash_32(i, IOMMU_POOL_HASHBITS);
+
+ return 0;
+}
+subsys_initcall(setup_iommu_pool_hash);
+
static unsigned long iommu_range_alloc(struct device *dev,
struct iommu_table *tbl,
unsigned long npages,
@@ -72,6 +93,8 @@ static unsigned long iommu_range_alloc(s
unsigned long align_mask;
unsigned long boundary_size;
unsigned long flags;
+ unsigned int pool_nr;
+ struct iommu_pool *pool;
align_mask = 0xffffffffffffffffl >> (64 - align_order);
@@ -84,38 +107,46 @@ static unsigned long iommu_range_alloc(s
return DMA_ERROR_CODE;
}
- spin_lock_irqsave(&(tbl->it_lock), flags);
+ /*
+ * We don't need to disable preemption here because any CPU can
+ * safely use any IOMMU pool.
+ */
+ pool_nr = __raw_get_cpu_var(iommu_pool_hash) & (tbl->nr_pools - 1);
- if (handle && *handle)
- start = *handle;
+ if (largealloc)
+ pool = &(tbl->large_pool);
else
- start = largealloc ? tbl->it_largehint : tbl->it_hint;
+ pool = &(tbl->pools[pool_nr]);
+
+ spin_lock_irqsave(&(pool->lock), flags);
- /* Use only half of the table for small allocs (15 pages or less) */
- limit = largealloc ? tbl->it_size : tbl->it_halfpoint;
+again:
+ if ((pass == 0) && handle && *handle)
+ start = *handle;
+ else
+ start = pool->hint;
- if (largealloc && start < tbl->it_halfpoint)
- start = tbl->it_halfpoint;
+ limit = pool->end;
/* The case below can happen if we have a small segment appended
* to a large, or when the previous alloc was at the very end of
* the available space. If so, go back to the initial start.
*/
if (start >= limit)
- start = largealloc ? tbl->it_largehint : tbl->it_hint;
-
- again:
+ start = pool->start;
if (limit + tbl->it_offset > mask) {
limit = mask - tbl->it_offset + 1;
/* If we're constrained on address range, first try
* at the masked hint to avoid O(n) search complexity,
- * but on second pass, start at 0.
+ * but on second pass, start at 0 in pool 0.
*/
- if ((start & mask) >= limit || pass > 0)
- start = 0;
- else
+ if ((start & mask) >= limit || pass > 0) {
+ pool = &(tbl->pools[0]);
+ start = pool->start;
+ } else {
start &= mask;
+ }
}
if (dev)
@@ -129,17 +160,25 @@ static unsigned long iommu_range_alloc(s
tbl->it_offset, boundary_size >> IOMMU_PAGE_SHIFT,
align_mask);
if (n == -1) {
- if (likely(pass < 2)) {
- /* First failure, just rescan the half of the table.
- * Second failure, rescan the other half of the table.
- */
- start = (largealloc ^ pass) ? tbl->it_halfpoint : 0;
- limit = pass ? tbl->it_size : limit;
+ if (likely(pass == 0)) {
+ /* First try the pool from the start */
+ pool->hint = pool->start;
pass++;
goto again;
+
+ } else if (pass <= tbl->nr_pools) {
+ /* Now try scanning all the other pools */
+ spin_unlock(&(pool->lock));
+ pool_nr = (pool_nr + 1) & (tbl->nr_pools - 1);
+ pool = &tbl->pools[pool_nr];
+ spin_lock(&(pool->lock));
+ pool->hint = pool->start;
+ pass++;
+ goto again;
+
} else {
- /* Third failure, give up */
- spin_unlock_irqrestore(&(tbl->it_lock), flags);
+ /* Give up */
+ spin_unlock_irqrestore(&(pool->lock), flags);
return DMA_ERROR_CODE;
}
}
@@ -149,10 +188,10 @@ static unsigned long iommu_range_alloc(s
/* Bump the hint to a new block for small allocs. */
if (largealloc) {
/* Don't bump to new block to avoid fragmentation */
- tbl->it_largehint = end;
+ pool->hint = end;
} else {
/* Overflow will be taken care of at the next allocation */
- tbl->it_hint = (end + tbl->it_blocksize - 1) &
+ pool->hint = (end + tbl->it_blocksize - 1) &
~(tbl->it_blocksize - 1);
}
@@ -160,7 +199,8 @@ static unsigned long iommu_range_alloc(s
if (handle)
*handle = end;
- spin_unlock_irqrestore(&(tbl->it_lock), flags);
+ spin_unlock_irqrestore(&(pool->lock), flags);
+
return n;
}
@@ -235,23 +275,45 @@ static bool iommu_free_check(struct iomm
return true;
}
+static struct iommu_pool *get_pool(struct iommu_table *tbl,
+ unsigned long entry)
+{
+ struct iommu_pool *p;
+ unsigned long largepool_start = tbl->large_pool.start;
+
+ /* The large pool is the last pool at the top of the table */
+ if (entry >= largepool_start) {
+ p = &tbl->large_pool;
+ } else {
+ unsigned int pool_nr = entry / tbl->poolsize;
+
+ BUG_ON(pool_nr > tbl->nr_pools);
+ p = &tbl->pools[pool_nr];
+ }
+
+ return p;
+}
+
static void __iommu_free(struct iommu_table *tbl, dma_addr_t dma_addr,
unsigned int npages)
{
unsigned long entry, free_entry;
unsigned long flags;
+ struct iommu_pool *pool;
entry = dma_addr >> IOMMU_PAGE_SHIFT;
free_entry = entry - tbl->it_offset;
+ pool = get_pool(tbl, free_entry);
+
if (!iommu_free_check(tbl, dma_addr, npages))
return;
ppc_md.tce_free(tbl, entry, npages);
- spin_lock_irqsave(&(tbl->it_lock), flags);
+ spin_lock_irqsave(&(pool->lock), flags);
bitmap_clear(tbl->it_map, free_entry, npages);
- spin_unlock_irqrestore(&(tbl->it_lock), flags);
+ spin_unlock_irqrestore(&(pool->lock), flags);
}
static void iommu_free(struct iommu_table *tbl, dma_addr_t dma_addr,
@@ -493,9 +555,8 @@ struct iommu_table *iommu_init_table(str
unsigned long sz;
static int welcomed = 0;
struct page *page;
-
- /* Set aside 1/4 of the table for large allocations. */
- tbl->it_halfpoint = tbl->it_size * 3 / 4;
+ unsigned int i;
+ struct iommu_pool *p;
/* number of bytes needed for the bitmap */
sz = (tbl->it_size + 7) >> 3;
@@ -514,9 +575,28 @@ struct iommu_table *iommu_init_table(str
if (tbl->it_offset == 0)
set_bit(0, tbl->it_map);
- tbl->it_hint = 0;
- tbl->it_largehint = tbl->it_halfpoint;
- spin_lock_init(&tbl->it_lock);
+ /* We only split the IOMMU table if we have 1GB or more of space */
+ if ((tbl->it_size << IOMMU_PAGE_SHIFT) >= (1UL * 1024 * 1024 * 1024))
+ tbl->nr_pools = IOMMU_NR_POOLS;
+ else
+ tbl->nr_pools = 1;
+
+ /* We reserve the top 1/4 of the table for large allocations */
+ tbl->poolsize = (tbl->it_size * 3 / 4) / IOMMU_NR_POOLS;
+
+ for (i = 0; i < IOMMU_NR_POOLS; i++) {
+ p = &tbl->pools[i];
+ spin_lock_init(&(p->lock));
+ p->start = tbl->poolsize * i;
+ p->hint = p->start;
+ p->end = p->start + tbl->poolsize;
+ }
+
+ p = &tbl->large_pool;
+ spin_lock_init(&(p->lock));
+ p->start = tbl->poolsize * i;
+ p->hint = p->start;
+ p->end = tbl->it_size;
iommu_table_clear(tbl);
Index: linux-build/arch/powerpc/include/asm/iommu.h
===================================================================
--- linux-build.orig/arch/powerpc/include/asm/iommu.h 2012-06-06 14:44:13.106458136 +1000
+++ linux-build/arch/powerpc/include/asm/iommu.h 2012-06-08 14:02:46.861113517 +1000
@@ -53,6 +53,16 @@ static __inline__ __attribute_const__ in
*/
#define IOMAP_MAX_ORDER 13
+#define IOMMU_POOL_HASHBITS 2
+#define IOMMU_NR_POOLS (1 << IOMMU_POOL_HASHBITS)
+
+struct iommu_pool {
+ unsigned long start;
+ unsigned long end;
+ unsigned long hint;
+ spinlock_t lock;
+} ____cacheline_aligned_in_smp;
+
struct iommu_table {
unsigned long it_busno; /* Bus number this table belongs to */
unsigned long it_size; /* Size of iommu table in entries */
@@ -61,10 +71,10 @@ struct iommu_table {
unsigned long it_index; /* which iommu table this is */
unsigned long it_type; /* type: PCI or Virtual Bus */
unsigned long it_blocksize; /* Entries in each block (cacheline) */
- unsigned long it_hint; /* Hint for next alloc */
- unsigned long it_largehint; /* Hint for large allocs */
- unsigned long it_halfpoint; /* Breaking point for small/large allocs */
- spinlock_t it_lock; /* Protects it_map */
+ unsigned long poolsize;
+ unsigned long nr_pools;
+ struct iommu_pool large_pool;
+ struct iommu_pool pools[IOMMU_NR_POOLS];
unsigned long *it_map; /* A simple allocation bitmap for now */
};
Index: linux-build/arch/powerpc/platforms/cell/iommu.c
===================================================================
--- linux-build.orig/arch/powerpc/platforms/cell/iommu.c 2012-04-05 13:47:45.715857539 +1000
+++ linux-build/arch/powerpc/platforms/cell/iommu.c 2012-06-08 14:03:00.053305540 +1000
@@ -518,7 +518,6 @@ cell_iommu_setup_window(struct cbe_iommu
__set_bit(0, window->table.it_map);
tce_build_cell(&window->table, window->table.it_offset, 1,
(unsigned long)iommu->pad_page, DMA_TO_DEVICE, NULL);
- window->table.it_hint = window->table.it_blocksize;
return window;
}
^ permalink raw reply
* Re: [PATCH 1/3][RFC] ftrace/ppc: Have PPC skip updating with stop_machine()
From: Michael Ellerman @ 2012-06-08 4:13 UTC (permalink / raw)
To: Steven Rostedt; +Cc: linuxppc-dev, linux-kernel
In-Reply-To: <20120426183508.749515835@goodmis.org>
On Thu, 2012-04-26 at 14:31 -0400, Steven Rostedt wrote:
> plain text document attachment
> (0001-ftrace-ppc-Have-PPC-skip-updating-with-stop_machine.patch)
> From: Steven Rostedt <srostedt@redhat.com>
>
> PPC does not have the synchronization issues that x86 has with
> modifying code on one CPU while another CPU is executing it.
> The other CPU will either see the old or new code without any
> issues, unlike x86 which may issue a GPF.
>
> Instead of calling the heavy stop_machine, just update the code.
This looks nice, but it's giving me this:
arch/powerpc/kernel/ftrace.c:497:13: error: static declaration of 'ftrace_replace_code' follows non-static declaration
include/linux/ftrace.h:317:13: note: previous declaration of 'ftrace_replace_code' was here
I think the fix is just to make our ftrace_replace_code() non-static?
cheers
> +static void ftrace_replace_code(int enable)
> +{
> + struct ftrace_rec_iter *iter;
> + struct dyn_ftrace *rec;
> + int ret;
> +
> + for (iter = ftrace_rec_iter_start(); iter;
> + iter = ftrace_rec_iter_next(iter)) {
> + rec = ftrace_rec_iter_record(iter);
> + ret = __ftrace_replace_code(rec, enable);
> + if (ret) {
> + ftrace_bug(ret, rec->ip);
> + return;
> + }
> + }
> +}
> +
^ permalink raw reply
* Re: [PATCH 5/5] powerpc: iommu: Implement IOMMU pools to improve multiqueue adapter performance
From: Michael Ellerman @ 2012-06-08 4:03 UTC (permalink / raw)
To: Anton Blanchard; +Cc: olof, paulus, linuxppc-dev
In-Reply-To: <20120608140204.49f475e8@kryten>
Anton Blanchard <anton@samba.org> wrote:
>
>Hi,
>
>> Breaks the cell code with:
>>
>> arch/powerpc/platforms/cell/iommu.c:521:15: error: 'struct
>> iommu_table' has no member named 'it_hint'
>
>Yuck, I'll spin a fix. There's no need for the code to bump the hint.
OK, I can fix it up.
Cheers
--
Sent from my Android phone with K-9 Mail. Please excuse my brevity.
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox