* Re: [PATCH] [2.6.18] powerpc: kill union tce_entry
From: Jon Mason @ 2006-04-28 20:42 UTC (permalink / raw)
To: Olof Johansson; +Cc: linuxppc-dev, mulix, paulus, sfr
In-Reply-To: <20060428140835.GG5518@pb15.lixom.net>
This looks very similar to the way Muli did it for x86_64 Calgary, only
in the reverse. You gotta love endianness. :-)
Looks good to my eyeball.
Thanks,
Jon
On Fri, Apr 28, 2006 at 09:08:35AM -0500, Olof Johansson wrote:
> It's been long overdue to kill the union tce_entry in the pSeries/iSeries
> TCE code, especially since I asked the Summit guys to do it on the code
> they copied from us.
>
> Also, while I was at it, I cleaned up some whitespace.
>
> Built and booted on pSeries, built on iSeries.
>
>
> Signed-off-by: Olof Johansson <olof@lixom.net>
>
>
> Index: powerpc/arch/powerpc/platforms/iseries/iommu.c
> ===================================================================
> --- powerpc.orig/arch/powerpc/platforms/iseries/iommu.c
> +++ powerpc/arch/powerpc/platforms/iseries/iommu.c
> @@ -4,6 +4,7 @@
> * Rewrite, cleanup:
> *
> * Copyright (C) 2004 Olof Johansson <olof@lixom.net>, IBM Corporation
> + * Copyright (C) 2006 Olof Johansson <olof@lixom.net>
> *
> * Dynamic DMA mapping support, iSeries-specific parts.
> *
> @@ -43,30 +44,28 @@ static void tce_build_iSeries(struct iom
> unsigned long uaddr, enum dma_data_direction direction)
> {
> u64 rc;
> - union tce_entry tce;
> + u64 tce, rpn;
>
> index <<= TCE_PAGE_FACTOR;
> npages <<= TCE_PAGE_FACTOR;
>
> while (npages--) {
> - tce.te_word = 0;
> - tce.te_bits.tb_rpn = virt_to_abs(uaddr) >> TCE_SHIFT;
> + rpn = virt_to_abs(uaddr) >> TCE_SHIFT;
> + tce = (rpn & TCE_RPN_MASK) << TCE_RPN_SHIFT;
>
> if (tbl->it_type == TCE_VB) {
> /* Virtual Bus */
> - tce.te_bits.tb_valid = 1;
> - tce.te_bits.tb_allio = 1;
> + tce |= TCE_VALID|TCE_ALLIO;
> if (direction != DMA_TO_DEVICE)
> - tce.te_bits.tb_rdwr = 1;
> + tce |= TCE_VB_WRITE;
> } else {
> /* PCI Bus */
> - tce.te_bits.tb_rdwr = 1; /* Read allowed */
> + tce |= TCE_PCI_READ; /* Read allowed */
> if (direction != DMA_TO_DEVICE)
> - tce.te_bits.tb_pciwr = 1;
> + tce |= TCE_PCI_WRITE;
> }
>
> - rc = HvCallXm_setTce((u64)tbl->it_index, (u64)index,
> - tce.te_word);
> + rc = HvCallXm_setTce((u64)tbl->it_index, (u64)index, tce);
> if (rc)
> panic("PCI_DMA: HvCallXm_setTce failed, Rc: 0x%lx\n",
> rc);
> @@ -124,7 +123,7 @@ void iommu_table_getparms_iSeries(unsign
>
> /* itc_size is in pages worth of table, it_size is in # of entries */
> tbl->it_size = ((parms->itc_size * TCE_PAGE_SIZE) /
> - sizeof(union tce_entry)) >> TCE_PAGE_FACTOR;
> + TCE_ENTRY_SIZE) >> TCE_PAGE_FACTOR;
> tbl->it_busno = parms->itc_busno;
> tbl->it_offset = parms->itc_offset >> TCE_PAGE_FACTOR;
> tbl->it_index = parms->itc_index;
> Index: powerpc/arch/powerpc/platforms/pseries/iommu.c
> ===================================================================
> --- powerpc.orig/arch/powerpc/platforms/pseries/iommu.c
> +++ powerpc/arch/powerpc/platforms/pseries/iommu.c
> @@ -1,23 +1,24 @@
> /*
> * Copyright (C) 2001 Mike Corrigan & Dave Engebretsen, IBM Corporation
> *
> - * Rewrite, cleanup:
> + * Rewrite, cleanup:
> *
> * Copyright (C) 2004 Olof Johansson <olof@lixom.net>, IBM Corporation
> + * Copyright (C) 2006 Olof Johansson <olof@lixom.net>
> *
> * Dynamic DMA mapping support, pSeries-specific parts, both SMP and LPAR.
> *
> - *
> + *
> * 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
> @@ -49,52 +50,46 @@
>
> #define DBG(fmt...)
>
> -static void tce_build_pSeries(struct iommu_table *tbl, long index,
> - long npages, unsigned long uaddr,
> +static void tce_build_pSeries(struct iommu_table *tbl, long index,
> + long npages, unsigned long uaddr,
> enum dma_data_direction direction)
> {
> - union tce_entry t;
> - union tce_entry *tp;
> + u64 proto_tce;
> + u64 *tcep;
> + u64 rpn;
>
> index <<= TCE_PAGE_FACTOR;
> npages <<= TCE_PAGE_FACTOR;
>
> - t.te_word = 0;
> - t.te_rdwr = 1; // Read allowed
> + proto_tce = TCE_PCI_READ; // Read allowed
>
> if (direction != DMA_TO_DEVICE)
> - t.te_pciwr = 1;
> + proto_tce |= TCE_PCI_WRITE;
>
> - tp = ((union tce_entry *)tbl->it_base) + index;
> + tcep = ((u64 *)tbl->it_base) + index;
>
> while (npages--) {
> /* can't move this out since we might cross LMB boundary */
> - t.te_rpn = (virt_to_abs(uaddr)) >> TCE_SHIFT;
> -
> - tp->te_word = t.te_word;
> + rpn = (virt_to_abs(uaddr)) >> TCE_SHIFT;
> + *tcep = proto_tce | (rpn & TCE_RPN_MASK) << TCE_RPN_SHIFT;
>
> uaddr += TCE_PAGE_SIZE;
> - tp++;
> + tcep++;
> }
> }
>
>
> static void tce_free_pSeries(struct iommu_table *tbl, long index, long npages)
> {
> - union tce_entry t;
> - union tce_entry *tp;
> + u64 *tcep;
>
> npages <<= TCE_PAGE_FACTOR;
> index <<= TCE_PAGE_FACTOR;
>
> - t.te_word = 0;
> - tp = ((union tce_entry *)tbl->it_base) + index;
> -
> - while (npages--) {
> - tp->te_word = t.te_word;
> -
> - tp++;
> - }
> + tcep = ((u64 *)tbl->it_base) + index;
> +
> + while (npages--)
> + *(tcep++) = 0;
> }
>
>
> @@ -103,43 +98,44 @@ static void tce_build_pSeriesLP(struct i
> enum dma_data_direction direction)
> {
> u64 rc;
> - union tce_entry tce;
> + u64 proto_tce, tce;
> + u64 rpn;
>
> tcenum <<= TCE_PAGE_FACTOR;
> npages <<= TCE_PAGE_FACTOR;
>
> - tce.te_word = 0;
> - tce.te_rpn = (virt_to_abs(uaddr)) >> TCE_SHIFT;
> - tce.te_rdwr = 1;
> + rpn = (virt_to_abs(uaddr)) >> TCE_SHIFT;
> + proto_tce = TCE_PCI_READ;
> if (direction != DMA_TO_DEVICE)
> - tce.te_pciwr = 1;
> + proto_tce |= TCE_PCI_WRITE;
>
> while (npages--) {
> - rc = plpar_tce_put((u64)tbl->it_index,
> - (u64)tcenum << 12,
> - tce.te_word );
> -
> + tce = proto_tce | (rpn & TCE_RPN_MASK) << TCE_RPN_SHIFT;
> + rc = plpar_tce_put((u64)tbl->it_index, (u64)tcenum << 12, tce);
> +
> if (rc && printk_ratelimit()) {
> printk("tce_build_pSeriesLP: plpar_tce_put failed. rc=%ld\n", rc);
> printk("\tindex = 0x%lx\n", (u64)tbl->it_index);
> printk("\ttcenum = 0x%lx\n", (u64)tcenum);
> - printk("\ttce val = 0x%lx\n", tce.te_word );
> + printk("\ttce val = 0x%lx\n", tce );
> show_stack(current, (unsigned long *)__get_SP());
> }
> -
> +
> tcenum++;
> - tce.te_rpn++;
> + rpn++;
> }
> }
>
> -static DEFINE_PER_CPU(void *, tce_page) = NULL;
> +static DEFINE_PER_CPU(u64 *, tce_page) = NULL;
>
> static void tce_buildmulti_pSeriesLP(struct iommu_table *tbl, long tcenum,
> long npages, unsigned long uaddr,
> enum dma_data_direction direction)
> {
> u64 rc;
> - union tce_entry tce, *tcep;
> + u64 proto_tce;
> + u64 *tcep;
> + u64 rpn;
> long l, limit;
>
> if (TCE_PAGE_FACTOR == 0 && npages == 1)
> @@ -152,7 +148,7 @@ static void tce_buildmulti_pSeriesLP(str
> * from iommu_alloc{,_sg}()
> */
> if (!tcep) {
> - tcep = (void *)__get_free_page(GFP_ATOMIC);
> + tcep = (u64 *)__get_free_page(GFP_ATOMIC);
> /* If allocation fails, fall back to the loop implementation */
> if (!tcep)
> return tce_build_pSeriesLP(tbl, tcenum, npages,
> @@ -163,11 +159,10 @@ static void tce_buildmulti_pSeriesLP(str
> tcenum <<= TCE_PAGE_FACTOR;
> npages <<= TCE_PAGE_FACTOR;
>
> - tce.te_word = 0;
> - tce.te_rpn = (virt_to_abs(uaddr)) >> TCE_SHIFT;
> - tce.te_rdwr = 1;
> + rpn = (virt_to_abs(uaddr)) >> TCE_SHIFT;
> + proto_tce = TCE_PCI_READ;
> if (direction != DMA_TO_DEVICE)
> - tce.te_pciwr = 1;
> + proto_tce |= TCE_PCI_WRITE;
>
> /* We can map max one pageful of TCEs at a time */
> do {
> @@ -175,11 +170,11 @@ static void tce_buildmulti_pSeriesLP(str
> * Set up the page with TCE data, looping through and setting
> * the values.
> */
> - limit = min_t(long, npages, 4096/sizeof(union tce_entry));
> + limit = min_t(long, npages, 4096/TCE_ENTRY_SIZE);
>
> for (l = 0; l < limit; l++) {
> - tcep[l] = tce;
> - tce.te_rpn++;
> + tcep[l] = proto_tce | (rpn & TCE_RPN_MASK) << TCE_RPN_SHIFT;
> + rpn++;
> }
>
> rc = plpar_tce_put_indirect((u64)tbl->it_index,
> @@ -195,7 +190,7 @@ static void tce_buildmulti_pSeriesLP(str
> printk("tce_buildmulti_pSeriesLP: plpar_tce_put failed. rc=%ld\n", rc);
> printk("\tindex = 0x%lx\n", (u64)tbl->it_index);
> printk("\tnpages = 0x%lx\n", (u64)npages);
> - printk("\ttce[0] val = 0x%lx\n", tcep[0].te_word);
> + printk("\ttce[0] val = 0x%lx\n", tcep[0]);
> show_stack(current, (unsigned long *)__get_SP());
> }
> }
> @@ -203,23 +198,17 @@ static void tce_buildmulti_pSeriesLP(str
> static void tce_free_pSeriesLP(struct iommu_table *tbl, long tcenum, long npages)
> {
> u64 rc;
> - union tce_entry tce;
>
> tcenum <<= TCE_PAGE_FACTOR;
> npages <<= TCE_PAGE_FACTOR;
>
> - tce.te_word = 0;
> -
> while (npages--) {
> - rc = plpar_tce_put((u64)tbl->it_index,
> - (u64)tcenum << 12,
> - tce.te_word);
> + rc = plpar_tce_put((u64)tbl->it_index, (u64)tcenum << 12, 0);
>
> if (rc && printk_ratelimit()) {
> printk("tce_free_pSeriesLP: plpar_tce_put failed. rc=%ld\n", rc);
> printk("\tindex = 0x%lx\n", (u64)tbl->it_index);
> printk("\ttcenum = 0x%lx\n", (u64)tcenum);
> - printk("\ttce val = 0x%lx\n", tce.te_word );
> show_stack(current, (unsigned long *)__get_SP());
> }
>
> @@ -231,31 +220,24 @@ static void tce_free_pSeriesLP(struct io
> static void tce_freemulti_pSeriesLP(struct iommu_table *tbl, long tcenum, long npages)
> {
> u64 rc;
> - union tce_entry tce;
>
> tcenum <<= TCE_PAGE_FACTOR;
> npages <<= TCE_PAGE_FACTOR;
>
> - tce.te_word = 0;
> -
> - rc = plpar_tce_stuff((u64)tbl->it_index,
> - (u64)tcenum << 12,
> - tce.te_word,
> - npages);
> + rc = plpar_tce_stuff((u64)tbl->it_index, (u64)tcenum << 12, 0, npages);
>
> if (rc && printk_ratelimit()) {
> printk("tce_freemulti_pSeriesLP: plpar_tce_stuff failed\n");
> printk("\trc = %ld\n", rc);
> printk("\tindex = 0x%lx\n", (u64)tbl->it_index);
> printk("\tnpages = 0x%lx\n", (u64)npages);
> - printk("\ttce val = 0x%lx\n", tce.te_word );
> show_stack(current, (unsigned long *)__get_SP());
> }
> }
>
> static void iommu_table_setparms(struct pci_controller *phb,
> struct device_node *dn,
> - struct iommu_table *tbl)
> + struct iommu_table *tbl)
> {
> struct device_node *node;
> unsigned long *basep;
> @@ -275,16 +257,16 @@ static void iommu_table_setparms(struct
> memset((void *)tbl->it_base, 0, *sizep);
>
> tbl->it_busno = phb->bus->number;
> -
> +
> /* Units of tce entries */
> tbl->it_offset = phb->dma_window_base_cur >> PAGE_SHIFT;
> -
> +
> /* Test if we are going over 2GB of DMA space */
> if (phb->dma_window_base_cur + phb->dma_window_size > 0x80000000ul) {
> udbg_printf("PCI_DMA: Unexpected number of IOAs under this PHB.\n");
> - panic("PCI_DMA: Unexpected number of IOAs under this PHB.\n");
> + panic("PCI_DMA: Unexpected number of IOAs under this PHB.\n");
> }
> -
> +
> phb->dma_window_base_cur += phb->dma_window_size;
>
> /* Set the tce table size - measured in entries */
> @@ -442,7 +424,7 @@ static void iommu_bus_setup_pSeriesLP(st
>
> tbl = (struct iommu_table *)kmalloc(sizeof(struct iommu_table),
> GFP_KERNEL);
> -
> +
> iommu_table_setparms_lpar(ppci->phb, pdn, tbl, dma_window);
>
> ppci->iommu_table = iommu_init_table(tbl);
> Index: powerpc/include/asm-powerpc/tce.h
> ===================================================================
> --- powerpc.orig/include/asm-powerpc/tce.h
> +++ powerpc/include/asm-powerpc/tce.h
> @@ -35,32 +35,15 @@
> #define TCE_PAGE_SIZE (1 << TCE_SHIFT)
> #define TCE_PAGE_FACTOR (PAGE_SHIFT - TCE_SHIFT)
>
> +#define TCE_ENTRY_SIZE 8 /* each TCE is 64 bits */
>
> -/* tce_entry
> - * Used by pSeries (SMP) and iSeries/pSeries LPAR, but there it's
> - * abstracted so layout is irrelevant.
> - */
> -union tce_entry {
> - unsigned long te_word;
> - struct {
> - unsigned int tb_cacheBits :6; /* Cache hash bits - not used */
> - unsigned int tb_rsvd :6;
> - unsigned long tb_rpn :40; /* Real page number */
> - unsigned int tb_valid :1; /* Tce is valid (vb only) */
> - unsigned int tb_allio :1; /* Tce is valid for all lps (vb only) */
> - unsigned int tb_lpindex :8; /* LpIndex for user of TCE (vb only) */
> - unsigned int tb_pciwr :1; /* Write allowed (pci only) */
> - unsigned int tb_rdwr :1; /* Read allowed (pci), Write allowed (vb) */
> - } te_bits;
> -#define te_cacheBits te_bits.tb_cacheBits
> -#define te_rpn te_bits.tb_rpn
> -#define te_valid te_bits.tb_valid
> -#define te_allio te_bits.tb_allio
> -#define te_lpindex te_bits.tb_lpindex
> -#define te_pciwr te_bits.tb_pciwr
> -#define te_rdwr te_bits.tb_rdwr
> -};
> -
> +#define TCE_RPN_MASK 0xfffffffffful /* 40-bit RPN (4K pages) */
> +#define TCE_RPN_SHIFT 12
> +#define TCE_VALID 0x200 /* TCE valid */
> +#define TCE_ALLIO 0x100 /* TCE valid for all lpars */
> +#define TCE_PCI_WRITE 0x2 /* write from PCI allowed */
> +#define TCE_PCI_READ 0x1 /* read from PCI allowed */
> +#define TCE_VB_WRITE 0x1 /* write from VB allowed */
>
> #endif /* __KERNEL__ */
> #endif /* _ASM_POWERPC_TCE_H */
> _______________________________________________
> Linuxppc-dev mailing list
> Linuxppc-dev@ozlabs.org
> https://ozlabs.org/mailman/listinfo/linuxppc-dev
^ permalink raw reply
* Re: FT u-boot shim
From: Tom Rini @ 2006-04-28 19:44 UTC (permalink / raw)
To: Wolfgang Denk; +Cc: linuxppc-dev@ozlabs.org list, Paul Mackerras
In-Reply-To: <20060428191124.B202B353DAC@atlas.denx.de>
On Fri, Apr 28, 2006 at 09:11:24PM +0200, Wolfgang Denk wrote:
> In message <EA2821E8-FB7E-4DDA-8C18-C659B5483DC2@kernel.crashing.org>
> Kumar Gala wrote:
> >
> > What I envision as the way one boots for something like u-boot is one
> > of three options:
> > 1. using an old u-boot + boot wrapper (bd_t -> wrapper -> kernel)
> > 2. using a u-boot that is ft aware + dtb (boot command in u-boot
> > takes kernel & dtb images, updates blob and passes to kernel)
> > 3. using a u-boot that is ft aware + built in dtb.
> >
> > The issue is that for a given system/board you may need to support
> > multiple or all three. This raises the question where does the .dts
>
> Assuming we had 2., under which circumstances would we need 3. then?
Especially if we had mkuimage let you tack your dtb into the 'kernel'
image.
--
Tom Rini
http://gate.crashing.org/~trini/
^ permalink raw reply
* [patch 0/4] cell: support multi-platform image
From: Geoff Levand @ 2006-04-28 21:44 UTC (permalink / raw)
To: Paul Mackerras; +Cc: linuxppc-dev, cbe-oss-dev, arnd
Paul,
This series of patches adds support to build multi-platform
images with Cell BPA targets.
These patches apply to current powerpc.git, and should be
considered for inclusion in 2.6.18
They have already seen some review on the
cbe-oss-dev@ozlabs.org ML.
-Geoff
^ permalink raw reply
* [patch 1/4] spufs: add missing headers
From: Geoff Levand @ 2006-04-28 21:44 UTC (permalink / raw)
To: Paul Mackerras; +Cc: linuxppc-dev, cbe-oss-dev, arnd
Add spu.h header dependencies. Fixes these errors:
spu.h:168: warning: 'struct file' declared inside parameter list
spu.h:186: error: syntax error before 'cell_spumem_init'
Signed-off-by: Geoff Levand <geoffrey.levand@am.sony.com>
---
Index: linux-powerpc.git/include/asm-powerpc/spu.h
===================================================================
--- linux-powerpc.git.orig/include/asm-powerpc/spu.h 2006-04-28 14:32:25.000000000 -0700
+++ linux-powerpc.git/include/asm-powerpc/spu.h 2006-04-28 14:38:18.000000000 -0700
@@ -27,6 +27,8 @@
#include <linux/config.h>
#include <linux/kref.h>
#include <linux/workqueue.h>
+#include <linux/file.h>
+#include <linux/init.h>
#define LS_SIZE (256 * 1024)
#define LS_ADDR_MASK (LS_SIZE - 1)
^ permalink raw reply
* [patch 2/4] cell: split out platform code
From: Geoff Levand @ 2006-04-28 21:44 UTC (permalink / raw)
To: Paul Mackerras; +Cc: linuxppc-dev, cbe-oss-dev, arnd
Split the Cell BPA support into generic and platform
dependant parts.
Creates a new config variable CONFIG_PPC_IBM_CELL_BLADE.
The existing CONFIG_PPC_CELL is now used to denote the
generic Cell processor support. Also renames spu_priv1.c
to spu_priv1_mmio.c.
Signed-off-by: Geoff Levand <geoffrey.levand@am.sony.com>
---
Index: linux-powerpc.git/arch/powerpc/Kconfig
===================================================================
--- linux-powerpc.git.orig/arch/powerpc/Kconfig 2006-04-28 14:32:25.000000000 -0700
+++ linux-powerpc.git/arch/powerpc/Kconfig 2006-04-28 14:34:06.000000000 -0700
@@ -391,11 +391,17 @@
For more informations, refer to <http://www.970eval.com>
config PPC_CELL
- bool " Cell Broadband Processor Architecture"
+ bool
+ default n
+
+config PPC_IBM_CELL_BLADE
+ bool " IBM Cell Blade"
depends on PPC_MULTIPLATFORM && PPC64
+ select PPC_CELL
select PPC_RTAS
select MMIO_NVRAM
select PPC_UDBG_16550
+ select SPUFS_PRIV1_MMIO
config XICS
depends on PPC_PSERIES
@@ -440,7 +446,7 @@
default y
config CELL_IIC
- depends on PPC_CELL
+ depends on PPC_IBM_CELL_BLADE
bool
default y
Index: linux-powerpc.git/arch/powerpc/configs/cell_defconfig
===================================================================
--- linux-powerpc.git.orig/arch/powerpc/configs/cell_defconfig 2006-04-28 14:32:25.000000000 -0700
+++ linux-powerpc.git/arch/powerpc/configs/cell_defconfig 2006-04-28 14:34:06.000000000 -0700
@@ -118,6 +118,7 @@
# CONFIG_PPC_PMAC is not set
# CONFIG_PPC_MAPLE is not set
CONFIG_PPC_CELL=y
+CONFIG_PPC_IBM_CELL_BLADE=y
# CONFIG_U3_DART is not set
CONFIG_PPC_RTAS=y
# CONFIG_RTAS_ERROR_LOGGING is not set
@@ -133,6 +134,8 @@
# Cell Broadband Engine options
#
CONFIG_SPU_FS=m
+CONFIG_SPU_BASE=y
+CONFIG_SPUFS_PRIV1_MMIO=y
CONFIG_SPUFS_MMAP=y
#
Index: linux-powerpc.git/arch/powerpc/platforms/cell/Kconfig
===================================================================
--- linux-powerpc.git.orig/arch/powerpc/platforms/cell/Kconfig 2006-04-28 14:32:25.000000000 -0700
+++ linux-powerpc.git/arch/powerpc/platforms/cell/Kconfig 2006-04-28 14:34:06.000000000 -0700
@@ -5,11 +5,20 @@
tristate "SPU file system"
default m
depends on PPC_CELL
+ select SPU_BASE
help
The SPU file system is used to access Synergistic Processing
Units on machines implementing the Broadband Processor
Architecture.
+config SPU_BASE
+ bool
+ default n
+
+config SPUFS_PRIV1_MMIO
+ bool
+ default n
+
config SPUFS_MMAP
bool
depends on SPU_FS && SPARSEMEM && !PPC_64K_PAGES
Index: linux-powerpc.git/arch/powerpc/platforms/cell/Makefile
===================================================================
--- linux-powerpc.git.orig/arch/powerpc/platforms/cell/Makefile 2006-04-28 14:32:25.000000000 -0700
+++ linux-powerpc.git/arch/powerpc/platforms/cell/Makefile 2006-04-28 14:34:06.000000000 -0700
@@ -1,16 +1,13 @@
-obj-y += interrupt.o iommu.o setup.o spider-pic.o
-obj-y += pervasive.o
-
-obj-$(CONFIG_SMP) += smp.o
-obj-$(CONFIG_SPU_FS) += spu-base.o spufs/
-
-spu-base-y += spu_base.o spu_priv1.o
+obj-$(CONFIG_PPC_IBM_CELL_BLADE) += interrupt.o iommu.o setup.o \
+ spider-pic.o pervasive.o
+ifeq ($(CONFIG_SMP),y)
+obj-$(CONFIG_PPC_IBM_CELL_BLADE) += smp.o
+endif
# needed only when building loadable spufs.ko
-spufs-modular-$(CONFIG_SPU_FS) += spu_syscalls.o
-obj-y += $(spufs-modular-m)
-
-# always needed in kernel
-spufs-builtin-$(CONFIG_SPU_FS) += spu_callbacks.o
-obj-y += $(spufs-builtin-y) $(spufs-builtin-m)
+spufs-modular-$(CONFIG_SPU_FS) += spu_syscalls.o
+obj-$(CONFIG_SPU_BASE) += spu_callbacks.o spu_base.o \
+ $(spufs-modular-m)
+obj-$(CONFIG_SPUFS_PRIV1_MMIO) += spu_priv1_mmio.o
+obj-$(CONFIG_SPU_FS) += spufs/
Index: linux-powerpc.git/arch/powerpc/platforms/cell/spu_priv1.c
===================================================================
--- linux-powerpc.git.orig/arch/powerpc/platforms/cell/spu_priv1.c 2006-04-28 14:32:25.000000000 -0700
+++ linux-powerpc.git/arch/powerpc/platforms/cell/spu_priv1.c 2006-04-21 13:04:41.284693750 -0700
@@ -1,133 +0,0 @@
-/*
- * access to SPU privileged registers
- */
-#include <linux/module.h>
-
-#include <asm/io.h>
-#include <asm/spu.h>
-
-void spu_int_mask_and(struct spu *spu, int class, u64 mask)
-{
- u64 old_mask;
-
- old_mask = in_be64(&spu->priv1->int_mask_RW[class]);
- out_be64(&spu->priv1->int_mask_RW[class], old_mask & mask);
-}
-EXPORT_SYMBOL_GPL(spu_int_mask_and);
-
-void spu_int_mask_or(struct spu *spu, int class, u64 mask)
-{
- u64 old_mask;
-
- old_mask = in_be64(&spu->priv1->int_mask_RW[class]);
- out_be64(&spu->priv1->int_mask_RW[class], old_mask | mask);
-}
-EXPORT_SYMBOL_GPL(spu_int_mask_or);
-
-void spu_int_mask_set(struct spu *spu, int class, u64 mask)
-{
- out_be64(&spu->priv1->int_mask_RW[class], mask);
-}
-EXPORT_SYMBOL_GPL(spu_int_mask_set);
-
-u64 spu_int_mask_get(struct spu *spu, int class)
-{
- return in_be64(&spu->priv1->int_mask_RW[class]);
-}
-EXPORT_SYMBOL_GPL(spu_int_mask_get);
-
-void spu_int_stat_clear(struct spu *spu, int class, u64 stat)
-{
- out_be64(&spu->priv1->int_stat_RW[class], stat);
-}
-EXPORT_SYMBOL_GPL(spu_int_stat_clear);
-
-u64 spu_int_stat_get(struct spu *spu, int class)
-{
- return in_be64(&spu->priv1->int_stat_RW[class]);
-}
-EXPORT_SYMBOL_GPL(spu_int_stat_get);
-
-void spu_int_route_set(struct spu *spu, u64 route)
-{
- out_be64(&spu->priv1->int_route_RW, route);
-}
-EXPORT_SYMBOL_GPL(spu_int_route_set);
-
-u64 spu_mfc_dar_get(struct spu *spu)
-{
- return in_be64(&spu->priv1->mfc_dar_RW);
-}
-EXPORT_SYMBOL_GPL(spu_mfc_dar_get);
-
-u64 spu_mfc_dsisr_get(struct spu *spu)
-{
- return in_be64(&spu->priv1->mfc_dsisr_RW);
-}
-EXPORT_SYMBOL_GPL(spu_mfc_dsisr_get);
-
-void spu_mfc_dsisr_set(struct spu *spu, u64 dsisr)
-{
- out_be64(&spu->priv1->mfc_dsisr_RW, dsisr);
-}
-EXPORT_SYMBOL_GPL(spu_mfc_dsisr_set);
-
-void spu_mfc_sdr_set(struct spu *spu, u64 sdr)
-{
- out_be64(&spu->priv1->mfc_sdr_RW, sdr);
-}
-EXPORT_SYMBOL_GPL(spu_mfc_sdr_set);
-
-void spu_mfc_sr1_set(struct spu *spu, u64 sr1)
-{
- out_be64(&spu->priv1->mfc_sr1_RW, sr1);
-}
-EXPORT_SYMBOL_GPL(spu_mfc_sr1_set);
-
-u64 spu_mfc_sr1_get(struct spu *spu)
-{
- return in_be64(&spu->priv1->mfc_sr1_RW);
-}
-EXPORT_SYMBOL_GPL(spu_mfc_sr1_get);
-
-void spu_mfc_tclass_id_set(struct spu *spu, u64 tclass_id)
-{
- out_be64(&spu->priv1->mfc_tclass_id_RW, tclass_id);
-}
-EXPORT_SYMBOL_GPL(spu_mfc_tclass_id_set);
-
-u64 spu_mfc_tclass_id_get(struct spu *spu)
-{
- return in_be64(&spu->priv1->mfc_tclass_id_RW);
-}
-EXPORT_SYMBOL_GPL(spu_mfc_tclass_id_get);
-
-void spu_tlb_invalidate(struct spu *spu)
-{
- out_be64(&spu->priv1->tlb_invalidate_entry_W, 0ul);
-}
-EXPORT_SYMBOL_GPL(spu_tlb_invalidate);
-
-void spu_resource_allocation_groupID_set(struct spu *spu, u64 id)
-{
- out_be64(&spu->priv1->resource_allocation_groupID_RW, id);
-}
-EXPORT_SYMBOL_GPL(spu_resource_allocation_groupID_set);
-
-u64 spu_resource_allocation_groupID_get(struct spu *spu)
-{
- return in_be64(&spu->priv1->resource_allocation_groupID_RW);
-}
-EXPORT_SYMBOL_GPL(spu_resource_allocation_groupID_get);
-
-void spu_resource_allocation_enable_set(struct spu *spu, u64 enable)
-{
- out_be64(&spu->priv1->resource_allocation_enable_RW, enable);
-}
-EXPORT_SYMBOL_GPL(spu_resource_allocation_enable_set);
-
-u64 spu_resource_allocation_enable_get(struct spu *spu)
-{
- return in_be64(&spu->priv1->resource_allocation_enable_RW);
-}
-EXPORT_SYMBOL_GPL(spu_resource_allocation_enable_get);
Index: linux-powerpc.git/arch/powerpc/platforms/cell/spu_priv1_mmio.c
===================================================================
--- linux-powerpc.git.orig/arch/powerpc/platforms/cell/spu_priv1_mmio.c 2006-04-21 13:04:41.284693750 -0700
+++ linux-powerpc.git/arch/powerpc/platforms/cell/spu_priv1_mmio.c 2006-04-28 14:38:18.000000000 -0700
@@ -0,0 +1,133 @@
+/*
+ * access to SPU privileged registers
+ */
+#include <linux/module.h>
+
+#include <asm/io.h>
+#include <asm/spu.h>
+
+void spu_int_mask_and(struct spu *spu, int class, u64 mask)
+{
+ u64 old_mask;
+
+ old_mask = in_be64(&spu->priv1->int_mask_RW[class]);
+ out_be64(&spu->priv1->int_mask_RW[class], old_mask & mask);
+}
+EXPORT_SYMBOL_GPL(spu_int_mask_and);
+
+void spu_int_mask_or(struct spu *spu, int class, u64 mask)
+{
+ u64 old_mask;
+
+ old_mask = in_be64(&spu->priv1->int_mask_RW[class]);
+ out_be64(&spu->priv1->int_mask_RW[class], old_mask | mask);
+}
+EXPORT_SYMBOL_GPL(spu_int_mask_or);
+
+void spu_int_mask_set(struct spu *spu, int class, u64 mask)
+{
+ out_be64(&spu->priv1->int_mask_RW[class], mask);
+}
+EXPORT_SYMBOL_GPL(spu_int_mask_set);
+
+u64 spu_int_mask_get(struct spu *spu, int class)
+{
+ return in_be64(&spu->priv1->int_mask_RW[class]);
+}
+EXPORT_SYMBOL_GPL(spu_int_mask_get);
+
+void spu_int_stat_clear(struct spu *spu, int class, u64 stat)
+{
+ out_be64(&spu->priv1->int_stat_RW[class], stat);
+}
+EXPORT_SYMBOL_GPL(spu_int_stat_clear);
+
+u64 spu_int_stat_get(struct spu *spu, int class)
+{
+ return in_be64(&spu->priv1->int_stat_RW[class]);
+}
+EXPORT_SYMBOL_GPL(spu_int_stat_get);
+
+void spu_int_route_set(struct spu *spu, u64 route)
+{
+ out_be64(&spu->priv1->int_route_RW, route);
+}
+EXPORT_SYMBOL_GPL(spu_int_route_set);
+
+u64 spu_mfc_dar_get(struct spu *spu)
+{
+ return in_be64(&spu->priv1->mfc_dar_RW);
+}
+EXPORT_SYMBOL_GPL(spu_mfc_dar_get);
+
+u64 spu_mfc_dsisr_get(struct spu *spu)
+{
+ return in_be64(&spu->priv1->mfc_dsisr_RW);
+}
+EXPORT_SYMBOL_GPL(spu_mfc_dsisr_get);
+
+void spu_mfc_dsisr_set(struct spu *spu, u64 dsisr)
+{
+ out_be64(&spu->priv1->mfc_dsisr_RW, dsisr);
+}
+EXPORT_SYMBOL_GPL(spu_mfc_dsisr_set);
+
+void spu_mfc_sdr_set(struct spu *spu, u64 sdr)
+{
+ out_be64(&spu->priv1->mfc_sdr_RW, sdr);
+}
+EXPORT_SYMBOL_GPL(spu_mfc_sdr_set);
+
+void spu_mfc_sr1_set(struct spu *spu, u64 sr1)
+{
+ out_be64(&spu->priv1->mfc_sr1_RW, sr1);
+}
+EXPORT_SYMBOL_GPL(spu_mfc_sr1_set);
+
+u64 spu_mfc_sr1_get(struct spu *spu)
+{
+ return in_be64(&spu->priv1->mfc_sr1_RW);
+}
+EXPORT_SYMBOL_GPL(spu_mfc_sr1_get);
+
+void spu_mfc_tclass_id_set(struct spu *spu, u64 tclass_id)
+{
+ out_be64(&spu->priv1->mfc_tclass_id_RW, tclass_id);
+}
+EXPORT_SYMBOL_GPL(spu_mfc_tclass_id_set);
+
+u64 spu_mfc_tclass_id_get(struct spu *spu)
+{
+ return in_be64(&spu->priv1->mfc_tclass_id_RW);
+}
+EXPORT_SYMBOL_GPL(spu_mfc_tclass_id_get);
+
+void spu_tlb_invalidate(struct spu *spu)
+{
+ out_be64(&spu->priv1->tlb_invalidate_entry_W, 0ul);
+}
+EXPORT_SYMBOL_GPL(spu_tlb_invalidate);
+
+void spu_resource_allocation_groupID_set(struct spu *spu, u64 id)
+{
+ out_be64(&spu->priv1->resource_allocation_groupID_RW, id);
+}
+EXPORT_SYMBOL_GPL(spu_resource_allocation_groupID_set);
+
+u64 spu_resource_allocation_groupID_get(struct spu *spu)
+{
+ return in_be64(&spu->priv1->resource_allocation_groupID_RW);
+}
+EXPORT_SYMBOL_GPL(spu_resource_allocation_groupID_get);
+
+void spu_resource_allocation_enable_set(struct spu *spu, u64 enable)
+{
+ out_be64(&spu->priv1->resource_allocation_enable_RW, enable);
+}
+EXPORT_SYMBOL_GPL(spu_resource_allocation_enable_set);
+
+u64 spu_resource_allocation_enable_get(struct spu *spu)
+{
+ return in_be64(&spu->priv1->resource_allocation_enable_RW);
+}
+EXPORT_SYMBOL_GPL(spu_resource_allocation_enable_get);
Index: linux-powerpc.git/drivers/net/Kconfig
===================================================================
--- linux-powerpc.git.orig/drivers/net/Kconfig 2006-04-28 14:32:25.000000000 -0700
+++ linux-powerpc.git/drivers/net/Kconfig 2006-04-28 14:34:06.000000000 -0700
@@ -2171,7 +2171,7 @@
config SPIDER_NET
tristate "Spider Gigabit Ethernet driver"
- depends on PCI && PPC_CELL
+ depends on PCI && PPC_IBM_CELL_BLADE
select FW_LOADER
help
This driver supports the Gigabit Ethernet chips present on the
^ permalink raw reply
* [patch 3/4] spufs: support multi-platform priv1 access
From: Geoff Levand @ 2006-04-28 21:44 UTC (permalink / raw)
To: Paul Mackerras; +Cc: linuxppc-dev, cbe-oss-dev, arnd
To support muti-platform binaries the spu hypervisor accessor
routines must have runtime binding.
I removed the existing statically linked routines in spu.h
and spu_priv1_mmio.c and created new accessor routines in spu_priv1.h
that operate indirectly through an ops struct spu_priv1_ops.
spu_priv1_mmio.c contains the instance of the accessor routines
for running on raw hardware.
Signed-off-by: Geoff Levand <geoffrey.levand@am.sony.com>
---
Index: linux-powerpc.git/arch/powerpc/platforms/cell/setup.c
===================================================================
--- linux-powerpc.git.orig/arch/powerpc/platforms/cell/setup.c 2006-04-28 14:32:25.000000000 -0700
+++ linux-powerpc.git/arch/powerpc/platforms/cell/setup.c 2006-04-28 14:34:06.000000000 -0700
@@ -46,6 +46,7 @@
#include <asm/cputable.h>
#include <asm/ppc-pci.h>
#include <asm/irq.h>
+#include <asm/spu_priv1.h>
#include "interrupt.h"
#include "iommu.h"
@@ -149,6 +150,9 @@
{
ppc_md.init_IRQ = iic_init_IRQ;
ppc_md.get_irq = iic_get_irq;
+#ifdef CONFIG_SPU_BASE
+ spu_priv1_ops = &spu_priv1_mmio_ops;
+#endif
#ifdef CONFIG_SMP
smp_init_cell();
Index: linux-powerpc.git/arch/powerpc/platforms/cell/spu_base.c
===================================================================
--- linux-powerpc.git.orig/arch/powerpc/platforms/cell/spu_base.c 2006-04-28 14:32:25.000000000 -0700
+++ linux-powerpc.git/arch/powerpc/platforms/cell/spu_base.c 2006-04-28 14:38:16.000000000 -0700
@@ -34,10 +34,15 @@
#include <asm/prom.h>
#include <linux/mutex.h>
#include <asm/spu.h>
+#include <asm/spu_priv1.h>
#include <asm/mmu_context.h>
#include "interrupt.h"
+const struct spu_priv1_ops *spu_priv1_ops;
+
+EXPORT_SYMBOL_GPL(spu_priv1_ops);
+
static int __spu_trap_invalid_dma(struct spu *spu)
{
pr_debug("%s\n", __FUNCTION__);
@@ -687,6 +692,8 @@
struct device_node *node;
int ret;
+ BUG_ON(!spu_priv1_ops);
+
ret = -ENODEV;
for (node = of_find_node_by_type(NULL, "spe");
node; node = of_find_node_by_type(node, "spe")) {
Index: linux-powerpc.git/arch/powerpc/platforms/cell/spu_priv1_mmio.c
===================================================================
--- linux-powerpc.git.orig/arch/powerpc/platforms/cell/spu_priv1_mmio.c 2006-04-28 14:34:06.000000000 -0700
+++ linux-powerpc.git/arch/powerpc/platforms/cell/spu_priv1_mmio.c 2006-04-28 14:38:16.000000000 -0700
@@ -1,133 +1,165 @@
/*
- * access to SPU privileged registers
+ * spu hypervisor abstraction for direct hardware access.
+ *
+ * (C) Copyright IBM Deutschland Entwicklung GmbH 2005
+ * Copyright 2006 Sony Corp.
+ *
+ * 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; version 2 of the License.
+ *
+ * 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 <linux/module.h>
#include <asm/io.h>
#include <asm/spu.h>
+#include <asm/spu_priv1.h>
-void spu_int_mask_and(struct spu *spu, int class, u64 mask)
+static void int_mask_and(struct spu *spu, int class, u64 mask)
{
u64 old_mask;
old_mask = in_be64(&spu->priv1->int_mask_RW[class]);
out_be64(&spu->priv1->int_mask_RW[class], old_mask & mask);
}
-EXPORT_SYMBOL_GPL(spu_int_mask_and);
-void spu_int_mask_or(struct spu *spu, int class, u64 mask)
+static void int_mask_or(struct spu *spu, int class, u64 mask)
{
u64 old_mask;
old_mask = in_be64(&spu->priv1->int_mask_RW[class]);
out_be64(&spu->priv1->int_mask_RW[class], old_mask | mask);
}
-EXPORT_SYMBOL_GPL(spu_int_mask_or);
-void spu_int_mask_set(struct spu *spu, int class, u64 mask)
+static void int_mask_set(struct spu *spu, int class, u64 mask)
{
out_be64(&spu->priv1->int_mask_RW[class], mask);
}
-EXPORT_SYMBOL_GPL(spu_int_mask_set);
-u64 spu_int_mask_get(struct spu *spu, int class)
+static u64 int_mask_get(struct spu *spu, int class)
{
return in_be64(&spu->priv1->int_mask_RW[class]);
}
-EXPORT_SYMBOL_GPL(spu_int_mask_get);
-void spu_int_stat_clear(struct spu *spu, int class, u64 stat)
+static void int_stat_clear(struct spu *spu, int class, u64 stat)
{
out_be64(&spu->priv1->int_stat_RW[class], stat);
}
-EXPORT_SYMBOL_GPL(spu_int_stat_clear);
-u64 spu_int_stat_get(struct spu *spu, int class)
+static u64 int_stat_get(struct spu *spu, int class)
{
return in_be64(&spu->priv1->int_stat_RW[class]);
}
-EXPORT_SYMBOL_GPL(spu_int_stat_get);
-void spu_int_route_set(struct spu *spu, u64 route)
+static void int_route_set(struct spu *spu, u64 route)
{
out_be64(&spu->priv1->int_route_RW, route);
}
-EXPORT_SYMBOL_GPL(spu_int_route_set);
-u64 spu_mfc_dar_get(struct spu *spu)
+static u64 mfc_dar_get(struct spu *spu)
{
return in_be64(&spu->priv1->mfc_dar_RW);
}
-EXPORT_SYMBOL_GPL(spu_mfc_dar_get);
-u64 spu_mfc_dsisr_get(struct spu *spu)
+static u64 mfc_dsisr_get(struct spu *spu)
{
return in_be64(&spu->priv1->mfc_dsisr_RW);
}
-EXPORT_SYMBOL_GPL(spu_mfc_dsisr_get);
-void spu_mfc_dsisr_set(struct spu *spu, u64 dsisr)
+static void mfc_dsisr_set(struct spu *spu, u64 dsisr)
{
out_be64(&spu->priv1->mfc_dsisr_RW, dsisr);
}
-EXPORT_SYMBOL_GPL(spu_mfc_dsisr_set);
-void spu_mfc_sdr_set(struct spu *spu, u64 sdr)
+static void mfc_sdr_set(struct spu *spu, u64 sdr)
{
out_be64(&spu->priv1->mfc_sdr_RW, sdr);
}
-EXPORT_SYMBOL_GPL(spu_mfc_sdr_set);
-void spu_mfc_sr1_set(struct spu *spu, u64 sr1)
+static void mfc_sr1_set(struct spu *spu, u64 sr1)
{
out_be64(&spu->priv1->mfc_sr1_RW, sr1);
}
-EXPORT_SYMBOL_GPL(spu_mfc_sr1_set);
-u64 spu_mfc_sr1_get(struct spu *spu)
+static u64 mfc_sr1_get(struct spu *spu)
{
return in_be64(&spu->priv1->mfc_sr1_RW);
}
-EXPORT_SYMBOL_GPL(spu_mfc_sr1_get);
-void spu_mfc_tclass_id_set(struct spu *spu, u64 tclass_id)
+static void mfc_tclass_id_set(struct spu *spu, u64 tclass_id)
{
out_be64(&spu->priv1->mfc_tclass_id_RW, tclass_id);
}
-EXPORT_SYMBOL_GPL(spu_mfc_tclass_id_set);
-u64 spu_mfc_tclass_id_get(struct spu *spu)
+static u64 mfc_tclass_id_get(struct spu *spu)
{
return in_be64(&spu->priv1->mfc_tclass_id_RW);
}
-EXPORT_SYMBOL_GPL(spu_mfc_tclass_id_get);
-void spu_tlb_invalidate(struct spu *spu)
+static void smm_pgsz_set(struct spu *spu, u64 pgsz)
+{
+ u64 smm_hid;
+ smm_hid = in_be64(&spu->priv1->smm_hid);
+ smm_hid &= ~(0xfull << 60);
+ smm_hid |= pgsz << 60;
+ out_be64(&spu->priv1->smm_hid, smm_hid);
+}
+
+static void tlb_invalidate(struct spu *spu)
{
out_be64(&spu->priv1->tlb_invalidate_entry_W, 0ul);
}
-EXPORT_SYMBOL_GPL(spu_tlb_invalidate);
-void spu_resource_allocation_groupID_set(struct spu *spu, u64 id)
+static void resource_allocation_groupID_set(struct spu *spu, u64 id)
{
out_be64(&spu->priv1->resource_allocation_groupID_RW, id);
}
-EXPORT_SYMBOL_GPL(spu_resource_allocation_groupID_set);
-u64 spu_resource_allocation_groupID_get(struct spu *spu)
+static u64 resource_allocation_groupID_get(struct spu *spu)
{
return in_be64(&spu->priv1->resource_allocation_groupID_RW);
}
-EXPORT_SYMBOL_GPL(spu_resource_allocation_groupID_get);
-void spu_resource_allocation_enable_set(struct spu *spu, u64 enable)
+static void resource_allocation_enable_set(struct spu *spu, u64 enable)
{
out_be64(&spu->priv1->resource_allocation_enable_RW, enable);
}
-EXPORT_SYMBOL_GPL(spu_resource_allocation_enable_set);
-u64 spu_resource_allocation_enable_get(struct spu *spu)
+static u64 resource_allocation_enable_get(struct spu *spu)
{
return in_be64(&spu->priv1->resource_allocation_enable_RW);
}
-EXPORT_SYMBOL_GPL(spu_resource_allocation_enable_get);
+
+const struct spu_priv1_ops spu_priv1_mmio_ops =
+{
+ .int_mask_and = int_mask_and,
+ .int_mask_or = int_mask_or,
+ .int_mask_set = int_mask_set,
+ .int_mask_get = int_mask_get,
+ .int_stat_clear = int_stat_clear,
+ .int_stat_get = int_stat_get,
+ .int_route_set = int_route_set,
+ .mfc_dar_get = mfc_dar_get,
+ .mfc_dsisr_get = mfc_dsisr_get,
+ .mfc_dsisr_set = mfc_dsisr_set,
+ .mfc_sdr_set = mfc_sdr_set,
+ .mfc_sr1_set = mfc_sr1_set,
+ .mfc_sr1_get = mfc_sr1_get,
+ .mfc_tclass_id_set = mfc_tclass_id_set,
+ .mfc_tclass_id_get = mfc_tclass_id_get,
+ .smm_pgsz_set = smm_pgsz_set,
+ .tlb_invalidate = tlb_invalidate,
+ .resource_allocation_groupID_set = resource_allocation_groupID_set,
+ .resource_allocation_groupID_get = resource_allocation_groupID_get,
+ .resource_allocation_enable_set = resource_allocation_enable_set,
+ .resource_allocation_enable_get = resource_allocation_enable_get,
+};
Index: linux-powerpc.git/arch/powerpc/platforms/cell/spufs/hw_ops.c
===================================================================
--- linux-powerpc.git.orig/arch/powerpc/platforms/cell/spufs/hw_ops.c 2006-04-28 14:32:25.000000000 -0700
+++ linux-powerpc.git/arch/powerpc/platforms/cell/spufs/hw_ops.c 2006-04-28 14:34:06.000000000 -0700
@@ -32,6 +32,7 @@
#include <asm/io.h>
#include <asm/spu.h>
+#include <asm/spu_priv1.h>
#include <asm/spu_csa.h>
#include <asm/mmu_context.h>
#include "spufs.h"
Index: linux-powerpc.git/arch/powerpc/platforms/cell/spufs/switch.c
===================================================================
--- linux-powerpc.git.orig/arch/powerpc/platforms/cell/spufs/switch.c 2006-04-28 14:32:25.000000000 -0700
+++ linux-powerpc.git/arch/powerpc/platforms/cell/spufs/switch.c 2006-04-28 14:34:06.000000000 -0700
@@ -46,6 +46,7 @@
#include <asm/io.h>
#include <asm/spu.h>
+#include <asm/spu_priv1.h>
#include <asm/spu_csa.h>
#include <asm/mmu_context.h>
Index: linux-powerpc.git/include/asm-powerpc/spu.h
===================================================================
--- linux-powerpc.git.orig/include/asm-powerpc/spu.h 2006-04-28 14:34:06.000000000 -0700
+++ linux-powerpc.git/include/asm-powerpc/spu.h 2006-04-28 14:34:06.000000000 -0700
@@ -182,30 +182,6 @@
}
#endif /* MODULE */
-
-/* access to priv1 registers */
-void spu_int_mask_and(struct spu *spu, int class, u64 mask);
-void spu_int_mask_or(struct spu *spu, int class, u64 mask);
-void spu_int_mask_set(struct spu *spu, int class, u64 mask);
-u64 spu_int_mask_get(struct spu *spu, int class);
-void spu_int_stat_clear(struct spu *spu, int class, u64 stat);
-u64 spu_int_stat_get(struct spu *spu, int class);
-void spu_int_route_set(struct spu *spu, u64 route);
-u64 spu_mfc_dar_get(struct spu *spu);
-u64 spu_mfc_dsisr_get(struct spu *spu);
-void spu_mfc_dsisr_set(struct spu *spu, u64 dsisr);
-void spu_mfc_sdr_set(struct spu *spu, u64 sdr);
-void spu_mfc_sr1_set(struct spu *spu, u64 sr1);
-u64 spu_mfc_sr1_get(struct spu *spu);
-void spu_mfc_tclass_id_set(struct spu *spu, u64 tclass_id);
-u64 spu_mfc_tclass_id_get(struct spu *spu);
-void spu_tlb_invalidate(struct spu *spu);
-void spu_resource_allocation_groupID_set(struct spu *spu, u64 id);
-u64 spu_resource_allocation_groupID_get(struct spu *spu);
-void spu_resource_allocation_enable_set(struct spu *spu, u64 enable);
-u64 spu_resource_allocation_enable_get(struct spu *spu);
-
-
/*
* This defines the Local Store, Problem Area and Privlege Area of an SPU.
*/
Index: linux-powerpc.git/include/asm-powerpc/spu_priv1.h
===================================================================
--- linux-powerpc.git.orig/include/asm-powerpc/spu_priv1.h 2006-04-21 13:04:41.284693750 -0700
+++ linux-powerpc.git/include/asm-powerpc/spu_priv1.h 2006-04-28 14:38:16.000000000 -0700
@@ -0,0 +1,189 @@
+/*
+ * Defines an spu hypervisor abstraction layer.
+ *
+ * Copyright 2006 Sony Corp.
+ *
+ * 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; version 2 of the License.
+ *
+ * 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
+ */
+
+#if !defined(_SPU_PRIV1_H)
+#define _SPU_PRIV1_H
+#if defined(__KERNEL__)
+
+struct spu;
+
+/* access to priv1 registers */
+
+struct spu_priv1_ops
+{
+ void (*int_mask_and) (struct spu *spu, int class, u64 mask);
+ void (*int_mask_or) (struct spu *spu, int class, u64 mask);
+ void (*int_mask_set) (struct spu *spu, int class, u64 mask);
+ u64 (*int_mask_get) (struct spu *spu, int class);
+ void (*int_stat_clear) (struct spu *spu, int class, u64 stat);
+ u64 (*int_stat_get) (struct spu *spu, int class);
+ void (*int_route_set) (struct spu *spu, u64 route);
+ u64 (*mfc_dar_get) (struct spu *spu);
+ u64 (*mfc_dsisr_get) (struct spu *spu);
+ void (*mfc_dsisr_set) (struct spu *spu, u64 dsisr);
+ void (*mfc_sdr_set) (struct spu *spu, u64 sdr);
+ void (*mfc_sr1_set) (struct spu *spu, u64 sr1);
+ u64 (*mfc_sr1_get) (struct spu *spu);
+ void (*mfc_tclass_id_set) (struct spu *spu, u64 tclass_id);
+ u64 (*mfc_tclass_id_get) (struct spu *spu);
+ void (*smm_pgsz_set) (struct spu *spu, u64 pgsz);
+ void (*tlb_invalidate) (struct spu *spu);
+ void (*resource_allocation_groupID_set) (struct spu *spu, u64 id);
+ u64 (*resource_allocation_groupID_get) (struct spu *spu);
+ void (*resource_allocation_enable_set) (struct spu *spu, u64 enable);
+ u64 (*resource_allocation_enable_get) (struct spu *spu);
+};
+
+extern const struct spu_priv1_ops* spu_priv1_ops;
+
+static inline void
+spu_int_mask_and (struct spu *spu, int class, u64 mask)
+{
+ spu_priv1_ops->int_mask_and(spu, class, mask);
+}
+
+static inline void
+spu_int_mask_or (struct spu *spu, int class, u64 mask)
+{
+ spu_priv1_ops->int_mask_or(spu, class, mask);
+}
+
+static inline void
+spu_int_mask_set (struct spu *spu, int class, u64 mask)
+{
+ spu_priv1_ops->int_mask_set(spu, class, mask);
+}
+
+static inline u64
+spu_int_mask_get (struct spu *spu, int class)
+{
+ return spu_priv1_ops->int_mask_get(spu, class);
+}
+
+static inline void
+spu_int_stat_clear (struct spu *spu, int class, u64 stat)
+{
+ spu_priv1_ops->int_stat_clear(spu, class, stat);
+}
+
+static inline u64
+spu_int_stat_get (struct spu *spu, int class)
+{
+ return spu_priv1_ops->int_stat_get (spu, class);
+}
+
+static inline void
+spu_int_route_set (struct spu *spu, u64 route)
+{
+ spu_priv1_ops->int_stat_get(spu, route);
+}
+
+static inline u64
+spu_mfc_dar_get (struct spu *spu)
+{
+ return spu_priv1_ops->mfc_dar_get(spu);
+}
+
+static inline u64
+spu_mfc_dsisr_get (struct spu *spu)
+{
+ return spu_priv1_ops->mfc_dsisr_get(spu);
+}
+
+static inline void
+spu_mfc_dsisr_set (struct spu *spu, u64 dsisr)
+{
+ spu_priv1_ops->mfc_dsisr_set(spu, dsisr);
+}
+
+static inline void
+spu_mfc_sdr_set (struct spu *spu, u64 sdr)
+{
+ spu_priv1_ops->mfc_sdr_set(spu, sdr);
+}
+
+static inline void
+spu_mfc_sr1_set (struct spu *spu, u64 sr1)
+{
+ spu_priv1_ops->mfc_sr1_set(spu, sr1);
+}
+
+static inline u64
+spu_mfc_sr1_get (struct spu *spu)
+{
+ return spu_priv1_ops->mfc_sr1_get(spu);
+}
+
+static inline void
+spu_mfc_tclass_id_set (struct spu *spu, u64 tclass_id)
+{
+ spu_priv1_ops->mfc_tclass_id_set(spu, tclass_id);
+}
+
+static inline u64
+spu_mfc_tclass_id_get (struct spu *spu)
+{
+ return spu_priv1_ops->mfc_tclass_id_get(spu);
+}
+
+static inline void
+spu_smm_pgsz_set (struct spu *spu, u64 pgsz)
+{
+ spu_priv1_ops->smm_pgsz_set(spu, pgsz);
+}
+
+static inline void
+spu_tlb_invalidate (struct spu *spu)
+{
+ spu_priv1_ops->tlb_invalidate(spu);
+}
+
+static inline void
+spu_resource_allocation_groupID_set (struct spu *spu, u64 id)
+{
+ spu_priv1_ops->resource_allocation_groupID_set(spu, id);
+}
+
+static inline u64
+spu_resource_allocation_groupID_get (struct spu *spu)
+{
+ return spu_priv1_ops->resource_allocation_groupID_get(spu);
+}
+
+static inline void
+spu_resource_allocation_enable_set (struct spu *spu, u64 enable)
+{
+ spu_priv1_ops->resource_allocation_enable_set(spu, enable);
+}
+
+static inline u64
+spu_resource_allocation_enable_get (struct spu *spu)
+{
+ return spu_priv1_ops->resource_allocation_enable_get(spu);
+}
+
+/* The declarations folowing are put here for convenience
+ * and only intended to be used by the platform setup code
+ * for initializing spu_priv1_ops.
+ */
+
+extern const struct spu_priv1_ops spu_priv1_mmio_ops;
+
+#endif /* __KERNEL__ */
+#endif
^ permalink raw reply
* [patch 4/4] spufs: wrap cpu affinity
From: Geoff Levand @ 2006-04-28 21:44 UTC (permalink / raw)
To: Paul Mackerras; +Cc: linuxppc-dev, cbe-oss-dev, arnd
This changes the hypervisor abstraction of setting cpu affinity to a
higher level to avoid platform dependent interrupt controller
routines. I replaced spu_priv1_ops:spu_int_route_set() with a
new routine spu_priv1_ops:spu_cpu_affinity_set().
As a by-product, this change eliminated what looked like an
existing bug in the set affinity code where spu_int_route_set()
mistakenly called int_stat_get().
Signed-off-by: Geoff Levand <geoffrey.levand@am.sony.com>
---
Index: linux-powerpc.git/arch/powerpc/platforms/cell/spu_base.c
===================================================================
--- linux-powerpc.git.orig/arch/powerpc/platforms/cell/spu_base.c 2006-04-28 14:34:06.000000000 -0700
+++ linux-powerpc.git/arch/powerpc/platforms/cell/spu_base.c 2006-04-28 14:34:06.000000000 -0700
@@ -513,14 +513,6 @@
return ret;
}
-void spu_irq_setaffinity(struct spu *spu, int cpu)
-{
- u64 target = iic_get_target_id(cpu);
- u64 route = target << 48 | target << 32 | target << 16;
- spu_int_route_set(spu, route);
-}
-EXPORT_SYMBOL_GPL(spu_irq_setaffinity);
-
static void __iomem * __init map_spe_prop(struct device_node *n,
const char *name)
{
Index: linux-powerpc.git/arch/powerpc/platforms/cell/spu_priv1_mmio.c
===================================================================
--- linux-powerpc.git.orig/arch/powerpc/platforms/cell/spu_priv1_mmio.c 2006-04-28 14:34:06.000000000 -0700
+++ linux-powerpc.git/arch/powerpc/platforms/cell/spu_priv1_mmio.c 2006-04-28 14:34:06.000000000 -0700
@@ -24,6 +24,8 @@
#include <asm/spu.h>
#include <asm/spu_priv1.h>
+#include "interrupt.h"
+
static void int_mask_and(struct spu *spu, int class, u64 mask)
{
u64 old_mask;
@@ -60,8 +62,10 @@
return in_be64(&spu->priv1->int_stat_RW[class]);
}
-static void int_route_set(struct spu *spu, u64 route)
+static void cpu_affinity_set(struct spu *spu, int cpu)
{
+ u64 target = iic_get_target_id(cpu);
+ u64 route = target << 48 | target << 32 | target << 16;
out_be64(&spu->priv1->int_route_RW, route);
}
@@ -147,7 +151,7 @@
.int_mask_get = int_mask_get,
.int_stat_clear = int_stat_clear,
.int_stat_get = int_stat_get,
- .int_route_set = int_route_set,
+ .cpu_affinity_set = cpu_affinity_set,
.mfc_dar_get = mfc_dar_get,
.mfc_dsisr_get = mfc_dsisr_get,
.mfc_dsisr_set = mfc_dsisr_set,
Index: linux-powerpc.git/arch/powerpc/platforms/cell/spufs/sched.c
===================================================================
--- linux-powerpc.git.orig/arch/powerpc/platforms/cell/spufs/sched.c 2006-04-19 11:48:28.000000000 -0700
+++ linux-powerpc.git/arch/powerpc/platforms/cell/spufs/sched.c 2006-04-28 14:34:06.000000000 -0700
@@ -43,6 +43,7 @@
#include <asm/mmu_context.h>
#include <asm/spu.h>
#include <asm/spu_csa.h>
+#include <asm/spu_priv1.h>
#include "spufs.h"
#define SPU_MIN_TIMESLICE (100 * HZ / 1000)
@@ -363,7 +364,7 @@
* We're likely to wait for interrupts on the same
* CPU that we are now on, so send them here.
*/
- spu_irq_setaffinity(spu, raw_smp_processor_id());
+ spu_cpu_affinity_set(spu, raw_smp_processor_id());
put_active_spu(spu);
return 0;
}
Index: linux-powerpc.git/include/asm-powerpc/spu_priv1.h
===================================================================
--- linux-powerpc.git.orig/include/asm-powerpc/spu_priv1.h 2006-04-28 14:34:06.000000000 -0700
+++ linux-powerpc.git/include/asm-powerpc/spu_priv1.h 2006-04-28 14:34:06.000000000 -0700
@@ -33,7 +33,7 @@
u64 (*int_mask_get) (struct spu *spu, int class);
void (*int_stat_clear) (struct spu *spu, int class, u64 stat);
u64 (*int_stat_get) (struct spu *spu, int class);
- void (*int_route_set) (struct spu *spu, u64 route);
+ void (*cpu_affinity_set) (struct spu *spu, int cpu);
u64 (*mfc_dar_get) (struct spu *spu);
u64 (*mfc_dsisr_get) (struct spu *spu);
void (*mfc_dsisr_set) (struct spu *spu, u64 dsisr);
@@ -89,9 +89,9 @@
}
static inline void
-spu_int_route_set (struct spu *spu, u64 route)
+spu_cpu_affinity_set (struct spu *spu, int cpu)
{
- spu_priv1_ops->int_stat_get(spu, route);
+ spu_priv1_ops->cpu_affinity_set(spu, cpu);
}
static inline u64
^ permalink raw reply
* Re: [RFC , PATCH] support for the ibm,pa_features cpu property
From: Will Schmidt @ 2006-04-28 21:53 UTC (permalink / raw)
To: linuxppc-dev list; +Cc: paulus
In-Reply-To: <1146249684.27214.18.camel@localhost.localdomain>
Whoops.. funny thing occurred to me on my drive home.. comment inline
On Fri, 2006-04-28 at 13:41 -0500, Will Schmidt wrote:
> To determine if our processors support some features, such as large
> pages, we should be using the ibm,pa_features property, rather than just
> the PVR values.
> This is an initial pass at the functionality. This has been tested in
> the case where the property is missing, but still needs to be tested
> against a system where the property actually exists. :-o
>
>
>
> diff --git a/arch/powerpc/kernel/setup_64.c
> b/arch/powerpc/kernel/setup_64.c
> index 13e91c4..78ad054 100644
> --- a/arch/powerpc/kernel/setup_64.c
> +++ b/arch/powerpc/kernel/setup_64.c
> @@ -106,6 +106,65 @@ static struct notifier_block ppc64_panic
> .priority = INT_MIN /* may not return; must be done last */
> };
>
> +/*
> + * ibm,pa-features is a per-cpu property that contains a 2 byte header
> + * plus up to 256 bytes worth of processor attributes. First header
> + * byte specifies the number of bytes implemented by the platform.
> + * Second header byte is an "attribute-specifier" type, which should
> + * be zero. Remainder of the data consists of ones and zeros.
> + * Implementation: Pass in the byte and bit offset for the feature
> + * that we are interested in. The function will return -1 if the
> + * pa-features property is missing, or a 1/0 to indicate if the feature
> + * is supported/not supported.
> + */
> +
> +static int get_pa_features(int pabyte,int pabit)
> +{
> + struct device_node *cpu;
> + char *pa_feature_table;
> +
> + cpu = of_find_node_by_type(NULL, "cpu");
> + pa_feature_table =
> + (char *)get_property(cpu, "ibm,pa-features", NULL);
> +
> + if ( pa_feature_table == NULL ) {
> + printk("ibm,pa-features property is missing.\n");
> + return -1;
> + }
> +
> + /* sanity check */
> + if ( pabyte > pa_feature_table[0] ) {
> + printk("%s: %d out of range for table of size %d\n",
> + __FUNCTION__,pabyte,pa_feature_table[0]);
> + return -1;
> + }
> +
> + return pa_feature_table[2+pabyte*8+pabit];
pa_feature_table would be byte (char) addressable, while the fields that
we are interested with inside are actually bit values. So this should
be something like
return (pa_feature_table[2+pabyte] & 1<<pabit);
> +}
> +
> +/*
> + * set values within the cur_cpu_spec table according to
> + * the ibm,pa_features property.
> + * potential entries include:
> + * Byte 0, bit 1 - FPU available
> + * Byte 1, bit 2 - Large Pages
> + * Byte 2, bit 3 - DAR set on alignment Interrupt.
> + */
> +static void add_cpu_features()
> +{
> + /* if no property, bail early */
> + if (get_pa_features(0,0) == -1 ) return;
> +
> + if (get_pa_features(1,2) ) {
> + printk("Adding CI_LARGE_PAGE to cur_cpu_spec \n");
> + cur_cpu_spec->cpu_features |= CPU_FTR_CI_LARGE_PAGE;
> + }
> +
> + /* add more here... */
> +
> +}
> +
> +
> #ifdef CONFIG_SMP
>
> static int smt_enabled_cmdline;
> @@ -425,6 +484,8 @@ void __init setup_system(void)
>
> parse_early_param();
>
> + add_cpu_features();
> +
> check_smt_enabled();
> smp_setup_cpu_maps();
>
>
>
>
>
> _______________________________________________
> Linuxppc-dev mailing list
> Linuxppc-dev@ozlabs.org
> https://ozlabs.org/mailman/listinfo/linuxppc-dev
^ permalink raw reply
* [PATCH]: powerpc/pseries: Increment fail counter in PCI recovery
From: Linas Vepstas @ 2006-04-28 22:39 UTC (permalink / raw)
To: Paul Mackerras; +Cc: linuxppc-dev, linux-kernel
Paul,
A small medium-priority patch; please send upstream as appropriate.
--linas
[PATCH]: powerpc/pseries: Increment fail counter in PCI recovery
When a PCI device driver does not support PCI error recovery,
the powerpc/pseries code takes a walk through a branch of code
that resets the failure counter. Because of this, if a broken
PCI card is present, the kernel will attempt to reset it an
infinite number of times. (This is annoying but mostly harmless:
each reset takes about 10-20 seconds, and uses almost no CPU time).
This patch preserves the failure count across resets.
Signed-off-by: Linas Vepstas <linas@austin.ibm.com>
----
arch/powerpc/platforms/pseries/eeh_driver.c | 7 ++++++-
1 files changed, 6 insertions(+), 1 deletion(-)
Index: linux-2.6.17-rc1/arch/powerpc/platforms/pseries/eeh_driver.c
===================================================================
--- linux-2.6.17-rc1.orig/arch/powerpc/platforms/pseries/eeh_driver.c 2006-04-28 17:30:21.000000000 -0500
+++ linux-2.6.17-rc1/arch/powerpc/platforms/pseries/eeh_driver.c 2006-04-28 17:31:31.000000000 -0500
@@ -201,7 +201,11 @@ static void eeh_report_failure(struct pc
static int eeh_reset_device (struct pci_dn *pe_dn, struct pci_bus *bus)
{
- int rc;
+ int cnt, rc;
+
+ /* pcibios will clear the counter; save the value */
+ cnt = pe_dn->eeh_freeze_count;
+
if (bus)
pcibios_remove_pci_devices(bus);
@@ -240,6 +244,7 @@ static int eeh_reset_device (struct pci_
ssleep (5);
pcibios_add_pci_devices(bus);
}
+ pe_dn->eeh_freeze_count = cnt;
return 0;
}
^ permalink raw reply
* [PATCH]: powerpc/pseries: Print PCI slot location code on failure
From: Linas Vepstas @ 2006-04-28 22:42 UTC (permalink / raw)
To: Paul Mackerras; +Cc: linuxppc-dev, linux-kernel
Paul,
A low-priority patch the improves diagnostic printing on EEH failures.
Please review and forward upstream as appropriate.
--linas
[PATCH]: powerpc/pseries: Print PCI slot location code on failure
The PCI error recovery code will printk diagnostic info when
a PCI error event occurs. Change the messages to include the slot
location code, which is how most sysadmins will know the device.
Signed-off-by: Linas Vepstas <linas@austin.ibm.com>
----
arch/powerpc/platforms/pseries/eeh_driver.c | 33 ++++++++++++++++------------
1 files changed, 20 insertions(+), 13 deletions(-)
Index: linux-2.6.17-rc1/arch/powerpc/platforms/pseries/eeh_driver.c
===================================================================
--- linux-2.6.17-rc1.orig/arch/powerpc/platforms/pseries/eeh_driver.c 2006-04-28 17:31:31.000000000 -0500
+++ linux-2.6.17-rc1/arch/powerpc/platforms/pseries/eeh_driver.c 2006-04-28 17:31:39.000000000 -0500
@@ -261,16 +261,20 @@ struct pci_dn * handle_eeh_events (struc
struct pci_bus *frozen_bus;
int rc = 0;
enum pci_ers_result result = PCI_ERS_RESULT_NONE;
- const char *pci_str, *drv_str;
+ const char *location, *pci_str, *drv_str;
frozen_dn = find_device_pe(event->dn);
frozen_bus = pcibios_find_pci_bus(frozen_dn);
if (!frozen_dn) {
- printk(KERN_ERR "EEH: Error: Cannot find partition endpoint for %s\n",
- pci_name(event->dev));
+
+ location = (char *) get_property(event->dn, "ibm,loc-code", NULL);
+ printk(KERN_ERR "EEH: Error: Cannot find partition endpoint "
+ "for location=%s pci addr=%s\n",
+ location, pci_name(event->dev));
return NULL;
}
+ location = (char *) get_property(frozen_dn, "ibm,loc-code", NULL);
/* There are two different styles for coming up with the PE.
* In the old style, it was the highest EEH-capable device
@@ -282,8 +286,9 @@ struct pci_dn * handle_eeh_events (struc
frozen_bus = pcibios_find_pci_bus (frozen_dn->parent);
if (!frozen_bus) {
- printk(KERN_ERR "EEH: Cannot find PCI bus for %s\n",
- frozen_dn->full_name);
+ printk(KERN_ERR "EEH: Cannot find PCI bus "
+ "for location=%s dn=%s\n",
+ location, frozen_dn->full_name);
return NULL;
}
@@ -318,8 +323,9 @@ struct pci_dn * handle_eeh_events (struc
eeh_slot_error_detail(frozen_pdn, 1 /* Temporary Error */);
printk(KERN_WARNING
- "EEH: This PCI device has failed %d times since last reboot: %s - %s\n",
- frozen_pdn->eeh_freeze_count, drv_str, pci_str);
+ "EEH: This PCI device has failed %d times since last reboot: "
+ "location=%s driver=%s pci addr=%s\n",
+ frozen_pdn->eeh_freeze_count, location, drv_str, pci_str);
/* Walk the various device drivers attached to this slot through
* a reset sequence, giving each an opportunity to do what it needs
@@ -368,17 +374,18 @@ excess_failures:
* due to actual, failed cards.
*/
printk(KERN_ERR
- "EEH: PCI device %s - %s has failed %d times \n"
- "and has been permanently disabled. Please try reseating\n"
- "this device or replacing it.\n",
- drv_str, pci_str, frozen_pdn->eeh_freeze_count);
+ "EEH: PCI device at location=%s driver=%s pci addr=%s \n"
+ "has failed %d times and has been permanently disabled. \n"
+ "Please try reseating this device or replacing it.\n",
+ location, drv_str, pci_str, frozen_pdn->eeh_freeze_count);
goto perm_error;
hard_fail:
printk(KERN_ERR
- "EEH: Unable to recover from failure of PCI device %s - %s\n"
+ "EEH: Unable to recover from failure of PCI device "
+ "at location=%s driver=%s pci addr=%s \n"
"Please try reseating this device or replacing it.\n",
- drv_str, pci_str);
+ location, drv_str, pci_str);
perm_error:
eeh_slot_error_detail(frozen_pdn, 2 /* Permanent Error */);
^ permalink raw reply
* PCI init vs. memory init
From: Linas Vepstas @ 2006-04-28 23:04 UTC (permalink / raw)
To: Paul Mackerras; +Cc: linuxppc-dev, linux-kernel
Paul,
I'd previously reported a problem where the PCI subsystem
was getting inited before the memory subsystem. In the unusual
case of an EEH failure, this resulted in a crash in kmalloc,
which I hacked around with a if(!mem_init_done).
You mentioned that the sequence of inits seemed wrong, that the
PCI init should be done later, after the memory init. I think
I agree; but when I took a very very quick look at the code, there
was no obvious hook in later init to move the PCI init over to.
Are you pursuing this further? Should I dig into it? Any bright
ideas? Am I missing something obvious?
There are several spots in in the powerpc PCI init code where
a boot_mem alloc is used instead of kmalloc, and this boot_mem is
then hacked around in the case of a PCI hotplug remove. It would
be nice to fix this...
--linas
^ permalink raw reply
* Re: FT u-boot shim
From: Wolfgang Denk @ 2006-04-28 23:07 UTC (permalink / raw)
To: Tom Rini; +Cc: linuxppc-dev@ozlabs.org list, Paul Mackerras
In-Reply-To: <20060428194457.GA458@smtp.west.cox.net>
Dear Tom,
in message <20060428194457.GA458@smtp.west.cox.net> you wrote:
>
> > > 3. using a u-boot that is ft aware + built in dtb.
...
> > Assuming we had 2., under which circumstances would we need 3. then?
>
> Especially if we had mkuimage let you tack your dtb into the 'kernel'
> image.
Sorry, but I don't understand. If we have the dtb combined with the
kernel image, then why would we need another copy of the dtb built
into U-Boot?
Best regards,
Wolfgang Denk
--
Software Engineering: Embedded and Realtime Systems, Embedded Linux
Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd@denx.de
A day without sunshine is like night.
^ permalink raw reply
* Re: FT u-boot shim
From: Tom Rini @ 2006-04-28 23:22 UTC (permalink / raw)
To: Wolfgang Denk; +Cc: linuxppc-dev@ozlabs.org list, Paul Mackerras
In-Reply-To: <20060428230720.7C0CB353DAC@atlas.denx.de>
On Sat, Apr 29, 2006 at 01:07:20AM +0200, Wolfgang Denk wrote:
> Dear Tom,
>
> in message <20060428194457.GA458@smtp.west.cox.net> you wrote:
> >
> > > > 3. using a u-boot that is ft aware + built in dtb.
> ...
> > > Assuming we had 2., under which circumstances would we need 3. then?
> >
> > Especially if we had mkuimage let you tack your dtb into the 'kernel'
> > image.
>
> Sorry, but I don't understand. If we have the dtb combined with the
> kernel image, then why would we need another copy of the dtb built
> into U-Boot?
You wouldn't have the dtb combined in the kernel image, unless you have
the shim. This is instead of loading a separate dtb anyhow.
--
Tom Rini
http://gate.crashing.org/~trini/
^ permalink raw reply
* Re: sign extension for 32bit syscalls on ppc64
From: Paul Mackerras @ 2006-04-28 23:32 UTC (permalink / raw)
To: Christoph Hellwig; +Cc: linuxppc-dev
In-Reply-To: <20060428131254.GA507@lst.de>
Christoph Hellwig writes:
> OTOH various syscalls in the generic code don't do that and it seems to
> still work fine. I have patches for various new generic compat
> routines, and they all seem to work fine without this sign extension.
>
> What's the exact sign extention rules for ppc64?
As far as the ABI and the compiler are concerned, 32-bit values stored
in registers are always correctly extended to 64 bits according to
their type. That is, the top 32 bits of the register will be either
all zeroes or all ones, and will only be all ones for negative values
of a signed type.
Syscall arguments are zero-extended in the syscall entry path for
32-bit processes (see lines 131-136 of arch/powerpc/kernel/entry_64.S)
so if the argument is an int, we do an (int) cast in the compat
wrapper, which makes the compiler emit an extsw instruction to get the
value correctly sign-extended.
However, it's debatable whether file descriptor arguments really need
to be sign-extended. Although they are typed as int, negative values
are not generally valid (although there are one or two cases where
they are), and an fd value of 4294967295 will generate an EBADF error
just as well as -1 will.
Paul.
^ permalink raw reply
* Re: FT u-boot shim
From: Paul Mackerras @ 2006-04-28 23:35 UTC (permalink / raw)
To: Wolfgang Denk; +Cc: linuxppc-dev@ozlabs.org list
In-Reply-To: <20060428191124.B202B353DAC@atlas.denx.de>
Wolfgang Denk writes:
> > 2. using a u-boot that is ft aware + dtb (boot command in u-boot
> > takes kernel & dtb images, updates blob and passes to kernel)
> > 3. using a u-boot that is ft aware + built in dtb.
> >
> > The issue is that for a given system/board you may need to support
> > multiple or all three. This raises the question where does the .dts
>
> Assuming we had 2., under which circumstances would we need 3. then?
I imagine 3. would be more convenient for users than 2., or at least
it would seem to mean less typing for them.
Paul.
^ permalink raw reply
* Re: alignment exceptionhandler sleeps in invalid context
From: Paul Mackerras @ 2006-04-28 23:41 UTC (permalink / raw)
To: Kumar Gala; +Cc: linuxppc-dev, Olaf Hering
In-Reply-To: <27BDABD8-B970-4F2C-AA0A-07D55A9D3303@kernel.crashing.org>
Kumar Gala writes:
> I was going to ask how this was actually hit. It seems odd that we
> would have an alignment error in the network stack. From the oops
> can we determine what the instruction was that faulted and what
> address it was trying to access.
No, it's not particularly odd, given that our get_unaligned() and
put_unaligned() in include/asm-powerpc/unaligned.h just do a single
access. That makes the common case (address is actually aligned, or
cpu handles it in hardware) fast at the expense of occasionally taking
an alignment exception.
Paul.
^ permalink raw reply
* Re: FT u-boot shim
From: Wolfgang Denk @ 2006-04-28 23:55 UTC (permalink / raw)
To: Paul Mackerras; +Cc: linuxppc-dev@ozlabs.org list
In-Reply-To: <17490.42678.793678.267072@cargo.ozlabs.ibm.com>
In message <17490.42678.793678.267072@cargo.ozlabs.ibm.com> you wrote:
>
> > > 2. using a u-boot that is ft aware + dtb (boot command in u-boot
> > > takes kernel & dtb images, updates blob and passes to kernel)
> > > 3. using a u-boot that is ft aware + built in dtb.
...
> I imagine 3. would be more convenient for users than 2., or at least
> it would seem to mean less typing for them.
This is not necessarily the case. We discussed that kernel & dtb
could be combined in what U-Boot calls a single "multi-file image".
>From the user's point of view there would be no difference to the
current state: he has to deal with a single image file, and needs
only it's start address in emory as argument to the "bootm" command.
Best regards,
Wolfgang Denk
--
Software Engineering: Embedded and Realtime Systems, Embedded Linux
Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd@denx.de
Cleverness and Style have no place in getting a project completed.
-- Tom Christiansen
^ permalink raw reply
* Re: FT u-boot shim
From: Wolfgang Denk @ 2006-04-29 0:32 UTC (permalink / raw)
To: Tom Rini; +Cc: linuxppc-dev@ozlabs.org list, Paul Mackerras
In-Reply-To: <20060428232211.GE458@smtp.west.cox.net>
In message <20060428232211.GE458@smtp.west.cox.net> you wrote:
>
> You wouldn't have the dtb combined in the kernel image, unless you have
> the shim. This is instead of loading a separate dtb anyhow.
Now you got me completely confused. [Maybe I should go to bed.]
Kumar wrote:
> What I envision as the way one boots for something like u-boot is one
> of three options:
> 1. using an old u-boot + boot wrapper (bd_t -> wrapper -> kernel)
> 2. using a u-boot that is ft aware + dtb (boot command in u-boot
> takes kernel & dtb images, updates blob and passes to kernel)
> 3. using a u-boot that is ft aware + built in dtb.
In my understanding, 1. is with a shim; 2. is loading a separate dtb
(probably as multi-file image), and 3. is when U-Boot provides the
dtb. Am I missing something?
Best regards,
Wolfgang Denk
--
Software Engineering: Embedded and Realtime Systems, Embedded Linux
Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd@denx.de
If you fail to plan, plan to fail.
^ permalink raw reply
* [PATCH 0/3] cell: 2.6.17-rc3 bug fixes
From: Arnd Bergmann @ 2006-04-29 0:40 UTC (permalink / raw)
To: Paul Mackerras; +Cc: linuxppc-dev, cbe-oss-dev, linux-kernel
Two small bug fixes for cell, and an update to cell_defconfig.
Please apply.
Arnd <><
^ permalink raw reply
* [PATCH 2/3] spufs: Disable local interrupts for SPE hash_page calls.
From: Arnd Bergmann @ 2006-04-29 0:40 UTC (permalink / raw)
To: Paul Mackerras; +Cc: Arnd Bergmann, linuxppc-dev, cbe-oss-dev, linux-kernel
In-Reply-To: <20060429004019.126937000@localhost.localdomain>
This patch disables and saves local interrupts during
hash_page processing for SPE contexts.
We have to do it explicitly in the spu_irq_class_1_bottom
function. For the interrupt handlers, we get the behaviour
implicitly by using SA_INTERRUPT to disable interrupts while
in the handler.
Signed-off-by: Arnd Bergmann <arnd.bergmann@de.ibm.com>
---
Index: linus-2.6/arch/powerpc/platforms/cell/spu_base.c
===================================================================
--- linus-2.6.orig/arch/powerpc/platforms/cell/spu_base.c
+++ linus-2.6/arch/powerpc/platforms/cell/spu_base.c
@@ -306,19 +306,19 @@ spu_request_irqs(struct spu *spu)
snprintf(spu->irq_c0, sizeof (spu->irq_c0), "spe%02d.0", spu->number);
ret = request_irq(irq_base + spu->isrc,
- spu_irq_class_0, 0, spu->irq_c0, spu);
+ spu_irq_class_0, SA_INTERRUPT, spu->irq_c0, spu);
if (ret)
goto out;
snprintf(spu->irq_c1, sizeof (spu->irq_c1), "spe%02d.1", spu->number);
ret = request_irq(irq_base + IIC_CLASS_STRIDE + spu->isrc,
- spu_irq_class_1, 0, spu->irq_c1, spu);
+ spu_irq_class_1, SA_INTERRUPT, spu->irq_c1, spu);
if (ret)
goto out1;
snprintf(spu->irq_c2, sizeof (spu->irq_c2), "spe%02d.2", spu->number);
ret = request_irq(irq_base + 2*IIC_CLASS_STRIDE + spu->isrc,
- spu_irq_class_2, 0, spu->irq_c2, spu);
+ spu_irq_class_2, SA_INTERRUPT, spu->irq_c2, spu);
if (ret)
goto out2;
goto out;
@@ -487,10 +487,14 @@ int spu_irq_class_1_bottom(struct spu *s
ea = spu->dar;
dsisr = spu->dsisr;
if (dsisr & (MFC_DSISR_PTE_NOT_FOUND | MFC_DSISR_ACCESS_DENIED)) {
+ u64 flags;
+
access = (_PAGE_PRESENT | _PAGE_USER);
access |= (dsisr & MFC_DSISR_ACCESS_PUT) ? _PAGE_RW : 0UL;
+ local_irq_save(flags);
if (hash_page(ea, access, 0x300) != 0)
error |= CLASS1_ENABLE_STORAGE_FAULT_INTR;
+ local_irq_restore(flags);
}
if (error & CLASS1_ENABLE_STORAGE_FAULT_INTR) {
if ((ret = spu_handle_mm_fault(spu)) != 0)
--
^ permalink raw reply
* [PATCH 3/3] powerpc: update cell_defconfig
From: Arnd Bergmann @ 2006-04-29 0:40 UTC (permalink / raw)
To: Paul Mackerras; +Cc: Arnd Bergmann, linuxppc-dev, cbe-oss-dev, linux-kernel
In-Reply-To: <20060429004019.126937000@localhost.localdomain>
reflect the changes to Kconfig since the last update.
Signed-off-by: Arnd Bergmann <arnd.bergmann@de.ibm.com>
---
Index: linus-2.6/arch/powerpc/configs/cell_defconfig
===================================================================
--- linus-2.6.orig/arch/powerpc/configs/cell_defconfig 2006-04-29 01:50:25.000000000 +0200
+++ linus-2.6/arch/powerpc/configs/cell_defconfig 2006-04-29 02:05:56.000000000 +0200
@@ -9,6 +9,7 @@
CONFIG_MMU=y
CONFIG_GENERIC_HARDIRQS=y
CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_GENERIC_HWEIGHT=y
CONFIG_GENERIC_CALIBRATE_DELAY=y
CONFIG_PPC=y
CONFIG_EARLY_PRINTK=y
@@ -55,6 +56,7 @@
CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y
# CONFIG_CPUSETS is not set
+# CONFIG_RELAY is not set
CONFIG_INITRAMFS_SOURCE=""
CONFIG_CC_OPTIMIZE_FOR_SIZE=y
# CONFIG_EMBEDDED is not set
@@ -69,10 +71,6 @@
CONFIG_FUTEX=y
CONFIG_EPOLL=y
CONFIG_SHMEM=y
-CONFIG_CC_ALIGN_FUNCTIONS=0
-CONFIG_CC_ALIGN_LABELS=0
-CONFIG_CC_ALIGN_LOOPS=0
-CONFIG_CC_ALIGN_JUMPS=0
CONFIG_SLAB=y
# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
@@ -84,7 +82,6 @@
CONFIG_MODULES=y
CONFIG_MODULE_UNLOAD=y
# CONFIG_MODULE_FORCE_UNLOAD is not set
-CONFIG_OBSOLETE_MODPARM=y
# CONFIG_MODVERSIONS is not set
# CONFIG_MODULE_SRCVERSION_ALL is not set
CONFIG_KMOD=y
@@ -93,6 +90,7 @@
#
# Block layer
#
+# CONFIG_BLK_DEV_IO_TRACE is not set
#
# IO Schedulers
@@ -126,6 +124,7 @@
CONFIG_MMIO_NVRAM=y
CONFIG_CELL_IIC=y
# CONFIG_PPC_MPC106 is not set
+# CONFIG_PPC_970_NAP is not set
# CONFIG_CPU_FREQ is not set
# CONFIG_WANT_EARLY_SERIAL is not set
@@ -167,7 +166,6 @@
CONFIG_SPARSEMEM_EXTREME=y
# CONFIG_MEMORY_HOTPLUG is not set
CONFIG_SPLIT_PTLOCK_CPUS=4
-CONFIG_MIGRATION=y
# CONFIG_PPC_64K_PAGES is not set
CONFIG_SCHED_SMT=y
CONFIG_PROC_DEVICETREE=y
@@ -184,7 +182,6 @@
# CONFIG_PPC_INDIRECT_PCI is not set
CONFIG_PCI=y
CONFIG_PCI_DOMAINS=y
-CONFIG_PCI_LEGACY_PROC=y
# CONFIG_PCI_DEBUG is not set
#
@@ -226,6 +223,7 @@
# CONFIG_INET_AH is not set
# CONFIG_INET_ESP is not set
# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_XFRM_TUNNEL is not set
CONFIG_INET_TUNNEL=y
CONFIG_INET_DIAG=y
CONFIG_INET_TCP_DIAG=y
@@ -242,6 +240,7 @@
CONFIG_INET6_AH=m
CONFIG_INET6_ESP=m
CONFIG_INET6_IPCOMP=m
+CONFIG_INET6_XFRM_TUNNEL=m
CONFIG_INET6_TUNNEL=m
CONFIG_IPV6_TUNNEL=m
CONFIG_NETFILTER=y
@@ -632,6 +631,7 @@
#
CONFIG_SERIAL_8250=y
CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_PCI=y
CONFIG_SERIAL_8250_NR_UARTS=4
CONFIG_SERIAL_8250_RUNTIME_UARTS=4
# CONFIG_SERIAL_8250_EXTENDED is not set
@@ -717,7 +717,6 @@
# CONFIG_I2C_PARPORT_LIGHT is not set
# CONFIG_I2C_PROSAVAGE is not set
# CONFIG_I2C_SAVAGE4 is not set
-# CONFIG_SCx200_ACB is not set
# CONFIG_I2C_SIS5595 is not set
# CONFIG_I2C_SIS630 is not set
# CONFIG_I2C_SIS96X is not set
@@ -736,9 +735,7 @@
# CONFIG_SENSORS_PCF8574 is not set
# CONFIG_SENSORS_PCA9539 is not set
# CONFIG_SENSORS_PCF8591 is not set
-# CONFIG_SENSORS_RTC8564 is not set
# CONFIG_SENSORS_MAX6875 is not set
-# CONFIG_RTC_X1205_I2C is not set
# CONFIG_I2C_DEBUG_CORE is not set
# CONFIG_I2C_DEBUG_ALGO is not set
# CONFIG_I2C_DEBUG_BUS is not set
@@ -766,10 +763,6 @@
#
#
-# Multimedia Capabilities Port drivers
-#
-
-#
# Multimedia devices
#
# CONFIG_VIDEO_DEV is not set
@@ -818,6 +811,19 @@
# CONFIG_MMC is not set
#
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+
+#
# InfiniBand support
#
CONFIG_INFINIBAND=y
@@ -834,6 +840,11 @@
#
#
+# Real Time Clock
+#
+# CONFIG_RTC_CLASS is not set
+
+#
# File systems
#
CONFIG_EXT2_FS=y
@@ -889,7 +900,6 @@
CONFIG_HUGETLBFS=y
CONFIG_HUGETLB_PAGE=y
CONFIG_RAMFS=y
-# CONFIG_RELAYFS_FS is not set
# CONFIG_CONFIGFS_FS is not set
#
--
^ permalink raw reply
* [PATCH 1/3] powerpc: Make rtas console _much_ faster
From: Arnd Bergmann @ 2006-04-29 0:45 UTC (permalink / raw)
To: Paul Mackerras; +Cc: linux-kernel, linuxppc-dev, cbe-oss-dev, Arnd Bergmann
In-Reply-To: <20060429004019.126937000@localhost.localdomain>
Currently the hvc_rtas driver is painfully slow to use. Our "benchmark" is
ls -R /etc, which spits out about 27866 characters. The theoretical maximum
speed would be about 2.2 seconds, the current code takes ~50 seconds.
The core of the problem is that sometimes when the tty layer asks us to push
characters the firmware isn't able to handle some or all of them, and so
returns an error. The current code sees this and just returns to the tty code
with the buffer half sent.
There's the khvcd thread which will eventually wake up and try to push more
characters, that will usually work because the firmware's had time to push
the characters out. But the thread only wakes up every 10 milliseconds, which
isn't fast enough.
There's already code in the hvc_console driver to make the khvcd thread do
a "quick" loop, where it just calls yield() instead of sleeping. The only code
that triggered that behaviour was recently removed though, which I don't
quite understand.
Still, if we set HVC_POLL_QUICK whenever the push hvc_push() doesn't push all
characters (ie. RTAS blocks), we can get good performance out of the hvc_rtas
backend. With this patch the "benchmark" takes ~2.8 seconds.
Cc: Ryan Arnold <rsa@us.ibm.com>
Signed-off-by: Michael Ellerman <michael@ellerman.id.au>
Signed-off-by: Arnd Bergmann <arnd.bergmann@de.ibm.com>
---
drivers/char/hvc_console.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
Index: linus-2.6/drivers/char/hvc_console.c
===================================================================
--- linus-2.6.orig/drivers/char/hvc_console.c
+++ linus-2.6/drivers/char/hvc_console.c
@@ -570,7 +570,7 @@ static int hvc_poll(struct hvc_struct *h
hvc_push(hp);
/* Reschedule us if still some write pending */
if (hp->n_outbuf > 0)
- poll_mask |= HVC_POLL_WRITE;
+ poll_mask |= HVC_POLL_WRITE | HVC_POLL_QUICK;
/* No tty attached, just skip */
tty = hp->tty;
--
^ permalink raw reply
* Re: FT u-boot shim
From: Tom Rini @ 2006-04-29 0:52 UTC (permalink / raw)
To: Wolfgang Denk; +Cc: linuxppc-dev@ozlabs.org list, Paul Mackerras
In-Reply-To: <20060429003232.9926C353DAC@atlas.denx.de>
On Sat, Apr 29, 2006 at 02:32:32AM +0200, Wolfgang Denk wrote:
> In message <20060428232211.GE458@smtp.west.cox.net> you wrote:
> >
> > You wouldn't have the dtb combined in the kernel image, unless you have
> > the shim. This is instead of loading a separate dtb anyhow.
>
> Now you got me completely confused. [Maybe I should go to bed.]
>
> Kumar wrote:
>
> > What I envision as the way one boots for something like u-boot is one
> > of three options:
> > 1. using an old u-boot + boot wrapper (bd_t -> wrapper -> kernel)
> > 2. using a u-boot that is ft aware + dtb (boot command in u-boot
> > takes kernel & dtb images, updates blob and passes to kernel)
> > 3. using a u-boot that is ft aware + built in dtb.
>
> In my understanding, 1. is with a shim; 2. is loading a separate dtb
> (probably as multi-file image), and 3. is when U-Boot provides the
> dtb. Am I missing something?
I'm suggesting that we make 2 easier. U-Boot needs the file mkuimage'd
anyways. Why not make it easier and make adding the dtb part of that
step instead of a seperate load? It's still quite easy to replace if
you're testing new dtb's out.
--
Tom Rini
http://gate.crashing.org/~trini/
^ permalink raw reply
* [PATCH 0/4] NUMA support for spufs
From: Arnd Bergmann @ 2006-04-29 1:18 UTC (permalink / raw)
To: Andrew Morton; +Cc: linuxppc-dev, Paul Mackerras, cbe-oss-dev, linux-kernel
The current version of spufs breaks upon boot when NUMA support is enabled.
I'd like to fix that before 2.6.17 so we can use the same kernel image
on Cell that we use on other powerpc systems using NUMA.
This series has four patches, the first two are required to make it work
at all, the other two are there for a somewhat cleaner solution.
The second patch (sparsemem-interaction-with-memory-add-bug-fixes.patch)
actually comes from 2.6.17-rc2-mm1, but in order to make this work,
we need it included in mainline along with the others.
Arnd <><
--
^ permalink raw reply
* [PATCH 1/4] spufs: fix for CONFIG_NUMA
From: Arnd Bergmann @ 2006-04-29 1:18 UTC (permalink / raw)
To: Andrew Morton
Cc: Arnd Bergmann, linuxppc-dev, Paul Mackerras, cbe-oss-dev,
linux-kernel
In-Reply-To: <20060429011827.502138000@localhost.localdomain>
From: Joel H Schopp <jschopp@us.ibm.com>
Based on an older patch from Mike Kravetz <kravetz@us.ibm.com>
We need to have a mem_map for high addresses in order to make
fops->no_page work on spufs mem and register files. So far, we
have used the memory_present() function during early bootup,
but that did not work when CONFIG_NUMA was enabled.
We now use the __add_pages() function to add the mem_map
when loading the spufs module, which is a lot nicer.
Signed-off-by: Arnd Bergmann <arnd.bergmann@de.ibm.com>
---
Index: linus-2.6/arch/powerpc/platforms/cell/setup.c
===================================================================
--- linus-2.6.orig/arch/powerpc/platforms/cell/setup.c 2006-04-29 02:51:29.000000000 +0200
+++ linus-2.6/arch/powerpc/platforms/cell/setup.c 2006-04-29 02:51:33.000000000 +0200
@@ -29,6 +29,8 @@
#include <linux/seq_file.h>
#include <linux/root_dev.h>
#include <linux/console.h>
+#include <linux/mutex.h>
+#include <linux/memory_hotplug.h>
#include <asm/mmu.h>
#include <asm/processor.h>
@@ -46,6 +48,7 @@
#include <asm/cputable.h>
#include <asm/ppc-pci.h>
#include <asm/irq.h>
+#include <asm/spu.h>
#include "interrupt.h"
#include "iommu.h"
@@ -69,77 +72,6 @@
of_node_put(root);
}
-#ifdef CONFIG_SPARSEMEM
-static int __init find_spu_node_id(struct device_node *spe)
-{
- unsigned int *id;
-#ifdef CONFIG_NUMA
- struct device_node *cpu;
- cpu = spe->parent->parent;
- id = (unsigned int *)get_property(cpu, "node-id", NULL);
-#else
- id = NULL;
-#endif
- return id ? *id : 0;
-}
-
-static void __init cell_spuprop_present(struct device_node *spe,
- const char *prop, int early)
-{
- struct address_prop {
- unsigned long address;
- unsigned int len;
- } __attribute__((packed)) *p;
- int proplen;
-
- unsigned long start_pfn, end_pfn, pfn;
- int node_id;
-
- p = (void*)get_property(spe, prop, &proplen);
- WARN_ON(proplen != sizeof (*p));
-
- node_id = find_spu_node_id(spe);
-
- start_pfn = p->address >> PAGE_SHIFT;
- end_pfn = (p->address + p->len + PAGE_SIZE - 1) >> PAGE_SHIFT;
-
- /* We need to call memory_present *before* the call to sparse_init,
- but we can initialize the page structs only *after* that call.
- Thus, we're being called twice. */
- if (early)
- memory_present(node_id, start_pfn, end_pfn);
- else {
- /* As the pages backing SPU LS and I/O are outside the range
- of regular memory, their page structs were not initialized
- by free_area_init. Do it here instead. */
- for (pfn = start_pfn; pfn < end_pfn; pfn++) {
- struct page *page = pfn_to_page(pfn);
- set_page_links(page, ZONE_DMA, node_id, pfn);
- init_page_count(page);
- reset_page_mapcount(page);
- SetPageReserved(page);
- INIT_LIST_HEAD(&page->lru);
- }
- }
-}
-
-static void __init cell_spumem_init(int early)
-{
- struct device_node *node;
- for (node = of_find_node_by_type(NULL, "spe");
- node; node = of_find_node_by_type(node, "spe")) {
- cell_spuprop_present(node, "local-store", early);
- cell_spuprop_present(node, "problem", early);
- cell_spuprop_present(node, "priv1", early);
- cell_spuprop_present(node, "priv2", early);
- }
-}
-#else
-static void __init cell_spumem_init(int early)
-{
-}
-#endif
-
static void cell_progress(char *s, unsigned short hex)
{
printk("*** %04x : %s\n", hex, s ? s : "");
@@ -172,8 +104,6 @@
#endif
mmio_nvram_init();
-
- cell_spumem_init(0);
}
/*
@@ -189,8 +119,6 @@
ppc64_interrupt_controller = IC_CELL_PIC;
- cell_spumem_init(1);
-
DBG(" <- cell_init_early()\n");
}
Index: linus-2.6/arch/powerpc/platforms/cell/Kconfig
===================================================================
--- linus-2.6.orig/arch/powerpc/platforms/cell/Kconfig 2006-04-29 02:51:29.000000000 +0200
+++ linus-2.6/arch/powerpc/platforms/cell/Kconfig 2006-04-29 02:51:33.000000000 +0200
@@ -12,7 +12,8 @@
config SPUFS_MMAP
bool
- depends on SPU_FS && SPARSEMEM && !PPC_64K_PAGES
+ depends on SPU_FS && SPARSEMEM
+ select MEMORY_HOTPLUG
default y
endmenu
Index: linus-2.6/arch/powerpc/platforms/cell/spu_base.c
===================================================================
--- linus-2.6.orig/arch/powerpc/platforms/cell/spu_base.c 2006-04-29 02:51:29.000000000 +0200
+++ linus-2.6/arch/powerpc/platforms/cell/spu_base.c 2006-04-29 02:51:33.000000000 +0200
@@ -516,6 +516,56 @@
}
EXPORT_SYMBOL_GPL(spu_irq_setaffinity);
+static int __init find_spu_node_id(struct device_node *spe)
+{
+ unsigned int *id;
+ struct device_node *cpu;
+ cpu = spe->parent->parent;
+ id = (unsigned int *)get_property(cpu, "node-id", NULL);
+ return id ? *id : 0;
+}
+
+static int __init cell_spuprop_present(struct device_node *spe,
+ const char *prop)
+{
+ static DEFINE_MUTEX(add_spumem_mutex);
+
+ struct address_prop {
+ unsigned long address;
+ unsigned int len;
+ } __attribute__((packed)) *p;
+ int proplen;
+
+ unsigned long start_pfn, nr_pages;
+ int node_id;
+ struct pglist_data *pgdata;
+ struct zone *zone;
+ int ret;
+
+ p = (void*)get_property(spe, prop, &proplen);
+ WARN_ON(proplen != sizeof (*p));
+
+ start_pfn = p->address >> PAGE_SHIFT;
+ nr_pages = ((unsigned long)p->len + PAGE_SIZE - 1) >> PAGE_SHIFT;
+
+ /*
+ * XXX need to get the correct NUMA node in here. This may
+ * be different from the spe::node_id property, e.g. when
+ * the host firmware is not NUMA aware.
+ */
+ node_id = 0;
+
+ pgdata = NODE_DATA(node_id);
+ zone = pgdata->node_zones;
+
+ /* XXX rethink locking here */
+ mutex_lock(&add_spumem_mutex);
+ ret = __add_pages(zone, start_pfn, nr_pages);
+ mutex_unlock(&add_spumem_mutex);
+
+ return ret;
+}
+
static void __iomem * __init map_spe_prop(struct device_node *n,
const char *name)
{
@@ -526,6 +576,8 @@
void *p;
int proplen;
+ void* ret = NULL;
+ int err = 0;
p = get_property(n, name, &proplen);
if (proplen != sizeof (struct address_prop))
@@ -533,7 +585,14 @@
prop = p;
- return ioremap(prop->address, prop->len);
+ err = cell_spuprop_present(n, name);
+ if (err && (err != -EEXIST))
+ goto out;
+
+ ret = ioremap(prop->address, prop->len);
+
+ out:
+ return ret;
}
static void spu_unmap(struct spu *spu)
@@ -593,17 +652,6 @@
return ret;
}
-static int __init find_spu_node_id(struct device_node *spe)
-{
- unsigned int *id;
- struct device_node *cpu;
-
- cpu = spe->parent->parent;
- id = (unsigned int *)get_property(cpu, "node-id", NULL);
-
- return id ? *id : 0;
-}
-
static int __init create_spu(struct device_node *spe)
{
struct spu *spu;
Index: linus-2.6/mm/memory_hotplug.c
===================================================================
--- linus-2.6.orig/mm/memory_hotplug.c 2006-04-29 02:51:29.000000000 +0200
+++ linus-2.6/mm/memory_hotplug.c 2006-04-29 02:51:33.000000000 +0200
@@ -69,12 +69,16 @@
for (i = 0; i < nr_pages; i += PAGES_PER_SECTION) {
err = __add_section(zone, phys_start_pfn + i);
- if (err)
+ /* We want to keep adding the rest of the
+ * sections if the first ones already exist
+ */
+ if (err && (err != -EEXIST))
break;
}
return err;
}
+EXPORT_SYMBOL_GPL(__add_pages);
static void grow_zone_span(struct zone *zone,
unsigned long start_pfn, unsigned long end_pfn)
--
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox