RE: [PATCH 2/2] powerpc/fsl-pci: Only scan PCI bus if configured as a host
-Original Message- From: linuxppc-dev-bounces+b38951=freescale@lists.ozlabs.org [mailto:linuxppc-dev-bounces+b38951=freescale@lists.ozlabs.org] On Behalf Of Kumar Gala Sent: Friday, October 28, 2011 9:10 PM To: Jia Hongtao-B38951 Cc: Gala Kumar-B11780; linuxppc-dev@lists.ozlabs.org Subject: Re: [PATCH 2/2] powerpc/fsl-pci: Only scan PCI bus if configured as a host On Oct 28, 2011, at 3:03 AM, Jia Hongtao wrote: > 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 > Signed-off-by: Li Yang > --- > arch/powerpc/sysdev/fsl_pci.c | 17 ++--- > 1 files changed, 10 insertions(+), 7 deletions(-) > > diff --git a/arch/powerpc/sysdev/fsl_pci.c > b/arch/powerpc/sysdev/fsl_pci.c index 4d4536f..caa7801 100644 > --- a/arch/powerpc/sysdev/fsl_pci.c > +++ b/arch/powerpc/sysdev/fsl_pci.c > @@ -370,7 +370,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); > @@ -418,6 +418,7 @@ void fsl_pci_setup(int primary_phb_addr) { > struct device_node *np; > struct pci_controller *hose; > + int ret; > dma_addr_t min_dma_addr = 0x; > > for_each_node_by_type(np, "pci") { > @@ -425,14 +426,16 @@ void fsl_pci_setup(int primary_phb_addr) > struct resource rsrc; > of_address_to_resource(np, 0, &rsrc); > if ((rsrc.start & 0xf) == primary_phb_addr) > - fsl_add_bridge(np, 1); > + ret = fsl_add_bridge(np, 1); > else > - fsl_add_bridge(np, 0); > + ret = fsl_add_bridge(np, 0); > > - hose = pci_find_hose_for_OF_device(np); > - min_dma_addr = min(min_dma_addr, > - hose->dma_window_base_cur > - + hose->dma_window_size); > + if (ret == 0) { > + hose = pci_find_hose_for_OF_device(np); > + min_dma_addr = min(min_dma_addr, > + hose->dma_window_base_cur > + + hose->dma_window_size); > + } > > } > } In the failure case (i.e. when ret != 0), what about the following code: +#ifdef CONFIG_SWIOTLB + /* +* 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() > min_dma_addr) { + ppc_swiotlb_enable = 1; + set_pci_dma_ops(&swiotlb_dma_ops); + ppc_md.pci_dma_dev_setup = pci_dma_dev_setup_swiotlb; + } +#endif This should get updated to be: if ((ret == 0) && (memblock_end_of_DRAM() > min_dma_arr)) { [Jia Hongtao-B38951] A board could have more than one pci controllers, so this update is not right for it only checked the last one. I will submit another patch to solve this issue. ___ 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
[PATCH SDK1.1 v2 0/2] PCIEP Patches Description
These patches against kernel 3.0 for SDK 1.1. The patches include contents from topic branch 15-pciep. Also we add PCI related patch from topic branch 05-MPC8572DS here. We update the pci/pcie initialization code. ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[PATCH 1/2] Unify pci/pcie initialization code
In previous version pci/pcie initialization is in platform code which Initialize PCI bridge base on EP/RC or host/agent settings. We unified pci/pcie initialization as common APIs named fsl_pci_setup which can be called by platform code. Signed-off-by: Jia Hongtao Signed-off-by: Li Yang --- arch/powerpc/platforms/85xx/mpc85xx_ds.c | 30 ++- arch/powerpc/sysdev/fsl_pci.c| 48 ++ arch/powerpc/sysdev/fsl_pci.h|5 +++ 3 files changed, 56 insertions(+), 27 deletions(-) diff --git a/arch/powerpc/platforms/85xx/mpc85xx_ds.c b/arch/powerpc/platforms/85xx/mpc85xx_ds.c index 10e7db0..7188c0b 100644 --- a/arch/powerpc/platforms/85xx/mpc85xx_ds.c +++ b/arch/powerpc/platforms/85xx/mpc85xx_ds.c @@ -157,33 +157,12 @@ extern void __init mpc85xx_smp_init(void); #endif static void __init mpc85xx_ds_setup_arch(void) { -#ifdef CONFIG_PCI - struct device_node *np; - struct pci_controller *hose; -#endif - dma_addr_t max = 0x; - 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 & 0xf) == 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); - } - } + fsl_pci_setup(primary_phb_addr); +#ifdef CONFIG_PCI ppc_md.pci_exclude_device = mpc85xx_exclude_device; #endif @@ -192,11 +171,8 @@ static void __init mpc85xx_ds_setup_arch(void) #endif #ifdef CONFIG_SWIOTLB - if (memblock_end_of_DRAM() > max) { + if (memblock_end_of_DRAM() > 0x) 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"); diff --git a/arch/powerpc/sysdev/fsl_pci.c b/arch/powerpc/sysdev/fsl_pci.c index 80b8b7a..4d4536f 100644 --- a/arch/powerpc/sysdev/fsl_pci.c +++ b/arch/powerpc/sysdev/fsl_pci.c @@ -402,6 +402,54 @@ int __init fsl_add_bridge(struct device_node *dev, int is_primary) } #endif /* CONFIG_FSL_SOC_BOOKE || CONFIG_PPC_86xx */ +static struct of_device_id pci_ids[] = { + { .compatible = "fsl,mpc8540-pci", }, + { .compatible = "fsl,mpc8548-pcie", }, + {}, +}; + +/** + * fsl_pci_setup - Initialization for PCI + * @primary_phb_addr: primary bus address + * + * Add bridge if pci controller is a host + */ +void fsl_pci_setup(int primary_phb_addr) +{ + struct device_node *np; + struct pci_controller *hose; + dma_addr_t min_dma_addr = 0x; + + for_each_node_by_type(np, "pci") { + if (of_match_node(pci_ids, np)) { + struct resource rsrc; + of_address_to_resource(np, 0, &rsrc); + if ((rsrc.start & 0xf) == primary_phb_addr) + fsl_add_bridge(np, 1); + else + fsl_add_bridge(np, 0); + + hose = pci_find_hose_for_OF_device(np); + min_dma_addr = min(min_dma_addr, + hose->dma_window_base_cur + + hose->dma_window_size); + + } + } + +#ifdef CONFIG_SWIOTLB + /* +* 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() > min_dma_addr) { + ppc_swiotlb_enable = 1; + set_pci_dma_ops(&swiotlb_dma_ops); + ppc_md.pci_dma_dev_setup = pci_dma_dev_setup_swiotlb; + } +#endif +} + DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_FREESCALE, PCI_ANY_ID, quirk_fsl_pcie_header); #if defined(CONFIG_PPC_83xx) || defined(CONFIG_PPC_MPC512x) diff --git a/arch/powerpc/sysdev/fsl_pci.h b/arch/powerpc/sysdev/fsl_pci.h index a39ed5c..775ea21 100644 --- a/arch/powerpc/sysdev/fsl_pci.h +++ b/arch/powerpc/sysdev/fsl_pci.h @@ -89,6 +89,11 @@ struct ccsr_pci { }; extern int fsl_add_bridge(struct device_node *dev, int is_primary); +#ifndef CONFIG_PCI +#define fsl_pci_setup(p) +#else +extern void fsl_pci_setup(int primary_phb_addr); +#endif extern void fsl
[PATCH 2/2] powerpc/fsl-pci: Only scan PCI bus if configured as a host
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 Signed-off-by: Li Yang --- arch/powerpc/sysdev/fsl_pci.c | 23 ++- 1 files changed, 14 insertions(+), 9 deletions(-) diff --git a/arch/powerpc/sysdev/fsl_pci.c b/arch/powerpc/sysdev/fsl_pci.c index 4d4536f..11c1e23 100644 --- a/arch/powerpc/sysdev/fsl_pci.c +++ b/arch/powerpc/sysdev/fsl_pci.c @@ -370,7 +370,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); @@ -418,6 +418,8 @@ void fsl_pci_setup(int primary_phb_addr) { struct device_node *np; struct pci_controller *hose; + int ret; + int has_host = 0; dma_addr_t min_dma_addr = 0x; for_each_node_by_type(np, "pci") { @@ -425,14 +427,17 @@ void fsl_pci_setup(int primary_phb_addr) struct resource rsrc; of_address_to_resource(np, 0, &rsrc); if ((rsrc.start & 0xf) == primary_phb_addr) - fsl_add_bridge(np, 1); + ret = fsl_add_bridge(np, 1); else - fsl_add_bridge(np, 0); - - hose = pci_find_hose_for_OF_device(np); - min_dma_addr = min(min_dma_addr, - hose->dma_window_base_cur - + hose->dma_window_size); + ret = fsl_add_bridge(np, 0); + + if (ret == 0) { + has_host = 1; + hose = pci_find_hose_for_OF_device(np); + min_dma_addr = min(min_dma_addr, + hose->dma_window_base_cur + + hose->dma_window_size); + } } } @@ -442,7 +447,7 @@ void fsl_pci_setup(int primary_phb_addr) * 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() > min_dma_addr) { + if (has_host && memblock_end_of_DRAM() > min_dma_addr) { ppc_swiotlb_enable = 1; set_pci_dma_ops(&swiotlb_dma_ops); ppc_md.pci_dma_dev_setup = pci_dma_dev_setup_swiotlb; -- 1.7.5.1 ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
Re: powerpc 476, Little-endian, pte fault
> I have built a cross compiler for ppc440 in little endian mode and > using it to build the kernel. > > Yes i am running Linux in Little-Endian. This is the first user space > process. I wrote the below program and running it as init from > /sbin/init. I have also set the permissions with chmod +s. > > main() > { > > while(1){ > printf("hello world"); > sleep(1); > } > } Does libc even support little endian on PPC? > I have attached the patch. This is a pretty huge patch: 115 files changed, 44479 insertions(+), 7398 deletions(-) It seems to include a new platform as well as a bunch of unrelated junk. I suggest you need to break this down into something more digestible. Like remove all the junk in the patch. Then add the support for the new platform (invader? platform). Then start looking at little endian. Unless you do this, it's unlikely anyone here is going to be able to help. When you get to the little endian work, you might want to take a look at this patch series from Ian Munsie: http://lists.ozlabs.org/pipermail/linuxppc-dev/2010-October/086165.html Mikey ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[PATCH] mtd/nand : set Nand flash page address to FBAR and FPAR correctly
From: Liu Shuo If we use the Nand flash chip whose number of pages in a block is greater than 64(for large page), we must treat the low bit of FBAR as being the high bit of the page address due to the limitation of FCM, it simply uses the low 6-bits (for large page) of the combined block/page address as the FPAR component, rather than considering the actual block size. Signed-off-by: Liu Shuo Signed-off-by: Jerry Huang Signed-off-by: Tang Yuantian Signed-off-by: Li Yang --- drivers/mtd/nand/fsl_elbc_nand.c | 13 ++--- 1 files changed, 10 insertions(+), 3 deletions(-) diff --git a/drivers/mtd/nand/fsl_elbc_nand.c b/drivers/mtd/nand/fsl_elbc_nand.c index 33d8aad..681d8c5 100644 --- a/drivers/mtd/nand/fsl_elbc_nand.c +++ b/drivers/mtd/nand/fsl_elbc_nand.c @@ -167,15 +167,22 @@ static void set_addr(struct mtd_info *mtd, int column, int page_addr, int oob) elbc_fcm_ctrl->page = page_addr; - out_be32(&lbc->fbar, -page_addr >> (chip->phys_erase_shift - chip->page_shift)); - if (priv->page_size) { + /* +* large page size chip : FPAR[PI] save the lowest 6 bits, +*FBAR[BLK] save the other bits. +*/ + out_be32(&lbc->fbar, page_addr >> 6); out_be32(&lbc->fpar, ((page_addr << FPAR_LP_PI_SHIFT) & FPAR_LP_PI) | (oob ? FPAR_LP_MS : 0) | column); buf_num = (page_addr & 1) << 2; } else { + /* +* small page size chip : FPAR[PI] save the lowest 5 bits, +*FBAR[BLK] save the other bits. +*/ + out_be32(&lbc->fbar, page_addr >> 5); out_be32(&lbc->fpar, ((page_addr << FPAR_SP_PI_SHIFT) & FPAR_SP_PI) | (oob ? FPAR_SP_MS : 0) | column); -- 1.7.1 ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[PATCH v2] Integrated Flash Controller support
From: Liu Shuo Integrated Flash Controller supports various flashes like NOR, NAND and other devices using NOR, NAND and GPCM Machine available on it. IFC supports four chip selects. Signed-off-by: Dipen Dudhat Signed-off-by: Scott Wood Signed-off-by: Li Yang Signed-off-by: Liu Shuo --- arch/powerpc/Kconfig |4 + arch/powerpc/include/asm/fsl_ifc.h | 834 arch/powerpc/sysdev/Makefile |1 + arch/powerpc/sysdev/fsl_ifc.c | 322 ++ 4 files changed, 1161 insertions(+), 0 deletions(-) create mode 100644 arch/powerpc/include/asm/fsl_ifc.h create mode 100644 arch/powerpc/sysdev/fsl_ifc.c diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig index f8e578b..3cd1e64 100644 --- a/arch/powerpc/Kconfig +++ b/arch/powerpc/Kconfig @@ -688,6 +688,10 @@ config FSL_LBC controller. Also contains some common code used by drivers for specific local bus peripherals. +config FSL_IFC + bool +depends on FSL_SOC + config FSL_GTM bool depends on PPC_83xx || QUICC_ENGINE || CPM2 diff --git a/arch/powerpc/include/asm/fsl_ifc.h b/arch/powerpc/include/asm/fsl_ifc.h new file mode 100644 index 000..b955012 --- /dev/null +++ b/arch/powerpc/include/asm/fsl_ifc.h @@ -0,0 +1,834 @@ +/* Freescale Integrated Flash Controller + * + * Copyright 2011 Freescale Semiconductor, Inc + * + * Author: Dipen Dudhat + * + * 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 + */ + +#ifndef __ASM_FSL_IFC_H +#define __ASM_FSL_IFC_H + +#include +#include +#include + +#include +#include + +#define FSL_IFC_BANK_COUNT 4 + +/* + * CSPR - Chip Select Property Register + */ +#define CSPR_BA0x +#define CSPR_BA_SHIFT 16 +#define CSPR_PORT_SIZE 0x0180 +#define CSPR_PORT_SIZE_SHIFT 7 +/* Port Size 8 bit */ +#define CSPR_PORT_SIZE_8 0x0080 +/* Port Size 16 bit */ +#define CSPR_PORT_SIZE_16 0x0100 +/* Port Size 32 bit */ +#define CSPR_PORT_SIZE_32 0x0180 +/* Write Protect */ +#define CSPR_WP0x0040 +#define CSPR_WP_SHIFT 6 +/* Machine Select */ +#define CSPR_MSEL 0x0006 +#define CSPR_MSEL_SHIFT1 +/* NOR */ +#define CSPR_MSEL_NOR 0x +/* NAND */ +#define CSPR_MSEL_NAND 0x0002 +/* GPCM */ +#define CSPR_MSEL_GPCM 0x0004 +/* Bank Valid */ +#define CSPR_V 0x0001 +#define CSPR_V_SHIFT 0 + +/* + * Address Mask Register + */ +#define IFC_AMASK_MASK 0x +#define IFC_AMASK_SHIFT16 +#define IFC_AMASK(n) (IFC_AMASK_MASK << \ + (__ilog2(n) - IFC_AMASK_SHIFT)) + +/* + * Chip Select Option Register IFC_NAND Machine + */ +/* Enable ECC Encoder */ +#define CSOR_NAND_ECC_ENC_EN 0x8000 +#define CSOR_NAND_ECC_MODE_MASK0x3000 +/* 4 bit correction per 520 Byte sector */ +#define CSOR_NAND_ECC_MODE_4 0x +/* 8 bit correction per 528 Byte sector */ +#define CSOR_NAND_ECC_MODE_8 0x1000 +/* Enable ECC Decoder */ +#define CSOR_NAND_ECC_DEC_EN 0x0400 +/* Row Address Length */ +#define CSOR_NAND_RAL_MASK 0x0180 +#define CSOR_NAND_RAL_SHIFT20 +#define CSOR_NAND_RAL_10x +#define CSOR_NAND_RAL_20x0080 +#define CSOR_NAND_RAL_30x0100 +#define CSOR_NAND_RAL_40x0180 +/* Page Size 512b, 2k, 4k */ +#define CSOR_NAND_PGS_MASK 0x0018 +#define CSOR_NAND_PGS_SHIFT16 +#define CSOR_NAND_PGS_512 0x +#define CSOR_NAND_PGS_2K 0x0008 +#define CSOR_NAND_PGS_4K 0x0010 +/* Spare region Size */ +#define CSOR_NAND_SPRZ_MASK0xE000 +#define CSOR_NAND_SPRZ_SHIFT 13 +#define CSOR_NAND_SPRZ_16 0x +#define CSOR_NAND_SPRZ_64 0x2000 +#define CSOR_NAND_SPRZ_128 0x4000 +#define CSOR_NAND_SPR
[PATCH 2/2] NAND Machine support for Integrated Flash Controller
From: Liu Shuo Integrated Flash Controller(IFC) can be used to hook NAND Flash chips using NAND Flash Machine available on it. Signed-off-by: Scott Wood Signed-off-by: Li Yang Signed-off-by: Liu Shuo --- drivers/mtd/nand/Kconfig| 10 + drivers/mtd/nand/Makefile |1 + drivers/mtd/nand/fsl_ifc_nand.c | 1076 +++ 3 files changed, 1087 insertions(+), 0 deletions(-) create mode 100644 drivers/mtd/nand/fsl_ifc_nand.c diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig index 4c34252..126d9cc 100644 --- a/drivers/mtd/nand/Kconfig +++ b/drivers/mtd/nand/Kconfig @@ -456,6 +456,16 @@ config MTD_NAND_FSL_ELBC Enabling this option will enable you to use this to control external NAND devices. +config MTD_NAND_FSL_IFC + tristate "NAND support for Freescale IFC controller" + depends on MTD_NAND && FSL_SOC + select FSL_IFC + help + Various Freescale chips e.g P1010, include a NAND Flash machine + with built-in hardware ECC capabilities. + Enabling this option will enable you to use this to control + external NAND devices. + config MTD_NAND_FSL_UPM tristate "Support for NAND on Freescale UPM" depends on PPC_83xx || PPC_85xx diff --git a/drivers/mtd/nand/Makefile b/drivers/mtd/nand/Makefile index 5745d83..3094131 100644 --- a/drivers/mtd/nand/Makefile +++ b/drivers/mtd/nand/Makefile @@ -38,6 +38,7 @@ obj-$(CONFIG_MTD_ALAUDA) += alauda.o obj-$(CONFIG_MTD_NAND_PASEMI) += pasemi_nand.o obj-$(CONFIG_MTD_NAND_ORION) += orion_nand.o obj-$(CONFIG_MTD_NAND_FSL_ELBC)+= fsl_elbc_nand.o +obj-$(CONFIG_MTD_NAND_FSL_IFC) += fsl_ifc_nand.o obj-$(CONFIG_MTD_NAND_FSL_UPM) += fsl_upm.o obj-$(CONFIG_MTD_NAND_SH_FLCTL)+= sh_flctl.o obj-$(CONFIG_MTD_NAND_MXC) += mxc_nand.o diff --git a/drivers/mtd/nand/fsl_ifc_nand.c b/drivers/mtd/nand/fsl_ifc_nand.c new file mode 100644 index 000..2c9116c --- /dev/null +++ b/drivers/mtd/nand/fsl_ifc_nand.c @@ -0,0 +1,1076 @@ +/* + * Freescale Integrated Flash Controller NAND driver + * + * Copyright 2011 Freescale Semiconductor, Inc + * + * Author: Dipen Dudhat + * + * 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 + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define ERR_BYTE 0xFF /* Value returned for read + bytes when read failed */ +#define IFC_TIMEOUT_MSECS 500 /* Maximum number of mSecs to wait + for IFC NAND Machine*/ + +struct fsl_ifc_ctrl; + +/* mtd information per set */ +struct fsl_ifc_mtd { + struct mtd_info mtd; + struct nand_chip chip; + struct fsl_ifc_ctrl *ctrl; + + struct device *dev; + int bank; /* Chip select bank number */ + unsigned int bufnum_mask; /* bufnum = page & bufnum_mask */ + u8 __iomem *vbase; /* Chip select base virtual address */ +}; + +/* overview of the fsl ifc controller */ +struct fsl_ifc_nand_ctrl { + struct nand_hw_control controller; + struct fsl_ifc_mtd *chips[FSL_IFC_BANK_COUNT]; + + u8 __iomem *addr; /* Address of assigned IFC buffer */ + unsigned int page; /* Last page written to / read from */ + unsigned int read_bytes;/* Number of bytes read during command */ + unsigned int column;/* Saved column from SEQIN */ + unsigned int index; /* Pointer to next byte to 'read' */ + unsigned int oob; /* Non zero if operating on OOB data*/ + unsigned int eccread; /* Non zero for a full-page ECC read*/ + unsigned int counter; /* counter for the initializations */ +}; + +static struct fsl_ifc_nand_ctrl *ifc_nand_ctrl; + +/* 512-byte page with 4-bit ECC, 8-bit */ +static struct nand_ecclayout oob_512_8bit_ecc4 = { + .eccbytes = 8, + .eccpos = {8, 9, 10, 11, 12, 13, 14, 15}, + .oobfree = { {0, 5}, {6, 2} }, +}; + +/* 512-byte page with 4-bit ECC, 16-bit */ +static struct nand_ecclayout oob_512_16bit_ecc4 = { + .eccbytes = 8, + .eccpos = {8, 9,
Re: powerpc 476, Little-endian, pte fault
On Mon, 2011-10-31 at 20:49 +1100, Michael Neuling wrote: > > I have built a cross compiler for ppc440 in little endian mode and > > using it to build the kernel. > > > > Yes i am running Linux in Little-Endian. This is the first user space > > process. I wrote the below program and running it as init from > > /sbin/init. I have also set the permissions with chmod +s. > > > > main() > > { > > > > while(1){ > > printf("hello world"); > > sleep(1); > > } > > } > > Does libc even support little endian on PPC? Ian did a port a while back for uClibc, is that at least partially based on it ? > > I have attached the patch. > > This is a pretty huge patch: > > 115 files changed, 44479 insertions(+), 7398 deletions(-) > > It seems to include a new platform as well as a bunch of unrelated junk. > > I suggest you need to break this down into something more digestible. > Like remove all the junk in the patch. Then add the support for the new > platform (invader? platform). Then start looking at little endian. > Unless you do this, it's unlikely anyone here is going to be able to > help. > > When you get to the little endian work, you might want to take a look at > this patch series from Ian Munsie: > > http://lists.ozlabs.org/pipermail/linuxppc-dev/2010-October/086165.html Right, the new patch should be if possible based on Ian's series or at least a cleaned / rebased variant of it. Then split in bits so we can review it properly. Cheers, Ben. > Mikey > ___ > 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
Re: [RFC][PATCH 1/2] uio: allow drivers to override the pgprot for mmap
On Oct 29, 2011, at 1:38 AM, Greg KH wrote: > On Fri, Oct 28, 2011 at 11:48:12PM +0200, Hans J. Koch wrote: >> On Fri, Oct 28, 2011 at 10:50:29AM -0500, Kumar Gala wrote: >>> For some devices, the default behavior of pgprot_noncached() is not >>> appropriate for all of its mappable regions. This provides a means for >>> the kernel side of the UIO driver to override the flags without having >>> to implement its own full mmap callback. >> >> Thanks for also providing an example driver showing the use of this. >> You should also post this driver in a mainline-ready version, I'm a bit >> uncomfortable with adding a new function pointer without having any users. > > I'm more than "uncomfortable", I'll refuse to take any such patch unless > there is a in-kernel user, otherwise it makes no sense to add the > pointer at all. > > thanks, > > greg k-h I'm in agreement with this view. I wanted to post this to make sure the direction we took was ok so when the upstream driver is posted this patch / change isn't a concern. - k ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
Re: [1/4] powerpc: Revert show_regs() define for readability
On Oct 28, 2011, at 2:40 PM, Jimi Xenidis wrote: > > On Oct 5, 2011, at 9:53 PM, Kumar Gala wrote: > >> We had an existing ifdef for 4xx & BOOKE processors that got changed to >> CONFIG_PPC_ADV_DEBUG_REGS. The define has nothing to do with >> CONFIG_PPC_ADV_DEBUG_REGS. The define really should be: >> >> #if defined(CONFIG_4xx) || defined(CONFIG_BOOKE) >> >> and not >> >> #ifdef CONFIG_PPC_ADV_DEBUG_REGS >> >> Signed-off-by: Kumar Gala >> >> --- >> arch/powerpc/kernel/process.c |2 +- >> 1 files changed, 1 insertions(+), 1 deletions(-) >> >> diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c >> index 8f53954..a1b5981 100644 >> --- a/arch/powerpc/kernel/process.c >> +++ b/arch/powerpc/kernel/process.c >> @@ -657,7 +657,7 @@ void show_regs(struct pt_regs * regs) >> if ((regs->trap != 0xc00) && cpu_has_feature(CPU_FTR_CFAR)) >> printk("CFAR: "REG"\n", regs->orig_gpr3); >> if (trap == 0x300 || trap == 0x600) >> -#ifdef CONFIG_PPC_ADV_DEBUG_REGS >> +#if defined(CONFIG_4xx) || defined(CONFIG_BOOKE) >> printk("DEAR: "REG", ESR: "REG"\n", regs->dar, regs->dsisr); > > I'll be needing "|| defined(CONFIG_PPC_BOOK3E)" added to this please. > -jx Under what platform is CONFIG_PPC_BOOK3E set and CONFIG_BOOKE is not? - k ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
Re: RFC: ESR_I/DLK processing
On Oct 28, 2011, at 3:43 PM, Jimi Xenidis wrote: > arch/powerpc/kernel/head_fsl_booke.S has the following code: >> /* Data Storage Interrupt */ >> START_EXCEPTION(DataStorage) >> NORMAL_EXCEPTION_PROLOG >> mfspr r5,SPRN_ESR /* Grab the ESR, save it, pass arg3 */ >> stw r5,_ESR(r11) >> mfspr r4,SPRN_DEAR/* Grab the DEAR, save it, pass arg2 */ >> andis. r10,r5,(ESR_ILK|ESR_DLK)@h >> bne 1f >> EXC_XFER_EE_LITE(0x0300, handle_page_fault) >> 1: >> addir3,r1,STACK_FRAME_OVERHEAD >> EXC_XFER_EE_LITE(0x0300, CacheLockingException) > > > I need something similar for A2 (and all book3e) and was wondering, why this > isn't just: > >> diff --git a/arch/powerpc/mm/fault.c b/arch/powerpc/mm/fault.c >> index 88abe70..8451822 100644 >> --- a/arch/powerpc/mm/fault.c >> +++ b/arch/powerpc/mm/fault.c >> @@ -159,6 +159,14 @@ int __kprobes do_page_fault(struct pt_regs *regs, >> unsigned long address, >> } >> #endif >> >> +#ifdef CONFIG_PPC_BOOK3E >> +if (error_code & (ESR_DLK|ESR_ILK)) { >> +/* detect that this is a privileged op and SIGILL */ >> +_exception(SIGILL, regs, ILL_PRVOPC, regs->nip); >> +return 0; >> +} >> +#endif >> + >> if (notify_page_fault(regs)) >> return 0; > > Its not like this need to be fast or anything. > I'd be happy to submit a patch that adds to fault.c and removed the I/DLK > processing from head_fsl_booke.S > > Thoughts? > -jx Probably because at one point in time DSI had a fast path handling for us. I've got no issues w/the proposed patch, just remember to mixup the CONFIG_PPC_BOOK3E as we don't define that in 32-bit fsl-booke - k ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
Re: [4/4] powerpc/booke: Re-organize debug code
On Oct 28, 2011, at 2:37 PM, Jimi Xenidis wrote: > > On Oct 5, 2011, at 9:53 PM, Kumar Gala wrote: > >> * set_dabr/do_dabr are no longer used when CNFIG_PPC_ADV_DEBUG_REGS is set >> refactor code a bit such that we only build the dabr code for >> !CONFIG_PPC_ADV_DEBUG_REGS and removed some CONFIG_PPC_ADV_DEBUG_REGS >> code in set_dabr that would never get built. >> >> * Move do_send_trap into traps.c as its only used there >> >> Signed-off-by: Kumar Gala >> >> --- >> arch/powerpc/include/asm/system.h |5 +-- >> arch/powerpc/kernel/process.c | 97 +--- >> arch/powerpc/kernel/traps.c | 17 +++ >> 3 files changed, 53 insertions(+), 66 deletions(-) >> >> diff --git a/arch/powerpc/include/asm/system.h >> b/arch/powerpc/include/asm/system.h >> index e30a13d..1dc5d9c 100644 >> --- a/arch/powerpc/include/asm/system.h >> +++ b/arch/powerpc/include/asm/system.h >> @@ -111,11 +111,8 @@ static inline int debugger_dabr_match(struct pt_regs >> *regs) { return 0; } >> static inline int debugger_fault_handler(struct pt_regs *regs) { return 0; } >> #endif >> >> +#ifndef CONFIG_PPC_ADV_DEBUG_REGS >> extern int set_dabr(unsigned long dabr); >> -#ifdef CONFIG_PPC_ADV_DEBUG_REGS >> -extern void do_send_trap(struct pt_regs *regs, unsigned long address, >> - unsigned long error_code, int signal_code, int brkpt); >> -#else > > > This part of the patch breaks xmon.c > Naively I simply wrapped the xmon call: > > diff --git a/arch/powerpc/xmon/xmon.c b/arch/powerpc/xmon/xmon.c > index f08836a..b5911b2 100644 > --- a/arch/powerpc/xmon/xmon.c > +++ b/arch/powerpc/xmon/xmon.c > @@ -738,8 +738,10 @@ static void insert_bpts(void) > > static void insert_cpu_bpts(void) > { > +#ifndef CONFIG_PPC_ADV_DEBUG_REGS > if (dabr.enabled) > set_dabr(dabr.address | (dabr.enabled & 7)); > +#endif > if (iabr && cpu_has_feature(CPU_FTR_IABR)) > mtspr(SPRN_IABR, iabr->address >| (iabr->enabled & (BP_IABR|BP_IABR_TE))); > @@ -767,7 +769,9 @@ static void remove_bpts(void) > > static void remove_cpu_bpts(void) > { > +#ifndef CONFIG_PPC_ADV_DEBUG_REGS > set_dabr(0); > +#endif > if (cpu_has_feature(CPU_FTR_IABR)) > mtspr(SPRN_IABR, 0); > } Shouldn't all of these functions be #ifndef'd out as we don't support cpu_bpts on book-e parts in xmon code today? > > -JX > > >> extern void do_dabr(struct pt_regs *regs, unsigned long address, >> unsigned long error_code); >> #endif >> diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c >> index 269a309..989e574 100644 >> --- a/arch/powerpc/kernel/process.c >> +++ b/arch/powerpc/kernel/process.c >> @@ -251,50 +251,6 @@ void discard_lazy_cpu_state(void) >> #endif /* CONFIG_SMP */ >> >> #ifdef CONFIG_PPC_ADV_DEBUG_REGS >> -void do_send_trap(struct pt_regs *regs, unsigned long address, >> - unsigned long error_code, int signal_code, int breakpt) >> -{ >> -siginfo_t info; >> - >> -if (notify_die(DIE_DABR_MATCH, "dabr_match", regs, error_code, >> -11, SIGSEGV) == NOTIFY_STOP) >> -return; >> - >> -/* Deliver the signal to userspace */ >> -info.si_signo = SIGTRAP; >> -info.si_errno = breakpt;/* breakpoint or watchpoint id */ >> -info.si_code = signal_code; >> -info.si_addr = (void __user *)address; >> -force_sig_info(SIGTRAP, &info, current); >> -} >> -#else /* !CONFIG_PPC_ADV_DEBUG_REGS */ >> -void do_dabr(struct pt_regs *regs, unsigned long address, >> -unsigned long error_code) >> -{ >> -siginfo_t info; >> - >> -if (notify_die(DIE_DABR_MATCH, "dabr_match", regs, error_code, >> -11, SIGSEGV) == NOTIFY_STOP) >> -return; >> - >> -if (debugger_dabr_match(regs)) >> -return; >> - >> -/* Clear the DABR */ >> -set_dabr(0); >> - >> -/* Deliver the signal to userspace */ >> -info.si_signo = SIGTRAP; >> -info.si_errno = 0; >> -info.si_code = TRAP_HWBKPT; >> -info.si_addr = (void __user *)address; >> -force_sig_info(SIGTRAP, &info, current); >> -} >> -#endif /* CONFIG_PPC_ADV_DEBUG_REGS */ >> - >> -static DEFINE_PER_CPU(unsigned long, current_dabr); >> - >> -#ifdef CONFIG_PPC_ADV_DEBUG_REGS >> /* >> * Set the debug registers back to their default "safe" values. >> */ >> @@ -357,16 +313,7 @@ static void switch_booke_debug_regs(struct >> thread_struct *new_thread) >> prime_debug_regs(new_thread); >> } >> #else/* !CONFIG_PPC_ADV_DEBUG_REGS */ >> -#ifndef CONFIG_HAVE_HW_BREAKPOINT >> -static void set_debug_reg_defaults(struct thread_struct *thread) >> -{ >> -if (thread->dabr) { >> -thread->dabr = 0; >> -set_dabr(0); >> -} >> -} >> -#endif /* !CONFIG_HAVE_HW_BREAKPOINT */ >> -#endif /* CONFIG_PPC_ADV_DEBUG_REGS */ >> +static DEFINE_PER_CPU(unsigned long, curre
Re: powerpc 476, Little-endian, pte fault
This is not the first user-space instruction. While executing this process kernel has added two TLB entries with TID(process id) 1. while trying to map 0x10fc it is raising pte faults . Santosh Kumar .A Vision without Action is a daydream... Action without Vision is a nightmare... On 31 October 2011 12:05, Santosh Kumar wrote: > I have built a cross compiler for ppc440 in little endian mode and > using it to build the kernel. > > Yes i am running Linux in Little-Endian. This is the first user space > process. I wrote the below program and running it as init from > /sbin/init. I have also set the permissions with chmod +s. > > main() > { > > while(1){ > printf("hello world"); > sleep(1); > } > } > > I have attached the patch. > > - > Santosh Kumar .A > > Vision without Action is a daydream... Action without Vision is a nightmare... > > > > On 31 October 2011 11:21, Michael Neuling wrote: >> Adding linuxppc-dev list to the CC >> >>> KERNEL: linux 2.6.39.4 >>> POWERPC: 476, little endian. >>> >>> I am trying to get linux 2.6.39.4 up on PPC 476 i have done done >>> Big-endian to little endian Changes in: >> >> Can you explain what you are trying to do in more detail? What does "i >> have done Big-endian to little endian Changes" mean? >> >>> 1) bitops header file. >>> 2) while reading the device tree. >>> 3) the PTE read/computed in head_32.S >>> 4) added E bit in the TLB entries. >>> >>> with all the above changes the kernel_init is done but and inited is >>> mounted. >> >> Can you post your patch? >> >> Are you trying to boot the kernel in little endian or just run userspace >> in little endian? >> >>> But while spawning init process the kernel continuously hits pte >>> faults at address 0x10fc and never comes out. Please let me know >>> where i should be looking into. >> >> Is this the very first userspace instruction? >> >> Mikey >> >> > ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[RFC PATCH v3 00/10] fadump: Firmware-assisted dump support for Powerpc.
Hi All, Please find the version 3 of the patchset that implements firmware-assisted dump mechanism to capture kernel crash dump for Powerpc architecture. The firmware-assisted dump is a robust mechanism to get reliable kernel crash dump with assistance from firmware. This approach does not use kexec, instead firmware assists in booting the kdump kernel while preserving memory contents. Changes in v3: - - Re-factored the implementation to work with kdump service start/stop. Introduced fadump_registered sysfs control file which will be used by kdump init scripts to start/stop firmware assisted dump. echo 1 to /sys/kernel/fadump_registered file for fadump registration and echo 0 to /sys/kernel/fadump_registered file for fadump un-registration. - Introduced the locking mechanism to handle simultaneous writes to sysfs control files fadump_registered and fadump_release_mem Affected patches are: 01/10, 03/10, 08/10. Changes in v2: - patch 01/10: - Modified the documentation to reflect the change of fadump_region file under debugfs filesystem. patch 02/10: - Modified to use standard pr_debug() macro. - Modified early_init_dt_scan_fw_dump() to get the size of "ibm,configure-kernel-dump-sizes" property and use it to iterate through an array of dump sections. - Introduced boot option 'fadump_reserve_mem=' to let user specify the fadump boot memory to be reserved. patch 03/10: - Removed few debug print statements. - Moved the setup_fadump() call from setup_system() and now calling it subsys_initcall. - Moved fadump_region attribute under debugfs. - Clear the TCE entries if firmware assisted dump is active. patch 05/10: - Moved the crash_fadump() invocation from generic code to panic notifier. - Introduced cpu_notes_buf_alloc() function to allocate cpu notes buffer using get_free_pages(). patch 08/10: - Introduced cpu_notes_buf_free() function to free memory allocated for cpu notes buffer. The most of the code implementation has been adapted from phyp assisted dump implementation written by Linas Vepstas and Manish Ahuja. The first patch is a documentation that talks about firmware-assisted dump mechanism, implementation details and TODO list. I have tested the patches on following system configuration: 1. LPAR on Power6 with 4GB RAM and 8 CPUs 2. LPAR on Power7 with 2GB RAM and 20 CPUs 3. LPAR on Power7 with 1TB RAM and 896 CPUs These patches cleanly apply on commit c3b92c878 in linux-2.6 git tree. Please review the patchset and let me know your comments. Thanks, -Mahesh. --- Mahesh Salgaonkar (10): fadump: Add documentation for firmware-assisted dump. fadump: Reserve the memory for firmware assisted dump. fadump: Register for firmware assisted dump. fadump: Initialize elfcore header and add PT_LOAD program headers. fadump: Convert firmware-assisted cpu state dump data into elf notes. fadump: Add PT_NOTE program header for vmcoreinfo fadump: Introduce cleanup routine to invalidate /proc/vmcore. fadump: Invalidate registration and release reserved memory for general use. fadump: Invalidate the fadump registration during machine shutdown. fadump: Introduce config option for firmware assisted dump feature Documentation/powerpc/firmware-assisted-dump.txt | 262 arch/powerpc/Kconfig | 13 arch/powerpc/include/asm/fadump.h| 205 arch/powerpc/kernel/Makefile |1 arch/powerpc/kernel/fadump.c | 1284 ++ arch/powerpc/kernel/iommu.c |8 arch/powerpc/kernel/prom.c | 15 arch/powerpc/kernel/setup-common.c | 16 arch/powerpc/kernel/traps.c |5 arch/powerpc/mm/hash_utils_64.c | 11 fs/proc/vmcore.c | 23 include/linux/crash_dump.h |1 include/linux/memblock.h |1 kernel/crash_dump.c | 33 + 14 files changed, 1876 insertions(+), 2 deletions(-) create mode 100644 Documentation/powerpc/firmware-assisted-dump.txt create mode 100644 arch/powerpc/include/asm/fadump.h create mode 100644 arch/powerpc/kernel/fadump.c -- Signature ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[RFC PATCH v3 01/10] fadump: Add documentation for firmware-assisted dump.
From: Mahesh Salgaonkar Documentation for firmware-assisted dump. This document is based on the original documentation written for phyp assisted dump by Linas Vepstas and Manish Ahuja, with few changes to reflect the current implementation. Change in v3: - Modified the documentation to reflect introdunction of fadump_registered sysfs file and few minor changes. Change in v2: - Modified the documentation to reflect the change of fadump_region file under debugfs filesystem. Signed-off-by: Mahesh Salgaonkar --- Documentation/powerpc/firmware-assisted-dump.txt | 262 ++ 1 files changed, 262 insertions(+), 0 deletions(-) create mode 100644 Documentation/powerpc/firmware-assisted-dump.txt diff --git a/Documentation/powerpc/firmware-assisted-dump.txt b/Documentation/powerpc/firmware-assisted-dump.txt new file mode 100644 index 000..ba6724a --- /dev/null +++ b/Documentation/powerpc/firmware-assisted-dump.txt @@ -0,0 +1,262 @@ + + Firmware-Assisted Dump + + July 2011 + +The goal of firmware-assisted dump is to enable the dump of +a crashed system, and to do so from a fully-reset system, and +to minimize the total elapsed time until the system is back +in production use. + +As compared to kdump or other strategies, firmware-assisted +dump offers several strong, practical advantages: + +-- Unlike kdump, the system has been reset, and loaded + with a fresh copy of the kernel. In particular, + PCI and I/O devices have been reinitialized and are + in a clean, consistent state. +-- Once the dump is copied out, the memory that held the dump + is immediately available to the running kernel. A further + reboot isn't required. + +The above can only be accomplished by coordination with, +and assistance from the Power firmware. The procedure is +as follows: + +-- The first kernel registers the sections of memory with the + Power firmware for dump preservation during OS initialization. + This registered sections of memory is reserved by the first + kernel during early boot. + +-- When a system crashes, the Power firmware will save + the low memory (boot memory of size larger of 5% of system RAM + or 256MB) of RAM to a previously registered save region. It + will also save system registers, and hardware PTE's. + + NOTE: The term 'boot memory' means size of the low memory chunk + that is required for a kernel to boot successfully when + booted with restricted memory. By default, the boot memory + size will be calculated to larger of 5% of system RAM or + 256MB. Alternatively, user can also specify boot memory + size through boot parameter 'fadump_reserve_mem=' which + will override the default calculated size. + +-- After the low memory (boot memory) area has been saved, the + firmware will reset PCI and other hardware state. It will + *not* clear the RAM. It will then launch the bootloader, as + normal. + +-- The freshly booted kernel will notice that there is a new + node (ibm,dump-kernel) in the device tree, indicating that + there is crash data available from a previous boot. During + the early boot OS will reserve rest of the memory above + boot memory size effectively booting with restricted memory + size. This will make sure that the second kernel will not + touch any of the dump memory area. + +-- Userspace tools will read /proc/vmcore to obtain the contents + of memory, which holds the previous crashed kernel dump in ELF + format. The userspace tools may copy this info to disk, or + network, nas, san, iscsi, etc. as desired. + +-- Once the userspace tool is done saving dump, it will echo + '1' to /sys/kernel/fadump_release_mem to release the reserved + memory back to general use, except the memory required for + next firmware-assisted dump registration. + + e.g. + # echo 1 > /sys/kernel/fadump_release_mem + +Please note that the firmware-assisted dump feature +is only available on Power6 and above systems with recent +firmware versions. + +Implementation details: +-- + +During boot, a check is made to see if firmware supports +this feature on that particular machine. If it does, then +we check to see if an active dump is waiting for us. If yes +then everything but boot memory size of RAM is reserved during +early boot (See Fig. 2). This area is released once we collect a +dump from user land scripts (kdump scripts) that are run. If +there is dump data, then the /sys/kernel/fadump_release_mem +file is created, and the reserved memory is held. + +If there is no waiting dump data, then only the memory required +to hold CPU state, HPTE region, boot memory dump and elfcore +header, is reserved at the top of memory (see Fig. 1). This area +is *not* released: this region will be kept permanently reserved, +so that it can act as a receptacle for a copy of the boot memory +content i
[RFC PATCH v3 02/10] fadump: Reserve the memory for firmware assisted dump.
From: Mahesh Salgaonkar Reserve the memory during early boot to preserve CPU state data, HPTE region and RMR region data in case of kernel crash. At the time of crash, powerpc firmware will store CPU state data, HPTE region data and move RMR region data to the reserved memory area. If the firmware-assisted dump fails to reserve the memory, then fallback to existing kexec-based kdump. The most of the code implementation to reserve memory has been adapted from phyp assisted dump implementation written by Linas Vepstas and Manish Ahuja Change in v2: - Modified to use standard pr_debug() macro. - Modified early_init_dt_scan_fw_dump() to get the size of "ibm,configure-kernel-dump-sizes" property and use it to iterate through an array of dump sections. - Introduced boot option 'fadump_reserve_mem=' to let user specify the fadump boot memory to be reserved. Signed-off-by: Mahesh Salgaonkar --- arch/powerpc/include/asm/fadump.h | 65 ++ arch/powerpc/kernel/Makefile |1 arch/powerpc/kernel/fadump.c | 250 + arch/powerpc/kernel/prom.c| 15 ++ 4 files changed, 330 insertions(+), 1 deletions(-) create mode 100644 arch/powerpc/include/asm/fadump.h create mode 100644 arch/powerpc/kernel/fadump.c diff --git a/arch/powerpc/include/asm/fadump.h b/arch/powerpc/include/asm/fadump.h new file mode 100644 index 000..0b040c1 --- /dev/null +++ b/arch/powerpc/include/asm/fadump.h @@ -0,0 +1,65 @@ +/* + * Firmware Assisted dump header file. + * + * 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 2011 IBM Corporation + * Author: Mahesh Salgaonkar + */ + +#ifndef __PPC64_FA_DUMP_H__ +#define __PPC64_FA_DUMP_H__ + +#ifdef CONFIG_FA_DUMP + +/* + * The RMR region will be saved for later dumping when kernel crashes. + * Set this to 256MB. + */ +#define RMR_START 0x0 +#define RMR_END(ppc64_rma_size) + +/* + * On some Power systems where RMO is 128MB, it still requires minimum of + * 256MB for kernel to boot successfully. + */ +#define MIN_BOOT_MEM ((RMR_END < (0x1UL << 28)) ? (0x1UL << 28) : RMR_END) + +/* Firmware provided dump sections */ +#define FADUMP_CPU_STATE_DATA 0x0001 +#define FADUMP_HPTE_REGION 0x0002 +#define FADUMP_REAL_MODE_REGION0x0011 + +struct fw_dump { + unsigned long cpu_state_data_size; + unsigned long hpte_region_size; + unsigned long boot_memory_size; + unsigned long reserve_dump_area_start; + unsigned long reserve_dump_area_size; + /* cmd line option during boot */ + unsigned long reserve_bootvar; + + int ibm_configure_kernel_dump; + + unsigned long fadump_enabled:1; + unsigned long fadump_supported:1; + unsigned long dump_active:1; +}; + +extern int early_init_dt_scan_fw_dump(unsigned long node, + const char *uname, int depth, void *data); +extern int fadump_reserve_mem(void); +#endif +#endif diff --git a/arch/powerpc/kernel/Makefile b/arch/powerpc/kernel/Makefile index ce4f7f1..59b549c 100644 --- a/arch/powerpc/kernel/Makefile +++ b/arch/powerpc/kernel/Makefile @@ -60,6 +60,7 @@ obj-$(CONFIG_IBMVIO) += vio.o obj-$(CONFIG_IBMEBUS) += ibmebus.o obj-$(CONFIG_GENERIC_TBSYNC) += smp-tbsync.o obj-$(CONFIG_CRASH_DUMP) += crash_dump.o +obj-$(CONFIG_FA_DUMP) += fadump.o ifeq ($(CONFIG_PPC32),y) obj-$(CONFIG_E500) += idle_e500.o endif diff --git a/arch/powerpc/kernel/fadump.c b/arch/powerpc/kernel/fadump.c new file mode 100644 index 000..05dffc0 --- /dev/null +++ b/arch/powerpc/kernel/fadump.c @@ -0,0 +1,250 @@ +/* + * Firmware Assisted dump: A robust mechanism to get reliable kernel crash + * dump with assistance from firmware. This approach does not use kexec, + * instead firmware assists in booting the kdump kernel while preserving + * memory contents. The most of the code implementation has been adapted + * from phyp assisted dump implementation written by Linas Vepstas and + * Manish Ahuja + * + * 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. +
[RFC PATCH v3 03/10] fadump: Register for firmware assisted dump.
From: Mahesh Salgaonkar This patch registers for firmware-assisted dump using rtas token ibm,configure-kernel-dump. During registration firmware is informed about the reserved area where it saves the CPU state data, HPTE table and contents of RMR region at the time of kernel crash. Apart from this, firmware also preserves the contents of entire partition memory even if it is not specified during registration. This patch also populates sysfs files under /sys/kernel to display fadump status and reserved memory regions. Change in v3: - Re-factored the implementation to work with kdump service start/stop. Introduce fadump_registered sysfs control file which will be used by kdump init scripts to start/stop firmware assisted dump. echo 1 to /sys/kernel/fadump_registered file for fadump registration and echo 0 to /sys/kernel/fadump_registered file for fadump un-registration. - Introduced the locking mechanism to handle simultaneous writes to /sys/kernel/fadump_registered file. Change in v2: - Removed few debug print statements. - Moved the setup_fadump() call from setup_system() and now calling it subsys_initcall. - Moved fadump_region attribute under debugfs. - Clear the TCE entries if firmware assisted dump is active. Signed-off-by: Mahesh Salgaonkar --- arch/powerpc/include/asm/fadump.h | 57 ++ arch/powerpc/kernel/fadump.c | 352 + arch/powerpc/kernel/iommu.c |8 + arch/powerpc/mm/hash_utils_64.c | 11 + 4 files changed, 424 insertions(+), 4 deletions(-) diff --git a/arch/powerpc/include/asm/fadump.h b/arch/powerpc/include/asm/fadump.h index 0b040c1..3b2f8cc 100644 --- a/arch/powerpc/include/asm/fadump.h +++ b/arch/powerpc/include/asm/fadump.h @@ -42,6 +42,58 @@ #define FADUMP_HPTE_REGION 0x0002 #define FADUMP_REAL_MODE_REGION0x0011 +/* Dump request flag */ +#define FADUMP_REQUEST_FLAG0x0001 + +/* FAD commands */ +#define FADUMP_REGISTER1 +#define FADUMP_UNREGISTER 2 +#define FADUMP_INVALIDATE 3 + +/* Kernel Dump section info */ +struct fadump_section { + u32 request_flag; + u16 source_data_type; + u16 error_flags; + u64 source_address; + u64 source_len; + u64 bytes_dumped; + u64 destination_address; +}; + +/* ibm,configure-kernel-dump header. */ +struct fadump_section_header { + u32 dump_format_version; + u16 dump_num_sections; + u16 dump_status_flag; + u32 offset_first_dump_section; + + /* Fields for disk dump option. */ + u32 dd_block_size; + u64 dd_block_offset; + u64 dd_num_blocks; + u32 dd_offset_disk_path; + + /* Maximum time allowed to prevent an automatic dump-reboot. */ + u32 max_time_auto; +}; + +/* + * Firmware Assisted dump memory structure. This structure is required for + * registering future kernel dump with power firmware through rtas call. + * + * No disk dump option. Hence disk dump path string section is not included. + */ +struct fadump_mem_struct { + struct fadump_section_headerheader; + + /* Kernel dump sections */ + struct fadump_section cpu_state_data; + struct fadump_section hpte_region; + struct fadump_section rmr_region; +}; + +/* Firmware-assisted dump configuration details. */ struct fw_dump { unsigned long cpu_state_data_size; unsigned long hpte_region_size; @@ -56,10 +108,15 @@ struct fw_dump { unsigned long fadump_enabled:1; unsigned long fadump_supported:1; unsigned long dump_active:1; + unsigned long dump_registered:1; }; extern int early_init_dt_scan_fw_dump(unsigned long node, const char *uname, int depth, void *data); extern int fadump_reserve_mem(void); +extern int setup_fadump(void); +extern int is_fadump_active(void); +#else /* CONFIG_FA_DUMP */ +static inline int is_fadump_active(void) { return 0; } #endif #endif diff --git a/arch/powerpc/kernel/fadump.c b/arch/powerpc/kernel/fadump.c index 05dffc0..ed38f86 100644 --- a/arch/powerpc/kernel/fadump.c +++ b/arch/powerpc/kernel/fadump.c @@ -29,6 +29,9 @@ #include #include +#include +#include +#include #include #include @@ -46,6 +49,10 @@ struct dump_section { } __packed; static struct fw_dump fw_dump; +static struct fadump_mem_struct fdm; +static const struct fadump_mem_struct *fdm_active; + +static DEFINE_MUTEX(fadump_mutex); /* Scan the Firmware Assisted dump configuration details. */ int __init early_init_dt_scan_fw_dump(unsigned long node, @@ -74,7 +81,8 @@ int __init early_init_dt_scan_fw_dump(unsigned long node, * The 'ibm,kernel-dump' rtas node is present only if there is * dump data waiting for us. */ - if (of_get_flat_dt_prop(node, "ibm,kernel-dump", NULL)) + fdm_active = of_get_flat_dt_prop(node, "ibm,kerne
[RFC PATCH v3 04/10] fadump: Initialize elfcore header and add PT_LOAD program headers.
From: Mahesh Salgaonkar Build the crash memory range list by traversing through system memory during the first kernel before we register for firmware-assisted dump. After the successful dump registration, initialize the elfcore header and populate PT_LOAD program headers with crash memory ranges. The elfcore header is saved in the scratch area within the reserved memory. The scratch area starts at the end of the memory reserved for saving RMR region contents. The scratch area contains fadump crash info structure that contains magic number for fadump validation and physical address where the eflcore header can be found. This structure will also be used to pass some important crash info data to the second kernel which will help second kernel to populate ELF core header with correct data before it gets exported through /proc/vmcore. Since the firmware preserves the entire partition memory at the time of crash the contents of the scratch area will be preserved till second kernel boot. NOTE: The current design implementation does not address a possibility of introducing additional fields (in future) to this structure without affecting compatibility. It's on TODO list to come up with better approach to address this. Reserved dump area start => +-+ | CPU state dump data| +-+ | HPTE region data | +-+ | RMR region data| Scratch area start => +-+ | fadump crash info structure { | | magic nummber | +--| elfcorehdr_addr | | | } | +> +-+ | ELF core header| Reserved dump area end => +-+ Signed-off-by: Mahesh Salgaonkar --- arch/powerpc/include/asm/fadump.h | 37 +++ arch/powerpc/kernel/fadump.c | 206 + include/linux/crash_dump.h|1 include/linux/memblock.h |1 kernel/crash_dump.c | 33 ++ 5 files changed, 276 insertions(+), 2 deletions(-) diff --git a/arch/powerpc/include/asm/fadump.h b/arch/powerpc/include/asm/fadump.h index 3b2f8cc..8c57cdd 100644 --- a/arch/powerpc/include/asm/fadump.h +++ b/arch/powerpc/include/asm/fadump.h @@ -50,6 +50,9 @@ #define FADUMP_UNREGISTER 2 #define FADUMP_INVALIDATE 3 +/* Dump status flag */ +#define FADUMP_ERROR_FLAG 0x2000 + /* Kernel Dump section info */ struct fadump_section { u32 request_flag; @@ -103,6 +106,7 @@ struct fw_dump { /* cmd line option during boot */ unsigned long reserve_bootvar; + unsigned long fadumphdr_addr; int ibm_configure_kernel_dump; unsigned long fadump_enabled:1; @@ -111,6 +115,39 @@ struct fw_dump { unsigned long dump_registered:1; }; +/* + * Copy the ascii values for first 8 characters from a string into u64 + * variable at their respective indexes. + * e.g. + * The string "FADMPINF" will be converted into 0x4641444d50494e46 + */ +static inline u64 str_to_u64(const char *str) +{ + u64 val = 0; + int i; + + for (i = 0; i < sizeof(val); i++) + val = (*str) ? (val << 8) | *str++ : val << 8; + return val; +} +#define STR_TO_HEX(x) str_to_u64(x) + +#define FADUMP_CRASH_INFO_MAGICSTR_TO_HEX("FADMPINF") + +/* fadump crash info structure */ +struct fadump_crash_info_header { + u64 magic_number; + u64 elfcorehdr_addr; +}; + +/* Crash memory ranges */ +#define INIT_CRASHMEM_RANGES (INIT_MEMBLOCK_REGIONS + 2) + +struct fad_crash_memory_ranges { + unsigned long long base; + unsigned long long size; +}; + extern int early_init_dt_scan_fw_dump(unsigned long node, const char *uname, int depth, void *data); extern int fadump_reserve_mem(void); diff --git a/arch/powerpc/kernel/fadump.c b/arch/powerpc/kernel/fadump.c index ed38f86..7bfa67b 100644 --- a/arch/powerpc/kernel/fadump.c +++ b/arch/powerpc/kernel/fadump.c @@ -32,6 +32,7 @@ #include #include #include +#include #include #include @@ -53,6 +54,8 @@ static struct fadump_mem_struct fdm; static const struct fadump_mem_struct *fdm_active; static DEFINE_MUTEX(fadump_mutex); +struct fad_crash_memory_ranges crash_memory_ranges[INIT_CRASHMEM_RANGES]; +int crash_mem_ranges; /* Scan the Firmware Assisted dump configuration details. */ int __init early_init_dt_scan_fw_dump(unsigned long node, @@ -239
[RFC PATCH v3 05/10] fadump: Convert firmware-assisted cpu state dump data into elf notes.
From: Mahesh Salgaonkar When registered for firmware assisted dump on powerpc, firmware preserves the registers for the active CPUs during a system crash. This patch reads the cpu register data stored in Firmware-assisted dump format (except for crashing cpu) and converts it into elf notes and updates the PT_NOTE program header accordingly. The exact register state for crashing cpu is saved to fadump crash info structure in scratch area during crash_fadump() and read during second kernel boot. Change in v2: - Moved the crash_fadump() invocation from generic code to panic notifier. - Introduced cpu_notes_buf_alloc() function to allocate cpu notes buffer using get_free_pages(). The reason is, with the use of subsys_initcall the setup_fadump() is now called after mem_init(). Hence use of get_free_pages() to allocate memory is more approriate then using memblock_alloc(). Signed-off-by: Mahesh Salgaonkar --- arch/powerpc/include/asm/fadump.h | 43 + arch/powerpc/kernel/fadump.c | 299 arch/powerpc/kernel/setup-common.c |8 + arch/powerpc/kernel/traps.c|5 + 4 files changed, 353 insertions(+), 2 deletions(-) diff --git a/arch/powerpc/include/asm/fadump.h b/arch/powerpc/include/asm/fadump.h index 8c57cdd..4a7d63e 100644 --- a/arch/powerpc/include/asm/fadump.h +++ b/arch/powerpc/include/asm/fadump.h @@ -53,6 +53,18 @@ /* Dump status flag */ #define FADUMP_ERROR_FLAG 0x2000 +#define FADUMP_CPU_ID_MASK ((1UL << 32) - 1) + +#define CPU_UNKNOWN(~((u32)0)) + +/* Utility macros */ +#define SKIP_TO_NEXT_CPU(reg_entry)\ +({ \ + while (reg_entry->reg_id != REG_ID("CPUEND")) \ + reg_entry++;\ + reg_entry++;\ +}) + /* Kernel Dump section info */ struct fadump_section { u32 request_flag; @@ -107,6 +119,9 @@ struct fw_dump { unsigned long reserve_bootvar; unsigned long fadumphdr_addr; + unsigned long cpu_notes_buf; + unsigned long cpu_notes_buf_size; + int ibm_configure_kernel_dump; unsigned long fadump_enabled:1; @@ -131,13 +146,40 @@ static inline u64 str_to_u64(const char *str) return val; } #define STR_TO_HEX(x) str_to_u64(x) +#define REG_ID(x) str_to_u64(x) #define FADUMP_CRASH_INFO_MAGICSTR_TO_HEX("FADMPINF") +#define REGSAVE_AREA_MAGIC STR_TO_HEX("REGSAVE") + +/* The firmware-assisted dump format. + * + * The register save area is an area in the partition's memory used to preserve + * the register contents (CPU state data) for the active CPUs during a firmware + * assisted dump. The dump format contains register save area header followed + * by register entries. Each list of registers for a CPU starts with + * "CPUSTRT" and ends with "CPUEND". + */ + +/* Register save area header. */ +struct fadump_reg_save_area_header { + u64 magic_number; + u32 version; + u32 num_cpu_offset; +}; + +/* Register entry. */ +struct fadump_reg_entry { + u64 reg_id; + u64 reg_value; +}; /* fadump crash info structure */ struct fadump_crash_info_header { u64 magic_number; u64 elfcorehdr_addr; + u32 crashing_cpu; + struct pt_regs regs; + struct cpumask cpu_online_mask; }; /* Crash memory ranges */ @@ -153,6 +195,7 @@ extern int early_init_dt_scan_fw_dump(unsigned long node, extern int fadump_reserve_mem(void); extern int setup_fadump(void); extern int is_fadump_active(void); +extern void crash_fadump(struct pt_regs *, const char *); #else /* CONFIG_FA_DUMP */ static inline int is_fadump_active(void) { return 0; } #endif diff --git a/arch/powerpc/kernel/fadump.c b/arch/powerpc/kernel/fadump.c index 7bfa67b..c0ecd6a 100644 --- a/arch/powerpc/kernel/fadump.c +++ b/arch/powerpc/kernel/fadump.c @@ -244,6 +244,7 @@ static unsigned long get_dump_area_size(void) size += fw_dump.boot_memory_size; size += sizeof(struct fadump_crash_info_header); size += sizeof(struct elfhdr); /* ELF core header.*/ + size += sizeof(struct elf_phdr); /* place holder for cpu notes */ /* Program headers for crash memory regions. */ size += sizeof(struct elf_phdr) * (memblock_num_regions(memory) + 2); @@ -397,6 +398,269 @@ static void register_fw_dump(struct fadump_mem_struct *fdm) } } +void crash_fadump(struct pt_regs *regs, const char *str) +{ + struct fadump_crash_info_header *fdh = NULL; + + if (!fw_dump.dump_registered || !fw_dump.fadumphdr_addr) + return; + + fdh = __va(fw_dump.fadumphdr_addr); + crashing_cpu = smp_processor_id(); + fdh->crashing_cpu = crashing_cpu; + crash_save_vmcoreinfo()
[RFC PATCH v3 07/10] fadump: Introduce cleanup routine to invalidate /proc/vmcore.
From: Mahesh Salgaonkar With the firmware-assisted dump support we don't require a reboot when we are in second kernel after crash. The second kernel after crash is a normal kernel boot and has knowledge about entire system RAM with the page tables initialized for entire system RAM. Hence once the dump is saved to disk, we can just release the reserved memory area for general use and continue with second kernel as production kernel. Hence when we release the reserved memory that contains dump data, the '/proc/vmcore' will not be valid anymore. Hence this patch introduces a cleanup routine that invalidates and removes the /proc/vmcore file. This routine will be invoked before we release the reserved dump memory area. Signed-off-by: Mahesh Salgaonkar --- fs/proc/vmcore.c | 23 +++ 1 files changed, 23 insertions(+), 0 deletions(-) diff --git a/fs/proc/vmcore.c b/fs/proc/vmcore.c index cd99bf5..fae5526 100644 --- a/fs/proc/vmcore.c +++ b/fs/proc/vmcore.c @@ -699,3 +699,26 @@ static int __init vmcore_init(void) return 0; } module_init(vmcore_init) + +/* Cleanup function for vmcore module. */ +void vmcore_cleanup(void) +{ + struct list_head *pos, *next; + + if (proc_vmcore) { + remove_proc_entry(proc_vmcore->name, proc_vmcore->parent); + proc_vmcore = NULL; + } + + /* clear the vmcore list. */ + list_for_each_safe(pos, next, &vmcore_list) { + struct vmcore *m; + + m = list_entry(pos, struct vmcore, list); + list_del(&m->list); + kfree(m); + } + kfree(elfcorebuf); + elfcorebuf = NULL; +} +EXPORT_SYMBOL_GPL(vmcore_cleanup); ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[RFC PATCH v3 08/10] fadump: Invalidate registration and release reserved memory for general use.
From: Mahesh Salgaonkar This patch introduces an sysfs interface '/sys/kernel/fadump_release_mem' to invalidate the last fadump registration, invalidate '/proc/vmcore', release the reserved memory for general use and re-register for future kernel dump. Once the dump is copied to the disk, the userspace tool will echo 1 to '/sys/kernel/fadump_release_mem'. Release the reserved memory region excluding the size of the memory required for future kernel dump registration. Change in v3: - Syncronize the fadump invalidation step to handle simultaneous writes to /sys/kernel/fadump_release_mem. Change in v2: - Introduced cpu_notes_buf_free() function to free memory allocated for cpu notes buffer. Signed-off-by: Mahesh Salgaonkar --- arch/powerpc/include/asm/fadump.h |3 + arch/powerpc/kernel/fadump.c | 170 - 2 files changed, 169 insertions(+), 4 deletions(-) diff --git a/arch/powerpc/include/asm/fadump.h b/arch/powerpc/include/asm/fadump.h index 4a7d63e..2d983e8 100644 --- a/arch/powerpc/include/asm/fadump.h +++ b/arch/powerpc/include/asm/fadump.h @@ -196,6 +196,9 @@ extern int fadump_reserve_mem(void); extern int setup_fadump(void); extern int is_fadump_active(void); extern void crash_fadump(struct pt_regs *, const char *); +extern void fadump_cleanup(void); + +extern void vmcore_cleanup(void); #else /* CONFIG_FA_DUMP */ static inline int is_fadump_active(void) { return 0; } #endif diff --git a/arch/powerpc/kernel/fadump.c b/arch/powerpc/kernel/fadump.c index 4d42fe5..ecdf81b 100644 --- a/arch/powerpc/kernel/fadump.c +++ b/arch/powerpc/kernel/fadump.c @@ -33,6 +33,8 @@ #include #include #include +#include +#include #include #include @@ -560,6 +562,19 @@ static void *cpu_notes_buf_alloc(unsigned long size) return vaddr; } +static void cpu_notes_buf_free(unsigned long vaddr, unsigned long size) +{ + struct page *page; + unsigned long order, count, i; + + order = get_order(size); + count = 1 << order; + page = virt_to_page(vaddr); + for (i = 0; i < count; i++) + ClearPageReserved(page + i); + __free_pages(page, order); +} + /* * Read CPU state dump data and convert it into ELF notes. * The CPU dump starts with magic number "REGSAVE". NumCpusOffset should be @@ -944,6 +959,131 @@ static int fadump_unregister_dump(struct fadump_mem_struct *fdm) return 0; } +static int fadump_invalidate_dump(struct fadump_mem_struct *fdm) +{ + int rc = 0; + unsigned int wait_time; + + pr_debug("Invalidating firmware-assisted dump registration\n"); + + /* TODO: Add upper time limit for the delay */ + do { + rc = rtas_call(fw_dump.ibm_configure_kernel_dump, 3, 1, NULL, + FADUMP_INVALIDATE, fdm, + sizeof(struct fadump_mem_struct)); + + wait_time = rtas_busy_delay_time(rc); + if (wait_time) + mdelay(wait_time); + } while (wait_time); + + if (rc) { + printk(KERN_ERR "Failed to invalidate firmware-assisted dump " + "rgistration. unexpected error(%d).\n", rc); + return rc; + } + fw_dump.dump_active = 0; + fdm_active = NULL; + return 0; +} + +void fadump_cleanup(void) +{ + /* Invalidate the registration only if dump is active. */ + if (fw_dump.dump_active) { + init_fadump_mem_struct(&fdm, + fdm_active->cpu_state_data.destination_address); + fadump_invalidate_dump(&fdm); + } +} + +/* + * Release the memory that was reserved in early boot to preserve the memory + * contents. The released memory will be available for general use. + */ +static void fadump_release_memory(unsigned long begin, unsigned long end) +{ + unsigned long addr; + unsigned long ra_start, ra_end; + + ra_start = fw_dump.reserve_dump_area_start; + ra_end = ra_start + fw_dump.reserve_dump_area_size; + + for (addr = begin; addr < end; addr += PAGE_SIZE) { + /* +* exclude the dump reserve area. Will reuse it for next +* fadump registration. +*/ + if (addr <= ra_end && ((addr + PAGE_SIZE) > ra_start)) + continue; + + ClearPageReserved(pfn_to_page(addr >> PAGE_SHIFT)); + init_page_count(pfn_to_page(addr >> PAGE_SHIFT)); + free_page((unsigned long)__va(addr)); + totalram_pages++; + } +} + +static void fadump_invalidate_release_mem(void) +{ + unsigned long reserved_area_start, reserved_area_end; + unsigned long destination_address; + + mutex_lock(&fadump_mutex); + if (!fw_dump.dump_active) { + mutex_unlock(&fadump_mutex); + return; + } + + destination_address = fdm_active->cpu_state_data.
[RFC PATCH v3 06/10] fadump: Add PT_NOTE program header for vmcoreinfo
From: Mahesh Salgaonkar Introduce a PT_NOTE program header that points to physical address of vmcoreinfo_note buffer declared in kernel/kexec.c. The vmcoreinfo note buffer is populated during crash_fadump() at the time of system crash. Signed-off-by: Mahesh Salgaonkar --- arch/powerpc/kernel/fadump.c | 29 + 1 files changed, 29 insertions(+), 0 deletions(-) diff --git a/arch/powerpc/kernel/fadump.c b/arch/powerpc/kernel/fadump.c index c0ecd6a..4d42fe5 100644 --- a/arch/powerpc/kernel/fadump.c +++ b/arch/powerpc/kernel/fadump.c @@ -773,6 +773,19 @@ static void setup_crash_memory_ranges(void) } } +/* + * If the given physical address falls within the boot memory region then + * return the relocated address that points to the dump region reserved + * for saving initial boot memory contents. + */ +static inline unsigned long relocate(unsigned long paddr) +{ + if (paddr > RMR_START && paddr < fw_dump.boot_memory_size) + return fdm.rmr_region.destination_address + paddr; + else + return paddr; +} + static int create_elfcore_headers(char *bufp) { struct elfhdr *elf; @@ -805,6 +818,22 @@ static int create_elfcore_headers(char *bufp) /* Increment number of program headers. */ (elf->e_phnum)++; + /* setup ELF PT_NOTE for vmcoreinfo */ + phdr = (struct elf_phdr *)bufp; + bufp += sizeof(struct elf_phdr); + phdr->p_type= PT_NOTE; + phdr->p_flags = 0; + phdr->p_vaddr = 0; + phdr->p_align = 0; + + phdr->p_paddr = relocate(paddr_vmcoreinfo_note()); + phdr->p_offset = phdr->p_paddr; + phdr->p_memsz = vmcoreinfo_max_size; + phdr->p_filesz = vmcoreinfo_max_size; + + /* Increment number of program headers. */ + (elf->e_phnum)++; + /* setup PT_LOAD sections. */ for (i = 0; i < crash_mem_ranges; i++) { ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[RFC PATCH v3 09/10] fadump: Invalidate the fadump registration during machine shutdown.
From: Mahesh Salgaonkar If dump is active during system reboot, shutdown or halt then invalidate the fadump registration as it does not get invalidated automatically. Signed-off-by: Mahesh Salgaonkar --- arch/powerpc/kernel/setup-common.c |8 1 files changed, 8 insertions(+), 0 deletions(-) diff --git a/arch/powerpc/kernel/setup-common.c b/arch/powerpc/kernel/setup-common.c index ce35aaf..67e5caa 100644 --- a/arch/powerpc/kernel/setup-common.c +++ b/arch/powerpc/kernel/setup-common.c @@ -110,6 +110,14 @@ EXPORT_SYMBOL(ppc_do_canonicalize_irqs); /* also used by kexec */ void machine_shutdown(void) { +#ifdef CONFIG_FA_DUMP + /* +* if fadump is active, cleanup the fadump registration before we +* shutdown. +*/ + fadump_cleanup(); +#endif + if (ppc_md.machine_shutdown) ppc_md.machine_shutdown(); } ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[RFC PATCH v3 10/10] fadump: Introduce config option for firmware assisted dump feature
From: Mahesh Salgaonkar This patch introduces a new config option CONFIG_FA_DUMP for firmware assisted dump feature on Powerpc (ppc64) architecture. Signed-off-by: Mahesh Salgaonkar --- arch/powerpc/Kconfig | 13 + 1 files changed, 13 insertions(+), 0 deletions(-) diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig index 6926b61..7ce773c 100644 --- a/arch/powerpc/Kconfig +++ b/arch/powerpc/Kconfig @@ -379,6 +379,19 @@ config PHYP_DUMP If unsure, say "N" +config FA_DUMP + bool "Firmware-assisted dump" + depends on PPC64 && PPC_RTAS && CRASH_DUMP + help + A robust mechanism to get reliable kernel crash dump with + assistance from firmware. This approach does not use kexec, + instead firmware assists in booting the kdump kernel + while preserving memory contents. Firmware-assisted dump + is meant to be a kdump replacement offering robustness and + speed not possible without system firmware assistance. + + If unsure, say "N" + config PPCBUG_NVRAM bool "Enable reading PPCBUG NVRAM during boot" if PPLUS || LOPEC default y if PPC_PREP ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
Re: [1/4] powerpc: Revert show_regs() define for readability
On Oct 31, 2011, at 9:18 AM, Kumar Gala wrote: > > On Oct 28, 2011, at 2:40 PM, Jimi Xenidis wrote: > >> >> On Oct 5, 2011, at 9:53 PM, Kumar Gala wrote: >> >>> We had an existing ifdef for 4xx & BOOKE processors that got changed to >>> CONFIG_PPC_ADV_DEBUG_REGS. The define has nothing to do with >>> CONFIG_PPC_ADV_DEBUG_REGS. The define really should be: >>> >>> #if defined(CONFIG_4xx) || defined(CONFIG_BOOKE) >>> >>> and not >>> >>> #ifdef CONFIG_PPC_ADV_DEBUG_REGS >>> >>> Signed-off-by: Kumar Gala >>> >>> --- >>> arch/powerpc/kernel/process.c |2 +- >>> 1 files changed, 1 insertions(+), 1 deletions(-) >>> >>> diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c >>> index 8f53954..a1b5981 100644 >>> --- a/arch/powerpc/kernel/process.c >>> +++ b/arch/powerpc/kernel/process.c >>> @@ -657,7 +657,7 @@ void show_regs(struct pt_regs * regs) >>> if ((regs->trap != 0xc00) && cpu_has_feature(CPU_FTR_CFAR)) >>> printk("CFAR: "REG"\n", regs->orig_gpr3); >>> if (trap == 0x300 || trap == 0x600) >>> -#ifdef CONFIG_PPC_ADV_DEBUG_REGS >>> +#if defined(CONFIG_4xx) || defined(CONFIG_BOOKE) >>> printk("DEAR: "REG", ESR: "REG"\n", regs->dar, regs->dsisr); >> >> I'll be needing "|| defined(CONFIG_PPC_BOOK3E)" added to this please. >> -jx > > Under what platform is CONFIG_PPC_BOOK3E set and CONFIG_BOOKE is not? this was a grep typo on my part. sorry. -jx > > - k > ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
Re: [4/4] powerpc/booke: Re-organize debug code
On Oct 31, 2011, at 9:21 AM, Kumar Gala wrote: > > On Oct 28, 2011, at 2:37 PM, Jimi Xenidis wrote: > >> >> On Oct 5, 2011, at 9:53 PM, Kumar Gala wrote: >> >>> * set_dabr/do_dabr are no longer used when CNFIG_PPC_ADV_DEBUG_REGS is set >>> refactor code a bit such that we only build the dabr code for >>> !CONFIG_PPC_ADV_DEBUG_REGS and removed some CONFIG_PPC_ADV_DEBUG_REGS >>> code in set_dabr that would never get built. >>> >>> * Move do_send_trap into traps.c as its only used there >>> >>> Signed-off-by: Kumar Gala >>> >>> --- >>> arch/powerpc/include/asm/system.h |5 +-- >>> arch/powerpc/kernel/process.c | 97 >>> +--- >>> arch/powerpc/kernel/traps.c | 17 +++ >>> 3 files changed, 53 insertions(+), 66 deletions(-) >>> >>> diff --git a/arch/powerpc/include/asm/system.h >>> b/arch/powerpc/include/asm/system.h >>> index e30a13d..1dc5d9c 100644 >>> --- a/arch/powerpc/include/asm/system.h >>> +++ b/arch/powerpc/include/asm/system.h >>> @@ -111,11 +111,8 @@ static inline int debugger_dabr_match(struct pt_regs >>> *regs) { return 0; } >>> static inline int debugger_fault_handler(struct pt_regs *regs) { return 0; } >>> #endif >>> >>> +#ifndef CONFIG_PPC_ADV_DEBUG_REGS >>> extern int set_dabr(unsigned long dabr); >>> -#ifdef CONFIG_PPC_ADV_DEBUG_REGS >>> -extern void do_send_trap(struct pt_regs *regs, unsigned long address, >>> -unsigned long error_code, int signal_code, int brkpt); >>> -#else >> >> >> This part of the patch breaks xmon.c >> Naively I simply wrapped the xmon call: >> >> diff --git a/arch/powerpc/xmon/xmon.c b/arch/powerpc/xmon/xmon.c >> index f08836a..b5911b2 100644 >> --- a/arch/powerpc/xmon/xmon.c >> +++ b/arch/powerpc/xmon/xmon.c >> @@ -738,8 +738,10 @@ static void insert_bpts(void) >> >> static void insert_cpu_bpts(void) >> { >> +#ifndef CONFIG_PPC_ADV_DEBUG_REGS >> if (dabr.enabled) >> set_dabr(dabr.address | (dabr.enabled & 7)); >> +#endif >> if (iabr && cpu_has_feature(CPU_FTR_IABR)) >> mtspr(SPRN_IABR, iabr->address >> | (iabr->enabled & (BP_IABR|BP_IABR_TE))); >> @@ -767,7 +769,9 @@ static void remove_bpts(void) >> >> static void remove_cpu_bpts(void) >> { >> +#ifndef CONFIG_PPC_ADV_DEBUG_REGS >> set_dabr(0); >> +#endif >> if (cpu_has_feature(CPU_FTR_IABR)) >> mtspr(SPRN_IABR, 0); >> } > > Shouldn't all of these functions be #ifndef'd out as we don't support > cpu_bpts on book-e parts in xmon code today? Well I guess this is one for benh, because I would have expected xmon to test and call ppc_md.dabr. Actually, should everyone be doing that? -jx > >> >> -JX >> >> >>> extern void do_dabr(struct pt_regs *regs, unsigned long address, >>> unsigned long error_code); >>> #endif >>> diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c >>> index 269a309..989e574 100644 >>> --- a/arch/powerpc/kernel/process.c >>> +++ b/arch/powerpc/kernel/process.c >>> @@ -251,50 +251,6 @@ void discard_lazy_cpu_state(void) >>> #endif /* CONFIG_SMP */ >>> >>> #ifdef CONFIG_PPC_ADV_DEBUG_REGS >>> -void do_send_trap(struct pt_regs *regs, unsigned long address, >>> - unsigned long error_code, int signal_code, int breakpt) >>> -{ >>> - siginfo_t info; >>> - >>> - if (notify_die(DIE_DABR_MATCH, "dabr_match", regs, error_code, >>> - 11, SIGSEGV) == NOTIFY_STOP) >>> - return; >>> - >>> - /* Deliver the signal to userspace */ >>> - info.si_signo = SIGTRAP; >>> - info.si_errno = breakpt;/* breakpoint or watchpoint id */ >>> - info.si_code = signal_code; >>> - info.si_addr = (void __user *)address; >>> - force_sig_info(SIGTRAP, &info, current); >>> -} >>> -#else /* !CONFIG_PPC_ADV_DEBUG_REGS */ >>> -void do_dabr(struct pt_regs *regs, unsigned long address, >>> - unsigned long error_code) >>> -{ >>> - siginfo_t info; >>> - >>> - if (notify_die(DIE_DABR_MATCH, "dabr_match", regs, error_code, >>> - 11, SIGSEGV) == NOTIFY_STOP) >>> - return; >>> - >>> - if (debugger_dabr_match(regs)) >>> - return; >>> - >>> - /* Clear the DABR */ >>> - set_dabr(0); >>> - >>> - /* Deliver the signal to userspace */ >>> - info.si_signo = SIGTRAP; >>> - info.si_errno = 0; >>> - info.si_code = TRAP_HWBKPT; >>> - info.si_addr = (void __user *)address; >>> - force_sig_info(SIGTRAP, &info, current); >>> -} >>> -#endif /* CONFIG_PPC_ADV_DEBUG_REGS */ >>> - >>> -static DEFINE_PER_CPU(unsigned long, current_dabr); >>> - >>> -#ifdef CONFIG_PPC_ADV_DEBUG_REGS >>> /* >>> * Set the debug registers back to their default "safe" values. >>> */ >>> @@ -357,16 +313,7 @@ static void switch_booke_debug_regs(struct >>> thread_struct *new_thread) >>> prime_debug_regs(new_thread); >>> } >>> #else /* !CONFIG_PPC_ADV_DEBUG_REGS */ >>> -#ifndef CONFIG_HAVE_HW_BREAKPOINT >>> -static
[RFC PATCH 00/10] powerpc/mpic: General cleanup patch series
Hello, I've been tinkering with a series of patches to clean up the PowerPC MPIC/OpenPIC init recently as part of a new board port I'm working on. It's reached the point where I'd like some feedback on the general approach. The code itself hasn't been tested at all yet, and probably does not compile right now (though that is my next step). (Oh, actually, the first patch isn't really even about the MPIC code, it should probably be reviewed on its own; oh well...) Please let me know what you think. Cheers, Kyle Moffett -- Curious about my work on the Debian powerpcspe port? I'm keeping a blog here: http://pureperl.blogspot.com/ ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[RFC PATCH 01/10] powerpc/85xx: Move mpc85xx_smp_init() decl to a new "smp.h"
This removes a bunch of "extern" declarations and CONFIG_SMP ifdefs. Signed-off-by: Kyle Moffett Cc: Benjamin Herrenschmidt Cc: Paul Mackerras Cc: Kumar Gala --- arch/powerpc/platforms/85xx/corenet_ds.c |7 +-- arch/powerpc/platforms/85xx/mpc85xx_ds.c |6 +- arch/powerpc/platforms/85xx/mpc85xx_mds.c |7 +-- arch/powerpc/platforms/85xx/mpc85xx_rdb.c |7 +-- arch/powerpc/platforms/85xx/p1022_ds.c|7 +-- arch/powerpc/platforms/85xx/p1023_rds.c |5 + arch/powerpc/platforms/85xx/smp.c |1 + arch/powerpc/platforms/85xx/smp.h | 15 +++ arch/powerpc/platforms/85xx/xes_mpc85xx.c |6 +- 9 files changed, 23 insertions(+), 38 deletions(-) create mode 100644 arch/powerpc/platforms/85xx/smp.h diff --git a/arch/powerpc/platforms/85xx/corenet_ds.c b/arch/powerpc/platforms/85xx/corenet_ds.c index 802ad11..435074d 100644 --- a/arch/powerpc/platforms/85xx/corenet_ds.c +++ b/arch/powerpc/platforms/85xx/corenet_ds.c @@ -31,6 +31,7 @@ #include #include #include +#include "smp.h" void __init corenet_ds_pic_init(void) { @@ -65,10 +66,6 @@ void __init corenet_ds_pic_init(void) /* * Setup the architecture */ -#ifdef CONFIG_SMP -void __init mpc85xx_smp_init(void); -#endif - void __init corenet_ds_setup_arch(void) { #ifdef CONFIG_PCI @@ -77,9 +74,7 @@ void __init corenet_ds_setup_arch(void) #endif dma_addr_t max = 0x; -#ifdef CONFIG_SMP mpc85xx_smp_init(); -#endif #ifdef CONFIG_PCI for_each_node_by_type(np, "pci") { diff --git a/arch/powerpc/platforms/85xx/mpc85xx_ds.c b/arch/powerpc/platforms/85xx/mpc85xx_ds.c index 1b9a8cf..52d2a3e 100644 --- a/arch/powerpc/platforms/85xx/mpc85xx_ds.c +++ b/arch/powerpc/platforms/85xx/mpc85xx_ds.c @@ -35,6 +35,7 @@ #include #include +#include "smp.h" #undef DEBUG @@ -152,9 +153,6 @@ static int mpc85xx_exclude_device(struct pci_controller *hose, /* * Setup the architecture */ -#ifdef CONFIG_SMP -extern void __init mpc85xx_smp_init(void); -#endif static void __init mpc85xx_ds_setup_arch(void) { #ifdef CONFIG_PCI @@ -187,9 +185,7 @@ static void __init mpc85xx_ds_setup_arch(void) ppc_md.pci_exclude_device = mpc85xx_exclude_device; #endif -#ifdef CONFIG_SMP mpc85xx_smp_init(); -#endif #ifdef CONFIG_SWIOTLB if (memblock_end_of_DRAM() > max) { diff --git a/arch/powerpc/platforms/85xx/mpc85xx_mds.c b/arch/powerpc/platforms/85xx/mpc85xx_mds.c index 973b3f4..074be05 100644 --- a/arch/powerpc/platforms/85xx/mpc85xx_mds.c +++ b/arch/powerpc/platforms/85xx/mpc85xx_mds.c @@ -52,6 +52,7 @@ #include #include #include +#include "smp.h" #undef DEBUG #ifdef DEBUG @@ -154,10 +155,6 @@ static int mpc8568_mds_phy_fixups(struct phy_device *phydev) * Setup the architecture * */ -#ifdef CONFIG_SMP -extern void __init mpc85xx_smp_init(void); -#endif - #ifdef CONFIG_QUICC_ENGINE static struct of_device_id mpc85xx_qe_ids[] __initdata = { { .type = "qe", }, @@ -382,9 +379,7 @@ static void __init mpc85xx_mds_setup_arch(void) } #endif -#ifdef CONFIG_SMP mpc85xx_smp_init(); -#endif mpc85xx_mds_qe_init(); diff --git a/arch/powerpc/platforms/85xx/mpc85xx_rdb.c b/arch/powerpc/platforms/85xx/mpc85xx_rdb.c index f5ff911..cd49898 100644 --- a/arch/powerpc/platforms/85xx/mpc85xx_rdb.c +++ b/arch/powerpc/platforms/85xx/mpc85xx_rdb.c @@ -29,6 +29,7 @@ #include #include +#include "smp.h" #undef DEBUG @@ -82,9 +83,6 @@ void __init mpc85xx_rdb_pic_init(void) /* * Setup the architecture */ -#ifdef CONFIG_SMP -extern void __init mpc85xx_smp_init(void); -#endif static void __init mpc85xx_rdb_setup_arch(void) { #ifdef CONFIG_PCI @@ -102,10 +100,7 @@ static void __init mpc85xx_rdb_setup_arch(void) #endif -#ifdef CONFIG_SMP mpc85xx_smp_init(); -#endif - printk(KERN_INFO "MPC85xx RDB board from Freescale Semiconductor\n"); } diff --git a/arch/powerpc/platforms/85xx/p1022_ds.c b/arch/powerpc/platforms/85xx/p1022_ds.c index 266b3aa..7e90e24 100644 --- a/arch/powerpc/platforms/85xx/p1022_ds.c +++ b/arch/powerpc/platforms/85xx/p1022_ds.c @@ -26,6 +26,7 @@ #include #include #include +#include "smp.h" #if defined(CONFIG_FB_FSL_DIU) || defined(CONFIG_FB_FSL_DIU_MODULE) @@ -265,10 +266,6 @@ void __init p1022_ds_pic_init(void) mpic_init(mpic); } -#ifdef CONFIG_SMP -void __init mpc85xx_smp_init(void); -#endif - /* * Setup the architecture */ @@ -309,9 +306,7 @@ static void __init p1022_ds_setup_arch(void) diu_ops.set_sysfs_monitor_port = p1022ds_set_sysfs_monitor_port; #endif -#ifdef CONFIG_SMP mpc85xx_smp_init(); -#endif #ifdef CONFIG_SWIOTLB if (memblock_end_of_DRAM() > max) { diff --git a/arch/powerpc/platforms/85xx/p1023_rds.c b/arch/powerpc/platforms/85xx/p1023_rds.c index 835e0b3..5ab21f3 100644 --- a/arch/powerpc/platforms/85xx/p1023_rds.c +++ b/arch/powerpc/platforms/85xx/p1023_rd
[RFC PATCH 02/10] powerpc: Consolidate mpic_alloc() OF address translation
Instead of using the open-coded "reg" property lookup and address translation in mpic_alloc(), directly call of_address_to_resource(). This includes various workarounds for special cases which the naive of_address_translate() does not. Afterwards it is possible to remove the copiously copy-pasted calls to of_address_translate() from the 85xx/86xx/powermac platforms. Signed-off-by: Kyle Moffett Cc: Benjamin Herrenschmidt Cc: Paul Mackerras Cc: Grant Likely Cc: Kumar Gala --- arch/powerpc/platforms/85xx/corenet_ds.c |9 + arch/powerpc/platforms/85xx/ksi8560.c |9 + arch/powerpc/platforms/85xx/mpc8536_ds.c |9 + arch/powerpc/platforms/85xx/mpc85xx_ads.c |9 + arch/powerpc/platforms/85xx/mpc85xx_cds.c |9 + arch/powerpc/platforms/85xx/mpc85xx_ds.c | 11 + arch/powerpc/platforms/85xx/mpc85xx_mds.c |9 + arch/powerpc/platforms/85xx/mpc85xx_rdb.c | 11 + arch/powerpc/platforms/85xx/p1010rdb.c|9 + arch/powerpc/platforms/85xx/p1022_ds.c|9 + arch/powerpc/platforms/85xx/p1023_rds.c |9 + arch/powerpc/platforms/85xx/sbc8548.c |9 + arch/powerpc/platforms/85xx/sbc8560.c |9 + arch/powerpc/platforms/85xx/socrates.c|9 + arch/powerpc/platforms/85xx/stx_gp3.c |9 + arch/powerpc/platforms/85xx/tqm85xx.c |9 + arch/powerpc/platforms/85xx/xes_mpc85xx.c |9 + arch/powerpc/platforms/86xx/pic.c |4 +- arch/powerpc/platforms/powermac/pic.c |7 +--- arch/powerpc/sysdev/mpic.c| 63 +++-- 20 files changed, 54 insertions(+), 177 deletions(-) diff --git a/arch/powerpc/platforms/85xx/corenet_ds.c b/arch/powerpc/platforms/85xx/corenet_ds.c index 435074d..7893ad3 100644 --- a/arch/powerpc/platforms/85xx/corenet_ds.c +++ b/arch/powerpc/platforms/85xx/corenet_ds.c @@ -36,7 +36,6 @@ void __init corenet_ds_pic_init(void) { struct mpic *mpic; - struct resource r; struct device_node *np = NULL; unsigned int flags = MPIC_PRIMARY | MPIC_BIG_ENDIAN | MPIC_BROKEN_FRR_NIRQS | MPIC_SINGLE_DEST_CPU; @@ -48,16 +47,10 @@ void __init corenet_ds_pic_init(void) return; } - if (of_address_to_resource(np, 0, &r)) { - printk(KERN_ERR "Failed to map mpic register space\n"); - of_node_put(np); - return; - } - if (ppc_md.get_irq == mpic_get_coreint_irq) flags |= MPIC_ENABLE_COREINT; - mpic = mpic_alloc(np, r.start, flags, 0, 256, " OpenPIC "); + mpic = mpic_alloc(np, 0, flags, 0, 256, " OpenPIC "); BUG_ON(mpic == NULL); mpic_init(mpic); diff --git a/arch/powerpc/platforms/85xx/ksi8560.c b/arch/powerpc/platforms/85xx/ksi8560.c index c46f935..b20c07d 100644 --- a/arch/powerpc/platforms/85xx/ksi8560.c +++ b/arch/powerpc/platforms/85xx/ksi8560.c @@ -68,7 +68,6 @@ static void cpm2_cascade(unsigned int irq, struct irq_desc *desc) static void __init ksi8560_pic_init(void) { struct mpic *mpic; - struct resource r; struct device_node *np; #ifdef CONFIG_CPM2 int irq; @@ -81,13 +80,7 @@ static void __init ksi8560_pic_init(void) return; } - if (of_address_to_resource(np, 0, &r)) { - printk(KERN_ERR "Could not map mpic register space\n"); - of_node_put(np); - return; - } - - mpic = mpic_alloc(np, r.start, + mpic = mpic_alloc(np, 0, MPIC_PRIMARY | MPIC_WANTS_RESET | MPIC_BIG_ENDIAN, 0, 256, " OpenPIC "); BUG_ON(mpic == NULL); diff --git a/arch/powerpc/platforms/85xx/mpc8536_ds.c b/arch/powerpc/platforms/85xx/mpc8536_ds.c index f79f2f1..03173ba 100644 --- a/arch/powerpc/platforms/85xx/mpc8536_ds.c +++ b/arch/powerpc/platforms/85xx/mpc8536_ds.c @@ -35,7 +35,6 @@ void __init mpc8536_ds_pic_init(void) { struct mpic *mpic; - struct resource r; struct device_node *np; np = of_find_node_by_type(NULL, "open-pic"); @@ -44,13 +43,7 @@ void __init mpc8536_ds_pic_init(void) return; } - if (of_address_to_resource(np, 0, &r)) { - printk(KERN_ERR "Failed to map mpic register space\n"); - of_node_put(np); - return; - } - - mpic = mpic_alloc(np, r.start, + mpic = mpic_alloc(np, 0, MPIC_PRIMARY | MPIC_WANTS_RESET | MPIC_BIG_ENDIAN | MPIC_BROKEN_FRR_NIRQS, 0, 256, " OpenPIC "); diff --git a/arch/powerpc/platforms/85xx/mpc85xx_ads.c b/arch/powerpc/platforms/85xx/mpc85xx_ads.c index 3b2c9bb..5cb797b 100644 --- a/arch/powerpc/platforms/85xx/mpc85xx_ads.c +++ b/arch/powerpc/platforms/85xx/mpc85xx_ads.c @@ -64,7 +64,6 @@ static void cpm2_cascade(unsigned int irq, struct irq_desc
[RFC PATCH 03/10] powerpc/mpic: Assume a device-node was passed in mpic_alloc()
All of the existing callers of mpic_alloc() pass in a non-NULL device-node pointer, so the checks for a NULL device-node may be removed. Signed-off-by: Kyle Moffett --- arch/powerpc/sysdev/mpic.c | 50 ++- 1 files changed, 21 insertions(+), 29 deletions(-) diff --git a/arch/powerpc/sysdev/mpic.c b/arch/powerpc/sysdev/mpic.c index d6ef4d9..f7de33e 100644 --- a/arch/powerpc/sysdev/mpic.c +++ b/arch/powerpc/sysdev/mpic.c @@ -1139,19 +1139,17 @@ struct mpic * __init mpic_alloc(struct device_node *node, unsigned int irq_count, const char *name) { - struct mpic *mpic; - u32 greg_feature; - const char *vers; - int i; - int intvec_top; + int i, psize, intvec_top; + struct mpic *mpic; + u32 greg_feature; + const char *vers; + const u32 *psrc; - /* -* If no phyiscal address was specified then all of the phyiscal -* addressing parameters must come from the device-tree. -*/ - if (!phys_addr) { - BUG_ON(!node); + /* This code assumes that a non-NULL device node is passed in */ + BUG_ON(!node); + /* Pick the physical address from the device tree if unspecified */ + if (!phys_addr) { /* Check if it is DCR-based */ if (of_get_property(node, "dcr-reg")) { flags |= MPIC_USES_DCR; @@ -1218,28 +1216,22 @@ struct mpic * __init mpic_alloc(struct device_node *node, mpic->spurious_vec = intvec_top; /* Check for "big-endian" in device-tree */ - if (node && of_get_property(node, "big-endian", NULL) != NULL) + if (of_get_property(node, "big-endian", NULL) != NULL) mpic->flags |= MPIC_BIG_ENDIAN; - if (node && of_device_is_compatible(node, "fsl,mpic")) + if (of_device_is_compatible(node, "fsl,mpic")) mpic->flags |= MPIC_FSL; /* Look for protected sources */ - if (node) { - int psize; - unsigned int bits, mapsize; - const u32 *psrc = - of_get_property(node, "protected-sources", &psize); - if (psrc) { - psize /= 4; - bits = intvec_top + 1; - mapsize = BITS_TO_LONGS(bits) * sizeof(unsigned long); - mpic->protected = kzalloc(mapsize, GFP_KERNEL); - BUG_ON(mpic->protected == NULL); - for (i = 0; i < psize; i++) { - if (psrc[i] > intvec_top) - continue; - __set_bit(psrc[i], mpic->protected); - } + psrc = of_get_property(node, "protected-sources", &psize); + if (psrc) { + /* Allocate a bitmap with one bit per interrupt */ + unsigned int mapsize = BITS_TO_LONGS(intvec_top + 1); + mpic->protected = kzalloc(mapsize*sizeof(long), GFP_KERNEL); + BUG_ON(mpic->protected == NULL); + for (i = 0; i < psize/sizeof(u32); i++) { + if (psrc[i] > intvec_top) + continue; + __set_bit(psrc[i], mpic->protected); } } -- 1.7.2.5 ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[RFC PATCH 04/10] powerpc/mpic: Save computed phys_addr for board-specific code
The MPIC code can already perform an automatic OF address translation step as part of mpic_alloc(), but several boards need to use that base address when they perform mpic_assign_isu(). The easiest solution is to save the computed physical address into the "struct mpic" for later use by the board code. Signed-off-by: Kyle Moffett --- arch/powerpc/include/asm/mpic.h |3 +++ arch/powerpc/platforms/embedded6xx/holly.c| 15 +++ arch/powerpc/platforms/embedded6xx/linkstation.c | 14 -- arch/powerpc/platforms/embedded6xx/mpc7448_hpc2.c | 16 +++- arch/powerpc/platforms/embedded6xx/storcenter.c | 16 +++- arch/powerpc/platforms/pasemi/setup.c |2 +- arch/powerpc/sysdev/mpic.c| 11 ++- 7 files changed, 23 insertions(+), 54 deletions(-) diff --git a/arch/powerpc/include/asm/mpic.h b/arch/powerpc/include/asm/mpic.h index df18989..49bab41 100644 --- a/arch/powerpc/include/asm/mpic.h +++ b/arch/powerpc/include/asm/mpic.h @@ -295,6 +295,9 @@ struct mpic /* Register access method */ enum mpic_reg_type reg_type; + /* The physical base address of the MPIC */ + phys_addr_t paddr; + /* The various ioremap'ed bases */ struct mpic_reg_bankgregs; struct mpic_reg_banktmregs; diff --git a/arch/powerpc/platforms/embedded6xx/holly.c b/arch/powerpc/platforms/embedded6xx/holly.c index 487bda0..80b2e2a 100644 --- a/arch/powerpc/platforms/embedded6xx/holly.c +++ b/arch/powerpc/platforms/embedded6xx/holly.c @@ -147,7 +147,6 @@ static void __init holly_setup_arch(void) static void __init holly_init_IRQ(void) { struct mpic *mpic; - phys_addr_t mpic_paddr = 0; struct device_node *tsi_pic; #ifdef CONFIG_PCI unsigned int cascade_pci_irq; @@ -156,20 +155,12 @@ static void __init holly_init_IRQ(void) #endif tsi_pic = of_find_node_by_type(NULL, "open-pic"); - if (tsi_pic) { - unsigned int size; - const void *prop = of_get_property(tsi_pic, "reg", &size); - mpic_paddr = of_translate_address(tsi_pic, prop); - } - - if (mpic_paddr == 0) { + if (!tsi_pic) { printk(KERN_ERR "%s: No tsi108 PIC found !\n", __func__); return; } - pr_debug("%s: tsi108 pic phys_addr = 0x%x\n", __func__, (u32) mpic_paddr); - - mpic = mpic_alloc(tsi_pic, mpic_paddr, + mpic = mpic_alloc(tsi_pic, 0, MPIC_PRIMARY | MPIC_BIG_ENDIAN | MPIC_WANTS_RESET | MPIC_SPV_EOI | MPIC_NO_PTHROU_DIS | MPIC_REGSET_TSI108, 24, @@ -178,7 +169,7 @@ static void __init holly_init_IRQ(void) BUG_ON(mpic == NULL); - mpic_assign_isu(mpic, 0, mpic_paddr + 0x100); + mpic_assign_isu(mpic, 0, mpic->paddr + 0x100); mpic_init(mpic); diff --git a/arch/powerpc/platforms/embedded6xx/linkstation.c b/arch/powerpc/platforms/embedded6xx/linkstation.c index 244f997..72b3685 100644 --- a/arch/powerpc/platforms/embedded6xx/linkstation.c +++ b/arch/powerpc/platforms/embedded6xx/linkstation.c @@ -82,28 +82,22 @@ static void __init linkstation_init_IRQ(void) { struct mpic *mpic; struct device_node *dnp; - const u32 *prop; - int size; - phys_addr_t paddr; dnp = of_find_node_by_type(NULL, "open-pic"); if (dnp == NULL) return; - prop = of_get_property(dnp, "reg", &size); - paddr = (phys_addr_t)of_translate_address(dnp, prop); - - mpic = mpic_alloc(dnp, paddr, MPIC_PRIMARY | MPIC_WANTS_RESET, 4, 32, " EPIC "); + mpic = mpic_alloc(dnp, 0, MPIC_PRIMARY | MPIC_WANTS_RESET, 4, 32, " EPIC "); BUG_ON(mpic == NULL); /* PCI IRQs */ - mpic_assign_isu(mpic, 0, paddr + 0x10200); + mpic_assign_isu(mpic, 0, mpic->paddr + 0x10200); /* I2C */ - mpic_assign_isu(mpic, 1, paddr + 0x11000); + mpic_assign_isu(mpic, 1, mpic->paddr + 0x11000); /* ttyS0, ttyS1 */ - mpic_assign_isu(mpic, 2, paddr + 0x11100); + mpic_assign_isu(mpic, 2, mpic->paddr + 0x11100); mpic_init(mpic); } diff --git a/arch/powerpc/platforms/embedded6xx/mpc7448_hpc2.c b/arch/powerpc/platforms/embedded6xx/mpc7448_hpc2.c index 1cb907c..28082f9 100644 --- a/arch/powerpc/platforms/embedded6xx/mpc7448_hpc2.c +++ b/arch/powerpc/platforms/embedded6xx/mpc7448_hpc2.c @@ -101,7 +101,6 @@ static void __init mpc7448_hpc2_setup_arch(void) static void __init mpc7448_hpc2_init_IRQ(void) { struct mpic *mpic; - phys_addr_t mpic_paddr = 0; struct device_node *tsi_pic; #ifdef CONFIG_PCI unsigned int cascade_pci_irq; @@ -110,21 +109,12 @@ static void __init mpc7448_hpc2_init_IRQ(void) #endif tsi_pic = of_find_node_by_type(NULL, "open-pic"); - if (tsi_pic) { - un
[RFC PATCH 05/10] powerpc/mpic: Search for open-pic device-tree node if NULL
Almost all PowerPC platforms use a standard "open-pic" device node so the mpic_alloc() function now accepts NULL for the device-node. This will cause it to perform a default search with of_find_matching_node(). Signed-off-by: Kyle Moffett --- arch/powerpc/platforms/85xx/corenet_ds.c | 10 +- arch/powerpc/platforms/85xx/ksi8560.c | 13 ++--- arch/powerpc/platforms/85xx/mpc8536_ds.c | 13 + arch/powerpc/platforms/85xx/mpc85xx_ads.c | 12 ++-- arch/powerpc/platforms/85xx/mpc85xx_cds.c | 15 +-- arch/powerpc/platforms/85xx/mpc85xx_ds.c | 14 +++--- arch/powerpc/platforms/85xx/mpc85xx_mds.c | 10 +- arch/powerpc/platforms/85xx/mpc85xx_rdb.c | 14 ++ arch/powerpc/platforms/85xx/p1022_ds.c| 14 +- arch/powerpc/platforms/85xx/sbc8548.c | 16 +--- arch/powerpc/platforms/85xx/sbc8560.c | 13 ++--- arch/powerpc/platforms/85xx/socrates.c| 11 +-- arch/powerpc/platforms/85xx/stx_gp3.c | 13 ++--- arch/powerpc/platforms/85xx/tqm85xx.c | 13 ++--- arch/powerpc/platforms/85xx/xes_mpc85xx.c | 13 + arch/powerpc/platforms/embedded6xx/holly.c| 10 +- arch/powerpc/platforms/embedded6xx/linkstation.c |8 ++-- arch/powerpc/platforms/embedded6xx/mpc7448_hpc2.c | 10 +- arch/powerpc/platforms/embedded6xx/storcenter.c | 10 +- arch/powerpc/sysdev/mpic.c| 19 +-- 20 files changed, 45 insertions(+), 206 deletions(-) diff --git a/arch/powerpc/platforms/85xx/corenet_ds.c b/arch/powerpc/platforms/85xx/corenet_ds.c index 7893ad3..134e1f8 100644 --- a/arch/powerpc/platforms/85xx/corenet_ds.c +++ b/arch/powerpc/platforms/85xx/corenet_ds.c @@ -36,21 +36,13 @@ void __init corenet_ds_pic_init(void) { struct mpic *mpic; - struct device_node *np = NULL; unsigned int flags = MPIC_PRIMARY | MPIC_BIG_ENDIAN | MPIC_BROKEN_FRR_NIRQS | MPIC_SINGLE_DEST_CPU; - np = of_find_node_by_type(np, "open-pic"); - - if (np == NULL) { - printk(KERN_ERR "Could not find open-pic node\n"); - return; - } - if (ppc_md.get_irq == mpic_get_coreint_irq) flags |= MPIC_ENABLE_COREINT; - mpic = mpic_alloc(np, 0, flags, 0, 256, " OpenPIC "); + mpic = mpic_alloc(NULL, 0, flags, 0, 256, " OpenPIC "); BUG_ON(mpic == NULL); mpic_init(mpic); diff --git a/arch/powerpc/platforms/85xx/ksi8560.c b/arch/powerpc/platforms/85xx/ksi8560.c index b20c07d..d49dbc4 100644 --- a/arch/powerpc/platforms/85xx/ksi8560.c +++ b/arch/powerpc/platforms/85xx/ksi8560.c @@ -68,24 +68,15 @@ static void cpm2_cascade(unsigned int irq, struct irq_desc *desc) static void __init ksi8560_pic_init(void) { struct mpic *mpic; - struct device_node *np; #ifdef CONFIG_CPM2 + struct device_node *np; int irq; #endif - np = of_find_node_by_type(NULL, "open-pic"); - - if (np == NULL) { - printk(KERN_ERR "Could not find open-pic node\n"); - return; - } - - mpic = mpic_alloc(np, 0, + mpic = mpic_alloc(NULL, 0, MPIC_PRIMARY | MPIC_WANTS_RESET | MPIC_BIG_ENDIAN, 0, 256, " OpenPIC "); BUG_ON(mpic == NULL); - of_node_put(np); - mpic_init(mpic); #ifdef CONFIG_CPM2 diff --git a/arch/powerpc/platforms/85xx/mpc8536_ds.c b/arch/powerpc/platforms/85xx/mpc8536_ds.c index 03173ba..2c928f0 100644 --- a/arch/powerpc/platforms/85xx/mpc8536_ds.c +++ b/arch/powerpc/platforms/85xx/mpc8536_ds.c @@ -34,22 +34,11 @@ void __init mpc8536_ds_pic_init(void) { - struct mpic *mpic; - struct device_node *np; - - np = of_find_node_by_type(NULL, "open-pic"); - if (np == NULL) { - printk(KERN_ERR "Could not find open-pic node\n"); - return; - } - - mpic = mpic_alloc(np, 0, + struct mpic *mpic = mpic_alloc(NULL, 0, MPIC_PRIMARY | MPIC_WANTS_RESET | MPIC_BIG_ENDIAN | MPIC_BROKEN_FRR_NIRQS, 0, 256, " OpenPIC "); BUG_ON(mpic == NULL); - of_node_put(np); - mpic_init(mpic); } diff --git a/arch/powerpc/platforms/85xx/mpc85xx_ads.c b/arch/powerpc/platforms/85xx/mpc85xx_ads.c index 5cb797b..2b443ba 100644 --- a/arch/powerpc/platforms/85xx/mpc85xx_ads.c +++ b/arch/powerpc/platforms/85xx/mpc85xx_ads.c @@ -64,23 +64,15 @@ static void cpm2_cascade(unsigned int irq, struct irq_desc *desc) static void __init mpc85xx_ads_pic_init(void) { struct mpic *mpic; - struct device_node *np = NULL; #ifdef CONFIG_CPM2 + struct device_node *n
[RFC PATCH 06/10] powerpc/mpic: Invert the meaning of MPIC_PRIMARY
It turns out that there are only 2 in-tree platforms which use MPICs which are not "primary": IBM Cell and PowerMac. To reduce the complexity of the typical board setup code, invert the MPIC_PRIMARY bit into MPIC_SECONDARY. Signed-off-by: Kyle Moffett --- arch/powerpc/include/asm/mpic.h |8 arch/powerpc/platforms/44x/iss4xx.c |2 +- arch/powerpc/platforms/85xx/corenet_ds.c |2 +- arch/powerpc/platforms/85xx/ksi8560.c |2 +- arch/powerpc/platforms/85xx/mpc8536_ds.c |2 +- arch/powerpc/platforms/85xx/mpc85xx_ads.c |3 +-- arch/powerpc/platforms/85xx/mpc85xx_cds.c |2 +- arch/powerpc/platforms/85xx/mpc85xx_ds.c |3 +-- arch/powerpc/platforms/85xx/mpc85xx_mds.c |2 +- arch/powerpc/platforms/85xx/mpc85xx_rdb.c |3 +-- arch/powerpc/platforms/85xx/p1010rdb.c|2 +- arch/powerpc/platforms/85xx/p1022_ds.c|2 +- arch/powerpc/platforms/85xx/p1023_rds.c |2 +- arch/powerpc/platforms/85xx/sbc8548.c |2 +- arch/powerpc/platforms/85xx/sbc8560.c |2 +- arch/powerpc/platforms/85xx/socrates.c|2 +- arch/powerpc/platforms/85xx/stx_gp3.c |2 +- arch/powerpc/platforms/85xx/tqm85xx.c |2 +- arch/powerpc/platforms/85xx/xes_mpc85xx.c |2 +- arch/powerpc/platforms/86xx/pic.c |2 +- arch/powerpc/platforms/cell/setup.c |2 +- arch/powerpc/platforms/chrp/setup.c |3 +-- arch/powerpc/platforms/embedded6xx/holly.c|2 +- arch/powerpc/platforms/embedded6xx/linkstation.c |2 +- arch/powerpc/platforms/embedded6xx/mpc7448_hpc2.c |2 +- arch/powerpc/platforms/embedded6xx/storcenter.c |2 +- arch/powerpc/platforms/maple/setup.c |2 +- arch/powerpc/platforms/pasemi/setup.c |2 +- arch/powerpc/platforms/powermac/pic.c |2 +- arch/powerpc/platforms/pseries/setup.c|3 +-- arch/powerpc/sysdev/mpic.c| 14 +++--- 31 files changed, 40 insertions(+), 45 deletions(-) diff --git a/arch/powerpc/include/asm/mpic.h b/arch/powerpc/include/asm/mpic.h index 49bab41..a241076 100644 --- a/arch/powerpc/include/asm/mpic.h +++ b/arch/powerpc/include/asm/mpic.h @@ -336,11 +336,11 @@ struct mpic * Note setting any ID (leaving those bits to 0) means standard MPIC */ -/* This is the primary controller, only that one has IPIs and - * has afinity control. A non-primary MPIC always uses CPU0 - * registers only +/* + * This is a secondary ("chained") controller; it only uses the CPU0 + * registers. Primary controllers have IPIs and affinity control. */ -#define MPIC_PRIMARY 0x0001 +#define MPIC_SECONDARY 0x0001 /* Set this for a big-endian MPIC */ #define MPIC_BIG_ENDIAN0x0002 diff --git a/arch/powerpc/platforms/44x/iss4xx.c b/arch/powerpc/platforms/44x/iss4xx.c index 19395f1..5b8cdbb 100644 --- a/arch/powerpc/platforms/44x/iss4xx.c +++ b/arch/powerpc/platforms/44x/iss4xx.c @@ -71,7 +71,7 @@ static void __init iss4xx_init_irq(void) /* The MPIC driver will get everything it needs from the * device-tree, just pass 0 to all arguments */ - struct mpic *mpic = mpic_alloc(np, 0, MPIC_PRIMARY, 0, 0, + struct mpic *mpic = mpic_alloc(np, 0, 0, 0, 0, " MPIC "); BUG_ON(mpic == NULL); mpic_init(mpic); diff --git a/arch/powerpc/platforms/85xx/corenet_ds.c b/arch/powerpc/platforms/85xx/corenet_ds.c index 134e1f8..7b737a9 100644 --- a/arch/powerpc/platforms/85xx/corenet_ds.c +++ b/arch/powerpc/platforms/85xx/corenet_ds.c @@ -36,7 +36,7 @@ void __init corenet_ds_pic_init(void) { struct mpic *mpic; - unsigned int flags = MPIC_PRIMARY | MPIC_BIG_ENDIAN | + unsigned int flags = MPIC_BIG_ENDIAN | MPIC_BROKEN_FRR_NIRQS | MPIC_SINGLE_DEST_CPU; if (ppc_md.get_irq == mpic_get_coreint_irq) diff --git a/arch/powerpc/platforms/85xx/ksi8560.c b/arch/powerpc/platforms/85xx/ksi8560.c index d49dbc4..278962b 100644 --- a/arch/powerpc/platforms/85xx/ksi8560.c +++ b/arch/powerpc/platforms/85xx/ksi8560.c @@ -74,7 +74,7 @@ static void __init ksi8560_pic_init(void) #endif mpic = mpic_alloc(NULL, 0, - MPIC_PRIMARY | MPIC_WANTS_RESET | MPIC_BIG_ENDIAN, + MPIC_WANTS_RESET | MPIC_BIG_ENDIAN, 0, 256, " OpenPIC "); BUG_ON(mpic == NULL); mpic_init(mpic); diff --git a/arch/powerpc/platforms/85xx/mpc8536_ds.c b/arch/powerpc/platforms/85xx/mpc8536_ds.c index 2c928f0..d1aece5 100644 --- a/arch/powerpc/platforms/85xx/mpc8536_ds.c +++ b/arch/powerpc/pla
[RFC PATCH 07/10] powerpc/mpic: Don't open-code dcr_resource_start
Don't open-code the OpenFirmware "dcr-reg" property lookup trying to map DCR resources. This makes the code a bit easier to read. Signed-off-by: Kyle Moffett --- arch/powerpc/sysdev/mpic.c |7 ++- 1 files changed, 2 insertions(+), 5 deletions(-) diff --git a/arch/powerpc/sysdev/mpic.c b/arch/powerpc/sysdev/mpic.c index 31a9ada..0342ab8 100644 --- a/arch/powerpc/sysdev/mpic.c +++ b/arch/powerpc/sysdev/mpic.c @@ -319,11 +319,8 @@ static void _mpic_map_dcr(struct mpic *mpic, struct device_node *node, struct mpic_reg_bank *rb, unsigned int offset, unsigned int size) { - const u32 *dbasep; - - dbasep = of_get_property(node, "dcr-reg", NULL); - - rb->dhost = dcr_map(node, *dbasep + offset, size); + phys_addr_t phys_addr = dcr_resource_start(node); + rb->dhost = dcr_map(mpic->node, phys_addr + offset, size); BUG_ON(!DCR_MAP_OK(rb->dhost)); } -- 1.7.2.5 ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[RFC PATCH 08/10] powerpc/mpic: Put "pic-no-reset" test back into the MPIC code
There's not really any reason to have this one-liner in a separate static inline function, given that all the other similar tests are already in the alloc_mpic() code. Signed-off-by: Kyle Moffett --- arch/powerpc/sysdev/mpic.c |7 +-- 1 files changed, 1 insertions(+), 6 deletions(-) diff --git a/arch/powerpc/sysdev/mpic.c b/arch/powerpc/sysdev/mpic.c index 0342ab8..8b4f022 100644 --- a/arch/powerpc/sysdev/mpic.c +++ b/arch/powerpc/sysdev/mpic.c @@ -1120,11 +1120,6 @@ static struct irq_host_ops mpic_host_ops = { .xlate = mpic_host_xlate, }; -static int mpic_reset_prohibited(struct device_node *node) -{ - return node && of_get_property(node, "pic-no-reset", NULL); -} - /* * Exported functions */ @@ -1269,7 +1264,7 @@ struct mpic * __init mpic_alloc(struct device_node *node, /* When using a device-node, reset requests are only honored if the MPIC * is allowed to reset. */ - if (mpic_reset_prohibited(node)) + if (of_get_property(node, "pic-no-reset", NULL)) mpic->flags |= MPIC_NO_RESET; if ((flags & MPIC_WANTS_RESET) && !(mpic->flags & MPIC_NO_RESET)) { -- 1.7.2.5 ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[RFC PATCH 10/10] powerpc/mpic: Add in-core support for cascaded MPICs
The Cell and PowerMac platforms use virtually identical cascaded-IRQ setup code, so just merge it into the core. This does the obvious thing when an MPIC device-node specifies an "interrupts" property. Signed-off-by: Kyle Moffett --- arch/powerpc/platforms/cell/setup.c | 22 arch/powerpc/platforms/powermac/pic.c | 36 arch/powerpc/sysdev/mpic.c| 27 ++- 3 files changed, 30 insertions(+), 55 deletions(-) diff --git a/arch/powerpc/platforms/cell/setup.c b/arch/powerpc/platforms/cell/setup.c index 392cbdb..8708a71 100644 --- a/arch/powerpc/platforms/cell/setup.c +++ b/arch/powerpc/platforms/cell/setup.c @@ -183,19 +183,6 @@ static int __init cell_publish_devices(void) } machine_subsys_initcall(cell, cell_publish_devices); -static void cell_mpic_cascade(unsigned int irq, struct irq_desc *desc) -{ - struct irq_chip *chip = irq_desc_get_chip(desc); - struct mpic *mpic = irq_desc_get_handler_data(desc); - unsigned int virq; - - virq = mpic_get_one_irq(mpic); - if (virq != NO_IRQ) - generic_handle_irq(virq); - - chip->irq_eoi(&desc->irq_data); -} - static void __init mpic_init_IRQ(void) { struct device_node *dn; @@ -214,15 +201,6 @@ static void __init mpic_init_IRQ(void) if (mpic == NULL) continue; mpic_init(mpic); - - virq = irq_of_parse_and_map(dn, 0); - if (virq == NO_IRQ) - continue; - - printk(KERN_INFO "%s : hooking up to IRQ %d\n", - dn->full_name, virq); - irq_set_handler_data(virq, mpic); - irq_set_chained_handler(virq, cell_mpic_cascade); } } diff --git a/arch/powerpc/platforms/powermac/pic.c b/arch/powerpc/platforms/powermac/pic.c index f4dc247..e02cd79 100644 --- a/arch/powerpc/platforms/powermac/pic.c +++ b/arch/powerpc/platforms/powermac/pic.c @@ -466,18 +466,6 @@ int of_irq_map_oldworld(struct device_node *device, int index, } #endif /* CONFIG_PPC32 */ -static void pmac_u3_cascade(unsigned int irq, struct irq_desc *desc) -{ - struct irq_chip *chip = irq_desc_get_chip(desc); - struct mpic *mpic = irq_desc_get_handler_data(desc); - unsigned int cascade_irq = mpic_get_one_irq(mpic); - - if (cascade_irq != NO_IRQ) - generic_handle_irq(cascade_irq); - - chip->irq_eoi(&desc->irq_data); -} - static void __init pmac_pic_setup_mpic_nmi(struct mpic *mpic) { #if defined(CONFIG_XMON) && defined(CONFIG_PPC32) @@ -529,7 +517,6 @@ static int __init pmac_pic_probe_mpic(void) { struct mpic *mpic1, *mpic2; struct device_node *np, *master = NULL, *slave = NULL; - unsigned int cascade; /* We can have up to 2 MPICs cascaded */ for (np = NULL; (np = of_find_node_by_type(np, "open-pic")) @@ -565,27 +552,14 @@ static int __init pmac_pic_probe_mpic(void) of_node_put(master); - /* No slave, let's go out */ - if (slave == NULL) - return 0; - - /* Get/Map slave interrupt */ - cascade = irq_of_parse_and_map(slave, 0); - if (cascade == NO_IRQ) { - printk(KERN_ERR "Failed to map cascade IRQ\n"); - return 0; - } - - mpic2 = pmac_setup_one_mpic(slave, 0); - if (mpic2 == NULL) { - printk(KERN_ERR "Failed to setup slave MPIC\n"); + /* Set up a cascaded controller, if present */ + if (slave) { + mpic2 = pmac_setup_one_mpic(slave, 0); + if (mpic2 == NULL) + printk(KERN_ERR "Failed to setup slave MPIC\n"); of_node_put(slave); - return 0; } - irq_set_handler_data(cascade, mpic2); - irq_set_chained_handler(cascade, pmac_u3_cascade); - of_node_put(slave); return 0; } diff --git a/arch/powerpc/sysdev/mpic.c b/arch/powerpc/sysdev/mpic.c index 1826dae..d5cf276 100644 --- a/arch/powerpc/sysdev/mpic.c +++ b/arch/powerpc/sysdev/mpic.c @@ -1113,6 +1113,21 @@ static int mpic_host_xlate(struct irq_host *h, struct device_node *ct, return 0; } +/* IRQ handler for a secondary MPIC cascaded from another IRQ controller */ +static void mpic_cascade(unsigned int irq, struct irq_desc *desc) +{ + struct irq_chip *chip = irq_desc_get_chip(desc); + struct mpic *mpic = irq_desc_get_handler_data(desc); + + BUG_ON(!(mpic->flags & MPIC_SECONDARY)); + + unsigned int virq = mpic_get_one_irq(mpic); + if (virq != NO_IRQ) + generic_handle_irq(virq); + + chip->irq_eoi(&desc->irq_data); +} + static struct irq_host_ops mpic_host_ops = { .match = mpic_host_match, .map = mpic_host_map, @@ -1384,8 +1399,7 @@ void __init mpic_set_default_senses(struct mpic *mpic, u8 *senses, int count) void __init mpic_init(struct mpic *m
[RFC PATCH 09/10] powerpc/mpic: Cache the device-tree node in "struct mpic"
Store the node pointer in the MPIC during initialization so that all of the later operational code can just reuse the cached pointer. Signed-off-by: Kyle Moffett --- arch/powerpc/include/asm/mpic.h |3 +++ arch/powerpc/sysdev/mpic.c | 32 2 files changed, 19 insertions(+), 16 deletions(-) diff --git a/arch/powerpc/include/asm/mpic.h b/arch/powerpc/include/asm/mpic.h index a241076..db78b89 100644 --- a/arch/powerpc/include/asm/mpic.h +++ b/arch/powerpc/include/asm/mpic.h @@ -251,6 +251,9 @@ struct mpic_irq_save { /* The instance data of a given MPIC */ struct mpic { + /* The OpenFirmware dt node for this MPIC */ + struct device_node *node; + /* The remapper for this MPIC */ struct irq_host *irqhost; diff --git a/arch/powerpc/sysdev/mpic.c b/arch/powerpc/sysdev/mpic.c index 8b4f022..1826dae 100644 --- a/arch/powerpc/sysdev/mpic.c +++ b/arch/powerpc/sysdev/mpic.c @@ -315,26 +315,25 @@ static void _mpic_map_mmio(struct mpic *mpic, phys_addr_t phys_addr, } #ifdef CONFIG_PPC_DCR -static void _mpic_map_dcr(struct mpic *mpic, struct device_node *node, - struct mpic_reg_bank *rb, +static void _mpic_map_dcr(struct mpic *mpic, struct mpic_reg_bank *rb, unsigned int offset, unsigned int size) { - phys_addr_t phys_addr = dcr_resource_start(node); + phys_addr_t phys_addr = dcr_resource_start(mpic->node); rb->dhost = dcr_map(mpic->node, phys_addr + offset, size); BUG_ON(!DCR_MAP_OK(rb->dhost)); } -static inline void mpic_map(struct mpic *mpic, struct device_node *node, +static inline void mpic_map(struct mpic *mpic, phys_addr_t phys_addr, struct mpic_reg_bank *rb, unsigned int offset, unsigned int size) { if (mpic->flags & MPIC_USES_DCR) - _mpic_map_dcr(mpic, node, rb, offset, size); + _mpic_map_dcr(mpic, rb, offset, size); else _mpic_map_mmio(mpic, phys_addr, rb, offset, size); } #else /* CONFIG_PPC_DCR */ -#define mpic_map(m,n,p,b,o,s) _mpic_map_mmio(m,p,b,o,s) +#define mpic_map(m,p,b,o,s)_mpic_map_mmio(m,p,b,o,s) #endif /* !CONFIG_PPC_DCR */ @@ -1178,6 +1177,7 @@ struct mpic * __init mpic_alloc(struct device_node *node, return NULL; mpic->name = name; + mpic->node = node; mpic->paddr = phys_addr; mpic->hc_irq = mpic_irq_chip; @@ -1224,13 +1224,13 @@ struct mpic * __init mpic_alloc(struct device_node *node, mpic->spurious_vec = intvec_top; /* Check for "big-endian" in device-tree */ - if (of_get_property(node, "big-endian", NULL) != NULL) + if (of_get_property(mpic->node, "big-endian", NULL) != NULL) mpic->flags |= MPIC_BIG_ENDIAN; - if (of_device_is_compatible(node, "fsl,mpic")) + if (of_device_is_compatible(mpic->node, "fsl,mpic")) mpic->flags |= MPIC_FSL; /* Look for protected sources */ - psrc = of_get_property(node, "protected-sources", &psize); + psrc = of_get_property(mpic->node, "protected-sources", &psize); if (psrc) { /* Allocate a bitmap with one bit per interrupt */ unsigned int mapsize = BITS_TO_LONGS(intvec_top + 1); @@ -1256,15 +1256,15 @@ struct mpic * __init mpic_alloc(struct device_node *node, mpic->reg_type = mpic_access_mmio_le; /* Map the global registers */ - mpic_map(mpic, node, mpic->paddr, &mpic->gregs, MPIC_INFO(GREG_BASE), 0x1000); - mpic_map(mpic, node, mpic->paddr, &mpic->tmregs, MPIC_INFO(TIMER_BASE), 0x1000); + mpic_map(mpic, mpic->paddr, &mpic->gregs, MPIC_INFO(GREG_BASE), 0x1000); + mpic_map(mpic, mpic->paddr, &mpic->tmregs, MPIC_INFO(TIMER_BASE), 0x1000); /* Reset */ /* When using a device-node, reset requests are only honored if the MPIC * is allowed to reset. */ - if (of_get_property(node, "pic-no-reset", NULL)) + if (of_get_property(mpic->node, "pic-no-reset", NULL)) mpic->flags |= MPIC_NO_RESET; if ((flags & MPIC_WANTS_RESET) && !(mpic->flags & MPIC_NO_RESET)) { @@ -1306,7 +1306,7 @@ struct mpic * __init mpic_alloc(struct device_node *node, /* Map the per-CPU registers */ for (i = 0; i < mpic->num_cpus; i++) { - mpic_map(mpic, node, mpic->paddr, &mpic->cpuregs[i], + mpic_map(mpic, mpic->paddr, &mpic->cpuregs[i], MPIC_INFO(CPU_BASE) + i * MPIC_INFO(CPU_STRIDE), 0x1000); } @@ -1314,13 +1314,13 @@ struct mpic * __init mpic_alloc(struct device_node *node, /* Initialize main ISU if none provided */ if (mpic->isu_size == 0) { mpic->isu_size = mpic->num_sources; - mpic_map(mpic, node, mpic->paddr, &mpic->isus[0], +
[PATCH] [v3] powerpc/fsl_msi: add support for the fsl, msi property in PCI nodes
On Freescale parts with multiple MSI controllers, the controllers are combined into one "pool" of interrupts. Whenever a device requests an MSI interrupt, the next available interrupt from the pool is selected, regardless of which MSI controller the interrupt is from. This works because each PCI bus has an ATMU to all of CCSR, so any PCI device can access any MSI interrupt register. The fsl,msi property is used to specify that a given PCI bus should only use a specific MSI device. This is necessary, for example, with the Freescale hypervisor, because the MSI devices are assigned to specific partitions. Ideally, we'd like to be able to assign MSI devices to PCI busses within the MSI or PCI layers. However, there does not appear to be a mechanism to do that. Whenever the MSI layer wants to allocate an MSI interrupt to a PCI device, it just calls arch_setup_msi_irqs(). It would be nice if we could register an MSI device with a specific PCI bus. So instead we remember the phandles of each MSI device, and we use that to limit our search for an available interrupt. Whenever we are asked to allocate a new interrupt for a PCI device, we check the fsl,msi property of the PCI bus for that device. If it exists, then as we are looping over all MSI devices, we skip the ones that don't have a matching phandle. Signed-off-by: Timur Tabi --- v3: added check for invalid fsl,msi phandles arch/powerpc/sysdev/fsl_msi.c | 39 +++ arch/powerpc/sysdev/fsl_msi.h |3 +++ 2 files changed, 42 insertions(+), 0 deletions(-) diff --git a/arch/powerpc/sysdev/fsl_msi.c b/arch/powerpc/sysdev/fsl_msi.c index e5c344d..89548e0 100644 --- a/arch/powerpc/sysdev/fsl_msi.c +++ b/arch/powerpc/sysdev/fsl_msi.c @@ -148,14 +148,47 @@ static void fsl_compose_msi_msg(struct pci_dev *pdev, int hwirq, static int fsl_setup_msi_irqs(struct pci_dev *pdev, int nvec, int type) { + struct pci_controller *hose = pci_bus_to_host(pdev->bus); + struct device_node *np; + phandle phandle = 0; int rc, hwirq = -ENOMEM; unsigned int virq; struct msi_desc *entry; struct msi_msg msg; struct fsl_msi *msi_data; + /* +* If the PCI node has an fsl,msi property, then we need to use it +* to find the specific MSI. +*/ + np = of_parse_phandle(hose->dn, "fsl,msi", 0); + if (np) { + if (of_device_is_compatible(np, "fsl,mpic-msi")) + phandle = np->phandle; + else { + dev_err(&pdev->dev, "node %s has an invalid fsl,msi" + " phandle\n", hose->dn->full_name); + return -EINVAL; + } + } + list_for_each_entry(entry, &pdev->msi_list, list) { + /* +* Loop over all the MSI devices until we find one that has an +* available interrupt. +*/ list_for_each_entry(msi_data, &msi_head, list) { + /* +* If the PCI node has an fsl,msi property, then we +* restrict our search to the corresponding MSI node. +* The simplest way is to skip over MSI nodes with the +* wrong phandle. Under the Freescale hypervisor, this +* has the additional benefit of skipping over MSI +* nodes that are not mapped in the PAMU. +*/ + if (phandle && (phandle != msi_data->phandle)) + continue; + hwirq = msi_bitmap_alloc_hwirqs(&msi_data->bitmap, 1); if (hwirq >= 0) break; @@ -370,6 +403,12 @@ static int __devinit fsl_of_msi_probe(struct platform_device *dev) msi->msiir_offset = features->msiir_offset + (res.start & 0xf); + /* +* Remember the phandle, so that we can match with any PCI nodes +* that have an "fsl,msi" property. +*/ + msi->phandle = dev->dev.of_node->phandle; + rc = fsl_msi_init_allocator(msi); if (rc) { dev_err(&dev->dev, "Error allocating MSI bitmap\n"); diff --git a/arch/powerpc/sysdev/fsl_msi.h b/arch/powerpc/sysdev/fsl_msi.h index 1313abb..b5d25ba 100644 --- a/arch/powerpc/sysdev/fsl_msi.h +++ b/arch/powerpc/sysdev/fsl_msi.h @@ -13,6 +13,7 @@ #ifndef _POWERPC_SYSDEV_FSL_MSI_H #define _POWERPC_SYSDEV_FSL_MSI_H +#include #include #define NR_MSI_REG 8 @@ -36,6 +37,8 @@ struct fsl_msi { struct msi_bitmap bitmap; struct list_head list; /* support multiple MSI banks */ + + phandle phandle; }; #endif /* _POWERPC_SYSDEV_FSL_MSI_H */ -- 1.7.3.4 ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.
Re: [PATCH] powerpc/iommu: remove default window before creating larger window
Hi Ben, Please don't take this patch :) While, it does work around some issues I'm tracking down, it can lead to worse ones if we are unable to configure the larger DMA window, or if some functions in a PE don't use 64-bit DMA masks. Thanks, Nish On 26.10.2011 [15:43:23 -0700], Nishanth Aravamudan wrote: > The DDW feature relies on there being sufficient TCE space to allocate > for the requested DMA window size. The default window uses up some of > that space, though, and it is recommended to first remove the default > window and then allocate the larger window advertised by firmware. Do > this by abstracting out parts of remove_ddw into a function that does > not assume an existing larger window has been created. > > Signed-off-by: Nishanth Aravamudan > --- > arch/powerpc/platforms/pseries/iommu.c | 35 +++ > 1 files changed, 26 insertions(+), 9 deletions(-) > > Is there a better way to get the default window's LIOBN than to call > of_parse_dma_window? > > diff --git a/arch/powerpc/platforms/pseries/iommu.c > b/arch/powerpc/platforms/pseries/iommu.c > index 01faab9..afcc04c 100644 > --- a/arch/powerpc/platforms/pseries/iommu.c > +++ b/arch/powerpc/platforms/pseries/iommu.c > @@ -655,6 +655,21 @@ static int __init disable_ddw_setup(char *str) > > early_param("disable_ddw", disable_ddw_setup); > > +static void __remove_ddw(struct device_node *np, const u32 *ddw_avail, u64 > liobn) > +{ > + int ret; > + > + ret = rtas_call(ddw_avail[2], 1, 1, NULL, liobn); > + if (ret) > + pr_warning("%s: failed to remove direct window: rtas returned " > + "%d to ibm,remove-pe-dma-window(%x) %llx\n", > + np->full_name, ret, ddw_avail[2], liobn); > + else > + pr_debug("%s: successfully removed direct window: rtas returned > " > + "%d to ibm,remove-pe-dma-window(%x) %llx\n", > + np->full_name, ret, ddw_avail[2], liobn); > +} > + > static void remove_ddw(struct device_node *np) > { > struct dynamic_dma_window_prop *dwp; > @@ -684,15 +699,7 @@ static void remove_ddw(struct device_node *np) > pr_debug("%s successfully cleared tces in window.\n", >np->full_name); > > - ret = rtas_call(ddw_avail[2], 1, 1, NULL, liobn); > - if (ret) > - pr_warning("%s: failed to remove direct window: rtas returned " > - "%d to ibm,remove-pe-dma-window(%x) %llx\n", > - np->full_name, ret, ddw_avail[2], liobn); > - else > - pr_debug("%s: successfully removed direct window: rtas returned > " > - "%d to ibm,remove-pe-dma-window(%x) %llx\n", > - np->full_name, ret, ddw_avail[2], liobn); > + __remove_ddw(np, ddw_avail, liobn); > > delprop: > ret = prom_remove_property(np, win64); > @@ -843,6 +850,8 @@ static u64 enable_ddw(struct pci_dev *dev, struct > device_node *pdn) > struct direct_window *window; > struct property *win64; > struct dynamic_dma_window_prop *ddwprop; > + const void *dma_window = NULL; > + unsigned long liobn, offset, size; > > mutex_lock(&direct_window_init_mutex); > > @@ -918,6 +927,14 @@ static u64 enable_ddw(struct pci_dev *dev, struct > device_node *pdn) > goto out_free_prop; > } > > + /* > + * To maximize the resources available to the create RTAS call, > + * delete the existing DMA window > + */ > + dma_window = of_get_property(pdn, "ibm,dma-window", NULL); > + of_parse_dma_window(pdn, dma_window, &liobn, &offset, &size); > + __remove_ddw(pdn, ddw_avail, liobn); > + > ret = create_ddw(dev, ddw_avail, &create, page_shift, len); > if (ret != 0) > goto out_free_prop; > -- > 1.7.5.4 > > > -- > Nishanth Aravamudan > IBM Linux Technology Center -- Nishanth Aravamudan IBM Linux Technology Center ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev