* [PATCH] powerpc/fsl: 85xx: add cache-sram support
From: harninder.rai @ 2010-10-12 10:25 UTC (permalink / raw)
To: linuxppc-dev; +Cc: Harninder Rai
From: Harninder Rai <harninder.rai@freescale.com>
It adds cache-sram support in P1/P2 QorIQ platforms as under:
* A small abstraction over powerpc's remote heap allocator
* Exports mpc85xx_cache_sram_alloc()/free() APIs
* Supports only one contiguous SRAM window
* Drivers can do the following in Kconfig to use these APIs
"select FSL_85XX_CACHE_SRAM if MPC85xx"
* Required SRAM size and the offset where SRAM should be mapped must be
provided at kernel command line as
cache-sram-size=<value>
cache-sram-offset=<offset>
Signed-off-by: Harninder Rai <harninder.rai@freescale.com>
---
arch/powerpc/include/asm/fsl_85xx_cache_sram.h | 48 +++++
arch/powerpc/sysdev/Makefile | 1 +
arch/powerpc/sysdev/fsl_85xx_cache_ctlr.h | 101 ++++++++++
arch/powerpc/sysdev/fsl_85xx_cache_sram.c | 155 +++++++++++++++
arch/powerpc/sysdev/fsl_85xx_l2ctlr.c | 247 ++++++++++++++++++++++++
5 files changed, 552 insertions(+), 0 deletions(-)
create mode 100644 arch/powerpc/include/asm/fsl_85xx_cache_sram.h
create mode 100644 arch/powerpc/sysdev/fsl_85xx_cache_ctlr.h
create mode 100644 arch/powerpc/sysdev/fsl_85xx_cache_sram.c
create mode 100644 arch/powerpc/sysdev/fsl_85xx_l2ctlr.c
diff --git a/arch/powerpc/include/asm/fsl_85xx_cache_sram.h b/arch/powerpc/include/asm/fsl_85xx_cache_sram.h
new file mode 100644
index 0000000..2af2bdc
--- /dev/null
+++ b/arch/powerpc/include/asm/fsl_85xx_cache_sram.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright 2009 Freescale Semiconductor, Inc.
+ *
+ * Cache SRAM handling for QorIQ platform
+ *
+ * Author: Vivek Mahajan <vivek.mahajan@freescale.com>
+
+ * This file is derived from the original work done
+ * by Sylvain Munaut for the Bestcomm SRAM allocator.
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef __ASM_POWERPC_FSL_85XX_CACHE_SRAM_H__
+#define __ASM_POWERPC_FSL_85XX_CACHE_SRAM_H__
+
+#include <asm/rheap.h>
+#include <linux/spinlock.h>
+
+/*
+ * Cache-SRAM
+ */
+
+struct mpc85xx_cache_sram {
+ phys_addr_t base_phys;
+ void *base_virt;
+ unsigned int size;
+ rh_info_t *rh;
+ spinlock_t lock;
+};
+
+extern void mpc85xx_cache_sram_free(void *ptr);
+extern void *mpc85xx_cache_sram_alloc(unsigned int size,
+ phys_addr_t *phys, unsigned int align);
+
+#endif /* __AMS_POWERPC_FSL_85XX_CACHE_SRAM_H__ */
diff --git a/arch/powerpc/sysdev/Makefile b/arch/powerpc/sysdev/Makefile
index 5642924..fb60eb1 100644
--- a/arch/powerpc/sysdev/Makefile
+++ b/arch/powerpc/sysdev/Makefile
@@ -20,6 +20,7 @@ obj-$(CONFIG_FSL_PMC) += fsl_pmc.o
obj-$(CONFIG_FSL_LBC) += fsl_lbc.o
obj-$(CONFIG_FSL_GTM) += fsl_gtm.o
obj-$(CONFIG_MPC8xxx_GPIO) += mpc8xxx_gpio.o
+obj-$(CONFIG_FSL_85XX_CACHE_SRAM) += fsl_85xx_l2ctlr.o fsl_85xx_cache_sram.o
obj-$(CONFIG_SIMPLE_GPIO) += simple_gpio.o
obj-$(CONFIG_RAPIDIO) += fsl_rio.o
obj-$(CONFIG_TSI108_BRIDGE) += tsi108_pci.o tsi108_dev.o
diff --git a/arch/powerpc/sysdev/fsl_85xx_cache_ctlr.h b/arch/powerpc/sysdev/fsl_85xx_cache_ctlr.h
new file mode 100644
index 0000000..62f296e
--- /dev/null
+++ b/arch/powerpc/sysdev/fsl_85xx_cache_ctlr.h
@@ -0,0 +1,101 @@
+/*
+ * Copyright 2009-2010 Freescale Semiconductor, Inc
+ *
+ * QorIQ based Cache Controller Memory Mapped Registers
+ *
+ * Author: Vivek Mahajan <vivek.mahajan@freescale.com>
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef __FSL_85XX_CACHE_CTLR_H__
+#define __FSL_85XX_CACHE_CTLR_H__
+
+#define L2CR_L2FI 0x40000000 /* L2 flash invalidate */
+#define L2CR_L2IO 0x00200000 /* L2 instruction only */
+#define L2CR_SRAM_ZERO 0x00000000 /* L2SRAM zero size */
+#define L2CR_SRAM_FULL 0x00010000 /* L2SRAM full size */
+#define L2CR_SRAM_HALF 0x00020000 /* L2SRAM half size */
+#define L2CR_SRAM_TWO_HALFS 0x00030000 /* L2SRAM two half sizes */
+#define L2CR_SRAM_QUART 0x00040000 /* L2SRAM one quarter size */
+#define L2CR_SRAM_TWO_QUARTS 0x00050000 /* L2SRAM two quarter size */
+#define L2CR_SRAM_EIGHTH 0x00060000 /* L2SRAM one eighth size */
+#define L2CR_SRAM_TWO_EIGHTH 0x00070000 /* L2SRAM two eighth size */
+
+#define L2SRAM_OPTIMAL_SZ_SHIFT 0x00000003 /* Optimum size for L2SRAM */
+
+#define L2SRAM_BAR_MSK_LO18 0xFFFFC000 /* Lower 18 bits */
+#define L2SRAM_BARE_MSK_HI4 0x0000000F /* Upper 4 bits */
+
+enum cache_sram_lock_ways {
+ LOCK_WAYS_ZERO,
+ LOCK_WAYS_EIGHTH,
+ LOCK_WAYS_TWO_EIGHTH,
+ LOCK_WAYS_HALF = 4,
+ LOCK_WAYS_FULL = 8,
+};
+
+struct mpc85xx_l2ctlr {
+ u32 ctl; /* 0x000 - L2 control */
+ u8 res1[0xC];
+ u32 ewar0; /* 0x010 - External write address 0 */
+ u32 ewarea0; /* 0x014 - External write address extended 0 */
+ u32 ewcr0; /* 0x018 - External write ctrl */
+ u8 res2[4];
+ u32 ewar1; /* 0x020 - External write address 1 */
+ u32 ewarea1; /* 0x024 - External write address extended 1 */
+ u32 ewcr1; /* 0x028 - External write ctrl 1 */
+ u8 res3[4];
+ u32 ewar2; /* 0x030 - External write address 2 */
+ u32 ewarea2; /* 0x034 - External write address extended 2 */
+ u32 ewcr2; /* 0x038 - External write ctrl 2 */
+ u8 res4[4];
+ u32 ewar3; /* 0x040 - External write address 3 */
+ u32 ewarea3; /* 0x044 - External write address extended 3 */
+ u32 ewcr3; /* 0x048 - External write ctrl 3 */
+ u8 res5[0xB4];
+ u32 srbar0; /* 0x100 - SRAM base address 0 */
+ u32 srbarea0; /* 0x104 - SRAM base addr reg ext address 0 */
+ u32 srbar1; /* 0x108 - SRAM base address 1 */
+ u32 srbarea1; /* 0x10C - SRAM base addr reg ext address 1 */
+ u8 res6[0xCF0];
+ u32 errinjhi; /* 0xE00 - Error injection mask high */
+ u32 errinjlo; /* 0xE04 - Error injection mask low */
+ u32 errinjctl; /* 0xE08 - Error injection tag/ecc control */
+ u8 res7[0x14];
+ u32 captdatahi; /* 0xE20 - Error data high capture */
+ u32 captdatalo; /* 0xE24 - Error data low capture */
+ u32 captecc; /* 0xE28 - Error syndrome */
+ u8 res8[0x14];
+ u32 errdet; /* 0xE40 - Error detect */
+ u32 errdis; /* 0xE44 - Error disable */
+ u32 errinten; /* 0xE48 - Error interrupt enable */
+ u32 errattr; /* 0xE4c - Error attribute capture */
+ u32 erradrrl; /* 0xE50 - Error address capture low */
+ u32 erradrrh; /* 0xE54 - Error address capture high */
+ u32 errctl; /* 0xE58 - Error control */
+ u8 res9[0x1A4];
+};
+
+struct sram_parameters {
+ unsigned int sram_size;
+ uint64_t sram_offset;
+};
+
+extern int instantiate_cache_sram(struct platform_device *dev,
+ struct sram_parameters sram_params, bool amp);
+extern void remove_cache_sram(struct platform_device *dev);
+
+#endif /* __FSL_85XX_CACHE_CTLR_H__ */
diff --git a/arch/powerpc/sysdev/fsl_85xx_cache_sram.c b/arch/powerpc/sysdev/fsl_85xx_cache_sram.c
new file mode 100644
index 0000000..685c4de
--- /dev/null
+++ b/arch/powerpc/sysdev/fsl_85xx_cache_sram.c
@@ -0,0 +1,155 @@
+/*
+ * Copyright 2009-2010 Freescale Semiconductor, Inc.
+ *
+ * Simple memory allocator abstraction for QorIQ (P1/P2) based Cache-SRAM
+ *
+ * Author: Vivek Mahajan <vivek.mahajan@freescale.com>
+ *
+ * This file is derived from the original work done
+ * by Sylvain Munaut for the Bestcomm SRAM allocator.
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/err.h>
+#include <linux/of_platform.h>
+#include <asm/pgtable.h>
+#include <asm/fsl_85xx_cache_sram.h>
+
+#include "fsl_85xx_cache_ctlr.h"
+
+struct mpc85xx_cache_sram *cache_sram;
+
+void *mpc85xx_cache_sram_alloc(unsigned int size,
+ phys_addr_t *phys, unsigned int align)
+{
+ unsigned long offset;
+ unsigned long flags;
+
+ if (unlikely(cache_sram == NULL))
+ return NULL;
+
+ if (!size || (size > cache_sram->size) || (align > cache_sram->size)) {
+ pr_err("%s(): size(=%x) or align(=%x) zero or too big\n",
+ __func__, size, align);
+ return NULL;
+ }
+
+ if ((align & (align - 1)) || align <= 1) {
+ pr_err("%s(): align(=%x) must be power of two and >1\n",
+ __func__, align);
+ return NULL;
+ }
+
+ spin_lock_irqsave(&cache_sram->lock, flags);
+ offset = rh_alloc_align(cache_sram->rh, size, align, NULL);
+ spin_unlock_irqrestore(&cache_sram->lock, flags);
+
+ if (IS_ERR_VALUE(offset))
+ return NULL;
+
+ *phys = cache_sram->base_phys + offset;
+
+ return (unsigned char *)cache_sram->base_virt + offset;
+}
+EXPORT_SYMBOL(mpc85xx_cache_sram_alloc);
+
+void mpc85xx_cache_sram_free(void *ptr)
+{
+ unsigned long flags;
+ BUG_ON(!ptr);
+
+ spin_lock_irqsave(&cache_sram->lock, flags);
+ rh_free(cache_sram->rh, ptr - cache_sram->base_virt);
+ spin_unlock_irqrestore(&cache_sram->lock, flags);
+}
+EXPORT_SYMBOL(mpc85xx_cache_sram_free);
+
+int __init instantiate_cache_sram(struct platform_device *dev,
+ struct sram_parameters sram_params, bool amp)
+{
+ if (cache_sram) {
+ dev_err(&dev->dev, "Already initialized cache-sram\n");
+ return -EBUSY;
+ }
+
+ cache_sram = kzalloc(sizeof(struct mpc85xx_cache_sram), GFP_KERNEL);
+ if (!cache_sram) {
+ dev_err(&dev->dev, "Out of memory for cache_sram structure\n");
+ return -ENOMEM;
+ }
+
+ cache_sram->base_phys = sram_params.sram_offset;
+ cache_sram->size = sram_params.sram_size;
+
+ if (amp) {
+ cache_sram->size /= 2;
+ if (mfspr(SPRN_PIR))
+ cache_sram->base_phys += cache_sram->size;
+ }
+
+ if (!request_mem_region(cache_sram->base_phys, cache_sram->size,
+ "fsl_85xx_cache_sram")) {
+ dev_err(&dev->dev, "%s: request memory failed\n",
+ dev->dev.of_node->full_name);
+ kfree(cache_sram);
+ return -ENXIO;
+ }
+
+ cache_sram->base_virt = ioremap_flags(cache_sram->base_phys,
+ cache_sram->size, _PAGE_COHERENT | PAGE_KERNEL);
+ if (!cache_sram->base_virt) {
+ dev_err(&dev->dev, "%s: ioremap_flags failed\n",
+ dev->dev.of_node->full_name);
+ release_mem_region(cache_sram->base_phys, cache_sram->size);
+ kfree(cache_sram);
+ return -ENOMEM;
+ }
+
+ cache_sram->rh = rh_create(sizeof(unsigned int));
+ if (IS_ERR(cache_sram->rh)) {
+ dev_err(&dev->dev, "%s: Unable to create remote heap\n",
+ dev->dev.of_node->full_name);
+ iounmap(cache_sram->base_virt);
+ release_mem_region(cache_sram->base_phys, cache_sram->size);
+ kfree(cache_sram);
+ return PTR_ERR(cache_sram->rh);
+ }
+
+ rh_attach_region(cache_sram->rh, 0, cache_sram->size);
+ spin_lock_init(&cache_sram->lock);
+
+ dev_info(&dev->dev, "[base:0x%llx, size:0x%x] configured and loaded\n",
+ (unsigned long long)cache_sram->base_phys, cache_sram->size);
+ return 0;
+}
+
+void remove_cache_sram(struct platform_device *dev)
+{
+ BUG_ON(!cache_sram);
+
+ rh_detach_region(cache_sram->rh, 0, cache_sram->size);
+ rh_destroy(cache_sram->rh);
+
+ iounmap(cache_sram->base_virt);
+ release_mem_region(cache_sram->base_phys, cache_sram->size);
+
+ kfree(cache_sram);
+ cache_sram = NULL;
+
+ dev_info(&dev->dev, "MPC85xx Cache-SRAM driver unloaded\n");
+}
diff --git a/arch/powerpc/sysdev/fsl_85xx_l2ctlr.c b/arch/powerpc/sysdev/fsl_85xx_l2ctlr.c
new file mode 100644
index 0000000..771c624
--- /dev/null
+++ b/arch/powerpc/sysdev/fsl_85xx_l2ctlr.c
@@ -0,0 +1,247 @@
+/*
+ * Copyright 2009-2010 Freescale Semiconductor, Inc.
+ *
+ * QorIQ (P1/P2) L2 controller init for Cache-SRAM instantiation
+ *
+ * Author: Vivek Mahajan <vivek.mahajan@freescale.com>
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/kernel.h>
+#include <linux/of_platform.h>
+#include <asm/io.h>
+
+#include "fsl_85xx_cache_ctlr.h"
+
+static char *sram_size;
+static char *sram_offset;
+struct mpc85xx_l2ctlr __iomem *l2ctlr;
+
+static long get_cache_sram_size(void)
+{
+ unsigned long val;
+
+ if (!sram_size || (strict_strtoul(sram_size, 0, &val) < 0))
+ return -EINVAL;
+
+ return val;
+}
+
+static long get_cache_sram_offset(void)
+{
+ unsigned long val;
+
+ if (!sram_offset || (strict_strtoul(sram_offset, 0, &val) < 0))
+ return -EINVAL;
+
+ return val;
+}
+
+static int __init get_size_from_cmdline(char *str)
+{
+ if (!str)
+ return 0;
+
+ sram_size = str;
+ return 1;
+}
+
+static int __init get_offset_from_cmdline(char *str)
+{
+ if (!str)
+ return 0;
+
+ sram_offset = str;
+ return 1;
+}
+
+__setup("cache-sram-size=", get_size_from_cmdline);
+__setup("cache-sram-offset=", get_offset_from_cmdline);
+
+static int __devinit mpc85xx_l2ctlr_of_probe(struct platform_device *dev,
+ const struct of_device_id *match)
+{
+ long rval;
+ unsigned int rem;
+ unsigned char ways;
+ const unsigned int *prop;
+ unsigned int l2cache_size;
+ struct device_node *np;
+ int i = 0;
+ bool amp = 0;
+ struct sram_parameters sram_params;
+ static char *compatible_list[] = {
+ "fsl,MPC85XXRDB-CAMP",
+ "fsl,P2020DS-CAMP",
+ NULL
+ };
+
+ if (!dev->dev.of_node) {
+ dev_err(&dev->dev, "Device's OF-node is NULL\n");
+ return -EINVAL;
+ }
+
+ prop = of_get_property(dev->dev.of_node, "cache-size", NULL);
+ if (!prop) {
+ dev_err(&dev->dev, "Missing L2 cache-size\n");
+ return -EINVAL;
+ }
+ l2cache_size = *prop;
+
+ sram_params.sram_size = get_cache_sram_size();
+ if (sram_params.sram_size <= 0) {
+ dev_err(&dev->dev,
+ "Entire L2 as cache, Aborting Cache-SRAM stuff\n");
+ return -EINVAL;
+ }
+
+ sram_params.sram_offset = get_cache_sram_offset();
+ if (sram_params.sram_offset <= 0) {
+ dev_err(&dev->dev,
+ "Entire L2 as cache, provide a valid sram offset\n");
+ return -EINVAL;
+ }
+
+
+ rem = l2cache_size % sram_params.sram_size;
+ ways = LOCK_WAYS_FULL * sram_params.sram_size / l2cache_size;
+ if (rem || (ways & (ways - 1))) {
+ dev_err(&dev->dev, "Illegal cache-sram-size in command line\n");
+ return -EINVAL;
+ }
+
+ l2ctlr = of_iomap(dev->dev.of_node, 0);
+ if (!l2ctlr) {
+ dev_err(&dev->dev, "Can't map L2 controller\n");
+ return -EINVAL;
+ }
+
+ /*
+ * Write bits[0-17] to srbar0
+ */
+ out_be32(&l2ctlr->srbar0,
+ sram_params.sram_offset & L2SRAM_BAR_MSK_LO18);
+
+ /*
+ * Write bits[18-21] to srbare0
+ */
+#ifdef CONFIG_PHYS_64BIT
+ out_be32(&l2ctlr->srbarea0,
+ (sram_params.sram_offset >> 32) & L2SRAM_BARE_MSK_HI4);
+#endif
+
+ clrsetbits_be32(&l2ctlr->ctl, L2CR_L2E, L2CR_L2FI);
+
+ switch (ways) {
+ case LOCK_WAYS_EIGHTH:
+ setbits32(&l2ctlr->ctl,
+ L2CR_L2E | L2CR_L2FI | L2CR_SRAM_EIGHTH);
+ break;
+
+ case LOCK_WAYS_TWO_EIGHTH:
+ setbits32(&l2ctlr->ctl,
+ L2CR_L2E | L2CR_L2FI | L2CR_SRAM_QUART);
+ break;
+
+ case LOCK_WAYS_HALF:
+ setbits32(&l2ctlr->ctl,
+ L2CR_L2E | L2CR_L2FI | L2CR_SRAM_HALF);
+ break;
+
+ case LOCK_WAYS_FULL:
+ default:
+ setbits32(&l2ctlr->ctl,
+ L2CR_L2E | L2CR_L2FI | L2CR_SRAM_FULL);
+ break;
+ }
+ eieio();
+
+ for (i = 0; compatible_list[i] != NULL; i++) {
+ np = of_find_compatible_node(NULL, NULL, compatible_list[i]);
+ if (np) {
+ amp = 1;
+ break;
+ }
+ }
+
+ rval = instantiate_cache_sram(dev, sram_params, amp);
+ if (rval < 0) {
+ dev_err(&dev->dev, "Can't instantiate Cache-SRAM\n");
+ iounmap(l2ctlr);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int __devexit mpc85xx_l2ctlr_of_remove(struct platform_device *dev)
+{
+ BUG_ON(!l2ctlr);
+
+ iounmap(l2ctlr);
+ remove_cache_sram(dev);
+ dev_info(&dev->dev, "MPC85xx L2 controller unloaded\n");
+
+ return 0;
+}
+
+static struct of_device_id mpc85xx_l2ctlr_of_match[] = {
+ {
+ .compatible = "fsl,p2020-l2-cache-controller",
+ },
+ {
+ .compatible = "fsl,p2010-l2-cache-controller",
+ },
+ {
+ .compatible = "fsl,p1020-l2-cache-controller",
+ },
+ {
+ .compatible = "fsl,p1011-l2-cache-controller",
+ },
+ {
+ .compatible = "fsl,p1013-l2-cache-controller",
+ },
+ {
+ .compatible = "fsl,p1022-l2-cache-controller",
+ },
+ {},
+};
+
+static struct of_platform_driver mpc85xx_l2ctlr_of_platform_driver = {
+ .driver = {
+ .name = "fsl-l2ctlr",
+ .owner = THIS_MODULE,
+ .of_match_table = mpc85xx_l2ctlr_of_match,
+ },
+ .probe = mpc85xx_l2ctlr_of_probe,
+ .remove = __devexit_p(mpc85xx_l2ctlr_of_remove),
+};
+
+static __init int mpc85xx_l2ctlr_of_init(void)
+{
+ return of_register_platform_driver(&mpc85xx_l2ctlr_of_platform_driver);
+}
+
+static void __exit mpc85xx_l2ctlr_of_exit(void)
+{
+ of_unregister_platform_driver(&mpc85xx_l2ctlr_of_platform_driver);
+}
+
+subsys_initcall(mpc85xx_l2ctlr_of_init);
+module_exit(mpc85xx_l2ctlr_of_exit);
+
+MODULE_DESCRIPTION("Freescale MPC85xx L2 controller init");
+MODULE_LICENSE("GPL v2");
--
1.5.5.6
^ permalink raw reply related
* [PATCH] add icswx support v2
From: Tseng-Hui (Frank) Lin @ 2010-10-12 3:45 UTC (permalink / raw)
To: linuxppc-dev
icswx is a PowerPC co-processor instruction to send data to a
co-processor. On Book-S processors the LPAR_ID and process ID (PID) of
the owning process are registered in the window context of the
co-processor at initial time. When the icswx instruction is executed,
the L2 generates a cop-reg transaction on PowerBus. The transaction has
no address and the processor does not perform an MMU access to
authenticate the transaction. The coprocessor compares the LPAR_ID and
the PID included in the transaction and the LPAR_ID and PID held in the
window context to determine if the process is authorized to generate the
transaction.
This patch adds icswx co-processor instruction support.
Signed-off-by: Sonny Rao <sonnyrao@linux.vnet.ibm.com>
Signed-off-by: Tseng-Hui (Frank) Lin <thlin@linux.vnet.ibm.com>
---
arch/powerpc/include/asm/mmu-hash64.h | 5 ++
arch/powerpc/include/asm/mmu_context.h | 6 ++
arch/powerpc/include/asm/reg.h | 12 ++++
arch/powerpc/include/asm/reg_booke.h | 3 -
arch/powerpc/mm/mmu_context_hash64.c | 105
++++++++++++++++++++++++++++++++
arch/powerpc/platforms/Kconfig.cputype | 16 +++++
6 files changed, 144 insertions(+), 3 deletions(-)
diff --git a/arch/powerpc/include/asm/mmu-hash64.h
b/arch/powerpc/include/asm/mmu-hash64.h
index acac35d..6c1ab90 100644
--- a/arch/powerpc/include/asm/mmu-hash64.h
+++ b/arch/powerpc/include/asm/mmu-hash64.h
@@ -423,6 +423,11 @@ typedef struct {
#ifdef CONFIG_PPC_SUBPAGE_PROT
struct subpage_prot_table spt;
#endif /* CONFIG_PPC_SUBPAGE_PROT */
+#ifdef CONFIG_ICSWX
+ unsigned long acop; /* mask of enabled coprocessor types */
+#define HASH64_MAX_PID (0xFFFF)
+ unsigned int acop_pid; /* pid value used with coprocessors */
+#endif /* CONFIG_ICSWX */
} mm_context_t;
diff --git a/arch/powerpc/include/asm/mmu_context.h
b/arch/powerpc/include/asm/mmu_context.h
index 81fb412..88118de 100644
--- a/arch/powerpc/include/asm/mmu_context.h
+++ b/arch/powerpc/include/asm/mmu_context.h
@@ -80,6 +80,12 @@ static inline void switch_mm(struct mm_struct *prev,
struct mm_struct *next,
#define deactivate_mm(tsk,mm) do { } while (0)
+#ifdef CONFIG_ICSWX
+extern void switch_cop(struct mm_struct *next);
+extern int use_cop(unsigned long acop, struct mm_struct *mm);
+extern void drop_cop(unsigned long acop, struct mm_struct *mm);
+#endif /* CONFIG_ICSWX */
+
/*
* After we have set current->mm to a new value, this activates
* the context for the new mm so we see the new mappings.
diff --git a/arch/powerpc/include/asm/reg.h
b/arch/powerpc/include/asm/reg.h
index ff0005eec..9bbf178 100644
--- a/arch/powerpc/include/asm/reg.h
+++ b/arch/powerpc/include/asm/reg.h
@@ -170,8 +170,19 @@
#define SPEFSCR_FRMC 0x00000003 /* Embedded FP rounding mode control
*/
/* Special Purpose Registers (SPRNs)*/
+
+#ifdef CONFIG_40x
+#define SPRN_PID 0x3B1 /* Process ID */
+#else
+#define SPRN_PID 0x030 /* Process ID */
+#ifdef CONFIG_BOOKE
+#define SPRN_PID0 SPRN_PID/* Process ID Register 0 */
+#endif
+#endif
+
#define SPRN_CTR 0x009 /* Count Register */
#define SPRN_DSCR 0x11
+#define SPRN_ACOP 0x1F /* Available Coprocessor Register */
#define SPRN_CTRLF 0x088
#define SPRN_CTRLT 0x098
#define CTRL_CT 0xc0000000 /* current thread */
@@ -879,6 +890,7 @@
#define PV_POWER5 0x003A
#define PV_POWER5p 0x003B
#define PV_970FX 0x003C
+#define PV_POWER7 0x003F
#define PV_630 0x0040
#define PV_630p 0x0041
#define PV_970MP 0x0044
diff --git a/arch/powerpc/include/asm/reg_booke.h
b/arch/powerpc/include/asm/reg_booke.h
index 667a498..5b0c781 100644
--- a/arch/powerpc/include/asm/reg_booke.h
+++ b/arch/powerpc/include/asm/reg_booke.h
@@ -150,8 +150,6 @@
* or IBM 40x.
*/
#ifdef CONFIG_BOOKE
-#define SPRN_PID 0x030 /* Process ID */
-#define SPRN_PID0 SPRN_PID/* Process ID Register 0 */
#define SPRN_CSRR0 0x03A /* Critical Save and Restore Register 0 */
#define SPRN_CSRR1 0x03B /* Critical Save and Restore Register 1 */
#define SPRN_DEAR 0x03D /* Data Error Address Register */
@@ -168,7 +166,6 @@
#define SPRN_TCR 0x154 /* Timer Control Register */
#endif /* Book E */
#ifdef CONFIG_40x
-#define SPRN_PID 0x3B1 /* Process ID */
#define SPRN_DBCR1 0x3BD /* Debug Control Register 1 */
#define SPRN_ESR 0x3D4 /* Exception Syndrome Register */
#define SPRN_DEAR 0x3D5 /* Data Error Address Register */
diff --git a/arch/powerpc/mm/mmu_context_hash64.c
b/arch/powerpc/mm/mmu_context_hash64.c
index 2535828..8f432b6 100644
--- a/arch/powerpc/mm/mmu_context_hash64.c
+++ b/arch/powerpc/mm/mmu_context_hash64.c
@@ -18,6 +18,7 @@
#include <linux/mm.h>
#include <linux/spinlock.h>
#include <linux/idr.h>
+#include <linux/percpu.h>
#include <linux/module.h>
#include <linux/gfp.h>
@@ -26,6 +27,103 @@
static DEFINE_SPINLOCK(mmu_context_lock);
static DEFINE_IDA(mmu_context_ida);
+#ifdef CONFIG_ICSWX
+static DEFINE_SPINLOCK(mmu_context_acop_lock);
+static DEFINE_IDA(cop_ida);
+
+/* Lazy switch the ACOP register */
+static DEFINE_PER_CPU(unsigned long, acop_reg);
+
+void switch_cop(struct mm_struct *next)
+{
+ if (!__is_processor(PV_POWER7))
+ return;
+
+ mtspr(SPRN_PID, next->context.acop_pid);
+ if (next->context.acop_pid &&
+ __get_cpu_var(acop_reg) != next->context.acop) {
+ mtspr(SPRN_ACOP, next->context.acop);
+ __get_cpu_var(acop_reg) = next->context.acop;
+ }
+}
+EXPORT_SYMBOL(switch_cop);
+
+int use_cop(unsigned long acop, struct mm_struct *mm)
+{
+ int acop_pid;
+ int err;
+
+ if (!__is_processor(PV_POWER7))
+ return -ENOSYS;
+
+ if (!mm)
+ return -EINVAL;
+
+ if (!mm->context.acop_pid) {
+ if (!ida_pre_get(&cop_ida, GFP_KERNEL))
+ return -ENOMEM;
+again:
+ spin_lock(&mmu_context_acop_lock);
+ err = ida_get_new_above(&cop_ida, 1, &acop_pid);
+ spin_unlock(&mmu_context_acop_lock);
+
+ if (err == -EAGAIN)
+ goto again;
+ else if (err)
+ return err;
+
+ if (acop_pid > HASH64_MAX_PID) {
+ spin_lock(&mmu_context_acop_lock);
+ ida_remove(&cop_ida, acop_pid);
+ spin_unlock(&mmu_context_acop_lock);
+ return -EBUSY;
+ }
+ mm->context.acop_pid = acop_pid;
+ if (mm == current->active_mm)
+ mtspr(SPRN_PID, mm->context.acop_pid);
+ }
+ spin_lock(&mmu_context_acop_lock);
+ mm->context.acop |= acop;
+ spin_unlock(&mmu_context_acop_lock);
+
+ get_cpu_var(acop_reg) = mm->context.acop;
+ if (mm == current->active_mm)
+ mtspr(SPRN_ACOP, mm->context.acop);
+ put_cpu_var(acop_reg);
+
+ return mm->context.acop_pid;
+}
+EXPORT_SYMBOL(use_cop);
+
+void drop_cop(unsigned long acop, struct mm_struct *mm)
+{
+ if (!__is_processor(PV_POWER7))
+ return;
+
+ if (WARN_ON(!mm))
+ return;
+
+ spin_lock(&mmu_context_acop_lock);
+ mm->context.acop &= ~acop;
+ spin_unlock(&mmu_context_acop_lock);
+ if (!mm->context.acop) {
+ spin_lock(&mmu_context_acop_lock);
+ ida_remove(&cop_ida, mm->context.acop_pid);
+ spin_unlock(&mmu_context_acop_lock);
+ mm->context.acop_pid = 0;
+ if (mm == current->active_mm)
+ mtspr(SPRN_PID, mm->context.acop_pid);
+ } else {
+ get_cpu_var(acop_reg) = mm->context.acop;
+ if (mm == current->active_mm)
+ mtspr(SPRN_ACOP, mm->context.acop);
+ put_cpu_var(acop_reg);
+ }
+ mmput(mm);
+}
+EXPORT_SYMBOL(drop_cop);
+#endif /* CONFIG_ICSWX */
+
/*
* The proto-VSID space has 2^35 - 1 segments available for user
mappings.
* Each segment contains 2^28 bytes. Each context maps 2^44 bytes,
@@ -93,6 +191,13 @@ EXPORT_SYMBOL_GPL(__destroy_context);
void destroy_context(struct mm_struct *mm)
{
+#ifdef CONFIG_ICSWX
+ if (mm->context.acop_pid) {
+ spin_lock(&mmu_context_acop_lock);
+ ida_remove(&cop_ida, mm->context.acop_pid);
+ spin_unlock(&mmu_context_acop_lock);
+ }
+#endif /* CONFIG_ICSWX */
__destroy_context(mm->context.id);
subpage_prot_free(mm);
mm->context.id = NO_CONTEXT;
diff --git a/arch/powerpc/platforms/Kconfig.cputype
b/arch/powerpc/platforms/Kconfig.cputype
index d361f81..9674703 100644
--- a/arch/powerpc/platforms/Kconfig.cputype
+++ b/arch/powerpc/platforms/Kconfig.cputype
@@ -220,6 +220,22 @@ config VSX
If in doubt, say Y here.
+config ICSWX
+ bool "Support for PowerPC icswx co-processor instruction"
+ depends on POWER4
+ default n
+ ---help---
+
+ Enabling this option to turn on the PowerPC icswx co-processor
+ instruction support for POWER7 processors.
+ This option is only useful if you have a processor that supports
+ icswx co-processor instruction. It does not have any affect on
+ processors without icswx co-processor instruction.
+
+ This support slightly increases kernel memory usage.
+
+ Say N if you do not have a POWER7 processor and a PowerPC
co-processor.
+
config SPE
bool "SPE Support"
depends on E200 || (E500 && !PPC_E500MC)
^ permalink raw reply related
* Re: Questions on interrupt vector assignment on MPC8641D
From: tiejun.chen @ 2010-10-12 3:11 UTC (permalink / raw)
To: Scott Wood; +Cc: david.hagood, linuxppc-dev@lists.ozlabs.org
In-Reply-To: <20101011123006.5b489d19@udp111988uds.am.freescale.net>
Scott Wood wrote:
> On Mon, 11 Oct 2010 12:02:15 -0500
> <david.hagood@gmail.com> wrote:
>
>> Re-ordering your questions a bit:
>>
>>> What board are you using? What kernel?
>> One of 2 boards: Either an Embedded Planet or a Performance Tech uTCA
>> board based on the MPC8641D, running the 2.6.26 as supplied by EP.
>
> That's a very old kernel. Have you contacted EP support?
>
> You may be better off trying to migrate anything board-specific to the
> latest kernel, rather than do new development on the vendor kernel,
> especially if you're looking for community support, and definitely if
> you're trying to do something that could be merged upstream to help
> others.
>
> The MPC8641D itself is supported in mainline Linux.
>
>>> On Sat, 9 Oct 2010 10:52:49 -0500
>>> Documentation/powerpc/dts-bindings/fsl/mpic.txt
>> Not present in the version I have.
>
> We didn't have a time machine, so we were only able to add things to new
> releases, not old ones. :-)
>
> Should it have been documented from the start? Ideally, yes, and we're
> pickier now than we were then about insisting on bindings being
> documented before they're used. But nothing's perfect.
On the *latest* tree you can find more than your tree:
------
Documentation/powerpc/dts-bindings/fsl/msi-pic.txt
Documentation/powerpc/booting-without-of.txt
If you want to understand dts in detail you can refer to the file,
------
http://www.power.org/resources/downloads/Power_ePAPR_APPROVED_v1.0.pdf
>
>>> If it's not in the dts, add it. If for whatever reason that's not an
>>> option, you can use irq_create_mapping() as I mentioned in the previous
>>> e-mail.
>> And as I've said previously, I have no good info on HOW to add the nodes,
>> WHAT to add, or WHERE. You may as well be saying "Bargle the Narbog".
>
> There are no nodes to add with irq_create_mapping().
Sure.
>
> Just bargle the narbog.
>
>> And when I try to use irq_create_mapping() it seg faults, which doesn't
>> exactly help me get my interrupt hooked up.
>
> Well, I didn't know it was going to do that... Your usage of
> irq_create_mapping() seems fine, there's just something going wrong.
The 'NULL' host would be 'irq_default_host'. For OOPS you can check my another
email and hope its useful.
-Tiejun
> See my other reply about the number of MPIC interrupts.
^ permalink raw reply
* Re: PPC: Possible bug in prom_parse.c:of_irq_map_raw?
From: John Williams @ 2010-10-12 3:02 UTC (permalink / raw)
To: Grant Likely
Cc: linuxppc-dev, devicetree-discuss, Linux Kernel list, Michal Simek
In-Reply-To: <AANLkTi=dU4oYfqrBGYmSCmYf2cRsBX-Pf6A9X9N0YaZA@mail.gmail.com>
Hi Grant,
On Fri, Oct 8, 2010 at 4:34 AM, Grant Likely <grant.likely@secretlab.ca> wr=
ote:
> Reaching way back into the past....
Indeed
> John, did you ever solve your issue here? =A0Comments below.
The fix in our case was to explicitly add child nodes to the PCI
controller, with interrupt-parent and interrupts properties. The
product in question had a fixed set of devices on the PCI bus, so this
was not a problem.
So, it's not really resolved so much as avoided.
Other comments below:
>> Perhaps this is my misunderstanding, but I'm looking at the bit of
>> code in of_irq_map_raw() that iterates the interrupt-map DTS node,
>> which I am seeing to behave strangely when handling the interrupt-map
>> property on a PCI bridge node.
>>
>> Early in the function, we get the #address-cells value from the node -
>> in this case the PCI bridge, and store it in local var addrsize:
>>
>> =A0 =A0 =A0 =A0/* Look for this #address-cells. We have to implement the=
old linux
>> =A0 =A0 =A0 =A0 * trick of looking for the parent here as some device-tr=
ees rely on it
>> =A0 =A0 =A0 =A0 */
>> =A0 =A0 =A0 =A0old =3D of_node_get(ipar);
>> =A0 =A0 =A0 =A0do {
>> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0tmp =3D of_get_property(old, "#address-ce=
lls", NULL);
>> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0tnode =3D of_get_parent(old);
>> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0of_node_put(old);
>> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0old =3D tnode;
>> =A0 =A0 =A0 =A0} while(old && tmp =3D=3D NULL);
>> =A0 =A0 =A0 =A0of_node_put(old);
>> =A0 =A0 =A0 =A0old =3D NULL;
>> =A0 =A0 =A0 =A0addrsize =3D (tmp =3D=3D NULL) ? 2 : *tmp;
>>
>> =A0 =A0 =A0 =A0DBG(" -> addrsize=3D%d\n", addrsize);
>>
>>
>> Later, once we've found the interrupt-map and are iterating over it
>> attempting to match on PCI device addresses, there is this little
>> fragment:
>>
>> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0/* Get the interrupt pare=
nt */
>> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0if (of_irq_workarounds & =
OF_IMAP_NO_PHANDLE)
>> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0newpar =
=3D of_node_get(of_irq_dflt_pic);
>> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0else
>> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0newpar =
=3D
>> of_find_node_by_phandle((phandle)*imap);
>> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0imap++;
>> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0--imaplen;
>>
>> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0/* Check if not found */
>> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0if (newpar =3D=3D NULL) {
>> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0DBG(" -> =
imap parent not found !\n");
>> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0goto fail=
;
>> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0}
>>
>> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0/* Get #interrupt-cells a=
nd #address-cells of new
>> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 * parent
>> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 */
>> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0tmp =3D of_get_property(n=
ewpar, "#interrupt-cells", NULL);
>> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0if (tmp =3D=3D NULL) {
>> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0DBG(" -> =
parent lacks #interrupt-cells !\n");
>> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0goto fail=
;
>> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0}
>> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0newintsize =3D *tmp;
>> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0tmp =3D of_get_property(n=
ewpar, "#address-cells", NULL);
>> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0newaddrsize =3D (tmp =3D=
=3D NULL) ? 0 : *tmp;
>>
>> Finally, later in the loop we update addrsize=3Dnewaddrsize
>>
>> As I read this code, and the behaviour I'm seeing, is that if the
>> interrupt controller parent device doesn't have an #address-cells
>> entry, then this get_property will return fail, therefore setting
>> newaddrsize =A0to zero. =A0This then means that subsequent match attempt=
s
>> when iterating the interrupt-map always fail, because the match length
>> (addrsize) is 0.
>
> Correct. =A0The interrupt-map property contains the following fields:
>
> child-unit-address child-irq irq-controller irq-parent-unit-address paren=
t-irq
>
> In the *vast majority* of cases, the irq-parent-unit-address is a
> zero-length field because #address-cells isn't present on the
> interrupt controller parent. =A0So effectively interrupt-map becomes:
>
> child-unit-address child-irq irq-controller parent-irq
>
> See epapr 1.0 for a full discussion
>
>>
>> Maybe I'm missing something here, but shouldn't this last bit of code
>> instead be:
>>
>> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0tmp =3D of_get_property(n=
ewpar, "#address-cells", NULL);
>> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0newaddrsize =3D (tmp =3D=
=3D NULL) ? addrsize : *tmp;
>>
>> =A0^^^^^^^^^
>> ?
>>
>> In other words, if the parent node has an #address-cells value, then
>> use it, otherwise stick to the #address-cells value we picked up for
>> the actual node in question (ie the PCI bridge).
>
> No, because at this point we absolutely do want to know how big the
> parent #address-cells is, and if it is missing, we need to use 0. =A0If
> the child's addrsize continued to be used, then the interrupt-map
> parsing would get unaligned.
>
> The inner loop is over the entries in interrupt-map. =A0addrsize and
> intsize are only updated in the case where a match is found in the
> table. =A0If a match isn't found, then it should bail out to the 'fail'
> label.
>
>> The way this is manifesting itself in the system I'm looking at is
>> that only the PCI device matching the first entry in the PCI bridge
>> interrupt-map property is correctly matching. For PCI devices that
>> require more than one pass through the interrupt-map loop, addrsize
>> goes to zero and no further match is possible.
>
> Something sounds fishy. =A0If you're still having problems, can you
> enable #define DEBUG in drivers/of/irq.c and post the output?
OK, this may take me a lilttle while as the test system is in storage!
Thanks,
John
^ permalink raw reply
* Re: Questions on interrupt vector assignment on MPC8641D
From: tiejun.chen @ 2010-10-12 3:00 UTC (permalink / raw)
To: tiejun.chen; +Cc: Scott Wood, david.hagood, linuxppc-dev@lists.ozlabs.org
In-Reply-To: <4CB2DEFB.90204@windriver.com>
tiejun.chen wrote:
> david.hagood@gmail.com wrote:
>> OK, using 224 as the MPIC interrupt number, and attempting to map it via
>> irq_create_mapping(0,224) gives me a kernel seg fault:
>
> This should not be correct without initialing MSI for MPIC host. As I comment on
> another email, please refer to the file, arch/powerpc/sysdev/fsl_msi.c.
With Scott's comment I remember the NULL host would be always 'irq_default_host'
at last. The 'irq_default_host' should be your MPIC host so it should be fine.
>
> -Tiejun
>
>> Unable to handle kernel paging request for data at address 0x00000000
>> Faulting instruction address: 0xc0016540
>> Oops: Kernel access of bad area, sig: 11 [#1]
>> PREEMPT SMP NR_CPUS=2 EP8641A
>> Modules linked in: Endpoint_driver(+)
>> NIP: c0016540 LR: c0050b38 CTR: c00163b8
>> REGS: ef8c1ab0 TRAP: 0300 Not tainted (2.6.26.2-ep1.10)
>> MSR: 00001032 <ME,IR,DR> CR: 24024482 XER: 00000000
>> DAR: 00000000, DSISR: 40000000
>> TASK = eedec6a0[60] 'insmod' THREAD: ef8c0000 CPU: 1
>> GPR00: 00000000 ef8c1b60 eedec6a0 ffffffea 00000000 00000000 c035c17c
^
The return value, r3, should be -22, '-EINVAL'.
And refer to the call trace and the source codes
------
int mpic_set_irq_type(unsigned int virq, unsigned int flow_type)
{
struct mpic *mpic = mpic_from_irq(virq);
unsigned int src = mpic_irq_to_hw(virq);
struct irq_desc *desc = get_irq_desc(virq);
unsigned int vecpri, vold, vnew;
DBG("mpic: set_irq_type(mpic:@%p,virq:%d,src:0x%x,type:0x%x)\n",
mpic, virq, src, flow_type);
if (src >= mpic->irq_count)
return -EINVAL;
^
I think this OOPS may be from here.
You can enable DBG on this file, arch/powerpc/sysdev/mpic.c, to track 'src' and
'mpic->irq_count' on your old tree.
-Tiejun
>> 000000e0
>> GPR08: 00400000 00000000 c035c020 00000000 24024422 100a7264 00000000
>> 00000095
>> GPR16: 00000095 00000000 0000000d 00000124 f102fd98 00000000 c004a4fc
>> f102c000
>> GPR24: 0000001a f1038400 00000000 c031e610 fffffffa 00009032 c031e5e0
>> 000000e0
>> NIP [c0016540] mpic_set_irq_type+0x188/0x1c4
>> LR [c0050b38] set_irq_type+0x84/0xc8
>> Call Trace:
>> [ef8c1b60] [c0050b1c] set_irq_type+0x68/0xc8 (unreliable)
>> [ef8c1b80] [c001572c] mpic_host_map+0xec/0xf4
>> [ef8c1b90] [c00064a0] irq_setup_virq+0x60/0x98
>> [ef8c1bb0] [c00065dc] irq_create_mapping+0x104/0x114
>> [ef8c1bd0] [f1034798] Endpoint_device_ctor+0x258/0x3b8 [Endpoint_driver]
>>
>> Reading the source (since these calls don't seem to have any other
>> documentation), it *looks* like it ought to be valid to call
>> irq_create_mapping with a null irq_host *host - which is good, since I
>> can't see anything obvious that would give me some other irq_host (again,
>> since none of this seems to be documented anywhere).
>>
>> I am assuming the default host used by the system would be correct.
>>
>> However, then I get this fault.
>>
>>
>>
>> _______________________________________________
>> Linuxppc-dev mailing list
>> Linuxppc-dev@lists.ozlabs.org
>> https://lists.ozlabs.org/listinfo/linuxppc-dev
>>
>
> _______________________________________________
> Linuxppc-dev mailing list
> Linuxppc-dev@lists.ozlabs.org
> https://lists.ozlabs.org/listinfo/linuxppc-dev
>
^ permalink raw reply
* Re: Questions on interrupt vector assignment on MPC8641D
From: tiejun.chen @ 2010-10-12 1:39 UTC (permalink / raw)
To: Scott Wood; +Cc: david.hagood, linuxppc-dev@lists.ozlabs.org
In-Reply-To: <20101011105155.1b2f4611@udp111988uds.am.freescale.net>
Scott Wood wrote:
> On Mon, 11 Oct 2010 17:51:39 +0800
> "tiejun.chen" <tiejun.chen@windriver.com> wrote:
>
>> Maybe you can check the file, ppc4xx_pci.c since ppc4xx also can support EP as I
>> previously said. And sounds Scott will do something to support EP for Freescale
>> chip.
>
> What did I get signed up for? :-)
As far as I recalled you ever comment you will support EP when you replied to
David in the previous email. If no I may misunderstand something so sorry for
this :)
Tiejun
>
> -Scott
>
>
^ permalink raw reply
* Re: [RFC] [PATCH] allow low HZ values?
From: H. Peter Anvin @ 2010-10-11 22:47 UTC (permalink / raw)
To: Thomas Gleixner
Cc: Marcio Saito, Jiri Slaby, x86, linux-kernel, Tim Pepper,
Ingo Molnar, Paul Mackerras, John Stultz, Avantika Mathur,
linuxppc-dev
In-Reply-To: <alpine.LFD.2.00.1010120032060.2909@localhost6.localdomain6>
On 10/11/2010 03:33 PM, Thomas Gleixner wrote:
> On Tue, 12 Oct 2010, Benjamin Herrenschmidt wrote:
>
>> On Mon, 2010-10-11 at 13:11 -0700, Tim Pepper wrote:
>>> I'm not necessarily wanting to open up the age old question of "what is
>>> a good HZ", but we were doing some testing on timer tick overheads for
>>> HPC applications and this came up...
>>
>> Note that this is also very useful when working on CPU prototypes
>> implemented in FPGAs and running at something like 12Mhz :-)
>
> /me hands benh 0.5$ for a FPGA upgrade
That's often not possible if the CPU cannot be mapped onto a single FPGA
(either because the core is too large, multiple cores are tested, or
because there is debugging logic is included.) The interconnects slows
things down tremendously.
-hpa
^ permalink raw reply
* Re: [RFC] [PATCH] allow low HZ values?
From: Thomas Gleixner @ 2010-10-11 22:33 UTC (permalink / raw)
To: Benjamin Herrenschmidt
Cc: Marcio Saito, Jiri Slaby, John Stultz, x86, linux-kernel,
Tim Pepper, Ingo Molnar, Paul Mackerras, H. Peter Anvin,
Avantika Mathur, linuxppc-dev
In-Reply-To: <1286836212.5220.19.camel@pasglop>
On Tue, 12 Oct 2010, Benjamin Herrenschmidt wrote:
> On Mon, 2010-10-11 at 13:11 -0700, Tim Pepper wrote:
> > I'm not necessarily wanting to open up the age old question of "what is
> > a good HZ", but we were doing some testing on timer tick overheads for
> > HPC applications and this came up...
>
> Note that this is also very useful when working on CPU prototypes
> implemented in FPGAs and running at something like 12Mhz :-)
/me hands benh 0.5$ for a FPGA upgrade
^ permalink raw reply
* Re: [RFC] [PATCH] allow low HZ values?
From: Benjamin Herrenschmidt @ 2010-10-11 22:30 UTC (permalink / raw)
To: Tim Pepper
Cc: Marcio Saito, Jiri Slaby, John Stultz, x86, linux-kernel,
Ingo Molnar, Paul Mackerras, H. Peter Anvin, Thomas Gleixner,
linuxppc-dev, Avantika Mathur
In-Reply-To: <20101011201121.GA953@tpepper-t61p.dolavim.us>
On Mon, 2010-10-11 at 13:11 -0700, Tim Pepper wrote:
> I'm not necessarily wanting to open up the age old question of "what is
> a good HZ", but we were doing some testing on timer tick overheads for
> HPC applications and this came up...
Note that this is also very useful when working on CPU prototypes
implemented in FPGAs and running at something like 12Mhz :-)
Cheers,
Ben.
> Below is a minimal hack at enabling lower HZ values. The kernel builds
> and boots for me on x86_64 (simple laptop and kvm configs) and ppc64
> (misc. IBM System p) with each of the added HZ options.
>
> There's explicit code checking HZ down to 12, but HZ<100 wasn't a config
> option. We collected some data at 10, 12 and 25. There'd been some
> question of whether 10 would even work or not but it looks fine in the
> relatively minimal testing we did. We tried 12 since the code seemed
> to allow for it. And 25 as a "safe" lower value. The only difference
> observed under load (ie: no no idle HZ in play) was the expected timer
> tick happening less often. There was definitely surprise that nothing
> else seemed to break anywhere, especially at 10.
>
> Do people feel it is reasonable to have Kconfig bits to allow some lower
> HZ values?
>
> If so, then there's the question of what breaks. It's reasonable to
> think there are other going to be subtleties buried in code around
> assumptions on the likely range of HZ:
>
> - I'm not sure that what I did in inet_timewait_sock.h and jiffies.h is
> reasonable.
> - arch/x86/kernel/i8253.c throws a warning at line 43 (v2.6.36-rc7):
> warning: large integer implicitly truncated to unsigned type
> - drivers/char/cyclades.c's cy_ioctl() warns:
> drivers/char/cyclades.c:2761: warning: division by zero
> - drivers, drivers, drivers across all the arch's could use sanity checking
>
^ permalink raw reply
* Re: [RFC] [PATCH] allow low HZ values?
From: Tim Pepper @ 2010-10-11 21:11 UTC (permalink / raw)
To: Thomas Gleixner
Cc: Marcio Saito, John Stultz, Jiri Slaby, Peter Zijlstra, x86, LKML,
Tim Pepper, Frederic Weisbecker, Ingo Molnar, Paul Mackerras,
H. Peter Anvin, Avantika Mathur, linuxppc-dev
In-Reply-To: <alpine.LFD.2.00.1010112227190.2909@localhost6.localdomain6>
On Mon 11 Oct at 22:32:06 +0200 tglx@linutronix.de said:
> On Mon, 11 Oct 2010, Tim Pepper wrote:
>
> > I'm not necessarily wanting to open up the age old question of "what is
> > a good HZ", but we were doing some testing on timer tick overheads for
> > HPC applications and this came up...
>
> Yeah. This comes always up when the timer tick overhead on HPC is
> tested. And this patch is again the fundamentally wrong answer.
Yep. Long term no hz is definitely the goal. I'm not sufficiently
connected to the -rt space I guess to have followed that there's somebody
again looking in that direction. The rfc patch was mostly just a minimal
is there anything simple we can do in the meantime exercise.
> We have told HPC folks for years that we need a kind of "NOHZ" mode
> for HPC where we can transparently switch off the tick when only one
> user space bound thread is active and switch back to normal once this
> thing terminates or goes into the kernel via a syscall.
I'd not heard of this in between NOHZ-y idea...sounds promising.
We'd talked about different non-idle no hz approaches in the past year
or so, some of which were on the veeery complicated side of the spectrum.
> Sigh, nothing
> happened ever except for repeating the same crap patches over and
> over.
I'll check out what Frederic is doing. Thanks for the pointer and
apologies for the noise.
--
Tim Pepper <lnxninja@linux.vnet.ibm.com>
IBM Linux Technology Center
^ permalink raw reply
* Re: PROBLEM: memory corrupting bug, bisected to 6dda9d55
From: Andrew Morton @ 2010-10-11 21:00 UTC (permalink / raw)
To: Mel Gorman
Cc: linuxppc-dev, linux-kernel, linux-mm, pacman, KOSAKI Motohiro,
Christoph Lameter, Yinghai Lu
In-Reply-To: <20101011143022.GD30667@csn.ul.ie>
(cc linuxppc-dev@lists.ozlabs.org)
On Mon, 11 Oct 2010 15:30:22 +0100
Mel Gorman <mel@csn.ul.ie> wrote:
> On Sat, Oct 09, 2010 at 04:57:18AM -0500, pacman@kosh.dhis.org wrote:
> > (What a big Cc: list... scripts/get_maintainer.pl made me do it.)
> >
> > This will be a long story with a weak conclusion, sorry about that, but it's
> > been a long bug-hunt.
> >
> > With recent kernels I've seen a bug that appears to corrupt random 4-byte
> > chunks of memory. It's not easy to reproduce. It seems to happen only once
> > per boot, pretty quickly after userspace has gotten started, and sometimes it
> > doesn't happen at all.
> >
>
> A corruption of 4 bytes could be consistent with a pointer value being
> written to an incorrect location.
It's corruption of user memory, which is unusual. I'd be wondering if
there was a pre-existing bug which 6dda9d55bf545013597 has exposed -
previously the corruption was hitting something harmless. Something
like a missed CPU cache writeback or invalidate operation.
How sensitive/vulnerable is PPC32 to such things?
^ permalink raw reply
* Re: [RFC] [PATCH] allow low HZ values?
From: Thomas Gleixner @ 2010-10-11 20:32 UTC (permalink / raw)
To: Tim Pepper
Cc: Marcio Saito, John Stultz, Jiri Slaby, Peter Zijlstra, x86, LKML,
Frederic Weisbecker, Ingo Molnar, Paul Mackerras, H. Peter Anvin,
Avantika Mathur, linuxppc-dev
In-Reply-To: <20101011201121.GA953@tpepper-t61p.dolavim.us>
On Mon, 11 Oct 2010, Tim Pepper wrote:
> I'm not necessarily wanting to open up the age old question of "what is
> a good HZ", but we were doing some testing on timer tick overheads for
> HPC applications and this came up...
Yeah. This comes always up when the timer tick overhead on HPC is
tested. And this patch is again the fundamentally wrong answer.
We have told HPC folks for years that we need a kind of "NOHZ" mode
for HPC where we can transparently switch off the tick when only one
user space bound thread is active and switch back to normal once this
thing terminates or goes into the kernel via a syscall. Sigh, nothing
happened ever except for repeating the same crap patches over and
over.
FYI, Frederic is working on that right now. He will talk about it at
the plumbers RT microconf, so you might catch him there.
Thanks,
tglx
^ permalink raw reply
* [RFC] [PATCH] allow low HZ values?
From: Tim Pepper @ 2010-10-11 20:11 UTC (permalink / raw)
To: linux-kernel
Cc: Marcio Saito, John Stultz, Jiri Slaby, x86, Ingo Molnar,
Paul Mackerras, H. Peter Anvin, Thomas Gleixner, linuxppc-dev,
Avantika Mathur
I'm not necessarily wanting to open up the age old question of "what is
a good HZ", but we were doing some testing on timer tick overheads for
HPC applications and this came up...
Below is a minimal hack at enabling lower HZ values. The kernel builds
and boots for me on x86_64 (simple laptop and kvm configs) and ppc64
(misc. IBM System p) with each of the added HZ options.
There's explicit code checking HZ down to 12, but HZ<100 wasn't a config
option. We collected some data at 10, 12 and 25. There'd been some
question of whether 10 would even work or not but it looks fine in the
relatively minimal testing we did. We tried 12 since the code seemed
to allow for it. And 25 as a "safe" lower value. The only difference
observed under load (ie: no no idle HZ in play) was the expected timer
tick happening less often. There was definitely surprise that nothing
else seemed to break anywhere, especially at 10.
Do people feel it is reasonable to have Kconfig bits to allow some lower
HZ values?
If so, then there's the question of what breaks. It's reasonable to
think there are other going to be subtleties buried in code around
assumptions on the likely range of HZ:
- I'm not sure that what I did in inet_timewait_sock.h and jiffies.h is
reasonable.
- arch/x86/kernel/i8253.c throws a warning at line 43 (v2.6.36-rc7):
warning: large integer implicitly truncated to unsigned type
- drivers/char/cyclades.c's cy_ioctl() warns:
drivers/char/cyclades.c:2761: warning: division by zero
- drivers, drivers, drivers across all the arch's could use sanity checking
--
Tim Pepper <lnxninja@linux.vnet.ibm.com>
IBM Linux Technology Center
Not-Signed-off-by: Tim Pepper <lnxninja@us.ibm.com>
diff --git a/include/linux/jiffies.h b/include/linux/jiffies.h
index 6811f4b..8c225b2 100644
--- a/include/linux/jiffies.h
+++ b/include/linux/jiffies.h
@@ -15,7 +15,9 @@
* OSF/1 kernel. The SHIFT_HZ define expresses the same value as the
* nearest power of two in order to avoid hardware multiply operations.
*/
-#if HZ >= 12 && HZ < 24
+#if HZ < 12
+# define SHIFT_HZ 3
+#elif HZ >= 12 && HZ < 24
# define SHIFT_HZ 4
#elif HZ >= 24 && HZ < 48
# define SHIFT_HZ 5
diff --git a/include/net/inet_timewait_sock.h b/include/net/inet_timewait_sock.h
index a066fdd..1aba305 100644
--- a/include/net/inet_timewait_sock.h
+++ b/include/net/inet_timewait_sock.h
@@ -39,8 +39,9 @@ struct inet_hashinfo;
* If time > 4sec, it is "slow" path, no recycling is required,
* so that we select tick to get range about 4 seconds.
*/
-#if HZ <= 16 || HZ > 4096
-# error Unsupported: HZ <= 16 or HZ > 4096
+/* HACK HACK */
+#if HZ > 4096
+# error Unsupported: HZ > 4096
#elif HZ <= 32
# define INET_TWDR_RECYCLE_TICK (5 + 2 - INET_TWDR_RECYCLE_SLOTS_LOG)
#elif HZ <= 64
diff --git a/kernel/Kconfig.hz b/kernel/Kconfig.hz
index 94fabd5..37302bf 100644
--- a/kernel/Kconfig.hz
+++ b/kernel/Kconfig.hz
@@ -15,6 +15,22 @@ choice
environment leading to NR_CPUS * HZ number of timer interrupts
per second.
+ config HZ_10
+ bool "10 HZ"
+ help
+ 10 Hz is extremely aggressive and may break things.
+
+ config HZ_12
+ bool "12 HZ"
+ help
+ 12 Hz because it's less aggressive than 10?
+
+ config HZ_25
+ bool "25 HZ"
+ help
+ 25 Hz is useful for reducing HPC application jitter caused by
+ timer interrupts happening during a "fixed time quantum of work
+ then barrier" style workload.
config HZ_100
bool "100 HZ"
@@ -49,6 +65,9 @@ endchoice
config HZ
int
+ default 10 if HZ_10
+ default 12 if HZ_12
+ default 25 if HZ_25
default 100 if HZ_100
default 250 if HZ_250
default 300 if HZ_300
^ permalink raw reply related
* Re: [patch] ps3disk: passing wrong variable to bvec_kunmap_irq()
From: Jens Axboe @ 2010-10-11 19:42 UTC (permalink / raw)
To: Dan Carpenter
Cc: cbe-oss-dev@lists.ozlabs.org, Martin K. Petersen, Geoff Levand,
kernel-janitors@vger.kernel.org, FUJITA Tomonori,
linuxppc-dev@lists.ozlabs.org
In-Reply-To: <20101011191335.GH5851@bicker>
On 2010-10-11 21:13, Dan Carpenter wrote:
> This should pass "buf" to bvec_kunmap_irq() instead of "bv". The api is
> like kmap_atomic() instead of kmap().
>
> Signed-off-by: Dan Carpenter <error27@gmail.com>
>
> diff --git a/drivers/block/ps3disk.c b/drivers/block/ps3disk.c
> index e9da874..03688c2 100644
> --- a/drivers/block/ps3disk.c
> +++ b/drivers/block/ps3disk.c
> @@ -113,7 +113,7 @@ static void ps3disk_scatter_gather(struct ps3_storage_device *dev,
> memcpy(buf, dev->bounce_buf+offset, size);
> offset += size;
> flush_kernel_dcache_page(bvec->bv_page);
> - bvec_kunmap_irq(bvec, &flags);
> + bvec_kunmap_irq(buf, &flags);
> i++;
> }
> }
Thanks applied, that bug is all too common.
--
Jens Axboe
^ permalink raw reply
* [patch] ps3disk: passing wrong variable to bvec_kunmap_irq()
From: Dan Carpenter @ 2010-10-11 19:13 UTC (permalink / raw)
To: Geoff Levand
Cc: cbe-oss-dev, Martin K. Petersen, Jens Axboe, kernel-janitors,
FUJITA Tomonori, linuxppc-dev
This should pass "buf" to bvec_kunmap_irq() instead of "bv". The api is
like kmap_atomic() instead of kmap().
Signed-off-by: Dan Carpenter <error27@gmail.com>
diff --git a/drivers/block/ps3disk.c b/drivers/block/ps3disk.c
index e9da874..03688c2 100644
--- a/drivers/block/ps3disk.c
+++ b/drivers/block/ps3disk.c
@@ -113,7 +113,7 @@ static void ps3disk_scatter_gather(struct ps3_storage_device *dev,
memcpy(buf, dev->bounce_buf+offset, size);
offset += size;
flush_kernel_dcache_page(bvec->bv_page);
- bvec_kunmap_irq(bvec, &flags);
+ bvec_kunmap_irq(buf, &flags);
i++;
}
}
^ permalink raw reply related
* Re: Questions on interrupt vector assignment on MPC8641D
From: Scott Wood @ 2010-10-11 17:30 UTC (permalink / raw)
To: david.hagood; +Cc: linuxppc-dev@lists.ozlabs.org
In-Reply-To: <9af5fd3c8f713d261c7acdc1d195fb84.squirrel@localhost>
On Mon, 11 Oct 2010 12:02:15 -0500
<david.hagood@gmail.com> wrote:
> Re-ordering your questions a bit:
>
> > What board are you using? What kernel?
>
> One of 2 boards: Either an Embedded Planet or a Performance Tech uTCA
> board based on the MPC8641D, running the 2.6.26 as supplied by EP.
That's a very old kernel. Have you contacted EP support?
You may be better off trying to migrate anything board-specific to the
latest kernel, rather than do new development on the vendor kernel,
especially if you're looking for community support, and definitely if
you're trying to do something that could be merged upstream to help
others.
The MPC8641D itself is supported in mainline Linux.
> > On Sat, 9 Oct 2010 10:52:49 -0500
> > Documentation/powerpc/dts-bindings/fsl/mpic.txt
> Not present in the version I have.
We didn't have a time machine, so we were only able to add things to new
releases, not old ones. :-)
Should it have been documented from the start? Ideally, yes, and we're
pickier now than we were then about insisting on bindings being
documented before they're used. But nothing's perfect.
> > If it's not in the dts, add it. If for whatever reason that's not an
> > option, you can use irq_create_mapping() as I mentioned in the previous
> > e-mail.
> And as I've said previously, I have no good info on HOW to add the nodes,
> WHAT to add, or WHERE. You may as well be saying "Bargle the Narbog".
There are no nodes to add with irq_create_mapping().
Just bargle the narbog.
> And when I try to use irq_create_mapping() it seg faults, which doesn't
> exactly help me get my interrupt hooked up.
Well, I didn't know it was going to do that... Your usage of
irq_create_mapping() seems fine, there's just something going wrong.
See my other reply about the number of MPIC interrupts.
> > If you grep arch/powerpc/boot/dts for msi in a reasonably recent kernel
> > you should find msi nodes.
>
> ddhagood@WIC-102362:..Workspace/Linux_Kernel_for_PPC> grep msi
> arch/powerpc/boot/dts -ir
> arch/powerpc/boot/dts/glacier.dts: enable-msi-hole;
> arch/powerpc/boot/dts/taishan.dts: enable-msi-hole;
> arch/powerpc/boot/dts/canyonlands.dts: enable-msi-hole;
> arch/powerpc/boot/dts/katmai.dts: enable-msi-hole;
"reasonably recent kernel"
$ grep -rI msi arch/powerpc/boot/dts/|wc -l
85
> > What did I get signed up for? :-)
>
> It sounds like Tiejun thinks you might be working on, well, basically what
> I am working on - a generic interface to allow user space to support being
> a endpoint,
I am not working on that -- not sure how I gave that impression.
> with the ability to generate interrupts to the host root
> complex, get interrupts from the host root complex, provide memory to be
> accessed by the host root complex via the PPC's BARs, and to access the
> host root complex's PCI address space via the OATMU windows. Something to
> allow a person to use a PPC SOC as an endpoint, and to get on with the job
> of providing functionality rather than having to deal with esoterica.
That does sound like it would be a useful addition.
-Scott
^ permalink raw reply
* Re: Serial RapidIO Maintaintance read causes lock up
From: Bastiaan Nijkamp @ 2010-10-11 17:27 UTC (permalink / raw)
To: John Traill, Bounine, Alexandre; +Cc: linuxppc-dev
In-Reply-To: <4CAB39F4.3030208@freescale.com>
[-- Attachment #1: Type: text/plain, Size: 1757 bytes --]
Hi,
We have found a poorly documented jumper on our boards that force pci-mode
to 32bit instead of 64bit. It seems to have an effect on RapidIO aswell
since the host now completes the enumeration process including finding the
other board. However, as soon as the agent starts the peer discovery
process, ALL RapidIO related registers on the agent are set to 0xFF4A.
Which, offcourse, caused unpredicted behaviour. All other jumpers are set as
they should be, especially the reference clock (100Mhz) and linkspeed
settings (1.25Gbps). I am currently having some trouble understanding why
this happens.
I've double checked Accept All on both boards in the registers and on both
boards it has been set correctly before discovery/enumeration.
Here is the LAW configuration from u-boot for the agent and host:
Local Access Window Configuration
LAWBAR00: 0x00000000 LAWAR0x00: 0x80f0001b
(EN: 1 TGT: 0x0f SIZE: 256 MiB)
LAWBAR01: 0x00080000 LAWAR0x01: 0x8000001c
(EN: 1 TGT: 0x00 SIZE: 512 MiB)
LAWBAR02: 0x000e2000 LAWAR0x02: 0x80000016
(EN: 1 TGT: 0x00 SIZE: 8 MiB)
LAWBAR03: 0x000f0000 LAWAR0x03: 0x8040001b
(EN: 1 TGT: 0x04 SIZE: 256 MiB)
LAWBAR04: 0x000c0000 LAWAR0x04: 0x80c0001c
(EN: 1 TGT: 0x0c SIZE: 512 MiB)
LAWBAR05: 0x00000000 LAWAR0x05: 0x00000000
(EN: 0 TGT: 0x00 SIZE: 2 Bytes)
LAWBAR06: 0x00000000 LAWAR0x06: 0x00000000
(EN: 0 TGT: 0x00 SIZE: 2 Bytes)
LAWBAR07: 0x00000000 LAWAR0x07: 0x00000000
(EN: 0 TGT: 0x00 SIZE: 2 Bytes)
LAWBAR08: 0x00000000 LAWAR0x08: 0x00000000
(EN: 0 TGT: 0x00 SIZE: 2 Bytes)
LAWBAR09: 0x00000000 LAWAR0x09: 0x00000000
(EN: 0 TGT: 0x00 SIZE: 2 Bytes)
We have removed the RapidIO TLB Entries from u-boot.
Kind regards,
Bastiaan Nijkamp
[-- Attachment #2: Type: text/html, Size: 2202 bytes --]
^ permalink raw reply
* Re: Questions on interrupt vector assignment on MPC8641D
From: Scott Wood @ 2010-10-11 17:17 UTC (permalink / raw)
To: tiejun.chen; +Cc: david.hagood, linuxppc-dev@lists.ozlabs.org
In-Reply-To: <4CB2DEFB.90204@windriver.com>
On Mon, 11 Oct 2010 17:55:07 +0800
"tiejun.chen" <tiejun.chen@windriver.com> wrote:
> david.hagood@gmail.com wrote:
> > OK, using 224 as the MPIC interrupt number, and attempting to map it via
> > irq_create_mapping(0,224) gives me a kernel seg fault:
>
> This should not be correct without initialing MSI for MPIC host. As I comment on
> another email, please refer to the file, arch/powerpc/sysdev/fsl_msi.c.
The MSI driver is not going to do anything that would change whether
that call to irq_create_mapping() works or not. fsl_msi.c would also
probably require some changes to be useful in endpoint mode.
> > Reading the source (since these calls don't seem to have any other
> > documentation), it *looks* like it ought to be valid to call
> > irq_create_mapping with a null irq_host *host - which is good, since I
> > can't see anything obvious that would give me some other irq_host (again,
> > since none of this seems to be documented anywhere).
There's mpic stuff in the call trace, so the NULL host was OK.
Look in arch/powerpc/platforms/86xx/pic.c. What is the second-to-last
parameter of mpc86xx_init_irq() in your kernel tree? It's 256 in
current upstream -- this is the number of IRQ sources the MPIC driver
will handle.
-Scott
^ permalink raw reply
* Re: Questions on interrupt vector assignment on MPC8641D
From: david.hagood @ 2010-10-11 17:02 UTC (permalink / raw)
To: Scott Wood; +Cc: david.hagood, linuxppc-dev@lists.ozlabs.org
In-Reply-To: <20101011105031.52a5c06a@udp111988uds.am.freescale.net>
Re-ordering your questions a bit:
> What board are you using? What kernel?
One of 2 boards: Either an Embedded Planet or a Performance Tech uTCA
board based on the MPC8641D, running the 2.6.26 as supplied by EP.
> On Sat, 9 Oct 2010 10:52:49 -0500
> Documentation/powerpc/dts-bindings/fsl/mpic.txt
Not present in the version I have.
>
> Plus the chip manual, for the register offsets.
I have that now, so at least one part of the fog is a bit less dense.
> If it's not in the dts, add it. If for whatever reason that's not an
> option, you can use irq_create_mapping() as I mentioned in the previous
> e-mail.
And as I've said previously, I have no good info on HOW to add the nodes,
WHAT to add, or WHERE. You may as well be saying "Bargle the Narbog".
And when I try to use irq_create_mapping() it seg faults, which doesn't
exactly help me get my interrupt hooked up.
(crotchety old man mode)Kids these day - when I was a kid, you just
grabbed the IRQ vector into your assembly code and away you went. Now GET
OFF MY YARD!(/crotchety old man mode).
> If you grep arch/powerpc/boot/dts for msi in a reasonably recent kernel
> you should find msi nodes.
ddhagood@WIC-102362:..Workspace/Linux_Kernel_for_PPC> grep msi
arch/powerpc/boot/dts -ir
arch/powerpc/boot/dts/glacier.dts: enable-msi-hole;
arch/powerpc/boot/dts/taishan.dts: enable-msi-hole;
arch/powerpc/boot/dts/canyonlands.dts: enable-msi-hole;
arch/powerpc/boot/dts/katmai.dts: enable-msi-hole;
> What did I get signed up for? :-)
It sounds like Tiejun thinks you might be working on, well, basically what
I am working on - a generic interface to allow user space to support being
a endpoint, with the ability to generate interrupts to the host root
complex, get interrupts from the host root complex, provide memory to be
accessed by the host root complex via the PPC's BARs, and to access the
host root complex's PCI address space via the OATMU windows. Something to
allow a person to use a PPC SOC as an endpoint, and to get on with the job
of providing functionality rather than having to deal with esoterica.
I'm hoping to make an interface generic enough to support not only the
PPC, but other devices as well (things I cannot go into due to NDAs at
this time). As a systems programmer, I am tired of re-inventing the wheel
when dealing with being an endpoint - I want to invent the wheel, and push
it uphill to the greater Linux community so that a) others are spared the
pain I am suffering, and b) maybe other SOC vendors will implement my
interface (and thus I won't have to).
^ permalink raw reply
* Re: Questions on interrupt vector assignment on MPC8641D
From: Scott Wood @ 2010-10-11 15:50 UTC (permalink / raw)
To: david.hagood; +Cc: linuxppc-dev@lists.ozlabs.org
In-Reply-To: <adaf806ee1c11621dbb51246bef0acd8.squirrel@localhost>
On Sat, 9 Oct 2010 10:52:49 -0500
<david.hagood@gmail.com> wrote:
> First of all - where is all of this documented? There seems to be a great
> deal of "oral tradition" type knowledge here, but is any of it actually
> written down somewhere? (see below for examples)
Documentation/powerpc/dts-bindings/fsl/mpic.txt
Plus the chip manual, for the register offsets.
> > On Thu, 7 Oct 2010 15:12:26 -0500
> > This is asking for the 256th specifier in the interrupts property in
> > the mpic node -- not what you want.
>
> That was from some of the previous emails in this thread.
>
> > Ideally you would have a node for your device with an interrupt
> > specifier that you could look up with irq_of_parse_and_map().
>
> OK, and how do these devices come into being? From what I can tell, they
> are defined by uBoot, and if uBoot doesn't define it, then you are out of
> luck.
More commonly they're statically defined in the dts file, not
dynamically created by u-boot.
If it's not in the dts, add it. If for whatever reason that's not an
option, you can use irq_create_mapping() as I mentioned in the previous
e-mail.
> * A set of APIs (irq_of_parse_and_map(), irq_create_mapping) that were,
> for all intents, undocumented (just "here's the parameters", no
> description of when and how to use them), that took a ???? and returned a
> ???? (because, with the documentation I had, that's basically all I could
> say about them).
Yes, there are many parts of the kernel that could use better
documentation.
> > BTW, the MSIs are already described in an msi node in the device tree.
>
> As I stated previously - not that I can see.
What board are you using? What kernel?
If you grep arch/powerpc/boot/dts for msi in a reasonably recent kernel
you should find msi nodes.
> It may be they are defined in PCI Root Complex mode,
No, it's a separate node.
-Scott
^ permalink raw reply
* Re: Questions on interrupt vector assignment on MPC8641D
From: Scott Wood @ 2010-10-11 15:51 UTC (permalink / raw)
To: tiejun.chen; +Cc: david.hagood, linuxppc-dev@lists.ozlabs.org
In-Reply-To: <4CB2DE2B.7040504@windriver.com>
On Mon, 11 Oct 2010 17:51:39 +0800
"tiejun.chen" <tiejun.chen@windriver.com> wrote:
> Maybe you can check the file, ppc4xx_pci.c since ppc4xx also can support EP as I
> previously said. And sounds Scott will do something to support EP for Freescale
> chip.
What did I get signed up for? :-)
-Scott
^ permalink raw reply
* Re: Questions on interrupt vector assignment on MPC8641D
From: david.hagood @ 2010-10-11 14:44 UTC (permalink / raw)
To: tiejun.chen; +Cc: Scott Wood, david.hagood, linuxppc-dev@lists.ozlabs.org
In-Reply-To: <4CB2DE2B.7040504@windriver.com>
> You should define MSI device nodes on your target dts. And you can refer
> to the
> file, mpc8572ds.dts.
I see nothing in that file that defines any MSIs. I see code that looks
like it maps ROOT COMPLEX MODE interrupts on regular PCI interfaces, which
IS NOT WHAT I AM DOING.
Since it seems I have been unclear, let me state this as clearly as possible.
I AM DOING ENDPOINT MODE.
> I think you can check fsl_msi.c to figure out what you want.
Except that file doesn't exist in the 2.6.26 kernel with which I am working.
> Firstly you should use irq_of_parse_and_map()/irq_create_mapping() to map
> the
> real hardware irq to virtual irq. Then use request_irq() with the virtual
> irq to
> hook your interrupt handler.
Except I have no device to pass irq_of_parse_and_map, and when I call
irq_create_mapping it seg faults.
>
> Maybe you can check the file, ppc4xx_pci.c since ppc4xx also can support
> EP as I
> previously said.
It only "supports" EP mode in the sense that it sets the hardware up to
export a BAR, and does nothing else. It doesn't provide any means for any
other code to actually DO anything in that mode. It doesn't define a way
to be interrupted by the root complex, nor to do anything when that
interrupt happens. It doesn't supply any meaningful framework to get any
data from the Root Complex.
That's the whole reason I am trying to make a piece of code that actually
WILL make those things available in a useful fashion.
^ permalink raw reply
* Re: powerpc, fs_enet: scanning PHY after Linux is up
From: Holger brunck @ 2010-10-11 11:49 UTC (permalink / raw)
To: Grant Likely; +Cc: linuxppc-dev, devicetree-discuss, hs, Detlev Zundel, netdev
In-Reply-To: <20101008170615.GC3863@angua.secretlab.ca>
Hi Grant,
On 10/08/2010 07:06 PM, Grant Likely wrote:
> On Fri, Oct 08, 2010 at 10:50:50AM +0200, Holger brunck wrote:
>>> On Wed, Oct 6, 2010 at 3:53 AM, Heiko Schocher <hs@denx.de> wrote:
>>
>>>> Wouldn;t it be good, just if we need a PHY (on calling fs_enet_open)
>>>> to look if there is one?
>>>>
>>>> Something like that (not tested):
>>>>
>>>> in drivers/net/fs_enet/fs_enet-main.c in fs_init_phy()
>>>> called from fs_enet_open():
>>>>
>>>> Do first:
>>>> phydev = of_phy_find_device(fep->fpi->phy_node);
>>>>
>>>> Look if there is a driver (phy_dev->drv == NULL ?)
>>>>
>>>> If not, call new function
>>>> of_mdiobus_register_phy(mii_bus, fep->fpi->phy_node)
>>>> see below patch for it.
>>>>
>>>> If this succeeds, all is OK, and we can use this phy,
>>>> else ethernet not work.
>>>
>>> I don't like this approach because it muddies the concept of which
>>> device is actually responsible for managing the phys on the bus. Is
>>> it managed by the mdio bus device or the Ethernet device? It also has
>>> a potential race condition. Whereas triggering a late driver bind
>>> will be safe.
>>>
>>> Alternately, I'd also be okay with a common method to trigger a
>>> reprobe of a particular phy from userspace, but I fear that would be a
>>> significantly more complex solution.
>>>
>>>>
>>>> !!just no idea, how to get mii_bus pointer ...
>>>
>>> You'd have to get the parent of the phy node, and then loop over all
>>> the registered mdio busses looking for a bus that uses that node.
>>>
>>
>> you say that you don't like the approach to probe the phy again in fs_enet_open,
>> but currently I don't understand what would be the alternate trigger point to
>> rescan the mdio bus?
>
> Same trigger point, but different operation. At fs_enet_open time,
> instead of registering the phy_device, the phy layer could sanity
> check the already registered phy_device, and refuse to connect to it
> if the phy isn't responding. If it is responding, then it could
> re-attempt binding a phy_driver to it (although I just realized that
> this has other problems, such as correct module loading. See below)
>
ok.
>> I made a first patch to enhance the phy_device structure and rescan the mdio bus
>> at time of fs_enet_open (because I didn't see a better trigger point). The
>> advantage is that we got the mii_bus pointer and the phy addr stored in the
>> already created phy device structure and is therefore easy to use. See the patch
>> below for this modifications. Whats currently missing in the patch is to set the
>> phy_id if the phy was scanned later after phy_device creation. For the mgcoge
>> board it seems to solve our problem, but maybe I miss something important.
>>
>> Best regards
>> Holger Brunck
>>
>> diff --git a/drivers/net/fs_enet/fs_enet-main.c b/drivers/net/fs_enet/fs_enet-main.c
>> index ec2f503..6bc117f 100644
>> --- a/drivers/net/fs_enet/fs_enet-main.c
>> +++ b/drivers/net/fs_enet/fs_enet-main.c
>> @@ -775,7 +774,8 @@ static int fs_enet_open(struct net_device *dev)
>> {
>> struct fs_enet_private *fep = netdev_priv(dev);
>> int r;
>> - int err;
>> + int err = 0;
>> + u32 phy_id = 0;
>>
>> /* to initialize the fep->cur_rx,... */
>> /* not doing this, will cause a crash in fs_enet_rx_napi */
>> @@ -795,13 +795,23 @@ static int fs_enet_open(struct net_device *dev)
>> return -EINVAL;
>> }
>>
>> - err = fs_init_phy(dev);
>> - if (err) {
>> + if (fep->phydev == NULL)
>> + err = fs_init_phy(dev);
>> +
>> + if (!err && (fep->phydev->available == false))
>> + r = get_phy_id(fep->phydev->bus, fep->phydev->addr, &phy_id);
>> +
>> + if (err || (phy_id == 0xffffffff)) {
>> free_irq(fep->interrupt, dev);
>> if (fep->fpi->use_napi)
>> napi_disable(&fep->napi);
>> - return err;
>> + if (err)
>> + return err;
>> + else
>> + return -EINVAL;
>> }
>> + else
>> + fep->phydev->available = true;
>> phy_start(fep->phydev);
>>
>> netif_start_queue(dev);
>> diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c
>> index adbc0fd..1f443cb 100644
>> --- a/drivers/net/phy/phy_device.c
>> +++ b/drivers/net/phy/phy_device.c
>> @@ -173,6 +173,10 @@ struct phy_device* phy_device_create(struct mii_bus *bus,
>> int addr, int phy_id)
>> dev->dev.bus = &mdio_bus_type;
>> dev->irq = bus->irq != NULL ? bus->irq[addr] : PHY_POLL;
>> dev_set_name(&dev->dev, PHY_ID_FMT, bus->id, addr);
>> + if (phy_id == 0xffffffff)
>> + dev->available = false;
>> + else
>> + dev->available = true;
>
> This flag shouldn't be necessary. Just check whether or not
> phy_device->phy_id is sane at phy_attach_direct() time. If it is
> mostly f's, then don't attach.
>
Yes, indeed it is unneeded. Thanks for pointing out.
>>
>> dev->state = PHY_DOWN;
>>
>> @@ -232,13 +236,11 @@ struct phy_device * get_phy_device(struct mii_bus *bus,
>> int addr)
>> int r;
>>
>> r = get_phy_id(bus, addr, &phy_id);
>> - if (r)
>> - return ERR_PTR(r);
>>
>> /* If the phy_id is mostly Fs, there is no device there */
>> - if ((phy_id & 0x1fffffff) == 0x1fffffff)
>> - return NULL;
>> -
>> + if (((phy_id & 0x1fffffff) == 0x1fffffff) || r)
>> + phy_id = 0xffffffff;
>> + /* create phy even if the phy is currently not available */
>> dev = phy_device_create(bus, addr, phy_id);
>
> Cannot do it this way because many phylib users probe the bus for phys
> instead of the explicit creation used with the device tree. There
> needs to be a method to explicitly skip this test when creating a phy;
> possibly by having the device tree code call phy_device_create()
> directly.
>
Ah ok, every phy_device_create() call from of_mdiobus_register should skip this
test, because if a phy is described in the dts it is present (sooner or later)
and if phy_device_create is called from somewhere else I do this test as usual.
I adapted my patch accordingly.
> Hmmm.... I see another problem. Deferred probing of the phy will
> potentially cause problems with module loading. If the binding is
> deferred to phy connect time; then the phy driver may not have time to
> get loaded before the phy layer decides there is no driver and binds
> it to the generic one. Blech.
>
> Okay, so it seems like a method of explicitly triggering a phy_device
> rebind from userspace is necessary. This could be done with a
> per-phy_device sysfs file I suppose. Just an empty file that when
> read triggers a re-read of the phy id registers, and retries binding a
> driver, including the request_module call in phy_device_create().
>
Okay I suspected that there is not an easy solution for our problem. Another
solution comes in my mind. If we defer the call to fs_enet_probe at startup. So
enhance the dts entry with something like an hotplug indication and then trigger
via an sysfs entry the call to fs_enet_probe if the phy is up... Other hotplug
devices should have similar problems...
However for our mgcoge board we can live with the fact that we can't load/unload
the driver dynamically. So I think we will go with this modified "out of tree"
patch for our board. Thanks for your support.
Best regards
Holger Brunck
^ permalink raw reply
* Re: Freescale P2020 / 85xx PCIe and Advance Error Reporting (AER) service problem
From: Benjamin Herrenschmidt @ 2010-10-11 11:32 UTC (permalink / raw)
To: Eran Liberty; +Cc: linux-pci, linuxppc-dev
In-Reply-To: <4CB2E517.8020401@extricom.com>
> BUT if we take into consideration that:
> 1. Freescale is a serious dude in the hood and on the whole does a good
> job with its products and their Linux support.
Sure but that's irrelevant to the technical problem at hand :-)
> 2. The P2020 does state it has an MSI mechanism support (although one is
> not present as a PCIe capability header for some reason)
Then it's broken :-(
> 3. Errors in general and AER are major features in PCIe.
> 4. PCIe has been here quite a while and it is not new to Freescale or
> anyone else.
Right but we don't do AER on ppc44x either, I know we should but for
some reason, AER hasn't been on anybody #1 priority list in embedded
world so far...
> I am much more inclined to believe that I have missed something by a
> mile then that Freescale did. I just don't know what I am missing.
No, I think you haven't and we just need to fix it :-)
Cheers,
Ben.
> My device tree is a clone of "arch/ powerpc/ boot/ dts/ p2020rdb.dts"
>
> It has a PCI node that looks like this:
> ----------------------------- snip -----------------------------
> pci0: pcie@ffe09000 {
> cell-index = <1>;
> compatible = "fsl,mpc8548-pcie";
> device_type = "pci";
> #interrupt-cells = <1>;
> #size-cells = <2>;
> #address-cells = <3>;
> reg = <0 0xffe09000 0 0x1000>;
> bus-range = <0 255>;
> ranges = <0x2000000 0x0 0xa0000000 0 0xa0000000 0x0 0x20000000
> 0x1000000 0x0 0x00000000 0 0xffc30000 0x0 0x10000>;
> clock-frequency = <33333333>;
> interrupt-parent = <&mpic>;
> interrupts = <25 2>;
> interrupt-map-mask = <0xf800 0x0 0x0 0x7>;
> interrupt-map = <
> /* IDSEL 0x0 */
> 0000 0x0 0x0 0x1 &mpic 0x4 0x1
> 0000 0x0 0x0 0x2 &mpic 0x5 0x1
> 0000 0x0 0x0 0x3 &mpic 0x6 0x1
> 0000 0x0 0x0 0x4 &mpic 0x7 0x1
> >;
> pcie@0 {
> reg = <0x0 0x0 0x0 0x0 0x0>;
> #size-cells = <2>;
> #address-cells = <3>;
> device_type = "pci";
> ranges = <0x2000000 0x0 0xa0000000
> 0x2000000 0x0 0xa0000000
> 0x0 0x20000000
>
> 0x1000000 0x0 0x0
> 0x1000000 0x0 0x0
> 0x0 0x100000>;
> };
> };
> ----------------------------- snap -----------------------------
>
> and under "soc" it has an MSI node that looks like that:
> ----------------------------- snip -----------------------------
> msi@41600 {
> compatible = "fsl,p2020-msi", "fsl,mpic-msi";
> reg = <0x41600 0x80>;
> msi-available-ranges = <0 0x100>;
> interrupts = <
> 0xe0 0
> 0xe1 0
> 0xe2 0
> 0xe3 0
> 0xe4 0
> 0xe5 0
> 0xe6 0
> 0xe7 0>;
> interrupt-parent = <&mpic>;
> };
> ----------------------------- snap -----------------------------
>
> -- Liberty
>
^ permalink raw reply
* Re: Questions on interrupt vector assignment on MPC8641D
From: David Hagood @ 2010-10-11 11:30 UTC (permalink / raw)
To: tiejun.chen; +Cc: Scott Wood, linuxppc-dev@lists.ozlabs.org
In-Reply-To: <4CB2DE2B.7040504@windriver.com>
On Mon, 2010-10-11 at 17:51 +0800, tiejun.chen wrote:
>
> You should define MSI device nodes on your target dts. And you can refer to the
> file, mpc8572ds.dts.
>
> Often U-Boot dose not generate MSI information and embed that to dtb.
>
> >
> > But even assuming you can define these nodes at run time, as far as I can
> > see, you are right back to the question of "and how do I know what the
> > mappings are so I can create the node?" You haven't answered the question,
> > you've just moved where you are asking it.
>
> I think you can check fsl_msi.c to figure out what you want.
<snip>
> Often most latest classic books/articles always use x86 code as an
example to
> clarify Linux. So you have to understand something on PPC via codes.
But I think
> you will benefit more information from the codes than documents :)
>
RTFS. That wouldn't be bad advice, if the source were actually
commented. None of these APIS have any meaningful comments in them,
around them, or anywhere near them. You'd think we were back in the old
BASIC days, when comments occupied run-time memory. Code can tell me
WHAT is being done, but not WHY, and not what assumptions are being
made.
So when you say "You should define MSI device nodes on your target dts."
we go right back to my comment of "You haven't answered the question,
you've just moved where you are asking it."
>
> Firstly you should use irq_of_parse_and_map()/irq_create_mapping() to map the
> real hardware irq to virtual irq. Then use request_irq() with the virtual irq to
> hook your interrupt handler.
And when I do that, I get a segfault as my follow-on mail reports.
>
> Maybe you can check the file, ppc4xx_pci.c since ppc4xx also can support EP as I
> previously said. And sounds Scott will do something to support EP for Freescale
> chip.
I will look at that file.
>
> Looks you want to your host root complex to trigger MSI to mpc8641 EP target? If
> so I'm a bit confused since MSIs should be delivered to to the Root Complex
> resided on your host.
I want the host to be able to interrupt the PPC. Since this is PCIe, the
only way that will be working is for the root complex to do a write to
somewhere on the PPC. This is basically the same mechanism as MSI, only
with the PPC as the target of the write rather than the root complex.
Obviously, the rest of the PCI devices will be sending interrupts to the
root complex, some via MSI. That has nothing to do with this discussion.
Since the PPC is in endpoint mode, the MSI hardware on the PPC won't be
used. The hardware is writable from the root complex via the PPC BAR0,
so I see no reason not to reuse it to trigger interrupts on the PPC from
the Root complex.
^ 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