From greg at kroah.com Thu Sep 1 07:32:56 2005 From: greg at kroah.com (Greg KH) Date: Wed, 31 Aug 2005 14:32:56 -0700 Subject: [RFC/PATCH] Set up PCI tree from OF on ppc64 In-Reply-To: <17165.800.617053.891578@cargo.ozlabs.ibm.com> References: <17165.800.617053.891578@cargo.ozlabs.ibm.com> Message-ID: <20050831213256.GA20443@kroah.com> On Thu, Aug 25, 2005 at 09:30:40AM +1000, Paul Mackerras wrote: > The patch does some minor rearrangement of the generic PCI probing > code so that we can reuse as much code from drivers/pci as makes > sense. > > This has been tested on a dual G5 powermac and a partition on a POWER5 > machine (running under the hypervisor). > > Any comments? The pci rearrangement is fine with me. thanks, greg k-h From arnd at arndb.de Thu Sep 1 10:47:06 2005 From: arnd at arndb.de (Arnd Bergmann) Date: Thu, 1 Sep 2005 02:47:06 +0200 Subject: [PATCH,RFC] Move Cell platform code to arch/powerpc Message-ID: <200509010247.07399.arnd@arndb.de> Move all files from arch/ppc64/kernel/bpa_* to arch/powerpc/platforms/cell, I would like to see a patch like this go into 2.6.14, for multiple reasons: - The marketing folks have changed the names and we are no longer supposed to refer to Cell as 'BPA' or 'Broadband Processor Architecture'. The platform is officially known as 'Cell Broadband Engine Architecture', while the CPU is the 'Cell Broadband Engine'. - We are now moving all platforms into arch/powerpc/platforms and someone has to start so we get a template for the other architectures to follow. - It would be a big mess for me to maintain my own patches on top of file names that are different from mainline during the 2.6.14 freeze. My impression is that Cell is a good target for moving first, because I have to move it anyway and the number of users is extremely low, so it doesn't cause too much harm if we screw up. What thing that makes moving Cell relatively easy is that it only supports 64 bit and only a single hardware configuration so far. I have tested this a bit on Cell and also done compile-only test for the other platforms, but it doesn't really make any changes to the code itself. Please comment on wether this is what everybody like the merge process be like. Signed-off-by: Arnd Bergmann -- arch/powerpc/platforms/cell/Makefile | 1 arch/ppc64/kernel/Makefile | 5 arch/powerpc/platforms/cell/pic.c | 269 ++++++++++++++++++++++ arch/ppc64/kernel/bpa_iic.c | 270 ---------------------- include/asm-powerpc/cell-pic.h | 62 +++++ arch/ppc64/kernel/bpa_iic.h | 62 ----- arch/powerpc/platforms/cell/iommu.c | 377 +++++++++++++++++++++++++++++++ arch/ppc64/kernel/bpa_iommu.c | 377 ------------------------------- arch/powerpc/platforms/cell/iommu.h | 65 +++++ arch/ppc64/kernel/bpa_iommu.h | 65 ----- arch/powerpc/platforms/cell/nvram.c | 118 +++++++++ arch/ppc64/kernel/bpa_nvram.c | 118 --------- arch/powerpc/platforms/cell/setup.c | 138 +++++++++++ arch/ppc64/kernel/bpa_setup.c | 140 ----------- arch/powerpc/platforms/cell/spider-pic.c | 190 +++++++++++++++ arch/ppc64/kernel/spider-pic.c | 191 --------------- arch/ppc64/Kconfig | 10 arch/ppc64/kernel/cpu_setup_power4.S | 2 arch/ppc64/kernel/cputable.c | 6 arch/ppc64/kernel/irq.c | 2 arch/ppc64/kernel/pSeries_smp.c | 4 arch/ppc64/kernel/setup.c | 8 arch/ppc64/kernel/traps.c | 4 include/asm-ppc64/nvram.h | 2 include/asm-ppc64/processor.h | 7 25 files changed, 1248 insertions(+), 1245 deletions(-) --- linux-cg.orig/arch/powerpc/platforms/cell/Makefile 1969-12-31 19:00:00.000000000 -0500 +++ linux-cg/arch/powerpc/platforms/cell/Makefile 2005-09-01 02:37:46.074992344 -0400 @@ -0,0 +1 @@ +obj-y += iommu.o nvram.o setup.o pic.o spider-pic.o --- linux-cg.orig/arch/powerpc/platforms/cell/iommu.c 1969-12-31 19:00:00.000000000 -0500 +++ linux-cg/arch/powerpc/platforms/cell/iommu.c 2005-09-01 02:37:46.076992040 -0400 @@ -0,0 +1,377 @@ +/* + * IOMMU implementation for Cell Broadband Engine + * + * We just establish a linear mapping at boot by setting all the + * IOPT cache entries in the CPU. + * The mapping functions should be identical to pci_direct_iommu, + * except for the handling of the high order bit that is required + * by the Spider bridge. These should be split into a separate + * file at the point where we get a different bridge chip. + * + * Copyright (C) 2005 IBM Deutschland Entwicklung GmbH, + * Arnd Bergmann + * + * Based on linear mapping + * Copyright (C) 2003 Benjamin Herrenschmidt (benh at kernel.crashing.org) + * + * 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. + */ + +#undef DEBUG + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "iommu.h" + +static inline unsigned long +get_iopt_entry(unsigned long real_address, unsigned long ioid, + unsigned long prot) +{ + return (prot & IOPT_PROT_MASK) + | (IOPT_COHERENT) + | (IOPT_ORDER_VC) + | (real_address & IOPT_RPN_MASK) + | (ioid & IOPT_IOID_MASK); +} + +typedef struct { + unsigned long val; +} ioste; + +static inline ioste +mk_ioste(unsigned long val) +{ + ioste ioste = { .val = val, }; + return ioste; +} + +static inline ioste +get_iost_entry(unsigned long iopt_base, unsigned long io_address, unsigned page_size) +{ + unsigned long ps; + unsigned long iostep; + unsigned long nnpt; + unsigned long shift; + + switch (page_size) { + case 0x1000000: + ps = IOST_PS_16M; + nnpt = 0; /* one page per segment */ + shift = 5; /* segment has 16 iopt entries */ + break; + + case 0x100000: + ps = IOST_PS_1M; + nnpt = 0; /* one page per segment */ + shift = 1; /* segment has 256 iopt entries */ + break; + + case 0x10000: + ps = IOST_PS_64K; + nnpt = 0x07; /* 8 pages per io page table */ + shift = 0; /* all entries are used */ + break; + + case 0x1000: + ps = IOST_PS_4K; + nnpt = 0x7f; /* 128 pages per io page table */ + shift = 0; /* all entries are used */ + break; + + default: /* not a known compile time constant */ + BUILD_BUG_ON(1); + break; + } + + iostep = iopt_base + + /* need 8 bytes per iopte */ + (((io_address / page_size * 8) + /* align io page tables on 4k page boundaries */ + << shift) + /* nnpt+1 pages go into each iopt */ + & ~(nnpt << 12)); + + nnpt++; /* this seems to work, but the documentation is not clear + about wether we put nnpt or nnpt-1 into the ioste bits. + In theory, this can't work for 4k pages. */ + return mk_ioste(IOST_VALID_MASK + | (iostep & IOST_PT_BASE_MASK) + | ((nnpt << 5) & IOST_NNPT_MASK) + | (ps & IOST_PS_MASK)); +} + +/* compute the address of an io pte */ +static inline unsigned long +get_ioptep(ioste iost_entry, unsigned long io_address) +{ + unsigned long iopt_base; + unsigned long page_size; + unsigned long page_number; + unsigned long iopt_offset; + + iopt_base = iost_entry.val & IOST_PT_BASE_MASK; + page_size = iost_entry.val & IOST_PS_MASK; + + /* decode page size to compute page number */ + page_number = (io_address & 0x0fffffff) >> (10 + 2 * page_size); + /* page number is an offset into the io page table */ + iopt_offset = (page_number << 3) & 0x7fff8ul; + return iopt_base + iopt_offset; +} + +/* compute the tag field of the iopt cache entry */ +static inline unsigned long +get_ioc_tag(ioste iost_entry, unsigned long io_address) +{ + unsigned long iopte = get_ioptep(iost_entry, io_address); + + return IOPT_VALID_MASK + | ((iopte & 0x00000000000000ff8ul) >> 3) + | ((iopte & 0x0000003fffffc0000ul) >> 9); +} + +/* compute the hashed 6 bit index for the 4-way associative pte cache */ +static inline unsigned long +get_ioc_hash(ioste iost_entry, unsigned long io_address) +{ + unsigned long iopte = get_ioptep(iost_entry, io_address); + + return ((iopte & 0x000000000000001f8ul) >> 3) + ^ ((iopte & 0x00000000000020000ul) >> 17) + ^ ((iopte & 0x00000000000010000ul) >> 15) + ^ ((iopte & 0x00000000000008000ul) >> 13) + ^ ((iopte & 0x00000000000004000ul) >> 11) + ^ ((iopte & 0x00000000000002000ul) >> 9) + ^ ((iopte & 0x00000000000001000ul) >> 7); +} + +/* same as above, but pretend that we have a simpler 1-way associative + pte cache with an 8 bit index */ +static inline unsigned long +get_ioc_hash_1way(ioste iost_entry, unsigned long io_address) +{ + unsigned long iopte = get_ioptep(iost_entry, io_address); + + return ((iopte & 0x000000000000001f8ul) >> 3) + ^ ((iopte & 0x00000000000020000ul) >> 17) + ^ ((iopte & 0x00000000000010000ul) >> 15) + ^ ((iopte & 0x00000000000008000ul) >> 13) + ^ ((iopte & 0x00000000000004000ul) >> 11) + ^ ((iopte & 0x00000000000002000ul) >> 9) + ^ ((iopte & 0x00000000000001000ul) >> 7) + ^ ((iopte & 0x0000000000000c000ul) >> 8); +} + +static inline ioste +get_iost_cache(void __iomem *base, unsigned long index) +{ + unsigned long __iomem *p = (base + IOC_ST_CACHE_DIR); + return mk_ioste(in_be64(&p[index])); +} + +static inline void +set_iost_cache(void __iomem *base, unsigned long index, ioste ste) +{ + unsigned long __iomem *p = (base + IOC_ST_CACHE_DIR); + pr_debug("ioste %02lx was %016lx, store %016lx", index, + get_iost_cache(base, index).val, ste.val); + out_be64(&p[index], ste.val); + pr_debug(" now %016lx\n", get_iost_cache(base, index).val); +} + +static inline unsigned long +get_iopt_cache(void __iomem *base, unsigned long index, unsigned long *tag) +{ + unsigned long __iomem *tags = (void *)(base + IOC_PT_CACHE_DIR); + unsigned long __iomem *p = (void *)(base + IOC_PT_CACHE_REG); + + *tag = tags[index]; + rmb(); + return *p; +} + +static inline void +set_iopt_cache(void __iomem *base, unsigned long index, + unsigned long tag, unsigned long val) +{ + unsigned long __iomem *tags = base + IOC_PT_CACHE_DIR; + unsigned long __iomem *p = base + IOC_PT_CACHE_REG; + pr_debug("iopt %02lx was v%016lx/t%016lx, store v%016lx/t%016lx\n", + index, get_iopt_cache(base, index, &oldtag), oldtag, val, tag); + + out_be64(p, val); + out_be64(&tags[index], tag); +} + +static inline void +set_iost_origin(void __iomem *base) +{ + unsigned long __iomem *p = base + IOC_ST_ORIGIN; + unsigned long origin = IOSTO_ENABLE | IOSTO_SW; + + pr_debug("iost_origin %016lx, now %016lx\n", in_be64(p), origin); + out_be64(p, origin); +} + +static inline void +set_iocmd_config(void __iomem *base) +{ + unsigned long __iomem *p = base + 0xc00; + unsigned long conf; + + conf = in_be64(p); + pr_debug("iost_conf %016lx, now %016lx\n", conf, conf | IOCMD_CONF_TE); + out_be64(p, conf | IOCMD_CONF_TE); +} + +/* FIXME: get these from the device tree */ +#define ioc_base 0x20000511000ull +#define ioc_mmio_base 0x20000510000ull +#define ioid 0x48a +#define iopt_phys_offset (- 0x20000000) /* We have a 512MB offset from the SB */ +#define io_page_size 0x1000000 + +static unsigned long map_iopt_entry(unsigned long address) +{ + switch (address >> 20) { + case 0x600: + address = 0x24020000000ull; /* spider i/o */ + break; + default: + address += iopt_phys_offset; + break; + } + + return get_iopt_entry(address, ioid, IOPT_PROT_RW); +} + +static void iommu_bus_setup_null(struct pci_bus *b) { } +static void iommu_dev_setup_null(struct pci_dev *d) { } + +/* initialize the iommu to support a simple linear mapping + * for each DMA window used by any device. For now, we + * happen to know that there is only one DMA window in use, + * starting at iopt_phys_offset. */ +static void cell_map_iommu(void) +{ + unsigned long address; + void __iomem *base; + ioste ioste; + unsigned long index; + + base = __ioremap(ioc_base, 0x1000, _PAGE_NO_CACHE); + pr_debug("%lx mapped to %p\n", ioc_base, base); + set_iocmd_config(base); + iounmap(base); + + base = __ioremap(ioc_mmio_base, 0x1000, _PAGE_NO_CACHE); + pr_debug("%lx mapped to %p\n", ioc_mmio_base, base); + + set_iost_origin(base); + + for (address = 0; address < 0x100000000ul; address += io_page_size) { + ioste = get_iost_entry(0x10000000000ul, address, io_page_size); + if ((address & 0xfffffff) == 0) /* segment start */ + set_iost_cache(base, address >> 28, ioste); + index = get_ioc_hash_1way(ioste, address); + pr_debug("addr %08lx, index %02lx, ioste %016lx\n", + address, index, ioste.val); + set_iopt_cache(base, + get_ioc_hash_1way(ioste, address), + get_ioc_tag(ioste, address), + map_iopt_entry(address)); + } + iounmap(base); +} + + +static void *cell_alloc_coherent(struct device *hwdev, size_t size, + dma_addr_t *dma_handle, unsigned int __nocast flag) +{ + void *ret; + + ret = (void *)__get_free_pages(flag, get_order(size)); + if (ret != NULL) { + memset(ret, 0, size); + *dma_handle = virt_to_abs(ret) | CELL_DMA_VALID; + } + return ret; +} + +static void cell_free_coherent(struct device *hwdev, size_t size, + void *vaddr, dma_addr_t dma_handle) +{ + free_pages((unsigned long)vaddr, get_order(size)); +} + +static dma_addr_t cell_map_single(struct device *hwdev, void *ptr, + size_t size, enum dma_data_direction direction) +{ + return virt_to_abs(ptr) | CELL_DMA_VALID; +} + +static void cell_unmap_single(struct device *hwdev, dma_addr_t dma_addr, + size_t size, enum dma_data_direction direction) +{ +} + +static int cell_map_sg(struct device *hwdev, struct scatterlist *sg, + int nents, enum dma_data_direction direction) +{ + int i; + + for (i = 0; i < nents; i++, sg++) { + sg->dma_address = (page_to_phys(sg->page) + sg->offset) + | CELL_DMA_VALID; + sg->dma_length = sg->length; + } + + return nents; +} + +static void cell_unmap_sg(struct device *hwdev, struct scatterlist *sg, + int nents, enum dma_data_direction direction) +{ +} + +static int cell_dma_supported(struct device *dev, u64 mask) +{ + return mask < 0x100000000ull; +} + +void cell_init_iommu(void) +{ + cell_map_iommu(); + + /* Direct I/O, IOMMU off */ + ppc_md.iommu_dev_setup = iommu_dev_setup_null; + ppc_md.iommu_bus_setup = iommu_bus_setup_null; + + pci_dma_ops.alloc_coherent = cell_alloc_coherent; + pci_dma_ops.free_coherent = cell_free_coherent; + pci_dma_ops.map_single = cell_map_single; + pci_dma_ops.unmap_single = cell_unmap_single; + pci_dma_ops.map_sg = cell_map_sg; + pci_dma_ops.unmap_sg = cell_unmap_sg; + pci_dma_ops.dma_supported = cell_dma_supported; +} --- linux-cg.orig/arch/powerpc/platforms/cell/iommu.h 1969-12-31 19:00:00.000000000 -0500 +++ linux-cg/arch/powerpc/platforms/cell/iommu.h 2005-09-01 02:37:46.077991888 -0400 @@ -0,0 +1,65 @@ +#ifndef CELL_IOMMU_H +#define CELL_IOMMU_H + +/* some constants */ +enum { + /* segment table entries */ + IOST_VALID_MASK = 0x8000000000000000ul, + IOST_TAG_MASK = 0x3000000000000000ul, + IOST_PT_BASE_MASK = 0x000003fffffff000ul, + IOST_NNPT_MASK = 0x0000000000000fe0ul, + IOST_PS_MASK = 0x000000000000000ful, + + IOST_PS_4K = 0x1, + IOST_PS_64K = 0x3, + IOST_PS_1M = 0x5, + IOST_PS_16M = 0x7, + + /* iopt tag register */ + IOPT_VALID_MASK = 0x0000000200000000ul, + IOPT_TAG_MASK = 0x00000001fffffffful, + + /* iopt cache register */ + IOPT_PROT_MASK = 0xc000000000000000ul, + IOPT_PROT_NONE = 0x0000000000000000ul, + IOPT_PROT_READ = 0x4000000000000000ul, + IOPT_PROT_WRITE = 0x8000000000000000ul, + IOPT_PROT_RW = 0xc000000000000000ul, + IOPT_COHERENT = 0x2000000000000000ul, + + IOPT_ORDER_MASK = 0x1800000000000000ul, + /* order access to same IOID/VC on same address */ + IOPT_ORDER_ADDR = 0x0800000000000000ul, + /* similar, but only after a write access */ + IOPT_ORDER_WRITES = 0x1000000000000000ul, + /* Order all accesses to same IOID/VC */ + IOPT_ORDER_VC = 0x1800000000000000ul, + + IOPT_RPN_MASK = 0x000003fffffff000ul, + IOPT_HINT_MASK = 0x0000000000000800ul, + IOPT_IOID_MASK = 0x00000000000007fful, + + IOSTO_ENABLE = 0x8000000000000000ul, + IOSTO_ORIGIN = 0x000003fffffff000ul, + IOSTO_HW = 0x0000000000000800ul, + IOSTO_SW = 0x0000000000000400ul, + + IOCMD_CONF_TE = 0x0000800000000000ul, + + /* memory mapped registers */ + IOC_PT_CACHE_DIR = 0x000, + IOC_ST_CACHE_DIR = 0x800, + IOC_PT_CACHE_REG = 0x910, + IOC_ST_ORIGIN = 0x918, + IOC_CONF = 0x930, + + /* The high bit needs to be set on every DMA address, + only 2GB are addressable */ + CELL_DMA_VALID = 0x80000000, + CELL_DMA_MASK = 0x7fffffff, +}; + + +void cell_init_iommu(void); + +#endif --- linux-cg.orig/arch/powerpc/platforms/cell/nvram.c 1969-12-31 19:00:00.000000000 -0500 +++ linux-cg/arch/powerpc/platforms/cell/nvram.c 2005-09-01 02:37:46.077991888 -0400 @@ -0,0 +1,118 @@ +/* + * NVRAM for Cell Blade + * + * (C) Copyright IBM Corp. 2005 + * + * Authors : Utz Bacher + * + * 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, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include + +#include +#include +#include + +static void __iomem *cell_nvram_start; +static long cell_nvram_len; +static spinlock_t cell_nvram_lock = SPIN_LOCK_UNLOCKED; + +static ssize_t cell_nvram_read(char *buf, size_t count, loff_t *index) +{ + unsigned long flags; + + if (*index >= cell_nvram_len) + return 0; + if (*index + count > cell_nvram_len) + count = cell_nvram_len - *index; + + spin_lock_irqsave(&cell_nvram_lock, flags); + + memcpy_fromio(buf, cell_nvram_start + *index, count); + + spin_unlock_irqrestore(&cell_nvram_lock, flags); + + *index += count; + return count; +} + +static ssize_t cell_nvram_write(char *buf, size_t count, loff_t *index) +{ + unsigned long flags; + + if (*index >= cell_nvram_len) + return 0; + if (*index + count > cell_nvram_len) + count = cell_nvram_len - *index; + + spin_lock_irqsave(&cell_nvram_lock, flags); + + memcpy_toio(cell_nvram_start + *index, buf, count); + + spin_unlock_irqrestore(&cell_nvram_lock, flags); + + *index += count; + return count; +} + +static ssize_t cell_nvram_get_size(void) +{ + return cell_nvram_len; +} + +int __init cell_nvram_init(void) +{ + struct device_node *nvram_node; + unsigned long *buffer; + int proplen; + unsigned long nvram_addr; + int ret; + + ret = -ENODEV; + nvram_node = of_find_node_by_type(NULL, "nvram"); + if (!nvram_node) + goto out; + + ret = -EIO; + buffer = (unsigned long *)get_property(nvram_node, "reg", &proplen); + if (proplen != 2*sizeof(unsigned long)) + goto out; + + ret = -ENODEV; + nvram_addr = buffer[0]; + cell_nvram_len = buffer[1]; + if ( (!cell_nvram_len) || (!nvram_addr) ) + goto out; + + cell_nvram_start = ioremap(nvram_addr, cell_nvram_len); + if (!cell_nvram_start) + goto out; + + printk(KERN_INFO "CBEA NVRAM, %luk mapped to %p\n", + cell_nvram_len >> 10, cell_nvram_start); + + ppc_md.nvram_read = cell_nvram_read; + ppc_md.nvram_write = cell_nvram_write; + ppc_md.nvram_size = cell_nvram_get_size; + +out: + of_node_put(nvram_node); + return ret; +} --- linux-cg.orig/arch/powerpc/platforms/cell/pic.c 1969-12-31 19:00:00.000000000 -0500 +++ linux-cg/arch/powerpc/platforms/cell/pic.c 2005-09-01 02:37:46.079991584 -0400 @@ -0,0 +1,269 @@ +/* + * Cell Internal Interrupt Controller + * + * (C) Copyright IBM Deutschland Entwicklung GmbH 2005 + * + * Author: Arnd Bergmann + * + * 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, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +struct iic_pending_bits { + u32 data; + u8 flags; + u8 class; + u8 source; + u8 prio; +}; + +enum iic_pending_flags { + IIC_VALID = 0x80, + IIC_IPI = 0x40, +}; + +struct iic_regs { + struct iic_pending_bits pending; + struct iic_pending_bits pending_destr; + u64 generate; + u64 prio; +}; + +struct iic { + struct iic_regs __iomem *regs; +}; + +static DEFINE_PER_CPU(struct iic, iic); + +void iic_local_enable(void) +{ + out_be64(&__get_cpu_var(iic).regs->prio, 0xff); +} + +void iic_local_disable(void) +{ + out_be64(&__get_cpu_var(iic).regs->prio, 0x0); +} + +static unsigned int iic_startup(unsigned int irq) +{ + return 0; +} + +static void iic_enable(unsigned int irq) +{ + iic_local_enable(); +} + +static void iic_disable(unsigned int irq) +{ +} + +static void iic_end(unsigned int irq) +{ + iic_local_enable(); +} + +static struct hw_interrupt_type iic_pic = { + .typename = " CELLPIC ", + .startup = iic_startup, + .enable = iic_enable, + .disable = iic_disable, + .end = iic_end, +}; + +static int iic_external_get_irq(struct iic_pending_bits pending) +{ + int irq; + unsigned char node, unit; + + node = pending.source >> 4; + unit = pending.source & 0xf; + irq = -1; + + /* + * This mapping is specific to the Broadband + * Engine. We might need to get the numbers + * from the device tree to support future CPUs. + */ + switch (unit) { + case 0x00: + case 0x0b: + /* + * One of these units can be connected + * to an external interrupt controller. + */ + if (pending.prio > 0x3f || + pending.class != 2) + break; + irq = IIC_EXT_OFFSET + + spider_get_irq(pending.prio + node * IIC_NODE_STRIDE) + + node * IIC_NODE_STRIDE; + break; + case 0x01 ... 0x04: + case 0x07 ... 0x0a: + /* + * These units are connected to the SPEs + */ + if (pending.class > 2) + break; + irq = IIC_SPE_OFFSET + + pending.class * IIC_CLASS_STRIDE + + node * IIC_NODE_STRIDE + + unit; + break; + } + if (irq == -1) + printk(KERN_WARNING "Unexpected interrupt class %02x, " + "source %02x, prio %02x, cpu %02x\n", pending.class, + pending.source, pending.prio, smp_processor_id()); + return irq; +} + +/* Get an IRQ number from the pending state register of the IIC */ +int iic_get_irq(struct pt_regs *regs) +{ + struct iic *iic; + int irq; + struct iic_pending_bits pending; + + iic = &__get_cpu_var(iic); + *(unsigned long *) &pending = + in_be64((unsigned long __iomem *) &iic->regs->pending_destr); + + irq = -1; + if (pending.flags & IIC_VALID) { + if (pending.flags & IIC_IPI) { + irq = IIC_IPI_OFFSET + (pending.prio >> 4); +/* + if (irq > 0x80) + printk(KERN_WARNING "Unexpected IPI prio %02x" + "on CPU %02x\n", pending.prio, + smp_processor_id()); +*/ + } else { + irq = iic_external_get_irq(pending); + } + } + return irq; +} + +static struct iic_regs __iomem *find_iic(int cpu) +{ + struct device_node *np; + int nodeid = cpu / 2; + unsigned long regs; + struct iic_regs __iomem *iic_regs; + + for (np = of_find_node_by_type(NULL, "cpu"); + np; + np = of_find_node_by_type(np, "cpu")) { + if (nodeid == *(int *)get_property(np, "node-id", NULL)) + break; + } + + if (!np) { + printk(KERN_WARNING "IIC: CPU %d not found\n", cpu); + iic_regs = NULL; + } else { + regs = *(long *)get_property(np, "iic", NULL); + + /* hack until we have decided on the devtree info */ + regs += 0x400; + if (cpu & 1) + regs += 0x20; + + printk(KERN_DEBUG "IIC for CPU %d at %lx\n", cpu, regs); + iic_regs = __ioremap(regs, sizeof(struct iic_regs), + _PAGE_NO_CACHE); + } + return iic_regs; +} + +#ifdef CONFIG_SMP +void iic_setup_cpu(void) +{ + out_be64(&__get_cpu_var(iic).regs->prio, 0xff); +} + +void iic_cause_IPI(int cpu, int mesg) +{ + out_be64(&per_cpu(iic, cpu).regs->generate, mesg); +} + +static irqreturn_t iic_ipi_action(int irq, void *dev_id, struct pt_regs *regs) +{ + + smp_message_recv(irq - IIC_IPI_OFFSET, regs); + return IRQ_HANDLED; +} + +static void iic_request_ipi(int irq, const char *name) +{ + /* IPIs are marked SA_INTERRUPT as they must run with irqs + * disabled */ + get_irq_desc(irq)->handler = &iic_pic; + get_irq_desc(irq)->status |= IRQ_PER_CPU; + request_irq(irq, iic_ipi_action, SA_INTERRUPT, name, NULL); +} + +void iic_request_IPIs(void) +{ + iic_request_ipi(IIC_IPI_OFFSET + PPC_MSG_CALL_FUNCTION, "IPI-call"); + iic_request_ipi(IIC_IPI_OFFSET + PPC_MSG_RESCHEDULE, "IPI-resched"); +#ifdef CONFIG_DEBUGGER + iic_request_ipi(IIC_IPI_OFFSET + PPC_MSG_DEBUGGER_BREAK, "IPI-debug"); +#endif /* CONFIG_DEBUGGER */ +} +#endif /* CONFIG_SMP */ + +static void iic_setup_spe_handlers(void) +{ + int be, isrc; + + /* Assume two threads per BE are present */ + for (be=0; be < num_present_cpus() / 2; be++) { + for (isrc = 0; isrc < IIC_CLASS_STRIDE * 3; isrc++) { + int irq = IIC_NODE_STRIDE * be + IIC_SPE_OFFSET + isrc; + get_irq_desc(irq)->handler = &iic_pic; + } + } +} + +void iic_init_IRQ(void) +{ + int cpu, irq_offset; + struct iic *iic; + + irq_offset = 0; + for_each_cpu(cpu) { + iic = &per_cpu(iic, cpu); + iic->regs = find_iic(cpu); + if (iic->regs) + out_be64(&iic->regs->prio, 0xff); + } + iic_setup_spe_handlers(); +} --- linux-cg.orig/arch/powerpc/platforms/cell/setup.c 1969-12-31 19:00:00.000000000 -0500 +++ linux-cg/arch/powerpc/platforms/cell/setup.c 2005-09-01 02:37:46.079991584 -0400 @@ -0,0 +1,138 @@ +/* + * Copyright (C) 1995 Linus Torvalds + * Adapted from 'alpha' version by Gary Thomas + * Modified by Cort Dougan (cort at cs.nmt.edu) + * Modified by PPC64 Team, IBM Corp + * Modified by Cell Team, IBM Deutschland Entwicklung GmbH + * + * 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. + */ +#undef DEBUG + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "../../../ppc64/kernel/pci.h" +#include "iommu.h" + +#ifdef DEBUG +#define DBG(fmt...) udbg_printf(fmt) +#else +#define DBG(fmt...) +#endif + +void cell_get_cpuinfo(struct seq_file *m) +{ + struct device_node *root; + const char *model = ""; + + root = of_find_node_by_path("/"); + if (root) + model = get_property(root, "model", NULL); + seq_printf(m, "machine\t\t: Cell %s\n", model); + of_node_put(root); +} + +static void cell_progress(char *s, unsigned short hex) +{ + printk("*** %04x : %s\n", hex, s ? s : ""); +} + +static void __init cell_setup_arch(void) +{ + ppc_md.init_IRQ = iic_init_IRQ; + ppc_md.get_irq = iic_get_irq; + +#ifdef CONFIG_SMP + smp_init_pSeries(); +#endif + + /* init to some ~sane value until calibrate_delay() runs */ + loops_per_jiffy = 50000000; + + if (ROOT_DEV == 0) { + printk("No ramdisk, default root is /dev/hda2\n"); + ROOT_DEV = Root_HDA2; + } + + /* Find and initialize PCI host bridges */ + init_pci_config_tokens(); + find_and_init_phbs(); + spider_init_IRQ(); +#ifdef CONFIG_DUMMY_CONSOLE + conswitchp = &dummy_con; +#endif + + cell_nvram_init(); +} + +/* + * Early initialization. Relocation is on but do not reference unbolted pages + */ +static void __init cell_init_early(void) +{ + DBG(" -> cell_init_early()\n"); + + hpte_init_native(); + + cell_init_iommu(); + + ppc64_interrupt_controller = IC_CELL_PIC; + + DBG(" <- cell_init_early()\n"); +} + + +static int __init cell_probe(int platform) +{ + if (platform != PLATFORM_CELL) + return 0; + + return 1; +} + +struct machdep_calls __initdata cell_md = { + .probe = cell_probe, + .setup_arch = cell_setup_arch, + .init_early = cell_init_early, + .get_cpuinfo = cell_get_cpuinfo, + .restart = rtas_restart, + .power_off = rtas_power_off, + .halt = rtas_halt, + .get_boot_time = rtas_get_boot_time, + .get_rtc_time = rtas_get_rtc_time, + .set_rtc_time = rtas_set_rtc_time, + .calibrate_decr = generic_calibrate_decr, + .progress = cell_progress, +}; --- linux-cg.orig/arch/powerpc/platforms/cell/spider-pic.c 1969-12-31 19:00:00.000000000 -0500 +++ linux-cg/arch/powerpc/platforms/cell/spider-pic.c 2005-09-01 02:37:46.081991280 -0400 @@ -0,0 +1,190 @@ +/* + * External Interrupt Controller on Spider South Bridge + * + * (C) Copyright IBM Deutschland Entwicklung GmbH 2005 + * + * Author: Arnd Bergmann + * + * 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, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include + +#include +#include +#include +#include + +/* register layout taken from Spider spec, table 7.4-4 */ +enum { + TIR_DEN = 0x004, /* Detection Enable Register */ + TIR_MSK = 0x084, /* Mask Level Register */ + TIR_EDC = 0x0c0, /* Edge Detection Clear Register */ + TIR_PNDA = 0x100, /* Pending Register A */ + TIR_PNDB = 0x104, /* Pending Register B */ + TIR_CS = 0x144, /* Current Status Register */ + TIR_LCSA = 0x150, /* Level Current Status Register A */ + TIR_LCSB = 0x154, /* Level Current Status Register B */ + TIR_LCSC = 0x158, /* Level Current Status Register C */ + TIR_LCSD = 0x15c, /* Level Current Status Register D */ + TIR_CFGA = 0x200, /* Setting Register A0 */ + TIR_CFGB = 0x204, /* Setting Register B0 */ + /* 0x208 ... 0x3ff Setting Register An/Bn */ + TIR_PPNDA = 0x400, /* Packet Pending Register A */ + TIR_PPNDB = 0x404, /* Packet Pending Register B */ + TIR_PIERA = 0x408, /* Packet Output Error Register A */ + TIR_PIERB = 0x40c, /* Packet Output Error Register B */ + TIR_PIEN = 0x444, /* Packet Output Enable Register */ + TIR_PIPND = 0x454, /* Packet Output Pending Register */ + TIRDID = 0x484, /* Spider Device ID Register */ + REISTIM = 0x500, /* Reissue Command Timeout Time Setting */ + REISTIMEN = 0x504, /* Reissue Command Timeout Setting */ + REISWAITEN = 0x508, /* Reissue Wait Control*/ +}; + +static void __iomem *spider_pics[4]; + +static void __iomem *spider_get_pic(int irq) +{ + int node = irq / IIC_NODE_STRIDE; + irq %= IIC_NODE_STRIDE; + + if (irq >= IIC_EXT_OFFSET && + irq < IIC_EXT_OFFSET + IIC_NUM_EXT && + spider_pics) + return spider_pics[node]; + return NULL; +} + +static int spider_get_nr(unsigned int irq) +{ + return (irq % IIC_NODE_STRIDE) - IIC_EXT_OFFSET; +} + +static void __iomem *spider_get_irq_config(int irq) +{ + void __iomem *pic; + pic = spider_get_pic(irq); + return pic + TIR_CFGA + 8 * spider_get_nr(irq); +} + +static void spider_enable_irq(unsigned int irq) +{ + void __iomem *cfg = spider_get_irq_config(irq); + irq = spider_get_nr(irq); + + out_be32(cfg, in_be32(cfg) | 0x3107000eu); + out_be32(cfg + 4, in_be32(cfg + 4) | 0x00020000u | irq); +} + +static void spider_disable_irq(unsigned int irq) +{ + void __iomem *cfg = spider_get_irq_config(irq); + irq = spider_get_nr(irq); + + out_be32(cfg, in_be32(cfg) & ~0x30000000u); +} + +static unsigned int spider_startup_irq(unsigned int irq) +{ + spider_enable_irq(irq); + return 0; +} + +static void spider_shutdown_irq(unsigned int irq) +{ + spider_disable_irq(irq); +} + +static void spider_end_irq(unsigned int irq) +{ + spider_enable_irq(irq); +} + +static void spider_ack_irq(unsigned int irq) +{ + spider_disable_irq(irq); + iic_local_enable(); +} + +static struct hw_interrupt_type spider_pic = { + .typename = " SPIDER ", + .startup = spider_startup_irq, + .shutdown = spider_shutdown_irq, + .enable = spider_enable_irq, + .disable = spider_disable_irq, + .ack = spider_ack_irq, + .end = spider_end_irq, +}; + + +int spider_get_irq(unsigned long int_pending) +{ + void __iomem *regs = spider_get_pic(int_pending); + unsigned long cs; + int irq; + + cs = in_be32(regs + TIR_CS); + + irq = cs >> 24; + if (irq != 63) + return irq; + + return -1; +} + +void spider_init_IRQ(void) +{ + int node; + struct device_node *dn; + unsigned int *property; + long spiderpic; + int n; + +/* FIXME: detect multiple PICs as soon as the device tree has them */ + for (node = 0; node < 1; node++) { + dn = of_find_node_by_path("/"); + n = prom_n_addr_cells(dn); + property = (unsigned int *) get_property(dn, + "platform-spider-pic", NULL); + + if (!property) + continue; + for (spiderpic = 0; n > 0; --n) + spiderpic = (spiderpic << 32) + *property++; + printk(KERN_DEBUG "SPIDER addr: %lx\n", spiderpic); + spider_pics[node] = __ioremap(spiderpic, 0x800, _PAGE_NO_CACHE); + for (n = 0; n < IIC_NUM_EXT; n++) { + int irq = n + IIC_EXT_OFFSET + node * IIC_NODE_STRIDE; + get_irq_desc(irq)->handler = &spider_pic; + + /* do not mask any interrupts because of level */ + out_be32(spider_pics[node] + TIR_MSK, 0x0); + + /* disable edge detection clear */ + /* out_be32(spider_pics[node] + TIR_EDC, 0x0); */ + + /* enable interrupt packets to be output */ + out_be32(spider_pics[node] + TIR_PIEN, + in_be32(spider_pics[node] + TIR_PIEN) | 0x1); + + /* Enable the interrupt detection enable bit. Do this last! */ + out_be32(spider_pics[node] + TIR_DEN, + in_be32(spider_pics[node] +TIR_DEN) | 0x1); + + } + } +} --- linux-cg.orig/arch/ppc64/Kconfig 2005-09-01 02:37:40.900980184 -0400 +++ linux-cg/arch/ppc64/Kconfig 2005-09-01 02:37:46.081991280 -0400 @@ -77,10 +77,16 @@ config PPC_PSERIES bool " IBM pSeries & new iSeries" default y -config PPC_BPA - bool " Broadband Processor Architecture" +config PPC_CELL + bool " Cell Broadband Engine Architecture" depends on PPC_MULTIPLATFORM +# This is being phased out in the move to arch/powerpc +config PPC_BPA + bool + default y + depends on PPC_CELL + config PPC_PMAC depends on PPC_MULTIPLATFORM bool " Apple G5 based machines" --- linux-cg.orig/arch/ppc64/kernel/Makefile 2005-09-01 02:37:40.903979728 -0400 +++ linux-cg/arch/ppc64/kernel/Makefile 2005-09-01 02:37:46.082991128 -0400 @@ -33,8 +33,7 @@ obj-$(CONFIG_PPC_PSERIES) += pSeries_pci pSeries_nvram.o rtasd.o ras.o pSeries_reconfig.o \ pSeries_setup.o pSeries_iommu.o -obj-$(CONFIG_PPC_BPA) += bpa_setup.o bpa_iommu.o bpa_nvram.o \ - bpa_iic.o spider-pic.o +obj-$(CONFIG_PPC_CELL) += ../../powerpc/platforms/cell/ obj-$(CONFIG_KEXEC) += machine_kexec.o obj-$(CONFIG_EEH) += eeh.o @@ -68,7 +67,7 @@ ifdef CONFIG_SMP obj-$(CONFIG_PPC_PMAC) += pmac_smp.o smp-tbsync.o obj-$(CONFIG_PPC_ISERIES) += iSeries_smp.o obj-$(CONFIG_PPC_PSERIES) += pSeries_smp.o -obj-$(CONFIG_PPC_BPA) += pSeries_smp.o +obj-$(CONFIG_PPC_CELL) += pSeries_smp.o obj-$(CONFIG_PPC_MAPLE) += smp-tbsync.o endif --- linux-cg.orig/arch/ppc64/kernel/bpa_iic.c 2005-09-01 02:37:40.905979424 -0400 +++ linux-cg/arch/ppc64/kernel/bpa_iic.c 1969-12-31 19:00:00.000000000 -0500 @@ -1,270 +0,0 @@ -/* - * BPA Internal Interrupt Controller - * - * (C) Copyright IBM Deutschland Entwicklung GmbH 2005 - * - * Author: Arnd Bergmann - * - * 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, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#include "bpa_iic.h" - -struct iic_pending_bits { - u32 data; - u8 flags; - u8 class; - u8 source; - u8 prio; -}; - -enum iic_pending_flags { - IIC_VALID = 0x80, - IIC_IPI = 0x40, -}; - -struct iic_regs { - struct iic_pending_bits pending; - struct iic_pending_bits pending_destr; - u64 generate; - u64 prio; -}; - -struct iic { - struct iic_regs __iomem *regs; -}; - -static DEFINE_PER_CPU(struct iic, iic); - -void iic_local_enable(void) -{ - out_be64(&__get_cpu_var(iic).regs->prio, 0xff); -} - -void iic_local_disable(void) -{ - out_be64(&__get_cpu_var(iic).regs->prio, 0x0); -} - -static unsigned int iic_startup(unsigned int irq) -{ - return 0; -} - -static void iic_enable(unsigned int irq) -{ - iic_local_enable(); -} - -static void iic_disable(unsigned int irq) -{ -} - -static void iic_end(unsigned int irq) -{ - iic_local_enable(); -} - -static struct hw_interrupt_type iic_pic = { - .typename = " BPA-IIC ", - .startup = iic_startup, - .enable = iic_enable, - .disable = iic_disable, - .end = iic_end, -}; - -static int iic_external_get_irq(struct iic_pending_bits pending) -{ - int irq; - unsigned char node, unit; - - node = pending.source >> 4; - unit = pending.source & 0xf; - irq = -1; - - /* - * This mapping is specific to the Broadband - * Engine. We might need to get the numbers - * from the device tree to support future CPUs. - */ - switch (unit) { - case 0x00: - case 0x0b: - /* - * One of these units can be connected - * to an external interrupt controller. - */ - if (pending.prio > 0x3f || - pending.class != 2) - break; - irq = IIC_EXT_OFFSET - + spider_get_irq(pending.prio + node * IIC_NODE_STRIDE) - + node * IIC_NODE_STRIDE; - break; - case 0x01 ... 0x04: - case 0x07 ... 0x0a: - /* - * These units are connected to the SPEs - */ - if (pending.class > 2) - break; - irq = IIC_SPE_OFFSET - + pending.class * IIC_CLASS_STRIDE - + node * IIC_NODE_STRIDE - + unit; - break; - } - if (irq == -1) - printk(KERN_WARNING "Unexpected interrupt class %02x, " - "source %02x, prio %02x, cpu %02x\n", pending.class, - pending.source, pending.prio, smp_processor_id()); - return irq; -} - -/* Get an IRQ number from the pending state register of the IIC */ -int iic_get_irq(struct pt_regs *regs) -{ - struct iic *iic; - int irq; - struct iic_pending_bits pending; - - iic = &__get_cpu_var(iic); - *(unsigned long *) &pending = - in_be64((unsigned long __iomem *) &iic->regs->pending_destr); - - irq = -1; - if (pending.flags & IIC_VALID) { - if (pending.flags & IIC_IPI) { - irq = IIC_IPI_OFFSET + (pending.prio >> 4); -/* - if (irq > 0x80) - printk(KERN_WARNING "Unexpected IPI prio %02x" - "on CPU %02x\n", pending.prio, - smp_processor_id()); -*/ - } else { - irq = iic_external_get_irq(pending); - } - } - return irq; -} - -static struct iic_regs __iomem *find_iic(int cpu) -{ - struct device_node *np; - int nodeid = cpu / 2; - unsigned long regs; - struct iic_regs __iomem *iic_regs; - - for (np = of_find_node_by_type(NULL, "cpu"); - np; - np = of_find_node_by_type(np, "cpu")) { - if (nodeid == *(int *)get_property(np, "node-id", NULL)) - break; - } - - if (!np) { - printk(KERN_WARNING "IIC: CPU %d not found\n", cpu); - iic_regs = NULL; - } else { - regs = *(long *)get_property(np, "iic", NULL); - - /* hack until we have decided on the devtree info */ - regs += 0x400; - if (cpu & 1) - regs += 0x20; - - printk(KERN_DEBUG "IIC for CPU %d at %lx\n", cpu, regs); - iic_regs = __ioremap(regs, sizeof(struct iic_regs), - _PAGE_NO_CACHE); - } - return iic_regs; -} - -#ifdef CONFIG_SMP -void iic_setup_cpu(void) -{ - out_be64(&__get_cpu_var(iic).regs->prio, 0xff); -} - -void iic_cause_IPI(int cpu, int mesg) -{ - out_be64(&per_cpu(iic, cpu).regs->generate, mesg); -} - -static irqreturn_t iic_ipi_action(int irq, void *dev_id, struct pt_regs *regs) -{ - - smp_message_recv(irq - IIC_IPI_OFFSET, regs); - return IRQ_HANDLED; -} - -static void iic_request_ipi(int irq, const char *name) -{ - /* IPIs are marked SA_INTERRUPT as they must run with irqs - * disabled */ - get_irq_desc(irq)->handler = &iic_pic; - get_irq_desc(irq)->status |= IRQ_PER_CPU; - request_irq(irq, iic_ipi_action, SA_INTERRUPT, name, NULL); -} - -void iic_request_IPIs(void) -{ - iic_request_ipi(IIC_IPI_OFFSET + PPC_MSG_CALL_FUNCTION, "IPI-call"); - iic_request_ipi(IIC_IPI_OFFSET + PPC_MSG_RESCHEDULE, "IPI-resched"); -#ifdef CONFIG_DEBUGGER - iic_request_ipi(IIC_IPI_OFFSET + PPC_MSG_DEBUGGER_BREAK, "IPI-debug"); -#endif /* CONFIG_DEBUGGER */ -} -#endif /* CONFIG_SMP */ - -static void iic_setup_spe_handlers(void) -{ - int be, isrc; - - /* Assume two threads per BE are present */ - for (be=0; be < num_present_cpus() / 2; be++) { - for (isrc = 0; isrc < IIC_CLASS_STRIDE * 3; isrc++) { - int irq = IIC_NODE_STRIDE * be + IIC_SPE_OFFSET + isrc; - get_irq_desc(irq)->handler = &iic_pic; - } - } -} - -void iic_init_IRQ(void) -{ - int cpu, irq_offset; - struct iic *iic; - - irq_offset = 0; - for_each_cpu(cpu) { - iic = &per_cpu(iic, cpu); - iic->regs = find_iic(cpu); - if (iic->regs) - out_be64(&iic->regs->prio, 0xff); - } - iic_setup_spe_handlers(); -} --- linux-cg.orig/arch/ppc64/kernel/bpa_iic.h 2005-09-01 02:37:40.908978968 -0400 +++ linux-cg/arch/ppc64/kernel/bpa_iic.h 1969-12-31 19:00:00.000000000 -0500 @@ -1,62 +0,0 @@ -#ifndef ASM_BPA_IIC_H -#define ASM_BPA_IIC_H -#ifdef __KERNEL__ -/* - * Mapping of IIC pending bits into per-node - * interrupt numbers. - * - * IRQ FF CC SS PP FF CC SS PP Description - * - * 00-3f 80 02 +0 00 - 80 02 +0 3f South Bridge - * 00-3f 80 02 +b 00 - 80 02 +b 3f South Bridge - * 41-4a 80 00 +1 ** - 80 00 +a ** SPU Class 0 - * 51-5a 80 01 +1 ** - 80 01 +a ** SPU Class 1 - * 61-6a 80 02 +1 ** - 80 02 +a ** SPU Class 2 - * 70-7f C0 ** ** 00 - C0 ** ** 0f IPI - * - * F flags - * C class - * S source - * P Priority - * + node number - * * don't care - * - * A node consists of a Broadband Engine and an optional - * south bridge device providing a maximum of 64 IRQs. - * The south bridge may be connected to either IOIF0 - * or IOIF1. - * Each SPE is represented as three IRQ lines, one per - * interrupt class. - * 16 IRQ numbers are reserved for inter processor - * interruptions, although these are only used in the - * range of the first node. - * - * This scheme needs 128 IRQ numbers per BIF node ID, - * which means that with the total of 512 lines - * available, we can have a maximum of four nodes. - */ - -enum { - IIC_EXT_OFFSET = 0x00, /* Start of south bridge IRQs */ - IIC_NUM_EXT = 0x40, /* Number of south bridge IRQs */ - IIC_SPE_OFFSET = 0x40, /* Start of SPE interrupts */ - IIC_CLASS_STRIDE = 0x10, /* SPE IRQs per class */ - IIC_IPI_OFFSET = 0x70, /* Start of IPI IRQs */ - IIC_NUM_IPIS = 0x10, /* IRQs reserved for IPI */ - IIC_NODE_STRIDE = 0x80, /* Total IRQs per node */ -}; - -extern void iic_init_IRQ(void); -extern int iic_get_irq(struct pt_regs *regs); -extern void iic_cause_IPI(int cpu, int mesg); -extern void iic_request_IPIs(void); -extern void iic_setup_cpu(void); -extern void iic_local_enable(void); -extern void iic_local_disable(void); - - -extern void spider_init_IRQ(void); -extern int spider_get_irq(unsigned long int_pending); - -#endif -#endif /* ASM_BPA_IIC_H */ --- linux-cg.orig/arch/ppc64/kernel/bpa_iommu.c 2005-09-01 02:37:40.910978664 -0400 +++ linux-cg/arch/ppc64/kernel/bpa_iommu.c 1969-12-31 19:00:00.000000000 -0500 @@ -1,377 +0,0 @@ -/* - * IOMMU implementation for Broadband Processor Architecture - * We just establish a linear mapping at boot by setting all the - * IOPT cache entries in the CPU. - * The mapping functions should be identical to pci_direct_iommu, - * except for the handling of the high order bit that is required - * by the Spider bridge. These should be split into a separate - * file at the point where we get a different bridge chip. - * - * Copyright (C) 2005 IBM Deutschland Entwicklung GmbH, - * Arnd Bergmann - * - * Based on linear mapping - * Copyright (C) 2003 Benjamin Herrenschmidt (benh at kernel.crashing.org) - * - * 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. - */ - -#undef DEBUG - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "pci.h" -#include "bpa_iommu.h" - -static inline unsigned long -get_iopt_entry(unsigned long real_address, unsigned long ioid, - unsigned long prot) -{ - return (prot & IOPT_PROT_MASK) - | (IOPT_COHERENT) - | (IOPT_ORDER_VC) - | (real_address & IOPT_RPN_MASK) - | (ioid & IOPT_IOID_MASK); -} - -typedef struct { - unsigned long val; -} ioste; - -static inline ioste -mk_ioste(unsigned long val) -{ - ioste ioste = { .val = val, }; - return ioste; -} - -static inline ioste -get_iost_entry(unsigned long iopt_base, unsigned long io_address, unsigned page_size) -{ - unsigned long ps; - unsigned long iostep; - unsigned long nnpt; - unsigned long shift; - - switch (page_size) { - case 0x1000000: - ps = IOST_PS_16M; - nnpt = 0; /* one page per segment */ - shift = 5; /* segment has 16 iopt entries */ - break; - - case 0x100000: - ps = IOST_PS_1M; - nnpt = 0; /* one page per segment */ - shift = 1; /* segment has 256 iopt entries */ - break; - - case 0x10000: - ps = IOST_PS_64K; - nnpt = 0x07; /* 8 pages per io page table */ - shift = 0; /* all entries are used */ - break; - - case 0x1000: - ps = IOST_PS_4K; - nnpt = 0x7f; /* 128 pages per io page table */ - shift = 0; /* all entries are used */ - break; - - default: /* not a known compile time constant */ - BUILD_BUG_ON(1); - break; - } - - iostep = iopt_base + - /* need 8 bytes per iopte */ - (((io_address / page_size * 8) - /* align io page tables on 4k page boundaries */ - << shift) - /* nnpt+1 pages go into each iopt */ - & ~(nnpt << 12)); - - nnpt++; /* this seems to work, but the documentation is not clear - about wether we put nnpt or nnpt-1 into the ioste bits. - In theory, this can't work for 4k pages. */ - return mk_ioste(IOST_VALID_MASK - | (iostep & IOST_PT_BASE_MASK) - | ((nnpt << 5) & IOST_NNPT_MASK) - | (ps & IOST_PS_MASK)); -} - -/* compute the address of an io pte */ -static inline unsigned long -get_ioptep(ioste iost_entry, unsigned long io_address) -{ - unsigned long iopt_base; - unsigned long page_size; - unsigned long page_number; - unsigned long iopt_offset; - - iopt_base = iost_entry.val & IOST_PT_BASE_MASK; - page_size = iost_entry.val & IOST_PS_MASK; - - /* decode page size to compute page number */ - page_number = (io_address & 0x0fffffff) >> (10 + 2 * page_size); - /* page number is an offset into the io page table */ - iopt_offset = (page_number << 3) & 0x7fff8ul; - return iopt_base + iopt_offset; -} - -/* compute the tag field of the iopt cache entry */ -static inline unsigned long -get_ioc_tag(ioste iost_entry, unsigned long io_address) -{ - unsigned long iopte = get_ioptep(iost_entry, io_address); - - return IOPT_VALID_MASK - | ((iopte & 0x00000000000000ff8ul) >> 3) - | ((iopte & 0x0000003fffffc0000ul) >> 9); -} - -/* compute the hashed 6 bit index for the 4-way associative pte cache */ -static inline unsigned long -get_ioc_hash(ioste iost_entry, unsigned long io_address) -{ - unsigned long iopte = get_ioptep(iost_entry, io_address); - - return ((iopte & 0x000000000000001f8ul) >> 3) - ^ ((iopte & 0x00000000000020000ul) >> 17) - ^ ((iopte & 0x00000000000010000ul) >> 15) - ^ ((iopte & 0x00000000000008000ul) >> 13) - ^ ((iopte & 0x00000000000004000ul) >> 11) - ^ ((iopte & 0x00000000000002000ul) >> 9) - ^ ((iopte & 0x00000000000001000ul) >> 7); -} - -/* same as above, but pretend that we have a simpler 1-way associative - pte cache with an 8 bit index */ -static inline unsigned long -get_ioc_hash_1way(ioste iost_entry, unsigned long io_address) -{ - unsigned long iopte = get_ioptep(iost_entry, io_address); - - return ((iopte & 0x000000000000001f8ul) >> 3) - ^ ((iopte & 0x00000000000020000ul) >> 17) - ^ ((iopte & 0x00000000000010000ul) >> 15) - ^ ((iopte & 0x00000000000008000ul) >> 13) - ^ ((iopte & 0x00000000000004000ul) >> 11) - ^ ((iopte & 0x00000000000002000ul) >> 9) - ^ ((iopte & 0x00000000000001000ul) >> 7) - ^ ((iopte & 0x0000000000000c000ul) >> 8); -} - -static inline ioste -get_iost_cache(void __iomem *base, unsigned long index) -{ - unsigned long __iomem *p = (base + IOC_ST_CACHE_DIR); - return mk_ioste(in_be64(&p[index])); -} - -static inline void -set_iost_cache(void __iomem *base, unsigned long index, ioste ste) -{ - unsigned long __iomem *p = (base + IOC_ST_CACHE_DIR); - pr_debug("ioste %02lx was %016lx, store %016lx", index, - get_iost_cache(base, index).val, ste.val); - out_be64(&p[index], ste.val); - pr_debug(" now %016lx\n", get_iost_cache(base, index).val); -} - -static inline unsigned long -get_iopt_cache(void __iomem *base, unsigned long index, unsigned long *tag) -{ - unsigned long __iomem *tags = (void *)(base + IOC_PT_CACHE_DIR); - unsigned long __iomem *p = (void *)(base + IOC_PT_CACHE_REG); - - *tag = tags[index]; - rmb(); - return *p; -} - -static inline void -set_iopt_cache(void __iomem *base, unsigned long index, - unsigned long tag, unsigned long val) -{ - unsigned long __iomem *tags = base + IOC_PT_CACHE_DIR; - unsigned long __iomem *p = base + IOC_PT_CACHE_REG; - pr_debug("iopt %02lx was v%016lx/t%016lx, store v%016lx/t%016lx\n", - index, get_iopt_cache(base, index, &oldtag), oldtag, val, tag); - - out_be64(p, val); - out_be64(&tags[index], tag); -} - -static inline void -set_iost_origin(void __iomem *base) -{ - unsigned long __iomem *p = base + IOC_ST_ORIGIN; - unsigned long origin = IOSTO_ENABLE | IOSTO_SW; - - pr_debug("iost_origin %016lx, now %016lx\n", in_be64(p), origin); - out_be64(p, origin); -} - -static inline void -set_iocmd_config(void __iomem *base) -{ - unsigned long __iomem *p = base + 0xc00; - unsigned long conf; - - conf = in_be64(p); - pr_debug("iost_conf %016lx, now %016lx\n", conf, conf | IOCMD_CONF_TE); - out_be64(p, conf | IOCMD_CONF_TE); -} - -/* FIXME: get these from the device tree */ -#define ioc_base 0x20000511000ull -#define ioc_mmio_base 0x20000510000ull -#define ioid 0x48a -#define iopt_phys_offset (- 0x20000000) /* We have a 512MB offset from the SB */ -#define io_page_size 0x1000000 - -static unsigned long map_iopt_entry(unsigned long address) -{ - switch (address >> 20) { - case 0x600: - address = 0x24020000000ull; /* spider i/o */ - break; - default: - address += iopt_phys_offset; - break; - } - - return get_iopt_entry(address, ioid, IOPT_PROT_RW); -} - -static void iommu_bus_setup_null(struct pci_bus *b) { } -static void iommu_dev_setup_null(struct pci_dev *d) { } - -/* initialize the iommu to support a simple linear mapping - * for each DMA window used by any device. For now, we - * happen to know that there is only one DMA window in use, - * starting at iopt_phys_offset. */ -static void bpa_map_iommu(void) -{ - unsigned long address; - void __iomem *base; - ioste ioste; - unsigned long index; - - base = __ioremap(ioc_base, 0x1000, _PAGE_NO_CACHE); - pr_debug("%lx mapped to %p\n", ioc_base, base); - set_iocmd_config(base); - iounmap(base); - - base = __ioremap(ioc_mmio_base, 0x1000, _PAGE_NO_CACHE); - pr_debug("%lx mapped to %p\n", ioc_mmio_base, base); - - set_iost_origin(base); - - for (address = 0; address < 0x100000000ul; address += io_page_size) { - ioste = get_iost_entry(0x10000000000ul, address, io_page_size); - if ((address & 0xfffffff) == 0) /* segment start */ - set_iost_cache(base, address >> 28, ioste); - index = get_ioc_hash_1way(ioste, address); - pr_debug("addr %08lx, index %02lx, ioste %016lx\n", - address, index, ioste.val); - set_iopt_cache(base, - get_ioc_hash_1way(ioste, address), - get_ioc_tag(ioste, address), - map_iopt_entry(address)); - } - iounmap(base); -} - - -static void *bpa_alloc_coherent(struct device *hwdev, size_t size, - dma_addr_t *dma_handle, unsigned int __nocast flag) -{ - void *ret; - - ret = (void *)__get_free_pages(flag, get_order(size)); - if (ret != NULL) { - memset(ret, 0, size); - *dma_handle = virt_to_abs(ret) | BPA_DMA_VALID; - } - return ret; -} - -static void bpa_free_coherent(struct device *hwdev, size_t size, - void *vaddr, dma_addr_t dma_handle) -{ - free_pages((unsigned long)vaddr, get_order(size)); -} - -static dma_addr_t bpa_map_single(struct device *hwdev, void *ptr, - size_t size, enum dma_data_direction direction) -{ - return virt_to_abs(ptr) | BPA_DMA_VALID; -} - -static void bpa_unmap_single(struct device *hwdev, dma_addr_t dma_addr, - size_t size, enum dma_data_direction direction) -{ -} - -static int bpa_map_sg(struct device *hwdev, struct scatterlist *sg, - int nents, enum dma_data_direction direction) -{ - int i; - - for (i = 0; i < nents; i++, sg++) { - sg->dma_address = (page_to_phys(sg->page) + sg->offset) - | BPA_DMA_VALID; - sg->dma_length = sg->length; - } - - return nents; -} - -static void bpa_unmap_sg(struct device *hwdev, struct scatterlist *sg, - int nents, enum dma_data_direction direction) -{ -} - -static int bpa_dma_supported(struct device *dev, u64 mask) -{ - return mask < 0x100000000ull; -} - -void bpa_init_iommu(void) -{ - bpa_map_iommu(); - - /* Direct I/O, IOMMU off */ - ppc_md.iommu_dev_setup = iommu_dev_setup_null; - ppc_md.iommu_bus_setup = iommu_bus_setup_null; - - pci_dma_ops.alloc_coherent = bpa_alloc_coherent; - pci_dma_ops.free_coherent = bpa_free_coherent; - pci_dma_ops.map_single = bpa_map_single; - pci_dma_ops.unmap_single = bpa_unmap_single; - pci_dma_ops.map_sg = bpa_map_sg; - pci_dma_ops.unmap_sg = bpa_unmap_sg; - pci_dma_ops.dma_supported = bpa_dma_supported; -} --- linux-cg.orig/arch/ppc64/kernel/bpa_iommu.h 2005-09-01 02:37:40.912978360 -0400 +++ linux-cg/arch/ppc64/kernel/bpa_iommu.h 1969-12-31 19:00:00.000000000 -0500 @@ -1,65 +0,0 @@ -#ifndef BPA_IOMMU_H -#define BPA_IOMMU_H - -/* some constants */ -enum { - /* segment table entries */ - IOST_VALID_MASK = 0x8000000000000000ul, - IOST_TAG_MASK = 0x3000000000000000ul, - IOST_PT_BASE_MASK = 0x000003fffffff000ul, - IOST_NNPT_MASK = 0x0000000000000fe0ul, - IOST_PS_MASK = 0x000000000000000ful, - - IOST_PS_4K = 0x1, - IOST_PS_64K = 0x3, - IOST_PS_1M = 0x5, - IOST_PS_16M = 0x7, - - /* iopt tag register */ - IOPT_VALID_MASK = 0x0000000200000000ul, - IOPT_TAG_MASK = 0x00000001fffffffful, - - /* iopt cache register */ - IOPT_PROT_MASK = 0xc000000000000000ul, - IOPT_PROT_NONE = 0x0000000000000000ul, - IOPT_PROT_READ = 0x4000000000000000ul, - IOPT_PROT_WRITE = 0x8000000000000000ul, - IOPT_PROT_RW = 0xc000000000000000ul, - IOPT_COHERENT = 0x2000000000000000ul, - - IOPT_ORDER_MASK = 0x1800000000000000ul, - /* order access to same IOID/VC on same address */ - IOPT_ORDER_ADDR = 0x0800000000000000ul, - /* similar, but only after a write access */ - IOPT_ORDER_WRITES = 0x1000000000000000ul, - /* Order all accesses to same IOID/VC */ - IOPT_ORDER_VC = 0x1800000000000000ul, - - IOPT_RPN_MASK = 0x000003fffffff000ul, - IOPT_HINT_MASK = 0x0000000000000800ul, - IOPT_IOID_MASK = 0x00000000000007fful, - - IOSTO_ENABLE = 0x8000000000000000ul, - IOSTO_ORIGIN = 0x000003fffffff000ul, - IOSTO_HW = 0x0000000000000800ul, - IOSTO_SW = 0x0000000000000400ul, - - IOCMD_CONF_TE = 0x0000800000000000ul, - - /* memory mapped registers */ - IOC_PT_CACHE_DIR = 0x000, - IOC_ST_CACHE_DIR = 0x800, - IOC_PT_CACHE_REG = 0x910, - IOC_ST_ORIGIN = 0x918, - IOC_CONF = 0x930, - - /* The high bit needs to be set on every DMA address, - only 2GB are addressable */ - BPA_DMA_VALID = 0x80000000, - BPA_DMA_MASK = 0x7fffffff, -}; - - -void bpa_init_iommu(void); - -#endif --- linux-cg.orig/arch/ppc64/kernel/bpa_nvram.c 2005-09-01 02:37:40.914978056 -0400 +++ linux-cg/arch/ppc64/kernel/bpa_nvram.c 1969-12-31 19:00:00.000000000 -0500 @@ -1,118 +0,0 @@ -/* - * NVRAM for CPBW - * - * (C) Copyright IBM Corp. 2005 - * - * Authors : Utz Bacher - * - * 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, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include -#include -#include -#include -#include - -#include -#include -#include - -static void __iomem *bpa_nvram_start; -static long bpa_nvram_len; -static spinlock_t bpa_nvram_lock = SPIN_LOCK_UNLOCKED; - -static ssize_t bpa_nvram_read(char *buf, size_t count, loff_t *index) -{ - unsigned long flags; - - if (*index >= bpa_nvram_len) - return 0; - if (*index + count > bpa_nvram_len) - count = bpa_nvram_len - *index; - - spin_lock_irqsave(&bpa_nvram_lock, flags); - - memcpy_fromio(buf, bpa_nvram_start + *index, count); - - spin_unlock_irqrestore(&bpa_nvram_lock, flags); - - *index += count; - return count; -} - -static ssize_t bpa_nvram_write(char *buf, size_t count, loff_t *index) -{ - unsigned long flags; - - if (*index >= bpa_nvram_len) - return 0; - if (*index + count > bpa_nvram_len) - count = bpa_nvram_len - *index; - - spin_lock_irqsave(&bpa_nvram_lock, flags); - - memcpy_toio(bpa_nvram_start + *index, buf, count); - - spin_unlock_irqrestore(&bpa_nvram_lock, flags); - - *index += count; - return count; -} - -static ssize_t bpa_nvram_get_size(void) -{ - return bpa_nvram_len; -} - -int __init bpa_nvram_init(void) -{ - struct device_node *nvram_node; - unsigned long *buffer; - int proplen; - unsigned long nvram_addr; - int ret; - - ret = -ENODEV; - nvram_node = of_find_node_by_type(NULL, "nvram"); - if (!nvram_node) - goto out; - - ret = -EIO; - buffer = (unsigned long *)get_property(nvram_node, "reg", &proplen); - if (proplen != 2*sizeof(unsigned long)) - goto out; - - ret = -ENODEV; - nvram_addr = buffer[0]; - bpa_nvram_len = buffer[1]; - if ( (!bpa_nvram_len) || (!nvram_addr) ) - goto out; - - bpa_nvram_start = ioremap(nvram_addr, bpa_nvram_len); - if (!bpa_nvram_start) - goto out; - - printk(KERN_INFO "BPA NVRAM, %luk mapped to %p\n", - bpa_nvram_len >> 10, bpa_nvram_start); - - ppc_md.nvram_read = bpa_nvram_read; - ppc_md.nvram_write = bpa_nvram_write; - ppc_md.nvram_size = bpa_nvram_get_size; - -out: - of_node_put(nvram_node); - return ret; -} --- linux-cg.orig/arch/ppc64/kernel/bpa_setup.c 2005-09-01 02:37:40.917977600 -0400 +++ linux-cg/arch/ppc64/kernel/bpa_setup.c 1969-12-31 19:00:00.000000000 -0500 @@ -1,140 +0,0 @@ -/* - * linux/arch/ppc/kernel/bpa_setup.c - * - * Copyright (C) 1995 Linus Torvalds - * Adapted from 'alpha' version by Gary Thomas - * Modified by Cort Dougan (cort at cs.nmt.edu) - * Modified by PPC64 Team, IBM Corp - * Modified by BPA Team, IBM Deutschland Entwicklung GmbH - * - * 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. - */ -#undef DEBUG - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "pci.h" -#include "bpa_iic.h" -#include "bpa_iommu.h" - -#ifdef DEBUG -#define DBG(fmt...) udbg_printf(fmt) -#else -#define DBG(fmt...) -#endif - -void bpa_get_cpuinfo(struct seq_file *m) -{ - struct device_node *root; - const char *model = ""; - - root = of_find_node_by_path("/"); - if (root) - model = get_property(root, "model", NULL); - seq_printf(m, "machine\t\t: BPA %s\n", model); - of_node_put(root); -} - -static void bpa_progress(char *s, unsigned short hex) -{ - printk("*** %04x : %s\n", hex, s ? s : ""); -} - -static void __init bpa_setup_arch(void) -{ - ppc_md.init_IRQ = iic_init_IRQ; - ppc_md.get_irq = iic_get_irq; - -#ifdef CONFIG_SMP - smp_init_pSeries(); -#endif - - /* init to some ~sane value until calibrate_delay() runs */ - loops_per_jiffy = 50000000; - - if (ROOT_DEV == 0) { - printk("No ramdisk, default root is /dev/hda2\n"); - ROOT_DEV = Root_HDA2; - } - - /* Find and initialize PCI host bridges */ - init_pci_config_tokens(); - find_and_init_phbs(); - spider_init_IRQ(); -#ifdef CONFIG_DUMMY_CONSOLE - conswitchp = &dummy_con; -#endif - - bpa_nvram_init(); -} - -/* - * Early initialization. Relocation is on but do not reference unbolted pages - */ -static void __init bpa_init_early(void) -{ - DBG(" -> bpa_init_early()\n"); - - hpte_init_native(); - - bpa_init_iommu(); - - ppc64_interrupt_controller = IC_BPA_IIC; - - DBG(" <- bpa_init_early()\n"); -} - - -static int __init bpa_probe(int platform) -{ - if (platform != PLATFORM_BPA) - return 0; - - return 1; -} - -struct machdep_calls __initdata bpa_md = { - .probe = bpa_probe, - .setup_arch = bpa_setup_arch, - .init_early = bpa_init_early, - .get_cpuinfo = bpa_get_cpuinfo, - .restart = rtas_restart, - .power_off = rtas_power_off, - .halt = rtas_halt, - .get_boot_time = rtas_get_boot_time, - .get_rtc_time = rtas_get_rtc_time, - .set_rtc_time = rtas_set_rtc_time, - .calibrate_decr = generic_calibrate_decr, - .progress = bpa_progress, -}; --- linux-cg.orig/arch/ppc64/kernel/cpu_setup_power4.S 2005-09-01 02:37:44.101892936 -0400 +++ linux-cg/arch/ppc64/kernel/cpu_setup_power4.S 2005-09-01 02:37:49.128927440 -0400 @@ -77,7 +77,7 @@ _GLOBAL(__970_cpu_preinit) _GLOBAL(__setup_cpu_power4) blr -_GLOBAL(__setup_cpu_be) +_GLOBAL(__setup_cpu_cbe) /* Set large page sizes LP=0: 16MB, LP=1: 64KB */ addi r3, 0, 0 ori r3, r3, HID6_LB --- linux-cg.orig/arch/ppc64/kernel/cputable.c 2005-09-01 02:37:40.919977296 -0400 +++ linux-cg/arch/ppc64/kernel/cputable.c 2005-09-01 02:37:46.088990216 -0400 @@ -34,7 +34,7 @@ EXPORT_SYMBOL(cur_cpu_spec); extern void __setup_cpu_power3(unsigned long offset, struct cpu_spec* spec); extern void __setup_cpu_power4(unsigned long offset, struct cpu_spec* spec); extern void __setup_cpu_ppc970(unsigned long offset, struct cpu_spec* spec); -extern void __setup_cpu_be(unsigned long offset, struct cpu_spec* spec); +extern void __setup_cpu_cbe(unsigned long offset, struct cpu_spec* spec); /* We only set the altivec features if the kernel was compiled with altivec @@ -218,7 +218,7 @@ struct cpu_spec cpu_specs[] = { { /* BE DD1.x */ .pvr_mask = 0xffff0000, .pvr_value = 0x00700000, - .cpu_name = "Broadband Engine", + .cpu_name = "Cell Broadband Engine", .cpu_features = CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE | CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_ALTIVEC_COMP | @@ -227,7 +227,7 @@ struct cpu_spec cpu_specs[] = { PPC_FEATURE_HAS_ALTIVEC_COMP, .icache_bsize = 128, .dcache_bsize = 128, - .cpu_setup = __setup_cpu_be, + .cpu_setup = __setup_cpu_cbe, }, { /* default match */ .pvr_mask = 0x00000000, --- linux-cg.orig/arch/ppc64/kernel/irq.c 2005-09-01 02:37:40.921976992 -0400 +++ linux-cg/arch/ppc64/kernel/irq.c 2005-09-01 02:37:46.089990064 -0400 @@ -392,7 +392,7 @@ int virt_irq_create_mapping(unsigned int if (ppc64_interrupt_controller == IC_OPEN_PIC) return real_irq; /* no mapping for openpic (for now) */ - if (ppc64_interrupt_controller == IC_BPA_IIC) + if (ppc64_interrupt_controller == IC_CELL_PIC) return real_irq; /* no mapping for iic either */ /* don't map interrupts < MIN_VIRT_IRQ */ --- linux-cg.orig/arch/ppc64/kernel/pSeries_smp.c 2005-09-01 02:37:40.924976536 -0400 +++ linux-cg/arch/ppc64/kernel/pSeries_smp.c 2005-09-01 02:37:46.089990064 -0400 @@ -40,6 +40,7 @@ #include #include #include +#include #include #include #include @@ -48,7 +49,6 @@ #include #include "mpic.h" -#include "bpa_iic.h" #ifdef DEBUG #define DBG(fmt...) udbg_printf(fmt) @@ -464,7 +464,7 @@ void __init smp_init_pSeries(void) break; #endif #ifdef CONFIG_BPA_IIC - case IC_BPA_IIC: + case IC_CELL_PIC: smp_ops = &bpa_iic_smp_ops; break; #endif --- linux-cg.orig/arch/ppc64/kernel/setup.c 2005-09-01 02:37:40.926976232 -0400 +++ linux-cg/arch/ppc64/kernel/setup.c 2005-09-01 02:37:46.091989760 -0400 @@ -343,7 +343,7 @@ static void __init setup_cpu_maps(void) extern struct machdep_calls pSeries_md; extern struct machdep_calls pmac_md; extern struct machdep_calls maple_md; -extern struct machdep_calls bpa_md; +extern struct machdep_calls cell_md; /* Ultimately, stuff them in an elf section like initcalls... */ static struct machdep_calls __initdata *machines[] = { @@ -356,9 +356,9 @@ static struct machdep_calls __initdata * #ifdef CONFIG_PPC_MAPLE &maple_md, #endif /* CONFIG_PPC_MAPLE */ -#ifdef CONFIG_PPC_BPA - &bpa_md, -#endif +#ifdef CONFIG_PPC_CELL + &cell_md, +#endif /* CONFIG_PPC_CELL */ NULL }; --- linux-cg.orig/arch/ppc64/kernel/spider-pic.c 2005-09-01 02:37:40.928975928 -0400 +++ linux-cg/arch/ppc64/kernel/spider-pic.c 1969-12-31 19:00:00.000000000 -0500 @@ -1,191 +0,0 @@ -/* - * External Interrupt Controller on Spider South Bridge - * - * (C) Copyright IBM Deutschland Entwicklung GmbH 2005 - * - * Author: Arnd Bergmann - * - * 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, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include -#include - -#include -#include -#include - -#include "bpa_iic.h" - -/* register layout taken from Spider spec, table 7.4-4 */ -enum { - TIR_DEN = 0x004, /* Detection Enable Register */ - TIR_MSK = 0x084, /* Mask Level Register */ - TIR_EDC = 0x0c0, /* Edge Detection Clear Register */ - TIR_PNDA = 0x100, /* Pending Register A */ - TIR_PNDB = 0x104, /* Pending Register B */ - TIR_CS = 0x144, /* Current Status Register */ - TIR_LCSA = 0x150, /* Level Current Status Register A */ - TIR_LCSB = 0x154, /* Level Current Status Register B */ - TIR_LCSC = 0x158, /* Level Current Status Register C */ - TIR_LCSD = 0x15c, /* Level Current Status Register D */ - TIR_CFGA = 0x200, /* Setting Register A0 */ - TIR_CFGB = 0x204, /* Setting Register B0 */ - /* 0x208 ... 0x3ff Setting Register An/Bn */ - TIR_PPNDA = 0x400, /* Packet Pending Register A */ - TIR_PPNDB = 0x404, /* Packet Pending Register B */ - TIR_PIERA = 0x408, /* Packet Output Error Register A */ - TIR_PIERB = 0x40c, /* Packet Output Error Register B */ - TIR_PIEN = 0x444, /* Packet Output Enable Register */ - TIR_PIPND = 0x454, /* Packet Output Pending Register */ - TIRDID = 0x484, /* Spider Device ID Register */ - REISTIM = 0x500, /* Reissue Command Timeout Time Setting */ - REISTIMEN = 0x504, /* Reissue Command Timeout Setting */ - REISWAITEN = 0x508, /* Reissue Wait Control*/ -}; - -static void __iomem *spider_pics[4]; - -static void __iomem *spider_get_pic(int irq) -{ - int node = irq / IIC_NODE_STRIDE; - irq %= IIC_NODE_STRIDE; - - if (irq >= IIC_EXT_OFFSET && - irq < IIC_EXT_OFFSET + IIC_NUM_EXT && - spider_pics) - return spider_pics[node]; - return NULL; -} - -static int spider_get_nr(unsigned int irq) -{ - return (irq % IIC_NODE_STRIDE) - IIC_EXT_OFFSET; -} - -static void __iomem *spider_get_irq_config(int irq) -{ - void __iomem *pic; - pic = spider_get_pic(irq); - return pic + TIR_CFGA + 8 * spider_get_nr(irq); -} - -static void spider_enable_irq(unsigned int irq) -{ - void __iomem *cfg = spider_get_irq_config(irq); - irq = spider_get_nr(irq); - - out_be32(cfg, in_be32(cfg) | 0x3107000eu); - out_be32(cfg + 4, in_be32(cfg + 4) | 0x00020000u | irq); -} - -static void spider_disable_irq(unsigned int irq) -{ - void __iomem *cfg = spider_get_irq_config(irq); - irq = spider_get_nr(irq); - - out_be32(cfg, in_be32(cfg) & ~0x30000000u); -} - -static unsigned int spider_startup_irq(unsigned int irq) -{ - spider_enable_irq(irq); - return 0; -} - -static void spider_shutdown_irq(unsigned int irq) -{ - spider_disable_irq(irq); -} - -static void spider_end_irq(unsigned int irq) -{ - spider_enable_irq(irq); -} - -static void spider_ack_irq(unsigned int irq) -{ - spider_disable_irq(irq); - iic_local_enable(); -} - -static struct hw_interrupt_type spider_pic = { - .typename = " SPIDER ", - .startup = spider_startup_irq, - .shutdown = spider_shutdown_irq, - .enable = spider_enable_irq, - .disable = spider_disable_irq, - .ack = spider_ack_irq, - .end = spider_end_irq, -}; - - -int spider_get_irq(unsigned long int_pending) -{ - void __iomem *regs = spider_get_pic(int_pending); - unsigned long cs; - int irq; - - cs = in_be32(regs + TIR_CS); - - irq = cs >> 24; - if (irq != 63) - return irq; - - return -1; -} - -void spider_init_IRQ(void) -{ - int node; - struct device_node *dn; - unsigned int *property; - long spiderpic; - int n; - -/* FIXME: detect multiple PICs as soon as the device tree has them */ - for (node = 0; node < 1; node++) { - dn = of_find_node_by_path("/"); - n = prom_n_addr_cells(dn); - property = (unsigned int *) get_property(dn, - "platform-spider-pic", NULL); - - if (!property) - continue; - for (spiderpic = 0; n > 0; --n) - spiderpic = (spiderpic << 32) + *property++; - printk(KERN_DEBUG "SPIDER addr: %lx\n", spiderpic); - spider_pics[node] = __ioremap(spiderpic, 0x800, _PAGE_NO_CACHE); - for (n = 0; n < IIC_NUM_EXT; n++) { - int irq = n + IIC_EXT_OFFSET + node * IIC_NODE_STRIDE; - get_irq_desc(irq)->handler = &spider_pic; - - /* do not mask any interrupts because of level */ - out_be32(spider_pics[node] + TIR_MSK, 0x0); - - /* disable edge detection clear */ - /* out_be32(spider_pics[node] + TIR_EDC, 0x0); */ - - /* enable interrupt packets to be output */ - out_be32(spider_pics[node] + TIR_PIEN, - in_be32(spider_pics[node] + TIR_PIEN) | 0x1); - - /* Enable the interrupt detection enable bit. Do this last! */ - out_be32(spider_pics[node] + TIR_DEN, - in_be32(spider_pics[node] +TIR_DEN) | 0x1); - - } - } -} --- linux-cg.orig/arch/ppc64/kernel/traps.c 2005-09-01 02:37:40.931975472 -0400 +++ linux-cg/arch/ppc64/kernel/traps.c 2005-09-01 02:37:46.093989456 -0400 @@ -126,8 +126,8 @@ int die(const char *str, struct pt_regs printk("POWERMAC "); nl = 1; break; - case PLATFORM_BPA: - printk("BPA "); + case PLATFORM_CELL: + printk("CBEA "); nl = 1; break; } --- linux-cg.orig/include/asm-powerpc/cell-pic.h 1969-12-31 19:00:00.000000000 -0500 +++ linux-cg/include/asm-powerpc/cell-pic.h 2005-09-01 02:37:46.093989456 -0400 @@ -0,0 +1,62 @@ +#ifndef __ASM_CELL_PIC_H +#define __ASM_CELL_PIC_H +#ifdef __KERNEL__ +/* + * Mapping of IIC pending bits into per-node + * interrupt numbers. + * + * IRQ FF CC SS PP FF CC SS PP Description + * + * 00-3f 80 02 +0 00 - 80 02 +0 3f South Bridge + * 00-3f 80 02 +b 00 - 80 02 +b 3f South Bridge + * 41-4a 80 00 +1 ** - 80 00 +a ** SPU Class 0 + * 51-5a 80 01 +1 ** - 80 01 +a ** SPU Class 1 + * 61-6a 80 02 +1 ** - 80 02 +a ** SPU Class 2 + * 70-7f C0 ** ** 00 - C0 ** ** 0f IPI + * + * F flags + * C class + * S source + * P Priority + * + node number + * * don't care + * + * A node consists of a Cell Processor and an optional + * south bridge device providing a maximum of 64 IRQs. + * The south bridge may be connected to either IOIF0 + * or IOIF1. + * Each SPE is represented as three IRQ lines, one per + * interrupt class. + * 16 IRQ numbers are reserved for inter processor + * interruptions, although these are only used in the + * range of the first node. + * + * This scheme needs 128 IRQ numbers per BIF node ID, + * which means that with the total of 512 lines + * available, we can have a maximum of four nodes. + */ + +enum { + IIC_EXT_OFFSET = 0x00, /* Start of south bridge IRQs */ + IIC_NUM_EXT = 0x40, /* Number of south bridge IRQs */ + IIC_SPE_OFFSET = 0x40, /* Start of SPE interrupts */ + IIC_CLASS_STRIDE = 0x10, /* SPE IRQs per class */ + IIC_IPI_OFFSET = 0x70, /* Start of IPI IRQs */ + IIC_NUM_IPIS = 0x10, /* IRQs reserved for IPI */ + IIC_NODE_STRIDE = 0x80, /* Total IRQs per node */ +}; + +extern void iic_init_IRQ(void); +extern int iic_get_irq(struct pt_regs *regs); +extern void iic_cause_IPI(int cpu, int mesg); +extern void iic_request_IPIs(void); +extern void iic_setup_cpu(void); +extern void iic_local_enable(void); +extern void iic_local_disable(void); + + +extern void spider_init_IRQ(void); +extern int spider_get_irq(unsigned long int_pending); + +#endif /* __KERNEL__ */ +#endif /* __ASM_CELL_PIC_H */ --- linux-cg.orig/include/asm-ppc64/nvram.h 2005-09-01 02:37:40.935974864 -0400 +++ linux-cg/include/asm-ppc64/nvram.h 2005-09-01 02:37:46.094989304 -0400 @@ -70,7 +70,7 @@ extern struct nvram_partition *nvram_fin extern int pSeries_nvram_init(void); extern int pmac_nvram_init(void); -extern int bpa_nvram_init(void); +extern int cell_nvram_init(void); /* PowerMac specific nvram stuffs */ --- linux-cg.orig/include/asm-ppc64/processor.h 2005-09-01 02:37:40.938974408 -0400 +++ linux-cg/include/asm-ppc64/processor.h 2005-09-01 02:37:46.095989152 -0400 @@ -269,7 +269,7 @@ #define PV_630 0x0040 #define PV_630p 0x0041 #define PV_970MP 0x0044 -#define PV_BE 0x0070 +#define PV_CBE 0x0070 /* Platforms supported by PPC64 */ #define PLATFORM_PSERIES 0x0100 @@ -278,7 +278,8 @@ #define PLATFORM_LPAR 0x0001 #define PLATFORM_POWERMAC 0x0400 #define PLATFORM_MAPLE 0x0500 -#define PLATFORM_BPA 0x1000 +#define PLATFORM_CELL 0x1000 +#define PLATFORM_BPA PLATFORM_CELL /* Compatibility with drivers coming from PPC32 world */ #define _machine (systemcfg->platform) @@ -290,7 +291,7 @@ #define IC_INVALID 0 #define IC_OPEN_PIC 1 #define IC_PPC_XIC 2 -#define IC_BPA_IIC 3 +#define IC_CELL_PIC 3 #define XGLUE(a,b) a##b #define GLUE(a,b) XGLUE(a,b) From michael at ellerman.id.au Thu Sep 1 11:28:53 2005 From: michael at ellerman.id.au (Michael Ellerman) Date: Thu, 1 Sep 2005 11:28:53 +1000 (EST) Subject: [PATCH 0/18] Updates & bug fixes for iseries_veth network driver Message-ID: <1125538127.859382.875909607846.qpush@concordia> Hi, This is a series of patches for the iseries_veth driver. Most of these are pretty much unchanged since I posted them earlier: http://www.uwsg.iu.edu/hypermail/linux/kernel/0506.3/1837.html I've added patches to add sysfs support, and do some further code cleanups. Please merge if they look ok. cheers From michael at ellerman.id.au Thu Sep 1 11:28:57 2005 From: michael at ellerman.id.au (Michael Ellerman) Date: Thu, 1 Sep 2005 11:28:57 +1000 (EST) Subject: [PATCH 1/18] iseries_veth: Cleanup error and debug messages In-Reply-To: <1125538127.859382.875909607846.qpush@concordia> Message-ID: <20050901012857.38EFD681EA@ozlabs.org> Currently the iseries_veth driver prints the file name and line number in its error messages. This isn't very useful for most users, so just print "iseries_veth: message" instead. - convert uses of veth_printk() to veth_debug()/veth_error()/veth_info() - make terminology consistent, ie. always refer to LPAR not lpar - be consistent about printing return codes as %d not %x - make format strings fit in 80 columns Signed-off-by: Michael Ellerman --- drivers/net/iseries_veth.c | 98 +++++++++++++++++++++++---------------------- 1 files changed, 51 insertions(+), 47 deletions(-) Index: veth-dev2/drivers/net/iseries_veth.c =================================================================== --- veth-dev2.orig/drivers/net/iseries_veth.c +++ veth-dev2/drivers/net/iseries_veth.c @@ -79,6 +79,8 @@ #include #include +#undef DEBUG + #include "iseries_veth.h" MODULE_AUTHOR("Kyle Lucke "); @@ -176,11 +178,18 @@ static void veth_timed_ack(unsigned long * Utility functions */ -#define veth_printk(prio, fmt, args...) \ - printk(prio "%s: " fmt, __FILE__, ## args) +#define veth_info(fmt, args...) \ + printk(KERN_INFO "iseries_veth: " fmt, ## args) #define veth_error(fmt, args...) \ - printk(KERN_ERR "(%s:%3.3d) ERROR: " fmt, __FILE__, __LINE__ , ## args) + printk(KERN_ERR "iseries_veth: Error: " fmt, ## args) + +#ifdef DEBUG +#define veth_debug(fmt, args...) \ + printk(KERN_DEBUG "iseries_veth: " fmt, ## args) +#else +#define veth_debug(fmt, args...) do {} while (0) +#endif static inline void veth_stack_push(struct veth_lpar_connection *cnx, struct veth_msg *msg) @@ -278,7 +287,7 @@ static void veth_take_cap(struct veth_lp HvLpEvent_Type_VirtualLan); if (cnx->state & VETH_STATE_GOTCAPS) { - veth_error("Received a second capabilities from lpar %d\n", + veth_error("Received a second capabilities from LPAR %d.\n", cnx->remote_lp); event->base_event.xRc = HvLpEvent_Rc_BufferNotAvailable; HvCallEvent_ackLpEvent((struct HvLpEvent *) event); @@ -297,7 +306,7 @@ static void veth_take_cap_ack(struct vet spin_lock_irqsave(&cnx->lock, flags); if (cnx->state & VETH_STATE_GOTCAPACK) { - veth_error("Received a second capabilities ack from lpar %d\n", + veth_error("Received a second capabilities ack from LPAR %d.\n", cnx->remote_lp); } else { memcpy(&cnx->cap_ack_event, event, @@ -314,8 +323,7 @@ static void veth_take_monitor_ack(struct unsigned long flags; spin_lock_irqsave(&cnx->lock, flags); - veth_printk(KERN_DEBUG, "Monitor ack returned for lpar %d\n", - cnx->remote_lp); + veth_debug("cnx %d: lost connection.\n", cnx->remote_lp); cnx->state |= VETH_STATE_RESET; veth_kick_statemachine(cnx); spin_unlock_irqrestore(&cnx->lock, flags); @@ -336,8 +344,8 @@ static void veth_handle_ack(struct VethL veth_take_monitor_ack(cnx, event); break; default: - veth_error("Unknown ack type %d from lpar %d\n", - event->base_event.xSubtype, rlp); + veth_error("Unknown ack type %d from LPAR %d.\n", + event->base_event.xSubtype, rlp); }; } @@ -373,8 +381,8 @@ static void veth_handle_int(struct VethL veth_receive(cnx, event); break; default: - veth_error("Unknown interrupt type %d from lpar %d\n", - event->base_event.xSubtype, rlp); + veth_error("Unknown interrupt type %d from LPAR %d.\n", + event->base_event.xSubtype, rlp); }; } @@ -400,8 +408,8 @@ static int veth_process_caps(struct veth || (remote_caps->ack_threshold > VETH_MAX_ACKS_PER_MSG) || (remote_caps->ack_threshold == 0) || (cnx->ack_timeout == 0) ) { - veth_error("Received incompatible capabilities from lpar %d\n", - cnx->remote_lp); + veth_error("Received incompatible capabilities from LPAR %d.\n", + cnx->remote_lp); return HvLpEvent_Rc_InvalidSubtypeData; } @@ -418,8 +426,8 @@ static int veth_process_caps(struct veth cnx->num_ack_events += num; if (cnx->num_ack_events < num_acks_needed) { - veth_error("Couldn't allocate enough ack events for lpar %d\n", - cnx->remote_lp); + veth_error("Couldn't allocate enough ack events " + "for LPAR %d.\n", cnx->remote_lp); return HvLpEvent_Rc_BufferNotAvailable; } @@ -498,9 +506,8 @@ static void veth_statemachine(void *p) } else { if ( (rc != HvLpEvent_Rc_PartitionDead) && (rc != HvLpEvent_Rc_PathClosed) ) - veth_error("Error sending monitor to " - "lpar %d, rc=%x\n", - rlp, (int) rc); + veth_error("Error sending monitor to LPAR %d, " + "rc = %d\n", rlp, rc); /* Oh well, hope we get a cap from the other * end and do better when that kicks us */ @@ -523,9 +530,9 @@ static void veth_statemachine(void *p) } else { if ( (rc != HvLpEvent_Rc_PartitionDead) && (rc != HvLpEvent_Rc_PathClosed) ) - veth_error("Error sending caps to " - "lpar %d, rc=%x\n", - rlp, (int) rc); + veth_error("Error sending caps to LPAR %d, " + "rc = %d\n", rlp, rc); + /* Oh well, hope we get a cap from the other * end and do better when that kicks us */ goto out; @@ -565,10 +572,8 @@ static void veth_statemachine(void *p) add_timer(&cnx->ack_timer); cnx->state |= VETH_STATE_READY; } else { - veth_printk(KERN_ERR, "Caps rejected (rc=%d) by " - "lpar %d\n", - cnx->cap_ack_event.base_event.xRc, - rlp); + veth_error("Caps rejected by LPAR %d, rc = %d\n", + rlp, cnx->cap_ack_event.base_event.xRc); goto cant_cope; } } @@ -581,8 +586,8 @@ static void veth_statemachine(void *p) /* FIXME: we get here if something happens we really can't * cope with. The link will never work once we get here, and * all we can do is not lock the rest of the system up */ - veth_error("Badness on connection to lpar %d (state=%04lx) " - " - shutting down\n", rlp, cnx->state); + veth_error("Unrecoverable error on connection to LPAR %d, shutting down" + " (state = 0x%04lx)\n", rlp, cnx->state); cnx->state |= VETH_STATE_SHUTDOWN; spin_unlock_irq(&cnx->lock); } @@ -614,7 +619,7 @@ static int veth_init_connection(u8 rlp) msgs = kmalloc(VETH_NUMBUFFERS * sizeof(struct veth_msg), GFP_KERNEL); if (! msgs) { - veth_error("Can't allocate buffers for lpar %d\n", rlp); + veth_error("Can't allocate buffers for LPAR %d.\n", rlp); return -ENOMEM; } @@ -630,8 +635,7 @@ static int veth_init_connection(u8 rlp) cnx->num_events = veth_allocate_events(rlp, 2 + VETH_NUMBUFFERS); if (cnx->num_events < (2 + VETH_NUMBUFFERS)) { - veth_error("Can't allocate events for lpar %d, only got %d\n", - rlp, cnx->num_events); + veth_error("Can't allocate enough events for LPAR %d.\n", rlp); return -ENOMEM; } @@ -889,15 +893,13 @@ static struct net_device * __init veth_p rc = register_netdev(dev); if (rc != 0) { - veth_printk(KERN_ERR, - "Failed to register ethernet device for vlan %d\n", - vlan); + veth_error("Failed registering net device for vlan%d.\n", vlan); free_netdev(dev); return NULL; } - veth_printk(KERN_DEBUG, "%s attached to iSeries vlan %d (lpar_map=0x%04x)\n", - dev->name, vlan, port->lpar_map); + veth_info("%s attached to iSeries vlan %d (LPAR map = 0x%.4X)\n", + dev->name, vlan, port->lpar_map); return dev; } @@ -1030,7 +1032,7 @@ static int veth_start_xmit(struct sk_buf dev_kfree_skb(skb); } else { if (port->pending_skb) { - veth_error("%s: Tx while skb was pending!\n", + veth_error("%s: TX while skb was pending!\n", dev->name); dev_kfree_skb(skb); spin_unlock_irqrestore(&port->pending_gate, flags); @@ -1066,10 +1068,10 @@ static void veth_recycle_msg(struct veth memset(&msg->data, 0, sizeof(msg->data)); veth_stack_push(cnx, msg); - } else - if (cnx->state & VETH_STATE_OPEN) - veth_error("Bogus frames ack from lpar %d (#%d)\n", - cnx->remote_lp, msg->token); + } else if (cnx->state & VETH_STATE_OPEN) { + veth_error("Non-pending frame (# %d) acked by LPAR %d.\n", + cnx->remote_lp, msg->token); + } } static void veth_flush_pending(struct veth_lpar_connection *cnx) @@ -1179,8 +1181,8 @@ static void veth_flush_acks(struct veth_ 0, &cnx->pending_acks); if (rc != HvLpEvent_Rc_Good) - veth_error("Error 0x%x acking frames from lpar %d!\n", - (unsigned)rc, cnx->remote_lp); + veth_error("Failed acking frames from LPAR %d, rc = %d\n", + cnx->remote_lp, (int)rc); cnx->num_pending_acks = 0; memset(&cnx->pending_acks, 0xff, sizeof(cnx->pending_acks)); @@ -1216,9 +1218,10 @@ static void veth_receive(struct veth_lpa /* make sure that we have at least 1 EOF entry in the * remaining entries */ if (! (senddata->eofmask >> (startchunk + VETH_EOF_SHIFT))) { - veth_error("missing EOF frag in event " - "eofmask=0x%x startchunk=%d\n", - (unsigned) senddata->eofmask, startchunk); + veth_error("Missing EOF fragment in event " + "eofmask = 0x%x startchunk = %d\n", + (unsigned)senddata->eofmask, + startchunk); break; } @@ -1237,8 +1240,9 @@ static void veth_receive(struct veth_lpa /* nchunks == # of chunks in this frame */ if ((length - ETH_HLEN) > VETH_MAX_MTU) { - veth_error("Received oversize frame from lpar %d " - "(length=%d)\n", cnx->remote_lp, length); + veth_error("Received oversize frame from LPAR %d " + "(length = %d)\n", + cnx->remote_lp, length); continue; } From michael at ellerman.id.au Thu Sep 1 11:28:59 2005 From: michael at ellerman.id.au (Michael Ellerman) Date: Thu, 1 Sep 2005 11:28:59 +1000 (EST) Subject: [PATCH 2/18] iseries_veth: Remove a FIXME WRT deletion of the ack_timer In-Reply-To: <1125538127.859382.875909607846.qpush@concordia> Message-ID: <20050901012859.BDDC3681F5@ozlabs.org> The iseries_veth driver has a timer which we use to send acks. When the connection is reset or stopped we need to delete the timer. Currently we only call del_timer() when resetting a connection, which means the timer might run again while the connection is being re-setup. As it turns out that's ok, because the flags the timer consults have been reset. It's cleaner though to call del_timer_sync() once we've dropped the lock, although the timer may still run between us dropping the lock and calling del_timer_sync(), but as above that's ok. Signed-off-by: Michael Ellerman --- drivers/net/iseries_veth.c | 21 +++++++++++++-------- 1 files changed, 13 insertions(+), 8 deletions(-) Index: veth-dev2/drivers/net/iseries_veth.c =================================================================== --- veth-dev2.orig/drivers/net/iseries_veth.c +++ veth-dev2/drivers/net/iseries_veth.c @@ -450,13 +450,15 @@ static void veth_statemachine(void *p) if (cnx->state & VETH_STATE_RESET) { int i; - del_timer(&cnx->ack_timer); - if (cnx->state & VETH_STATE_OPEN) HvCallEvent_closeLpEventPath(cnx->remote_lp, HvLpEvent_Type_VirtualLan); - /* reset ack data */ + /* + * Reset ack data. This prevents the ack_timer actually + * doing anything, even if it runs one more time when + * we drop the lock below. + */ memset(&cnx->pending_acks, 0xff, sizeof (cnx->pending_acks)); cnx->num_pending_acks = 0; @@ -469,9 +471,16 @@ static void veth_statemachine(void *p) if (cnx->msgs) for (i = 0; i < VETH_NUMBUFFERS; ++i) veth_recycle_msg(cnx, cnx->msgs + i); + + /* Drop the lock so we can do stuff that might sleep or + * take other locks. */ spin_unlock_irq(&cnx->lock); + + del_timer_sync(&cnx->ack_timer); veth_flush_pending(cnx); + spin_lock_irq(&cnx->lock); + if (cnx->state & VETH_STATE_RESET) goto restart; } @@ -658,13 +667,9 @@ static void veth_stop_connection(u8 rlp) veth_kick_statemachine(cnx); spin_unlock_irq(&cnx->lock); + /* Wait for the state machine to run. */ flush_scheduled_work(); - /* FIXME: not sure if this is necessary - will already have - * been deleted by the state machine, just want to make sure - * its not running any more */ - del_timer_sync(&cnx->ack_timer); - if (cnx->num_events > 0) mf_deallocate_lp_events(cnx->remote_lp, HvLpEvent_Type_VirtualLan, From michael at ellerman.id.au Thu Sep 1 11:29:00 2005 From: michael at ellerman.id.au (Michael Ellerman) Date: Thu, 1 Sep 2005 11:29:00 +1000 (EST) Subject: [PATCH 3/18] iseries_veth: Try to avoid pathological reset behaviour In-Reply-To: <1125538127.859382.875909607846.qpush@concordia> Message-ID: <20050901012900.142D5681F7@ozlabs.org> The iseries_veth driver contains a state machine which is used to manage how connections are setup and neogotiated between LPARs. If one side of a connection resets for some reason, the two LPARs can get stuck in a race to re-setup the connection. This can lead to the connection being declared dead by one or both ends. In practice the connection is declared dead by one or both ends approximately 8/10 times a connection is reset, although it is rare for connections to be reset. (an example here: http://michael.ellerman.id.au/files/misc/veth-trace.html) The core of the problem is that the end that resets the connection doesn't wait for the other end to become aware of the reset. So the resetting end starts setting the connection back up, and then receives a reset from the other end (which is the response to the initial reset). And so on. We're severely limited in what we can do to fix this. The protocol between LPARs is essentially fixed, as we have to interoperate with both OS/400 and old Linux drivers. Which also means we need a fix that only changes the code on one end. The only fix I've found given that, is to just blindly sleep for a bit when resetting the connection, in the hope that the other end will get itself sorted. Needless to say I'd love it if someone has a better idea. This does work, I've so far been unable to get it to break, whereas without the fix a reset of one end will lead to a dead connection ~8/10 times. Signed-off-by: Michael Ellerman --- drivers/net/iseries_veth.c | 25 +++++++++++++++++++++++-- 1 files changed, 23 insertions(+), 2 deletions(-) Index: veth-dev2/drivers/net/iseries_veth.c =================================================================== --- veth-dev2.orig/drivers/net/iseries_veth.c +++ veth-dev2/drivers/net/iseries_veth.c @@ -324,8 +324,14 @@ static void veth_take_monitor_ack(struct spin_lock_irqsave(&cnx->lock, flags); veth_debug("cnx %d: lost connection.\n", cnx->remote_lp); - cnx->state |= VETH_STATE_RESET; - veth_kick_statemachine(cnx); + + /* Avoid kicking the statemachine once we're shutdown. + * It's unnecessary and it could break veth_stop_connection(). */ + + if (! (cnx->state & VETH_STATE_SHUTDOWN)) { + cnx->state |= VETH_STATE_RESET; + veth_kick_statemachine(cnx); + } spin_unlock_irqrestore(&cnx->lock, flags); } @@ -483,6 +489,12 @@ static void veth_statemachine(void *p) if (cnx->state & VETH_STATE_RESET) goto restart; + + /* Hack, wait for the other end to reset itself. */ + if (! (cnx->state & VETH_STATE_SHUTDOWN)) { + schedule_delayed_work(&cnx->statemachine_wq, 5 * HZ); + goto out; + } } if (cnx->state & VETH_STATE_SHUTDOWN) @@ -667,6 +679,15 @@ static void veth_stop_connection(u8 rlp) veth_kick_statemachine(cnx); spin_unlock_irq(&cnx->lock); + /* There's a slim chance the reset code has just queued the + * statemachine to run in five seconds. If so we need to cancel + * that and requeue the work to run now. */ + if (cancel_delayed_work(&cnx->statemachine_wq)) { + spin_lock_irq(&cnx->lock); + veth_kick_statemachine(cnx); + spin_unlock_irq(&cnx->lock); + } + /* Wait for the state machine to run. */ flush_scheduled_work(); From michael at ellerman.id.au Thu Sep 1 11:29:02 2005 From: michael at ellerman.id.au (Michael Ellerman) Date: Thu, 1 Sep 2005 11:29:02 +1000 (EST) Subject: [PATCH 4/18] iseries_veth: Fix broken promiscuous handling In-Reply-To: <1125538127.859382.875909607846.qpush@concordia> Message-ID: <20050901012902.89A72681F5@ozlabs.org> Due to a logic bug, once promiscuous mode is enabled in the iseries_veth driver it is never disabled. The driver keeps two flags, promiscuous and all_mcast which have exactly the same effect. This is because we only ever receive packets destined for us, or multicast packets. So consolidate them into one promiscuous flag for simplicity. Signed-off-by: Michael Ellerman --- drivers/net/iseries_veth.c | 16 +++++----------- 1 files changed, 5 insertions(+), 11 deletions(-) Index: veth-dev2/drivers/net/iseries_veth.c =================================================================== --- veth-dev2.orig/drivers/net/iseries_veth.c +++ veth-dev2/drivers/net/iseries_veth.c @@ -159,7 +159,6 @@ struct veth_port { rwlock_t mcast_gate; int promiscuous; - int all_mcast; int num_mcast; u64 mcast_addr[VETH_MAX_MCAST]; }; @@ -756,17 +755,15 @@ static void veth_set_multicast_list(stru write_lock_irqsave(&port->mcast_gate, flags); - if (dev->flags & IFF_PROMISC) { /* set promiscuous mode */ - printk(KERN_INFO "%s: Promiscuous mode enabled.\n", - dev->name); + if ((dev->flags & IFF_PROMISC) || (dev->flags & IFF_ALLMULTI) || + (dev->mc_count > VETH_MAX_MCAST)) { port->promiscuous = 1; - } else if ( (dev->flags & IFF_ALLMULTI) - || (dev->mc_count > VETH_MAX_MCAST) ) { - port->all_mcast = 1; } else { struct dev_mc_list *dmi = dev->mc_list; int i; + port->promiscuous = 0; + /* Update table */ port->num_mcast = 0; @@ -1145,12 +1142,9 @@ static inline int veth_frame_wanted(stru if ( (mac_addr == port->mac_addr) || (mac_addr == 0xffffffffffff0000) ) return 1; - if (! (((char *) &mac_addr)[0] & 0x01)) - return 0; - read_lock_irqsave(&port->mcast_gate, flags); - if (port->promiscuous || port->all_mcast) { + if (port->promiscuous) { wanted = 1; goto out; } From michael at ellerman.id.au Thu Sep 1 11:29:05 2005 From: michael at ellerman.id.au (Michael Ellerman) Date: Thu, 1 Sep 2005 11:29:05 +1000 (EST) Subject: [PATCH 5/18] iseries_veth: Remove redundant message stack lock In-Reply-To: <1125538127.859382.875909607846.qpush@concordia> Message-ID: <20050901012905.C9D3668205@ozlabs.org> The iseries_veth driver keeps a stack of messages for each connection and a lock to protect the stack. However there is also a per-connection lock which makes the message stack lock redundant. Remove the message stack lock and document the fact that callers of the stack-manipulation functions must hold the connection's lock. Signed-off-by: Michael Ellerman --- drivers/net/iseries_veth.c | 12 +++--------- 1 files changed, 3 insertions(+), 9 deletions(-) Index: veth-dev2/drivers/net/iseries_veth.c =================================================================== --- veth-dev2.orig/drivers/net/iseries_veth.c +++ veth-dev2/drivers/net/iseries_veth.c @@ -143,7 +143,6 @@ struct veth_lpar_connection { struct VethCapData remote_caps; u32 ack_timeout; - spinlock_t msg_stack_lock; struct veth_msg *msg_stack_head; }; @@ -190,27 +189,23 @@ static void veth_timed_ack(unsigned long #define veth_debug(fmt, args...) do {} while (0) #endif +/* You must hold the connection's lock when you call this function. */ static inline void veth_stack_push(struct veth_lpar_connection *cnx, struct veth_msg *msg) { - unsigned long flags; - - spin_lock_irqsave(&cnx->msg_stack_lock, flags); msg->next = cnx->msg_stack_head; cnx->msg_stack_head = msg; - spin_unlock_irqrestore(&cnx->msg_stack_lock, flags); } +/* You must hold the connection's lock when you call this function. */ static inline struct veth_msg *veth_stack_pop(struct veth_lpar_connection *cnx) { - unsigned long flags; struct veth_msg *msg; - spin_lock_irqsave(&cnx->msg_stack_lock, flags); msg = cnx->msg_stack_head; if (msg) cnx->msg_stack_head = cnx->msg_stack_head->next; - spin_unlock_irqrestore(&cnx->msg_stack_lock, flags); + return msg; } @@ -645,7 +640,6 @@ static int veth_init_connection(u8 rlp) cnx->msgs = msgs; memset(msgs, 0, VETH_NUMBUFFERS * sizeof(struct veth_msg)); - spin_lock_init(&cnx->msg_stack_lock); for (i = 0; i < VETH_NUMBUFFERS; i++) { msgs[i].token = i; From michael at ellerman.id.au Thu Sep 1 11:29:06 2005 From: michael at ellerman.id.au (Michael Ellerman) Date: Thu, 1 Sep 2005 11:29:06 +1000 (EST) Subject: [PATCH 6/18] iseries_veth: Replace lock-protected atomic with an ordinary variable In-Reply-To: <1125538127.859382.875909607846.qpush@concordia> Message-ID: <20050901012906.9EF9568206@ozlabs.org> The iseries_veth driver uses atomic ops to manipulate the in_use field of one of its per-connection structures. However all references to the flag occur while the connection's lock is held, so the atomic ops aren't necessary. Signed-off-by: Michael Ellerman --- drivers/net/iseries_veth.c | 13 +++++++------ 1 files changed, 7 insertions(+), 6 deletions(-) Index: veth-dev2/drivers/net/iseries_veth.c =================================================================== --- veth-dev2.orig/drivers/net/iseries_veth.c +++ veth-dev2/drivers/net/iseries_veth.c @@ -117,7 +117,7 @@ struct veth_msg { struct veth_msg *next; struct VethFramesData data; int token; - unsigned long in_use; + int in_use; struct sk_buff *skb; struct device *dev; }; @@ -957,6 +957,8 @@ static int veth_transmit_to_one(struct s goto drop; } + msg->in_use = 1; + dma_length = skb->len; dma_address = dma_map_single(port->dev, skb->data, dma_length, DMA_TO_DEVICE); @@ -971,7 +973,6 @@ static int veth_transmit_to_one(struct s msg->data.addr[0] = dma_address; msg->data.len[0] = dma_length; msg->data.eofmask = 1 << VETH_EOF_SHIFT; - set_bit(0, &(msg->in_use)); rc = veth_signaldata(cnx, VethEventTypeFrames, msg->token, &msg->data); if (rc != HvLpEvent_Rc_Good) @@ -981,10 +982,8 @@ static int veth_transmit_to_one(struct s return 0; recycle_and_drop: + /* we free the skb below, so tell veth_recycle_msg() not to. */ msg->skb = NULL; - /* need to set in use to make veth_recycle_msg in case this - * was a mapping failure */ - set_bit(0, &msg->in_use); veth_recycle_msg(cnx, msg); drop: port->stats.tx_errors++; @@ -1066,12 +1065,14 @@ static int veth_start_xmit(struct sk_buf return 0; } +/* You must hold the connection's lock when you call this function. */ static void veth_recycle_msg(struct veth_lpar_connection *cnx, struct veth_msg *msg) { u32 dma_address, dma_length; - if (test_and_clear_bit(0, &msg->in_use)) { + if (msg->in_use) { + msg->in_use = 0; dma_address = msg->data.addr[0]; dma_length = msg->data.len[0]; From michael at ellerman.id.au Thu Sep 1 11:29:07 2005 From: michael at ellerman.id.au (Michael Ellerman) Date: Thu, 1 Sep 2005 11:29:07 +1000 (EST) Subject: [PATCH 7/18] iseries_veth: Only call dma_unmap_single() if dma_map_single() succeeded In-Reply-To: <1125538127.859382.875909607846.qpush@concordia> Message-ID: <20050901012907.A531B681F5@ozlabs.org> The iseries_veth driver unconditionally calls dma_unmap_single() even when the corresponding dma_map_single() may have failed. Rework the code a bit to keep the return value from dma_unmap_single() around, and then check if it's a dma_mapping_error() before we do the dma_unmap_single(). Signed-off-by: Michael Ellerman --- drivers/net/iseries_veth.c | 17 ++++++++--------- 1 files changed, 8 insertions(+), 9 deletions(-) Index: veth-dev2/drivers/net/iseries_veth.c =================================================================== --- veth-dev2.orig/drivers/net/iseries_veth.c +++ veth-dev2/drivers/net/iseries_veth.c @@ -931,7 +931,6 @@ static int veth_transmit_to_one(struct s struct veth_lpar_connection *cnx = veth_cnx[rlp]; struct veth_port *port = (struct veth_port *) dev->priv; HvLpEvent_Rc rc; - u32 dma_address, dma_length; struct veth_msg *msg = NULL; int err = 0; unsigned long flags; @@ -959,20 +958,19 @@ static int veth_transmit_to_one(struct s msg->in_use = 1; - dma_length = skb->len; - dma_address = dma_map_single(port->dev, skb->data, - dma_length, DMA_TO_DEVICE); + msg->data.addr[0] = dma_map_single(port->dev, skb->data, + skb->len, DMA_TO_DEVICE); - if (dma_mapping_error(dma_address)) + if (dma_mapping_error(msg->data.addr[0])) goto recycle_and_drop; /* Is it really necessary to check the length and address * fields of the first entry here? */ msg->skb = skb; msg->dev = port->dev; - msg->data.addr[0] = dma_address; - msg->data.len[0] = dma_length; + msg->data.len[0] = skb->len; msg->data.eofmask = 1 << VETH_EOF_SHIFT; + rc = veth_signaldata(cnx, VethEventTypeFrames, msg->token, &msg->data); if (rc != HvLpEvent_Rc_Good) @@ -1076,8 +1074,9 @@ static void veth_recycle_msg(struct veth dma_address = msg->data.addr[0]; dma_length = msg->data.len[0]; - dma_unmap_single(msg->dev, dma_address, dma_length, - DMA_TO_DEVICE); + if (!dma_mapping_error(dma_address)) + dma_unmap_single(msg->dev, dma_address, dma_length, + DMA_TO_DEVICE); if (msg->skb) { dev_kfree_skb_any(msg->skb); From michael at ellerman.id.au Thu Sep 1 11:29:08 2005 From: michael at ellerman.id.au (Michael Ellerman) Date: Thu, 1 Sep 2005 11:29:08 +1000 (EST) Subject: [PATCH 8/18] iseries_veth: Make init_connection() & destroy_connection() symmetrical In-Reply-To: <1125538127.859382.875909607846.qpush@concordia> Message-ID: <20050901012908.E24DF68212@ozlabs.org> This patch makes veth_init_connection() and veth_destroy_connection() symmetrical in that they allocate/deallocate the same data. Currently if there's an error while initialising connections (ie. ENOMEM) we call veth_module_cleanup(), however this will oops because we call driver_unregister() before we've called driver_register(). I've never seen this actually happen though. So instead we explicitly call veth_destroy_connection() for each connection, any that have been set up will be deallocated. We also fix a potential leak if vio_register_driver() fails. Signed-off-by: Michael Ellerman --- drivers/net/iseries_veth.c | 35 ++++++++++++++++++++++------------- 1 files changed, 22 insertions(+), 13 deletions(-) Index: veth-dev2/drivers/net/iseries_veth.c =================================================================== --- veth-dev2.orig/drivers/net/iseries_veth.c +++ veth-dev2/drivers/net/iseries_veth.c @@ -683,6 +683,14 @@ static void veth_stop_connection(u8 rlp) /* Wait for the state machine to run. */ flush_scheduled_work(); +} + +static void veth_destroy_connection(u8 rlp) +{ + struct veth_lpar_connection *cnx = veth_cnx[rlp]; + + if (! cnx) + return; if (cnx->num_events > 0) mf_deallocate_lp_events(cnx->remote_lp, @@ -694,14 +702,6 @@ static void veth_stop_connection(u8 rlp) HvLpEvent_Type_VirtualLan, cnx->num_ack_events, NULL, NULL); -} - -static void veth_destroy_connection(u8 rlp) -{ - struct veth_lpar_connection *cnx = veth_cnx[rlp]; - - if (! cnx) - return; kfree(cnx->msgs); kfree(cnx); @@ -1441,15 +1441,24 @@ int __init veth_module_init(void) for (i = 0; i < HVMAXARCHITECTEDLPS; ++i) { rc = veth_init_connection(i); - if (rc != 0) { - veth_module_cleanup(); - return rc; - } + if (rc != 0) + goto error; } HvLpEvent_registerHandler(HvLpEvent_Type_VirtualLan, &veth_handle_event); - return vio_register_driver(&veth_driver); + rc = vio_register_driver(&veth_driver); + if (rc != 0) + goto error; + + return 0; + +error: + for (i = 0; i < HVMAXARCHITECTEDLPS; ++i) { + veth_destroy_connection(i); + } + + return rc; } module_init(veth_module_init); From michael at ellerman.id.au Thu Sep 1 11:29:09 2005 From: michael at ellerman.id.au (Michael Ellerman) Date: Thu, 1 Sep 2005 11:29:09 +1000 (EST) Subject: [PATCH 9/18] iseries_veth: Use kobjects to track lifecycle of connection structs In-Reply-To: <1125538127.859382.875909607846.qpush@concordia> Message-ID: <20050901012909.C98036820F@ozlabs.org> The iseries_veth driver can attach to multiple vlans, which correspond to multiple net devices. However there is only 1 connection between each LPAR, so the connection structure may be shared by multiple net devices. This makes module removal messy, because we can't deallocate the connections until we know there are no net devices still using them. The solution is to use ref counts on the connections, so we can delete them (actually stop) as soon as the ref count hits zero. This patch fixes (part of) a bug we were seeing with IPv6 sending probes to a dead LPAR, which would then hang us forever due to leftover skbs. Signed-off-by: Michael Ellerman --- drivers/net/iseries_veth.c | 121 ++++++++++++++++++++++++++++++--------------- 1 files changed, 83 insertions(+), 38 deletions(-) Index: veth-dev2/drivers/net/iseries_veth.c =================================================================== --- veth-dev2.orig/drivers/net/iseries_veth.c +++ veth-dev2/drivers/net/iseries_veth.c @@ -129,6 +129,7 @@ struct veth_lpar_connection { int num_events; struct VethCapData local_caps; + struct kobject kobject; struct timer_list ack_timer; spinlock_t lock; @@ -171,6 +172,11 @@ static void veth_recycle_msg(struct veth static void veth_flush_pending(struct veth_lpar_connection *cnx); static void veth_receive(struct veth_lpar_connection *, struct VethLpEvent *); static void veth_timed_ack(unsigned long connectionPtr); +static void veth_release_connection(struct kobject *kobject); + +static struct kobj_type veth_lpar_connection_ktype = { + .release = veth_release_connection +}; /* * Utility functions @@ -611,7 +617,7 @@ static int veth_init_connection(u8 rlp) { struct veth_lpar_connection *cnx; struct veth_msg *msgs; - int i; + int i, rc; if ( (rlp == this_lp) || ! HvLpConfig_doLpsCommunicateOnVirtualLan(this_lp, rlp) ) @@ -632,6 +638,14 @@ static int veth_init_connection(u8 rlp) veth_cnx[rlp] = cnx; + /* This gets us 1 reference, which is held on behalf of the driver + * infrastructure. It's released at module unload. */ + kobject_init(&cnx->kobject); + cnx->kobject.ktype = &veth_lpar_connection_ktype; + rc = kobject_set_name(&cnx->kobject, "cnx%.2d", rlp); + if (rc != 0) + return rc; + msgs = kmalloc(VETH_NUMBUFFERS * sizeof(struct veth_msg), GFP_KERNEL); if (! msgs) { veth_error("Can't allocate buffers for LPAR %d.\n", rlp); @@ -660,11 +674,9 @@ static int veth_init_connection(u8 rlp) return 0; } -static void veth_stop_connection(u8 rlp) +static void veth_stop_connection(struct veth_lpar_connection *cnx) { - struct veth_lpar_connection *cnx = veth_cnx[rlp]; - - if (! cnx) + if (!cnx) return; spin_lock_irq(&cnx->lock); @@ -685,11 +697,9 @@ static void veth_stop_connection(u8 rlp) flush_scheduled_work(); } -static void veth_destroy_connection(u8 rlp) +static void veth_destroy_connection(struct veth_lpar_connection *cnx) { - struct veth_lpar_connection *cnx = veth_cnx[rlp]; - - if (! cnx) + if (!cnx) return; if (cnx->num_events > 0) @@ -704,8 +714,16 @@ static void veth_destroy_connection(u8 r NULL, NULL); kfree(cnx->msgs); + veth_cnx[cnx->remote_lp] = NULL; kfree(cnx); - veth_cnx[rlp] = NULL; +} + +static void veth_release_connection(struct kobject *kobj) +{ + struct veth_lpar_connection *cnx; + cnx = container_of(kobj, struct veth_lpar_connection, kobject); + veth_stop_connection(cnx); + veth_destroy_connection(cnx); } /* @@ -1349,15 +1367,31 @@ static void veth_timed_ack(unsigned long static int veth_remove(struct vio_dev *vdev) { - int i = vdev->unit_address; + struct veth_lpar_connection *cnx; struct net_device *dev; + struct veth_port *port; + int i; - dev = veth_dev[i]; - if (dev != NULL) { - veth_dev[i] = NULL; - unregister_netdev(dev); - free_netdev(dev); + dev = veth_dev[vdev->unit_address]; + + if (! dev) + return 0; + + port = netdev_priv(dev); + + for (i = 0; i < HVMAXARCHITECTEDLPS; i++) { + cnx = veth_cnx[i]; + + if (cnx && (port->lpar_map & (1 << i))) { + /* Drop our reference to connections on our VLAN */ + kobject_put(&cnx->kobject); + } } + + veth_dev[vdev->unit_address] = NULL; + unregister_netdev(dev); + free_netdev(dev); + return 0; } @@ -1365,6 +1399,7 @@ static int veth_probe(struct vio_dev *vd { int i = vdev->unit_address; struct net_device *dev; + struct veth_port *port; dev = veth_probe_one(i, &vdev->dev); if (dev == NULL) { @@ -1373,11 +1408,23 @@ static int veth_probe(struct vio_dev *vd } veth_dev[i] = dev; - /* Start the state machine on each connection, to commence - * link negotiation */ - for (i = 0; i < HVMAXARCHITECTEDLPS; i++) - if (veth_cnx[i]) - veth_kick_statemachine(veth_cnx[i]); + port = (struct veth_port*)netdev_priv(dev); + + /* Start the state machine on each connection on this vlan. If we're + * the first dev to do so this will commence link negotiation */ + for (i = 0; i < HVMAXARCHITECTEDLPS; i++) { + struct veth_lpar_connection *cnx; + + if (! (port->lpar_map & (1 << i))) + continue; + + cnx = veth_cnx[i]; + if (!cnx) + continue; + + kobject_get(&cnx->kobject); + veth_kick_statemachine(cnx); + } return 0; } @@ -1406,29 +1453,27 @@ static struct vio_driver veth_driver = { void __exit veth_module_cleanup(void) { int i; + struct veth_lpar_connection *cnx; - /* Stop the queues first to stop any new packets being sent. */ - for (i = 0; i < HVMAXARCHITECTEDVIRTUALLANS; i++) - if (veth_dev[i]) - netif_stop_queue(veth_dev[i]); - - /* Stop the connections before we unregister the driver. This - * ensures there's no skbs lying around holding the device open. */ - for (i = 0; i < HVMAXARCHITECTEDLPS; ++i) - veth_stop_connection(i); - + /* Disconnect our "irq" to stop events coming from the Hypervisor. */ HvLpEvent_unregisterHandler(HvLpEvent_Type_VirtualLan); - /* Hypervisor callbacks may have scheduled more work while we - * were stoping connections. Now that we've disconnected from - * the hypervisor make sure everything's finished. */ + /* Make sure any work queued from Hypervisor callbacks is finished. */ flush_scheduled_work(); - vio_unregister_driver(&veth_driver); + for (i = 0; i < HVMAXARCHITECTEDLPS; ++i) { + cnx = veth_cnx[i]; + + if (!cnx) + continue; - for (i = 0; i < HVMAXARCHITECTEDLPS; ++i) - veth_destroy_connection(i); + /* Drop the driver's reference to the connection */ + kobject_put(&cnx->kobject); + } + /* Unregister the driver, which will close all the netdevs and stop + * the connections when they're no longer referenced. */ + vio_unregister_driver(&veth_driver); } module_exit(veth_module_cleanup); @@ -1456,7 +1501,7 @@ int __init veth_module_init(void) error: for (i = 0; i < HVMAXARCHITECTEDLPS; ++i) { - veth_destroy_connection(i); + veth_destroy_connection(veth_cnx[i]); } return rc; From michael at ellerman.id.au Thu Sep 1 11:29:12 2005 From: michael at ellerman.id.au (Michael Ellerman) Date: Thu, 1 Sep 2005 11:29:12 +1000 (EST) Subject: [PATCH 10/18] iseries_veth: Remove TX timeout code In-Reply-To: <1125538127.859382.875909607846.qpush@concordia> Message-ID: <20050901012912.2A0B768212@ozlabs.org> The iseries_veth driver uses the generic TX timeout watchdog, however a better solution is in the works, so remove this code. Signed-off-by: Michael Ellerman --- drivers/net/iseries_veth.c | 48 --------------------------------------------- 1 files changed, 48 deletions(-) Index: veth-dev2/drivers/net/iseries_veth.c =================================================================== --- veth-dev2.orig/drivers/net/iseries_veth.c +++ veth-dev2/drivers/net/iseries_veth.c @@ -830,49 +830,6 @@ static struct ethtool_ops ops = { .get_link = veth_get_link, }; -static void veth_tx_timeout(struct net_device *dev) -{ - struct veth_port *port = (struct veth_port *)dev->priv; - struct net_device_stats *stats = &port->stats; - unsigned long flags; - int i; - - stats->tx_errors++; - - spin_lock_irqsave(&port->pending_gate, flags); - - if (!port->pending_lpmask) { - spin_unlock_irqrestore(&port->pending_gate, flags); - return; - } - - printk(KERN_WARNING "%s: Tx timeout! Resetting lp connections: %08x\n", - dev->name, port->pending_lpmask); - - for (i = 0; i < HVMAXARCHITECTEDLPS; i++) { - struct veth_lpar_connection *cnx = veth_cnx[i]; - - if (! (port->pending_lpmask & (1<lock); - cnx->state |= VETH_STATE_RESET; - veth_kick_statemachine(cnx); - spin_unlock(&cnx->lock); - } - - spin_unlock_irqrestore(&port->pending_gate, flags); -} - static struct net_device * __init veth_probe_one(int vlan, struct device *vdev) { struct net_device *dev; @@ -921,9 +878,6 @@ static struct net_device * __init veth_p dev->set_multicast_list = veth_set_multicast_list; SET_ETHTOOL_OPS(dev, &ops); - dev->watchdog_timeo = 2 * (VETH_ACKTIMEOUT * HZ / 1000000); - dev->tx_timeout = veth_tx_timeout; - SET_NETDEV_DEV(dev, vdev); rc = register_netdev(dev); @@ -1058,8 +1012,6 @@ static int veth_start_xmit(struct sk_buf lpmask = veth_transmit_to_many(skb, lpmask, dev); - dev->trans_start = jiffies; - if (! lpmask) { dev_kfree_skb(skb); } else { From michael at ellerman.id.au Thu Sep 1 11:29:17 2005 From: michael at ellerman.id.au (Michael Ellerman) Date: Thu, 1 Sep 2005 11:29:17 +1000 (EST) Subject: [PATCH 11/18] iseries_veth: Add a per-connection ack timer In-Reply-To: <1125538127.859382.875909607846.qpush@concordia> Message-ID: <20050901012917.18BA6681F5@ozlabs.org> Currently the iseries_veth driver contravenes the specification in Documentation/networking/driver.txt, in that if packets are not acked by the other LPAR they will sit around forever. This patch adds a per-connection timer which fires if we've had no acks for five seconds. This is superior to the generic TX timer because it catches the case of a small number of packets being sent and never acked. This fixes a bug we were seeing on real systems, where some IPv6 neighbour discovery packets would not be acked and then prevent the module from being removed, due to skbs lying around. Signed-off-by: Michael Ellerman --- drivers/net/iseries_veth.c | 75 +++++++++++++++++++++++++++++++++++++++++---- 1 files changed, 69 insertions(+), 6 deletions(-) Index: veth-dev2/drivers/net/iseries_veth.c =================================================================== --- veth-dev2.orig/drivers/net/iseries_veth.c +++ veth-dev2/drivers/net/iseries_veth.c @@ -132,6 +132,11 @@ struct veth_lpar_connection { struct kobject kobject; struct timer_list ack_timer; + struct timer_list reset_timer; + unsigned int reset_timeout; + unsigned long last_contact; + int outstanding_tx; + spinlock_t lock; unsigned long state; HvLpInstanceId src_inst; @@ -171,8 +176,9 @@ static int veth_start_xmit(struct sk_buf static void veth_recycle_msg(struct veth_lpar_connection *, struct veth_msg *); static void veth_flush_pending(struct veth_lpar_connection *cnx); static void veth_receive(struct veth_lpar_connection *, struct VethLpEvent *); -static void veth_timed_ack(unsigned long connectionPtr); static void veth_release_connection(struct kobject *kobject); +static void veth_timed_ack(unsigned long ptr); +static void veth_timed_reset(unsigned long ptr); static struct kobj_type veth_lpar_connection_ktype = { .release = veth_release_connection @@ -360,7 +366,7 @@ static void veth_handle_int(struct VethL HvLpIndex rlp = event->base_event.xSourceLp; struct veth_lpar_connection *cnx = veth_cnx[rlp]; unsigned long flags; - int i; + int i, acked = 0; BUG_ON(! cnx); @@ -374,13 +380,22 @@ static void veth_handle_int(struct VethL break; case VethEventTypeFramesAck: spin_lock_irqsave(&cnx->lock, flags); + for (i = 0; i < VETH_MAX_ACKS_PER_MSG; ++i) { u16 msgnum = event->u.frames_ack_data.token[i]; - if (msgnum < VETH_NUMBUFFERS) + if (msgnum < VETH_NUMBUFFERS) { veth_recycle_msg(cnx, cnx->msgs + msgnum); + cnx->outstanding_tx--; + acked++; + } } + + if (acked > 0) + cnx->last_contact = jiffies; + spin_unlock_irqrestore(&cnx->lock, flags); + veth_flush_pending(cnx); break; case VethEventTypeFrames: @@ -454,8 +469,6 @@ static void veth_statemachine(void *p) restart: if (cnx->state & VETH_STATE_RESET) { - int i; - if (cnx->state & VETH_STATE_OPEN) HvCallEvent_closeLpEventPath(cnx->remote_lp, HvLpEvent_Type_VirtualLan); @@ -474,15 +487,20 @@ static void veth_statemachine(void *p) | VETH_STATE_SENTCAPACK | VETH_STATE_READY); /* Clean up any leftover messages */ - if (cnx->msgs) + if (cnx->msgs) { + int i; for (i = 0; i < VETH_NUMBUFFERS; ++i) veth_recycle_msg(cnx, cnx->msgs + i); + } + cnx->outstanding_tx = 0; /* Drop the lock so we can do stuff that might sleep or * take other locks. */ spin_unlock_irq(&cnx->lock); del_timer_sync(&cnx->ack_timer); + del_timer_sync(&cnx->reset_timer); + veth_flush_pending(cnx); spin_lock_irq(&cnx->lock); @@ -631,9 +649,16 @@ static int veth_init_connection(u8 rlp) cnx->remote_lp = rlp; spin_lock_init(&cnx->lock); INIT_WORK(&cnx->statemachine_wq, veth_statemachine, cnx); + init_timer(&cnx->ack_timer); cnx->ack_timer.function = veth_timed_ack; cnx->ack_timer.data = (unsigned long) cnx; + + init_timer(&cnx->reset_timer); + cnx->reset_timer.function = veth_timed_reset; + cnx->reset_timer.data = (unsigned long) cnx; + cnx->reset_timeout = 5 * HZ * (VETH_ACKTIMEOUT / 1000000); + memset(&cnx->pending_acks, 0xff, sizeof (cnx->pending_acks)); veth_cnx[rlp] = cnx; @@ -948,6 +973,13 @@ static int veth_transmit_to_one(struct s if (rc != HvLpEvent_Rc_Good) goto recycle_and_drop; + /* If the timer's not already running, start it now. */ + if (0 == cnx->outstanding_tx) + mod_timer(&cnx->reset_timer, jiffies + cnx->reset_timeout); + + cnx->last_contact = jiffies; + cnx->outstanding_tx++; + spin_unlock_irqrestore(&cnx->lock, flags); return 0; @@ -1093,6 +1125,37 @@ static void veth_flush_pending(struct ve } } +static void veth_timed_reset(unsigned long ptr) +{ + struct veth_lpar_connection *cnx = (struct veth_lpar_connection *)ptr; + unsigned long trigger_time, flags; + + /* FIXME is it possible this fires after veth_stop_connection()? + * That would reschedule the statemachine for 5 seconds and probably + * execute it after the module's been unloaded. Hmm. */ + + spin_lock_irqsave(&cnx->lock, flags); + + if (cnx->outstanding_tx > 0) { + trigger_time = cnx->last_contact + cnx->reset_timeout; + + if (trigger_time < jiffies) { + cnx->state |= VETH_STATE_RESET; + veth_kick_statemachine(cnx); + veth_error("%d packets not acked by LPAR %d within %d " + "seconds, resetting.\n", + cnx->outstanding_tx, cnx->remote_lp, + cnx->reset_timeout / HZ); + } else { + /* Reschedule the timer */ + trigger_time = jiffies + cnx->reset_timeout; + mod_timer(&cnx->reset_timer, trigger_time); + } + } + + spin_unlock_irqrestore(&cnx->lock, flags); +} + /* * Rx path */ From michael at ellerman.id.au Thu Sep 1 11:29:18 2005 From: michael at ellerman.id.au (Michael Ellerman) Date: Thu, 1 Sep 2005 11:29:18 +1000 (EST) Subject: [PATCH 12/18] iseries_veth: Simplify full-queue handling In-Reply-To: <1125538127.859382.875909607846.qpush@concordia> Message-ID: <20050901012918.2C8EA68224@ozlabs.org> The iseries_veth driver often has multiple netdevices sending packets over a single connection to another LPAR. If the bandwidth to the other LPAR is exceeded, all the netdevices must have their queues stopped. The current code achieves this by queueing one incoming skb on the per-netdevice port structure. When the connection is able to send more packets we iterate through the port structs and flush any packet that is queued, as well as restarting the associated netdevice's queue. This arrangement makes less sense now that we have per-connection TX timers, rather than the per-netdevice generic TX timer. The new code simply detects when one of the connections is full, and stops the queue of all associated netdevices. Then when a packet is acked on that connection (ie. there is space again) all the queues are woken up. Signed-off-by: Michael Ellerman --- drivers/net/iseries_veth.c | 108 ++++++++++++++++++++++++++------------------- 1 files changed, 64 insertions(+), 44 deletions(-) Index: veth-dev2/drivers/net/iseries_veth.c =================================================================== --- veth-dev2.orig/drivers/net/iseries_veth.c +++ veth-dev2/drivers/net/iseries_veth.c @@ -158,10 +158,11 @@ struct veth_port { u64 mac_addr; HvLpIndexMap lpar_map; - spinlock_t pending_gate; - struct sk_buff *pending_skb; - HvLpIndexMap pending_lpmask; + /* queue_lock protects the stopped_map and dev's queue. */ + spinlock_t queue_lock; + HvLpIndexMap stopped_map; + /* mcast_gate protects promiscuous, num_mcast & mcast_addr. */ rwlock_t mcast_gate; int promiscuous; int num_mcast; @@ -174,7 +175,8 @@ static struct net_device *veth_dev[HVMAX static int veth_start_xmit(struct sk_buff *skb, struct net_device *dev); static void veth_recycle_msg(struct veth_lpar_connection *, struct veth_msg *); -static void veth_flush_pending(struct veth_lpar_connection *cnx); +static void veth_wake_queues(struct veth_lpar_connection *cnx); +static void veth_stop_queues(struct veth_lpar_connection *cnx); static void veth_receive(struct veth_lpar_connection *, struct VethLpEvent *); static void veth_release_connection(struct kobject *kobject); static void veth_timed_ack(unsigned long ptr); @@ -221,6 +223,12 @@ static inline struct veth_msg *veth_stac return msg; } +/* You must hold the connection's lock when you call this function. */ +static inline int veth_stack_is_empty(struct veth_lpar_connection *cnx) +{ + return cnx->msg_stack_head == NULL; +} + static inline HvLpEvent_Rc veth_signalevent(struct veth_lpar_connection *cnx, u16 subtype, HvLpEvent_AckInd ackind, HvLpEvent_AckType acktype, @@ -391,12 +399,12 @@ static void veth_handle_int(struct VethL } } - if (acked > 0) + if (acked > 0) { cnx->last_contact = jiffies; + veth_wake_queues(cnx); + } spin_unlock_irqrestore(&cnx->lock, flags); - - veth_flush_pending(cnx); break; case VethEventTypeFrames: veth_receive(cnx, event); @@ -492,7 +500,9 @@ static void veth_statemachine(void *p) for (i = 0; i < VETH_NUMBUFFERS; ++i) veth_recycle_msg(cnx, cnx->msgs + i); } + cnx->outstanding_tx = 0; + veth_wake_queues(cnx); /* Drop the lock so we can do stuff that might sleep or * take other locks. */ @@ -501,8 +511,6 @@ static void veth_statemachine(void *p) del_timer_sync(&cnx->ack_timer); del_timer_sync(&cnx->reset_timer); - veth_flush_pending(cnx); - spin_lock_irq(&cnx->lock); if (cnx->state & VETH_STATE_RESET) @@ -869,8 +877,9 @@ static struct net_device * __init veth_p port = (struct veth_port *) dev->priv; - spin_lock_init(&port->pending_gate); + spin_lock_init(&port->queue_lock); rwlock_init(&port->mcast_gate); + port->stopped_map = 0; for (i = 0; i < HVMAXARCHITECTEDLPS; i++) { HvLpVirtualLanIndexMap map; @@ -980,6 +989,9 @@ static int veth_transmit_to_one(struct s cnx->last_contact = jiffies; cnx->outstanding_tx++; + if (veth_stack_is_empty(cnx)) + veth_stop_queues(cnx); + spin_unlock_irqrestore(&cnx->lock, flags); return 0; @@ -1023,7 +1035,6 @@ static int veth_start_xmit(struct sk_buf { unsigned char *frame = skb->data; struct veth_port *port = (struct veth_port *) dev->priv; - unsigned long flags; HvLpIndexMap lpmask; if (! (frame[0] & 0x01)) { @@ -1040,27 +1051,9 @@ static int veth_start_xmit(struct sk_buf lpmask = port->lpar_map; } - spin_lock_irqsave(&port->pending_gate, flags); - - lpmask = veth_transmit_to_many(skb, lpmask, dev); + veth_transmit_to_many(skb, lpmask, dev); - if (! lpmask) { - dev_kfree_skb(skb); - } else { - if (port->pending_skb) { - veth_error("%s: TX while skb was pending!\n", - dev->name); - dev_kfree_skb(skb); - spin_unlock_irqrestore(&port->pending_gate, flags); - return 1; - } - - port->pending_skb = skb; - port->pending_lpmask = lpmask; - netif_stop_queue(dev); - } - - spin_unlock_irqrestore(&port->pending_gate, flags); + dev_kfree_skb(skb); return 0; } @@ -1093,9 +1086,10 @@ static void veth_recycle_msg(struct veth } } -static void veth_flush_pending(struct veth_lpar_connection *cnx) +static void veth_wake_queues(struct veth_lpar_connection *cnx) { int i; + for (i = 0; i < HVMAXARCHITECTEDVIRTUALLANS; i++) { struct net_device *dev = veth_dev[i]; struct veth_port *port; @@ -1109,19 +1103,45 @@ static void veth_flush_pending(struct ve if (! (port->lpar_map & (1<remote_lp))) continue; - spin_lock_irqsave(&port->pending_gate, flags); - if (port->pending_skb) { - port->pending_lpmask = - veth_transmit_to_many(port->pending_skb, - port->pending_lpmask, - dev); - if (! port->pending_lpmask) { - dev_kfree_skb_any(port->pending_skb); - port->pending_skb = NULL; - netif_wake_queue(dev); - } + spin_lock_irqsave(&port->queue_lock, flags); + + port->stopped_map &= ~(1 << cnx->remote_lp); + + if (0 == port->stopped_map && netif_queue_stopped(dev)) { + veth_debug("cnx %d: woke queue for %s.\n", + cnx->remote_lp, dev->name); + netif_wake_queue(dev); } - spin_unlock_irqrestore(&port->pending_gate, flags); + spin_unlock_irqrestore(&port->queue_lock, flags); + } +} + +static void veth_stop_queues(struct veth_lpar_connection *cnx) +{ + int i; + + for (i = 0; i < HVMAXARCHITECTEDVIRTUALLANS; i++) { + struct net_device *dev = veth_dev[i]; + struct veth_port *port; + + if (! dev) + continue; + + port = (struct veth_port *)dev->priv; + + /* If this cnx is not on the vlan for this port, continue */ + if (! (port->lpar_map & (1 << cnx->remote_lp))) + continue; + + spin_lock(&port->queue_lock); + + netif_stop_queue(dev); + port->stopped_map |= (1 << cnx->remote_lp); + + veth_debug("cnx %d: stopped queue for %s, map = 0x%x.\n", + cnx->remote_lp, dev->name, port->stopped_map); + + spin_unlock(&port->queue_lock); } } From michael at ellerman.id.au Thu Sep 1 11:29:19 2005 From: michael at ellerman.id.au (Michael Ellerman) Date: Thu, 1 Sep 2005 11:29:19 +1000 (EST) Subject: [PATCH 13/18] iseries_veth: Fix bogus counting of TX errors In-Reply-To: <1125538127.859382.875909607846.qpush@concordia> Message-ID: <20050901012919.7A19868232@ozlabs.org> There's a number of problems with the way iseries_veth counts TX errors. Firstly it counts conditions which aren't really errors as TX errors. This includes if we don't have a connection struct for the other LPAR, or if the other LPAR is currently down (or just doesn't want to talk to us). Neither of these should count as TX errors. Secondly, it counts one TX error for each LPAR that fails to accept the packet. This can lead to TX error counts higher than the total number of packets sent through the interface. This is confusing for users. This patch fixes that behaviour. The non-error conditions are no longer counted, and we introduce a new and I think saner meaning to the TX counts. If a packet is successfully transmitted to any LPAR then it is transmitted and tx_packets is incremented by 1. If there is an error transmitting a packet to any LPAR then that is counted as one error, ie. tx_errors is incremented by 1. Signed-off-by: Michael Ellerman --- drivers/net/iseries_veth.c | 47 ++++++++++++++++++--------------------------- 1 files changed, 19 insertions(+), 28 deletions(-) Index: veth-dev2/drivers/net/iseries_veth.c =================================================================== --- veth-dev2.orig/drivers/net/iseries_veth.c +++ veth-dev2/drivers/net/iseries_veth.c @@ -938,31 +938,25 @@ static int veth_transmit_to_one(struct s struct veth_port *port = (struct veth_port *) dev->priv; HvLpEvent_Rc rc; struct veth_msg *msg = NULL; - int err = 0; unsigned long flags; - if (! cnx) { - port->stats.tx_errors++; - dev_kfree_skb(skb); + if (! cnx) return 0; - } spin_lock_irqsave(&cnx->lock, flags); if (! (cnx->state & VETH_STATE_READY)) - goto drop; + goto no_error; - if ((skb->len - 14) > VETH_MAX_MTU) + if ((skb->len - ETH_HLEN) > VETH_MAX_MTU) goto drop; msg = veth_stack_pop(cnx); - - if (! msg) { - err = 1; + if (! msg) goto drop; - } msg->in_use = 1; + msg->skb = skb_get(skb); msg->data.addr[0] = dma_map_single(port->dev, skb->data, skb->len, DMA_TO_DEVICE); @@ -970,9 +964,6 @@ static int veth_transmit_to_one(struct s if (dma_mapping_error(msg->data.addr[0])) goto recycle_and_drop; - /* Is it really necessary to check the length and address - * fields of the first entry here? */ - msg->skb = skb; msg->dev = port->dev; msg->data.len[0] = skb->len; msg->data.eofmask = 1 << VETH_EOF_SHIFT; @@ -992,43 +983,43 @@ static int veth_transmit_to_one(struct s if (veth_stack_is_empty(cnx)) veth_stop_queues(cnx); + no_error: spin_unlock_irqrestore(&cnx->lock, flags); return 0; recycle_and_drop: - /* we free the skb below, so tell veth_recycle_msg() not to. */ - msg->skb = NULL; veth_recycle_msg(cnx, msg); drop: - port->stats.tx_errors++; - dev_kfree_skb(skb); spin_unlock_irqrestore(&cnx->lock, flags); - return err; + return 1; } -static HvLpIndexMap veth_transmit_to_many(struct sk_buff *skb, +static void veth_transmit_to_many(struct sk_buff *skb, HvLpIndexMap lpmask, struct net_device *dev) { struct veth_port *port = (struct veth_port *) dev->priv; - int i; - int rc; + int i, success, error; + + success = error = 0; for (i = 0; i < HVMAXARCHITECTEDLPS; i++) { if ((lpmask & (1 << i)) == 0) continue; - rc = veth_transmit_to_one(skb_get(skb), i, dev); - if (! rc) - lpmask &= ~(1<stats.tx_errors++; + + if (success) { port->stats.tx_packets++; port->stats.tx_bytes += skb->len; } - - return lpmask; } static int veth_start_xmit(struct sk_buff *skb, struct net_device *dev) From michael at ellerman.id.au Thu Sep 1 11:29:20 2005 From: michael at ellerman.id.au (Michael Ellerman) Date: Thu, 1 Sep 2005 11:29:20 +1000 (EST) Subject: [PATCH 14/18] iseries_veth: Add sysfs support for connection structs In-Reply-To: <1125538127.859382.875909607846.qpush@concordia> Message-ID: <20050901012920.5D74D68231@ozlabs.org> To aid in field debugging, add sysfs support for iseries_veth's connection structures. At the moment this is all read-only, however we could think about adding write support for some attributes in future. Signed-off-by: Michael Ellerman --- drivers/net/iseries_veth.c | 94 +++++++++++++++++++++++++++++++++++++++++++-- 1 files changed, 90 insertions(+), 4 deletions(-) Index: veth-dev2/drivers/net/iseries_veth.c =================================================================== --- veth-dev2.orig/drivers/net/iseries_veth.c +++ veth-dev2/drivers/net/iseries_veth.c @@ -182,10 +182,6 @@ static void veth_release_connection(stru static void veth_timed_ack(unsigned long ptr); static void veth_timed_reset(unsigned long ptr); -static struct kobj_type veth_lpar_connection_ktype = { - .release = veth_release_connection -}; - /* * Utility functions */ @@ -280,6 +276,81 @@ static int veth_allocate_events(HvLpInde } /* + * sysfs support + */ + +struct veth_cnx_attribute { + struct attribute attr; + ssize_t (*show)(struct veth_lpar_connection *, char *buf); + ssize_t (*store)(struct veth_lpar_connection *, const char *buf); +}; + +static ssize_t veth_cnx_attribute_show(struct kobject *kobj, + struct attribute *attr, char *buf) +{ + struct veth_cnx_attribute *cnx_attr; + struct veth_lpar_connection *cnx; + + cnx_attr = container_of(attr, struct veth_cnx_attribute, attr); + cnx = container_of(kobj, struct veth_lpar_connection, kobject); + + if (!cnx_attr->show) + return -EIO; + + return cnx_attr->show(cnx, buf); +} + +#define CUSTOM_CNX_ATTR(_name, _format, _expression) \ +static ssize_t _name##_show(struct veth_lpar_connection *cnx, char *buf)\ +{ \ + return sprintf(buf, _format, _expression); \ +} \ +struct veth_cnx_attribute veth_cnx_attr_##_name = __ATTR_RO(_name) + +#define SIMPLE_CNX_ATTR(_name) \ + CUSTOM_CNX_ATTR(_name, "%lu\n", (unsigned long)cnx->_name) + +SIMPLE_CNX_ATTR(outstanding_tx); +SIMPLE_CNX_ATTR(remote_lp); +SIMPLE_CNX_ATTR(num_events); +SIMPLE_CNX_ATTR(src_inst); +SIMPLE_CNX_ATTR(dst_inst); +SIMPLE_CNX_ATTR(num_pending_acks); +SIMPLE_CNX_ATTR(num_ack_events); +CUSTOM_CNX_ATTR(ack_timeout, "%d\n", jiffies_to_msecs(cnx->ack_timeout)); +CUSTOM_CNX_ATTR(reset_timeout, "%d\n", jiffies_to_msecs(cnx->reset_timeout)); +CUSTOM_CNX_ATTR(state, "0x%.4lX\n", cnx->state); +CUSTOM_CNX_ATTR(last_contact, "%d\n", cnx->last_contact ? + jiffies_to_msecs(jiffies - cnx->last_contact) : 0); + +#define GET_CNX_ATTR(_name) (&veth_cnx_attr_##_name.attr) + +static struct attribute *veth_cnx_default_attrs[] = { + GET_CNX_ATTR(outstanding_tx), + GET_CNX_ATTR(remote_lp), + GET_CNX_ATTR(num_events), + GET_CNX_ATTR(reset_timeout), + GET_CNX_ATTR(last_contact), + GET_CNX_ATTR(state), + GET_CNX_ATTR(src_inst), + GET_CNX_ATTR(dst_inst), + GET_CNX_ATTR(num_pending_acks), + GET_CNX_ATTR(num_ack_events), + GET_CNX_ATTR(ack_timeout), + NULL +}; + +static struct sysfs_ops veth_cnx_sysfs_ops = { + .show = veth_cnx_attribute_show +}; + +static struct kobj_type veth_lpar_connection_ktype = { + .release = veth_release_connection, + .sysfs_ops = &veth_cnx_sysfs_ops, + .default_attrs = veth_cnx_default_attrs +}; + +/* * LPAR connection code */ @@ -1493,6 +1564,8 @@ void __exit veth_module_cleanup(void) if (!cnx) continue; + /* Remove the connection from sysfs */ + kobject_del(&cnx->kobject); /* Drop the driver's reference to the connection */ kobject_put(&cnx->kobject); } @@ -1523,6 +1596,19 @@ int __init veth_module_init(void) if (rc != 0) goto error; + for (i = 0; i < HVMAXARCHITECTEDLPS; ++i) { + struct kobject *kobj; + + if (!veth_cnx[i]) + continue; + + kobj = &veth_cnx[i]->kobject; + kobj->parent = &veth_driver.driver.kobj; + /* If the add failes, complain but otherwise continue */ + if (0 != kobject_add(kobj)) + veth_error("cnx %d: Failed adding to sysfs.\n", i); + } + return 0; error: From michael at ellerman.id.au Thu Sep 1 11:29:21 2005 From: michael at ellerman.id.au (Michael Ellerman) Date: Thu, 1 Sep 2005 11:29:21 +1000 (EST) Subject: [PATCH 15/18] iseries_veth: Add sysfs support for port structs In-Reply-To: <1125538127.859382.875909607846.qpush@concordia> Message-ID: <20050901012921.7BA6B68235@ozlabs.org> Also to aid debugging, add sysfs support for iseries_veth's port structures. Signed-off-by: Michael Ellerman --- drivers/net/iseries_veth.c | 67 +++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 67 insertions(+) Index: veth-dev2/drivers/net/iseries_veth.c =================================================================== --- veth-dev2.orig/drivers/net/iseries_veth.c +++ veth-dev2/drivers/net/iseries_veth.c @@ -167,6 +167,8 @@ struct veth_port { int promiscuous; int num_mcast; u64 mcast_addr[VETH_MAX_MCAST]; + + struct kobject kobject; }; static HvLpIndex this_lp; @@ -350,6 +352,62 @@ static struct kobj_type veth_lpar_connec .default_attrs = veth_cnx_default_attrs }; +struct veth_port_attribute { + struct attribute attr; + ssize_t (*show)(struct veth_port *, char *buf); + ssize_t (*store)(struct veth_port *, const char *buf); +}; + +static ssize_t veth_port_attribute_show(struct kobject *kobj, + struct attribute *attr, char *buf) +{ + struct veth_port_attribute *port_attr; + struct veth_port *port; + + port_attr = container_of(attr, struct veth_port_attribute, attr); + port = container_of(kobj, struct veth_port, kobject); + + if (!port_attr->show) + return -EIO; + + return port_attr->show(port, buf); +} + +#define CUSTOM_PORT_ATTR(_name, _format, _expression) \ +static ssize_t _name##_show(struct veth_port *port, char *buf) \ +{ \ + return sprintf(buf, _format, _expression); \ +} \ +struct veth_port_attribute veth_port_attr_##_name = __ATTR_RO(_name) + +#define SIMPLE_PORT_ATTR(_name) \ + CUSTOM_PORT_ATTR(_name, "%lu\n", (unsigned long)port->_name) + +SIMPLE_PORT_ATTR(promiscuous); +SIMPLE_PORT_ATTR(num_mcast); +CUSTOM_PORT_ATTR(lpar_map, "0x%X\n", port->lpar_map); +CUSTOM_PORT_ATTR(stopped_map, "0x%X\n", port->stopped_map); +CUSTOM_PORT_ATTR(mac_addr, "0x%lX\n", port->mac_addr); + +#define GET_PORT_ATTR(_name) (&veth_port_attr_##_name.attr) +static struct attribute *veth_port_default_attrs[] = { + GET_PORT_ATTR(mac_addr), + GET_PORT_ATTR(lpar_map), + GET_PORT_ATTR(stopped_map), + GET_PORT_ATTR(promiscuous), + GET_PORT_ATTR(num_mcast), + NULL +}; + +static struct sysfs_ops veth_port_sysfs_ops = { + .show = veth_port_attribute_show +}; + +static struct kobj_type veth_port_ktype = { + .sysfs_ops = &veth_port_sysfs_ops, + .default_attrs = veth_port_default_attrs +}; + /* * LPAR connection code */ @@ -992,6 +1050,13 @@ static struct net_device * __init veth_p return NULL; } + kobject_init(&port->kobject); + port->kobject.parent = &dev->class_dev.kobj; + port->kobject.ktype = &veth_port_ktype; + kobject_set_name(&port->kobject, "veth_port"); + if (0 != kobject_add(&port->kobject)) + veth_error("Failed adding port for %s to sysfs.\n", dev->name); + veth_info("%s attached to iSeries vlan %d (LPAR map = 0x%.4X)\n", dev->name, vlan, port->lpar_map); @@ -1486,6 +1551,8 @@ static int veth_remove(struct vio_dev *v } veth_dev[vdev->unit_address] = NULL; + kobject_del(&port->kobject); + kobject_put(&port->kobject); unregister_netdev(dev); free_netdev(dev); From michael at ellerman.id.au Thu Sep 1 11:29:25 2005 From: michael at ellerman.id.au (Michael Ellerman) Date: Thu, 1 Sep 2005 11:29:25 +1000 (EST) Subject: [PATCH 16/18] iseries_veth: Incorporate iseries_veth.h in iseries_veth.c In-Reply-To: <1125538127.859382.875909607846.qpush@concordia> Message-ID: <20050901012925.4CAC368247@ozlabs.org> iseries_veth.h is only used by iseries_veth.c, so merge the former into the latter. Signed-off-by: Michael Ellerman --- drivers/net/iseries_veth.h | 46 --------------------------------------------- drivers/net/iseries_veth.c | 42 +++++++++++++++++++++++++++++++++++++++-- 2 files changed, 40 insertions(+), 48 deletions(-) Index: veth-dev2/drivers/net/iseries_veth.c =================================================================== --- veth-dev2.orig/drivers/net/iseries_veth.c +++ veth-dev2/drivers/net/iseries_veth.c @@ -81,12 +81,50 @@ #undef DEBUG -#include "iseries_veth.h" - MODULE_AUTHOR("Kyle Lucke "); MODULE_DESCRIPTION("iSeries Virtual ethernet driver"); MODULE_LICENSE("GPL"); +#define VethEventTypeCap (0) +#define VethEventTypeFrames (1) +#define VethEventTypeMonitor (2) +#define VethEventTypeFramesAck (3) + +#define VETH_MAX_ACKS_PER_MSG (20) +#define VETH_MAX_FRAMES_PER_MSG (6) + +struct VethFramesData { + u32 addr[VETH_MAX_FRAMES_PER_MSG]; + u16 len[VETH_MAX_FRAMES_PER_MSG]; + u32 eofmask; +}; +#define VETH_EOF_SHIFT (32-VETH_MAX_FRAMES_PER_MSG) + +struct VethFramesAckData { + u16 token[VETH_MAX_ACKS_PER_MSG]; +}; + +struct VethCapData { + u8 caps_version; + u8 rsvd1; + u16 num_buffers; + u16 ack_threshold; + u16 rsvd2; + u32 ack_timeout; + u32 rsvd3; + u64 rsvd4[3]; +}; + +struct VethLpEvent { + struct HvLpEvent base_event; + union { + struct VethCapData caps_data; + struct VethFramesData frames_data; + struct VethFramesAckData frames_ack_data; + } u; + +}; + #define VETH_NUMBUFFERS (120) #define VETH_ACKTIMEOUT (1000000) /* microseconds */ #define VETH_MAX_MCAST (12) Index: veth-dev2/drivers/net/iseries_veth.h =================================================================== --- veth-dev2.orig/drivers/net/iseries_veth.h +++ /dev/null @@ -1,46 +0,0 @@ -/* File veth.h created by Kyle A. Lucke on Mon Aug 7 2000. */ - -#ifndef _ISERIES_VETH_H -#define _ISERIES_VETH_H - -#define VethEventTypeCap (0) -#define VethEventTypeFrames (1) -#define VethEventTypeMonitor (2) -#define VethEventTypeFramesAck (3) - -#define VETH_MAX_ACKS_PER_MSG (20) -#define VETH_MAX_FRAMES_PER_MSG (6) - -struct VethFramesData { - u32 addr[VETH_MAX_FRAMES_PER_MSG]; - u16 len[VETH_MAX_FRAMES_PER_MSG]; - u32 eofmask; -}; -#define VETH_EOF_SHIFT (32-VETH_MAX_FRAMES_PER_MSG) - -struct VethFramesAckData { - u16 token[VETH_MAX_ACKS_PER_MSG]; -}; - -struct VethCapData { - u8 caps_version; - u8 rsvd1; - u16 num_buffers; - u16 ack_threshold; - u16 rsvd2; - u32 ack_timeout; - u32 rsvd3; - u64 rsvd4[3]; -}; - -struct VethLpEvent { - struct HvLpEvent base_event; - union { - struct VethCapData caps_data; - struct VethFramesData frames_data; - struct VethFramesAckData frames_ack_data; - } u; - -}; - -#endif /* _ISERIES_VETH_H */ From michael at ellerman.id.au Thu Sep 1 11:29:27 2005 From: michael at ellerman.id.au (Michael Ellerman) Date: Thu, 1 Sep 2005 11:29:27 +1000 (EST) Subject: [PATCH 17/18] iseries_veth: Remove studly caps from iseries_veth.c In-Reply-To: <1125538127.859382.875909607846.qpush@concordia> Message-ID: <20050901012927.35CE7681A0@ozlabs.org> Having merged iseries_veth.h, let's remove some of the studly caps that came with it. Signed-off-by: Michael Ellerman --- drivers/net/iseries_veth.c | 74 ++++++++++++++++++++++----------------------- 1 files changed, 37 insertions(+), 37 deletions(-) Index: veth-dev2/drivers/net/iseries_veth.c =================================================================== --- veth-dev2.orig/drivers/net/iseries_veth.c +++ veth-dev2/drivers/net/iseries_veth.c @@ -85,26 +85,26 @@ MODULE_AUTHOR("Kyle Lucke lock, flags); } -static void veth_handle_ack(struct VethLpEvent *event) +static void veth_handle_ack(struct veth_lpevent *event) { HvLpIndex rlp = event->base_event.xTargetLp; struct veth_lpar_connection *cnx = veth_cnx[rlp]; @@ -524,10 +524,10 @@ static void veth_handle_ack(struct VethL BUG_ON(! cnx); switch (event->base_event.xSubtype) { - case VethEventTypeCap: + case VETH_EVENT_CAP: veth_take_cap_ack(cnx, event); break; - case VethEventTypeMonitor: + case VETH_EVENT_MONITOR: veth_take_monitor_ack(cnx, event); break; default: @@ -536,7 +536,7 @@ static void veth_handle_ack(struct VethL }; } -static void veth_handle_int(struct VethLpEvent *event) +static void veth_handle_int(struct veth_lpevent *event) { HvLpIndex rlp = event->base_event.xSourceLp; struct veth_lpar_connection *cnx = veth_cnx[rlp]; @@ -546,14 +546,14 @@ static void veth_handle_int(struct VethL BUG_ON(! cnx); switch (event->base_event.xSubtype) { - case VethEventTypeCap: + case VETH_EVENT_CAP: veth_take_cap(cnx, event); break; - case VethEventTypeMonitor: + case VETH_EVENT_MONITOR: /* do nothing... this'll hang out here til we're dead, * and the hypervisor will return it for us. */ break; - case VethEventTypeFramesAck: + case VETH_EVENT_FRAMES_ACK: spin_lock_irqsave(&cnx->lock, flags); for (i = 0; i < VETH_MAX_ACKS_PER_MSG; ++i) { @@ -573,7 +573,7 @@ static void veth_handle_int(struct VethL spin_unlock_irqrestore(&cnx->lock, flags); break; - case VethEventTypeFrames: + case VETH_EVENT_FRAMES: veth_receive(cnx, event); break; default: @@ -584,7 +584,7 @@ static void veth_handle_int(struct VethL static void veth_handle_event(struct HvLpEvent *event, struct pt_regs *regs) { - struct VethLpEvent *veth_event = (struct VethLpEvent *)event; + struct veth_lpevent *veth_event = (struct veth_lpevent *)event; if (event->xFlags.xFunction == HvLpEvent_Function_Ack) veth_handle_ack(veth_event); @@ -594,7 +594,7 @@ static void veth_handle_event(struct HvL static int veth_process_caps(struct veth_lpar_connection *cnx) { - struct VethCapData *remote_caps = &cnx->remote_caps; + struct veth_cap_data *remote_caps = &cnx->remote_caps; int num_acks_needed; /* Convert timer to jiffies */ @@ -710,7 +710,7 @@ static void veth_statemachine(void *p) if ( (cnx->state & VETH_STATE_OPEN) && !(cnx->state & VETH_STATE_SENTMON) ) { - rc = veth_signalevent(cnx, VethEventTypeMonitor, + rc = veth_signalevent(cnx, VETH_EVENT_MONITOR, HvLpEvent_AckInd_DoAck, HvLpEvent_AckType_DeferredAck, 0, 0, 0, 0, 0, 0); @@ -733,7 +733,7 @@ static void veth_statemachine(void *p) && !(cnx->state & VETH_STATE_SENTCAPS)) { u64 *rawcap = (u64 *)&cnx->local_caps; - rc = veth_signalevent(cnx, VethEventTypeCap, + rc = veth_signalevent(cnx, VETH_EVENT_CAP, HvLpEvent_AckInd_DoAck, HvLpEvent_AckType_ImmediateAck, 0, rawcap[0], rawcap[1], rawcap[2], @@ -755,7 +755,7 @@ static void veth_statemachine(void *p) if ((cnx->state & VETH_STATE_GOTCAPS) && !(cnx->state & VETH_STATE_SENTCAPACK)) { - struct VethCapData *remote_caps = &cnx->remote_caps; + struct veth_cap_data *remote_caps = &cnx->remote_caps; memcpy(remote_caps, &cnx->cap_event.u.caps_data, sizeof(*remote_caps)); @@ -1142,7 +1142,7 @@ static int veth_transmit_to_one(struct s msg->data.len[0] = skb->len; msg->data.eofmask = 1 << VETH_EOF_SHIFT; - rc = veth_signaldata(cnx, VethEventTypeFrames, msg->token, &msg->data); + rc = veth_signaldata(cnx, VETH_EVENT_FRAMES, msg->token, &msg->data); if (rc != HvLpEvent_Rc_Good) goto recycle_and_drop; @@ -1409,7 +1409,7 @@ static void veth_flush_acks(struct veth_ { HvLpEvent_Rc rc; - rc = veth_signaldata(cnx, VethEventTypeFramesAck, + rc = veth_signaldata(cnx, VETH_EVENT_FRAMES_ACK, 0, &cnx->pending_acks); if (rc != HvLpEvent_Rc_Good) @@ -1421,9 +1421,9 @@ static void veth_flush_acks(struct veth_ } static void veth_receive(struct veth_lpar_connection *cnx, - struct VethLpEvent *event) + struct veth_lpevent *event) { - struct VethFramesData *senddata = &event->u.frames_data; + struct veth_frames_data *senddata = &event->u.frames_data; int startchunk = 0; int nchunks; unsigned long flags; From michael at ellerman.id.au Thu Sep 1 11:29:29 2005 From: michael at ellerman.id.au (Michael Ellerman) Date: Thu, 1 Sep 2005 11:29:29 +1000 (EST) Subject: [PATCH 18/18] iseries_veth: Be consistent about driver name, increment version In-Reply-To: <1125538127.859382.875909607846.qpush@concordia> Message-ID: <20050901012929.4B45F68249@ozlabs.org> The iseries_veth driver tells sysfs that it's called 'iseries_veth', but if you ask it via ethtool it thinks it's called 'veth'. I think this comes from 2.4 when the driver was called 'veth', but it's definitely called 'iseries_veth' now, so fix it. To make sure we don't do it again define DRV_NAME and use it everywhere. While we're at it, change the version number to 2.0, to reflect the changes made in this patch series. Signed-off-by: Michael Ellerman --- drivers/net/iseries_veth.c | 16 ++++++++++------ 1 files changed, 10 insertions(+), 6 deletions(-) Index: veth-dev2/drivers/net/iseries_veth.c =================================================================== --- veth-dev2.orig/drivers/net/iseries_veth.c +++ veth-dev2/drivers/net/iseries_veth.c @@ -125,6 +125,9 @@ struct veth_lpevent { }; +#define DRV_NAME "iseries_veth" +#define DRV_VERSION "2.0" + #define VETH_NUMBUFFERS (120) #define VETH_ACKTIMEOUT (1000000) /* microseconds */ #define VETH_MAX_MCAST (12) @@ -227,14 +230,14 @@ static void veth_timed_reset(unsigned lo */ #define veth_info(fmt, args...) \ - printk(KERN_INFO "iseries_veth: " fmt, ## args) + printk(KERN_INFO DRV_NAME ": " fmt, ## args) #define veth_error(fmt, args...) \ - printk(KERN_ERR "iseries_veth: Error: " fmt, ## args) + printk(KERN_ERR DRV_NAME ": Error: " fmt, ## args) #ifdef DEBUG #define veth_debug(fmt, args...) \ - printk(KERN_DEBUG "iseries_veth: " fmt, ## args) + printk(KERN_DEBUG DRV_NAME ": " fmt, ## args) #else #define veth_debug(fmt, args...) do {} while (0) #endif @@ -997,9 +1000,10 @@ static void veth_set_multicast_list(stru static void veth_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info) { - strncpy(info->driver, "veth", sizeof(info->driver) - 1); + strncpy(info->driver, DRV_NAME, sizeof(info->driver) - 1); info->driver[sizeof(info->driver) - 1] = '\0'; - strncpy(info->version, "1.0", sizeof(info->version) - 1); + strncpy(info->version, DRV_VERSION, sizeof(info->version) - 1); + info->version[sizeof(info->version) - 1] = '\0'; } static int veth_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd) @@ -1642,7 +1646,7 @@ static struct vio_device_id veth_device_ MODULE_DEVICE_TABLE(vio, veth_device_table); static struct vio_driver veth_driver = { - .name = "iseries_veth", + .name = DRV_NAME, .id_table = veth_device_table, .probe = veth_probe, .remove = veth_remove From service at paypal.com Thu Sep 1 11:33:02 2005 From: service at paypal.com (service at paypal.com) Date: Thu, 1 Sep 2005 09:33:02 +0800 Subject: PayPal Account Security Measures Message-ID: <200509010133.j811X2mX014268@mail.kuantong.com> An HTML attachment was scrubbed... URL: http://ozlabs.org/pipermail/linuxppc64-dev/attachments/20050901/da10b4aa/attachment.htm From jgarzik at pobox.com Thu Sep 1 12:43:58 2005 From: jgarzik at pobox.com (Jeff Garzik) Date: Wed, 31 Aug 2005 22:43:58 -0400 Subject: [PATCH 0/18] Updates & bug fixes for iseries_veth network driver In-Reply-To: <1125538127.859382.875909607846.qpush@concordia> References: <1125538127.859382.875909607846.qpush@concordia> Message-ID: <43166AEE.8090002@pobox.com> applied patches 1-18 From mniyer at us.ibm.com Thu Sep 1 14:22:39 2005 From: mniyer at us.ibm.com (Murali N Iyer) Date: Wed, 31 Aug 2005 23:22:39 -0500 Subject: [PATCH,RFC] Move Cell platform code to arch/powerpc In-Reply-To: <200509010247.07399.arnd@arndb.de> Message-ID: Arnd, Architecture "cell" seems to be fine. What is your thought on supporting multiple different hardware configurations under cell. I think this patch has been tested only in CPBW hardware. For example "+++ linux-cg/arch/ppc64/kernel/bpa_nvram.c" assumes one particular hardware which may not be true for different hardware configurations. Murali Arnd Bergmann Sent by: To linuxppc64-dev-bo linuxppc64-dev at ozlabs.org unces at ozlabs.org cc akpm at osdl.org, Stephen Rothwell , Paul 08/31/2005 07:47 Mackerras , PM linux-kernel Subject [PATCH,RFC] Move Cell platform code to arch/powerpc Move all files from arch/ppc64/kernel/bpa_* to arch/powerpc/platforms/cell, I would like to see a patch like this go into 2.6.14, for multiple reasons: - The marketing folks have changed the names and we are no longer supposed to refer to Cell as 'BPA' or 'Broadband Processor Architecture'. The platform is officially known as 'Cell Broadband Engine Architecture', while the CPU is the 'Cell Broadband Engine'. - We are now moving all platforms into arch/powerpc/platforms and someone has to start so we get a template for the other architectures to follow. - It would be a big mess for me to maintain my own patches on top of file names that are different from mainline during the 2.6.14 freeze. My impression is that Cell is a good target for moving first, because I have to move it anyway and the number of users is extremely low, so it doesn't cause too much harm if we screw up. What thing that makes moving Cell relatively easy is that it only supports 64 bit and only a single hardware configuration so far. I have tested this a bit on Cell and also done compile-only test for the other platforms, but it doesn't really make any changes to the code itself. Please comment on wether this is what everybody like the merge process be like. Signed-off-by: Arnd Bergmann -- arch/powerpc/platforms/cell/Makefile | 1 arch/ppc64/kernel/Makefile | 5 arch/powerpc/platforms/cell/pic.c | 269 ++++++++++++++++++++++ arch/ppc64/kernel/bpa_iic.c | 270 ---------------------- include/asm-powerpc/cell-pic.h | 62 +++++ arch/ppc64/kernel/bpa_iic.h | 62 ----- arch/powerpc/platforms/cell/iommu.c | 377 +++++++++++++++++++++++++++++++ arch/ppc64/kernel/bpa_iommu.c | 377 ------------------------------- arch/powerpc/platforms/cell/iommu.h | 65 +++++ arch/ppc64/kernel/bpa_iommu.h | 65 ----- arch/powerpc/platforms/cell/nvram.c | 118 +++++++++ arch/ppc64/kernel/bpa_nvram.c | 118 --------- arch/powerpc/platforms/cell/setup.c | 138 +++++++++++ arch/ppc64/kernel/bpa_setup.c | 140 ----------- arch/powerpc/platforms/cell/spider-pic.c | 190 +++++++++++++++ arch/ppc64/kernel/spider-pic.c | 191 --------------- arch/ppc64/Kconfig | 10 arch/ppc64/kernel/cpu_setup_power4.S | 2 arch/ppc64/kernel/cputable.c | 6 arch/ppc64/kernel/irq.c | 2 arch/ppc64/kernel/pSeries_smp.c | 4 arch/ppc64/kernel/setup.c | 8 arch/ppc64/kernel/traps.c | 4 include/asm-ppc64/nvram.h | 2 include/asm-ppc64/processor.h | 7 25 files changed, 1248 insertions(+), 1245 deletions(-) --- linux-cg.orig/arch/powerpc/platforms/cell/Makefile 1969-12-31 19:00:00.000000000 -0500 +++ linux-cg/arch/powerpc/platforms/cell/Makefile 2005-09-01 02:37:46.074992344 -0400 @@ -0,0 +1 @@ +obj-y += iommu.o nvram.o setup.o pic.o spider-pic.o --- linux-cg.orig/arch/powerpc/platforms/cell/iommu.c 1969-12-31 19:00:00.000000000 -0500 +++ linux-cg/arch/powerpc/platforms/cell/iommu.c 2005-09-01 02:37:46.076992040 -0400 @@ -0,0 +1,377 @@ +/* + * IOMMU implementation for Cell Broadband Engine + * + * We just establish a linear mapping at boot by setting all the + * IOPT cache entries in the CPU. + * The mapping functions should be identical to pci_direct_iommu, + * except for the handling of the high order bit that is required + * by the Spider bridge. These should be split into a separate + * file at the point where we get a different bridge chip. + * + * Copyright (C) 2005 IBM Deutschland Entwicklung GmbH, + * Arnd Bergmann + * + * Based on linear mapping + * Copyright (C) 2003 Benjamin Herrenschmidt (benh at kernel.crashing.org) + * + * 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. + */ + +#undef DEBUG + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "iommu.h" + +static inline unsigned long +get_iopt_entry(unsigned long real_address, unsigned long ioid, + unsigned long prot) +{ + return (prot & IOPT_PROT_MASK) + | (IOPT_COHERENT) + | (IOPT_ORDER_VC) + | (real_address & IOPT_RPN_MASK) + | (ioid & IOPT_IOID_MASK); +} + +typedef struct { + unsigned long val; +} ioste; + +static inline ioste +mk_ioste(unsigned long val) +{ + ioste ioste = { .val = val, }; + return ioste; +} + +static inline ioste +get_iost_entry(unsigned long iopt_base, unsigned long io_address, unsigned page_size) +{ + unsigned long ps; + unsigned long iostep; + unsigned long nnpt; + unsigned long shift; + + switch (page_size) { + case 0x1000000: + ps = IOST_PS_16M; + nnpt = 0; /* one page per segment */ + shift = 5; /* segment has 16 iopt entries */ + break; + + case 0x100000: + ps = IOST_PS_1M; + nnpt = 0; /* one page per segment */ + shift = 1; /* segment has 256 iopt entries */ + break; + + case 0x10000: + ps = IOST_PS_64K; + nnpt = 0x07; /* 8 pages per io page table */ + shift = 0; /* all entries are used */ + break; + + case 0x1000: + ps = IOST_PS_4K; + nnpt = 0x7f; /* 128 pages per io page table */ + shift = 0; /* all entries are used */ + break; + + default: /* not a known compile time constant */ + BUILD_BUG_ON(1); + break; + } + + iostep = iopt_base + + /* need 8 bytes per iopte */ + (((io_address / page_size * 8) + /* align io page tables on 4k page boundaries */ + << shift) + /* nnpt+1 pages go into each iopt */ + & ~(nnpt << 12)); + + nnpt++; /* this seems to work, but the documentation is not clear + about wether we put nnpt or nnpt-1 into the ioste bits. + In theory, this can't work for 4k pages. */ + return mk_ioste(IOST_VALID_MASK + | (iostep & IOST_PT_BASE_MASK) + | ((nnpt << 5) & IOST_NNPT_MASK) + | (ps & IOST_PS_MASK)); +} + +/* compute the address of an io pte */ +static inline unsigned long +get_ioptep(ioste iost_entry, unsigned long io_address) +{ + unsigned long iopt_base; + unsigned long page_size; + unsigned long page_number; + unsigned long iopt_offset; + + iopt_base = iost_entry.val & IOST_PT_BASE_MASK; + page_size = iost_entry.val & IOST_PS_MASK; + + /* decode page size to compute page number */ + page_number = (io_address & 0x0fffffff) >> (10 + 2 * page_size); + /* page number is an offset into the io page table */ + iopt_offset = (page_number << 3) & 0x7fff8ul; + return iopt_base + iopt_offset; +} + +/* compute the tag field of the iopt cache entry */ +static inline unsigned long +get_ioc_tag(ioste iost_entry, unsigned long io_address) +{ + unsigned long iopte = get_ioptep(iost_entry, io_address); + + return IOPT_VALID_MASK + | ((iopte & 0x00000000000000ff8ul) >> 3) + | ((iopte & 0x0000003fffffc0000ul) >> 9); +} + +/* compute the hashed 6 bit index for the 4-way associative pte cache */ +static inline unsigned long +get_ioc_hash(ioste iost_entry, unsigned long io_address) +{ + unsigned long iopte = get_ioptep(iost_entry, io_address); + + return ((iopte & 0x000000000000001f8ul) >> 3) + ^ ((iopte & 0x00000000000020000ul) >> 17) + ^ ((iopte & 0x00000000000010000ul) >> 15) + ^ ((iopte & 0x00000000000008000ul) >> 13) + ^ ((iopte & 0x00000000000004000ul) >> 11) + ^ ((iopte & 0x00000000000002000ul) >> 9) + ^ ((iopte & 0x00000000000001000ul) >> 7); +} + +/* same as above, but pretend that we have a simpler 1-way associative + pte cache with an 8 bit index */ +static inline unsigned long +get_ioc_hash_1way(ioste iost_entry, unsigned long io_address) +{ + unsigned long iopte = get_ioptep(iost_entry, io_address); + + return ((iopte & 0x000000000000001f8ul) >> 3) + ^ ((iopte & 0x00000000000020000ul) >> 17) + ^ ((iopte & 0x00000000000010000ul) >> 15) + ^ ((iopte & 0x00000000000008000ul) >> 13) + ^ ((iopte & 0x00000000000004000ul) >> 11) + ^ ((iopte & 0x00000000000002000ul) >> 9) + ^ ((iopte & 0x00000000000001000ul) >> 7) + ^ ((iopte & 0x0000000000000c000ul) >> 8); +} + +static inline ioste +get_iost_cache(void __iomem *base, unsigned long index) +{ + unsigned long __iomem *p = (base + IOC_ST_CACHE_DIR); + return mk_ioste(in_be64(&p[index])); +} + +static inline void +set_iost_cache(void __iomem *base, unsigned long index, ioste ste) +{ + unsigned long __iomem *p = (base + IOC_ST_CACHE_DIR); + pr_debug("ioste %02lx was %016lx, store %016lx", index, + get_iost_cache(base, index).val, ste.val); + out_be64(&p[index], ste.val); + pr_debug(" now %016lx\n", get_iost_cache(base, index).val); +} + +static inline unsigned long +get_iopt_cache(void __iomem *base, unsigned long index, unsigned long *tag) +{ + unsigned long __iomem *tags = (void *)(base + IOC_PT_CACHE_DIR); + unsigned long __iomem *p = (void *)(base + IOC_PT_CACHE_REG); + + *tag = tags[index]; + rmb(); + return *p; +} + +static inline void +set_iopt_cache(void __iomem *base, unsigned long index, + unsigned long tag, unsigned long val) +{ + unsigned long __iomem *tags = base + IOC_PT_CACHE_DIR; + unsigned long __iomem *p = base + IOC_PT_CACHE_REG; + pr_debug("iopt %02lx was v%016lx/t%016lx, store v%016lx/t%016lx\n", + index, get_iopt_cache(base, index, &oldtag), oldtag, val, tag); + + out_be64(p, val); + out_be64(&tags[index], tag); +} + +static inline void +set_iost_origin(void __iomem *base) +{ + unsigned long __iomem *p = base + IOC_ST_ORIGIN; + unsigned long origin = IOSTO_ENABLE | IOSTO_SW; + + pr_debug("iost_origin %016lx, now %016lx\n", in_be64(p), origin); + out_be64(p, origin); +} + +static inline void +set_iocmd_config(void __iomem *base) +{ + unsigned long __iomem *p = base + 0xc00; + unsigned long conf; + + conf = in_be64(p); + pr_debug("iost_conf %016lx, now %016lx\n", conf, conf | IOCMD_CONF_TE); + out_be64(p, conf | IOCMD_CONF_TE); +} + +/* FIXME: get these from the device tree */ +#define ioc_base 0x20000511000ull +#define ioc_mmio_base 0x20000510000ull +#define ioid 0x48a +#define iopt_phys_offset (- 0x20000000) /* We have a 512MB offset from the SB */ +#define io_page_size 0x1000000 + +static unsigned long map_iopt_entry(unsigned long address) +{ + switch (address >> 20) { + case 0x600: + address = 0x24020000000ull; /* spider i/o */ + break; + default: + address += iopt_phys_offset; + break; + } + + return get_iopt_entry(address, ioid, IOPT_PROT_RW); +} + +static void iommu_bus_setup_null(struct pci_bus *b) { } +static void iommu_dev_setup_null(struct pci_dev *d) { } + +/* initialize the iommu to support a simple linear mapping + * for each DMA window used by any device. For now, we + * happen to know that there is only one DMA window in use, + * starting at iopt_phys_offset. */ +static void cell_map_iommu(void) +{ + unsigned long address; + void __iomem *base; + ioste ioste; + unsigned long index; + + base = __ioremap(ioc_base, 0x1000, _PAGE_NO_CACHE); + pr_debug("%lx mapped to %p\n", ioc_base, base); + set_iocmd_config(base); + iounmap(base); + + base = __ioremap(ioc_mmio_base, 0x1000, _PAGE_NO_CACHE); + pr_debug("%lx mapped to %p\n", ioc_mmio_base, base); + + set_iost_origin(base); + + for (address = 0; address < 0x100000000ul; address += io_page_size) { + ioste = get_iost_entry(0x10000000000ul, address, io_page_size); + if ((address & 0xfffffff) == 0) /* segment start */ + set_iost_cache(base, address >> 28, ioste); + index = get_ioc_hash_1way(ioste, address); + pr_debug("addr %08lx, index %02lx, ioste %016lx\n", + address, index, ioste.val); + set_iopt_cache(base, + get_ioc_hash_1way(ioste, address), + get_ioc_tag(ioste, address), + map_iopt_entry(address)); + } + iounmap(base); +} + + +static void *cell_alloc_coherent(struct device *hwdev, size_t size, + dma_addr_t *dma_handle, unsigned int __nocast flag) +{ + void *ret; + + ret = (void *)__get_free_pages(flag, get_order(size)); + if (ret != NULL) { + memset(ret, 0, size); + *dma_handle = virt_to_abs(ret) | CELL_DMA_VALID; + } + return ret; +} + +static void cell_free_coherent(struct device *hwdev, size_t size, + void *vaddr, dma_addr_t dma_handle) +{ + free_pages((unsigned long)vaddr, get_order(size)); +} + +static dma_addr_t cell_map_single(struct device *hwdev, void *ptr, + size_t size, enum dma_data_direction direction) +{ + return virt_to_abs(ptr) | CELL_DMA_VALID; +} + +static void cell_unmap_single(struct device *hwdev, dma_addr_t dma_addr, + size_t size, enum dma_data_direction direction) +{ +} + +static int cell_map_sg(struct device *hwdev, struct scatterlist *sg, + int nents, enum dma_data_direction direction) +{ + int i; + + for (i = 0; i < nents; i++, sg++) { + sg->dma_address = (page_to_phys(sg->page) + sg->offset) + | CELL_DMA_VALID; + sg->dma_length = sg->length; + } + + return nents; +} + +static void cell_unmap_sg(struct device *hwdev, struct scatterlist *sg, + int nents, enum dma_data_direction direction) +{ +} + +static int cell_dma_supported(struct device *dev, u64 mask) +{ + return mask < 0x100000000ull; +} + +void cell_init_iommu(void) +{ + cell_map_iommu(); + + /* Direct I/O, IOMMU off */ + ppc_md.iommu_dev_setup = iommu_dev_setup_null; + ppc_md.iommu_bus_setup = iommu_bus_setup_null; + + pci_dma_ops.alloc_coherent = cell_alloc_coherent; + pci_dma_ops.free_coherent = cell_free_coherent; + pci_dma_ops.map_single = cell_map_single; + pci_dma_ops.unmap_single = cell_unmap_single; + pci_dma_ops.map_sg = cell_map_sg; + pci_dma_ops.unmap_sg = cell_unmap_sg; + pci_dma_ops.dma_supported = cell_dma_supported; +} --- linux-cg.orig/arch/powerpc/platforms/cell/iommu.h 1969-12-31 19:00:00.000000000 -0500 +++ linux-cg/arch/powerpc/platforms/cell/iommu.h 2005-09-01 02:37:46.077991888 -0400 @@ -0,0 +1,65 @@ +#ifndef CELL_IOMMU_H +#define CELL_IOMMU_H + +/* some constants */ +enum { + /* segment table entries */ + IOST_VALID_MASK = 0x8000000000000000ul, + IOST_TAG_MASK = 0x3000000000000000ul, + IOST_PT_BASE_MASK = 0x000003fffffff000ul, + IOST_NNPT_MASK = 0x0000000000000fe0ul, + IOST_PS_MASK = 0x000000000000000ful, + + IOST_PS_4K = 0x1, + IOST_PS_64K = 0x3, + IOST_PS_1M = 0x5, + IOST_PS_16M = 0x7, + + /* iopt tag register */ + IOPT_VALID_MASK = 0x0000000200000000ul, + IOPT_TAG_MASK = 0x00000001fffffffful, + + /* iopt cache register */ + IOPT_PROT_MASK = 0xc000000000000000ul, + IOPT_PROT_NONE = 0x0000000000000000ul, + IOPT_PROT_READ = 0x4000000000000000ul, + IOPT_PROT_WRITE = 0x8000000000000000ul, + IOPT_PROT_RW = 0xc000000000000000ul, + IOPT_COHERENT = 0x2000000000000000ul, + + IOPT_ORDER_MASK = 0x1800000000000000ul, + /* order access to same IOID/VC on same address */ + IOPT_ORDER_ADDR = 0x0800000000000000ul, + /* similar, but only after a write access */ + IOPT_ORDER_WRITES = 0x1000000000000000ul, + /* Order all accesses to same IOID/VC */ + IOPT_ORDER_VC = 0x1800000000000000ul, + + IOPT_RPN_MASK = 0x000003fffffff000ul, + IOPT_HINT_MASK = 0x0000000000000800ul, + IOPT_IOID_MASK = 0x00000000000007fful, + + IOSTO_ENABLE = 0x8000000000000000ul, + IOSTO_ORIGIN = 0x000003fffffff000ul, + IOSTO_HW = 0x0000000000000800ul, + IOSTO_SW = 0x0000000000000400ul, + + IOCMD_CONF_TE = 0x0000800000000000ul, + + /* memory mapped registers */ + IOC_PT_CACHE_DIR = 0x000, + IOC_ST_CACHE_DIR = 0x800, + IOC_PT_CACHE_REG = 0x910, + IOC_ST_ORIGIN = 0x918, + IOC_CONF = 0x930, + + /* The high bit needs to be set on every DMA address, + only 2GB are addressable */ + CELL_DMA_VALID = 0x80000000, + CELL_DMA_MASK = 0x7fffffff, +}; + + +void cell_init_iommu(void); + +#endif --- linux-cg.orig/arch/powerpc/platforms/cell/nvram.c 1969-12-31 19:00:00.000000000 -0500 +++ linux-cg/arch/powerpc/platforms/cell/nvram.c 2005-09-01 02:37:46.077991888 -0400 @@ -0,0 +1,118 @@ +/* + * NVRAM for Cell Blade + * + * (C) Copyright IBM Corp. 2005 + * + * Authors : Utz Bacher + * + * 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, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include + +#include +#include +#include + +static void __iomem *cell_nvram_start; +static long cell_nvram_len; +static spinlock_t cell_nvram_lock = SPIN_LOCK_UNLOCKED; + +static ssize_t cell_nvram_read(char *buf, size_t count, loff_t *index) +{ + unsigned long flags; + + if (*index >= cell_nvram_len) + return 0; + if (*index + count > cell_nvram_len) + count = cell_nvram_len - *index; + + spin_lock_irqsave(&cell_nvram_lock, flags); + + memcpy_fromio(buf, cell_nvram_start + *index, count); + + spin_unlock_irqrestore(&cell_nvram_lock, flags); + + *index += count; + return count; +} + +static ssize_t cell_nvram_write(char *buf, size_t count, loff_t *index) +{ + unsigned long flags; + + if (*index >= cell_nvram_len) + return 0; + if (*index + count > cell_nvram_len) + count = cell_nvram_len - *index; + + spin_lock_irqsave(&cell_nvram_lock, flags); + + memcpy_toio(cell_nvram_start + *index, buf, count); + + spin_unlock_irqrestore(&cell_nvram_lock, flags); + + *index += count; + return count; +} + +static ssize_t cell_nvram_get_size(void) +{ + return cell_nvram_len; +} + +int __init cell_nvram_init(void) +{ + struct device_node *nvram_node; + unsigned long *buffer; + int proplen; + unsigned long nvram_addr; + int ret; + + ret = -ENODEV; + nvram_node = of_find_node_by_type(NULL, "nvram"); + if (!nvram_node) + goto out; + + ret = -EIO; + buffer = (unsigned long *)get_property(nvram_node, "reg", &proplen); + if (proplen != 2*sizeof(unsigned long)) + goto out; + + ret = -ENODEV; + nvram_addr = buffer[0]; + cell_nvram_len = buffer[1]; + if ( (!cell_nvram_len) || (!nvram_addr) ) + goto out; + + cell_nvram_start = ioremap(nvram_addr, cell_nvram_len); + if (!cell_nvram_start) + goto out; + + printk(KERN_INFO "CBEA NVRAM, %luk mapped to %p\n", + cell_nvram_len >> 10, cell_nvram_start); + + ppc_md.nvram_read = cell_nvram_read; + ppc_md.nvram_write = cell_nvram_write; + ppc_md.nvram_size = cell_nvram_get_size; + +out: + of_node_put(nvram_node); + return ret; +} --- linux-cg.orig/arch/powerpc/platforms/cell/pic.c 1969-12-31 19:00:00.000000000 -0500 +++ linux-cg/arch/powerpc/platforms/cell/pic.c 2005-09-01 02:37:46.079991584 -0400 @@ -0,0 +1,269 @@ +/* + * Cell Internal Interrupt Controller + * + * (C) Copyright IBM Deutschland Entwicklung GmbH 2005 + * + * Author: Arnd Bergmann + * + * 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, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +struct iic_pending_bits { + u32 data; + u8 flags; + u8 class; + u8 source; + u8 prio; +}; + +enum iic_pending_flags { + IIC_VALID = 0x80, + IIC_IPI = 0x40, +}; + +struct iic_regs { + struct iic_pending_bits pending; + struct iic_pending_bits pending_destr; + u64 generate; + u64 prio; +}; + +struct iic { + struct iic_regs __iomem *regs; +}; + +static DEFINE_PER_CPU(struct iic, iic); + +void iic_local_enable(void) +{ + out_be64(&__get_cpu_var(iic).regs->prio, 0xff); +} + +void iic_local_disable(void) +{ + out_be64(&__get_cpu_var(iic).regs->prio, 0x0); +} + +static unsigned int iic_startup(unsigned int irq) +{ + return 0; +} + +static void iic_enable(unsigned int irq) +{ + iic_local_enable(); +} + +static void iic_disable(unsigned int irq) +{ +} + +static void iic_end(unsigned int irq) +{ + iic_local_enable(); +} + +static struct hw_interrupt_type iic_pic = { + .typename = " CELLPIC ", + .startup = iic_startup, + .enable = iic_enable, + .disable = iic_disable, + .end = iic_end, +}; + +static int iic_external_get_irq(struct iic_pending_bits pending) +{ + int irq; + unsigned char node, unit; + + node = pending.source >> 4; + unit = pending.source & 0xf; + irq = -1; + + /* + * This mapping is specific to the Broadband + * Engine. We might need to get the numbers + * from the device tree to support future CPUs. + */ + switch (unit) { + case 0x00: + case 0x0b: + /* + * One of these units can be connected + * to an external interrupt controller. + */ + if (pending.prio > 0x3f || + pending.class != 2) + break; + irq = IIC_EXT_OFFSET + + spider_get_irq(pending.prio + node * IIC_NODE_STRIDE) + + node * IIC_NODE_STRIDE; + break; + case 0x01 ... 0x04: + case 0x07 ... 0x0a: + /* + * These units are connected to the SPEs + */ + if (pending.class > 2) + break; + irq = IIC_SPE_OFFSET + + pending.class * IIC_CLASS_STRIDE + + node * IIC_NODE_STRIDE + + unit; + break; + } + if (irq == -1) + printk(KERN_WARNING "Unexpected interrupt class %02x, " + "source %02x, prio %02x, cpu %02x\n", pending.class, + pending.source, pending.prio, smp_processor_id()); + return irq; +} + +/* Get an IRQ number from the pending state register of the IIC */ +int iic_get_irq(struct pt_regs *regs) +{ + struct iic *iic; + int irq; + struct iic_pending_bits pending; + + iic = &__get_cpu_var(iic); + *(unsigned long *) &pending = + in_be64((unsigned long __iomem *) &iic->regs->pending_destr); + + irq = -1; + if (pending.flags & IIC_VALID) { + if (pending.flags & IIC_IPI) { + irq = IIC_IPI_OFFSET + (pending.prio >> 4); +/* + if (irq > 0x80) + printk(KERN_WARNING "Unexpected IPI prio %02x" + "on CPU %02x\n", pending.prio, + smp_processor_id()); +*/ + } else { + irq = iic_external_get_irq(pending); + } + } + return irq; +} + +static struct iic_regs __iomem *find_iic(int cpu) +{ + struct device_node *np; + int nodeid = cpu / 2; + unsigned long regs; + struct iic_regs __iomem *iic_regs; + + for (np = of_find_node_by_type(NULL, "cpu"); + np; + np = of_find_node_by_type(np, "cpu")) { + if (nodeid == *(int *)get_property(np, "node-id", NULL)) + break; + } + + if (!np) { + printk(KERN_WARNING "IIC: CPU %d not found\n", cpu); + iic_regs = NULL; + } else { + regs = *(long *)get_property(np, "iic", NULL); + + /* hack until we have decided on the devtree info */ + regs += 0x400; + if (cpu & 1) + regs += 0x20; + + printk(KERN_DEBUG "IIC for CPU %d at %lx\n", cpu, regs); + iic_regs = __ioremap(regs, sizeof(struct iic_regs), + _PAGE_NO_CACHE); + } + return iic_regs; +} + +#ifdef CONFIG_SMP +void iic_setup_cpu(void) +{ + out_be64(&__get_cpu_var(iic).regs->prio, 0xff); +} + +void iic_cause_IPI(int cpu, int mesg) +{ + out_be64(&per_cpu(iic, cpu).regs->generate, mesg); +} + +static irqreturn_t iic_ipi_action(int irq, void *dev_id, struct pt_regs *regs) +{ + + smp_message_recv(irq - IIC_IPI_OFFSET, regs); + return IRQ_HANDLED; +} + +static void iic_request_ipi(int irq, const char *name) +{ + /* IPIs are marked SA_INTERRUPT as they must run with irqs + * disabled */ + get_irq_desc(irq)->handler = &iic_pic; + get_irq_desc(irq)->status |= IRQ_PER_CPU; + request_irq(irq, iic_ipi_action, SA_INTERRUPT, name, NULL); +} + +void iic_request_IPIs(void) +{ + iic_request_ipi(IIC_IPI_OFFSET + PPC_MSG_CALL_FUNCTION, "IPI-call"); + iic_request_ipi(IIC_IPI_OFFSET + PPC_MSG_RESCHEDULE, "IPI-resched"); +#ifdef CONFIG_DEBUGGER + iic_request_ipi(IIC_IPI_OFFSET + PPC_MSG_DEBUGGER_BREAK, "IPI-debug"); +#endif /* CONFIG_DEBUGGER */ +} +#endif /* CONFIG_SMP */ + +static void iic_setup_spe_handlers(void) +{ + int be, isrc; + + /* Assume two threads per BE are present */ + for (be=0; be < num_present_cpus() / 2; be++) { + for (isrc = 0; isrc < IIC_CLASS_STRIDE * 3; isrc++) { + int irq = IIC_NODE_STRIDE * be + IIC_SPE_OFFSET + isrc; + get_irq_desc(irq)->handler = &iic_pic; + } + } +} + +void iic_init_IRQ(void) +{ + int cpu, irq_offset; + struct iic *iic; + + irq_offset = 0; + for_each_cpu(cpu) { + iic = &per_cpu(iic, cpu); + iic->regs = find_iic(cpu); + if (iic->regs) + out_be64(&iic->regs->prio, 0xff); + } + iic_setup_spe_handlers(); +} --- linux-cg.orig/arch/powerpc/platforms/cell/setup.c 1969-12-31 19:00:00.000000000 -0500 +++ linux-cg/arch/powerpc/platforms/cell/setup.c 2005-09-01 02:37:46.079991584 -0400 @@ -0,0 +1,138 @@ +/* + * Copyright (C) 1995 Linus Torvalds + * Adapted from 'alpha' version by Gary Thomas + * Modified by Cort Dougan (cort at cs.nmt.edu) + * Modified by PPC64 Team, IBM Corp + * Modified by Cell Team, IBM Deutschland Entwicklung GmbH + * + * 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. + */ +#undef DEBUG + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "../../../ppc64/kernel/pci.h" +#include "iommu.h" + +#ifdef DEBUG +#define DBG(fmt...) udbg_printf(fmt) +#else +#define DBG(fmt...) +#endif + +void cell_get_cpuinfo(struct seq_file *m) +{ + struct device_node *root; + const char *model = ""; + + root = of_find_node_by_path("/"); + if (root) + model = get_property(root, "model", NULL); + seq_printf(m, "machine\t\t: Cell %s\n", model); + of_node_put(root); +} + +static void cell_progress(char *s, unsigned short hex) +{ + printk("*** %04x : %s\n", hex, s ? s : ""); +} + +static void __init cell_setup_arch(void) +{ + ppc_md.init_IRQ = iic_init_IRQ; + ppc_md.get_irq = iic_get_irq; + +#ifdef CONFIG_SMP + smp_init_pSeries(); +#endif + + /* init to some ~sane value until calibrate_delay() runs */ + loops_per_jiffy = 50000000; + + if (ROOT_DEV == 0) { + printk("No ramdisk, default root is /dev/hda2\n"); + ROOT_DEV = Root_HDA2; + } + + /* Find and initialize PCI host bridges */ + init_pci_config_tokens(); + find_and_init_phbs(); + spider_init_IRQ(); +#ifdef CONFIG_DUMMY_CONSOLE + conswitchp = &dummy_con; +#endif + + cell_nvram_init(); +} + +/* + * Early initialization. Relocation is on but do not reference unbolted pages + */ +static void __init cell_init_early(void) +{ + DBG(" -> cell_init_early()\n"); + + hpte_init_native(); + + cell_init_iommu(); + + ppc64_interrupt_controller = IC_CELL_PIC; + + DBG(" <- cell_init_early()\n"); +} + + +static int __init cell_probe(int platform) +{ + if (platform != PLATFORM_CELL) + return 0; + + return 1; +} + +struct machdep_calls __initdata cell_md = { + .probe = cell_probe, + .setup_arch = cell_setup_arch, + .init_early = cell_init_early, + .get_cpuinfo = cell_get_cpuinfo, + .restart = rtas_restart, + .power_off = rtas_power_off, + .halt = rtas_halt, + .get_boot_time = rtas_get_boot_time, + .get_rtc_time = rtas_get_rtc_time, + .set_rtc_time = rtas_set_rtc_time, + .calibrate_decr = generic_calibrate_decr, + .progress = cell_progress, +}; --- linux-cg.orig/arch/powerpc/platforms/cell/spider-pic.c 1969-12-31 19:00:00.000000000 -0500 +++ linux-cg/arch/powerpc/platforms/cell/spider-pic.c 2005-09-01 02:37:46.081991280 -0400 @@ -0,0 +1,190 @@ +/* + * External Interrupt Controller on Spider South Bridge + * + * (C) Copyright IBM Deutschland Entwicklung GmbH 2005 + * + * Author: Arnd Bergmann + * + * 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, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include + +#include +#include +#include +#include + +/* register layout taken from Spider spec, table 7.4-4 */ +enum { + TIR_DEN = 0x004, /* Detection Enable Register */ + TIR_MSK = 0x084, /* Mask Level Register */ + TIR_EDC = 0x0c0, /* Edge Detection Clear Register */ + TIR_PNDA = 0x100, /* Pending Register A */ + TIR_PNDB = 0x104, /* Pending Register B */ + TIR_CS = 0x144, /* Current Status Register */ + TIR_LCSA = 0x150, /* Level Current Status Register A */ + TIR_LCSB = 0x154, /* Level Current Status Register B */ + TIR_LCSC = 0x158, /* Level Current Status Register C */ + TIR_LCSD = 0x15c, /* Level Current Status Register D */ + TIR_CFGA = 0x200, /* Setting Register A0 */ + TIR_CFGB = 0x204, /* Setting Register B0 */ + /* 0x208 ... 0x3ff Setting Register An/Bn */ + TIR_PPNDA = 0x400, /* Packet Pending Register A */ + TIR_PPNDB = 0x404, /* Packet Pending Register B */ + TIR_PIERA = 0x408, /* Packet Output Error Register A */ + TIR_PIERB = 0x40c, /* Packet Output Error Register B */ + TIR_PIEN = 0x444, /* Packet Output Enable Register */ + TIR_PIPND = 0x454, /* Packet Output Pending Register */ + TIRDID = 0x484, /* Spider Device ID Register */ + REISTIM = 0x500, /* Reissue Command Timeout Time Setting */ + REISTIMEN = 0x504, /* Reissue Command Timeout Setting */ + REISWAITEN = 0x508, /* Reissue Wait Control*/ +}; + +static void __iomem *spider_pics[4]; + +static void __iomem *spider_get_pic(int irq) +{ + int node = irq / IIC_NODE_STRIDE; + irq %= IIC_NODE_STRIDE; + + if (irq >= IIC_EXT_OFFSET && + irq < IIC_EXT_OFFSET + IIC_NUM_EXT && + spider_pics) + return spider_pics[node]; + return NULL; +} + +static int spider_get_nr(unsigned int irq) +{ + return (irq % IIC_NODE_STRIDE) - IIC_EXT_OFFSET; +} + +static void __iomem *spider_get_irq_config(int irq) +{ + void __iomem *pic; + pic = spider_get_pic(irq); + return pic + TIR_CFGA + 8 * spider_get_nr(irq); +} + +static void spider_enable_irq(unsigned int irq) +{ + void __iomem *cfg = spider_get_irq_config(irq); + irq = spider_get_nr(irq); + + out_be32(cfg, in_be32(cfg) | 0x3107000eu); + out_be32(cfg + 4, in_be32(cfg + 4) | 0x00020000u | irq); +} + +static void spider_disable_irq(unsigned int irq) +{ + void __iomem *cfg = spider_get_irq_config(irq); + irq = spider_get_nr(irq); + + out_be32(cfg, in_be32(cfg) & ~0x30000000u); +} + +static unsigned int spider_startup_irq(unsigned int irq) +{ + spider_enable_irq(irq); + return 0; +} + +static void spider_shutdown_irq(unsigned int irq) +{ + spider_disable_irq(irq); +} + +static void spider_end_irq(unsigned int irq) +{ + spider_enable_irq(irq); +} + +static void spider_ack_irq(unsigned int irq) +{ + spider_disable_irq(irq); + iic_local_enable(); +} + +static struct hw_interrupt_type spider_pic = { + .typename = " SPIDER ", + .startup = spider_startup_irq, + .shutdown = spider_shutdown_irq, + .enable = spider_enable_irq, + .disable = spider_disable_irq, + .ack = spider_ack_irq, + .end = spider_end_irq, +}; + + +int spider_get_irq(unsigned long int_pending) +{ + void __iomem *regs = spider_get_pic(int_pending); + unsigned long cs; + int irq; + + cs = in_be32(regs + TIR_CS); + + irq = cs >> 24; + if (irq != 63) + return irq; + + return -1; +} + +void spider_init_IRQ(void) +{ + int node; + struct device_node *dn; + unsigned int *property; + long spiderpic; + int n; + +/* FIXME: detect multiple PICs as soon as the device tree has them */ + for (node = 0; node < 1; node++) { + dn = of_find_node_by_path("/"); + n = prom_n_addr_cells(dn); + property = (unsigned int *) get_property(dn, + "platform-spider-pic", NULL); + + if (!property) + continue; + for (spiderpic = 0; n > 0; --n) + spiderpic = (spiderpic << 32) + *property++; + printk(KERN_DEBUG "SPIDER addr: %lx\n", spiderpic); + spider_pics[node] = __ioremap(spiderpic, 0x800, _PAGE_NO_CACHE); + for (n = 0; n < IIC_NUM_EXT; n++) { + int irq = n + IIC_EXT_OFFSET + node * IIC_NODE_STRIDE; + get_irq_desc(irq)->handler = &spider_pic; + + /* do not mask any interrupts because of level */ + out_be32(spider_pics[node] + TIR_MSK, 0x0); + + /* disable edge detection clear */ + /* out_be32(spider_pics[node] + TIR_EDC, 0x0); */ + + /* enable interrupt packets to be output */ + out_be32(spider_pics[node] + TIR_PIEN, + in_be32(spider_pics[node] + TIR_PIEN) | 0x1); + + /* Enable the interrupt detection enable bit. Do this last! */ + out_be32(spider_pics[node] + TIR_DEN, + in_be32(spider_pics[node] +TIR_DEN) | 0x1); + + } + } +} --- linux-cg.orig/arch/ppc64/Kconfig 2005-09-01 02:37:40.900980184 -0400 +++ linux-cg/arch/ppc64/Kconfig 2005-09-01 02:37:46.081991280 -0400 @@ -77,10 +77,16 @@ config PPC_PSERIES bool " IBM pSeries & new iSeries" default y -config PPC_BPA - bool " Broadband Processor Architecture" +config PPC_CELL + bool " Cell Broadband Engine Architecture" depends on PPC_MULTIPLATFORM +# This is being phased out in the move to arch/powerpc +config PPC_BPA + bool + default y + depends on PPC_CELL + config PPC_PMAC depends on PPC_MULTIPLATFORM bool " Apple G5 based machines" --- linux-cg.orig/arch/ppc64/kernel/Makefile 2005-09-01 02:37:40.903979728 -0400 +++ linux-cg/arch/ppc64/kernel/Makefile 2005-09-01 02:37:46.082991128 -0400 @@ -33,8 +33,7 @@ obj-$(CONFIG_PPC_PSERIES) += pSeries_pci pSeries_nvram.o rtasd.o ras.o pSeries_reconfig.o \ pSeries_setup.o pSeries_iommu.o -obj-$(CONFIG_PPC_BPA) += bpa_setup.o bpa_iommu.o bpa_nvram.o \ - bpa_iic.o spider-pic.o +obj-$(CONFIG_PPC_CELL) += ../../powerpc/platforms/cell/ obj-$(CONFIG_KEXEC) += machine_kexec.o obj-$(CONFIG_EEH) += eeh.o @@ -68,7 +67,7 @@ ifdef CONFIG_SMP obj-$(CONFIG_PPC_PMAC) += pmac_smp.o smp-tbsync.o obj-$(CONFIG_PPC_ISERIES) += iSeries_smp.o obj-$(CONFIG_PPC_PSERIES) += pSeries_smp.o -obj-$(CONFIG_PPC_BPA) += pSeries_smp.o +obj-$(CONFIG_PPC_CELL) += pSeries_smp.o obj-$(CONFIG_PPC_MAPLE) += smp-tbsync.o endif --- linux-cg.orig/arch/ppc64/kernel/bpa_iic.c 2005-09-01 02:37:40.905979424 -0400 +++ linux-cg/arch/ppc64/kernel/bpa_iic.c 1969-12-31 19:00:00.000000000 -0500 @@ -1,270 +0,0 @@ -/* - * BPA Internal Interrupt Controller - * - * (C) Copyright IBM Deutschland Entwicklung GmbH 2005 - * - * Author: Arnd Bergmann - * - * 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, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#include "bpa_iic.h" - -struct iic_pending_bits { - u32 data; - u8 flags; - u8 class; - u8 source; - u8 prio; -}; - -enum iic_pending_flags { - IIC_VALID = 0x80, - IIC_IPI = 0x40, -}; - -struct iic_regs { - struct iic_pending_bits pending; - struct iic_pending_bits pending_destr; - u64 generate; - u64 prio; -}; - -struct iic { - struct iic_regs __iomem *regs; -}; - -static DEFINE_PER_CPU(struct iic, iic); - -void iic_local_enable(void) -{ - out_be64(&__get_cpu_var(iic).regs->prio, 0xff); -} - -void iic_local_disable(void) -{ - out_be64(&__get_cpu_var(iic).regs->prio, 0x0); -} - -static unsigned int iic_startup(unsigned int irq) -{ - return 0; -} - -static void iic_enable(unsigned int irq) -{ - iic_local_enable(); -} - -static void iic_disable(unsigned int irq) -{ -} - -static void iic_end(unsigned int irq) -{ - iic_local_enable(); -} - -static struct hw_interrupt_type iic_pic = { - .typename = " BPA-IIC ", - .startup = iic_startup, - .enable = iic_enable, - .disable = iic_disable, - .end = iic_end, -}; - -static int iic_external_get_irq(struct iic_pending_bits pending) -{ - int irq; - unsigned char node, unit; - - node = pending.source >> 4; - unit = pending.source & 0xf; - irq = -1; - - /* - * This mapping is specific to the Broadband - * Engine. We might need to get the numbers - * from the device tree to support future CPUs. - */ - switch (unit) { - case 0x00: - case 0x0b: - /* - * One of these units can be connected - * to an external interrupt controller. - */ - if (pending.prio > 0x3f || - pending.class != 2) - break; - irq = IIC_EXT_OFFSET - + spider_get_irq(pending.prio + node * IIC_NODE_STRIDE) - + node * IIC_NODE_STRIDE; - break; - case 0x01 ... 0x04: - case 0x07 ... 0x0a: - /* - * These units are connected to the SPEs - */ - if (pending.class > 2) - break; - irq = IIC_SPE_OFFSET - + pending.class * IIC_CLASS_STRIDE - + node * IIC_NODE_STRIDE - + unit; - break; - } - if (irq == -1) - printk(KERN_WARNING "Unexpected interrupt class %02x, " - "source %02x, prio %02x, cpu %02x\n", pending.class, - pending.source, pending.prio, smp_processor_id()); - return irq; -} - -/* Get an IRQ number from the pending state register of the IIC */ -int iic_get_irq(struct pt_regs *regs) -{ - struct iic *iic; - int irq; - struct iic_pending_bits pending; - - iic = &__get_cpu_var(iic); - *(unsigned long *) &pending = - in_be64((unsigned long __iomem *) &iic->regs->pending_destr); - - irq = -1; - if (pending.flags & IIC_VALID) { - if (pending.flags & IIC_IPI) { - irq = IIC_IPI_OFFSET + (pending.prio >> 4); -/* - if (irq > 0x80) - printk(KERN_WARNING "Unexpected IPI prio %02x" - "on CPU %02x\n", pending.prio, - smp_processor_id()); -*/ - } else { - irq = iic_external_get_irq(pending); - } - } - return irq; -} - -static struct iic_regs __iomem *find_iic(int cpu) -{ - struct device_node *np; - int nodeid = cpu / 2; - unsigned long regs; - struct iic_regs __iomem *iic_regs; - - for (np = of_find_node_by_type(NULL, "cpu"); - np; - np = of_find_node_by_type(np, "cpu")) { - if (nodeid == *(int *)get_property(np, "node-id", NULL)) - break; - } - - if (!np) { - printk(KERN_WARNING "IIC: CPU %d not found\n", cpu); - iic_regs = NULL; - } else { - regs = *(long *)get_property(np, "iic", NULL); - - /* hack until we have decided on the devtree info */ - regs += 0x400; - if (cpu & 1) - regs += 0x20; - - printk(KERN_DEBUG "IIC for CPU %d at %lx\n", cpu, regs); - iic_regs = __ioremap(regs, sizeof(struct iic_regs), - _PAGE_NO_CACHE); - } - return iic_regs; -} - -#ifdef CONFIG_SMP -void iic_setup_cpu(void) -{ - out_be64(&__get_cpu_var(iic).regs->prio, 0xff); -} - -void iic_cause_IPI(int cpu, int mesg) -{ - out_be64(&per_cpu(iic, cpu).regs->generate, mesg); -} - -static irqreturn_t iic_ipi_action(int irq, void *dev_id, struct pt_regs *regs) -{ - - smp_message_recv(irq - IIC_IPI_OFFSET, regs); - return IRQ_HANDLED; -} - -static void iic_request_ipi(int irq, const char *name) -{ - /* IPIs are marked SA_INTERRUPT as they must run with irqs - * disabled */ - get_irq_desc(irq)->handler = &iic_pic; - get_irq_desc(irq)->status |= IRQ_PER_CPU; - request_irq(irq, iic_ipi_action, SA_INTERRUPT, name, NULL); -} - -void iic_request_IPIs(void) -{ - iic_request_ipi(IIC_IPI_OFFSET + PPC_MSG_CALL_FUNCTION, "IPI-call"); - iic_request_ipi(IIC_IPI_OFFSET + PPC_MSG_RESCHEDULE, "IPI-resched"); -#ifdef CONFIG_DEBUGGER - iic_request_ipi(IIC_IPI_OFFSET + PPC_MSG_DEBUGGER_BREAK, "IPI-debug"); -#endif /* CONFIG_DEBUGGER */ -} -#endif /* CONFIG_SMP */ - -static void iic_setup_spe_handlers(void) -{ - int be, isrc; - - /* Assume two threads per BE are present */ - for (be=0; be < num_present_cpus() / 2; be++) { - for (isrc = 0; isrc < IIC_CLASS_STRIDE * 3; isrc++) { - int irq = IIC_NODE_STRIDE * be + IIC_SPE_OFFSET + isrc; - get_irq_desc(irq)->handler = &iic_pic; - } - } -} - -void iic_init_IRQ(void) -{ - int cpu, irq_offset; - struct iic *iic; - - irq_offset = 0; - for_each_cpu(cpu) { - iic = &per_cpu(iic, cpu); - iic->regs = find_iic(cpu); - if (iic->regs) - out_be64(&iic->regs->prio, 0xff); - } - iic_setup_spe_handlers(); -} --- linux-cg.orig/arch/ppc64/kernel/bpa_iic.h 2005-09-01 02:37:40.908978968 -0400 +++ linux-cg/arch/ppc64/kernel/bpa_iic.h 1969-12-31 19:00:00.000000000 -0500 @@ -1,62 +0,0 @@ -#ifndef ASM_BPA_IIC_H -#define ASM_BPA_IIC_H -#ifdef __KERNEL__ -/* - * Mapping of IIC pending bits into per-node - * interrupt numbers. - * - * IRQ FF CC SS PP FF CC SS PP Description - * - * 00-3f 80 02 +0 00 - 80 02 +0 3f South Bridge - * 00-3f 80 02 +b 00 - 80 02 +b 3f South Bridge - * 41-4a 80 00 +1 ** - 80 00 +a ** SPU Class 0 - * 51-5a 80 01 +1 ** - 80 01 +a ** SPU Class 1 - * 61-6a 80 02 +1 ** - 80 02 +a ** SPU Class 2 - * 70-7f C0 ** ** 00 - C0 ** ** 0f IPI - * - * F flags - * C class - * S source - * P Priority - * + node number - * * don't care - * - * A node consists of a Broadband Engine and an optional - * south bridge device providing a maximum of 64 IRQs. - * The south bridge may be connected to either IOIF0 - * or IOIF1. - * Each SPE is represented as three IRQ lines, one per - * interrupt class. - * 16 IRQ numbers are reserved for inter processor - * interruptions, although these are only used in the - * range of the first node. - * - * This scheme needs 128 IRQ numbers per BIF node ID, - * which means that with the total of 512 lines - * available, we can have a maximum of four nodes. - */ - -enum { - IIC_EXT_OFFSET = 0x00, /* Start of south bridge IRQs */ - IIC_NUM_EXT = 0x40, /* Number of south bridge IRQs */ - IIC_SPE_OFFSET = 0x40, /* Start of SPE interrupts */ - IIC_CLASS_STRIDE = 0x10, /* SPE IRQs per class */ - IIC_IPI_OFFSET = 0x70, /* Start of IPI IRQs */ - IIC_NUM_IPIS = 0x10, /* IRQs reserved for IPI */ - IIC_NODE_STRIDE = 0x80, /* Total IRQs per node */ -}; - -extern void iic_init_IRQ(void); -extern int iic_get_irq(struct pt_regs *regs); -extern void iic_cause_IPI(int cpu, int mesg); -extern void iic_request_IPIs(void); -extern void iic_setup_cpu(void); -extern void iic_local_enable(void); -extern void iic_local_disable(void); - - -extern void spider_init_IRQ(void); -extern int spider_get_irq(unsigned long int_pending); - -#endif -#endif /* ASM_BPA_IIC_H */ --- linux-cg.orig/arch/ppc64/kernel/bpa_iommu.c 2005-09-01 02:37:40.910978664 -0400 +++ linux-cg/arch/ppc64/kernel/bpa_iommu.c 1969-12-31 19:00:00.000000000 -0500 @@ -1,377 +0,0 @@ -/* - * IOMMU implementation for Broadband Processor Architecture - * We just establish a linear mapping at boot by setting all the - * IOPT cache entries in the CPU. - * The mapping functions should be identical to pci_direct_iommu, - * except for the handling of the high order bit that is required - * by the Spider bridge. These should be split into a separate - * file at the point where we get a different bridge chip. - * - * Copyright (C) 2005 IBM Deutschland Entwicklung GmbH, - * Arnd Bergmann - * - * Based on linear mapping - * Copyright (C) 2003 Benjamin Herrenschmidt (benh at kernel.crashing.org) - * - * 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. - */ - -#undef DEBUG - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "pci.h" -#include "bpa_iommu.h" - -static inline unsigned long -get_iopt_entry(unsigned long real_address, unsigned long ioid, - unsigned long prot) -{ - return (prot & IOPT_PROT_MASK) - | (IOPT_COHERENT) - | (IOPT_ORDER_VC) - | (real_address & IOPT_RPN_MASK) - | (ioid & IOPT_IOID_MASK); -} - -typedef struct { - unsigned long val; -} ioste; - -static inline ioste -mk_ioste(unsigned long val) -{ - ioste ioste = { .val = val, }; - return ioste; -} - -static inline ioste -get_iost_entry(unsigned long iopt_base, unsigned long io_address, unsigned page_size) -{ - unsigned long ps; - unsigned long iostep; - unsigned long nnpt; - unsigned long shift; - - switch (page_size) { - case 0x1000000: - ps = IOST_PS_16M; - nnpt = 0; /* one page per segment */ - shift = 5; /* segment has 16 iopt entries */ - break; - - case 0x100000: - ps = IOST_PS_1M; - nnpt = 0; /* one page per segment */ - shift = 1; /* segment has 256 iopt entries */ - break; - - case 0x10000: - ps = IOST_PS_64K; - nnpt = 0x07; /* 8 pages per io page table */ - shift = 0; /* all entries are used */ - break; - - case 0x1000: - ps = IOST_PS_4K; - nnpt = 0x7f; /* 128 pages per io page table */ - shift = 0; /* all entries are used */ - break; - - default: /* not a known compile time constant */ - BUILD_BUG_ON(1); - break; - } - - iostep = iopt_base + - /* need 8 bytes per iopte */ - (((io_address / page_size * 8) - /* align io page tables on 4k page boundaries */ - << shift) - /* nnpt+1 pages go into each iopt */ - & ~(nnpt << 12)); - - nnpt++; /* this seems to work, but the documentation is not clear - about wether we put nnpt or nnpt-1 into the ioste bits. - In theory, this can't work for 4k pages. */ - return mk_ioste(IOST_VALID_MASK - | (iostep & IOST_PT_BASE_MASK) - | ((nnpt << 5) & IOST_NNPT_MASK) - | (ps & IOST_PS_MASK)); -} - -/* compute the address of an io pte */ -static inline unsigned long -get_ioptep(ioste iost_entry, unsigned long io_address) -{ - unsigned long iopt_base; - unsigned long page_size; - unsigned long page_number; - unsigned long iopt_offset; - - iopt_base = iost_entry.val & IOST_PT_BASE_MASK; - page_size = iost_entry.val & IOST_PS_MASK; - - /* decode page size to compute page number */ - page_number = (io_address & 0x0fffffff) >> (10 + 2 * page_size); - /* page number is an offset into the io page table */ - iopt_offset = (page_number << 3) & 0x7fff8ul; - return iopt_base + iopt_offset; -} - -/* compute the tag field of the iopt cache entry */ -static inline unsigned long -get_ioc_tag(ioste iost_entry, unsigned long io_address) -{ - unsigned long iopte = get_ioptep(iost_entry, io_address); - - return IOPT_VALID_MASK - | ((iopte & 0x00000000000000ff8ul) >> 3) - | ((iopte & 0x0000003fffffc0000ul) >> 9); -} - -/* compute the hashed 6 bit index for the 4-way associative pte cache */ -static inline unsigned long -get_ioc_hash(ioste iost_entry, unsigned long io_address) -{ - unsigned long iopte = get_ioptep(iost_entry, io_address); - - return ((iopte & 0x000000000000001f8ul) >> 3) - ^ ((iopte & 0x00000000000020000ul) >> 17) - ^ ((iopte & 0x00000000000010000ul) >> 15) - ^ ((iopte & 0x00000000000008000ul) >> 13) - ^ ((iopte & 0x00000000000004000ul) >> 11) - ^ ((iopte & 0x00000000000002000ul) >> 9) - ^ ((iopte & 0x00000000000001000ul) >> 7); -} - -/* same as above, but pretend that we have a simpler 1-way associative - pte cache with an 8 bit index */ -static inline unsigned long -get_ioc_hash_1way(ioste iost_entry, unsigned long io_address) -{ - unsigned long iopte = get_ioptep(iost_entry, io_address); - - return ((iopte & 0x000000000000001f8ul) >> 3) - ^ ((iopte & 0x00000000000020000ul) >> 17) - ^ ((iopte & 0x00000000000010000ul) >> 15) - ^ ((iopte & 0x00000000000008000ul) >> 13) - ^ ((iopte & 0x00000000000004000ul) >> 11) - ^ ((iopte & 0x00000000000002000ul) >> 9) - ^ ((iopte & 0x00000000000001000ul) >> 7) - ^ ((iopte & 0x0000000000000c000ul) >> 8); -} - -static inline ioste -get_iost_cache(void __iomem *base, unsigned long index) -{ - unsigned long __iomem *p = (base + IOC_ST_CACHE_DIR); - return mk_ioste(in_be64(&p[index])); -} - -static inline void -set_iost_cache(void __iomem *base, unsigned long index, ioste ste) -{ - unsigned long __iomem *p = (base + IOC_ST_CACHE_DIR); - pr_debug("ioste %02lx was %016lx, store %016lx", index, - get_iost_cache(base, index).val, ste.val); - out_be64(&p[index], ste.val); - pr_debug(" now %016lx\n", get_iost_cache(base, index).val); -} - -static inline unsigned long -get_iopt_cache(void __iomem *base, unsigned long index, unsigned long *tag) -{ - unsigned long __iomem *tags = (void *)(base + IOC_PT_CACHE_DIR); - unsigned long __iomem *p = (void *)(base + IOC_PT_CACHE_REG); - - *tag = tags[index]; - rmb(); - return *p; -} - -static inline void -set_iopt_cache(void __iomem *base, unsigned long index, - unsigned long tag, unsigned long val) -{ - unsigned long __iomem *tags = base + IOC_PT_CACHE_DIR; - unsigned long __iomem *p = base + IOC_PT_CACHE_REG; - pr_debug("iopt %02lx was v%016lx/t%016lx, store v%016lx/t%016lx\n", - index, get_iopt_cache(base, index, &oldtag), oldtag, val, tag); - - out_be64(p, val); - out_be64(&tags[index], tag); -} - -static inline void -set_iost_origin(void __iomem *base) -{ - unsigned long __iomem *p = base + IOC_ST_ORIGIN; - unsigned long origin = IOSTO_ENABLE | IOSTO_SW; - - pr_debug("iost_origin %016lx, now %016lx\n", in_be64(p), origin); - out_be64(p, origin); -} - -static inline void -set_iocmd_config(void __iomem *base) -{ - unsigned long __iomem *p = base + 0xc00; - unsigned long conf; - - conf = in_be64(p); - pr_debug("iost_conf %016lx, now %016lx\n", conf, conf | IOCMD_CONF_TE); - out_be64(p, conf | IOCMD_CONF_TE); -} - -/* FIXME: get these from the device tree */ -#define ioc_base 0x20000511000ull -#define ioc_mmio_base 0x20000510000ull -#define ioid 0x48a -#define iopt_phys_offset (- 0x20000000) /* We have a 512MB offset from the SB */ -#define io_page_size 0x1000000 - -static unsigned long map_iopt_entry(unsigned long address) -{ - switch (address >> 20) { - case 0x600: - address = 0x24020000000ull; /* spider i/o */ - break; - default: - address += iopt_phys_offset; - break; - } - - return get_iopt_entry(address, ioid, IOPT_PROT_RW); -} - -static void iommu_bus_setup_null(struct pci_bus *b) { } -static void iommu_dev_setup_null(struct pci_dev *d) { } - -/* initialize the iommu to support a simple linear mapping - * for each DMA window used by any device. For now, we - * happen to know that there is only one DMA window in use, - * starting at iopt_phys_offset. */ -static void bpa_map_iommu(void) -{ - unsigned long address; - void __iomem *base; - ioste ioste; - unsigned long index; - - base = __ioremap(ioc_base, 0x1000, _PAGE_NO_CACHE); - pr_debug("%lx mapped to %p\n", ioc_base, base); - set_iocmd_config(base); - iounmap(base); - - base = __ioremap(ioc_mmio_base, 0x1000, _PAGE_NO_CACHE); - pr_debug("%lx mapped to %p\n", ioc_mmio_base, base); - - set_iost_origin(base); - - for (address = 0; address < 0x100000000ul; address += io_page_size) { - ioste = get_iost_entry(0x10000000000ul, address, io_page_size); - if ((address & 0xfffffff) == 0) /* segment start */ - set_iost_cache(base, address >> 28, ioste); - index = get_ioc_hash_1way(ioste, address); - pr_debug("addr %08lx, index %02lx, ioste %016lx\n", - address, index, ioste.val); - set_iopt_cache(base, - get_ioc_hash_1way(ioste, address), - get_ioc_tag(ioste, address), - map_iopt_entry(address)); - } - iounmap(base); -} - - -static void *bpa_alloc_coherent(struct device *hwdev, size_t size, - dma_addr_t *dma_handle, unsigned int __nocast flag) -{ - void *ret; - - ret = (void *)__get_free_pages(flag, get_order(size)); - if (ret != NULL) { - memset(ret, 0, size); - *dma_handle = virt_to_abs(ret) | BPA_DMA_VALID; - } - return ret; -} - -static void bpa_free_coherent(struct device *hwdev, size_t size, - void *vaddr, dma_addr_t dma_handle) -{ - free_pages((unsigned long)vaddr, get_order(size)); -} - -static dma_addr_t bpa_map_single(struct device *hwdev, void *ptr, - size_t size, enum dma_data_direction direction) -{ - return virt_to_abs(ptr) | BPA_DMA_VALID; -} - -static void bpa_unmap_single(struct device *hwdev, dma_addr_t dma_addr, - size_t size, enum dma_data_direction direction) -{ -} - -static int bpa_map_sg(struct device *hwdev, struct scatterlist *sg, - int nents, enum dma_data_direction direction) -{ - int i; - - for (i = 0; i < nents; i++, sg++) { - sg->dma_address = (page_to_phys(sg->page) + sg->offset) - | BPA_DMA_VALID; - sg->dma_length = sg->length; - } - - return nents; -} - -static void bpa_unmap_sg(struct device *hwdev, struct scatterlist *sg, - int nents, enum dma_data_direction direction) -{ -} - -static int bpa_dma_supported(struct device *dev, u64 mask) -{ - return mask < 0x100000000ull; -} - -void bpa_init_iommu(void) -{ - bpa_map_iommu(); - - /* Direct I/O, IOMMU off */ - ppc_md.iommu_dev_setup = iommu_dev_setup_null; - ppc_md.iommu_bus_setup = iommu_bus_setup_null; - - pci_dma_ops.alloc_coherent = bpa_alloc_coherent; - pci_dma_ops.free_coherent = bpa_free_coherent; - pci_dma_ops.map_single = bpa_map_single; - pci_dma_ops.unmap_single = bpa_unmap_single; - pci_dma_ops.map_sg = bpa_map_sg; - pci_dma_ops.unmap_sg = bpa_unmap_sg; - pci_dma_ops.dma_supported = bpa_dma_supported; -} --- linux-cg.orig/arch/ppc64/kernel/bpa_iommu.h 2005-09-01 02:37:40.912978360 -0400 +++ linux-cg/arch/ppc64/kernel/bpa_iommu.h 1969-12-31 19:00:00.000000000 -0500 @@ -1,65 +0,0 @@ -#ifndef BPA_IOMMU_H -#define BPA_IOMMU_H - -/* some constants */ -enum { - /* segment table entries */ - IOST_VALID_MASK = 0x8000000000000000ul, - IOST_TAG_MASK = 0x3000000000000000ul, - IOST_PT_BASE_MASK = 0x000003fffffff000ul, - IOST_NNPT_MASK = 0x0000000000000fe0ul, - IOST_PS_MASK = 0x000000000000000ful, - - IOST_PS_4K = 0x1, - IOST_PS_64K = 0x3, - IOST_PS_1M = 0x5, - IOST_PS_16M = 0x7, - - /* iopt tag register */ - IOPT_VALID_MASK = 0x0000000200000000ul, - IOPT_TAG_MASK = 0x00000001fffffffful, - - /* iopt cache register */ - IOPT_PROT_MASK = 0xc000000000000000ul, - IOPT_PROT_NONE = 0x0000000000000000ul, - IOPT_PROT_READ = 0x4000000000000000ul, - IOPT_PROT_WRITE = 0x8000000000000000ul, - IOPT_PROT_RW = 0xc000000000000000ul, - IOPT_COHERENT = 0x2000000000000000ul, - - IOPT_ORDER_MASK = 0x1800000000000000ul, - /* order access to same IOID/VC on same address */ - IOPT_ORDER_ADDR = 0x0800000000000000ul, - /* similar, but only after a write access */ - IOPT_ORDER_WRITES = 0x1000000000000000ul, - /* Order all accesses to same IOID/VC */ - IOPT_ORDER_VC = 0x1800000000000000ul, - - IOPT_RPN_MASK = 0x000003fffffff000ul, - IOPT_HINT_MASK = 0x0000000000000800ul, - IOPT_IOID_MASK = 0x00000000000007fful, - - IOSTO_ENABLE = 0x8000000000000000ul, - IOSTO_ORIGIN = 0x000003fffffff000ul, - IOSTO_HW = 0x0000000000000800ul, - IOSTO_SW = 0x0000000000000400ul, - - IOCMD_CONF_TE = 0x0000800000000000ul, - - /* memory mapped registers */ - IOC_PT_CACHE_DIR = 0x000, - IOC_ST_CACHE_DIR = 0x800, - IOC_PT_CACHE_REG = 0x910, - IOC_ST_ORIGIN = 0x918, - IOC_CONF = 0x930, - - /* The high bit needs to be set on every DMA address, - only 2GB are addressable */ - BPA_DMA_VALID = 0x80000000, - BPA_DMA_MASK = 0x7fffffff, -}; - - -void bpa_init_iommu(void); - -#endif --- linux-cg.orig/arch/ppc64/kernel/bpa_nvram.c 2005-09-01 02:37:40.914978056 -0400 +++ linux-cg/arch/ppc64/kernel/bpa_nvram.c 1969-12-31 19:00:00.000000000 -0500 @@ -1,118 +0,0 @@ -/* - * NVRAM for CPBW - * - * (C) Copyright IBM Corp. 2005 - * - * Authors : Utz Bacher - * - * 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, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include -#include -#include -#include -#include - -#include -#include -#include - -static void __iomem *bpa_nvram_start; -static long bpa_nvram_len; -static spinlock_t bpa_nvram_lock = SPIN_LOCK_UNLOCKED; - -static ssize_t bpa_nvram_read(char *buf, size_t count, loff_t *index) -{ - unsigned long flags; - - if (*index >= bpa_nvram_len) - return 0; - if (*index + count > bpa_nvram_len) - count = bpa_nvram_len - *index; - - spin_lock_irqsave(&bpa_nvram_lock, flags); - - memcpy_fromio(buf, bpa_nvram_start + *index, count); - - spin_unlock_irqrestore(&bpa_nvram_lock, flags); - - *index += count; - return count; -} - -static ssize_t bpa_nvram_write(char *buf, size_t count, loff_t *index) -{ - unsigned long flags; - - if (*index >= bpa_nvram_len) - return 0; - if (*index + count > bpa_nvram_len) - count = bpa_nvram_len - *index; - - spin_lock_irqsave(&bpa_nvram_lock, flags); - - memcpy_toio(bpa_nvram_start + *index, buf, count); - - spin_unlock_irqrestore(&bpa_nvram_lock, flags); - - *index += count; - return count; -} - -static ssize_t bpa_nvram_get_size(void) -{ - return bpa_nvram_len; -} - -int __init bpa_nvram_init(void) -{ - struct device_node *nvram_node; - unsigned long *buffer; - int proplen; - unsigned long nvram_addr; - int ret; - - ret = -ENODEV; - nvram_node = of_find_node_by_type(NULL, "nvram"); - if (!nvram_node) - goto out; - - ret = -EIO; - buffer = (unsigned long *)get_property(nvram_node, "reg", &proplen); - if (proplen != 2*sizeof(unsigned long)) - goto out; - - ret = -ENODEV; - nvram_addr = buffer[0]; - bpa_nvram_len = buffer[1]; - if ( (!bpa_nvram_len) || (!nvram_addr) ) - goto out; - - bpa_nvram_start = ioremap(nvram_addr, bpa_nvram_len); - if (!bpa_nvram_start) - goto out; - - printk(KERN_INFO "BPA NVRAM, %luk mapped to %p\n", - bpa_nvram_len >> 10, bpa_nvram_start); - - ppc_md.nvram_read = bpa_nvram_read; - ppc_md.nvram_write = bpa_nvram_write; - ppc_md.nvram_size = bpa_nvram_get_size; - -out: - of_node_put(nvram_node); - return ret; -} --- linux-cg.orig/arch/ppc64/kernel/bpa_setup.c 2005-09-01 02:37:40.917977600 -0400 +++ linux-cg/arch/ppc64/kernel/bpa_setup.c 1969-12-31 19:00:00.000000000 -0500 @@ -1,140 +0,0 @@ -/* - * linux/arch/ppc/kernel/bpa_setup.c - * - * Copyright (C) 1995 Linus Torvalds - * Adapted from 'alpha' version by Gary Thomas - * Modified by Cort Dougan (cort at cs.nmt.edu) - * Modified by PPC64 Team, IBM Corp - * Modified by BPA Team, IBM Deutschland Entwicklung GmbH - * - * 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. - */ -#undef DEBUG - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "pci.h" -#include "bpa_iic.h" -#include "bpa_iommu.h" - -#ifdef DEBUG -#define DBG(fmt...) udbg_printf(fmt) -#else -#define DBG(fmt...) -#endif - -void bpa_get_cpuinfo(struct seq_file *m) -{ - struct device_node *root; - const char *model = ""; - - root = of_find_node_by_path("/"); - if (root) - model = get_property(root, "model", NULL); - seq_printf(m, "machine\t\t: BPA %s\n", model); - of_node_put(root); -} - -static void bpa_progress(char *s, unsigned short hex) -{ - printk("*** %04x : %s\n", hex, s ? s : ""); -} - -static void __init bpa_setup_arch(void) -{ - ppc_md.init_IRQ = iic_init_IRQ; - ppc_md.get_irq = iic_get_irq; - -#ifdef CONFIG_SMP - smp_init_pSeries(); -#endif - - /* init to some ~sane value until calibrate_delay() runs */ - loops_per_jiffy = 50000000; - - if (ROOT_DEV == 0) { - printk("No ramdisk, default root is /dev/hda2\n"); - ROOT_DEV = Root_HDA2; - } - - /* Find and initialize PCI host bridges */ - init_pci_config_tokens(); - find_and_init_phbs(); - spider_init_IRQ(); -#ifdef CONFIG_DUMMY_CONSOLE - conswitchp = &dummy_con; -#endif - - bpa_nvram_init(); -} - -/* - * Early initialization. Relocation is on but do not reference unbolted pages - */ -static void __init bpa_init_early(void) -{ - DBG(" -> bpa_init_early()\n"); - - hpte_init_native(); - - bpa_init_iommu(); - - ppc64_interrupt_controller = IC_BPA_IIC; - - DBG(" <- bpa_init_early()\n"); -} - - -static int __init bpa_probe(int platform) -{ - if (platform != PLATFORM_BPA) - return 0; - - return 1; -} - -struct machdep_calls __initdata bpa_md = { - .probe = bpa_probe, - .setup_arch = bpa_setup_arch, - .init_early = bpa_init_early, - .get_cpuinfo = bpa_get_cpuinfo, - .restart = rtas_restart, - .power_off = rtas_power_off, - .halt = rtas_halt, - .get_boot_time = rtas_get_boot_time, - .get_rtc_time = rtas_get_rtc_time, - .set_rtc_time = rtas_set_rtc_time, - .calibrate_decr = generic_calibrate_decr, - .progress = bpa_progress, -}; --- linux-cg.orig/arch/ppc64/kernel/cpu_setup_power4.S 2005-09-01 02:37:44.101892936 -0400 +++ linux-cg/arch/ppc64/kernel/cpu_setup_power4.S 2005-09-01 02:37:49.128927440 -0400 @@ -77,7 +77,7 @@ _GLOBAL(__970_cpu_preinit) _GLOBAL(__setup_cpu_power4) blr -_GLOBAL(__setup_cpu_be) +_GLOBAL(__setup_cpu_cbe) /* Set large page sizes LP=0: 16MB, LP=1: 64KB */ addi r3, 0, 0 ori r3, r3, HID6_LB --- linux-cg.orig/arch/ppc64/kernel/cputable.c 2005-09-01 02:37:40.919977296 -0400 +++ linux-cg/arch/ppc64/kernel/cputable.c 2005-09-01 02:37:46.088990216 -0400 @@ -34,7 +34,7 @@ EXPORT_SYMBOL(cur_cpu_spec); extern void __setup_cpu_power3(unsigned long offset, struct cpu_spec* spec); extern void __setup_cpu_power4(unsigned long offset, struct cpu_spec* spec); extern void __setup_cpu_ppc970(unsigned long offset, struct cpu_spec* spec); -extern void __setup_cpu_be(unsigned long offset, struct cpu_spec* spec); +extern void __setup_cpu_cbe(unsigned long offset, struct cpu_spec* spec); /* We only set the altivec features if the kernel was compiled with altivec @@ -218,7 +218,7 @@ struct cpu_spec cpu_specs[] = { { /* BE DD1.x */ .pvr_mask = 0xffff0000, .pvr_value = 0x00700000, - .cpu_name = "Broadband Engine", + .cpu_name = "Cell Broadband Engine", .cpu_features = CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE | CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_ALTIVEC_COMP | @@ -227,7 +227,7 @@ struct cpu_spec cpu_specs[] = { PPC_FEATURE_HAS_ALTIVEC_COMP, .icache_bsize = 128, .dcache_bsize = 128, - .cpu_setup = __setup_cpu_be, + .cpu_setup = __setup_cpu_cbe, }, { /* default match */ .pvr_mask = 0x00000000, --- linux-cg.orig/arch/ppc64/kernel/irq.c 2005-09-01 02:37:40.921976992 -0400 +++ linux-cg/arch/ppc64/kernel/irq.c 2005-09-01 02:37:46.089990064 -0400 @@ -392,7 +392,7 @@ int virt_irq_create_mapping(unsigned int if (ppc64_interrupt_controller == IC_OPEN_PIC) return real_irq; /* no mapping for openpic (for now) */ - if (ppc64_interrupt_controller == IC_BPA_IIC) + if (ppc64_interrupt_controller == IC_CELL_PIC) return real_irq; /* no mapping for iic either */ /* don't map interrupts < MIN_VIRT_IRQ */ --- linux-cg.orig/arch/ppc64/kernel/pSeries_smp.c 2005-09-01 02:37:40.924976536 -0400 +++ linux-cg/arch/ppc64/kernel/pSeries_smp.c 2005-09-01 02:37:46.089990064 -0400 @@ -40,6 +40,7 @@ #include #include #include +#include #include #include #include @@ -48,7 +49,6 @@ #include #include "mpic.h" -#include "bpa_iic.h" #ifdef DEBUG #define DBG(fmt...) udbg_printf(fmt) @@ -464,7 +464,7 @@ void __init smp_init_pSeries(void) break; #endif #ifdef CONFIG_BPA_IIC - case IC_BPA_IIC: + case IC_CELL_PIC: smp_ops = &bpa_iic_smp_ops; break; #endif --- linux-cg.orig/arch/ppc64/kernel/setup.c 2005-09-01 02:37:40.926976232 -0400 +++ linux-cg/arch/ppc64/kernel/setup.c 2005-09-01 02:37:46.091989760 -0400 @@ -343,7 +343,7 @@ static void __init setup_cpu_maps(void) extern struct machdep_calls pSeries_md; extern struct machdep_calls pmac_md; extern struct machdep_calls maple_md; -extern struct machdep_calls bpa_md; +extern struct machdep_calls cell_md; /* Ultimately, stuff them in an elf section like initcalls... */ static struct machdep_calls __initdata *machines[] = { @@ -356,9 +356,9 @@ static struct machdep_calls __initdata * #ifdef CONFIG_PPC_MAPLE &maple_md, #endif /* CONFIG_PPC_MAPLE */ -#ifdef CONFIG_PPC_BPA - &bpa_md, -#endif +#ifdef CONFIG_PPC_CELL + &cell_md, +#endif /* CONFIG_PPC_CELL */ NULL }; --- linux-cg.orig/arch/ppc64/kernel/spider-pic.c 2005-09-01 02:37:40.928975928 -0400 +++ linux-cg/arch/ppc64/kernel/spider-pic.c 1969-12-31 19:00:00.000000000 -0500 @@ -1,191 +0,0 @@ -/* - * External Interrupt Controller on Spider South Bridge - * - * (C) Copyright IBM Deutschland Entwicklung GmbH 2005 - * - * Author: Arnd Bergmann - * - * 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, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include -#include - -#include -#include -#include - -#include "bpa_iic.h" - -/* register layout taken from Spider spec, table 7.4-4 */ -enum { - TIR_DEN = 0x004, /* Detection Enable Register */ - TIR_MSK = 0x084, /* Mask Level Register */ - TIR_EDC = 0x0c0, /* Edge Detection Clear Register */ - TIR_PNDA = 0x100, /* Pending Register A */ - TIR_PNDB = 0x104, /* Pending Register B */ - TIR_CS = 0x144, /* Current Status Register */ - TIR_LCSA = 0x150, /* Level Current Status Register A */ - TIR_LCSB = 0x154, /* Level Current Status Register B */ - TIR_LCSC = 0x158, /* Level Current Status Register C */ - TIR_LCSD = 0x15c, /* Level Current Status Register D */ - TIR_CFGA = 0x200, /* Setting Register A0 */ - TIR_CFGB = 0x204, /* Setting Register B0 */ - /* 0x208 ... 0x3ff Setting Register An/Bn */ - TIR_PPNDA = 0x400, /* Packet Pending Register A */ - TIR_PPNDB = 0x404, /* Packet Pending Register B */ - TIR_PIERA = 0x408, /* Packet Output Error Register A */ - TIR_PIERB = 0x40c, /* Packet Output Error Register B */ - TIR_PIEN = 0x444, /* Packet Output Enable Register */ - TIR_PIPND = 0x454, /* Packet Output Pending Register */ - TIRDID = 0x484, /* Spider Device ID Register */ - REISTIM = 0x500, /* Reissue Command Timeout Time Setting */ - REISTIMEN = 0x504, /* Reissue Command Timeout Setting */ - REISWAITEN = 0x508, /* Reissue Wait Control*/ -}; - -static void __iomem *spider_pics[4]; - -static void __iomem *spider_get_pic(int irq) -{ - int node = irq / IIC_NODE_STRIDE; - irq %= IIC_NODE_STRIDE; - - if (irq >= IIC_EXT_OFFSET && - irq < IIC_EXT_OFFSET + IIC_NUM_EXT && - spider_pics) - return spider_pics[node]; - return NULL; -} - -static int spider_get_nr(unsigned int irq) -{ - return (irq % IIC_NODE_STRIDE) - IIC_EXT_OFFSET; -} - -static void __iomem *spider_get_irq_config(int irq) -{ - void __iomem *pic; - pic = spider_get_pic(irq); - return pic + TIR_CFGA + 8 * spider_get_nr(irq); -} - -static void spider_enable_irq(unsigned int irq) -{ - void __iomem *cfg = spider_get_irq_config(irq); - irq = spider_get_nr(irq); - - out_be32(cfg, in_be32(cfg) | 0x3107000eu); - out_be32(cfg + 4, in_be32(cfg + 4) | 0x00020000u | irq); -} - -static void spider_disable_irq(unsigned int irq) -{ - void __iomem *cfg = spider_get_irq_config(irq); - irq = spider_get_nr(irq); - - out_be32(cfg, in_be32(cfg) & ~0x30000000u); -} - -static unsigned int spider_startup_irq(unsigned int irq) -{ - spider_enable_irq(irq); - return 0; -} - -static void spider_shutdown_irq(unsigned int irq) -{ - spider_disable_irq(irq); -} - -static void spider_end_irq(unsigned int irq) -{ - spider_enable_irq(irq); -} - -static void spider_ack_irq(unsigned int irq) -{ - spider_disable_irq(irq); - iic_local_enable(); -} - -static struct hw_interrupt_type spider_pic = { - .typename = " SPIDER ", - .startup = spider_startup_irq, - .shutdown = spider_shutdown_irq, - .enable = spider_enable_irq, - .disable = spider_disable_irq, - .ack = spider_ack_irq, - .end = spider_end_irq, -}; - - -int spider_get_irq(unsigned long int_pending) -{ - void __iomem *regs = spider_get_pic(int_pending); - unsigned long cs; - int irq; - - cs = in_be32(regs + TIR_CS); - - irq = cs >> 24; - if (irq != 63) - return irq; - - return -1; -} - -void spider_init_IRQ(void) -{ - int node; - struct device_node *dn; - unsigned int *property; - long spiderpic; - int n; - -/* FIXME: detect multiple PICs as soon as the device tree has them */ - for (node = 0; node < 1; node++) { - dn = of_find_node_by_path("/"); - n = prom_n_addr_cells(dn); - property = (unsigned int *) get_property(dn, - "platform-spider-pic", NULL); - - if (!property) - continue; - for (spiderpic = 0; n > 0; --n) - spiderpic = (spiderpic << 32) + *property++; - printk(KERN_DEBUG "SPIDER addr: %lx\n", spiderpic); - spider_pics[node] = __ioremap(spiderpic, 0x800, _PAGE_NO_CACHE); - for (n = 0; n < IIC_NUM_EXT; n++) { - int irq = n + IIC_EXT_OFFSET + node * IIC_NODE_STRIDE; - get_irq_desc(irq)->handler = &spider_pic; - - /* do not mask any interrupts because of level */ - out_be32(spider_pics[node] + TIR_MSK, 0x0); - - /* disable edge detection clear */ - /* out_be32(spider_pics[node] + TIR_EDC, 0x0); */ - - /* enable interrupt packets to be output */ - out_be32(spider_pics[node] + TIR_PIEN, - in_be32(spider_pics[node] + TIR_PIEN) | 0x1); - - /* Enable the interrupt detection enable bit. Do this last! */ - out_be32(spider_pics[node] + TIR_DEN, - in_be32(spider_pics[node] +TIR_DEN) | 0x1); - - } - } -} --- linux-cg.orig/arch/ppc64/kernel/traps.c 2005-09-01 02:37:40.931975472 -0400 +++ linux-cg/arch/ppc64/kernel/traps.c 2005-09-01 02:37:46.093989456 -0400 @@ -126,8 +126,8 @@ int die(const char *str, struct pt_regs printk("POWERMAC "); nl = 1; break; - case PLATFORM_BPA: - printk("BPA "); + case PLATFORM_CELL: + printk("CBEA "); nl = 1; break; } --- linux-cg.orig/include/asm-powerpc/cell-pic.h 1969-12-31 19:00:00.000000000 -0500 +++ linux-cg/include/asm-powerpc/cell-pic.h 2005-09-01 02:37:46.093989456 -0400 @@ -0,0 +1,62 @@ +#ifndef __ASM_CELL_PIC_H +#define __ASM_CELL_PIC_H +#ifdef __KERNEL__ +/* + * Mapping of IIC pending bits into per-node + * interrupt numbers. + * + * IRQ FF CC SS PP FF CC SS PP Description + * + * 00-3f 80 02 +0 00 - 80 02 +0 3f South Bridge + * 00-3f 80 02 +b 00 - 80 02 +b 3f South Bridge + * 41-4a 80 00 +1 ** - 80 00 +a ** SPU Class 0 + * 51-5a 80 01 +1 ** - 80 01 +a ** SPU Class 1 + * 61-6a 80 02 +1 ** - 80 02 +a ** SPU Class 2 + * 70-7f C0 ** ** 00 - C0 ** ** 0f IPI + * + * F flags + * C class + * S source + * P Priority + * + node number + * * don't care + * + * A node consists of a Cell Processor and an optional + * south bridge device providing a maximum of 64 IRQs. + * The south bridge may be connected to either IOIF0 + * or IOIF1. + * Each SPE is represented as three IRQ lines, one per + * interrupt class. + * 16 IRQ numbers are reserved for inter processor + * interruptions, although these are only used in the + * range of the first node. + * + * This scheme needs 128 IRQ numbers per BIF node ID, + * which means that with the total of 512 lines + * available, we can have a maximum of four nodes. + */ + +enum { + IIC_EXT_OFFSET = 0x00, /* Start of south bridge IRQs */ + IIC_NUM_EXT = 0x40, /* Number of south bridge IRQs */ + IIC_SPE_OFFSET = 0x40, /* Start of SPE interrupts */ + IIC_CLASS_STRIDE = 0x10, /* SPE IRQs per class */ + IIC_IPI_OFFSET = 0x70, /* Start of IPI IRQs */ + IIC_NUM_IPIS = 0x10, /* IRQs reserved for IPI */ + IIC_NODE_STRIDE = 0x80, /* Total IRQs per node */ +}; + +extern void iic_init_IRQ(void); +extern int iic_get_irq(struct pt_regs *regs); +extern void iic_cause_IPI(int cpu, int mesg); +extern void iic_request_IPIs(void); +extern void iic_setup_cpu(void); +extern void iic_local_enable(void); +extern void iic_local_disable(void); + + +extern void spider_init_IRQ(void); +extern int spider_get_irq(unsigned long int_pending); + +#endif /* __KERNEL__ */ +#endif /* __ASM_CELL_PIC_H */ --- linux-cg.orig/include/asm-ppc64/nvram.h 2005-09-01 02:37:40.935974864 -0400 +++ linux-cg/include/asm-ppc64/nvram.h 2005-09-01 02:37:46.094989304 -0400 @@ -70,7 +70,7 @@ extern struct nvram_partition *nvram_fin extern int pSeries_nvram_init(void); extern int pmac_nvram_init(void); -extern int bpa_nvram_init(void); +extern int cell_nvram_init(void); /* PowerMac specific nvram stuffs */ --- linux-cg.orig/include/asm-ppc64/processor.h 2005-09-01 02:37:40.938974408 -0400 +++ linux-cg/include/asm-ppc64/processor.h 2005-09-01 02:37:46.095989152 -0400 @@ -269,7 +269,7 @@ #define PV_630 0x0040 #define PV_630p 0x0041 #define PV_970MP 0x0044 -#define PV_BE 0x0070 +#define PV_CBE 0x0070 /* Platforms supported by PPC64 */ #define PLATFORM_PSERIES 0x0100 @@ -278,7 +278,8 @@ #define PLATFORM_LPAR 0x0001 #define PLATFORM_POWERMAC 0x0400 #define PLATFORM_MAPLE 0x0500 -#define PLATFORM_BPA 0x1000 +#define PLATFORM_CELL 0x1000 +#define PLATFORM_BPA PLATFORM_CELL /* Compatibility with drivers coming from PPC32 world */ #define _machine (systemcfg->platform) @@ -290,7 +291,7 @@ #define IC_INVALID 0 #define IC_OPEN_PIC 1 #define IC_PPC_XIC 2 -#define IC_BPA_IIC 3 +#define IC_CELL_PIC 3 #define XGLUE(a,b) a##b #define GLUE(a,b) XGLUE(a,b) _______________________________________________ Linuxppc64-dev mailing list Linuxppc64-dev at ozlabs.org https://ozlabs.org/mailman/listinfo/linuxppc64-dev From anton at samba.org Thu Sep 1 20:09:11 2005 From: anton at samba.org (Anton Blanchard) Date: Thu, 1 Sep 2005 20:09:11 +1000 Subject: [PATCH] Add PTRACE_{GET|SET}VRREGS In-Reply-To: References: Message-ID: <20050901100910.GA27213@krispykreme> Hi Rob, > The ptrace get and set methods for VMX/Altivec registers present in the > ppc tree were missing for ppc64. This patch adds the 32-bit and 64-bit > methods. Nice work. A couple of suggestions: 1. You need to call flush_altivec_to_thread(child) before reading or writing the altivec state. 2. It looks like vrsave will be read/written incorrectly: /* * Get/set all the altivec registers vr0..vr31, vscr, vrsave, in one go. * The transfer totals 34 quadword. Quadwords 0-31 contain the * corresponding vector registers. Quadword 32 contains the vscr as the * last word (offset 12) within that quadword. Quadword 33 contains the * vrsave as the first word (offset 0) within the quadword. * * This definition of the VMX state is compatible with the current PPC32 * ptrace interface. This allows signal handling and ptrace to use the * same * structures. This also simplifies the implementation of a bi-arch * (combined (32- and 64-bit) gdb. */ vrsave is a 64bit field in the ppc64 task struct (its only 32bit on ppc32). It might be safer to read all three parts separately, such as: unsigned long regsize; /* copy AltiVec registers VR[0] .. VR[31] */ regsize = 32 * sizeof(vector128); if (copy_from_user(task->thread.vr, data, regsize)) return -EFAULT; data += (regsize / sizeof(unsigned long)); /* copy VSCR */ regsize = 1 * sizeof(vector128); if (copy_from_user(&task->thread.vscr, data, regsize)) return -EFAULT; data += (regsize / sizeof(unsigned long)); /* copy VRSAVE */ if (get_user(task->thread.vrsave, (u32 __user *)data)) return -EFAULT; In this case we only grab 32bits of vrsave. Anton From anton at samba.org Thu Sep 1 23:57:14 2005 From: anton at samba.org (Anton Blanchard) Date: Thu, 1 Sep 2005 23:57:14 +1000 Subject: mainline breakage on POWER4 lpar Message-ID: <20050901135713.GA11064@krispykreme> Hi, Backing the patch below out makes POWER4 LPAR boot. I havent worked out why apart from noticing that boot_cpuid_phys was 0 when it should have been 1 which caused the xics code to get confused. Any ideas? Anton [PATCH] flattened device tree changes This patch updates the format of the flattened device-tree passed between the boot trampoline and the kernel to support a more compact representation, for use by embedded systems mostly. Signed-off-by: Benjamin Herrenschmidt Signed-off-by: Paul Mackerras --- --- a/arch/ppc64/kernel/prom.c +++ b/arch/ppc64/kernel/prom.c @@ -625,8 +625,8 @@ void __init finish_device_tree(void) static inline char *find_flat_dt_string(u32 offset) { - return ((char *)initial_boot_params) + initial_boot_params->off_dt_strings - + offset; + return ((char *)initial_boot_params) + + initial_boot_params->off_dt_strings + offset; } /** @@ -635,26 +635,33 @@ static inline char *find_flat_dt_string( * unflatten the tree */ static int __init scan_flat_dt(int (*it)(unsigned long node, - const char *full_path, void *data), + const char *uname, int depth, + void *data), void *data) { unsigned long p = ((unsigned long)initial_boot_params) + initial_boot_params->off_dt_struct; int rc = 0; + int depth = -1; do { u32 tag = *((u32 *)p); char *pathp; p += 4; - if (tag == OF_DT_END_NODE) + if (tag == OF_DT_END_NODE) { + depth --; + continue; + } + if (tag == OF_DT_NOP) continue; if (tag == OF_DT_END) break; if (tag == OF_DT_PROP) { u32 sz = *((u32 *)p); p += 8; - p = _ALIGN(p, sz >= 8 ? 8 : 4); + if (initial_boot_params->version < 0x10) + p = _ALIGN(p, sz >= 8 ? 8 : 4); p += sz; p = _ALIGN(p, 4); continue; @@ -664,9 +671,18 @@ static int __init scan_flat_dt(int (*it) " device tree !\n", tag); return -EINVAL; } + depth++; pathp = (char *)p; p = _ALIGN(p + strlen(pathp) + 1, 4); - rc = it(p, pathp, data); + if ((*pathp) == '/') { + char *lp, *np; + for (lp = NULL, np = pathp; *np; np++) + if ((*np) == '/') + lp = np+1; + if (lp != NULL) + pathp = lp; + } + rc = it(p, pathp, depth, data); if (rc != 0) break; } while(1); @@ -689,17 +705,21 @@ static void* __init get_flat_dt_prop(uns const char *nstr; p += 4; + if (tag == OF_DT_NOP) + continue; if (tag != OF_DT_PROP) return NULL; sz = *((u32 *)p); noff = *((u32 *)(p + 4)); p += 8; - p = _ALIGN(p, sz >= 8 ? 8 : 4); + if (initial_boot_params->version < 0x10) + p = _ALIGN(p, sz >= 8 ? 8 : 4); nstr = find_flat_dt_string(noff); if (nstr == NULL) { - printk(KERN_WARNING "Can't find property index name !\n"); + printk(KERN_WARNING "Can't find property index" + " name !\n"); return NULL; } if (strcmp(name, nstr) == 0) { @@ -713,7 +733,7 @@ static void* __init get_flat_dt_prop(uns } static void *__init unflatten_dt_alloc(unsigned long *mem, unsigned long size, - unsigned long align) + unsigned long align) { void *res; @@ -727,13 +747,16 @@ static void *__init unflatten_dt_alloc(u static unsigned long __init unflatten_dt_node(unsigned long mem, unsigned long *p, struct device_node *dad, - struct device_node ***allnextpp) + struct device_node ***allnextpp, + unsigned long fpsize) { struct device_node *np; struct property *pp, **prev_pp = NULL; char *pathp; u32 tag; - unsigned int l; + unsigned int l, allocl; + int has_name = 0; + int new_format = 0; tag = *((u32 *)(*p)); if (tag != OF_DT_BEGIN_NODE) { @@ -742,21 +765,62 @@ static unsigned long __init unflatten_dt } *p += 4; pathp = (char *)*p; - l = strlen(pathp) + 1; + l = allocl = strlen(pathp) + 1; *p = _ALIGN(*p + l, 4); - np = unflatten_dt_alloc(&mem, sizeof(struct device_node) + l, + /* version 0x10 has a more compact unit name here instead of the full + * path. we accumulate the full path size using "fpsize", we'll rebuild + * it later. We detect this because the first character of the name is + * not '/'. + */ + if ((*pathp) != '/') { + new_format = 1; + if (fpsize == 0) { + /* root node: special case. fpsize accounts for path + * plus terminating zero. root node only has '/', so + * fpsize should be 2, but we want to avoid the first + * level nodes to have two '/' so we use fpsize 1 here + */ + fpsize = 1; + allocl = 2; + } else { + /* account for '/' and path size minus terminal 0 + * already in 'l' + */ + fpsize += l; + allocl = fpsize; + } + } + + + np = unflatten_dt_alloc(&mem, sizeof(struct device_node) + allocl, __alignof__(struct device_node)); if (allnextpp) { memset(np, 0, sizeof(*np)); np->full_name = ((char*)np) + sizeof(struct device_node); - memcpy(np->full_name, pathp, l); + if (new_format) { + char *p = np->full_name; + /* rebuild full path for new format */ + if (dad && dad->parent) { + strcpy(p, dad->full_name); +#ifdef DEBUG + if ((strlen(p) + l + 1) != allocl) { + DBG("%s: p: %d, l: %d, a: %d\n", + pathp, strlen(p), l, allocl); + } +#endif + p += strlen(p); + } + *(p++) = '/'; + memcpy(p, pathp, l); + } else + memcpy(np->full_name, pathp, l); prev_pp = &np->properties; **allnextpp = np; *allnextpp = &np->allnext; if (dad != NULL) { np->parent = dad; - /* we temporarily use the `next' field as `last_child'. */ + /* we temporarily use the next field as `last_child'*/ if (dad->next == 0) dad->child = np; else @@ -770,18 +834,26 @@ static unsigned long __init unflatten_dt char *pname; tag = *((u32 *)(*p)); + if (tag == OF_DT_NOP) { + *p += 4; + continue; + } if (tag != OF_DT_PROP) break; *p += 4; sz = *((u32 *)(*p)); noff = *((u32 *)((*p) + 4)); - *p = _ALIGN((*p) + 8, sz >= 8 ? 8 : 4); + *p += 8; + if (initial_boot_params->version < 0x10) + *p = _ALIGN(*p, sz >= 8 ? 8 : 4); pname = find_flat_dt_string(noff); if (pname == NULL) { printk("Can't find property name in list !\n"); break; } + if (strcmp(pname, "name") == 0) + has_name = 1; l = strlen(pname) + 1; pp = unflatten_dt_alloc(&mem, sizeof(struct property), __alignof__(struct property)); @@ -801,6 +873,36 @@ static unsigned long __init unflatten_dt } *p = _ALIGN((*p) + sz, 4); } + /* with version 0x10 we may not have the name property, recreate + * it here from the unit name if absent + */ + if (!has_name) { + char *p = pathp, *ps = pathp, *pa = NULL; + int sz; + + while (*p) { + if ((*p) == '@') + pa = p; + if ((*p) == '/') + ps = p + 1; + p++; + } + if (pa < ps) + pa = p; + sz = (pa - ps) + 1; + pp = unflatten_dt_alloc(&mem, sizeof(struct property) + sz, + __alignof__(struct property)); + if (allnextpp) { + pp->name = "name"; + pp->length = sz; + pp->value = (unsigned char *)(pp + 1); + *prev_pp = pp; + prev_pp = &pp->next; + memcpy(pp->value, ps, sz - 1); + ((char *)pp->value)[sz - 1] = 0; + DBG("fixed up name for %s -> %s\n", pathp, pp->value); + } + } if (allnextpp) { *prev_pp = NULL; np->name = get_property(np, "name", NULL); @@ -812,7 +914,7 @@ static unsigned long __init unflatten_dt np->type = ""; } while (tag == OF_DT_BEGIN_NODE) { - mem = unflatten_dt_node(mem, p, np, allnextpp); + mem = unflatten_dt_node(mem, p, np, allnextpp, fpsize); tag = *((u32 *)(*p)); } if (tag != OF_DT_END_NODE) { @@ -842,21 +944,27 @@ void __init unflatten_device_tree(void) /* First pass, scan for size */ start = ((unsigned long)initial_boot_params) + initial_boot_params->off_dt_struct; - size = unflatten_dt_node(0, &start, NULL, NULL); + size = unflatten_dt_node(0, &start, NULL, NULL, 0); + size = (size | 3) + 1; DBG(" size is %lx, allocating...\n", size); /* Allocate memory for the expanded device tree */ - mem = (unsigned long)abs_to_virt(lmb_alloc(size, + mem = (unsigned long)abs_to_virt(lmb_alloc(size + 4, __alignof__(struct device_node))); + ((u32 *)mem)[size / 4] = 0xdeadbeef; + DBG(" unflattening...\n", mem); /* Second pass, do actual unflattening */ start = ((unsigned long)initial_boot_params) + initial_boot_params->off_dt_struct; - unflatten_dt_node(mem, &start, NULL, &allnextp); + unflatten_dt_node(mem, &start, NULL, &allnextp, 0); if (*((u32 *)start) != OF_DT_END) - printk(KERN_WARNING "Weird tag at end of tree: %x\n", *((u32 *)start)); + printk(KERN_WARNING "Weird tag at end of tree: %08x\n", *((u32 *)start)); + if (((u32 *)mem)[size / 4] != 0xdeadbeef) + printk(KERN_WARNING "End of tree marker overwritten: %08x\n", + ((u32 *)mem)[size / 4] ); *allnextp = NULL; /* Get pointer to OF "/chosen" node for use everywhere */ @@ -880,7 +988,7 @@ void __init unflatten_device_tree(void) static int __init early_init_dt_scan_cpus(unsigned long node, - const char *full_path, void *data) + const char *uname, int depth, void *data) { char *type = get_flat_dt_prop(node, "device_type", NULL); u32 *prop; @@ -947,13 +1055,15 @@ static int __init early_init_dt_scan_cpu } static int __init early_init_dt_scan_chosen(unsigned long node, - const char *full_path, void *data) + const char *uname, int depth, void *data) { u32 *prop; u64 *prop64; extern unsigned long memory_limit, tce_alloc_start, tce_alloc_end; - if (strcmp(full_path, "/chosen") != 0) + DBG("search \"chosen\", depth: %d, uname: %s\n", depth, uname); + + if (depth != 1 || strcmp(uname, "chosen") != 0) return 0; /* get platform type */ @@ -1003,18 +1113,20 @@ static int __init early_init_dt_scan_cho } static int __init early_init_dt_scan_root(unsigned long node, - const char *full_path, void *data) + const char *uname, int depth, void *data) { u32 *prop; - if (strcmp(full_path, "/") != 0) + if (depth != 0) return 0; prop = (u32 *)get_flat_dt_prop(node, "#size-cells", NULL); dt_root_size_cells = (prop == NULL) ? 1 : *prop; - + DBG("dt_root_size_cells = %x\n", dt_root_size_cells); + prop = (u32 *)get_flat_dt_prop(node, "#address-cells", NULL); dt_root_addr_cells = (prop == NULL) ? 2 : *prop; + DBG("dt_root_addr_cells = %x\n", dt_root_addr_cells); /* break now */ return 1; @@ -1042,7 +1154,7 @@ static unsigned long __init dt_mem_next_ static int __init early_init_dt_scan_memory(unsigned long node, - const char *full_path, void *data) + const char *uname, int depth, void *data) { char *type = get_flat_dt_prop(node, "device_type", NULL); cell_t *reg, *endp; @@ -1058,7 +1170,9 @@ static int __init early_init_dt_scan_mem endp = reg + (l / sizeof(cell_t)); - DBG("memory scan node %s ...\n", full_path); + DBG("memory scan node %s ..., reg size %ld, data: %x %x %x %x, ...\n", + uname, l, reg[0], reg[1], reg[2], reg[3]); + while ((endp - reg) >= (dt_root_addr_cells + dt_root_size_cells)) { unsigned long base, size; @@ -1469,10 +1583,11 @@ struct device_node *of_find_node_by_path struct device_node *np = allnodes; read_lock(&devtree_lock); - for (; np != 0; np = np->allnext) + for (; np != 0; np = np->allnext) { if (np->full_name != 0 && strcasecmp(np->full_name, path) == 0 && of_node_get(np)) break; + } read_unlock(&devtree_lock); return np; } --- a/arch/ppc64/kernel/prom_init.c +++ b/arch/ppc64/kernel/prom_init.c @@ -1534,7 +1534,8 @@ static unsigned long __init dt_find_stri */ #define MAX_PROPERTY_NAME 64 -static void __init scan_dt_build_strings(phandle node, unsigned long *mem_start, +static void __init scan_dt_build_strings(phandle node, + unsigned long *mem_start, unsigned long *mem_end) { unsigned long offset = reloc_offset(); @@ -1547,16 +1548,21 @@ static void __init scan_dt_build_strings /* get and store all property names */ prev_name = RELOC(""); for (;;) { - int rc; - /* 64 is max len of name including nul. */ namep = make_room(mem_start, mem_end, MAX_PROPERTY_NAME, 1); - rc = call_prom("nextprop", 3, 1, node, prev_name, namep); - if (rc != 1) { + if (call_prom("nextprop", 3, 1, node, prev_name, namep) != 1) { /* No more nodes: unwind alloc */ *mem_start = (unsigned long)namep; break; } + + /* skip "name" */ + if (strcmp(namep, RELOC("name")) == 0) { + *mem_start = (unsigned long)namep; + prev_name = RELOC("name"); + continue; + } + /* get/create string entry */ soff = dt_find_string(namep); if (soff != 0) { *mem_start = (unsigned long)namep; @@ -1571,7 +1577,7 @@ static void __init scan_dt_build_strings /* do all our children */ child = call_prom("child", 1, 1, node); - while (child != (phandle)0) { + while (child != 0) { scan_dt_build_strings(child, mem_start, mem_end); child = call_prom("peer", 1, 1, child); } @@ -1580,16 +1586,13 @@ static void __init scan_dt_build_strings static void __init scan_dt_build_struct(phandle node, unsigned long *mem_start, unsigned long *mem_end) { - int l, align; phandle child; - char *namep, *prev_name, *sstart, *p, *ep; + char *namep, *prev_name, *sstart, *p, *ep, *lp, *path; unsigned long soff; unsigned char *valp; unsigned long offset = reloc_offset(); - char pname[MAX_PROPERTY_NAME]; - char *path; - - path = RELOC(prom_scratch); + static char pname[MAX_PROPERTY_NAME]; + int l; dt_push_token(OF_DT_BEGIN_NODE, mem_start, mem_end); @@ -1599,23 +1602,33 @@ static void __init scan_dt_build_struct( namep, *mem_end - *mem_start); if (l >= 0) { /* Didn't fit? Get more room. */ - if (l+1 > *mem_end - *mem_start) { + if ((l+1) > (*mem_end - *mem_start)) { namep = make_room(mem_start, mem_end, l+1, 1); call_prom("package-to-path", 3, 1, node, namep, l); } namep[l] = '\0'; + /* Fixup an Apple bug where they have bogus \0 chars in the * middle of the path in some properties */ for (p = namep, ep = namep + l; p < ep; p++) if (*p == '\0') { memmove(p, p+1, ep - p); - ep--; l--; + ep--; l--; p--; } - *mem_start = _ALIGN(((unsigned long) namep) + strlen(namep) + 1, 4); + + /* now try to extract the unit name in that mess */ + for (p = namep, lp = NULL; *p; p++) + if (*p == '/') + lp = p + 1; + if (lp != NULL) + memmove(namep, lp, strlen(lp) + 1); + *mem_start = _ALIGN(((unsigned long) namep) + + strlen(namep) + 1, 4); } /* get it again for debugging */ + path = RELOC(prom_scratch); memset(path, 0, PROM_SCRATCH_SIZE); call_prom("package-to-path", 3, 1, node, path, PROM_SCRATCH_SIZE-1); @@ -1623,23 +1636,27 @@ static void __init scan_dt_build_struct( prev_name = RELOC(""); sstart = (char *)RELOC(dt_string_start); for (;;) { - int rc; - - rc = call_prom("nextprop", 3, 1, node, prev_name, pname); - if (rc != 1) + if (call_prom("nextprop", 3, 1, node, prev_name, + RELOC(pname)) != 1) break; + /* skip "name" */ + if (strcmp(RELOC(pname), RELOC("name")) == 0) { + prev_name = RELOC("name"); + continue; + } + /* find string offset */ - soff = dt_find_string(pname); + soff = dt_find_string(RELOC(pname)); if (soff == 0) { - prom_printf("WARNING: Can't find string index for <%s>, node %s\n", - pname, path); + prom_printf("WARNING: Can't find string index for" + " <%s>, node %s\n", RELOC(pname), path); break; } prev_name = sstart + soff; /* get length */ - l = call_prom("getproplen", 2, 1, node, pname); + l = call_prom("getproplen", 2, 1, node, RELOC(pname)); /* sanity checks */ if (l == PROM_ERROR) @@ -1648,7 +1665,7 @@ static void __init scan_dt_build_struct( prom_printf("WARNING: ignoring large property "); /* It seems OF doesn't null-terminate the path :-( */ prom_printf("[%s] ", path); - prom_printf("%s length 0x%x\n", pname, l); + prom_printf("%s length 0x%x\n", RELOC(pname), l); continue; } @@ -1658,17 +1675,16 @@ static void __init scan_dt_build_struct( dt_push_token(soff, mem_start, mem_end); /* push property content */ - align = (l >= 8) ? 8 : 4; - valp = make_room(mem_start, mem_end, l, align); - call_prom("getprop", 4, 1, node, pname, valp, l); + valp = make_room(mem_start, mem_end, l, 4); + call_prom("getprop", 4, 1, node, RELOC(pname), valp, l); *mem_start = _ALIGN(*mem_start, 4); } /* Add a "linux,phandle" property. */ soff = dt_find_string(RELOC("linux,phandle")); if (soff == 0) - prom_printf("WARNING: Can't find string index for " - " node %s\n", path); + prom_printf("WARNING: Can't find string index for" + " node %s\n", path); else { dt_push_token(OF_DT_PROP, mem_start, mem_end); dt_push_token(4, mem_start, mem_end); @@ -1679,7 +1695,7 @@ static void __init scan_dt_build_struct( /* do all our children */ child = call_prom("child", 1, 1, node); - while (child != (phandle)0) { + while (child != 0) { scan_dt_build_struct(child, mem_start, mem_end); child = call_prom("peer", 1, 1, child); } @@ -1718,7 +1734,8 @@ static void __init flatten_device_tree(v /* Build header and make room for mem rsv map */ mem_start = _ALIGN(mem_start, 4); - hdr = make_room(&mem_start, &mem_end, sizeof(struct boot_param_header), 4); + hdr = make_room(&mem_start, &mem_end, + sizeof(struct boot_param_header), 4); RELOC(dt_header_start) = (unsigned long)hdr; rsvmap = make_room(&mem_start, &mem_end, sizeof(mem_reserve_map), 8); @@ -1731,11 +1748,11 @@ static void __init flatten_device_tree(v namep = make_room(&mem_start, &mem_end, 16, 1); strcpy(namep, RELOC("linux,phandle")); mem_start = (unsigned long)namep + strlen(namep) + 1; - RELOC(dt_string_end) = mem_start; /* Build string array */ prom_printf("Building dt strings...\n"); scan_dt_build_strings(root, &mem_start, &mem_end); + RELOC(dt_string_end) = mem_start; /* Build structure */ mem_start = PAGE_ALIGN(mem_start); @@ -1750,9 +1767,11 @@ static void __init flatten_device_tree(v hdr->totalsize = RELOC(dt_struct_end) - RELOC(dt_header_start); hdr->off_dt_struct = RELOC(dt_struct_start) - RELOC(dt_header_start); hdr->off_dt_strings = RELOC(dt_string_start) - RELOC(dt_header_start); + hdr->dt_strings_size = RELOC(dt_string_end) - RELOC(dt_string_start); hdr->off_mem_rsvmap = ((unsigned long)rsvmap) - RELOC(dt_header_start); hdr->version = OF_DT_VERSION; - hdr->last_comp_version = 1; + /* Version 16 is not backward compatible */ + hdr->last_comp_version = 0x10; /* Reserve the whole thing and copy the reserve map in, we * also bump mem_reserve_cnt to cause further reservations to @@ -1808,6 +1827,9 @@ static void __init fixup_device_tree(voi /* does it need fixup ? */ if (prom_getproplen(i2c, "interrupts") > 0) return; + + prom_printf("fixing up bogus interrupts for u3 i2c...\n"); + /* interrupt on this revision of u3 is number 0 and level */ interrupts[0] = 0; interrupts[1] = 1; --- a/include/asm-ppc64/prom.h +++ b/include/asm-ppc64/prom.h @@ -22,13 +22,15 @@ #define RELOC(x) (*PTRRELOC(&(x))) /* Definitions used by the flattened device tree */ -#define OF_DT_HEADER 0xd00dfeed /* 4: version, 4: total size */ -#define OF_DT_BEGIN_NODE 0x1 /* Start node: full name */ +#define OF_DT_HEADER 0xd00dfeed /* marker */ +#define OF_DT_BEGIN_NODE 0x1 /* Start of node, full name */ #define OF_DT_END_NODE 0x2 /* End node */ -#define OF_DT_PROP 0x3 /* Property: name off, size, content */ +#define OF_DT_PROP 0x3 /* Property: name off, size, + * content */ +#define OF_DT_NOP 0x4 /* nop */ #define OF_DT_END 0x9 -#define OF_DT_VERSION 1 +#define OF_DT_VERSION 0x10 /* * This is what gets passed to the kernel by prom_init or kexec @@ -54,7 +56,9 @@ struct boot_param_header u32 version; /* format version */ u32 last_comp_version; /* last compatible version */ /* version 2 fields below */ - u32 boot_cpuid_phys; /* Which physical CPU id we're booting on */ + u32 boot_cpuid_phys; /* Physical CPU id we're booting on */ + /* version 3 fields below */ + u32 dt_strings_size; /* size of the DT strings block */ }; From kumar.gala at freescale.com Fri Sep 2 00:11:38 2005 From: kumar.gala at freescale.com (Kumar Gala) Date: Thu, 1 Sep 2005 09:11:38 -0500 Subject: [PATCH,RFC] Move Cell platform code to arch/powerpc In-Reply-To: <200509010247.07399.arnd@arndb.de> References: <200509010247.07399.arnd@arndb.de> Message-ID: <8E11258A-70AD-4285-962E-797F7A3D55E3@freescale.com> On Aug 31, 2005, at 7:47 PM, Arnd Bergmann wrote: > Move all files from arch/ppc64/kernel/bpa_* to arch/powerpc/ > platforms/cell, > > I would like to see a patch like this go into 2.6.14, for multiple > reasons: > > - The marketing folks have changed the names and we are no longer > supposed > to refer to Cell as 'BPA' or 'Broadband Processor Architecture'. > The platform is officially known as 'Cell Broadband Engine > Architecture', > while the CPU is the 'Cell Broadband Engine'. > > - We are now moving all platforms into arch/powerpc/platforms and > someone > has to start so we get a template for the other architectures to > follow. > > - It would be a big mess for me to maintain my own patches on top > of file > names that are different from mainline during the 2.6.14 freeze. > > My impression is that Cell is a good target for moving first, > because I > have to move it anyway and the number of users is extremely low, so it > doesn't cause too much harm if we screw up. What thing that makes > moving > Cell relatively easy is that it only supports 64 bit and only a single > hardware configuration so far. > > I have tested this a bit on Cell and also done compile-only test > for the > other platforms, but it doesn't really make any changes to the code > itself. > > Please comment on wether this is what everybody like the merge process > be like. I'm not 100% sure if this is the right time for introducing a platform into arch/powerpc. My concern is around that fact that we have not tried to move any "code" from arch/ppc or arch/ppc64 into arch/powerpc and so havent figured out how we are going to do that will not breaking arch/ppc & arch/ppc64. By introducing cell this way we create a dependency between ppc64 and powerpc that might constrain decisions we want to make. > Signed-off-by: Arnd Bergmann > > -- > arch/powerpc/platforms/cell/Makefile | 1 > arch/ppc64/kernel/Makefile | 5 > arch/powerpc/platforms/cell/pic.c | 269 +++++++++++++++++++ > +++ > arch/ppc64/kernel/bpa_iic.c | 270 > ---------------------- > include/asm-powerpc/cell-pic.h | 62 +++++ > arch/ppc64/kernel/bpa_iic.h | 62 ----- > arch/powerpc/platforms/cell/iommu.c | 377 +++++++++++++++++++ > ++++++++++++ > arch/ppc64/kernel/bpa_iommu.c | 377 > ------------------------------- > arch/powerpc/platforms/cell/iommu.h | 65 +++++ > arch/ppc64/kernel/bpa_iommu.h | 65 ----- > arch/powerpc/platforms/cell/nvram.c | 118 +++++++++ > arch/ppc64/kernel/bpa_nvram.c | 118 --------- Should pic, iommu, and nvram really be in arch/powerpc/sysdev/ Also, since your renaming things any chance there is a better name for iic? (just wondering since its way to similar to what some people use for I2C). > arch/powerpc/platforms/cell/setup.c | 138 +++++++++++ > arch/ppc64/kernel/bpa_setup.c | 140 ----------- > arch/powerpc/platforms/cell/spider-pic.c | 190 +++++++++++++++ > arch/ppc64/kernel/spider-pic.c | 191 --------------- > arch/ppc64/Kconfig | 10 > arch/ppc64/kernel/cpu_setup_power4.S | 2 > arch/ppc64/kernel/cputable.c | 6 > arch/ppc64/kernel/irq.c | 2 > arch/ppc64/kernel/pSeries_smp.c | 4 > arch/ppc64/kernel/setup.c | 8 > arch/ppc64/kernel/traps.c | 4 > include/asm-ppc64/nvram.h | 2 > include/asm-ppc64/processor.h | 7 > 25 files changed, 1248 insertions(+), 1245 deletions(-) From kumar.gala at freescale.com Fri Sep 2 00:28:34 2005 From: kumar.gala at freescale.com (Kumar Gala) Date: Thu, 1 Sep 2005 09:28:34 -0500 Subject: [PATCH] Add PTRACE_{GET|SET}VRREGS In-Reply-To: <20050901100910.GA27213@krispykreme> References: <20050901100910.GA27213@krispykreme> Message-ID: <809E47E8-75D8-41F1-9DB3-8D440C8F6B64@freescale.com> On Sep 1, 2005, at 5:09 AM, Anton Blanchard wrote: > > Hi Rob, > > >> The ptrace get and set methods for VMX/Altivec registers present in >> > the > >> ppc tree were missing for ppc64. This patch adds the 32-bit and >> > 64-bit > >> methods. >> > > Nice work. A couple of suggestions: > > 1. You need to call flush_altivec_to_thread(child) before reading or > writing the altivec state. > > 2. It looks like vrsave will be read/written incorrectly: > > /* > * Get/set all the altivec registers vr0..vr31, vscr, vrsave, in > one go. > * The transfer totals 34 quadword. Quadwords 0-31 contain the > * corresponding vector registers. Quadword 32 contains the vscr > as the > * last word (offset 12) within that quadword. Quadword 33 > contains the > * vrsave as the first word (offset 0) within the quadword. > * > * This definition of the VMX state is compatible with the current > PPC32 > * ptrace interface. This allows signal handling and ptrace to use > the > * same > * structures. This also simplifies the implementation of a bi-arch > * (combined (32- and 64-bit) gdb. > */ > > vrsave is a 64bit field in the ppc64 task struct (its only 32bit on > ppc32). It might be safer to read all three parts separately, such as: Is vrsave really a 64-bit register in ppc64? If not can we make it be a 32-bit quantity on ppc64 to simplify our lives later. - kumar From arnd at arndb.de Fri Sep 2 01:00:17 2005 From: arnd at arndb.de (Arnd Bergmann) Date: Thu, 1 Sep 2005 17:00:17 +0200 Subject: [PATCH,RFC] Move Cell platform code to arch/powerpc In-Reply-To: References: Message-ID: <200509011700.20759.arnd@arndb.de> On Dunnersdag 01 September 2005 06:22, Murali N Iyer wrote: > Architecture "cell" seems to be fine. What is your thought on supporting > multiple different hardware configurations under cell. I think this patch > has been tested only in CPBW hardware. ?For example "+++ My general idea about future Cell based products is that we make the changes to the platform code at the time we add new code. Of course, a number of companies are working on designs that I have no insight in, so I'll just wait what comes, but at least I've tried to make it easy to add the stuff that I know about. > linux-cg/arch/ppc64/kernel/bpa_nvram.c" assumes one particular hardware > which may not be true for different hardware configurations. Yes, this one is a bit odd. On the one hand, it is very generic and could be used for any future open firmware or flat device tree based system (even non-PowerPC). On the other hand, it works only on one particular board design currently. I don't really care about where this is put, ranging from: arch/{ppc64,powerpc}/kernel/of_nvram.c, meaning that everyone using the flat device tree can just add an "nvram" node that will work with this driver. arch/powerpc/platforms/cell/cellblade_nvram.c, to keep it specific to the one design that we have, assuming that future Cell based designs will use something else. Arnd <>< From arnd at arndb.de Fri Sep 2 01:40:50 2005 From: arnd at arndb.de (Arnd Bergmann) Date: Thu, 1 Sep 2005 17:40:50 +0200 Subject: [PATCH,RFC] Move Cell platform code to arch/powerpc In-Reply-To: <8E11258A-70AD-4285-962E-797F7A3D55E3@freescale.com> References: <200509010247.07399.arnd@arndb.de> <8E11258A-70AD-4285-962E-797F7A3D55E3@freescale.com> Message-ID: <200509011740.51484.arnd@arndb.de> On Dunnersdag 01 September 2005 16:11, Kumar Gala wrote: > I'm not 100% sure if this is the right time for introducing a > platform into arch/powerpc. My concern is around that fact that we > have not tried to move any "code" from arch/ppc or arch/ppc64 into > arch/powerpc and so havent figured out how we are going to do that > will not breaking arch/ppc & arch/ppc64. By introducing cell this > way we create a dependency between ppc64 and powerpc that might > constrain decisions we want to make. I understand that there are good reasons for merging all the headers first and only then start with the architecture code, that also was my idea at first. At least from the Kbuild side, it should not cause trouble to refer to different architecture directories from arch/ppc64/kernel/Makefile, that does not introduce any strong dependency. For the code itself, we probably need to make substantial changes at some point, e.g. when we merge arch/powerpc/kernel/setup.c. However, I don't think it makes much difference wether that is done while the code resides in arch/ppc64 or arch/powerpc. > > Signed-off-by: Arnd Bergmann > > > > -- > > arch/powerpc/platforms/cell/Makefile | 1 > > arch/ppc64/kernel/Makefile | 5 > > arch/powerpc/platforms/cell/pic.c | 269 ++++++++++++++++++++++ > > arch/ppc64/kernel/bpa_iic.c | 270 ---------------------- > > include/asm-powerpc/cell-pic.h | 62 +++++ > > arch/ppc64/kernel/bpa_iic.h | 62 ----- > > arch/powerpc/platforms/cell/iommu.c | 377 +++++++++++++++++++++++++++++++ > > arch/ppc64/kernel/bpa_iommu.c | 377 ------------------------------- > > arch/powerpc/platforms/cell/iommu.h | 65 +++++ > > arch/ppc64/kernel/bpa_iommu.h | 65 ----- > > arch/powerpc/platforms/cell/nvram.c | 118 +++++++++ > > arch/ppc64/kernel/bpa_nvram.c | 118 --------- > > Should pic, iommu, and nvram really be in arch/powerpc/sysdev/ The pic and iommu are defined in the CBE Architecture documents and different from all others, so I would prefer to keep them here. Both the internal interrupt controller (IIC) and the IO page tables are part of the CPU itself, so you will always see them together with Cell based hardware. For nvram, you are probably right that it belongs to a more generic place, as I just wrote in my reply to Murali. With regard to the arch/powerpc/sysdev/ location for putting the drivers, I'm not sure if we should first find a better definition of what goes in there. I remember that some people did not like the current split between arch/ppc/kernel and arch/ppc/syslib. Do you think of arch/powerpc/sysdev/ as a different thing from the current syslib (e.g. stuff using include/linux/sysdev.h), or just a different name for the same thing? > Also, since your renaming things any chance there is a better name > for iic? (just wondering since its way to similar to what some people > use for I2C). Yes, Ben has expressed the same concern to me, therefore I have renamed the file to 'pic' instead of 'iic'. However, the architecture is very specifically calling it IIC, so my idea was to keep the identifiers with that name, hoping that this does not cause trouble when the files are clearly marked as belonging to one specific platform. If you have a better idea for naming it, I can change it of course. Arnd <>< From segher at kernel.crashing.org Fri Sep 2 01:47:09 2005 From: segher at kernel.crashing.org (Segher Boessenkool) Date: Thu, 1 Sep 2005 17:47:09 +0200 Subject: [PATCH] Add PTRACE_{GET|SET}VRREGS In-Reply-To: <809E47E8-75D8-41F1-9DB3-8D440C8F6B64@freescale.com> References: <20050901100910.GA27213@krispykreme> <809E47E8-75D8-41F1-9DB3-8D440C8F6B64@freescale.com> Message-ID: > Is vrsave really a 64-bit register in ppc64? If not can we make it be > a 32-bit quantity on ppc64 to simplify our lives later. Architecturally it is 32-bit. Segher From kumar.gala at freescale.com Fri Sep 2 01:50:48 2005 From: kumar.gala at freescale.com (Kumar Gala) Date: Thu, 1 Sep 2005 10:50:48 -0500 Subject: [PATCH] Add PTRACE_{GET|SET}VRREGS In-Reply-To: References: Message-ID: On Sep 1, 2005, at 10:47 AM, Segher Boessenkool wrote: >> Is vrsave really a 64-bit register in ppc64? If not can we make >> it be >> > > >> a 32-bit quantity on ppc64 to simplify our lives later. >> > > Architecturally it is 32-bit. If that's the case I would really like to see the patches also fixup thread_struct to make vrsave a u32 instead of unsigned long on ppc64. We are going to have to do this sooner or later, might as well make it sooner. - kumar From jimix at watson.ibm.com Fri Sep 2 01:57:10 2005 From: jimix at watson.ibm.com (Jimi Xenidis) Date: Thu, 1 Sep 2005 11:57:10 -0400 Subject: [PATCH] systemcfg is now a pointer Message-ID: <17175.9430.831277.41595@kitch0.watson.ibm.com> This is a resend, better explaination. The following patch "fixes" 2 issues: 1) use PLATFORM_LPAR bit to test if running in LPAR mode 2) systemcfg pointer is assigned from static data in arch/ppc64/kernel/pacaData.c. The file arch/ppc64/kernel/head.S now refers to is using the GOT binding to the pointer and hence must deref it. let me know if you'd like separate diffs. Signed-off-by: Jimi Xenidis diff -r e783ced09546 arch/ppc64/kernel/head.S --- a/arch/ppc64/kernel/head.S Thu Aug 18 22:16:12 2005 +++ b/arch/ppc64/kernel/head.S Sat Aug 20 12:10:24 2005 @@ -1753,8 +1753,9 @@ #else /* set the ASR */ ld r3,systemcfg at got(r2) /* r3 = ptr to systemcfg */ + ld r3,0(r3) lwz r3,PLATFORM(r3) /* r3 = platform flags */ - cmpldi r3,PLATFORM_PSERIES_LPAR + andi. r3,r3,PLATFORM_LPAR /* Test if bit 0 is set (LPAR bit) */ bne 98f mfspr r3,PVR srwi r3,r3,16 @@ -1916,8 +1917,9 @@ ld r3,PACASTABREAL(r13) ori r4,r3,1 /* turn on valid bit */ ld r3,systemcfg at got(r2) /* r3 = ptr to systemcfg */ + ld r3,0(r3) lwz r3,PLATFORM(r3) /* r3 = platform flags */ - cmpldi r3,PLATFORM_PSERIES_LPAR + andi. r3,r3,PLATFORM_LPAR /* Test if bit 0 is set (LPAR bit) */ bne 98f mfspr r3,PVR srwi r3,r3,16 @@ -1935,9 +1937,10 @@ 99: /* Set SDR1 (hash table pointer) */ ld r3,systemcfg at got(r2) /* r3 = ptr to systemcfg */ + ld r3,0(r3) lwz r3,PLATFORM(r3) /* r3 = platform flags */ /* Test if bit 0 is set (LPAR bit) */ - andi. r3,r3,0x1 + andi. r3,r3,PLATFORM_LPAR bne 98f LOADADDR(r6,_SDR1) /* Only if NOT LPAR */ sub r6,r6,r26 From msdemlei at cl.uni-heidelberg.de Fri Sep 2 02:25:40 2005 From: msdemlei at cl.uni-heidelberg.de (Markus Demleitner) Date: Thu, 1 Sep 2005 18:25:40 +0200 Subject: iMac G5 Temperature control revisited Message-ID: <20050901162540.GE9309@victor.rh.local> Hi, A while ago, benh posted a patch to improve SMU support on iMac G5s, see http://ozlabs.org/pipermail/linuxppc64-dev/2005-April/003835.html I didn't really get to try it till now, but it still applies cleanly to 2.6.13, which was a severe blow to my hopes someone else might step in and improve iMac G5 support. Now, for the benefit of others that might want to run linux on the iMac G5, here's a quick hack that uses the above interface for fan control. It's more of a testbed but should work (you should comment out the printks in benh's smu driver, though, if you run it for extended periods of time). It's a python script you can dump into /etc/init.d and then use as you'd use other init scripts. In case anyone else still uses the horrible g5-fanctl module I wrote in April: Upgrading is worth it, benh's new asynchronous SMU interface brings the CPU load of the temperature control down to basically naught. Here's the URL: http://tucana.cl.uni-heidelberg.de/homepage/hacks/simpleTemp Let me know if you use this script, because if others do (or want to), I might actually write some docs. I may give an in-kernel solution a shot, but given that I know nothing about kernel-threads it's not likely right now -- if I find time to hack on the kernel, I'd first like to get sound working and then CPU frequency scaling. Hints and tips regarding those two issues welcome and solicited... Cheers, Markus From jdl at freescale.com Fri Sep 2 06:51:52 2005 From: jdl at freescale.com (Jon Loeliger) Date: Thu, 01 Sep 2005 15:51:52 -0500 Subject: PATCH Merge more include files Message-ID: <1125607912.16685.111.camel@cashmere.sps.mot.com> This patch merges several include files from asm-ppc and asm-ppc64 into the new asm-powerpc. Signed-off-by: Jon Loeliger Signed-off-by: Kumar Gala --- include/asm-powerpc/bugs.h | 18 +++++++++ include/asm-powerpc/kmap_types.h | 32 +++++++++++++++ include/asm-powerpc/mc146818rtc.h | 36 +++++++++++++++++ include/asm-powerpc/module.h | 77 +++++++++++++++++++++++++++++++++++++ include/asm-powerpc/sembuf.h | 36 +++++++++++++++++ include/asm-powerpc/shmbuf.h | 59 ++++++++++++++++++++++++++++ include/asm-powerpc/siginfo.h | 18 +++++++++ include/asm-powerpc/socket.h | 59 ++++++++++++++++++++++++++++ include/asm-powerpc/sockios.h | 19 +++++++++ include/asm-ppc/bugs.h | 6 --- include/asm-ppc/kmap_types.h | 24 ------------ include/asm-ppc/mc146818rtc.h | 31 --------------- include/asm-ppc/module.h | 44 --------------------- include/asm-ppc/sembuf.h | 19 --------- include/asm-ppc/shmbuf.h | 37 ------------------ include/asm-ppc/siginfo.h | 6 --- include/asm-ppc/socket.h | 58 ---------------------------- include/asm-ppc/sockios.h | 17 -------- include/asm-ppc64/bugs.h | 12 ------ include/asm-ppc64/kmap_types.h | 23 ----------- include/asm-ppc64/mc146818rtc.h | 32 --------------- include/asm-ppc64/module.h | 36 ----------------- include/asm-ppc64/sembuf.h | 27 ------------- include/asm-ppc64/shmbuf.h | 43 --------------------- include/asm-ppc64/siginfo.h | 16 -------- include/asm-ppc64/socket.h | 59 ---------------------------- include/asm-ppc64/sockios.h | 19 --------- 27 files changed, 354 insertions(+), 509 deletions(-) diff --git a/include/asm-powerpc/bugs.h b/include/asm-powerpc/bugs.h new file mode 100644 --- /dev/null +++ b/include/asm-powerpc/bugs.h @@ -0,0 +1,18 @@ +#ifndef _POWERPC_BUGS_H +#define _POWERPC_BUGS_H + +/* + * 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 file is included by 'init/main.c' to check for + * architecture-dependent bugs. + */ + +extern void check_bugs(void); + +#endif /* _POWERPC_BUGS_H */ diff --git a/include/asm-powerpc/kmap_types.h b/include/asm-powerpc/kmap_types.h new file mode 100644 --- /dev/null +++ b/include/asm-powerpc/kmap_types.h @@ -0,0 +1,32 @@ +#ifndef _POWERPC_KMAP_TYPES_H +#define _POWERPC_KMAP_TYPES_H + +#ifdef __KERNEL__ + +/* + * 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. + */ + +enum km_type { + KM_BOUNCE_READ, + KM_SKB_SUNRPC_DATA, + KM_SKB_DATA_SOFTIRQ, + KM_USER0, + KM_USER1, + KM_BIO_SRC_IRQ, + KM_BIO_DST_IRQ, + KM_PTE0, + KM_PTE1, + KM_IRQ0, + KM_IRQ1, + KM_SOFTIRQ0, + KM_SOFTIRQ1, + KM_PPC_SYNC_PAGE, + KM_TYPE_NR +}; + +#endif /* __KERNEL__ */ +#endif /* _POWERPC_KMAP_TYPES_H */ diff --git a/include/asm-powerpc/mc146818rtc.h b/include/asm-powerpc/mc146818rtc.h new file mode 100644 --- /dev/null +++ b/include/asm-powerpc/mc146818rtc.h @@ -0,0 +1,36 @@ +#ifndef _POWERPC_MC146818RTC_H +#define _POWERPC_MC146818RTC_H + +/* + * Machine dependent access functions for RTC registers. + * + * 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. + */ + +#ifdef __KERNEL__ + +#include + +#ifndef RTC_PORT +#define RTC_PORT(x) (0x70 + (x)) +#define RTC_ALWAYS_BCD 1 /* RTC operates in binary mode */ +#endif + +/* + * The yet supported machines all access the RTC index register via + * an ISA port access but the way to access the date register differs ... + */ +#define CMOS_READ(addr) ({ \ +outb_p((addr),RTC_PORT(0)); \ +inb_p(RTC_PORT(1)); \ +}) +#define CMOS_WRITE(val, addr) ({ \ +outb_p((addr),RTC_PORT(0)); \ +outb_p((val),RTC_PORT(1)); \ +}) + +#endif /* __KERNEL__ */ +#endif /* _POWERPC_MC146818RTC_H */ diff --git a/include/asm-powerpc/module.h b/include/asm-powerpc/module.h new file mode 100644 --- /dev/null +++ b/include/asm-powerpc/module.h @@ -0,0 +1,77 @@ +#ifndef _POWERPC_MODULE_H +#define _POWERPC_MODULE_H + +/* + * 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. + */ + +#include +#include + + +#ifndef __powerpc64__ +/* + * Thanks to Paul M for explaining this. + * + * PPC can only do rel jumps += 32MB, and often the kernel and other + * modules are furthur away than this. So, we jump to a table of + * trampolines attached to the module (the Procedure Linkage Table) + * whenever that happens. + */ + +struct ppc_plt_entry { + /* 16 byte jump instruction sequence (4 instructions) */ + unsigned int jump[4]; +}; +#endif /* __powerpc64__ */ + + +struct mod_arch_specific { +#ifdef __powerpc64__ + unsigned int stubs_section; /* Index of stubs section in module */ + unsigned int toc_section; /* What section is the TOC? */ +#else + /* Indices of PLT sections within module. */ + unsigned int core_plt_section; + unsigned int init_plt_section; +#endif + + /* List of BUG addresses, source line numbers and filenames */ + struct list_head bug_list; + struct bug_entry *bug_table; + unsigned int num_bugs; +}; + +extern struct bug_entry *module_find_bug(unsigned long bugaddr); + +/* + * Select ELF headers. + * Make empty section for module_frob_arch_sections to expand. + */ + +#ifdef __powerpc64__ +# define Elf_Shdr Elf64_Shdr +# define Elf_Sym Elf64_Sym +# define Elf_Ehdr Elf64_Ehdr +# ifdef MODULE + asm(".section .stubs,\"ax\", at nobits; .align 3; .previous"); +# endif +#else +# define Elf_Shdr Elf32_Shdr +# define Elf_Sym Elf32_Sym +# define Elf_Ehdr Elf32_Ehdr +# ifdef MODULE + asm(".section .plt,\"ax\", at nobits; .align 3; .previous"); + asm(".section .init.plt,\"ax\", at nobits; .align 3; .previous"); +# endif /* MODULE */ +#endif + + +struct exception_table_entry; +void sort_ex_table(struct exception_table_entry *start, + struct exception_table_entry *finish); + +#endif /* _POWERPC_MODULE_H */ diff --git a/include/asm-powerpc/sembuf.h b/include/asm-powerpc/sembuf.h new file mode 100644 --- /dev/null +++ b/include/asm-powerpc/sembuf.h @@ -0,0 +1,36 @@ +#ifndef _POWERPC_SEMBUF_H +#define _POWERPC_SEMBUF_H + +/* + * 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. + */ + +/* + * The semid64_ds structure for PPC architecture. + * Note extra padding because this structure is passed back and forth + * between kernel and user space. + * + * Pad space is left for: + * - 64-bit time_t to solve y2038 problem + * - 2 miscellaneous 32-bit values + */ + +struct semid64_ds { + struct ipc64_perm sem_perm; /* permissions .. see ipc.h */ +#ifndef __powerpc64__ + unsigned long __unused1; +#endif + __kernel_time_t sem_otime; /* last semop time */ +#ifndef __powerpc64__ + unsigned long __unused2; +#endif + __kernel_time_t sem_ctime; /* last change time */ + unsigned long sem_nsems; /* no. of semaphores in array */ + unsigned long __unused3; + unsigned long __unused4; +}; + +#endif /* _POWERPC_SEMBUF_H */ diff --git a/include/asm-powerpc/shmbuf.h b/include/asm-powerpc/shmbuf.h new file mode 100644 --- /dev/null +++ b/include/asm-powerpc/shmbuf.h @@ -0,0 +1,59 @@ +#ifndef _POWERPC_SHMBUF_H +#define _POWERPC_SHMBUF_H + +/* + * 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. + */ + +/* + * The shmid64_ds structure for PPC architecture. + * + * Note extra padding because this structure is passed back and forth + * between kernel and user space. + * + * Pad space is left for: + * - 64-bit time_t to solve y2038 problem + * - 2 miscellaneous 32-bit values + */ + +struct shmid64_ds { + struct ipc64_perm shm_perm; /* operation perms */ +#ifndef __power64__ + unsigned long __unused1; +#endif + __kernel_time_t shm_atime; /* last attach time */ +#ifndef __power64__ + unsigned long __unused2; +#endif + __kernel_time_t shm_dtime; /* last detach time */ +#ifndef __power64__ + unsigned long __unused3; +#endif + __kernel_time_t shm_ctime; /* last change time */ +#ifndef __power64__ + unsigned long __unused4; +#endif + size_t shm_segsz; /* size of segment (bytes) */ + __kernel_pid_t shm_cpid; /* pid of creator */ + __kernel_pid_t shm_lpid; /* pid of last operator */ + unsigned long shm_nattch; /* no. of current attaches */ + unsigned long __unused5; + unsigned long __unused6; +}; + +struct shminfo64 { + unsigned long shmmax; + unsigned long shmmin; + unsigned long shmmni; + unsigned long shmseg; + unsigned long shmall; + unsigned long __unused1; + unsigned long __unused2; + unsigned long __unused3; + unsigned long __unused4; +}; + +#endif /* _POWERPC_SHMBUF_H */ diff --git a/include/asm-powerpc/siginfo.h b/include/asm-powerpc/siginfo.h new file mode 100644 --- /dev/null +++ b/include/asm-powerpc/siginfo.h @@ -0,0 +1,18 @@ +#ifndef _POWERPC_SIGINFO_H +#define _POWERPC_SIGINFO_H + +/* + * 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. + */ + +#ifdef __powerpc64__ +# define __ARCH_SI_PREAMBLE_SIZE (4 * sizeof(int)) +# define SI_PAD_SIZE32 ((SI_MAX_SIZE/sizeof(int)) - 3) +#endif + +#include + +#endif /* _POWERPC_SIGINFO_H */ diff --git a/include/asm-powerpc/socket.h b/include/asm-powerpc/socket.h new file mode 100644 --- /dev/null +++ b/include/asm-powerpc/socket.h @@ -0,0 +1,59 @@ +#ifndef _POWERPC_SOCKET_H +#define _POWERPC_SOCKET_H + +/* + * 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. + */ + +#include + +/* For setsockopt(2) */ +#define SOL_SOCKET 1 + +#define SO_DEBUG 1 +#define SO_REUSEADDR 2 +#define SO_TYPE 3 +#define SO_ERROR 4 +#define SO_DONTROUTE 5 +#define SO_BROADCAST 6 +#define SO_SNDBUF 7 +#define SO_RCVBUF 8 +#define SO_SNDBUFFORCE 32 +#define SO_RCVBUFFORCE 33 +#define SO_KEEPALIVE 9 +#define SO_OOBINLINE 10 +#define SO_NO_CHECK 11 +#define SO_PRIORITY 12 +#define SO_LINGER 13 +#define SO_BSDCOMPAT 14 +/* To add :#define SO_REUSEPORT 15 */ +#define SO_RCVLOWAT 16 +#define SO_SNDLOWAT 17 +#define SO_RCVTIMEO 18 +#define SO_SNDTIMEO 19 +#define SO_PASSCRED 20 +#define SO_PEERCRED 21 + +/* Security levels - as per NRL IPv6 - don't actually do anything */ +#define SO_SECURITY_AUTHENTICATION 22 +#define SO_SECURITY_ENCRYPTION_TRANSPORT 23 +#define SO_SECURITY_ENCRYPTION_NETWORK 24 + +#define SO_BINDTODEVICE 25 + +/* Socket filtering */ +#define SO_ATTACH_FILTER 26 +#define SO_DETACH_FILTER 27 + +#define SO_PEERNAME 28 +#define SO_TIMESTAMP 29 +#define SCM_TIMESTAMP SO_TIMESTAMP + +#define SO_ACCEPTCONN 30 + +#define SO_PEERSEC 31 + +#endif /* _POWERPC_SOCKET_H */ diff --git a/include/asm-powerpc/sockios.h b/include/asm-powerpc/sockios.h new file mode 100644 --- /dev/null +++ b/include/asm-powerpc/sockios.h @@ -0,0 +1,19 @@ +#ifndef _POWERPC_SOCKIOS_H +#define _POWERPC_SOCKIOS_H + +/* + * 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. + */ + +/* Socket-level I/O control calls. */ +#define FIOSETOWN 0x8901 +#define SIOCSPGRP 0x8902 +#define FIOGETOWN 0x8903 +#define SIOCGPGRP 0x8904 +#define SIOCATMARK 0x8905 +#define SIOCGSTAMP 0x8906 /* Get stamp */ + +#endif /* _POWERPC_SOCKIOS_H */ diff --git a/include/asm-ppc/bugs.h b/include/asm-ppc/bugs.h deleted file mode 100644 --- a/include/asm-ppc/bugs.h +++ /dev/null @@ -1,6 +0,0 @@ -/* - * This file is included by 'init/main.c' - */ - -extern void -check_bugs(void); diff --git a/include/asm-ppc/kmap_types.h b/include/asm-ppc/kmap_types.h deleted file mode 100644 --- a/include/asm-ppc/kmap_types.h +++ /dev/null @@ -1,24 +0,0 @@ -#ifdef __KERNEL__ -#ifndef _ASM_KMAP_TYPES_H -#define _ASM_KMAP_TYPES_H - -enum km_type { - KM_BOUNCE_READ, - KM_SKB_SUNRPC_DATA, - KM_SKB_DATA_SOFTIRQ, - KM_USER0, - KM_USER1, - KM_BIO_SRC_IRQ, - KM_BIO_DST_IRQ, - KM_PTE0, - KM_PTE1, - KM_IRQ0, - KM_IRQ1, - KM_SOFTIRQ0, - KM_SOFTIRQ1, - KM_PPC_SYNC_PAGE, - KM_TYPE_NR -}; - -#endif -#endif /* __KERNEL__ */ diff --git a/include/asm-ppc/mc146818rtc.h b/include/asm-ppc/mc146818rtc.h deleted file mode 100644 --- a/include/asm-ppc/mc146818rtc.h +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Machine dependent access functions for RTC registers. - */ -#ifdef __KERNEL__ -#ifndef __ASM_PPC_MC146818RTC_H -#define __ASM_PPC_MC146818RTC_H - -#include - -#ifndef RTC_PORT -#define RTC_PORT(x) (0x70 + (x)) -#define RTC_ALWAYS_BCD 1 /* RTC operates in binary mode */ -#endif - -/* - * The yet supported machines all access the RTC index register via - * an ISA port access but the way to access the date register differs ... - */ -#define CMOS_READ(addr) ({ \ -outb_p((addr),RTC_PORT(0)); \ -inb_p(RTC_PORT(1)); \ -}) -#define CMOS_WRITE(val, addr) ({ \ -outb_p((addr),RTC_PORT(0)); \ -outb_p((val),RTC_PORT(1)); \ -}) - -#define RTC_IRQ 8 - -#endif /* __ASM_PPC_MC146818RTC_H */ -#endif /* __KERNEL__ */ diff --git a/include/asm-ppc/module.h b/include/asm-ppc/module.h deleted file mode 100644 --- a/include/asm-ppc/module.h +++ /dev/null @@ -1,44 +0,0 @@ -#ifndef _ASM_PPC_MODULE_H -#define _ASM_PPC_MODULE_H -/* Module stuff for PPC. (C) 2001 Rusty Russell */ - -#include -#include - -/* Thanks to Paul M for explaining this. - - PPC can only do rel jumps += 32MB, and often the kernel and other - modules are furthur away than this. So, we jump to a table of - trampolines attached to the module (the Procedure Linkage Table) - whenever that happens. -*/ - -struct ppc_plt_entry -{ - /* 16 byte jump instruction sequence (4 instructions) */ - unsigned int jump[4]; -}; - -struct mod_arch_specific -{ - /* Indices of PLT sections within module. */ - unsigned int core_plt_section, init_plt_section; - - /* List of BUG addresses, source line numbers and filenames */ - struct list_head bug_list; - struct bug_entry *bug_table; - unsigned int num_bugs; -}; - -extern struct bug_entry *module_find_bug(unsigned long bugaddr); - -#define Elf_Shdr Elf32_Shdr -#define Elf_Sym Elf32_Sym -#define Elf_Ehdr Elf32_Ehdr - -/* Make empty sections for module_frob_arch_sections to expand. */ -#ifdef MODULE -asm(".section .plt,\"ax\", at nobits; .align 3; .previous"); -asm(".section .init.plt,\"ax\", at nobits; .align 3; .previous"); -#endif -#endif /* _ASM_PPC_MODULE_H */ diff --git a/include/asm-ppc/sembuf.h b/include/asm-ppc/sembuf.h deleted file mode 100644 --- a/include/asm-ppc/sembuf.h +++ /dev/null @@ -1,19 +0,0 @@ -#ifndef _PPC_SEMBUF_H -#define _PPC_SEMBUF_H - -/* - * The semid64_ds structure for PPC architecture. - */ - -struct semid64_ds { - struct ipc64_perm sem_perm; /* permissions .. see ipc.h */ - unsigned int __unused1; - __kernel_time_t sem_otime; /* last semop time */ - unsigned int __unused2; - __kernel_time_t sem_ctime; /* last change time */ - unsigned long sem_nsems; /* no. of semaphores in array */ - unsigned long __unused3; - unsigned long __unused4; -}; - -#endif /* _PPC_SEMBUF_H */ diff --git a/include/asm-ppc/shmbuf.h b/include/asm-ppc/shmbuf.h deleted file mode 100644 --- a/include/asm-ppc/shmbuf.h +++ /dev/null @@ -1,37 +0,0 @@ -#ifndef _PPC_SHMBUF_H -#define _PPC_SHMBUF_H - -/* - * The shmid64_ds structure for PPC architecture. - */ - -struct shmid64_ds { - struct ipc64_perm shm_perm; /* operation perms */ - unsigned int __unused1; - __kernel_time_t shm_atime; /* last attach time */ - unsigned int __unused2; - __kernel_time_t shm_dtime; /* last detach time */ - unsigned int __unused3; - __kernel_time_t shm_ctime; /* last change time */ - unsigned int __unused4; - size_t shm_segsz; /* size of segment (bytes) */ - __kernel_pid_t shm_cpid; /* pid of creator */ - __kernel_pid_t shm_lpid; /* pid of last operator */ - unsigned long shm_nattch; /* no. of current attaches */ - unsigned long __unused5; - unsigned long __unused6; -}; - -struct shminfo64 { - unsigned long shmmax; - unsigned long shmmin; - unsigned long shmmni; - unsigned long shmseg; - unsigned long shmall; - unsigned long __unused1; - unsigned long __unused2; - unsigned long __unused3; - unsigned long __unused4; -}; - -#endif /* _PPC_SHMBUF_H */ diff --git a/include/asm-ppc/siginfo.h b/include/asm-ppc/siginfo.h deleted file mode 100644 --- a/include/asm-ppc/siginfo.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef _PPC_SIGINFO_H -#define _PPC_SIGINFO_H - -#include - -#endif diff --git a/include/asm-ppc/socket.h b/include/asm-ppc/socket.h deleted file mode 100644 --- a/include/asm-ppc/socket.h +++ /dev/null @@ -1,58 +0,0 @@ -#ifndef _ASM_SOCKET_H -#define _ASM_SOCKET_H - -/* Socket-level I/O control calls. */ -#define FIOSETOWN 0x8901 -#define SIOCSPGRP 0x8902 -#define FIOGETOWN 0x8903 -#define SIOCGPGRP 0x8904 -#define SIOCATMARK 0x8905 -#define SIOCGSTAMP 0x8906 /* Get stamp */ - -/* For setsockopt(2) */ -#define SOL_SOCKET 1 - -#define SO_DEBUG 1 -#define SO_REUSEADDR 2 -#define SO_TYPE 3 -#define SO_ERROR 4 -#define SO_DONTROUTE 5 -#define SO_BROADCAST 6 -#define SO_SNDBUF 7 -#define SO_RCVBUF 8 -#define SO_SNDBUFFORCE 32 -#define SO_RCVBUFFORCE 33 -#define SO_KEEPALIVE 9 -#define SO_OOBINLINE 10 -#define SO_NO_CHECK 11 -#define SO_PRIORITY 12 -#define SO_LINGER 13 -#define SO_BSDCOMPAT 14 -/* To add :#define SO_REUSEPORT 15 */ -#define SO_RCVLOWAT 16 -#define SO_SNDLOWAT 17 -#define SO_RCVTIMEO 18 -#define SO_SNDTIMEO 19 -#define SO_PASSCRED 20 -#define SO_PEERCRED 21 - -/* Security levels - as per NRL IPv6 - don't actually do anything */ -#define SO_SECURITY_AUTHENTICATION 22 -#define SO_SECURITY_ENCRYPTION_TRANSPORT 23 -#define SO_SECURITY_ENCRYPTION_NETWORK 24 - -#define SO_BINDTODEVICE 25 - -/* Socket filtering */ -#define SO_ATTACH_FILTER 26 -#define SO_DETACH_FILTER 27 - -#define SO_PEERNAME 28 -#define SO_TIMESTAMP 29 -#define SCM_TIMESTAMP SO_TIMESTAMP - -#define SO_ACCEPTCONN 30 - -#define SO_PEERSEC 31 - -#endif /* _ASM_SOCKET_H */ diff --git a/include/asm-ppc/sockios.h b/include/asm-ppc/sockios.h deleted file mode 100644 --- a/include/asm-ppc/sockios.h +++ /dev/null @@ -1,17 +0,0 @@ -#ifndef _ASM_PPC_SOCKIOS_H -#define _ASM_PPC_SOCKIOS_H - -#if 0 /* These are defined this way on Alpha - maybe later. */ -/* Socket-level I/O control calls. */ - -#define FIOGETOWN _IOR('f', 123, int) -#define FIOSETOWN _IOW('f', 124, int) - -#define SIOCATMARK _IOR('s', 7, int) -#define SIOCSPGRP _IOW('s', 8, pid_t) -#define SIOCGPGRP _IOR('s', 9, pid_t) - -#define SIOCGSTAMP 0x8906 /* Get stamp - linux-specific */ -#endif - -#endif /* _ASM_PPC_SOCKIOS_H */ diff --git a/include/asm-ppc64/bugs.h b/include/asm-ppc64/bugs.h deleted file mode 100644 --- a/include/asm-ppc64/bugs.h +++ /dev/null @@ -1,12 +0,0 @@ -/* - * This file is included by 'init/main.c' to check for architecture-dependent - * bugs. - * - */ -#ifndef _ASM_PPC64_BUGS_H -#define _ASM_PPC64_BUGS_H - -static void check_bugs(void) { -} - -#endif /* _ASM_PPC64_BUGS_H */ diff --git a/include/asm-ppc64/kmap_types.h b/include/asm-ppc64/kmap_types.h deleted file mode 100644 --- a/include/asm-ppc64/kmap_types.h +++ /dev/null @@ -1,23 +0,0 @@ -#ifdef __KERNEL__ -#ifndef _ASM_KMAP_TYPES_H -#define _ASM_KMAP_TYPES_H - -enum km_type { - KM_BOUNCE_READ, - KM_SKB_SUNRPC_DATA, - KM_SKB_DATA_SOFTIRQ, - KM_USER0, - KM_USER1, - KM_BIO_SRC_IRQ, - KM_BIO_DST_IRQ, - KM_PTE0, - KM_PTE1, - KM_IRQ0, - KM_IRQ1, - KM_SOFTIRQ0, - KM_SOFTIRQ1, - KM_TYPE_NR -}; - -#endif -#endif /* __KERNEL__ */ diff --git a/include/asm-ppc64/mc146818rtc.h b/include/asm-ppc64/mc146818rtc.h deleted file mode 100644 --- a/include/asm-ppc64/mc146818rtc.h +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Machine dependent access functions for RTC registers. - * - * 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. - */ -#ifndef __ASM_PPC64_MC146818RTC_H -#define __ASM_PPC64_MC146818RTC_H - -#include - -#ifndef RTC_PORT -#define RTC_PORT(x) (0x70 + (x)) -#define RTC_ALWAYS_BCD 1 /* RTC operates in binary mode */ -#endif - -/* - * The yet supported machines all access the RTC index register via - * an ISA port access but the way to access the date register differs ... - */ -#define CMOS_READ(addr) ({ \ -outb_p((addr),RTC_PORT(0)); \ -inb_p(RTC_PORT(1)); \ -}) -#define CMOS_WRITE(val, addr) ({ \ -outb_p((addr),RTC_PORT(0)); \ -outb_p((val),RTC_PORT(1)); \ -}) - -#endif /* __ASM_PPC64_MC146818RTC_H */ diff --git a/include/asm-ppc64/module.h b/include/asm-ppc64/module.h deleted file mode 100644 --- a/include/asm-ppc64/module.h +++ /dev/null @@ -1,36 +0,0 @@ -#ifndef _ASM_PPC64_MODULE_H -#define _ASM_PPC64_MODULE_H - -#include -#include - -struct mod_arch_specific -{ - /* Index of stubs section within module. */ - unsigned int stubs_section; - - /* What section is the TOC? */ - unsigned int toc_section; - - /* List of BUG addresses, source line numbers and filenames */ - struct list_head bug_list; - struct bug_entry *bug_table; - unsigned int num_bugs; -}; - -extern struct bug_entry *module_find_bug(unsigned long bugaddr); - -#define Elf_Shdr Elf64_Shdr -#define Elf_Sym Elf64_Sym -#define Elf_Ehdr Elf64_Ehdr - -/* Make empty section for module_frob_arch_sections to expand. */ -#ifdef MODULE -asm(".section .stubs,\"ax\", at nobits; .align 3; .previous"); -#endif - -struct exception_table_entry; -void sort_ex_table(struct exception_table_entry *start, - struct exception_table_entry *finish); - -#endif /* _ASM_PPC64_MODULE_H */ diff --git a/include/asm-ppc64/sembuf.h b/include/asm-ppc64/sembuf.h deleted file mode 100644 --- a/include/asm-ppc64/sembuf.h +++ /dev/null @@ -1,27 +0,0 @@ -#ifndef _PPC64_SEMBUF_H -#define _PPC64_SEMBUF_H - -/* - * The semid64_ds structure for PPC architecture. - * - * - * 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. - * - * Pad space is left for: - * - 2 miscellaneous 64-bit values - */ - -struct semid64_ds { - struct ipc64_perm sem_perm; /* permissions .. see ipc.h */ - __kernel_time_t sem_otime; /* last semop time */ - __kernel_time_t sem_ctime; /* last change time */ - unsigned long sem_nsems; /* no. of semaphores in array */ - - unsigned long __unused1; - unsigned long __unused2; -}; - -#endif /* _PPC64_SEMBUF_H */ diff --git a/include/asm-ppc64/shmbuf.h b/include/asm-ppc64/shmbuf.h deleted file mode 100644 --- a/include/asm-ppc64/shmbuf.h +++ /dev/null @@ -1,43 +0,0 @@ -#ifndef _PPC64_SHMBUF_H -#define _PPC64_SHMBUF_H - -/* - * The shmid64_ds structure for PPC64 architecture. - * Note extra padding because this structure is passed back and forth - * between kernel and user space. - * - * Pad space is left for: - * - 2 miscellaneous 64-bit values - * - * 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. - */ - -struct shmid64_ds { - struct ipc64_perm shm_perm; /* operation perms */ - __kernel_time_t shm_atime; /* last attach time */ - __kernel_time_t shm_dtime; /* last detach time */ - __kernel_time_t shm_ctime; /* last change time */ - size_t shm_segsz; /* size of segment (bytes) */ - __kernel_pid_t shm_cpid; /* pid of creator */ - __kernel_pid_t shm_lpid; /* pid of last operator */ - unsigned long shm_nattch; /* no. of current attaches */ - unsigned long __unused1; - unsigned long __unused2; -}; - -struct shminfo64 { - unsigned long shmmax; - unsigned long shmmin; - unsigned long shmmni; - unsigned long shmseg; - unsigned long shmall; - unsigned long __unused1; - unsigned long __unused2; - unsigned long __unused3; - unsigned long __unused4; -}; - -#endif /* _PPC64_SHMBUF_H */ diff --git a/include/asm-ppc64/siginfo.h b/include/asm-ppc64/siginfo.h deleted file mode 100644 --- a/include/asm-ppc64/siginfo.h +++ /dev/null @@ -1,16 +0,0 @@ -#ifndef _PPC64_SIGINFO_H -#define _PPC64_SIGINFO_H - -/* - * 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. - */ - -#define __ARCH_SI_PREAMBLE_SIZE (4 * sizeof(int)) -#define SI_PAD_SIZE32 ((SI_MAX_SIZE/sizeof(int)) - 3) - -#include - -#endif /* _PPC64_SIGINFO_H */ diff --git a/include/asm-ppc64/socket.h b/include/asm-ppc64/socket.h deleted file mode 100644 --- a/include/asm-ppc64/socket.h +++ /dev/null @@ -1,59 +0,0 @@ -#ifndef _ASM_SOCKET_H -#define _ASM_SOCKET_H - -/* - * 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. - */ - -#include - -/* For setsockoptions(2) */ -#define SOL_SOCKET 1 - -#define SO_DEBUG 1 -#define SO_REUSEADDR 2 -#define SO_TYPE 3 -#define SO_ERROR 4 -#define SO_DONTROUTE 5 -#define SO_BROADCAST 6 -#define SO_SNDBUF 7 -#define SO_RCVBUF 8 -#define SO_SNDBUFFORCE 32 -#define SO_RCVBUFFORCE 33 -#define SO_KEEPALIVE 9 -#define SO_OOBINLINE 10 -#define SO_NO_CHECK 11 -#define SO_PRIORITY 12 -#define SO_LINGER 13 -#define SO_BSDCOMPAT 14 -/* To add :#define SO_REUSEPORT 15 */ -#define SO_RCVLOWAT 16 -#define SO_SNDLOWAT 17 -#define SO_RCVTIMEO 18 -#define SO_SNDTIMEO 19 -#define SO_PASSCRED 20 -#define SO_PEERCRED 21 - -/* Security levels - as per NRL IPv6 - don't actually do anything */ -#define SO_SECURITY_AUTHENTICATION 22 -#define SO_SECURITY_ENCRYPTION_TRANSPORT 23 -#define SO_SECURITY_ENCRYPTION_NETWORK 24 - -#define SO_BINDTODEVICE 25 - -/* Socket filtering */ -#define SO_ATTACH_FILTER 26 -#define SO_DETACH_FILTER 27 - -#define SO_PEERNAME 28 -#define SO_TIMESTAMP 29 -#define SCM_TIMESTAMP SO_TIMESTAMP - -#define SO_ACCEPTCONN 30 - -#define SO_PEERSEC 31 - -#endif /* _ASM_SOCKET_H */ diff --git a/include/asm-ppc64/sockios.h b/include/asm-ppc64/sockios.h deleted file mode 100644 --- a/include/asm-ppc64/sockios.h +++ /dev/null @@ -1,19 +0,0 @@ -#ifndef _ASM_PPC64_SOCKIOS_H -#define _ASM_PPC64_SOCKIOS_H - -/* - * 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. - */ - -/* Socket-level I/O control calls. */ -#define FIOSETOWN 0x8901 -#define SIOCSPGRP 0x8902 -#define FIOGETOWN 0x8903 -#define SIOCGPGRP 0x8904 -#define SIOCATMARK 0x8905 -#define SIOCGSTAMP 0x8906 /* Get stamp */ - -#endif /* _ASM_PPC64_SOCKIOS_H */ From sharada at in.ibm.com Fri Sep 2 10:28:47 2005 From: sharada at in.ibm.com (R Sharada) Date: Fri, 2 Sep 2005 05:58:47 +0530 Subject: [PATCH] - Revised patch to export kernel end, htab values In-Reply-To: <20050830053618.GA1273@in.ibm.com> References: <20050823080423.GA2380@in.ibm.com> <20050824190652.GO1012@otto> <20050825044206.GA2079@in.ibm.com> <200508251649.26156.arnd@arndb.de> <20050829115207.GA2858@in.ibm.com> <17171.58504.946616.395669@cargo.ozlabs.ibm.com> <20050830053618.GA1273@in.ibm.com> Message-ID: <20050902002847.GA2158@in.ibm.com> Hello Paulus/All, While working on the kexec-tools for ppc64, we came across this requirement - kexec-tools needs to be able to discover a set of memory ranges in userspace, such that we can allocate a hole from that memory to load the various kernel segments. In kexec on ppc64 it means the following: - in non-lpar machines, the memory ranges obtained should exclude tce_tables and htab_tables - in all machines, the memory ranges obtained should exclude the kernel resident memory (from _start to _end), rtas region, as we use RTAS in kexec-ed kernel While rtas, and tce details are available in userspace via /proc/device-tree, end of kernel and htab values are currently not available. Hence the need for a patch to export the htab and kernel end values into /proc/device-tree. The other alternative, as it has been discussed before, is to be able to export a complete set of memory_ranges from kernel into /proc/device-tree, that displays only valid mempory ranges, excluding all the above regions, something similar to /proc/iomem of x86. This current patch export htab and kernel end values, and does the exclusion logic from within kexec-tools. I would like to request feedback on - this patch and consider for temporary inclusion (while a cleaner or more acceptable approach is put down) - on this approach vs exporting the complete set of ranges from kernel in a lightweight manner Thanks and Regards, Sharada Signed-off-by: R Sharada --- diff -puN include/asm-ppc64/mmu.h~kexec-export-htab-value include/asm-ppc64/mmu.h --- linux-2.6.13-rc6-org/include/asm-ppc64/mmu.h~kexec-export-htab-value 2005-08-25 05:27:35.000000000 +0530 +++ linux-2.6.13-rc6-org-sharada/include/asm-ppc64/mmu.h 2005-08-29 22:09:04.000000000 +0530 @@ -58,6 +58,7 @@ * Hash table */ +#define HASH_GROUP_SIZE 0x80 /* size of each hash group */ #define HPTES_PER_GROUP 8 #define HPTE_V_AVPN_SHIFT 7 diff -puN ./arch/ppc64/kernel/setup.c~kexec-export-htab-value ./arch/ppc64/kernel/setup.c --- linux-2.6.13-rc6-org/./arch/ppc64/kernel/setup.c~kexec-export-htab-value 2005-08-25 05:27:35.000000000 +0530 +++ linux-2.6.13-rc6-org-sharada/./arch/ppc64/kernel/setup.c 2005-09-02 11:31:33.000000000 +0530 @@ -1033,6 +1033,59 @@ void __init setup_syscall_map(void) count32, count64); } +static void __init export_kernel_end(void) +{ + static unsigned long kernel_end; + static struct property kernel_end_prop = { + .name = "kernel_end", + .length = sizeof(unsigned long), + .value = (unsigned char *)&kernel_end, + }; + + struct device_node *node; + node = of_find_node_by_path("/chosen"); + if (!node) + return; + + kernel_end = __pa(_end); + prom_add_property(node, &kernel_end_prop); + + of_node_put(node); +} + +static void __init export_htab_value(void) +{ + static unsigned long htab_base; + static struct property htab_base_prop = { + .name = "htab_base", + .length = sizeof(unsigned long), + .value = (unsigned char *)&htab_base, + }; + + static unsigned long htab_size; + static struct property htab_size_prop = { + .name = "htab_size", + .length = sizeof(unsigned long), + .value = (unsigned char *)&htab_size, + }; + + struct device_node *node; + + if (systemcfg->platform == PLATFORM_PSERIES_LPAR) + return; + + node = of_find_node_by_path("/chosen"); + if (!node) + return; + + htab_base = __pa(htab_address); + prom_add_property(node, &htab_base_prop); + htab_size = (htab_hash_mask + 1) * HASH_GROUP_SIZE; + prom_add_property(node, &htab_size_prop); + + of_node_put(node); +} + /* * Called into from start_kernel, after lock_kernel has been called. * Initializes bootmem, which is unsed to manage page allocation until @@ -1086,6 +1139,12 @@ void __init setup_arch(char **cmdline_p) } paging_init(); + + /* export htab and kernel end values into /proc/device-tree/chosen + * for kexec + */ + export_htab_value(); + export_kernel_end(); ppc64_boot_msg(0x15, "Setup Done"); } _ From junkio at cox.net Fri Sep 2 10:20:02 2005 From: junkio at cox.net (Junio C Hamano) Date: Thu, 01 Sep 2005 17:20:02 -0700 Subject: please pull ppc64-2.6.git In-Reply-To: <20050829184510.A20605@flint.arm.linux.org.uk> (Russell King's message of "Mon, 29 Aug 2005 18:45:10 +0100") References: <17170.25803.413408.44080@cargo.ozlabs.ibm.com> <20050829184510.A20605@flint.arm.linux.org.uk> Message-ID: <7vpsrstj65.fsf@assigned-by-dhcp.cox.net> Russell King writes: > Is the expected filesystem layout documented somewhere online (_external_ > to the source code) ? There already was a sketchy description in git(7), at I've updated it a bit to describe the current status; please look for "File/Directory Structure" section of the above URL. From arnd at arndb.de Fri Sep 2 13:18:32 2005 From: arnd at arndb.de (Arnd Bergmann) Date: Fri, 2 Sep 2005 05:18:32 +0200 Subject: PATCH Merge more include files In-Reply-To: <1125607912.16685.111.camel@cashmere.sps.mot.com> References: <1125607912.16685.111.camel@cashmere.sps.mot.com> Message-ID: <200509020518.32732.arnd@arndb.de> On Dunnersdag 01 September 2005 22:51, Jon Loeliger wrote: > +/* > + * This file is included by 'init/main.c' to check for > + * architecture-dependent bugs. > + */ > + > +extern void check_bugs(void); > + Actually, I think this could to be +static inline void check_bugs(void) +{ +} The function is empty on both ppc and ppc64, so we can just as well get rid of the symbol as well. The rest of the patch looks perfect to me. Arnd <>< From sfr at canb.auug.org.au Fri Sep 2 16:15:53 2005 From: sfr at canb.auug.org.au (Stephen Rothwell) Date: Fri, 2 Sep 2005 16:15:53 +1000 Subject: PATCH Merge more include files In-Reply-To: <1125607912.16685.111.camel@cashmere.sps.mot.com> References: <1125607912.16685.111.camel@cashmere.sps.mot.com> Message-ID: <20050902161553.482156c3.sfr@canb.auug.org.au> On Thu, 01 Sep 2005 15:51:52 -0500 Jon Loeliger wrote: > > +/* > + * 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. > + */ I thought that we generally did't put the GPL licence stuff in header files ... -- Cheers, Stephen Rothwell sfr at canb.auug.org.au http://www.canb.auug.org.au/~sfr/ -------------- next part -------------- A non-text attachment was scrubbed... Name: not available Type: application/pgp-signature Size: 189 bytes Desc: not available Url : http://ozlabs.org/pipermail/linuxppc64-dev/attachments/20050902/79e259c5/attachment.pgp From sfr at canb.auug.org.au Fri Sep 2 16:37:08 2005 From: sfr at canb.auug.org.au (Stephen Rothwell) Date: Fri, 2 Sep 2005 16:37:08 +1000 Subject: PATCH Merge more include files In-Reply-To: <1125607912.16685.111.camel@cashmere.sps.mot.com> References: <1125607912.16685.111.camel@cashmere.sps.mot.com> Message-ID: <20050902163708.12c1abe3.sfr@canb.auug.org.au> On Thu, 01 Sep 2005 15:51:52 -0500 Jon Loeliger wrote: > > This patch merges several include files from > asm-ppc and asm-ppc64 into the new asm-powerpc. > > Signed-off-by: Jon Loeliger > Signed-off-by: Kumar Gala > +#ifndef _POWERPC_BUGS_H I would use _ASM_POWERPC_... but that is just me. Looks good. -- Cheers, Stephen Rothwell sfr at canb.auug.org.au http://www.canb.auug.org.au/~sfr/ -------------- next part -------------- A non-text attachment was scrubbed... Name: not available Type: application/pgp-signature Size: 189 bytes Desc: not available Url : http://ozlabs.org/pipermail/linuxppc64-dev/attachments/20050902/c189546a/attachment.pgp From member.support at creditunion1.org Fri Sep 2 05:49:43 2005 From: member.support at creditunion1.org (Credit Union 1) Date: 1 Sep 2005 19:49:43 -0000 Subject: Credit Union 1 Members Update Aplication Message-ID: <20050901194943.8619.qmail@server1.swiss-web.com> An HTML attachment was scrubbed... URL: http://ozlabs.org/pipermail/linuxppc64-dev/attachments/20050901/20cc9ed4/attachment.htm From kumar.gala at freescale.com Fri Sep 2 23:38:39 2005 From: kumar.gala at freescale.com (Kumar Gala) Date: Fri, 2 Sep 2005 08:38:39 -0500 Subject: PATCH Merge more include files In-Reply-To: <200509020518.32732.arnd@arndb.de> References: <200509020518.32732.arnd@arndb.de> Message-ID: On Sep 1, 2005, at 10:18 PM, Arnd Bergmann wrote: > On Dunnersdag 01 September 2005 22:51, Jon Loeliger wrote: > >> +/* >> + * This file is included by 'init/main.c' to check for >> + * architecture-dependent bugs. >> + */ >> + >> +extern void check_bugs(void); >> + >> > > Actually, I think this could to be > > +static inline void check_bugs(void) > +{ > +} > > The function is empty on both ppc and ppc64, so we can just as > well get rid of the symbol as well. > The rest of the patch looks perfect to me. We just have to make sure to get ride of the implementation in arch/ ppc*/kernel/syscalls.c if we do this. - kumar From dave at sr71.net Sat Sep 3 06:39:13 2005 From: dave at sr71.net (Dave Hansen) Date: Fri, 02 Sep 2005 13:39:13 -0700 Subject: [RFC] broken installkernel.sh with CROSS_COMPILE Message-ID: <1125693554.26605.10.camel@localhost> I noticed that my cross-compilation 'make install' broke with 2.6.13 (I don't use it horribly often). It's from this commit: http://www.kernel.org/git/gitweb.cgi?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=0f8e2d62fa04441cd12c08ce521e84e5bd3f8a46 Which added CROSS_COMPILE to each arch's install.sh: if [ -x ~/bin/${CROSS_COMPILE}installkernel ]; then exec ~/bin/${CROSS_COMPILE}installkernel "$@"; fi However, I don't just have a simple arch name as my CROSS_COMPILE, I have a whole path, so that line expands like this for me: + '[' -x /home/dave/bin//home/services/cross_compile/ppc64/bin/ppc64-linux-gnu-installkernel ']' Needless to say, that doesn't work :) Could we do something that's guaranteed to not have lots of extra path elements in it, like ARCH? Something like this? That way, people like me who have a single installkernel script that does all of the fancy arch-detection can just do this: for i in `ls linux-2.6.git/arch/`; do ln -s ~/bin/installkernel ~/bin/$i-installkernel fi And be done with it forever. --- linux-2.6/arch/ppc64/boot/install.sh.orig 2005-09-02 13:34:16.000000000 -0700 +++ linux-2.6/arch/ppc64/boot/install.sh 2005-09-02 13:34:52.000000000 -0700 @@ -22,6 +22,7 @@ # User may have a custom install script +if [ -x ~/bin/${ARCH}-installkernel ]; then exec ~/bin/${ARCH}-installkernel "$@"; fi if [ -x ~/bin/${CROSS_COMPILE}installkernel ]; then exec ~/bin/${CROSS_COMPILE}installkernel "$@"; fi if [ -x /sbin/${CROSS_COMPILE}installkernel ]; then exec /sbin/${CROSS_COMPILE}installkernel "$@"; fi -- Dave From icampbell at arcom.com Sat Sep 3 18:50:20 2005 From: icampbell at arcom.com (Ian Campbell) Date: Sat, 03 Sep 2005 09:50:20 +0100 Subject: [RFC] broken installkernel.sh with CROSS_COMPILE In-Reply-To: <1125693554.26605.10.camel@localhost> References: <1125693554.26605.10.camel@localhost> Message-ID: <1125737431.6565.88.camel@azathoth.hellion.org.uk> On Fri, 2005-09-02 at 13:39 -0700, Dave Hansen wrote: > I noticed that my cross-compilation 'make install' broke with 2.6.13 (I > don't use it horribly often). It's from this commit: > > http://www.kernel.org/git/gitweb.cgi?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=0f8e2d62fa04441cd12c08ce521e84e5bd3f8a46 > > Which added CROSS_COMPILE to each arch's install.sh: > > if [ -x ~/bin/${CROSS_COMPILE}installkernel ]; then exec ~/bin/${CROSS_COMPILE}installkernel "$@"; fi > > However, I don't just have a simple arch name as my CROSS_COMPILE, I > have a whole path Ah, I didn't consider that case, sorry. > , so that line expands like this for me: > > + '[' -x /home/dave/bin//home/services/cross_compile/ppc64/bin/ppc64-linux-gnu-installkernel ']' > > Needless to say, that doesn't work :) > > Could we do something that's guaranteed to not have lots of extra path > elements in it, like ARCH? Or perhaps basename ${CROSSCOMPILE}? Ian. -- Ian Campbell Campbell's Law: Nature abhors a vacuous experimenter. From dave at sr71.net Sat Sep 3 22:31:57 2005 From: dave at sr71.net (Dave Hansen) Date: Sat, 03 Sep 2005 05:31:57 -0700 Subject: [RFC] broken installkernel.sh with CROSS_COMPILE In-Reply-To: <1125737431.6565.88.camel@azathoth.hellion.org.uk> References: <1125693554.26605.10.camel@localhost> <1125737431.6565.88.camel@azathoth.hellion.org.uk> Message-ID: <1125750717.11083.2.camel@localhost> On Sat, 2005-09-03 at 09:50 +0100, Ian Campbell wrote: > > Could we do something that's guaranteed to not have lots of extra > path > > elements in it, like ARCH? > > Or perhaps basename ${CROSSCOMPILE}? The only problem with that is that some people do really have a cross compiler named /usr/ppc64/bin/gcc. So, basename will just give you something useless like "bin". -- Dave From icampbell at arcom.com Sun Sep 4 00:35:51 2005 From: icampbell at arcom.com (Ian Campbell) Date: Sat, 03 Sep 2005 15:35:51 +0100 Subject: [RFC] broken installkernel.sh with CROSS_COMPILE In-Reply-To: <1125750717.11083.2.camel@localhost> References: <1125693554.26605.10.camel@localhost> <1125737431.6565.88.camel@azathoth.hellion.org.uk> <1125750717.11083.2.camel@localhost> Message-ID: <1125758151.6565.90.camel@azathoth.hellion.org.uk> On Sat, 2005-09-03 at 05:31 -0700, Dave Hansen wrote: > On Sat, 2005-09-03 at 09:50 +0100, Ian Campbell wrote: > > > Could we do something that's guaranteed to not have lots of extra > > path > > > elements in it, like ARCH? > > > > Or perhaps basename ${CROSSCOMPILE}? > > The only problem with that is that some people do really have a cross > compiler named /usr/ppc64/bin/gcc. So, basename will just give you > something useless like "bin". Of course, that makes perfect sense. Ian. -- Ian Campbell It seems to make an auto driver mad if he misses you. From bgill at freescale.com Sun Sep 4 10:01:57 2005 From: bgill at freescale.com (Becky Bruce) Date: Sat, 3 Sep 2005 19:01:57 -0500 (CDT) Subject: [PATCH] (updated) Move 3 more headers to asm-powerpc Message-ID: Merged several nearly-identical header files from asm-ppc and asm-ppc64 into asm-powerpc. Note: This patch supersedes the earlier patch by this name. Signed-off-by: Kumar Gala Signed-off-by: Becky Bruce --- commit 7e2f23568d8c7fbd5524f5d8940dea64e8e3d067 tree b5d10b5d6a66ffa37635d5824a48bca9cc23aa85 parent 6b39374a27eb4be7e9d82145ae270ba02ea90dc8 author Becky Bruce Sat, 03 Sep 2005 17:29:11 -0500 committer Becky Bruce Sat, 03 Sep 2005 17:29:11 -0500 include/asm-powerpc/mman.h | 52 +++++++++ include/asm-powerpc/termbits.h | 191 ++++++++++++++++++++++++++++++++ include/asm-powerpc/termios.h | 236 ++++++++++++++++++++++++++++++++++++++++ include/asm-ppc/mman.h | 44 ------- include/asm-ppc/termbits.h | 185 ------------------------------- include/asm-ppc/termios.h | 232 --------------------------------------- include/asm-ppc64/mman.h | 52 --------- include/asm-ppc64/termbits.h | 193 --------------------------------- include/asm-ppc64/termios.h | 235 ---------------------------------------- 9 files changed, 479 insertions(+), 941 deletions(-) diff --git a/include/asm-powerpc/mman.h b/include/asm-powerpc/mman.h new file mode 100644 --- /dev/null +++ b/include/asm-powerpc/mman.h @@ -0,0 +1,52 @@ +#ifndef _POWERPC_MMAN_H +#define _POWERPC_MMAN_H + +/* + * 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. + */ + +#define PROT_READ 0x1 /* page can be read */ +#define PROT_WRITE 0x2 /* page can be written */ +#define PROT_EXEC 0x4 /* page can be executed */ +#define PROT_SEM 0x8 /* page may be used for atomic ops */ +#define PROT_NONE 0x0 /* page can not be accessed */ +#define PROT_GROWSDOWN 0x01000000 /* mprotect flag: extend change to start of growsdown vma */ +#define PROT_GROWSUP 0x02000000 /* mprotect flag: extend change to end of growsup vma */ + +#define MAP_SHARED 0x01 /* Share changes */ +#define MAP_PRIVATE 0x02 /* Changes are private */ +#define MAP_TYPE 0x0f /* Mask for type of mapping */ +#define MAP_FIXED 0x10 /* Interpret addr exactly */ +#define MAP_ANONYMOUS 0x20 /* don't use a file */ +#define MAP_RENAME MAP_ANONYMOUS /* In SunOS terminology */ +#define MAP_NORESERVE 0x40 /* don't reserve swap pages */ +#define MAP_LOCKED 0x80 + +#define MAP_GROWSDOWN 0x0100 /* stack-like segment */ +#define MAP_DENYWRITE 0x0800 /* ETXTBSY */ +#define MAP_EXECUTABLE 0x1000 /* mark it as an executable */ + +#define MS_ASYNC 1 /* sync memory asynchronously */ +#define MS_INVALIDATE 2 /* invalidate the caches */ +#define MS_SYNC 4 /* synchronous memory sync */ + +#define MCL_CURRENT 0x2000 /* lock all currently mapped pages */ +#define MCL_FUTURE 0x4000 /* lock all additions to address space */ + +#define MAP_POPULATE 0x8000 /* populate (prefault) pagetables */ +#define MAP_NONBLOCK 0x10000 /* do not block on IO */ + +#define MADV_NORMAL 0x0 /* default page-in behavior */ +#define MADV_RANDOM 0x1 /* page-in minimum required */ +#define MADV_SEQUENTIAL 0x2 /* read-ahead aggressively */ +#define MADV_WILLNEED 0x3 /* pre-fault pages */ +#define MADV_DONTNEED 0x4 /* discard these pages */ + +/* compatibility flags */ +#define MAP_ANON MAP_ANONYMOUS +#define MAP_FILE 0 + +#endif /* _POWERPC_MMAN_H */ diff --git a/include/asm-powerpc/termbits.h b/include/asm-powerpc/termbits.h new file mode 100644 --- /dev/null +++ b/include/asm-powerpc/termbits.h @@ -0,0 +1,191 @@ +#ifndef _POWERPC_TERMBITS_H +#define _POWERPC_TERMBITS_H + +/* + * 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. + */ + +typedef unsigned char cc_t; +typedef unsigned int speed_t; +typedef unsigned int tcflag_t; + +/* + * termios type and macro definitions. Be careful about adding stuff + * to this file since it's used in GNU libc and there are strict rules + * concerning namespace pollution. + */ + +#define NCCS 19 +struct termios { + tcflag_t c_iflag; /* input mode flags */ + tcflag_t c_oflag; /* output mode flags */ + tcflag_t c_cflag; /* control mode flags */ + tcflag_t c_lflag; /* local mode flags */ + cc_t c_cc[NCCS]; /* control characters */ + cc_t c_line; /* line discipline (== c_cc[19]) */ + speed_t c_ispeed; /* input speed */ + speed_t c_ospeed; /* output speed */ +}; + +/* c_cc characters */ +#define VINTR 0 +#define VQUIT 1 +#define VERASE 2 +#define VKILL 3 +#define VEOF 4 +#define VMIN 5 +#define VEOL 6 +#define VTIME 7 +#define VEOL2 8 +#define VSWTC 9 +#define VWERASE 10 +#define VREPRINT 11 +#define VSUSP 12 +#define VSTART 13 +#define VSTOP 14 +#define VLNEXT 15 +#define VDISCARD 16 + +/* c_iflag bits */ +#define IGNBRK 0000001 +#define BRKINT 0000002 +#define IGNPAR 0000004 +#define PARMRK 0000010 +#define INPCK 0000020 +#define ISTRIP 0000040 +#define INLCR 0000100 +#define IGNCR 0000200 +#define ICRNL 0000400 +#define IXON 0001000 +#define IXOFF 0002000 +#define IXANY 0004000 +#define IUCLC 0010000 +#define IMAXBEL 0020000 +#define IUTF8 0040000 + +/* c_oflag bits */ +#define OPOST 0000001 +#define ONLCR 0000002 +#define OLCUC 0000004 + +#define OCRNL 0000010 +#define ONOCR 0000020 +#define ONLRET 0000040 + +#define OFILL 00000100 +#define OFDEL 00000200 +#define NLDLY 00001400 +#define NL0 00000000 +#define NL1 00000400 +#define NL2 00001000 +#define NL3 00001400 +#define TABDLY 00006000 +#define TAB0 00000000 +#define TAB1 00002000 +#define TAB2 00004000 +#define TAB3 00006000 +#define XTABS 00006000 /* required by POSIX to == TAB3 */ +#define CRDLY 00030000 +#define CR0 00000000 +#define CR1 00010000 +#define CR2 00020000 +#define CR3 00030000 +#define FFDLY 00040000 +#define FF0 00000000 +#define FF1 00040000 +#define BSDLY 00100000 +#define BS0 00000000 +#define BS1 00100000 +#define VTDLY 00200000 +#define VT0 00000000 +#define VT1 00200000 + +/* c_cflag bit meaning */ +#define CBAUD 0000377 +#define B0 0000000 /* hang up */ +#define B50 0000001 +#define B75 0000002 +#define B110 0000003 +#define B134 0000004 +#define B150 0000005 +#define B200 0000006 +#define B300 0000007 +#define B600 0000010 +#define B1200 0000011 +#define B1800 0000012 +#define B2400 0000013 +#define B4800 0000014 +#define B9600 0000015 +#define B19200 0000016 +#define B38400 0000017 +#define EXTA B19200 +#define EXTB B38400 +#define CBAUDEX 0000000 +#define B57600 00020 +#define B115200 00021 +#define B230400 00022 +#define B460800 00023 +#define B500000 00024 +#define B576000 00025 +#define B921600 00026 +#define B1000000 00027 +#define B1152000 00030 +#define B1500000 00031 +#define B2000000 00032 +#define B2500000 00033 +#define B3000000 00034 +#define B3500000 00035 +#define B4000000 00036 + +#define CSIZE 00001400 +#define CS5 00000000 +#define CS6 00000400 +#define CS7 00001000 +#define CS8 00001400 + +#define CSTOPB 00002000 +#define CREAD 00004000 +#define PARENB 00010000 +#define PARODD 00020000 +#define HUPCL 00040000 + +#define CLOCAL 00100000 +#define CRTSCTS 020000000000 /* flow control */ + +/* c_lflag bits */ +#define ISIG 0x00000080 +#define ICANON 0x00000100 +#define XCASE 0x00004000 +#define ECHO 0x00000008 +#define ECHOE 0x00000002 +#define ECHOK 0x00000004 +#define ECHONL 0x00000010 +#define NOFLSH 0x80000000 +#define TOSTOP 0x00400000 +#define ECHOCTL 0x00000040 +#define ECHOPRT 0x00000020 +#define ECHOKE 0x00000001 +#define FLUSHO 0x00800000 +#define PENDIN 0x20000000 +#define IEXTEN 0x00000400 + +/* Values for the ACTION argument to `tcflow'. */ +#define TCOOFF 0 +#define TCOON 1 +#define TCIOFF 2 +#define TCION 3 + +/* Values for the QUEUE_SELECTOR argument to `tcflush'. */ +#define TCIFLUSH 0 +#define TCOFLUSH 1 +#define TCIOFLUSH 2 + +/* Values for the OPTIONAL_ACTIONS argument to `tcsetattr'. */ +#define TCSANOW 0 +#define TCSADRAIN 1 +#define TCSAFLUSH 2 + +#endif /* _POWERPC_TERMBITS_H */ diff --git a/include/asm-powerpc/termios.h b/include/asm-powerpc/termios.h new file mode 100644 --- /dev/null +++ b/include/asm-powerpc/termios.h @@ -0,0 +1,236 @@ +#ifndef _POWERPC_TERMIOS_H +#define _POWERPC_TERMIOS_H + +/* + * Liberally adapted from alpha/termios.h. In particular, the c_cc[] + * fields have been reordered so that termio & termios share the + * common subset in the same order (for brain dead programs that don't + * know or care about the differences). + * + * 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. + */ + +#include +#include + +struct sgttyb { + char sg_ispeed; + char sg_ospeed; + char sg_erase; + char sg_kill; + short sg_flags; +}; + +struct tchars { + char t_intrc; + char t_quitc; + char t_startc; + char t_stopc; + char t_eofc; + char t_brkc; +}; + +struct ltchars { + char t_suspc; + char t_dsuspc; + char t_rprntc; + char t_flushc; + char t_werasc; + char t_lnextc; +}; + +struct winsize { + unsigned short ws_row; + unsigned short ws_col; + unsigned short ws_xpixel; + unsigned short ws_ypixel; +}; + +#define NCC 10 +struct termio { + unsigned short c_iflag; /* input mode flags */ + unsigned short c_oflag; /* output mode flags */ + unsigned short c_cflag; /* control mode flags */ + unsigned short c_lflag; /* local mode flags */ + unsigned char c_line; /* line discipline */ + unsigned char c_cc[NCC]; /* control characters */ +}; + +/* c_cc characters */ +#define _VINTR 0 +#define _VQUIT 1 +#define _VERASE 2 +#define _VKILL 3 +#define _VEOF 4 +#define _VMIN 5 +#define _VEOL 6 +#define _VTIME 7 +#define _VEOL2 8 +#define _VSWTC 9 + +/* line disciplines */ +#define N_TTY 0 +#define N_SLIP 1 +#define N_MOUSE 2 +#define N_PPP 3 +#define N_STRIP 4 +#define N_AX25 5 +#define N_X25 6 /* X.25 async */ +#define N_6PACK 7 +#define N_MASC 8 /* Reserved for Mobitex module */ +#define N_R3964 9 /* Reserved for Simatic R3964 module */ +#define N_PROFIBUS_FDL 10 /* Reserved for Profibus */ +#define N_IRDA 11 /* Linux IrDa - http://www.cs.uit.no/~dagb/irda/irda.html */ +#define N_SMSBLOCK 12 /* SMS block mode - for talking to GSM data cards about SMS messages */ +#define N_HDLC 13 /* synchronous HDLC */ +#define N_SYNC_PPP 14 +#define N_HCI 15 /* Bluetooth HCI UART */ + +#ifdef __KERNEL__ +/* ^C ^\ del ^U ^D 1 0 0 0 0 ^W ^R ^Z ^Q ^S ^V ^U */ +#define INIT_C_CC "\003\034\177\025\004\001\000\000\000\000\027\022\032\021\023\026\025" +#endif + +#define FIOCLEX _IO('f', 1) +#define FIONCLEX _IO('f', 2) +#define FIOASYNC _IOW('f', 125, int) +#define FIONBIO _IOW('f', 126, int) +#define FIONREAD _IOR('f', 127, int) +#define TIOCINQ FIONREAD + +#define TIOCGETP _IOR('t', 8, struct sgttyb) +#define TIOCSETP _IOW('t', 9, struct sgttyb) +#define TIOCSETN _IOW('t', 10, struct sgttyb) /* TIOCSETP wo flush */ + +#define TIOCSETC _IOW('t', 17, struct tchars) +#define TIOCGETC _IOR('t', 18, struct tchars) +#define TCGETS _IOR('t', 19, struct termios) +#define TCSETS _IOW('t', 20, struct termios) +#define TCSETSW _IOW('t', 21, struct termios) +#define TCSETSF _IOW('t', 22, struct termios) + +#define TCGETA _IOR('t', 23, struct termio) +#define TCSETA _IOW('t', 24, struct termio) +#define TCSETAW _IOW('t', 25, struct termio) +#define TCSETAF _IOW('t', 28, struct termio) + +#define TCSBRK _IO('t', 29) +#define TCXONC _IO('t', 30) +#define TCFLSH _IO('t', 31) + +#define TIOCSWINSZ _IOW('t', 103, struct winsize) +#define TIOCGWINSZ _IOR('t', 104, struct winsize) +#define TIOCSTART _IO('t', 110) /* start output, like ^Q */ +#define TIOCSTOP _IO('t', 111) /* stop output, like ^S */ +#define TIOCOUTQ _IOR('t', 115, int) /* output queue size */ + +#define TIOCGLTC _IOR('t', 116, struct ltchars) +#define TIOCSLTC _IOW('t', 117, struct ltchars) +#define TIOCSPGRP _IOW('t', 118, int) +#define TIOCGPGRP _IOR('t', 119, int) + +#define TIOCEXCL 0x540C +#define TIOCNXCL 0x540D +#define TIOCSCTTY 0x540E + +#define TIOCSTI 0x5412 +#define TIOCMGET 0x5415 +#define TIOCMBIS 0x5416 +#define TIOCMBIC 0x5417 +#define TIOCMSET 0x5418 +#define TIOCGSOFTCAR 0x5419 +#define TIOCSSOFTCAR 0x541A +#define TIOCLINUX 0x541C +#define TIOCCONS 0x541D +#define TIOCGSERIAL 0x541E +#define TIOCSSERIAL 0x541F +#define TIOCPKT 0x5420 + +#define TIOCNOTTY 0x5422 +#define TIOCSETD 0x5423 +#define TIOCGETD 0x5424 +#define TCSBRKP 0x5425 /* Needed for POSIX tcsendbreak() */ + +#define TIOCSERCONFIG 0x5453 +#define TIOCSERGWILD 0x5454 +#define TIOCSERSWILD 0x5455 +#define TIOCGLCKTRMIOS 0x5456 +#define TIOCSLCKTRMIOS 0x5457 +#define TIOCSERGSTRUCT 0x5458 /* For debugging only */ +#define TIOCSERGETLSR 0x5459 /* Get line status register */ +#define TIOCSERGETMULTI 0x545A /* Get multiport config */ +#define TIOCSERSETMULTI 0x545B /* Set multiport config */ + +#define TIOCMIWAIT 0x545C /* wait for a change on serial input line(s) */ +#define TIOCGICOUNT 0x545D /* read serial port inline interrupt counts */ + +/* Used for packet mode */ +#define TIOCPKT_DATA 0 +#define TIOCPKT_FLUSHREAD 1 +#define TIOCPKT_FLUSHWRITE 2 +#define TIOCPKT_STOP 4 +#define TIOCPKT_START 8 +#define TIOCPKT_NOSTOP 16 +#define TIOCPKT_DOSTOP 32 + +/* modem lines */ +#define TIOCM_LE 0x001 +#define TIOCM_DTR 0x002 +#define TIOCM_RTS 0x004 +#define TIOCM_ST 0x008 +#define TIOCM_SR 0x010 +#define TIOCM_CTS 0x020 +#define TIOCM_CAR 0x040 +#define TIOCM_RNG 0x080 +#define TIOCM_DSR 0x100 +#define TIOCM_CD TIOCM_CAR +#define TIOCM_RI TIOCM_RNG +#define TIOCM_OUT1 0x2000 +#define TIOCM_OUT2 0x4000 +#define TIOCM_LOOP 0x8000 + +/* ioctl (fd, TIOCSERGETLSR, &result) where result may be as below */ +#define TIOCSER_TEMT 0x01 /* Transmitter physically empty */ + +#ifdef __KERNEL__ + +/* + * Translate a "termio" structure into a "termios". Ugh. + */ +#define SET_LOW_TERMIOS_BITS(termios, termio, x) { \ + unsigned short __tmp; \ + get_user(__tmp,&(termio)->x); \ + (termios)->x = (0xffff0000 & (termios)->x) | __tmp; \ +} + +#define user_termio_to_kernel_termios(termios, termio) \ +({ \ + SET_LOW_TERMIOS_BITS(termios, termio, c_iflag); \ + SET_LOW_TERMIOS_BITS(termios, termio, c_oflag); \ + SET_LOW_TERMIOS_BITS(termios, termio, c_cflag); \ + SET_LOW_TERMIOS_BITS(termios, termio, c_lflag); \ + copy_from_user((termios)->c_cc, (termio)->c_cc, NCC); \ +}) + +/* + * Translate a "termios" structure into a "termio". Ugh. + */ +#define kernel_termios_to_user_termio(termio, termios) \ +({ \ + put_user((termios)->c_iflag, &(termio)->c_iflag); \ + put_user((termios)->c_oflag, &(termio)->c_oflag); \ + put_user((termios)->c_cflag, &(termio)->c_cflag); \ + put_user((termios)->c_lflag, &(termio)->c_lflag); \ + put_user((termios)->c_line, &(termio)->c_line); \ + copy_to_user((termio)->c_cc, (termios)->c_cc, NCC); \ +}) + +#define user_termios_to_kernel_termios(k, u) copy_from_user(k, u, sizeof(struct termios)) +#define kernel_termios_to_user_termios(u, k) copy_to_user(u, k, sizeof(struct termios)) + +#endif /* __KERNEL__ */ + +#endif /* _POWERPC_TERMIOS_H */ diff --git a/include/asm-ppc/mman.h b/include/asm-ppc/mman.h deleted file mode 100644 --- a/include/asm-ppc/mman.h +++ /dev/null @@ -1,44 +0,0 @@ -#ifndef __PPC_MMAN_H__ -#define __PPC_MMAN_H__ - -#define PROT_READ 0x1 /* page can be read */ -#define PROT_WRITE 0x2 /* page can be written */ -#define PROT_EXEC 0x4 /* page can be executed */ -#define PROT_SEM 0x8 /* page may be used for atomic ops */ -#define PROT_NONE 0x0 /* page can not be accessed */ -#define PROT_GROWSDOWN 0x01000000 /* mprotect flag: extend change to start of growsdown vma */ -#define PROT_GROWSUP 0x02000000 /* mprotect flag: extend change to end of growsup vma */ - -#define MAP_SHARED 0x01 /* Share changes */ -#define MAP_PRIVATE 0x02 /* Changes are private */ -#define MAP_TYPE 0x0f /* Mask for type of mapping */ -#define MAP_FIXED 0x10 /* Interpret addr exactly */ -#define MAP_ANONYMOUS 0x20 /* don't use a file */ -#define MAP_RENAME MAP_ANONYMOUS /* In SunOS terminology */ -#define MAP_NORESERVE 0x40 /* don't reserve swap pages */ -#define MAP_LOCKED 0x80 - -#define MAP_GROWSDOWN 0x0100 /* stack-like segment */ -#define MAP_DENYWRITE 0x0800 /* ETXTBSY */ -#define MAP_EXECUTABLE 0x1000 /* mark it as an executable */ -#define MAP_POPULATE 0x8000 /* populate (prefault) pagetables */ -#define MAP_NONBLOCK 0x10000 /* do not block on IO */ - -#define MS_ASYNC 1 /* sync memory asynchronously */ -#define MS_INVALIDATE 2 /* invalidate the caches */ -#define MS_SYNC 4 /* synchronous memory sync */ - -#define MCL_CURRENT 0x2000 /* lock all currently mapped pages */ -#define MCL_FUTURE 0x4000 /* lock all additions to address space */ - -#define MADV_NORMAL 0x0 /* default page-in behavior */ -#define MADV_RANDOM 0x1 /* page-in minimum required */ -#define MADV_SEQUENTIAL 0x2 /* read-ahead aggressively */ -#define MADV_WILLNEED 0x3 /* pre-fault pages */ -#define MADV_DONTNEED 0x4 /* discard these pages */ - -/* compatibility flags */ -#define MAP_ANON MAP_ANONYMOUS -#define MAP_FILE 0 - -#endif /* __PPC_MMAN_H__ */ diff --git a/include/asm-ppc/termbits.h b/include/asm-ppc/termbits.h deleted file mode 100644 --- a/include/asm-ppc/termbits.h +++ /dev/null @@ -1,185 +0,0 @@ -#ifndef _PPC_TERMBITS_H -#define _PPC_TERMBITS_H - -typedef unsigned char cc_t; -typedef unsigned int speed_t; -typedef unsigned int tcflag_t; - -/* - * termios type and macro definitions. Be careful about adding stuff - * to this file since it's used in GNU libc and there are strict rules - * concerning namespace pollution. - */ - -#define NCCS 19 -struct termios { - tcflag_t c_iflag; /* input mode flags */ - tcflag_t c_oflag; /* output mode flags */ - tcflag_t c_cflag; /* control mode flags */ - tcflag_t c_lflag; /* local mode flags */ - cc_t c_cc[NCCS]; /* control characters */ - cc_t c_line; /* line discipline (== c_cc[19]) */ - speed_t c_ispeed; /* input speed */ - speed_t c_ospeed; /* output speed */ -}; - -/* c_cc characters */ -#define VINTR 0 -#define VQUIT 1 -#define VERASE 2 -#define VKILL 3 -#define VEOF 4 -#define VMIN 5 -#define VEOL 6 -#define VTIME 7 -#define VEOL2 8 -#define VSWTC 9 - -#define VWERASE 10 -#define VREPRINT 11 -#define VSUSP 12 -#define VSTART 13 -#define VSTOP 14 -#define VLNEXT 15 -#define VDISCARD 16 - -/* c_iflag bits */ -#define IGNBRK 0000001 -#define BRKINT 0000002 -#define IGNPAR 0000004 -#define PARMRK 0000010 -#define INPCK 0000020 -#define ISTRIP 0000040 -#define INLCR 0000100 -#define IGNCR 0000200 -#define ICRNL 0000400 -#define IXON 0001000 -#define IXOFF 0002000 -#define IXANY 0004000 -#define IUCLC 0010000 -#define IMAXBEL 0020000 -#define IUTF8 0040000 - -/* c_oflag bits */ -#define OPOST 0000001 -#define ONLCR 0000002 -#define OLCUC 0000004 - -#define OCRNL 0000010 -#define ONOCR 0000020 -#define ONLRET 0000040 - -#define OFILL 00000100 -#define OFDEL 00000200 -#define NLDLY 00001400 -#define NL0 00000000 -#define NL1 00000400 -#define NL2 00001000 -#define NL3 00001400 -#define TABDLY 00006000 -#define TAB0 00000000 -#define TAB1 00002000 -#define TAB2 00004000 -#define TAB3 00006000 -#define XTABS 00006000 /* required by POSIX to == TAB3 */ -#define CRDLY 00030000 -#define CR0 00000000 -#define CR1 00010000 -#define CR2 00020000 -#define CR3 00030000 -#define FFDLY 00040000 -#define FF0 00000000 -#define FF1 00040000 -#define BSDLY 00100000 -#define BS0 00000000 -#define BS1 00100000 -#define VTDLY 00200000 -#define VT0 00000000 -#define VT1 00200000 - -/* c_cflag bit meaning */ -#define CBAUD 0000377 -#define B0 0000000 /* hang up */ -#define B50 0000001 -#define B75 0000002 -#define B110 0000003 -#define B134 0000004 -#define B150 0000005 -#define B200 0000006 -#define B300 0000007 -#define B600 0000010 -#define B1200 0000011 -#define B1800 0000012 -#define B2400 0000013 -#define B4800 0000014 -#define B9600 0000015 -#define B19200 0000016 -#define B38400 0000017 -#define EXTA B19200 -#define EXTB B38400 -#define CBAUDEX 0000000 -#define B57600 00020 -#define B115200 00021 -#define B230400 00022 -#define B460800 00023 -#define B500000 00024 -#define B576000 00025 -#define B921600 00026 -#define B1000000 00027 -#define B1152000 00030 -#define B1500000 00031 -#define B2000000 00032 -#define B2500000 00033 -#define B3000000 00034 -#define B3500000 00035 -#define B4000000 00036 - -#define CSIZE 00001400 -#define CS5 00000000 -#define CS6 00000400 -#define CS7 00001000 -#define CS8 00001400 - -#define CSTOPB 00002000 -#define CREAD 00004000 -#define PARENB 00010000 -#define PARODD 00020000 -#define HUPCL 00040000 - -#define CLOCAL 00100000 -#define CRTSCTS 020000000000 /* flow control */ - -/* c_lflag bits */ -#define ISIG 0x00000080 -#define ICANON 0x00000100 -#define XCASE 0x00004000 -#define ECHO 0x00000008 -#define ECHOE 0x00000002 -#define ECHOK 0x00000004 -#define ECHONL 0x00000010 -#define NOFLSH 0x80000000 -#define TOSTOP 0x00400000 -#define ECHOCTL 0x00000040 -#define ECHOPRT 0x00000020 -#define ECHOKE 0x00000001 -#define FLUSHO 0x00800000 -#define PENDIN 0x20000000 -#define IEXTEN 0x00000400 - -/* Values for the ACTION argument to `tcflow'. */ -#define TCOOFF 0 -#define TCOON 1 -#define TCIOFF 2 -#define TCION 3 - -/* Values for the QUEUE_SELECTOR argument to `tcflush'. */ -#define TCIFLUSH 0 -#define TCOFLUSH 1 -#define TCIOFLUSH 2 - -/* Values for the OPTIONAL_ACTIONS argument to `tcsetattr'. */ -#define TCSANOW 0 -#define TCSADRAIN 1 -#define TCSAFLUSH 2 - -#endif /* _PPC_TERMBITS_H */ diff --git a/include/asm-ppc/termios.h b/include/asm-ppc/termios.h deleted file mode 100644 --- a/include/asm-ppc/termios.h +++ /dev/null @@ -1,232 +0,0 @@ -#ifndef _PPC_TERMIOS_H -#define _PPC_TERMIOS_H - -/* - * Liberally adapted from alpha/termios.h. In particular, the c_cc[] - * fields have been reordered so that termio & termios share the - * common subset in the same order (for brain dead programs that don't - * know or care about the differences). - */ - -#include -#include - -struct sgttyb { - char sg_ispeed; - char sg_ospeed; - char sg_erase; - char sg_kill; - short sg_flags; -}; - -struct tchars { - char t_intrc; - char t_quitc; - char t_startc; - char t_stopc; - char t_eofc; - char t_brkc; -}; - -struct ltchars { - char t_suspc; - char t_dsuspc; - char t_rprntc; - char t_flushc; - char t_werasc; - char t_lnextc; -}; - -#define FIOCLEX _IO('f', 1) -#define FIONCLEX _IO('f', 2) -#define FIOASYNC _IOW('f', 125, int) -#define FIONBIO _IOW('f', 126, int) -#define FIONREAD _IOR('f', 127, int) -#define TIOCINQ FIONREAD -#define FIOQSIZE _IOR('f', 128, loff_t) - -#define TIOCGETP _IOR('t', 8, struct sgttyb) -#define TIOCSETP _IOW('t', 9, struct sgttyb) -#define TIOCSETN _IOW('t', 10, struct sgttyb) /* TIOCSETP wo flush */ - -#define TIOCSETC _IOW('t', 17, struct tchars) -#define TIOCGETC _IOR('t', 18, struct tchars) -#define TCGETS _IOR('t', 19, struct termios) -#define TCSETS _IOW('t', 20, struct termios) -#define TCSETSW _IOW('t', 21, struct termios) -#define TCSETSF _IOW('t', 22, struct termios) - -#define TCGETA _IOR('t', 23, struct termio) -#define TCSETA _IOW('t', 24, struct termio) -#define TCSETAW _IOW('t', 25, struct termio) -#define TCSETAF _IOW('t', 28, struct termio) - -#define TCSBRK _IO('t', 29) -#define TCXONC _IO('t', 30) -#define TCFLSH _IO('t', 31) - -#define TIOCSWINSZ _IOW('t', 103, struct winsize) -#define TIOCGWINSZ _IOR('t', 104, struct winsize) -#define TIOCSTART _IO('t', 110) /* start output, like ^Q */ -#define TIOCSTOP _IO('t', 111) /* stop output, like ^S */ -#define TIOCOUTQ _IOR('t', 115, int) /* output queue size */ - -#define TIOCGLTC _IOR('t', 116, struct ltchars) -#define TIOCSLTC _IOW('t', 117, struct ltchars) -#define TIOCSPGRP _IOW('t', 118, int) -#define TIOCGPGRP _IOR('t', 119, int) - -#define TIOCEXCL 0x540C -#define TIOCNXCL 0x540D -#define TIOCSCTTY 0x540E - -#define TIOCSTI 0x5412 -#define TIOCMGET 0x5415 -#define TIOCMBIS 0x5416 -#define TIOCMBIC 0x5417 -#define TIOCMSET 0x5418 -#define TIOCGSOFTCAR 0x5419 -#define TIOCSSOFTCAR 0x541A -#define TIOCLINUX 0x541C -#define TIOCCONS 0x541D -#define TIOCGSERIAL 0x541E -#define TIOCSSERIAL 0x541F -#define TIOCPKT 0x5420 - -#define TIOCNOTTY 0x5422 -#define TIOCSETD 0x5423 -#define TIOCGETD 0x5424 -#define TCSBRKP 0x5425 /* Needed for POSIX tcsendbreak() */ - -#define TIOCSERCONFIG 0x5453 -#define TIOCSERGWILD 0x5454 -#define TIOCSERSWILD 0x5455 -#define TIOCGLCKTRMIOS 0x5456 -#define TIOCSLCKTRMIOS 0x5457 -#define TIOCSERGSTRUCT 0x5458 /* For debugging only */ -#define TIOCSERGETLSR 0x5459 /* Get line status register */ -#define TIOCSERGETMULTI 0x545A /* Get multiport config */ -#define TIOCSERSETMULTI 0x545B /* Set multiport config */ - -#define TIOCMIWAIT 0x545C /* wait for a change on serial input line(s) */ -#define TIOCGICOUNT 0x545D /* read serial port inline interrupt counts */ - -/* Used for packet mode */ -#define TIOCPKT_DATA 0 -#define TIOCPKT_FLUSHREAD 1 -#define TIOCPKT_FLUSHWRITE 2 -#define TIOCPKT_STOP 4 -#define TIOCPKT_START 8 -#define TIOCPKT_NOSTOP 16 -#define TIOCPKT_DOSTOP 32 - -struct winsize { - unsigned short ws_row; - unsigned short ws_col; - unsigned short ws_xpixel; - unsigned short ws_ypixel; -}; - -#define NCC 10 -struct termio { - unsigned short c_iflag; /* input mode flags */ - unsigned short c_oflag; /* output mode flags */ - unsigned short c_cflag; /* control mode flags */ - unsigned short c_lflag; /* local mode flags */ - unsigned char c_line; /* line discipline */ - unsigned char c_cc[NCC]; /* control characters */ -}; - -/* c_cc characters */ -#define _VINTR 0 -#define _VQUIT 1 -#define _VERASE 2 -#define _VKILL 3 -#define _VEOF 4 -#define _VMIN 5 -#define _VEOL 6 -#define _VTIME 7 -#define _VEOL2 8 -#define _VSWTC 9 - -#ifdef __KERNEL__ -/* ^C ^\ del ^U ^D 1 0 0 0 0 ^W ^R ^Z ^Q ^S ^V ^U */ -#define INIT_C_CC "\003\034\177\025\004\001\000\000\000\000\027\022\032\021\023\026\025" -#endif /* __KERNEL__ */ - -/* modem lines */ -#define TIOCM_LE 0x001 -#define TIOCM_DTR 0x002 -#define TIOCM_RTS 0x004 -#define TIOCM_ST 0x008 -#define TIOCM_SR 0x010 -#define TIOCM_CTS 0x020 -#define TIOCM_CAR 0x040 -#define TIOCM_RNG 0x080 -#define TIOCM_DSR 0x100 -#define TIOCM_CD TIOCM_CAR -#define TIOCM_RI TIOCM_RNG -#define TIOCM_OUT1 0x2000 -#define TIOCM_OUT2 0x4000 -#define TIOCM_LOOP 0x8000 - -/* ioctl (fd, TIOCSERGETLSR, &result) where result may be as below */ -#define TIOCSER_TEMT 0x01 /* Transmitter physically empty */ - -/* line disciplines */ -#define N_TTY 0 -#define N_SLIP 1 -#define N_MOUSE 2 -#define N_PPP 3 -#define N_STRIP 4 -#define N_AX25 5 -#define N_X25 6 /* X.25 async */ -#define N_6PACK 7 -#define N_MASC 8 /* Reserved for Mobitex module */ -#define N_R3964 9 /* Reserved for Simatic R3964 module */ -#define N_PROFIBUS_FDL 10 /* Reserved for Profibus */ -#define N_IRDA 11 /* Linux IrDa - http://irda.sourceforge.net/ */ -#define N_SMSBLOCK 12 /* SMS block mode - for talking to GSM data cards about SMS messages */ -#define N_HDLC 13 /* synchronous HDLC */ -#define N_SYNC_PPP 14 -#define N_HCI 15 /* Bluetooth HCI UART */ - -#ifdef __KERNEL__ - -/* - * Translate a "termio" structure into a "termios". Ugh. - */ -#define SET_LOW_TERMIOS_BITS(termios, termio, x) { \ - unsigned short __tmp; \ - get_user(__tmp,&(termio)->x); \ - (termios)->x = (0xffff0000 & (termios)->x) | __tmp; \ -} - -#define user_termio_to_kernel_termios(termios, termio) \ -({ \ - SET_LOW_TERMIOS_BITS(termios, termio, c_iflag); \ - SET_LOW_TERMIOS_BITS(termios, termio, c_oflag); \ - SET_LOW_TERMIOS_BITS(termios, termio, c_cflag); \ - SET_LOW_TERMIOS_BITS(termios, termio, c_lflag); \ - copy_from_user((termios)->c_cc, (termio)->c_cc, NCC); \ -}) - -/* - * Translate a "termios" structure into a "termio". Ugh. - */ -#define kernel_termios_to_user_termio(termio, termios) \ -({ \ - put_user((termios)->c_iflag, &(termio)->c_iflag); \ - put_user((termios)->c_oflag, &(termio)->c_oflag); \ - put_user((termios)->c_cflag, &(termio)->c_cflag); \ - put_user((termios)->c_lflag, &(termio)->c_lflag); \ - put_user((termios)->c_line, &(termio)->c_line); \ - copy_to_user((termio)->c_cc, (termios)->c_cc, NCC); \ -}) - -#define user_termios_to_kernel_termios(k, u) copy_from_user(k, u, sizeof(struct termios)) -#define kernel_termios_to_user_termios(u, k) copy_to_user(u, k, sizeof(struct termios)) - -#endif /* __KERNEL__ */ - -#endif /* _PPC_TERMIOS_H */ diff --git a/include/asm-ppc64/mman.h b/include/asm-ppc64/mman.h deleted file mode 100644 --- a/include/asm-ppc64/mman.h +++ /dev/null @@ -1,52 +0,0 @@ -#ifndef __PPC64_MMAN_H__ -#define __PPC64_MMAN_H__ - -/* - * 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. - */ - -#define PROT_READ 0x1 /* page can be read */ -#define PROT_WRITE 0x2 /* page can be written */ -#define PROT_EXEC 0x4 /* page can be executed */ -#define PROT_SEM 0x8 /* page may be used for atomic ops */ -#define PROT_NONE 0x0 /* page can not be accessed */ -#define PROT_GROWSDOWN 0x01000000 /* mprotect flag: extend change to start of growsdown vma */ -#define PROT_GROWSUP 0x02000000 /* mprotect flag: extend change to end of growsup vma */ - -#define MAP_SHARED 0x01 /* Share changes */ -#define MAP_PRIVATE 0x02 /* Changes are private */ -#define MAP_TYPE 0x0f /* Mask for type of mapping */ -#define MAP_FIXED 0x10 /* Interpret addr exactly */ -#define MAP_ANONYMOUS 0x20 /* don't use a file */ -#define MAP_RENAME MAP_ANONYMOUS /* In SunOS terminology */ -#define MAP_NORESERVE 0x40 /* don't reserve swap pages */ -#define MAP_LOCKED 0x80 - -#define MAP_GROWSDOWN 0x0100 /* stack-like segment */ -#define MAP_DENYWRITE 0x0800 /* ETXTBSY */ -#define MAP_EXECUTABLE 0x1000 /* mark it as an executable */ - -#define MS_ASYNC 1 /* sync memory asynchronously */ -#define MS_INVALIDATE 2 /* invalidate the caches */ -#define MS_SYNC 4 /* synchronous memory sync */ - -#define MCL_CURRENT 0x2000 /* lock all currently mapped pages */ -#define MCL_FUTURE 0x4000 /* lock all additions to address space */ - -#define MAP_POPULATE 0x8000 /* populate (prefault) pagetables */ -#define MAP_NONBLOCK 0x10000 /* do not block on IO */ - -#define MADV_NORMAL 0x0 /* default page-in behavior */ -#define MADV_RANDOM 0x1 /* page-in minimum required */ -#define MADV_SEQUENTIAL 0x2 /* read-ahead aggressively */ -#define MADV_WILLNEED 0x3 /* pre-fault pages */ -#define MADV_DONTNEED 0x4 /* discard these pages */ - -/* compatibility flags */ -#define MAP_ANON MAP_ANONYMOUS -#define MAP_FILE 0 - -#endif /* __PPC64_MMAN_H__ */ diff --git a/include/asm-ppc64/termbits.h b/include/asm-ppc64/termbits.h deleted file mode 100644 --- a/include/asm-ppc64/termbits.h +++ /dev/null @@ -1,193 +0,0 @@ -#ifndef _PPC64_TERMBITS_H -#define _PPC64_TERMBITS_H - -/* - * 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. - */ - -#include - -typedef unsigned char cc_t; -typedef unsigned int speed_t; -typedef unsigned int tcflag_t; - -/* - * termios type and macro definitions. Be careful about adding stuff - * to this file since it's used in GNU libc and there are strict rules - * concerning namespace pollution. - */ - -#define NCCS 19 -struct termios { - tcflag_t c_iflag; /* input mode flags */ - tcflag_t c_oflag; /* output mode flags */ - tcflag_t c_cflag; /* control mode flags */ - tcflag_t c_lflag; /* local mode flags */ - cc_t c_cc[NCCS]; /* control characters */ - cc_t c_line; /* line discipline (== c_cc[19]) */ - speed_t c_ispeed; /* input speed */ - speed_t c_ospeed; /* output speed */ -}; - -/* c_cc characters */ -#define VINTR 0 -#define VQUIT 1 -#define VERASE 2 -#define VKILL 3 -#define VEOF 4 -#define VMIN 5 -#define VEOL 6 -#define VTIME 7 -#define VEOL2 8 -#define VSWTC 9 -#define VWERASE 10 -#define VREPRINT 11 -#define VSUSP 12 -#define VSTART 13 -#define VSTOP 14 -#define VLNEXT 15 -#define VDISCARD 16 - -/* c_iflag bits */ -#define IGNBRK 0000001 -#define BRKINT 0000002 -#define IGNPAR 0000004 -#define PARMRK 0000010 -#define INPCK 0000020 -#define ISTRIP 0000040 -#define INLCR 0000100 -#define IGNCR 0000200 -#define ICRNL 0000400 -#define IXON 0001000 -#define IXOFF 0002000 -#define IXANY 0004000 -#define IUCLC 0010000 -#define IMAXBEL 0020000 -#define IUTF8 0040000 - -/* c_oflag bits */ -#define OPOST 0000001 -#define ONLCR 0000002 -#define OLCUC 0000004 - -#define OCRNL 0000010 -#define ONOCR 0000020 -#define ONLRET 0000040 - -#define OFILL 00000100 -#define OFDEL 00000200 -#define NLDLY 00001400 -#define NL0 00000000 -#define NL1 00000400 -#define NL2 00001000 -#define NL3 00001400 -#define TABDLY 00006000 -#define TAB0 00000000 -#define TAB1 00002000 -#define TAB2 00004000 -#define TAB3 00006000 -#define XTABS 00006000 /* required by POSIX to == TAB3 */ -#define CRDLY 00030000 -#define CR0 00000000 -#define CR1 00010000 -#define CR2 00020000 -#define CR3 00030000 -#define FFDLY 00040000 -#define FF0 00000000 -#define FF1 00040000 -#define BSDLY 00100000 -#define BS0 00000000 -#define BS1 00100000 -#define VTDLY 00200000 -#define VT0 00000000 -#define VT1 00200000 - -/* c_cflag bit meaning */ -#define CBAUD 0000377 -#define B0 0000000 /* hang up */ -#define B50 0000001 -#define B75 0000002 -#define B110 0000003 -#define B134 0000004 -#define B150 0000005 -#define B200 0000006 -#define B300 0000007 -#define B600 0000010 -#define B1200 0000011 -#define B1800 0000012 -#define B2400 0000013 -#define B4800 0000014 -#define B9600 0000015 -#define B19200 0000016 -#define B38400 0000017 -#define EXTA B19200 -#define EXTB B38400 -#define CBAUDEX 0000000 -#define B57600 00020 -#define B115200 00021 -#define B230400 00022 -#define B460800 00023 -#define B500000 00024 -#define B576000 00025 -#define B921600 00026 -#define B1000000 00027 -#define B1152000 00030 -#define B1500000 00031 -#define B2000000 00032 -#define B2500000 00033 -#define B3000000 00034 -#define B3500000 00035 -#define B4000000 00036 - -#define CSIZE 00001400 -#define CS5 00000000 -#define CS6 00000400 -#define CS7 00001000 -#define CS8 00001400 - -#define CSTOPB 00002000 -#define CREAD 00004000 -#define PARENB 00010000 -#define PARODD 00020000 -#define HUPCL 00040000 - -#define CLOCAL 00100000 -#define CRTSCTS 020000000000 /* flow control */ - -/* c_lflag bits */ -#define ISIG 0x00000080 -#define ICANON 0x00000100 -#define XCASE 0x00004000 -#define ECHO 0x00000008 -#define ECHOE 0x00000002 -#define ECHOK 0x00000004 -#define ECHONL 0x00000010 -#define NOFLSH 0x80000000 -#define TOSTOP 0x00400000 -#define ECHOCTL 0x00000040 -#define ECHOPRT 0x00000020 -#define ECHOKE 0x00000001 -#define FLUSHO 0x00800000 -#define PENDIN 0x20000000 -#define IEXTEN 0x00000400 - -/* Values for the ACTION argument to `tcflow'. */ -#define TCOOFF 0 -#define TCOON 1 -#define TCIOFF 2 -#define TCION 3 - -/* Values for the QUEUE_SELECTOR argument to `tcflush'. */ -#define TCIFLUSH 0 -#define TCOFLUSH 1 -#define TCIOFLUSH 2 - -/* Values for the OPTIONAL_ACTIONS argument to `tcsetattr'. */ -#define TCSANOW 0 -#define TCSADRAIN 1 -#define TCSAFLUSH 2 - -#endif /* _PPC64_TERMBITS_H */ diff --git a/include/asm-ppc64/termios.h b/include/asm-ppc64/termios.h deleted file mode 100644 --- a/include/asm-ppc64/termios.h +++ /dev/null @@ -1,235 +0,0 @@ -#ifndef _PPC64_TERMIOS_H -#define _PPC64_TERMIOS_H - -/* - * Liberally adapted from alpha/termios.h. In particular, the c_cc[] - * fields have been reordered so that termio & termios share the - * common subset in the same order (for brain dead programs that don't - * know or care about the differences). - * - * 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. - */ - -#include -#include - -struct sgttyb { - char sg_ispeed; - char sg_ospeed; - char sg_erase; - char sg_kill; - short sg_flags; -}; - -struct tchars { - char t_intrc; - char t_quitc; - char t_startc; - char t_stopc; - char t_eofc; - char t_brkc; -}; - -struct ltchars { - char t_suspc; - char t_dsuspc; - char t_rprntc; - char t_flushc; - char t_werasc; - char t_lnextc; -}; - -struct winsize { - unsigned short ws_row; - unsigned short ws_col; - unsigned short ws_xpixel; - unsigned short ws_ypixel; -}; - -#define NCC 10 -struct termio { - unsigned short c_iflag; /* input mode flags */ - unsigned short c_oflag; /* output mode flags */ - unsigned short c_cflag; /* control mode flags */ - unsigned short c_lflag; /* local mode flags */ - unsigned char c_line; /* line discipline */ - unsigned char c_cc[NCC]; /* control characters */ -}; - -/* c_cc characters */ -#define _VINTR 0 -#define _VQUIT 1 -#define _VERASE 2 -#define _VKILL 3 -#define _VEOF 4 -#define _VMIN 5 -#define _VEOL 6 -#define _VTIME 7 -#define _VEOL2 8 -#define _VSWTC 9 - -/* line disciplines */ -#define N_TTY 0 -#define N_SLIP 1 -#define N_MOUSE 2 -#define N_PPP 3 -#define N_STRIP 4 -#define N_AX25 5 -#define N_X25 6 /* X.25 async */ -#define N_6PACK 7 -#define N_MASC 8 /* Reserved for Mobitex module */ -#define N_R3964 9 /* Reserved for Simatic R3964 module */ -#define N_PROFIBUS_FDL 10 /* Reserved for Profibus */ -#define N_IRDA 11 /* Linux IrDa - http://www.cs.uit.no/~dagb/irda/irda.html */ -#define N_SMSBLOCK 12 /* SMS block mode - for talking to GSM data cards about SMS messages */ -#define N_HDLC 13 /* synchronous HDLC */ -#define N_SYNC_PPP 14 - -#ifdef __KERNEL__ -/* ^C ^\ del ^U ^D 1 0 0 0 0 ^W ^R ^Z ^Q ^S ^V ^U */ -#define INIT_C_CC "\003\034\177\025\004\001\000\000\000\000\027\022\032\021\023\026\025" -#endif - -#define FIOCLEX _IO('f', 1) -#define FIONCLEX _IO('f', 2) -#define FIOASYNC _IOW('f', 125, int) -#define FIONBIO _IOW('f', 126, int) -#define FIONREAD _IOR('f', 127, int) -#define TIOCINQ FIONREAD - -#define TIOCGETP _IOR('t', 8, struct sgttyb) -#define TIOCSETP _IOW('t', 9, struct sgttyb) -#define TIOCSETN _IOW('t', 10, struct sgttyb) /* TIOCSETP wo flush */ - -#define TIOCSETC _IOW('t', 17, struct tchars) -#define TIOCGETC _IOR('t', 18, struct tchars) -#define TCGETS _IOR('t', 19, struct termios) -#define TCSETS _IOW('t', 20, struct termios) -#define TCSETSW _IOW('t', 21, struct termios) -#define TCSETSF _IOW('t', 22, struct termios) - -#define TCGETA _IOR('t', 23, struct termio) -#define TCSETA _IOW('t', 24, struct termio) -#define TCSETAW _IOW('t', 25, struct termio) -#define TCSETAF _IOW('t', 28, struct termio) - -#define TCSBRK _IO('t', 29) -#define TCXONC _IO('t', 30) -#define TCFLSH _IO('t', 31) - -#define TIOCSWINSZ _IOW('t', 103, struct winsize) -#define TIOCGWINSZ _IOR('t', 104, struct winsize) -#define TIOCSTART _IO('t', 110) /* start output, like ^Q */ -#define TIOCSTOP _IO('t', 111) /* stop output, like ^S */ -#define TIOCOUTQ _IOR('t', 115, int) /* output queue size */ - -#define TIOCGLTC _IOR('t', 116, struct ltchars) -#define TIOCSLTC _IOW('t', 117, struct ltchars) -#define TIOCSPGRP _IOW('t', 118, int) -#define TIOCGPGRP _IOR('t', 119, int) - -#define TIOCEXCL 0x540C -#define TIOCNXCL 0x540D -#define TIOCSCTTY 0x540E - -#define TIOCSTI 0x5412 -#define TIOCMGET 0x5415 -#define TIOCMBIS 0x5416 -#define TIOCMBIC 0x5417 -#define TIOCMSET 0x5418 -#define TIOCGSOFTCAR 0x5419 -#define TIOCSSOFTCAR 0x541A -#define TIOCLINUX 0x541C -#define TIOCCONS 0x541D -#define TIOCGSERIAL 0x541E -#define TIOCSSERIAL 0x541F -#define TIOCPKT 0x5420 - -#define TIOCNOTTY 0x5422 -#define TIOCSETD 0x5423 -#define TIOCGETD 0x5424 -#define TCSBRKP 0x5425 /* Needed for POSIX tcsendbreak() */ - -#define TIOCSERCONFIG 0x5453 -#define TIOCSERGWILD 0x5454 -#define TIOCSERSWILD 0x5455 -#define TIOCGLCKTRMIOS 0x5456 -#define TIOCSLCKTRMIOS 0x5457 -#define TIOCSERGSTRUCT 0x5458 /* For debugging only */ -#define TIOCSERGETLSR 0x5459 /* Get line status register */ -#define TIOCSERGETMULTI 0x545A /* Get multiport config */ -#define TIOCSERSETMULTI 0x545B /* Set multiport config */ - -#define TIOCMIWAIT 0x545C /* wait for a change on serial input line(s) */ -#define TIOCGICOUNT 0x545D /* read serial port inline interrupt counts */ - -/* Used for packet mode */ -#define TIOCPKT_DATA 0 -#define TIOCPKT_FLUSHREAD 1 -#define TIOCPKT_FLUSHWRITE 2 -#define TIOCPKT_STOP 4 -#define TIOCPKT_START 8 -#define TIOCPKT_NOSTOP 16 -#define TIOCPKT_DOSTOP 32 - -/* modem lines */ -#define TIOCM_LE 0x001 -#define TIOCM_DTR 0x002 -#define TIOCM_RTS 0x004 -#define TIOCM_ST 0x008 -#define TIOCM_SR 0x010 -#define TIOCM_CTS 0x020 -#define TIOCM_CAR 0x040 -#define TIOCM_RNG 0x080 -#define TIOCM_DSR 0x100 -#define TIOCM_CD TIOCM_CAR -#define TIOCM_RI TIOCM_RNG -#define TIOCM_OUT1 0x2000 -#define TIOCM_OUT2 0x4000 -#define TIOCM_LOOP 0x8000 - -/* ioctl (fd, TIOCSERGETLSR, &result) where result may be as below */ -#define TIOCSER_TEMT 0x01 /* Transmitter physically empty */ - -#ifdef __KERNEL__ - -/* - * Translate a "termio" structure into a "termios". Ugh. - */ -#define SET_LOW_TERMIOS_BITS(termios, termio, x) { \ - unsigned short __tmp; \ - get_user(__tmp,&(termio)->x); \ - (termios)->x = (0xffff0000 & (termios)->x) | __tmp; \ -} - -#define user_termio_to_kernel_termios(termios, termio) \ -({ \ - SET_LOW_TERMIOS_BITS(termios, termio, c_iflag); \ - SET_LOW_TERMIOS_BITS(termios, termio, c_oflag); \ - SET_LOW_TERMIOS_BITS(termios, termio, c_cflag); \ - SET_LOW_TERMIOS_BITS(termios, termio, c_lflag); \ - copy_from_user((termios)->c_cc, (termio)->c_cc, NCC); \ -}) - -/* - * Translate a "termios" structure into a "termio". Ugh. - */ -#define kernel_termios_to_user_termio(termio, termios) \ -({ \ - put_user((termios)->c_iflag, &(termio)->c_iflag); \ - put_user((termios)->c_oflag, &(termio)->c_oflag); \ - put_user((termios)->c_cflag, &(termio)->c_cflag); \ - put_user((termios)->c_lflag, &(termio)->c_lflag); \ - put_user((termios)->c_line, &(termio)->c_line); \ - copy_to_user((termio)->c_cc, (termios)->c_cc, NCC); \ -}) - -#define user_termios_to_kernel_termios(k, u) copy_from_user(k, u, sizeof(struct termios)) -#define kernel_termios_to_user_termios(u, k) copy_to_user(u, k, sizeof(struct termios)) - -#endif /* __KERNEL__ */ - -#endif /* _PPC64_TERMIOS_H */ From anton at samba.org Tue Sep 6 11:50:55 2005 From: anton at samba.org (Anton Blanchard) Date: Tue, 6 Sep 2005 11:50:55 +1000 Subject: [PATCH] ppc64: Add missing include Message-ID: <20050906015055.GA6945@krispykreme> From: Milton Miller inline pmac_call_feature references ppc_md so include asm/machdep.h in asm/pmac_feature.h Signed-off-by: Milton Miller Signed-off-by: Anton Blanchard Index: build/include/asm-ppc/pmac_feature.h =================================================================== --- build.orig/include/asm-ppc/pmac_feature.h 2005-09-05 20:29:30.000000000 +1000 +++ build/include/asm-ppc/pmac_feature.h 2005-09-05 20:29:35.000000000 +1000 @@ -32,6 +32,7 @@ #define __PPC_ASM_PMAC_FEATURE_H #include +#include /* * Known Mac motherboard models From anton at samba.org Tue Sep 6 11:57:00 2005 From: anton at samba.org (Anton Blanchard) Date: Tue, 6 Sep 2005 11:57:00 +1000 Subject: [PATCH] ppc64: Remove old includes In-Reply-To: <20050906015642.GG6945@krispykreme> References: <20050906015412.GB6945@krispykreme> <20050906015442.GC6945@krispykreme> <20050906015500.GD6945@krispykreme> <20050906015538.GE6945@krispykreme> <20050906015602.GF6945@krispykreme> <20050906015642.GG6945@krispykreme> Message-ID: <20050906015700.GH6945@krispykreme> From: Milton Miller Trim some no longer needed includes from udbg.c and friends. Signed-off-by: Milton Miller Signed-off-by: Anton Blanchard Index: build/arch/ppc64/kernel/udbg.c =================================================================== --- build.orig/arch/ppc64/kernel/udbg.c 2005-09-05 20:29:46.000000000 +1000 +++ build/arch/ppc64/kernel/udbg.c 2005-09-05 20:29:47.000000000 +1000 @@ -13,12 +13,9 @@ #define WANT_PPCDBG_TAB /* Only defined here */ #include #include +#include #include #include -#include -#include -#include -#include void (*udbg_putc)(unsigned char c); unsigned char (*udbg_getc)(void); Index: build/arch/ppc64/kernel/udbg_16550.c =================================================================== --- build.orig/arch/ppc64/kernel/udbg_16550.c 2005-09-05 20:29:46.000000000 +1000 +++ build/arch/ppc64/kernel/udbg_16550.c 2005-09-05 20:29:47.000000000 +1000 @@ -10,13 +10,8 @@ */ #include #include -#include -#include -#include -#include -#include +#include #include -#include extern u8 real_readb(volatile u8 __iomem *addr); extern void real_writeb(u8 data, volatile u8 __iomem *addr); Index: build/arch/ppc64/kernel/udbg_scc.c =================================================================== --- build.orig/arch/ppc64/kernel/udbg_scc.c 2005-09-05 20:29:46.000000000 +1000 +++ build/arch/ppc64/kernel/udbg_scc.c 2005-09-05 20:29:47.000000000 +1000 @@ -10,11 +10,9 @@ */ #include #include -#include +#include #include #include -#include -#include #include #include #include From anton at samba.org Tue Sep 6 11:56:42 2005 From: anton at samba.org (Anton Blanchard) Date: Tue, 6 Sep 2005 11:56:42 +1000 Subject: [PATCH] ppc64: Take udbg out of ppc_md In-Reply-To: <20050906015602.GF6945@krispykreme> References: <20050906015412.GB6945@krispykreme> <20050906015442.GC6945@krispykreme> <20050906015500.GD6945@krispykreme> <20050906015538.GE6945@krispykreme> <20050906015602.GF6945@krispykreme> Message-ID: <20050906015642.GG6945@krispykreme> From: Milton Miller Take udbg out of ppc_md. Allows us to not overwrite early udbg inits when assigning ppc_md. Signed-off-by: Milton Miller Signed-off-by: Anton Blanchard Index: build/arch/ppc64/kernel/pSeries_lpar.c =================================================================== --- build.orig/arch/ppc64/kernel/pSeries_lpar.c 2005-09-05 16:11:18.000000000 +1000 +++ build/arch/ppc64/kernel/pSeries_lpar.c 2005-09-05 20:29:46.000000000 +1000 @@ -192,9 +192,9 @@ void udbg_init_debug_lpar(void) { vtermno = 0; - ppc_md.udbg_putc = udbg_putcLP; - ppc_md.udbg_getc = udbg_getcLP; - ppc_md.udbg_getc_poll = udbg_getc_pollLP; + udbg_putc = udbg_putcLP; + udbg_getc = udbg_getcLP; + udbg_getc_poll = udbg_getc_pollLP; } /* returns 0 if couldn't find or use /chosen/stdout as console */ @@ -227,18 +227,18 @@ termno = (u32 *)get_property(stdout_node, "reg", NULL); if (termno) { vtermno = termno[0]; - ppc_md.udbg_putc = udbg_putcLP; - ppc_md.udbg_getc = udbg_getcLP; - ppc_md.udbg_getc_poll = udbg_getc_pollLP; + udbg_putc = udbg_putcLP; + udbg_getc = udbg_getcLP; + udbg_getc_poll = udbg_getc_pollLP; found = 1; } } else if (device_is_compatible(stdout_node, "hvterm-protocol")) { termno = (u32 *)get_property(stdout_node, "reg", NULL); if (termno) { vtermno = termno[0]; - ppc_md.udbg_putc = udbg_hvsi_putc; - ppc_md.udbg_getc = udbg_hvsi_getc; - ppc_md.udbg_getc_poll = udbg_hvsi_getc_poll; + udbg_putc = udbg_hvsi_putc; + udbg_getc = udbg_hvsi_getc; + udbg_getc_poll = udbg_hvsi_getc_poll; found = 1; } } Index: build/arch/ppc64/kernel/pmac_setup.c =================================================================== --- build.orig/arch/ppc64/kernel/pmac_setup.c 2005-09-05 20:29:37.000000000 +1000 +++ build/arch/ppc64/kernel/pmac_setup.c 2005-09-05 20:29:46.000000000 +1000 @@ -332,16 +332,13 @@ sccdbg = 1; udbg_init_scc(NULL); } - - else { #ifdef CONFIG_BOOTX_TEXT + else { init_boot_display(); - ppc_md.udbg_putc = btext_putc; - ppc_md.udbg_getc = NULL; - ppc_md.udbg_getc_poll = NULL; -#endif /* CONFIG_BOOTX_TEXT */ + udbg_putc = btext_putc; } +#endif /* CONFIG_BOOTX_TEXT */ /* Setup interrupt mapping options */ ppc64_interrupt_controller = IC_OPEN_PIC; Index: build/arch/ppc64/kernel/setup.c =================================================================== --- build.orig/arch/ppc64/kernel/setup.c 2005-09-05 16:11:18.000000000 +1000 +++ build/arch/ppc64/kernel/setup.c 2005-09-05 20:29:46.000000000 +1000 @@ -89,7 +89,7 @@ #define EARLY_DEBUG_INIT() udbg_init_maple_realmode() #define EARLY_DEBUG_INIT() udbg_init_pmac_realmode() #define EARLY_DEBUG_INIT() \ - do { ppc_md.udbg_putc = call_rtas_display_status_delay; } while(0) + do { udbg_putc = call_rtas_display_status_delay; } while(0) #endif /* extern void *stab; */ @@ -425,12 +425,6 @@ } ppc_md = **mach; - /* our udbg callbacks got overriden by the above, let's put them - * back in. Ultimately, I want those things to be split from the - * main ppc_md - */ - EARLY_DEBUG_INIT(); - DBG("Found, Initializing memory management...\n"); /* Index: build/arch/ppc64/kernel/udbg.c =================================================================== --- build.orig/arch/ppc64/kernel/udbg.c 2005-09-05 20:29:39.000000000 +1000 +++ build/arch/ppc64/kernel/udbg.c 2005-09-05 20:29:46.000000000 +1000 @@ -20,14 +20,18 @@ #include #include +void (*udbg_putc)(unsigned char c); +unsigned char (*udbg_getc)(void); +int (*udbg_getc_poll)(void); + void udbg_puts(const char *s) { - if (ppc_md.udbg_putc) { + if (udbg_putc) { char c; if (s && *s != '\0') { while ((c = *s++) != '\0') - ppc_md.udbg_putc(c); + udbg_putc(c); } } #if 0 @@ -42,12 +46,12 @@ int remain = n; char c; - if (!ppc_md.udbg_putc) + if (!udbg_putc) return 0; if (s && *s != '\0') { while (((c = *s++) != '\0') && (remain-- > 0)) { - ppc_md.udbg_putc(c); + udbg_putc(c); } } @@ -59,12 +63,12 @@ char c, *p = buf; int i; - if (!ppc_md.udbg_getc) + if (!udbg_getc) return 0; for (i = 0; i < buflen; ++i) { do { - c = ppc_md.udbg_getc(); + c = udbg_getc(); } while (c == 0x11 || c == 0x13); if (c == 0) break; Index: build/arch/ppc64/kernel/udbg_16550.c =================================================================== --- build.orig/arch/ppc64/kernel/udbg_16550.c 2005-09-05 20:29:39.000000000 +1000 +++ build/arch/ppc64/kernel/udbg_16550.c 2005-09-05 20:29:46.000000000 +1000 @@ -99,9 +99,9 @@ out_8(&udbg_comport->lcr, 0x03); /* 8 data, 1 stop, no parity */ out_8(&udbg_comport->mcr, 0x03); /* RTS/DTR */ out_8(&udbg_comport->fcr ,0x07); /* Clear & enable FIFOs */ - ppc_md.udbg_putc = udbg_550_putc; - ppc_md.udbg_getc = udbg_550_getc; - ppc_md.udbg_getc_poll = udbg_550_getc_poll; + udbg_putc = udbg_550_putc; + udbg_getc = udbg_550_getc; + udbg_getc_poll = udbg_550_getc_poll; } } @@ -121,8 +121,8 @@ { udbg_comport = (volatile struct NS16550 __iomem *)0xf40003f8; - ppc_md.udbg_putc = udbg_maple_real_putc; - ppc_md.udbg_getc = NULL; - ppc_md.udbg_getc_poll = NULL; + udbg_putc = udbg_maple_real_putc; + udbg_getc = NULL; + udbg_getc_poll = NULL; } #endif /* CONFIG_PPC_MAPLE */ Index: build/arch/ppc64/kernel/udbg_scc.c =================================================================== --- build.orig/arch/ppc64/kernel/udbg_scc.c 2005-09-05 20:29:39.000000000 +1000 +++ build/arch/ppc64/kernel/udbg_scc.c 2005-09-05 20:29:46.000000000 +1000 @@ -111,9 +111,9 @@ for (i = 0; i < sizeof(scc_inittab); ++i) out_8(sccc, scc_inittab[i]); - ppc_md.udbg_putc = udbg_scc_putc; - ppc_md.udbg_getc = udbg_scc_getc; - ppc_md.udbg_getc_poll = udbg_scc_getc_poll; + udbg_putc = udbg_scc_putc; + udbg_getc = udbg_scc_getc; + udbg_getc_poll = udbg_scc_getc_poll; udbg_puts("Hello World !\n"); } @@ -132,7 +132,7 @@ sccc = (volatile u8 __iomem *)0x80013020ul; sccd = (volatile u8 __iomem *)0x80013030ul; - ppc_md.udbg_putc = udbg_real_scc_putc; - ppc_md.udbg_getc = NULL; - ppc_md.udbg_getc_poll = NULL; + udbg_putc = udbg_real_scc_putc; + udbg_getc = NULL; + udbg_getc_poll = NULL; } Index: build/arch/ppc64/xmon/start.c =================================================================== --- build.orig/arch/ppc64/xmon/start.c 2005-09-05 20:29:36.000000000 +1000 +++ build/arch/ppc64/xmon/start.c 2005-09-05 20:29:46.000000000 +1000 @@ -61,8 +61,8 @@ int xmon_read_poll(void) { - if (ppc_md.udbg_getc_poll) - return ppc_md.udbg_getc_poll(); + if (udbg_getc_poll) + return udbg_getc_poll(); return -1; } Index: build/include/asm-ppc64/machdep.h =================================================================== --- build.orig/include/asm-ppc64/machdep.h 2005-09-05 16:11:21.000000000 +1000 +++ build/include/asm-ppc64/machdep.h 2005-09-05 20:29:46.000000000 +1000 @@ -103,11 +103,6 @@ void (*progress)(char *, unsigned short); - /* Debug interface. Low level I/O to some terminal device */ - void (*udbg_putc)(unsigned char c); - unsigned char (*udbg_getc)(void); - int (*udbg_getc_poll)(void); - /* Interface for platform error logging */ void (*log_error)(char *buf, unsigned int err_type, int fatal); Index: build/include/asm-ppc64/udbg.h =================================================================== --- build.orig/include/asm-ppc64/udbg.h 2005-09-05 16:11:21.000000000 +1000 +++ build/include/asm-ppc64/udbg.h 2005-09-05 20:29:46.000000000 +1000 @@ -12,17 +12,20 @@ * 2 of the License, or (at your option) any later version. */ -void udbg_init_uart(void __iomem *comport, unsigned int speed); -void udbg_putc(unsigned char c); -unsigned char udbg_getc(void); -int udbg_getc_poll(void); -void udbg_puts(const char *s); -int udbg_write(const char *s, int n); -int udbg_read(char *buf, int buflen); +extern void (*udbg_putc)(unsigned char c); +extern unsigned char (*udbg_getc)(void); +extern int (*udbg_getc_poll)(void); + +extern void udbg_puts(const char *s); +extern int udbg_write(const char *s, int n); +extern int udbg_read(char *buf, int buflen); + struct console; -void udbg_console_write(struct console *con, const char *s, unsigned int n); -void udbg_printf(const char *fmt, ...); -void udbg_ppcdbg(unsigned long flags, const char *fmt, ...); -unsigned long udbg_ifdebug(unsigned long flags); +extern void udbg_console_write(struct console *con, const char *s, unsigned int n); +extern void udbg_printf(const char *fmt, ...); +extern void udbg_ppcdbg(unsigned long flags, const char *fmt, ...); +extern unsigned long udbg_ifdebug(unsigned long flags); + +extern void udbg_init_uart(void __iomem *comport, unsigned int speed); #endif From anton at samba.org Tue Sep 6 11:54:13 2005 From: anton at samba.org (Anton Blanchard) Date: Tue, 6 Sep 2005 11:54:13 +1000 Subject: [PATCH] ppc64: dont bypass ppc_md.udbg* functions Message-ID: <20050906015412.GB6945@krispykreme> From: Milton Miller udbg_getc_poll is a ppc_md function. don't call directly into udbg.c Signed-off-by: Milton Miller Signed-off-by: Anton Blanchard Index: build/arch/ppc64/xmon/start.c =================================================================== --- build.orig/arch/ppc64/xmon/start.c 2005-09-05 20:29:29.000000000 +1000 +++ build/arch/ppc64/xmon/start.c 2005-09-05 20:29:36.000000000 +1000 @@ -61,7 +61,9 @@ int xmon_read_poll(void) { - return udbg_getc_poll(); + if (ppc_md.udbg_getc_poll) + return ppc_md.udbg_getc_poll(); + return -1; } FILE *xmon_stdin; From anton at samba.org Tue Sep 6 11:54:42 2005 From: anton at samba.org (Anton Blanchard) Date: Tue, 6 Sep 2005 11:54:42 +1000 Subject: [PATCH] ppc64: Remove dummy getc routines In-Reply-To: <20050906015412.GB6945@krispykreme> References: <20050906015412.GB6945@krispykreme> Message-ID: <20050906015442.GC6945@krispykreme> From: Milton Miller Now that xmon is fixed we should not need the dummy getc routines. Signed-off-by: Milton Miller Signed-off-by: Anton Blanchard Index: build/arch/ppc64/kernel/pmac_setup.c =================================================================== --- build.orig/arch/ppc64/kernel/pmac_setup.c 2005-09-05 20:29:29.000000000 +1000 +++ build/arch/ppc64/kernel/pmac_setup.c 2005-09-05 20:29:37.000000000 +1000 @@ -274,16 +274,6 @@ } #ifdef CONFIG_BOOTX_TEXT -static int dummy_getc_poll(void) -{ - return -1; -} - -static unsigned char dummy_getc(void) -{ - return 0; -} - static void btext_putc(unsigned char c) { btext_drawchar(c); @@ -348,8 +338,8 @@ init_boot_display(); ppc_md.udbg_putc = btext_putc; - ppc_md.udbg_getc = dummy_getc; - ppc_md.udbg_getc_poll = dummy_getc_poll; + ppc_md.udbg_getc = NULL; + ppc_md.udbg_getc_poll = NULL; #endif /* CONFIG_BOOTX_TEXT */ } From anton at samba.org Tue Sep 6 11:55:00 2005 From: anton at samba.org (Anton Blanchard) Date: Tue, 6 Sep 2005 11:55:00 +1000 Subject: [PATCH] ppc64: Clean up CR handling In-Reply-To: <20050906015442.GC6945@krispykreme> References: <20050906015412.GB6945@krispykreme> <20050906015442.GC6945@krispykreme> Message-ID: <20050906015500.GD6945@krispykreme> From: Milton Miller Make the 16550 and real mode 16550 use tail recursion like the scc code instead of repeating the routine except for the character sent. Gcc recoginizes the tail recursion and handles it efficently without stack allocations. The maple real putc shrinks from 188 to 104 bytes of instructions. udbg_putc drops from 188 to 140 bytes. Signed-off-by: Milton Miller Signed-off-by: Anton Blanchard Index: build/arch/ppc64/kernel/udbg.c =================================================================== --- build.orig/arch/ppc64/kernel/udbg.c 2005-09-05 20:29:29.000000000 +1000 +++ build/arch/ppc64/kernel/udbg.c 2005-09-05 20:29:38.000000000 +1000 @@ -169,12 +169,8 @@ while ((real_readb(&udbg_comport->lsr) & LSR_THRE) == 0) /* wait for idle */; real_writeb(c, &udbg_comport->thr); eieio(); - if (c == '\n') { - /* Also put a CR. This is for convenience. */ - while ((real_readb(&udbg_comport->lsr) & LSR_THRE) == 0) - /* wait for idle */; - real_writeb('\r', &udbg_comport->thr); eieio(); - } + if (c == '\n') + udbg_maple_real_putc('\r'); } } @@ -194,12 +190,8 @@ while ((in_8(&udbg_comport->lsr) & LSR_THRE) == 0) /* wait for idle */; out_8(&udbg_comport->thr, c); - if (c == '\n') { - /* Also put a CR. This is for convenience. */ - while ((in_8(&udbg_comport->lsr) & LSR_THRE) == 0) - /* wait for idle */; - out_8(&udbg_comport->thr, '\r'); - } + if (c == '\n') + udbg_putc('\r'); } #ifdef CONFIG_PPC_PMAC else if (sccc) { From anton at samba.org Tue Sep 6 11:56:02 2005 From: anton at samba.org (Anton Blanchard) Date: Tue, 6 Sep 2005 11:56:02 +1000 Subject: [PATCH] ppc64: Split SCC and 15550 udbg code In-Reply-To: <20050906015538.GE6945@krispykreme> References: <20050906015412.GB6945@krispykreme> <20050906015442.GC6945@krispykreme> <20050906015500.GD6945@krispykreme> <20050906015538.GE6945@krispykreme> Message-ID: <20050906015602.GF6945@krispykreme> From: Milton Miller Split scc and 15550 functions from udbg each into their own file. This makes them more symetric with the lpar and btext code. Signed-off-by: Milton Miller Signed-off-by: Anton Blanchard Index: build/arch/ppc64/kernel/Makefile =================================================================== --- build.orig/arch/ppc64/kernel/Makefile 2005-09-05 20:29:29.000000000 +1000 +++ build/arch/ppc64/kernel/Makefile 2005-09-05 20:29:39.000000000 +1000 @@ -31,7 +31,7 @@ obj-$(CONFIG_PPC_PSERIES) += pSeries_pci.o pSeries_lpar.o pSeries_hvCall.o \ pSeries_nvram.o rtasd.o ras.o pSeries_reconfig.o \ - pSeries_setup.o pSeries_iommu.o + pSeries_setup.o pSeries_iommu.o udbg_16550.o obj-$(CONFIG_PPC_BPA) += bpa_setup.o bpa_iommu.o bpa_nvram.o \ bpa_iic.o spider-pic.o @@ -58,9 +58,11 @@ obj-$(CONFIG_MPIC) += mpic.o obj-$(CONFIG_PPC_PMAC) += pmac_setup.o pmac_feature.o pmac_pci.o \ - pmac_time.o pmac_nvram.o pmac_low_i2c.o + pmac_time.o pmac_nvram.o pmac_low_i2c.o \ + udbg_scc.o -obj-$(CONFIG_PPC_MAPLE) += maple_setup.o maple_pci.o maple_time.o +obj-$(CONFIG_PPC_MAPLE) += maple_setup.o maple_pci.o maple_time.o \ + udbg_16550.o obj-$(CONFIG_U3_DART) += u3_iommu.o Index: build/arch/ppc64/kernel/udbg.c =================================================================== --- build.orig/arch/ppc64/kernel/udbg.c 2005-09-05 20:29:39.000000000 +1000 +++ build/arch/ppc64/kernel/udbg.c 2005-09-05 20:29:39.000000000 +1000 @@ -1,5 +1,5 @@ /* - * NS16550 Serial Port (uart) debugging stuff. + * polling mode stateless debugging stuff, originally for NS16550 Serial Ports * * c 2001 PPC 64 Team, IBM Corp * @@ -19,229 +19,6 @@ #include #include #include -#include - -extern u8 real_readb(volatile u8 __iomem *addr); -extern void real_writeb(u8 data, volatile u8 __iomem *addr); - -struct NS16550 { - /* this struct must be packed */ - unsigned char rbr; /* 0 */ - unsigned char ier; /* 1 */ - unsigned char fcr; /* 2 */ - unsigned char lcr; /* 3 */ - unsigned char mcr; /* 4 */ - unsigned char lsr; /* 5 */ - unsigned char msr; /* 6 */ - unsigned char scr; /* 7 */ -}; - -#define thr rbr -#define iir fcr -#define dll rbr -#define dlm ier -#define dlab lcr - -#define LSR_DR 0x01 /* Data ready */ -#define LSR_OE 0x02 /* Overrun */ -#define LSR_PE 0x04 /* Parity error */ -#define LSR_FE 0x08 /* Framing error */ -#define LSR_BI 0x10 /* Break */ -#define LSR_THRE 0x20 /* Xmit holding register empty */ -#define LSR_TEMT 0x40 /* Xmitter empty */ -#define LSR_ERR 0x80 /* Error */ - -static volatile struct NS16550 __iomem *udbg_comport; - -void udbg_init_uart(void __iomem *comport, unsigned int speed) -{ - u16 dll = speed ? (115200 / speed) : 12; - - if (comport) { - udbg_comport = (struct NS16550 __iomem *)comport; - out_8(&udbg_comport->lcr, 0x00); - out_8(&udbg_comport->ier, 0xff); - out_8(&udbg_comport->ier, 0x00); - out_8(&udbg_comport->lcr, 0x80); /* Access baud rate */ - out_8(&udbg_comport->dll, dll & 0xff); /* 1 = 115200, 2 = 57600, - 3 = 38400, 12 = 9600 baud */ - out_8(&udbg_comport->dlm, dll >> 8); /* dll >> 8 which should be zero - for fast rates; */ - out_8(&udbg_comport->lcr, 0x03); /* 8 data, 1 stop, no parity */ - out_8(&udbg_comport->mcr, 0x03); /* RTS/DTR */ - out_8(&udbg_comport->fcr ,0x07); /* Clear & enable FIFOs */ - ppc_md.udbg_putc = udbg_putc; /* set access methods */ - ppc_md.udbg_getc = udbg_getc; - ppc_md.udbg_getc_poll = udbg_getc_poll; - } -} - -#ifdef CONFIG_PPC_PMAC - -#define SCC_TXRDY 4 -#define SCC_RXRDY 1 - -static volatile u8 __iomem *sccc; -static volatile u8 __iomem *sccd; - -static unsigned char scc_inittab[] = { - 13, 0, /* set baud rate divisor */ - 12, 0, - 14, 1, /* baud rate gen enable, src=rtxc */ - 11, 0x50, /* clocks = br gen */ - 5, 0xea, /* tx 8 bits, assert DTR & RTS */ - 4, 0x46, /* x16 clock, 1 stop */ - 3, 0xc1, /* rx enable, 8 bits */ -}; - -void udbg_init_scc(struct device_node *np) -{ - u32 *reg; - unsigned long addr; - int i, x; - - if (np == NULL) - np = of_find_node_by_name(NULL, "escc"); - if (np == NULL || np->parent == NULL) - return; - - udbg_printf("found SCC...\n"); - /* Get address within mac-io ASIC */ - reg = (u32 *)get_property(np, "reg", NULL); - if (reg == NULL) - return; - addr = reg[0]; - udbg_printf("local addr: %lx\n", addr); - /* Get address of mac-io PCI itself */ - reg = (u32 *)get_property(np->parent, "assigned-addresses", NULL); - if (reg == NULL) - return; - addr += reg[2]; - udbg_printf("final addr: %lx\n", addr); - - /* Setup for 57600 8N1 */ - addr += 0x20; - sccc = (volatile u8 * __iomem) ioremap(addr & PAGE_MASK, PAGE_SIZE) ; - sccc += addr & ~PAGE_MASK; - sccd = sccc + 0x10; - - udbg_printf("ioremap result sccc: %p\n", sccc); - mb(); - - for (i = 20000; i != 0; --i) - x = in_8(sccc); - out_8(sccc, 0x09); /* reset A or B side */ - out_8(sccc, 0xc0); - for (i = 0; i < sizeof(scc_inittab); ++i) - out_8(sccc, scc_inittab[i]); - - ppc_md.udbg_putc = udbg_putc; - ppc_md.udbg_getc = udbg_getc; - ppc_md.udbg_getc_poll = udbg_getc_poll; - - udbg_puts("Hello World !\n"); -} - -#endif /* CONFIG_PPC_PMAC */ - -#ifdef CONFIG_PPC_PMAC -static void udbg_real_putc(unsigned char c) -{ - while ((real_readb(sccc) & SCC_TXRDY) == 0) - ; - real_writeb(c, sccd); - if (c == '\n') - udbg_real_putc('\r'); -} - -void udbg_init_pmac_realmode(void) -{ - sccc = (volatile u8 __iomem *)0x80013020ul; - sccd = (volatile u8 __iomem *)0x80013030ul; - - ppc_md.udbg_putc = udbg_real_putc; - ppc_md.udbg_getc = NULL; - ppc_md.udbg_getc_poll = NULL; -} -#endif /* CONFIG_PPC_PMAC */ - -#ifdef CONFIG_PPC_MAPLE -void udbg_maple_real_putc(unsigned char c) -{ - if (udbg_comport) { - while ((real_readb(&udbg_comport->lsr) & LSR_THRE) == 0) - /* wait for idle */; - real_writeb(c, &udbg_comport->thr); eieio(); - if (c == '\n') - udbg_maple_real_putc('\r'); - } -} - -void udbg_init_maple_realmode(void) -{ - udbg_comport = (volatile struct NS16550 __iomem *)0xf40003f8; - - ppc_md.udbg_putc = udbg_maple_real_putc; - ppc_md.udbg_getc = NULL; - ppc_md.udbg_getc_poll = NULL; -} -#endif /* CONFIG_PPC_MAPLE */ - -void udbg_putc(unsigned char c) -{ - if (udbg_comport) { - while ((in_8(&udbg_comport->lsr) & LSR_THRE) == 0) - /* wait for idle */; - out_8(&udbg_comport->thr, c); - if (c == '\n') - udbg_putc('\r'); - } -#ifdef CONFIG_PPC_PMAC - else if (sccc) { - while ((in_8(sccc) & SCC_TXRDY) == 0) - ; - out_8(sccd, c); - if (c == '\n') - udbg_putc('\r'); - } -#endif /* CONFIG_PPC_PMAC */ -} - -int udbg_getc_poll(void) -{ - if (udbg_comport) { - if ((in_8(&udbg_comport->lsr) & LSR_DR) != 0) - return in_8(&udbg_comport->rbr); - else - return -1; - } -#ifdef CONFIG_PPC_PMAC - else if (sccc) { - if ((in_8(sccc) & SCC_RXRDY) != 0) - return in_8(sccd); - else - return -1; - } -#endif /* CONFIG_PPC_PMAC */ - return -1; -} - -unsigned char udbg_getc(void) -{ - if (udbg_comport) { - while ((in_8(&udbg_comport->lsr) & LSR_DR) == 0) - /* wait for char */; - return in_8(&udbg_comport->rbr); - } -#ifdef CONFIG_PPC_PMAC - else if (sccc) { - while ((in_8(sccc) & SCC_RXRDY) == 0) - ; - return in_8(sccd); - } -#endif /* CONFIG_PPC_PMAC */ - return 0; -} void udbg_puts(const char *s) { Index: build/arch/ppc64/kernel/udbg_16550.c =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ build/arch/ppc64/kernel/udbg_16550.c 2005-09-05 20:29:39.000000000 +1000 @@ -0,0 +1,128 @@ +/* + * udbg for for NS16550 compatable serial ports + * + * Copyright (C) 2001-2005 PPC 64 Team, IBM 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; either version + * 2 of the License, or (at your option) any later version. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +extern u8 real_readb(volatile u8 __iomem *addr); +extern void real_writeb(u8 data, volatile u8 __iomem *addr); + +struct NS16550 { + /* this struct must be packed */ + unsigned char rbr; /* 0 */ + unsigned char ier; /* 1 */ + unsigned char fcr; /* 2 */ + unsigned char lcr; /* 3 */ + unsigned char mcr; /* 4 */ + unsigned char lsr; /* 5 */ + unsigned char msr; /* 6 */ + unsigned char scr; /* 7 */ +}; + +#define thr rbr +#define iir fcr +#define dll rbr +#define dlm ier +#define dlab lcr + +#define LSR_DR 0x01 /* Data ready */ +#define LSR_OE 0x02 /* Overrun */ +#define LSR_PE 0x04 /* Parity error */ +#define LSR_FE 0x08 /* Framing error */ +#define LSR_BI 0x10 /* Break */ +#define LSR_THRE 0x20 /* Xmit holding register empty */ +#define LSR_TEMT 0x40 /* Xmitter empty */ +#define LSR_ERR 0x80 /* Error */ + +static volatile struct NS16550 __iomem *udbg_comport; + +static void udbg_550_putc(unsigned char c) +{ + if (udbg_comport) { + while ((in_8(&udbg_comport->lsr) & LSR_THRE) == 0) + /* wait for idle */; + out_8(&udbg_comport->thr, c); + if (c == '\n') + udbg_550_putc('\r'); + } +} + +static int udbg_550_getc_poll(void) +{ + if (udbg_comport) { + if ((in_8(&udbg_comport->lsr) & LSR_DR) != 0) + return in_8(&udbg_comport->rbr); + else + return -1; + } + return -1; +} + +static unsigned char udbg_550_getc(void) +{ + if (udbg_comport) { + while ((in_8(&udbg_comport->lsr) & LSR_DR) == 0) + /* wait for char */; + return in_8(&udbg_comport->rbr); + } + return 0; +} + +void udbg_init_uart(void __iomem *comport, unsigned int speed) +{ + u16 dll = speed ? (115200 / speed) : 12; + + if (comport) { + udbg_comport = (struct NS16550 __iomem *)comport; + out_8(&udbg_comport->lcr, 0x00); + out_8(&udbg_comport->ier, 0xff); + out_8(&udbg_comport->ier, 0x00); + out_8(&udbg_comport->lcr, 0x80); /* Access baud rate */ + out_8(&udbg_comport->dll, dll & 0xff); /* 1 = 115200, 2 = 57600, + 3 = 38400, 12 = 9600 baud */ + out_8(&udbg_comport->dlm, dll >> 8); /* dll >> 8 which should be zero + for fast rates; */ + out_8(&udbg_comport->lcr, 0x03); /* 8 data, 1 stop, no parity */ + out_8(&udbg_comport->mcr, 0x03); /* RTS/DTR */ + out_8(&udbg_comport->fcr ,0x07); /* Clear & enable FIFOs */ + ppc_md.udbg_putc = udbg_550_putc; + ppc_md.udbg_getc = udbg_550_getc; + ppc_md.udbg_getc_poll = udbg_550_getc_poll; + } +} + +#ifdef CONFIG_PPC_MAPLE +void udbg_maple_real_putc(unsigned char c) +{ + if (udbg_comport) { + while ((real_readb(&udbg_comport->lsr) & LSR_THRE) == 0) + /* wait for idle */; + real_writeb(c, &udbg_comport->thr); eieio(); + if (c == '\n') + udbg_maple_real_putc('\r'); + } +} + +void udbg_init_maple_realmode(void) +{ + udbg_comport = (volatile struct NS16550 __iomem *)0xf40003f8; + + ppc_md.udbg_putc = udbg_maple_real_putc; + ppc_md.udbg_getc = NULL; + ppc_md.udbg_getc_poll = NULL; +} +#endif /* CONFIG_PPC_MAPLE */ Index: build/arch/ppc64/kernel/udbg_scc.c =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ build/arch/ppc64/kernel/udbg_scc.c 2005-09-05 20:29:39.000000000 +1000 @@ -0,0 +1,138 @@ +/* + * udbg for for zilog scc ports as found on Apple PowerMacs + * + * Copyright (C) 2001-2005 PPC 64 Team, IBM 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; either version + * 2 of the License, or (at your option) any later version. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +extern u8 real_readb(volatile u8 __iomem *addr); +extern void real_writeb(u8 data, volatile u8 __iomem *addr); + +#define SCC_TXRDY 4 +#define SCC_RXRDY 1 + +static volatile u8 __iomem *sccc; +static volatile u8 __iomem *sccd; + +static void udbg_scc_putc(unsigned char c) +{ + if (sccc) { + while ((in_8(sccc) & SCC_TXRDY) == 0) + ; + out_8(sccd, c); + if (c == '\n') + udbg_scc_putc('\r'); + } +} + +static int udbg_scc_getc_poll(void) +{ + if (sccc) { + if ((in_8(sccc) & SCC_RXRDY) != 0) + return in_8(sccd); + else + return -1; + } + return -1; +} + +static unsigned char udbg_scc_getc(void) +{ + if (sccc) { + while ((in_8(sccc) & SCC_RXRDY) == 0) + ; + return in_8(sccd); + } + return 0; +} + +static unsigned char scc_inittab[] = { + 13, 0, /* set baud rate divisor */ + 12, 0, + 14, 1, /* baud rate gen enable, src=rtxc */ + 11, 0x50, /* clocks = br gen */ + 5, 0xea, /* tx 8 bits, assert DTR & RTS */ + 4, 0x46, /* x16 clock, 1 stop */ + 3, 0xc1, /* rx enable, 8 bits */ +}; + +void udbg_init_scc(struct device_node *np) +{ + u32 *reg; + unsigned long addr; + int i, x; + + if (np == NULL) + np = of_find_node_by_name(NULL, "escc"); + if (np == NULL || np->parent == NULL) + return; + + udbg_printf("found SCC...\n"); + /* Get address within mac-io ASIC */ + reg = (u32 *)get_property(np, "reg", NULL); + if (reg == NULL) + return; + addr = reg[0]; + udbg_printf("local addr: %lx\n", addr); + /* Get address of mac-io PCI itself */ + reg = (u32 *)get_property(np->parent, "assigned-addresses", NULL); + if (reg == NULL) + return; + addr += reg[2]; + udbg_printf("final addr: %lx\n", addr); + + /* Setup for 57600 8N1 */ + addr += 0x20; + sccc = (volatile u8 * __iomem) ioremap(addr & PAGE_MASK, PAGE_SIZE) ; + sccc += addr & ~PAGE_MASK; + sccd = sccc + 0x10; + + udbg_printf("ioremap result sccc: %p\n", sccc); + mb(); + + for (i = 20000; i != 0; --i) + x = in_8(sccc); + out_8(sccc, 0x09); /* reset A or B side */ + out_8(sccc, 0xc0); + for (i = 0; i < sizeof(scc_inittab); ++i) + out_8(sccc, scc_inittab[i]); + + ppc_md.udbg_putc = udbg_scc_putc; + ppc_md.udbg_getc = udbg_scc_getc; + ppc_md.udbg_getc_poll = udbg_scc_getc_poll; + + udbg_puts("Hello World !\n"); +} + +static void udbg_real_scc_putc(unsigned char c) +{ + while ((real_readb(sccc) & SCC_TXRDY) == 0) + ; + real_writeb(c, sccd); + if (c == '\n') + udbg_real_scc_putc('\r'); +} + +void udbg_init_pmac_realmode(void) +{ + sccc = (volatile u8 __iomem *)0x80013020ul; + sccd = (volatile u8 __iomem *)0x80013030ul; + + ppc_md.udbg_putc = udbg_real_scc_putc; + ppc_md.udbg_getc = NULL; + ppc_md.udbg_getc_poll = NULL; +} From anton at samba.org Tue Sep 6 11:55:38 2005 From: anton at samba.org (Anton Blanchard) Date: Tue, 6 Sep 2005 11:55:38 +1000 Subject: [PATCH] ppc64: Make udbg_init_uart set the ppc_md udbg methods. In-Reply-To: <20050906015500.GD6945@krispykreme> References: <20050906015412.GB6945@krispykreme> <20050906015442.GC6945@krispykreme> <20050906015500.GD6945@krispykreme> Message-ID: <20050906015538.GE6945@krispykreme> From: Milton Miller make udbg_init_uart set the ppc_md udbg methods. Signed-off-by: Milton Miller Signed-off-by: Anton Blanchard Index: build/arch/ppc64/kernel/maple_setup.c =================================================================== --- build.orig/arch/ppc64/kernel/maple_setup.c 2005-09-05 20:29:29.000000000 +1000 +++ build/arch/ppc64/kernel/maple_setup.c 2005-09-05 20:29:39.000000000 +1000 @@ -207,9 +207,6 @@ comport = (void *)ioremap(physport, 16); udbg_init_uart(comport, default_speed); - ppc_md.udbg_putc = udbg_putc; - ppc_md.udbg_getc = udbg_getc; - ppc_md.udbg_getc_poll = udbg_getc_poll; DBG("Hello World !\n"); } Index: build/arch/ppc64/kernel/pSeries_setup.c =================================================================== --- build.orig/arch/ppc64/kernel/pSeries_setup.c 2005-09-05 20:29:29.000000000 +1000 +++ build/arch/ppc64/kernel/pSeries_setup.c 2005-09-05 20:29:39.000000000 +1000 @@ -397,9 +397,6 @@ comport = (void *)ioremap(physport, 16); udbg_init_uart(comport, default_speed); - ppc_md.udbg_putc = udbg_putc; - ppc_md.udbg_getc = udbg_getc; - ppc_md.udbg_getc_poll = udbg_getc_poll; DBG("Hello World !\n"); } Index: build/arch/ppc64/kernel/udbg.c =================================================================== --- build.orig/arch/ppc64/kernel/udbg.c 2005-09-05 20:29:38.000000000 +1000 +++ build/arch/ppc64/kernel/udbg.c 2005-09-05 20:29:39.000000000 +1000 @@ -70,6 +70,9 @@ out_8(&udbg_comport->lcr, 0x03); /* 8 data, 1 stop, no parity */ out_8(&udbg_comport->mcr, 0x03); /* RTS/DTR */ out_8(&udbg_comport->fcr ,0x07); /* Clear & enable FIFOs */ + ppc_md.udbg_putc = udbg_putc; /* set access methods */ + ppc_md.udbg_getc = udbg_getc; + ppc_md.udbg_getc_poll = udbg_getc_poll; } } From anton at samba.org Tue Sep 6 11:57:27 2005 From: anton at samba.org (Anton Blanchard) Date: Tue, 6 Sep 2005 11:57:27 +1000 Subject: [PATCH] ppc64: Consolidate early console and PPCDBG code In-Reply-To: <20050906015700.GH6945@krispykreme> References: <20050906015412.GB6945@krispykreme> <20050906015442.GC6945@krispykreme> <20050906015500.GD6945@krispykreme> <20050906015538.GE6945@krispykreme> <20050906015602.GF6945@krispykreme> <20050906015642.GG6945@krispykreme> <20050906015700.GH6945@krispykreme> Message-ID: <20050906015726.GI6945@krispykreme> From: Milton Miller Consolidate the early console and PPCDBG code in udbg.c Signed-off-by: Milton Miller Signed-off-by: Anton Blanchard Index: build/arch/ppc64/kernel/setup.c =================================================================== --- build.orig/arch/ppc64/kernel/setup.c 2005-09-05 20:29:46.000000000 +1000 +++ build/arch/ppc64/kernel/setup.c 2005-09-05 20:33:24.000000000 +1000 @@ -108,7 +108,6 @@ int boot_cpuid_phys = 0; dev_t boot_dev; u64 ppc64_pft_size; -u64 ppc64_debug_switch; struct ppc64_caches ppc64_caches; EXPORT_SYMBOL_GPL(ppc64_caches); @@ -154,34 +153,6 @@ .orig_video_points = 16 }; -/* - * Initialize the PPCDBG state. Called before relocation has been enabled. - */ -void __init ppcdbg_initialize(void) -{ - ppc64_debug_switch = PPC_DEBUG_DEFAULT; /* | PPCDBG_BUSWALK | */ - /* PPCDBG_PHBINIT | PPCDBG_MM | PPCDBG_MMINIT | PPCDBG_TCEINIT | PPCDBG_TCE */; -} - -/* - * Early boot console based on udbg - */ -static struct console udbg_console = { - .name = "udbg", - .write = udbg_console_write, - .flags = CON_PRINTBUFFER, - .index = -1, -}; -static int early_console_initialized; - -void __init disable_early_printk(void) -{ - if (!early_console_initialized) - return; - unregister_console(&udbg_console); - early_console_initialized = 0; -} - #if defined(CONFIG_PPC_MULTIPLATFORM) && defined(CONFIG_SMP) static int smt_enabled_cmdline; @@ -630,8 +601,7 @@ /* * Register early console */ - early_console_initialized = 1; - register_console(&udbg_console); + register_early_udbg_console(); /* Save unparsed command line copy for /proc/cmdline */ strlcpy(saved_command_line, cmd_line, COMMAND_LINE_SIZE); Index: build/arch/ppc64/kernel/udbg.c =================================================================== --- build.orig/arch/ppc64/kernel/udbg.c 2005-09-05 20:29:47.000000000 +1000 +++ build/arch/ppc64/kernel/udbg.c 2005-09-05 20:29:48.000000000 +1000 @@ -14,6 +14,7 @@ #include #include #include +#include #include #include @@ -21,6 +22,7 @@ unsigned char (*udbg_getc)(void); int (*udbg_getc_poll)(void); +/* udbg library, used by xmon et al */ void udbg_puts(const char *s) { if (udbg_putc) { @@ -75,11 +77,6 @@ return i; } -void udbg_console_write(struct console *con, const char *s, unsigned int n) -{ - udbg_write(s, n); -} - #define UDBG_BUFSIZE 256 void udbg_printf(const char *fmt, ...) { @@ -92,6 +89,10 @@ va_end(args); } +/* PPCDBG stuff */ + +u64 ppc64_debug_switch; + /* Special print used by PPCDBG() macro */ void udbg_ppcdbg(unsigned long debug_flags, const char *fmt, ...) { @@ -131,3 +132,43 @@ { return (flags & ppc64_debug_switch); } + +/* + * Initialize the PPCDBG state. Called before relocation has been enabled. + */ +void __init ppcdbg_initialize(void) +{ + ppc64_debug_switch = PPC_DEBUG_DEFAULT; /* | PPCDBG_BUSWALK | */ + /* PPCDBG_PHBINIT | PPCDBG_MM | PPCDBG_MMINIT | PPCDBG_TCEINIT | PPCDBG_TCE */; +} + +/* + * Early boot console based on udbg + */ +static void udbg_console_write(struct console *con, const char *s, + unsigned int n) +{ + udbg_write(s, n); +} + +static struct console udbg_console = { + .name = "udbg", + .write = udbg_console_write, + .flags = CON_PRINTBUFFER, + .index = -1, +}; + +void __init disable_early_printk(void) +{ + unregister_console(&udbg_console); +} + +/* called by setup_system */ +void register_early_udbg_console(void) +{ + register_console(&udbg_console); +} + +#if 0 /* if you want to use this as a regular output console */ +console_initcall(register_udbg_console); +#endif Index: build/include/asm-ppc64/udbg.h =================================================================== --- build.orig/include/asm-ppc64/udbg.h 2005-09-05 20:29:46.000000000 +1000 +++ build/include/asm-ppc64/udbg.h 2005-09-05 20:29:48.000000000 +1000 @@ -2,6 +2,7 @@ #define __UDBG_HDR #include +#include /* * c 2001 PPC 64 Team, IBM Corp @@ -20,12 +21,11 @@ extern int udbg_write(const char *s, int n); extern int udbg_read(char *buf, int buflen); -struct console; -extern void udbg_console_write(struct console *con, const char *s, unsigned int n); +extern void register_early_udbg_console(void); extern void udbg_printf(const char *fmt, ...); extern void udbg_ppcdbg(unsigned long flags, const char *fmt, ...); extern unsigned long udbg_ifdebug(unsigned long flags); - +extern void __init ppcdbg_initialize(void); extern void udbg_init_uart(void __iomem *comport, unsigned int speed); #endif From anton at samba.org Tue Sep 6 12:05:26 2005 From: anton at samba.org (Anton Blanchard) Date: Tue, 6 Sep 2005 12:05:26 +1000 Subject: [PATCH] ppc64: poison initmem Message-ID: <20050906020526.GJ6945@krispykreme> Poison initmem after we free it so we catch use after free issues. Signed-off-by: Anton Blanchard Index: build/arch/ppc64/mm/init.c =================================================================== --- build.orig/arch/ppc64/mm/init.c 2005-09-06 11:29:15.000000000 +1000 +++ build/arch/ppc64/mm/init.c 2005-09-06 11:29:36.000000000 +1000 @@ -392,6 +392,7 @@ addr = (unsigned long)__init_begin; for (; addr < (unsigned long)__init_end; addr += PAGE_SIZE) { + memset((void *)addr, 0xcc, PAGE_SIZE); ClearPageReserved(virt_to_page(addr)); set_page_count(virt_to_page(addr), 1); free_page(addr); From anton at samba.org Tue Sep 6 13:05:58 2005 From: anton at samba.org (Anton Blanchard) Date: Tue, 6 Sep 2005 13:05:58 +1000 Subject: [PATCH] ppc64: speedup cmpxchg Message-ID: <20050906030558.GK6945@krispykreme> cmpxchg has the following code: __typeof__(*(ptr)) _o_ = (o); __typeof__(*(ptr)) _n_ = (n); Unfortunately it makes gcc 4.0 store and load the variables to the stack. Eg in atomic_dec_and_test we get: stw r10,112(r1) stw r9,116(r1) lwz r9,112(r1) lwz r0,116(r1) x86 is just casting the values so do that instead. Also change __xchg* and __cmpxchg* to take unsigned values, removing a few sign extensions. Signed-off-by: Anton Blanchard Index: build/include/asm-ppc64/system.h =================================================================== --- build.orig/include/asm-ppc64/system.h 2005-09-06 11:29:32.000000000 +1000 +++ build/include/asm-ppc64/system.h 2005-09-06 11:29:37.000000000 +1000 @@ -158,7 +158,7 @@ * is more like most of the other architectures. */ static __inline__ unsigned long -__xchg_u32(volatile int *m, unsigned long val) +__xchg_u32(volatile unsigned int *m, unsigned long val) { unsigned long dummy; @@ -200,7 +200,7 @@ extern void __xchg_called_with_bad_pointer(void); static __inline__ unsigned long -__xchg(volatile void *ptr, unsigned long x, int size) +__xchg(volatile void *ptr, unsigned long x, unsigned int size) { switch (size) { case 4: @@ -223,7 +223,7 @@ #define __HAVE_ARCH_CMPXCHG 1 static __inline__ unsigned long -__cmpxchg_u32(volatile int *p, int old, int new) +__cmpxchg_u32(volatile unsigned int *p, unsigned long old, unsigned long new) { unsigned int prev; @@ -271,7 +271,8 @@ extern void __cmpxchg_called_with_bad_pointer(void); static __inline__ unsigned long -__cmpxchg(volatile void *ptr, unsigned long old, unsigned long new, int size) +__cmpxchg(volatile void *ptr, unsigned long old, unsigned long new, + unsigned int size) { switch (size) { case 4: @@ -283,13 +284,9 @@ return old; } -#define cmpxchg(ptr,o,n) \ - ({ \ - __typeof__(*(ptr)) _o_ = (o); \ - __typeof__(*(ptr)) _n_ = (n); \ - (__typeof__(*(ptr))) __cmpxchg((ptr), (unsigned long)_o_, \ - (unsigned long)_n_, sizeof(*(ptr))); \ - }) +#define cmpxchg(ptr,o,n)\ + ((__typeof__(*(ptr)))__cmpxchg((ptr),(unsigned long)(o),\ + (unsigned long)(n),sizeof(*(ptr)))) /* * We handle most unaligned accesses in hardware. On the other hand From paulus at samba.org Tue Sep 6 13:17:54 2005 From: paulus at samba.org (Paul Mackerras) Date: Tue, 6 Sep 2005 13:17:54 +1000 Subject: [PATCH] Separate pci bits out of struct device_node Message-ID: <17181.2658.910786.938698@cargo.ozlabs.ibm.com> This patch pulls the PCI-related junk out of struct device_node and puts it in a separate structure, struct pci_dn. The device_node now just has a void * pointer in it, which points to a struct pci_dn for nodes that represent PCI devices. It could potentially be used in future for device-specific data for other sorts of devices, such as virtual I/O devices. Signed-off-by: Paul Mackerras --- diff -urN linux-2.6/arch/ppc64/kernel/eeh.c pcidn/arch/ppc64/kernel/eeh.c --- linux-2.6/arch/ppc64/kernel/eeh.c 2005-06-24 13:38:52.000000000 +1000 +++ pcidn/arch/ppc64/kernel/eeh.c 2005-09-06 09:53:00.000000000 +1000 @@ -255,6 +255,7 @@ static void __pci_addr_cache_insert_device(struct pci_dev *dev) { struct device_node *dn; + struct pci_dn *pdn; int i; int inserted = 0; @@ -266,8 +267,9 @@ } /* Skip any devices for which EEH is not enabled. */ - if (!(dn->eeh_mode & EEH_MODE_SUPPORTED) || - dn->eeh_mode & EEH_MODE_NOCHECK) { + pdn = dn->data; + if (!(pdn->eeh_mode & EEH_MODE_SUPPORTED) || + pdn->eeh_mode & EEH_MODE_NOCHECK) { #ifdef DEBUG printk(KERN_INFO "PCI: skip building address cache for=%s %s\n", pci_name(dev), pci_pretty_name(dev)); @@ -416,6 +418,7 @@ static int read_slot_reset_state(struct device_node *dn, int rets[]) { int token, outputs; + struct pci_dn *pdn = dn->data; if (ibm_read_slot_reset_state2 != RTAS_UNKNOWN_SERVICE) { token = ibm_read_slot_reset_state2; @@ -425,8 +428,8 @@ outputs = 3; } - return rtas_call(token, 3, outputs, rets, dn->eeh_config_addr, - BUID_HI(dn->phb->buid), BUID_LO(dn->phb->buid)); + return rtas_call(token, 3, outputs, rets, pdn->eeh_config_addr, + BUID_HI(pdn->phb->buid), BUID_LO(pdn->phb->buid)); } /** @@ -535,6 +538,7 @@ unsigned long flags; int rc, reset_state; struct eeh_event *event; + struct pci_dn *pdn; __get_cpu_var(total_mmio_ffs)++; @@ -543,14 +547,15 @@ if (!dn) return 0; + pdn = dn->data; /* Access to IO BARs might get this far and still not want checking. */ - if (!(dn->eeh_mode & EEH_MODE_SUPPORTED) || - dn->eeh_mode & EEH_MODE_NOCHECK) { + if (!pdn->eeh_capable || !(pdn->eeh_mode & EEH_MODE_SUPPORTED) || + pdn->eeh_mode & EEH_MODE_NOCHECK) { return 0; } - if (!dn->eeh_config_addr) { + if (!pdn->eeh_config_addr) { return 0; } @@ -558,7 +563,7 @@ * If we already have a pending isolation event for this * slot, we know it's bad already, we don't need to check... */ - if (dn->eeh_mode & EEH_MODE_ISOLATED) { + if (pdn->eeh_mode & EEH_MODE_ISOLATED) { atomic_inc(&eeh_fail_count); if (atomic_read(&eeh_fail_count) >= EEH_MAX_FAILS) { /* re-read the slot reset state */ @@ -583,7 +588,7 @@ } /* prevent repeated reports of this failure */ - dn->eeh_mode |= EEH_MODE_ISOLATED; + pdn->eeh_mode |= EEH_MODE_ISOLATED; reset_state = rets[0]; @@ -591,9 +596,9 @@ memset(slot_errbuf, 0, eeh_error_buf_size); rc = rtas_call(ibm_slot_error_detail, - 8, 1, NULL, dn->eeh_config_addr, - BUID_HI(dn->phb->buid), - BUID_LO(dn->phb->buid), NULL, 0, + 8, 1, NULL, pdn->eeh_config_addr, + BUID_HI(pdn->phb->buid), + BUID_LO(pdn->phb->buid), NULL, 0, virt_to_phys(slot_errbuf), eeh_error_buf_size, 1 /* Temporary Error */); @@ -680,8 +685,9 @@ u32 *device_id = (u32 *)get_property(dn, "device-id", NULL); u32 *regs; int enable; + struct pci_dn *pdn = dn->data; - dn->eeh_mode = 0; + pdn->eeh_mode = 0; if (status && strcmp(status, "ok") != 0) return NULL; /* ignore devices with bad status */ @@ -692,7 +698,7 @@ /* There is nothing to check on PCI to ISA bridges */ if (dn->type && !strcmp(dn->type, "isa")) { - dn->eeh_mode |= EEH_MODE_NOCHECK; + pdn->eeh_mode |= EEH_MODE_NOCHECK; return NULL; } @@ -709,7 +715,7 @@ enable = 0; if (!enable) - dn->eeh_mode |= EEH_MODE_NOCHECK; + pdn->eeh_mode |= EEH_MODE_NOCHECK; /* Ok... see if this device supports EEH. Some do, some don't, * and the only way to find out is to check each and every one. */ @@ -722,8 +728,8 @@ EEH_ENABLE); if (ret == 0) { eeh_subsystem_enabled = 1; - dn->eeh_mode |= EEH_MODE_SUPPORTED; - dn->eeh_config_addr = regs[0]; + pdn->eeh_mode |= EEH_MODE_SUPPORTED; + pdn->eeh_config_addr = regs[0]; #ifdef DEBUG printk(KERN_DEBUG "EEH: %s: eeh enabled\n", dn->full_name); #endif @@ -731,10 +737,11 @@ /* This device doesn't support EEH, but it may have an * EEH parent, in which case we mark it as supported. */ - if (dn->parent && (dn->parent->eeh_mode & EEH_MODE_SUPPORTED)) { + if (dn->parent && dn->parent->data + && (PCI_DN(dn->parent)->eeh_mode & EEH_MODE_SUPPORTED)) { /* Parent supports EEH. */ - dn->eeh_mode |= EEH_MODE_SUPPORTED; - dn->eeh_config_addr = dn->parent->eeh_config_addr; + pdn->eeh_mode |= EEH_MODE_SUPPORTED; + pdn->eeh_config_addr = PCI_DN(dn->parent)->eeh_config_addr; return NULL; } } @@ -791,11 +798,13 @@ for (phb = of_find_node_by_name(NULL, "pci"); phb; phb = of_find_node_by_name(phb, "pci")) { unsigned long buid; + struct pci_dn *pci; buid = get_phb_buid(phb); - if (buid == 0) + if (buid == 0 || phb->data == NULL) continue; + pci = phb->data; info.buid_lo = BUID_LO(buid); info.buid_hi = BUID_HI(buid); traverse_pci_devices(phb, early_enable_eeh, &info); @@ -824,9 +833,9 @@ struct pci_controller *phb; struct eeh_early_enable_info info; - if (!dn) + if (!dn || !dn->data) return; - phb = dn->phb; + phb = PCI_DN(dn)->phb; if (NULL == phb || 0 == phb->buid) { printk(KERN_WARNING "EEH: Expected buid but found none\n"); return; diff -urN linux-2.6/arch/ppc64/kernel/iommu.c pcidn/arch/ppc64/kernel/iommu.c --- linux-2.6/arch/ppc64/kernel/iommu.c 2005-08-18 12:59:18.000000000 +1000 +++ pcidn/arch/ppc64/kernel/iommu.c 2005-09-06 08:18:54.000000000 +1000 @@ -438,7 +438,8 @@ void iommu_free_table(struct device_node *dn) { - struct iommu_table *tbl = dn->iommu_table; + struct pci_dn *pdn = dn->data; + struct iommu_table *tbl = pdn->iommu_table; unsigned long bitmap_sz, i; unsigned int order; diff -urN linux-2.6/arch/ppc64/kernel/maple_pci.c pcidn/arch/ppc64/kernel/maple_pci.c --- linux-2.6/arch/ppc64/kernel/maple_pci.c 2005-04-26 15:37:55.000000000 +1000 +++ pcidn/arch/ppc64/kernel/maple_pci.c 2005-09-06 10:13:13.000000000 +1000 @@ -447,9 +447,9 @@ */ if (u3_agp) { struct device_node *np = u3_agp->arch_data; - np->busno = 0xf0; + PCI_DN(np)->busno = 0xf0; for (np = np->child; np; np = np->sibling) - np->busno = 0xf0; + PCI_DN(np)->busno = 0xf0; } /* Tell pci.c to use the common resource allocation mecanism */ diff -urN linux-2.6/arch/ppc64/kernel/pSeries_iommu.c pcidn/arch/ppc64/kernel/pSeries_iommu.c --- linux-2.6/arch/ppc64/kernel/pSeries_iommu.c 2005-08-30 11:43:32.000000000 +1000 +++ pcidn/arch/ppc64/kernel/pSeries_iommu.c 2005-09-06 09:51:49.000000000 +1000 @@ -295,7 +295,7 @@ struct iommu_table *tbl, unsigned int *dma_window) { - tbl->it_busno = dn->bussubno; + tbl->it_busno = PCI_DN(dn)->bussubno; /* TODO: Parse field size properties properly. */ tbl->it_size = (((unsigned long)dma_window[4] << 32) | @@ -311,6 +311,7 @@ static void iommu_bus_setup_pSeries(struct pci_bus *bus) { struct device_node *dn, *pdn; + struct pci_dn *pci; struct iommu_table *tbl; DBG("iommu_bus_setup_pSeries, bus %p, bus->self %p\n", bus, bus->self); @@ -325,6 +326,7 @@ */ dn = pci_bus_to_OF_node(bus); + pci = dn->data; if (!bus->self) { /* Root bus */ @@ -341,18 +343,18 @@ * alltogether. This leaves 768MB for the window. */ DBG("PHB has io-hole, reserving 256MB\n"); - dn->phb->dma_window_size = 3 << 28; - dn->phb->dma_window_base_cur = 1 << 28; + pci->phb->dma_window_size = 3 << 28; + pci->phb->dma_window_base_cur = 1 << 28; } else { /* 1GB window by default */ - dn->phb->dma_window_size = 1 << 30; - dn->phb->dma_window_base_cur = 0; + pci->phb->dma_window_size = 1 << 30; + pci->phb->dma_window_base_cur = 0; } tbl = kmalloc(sizeof(struct iommu_table), GFP_KERNEL); - iommu_table_setparms(dn->phb, dn, tbl); - dn->iommu_table = iommu_init_table(tbl); + iommu_table_setparms(pci->phb, dn, tbl); + pci->iommu_table = iommu_init_table(tbl); } else { /* Do a 128MB table at root. This is used for the IDE * controller on some SMP-mode POWER4 machines. It @@ -363,16 +365,16 @@ * Allocate at offset 128MB to avoid having to deal * with ISA holes; 128MB table for IDE is plenty. */ - dn->phb->dma_window_size = 1 << 27; - dn->phb->dma_window_base_cur = 1 << 27; + pci->phb->dma_window_size = 1 << 27; + pci->phb->dma_window_base_cur = 1 << 27; tbl = kmalloc(sizeof(struct iommu_table), GFP_KERNEL); - iommu_table_setparms(dn->phb, dn, tbl); - dn->iommu_table = iommu_init_table(tbl); + iommu_table_setparms(pci->phb, dn, tbl); + pci->iommu_table = iommu_init_table(tbl); /* All child buses have 256MB tables */ - dn->phb->dma_window_size = 1 << 28; + pci->phb->dma_window_size = 1 << 28; } } else { pdn = pci_bus_to_OF_node(bus->parent); @@ -386,12 +388,12 @@ tbl = kmalloc(sizeof(struct iommu_table), GFP_KERNEL); - iommu_table_setparms(dn->phb, dn, tbl); + iommu_table_setparms(pci->phb, dn, tbl); - dn->iommu_table = iommu_init_table(tbl); + pci->iommu_table = iommu_init_table(tbl); } else { /* Lower than first child or under python, use parent table */ - dn->iommu_table = pdn->iommu_table; + pci->iommu_table = PCI_DN(pdn)->iommu_table; } } } @@ -401,6 +403,7 @@ { struct iommu_table *tbl; struct device_node *dn, *pdn; + struct pci_dn *ppci; unsigned int *dma_window = NULL; DBG("iommu_bus_setup_pSeriesLP, bus %p, bus->self %p\n", bus, bus->self); @@ -419,22 +422,24 @@ return; } - if (!pdn->iommu_table) { + ppci = pdn->data; + if (!ppci->iommu_table) { /* Bussubno hasn't been copied yet. * Do it now because iommu_table_setparms_lpar needs it. */ - pdn->bussubno = bus->number; + + ppci->bussubno = bus->number; tbl = (struct iommu_table *)kmalloc(sizeof(struct iommu_table), GFP_KERNEL); - iommu_table_setparms_lpar(pdn->phb, pdn, tbl, dma_window); + iommu_table_setparms_lpar(ppci->phb, pdn, tbl, dma_window); - pdn->iommu_table = iommu_init_table(tbl); + ppci->iommu_table = iommu_init_table(tbl); } if (pdn != dn) - dn->iommu_table = pdn->iommu_table; + PCI_DN(dn)->iommu_table = ppci->iommu_table; } @@ -449,11 +454,11 @@ */ mydn = dn = pci_device_to_OF_node(dev); - while (dn && dn->iommu_table == NULL) + while (dn && dn->data && PCI_DN(dn)->iommu_table == NULL) dn = dn->parent; - if (dn) { - mydn->iommu_table = dn->iommu_table; + if (dn && dn->data) { + PCI_DN(mydn)->iommu_table = PCI_DN(dn)->iommu_table; } else { DBG("iommu_dev_setup_pSeries, dev %p (%s) has no iommu table\n", dev, dev->pretty_name); } @@ -463,10 +468,11 @@ { int err = NOTIFY_OK; struct device_node *np = node; + struct pci_dn *pci = np->data; switch (action) { case PSERIES_RECONFIG_REMOVE: - if (np->iommu_table && + if (pci->iommu_table && get_property(np, "ibm,dma-window", NULL)) iommu_free_table(np); break; @@ -486,6 +492,7 @@ struct device_node *pdn, *dn; struct iommu_table *tbl; int *dma_window = NULL; + struct pci_dn *pci; DBG("iommu_dev_setup_pSeriesLP, dev %p (%s)\n", dev, dev->pretty_name); @@ -497,8 +504,10 @@ */ dn = pci_device_to_OF_node(dev); - for (pdn = dn; pdn && !pdn->iommu_table; pdn = pdn->parent) { - dma_window = (unsigned int *)get_property(pdn, "ibm,dma-window", NULL); + for (pdn = dn; pdn && pdn->data && !PCI_DN(pdn)->iommu_table; + pdn = pdn->parent) { + dma_window = (unsigned int *) + get_property(pdn, "ibm,dma-window", NULL); if (dma_window) break; } @@ -515,20 +524,21 @@ DBG("Found DMA window, allocating table\n"); } - if (!pdn->iommu_table) { + pci = pdn->data; + if (!pci->iommu_table) { /* iommu_table_setparms_lpar needs bussubno. */ - pdn->bussubno = pdn->phb->bus->number; + pci->bussubno = pci->phb->bus->number; tbl = (struct iommu_table *)kmalloc(sizeof(struct iommu_table), GFP_KERNEL); - iommu_table_setparms_lpar(pdn->phb, pdn, tbl, dma_window); + iommu_table_setparms_lpar(pci->phb, pdn, tbl, dma_window); - pdn->iommu_table = iommu_init_table(tbl); + pci->iommu_table = iommu_init_table(tbl); } if (pdn != dn) - dn->iommu_table = pdn->iommu_table; + PCI_DN(dn)->iommu_table = pci->iommu_table; } static void iommu_bus_setup_null(struct pci_bus *b) { } diff -urN linux-2.6/arch/ppc64/kernel/pci.c pcidn/arch/ppc64/kernel/pci.c --- linux-2.6/arch/ppc64/kernel/pci.c 2005-08-05 16:04:58.000000000 +1000 +++ pcidn/arch/ppc64/kernel/pci.c 2005-09-06 09:25:07.000000000 +1000 @@ -838,9 +838,11 @@ * device tree. If they are then we need to scan all the * functions of this slot. */ - for (dn = busdn->child; dn; dn = dn->sibling) - if ((dn->devfn >> 3) == (devfn >> 3)) + for (dn = busdn->child; dn; dn = dn->sibling) { + struct pci_dn *pdn = dn->data; + if (pdn && (pdn->devfn >> 3) == (devfn >> 3)) return 1; + } return 0; } diff -urN linux-2.6/arch/ppc64/kernel/pci.h pcidn/arch/ppc64/kernel/pci.h --- linux-2.6/arch/ppc64/kernel/pci.h 2005-06-24 13:38:52.000000000 +1000 +++ pcidn/arch/ppc64/kernel/pci.h 2005-09-06 08:18:54.000000000 +1000 @@ -34,7 +34,6 @@ void pci_devs_phb_init(void); void pci_devs_phb_init_dynamic(struct pci_controller *phb); -struct device_node *fetch_dev_dn(struct pci_dev *dev); /* PCI address cache management routines */ void pci_addr_cache_insert_device(struct pci_dev *dev); diff -urN linux-2.6/arch/ppc64/kernel/pci_dn.c pcidn/arch/ppc64/kernel/pci_dn.c --- linux-2.6/arch/ppc64/kernel/pci_dn.c 2005-04-26 15:37:55.000000000 +1000 +++ pcidn/arch/ppc64/kernel/pci_dn.c 2005-09-06 11:39:47.000000000 +1000 @@ -23,6 +23,8 @@ #include #include #include +#include +#include #include #include @@ -40,16 +42,26 @@ struct pci_controller *phb = data; int *type = (int *)get_property(dn, "ibm,pci-config-space-type", NULL); u32 *regs; + struct pci_dn *pdn; - dn->phb = phb; + if (phb->is_dynamic) + pdn = kmalloc(sizeof(*pdn), GFP_KERNEL); + else + pdn = alloc_bootmem(sizeof(*pdn)); + if (pdn == NULL) + return NULL; + memset(pdn, 0, sizeof(*pdn)); + dn->data = pdn; + pdn->node = dn; + pdn->phb = phb; regs = (u32 *)get_property(dn, "reg", NULL); if (regs) { /* First register entry is addr (00BBSS00) */ - dn->busno = (regs[0] >> 16) & 0xff; - dn->devfn = (regs[0] >> 8) & 0xff; + pdn->busno = (regs[0] >> 16) & 0xff; + pdn->devfn = (regs[0] >> 8) & 0xff; } - dn->pci_ext_config_space = (type && *type == 1); + pdn->pci_ext_config_space = (type && *type == 1); return NULL; } @@ -112,10 +124,15 @@ void __devinit pci_devs_phb_init_dynamic(struct pci_controller *phb) { struct device_node * dn = (struct device_node *) phb->arch_data; + struct pci_dn *pdn; /* PHB nodes themselves must not match */ - dn->devfn = dn->busno = -1; - dn->phb = phb; + update_dn_pci_info(dn, phb); + pdn = dn->data; + if (pdn) { + pdn->devfn = pdn->busno = -1; + pdn->phb = phb; + } /* Update dn->phb ptrs for new phb and children devices */ traverse_pci_devices(dn, update_dn_pci_info, phb); @@ -123,14 +140,17 @@ /* * Traversal func that looks for a value. - * If found, the device_node is returned (thus terminating the traversal). + * If found, the pci_dn is returned (thus terminating the traversal). */ static void *is_devfn_node(struct device_node *dn, void *data) { int busno = ((unsigned long)data >> 8) & 0xff; int devfn = ((unsigned long)data) & 0xff; + struct pci_dn *pci = dn->data; - return ((devfn == dn->devfn) && (busno == dn->busno)) ? dn : NULL; + if (pci && (devfn == pci->devfn) && (busno == pci->busno)) + return dn; + return NULL; } /* @@ -149,13 +169,10 @@ struct device_node *fetch_dev_dn(struct pci_dev *dev) { struct device_node *orig_dn = dev->sysdata; - struct pci_controller *phb = orig_dn->phb; /* assume same phb as orig_dn */ - struct device_node *phb_dn; struct device_node *dn; unsigned long searchval = (dev->bus->number << 8) | dev->devfn; - phb_dn = phb->arch_data; - dn = traverse_pci_devices(phb_dn, is_devfn_node, (void *)searchval); + dn = traverse_pci_devices(orig_dn, is_devfn_node, (void *)searchval); if (dn) dev->sysdata = dn; return dn; @@ -165,11 +182,13 @@ static int pci_dn_reconfig_notifier(struct notifier_block *nb, unsigned long action, void *node) { struct device_node *np = node; + struct pci_dn *pci; int err = NOTIFY_OK; switch (action) { case PSERIES_RECONFIG_ADD: - update_dn_pci_info(np, np->parent->phb); + pci = np->parent->data; + update_dn_pci_info(np, pci->phb); break; default: err = NOTIFY_DONE; diff -urN linux-2.6/arch/ppc64/kernel/pci_iommu.c pcidn/arch/ppc64/kernel/pci_iommu.c --- linux-2.6/arch/ppc64/kernel/pci_iommu.c 2005-04-26 15:37:55.000000000 +1000 +++ pcidn/arch/ppc64/kernel/pci_iommu.c 2005-09-06 09:58:44.000000000 +1000 @@ -66,7 +66,7 @@ #endif /* CONFIG_PPC_ISERIES */ #ifdef CONFIG_PPC_MULTIPLATFORM - return PCI_GET_DN(pdev)->iommu_table; + return PCI_DN(PCI_GET_DN(pdev))->iommu_table; #endif /* CONFIG_PPC_MULTIPLATFORM */ } diff -urN linux-2.6/arch/ppc64/kernel/pmac_feature.c pcidn/arch/ppc64/kernel/pmac_feature.c --- linux-2.6/arch/ppc64/kernel/pmac_feature.c 2005-04-26 15:37:55.000000000 +1000 +++ pcidn/arch/ppc64/kernel/pmac_feature.c 2005-09-06 10:14:24.000000000 +1000 @@ -674,6 +674,7 @@ #if 0 /* Disabled for now */ u32 ufreq, freq, ucfg, cfg; struct device_node *pcix_node; + struct pci_dn *pdn; u8 px_bus, px_devfn; struct pci_controller *px_hose; @@ -687,9 +688,10 @@ printk("No PCI-X bridge found\n"); return; } - px_hose = pcix_node->phb; - px_bus = pcix_node->busno; - px_devfn = pcix_node->devfn; + pdn = pcix_node->data; + px_hose = pdn->phb; + px_bus = pdn->busno; + px_devfn = pdn->devfn; early_read_config_dword(px_hose, px_bus, px_devfn, 0xc4, &cfg); early_read_config_dword(px_hose, px_bus, px_devfn, 0xcc, &freq); diff -urN linux-2.6/arch/ppc64/kernel/pmac_pci.c pcidn/arch/ppc64/kernel/pmac_pci.c --- linux-2.6/arch/ppc64/kernel/pmac_pci.c 2005-04-26 15:37:55.000000000 +1000 +++ pcidn/arch/ppc64/kernel/pmac_pci.c 2005-09-06 10:12:57.000000000 +1000 @@ -242,7 +242,7 @@ else busdn = hose->arch_data; for (dn = busdn->child; dn; dn = dn->sibling) - if (dn->devfn == devfn) + if (dn->data && PCI_DN(dn)->devfn == devfn) break; if (dn == NULL) return -1; @@ -746,9 +746,9 @@ */ if (u3_agp) { struct device_node *np = u3_agp->arch_data; - np->busno = 0xf0; + PCI_DN(np)->busno = 0xf0; for (np = np->child; np; np = np->sibling) - np->busno = 0xf0; + PCI_DN(np)->busno = 0xf0; } pmac_check_ht_link(); diff -urN linux-2.6/arch/ppc64/kernel/rtas_pci.c pcidn/arch/ppc64/kernel/rtas_pci.c --- linux-2.6/arch/ppc64/kernel/rtas_pci.c 2005-08-30 11:43:32.000000000 +1000 +++ pcidn/arch/ppc64/kernel/rtas_pci.c 2005-09-06 09:52:59.000000000 +1000 @@ -48,7 +48,7 @@ static int ibm_read_pci_config; static int ibm_write_pci_config; -static int config_access_valid(struct device_node *dn, int where) +static int config_access_valid(struct pci_dn *dn, int where) { if (where < 256) return 1; @@ -78,15 +78,17 @@ int returnval = -1; unsigned long buid, addr; int ret; + struct pci_dn *pdn; - if (!dn) + if (!dn || !dn->data) return PCIBIOS_DEVICE_NOT_FOUND; - if (!config_access_valid(dn, where)) + pdn = dn->data; + if (!config_access_valid(pdn, where)) return PCIBIOS_BAD_REGISTER_NUMBER; - addr = ((where & 0xf00) << 20) | (dn->busno << 16) | - (dn->devfn << 8) | (where & 0xff); - buid = dn->phb->buid; + addr = ((where & 0xf00) << 20) | (pdn->busno << 16) | + (pdn->devfn << 8) | (where & 0xff); + buid = pdn->phb->buid; if (buid) { ret = rtas_call(ibm_read_pci_config, 4, 2, &returnval, addr, buid >> 32, buid & 0xffffffff, size); @@ -98,8 +100,8 @@ if (ret) return PCIBIOS_DEVICE_NOT_FOUND; - if (returnval == EEH_IO_ERROR_VALUE(size) - && eeh_dn_check_failure (dn, NULL)) + if (returnval == EEH_IO_ERROR_VALUE(size) && + eeh_dn_check_failure (dn, NULL)) return PCIBIOS_DEVICE_NOT_FOUND; return PCIBIOS_SUCCESSFUL; @@ -118,24 +120,28 @@ /* Search only direct children of the bus */ for (dn = busdn->child; dn; dn = dn->sibling) - if (dn->devfn == devfn && of_device_available(dn)) + if (dn->data && PCI_DN(dn)->devfn == devfn + && of_device_available(dn)) return rtas_read_config(dn, where, size, val); + return PCIBIOS_DEVICE_NOT_FOUND; } -static int rtas_write_config(struct device_node *dn, int where, int size, u32 val) +int rtas_write_config(struct device_node *dn, int where, int size, u32 val) { unsigned long buid, addr; int ret; + struct pci_dn *pdn; - if (!dn) + if (!dn || !dn->data) return PCIBIOS_DEVICE_NOT_FOUND; - if (!config_access_valid(dn, where)) + pdn = dn->data; + if (!config_access_valid(pdn, where)) return PCIBIOS_BAD_REGISTER_NUMBER; - addr = ((where & 0xf00) << 20) | (dn->busno << 16) | - (dn->devfn << 8) | (where & 0xff); - buid = dn->phb->buid; + addr = ((where & 0xf00) << 20) | (pdn->busno << 16) | + (pdn->devfn << 8) | (where & 0xff); + buid = pdn->phb->buid; if (buid) { ret = rtas_call(ibm_write_pci_config, 5, 1, NULL, addr, buid >> 32, buid & 0xffffffff, size, (ulong) val); } else { @@ -161,7 +167,8 @@ /* Search only direct children of the bus */ for (dn = busdn->child; dn; dn = dn->sibling) - if (dn->devfn == devfn && of_device_available(dn)) + if (dn->data && PCI_DN(dn)->devfn == devfn + && of_device_available(dn)) return rtas_write_config(dn, where, size, val); return PCIBIOS_DEVICE_NOT_FOUND; } diff -urN linux-2.6/arch/ppc64/kernel/sys_ppc32.c pcidn/arch/ppc64/kernel/sys_ppc32.c --- linux-2.6/arch/ppc64/kernel/sys_ppc32.c 2005-07-14 20:07:04.000000000 +1000 +++ pcidn/arch/ppc64/kernel/sys_ppc32.c 2005-09-06 09:58:44.000000000 +1000 @@ -747,8 +747,8 @@ if (bus == NULL || bus->sysdata == NULL) return -ENODEV; - hose_node = (struct device_node *)bus->sysdata; - hose = hose_node->phb; + hose_node = bus->sysdata; + hose = PCI_DN(hose_node)->phb; switch (which) { case IOBASE_BRIDGE_NUMBER: diff -urN linux-2.6/arch/ppc64/kernel/u3_iommu.c pcidn/arch/ppc64/kernel/u3_iommu.c --- linux-2.6/arch/ppc64/kernel/u3_iommu.c 2005-04-26 15:37:55.000000000 +1000 +++ pcidn/arch/ppc64/kernel/u3_iommu.c 2005-09-06 10:14:57.000000000 +1000 @@ -276,7 +276,7 @@ dn = pci_device_to_OF_node(dev); if (dn) - dn->iommu_table = &iommu_table_u3; + PCI_DN(dn)->iommu_table = &iommu_table_u3; } static void iommu_bus_setup_u3(struct pci_bus *bus) @@ -291,7 +291,7 @@ dn = pci_bus_to_OF_node(bus); if (dn) - dn->iommu_table = &iommu_table_u3; + PCI_DN(dn)->iommu_table = &iommu_table_u3; } static void iommu_dev_setup_null(struct pci_dev *dev) { } diff -urN linux-2.6/drivers/pci/hotplug/rpadlpar_core.c pcidn/drivers/pci/hotplug/rpadlpar_core.c --- linux-2.6/drivers/pci/hotplug/rpadlpar_core.c 2005-04-26 15:37:58.000000000 +1000 +++ pcidn/drivers/pci/hotplug/rpadlpar_core.c 2005-09-06 08:18:54.000000000 +1000 @@ -131,7 +131,8 @@ static int pci_add_secondary_bus(struct device_node *dn, struct pci_dev *bridge_dev) { - struct pci_controller *hose = dn->phb; + struct pci_dn *pdn = dn->data; + struct pci_controller *hose = pdn->phb; struct pci_bus *child; u8 sec_busno; @@ -156,7 +157,7 @@ if (hose->last_busno < child->number) hose->last_busno = child->number; - dn->bussubno = child->number; + pdn->bussubno = child->number; /* ioremap() for child bus, which may or may not succeed */ remap_bus_range(child); @@ -166,11 +167,12 @@ static struct pci_dev *dlpar_pci_add_bus(struct device_node *dn) { - struct pci_controller *hose = dn->phb; + struct pci_dn *pdn = dn->data; + struct pci_controller *hose = pdn->phb; struct pci_dev *dev = NULL; /* Scan phb bus for EADS device, adding new one to bus->devices */ - if (!pci_scan_single_device(hose->bus, dn->devfn)) { + if (!pci_scan_single_device(hose->bus, pdn->devfn)) { printk(KERN_ERR "%s: found no device on bus\n", __FUNCTION__); return NULL; } @@ -259,16 +261,18 @@ { struct pci_controller *phb; struct device_node *dn; + struct pci_dn *pdn; int rc = 0; dn = slot->dn; - if (!dn) { + if (!dn || !dn->data) { printk(KERN_ERR "%s: unexpected NULL slot device node\n", __FUNCTION__); return -EIO; } - phb = dn->phb; + pdn = dn->data; + phb = pdn->phb; if (!phb) { printk(KERN_ERR "%s: unexpected NULL phb pointer\n", __FUNCTION__); diff -urN linux-2.6/drivers/pci/hotplug/rpaphp_pci.c pcidn/drivers/pci/hotplug/rpaphp_pci.c --- linux-2.6/drivers/pci/hotplug/rpaphp_pci.c 2005-04-26 15:37:58.000000000 +1000 +++ pcidn/drivers/pci/hotplug/rpaphp_pci.c 2005-09-06 08:18:54.000000000 +1000 @@ -33,10 +33,11 @@ struct pci_dev *rpaphp_find_pci_dev(struct device_node *dn) { struct pci_dev *dev = NULL; + struct pci_dn *pdn = dn->data; char bus_id[BUS_ID_SIZE]; - sprintf(bus_id, "%04x:%02x:%02x.%d", dn->phb->global_number, - dn->busno, PCI_SLOT(dn->devfn), PCI_FUNC(dn->devfn)); + sprintf(bus_id, "%04x:%02x:%02x.%d", pdn->phb->global_number, + pdn->busno, PCI_SLOT(pdn->devfn), PCI_FUNC(pdn->devfn)); for_each_pci_dev(dev) { if (!strcmp(pci_name(dev), bus_id)) { break; @@ -203,7 +204,8 @@ if (eads_first_child) { /* pci_scan_slot should find all children of EADs */ - num = pci_scan_slot(bus, PCI_DEVFN(PCI_SLOT(eads_first_child->devfn), 0)); + struct pci_dn *pdn = eads_first_child->data; + num = pci_scan_slot(bus, PCI_DEVFN(PCI_SLOT(pdn->devfn), 0)); if (num) { rpaphp_fixup_new_pci_devices(bus, 1); pci_bus_add_devices(bus); @@ -359,14 +361,16 @@ static int set_phb_slot_name(struct slot *slot) { struct device_node *dn; + struct pci_dn *pdn; struct pci_controller *phb; struct pci_bus *bus; dn = slot->dn; - if (!dn) { + if (!dn || !dn->data) { return -EINVAL; } - phb = dn->phb; + pdn = dn->data; + phb = pdn->phb; if (!phb) { return -EINVAL; } diff -urN linux-2.6/drivers/video/offb.c pcidn/drivers/video/offb.c --- linux-2.6/drivers/video/offb.c 2005-04-26 15:37:59.000000000 +1000 +++ pcidn/drivers/video/offb.c 2005-09-06 08:18:54.000000000 +1000 @@ -363,7 +363,7 @@ address = (u_long) dp->addrs[i].address; #ifdef CONFIG_PPC64 - address += dp->phb->pci_mem_offset; + address += ((struct pci_dn *)dp->data)->phb->pci_mem_offset; #endif /* kludge for valkyrie */ diff -urN linux-2.6/include/asm-ppc64/pci-bridge.h pcidn/include/asm-ppc64/pci-bridge.h --- linux-2.6/include/asm-ppc64/pci-bridge.h 2005-04-26 15:38:02.000000000 +1000 +++ pcidn/include/asm-ppc64/pci-bridge.h 2005-09-06 11:51:33.000000000 +1000 @@ -48,19 +48,52 @@ unsigned long dma_window_size; }; +/* + * PCI stuff, for nodes representing PCI devices, pointed to + * by device_node->data. + */ +struct pci_controller; +struct iommu_table; + +struct pci_dn { + int busno; /* for pci devices */ + int bussubno; /* for pci devices */ + int devfn; /* for pci devices */ + int eeh_mode; /* See eeh.h for possible EEH_MODEs */ + int eeh_config_addr; + int eeh_capable; /* from firmware */ + int eeh_check_count; /* # times driver ignored error */ + int eeh_freeze_count; /* # times this device froze up. */ + int eeh_is_bridge; /* device is pci-to-pci bridge */ + + int pci_ext_config_space; /* for pci devices */ + struct pci_controller *phb; /* for pci devices */ + struct iommu_table *iommu_table; /* for phb's or bridges */ + struct pci_dev *pcidev; /* back-pointer to the pci device */ + struct device_node *node; /* back-pointer to the device_node */ + u32 config_space[16]; /* saved PCI config space */ +}; + +/* Get the pointer to a device_node's pci_dn */ +#define PCI_DN(dn) ((struct pci_dn *) (dn)->data) + struct device_node *fetch_dev_dn(struct pci_dev *dev); -/* Get a device_node from a pci_dev. This code must be fast except in the case - * where the sysdata is incorrect and needs to be fixed up (hopefully just once) +/* Get a device_node from a pci_dev. This code must be fast except + * in the case where the sysdata is incorrect and needs to be fixed + * up (this will only happen once). + * In this case the sysdata will have been inherited from a PCI host + * bridge or a PCI-PCI bridge further up the tree, so it will point + * to a valid struct pci_dn, just not the one we want. */ static inline struct device_node *pci_device_to_OF_node(struct pci_dev *dev) { struct device_node *dn = dev->sysdata; + struct pci_dn *pdn = dn->data; - if (dn->devfn == dev->devfn && dn->busno == dev->bus->number) + if (pdn && pdn->devfn == dev->devfn && pdn->busno == dev->bus->number) return dn; /* fast path. sysdata is good */ - else - return fetch_dev_dn(dev); + return fetch_dev_dn(dev); } static inline struct device_node *pci_bus_to_OF_node(struct pci_bus *bus) @@ -83,7 +116,7 @@ struct device_node *busdn = bus->sysdata; BUG_ON(busdn == NULL); - return busdn->phb; + return PCI_DN(busdn)->phb; } #endif diff -urN linux-2.6/include/asm-ppc64/prom.h pcidn/include/asm-ppc64/prom.h --- linux-2.6/include/asm-ppc64/prom.h 2005-08-30 11:43:32.000000000 +1000 +++ pcidn/include/asm-ppc64/prom.h 2005-09-06 08:18:54.000000000 +1000 @@ -116,14 +116,6 @@ struct property *next; }; -/* NOTE: the device_node contains PCI specific info for pci devices. - * This perhaps could be hung off the device_node with another struct, - * but for now it is directly in the node. The phb ptr is a good - * indication of a real PCI node. Other nodes leave these fields zeroed. - */ -struct pci_controller; -struct iommu_table; - struct device_node { char *name; char *type; @@ -135,16 +127,6 @@ struct interrupt_info *intrs; char *full_name; - /* PCI stuff probably doesn't belong here */ - int busno; /* for pci devices */ - int bussubno; /* for pci devices */ - int devfn; /* for pci devices */ - int eeh_mode; /* See eeh.h for possible EEH_MODEs */ - int eeh_config_addr; - int pci_ext_config_space; /* for pci devices */ - struct pci_controller *phb; /* for pci devices */ - struct iommu_table *iommu_table; /* for phb's or bridges */ - struct property *properties; struct device_node *parent; struct device_node *child; @@ -154,6 +136,7 @@ struct proc_dir_entry *pde; /* this node's proc directory */ struct kref kref; unsigned long _flags; + void *data; }; extern struct device_node *of_chosen; From wim.coekaerts at oracle.com Tue Sep 6 13:22:47 2005 From: wim.coekaerts at oracle.com (Wim Coekaerts) Date: Mon, 5 Sep 2005 20:22:47 -0700 Subject: [RFC] patch to allow world readable /proc/ppc64/lparcfg Message-ID: <20050906032247.GA313@ca-server1.us.oracle.com> Hi - resent my mailserver is having issues like to be able to read the lparcfg data from any user so we can make "intelligent" decisions based on underlying attributes when running in lpars. yes there's software that likes to do this :) and runs as non-root. I'm not sure if anyone has any issues with this but I'd say it would be pretty harmless. if ok please apply this just clearly allows all read of /proc/ppc64/lparcfg it's very similar to say VM where you can get CP to provide feedback of the real hardware inside a VM guest Signed-off-by: Wim Coekaerts --- /tmp/l/arch/ppc64/kernel/lparcfg.c 2005-09-01 16:36:50.000000000 -0700 +++ linux-2.6.13/arch/ppc64/kernel/lparcfg.c 2005-09-01 16:37:28.000000000 -0700 @@ -568,7 +568,7 @@ int __init lparcfg_init(void) { struct proc_dir_entry *ent; - mode_t mode = S_IRUSR; + mode_t mode = S_IRUSR | S_IRGRP | S_IROTH; /* Allow writing if we have FW_FEATURE_SPLPAR */ if (cur_cpu_spec->firmware_features & FW_FEATURE_SPLPAR) { From ntl at pobox.com Tue Sep 6 14:13:31 2005 From: ntl at pobox.com (Nathan Lynch) Date: Mon, 5 Sep 2005 23:13:31 -0500 Subject: [PATCH] Separate pci bits out of struct device_node In-Reply-To: <17181.2658.910786.938698@cargo.ozlabs.ibm.com> References: <17181.2658.910786.938698@cargo.ozlabs.ibm.com> Message-ID: <20050906041331.GA3560@otto> Hi Paul, No objection to the intent, but some concerns below. Paul Mackerras wrote: > @@ -40,16 +42,26 @@ > struct pci_controller *phb = data; > int *type = (int *)get_property(dn, "ibm,pci-config-space-type", NULL); > u32 *regs; > + struct pci_dn *pdn; > > - dn->phb = phb; > + if (phb->is_dynamic) > + pdn = kmalloc(sizeof(*pdn), GFP_KERNEL); > + else > + pdn = alloc_bootmem(sizeof(*pdn)); I don't see in the patch where the pci_dn is freed when its device_node goes away. Should the lifetime of a pci_dn be tied to its corresponding device_node? Should code which accesses a pci_dn hold a reference to its corresponding device_node? From paulus at samba.org Tue Sep 6 14:31:58 2005 From: paulus at samba.org (Paul Mackerras) Date: Tue, 6 Sep 2005 14:31:58 +1000 Subject: [PATCH] Separate pci bits out of struct device_node In-Reply-To: <20050906041331.GA3560@otto> References: <17181.2658.910786.938698@cargo.ozlabs.ibm.com> <20050906041331.GA3560@otto> Message-ID: <17181.7102.364381.677922@cargo.ozlabs.ibm.com> Nathan Lynch writes: > I don't see in the patch where the pci_dn is freed when its > device_node goes away. > > Should the lifetime of a pci_dn be tied to its corresponding > device_node? Yes... something like the (additional) patch below should do it. > Should code which accesses a pci_dn hold a reference to its > corresponding device_node? Well, you can only get to a pci_dn via a device_node, and nothing keeps long-lived references to a pci_dn, so I don't think I have changed the situation at all. The reference to the device_node from the pci_dev and pci_bus are already refcounted IIRC. Regards, Paul. diff -urN linux-2.6/arch/ppc64/kernel/prom.c pcidn/arch/ppc64/kernel/prom.c --- linux-2.6/arch/ppc64/kernel/prom.c 2005-08-30 11:43:32.000000000 +1000 +++ pcidn/arch/ppc64/kernel/prom.c 2005-09-06 14:23:49.000000000 +1000 @@ -1734,6 +1734,8 @@ kfree(node->intrs); kfree(node->addrs); kfree(node->full_name); + if (node->data) + kfree(node->data); kfree(node); } From david at gibson.dropbear.id.au Tue Sep 6 14:59:47 2005 From: david at gibson.dropbear.id.au (David Gibson) Date: Tue, 6 Sep 2005 14:59:47 +1000 Subject: Invert sense of SLB class bit Message-ID: <20050906045947.GB8628@localhost.localdomain> Currently, we set the class bit in kernel SLB entries, and clear it on user SLB entries. On POWER5, ERAT entries created in real mode have the class bit clear. So to avoid flushing kernel ERAT entries on each context switch, this patch inverts our usage of the class bit, setting it on user SLB entries and clearing it on kernel SLB entries. Booted on POWER5 and G5. Signed-off-by: David Gibson Index: working-2.6/arch/ppc64/kernel/entry.S =================================================================== --- working-2.6.orig/arch/ppc64/kernel/entry.S 2005-06-08 15:50:39.000000000 +1000 +++ working-2.6/arch/ppc64/kernel/entry.S 2005-09-05 10:52:47.000000000 +1000 @@ -400,15 +400,14 @@ cmpd cr1,r6,r9 /* or is new ESID the same as current ESID? */ cror eq,4*cr1+eq,eq beq 2f /* if yes, don't slbie it */ - oris r0,r6,0x0800 /* set C (class) bit */ /* Bolt in the new stack SLB entry */ ld r7,KSP_VSID(r4) /* Get new stack's VSID */ - oris r6,r6,(SLB_ESID_V)@h - ori r6,r6,(SLB_NUM_BOLTED-1)@l - slbie r0 - slbie r0 /* Workaround POWER5 < DD2.1 issue */ - slbmte r7,r6 + oris r0,r6,(SLB_ESID_V)@h + ori r0,r0,(SLB_NUM_BOLTED-1)@l + slbie r6 + slbie r6 /* Workaround POWER5 < DD2.1 issue */ + slbmte r7,r0 isync 2: Index: working-2.6/arch/ppc64/mm/hugetlbpage.c =================================================================== --- working-2.6.orig/arch/ppc64/mm/hugetlbpage.c 2005-08-31 11:41:53.000000000 +1000 +++ working-2.6/arch/ppc64/mm/hugetlbpage.c 2005-09-05 11:01:14.000000000 +1000 @@ -144,7 +144,8 @@ for (i = 0; i < NUM_LOW_AREAS; i++) { if (! (areas & (1U << i))) continue; - asm volatile("slbie %0" : : "r" (i << SID_SHIFT)); + asm volatile("slbie %0" + : : "r" ((i << SID_SHIFT) | SLBIE_C)); } asm volatile("isync" : : : "memory"); @@ -164,7 +165,8 @@ continue; for (j = 0; j < (1UL << (HTLB_AREA_SHIFT-SID_SHIFT)); j++) asm volatile("slbie %0" - :: "r" ((i << HTLB_AREA_SHIFT) + (j << SID_SHIFT))); + :: "r" (((i << HTLB_AREA_SHIFT) + + (j << SID_SHIFT)) | SLBIE_C)); } asm volatile("isync" : : : "memory"); Index: working-2.6/arch/ppc64/mm/slb.c =================================================================== --- working-2.6.orig/arch/ppc64/mm/slb.c 2005-06-08 15:46:23.000000000 +1000 +++ working-2.6/arch/ppc64/mm/slb.c 2005-09-05 10:52:47.000000000 +1000 @@ -87,8 +87,8 @@ int i; asm volatile("isync" : : : "memory"); for (i = 0; i < offset; i++) { - esid_data = (unsigned long)get_paca()->slb_cache[i] - << SID_SHIFT; + esid_data = ((unsigned long)get_paca()->slb_cache[i] + << SID_SHIFT) | SLBIE_C; asm volatile("slbie %0" : : "r" (esid_data)); } asm volatile("isync" : : : "memory"); Index: working-2.6/include/asm-ppc64/mmu.h =================================================================== --- working-2.6.orig/include/asm-ppc64/mmu.h 2005-08-31 11:41:57.000000000 +1000 +++ working-2.6/include/asm-ppc64/mmu.h 2005-09-05 11:04:37.000000000 +1000 @@ -54,8 +54,10 @@ #define SLB_VSID_C ASM_CONST(0x0000000000000080) /* class */ #define SLB_VSID_LS ASM_CONST(0x0000000000000070) /* size of largepage */ -#define SLB_VSID_KERNEL (SLB_VSID_KP|SLB_VSID_C) -#define SLB_VSID_USER (SLB_VSID_KP|SLB_VSID_KS) +#define SLB_VSID_KERNEL (SLB_VSID_KP) +#define SLB_VSID_USER (SLB_VSID_KP|SLB_VSID_KS|SLB_VSID_C) + +#define SLBIE_C (0x08000000) /* * Hash table -- David Gibson | I'll have my music baroque, and my code david AT gibson.dropbear.id.au | minimalist, thank you. NOT _the_ _other_ | _way_ _around_! http://www.ozlabs.org/people/dgibson From anton at samba.org Tue Sep 6 14:50:48 2005 From: anton at samba.org (Anton Blanchard) Date: Tue, 6 Sep 2005 14:50:48 +1000 Subject: [PATCH] ppc64: remove CPU_FTR_PMC8 In-Reply-To: <20050906044749.GL6945@krispykreme> References: <20050906044749.GL6945@krispykreme> Message-ID: <20050906045047.GM6945@krispykreme> Remove the CPU_FTR_PMC8 feature now we encode the number of PMCs directly. Signed-off-by: Anton Blanchard Index: build/arch/ppc64/kernel/cputable.c =================================================================== --- build.orig/arch/ppc64/kernel/cputable.c 2005-09-05 20:52:28.000000000 +1000 +++ build/arch/ppc64/kernel/cputable.c 2005-09-05 20:52:41.000000000 +1000 @@ -54,8 +54,7 @@ .pvr_value = 0x00400000, .cpu_name = "POWER3 (630)", .cpu_features = CPU_FTR_SPLIT_ID_CACHE | - CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE | CPU_FTR_IABR | - CPU_FTR_PMC8, + CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE | CPU_FTR_IABR, .cpu_user_features = COMMON_USER_PPC64, .icache_bsize = 128, .dcache_bsize = 128, @@ -67,8 +66,7 @@ .pvr_value = 0x00410000, .cpu_name = "POWER3 (630+)", .cpu_features = CPU_FTR_SPLIT_ID_CACHE | - CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE | CPU_FTR_IABR | - CPU_FTR_PMC8, + CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE | CPU_FTR_IABR, .cpu_user_features = COMMON_USER_PPC64, .icache_bsize = 128, .dcache_bsize = 128, @@ -81,7 +79,7 @@ .cpu_name = "RS64-II (northstar)", .cpu_features = CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE | CPU_FTR_IABR | - CPU_FTR_PMC8 | CPU_FTR_MMCRA | CPU_FTR_CTRL, + CPU_FTR_MMCRA | CPU_FTR_CTRL, .cpu_user_features = COMMON_USER_PPC64, .icache_bsize = 128, .dcache_bsize = 128, @@ -94,7 +92,7 @@ .cpu_name = "RS64-III (pulsar)", .cpu_features = CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE | CPU_FTR_IABR | - CPU_FTR_PMC8 | CPU_FTR_MMCRA | CPU_FTR_CTRL, + CPU_FTR_MMCRA | CPU_FTR_CTRL, .cpu_user_features = COMMON_USER_PPC64, .icache_bsize = 128, .dcache_bsize = 128, @@ -107,7 +105,7 @@ .cpu_name = "RS64-III (icestar)", .cpu_features = CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE | CPU_FTR_IABR | - CPU_FTR_PMC8 | CPU_FTR_MMCRA | CPU_FTR_CTRL, + CPU_FTR_MMCRA | CPU_FTR_CTRL, .cpu_user_features = COMMON_USER_PPC64, .icache_bsize = 128, .dcache_bsize = 128, @@ -120,7 +118,7 @@ .cpu_name = "RS64-IV (sstar)", .cpu_features = CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE | CPU_FTR_IABR | - CPU_FTR_PMC8 | CPU_FTR_MMCRA | CPU_FTR_CTRL, + CPU_FTR_MMCRA | CPU_FTR_CTRL, .cpu_user_features = COMMON_USER_PPC64, .icache_bsize = 128, .dcache_bsize = 128, @@ -133,7 +131,7 @@ .cpu_name = "POWER4 (gp)", .cpu_features = CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE | - CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_PMC8 | CPU_FTR_MMCRA, + CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_MMCRA, .cpu_user_features = COMMON_USER_PPC64, .icache_bsize = 128, .dcache_bsize = 128, @@ -146,7 +144,7 @@ .cpu_name = "POWER4+ (gq)", .cpu_features = CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE | - CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_PMC8 | CPU_FTR_MMCRA, + CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_MMCRA, .cpu_user_features = COMMON_USER_PPC64, .icache_bsize = 128, .dcache_bsize = 128, @@ -160,7 +158,7 @@ .cpu_features = CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE | CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_ALTIVEC_COMP | - CPU_FTR_CAN_NAP | CPU_FTR_PMC8 | CPU_FTR_MMCRA, + CPU_FTR_CAN_NAP | CPU_FTR_MMCRA, .cpu_user_features = COMMON_USER_PPC64 | PPC_FEATURE_HAS_ALTIVEC_COMP, .icache_bsize = 128, @@ -175,7 +173,7 @@ .cpu_features = CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE | CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_ALTIVEC_COMP | - CPU_FTR_CAN_NAP | CPU_FTR_PMC8 | CPU_FTR_MMCRA, + CPU_FTR_CAN_NAP | CPU_FTR_MMCRA, .cpu_user_features = COMMON_USER_PPC64 | PPC_FEATURE_HAS_ALTIVEC_COMP, .icache_bsize = 128, @@ -190,7 +188,7 @@ .cpu_features = CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE | CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_ALTIVEC_COMP | - CPU_FTR_CAN_NAP | CPU_FTR_PMC8 | CPU_FTR_MMCRA, + CPU_FTR_CAN_NAP | CPU_FTR_MMCRA, .cpu_user_features = COMMON_USER_PPC64 | PPC_FEATURE_HAS_ALTIVEC_COMP, .icache_bsize = 128, Index: build/include/asm-ppc64/cputable.h =================================================================== --- build.orig/include/asm-ppc64/cputable.h 2005-09-05 20:52:28.000000000 +1000 +++ build/include/asm-ppc64/cputable.h 2005-09-05 20:52:41.000000000 +1000 @@ -98,7 +98,7 @@ #define CPU_FTR_NODSISRALIGN ASM_CONST(0x0000001000000000) #define CPU_FTR_IABR ASM_CONST(0x0000002000000000) #define CPU_FTR_MMCRA ASM_CONST(0x0000004000000000) -#define CPU_FTR_PMC8 ASM_CONST(0x0000008000000000) +/* unused ASM_CONST(0x0000008000000000) */ #define CPU_FTR_SMT ASM_CONST(0x0000010000000000) #define CPU_FTR_COHERENT_ICACHE ASM_CONST(0x0000020000000000) #define CPU_FTR_LOCKLESS_TLBIE ASM_CONST(0x0000040000000000) From anton at samba.org Tue Sep 6 14:55:35 2005 From: anton at samba.org (Anton Blanchard) Date: Tue, 6 Sep 2005 14:55:35 +1000 Subject: [PATCH] ppc64: Move oprofile_impl.h into include/asm-ppc64 In-Reply-To: <20050906045357.GO6945@krispykreme> References: <20050906044749.GL6945@krispykreme> <20050906045047.GM6945@krispykreme> <20050906045212.GN6945@krispykreme> <20050906045357.GO6945@krispykreme> Message-ID: <20050906045535.GP6945@krispykreme> Move oprofile_impl.h into include/asm-ppc64 in preparation for moving oprofile_model into cpu feature struct. Signed-off-by: Anton Blanchard Index: build/include/asm-ppc64/oprofile_impl.h =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ build/include/asm-ppc64/oprofile_impl.h 2005-09-05 21:13:10.000000000 +1000 @@ -0,0 +1,111 @@ +/* + * Copyright (C) 2004 Anton Blanchard , IBM + * + * Based on alpha version. + * + * 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. + */ + +#ifndef OP_IMPL_H +#define OP_IMPL_H 1 + +#define OP_MAX_COUNTER 8 + +/* Per-counter configuration as set via oprofilefs. */ +struct op_counter_config { + unsigned long valid; + unsigned long enabled; + unsigned long event; + unsigned long count; + unsigned long kernel; + /* We dont support per counter user/kernel selection */ + unsigned long user; + unsigned long unit_mask; +}; + +/* System-wide configuration as set via oprofilefs. */ +struct op_system_config { + unsigned long mmcr0; + unsigned long mmcr1; + unsigned long mmcra; + unsigned long enable_kernel; + unsigned long enable_user; + unsigned long backtrace_spinlocks; +}; + +/* Per-arch configuration */ +struct op_ppc64_model { + void (*reg_setup) (struct op_counter_config *, + struct op_system_config *, + int num_counters); + void (*cpu_setup) (void *); + void (*start) (struct op_counter_config *); + void (*stop) (void); + void (*handle_interrupt) (struct pt_regs *, + struct op_counter_config *); + int num_counters; +}; + +extern struct op_ppc64_model op_model_rs64; +extern struct op_ppc64_model op_model_power4; + +static inline unsigned int ctr_read(unsigned int i) +{ + switch(i) { + case 0: + return mfspr(SPRN_PMC1); + case 1: + return mfspr(SPRN_PMC2); + case 2: + return mfspr(SPRN_PMC3); + case 3: + return mfspr(SPRN_PMC4); + case 4: + return mfspr(SPRN_PMC5); + case 5: + return mfspr(SPRN_PMC6); + case 6: + return mfspr(SPRN_PMC7); + case 7: + return mfspr(SPRN_PMC8); + default: + return 0; + } +} + +static inline void ctr_write(unsigned int i, unsigned int val) +{ + switch(i) { + case 0: + mtspr(SPRN_PMC1, val); + break; + case 1: + mtspr(SPRN_PMC2, val); + break; + case 2: + mtspr(SPRN_PMC3, val); + break; + case 3: + mtspr(SPRN_PMC4, val); + break; + case 4: + mtspr(SPRN_PMC5, val); + break; + case 5: + mtspr(SPRN_PMC6, val); + break; + case 6: + mtspr(SPRN_PMC7, val); + break; + case 7: + mtspr(SPRN_PMC8, val); + break; + default: + break; + } +} + +#endif Index: build/arch/ppc64/oprofile/op_model_rs64.c =================================================================== --- build.orig/arch/ppc64/oprofile/op_model_rs64.c 2005-09-05 21:07:00.000000000 +1000 +++ build/arch/ppc64/oprofile/op_model_rs64.c 2005-09-05 21:13:10.000000000 +1000 @@ -14,11 +14,10 @@ #include #include #include +#include #define dbg(args...) -#include "op_impl.h" - static void ctrl_write(unsigned int i, unsigned int val) { unsigned int tmp = 0; Index: build/arch/ppc64/oprofile/common.c =================================================================== --- build.orig/arch/ppc64/oprofile/common.c 2005-09-05 21:10:43.000000000 +1000 +++ build/arch/ppc64/oprofile/common.c 2005-09-05 21:13:10.000000000 +1000 @@ -17,11 +17,8 @@ #include #include #include +#include -#include "op_impl.h" - -extern struct op_ppc64_model op_model_rs64; -extern struct op_ppc64_model op_model_power4; static struct op_ppc64_model *model; static struct op_counter_config ctr[OP_MAX_COUNTER]; Index: build/arch/ppc64/oprofile/op_model_power4.c =================================================================== --- build.orig/arch/ppc64/oprofile/op_model_power4.c 2005-09-05 21:07:00.000000000 +1000 +++ build/arch/ppc64/oprofile/op_model_power4.c 2005-09-05 21:13:10.000000000 +1000 @@ -16,11 +16,10 @@ #include #include #include +#include #define dbg(args...) -#include "op_impl.h" - static unsigned long reset_value[OP_MAX_COUNTER]; static int oprofile_running; Index: build/arch/ppc64/oprofile/op_impl.h =================================================================== --- build.orig/arch/ppc64/oprofile/op_impl.h 2005-09-05 21:07:00.000000000 +1000 +++ /dev/null 1970-01-01 00:00:00.000000000 +0000 @@ -1,108 +0,0 @@ -/* - * Copyright (C) 2004 Anton Blanchard , IBM - * - * Based on alpha version. - * - * 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. - */ - -#ifndef OP_IMPL_H -#define OP_IMPL_H 1 - -#define OP_MAX_COUNTER 8 - -/* Per-counter configuration as set via oprofilefs. */ -struct op_counter_config { - unsigned long valid; - unsigned long enabled; - unsigned long event; - unsigned long count; - unsigned long kernel; - /* We dont support per counter user/kernel selection */ - unsigned long user; - unsigned long unit_mask; -}; - -/* System-wide configuration as set via oprofilefs. */ -struct op_system_config { - unsigned long mmcr0; - unsigned long mmcr1; - unsigned long mmcra; - unsigned long enable_kernel; - unsigned long enable_user; - unsigned long backtrace_spinlocks; -}; - -/* Per-arch configuration */ -struct op_ppc64_model { - void (*reg_setup) (struct op_counter_config *, - struct op_system_config *, - int num_counters); - void (*cpu_setup) (void *); - void (*start) (struct op_counter_config *); - void (*stop) (void); - void (*handle_interrupt) (struct pt_regs *, - struct op_counter_config *); - int num_counters; -}; - -static inline unsigned int ctr_read(unsigned int i) -{ - switch(i) { - case 0: - return mfspr(SPRN_PMC1); - case 1: - return mfspr(SPRN_PMC2); - case 2: - return mfspr(SPRN_PMC3); - case 3: - return mfspr(SPRN_PMC4); - case 4: - return mfspr(SPRN_PMC5); - case 5: - return mfspr(SPRN_PMC6); - case 6: - return mfspr(SPRN_PMC7); - case 7: - return mfspr(SPRN_PMC8); - default: - return 0; - } -} - -static inline void ctr_write(unsigned int i, unsigned int val) -{ - switch(i) { - case 0: - mtspr(SPRN_PMC1, val); - break; - case 1: - mtspr(SPRN_PMC2, val); - break; - case 2: - mtspr(SPRN_PMC3, val); - break; - case 3: - mtspr(SPRN_PMC4, val); - break; - case 4: - mtspr(SPRN_PMC5, val); - break; - case 5: - mtspr(SPRN_PMC6, val); - break; - case 6: - mtspr(SPRN_PMC7, val); - break; - case 7: - mtspr(SPRN_PMC8, val); - break; - default: - break; - } -} - -#endif From anton at samba.org Tue Sep 6 14:53:57 2005 From: anton at samba.org (Anton Blanchard) Date: Tue, 6 Sep 2005 14:53:57 +1000 Subject: [PATCH] ppc64: Add oprofile cpu_type to cpu feature struct In-Reply-To: <20050906045212.GN6945@krispykreme> References: <20050906044749.GL6945@krispykreme> <20050906045047.GM6945@krispykreme> <20050906045212.GN6945@krispykreme> Message-ID: <20050906045357.GO6945@krispykreme> Add oprofile cpu_type to cpu feature struct. Signed-off-by: Anton Blanchard Index: build/arch/ppc64/kernel/cputable.c =================================================================== --- build.orig/arch/ppc64/kernel/cputable.c 2005-09-05 21:10:26.000000000 +1000 +++ build/arch/ppc64/kernel/cputable.c 2005-09-05 21:10:43.000000000 +1000 @@ -60,6 +60,7 @@ .dcache_bsize = 128, .num_pmcs = 8, .cpu_setup = __setup_cpu_power3, + .oprofile_cpu_type = "ppc64/power3", }, { /* Power3+ */ .pvr_mask = 0xffff0000, @@ -72,6 +73,7 @@ .dcache_bsize = 128, .num_pmcs = 8, .cpu_setup = __setup_cpu_power3, + .oprofile_cpu_type = "ppc64/power3", }, { /* Northstar */ .pvr_mask = 0xffff0000, @@ -85,6 +87,7 @@ .dcache_bsize = 128, .num_pmcs = 8, .cpu_setup = __setup_cpu_power3, + .oprofile_cpu_type = "ppc64/rs64", }, { /* Pulsar */ .pvr_mask = 0xffff0000, @@ -98,6 +101,7 @@ .dcache_bsize = 128, .num_pmcs = 8, .cpu_setup = __setup_cpu_power3, + .oprofile_cpu_type = "ppc64/rs64", }, { /* I-star */ .pvr_mask = 0xffff0000, @@ -111,6 +115,7 @@ .dcache_bsize = 128, .num_pmcs = 8, .cpu_setup = __setup_cpu_power3, + .oprofile_cpu_type = "ppc64/rs64", }, { /* S-star */ .pvr_mask = 0xffff0000, @@ -124,6 +129,7 @@ .dcache_bsize = 128, .num_pmcs = 8, .cpu_setup = __setup_cpu_power3, + .oprofile_cpu_type = "ppc64/rs64", }, { /* Power4 */ .pvr_mask = 0xffff0000, @@ -137,6 +143,7 @@ .dcache_bsize = 128, .num_pmcs = 8, .cpu_setup = __setup_cpu_power4, + .oprofile_cpu_type = "ppc64/power4", }, { /* Power4+ */ .pvr_mask = 0xffff0000, @@ -150,6 +157,7 @@ .dcache_bsize = 128, .num_pmcs = 8, .cpu_setup = __setup_cpu_power4, + .oprofile_cpu_type = "ppc64/power4", }, { /* PPC970 */ .pvr_mask = 0xffff0000, @@ -165,6 +173,7 @@ .dcache_bsize = 128, .num_pmcs = 8, .cpu_setup = __setup_cpu_ppc970, + .oprofile_cpu_type = "ppc64/970", }, { /* PPC970FX */ .pvr_mask = 0xffff0000, @@ -180,6 +189,7 @@ .dcache_bsize = 128, .num_pmcs = 8, .cpu_setup = __setup_cpu_ppc970, + .oprofile_cpu_type = "ppc64/970", }, { /* PPC970MP */ .pvr_mask = 0xffff0000, @@ -194,6 +204,7 @@ .icache_bsize = 128, .dcache_bsize = 128, .cpu_setup = __setup_cpu_ppc970, + .oprofile_cpu_type = "ppc64/970", }, { /* Power5 */ .pvr_mask = 0xffff0000, @@ -209,6 +220,7 @@ .dcache_bsize = 128, .num_pmcs = 6, .cpu_setup = __setup_cpu_power4, + .oprofile_cpu_type = "ppc64/power5", }, { /* Power5 */ .pvr_mask = 0xffff0000, @@ -224,6 +236,7 @@ .dcache_bsize = 128, .num_pmcs = 6, .cpu_setup = __setup_cpu_power4, + .oprofile_cpu_type = "ppc64/power5", }, { /* BE DD1.x */ .pvr_mask = 0xffff0000, Index: build/arch/ppc64/oprofile/common.c =================================================================== --- build.orig/arch/ppc64/oprofile/common.c 2005-09-05 21:10:26.000000000 +1000 +++ build/arch/ppc64/oprofile/common.c 2005-09-05 21:10:43.000000000 +1000 @@ -132,7 +132,6 @@ case PV_630: case PV_630p: model = &op_model_rs64; - ops->cpu_type = "ppc64/power3"; break; case PV_NORTHSTAR: @@ -140,32 +139,29 @@ case PV_ICESTAR: case PV_SSTAR: model = &op_model_rs64; - ops->cpu_type = "ppc64/rs64"; break; case PV_POWER4: case PV_POWER4p: model = &op_model_power4; - ops->cpu_type = "ppc64/power4"; break; case PV_970: case PV_970FX: case PV_970MP: model = &op_model_power4; - ops->cpu_type = "ppc64/970"; break; case PV_POWER5: case PV_POWER5p: model = &op_model_power4; - ops->cpu_type = "ppc64/power5"; break; default: return -ENODEV; } + ops->cpu_type = cur_cpu_spec->oprofile_cpu_type; model->num_counters = cur_cpu_spec->num_pmcs; ops->create_files = op_ppc64_create_files; ops->setup = op_ppc64_setup; Index: build/include/asm-ppc64/cputable.h =================================================================== --- build.orig/include/asm-ppc64/cputable.h 2005-09-05 21:10:39.000000000 +1000 +++ build/include/asm-ppc64/cputable.h 2005-09-05 21:10:53.000000000 +1000 @@ -59,6 +59,9 @@ * BHT, SPD, etc... from head.S before branching to identify_machine */ cpu_setup_t cpu_setup; + + /* Used by oprofile userspace to select the right counters */ + char *oprofile_cpu_type; }; extern struct cpu_spec cpu_specs[]; From anton at samba.org Tue Sep 6 14:57:52 2005 From: anton at samba.org (Anton Blanchard) Date: Tue, 6 Sep 2005 14:57:52 +1000 Subject: [PATCH] ppc64: Move oprofile_model into cpu feature struct In-Reply-To: <20050906045535.GP6945@krispykreme> References: <20050906044749.GL6945@krispykreme> <20050906045047.GM6945@krispykreme> <20050906045212.GN6945@krispykreme> <20050906045357.GO6945@krispykreme> <20050906045535.GP6945@krispykreme> Message-ID: <20050906045752.GQ6945@krispykreme> Move oprofile_model into cpu feature struct. Signed-off-by: Anton Blanchard Index: build/arch/ppc64/kernel/cputable.c =================================================================== --- build.orig/arch/ppc64/kernel/cputable.c 2005-09-05 21:10:43.000000000 +1000 +++ build/arch/ppc64/kernel/cputable.c 2005-09-05 21:22:32.000000000 +1000 @@ -19,6 +19,7 @@ #include #include +#include #include struct cpu_spec* cur_cpu_spec = NULL; @@ -61,6 +62,7 @@ .num_pmcs = 8, .cpu_setup = __setup_cpu_power3, .oprofile_cpu_type = "ppc64/power3", + .oprofile_model = &op_model_rs64, }, { /* Power3+ */ .pvr_mask = 0xffff0000, @@ -74,6 +76,7 @@ .num_pmcs = 8, .cpu_setup = __setup_cpu_power3, .oprofile_cpu_type = "ppc64/power3", + .oprofile_model = &op_model_rs64, }, { /* Northstar */ .pvr_mask = 0xffff0000, @@ -88,6 +91,7 @@ .num_pmcs = 8, .cpu_setup = __setup_cpu_power3, .oprofile_cpu_type = "ppc64/rs64", + .oprofile_model = &op_model_rs64, }, { /* Pulsar */ .pvr_mask = 0xffff0000, @@ -102,6 +106,7 @@ .num_pmcs = 8, .cpu_setup = __setup_cpu_power3, .oprofile_cpu_type = "ppc64/rs64", + .oprofile_model = &op_model_rs64, }, { /* I-star */ .pvr_mask = 0xffff0000, @@ -116,6 +121,7 @@ .num_pmcs = 8, .cpu_setup = __setup_cpu_power3, .oprofile_cpu_type = "ppc64/rs64", + .oprofile_model = &op_model_rs64, }, { /* S-star */ .pvr_mask = 0xffff0000, @@ -130,6 +136,7 @@ .num_pmcs = 8, .cpu_setup = __setup_cpu_power3, .oprofile_cpu_type = "ppc64/rs64", + .oprofile_model = &op_model_rs64, }, { /* Power4 */ .pvr_mask = 0xffff0000, @@ -144,6 +151,7 @@ .num_pmcs = 8, .cpu_setup = __setup_cpu_power4, .oprofile_cpu_type = "ppc64/power4", + .oprofile_model = &op_model_rs64, }, { /* Power4+ */ .pvr_mask = 0xffff0000, @@ -158,6 +166,7 @@ .num_pmcs = 8, .cpu_setup = __setup_cpu_power4, .oprofile_cpu_type = "ppc64/power4", + .oprofile_model = &op_model_power4, }, { /* PPC970 */ .pvr_mask = 0xffff0000, @@ -174,6 +183,7 @@ .num_pmcs = 8, .cpu_setup = __setup_cpu_ppc970, .oprofile_cpu_type = "ppc64/970", + .oprofile_model = &op_model_power4, }, { /* PPC970FX */ .pvr_mask = 0xffff0000, @@ -190,6 +200,7 @@ .num_pmcs = 8, .cpu_setup = __setup_cpu_ppc970, .oprofile_cpu_type = "ppc64/970", + .oprofile_model = &op_model_power4, }, { /* PPC970MP */ .pvr_mask = 0xffff0000, @@ -205,6 +216,7 @@ .dcache_bsize = 128, .cpu_setup = __setup_cpu_ppc970, .oprofile_cpu_type = "ppc64/970", + .oprofile_model = &op_model_power4, }, { /* Power5 */ .pvr_mask = 0xffff0000, @@ -221,6 +233,7 @@ .num_pmcs = 6, .cpu_setup = __setup_cpu_power4, .oprofile_cpu_type = "ppc64/power5", + .oprofile_model = &op_model_power4, }, { /* Power5 */ .pvr_mask = 0xffff0000, @@ -237,6 +250,7 @@ .num_pmcs = 6, .cpu_setup = __setup_cpu_power4, .oprofile_cpu_type = "ppc64/power5", + .oprofile_model = &op_model_power4, }, { /* BE DD1.x */ .pvr_mask = 0xffff0000, Index: build/arch/ppc64/oprofile/common.c =================================================================== --- build.orig/arch/ppc64/oprofile/common.c 2005-09-05 21:13:10.000000000 +1000 +++ build/arch/ppc64/oprofile/common.c 2005-09-05 21:15:14.000000000 +1000 @@ -121,45 +121,13 @@ int __init oprofile_arch_init(struct oprofile_operations *ops) { - unsigned int pvr; + if (!cur_cpu_spec->oprofile_model || !cur_cpu_spec->oprofile_cpu_type) + return -ENODEV; - pvr = mfspr(SPRN_PVR); - - switch (PVR_VER(pvr)) { - case PV_630: - case PV_630p: - model = &op_model_rs64; - break; - - case PV_NORTHSTAR: - case PV_PULSAR: - case PV_ICESTAR: - case PV_SSTAR: - model = &op_model_rs64; - break; - - case PV_POWER4: - case PV_POWER4p: - model = &op_model_power4; - break; - - case PV_970: - case PV_970FX: - case PV_970MP: - model = &op_model_power4; - break; - - case PV_POWER5: - case PV_POWER5p: - model = &op_model_power4; - break; - - default: - return -ENODEV; - } + model = cur_cpu_spec->oprofile_model; + model->num_counters = cur_cpu_spec->num_pmcs; ops->cpu_type = cur_cpu_spec->oprofile_cpu_type; - model->num_counters = cur_cpu_spec->num_pmcs; ops->create_files = op_ppc64_create_files; ops->setup = op_ppc64_setup; ops->shutdown = op_ppc64_shutdown; Index: build/include/asm-ppc64/cputable.h =================================================================== --- build.orig/include/asm-ppc64/cputable.h 2005-09-05 21:10:53.000000000 +1000 +++ build/include/asm-ppc64/cputable.h 2005-09-05 21:13:51.000000000 +1000 @@ -36,6 +36,7 @@ * via the mkdefs mechanism. */ struct cpu_spec; +struct op_ppc64_model; typedef void (*cpu_setup_t)(unsigned long offset, struct cpu_spec* spec); @@ -62,6 +63,9 @@ /* Used by oprofile userspace to select the right counters */ char *oprofile_cpu_type; + + /* Processor specific oprofile operations */ + struct op_ppc64_model *oprofile_model; }; extern struct cpu_spec cpu_specs[]; From anton at samba.org Tue Sep 6 14:47:49 2005 From: anton at samba.org (Anton Blanchard) Date: Tue, 6 Sep 2005 14:47:49 +1000 Subject: [PATCH] ppc64: add number of PMCs to cputable Message-ID: <20050906044749.GL6945@krispykreme> Add a field in the cputable struct to store the number of PMCs. Signed-off-by: Anton Blanchard Index: build/arch/ppc64/kernel/cputable.c =================================================================== --- build.orig/arch/ppc64/kernel/cputable.c 2005-09-05 16:11:18.000000000 +1000 +++ build/arch/ppc64/kernel/cputable.c 2005-09-05 20:52:28.000000000 +1000 @@ -59,6 +59,7 @@ .cpu_user_features = COMMON_USER_PPC64, .icache_bsize = 128, .dcache_bsize = 128, + .num_pmcs = 8, .cpu_setup = __setup_cpu_power3, }, { /* Power3+ */ @@ -71,6 +72,7 @@ .cpu_user_features = COMMON_USER_PPC64, .icache_bsize = 128, .dcache_bsize = 128, + .num_pmcs = 8, .cpu_setup = __setup_cpu_power3, }, { /* Northstar */ @@ -83,6 +85,7 @@ .cpu_user_features = COMMON_USER_PPC64, .icache_bsize = 128, .dcache_bsize = 128, + .num_pmcs = 8, .cpu_setup = __setup_cpu_power3, }, { /* Pulsar */ @@ -95,6 +98,7 @@ .cpu_user_features = COMMON_USER_PPC64, .icache_bsize = 128, .dcache_bsize = 128, + .num_pmcs = 8, .cpu_setup = __setup_cpu_power3, }, { /* I-star */ @@ -107,6 +111,7 @@ .cpu_user_features = COMMON_USER_PPC64, .icache_bsize = 128, .dcache_bsize = 128, + .num_pmcs = 8, .cpu_setup = __setup_cpu_power3, }, { /* S-star */ @@ -119,6 +124,7 @@ .cpu_user_features = COMMON_USER_PPC64, .icache_bsize = 128, .dcache_bsize = 128, + .num_pmcs = 8, .cpu_setup = __setup_cpu_power3, }, { /* Power4 */ @@ -131,6 +137,7 @@ .cpu_user_features = COMMON_USER_PPC64, .icache_bsize = 128, .dcache_bsize = 128, + .num_pmcs = 8, .cpu_setup = __setup_cpu_power4, }, { /* Power4+ */ @@ -143,6 +150,7 @@ .cpu_user_features = COMMON_USER_PPC64, .icache_bsize = 128, .dcache_bsize = 128, + .num_pmcs = 8, .cpu_setup = __setup_cpu_power4, }, { /* PPC970 */ @@ -157,6 +165,7 @@ PPC_FEATURE_HAS_ALTIVEC_COMP, .icache_bsize = 128, .dcache_bsize = 128, + .num_pmcs = 8, .cpu_setup = __setup_cpu_ppc970, }, { /* PPC970FX */ @@ -171,6 +180,7 @@ PPC_FEATURE_HAS_ALTIVEC_COMP, .icache_bsize = 128, .dcache_bsize = 128, + .num_pmcs = 8, .cpu_setup = __setup_cpu_ppc970, }, { /* PPC970MP */ @@ -199,6 +209,7 @@ .cpu_user_features = COMMON_USER_PPC64, .icache_bsize = 128, .dcache_bsize = 128, + .num_pmcs = 6, .cpu_setup = __setup_cpu_power4, }, { /* Power5 */ @@ -213,6 +224,7 @@ .cpu_user_features = COMMON_USER_PPC64, .icache_bsize = 128, .dcache_bsize = 128, + .num_pmcs = 6, .cpu_setup = __setup_cpu_power4, }, { /* BE DD1.x */ @@ -239,6 +251,7 @@ .cpu_user_features = COMMON_USER_PPC64, .icache_bsize = 128, .dcache_bsize = 128, + .num_pmcs = 6, .cpu_setup = __setup_cpu_power4, } }; Index: build/arch/ppc64/kernel/sysfs.c =================================================================== --- build.orig/arch/ppc64/kernel/sysfs.c 2005-09-05 16:11:18.000000000 +1000 +++ build/arch/ppc64/kernel/sysfs.c 2005-09-05 20:52:28.000000000 +1000 @@ -215,18 +215,23 @@ if (cpu_has_feature(CPU_FTR_MMCRA)) sysdev_create_file(s, &attr_mmcra); - sysdev_create_file(s, &attr_pmc1); - sysdev_create_file(s, &attr_pmc2); - sysdev_create_file(s, &attr_pmc3); - sysdev_create_file(s, &attr_pmc4); - sysdev_create_file(s, &attr_pmc5); - sysdev_create_file(s, &attr_pmc6); - - if (cpu_has_feature(CPU_FTR_PMC8)) { + if (cur_cpu_spec->num_pmcs >= 1) + sysdev_create_file(s, &attr_pmc1); + if (cur_cpu_spec->num_pmcs >= 2) + sysdev_create_file(s, &attr_pmc2); + if (cur_cpu_spec->num_pmcs >= 3) + sysdev_create_file(s, &attr_pmc3); + if (cur_cpu_spec->num_pmcs >= 4) + sysdev_create_file(s, &attr_pmc4); + if (cur_cpu_spec->num_pmcs >= 5) + sysdev_create_file(s, &attr_pmc5); + if (cur_cpu_spec->num_pmcs >= 6) + sysdev_create_file(s, &attr_pmc6); + if (cur_cpu_spec->num_pmcs >= 7) sysdev_create_file(s, &attr_pmc7); + if (cur_cpu_spec->num_pmcs >= 8) sysdev_create_file(s, &attr_pmc8); - } - + if (cpu_has_feature(CPU_FTR_SMT)) sysdev_create_file(s, &attr_purr); } @@ -252,17 +257,22 @@ if (cpu_has_feature(CPU_FTR_MMCRA)) sysdev_remove_file(s, &attr_mmcra); - sysdev_remove_file(s, &attr_pmc1); - sysdev_remove_file(s, &attr_pmc2); - sysdev_remove_file(s, &attr_pmc3); - sysdev_remove_file(s, &attr_pmc4); - sysdev_remove_file(s, &attr_pmc5); - sysdev_remove_file(s, &attr_pmc6); - - if (cpu_has_feature(CPU_FTR_PMC8)) { + if (cur_cpu_spec->num_pmcs >= 1) + sysdev_remove_file(s, &attr_pmc1); + if (cur_cpu_spec->num_pmcs >= 2) + sysdev_remove_file(s, &attr_pmc2); + if (cur_cpu_spec->num_pmcs >= 3) + sysdev_remove_file(s, &attr_pmc3); + if (cur_cpu_spec->num_pmcs >= 4) + sysdev_remove_file(s, &attr_pmc4); + if (cur_cpu_spec->num_pmcs >= 5) + sysdev_remove_file(s, &attr_pmc5); + if (cur_cpu_spec->num_pmcs >= 6) + sysdev_remove_file(s, &attr_pmc6); + if (cur_cpu_spec->num_pmcs >= 7) sysdev_remove_file(s, &attr_pmc7); + if (cur_cpu_spec->num_pmcs >= 8) sysdev_remove_file(s, &attr_pmc8); - } if (cpu_has_feature(CPU_FTR_SMT)) sysdev_remove_file(s, &attr_purr); Index: build/include/asm-ppc64/cputable.h =================================================================== --- build.orig/include/asm-ppc64/cputable.h 2005-09-05 16:11:21.000000000 +1000 +++ build/include/asm-ppc64/cputable.h 2005-09-05 20:52:28.000000000 +1000 @@ -52,6 +52,9 @@ unsigned int icache_bsize; unsigned int dcache_bsize; + /* number of performance monitor counters */ + unsigned int num_pmcs; + /* this is called to initialize various CPU bits like L1 cache, * BHT, SPD, etc... from head.S before branching to identify_machine */ From anton at samba.org Tue Sep 6 14:52:12 2005 From: anton at samba.org (Anton Blanchard) Date: Tue, 6 Sep 2005 14:52:12 +1000 Subject: [PATCH] ppc64: Use num_pmcs in oprofile code In-Reply-To: <20050906045047.GM6945@krispykreme> References: <20050906044749.GL6945@krispykreme> <20050906045047.GM6945@krispykreme> Message-ID: <20050906045212.GN6945@krispykreme> Change oprofile to use num_pmcs from the cpu feature struct. Signed-off-by: Anton Blanchard Index: build/arch/ppc64/oprofile/common.c =================================================================== --- build.orig/arch/ppc64/oprofile/common.c 2005-09-05 16:11:18.000000000 +1000 +++ build/arch/ppc64/oprofile/common.c 2005-09-05 20:54:34.000000000 +1000 @@ -16,6 +16,7 @@ #include #include #include +#include #include "op_impl.h" @@ -131,7 +132,6 @@ case PV_630: case PV_630p: model = &op_model_rs64; - model->num_counters = 8; ops->cpu_type = "ppc64/power3"; break; @@ -140,14 +140,12 @@ case PV_ICESTAR: case PV_SSTAR: model = &op_model_rs64; - model->num_counters = 8; ops->cpu_type = "ppc64/rs64"; break; case PV_POWER4: case PV_POWER4p: model = &op_model_power4; - model->num_counters = 8; ops->cpu_type = "ppc64/power4"; break; @@ -155,14 +153,12 @@ case PV_970FX: case PV_970MP: model = &op_model_power4; - model->num_counters = 8; ops->cpu_type = "ppc64/970"; break; case PV_POWER5: case PV_POWER5p: model = &op_model_power4; - model->num_counters = 6; ops->cpu_type = "ppc64/power5"; break; @@ -170,6 +166,7 @@ return -ENODEV; } + model->num_counters = cur_cpu_spec->num_pmcs; ops->create_files = op_ppc64_create_files; ops->setup = op_ppc64_setup; ops->shutdown = op_ppc64_shutdown; Index: build/arch/ppc64/oprofile/op_model_power4.c =================================================================== --- build.orig/arch/ppc64/oprofile/op_model_power4.c 2005-09-05 16:11:18.000000000 +1000 +++ build/arch/ppc64/oprofile/op_model_power4.c 2005-09-05 20:53:01.000000000 +1000 @@ -23,7 +23,6 @@ static unsigned long reset_value[OP_MAX_COUNTER]; -static int num_counters; static int oprofile_running; static int mmcra_has_sihv; @@ -45,8 +44,6 @@ { int i; - num_counters = num_ctrs; - /* * SIHV / SIPR bits are only implemented on POWER4+ (GQ) and above. * However we disable it on all POWER4 until we verify it works @@ -68,7 +65,7 @@ backtrace_spinlocks = sys->backtrace_spinlocks; - for (i = 0; i < num_counters; ++i) + for (i = 0; i < cur_cpu_spec->num_pmcs; ++i) reset_value[i] = 0x80000000UL - ctr[i].count; /* setup user and kernel profiling */ @@ -121,7 +118,7 @@ /* set the PMM bit (see comment below) */ mtmsrd(mfmsr() | MSR_PMM); - for (i = 0; i < num_counters; ++i) { + for (i = 0; i < cur_cpu_spec->num_pmcs; ++i) { if (ctr[i].enabled) { ctr_write(i, reset_value[i]); } else { @@ -272,7 +269,7 @@ /* set the PMM bit (see comment below) */ mtmsrd(mfmsr() | MSR_PMM); - for (i = 0; i < num_counters; ++i) { + for (i = 0; i < cur_cpu_spec->num_pmcs; ++i) { val = ctr_read(i); if (val < 0) { if (oprofile_running && ctr[i].enabled) { From anton at samba.org Tue Sep 6 14:59:16 2005 From: anton at samba.org (Anton Blanchard) Date: Tue, 6 Sep 2005 14:59:16 +1000 Subject: [PATCH] ppc64: Fix build with oprofile disabled In-Reply-To: <20050906045752.GQ6945@krispykreme> References: <20050906044749.GL6945@krispykreme> <20050906045047.GM6945@krispykreme> <20050906045212.GN6945@krispykreme> <20050906045357.GO6945@krispykreme> <20050906045535.GP6945@krispykreme> <20050906045752.GQ6945@krispykreme> Message-ID: <20050906045916.GR6945@krispykreme> Fix build with oprofile disabled. Signed-off-by: Anton Blanchard Index: build/arch/ppc64/kernel/cputable.c =================================================================== --- build.orig/arch/ppc64/kernel/cputable.c 2005-09-05 21:22:32.000000000 +1000 +++ build/arch/ppc64/kernel/cputable.c 2005-09-05 21:22:58.000000000 +1000 @@ -61,8 +61,10 @@ .dcache_bsize = 128, .num_pmcs = 8, .cpu_setup = __setup_cpu_power3, +#ifdef CONFIG_OPROFILE .oprofile_cpu_type = "ppc64/power3", .oprofile_model = &op_model_rs64, +#endif }, { /* Power3+ */ .pvr_mask = 0xffff0000, @@ -75,8 +77,10 @@ .dcache_bsize = 128, .num_pmcs = 8, .cpu_setup = __setup_cpu_power3, +#ifdef CONFIG_OPROFILE .oprofile_cpu_type = "ppc64/power3", .oprofile_model = &op_model_rs64, +#endif }, { /* Northstar */ .pvr_mask = 0xffff0000, @@ -90,8 +94,10 @@ .dcache_bsize = 128, .num_pmcs = 8, .cpu_setup = __setup_cpu_power3, +#ifdef CONFIG_OPROFILE .oprofile_cpu_type = "ppc64/rs64", .oprofile_model = &op_model_rs64, +#endif }, { /* Pulsar */ .pvr_mask = 0xffff0000, @@ -105,8 +111,10 @@ .dcache_bsize = 128, .num_pmcs = 8, .cpu_setup = __setup_cpu_power3, +#ifdef CONFIG_OPROFILE .oprofile_cpu_type = "ppc64/rs64", .oprofile_model = &op_model_rs64, +#endif }, { /* I-star */ .pvr_mask = 0xffff0000, @@ -120,8 +128,10 @@ .dcache_bsize = 128, .num_pmcs = 8, .cpu_setup = __setup_cpu_power3, +#ifdef CONFIG_OPROFILE .oprofile_cpu_type = "ppc64/rs64", .oprofile_model = &op_model_rs64, +#endif }, { /* S-star */ .pvr_mask = 0xffff0000, @@ -135,8 +145,10 @@ .dcache_bsize = 128, .num_pmcs = 8, .cpu_setup = __setup_cpu_power3, +#ifdef CONFIG_OPROFILE .oprofile_cpu_type = "ppc64/rs64", .oprofile_model = &op_model_rs64, +#endif }, { /* Power4 */ .pvr_mask = 0xffff0000, @@ -150,8 +162,10 @@ .dcache_bsize = 128, .num_pmcs = 8, .cpu_setup = __setup_cpu_power4, +#ifdef CONFIG_OPROFILE .oprofile_cpu_type = "ppc64/power4", .oprofile_model = &op_model_rs64, +#endif }, { /* Power4+ */ .pvr_mask = 0xffff0000, @@ -165,8 +179,10 @@ .dcache_bsize = 128, .num_pmcs = 8, .cpu_setup = __setup_cpu_power4, +#ifdef CONFIG_OPROFILE .oprofile_cpu_type = "ppc64/power4", .oprofile_model = &op_model_power4, +#endif }, { /* PPC970 */ .pvr_mask = 0xffff0000, @@ -182,8 +198,10 @@ .dcache_bsize = 128, .num_pmcs = 8, .cpu_setup = __setup_cpu_ppc970, +#ifdef CONFIG_OPROFILE .oprofile_cpu_type = "ppc64/970", .oprofile_model = &op_model_power4, +#endif }, { /* PPC970FX */ .pvr_mask = 0xffff0000, @@ -199,8 +217,10 @@ .dcache_bsize = 128, .num_pmcs = 8, .cpu_setup = __setup_cpu_ppc970, +#ifdef CONFIG_OPROFILE .oprofile_cpu_type = "ppc64/970", .oprofile_model = &op_model_power4, +#endif }, { /* PPC970MP */ .pvr_mask = 0xffff0000, @@ -215,8 +235,10 @@ .icache_bsize = 128, .dcache_bsize = 128, .cpu_setup = __setup_cpu_ppc970, +#ifdef CONFIG_OPROFILE .oprofile_cpu_type = "ppc64/970", .oprofile_model = &op_model_power4, +#endif }, { /* Power5 */ .pvr_mask = 0xffff0000, @@ -232,8 +254,10 @@ .dcache_bsize = 128, .num_pmcs = 6, .cpu_setup = __setup_cpu_power4, +#ifdef CONFIG_OPROFILE .oprofile_cpu_type = "ppc64/power5", .oprofile_model = &op_model_power4, +#endif }, { /* Power5 */ .pvr_mask = 0xffff0000, @@ -249,8 +273,10 @@ .dcache_bsize = 128, .num_pmcs = 6, .cpu_setup = __setup_cpu_power4, +#ifdef CONFIG_OPROFILE .oprofile_cpu_type = "ppc64/power5", .oprofile_model = &op_model_power4, +#endif }, { /* BE DD1.x */ .pvr_mask = 0xffff0000, From ntl at pobox.com Tue Sep 6 15:04:18 2005 From: ntl at pobox.com (Nathan Lynch) Date: Tue, 6 Sep 2005 00:04:18 -0500 Subject: [RFC] patch to allow world readable /proc/ppc64/lparcfg In-Reply-To: <20050906032247.GA313@ca-server1.us.oracle.com> References: <20050906032247.GA313@ca-server1.us.oracle.com> Message-ID: <20050906050418.GB3560@otto> Wim Coekaerts wrote: > like to be able to read the lparcfg data from any user so we can make > "intelligent" decisions based on underlying attributes when running in > lpars. yes there's software that likes to do this :) and runs as > non-root. I'm not sure if anyone has any issues with this but I'd say it > would be pretty harmless. Can you tell us more about which information in lparcfg is useful to you? Some of the fields in lparcfg duplicate information that is already available in /proc/device-tree. Furthermore, we could have lparcfg display a useful subset of its info to non-root users. > it's very similar to say VM where you can get CP to provide feedback of > the real hardware inside a VM guest Case in point, the machine's model number etc are in the device tree. From wim.coekaerts at oracle.com Tue Sep 6 15:09:47 2005 From: wim.coekaerts at oracle.com (Wim Coekaerts) Date: Mon, 5 Sep 2005 22:09:47 -0700 Subject: [RFC] patch to allow world readable /proc/ppc64/lparcfg In-Reply-To: <20050906050418.GB3560@otto> References: <20050906032247.GA313@ca-server1.us.oracle.com> <20050906050418.GB3560@otto> Message-ID: <20050906050942.GB313@ca-server1.us.oracle.com> well, basically the info around cpu's how many physical, how many allocated, how much allocated for the lpar. if we want to run jobs in parallel where we really want to limit the degree to max #phys cpu / real cpu time On Tue, Sep 06, 2005 at 12:04:18AM -0500, Nathan Lynch wrote: > Wim Coekaerts wrote: > > like to be able to read the lparcfg data from any user so we can make > > "intelligent" decisions based on underlying attributes when running in > > lpars. yes there's software that likes to do this :) and runs as > > non-root. I'm not sure if anyone has any issues with this but I'd say it > > would be pretty harmless. > > Can you tell us more about which information in lparcfg is useful to > you? Some of the fields in lparcfg duplicate information that is > already available in /proc/device-tree. Furthermore, we could > have lparcfg display a useful subset of its info to non-root users. > > > it's very similar to say VM where you can get CP to provide feedback of > > the real hardware inside a VM guest > > Case in point, the machine's model number etc are in the device tree. > From benh at kernel.crashing.org Tue Sep 6 15:32:50 2005 From: benh at kernel.crashing.org (Benjamin Herrenschmidt) Date: Tue, 06 Sep 2005 15:32:50 +1000 Subject: [PATCH] ppc64: iommu cleanup 1/2 Message-ID: <1125984770.1333.3.camel@gaston> This is Olof's patch rebased. I'll need it for the 64k pages work so let's get it in now. Split out the implementation-specific parts of include/asm-ppc64/iommu.h to separate include files (tce.h and dart.h respectively). The generic iommu code really doesn't care about the underlying implementation, and the TCE and DART stuff is completely different. Signed-off-by: Olof Johansson Signed-off-by: Benjamin Herrenschmidt Index: linux-work/include/asm-ppc64/dart.h =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ linux-work/include/asm-ppc64/dart.h 2005-09-05 14:57:26.000000000 +1000 @@ -0,0 +1,55 @@ +/* + * Copyright (C) 2004 Olof Johansson , IBM Corporation + * + * 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_DART_H +#define _ASM_DART_H + + +/* physical base of DART registers */ +#define DART_BASE 0xf8033000UL + +/* Offset from base to control register */ +#define DARTCNTL 0 +/* Offset from base to exception register */ +#define DARTEXCP 0x10 +/* Offset from base to TLB tag registers */ +#define DARTTAG 0x1000 + + +/* Control Register fields */ + +/* base address of table (pfn) */ +#define DARTCNTL_BASE_MASK 0xfffff +#define DARTCNTL_BASE_SHIFT 12 + +#define DARTCNTL_FLUSHTLB 0x400 +#define DARTCNTL_ENABLE 0x200 + +/* size of table in pages */ +#define DARTCNTL_SIZE_MASK 0x1ff +#define DARTCNTL_SIZE_SHIFT 0 + + +/* DART table fields */ + +#define DARTMAP_VALID 0x80000000 +#define DARTMAP_RPNMASK 0x00ffffff + + + +#endif Index: linux-work/include/asm-ppc64/iommu.h =================================================================== --- linux-work.orig/include/asm-ppc64/iommu.h 2005-08-30 11:18:13.000000000 +1000 +++ linux-work/include/asm-ppc64/iommu.h 2005-09-05 14:33:08.000000000 +1000 @@ -1,5 +1,4 @@ /* - * iommu.h * Copyright (C) 2001 Mike Corrigan & Dave Engebretsen, IBM Corporation * Rewrite, cleanup: * Copyright (C) 2004 Olof Johansson , IBM Corporation @@ -29,44 +28,11 @@ /* * IOMAP_MAX_ORDER defines the largest contiguous block - * of dma (tce) space we can get. IOMAP_MAX_ORDER = 13 + * of dma space we can get. IOMAP_MAX_ORDER = 13 * allows up to 2**12 pages (4096 * 4096) = 16 MB */ #define IOMAP_MAX_ORDER 13 -/* - * Tces come in two formats, one for the virtual bus and a different - * format for PCI - */ -#define TCE_VB 0 -#define TCE_PCI 1 - -/* 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 -}; - - struct iommu_table { unsigned long it_busno; /* Bus number this table belongs to */ unsigned long it_size; /* Size of iommu table in entries */ Index: linux-work/include/asm-ppc64/tce.h =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ linux-work/include/asm-ppc64/tce.h 2005-09-05 14:57:26.000000000 +1000 @@ -0,0 +1,57 @@ +/* + * Copyright (C) 2001 Mike Corrigan & Dave Engebretsen, IBM Corporation + * Rewrite, cleanup: + * Copyright (C) 2004 Olof Johansson , IBM Corporation + * + * 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_TCE_H +#define _ASM_TCE_H + +/* + * Tces come in two formats, one for the virtual bus and a different + * format for PCI + */ +#define TCE_VB 0 +#define TCE_PCI 1 + +/* 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 +}; + + +#endif Index: linux-work/arch/ppc64/kernel/u3_iommu.c =================================================================== --- linux-work.orig/arch/ppc64/kernel/u3_iommu.c 2005-08-24 13:26:31.000000000 +1000 +++ linux-work/arch/ppc64/kernel/u3_iommu.c 2005-09-05 14:57:26.000000000 +1000 @@ -44,39 +44,12 @@ #include #include #include +#include #include "pci.h" extern int iommu_force_on; -/* physical base of DART registers */ -#define DART_BASE 0xf8033000UL - -/* Offset from base to control register */ -#define DARTCNTL 0 -/* Offset from base to exception register */ -#define DARTEXCP 0x10 -/* Offset from base to TLB tag registers */ -#define DARTTAG 0x1000 - - -/* Control Register fields */ - -/* base address of table (pfn) */ -#define DARTCNTL_BASE_MASK 0xfffff -#define DARTCNTL_BASE_SHIFT 12 - -#define DARTCNTL_FLUSHTLB 0x400 -#define DARTCNTL_ENABLE 0x200 - -/* size of table in pages */ -#define DARTCNTL_SIZE_MASK 0x1ff -#define DARTCNTL_SIZE_SHIFT 0 - -/* DART table fields */ -#define DARTMAP_VALID 0x80000000 -#define DARTMAP_RPNMASK 0x00ffffff - /* Physical base address and size of the DART table */ unsigned long dart_tablebase; /* exported to htab_initialize */ static unsigned long dart_tablesize; Index: linux-work/arch/ppc64/kernel/pSeries_iommu.c =================================================================== --- linux-work.orig/arch/ppc64/kernel/pSeries_iommu.c 2005-08-30 11:18:12.000000000 +1000 +++ linux-work/arch/ppc64/kernel/pSeries_iommu.c 2005-09-05 14:57:26.000000000 +1000 @@ -46,6 +46,7 @@ #include #include #include +#include #include "pci.h" #define DBG(fmt...) Index: linux-work/arch/ppc64/kernel/pSeries_vio.c =================================================================== --- linux-work.orig/arch/ppc64/kernel/pSeries_vio.c 2005-09-01 13:05:12.000000000 +1000 +++ linux-work/arch/ppc64/kernel/pSeries_vio.c 2005-09-05 14:58:04.000000000 +1000 @@ -22,6 +22,7 @@ #include #include #include +#include extern struct subsystem devices_subsys; /* needed for vio_find_name() */ From benh at kernel.crashing.org Tue Sep 6 15:34:03 2005 From: benh at kernel.crashing.org (Benjamin Herrenschmidt) Date: Tue, 06 Sep 2005 15:34:03 +1000 Subject: [PATCH] ppc64: iommu cleanup 2/2 Message-ID: <1125984843.1333.6.camel@gaston> There are potential cases in the future where the IOMMU might be mapping smaller pages than the regular MMU is using. Keep the allocator working on MMU pagesizes, but the low-level mapping functions need to map more than one TCE entry per page to deal with this. Signed-off-by: Olof Johansson Signed-off-by: Benjamin Herrenschmidt Index: linux-work/arch/ppc64/kernel/pSeries_iommu.c =================================================================== --- linux-work.orig/arch/ppc64/kernel/pSeries_iommu.c 2005-09-01 13:22:18.000000000 +1000 +++ linux-work/arch/ppc64/kernel/pSeries_iommu.c 2005-09-01 13:23:02.000000000 +1000 @@ -60,6 +60,9 @@ union tce_entry t; union tce_entry *tp; + index <<= TCE_PAGE_FACTOR; + npages <<= TCE_PAGE_FACTOR; + t.te_word = 0; t.te_rdwr = 1; // Read allowed @@ -70,11 +73,11 @@ while (npages--) { /* can't move this out since we might cross LMB boundary */ - t.te_rpn = (virt_to_abs(uaddr)) >> PAGE_SHIFT; + t.te_rpn = (virt_to_abs(uaddr)) >> TCE_SHIFT; tp->te_word = t.te_word; - uaddr += PAGE_SIZE; + uaddr += TCE_PAGE_SIZE; tp++; } } @@ -85,6 +88,9 @@ union tce_entry t; union tce_entry *tp; + npages <<= TCE_PAGE_FACTOR; + index <<= TCE_PAGE_FACTOR; + t.te_word = 0; tp = ((union tce_entry *)tbl->it_base) + index; @@ -104,7 +110,7 @@ union tce_entry tce; tce.te_word = 0; - tce.te_rpn = (virt_to_abs(uaddr)) >> PAGE_SHIFT; + tce.te_rpn = (virt_to_abs(uaddr)) >> TCE_SHIFT; tce.te_rdwr = 1; if (direction != DMA_TO_DEVICE) tce.te_pciwr = 1; @@ -137,6 +143,9 @@ union tce_entry tce, *tcep; long l, limit; + tcenum <<= TCE_PAGE_FACTOR; + npages <<= TCE_PAGE_FACTOR; + if (npages == 1) return tce_build_pSeriesLP(tbl, tcenum, npages, uaddr, direction); @@ -156,7 +165,7 @@ } tce.te_word = 0; - tce.te_rpn = (virt_to_abs(uaddr)) >> PAGE_SHIFT; + tce.te_rpn = (virt_to_abs(uaddr)) >> TCE_SHIFT; tce.te_rdwr = 1; if (direction != DMA_TO_DEVICE) tce.te_pciwr = 1; @@ -167,7 +176,7 @@ * Set up the page with TCE data, looping through and setting * the values. */ - limit = min_t(long, npages, PAGE_SIZE/sizeof(union tce_entry)); + limit = min_t(long, npages, 4096/sizeof(union tce_entry)); for (l = 0; l < limit; l++) { tcep[l] = tce; @@ -197,6 +206,9 @@ u64 rc; union tce_entry tce; + tcenum <<= TCE_PAGE_FACTOR; + npages <<= TCE_PAGE_FACTOR; + tce.te_word = 0; while (npages--) { @@ -222,6 +234,9 @@ 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, Index: linux-work/include/asm-ppc64/tce.h =================================================================== --- linux-work.orig/include/asm-ppc64/tce.h 2005-09-01 13:21:52.000000000 +1000 +++ linux-work/include/asm-ppc64/tce.h 2005-09-01 13:23:02.000000000 +1000 @@ -28,6 +28,13 @@ #define TCE_VB 0 #define TCE_PCI 1 +/* TCE page size is 4096 bytes (1 << 12) */ + +#define TCE_SHIFT 12 +#define TCE_PAGE_SIZE (1 << TCE_SHIFT) +#define TCE_PAGE_FACTOR (PAGE_SHIFT - TCE_SHIFT) + + /* tce_entry * Used by pSeries (SMP) and iSeries/pSeries LPAR, but there it's * abstracted so layout is irrelevant. Index: linux-work/arch/ppc64/kernel/u3_iommu.c =================================================================== --- linux-work.orig/arch/ppc64/kernel/u3_iommu.c 2005-09-01 13:21:52.000000000 +1000 +++ linux-work/arch/ppc64/kernel/u3_iommu.c 2005-09-01 13:23:02.000000000 +1000 @@ -125,18 +125,21 @@ DBG("dart: build at: %lx, %lx, addr: %x\n", index, npages, uaddr); + index <<= DART_PAGE_FACTOR; + npages <<= DART_PAGE_FACTOR; + dp = ((unsigned int*)tbl->it_base) + index; /* On U3, all memory is contigous, so we can move this * out of the loop. */ while (npages--) { - rpn = virt_to_abs(uaddr) >> PAGE_SHIFT; + rpn = virt_to_abs(uaddr) >> DART_PAGE_SHIFT; *(dp++) = DARTMAP_VALID | (rpn & DARTMAP_RPNMASK); rpn++; - uaddr += PAGE_SIZE; + uaddr += DART_PAGE_SIZE; } dart_dirty = 1; @@ -154,6 +157,9 @@ DBG("dart: free at: %lx, %lx\n", index, npages); + index <<= DART_PAGE_FACTOR; + npages <<= DART_PAGE_FACTOR; + dp = ((unsigned int *)tbl->it_base) + index; while (npages--) @@ -182,10 +188,10 @@ * that to work around what looks like a problem with the HT bridge * prefetching into invalid pages and corrupting data */ - tmp = lmb_alloc(PAGE_SIZE, PAGE_SIZE); + tmp = lmb_alloc(DART_PAGE_SIZE, DART_PAGE_SIZE); if (!tmp) panic("U3-DART: Cannot allocate spare page!"); - dart_emptyval = DARTMAP_VALID | ((tmp >> PAGE_SHIFT) & DARTMAP_RPNMASK); + dart_emptyval = DARTMAP_VALID | ((tmp >> DART_PAGE_SHIFT) & DARTMAP_RPNMASK); /* Map in DART registers. FIXME: Use device node to get base address */ dart = ioremap(DART_BASE, 0x7000); @@ -196,8 +202,8 @@ * table size and enable bit */ regword = DARTCNTL_ENABLE | - ((dart_tablebase >> PAGE_SHIFT) << DARTCNTL_BASE_SHIFT) | - (((dart_tablesize >> PAGE_SHIFT) & DARTCNTL_SIZE_MASK) + ((dart_tablebase >> DART_PAGE_SHIFT) << DARTCNTL_BASE_SHIFT) | + (((dart_tablesize >> DART_PAGE_SHIFT) & DARTCNTL_SIZE_MASK) << DARTCNTL_SIZE_SHIFT); dart_vbase = ioremap(virt_to_abs(dart_tablebase), dart_tablesize); Index: linux-work/include/asm-ppc64/dart.h =================================================================== --- linux-work.orig/include/asm-ppc64/dart.h 2005-09-01 13:21:52.000000000 +1000 +++ linux-work/include/asm-ppc64/dart.h 2005-09-01 13:23:02.000000000 +1000 @@ -51,5 +51,9 @@ #define DARTMAP_RPNMASK 0x00ffffff +#define DART_SHIFT 12 +#define DART_PAGE_SIZE (1 << DART_SHIFT) +#define DART_PAGE_FACTOR (PAGE_SHIFT - DART_SHIFT) + #endif From benh at kernel.crashing.org Tue Sep 6 15:34:59 2005 From: benh at kernel.crashing.org (Benjamin Herrenschmidt) Date: Tue, 06 Sep 2005 15:34:59 +1000 Subject: [PATCH] ppc64:misc page size cleanups Message-ID: <1125984899.1333.8.camel@gaston> Replace some of the hard-coded constants with PAGE_SIZE/SHIFT/ORDER where appropriate. Likewise, in a couple of places it doesn't make sense to base some allocations on page size when all that's required is a constant 4K, etc. Signed-off-by: Olof Johansson Signed-off-by: Benjamin Herrenschmidt Index: linux-work/arch/ppc64/kernel/head.S =================================================================== --- linux-work.orig/arch/ppc64/kernel/head.S 2005-09-01 13:05:12.000000000 +1000 +++ linux-work/arch/ppc64/kernel/head.S 2005-09-01 13:25:04.000000000 +1000 @@ -1989,7 +1989,7 @@ */ .section ".bss" - .align 12 + .align PAGE_SHIFT .globl empty_zero_page empty_zero_page: Index: linux-work/arch/ppc64/kernel/misc.S =================================================================== --- linux-work.orig/arch/ppc64/kernel/misc.S 2005-08-30 11:18:12.0