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.000000000 +1000 +++ linux-work/arch/ppc64/kernel/misc.S 2005-09-01 13:23:34.000000000 +1000 @@ -329,7 +329,7 @@ /* Flush the dcache */ ld r7,PPC64_CACHES at toc(r2) - clrrdi r3,r3,12 /* Page align */ + clrrdi r3,r3,PAGE_SHIFT /* Page align */ lwz r4,DCACHEL1LINESPERPAGE(r7) /* Get # dcache lines per page */ lwz r5,DCACHEL1LINESIZE(r7) /* Get dcache line size */ mr r6,r3 Index: linux-work/arch/ppc64/kernel/vmlinux.lds.S =================================================================== --- linux-work.orig/arch/ppc64/kernel/vmlinux.lds.S 2005-08-24 13:26:31.000000000 +1000 +++ linux-work/arch/ppc64/kernel/vmlinux.lds.S 2005-09-01 13:23:34.000000000 +1000 @@ -1,3 +1,4 @@ +#include #include OUTPUT_ARCH(powerpc:common64) @@ -16,7 +17,7 @@ SCHED_TEXT LOCK_TEXT *(.fixup) - . = ALIGN(4096); + . = ALIGN(PAGE_SIZE); _etext = .; } @@ -42,7 +43,7 @@ /* will be freed after init */ - . = ALIGN(4096); + . = ALIGN(PAGE_SIZE); __init_begin = .; .init.text : { @@ -82,7 +83,7 @@ SECURITY_INIT - . = ALIGN(4096); + . = ALIGN(PAGE_SIZE); .init.ramfs : { __initramfs_start = .; *(.init.ramfs) @@ -95,13 +96,13 @@ __per_cpu_end = .; } - . = ALIGN(16384); + . = ALIGN(PAGE_SIZE); __init_end = .; /* freed after init ends here */ /* Read/write sections */ - . = ALIGN(16384); + . = ALIGN(PAGE_SIZE); /* The initial task and kernel stack */ .data.init_task : { *(.data.init_task) @@ -128,18 +129,18 @@ __toc_start = .; *(.got) *(.toc) - . = ALIGN(4096); + . = ALIGN(PAGE_SIZE); _edata = .; } - . = ALIGN(4096); + . = ALIGN(PAGE_SIZE); .bss : { __bss_start = .; *(.bss) __bss_stop = .; } - . = ALIGN(4096); + . = ALIGN(PAGE_SIZE); _end = . ; } Index: linux-work/include/asm-ppc64/elf.h =================================================================== --- linux-work.orig/include/asm-ppc64/elf.h 2005-08-24 13:26:46.000000000 +1000 +++ linux-work/include/asm-ppc64/elf.h 2005-09-01 13:23:34.000000000 +1000 @@ -4,6 +4,7 @@ #include #include #include +#include /* PowerPC relocations defined by the ABIs */ #define R_PPC_NONE 0 @@ -145,7 +146,7 @@ #define elf_check_arch(x) ((x)->e_machine == ELF_ARCH) #define USE_ELF_CORE_DUMP -#define ELF_EXEC_PAGESIZE 4096 +#define ELF_EXEC_PAGESIZE PAGE_SIZE /* This is the location that an ET_DYN program is loaded if exec'ed. Typical use of this is to invoke "./ld.so someprog" to test out a new version of Index: linux-work/include/asm-ppc64/thread_info.h =================================================================== --- linux-work.orig/include/asm-ppc64/thread_info.h 2005-08-24 13:26:46.000000000 +1000 +++ linux-work/include/asm-ppc64/thread_info.h 2005-09-01 13:23:34.000000000 +1000 @@ -54,9 +54,9 @@ /* thread information allocation */ -#define THREAD_ORDER 2 -#define THREAD_SIZE (PAGE_SIZE << THREAD_ORDER) -#define THREAD_SHIFT (PAGE_SHIFT + THREAD_ORDER) +#define THREAD_SHIFT 14 +#define THREAD_ORDER (THREAD_SHIFT - PAGE_SHIFT) +#define THREAD_SIZE (1 << THREAD_SHIFT) #ifdef CONFIG_DEBUG_STACK_USAGE #define alloc_thread_info(tsk) \ ({ \ Index: linux-work/include/asm-ppc64/mmu.h =================================================================== --- linux-work.orig/include/asm-ppc64/mmu.h 2005-08-30 11:18:13.000000000 +1000 +++ linux-work/include/asm-ppc64/mmu.h 2005-09-01 13:25:43.000000000 +1000 @@ -29,7 +29,7 @@ /* Location of cpu0's segment table */ #define STAB0_PAGE 0x6 -#define STAB0_PHYS_ADDR (STAB0_PAGE< This patch slightly change the mmu batching code to use the full vaddr instead of getting it from the vsid. This avoids playing with contexts late when doing the actual flush. This version of the patch is untested ;) Signed-off-by: Benjamin Herrenschmidt Index: linux-work/include/asm-ppc64/tlbflush.h =================================================================== --- linux-work.orig/include/asm-ppc64/tlbflush.h 2005-09-05 14:55:10.000000000 +1000 +++ linux-work/include/asm-ppc64/tlbflush.h 2005-09-05 14:55:42.000000000 +1000 @@ -20,10 +20,8 @@ struct mm_struct; struct ppc64_tlb_batch { unsigned long index; - unsigned long context; struct mm_struct *mm; pte_t pte[PPC64_TLB_BATCH_NR]; - unsigned long addr[PPC64_TLB_BATCH_NR]; unsigned long vaddr[PPC64_TLB_BATCH_NR]; }; DECLARE_PER_CPU(struct ppc64_tlb_batch, ppc64_tlb_batch); @@ -47,8 +45,7 @@ #define flush_tlb_kernel_range(start, end) flush_tlb_pending() #define flush_tlb_pgtables(mm, start, end) do { } while (0) -extern void flush_hash_page(unsigned long context, unsigned long ea, pte_t pte, - int local); -void flush_hash_range(unsigned long context, unsigned long number, int local); +extern void flush_hash_page(unsigned long va, pte_t pte, int local); +void flush_hash_range(unsigned long number, int local); #endif /* _PPC64_TLBFLUSH_H */ Index: linux-work/arch/ppc64/mm/tlb.c =================================================================== --- linux-work.orig/arch/ppc64/mm/tlb.c 2005-09-05 14:55:10.000000000 +1000 +++ linux-work/arch/ppc64/mm/tlb.c 2005-09-05 14:55:42.000000000 +1000 @@ -128,12 +128,10 @@ void hpte_update(struct mm_struct *mm, unsigned long addr, unsigned long pte, int wrprot) { - int i; - unsigned long context = 0; struct ppc64_tlb_batch *batch = &__get_cpu_var(ppc64_tlb_batch); + unsigned long vsid; + int i; - if (REGION_ID(addr) == USER_REGION_ID) - context = mm->context.id; i = batch->index; /* @@ -143,17 +141,19 @@ * up scanning and resetting referenced bits then our batch context * will change mid stream. */ - if (unlikely(i != 0 && context != batch->context)) { + if (unlikely(i != 0 && mm != batch->mm)) { flush_tlb_pending(); i = 0; } - - if (i == 0) { - batch->context = context; + if (i == 0) batch->mm = mm; - } + if (addr < KERNELBASE) { + vsid = get_vsid(mm->context.id, addr); + WARN_ON(vsid == 0); + } else + vsid = get_kernel_vsid(addr); + batch->vaddr[i] = (vsid << 28 ) | (addr & 0x0fffffff); batch->pte[i] = __pte(pte); - batch->addr[i] = addr; batch->index = ++i; if (i >= PPC64_TLB_BATCH_NR) flush_tlb_pending(); @@ -175,10 +175,9 @@ local = 1; if (i == 1) - flush_hash_page(batch->context, batch->addr[0], batch->pte[0], - local); + flush_hash_page(batch->vaddr[0], batch->pte[0], local); else - flush_hash_range(batch->context, i, local); + flush_hash_range(i, local); batch->index = 0; put_cpu(); } Index: linux-work/arch/ppc64/mm/hash_utils.c =================================================================== --- linux-work.orig/arch/ppc64/mm/hash_utils.c 2005-09-05 14:55:10.000000000 +1000 +++ linux-work/arch/ppc64/mm/hash_utils.c 2005-09-05 14:56:02.000000000 +1000 @@ -355,18 +355,11 @@ return ret; } -void flush_hash_page(unsigned long context, unsigned long ea, pte_t pte, - int local) +void flush_hash_page(unsigned long va, pte_t pte, int local) { - unsigned long vsid, vpn, va, hash, secondary, slot; + unsigned long vpn, hash, secondary, slot; unsigned long huge = pte_huge(pte); - if (ea < KERNELBASE) - vsid = get_vsid(context, ea); - else - vsid = get_kernel_vsid(ea); - - va = (vsid << 28) | (ea & 0x0fffffff); if (huge) vpn = va >> HPAGE_SHIFT; else @@ -381,17 +374,17 @@ ppc_md.hpte_invalidate(slot, va, huge, local); } -void flush_hash_range(unsigned long context, unsigned long number, int local) +void flush_hash_range(unsigned long number, int local) { if (ppc_md.flush_hash_range) { - ppc_md.flush_hash_range(context, number, local); + ppc_md.flush_hash_range(number, local); } else { int i; - struct ppc64_tlb_batch *batch = &__get_cpu_var(ppc64_tlb_batch); + struct ppc64_tlb_batch *batch = + &__get_cpu_var(ppc64_tlb_batch); for (i = 0; i < number; i++) - flush_hash_page(context, batch->addr[i], batch->pte[i], - local); + flush_hash_page(batch->vaddr[i], batch->pte[i], local); } } Index: linux-work/include/asm-ppc64/machdep.h =================================================================== --- linux-work.orig/include/asm-ppc64/machdep.h 2005-09-05 14:55:10.000000000 +1000 +++ linux-work/include/asm-ppc64/machdep.h 2005-09-05 14:55:42.000000000 +1000 @@ -56,9 +56,8 @@ unsigned long vflags, unsigned long rflags); long (*hpte_remove)(unsigned long hpte_group); - void (*flush_hash_range)(unsigned long context, - unsigned long number, - int local); + void (*flush_hash_range)(unsigned long number, int local); + /* special for kexec, to be called in real mode, linar mapping is * destroyed as well */ void (*hpte_clear_all)(void); Index: linux-work/arch/ppc64/mm/hash_native.c =================================================================== --- linux-work.orig/arch/ppc64/mm/hash_native.c 2005-09-05 14:55:10.000000000 +1000 +++ linux-work/arch/ppc64/mm/hash_native.c 2005-09-05 14:55:42.000000000 +1000 @@ -335,10 +335,9 @@ local_irq_restore(flags); } -static void native_flush_hash_range(unsigned long context, - unsigned long number, int local) +static void native_flush_hash_range(unsigned long number, int local) { - unsigned long vsid, vpn, va, hash, secondary, slot, flags, avpn; + unsigned long va, vpn, hash, secondary, slot, flags, avpn; int i, j; hpte_t *hptep; unsigned long hpte_v; @@ -351,13 +350,7 @@ j = 0; for (i = 0; i < number; i++) { - if (batch->addr[i] < KERNELBASE) - vsid = get_vsid(context, batch->addr[i]); - else - vsid = get_kernel_vsid(batch->addr[i]); - - va = (vsid << 28) | (batch->addr[i] & 0x0fffffff); - batch->vaddr[j] = va; + va = batch->vaddr[j]; if (large) vpn = va >> HPAGE_SHIFT; else Index: linux-work/arch/ppc64/kernel/pSeries_lpar.c =================================================================== --- linux-work.orig/arch/ppc64/kernel/pSeries_lpar.c 2005-09-05 14:55:10.000000000 +1000 +++ linux-work/arch/ppc64/kernel/pSeries_lpar.c 2005-09-05 14:55:42.000000000 +1000 @@ -482,8 +482,7 @@ * Take a spinlock around flushes to avoid bouncing the hypervisor tlbie * lock. */ -void pSeries_lpar_flush_hash_range(unsigned long context, unsigned long number, - int local) +void pSeries_lpar_flush_hash_range(unsigned long number, int local) { int i; unsigned long flags = 0; @@ -494,7 +493,7 @@ spin_lock_irqsave(&pSeries_lpar_tlbie_lock, flags); for (i = 0; i < number; i++) - flush_hash_page(context, batch->addr[i], batch->pte[i], local); + flush_hash_page(batch->vaddr[i], batch->pte[i], local); if (lock_tlbie) spin_unlock_irqrestore(&pSeries_lpar_tlbie_lock, flags); From paulus at samba.org Tue Sep 6 16:33:49 2005 From: paulus at samba.org (Paul Mackerras) Date: Tue, 6 Sep 2005 16:33:49 +1000 Subject: [PATCH] - Revised patch to export kernel end, htab values In-Reply-To: <20050902002847.GA2158@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> <20050902002847.GA2158@in.ibm.com> Message-ID: <17181.14413.180481.331250@cargo.ozlabs.ibm.com> Sharada, > I would like to request feedback on > - this patch and consider for temporary inclusion (while a cleaner or > more acceptable approach is put down) The patch mostly looks OK except that when compiling with the iSeries_defconfig configuration, I get: arch/ppc64/kernel/built-in.o: In function `.setup_arch': : undefined reference to `.of_find_node_by_path' arch/ppc64/kernel/built-in.o: In function `.setup_arch': : undefined reference to `.prom_add_property' arch/ppc64/kernel/built-in.o: In function `.setup_arch': : undefined reference to `.prom_add_property' arch/ppc64/kernel/built-in.o: In function `.setup_arch': : undefined reference to `.of_node_put' arch/ppc64/kernel/built-in.o: In function `.setup_arch': : undefined reference to `.of_find_node_by_path' arch/ppc64/kernel/built-in.o: In function `.setup_arch': : undefined reference to `.prom_add_property' arch/ppc64/kernel/built-in.o: In function `.setup_arch': : undefined reference to `.of_node_put' make: *** [.tmp_vmlinux1] Error 1 I think you need to put your new code inside #ifdef CONFIG_PPC_MULTIPLATFORM. Regards, Paul. From sfr at canb.auug.org.au Tue Sep 6 17:09:13 2005 From: sfr at canb.auug.org.au (Stephen Rothwell) Date: Tue, 6 Sep 2005 17:09:13 +1000 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: <20050906170913.62b818e5.sfr@canb.auug.org.au> On Tue, 6 Sep 2005 13:17:54 +1000 Paul Mackerras wrote: > > @@ -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); The "pci" variable doesn't get used ... > @@ -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; > } The original comment is still correct. > 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; ^^^^^^^^^^^^^^^^^^^^^^^^^^^ PCI_DN ? -- 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/20050906/a2a3ef28/attachment.pgp From michael at ellerman.id.au Tue Sep 6 17:22:42 2005 From: michael at ellerman.id.au (Michael Ellerman) Date: Tue, 6 Sep 2005 17:22:42 +1000 Subject: [PATCH] - Revised patch to export kernel end, htab values In-Reply-To: <17181.14413.180481.331250@cargo.ozlabs.ibm.com> References: <20050823080423.GA2380@in.ibm.com> <20050902002847.GA2158@in.ibm.com> <17181.14413.180481.331250@cargo.ozlabs.ibm.com> Message-ID: <200509061722.42786.michael@ellerman.id.au> On Tue, 6 Sep 2005 16:33, Paul Mackerras wrote: > arch/ppc64/kernel/built-in.o: In function `.setup_arch': > : undefined reference to `.of_node_put' > > make: *** [.tmp_vmlinux1] Error 1 > > I think you need to put your new code inside #ifdef > CONFIG_PPC_MULTIPLATFORM. Or better still CONFIG_KEXEC, which currently depends on PPC_MULTIPLATFORM. cheers -- Michael Ellerman IBM OzLabs email: michael:ellerman.id.au inmsg: mpe:jabber.org wwweb: http://michael.ellerman.id.au phone: +61 2 6212 1183 (tie line 70 21183) We do not inherit the earth from our ancestors, we borrow it from our children. - S.M.A.R.T Person -------------- 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/20050906/a06a124b/attachment.pgp From mach at e-century.com.cn Tue Sep 6 17:36:34 2005 From: mach at e-century.com.cn (mach at e-century.com.cn) Date: Tue, 6 Sep 2005 15:36:34 +0800 Subject: oil press Message-ID: <20050906073548.EE47868164@ozlabs.org> Dear Sir/Madam, It's our pleasure to send the business letter to your esteemed company. We are a professional trading company in China. In the past ten years, our grain and oil machinery were exported to many countries and areas in the world ,and have won a good reputation from our customers . I am very glad to get the e-mail address by Internet. So we specially introduce our oil press equipment and oil refining equipment and hulling equipment and other agricultural machinery to satisfy your needs. We hope to build a mutual beneficial business relationship with your esteemed company. The quotation of our extraction machinery as follows: 1)Model 6YL-68 Capacity: 0.8-1ton/24h. Power: 5.5kw Net Weight: 140kg Packing Dimensions: 920*480*760 2) Model 6YL-80 Capacity: 2-3ton/24h Power: 5.5kw Net Weight: 330kg Packing Dimensions(mm): 1370*570*1080 3) Model 6YL-95 Capacity: 3-4ton/24h. Power: 7.5-11kw Net Weight: 620kg Packing Dimensions(mm):1940*700*780 4) Model 6YL-100 Capacity: 4-5Ton/24h. Power: 7.5kw Net Weight: 480kg Packing Dimensions(mm):1700*600*1130 5) 6YL-120 Capacity: 6Ton/24h. Power: 15kw Net Weight: 650kg Packing Dimensions (mm): 1970*700*780 6) 6YL-80A Integrated oil press Capacity: 2-3Ton/24h Power: 5.5 +0.75kw Net Weight: 520kg Packing Dimensions(mm): 1420*635*1480 & 1135*530*520 7) 6YL-100A Integrated Oil press Capacity: 5Ton/24h. Power: 7.5+1.1 kw Net Weight: 780kg Packing dimensions (mm): 2270*1100*1950 & 1170*660*760 8) LYZX18 Cold Press Expeller Capacity: 6-10Ton/24h(taking non-shell rapeseed as an example) Residual Oil Content in Cake: 4-13% Total Power: 27.2KW Net Weight: 3500KG Boundary Dimensions(mm): 3176*1850*2600 9) 202-3 Screw Pre-press Expeller Capacity: 45-50Ton/24h(sunflower kernel or rapeseed serving as an example) Residual Oil Content in Cake: 13% approx(under normal conditions) Electric Motor: Y225-M-6,1000R.P.M.30KW.220/380V,50Hz Net Weight: 5500KG.approx Boundary Dimensions(mm): 2900*1850*3640 10) ZY283-3 Screw Pre-press Expeller Capacity: 140-460Ton/24h(sunflower kernel or rapeseed serving as an example) Residual Oil Content in Cake: 15-20%(under the normal conditions) Total Power: 55KW 15KW Net Weight: 9380KG.approx Boundary Dimensions(mm): 3708*1920*3843 11) Generator 950 Generator 3900 Generator 7800 Generator 12) Peanut Sheller Model 6B-180 Capacity: 7.2 Ton/24h. Power: 1.5kw Net Weight: 100kg Packing Dimensions: 1280*670*1200 Model 6BH-45 Capacity: 12 Ton/24h. Power: 4kw Net Weight: 380kg Packing Dimensions: 1200*990*2090 Model 6BH-65 Capacity: 24 Ton/24h. Power: 7.5kw Net Weight: 700kg Packing Dimensions: 2000*1400*3010 13) Rice Mill 14) Flour Mill 15) Combine Harvest 16) Tractor 17) The Complete Plant of Hulling Sesame Equipment 18) The Complete Plant of All Kinds of Oil Corps(Extraction and Refinery), 10MTPD-3000MTPD 19) The Complete Plant of Tomato Paste If you want to get further information that you are interested in products, please send me the concrete request, I will do my best to supply you with the satisfying service with the competitive price. I will appreciate you very much, if I can receive your reply. Best regards Alisa Zhao Anyang General International Trading Co., Ltd. Address: Jiefang Rd No.99,Anyang , Henan, China Tel:86-372-5953961 Fax:86-372-5951936 E-mail:mach at e-century.com.cn http://www.ayimpex.com From michael at ellerman.id.au Tue Sep 6 21:00:02 2005 From: michael at ellerman.id.au (Michael Ellerman) Date: Tue, 6 Sep 2005 21:00:02 +1000 (EST) Subject: [PATCH] ppc64: Fix oops for !CONFIG_NUMA Message-ID: <20050906110002.B586C68110@ozlabs.org> The SPARSEMEM EXTREME code (802f192e4a600f7ef84ca25c8b818c8830acef5a) that went in yesterday broke PPC64 for !CONFIG_NUMA. The problem is that (free|reserve)_bootmem don't take a page number as their first argument, they take an address. Ruh roh. Booted on P5 LPAR, iSeries and G5. Signed-off-by: Michael Ellerman --- arch/ppc64/mm/init.c | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) Index: work/arch/ppc64/mm/init.c =================================================================== --- work.orig/arch/ppc64/mm/init.c +++ work/arch/ppc64/mm/init.c @@ -553,12 +553,12 @@ void __init do_init_bootmem(void) * present. */ for (i=0; i < lmb.memory.cnt; i++) - free_bootmem(lmb_start_pfn(&lmb.memory, i), + free_bootmem(lmb.memory.region[i].base, lmb_size_bytes(&lmb.memory, i)); /* reserve the sections we're already using */ for (i=0; i < lmb.reserved.cnt; i++) - reserve_bootmem(lmb_start_pfn(&lmb.reserved, i), + reserve_bootmem(lmb.reserved.region[i].base, lmb_size_bytes(&lmb.reserved, i)); for (i=0; i < lmb.memory.cnt; i++) From paulus at samba.org Tue Sep 6 22:06:29 2005 From: paulus at samba.org (Paul Mackerras) Date: Tue, 6 Sep 2005 22:06:29 +1000 Subject: Please pull ppc64-2.6.git Message-ID: <17181.34373.982692.908365@cargo.ozlabs.ibm.com> Linus, There is another bunch of ppc64 updates in the usual place: rsync://rsync.kernel.org/pub/scm/linux/kernel/git/paulus/ppc64-2.6.git Diffstat and log follow. Thanks, Paul. arch/ppc64/kernel/Makefile | 8 + arch/ppc64/kernel/btext.c | 1 arch/ppc64/kernel/cputable.c | 90 ++++++++-- arch/ppc64/kernel/entry.S | 11 + arch/ppc64/kernel/head.S | 9 + arch/ppc64/kernel/lparcfg.c | 2 arch/ppc64/kernel/maple_setup.c | 3 arch/ppc64/kernel/pSeries_lpar.c | 18 +- arch/ppc64/kernel/pSeries_setup.c | 7 - arch/ppc64/kernel/pmac_setup.c | 19 -- arch/ppc64/kernel/prom.c | 1 arch/ppc64/kernel/prom_init.c | 1 arch/ppc64/kernel/setup.c | 44 ----- arch/ppc64/kernel/sysfs.c | 48 +++-- arch/ppc64/kernel/time.c | 1 arch/ppc64/kernel/udbg.c | 300 ++++++--------------------------- arch/ppc64/kernel/udbg_16550.c | 123 ++++++++++++++ arch/ppc64/kernel/udbg_scc.c | 136 +++++++++++++++ arch/ppc64/mm/hugetlbpage.c | 6 - arch/ppc64/mm/init.c | 1 arch/ppc64/mm/slb.c | 4 arch/ppc64/oprofile/common.c | 56 +----- arch/ppc64/oprofile/op_model_power4.c | 12 - arch/ppc64/oprofile/op_model_rs64.c | 3 arch/ppc64/xmon/start.c | 4 include/asm-powerpc/bugs.h | 18 ++ include/asm-powerpc/mc146818rtc.h | 10 + include/asm-powerpc/mman.h | 6 - include/asm-powerpc/module.h | 77 ++++++++ include/asm-powerpc/sembuf.h | 36 ++++ include/asm-powerpc/shmbuf.h | 42 +++-- include/asm-powerpc/siginfo.h | 12 + include/asm-powerpc/socket.h | 12 + include/asm-powerpc/sockios.h | 6 - include/asm-powerpc/termbits.h | 8 - include/asm-powerpc/termios.h | 7 - include/asm-ppc/bugs.h | 6 - include/asm-ppc/mc146818rtc.h | 31 --- include/asm-ppc/mman.h | 44 ----- include/asm-ppc/module.h | 44 ----- include/asm-ppc/pmac_feature.h | 1 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-ppc/termbits.h | 185 -------------------- include/asm-ppc/termios.h | 232 -------------------------- include/asm-ppc64/bugs.h | 12 - include/asm-ppc64/cputable.h | 12 + include/asm-ppc64/machdep.h | 5 - include/asm-ppc64/mmu.h | 6 - include/asm-ppc64/module.h | 36 ---- include/asm-ppc64/oprofile_impl.h | 3 include/asm-ppc64/sembuf.h | 27 --- include/asm-ppc64/system.h | 19 +- include/asm-ppc64/udbg.h | 27 ++- 57 files changed, 714 insertions(+), 1255 deletions(-) create mode 100644 arch/ppc64/kernel/udbg_16550.c create mode 100644 arch/ppc64/kernel/udbg_scc.c create mode 100644 include/asm-powerpc/bugs.h rename include/{asm-ppc64/mc146818rtc.h => asm-powerpc/mc146818rtc.h} (74%) rename include/{asm-ppc64/mman.h => asm-powerpc/mman.h} (92%) create mode 100644 include/asm-powerpc/module.h create mode 100644 include/asm-powerpc/sembuf.h rename include/{asm-ppc64/shmbuf.h => asm-powerpc/shmbuf.h} (68%) rename include/{asm-ppc64/siginfo.h => asm-powerpc/siginfo.h} (66%) rename include/{asm-ppc64/socket.h => asm-powerpc/socket.h} (86%) rename include/{asm-ppc64/sockios.h => asm-powerpc/sockios.h} (76%) rename include/{asm-ppc64/termbits.h => asm-powerpc/termbits.h} (97%) rename include/{asm-ppc64/termios.h => asm-powerpc/termios.h} (98%) delete mode 100644 include/asm-ppc/bugs.h delete mode 100644 include/asm-ppc/mc146818rtc.h delete mode 100644 include/asm-ppc/mman.h delete mode 100644 include/asm-ppc/module.h delete mode 100644 include/asm-ppc/sembuf.h delete mode 100644 include/asm-ppc/shmbuf.h delete mode 100644 include/asm-ppc/siginfo.h delete mode 100644 include/asm-ppc/socket.h delete mode 100644 include/asm-ppc/sockios.h delete mode 100644 include/asm-ppc/termbits.h delete mode 100644 include/asm-ppc/termios.h delete mode 100644 include/asm-ppc64/bugs.h delete mode 100644 include/asm-ppc64/module.h rename arch/ppc64/oprofile/op_impl.h => include/asm-ppc64/oprofile_impl.h (96%) delete mode 100644 include/asm-ppc64/sembuf.h commit cebb2b156319990fc2fba615bbfeac81be62a86a Author: Olaf Hering Date: Sun Jul 10 19:35:15 2005 +0000 [PATCH] remove linux/version.h include from arch/ppc64 Changing CONFIG_LOCALVERSION rebuilds too much, for no apparent reason. Use system_utsname for progress and debug header. Signed-off-by: Olaf Hering Signed-off-by: Paul Mackerras commit 14b34661615ec036ab4c91637913706e4caccc93 Author: David Gibson Date: Tue Sep 6 14:59:47 2005 +1000 [PATCH] Invert sense of SLB class bit 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 Signed-off-by: Paul Mackerras commit 0fdf0b8634055b016f7b93cfcdea2eb9091f0271 Author: Anton Blanchard Date: Tue Sep 6 14:59:16 2005 +1000 [PATCH] ppc64: Fix build with oprofile disabled Fix build with oprofile disabled. Signed-off-by: Anton Blanchard Signed-off-by: Paul Mackerras commit 8fef0306f9164d4bfd0befb62e63e4d1167681b5 Author: Anton Blanchard Date: Tue Sep 6 14:57:52 2005 +1000 [PATCH] ppc64: Move oprofile_model into cpu feature struct Move oprofile_model into cpu feature struct. Signed-off-by: Anton Blanchard Signed-off-by: Paul Mackerras commit dca859329cee9b4cf02c8b7cb805b49973292ed2 Author: Anton Blanchard Date: Tue Sep 6 14:55:35 2005 +1000 [PATCH] ppc64: Move oprofile_impl.h into include/asm-ppc64 Move oprofile_impl.h into include/asm-ppc64 in preparation for moving oprofile_model into cpu feature struct. Signed-off-by: Anton Blanchard Signed-off-by: Paul Mackerras commit 1a410d883023da70806a0190c4bde104545cb9c6 Author: Anton Blanchard Date: Tue Sep 6 14:53:57 2005 +1000 [PATCH] ppc64: Add oprofile cpu_type to cpu feature struct Add oprofile cpu_type to cpu feature struct. Signed-off-by: Anton Blanchard Signed-off-by: Paul Mackerras commit a6908cd00036080fbea14ff67335e5f2a1ab5489 Author: Anton Blanchard Date: Tue Sep 6 14:52:12 2005 +1000 [PATCH] ppc64: Use num_pmcs in oprofile code Change oprofile to use num_pmcs from the cpu feature struct. Signed-off-by: Anton Blanchard Signed-off-by: Paul Mackerras commit 8530935d384bef1467ba76e1f4382f0f8b3c899d Author: Anton Blanchard Date: Tue Sep 6 14:50:48 2005 +1000 [PATCH] ppc64: remove CPU_FTR_PMC8 Remove the CPU_FTR_PMC8 feature now we encode the number of PMCs directly. Signed-off-by: Anton Blanchard Signed-off-by: Paul Mackerras commit fd5b4377eacac42293b1a349dbb0f9892bf7f74a Author: Anton Blanchard Date: Tue Sep 6 14:47:49 2005 +1000 [PATCH] ppc64: add number of PMCs to cputable Add a field in the cputable struct to store the number of PMCs. Signed-off-by: Anton Blanchard Signed-off-by: Paul Mackerras commit 71839267f2554d76bb0862cdd0181a60bd0f4970 Author: Wim Coekaerts Date: Mon Sep 5 20:22:47 2005 -0700 [PATCH] ppc64: Allow world readable /proc/ppc64/lparcfg I would 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. 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 Signed-off-by: Paul Mackerras commit fa2259b06c38a7c392966c66cd1cdd710d487463 Author: Kumar Gala Date: Wed Aug 24 11:56:56 2005 -0500 [PATCH] ppc64: remove use of asm/segment.h Removed PPC64 architecture specific users of asm/segment.h. Signed-off-by: Kumar Gala Signed-off-by: Paul Mackerras commit 6b9269abd64c54f11dc4aaf162d2915fccae6c77 Author: Jon Loeliger Date: Thu Sep 1 15:51:52 2005 -0500 [PATCH] ppc/ppc64: Merge more include files 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 Signed-off-by: Paul Mackerras commit ad6571a78ac74e9fa27e581834709067dba459af Author: Becky Bruce Date: Sat Sep 3 19:01:57 2005 -0500 [PATCH] Move 3 more headers to asm-powerpc Merged several nearly-identical header files from asm-ppc and asm-ppc64 into asm-powerpc. Signed-off-by: Kumar Gala Signed-off-by: Becky Bruce Signed-off-by: Paul Mackerras commit b2c0ab17ba751abe13a28508b1ac7e9ca074cd87 Author: Anton Blanchard Date: Tue Sep 6 13:05:58 2005 +1000 [PATCH] ppc64: speedup cmpxchg 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 Signed-off-by: Paul Mackerras commit 4721e2214b5fd6eca48caea76afb1bad3148930f Author: Anton Blanchard Date: Tue Sep 6 12:05:26 2005 +1000 [PATCH] ppc64: poison initmem Poison initmem after we free it so we catch use after free issues. Signed-off-by: Anton Blanchard Signed-off-by: Paul Mackerras commit 2f4cf721eb2ff23b60af2932fd9fa4026f2a1164 Author: Jimi Xenidis Date: Thu Sep 1 11:57:10 2005 -0400 [PATCH] ppc64: systemcfg is now a pointer 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. Signed-off-by: Jimi Xenidis Signed-off-by: Paul Mackerras commit 8d9273918635f0301368c01b56c03a6f339e8d51 Author: Milton Miller Date: Tue Sep 6 11:57:27 2005 +1000 [PATCH] ppc64: Consolidate early console and PPCDBG code Consolidate the early console and PPCDBG code in udbg.c Signed-off-by: Milton Miller Signed-off-by: Anton Blanchard Signed-off-by: Paul Mackerras commit 188d2ce78feac67e41e41808acda7951810f677b Author: Milton Miller Date: Tue Sep 6 11:57:00 2005 +1000 [PATCH] ppc64: Remove old includes Trim some no longer needed includes from udbg.c and friends. Signed-off-by: Milton Miller Signed-off-by: Anton Blanchard Signed-off-by: Paul Mackerras commit c8f1c8be629ee34991fdba8bfe46a5c455393209 Author: Milton Miller Date: Tue Sep 6 11:56:42 2005 +1000 [PATCH] ppc64: Take udbg out of ppc_md 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 Signed-off-by: Paul Mackerras commit 7f853352e79bf57c4ee279b7458ed0c072e2be76 Author: Milton Miller Date: Tue Sep 6 11:56:02 2005 +1000 [PATCH] ppc64: Split SCC and 15550 udbg code 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 Signed-off-by: Paul Mackerras commit 37548d58e5ce53dda609c5b35c0eb62d50d59675 Author: Milton Miller Date: Tue Sep 6 11:55:38 2005 +1000 [PATCH] ppc64: Make udbg_init_uart set the ppc_md udbg methods. make udbg_init_uart set the ppc_md udbg methods. Signed-off-by: Milton Miller Signed-off-by: Anton Blanchard Signed-off-by: Paul Mackerras commit cb14c4d641b4e083fae7ce4a0e8a3973cecb7554 Author: Milton Miller Date: Tue Sep 6 11:55:00 2005 +1000 [PATCH] ppc64: Clean up CR handling 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 Signed-off-by: Paul Mackerras commit 5fdabaab01ee8928597aae8a0178a3a4f7b66365 Author: Milton Miller Date: Tue Sep 6 11:54:42 2005 +1000 [PATCH] ppc64: Remove dummy getc routines Now that xmon is fixed we should not need the dummy getc routines. Signed-off-by: Milton Miller Signed-off-by: Anton Blanchard Signed-off-by: Paul Mackerras commit 41be31b7d61c661a63bb1d5c8be3c39f124beabd Author: Milton Miller Date: Tue Sep 6 11:54:13 2005 +1000 [PATCH] ppc64: dont bypass ppc_md.udbg* functions 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 Signed-off-by: Paul Mackerras commit cdcd318fefab8c8655fdc3b085ccc23848a93001 Author: Milton Miller Date: Tue Sep 6 11:50:55 2005 +1000 [PATCH] ppc64: Add missing include 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 Signed-off-by: Paul Mackerras From hollis at penguinppc.org Tue Sep 6 23:32:26 2005 From: hollis at penguinppc.org (Hollis Blanchard) Date: Tue, 6 Sep 2005 08:32:26 -0500 Subject: [PATCH] Separate pci bits out of struct device_node In-Reply-To: <17181.7102.364381.677922@cargo.ozlabs.ibm.com> References: <17181.2658.910786.938698@cargo.ozlabs.ibm.com> <20050906041331.GA3560@otto> <17181.7102.364381.677922@cargo.ozlabs.ibm.com> Message-ID: <66b2f2340d01f5920c2458a068a41ec2@penguinppc.org> On Sep 5, 2005, at 11:31 PM, Paul Mackerras wrote: > > 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); > } kfree already checks for NULL, so the test is unnecessary above. -Hollis From sfr at canb.auug.org.au Wed Sep 7 00:22:26 2005 From: sfr at canb.auug.org.au (Stephen Rothwell) Date: Wed, 7 Sep 2005 00:22:26 +1000 Subject: [PATCH] ppc64: Move oprofile_impl.h into include/asm-ppc64 In-Reply-To: <20050906045535.GP6945@krispykreme> References: <20050906044749.GL6945@krispykreme> <20050906045047.GM6945@krispykreme> <20050906045212.GN6945@krispykreme> <20050906045357.GO6945@krispykreme> <20050906045535.GP6945@krispykreme> Message-ID: <20050907002226.3fea790e.sfr@canb.auug.org.au> On Tue, 6 Sep 2005 14:55:35 +1000 Anton Blanchard wrote: > > Move oprofile_impl.h into include/asm-ppc64 in preparation for moving > oprofile_model into cpu feature struct. Shouldn't it be moved to include/asm-powerpc instead? -- Cheers, Stephen Rothwell sfr at canb.auug.org.au http://www.canb.auug.org.au/~sfr/ From sfr at canb.auug.org.au Wed Sep 7 00:45:49 2005 From: sfr at canb.auug.org.au (Stephen Rothwell) Date: Wed, 7 Sep 2005 00:45:49 +1000 Subject: [PATCH] ppc64: iommu cleanup 1/2 In-Reply-To: <1125984770.1333.3.camel@gaston> References: <1125984770.1333.3.camel@gaston> Message-ID: <20050907004549.0c1a1783.sfr@canb.auug.org.au> On Tue, 06 Sep 2005 15:32:50 +1000 Benjamin Herrenschmidt wrote: > > Index: linux-work/include/asm-ppc64/dart.h > Index: linux-work/include/asm-ppc64/tce.h How about include/asm-powerpc for new include files? Or keep them in arch/ppc64/kernel if they are only used locally? > =================================================================== > --- /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 > . > . > +/* tce_entry > + * Used by pSeries (SMP) and iSeries/pSeries LPAR, but there it's And Michael is (hopefully) going to send you a patch that makes iSeries build again .. :-) -- Cheers, Stephen Rothwell sfr at canb.auug.org.au http://www.canb.auug.org.au/~sfr/ From ameet at austin.ibm.com Wed Sep 7 04:42:59 2005 From: ameet at austin.ibm.com (Ameet Paranjape) Date: Tue, 06 Sep 2005 13:42:59 -0500 Subject: Booting a system with cpu0 in 'failed' state Message-ID: <431DE333.6010700@austin.ibm.com> This patch allows a system to boot up even with cpu0 in the 'failed' state. --- linux-2.6.5-7.183/arch/ppc64/kernel/prom.c 2005-06-17 15:04:31.000000000 -0500 +++ linux-2.6.5-7.183-16463/arch/ppc64/kernel/prom.c 2005-06-22 17:07:33.000000000 -0500 @@ -1102,8 +1102,24 @@ static void __init prom_hold_cpus(unsign } hw_cpu_num = interrupt_server[0]; + + /* + * As we iterate through each cpu in the loop, we look for the first cpu with 'okay' status. Once found, + * that cpu becomes the boot cpu following the boot cpu path. + */ + { + static int check=0; + if((strcmp(type, RELOC("okay")) == 0) && !check++) + _prom->cpu = hw_cpu_num; + } + + if (hw_cpu_num != _prom->cpu) { /* Primary Thread of non-boot cpu */ prom_print_hex(cpuid); prom_print(RELOC(" : starting cpu ")); prom_print(path); From ntl at pobox.com Wed Sep 7 05:38:51 2005 From: ntl at pobox.com (Nathan Lynch) Date: Tue, 6 Sep 2005 14:38:51 -0500 Subject: Booting a system with cpu0 in 'failed' state In-Reply-To: <431DE333.6010700@austin.ibm.com> References: <431DE333.6010700@austin.ibm.com> Message-ID: <20050906193851.GC3560@otto> Ameet Paranjape wrote: > This patch allows a system to boot up even with cpu0 in the 'failed' state. > > --- linux-2.6.5-7.183/arch/ppc64/kernel/prom.c 2005-06-17 > 15:04:31.000000000 -0500 > +++ linux-2.6.5-7.183-16463/arch/ppc64/kernel/prom.c 2005-06-22 > 17:07:33.000000000 -0500 Does this patch even apply to a current mainline kernel? From ameet at austin.ibm.com Wed Sep 7 06:05:21 2005 From: ameet at austin.ibm.com (Ameet Paranjape) Date: Tue, 06 Sep 2005 15:05:21 -0500 Subject: Booting a system with cpu0 in 'failed' state In-Reply-To: <20050906193851.GC3560@otto> References: <431DE333.6010700@austin.ibm.com> <20050906193851.GC3560@otto> Message-ID: <431DF681.6040102@austin.ibm.com> Nathan Lynch wrote: >Ameet Paranjape wrote: > > >>This patch allows a system to boot up even with cpu0 in the 'failed' state. >> >>--- linux-2.6.5-7.183/arch/ppc64/kernel/prom.c 2005-06-17 >>15:04:31.000000000 -0500 >>+++ linux-2.6.5-7.183-16463/arch/ppc64/kernel/prom.c 2005-06-22 >>17:07:33.000000000 -0500 >> >> > >Does this patch even apply to a current mainline kernel? > > > > No, the patch has not been tested on mainline. From jdl at freescale.com Wed Sep 7 06:12:36 2005 From: jdl at freescale.com (Jon Loeliger) Date: Tue, 06 Sep 2005 15:12:36 -0500 Subject: [PATCH 0/3] Start the merge In-Reply-To: <200508290845.34544.arnd@arndb.de> References: <20050829130133.519391c6.sfr@canb.auug.org.au> <200508290845.34544.arnd@arndb.de> Message-ID: <1126037554.25148.41.camel@cashmere.sps.mot.com> On Mon, 2005-08-29 at 01:45, Arnd Bergmann wrote: > On Maandag 29 August 2005 05:01, Stephen Rothwell wrote: > > > Please send at least the first upstream. The other two can also probably > > be sent. > > These certainly look good to me. > > This is another patch to merge the atomic.h file. It is not completely > trivial and changes the semantics for 32 bit SMP systems, which previously > did not do EIEIO_ON_SMP within the atomic operations. AFAICT, that was > a bug in the 32 bit version, which is now fixed as a side-effect of > the merge. > > The combined version of this file also prevents building user space > applications using atomic.h on ppc64. That was already impossible > on 32 bit ppc, but probably also created broken output on ppc64. > > Signed-off-by: Arnd Bergmann > > -- > > include/asm-ppc/atomic.h | 214 ------------------------------ > include/asm-ppc64/atomic.h | 197 --------------------------- > include/asm-ppc64/memory.h | 59 -------- > linux-2.6.12/include/asm-powerpc/atomic.h | 209 +++++++++++++++++++++++++++++ > linux-2.6.12/include/asm-powerpc/memory.h | 59 ++++++++ > linux-2.6.12/include/asm-ppc/io.h | 11 - > 6 files changed, 269 insertions(+), 480 deletions(-) Paul, I'd like to call attention to this buried patch. It appears that it might be lost due to Subject: line swiping; it likely hasn't gotten first class status as its own independent patch. Any chance we can get this one reviewed and pushed upstream too? Thanks, jdl From jdl at freescale.com Wed Sep 7 06:45:09 2005 From: jdl at freescale.com (Jon Loeliger) Date: Tue, 06 Sep 2005 15:45:09 -0500 Subject: PATCH Merge more include files In-Reply-To: <20050902163708.12c1abe3.sfr@canb.auug.org.au> References: <1125607912.16685.111.camel@cashmere.sps.mot.com> <20050902163708.12c1abe3.sfr@canb.auug.org.au> Message-ID: <1126039509.25148.54.camel@cashmere.sps.mot.com> On Fri, 2005-09-02 at 01:37, Stephen Rothwell wrote: > 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. I'll start using _ASM_POWERPC_ from now on. I will also submit a different patch to do a round of this sort of cleanup. Can we get an official call on the GPL header in include files? I'm defaulting to adding them for now. > Looks good. Thanks. More coming, of course. So, will you resubmit patches based on your 3/3 patch that cover the slid-through the cracks set, or shall I? I'm thinking pmac_features.h, dbdma.h, keylargo.h, etc. Thanks, jdl From jdl at freescale.com Wed Sep 7 06:46:38 2005 From: jdl at freescale.com (Jon Loeliger) Date: Tue, 06 Sep 2005 15:46:38 -0500 Subject: PATCH Merge more include files In-Reply-To: References: <200509020518.32732.arnd@arndb.de> Message-ID: <1126039597.25148.59.camel@cashmere.sps.mot.com> On Fri, 2005-09-02 at 08:38, Kumar Gala wrote: > 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 Arnd, If you'd like, I'll submit a patch to use the static inline variant and rip out the definiton in the syscalls.c files. jdl From jdl at freescale.com Wed Sep 7 06:51:47 2005 From: jdl at freescale.com (Jon Loeliger) Date: Tue, 06 Sep 2005 15:51:47 -0500 Subject: PATCH Merge kmap_types.h Message-ID: <1126039905.25148.66.camel@cashmere.sps.mot.com> Here is a patch to merge the ppc and pp64 version of kmap_types.h Signed-off-by: Jon Loeliger Signed-off-by: Kumar Gala --- 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,33 @@ +#ifndef _ASM_POWERPC_KMAP_TYPES_H +#define _ASM_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_PPC_SYNC_ICACHE, + KM_TYPE_NR +}; + +#endif /* __KERNEL__ */ +#endif /* _ASM_POWERPC_KMAP_TYPES_H */ 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,25 +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_PPC_SYNC_ICACHE, - KM_TYPE_NR -}; - -#endif -#endif /* __KERNEL__ */ 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__ */ From sonny at burdell.org Wed Sep 7 07:03:22 2005 From: sonny at burdell.org (Sonny Rao) Date: Tue, 6 Sep 2005 17:03:22 -0400 Subject: Invert sense of SLB class bit In-Reply-To: <20050906045947.GB8628@localhost.localdomain> References: <20050906045947.GB8628@localhost.localdomain> Message-ID: <20050906210322.GA24574@kevlar.burdell.org> On Tue, Sep 06, 2005 at 02:59:47PM +1000, David Gibson wrote: > 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. Hmm, do you think it is worth doing an SDET (or something ) comparison w/ and w/out this patch? Sonny From benh at kernel.crashing.org Wed Sep 7 07:37:18 2005 From: benh at kernel.crashing.org (Benjamin Herrenschmidt) Date: Wed, 07 Sep 2005 07:37:18 +1000 Subject: [PATCH] ppc64: iommu cleanup 1/2 In-Reply-To: <20050907004549.0c1a1783.sfr@canb.auug.org.au> References: <1125984770.1333.3.camel@gaston> <20050907004549.0c1a1783.sfr@canb.auug.org.au> Message-ID: <1126042638.1333.40.camel@gaston> On Wed, 2005-09-07 at 00:45 +1000, Stephen Rothwell wrote: > On Tue, 06 Sep 2005 15:32:50 +1000 Benjamin Herrenschmidt wrote: > > > > Index: linux-work/include/asm-ppc64/dart.h > > Index: linux-work/include/asm-ppc64/tce.h > > How about include/asm-powerpc for new include files? Or keep them in arch/ppc64/kernel if > they are only used locally? They are probably only used locally, I'll have a look. Good idea. They might be used ulitmately by things in "platforms" though... > > =================================================================== > > --- /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 > > . > > . > > +/* tce_entry > > + * Used by pSeries (SMP) and iSeries/pSeries LPAR, but there it's > > And Michael is (hopefully) going to send you a patch that makes iSeries build again .. :-) I know :) Ben. From arnd at arndb.de Wed Sep 7 08:14:14 2005 From: arnd at arndb.de (Arnd Bergmann) Date: Wed, 7 Sep 2005 00:14:14 +0200 Subject: PATCH Merge more include files In-Reply-To: <1126039597.25148.59.camel@cashmere.sps.mot.com> References: <200509020518.32732.arnd@arndb.de> <1126039597.25148.59.camel@cashmere.sps.mot.com> Message-ID: <200509070014.15564.arnd@arndb.de> On Dinsdag 06 September 2005 22:46, Jon Loeliger wrote: > > If you'd like, I'll submit a patch to use the static inline > variant and rip out the definiton in the syscalls.c files. Yes, that sounds good. Thanks, Arnd <>< From mbellon at mvista.com Wed Sep 7 08:50:02 2005 From: mbellon at mvista.com (Mark Bellon) Date: Tue, 06 Sep 2005 15:50:02 -0700 Subject: [PATCH] PPC64: large INITRD causes kernel not to boot [UPDATE] Message-ID: <431E1D1A.2090601@mvista.com> In PPC64 there are number of problems in arch/ppc64/boot/main.c that prevent a kernel from making use of a large (greater than ~16MB) INITRD. This is 64 bit architecture and really large INITRD images should be possible. Simply put the existing code has a fixed reservation (claim) address and once the kernel plus initrd image are large enough to pass this address all sorts of bad things occur. The fix is the dynamically establish the first claim address above the loaded kernel plus initrd (plus some "padding" and rounding). If PROG_START is defined this will be used as the minimum safe address - currently known to be 0x01400000 for the firmwares tested so far. We've talked about this in linuxppc64-dev at ozlabs.org and this is what seems to have settled out. mark Signed-off-by: Mark Bellon -------------- next part -------------- An embedded and charset-unspecified text was scrubbed... Name: initrd-patch Url: http://ozlabs.org/pipermail/linuxppc64-dev/attachments/20050906/a747e99f/attachment.txt From paulus at samba.org Wed Sep 7 08:49:02 2005 From: paulus at samba.org (Paul Mackerras) Date: Wed, 7 Sep 2005 08:49:02 +1000 Subject: [PATCH 0/3] Start the merge In-Reply-To: <1126037554.25148.41.camel@cashmere.sps.mot.com> References: <20050829130133.519391c6.sfr@canb.auug.org.au> <200508290845.34544.arnd@arndb.de> <1126037554.25148.41.camel@cashmere.sps.mot.com> Message-ID: <17182.7390.886339.12876@cargo.ozlabs.ibm.com> Jon Loeliger writes: > I'd like to call attention to this buried patch. It appears that > it might be lost due to Subject: line swiping; it likely hasn't > gotten first class status as its own independent patch. > > Any chance we can get this one reviewed and pushed upstream too? I went to send it on yesterday and found that it doesn't apply any more. If Arnd or someone would like to update it, I'll send it on. Paul. From paulus at samba.org Wed Sep 7 09:42:13 2005 From: paulus at samba.org (Paul Mackerras) Date: Wed, 7 Sep 2005 09:42:13 +1000 Subject: [PATCH] PPC64: large INITRD causes kernel not to boot [UPDATE] In-Reply-To: <431E1D1A.2090601@mvista.com> References: <431E1D1A.2090601@mvista.com> Message-ID: <17182.10581.159598.839256@cargo.ozlabs.ibm.com> Mark Bellon writes: > Simply put the existing code has a fixed reservation (claim) address and > once the kernel plus initrd image are large enough to pass this address > all sorts of bad things occur. The fix is the dynamically establish the > first claim address above the loaded kernel plus initrd (plus some > "padding" and rounding). If PROG_START is defined this will be used as > the minimum safe address - currently known to be 0x01400000 for the > firmwares tested so far. The idea is fine, but I have some questions about the actual patch: > -void *claim(unsigned int, unsigned int, unsigned int); > +void *claim(unsigned long, unsigned long, unsigned long); What was the motivation for this change? Since the zImage wrapper is a 32-bit executable, int and long are both 32 bits. I would prefer to leave the parameters as unsigned int to force people to realize that the parameters are 32 bits (even if said people have been working on 64-bit programs recently). > + claim_base = _ALIGN_UP((unsigned long)_end, ONE_MB); > + > +#if defined(PROG_START) > + /* > + * Maintain a "magic" minimum address. This keeps some older > + * firmware platforms running. > + */ > + > + if (claim_base < PROG_START) > + claim_base = PROG_START; > +#endif This appears to be the meat of the patch, the rest is "cleanup", right? Paul. From mbellon at mvista.com Wed Sep 7 09:47:38 2005 From: mbellon at mvista.com (Mark Bellon) Date: Tue, 06 Sep 2005 16:47:38 -0700 Subject: [PATCH] PPC64: large INITRD causes kernel not to boot [UPDATE] In-Reply-To: <17182.10581.159598.839256@cargo.ozlabs.ibm.com> References: <431E1D1A.2090601@mvista.com> <17182.10581.159598.839256@cargo.ozlabs.ibm.com> Message-ID: <431E2A9A.4000107@mvista.com> Paul Mackerras wrote: >Mark Bellon writes: > > > >>Simply put the existing code has a fixed reservation (claim) address and >>once the kernel plus initrd image are large enough to pass this address >>all sorts of bad things occur. The fix is the dynamically establish the >>first claim address above the loaded kernel plus initrd (plus some >>"padding" and rounding). If PROG_START is defined this will be used as >>the minimum safe address - currently known to be 0x01400000 for the >>firmwares tested so far. >> >> > >The idea is fine, but I have some questions about the actual patch: > > > >>-void *claim(unsigned int, unsigned int, unsigned int); >>+void *claim(unsigned long, unsigned long, unsigned long); >> >> > >What was the motivation for this change? Since the zImage wrapper is >a 32-bit executable, int and long are both 32 bits. I would prefer to >leave the parameters as unsigned int to force people to realize that >the parameters are 32 bits (even if said people have been working on >64-bit programs recently). > > The function, claim, is found in prom.c uses longs. The long is the usual idiom for hiding a pointer, not an int, so I fixed accordingly. I'm open to further discussion of course. On a 64 bit machine long and int are different sizes. This would make things "proper" if things changed in the future. > > >>+ claim_base = _ALIGN_UP((unsigned long)_end, ONE_MB); >>+ >>+#if defined(PROG_START) >>+ /* >>+ * Maintain a "magic" minimum address. This keeps some older >>+ * firmware platforms running. >>+ */ >>+ >>+ if (claim_base < PROG_START) >>+ claim_base = PROG_START; >>+#endif >> >> > >This appears to be the meat of the patch, the rest is "cleanup", right? > > Correct. The preceding comment explains what is going on. Removing the magic numbers seemed like a good idea. mark >Paul. > > -------------- next part -------------- An HTML attachment was scrubbed... URL: http://ozlabs.org/pipermail/linuxppc64-dev/attachments/20050906/622a18a1/attachment.htm From mbellon at mvista.com Wed Sep 7 09:49:55 2005 From: mbellon at mvista.com (Mark Bellon) Date: Tue, 06 Sep 2005 16:49:55 -0700 Subject: [PATCH] PPC64: large INITRD causes kernel not to boot [UPDATE] In-Reply-To: <17182.10581.159598.839256@cargo.ozlabs.ibm.com> References: <431E1D1A.2090601@mvista.com> <17182.10581.159598.839256@cargo.ozlabs.ibm.com> Message-ID: <431E2B23.40509@mvista.com> Paul Mackerras wrote: >Mark Bellon writes: > > > >>Simply put the existing code has a fixed reservation (claim) address and >>once the kernel plus initrd image are large enough to pass this address >>all sorts of bad things occur. The fix is the dynamically establish the >>first claim address above the loaded kernel plus initrd (plus some >>"padding" and rounding). If PROG_START is defined this will be used as >>the minimum safe address - currently known to be 0x01400000 for the >>firmwares tested so far. >> >> > >The idea is fine, but I have some questions about the actual patch: > > > >>-void *claim(unsigned int, unsigned int, unsigned int); >>+void *claim(unsigned long, unsigned long, unsigned long); >> >> > >What was the motivation for this change? Since the zImage wrapper is >a 32-bit executable, int and long are both 32 bits. I would prefer to >leave the parameters as unsigned int to force people to realize that >the parameters are 32 bits (even if said people have been working on >64-bit programs recently). > > > The function, claim, is found in prom.c uses longs. The long is the usual idiom for hiding a pointer, not an int, so I fixed accordingly. I'm open to further discussion of course. On a 64 bit machine long and int are different sizes. This would make things "proper" if things changed in the future. >>+ claim_base = _ALIGN_UP((unsigned long)_end, ONE_MB); >>+ >>+#if defined(PROG_START) >>+ /* >>+ * Maintain a "magic" minimum address. This keeps some older >>+ * firmware platforms running. >>+ */ >>+ >>+ if (claim_base < PROG_START) >>+ claim_base = PROG_START; >>+#endif >> >> > >This appears to be the meat of the patch, the rest is "cleanup", right? > > Correct. The preceding comment explains what is going on. Removing the magic numbers seemed like a good idea. mark >Paul. > > From arnd at arndb.de Wed Sep 7 10:07:32 2005 From: arnd at arndb.de (Arnd Bergmann) Date: Wed, 7 Sep 2005 02:07:32 +0200 Subject: [PATCH 0/3] Start the merge In-Reply-To: <17182.7390.886339.12876@cargo.ozlabs.ibm.com> References: <20050829130133.519391c6.sfr@canb.auug.org.au> <1126037554.25148.41.camel@cashmere.sps.mot.com> <17182.7390.886339.12876@cargo.ozlabs.ibm.com> Message-ID: <200509070207.33504.arnd@arndb.de> On Middeweken 07 September 2005 00:49, Paul Mackerras wrote: > I went to send it on yesterday and found that it doesn't apply any > more. ?If Arnd or someone would like to update it, I'll send it on. > Hmm. I don't get rejects against the git head. For which tree do you want the patch? Arnd <>< From david at gibson.dropbear.id.au Wed Sep 7 09:47:02 2005 From: david at gibson.dropbear.id.au (David Gibson) Date: Wed, 7 Sep 2005 09:47:02 +1000 Subject: Invert sense of SLB class bit In-Reply-To: <20050906210322.GA24574@kevlar.burdell.org> References: <20050906045947.GB8628@localhost.localdomain> <20050906210322.GA24574@kevlar.burdell.org> Message-ID: <20050906234702.GA7337@localhost.localdomain> On Tue, Sep 06, 2005 at 05:03:22PM -0400, Sonny Rao wrote: > On Tue, Sep 06, 2005 at 02:59:47PM +1000, David Gibson wrote: > > 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. > > Hmm, do you think it is worth doing an SDET (or something ) comparison > w/ and w/out this patch? Erm.. probably.. although paulus seems to have pushed it already.. -- 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 sfr at canb.auug.org.au Wed Sep 7 11:02:17 2005 From: sfr at canb.auug.org.au (Stephen Rothwell) Date: Wed, 7 Sep 2005 11:02:17 +1000 Subject: PATCH Merge more include files In-Reply-To: <1126039509.25148.54.camel@cashmere.sps.mot.com> References: <1125607912.16685.111.camel@cashmere.sps.mot.com> <20050902163708.12c1abe3.sfr@canb.auug.org.au> <1126039509.25148.54.camel@cashmere.sps.mot.com> Message-ID: <20050907110217.78c9d8bf.sfr@canb.auug.org.au> On Tue, 06 Sep 2005 15:45:09 -0500 Jon Loeliger wrote: > > I'll start using _ASM_POWERPC_ from now on. I will > also submit a different patch to do a round of this > sort of cleanup. OK, thanks. > Can we get an official call on the GPL header in > include files? I'm defaulting to adding them for now. And I've been removing them :-) It actually often depends on which of the asm-ppc or asm-ppc64 files you actually copy. You are right, we need a statement. > Thanks. More coming, of course. Great. > So, will you resubmit patches based on your 3/3 patch > that cover the slid-through the cracks set, or shall I? > I'm thinking pmac_features.h, dbdma.h, keylargo.h, etc. I took those out because they were controversial and may require some more thought about where they actually end up. -- 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/20050907/a40c56a4/attachment.pgp From sleddog at us.ibm.com Wed Sep 7 07:28:01 2005 From: sleddog at us.ibm.com (Dave C Boutcher) Date: Tue, 6 Sep 2005 16:28:01 -0500 Subject: [RFC] SCSI target for IBM Power5 LPAR Message-ID: <20050906212801.GB14057@cs.umn.edu> This device driver provides the SCSI target side of the "virtual SCSI" on IBM Power5 systems. The initiator side has been in mainline for a while now (drivers/scsi/ibmvscsi/ibmvscsi.c.) Targets already exist for AIX and OS/400. One of the biggest discussions, I expect, will be whether much of this belongs in user-land. We have had considerable debates on that subject, and ended up with it all in the kernel. Unlike some other targets (e.g. iSCSI) that sit on top of nice TCP/IP stacks, this one interacts at a pretty low level with the firmware. There weren't any good user-land splits that seemed to make sense (and looking at the history of the NFS server also influenced the discussion.) This is currently just an RFC...if my boxers survive the flamage I'll submit it for inclusion. Thanks Dave B Signed-off-by: Dave Boutcher Signed-off-by: Santiago Leon Signed-off-by: Linda Xie diff -uNr linux-2.6.13-rc7/drivers/scsi/ibmvscsi/ibmvscsi.h linux-2.6.13-rc7-ibmvscsis/drivers/scsi/ibmvscsi/ibmvscsi.h --- linux-2.6.13-rc7/drivers/scsi/ibmvscsi/ibmvscsi.h 2005-09-06 15:56:35.231844303 -0500 +++ linux-2.6.13-rc7-ibmvscsis/drivers/scsi/ibmvscsi/ibmvscsi.h 2005-09-06 16:02:41.279485577 -0500 @@ -33,6 +33,7 @@ #include #include #include +#include #include "viosrp.h" struct scsi_cmnd; diff -uNr linux-2.6.13-rc7/drivers/scsi/ibmvscsi/ibmvscsis.c linux-2.6.13-rc7-ibmvscsis/drivers/scsi/ibmvscsi/ibmvscsis.c --- linux-2.6.13-rc7/drivers/scsi/ibmvscsi/ibmvscsis.c 1969-12-31 18:00:00.000000000 -0600 +++ linux-2.6.13-rc7-ibmvscsis/drivers/scsi/ibmvscsi/ibmvscsis.c 2005-09-06 16:03:32.335092947 -0500 @@ -0,0 +1,3775 @@ +/************************************************************************ + + IBM eServer i/pSeries Virtual SCSI Target Driver + Copyright (C) 2003-2005 Dave Boutcher (boutcher at us.ibm.com) IBM Corp. + Santiago Leon (santil at us.ibm.com) IBM Corp. + Linda Xie (lxie at us.ibm.com) 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. + + 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 + + ********************************************************************** + This driver is a SCSI target that interoperates according to the PAPR + (POWER Architecture Platform Requirements) document. Currently it is + specific to POWER logical partitioning, however in the future it would + be nice to extend this to other virtualized environments. + + The architecture defines virtual adapters, whose configuration is + reported in the Open Firmware device tree. There area number of + power hypervisor calls (such as h_reg_crq, to register the inter-OS + queue) that support the virtual adapters. + + Messages are sent between partitions on a "Command/Response Queue" + (CRQ), which is just a buffer of 16 byte entries in the receiver's + Senders cannot access the buffer directly, but send messages by + making a hypervisor call and passing in the 16 bytes. The hypervisor + puts the message in the next 16 byte space in round-robbin fashion, + turns on the high order bit of the message (the valid bit), and + generates an interrupt to the receiver (if interrupts are turned on.) + The receiver just turns off the valid bit when they have copied out + the message. + + The VSCSI client builds a SCSI Remote Protocol (SRP) Information Unit + (IU) (as defined in the T10 standard available at www.t10.org), gets + a DMA address for the message, and sends it to the target as the + payload of a CRQ message. The target DMAs the SRP IU and processes it, + including doing any additional data transfers. When it is done, it + DMAs the SRP response back to the same address as the request came from + and sends a CRQ message back to inform the client that the request has + completed. + + This target interoperates not only with the Linux client (ibmvscsi.c) + but also with AIX and OS/400 clients. Thus, while the implementation + can be changed, the underlying behaviour (protocol) is fixed. + + Configuration of the target is done via sysfs. The target driver + maps either block devices (e.g. IDE CD drive, loopback file, etc) to + SCSI LUNs, in which case it emulates the SCSI protocol and issues + kernel block device calls, or maps real SCSI devices, in which case + the SCSI commands are just passed on to the real SCSI device. +************************************************************************/ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include "viosrp.h" + +#define IBMVSCSIS_VERSION "1.0.0" + +#define DEFAULT_TIMEOUT (30*HZ) +#define TARGET_MAX_NAME_LEN 128 +#define INITIAL_SRP_LIMIT 16 +#define TARGETS_PER_BUS (64) +#define BUS_PER_ADAPTER (8) +#define DMA_BUFFER_CACHE_SIZE (16) +#define DMA_BUFFER_INIT_COUNT (4) +#define DMA_BUFFER_INIT_LEN (PAGE_SIZE*16) +#define MODE_SENSE_BUFFER_SIZE (512) +#define REFCOUNT_TIMEOUT_MS (250) /* 1/4 second */ + +/* + * The following are lifted from usb.h + */ +static int ibmvscsis_debug = 0; +#define dbg(format, arg...) \ + do {\ + if (ibmvscsis_debug) printk(KERN_WARNING __FILE__ ": " \ + format , ## arg);\ + } while(0) +#define err(format, arg...) printk(KERN_ERR "ibmvscsis: " format , ## arg) +#define info(format, arg...) printk(KERN_INFO "ibmvscsis: " format , ## arg) +#define warn(format, arg...) printk(KERN_WARNING "ibmvscsis: " format , ## arg) + +/* + * Given an 8 byte LUN, return the first level bus/target/lun. + * Today this doesn't support multi-level LUNs + */ +#define GETBUS(x) ((int)((((u64)(x)) >> 53) & 0x0007)) +#define GETTARGET(x) ((int)((((u64)(x)) >> 56) & 0x003f)) +#define GETLUN(x) ((int)((((u64)(x)) >> 48) & 0x001f)) + +/* + * sysfs attributes macro + */ +#define ATTR(_type, _name, _mode) \ + struct attribute vscsi_##_type##_##_name##_attr = { \ + .name = __stringify(_name), .mode = _mode, .owner = THIS_MODULE \ + }; + +/* + * Hypervisor calls. + */ +#define h_copy_rdma(l, sa, sb, da, db) \ + plpar_hcall_norets(H_COPY_RDMA, l, sa, sb, da, db) +#define h_send_crq(ua, l, h) \ + plpar_hcall_norets(H_SEND_CRQ, ua, l, h) +#define h_reg_crq(ua, tok, sz)\ + plpar_hcall_norets(H_REG_CRQ, ua, tok, sz); +#define h_free_crq(ua) \ + plpar_hcall_norets(H_FREE_CRQ, ua); + +MODULE_DESCRIPTION("IBM Virtual SCSI Target"); +MODULE_AUTHOR("Dave Boutcher"); +MODULE_LICENSE("GPL"); +MODULE_VERSION(IBMVSCSIS_VERSION); + +/* + * These are fixed for the system and come from the Open Firmware device tree. + * We just store them here to save getting them every time. + */ +static char system_id[64] = ""; +static char partition_name[97] = "UNKNOWN"; +static unsigned int partition_number = -1; + +/* + * SCSI defined structure for inquiry data + */ +struct inquiry_data { + u8 qual_type; + u8 rmb_reserve; + u8 version; + u8 aerc_naca_hisup_format; + u8 addl_len; + u8 sccs_reserved; + u8 bque_encserv_vs_multip_mchngr_reserved; + u8 reladr_reserved_linked_cmdqueue_vs; + char vendor[8]; + char product[16]; + char revision[4]; + char vendor_specific[20]; + char reserved1[2]; + char version_descriptor[16]; + char reserved2[22]; + char unique[158]; +}; + +/* + * an RPA command/response transport queue. This is our structure + * that points to the actual queue (not architected by firmware) + */ +struct crq_queue { + struct viosrp_crq *msgs; + int size, cur; + dma_addr_t msg_token; + spinlock_t lock; +}; + +enum iue_flags { + V_IN_USE = 0, + V_DIOVER = 1, + V_WRITE = 2, + V_LINKED = 3, + V_ABORTED = 4, + V_FLYING = 5, + V_BARRIER = 6, + V_PARSED = 7, + V_DONE = 8, +}; + +/* + * This structure tracks our fundamental unit of work. Whenever + * an SRP Information Unit (IU) arrives, we track all the good stuff + * here + */ +struct iu_entry { + union viosrp_iu *iu; + struct server_adapter *adapter; + struct list_head next; + dma_addr_t iu_token; + struct { + dma_addr_t remote_token; + char *data_buffer; + dma_addr_t data_token; + long data_len; + struct vdev *vd; + unsigned long flags; + char *sense; + int data_out_residual_count; + int data_in_residual_count; + int ioerr; + int timeout; + struct scsi_request* sreq; + struct iu_entry *child[2]; + struct iu_entry *parent; + unsigned char child_status; + int rw; + long lba; + long len; + } req; +}; + +/* + * a pool of ius for use + */ +struct iu_pool { + spinlock_t lock; + struct list_head iu_entries; + struct iu_entry *list; + union viosrp_iu *iu_storage; + dma_addr_t iu_token; + u32 size; +}; + +/* + * Represents a single device that someone told us about + * that we treat as a LUN + */ +struct vdev { + struct list_head list; + char direct_scsi; + atomic_t refcount; + int disabled; + u64 lun; + struct kobject kobj; + char device_name[TARGET_MAX_NAME_LEN]; + struct { + struct block_device *bdev; + long blocksize; + long sectsize; + long lastlba; + unsigned char scsi_type; + int ro; + int removable; + int changed; + } b; + struct { + struct scsi_device *sdev; + } s; +}; + +/* + * Represents a bus. target #'s in SCSI are 6 bits long, + * so you can have 64 targets per bus + */ +struct vbus { + struct vdev *vdev[TARGETS_PER_BUS]; + atomic_t num_targets; + struct kobject kobj; + int bus_num; +}; + +/* + * Cached buffer. This is a data buffer that we have issued + * dma_map_foo on. Rather than do this every time we need a + * data buffer, keep a cache of mapped buffers around. + */ +struct dma_buffer { + dma_addr_t token; + char *addr; + size_t len; +}; + +/* all driver data associated with a host adapter */ +struct server_adapter { + struct device *dev; + struct vio_dev *dma_dev; + struct crq_queue queue; + struct work_struct crq_task; + struct tasklet_struct endio_tasklet; + struct iu_pool pool; + spinlock_t lock; + struct bio *bio_done; + struct bio *bio_donetail; + struct list_head cmd_queue; + struct vbus *vbus[BUS_PER_ADAPTER]; + int nvdevs; + int next_rsp_delta; + unsigned long liobn; + unsigned long riobn; + + atomic_t num_buses; + int max_sectors; + struct kobject stats_kobj; + DECLARE_BITMAP(dma_buffer_use, DMA_BUFFER_CACHE_SIZE); + struct dma_buffer dma_buffer[DMA_BUFFER_CACHE_SIZE]; + + /* Statistics only */ + atomic_t iu_count; /* number allocated */ + atomic_t bio_count; /* number allocated */ + atomic_t crq_processed; + atomic_t interrupts; + atomic_t read_processed; + atomic_t write_processed; + atomic_t buffers_allocated; + atomic_t errors; +}; + +/* + * We use the following struct, list, and lock to keep track of the scsi + * devices and their mapping to targets in the vscsis adapters. + */ +struct scsi_dev_node { + struct list_head node; + struct scsi_device *sdev; + struct vdev *vdev; +}; + +/* The state of a request */ +enum ibmvscsis_iue_state { + FREE_IU, + INFLIGHT, + RETRY, + RETRY_SPLIT_BUF, +}; + +static LIST_HEAD(scsi_dev_list); +static spinlock_t sdev_list_lock = SPIN_LOCK_UNLOCKED; + +/* ============================================================== + * Utility Routines + * ============================================================== + */ +/* + * return an 8 byte lun given a bus, target, lun. + * Today this only supports single level luns. + */ +u64 make_lun(unsigned int bus, unsigned int target, unsigned int lun) +{ + u16 result = (0x8000 | + ((target & 0x003f) << 8) | + ((bus & 0x0007) << 5) | (lun & 0x001f)); + return ((u64) result) << 48; +} + +/* + * Get the control byte from a SCSI CDB + */ +static u8 getcontrolbyte(u8 * cdb) +{ + return cdb[COMMAND_SIZE(cdb[0]) - 1]; +} + +/* + * Get the "link" bit from a SCSI CDB + */ +static u8 getlink(struct iu_entry *iue) +{ + return (getcontrolbyte(iue->iu->srp.cmd.cdb) & 0x01); +} + +static int data_out_desc_size(struct srp_cmd *cmd) +{ + switch (cmd->data_out_format) { + case SRP_NO_BUFFER: + return 0; + case SRP_DIRECT_BUFFER: + return sizeof(struct memory_descriptor); + case SRP_INDIRECT_BUFFER: + return sizeof(struct indirect_descriptor) + + ((cmd->data_out_count - + 1) * sizeof(struct memory_descriptor)); + default: + err("client error. Invalid data_out_format %d\n", + cmd->data_out_format); + return 0; + } +} + +/* + * Given an SRP, figure out the "data in" or "data out" length + */ +static int vscsis_data_length(struct srp_cmd *cmd, int out) +{ + struct memory_descriptor *md; + struct indirect_descriptor *id; + int offset = cmd->additional_cdb_len * 4; + int switch_value; + + if (out) + switch_value = cmd->data_out_format; + else { + switch_value = cmd->data_in_format; + offset += data_out_desc_size(cmd); + } + + switch (switch_value) { + case SRP_NO_BUFFER: + return 0; + case SRP_DIRECT_BUFFER: + md = (struct memory_descriptor *)(cmd->additional_data + + offset); + return md->length; + case SRP_INDIRECT_BUFFER: + id = (struct indirect_descriptor *)(cmd->additional_data + + offset); + return id->total_length; + default: + err("invalid data format\n"); + return 0; + } +} + +/* Allocate a buffer with a dma_address. Don't use dma_alloc_coherent + * since that uses GFP_ATOMIC internally and we can tollerate a delay + */ +static void *alloc_coherent_buffer(struct server_adapter *adapter, size_t size, + dma_addr_t *dma_handle) +{ + void *buffer = kmalloc(size, GFP_KERNEL); + + if (buffer) { + *dma_handle = dma_map_single(adapter->dev, buffer, size, + DMA_BIDIRECTIONAL); + + if (dma_mapping_error(*dma_handle)) { + kfree(buffer); + buffer = NULL; + } + } + + return buffer; +} + +static void free_coherent_buffer(struct device *dev, size_t size, + void *buffer, dma_addr_t dma_handle) { + dma_unmap_single(dev, dma_handle, size, DMA_BIDIRECTIONAL); + kfree(buffer); +} + +/* + * Helper function to create a direct buffer descriptor from an indirect + * buffer descriptor of length 1 + */ +static void make_direct_buffer(struct srp_cmd *cmd) +{ + struct indirect_descriptor *id = (struct indirect_descriptor *) + (cmd->additional_data); + struct memory_descriptor *md = (struct memory_descriptor *) + (cmd->additional_data); + unsigned int length = id->list[0].length; + unsigned int address = id->list[0].virtual_address; + + if (cmd->data_out_format == SRP_INDIRECT_BUFFER) + cmd->data_out_format = SRP_DIRECT_BUFFER; + if (cmd->data_in_format == SRP_INDIRECT_BUFFER) + cmd->data_in_format = SRP_DIRECT_BUFFER; + + md->length = length; + md->virtual_address = address; + cmd->data_in_count = cmd->data_out_count = 0; +} + +/* + * Find the vdev structure from the LUN field in an SRP IUE + * Note that this routine bumps a refcount field in the vdev. + * Normally this is done when free_iu is called. + */ +static struct vdev *find_vscsis_vdev(struct iu_entry *iue) +{ + u16 *lun = (u16 *) & iue->iu->srp.cmd.lun; + u32 bus = (lun[0] & 0x00E0) >> 5; + u32 target = (lun[0] & 0x3F00) >> 8; + u32 slun = (lun[0] & 0x001F); + struct vdev *vd = NULL; + unsigned long flags; + + /* If asking for a lun other than 0, return nope */ + if (slun) + return NULL; + + /* Only from SRP CMD */ + if (iue->iu->srp.generic.type != SRP_CMD_TYPE) + return NULL; + + /* if not a recognized LUN format, return NULL */ + if ((lun[0] & 0xC000) != 0x8000) + return NULL; + + spin_lock_irqsave(&iue->adapter->lock, flags); + if (iue->adapter->vbus[bus] == NULL) + goto out_unlock; + + vd = iue->adapter->vbus[bus]->vdev[target]; + + if ((vd == NULL) || (vd->disabled)) { + vd = NULL; + goto out_unlock; + } + + if (vd) + atomic_inc(&vd->refcount); + +out_unlock: + spin_unlock_irqrestore(&iue->adapter->lock, flags); + return vd; +} + +/* ============================================================== + * Information Unit (IU) Pool Routines + * ============================================================== + */ +/* + * We keep a pool of IUs, this routine builds the pool. The pool is + * per-adapter. The size of the pool is negotiated as part of the SRP + * login, where we negotiate the number of requests (IUs) the client + * can send us. This routine is not synchronized, since it happens + * only at probe time. + */ +static int initialize_iu_pool(struct server_adapter *adapter, int size) +{ + struct iu_pool *pool = &adapter->pool; + int i; + + pool->size = size; + pool->lock = SPIN_LOCK_UNLOCKED; + INIT_LIST_HEAD(&pool->iu_entries); + + pool->list = kmalloc(pool->size * sizeof(*pool->list), GFP_KERNEL); + if (!pool->list) { + err("Error: Cannot allocate memory for IU list\n"); + return -ENOMEM; + } + memset(pool->list, 0, pool->size * sizeof(*pool->list)); + + pool->iu_storage = + alloc_coherent_buffer(adapter, + pool->size * sizeof(*pool->iu_storage), + &pool->iu_token); + if (!pool->iu_storage) { + err("Error: Cannot allocate memory for IU pool\n"); + kfree(pool->list); + return -ENOMEM; + } + + for (i = 0; i < pool->size; ++i) { + pool->list[i].iu = pool->iu_storage + i; + pool->list[i].iu_token = + pool->iu_token + sizeof(*pool->iu_storage) * i; + pool->list[i].adapter = adapter; + list_add_tail(&pool->list[i].next, &pool->iu_entries); + } + + return 0; +} + +/* + * Free the pool we allocated in initialize_iu_pool + */ +static void release_iu_pool(struct server_adapter *adapter) +{ + struct iu_pool *pool = &adapter->pool; + int i, in_use = 0; + for (i = 0; i < pool->size; ++i) + if (test_bit(V_IN_USE, &pool->list[i].req.flags)) + ++in_use; + if (in_use) + err("Releasing event pool with %d IUs still in use!\n", in_use); + + kfree(pool->list); + free_coherent_buffer(adapter->dev, + pool->size * sizeof(*pool->iu_storage), + pool->iu_storage, pool->iu_token); +} + +/* + * Get an IU from the pool. Return NULL if the pool is empty. This + * routine is syncronized by the adapter lock. The routine sets all the + * important fields to 0 + */ +static struct iu_entry *get_iu(struct server_adapter *adapter) +{ + struct iu_entry *e; + unsigned long flags; + + spin_lock_irqsave(&adapter->pool.lock, flags); + if (!list_empty(&adapter->pool.iu_entries)) { + e = list_entry(adapter->pool.iu_entries.next, struct iu_entry, + next); + list_del(adapter->pool.iu_entries.next); + + if (test_bit(V_IN_USE, &e->req.flags)) + err("Found in-use iu in free pool!"); + + memset(&e->req, 0, sizeof(e->req)); + + __set_bit(V_IN_USE, &e->req.flags); + } else + e = NULL; + + spin_unlock_irqrestore(&adapter->pool.lock, flags); + atomic_inc(&adapter->iu_count); + return e; +} + +/* + * Return an IU to the pool. This routine is synchronized by the + * adapter lock + */ +static void free_iu(struct iu_entry *iue) +{ + /* iue's with parents are kmalloc'ed, not picked from the pool */ + if (iue->req.parent) { + kfree(iue); + return; + } + + if (iue->req.vd) + atomic_dec(&iue->req.vd->refcount); + + if (!test_bit(V_IN_USE, &iue->req.flags)) + warn("Internal error, freeing iue twice!\n"); + else { + __clear_bit(V_IN_USE, &iue->req.flags); + list_add_tail(&iue->next, &iue->adapter->pool.iu_entries); + } + atomic_dec(&iue->adapter->iu_count); +} + +/* + * Allocates two iue's and splits the buffer descriptors between them + */ +static int split_iu(struct iu_entry* iue) +{ + int length = 0, i, child1i = 0, count; + struct iu_entry *child1, *child2; + struct iu_entry *child_iue; + struct srp_cmd *child_cmd; + struct srp_cmd *cmd = &iue->iu->srp.cmd; + struct indirect_descriptor *child_id; + struct indirect_descriptor *id = (struct indirect_descriptor *) + (cmd->additional_data); + + if (cmd->data_out_format && cmd->data_in_format) { + err("Don't support bidirectional buffers yet\n"); + return -EPERM; + } + + dbg("splitting %p len %lx incount %x outcount %x lba %lx\n", iue, + iue->req.len, cmd->data_in_count, cmd->data_out_count, + iue->req.lba); + + child1 = kmalloc(sizeof(struct iu_entry) + sizeof(union viosrp_iu), + GFP_KERNEL); + if (child1 == NULL) + return -ENOMEM; + + child2 = kmalloc(sizeof(struct iu_entry) + sizeof(union viosrp_iu), + GFP_KERNEL); + if (child2 == NULL) { + free_iu(child1); + return -ENOMEM; + } + + if (iue->req.len < PAGE_SIZE) { + err("Can't split buffers less than a page\n"); + return -EPERM; + } + + child1->iu = (union viosrp_iu *)((char*)child1 + sizeof(*child1)); + child2->iu = (union viosrp_iu *)((char*)child2 + sizeof(*child2)); + child1->adapter = child2->adapter = iue->adapter; + memset(&child1->req, 0, sizeof(child1->req)); + memset(&child2->req, 0, sizeof(child2->req)); + memset(&child1->iu->srp.cmd, 0, sizeof(struct srp_cmd)); + memset(&child2->iu->srp.cmd, 0, sizeof(struct srp_cmd)); + __set_bit(V_IN_USE, &child1->req.flags); + __set_bit(V_IN_USE, &child2->req.flags); + + /* Split a direct buffer */ + if (cmd->data_out_format == SRP_DIRECT_BUFFER || + cmd->data_in_format == SRP_DIRECT_BUFFER) { + struct memory_descriptor *md = (struct memory_descriptor *) + (cmd->additional_data); + struct memory_descriptor *ch1_md = (struct memory_descriptor *) + (child1->iu->srp.cmd.additional_data); + struct memory_descriptor *ch2_md = (struct memory_descriptor *) + (child2->iu->srp.cmd.additional_data); + + int npages = (md->length - 1) / PAGE_SIZE + 1; + ch1_md->length = ((npages + 1) / 2) * PAGE_SIZE; + ch2_md->length = md->length - ch1_md->length; + ch1_md->virtual_address = md->virtual_address; + ch2_md->virtual_address = md->virtual_address + ch1_md->length; + child1->req.len = ch1_md->length; + child2->req.len = ch2_md->length; + goto splitted; + } + + child_iue = child1; + child_cmd = &child1->iu->srp.cmd; + child_id = (struct indirect_descriptor *) (child_cmd->additional_data); + count = iue->req.rw ? cmd->data_out_count : cmd->data_in_count; + + for (i = 0; i < count ; i++) { + child_id->list[i - child1i].length = id->list[i].length; + child_id->list[i - child1i].virtual_address = + id->list[i].virtual_address; + if (iue->req.rw) + child_cmd->data_out_count++; + else + child_cmd->data_in_count++; + + child_id->total_length += id->list[i].length; + length += id->list[i].length; + child_iue->req.len += id->list[i].length; + if (!child1i && (length >= iue->req.len / 2 || + i >= count - 2)) { + child_iue = child2; + child_cmd = &child2->iu->srp.cmd; + child_id = (struct indirect_descriptor *) + (child_cmd->additional_data); + child1i = i + 1; + } + } + +splitted: + child1->iu->srp.cmd.data_out_format = iue->iu->srp.cmd.data_out_format; + child1->iu->srp.cmd.data_in_format = iue->iu->srp.cmd.data_in_format; + child2->iu->srp.cmd.data_out_format = iue->iu->srp.cmd.data_out_format; + child2->iu->srp.cmd.data_in_format = iue->iu->srp.cmd.data_in_format; + + if (child1->iu->srp.cmd.data_out_count == 1 || + child1->iu->srp.cmd.data_in_count == 1) + make_direct_buffer(&child1->iu->srp.cmd); + if (child2->iu->srp.cmd.data_out_count == 1 || + child2->iu->srp.cmd.data_in_count == 1) + make_direct_buffer(&child2->iu->srp.cmd); + + child1->req.rw = child2->req.rw = iue->req.rw; + __set_bit(V_PARSED, &child1->req.flags); + __set_bit(V_PARSED, &child2->req.flags); + child1->req.lba = iue->req.lba; + child2->req.lba = iue->req.lba + (child1->req.len >> 9); + + iue->req.child[0] = child1; + iue->req.child[1] = child2; + child1->req.parent = child2->req.parent = iue; + child1->req.vd = child2->req.vd = iue->req.vd; + + return 0; +} + +/* ============================================================== + * Data buffer cache routines. Note that we don't NEED a + * data cache, but this eliminates mapping and unmapping DMA + * addresses for data buffers on every request, which can be quite + * expensive on a PPC64 system. santi hates these routines (that + * just do first-fit allocation) but they are Good Enough (tm) until + * he writes something more elegant. + * ============================================================== + */ +/* + * Get some data buffers to start. This doesn't lock the adapter structure! + */ +static void init_data_buffer(struct server_adapter *adapter) +{ + int i; + + for (i = 0; i < DMA_BUFFER_INIT_COUNT; i++) { + if (adapter->dma_buffer[i].addr == NULL) { + adapter->dma_buffer[i].addr = + alloc_coherent_buffer(adapter, DMA_BUFFER_INIT_LEN, + &adapter->dma_buffer[i]. + token); + adapter->dma_buffer[i].len = DMA_BUFFER_INIT_LEN; + atomic_inc(&adapter->buffers_allocated); + } + } +} + +/* + * Get a memory buffer that includes a mapped DMA address. Just use first-fit + */ +static void get_data_buffer(char **buffer, dma_addr_t * data_token, size_t len, + struct server_adapter *adapter) +{ + int i; + + for (i = 0; i < DMA_BUFFER_CACHE_SIZE; i++) { + if ((adapter->dma_buffer[i].addr) && + (adapter->dma_buffer[i].len >= len) && + (!test_and_set_bit(i, adapter->dma_buffer_use))) { + *buffer = adapter->dma_buffer[i].addr; + *data_token = adapter->dma_buffer[i].token; + return; + } + } + + /* Couldn't get a buffer! Try and get a new one */ + *buffer = alloc_coherent_buffer(adapter, len, data_token); + atomic_inc(&adapter->buffers_allocated); + return; +} + +/* + * Free a memory buffer that includes a mapped DMA address. + */ +static void free_data_buffer(char *buffer, dma_addr_t data_token, size_t len, + struct server_adapter *adapter) +{ + int i; + + /* First see if this buffer is already in the cache */ + for (i = 0; i < DMA_BUFFER_CACHE_SIZE; i++) { + if (adapter->dma_buffer[i].addr == buffer) { + if (adapter->dma_buffer[i].token != data_token) + err("Inconsistent data buffer pool info!\n"); + if (!test_and_clear_bit(i, adapter->dma_buffer_use)) + err("Freeing data buffer twice!\n"); + return; + } + } + + /* See if there is an empty slot in our list */ + for (i = 0; i < DMA_BUFFER_CACHE_SIZE; i++) { + if (!test_and_set_bit(i, adapter->dma_buffer_use)) { + if (adapter->dma_buffer[i].addr == NULL) { + adapter->dma_buffer[i].addr = buffer; + adapter->dma_buffer[i].token = data_token; + adapter->dma_buffer[i].len = len; + smp_mb__before_clear_bit(); + clear_bit(i, adapter->dma_buffer_use); + return; + } else + clear_bit(i, adapter->dma_buffer_use); + } + } + + /* Now see if there is a smaller buffer we should throw out */ + for (i = 0; i < DMA_BUFFER_CACHE_SIZE; i++) { + if (!test_and_set_bit(i, adapter->dma_buffer_use)) { + if (adapter->dma_buffer[i].len < len) { + free_coherent_buffer(adapter->dev, + adapter->dma_buffer[i].len, + adapter->dma_buffer[i].addr, + adapter->dma_buffer[i].token); + + atomic_dec(&adapter->buffers_allocated); + + adapter->dma_buffer[i].addr = buffer; + adapter->dma_buffer[i].token = data_token; + adapter->dma_buffer[i].len = len; + smp_mb__before_clear_bit(); + clear_bit(i, adapter->dma_buffer_use); + return; + } else + clear_bit(i, adapter->dma_buffer_use); + } + } + + /* No space to cache this. Give it back to the kernel */ + free_coherent_buffer(adapter->dev, len, buffer, data_token); + atomic_dec(&adapter->buffers_allocated); +} + +/* + * Release all the data buffers + */ +static void release_data_buffer(struct server_adapter *adapter) +{ + int i; + int free_in_use = 0; + + for (i = 0; i < DMA_BUFFER_CACHE_SIZE; i++) { + if (adapter->dma_buffer[i].addr != NULL) { + if (test_bit(i, adapter->dma_buffer_use)) + free_in_use++; + free_coherent_buffer(adapter->dev, + adapter->dma_buffer[i].len, + adapter->dma_buffer[i].addr, + adapter->dma_buffer[i].token); + + atomic_dec(&adapter->buffers_allocated); + } + } + + if (free_in_use) + err("Freeing %d in-use data buffers\n", free_in_use); + return; +} + +/* ============================================================== + * Inter-OS send and receive routines + * ============================================================== + */ +/* + * Get a CRQ from the inter-partition queue. + */ +static struct viosrp_crq *crq_queue_next_crq(struct crq_queue *queue) +{ + struct viosrp_crq *crq; + unsigned long flags; + + spin_lock_irqsave(&queue->lock, flags); + crq = &queue->msgs[queue->cur]; + if (crq->valid & 0x80) { + if (++queue->cur == queue->size) + queue->cur = 0; + } + else + crq = NULL; + spin_unlock_irqrestore(&queue->lock, flags); + + return crq; +} + +/* + * Send an IU to another partition using the CRQ. + */ +static int send_iu(struct iu_entry *iue, u64 length, u8 format) +{ + long rc, rc1; + union { + struct viosrp_crq cooked; + u64 raw[2]; + } crq; + + /* First copy the SRP */ + rc = h_copy_rdma(length, + iue->adapter->liobn, + iue->iu_token, + iue->adapter->riobn, iue->req.remote_token); + + if (rc) + err("Send_iu: Error %ld transferring data to client\n", rc); + + crq.cooked.valid = 0x80; + crq.cooked.format = format; + crq.cooked.reserved = 0x00; + crq.cooked.timeout = 0x00; + crq.cooked.IU_length = length; + crq.cooked.IU_data_ptr = iue->iu->srp.generic.tag; + + if (rc == 0) + crq.cooked.status = 0x99; /* Just needs to be non-zero */ + else + crq.cooked.status = 0x00; + + rc1 = h_send_crq(iue->adapter->dma_dev->unit_address, + crq.raw[0], + crq.raw[1]); + + if (rc1) { + err("Error %ld sending response to client\n", rc1); + return rc1; + } + + return rc; +} + +/* + * Send data to a single SRP memory descriptor + * Returns amount of data sent, or negative value on error + */ +static long send_md_data(dma_addr_t stoken, int len, + struct memory_descriptor *md, + struct server_adapter *adapter) +{ + int tosend; + long rc; + + if (len < md->length) + tosend = len; + else + tosend = md->length; + + rc = h_copy_rdma(tosend, + adapter->liobn, + stoken, adapter->riobn, md->virtual_address); + + if (rc != H_Success) { + err("send_md_data: Error %ld transferring data to client\n", + rc); + return -EIO; + } + + return tosend; +} + +/* Send data to a list of memory descriptors + */ +static int send_md_list(int num_entries, int tosendlen, + dma_addr_t stoken, + struct memory_descriptor *md, + struct iu_entry *iue) +{ + int i, thislen, bytes; + int sentlen = 0; + + for (i = 0; ((i < num_entries) && (tosendlen)); i++) { + if (tosendlen > md[i].length) + thislen = md[i].length; + else + thislen = tosendlen; + + bytes = send_md_data(stoken + sentlen, thislen, + md + i, iue->adapter); + if (bytes < 0) + return bytes; + + if (bytes != thislen) + warn("Error: Tried to send %d, sent %d\n", thislen, + bytes); + + sentlen += bytes; + tosendlen -= bytes; + } + return sentlen; +} + +/* + * Send data to the SRP data_in buffers + * Returns amount of data sent, or negative value on error + */ +static long send_cmd_data(dma_addr_t stoken, int len, struct iu_entry *iue) +{ + struct srp_cmd *cmd = &iue->iu->srp.cmd; + struct memory_descriptor *md = NULL, *ext_list = NULL; + struct indirect_descriptor *id = NULL; + dma_addr_t data_token; + int offset = 0; + int sentlen = 0; + int num_md, rc; + + offset = cmd->additional_cdb_len * 4 + data_out_desc_size(cmd); + + switch (cmd->data_in_format) { + case SRP_NO_BUFFER: + return 0; + case SRP_DIRECT_BUFFER: + md = (struct memory_descriptor *)(cmd->additional_data + + offset); + sentlen = send_md_data(stoken, len, md, iue->adapter); + len -= sentlen; + if (len) { + __set_bit(V_DIOVER, &iue->req.flags); + iue->req.data_in_residual_count = len; + } + return sentlen; + } + + if (cmd->data_in_format != SRP_INDIRECT_BUFFER) { + err("client error Invalid data_in_format %d\n", + cmd->data_in_format); + return 0; + } + + id = (struct indirect_descriptor *)(cmd->additional_data + offset); + num_md = id->head.length / sizeof(struct memory_descriptor); + + if (num_md == cmd->data_in_count) + md = &id->list[0]; + + else { + ext_list = alloc_coherent_buffer(iue->adapter, id->head.length, + &data_token); + if (!ext_list) { + err("Error dma_alloc_coherent indirect table!\n"); + return 0; + } + + /* get indirect memory descriptor table from initiator */ + rc = h_copy_rdma(id->head.length, + iue->adapter->riobn, + id->head.virtual_address, + iue->adapter->liobn, + data_token); + if (rc != H_Success) { + err("Error copying indirect table rc %d\n", rc); + return 0; + } + + md = (struct memory_descriptor *)ext_list; + } + + /* Work through the memory descriptor list */ + sentlen = send_md_list(num_md, len, stoken, md, iue); + if (sentlen < 0 ) + return sentlen; + + len -= sentlen; + + if (len) { + __set_bit(V_DIOVER, &iue->req.flags); + iue->req.data_in_residual_count = len; + } + + if (ext_list) + free_coherent_buffer(iue->adapter->dev, + id->head.length, ext_list, data_token); + + return sentlen; +} + +/* + * Get data from the other partition from a single SRP memory descriptor + * Returns amount of data received, or negative value on error + */ +static long get_md_data(dma_addr_t ttoken, int len, + struct memory_descriptor *md, + struct server_adapter *adapter) +{ + int toget; + long rc; + + if (len < md->length) + toget = len; + else + toget = md->length; + + rc = h_copy_rdma(toget, + adapter->riobn, + md->virtual_address, adapter->liobn, ttoken); + + if (rc != H_Success) { + err("get_md_data: Error %ld transferring data from client\n", + rc); + return -EIO; + } + + return toget; +} + +static int get_md_list(int num_entries, int togetlen, + dma_addr_t stoken, + struct memory_descriptor *md, + struct iu_entry *iue) +{ + int i, thislen, bytes; + int gotlen = 0; + + for (i = 0; ((i < num_entries) && (togetlen)); i++) { + if (togetlen > md[i].length) + thislen = md[i].length; + else + thislen = togetlen; + + bytes = get_md_data(stoken + gotlen, thislen, md + i, + iue->adapter); + if (bytes < 0) + return bytes; + + if (bytes != thislen) + err("Partial data got from client (%d/%d)\n", + bytes, thislen); + + gotlen += bytes; + togetlen -= bytes; + } + + return gotlen; +} + +/* + * Get data from an SRP data in area. + * Returns amount of data received, or negative value on error + */ +static long get_cmd_data(dma_addr_t stoken, int len, struct iu_entry *iue) +{ + struct srp_cmd *cmd = &iue->iu->srp.cmd; + struct memory_descriptor *md, *ext_list; + struct indirect_descriptor *id; + dma_addr_t data_token; + int offset = 0; + int total_length = 0; + int num_md, rc; + int gotlen = 0; + + offset = cmd->additional_cdb_len * 4; + + switch (cmd->data_out_format) { + case SRP_NO_BUFFER: + return 0; + break; + case SRP_DIRECT_BUFFER: + md = (struct memory_descriptor *)(cmd->additional_data + + offset); + return get_md_data(stoken, len, md, iue->adapter); + break; + } + + if (cmd->data_out_format != SRP_INDIRECT_BUFFER) { + err("client error: Invalid data_out_format %d\n", + cmd->data_out_format); + return 0; + } + + id = (struct indirect_descriptor *)(cmd->additional_data + offset); + + total_length = id->total_length; + + num_md = id->head.length / sizeof(struct memory_descriptor); + + if (num_md == cmd->data_out_count) { + /* Work through the partial memory descriptor list */ + gotlen = get_md_list(num_md, len, + stoken, &id->list[0], iue); + return gotlen; + } + + /* get indirect table */ + + ext_list = alloc_coherent_buffer(iue->adapter, id->head.length, + &data_token); + if (!ext_list) { + err("Error dma_alloc_coherent indirect table!\n"); + return 0; + } + + /* get indirect memory descriptor table */ + rc = h_copy_rdma(id->head.length, + iue->adapter->riobn, + id->head.virtual_address, + iue->adapter->liobn, + data_token); + if (rc != H_Success) { + err("Error copying indirect table rc %d\n", rc); + free_coherent_buffer(iue->adapter->dev, + id->head.length, + ext_list, data_token); + return 0; + } + + gotlen = get_md_list(num_md, len, + stoken, ext_list, iue); + free_coherent_buffer(iue->adapter->dev, + id->head.length, + ext_list, data_token); + + return gotlen; +} + +/* + * Send an SRP response that includes sense data + */ +static long send_rsp(struct iu_entry *iue, + unsigned char status, + unsigned char asc) +{ + u8 *sense = iue->iu->srp.rsp.sense_and_response_data; + u64 tag = iue->iu->srp.generic.tag; + union viosrp_iu *iu = iue->iu; + unsigned long flags; + + if (status != NO_SENSE) + atomic_inc(&iue->adapter->errors); + + if (iue->req.parent) { + struct iu_entry *parent = iue->req.parent; + if (parent->req.child[0] == iue) + parent->req.child[0] = NULL; + else if (parent->req.child[1] == iue) + parent->req.child[1] = NULL; + else + err("parent %p doesn't know child!\n", iue->req.parent); + + /* get only the first error */ + if (status && !parent->req.child_status) + parent->req.child_status = status; + + /* all children are done, send response */ + if (!parent->req.child[0] && !parent->req.child[1]) { + if (!test_bit(V_ABORTED, &parent->req.flags)) + send_rsp(parent, parent->req.child_status, + 0x00); + else + iue->adapter->next_rsp_delta++; + + __set_bit(V_DONE, &parent->req.flags); + kblockd_schedule_work(&iue->adapter->crq_task); + } + return 0; + } + /* If the linked bit is on and status is good */ + if (test_bit(V_LINKED, &iue->req.flags) && (status == NO_SENSE)) + status = 0x10; + + memset(iu, 0, sizeof(struct srp_rsp)); + iu->srp.rsp.type = SRP_RSP_TYPE; + spin_lock_irqsave(&iue->adapter->lock, flags); + iu->srp.rsp.request_limit_delta = 1 + iue->adapter->next_rsp_delta; + iue->adapter->next_rsp_delta = 0; + spin_unlock_irqrestore(&iue->adapter->lock, flags); + iu->srp.rsp.tag = tag; + + iu->srp.rsp.diover = test_bit(V_DIOVER, &iue->req.flags) ? 1 : 0; + + iu->srp.rsp.data_in_residual_count = iue->req.data_in_residual_count; + iu->srp.rsp.data_out_residual_count = iue->req.data_out_residual_count; + + iu->srp.rsp.rspvalid = 0; + + iu->srp.rsp.response_data_list_length = 0; + + if (status && !iue->req.sense) { + iu->srp.rsp.status = SAM_STAT_CHECK_CONDITION; + iu->srp.rsp.snsvalid = 1; + iu->srp.rsp.sense_data_list_length = 18; + + /* Valid bit and 'current errors' */ + sense[0] = (0x1 << 7 | 0x70); + + /* Sense key */ + sense[2] = status; + + /* Additional sense length */ + sense[7] = 0xa; /* 10 bytes */ + + /* Additional sense code */ + sense[12] = asc; + } else { + if (iue->req.sense) { + iu->srp.rsp.snsvalid = 1; + iu->srp.rsp.sense_data_list_length = + SCSI_SENSE_BUFFERSIZE; + memcpy(sense, iue->req.sense, SCSI_SENSE_BUFFERSIZE); + } + iu->srp.rsp.status = status; + } + + send_iu(iue, sizeof(iu->srp.rsp), VIOSRP_SRP_FORMAT); + + return 0; +} + +/* ============================================================== + * Block device endio routines (top and bottom) + * ============================================================== + */ +static void finish_iue(struct iu_entry *iue) +{ + int bytes; + unsigned long flags; + struct server_adapter *adapter = iue->adapter; + + /* Send back the SRP and data if this request was NOT + * aborted + */ + if (test_bit(V_ABORTED, &iue->req.flags)) { + spin_lock_irqsave(&adapter->lock, flags); + adapter->next_rsp_delta++; + spin_unlock_irqrestore(&adapter->lock, flags); + goto out; + } + + if (iue->req.ioerr) { + err("Block operation failed\n"); + send_rsp(iue, HARDWARE_ERROR, 0x00); + goto out; + } + + if (test_bit(V_WRITE, &iue->req.flags)) { + send_rsp(iue, NO_SENSE, 0x00); + goto out; + } + + /* return data if this was a read */ + bytes = send_cmd_data(iue->req.data_token, + iue->req.data_len, + iue); + if (bytes != iue->req.data_len) { + err("Error sending data on response (tried %ld, sent %d\n", + iue->req.data_len, bytes); + send_rsp(iue, ABORTED_COMMAND, 0x00); + } else + send_rsp(iue, NO_SENSE, 0x00); + +out: free_data_buffer(iue->req.data_buffer, + iue->req.data_token, iue->req.data_len, + adapter); + spin_lock_irqsave(&adapter->lock, flags); + free_iu(iue); + spin_unlock_irqrestore(&adapter->lock, flags); +} +/* + * the routine that gets called on end_io of our bios. We basically + * schedule the processing to be done in our task, since we don't want + * do things like RDMA in someone else's interrupt handler + * + * Each iu request may result in multiple bio requests. only proceed + * when all the bio requests have done. + */ +static int ibmvscsis_end_io(struct bio *bio, unsigned int nbytes, int error) +{ + struct iu_entry *iue = (struct iu_entry *)bio->bi_private; + struct server_adapter *adapter = iue->adapter; + unsigned long flags; + + if (bio->bi_size) + return 1; + + if (!test_bit(BIO_UPTODATE, &bio->bi_flags)) + iue->req.ioerr = 1; + + /* Add the bio to the done queue */ + spin_lock_irqsave(&adapter->lock, flags); + if (adapter->bio_donetail) { + adapter->bio_donetail->bi_next = bio; + adapter->bio_donetail = bio; + } else + adapter->bio_done = adapter->bio_donetail = bio; + bio->bi_next = NULL; + spin_unlock_irqrestore(&adapter->lock, flags); + + /* Schedule the task */ + tasklet_schedule(&adapter->endio_tasklet); + + return 0; +} + +/* + * Process BH buffer completions. When the end_io routine gets called + * we queue the bio on an internal queue and start a task to process them + */ +static void endio_task(unsigned long data) +{ + struct server_adapter *adapter = (struct server_adapter *)data; + struct iu_entry *iue; + struct bio *bio; + unsigned long flags; + + do { + iue = NULL; + spin_lock_irqsave(&adapter->lock, flags); + bio = adapter->bio_done; + if (bio) { + if (bio == adapter->bio_donetail) + adapter->bio_donetail = NULL; + adapter->bio_done = bio->bi_next; + bio->bi_next = NULL; + + /* Remove this iue from the in-flight list */ + iue = (struct iu_entry *)bio->bi_private; + if (!test_bit(V_IN_USE, &iue->req.flags)) { + err("Internal error! freed iue in bio!!!\n"); + spin_unlock_irqrestore(&adapter->lock, flags); + return; + } + + list_del(&iue->next); + } + + spin_unlock_irqrestore(&adapter->lock, flags); + + if (iue) { + finish_iue(iue); + bio_put(bio); + atomic_dec(&adapter->bio_count); + } + } while (bio); + kblockd_schedule_work(&adapter->crq_task); +} + +/* ============================================================== + * SCSI Command Emulation Routines + * ============================================================== + */ +/* + * Process an inquiry SCSI Command + */ +static int process_inquiry(struct iu_entry *iue) +{ + struct inquiry_data *id; + dma_addr_t data_token; + u8 *raw_id; + int bytes; + unsigned long flags; + int genhd_flags; + + id = alloc_coherent_buffer(iue->adapter, sizeof(*id), &data_token); + + if (id == NULL) { + err("Not able to get inquiry buffer, retrying later\n"); + return RETRY; + } + + raw_id = (u8 *)id; + memset(id, 0, sizeof(*id)); + + /* If we have a valid device */ + if (iue->req.vd) { + genhd_flags = iue->req.vd->b.bdev->bd_disk->flags; + /* Standard inquiry page */ + if ((iue->iu->srp.cmd.cdb[1] == 0x00) && + (iue->iu->srp.cmd.cdb[2] == 0x00)) { + dbg(" inquiry returning device\n"); + id->qual_type = iue->req.vd->b.scsi_type; + id->rmb_reserve = + iue->req.vd->b.removable ? 0x80 : 0x00; + id->version = 0x84; /* ISO/IE */ + id->aerc_naca_hisup_format = 0x22;/* naca & fmt 0x02 */ + id->addl_len = sizeof(*id) - 4; + id->bque_encserv_vs_multip_mchngr_reserved = 0x00; + id->reladr_reserved_linked_cmdqueue_vs = 0x02;/*CMDQ*/ + memcpy(id->vendor, "IBM ", 8); + /* Don't even ask about the next bit. AIX uses + * hardcoded device naming to recognize device types + * and their client won't work unless we use VOPT and + * VDASD. + */ + if (id->qual_type == TYPE_ROM) + memcpy(id->product, "VOPT blkdev ", 16); + else + memcpy(id->product, "VDASD blkdev ", 16); + memcpy(id->revision, "0001", 4); + snprintf(id->unique,sizeof(id->unique), + "IBM-VSCSI-%s-P%d-%x-%d-%d-%d\n", + system_id, + partition_number, + iue->adapter->dma_dev->unit_address, + GETBUS(iue->req.vd->lun), + GETTARGET(iue->req.vd->lun), + GETLUN(iue->req.vd->lun)); + } else if ((iue->iu->srp.cmd.cdb[1] == 0x01) && + (iue->iu->srp.cmd.cdb[2] == 0x00)) { + /* Supported VPD pages */ + id->qual_type = iue->req.vd->b.scsi_type; + raw_id[1] = 0x80; /* page */ + raw_id[2] = 0x00; /* reserved */ + raw_id[3] = 0x03; /* length */ + raw_id[4] = 0x00; /* page 0 */ + raw_id[5] = 0x80; /* serial number page */ + } else if ((iue->iu->srp.cmd.cdb[1] == 0x01) && + (iue->iu->srp.cmd.cdb[2] == 0x80)) { + /* serial number page */ + id->qual_type = iue->req.vd->b.scsi_type; + raw_id[1] = 0x80; /* page */ + raw_id[2] = 0x00; /* reserved */ + snprintf((char *)(raw_id+4), + sizeof(*id)-4, + "IBM-VSCSI-%s-P%d-%x-%d-%d-%d\n", + system_id, + partition_number, + iue->adapter->dma_dev->unit_address, + GETBUS(iue->req.vd->lun), + GETTARGET(iue->req.vd->lun), + GETLUN(iue->req.vd->lun)); + raw_id[3] = strlen((char *)raw_id+4); + } else { + /* Some unsupported data */ + err("unknown inquiry page %d %d\n", + iue->iu->srp.cmd.cdb[1], + iue->iu->srp.cmd.cdb[2]); + send_rsp(iue, ILLEGAL_REQUEST, 0x24); + return FREE_IU; + } + } else { + dbg(" inquiry returning no device\n"); + id->qual_type = 0x7F; /* Not supported, no device */ + } + + if (test_bit(V_ABORTED, &iue->req.flags)) { + spin_lock_irqsave(&iue->adapter->lock, flags); + iue->adapter->next_rsp_delta++; + spin_unlock_irqrestore(&iue->adapter->lock, flags); + free_coherent_buffer(iue->adapter->dev, sizeof(*id), id, + data_token); + return FREE_IU; + } + + bytes = send_cmd_data(data_token, sizeof(*id), iue); + + free_coherent_buffer(iue->adapter->dev, sizeof(*id), id, data_token); + + if (bytes < 0) + send_rsp(iue, HARDWARE_ERROR, 0x00); + else + send_rsp(iue, NO_SENSE, 0x00); + + return FREE_IU; +} + +/* + * Handle an I/O. Called by WRITE6, WRITE10, etc + */ +static int process_rw(char *cmd, int rw, struct iu_entry *iue, long lba, + long len) +{ + char *buffer; + struct bio *bio; + int bytes; + int num_biovec; + int cur_biovec; + long flags; + + dbg("%s lba %ld, len %ld\n",cmd,lba,len); + + if (rw == WRITE) + atomic_inc(&iue->adapter->write_processed); + else if (rw == READ) + atomic_inc(&iue->adapter->read_processed); + else { + err("Major internal error...rw not read or write\n"); + send_rsp(iue, HARDWARE_ERROR, 0x00); + return FREE_IU; + } + + if (len == 0) { + warn("Zero length I/O\n"); + send_rsp(iue, ILLEGAL_REQUEST, 0x20); + return FREE_IU; + } + + /* Writing to a read-only device */ + if ((rw == WRITE) && (iue->req.vd->b.ro)) { + warn("WRITE to read-only device\n"); + send_rsp(iue, DATA_PROTECT, 0x27); + return FREE_IU; + } + + iue->req.rw = rw; + iue->req.lba = lba; + iue->req.len = len; + __set_bit(V_PARSED, &iue->req.flags); + + if (bdev_get_queue(iue->req.vd->b.bdev)->max_sectors < (len >> 9)) + return RETRY_SPLIT_BUF; + + get_data_buffer(&buffer, &iue->req.data_token, len, iue->adapter); + iue->req.data_buffer = buffer; + iue->req.data_len = len; + + if (buffer == NULL || dma_mapping_error(iue->req.data_token)) { + err("Not able to get %lu pages for buffer, retrying later\n", + len / PAGE_SIZE); + + return RETRY_SPLIT_BUF; + } + + /* if reladr */ + if (iue->iu->srp.cmd.cdb[1] & 0x01) + lba = lba + iue->req.vd->b.lastlba; + + /* If this command is linked, Keep this lba */ + if (test_bit(V_LINKED, &iue->req.flags)) + iue->req.vd->b.lastlba = lba; + else + iue->req.vd->b.lastlba = 0; + + if (rw == WRITE) { + __set_bit(V_WRITE, &iue->req.flags); + /* Get the data */ + bytes = get_cmd_data(iue->req.data_token, len, iue); + if (bytes != len) { + err("Error transferring data\n"); + free_data_buffer(buffer, iue->req.data_token, len, + iue->adapter); + send_rsp(iue, HARDWARE_ERROR, 0x00); + return FREE_IU; + } + } + + num_biovec = (len - 1) / iue->req.vd->b.blocksize + 1; + + bio = bio_alloc(GFP_KERNEL, num_biovec); + if (!bio) { + err("Not able to allocate a bio, retrying later\n"); + + free_data_buffer(buffer, iue->req.data_token, len, + iue->adapter); + + return RETRY; + } + + if (test_bit(V_ABORTED, &iue->req.flags)) { + spin_lock_irqsave(&iue->adapter->lock, flags); + iue->adapter->next_rsp_delta++; + free_data_buffer(buffer, iue->req.data_token, len, + iue->adapter); + spin_unlock_irqrestore(&iue->adapter->lock, flags); + bio_put(bio); + return FREE_IU; + } + + atomic_inc(&iue->adapter->bio_count); + bio->bi_size = len; + bio->bi_bdev = iue->req.vd->b.bdev; + bio->bi_sector = lba * (iue->req.vd->b.sectsize >> 9); + bio->bi_end_io = &ibmvscsis_end_io; + bio->bi_private = iue; + bio->bi_rw = (rw == WRITE) ? 1 : 0; + bio->bi_rw |= 1 << BIO_RW_SYNC; + bio->bi_phys_segments = 1; + bio->bi_hw_segments = 1; + if (bdev_get_queue(bio->bi_bdev)->ordered != QUEUE_ORDERED_NONE + && test_bit(V_BARRIER, &iue->req.flags)) + bio->bi_rw |= 1 << BIO_RW_BARRIER; + + + /* This all assumes that the buffers we get are page-aligned */ + for (cur_biovec = 0; cur_biovec < num_biovec; cur_biovec++) { + long thislen; + + if (len > iue->req.vd->b.blocksize) + thislen = iue->req.vd->b.blocksize; + else + thislen = len; + + bio->bi_io_vec[cur_biovec].bv_page = virt_to_page(buffer); + bio->bi_io_vec[cur_biovec].bv_len = thislen; + bio->bi_io_vec[cur_biovec].bv_offset = + (unsigned long)buffer & (PAGE_SIZE-1); + bio->bi_vcnt++; + + len -= thislen; + buffer += thislen; + } + generic_make_request(bio); + return INFLIGHT; +} + +/* + * Process a READ6 + */ +static int process_read6(struct iu_entry *iue) +{ + long lba = (*((u32 *) (iue->iu->srp.cmd.cdb))) & 0x001FFFFF; + long len = iue->iu->srp.cmd.cdb[4]; + + /* Length of 0 indicates 256 */ + if (len == 0) + len = 256; + + len = len * iue->req.vd->b.sectsize; + + return process_rw("Read6", READ, iue, lba, len); +} + +/* + * Process a {READ,WRITE}{6,10,12} + */ +static int process_read10(struct iu_entry *iue) +{ + long lba = *((u32 *) (iue->iu->srp.cmd.cdb + 2)); + long len = + *((u16 *) (iue->iu->srp.cmd.cdb + 7)) * iue->req.vd->b.sectsize; + + return process_rw("Read10", READ, iue, lba, len); +} + +static int process_read12(struct iu_entry *iue) +{ + long lba = *((u32 *) (iue->iu->srp.cmd.cdb + 2)); + long len = + *((u32 *) (iue->iu->srp.cmd.cdb + 6)) * iue->req.vd->b.sectsize; + + return process_rw("Read12", READ, iue, lba, len); +} + +static int process_write6(struct iu_entry *iue) +{ + long lba = (*((u32 *) (iue->iu->srp.cmd.cdb))) & 0x001FFFFF; + long len = iue->iu->srp.cmd.cdb[4]; + + /* Length of 0 indicates 256 */ + if (len == 0) + len = 256; + + len = len * iue->req.vd->b.sectsize; + + return process_rw("Write6", WRITE, iue, lba, len); +} + +static int process_write10(struct iu_entry *iue) +{ + long lba = *((u32 *) (iue->iu->srp.cmd.cdb + 2)); + long len = + *((u16 *) (iue->iu->srp.cmd.cdb + 7)) * iue->req.vd->b.sectsize; + + return process_rw("Write10", WRITE, iue, lba, len); +} + +static int process_write12(struct iu_entry *iue) +{ + long lba = *((u32 *) (iue->iu->srp.cmd.cdb + 2)); + long len = + *((u32 *) (iue->iu->srp.cmd.cdb + 6)) * iue->req.vd->b.sectsize; + + return process_rw("Write12", WRITE, iue, lba, len); +} + +/* + * Handle Read Capacity + */ +static int process_read_capacity(struct iu_entry *iue) +{ + struct read_capacity_data { + u32 blocks; + u32 blocksize; + } *cap; + dma_addr_t data_token; + int bytes; + unsigned long flags; + + cap = alloc_coherent_buffer(iue->adapter, sizeof(*cap), &data_token); + + if (cap == NULL) { + err("Not able to get capacity buffer, retrying later\n"); + return RETRY; + } + + /* return block size and last valid block */ + cap->blocksize = iue->req.vd->b.sectsize; + cap->blocks = + iue->req.vd->b.bdev->bd_inode->i_size / cap->blocksize - 1; + + dbg("capacity %ld bytes, %d blocks, %d blocksize\n", + (long)iue->req.vd->b.bdev->bd_inode->i_size, + cap->blocks, + cap->blocksize); + + + if (test_bit(V_ABORTED, &iue->req.flags)) { + spin_lock_irqsave(&iue->adapter->lock, flags); + iue->adapter->next_rsp_delta++; + spin_unlock_irqrestore(&iue->adapter->lock, flags); + free_coherent_buffer(iue->adapter->dev, sizeof(*cap), cap, + data_token); + return FREE_IU; + } + + bytes = send_cmd_data(data_token, sizeof(*cap), iue); + + free_coherent_buffer(iue->adapter->dev, sizeof(*cap), cap, data_token); + + if (bytes != sizeof(*cap)) + err("Error sending read capacity data. bytes %d, wanted %ld\n", + bytes, sizeof(*cap)); + + send_rsp(iue, NO_SENSE, 0x00); + + return FREE_IU; +} + +/* + * Process Mode Sense + */ +static int process_mode_sense(struct iu_entry *iue) +{ + dma_addr_t data_token; + int bytes; + unsigned long flags; + + u8 *mode = alloc_coherent_buffer(iue->adapter, MODE_SENSE_BUFFER_SIZE, + &data_token); + + if (mode == NULL) { + err("Not able to get mode buffer, retrying later\n"); + return RETRY; + } + + /* which page */ + switch (iue->iu->srp.cmd.cdb[2]) { + case 0: + case 0x3f: + mode[1] = 0x00; /* Default medium */ + if (iue->req.vd->b.ro) + mode[2] = 0x80; /* device specific */ + else + mode[2] = 0x00; /* device specific */ + + /* note the DPOFUA bit is set to zero! */ + mode[3] = 0x08; /* block descriptor length */ + *((u32 *) & mode[4]) = + iue->req.vd->b.bdev->bd_inode->i_size + / iue->req.vd->b.sectsize - 1; + + *((u32 *) & mode[8]) = iue->req.vd->b.sectsize; + bytes = mode[0] = 12; /* length */ + break; + + case 0x08: /* Cache page */ + /* length should be 4 */ + if (iue->iu->srp.cmd.cdb[4] != 4 + && iue->iu->srp.cmd.cdb[4] != 0x20) { + send_rsp(iue, ILLEGAL_REQUEST, 0x20); + free_coherent_buffer(iue->adapter->dev, + MODE_SENSE_BUFFER_SIZE, + mode, data_token); + return FREE_IU; + } + + mode[1] = 0x00; /* Default medium */ + if (iue->req.vd->b.ro) + mode[2] = 0x80; /* device specific */ + else + mode[2] = 0x00; /* device specific */ + + /* note the DPOFUA bit is set to zero! */ + mode[3] = 0x08; /* block descriptor length */ + *((u32 *) & mode[4]) = + iue->req.vd->b.bdev->bd_inode->i_size + / iue->req.vd->b.sectsize - 1; + *((u32 *) & mode[8]) = iue->req.vd->b.sectsize; + + /* Cache page */ + mode[12] = 0x08; /* page */ + mode[13] = 0x12; /* page length */ + mode[14] = 0x01; /* no cache (0x04 for read/write cache) */ + + bytes = mode[0] = 12 + mode[13]; /* length */ + break; + default: + warn("Request for unknown mode page %d\n", + iue->iu->srp.cmd.cdb[2]); + send_rsp(iue, ILLEGAL_REQUEST, 0x20); + free_coherent_buffer(iue->adapter->dev, + MODE_SENSE_BUFFER_SIZE, mode, data_token); + return FREE_IU; + } + + if (test_bit(V_ABORTED, &iue->req.flags)) { + spin_lock_irqsave(&iue->adapter->lock, flags); + iue->adapter->next_rsp_delta++; + spin_unlock_irqrestore(&iue->adapter->lock, flags); + free_coherent_buffer(iue->adapter->dev, + MODE_SENSE_BUFFER_SIZE, mode, data_token); + return FREE_IU; + } + + bytes = send_cmd_data(data_token, bytes, iue); + + free_coherent_buffer(iue->adapter->dev, + MODE_SENSE_BUFFER_SIZE, mode, data_token); + + send_rsp(iue, NO_SENSE, 0x00); + + return FREE_IU; +} + +/* + * Report LUNS command. + */ +static int process_reportLUNs(struct iu_entry *iue) +{ + int listsize = vscsis_data_length(&iue->iu->srp.cmd, 0); + dma_addr_t data_token; + int index = 2; /* Start after the two entries (length and LUN0) */ + int bus; + int target; + int bytes; + unsigned long flags; + + u64 *lunlist = alloc_coherent_buffer(iue->adapter, listsize, + &data_token); + + if (lunlist == NULL) { + err("Not able to get lunlist buffer, retrying later\n"); + return RETRY; + } + + memset(lunlist, 0, listsize); + + /* work out list size in units of u64 */ + listsize = listsize / 8; + + if (listsize < 1) { + send_rsp(iue, ILLEGAL_REQUEST, 0x20); + return FREE_IU; + } + + spin_lock_irqsave(&iue->adapter->lock, flags); + + /* send lunlist of size 1 when requesting lun is not all zeros */ + if (iue->iu->srp.cmd.lun != 0x0LL) { + *lunlist = ((u64) 1 * 8) << 32; + goto send_lunlist; + } + + /* return the total number of luns plus LUN0 in bytes */ + *lunlist = (((u64) ((iue->adapter->nvdevs + 1) * 8)) << 32); + + dbg("reporting %d luns\n", iue->adapter->nvdevs + 1); + /* loop through the bus */ + for (bus = 0; bus < BUS_PER_ADAPTER; bus++) { + /* If this bus exists */ + if (!iue->adapter->vbus[bus]) + continue; + /* loop through the targets */ + for (target = 0; target < TARGETS_PER_BUS; target++) { + if (!iue->adapter->vbus[bus]->vdev[target]) + continue; + /* If the target exists */ + if ((index < listsize) && + (!iue->adapter->vbus[bus]-> + vdev[target]->disabled)) { + lunlist[index++] = + iue->adapter->vbus[bus]->vdev[target]->lun; + dbg(" lun %16.16lx\n", + iue->adapter->vbus[bus]->vdev[target]->lun); + } + + } + } + + send_lunlist: + spin_unlock_irqrestore(&iue->adapter->lock, flags); + + if (test_bit(V_ABORTED, &iue->req.flags)) { + spin_lock_irqsave(&iue->adapter->lock, flags); + iue->adapter->next_rsp_delta++; + spin_unlock_irqrestore(&iue->adapter->lock, flags); + free_coherent_buffer(iue->adapter->dev, listsize * 8, lunlist, + data_token); + return FREE_IU; + } + + bytes = send_cmd_data(data_token, (index * 8), iue); + + free_coherent_buffer(iue->adapter->dev, listsize * 8, + lunlist, data_token); + + if (bytes != (index * 8)) { + err("Error sending report luns data. bytes %d, wanted %d\n", + bytes, index * 4); + send_rsp(iue, ABORTED_COMMAND, 0x00); + } else + send_rsp(iue, NO_SENSE, 0x00); + + return FREE_IU; +} + +/* For unrecognized SCSI commands, try passing them + * through + */ +static int try_passthru(struct iu_entry *iue) +{ + request_queue_t *q = bdev_get_queue(iue->req.vd->b.bdev); + struct request *rq; + char *buffer; + int dodlen = vscsis_data_length(&iue->iu->srp.cmd, 1); + int didlen = vscsis_data_length(&iue->iu->srp.cmd, 0); + int bytes, len, rw; + int err = 0; + + if (dodlen && didlen) + return -EIO; + + if (dodlen) + rw = WRITE; + else + rw = READ; + + len = dodlen + didlen; + + if (len) { + get_data_buffer(&buffer, &iue->req.data_token, len, iue->adapter); + if (!buffer) { + err("Unable to get data buffer of len %d\n",len); + return -ENOMEM; + } + + if (dodlen) { + bytes = get_cmd_data(iue->req.data_token, len, iue); + if (bytes != len) { + err("Error transferring data\n"); + free_data_buffer(buffer, + iue->req.data_token, + len, + iue->adapter); + return -ENOMEM; + } + } + } else + buffer = NULL; + + rq = blk_get_request(q, rw, __GFP_WAIT); + rq->flags |= REQ_BLOCK_PC; + rq->data = buffer; + rq->data_len = len; + rq->timeout = iue->req.timeout; + + memcpy(rq->cmd, iue->iu->srp.cmd.cdb, BLK_MAX_CDB); + err = blk_execute_rq(q, iue->req.vd->b.bdev->bd_disk, rq); + blk_put_request(rq); + if ((err == 0) && (rw == READ) && (len)) { + bytes = send_cmd_data(iue->req.data_token, + iue->req.data_len, + iue); + if (bytes != iue->req.data_len) { + err("Error sending data " + "on response " + "(tried %ld, sent %d\n", + iue->req.data_len, bytes); + free_data_buffer(buffer, + iue->req.data_token, + len, + iue->adapter); + err = -EIO; + } + } + + if (buffer) + free_data_buffer(buffer, + iue->req.data_token, + len, + iue->adapter); + + return err; +} + +static void reset_changed(struct iu_entry *iue) +{ + if (iue->req.vd->b.changed) { + bd_set_size(iue->req.vd->b.bdev, + (loff_t)get_capacity(iue->req.vd->b.bdev->bd_disk) + <<9); + iue->req.vd->b.changed = 0; + } +} + +/* + * Process an IU when the target is a block device + */ +static int process_cmd_block(struct iu_entry *iue) +{ + union viosrp_iu *iu = iue->iu; + unsigned long flags; + + if (test_bit(V_PARSED, &iue->req.flags)) + return process_rw("pre-parsed", iue->req.rw, iue, iue->req.lba, + iue->req.len); + + if (iu->srp.cmd.cdb[0] == INQUIRY) { + dbg("INQUIRY lun %16.16lx\n", iue->iu->srp.cmd.lun); + return process_inquiry(iue); + } + + if (iue->req.vd && + iue->req.vd->b.removable && + check_disk_change(iue->req.vd->b.bdev)) { + if (iue->req.vd->b.changed) { + dbg("Media changed not ready!...cmd 0x%2.2x\n", + iu->srp.cmd.cdb[0]); + send_rsp(iue, NOT_READY, 0x3a); + return FREE_IU; + } + iue->req.vd->b.changed = 1; + dbg("Media changed attention!...cmd 0x%2.2x\n", + iu->srp.cmd.cdb[0]); + send_rsp(iue, UNIT_ATTENTION, 0x3a); + return FREE_IU; + } + + switch (iu->srp.cmd.cdb[0]) { + case REPORT_LUNS: + dbg("REPORT LUNS lun %16.16lx\n", iue->iu->srp.cmd.lun); + return process_reportLUNs(iue); + case READ_CAPACITY: + dbg("READ CAPACITY lun %16.16lx\n", iue->iu->srp.cmd.lun); + return process_read_capacity(iue); + case MODE_SENSE: + dbg("MODE SENSE lun %16.16lx\n", iue->iu->srp.cmd.lun); + return process_mode_sense(iue); + case TEST_UNIT_READY: + /* we already know the device exists */ + dbg("TEST UNIT READY lun %16.16lx\n", iue->iu->srp.cmd.lun); + if (!test_bit(V_ABORTED, &iue->req.flags)) { + reset_changed(iue); + send_rsp(iue, NO_SENSE, 0x00); + } + else { + spin_lock_irqsave(&iue->adapter->lock, flags); + iue->adapter->next_rsp_delta++; + spin_unlock_irqrestore(&iue->adapter->lock, flags); + } + return FREE_IU; + case START_STOP: + dbg("START_STOP lun %16.16lx\n", iue->iu->srp.cmd.lun); + + if (!test_bit(V_ABORTED, &iue->req.flags)) { + reset_changed(iue); + if ((iu->srp.cmd.cdb[5] & 0x03) == 0x02) { + /* Unload! */ + if (ioctl_by_bdev(iue->req.vd->b.bdev, + CDROMEJECT, 0) == 0) + send_rsp(iue, NO_SENSE, 0x00); + else + send_rsp(iue, HARDWARE_ERROR, 0x00); + } else if ((iu->srp.cmd.cdb[4] & 0x03) == 0x03) { + iue->req.vd->b.changed = 0; + if (ioctl_by_bdev(iue->req.vd->b.bdev, + CDROMCLOSETRAY, 0) == 0) + send_rsp(iue, NO_SENSE, 0x00); + else + send_rsp(iue, HARDWARE_ERROR, 0x00); + } else + send_rsp(iue, NO_SENSE, 0x00); + } else { + spin_lock_irqsave(&iue->adapter->lock, flags); + iue->adapter->next_rsp_delta++; + spin_unlock_irqrestore(&iue->adapter->lock, flags); + } + return FREE_IU; + case READ_6: + return process_read6(iue); + case READ_10: + return process_read10(iue); + case READ_12: + return process_read12(iue); + case WRITE_6: + return process_write6(iue); + case WRITE_10: + case WRITE_VERIFY: + return process_write10(iue); + case WRITE_12: + case WRITE_VERIFY_12: + return process_write12(iue); + default: + dbg("removable unknown command 0x%2.2x\n`",iu->srp.cmd.cdb[0]); + if (try_passthru(iue) == 0) { + dbg("Successfully passed through command 0x%2.2x!\n", + iu->srp.cmd.cdb[0]); + send_rsp(iue, NO_SENSE, 0x00); + return FREE_IU; + } + + dbg("Unsupported SCSI Command 0x%2.2x\n", iu->srp.cmd.cdb[0]); + + if (!test_bit(V_ABORTED, &iue->req.flags)) + send_rsp(iue, ILLEGAL_REQUEST, 0x20); + else { + spin_lock_irqsave(&iue->adapter->lock, flags); + iue->adapter->next_rsp_delta++; + spin_unlock_irqrestore(&iue->adapter->lock, flags); + } + return FREE_IU; + } +} + +/* ============================================================== + * SCSI Redirection Routines + * ============================================================== + */ +/* + * Callback when the scsi command issued by process_cmd_scsi() is completed + */ +static void scsi_cmd_done(struct scsi_cmnd *cmd) +{ + struct iu_entry *iue = (struct iu_entry*)cmd->sc_request-> + upper_private_data; + struct server_adapter *adapter = iue->adapter; + unsigned long flags; + int bytes; + + dbg("scsi_cmd_done got cmd %p iue %p\n", cmd, iue); + + spin_lock_irqsave(&adapter->lock, flags); + list_del(&iue->next); + spin_unlock_irqrestore(&adapter->lock, flags); + + if (test_bit(V_ABORTED, &iue->req.flags)) { + dbg("scsi_cmd_done: aborted tag %16.16x\n", cmd->tag); + spin_lock_irqsave(&iue->adapter->lock, flags); + iue->adapter->next_rsp_delta++; + spin_unlock_irqrestore(&iue->adapter->lock, flags); + goto out; + } + + if(!test_bit(V_WRITE, &iue->req.flags)) { + bytes = send_cmd_data(iue->req.data_token, + iue->req.data_len, iue); + if(bytes != iue->req.data_len) { + err("Error sending data on response (%ld, sent %d)\n", + iue->req.data_len, bytes); + send_rsp(iue, ABORTED_COMMAND, 0x00); + goto out; + } + } + + if (cmd->result) + iue->req.sense = cmd->sense_buffer; + + send_rsp(iue, cmd->result, 0x00); + +out: scsi_release_request(iue->req.sreq); + if (iue->req.data_len) { + free_data_buffer(iue->req.data_buffer, iue->req.data_token, + iue->req.data_len, adapter); + } + spin_lock_irqsave(&adapter->lock, flags); + free_iu(iue); + spin_unlock_irqrestore(&adapter->lock, flags); +} + +/* + * Process an IU when the target is a scsi device + */ +static int process_cmd_scsi(struct iu_entry *iue) +{ + union viosrp_iu *iu = iue->iu; + struct scsi_request *req; + char *buffer; + int len = 0; + + dbg("%x %x %16.16lx[%d:%d:%d][%s] link %d iue %p\n", + iu->srp.cmd.cdb[0], + iu->srp.cmd.cdb[1], + iue->iu->srp.cmd.lun, + GETBUS(iue->iu->srp.cmd.lun), + GETTARGET(iue->iu->srp.cmd.lun), + GETLUN(iue->iu->srp.cmd.lun), + iue->req.vd->device_name, + test_bit(V_LINKED, &iue->req.flags), iue); + + req = scsi_allocate_request(iue->req.vd->s.sdev, GFP_KERNEL); + if (req == NULL) { + err("Not able to get scsi_request, retrying later\n"); + return RETRY; + } + + memcpy(req->sr_cmnd, iu->srp.cmd.cdb, sizeof(iu->srp.cmd.cdb)); + + req->sr_cmd_len = sizeof(iu->srp.cmd.cdb); + if (iu->srp.cmd.data_out_format && iu->srp.cmd.data_in_format) { + err("Don't support bidirectional buffers yet\n"); + send_rsp(iue, ABORTED_COMMAND, 0x00); + scsi_release_request(req); + return FREE_IU; + } else if (iu->srp.cmd.data_out_format) { /* write */ + atomic_inc(&iue->adapter->write_processed); + req->sr_data_direction = DMA_TO_DEVICE; + len = vscsis_data_length(&iue->iu->srp.cmd, 1); + __set_bit(V_WRITE, &iue->req.flags); + if (iue->req.vd->b.ro) { + warn("WRITE to read-only device\n"); + send_rsp(iue, DATA_PROTECT, 0x27); + scsi_release_request(req); + return FREE_IU; + } + } else if (iu->srp.cmd.data_in_format) { /* read */ + atomic_inc(&iue->adapter->read_processed); + req->sr_data_direction = DMA_FROM_DEVICE; + len = vscsis_data_length(&iue->iu->srp.cmd, 0); + } else { + dbg("No buffer command\n"); + req->sr_data_direction = DMA_NONE; + goto nobuf; + } + + get_data_buffer(&buffer, &iue->req.data_token, len, iue->adapter); + iue->req.data_buffer = buffer; + iue->req.data_len = len; + + if (test_bit(V_WRITE, &iue->req.flags)) { + int bytes = get_cmd_data(iue->req.data_token, len, iue); + + if (bytes != len) { + err("Error transferring data\n"); + free_data_buffer(buffer, iue->req.data_token, len, + iue->adapter); + scsi_release_request(req); + send_rsp(iue, HARDWARE_ERROR, 0x00); + return FREE_IU; + } + } + +nobuf: req->sr_use_sg = 0; + req->sr_bufflen = len; + req->sr_buffer = buffer; + req->sr_sense_buffer[0] = 0; + req->sr_request->flags = + test_bit(V_BARRIER, &iue->req.flags) ? REQ_HARDBARRIER : 0; + req->upper_private_data = (void*)iue; + iue->req.sreq = req; + dbg("sending %s of %d bytes, buffer %p, timeout=%d\n", + test_bit(V_WRITE, &iue->req.flags) ? "write" : "read", len, buffer, + iue->req.timeout); + + scsi_do_req(req, iu->srp.cmd.cdb, buffer, len, scsi_cmd_done, + iue->req.timeout, 3); + + return INFLIGHT; + +} + +/* ============================================================== + * SRP Processing Routines + * ============================================================== + */ +/* + * Process an incoming SRP Login request + */ +static void process_login(struct iu_entry *iue) +{ + union viosrp_iu *iu = iue->iu; + u64 tag = iu->srp.generic.tag; + + /* TODO handle case that requested size is wrong and + * buffer format is wrong + */ + memset(iu, 0, sizeof(struct srp_login_rsp)); + iu->srp.login_rsp.type = SRP_LOGIN_RSP_TYPE; + iu->srp.login_rsp.request_limit_delta = INITIAL_SRP_LIMIT; + iu->srp.login_rsp.tag = tag; + iu->srp.login_rsp.max_initiator_to_target_iulen = sizeof(union srp_iu); + iu->srp.login_rsp.max_target_to_initiator_iulen = sizeof(union srp_iu); + iu->srp.login_rsp.supported_buffer_formats = 0x0006; /* direct and indirect */ + iu->srp.login_rsp.multi_channel_result = 0x00; /* TODO fix if we were already logged in */ + + send_iu(iue, sizeof(iu->srp.login_rsp), VIOSRP_SRP_FORMAT); +} + +/* + * Process an incoming device_reset request + */ +static void process_device_reset(struct iu_entry *iue) +{ + struct iu_entry *tmp_iue; + unsigned long flags; + union viosrp_iu *iu = iue->iu; + u64 lun = iu->srp.tsk_mgmt.lun; + + info("device reset for lun %16.16lx\n", lun); + + spin_lock_irqsave(&iue->adapter->lock, flags); + + list_for_each_entry(tmp_iue, &iue->adapter->cmd_queue, next) + if (tmp_iue->iu->srp.cmd.lun == lun) + __set_bit(V_ABORTED, &tmp_iue->req.flags); + + spin_unlock_irqrestore(&iue->adapter->lock, flags); + send_rsp(iue, NO_SENSE, 0x00); +} + +/* + * Process an incoming abort request + */ +static void process_abort(struct iu_entry *iue) +{ + struct iu_entry *tmp_iue; + unsigned long flags; + union viosrp_iu *iu = iue->iu; + u64 tag = iu->srp.tsk_mgmt.managed_task_tag; + unsigned char status = ABORTED_COMMAND; + + info("aborting task with tag %16.16lx, lun %16.16lx\n", + tag, iu->srp.tsk_mgmt.lun); + + spin_lock_irqsave(&iue->adapter->lock, flags); + + list_for_each_entry(tmp_iue, &iue->adapter->cmd_queue, next) { + if (tmp_iue->iu->srp.cmd.tag != tag) + continue; + + __set_bit(V_ABORTED, &tmp_iue->req.flags); + status = NO_SENSE; + break; + } + + spin_unlock_irqrestore(&iue->adapter->lock, flags); + + if (status == NO_SENSE) + info("abort successful\n"); + else + info("unable to abort cmd\n"); + + send_rsp(iue, status, 0x14); +} + +/* + * Process an incoming task management request + */ +static void process_tsk_mgmt(struct iu_entry *iue) +{ + union viosrp_iu *iu = iue->iu; + + if (iu->srp.tsk_mgmt.task_mgmt_flags == 0x01) + process_abort(iue); + else if (iu->srp.tsk_mgmt.task_mgmt_flags == 0x08) + process_device_reset(iue); + else + send_rsp(iue, ILLEGAL_REQUEST, 0x20); +} + +/* + * Process an incoming SRP command + */ +static int process_cmd(struct iu_entry *iue) +{ + union viosrp_iu *iu = iue->iu; + + if (!test_bit(V_PARSED, &iue->req.flags)) + iue->req.vd = find_vscsis_vdev(iue); + + if ((iue->req.vd == NULL) && + (iu->srp.cmd.cdb[0] != REPORT_LUNS) && + (iu->srp.cmd.cdb[0] != INQUIRY)) { + dbg("Cmd %2.2x for unknown LUN %16.16lx\n", + iu->srp.cmd.cdb[0], iue->iu->srp.cmd.lun); + send_rsp(iue, ABORTED_COMMAND, 0x14); + return FREE_IU; + } + + if (getlink(iue)) + __set_bit(V_LINKED, &iue->req.flags); + + switch (iu->srp.cmd.task_attribute) { + case SRP_ORDERED_TASK: + __set_bit(V_BARRIER, &iue->req.flags); + case SRP_SIMPLE_TASK: + break; + default: + __set_bit(V_BARRIER, &iue->req.flags); + warn("Task attribute %d not supported, assuming barrier\n", + iu->srp.cmd.task_attribute); + } + + if (!iue->req.vd || !iue->req.vd->direct_scsi) + return process_cmd_block(iue); + else + return process_cmd_scsi(iue); +} + +/* + * Respond to the adapter_info request + */ +u16 send_adapter_info(struct iu_entry *iue, + dma_addr_t remote_buffer, u16 length) +{ + dma_addr_t data_token; + struct mad_adapter_info_data *info = + alloc_coherent_buffer(iue->adapter, sizeof(*info), &data_token); + + dbg("in send_adapter_info\n "); + if (info != NULL) { + int rc; + + /* Get remote info */ + rc = h_copy_rdma(sizeof(*info), + iue->adapter->riobn, + remote_buffer, + iue->adapter->liobn, + data_token); + if (rc == H_Success) { + info("Client connect: %s (%d)\n", + info->partition_name, + info->partition_number); + } + + memset(info, 0, sizeof(*info)); + + dbg("building adapter_info\n "); + strcpy(info->srp_version, "16.a"); + strncpy(info->partition_name, partition_name, + sizeof(info->partition_name)); + info->partition_number = partition_number; + info->mad_version = 1; + info->os_type = 2; + info->port_max_txu[0] = iue->adapter->max_sectors << 9; + + rc = h_copy_rdma(sizeof(*info), + iue->adapter->liobn, + data_token, + iue->adapter->riobn, + remote_buffer); + + free_coherent_buffer(iue->adapter->dev, + sizeof(*info), info, data_token); + + if (rc != H_Success) { + err("Error sending adapter info rc %d\n",rc); + return 1; + } + } else { + dbg("bad dma_alloc_coherent in adapter_info\n "); + return 1; + } + return 0; + +} + +/* + * Process our queue of incoming commands + */ +static void run_cmd_queue(struct server_adapter *adapter) +{ + struct iu_entry *curr_iue; + struct list_head *next = NULL; + unsigned long flags; + spin_lock_irqsave(&adapter->lock, flags); + + next = list_empty(&adapter->cmd_queue) ? NULL : adapter->cmd_queue.next; + while (next) { + curr_iue = list_entry(next, struct iu_entry, next); + next = next->next == &adapter->cmd_queue ? NULL : next->next; + if (test_bit(V_FLYING, &curr_iue->req.flags)) { + if (test_bit(V_DONE, &curr_iue->req.flags)) { + list_del(&curr_iue->next); + free_iu(curr_iue); + } + continue; + } + if (test_bit(V_ABORTED, &curr_iue->req.flags)) { + adapter->next_rsp_delta++; + list_del(&curr_iue->next); + free_iu(curr_iue); + } else { + int rc; + __set_bit(V_FLYING, &curr_iue->req.flags); + spin_unlock_irqrestore(&adapter->lock, flags); + dbg("process_cmd sending %p\n", curr_iue); + rc = process_cmd(curr_iue); + spin_lock_irqsave(&adapter->lock, flags); + + /* if the iue is not in any list, we're racing with + endio, so we lost the cmd_queue */ + if (curr_iue->next.next == LIST_POISON1) + goto out; + + next = curr_iue->next.next == &adapter->cmd_queue + ? NULL : curr_iue->next.next; + + switch (rc) { + case FREE_IU: + list_del(&curr_iue->next); + free_iu(curr_iue); + break; + case INFLIGHT: + if (!test_bit(V_IN_USE, &curr_iue->req.flags)) + /* this means that the request finished + before process_cmd() returned, so we + lost a handle of the cmd_queue list */ + goto out; + break; + case RETRY_SPLIT_BUF: + if (!split_iu(curr_iue)) { + list_add(&curr_iue->req.child[1]->next, + &curr_iue->next); + list_add(&curr_iue->req.child[0]->next, + &curr_iue->next); + next = curr_iue->next.next; + break; + } + case RETRY: + __clear_bit(V_FLYING, &curr_iue->req.flags); + kblockd_schedule_work(&adapter->crq_task); + + /* if a barrier fails, we don't want anything + new to go through, retry when new cmd arrives + or when workqueue runs */ + if (test_bit(V_BARRIER, &curr_iue->req.flags)) + goto out; + break; + default: + err("Invalid return code %i from process_cmd\n", + rc); + } + } + } + +out: + spin_unlock_irqrestore(&adapter->lock, flags); +} + +/* + * Process an incoming information unit. + */ +static void process_iu(struct viosrp_crq *crq, struct server_adapter *adapter) +{ + struct iu_entry *iue = get_iu(adapter); + union viosrp_iu *iu; + long rc; + unsigned long flags; + + if (iue == NULL) { + warn("Error getting IU from pool, other side exceeded limit\n"); + return; + } + + iue->req.remote_token = crq->IU_data_ptr; + iue->req.timeout= crq->timeout ? crq->timeout*HZ : DEFAULT_TIMEOUT; + + rc = h_copy_rdma(crq->IU_length, + iue->adapter->riobn, + iue->req.remote_token, adapter->liobn, iue->iu_token); + + iu = iue->iu; + + if (rc) { + err("process_iu: Error %ld transferring data from client\n", + rc); + } + + if (crq->format == VIOSRP_MAD_FORMAT) { + switch (iu->mad.empty_iu.common.type) { + case VIOSRP_EMPTY_IU_TYPE: + warn("Unsupported EMPTY MAD IU\n"); + break; + case VIOSRP_ERROR_LOG_TYPE: + warn("Unsupported ERROR LOG MAD IU\n"); + iu->mad.error_log.common.status = 1; + send_iu(iue, sizeof(iu->mad.error_log), + VIOSRP_MAD_FORMAT); + break; + case VIOSRP_ADAPTER_INFO_TYPE: + iu->mad.adapter_info.common.status = + send_adapter_info(iue, + iu->mad.adapter_info.buffer, + iu->mad.adapter_info.common. + length); + + send_iu(iue, sizeof(iu->mad.adapter_info), + VIOSRP_MAD_FORMAT); + break; + case VIOSRP_HOST_CONFIG_TYPE: + iu->mad.host_config.common.status = 1; + send_iu(iue, sizeof(iu->mad.host_config), + VIOSRP_MAD_FORMAT); + break; + default: + warn("Unsupported MAD type %d\n", iu->srp.generic.type); + } + } else { + switch (iu->srp.generic.type) { + case SRP_LOGIN_REQ_TYPE: + dbg("SRP LOGIN\n"); + process_login(iue); + break; + case SRP_LOGIN_RSP_TYPE: + warn("Unsupported LOGIN_RSP SRP IU\n"); + break; + case SRP_I_LOGOUT_TYPE: + warn("Unsupported I_LOGOUT SRP IU\n"); + break; + case SRP_T_LOGOUT_TYPE: + warn("Unsupported T_LOGOUT SRP IU\n"); + break; + case SRP_TSK_MGMT_TYPE: + process_tsk_mgmt(iue); + break; + case SRP_CMD_TYPE: + spin_lock_irqsave(&iue->adapter->lock, flags); + list_add_tail(&iue->next, &adapter->cmd_queue); + spin_unlock_irqrestore(&iue->adapter->lock, flags); + run_cmd_queue(adapter); + return; + break; + case SRP_RSP_TYPE: + warn("Unsupported RSP SRP IU\n"); + break; + case SRP_CRED_REQ_TYPE: + warn("Unsupported CRED_REQ SRP IU\n"); + break; + case SRP_CRED_RSP_TYPE: + warn("Unsupported CRED_RSP SRP IU\n"); + break; + case SRP_AER_REQ_TYPE: + warn("Unsupported AER_REQ SRP IU\n"); + break; + case SRP_AER_RSP_TYPE: + warn("Unsupported AER_RSP SRP IU\n"); + break; + default: + warn("Unsupported SRP type %d\n", iu->srp.generic.type); + } + } + + spin_lock_irqsave(&iue->adapter->lock, flags); + free_iu(iue); + spin_unlock_irqrestore(&iue->adapter->lock, flags); +} + +/* ============================================================== + * CRQ Processing Routines + * ============================================================== + */ + +/* + * Handle a CRQ event + */ +static void handle_crq(struct viosrp_crq *crq, struct server_adapter *adapter) +{ + switch (crq->valid) { + case 0xC0: /* initialization */ + switch (crq->format) { + case 0x01: + h_send_crq(adapter->dma_dev->unit_address, + 0xC002000000000000, 0); + break; + case 0x02: + break; + default: + err("Client error: Unknwn msg format %d\n", + crq->format); + } + return; + case 0xFF: /* transport event */ + return; + case 0x80: /* real payload */ + { + switch (crq->format) { + case VIOSRP_SRP_FORMAT: + case VIOSRP_MAD_FORMAT: + process_iu(crq, adapter); + break; + case VIOSRP_OS400_FORMAT: + warn("Unsupported OS400 format CRQ\n"); + break; + + case VIOSRP_AIX_FORMAT: + warn("Unsupported AIX format CRQ\n"); + break; + + case VIOSRP_LINUX_FORMAT: + warn("Unsupported LINUX format CRQ\n"); + break; + + case VIOSRP_INLINE_FORMAT: + warn("Unsupported _INLINE_ format CRQ\n"); + break; + + default: + err("Client error: Unsupported msg format %d\n", + crq->format); + } + } + break; + default: + err("Client error: unknown message type 0x%02x!?\n", + crq->valid); + return; + } + +} + +/* + * Task to handle CRQs + */ +static void crq_task(void *data) +{ + struct server_adapter *adapter = (struct server_adapter *)data; + struct viosrp_crq *crq; + int done = 0; + + while (!done) { + + /* Loop through and process CRQs */ + while ((crq = crq_queue_next_crq(&adapter->queue)) != NULL) { + atomic_inc(&adapter->crq_processed); + handle_crq(crq, adapter); + crq->valid = 0x00; + } + + vio_enable_interrupts(adapter->dma_dev); + if ((crq = crq_queue_next_crq(&adapter->queue)) != NULL) { + vio_disable_interrupts(adapter->dma_dev); + handle_crq(crq, adapter); + crq->valid = 0x00; + } else + done = 1; + } + run_cmd_queue(adapter); +} + +/* + * Handle the interrupt that occurs when something is placed on our CRQ + */ +static irqreturn_t handle_interrupt(int irq, void *dev_instance, + struct pt_regs *regs) +{ + struct server_adapter *adapter = (struct server_adapter *)dev_instance; + + vio_disable_interrupts(adapter->dma_dev); + + atomic_inc(&adapter->interrupts); + + kblockd_schedule_work(&adapter->crq_task); + + return IRQ_HANDLED; +} + +/* + * Initialize our CRQ + * return zero on success, non-zero on failure + */ +static int initialize_crq_queue(struct crq_queue *queue, + struct server_adapter *adapter) +{ + int rc; + + queue->msgs = (struct viosrp_crq *)get_zeroed_page(GFP_KERNEL); + if (!queue->msgs) + goto malloc_failed; + queue->size = PAGE_SIZE / sizeof(*queue->msgs); + + queue->msg_token = dma_map_single(adapter->dev, queue->msgs, + queue->size * sizeof(*queue->msgs), + DMA_BIDIRECTIONAL); + + if (dma_mapping_error(queue->msg_token)) + goto map_failed; + + rc = h_reg_crq(adapter->dma_dev->unit_address, queue->msg_token, + PAGE_SIZE); + + if ((rc != H_Success) && (rc != 2)) { + err("Error 0x%x opening virtual adapter\n", rc); + goto reg_crq_failed; + } + + if (request_irq + (adapter->dma_dev->irq, &handle_interrupt, SA_INTERRUPT, + "ibmvscsis", adapter) != 0) + goto req_irq_failed; + + vio_enable_interrupts(adapter->dma_dev); + + h_send_crq(adapter->dma_dev->unit_address, 0xC001000000000000, 0); + + queue->cur = 0; + queue->lock = SPIN_LOCK_UNLOCKED; + + return 0; + + req_irq_failed: + do { + rc = h_free_crq(adapter->dma_dev->unit_address); + } while ((rc == H_Busy) || (H_isLongBusy(rc))); + + reg_crq_failed: + dma_unmap_single(adapter->dev, queue->msg_token, + queue->size * sizeof(*queue->msgs), DMA_BIDIRECTIONAL); + map_failed: + free_page((unsigned long)queue->msgs); + malloc_failed: + return -ENOMEM; +} + +/* + * Release the CRQ + */ +static void release_crq_queue(struct crq_queue *queue, + struct server_adapter *adapter) +{ + int rc; + + info("releasing adapter\n"); + free_irq(adapter->dma_dev->irq, adapter); + do { + rc = h_free_crq(adapter->dma_dev->unit_address); + } while ((rc == H_Busy) || (H_isLongBusy(rc))); + dma_unmap_single(adapter->dev, queue->msg_token, + queue->size * sizeof(*queue->msgs), DMA_BIDIRECTIONAL); + free_page((unsigned long)queue->msgs); +} + +/* ============================================================== + * Shared Device Management + * ============================================================== + */ +/* + * Add a block device as a SCSI LUN + */ +static int activate_device(struct vdev *vdev) +{ + struct block_device *bdev; + char *name = vdev->device_name; + int ro = vdev->b.ro; + unsigned long flags; + struct scsi_dev_node *tmp_sdn; + + bdev = open_bdev_excl(name, ro, activate_device); + if (IS_ERR(bdev)) + return PTR_ERR(bdev);; + + spin_lock_irqsave(&sdev_list_lock, flags); + list_for_each_entry(tmp_sdn, &scsi_dev_list, node) { + struct scsi_device *sdev = tmp_sdn->sdev; + /* if the block device is a known scsi_device and + device is not a partition */ + if (sdev->request_queue == bdev->bd_disk->queue && + bdev == bdev->bd_contains) { + vdev->s.sdev = sdev; + tmp_sdn->vdev = vdev; + spin_unlock_irqrestore(&sdev_list_lock, flags); + close_bdev_excl(bdev); + vdev->direct_scsi = (char)1; + vdev->disabled = 0; + info("Activating %s (scsi %d:%d:%d:%d) as LUN 0x%lx\n", + name, sdev->host->host_no, sdev->channel, + sdev->id, sdev->lun, vdev->lun); + return 0; + } + } + spin_unlock_irqrestore(&sdev_list_lock, flags); + + vdev->direct_scsi = 0; + vdev->b.bdev = bdev; + vdev->disabled = 0; + vdev->b.sectsize = bdev_hardsect_size(bdev); + vdev->b.blocksize = bdev->bd_block_size; + if (bdev->bd_disk->flags & GENHD_FL_CD) + vdev->b.scsi_type = TYPE_ROM; /* CD/DVD */ + else + vdev->b.scsi_type = TYPE_DISK; /* disk */ + + if (bdev->bd_disk->flags & GENHD_FL_REMOVABLE) { + vdev->b.removable = 1; /* rmb bit of inquiry */ + vdev->b.changed = 1; + } else + vdev->b.removable = 0; + + info("Activating block device %s as %s %s LUN 0x%lx sector size %ld\n", + name, ro ? "read only " : "", + vdev->b.scsi_type ? "CD" : "disk", vdev->lun, + vdev->b.sectsize); + + return 0; +} + +static void deactivate_scsi_device(struct vdev *vdev) +{ + struct scsi_dev_node *tmp_sdn; + + vdev->disabled = 1; + vdev->s.sdev = NULL; + + list_for_each_entry(tmp_sdn, &scsi_dev_list, node) + if (tmp_sdn->vdev == vdev) + tmp_sdn->vdev = NULL; +} + +static void deactivate_device(struct vdev *vdev) +{ + info("Deactivating block device, LUN 0x%lx\n", vdev->lun); + + /* Wait while any users of this device finish. Note there should + * be no new users, since we have marked this disabled + * + * We just poll here, since we are blocking write + */ + while (atomic_read(&vdev->refcount)) { + msleep(REFCOUNT_TIMEOUT_MS); + } + + vdev->disabled = 1; + + if (!vdev->direct_scsi) + close_bdev_excl(vdev->b.bdev); + else + deactivate_scsi_device(vdev); +} + +/* + * Callback when a scsi_device gets added to the system + */ +static int add_scsi_device(struct class_device *cdev) +{ + struct scsi_device *sdev = to_scsi_device(cdev->dev); + struct scsi_dev_node * sdevnode = + kmalloc(sizeof(struct scsi_dev_node), GFP_ATOMIC); + unsigned long flags; + + dbg("add_scsi_device got %p, %d:%d:%d:%d, sdn=%p\n", sdev, + sdev->host->host_no, sdev->channel, sdev->id, sdev->lun, sdevnode); + + sdevnode->sdev = sdev; + sdevnode->vdev = NULL; + + spin_lock_irqsave(&sdev_list_lock, flags); + list_add_tail(&sdevnode->node, &scsi_dev_list); + spin_unlock_irqrestore(&sdev_list_lock, flags); + return 0; +} + +/* + * Callback when a scsi_device gets removed from the system + */ +static void rem_scsi_device(struct class_device *cdev) +{ + struct scsi_dev_node *tmp_sdn; + struct scsi_device *sdev = to_scsi_device(cdev->dev); + unsigned long flags; + + spin_lock_irqsave(&sdev_list_lock, flags); + list_for_each_entry(tmp_sdn, &scsi_dev_list, node) { + if (sdev == tmp_sdn->sdev) { + if (tmp_sdn->vdev && !tmp_sdn->vdev->disabled) + deactivate_scsi_device(tmp_sdn->vdev); + list_del(&tmp_sdn->node); + kfree(tmp_sdn); + goto out; + } + } + + warn("rem_scsi_device: Couldn't find scsi_device %p %d:%d:%d:%d\n", + sdev, sdev->host->host_no, sdev->channel, sdev->id, sdev->lun); +out: spin_unlock_irqrestore(&sdev_list_lock, flags); + return; +} + +/* ============================================================== + * SYSFS Routines + * ============================================================== + */ +static struct class_interface vscsis_interface = { + .add = add_scsi_device, + .remove = rem_scsi_device, +}; + +static struct kobj_type ktype_vscsi_target; +static struct kobj_type ktype_vscsi_bus; +static struct kobj_type ktype_vscsi_stats; + +static void vscsi_target_release(struct kobject *kobj) { + struct vdev *tmpdev = + container_of(kobj,struct vdev,kobj); + kfree(tmpdev); +} + +static void vscsi_bus_release(struct kobject *kobj) { + struct vbus *tmpbus = + container_of(kobj,struct vbus,kobj); + kfree(tmpbus); +} + +static void set_num_targets(struct vbus* vbus, long value) +{ + struct device *dev = + container_of(vbus->kobj.parent, struct device , kobj); + struct server_adapter *adapter = + (struct server_adapter *)dev->driver_data; + int cur_num_targets = atomic_read(&vbus->num_targets); + unsigned long flags; + struct vdev *tmpdev; + + /* Growing */ + if (cur_num_targets < value) { + int i; + for (i = cur_num_targets; i < value; i++) { + tmpdev = (struct vdev *)kmalloc(sizeof(struct vdev), + GFP_KERNEL); + if (!tmpdev) { + err("Couldn't allocate target memory %d\n", i); + return; + } + memset(tmpdev, 0, sizeof(struct vdev)); + + tmpdev->lun = make_lun(vbus->bus_num, i, 0); + tmpdev->b.blocksize = PAGE_CACHE_SIZE; + tmpdev->b.sectsize = 512; + tmpdev->disabled = 1; + + tmpdev->kobj.parent = &vbus->kobj; + sprintf(tmpdev->kobj.name, "target%d", i); + tmpdev->kobj.ktype = &ktype_vscsi_target; + kobject_register(&tmpdev->kobj); + + spin_lock_irqsave(&adapter->lock, flags); + if (vbus->vdev[i]) { + /* Race!!! */ + spin_unlock_irqrestore(&adapter->lock, flags); + kobject_unregister(&tmpdev->kobj); + continue; + } + + adapter->nvdevs++; + atomic_inc(&vbus->num_targets); + vbus->vdev[i] = tmpdev; + spin_unlock_irqrestore(&adapter->lock, flags); + } + } else { /* shrinking */ + int i; + for (i = cur_num_targets - 1; i >= value; i--) + { + if (!vbus->vdev[i]->disabled) { + err("Can't remove active target %d\n", i); + return; + } + + spin_lock_irqsave(&adapter->lock, flags); + tmpdev = vbus->vdev[i]; + vbus->vdev[i] = NULL; + spin_unlock_irqrestore(&adapter->lock, flags); + + if (tmpdev) + kobject_unregister(&tmpdev->kobj); + + adapter->nvdevs--; + atomic_dec(&vbus->num_targets); + } + } +} + +static void set_num_buses(struct device *dev, long value) +{ + struct server_adapter *adapter = + (struct server_adapter *)dev->driver_data; + int cur_num_buses = atomic_read(&adapter->num_buses); + unsigned long flags; + struct vbus *tmpbus; + + if (cur_num_buses < value) { /* growing */ + int i; + for (i = cur_num_buses; i < value; i++) { + tmpbus = (struct vbus *) kmalloc(sizeof(struct vbus), + GFP_KERNEL); + if (!tmpbus) { + err("Couldn't allocate bus %d memory\n", i); + return; + } + + memset(tmpbus, 0, sizeof(struct vbus)); + tmpbus->bus_num = i; + tmpbus->kobj.parent = &dev->kobj; + sprintf(tmpbus->kobj.name, "bus%d", i); + tmpbus->kobj.ktype = &ktype_vscsi_bus; + kobject_register(&tmpbus->kobj); + + spin_lock_irqsave(&adapter->lock, flags); + + if (adapter->vbus[i] != NULL) { + /* Race condition! */ + spin_unlock_irqrestore(&adapter->lock, flags); + kobject_unregister(&tmpbus->kobj); + continue; + } + + adapter->vbus[i] = tmpbus; + + atomic_inc(&adapter->num_buses); + spin_unlock_irqrestore(&adapter->lock, flags); + + set_num_targets(adapter->vbus[i], 1); + } + + } else if (cur_num_buses > value) { /* shrinking */ + int i, j, active_target; + for (i = cur_num_buses - 1; i >= value; i--) { + active_target = -1; + for (j = 0; j < TARGETS_PER_BUS; j++) { + if (adapter->vbus[i]->vdev[j] && + !adapter->vbus[i]->vdev[j]->disabled) { + active_target = j; + break; + } + } + if (active_target != -1) { + err("Can't remove bus%d, target%d active\n", + i, active_target); + return ; + } + + set_num_targets(adapter->vbus[i], 0); + + spin_lock_irqsave(&adapter->lock, flags); + atomic_dec(&adapter->num_buses); + tmpbus = adapter->vbus[i]; + adapter->vbus[i] = NULL; + spin_unlock_irqrestore(&adapter->lock, flags); + + /* If we race this could already be NULL */ + if (tmpbus) + kobject_unregister(&tmpbus->kobj); + } + } +} + +/* Target sysfs stuff */ +static ATTR(target, device, 0644); +static ATTR(target, active, 0644); +static ATTR(target, ro, 0644); + +static ssize_t vscsi_target_show(struct kobject * kobj, + struct attribute * attr, char * buf) +{ + struct vdev *vdev = container_of(kobj, struct vdev, kobj); + struct device *dev = container_of(kobj->parent->parent, + struct device, kobj); + struct server_adapter *adapter = + (struct server_adapter *)dev->driver_data; + unsigned long flags; + ssize_t returned; + + spin_lock_irqsave(&adapter->lock, flags); + + if (attr == &vscsi_target_device_attr) + returned = sprintf(buf, "%s\n", vdev->device_name); + else if (attr == &vscsi_target_active_attr) + returned = sprintf(buf, "%d\n", !vdev->disabled); + else if (attr == &vscsi_target_ro_attr) + returned = sprintf(buf, "%d\n", vdev->b.ro); + else { + returned = -EFAULT; + BUG(); + } + + spin_unlock_irqrestore(&adapter->lock, flags); + + return returned; +} + +static ssize_t vscsi_target_store(struct kobject * kobj, + struct attribute * attr, + const char * buf, size_t count) +{ + struct vdev *vdev = container_of(kobj, struct vdev, kobj); + struct device *dev = container_of(kobj->parent->parent, + struct device, kobj); + struct server_adapter *adapter = + (struct server_adapter *)dev->driver_data; + long flags; + long value = simple_strtol(buf, NULL, 10); + + if (attr != &vscsi_target_active_attr && !vdev->disabled) { + err("Error: Can't modify properties while target is active.\n"); + return -EPERM; + } + + if (attr == &vscsi_target_device_attr) { + int i; + spin_lock_irqsave(&adapter->lock, flags); + i = strlcpy(vdev->device_name, buf, TARGET_MAX_NAME_LEN); + for (; i >= 0; i--) + if (vdev->device_name[i] == '\n') + vdev->device_name[i] = '\0'; + spin_unlock_irqrestore(&adapter->lock, flags); + } else if (attr == &vscsi_target_active_attr) { + if (value) { + int rc; + if (!vdev->disabled) { + warn("Warning: Target was already active\n"); + return -EINVAL; + } + rc = activate_device(vdev); + if (rc) { + err("Error opening device=%d\n", rc); + return rc; + } + } else { + if (!vdev->disabled) + deactivate_device(vdev); + } + } else if (attr == &vscsi_target_ro_attr) + vdev->b.ro = value > 0 ? 1 : 0; + else + BUG(); + + return count; +} + +static struct attribute * vscsi_target_attrs[] = { + &vscsi_target_device_attr, + &vscsi_target_active_attr, + &vscsi_target_ro_attr, + NULL, +}; + +static struct sysfs_ops vscsi_target_ops = { + .show = vscsi_target_show, + .store = vscsi_target_store, +}; + +static struct kobj_type ktype_vscsi_target = { + .release = vscsi_target_release, + .sysfs_ops = &vscsi_target_ops, + .default_attrs = vscsi_target_attrs, +}; + + + +/* Bus sysfs stuff */ +static ssize_t vscsi_bus_show(struct kobject * kobj, + struct attribute * attr, char * buf) +{ + struct vbus *vbus = container_of(kobj, struct vbus, kobj); + return sprintf(buf, "%d\n", atomic_read(&vbus->num_targets)); +} + +static ssize_t vscsi_bus_store(struct kobject * kobj, struct attribute * attr, +const char * buf, size_t count) +{ + struct vbus *vbus = container_of(kobj, struct vbus, kobj); + long value = simple_strtol(buf, NULL, 10); + + if (value < 0 || value > TARGETS_PER_BUS) + return -EINVAL; + + set_num_targets(vbus, value); + + return count; +} + + +static ATTR(bus, num_targets, 0644); + +static struct attribute * vscsi_bus_attrs[] = { + &vscsi_bus_num_targets_attr, + NULL, +}; + +static struct sysfs_ops vscsi_bus_ops = { + .show = vscsi_bus_show, + .store = vscsi_bus_store, +}; + +static struct kobj_type ktype_vscsi_bus = { + .release = vscsi_bus_release, + .sysfs_ops = &vscsi_bus_ops, + .default_attrs = vscsi_bus_attrs, +}; + + +/* Device attributes */ +static ssize_t vscsi_dev_bus_show(struct device * dev, + struct device_attribute *attr, + char * buf) +{ + struct server_adapter *adapter = + (struct server_adapter *)dev->driver_data; + + return sprintf(buf, "%d\n", atomic_read(&adapter->num_buses)); +} + +static ssize_t vscsi_dev_sector_show(struct device * dev, + struct device_attribute *attr, + char * buf) +{ + struct server_adapter *adapter = + (struct server_adapter *)dev->driver_data; + + return sprintf(buf, "%d\n", adapter->max_sectors); +} + +static ssize_t vscsi_dev_bus_store(struct device * dev, + struct device_attribute *attr, + const char * buf, size_t count) +{ + long value = simple_strtol(buf, NULL, 10); + + if (value < 0 || value > BUS_PER_ADAPTER) + return -EINVAL; + + set_num_buses(dev, value); + return count; +} + +static ssize_t vscsi_dev_sector_store(struct device * dev, + struct device_attribute *attr, + const char * buf, size_t count) +{ + long value = simple_strtol(buf, NULL, 10); + struct server_adapter *adapter = + (struct server_adapter *)dev->driver_data; + + if (value <= 8 || value > SCSI_DEFAULT_MAX_SECTORS) + return -EINVAL; + + adapter->max_sectors = value; + + return count; +} + +static ssize_t vscsi_dev_debug_store(struct device * dev, + struct device_attribute *attr, + const char * buf, size_t count) +{ + long value = simple_strtol(buf, NULL, 10); + + ibmvscsis_debug = value; + return count; +} + +static ssize_t vscsi_dev_debug_show(struct device * dev, + struct device_attribute *attr, + char * buf) +{ + return sprintf(buf, "%d\n", ibmvscsis_debug); +} + +static DEVICE_ATTR(debug, 0644, vscsi_dev_debug_show, vscsi_dev_debug_store); +static DEVICE_ATTR(num_buses, 0644, vscsi_dev_bus_show, vscsi_dev_bus_store); +static DEVICE_ATTR(max_sectors, 0644, vscsi_dev_sector_show, + vscsi_dev_sector_store); + + +/* Stats kobj stuff */ + +static ATTR(stats, interrupts, 0444); +static ATTR(stats, read_ops, 0444); +static ATTR(stats, write_ops, 0444); +static ATTR(stats, crq_msgs, 0444); +static ATTR(stats, iu_allocs, 0444); +static ATTR(stats, bio_allocs, 0444); +static ATTR(stats, buf_allocs, 0444); +static ATTR(stats, errors, 0444); + +static struct attribute * vscsi_stats_attrs[] = { + &vscsi_stats_interrupts_attr, + &vscsi_stats_read_ops_attr, + &vscsi_stats_write_ops_attr, + &vscsi_stats_crq_msgs_attr, + &vscsi_stats_iu_allocs_attr, + &vscsi_stats_bio_allocs_attr, + &vscsi_stats_buf_allocs_attr, + &vscsi_stats_errors_attr, + NULL, +}; + + +static ssize_t vscsi_stats_show(struct kobject * kobj, + struct attribute * attr, char * buf) +{ + struct server_adapter *adapter= container_of(kobj, + struct server_adapter, + stats_kobj); + if (attr == &vscsi_stats_interrupts_attr) + return sprintf(buf, "%d\n", + atomic_read(&adapter->interrupts)); + if (attr == &vscsi_stats_read_ops_attr) + return sprintf(buf, "%d\n", + atomic_read(&adapter->read_processed)); + if (attr == &vscsi_stats_write_ops_attr) + return sprintf(buf, "%d\n", + atomic_read(&adapter->write_processed)); + if (attr == &vscsi_stats_crq_msgs_attr) + return sprintf(buf, "%d\n", + atomic_read(&adapter->crq_processed)); + if (attr == &vscsi_stats_iu_allocs_attr) + return sprintf(buf, "%d\n", + atomic_read(&adapter->iu_count)); + if (attr == &vscsi_stats_bio_allocs_attr) + return sprintf(buf, "%d\n", + atomic_read(&adapter->bio_count)); + if (attr == &vscsi_stats_buf_allocs_attr) + return sprintf(buf, "%d\n", + atomic_read(&adapter->buffers_allocated)); + if (attr == &vscsi_stats_errors_attr) + return sprintf(buf, "%d\n", + atomic_read(&adapter->errors)); + + BUG(); + return 0; +} + +static struct sysfs_ops vscsi_stats_ops = { + .show = vscsi_stats_show, + .store = NULL, +}; + +static struct kobj_type ktype_vscsi_stats = { + .release = NULL, + .sysfs_ops = &vscsi_stats_ops, + .default_attrs = vscsi_stats_attrs, +}; + + +/* ============================================================== + * Module load and unload + * ============================================================== + */ +static int ibmvscsis_probe(struct vio_dev *dev, const struct vio_device_id *id) +{ + struct server_adapter *adapter; + int rc; + unsigned int *dma_window; + unsigned int dma_window_property_size; + + adapter = kmalloc(sizeof(*adapter), GFP_KERNEL); + if (!adapter) { + err("couldn't allocate adapter memory\n"); + return -ENOMEM; + } + memset(adapter, 0, sizeof(*adapter)); + adapter->dma_dev = dev; + adapter->dev = &dev->dev; + adapter->dev->driver_data = adapter; + adapter->next_rsp_delta = 0; + adapter->lock = SPIN_LOCK_UNLOCKED; + + dma_window = + (unsigned int *)vio_get_attribute(dev, "ibm,my-dma-window", + &dma_window_property_size); + if (!dma_window) + warn("Couldn't find ibm,my-dma-window property\n"); + + adapter->liobn = dma_window[0]; + if (dma_window_property_size == 24) + adapter->riobn = dma_window[3]; + else if (dma_window_property_size == 40) + adapter->riobn = dma_window[5]; + else + warn("Invalid size of ibm,my-dma-window=%i\n", + dma_window_property_size); + + INIT_WORK(&adapter->crq_task, crq_task, adapter); + + tasklet_init(&adapter->endio_tasklet, + endio_task, (unsigned long)adapter); + + INIT_LIST_HEAD(&adapter->cmd_queue); + + /* Initialize the buffer cache */ + init_data_buffer(adapter); + + /* Arbitrarily support 16 IUs right now */ + rc = initialize_iu_pool(adapter, INITIAL_SRP_LIMIT); + if (rc) { + kfree(adapter); + return rc; + } + + rc = initialize_crq_queue(&adapter->queue, adapter); + if (rc != 0) { + kfree(adapter); + return rc; + } + + set_num_buses(&dev->dev, 1); + adapter->max_sectors = MAX_SECTORS; + device_create_file(&dev->dev, &dev_attr_debug); + device_create_file(&dev->dev, &dev_attr_num_buses); + device_create_file(&dev->dev, &dev_attr_max_sectors); + + adapter->stats_kobj.parent = &dev->dev.kobj; + strcpy(adapter->stats_kobj.name, "stats"); + adapter->stats_kobj.ktype = & ktype_vscsi_stats; + kobject_register(&adapter->stats_kobj); + + return 0; +} + +static int ibmvscsis_remove(struct vio_dev *dev) +{ + int bus; + int target; + unsigned long flags; + struct server_adapter *adapter = + (struct server_adapter *)dev->dev.driver_data; + + spin_lock_irqsave(&adapter->lock, flags); + + /* + * Loop through the bus + */ + for (bus = 0; bus < BUS_PER_ADAPTER; bus++) { + /* If this bus exists */ + if (adapter->vbus[bus]) { + /* loop through the targets */ + for (target = 0; target < TARGETS_PER_BUS; target++) { + /* If the target exists */ + struct vdev *vdev = + adapter->vbus[bus]->vdev[target]; + if (vdev && !vdev ->disabled) + deactivate_device(vdev); + } + spin_unlock_irqrestore(&adapter->lock, flags); + set_num_targets(adapter->vbus[bus], 0); + spin_lock_irqsave(&adapter->lock, flags); + } + } + + spin_unlock_irqrestore(&adapter->lock, flags); + set_num_buses(adapter->dev, 0); + release_crq_queue(&adapter->queue, adapter); + + release_iu_pool(adapter); + + release_data_buffer(adapter); + + kobject_unregister(&adapter->stats_kobj); + device_remove_file(&dev->dev, &dev_attr_debug); + device_remove_file(&dev->dev, &dev_attr_num_buses); + device_remove_file(&dev->dev, &dev_attr_max_sectors); + + kfree(adapter); + + return 0; +} + +static struct vio_device_id ibmvscsis_device_table[] __devinitdata = { + {"v-scsi-host", "IBM,v-scsi-host"}, + {0,} +}; + +MODULE_DEVICE_TABLE(vio, ibmvscsis_device_table); + +static struct vio_driver ibmvscsis_driver = { + .name = "ibmvscsis", + .id_table = ibmvscsis_device_table, + .probe = ibmvscsis_probe, + .remove = ibmvscsis_remove, +}; + +static int mod_init(void) +{ + struct device_node *rootdn; + char *ppartition_name; + char *psystem_id; + char *pmodel; + unsigned int *p_number_ptr; + int rc; + + /* Retrieve information about this partition */ + rootdn = find_path_device("/"); + if (rootdn) { + pmodel = get_property(rootdn, "model", NULL); + psystem_id = get_property(rootdn, "system-id", NULL); + if (pmodel && psystem_id) + snprintf(system_id,sizeof(system_id), + "%s-%s", + pmodel, psystem_id); + ppartition_name = + get_property(rootdn, "ibm,partition-name", NULL); + if (ppartition_name) + strncpy(partition_name, ppartition_name, + sizeof(partition_name)); + p_number_ptr = + (unsigned int *)get_property(rootdn, "ibm,partition-no", + NULL); + if (p_number_ptr) + partition_number = *p_number_ptr; + } + + info("initialized version "IBMVSCSIS_VERSION"\n"); + + rc = vio_register_driver(&ibmvscsis_driver); + + if (rc) { + warn("rc %d from vio_register_driver\n", rc); + return rc; + } + + rc = scsi_register_interface(&vscsis_interface); + + if (rc) + warn("rc %d from scsi_register_interface\n", rc); + + return rc; +} + +static void mod_exit(void) +{ + info("terminated\n"); + + scsi_unregister_interface(&vscsis_interface); + vio_unregister_driver(&ibmvscsis_driver); +} + +module_init(mod_init); +module_exit(mod_exit); diff -uNr linux-2.6.13-rc7/drivers/scsi/ibmvscsi/Makefile linux-2.6.13-rc7-ibmvscsis/drivers/scsi/ibmvscsi/Makefile --- linux-2.6.13-rc7/drivers/scsi/ibmvscsi/Makefile 2004-10-18 16:54:37.000000000 -0500 +++ linux-2.6.13-rc7-ibmvscsis/drivers/scsi/ibmvscsi/Makefile 2005-09-06 16:02:41.279485577 -0500 @@ -3,3 +3,5 @@ ibmvscsic-y += ibmvscsi.o ibmvscsic-$(CONFIG_PPC_ISERIES) += iseries_vscsi.o ibmvscsic-$(CONFIG_PPC_PSERIES) += rpa_vscsi.o + +obj-$(CONFIG_SCSI_IBMVSCSIS) += ibmvscsis.o diff -uNr linux-2.6.13-rc7/drivers/scsi/ibmvscsi/srp.h linux-2.6.13-rc7-ibmvscsis/drivers/scsi/ibmvscsi/srp.h --- linux-2.6.13-rc7/drivers/scsi/ibmvscsi/srp.h 2005-09-06 15:57:27.855492658 -0500 +++ linux-2.6.13-rc7-ibmvscsis/drivers/scsi/ibmvscsi/srp.h 2005-09-06 16:02:41.297483076 -0500 @@ -53,6 +53,13 @@ SRP_INDIRECT_BUFFER = 0x02 }; +enum srp_task_attributes { + SRP_SIMPLE_TASK = 0, + SRP_HEAD_TASK = 1, + SRP_ORDERED_TASK = 2, + SRP_ACA_TASK = 4 +}; + struct memory_descriptor { u64 virtual_address; u32 memory_handle; @@ -174,7 +181,7 @@ u32 data_out_residual_count; u32 sense_data_list_length; u32 response_data_list_length; - u8 sense_and_response_data[18]; + u8 sense_and_response_data[SCSI_SENSE_BUFFERSIZE]; }; struct srp_cred_req { diff -uNr linux-2.6.13-rc7/drivers/scsi/Kconfig linux-2.6.13-rc7-ibmvscsis/drivers/scsi/Kconfig --- linux-2.6.13-rc7/drivers/scsi/Kconfig 2005-09-06 15:57:27.674385086 -0500 +++ linux-2.6.13-rc7-ibmvscsis/drivers/scsi/Kconfig 2005-09-06 16:02:41.278485716 -0500 @@ -831,6 +831,16 @@ To compile this driver as a module, choose M here: the module will be called ibmvscsic. +config SCSI_IBMVSCSIS + tristate "IBM Virtual SCSI Server support" + depends on PPC_PSERIES + help + This is the IBM Virtual SCSI Server which can be configured using + the ppc64-utils package available at + http://techsupport.services.ibm.com/server/lopdiags + To compile this driver as a module, choose M here: the + module will be called ibmvscsis. + config SCSI_INITIO tristate "Initio 9100U(W) support" depends on PCI && SCSI From anton at samba.org Wed Sep 7 12:59:32 2005 From: anton at samba.org (Anton Blanchard) Date: Wed, 7 Sep 2005 12:59:32 +1000 Subject: [RFC] SCSI target for IBM Power5 LPAR In-Reply-To: <20050906212801.GB14057@cs.umn.edu> References: <20050906212801.GB14057@cs.umn.edu> Message-ID: <20050907025932.GU6945@krispykreme> Hi Dave, > This device driver provides the SCSI target side of the "virtual > SCSI" on IBM Power5 systems. The initiator side has been in mainline > for a while now (drivers/scsi/ibmvscsi/ibmvscsi.c.) Targets already > exist for AIX and OS/400. Good stuff. Got a couple of small suggestions. +/* Allocate a buffer with a dma_address. Don't use dma_alloc_coherent + * since that uses GFP_ATOMIC internally and we can tollerate a delay + */ +static void *alloc_coherent_buffer(struct server_adapter *adapter, size_t size, + dma_addr_t *dma_handle) +{ + void *buffer = kmalloc(size, GFP_KERNEL); + + if (buffer) { + *dma_handle = dma_map_single(adapter->dev, buffer, size, + DMA_BIDIRECTIONAL); + + if (dma_mapping_error(*dma_handle)) { + kfree(buffer); + buffer = NULL; + } + } + + return buffer; +} This should be fixed in mainline, on ppc64 we no longer build the dma_* ops on top of the pci_* ops. This means we actually look at the flags :) + adapter->max_sectors = MAX_SECTORS; Does this mean we are limited to 128kB transfers? Would it be OK to bump the default? Anton From sfr at canb.auug.org.au Wed Sep 7 13:43:12 2005 From: sfr at canb.auug.org.au (Stephen Rothwell) Date: Wed, 7 Sep 2005 13:43:12 +1000 Subject: [PATCH 0/4] ibmveth cleanup Message-ID: <20050907134312.21171f5c.sfr@canb.auug.org.au> This set of patches just does simple cleanups on ibmveth to make it more "linux kernel coding"-like. Please consider for merging upstream. There are no semantic changes. -- Cheers, Stephen Rothwell sfr at canb.auug.org.au http://www.canb.auug.org.au/~sfr/ From sfr at canb.auug.org.au Wed Sep 7 13:45:36 2005 From: sfr at canb.auug.org.au (Stephen Rothwell) Date: Wed, 7 Sep 2005 13:45:36 +1000 Subject: [PATCH 1/4] ibmveth: Use vio_{en,dis}able_intterrupts In-Reply-To: <20050907134312.21171f5c.sfr@canb.auug.org.au> References: <20050907134312.21171f5c.sfr@canb.auug.org.au> Message-ID: <20050907134536.5fd0ff8a.sfr@canb.auug.org.au> Signed-off-by: Stephen Rothwell --- drivers/net/ibmveth.c | 6 +++--- 1 files changed, 3 insertions(+), 3 deletions(-) -- Cheers, Stephen Rothwell sfr at canb.auug.org.au http://www.canb.auug.org.au/~sfr/ ac0ae32c0250535cf02a74164b83cdabbcd535e3 diff --git a/drivers/net/ibmveth.c b/drivers/net/ibmveth.c --- a/drivers/net/ibmveth.c +++ b/drivers/net/ibmveth.c @@ -792,7 +792,7 @@ static int ibmveth_poll(struct net_devic } /* we think we are done - reenable interrupts, then check once more to make sure we are done */ - lpar_rc = h_vio_signal(adapter->vdev->unit_address, VIO_IRQ_ENABLE); + lpar_rc = vio_enable_interrupts(adapter->vdev); ibmveth_assert(lpar_rc == H_Success); @@ -800,7 +800,7 @@ static int ibmveth_poll(struct net_devic if(ibmveth_rxq_pending_buffer(adapter) && netif_rx_reschedule(netdev, frames_processed)) { - lpar_rc = h_vio_signal(adapter->vdev->unit_address, VIO_IRQ_DISABLE); + lpar_rc = vio_disable_interrupts(adapter->vdev); ibmveth_assert(lpar_rc == H_Success); more_work = 1; goto restart_poll; @@ -820,7 +820,7 @@ static irqreturn_t ibmveth_interrupt(int unsigned long lpar_rc; if(netif_rx_schedule_prep(netdev)) { - lpar_rc = h_vio_signal(adapter->vdev->unit_address, VIO_IRQ_DISABLE); + lpar_rc = vio_disable_interrupts(adapter->vdev); ibmveth_assert(lpar_rc == H_Success); __netif_rx_schedule(netdev); } From sfr at canb.auug.org.au Wed Sep 7 13:47:06 2005 From: sfr at canb.auug.org.au (Stephen Rothwell) Date: Wed, 7 Sep 2005 13:47:06 +1000 Subject: [PATCH 2/4] ibmveth: White space, comment and formatting changes only In-Reply-To: <20050907134536.5fd0ff8a.sfr@canb.auug.org.au> References: <20050907134312.21171f5c.sfr@canb.auug.org.au> <20050907134536.5fd0ff8a.sfr@canb.auug.org.au> Message-ID: <20050907134706.07b881c0.sfr@canb.auug.org.au> Signed-off-by: Stephen Rothwell --- drivers/net/ibmveth.c | 663 ++++++++++++++++++++++++++----------------------- drivers/net/ibmveth.h | 253 +++++++++---------- 2 files changed, 482 insertions(+), 434 deletions(-) -- Cheers, Stephen Rothwell sfr at canb.auug.org.au http://www.canb.auug.org.au/~sfr/ 59f175c61878fef914654329662e172707619710 diff --git a/drivers/net/ibmveth.c b/drivers/net/ibmveth.c --- a/drivers/net/ibmveth.c +++ b/drivers/net/ibmveth.c @@ -1,37 +1,34 @@ -/**************************************************************************/ -/* */ -/* IBM eServer i/pSeries Virtual Ethernet Device Driver */ -/* Copyright (C) 2003 IBM Corp. */ -/* Originally written by Dave Larson (larson1 at us.ibm.com) */ -/* Maintained by Santiago Leon (santil at us.ibm.com) */ -/* */ -/* This program is free software; you can redistribute it and/or modify */ -/* it under the terms of the GNU General Public License as published by */ -/* the Free Software Foundation; either version 2 of the License, or */ -/* (at your option) any later version. */ -/* */ -/* This program is distributed in the hope that it will be useful, */ -/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ -/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ -/* GNU General Public License for more details. */ -/* */ -/* You should have received a copy of the GNU General Public License */ -/* along with this program; if not, write to the Free Software */ -/* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 */ -/* USA */ -/* */ -/* This module contains the implementation of a virtual ethernet device */ -/* for use with IBM i/pSeries LPAR Linux. It utilizes the logical LAN */ -/* option of the RS/6000 Platform Architechture to interface with virtual */ -/* ethernet NICs that are presented to the partition by the hypervisor. */ -/* */ -/**************************************************************************/ /* - TODO: - - remove frag processing code - no longer needed - - add support for sysfs - - possibly remove procfs support -*/ + * IBM eServer i/pSeries Virtual Ethernet Device Driver + * Copyright (C) 2003 IBM Corp. + * Originally written by Dave Larson (larson1 at us.ibm.com) + * Maintained by Santiago Leon (santil at us.ibm.com) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA + * + * This module contains the implementation of a virtual ethernet device + * for use with IBM i/pSeries LPAR Linux. It utilizes the logical LAN + * option of the RS/6000 Platform Architechture to interface with virtual + * ethernet NICs that are presented to the partition by the hypervisor. + * + * TODO: + * - remove frag processing code - no longer needed + * - add support for sysfs + * - possibly remove procfs support + */ #include #include @@ -49,6 +46,7 @@ #include #include #include + #include #include #include @@ -61,26 +59,30 @@ #define DEBUG 1 -#define ibmveth_printk(fmt, args...) \ - printk(KERN_INFO "%s: " fmt, __FILE__, ## args) +#define ibmveth_printk(fmt, args...) \ + printk(KERN_INFO "%s: " fmt, __FILE__, ## args) -#define ibmveth_error_printk(fmt, args...) \ - printk(KERN_ERR "(%s:%3.3d ua:%x) ERROR: " fmt, __FILE__, __LINE__ , adapter->vdev->unit_address, ## args) +#define ibmveth_error_printk(fmt, args...) \ + printk(KERN_ERR "(%s:%3.3d ua:%x) ERROR: " fmt, __FILE__, __LINE__, \ + adapter->vdev->unit_address, ## args) #ifdef DEBUG -#define ibmveth_debug_printk_no_adapter(fmt, args...) \ - printk(KERN_DEBUG "(%s:%3.3d): " fmt, __FILE__, __LINE__ , ## args) -#define ibmveth_debug_printk(fmt, args...) \ - printk(KERN_DEBUG "(%s:%3.3d ua:%x): " fmt, __FILE__, __LINE__ , adapter->vdev->unit_address, ## args) -#define ibmveth_assert(expr) \ - if(!(expr)) { \ - printk(KERN_DEBUG "assertion failed (%s:%3.3d ua:%x): %s\n", __FILE__, __LINE__, adapter->vdev->unit_address, #expr); \ - BUG(); \ - } +#define ibmveth_debug_printk_no_adapter(fmt, args...) \ + printk(KERN_DEBUG "(%s:%3.3d): " fmt, __FILE__, __LINE__, ## args) +#define ibmveth_debug_printk(fmt, args...) \ + printk(KERN_DEBUG "(%s:%3.3d ua:%x): " fmt, __FILE__, __LINE__, \ + adapter->vdev->unit_address, ## args) +#define ibmveth_assert(expr) \ + if (!(expr)) { \ + printk(KERN_DEBUG "assertion failed (%s:%3.3d ua:%x): %s\n", \ + __FILE__, __LINE__, \ + adapter->vdev->unit_address, #expr); \ + BUG(); \ + } #else #define ibmveth_debug_printk_no_adapter(fmt, args...) #define ibmveth_debug_printk(fmt, args...) -#define ibmveth_assert(expr) +#define ibmveth_assert(expr) #endif static int ibmveth_open(struct net_device *dev); @@ -95,7 +97,8 @@ static void ibmveth_proc_register_driver static void ibmveth_proc_unregister_driver(void); static void ibmveth_proc_register_adapter(struct ibmveth_adapter *adapter); static void ibmveth_proc_unregister_adapter(struct ibmveth_adapter *adapter); -static irqreturn_t ibmveth_interrupt(int irq, void *dev_instance, struct pt_regs *regs); +static irqreturn_t ibmveth_interrupt(int irq, void *dev_instance, + struct pt_regs *regs); static inline void ibmveth_schedule_replenishing(struct ibmveth_adapter*); #ifdef CONFIG_PROC_FS @@ -104,7 +107,8 @@ static struct proc_dir_entry *ibmveth_pr #endif static const char ibmveth_driver_name[] = "ibmveth"; -static const char ibmveth_driver_string[] = "IBM i/pSeries Virtual Ethernet Driver"; +static const char ibmveth_driver_string[] = + "IBM i/pSeries Virtual Ethernet Driver"; #define ibmveth_driver_version "1.03" MODULE_AUTHOR("Santiago Leon "); @@ -115,26 +119,28 @@ MODULE_VERSION(ibmveth_driver_version); /* simple methods of getting data from the current rxq entry */ static inline int ibmveth_rxq_pending_buffer(struct ibmveth_adapter *adapter) { - return (adapter->rx_queue.queue_addr[adapter->rx_queue.index].toggle == adapter->rx_queue.toggle); + return adapter->rx_queue.queue_addr[adapter->rx_queue.index].toggle + == adapter->rx_queue.toggle; } static inline int ibmveth_rxq_buffer_valid(struct ibmveth_adapter *adapter) { - return (adapter->rx_queue.queue_addr[adapter->rx_queue.index].valid); + return adapter->rx_queue.queue_addr[adapter->rx_queue.index].valid; } static inline int ibmveth_rxq_frame_offset(struct ibmveth_adapter *adapter) { - return (adapter->rx_queue.queue_addr[adapter->rx_queue.index].offset); + return adapter->rx_queue.queue_addr[adapter->rx_queue.index].offset; } static inline int ibmveth_rxq_frame_length(struct ibmveth_adapter *adapter) { - return (adapter->rx_queue.queue_addr[adapter->rx_queue.index].length); + return adapter->rx_queue.queue_addr[adapter->rx_queue.index].length; } /* setup the initial settings for a buffer pool */ -static void ibmveth_init_buffer_pool(struct ibmveth_buff_pool *pool, u32 pool_index, u32 pool_size, u32 buff_size) +static void ibmveth_init_buffer_pool(struct ibmveth_buff_pool *pool, + u32 pool_index, u32 pool_size, u32 buff_size) { pool->size = pool_size; pool->index = pool_index; @@ -147,22 +153,20 @@ static int ibmveth_alloc_buffer_pool(str { int i; - pool->free_map = kmalloc(sizeof(u16) * pool->size, GFP_KERNEL); - - if(!pool->free_map) { + pool->free_map = kmalloc(sizeof(u16) * pool->size, GFP_KERNEL); + if (!pool->free_map) return -1; - } - pool->dma_addr = kmalloc(sizeof(dma_addr_t) * pool->size, GFP_KERNEL); - if(!pool->dma_addr) { + pool->dma_addr = kmalloc(sizeof(dma_addr_t) * pool->size, GFP_KERNEL); + if (!pool->dma_addr) { kfree(pool->free_map); pool->free_map = NULL; return -1; } - pool->skbuff = kmalloc(sizeof(void*) * pool->size, GFP_KERNEL); + pool->skbuff = kmalloc(sizeof(void *) * pool->size, GFP_KERNEL); - if(!pool->skbuff) { + if (!pool->skbuff) { kfree(pool->dma_addr); pool->dma_addr = NULL; @@ -171,12 +175,11 @@ static int ibmveth_alloc_buffer_pool(str return -1; } - memset(pool->skbuff, 0, sizeof(void*) * pool->size); + memset(pool->skbuff, 0, sizeof(void *) * pool->size); memset(pool->dma_addr, 0, sizeof(dma_addr_t) * pool->size); - for(i = 0; i < pool->size; ++i) { + for (i = 0; i < pool->size; ++i) pool->free_map[i] = i; - } atomic_set(&pool->available, 0); pool->producer_index = 0; @@ -185,10 +188,12 @@ static int ibmveth_alloc_buffer_pool(str return 0; } -/* replenish the buffers for a pool. note that we don't need to +/* + * replenish the buffers for a pool. note that we don't need to * skb_reserve these since they are used for incoming... */ -static void ibmveth_replenish_buffer_pool(struct ibmveth_adapter *adapter, struct ibmveth_buff_pool *pool) +static void ibmveth_replenish_buffer_pool(struct ibmveth_adapter *adapter, + struct ibmveth_buff_pool *pool) { u32 i; u32 count = pool->size - atomic_read(&pool->available); @@ -196,17 +201,17 @@ static void ibmveth_replenish_buffer_poo mb(); - for(i = 0; i < count; ++i) { + for (i = 0; i < count; ++i) { struct sk_buff *skb; - unsigned int free_index, index; + unsigned int free_index; + unsigned int index; u64 correlator; union ibmveth_buf_desc desc; unsigned long lpar_rc; dma_addr_t dma_addr; skb = alloc_skb(pool->buff_size, GFP_ATOMIC); - - if(!skb) { + if (!skb) { ibmveth_debug_printk("replenish: unable to allocate skb\n"); adapter->replenish_no_mem++; break; @@ -214,7 +219,7 @@ static void ibmveth_replenish_buffer_poo free_index = pool->consumer_index++ % pool->size; index = pool->free_map[free_index]; - + ibmveth_assert(index != IBM_VETH_INVALID_MAP); ibmveth_assert(pool->skbuff[index] == NULL); @@ -231,11 +236,12 @@ static void ibmveth_replenish_buffer_poo desc.desc = 0; desc.fields.valid = 1; desc.fields.length = pool->buff_size; - desc.fields.address = dma_addr; + desc.fields.address = dma_addr; - lpar_rc = h_add_logical_lan_buffer(adapter->vdev->unit_address, desc.desc); - - if(lpar_rc != H_Success) { + lpar_rc = h_add_logical_lan_buffer(adapter->vdev->unit_address, + desc.desc); + + if (lpar_rc != H_Success) { pool->free_map[free_index] = IBM_VETH_INVALID_MAP; pool->skbuff[index] = NULL; pool->consumer_index--; @@ -250,30 +256,38 @@ static void ibmveth_replenish_buffer_poo adapter->replenish_add_buff_success++; } } - + mb(); atomic_add(buffers_added, &(pool->available)); } /* check if replenishing is needed. */ -static inline int ibmveth_is_replenishing_needed(struct ibmveth_adapter *adapter) +static inline int ibmveth_is_replenishing_needed( + struct ibmveth_adapter *adapter) { - return ((atomic_read(&adapter->rx_buff_pool[0].available) < adapter->rx_buff_pool[0].threshold) || - (atomic_read(&adapter->rx_buff_pool[1].available) < adapter->rx_buff_pool[1].threshold) || - (atomic_read(&adapter->rx_buff_pool[2].available) < adapter->rx_buff_pool[2].threshold)); + return (atomic_read(&adapter->rx_buff_pool[0].available) + < adapter->rx_buff_pool[0].threshold) + || (atomic_read(&adapter->rx_buff_pool[1].available) + < adapter->rx_buff_pool[1].threshold) + || (atomic_read(&adapter->rx_buff_pool[2].available) + < adapter->rx_buff_pool[2].threshold); } -/* kick the replenish tasklet if we need replenishing and it isn't already running */ -static inline void ibmveth_schedule_replenishing(struct ibmveth_adapter *adapter) +/* + * kick the replenish tasklet if we need replenishing and it + * isn't already running + */ +static inline void ibmveth_schedule_replenishing( + struct ibmveth_adapter *adapter) { - if(ibmveth_is_replenishing_needed(adapter) && - (atomic_dec_if_positive(&adapter->not_replenishing) == 0)) { + if (ibmveth_is_replenishing_needed(adapter) + && (atomic_dec_if_positive(&adapter->not_replenishing) + == 0)) schedule_work(&adapter->replenish_task); - } } /* replenish tasklet routine */ -static void ibmveth_replenish_task(struct ibmveth_adapter *adapter) +static void ibmveth_replenish_task(struct ibmveth_adapter *adapter) { adapter->replenish_task_cycles++; @@ -281,7 +295,8 @@ static void ibmveth_replenish_task(struc ibmveth_replenish_buffer_pool(adapter, &adapter->rx_buff_pool[1]); ibmveth_replenish_buffer_pool(adapter, &adapter->rx_buff_pool[2]); - adapter->rx_no_buffer = *(u64*)(((char*)adapter->buffer_list_addr) + 4096 - 8); + adapter->rx_no_buffer = *(u64*)(((char*)adapter->buffer_list_addr) + + 4096 - 8); atomic_inc(&adapter->not_replenishing); @@ -289,19 +304,21 @@ static void ibmveth_replenish_task(struc } /* empty and free ana buffer pool - also used to do cleanup in error paths */ -static void ibmveth_free_buffer_pool(struct ibmveth_adapter *adapter, struct ibmveth_buff_pool *pool) +static void ibmveth_free_buffer_pool(struct ibmveth_adapter *adapter, + struct ibmveth_buff_pool *pool) { int i; - if(pool->free_map) { + if (pool->free_map) { kfree(pool->free_map); pool->free_map = NULL; } - if(pool->skbuff && pool->dma_addr) { - for(i = 0; i < pool->size; ++i) { + if (pool->skbuff && pool->dma_addr) { + for (i = 0; i < pool->size; ++i) { struct sk_buff *skb = pool->skbuff[i]; - if(skb) { + + if (skb) { dma_unmap_single(&adapter->vdev->dev, pool->dma_addr[i], pool->buff_size, @@ -312,21 +329,22 @@ static void ibmveth_free_buffer_pool(str } } - if(pool->dma_addr) { + if (pool->dma_addr) { kfree(pool->dma_addr); pool->dma_addr = NULL; } - if(pool->skbuff) { + if (pool->skbuff) { kfree(pool->skbuff); pool->skbuff = NULL; } } /* remove a buffer from a pool */ -static void ibmveth_remove_buffer_from_pool(struct ibmveth_adapter *adapter, u64 correlator) +static void ibmveth_remove_buffer_from_pool(struct ibmveth_adapter *adapter, + u64 correlator) { - unsigned int pool = correlator >> 32; + unsigned int pool = correlator >> 32; unsigned int index = correlator & 0xffffffffUL; unsigned int free_index; struct sk_buff *skb; @@ -345,7 +363,8 @@ static void ibmveth_remove_buffer_from_p adapter->rx_buff_pool[pool].buff_size, DMA_FROM_DEVICE); - free_index = adapter->rx_buff_pool[pool].producer_index++ % adapter->rx_buff_pool[pool].size; + free_index = adapter->rx_buff_pool[pool].producer_index++ + % adapter->rx_buff_pool[pool].size; adapter->rx_buff_pool[pool].free_map[free_index] = index; mb(); @@ -354,7 +373,8 @@ static void ibmveth_remove_buffer_from_p } /* get the current buffer on the rx queue */ -static inline struct sk_buff *ibmveth_rxq_get_buffer(struct ibmveth_adapter *adapter) +static inline struct sk_buff *ibmveth_rxq_get_buffer( + struct ibmveth_adapter *adapter) { u64 correlator = adapter->rx_queue.queue_addr[adapter->rx_queue.index].correlator; unsigned int pool = correlator >> 32; @@ -384,14 +404,16 @@ static void ibmveth_rxq_recycle_buffer(s desc.fields.length = adapter->rx_buff_pool[pool].buff_size; desc.fields.address = adapter->rx_buff_pool[pool].dma_addr[index]; - lpar_rc = h_add_logical_lan_buffer(adapter->vdev->unit_address, desc.desc); - - if(lpar_rc != H_Success) { - ibmveth_debug_printk("h_add_logical_lan_buffer failed during recycle rc=%ld", lpar_rc); - ibmveth_remove_buffer_from_pool(adapter, adapter->rx_queue.queue_addr[adapter->rx_queue.index].correlator); + lpar_rc = h_add_logical_lan_buffer(adapter->vdev->unit_address, + desc.desc); + if (lpar_rc != H_Success) { + ibmveth_debug_printk("h_add_logical_lan_buffer failed " + "during recycle rc=%ld", lpar_rc); + ibmveth_remove_buffer_from_pool(adapter, + adapter->rx_queue.queue_addr[adapter->rx_queue.index].correlator); } - if(++adapter->rx_queue.index == adapter->rx_queue.num_slots) { + if (++adapter->rx_queue.index == adapter->rx_queue.num_slots) { adapter->rx_queue.index = 0; adapter->rx_queue.toggle = !adapter->rx_queue.toggle; } @@ -399,9 +421,10 @@ static void ibmveth_rxq_recycle_buffer(s static inline void ibmveth_rxq_harvest_buffer(struct ibmveth_adapter *adapter) { - ibmveth_remove_buffer_from_pool(adapter, adapter->rx_queue.queue_addr[adapter->rx_queue.index].correlator); + ibmveth_remove_buffer_from_pool(adapter, + adapter->rx_queue.queue_addr[adapter->rx_queue.index].correlator); - if(++adapter->rx_queue.index == adapter->rx_queue.num_slots) { + if (++adapter->rx_queue.index == adapter->rx_queue.num_slots) { adapter->rx_queue.index = 0; adapter->rx_queue.toggle = !adapter->rx_queue.toggle; } @@ -409,8 +432,8 @@ static inline void ibmveth_rxq_harvest_b static void ibmveth_cleanup(struct ibmveth_adapter *adapter) { - if(adapter->buffer_list_addr != NULL) { - if(!dma_mapping_error(adapter->buffer_list_dma)) { + if (adapter->buffer_list_addr != NULL) { + if (!dma_mapping_error(adapter->buffer_list_dma)) { dma_unmap_single(&adapter->vdev->dev, adapter->buffer_list_dma, 4096, DMA_BIDIRECTIONAL); @@ -418,10 +441,10 @@ static void ibmveth_cleanup(struct ibmve } free_page((unsigned long)adapter->buffer_list_addr); adapter->buffer_list_addr = NULL; - } + } - if(adapter->filter_list_addr != NULL) { - if(!dma_mapping_error(adapter->filter_list_dma)) { + if (adapter->filter_list_addr != NULL) { + if (!dma_mapping_error(adapter->filter_list_dma)) { dma_unmap_single(&adapter->vdev->dev, adapter->filter_list_dma, 4096, DMA_BIDIRECTIONAL); @@ -431,8 +454,8 @@ static void ibmveth_cleanup(struct ibmve adapter->filter_list_addr = NULL; } - if(adapter->rx_queue.queue_addr != NULL) { - if(!dma_mapping_error(adapter->rx_queue.queue_dma)) { + if (adapter->rx_queue.queue_addr != NULL) { + if (!dma_mapping_error(adapter->rx_queue.queue_dma)) { dma_unmap_single(&adapter->vdev->dev, adapter->rx_queue.queue_dma, adapter->rx_queue.queue_len, @@ -459,24 +482,26 @@ static int ibmveth_open(struct net_devic ibmveth_debug_printk("open starting\n"); - rxq_entries = - adapter->rx_buff_pool[0].size + + rxq_entries = adapter->rx_buff_pool[0].size + adapter->rx_buff_pool[1].size + adapter->rx_buff_pool[2].size + 1; - - adapter->buffer_list_addr = (void*) get_zeroed_page(GFP_KERNEL); - adapter->filter_list_addr = (void*) get_zeroed_page(GFP_KERNEL); - - if(!adapter->buffer_list_addr || !adapter->filter_list_addr) { - ibmveth_error_printk("unable to allocate filter or buffer list pages\n"); + + adapter->buffer_list_addr = (void *)get_zeroed_page(GFP_KERNEL); + adapter->filter_list_addr = (void *)get_zeroed_page(GFP_KERNEL); + + if (!adapter->buffer_list_addr || !adapter->filter_list_addr) { + ibmveth_error_printk("unable to allocate filter or " + "buffer list pages\n"); ibmveth_cleanup(adapter); return -ENOMEM; } - adapter->rx_queue.queue_len = sizeof(struct ibmveth_rx_q_entry) * rxq_entries; - adapter->rx_queue.queue_addr = kmalloc(adapter->rx_queue.queue_len, GFP_KERNEL); + adapter->rx_queue.queue_len = sizeof(struct ibmveth_rx_q_entry) * + rxq_entries; + adapter->rx_queue.queue_addr = kmalloc(adapter->rx_queue.queue_len, + GFP_KERNEL); - if(!adapter->rx_queue.queue_addr) { + if (!adapter->rx_queue.queue_addr) { ibmveth_error_printk("unable to allocate rx queue pages\n"); ibmveth_cleanup(adapter); return -ENOMEM; @@ -490,10 +515,11 @@ static int ibmveth_open(struct net_devic adapter->rx_queue.queue_addr, adapter->rx_queue.queue_len, DMA_BIDIRECTIONAL); - if((dma_mapping_error(adapter->buffer_list_dma) ) || - (dma_mapping_error(adapter->filter_list_dma)) || - (dma_mapping_error(adapter->rx_queue.queue_dma))) { - ibmveth_error_printk("unable to map filter or buffer list pages\n"); + if (dma_mapping_error(adapter->buffer_list_dma) || + dma_mapping_error(adapter->filter_list_dma) || + dma_mapping_error(adapter->rx_queue.queue_dma)) { + ibmveth_error_printk("unable to map filter or " + "buffer list pages\n"); ibmveth_cleanup(adapter); return -ENOMEM; } @@ -502,10 +528,9 @@ static int ibmveth_open(struct net_devic adapter->rx_queue.num_slots = rxq_entries; adapter->rx_queue.toggle = 1; - if(ibmveth_alloc_buffer_pool(&adapter->rx_buff_pool[0]) || - ibmveth_alloc_buffer_pool(&adapter->rx_buff_pool[1]) || - ibmveth_alloc_buffer_pool(&adapter->rx_buff_pool[2])) - { + if (ibmveth_alloc_buffer_pool(&adapter->rx_buff_pool[0]) || + ibmveth_alloc_buffer_pool(&adapter->rx_buff_pool[1]) || + ibmveth_alloc_buffer_pool(&adapter->rx_buff_pool[2])) { ibmveth_error_printk("unable to allocate buffer pools\n"); ibmveth_cleanup(adapter); return -ENOMEM; @@ -521,29 +546,31 @@ static int ibmveth_open(struct net_devic ibmveth_debug_printk("buffer list @ 0x%p\n", adapter->buffer_list_addr); ibmveth_debug_printk("filter list @ 0x%p\n", adapter->filter_list_addr); - ibmveth_debug_printk("receive q @ 0x%p\n", adapter->rx_queue.queue_addr); + ibmveth_debug_printk("receive q @ 0x%p\n", + adapter->rx_queue.queue_addr); + - lpar_rc = h_register_logical_lan(adapter->vdev->unit_address, - adapter->buffer_list_dma, - rxq_desc.desc, - adapter->filter_list_dma, - mac_address); - - if(lpar_rc != H_Success) { - ibmveth_error_printk("h_register_logical_lan failed with %ld\n", lpar_rc); - ibmveth_error_printk("buffer TCE:0x%x filter TCE:0x%x rxq desc:0x%lx MAC:0x%lx\n", - adapter->buffer_list_dma, - adapter->filter_list_dma, - rxq_desc.desc, - mac_address); + adapter->buffer_list_dma, rxq_desc.desc, + adapter->filter_list_dma, mac_address); + if (lpar_rc != H_Success) { + ibmveth_error_printk("h_register_logical_lan failed with %ld\n", + lpar_rc); + ibmveth_error_printk("buffer TCE:0x%x filter TCE:0x%x " + "rxq desc:0x%lx MAC:0x%lx\n", + adapter->buffer_list_dma, + adapter->filter_list_dma, rxq_desc.desc, + mac_address); ibmveth_cleanup(adapter); - return -ENONET; + return -ENONET; } ibmveth_debug_printk("registering irq 0x%x\n", netdev->irq); - if((rc = request_irq(netdev->irq, &ibmveth_interrupt, 0, netdev->name, netdev)) != 0) { - ibmveth_error_printk("unable to request irq 0x%x, rc %d\n", netdev->irq, rc); + rc = request_irq(netdev->irq, &ibmveth_interrupt, 0, netdev->name, + netdev); + if (rc != 0) { + ibmveth_error_printk("unable to request irq 0x%x, rc %d\n", + netdev->irq, rc); do { rc = h_free_logical_lan(adapter->vdev->unit_address); } while (H_isLongBusy(rc) || (rc == H_Busy)); @@ -566,7 +593,7 @@ static int ibmveth_close(struct net_devi { struct ibmveth_adapter *adapter = netdev->priv; long lpar_rc; - + ibmveth_debug_printk("close starting\n"); netif_stop_queue(netdev); @@ -580,13 +607,12 @@ static int ibmveth_close(struct net_devi lpar_rc = h_free_logical_lan(adapter->vdev->unit_address); } while (H_isLongBusy(lpar_rc) || (lpar_rc == H_Busy)); - if(lpar_rc != H_Success) - { - ibmveth_error_printk("h_free_logical_lan failed with %lx, continuing with close\n", - lpar_rc); - } + if (lpar_rc != H_Success) + ibmveth_error_printk("h_free_logical_lan failed with %lx, " + "continuing with close\n", lpar_rc); - adapter->rx_no_buffer = *(u64*)(((char*)adapter->buffer_list_addr) + 4096 - 8); + adapter->rx_no_buffer = *(u64*)(((char*)adapter->buffer_list_addr) + + 4096 - 8); ibmveth_cleanup(adapter); @@ -595,9 +621,12 @@ static int ibmveth_close(struct net_devi return 0; } -static int netdev_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) { - cmd->supported = (SUPPORTED_1000baseT_Full | SUPPORTED_Autoneg | SUPPORTED_FIBRE); - cmd->advertising = (ADVERTISED_1000baseT_Full | ADVERTISED_Autoneg | ADVERTISED_FIBRE); +static int netdev_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) +{ + cmd->supported = (SUPPORTED_1000baseT_Full | SUPPORTED_Autoneg | + SUPPORTED_FIBRE); + cmd->advertising = (ADVERTISED_1000baseT_Full | ADVERTISED_Autoneg | + ADVERTISED_FIBRE); cmd->speed = SPEED_1000; cmd->duplex = DUPLEX_FULL; cmd->port = PORT_FIBRE; @@ -609,21 +638,25 @@ static int netdev_get_settings(struct ne return 0; } -static void netdev_get_drvinfo (struct net_device *dev, struct ethtool_drvinfo *info) { +static void netdev_get_drvinfo (struct net_device *dev, + struct ethtool_drvinfo *info) +{ strncpy(info->driver, ibmveth_driver_name, sizeof(info->driver) - 1); - strncpy(info->version, ibmveth_driver_version, sizeof(info->version) - 1); + strncpy(info->version, ibmveth_driver_version, + sizeof(info->version) - 1); } -static u32 netdev_get_link(struct net_device *dev) { +static u32 netdev_get_link(struct net_device *dev) +{ return 1; } static struct ethtool_ops netdev_ethtool_ops = { - .get_drvinfo = netdev_get_drvinfo, - .get_settings = netdev_get_settings, - .get_link = netdev_get_link, - .get_sg = ethtool_op_get_sg, - .get_tx_csum = ethtool_op_get_tx_csum, + .get_drvinfo = netdev_get_drvinfo, + .get_settings = netdev_get_settings, + .get_link = netdev_get_link, + .get_sg = ethtool_op_get_sg, + .get_tx_csum = ethtool_op_get_tx_csum, }; static int ibmveth_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) @@ -653,7 +686,7 @@ static int ibmveth_start_xmit(struct sk_ /* nfrags = number of frags after the initial fragment */ nfrags = skb_shinfo(skb)->nr_frags; - if(nfrags) + if (nfrags) adapter->tx_multidesc_send++; /* map the initial fragment */ @@ -662,7 +695,7 @@ static int ibmveth_start_xmit(struct sk_ desc[0].fields.length, DMA_TO_DEVICE); desc[0].fields.valid = 1; - if(dma_mapping_error(desc[0].fields.address)) { + if (dma_mapping_error(desc[0].fields.address)) { ibmveth_error_printk("tx: unable to map initial fragment\n"); adapter->tx_map_failed++; adapter->stats.tx_dropped++; @@ -682,8 +715,9 @@ static int ibmveth_start_xmit(struct sk_ desc[curfrag+1].fields.length = frag->size; desc[curfrag+1].fields.valid = 1; - if(dma_mapping_error(desc[curfrag+1].fields.address)) { - ibmveth_error_printk("tx: unable to map fragment %d\n", curfrag); + if (dma_mapping_error(desc[curfrag+1].fields.address)) { + ibmveth_error_printk("tx: unable to map fragment %d\n", + curfrag); adapter->tx_map_failed++; adapter->stats.tx_dropped++; /* Free all the mappings we just created */ @@ -704,21 +738,22 @@ static int ibmveth_start_xmit(struct sk_ retry_count = 1024; do { lpar_rc = h_send_logical_lan(adapter->vdev->unit_address, - desc[0].desc, - desc[1].desc, - desc[2].desc, - desc[3].desc, - desc[4].desc, - desc[5].desc, - correlator); + desc[0].desc, desc[1].desc, desc[2].desc, + desc[3].desc, desc[4].desc, desc[5].desc, + correlator); } while ((lpar_rc == H_Busy) && (retry_count--)); - - if(lpar_rc != H_Success && lpar_rc != H_Dropped) { + + if (lpar_rc != H_Success && lpar_rc != H_Dropped) { int i; - ibmveth_error_printk("tx: h_send_logical_lan failed with rc=%ld\n", lpar_rc); - for(i = 0; i < 6; i++) { - ibmveth_error_printk("tx: desc[%i] valid=%d, len=%d, address=0x%d\n", i, - desc[i].fields.valid, desc[i].fields.length, desc[i].fields.address); + + ibmveth_error_printk("tx: h_send_logical_lan failed with " + "rc=%ld\n", lpar_rc); + for (i = 0; i < 6; i++) { + ibmveth_error_printk("tx: desc[%i] valid=%d, len=%d, " + "address=0x%d\n", i, + desc[i].fields.valid, + desc[i].fields.length, + desc[i].fields.address); } adapter->tx_send_failed++; adapter->stats.tx_dropped++; @@ -731,7 +766,7 @@ static int ibmveth_start_xmit(struct sk_ dma_unmap_single(&adapter->vdev->dev, desc[nfrags].fields.address, desc[nfrags].fields.length, DMA_TO_DEVICE); - } while(--nfrags >= 0); + } while (--nfrags >= 0); dev_kfree_skb(skb); return 0; @@ -745,19 +780,20 @@ static int ibmveth_poll(struct net_devic int more_work = 1; unsigned long lpar_rc; - restart_poll: +restart_poll: do { struct net_device *netdev = adapter->netdev; - if(ibmveth_rxq_pending_buffer(adapter)) { + if (ibmveth_rxq_pending_buffer(adapter)) { struct sk_buff *skb; rmb(); - if(!ibmveth_rxq_buffer_valid(adapter)) { + if (!ibmveth_rxq_buffer_valid(adapter)) { wmb(); /* suggested by larson1 */ adapter->rx_invalid_buffer++; - ibmveth_debug_printk("recycling invalid buffer\n"); + ibmveth_debug_printk("recycling invalid " + "buffer\n"); ibmveth_rxq_recycle_buffer(adapter); } else { int length = ibmveth_rxq_frame_length(adapter); @@ -780,26 +816,29 @@ static int ibmveth_poll(struct net_devic } else { more_work = 0; } - } while(more_work && (frames_processed < max_frames_to_process)); + } while (more_work && (frames_processed < max_frames_to_process)); ibmveth_schedule_replenishing(adapter); - if(more_work) { + if (more_work) { /* more work to do - return that we are not done yet */ netdev->quota -= frames_processed; *budget -= frames_processed; - return 1; + return 1; } - /* we think we are done - reenable interrupts, then check once more to make sure we are done */ + /* + * we think we are done - reenable interrupts, then check + * once more to make sure we are done + */ lpar_rc = vio_enable_interrupts(adapter->vdev); ibmveth_assert(lpar_rc == H_Success); netif_rx_complete(netdev); - if(ibmveth_rxq_pending_buffer(adapter) && netif_rx_reschedule(netdev, frames_processed)) - { + if (ibmveth_rxq_pending_buffer(adapter) && + netif_rx_reschedule(netdev, frames_processed)) { lpar_rc = vio_disable_interrupts(adapter->vdev); ibmveth_assert(lpar_rc == H_Success); more_work = 1; @@ -813,13 +852,14 @@ static int ibmveth_poll(struct net_devic return 0; } -static irqreturn_t ibmveth_interrupt(int irq, void *dev_instance, struct pt_regs *regs) -{ +static irqreturn_t ibmveth_interrupt(int irq, void *dev_instance, + struct pt_regs *regs) +{ struct net_device *netdev = dev_instance; struct ibmveth_adapter *adapter = netdev->priv; unsigned long lpar_rc; - if(netif_rx_schedule_prep(netdev)) { + if (netif_rx_schedule_prep(netdev)) { lpar_rc = vio_disable_interrupts(adapter->vdev); ibmveth_assert(lpar_rc == H_Success); __netif_rx_schedule(netdev); @@ -838,88 +878,90 @@ static void ibmveth_set_multicast_list(s struct ibmveth_adapter *adapter = netdev->priv; unsigned long lpar_rc; - if((netdev->flags & IFF_PROMISC) || (netdev->mc_count > adapter->mcastFilterSize)) { + if ((netdev->flags & IFF_PROMISC) || + (netdev->mc_count > adapter->mcastFilterSize)) { lpar_rc = h_multicast_ctrl(adapter->vdev->unit_address, IbmVethMcastEnableRecv | IbmVethMcastDisableFiltering, 0); - if(lpar_rc != H_Success) { - ibmveth_error_printk("h_multicast_ctrl rc=%ld when entering promisc mode\n", lpar_rc); - } + if (lpar_rc != H_Success) + ibmveth_error_printk("h_multicast_ctrl rc=%ld when " + "entering promisc mode\n", lpar_rc); } else { struct dev_mc_list *mclist = netdev->mc_list; int i; + /* clear the filter table & disable filtering */ lpar_rc = h_multicast_ctrl(adapter->vdev->unit_address, IbmVethMcastEnableRecv | IbmVethMcastDisableFiltering | - IbmVethMcastClearFilterTable, - 0); - if(lpar_rc != H_Success) { - ibmveth_error_printk("h_multicast_ctrl rc=%ld when attempting to clear filter table\n", lpar_rc); - } + IbmVethMcastClearFilterTable, 0); + if (lpar_rc != H_Success) + ibmveth_error_printk("h_multicast_ctrl rc=%ld when " + "attempting to clear filter table\n", + lpar_rc); /* add the addresses to the filter table */ - for(i = 0; i < netdev->mc_count; ++i, mclist = mclist->next) { - // add the multicast address to the filter table + for (i = 0; i < netdev->mc_count; ++i, mclist = mclist->next) { + /* add the multicast address to the filter table */ unsigned long mcast_addr = 0; - memcpy(((char *)&mcast_addr)+2, mclist->dmi_addr, 6); + + memcpy(((char *)&mcast_addr) + 2, mclist->dmi_addr, 6); lpar_rc = h_multicast_ctrl(adapter->vdev->unit_address, IbmVethMcastAddFilter, mcast_addr); - if(lpar_rc != H_Success) { - ibmveth_error_printk("h_multicast_ctrl rc=%ld when adding an entry to the filter table\n", lpar_rc); - } + if (lpar_rc != H_Success) + ibmveth_error_printk("h_multicast_ctrl rc=%ld " + "when adding an entry to the " + "filter table\n", lpar_rc); } - + /* re-enable filtering */ lpar_rc = h_multicast_ctrl(adapter->vdev->unit_address, - IbmVethMcastEnableFiltering, - 0); - if(lpar_rc != H_Success) { - ibmveth_error_printk("h_multicast_ctrl rc=%ld when enabling filtering\n", lpar_rc); - } + IbmVethMcastEnableFiltering, 0); + if (lpar_rc != H_Success) + ibmveth_error_printk("h_multicast_ctrl rc=%ld when " + "enabling filtering\n", lpar_rc); } } static int ibmveth_change_mtu(struct net_device *dev, int new_mtu) { - if ((new_mtu < 68) || (new_mtu > (1<<20))) + if ((new_mtu < 68) || (new_mtu > (1 << 20))) return -EINVAL; dev->mtu = new_mtu; - return 0; + return 0; } -static int __devinit ibmveth_probe(struct vio_dev *dev, const struct vio_device_id *id) +static int __devinit ibmveth_probe(struct vio_dev *dev, + const struct vio_device_id *id) { int rc; struct net_device *netdev; struct ibmveth_adapter *adapter; - unsigned char *mac_addr_p; unsigned int *mcastFilterSize_p; + ibmveth_debug_printk_no_adapter("entering ibmveth_probe for UA 0x%x\n", + dev->unit_address); - ibmveth_debug_printk_no_adapter("entering ibmveth_probe for UA 0x%x\n", - dev->unit_address); - - mac_addr_p = (unsigned char *) vio_get_attribute(dev, VETH_MAC_ADDR, 0); - if(!mac_addr_p) { + mac_addr_p = (unsigned char *)vio_get_attribute(dev, VETH_MAC_ADDR, 0); + if (!mac_addr_p) { printk(KERN_ERR "(%s:%3.3d) ERROR: Can't find VETH_MAC_ADDR " "attribute\n", __FILE__, __LINE__); return 0; } - - mcastFilterSize_p= (unsigned int *) vio_get_attribute(dev, VETH_MCAST_FILTER_SIZE, 0); - if(!mcastFilterSize_p) { + + mcastFilterSize_p = (unsigned int *)vio_get_attribute(dev, + VETH_MCAST_FILTER_SIZE, 0); + if (!mcastFilterSize_p) { printk(KERN_ERR "(%s:%3.3d) ERROR: Can't find " "VETH_MCAST_FILTER_SIZE attribute\n", __FILE__, __LINE__); return 0; } - - netdev = alloc_etherdev(sizeof(struct ibmveth_adapter)); - if(!netdev) + netdev = alloc_etherdev(sizeof(struct ibmveth_adapter)); + if (!netdev) return -ENOMEM; SET_MODULE_OWNER(netdev); @@ -931,15 +973,16 @@ static int __devinit ibmveth_probe(struc adapter->vdev = dev; adapter->netdev = netdev; adapter->mcastFilterSize= *mcastFilterSize_p; - - /* Some older boxes running PHYP non-natively have an OF that - returns a 8-byte local-mac-address field (and the first - 2 bytes have to be ignored) while newer boxes' OF return - a 6-byte field. Note that IEEE 1275 specifies that - local-mac-address must be a 6-byte field. - The RPA doc specifies that the first byte must be 10b, so - we'll just look for it to solve this 8 vs. 6 byte field issue */ + /* + * Some older boxes running PHYP non-natively have an OF that + * returns a 8-byte local-mac-address field (and the first + * 2 bytes have to be ignored) while newer boxes' OF return + * a 6-byte field. Note that IEEE 1275 specifies that + * local-mac-address must be a 6-byte field. The RPA doc + * specifies that the first byte must be 10b, so we'll just + * look for it to solve this 8 vs. 6 byte field issue + */ if ((*mac_addr_p & 0x3) != 0x02) mac_addr_p += 2; @@ -947,48 +990,47 @@ static int __devinit ibmveth_probe(struc memcpy(&adapter->mac_addr, mac_addr_p, 6); adapter->liobn = dev->iommu_table->it_index; - + netdev->irq = dev->irq; - netdev->open = ibmveth_open; - netdev->poll = ibmveth_poll; - netdev->weight = 16; - netdev->stop = ibmveth_close; - netdev->hard_start_xmit = ibmveth_start_xmit; - netdev->get_stats = ibmveth_get_stats; + netdev->open = ibmveth_open; + netdev->poll = ibmveth_poll; + netdev->weight = 16; + netdev->stop = ibmveth_close; + netdev->hard_start_xmit = ibmveth_start_xmit; + netdev->get_stats = ibmveth_get_stats; netdev->set_multicast_list = ibmveth_set_multicast_list; - netdev->do_ioctl = ibmveth_ioctl; - netdev->ethtool_ops = &netdev_ethtool_ops; - netdev->change_mtu = ibmveth_change_mtu; + netdev->do_ioctl = ibmveth_ioctl; + netdev->ethtool_ops = &netdev_ethtool_ops; + netdev->change_mtu = ibmveth_change_mtu; SET_NETDEV_DEV(netdev, &dev->dev); memcpy(&netdev->dev_addr, &adapter->mac_addr, netdev->addr_len); - ibmveth_init_buffer_pool(&adapter->rx_buff_pool[0], 0, IbmVethPool0DftCnt, IbmVethPool0DftSize); - ibmveth_init_buffer_pool(&adapter->rx_buff_pool[1], 1, IbmVethPool1DftCnt, IbmVethPool1DftSize); - ibmveth_init_buffer_pool(&adapter->rx_buff_pool[2], 2, IbmVethPool2DftCnt, IbmVethPool2DftSize); + ibmveth_init_buffer_pool(&adapter->rx_buff_pool[0], 0, + IbmVethPool0DftCnt, IbmVethPool0DftSize); + ibmveth_init_buffer_pool(&adapter->rx_buff_pool[1], 1, + IbmVethPool1DftCnt, IbmVethPool1DftSize); + ibmveth_init_buffer_pool(&adapter->rx_buff_pool[2], 2, + IbmVethPool2DftCnt, IbmVethPool2DftSize); ibmveth_debug_printk("adapter @ 0x%p\n", adapter); - INIT_WORK(&adapter->replenish_task, (void*)ibmveth_replenish_task, (void*)adapter); + INIT_WORK(&adapter->replenish_task, (void *)ibmveth_replenish_task, + (void *)adapter); adapter->buffer_list_dma = DMA_ERROR_CODE; adapter->filter_list_dma = DMA_ERROR_CODE; adapter->rx_queue.queue_dma = DMA_ERROR_CODE; - atomic_set(&adapter->not_replenishing, 1); - ibmveth_debug_printk("registering netdev...\n"); rc = register_netdev(netdev); - - if(rc) { + if (rc) { ibmveth_debug_printk("failed to register netdev rc=%d\n", rc); free_netdev(netdev); return rc; } - ibmveth_debug_printk("registered\n"); - ibmveth_proc_register_adapter(adapter); return 0; @@ -1000,9 +1042,7 @@ static int __devexit ibmveth_remove(stru struct ibmveth_adapter *adapter = netdev->priv; unregister_netdev(netdev); - ibmveth_proc_unregister_adapter(adapter); - free_netdev(netdev); return 0; } @@ -1010,10 +1050,10 @@ static int __devexit ibmveth_remove(stru #ifdef CONFIG_PROC_FS static void ibmveth_proc_register_driver(void) { - ibmveth_proc_dir = create_proc_entry(IBMVETH_PROC_DIR, S_IFDIR, proc_net); - if (ibmveth_proc_dir) { + ibmveth_proc_dir = create_proc_entry(IBMVETH_PROC_DIR, S_IFDIR, + proc_net); + if (ibmveth_proc_dir) SET_MODULE_OWNER(ibmveth_proc_dir); - } } static void ibmveth_proc_unregister_driver(void) @@ -1021,13 +1061,12 @@ static void ibmveth_proc_unregister_driv remove_proc_entry(IBMVETH_PROC_DIR, proc_net); } -static void *ibmveth_seq_start(struct seq_file *seq, loff_t *pos) +static void *ibmveth_seq_start(struct seq_file *seq, loff_t *pos) { - if (*pos == 0) { + if (*pos == 0) return (void *)1; - } else { + else return NULL; - } } static void *ibmveth_seq_next(struct seq_file *seq, void *v, loff_t *pos) @@ -1036,18 +1075,18 @@ static void *ibmveth_seq_next(struct seq return NULL; } -static void ibmveth_seq_stop(struct seq_file *seq, void *v) +static void ibmveth_seq_stop(struct seq_file *seq, void *v) { } -static int ibmveth_seq_show(struct seq_file *seq, void *v) +static int ibmveth_seq_show(struct seq_file *seq, void *v) { struct ibmveth_adapter *adapter = seq->private; - char *current_mac = ((char*) &adapter->netdev->dev_addr); - char *firmware_mac = ((char*) &adapter->mac_addr) ; + char *current_mac = (char *)&adapter->netdev->dev_addr; + char *firmware_mac = (char *)&adapter->mac_addr; - seq_printf(seq, "%s %s\n\n", ibmveth_driver_string, ibmveth_driver_version); - + seq_printf(seq, "%s %s\n\n", ibmveth_driver_string, + ibmveth_driver_version); seq_printf(seq, "Unit Address: 0x%x\n", adapter->vdev->unit_address); seq_printf(seq, "LIOBN: 0x%lx\n", adapter->liobn); seq_printf(seq, "Current MAC: %02X:%02X:%02X:%02X:%02X:%02X\n", @@ -1056,19 +1095,27 @@ static int ibmveth_seq_show(struct seq_f seq_printf(seq, "Firmware MAC: %02X:%02X:%02X:%02X:%02X:%02X\n", firmware_mac[0], firmware_mac[1], firmware_mac[2], firmware_mac[3], firmware_mac[4], firmware_mac[5]); - seq_printf(seq, "\nAdapter Statistics:\n"); - seq_printf(seq, " TX: skbuffs linearized: %ld\n", adapter->tx_linearized); - seq_printf(seq, " multi-descriptor sends: %ld\n", adapter->tx_multidesc_send); - seq_printf(seq, " skb_linearize failures: %ld\n", adapter->tx_linearize_failed); - seq_printf(seq, " vio_map_single failres: %ld\n", adapter->tx_map_failed); - seq_printf(seq, " send failures: %ld\n", adapter->tx_send_failed); - seq_printf(seq, " RX: replenish task cycles: %ld\n", adapter->replenish_task_cycles); - seq_printf(seq, " alloc_skb_failures: %ld\n", adapter->replenish_no_mem); - seq_printf(seq, " add buffer failures: %ld\n", adapter->replenish_add_buff_failure); - seq_printf(seq, " invalid buffers: %ld\n", adapter->rx_invalid_buffer); - seq_printf(seq, " no buffers: %ld\n", adapter->rx_no_buffer); - + seq_printf(seq, " TX: skbuffs linearized: %ld\n", + adapter->tx_linearized); + seq_printf(seq, " multi-descriptor sends: %ld\n", + adapter->tx_multidesc_send); + seq_printf(seq, " skb_linearize failures: %ld\n", + adapter->tx_linearize_failed); + seq_printf(seq, " vio_map_single failres: %ld\n", + adapter->tx_map_failed); + seq_printf(seq, " send failures: %ld\n", + adapter->tx_send_failed); + seq_printf(seq, " RX: replenish task cycles: %ld\n", + adapter->replenish_task_cycles); + seq_printf(seq, " alloc_skb_failures: %ld\n", + adapter->replenish_no_mem); + seq_printf(seq, " add buffer failures: %ld\n", + adapter->replenish_add_buff_failure); + seq_printf(seq, " invalid buffers: %ld\n", + adapter->rx_invalid_buffer); + seq_printf(seq, " no buffers: %ld\n", + adapter->rx_no_buffer); return 0; } static struct seq_operations ibmveth_seq_ops = { @@ -1095,42 +1142,42 @@ static int ibmveth_proc_open(struct inod } static struct file_operations ibmveth_proc_fops = { - .owner = THIS_MODULE, - .open = ibmveth_proc_open, - .read = seq_read, - .llseek = seq_lseek, - .release = seq_release, + .owner = THIS_MODULE, + .open = ibmveth_proc_open, + .read = seq_read, + .llseek = seq_lseek, + .release = seq_release, }; static void ibmveth_proc_register_adapter(struct ibmveth_adapter *adapter) { struct proc_dir_entry *entry; + if (ibmveth_proc_dir) { - entry = create_proc_entry(adapter->netdev->name, S_IFREG, ibmveth_proc_dir); - if (!entry) { + entry = create_proc_entry(adapter->netdev->name, S_IFREG, + ibmveth_proc_dir); + if (!entry) ibmveth_error_printk("Cannot create adapter proc entry"); - } else { - entry->data = (void *) adapter; + else { + entry->data = adapter; entry->proc_fops = &ibmveth_proc_fops; SET_MODULE_OWNER(entry); } } - return; } static void ibmveth_proc_unregister_adapter(struct ibmveth_adapter *adapter) { - if (ibmveth_proc_dir) { + if (ibmveth_proc_dir) remove_proc_entry(adapter->netdev->name, ibmveth_proc_dir); - } } #else /* CONFIG_PROC_FS */ -static void ibmveth_proc_register_adapter(struct ibmveth_adapter *adapter) +static void ibmveth_proc_register_adapter(struct ibmveth_adapter *adapter) { } -static void ibmveth_proc_unregister_adapter(struct ibmveth_adapter *adapter) +static void ibmveth_proc_unregister_adapter(struct ibmveth_adapter *adapter) { } static void ibmveth_proc_register_driver(void) @@ -1146,7 +1193,6 @@ static struct vio_device_id ibmveth_devi { "network", "IBM,l-lan"}, { "", "" } }; - MODULE_DEVICE_TABLE(vio, ibmveth_device_table); static struct vio_driver ibmveth_driver = { @@ -1158,10 +1204,9 @@ static struct vio_driver ibmveth_driver static int __init ibmveth_module_init(void) { - ibmveth_printk("%s: %s %s\n", ibmveth_driver_name, ibmveth_driver_string, ibmveth_driver_version); - + ibmveth_printk("%s: %s %s\n", ibmveth_driver_name, + ibmveth_driver_string, ibmveth_driver_version); ibmveth_proc_register_driver(); - return vio_register_driver(&ibmveth_driver); } @@ -1169,7 +1214,7 @@ static void __exit ibmveth_module_exit(v { vio_unregister_driver(&ibmveth_driver); ibmveth_proc_unregister_driver(); -} +} module_init(ibmveth_module_init); module_exit(ibmveth_module_exit); diff --git a/drivers/net/ibmveth.h b/drivers/net/ibmveth.h --- a/drivers/net/ibmveth.h +++ b/drivers/net/ibmveth.h @@ -1,26 +1,24 @@ -/**************************************************************************/ -/* */ -/* IBM eServer i/[Series Virtual Ethernet Device Driver */ -/* Copyright (C) 2003 IBM Corp. */ -/* Dave Larson (larson1 at us.ibm.com) */ -/* Santiago Leon (santil at us.ibm.com) */ -/* */ -/* This program is free software; you can redistribute it and/or modify */ -/* it under the terms of the GNU General Public License as published by */ -/* the Free Software Foundation; either version 2 of the License, or */ -/* (at your option) any later version. */ -/* */ -/* This program is distributed in the hope that it will be useful, */ -/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ -/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ -/* GNU General Public License for more details. */ -/* */ -/* You should have received a copy of the GNU General Public License */ -/* along with this program; if not, write to the Free Software */ -/* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 */ -/* USA */ -/* */ -/**************************************************************************/ +/* + * IBM eServer i/[Series Virtual Ethernet Device Driver + * Copyright (C) 2003 IBM Corp. + * Dave Larson (larson1 at us.ibm.com) + * Santiago Leon (santil at us.ibm.com) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA + */ #ifndef _IBMVETH_H #define _IBMVETH_H @@ -28,131 +26,136 @@ #define IbmVethMaxSendFrags 6 /* constants for H_MULTICAST_CTRL */ -#define IbmVethMcastReceptionModifyBit 0x80000UL -#define IbmVethMcastReceptionEnableBit 0x20000UL -#define IbmVethMcastFilterModifyBit 0x40000UL -#define IbmVethMcastFilterEnableBit 0x10000UL - -#define IbmVethMcastEnableRecv (IbmVethMcastReceptionModifyBit | IbmVethMcastReceptionEnableBit) -#define IbmVethMcastDisableRecv (IbmVethMcastReceptionModifyBit) -#define IbmVethMcastEnableFiltering (IbmVethMcastFilterModifyBit | IbmVethMcastFilterEnableBit) -#define IbmVethMcastDisableFiltering (IbmVethMcastFilterModifyBit) -#define IbmVethMcastAddFilter 0x1UL -#define IbmVethMcastRemoveFilter 0x2UL -#define IbmVethMcastClearFilterTable 0x3UL +#define IbmVethMcastReceptionModifyBit 0x80000UL +#define IbmVethMcastReceptionEnableBit 0x20000UL +#define IbmVethMcastFilterModifyBit 0x40000UL +#define IbmVethMcastFilterEnableBit 0x10000UL + +#define IbmVethMcastEnableRecv (IbmVethMcastReceptionModifyBit | \ + IbmVethMcastReceptionEnableBit) +#define IbmVethMcastDisableRecv (IbmVethMcastReceptionModifyBit) +#define IbmVethMcastEnableFiltering (IbmVethMcastFilterModifyBit | \ + IbmVethMcastFilterEnableBit) +#define IbmVethMcastDisableFiltering (IbmVethMcastFilterModifyBit) +#define IbmVethMcastAddFilter 0x1UL +#define IbmVethMcastRemoveFilter 0x2UL +#define IbmVethMcastClearFilterTable 0x3UL /* hcall numbers */ -#define H_VIO_SIGNAL 0x104 -#define H_REGISTER_LOGICAL_LAN 0x114 -#define H_FREE_LOGICAL_LAN 0x118 -#define H_ADD_LOGICAL_LAN_BUFFER 0x11C -#define H_SEND_LOGICAL_LAN 0x120 -#define H_MULTICAST_CTRL 0x130 -#define H_CHANGE_LOGICAL_LAN_MAC 0x14C +#define H_VIO_SIGNAL 0x104 +#define H_REGISTER_LOGICAL_LAN 0x114 +#define H_FREE_LOGICAL_LAN 0x118 +#define H_ADD_LOGICAL_LAN_BUFFER 0x11C +#define H_SEND_LOGICAL_LAN 0x120 +#define H_MULTICAST_CTRL 0x130 +#define H_CHANGE_LOGICAL_LAN_MAC 0x14C /* hcall macros */ -#define h_register_logical_lan(ua, buflst, rxq, fltlst, mac) \ - plpar_hcall_norets(H_REGISTER_LOGICAL_LAN, ua, buflst, rxq, fltlst, mac) +#define h_register_logical_lan(ua, buflst, rxq, fltlst, mac) \ + plpar_hcall_norets(H_REGISTER_LOGICAL_LAN, (ua), (buflst), \ + (rxq), (fltlst), (mac)) -#define h_free_logical_lan(ua) \ - plpar_hcall_norets(H_FREE_LOGICAL_LAN, ua) +#define h_free_logical_lan(ua) \ + plpar_hcall_norets(H_FREE_LOGICAL_LAN, (ua)) -#define h_add_logical_lan_buffer(ua, buf) \ - plpar_hcall_norets(H_ADD_LOGICAL_LAN_BUFFER, ua, buf) +#define h_add_logical_lan_buffer(ua, buf) \ + plpar_hcall_norets(H_ADD_LOGICAL_LAN_BUFFER, (ua), (buf)) #define h_send_logical_lan(ua, buf1, buf2, buf3, buf4, buf5, buf6, correlator) \ - plpar_hcall_8arg_2ret(H_SEND_LOGICAL_LAN, ua, buf1, buf2, buf3, buf4, buf5, buf6, correlator, &correlator) + plpar_hcall_8arg_2ret(H_SEND_LOGICAL_LAN, (ua), (buf1), \ + (buf2), (buf3), (buf4), (buf5), (buf6), \ + (correlator), &(correlator)) + +#define h_multicast_ctrl(ua, cmd, mac) \ + plpar_hcall_norets(H_MULTICAST_CTRL, (ua), (cmd), (mac)) + +#define h_change_logical_lan_mac(ua, mac) \ + plpar_hcall_norets(H_CHANGE_LOGICAL_LAN_MAC, (ua), (mac)) + +#define IbmVethNumBufferPools 3 +#define IbmVethPool0DftSize (1024 * 2) +#define IbmVethPool1DftSize (1024 * 4) +#define IbmVethPool2DftSize (1024 * 10) +#define IbmVethPool0DftCnt 256 +#define IbmVethPool1DftCnt 256 +#define IbmVethPool2DftCnt 256 -#define h_multicast_ctrl(ua, cmd, mac) \ - plpar_hcall_norets(H_MULTICAST_CTRL, ua, cmd, mac) - -#define h_change_logical_lan_mac(ua, mac) \ - plpar_hcall_norets(H_CHANGE_LOGICAL_LAN_MAC, ua, mac) - -#define IbmVethNumBufferPools 3 -#define IbmVethPool0DftSize (1024 * 2) -#define IbmVethPool1DftSize (1024 * 4) -#define IbmVethPool2DftSize (1024 * 10) -#define IbmVethPool0DftCnt 256 -#define IbmVethPool1DftCnt 256 -#define IbmVethPool2DftCnt 256 - -#define IBM_VETH_INVALID_MAP ((u16)0xffff) +#define IBM_VETH_INVALID_MAP ((u16)0xffff) struct ibmveth_buff_pool { - u32 size; - u32 index; - u32 buff_size; - u32 threshold; - atomic_t available; - u32 consumer_index; - u32 producer_index; - u16 *free_map; - dma_addr_t *dma_addr; - struct sk_buff **skbuff; + u32 size; + u32 index; + u32 buff_size; + u32 threshold; + atomic_t available; + u32 consumer_index; + u32 producer_index; + u16 *free_map; + dma_addr_t *dma_addr; + struct sk_buff **skbuff; }; struct ibmveth_rx_q { - u64 index; - u64 num_slots; - u64 toggle; - dma_addr_t queue_dma; - u32 queue_len; - struct ibmveth_rx_q_entry *queue_addr; + u64 index; + u64 num_slots; + u64 toggle; + dma_addr_t queue_dma; + u32 queue_len; + struct ibmveth_rx_q_entry *queue_addr; }; struct ibmveth_adapter { - struct vio_dev *vdev; - struct net_device *netdev; - struct net_device_stats stats; - unsigned int mcastFilterSize; - unsigned long mac_addr; - unsigned long liobn; - void * buffer_list_addr; - void * filter_list_addr; - dma_addr_t buffer_list_dma; - dma_addr_t filter_list_dma; - struct ibmveth_buff_pool rx_buff_pool[IbmVethNumBufferPools]; - struct ibmveth_rx_q rx_queue; - atomic_t not_replenishing; - - /* helper tasks */ - struct work_struct replenish_task; - - /* adapter specific stats */ - u64 replenish_task_cycles; - u64 replenish_no_mem; - u64 replenish_add_buff_failure; - u64 replenish_add_buff_success; - u64 rx_invalid_buffer; - u64 rx_no_buffer; - u64 tx_multidesc_send; - u64 tx_linearized; - u64 tx_linearize_failed; - u64 tx_map_failed; - u64 tx_send_failed; -}; - -struct ibmveth_buf_desc_fields { - u32 valid : 1; - u32 toggle : 1; - u32 reserved : 6; - u32 length : 24; - u32 address; + struct vio_dev *vdev; + struct net_device *netdev; + struct net_device_stats stats; + unsigned int mcastFilterSize; + unsigned long mac_addr; + unsigned long liobn; + void *buffer_list_addr; + void *filter_list_addr; + dma_addr_t buffer_list_dma; + dma_addr_t filter_list_dma; + struct ibmveth_buff_pool rx_buff_pool[IbmVethNumBufferPools]; + struct ibmveth_rx_q rx_queue; + atomic_t not_replenishing; + + /* helper tasks */ + struct work_struct replenish_task; + + /* adapter specific stats */ + u64 replenish_task_cycles; + u64 replenish_no_mem; + u64 replenish_add_buff_failure; + u64 replenish_add_buff_success; + u64 rx_invalid_buffer; + u64 rx_no_buffer; + u64 tx_multidesc_send; + u64 tx_linearized; + u64 tx_linearize_failed; + u64 tx_map_failed; + u64 tx_send_failed; +}; + +struct ibmveth_buf_desc_fields { + u32 valid : 1; + u32 toggle : 1; + u32 reserved : 6; + u32 length : 24; + u32 address; }; union ibmveth_buf_desc { - u64 desc; - struct ibmveth_buf_desc_fields fields; + u64 desc; + struct ibmveth_buf_desc_fields fields; }; struct ibmveth_rx_q_entry { - u16 toggle : 1; - u16 valid : 1; - u16 reserved : 14; - u16 offset; - u32 length; - u64 correlator; + u16 toggle : 1; + u16 valid : 1; + u16 reserved : 14; + u16 offset; + u32 length; + u64 correlator; }; #endif /* _IBMVETH_H */ From sfr at canb.auug.org.au Wed Sep 7 13:48:58 2005 From: sfr at canb.auug.org.au (Stephen Rothwell) Date: Wed, 7 Sep 2005 13:48:58 +1000 Subject: [PATCH 3/4] ibmveth: Incorporate ibmveth.h into ibmveth.c In-Reply-To: <20050907134706.07b881c0.sfr@canb.auug.org.au> References: <20050907134312.21171f5c.sfr@canb.auug.org.au> <20050907134536.5fd0ff8a.sfr@canb.auug.org.au> <20050907134706.07b881c0.sfr@canb.auug.org.au> Message-ID: <20050907134858.3e5fadb9.sfr@canb.auug.org.au> No other file includes ibmveth.h Signed-off-by: Stephen Rothwell --- drivers/net/ibmveth.c | 135 +++++++++++++++++++++++++++++++++++++++++ drivers/net/ibmveth.h | 161 ------------------------------------------------- 2 files changed, 134 insertions(+), 162 deletions(-) delete mode 100644 drivers/net/ibmveth.h -- Cheers, Stephen Rothwell sfr at canb.auug.org.au http://www.canb.auug.org.au/~sfr/ 0e613250ad1b8564058728948fa788890a5005cd diff --git a/drivers/net/ibmveth.c b/drivers/net/ibmveth.c --- a/drivers/net/ibmveth.c +++ b/drivers/net/ibmveth.c @@ -55,7 +55,140 @@ #include #include -#include "ibmveth.h" +#define IbmVethMaxSendFrags 6 + +/* constants for H_MULTICAST_CTRL */ +#define IbmVethMcastReceptionModifyBit 0x80000UL +#define IbmVethMcastReceptionEnableBit 0x20000UL +#define IbmVethMcastFilterModifyBit 0x40000UL +#define IbmVethMcastFilterEnableBit 0x10000UL + +#define IbmVethMcastEnableRecv (IbmVethMcastReceptionModifyBit | \ + IbmVethMcastReceptionEnableBit) +#define IbmVethMcastDisableRecv (IbmVethMcastReceptionModifyBit) +#define IbmVethMcastEnableFiltering (IbmVethMcastFilterModifyBit | \ + IbmVethMcastFilterEnableBit) +#define IbmVethMcastDisableFiltering (IbmVethMcastFilterModifyBit) +#define IbmVethMcastAddFilter 0x1UL +#define IbmVethMcastRemoveFilter 0x2UL +#define IbmVethMcastClearFilterTable 0x3UL + +/* hcall numbers */ +#define H_VIO_SIGNAL 0x104 +#define H_REGISTER_LOGICAL_LAN 0x114 +#define H_FREE_LOGICAL_LAN 0x118 +#define H_ADD_LOGICAL_LAN_BUFFER 0x11C +#define H_SEND_LOGICAL_LAN 0x120 +#define H_MULTICAST_CTRL 0x130 +#define H_CHANGE_LOGICAL_LAN_MAC 0x14C + +/* hcall macros */ +#define h_register_logical_lan(ua, buflst, rxq, fltlst, mac) \ + plpar_hcall_norets(H_REGISTER_LOGICAL_LAN, (ua), (buflst), \ + (rxq), (fltlst), (mac)) + +#define h_free_logical_lan(ua) \ + plpar_hcall_norets(H_FREE_LOGICAL_LAN, (ua)) + +#define h_add_logical_lan_buffer(ua, buf) \ + plpar_hcall_norets(H_ADD_LOGICAL_LAN_BUFFER, (ua), (buf)) + +#define h_send_logical_lan(ua, buf1, buf2, buf3, buf4, buf5, buf6, correlator) \ + plpar_hcall_8arg_2ret(H_SEND_LOGICAL_LAN, (ua), (buf1), \ + (buf2), (buf3), (buf4), (buf5), (buf6), \ + (correlator), &(correlator)) + +#define h_multicast_ctrl(ua, cmd, mac) \ + plpar_hcall_norets(H_MULTICAST_CTRL, (ua), (cmd), (mac)) + +#define h_change_logical_lan_mac(ua, mac) \ + plpar_hcall_norets(H_CHANGE_LOGICAL_LAN_MAC, (ua), (mac)) + +#define IbmVethNumBufferPools 3 +#define IbmVethPool0DftSize (1024 * 2) +#define IbmVethPool1DftSize (1024 * 4) +#define IbmVethPool2DftSize (1024 * 10) +#define IbmVethPool0DftCnt 256 +#define IbmVethPool1DftCnt 256 +#define IbmVethPool2DftCnt 256 + +#define IBM_VETH_INVALID_MAP ((u16)0xffff) + +struct ibmveth_buff_pool { + u32 size; + u32 index; + u32 buff_size; + u32 threshold; + atomic_t available; + u32 consumer_index; + u32 producer_index; + u16 *free_map; + dma_addr_t *dma_addr; + struct sk_buff **skbuff; +}; + +struct ibmveth_rx_q { + u64 index; + u64 num_slots; + u64 toggle; + dma_addr_t queue_dma; + u32 queue_len; + struct ibmveth_rx_q_entry *queue_addr; +}; + +struct ibmveth_adapter { + struct vio_dev *vdev; + struct net_device *netdev; + struct net_device_stats stats; + unsigned int mcastFilterSize; + unsigned long mac_addr; + unsigned long liobn; + void *buffer_list_addr; + void *filter_list_addr; + dma_addr_t buffer_list_dma; + dma_addr_t filter_list_dma; + struct ibmveth_buff_pool rx_buff_pool[IbmVethNumBufferPools]; + struct ibmveth_rx_q rx_queue; + atomic_t not_replenishing; + + /* helper tasks */ + struct work_struct replenish_task; + + /* adapter specific stats */ + u64 replenish_task_cycles; + u64 replenish_no_mem; + u64 replenish_add_buff_failure; + u64 replenish_add_buff_success; + u64 rx_invalid_buffer; + u64 rx_no_buffer; + u64 tx_multidesc_send; + u64 tx_linearized; + u64 tx_linearize_failed; + u64 tx_map_failed; + u64 tx_send_failed; +}; + +struct ibmveth_buf_desc_fields { + u32 valid : 1; + u32 toggle : 1; + u32 reserved : 6; + u32 length : 24; + u32 address; +}; + +union ibmveth_buf_desc { + u64 desc; + struct ibmveth_buf_desc_fields fields; +}; + +struct ibmveth_rx_q_entry { + u16 toggle : 1; + u16 valid : 1; + u16 reserved : 14; + u16 offset; + u32 length; + u64 correlator; +}; #define DEBUG 1 diff --git a/drivers/net/ibmveth.h b/drivers/net/ibmveth.h deleted file mode 100644 --- a/drivers/net/ibmveth.h +++ /dev/null @@ -1,161 +0,0 @@ -/* - * IBM eServer i/[Series Virtual Ethernet Device Driver - * Copyright (C) 2003 IBM Corp. - * Dave Larson (larson1 at us.ibm.com) - * Santiago Leon (santil at us.ibm.com) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA - */ - -#ifndef _IBMVETH_H -#define _IBMVETH_H - -#define IbmVethMaxSendFrags 6 - -/* constants for H_MULTICAST_CTRL */ -#define IbmVethMcastReceptionModifyBit 0x80000UL -#define IbmVethMcastReceptionEnableBit 0x20000UL -#define IbmVethMcastFilterModifyBit 0x40000UL -#define IbmVethMcastFilterEnableBit 0x10000UL - -#define IbmVethMcastEnableRecv (IbmVethMcastReceptionModifyBit | \ - IbmVethMcastReceptionEnableBit) -#define IbmVethMcastDisableRecv (IbmVethMcastReceptionModifyBit) -#define IbmVethMcastEnableFiltering (IbmVethMcastFilterModifyBit | \ - IbmVethMcastFilterEnableBit) -#define IbmVethMcastDisableFiltering (IbmVethMcastFilterModifyBit) -#define IbmVethMcastAddFilter 0x1UL -#define IbmVethMcastRemoveFilter 0x2UL -#define IbmVethMcastClearFilterTable 0x3UL - -/* hcall numbers */ -#define H_VIO_SIGNAL 0x104 -#define H_REGISTER_LOGICAL_LAN 0x114 -#define H_FREE_LOGICAL_LAN 0x118 -#define H_ADD_LOGICAL_LAN_BUFFER 0x11C -#define H_SEND_LOGICAL_LAN 0x120 -#define H_MULTICAST_CTRL 0x130 -#define H_CHANGE_LOGICAL_LAN_MAC 0x14C - -/* hcall macros */ -#define h_register_logical_lan(ua, buflst, rxq, fltlst, mac) \ - plpar_hcall_norets(H_REGISTER_LOGICAL_LAN, (ua), (buflst), \ - (rxq), (fltlst), (mac)) - -#define h_free_logical_lan(ua) \ - plpar_hcall_norets(H_FREE_LOGICAL_LAN, (ua)) - -#define h_add_logical_lan_buffer(ua, buf) \ - plpar_hcall_norets(H_ADD_LOGICAL_LAN_BUFFER, (ua), (buf)) - -#define h_send_logical_lan(ua, buf1, buf2, buf3, buf4, buf5, buf6, correlator) \ - plpar_hcall_8arg_2ret(H_SEND_LOGICAL_LAN, (ua), (buf1), \ - (buf2), (buf3), (buf4), (buf5), (buf6), \ - (correlator), &(correlator)) - -#define h_multicast_ctrl(ua, cmd, mac) \ - plpar_hcall_norets(H_MULTICAST_CTRL, (ua), (cmd), (mac)) - -#define h_change_logical_lan_mac(ua, mac) \ - plpar_hcall_norets(H_CHANGE_LOGICAL_LAN_MAC, (ua), (mac)) - -#define IbmVethNumBufferPools 3 -#define IbmVethPool0DftSize (1024 * 2) -#define IbmVethPool1DftSize (1024 * 4) -#define IbmVethPool2DftSize (1024 * 10) -#define IbmVethPool0DftCnt 256 -#define IbmVethPool1DftCnt 256 -#define IbmVethPool2DftCnt 256 - -#define IBM_VETH_INVALID_MAP ((u16)0xffff) - -struct ibmveth_buff_pool { - u32 size; - u32 index; - u32 buff_size; - u32 threshold; - atomic_t available; - u32 consumer_index; - u32 producer_index; - u16 *free_map; - dma_addr_t *dma_addr; - struct sk_buff **skbuff; -}; - -struct ibmveth_rx_q { - u64 index; - u64 num_slots; - u64 toggle; - dma_addr_t queue_dma; - u32 queue_len; - struct ibmveth_rx_q_entry *queue_addr; -}; - -struct ibmveth_adapter { - struct vio_dev *vdev; - struct net_device *netdev; - struct net_device_stats stats; - unsigned int mcastFilterSize; - unsigned long mac_addr; - unsigned long liobn; - void *buffer_list_addr; - void *filter_list_addr; - dma_addr_t buffer_list_dma; - dma_addr_t filter_list_dma; - struct ibmveth_buff_pool rx_buff_pool[IbmVethNumBufferPools]; - struct ibmveth_rx_q rx_queue; - atomic_t not_replenishing; - - /* helper tasks */ - struct work_struct replenish_task; - - /* adapter specific stats */ - u64 replenish_task_cycles; - u64 replenish_no_mem; - u64 replenish_add_buff_failure; - u64 replenish_add_buff_success; - u64 rx_invalid_buffer; - u64 rx_no_buffer; - u64 tx_multidesc_send; - u64 tx_linearized; - u64 tx_linearize_failed; - u64 tx_map_failed; - u64 tx_send_failed; -}; - -struct ibmveth_buf_desc_fields { - u32 valid : 1; - u32 toggle : 1; - u32 reserved : 6; - u32 length : 24; - u32 address; -}; - -union ibmveth_buf_desc { - u64 desc; - struct ibmveth_buf_desc_fields fields; -}; - -struct ibmveth_rx_q_entry { - u16 toggle : 1; - u16 valid : 1; - u16 reserved : 14; - u16 offset; - u32 length; - u64 correlator; -}; - -#endif /* _IBMVETH_H */ From sfr at canb.auug.org.au Wed Sep 7 13:50:35 2005 From: sfr at canb.auug.org.au (Stephen Rothwell) Date: Wed, 7 Sep 2005 13:50:35 +1000 Subject: [PATCH 4/4] ibmveth: General cleanups In-Reply-To: <20050907134858.3e5fadb9.sfr@canb.auug.org.au> References: <20050907134312.21171f5c.sfr@canb.auug.org.au> <20050907134536.5fd0ff8a.sfr@canb.auug.org.au> <20050907134706.07b881c0.sfr@canb.auug.org.au> <20050907134858.3e5fadb9.sfr@canb.auug.org.au> Message-ID: <20050907135035.1d645baa.sfr@canb.auug.org.au> There are no semantic changes here. - remove an unused define - remove lionb from struct ibmveth_adapter it was only used for a proc file and could be obtained from other available data - rearrange some functions to get rid of forward declarations Signed-off-by: Stephen Rothwell --- drivers/net/ibmveth.c | 318 ++++++++++++++++++++----------------------------- 1 files changed, 133 insertions(+), 185 deletions(-) -- Cheers, Stephen Rothwell sfr at canb.auug.org.au http://www.canb.auug.org.au/~sfr/ d53d2f190a0cad40f593cb03e110b1a4c3204a5e diff --git a/drivers/net/ibmveth.c b/drivers/net/ibmveth.c --- a/drivers/net/ibmveth.c +++ b/drivers/net/ibmveth.c @@ -46,6 +46,7 @@ #include #include #include +#include #include #include @@ -53,7 +54,6 @@ #include #include #include -#include #define IbmVethMaxSendFrags 6 @@ -74,7 +74,6 @@ #define IbmVethMcastClearFilterTable 0x3UL /* hcall numbers */ -#define H_VIO_SIGNAL 0x104 #define H_REGISTER_LOGICAL_LAN 0x114 #define H_FREE_LOGICAL_LAN 0x118 #define H_ADD_LOGICAL_LAN_BUFFER 0x11C @@ -142,7 +141,6 @@ struct ibmveth_adapter { struct net_device_stats stats; unsigned int mcastFilterSize; unsigned long mac_addr; - unsigned long liobn; void *buffer_list_addr; void *filter_list_addr; dma_addr_t buffer_list_dma; @@ -218,27 +216,6 @@ struct ibmveth_rx_q_entry { #define ibmveth_assert(expr) #endif -static int ibmveth_open(struct net_device *dev); -static int ibmveth_close(struct net_device *dev); -static int ibmveth_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd); -static int ibmveth_poll(struct net_device *dev, int *budget); -static int ibmveth_start_xmit(struct sk_buff *skb, struct net_device *dev); -static struct net_device_stats *ibmveth_get_stats(struct net_device *dev); -static void ibmveth_set_multicast_list(struct net_device *dev); -static int ibmveth_change_mtu(struct net_device *dev, int new_mtu); -static void ibmveth_proc_register_driver(void); -static void ibmveth_proc_unregister_driver(void); -static void ibmveth_proc_register_adapter(struct ibmveth_adapter *adapter); -static void ibmveth_proc_unregister_adapter(struct ibmveth_adapter *adapter); -static irqreturn_t ibmveth_interrupt(int irq, void *dev_instance, - struct pt_regs *regs); -static inline void ibmveth_schedule_replenishing(struct ibmveth_adapter*); - -#ifdef CONFIG_PROC_FS -#define IBMVETH_PROC_DIR "ibmveth" -static struct proc_dir_entry *ibmveth_proc_dir; -#endif - static const char ibmveth_driver_name[] = "ibmveth"; static const char ibmveth_driver_string[] = "IBM i/pSeries Virtual Ethernet Driver"; @@ -428,7 +405,7 @@ static void ibmveth_replenish_task(struc ibmveth_replenish_buffer_pool(adapter, &adapter->rx_buff_pool[1]); ibmveth_replenish_buffer_pool(adapter, &adapter->rx_buff_pool[2]); - adapter->rx_no_buffer = *(u64*)(((char*)adapter->buffer_list_addr) + adapter->rx_no_buffer = *(u64 *)(((char *)adapter->buffer_list_addr) + 4096 - 8); atomic_inc(&adapter->not_replenishing); @@ -436,7 +413,7 @@ static void ibmveth_replenish_task(struc ibmveth_schedule_replenishing(adapter); } -/* empty and free ana buffer pool - also used to do cleanup in error paths */ +/* empty and free a buffer pool - also used to do cleanup in error paths */ static void ibmveth_free_buffer_pool(struct ibmveth_adapter *adapter, struct ibmveth_buff_pool *pool) { @@ -604,6 +581,21 @@ static void ibmveth_cleanup(struct ibmve ibmveth_free_buffer_pool(adapter, &adapter->rx_buff_pool[2]); } +static irqreturn_t ibmveth_interrupt(int irq, void *dev_instance, + struct pt_regs *regs) +{ + struct net_device *netdev = dev_instance; + struct ibmveth_adapter *adapter = netdev->priv; + unsigned long lpar_rc; + + if (netif_rx_schedule_prep(netdev)) { + lpar_rc = vio_disable_interrupts(adapter->vdev); + ibmveth_assert(lpar_rc == H_Success); + __netif_rx_schedule(netdev); + } + return IRQ_HANDLED; +} + static int ibmveth_open(struct net_device *netdev) { struct ibmveth_adapter *adapter = netdev->priv; @@ -985,21 +977,6 @@ restart_poll: return 0; } -static irqreturn_t ibmveth_interrupt(int irq, void *dev_instance, - struct pt_regs *regs) -{ - struct net_device *netdev = dev_instance; - struct ibmveth_adapter *adapter = netdev->priv; - unsigned long lpar_rc; - - if (netif_rx_schedule_prep(netdev)) { - lpar_rc = vio_disable_interrupts(adapter->vdev); - ibmveth_assert(lpar_rc == H_Success); - __netif_rx_schedule(netdev); - } - return IRQ_HANDLED; -} - static struct net_device_stats *ibmveth_get_stats(struct net_device *dev) { struct ibmveth_adapter *adapter = dev->priv; @@ -1065,6 +1042,121 @@ static int ibmveth_change_mtu(struct net return 0; } +#ifdef CONFIG_PROC_FS + +#define IBMVETH_PROC_DIR "ibmveth" +static struct proc_dir_entry *ibmveth_proc_dir; + +static void ibmveth_proc_register_driver(void) +{ + ibmveth_proc_dir = create_proc_entry(IBMVETH_PROC_DIR, S_IFDIR, + proc_net); + if (ibmveth_proc_dir) + SET_MODULE_OWNER(ibmveth_proc_dir); +} + +static void ibmveth_proc_unregister_driver(void) +{ + remove_proc_entry(IBMVETH_PROC_DIR, proc_net); +} + +static int ibmveth_seq_show(struct seq_file *seq, void *v) +{ + struct ibmveth_adapter *adapter = seq->private; + char *current_mac = (char *)&adapter->netdev->dev_addr; + char *firmware_mac = (char *)&adapter->mac_addr; + + seq_printf(seq, "%s %s\n\n", ibmveth_driver_string, + ibmveth_driver_version); + seq_printf(seq, "Unit Address: 0x%x\n", adapter->vdev->unit_address); + seq_printf(seq, "LIOBN: 0x%lx\n", + adapter->vdev->iommu_table->it_index); + seq_printf(seq, "Current MAC: %02X:%02X:%02X:%02X:%02X:%02X\n", + current_mac[0], current_mac[1], current_mac[2], + current_mac[3], current_mac[4], current_mac[5]); + seq_printf(seq, "Firmware MAC: %02X:%02X:%02X:%02X:%02X:%02X\n", + firmware_mac[0], firmware_mac[1], firmware_mac[2], + firmware_mac[3], firmware_mac[4], firmware_mac[5]); + seq_printf(seq, "\nAdapter Statistics:\n"); + seq_printf(seq, " TX: skbuffs linearized: %ld\n", + adapter->tx_linearized); + seq_printf(seq, " multi-descriptor sends: %ld\n", + adapter->tx_multidesc_send); + seq_printf(seq, " skb_linearize failures: %ld\n", + adapter->tx_linearize_failed); + seq_printf(seq, " vio_map_single failres: %ld\n", + adapter->tx_map_failed); + seq_printf(seq, " send failures: %ld\n", + adapter->tx_send_failed); + seq_printf(seq, " RX: replenish task cycles: %ld\n", + adapter->replenish_task_cycles); + seq_printf(seq, " alloc_skb_failures: %ld\n", + adapter->replenish_no_mem); + seq_printf(seq, " add buffer failures: %ld\n", + adapter->replenish_add_buff_failure); + seq_printf(seq, " invalid buffers: %ld\n", + adapter->rx_invalid_buffer); + seq_printf(seq, " no buffers: %ld\n", + adapter->rx_no_buffer); + return 0; +} + +static int ibmveth_proc_open(struct inode *inode, struct file *file) +{ + return single_open(file, ibmveth_seq_show, PDE(inode)->data); +} + +static struct file_operations ibmveth_proc_fops = { + .owner = THIS_MODULE, + .open = ibmveth_proc_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + +static void ibmveth_proc_register_adapter(struct ibmveth_adapter *adapter) +{ + struct proc_dir_entry *entry; + + if (ibmveth_proc_dir) { + entry = create_proc_entry(adapter->netdev->name, S_IFREG, + ibmveth_proc_dir); + if (!entry) + ibmveth_error_printk("Cannot create adapter proc entry"); + else { + entry->data = adapter; + entry->proc_fops = &ibmveth_proc_fops; + SET_MODULE_OWNER(entry); + } + } +} + +static void ibmveth_proc_unregister_adapter(struct ibmveth_adapter *adapter) +{ + if (ibmveth_proc_dir) + remove_proc_entry(adapter->netdev->name, ibmveth_proc_dir); +} + +#else /* CONFIG_PROC_FS */ + +static void ibmveth_proc_register_driver(void) +{ +} + +static void ibmveth_proc_unregister_driver(void) +{ +} + +static void ibmveth_proc_register_adapter(struct ibmveth_adapter *adapter) +{ +} + +static void ibmveth_proc_unregister_adapter(struct ibmveth_adapter *adapter) +{ +} + +#endif /* CONFIG_PROC_FS */ + static int __devinit ibmveth_probe(struct vio_dev *dev, const struct vio_device_id *id) { @@ -1122,8 +1214,6 @@ static int __devinit ibmveth_probe(struc adapter->mac_addr = 0; memcpy(&adapter->mac_addr, mac_addr_p, 6); - adapter->liobn = dev->iommu_table->it_index; - netdev->irq = dev->irq; netdev->open = ibmveth_open; netdev->poll = ibmveth_poll; @@ -1180,148 +1270,6 @@ static int __devexit ibmveth_remove(stru return 0; } -#ifdef CONFIG_PROC_FS -static void ibmveth_proc_register_driver(void) -{ - ibmveth_proc_dir = create_proc_entry(IBMVETH_PROC_DIR, S_IFDIR, - proc_net); - if (ibmveth_proc_dir) - SET_MODULE_OWNER(ibmveth_proc_dir); -} - -static void ibmveth_proc_unregister_driver(void) -{ - remove_proc_entry(IBMVETH_PROC_DIR, proc_net); -} - -static void *ibmveth_seq_start(struct seq_file *seq, loff_t *pos) -{ - if (*pos == 0) - return (void *)1; - else - return NULL; -} - -static void *ibmveth_seq_next(struct seq_file *seq, void *v, loff_t *pos) -{ - ++*pos; - return NULL; -} - -static void ibmveth_seq_stop(struct seq_file *seq, void *v) -{ -} - -static int ibmveth_seq_show(struct seq_file *seq, void *v) -{ - struct ibmveth_adapter *adapter = seq->private; - char *current_mac = (char *)&adapter->netdev->dev_addr; - char *firmware_mac = (char *)&adapter->mac_addr; - - seq_printf(seq, "%s %s\n\n", ibmveth_driver_string, - ibmveth_driver_version); - seq_printf(seq, "Unit Address: 0x%x\n", adapter->vdev->unit_address); - seq_printf(seq, "LIOBN: 0x%lx\n", adapter->liobn); - seq_printf(seq, "Current MAC: %02X:%02X:%02X:%02X:%02X:%02X\n", - current_mac[0], current_mac[1], current_mac[2], - current_mac[3], current_mac[4], current_mac[5]); - seq_printf(seq, "Firmware MAC: %02X:%02X:%02X:%02X:%02X:%02X\n", - firmware_mac[0], firmware_mac[1], firmware_mac[2], - firmware_mac[3], firmware_mac[4], firmware_mac[5]); - seq_printf(seq, "\nAdapter Statistics:\n"); - seq_printf(seq, " TX: skbuffs linearized: %ld\n", - adapter->tx_linearized); - seq_printf(seq, " multi-descriptor sends: %ld\n", - adapter->tx_multidesc_send); - seq_printf(seq, " skb_linearize failures: %ld\n", - adapter->tx_linearize_failed); - seq_printf(seq, " vio_map_single failres: %ld\n", - adapter->tx_map_failed); - seq_printf(seq, " send failures: %ld\n", - adapter->tx_send_failed); - seq_printf(seq, " RX: replenish task cycles: %ld\n", - adapter->replenish_task_cycles); - seq_printf(seq, " alloc_skb_failures: %ld\n", - adapter->replenish_no_mem); - seq_printf(seq, " add buffer failures: %ld\n", - adapter->replenish_add_buff_failure); - seq_printf(seq, " invalid buffers: %ld\n", - adapter->rx_invalid_buffer); - seq_printf(seq, " no buffers: %ld\n", - adapter->rx_no_buffer); - return 0; -} -static struct seq_operations ibmveth_seq_ops = { - .start = ibmveth_seq_start, - .next = ibmveth_seq_next, - .stop = ibmveth_seq_stop, - .show = ibmveth_seq_show, -}; - -static int ibmveth_proc_open(struct inode *inode, struct file *file) -{ - struct seq_file *seq; - struct proc_dir_entry *proc; - int rc; - - rc = seq_open(file, &ibmveth_seq_ops); - if (!rc) { - /* recover the pointer buried in proc_dir_entry data */ - seq = file->private_data; - proc = PDE(inode); - seq->private = proc->data; - } - return rc; -} - -static struct file_operations ibmveth_proc_fops = { - .owner = THIS_MODULE, - .open = ibmveth_proc_open, - .read = seq_read, - .llseek = seq_lseek, - .release = seq_release, -}; - -static void ibmveth_proc_register_adapter(struct ibmveth_adapter *adapter) -{ - struct proc_dir_entry *entry; - - if (ibmveth_proc_dir) { - entry = create_proc_entry(adapter->netdev->name, S_IFREG, - ibmveth_proc_dir); - if (!entry) - ibmveth_error_printk("Cannot create adapter proc entry"); - else { - entry->data = adapter; - entry->proc_fops = &ibmveth_proc_fops; - SET_MODULE_OWNER(entry); - } - } -} - -static void ibmveth_proc_unregister_adapter(struct ibmveth_adapter *adapter) -{ - if (ibmveth_proc_dir) - remove_proc_entry(adapter->netdev->name, ibmveth_proc_dir); -} - -#else /* CONFIG_PROC_FS */ -static void ibmveth_proc_register_adapter(struct ibmveth_adapter *adapter) -{ -} - -static void ibmveth_proc_unregister_adapter(struct ibmveth_adapter *adapter) -{ -} -static void ibmveth_proc_register_driver(void) -{ -} - -static void ibmveth_proc_unregister_driver(void) -{ -} -#endif /* CONFIG_PROC_FS */ - static struct vio_device_id ibmveth_device_table[] __devinitdata= { { "network", "IBM,l-lan"}, { "", "" } From sfr at canb.auug.org.au Wed Sep 7 19:52:38 2005 From: sfr at canb.auug.org.au (Stephen Rothwell) Date: Wed, 7 Sep 2005 19:52:38 +1000 Subject: [PATCH] ppc64: iSeries early printk breakage Message-ID: <20050907195238.5523dada.sfr@canb.auug.org.au> The earlier commit 8d9273918635f0301368c01b56c03a6f339e8d51 (Consolidate early console and PPCDBG code) broke iSeries because it caused unregister_console(&udbg_console) to be called unconditionally. iSeries never registers the udbg_console. This just reverts part of the change. Signed-off-by: Stephen Rothwell --- arch/ppc64/kernel/udbg.c | 6 ++++++ 1 files changed, 6 insertions(+), 0 deletions(-) -- Cheers, Stephen Rothwell sfr at canb.auug.org.au http://www.canb.auug.org.au/~sfr/ 234f5032f6ccb4d72e4b74d33af55716b67d8a27 diff --git a/arch/ppc64/kernel/udbg.c b/arch/ppc64/kernel/udbg.c --- a/arch/ppc64/kernel/udbg.c +++ b/arch/ppc64/kernel/udbg.c @@ -158,14 +158,20 @@ static struct console udbg_console = { .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; } /* called by setup_system */ void register_early_udbg_console(void) { + early_console_initialized = 1; register_console(&udbg_console); } -------------- 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/20050907/052785a2/attachment.pgp From hch at lst.de Wed Sep 7 20:49:32 2005 From: hch at lst.de (Christoph Hellwig) Date: Wed, 7 Sep 2005 12:49:32 +0200 Subject: [RFC] SCSI target for IBM Power5 LPAR In-Reply-To: <20050906212801.GB14057@cs.umn.edu> References: <20050906212801.GB14057@cs.umn.edu> Message-ID: <20050907104932.GA14200@lst.de> On Tue, Sep 06, 2005 at 04:28:01PM -0500, Dave C Boutcher wrote: > This device driver provides the SCSI target side of the "virtual > SCSI" on IBM Power5 systems. The initiator side has been in mainline > for a while now (drivers/scsi/ibmvscsi/ibmvscsi.c.) Targets already > exist for AIX and OS/400. Please try to integrate that with the generic scsi target framework at http://developer.berlios.de/projects/stgt/. From miltonm at bga.com Wed Sep 7 21:04:36 2005 From: miltonm at bga.com (Milton Miller) Date: Wed, 7 Sep 2005 06:04:36 -0500 Subject: [PATCH] ppc64: iSeries early printk breakage In-Reply-To: <20050907195238.5523dada.sfr@canb.auug.org.au> References: <20050907195238.5523dada.sfr@canb.auug.org.au> Message-ID: Does anything actually break without this patch? My reading of unregister_console says we will acquire the console semaphore, walk the list, fail to find the console, relase the semaphore, and return. Hmm... unless there is a problem with the console preference code? I don't see anything that should deref a bad pointer, maybe it breaks the preference? From get web: if (console_drivers == NULL) preferred_console = selected_console; else if (console->flags & CON_CONSDEV) console_drivers->flags |= CON_CONSDEV; On Sep 7, 2005, at 4:52 AM, Stephen Rothwell wrote: > The earlier commit 8d9273918635f0301368c01b56c03a6f339e8d51 > (Consolidate early console and PPCDBG code) broke iSeries because > it caused unregister_console(&udbg_console) to be called > unconditionally. iSeries never registers the udbg_console. > > This just reverts part of the change. > > Signed-off-by: Stephen Rothwell > --- > > arch/ppc64/kernel/udbg.c | 6 ++++++ > 1 files changed, 6 insertions(+), 0 deletions(-) > > -- > Cheers, > Stephen Rothwell sfr at canb.auug.org.au > http://www.canb.auug.org.au/~sfr/ > > 234f5032f6ccb4d72e4b74d33af55716b67d8a27 > diff --git a/arch/ppc64/kernel/udbg.c b/arch/ppc64/kernel/udbg.c > --- a/arch/ppc64/kernel/udbg.c > +++ b/arch/ppc64/kernel/udbg.c > @@ -158,14 +158,20 @@ static struct console udbg_console = { > .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; > } > > /* called by setup_system */ > void register_early_udbg_console(void) > { > + early_console_initialized = 1; > register_console(&udbg_console); > } > From sleddog at us.ibm.com Wed Sep 7 22:45:04 2005 From: sleddog at us.ibm.com (Dave C Boutcher) Date: Wed, 7 Sep 2005 07:45:04 -0500 Subject: [RFC] SCSI target for IBM Power5 LPAR In-Reply-To: <20050907104932.GA14200@lst.de> References: <20050906212801.GB14057@cs.umn.edu> <20050907104932.GA14200@lst.de> Message-ID: <20050907124504.GA13614@cs.umn.edu> On Wed, Sep 07, 2005 at 12:49:32PM +0200, Christoph Hellwig wrote: > On Tue, Sep 06, 2005 at 04:28:01PM -0500, Dave C Boutcher wrote: > > This device driver provides the SCSI target side of the "virtual > > SCSI" on IBM Power5 systems. The initiator side has been in mainline > > for a while now (drivers/scsi/ibmvscsi/ibmvscsi.c.) Targets already > > exist for AIX and OS/400. > > Please try to integrate that with the generic scsi target framework at > http://developer.berlios.de/projects/stgt/. There hasn't been a lot of forward progress on stgt in over a year, and there were some issues (lack of scatterlist support, synchronous and serial command execution) that were an issue when last I looked. Vlad, can you comment on the state of stgt and whether you see it being ready for mainline any time soon? -- Dave Boutcher From santil at us.ibm.com Thu Sep 8 00:57:43 2005 From: santil at us.ibm.com (Santiago Leon) Date: Wed, 07 Sep 2005 09:57:43 -0500 Subject: [RFC] SCSI target for IBM Power5 LPAR In-Reply-To: <20050907025932.GU6945@krispykreme> References: <20050906212801.GB14057@cs.umn.edu> <20050907025932.GU6945@krispykreme> Message-ID: <431EFFE7.6070709@us.ibm.com> Hi Anton, > + adapter->max_sectors = MAX_SECTORS; > > Does this mean we are limited to 128kB transfers? Would it be OK to > bump the default? We use MAX_SECTORS (which is actually 127.5kB) because that's the max_sectors of the loopback device (we have a lot of users that like the flexibility of using loopback with the ibmvscsis driver)... It can be bumped up without any problems because there is code that splits requests if they are larger than the target's max_sectors... What would you recommend? 256kB? -- Santiago A. Leon Power Linux Development IBM Linux Technology Center From michaelc at cs.wisc.edu Thu Sep 8 03:17:30 2005 From: michaelc at cs.wisc.edu (Mike Christie) Date: Wed, 07 Sep 2005 12:17:30 -0500 Subject: [RFC] SCSI target for IBM Power5 LPAR In-Reply-To: <20050907215816C.fujita.tomonori@lab.ntt.co.jp> References: <20050906212801.GB14057@cs.umn.edu> <20050907104932.GA14200@lst.de> <20050907124504.GA13614@cs.umn.edu> <20050907215816C.fujita.tomonori@lab.ntt.co.jp> Message-ID: <431F20AA.1090101@cs.wisc.edu> FUJITA Tomonori wrote: > month. We discussed it with Christoph and decided that it would be > better to start from scratch because of the design differences. Some of the things we are trying to improve upon are things that are better supported in 2.6. Some differences: - We will support controller hotplug. - We allow any type of device (dm, scsi, ide, LVM@ etc) as storage. And we do not want hook into SCSI-ml's upper layer drivers and deal with that refcounting if we can help it so we push a lot of code to userspace and only do reads and writes in the kernel. - We also hope to support any block layer target. - As mentioned before, scatterlists by using the block layer's support. There may be more that I am forgetting, but originally we started out by trying to clean up the SCST code for 2.6 and make it resemble SCSI-ml's hotplug model. As we did this it looked like some code could live in userspace and it would end up being a rewrite becuase there was so much to do so we started a new project. We hope to work with Vlad and the SCST developers. From michaelc at cs.wisc.edu Thu Sep 8 03:04:59 2005 From: michaelc at cs.wisc.edu (Mike Christie) Date: Wed, 07 Sep 2005 12:04:59 -0500 Subject: [RFC] SCSI target for IBM Power5 LPAR In-Reply-To: <20050907124504.GA13614@cs.umn.edu> References: <20050906212801.GB14057@cs.umn.edu> <20050907104932.GA14200@lst.de> <20050907124504.GA13614@cs.umn.edu> Message-ID: <431F1DBB.8020107@cs.wisc.edu> Dave C Boutcher wrote: > On Wed, Sep 07, 2005 at 12:49:32PM +0200, Christoph Hellwig wrote: > >>On Tue, Sep 06, 2005 at 04:28:01PM -0500, Dave C Boutcher wrote: >> >>>This device driver provides the SCSI target side of the "virtual >>>SCSI" on IBM Power5 systems. The initiator side has been in mainline >>>for a while now (drivers/scsi/ibmvscsi/ibmvscsi.c.) Targets already >>>exist for AIX and OS/400. >> >>Please try to integrate that with the generic scsi target framework at >>http://developer.berlios.de/projects/stgt/. > > > There hasn't been a lot of forward progress on stgt in over a year, and > there were some issues (lack of scatterlist support, synchronous and > serial command execution) that were an issue when last I looked. > stgt is not scst. It is new. And yes we will have proper support for sccatterlists. We need something similar to what sg and st need so I plan on using the block layer functions that are implemented for those upper layer drivers for stgt. If you want to help out and implement that then that would be good. We are also very early in our design so all comments are welcome. From michaelc at cs.wisc.edu Thu Sep 8 04:56:38 2005 From: michaelc at cs.wisc.edu (Mike Christie) Date: Wed, 07 Sep 2005 13:56:38 -0500 Subject: [RFC] SCSI target for IBM Power5 LPAR In-Reply-To: <431F35D2.7040209@vlnb.net> References: <20050906212801.GB14057@cs.umn.edu> <20050907104932.GA14200@lst.de> <20050907124504.GA13614@cs.umn.edu> <431F35D2.7040209@vlnb.net> Message-ID: <431F37E6.3080706@cs.wisc.edu> Vladislav Bolkhovitin wrote: > Dave C Boutcher wrote: > >> On Wed, Sep 07, 2005 at 12:49:32PM +0200, Christoph Hellwig wrote: >> >>> On Tue, Sep 06, 2005 at 04:28:01PM -0500, Dave C Boutcher wrote: >>> >>>> This device driver provides the SCSI target side of the "virtual >>>> SCSI" on IBM Power5 systems. The initiator side has been in mainline >>>> for a while now (drivers/scsi/ibmvscsi/ibmvscsi.c.) Targets already >>>> exist for AIX and OS/400. >>> >>> >>> Please try to integrate that with the generic scsi target framework at >>> http://developer.berlios.de/projects/stgt/. >> >> >> >> There hasn't been a lot of forward progress on stgt in over a year, and >> there were some issues (lack of scatterlist support, synchronous and >> serial command execution) that were an issue when last I looked. >> >> Vlad, can you comment on the state of stgt and whether you see it >> being ready for mainline any time soon? > > > Sorry, I can see on stgt page only mail lists archive and not from start > (from Aug 22). Mike, can I see stgt code and some design description, > please? You can send it directly on my e-mail address, if necessary. goto the svn page for the code http://developer.berlios.de/svn/?group_id=4492 As for design desc, I do not have anything. It is the evolving source :) We are slowly merging leasons we learned from open-iscsi, your SCST code, the available software and HW targets, and the SCSI ULD's scatterlist code which needs redoing so it is a bit of a mess. From vst at vlnb.net Thu Sep 8 04:47:46 2005 From: vst at vlnb.net (Vladislav Bolkhovitin) Date: Wed, 07 Sep 2005 22:47:46 +0400 Subject: [RFC] SCSI target for IBM Power5 LPAR In-Reply-To: <20050907124504.GA13614@cs.umn.edu> References: <20050906212801.GB14057@cs.umn.edu> <20050907104932.GA14200@lst.de> <20050907124504.GA13614@cs.umn.edu> Message-ID: <431F35D2.7040209@vlnb.net> Dave C Boutcher wrote: > On Wed, Sep 07, 2005 at 12:49:32PM +0200, Christoph Hellwig wrote: > >>On Tue, Sep 06, 2005 at 04:28:01PM -0500, Dave C Boutcher wrote: >> >>>This device driver provides the SCSI target side of the "virtual >>>SCSI" on IBM Power5 systems. The initiator side has been in mainline >>>for a while now (drivers/scsi/ibmvscsi/ibmvscsi.c.) Targets already >>>exist for AIX and OS/400. >> >>Please try to integrate that with the generic scsi target framework at >>http://developer.berlios.de/projects/stgt/. > > > There hasn't been a lot of forward progress on stgt in over a year, and > there were some issues (lack of scatterlist support, synchronous and > serial command execution) that were an issue when last I looked. > > Vlad, can you comment on the state of stgt and whether you see it > being ready for mainline any time soon? Sorry, I can see on stgt page only mail lists archive and not from start (from Aug 22). Mike, can I see stgt code and some design description, please? You can send it directly on my e-mail address, if necessary. Vlad From vst at vlnb.net Thu Sep 8 06:07:13 2005 From: vst at vlnb.net (Vladislav Bolkhovitin) Date: Thu, 08 Sep 2005 00:07:13 +0400 Subject: [RFC] SCSI target for IBM Power5 LPAR/SCST 0.9.3-pre1 published In-Reply-To: <431F37E6.3080706@cs.wisc.edu> References: <20050906212801.GB14057@cs.umn.edu> <20050907104932.GA14200@lst.de> <20050907124504.GA13614@cs.umn.edu> <431F35D2.7040209@vlnb.net> <431F37E6.3080706@cs.wisc.edu> Message-ID: <431F4871.6080905@vlnb.net> Mike Christie wrote: > Vladislav Bolkhovitin wrote: >> Sorry, I can see on stgt page only mail lists archive and not from >> start (from Aug 22). Mike, can I see stgt code and some design >> description, please? You can send it directly on my e-mail address, if >> necessary. > > goto the svn page for the code > http://developer.berlios.de/svn/?group_id=4492 > > As for design desc, I do not have anything. It is the evolving source :) > We are slowly merging leasons we learned from open-iscsi, your SCST > code, the available software and HW targets, and the SCSI ULD's > scatterlist code which needs redoing so it is a bit of a mess. OK, thanks, will try tomorrow. I put SCST 0.9.3-pre1 on its page (http://sourceforge.net/projects/scst/). This is not the latest, but this is the one, which working. At the end of this week I'll try to put there the latest one as well. Hope, you will learn some more lessons from it :). Any comments are welcome. Vlad From jdl at freescale.com Thu Sep 8 06:27:09 2005 From: jdl at freescale.com (jdl at freescale.com) Date: Wed, 07 Sep 2005 15:27:09 -0500 Subject: PATCH Standardize on _ASM_POWERPC header symbol prefix Message-ID: Standardize on _ASM_POWERPC_... prefix for all #include exclusion symbols. Fixup all the non-compliers. include/asm-powerpc/8253pit.h | 8 ++++---- include/asm-powerpc/agp.h | 8 +++----- include/asm-powerpc/bugs.h | 6 +++--- include/asm-powerpc/errno.h | 6 +++--- include/asm-powerpc/ioctl.h | 6 +++--- include/asm-powerpc/ioctls.h | 6 +++--- include/asm-powerpc/linkage.h | 6 +++--- include/asm-powerpc/mc146818rtc.h | 6 +++--- include/asm-powerpc/mman.h | 6 +++--- include/asm-powerpc/module.h | 6 +++--- include/asm-powerpc/namei.h | 14 +++++++------- include/asm-powerpc/poll.h | 6 +++--- include/asm-powerpc/sembuf.h | 6 +++--- include/asm-powerpc/shmbuf.h | 6 +++--- include/asm-powerpc/shmparam.h | 6 +++--- include/asm-powerpc/siginfo.h | 6 +++--- include/asm-powerpc/socket.h | 6 +++--- include/asm-powerpc/sockios.h | 6 +++--- include/asm-powerpc/string.h | 6 +++--- include/asm-powerpc/termbits.h | 6 +++--- include/asm-powerpc/termios.h | 6 +++--- include/asm-powerpc/unaligned.h | 9 +++++---- 22 files changed, 73 insertions(+), 74 deletions(-) Signed-off-by: Jon Loeliger Signed-off-by: Kumar Gala --- diff --git a/include/asm-powerpc/8253pit.h b/include/asm-powerpc/8253pit.h --- a/include/asm-powerpc/8253pit.h +++ b/include/asm-powerpc/8253pit.h @@ -1,10 +1,10 @@ +#ifndef _ASM_POWERPC_8253PIT_H +#define _ASM_POWERPC_8253PIT_H + /* * 8253/8254 Programmable Interval Timer */ -#ifndef _8253PIT_H -#define _8253PIT_H - #define PIT_TICK_RATE 1193182UL -#endif +#endif /* _ASM_POWERPC_8253PIT_H */ diff --git a/include/asm-powerpc/agp.h b/include/asm-powerpc/agp.h --- a/include/asm-powerpc/agp.h +++ b/include/asm-powerpc/agp.h @@ -1,10 +1,8 @@ -#ifndef AGP_H -#define AGP_H 1 +#ifndef _ASM_POWERPC_AGP_H +#define _ASM_POWERPC_AGP_H #include -/* nothing much needed here */ - #define map_page_into_agp(page) #define unmap_page_from_agp(page) #define flush_agp_mappings() @@ -20,4 +18,4 @@ #define free_gatt_pages(table, order) \ free_pages((unsigned long)(table), (order)) -#endif +#endif /* _ASM_POWERPC_AGP_H */ diff --git a/include/asm-powerpc/bugs.h b/include/asm-powerpc/bugs.h --- a/include/asm-powerpc/bugs.h +++ b/include/asm-powerpc/bugs.h @@ -1,5 +1,5 @@ -#ifndef _POWERPC_BUGS_H -#define _POWERPC_BUGS_H +#ifndef _ASM_POWERPC_BUGS_H +#define _ASM_POWERPC_BUGS_H /* * This program is free software; you can redistribute it and/or @@ -15,4 +15,4 @@ extern void check_bugs(void); -#endif /* _POWERPC_BUGS_H */ +#endif /* _ASM_POWERPC_BUGS_H */ diff --git a/include/asm-powerpc/errno.h b/include/asm-powerpc/errno.h --- a/include/asm-powerpc/errno.h +++ b/include/asm-powerpc/errno.h @@ -1,5 +1,5 @@ -#ifndef _PPC_ERRNO_H -#define _PPC_ERRNO_H +#ifndef _ASM_POWERPC_ERRNO_H +#define _ASM_POWERPC_ERRNO_H #include @@ -8,4 +8,4 @@ #define _LAST_ERRNO 516 -#endif +#endif /* _ASM_POWERPC_ERRNO_H */ diff --git a/include/asm-powerpc/ioctl.h b/include/asm-powerpc/ioctl.h --- a/include/asm-powerpc/ioctl.h +++ b/include/asm-powerpc/ioctl.h @@ -1,5 +1,5 @@ -#ifndef _PPC_IOCTL_H -#define _PPC_IOCTL_H +#ifndef _ASM_POWERPC_IOCTL_H +#define _ASM_POWERPC_IOCTL_H /* @@ -66,4 +66,4 @@ extern unsigned int __invalid_size_argum #define IOCSIZE_MASK (_IOC_SIZEMASK << _IOC_SIZESHIFT) #define IOCSIZE_SHIFT (_IOC_SIZESHIFT) -#endif +#endif /* _ASM_POWERPC_IOCTL_H */ diff --git a/include/asm-powerpc/ioctls.h b/include/asm-powerpc/ioctls.h --- a/include/asm-powerpc/ioctls.h +++ b/include/asm-powerpc/ioctls.h @@ -1,5 +1,5 @@ -#ifndef _ASM_PPC_IOCTLS_H -#define _ASM_PPC_IOCTLS_H +#ifndef _ASM_POWERPC_IOCTLS_H +#define _ASM_POWERPC_IOCTLS_H #include @@ -104,4 +104,4 @@ #define TIOCMIWAIT 0x545C /* wait for a change on serial input line(s) */ #define TIOCGICOUNT 0x545D /* read serial port inline interrupt counts */ -#endif /* _ASM_PPC_IOCTLS_H */ +#endif /* _ASM_POWERPC_IOCTLS_H */ diff --git a/include/asm-powerpc/linkage.h b/include/asm-powerpc/linkage.h --- a/include/asm-powerpc/linkage.h +++ b/include/asm-powerpc/linkage.h @@ -1,6 +1,6 @@ -#ifndef __ASM_LINKAGE_H -#define __ASM_LINKAGE_H +#ifndef _ASM_POWERPC_LINKAGE_H +#define _ASM_POWERPC_LINKAGE_H /* Nothing to see here... */ -#endif +#endif /* _ASM_POWERPC_LINKAGE_H */ diff --git a/include/asm-powerpc/mc146818rtc.h b/include/asm-powerpc/mc146818rtc.h --- a/include/asm-powerpc/mc146818rtc.h +++ b/include/asm-powerpc/mc146818rtc.h @@ -1,5 +1,5 @@ -#ifndef _POWERPC_MC146818RTC_H -#define _POWERPC_MC146818RTC_H +#ifndef _ASM_POWERPC_MC146818RTC_H +#define _ASM_POWERPC_MC146818RTC_H /* * Machine dependent access functions for RTC registers. @@ -33,4 +33,4 @@ outb_p((val),RTC_PORT(1)); \ }) #endif /* __KERNEL__ */ -#endif /* _POWERPC_MC146818RTC_H */ +#endif /* _ASM_POWERPC_MC146818RTC_H */ diff --git a/include/asm-powerpc/mman.h b/include/asm-powerpc/mman.h --- a/include/asm-powerpc/mman.h +++ b/include/asm-powerpc/mman.h @@ -1,5 +1,5 @@ -#ifndef _POWERPC_MMAN_H -#define _POWERPC_MMAN_H +#ifndef _ASM_POWERPC_MMAN_H +#define _ASM_POWERPC_MMAN_H /* * This program is free software; you can redistribute it and/or @@ -49,4 +49,4 @@ #define MAP_ANON MAP_ANONYMOUS #define MAP_FILE 0 -#endif /* _POWERPC_MMAN_H */ +#endif /* _ASM_POWERPC_MMAN_H */ diff --git a/include/asm-powerpc/module.h b/include/asm-powerpc/module.h --- a/include/asm-powerpc/module.h +++ b/include/asm-powerpc/module.h @@ -1,5 +1,5 @@ -#ifndef _POWERPC_MODULE_H -#define _POWERPC_MODULE_H +#ifndef _ASM_POWERPC_MODULE_H +#define _ASM_POWERPC_MODULE_H /* * This program is free software; you can redistribute it and/or @@ -74,4 +74,4 @@ struct exception_table_entry; void sort_ex_table(struct exception_table_entry *start, struct exception_table_entry *finish); -#endif /* _POWERPC_MODULE_H */ +#endif /* _ASM_POWERPC_MODULE_H */ diff --git a/include/asm-powerpc/namei.h b/include/asm-powerpc/namei.h --- a/include/asm-powerpc/namei.h +++ b/include/asm-powerpc/namei.h @@ -1,14 +1,14 @@ +#ifndef _ASM_POWERPC_NAMEI_H +#define _ASM_POWERPC_NAMEI_H + +#ifdef __KERNEL__ + /* - * include/asm-ppc/namei.h * Adapted from include/asm-alpha/namei.h * * Included from fs/namei.c */ -#ifdef __KERNEL__ -#ifndef __PPC_NAMEI_H -#define __PPC_NAMEI_H - /* This dummy routine maybe changed to something useful * for /usr/gnemul/ emulation stuff. * Look at asm-sparc/namei.h for details. @@ -16,5 +16,5 @@ #define __emul_prefix() NULL -#endif /* __PPC_NAMEI_H */ -#endif /* __KERNEL__ */ +#endif /* __KERNEL__ */ +#endif /* _ASM_POWERPC_NAMEI_H */ diff --git a/include/asm-powerpc/poll.h b/include/asm-powerpc/poll.h --- a/include/asm-powerpc/poll.h +++ b/include/asm-powerpc/poll.h @@ -1,5 +1,5 @@ -#ifndef __PPC_POLL_H -#define __PPC_POLL_H +#ifndef _ASM_POWERPC_POLL_H +#define _ASM_POWERPC_POLL_H #define POLLIN 0x0001 #define POLLPRI 0x0002 @@ -20,4 +20,4 @@ struct pollfd { short revents; }; -#endif +#endif /* _ASM_POWERPC_POLL_H */ diff --git a/include/asm-powerpc/sembuf.h b/include/asm-powerpc/sembuf.h --- a/include/asm-powerpc/sembuf.h +++ b/include/asm-powerpc/sembuf.h @@ -1,5 +1,5 @@ -#ifndef _POWERPC_SEMBUF_H -#define _POWERPC_SEMBUF_H +#ifndef _ASM_POWERPC_SEMBUF_H +#define _ASM_POWERPC_SEMBUF_H /* * This program is free software; you can redistribute it and/or @@ -33,4 +33,4 @@ struct semid64_ds { unsigned long __unused4; }; -#endif /* _POWERPC_SEMBUF_H */ +#endif /* _ASM_POWERPC_SEMBUF_H */ diff --git a/include/asm-powerpc/shmbuf.h b/include/asm-powerpc/shmbuf.h --- a/include/asm-powerpc/shmbuf.h +++ b/include/asm-powerpc/shmbuf.h @@ -1,5 +1,5 @@ -#ifndef _POWERPC_SHMBUF_H -#define _POWERPC_SHMBUF_H +#ifndef _ASM_POWERPC_SHMBUF_H +#define _ASM_POWERPC_SHMBUF_H /* * This program is free software; you can redistribute it and/or @@ -56,4 +56,4 @@ struct shminfo64 { unsigned long __unused4; }; -#endif /* _POWERPC_SHMBUF_H */ +#endif /* _ASM_POWERPC_SHMBUF_H */ diff --git a/include/asm-powerpc/shmparam.h b/include/asm-powerpc/shmparam.h --- a/include/asm-powerpc/shmparam.h +++ b/include/asm-powerpc/shmparam.h @@ -1,6 +1,6 @@ -#ifndef _PPC_SHMPARAM_H -#define _PPC_SHMPARAM_H +#ifndef _ASM_POWERPC_SHMPARAM_H +#define _ASM_POWERPC_SHMPARAM_H #define SHMLBA PAGE_SIZE /* attach addr a multiple of this */ -#endif /* _PPC_SHMPARAM_H */ +#endif /* _ASM_POWERPC_SHMPARAM_H */ diff --git a/include/asm-powerpc/siginfo.h b/include/asm-powerpc/siginfo.h --- a/include/asm-powerpc/siginfo.h +++ b/include/asm-powerpc/siginfo.h @@ -1,5 +1,5 @@ -#ifndef _POWERPC_SIGINFO_H -#define _POWERPC_SIGINFO_H +#ifndef _ASM_POWERPC_SIGINFO_H +#define _ASM_POWERPC_SIGINFO_H /* * This program is free software; you can redistribute it and/or @@ -15,4 +15,4 @@ #include -#endif /* _POWERPC_SIGINFO_H */ +#endif /* _ASM_POWERPC_SIGINFO_H */ diff --git a/include/asm-powerpc/socket.h b/include/asm-powerpc/socket.h --- a/include/asm-powerpc/socket.h +++ b/include/asm-powerpc/socket.h @@ -1,5 +1,5 @@ -#ifndef _POWERPC_SOCKET_H -#define _POWERPC_SOCKET_H +#ifndef _ASM_POWERPC_SOCKET_H +#define _ASM_POWERPC_SOCKET_H /* * This program is free software; you can redistribute it and/or @@ -56,4 +56,4 @@ #define SO_PEERSEC 31 -#endif /* _POWERPC_SOCKET_H */ +#endif /* _ASM_POWERPC_SOCKET_H */ diff --git a/include/asm-powerpc/sockios.h b/include/asm-powerpc/sockios.h --- a/include/asm-powerpc/sockios.h +++ b/include/asm-powerpc/sockios.h @@ -1,5 +1,5 @@ -#ifndef _POWERPC_SOCKIOS_H -#define _POWERPC_SOCKIOS_H +#ifndef _ASM_POWERPC_SOCKIOS_H +#define _ASM_POWERPC_SOCKIOS_H /* * This program is free software; you can redistribute it and/or @@ -16,4 +16,4 @@ #define SIOCATMARK 0x8905 #define SIOCGSTAMP 0x8906 /* Get stamp */ -#endif /* _POWERPC_SOCKIOS_H */ +#endif /* _ASM_POWERPC_SOCKIOS_H */ diff --git a/include/asm-powerpc/string.h b/include/asm-powerpc/string.h --- a/include/asm-powerpc/string.h +++ b/include/asm-powerpc/string.h @@ -1,5 +1,5 @@ -#ifndef _PPC_STRING_H_ -#define _PPC_STRING_H_ +#ifndef _ASM_POWERPC_STRING_H +#define _ASM_POWERPC_STRING_H #ifdef __KERNEL__ @@ -29,4 +29,4 @@ extern void * memchr(const void *,int,__ #endif /* __KERNEL__ */ -#endif +#endif /* _ASM_POWERPC_STRING_H */ diff --git a/include/asm-powerpc/termbits.h b/include/asm-powerpc/termbits.h --- a/include/asm-powerpc/termbits.h +++ b/include/asm-powerpc/termbits.h @@ -1,5 +1,5 @@ -#ifndef _POWERPC_TERMBITS_H -#define _POWERPC_TERMBITS_H +#ifndef _ASM_POWERPC_TERMBITS_H +#define _ASM_POWERPC_TERMBITS_H /* * This program is free software; you can redistribute it and/or @@ -188,4 +188,4 @@ struct termios { #define TCSADRAIN 1 #define TCSAFLUSH 2 -#endif /* _POWERPC_TERMBITS_H */ +#endif /* _ASM_POWERPC_TERMBITS_H */ diff --git a/include/asm-powerpc/termios.h b/include/asm-powerpc/termios.h --- a/include/asm-powerpc/termios.h +++ b/include/asm-powerpc/termios.h @@ -1,5 +1,5 @@ -#ifndef _POWERPC_TERMIOS_H -#define _POWERPC_TERMIOS_H +#ifndef _ASM_POWERPC_TERMIOS_H +#define _ASM_POWERPC_TERMIOS_H /* * Liberally adapted from alpha/termios.h. In particular, the c_cc[] @@ -233,4 +233,4 @@ struct termio { #endif /* __KERNEL__ */ -#endif /* _POWERPC_TERMIOS_H */ +#endif /* _ASM_POWERPC_TERMIOS_H */ diff --git a/include/asm-powerpc/unaligned.h b/include/asm-powerpc/unaligned.h --- a/include/asm-powerpc/unaligned.h +++ b/include/asm-powerpc/unaligned.h @@ -1,6 +1,7 @@ +#ifndef _ASM_POWERPC_UNALIGNED_H +#define _ASM_POWERPC_UNALIGNED_H + #ifdef __KERNEL__ -#ifndef __PPC_UNALIGNED_H -#define __PPC_UNALIGNED_H /* * The PowerPC can do unaligned accesses itself in big endian mode. @@ -14,5 +15,5 @@ #define put_unaligned(val, ptr) ((void)( *(ptr) = (val) )) -#endif -#endif /* __KERNEL__ */ +#endif /* __KERNEL__ */ +#endif /* _ASM_POWERPC_UNALIGNED_H */ From terry.reynolds2 at us.army.mil Wed Sep 7 23:19:55 2005 From: terry.reynolds2 at us.army.mil (Reynolds, Terry (Contractor-SIMTECH)) Date: Wed, 7 Sep 2005 08:19:55 -0500 Subject: Altivec registers Message-ID: <0D21CBD1298D2C4790E2F2B86D96EC1935946C@amr-ex5.ds.amrdec.army.mil> Hi, Does anyone here know how to fix the configuration of the kernel so that gdb can find the altivec registers? The last time I heard from Andrew Cagney he said : "At the time the code was written it was for a special altivec kernel / build / config. Hence it was only enabled when built powerpc-*-*altivec. Time has passed and that restriction no longer applies. I'll see about removing it." I'll also post to gdb. TIA! Terry Reynolds Simulation Technologies, INC. If you had to identify, in one word, the reason why the human race has not achieved, and never will achieve, its full potential, that word would be "meetings." Dave Barry -------------- next part -------------- An HTML attachment was scrubbed... URL: http://ozlabs.org/pipermail/linuxppc64-dev/attachments/20050907/a965ee67/attachment.htm From jdl at freescale.com Thu Sep 8 06:56:20 2005 From: jdl at freescale.com (jdl at freescale.com) Date: Wed, 07 Sep 2005 15:56:20 -0500 Subject: PATCH ppc: Make check_bugs() static inline Message-ID: Make check_bugs() static inline and remove it from syscalls.c. arch/ppc/kernel/syscalls.c | 4 ---- arch/ppc64/kernel/syscalls.c | 4 ---- include/asm-powerpc/bugs.h | 2 +- 3 files changed, 1 insertions(+), 9 deletions(-) Signed-off-by: Jon Loeliger Signed-off-by: Kumar Gala --- diff --git a/arch/ppc/kernel/syscalls.c b/arch/ppc/kernel/syscalls.c --- a/arch/ppc/kernel/syscalls.c +++ b/arch/ppc/kernel/syscalls.c @@ -41,10 +41,6 @@ #include #include -void -check_bugs(void) -{ -} /* * sys_ipc() is the de-multiplexer for the SysV IPC calls.. diff --git a/arch/ppc64/kernel/syscalls.c b/arch/ppc64/kernel/syscalls.c --- a/arch/ppc64/kernel/syscalls.c +++ b/arch/ppc64/kernel/syscalls.c @@ -46,10 +46,6 @@ extern unsigned long wall_jiffies; -void -check_bugs(void) -{ -} /* * sys_ipc() is the de-multiplexer for the SysV IPC calls.. diff --git a/include/asm-powerpc/bugs.h b/include/asm-powerpc/bugs.h --- a/include/asm-powerpc/bugs.h +++ b/include/asm-powerpc/bugs.h @@ -13,6 +13,6 @@ * architecture-dependent bugs. */ -extern void check_bugs(void); +static inline void check_bugs(void) { } #endif /* _ASM_POWERPC_BUGS_H */ From jdl at freescale.com Thu Sep 8 06:59:48 2005 From: jdl at freescale.com (jdl at freescale.com) Date: Wed, 07 Sep 2005 15:59:48 -0500 Subject: PATCH ppc: Merge a few more include files Message-ID: Merge a few asm-ppc and asm-ppc64 header files. Note: the merge of setup.h intentionally does not carry forward the m68k cruft. That means this patch continues to break the already broken amiga on the ppc32. include/asm-powerpc/msgbuf.h | 33 +++++++++++++++++++ include/asm-powerpc/param.h | 24 ++++++++++++++ include/asm-powerpc/setup.h | 9 +++++ include/asm-powerpc/timex.h | 49 ++++++++++++++++++++++++++++ include/asm-powerpc/topology.h | 70 ++++++++++++++++++++++++++++++++++++++++ include/asm-powerpc/user.h | 55 +++++++++++++++++++++++++++++++ include/asm-ppc/msgbuf.h | 25 -------------- include/asm-ppc/param.h | 24 -------------- include/asm-ppc/setup.h | 14 -------- include/asm-ppc/timex.h | 40 ----------------------- include/asm-ppc/topology.h | 6 --- include/asm-ppc/user.h | 54 ------------------------------- include/asm-ppc64/msgbuf.h | 27 --------------- include/asm-ppc64/param.h | 31 ------------------ include/asm-ppc64/setup.h | 6 --- include/asm-ppc64/timex.h | 26 --------------- include/asm-ppc64/topology.h | 69 --------------------------------------- include/asm-ppc64/user.h | 58 --------------------------------- 18 files changed, 240 insertions(+), 380 deletions(-) Signed-off-by: Jon Loeliger Signed-off-by: Kumar Gala --- diff --git a/include/asm-powerpc/msgbuf.h b/include/asm-powerpc/msgbuf.h new file mode 100644 --- /dev/null +++ b/include/asm-powerpc/msgbuf.h @@ -0,0 +1,33 @@ +#ifndef _ASM_POWERPC_MSGBUF_H +#define _ASM_POWERPC_MSGBUF_H + +/* + * The msqid64_ds structure for the PowerPC architecture. + * Note extra padding because this structure is passed back and forth + * between kernel and user space. + */ + +struct msqid64_ds { + struct ipc64_perm msg_perm; +#ifndef __powerpc64__ + unsigned int __unused1; +#endif + __kernel_time_t msg_stime; /* last msgsnd time */ +#ifndef __powerpc64__ + unsigned int __unused2; +#endif + __kernel_time_t msg_rtime; /* last msgrcv time */ +#ifndef __powerpc64__ + unsigned int __unused3; +#endif + __kernel_time_t msg_ctime; /* last change time */ + unsigned long msg_cbytes; /* current number of bytes on queue */ + unsigned long msg_qnum; /* number of messages in queue */ + unsigned long msg_qbytes; /* max number of bytes on queue */ + __kernel_pid_t msg_lspid; /* pid of last msgsnd */ + __kernel_pid_t msg_lrpid; /* last receive pid */ + unsigned long __unused4; + unsigned long __unused5; +}; + +#endif /* _ASM_POWERPC_MSGBUF_H */ diff --git a/include/asm-powerpc/param.h b/include/asm-powerpc/param.h new file mode 100644 --- /dev/null +++ b/include/asm-powerpc/param.h @@ -0,0 +1,24 @@ +#ifndef _ASM_POWERPC_PARAM_H +#define _ASM_POWERPC_PARAM_H + +#include + +#ifdef __KERNEL__ +#define HZ CONFIG_HZ /* internal kernel timer frequency */ +#define USER_HZ 100 /* for user interfaces in "ticks" */ +#define CLOCKS_PER_SEC (USER_HZ) /* frequency at which times() counts */ +#endif /* __KERNEL__ */ + +#ifndef HZ +#define HZ 100 +#endif + +#define EXEC_PAGESIZE 4096 + +#ifndef NOGROUP +#define NOGROUP (-1) +#endif + +#define MAXHOSTNAMELEN 64 /* max length of hostname */ + +#endif /* _ASM_POWERPC_PARAM_H */ diff --git a/include/asm-powerpc/setup.h b/include/asm-powerpc/setup.h new file mode 100644 --- /dev/null +++ b/include/asm-powerpc/setup.h @@ -0,0 +1,9 @@ +#ifndef _ASM_POWERPC_SETUP_H +#define _ASM_POWERPC_SETUP_H + +#ifdef __KERNEL__ + +#define COMMAND_LINE_SIZE 512 + +#endif /* __KERNEL__ */ +#endif /* _ASM_POWERPC_SETUP_H */ diff --git a/include/asm-powerpc/timex.h b/include/asm-powerpc/timex.h new file mode 100644 --- /dev/null +++ b/include/asm-powerpc/timex.h @@ -0,0 +1,49 @@ +#ifndef _ASM_POWERPC_TIMEX_H +#define _ASM_POWERPC_TIMEX_H + +#ifdef __KERNEL__ + +/* + * PowerPC architecture timex specifications + */ + +#include +#include + +#define CLOCK_TICK_RATE 1193180 /* Underlying HZ */ + +typedef unsigned long cycles_t; + +static inline cycles_t get_cycles(void) +{ + cycles_t ret; + +#ifdef __powerpc64__ + + __asm__ __volatile__("mftb %0" : "=r" (ret) : ); + +#else + /* + * For the "cycle" counter we use the timebase lower half. + * Currently only used on SMP. + */ + + ret = 0; + + __asm__ __volatile__( + "98: mftb %0\n" + "99:\n" + ".section __ftr_fixup,\"a\"\n" + " .long %1\n" + " .long 0\n" + " .long 98b\n" + " .long 99b\n" + ".previous" + : "=r" (ret) : "i" (CPU_FTR_601)); +#endif + + return ret; +} + +#endif /* __KERNEL__ */ +#endif /* _ASM_POWERPC_TIMEX_H */ diff --git a/include/asm-powerpc/topology.h b/include/asm-powerpc/topology.h new file mode 100644 --- /dev/null +++ b/include/asm-powerpc/topology.h @@ -0,0 +1,70 @@ +#ifndef _ASM_POWERPC_TOPOLOGY_H +#define _ASM_POWERPC_TOPOLOGY_H + +#include + +#ifdef CONFIG_NUMA + +#include + +static inline int cpu_to_node(int cpu) +{ + int node; + + node = numa_cpu_lookup_table[cpu]; + +#ifdef DEBUG_NUMA + BUG_ON(node == -1); +#endif + + return node; +} + +#define parent_node(node) (node) + +static inline cpumask_t node_to_cpumask(int node) +{ + return numa_cpumask_lookup_table[node]; +} + +static inline int node_to_first_cpu(int node) +{ + cpumask_t tmp; + tmp = node_to_cpumask(node); + return first_cpu(tmp); +} + +#define pcibus_to_node(node) (-1) +#define pcibus_to_cpumask(bus) (cpu_online_map) + +#define nr_cpus_node(node) (nr_cpus_in_node[node]) + +/* sched_domains SD_NODE_INIT for PPC64 machines */ +#define SD_NODE_INIT (struct sched_domain) { \ + .span = CPU_MASK_NONE, \ + .parent = NULL, \ + .groups = NULL, \ + .min_interval = 8, \ + .max_interval = 32, \ + .busy_factor = 32, \ + .imbalance_pct = 125, \ + .cache_hot_time = (10*1000000), \ + .cache_nice_tries = 1, \ + .per_cpu_gain = 100, \ + .flags = SD_LOAD_BALANCE \ + | SD_BALANCE_EXEC \ + | SD_BALANCE_NEWIDLE \ + | SD_WAKE_IDLE \ + | SD_WAKE_BALANCE, \ + .last_balance = jiffies, \ + .balance_interval = 1, \ + .nr_balance_failed = 0, \ +} + +#else + +#include + +#endif /* CONFIG_NUMA */ + +#endif /* _ASM_POWERPC_TOPOLOGY_H */ diff --git a/include/asm-powerpc/user.h b/include/asm-powerpc/user.h new file mode 100644 --- /dev/null +++ b/include/asm-powerpc/user.h @@ -0,0 +1,55 @@ +#ifndef _ASM_POWERPC_USER_H +#define _ASM_POWERPC_USER_H + +#ifdef __KERNEL__ + +#include +#include + +/* + * Adapted from + * + * Core file format: The core file is written in such a way that gdb + * can understand it and provide useful information to the user (under + * linux we use the `trad-core' bfd, NOT the osf-core). The file contents + * are as follows: + * + * upage: 1 page consisting of a user struct that tells gdb + * what is present in the file. Directly after this is a + * copy of the task_struct, which is currently not used by gdb, + * but it may come in handy at some point. All of the registers + * are stored as part of the upage. The upage should always be + * only one page long. + * data: The data segment follows next. We use current->end_text to + * current->brk to pick up all of the user variables, plus any memory + * that may have been sbrk'ed. No attempt is made to determine if a + * page is demand-zero or if a page is totally unused, we just cover + * the entire range. All of the addresses are rounded in such a way + * that an integral number of pages is written. + * stack: We need the stack information in order to get a meaningful + * backtrace. We need to write the data from usp to + * current->start_stack, so we round each of these in order to be able + * to write an integer number of pages. + */ +struct user { + struct pt_regs regs; /* entire machine state */ + size_t u_tsize; /* text size (pages) */ + size_t u_dsize; /* data size (pages) */ + size_t u_ssize; /* stack size (pages) */ + unsigned long start_code; /* text starting address */ + unsigned long start_data; /* data starting address */ + unsigned long start_stack; /* stack starting address */ + long int signal; /* signal causing core dump */ + struct regs * u_ar0; /* help gdb find registers */ + unsigned long magic; /* identifies a core file */ + char u_comm[32]; /* user command name */ +}; + +#define NBPG PAGE_SIZE +#define UPAGES 1 +#define HOST_TEXT_START_ADDR (u.start_code) +#define HOST_DATA_START_ADDR (u.start_data) +#define HOST_STACK_END_ADDR (u.start_stack + u.u_ssize * NBPG) + +#endif /* __KERNEL__ */ +#endif /* _ASM_POWERPC_USER_H */ diff --git a/include/asm-ppc/msgbuf.h b/include/asm-ppc/msgbuf.h deleted file mode 100644 --- a/include/asm-ppc/msgbuf.h +++ /dev/null @@ -1,25 +0,0 @@ -#ifndef _PPC_MSGBUF_H -#define _PPC_MSGBUF_H - -/* - * The msqid64_ds structure for the PPC architecture. - */ - -struct msqid64_ds { - struct ipc64_perm msg_perm; - unsigned int __unused1; - __kernel_time_t msg_stime; /* last msgsnd time */ - unsigned int __unused2; - __kernel_time_t msg_rtime; /* last msgrcv time */ - unsigned int __unused3; - __kernel_time_t msg_ctime; /* last change time */ - unsigned long msg_cbytes; /* current number of bytes on queue */ - unsigned long msg_qnum; /* number of messages in queue */ - unsigned long msg_qbytes; /* max number of bytes on queue */ - __kernel_pid_t msg_lspid; /* pid of last msgsnd */ - __kernel_pid_t msg_lrpid; /* last receive pid */ - unsigned long __unused4; - unsigned long __unused5; -}; - -#endif /* _PPC_MSGBUF_H */ diff --git a/include/asm-ppc/param.h b/include/asm-ppc/param.h deleted file mode 100644 --- a/include/asm-ppc/param.h +++ /dev/null @@ -1,24 +0,0 @@ -#ifndef _ASM_PPC_PARAM_H -#define _ASM_PPC_PARAM_H - -#include - -#ifdef __KERNEL__ -#define HZ CONFIG_HZ /* internal timer frequency */ -#define USER_HZ 100 /* for user interfaces in "ticks" */ -#define CLOCKS_PER_SEC (USER_HZ) /* frequency at which times() counts */ -#endif /* __KERNEL__ */ - -#ifndef HZ -#define HZ 100 -#endif - -#define EXEC_PAGESIZE 4096 - -#ifndef NOGROUP -#define NOGROUP (-1) -#endif - -#define MAXHOSTNAMELEN 64 /* max length of hostname */ - -#endif diff --git a/include/asm-ppc/setup.h b/include/asm-ppc/setup.h deleted file mode 100644 --- a/include/asm-ppc/setup.h +++ /dev/null @@ -1,14 +0,0 @@ -#ifdef __KERNEL__ -#ifndef _PPC_SETUP_H -#define _PPC_SETUP_H - -#define m68k_num_memory num_memory -#define m68k_memory memory - -#include -/* We have a bigger command line buffer. */ -#undef COMMAND_LINE_SIZE -#define COMMAND_LINE_SIZE 512 - -#endif /* _PPC_SETUP_H */ -#endif /* __KERNEL__ */ diff --git a/include/asm-ppc/timex.h b/include/asm-ppc/timex.h deleted file mode 100644 --- a/include/asm-ppc/timex.h +++ /dev/null @@ -1,40 +0,0 @@ -/* - * include/asm-ppc/timex.h - * - * ppc architecture timex specifications - */ -#ifdef __KERNEL__ -#ifndef _ASMppc_TIMEX_H -#define _ASMppc_TIMEX_H - -#include -#include - -#define CLOCK_TICK_RATE 1193180 /* Underlying HZ */ - -typedef unsigned long cycles_t; - -/* - * For the "cycle" counter we use the timebase lower half. - * Currently only used on SMP. - */ - -static inline cycles_t get_cycles(void) -{ - cycles_t ret = 0; - - __asm__ __volatile__( - "98: mftb %0\n" - "99:\n" - ".section __ftr_fixup,\"a\"\n" - " .long %1\n" - " .long 0\n" - " .long 98b\n" - " .long 99b\n" - ".previous" - : "=r" (ret) : "i" (CPU_FTR_601)); - return ret; -} - -#endif -#endif /* __KERNEL__ */ diff --git a/include/asm-ppc/topology.h b/include/asm-ppc/topology.h deleted file mode 100644 --- a/include/asm-ppc/topology.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef _ASM_PPC_TOPOLOGY_H -#define _ASM_PPC_TOPOLOGY_H - -#include - -#endif /* _ASM_PPC_TOPOLOGY_H */ diff --git a/include/asm-ppc/user.h b/include/asm-ppc/user.h deleted file mode 100644 --- a/include/asm-ppc/user.h +++ /dev/null @@ -1,54 +0,0 @@ -#ifdef __KERNEL__ -#ifndef _PPC_USER_H -#define _PPC_USER_H - -/* Adapted from */ - -#include -#include - -/* - * Core file format: The core file is written in such a way that gdb - * can understand it and provide useful information to the user (under - * linux we use the `trad-core' bfd, NOT the osf-core). The file contents - * are as follows: - * - * upage: 1 page consisting of a user struct that tells gdb - * what is present in the file. Directly after this is a - * copy of the task_struct, which is currently not used by gdb, - * but it may come in handy at some point. All of the registers - * are stored as part of the upage. The upage should always be - * only one page long. - * data: The data segment follows next. We use current->end_text to - * current->brk to pick up all of the user variables, plus any memory - * that may have been sbrk'ed. No attempt is made to determine if a - * page is demand-zero or if a page is totally unused, we just cover - * the entire range. All of the addresses are rounded in such a way - * that an integral number of pages is written. - * stack: We need the stack information in order to get a meaningful - * backtrace. We need to write the data from usp to - * current->start_stack, so we round each of these in order to be able - * to write an integer number of pages. - */ -struct user { - struct pt_regs regs; /* entire machine state */ - size_t u_tsize; /* text size (pages) */ - size_t u_dsize; /* data size (pages) */ - size_t u_ssize; /* stack size (pages) */ - unsigned long start_code; /* text starting address */ - unsigned long start_data; /* data starting address */ - unsigned long start_stack; /* stack starting address */ - long int signal; /* signal causing core dump */ - struct regs * u_ar0; /* help gdb find registers */ - unsigned long magic; /* identifies a core file */ - char u_comm[32]; /* user command name */ -}; - -#define NBPG PAGE_SIZE -#define UPAGES 1 -#define HOST_TEXT_START_ADDR (u.start_code) -#define HOST_DATA_START_ADDR (u.start_data) -#define HOST_STACK_END_ADDR (u.start_stack + u.u_ssize * NBPG) - -#endif /* _PPC_USER_H */ -#endif /* __KERNEL__ */ diff --git a/include/asm-ppc64/msgbuf.h b/include/asm-ppc64/msgbuf.h deleted file mode 100644 --- a/include/asm-ppc64/msgbuf.h +++ /dev/null @@ -1,27 +0,0 @@ -#ifndef _PPC64_MSGBUF_H -#define _PPC64_MSGBUF_H - -/* - * The msqid64_ds structure for the 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. - */ - -struct msqid64_ds { - struct ipc64_perm msg_perm; - __kernel_time_t msg_stime; /* last msgsnd time */ - __kernel_time_t msg_rtime; /* last msgrcv time */ - __kernel_time_t msg_ctime; /* last change time */ - unsigned long msg_cbytes; /* current number of bytes on queue */ - unsigned long msg_qnum; /* number of messages in queue */ - unsigned long msg_qbytes; /* max number of bytes on queue */ - __kernel_pid_t msg_lspid; /* pid of last msgsnd */ - __kernel_pid_t msg_lrpid; /* last receive pid */ - unsigned long __unused1; - unsigned long __unused2; -}; - -#endif /* _PPC64_MSGBUF_H */ diff --git a/include/asm-ppc64/param.h b/include/asm-ppc64/param.h deleted file mode 100644 --- a/include/asm-ppc64/param.h +++ /dev/null @@ -1,31 +0,0 @@ -#ifndef _ASM_PPC64_PARAM_H -#define _ASM_PPC64_PARAM_H - -#include - -/* - * 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__ -# define HZ CONFIG_HZ /* Internal kernel timer frequency */ -# define USER_HZ 100 /* .. some user interfaces are in "ticks" */ -# define CLOCKS_PER_SEC (USER_HZ) /* like times() */ -#endif - -#ifndef HZ -#define HZ 100 -#endif - -#define EXEC_PAGESIZE 4096 - -#ifndef NOGROUP -#define NOGROUP (-1) -#endif - -#define MAXHOSTNAMELEN 64 /* max length of hostname */ - -#endif /* _ASM_PPC64_PARAM_H */ diff --git a/include/asm-ppc64/setup.h b/include/asm-ppc64/setup.h deleted file mode 100644 --- a/include/asm-ppc64/setup.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef _PPC_SETUP_H -#define _PPC_SETUP_H - -#define COMMAND_LINE_SIZE 512 - -#endif /* _PPC_SETUP_H */ diff --git a/include/asm-ppc64/timex.h b/include/asm-ppc64/timex.h deleted file mode 100644 --- a/include/asm-ppc64/timex.h +++ /dev/null @@ -1,26 +0,0 @@ -/* - * linux/include/asm-ppc/timex.h - * - * PPC64 architecture timex specifications - * - * 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 _ASMPPC64_TIMEX_H -#define _ASMPPC64_TIMEX_H - -#define CLOCK_TICK_RATE 1193180 /* Underlying HZ */ - -typedef unsigned long cycles_t; - -static inline cycles_t get_cycles(void) -{ - cycles_t ret; - - __asm__ __volatile__("mftb %0" : "=r" (ret) : ); - return ret; -} - -#endif diff --git a/include/asm-ppc64/topology.h b/include/asm-ppc64/topology.h deleted file mode 100644 --- a/include/asm-ppc64/topology.h +++ /dev/null @@ -1,69 +0,0 @@ -#ifndef _ASM_PPC64_TOPOLOGY_H -#define _ASM_PPC64_TOPOLOGY_H - -#include -#include - -#ifdef CONFIG_NUMA - -static inline int cpu_to_node(int cpu) -{ - int node; - - node = numa_cpu_lookup_table[cpu]; - -#ifdef DEBUG_NUMA - BUG_ON(node == -1); -#endif - - return node; -} - -#define parent_node(node) (node) - -static inline cpumask_t node_to_cpumask(int node) -{ - return numa_cpumask_lookup_table[node]; -} - -static inline int node_to_first_cpu(int node) -{ - cpumask_t tmp; - tmp = node_to_cpumask(node); - return first_cpu(tmp); -} - -#define pcibus_to_node(node) (-1) -#define pcibus_to_cpumask(bus) (cpu_online_map) - -#define nr_cpus_node(node) (nr_cpus_in_node[node]) - -/* sched_domains SD_NODE_INIT for PPC64 machines */ -#define SD_NODE_INIT (struct sched_domain) { \ - .span = CPU_MASK_NONE, \ - .parent = NULL, \ - .groups = NULL, \ - .min_interval = 8, \ - .max_interval = 32, \ - .busy_factor = 32, \ - .imbalance_pct = 125, \ - .cache_hot_time = (10*1000000), \ - .cache_nice_tries = 1, \ - .per_cpu_gain = 100, \ - .flags = SD_LOAD_BALANCE \ - | SD_BALANCE_EXEC \ - | SD_BALANCE_NEWIDLE \ - | SD_WAKE_IDLE \ - | SD_WAKE_BALANCE, \ - .last_balance = jiffies, \ - .balance_interval = 1, \ - .nr_balance_failed = 0, \ -} - -#else - -#include - -#endif /* CONFIG_NUMA */ - -#endif /* _ASM_PPC64_TOPOLOGY_H */ diff --git a/include/asm-ppc64/user.h b/include/asm-ppc64/user.h deleted file mode 100644 --- a/include/asm-ppc64/user.h +++ /dev/null @@ -1,58 +0,0 @@ -#ifndef _PPC_USER_H -#define _PPC_USER_H - -/* Adapted from - * - * 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 - -/* - * Core file format: The core file is written in such a way that gdb - * can understand it and provide useful information to the user (under - * linux we use the `trad-core' bfd, NOT the osf-core). The file contents - * are as follows: - * - * upage: 1 page consisting of a user struct that tells gdb - * what is present in the file. Directly after this is a - * copy of the task_struct, which is currently not used by gdb, - * but it may come in handy at some point. All of the registers - * are stored as part of the upage. The upage should always be - * only one page long. - * data: The data segment follows next. We use current->end_text to - * current->brk to pick up all of the user variables, plus any memory - * that may have been sbrk'ed. No attempt is made to determine if a - * page is demand-zero or if a page is totally unused, we just cover - * the entire range. All of the addresses are rounded in such a way - * that an integral number of pages is written. - * stack: We need the stack information in order to get a meaningful - * backtrace. We need to write the data from usp to - * current->start_stack, so we round each of these in order to be able - * to write an integer number of pages. - */ -struct user { - struct pt_regs regs; /* entire machine state */ - size_t u_tsize; /* text size (pages) */ - size_t u_dsize; /* data size (pages) */ - size_t u_ssize; /* stack size (pages) */ - unsigned long start_code; /* text starting address */ - unsigned long start_data; /* data starting address */ - unsigned long start_stack; /* stack starting address */ - long int signal; /* signal causing core dump */ - struct regs * u_ar0; /* help gdb find registers */ - unsigned long magic; /* identifies a core file */ - char u_comm[32]; /* user command name */ -}; - -#define NBPG PAGE_SIZE -#define UPAGES 1 -#define HOST_TEXT_START_ADDR (u.start_code) -#define HOST_DATA_START_ADDR (u.start_data) -#define HOST_STACK_END_ADDR (u.start_stack + u.u_ssize * NBPG) - -#endif /* _PPC_USER_H */ From linas at austin.ibm.com Thu Sep 8 08:28:16 2005 From: linas at austin.ibm.com (linas) Date: Wed, 7 Sep 2005 17:28:16 -0500 Subject: Invert sense of SLB class bit In-Reply-To: <20050906210322.GA24574@kevlar.burdell.org> References: <20050906045947.GB8628@localhost.localdomain> <20050906210322.GA24574@kevlar.burdell.org> Message-ID: <20050907222816.GE30028@austin.ibm.com> On Tue, Sep 06, 2005 at 05:03:22PM -0400, Sonny Rao was heard to remark: > On Tue, Sep 06, 2005 at 02:59:47PM +1000, David Gibson wrote: > > 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. Antonb had been talking about something like this more than a year ago ... as there was code added to not flush the 0xc segment. Did that code not work? Or did it get broken? Or was it never submitted upstream? Or is this a patch to not flush kernel erats on machines with more than 16GB memory? --linas From linas at austin.ibm.com Thu Sep 8 08:35:38 2005 From: linas at austin.ibm.com (linas) Date: Wed, 7 Sep 2005 17:35:38 -0500 Subject: [RFC] broken installkernel.sh with CROSS_COMPILE In-Reply-To: <1125693554.26605.10.camel@localhost> References: <1125693554.26605.10.camel@localhost> Message-ID: <20050907223538.GF30028@austin.ibm.com> On Fri, Sep 02, 2005 at 01:39:13PM -0700, Dave Hansen was heard to remark: > 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: > > 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: Try this: # path to compilers and binutils, user may override by setting # CROSS_PATH in environment CROSS_PATH=${CROSS_PATH:-/opt/cross-3.3.2/bin} CROSS_COMPILE=powerpc64-linux- export PATH=$CROSS_PATH:$PATH echo "using toolchain from $CROSS_PATH" --linas From paulus at samba.org Thu Sep 8 08:45:17 2005 From: paulus at samba.org (Paul Mackerras) Date: Thu, 8 Sep 2005 08:45:17 +1000 Subject: Invert sense of SLB class bit In-Reply-To: <20050907222816.GE30028@austin.ibm.com> References: <20050906045947.GB8628@localhost.localdomain> <20050906210322.GA24574@kevlar.burdell.org> <20050907222816.GE30028@austin.ibm.com> Message-ID: <17183.28029.403381.741907@cargo.ozlabs.ibm.com> linas writes: > Antonb had been talking about something like this more than a year > ago ... as there was code added to not flush the 0xc segment. > Did that code not work? Or did it get broken? Or was it never > submitted upstream? No, this is entirely different. POWER5 creates ERAT entries for pages which are accessed in real mode (these are created automatically by the hardware as needed). In other words, *all* accesses go through the ERAT, there isn't a bypass for real mode. The real-mode ERAT entries are created with C=0, so by using C=0 for user mappings we were blowing away all the real-mode entries on every context switch. Paul. From dave at sr71.net Thu Sep 8 08:53:51 2005 From: dave at sr71.net (Dave Hansen) Date: Wed, 07 Sep 2005 15:53:51 -0700 Subject: [RFC] broken installkernel.sh with CROSS_COMPILE In-Reply-To: <20050907223538.GF30028@austin.ibm.com> References: <1125693554.26605.10.camel@localhost> <20050907223538.GF30028@austin.ibm.com> Message-ID: <1126133631.6354.2.camel@localhost> On Wed, 2005-09-07 at 17:35 -0500, linas wrote: > On Fri, Sep 02, 2005 at 01:39:13PM -0700, Dave Hansen was heard to remark: > > 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: > > > > 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: > > Try this: > > # path to compilers and binutils, user may override by setting > # CROSS_PATH in environment > CROSS_PATH=${CROSS_PATH:-/opt/cross-3.3.2/bin} > > CROSS_COMPILE=powerpc64-linux- > > export PATH=$CROSS_PATH:$PATH > > echo "using toolchain from $CROSS_PATH" I'm not sure I understand. Where should that be done? -- Dave From viro at ZenIV.linux.org.uk Thu Sep 8 08:28:32 2005 From: viro at ZenIV.linux.org.uk (viro at ZenIV.linux.org.uk) Date: Wed, 7 Sep 2005 23:28:32 +0100 Subject: [PATCH] CHECKFLAGS on ppc64 got broken Message-ID: <20050907222832.GH13549@ZenIV.linux.org.uk> Now that asm-powerpc/* is using ifdefs on __powerpc64__ we need to add it to CHECKFLAGS on ppc64. Signed-off-by: Al Viro ---- diff -urN RC13-git7-simserial/arch/ppc64/Makefile RC13-git7-ppc64-sparse/arch/ppc64/Makefile --- RC13-git7-simserial/arch/ppc64/Makefile 2005-09-05 07:05:14.000000000 -0400 +++ RC13-git7-ppc64-sparse/arch/ppc64/Makefile 2005-09-07 13:55:41.000000000 -0400 @@ -49,7 +49,7 @@ endif -CHECKFLAGS += -m64 -D__powerpc__ +CHECKFLAGS += -m64 -D__powerpc__ -D__powerpc64__ LDFLAGS := -m elf64ppc LDFLAGS_vmlinux := -Bstatic -e $(KERNELLOAD) -Ttext $(KERNELLOAD) From sfr at canb.auug.org.au Thu Sep 8 11:01:15 2005 From: sfr at canb.auug.org.au (Stephen Rothwell) Date: Thu, 8 Sep 2005 11:01:15 +1000 Subject: [PATCH] ppc64: iSeries early printk breakage In-Reply-To: References: <20050907195238.5523dada.sfr@canb.auug.org.au> Message-ID: <20050908110115.1f1bce0c.sfr@canb.auug.org.au> On Wed, 7 Sep 2005 06:04:36 -0500 Milton Miller wrote: > > Does anything actually break without this patch? Yes, an iSeries box will not boot. > My reading of unregister_console says we will acquire > the console semaphore, walk the list, fail to find the > console, relase the semaphore, and return. Consider the case that console_drivers == NULL (because we have never called register_console). unregister_console dereferences console_drivers ... -- 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/20050908/5fd1e694/attachment.pgp From galak at freescale.com Thu Sep 8 04:55:15 2005 From: galak at freescale.com (Kumar Gala) Date: Wed, 7 Sep 2005 13:55:15 -0500 (CDT) Subject: [PATCH] ppc: Moved ASM_CONST macro into ppc_asm.h Message-ID: Moved the ASM_CONST macro into ppc_asm for ppc32 and ppc64 since that seems like a much better place for it long term. Also, by adding the macro to ppc32 it will ease some future merging of code into arch/powerpc. Signed-off-by: Kumar Gala --- commit f56255eddd631902e3835bf7cdd8d94e69799097 tree 82c222d64fdccbaed25e302816fd4cf6237e8d56 parent 71c22e7cc4bf30119761b60b26c498d7b9d33e36 author Kumar K. Gala Wed, 07 Sep 2005 13:53:35 -0500 committer Kumar K. Gala Wed, 07 Sep 2005 13:53:35 -0500 include/asm-ppc/ppc_asm.h | 12 ++++++++++++ include/asm-ppc64/cputable.h | 2 +- include/asm-ppc64/mmu.h | 1 + include/asm-ppc64/page.h | 8 +------- include/asm-ppc64/ppc_asm.h | 7 +++++++ 5 files changed, 22 insertions(+), 8 deletions(-) diff --git a/include/asm-ppc/ppc_asm.h b/include/asm-ppc/ppc_asm.h --- a/include/asm-ppc/ppc_asm.h +++ b/include/asm-ppc/ppc_asm.h @@ -11,6 +11,9 @@ * 2 of the License, or (at your option) any later version. */ +#ifndef __PPC_ASM_H +#define __PPC_ASM_H + #include /* @@ -348,3 +351,12 @@ END_FTR_SECTION_IFCLR(CPU_FTR_601) #define N_RSYM 64 #define N_SLINE 68 #define N_SO 100 + +#ifdef __ASSEMBLY__ + #define ASM_CONST(x) x +#else + #define __ASM_CONST(x) x##UL + #define ASM_CONST(x) __ASM_CONST(x) +#endif + +#endif /* __PPC_ASM_H */ diff --git a/include/asm-ppc64/cputable.h b/include/asm-ppc64/cputable.h --- a/include/asm-ppc64/cputable.h +++ b/include/asm-ppc64/cputable.h @@ -16,7 +16,7 @@ #define __ASM_PPC_CPUTABLE_H #include -#include /* for ASM_CONST */ +#include /* for ASM_CONST */ /* Exposed to userland CPU features - Must match ppc32 definitions */ #define PPC_FEATURE_32 0x80000000 diff --git a/include/asm-ppc64/mmu.h b/include/asm-ppc64/mmu.h --- a/include/asm-ppc64/mmu.h +++ b/include/asm-ppc64/mmu.h @@ -14,6 +14,7 @@ #define _PPC64_MMU_H_ #include +#include /* for ASM_CONST */ #include /* diff --git a/include/asm-ppc64/page.h b/include/asm-ppc64/page.h --- a/include/asm-ppc64/page.h +++ b/include/asm-ppc64/page.h @@ -11,13 +11,7 @@ */ #include - -#ifdef __ASSEMBLY__ - #define ASM_CONST(x) x -#else - #define __ASM_CONST(x) x##UL - #define ASM_CONST(x) __ASM_CONST(x) -#endif +#include /* for ASM_CONST */ /* PAGE_SHIFT determines the page size */ #define PAGE_SHIFT 12 diff --git a/include/asm-ppc64/ppc_asm.h b/include/asm-ppc64/ppc_asm.h --- a/include/asm-ppc64/ppc_asm.h +++ b/include/asm-ppc64/ppc_asm.h @@ -239,4 +239,11 @@ #define vr30 30 #define vr31 31 +#ifdef __ASSEMBLY__ + #define ASM_CONST(x) x +#else + #define __ASM_CONST(x) x##UL + #define ASM_CONST(x) __ASM_CONST(x) +#endif + #endif /* _PPC64_PPC_ASM_H */ From sonny at burdell.org Thu Sep 8 16:19:15 2005 From: sonny at burdell.org (Sonny Rao) Date: Thu, 8 Sep 2005 02:19:15 -0400 Subject: Invert sense of SLB class bit In-Reply-To: <17183.28029.403381.741907@cargo.ozlabs.ibm.com> References: <20050906045947.GB8628@localhost.localdomain> <20050906210322.GA24574@kevlar.burdell.org> <20050907222816.GE30028@austin.ibm.com> <17183.28029.403381.741907@cargo.ozlabs.ibm.com> Message-ID: <20050908061915.GA26376@kevlar.burdell.org> On Thu, Sep 08, 2005 at 08:45:17AM +1000, Paul Mackerras wrote: > linas writes: > > > Antonb had been talking about something like this more than a year > > ago ... as there was code added to not flush the 0xc segment. > > Did that code not work? Or did it get broken? Or was it never > > submitted upstream? > > No, this is entirely different. POWER5 creates ERAT entries for pages > which are accessed in real mode (these are created automatically by > the hardware as needed). In other words, *all* accesses go through > the ERAT, there isn't a bypass for real mode. The real-mode ERAT > entries are created with C=0, so by using C=0 for user mappings we > were blowing away all the real-mode entries on every context switch. So, when exactly do we go into real mode ? I know the SLB handler is now run in real mode, but is anything else? If we want to look at best-case improvements -- meaning a lot of SLB reloading and userspace context-switching, I suppose I should select a machine with a fair amount of memory. Either way, I'm going to run SDET on a 2-way box w/ 8GB of RAM and see if I can find a difference. If necessary, I'll find a bigger box to test on. Sonny From paulus at samba.org Thu Sep 8 16:33:57 2005 From: paulus at samba.org (Paul Mackerras) Date: Thu, 8 Sep 2005 16:33:57 +1000 Subject: Invert sense of SLB class bit In-Reply-To: <20050908061915.GA26376@kevlar.burdell.org> References: <20050906045947.GB8628@localhost.localdomain> <20050906210322.GA24574@kevlar.burdell.org> <20050907222816.GE30028@austin.ibm.com> <17183.28029.403381.741907@cargo.ozlabs.ibm.com> <20050908061915.GA26376@kevlar.burdell.org> Message-ID: <17183.56149.226292.708140@cargo.ozlabs.ibm.com> Sonny Rao writes: > So, when exactly do we go into real mode ? I know the SLB handler is > now run in real mode, but is anything else? On every interrupt and exception (including system calls); i.e. every time we enter the kernel. A few are handled entirely in real mode, but for most we do a small amount of exception entry code and then do an rfid instruction to turn the MMU back on. > If we want to look at best-case improvements -- meaning a lot of SLB > reloading and userspace context-switching, I suppose I should select a > machine with a fair amount of memory. > > Either way, I'm going to run SDET on a 2-way box w/ 8GB of RAM and see > if I can find a difference. If necessary, I'll find a bigger box to > test on. SDET sounds like a good choice, since it will do lots of system calls as well as context switches. Is this a POWER5 machine? Paul. From sonny at burdell.org Thu Sep 8 16:57:11 2005 From: sonny at burdell.org (Sonny Rao) Date: Thu, 8 Sep 2005 02:57:11 -0400 Subject: Invert sense of SLB class bit In-Reply-To: <17183.56149.226292.708140@cargo.ozlabs.ibm.com> References: <20050906045947.GB8628@localhost.localdomain> <20050906210322.GA24574@kevlar.burdell.org> <20050907222816.GE30028@austin.ibm.com> <17183.28029.403381.741907@cargo.ozlabs.ibm.com> <20050908061915.GA26376@kevlar.burdell.org> <17183.56149.226292.708140@cargo.ozlabs.ibm.com> Message-ID: <20050908065711.GA27791@kevlar.burdell.org> On Thu, Sep 08, 2005 at 04:33:57PM +1000, Paul Mackerras wrote: > Sonny Rao writes: > > > So, when exactly do we go into real mode ? I know the SLB handler is > > now run in real mode, but is anything else? > > On every interrupt and exception (including system calls); i.e. every > time we enter the kernel. A few are handled entirely in real mode, > but for most we do a small amount of exception entry code and then do > an rfid instruction to turn the MMU back on. > > > If we want to look at best-case improvements -- meaning a lot of SLB > > reloading and userspace context-switching, I suppose I should select a > > machine with a fair amount of memory. > > > > Either way, I'm going to run SDET on a 2-way box w/ 8GB of RAM and see > > if I can find a difference. If necessary, I'll find a bigger box to > > test on. > > SDET sounds like a good choice, since it will do lots of system calls > as well as context switches. > > Is this a POWER5 machine? Yes, actually a GS machine (SF2+). Sonny From kumar.gala at freescale.com Fri Sep 9 02:28:54 2005 From: kumar.gala at freescale.com (Kumar Gala) Date: Thu, 8 Sep 2005 11:28:54 -0500 Subject: r13 is non-volatile? Message-ID: <0C620F0B-92B0-4EBF-BC0C-49FD4D3D4323@freescale.com> Was looking at merging some code between ppc32 & ppc64 and noticed that in ppc32 we consider r13 to be part of the non-volatile register set. Is this really correct? r13 is suppose to be sdata pointer in ppc32 and system thread id in ppc64. So I'm wondering should we really be considering it NV on ppc32? PPC32: #define SAVE_NVGPRS(base) SAVE_GPR(13, base); SAVE_8GPRS(14, base); \ SAVE_10GPRS(22, base) #define REST_NVGPRS(base) REST_GPR(13, base); REST_8GPRS(14, base); \ REST_10GPRS(22, base) PPC64: #define SAVE_NVGPRS(base) SAVE_8GPRS(14, base); SAVE_10GPRS(22, base) #define REST_NVGPRS(base) REST_8GPRS(14, base); REST_10GPRS(22, base) - kumar From segher at kernel.crashing.org Fri Sep 9 03:01:18 2005 From: segher at kernel.crashing.org (Segher Boessenkool) Date: Thu, 8 Sep 2005 19:01:18 +0200 Subject: r13 is non-volatile? In-Reply-To: <0C620F0B-92B0-4EBF-BC0C-49FD4D3D4323@freescale.com> References: <0C620F0B-92B0-4EBF-BC0C-49FD4D3D4323@freescale.com> Message-ID: > Was looking at merging some code between ppc32 & ppc64 and noticed > that in ppc32 we consider r13 to be part of the non-volatile register > set. Is this really correct? I believe so, yes. > r13 is suppose to be sdata pointer in ppc32 sdata pointer is non-volatile by definition... > and system thread id in ppc64. The 64-bit kernel uses GPR13 as the PACA pointer, so it handles it specially -- it treats the userland values of the register as non-volatile, though. > So I'm wondering should we really be considering it NV on ppc32? Yeah. I'm sure there is some way to make the macro's identical between 32- and 64-bit, though. Segher From kumar.gala at freescale.com Fri Sep 9 04:29:33 2005 From: kumar.gala at freescale.com (Kumar Gala) Date: Thu, 8 Sep 2005 13:29:33 -0500 Subject: can we kill CONFIG_PPC64BRIDGE? Message-ID: <5AB80D6D-C8B0-4F08-9C06-A56119D5D696@freescale.com> Paul, Can we kill CONFIG_PPC64BRIDGE for ppc32... Not sure if anyone is using this or not? - kumar From sonny at burdell.org Fri Sep 9 04:32:04 2005 From: sonny at burdell.org (Sonny Rao) Date: Thu, 8 Sep 2005 14:32:04 -0400 Subject: Invert sense of SLB class bit In-Reply-To: <20050908065711.GA27791@kevlar.burdell.org> References: <20050906045947.GB8628@localhost.localdomain> <20050906210322.GA24574@kevlar.burdell.org> <20050907222816.GE30028@austin.ibm.com> <17183.28029.403381.741907@cargo.ozlabs.ibm.com> <20050908061915.GA26376@kevlar.burdell.org> <17183.56149.226292.708140@cargo.ozlabs.ibm.com> <20050908065711.GA27791@kevlar.burdell.org> Message-ID: <20050908183204.GA24291@kevlar.burdell.org> On Thu, Sep 08, 2005 at 02:57:11AM -0400, Sonny Rao wrote: > On Thu, Sep 08, 2005 at 04:33:57PM +1000, Paul Mackerras wrote: > > Sonny Rao writes: > > > > > So, when exactly do we go into real mode ? I know the SLB handler is > > > now run in real mode, but is anything else? > > > > On every interrupt and exception (including system calls); i.e. every > > time we enter the kernel. A few are handled entirely in real mode, > > but for most we do a small amount of exception entry code and then do > > an rfid instruction to turn the MMU back on. > > > > > If we want to look at best-case improvements -- meaning a lot of SLB > > > reloading and userspace context-switching, I suppose I should select a > > > machine with a fair amount of memory. > > > > > > Either way, I'm going to run SDET on a 2-way box w/ 8GB of RAM and see > > > if I can find a difference. If necessary, I'll find a bigger box to > > > test on. > > > > SDET sounds like a good choice, since it will do lots of system calls > > as well as context switches. Ok here are the results for 1,4,16, and 64 procs on stock 2.6.13 and 2.6.13 plus the patch. the tests were run three times and averaged with the std. dev in parens Kernel 1 proc 4 procs 16 procs 64 procs -- -- -- -- -- stock 4580 (29) 14757 (215) 15246 (244) 15317 (52) patched 4556 (51) 14694 (116) 15320 (293) 15390 (38) delta -0.05 % -0.04 % +0.05 % +0.05 % In all cases except 64 procs, the std. deviation is bigger than the difference. Sonny From kumar.gala at freescale.com Fri Sep 9 04:42:34 2005 From: kumar.gala at freescale.com (Kumar Gala) Date: Thu, 8 Sep 2005 13:42:34 -0500 Subject: RFC: merging of cputables between ppc32/64 Message-ID: <268E83D3-853C-4752-88D1-A7354E924C07@freescale.com> I was hoping to get some idea on which direction we wanted to head with cputable between ppc32/64. The only major difference that exists between the two is the use of cpu_setup(). On ppc32, cpu_setup is called for each processor in an SMP configuration. Which gives us the following signature: typedef void (*cpu_setup_t)(unsigned long offset, int cpu_nr, struct cpu_spec* spec); On ppc64, cpu_setup is only called for the boot cpu. It is left to the cpu save/restore functions to handle setting up the state for additional CPUs. Which gives is the following signature: typedef void (*cpu_setup_t)(unsigned long offset, struct cpu_spec* spec); So my question is do we just extend the ppc64 signature to match the ppc32 by having a dummy "int cpu_nr" that is ignored or do we do something else? As far as I can tell cpu_nr is only used by ppc32 as temp storage so that the cpu_setup functions can return properly. - kumar From sonny at burdell.org Fri Sep 9 04:41:35 2005 From: sonny at burdell.org (Sonny Rao) Date: Thu, 8 Sep 2005 14:41:35 -0400 Subject: Invert sense of SLB class bit In-Reply-To: <20050908183204.GA24291@kevlar.burdell.org> References: <20050906045947.GB8628@localhost.localdomain> <20050906210322.GA24574@kevlar.burdell.org> <20050907222816.GE30028@austin.ibm.com> <17183.28029.403381.741907@cargo.ozlabs.ibm.com> <20050908061915.GA26376@kevlar.burdell.org> <17183.56149.226292.708140@cargo.ozlabs.ibm.com> <20050908065711.GA27791@kevlar.burdell.org> <20050908183204.GA24291@kevlar.burdell.org> Message-ID: <20050908184135.GA25605@kevlar.burdell.org> On Thu, Sep 08, 2005 at 02:32:04PM -0400, Sonny Rao wrote: > On Thu, Sep 08, 2005 at 02:57:11AM -0400, Sonny Rao wrote: > > On Thu, Sep 08, 2005 at 04:33:57PM +1000, Paul Mackerras wrote: > > > Sonny Rao writes: > > > > > > > So, when exactly do we go into real mode ? I know the SLB handler is > > > > now run in real mode, but is anything else? > > > > > > On every interrupt and exception (including system calls); i.e. every > > > time we enter the kernel. A few are handled entirely in real mode, > > > but for most we do a small amount of exception entry code and then do > > > an rfid instruction to turn the MMU back on. > > > > > > > If we want to look at best-case improvements -- meaning a lot of SLB > > > > reloading and userspace context-switching, I suppose I should select a > > > > machine with a fair amount of memory. > > > > > > > > Either way, I'm going to run SDET on a 2-way box w/ 8GB of RAM and see > > > > if I can find a difference. If necessary, I'll find a bigger box to > > > > test on. > > > > > > SDET sounds like a good choice, since it will do lots of system calls > > > as well as context switches. > > Ok here are the results for 1,4,16, and 64 procs on stock 2.6.13 and > 2.6.13 plus the patch. > > the tests were run three times and averaged with the std. dev in parens > > Kernel 1 proc 4 procs 16 procs 64 procs > -- -- -- -- -- > stock 4580 (29) 14757 (215) 15246 (244) 15317 (52) > patched 4556 (51) 14694 (116) 15320 (293) 15390 (38) > > delta -0.05 % -0.04 % +0.05 % +0.05 % > > In all cases except 64 procs, the std. deviation is bigger than the > difference. Erk, I messed up, the percentages are off by a factor of ten, it should be: delta -0.5 % -0.4 % +0.5 % +0.5 % So, tenths of a percent rather than hundredths Sonny From jdl at freescale.com Fri Sep 9 05:05:49 2005 From: jdl at freescale.com (jdl at freescale.com) Date: Thu, 08 Sep 2005 14:05:49 -0500 Subject: PATCH Fix __power64__ typos that should be __powerpc64__ Message-ID: Fix __power64__ typo that should be __powerpc64__ instead. include/asm-powerpc/shmbuf.h | 8 ++++---- 1 files changed, 4 insertions(+), 4 deletions(-) Signed-off-by: Jon Loeliger Signed-off-by: Kumar Gala --- diff --git a/include/asm-powerpc/shmbuf.h b/include/asm-powerpc/shmbuf.h --- a/include/asm-powerpc/shmbuf.h +++ b/include/asm-powerpc/shmbuf.h @@ -21,19 +21,19 @@ struct shmid64_ds { struct ipc64_perm shm_perm; /* operation perms */ -#ifndef __power64__ +#ifndef __powerpc64__ unsigned long __unused1; #endif __kernel_time_t shm_atime; /* last attach time */ -#ifndef __power64__ +#ifndef __powerpc64__ unsigned long __unused2; #endif __kernel_time_t shm_dtime; /* last detach time */ -#ifndef __power64__ +#ifndef __powerpc64__ unsigned long __unused3; #endif __kernel_time_t shm_ctime; /* last change time */ -#ifndef __power64__ +#ifndef __powerpc64__ unsigned long __unused4; #endif size_t shm_segsz; /* size of segment (bytes) */ From rcjenn at austin.ibm.com Fri Sep 9 05:04:01 2005 From: rcjenn at austin.ibm.com (Robert Jennings) Date: Thu, 8 Sep 2005 14:04:01 -0500 Subject: [PATCH] Add PTRACE_{GET|SET}VRREGS In-Reply-To: <20050901100910.GA27213@krispykreme> References: <20050901100910.GA27213@krispykreme> Message-ID: <20050908190401.GB3416@austin.ibm.com> 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. Updated with the suggestions from Anton following the lines of his code snippet. Added: - flush_altivec_to_thread calls as suggested by Anton - piecewise copy of structure to preserve 32-bit vrsave data as per Anton Appologies if this gets to the list twice, I had an MTA issue earlier. Signed-off-by: Robert C Jennings --- ptrace.c | 58 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ptrace32.c | 58 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 116 insertions(+) diff -uprN -X linux-2.6.12.3.orig/Documentation/dontdiff linux-2.6.12.3.orig/arch/ppc64/kernel/ptrace32.c linux-2.6.12.3/arch/ppc64/kernel/ptrace32.c --- linux-2.6.12.3.orig/arch/ppc64/kernel/ptrace32.c 2005-09-06 17:07:48.000000000 -0500 +++ linux-2.6.12.3/arch/ppc64/kernel/ptrace32.c 2005-09-06 17:12:11.735819943 -0500 @@ -409,6 +409,64 @@ int sys32_ptrace(long request, long pid, ret = put_user(child->ptrace_message, (unsigned int __user *) data); break; +#ifdef CONFIG_ALTIVEC +/* + * 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. + */ + case PTRACE_GETVRREGS: { + flush_altivec_to_thread(child); + + /* copy AltiVec registers VR[0] .. VR[31] */ + unsigned long regsize; + regsize = 32 * sizeof(vector128); + if (copy_to_user((void *)data, &child->thread.vr, regsize)) + return -EFAULT; + data += (regsize / sizeof(unsigned long)); + + /* copy VSCR */ + regsize = 1 * sizeof(vector128); + if (copy_to_user((void *)data, &child->thread.vscr, regsize)) + return -EFAULT; + data += (regsize / sizeof(unsigned long)); + + /* copy VRSAVE */ + if (put_user(child->thread.vrsave, (u32 __user *)data)) + return -EFAULT; + break; + } + + case PTRACE_SETVRREGS: { + flush_altivec_to_thread(child); + + /* copy AltiVec registers VR[0] .. VR[31] */ + unsigned long regsize; + regsize = 32 * sizeof(vector128); + if (copy_from_user(&child->thread.vr, (void *)data, regsize)) + return -EFAULT; + data += (regsize / sizeof(unsigned long)); + + /* copy VSCR */ + regsize = 1 * sizeof(vector128); + if (copy_from_user(&child->thread.vscr, (void *)data, regsize)) + return -EFAULT; + data += (regsize / sizeof(unsigned long)); + + /* copy VRSAVE */ + if (get_user(child->thread.vrsave, (u32 __user *)data)) + return -EFAULT; + break; + } +#endif + default: ret = ptrace_request(child, request, addr, data); break; diff -uprN -X linux-2.6.12.3.orig/Documentation/dontdiff linux-2.6.12.3.orig/arch/ppc64/kernel/ptrace.c linux-2.6.12.3/arch/ppc64/kernel/ptrace.c --- linux-2.6.12.3.orig/arch/ppc64/kernel/ptrace.c 2005-09-06 17:07:34.000000000 -0500 +++ linux-2.6.12.3/arch/ppc64/kernel/ptrace.c 2005-09-06 17:11:54.202393173 -0500 @@ -274,6 +274,64 @@ int sys_ptrace(long request, long pid, l break; } +#ifdef CONFIG_ALTIVEC +/* + * 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. + */ + case PTRACE_GETVRREGS: { + flush_altivec_to_thread(child); + + /* copy AltiVec registers VR[0] .. VR[31] */ + unsigned long regsize; + regsize = 32 * sizeof(vector128); + if (copy_to_user((void *)data, &child->thread.vr, regsize)) + return -EFAULT; + data += (regsize / sizeof(unsigned long)); + + /* copy VSCR */ + regsize = 1 * sizeof(vector128); + if (copy_to_user((void *)data, &child->thread.vscr, regsize)) + return -EFAULT; + data += (regsize / sizeof(unsigned long)); + + /* copy VRSAVE */ + if (put_user(child->thread.vrsave, (u32 __user *)data)) + return -EFAULT; + break; + } + + case PTRACE_SETVRREGS: { + flush_altivec_to_thread(child); + + /* copy AltiVec registers VR[0] .. VR[31] */ + unsigned long regsize; + regsize = 32 * sizeof(vector128); + if (copy_from_user(&child->thread.vr, (void *)data, regsize)) + return -EFAULT; + data += (regsize / sizeof(unsigned long)); + + /* copy VSCR */ + regsize = 1 * sizeof(vector128); + if (copy_from_user(&child->thread.vscr, (void *)data, regsize)) + return -EFAULT; + data += (regsize / sizeof(unsigned long)); + + /* copy VRSAVE */ + if (get_user(child->thread.vrsave, (u32 __user *)data)) + return -EFAULT; + break; + } +#endif + default: ret = ptrace_request(child, request, addr, data); break; From linas at austin.ibm.com Fri Sep 9 05:30:53 2005 From: linas at austin.ibm.com (linas) Date: Thu, 8 Sep 2005 14:30:53 -0500 Subject: r13 is non-volatile? In-Reply-To: References: <0C620F0B-92B0-4EBF-BC0C-49FD4D3D4323@freescale.com> Message-ID: <20050908193053.GO30028@austin.ibm.com> On Thu, Sep 08, 2005 at 07:01:18PM +0200, Segher Boessenkool was heard to remark: > >Was looking at merging some code between ppc32 & ppc64 and noticed > >that in ppc32 we consider r13 to be part of the non-volatile register > >set. Is this really correct? > > >r13 is suppose to be sdata pointer in ppc32 > > sdata pointer is non-volatile by definition... > > >and system thread id in ppc64. > > The 64-bit kernel uses GPR13 as the PACA pointer, so it handles > it specially There's a different value in R13 depending on which cpu you're on, so one mustn't save R13 on one CPU and attempt to restore it on another. Maybe, for ppc32, you can pretend that r13 "is like a paca"? So that instead of saving/restoring r13 like this, you could set it up at the same time/instead of setting up the paca r13? --linas From kumar.gala at freescale.com Fri Sep 9 06:32:40 2005 From: kumar.gala at freescale.com (Kumar Gala) Date: Thu, 8 Sep 2005 15:32:40 -0500 Subject: [PATCH] ppc: Moved ASM_CONST macro into ppc_asm.h In-Reply-To: References: Message-ID: Well, this patch breaks thinks since ppc_asm.h really needs a hugh __ASSEMBLY__ protection for most of it. I'll send an updated patch that also moves ppc_asm.h into include/asm- powerpc once we close on the non-volatile issue with r13 between ppc32/64. - kumar On Sep 7, 2005, at 1:55 PM, Gala Kumar K.-galak wrote: > Moved the ASM_CONST macro into ppc_asm for ppc32 and ppc64 since that > seems like a much better place for it long term. Also, by adding the > macro to ppc32 it will ease some future merging of code into > arch/powerpc. > > Signed-off-by: Kumar Gala > > --- > commit f56255eddd631902e3835bf7cdd8d94e69799097 > tree 82c222d64fdccbaed25e302816fd4cf6237e8d56 > parent 71c22e7cc4bf30119761b60b26c498d7b9d33e36 > author Kumar K. Gala Wed, 07 Sep 2005 > 13:53:35 -0500 > committer Kumar K. Gala Wed, 07 Sep 2005 > 13:53:35 -0500 > > include/asm-ppc/ppc_asm.h | 12 ++++++++++++ > include/asm-ppc64/cputable.h | 2 +- > include/asm-ppc64/mmu.h | 1 + > include/asm-ppc64/page.h | 8 +------- > include/asm-ppc64/ppc_asm.h | 7 +++++++ > 5 files changed, 22 insertions(+), 8 deletions(-) > > diff --git a/include/asm-ppc/ppc_asm.h b/include/asm-ppc/ppc_asm.h > --- a/include/asm-ppc/ppc_asm.h > +++ b/include/asm-ppc/ppc_asm.h > @@ -11,6 +11,9 @@ > * 2 of the License, or (at your option) any later version. > */ > > +#ifndef __PPC_ASM_H > +#define __PPC_ASM_H > + > #include > > /* > @@ -348,3 +351,12 @@ END_FTR_SECTION_IFCLR(CPU_FTR_601) > #define N_RSYM 64 > #define N_SLINE 68 > #define N_SO 100 > + > +#ifdef __ASSEMBLY__ > + #define ASM_CONST(x) x > +#else > + #define __ASM_CONST(x) x##UL > + #define ASM_CONST(x) __ASM_CONST(x) > +#endif > + > +#endif /* __PPC_ASM_H */ > diff --git a/include/asm-ppc64/cputable.h b/include/asm-ppc64/ > cputable.h > --- a/include/asm-ppc64/cputable.h > +++ b/include/asm-ppc64/cputable.h > @@ -16,7 +16,7 @@ > #define __ASM_PPC_CPUTABLE_H > > #include > -#include /* for ASM_CONST */ > +#include /* for ASM_CONST */ > > /* Exposed to userland CPU features - Must match ppc32 definitions */ > #define PPC_FEATURE_32 0x80000000 > diff --git a/include/asm-ppc64/mmu.h b/include/asm-ppc64/mmu.h > --- a/include/asm-ppc64/mmu.h > +++ b/include/asm-ppc64/mmu.h > @@ -14,6 +14,7 @@ > #define _PPC64_MMU_H_ > > #include > +#include /* for ASM_CONST */ > #include > > /* > diff --git a/include/asm-ppc64/page.h b/include/asm-ppc64/page.h > --- a/include/asm-ppc64/page.h > +++ b/include/asm-ppc64/page.h > @@ -11,13 +11,7 @@ > */ > > #include > - > -#ifdef __ASSEMBLY__ > - #define ASM_CONST(x) x > -#else > - #define __ASM_CONST(x) x##UL > - #define ASM_CONST(x) __ASM_CONST(x) > -#endif > +#include /* for ASM_CONST */ > > /* PAGE_SHIFT determines the page size */ > #define PAGE_SHIFT 12 > diff --git a/include/asm-ppc64/ppc_asm.h b/include/asm-ppc64/ppc_asm.h > --- a/include/asm-ppc64/ppc_asm.h > +++ b/include/asm-ppc64/ppc_asm.h > @@ -239,4 +239,11 @@ > #define vr30 30 > #define vr31 31 > > +#ifdef __ASSEMBLY__ > + #define ASM_CONST(x) x > +#else > + #define __ASM_CONST(x) x##UL > + #define ASM_CONST(x) __ASM_CONST(x) > +#endif > + > #endif /* _PPC64_PPC_ASM_H */ > _______________________________________________ > Linuxppc64-dev mailing list > Linuxppc64-dev at ozlabs.org > https://ozlabs.org/mailman/listinfo/linuxppc64-dev > From will_schmidt at vnet.ibm.com Fri Sep 9 06:43:04 2005 From: will_schmidt at vnet.ibm.com (will schmidt) Date: Thu, 08 Sep 2005 15:43:04 -0500 Subject: RFC: merging of cputables between ppc32/64 In-Reply-To: <268E83D3-853C-4752-88D1-A7354E924C07@freescale.com> References: <268E83D3-853C-4752-88D1-A7354E924C07@freescale.com> Message-ID: <4320A258.1080706@vnet.ibm.com> Kumar Gala wrote: > I was hoping to get some idea on which direction we wanted to head with > cputable between ppc32/64. The only major difference that exists > between the two is the use of cpu_setup(). > > On ppc32, cpu_setup is called for each processor in an SMP > configuration. Which gives us the following signature: > > typedef void (*cpu_setup_t)(unsigned long offset, int cpu_nr, struct > cpu_spec* spec); > > On ppc64, cpu_setup is only called for the boot cpu. It is left to the Yeah, at the time, we figured all cpu's in a system would be the same. with the merge of 32/64, is this still going to be the case? > cpu save/restore functions to handle setting up the state for > additional CPUs. Which gives is the following signature: > > typedef void (*cpu_setup_t)(unsigned long offset, struct cpu_spec* spec); > > So my question is do we just extend the ppc64 signature to match the > ppc32 by having a dummy "int cpu_nr" that is ignored or do we do > something else? As far as I can tell cpu_nr is only used by ppc32 as > temp storage so that the cpu_setup functions can return properly. If cpu_nr is just used as temp storage, then can it be removed and replaced with a local variable? > > - kumar > _______________________________________________ > Linuxppc64-dev mailing list > Linuxppc64-dev at ozlabs.org > https://ozlabs.org/mailman/listinfo/linuxppc64-dev From becky.bruce at freescale.com Fri Sep 9 07:02:31 2005 From: becky.bruce at freescale.com (Becky Bruce) Date: Thu, 8 Sep 2005 16:02:31 -0500 Subject: cpu features testing 32 vs 64 bit Message-ID: <1729b6f2a199a759c4daeadd3ddcdc4a@freescale.com> So, in include/asm-ppc64/cacheflush.h is the following: static inline void flush_icache_range(unsigned long start, unsigned long stop) { if (!cpu_has_feature(CPU_FTR_COHERENT_ICACHE)) __flush_icache_range(start, stop); } On the 32-bit side, we don't need the feature test - CPU_FTR_COHERENT_CACHE is only defined in 64-bit land, and has bits set in the upper 32. There's a couple of ways to deal with merging this: 1) The ever-so-popular #ifdef __powerpc64__around the cpu_has_feature test 2) No ifdef in the code itself, but #define CPU_FTR_WHATEVER to be 0 when !__powerpc64__ in cputable.h so that the cpu_has_feature test will always fail for 32-bit. I'd like to get some opinions on this. Do folks feel like the performance hit of doing the compare is enough to justify going with method 1? Should we be using likely/unlikely with the feature test? This is just one code example - I suspect there will be others as we continue the merge, and the importance of performance may differ depending on where in the code we are. Thanks! -B From galak at freescale.com Fri Sep 9 07:11:55 2005 From: galak at freescale.com (Kumar Gala) Date: Thu, 8 Sep 2005 16:11:55 -0500 (CDT) Subject: [PATCH] ppc: Merge tlb.h Message-ID: Merged tlb.h between asm-ppc32 and asm-ppc64 into asm-powerpc. Also, fixed a compiler warning in arch/ppc/mm/tlb.c since it was roughly related. Signed-off-by: Kumar K. Gala --- commit c5f0c343d08ad9c6862c1755e7b2239f31a2a633 tree c80721ace951bc55b14a8f2a3bf69599bca2e8e9 parent cebb2b156319990fc2fba615bbfeac81be62a86a author Kumar K. Gala Thu, 08 Sep 2005 16:09:42 -0500 committer Kumar K. Gala Thu, 08 Sep 2005 16:09:42 -0500 arch/ppc/mm/tlb.c | 1 + include/asm-powerpc/tlb.h | 50 +++++++++++++++++++++++++++++++++++++++ include/asm-ppc/tlb.h | 57 --------------------------------------------- include/asm-ppc64/tlb.h | 39 ------------------------------- 4 files changed, 51 insertions(+), 96 deletions(-) diff --git a/arch/ppc/mm/tlb.c b/arch/ppc/mm/tlb.c --- a/arch/ppc/mm/tlb.c +++ b/arch/ppc/mm/tlb.c @@ -28,6 +28,7 @@ #include #include #include +#include #include #include diff --git a/include/asm-powerpc/tlb.h b/include/asm-powerpc/tlb.h new file mode 100644 --- /dev/null +++ b/include/asm-powerpc/tlb.h @@ -0,0 +1,50 @@ +#ifndef _ASM_POWERPC_TLB_H +#define _ASM_POWERPC_TLB_H + +#include +#include + +/* Nothing needed here in fact... */ +#define tlb_start_vma(tlb, vma) do { } while (0) +#define tlb_end_vma(tlb, vma) do { } while (0) + +/* Avoid pulling in another include just for this */ +#define check_pgt_cache() do { } while (0) + +#if defined(CONFIG_PPC64) +struct mmu_gather; + +extern void pte_free_finish(void); + +#define __tlb_remove_tlb_entry(tlb, pte, address) do { } while (0) +static inline void tlb_flush(struct mmu_gather *tlb) +{ + flush_tlb_pending(); + pte_free_finish(); +} +#elif defined(CONFIG_PPC_STD_MMU) +/* Classic PPC with hash-table based MMU... */ + +struct mmu_gather; +extern void tlb_flush(struct mmu_gather *tlb); +extern void flush_hash_entry(struct mm_struct *mm, pte_t *ptep, + unsigned long address); +#else +/* Embedded PPC with software-loaded TLB, very simple... */ + +#define __tlb_remove_tlb_entry(tlb, pte, address) do { } while (0) +#define tlb_flush(tlb) flush_tlb_mm((tlb)->mm) +#endif /* CONFIG_PPC64 */ + +/* Get the generic bits... */ +#include + +#ifdef CONFIG_PPC_STD_MMU +static inline void __tlb_remove_tlb_entry(struct mmu_gather *tlb, pte_t *ptep, + unsigned long address) +{ + if (pte_val(*ptep) & _PAGE_HASHPTE) + flush_hash_entry(tlb->mm, ptep, address); +} +#endif /* CONFIG_PPC_STD_MMU */ +#endif /* _ASM_POWERPC_TLB_H */ diff --git a/include/asm-ppc/tlb.h b/include/asm-ppc/tlb.h deleted file mode 100644 --- a/include/asm-ppc/tlb.h +++ /dev/null @@ -1,57 +0,0 @@ -/* - * TLB shootdown specifics for PPC - * - * Copyright (C) 2002 Paul Mackerras, 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. - */ -#ifndef _PPC_TLB_H -#define _PPC_TLB_H - -#include -#include -#include -#include -#include -#include - -#ifdef CONFIG_PPC_STD_MMU -/* Classic PPC with hash-table based MMU... */ - -struct mmu_gather; -extern void tlb_flush(struct mmu_gather *tlb); - -/* Get the generic bits... */ -#include - -/* Nothing needed here in fact... */ -#define tlb_start_vma(tlb, vma) do { } while (0) -#define tlb_end_vma(tlb, vma) do { } while (0) - -extern void flush_hash_entry(struct mm_struct *mm, pte_t *ptep, - unsigned long address); - -static inline void __tlb_remove_tlb_entry(struct mmu_gather *tlb, pte_t *ptep, - unsigned long address) -{ - if (pte_val(*ptep) & _PAGE_HASHPTE) - flush_hash_entry(tlb->mm, ptep, address); -} - -#else -/* Embedded PPC with software-loaded TLB, very simple... */ - -#define tlb_start_vma(tlb, vma) do { } while (0) -#define tlb_end_vma(tlb, vma) do { } while (0) -#define __tlb_remove_tlb_entry(tlb, pte, address) do { } while (0) -#define tlb_flush(tlb) flush_tlb_mm((tlb)->mm) - -/* Get the generic bits... */ -#include - -#endif /* CONFIG_PPC_STD_MMU */ - -#endif /* __PPC_TLB_H */ diff --git a/include/asm-ppc64/tlb.h b/include/asm-ppc64/tlb.h deleted file mode 100644 --- a/include/asm-ppc64/tlb.h +++ /dev/null @@ -1,39 +0,0 @@ -/* - * TLB shootdown specifics for PPC64 - * - * Copyright (C) 2002 Anton Blanchard, IBM Corp. - * Copyright (C) 2002 Paul Mackerras, 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. - */ -#ifndef _PPC64_TLB_H -#define _PPC64_TLB_H - -#include - -struct mmu_gather; - -extern void pte_free_finish(void); - -static inline void tlb_flush(struct mmu_gather *tlb) -{ - flush_tlb_pending(); - pte_free_finish(); -} - -/* Avoid pulling in another include just for this */ -#define check_pgt_cache() do { } while (0) - -/* Get the generic bits... */ -#include - -/* Nothing needed here in fact... */ -#define tlb_start_vma(tlb, vma) do { } while (0) -#define tlb_end_vma(tlb, vma) do { } while (0) - -#define __tlb_remove_tlb_entry(tlb, pte, address) do { } while (0) - -#endif /* _PPC64_TLB_H */ From pantelis.antoniou at gmail.com Fri Sep 9 07:08:39 2005 From: pantelis.antoniou at gmail.com (Pantelis Antoniou) Date: Fri, 9 Sep 2005 00:08:39 +0300 Subject: cpu features testing 32 vs 64 bit In-Reply-To: <1729b6f2a199a759c4daeadd3ddcdc4a@freescale.com> References: <1729b6f2a199a759c4daeadd3ddcdc4a@freescale.com> Message-ID: <200509090008.39692.pantelis.antoniou@gmail.com> On Friday 09 September 2005 00:02, Becky Bruce wrote: > So, > > in include/asm-ppc64/cacheflush.h is the following: > > static inline void flush_icache_range(unsigned long start, unsigned > long stop) > { > if (!cpu_has_feature(CPU_FTR_COHERENT_ICACHE)) > __flush_icache_range(start, stop); > } > > On the 32-bit side, we don't need the feature test - > CPU_FTR_COHERENT_CACHE is only defined in 64-bit land, and has bits set > in the upper 32. > Oh yes we need it. 8xx is non coherent. > There's a couple of ways to deal with merging this: > > 1) The ever-so-popular #ifdef __powerpc64__around the cpu_has_feature > test > 2) No ifdef in the code itself, but #define CPU_FTR_WHATEVER to be 0 > when !__powerpc64__ in cputable.h so that the cpu_has_feature test will > always fail for 32-bit. > > I'd like to get some opinions on this. Do folks feel like the > performance hit of doing the compare is enough to justify going with > method 1? Should we be using likely/unlikely with the feature test? > > This is just one code example - I suspect there will be others as we > continue the merge, and the importance of performance may differ > depending on where in the code we are. > > Thanks! > -B > Regards Pantelis From kumar.gala at freescale.com Fri Sep 9 07:20:17 2005 From: kumar.gala at freescale.com (Kumar Gala) Date: Thu, 8 Sep 2005 16:20:17 -0500 Subject: cpu features testing 32 vs 64 bit In-Reply-To: <200509090008.39692.pantelis.antoniou@gmail.com> References: <200509090008.39692.pantelis.antoniou@gmail.com> Message-ID: On Sep 8, 2005, at 4:08 PM, Pantelis Antoniou wrote: > On Friday 09 September 2005 00:02, Becky Bruce wrote: > >> So, >> >> in include/asm-ppc64/cacheflush.h is the following: >> >> static inline void flush_icache_range(unsigned long start, unsigned >> long stop) >> { >> if (!cpu_has_feature(CPU_FTR_COHERENT_ICACHE)) >> __flush_icache_range(start, stop); >> } >> >> On the 32-bit side, we don't need the feature test - >> CPU_FTR_COHERENT_CACHE is only defined in 64-bit land, and has >> bits set >> in the upper 32. >> >> > > Oh yes we need it. 8xx is non coherent. I think she lost the I in ICACHE... its a power5 only feature at this point. - kumar From dan at embeddededge.com Fri Sep 9 07:48:58 2005 From: dan at embeddededge.com (Dan Malek) Date: Thu, 8 Sep 2005 17:48:58 -0400 Subject: cpu features testing 32 vs 64 bit In-Reply-To: References: <200509090008.39692.pantelis.antoniou@gmail.com> Message-ID: On Sep 8, 2005, at 5:20 PM, Kumar Gala wrote: >>> if (!cpu_has_feature(CPU_FTR_COHERENT_ICACHE)) >>> __flush_icache_range(start, stop); >>> } If we #define CPU_FTR_xxx as a 0 or all 1's for processors that have or don't have these features, will the compiler be smart enough to recognize an always true or false condition and remove the test (or code as appropriate)? Thanks. -- Dan From benh at kernel.crashing.org Fri Sep 9 07:53:52 2005 From: benh at kernel.crashing.org (Benjamin Herrenschmidt) Date: Fri, 09 Sep 2005 07:53:52 +1000 Subject: r13 is non-volatile? In-Reply-To: <20050908193053.GO30028@austin.ibm.com> References: <0C620F0B-92B0-4EBF-BC0C-49FD4D3D4323@freescale.com> <20050908193053.GO30028@austin.ibm.com> Message-ID: <1126216432.29803.31.camel@gaston> > There's a different value in R13 depending on which cpu you're on, > so one mustn't save R13 on one CPU and attempt to restore it on > another. > > Maybe, for ppc32, you can pretend that r13 "is like a paca"? So > that instead of saving/restoring r13 like this, you could set it up > at the same time/instead of setting up the paca r13? ppc32 uses r2 for that, it contains "current". I don't think we need to bother merging those low level CPU specific things. We need to have a cpu32 and a cpu64 subdirs in there for things like these, memory management, etc... imho. Ben. From kumar.gala at freescale.com Fri Sep 9 08:02:30 2005 From: kumar.gala at freescale.com (Kumar Gala) Date: Thu, 8 Sep 2005 17:02:30 -0500 Subject: cpu features testing 32 vs 64 bit In-Reply-To: References: Message-ID: <39A39EEE-E3B1-4D34-BC6E-854C3EF56C7D@freescale.com> On Sep 8, 2005, at 4:48 PM, Dan Malek wrote: > > On Sep 8, 2005, at 5:20 PM, Kumar Gala wrote: > > >>>> if (!cpu_has_feature(CPU_FTR_COHERENT_ICACHE)) >>>> __flush_icache_range(start, stop); >>>> } >>>> > > If we #define CPU_FTR_xxx as a 0 or all 1's for processors that have > or don't have these features, will the compiler be smart enough to > recognize an always true or false condition and remove the > test (or code as appropriate)? The compiler is smart enough in this case since cpu_has_feature() is an inline function. - kumar From dan at embeddededge.com Fri Sep 9 08:20:47 2005 From: dan at embeddededge.com (Dan Malek) Date: Thu, 8 Sep 2005 18:20:47 -0400 Subject: cpu features testing 32 vs 64 bit In-Reply-To: <39A39EEE-E3B1-4D34-BC6E-854C3EF56C7D@freescale.com> References: <39A39EEE-E3B1-4D34-BC6E-854C3EF56C7D@freescale.com> Message-ID: <1f573d932fdab43ce4e4a0a918c5d9df@embeddededge.com> On Sep 8, 2005, at 6:02 PM, Kumar Gala wrote: > The compiler is smart enough in this case since cpu_has_feature() is > an inline function. I guess I didn't read Becky's comments close enough, but she did suggest this. I was trying to eliminate the #ifdef, but I guess we will need it some place. Thanks. -- Dan From members at paypal.com Fri Sep 9 07:47:48 2005 From: members at paypal.com (PayPal) Date: Thu, 8 Sep 2005 23:47:48 +0200 (CEST) Subject: Billing Information! Message-ID: <20050908214748.49CC482AA2@wsp2.surf-town.net> An HTML attachment was scrubbed... URL: http://ozlabs.org/pipermail/linuxppc64-dev/attachments/20050908/30d07931/attachment.htm From arnd at arndb.de Fri Sep 9 08:36:39 2005 From: arnd at arndb.de (Arnd Bergmann) Date: Fri, 9 Sep 2005 00:36:39 +0200 Subject: cpu features testing 32 vs 64 bit In-Reply-To: <39A39EEE-E3B1-4D34-BC6E-854C3EF56C7D@freescale.com> References: <39A39EEE-E3B1-4D34-BC6E-854C3EF56C7D@freescale.com> Message-ID: <200509090036.39992.arnd@arndb.de> On Freedag 09 September 2005 00:02, Kumar Gala wrote: > > On Sep 8, 2005, at 4:48 PM, Dan Malek wrote: > > > > If we #define CPU_FTR_xxx as a 0 or all 1's for processors that have > > or don't have these features, will the compiler be smart enough to > > recognize an always true or false condition and remove the > > test (or code as appropriate)? > > The compiler is smart enough in this case since cpu_has_feature() is > an inline function. I actually wrote a patch that solves the problem in a very generic way, see http://patchwork.ozlabs.org/linuxppc/patch?id=1048 . I don't remember exactly if there were serious objections against the patch at that time, but it looks like a much cleaner solution to me than defining CPU_FTR_xxx to different values depending on the configuration. Arnd <>< From benh at kernel.crashing.org Fri Sep 9 09:56:05 2005 From: benh at kernel.crashing.org (Benjamin Herrenschmidt) Date: Fri, 09 Sep 2005 09:56:05 +1000 Subject: [PATCH] ppc: Merge tlb.h In-Reply-To: References: Message-ID: <1126223767.29803.34.camel@gaston> On Thu, 2005-09-08 at 16:11 -0500, Kumar Gala wrote: > Merged tlb.h between asm-ppc32 and asm-ppc64 into asm-powerpc. Also, fixed > a compiler warning in arch/ppc/mm/tlb.c since it was roughly related. > > Signed-off-by: Kumar K. Gala Do we want to do that ? Replacing 2 different files with one split in #ifdef isn't a progress... As I said, I think we need two subdirs for the low level stuffs that is different, and that includes at this point all of the memory management related stuff. In addition, I'd appreciate if we could avoid touching ppc64 mm related files completely for a couple of weeks as I'm working on a fairly big patch that I'm really tired of having to rebase all the time ;) Ben. From david at gibson.dropbear.id.au Fri Sep 9 10:08:57 2005 From: david at gibson.dropbear.id.au (David Gibson) Date: Fri, 9 Sep 2005 10:08:57 +1000 Subject: cpu features testing 32 vs 64 bit In-Reply-To: <200509090036.39992.arnd@arndb.de> References: <39A39EEE-E3B1-4D34-BC6E-854C3EF56C7D@freescale.com> <200509090036.39992.arnd@arndb.de> Message-ID: <20050909000857.GC31045@localhost.localdomain> On Fri, Sep 09, 2005 at 12:36:39AM +0200, Arnd Bergmann wrote: > On Freedag 09 September 2005 00:02, Kumar Gala wrote: > > > > On Sep 8, 2005, at 4:48 PM, Dan Malek wrote: > > > > > > If we #define CPU_FTR_xxx as a 0 or all 1's for processors that have > > > or don't have these features, will the compiler be smart enough to > > > recognize an always true or false condition and remove the > > > test (or code as appropriate)? > > > > The compiler is smart enough in this case since cpu_has_feature() is > > an inline function. > > I actually wrote a patch that solves the problem in a very generic way, > see http://patchwork.ozlabs.org/linuxppc/patch?id=1048 . > I don't remember exactly if there were serious objections against > the patch at that time, but it looks like a much cleaner solution to me > than defining CPU_FTR_xxx to different values depending on the > configuration. And we already use a mechanism essentially identical to Arnd's for fw_has_feature(). -- 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 kumar.gala at freescale.com Fri Sep 9 11:30:58 2005 From: kumar.gala at freescale.com (Kumar Gala) Date: Thu, 8 Sep 2005 20:30:58 -0500 Subject: r13 is non-volatile? In-Reply-To: <1126216432.29803.31.camel@gaston> References: <1126216432.29803.31.camel@gaston> Message-ID: On Sep 8, 2005, at 4:53 PM, Benjamin Herrenschmidt wrote: > > >> There's a different value in R13 depending on which cpu you're on, >> so one mustn't save R13 on one CPU and attempt to restore it on >> another. >> >> Maybe, for ppc32, you can pretend that r13 "is like a paca"? So >> that instead of saving/restoring r13 like this, you could set it up >> at the same time/instead of setting up the paca r13? >> > > ppc32 uses r2 for that, it contains "current". > > I don't think we need to bother merging those low level CPU specific > things. We need to have a cpu32 and a cpu64 subdirs in there for > things > like these, memory management, etc... imho. My intent is to see if we can make a change so that there isn't an ifdef. - kumar From kumar.gala at freescale.com Fri Sep 9 11:34:52 2005 From: kumar.gala at freescale.com (Kumar Gala) Date: Thu, 8 Sep 2005 20:34:52 -0500 Subject: [PATCH] ppc: Merge tlb.h In-Reply-To: <1126223767.29803.34.camel@gaston> References: <1126223767.29803.34.camel@gaston> Message-ID: On Sep 8, 2005, at 6:56 PM, Benjamin Herrenschmidt wrote: > On Thu, 2005-09-08 at 16:11 -0500, Kumar Gala wrote: > >> Merged tlb.h between asm-ppc32 and asm-ppc64 into asm-powerpc. Also, >> > fixed > >> a compiler warning in arch/ppc/mm/tlb.c since it was roughly related. >> >> Signed-off-by: Kumar K. Gala >> > > Do we want to do that ? > > Replacing 2 different files with one split in #ifdef isn't a > progress... > As I said, I think we need two subdirs for the low level stuffs > that is > different, and that includes at this point all of the memory > management > related stuff. I understand, but I'm also not sure if its progress to duplicate a major of a file that is common. In this case it might be better handled by having specific versions per "sub-arch". I think the key is determining which files should be handled via sub-arch diffs and which should be handled via ifdef's in the file. Some cases like ppc_asm are so similar that it seems better to have a single file and ifdef the specific case. > In addition, I'd appreciate if we could avoid touching ppc64 mm > related > files completely for a couple of weeks as I'm working on a fairly big > patch that I'm really tired of having to rebase all the time ;) Will avoid touch any other mm related headers than :) - kumar From michael at ellerman.id.au Fri Sep 9 12:25:45 2005 From: michael at ellerman.id.au (Michael Ellerman) Date: Fri, 9 Sep 2005 12:25:45 +1000 Subject: Time for linuxpowerpc-dev? Message-ID: <200509091225.45440.michael@ellerman.id.au> With the arch's merging, and all this cross-posting maddness, is it time to start a linuxpowerpc-dev mailing list? cheers -- Michael Ellerman IBM OzLabs email: michael:ellerman.id.au inmsg: mpe:jabber.org wwweb: http://michael.ellerman.id.au phone: +61 2 6212 1183 (tie line 70 21183) We do not inherit the earth from our ancestors, we borrow it from our children. - S.M.A.R.T Person -------------- 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/20050909/c1310b98/attachment.pgp From kumar.gala at freescale.com Fri Sep 9 05:12:08 2005 From: kumar.gala at freescale.com (Kumar Gala) Date: Thu, 8 Sep 2005 14:12:08 -0500 Subject: [PATCH] Add PTRACE_{GET|SET}VRREGS In-Reply-To: <20050908190401.GB3416@austin.ibm.com> References: <20050908190401.GB3416@austin.ibm.com> Message-ID: <666AD09B-F17D-4AFA-9D53-5E3C1F5A04B4@freescale.com> I repeat my request that we make vrsave an unsigned int instead of an unsigned long in thread_struct since we are touch this code anyways. - kumar On Sep 8, 2005, at 2:04 PM, Robert Jennings wrote: > 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. Updated with the suggestions from Anton following the > lines > of his code snippet. > > Added: > - flush_altivec_to_thread calls as suggested by Anton > - piecewise copy of structure to preserve 32-bit vrsave data as per > Anton > > Appologies if this gets to the list twice, I had an MTA issue earlier. > > Signed-off-by: Robert C Jennings > --- > > ptrace.c | 58 > ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ > ptrace32.c | 58 > ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ > 2 files changed, 116 insertions(+) > > diff -uprN -X linux-2.6.12.3.orig/Documentation/dontdiff > linux-2.6.12.3.orig/arch/ppc64/kernel/ptrace32.c > linux-2.6.12.3/arch/ppc64/kernel/ptrace32.c > --- linux-2.6.12.3.orig/arch/ppc64/kernel/ptrace32.c 2005-09-06 > 17:07:48.000000000 -0500 > +++ linux-2.6.12.3/arch/ppc64/kernel/ptrace32.c 2005-09-06 > 17:12:11.735819943 -0500 > @@ -409,6 +409,64 @@ int sys32_ptrace(long request, long pid, > ret = put_user(child->ptrace_message, (unsigned int > __user *) data); > break; > > +#ifdef CONFIG_ALTIVEC > +/* > + * 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. > + */ > + case PTRACE_GETVRREGS: { > + flush_altivec_to_thread(child); > + > + /* copy AltiVec registers VR[0] .. VR[31] */ > + unsigned long regsize; > + regsize = 32 * sizeof(vector128); > + if (copy_to_user((void *)data, &child->thread.vr, > regsize)) > + return -EFAULT; > + data += (regsize / sizeof(unsigned long)); > + > + /* copy VSCR */ > + regsize = 1 * sizeof(vector128); > + if (copy_to_user((void *)data, &child->thread.vscr, > regsize)) > + return -EFAULT; > + data += (regsize / sizeof(unsigned long)); > + > + /* copy VRSAVE */ > + if (put_user(child->thread.vrsave, (u32 __user *)data)) > + return -EFAULT; > + break; > + } > + > + case PTRACE_SETVRREGS: { > + flush_altivec_to_thread(child); > + > + /* copy AltiVec registers VR[0] .. VR[31] */ > + unsigned long regsize; > + regsize = 32 * sizeof(vector128); > + if (copy_from_user(&child->thread.vr, (void *)data, > regsize)) > + return -EFAULT; > + data += (regsize / sizeof(unsigned long)); > + > + /* copy VSCR */ > + regsize = 1 * sizeof(vector128); > + if (copy_from_user(&child->thread.vscr, (void *)data, > regsize)) > + return -EFAULT; > + data += (regsize / sizeof(unsigned long)); > + > + /* copy VRSAVE */ > + if (get_user(child->thread.vrsave, (u32 __user *)data)) > + return -EFAULT; > + break; > + } > +#endif > + > default: > ret = ptrace_request(child, request, addr, data); > break; > diff -uprN -X linux-2.6.12.3.orig/Documentation/dontdiff > linux-2.6.12.3.orig/arch/ppc64/kernel/ptrace.c > linux-2.6.12.3/arch/ppc64/kernel/ptrace.c > --- linux-2.6.12.3.orig/arch/ppc64/kernel/ptrace.c 2005-09-06 > 17:07:34.000000000 -0500 > +++ linux-2.6.12.3/arch/ppc64/kernel/ptrace.c 2005-09-06 > 17:11:54.202393173 -0500 > @@ -274,6 +274,64 @@ int sys_ptrace(long request, long pid, l > break; > } > > +#ifdef CONFIG_ALTIVEC > +/* > + * 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. > + */ > + case PTRACE_GETVRREGS: { > + flush_altivec_to_thread(child); > + > + /* copy AltiVec registers VR[0] .. VR[31] */ > + unsigned long regsize; > + regsize = 32 * sizeof(vector128); > + if (copy_to_user((void *)data, &child->thread.vr, > regsize)) > + return -EFAULT; > + data += (regsize / sizeof(unsigned long)); > + > + /* copy VSCR */ > + regsize = 1 * sizeof(vector128); > + if (copy_to_user((void *)data, &child->thread.vscr, > regsize)) > + return -EFAULT; > + data += (regsize / sizeof(unsigned long)); > + > + /* copy VRSAVE */ > + if (put_user(child->thread.vrsave, (u32 __user *)data)) > + return -EFAULT; > + break; > + } > + > + case PTRACE_SETVRREGS: { > + flush_altivec_to_thread(child); > + > + /* copy AltiVec registers VR[0] .. VR[31] */ > + unsigned long regsize; > + regsize = 32 * sizeof(vector128); > + if (copy_from_user(&child->thread.vr, (void *)data, > regsize)) > + return -EFAULT; > + data += (regsize / sizeof(unsigned long)); > + > + /* copy VSCR */ > + regsize = 1 * sizeof(vector128); > + if (copy_from_user(&child->thread.vscr, (void *)data, > regsize)) > + return -EFAULT; > + data += (regsize / sizeof(unsigned long)); > + > + /* copy VRSAVE */ > + if (get_user(child->thread.vrsave, (u32 __user *)data)) > + return -EFAULT; > + break; > + } > +#endif > + > default: > ret = ptrace_request(child, request, addr, data); > break; > _______________________________________________ > Linuxppc64-dev mailing list > Linuxppc64-dev at ozlabs.org > https://ozlabs.org/mailman/listinfo/linuxppc64-dev > From arnd at arndb.de Fri Sep 9 14:23:40 2005 From: arnd at arndb.de (Arnd Bergmann) Date: Fri, 9 Sep 2005 06:23:40 +0200 Subject: [PATCH] powerpc: merge include/asm/cputable.h In-Reply-To: <200509090036.39992.arnd@arndb.de> References: <39A39EEE-E3B1-4D34-BC6E-854C3EF56C7D@freescale.com> <200509090036.39992.arnd@arndb.de> Message-ID: <200509090623.41889.arnd@arndb.de> This is an updated version of my old patch that creates a more optimized version of cpu_has_feature(). This version actually combines asm-ppc/cputable.h and asm-ppc64/cputable.h, which turned out to be a lot more work than only the 64 bit version. The 64 bit parts a relatively straightforward port of my earlier work which I tested in a number of configurations. The 32 bit parts are not tested at all, all I did was compiling the ppc defconfig with this. I think it is best if I hand the patch over to Kumar and Becky for further testing and cleaning up the remaining bits in the new file, as they appear to have invested some thought in it already. This version still has a number of #ifdef __powerpc64__ that should probably go away in the process. The patch also relies on having the ASM_CONST() macro in ppc_asm.h, as proposed by Kumar Gala, so it won't work on the current git head without that change. Signed-off-by: Arnd Bergmann -- clean-cg/arch/ppc/kernel/cputable.c | 401 +++++---------------------- clean-cg/arch/ppc64/Kconfig | 30 ++ clean-cg/arch/ppc64/kernel/cputable.c | 82 +---- clean-cg/include/asm-powerpc/cputable.h | 475 ++++++++++++++++++++++++++++++++ include/asm-ppc/cputable.h | 128 -------- include/asm-ppc64/cputable.h | 167 ----------- Index: clean-cg/include/asm-ppc64/cputable.h =================================================================== --- clean-cg.orig/include/asm-ppc64/cputable.h +++ /dev/null @@ -1,167 +0,0 @@ -/* - * include/asm-ppc64/cputable.h - * - * Copyright (C) 2001 Ben. Herrenschmidt (benh at kernel.crashing.org) - * - * Modifications for ppc64: - * Copyright (C) 2003 Dave Engebretsen - * - * 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_PPC_CPUTABLE_H -#define __ASM_PPC_CPUTABLE_H - -#include -#include /* for ASM_CONST */ - -/* Exposed to userland CPU features - Must match ppc32 definitions */ -#define PPC_FEATURE_32 0x80000000 -#define PPC_FEATURE_64 0x40000000 -#define PPC_FEATURE_601_INSTR 0x20000000 -#define PPC_FEATURE_HAS_ALTIVEC 0x10000000 -#define PPC_FEATURE_HAS_FPU 0x08000000 -#define PPC_FEATURE_HAS_MMU 0x04000000 -#define PPC_FEATURE_HAS_4xxMAC 0x02000000 -#define PPC_FEATURE_UNIFIED_CACHE 0x01000000 - -#ifdef __KERNEL__ - -#ifndef __ASSEMBLY__ - -/* This structure can grow, it's real size is used by head.S code - * via the mkdefs mechanism. - */ -struct cpu_spec; -struct op_ppc64_model; - -typedef void (*cpu_setup_t)(unsigned long offset, struct cpu_spec* spec); - -struct cpu_spec { - /* CPU is matched via (PVR & pvr_mask) == pvr_value */ - unsigned int pvr_mask; - unsigned int pvr_value; - - char *cpu_name; - unsigned long cpu_features; /* Kernel features */ - unsigned int cpu_user_features; /* Userland features */ - - /* cache line sizes */ - 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 - */ - cpu_setup_t cpu_setup; - - /* 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[]; -extern struct cpu_spec *cur_cpu_spec; - -static inline unsigned long cpu_has_feature(unsigned long feature) -{ - return cur_cpu_spec->cpu_features & feature; -} - -#endif /* __ASSEMBLY__ */ - -/* CPU kernel features */ - -/* Retain the 32b definitions for the time being - use bottom half of word */ -#define CPU_FTR_SPLIT_ID_CACHE ASM_CONST(0x0000000000000001) -#define CPU_FTR_L2CR ASM_CONST(0x0000000000000002) -#define CPU_FTR_SPEC7450 ASM_CONST(0x0000000000000004) -#define CPU_FTR_ALTIVEC ASM_CONST(0x0000000000000008) -#define CPU_FTR_TAU ASM_CONST(0x0000000000000010) -#define CPU_FTR_CAN_DOZE ASM_CONST(0x0000000000000020) -#define CPU_FTR_USE_TB ASM_CONST(0x0000000000000040) -#define CPU_FTR_604_PERF_MON ASM_CONST(0x0000000000000080) -#define CPU_FTR_601 ASM_CONST(0x0000000000000100) -#define CPU_FTR_HPTE_TABLE ASM_CONST(0x0000000000000200) -#define CPU_FTR_CAN_NAP ASM_CONST(0x0000000000000400) -#define CPU_FTR_L3CR ASM_CONST(0x0000000000000800) -#define CPU_FTR_L3_DISABLE_NAP ASM_CONST(0x0000000000001000) -#define CPU_FTR_NAP_DISABLE_L2_PR ASM_CONST(0x0000000000002000) -#define CPU_FTR_DUAL_PLL_750FX ASM_CONST(0x0000000000004000) - -/* Add the 64b processor unique features in the top half of the word */ -#define CPU_FTR_SLB ASM_CONST(0x0000000100000000) -#define CPU_FTR_16M_PAGE ASM_CONST(0x0000000200000000) -#define CPU_FTR_TLBIEL ASM_CONST(0x0000000400000000) -#define CPU_FTR_NOEXECUTE ASM_CONST(0x0000000800000000) -#define CPU_FTR_NODSISRALIGN ASM_CONST(0x0000001000000000) -#define CPU_FTR_IABR ASM_CONST(0x0000002000000000) -#define CPU_FTR_MMCRA ASM_CONST(0x0000004000000000) -/* 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) -#define CPU_FTR_MMCRA_SIHV ASM_CONST(0x0000080000000000) -#define CPU_FTR_CTRL ASM_CONST(0x0000100000000000) - -#ifndef __ASSEMBLY__ - -#define COMMON_USER_PPC64 (PPC_FEATURE_32 | PPC_FEATURE_64 | \ - PPC_FEATURE_HAS_FPU | PPC_FEATURE_HAS_MMU) - -#define CPU_FTR_PPCAS_ARCH_V2_BASE (CPU_FTR_SLB | \ - CPU_FTR_TLBIEL | CPU_FTR_NOEXECUTE | \ - CPU_FTR_NODSISRALIGN | CPU_FTR_CTRL) - -/* iSeries doesn't support large pages */ -#ifdef CONFIG_PPC_ISERIES -#define CPU_FTR_PPCAS_ARCH_V2 (CPU_FTR_PPCAS_ARCH_V2_BASE) -#else -#define CPU_FTR_PPCAS_ARCH_V2 (CPU_FTR_PPCAS_ARCH_V2_BASE | CPU_FTR_16M_PAGE) -#endif /* CONFIG_PPC_ISERIES */ - -#endif /* __ASSEMBLY */ - -#ifdef __ASSEMBLY__ - -#define BEGIN_FTR_SECTION 98: - -#define END_FTR_SECTION(msk, val) \ -99: \ - .section __ftr_fixup,"a"; \ - .align 3; \ - .llong msk; \ - .llong val; \ - .llong 98b; \ - .llong 99b; \ - .previous - -#else - -#define BEGIN_FTR_SECTION "98:\n" -#define END_FTR_SECTION(msk, val) \ -"99:\n" \ -" .section __ftr_fixup,\"a\";\n" \ -" .align 3;\n" \ -" .llong "#msk";\n" \ -" .llong "#val";\n" \ -" .llong 98b;\n" \ -" .llong 99b;\n" \ -" .previous\n" - -#endif /* __ASSEMBLY__ */ - -#define END_FTR_SECTION_IFSET(msk) END_FTR_SECTION((msk), (msk)) -#define END_FTR_SECTION_IFCLR(msk) END_FTR_SECTION((msk), 0) - -#endif /* __ASM_PPC_CPUTABLE_H */ -#endif /* __KERNEL__ */ - Index: clean-cg/arch/ppc64/Kconfig =================================================================== --- clean-cg.orig/arch/ppc64/Kconfig +++ clean-cg/arch/ppc64/Kconfig @@ -125,6 +125,36 @@ config BPA_IIC bool default y +config CPU_POWER3 + bool + default y + depends on (PPC_ISERIES || PPC_PSERIES) && !POWER4_ONLY + +config CPU_RS64 + bool + default y + depends on (PPC_ISERIES || PPC_PSERIES) && !POWER4_ONLY + +config CPU_POWER4 + bool + default y + depends on PPC_ISERIES || PPC_PSERIES + +config CPU_PPC970 + bool + default y + depends on PPC_PSERIES || PPC_PMAC || PPC_MAPLE + +config CPU_POWER5 + bool + default y + depends on PPC_PSERIES + +config CPU_CELL + bool + default y + depends on PPC_BPA + # VMX is pSeries only for now until somebody writes the iSeries # exception vectors for it config ALTIVEC Index: clean-cg/arch/ppc64/kernel/cputable.c =================================================================== --- clean-cg.orig/arch/ppc64/kernel/cputable.c +++ clean-cg/arch/ppc64/kernel/cputable.c @@ -37,26 +37,13 @@ extern void __setup_cpu_power4(unsigned extern void __setup_cpu_ppc970(unsigned long offset, struct cpu_spec* spec); extern void __setup_cpu_be(unsigned long offset, struct cpu_spec* spec); - -/* We only set the altivec features if the kernel was compiled with altivec - * support - */ -#ifdef CONFIG_ALTIVEC -#define CPU_FTR_ALTIVEC_COMP CPU_FTR_ALTIVEC -#define PPC_FEATURE_HAS_ALTIVEC_COMP PPC_FEATURE_HAS_ALTIVEC -#else -#define CPU_FTR_ALTIVEC_COMP 0 -#define PPC_FEATURE_HAS_ALTIVEC_COMP 0 -#endif - struct cpu_spec cpu_specs[] = { { /* Power3 */ .pvr_mask = 0xffff0000, .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_user_features = COMMON_USER_PPC64, + .cpu_features = CPU_FTR_POWER3, + .cpu_user_features = COMMON_USER_PPC64, .icache_bsize = 128, .dcache_bsize = 128, .num_pmcs = 8, @@ -70,8 +57,7 @@ struct cpu_spec cpu_specs[] = { .pvr_mask = 0xffff0000, .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_features = CPU_FTR_POWER3, .cpu_user_features = COMMON_USER_PPC64, .icache_bsize = 128, .dcache_bsize = 128, @@ -86,9 +72,7 @@ struct cpu_spec cpu_specs[] = { .pvr_mask = 0xffff0000, .pvr_value = 0x00330000, .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_MMCRA | CPU_FTR_CTRL, + .cpu_features = CPU_FTR_RS64, .cpu_user_features = COMMON_USER_PPC64, .icache_bsize = 128, .dcache_bsize = 128, @@ -103,9 +87,7 @@ struct cpu_spec cpu_specs[] = { .pvr_mask = 0xffff0000, .pvr_value = 0x00340000, .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_MMCRA | CPU_FTR_CTRL, + .cpu_features = CPU_FTR_RS64, .cpu_user_features = COMMON_USER_PPC64, .icache_bsize = 128, .dcache_bsize = 128, @@ -120,9 +102,7 @@ struct cpu_spec cpu_specs[] = { .pvr_mask = 0xffff0000, .pvr_value = 0x00360000, .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_MMCRA | CPU_FTR_CTRL, + .cpu_features = CPU_FTR_RS64, .cpu_user_features = COMMON_USER_PPC64, .icache_bsize = 128, .dcache_bsize = 128, @@ -137,9 +117,7 @@ struct cpu_spec cpu_specs[] = { .pvr_mask = 0xffff0000, .pvr_value = 0x00370000, .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_MMCRA | CPU_FTR_CTRL, + .cpu_features = CPU_FTR_RS64, .cpu_user_features = COMMON_USER_PPC64, .icache_bsize = 128, .dcache_bsize = 128, @@ -154,9 +132,7 @@ struct cpu_spec cpu_specs[] = { .pvr_mask = 0xffff0000, .pvr_value = 0x00350000, .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_MMCRA, + .cpu_features = CPU_FTR_POWER4, .cpu_user_features = COMMON_USER_PPC64, .icache_bsize = 128, .dcache_bsize = 128, @@ -171,9 +147,7 @@ struct cpu_spec cpu_specs[] = { .pvr_mask = 0xffff0000, .pvr_value = 0x00380000, .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_MMCRA, + .cpu_features = CPU_FTR_POWER4, .cpu_user_features = COMMON_USER_PPC64, .icache_bsize = 128, .dcache_bsize = 128, @@ -188,10 +162,7 @@ struct cpu_spec cpu_specs[] = { .pvr_mask = 0xffff0000, .pvr_value = 0x00390000, .cpu_name = "PPC970", - .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_MMCRA, + .cpu_features = CPU_FTR_PPC970, .cpu_user_features = COMMON_USER_PPC64 | PPC_FEATURE_HAS_ALTIVEC_COMP, .icache_bsize = 128, @@ -207,10 +178,7 @@ struct cpu_spec cpu_specs[] = { .pvr_mask = 0xffff0000, .pvr_value = 0x003c0000, .cpu_name = "PPC970FX", - .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_MMCRA, + .cpu_features = CPU_FTR_PPC970, .cpu_user_features = COMMON_USER_PPC64 | PPC_FEATURE_HAS_ALTIVEC_COMP, .icache_bsize = 128, @@ -226,10 +194,7 @@ struct cpu_spec cpu_specs[] = { .pvr_mask = 0xffff0000, .pvr_value = 0x00440000, .cpu_name = "PPC970MP", - .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_MMCRA, + .cpu_features = CPU_FTR_PPC970, .cpu_user_features = COMMON_USER_PPC64 | PPC_FEATURE_HAS_ALTIVEC_COMP, .icache_bsize = 128, @@ -244,11 +209,7 @@ struct cpu_spec cpu_specs[] = { .pvr_mask = 0xffff0000, .pvr_value = 0x003a0000, .cpu_name = "POWER5 (gr)", - .cpu_features = CPU_FTR_SPLIT_ID_CACHE | - CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE | - CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_MMCRA | CPU_FTR_SMT | - CPU_FTR_COHERENT_ICACHE | CPU_FTR_LOCKLESS_TLBIE | - CPU_FTR_MMCRA_SIHV, + .cpu_features = CPU_FTR_POWER5, .cpu_user_features = COMMON_USER_PPC64, .icache_bsize = 128, .dcache_bsize = 128, @@ -263,11 +224,7 @@ struct cpu_spec cpu_specs[] = { .pvr_mask = 0xffff0000, .pvr_value = 0x003b0000, .cpu_name = "POWER5 (gs)", - .cpu_features = CPU_FTR_SPLIT_ID_CACHE | - CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE | - CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_MMCRA | CPU_FTR_SMT | - CPU_FTR_COHERENT_ICACHE | CPU_FTR_LOCKLESS_TLBIE | - CPU_FTR_MMCRA_SIHV, + .cpu_features = CPU_FTR_POWER5, .cpu_user_features = COMMON_USER_PPC64, .icache_bsize = 128, .dcache_bsize = 128, @@ -281,11 +238,8 @@ struct cpu_spec cpu_specs[] = { { /* BE DD1.x */ .pvr_mask = 0xffff0000, .pvr_value = 0x00700000, - .cpu_name = "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 | - CPU_FTR_SMT, + .cpu_name = "Cell Broadband Engine", + .cpu_features = CPU_FTR_CELL, .cpu_user_features = COMMON_USER_PPC64 | PPC_FEATURE_HAS_ALTIVEC_COMP, .icache_bsize = 128, @@ -296,9 +250,7 @@ struct cpu_spec cpu_specs[] = { .pvr_mask = 0x00000000, .pvr_value = 0x00000000, .cpu_name = "POWER4 (compatible)", - .cpu_features = CPU_FTR_SPLIT_ID_CACHE | - CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE | - CPU_FTR_PPCAS_ARCH_V2, + .cpu_features = CPU_FTR_COMPATIBLE, .cpu_user_features = COMMON_USER_PPC64, .icache_bsize = 128, .dcache_bsize = 128, Index: clean-cg/arch/ppc/kernel/cputable.c =================================================================== --- clean-cg.orig/arch/ppc/kernel/cputable.c +++ clean-cg/arch/ppc/kernel/cputable.c @@ -42,17 +42,6 @@ extern void __setup_cpu_generic(unsigned #define COMMON_PPC (PPC_FEATURE_32 | PPC_FEATURE_HAS_FPU | \ PPC_FEATURE_HAS_MMU) -/* We only set the altivec features if the kernel was compiled with altivec - * support - */ -#ifdef CONFIG_ALTIVEC -#define CPU_FTR_ALTIVEC_COMP CPU_FTR_ALTIVEC -#define PPC_FEATURE_ALTIVEC_COMP PPC_FEATURE_HAS_ALTIVEC -#else -#define CPU_FTR_ALTIVEC_COMP 0 -#define PPC_FEATURE_ALTIVEC_COMP 0 -#endif - /* We only set the spe features if the kernel was compiled with * spe support */ @@ -62,34 +51,13 @@ extern void __setup_cpu_generic(unsigned #define PPC_FEATURE_SPE_COMP 0 #endif -/* We need to mark all pages as being coherent if we're SMP or we - * have a 74[45]x and an MPC107 host bridge. - */ -#if defined(CONFIG_SMP) || defined(CONFIG_MPC10X_BRIDGE) -#define CPU_FTR_COMMON CPU_FTR_NEED_COHERENT -#else -#define CPU_FTR_COMMON 0 -#endif - -/* The powersave features NAP & DOZE seems to confuse BDI when - debugging. So if a BDI is used, disable theses - */ -#ifndef CONFIG_BDI_SWITCH -#define CPU_FTR_MAYBE_CAN_DOZE CPU_FTR_CAN_DOZE -#define CPU_FTR_MAYBE_CAN_NAP CPU_FTR_CAN_NAP -#else -#define CPU_FTR_MAYBE_CAN_DOZE 0 -#define CPU_FTR_MAYBE_CAN_NAP 0 -#endif - struct cpu_spec cpu_specs[] = { #if CLASSIC_PPC { /* 601 */ .pvr_mask = 0xffff0000, .pvr_value = 0x00010000, .cpu_name = "601", - .cpu_features = CPU_FTR_COMMON | CPU_FTR_601 | - CPU_FTR_HPTE_TABLE, + .cpu_features = CPU_FTR_PPC601, .cpu_user_features = COMMON_PPC | PPC_FEATURE_601_INSTR | PPC_FEATURE_UNIFIED_CACHE, .icache_bsize = 32, @@ -100,9 +68,7 @@ struct cpu_spec cpu_specs[] = { .pvr_mask = 0xffff0000, .pvr_value = 0x00030000, .cpu_name = "603", - .cpu_features = CPU_FTR_COMMON | - CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_MAYBE_CAN_DOZE | - CPU_FTR_USE_TB | CPU_FTR_MAYBE_CAN_NAP, + .cpu_features = CPU_FTR_603, .cpu_user_features = COMMON_PPC, .icache_bsize = 32, .dcache_bsize = 32, @@ -112,9 +78,7 @@ struct cpu_spec cpu_specs[] = { .pvr_mask = 0xffff0000, .pvr_value = 0x00060000, .cpu_name = "603e", - .cpu_features = CPU_FTR_COMMON | - CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_MAYBE_CAN_DOZE | - CPU_FTR_USE_TB | CPU_FTR_MAYBE_CAN_NAP, + .cpu_features = CPU_FTR_603, .cpu_user_features = COMMON_PPC, .icache_bsize = 32, .dcache_bsize = 32, @@ -124,9 +88,7 @@ struct cpu_spec cpu_specs[] = { .pvr_mask = 0xffff0000, .pvr_value = 0x00070000, .cpu_name = "603ev", - .cpu_features = CPU_FTR_COMMON | - CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_MAYBE_CAN_DOZE | - CPU_FTR_USE_TB | CPU_FTR_MAYBE_CAN_NAP, + .cpu_features = CPU_FTR_603, .cpu_user_features = COMMON_PPC, .icache_bsize = 32, .dcache_bsize = 32, @@ -136,9 +98,7 @@ struct cpu_spec cpu_specs[] = { .pvr_mask = 0xffff0000, .pvr_value = 0x00040000, .cpu_name = "604", - .cpu_features = CPU_FTR_COMMON | - CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | - CPU_FTR_604_PERF_MON | CPU_FTR_HPTE_TABLE, + .cpu_features = CPU_FTR_604, .cpu_user_features = COMMON_PPC, .icache_bsize = 32, .dcache_bsize = 32, @@ -149,9 +109,7 @@ struct cpu_spec cpu_specs[] = { .pvr_mask = 0xfffff000, .pvr_value = 0x00090000, .cpu_name = "604e", - .cpu_features = CPU_FTR_COMMON | - CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | - CPU_FTR_604_PERF_MON | CPU_FTR_HPTE_TABLE, + .cpu_features = CPU_FTR_604, .cpu_user_features = COMMON_PPC, .icache_bsize = 32, .dcache_bsize = 32, @@ -162,9 +120,7 @@ struct cpu_spec cpu_specs[] = { .pvr_mask = 0xffff0000, .pvr_value = 0x00090000, .cpu_name = "604r", - .cpu_features = CPU_FTR_COMMON | - CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | - CPU_FTR_604_PERF_MON | CPU_FTR_HPTE_TABLE, + .cpu_features = CPU_FTR_604, .cpu_user_features = COMMON_PPC, .icache_bsize = 32, .dcache_bsize = 32, @@ -175,9 +131,7 @@ struct cpu_spec cpu_specs[] = { .pvr_mask = 0xffff0000, .pvr_value = 0x000a0000, .cpu_name = "604ev", - .cpu_features = CPU_FTR_COMMON | - CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | - CPU_FTR_604_PERF_MON | CPU_FTR_HPTE_TABLE, + .cpu_features = CPU_FTR_604, .cpu_user_features = COMMON_PPC, .icache_bsize = 32, .dcache_bsize = 32, @@ -188,10 +142,7 @@ struct cpu_spec cpu_specs[] = { .pvr_mask = 0xffffffff, .pvr_value = 0x00084202, .cpu_name = "740/750", - .cpu_features = CPU_FTR_COMMON | - CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_MAYBE_CAN_DOZE | - CPU_FTR_USE_TB | CPU_FTR_L2CR | CPU_FTR_HPTE_TABLE | - CPU_FTR_MAYBE_CAN_NAP, + .cpu_features = CPU_FTR_740_NOTAU, .cpu_user_features = COMMON_PPC, .icache_bsize = 32, .dcache_bsize = 32, @@ -202,10 +153,7 @@ struct cpu_spec cpu_specs[] = { .pvr_mask = 0xfffffff0, .pvr_value = 0x00080100, .cpu_name = "750CX", - .cpu_features = CPU_FTR_COMMON | - CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_MAYBE_CAN_DOZE | - CPU_FTR_USE_TB | CPU_FTR_L2CR | CPU_FTR_TAU | - CPU_FTR_HPTE_TABLE | CPU_FTR_MAYBE_CAN_NAP, + .cpu_features = CPU_FTR_750, .cpu_user_features = COMMON_PPC, .icache_bsize = 32, .dcache_bsize = 32, @@ -216,10 +164,7 @@ struct cpu_spec cpu_specs[] = { .pvr_mask = 0xfffffff0, .pvr_value = 0x00082200, .cpu_name = "750CX", - .cpu_features = CPU_FTR_COMMON | - CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_MAYBE_CAN_DOZE | - CPU_FTR_USE_TB | CPU_FTR_L2CR | CPU_FTR_TAU | - CPU_FTR_HPTE_TABLE | CPU_FTR_MAYBE_CAN_NAP, + .cpu_features = CPU_FTR_750, .cpu_user_features = COMMON_PPC, .icache_bsize = 32, .dcache_bsize = 32, @@ -230,10 +175,7 @@ struct cpu_spec cpu_specs[] = { .pvr_mask = 0xfffffff0, .pvr_value = 0x00082210, .cpu_name = "750CXe", - .cpu_features = CPU_FTR_COMMON | - CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_MAYBE_CAN_DOZE | - CPU_FTR_USE_TB | CPU_FTR_L2CR | CPU_FTR_TAU | - CPU_FTR_HPTE_TABLE | CPU_FTR_MAYBE_CAN_NAP, + .cpu_features = CPU_FTR_750, .cpu_user_features = COMMON_PPC, .icache_bsize = 32, .dcache_bsize = 32, @@ -244,10 +186,7 @@ struct cpu_spec cpu_specs[] = { .pvr_mask = 0xffffffff, .pvr_value = 0x00083214, .cpu_name = "750CXe", - .cpu_features = CPU_FTR_COMMON | - CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_MAYBE_CAN_DOZE | - CPU_FTR_USE_TB | CPU_FTR_L2CR | CPU_FTR_TAU | - CPU_FTR_HPTE_TABLE | CPU_FTR_MAYBE_CAN_NAP, + .cpu_features = CPU_FTR_750, .cpu_user_features = COMMON_PPC, .icache_bsize = 32, .dcache_bsize = 32, @@ -258,10 +197,7 @@ struct cpu_spec cpu_specs[] = { .pvr_mask = 0xfffff000, .pvr_value = 0x00083000, .cpu_name = "745/755", - .cpu_features = CPU_FTR_COMMON | - CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_MAYBE_CAN_DOZE | - CPU_FTR_USE_TB | CPU_FTR_L2CR | CPU_FTR_TAU | - CPU_FTR_HPTE_TABLE | CPU_FTR_MAYBE_CAN_NAP, + .cpu_features = CPU_FTR_750, .cpu_user_features = COMMON_PPC, .icache_bsize = 32, .dcache_bsize = 32, @@ -272,11 +208,7 @@ struct cpu_spec cpu_specs[] = { .pvr_mask = 0xffffff00, .pvr_value = 0x70000100, .cpu_name = "750FX", - .cpu_features = CPU_FTR_COMMON | - CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_MAYBE_CAN_DOZE | - CPU_FTR_USE_TB | CPU_FTR_L2CR | CPU_FTR_TAU | - CPU_FTR_HPTE_TABLE | CPU_FTR_MAYBE_CAN_NAP | - CPU_FTR_DUAL_PLL_750FX | CPU_FTR_NO_DPM, + .cpu_features = CPU_FTR_750FX1, .cpu_user_features = COMMON_PPC, .icache_bsize = 32, .dcache_bsize = 32, @@ -287,11 +219,7 @@ struct cpu_spec cpu_specs[] = { .pvr_mask = 0xffffffff, .pvr_value = 0x70000200, .cpu_name = "750FX", - .cpu_features = CPU_FTR_COMMON | - CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_MAYBE_CAN_DOZE | - CPU_FTR_USE_TB | CPU_FTR_L2CR | CPU_FTR_TAU | - CPU_FTR_HPTE_TABLE | CPU_FTR_MAYBE_CAN_NAP | - CPU_FTR_NO_DPM, + .cpu_features = CPU_FTR_750FX2, .cpu_user_features = COMMON_PPC, .icache_bsize = 32, .dcache_bsize = 32, @@ -302,11 +230,7 @@ struct cpu_spec cpu_specs[] = { .pvr_mask = 0xffff0000, .pvr_value = 0x70000000, .cpu_name = "750FX", - .cpu_features = CPU_FTR_COMMON | - CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_MAYBE_CAN_DOZE | - CPU_FTR_USE_TB | CPU_FTR_L2CR | CPU_FTR_TAU | - CPU_FTR_HPTE_TABLE | CPU_FTR_MAYBE_CAN_NAP | - CPU_FTR_DUAL_PLL_750FX | CPU_FTR_HAS_HIGH_BATS, + .cpu_features = CPU_FTR_750FX, .cpu_user_features = COMMON_PPC, .icache_bsize = 32, .dcache_bsize = 32, @@ -317,11 +241,7 @@ struct cpu_spec cpu_specs[] = { .pvr_mask = 0xffff0000, .pvr_value = 0x70020000, .cpu_name = "750GX", - .cpu_features = CPU_FTR_SPLIT_ID_CACHE | - CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB | - CPU_FTR_L2CR | CPU_FTR_TAU | CPU_FTR_HPTE_TABLE | - CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_DUAL_PLL_750FX | - CPU_FTR_HAS_HIGH_BATS, + .cpu_features = CPU_FTR_750GX, .cpu_user_features = COMMON_PPC, .icache_bsize = 32, .dcache_bsize = 32, @@ -332,10 +252,7 @@ struct cpu_spec cpu_specs[] = { .pvr_mask = 0xffff0000, .pvr_value = 0x00080000, .cpu_name = "740/750", - .cpu_features = CPU_FTR_COMMON | - CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_MAYBE_CAN_DOZE | - CPU_FTR_USE_TB | CPU_FTR_L2CR | CPU_FTR_TAU | - CPU_FTR_HPTE_TABLE | CPU_FTR_MAYBE_CAN_NAP, + .cpu_features = CPU_FTR_740, .cpu_user_features = COMMON_PPC, .icache_bsize = 32, .dcache_bsize = 32, @@ -346,11 +263,8 @@ struct cpu_spec cpu_specs[] = { .pvr_mask = 0xffffffff, .pvr_value = 0x000c1101, .cpu_name = "7400 (1.1)", - .cpu_features = CPU_FTR_COMMON | - CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_MAYBE_CAN_DOZE | - CPU_FTR_USE_TB | CPU_FTR_L2CR | CPU_FTR_ALTIVEC_COMP | - CPU_FTR_HPTE_TABLE | CPU_FTR_MAYBE_CAN_NAP, - .cpu_user_features = COMMON_PPC | PPC_FEATURE_ALTIVEC_COMP, + .cpu_features = CPU_FTR_7400_NOTAU, + .cpu_user_features = COMMON_PPC | PPC_FEATURE_HAS_ALTIVEC_COMP, .icache_bsize = 32, .dcache_bsize = 32, .num_pmcs = 4, @@ -360,12 +274,8 @@ struct cpu_spec cpu_specs[] = { .pvr_mask = 0xffff0000, .pvr_value = 0x000c0000, .cpu_name = "7400", - .cpu_features = CPU_FTR_COMMON | - CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_MAYBE_CAN_DOZE | - CPU_FTR_USE_TB | CPU_FTR_L2CR | CPU_FTR_TAU | - CPU_FTR_ALTIVEC_COMP | CPU_FTR_HPTE_TABLE | - CPU_FTR_MAYBE_CAN_NAP, - .cpu_user_features = COMMON_PPC | PPC_FEATURE_ALTIVEC_COMP, + .cpu_features = CPU_FTR_7400, + .cpu_user_features = COMMON_PPC | PPC_FEATURE_HAS_ALTIVEC_COMP, .icache_bsize = 32, .dcache_bsize = 32, .num_pmcs = 4, @@ -375,12 +285,8 @@ struct cpu_spec cpu_specs[] = { .pvr_mask = 0xffff0000, .pvr_value = 0x800c0000, .cpu_name = "7410", - .cpu_features = CPU_FTR_COMMON | - CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_MAYBE_CAN_DOZE | - CPU_FTR_USE_TB | CPU_FTR_L2CR | CPU_FTR_TAU | - CPU_FTR_ALTIVEC_COMP | CPU_FTR_HPTE_TABLE | - CPU_FTR_MAYBE_CAN_NAP, - .cpu_user_features = COMMON_PPC | PPC_FEATURE_ALTIVEC_COMP, + .cpu_features = CPU_FTR_7400, + .cpu_user_features = COMMON_PPC | PPC_FEATURE_HAS_ALTIVEC_COMP, .icache_bsize = 32, .dcache_bsize = 32, .num_pmcs = 4, @@ -390,12 +296,8 @@ struct cpu_spec cpu_specs[] = { .pvr_mask = 0xffffffff, .pvr_value = 0x80000200, .cpu_name = "7450", - .cpu_features = CPU_FTR_COMMON | - CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | - CPU_FTR_L2CR | CPU_FTR_ALTIVEC_COMP | CPU_FTR_L3CR | - CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 | - CPU_FTR_NEED_COHERENT, - .cpu_user_features = COMMON_PPC | PPC_FEATURE_ALTIVEC_COMP, + .cpu_features = CPU_FTR_7450_20, + .cpu_user_features = COMMON_PPC | PPC_FEATURE_HAS_ALTIVEC_COMP, .icache_bsize = 32, .dcache_bsize = 32, .num_pmcs = 6, @@ -405,14 +307,8 @@ struct cpu_spec cpu_specs[] = { .pvr_mask = 0xffffffff, .pvr_value = 0x80000201, .cpu_name = "7450", - .cpu_features = CPU_FTR_COMMON | - CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | - CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_L2CR | - CPU_FTR_ALTIVEC_COMP | CPU_FTR_L3CR | - CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 | - CPU_FTR_NAP_DISABLE_L2_PR | CPU_FTR_L3_DISABLE_NAP | - CPU_FTR_NEED_COHERENT, - .cpu_user_features = COMMON_PPC | PPC_FEATURE_ALTIVEC_COMP, + .cpu_features = CPU_FTR_7450_21, + .cpu_user_features = COMMON_PPC | PPC_FEATURE_HAS_ALTIVEC_COMP, .icache_bsize = 32, .dcache_bsize = 32, .num_pmcs = 6, @@ -422,13 +318,8 @@ struct cpu_spec cpu_specs[] = { .pvr_mask = 0xffff0000, .pvr_value = 0x80000000, .cpu_name = "7450", - .cpu_features = CPU_FTR_COMMON | - CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | - CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_L2CR | - CPU_FTR_ALTIVEC_COMP | CPU_FTR_L3CR | - CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 | - CPU_FTR_NAP_DISABLE_L2_PR | CPU_FTR_NEED_COHERENT, - .cpu_user_features = COMMON_PPC | PPC_FEATURE_ALTIVEC_COMP, + .cpu_features = CPU_FTR_7450_23, + .cpu_user_features = COMMON_PPC | PPC_FEATURE_HAS_ALTIVEC_COMP, .icache_bsize = 32, .dcache_bsize = 32, .num_pmcs = 6, @@ -438,12 +329,8 @@ struct cpu_spec cpu_specs[] = { .pvr_mask = 0xffffff00, .pvr_value = 0x80010100, .cpu_name = "7455", - .cpu_features = CPU_FTR_COMMON | - CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | - CPU_FTR_L2CR | CPU_FTR_ALTIVEC_COMP | CPU_FTR_L3CR | - CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 | - CPU_FTR_HAS_HIGH_BATS | CPU_FTR_NEED_COHERENT, - .cpu_user_features = COMMON_PPC | PPC_FEATURE_ALTIVEC_COMP, + .cpu_features = CPU_FTR_7455_1, + .cpu_user_features = COMMON_PPC | PPC_FEATURE_HAS_ALTIVEC_COMP, .icache_bsize = 32, .dcache_bsize = 32, .num_pmcs = 6, @@ -453,14 +340,8 @@ struct cpu_spec cpu_specs[] = { .pvr_mask = 0xffffffff, .pvr_value = 0x80010200, .cpu_name = "7455", - .cpu_features = CPU_FTR_COMMON | - CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | - CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_L2CR | - CPU_FTR_ALTIVEC_COMP | CPU_FTR_L3CR | - CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 | - CPU_FTR_NAP_DISABLE_L2_PR | CPU_FTR_L3_DISABLE_NAP | - CPU_FTR_NEED_COHERENT | CPU_FTR_HAS_HIGH_BATS, - .cpu_user_features = COMMON_PPC | PPC_FEATURE_ALTIVEC_COMP, + .cpu_features = CPU_FTR_7455_20, + .cpu_user_features = COMMON_PPC | PPC_FEATURE_HAS_ALTIVEC_COMP, .icache_bsize = 32, .dcache_bsize = 32, .num_pmcs = 6, @@ -470,14 +351,8 @@ struct cpu_spec cpu_specs[] = { .pvr_mask = 0xffff0000, .pvr_value = 0x80010000, .cpu_name = "7455", - .cpu_features = CPU_FTR_COMMON | - CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | - CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_L2CR | - CPU_FTR_ALTIVEC_COMP | CPU_FTR_L3CR | - CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 | - CPU_FTR_NAP_DISABLE_L2_PR | CPU_FTR_HAS_HIGH_BATS | - CPU_FTR_NEED_COHERENT, - .cpu_user_features = COMMON_PPC | PPC_FEATURE_ALTIVEC_COMP, + .cpu_features = CPU_FTR_7455, + .cpu_user_features = COMMON_PPC | PPC_FEATURE_HAS_ALTIVEC_COMP, .icache_bsize = 32, .dcache_bsize = 32, .num_pmcs = 6, @@ -487,14 +362,8 @@ struct cpu_spec cpu_specs[] = { .pvr_mask = 0xffffffff, .pvr_value = 0x80020100, .cpu_name = "7447/7457", - .cpu_features = CPU_FTR_COMMON | - CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | - CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_L2CR | - CPU_FTR_ALTIVEC_COMP | CPU_FTR_L3CR | - CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 | - CPU_FTR_NAP_DISABLE_L2_PR | CPU_FTR_HAS_HIGH_BATS | - CPU_FTR_NEED_COHERENT | CPU_FTR_NO_BTIC, - .cpu_user_features = COMMON_PPC | PPC_FEATURE_ALTIVEC_COMP, + .cpu_features = CPU_FTR_7447_10, + .cpu_user_features = COMMON_PPC | PPC_FEATURE_HAS_ALTIVEC_COMP, .icache_bsize = 32, .dcache_bsize = 32, .num_pmcs = 6, @@ -504,14 +373,8 @@ struct cpu_spec cpu_specs[] = { .pvr_mask = 0xffffffff, .pvr_value = 0x80020101, .cpu_name = "7447/7457", - .cpu_features = CPU_FTR_COMMON | - CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | - CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_L2CR | - CPU_FTR_ALTIVEC_COMP | CPU_FTR_L3CR | - CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 | - CPU_FTR_NAP_DISABLE_L2_PR | CPU_FTR_HAS_HIGH_BATS | - CPU_FTR_NEED_COHERENT | CPU_FTR_NO_BTIC, - .cpu_user_features = COMMON_PPC | PPC_FEATURE_ALTIVEC_COMP, + .cpu_features = CPU_FTR_7447_10, + .cpu_user_features = COMMON_PPC | PPC_FEATURE_HAS_ALTIVEC_COMP, .icache_bsize = 32, .dcache_bsize = 32, .num_pmcs = 6, @@ -521,14 +384,8 @@ struct cpu_spec cpu_specs[] = { .pvr_mask = 0xffff0000, .pvr_value = 0x80020000, .cpu_name = "7447/7457", - .cpu_features = CPU_FTR_COMMON | - CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | - CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_L2CR | - CPU_FTR_ALTIVEC_COMP | CPU_FTR_L3CR | - CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 | - CPU_FTR_NAP_DISABLE_L2_PR | CPU_FTR_HAS_HIGH_BATS | - CPU_FTR_NEED_COHERENT, - .cpu_user_features = COMMON_PPC | PPC_FEATURE_ALTIVEC_COMP, + .cpu_features = CPU_FTR_7447, + .cpu_user_features = COMMON_PPC | PPC_FEATURE_HAS_ALTIVEC_COMP, .icache_bsize = 32, .dcache_bsize = 32, .num_pmcs = 6, @@ -538,13 +395,8 @@ struct cpu_spec cpu_specs[] = { .pvr_mask = 0xffff0000, .pvr_value = 0x80030000, .cpu_name = "7447A", - .cpu_features = CPU_FTR_COMMON | - CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | - CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_L2CR | - CPU_FTR_ALTIVEC_COMP | CPU_FTR_HPTE_TABLE | - CPU_FTR_SPEC7450 | CPU_FTR_NAP_DISABLE_L2_PR | - CPU_FTR_HAS_HIGH_BATS | CPU_FTR_NEED_COHERENT, - .cpu_user_features = COMMON_PPC | PPC_FEATURE_ALTIVEC_COMP, + .cpu_features = CPU_FTR_7447A, + .cpu_user_features = COMMON_PPC | PPC_FEATURE_HAS_ALTIVEC_COMP, .icache_bsize = 32, .dcache_bsize = 32, .num_pmcs = 6, @@ -554,13 +406,8 @@ struct cpu_spec cpu_specs[] = { .pvr_mask = 0xffff0000, .pvr_value = 0x80040000, .cpu_name = "7448", - .cpu_features = CPU_FTR_COMMON | - CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | - CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_L2CR | - CPU_FTR_ALTIVEC_COMP | CPU_FTR_HPTE_TABLE | - CPU_FTR_SPEC7450 | CPU_FTR_NAP_DISABLE_L2_PR | - CPU_FTR_HAS_HIGH_BATS | CPU_FTR_NEED_COHERENT, - .cpu_user_features = COMMON_PPC | PPC_FEATURE_ALTIVEC_COMP, + .cpu_features = CPU_FTR_7447A, + .cpu_user_features = COMMON_PPC | PPC_FEATURE_HAS_ALTIVEC_COMP, .icache_bsize = 32, .dcache_bsize = 32, .num_pmcs = 6, @@ -570,9 +417,7 @@ struct cpu_spec cpu_specs[] = { .pvr_mask = 0x7fff0000, .pvr_value = 0x00810000, .cpu_name = "82xx", - .cpu_features = CPU_FTR_COMMON | - CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_MAYBE_CAN_DOZE | - CPU_FTR_USE_TB, + .cpu_features = CPU_FTR_82XX, .cpu_user_features = COMMON_PPC, .icache_bsize = 32, .dcache_bsize = 32, @@ -582,9 +427,7 @@ struct cpu_spec cpu_specs[] = { .pvr_mask = 0x7fff0000, .pvr_value = 0x00820000, .cpu_name = "G2_LE", - .cpu_features = CPU_FTR_SPLIT_ID_CACHE | - CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB | - CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_HAS_HIGH_BATS, + .cpu_features = CPU_FTR_G2_LE, .cpu_user_features = COMMON_PPC, .icache_bsize = 32, .dcache_bsize = 32, @@ -594,9 +437,7 @@ struct cpu_spec cpu_specs[] = { .pvr_mask = 0x7fff0000, .pvr_value = 0x00830000, .cpu_name = "e300", - .cpu_features = CPU_FTR_SPLIT_ID_CACHE | - CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB | - CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_HAS_HIGH_BATS, + .cpu_features = CPU_FTR_E300, .cpu_user_features = COMMON_PPC, .icache_bsize = 32, .dcache_bsize = 32, @@ -606,9 +447,7 @@ struct cpu_spec cpu_specs[] = { .pvr_mask = 0x00000000, .pvr_value = 0x00000000, .cpu_name = "(generic PPC)", - .cpu_features = CPU_FTR_COMMON | - CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | - CPU_FTR_HPTE_TABLE, + .cpu_features = CPU_FTR_CLASSIC32, .cpu_user_features = COMMON_PPC, .icache_bsize = 32, .dcache_bsize = 32, @@ -620,9 +459,7 @@ struct cpu_spec cpu_specs[] = { .pvr_mask = 0xffff0000, .pvr_value = 0x00400000, .cpu_name = "Power3 (630)", - .cpu_features = CPU_FTR_COMMON | - CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | - CPU_FTR_HPTE_TABLE, + .cpu_features = CPU_FTR_POWER3_32, .cpu_user_features = COMMON_PPC | PPC_FEATURE_64, .icache_bsize = 128, .dcache_bsize = 128, @@ -633,9 +470,7 @@ struct cpu_spec cpu_specs[] = { .pvr_mask = 0xffff0000, .pvr_value = 0x00410000, .cpu_name = "Power3 (630+)", - .cpu_features = CPU_FTR_COMMON | - CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | - CPU_FTR_HPTE_TABLE, + .cpu_features = CPU_FTR_POWER3_32, .cpu_user_features = COMMON_PPC | PPC_FEATURE_64, .icache_bsize = 128, .dcache_bsize = 128, @@ -646,9 +481,7 @@ struct cpu_spec cpu_specs[] = { .pvr_mask = 0xffff0000, .pvr_value = 0x00360000, .cpu_name = "I-star", - .cpu_features = CPU_FTR_COMMON | - CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | - CPU_FTR_HPTE_TABLE, + .cpu_features = CPU_FTR_POWER3_32, .cpu_user_features = COMMON_PPC | PPC_FEATURE_64, .icache_bsize = 128, .dcache_bsize = 128, @@ -659,55 +492,19 @@ struct cpu_spec cpu_specs[] = { .pvr_mask = 0xffff0000, .pvr_value = 0x00370000, .cpu_name = "S-star", - .cpu_features = CPU_FTR_COMMON | - CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | - CPU_FTR_HPTE_TABLE, + .cpu_features = CPU_FTR_POWER3_32, .cpu_user_features = COMMON_PPC | PPC_FEATURE_64, .icache_bsize = 128, .dcache_bsize = 128, .num_pmcs = 8, .cpu_setup = __setup_cpu_power3 }, -#endif /* CONFIG_PPC64BRIDGE */ -#ifdef CONFIG_POWER4 - { /* Power4 */ - .pvr_mask = 0xffff0000, - .pvr_value = 0x00350000, - .cpu_name = "Power4", - .cpu_features = CPU_FTR_COMMON | - CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | - CPU_FTR_HPTE_TABLE, - .cpu_user_features = COMMON_PPC | PPC_FEATURE_64, - .icache_bsize = 128, - .dcache_bsize = 128, - .num_pmcs = 8, - .cpu_setup = __setup_cpu_power4 - }, - { /* PPC970 */ - .pvr_mask = 0xffff0000, - .pvr_value = 0x00390000, - .cpu_name = "PPC970", - .cpu_features = CPU_FTR_COMMON | - CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | - CPU_FTR_HPTE_TABLE | - CPU_FTR_ALTIVEC_COMP | CPU_FTR_MAYBE_CAN_NAP, - .cpu_user_features = COMMON_PPC | PPC_FEATURE_64 | - PPC_FEATURE_ALTIVEC_COMP, - .icache_bsize = 128, - .dcache_bsize = 128, - .num_pmcs = 8, - .cpu_setup = __setup_cpu_ppc970 - }, { /* PPC970FX */ .pvr_mask = 0xffff0000, .pvr_value = 0x003c0000, .cpu_name = "PPC970FX", - .cpu_features = CPU_FTR_COMMON | - CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | - CPU_FTR_HPTE_TABLE | - CPU_FTR_ALTIVEC_COMP | CPU_FTR_MAYBE_CAN_NAP, - .cpu_user_features = COMMON_PPC | PPC_FEATURE_64 | - PPC_FEATURE_ALTIVEC_COMP, + .cpu_features = CPU_FTR_970_32, + .cpu_user_features = COMMON_PPC | PPC_FEATURE_64 | PPC_FEATURE_HAS_ALTIVEC_COMP, .icache_bsize = 128, .dcache_bsize = 128, .num_pmcs = 8, @@ -721,8 +518,7 @@ struct cpu_spec cpu_specs[] = { .cpu_name = "8xx", /* CPU_FTR_MAYBE_CAN_DOZE is possible, * if the 8xx code is there.... */ - .cpu_features = CPU_FTR_SPLIT_ID_CACHE | - CPU_FTR_USE_TB, + .cpu_features = CPU_FTR_8XX, .cpu_user_features = PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU, .icache_bsize = 16, .dcache_bsize = 16, @@ -733,8 +529,7 @@ struct cpu_spec cpu_specs[] = { .pvr_mask = 0xffffff00, .pvr_value = 0x00200200, .cpu_name = "403GC", - .cpu_features = CPU_FTR_SPLIT_ID_CACHE | - CPU_FTR_USE_TB, + .cpu_features = CPU_FTR_40X, .cpu_user_features = PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU, .icache_bsize = 16, .dcache_bsize = 16, @@ -743,8 +538,7 @@ struct cpu_spec cpu_specs[] = { .pvr_mask = 0xffffff00, .pvr_value = 0x00201400, .cpu_name = "403GCX", - .cpu_features = CPU_FTR_SPLIT_ID_CACHE | - CPU_FTR_USE_TB, + .cpu_features = CPU_FTR_40X, .cpu_user_features = PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU, .icache_bsize = 16, .dcache_bsize = 16, @@ -753,8 +547,7 @@ struct cpu_spec cpu_specs[] = { .pvr_mask = 0xffff0000, .pvr_value = 0x00200000, .cpu_name = "403G ??", - .cpu_features = CPU_FTR_SPLIT_ID_CACHE | - CPU_FTR_USE_TB, + .cpu_features = CPU_FTR_40X, .cpu_user_features = PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU, .icache_bsize = 16, .dcache_bsize = 16, @@ -763,8 +556,7 @@ struct cpu_spec cpu_specs[] = { .pvr_mask = 0xffff0000, .pvr_value = 0x40110000, .cpu_name = "405GP", - .cpu_features = CPU_FTR_SPLIT_ID_CACHE | - CPU_FTR_USE_TB, + .cpu_features = CPU_FTR_40X, .cpu_user_features = PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU | PPC_FEATURE_HAS_4xxMAC, .icache_bsize = 32, @@ -774,8 +566,7 @@ struct cpu_spec cpu_specs[] = { .pvr_mask = 0xffff0000, .pvr_value = 0x40130000, .cpu_name = "STB03xxx", - .cpu_features = CPU_FTR_SPLIT_ID_CACHE | - CPU_FTR_USE_TB, + .cpu_features = CPU_FTR_40X, .cpu_user_features = PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU | PPC_FEATURE_HAS_4xxMAC, .icache_bsize = 32, @@ -785,8 +576,7 @@ struct cpu_spec cpu_specs[] = { .pvr_mask = 0xffff0000, .pvr_value = 0x41810000, .cpu_name = "STB04xxx", - .cpu_features = CPU_FTR_SPLIT_ID_CACHE | - CPU_FTR_USE_TB, + .cpu_features = CPU_FTR_40X, .cpu_user_features = PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU | PPC_FEATURE_HAS_4xxMAC, .icache_bsize = 32, @@ -796,8 +586,7 @@ struct cpu_spec cpu_specs[] = { .pvr_mask = 0xffff0000, .pvr_value = 0x41610000, .cpu_name = "NP405L", - .cpu_features = CPU_FTR_SPLIT_ID_CACHE | - CPU_FTR_USE_TB, + .cpu_features = CPU_FTR_40X, .cpu_user_features = PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU | PPC_FEATURE_HAS_4xxMAC, .icache_bsize = 32, @@ -807,8 +596,7 @@ struct cpu_spec cpu_specs[] = { .pvr_mask = 0xffff0000, .pvr_value = 0x40B10000, .cpu_name = "NP4GS3", - .cpu_features = CPU_FTR_SPLIT_ID_CACHE | - CPU_FTR_USE_TB, + .cpu_features = CPU_FTR_40X, .cpu_user_features = PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU | PPC_FEATURE_HAS_4xxMAC, .icache_bsize = 32, @@ -818,8 +606,7 @@ struct cpu_spec cpu_specs[] = { .pvr_mask = 0xffff0000, .pvr_value = 0x41410000, .cpu_name = "NP405H", - .cpu_features = CPU_FTR_SPLIT_ID_CACHE | - CPU_FTR_USE_TB, + .cpu_features = CPU_FTR_40X, .cpu_user_features = PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU | PPC_FEATURE_HAS_4xxMAC, .icache_bsize = 32, @@ -829,8 +616,7 @@ struct cpu_spec cpu_specs[] = { .pvr_mask = 0xffff0000, .pvr_value = 0x50910000, .cpu_name = "405GPr", - .cpu_features = CPU_FTR_SPLIT_ID_CACHE | - CPU_FTR_USE_TB, + .cpu_features = CPU_FTR_40X, .cpu_user_features = PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU | PPC_FEATURE_HAS_4xxMAC, .icache_bsize = 32, @@ -840,8 +626,7 @@ struct cpu_spec cpu_specs[] = { .pvr_mask = 0xffff0000, .pvr_value = 0x51510000, .cpu_name = "STBx25xx", - .cpu_features = CPU_FTR_SPLIT_ID_CACHE | - CPU_FTR_USE_TB, + .cpu_features = CPU_FTR_40X, .cpu_user_features = PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU | PPC_FEATURE_HAS_4xxMAC, .icache_bsize = 32, @@ -851,8 +636,7 @@ struct cpu_spec cpu_specs[] = { .pvr_mask = 0xffff0000, .pvr_value = 0x41F10000, .cpu_name = "405LP", - .cpu_features = CPU_FTR_SPLIT_ID_CACHE | - CPU_FTR_USE_TB, + .cpu_features = CPU_FTR_40X, .cpu_user_features = PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU, .icache_bsize = 32, .dcache_bsize = 32, @@ -861,8 +645,7 @@ struct cpu_spec cpu_specs[] = { .pvr_mask = 0xffff0000, .pvr_value = 0x20010000, .cpu_name = "Virtex-II Pro", - .cpu_features = CPU_FTR_SPLIT_ID_CACHE | - CPU_FTR_USE_TB, + .cpu_features = CPU_FTR_40X, .cpu_user_features = PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU | PPC_FEATURE_HAS_4xxMAC, .icache_bsize = 32, @@ -872,8 +655,7 @@ struct cpu_spec cpu_specs[] = { .pvr_mask = 0xffff0000, .pvr_value = 0x51210000, .cpu_name = "405EP", - .cpu_features = CPU_FTR_SPLIT_ID_CACHE | - CPU_FTR_USE_TB, + .cpu_features = CPU_FTR_40X, .cpu_user_features = PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU | PPC_FEATURE_HAS_4xxMAC, .icache_bsize = 32, @@ -886,8 +668,7 @@ struct cpu_spec cpu_specs[] = { .pvr_mask = 0xf0000fff, .pvr_value = 0x40000850, .cpu_name = "440EP Rev. A", - .cpu_features = CPU_FTR_SPLIT_ID_CACHE | - CPU_FTR_USE_TB, + .cpu_features = CPU_FTR_44X, .cpu_user_features = COMMON_PPC, /* 440EP has an FPU */ .icache_bsize = 32, .dcache_bsize = 32, @@ -896,8 +677,7 @@ struct cpu_spec cpu_specs[] = { .pvr_mask = 0xf0000fff, .pvr_value = 0x400008d3, .cpu_name = "440EP Rev. B", - .cpu_features = CPU_FTR_SPLIT_ID_CACHE | - CPU_FTR_USE_TB, + .cpu_features = CPU_FTR_44X, .cpu_user_features = COMMON_PPC, /* 440EP has an FPU */ .icache_bsize = 32, .dcache_bsize = 32, @@ -906,8 +686,7 @@ struct cpu_spec cpu_specs[] = { .pvr_mask = 0xf0000fff, .pvr_value = 0x40000440, .cpu_name = "440GP Rev. B", - .cpu_features = CPU_FTR_SPLIT_ID_CACHE | - CPU_FTR_USE_TB, + .cpu_features = CPU_FTR_44X, .cpu_user_features = PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU, .icache_bsize = 32, .dcache_bsize = 32, @@ -916,8 +695,7 @@ struct cpu_spec cpu_specs[] = { .pvr_mask = 0xf0000fff, .pvr_value = 0x40000481, .cpu_name = "440GP Rev. C", - .cpu_features = CPU_FTR_SPLIT_ID_CACHE | - CPU_FTR_USE_TB, + .cpu_features = CPU_FTR_44X, .cpu_user_features = PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU, .icache_bsize = 32, .dcache_bsize = 32, @@ -926,8 +704,7 @@ struct cpu_spec cpu_specs[] = { .pvr_mask = 0xf0000fff, .pvr_value = 0x50000850, .cpu_name = "440GX Rev. A", - .cpu_features = CPU_FTR_SPLIT_ID_CACHE | - CPU_FTR_USE_TB, + .cpu_features = CPU_FTR_44X, .cpu_user_features = PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU, .icache_bsize = 32, .dcache_bsize = 32, @@ -936,8 +713,7 @@ struct cpu_spec cpu_specs[] = { .pvr_mask = 0xf0000fff, .pvr_value = 0x50000851, .cpu_name = "440GX Rev. B", - .cpu_features = CPU_FTR_SPLIT_ID_CACHE | - CPU_FTR_USE_TB, + .cpu_features = CPU_FTR_44X, .cpu_user_features = PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU, .icache_bsize = 32, .dcache_bsize = 32, @@ -946,8 +722,7 @@ struct cpu_spec cpu_specs[] = { .pvr_mask = 0xf0000fff, .pvr_value = 0x50000892, .cpu_name = "440GX Rev. C", - .cpu_features = CPU_FTR_SPLIT_ID_CACHE | - CPU_FTR_USE_TB, + .cpu_features = CPU_FTR_44X, .cpu_user_features = PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU, .icache_bsize = 32, .dcache_bsize = 32, @@ -956,8 +731,7 @@ struct cpu_spec cpu_specs[] = { .pvr_mask = 0xf0000fff, .pvr_value = 0x50000894, .cpu_name = "440GX Rev. F", - .cpu_features = CPU_FTR_SPLIT_ID_CACHE | - CPU_FTR_USE_TB, + .cpu_features = CPU_FTR_44X, .cpu_user_features = PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU, .icache_bsize = 32, .dcache_bsize = 32, @@ -966,8 +740,7 @@ struct cpu_spec cpu_specs[] = { .pvr_mask = 0xff000fff, .pvr_value = 0x53000891, .cpu_name = "440SP Rev. A", - .cpu_features = CPU_FTR_SPLIT_ID_CACHE | - CPU_FTR_USE_TB, + .cpu_features = CPU_FTR_44X, .cpu_user_features = PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU, .icache_bsize = 32, .dcache_bsize = 32, @@ -979,7 +752,7 @@ struct cpu_spec cpu_specs[] = { .pvr_value = 0x81000000, .cpu_name = "e200z5", /* xxx - galak: add CPU_FTR_MAYBE_CAN_DOZE */ - .cpu_features = CPU_FTR_USE_TB, + .cpu_features = CPU_FTR_E200, .cpu_user_features = PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU | PPC_FEATURE_HAS_EFP_SINGLE | PPC_FEATURE_UNIFIED_CACHE, @@ -990,7 +763,7 @@ struct cpu_spec cpu_specs[] = { .pvr_value = 0x81100000, .cpu_name = "e200z6", /* xxx - galak: add CPU_FTR_MAYBE_CAN_DOZE */ - .cpu_features = CPU_FTR_USE_TB, + .cpu_features = CPU_FTR_E200, .cpu_user_features = PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU | PPC_FEATURE_SPE_COMP | PPC_FEATURE_HAS_EFP_SINGLE | @@ -1002,8 +775,7 @@ struct cpu_spec cpu_specs[] = { .pvr_value = 0x80200000, .cpu_name = "e500", /* xxx - galak: add CPU_FTR_MAYBE_CAN_DOZE */ - .cpu_features = CPU_FTR_SPLIT_ID_CACHE | - CPU_FTR_USE_TB, + .cpu_features = CPU_FTR_E500, .cpu_user_features = PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU | PPC_FEATURE_SPE_COMP | PPC_FEATURE_HAS_EFP_SINGLE, @@ -1016,8 +788,7 @@ struct cpu_spec cpu_specs[] = { .pvr_value = 0x80210000, .cpu_name = "e500v2", /* xxx - galak: add CPU_FTR_MAYBE_CAN_DOZE */ - .cpu_features = CPU_FTR_SPLIT_ID_CACHE | - CPU_FTR_USE_TB | CPU_FTR_BIG_PHYS, + .cpu_features = CPU_FTR_E500_2, .cpu_user_features = PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU | PPC_FEATURE_SPE_COMP | PPC_FEATURE_HAS_EFP_SINGLE | PPC_FEATURE_HAS_EFP_DOUBLE, @@ -1031,7 +802,7 @@ struct cpu_spec cpu_specs[] = { .pvr_mask = 0x00000000, .pvr_value = 0x00000000, .cpu_name = "(generic PPC)", - .cpu_features = CPU_FTR_COMMON, + .cpu_features = CPU_FTR_GENERIC_32, .cpu_user_features = PPC_FEATURE_32, .icache_bsize = 32, .dcache_bsize = 32, Index: clean-cg/include/asm-powerpc/cputable.h =================================================================== --- /dev/null +++ clean-cg/include/asm-powerpc/cputable.h @@ -0,0 +1,475 @@ +#ifndef __ASM_POWERPC_CPUTABLE_H +#define __ASM_POWERPC_CPUTABLE_H + +#ifdef __KERNEL__ +#include +#include /* for ASM_CONST */ + +#define PPC_FEATURE_32 0x80000000 +#define PPC_FEATURE_64 0x40000000 +#define PPC_FEATURE_601_INSTR 0x20000000 +#define PPC_FEATURE_HAS_ALTIVEC 0x10000000 +#define PPC_FEATURE_HAS_FPU 0x08000000 +#define PPC_FEATURE_HAS_MMU 0x04000000 +#define PPC_FEATURE_HAS_4xxMAC 0x02000000 +#define PPC_FEATURE_UNIFIED_CACHE 0x01000000 +#define PPC_FEATURE_HAS_SPE 0x00800000 +#define PPC_FEATURE_HAS_EFP_SINGLE 0x00400000 +#define PPC_FEATURE_HAS_EFP_DOUBLE 0x00200000 + +#ifndef __ASSEMBLY__ + +/* This structure can grow, it's real size is used by head.S code + * via the mkdefs mechanism. + */ +struct cpu_spec; +struct op_ppc64_model; + +#ifndef __powerpc64__ +typedef void (*cpu_setup_t)(unsigned long offset, int cpu_nr, struct cpu_spec* spec); +#else /* __powerpc64__ */ +typedef void (*cpu_setup_t)(unsigned long offset, struct cpu_spec* spec); +#endif /* __powerpc64__ */ + +struct cpu_spec { + /* CPU is matched via (PVR & pvr_mask) == pvr_value */ + unsigned int pvr_mask; + unsigned int pvr_value; + + char *cpu_name; + unsigned long cpu_features; /* Kernel features */ + unsigned int cpu_user_features; /* Userland features */ + + /* cache line sizes */ + 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 + */ + cpu_setup_t cpu_setup; +#ifdef __powerpc64__ + + /* Used by oprofile userspace to select the right counters */ + char *oprofile_cpu_type; + + /* Processor specific oprofile operations */ + struct op_ppc64_model *oprofile_model; +#endif /* __powerpc64__ */ +}; + +extern struct cpu_spec cpu_specs[]; + +#ifndef __powerpc64__ +extern struct cpu_spec *cur_cpu_spec[]; +#else /* __powerpc64__ */ +extern struct cpu_spec *cur_cpu_spec; +#endif /* __powerpc64__ */ + +#endif /* __ASSEMBLY__ */ + +/* CPU kernel features */ + +/* Retain the 32b definitions all use bottom half of word */ +#define CPU_FTR_SPLIT_ID_CACHE ASM_CONST(0x0000000000000001) +#define CPU_FTR_L2CR ASM_CONST(0x0000000000000002) +#define CPU_FTR_SPEC7450 ASM_CONST(0x0000000000000004) +#define CPU_FTR_ALTIVEC ASM_CONST(0x0000000000000008) +#define CPU_FTR_TAU ASM_CONST(0x0000000000000010) +#define CPU_FTR_CAN_DOZE ASM_CONST(0x0000000000000020) +#define CPU_FTR_USE_TB ASM_CONST(0x0000000000000040) +#define CPU_FTR_604_PERF_MON ASM_CONST(0x0000000000000080) +#define CPU_FTR_601 ASM_CONST(0x0000000000000100) +#define CPU_FTR_HPTE_TABLE ASM_CONST(0x0000000000000200) +#define CPU_FTR_CAN_NAP ASM_CONST(0x0000000000000400) +#define CPU_FTR_L3CR ASM_CONST(0x0000000000000800) +#define CPU_FTR_L3_DISABLE_NAP ASM_CONST(0x0000000000001000) +#define CPU_FTR_NAP_DISABLE_L2_PR ASM_CONST(0x0000000000002000) +#define CPU_FTR_DUAL_PLL_750FX ASM_CONST(0x0000000000004000) +#define CPU_FTR_NO_DPM ASM_CONST(0x0000000000008000) +#define CPU_FTR_HAS_HIGH_BATS ASM_CONST(0x0000000000010000) +#define CPU_FTR_NEED_COHERENT ASM_CONST(0x0000000000020000) +#define CPU_FTR_NO_BTIC ASM_CONST(0x0000000000040000) +#define CPU_FTR_BIG_PHYS ASM_CONST(0x0000000000080000) + +#ifdef __powerpc64__ +/* Add the 64b processor unique features in the top half of the word */ +#define CPU_FTR_SLB ASM_CONST(0x0000000100000000) +#define CPU_FTR_16M_PAGE ASM_CONST(0x0000000200000000) +#define CPU_FTR_TLBIEL ASM_CONST(0x0000000400000000) +#define CPU_FTR_NOEXECUTE ASM_CONST(0x0000000800000000) +#define CPU_FTR_NODSISRALIGN ASM_CONST(0x0000001000000000) +#define CPU_FTR_IABR ASM_CONST(0x0000002000000000) +#define CPU_FTR_MMCRA ASM_CONST(0x0000004000000000) +/* 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) +#define CPU_FTR_MMCRA_SIHV ASM_CONST(0x0000080000000000) +#define CPU_FTR_CTRL ASM_CONST(0x0000100000000000) +#endif + +#ifndef __ASSEMBLY__ + +#define COMMON_USER_PPC64 (PPC_FEATURE_32 | PPC_FEATURE_64 | \ + PPC_FEATURE_HAS_FPU | PPC_FEATURE_HAS_MMU) + +#define CPU_FTR_PPCAS_ARCH_V2_BASE (CPU_FTR_SLB | \ + CPU_FTR_TLBIEL | CPU_FTR_NOEXECUTE | \ + CPU_FTR_NODSISRALIGN | CPU_FTR_CTRL) + +/* iSeries doesn't support large pages */ +#ifdef CONFIG_PPC_ISERIES +#define CPU_FTR_PPCAS_ARCH_V2 (CPU_FTR_PPCAS_ARCH_V2_BASE) +#else +#define CPU_FTR_PPCAS_ARCH_V2 (CPU_FTR_PPCAS_ARCH_V2_BASE | CPU_FTR_16M_PAGE) +#endif /* CONFIG_PPC_ISERIES */ + +/* We only set the altivec features if the kernel was compiled with altivec + * support + */ +#ifdef CONFIG_ALTIVEC +#define CPU_FTR_ALTIVEC_COMP CPU_FTR_ALTIVEC +#define PPC_FEATURE_HAS_ALTIVEC_COMP PPC_FEATURE_HAS_ALTIVEC +#else +#define CPU_FTR_ALTIVEC_COMP 0 +#define PPC_FEATURE_HAS_ALTIVEC_COMP 0 +#endif + +/* We need to mark all pages as being coherent if we're SMP or we + * have a 74[45]x and an MPC107 host bridge. + */ +#if defined(CONFIG_SMP) || defined(CONFIG_MPC10X_BRIDGE) +#define CPU_FTR_COMMON CPU_FTR_NEED_COHERENT +#else +#define CPU_FTR_COMMON 0 +#endif + +/* The powersave features NAP & DOZE seems to confuse BDI when + debugging. So if a BDI is used, disable theses + */ +#ifndef CONFIG_BDI_SWITCH +#define CPU_FTR_MAYBE_CAN_DOZE CPU_FTR_CAN_DOZE +#define CPU_FTR_MAYBE_CAN_NAP CPU_FTR_CAN_NAP +#else +#define CPU_FTR_MAYBE_CAN_DOZE 0 +#define CPU_FTR_MAYBE_CAN_NAP 0 +#endif + +#define CLASSIC_PPC (!defined(CONFIG_8xx) && !defined(CONFIG_4xx) && \ + !defined(CONFIG_POWER3) && !defined(CONFIG_POWER4) && \ + !defined(CONFIG_BOOKE)) + +enum { + CPU_FTR_PPC601 = CPU_FTR_COMMON | CPU_FTR_601 | CPU_FTR_HPTE_TABLE, + CPU_FTR_603 = CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | + CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB | + CPU_FTR_MAYBE_CAN_NAP, + CPU_FTR_604 = CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | + CPU_FTR_USE_TB | CPU_FTR_604_PERF_MON | CPU_FTR_HPTE_TABLE, + CPU_FTR_740_NOTAU = CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | + CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB | CPU_FTR_L2CR | + CPU_FTR_HPTE_TABLE | CPU_FTR_MAYBE_CAN_NAP, + CPU_FTR_740 = CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | + CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB | CPU_FTR_L2CR | + CPU_FTR_TAU | CPU_FTR_HPTE_TABLE | CPU_FTR_MAYBE_CAN_NAP, + CPU_FTR_750 = CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | + CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB | CPU_FTR_L2CR | + CPU_FTR_TAU | CPU_FTR_HPTE_TABLE | CPU_FTR_MAYBE_CAN_NAP, + CPU_FTR_750FX1 = CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | + CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB | CPU_FTR_L2CR | + CPU_FTR_TAU | CPU_FTR_HPTE_TABLE | CPU_FTR_MAYBE_CAN_NAP | + CPU_FTR_DUAL_PLL_750FX | CPU_FTR_NO_DPM, + CPU_FTR_750FX2 = CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | + CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB | CPU_FTR_L2CR | + CPU_FTR_TAU | CPU_FTR_HPTE_TABLE | CPU_FTR_MAYBE_CAN_NAP | + CPU_FTR_NO_DPM, + CPU_FTR_750FX = CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | + CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB | CPU_FTR_L2CR | + CPU_FTR_TAU | CPU_FTR_HPTE_TABLE | CPU_FTR_MAYBE_CAN_NAP | + CPU_FTR_DUAL_PLL_750FX | CPU_FTR_HAS_HIGH_BATS, + CPU_FTR_750GX = CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_MAYBE_CAN_DOZE | + CPU_FTR_USE_TB | CPU_FTR_L2CR | CPU_FTR_TAU | + CPU_FTR_HPTE_TABLE | CPU_FTR_MAYBE_CAN_NAP | + CPU_FTR_DUAL_PLL_750FX | CPU_FTR_HAS_HIGH_BATS, + CPU_FTR_7400_NOTAU = CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | + CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB | CPU_FTR_L2CR | + CPU_FTR_ALTIVEC_COMP | CPU_FTR_HPTE_TABLE | + CPU_FTR_MAYBE_CAN_NAP, + CPU_FTR_7400 = CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | + CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB | CPU_FTR_L2CR | + CPU_FTR_TAU | CPU_FTR_ALTIVEC_COMP | CPU_FTR_HPTE_TABLE | + CPU_FTR_MAYBE_CAN_NAP, + CPU_FTR_7450_20 = CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | + CPU_FTR_USE_TB | CPU_FTR_L2CR | CPU_FTR_ALTIVEC_COMP | + CPU_FTR_L3CR | CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 | + CPU_FTR_NEED_COHERENT, + CPU_FTR_7450_21 = CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | + CPU_FTR_USE_TB | + CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_L2CR | CPU_FTR_ALTIVEC_COMP | + CPU_FTR_L3CR | CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 | + CPU_FTR_NAP_DISABLE_L2_PR | CPU_FTR_L3_DISABLE_NAP | + CPU_FTR_NEED_COHERENT, + CPU_FTR_7450_23 = CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | + CPU_FTR_USE_TB | + CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_L2CR | CPU_FTR_ALTIVEC_COMP | + CPU_FTR_L3CR | CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 | + CPU_FTR_NAP_DISABLE_L2_PR | CPU_FTR_NEED_COHERENT, + CPU_FTR_7455_1 = CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | + CPU_FTR_USE_TB | + CPU_FTR_L2CR | CPU_FTR_ALTIVEC_COMP | CPU_FTR_L3CR | + CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 | CPU_FTR_HAS_HIGH_BATS | + CPU_FTR_NEED_COHERENT, + CPU_FTR_7455_20 = CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | + CPU_FTR_USE_TB | + CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_L2CR | CPU_FTR_ALTIVEC_COMP | + CPU_FTR_L3CR | CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 | + CPU_FTR_NAP_DISABLE_L2_PR | CPU_FTR_L3_DISABLE_NAP | + CPU_FTR_NEED_COHERENT | CPU_FTR_HAS_HIGH_BATS, + CPU_FTR_7455 = CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | + CPU_FTR_USE_TB | + CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_L2CR | CPU_FTR_ALTIVEC_COMP | + CPU_FTR_L3CR | CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 | + CPU_FTR_NAP_DISABLE_L2_PR | CPU_FTR_HAS_HIGH_BATS | + CPU_FTR_NEED_COHERENT, + CPU_FTR_7447_10 = CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | + CPU_FTR_USE_TB | + CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_L2CR | CPU_FTR_ALTIVEC_COMP | + CPU_FTR_L3CR | CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 | + CPU_FTR_NAP_DISABLE_L2_PR | CPU_FTR_HAS_HIGH_BATS | + CPU_FTR_NEED_COHERENT | CPU_FTR_NO_BTIC, + CPU_FTR_7447 = CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | + CPU_FTR_USE_TB | + CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_L2CR | CPU_FTR_ALTIVEC_COMP | + CPU_FTR_L3CR | CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 | + CPU_FTR_NAP_DISABLE_L2_PR | CPU_FTR_HAS_HIGH_BATS | + CPU_FTR_NEED_COHERENT, + CPU_FTR_7447A = CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | + CPU_FTR_USE_TB | + CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_L2CR | CPU_FTR_ALTIVEC_COMP | + CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 | + CPU_FTR_NAP_DISABLE_L2_PR | CPU_FTR_HAS_HIGH_BATS | + CPU_FTR_NEED_COHERENT, + CPU_FTR_82XX = CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | + CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB, + CPU_FTR_G2_LE = CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_MAYBE_CAN_DOZE | + CPU_FTR_USE_TB | CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_HAS_HIGH_BATS, + CPU_FTR_E300 = CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_MAYBE_CAN_DOZE | + CPU_FTR_USE_TB | CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_HAS_HIGH_BATS, + CPU_FTR_CLASSIC32 = CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | + CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE, + CPU_FTR_POWER3_32 = CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | + CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE, + CPU_FTR_POWER4_32 = CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | + CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE, + CPU_FTR_970_32 = CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | + CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE | CPU_FTR_ALTIVEC_COMP | + CPU_FTR_MAYBE_CAN_NAP, + CPU_FTR_8XX = CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB, + CPU_FTR_40X = CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB, + CPU_FTR_44X = CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB, + CPU_FTR_E200 = CPU_FTR_USE_TB, + CPU_FTR_E500 = CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB, + CPU_FTR_E500_2 = CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | + CPU_FTR_BIG_PHYS, + CPU_FTR_GENERIC_32 = CPU_FTR_COMMON, +#ifdef __powerpc64__ + CPU_FTR_POWER3 = CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | + CPU_FTR_HPTE_TABLE | CPU_FTR_IABR, + CPU_FTR_RS64 = CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | + CPU_FTR_HPTE_TABLE | CPU_FTR_IABR | + CPU_FTR_MMCRA | CPU_FTR_CTRL, + CPU_FTR_POWER4 = CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | + CPU_FTR_HPTE_TABLE | CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_MMCRA, + CPU_FTR_PPC970 = 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_MMCRA, + CPU_FTR_POWER5 = CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | + CPU_FTR_HPTE_TABLE | CPU_FTR_PPCAS_ARCH_V2 | + CPU_FTR_MMCRA | CPU_FTR_SMT | + CPU_FTR_COHERENT_ICACHE | CPU_FTR_LOCKLESS_TLBIE | + CPU_FTR_MMCRA_SIHV, + CPU_FTR_CELL = CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | + CPU_FTR_HPTE_TABLE | CPU_FTR_PPCAS_ARCH_V2 | + CPU_FTR_ALTIVEC_COMP | CPU_FTR_MMCRA | CPU_FTR_SMT, + CPU_FTR_COMPATIBLE = CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | + CPU_FTR_HPTE_TABLE | CPU_FTR_PPCAS_ARCH_V2, +#endif + CPU_FTR_POSSIBLE = +#if CLASSIC_PPC + CPU_FTR_601 | CPU_FTR_603 | CPU_FTR_604 | CPU_FTR_740_NOTAU | + CPU_FTR_740 | CPU_FTR_750 | CPU_FTR_750FX1 | + CPU_FTR_750FX2 | CPU_FTR_750FX | CPU_FTR_750GX | + CPU_FTR_7400_NOTAU | CPU_FTR_7400 | CPU_FTR_7450_20 | + CPU_FTR_7450_21 | CPU_FTR_7450_23 | CPU_FTR_7455_1 | + CPU_FTR_7455_20 | CPU_FTR_7455 | CPU_FTR_7447_10 | + CPU_FTR_7447 | CPU_FTR_7447A | CPU_FTR_82XX | + CPU_FTR_G2_LE | CPU_FTR_E300 | CPU_FTR_CLASSIC32 | +#else + CPU_FTR_GENERIC_32 | +#endif +#ifdef CONFIG_PPC64BRIDGE + CPU_FTR_POWER3_32 | +#endif +#ifdef CONFIG_POWER4 + CPU_FTR_POWER4_32 | CPU_FTR_970_32 | +#endif +#ifdef CONFIG_8xx + CPU_FTR_8XX | +#endif +#ifdef CONFIG_40x + CPU_FTR_40X | +#endif +#ifdef CONFIG_44x + CPU_FTR_44X | +#endif +#ifdef CONFIG_FSL_BOOKE + CPU_FTR_E200 | CPU_FTR_E500 | CPU_FTR_E500_2 | +#endif +#ifdef CONFIG_CPU_POWER3 + CPU_FTR_POWER3 | +#endif +#ifdef CONFIG_CPU_RS64 + CPU_FTR_RS64 | +#endif +#ifdef CONFIG_CPU_POWER4 + CPU_FTR_POWER4 | +#endif +#ifdef CONFIG_CPU_PPC970 + CPU_FTR_PPC970 | +#endif +#ifdef CONFIG_CPU_POWER5 + CPU_FTR_POWER5 | +#endif +#ifdef CONFIG_CPU_CELL + CPU_FTR_CELL | +#endif + 0, + CPU_FTR_ALWAYS = +#if CLASSIC_PPC + CPU_FTR_601 & CPU_FTR_603 & CPU_FTR_604 & CPU_FTR_740_NOTAU & + CPU_FTR_740 & CPU_FTR_750 & CPU_FTR_750FX1 & + CPU_FTR_750FX2 & CPU_FTR_750FX & CPU_FTR_750GX & + CPU_FTR_7400_NOTAU & CPU_FTR_7400 & CPU_FTR_7450_20 & + CPU_FTR_7450_21 & CPU_FTR_7450_23 & CPU_FTR_7455_1 & + CPU_FTR_7455_20 & CPU_FTR_7455 & CPU_FTR_7447_10 & + CPU_FTR_7447 & CPU_FTR_7447A & CPU_FTR_82XX & + CPU_FTR_G2_LE & CPU_FTR_E300 & CPU_FTR_CLASSIC32 & +#else + CPU_FTR_GENERIC_32 & +#endif +#ifdef CONFIG_PPC64BRIDGE + CPU_FTR_POWER3_32 & +#endif +#ifdef CONFIG_POWER4 + CPU_FTR_POWER4_32 & CPU_FTR_970_32 & +#endif +#ifdef CONFIG_8xx + CPU_FTR_8XX & +#endif +#ifdef CONFIG_40x + CPU_FTR_40X & +#endif +#ifdef CONFIG_44x + CPU_FTR_44X & +#endif +#ifdef CONFIG_FSL_BOOKE + CPU_FTR_E200 & CPU_FTR_E500 & CPU_FTR_E500_2 & +#endif +#ifdef CONFIG_CPU_POWER3 + CPU_FTR_POWER3 & +#endif +#ifdef CONFIG_CPU_RS64 + CPU_FTR_RS64 & +#endif +#ifdef CONFIG_CPU_POWER4 + CPU_FTR_POWER4 & +#endif +#ifdef CONFIG_CPU_PPC970 + CPU_FTR_PPC970 & +#endif +#ifdef CONFIG_CPU_POWER5 + CPU_FTR_POWER5 & +#endif +#ifdef CONFIG_CPU_CELL + CPU_FTR_CELL & +#endif + CPU_FTR_POSSIBLE, +}; + +static inline int cpu_has_feature(unsigned long feature) +{ + return (CPU_FTR_ALWAYS & feature) || + (CPU_FTR_POSSIBLE +#ifndef __powerpc64__ + & cur_cpu_spec[0]->cpu_features +#else + & cur_cpu_spec->cpu_features +#endif + & feature); +} + +#endif /* __ASSEMBLY */ + +#ifdef __ASSEMBLY__ + +#define BEGIN_FTR_SECTION 98: + +#ifndef __powerpc64__ +#define END_FTR_SECTION(msk, val) \ +99: \ + .section __ftr_fixup,"a"; \ + .align 2; \ + .long msk; \ + .long val; \ + .long 98b; \ + .long 99b; \ + .previous +#else /* __powerpc64__ */ +#define END_FTR_SECTION(msk, val) \ +99: \ + .section __ftr_fixup,"a"; \ + .align 3; \ + .llong msk; \ + .llong val; \ + .llong 98b; \ + .llong 99b; \ + .previous +#endif /* __powerpc64__ */ + +#else + +#define BEGIN_FTR_SECTION "98:\n" + +#ifndef __powerpc64__ +#define END_FTR_SECTION(msk, val) \ +"99:\n" \ +" .section __ftr_fixup,\"a\";\n" \ +" .align 2;\n" \ +" .long "#msk";\n" \ +" .long "#val";\n" \ +" .long 98b;\n" \ +" .long 99b;\n" \ +" .previous\n" +#else /* __powerpc64__ */ +#define END_FTR_SECTION(msk, val) \ +"99:\n" \ +" .section __ftr_fixup,\"a\";\n" \ +" .align 3;\n" \ +" .llong "#msk";\n" \ +" .llong "#val";\n" \ +" .llong 98b;\n" \ +" .llong 99b;\n" \ +" .previous\n" +#endif /* __powerpc64__ */ + +#endif /* __ASSEMBLY__ */ + +#define END_FTR_SECTION_IFSET(msk) END_FTR_SECTION((msk), (msk)) +#define END_FTR_SECTION_IFCLR(msk) END_FTR_SECTION((msk), 0) + +#endif /* __KERNEL__ */ +#endif /* __ASM_POWERPC_CPUTABLE_H */ Index: clean-cg/include/asm-ppc/cputable.h =================================================================== --- clean-cg.orig/include/asm-ppc/cputable.h +++ /dev/null @@ -1,128 +0,0 @@ -/* - * include/asm-ppc/cputable.h - * - * Copyright (C) 2001 Ben. 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. - */ - -#ifndef __ASM_PPC_CPUTABLE_H -#define __ASM_PPC_CPUTABLE_H - -/* Exposed to userland CPU features */ -#define PPC_FEATURE_32 0x80000000 -#define PPC_FEATURE_64 0x40000000 -#define PPC_FEATURE_601_INSTR 0x20000000 -#define PPC_FEATURE_HAS_ALTIVEC 0x10000000 -#define PPC_FEATURE_HAS_FPU 0x08000000 -#define PPC_FEATURE_HAS_MMU 0x04000000 -#define PPC_FEATURE_HAS_4xxMAC 0x02000000 -#define PPC_FEATURE_UNIFIED_CACHE 0x01000000 -#define PPC_FEATURE_HAS_SPE 0x00800000 -#define PPC_FEATURE_HAS_EFP_SINGLE 0x00400000 -#define PPC_FEATURE_HAS_EFP_DOUBLE 0x00200000 - -#ifdef __KERNEL__ - -#ifndef __ASSEMBLY__ - -/* This structure can grow, it's real size is used by head.S code - * via the mkdefs mecanism. - */ -struct cpu_spec; - -typedef void (*cpu_setup_t)(unsigned long offset, int cpu_nr, struct cpu_spec* spec); - -struct cpu_spec { - /* CPU is matched via (PVR & pvr_mask) == pvr_value */ - unsigned int pvr_mask; - unsigned int pvr_value; - - char *cpu_name; - unsigned int cpu_features; /* Kernel features */ - unsigned int cpu_user_features; /* Userland features */ - - /* cache line sizes */ - 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 - */ - cpu_setup_t cpu_setup; -}; - -extern struct cpu_spec cpu_specs[]; -extern struct cpu_spec *cur_cpu_spec[]; - -static inline unsigned int cpu_has_feature(unsigned int feature) -{ - return cur_cpu_spec[0]->cpu_features & feature; -} - -#endif /* __ASSEMBLY__ */ - -/* CPU kernel features */ -#define CPU_FTR_SPLIT_ID_CACHE 0x00000001 -#define CPU_FTR_L2CR 0x00000002 -#define CPU_FTR_SPEC7450 0x00000004 -#define CPU_FTR_ALTIVEC 0x00000008 -#define CPU_FTR_TAU 0x00000010 -#define CPU_FTR_CAN_DOZE 0x00000020 -#define CPU_FTR_USE_TB 0x00000040 -#define CPU_FTR_604_PERF_MON 0x00000080 -#define CPU_FTR_601 0x00000100 -#define CPU_FTR_HPTE_TABLE 0x00000200 -#define CPU_FTR_CAN_NAP 0x00000400 -#define CPU_FTR_L3CR 0x00000800 -#define CPU_FTR_L3_DISABLE_NAP 0x00001000 -#define CPU_FTR_NAP_DISABLE_L2_PR 0x00002000 -#define CPU_FTR_DUAL_PLL_750FX 0x00004000 -#define CPU_FTR_NO_DPM 0x00008000 -#define CPU_FTR_HAS_HIGH_BATS 0x00010000 -#define CPU_FTR_NEED_COHERENT 0x00020000 -#define CPU_FTR_NO_BTIC 0x00040000 -#define CPU_FTR_BIG_PHYS 0x00080000 - -#ifdef __ASSEMBLY__ - -#define BEGIN_FTR_SECTION 98: - -#define END_FTR_SECTION(msk, val) \ -99: \ - .section __ftr_fixup,"a"; \ - .align 2; \ - .long msk; \ - .long val; \ - .long 98b; \ - .long 99b; \ - .previous - -#else - -#define BEGIN_FTR_SECTION "98:\n" -#define END_FTR_SECTION(msk, val) \ -"99:\n" \ -" .section __ftr_fixup,\"a\";\n" \ -" .align 2;\n" \ -" .long "#msk";\n" \ -" .long "#val";\n" \ -" .long 98b;\n" \ -" .long 99b;\n" \ -" .previous\n" - - -#endif /* __ASSEMBLY__ */ - -#define END_FTR_SECTION_IFSET(msk) END_FTR_SECTION((msk), (msk)) -#define END_FTR_SECTION_IFCLR(msk) END_FTR_SECTION((msk), 0) - -#endif /* __ASM_PPC_CPUTABLE_H */ -#endif /* __KERNEL__ */ - From holindho at cs.helsinki.fi Fri Sep 9 15:54:21 2005 From: holindho at cs.helsinki.fi (Heikki Lindholm) Date: Fri, 09 Sep 2005 08:54:21 +0300 Subject: can we kill CONFIG_PPC64BRIDGE? In-Reply-To: <5AB80D6D-C8B0-4F08-9C06-A56119D5D696@freescale.com> References: <5AB80D6D-C8B0-4F08-9C06-A56119D5D696@freescale.com> Message-ID: <4321238D.5030309@cs.helsinki.fi> Kumar Gala kirjoitti: > Paul, > > Can we kill CONFIG_PPC64BRIDGE for ppc32... Not sure if anyone is using > this or not? It has been useful when porting stuff over to ppc64. Though, if nobody will maintain it... -- Heikki Lindholm From anton at samba.org Fri Sep 9 16:47:24 2005 From: anton at samba.org (Anton Blanchard) Date: Fri, 9 Sep 2005 16:47:24 +1000 Subject: [PATCH] Add PTRACE_{GET|SET}VRREGS In-Reply-To: <666AD09B-F17D-4AFA-9D53-5E3C1F5A04B4@freescale.com> References: <20050908190401.GB3416@austin.ibm.com> <666AD09B-F17D-4AFA-9D53-5E3C1F5A04B4@freescale.com> Message-ID: <20050909064724.GY6945@krispykreme> Hi Kumar, > I repeat my request that we make vrsave an unsigned int instead of an > unsigned long in thread_struct since we are touch this code anyways. Apparently the 3 word pad is there for a reason in the 64bit ABI, Steve Munroe would know the details. Anton From paulus at samba.org Fri Sep 9 23:06:56 2005 From: paulus at samba.org (Paul Mackerras) Date: Fri, 9 Sep 2005 23:06:56 +1000 Subject: Please pull ppc64-2.6.git Message-ID: <17185.35056.176419.427883@cargo.ozlabs.ibm.com> Linus, There are some more ppc64 updates in my tree, ready for you to pull, at: rsync://rsync.kernel.org/pub/scm/linux/kernel/git/paulus/ppc64-2.6.git Thanks, Paul. arch/ppc/kernel/syscalls.c | 4 -- arch/ppc64/Makefile | 21 ++++++---- arch/ppc64/boot/Makefile | 53 ++++++++++++++++---------- arch/ppc64/boot/main.c | 31 +++++++++++++-- arch/ppc64/kernel/bpa_iic.c | 28 ++++++++++---- arch/ppc64/kernel/eeh.c | 55 ++++++++++++++++----------- arch/ppc64/kernel/iomap.c | 20 ++++++++++ arch/ppc64/kernel/iommu.c | 3 + arch/ppc64/kernel/maple_pci.c | 4 +- arch/ppc64/kernel/misc.S | 6 +-- arch/ppc64/kernel/pSeries_iommu.c | 72 ++++++++++++++++++++--------------- arch/ppc64/kernel/pci.c | 66 +++++++++++++++++++++++++++++++- arch/ppc64/kernel/pci.h | 1 arch/ppc64/kernel/pci_dn.c | 45 ++++++++++++++++------ arch/ppc64/kernel/pci_iommu.c | 2 - arch/ppc64/kernel/pmac_feature.c | 8 ++-- arch/ppc64/kernel/pmac_pci.c | 6 +-- arch/ppc64/kernel/prom.c | 1 arch/ppc64/kernel/rtas_pci.c | 39 +++++++++++-------- arch/ppc64/kernel/sys_ppc32.c | 55 --------------------------- arch/ppc64/kernel/syscalls.c | 4 -- arch/ppc64/kernel/u3_iommu.c | 4 +- arch/ppc64/kernel/udbg.c | 6 +++ arch/ppc64/mm/init.c | 4 +- drivers/pci/hotplug/rpadlpar_core.c | 20 ++++++---- drivers/pci/hotplug/rpaphp_pci.c | 8 ++-- drivers/video/offb.c | 2 - include/asm-powerpc/8253pit.h | 8 ++-- include/asm-powerpc/agp.h | 8 +--- include/asm-powerpc/bugs.h | 8 ++-- include/asm-powerpc/errno.h | 6 +-- include/asm-powerpc/ioctl.h | 6 +-- include/asm-powerpc/ioctls.h | 6 +-- include/asm-powerpc/linkage.h | 6 +-- include/asm-powerpc/mc146818rtc.h | 6 +-- include/asm-powerpc/mman.h | 6 +-- include/asm-powerpc/module.h | 6 +-- include/asm-powerpc/msgbuf.h | 33 ++++++++++++++++ include/asm-powerpc/namei.h | 14 +++---- include/asm-powerpc/param.h | 8 ++-- include/asm-powerpc/poll.h | 6 +-- include/asm-powerpc/sembuf.h | 6 +-- include/asm-powerpc/setup.h | 9 ++++ include/asm-powerpc/shmbuf.h | 14 +++---- include/asm-powerpc/shmparam.h | 6 +-- include/asm-powerpc/siginfo.h | 6 +-- include/asm-powerpc/socket.h | 6 +-- include/asm-powerpc/sockios.h | 6 +-- include/asm-powerpc/string.h | 6 +-- include/asm-powerpc/termbits.h | 6 +-- include/asm-powerpc/termios.h | 6 +-- include/asm-powerpc/timex.h | 49 ++++++++++++++++++++++++ include/asm-powerpc/topology.h | 9 ++-- include/asm-powerpc/unaligned.h | 9 ++-- include/asm-powerpc/user.h | 15 ++++--- include/asm-ppc/msgbuf.h | 25 ------------ include/asm-ppc/setup.h | 14 ------- include/asm-ppc/timex.h | 40 ------------------- include/asm-ppc/topology.h | 6 --- include/asm-ppc64/msgbuf.h | 27 ------------- include/asm-ppc64/param.h | 31 --------------- include/asm-ppc64/pci-bridge.h | 45 +++++++++++++++++++--- include/asm-ppc64/prom.h | 19 --------- include/asm-ppc64/segment.h | 6 --- include/asm-ppc64/setup.h | 6 --- include/asm-ppc64/timex.h | 26 ------------- include/asm-ppc64/user.h | 58 ---------------------------- 67 files changed, 576 insertions(+), 575 deletions(-) create mode 100644 include/asm-powerpc/msgbuf.h rename include/{asm-ppc/param.h => asm-powerpc/param.h} (81%) create mode 100644 include/asm-powerpc/setup.h create mode 100644 include/asm-powerpc/timex.h rename include/{asm-ppc64/topology.h => asm-powerpc/topology.h} (86%) rename include/{asm-ppc/user.h => asm-powerpc/user.h} (87%) delete mode 100644 include/asm-ppc/msgbuf.h delete mode 100644 include/asm-ppc/setup.h delete mode 100644 include/asm-ppc/timex.h delete mode 100644 include/asm-ppc/topology.h delete mode 100644 include/asm-ppc64/msgbuf.h delete mode 100644 include/asm-ppc64/param.h delete mode 100644 include/asm-ppc64/segment.h delete mode 100644 include/asm-ppc64/setup.h delete mode 100644 include/asm-ppc64/timex.h delete mode 100644 include/asm-ppc64/user.h commit b2ad7b5e8115582cdf5bbda065aa516c24d62c21 Author: Paul Mackerras Date: Fri Sep 9 23:02:36 2005 +1000 Allow PCI config space syscalls to be used by 64-bit processes. The pciconfig_iobase, pciconfig_read and pciconfig_write system calls were only implemented for 32-bit processes; for 64-bit processes they returned an ENOSYS error. This allows them to be used by 64-bit processes as well. The X server uses pciconfig_iobase at least, and this change is necessary to allow a 64-bit X server to work on my G5. Signed-off-by: Paul Mackerras commit 766375362a1dcac63dc0c0fb61ce4143c8de63d9 Author: Arthur Othieno Date: Sat Aug 20 21:48:47 2005 -0400 [PATCH] ppc64: Big-endian I/O memory accessors. I/O memory accessors. Big-endian version. For those busses/devices that do export big-endian I/O memory. Of notable relevance/reference: http://lwn.net/Articles/132804/ http://ozlabs.org/pipermail/linuxppc-embedded/2005-August/019798.html http://ozlabs.org/pipermail/linuxppc-embedded/2005-August/019752.html Signed-Off-By: Arthur Othieno Signed-off-by: Paul Mackerras commit 1635317facea3094ddf34082cd86797efb1d9f7e Author: Paul Mackerras Date: Tue Sep 6 13:17:54 2005 +1000 [PATCH] Separate pci bits out of struct device_node 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 commit b28d2582ce8aafe531d909bb9c4dcf29189e786e Author: Kumar Gala Date: Wed Aug 24 11:56:56 2005 -0500 [PATCH] ppc64: remove use of asm/segment.h Remove asm-ppc64/segment.h now that all users are gone. Signed-off-by: Kumar Gala Signed-off-by: Paul Mackerras commit 3cc747e96480d4e26560e5bc59f2b9c9204ade0e Author: Mark Bellon Date: Tue Sep 6 15:50:02 2005 -0700 [PATCH] PPC64: large INITRD causes kernel not to boot In PPC64 there are number of problems in arch/ppc64/boot/main.c that prevent a kernel from making use of a large (greater than ~16MB) INITRD. This is 64 bit architecture and really large INITRD images should be possible. Simply put the existing code has a fixed reservation (claim) address and once the kernel plus initrd image are large enough to pass this address all sorts of bad things occur. The fix is the dynamically establish the first claim address above the loaded kernel plus initrd (plus some "padding" and rounding). If PROG_START is defined this will be used as the minimum safe address - currently known to be 0x01400000 for the firmwares tested so far. Signed-off-by: Mark Bellon Signed-off-by: Paul Mackerras commit f9526785d8a03fd0e21f9cfc951adc03bde1c395 Author: jdl at freescale.com Date: Thu Sep 8 14:05:49 2005 -0500 [PATCH] powerpc: Fix __power64__ typos that should be __powerpc64__ Fix __power64__ typo that should be __powerpc64__ instead. Signed-off-by: Jon Loeliger Signed-off-by: Kumar Gala Signed-off-by: Paul Mackerras commit e4df7671716f1fffb3437a7c1a14e3d2465fefef Author: Geoff Levand Date: Wed Aug 10 17:57:42 2005 -0700 [PATCH] ppc64: makefile cleanup This patch cleans up the output generated by ppc64 builds. Signed-off-by: Geoff Levand Signed-off-by: Paul Mackerras commit a24c8481b6439cb151a4750cc278ea2df4fb0e53 Author: Geoff Levand Date: Mon Aug 15 13:59:13 2005 -0700 [PATCH] ppc64: zimage build fix Signed-off-by: Geoff Levand Signed-off-by: Paul Mackerras commit dd56fdf23dfa0127d512b73d4238dbd2b5a7c1eb Author: jdl at freescale.com Date: Wed Sep 7 15:59:48 2005 -0500 [PATCH] powerpc: Merge a few more include files Merge a few asm-ppc and asm-ppc64 header files. Note: the merge of setup.h intentionally does not carry forward the m68k cruft. That means this patch continues to break the already broken amiga on the ppc32. Signed-off-by: Jon Loeliger Signed-off-by: Kumar Gala Signed-off-by: Paul Mackerras commit 64807081e38703617cf9a5d71db14ea2b3e1cb04 Author: jdl at freescale.com Date: Wed Sep 7 15:56:20 2005 -0500 [PATCH] powerpc: Make check_bugs() static inline Make check_bugs() static inline and remove it from syscalls.c. Signed-off-by: Jon Loeliger Signed-off-by: Kumar Gala Signed-off-by: Paul Mackerras commit a37c8875a764b4decf941859f4a2c63e1e86c8fa Author: jdl at freescale.com Date: Wed Sep 7 15:27:09 2005 -0500 [PATCH] powerpc: Standardize on _ASM_POWERPC header symbol prefix Standardize on _ASM_POWERPC_... prefix for all #include exclusion symbols. Fixup all the non-compilers. Signed-off-by: Jon Loeliger Signed-off-by: Kumar Gala Signed-off-by: Paul Mackerras commit 38c0ff06d5ba05b6fbf18652c49747ad320aaeb0 Author: Stephen Rothwell Date: Wed Sep 7 19:52:38 2005 +1000 [PATCH] ppc64: iSeries early printk breakage The earlier commit 8d9273918635f0301368c01b56c03a6f339e8d51 (Consolidate early console and PPCDBG code) broke iSeries because it caused unregister_console(&udbg_console) to be called unconditionally. iSeries never registers the udbg_console. This just reverts part of the change. Signed-off-by: Stephen Rothwell Signed-off-by: Paul Mackerras commit 34b5233f379847097a1925a02b62f129c407c1e4 Author: Michael Ellerman Date: Tue Sep 6 21:00:02 2005 +1000 [PATCH] ppc64: Fix oops for !CONFIG_NUMA The SPARSEMEM EXTREME code (802f192e4a600f7ef84ca25c8b818c8830acef5a) that went in yesterday broke PPC64 for !CONFIG_NUMA. The problem is that (free|reserve)_bootmem don't take a page number as their first argument, they take an address. Ruh roh. Booted on P5 LPAR, iSeries and G5. Signed-off-by: Michael Ellerman Signed-off-by: Paul Mackerras commit a84195f36e373001e6eed2e95a5dc1994cf30480 Author: Arnd Bergmann Date: Thu Aug 18 19:35:21 2005 +0200 [PATCH] ppc64: fix IPI on bpa_iic This fixes a severe bug in the bpa_iic driver that caused all sorts of problems. We had been using incorrect priority values for inter processor interrupts, which resulted in always doing CALL_FUNCTION instead of RESCHEDULE or DEBUGGER_BREAK. The symptoms cured by this patch include bad performance on SMP systems spurious kernel panics in the IPI code. Signed-off-by: Arnd Bergmann Signed-off-by: Paul Mackerras From msdemlei at cl.uni-heidelberg.de Fri Sep 9 21:43:11 2005 From: msdemlei at cl.uni-heidelberg.de (Markus Demleitner) Date: Fri, 9 Sep 2005 13:43:11 +0200 Subject: iMac G5 frequency switching Message-ID: <20050909114311.GA3732@victor.rh.local> Hi, I've figured out how to switch frequencies of the iMac G5 CPU (at least for my 1600 MHz models) and at that opportunity found that OF puts the machine into half speed on boot, and that's what Linux got, then. This is bad news for the solution of the riddle how Apple keeps the fans that quiet while I need to run them, since clearly it's not because they run the machine at half speed most of the time. Running the machine at full speed under Linux has the fans roaring even on an idle machine, at least when you've got about 30 degrees outside temperature. OS X keeps the thing quiet, even though not drawing considerably less power. I've written the cpufreq driver as an external module for now, since there's no "platforms" subdir in arch/ppc64 yet (which is where the pmac_cpufreq driver resides in ppc). Here's the code: http://tucana.cl.uni-heidelberg.de/imacg5/g5-cpufreq-0.01.tar.gz I don't do any voltage stuff myself, mainly because OF doesn't either. If anyone knows if I should, please let me know. Apart from the functions that actually do the switch this is completely untested, because compiling cpufreq itself into the kernel (I've simply hacked arch/ppc64/Kconfig to source the Kconfig) yields a kernel that locks up. I figure I could spend weeks trying to find out why, so here's my plea to the ppc64 gods: Could anyone have a look at why cpufreq without any cpu drivers loaded would lock the machine at boot time? Two somewhat related notes: (a) I've set up a page with hints on running linux on the iMac G5. If this is a duplicate effort, let me know and I'll pull the page. (b) On that page, I link to benh's first SMU patch as the one to apply (from http://ozlabs.org/pipermail/linuxppc64-dev/2005-April/003835.html). In the meantime, benh has put out a newer SMU patch -- however, that one won't compile with vanilla 2.6.13 (it's lacking struct of_match, OF_ANY_MATCH and some others, and I gave up on it after fiddling for a while), whereas the one I used does. That's an excuse to benh for having ignored the second patch. And then a last question: The nap/doze stuff the G5 can do sounds nifty and might be part of the explanation for the thermal trouble. It's G5 generic and thus I'm wondering if anyone has given putting it into Linux any thought already. Thanks all, Markus From kumar.gala at freescale.com Sat Sep 10 00:09:59 2005 From: kumar.gala at freescale.com (Kumar Gala) Date: Fri, 9 Sep 2005 09:09:59 -0500 Subject: [PATCH] Add PTRACE_{GET|SET}VRREGS In-Reply-To: <20050909064724.GY6945@krispykreme> References: <20050909064724.GY6945@krispykreme> Message-ID: <05C56EBB-4F23-48F2-8094-B6543753267A@freescale.com> Steve, Can you provide any insight into Anton's comment. What I would like to see is on ppc64: struct thread_struct { ... #ifdef CONFIG_ALTIVEC /* Complete AltiVec register set */ vector128 vr[32] __attribute((aligned(16))); /* AltiVec status */ vector128 vscr __attribute((aligned(16))); unsigned long vrsave; int used_vr; /* set if process has used altivec */ #endif /* CONFIG_ALTIVEC */ }; turn into: struct thread_struct { ... #ifdef CONFIG_ALTIVEC /* Complete AltiVec register set */ vector128 vr[32] __attribute((aligned(16))); /* AltiVec status */ vector128 vscr __attribute((aligned(16))); unsigned int vrsave; int used_vr; /* set if process has used altivec */ #endif /* CONFIG_ALTIVEC */ }; (Change of unsigned long to unsigned int for vrsave). This is because vrsave is truly only 32-bits in all implementations. Is there some reason this breaks the ppc64 ABI? - kumar On Sep 9, 2005, at 1:47 AM, Anton Blanchard wrote: > > Hi Kumar, > > >> I repeat my request that we make vrsave an unsigned int instead of an >> unsigned long in thread_struct since we are touch this code anyways. >> > > Apparently the 3 word pad is there for a reason in the 64bit ABI, > Steve > Munroe would know the details. > > Anton > From viro at ZenIV.linux.org.uk Sat Sep 10 01:50:43 2005 From: viro at ZenIV.linux.org.uk (viro at ZenIV.linux.org.uk) Date: Fri, 9 Sep 2005 16:50:43 +0100 Subject: [PATCH] basic iomem annotations (ppc64) Message-ID: <20050909155043.GE9623@ZenIV.linux.org.uk> Signed-off-by: Al Viro ---- diff -urN RC13-git8-base/arch/ppc64/kernel/iomap.c current/arch/ppc64/kernel/iomap.c --- RC13-git8-base/arch/ppc64/kernel/iomap.c 2005-06-17 15:48:29.000000000 -0400 +++ current/arch/ppc64/kernel/iomap.c 2005-09-08 23:53:33.000000000 -0400 @@ -56,15 +56,15 @@ */ void ioread8_rep(void __iomem *addr, void *dst, unsigned long count) { - _insb((u8 __force *) addr, dst, count); + _insb((u8 __iomem *) addr, dst, count); } void ioread16_rep(void __iomem *addr, void *dst, unsigned long count) { - _insw_ns((u16 __force *) addr, dst, count); + _insw_ns((u16 __iomem *) addr, dst, count); } void ioread32_rep(void __iomem *addr, void *dst, unsigned long count) { - _insl_ns((u32 __force *) addr, dst, count); + _insl_ns((u32 __iomem *) addr, dst, count); } EXPORT_SYMBOL(ioread8_rep); EXPORT_SYMBOL(ioread16_rep); @@ -72,15 +72,15 @@ void iowrite8_rep(void __iomem *addr, const void *src, unsigned long count) { - _outsb((u8 __force *) addr, src, count); + _outsb((u8 __iomem *) addr, src, count); } void iowrite16_rep(void __iomem *addr, const void *src, unsigned long count) { - _outsw_ns((u16 __force *) addr, src, count); + _outsw_ns((u16 __iomem *) addr, src, count); } void iowrite32_rep(void __iomem *addr, const void *src, unsigned long count) { - _outsl_ns((u32 __force *) addr, src, count); + _outsl_ns((u32 __iomem *) addr, src, count); } EXPORT_SYMBOL(iowrite8_rep); EXPORT_SYMBOL(iowrite16_rep); diff -urN RC13-git8-base/include/asm-ppc64/eeh.h current/include/asm-ppc64/eeh.h --- RC13-git8-base/include/asm-ppc64/eeh.h 2005-06-17 15:48:29.000000000 -0400 +++ current/include/asm-ppc64/eeh.h 2005-09-08 23:55:47.000000000 -0400 @@ -219,23 +219,24 @@ static inline void eeh_memset_io(volatile void __iomem *addr, int c, unsigned long n) { + void *p = (void __force *)addr; u32 lc = c; lc |= lc << 8; lc |= lc << 16; - while(n && !EEH_CHECK_ALIGN(addr, 4)) { - *((volatile u8 *)addr) = c; - addr = (void *)((unsigned long)addr + 1); + while(n && !EEH_CHECK_ALIGN(p, 4)) { + *((volatile u8 *)p) = c; + p++; n--; } while(n >= 4) { - *((volatile u32 *)addr) = lc; - addr = (void *)((unsigned long)addr + 4); + *((volatile u32 *)p) = lc; + p += 4; n -= 4; } while(n) { - *((volatile u8 *)addr) = c; - addr = (void *)((unsigned long)addr + 1); + *((volatile u8 *)p) = c; + p++; n--; } __asm__ __volatile__ ("sync" : : : "memory"); @@ -250,22 +251,22 @@ while(n && (!EEH_CHECK_ALIGN(vsrc, 4) || !EEH_CHECK_ALIGN(dest, 4))) { *((u8 *)dest) = *((volatile u8 *)vsrc); __asm__ __volatile__ ("eieio" : : : "memory"); - vsrc = (void *)((unsigned long)vsrc + 1); - dest = (void *)((unsigned long)dest + 1); + vsrc++; + dest++; n--; } while(n > 4) { *((u32 *)dest) = *((volatile u32 *)vsrc); __asm__ __volatile__ ("eieio" : : : "memory"); - vsrc = (void *)((unsigned long)vsrc + 4); - dest = (void *)((unsigned long)dest + 4); + vsrc += 4; + dest += 4; n -= 4; } while(n) { *((u8 *)dest) = *((volatile u8 *)vsrc); __asm__ __volatile__ ("eieio" : : : "memory"); - vsrc = (void *)((unsigned long)vsrc + 1); - dest = (void *)((unsigned long)dest + 1); + vsrc++; + dest++; n--; } __asm__ __volatile__ ("sync" : : : "memory"); @@ -286,20 +287,20 @@ while(n && (!EEH_CHECK_ALIGN(vdest, 4) || !EEH_CHECK_ALIGN(src, 4))) { *((volatile u8 *)vdest) = *((u8 *)src); - src = (void *)((unsigned long)src + 1); - vdest = (void *)((unsigned long)vdest + 1); + src++; + vdest++; n--; } while(n > 4) { *((volatile u32 *)vdest) = *((volatile u32 *)src); - src = (void *)((unsigned long)src + 4); - vdest = (void *)((unsigned long)vdest + 4); + src += 4; + vdest += 4; n-=4; } while(n) { *((volatile u8 *)vdest) = *((u8 *)src); - src = (void *)((unsigned long)src + 1); - vdest = (void *)((unsigned long)vdest + 1); + src++; + vdest++; n--; } __asm__ __volatile__ ("sync" : : : "memory"); diff -urN RC13-git8-base/include/asm-ppc64/io.h current/include/asm-ppc64/io.h --- RC13-git8-base/include/asm-ppc64/io.h 2005-06-17 15:48:29.000000000 -0400 +++ current/include/asm-ppc64/io.h 2005-09-08 23:54:20.000000000 -0400 @@ -20,10 +20,10 @@ #include -#define __ide_mm_insw(p, a, c) _insw_ns((volatile u16 *)(p), (a), (c)) -#define __ide_mm_insl(p, a, c) _insl_ns((volatile u32 *)(p), (a), (c)) -#define __ide_mm_outsw(p, a, c) _outsw_ns((volatile u16 *)(p), (a), (c)) -#define __ide_mm_outsl(p, a, c) _outsl_ns((volatile u32 *)(p), (a), (c)) +#define __ide_mm_insw(p, a, c) _insw_ns((volatile u16 __iomem *)(p), (a), (c)) +#define __ide_mm_insl(p, a, c) _insl_ns((volatile u32 __iomem *)(p), (a), (c)) +#define __ide_mm_outsw(p, a, c) _outsw_ns((volatile u16 __iomem *)(p), (a), (c)) +#define __ide_mm_outsl(p, a, c) _outsl_ns((volatile u32 __iomem *)(p), (a), (c)) #define SIO_CONFIG_RA 0x398 @@ -71,8 +71,8 @@ * Neither do the standard versions now, these are just here * for older code. */ -#define insw_ns(port, buf, ns) _insw_ns((u16 *)((port)+pci_io_base), (buf), (ns)) -#define insl_ns(port, buf, nl) _insl_ns((u32 *)((port)+pci_io_base), (buf), (nl)) +#define insw_ns(port, buf, ns) _insw_ns((u16 __iomem *)((port)+pci_io_base), (buf), (ns)) +#define insl_ns(port, buf, nl) _insl_ns((u32 __iomem *)((port)+pci_io_base), (buf), (nl)) #else static inline unsigned char __raw_readb(const volatile void __iomem *addr) @@ -136,9 +136,9 @@ #define insw_ns(port, buf, ns) eeh_insw_ns((port), (buf), (ns)) #define insl_ns(port, buf, nl) eeh_insl_ns((port), (buf), (nl)) -#define outsb(port, buf, ns) _outsb((u8 *)((port)+pci_io_base), (buf), (ns)) -#define outsw(port, buf, ns) _outsw_ns((u16 *)((port)+pci_io_base), (buf), (ns)) -#define outsl(port, buf, nl) _outsl_ns((u32 *)((port)+pci_io_base), (buf), (nl)) +#define outsb(port, buf, ns) _outsb((u8 __iomem *)((port)+pci_io_base), (buf), (ns)) +#define outsw(port, buf, ns) _outsw_ns((u16 __iomem *)((port)+pci_io_base), (buf), (ns)) +#define outsl(port, buf, nl) _outsl_ns((u32 __iomem *)((port)+pci_io_base), (buf), (nl)) #endif @@ -147,16 +147,16 @@ #define readl_relaxed(addr) readl(addr) #define readq_relaxed(addr) readq(addr) -extern void _insb(volatile u8 *port, void *buf, int ns); -extern void _outsb(volatile u8 *port, const void *buf, int ns); -extern void _insw(volatile u16 *port, void *buf, int ns); -extern void _outsw(volatile u16 *port, const void *buf, int ns); -extern void _insl(volatile u32 *port, void *buf, int nl); -extern void _outsl(volatile u32 *port, const void *buf, int nl); -extern void _insw_ns(volatile u16 *port, void *buf, int ns); -extern void _outsw_ns(volatile u16 *port, const void *buf, int ns); -extern void _insl_ns(volatile u32 *port, void *buf, int nl); -extern void _outsl_ns(volatile u32 *port, const void *buf, int nl); +extern void _insb(volatile u8 __iomem *port, void *buf, int ns); +extern void _outsb(volatile u8 __iomem *port, const void *buf, int ns); +extern void _insw(volatile u16 __iomem *port, void *buf, int ns); +extern void _outsw(volatile u16 __iomem *port, const void *buf, int ns); +extern void _insl(volatile u32 __iomem *port, void *buf, int nl); +extern void _outsl(volatile u32 __iomem *port, const void *buf, int nl); +extern void _insw_ns(volatile u16 __iomem *port, void *buf, int ns); +extern void _outsw_ns(volatile u16 __iomem *port, const void *buf, int ns); +extern void _insl_ns(volatile u32 __iomem *port, void *buf, int nl); +extern void _outsl_ns(volatile u32 __iomem *port, const void *buf, int nl); #define mmiowb() @@ -176,8 +176,8 @@ * Neither do the standard versions now, these are just here * for older code. */ -#define outsw_ns(port, buf, ns) _outsw_ns((u16 *)((port)+pci_io_base), (buf), (ns)) -#define outsl_ns(port, buf, nl) _outsl_ns((u32 *)((port)+pci_io_base), (buf), (nl)) +#define outsw_ns(port, buf, ns) _outsw_ns((u16 __iomem *)((port)+pci_io_base), (buf), (ns)) +#define outsl_ns(port, buf, nl) _outsl_ns((u32 __iomem *)((port)+pci_io_base), (buf), (nl)) #define IO_SPACE_LIMIT ~(0UL) From bgill at freescale.com Sat Sep 10 04:52:59 2005 From: bgill at freescale.com (Becky Bruce) Date: Fri, 9 Sep 2005 13:52:59 -0500 (CDT) Subject: [PATCH] ppc/ppc64: Merge bug.h into include/asm-powerpc Message-ID: This patch merges bug.h into include/asm-powerpc. Changed the data structure for bug_entry such that line is always an int on both 32 and 64-bit platforms; removed casts to int from the 64-bit trap code to reflect this. Signed-off-by: Kumar Gala Signed-off-by: Becky Bruce --- commit fcaf8560dc918048b43867d79efa5b26bd6a9a81 tree 079802fdb229c0e3721b893235e2ef912e30d7cd parent dfe2ac4994952cadc891f095668f9e582d4402b3 author Becky Bruce Fri, 09 Sep 2005 11:15:22 -0500 committer Becky Bruce Fri, 09 Sep 2005 11:15:22 -0500 arch/ppc/kernel/traps.c | 2 + arch/ppc64/kernel/traps.c | 4 +- include/asm-powerpc/bug.h | 81 +++++++++++++++++++++++++++++++++++++++++++++ include/asm-ppc/bug.h | 58 -------------------------------- include/asm-ppc64/bug.h | 69 -------------------------------------- 5 files changed, 84 insertions(+), 130 deletions(-) diff --git a/arch/ppc/kernel/traps.c b/arch/ppc/kernel/traps.c --- a/arch/ppc/kernel/traps.c +++ b/arch/ppc/kernel/traps.c @@ -553,7 +553,7 @@ extern struct bug_entry __start___bug_ta #define module_find_bug(x) NULL #endif -static struct bug_entry *find_bug(unsigned long bugaddr) +struct bug_entry *find_bug(unsigned long bugaddr) { struct bug_entry *bug; diff --git a/arch/ppc64/kernel/traps.c b/arch/ppc64/kernel/traps.c --- a/arch/ppc64/kernel/traps.c +++ b/arch/ppc64/kernel/traps.c @@ -389,12 +389,12 @@ check_bug_trap(struct pt_regs *regs) /* this is a WARN_ON rather than BUG/BUG_ON */ printk(KERN_ERR "Badness in %s at %s:%d\n", bug->function, bug->file, - (unsigned int)bug->line & ~BUG_WARNING_TRAP); + bug->line & ~BUG_WARNING_TRAP); show_stack(current, (void *)regs->gpr[1]); return 1; } printk(KERN_CRIT "kernel BUG in %s at %s:%d!\n", - bug->function, bug->file, (unsigned int)bug->line); + bug->function, bug->file, bug->line); return 0; } diff --git a/include/asm-powerpc/bug.h b/include/asm-powerpc/bug.h new file mode 100644 --- /dev/null +++ b/include/asm-powerpc/bug.h @@ -0,0 +1,81 @@ +#ifndef _ASM_POWERPC_BUG_H +#define _ASM_POWERPC_BUG_H + +/* + * Define an illegal instr to trap on the bug. + * We don't use 0 because that marks the end of a function + * in the ELF ABI. That's "Boo Boo" in case you wonder... + */ +#define BUG_OPCODE .long 0x00b00b00 /* For asm */ +#define BUG_ILLEGAL_INSTR "0x00b00b00" /* For BUG macro */ + +#ifndef __ASSEMBLY__ + +#ifdef __powerpc64__ +#define BUG_TABLE_ENTRY(label, line, file, func) \ + ".llong " #label "\n .long " #line "\n .llong " #file ", " #func "\n" +#define TRAP_OP(ra, rb) "1: tdnei " #ra ", " #rb "\n" +#define DATA_TYPE long long +#else +#define BUG_TABLE_ENTRY(label, line, file, func) \ + ".long " #label ", " #line ", " #file ", " #func "\n" +#define TRAP_OP(ra, rb) "1: twnei " #ra ", " #rb "\n" +#define DATA_TYPE int +#endif /* __powerpc64__ */ + +struct bug_entry { + unsigned long bug_addr; + int line; + const char *file; + const char *function; +}; + +struct bug_entry *find_bug(unsigned long bugaddr); + +/* + * If this bit is set in the line number it means that the trap + * is for WARN_ON rather than BUG or BUG_ON. + */ +#define BUG_WARNING_TRAP 0x1000000 + +#ifdef CONFIG_BUG + +#define BUG() do { \ + __asm__ __volatile__( \ + "1: twi 31,0,0\n" \ + ".section __bug_table,\"a\"\n\t" \ + BUG_TABLE_ENTRY(1b,%0,%1,%2) \ + ".previous" \ + : : "i" (__LINE__), "i" (__FILE__), "i" (__FUNCTION__)); \ +} while (0) + +#define BUG_ON(x) do { \ + __asm__ __volatile__( \ + TRAP_OP(%0,0) \ + ".section __bug_table,\"a\"\n\t" \ + BUG_TABLE_ENTRY(1b,%1,%2,%3) \ + ".previous" \ + : : "r" ((DATA_TYPE)(x)), "i" (__LINE__), \ + "i" (__FILE__), "i" (__FUNCTION__)); \ +} while (0) + +#define WARN_ON(x) do { \ + __asm__ __volatile__( \ + TRAP_OP(%0,0) \ + ".section __bug_table,\"a\"\n\t" \ + BUG_TABLE_ENTRY(1b,%1,%2,%3) \ + ".previous" \ + : : "r" ((DATA_TYPE)(x)), \ + "i" (__LINE__ + BUG_WARNING_TRAP), \ + "i" (__FILE__), "i" (__FUNCTION__)); \ +} while (0) + +#define HAVE_ARCH_BUG +#define HAVE_ARCH_BUG_ON +#define HAVE_ARCH_WARN_ON +#endif /* CONFIG_BUG */ +#endif /* __ASSEMBLY __ */ + +#include + +#endif /* _ASM_POWERPC_BUG_H */ diff --git a/include/asm-ppc/bug.h b/include/asm-ppc/bug.h deleted file mode 100644 --- a/include/asm-ppc/bug.h +++ /dev/null @@ -1,58 +0,0 @@ -#ifndef _PPC_BUG_H -#define _PPC_BUG_H - -struct bug_entry { - unsigned long bug_addr; - int line; - const char *file; - const char *function; -}; - -/* - * If this bit is set in the line number it means that the trap - * is for WARN_ON rather than BUG or BUG_ON. - */ -#define BUG_WARNING_TRAP 0x1000000 - -#ifdef CONFIG_BUG -#define BUG() do { \ - __asm__ __volatile__( \ - "1: twi 31,0,0\n" \ - ".section __bug_table,\"a\"\n\t" \ - " .long 1b,%0,%1,%2\n" \ - ".previous" \ - : : "i" (__LINE__), "i" (__FILE__), "i" (__FUNCTION__)); \ -} while (0) - -#define BUG_ON(x) do { \ - if (!__builtin_constant_p(x) || (x)) { \ - __asm__ __volatile__( \ - "1: twnei %0,0\n" \ - ".section __bug_table,\"a\"\n\t" \ - " .long 1b,%1,%2,%3\n" \ - ".previous" \ - : : "r" (x), "i" (__LINE__), "i" (__FILE__), \ - "i" (__FUNCTION__)); \ - } \ -} while (0) - -#define WARN_ON(x) do { \ - if (!__builtin_constant_p(x) || (x)) { \ - __asm__ __volatile__( \ - "1: twnei %0,0\n" \ - ".section __bug_table,\"a\"\n\t" \ - " .long 1b,%1,%2,%3\n" \ - ".previous" \ - : : "r" (x), "i" (__LINE__ + BUG_WARNING_TRAP), \ - "i" (__FILE__), "i" (__FUNCTION__)); \ - } \ -} while (0) - -#define HAVE_ARCH_BUG -#define HAVE_ARCH_BUG_ON -#define HAVE_ARCH_WARN_ON -#endif - -#include - -#endif diff --git a/include/asm-ppc64/bug.h b/include/asm-ppc64/bug.h deleted file mode 100644 --- a/include/asm-ppc64/bug.h +++ /dev/null @@ -1,69 +0,0 @@ -#ifndef _PPC64_BUG_H -#define _PPC64_BUG_H - -/* - * Define an illegal instr to trap on the bug. - * We don't use 0 because that marks the end of a function - * in the ELF ABI. That's "Boo Boo" in case you wonder... - */ -#define BUG_OPCODE .long 0x00b00b00 /* For asm */ -#define BUG_ILLEGAL_INSTR "0x00b00b00" /* For BUG macro */ - -#ifndef __ASSEMBLY__ - -struct bug_entry { - unsigned long bug_addr; - long line; - const char *file; - const char *function; -}; - -struct bug_entry *find_bug(unsigned long bugaddr); - -/* - * If this bit is set in the line number it means that the trap - * is for WARN_ON rather than BUG or BUG_ON. - */ -#define BUG_WARNING_TRAP 0x1000000 - -#ifdef CONFIG_BUG - -#define BUG() do { \ - __asm__ __volatile__( \ - "1: twi 31,0,0\n" \ - ".section __bug_table,\"a\"\n\t" \ - " .llong 1b,%0,%1,%2\n" \ - ".previous" \ - : : "i" (__LINE__), "i" (__FILE__), "i" (__FUNCTION__)); \ -} while (0) - -#define BUG_ON(x) do { \ - __asm__ __volatile__( \ - "1: tdnei %0,0\n" \ - ".section __bug_table,\"a\"\n\t" \ - " .llong 1b,%1,%2,%3\n" \ - ".previous" \ - : : "r" ((long long)(x)), "i" (__LINE__), \ - "i" (__FILE__), "i" (__FUNCTION__)); \ -} while (0) - -#define WARN_ON(x) do { \ - __asm__ __volatile__( \ - "1: tdnei %0,0\n" \ - ".section __bug_table,\"a\"\n\t" \ - " .llong 1b,%1,%2,%3\n" \ - ".previous" \ - : : "r" ((long long)(x)), \ - "i" (__LINE__ + BUG_WARNING_TRAP), \ - "i" (__FILE__), "i" (__FUNCTION__)); \ -} while (0) - -#define HAVE_ARCH_BUG -#define HAVE_ARCH_BUG_ON -#define HAVE_ARCH_WARN_ON -#endif -#endif - -#include - -#endif From galak at freescale.com Sat Sep 10 06:02:25 2005 From: galak at freescale.com (Kumar Gala) Date: Fri, 9 Sep 2005 15:02:25 -0500 (CDT) Subject: [PATCH] powerpc: Merged ppc_asm.h Message-ID: Merged ppc_asm.h between ppc32 & ppc64. The majority of the file is common between the two architectures excluding how a single GPR is saved/restored and which GPRs are non-volatile. Additionally, moved the ASM_CONST macro used on ppc64 into ppc_asm.h. Signed-off-by: Kumar Gala --- commit ba0d4d2e26509b73b7daed0c203f481d0bb06ea0 tree fa78f19160a9174f1fec441c4f3351962c75dad4 parent bbe4b1a6e25818f03d09f3260345bfa4442acca0 author Kumar K. Gala Fri, 09 Sep 2005 15:01:18 -0500 committer Kumar K. Gala Fri, 09 Sep 2005 15:01:18 -0500 arch/ppc/kernel/head.S | 6 - arch/ppc/kernel/head_fsl_booke.S | 6 - include/asm-powerpc/ppc_asm.h | 437 ++++++++++++++++++++++++++++++++++++++ include/asm-ppc/ppc_asm.h | 350 ------------------------------ include/asm-ppc64/cputable.h | 2 include/asm-ppc64/mmu.h | 1 include/asm-ppc64/page.h | 8 - include/asm-ppc64/ppc_asm.h | 242 --------------------- 8 files changed, 446 insertions(+), 606 deletions(-) diff --git a/arch/ppc/kernel/head.S b/arch/ppc/kernel/head.S --- a/arch/ppc/kernel/head.S +++ b/arch/ppc/kernel/head.S @@ -804,7 +804,7 @@ load_up_altivec: beq 1f add r4,r4,r6 addi r4,r4,THREAD /* want THREAD of last_task_used_altivec */ - SAVE_32VR(0,r10,r4) + SAVE_32VRS(0,r10,r4) mfvscr vr0 li r10,THREAD_VSCR stvx vr0,r10,r4 @@ -824,7 +824,7 @@ load_up_altivec: stw r4,THREAD_USED_VR(r5) lvx vr0,r10,r5 mtvscr vr0 - REST_32VR(0,r10,r5) + REST_32VRS(0,r10,r5) #ifndef CONFIG_SMP subi r4,r5,THREAD sub r4,r4,r6 @@ -870,7 +870,7 @@ giveup_altivec: addi r3,r3,THREAD /* want THREAD of task */ lwz r5,PT_REGS(r3) cmpwi 0,r5,0 - SAVE_32VR(0, r4, r3) + SAVE_32VRS(0, r4, r3) mfvscr vr0 li r4,THREAD_VSCR stvx vr0,r4,r3 diff --git a/arch/ppc/kernel/head_fsl_booke.S b/arch/ppc/kernel/head_fsl_booke.S --- a/arch/ppc/kernel/head_fsl_booke.S +++ b/arch/ppc/kernel/head_fsl_booke.S @@ -853,7 +853,7 @@ load_up_spe: cmpi 0,r4,0 beq 1f addi r4,r4,THREAD /* want THREAD of last_task_used_spe */ - SAVE_32EVR(0,r10,r4) + SAVE_32EVRS(0,r10,r4) evxor evr10, evr10, evr10 /* clear out evr10 */ evmwumiaa evr10, evr10, evr10 /* evr10 <- ACC = 0 * 0 + ACC */ li r5,THREAD_ACC @@ -873,7 +873,7 @@ load_up_spe: stw r4,THREAD_USED_SPE(r5) evlddx evr4,r10,r5 evmra evr4,evr4 - REST_32EVR(0,r10,r5) + REST_32EVRS(0,r10,r5) #ifndef CONFIG_SMP subi r4,r5,THREAD stw r4,last_task_used_spe at l(r3) @@ -963,7 +963,7 @@ _GLOBAL(giveup_spe) addi r3,r3,THREAD /* want THREAD of task */ lwz r5,PT_REGS(r3) cmpi 0,r5,0 - SAVE_32EVR(0, r4, r3) + SAVE_32EVRS(0, r4, r3) evxor evr6, evr6, evr6 /* clear out evr6 */ evmwumiaa evr6, evr6, evr6 /* evr6 <- ACC = 0 * 0 + ACC */ li r4,THREAD_ACC diff --git a/include/asm-powerpc/ppc_asm.h b/include/asm-powerpc/ppc_asm.h new file mode 100644 --- /dev/null +++ b/include/asm-powerpc/ppc_asm.h @@ -0,0 +1,437 @@ +/* + * Copyright (C) 1995-1999 Gary Thomas, Paul Mackerras, Cort Dougan. + */ + +#ifndef _ASM_POWERPC_PPC_ASM_H +#define _ASM_POWERPC_PPC_ASM_H + +#ifdef __ASSEMBLY__ + +/* + * Macros for storing registers into and loading registers from + * exception frames. + */ +#ifdef __powerpc64__ +#define SAVE_GPR(n, base) std n,GPR0+8*(n)(base) +#define REST_GPR(n, base) ld n,GPR0+8*(n)(base) +#define SAVE_NVGPRS(base) SAVE_8GPRS(14, base); SAVE_10GPRS(22, base) +#define REST_NVGPRS(base) REST_8GPRS(14, base); REST_10GPRS(22, base) +#else +#define SAVE_GPR(n, base) stw n,GPR0+4*(n)(base) +#define REST_GPR(n, base) lwz n,GPR0+4*(n)(base) +#define SAVE_NVGPRS(base) SAVE_GPR(13, base); SAVE_8GPRS(14, base); \ + SAVE_10GPRS(22, base) +#define REST_NVGPRS(base) REST_GPR(13, base); REST_8GPRS(14, base); \ + REST_10GPRS(22, base) +#endif + + +#define SAVE_2GPRS(n, base) SAVE_GPR(n, base); SAVE_GPR(n+1, base) +#define SAVE_4GPRS(n, base) SAVE_2GPRS(n, base); SAVE_2GPRS(n+2, base) +#define SAVE_8GPRS(n, base) SAVE_4GPRS(n, base); SAVE_4GPRS(n+4, base) +#define SAVE_10GPRS(n, base) SAVE_8GPRS(n, base); SAVE_2GPRS(n+8, base) +#define REST_2GPRS(n, base) REST_GPR(n, base); REST_GPR(n+1, base) +#define REST_4GPRS(n, base) REST_2GPRS(n, base); REST_2GPRS(n+2, base) +#define REST_8GPRS(n, base) REST_4GPRS(n, base); REST_4GPRS(n+4, base) +#define REST_10GPRS(n, base) REST_8GPRS(n, base); REST_2GPRS(n+8, base) + +#define SAVE_FPR(n, base) stfd n,THREAD_FPR0+8*(n)(base) +#define SAVE_2FPRS(n, base) SAVE_FPR(n, base); SAVE_FPR(n+1, base) +#define SAVE_4FPRS(n, base) SAVE_2FPRS(n, base); SAVE_2FPRS(n+2, base) +#define SAVE_8FPRS(n, base) SAVE_4FPRS(n, base); SAVE_4FPRS(n+4, base) +#define SAVE_16FPRS(n, base) SAVE_8FPRS(n, base); SAVE_8FPRS(n+8, base) +#define SAVE_32FPRS(n, base) SAVE_16FPRS(n, base); SAVE_16FPRS(n+16, base) +#define REST_FPR(n, base) lfd n,THREAD_FPR0+8*(n)(base) +#define REST_2FPRS(n, base) REST_FPR(n, base); REST_FPR(n+1, base) +#define REST_4FPRS(n, base) REST_2FPRS(n, base); REST_2FPRS(n+2, base) +#define REST_8FPRS(n, base) REST_4FPRS(n, base); REST_4FPRS(n+4, base) +#define REST_16FPRS(n, base) REST_8FPRS(n, base); REST_8FPRS(n+8, base) +#define REST_32FPRS(n, base) REST_16FPRS(n, base); REST_16FPRS(n+16, base) + +#define SAVE_VR(n,b,base) li b,THREAD_VR0+(16*(n)); stvx n,b,base +#define SAVE_2VRS(n,b,base) SAVE_VR(n,b,base); SAVE_VR(n+1,b,base) +#define SAVE_4VRS(n,b,base) SAVE_2VRS(n,b,base); SAVE_2VRS(n+2,b,base) +#define SAVE_8VRS(n,b,base) SAVE_4VRS(n,b,base); SAVE_4VRS(n+4,b,base) +#define SAVE_16VRS(n,b,base) SAVE_8VRS(n,b,base); SAVE_8VRS(n+8,b,base) +#define SAVE_32VRS(n,b,base) SAVE_16VRS(n,b,base); SAVE_16VRS(n+16,b,base) +#define REST_VR(n,b,base) li b,THREAD_VR0+(16*(n)); lvx n,b,base +#define REST_2VRS(n,b,base) REST_VR(n,b,base); REST_VR(n+1,b,base) +#define REST_4VRS(n,b,base) REST_2VRS(n,b,base); REST_2VRS(n+2,b,base) +#define REST_8VRS(n,b,base) REST_4VRS(n,b,base); REST_4VRS(n+4,b,base) +#define REST_16VRS(n,b,base) REST_8VRS(n,b,base); REST_8VRS(n+8,b,base) +#define REST_32VRS(n,b,base) REST_16VRS(n,b,base); REST_16VRS(n+16,b,base) + +#define SAVE_EVR(n,s,base) evmergehi s,s,n; stw s,THREAD_EVR0+4*(n)(base) +#define SAVE_2EVRS(n,s,base) SAVE_EVR(n,s,base); SAVE_EVR(n+1,s,base) +#define SAVE_4EVRS(n,s,base) SAVE_2EVRS(n,s,base); SAVE_2EVRS(n+2,s,base) +#define SAVE_8EVRS(n,s,base) SAVE_4EVRS(n,s,base); SAVE_4EVRS(n+4,s,base) +#define SAVE_16EVRS(n,s,base) SAVE_8EVRS(n,s,base); SAVE_8EVRS(n+8,s,base) +#define SAVE_32EVRS(n,s,base) SAVE_16EVRS(n,s,base); SAVE_16EVRS(n+16,s,base) +#define REST_EVR(n,s,base) lwz s,THREAD_EVR0+4*(n)(base); evmergelo n,s,n +#define REST_2EVRS(n,s,base) REST_EVR(n,s,base); REST_EVR(n+1,s,base) +#define REST_4EVRS(n,s,base) REST_2EVRS(n,s,base); REST_2EVRS(n+2,s,base) +#define REST_8EVRS(n,s,base) REST_4EVRS(n,s,base); REST_4EVRS(n+4,s,base) +#define REST_16EVRS(n,s,base) REST_8EVRS(n,s,base); REST_8EVRS(n+8,s,base) +#define REST_32EVRS(n,s,base) REST_16EVRS(n,s,base); REST_16EVRS(n+16,s,base) + +/* Macros to adjust thread priority for Iseries hardware multithreading */ +#define HMT_LOW or 1,1,1 +#define HMT_MEDIUM or 2,2,2 +#define HMT_HIGH or 3,3,3 + +/* handle instructions that older assemblers may not know */ +#define RFCI .long 0x4c000066 /* rfci instruction */ +#define RFDI .long 0x4c00004e /* rfdi instruction */ +#define RFMCI .long 0x4c00004c /* rfmci instruction */ + +/* + * LOADADDR( rn, name ) + * loads the address of 'name' into 'rn' + * + * LOADBASE( rn, name ) + * loads the address (less the low 16 bits) of 'name' into 'rn' + * suitable for base+disp addressing + */ +#ifdef __powerpc64__ +#define LOADADDR(rn,name) \ + lis rn,name##@highest; \ + ori rn,rn,name##@higher; \ + rldicr rn,rn,32,31; \ + oris rn,rn,name##@h; \ + ori rn,rn,name##@l + +#define LOADBASE(rn,name) \ + lis rn,name at highest; \ + ori rn,rn,name at higher; \ + rldicr rn,rn,32,31; \ + oris rn,rn,name at ha + + +#define SET_REG_TO_CONST(reg, value) \ + lis reg,(((value)>>48)&0xFFFF); \ + ori reg,reg,(((value)>>32)&0xFFFF); \ + rldicr reg,reg,32,31; \ + oris reg,reg,(((value)>>16)&0xFFFF); \ + ori reg,reg,((value)&0xFFFF); + +#define SET_REG_TO_LABEL(reg, label) \ + lis reg,(label)@highest; \ + ori reg,reg,(label)@higher; \ + rldicr reg,reg,32,31; \ + oris reg,reg,(label)@h; \ + ori reg,reg,(label)@l; +#endif + +/* various errata or part fixups */ +#ifdef CONFIG_PPC601_SYNC_FIX +#define SYNC \ +BEGIN_FTR_SECTION \ + sync; \ + isync; \ +END_FTR_SECTION_IFSET(CPU_FTR_601) +#define SYNC_601 \ +BEGIN_FTR_SECTION \ + sync; \ +END_FTR_SECTION_IFSET(CPU_FTR_601) +#define ISYNC_601 \ +BEGIN_FTR_SECTION \ + isync; \ +END_FTR_SECTION_IFSET(CPU_FTR_601) +#else +#define SYNC +#define SYNC_601 +#define ISYNC_601 +#endif + + +#ifndef CONFIG_SMP +#define TLBSYNC +#else /* CONFIG_SMP */ +/* tlbsync is not implemented on 601 */ +#define TLBSYNC \ +BEGIN_FTR_SECTION \ + tlbsync; \ + sync; \ +END_FTR_SECTION_IFCLR(CPU_FTR_601) +#endif + + +/* + * This instruction is not implemented on the PPC 603 or 601; however, on + * the 403GCX and 405GP tlbia IS defined and tlbie is not. + * All of these instructions exist in the 8xx, they have magical powers, + * and they must be used. + */ + +#if !defined(CONFIG_4xx) && !defined(CONFIG_8xx) +#define tlbia \ + li r4,1024; \ + mtctr r4; \ + lis r4,KERNELBASE at h; \ +0: tlbie r4; \ + addi r4,r4,0x1000; \ + bdnz 0b +#endif + + +#ifdef CONFIG_IBM405_ERR77 +#define PPC405_ERR77(ra,rb) dcbt ra, rb; +#define PPC405_ERR77_SYNC sync; +#else +#define PPC405_ERR77(ra,rb) +#define PPC405_ERR77_SYNC +#endif + + +#ifdef CONFIG_IBM440EP_ERR42 +#define PPC440EP_ERR42 isync +#else +#define PPC440EP_ERR42 +#endif + + +#if defined(CONFIG_BOOKE) +#define tophys(rd,rs) \ + addis rd,rs,0 + +#define tovirt(rd,rs) \ + addis rd,rs,0 + +#elif defined(CONFIG_PPC64) +/* PPPBBB - DRENG If KERNELBASE is always 0xC0..., + * Then we can easily do this with one asm insn. -Peter + */ +#define tophys(rd,rs) \ + lis rd,((KERNELBASE>>48)&0xFFFF); \ + rldicr rd,rd,32,31; \ + sub rd,rs,rd + +#define tovirt(rd,rs) \ + lis rd,((KERNELBASE>>48)&0xFFFF); \ + rldicr rd,rd,32,31; \ + add rd,rs,rd +#else +/* + * On APUS (Amiga PowerPC cpu upgrade board), we don't know the + * physical base address of RAM at compile time. + */ +#define tophys(rd,rs) \ +0: addis rd,rs,-KERNELBASE at h; \ + .section ".vtop_fixup","aw"; \ + .align 1; \ + .long 0b; \ + .previous + +#define tovirt(rd,rs) \ +0: addis rd,rs,KERNELBASE at h; \ + .section ".ptov_fixup","aw"; \ + .align 1; \ + .long 0b; \ + .previous +#endif + +/* + * On 64-bit cpus, we use the rfid instruction instead of rfi, but + * we then have to make sure we preserve the top 32 bits except for + * the 64-bit mode bit, which we clear. + */ +#if defined(CONFIG_PPC64BRIDGE) +#define FIX_SRR1(ra, rb) \ + mr rb,ra; \ + mfmsr ra; \ + clrldi ra,ra,1; /* turn off 64-bit mode */ \ + rldimi ra,rb,0,32 +#define RFI .long 0x4c000024 /* rfid instruction */ +#define MTMSRD(r) .long (0x7c000164 + ((r) << 21)) /* mtmsrd */ +#define CLR_TOP32(r) rlwinm (r),(r),0,0,31 /* clear top 32 bits */ +#elif defined(CONFIG_PPC64) +/* Insert the high 32 bits of the MSR into what will be the new + MSR (via SRR1 and rfid) This preserves the MSR.SF and MSR.ISF + bits. */ + +#define FIX_SRR1(ra, rb) \ + mr rb,ra; \ + mfmsr ra; \ + rldimi ra,rb,0,32 + +#define CLR_TOP32(r) rlwinm (r),(r),0,0,31 /* clear top 32 bits */ + +#else +#define FIX_SRR1(ra, rb) +#ifndef CONFIG_40x +#define RFI rfi +#else +#define RFI rfi; b . /* Prevent prefetch past rfi */ +#endif +#define MTMSRD(r) mtmsr r +#define CLR_TOP32(r) +#endif + +/* The boring bits... */ + +/* Condition Register Bit Fields */ + +#define cr0 0 +#define cr1 1 +#define cr2 2 +#define cr3 3 +#define cr4 4 +#define cr5 5 +#define cr6 6 +#define cr7 7 + + +/* General Purpose Registers (GPRs) */ + +#define r0 0 +#define r1 1 +#define r2 2 +#define r3 3 +#define r4 4 +#define r5 5 +#define r6 6 +#define r7 7 +#define r8 8 +#define r9 9 +#define r10 10 +#define r11 11 +#define r12 12 +#define r13 13 +#define r14 14 +#define r15 15 +#define r16 16 +#define r17 17 +#define r18 18 +#define r19 19 +#define r20 20 +#define r21 21 +#define r22 22 +#define r23 23 +#define r24 24 +#define r25 25 +#define r26 26 +#define r27 27 +#define r28 28 +#define r29 29 +#define r30 30 +#define r31 31 + + +/* Floating Point Registers (FPRs) */ + +#define fr0 0 +#define fr1 1 +#define fr2 2 +#define fr3 3 +#define fr4 4 +#define fr5 5 +#define fr6 6 +#define fr7 7 +#define fr8 8 +#define fr9 9 +#define fr10 10 +#define fr11 11 +#define fr12 12 +#define fr13 13 +#define fr14 14 +#define fr15 15 +#define fr16 16 +#define fr17 17 +#define fr18 18 +#define fr19 19 +#define fr20 20 +#define fr21 21 +#define fr22 22 +#define fr23 23 +#define fr24 24 +#define fr25 25 +#define fr26 26 +#define fr27 27 +#define fr28 28 +#define fr29 29 +#define fr30 30 +#define fr31 31 + +/* AltiVec Registers (VPRs) */ + +#define vr0 0 +#define vr1 1 +#define vr2 2 +#define vr3 3 +#define vr4 4 +#define vr5 5 +#define vr6 6 +#define vr7 7 +#define vr8 8 +#define vr9 9 +#define vr10 10 +#define vr11 11 +#define vr12 12 +#define vr13 13 +#define vr14 14 +#define vr15 15 +#define vr16 16 +#define vr17 17 +#define vr18 18 +#define vr19 19 +#define vr20 20 +#define vr21 21 +#define vr22 22 +#define vr23 23 +#define vr24 24 +#define vr25 25 +#define vr26 26 +#define vr27 27 +#define vr28 28 +#define vr29 29 +#define vr30 30 +#define vr31 31 + +/* SPE Registers (EVPRs) */ + +#define evr0 0 +#define evr1 1 +#define evr2 2 +#define evr3 3 +#define evr4 4 +#define evr5 5 +#define evr6 6 +#define evr7 7 +#define evr8 8 +#define evr9 9 +#define evr10 10 +#define evr11 11 +#define evr12 12 +#define evr13 13 +#define evr14 14 +#define evr15 15 +#define evr16 16 +#define evr17 17 +#define evr18 18 +#define evr19 19 +#define evr20 20 +#define evr21 21 +#define evr22 22 +#define evr23 23 +#define evr24 24 +#define evr25 25 +#define evr26 26 +#define evr27 27 +#define evr28 28 +#define evr29 29 +#define evr30 30 +#define evr31 31 + +/* some stab codes */ +#define N_FUN 36 +#define N_RSYM 64 +#define N_SLINE 68 +#define N_SO 100 + +#define ASM_CONST(x) x +#else + #define __ASM_CONST(x) x##UL + #define ASM_CONST(x) __ASM_CONST(x) +#endif /* __ASSEMBLY__ */ + +#endif /* _ASM_POWERPC_PPC_ASM_H */ diff --git a/include/asm-ppc/ppc_asm.h b/include/asm-ppc/ppc_asm.h deleted file mode 100644 --- a/include/asm-ppc/ppc_asm.h +++ /dev/null @@ -1,350 +0,0 @@ -/* - * include/asm-ppc/ppc_asm.h - * - * Definitions used by various bits of low-level assembly code on PowerPC. - * - * Copyright (C) 1995-1999 Gary Thomas, Paul Mackerras, Cort Dougan. - * - * 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 - -/* - * Macros for storing registers into and loading registers from - * exception frames. - */ -#define SAVE_GPR(n, base) stw n,GPR0+4*(n)(base) -#define SAVE_2GPRS(n, base) SAVE_GPR(n, base); SAVE_GPR(n+1, base) -#define SAVE_4GPRS(n, base) SAVE_2GPRS(n, base); SAVE_2GPRS(n+2, base) -#define SAVE_8GPRS(n, base) SAVE_4GPRS(n, base); SAVE_4GPRS(n+4, base) -#define SAVE_10GPRS(n, base) SAVE_8GPRS(n, base); SAVE_2GPRS(n+8, base) -#define REST_GPR(n, base) lwz n,GPR0+4*(n)(base) -#define REST_2GPRS(n, base) REST_GPR(n, base); REST_GPR(n+1, base) -#define REST_4GPRS(n, base) REST_2GPRS(n, base); REST_2GPRS(n+2, base) -#define REST_8GPRS(n, base) REST_4GPRS(n, base); REST_4GPRS(n+4, base) -#define REST_10GPRS(n, base) REST_8GPRS(n, base); REST_2GPRS(n+8, base) - -#define SAVE_NVGPRS(base) SAVE_GPR(13, base); SAVE_8GPRS(14, base); \ - SAVE_10GPRS(22, base) -#define REST_NVGPRS(base) REST_GPR(13, base); REST_8GPRS(14, base); \ - REST_10GPRS(22, base) - -#define SAVE_FPR(n, base) stfd n,THREAD_FPR0+8*(n)(base) -#define SAVE_2FPRS(n, base) SAVE_FPR(n, base); SAVE_FPR(n+1, base) -#define SAVE_4FPRS(n, base) SAVE_2FPRS(n, base); SAVE_2FPRS(n+2, base) -#define SAVE_8FPRS(n, base) SAVE_4FPRS(n, base); SAVE_4FPRS(n+4, base) -#define SAVE_16FPRS(n, base) SAVE_8FPRS(n, base); SAVE_8FPRS(n+8, base) -#define SAVE_32FPRS(n, base) SAVE_16FPRS(n, base); SAVE_16FPRS(n+16, base) -#define REST_FPR(n, base) lfd n,THREAD_FPR0+8*(n)(base) -#define REST_2FPRS(n, base) REST_FPR(n, base); REST_FPR(n+1, base) -#define REST_4FPRS(n, base) REST_2FPRS(n, base); REST_2FPRS(n+2, base) -#define REST_8FPRS(n, base) REST_4FPRS(n, base); REST_4FPRS(n+4, base) -#define REST_16FPRS(n, base) REST_8FPRS(n, base); REST_8FPRS(n+8, base) -#define REST_32FPRS(n, base) REST_16FPRS(n, base); REST_16FPRS(n+16, base) - -#define SAVE_VR(n,b,base) li b,THREAD_VR0+(16*(n)); stvx n,b,base -#define SAVE_2VR(n,b,base) SAVE_VR(n,b,base); SAVE_VR(n+1,b,base) -#define SAVE_4VR(n,b,base) SAVE_2VR(n,b,base); SAVE_2VR(n+2,b,base) -#define SAVE_8VR(n,b,base) SAVE_4VR(n,b,base); SAVE_4VR(n+4,b,base) -#define SAVE_16VR(n,b,base) SAVE_8VR(n,b,base); SAVE_8VR(n+8,b,base) -#define SAVE_32VR(n,b,base) SAVE_16VR(n,b,base); SAVE_16VR(n+16,b,base) -#define REST_VR(n,b,base) li b,THREAD_VR0+(16*(n)); lvx n,b,base -#define REST_2VR(n,b,base) REST_VR(n,b,base); REST_VR(n+1,b,base) -#define REST_4VR(n,b,base) REST_2VR(n,b,base); REST_2VR(n+2,b,base) -#define REST_8VR(n,b,base) REST_4VR(n,b,base); REST_4VR(n+4,b,base) -#define REST_16VR(n,b,base) REST_8VR(n,b,base); REST_8VR(n+8,b,base) -#define REST_32VR(n,b,base) REST_16VR(n,b,base); REST_16VR(n+16,b,base) - -#define SAVE_EVR(n,s,base) evmergehi s,s,n; stw s,THREAD_EVR0+4*(n)(base) -#define SAVE_2EVR(n,s,base) SAVE_EVR(n,s,base); SAVE_EVR(n+1,s,base) -#define SAVE_4EVR(n,s,base) SAVE_2EVR(n,s,base); SAVE_2EVR(n+2,s,base) -#define SAVE_8EVR(n,s,base) SAVE_4EVR(n,s,base); SAVE_4EVR(n+4,s,base) -#define SAVE_16EVR(n,s,base) SAVE_8EVR(n,s,base); SAVE_8EVR(n+8,s,base) -#define SAVE_32EVR(n,s,base) SAVE_16EVR(n,s,base); SAVE_16EVR(n+16,s,base) - -#define REST_EVR(n,s,base) lwz s,THREAD_EVR0+4*(n)(base); evmergelo n,s,n -#define REST_2EVR(n,s,base) REST_EVR(n,s,base); REST_EVR(n+1,s,base) -#define REST_4EVR(n,s,base) REST_2EVR(n,s,base); REST_2EVR(n+2,s,base) -#define REST_8EVR(n,s,base) REST_4EVR(n,s,base); REST_4EVR(n+4,s,base) -#define REST_16EVR(n,s,base) REST_8EVR(n,s,base); REST_8EVR(n+8,s,base) -#define REST_32EVR(n,s,base) REST_16EVR(n,s,base); REST_16EVR(n+16,s,base) - -#ifdef CONFIG_PPC601_SYNC_FIX -#define SYNC \ -BEGIN_FTR_SECTION \ - sync; \ - isync; \ -END_FTR_SECTION_IFSET(CPU_FTR_601) -#define SYNC_601 \ -BEGIN_FTR_SECTION \ - sync; \ -END_FTR_SECTION_IFSET(CPU_FTR_601) -#define ISYNC_601 \ -BEGIN_FTR_SECTION \ - isync; \ -END_FTR_SECTION_IFSET(CPU_FTR_601) -#else -#define SYNC -#define SYNC_601 -#define ISYNC_601 -#endif - -#ifndef CONFIG_SMP -#define TLBSYNC -#else /* CONFIG_SMP */ -/* tlbsync is not implemented on 601 */ -#define TLBSYNC \ -BEGIN_FTR_SECTION \ - tlbsync; \ - sync; \ -END_FTR_SECTION_IFCLR(CPU_FTR_601) -#endif - -/* - * This instruction is not implemented on the PPC 603 or 601; however, on - * the 403GCX and 405GP tlbia IS defined and tlbie is not. - * All of these instructions exist in the 8xx, they have magical powers, - * and they must be used. - */ - -#if !defined(CONFIG_4xx) && !defined(CONFIG_8xx) -#define tlbia \ - li r4,1024; \ - mtctr r4; \ - lis r4,KERNELBASE at h; \ -0: tlbie r4; \ - addi r4,r4,0x1000; \ - bdnz 0b -#endif - -#ifdef CONFIG_BOOKE -#define tophys(rd,rs) \ - addis rd,rs,0 - -#define tovirt(rd,rs) \ - addis rd,rs,0 - -#else /* CONFIG_BOOKE */ -/* - * On APUS (Amiga PowerPC cpu upgrade board), we don't know the - * physical base address of RAM at compile time. - */ -#define tophys(rd,rs) \ -0: addis rd,rs,-KERNELBASE at h; \ - .section ".vtop_fixup","aw"; \ - .align 1; \ - .long 0b; \ - .previous - -#define tovirt(rd,rs) \ -0: addis rd,rs,KERNELBASE at h; \ - .section ".ptov_fixup","aw"; \ - .align 1; \ - .long 0b; \ - .previous -#endif /* CONFIG_BOOKE */ - -/* - * On 64-bit cpus, we use the rfid instruction instead of rfi, but - * we then have to make sure we preserve the top 32 bits except for - * the 64-bit mode bit, which we clear. - */ -#ifdef CONFIG_PPC64BRIDGE -#define FIX_SRR1(ra, rb) \ - mr rb,ra; \ - mfmsr ra; \ - clrldi ra,ra,1; /* turn off 64-bit mode */ \ - rldimi ra,rb,0,32 -#define RFI .long 0x4c000024 /* rfid instruction */ -#define MTMSRD(r) .long (0x7c000164 + ((r) << 21)) /* mtmsrd */ -#define CLR_TOP32(r) rlwinm (r),(r),0,0,31 /* clear top 32 bits */ - -#else -#define FIX_SRR1(ra, rb) -#ifndef CONFIG_40x -#define RFI rfi -#else -#define RFI rfi; b . /* Prevent prefetch past rfi */ -#endif -#define MTMSRD(r) mtmsr r -#define CLR_TOP32(r) -#endif /* CONFIG_PPC64BRIDGE */ - -#define RFCI .long 0x4c000066 /* rfci instruction */ -#define RFDI .long 0x4c00004e /* rfdi instruction */ -#define RFMCI .long 0x4c00004c /* rfmci instruction */ - -#ifdef CONFIG_IBM405_ERR77 -#define PPC405_ERR77(ra,rb) dcbt ra, rb; -#define PPC405_ERR77_SYNC sync; -#else -#define PPC405_ERR77(ra,rb) -#define PPC405_ERR77_SYNC -#endif - -#ifdef CONFIG_IBM440EP_ERR42 -#define PPC440EP_ERR42 isync -#else -#define PPC440EP_ERR42 -#endif - -/* The boring bits... */ - -/* Condition Register Bit Fields */ - -#define cr0 0 -#define cr1 1 -#define cr2 2 -#define cr3 3 -#define cr4 4 -#define cr5 5 -#define cr6 6 -#define cr7 7 - - -/* General Purpose Registers (GPRs) */ - -#define r0 0 -#define r1 1 -#define r2 2 -#define r3 3 -#define r4 4 -#define r5 5 -#define r6 6 -#define r7 7 -#define r8 8 -#define r9 9 -#define r10 10 -#define r11 11 -#define r12 12 -#define r13 13 -#define r14 14 -#define r15 15 -#define r16 16 -#define r17 17 -#define r18 18 -#define r19 19 -#define r20 20 -#define r21 21 -#define r22 22 -#define r23 23 -#define r24 24 -#define r25 25 -#define r26 26 -#define r27 27 -#define r28 28 -#define r29 29 -#define r30 30 -#define r31 31 - - -/* Floating Point Registers (FPRs) */ - -#define fr0 0 -#define fr1 1 -#define fr2 2 -#define fr3 3 -#define fr4 4 -#define fr5 5 -#define fr6 6 -#define fr7 7 -#define fr8 8 -#define fr9 9 -#define fr10 10 -#define fr11 11 -#define fr12 12 -#define fr13 13 -#define fr14 14 -#define fr15 15 -#define fr16 16 -#define fr17 17 -#define fr18 18 -#define fr19 19 -#define fr20 20 -#define fr21 21 -#define fr22 22 -#define fr23 23 -#define fr24 24 -#define fr25 25 -#define fr26 26 -#define fr27 27 -#define fr28 28 -#define fr29 29 -#define fr30 30 -#define fr31 31 - -#define vr0 0 -#define vr1 1 -#define vr2 2 -#define vr3 3 -#define vr4 4 -#define vr5 5 -#define vr6 6 -#define vr7 7 -#define vr8 8 -#define vr9 9 -#define vr10 10 -#define vr11 11 -#define vr12 12 -#define vr13 13 -#define vr14 14 -#define vr15 15 -#define vr16 16 -#define vr17 17 -#define vr18 18 -#define vr19 19 -#define vr20 20 -#define vr21 21 -#define vr22 22 -#define vr23 23 -#define vr24 24 -#define vr25 25 -#define vr26 26 -#define vr27 27 -#define vr28 28 -#define vr29 29 -#define vr30 30 -#define vr31 31 - -#define evr0 0 -#define evr1 1 -#define evr2 2 -#define evr3 3 -#define evr4 4 -#define evr5 5 -#define evr6 6 -#define evr7 7 -#define evr8 8 -#define evr9 9 -#define evr10 10 -#define evr11 11 -#define evr12 12 -#define evr13 13 -#define evr14 14 -#define evr15 15 -#define evr16 16 -#define evr17 17 -#define evr18 18 -#define evr19 19 -#define evr20 20 -#define evr21 21 -#define evr22 22 -#define evr23 23 -#define evr24 24 -#define evr25 25 -#define evr26 26 -#define evr27 27 -#define evr28 28 -#define evr29 29 -#define evr30 30 -#define evr31 31 - -/* some stab codes */ -#define N_FUN 36 -#define N_RSYM 64 -#define N_SLINE 68 -#define N_SO 100 diff --git a/include/asm-ppc64/cputable.h b/include/asm-ppc64/cputable.h --- a/include/asm-ppc64/cputable.h +++ b/include/asm-ppc64/cputable.h @@ -16,7 +16,7 @@ #define __ASM_PPC_CPUTABLE_H #include -#include /* for ASM_CONST */ +#include /* for ASM_CONST */ /* Exposed to userland CPU features - Must match ppc32 definitions */ #define PPC_FEATURE_32 0x80000000 diff --git a/include/asm-ppc64/mmu.h b/include/asm-ppc64/mmu.h --- a/include/asm-ppc64/mmu.h +++ b/include/asm-ppc64/mmu.h @@ -14,6 +14,7 @@ #define _PPC64_MMU_H_ #include +#include /* for ASM_CONST */ #include /* diff --git a/include/asm-ppc64/page.h b/include/asm-ppc64/page.h --- a/include/asm-ppc64/page.h +++ b/include/asm-ppc64/page.h @@ -11,13 +11,7 @@ */ #include - -#ifdef __ASSEMBLY__ - #define ASM_CONST(x) x -#else - #define __ASM_CONST(x) x##UL - #define ASM_CONST(x) __ASM_CONST(x) -#endif +#include /* for ASM_CONST */ /* PAGE_SHIFT determines the page size */ #define PAGE_SHIFT 12 diff --git a/include/asm-ppc64/ppc_asm.h b/include/asm-ppc64/ppc_asm.h deleted file mode 100644 --- a/include/asm-ppc64/ppc_asm.h +++ /dev/null @@ -1,242 +0,0 @@ -/* - * arch/ppc64/kernel/ppc_asm.h - * - * Definitions used by various bits of low-level assembly code on PowerPC. - * - * Copyright (C) 1995-1999 Gary Thomas, Paul Mackerras, Cort Dougan. - * - * 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 _PPC64_PPC_ASM_H -#define _PPC64_PPC_ASM_H -/* - * Macros for storing registers into and loading registers from - * exception frames. - */ -#define SAVE_GPR(n, base) std n,GPR0+8*(n)(base) -#define SAVE_2GPRS(n, base) SAVE_GPR(n, base); SAVE_GPR(n+1, base) -#define SAVE_4GPRS(n, base) SAVE_2GPRS(n, base); SAVE_2GPRS(n+2, base) -#define SAVE_8GPRS(n, base) SAVE_4GPRS(n, base); SAVE_4GPRS(n+4, base) -#define SAVE_10GPRS(n, base) SAVE_8GPRS(n, base); SAVE_2GPRS(n+8, base) -#define REST_GPR(n, base) ld n,GPR0+8*(n)(base) -#define REST_2GPRS(n, base) REST_GPR(n, base); REST_GPR(n+1, base) -#define REST_4GPRS(n, base) REST_2GPRS(n, base); REST_2GPRS(n+2, base) -#define REST_8GPRS(n, base) REST_4GPRS(n, base); REST_4GPRS(n+4, base) -#define REST_10GPRS(n, base) REST_8GPRS(n, base); REST_2GPRS(n+8, base) - -#define SAVE_NVGPRS(base) SAVE_8GPRS(14, base); SAVE_10GPRS(22, base) -#define REST_NVGPRS(base) REST_8GPRS(14, base); REST_10GPRS(22, base) - -#define SAVE_FPR(n, base) stfd n,THREAD_FPR0+8*(n)(base) -#define SAVE_2FPRS(n, base) SAVE_FPR(n, base); SAVE_FPR(n+1, base) -#define SAVE_4FPRS(n, base) SAVE_2FPRS(n, base); SAVE_2FPRS(n+2, base) -#define SAVE_8FPRS(n, base) SAVE_4FPRS(n, base); SAVE_4FPRS(n+4, base) -#define SAVE_16FPRS(n, base) SAVE_8FPRS(n, base); SAVE_8FPRS(n+8, base) -#define SAVE_32FPRS(n, base) SAVE_16FPRS(n, base); SAVE_16FPRS(n+16, base) -#define REST_FPR(n, base) lfd n,THREAD_FPR0+8*(n)(base) -#define REST_2FPRS(n, base) REST_FPR(n, base); REST_FPR(n+1, base) -#define REST_4FPRS(n, base) REST_2FPRS(n, base); REST_2FPRS(n+2, base) -#define REST_8FPRS(n, base) REST_4FPRS(n, base); REST_4FPRS(n+4, base) -#define REST_16FPRS(n, base) REST_8FPRS(n, base); REST_8FPRS(n+8, base) -#define REST_32FPRS(n, base) REST_16FPRS(n, base); REST_16FPRS(n+16, base) - -#define SAVE_VR(n,b,base) li b,THREAD_VR0+(16*(n)); stvx n,b,base -#define SAVE_2VRS(n,b,base) SAVE_VR(n,b,base); SAVE_VR(n+1,b,base) -#define SAVE_4VRS(n,b,base) SAVE_2VRS(n,b,base); SAVE_2VRS(n+2,b,base) -#define SAVE_8VRS(n,b,base) SAVE_4VRS(n,b,base); SAVE_4VRS(n+4,b,base) -#define SAVE_16VRS(n,b,base) SAVE_8VRS(n,b,base); SAVE_8VRS(n+8,b,base) -#define SAVE_32VRS(n,b,base) SAVE_16VRS(n,b,base); SAVE_16VRS(n+16,b,base) -#define REST_VR(n,b,base) li b,THREAD_VR0+(16*(n)); lvx n,b,base -#define REST_2VRS(n,b,base) REST_VR(n,b,base); REST_VR(n+1,b,base) -#define REST_4VRS(n,b,base) REST_2VRS(n,b,base); REST_2VRS(n+2,b,base) -#define REST_8VRS(n,b,base) REST_4VRS(n,b,base); REST_4VRS(n+4,b,base) -#define REST_16VRS(n,b,base) REST_8VRS(n,b,base); REST_8VRS(n+8,b,base) -#define REST_32VRS(n,b,base) REST_16VRS(n,b,base); REST_16VRS(n+16,b,base) - -/* Macros to adjust thread priority for Iseries hardware multithreading */ -#define HMT_LOW or 1,1,1 -#define HMT_MEDIUM or 2,2,2 -#define HMT_HIGH or 3,3,3 - -/* Insert the high 32 bits of the MSR into what will be the new - MSR (via SRR1 and rfid) This preserves the MSR.SF and MSR.ISF - bits. */ - -#define FIX_SRR1(ra, rb) \ - mr rb,ra; \ - mfmsr ra; \ - rldimi ra,rb,0,32 - -#define CLR_TOP32(r) rlwinm (r),(r),0,0,31 /* clear top 32 bits */ - -/* - * LOADADDR( rn, name ) - * loads the address of 'name' into 'rn' - * - * LOADBASE( rn, name ) - * loads the address (less the low 16 bits) of 'name' into 'rn' - * suitable for base+disp addressing - */ -#define LOADADDR(rn,name) \ - lis rn,name##@highest; \ - ori rn,rn,name##@higher; \ - rldicr rn,rn,32,31; \ - oris rn,rn,name##@h; \ - ori rn,rn,name##@l - -#define LOADBASE(rn,name) \ - lis rn,name at highest; \ - ori rn,rn,name at higher; \ - rldicr rn,rn,32,31; \ - oris rn,rn,name at ha - - -#define SET_REG_TO_CONST(reg, value) \ - lis reg,(((value)>>48)&0xFFFF); \ - ori reg,reg,(((value)>>32)&0xFFFF); \ - rldicr reg,reg,32,31; \ - oris reg,reg,(((value)>>16)&0xFFFF); \ - ori reg,reg,((value)&0xFFFF); - -#define SET_REG_TO_LABEL(reg, label) \ - lis reg,(label)@highest; \ - ori reg,reg,(label)@higher; \ - rldicr reg,reg,32,31; \ - oris reg,reg,(label)@h; \ - ori reg,reg,(label)@l; - - -/* PPPBBB - DRENG If KERNELBASE is always 0xC0..., - * Then we can easily do this with one asm insn. -Peter - */ -#define tophys(rd,rs) \ - lis rd,((KERNELBASE>>48)&0xFFFF); \ - rldicr rd,rd,32,31; \ - sub rd,rs,rd - -#define tovirt(rd,rs) \ - lis rd,((KERNELBASE>>48)&0xFFFF); \ - rldicr rd,rd,32,31; \ - add rd,rs,rd - -/* Condition Register Bit Fields */ - -#define cr0 0 -#define cr1 1 -#define cr2 2 -#define cr3 3 -#define cr4 4 -#define cr5 5 -#define cr6 6 -#define cr7 7 - - -/* General Purpose Registers (GPRs) */ - -#define r0 0 -#define r1 1 -#define r2 2 -#define r3 3 -#define r4 4 -#define r5 5 -#define r6 6 -#define r7 7 -#define r8 8 -#define r9 9 -#define r10 10 -#define r11 11 -#define r12 12 -#define r13 13 -#define r14 14 -#define r15 15 -#define r16 16 -#define r17 17 -#define r18 18 -#define r19 19 -#define r20 20 -#define r21 21 -#define r22 22 -#define r23 23 -#define r24 24 -#define r25 25 -#define r26 26 -#define r27 27 -#define r28 28 -#define r29 29 -#define r30 30 -#define r31 31 - - -/* Floating Point Registers (FPRs) */ - -#define fr0 0 -#define fr1 1 -#define fr2 2 -#define fr3 3 -#define fr4 4 -#define fr5 5 -#define fr6 6 -#define fr7 7 -#define fr8 8 -#define fr9 9 -#define fr10 10 -#define fr11 11 -#define fr12 12 -#define fr13 13 -#define fr14 14 -#define fr15 15 -#define fr16 16 -#define fr17 17 -#define fr18 18 -#define fr19 19 -#define fr20 20 -#define fr21 21 -#define fr22 22 -#define fr23 23 -#define fr24 24 -#define fr25 25 -#define fr26 26 -#define fr27 27 -#define fr28 28 -#define fr29 29 -#define fr30 30 -#define fr31 31 - -#define vr0 0 -#define vr1 1 -#define vr2 2 -#define vr3 3 -#define vr4 4 -#define vr5 5 -#define vr6 6 -#define vr7 7 -#define vr8 8 -#define vr9 9 -#define vr10 10 -#define vr11 11 -#define vr12 12 -#define vr13 13 -#define vr14 14 -#define vr15 15 -#define vr16 16 -#define vr17 17 -#define vr18 18 -#define vr19 19 -#define vr20 20 -#define vr21 21 -#define vr22 22 -#define vr23 23 -#define vr24 24 -#define vr25 25 -#define vr26 26 -#define vr27 27 -#define vr28 28 -#define vr29 29 -#define vr30 30 -#define vr31 31 - -#endif /* _PPC64_PPC_ASM_H */ From jdl at freescale.com Sat Sep 10 07:43:52 2005 From: jdl at freescale.com (jdl at freescale.com) Date: Fri, 09 Sep 2005 16:43:52 -0500 Subject: PATCH ppc Merge asm-ppc*/posix_types.h Message-ID: Merge asm-ppc/posix_types.h and asm-ppc64/posix_types.h. include/asm-powerpc/posix_types.h | 129 +++++++++++++++++++++++++++++++++++++ include/asm-ppc/posix_types.h | 111 -------------------------------- include/asm-ppc64/posix_types.h | 119 ---------------------------------- 3 files changed, 129 insertions(+), 230 deletions(-) Signed-off-by: Jon Loeliger Signed-off-by: Kumar Gala --- diff --git a/include/asm-powerpc/posix_types.h b/include/asm-powerpc/posix_types.h new file mode 100644 --- /dev/null +++ b/include/asm-powerpc/posix_types.h @@ -0,0 +1,129 @@ +#ifndef _ASM_POWERPC_POSIX_TYPES_H +#define _ASM_POWERPC_POSIX_TYPES_H + +/* + * This file is generally used by user-level software, so you need to + * be a little careful about namespace pollution etc. Also, we cannot + * assume GCC is being used. + */ + +typedef unsigned long __kernel_ino_t; +typedef unsigned int __kernel_mode_t; +typedef long __kernel_off_t; +typedef int __kernel_pid_t; +typedef unsigned int __kernel_uid_t; +typedef unsigned int __kernel_gid_t; +typedef long __kernel_ptrdiff_t; +typedef long __kernel_time_t; +typedef long __kernel_clock_t; +typedef int __kernel_timer_t; +typedef int __kernel_clockid_t; +typedef long __kernel_suseconds_t; +typedef int __kernel_daddr_t; +typedef char * __kernel_caddr_t; +typedef unsigned short __kernel_uid16_t; +typedef unsigned short __kernel_gid16_t; +typedef unsigned int __kernel_uid32_t; +typedef unsigned int __kernel_gid32_t; +typedef unsigned int __kernel_old_uid_t; +typedef unsigned int __kernel_old_gid_t; + +#ifdef __powerpc64__ +typedef unsigned long __kernel_nlink_t; +typedef int __kernel_ipc_pid_t; +typedef unsigned long __kernel_size_t; +typedef long __kernel_ssize_t; +typedef unsigned long __kernel_old_dev_t; +#else +typedef unsigned short __kernel_nlink_t; +typedef short __kernel_ipc_pid_t; +typedef unsigned int __kernel_size_t; +typedef int __kernel_ssize_t; +typedef unsigned int __kernel_old_dev_t; +#endif + +#ifdef __powerpc64__ +typedef long long __kernel_loff_t; +#else +#ifdef __GNUC__ +typedef long long __kernel_loff_t; +#endif +#endif + +typedef struct { + int val[2]; +} __kernel_fsid_t; + +#ifndef __GNUC__ + +#define __FD_SET(d, set) ((set)->fds_bits[__FDELT(d)] |= __FDMASK(d)) +#define __FD_CLR(d, set) ((set)->fds_bits[__FDELT(d)] &= ~__FDMASK(d)) +#define __FD_ISSET(d, set) (((set)->fds_bits[__FDELT(d)] & __FDMASK(d)) != 0) +#define __FD_ZERO(set) \ + ((void) memset ((__ptr_t) (set), 0, sizeof (__kernel_fd_set))) + +#else /* __GNUC__ */ + +#if defined(__KERNEL__) || !defined(__GLIBC__) || (__GLIBC__ < 2) \ + || (__GLIBC__ == 2 && __GLIBC_MINOR__ == 0) +/* With GNU C, use inline functions instead so args are evaluated only once: */ + +#undef __FD_SET +static __inline__ void __FD_SET(unsigned long fd, __kernel_fd_set *fdsetp) +{ + unsigned long _tmp = fd / __NFDBITS; + unsigned long _rem = fd % __NFDBITS; + fdsetp->fds_bits[_tmp] |= (1UL<<_rem); +} + +#undef __FD_CLR +static __inline__ void __FD_CLR(unsigned long fd, __kernel_fd_set *fdsetp) +{ + unsigned long _tmp = fd / __NFDBITS; + unsigned long _rem = fd % __NFDBITS; + fdsetp->fds_bits[_tmp] &= ~(1UL<<_rem); +} + +#undef __FD_ISSET +static __inline__ int __FD_ISSET(unsigned long fd, __kernel_fd_set *p) +{ + unsigned long _tmp = fd / __NFDBITS; + unsigned long _rem = fd % __NFDBITS; + return (p->fds_bits[_tmp] & (1UL<<_rem)) != 0; +} + +/* + * This will unroll the loop for the normal constant case (8 ints, + * for a 256-bit fd_set) + */ +#undef __FD_ZERO +static __inline__ void __FD_ZERO(__kernel_fd_set *p) +{ + unsigned long *tmp = (unsigned long *)p->fds_bits; + int i; + + if (__builtin_constant_p(__FDSET_LONGS)) { + switch (__FDSET_LONGS) { + case 16: + tmp[12] = 0; tmp[13] = 0; tmp[14] = 0; tmp[15] = 0; + tmp[ 8] = 0; tmp[ 9] = 0; tmp[10] = 0; tmp[11] = 0; + + case 8: + tmp[ 4] = 0; tmp[ 5] = 0; tmp[ 6] = 0; tmp[ 7] = 0; + + case 4: + tmp[ 0] = 0; tmp[ 1] = 0; tmp[ 2] = 0; tmp[ 3] = 0; + return; + } + } + i = __FDSET_LONGS; + while (i) { + i--; + *tmp = 0; + tmp++; + } +} + +#endif /* defined(__KERNEL__) || !defined(__GLIBC__) || (__GLIBC__ < 2) */ +#endif /* __GNUC__ */ +#endif /* _ASM_POWERPC_POSIX_TYPES_H */ diff --git a/include/asm-ppc/posix_types.h b/include/asm-ppc/posix_types.h deleted file mode 100644 --- a/include/asm-ppc/posix_types.h +++ /dev/null @@ -1,111 +0,0 @@ -#ifndef _PPC_POSIX_TYPES_H -#define _PPC_POSIX_TYPES_H - -/* - * This file is generally used by user-level software, so you need to - * be a little careful about namespace pollution etc. Also, we cannot - * assume GCC is being used. - */ - -typedef unsigned long __kernel_ino_t; -typedef unsigned int __kernel_mode_t; -typedef unsigned short __kernel_nlink_t; -typedef long __kernel_off_t; -typedef int __kernel_pid_t; -typedef unsigned int __kernel_uid_t; -typedef unsigned int __kernel_gid_t; -typedef unsigned int __kernel_size_t; -typedef int __kernel_ssize_t; -typedef long __kernel_ptrdiff_t; -typedef long __kernel_time_t; -typedef long __kernel_suseconds_t; -typedef long __kernel_clock_t; -typedef int __kernel_timer_t; -typedef int __kernel_clockid_t; -typedef int __kernel_daddr_t; -typedef char * __kernel_caddr_t; -typedef short __kernel_ipc_pid_t; -typedef unsigned short __kernel_uid16_t; -typedef unsigned short __kernel_gid16_t; -typedef unsigned int __kernel_uid32_t; -typedef unsigned int __kernel_gid32_t; - -typedef unsigned int __kernel_old_uid_t; -typedef unsigned int __kernel_old_gid_t; -typedef unsigned int __kernel_old_dev_t; - -#ifdef __GNUC__ -typedef long long __kernel_loff_t; -#endif - -typedef struct { - int val[2]; -} __kernel_fsid_t; - -#ifndef __GNUC__ - -#define __FD_SET(d, set) ((set)->fds_bits[__FDELT(d)] |= __FDMASK(d)) -#define __FD_CLR(d, set) ((set)->fds_bits[__FDELT(d)] &= ~__FDMASK(d)) -#define __FD_ISSET(d, set) ((set)->fds_bits[__FDELT(d)] & __FDMASK(d)) -#define __FD_ZERO(set) \ - ((void) memset ((__ptr_t) (set), 0, sizeof (__kernel_fd_set))) - -#else /* __GNUC__ */ - -#if defined(__KERNEL__) || !defined(__GLIBC__) || (__GLIBC__ < 2) \ - || (__GLIBC__ == 2 && __GLIBC_MINOR__ == 0) -/* With GNU C, use inline functions instead so args are evaluated only once: */ - -#undef __FD_SET -static __inline__ void __FD_SET(unsigned long fd, __kernel_fd_set *fdsetp) -{ - unsigned long _tmp = fd / __NFDBITS; - unsigned long _rem = fd % __NFDBITS; - fdsetp->fds_bits[_tmp] |= (1UL<<_rem); -} - -#undef __FD_CLR -static __inline__ void __FD_CLR(unsigned long fd, __kernel_fd_set *fdsetp) -{ - unsigned long _tmp = fd / __NFDBITS; - unsigned long _rem = fd % __NFDBITS; - fdsetp->fds_bits[_tmp] &= ~(1UL<<_rem); -} - -#undef __FD_ISSET -static __inline__ int __FD_ISSET(unsigned long fd, __kernel_fd_set *p) -{ - unsigned long _tmp = fd / __NFDBITS; - unsigned long _rem = fd % __NFDBITS; - return (p->fds_bits[_tmp] & (1UL<<_rem)) != 0; -} - -/* - * This will unroll the loop for the normal constant case (8 ints, - * for a 256-bit fd_set) - */ -#undef __FD_ZERO -static __inline__ void __FD_ZERO(__kernel_fd_set *p) -{ - unsigned int *tmp = (unsigned int *)p->fds_bits; - int i; - - if (__builtin_constant_p(__FDSET_LONGS)) { - switch (__FDSET_LONGS) { - case 8: - tmp[0] = 0; tmp[1] = 0; tmp[2] = 0; tmp[3] = 0; - tmp[4] = 0; tmp[5] = 0; tmp[6] = 0; tmp[7] = 0; - return; - } - } - i = __FDSET_LONGS; - while (i) { - i--; - *tmp = 0; - tmp++; - } -} - -#endif /* defined(__KERNEL__) || !defined(__GLIBC__) || (__GLIBC__ < 2) */ -#endif /* __GNUC__ */ -#endif /* _PPC_POSIX_TYPES_H */ diff --git a/include/asm-ppc64/posix_types.h b/include/asm-ppc64/posix_types.h deleted file mode 100644 --- a/include/asm-ppc64/posix_types.h +++ /dev/null @@ -1,119 +0,0 @@ -#ifndef _PPC64_POSIX_TYPES_H -#define _PPC64_POSIX_TYPES_H - -/* - * This file is generally used by user-level software, so you need to - * be a little careful about namespace pollution etc. Also, we cannot - * assume GCC is being used. - * - * 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 long __kernel_ino_t; -typedef unsigned long __kernel_nlink_t; -typedef unsigned int __kernel_mode_t; -typedef long __kernel_off_t; -typedef long long __kernel_loff_t; -typedef int __kernel_pid_t; -typedef int __kernel_ipc_pid_t; -typedef unsigned int __kernel_uid_t; -typedef unsigned int __kernel_gid_t; -typedef unsigned long __kernel_size_t; -typedef long __kernel_ssize_t; -typedef long __kernel_ptrdiff_t; -typedef long __kernel_time_t; -typedef int __kernel_timer_t; -typedef int __kernel_clockid_t; -typedef long __kernel_suseconds_t; -typedef long __kernel_clock_t; -typedef int __kernel_daddr_t; -typedef char * __kernel_caddr_t; -typedef unsigned short __kernel_uid16_t; -typedef unsigned short __kernel_gid16_t; -typedef unsigned int __kernel_uid32_t; -typedef unsigned int __kernel_gid32_t; - -typedef unsigned int __kernel_old_uid_t; -typedef unsigned int __kernel_old_gid_t; -typedef unsigned long __kernel_old_dev_t; - -typedef struct { - int val[2]; -} __kernel_fsid_t; - -#ifndef __GNUC__ - -#define __FD_SET(d, set) ((set)->fds_bits[__FDELT(d)] |= __FDMASK(d)) -#define __FD_CLR(d, set) ((set)->fds_bits[__FDELT(d)] &= ~__FDMASK(d)) -#define __FD_ISSET(d, set) (((set)->fds_bits[__FDELT(d)] & __FDMASK(d)) != 0) -#define __FD_ZERO(set) \ - ((void) memset ((__ptr_t) (set), 0, sizeof (__kernel_fd_set))) - -#else /* __GNUC__ */ - -#if defined(__KERNEL__) || !defined(__GLIBC__) || (__GLIBC__ < 2) \ - || (__GLIBC__ == 2 && __GLIBC_MINOR__ == 0) -/* With GNU C, use inline functions instead so args are evaluated only once: */ - -#undef __FD_SET -static __inline__ void __FD_SET(unsigned long fd, __kernel_fd_set *fdsetp) -{ - unsigned long _tmp = fd / __NFDBITS; - unsigned long _rem = fd % __NFDBITS; - fdsetp->fds_bits[_tmp] |= (1UL<<_rem); -} - -#undef __FD_CLR -static __inline__ void __FD_CLR(unsigned long fd, __kernel_fd_set *fdsetp) -{ - unsigned long _tmp = fd / __NFDBITS; - unsigned long _rem = fd % __NFDBITS; - fdsetp->fds_bits[_tmp] &= ~(1UL<<_rem); -} - -#undef __FD_ISSET -static __inline__ int __FD_ISSET(unsigned long fd, __kernel_fd_set *p) -{ - unsigned long _tmp = fd / __NFDBITS; - unsigned long _rem = fd % __NFDBITS; - return (p->fds_bits[_tmp] & (1UL<<_rem)) != 0; -} - -/* - * This will unroll the loop for the normal constant case (8 ints, - * for a 256-bit fd_set) - */ -#undef __FD_ZERO -static __inline__ void __FD_ZERO(__kernel_fd_set *p) -{ - unsigned long *tmp = (unsigned long *)p->fds_bits; - int i; - - if (__builtin_constant_p(__FDSET_LONGS)) { - switch (__FDSET_LONGS) { - case 16: - tmp[12] = 0; tmp[13] = 0; tmp[14] = 0; tmp[15] = 0; - tmp[ 8] = 0; tmp[ 9] = 0; tmp[10] = 0; tmp[11] = 0; - - case 8: - tmp[ 4] = 0; tmp[ 5] = 0; tmp[ 6] = 0; tmp[ 7] = 0; - - case 4: - tmp[ 0] = 0; tmp[ 1] = 0; tmp[ 2] = 0; tmp[ 3] = 0; - return; - } - } - i = __FDSET_LONGS; - while (i) { - i--; - *tmp = 0; - tmp++; - } -} - -#endif /* defined(__KERNEL__) || !defined(__GLIBC__) || (__GLIBC__ < 2) */ -#endif /* __GNUC__ */ -#endif /* _PPC64_POSIX_TYPES_H */ From jimix at watson.ibm.com Sat Sep 10 08:16:59 2005 From: jimix at watson.ibm.com (Jimi Xenidis) Date: Fri, 9 Sep 2005 18:16:59 -0400 Subject: [PATCH] Use PLATFORM_LPAR rather than PLATFORM_PSERIES_LPAR Message-ID: <17186.2523.359820.285461@kitch0.watson.ibm.com> Since processor.h defines a PLATFORM_LPAR bit, it would be better to use the bit rather than the pSeries value to detect generic LPAR. This patch allows for a both furure PLATFORM_[MAPLE|CELL]_LPAR platforms to share PSERIES_LPAR code. Signed-off-by: Jimi Xenidis diff -r b8c644fc851a arch/ppc64/kernel/prom.c --- a/arch/ppc64/kernel/prom.c Fri Sep 9 17:45:35 2005 +++ b/arch/ppc64/kernel/prom.c Fri Sep 9 18:08:38 2005 @@ -1004,7 +1004,7 @@ /* On LPAR, look for the first ibm,pft-size property for the hash table size */ - if (systemcfg->platform == PLATFORM_PSERIES_LPAR && ppc64_pft_size == 0) { + if ((systemcfg->platform & PLATFORM_LPAR) && ppc64_pft_size == 0) { u32 *pft_size; pft_size = (u32 *)get_flat_dt_prop(node, "ibm,pft-size", NULL); if (pft_size != NULL) { diff -r b8c644fc851a arch/ppc64/kernel/prom_init.c --- a/arch/ppc64/kernel/prom_init.c Fri Sep 9 17:45:35 2005 +++ b/arch/ppc64/kernel/prom_init.c Fri Sep 9 18:08:38 2005 @@ -888,7 +888,7 @@ * Setup our top alloc point, that is top of RMO or top of * segment 0 when running non-LPAR. */ - if ( RELOC(of_platform) == PLATFORM_PSERIES_LPAR ) + if ( RELOC(of_platform) & PLATFORM_LPAR ) RELOC(alloc_top) = RELOC(rmo_top); else /* Some RS64 machines have buggy firmware where claims up at 1GB diff -r b8c644fc851a arch/ppc64/kernel/rtas.c --- a/arch/ppc64/kernel/rtas.c Fri Sep 9 17:45:35 2005 +++ b/arch/ppc64/kernel/rtas.c Fri Sep 9 18:08:38 2005 @@ -747,7 +747,7 @@ */ if (rtas.dev) { unsigned long rtas_region = RTAS_INSTANTIATE_MAX; - if (systemcfg->platform == PLATFORM_PSERIES_LPAR) + if (systemcfg->platform & PLATFORM_LPAR) rtas_region = min(lmb.rmo_size, RTAS_INSTANTIATE_MAX); rtas_rmo_buf = lmb_alloc_base(RTAS_RMOBUF_MAX, PAGE_SIZE, diff -r b8c644fc851a arch/ppc64/kernel/xics.c --- a/arch/ppc64/kernel/xics.c Fri Sep 9 17:45:35 2005 +++ b/arch/ppc64/kernel/xics.c Fri Sep 9 18:08:38 2005 @@ -561,7 +561,7 @@ #else xics_per_cpu[0] = ioremap(intr_base, intr_size); #endif /* CONFIG_SMP */ - } else if (systemcfg->platform == PLATFORM_PSERIES_LPAR) { + } else if (systemcfg->platform & PLATFORM_LPAR) { ops = &pSeriesLP_ops; } From benh at kernel.crashing.org Sat Sep 10 08:19:54 2005 From: benh at kernel.crashing.org (Benjamin Herrenschmidt) Date: Sat, 10 Sep 2005 08:19:54 +1000 Subject: cpu features testing 32 vs 64 bit In-Reply-To: References: <200509090008.39692.pantelis.antoniou@gmail.com> Message-ID: <1126304395.29803.52.camel@gaston> > > I think she lost the I in ICACHE... its a power5 only feature at this > point. And good old 601 too :) It has a unified cache. We could make a common feature bit for these. Ben. From torvalds at osdl.org Sat Sep 10 09:12:55 2005 From: torvalds at osdl.org (Linus Torvalds) Date: Fri, 9 Sep 2005 16:12:55 -0700 (PDT) Subject: Please pull ppc64-2.6.git In-Reply-To: <17181.34373.982692.908365@cargo.ozlabs.ibm.com> References: <17181.34373.982692.908365@cargo.ozlabs.ibm.com> Message-ID: On Tue, 6 Sep 2005, Paul Mackerras wrote: > > There is another bunch of ppc64 updates in the usual place: Btw, I can't even begin to describe how much I hate the "include3" directory crap that was introduced recently. Not only is it incredibly ugly, it totally breaks filename completion, since doing a "grep incli" no longer completes properly to "include/linux/" like it should, and like God intended it to. Instead, it beeps at you, and generates a crappy "includeli" completion. If we can't get things to use , then can we at least move that frigging ugly directory somewhere else? Instead of using "include3" (what a totally horrible name - that should already have told somebody that it wasn't a good idea), why not use arch/$(ARCH)/include" instead? Linus From paulus at samba.org Sat Sep 10 10:07:50 2005 From: paulus at samba.org (Paul Mackerras) Date: Sat, 10 Sep 2005 10:07:50 +1000 Subject: Please pull ppc64-2.6.git In-Reply-To: References: <17181.34373.982692.908365@cargo.ozlabs.ibm.com> Message-ID: <17186.9174.738507.424472@cargo.ozlabs.ibm.com> Linus Torvalds writes: > Btw, I can't even begin to describe how much I hate the "include3" > directory crap that was introduced recently. > > Not only is it incredibly ugly, it totally breaks filename completion, > since doing a "grep incli" no longer completes properly to > "include/linux/" like it should, and like God intended it to. Instead, it > beeps at you, and generates a crappy "includeli" completion. Well, we already had an include2 directory that gets created if you compile with a separate object tree, so Stephen was just following that precedent. In any case, it's only temporary scaffolding until we get far enough along with the merge that we can set ARCH to "powerpc" instead of "ppc" or "ppc64". I wanted a way to be able to proceed with the merge bit by bit rather than having a flag day, and this seemed the best approach. We can easily change the name to something like "altinclude" (but then your a for arch breaks), or how about "otherinclude"? > If we can't get things to use , then can we at least move > that frigging ugly directory somewhere else? Instead of using "include3" > (what a totally horrible name - that should already have told somebody > that it wasn't a good idea), why not use arch/$(ARCH)/include" instead? I guess that would work too... Stephen? Paul. From sfr at canb.auug.org.au Sat Sep 10 11:15:47 2005 From: sfr at canb.auug.org.au (Stephen Rothwell) Date: Sat, 10 Sep 2005 11:15:47 +1000 (EST) Subject: Please pull ppc64-2.6.git Message-ID: <200509100115.j8A1Fl6l015542@supreme.pcug.org.au> From: Paul Mackerras > > Linus Torvalds writes: > > > Btw, I can't even begin to describe how much I hate the "include3" > > directory crap that was introduced recently. > > > > Not only is it incredibly ugly, it totally breaks filename completion, > > since doing a "grep incli" no longer completes properly to > > "include/linux/" like it should, and like God intended it to. Instead, it > > beeps at you, and generates a crappy "includeli" completion. > > Well, we already had an include2 directory that gets created if you > compile with a separate object tree, so Stephen was just following > that precedent. I can see Linus's point, though. I guess it never affected me because I don't build in my work tree. > > If we can't get things to use , then can we at least move > > that frigging ugly directory somewhere else? Instead of using "include3" > > (what a totally horrible name - that should already have told somebody > > that it wasn't a good idea), why not use arch/$(ARCH)/include" instead? > > I guess that would work too... Stephen? I'll see if I can get something like arch/$(ARCH)/include to work. Cheers, Stephen Rothwell From dwg at au1.ibm.com Sat Sep 10 10:20:35 2005 From: dwg at au1.ibm.com (David Gibson) Date: Sat, 10 Sep 2005 10:20:35 +1000 Subject: [PATCH] Use PLATFORM_LPAR rather than PLATFORM_PSERIES_LPAR In-Reply-To: <17186.2523.359820.285461@kitch0.watson.ibm.com> References: <17186.2523.359820.285461@kitch0.watson.ibm.com> Message-ID: <20050910002035.GH31045@localhost.localdomain> On Fri, Sep 09, 2005 at 06:16:59PM -0400, Jimi Xenidis wrote: > > Since processor.h defines a PLATFORM_LPAR bit, it would be better to > use the bit rather than the pSeries value to detect generic LPAR. > This patch allows for a both furure PLATFORM_[MAPLE|CELL]_LPAR > platforms to share PSERIES_LPAR code. I think we would be better off using new firmware_has_feature() bits for this. It takes us a step closer to a kernel which can boot both pSeries and iSeries and a step closer to getting rid of the magic platform numbers entirely. -- 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 Sat Sep 10 16:01:08 2005 From: anton at samba.org (Anton Blanchard) Date: Sat, 10 Sep 2005 16:01:08 +1000 Subject: [patch 2/5] ppc64: ptrace cleanups References: <20050910060106.021913000@samba.org> Message-ID: <20050910060118.791393000@samba.org> - Remove the PPC_REG* defines - Wrap some more stuff with ifdef __KERNEL__ - Add missing PT_TRAP, PT_DAR, PT_DSISR defines - Add PTRACE_GETEVRREGS/PTRACE_SETEVRREGS, even though we dont use it on ppc64 we dont want to allocate them for something else. Signed-off-by: Anton Blanchard --- Index: build/include/asm-ppc64/ptrace.h =================================================================== --- build.orig/include/asm-ppc64/ptrace.h 2005-09-10 14:24:43.000000000 +1000 +++ build/include/asm-ppc64/ptrace.h 2005-09-10 14:26:22.000000000 +1000 @@ -25,56 +25,49 @@ */ #ifndef __ASSEMBLY__ -#define PPC_REG unsigned long + struct pt_regs { - PPC_REG gpr[32]; - PPC_REG nip; - PPC_REG msr; - PPC_REG orig_gpr3; /* Used for restarting system calls */ - PPC_REG ctr; - PPC_REG link; - PPC_REG xer; - PPC_REG ccr; - PPC_REG softe; /* Soft enabled/disabled */ - PPC_REG trap; /* Reason for being here */ - PPC_REG dar; /* Fault registers */ - PPC_REG dsisr; - PPC_REG result; /* Result of a system call */ + unsigned long gpr[32]; + unsigned long nip; + unsigned long msr; + unsigned long orig_gpr3; /* Used for restarting system calls */ + unsigned long ctr; + unsigned long link; + unsigned long xer; + unsigned long ccr; + unsigned long softe; /* Soft enabled/disabled */ + unsigned long trap; /* Reason for being here */ + unsigned long dar; /* Fault registers */ + unsigned long dsisr; + unsigned long result; /* Result of a system call */ }; -#define PPC_REG_32 unsigned int struct pt_regs32 { - PPC_REG_32 gpr[32]; - PPC_REG_32 nip; - PPC_REG_32 msr; - PPC_REG_32 orig_gpr3; /* Used for restarting system calls */ - PPC_REG_32 ctr; - PPC_REG_32 link; - PPC_REG_32 xer; - PPC_REG_32 ccr; - PPC_REG_32 mq; /* 601 only (not used at present) */ - /* Used on APUS to hold IPL value. */ - PPC_REG_32 trap; /* Reason for being here */ - PPC_REG_32 dar; /* Fault registers */ - PPC_REG_32 dsisr; - PPC_REG_32 result; /* Result of a system call */ + unsigned int gpr[32]; + unsigned int nip; + unsigned int msr; + unsigned int orig_gpr3; /* Used for restarting system calls */ + unsigned int ctr; + unsigned int link; + unsigned int xer; + unsigned int ccr; + unsigned int mq; /* 601 only (not used at present) */ + unsigned int trap; /* Reason for being here */ + unsigned int dar; /* Fault registers */ + unsigned int dsisr; + unsigned int result; /* Result of a system call */ }; +#ifdef __KERNEL__ + #define instruction_pointer(regs) ((regs)->nip) + #ifdef CONFIG_SMP extern unsigned long profile_pc(struct pt_regs *regs); #else #define profile_pc(regs) instruction_pointer(regs) #endif -#endif /* __ASSEMBLY__ */ - -#define STACK_FRAME_OVERHEAD 112 /* size of minimum stack frame */ - -/* Size of dummy stack frame allocated when calling signal handler. */ -#define __SIGNAL_FRAMESIZE 128 -#define __SIGNAL_FRAMESIZE32 64 - #define user_mode(regs) ((((regs)->msr) >> MSR_PR_LG) & 0x1) #define force_successful_syscall_return() \ @@ -89,6 +82,16 @@ #define TRAP(regs) ((regs)->trap & ~0xF) #define CHECK_FULL_REGS(regs) BUG_ON(regs->trap & 1) +#endif /* __KERNEL__ */ + +#endif /* __ASSEMBLY__ */ + +#define STACK_FRAME_OVERHEAD 112 /* size of minimum stack frame */ + +/* Size of dummy stack frame allocated when calling signal handler. */ +#define __SIGNAL_FRAMESIZE 128 +#define __SIGNAL_FRAMESIZE32 64 + /* * Offsets used by 'ptrace' system call interface. */ @@ -135,17 +138,21 @@ #define PT_XER 37 #define PT_CCR 38 #define PT_SOFTE 39 +#define PT_TRAP 40 +#define PT_DAR 41 +#define PT_DSISR 42 #define PT_RESULT 43 #define PT_FPR0 48 -/* Kernel and userspace will both use this PT_FPSCR value. 32-bit apps will have - * visibility to the asm-ppc/ptrace.h header instead of this one. +/* + * Kernel and userspace will both use this PT_FPSCR value. 32-bit apps will + * have visibility to the asm-ppc/ptrace.h header instead of this one. */ -#define PT_FPSCR (PT_FPR0 + 32) /* each FP reg occupies 1 slot in 64-bit space */ +#define PT_FPSCR (PT_FPR0 + 32) /* each FP reg occupies 1 slot in 64-bit space */ #ifdef __KERNEL__ -#define PT_FPSCR32 (PT_FPR0 + 2*32 + 1) /* each FP reg occupies 2 32-bit userspace slots */ +#define PT_FPSCR32 (PT_FPR0 + 2*32 + 1) /* each FP reg occupies 2 32-bit userspace slots */ #endif #define PT_VR0 82 /* each Vector reg occupies 2 slots in 64-bit */ @@ -173,17 +180,27 @@ #define PTRACE_GETVRREGS 18 #define PTRACE_SETVRREGS 19 -/* Additional PTRACE requests implemented on PowerPC. */ -#define PPC_PTRACE_GETREGS 0x99 /* Get GPRs 0 - 31 */ -#define PPC_PTRACE_SETREGS 0x98 /* Set GPRs 0 - 31 */ -#define PPC_PTRACE_GETFPREGS 0x97 /* Get FPRs 0 - 31 */ -#define PPC_PTRACE_SETFPREGS 0x96 /* Set FPRs 0 - 31 */ -#define PPC_PTRACE_PEEKTEXT_3264 0x95 /* Read word at location ADDR on a 64-bit process from a 32-bit process. */ -#define PPC_PTRACE_PEEKDATA_3264 0x94 /* Read word at location ADDR on a 64-bit process from a 32-bit process. */ -#define PPC_PTRACE_POKETEXT_3264 0x93 /* Write word at location ADDR on a 64-bit process from a 32-bit process. */ -#define PPC_PTRACE_POKEDATA_3264 0x92 /* Write word at location ADDR on a 64-bit process from a 32-bit process. */ -#define PPC_PTRACE_PEEKUSR_3264 0x91 /* Read a register (specified by ADDR) out of the "user area" on a 64-bit process from a 32-bit process. */ -#define PPC_PTRACE_POKEUSR_3264 0x90 /* Write DATA into location ADDR within the "user area" on a 64-bit process from a 32-bit process. */ +/* + * While we dont have 64bit book E processors, we need to reserve the + * relevant ptrace calls for 32bit compatibility. + */ +#if 0 +#define PTRACE_GETEVRREGS 20 +#define PTRACE_SETEVRREGS 21 +#endif +/* Additional PTRACE requests implemented on PowerPC. */ +#define PPC_PTRACE_GETREGS 0x99 /* Get GPRs 0 - 31 */ +#define PPC_PTRACE_SETREGS 0x98 /* Set GPRs 0 - 31 */ +#define PPC_PTRACE_GETFPREGS 0x97 /* Get FPRs 0 - 31 */ +#define PPC_PTRACE_SETFPREGS 0x96 /* Set FPRs 0 - 31 */ + +/* Calls to trace a 64bit program from a 32bit program */ +#define PPC_PTRACE_PEEKTEXT_3264 0x95 +#define PPC_PTRACE_PEEKDATA_3264 0x94 +#define PPC_PTRACE_POKETEXT_3264 0x93 +#define PPC_PTRACE_POKEDATA_3264 0x92 +#define PPC_PTRACE_PEEKUSR_3264 0x91 +#define PPC_PTRACE_POKEUSR_3264 0x90 #endif /* _PPC64_PTRACE_H */ -- From anton at samba.org Sat Sep 10 16:01:09 2005 From: anton at samba.org (Anton Blanchard) Date: Sat, 10 Sep 2005 16:01:09 +1000 Subject: [patch 3/5] ppc64: Fix up some whitespace issues in ptrace32.c References: <20050910060106.021913000@samba.org> Message-ID: <20050910060119.034008000@samba.org> Fix up some whitespace issues in ptrace32.c Signed-off-by: Anton Blanchard --- Index: build/arch/ppc64/kernel/ptrace32.c =================================================================== --- build.orig/arch/ppc64/kernel/ptrace32.c 2005-09-10 13:29:48.000000000 +1000 +++ build/arch/ppc64/kernel/ptrace32.c 2005-09-10 13:29:52.000000000 +1000 @@ -406,9 +406,9 @@ break; } - case PTRACE_GETEVENTMSG: - ret = put_user(child->ptrace_message, (unsigned int __user *) data); - break; + case PTRACE_GETEVENTMSG: + ret = put_user(child->ptrace_message, (unsigned int __user *) data); + break; #ifdef CONFIG_ALTIVEC case PTRACE_GETVRREGS: -- From anton at samba.org Sat Sep 10 16:01:10 2005 From: anton at samba.org (Anton Blanchard) Date: Sat, 10 Sep 2005 16:01:10 +1000 Subject: [patch 4/5] ppc64: Add definitions for new PTRACE calls References: <20050910060106.021913000@samba.org> Message-ID: <20050910060119.276430000@samba.org> - Add PTRACE_BRANCHSTEP. Like PTRACE_SINGLESTEP but takes an exception at every branch. This might be worth putting in include/linux/ptrace.h if other architectures are interested. - Add PTRACE_GET_DEBUGREG/PTRACE_SET_DEBUGREG. The definition is as follows: /* * Get or set a debug register. The first 16 are DABR registers and the * second 16 are IABR registers. */ #define PTRACE_GET_DEBUGREG 25 #define PTRACE_SET_DEBUGREG 26 DABR == data breakpoint and IABR = instruction breakpoint in IBM speak. We could split out the IABR into 2 more ptrace calls but I figured there was no need and 16 DABR registers should be more than enough (POWER4/POWER5 have one). - Add 2 new SIGTRAP si_codes: TRAP_HWBKPT and TRAP_BRANCH. I couldnt find any standards on either of these so I copied what ia64 is doing. Again this might be better placed in include/asm-generic/siginfo.h Signed-off-by: Anton Blanchard --- Index: build/include/asm-ppc/ptrace.h =================================================================== --- build.orig/include/asm-ppc/ptrace.h 2005-09-10 14:26:25.000000000 +1000 +++ build/include/asm-ppc/ptrace.h 2005-09-10 14:27:49.000000000 +1000 @@ -142,4 +142,13 @@ #define PTRACE_GETEVRREGS 20 #define PTRACE_SETEVRREGS 21 +#define PTRACE_BRANCHSTEP 22 + +/* + * Get or set a debug register. The first 16 are DABR registers and the + * second 16 are IABR registers. + */ +#define PTRACE_GET_DEBUGREG 25 +#define PTRACE_SET_DEBUGREG 26 + #endif Index: build/include/asm-ppc64/ptrace.h =================================================================== --- build.orig/include/asm-ppc64/ptrace.h 2005-09-10 14:28:44.000000000 +1000 +++ build/include/asm-ppc64/ptrace.h 2005-09-10 14:28:58.000000000 +1000 @@ -189,6 +189,15 @@ #define PTRACE_SETEVRREGS 21 #endif +#define PTRACE_BRANCHSTEP 22 + +/* + * Get or set a debug register. The first 16 are DABR registers and the + * second 16 are IABR registers. + */ +#define PTRACE_GET_DEBUGREG 25 +#define PTRACE_SET_DEBUGREG 26 + /* Additional PTRACE requests implemented on PowerPC. */ #define PPC_PTRACE_GETREGS 0x99 /* Get GPRs 0 - 31 */ #define PPC_PTRACE_SETREGS 0x98 /* Set GPRs 0 - 31 */ Index: build/include/asm-powerpc/siginfo.h =================================================================== --- build.orig/include/asm-powerpc/siginfo.h 2005-09-10 13:29:48.000000000 +1000 +++ build/include/asm-powerpc/siginfo.h 2005-09-10 13:29:54.000000000 +1000 @@ -15,4 +15,12 @@ #include +/* + * SIGTRAP si_codes + */ +#define TRAP_BRANCH (__SI_FAULT|3) /* process taken branch trap */ +#define TRAP_HWBKPT (__SI_FAULT|4) /* hardware breakpoint or watchpoint */ +#undef NSIGTRAP +#define NSIGTRAP 4 + #endif /* _ASM_POWERPC_SIGINFO_H */ -- From anton at samba.org Sat Sep 10 16:01:11 2005 From: anton at samba.org (Anton Blanchard) Date: Sat, 10 Sep 2005 16:01:11 +1000 Subject: [patch 5/5] ppc64: Add ptrace data breakpoint support References: <20050910060106.021913000@samba.org> Message-ID: <20050910060119.519387000@samba.org> Add hardware data breakpoint support. Signed-off-by: Anton Blanchard --- Index: build/arch/ppc64/kernel/process.c =================================================================== --- build.orig/arch/ppc64/kernel/process.c 2005-09-10 15:35:41.000000000 +1000 +++ build/arch/ppc64/kernel/process.c 2005-09-10 15:52:32.000000000 +1000 @@ -54,6 +54,7 @@ #include #include #include +#include #ifndef CONFIG_SMP struct task_struct *last_task_used_math = NULL; @@ -163,7 +164,30 @@ #endif /* CONFIG_ALTIVEC */ +static void set_dabr_spr(unsigned long val) +{ + mtspr(SPRN_DABR, val); +} + +int set_dabr(unsigned long dabr) +{ + int ret = 0; + + if (firmware_has_feature(FW_FEATURE_XDABR)) { + /* We want to catch accesses from kernel and userspace */ + unsigned long flags = H_DABRX_KERNEL|H_DABRX_USER; + ret = plpar_set_xdabr(dabr, flags); + } else if (firmware_has_feature(FW_FEATURE_DABR)) { + ret = plpar_set_dabr(dabr); + } else { + set_dabr_spr(dabr); + } + + return ret; +} + DEFINE_PER_CPU(struct cpu_usage, cpu_usage_array); +static DEFINE_PER_CPU(unsigned long, current_dabr); struct task_struct *__switch_to(struct task_struct *prev, struct task_struct *new) @@ -198,6 +222,11 @@ new->thread.regs->msr |= MSR_VEC; #endif /* CONFIG_ALTIVEC */ + if (unlikely(__get_cpu_var(current_dabr) != new->thread.dabr)) { + set_dabr(new->thread.dabr); + __get_cpu_var(current_dabr) = new->thread.dabr; + } + flush_tlb_pending(); new_thread = &new->thread; @@ -334,6 +363,11 @@ last_task_used_altivec = NULL; #endif /* CONFIG_ALTIVEC */ #endif /* CONFIG_SMP */ + + if (current->thread.dabr) { + current->thread.dabr = 0; + set_dabr(0); + } } void Index: build/arch/ppc64/kernel/ptrace.c =================================================================== --- build.orig/arch/ppc64/kernel/ptrace.c 2005-09-10 15:36:01.000000000 +1000 +++ build/arch/ppc64/kernel/ptrace.c 2005-09-10 15:36:05.000000000 +1000 @@ -207,6 +207,19 @@ break; } + case PTRACE_GET_DEBUGREG: { + ret = -EINVAL; + /* We only support one DABR and no IABRS at the moment */ + if (addr > 0) + break; + ret = put_user(child->thread.dabr, + (unsigned long __user *)data); + break; + } + + case PTRACE_SET_DEBUGREG: + ret = ptrace_set_debugreg(child, addr, data); + case PTRACE_DETACH: ret = ptrace_detach(child, data); break; Index: build/arch/ppc64/kernel/ptrace32.c =================================================================== --- build.orig/arch/ppc64/kernel/ptrace32.c 2005-09-10 15:36:02.000000000 +1000 +++ build/arch/ppc64/kernel/ptrace32.c 2005-09-10 15:36:05.000000000 +1000 @@ -338,6 +338,19 @@ break; } + case PTRACE_GET_DEBUGREG: { + ret = -EINVAL; + /* We only support one DABR and no IABRS at the moment */ + if (addr > 0) + break; + ret = put_user(child->thread.dabr, (u32 __user *)data); + break; + } + + case PTRACE_SET_DEBUGREG: + ret = ptrace_set_debugreg(child, addr, data); + break; + case PTRACE_DETACH: ret = ptrace_detach(child, data); break; Index: build/include/asm-ppc64/processor.h =================================================================== --- build.orig/include/asm-ppc64/processor.h 2005-09-10 15:35:41.000000000 +1000 +++ build/include/asm-ppc64/processor.h 2005-09-10 15:36:02.000000000 +1000 @@ -433,6 +433,7 @@ unsigned long start_tb; /* Start purr when proc switched in */ unsigned long accum_tb; /* Total accumilated purr for process */ unsigned long vdso_base; /* base of the vDSO library */ + unsigned long dabr; /* Data address breakpoint register */ #ifdef CONFIG_ALTIVEC /* Complete AltiVec register set */ vector128 vr[32] __attribute((aligned(16))); Index: build/arch/ppc64/mm/fault.c =================================================================== --- build.orig/arch/ppc64/mm/fault.c 2005-09-10 15:35:41.000000000 +1000 +++ build/arch/ppc64/mm/fault.c 2005-09-10 15:36:02.000000000 +1000 @@ -77,6 +77,28 @@ return 0; } +static void do_dabr(struct pt_regs *regs, unsigned long error_code) +{ + siginfo_t info; + + if (notify_die(DIE_DABR_MATCH, "dabr_match", regs, error_code, + 11, SIGSEGV) == NOTIFY_STOP) + return; + + if (debugger_dabr_match(regs)) + return; + + /* Clear the DABR */ + set_dabr(0); + + /* Deliver the signal to userspace */ + info.si_signo = SIGTRAP; + info.si_errno = 0; + info.si_code = TRAP_HWBKPT; + info.si_addr = (void __user *)regs->nip; + force_sig_info(SIGTRAP, &info, current); +} + /* * The error_code parameter is * - DSISR for a non-SLB data access fault, @@ -111,12 +133,9 @@ if (!user_mode(regs) && (address >= TASK_SIZE)) return SIGSEGV; - if (error_code & DSISR_DABRMATCH) { - if (notify_die(DIE_DABR_MATCH, "dabr_match", regs, error_code, - 11, SIGSEGV) == NOTIFY_STOP) - return 0; - if (debugger_dabr_match(regs)) - return 0; + if (error_code & DSISR_DABRMATCH) { + do_dabr(regs, error_code); + return 0; } if (in_atomic() || mm == NULL) { Index: build/arch/ppc64/kernel/ras.c =================================================================== --- build.orig/arch/ppc64/kernel/ras.c 2005-09-10 15:35:41.000000000 +1000 +++ build/arch/ppc64/kernel/ras.c 2005-09-10 15:36:02.000000000 +1000 @@ -59,8 +59,6 @@ /* This is true if we are using the firmware NMI handler (typically LPAR) */ extern int fwnmi_active; -extern void _exception(int signr, struct pt_regs *regs, int code, unsigned long addr); - static int ras_get_sensor_state_token; static int ras_check_exception_token; Index: build/include/asm-ppc64/system.h =================================================================== --- build.orig/include/asm-ppc64/system.h 2005-09-10 15:35:41.000000000 +1000 +++ build/include/asm-ppc64/system.h 2005-09-10 15:36:02.000000000 +1000 @@ -101,6 +101,9 @@ static inline int debugger_fault_handler(struct pt_regs *regs) { return 0; } #endif +extern int set_dabr(unsigned long dabr); +extern void _exception(int signr, struct pt_regs *regs, int code, + unsigned long addr); extern int fix_alignment(struct pt_regs *regs); extern void bad_page_fault(struct pt_regs *regs, unsigned long address, int sig); Index: build/include/asm-ppc64/ptrace-common.h =================================================================== --- build.orig/include/asm-ppc64/ptrace-common.h 2005-09-10 15:36:01.000000000 +1000 +++ build/include/asm-ppc64/ptrace-common.h 2005-09-10 15:36:05.000000000 +1000 @@ -13,6 +13,7 @@ #define _PPC64_PTRACE_COMMON_H #include +#include /* * Set of msr bits that gdb can change on behalf of a process. @@ -141,4 +142,23 @@ } #endif +static inline int ptrace_set_debugreg(struct task_struct *task, + unsigned long addr, unsigned long data) +{ + /* We only support one DABR and no IABRS at the moment */ + if (addr > 0) + return -EINVAL; + + /* The bottom 3 bits are flags */ + if ((data & ~0x7UL) >= TASK_SIZE) + return -EIO; + + /* Ensure translation is on */ + if (data && !(data & DABR_TRANSLATION)) + return -EIO; + + task->thread.dabr = data; + return 0; +} + #endif /* _PPC64_PTRACE_COMMON_H */ Index: build/arch/ppc64/xmon/privinst.h =================================================================== --- build.orig/arch/ppc64/xmon/privinst.h 2005-09-10 15:35:41.000000000 +1000 +++ build/arch/ppc64/xmon/privinst.h 2005-09-10 15:36:02.000000000 +1000 @@ -46,7 +46,6 @@ GSETSPR(1008, hid0) GSETSPR(1009, hid1) GSETSPR(1010, iabr) -GSETSPR(1013, dabr) GSETSPR(1023, pir) static inline void store_inst(void *p) Index: build/arch/ppc64/xmon/xmon.c =================================================================== --- build.orig/arch/ppc64/xmon/xmon.c 2005-09-10 15:35:41.000000000 +1000 +++ build/arch/ppc64/xmon/xmon.c 2005-09-10 15:36:02.000000000 +1000 @@ -586,6 +586,8 @@ { if ((regs->msr & (MSR_IR|MSR_PR|MSR_SF)) != (MSR_IR|MSR_SF)) return 0; + if (dabr.enabled == 0) + return 0; xmon_core(regs, 0); return 1; } @@ -628,20 +630,6 @@ return 0; } -/* On systems with a hypervisor, we can't set the DABR - (data address breakpoint register) directly. */ -static void set_controlled_dabr(unsigned long val) -{ -#ifdef CONFIG_PPC_PSERIES - if (systemcfg->platform == PLATFORM_PSERIES_LPAR) { - int rc = plpar_hcall_norets(H_SET_DABR, val); - if (rc != H_Success) - xmon_printf("Warning: setting DABR failed (%d)\n", rc); - } else -#endif - set_dabr(val); -} - static struct bpt *at_breakpoint(unsigned long pc) { int i; @@ -728,7 +716,7 @@ static void insert_cpu_bpts(void) { if (dabr.enabled) - set_controlled_dabr(dabr.address | (dabr.enabled & 7)); + set_dabr(dabr.address | (dabr.enabled & 7)); if (iabr && cpu_has_feature(CPU_FTR_IABR)) set_iabr(iabr->address | (iabr->enabled & (BP_IABR|BP_IABR_TE))); @@ -756,7 +744,7 @@ static void remove_cpu_bpts(void) { - set_controlled_dabr(0); + set_dabr(0); if (cpu_has_feature(CPU_FTR_IABR)) set_iabr(0); } Index: build/include/asm-ppc64/hvcall.h =================================================================== --- build.orig/include/asm-ppc64/hvcall.h 2005-09-10 15:35:41.000000000 +1000 +++ build/include/asm-ppc64/hvcall.h 2005-09-10 15:36:02.000000000 +1000 @@ -56,6 +56,11 @@ #define H_PP1 (1UL<<(63-62)) #define H_PP2 (1UL<<(63-63)) +/* DABRX flags */ +#define H_DABRX_HYPERVISOR (1UL<<(63-61)) +#define H_DABRX_KERNEL (1UL<<(63-62)) +#define H_DABRX_USER (1UL<<(63-63)) + /* pSeries hypervisor opcodes */ #define H_REMOVE 0x04 #define H_ENTER 0x08 @@ -101,6 +106,7 @@ #define H_VIO_SIGNAL 0x104 #define H_SEND_CRQ 0x108 #define H_COPY_RDMA 0x110 +#define H_SET_XDABR 0x134 #define H_STUFF_TCE 0x138 #define H_PUT_TCE_INDIRECT 0x13C #define H_VTERM_PARTNER_INFO 0x150 Index: build/include/asm-ppc64/plpar_wrappers.h =================================================================== --- build.orig/include/asm-ppc64/plpar_wrappers.h 2005-09-10 15:35:41.000000000 +1000 +++ build/include/asm-ppc64/plpar_wrappers.h 2005-09-10 15:36:02.000000000 +1000 @@ -107,5 +107,14 @@ lbuf[1]); } +static inline long plpar_set_xdabr(unsigned long address, unsigned long flags) +{ + return plpar_hcall_norets(H_SET_XDABR, address, flags); +} + +static inline long plpar_set_dabr(unsigned long val) +{ + return plpar_hcall_norets(H_SET_DABR, val); +} #endif /* _PPC64_PLPAR_WRAPPERS_H */ Index: build/arch/ppc64/kernel/signal.c =================================================================== --- build.orig/arch/ppc64/kernel/signal.c 2005-09-10 15:35:41.000000000 +1000 +++ build/arch/ppc64/kernel/signal.c 2005-09-10 15:36:02.000000000 +1000 @@ -550,6 +550,15 @@ /* Whee! Actually deliver the signal. */ if (TRAP(regs) == 0x0C00) syscall_restart(regs, &ka); + + /* + * Reenable the DABR before delivering the signal to + * user space. The DABR will have been cleared if it + * triggered inside the kernel. + */ + if (current->thread.dabr) + set_dabr(current->thread.dabr); + return handle_signal(signr, &ka, &info, oldset, regs); } Index: build/arch/ppc64/kernel/signal32.c =================================================================== --- build.orig/arch/ppc64/kernel/signal32.c 2005-09-10 15:35:41.000000000 +1000 +++ build/arch/ppc64/kernel/signal32.c 2005-09-10 15:36:02.000000000 +1000 @@ -970,6 +970,14 @@ newsp = regs->gpr[1]; newsp &= ~0xfUL; + /* + * Reenable the DABR before delivering the signal to + * user space. The DABR will have been cleared if it + * triggered inside the kernel. + */ + if (current->thread.dabr) + set_dabr(current->thread.dabr); + /* Whee! Actually deliver the signal. */ if (ka.sa.sa_flags & SA_SIGINFO) ret = handle_rt_signal32(signr, &ka, &info, oldset, regs, newsp); -- From anton at samba.org Sat Sep 10 16:01:06 2005 From: anton at samba.org (Anton Blanchard) Date: Sat, 10 Sep 2005 16:01:06 +1000 Subject: [patch 0/5] ppc64 ptrace update Message-ID: <20050910060106.021913000@samba.org> Here are some patches that update our ppc64 ptrace code. In particular it adds altivec support and hardware data breakpoint support. -- From anton at samba.org Sat Sep 10 16:01:07 2005 From: anton at samba.org (Anton Blanchard) Date: Sat, 10 Sep 2005 16:01:07 +1000 Subject: [patch 1/5] ppc64: Add PTRACE_{GET|SET}VRREGS References: <20050910060106.021913000@samba.org> Message-ID: <20050910060118.551754000@samba.org> From: Robert Jennings 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. Updated with the suggestions from Anton following the lines of his code snippet. Added: - flush_altivec_to_thread calls as suggested by Anton - piecewise copy of structure to preserve 32-bit vrsave data as per Anton (I consolidated the 32 and 64bit versions with 2 helper macros - Anton) Signed-off-by: Robert C Jennings Signed-off-by: Anton Blanchard --- Index: build/arch/ppc64/kernel/ptrace32.c =================================================================== --- build.orig/arch/ppc64/kernel/ptrace32.c 2005-09-10 12:40:54.000000000 +1000 +++ build/arch/ppc64/kernel/ptrace32.c 2005-09-10 13:29:48.000000000 +1000 @@ -17,6 +17,7 @@ * this archive for more details. */ +#include #include #include #include @@ -409,6 +410,20 @@ ret = put_user(child->ptrace_message, (unsigned int __user *) data); break; +#ifdef CONFIG_ALTIVEC + case PTRACE_GETVRREGS: + /* Get the child altivec register state. */ + flush_altivec_to_thread(child); + ret = get_vrregs((unsigned long __user *)data, child); + break; + + case PTRACE_SETVRREGS: + /* Set the child altivec register state. */ + flush_altivec_to_thread(child); + ret = set_vrregs(child, (unsigned long __user *)data); + break; +#endif + default: ret = ptrace_request(child, request, addr, data); break; Index: build/arch/ppc64/kernel/ptrace.c =================================================================== --- build.orig/arch/ppc64/kernel/ptrace.c 2005-09-10 12:40:54.000000000 +1000 +++ build/arch/ppc64/kernel/ptrace.c 2005-09-10 13:29:48.000000000 +1000 @@ -17,6 +17,7 @@ * this archive for more details. */ +#include #include #include #include @@ -274,6 +275,20 @@ break; } +#ifdef CONFIG_ALTIVEC + case PTRACE_GETVRREGS: + /* Get the child altivec register state. */ + flush_altivec_to_thread(child); + ret = get_vrregs((unsigned long __user *)data, child); + break; + + case PTRACE_SETVRREGS: + /* Set the child altivec register state. */ + flush_altivec_to_thread(child); + ret = set_vrregs(child, (unsigned long __user *)data); + break; +#endif + default: ret = ptrace_request(child, request, addr, data); break; Index: build/include/asm-ppc64/ptrace-common.h =================================================================== --- build.orig/include/asm-ppc64/ptrace-common.h 2005-09-10 12:40:58.000000000 +1000 +++ build/include/asm-ppc64/ptrace-common.h 2005-09-10 13:29:48.000000000 +1000 @@ -11,6 +11,9 @@ #ifndef _PPC64_PTRACE_COMMON_H #define _PPC64_PTRACE_COMMON_H + +#include + /* * Set of msr bits that gdb can change on behalf of a process. */ @@ -69,4 +72,73 @@ clear_ti_thread_flag(task->thread_info, TIF_SINGLESTEP); } +#ifdef CONFIG_ALTIVEC +/* + * 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. + */ + +/* + * Get contents of AltiVec register state in task TASK + */ +static inline int get_vrregs(unsigned long __user *data, + struct task_struct *task) +{ + unsigned long regsize; + + /* copy AltiVec registers VR[0] .. VR[31] */ + regsize = 32 * sizeof(vector128); + if (copy_to_user(data, task->thread.vr, regsize)) + return -EFAULT; + data += (regsize / sizeof(unsigned long)); + + /* copy VSCR */ + regsize = 1 * sizeof(vector128); + if (copy_to_user(data, &task->thread.vscr, regsize)) + return -EFAULT; + data += (regsize / sizeof(unsigned long)); + + /* copy VRSAVE */ + if (put_user(task->thread.vrsave, (u32 __user *)data)) + return -EFAULT; + + return 0; +} + +/* + * Write contents of AltiVec register state into task TASK. + */ +static inline int set_vrregs(struct task_struct *task, + unsigned long __user *data) +{ + 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; + + return 0; +} +#endif + #endif /* _PPC64_PTRACE_COMMON_H */ -- From sfr at canb.auug.org.au Sat Sep 10 20:12:22 2005 From: sfr at canb.auug.org.au (Stephen Rothwell) Date: Sat, 10 Sep 2005 20:12:22 +1000 Subject: PATCH ppc Merge asm-ppc*/posix_types.h In-Reply-To: References: Message-ID: <20050910201222.6861b172.sfr@canb.auug.org.au> On Fri, 09 Sep 2005 16:43:52 -0500 jdl at freescale.com wrote: > > +#ifdef __powerpc64__ > +typedef unsigned long __kernel_nlink_t; > +typedef int __kernel_ipc_pid_t; > +typedef unsigned long __kernel_size_t; > +typedef long __kernel_ssize_t; > +typedef unsigned long __kernel_old_dev_t; > +#else > +typedef unsigned short __kernel_nlink_t; > +typedef short __kernel_ipc_pid_t; > +typedef unsigned int __kernel_size_t; > +typedef int __kernel_ssize_t; > +typedef unsigned int __kernel_old_dev_t; > +#endif On 32 bit, int == long, so the last three could be removed from the ifdef by making them {unsigned }long ... -- 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/20050910/04f758ec/attachment.pgp From schwab at suse.de Sat Sep 10 20:33:35 2005 From: schwab at suse.de (Andreas Schwab) Date: Sat, 10 Sep 2005 12:33:35 +0200 Subject: [patch 4/5] ppc64: Add definitions for new PTRACE calls In-Reply-To: <20050910060119.276430000@samba.org> (Anton Blanchard's message of "Sat, 10 Sep 2005 16:01:10 +1000") References: <20050910060106.021913000@samba.org> <20050910060119.276430000@samba.org> Message-ID: Anton Blanchard writes: > - Add PTRACE_BRANCHSTEP. Like PTRACE_SINGLESTEP but takes an > exception at every branch. This might be worth putting in > include/linux/ptrace.h if other architectures are interested. That would be useful at least for m68k. Andreas. -- Andreas Schwab, SuSE Labs, schwab at suse.de SuSE Linux Products GmbH, Maxfeldstra?e 5, 90409 N?rnberg, Germany Key fingerprint = 58CA 54C7 6D53 942B 1756 01D3 44D5 214B 8276 4ED5 "And now for something completely different." From jdl at freescale.com Sat Sep 10 22:52:11 2005 From: jdl at freescale.com (jdl at freescale.com) Date: Sat, 10 Sep 2005 07:52:11 -0500 Subject: PATCH ppc Merge asm-ppc*/posix_types.h Message-ID: > On Fri, 09 Sep 2005 16:43:52 -0500 jdl at freescale.com wrote: > > > > +#ifdef __powerpc64__ > > +typedef unsigned long __kernel_nlink_t; > > +typedef int __kernel_ipc_pid_t; > > +typedef unsigned long __kernel_size_t; > > +typedef long __kernel_ssize_t; > > +typedef unsigned long __kernel_old_dev_t; > > +#else > > +typedef unsigned short __kernel_nlink_t; > > +typedef short __kernel_ipc_pid_t; > > +typedef unsigned int __kernel_size_t; > > +typedef int __kernel_ssize_t; > > +typedef unsigned int __kernel_old_dev_t; > > +#endif > > On 32 bit, int == long, so the last three could be removed from the ifdef > by making them {unsigned }long ... Yeah, I tried that too. In the ppc32 tree, it just starts looking nasty all over the place: CC drivers/pci/pci-driver.o fs/proc/base.c: In function `seccomp_write': fs/proc/base.c:932: warning: comparison of distinct pointer types lacks a cast net/sunrpc/svcsock.c: In function `svc_sendto': net/sunrpc/svcsock.c:424: warning: unsigned int format, size_t arg (arg 4) net/sunrpc/svcsock.c: In function `svc_recvfrom': net/sunrpc/svcsock.c:477: warning: unsigned int format, size_t arg (arg 4) Lots of others just like it: CC lib/klist.o net/core/dev.c: In function `dev_ifsioc': net/core/dev.c:2293: warning: comparison of distinct pointer types lacks a cast net/core/dev.c:2304: warning: comparison of distinct pointer types lacks a cast Pick your favorite subsystem! :-) I opted to maintain current breakage rather than try to fix anything and introduce new breakage. :-) I think that the approach we're taking here of placing the related-but-differing-by-a-__powerpc64__ concepts as close to each other as possible is a good one. In particular it calls attention to it, and causes people to wonder "Why is _that_ there? Why don't we just combine it like so..." And we probably should. It is just biting off more than we likely should at this step. Later, yes. jdl PS -Sorry about breaking threading; different MUA here. From paulus at samba.org Sat Sep 10 23:30:35 2005 From: paulus at samba.org (Paul Mackerras) Date: Sat, 10 Sep 2005 23:30:35 +1000 Subject: PATCH ppc Merge asm-ppc*/posix_types.h In-Reply-To: <20050910201222.6861b172.sfr@canb.auug.org.au> References: <20050910201222.6861b172.sfr@canb.auug.org.au> Message-ID: <17186.57339.793780.27220@cargo.ozlabs.ibm.com> Stephen Rothwell writes: > On 32 bit, int == long, so the last three could be removed from the ifdef > by making them {unsigned }long ... Yeah, I tried changing those to unsigned long once, long ago, and ran into problems because this header gets used in userspace, and gcc seems to have a fixed idea that size_t is unsigned int on ppc32. I think we should leave it as unsigned int. Paul. From sfr at canb.auug.org.au Sun Sep 11 00:00:14 2005 From: sfr at canb.auug.org.au (Stephen Rothwell) Date: Sun, 11 Sep 2005 00:00:14 +1000 Subject: [PATCH] powerpc: Move include3 to arch/$(ARCH)/include Message-ID: <20050911000014.7dc55b6f.sfr@canb.auug.org.au> This is less troublesome and makes more sense. Signed-off-by: Stephen Rothwell --- arch/ppc/Makefile | 16 +++++++++------- arch/ppc64/Makefile | 13 +++++++------ 2 files changed, 16 insertions(+), 13 deletions(-) -- Cheers, Stephen Rothwell sfr at canb.auug.org.au http://www.canb.auug.org.au/~sfr/ ed5a6c627c4bd12f2030318abb62e2c26e11113b diff --git a/arch/ppc/Makefile b/arch/ppc/Makefile --- a/arch/ppc/Makefile +++ b/arch/ppc/Makefile @@ -21,13 +21,14 @@ CC := $(CC) -m32 endif LDFLAGS_vmlinux := -Ttext $(KERNELLOAD) -Bstatic -CPPFLAGS += -Iarch/$(ARCH) -Iinclude3 +# The -Iarch/$(ARCH)/include is temporary while we are merging +CPPFLAGS += -Iarch/$(ARCH) -Iarch/$(ARCH)/include AFLAGS += -Iarch/$(ARCH) CFLAGS += -Iarch/$(ARCH) -msoft-float -pipe \ -ffixed-r2 -mmultiple CPP = $(CC) -E $(CFLAGS) # Temporary hack until we have migrated to asm-powerpc -LINUXINCLUDE += -Iinclude3 +LINUXINCLUDE += -Iarch/$(ARCH)/include CHECKFLAGS += -D__powerpc__ @@ -103,15 +104,16 @@ endef archclean: $(Q)$(MAKE) $(clean)=arch/ppc/boot - $(Q)rm -rf include3 + # Temporary hack until we have migrated to asm-powerpc + $(Q)rm -rf arch/$(ARCH)/include prepare: checkbin # Temporary hack until we have migrated to asm-powerpc -include/asm: include3/asm -include3/asm: - $(Q)if [ ! -d include3 ]; then mkdir -p include3; fi - $(Q)ln -fsn $(srctree)/include/asm-powerpc include3/asm +include/asm: arch/$(ARCH)/include/asm +arch/$(ARCH)/include/asm: + $(Q)if [ ! -d arch/$(ARCH)/include ]; then mkdir -p arch/$(ARCH)/include; fi + $(Q)ln -fsn $(srctree)/include/asm-powerpc arch/$(ARCH)/include/asm # Use the file '.tmp_gas_check' for binutils tests, as gas won't output # to stdout and these checks are run even on install targets. diff --git a/arch/ppc64/Makefile b/arch/ppc64/Makefile --- a/arch/ppc64/Makefile +++ b/arch/ppc64/Makefile @@ -56,7 +56,7 @@ LDFLAGS_vmlinux := -Bstatic -e $(KERNELL CFLAGS += -msoft-float -pipe -mminimal-toc -mtraceback=none \ -mcall-aixdesc # Temporary hack until we have migrated to asm-powerpc -CPPFLAGS += -Iinclude3 +CPPFLAGS += -Iarch/$(ARCH)/include GCC_VERSION := $(call cc-version) GCC_BROKEN_VEC := $(shell if [ $(GCC_VERSION) -lt 0400 ] ; then echo "y"; fi ;) @@ -115,14 +115,15 @@ all: $(KBUILD_IMAGE) archclean: $(Q)$(MAKE) $(clean)=$(boot) - $(Q)rm -rf include3 + # Temporary hack until we have migrated to asm-powerpc + $(Q)rm -rf arch/$(ARCH)/include # Temporary hack until we have migrated to asm-powerpc -include/asm: include3/asm -include3/asm: - $(Q)if [ ! -d include3 ]; then mkdir -p include3; fi; - $(Q)ln -fsn $(srctree)/include/asm-powerpc include3/asm +include/asm: arch/$(ARCH)/include/asm +arch/$(ARCH)/include/asm: + $(Q)if [ ! -d arch/$(ARCH)/include ]; then mkdir -p arch/$(ARCH)/include; fi + $(Q)ln -fsn $(srctree)/include/asm-powerpc arch/$(ARCH)/include/asm define archhelp echo ' zImage.vmode - Compressed kernel image (arch/$(ARCH)/boot/zImage.vmode)' From sfr at canb.auug.org.au Sun Sep 11 01:10:57 2005 From: sfr at canb.auug.org.au (Stephen Rothwell) Date: Sun, 11 Sep 2005 01:10:57 +1000 Subject: [PATCH] powerpc: Merge include/asm-ppc*/a.out.h into include/asm-powerpc Message-ID: <20050911011057.1e90fc41.sfr@canb.auug.org.au> Signed-off-by: Stephen Rothwell --- include/asm-powerpc/a.out.h | 36 ++++++++++++++++++++++++++++++++++++ include/asm-ppc/a.out.h | 26 -------------------------- include/asm-ppc64/a.out.h | 39 --------------------------------------- 3 files changed, 36 insertions(+), 65 deletions(-) create mode 100644 include/asm-powerpc/a.out.h delete mode 100644 include/asm-ppc/a.out.h delete mode 100644 include/asm-ppc64/a.out.h -- Cheers, Stephen Rothwell sfr at canb.auug.org.au http://www.canb.auug.org.au/~sfr/ dba4294fb3e51dc6f30e1f6252a5e0ae583db91f diff --git a/include/asm-powerpc/a.out.h b/include/asm-powerpc/a.out.h new file mode 100644 --- /dev/null +++ b/include/asm-powerpc/a.out.h @@ -0,0 +1,36 @@ +#ifndef _ASM_POWERPC_A_OUT_H +#define _ASM_POWERPC_A_OUT_H + +struct exec +{ + unsigned long a_info; /* Use macros N_MAGIC, etc for access */ + unsigned a_text; /* length of text, in bytes */ + unsigned a_data; /* length of data, in bytes */ + unsigned a_bss; /* length of uninitialized data area for file, in bytes */ + unsigned a_syms; /* length of symbol table data in file, in bytes */ + unsigned a_entry; /* start address */ + unsigned a_trsize; /* length of relocation info for text, in bytes */ + unsigned a_drsize; /* length of relocation info for data, in bytes */ +}; + +#define N_TRSIZE(a) ((a).a_trsize) +#define N_DRSIZE(a) ((a).a_drsize) +#define N_SYMSIZE(a) ((a).a_syms) + +#ifdef __KERNEL__ +#ifdef __powerpc64__ + +#define STACK_TOP_USER64 TASK_SIZE_USER64 +#define STACK_TOP_USER32 TASK_SIZE_USER32 + +#define STACK_TOP (test_thread_flag(TIF_32BIT) ? \ + STACK_TOP_USER32 : STACK_TOP_USER64) + +#else /* __powerpc64__ */ + +#define STACK_TOP TASK_SIZE + +#endif /* __powerpc64__ */ +#endif /* __KERNEL__ */ + +#endif /* _ASM_POWERPC_A_OUT_H */ diff --git a/include/asm-ppc/a.out.h b/include/asm-ppc/a.out.h deleted file mode 100644 --- a/include/asm-ppc/a.out.h +++ /dev/null @@ -1,26 +0,0 @@ -#ifndef __PPC_A_OUT_H__ -#define __PPC_A_OUT_H__ - -/* grabbed from the intel stuff */ -#define STACK_TOP TASK_SIZE - - -struct exec -{ - unsigned long a_info; /* Use macros N_MAGIC, etc for access */ - unsigned a_text; /* length of text, in bytes */ - unsigned a_data; /* length of data, in bytes */ - unsigned a_bss; /* length of uninitialized data area for file, in bytes */ - unsigned a_syms; /* length of symbol table data in file, in bytes */ - unsigned a_entry; /* start address */ - unsigned a_trsize; /* length of relocation info for text, in bytes */ - unsigned a_drsize; /* length of relocation info for data, in bytes */ -}; - - -#define N_TRSIZE(a) ((a).a_trsize) -#define N_DRSIZE(a) ((a).a_drsize) -#define N_SYMSIZE(a) ((a).a_syms) - - -#endif diff --git a/include/asm-ppc64/a.out.h b/include/asm-ppc64/a.out.h deleted file mode 100644 --- a/include/asm-ppc64/a.out.h +++ /dev/null @@ -1,39 +0,0 @@ -#ifndef __PPC64_A_OUT_H__ -#define __PPC64_A_OUT_H__ - -/* - * c 2001 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. - */ - -struct exec -{ - unsigned long a_info; /* Use macros N_MAGIC, etc for access */ - unsigned a_text; /* length of text, in bytes */ - unsigned a_data; /* length of data, in bytes */ - unsigned a_bss; /* length of uninitialized data area for file, in bytes */ - unsigned a_syms; /* length of symbol table data in file, in bytes */ - unsigned a_entry; /* start address */ - unsigned a_trsize; /* length of relocation info for text, in bytes */ - unsigned a_drsize; /* length of relocation info for data, in bytes */ -}; - -#define N_TRSIZE(a) ((a).a_trsize) -#define N_DRSIZE(a) ((a).a_drsize) -#define N_SYMSIZE(a) ((a).a_syms) - -#ifdef __KERNEL__ - -#define STACK_TOP_USER64 TASK_SIZE_USER64 -#define STACK_TOP_USER32 TASK_SIZE_USER32 - -#define STACK_TOP (test_thread_flag(TIF_32BIT) ? \ - STACK_TOP_USER32 : STACK_TOP_USER64) - -#endif /* __KERNEL__ */ - -#endif /* __PPC64_A_OUT_H__ */ From sfr at canb.auug.org.au Sun Sep 11 01:26:52 2005 From: sfr at canb.auug.org.au (Stephen Rothwell) Date: Sun, 11 Sep 2005 01:26:52 +1000 Subject: [PATCH] powerpc: Move arch/ppc*/kernel/vecemu.c to arch/powerpc Message-ID: <20050911012652.3f0fa31a.sfr@canb.auug.org.au> This file is the same in both architectures so create arch/powerpc/kernel and move it there. Signed-off-by: Stephen Rothwell --- arch/powerpc/kernel/vecemu.c | 345 ++++++++++++++++++++++++++++++++++++++++++ arch/ppc/kernel/Makefile | 2 arch/ppc/kernel/vecemu.c | 345 ------------------------------------------ arch/ppc64/kernel/Makefile | 3 arch/ppc64/kernel/vecemu.c | 346 ------------------------------------------ 5 files changed, 350 insertions(+), 691 deletions(-) create mode 100644 arch/powerpc/kernel/vecemu.c delete mode 100644 arch/ppc/kernel/vecemu.c delete mode 100644 arch/ppc64/kernel/vecemu.c -- Cheers, Stephen Rothwell sfr at canb.auug.org.au http://www.canb.auug.org.au/~sfr/ 995d61476dbab834c4e915b0c00d2f21d7cbec31 diff --git a/arch/powerpc/kernel/vecemu.c b/arch/powerpc/kernel/vecemu.c new file mode 100644 --- /dev/null +++ b/arch/powerpc/kernel/vecemu.c @@ -0,0 +1,345 @@ +/* + * Routines to emulate some Altivec/VMX instructions, specifically + * those that can trap when given denormalized operands in Java mode. + */ +#include +#include +#include +#include +#include +#include + +/* Functions in vector.S */ +extern void vaddfp(vector128 *dst, vector128 *a, vector128 *b); +extern void vsubfp(vector128 *dst, vector128 *a, vector128 *b); +extern void vmaddfp(vector128 *dst, vector128 *a, vector128 *b, vector128 *c); +extern void vnmsubfp(vector128 *dst, vector128 *a, vector128 *b, vector128 *c); +extern void vrefp(vector128 *dst, vector128 *src); +extern void vrsqrtefp(vector128 *dst, vector128 *src); +extern void vexptep(vector128 *dst, vector128 *src); + +static unsigned int exp2s[8] = { + 0x800000, + 0x8b95c2, + 0x9837f0, + 0xa5fed7, + 0xb504f3, + 0xc5672a, + 0xd744fd, + 0xeac0c7 +}; + +/* + * Computes an estimate of 2^x. The `s' argument is the 32-bit + * single-precision floating-point representation of x. + */ +static unsigned int eexp2(unsigned int s) +{ + int exp, pwr; + unsigned int mant, frac; + + /* extract exponent field from input */ + exp = ((s >> 23) & 0xff) - 127; + if (exp > 7) { + /* check for NaN input */ + if (exp == 128 && (s & 0x7fffff) != 0) + return s | 0x400000; /* return QNaN */ + /* 2^-big = 0, 2^+big = +Inf */ + return (s & 0x80000000)? 0: 0x7f800000; /* 0 or +Inf */ + } + if (exp < -23) + return 0x3f800000; /* 1.0 */ + + /* convert to fixed point integer in 9.23 representation */ + pwr = (s & 0x7fffff) | 0x800000; + if (exp > 0) + pwr <<= exp; + else + pwr >>= -exp; + if (s & 0x80000000) + pwr = -pwr; + + /* extract integer part, which becomes exponent part of result */ + exp = (pwr >> 23) + 126; + if (exp >= 254) + return 0x7f800000; + if (exp < -23) + return 0; + + /* table lookup on top 3 bits of fraction to get mantissa */ + mant = exp2s[(pwr >> 20) & 7]; + + /* linear interpolation using remaining 20 bits of fraction */ + asm("mulhwu %0,%1,%2" : "=r" (frac) + : "r" (pwr << 12), "r" (0x172b83ff)); + asm("mulhwu %0,%1,%2" : "=r" (frac) : "r" (frac), "r" (mant)); + mant += frac; + + if (exp >= 0) + return mant + (exp << 23); + + /* denormalized result */ + exp = -exp; + mant += 1 << (exp - 1); + return mant >> exp; +} + +/* + * Computes an estimate of log_2(x). The `s' argument is the 32-bit + * single-precision floating-point representation of x. + */ +static unsigned int elog2(unsigned int s) +{ + int exp, mant, lz, frac; + + exp = s & 0x7f800000; + mant = s & 0x7fffff; + if (exp == 0x7f800000) { /* Inf or NaN */ + if (mant != 0) + s |= 0x400000; /* turn NaN into QNaN */ + return s; + } + if ((exp | mant) == 0) /* +0 or -0 */ + return 0xff800000; /* return -Inf */ + + if (exp == 0) { + /* denormalized */ + asm("cntlzw %0,%1" : "=r" (lz) : "r" (mant)); + mant <<= lz - 8; + exp = (-118 - lz) << 23; + } else { + mant |= 0x800000; + exp -= 127 << 23; + } + + if (mant >= 0xb504f3) { /* 2^0.5 * 2^23 */ + exp |= 0x400000; /* 0.5 * 2^23 */ + asm("mulhwu %0,%1,%2" : "=r" (mant) + : "r" (mant), "r" (0xb504f334)); /* 2^-0.5 * 2^32 */ + } + if (mant >= 0x9837f0) { /* 2^0.25 * 2^23 */ + exp |= 0x200000; /* 0.25 * 2^23 */ + asm("mulhwu %0,%1,%2" : "=r" (mant) + : "r" (mant), "r" (0xd744fccb)); /* 2^-0.25 * 2^32 */ + } + if (mant >= 0x8b95c2) { /* 2^0.125 * 2^23 */ + exp |= 0x100000; /* 0.125 * 2^23 */ + asm("mulhwu %0,%1,%2" : "=r" (mant) + : "r" (mant), "r" (0xeac0c6e8)); /* 2^-0.125 * 2^32 */ + } + if (mant > 0x800000) { /* 1.0 * 2^23 */ + /* calculate (mant - 1) * 1.381097463 */ + /* 1.381097463 == 0.125 / (2^0.125 - 1) */ + asm("mulhwu %0,%1,%2" : "=r" (frac) + : "r" ((mant - 0x800000) << 1), "r" (0xb0c7cd3a)); + exp += frac; + } + s = exp & 0x80000000; + if (exp != 0) { + if (s) + exp = -exp; + asm("cntlzw %0,%1" : "=r" (lz) : "r" (exp)); + lz = 8 - lz; + if (lz > 0) + exp >>= lz; + else if (lz < 0) + exp <<= -lz; + s += ((lz + 126) << 23) + exp; + } + return s; +} + +#define VSCR_SAT 1 + +static int ctsxs(unsigned int x, int scale, unsigned int *vscrp) +{ + int exp, mant; + + exp = (x >> 23) & 0xff; + mant = x & 0x7fffff; + if (exp == 255 && mant != 0) + return 0; /* NaN -> 0 */ + exp = exp - 127 + scale; + if (exp < 0) + return 0; /* round towards zero */ + if (exp >= 31) { + /* saturate, unless the result would be -2^31 */ + if (x + (scale << 23) != 0xcf000000) + *vscrp |= VSCR_SAT; + return (x & 0x80000000)? 0x80000000: 0x7fffffff; + } + mant |= 0x800000; + mant = (mant << 7) >> (30 - exp); + return (x & 0x80000000)? -mant: mant; +} + +static unsigned int ctuxs(unsigned int x, int scale, unsigned int *vscrp) +{ + int exp; + unsigned int mant; + + exp = (x >> 23) & 0xff; + mant = x & 0x7fffff; + if (exp == 255 && mant != 0) + return 0; /* NaN -> 0 */ + exp = exp - 127 + scale; + if (exp < 0) + return 0; /* round towards zero */ + if (x & 0x80000000) { + /* negative => saturate to 0 */ + *vscrp |= VSCR_SAT; + return 0; + } + if (exp >= 32) { + /* saturate */ + *vscrp |= VSCR_SAT; + return 0xffffffff; + } + mant |= 0x800000; + mant = (mant << 8) >> (31 - exp); + return mant; +} + +/* Round to floating integer, towards 0 */ +static unsigned int rfiz(unsigned int x) +{ + int exp; + + exp = ((x >> 23) & 0xff) - 127; + if (exp == 128 && (x & 0x7fffff) != 0) + return x | 0x400000; /* NaN -> make it a QNaN */ + if (exp >= 23) + return x; /* it's an integer already (or Inf) */ + if (exp < 0) + return x & 0x80000000; /* |x| < 1.0 rounds to 0 */ + return x & ~(0x7fffff >> exp); +} + +/* Round to floating integer, towards +/- Inf */ +static unsigned int rfii(unsigned int x) +{ + int exp, mask; + + exp = ((x >> 23) & 0xff) - 127; + if (exp == 128 && (x & 0x7fffff) != 0) + return x | 0x400000; /* NaN -> make it a QNaN */ + if (exp >= 23) + return x; /* it's an integer already (or Inf) */ + if ((x & 0x7fffffff) == 0) + return x; /* +/-0 -> +/-0 */ + if (exp < 0) + /* 0 < |x| < 1.0 rounds to +/- 1.0 */ + return (x & 0x80000000) | 0x3f800000; + mask = 0x7fffff >> exp; + /* mantissa overflows into exponent - that's OK, + it can't overflow into the sign bit */ + return (x + mask) & ~mask; +} + +/* Round to floating integer, to nearest */ +static unsigned int rfin(unsigned int x) +{ + int exp, half; + + exp = ((x >> 23) & 0xff) - 127; + if (exp == 128 && (x & 0x7fffff) != 0) + return x | 0x400000; /* NaN -> make it a QNaN */ + if (exp >= 23) + return x; /* it's an integer already (or Inf) */ + if (exp < -1) + return x & 0x80000000; /* |x| < 0.5 -> +/-0 */ + if (exp == -1) + /* 0.5 <= |x| < 1.0 rounds to +/- 1.0 */ + return (x & 0x80000000) | 0x3f800000; + half = 0x400000 >> exp; + /* add 0.5 to the magnitude and chop off the fraction bits */ + return (x + half) & ~(0x7fffff >> exp); +} + +int emulate_altivec(struct pt_regs *regs) +{ + unsigned int instr, i; + unsigned int va, vb, vc, vd; + vector128 *vrs; + + if (get_user(instr, (unsigned int __user *) regs->nip)) + return -EFAULT; + if ((instr >> 26) != 4) + return -EINVAL; /* not an altivec instruction */ + vd = (instr >> 21) & 0x1f; + va = (instr >> 16) & 0x1f; + vb = (instr >> 11) & 0x1f; + vc = (instr >> 6) & 0x1f; + + vrs = current->thread.vr; + switch (instr & 0x3f) { + case 10: + switch (vc) { + case 0: /* vaddfp */ + vaddfp(&vrs[vd], &vrs[va], &vrs[vb]); + break; + case 1: /* vsubfp */ + vsubfp(&vrs[vd], &vrs[va], &vrs[vb]); + break; + case 4: /* vrefp */ + vrefp(&vrs[vd], &vrs[vb]); + break; + case 5: /* vrsqrtefp */ + vrsqrtefp(&vrs[vd], &vrs[vb]); + break; + case 6: /* vexptefp */ + for (i = 0; i < 4; ++i) + vrs[vd].u[i] = eexp2(vrs[vb].u[i]); + break; + case 7: /* vlogefp */ + for (i = 0; i < 4; ++i) + vrs[vd].u[i] = elog2(vrs[vb].u[i]); + break; + case 8: /* vrfin */ + for (i = 0; i < 4; ++i) + vrs[vd].u[i] = rfin(vrs[vb].u[i]); + break; + case 9: /* vrfiz */ + for (i = 0; i < 4; ++i) + vrs[vd].u[i] = rfiz(vrs[vb].u[i]); + break; + case 10: /* vrfip */ + for (i = 0; i < 4; ++i) { + u32 x = vrs[vb].u[i]; + x = (x & 0x80000000)? rfiz(x): rfii(x); + vrs[vd].u[i] = x; + } + break; + case 11: /* vrfim */ + for (i = 0; i < 4; ++i) { + u32 x = vrs[vb].u[i]; + x = (x & 0x80000000)? rfii(x): rfiz(x); + vrs[vd].u[i] = x; + } + break; + case 14: /* vctuxs */ + for (i = 0; i < 4; ++i) + vrs[vd].u[i] = ctuxs(vrs[vb].u[i], va, + ¤t->thread.vscr.u[3]); + break; + case 15: /* vctsxs */ + for (i = 0; i < 4; ++i) + vrs[vd].u[i] = ctsxs(vrs[vb].u[i], va, + ¤t->thread.vscr.u[3]); + break; + default: + return -EINVAL; + } + break; + case 46: /* vmaddfp */ + vmaddfp(&vrs[vd], &vrs[va], &vrs[vb], &vrs[vc]); + break; + case 47: /* vnmsubfp */ + vnmsubfp(&vrs[vd], &vrs[va], &vrs[vb], &vrs[vc]); + break; + default: + return -EINVAL; + } + + return 0; +} diff --git a/arch/ppc/kernel/Makefile b/arch/ppc/kernel/Makefile --- a/arch/ppc/kernel/Makefile +++ b/arch/ppc/kernel/Makefile @@ -36,3 +36,5 @@ ifndef CONFIG_MATH_EMULATION obj-$(CONFIG_8xx) += softemu8xx.o endif +# These are here while we do the architecture merge +vecemu-y += ../../powerpc/kernel/vecemu.o diff --git a/arch/ppc/kernel/vecemu.c b/arch/ppc/kernel/vecemu.c deleted file mode 100644 --- a/arch/ppc/kernel/vecemu.c +++ /dev/null @@ -1,345 +0,0 @@ -/* - * Routines to emulate some Altivec/VMX instructions, specifically - * those that can trap when given denormalized operands in Java mode. - */ -#include -#include -#include -#include -#include -#include - -/* Functions in vector.S */ -extern void vaddfp(vector128 *dst, vector128 *a, vector128 *b); -extern void vsubfp(vector128 *dst, vector128 *a, vector128 *b); -extern void vmaddfp(vector128 *dst, vector128 *a, vector128 *b, vector128 *c); -extern void vnmsubfp(vector128 *dst, vector128 *a, vector128 *b, vector128 *c); -extern void vrefp(vector128 *dst, vector128 *src); -extern void vrsqrtefp(vector128 *dst, vector128 *src); -extern void vexptep(vector128 *dst, vector128 *src); - -static unsigned int exp2s[8] = { - 0x800000, - 0x8b95c2, - 0x9837f0, - 0xa5fed7, - 0xb504f3, - 0xc5672a, - 0xd744fd, - 0xeac0c7 -}; - -/* - * Computes an estimate of 2^x. The `s' argument is the 32-bit - * single-precision floating-point representation of x. - */ -static unsigned int eexp2(unsigned int s) -{ - int exp, pwr; - unsigned int mant, frac; - - /* extract exponent field from input */ - exp = ((s >> 23) & 0xff) - 127; - if (exp > 7) { - /* check for NaN input */ - if (exp == 128 && (s & 0x7fffff) != 0) - return s | 0x400000; /* return QNaN */ - /* 2^-big = 0, 2^+big = +Inf */ - return (s & 0x80000000)? 0: 0x7f800000; /* 0 or +Inf */ - } - if (exp < -23) - return 0x3f800000; /* 1.0 */ - - /* convert to fixed point integer in 9.23 representation */ - pwr = (s & 0x7fffff) | 0x800000; - if (exp > 0) - pwr <<= exp; - else - pwr >>= -exp; - if (s & 0x80000000) - pwr = -pwr; - - /* extract integer part, which becomes exponent part of result */ - exp = (pwr >> 23) + 126; - if (exp >= 254) - return 0x7f800000; - if (exp < -23) - return 0; - - /* table lookup on top 3 bits of fraction to get mantissa */ - mant = exp2s[(pwr >> 20) & 7]; - - /* linear interpolation using remaining 20 bits of fraction */ - asm("mulhwu %0,%1,%2" : "=r" (frac) - : "r" (pwr << 12), "r" (0x172b83ff)); - asm("mulhwu %0,%1,%2" : "=r" (frac) : "r" (frac), "r" (mant)); - mant += frac; - - if (exp >= 0) - return mant + (exp << 23); - - /* denormalized result */ - exp = -exp; - mant += 1 << (exp - 1); - return mant >> exp; -} - -/* - * Computes an estimate of log_2(x). The `s' argument is the 32-bit - * single-precision floating-point representation of x. - */ -static unsigned int elog2(unsigned int s) -{ - int exp, mant, lz, frac; - - exp = s & 0x7f800000; - mant = s & 0x7fffff; - if (exp == 0x7f800000) { /* Inf or NaN */ - if (mant != 0) - s |= 0x400000; /* turn NaN into QNaN */ - return s; - } - if ((exp | mant) == 0) /* +0 or -0 */ - return 0xff800000; /* return -Inf */ - - if (exp == 0) { - /* denormalized */ - asm("cntlzw %0,%1" : "=r" (lz) : "r" (mant)); - mant <<= lz - 8; - exp = (-118 - lz) << 23; - } else { - mant |= 0x800000; - exp -= 127 << 23; - } - - if (mant >= 0xb504f3) { /* 2^0.5 * 2^23 */ - exp |= 0x400000; /* 0.5 * 2^23 */ - asm("mulhwu %0,%1,%2" : "=r" (mant) - : "r" (mant), "r" (0xb504f334)); /* 2^-0.5 * 2^32 */ - } - if (mant >= 0x9837f0) { /* 2^0.25 * 2^23 */ - exp |= 0x200000; /* 0.25 * 2^23 */ - asm("mulhwu %0,%1,%2" : "=r" (mant) - : "r" (mant), "r" (0xd744fccb)); /* 2^-0.25 * 2^32 */ - } - if (mant >= 0x8b95c2) { /* 2^0.125 * 2^23 */ - exp |= 0x100000; /* 0.125 * 2^23 */ - asm("mulhwu %0,%1,%2" : "=r" (mant) - : "r" (mant), "r" (0xeac0c6e8)); /* 2^-0.125 * 2^32 */ - } - if (mant > 0x800000) { /* 1.0 * 2^23 */ - /* calculate (mant - 1) * 1.381097463 */ - /* 1.381097463 == 0.125 / (2^0.125 - 1) */ - asm("mulhwu %0,%1,%2" : "=r" (frac) - : "r" ((mant - 0x800000) << 1), "r" (0xb0c7cd3a)); - exp += frac; - } - s = exp & 0x80000000; - if (exp != 0) { - if (s) - exp = -exp; - asm("cntlzw %0,%1" : "=r" (lz) : "r" (exp)); - lz = 8 - lz; - if (lz > 0) - exp >>= lz; - else if (lz < 0) - exp <<= -lz; - s += ((lz + 126) << 23) + exp; - } - return s; -} - -#define VSCR_SAT 1 - -static int ctsxs(unsigned int x, int scale, unsigned int *vscrp) -{ - int exp, mant; - - exp = (x >> 23) & 0xff; - mant = x & 0x7fffff; - if (exp == 255 && mant != 0) - return 0; /* NaN -> 0 */ - exp = exp - 127 + scale; - if (exp < 0) - return 0; /* round towards zero */ - if (exp >= 31) { - /* saturate, unless the result would be -2^31 */ - if (x + (scale << 23) != 0xcf000000) - *vscrp |= VSCR_SAT; - return (x & 0x80000000)? 0x80000000: 0x7fffffff; - } - mant |= 0x800000; - mant = (mant << 7) >> (30 - exp); - return (x & 0x80000000)? -mant: mant; -} - -static unsigned int ctuxs(unsigned int x, int scale, unsigned int *vscrp) -{ - int exp; - unsigned int mant; - - exp = (x >> 23) & 0xff; - mant = x & 0x7fffff; - if (exp == 255 && mant != 0) - return 0; /* NaN -> 0 */ - exp = exp - 127 + scale; - if (exp < 0) - return 0; /* round towards zero */ - if (x & 0x80000000) { - /* negative => saturate to 0 */ - *vscrp |= VSCR_SAT; - return 0; - } - if (exp >= 32) { - /* saturate */ - *vscrp |= VSCR_SAT; - return 0xffffffff; - } - mant |= 0x800000; - mant = (mant << 8) >> (31 - exp); - return mant; -} - -/* Round to floating integer, towards 0 */ -static unsigned int rfiz(unsigned int x) -{ - int exp; - - exp = ((x >> 23) & 0xff) - 127; - if (exp == 128 && (x & 0x7fffff) != 0) - return x | 0x400000; /* NaN -> make it a QNaN */ - if (exp >= 23) - return x; /* it's an integer already (or Inf) */ - if (exp < 0) - return x & 0x80000000; /* |x| < 1.0 rounds to 0 */ - return x & ~(0x7fffff >> exp); -} - -/* Round to floating integer, towards +/- Inf */ -static unsigned int rfii(unsigned int x) -{ - int exp, mask; - - exp = ((x >> 23) & 0xff) - 127; - if (exp == 128 && (x & 0x7fffff) != 0) - return x | 0x400000; /* NaN -> make it a QNaN */ - if (exp >= 23) - return x; /* it's an integer already (or Inf) */ - if ((x & 0x7fffffff) == 0) - return x; /* +/-0 -> +/-0 */ - if (exp < 0) - /* 0 < |x| < 1.0 rounds to +/- 1.0 */ - return (x & 0x80000000) | 0x3f800000; - mask = 0x7fffff >> exp; - /* mantissa overflows into exponent - that's OK, - it can't overflow into the sign bit */ - return (x + mask) & ~mask; -} - -/* Round to floating integer, to nearest */ -static unsigned int rfin(unsigned int x) -{ - int exp, half; - - exp = ((x >> 23) & 0xff) - 127; - if (exp == 128 && (x & 0x7fffff) != 0) - return x | 0x400000; /* NaN -> make it a QNaN */ - if (exp >= 23) - return x; /* it's an integer already (or Inf) */ - if (exp < -1) - return x & 0x80000000; /* |x| < 0.5 -> +/-0 */ - if (exp == -1) - /* 0.5 <= |x| < 1.0 rounds to +/- 1.0 */ - return (x & 0x80000000) | 0x3f800000; - half = 0x400000 >> exp; - /* add 0.5 to the magnitude and chop off the fraction bits */ - return (x + half) & ~(0x7fffff >> exp); -} - -int emulate_altivec(struct pt_regs *regs) -{ - unsigned int instr, i; - unsigned int va, vb, vc, vd; - vector128 *vrs; - - if (get_user(instr, (unsigned int __user *) regs->nip)) - return -EFAULT; - if ((instr >> 26) != 4) - return -EINVAL; /* not an altivec instruction */ - vd = (instr >> 21) & 0x1f; - va = (instr >> 16) & 0x1f; - vb = (instr >> 11) & 0x1f; - vc = (instr >> 6) & 0x1f; - - vrs = current->thread.vr; - switch (instr & 0x3f) { - case 10: - switch (vc) { - case 0: /* vaddfp */ - vaddfp(&vrs[vd], &vrs[va], &vrs[vb]); - break; - case 1: /* vsubfp */ - vsubfp(&vrs[vd], &vrs[va], &vrs[vb]); - break; - case 4: /* vrefp */ - vrefp(&vrs[vd], &vrs[vb]); - break; - case 5: /* vrsqrtefp */ - vrsqrtefp(&vrs[vd], &vrs[vb]); - break; - case 6: /* vexptefp */ - for (i = 0; i < 4; ++i) - vrs[vd].u[i] = eexp2(vrs[vb].u[i]); - break; - case 7: /* vlogefp */ - for (i = 0; i < 4; ++i) - vrs[vd].u[i] = elog2(vrs[vb].u[i]); - break; - case 8: /* vrfin */ - for (i = 0; i < 4; ++i) - vrs[vd].u[i] = rfin(vrs[vb].u[i]); - break; - case 9: /* vrfiz */ - for (i = 0; i < 4; ++i) - vrs[vd].u[i] = rfiz(vrs[vb].u[i]); - break; - case 10: /* vrfip */ - for (i = 0; i < 4; ++i) { - u32 x = vrs[vb].u[i]; - x = (x & 0x80000000)? rfiz(x): rfii(x); - vrs[vd].u[i] = x; - } - break; - case 11: /* vrfim */ - for (i = 0; i < 4; ++i) { - u32 x = vrs[vb].u[i]; - x = (x & 0x80000000)? rfii(x): rfiz(x); - vrs[vd].u[i] = x; - } - break; - case 14: /* vctuxs */ - for (i = 0; i < 4; ++i) - vrs[vd].u[i] = ctuxs(vrs[vb].u[i], va, - ¤t->thread.vscr.u[3]); - break; - case 15: /* vctsxs */ - for (i = 0; i < 4; ++i) - vrs[vd].u[i] = ctsxs(vrs[vb].u[i], va, - ¤t->thread.vscr.u[3]); - break; - default: - return -EINVAL; - } - break; - case 46: /* vmaddfp */ - vmaddfp(&vrs[vd], &vrs[va], &vrs[vb], &vrs[vc]); - break; - case 47: /* vnmsubfp */ - vnmsubfp(&vrs[vd], &vrs[va], &vrs[vb], &vrs[vc]); - break; - default: - return -EINVAL; - } - - return 0; -} diff --git a/arch/ppc64/kernel/Makefile b/arch/ppc64/kernel/Makefile --- a/arch/ppc64/kernel/Makefile +++ b/arch/ppc64/kernel/Makefile @@ -83,3 +83,6 @@ ifeq ($(CONFIG_PPC_ISERIES),y) arch/ppc64/kernel/head.o: arch/ppc64/kernel/lparmap.s AFLAGS_head.o += -Iarch/ppc64/kernel endif + +# These are here while we do the architecture merge +vecemu-y += ../../powerpc/kernel/vecemu.o diff --git a/arch/ppc64/kernel/vecemu.c b/arch/ppc64/kernel/vecemu.c deleted file mode 100644 --- a/arch/ppc64/kernel/vecemu.c +++ /dev/null @@ -1,346 +0,0 @@ -/* - * Routines to emulate some Altivec/VMX instructions, specifically - * those that can trap when given denormalized operands in Java mode. - */ -#include -#include -#include -#include -#include -#include - -/* Functions in vector.S */ -extern void vaddfp(vector128 *dst, vector128 *a, vector128 *b); -extern void vsubfp(vector128 *dst, vector128 *a, vector128 *b); -extern void vmaddfp(vector128 *dst, vector128 *a, vector128 *b, vector128 *c); -extern void vnmsubfp(vector128 *dst, vector128 *a, vector128 *b, vector128 *c); -extern void vrefp(vector128 *dst, vector128 *src); -extern void vrsqrtefp(vector128 *dst, vector128 *src); -extern void vexptep(vector128 *dst, vector128 *src); - -static unsigned int exp2s[8] = { - 0x800000, - 0x8b95c2, - 0x9837f0, - 0xa5fed7, - 0xb504f3, - 0xc5672a, - 0xd744fd, - 0xeac0c7 -}; - -/* - * Computes an estimate of 2^x. The `s' argument is the 32-bit - * single-precision floating-point representation of x. - */ -static unsigned int eexp2(unsigned int s) -{ - int exp, pwr; - unsigned int mant, frac; - - /* extract exponent field from input */ - exp = ((s >> 23) & 0xff) - 127; - if (exp > 7) { - /* check for NaN input */ - if (exp == 128 && (s & 0x7fffff) != 0) - return s | 0x400000; /* return QNaN */ - /* 2^-big = 0, 2^+big = +Inf */ - return (s & 0x80000000)? 0: 0x7f800000; /* 0 or +Inf */ - } - if (exp < -23) - return 0x3f800000; /* 1.0 */ - - /* convert to fixed point integer in 9.23 representation */ - pwr = (s & 0x7fffff) | 0x800000; - if (exp > 0) - pwr <<= exp; - else - pwr >>= -exp; - if (s & 0x80000000) - pwr = -pwr; - - /* extract integer part, which becomes exponent part of result */ - exp = (pwr >> 23) + 126; - if (exp >= 254) - return 0x7f800000; - if (exp < -23) - return 0; - - /* table lookup on top 3 bits of fraction to get mantissa */ - mant = exp2s[(pwr >> 20) & 7]; - - /* linear interpolation using remaining 20 bits of fraction */ - asm("mulhwu %0,%1,%2" : "=r" (frac) - : "r" (pwr << 12), "r" (0x172b83ff)); - asm("mulhwu %0,%1,%2" : "=r" (frac) : "r" (frac), "r" (mant)); - mant += frac; - - if (exp >= 0) - return mant + (exp << 23); - - /* denormalized result */ - exp = -exp; - mant += 1 << (exp - 1); - return mant >> exp; -} - -/* - * Computes an estimate of log_2(x). The `s' argument is the 32-bit - * single-precision floating-point representation of x. - */ -static unsigned int elog2(unsigned int s) -{ - int exp, mant, lz, frac; - - exp = s & 0x7f800000; - mant = s & 0x7fffff; - if (exp == 0x7f800000) { /* Inf or NaN */ - if (mant != 0) - s |= 0x400000; /* turn NaN into QNaN */ - return s; - } - if ((exp | mant) == 0) /* +0 or -0 */ - return 0xff800000; /* return -Inf */ - - if (exp == 0) { - /* denormalized */ - asm("cntlzw %0,%1" : "=r" (lz) : "r" (mant)); - mant <<= lz - 8; - exp = (-118 - lz) << 23; - } else { - mant |= 0x800000; - exp -= 127 << 23; - } - - if (mant >= 0xb504f3) { /* 2^0.5 * 2^23 */ - exp |= 0x400000; /* 0.5 * 2^23 */ - asm("mulhwu %0,%1,%2" : "=r" (mant) - : "r" (mant), "r" (0xb504f334)); /* 2^-0.5 * 2^32 */ - } - if (mant >= 0x9837f0) { /* 2^0.25 * 2^23 */ - exp |= 0x200000; /* 0.25 * 2^23 */ - asm("mulhwu %0,%1,%2" : "=r" (mant) - : "r" (mant), "r" (0xd744fccb)); /* 2^-0.25 * 2^32 */ - } - if (mant >= 0x8b95c2) { /* 2^0.125 * 2^23 */ - exp |= 0x100000; /* 0.125 * 2^23 */ - asm("mulhwu %0,%1,%2" : "=r" (mant) - : "r" (mant), "r" (0xeac0c6e8)); /* 2^-0.125 * 2^32 */ - } - if (mant > 0x800000) { /* 1.0 * 2^23 */ - /* calculate (mant - 1) * 1.381097463 */ - /* 1.381097463 == 0.125 / (2^0.125 - 1) */ - asm("mulhwu %0,%1,%2" : "=r" (frac) - : "r" ((mant - 0x800000) << 1), "r" (0xb0c7cd3a)); - exp += frac; - } - s = exp & 0x80000000; - if (exp != 0) { - if (s) - exp = -exp; - asm("cntlzw %0,%1" : "=r" (lz) : "r" (exp)); - lz = 8 - lz; - if (lz > 0) - exp >>= lz; - else if (lz < 0) - exp <<= -lz; - s += ((lz + 126) << 23) + exp; - } - return s; -} - -#define VSCR_SAT 1 - -static int ctsxs(unsigned int x, int scale, unsigned int *vscrp) -{ - int exp, mant; - - exp = (x >> 23) & 0xff; - mant = x & 0x7fffff; - if (exp == 255 && mant != 0) - return 0; /* NaN -> 0 */ - exp = exp - 127 + scale; - if (exp < 0) - return 0; /* round towards zero */ - if (exp >= 31) { - /* saturate, unless the result would be -2^31 */ - if (x + (scale << 23) != 0xcf000000) - *vscrp |= VSCR_SAT; - return (x & 0x80000000)? 0x80000000: 0x7fffffff; - } - mant |= 0x800000; - mant = (mant << 7) >> (30 - exp); - return (x & 0x80000000)? -mant: mant; -} - -static unsigned int ctuxs(unsigned int x, int scale, unsigned int *vscrp) -{ - int exp; - unsigned int mant; - - exp = (x >> 23) & 0xff; - mant = x & 0x7fffff; - if (exp == 255 && mant != 0) - return 0; /* NaN -> 0 */ - exp = exp - 127 + scale; - if (exp < 0) - return 0; /* round towards zero */ - if (x & 0x80000000) { - /* negative => saturate to 0 */ - *vscrp |= VSCR_SAT; - return 0; - } - if (exp >= 32) { - /* saturate */ - *vscrp |= VSCR_SAT; - return 0xffffffff; - } - mant |= 0x800000; - mant = (mant << 8) >> (31 - exp); - return mant; -} - -/* Round to floating integer, towards 0 */ -static unsigned int rfiz(unsigned int x) -{ - int exp; - - exp = ((x >> 23) & 0xff) - 127; - if (exp == 128 && (x & 0x7fffff) != 0) - return x | 0x400000; /* NaN -> make it a QNaN */ - if (exp >= 23) - return x; /* it's an integer already (or Inf) */ - if (exp < 0) - return x & 0x80000000; /* |x| < 1.0 rounds to 0 */ - return x & ~(0x7fffff >> exp); -} - -/* Round to floating integer, towards +/- Inf */ -static unsigned int rfii(unsigned int x) -{ - int exp, mask; - - exp = ((x >> 23) & 0xff) - 127; - if (exp == 128 && (x & 0x7fffff) != 0) - return x | 0x400000; /* NaN -> make it a QNaN */ - if (exp >= 23) - return x; /* it's an integer already (or Inf) */ - if ((x & 0x7fffffff) == 0) - return x; /* +/-0 -> +/-0 */ - if (exp < 0) - /* 0 < |x| < 1.0 rounds to +/- 1.0 */ - return (x & 0x80000000) | 0x3f800000; - mask = 0x7fffff >> exp; - /* mantissa overflows into exponent - that's OK, - it can't overflow into the sign bit */ - return (x + mask) & ~mask; -} - -/* Round to floating integer, to nearest */ -static unsigned int rfin(unsigned int x) -{ - int exp, half; - - exp = ((x >> 23) & 0xff) - 127; - if (exp == 128 && (x & 0x7fffff) != 0) - return x | 0x400000; /* NaN -> make it a QNaN */ - if (exp >= 23) - return x; /* it's an integer already (or Inf) */ - if (exp < -1) - return x & 0x80000000; /* |x| < 0.5 -> +/-0 */ - if (exp == -1) - /* 0.5 <= |x| < 1.0 rounds to +/- 1.0 */ - return (x & 0x80000000) | 0x3f800000; - half = 0x400000 >> exp; - /* add 0.5 to the magnitude and chop off the fraction bits */ - return (x + half) & ~(0x7fffff >> exp); -} - -int -emulate_altivec(struct pt_regs *regs) -{ - unsigned int instr, i; - unsigned int va, vb, vc, vd; - vector128 *vrs; - - if (get_user(instr, (unsigned int __user *) regs->nip)) - return -EFAULT; - if ((instr >> 26) != 4) - return -EINVAL; /* not an altivec instruction */ - vd = (instr >> 21) & 0x1f; - va = (instr >> 16) & 0x1f; - vb = (instr >> 11) & 0x1f; - vc = (instr >> 6) & 0x1f; - - vrs = current->thread.vr; - switch (instr & 0x3f) { - case 10: - switch (vc) { - case 0: /* vaddfp */ - vaddfp(&vrs[vd], &vrs[va], &vrs[vb]); - break; - case 1: /* vsubfp */ - vsubfp(&vrs[vd], &vrs[va], &vrs[vb]); - break; - case 4: /* vrefp */ - vrefp(&vrs[vd], &vrs[vb]); - break; - case 5: /* vrsqrtefp */ - vrsqrtefp(&vrs[vd], &vrs[vb]); - break; - case 6: /* vexptefp */ - for (i = 0; i < 4; ++i) - vrs[vd].u[i] = eexp2(vrs[vb].u[i]); - break; - case 7: /* vlogefp */ - for (i = 0; i < 4; ++i) - vrs[vd].u[i] = elog2(vrs[vb].u[i]); - break; - case 8: /* vrfin */ - for (i = 0; i < 4; ++i) - vrs[vd].u[i] = rfin(vrs[vb].u[i]); - break; - case 9: /* vrfiz */ - for (i = 0; i < 4; ++i) - vrs[vd].u[i] = rfiz(vrs[vb].u[i]); - break; - case 10: /* vrfip */ - for (i = 0; i < 4; ++i) { - u32 x = vrs[vb].u[i]; - x = (x & 0x80000000)? rfiz(x): rfii(x); - vrs[vd].u[i] = x; - } - break; - case 11: /* vrfim */ - for (i = 0; i < 4; ++i) { - u32 x = vrs[vb].u[i]; - x = (x & 0x80000000)? rfii(x): rfiz(x); - vrs[vd].u[i] = x; - } - break; - case 14: /* vctuxs */ - for (i = 0; i < 4; ++i) - vrs[vd].u[i] = ctuxs(vrs[vb].u[i], va, - ¤t->thread.vscr.u[3]); - break; - case 15: /* vctsxs */ - for (i = 0; i < 4; ++i) - vrs[vd].u[i] = ctsxs(vrs[vb].u[i], va, - ¤t->thread.vscr.u[3]); - break; - default: - return -EINVAL; - } - break; - case 46: /* vmaddfp */ - vmaddfp(&vrs[vd], &vrs[va], &vrs[vb], &vrs[vc]); - break; - case 47: /* vnmsubfp */ - vnmsubfp(&vrs[vd], &vrs[va], &vrs[vb], &vrs[vc]); - break; - default: - return -EINVAL; - } - - return 0; -} From sfr at canb.auug.org.au Sun Sep 11 01:35:15 2005 From: sfr at canb.auug.org.au (Stephen Rothwell) Date: Sun, 11 Sep 2005 01:35:15 +1000 Subject: [PATCH 0/4] iSeries: remove some include files Message-ID: <20050911013515.404e46a2.sfr@canb.auug.org.au> This series of patches removes some include files that are only referenced in one place. This will save us having to move them for the architecture merge and saves some lines as well. arch/ppc64/kernel/LparData.c | 116 +++++++++++++++++++++++++---- arch/ppc64/kernel/iSeries_setup.c | 11 ++ include/asm-ppc64/iSeries/HvCallSm.h | 38 --------- include/asm-ppc64/iSeries/HvReleaseData.h | 64 ---------------- include/asm-ppc64/iSeries/ItIplParmsReal.h | 71 ----------------- include/asm-ppc64/iSeries/ItSpCommArea.h | 37 --------- 6 files changed, 112 insertions(+), 225 deletions(-) -- 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/20050911/8a823ddc/attachment.pgp From sfr at canb.auug.org.au Sun Sep 11 01:37:34 2005 From: sfr at canb.auug.org.au (Stephen Rothwell) Date: Sun, 11 Sep 2005 01:37:34 +1000 Subject: [PATCH 1/4] iSeries: Remove include/asm-ppc64/iSeries/HvCallSm.h In-Reply-To: <20050911013515.404e46a2.sfr@canb.auug.org.au> References: <20050911013515.404e46a2.sfr@canb.auug.org.au> Message-ID: <20050911013734.7b0d111f.sfr@canb.auug.org.au> It is small and only used in one place. Signed-off-by: Stephen Rothwell --- arch/ppc64/kernel/iSeries_setup.c | 11 +++++++++- include/asm-ppc64/iSeries/HvCallSm.h | 38 ---------------------------------- 2 files changed, 10 insertions(+), 39 deletions(-) delete mode 100644 include/asm-ppc64/iSeries/HvCallSm.h -- Cheers, Stephen Rothwell sfr at canb.auug.org.au http://www.canb.auug.org.au/~sfr/ 2b9e02528315c8adb4a141465aaaa32b90ec0111 diff --git a/arch/ppc64/kernel/iSeries_setup.c b/arch/ppc64/kernel/iSeries_setup.c --- a/arch/ppc64/kernel/iSeries_setup.c +++ b/arch/ppc64/kernel/iSeries_setup.c @@ -48,10 +48,11 @@ #include #include #include +#include #include #include #include -#include +#include #include #include #include @@ -110,6 +111,14 @@ struct MemoryBlock { unsigned long logicalEnd; }; +#define HvCallSmGet64BitsOfAccessMap (HvCallSm + 11) + +static inline u64 HvCallSm_get64BitsOfAccessMap(HvLpIndex lpIndex, + u64 indexIntoBitMap) +{ + return HvCall2(HvCallSmGet64BitsOfAccessMap, lpIndex, indexIntoBitMap); +} + /* * Process the main store vpd to determine where the holes in memory are * and return the number of physical blocks and fill in the array of diff --git a/include/asm-ppc64/iSeries/HvCallSm.h b/include/asm-ppc64/iSeries/HvCallSm.h deleted file mode 100644 --- a/include/asm-ppc64/iSeries/HvCallSm.h +++ /dev/null @@ -1,38 +0,0 @@ -/* - * HvCallSm.h - * Copyright (C) 2001 Mike Corrigan 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 _HVCALLSM_H -#define _HVCALLSM_H - -/* - * This file contains the "hypervisor call" interface which is used to - * drive the hypervisor from the OS. - */ - -#include -#include - -#define HvCallSmGet64BitsOfAccessMap HvCallSm + 11 - -static inline u64 HvCallSm_get64BitsOfAccessMap(HvLpIndex lpIndex, - u64 indexIntoBitMap) -{ - return HvCall2(HvCallSmGet64BitsOfAccessMap, lpIndex, indexIntoBitMap); -} - -#endif /* _HVCALLSM_H */ From sfr at canb.auug.org.au Sun Sep 11 01:39:30 2005 From: sfr at canb.auug.org.au (Stephen Rothwell) Date: Sun, 11 Sep 2005 01:39:30 +1000 Subject: [PATCH 2/4] iSeries: Remove include/asm-ppc64/iSeries/HvReleaseData.h In-Reply-To: <20050911013734.7b0d111f.sfr@canb.auug.org.au> References: <20050911013515.404e46a2.sfr@canb.auug.org.au> <20050911013734.7b0d111f.sfr@canb.auug.org.au> Message-ID: <20050911013930.77b09243.sfr@canb.auug.org.au> It is only used in one place, so incorporate it there. Signed-off-by: Stephen Rothwell --- arch/ppc64/kernel/LparData.c | 41 +++++++++++++++++-- include/asm-ppc64/iSeries/HvReleaseData.h | 64 ----------------------------- 2 files changed, 37 insertions(+), 68 deletions(-) delete mode 100644 include/asm-ppc64/iSeries/HvReleaseData.h -- Cheers, Stephen Rothwell sfr at canb.auug.org.au http://www.canb.auug.org.au/~sfr/ 5cbab376775261658362d5fcaa6e12346f871b99 diff --git a/arch/ppc64/kernel/LparData.c b/arch/ppc64/kernel/LparData.c --- a/arch/ppc64/kernel/LparData.c +++ b/arch/ppc64/kernel/LparData.c @@ -19,7 +19,6 @@ #include #include #include -#include #include #include #include @@ -28,10 +27,44 @@ #include #include - -/* The HvReleaseData is the root of the information shared between - * the hypervisor and Linux. +/* + * The HvReleaseData is the root of the information shared between + * the hypervisor and Linux. + * + * hvReleaseData is referred to in head.S */ +/* + * When we IPL a secondary partition, we will check if if the + * secondary xMinPlicVrmIndex > the primary xVrmIndex. + * If it is then this tells PLIC that this secondary is not + * supported running on this "old" of a level of PLIC. + * + * Likewise, we will compare the primary xMinSlicVrmIndex to + * the secondary xVrmIndex. + * If the primary xMinSlicVrmDelta > secondary xVrmDelta then we + * know that this PLIC does not support running an OS "that old". + */ + +#define HVREL_TAGSINACTIVE 0x8000 +#define HVREL_32BIT 0x4000 +#define HVREL_NOSHAREDPROCS 0x2000 +#define HVREL_NOHMT 0x1000 + +struct HvReleaseData { + u32 xDesc; /* Descriptor "HvRD" ebcdic x00-x03 */ + u16 xSize; /* Size of this control block x04-x05 */ + u16 xVpdAreasPtrOffset; /* Offset in NACA of ItVpdAreas x06-x07 */ + struct naca_struct *xSlicNacaAddr; /* Virt addr of SLIC NACA x08-x0F */ + u32 xMsNucDataOffset; /* Offset of Linux Mapping Data x10-x13 */ + u32 xRsvd1; /* Reserved x14-x17 */ + u16 xFlags; + u16 xVrmIndex; /* VRM Index of OS image x1A-x1B */ + u16 xMinSupportedPlicVrmIndex; /* Min PLIC level (soft) x1C-x1D */ + u16 xMinCompatablePlicVrmIndex; /* Min PLIC levelP (hard) x1E-x1F */ + char xVrmName[12]; /* Displayable name x20-x2B */ + char xRsvd3[20]; /* Reserved x2C-x3F */ +}; + struct HvReleaseData hvReleaseData = { .xDesc = 0xc8a5d9c4, /* "HvRD" ebcdic */ .xSize = sizeof(struct HvReleaseData), diff --git a/include/asm-ppc64/iSeries/HvReleaseData.h b/include/asm-ppc64/iSeries/HvReleaseData.h deleted file mode 100644 --- a/include/asm-ppc64/iSeries/HvReleaseData.h +++ /dev/null @@ -1,64 +0,0 @@ -/* - * HvReleaseData.h - * Copyright (C) 2001 Mike Corrigan 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 _HVRELEASEDATA_H -#define _HVRELEASEDATA_H - -/* - * This control block contains the critical information about the - * release so that it can be changed in the future (ie, the virtual - * address of the OS's NACA). - */ -#include -#include - -/* - * When we IPL a secondary partition, we will check if if the - * secondary xMinPlicVrmIndex > the primary xVrmIndex. - * If it is then this tells PLIC that this secondary is not - * supported running on this "old" of a level of PLIC. - * - * Likewise, we will compare the primary xMinSlicVrmIndex to - * the secondary xVrmIndex. - * If the primary xMinSlicVrmDelta > secondary xVrmDelta then we - * know that this PLIC does not support running an OS "that old". - */ - -#define HVREL_TAGSINACTIVE 0x8000 -#define HVREL_32BIT 0x4000 -#define HVREL_NOSHAREDPROCS 0x2000 -#define HVREL_NOHMT 0x1000 - -struct HvReleaseData { - u32 xDesc; /* Descriptor "HvRD" ebcdic x00-x03 */ - u16 xSize; /* Size of this control block x04-x05 */ - u16 xVpdAreasPtrOffset; /* Offset in NACA of ItVpdAreas x06-x07 */ - struct naca_struct *xSlicNacaAddr; /* Virt addr of SLIC NACA x08-x0F */ - u32 xMsNucDataOffset; /* Offset of Linux Mapping Data x10-x13 */ - u32 xRsvd1; /* Reserved x14-x17 */ - u16 xFlags; - u16 xVrmIndex; /* VRM Index of OS image x1A-x1B */ - u16 xMinSupportedPlicVrmIndex; /* Min PLIC level (soft) x1C-x1D */ - u16 xMinCompatablePlicVrmIndex; /* Min PLIC levelP (hard) x1E-x1F */ - char xVrmName[12]; /* Displayable name x20-x2B */ - char xRsvd3[20]; /* Reserved x2C-x3F */ -}; - -extern struct HvReleaseData hvReleaseData; - -#endif /* _HVRELEASEDATA_H */ -------------- 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/20050911/faae622f/attachment.pgp From sfr at canb.auug.org.au Sun Sep 11 01:41:19 2005 From: sfr at canb.auug.org.au (Stephen Rothwell) Date: Sun, 11 Sep 2005 01:41:19 +1000 Subject: [PATCH 3/4] iSeries: Remove include/asm-ppc64/iSeries/ItIplParmsReal.h In-Reply-To: <20050911013930.77b09243.sfr@canb.auug.org.au> References: <20050911013515.404e46a2.sfr@canb.auug.org.au> <20050911013734.7b0d111f.sfr@canb.auug.org.au> <20050911013930.77b09243.sfr@canb.auug.org.au> Message-ID: <20050911014119.30e336cf.sfr@canb.auug.org.au> It is only used in one place so incorporate it there. Some small white space cleanups and make xItIplParmsReal static. Signed-off-by: Stephen Rothwell --- arch/ppc64/kernel/LparData.c | 61 +++++++++++++++++++++--- include/asm-ppc64/iSeries/ItIplParmsReal.h | 71 ---------------------------- 2 files changed, 53 insertions(+), 79 deletions(-) delete mode 100644 include/asm-ppc64/iSeries/ItIplParmsReal.h -- Cheers, Stephen Rothwell sfr at canb.auug.org.au http://www.canb.auug.org.au/~sfr/ 5801ac9224fdc35dd30f43b923a23be2879418ef diff --git a/arch/ppc64/kernel/LparData.c b/arch/ppc64/kernel/LparData.c --- a/arch/ppc64/kernel/LparData.c +++ b/arch/ppc64/kernel/LparData.c @@ -1,4 +1,4 @@ -/* +/* * Copyright 2001 Mike Corrigan, IBM Corp * * This program is free software; you can redistribute it and/or @@ -21,7 +21,6 @@ #include #include #include -#include #include #include #include @@ -65,6 +64,51 @@ struct HvReleaseData { char xRsvd3[20]; /* Reserved x2C-x3F */ }; +/* + * This struct maps the IPL Parameters DMA'd from the SP. + * + * Warning: + * This data must map in exactly 64 bytes and match the architecture for + * the IPL parms + */ + +struct ItIplParmsReal { + u8 xFormat; // Defines format of IplParms x00-x00 + u8 xRsvd01:6; // Reserved x01-x01 + u8 xAlternateSearch:1; // Alternate search indicator ... + u8 xUaSupplied:1; // UA Supplied on programmed IPL... + u8 xLsUaFormat; // Format byte for UA x02-x02 + u8 xRsvd02; // Reserved x03-x03 + u32 xLsUa; // LS UA x04-x07 + u32 xUnusedLsLid; // First OS LID to load x08-x0B + u16 xLsBusNumber; // LS Bus Number x0C-x0D + u8 xLsCardAdr; // LS Card Address x0E-x0E + u8 xLsBoardAdr; // LS Board Address x0F-x0F + u32 xRsvd03; // Reserved x10-x13 + u8 xSpcnPresent:1; // SPCN present x14-x14 + u8 xCpmPresent:1; // CPM present ... + u8 xRsvd04:6; // Reserved ... + u8 xRsvd05:4; // Reserved x15-x15 + u8 xKeyLock:4; // Keylock setting ... + u8 xRsvd06:6; // Reserved x16-x16 + u8 xIplMode:2; // Ipl mode (A|B|C|D) ... + u8 xHwIplType; // Fast v slow v slow EC HW IPL x17-x17 + u16 xCpmEnabledIpl:1; // CPM in effect when IPL initiatedx18-x19 + u16 xPowerOnResetIpl:1; // Indicate POR condition ... + u16 xMainStorePreserved:1; // Main Storage is preserved ... + u16 xRsvd07:13; // Reserved ... + u16 xIplSource:16; // Ipl source x1A-x1B + u8 xIplReason:8; // Reason for this IPL x1C-x1C + u8 xRsvd08; // Reserved x1D-x1D + u16 xRsvd09; // Reserved x1E-x1F + u16 xSysBoxType; // System Box Type x20-x21 + u16 xSysProcType; // System Processor Type x22-x23 + u32 xRsvd10; // Reserved x24-x27 + u64 xRsvd11; // Reserved x28-x2F + u64 xRsvd12; // Reserved x30-x37 + u64 xRsvd13; // Reserved x38-x3F +}; + struct HvReleaseData hvReleaseData = { .xDesc = 0xc8a5d9c4, /* "HvRD" ebcdic */ .xSize = sizeof(struct HvReleaseData), @@ -112,7 +156,7 @@ extern void trap_0e_iSeries(void); extern void performance_monitor_iSeries(void); extern void data_access_slb_iSeries(void); extern void instruction_access_slb_iSeries(void); - + struct ItLpNaca itLpNaca = { .xDesc = 0xd397d581, /* "LpNa" ebcdic */ .xSize = 0x0400, /* size of ItLpNaca */ @@ -139,7 +183,7 @@ struct ItLpNaca itLpNaca = { .xLoadAreaChunks = 0, /* chunks for load area */ .xPaseSysCallCRMask = 0, /* PASE mask */ .xSlicSegmentTablePtr = 0, /* seg table */ - .xOldLpQueue = { 0 }, /* Old LP Queue */ + .xOldLpQueue = { 0 }, /* Old LP Queue */ .xInterruptHdlr = { (u64)system_reset_iSeries, /* 0x100 System Reset */ (u64)machine_check_iSeries, /* 0x200 Machine Check */ @@ -167,7 +211,8 @@ struct ItLpNaca itLpNaca = { EXPORT_SYMBOL(itLpNaca); /* May be filled in by the hypervisor so cannot end up in the BSS */ -struct ItIplParmsReal xItIplParmsReal __attribute__((__section__(".data"))); +static struct ItIplParmsReal xItIplParmsReal + __attribute__((__section__(".data"))); /* May be filled in by the hypervisor so cannot end up in the BSS */ struct ItExtVpdPanel xItExtVpdPanel __attribute__((__section__(".data"))); @@ -184,7 +229,7 @@ struct IoHriProcessorVpd xIoHriProcessor .xPVR = 0x3600 } }; - + /* Space for Main Store Vpd 27,200 bytes */ /* May be filled in by the hypervisor so cannot end up in the BSS */ u64 xMsVpd[3400] __attribute__((__section__(".data"))); @@ -230,7 +275,7 @@ struct ItVpdAreas itVpdAreas = { 26992, /* 7 length of MS VPD */ 0, /* 8 */ sizeof(struct ItLpNaca),/* 9 length of LP Naca */ - 0, /* 10 */ + 0, /* 10 */ 256, /* 11 length of Recovery Log Buf */ sizeof(struct SpCommArea), /* 12 length of SP Comm Area */ 0,0,0, /* 13 - 15 */ @@ -240,7 +285,7 @@ struct ItVpdAreas itVpdAreas = { 0,0 /* 24 - 25 */ }, .xSlicVpdAdrs = { /* VPD addresses */ - 0,0,0, /* 0 - 2 */ + 0,0,0, /* 0 - 2 */ &xItExtVpdPanel, /* 3 Extended VPD */ &paca[0], /* 4 first Paca */ 0, /* 5 */ diff --git a/include/asm-ppc64/iSeries/ItIplParmsReal.h b/include/asm-ppc64/iSeries/ItIplParmsReal.h deleted file mode 100644 --- a/include/asm-ppc64/iSeries/ItIplParmsReal.h +++ /dev/null @@ -1,71 +0,0 @@ -/* - * ItIplParmsReal.h - * Copyright (C) 2001 Mike Corrigan 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 _ITIPLPARMSREAL_H -#define _ITIPLPARMSREAL_H - -/* - * This struct maps the IPL Parameters DMA'd from the SP. - * - * Warning: - * This data must map in exactly 64 bytes and match the architecture for - * the IPL parms - */ - -#include - -struct ItIplParmsReal { - u8 xFormat; // Defines format of IplParms x00-x00 - u8 xRsvd01:6; // Reserved x01-x01 - u8 xAlternateSearch:1; // Alternate search indicator ... - u8 xUaSupplied:1; // UA Supplied on programmed IPL... - u8 xLsUaFormat; // Format byte for UA x02-x02 - u8 xRsvd02; // Reserved x03-x03 - u32 xLsUa; // LS UA x04-x07 - u32 xUnusedLsLid; // First OS LID to load x08-x0B - u16 xLsBusNumber; // LS Bus Number x0C-x0D - u8 xLsCardAdr; // LS Card Address x0E-x0E - u8 xLsBoardAdr; // LS Board Address x0F-x0F - u32 xRsvd03; // Reserved x10-x13 - u8 xSpcnPresent:1; // SPCN present x14-x14 - u8 xCpmPresent:1; // CPM present ... - u8 xRsvd04:6; // Reserved ... - u8 xRsvd05:4; // Reserved x15-x15 - u8 xKeyLock:4; // Keylock setting ... - u8 xRsvd06:6; // Reserved x16-x16 - u8 xIplMode:2; // Ipl mode (A|B|C|D) ... - u8 xHwIplType; // Fast v slow v slow EC HW IPL x17-x17 - u16 xCpmEnabledIpl:1; // CPM in effect when IPL initiatedx18-x19 - u16 xPowerOnResetIpl:1; // Indicate POR condition ... - u16 xMainStorePreserved:1; // Main Storage is preserved ... - u16 xRsvd07:13; // Reserved ... - u16 xIplSource:16; // Ipl source x1A-x1B - u8 xIplReason:8; // Reason for this IPL x1C-x1C - u8 xRsvd08; // Reserved x1D-x1D - u16 xRsvd09; // Reserved x1E-x1F - u16 xSysBoxType; // System Box Type x20-x21 - u16 xSysProcType; // System Processor Type x22-x23 - u32 xRsvd10; // Reserved x24-x27 - u64 xRsvd11; // Reserved x28-x2F - u64 xRsvd12; // Reserved x30-x37 - u64 xRsvd13; // Reserved x38-x3F -}; - -extern struct ItIplParmsReal xItIplParmsReal; - -#endif /* _ITIPLPARMSREAL_H */ -------------- 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/20050911/660d01f0/attachment.pgp From sfr at canb.auug.org.au Sun Sep 11 01:42:55 2005 From: sfr at canb.auug.org.au (Stephen Rothwell) Date: Sun, 11 Sep 2005 01:42:55 +1000 Subject: [PATCH 4/4] iSeries: Remove include/asm-ppc64/iSeries/ItSpCommArea.h In-Reply-To: <20050911014119.30e336cf.sfr@canb.auug.org.au> References: <20050911013515.404e46a2.sfr@canb.auug.org.au> <20050911013734.7b0d111f.sfr@canb.auug.org.au> <20050911013930.77b09243.sfr@canb.auug.org.au> <20050911014119.30e336cf.sfr@canb.auug.org.au> Message-ID: <20050911014255.7c92290e.sfr@canb.auug.org.au> It is only used in one place, so incorporate it there. Make xSpCommArea static. Signed-off-by: Stephen Rothwell --- arch/ppc64/kernel/LparData.c | 14 ++++++++++- include/asm-ppc64/iSeries/ItSpCommArea.h | 37 ------------------------------ 2 files changed, 12 insertions(+), 39 deletions(-) delete mode 100644 include/asm-ppc64/iSeries/ItSpCommArea.h -- Cheers, Stephen Rothwell sfr at canb.auug.org.au http://www.canb.auug.org.au/~sfr/ 0d8c8cdaa0a1275050aef21b6642f03df95e7b99 diff --git a/arch/ppc64/kernel/LparData.c b/arch/ppc64/kernel/LparData.c --- a/arch/ppc64/kernel/LparData.c +++ b/arch/ppc64/kernel/LparData.c @@ -24,7 +24,6 @@ #include #include #include -#include /* * The HvReleaseData is the root of the information shared between @@ -109,6 +108,17 @@ struct ItIplParmsReal { u64 xRsvd13; // Reserved x38-x3F }; +struct SpCommArea { + u32 xDesc; // Descriptor (only in new formats) 000-003 + u8 xFormat; // Format (only in new formats) 004-004 + u8 xRsvd1[11]; // Reserved 005-00F + u64 xRawTbAtIplStart; // Raw HW TB value when IPL is started 010-017 + u64 xRawTodAtIplStart; // Raw HW TOD value when IPL is started 018-01F + u64 xBcdTimeAtIplStart; // BCD time when IPL is started 020-027 + u64 xBcdTimeAtOsStart; // BCD time when OS passed control 028-02F + u8 xRsvd2[80]; // Reserved 030-07F +}; + struct HvReleaseData hvReleaseData = { .xDesc = 0xc8a5d9c4, /* "HvRD" ebcdic */ .xSize = sizeof(struct HvReleaseData), @@ -238,7 +248,7 @@ u64 xMsVpd[3400] __attribute__((__sec /* May be filled in by the hypervisor so cannot end up in the BSS */ u64 xRecoveryLogBuffer[32] __attribute__((__section__(".data"))); -struct SpCommArea xSpCommArea = { +static struct SpCommArea xSpCommArea = { .xDesc = 0xE2D7C3C2, .xFormat = 1, }; diff --git a/include/asm-ppc64/iSeries/ItSpCommArea.h b/include/asm-ppc64/iSeries/ItSpCommArea.h deleted file mode 100644 --- a/include/asm-ppc64/iSeries/ItSpCommArea.h +++ /dev/null @@ -1,37 +0,0 @@ -/* - * ItSpCommArea.h - * Copyright (C) 2001 Mike Corrigan 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 _ITSPCOMMAREA_H -#define _ITSPCOMMAREA_H - - -struct SpCommArea { - u32 xDesc; // Descriptor (only in new formats) 000-003 - u8 xFormat; // Format (only in new formats) 004-004 - u8 xRsvd1[11]; // Reserved 005-00F - u64 xRawTbAtIplStart; // Raw HW TB value when IPL is started 010-017 - u64 xRawTodAtIplStart; // Raw HW TOD value when IPL is started 018-01F - u64 xBcdTimeAtIplStart; // BCD time when IPL is started 020-027 - u64 xBcdTimeAtOsStart; // BCD time when OS passed control 028-02F - u8 xRsvd2[80]; // Reserved 030-07F -}; - -extern struct SpCommArea xSpCommArea; - -#endif /* _ITSPCOMMAREA_H */ From sfr at canb.auug.org.au Sun Sep 11 02:04:37 2005 From: sfr at canb.auug.org.au (Stephen Rothwell) Date: Sun, 11 Sep 2005 02:04:37 +1000 Subject: [PATCH] powerpc: Move arch/ppc*/oprofile/Kconfig to arch/powerpc Message-ID: <20050911020437.1a690e1d.sfr@canb.auug.org.au> These files are identical. Signed-off-by: Stephen Rothwell --- arch/powerpc/oprofile/Kconfig | 23 +++++++++++++++++++++++ arch/ppc/Kconfig | 2 +- arch/ppc/oprofile/Kconfig | 23 ----------------------- arch/ppc64/Kconfig | 2 +- arch/ppc64/oprofile/Kconfig | 23 ----------------------- 5 files changed, 25 insertions(+), 48 deletions(-) create mode 100644 arch/powerpc/oprofile/Kconfig delete mode 100644 arch/ppc/oprofile/Kconfig delete mode 100644 arch/ppc64/oprofile/Kconfig -- Cheers, Stephen Rothwell sfr at canb.auug.org.au http://www.canb.auug.org.au/~sfr/ 8e32b39f684cae2125255e8c93faa2b45f8ffc58 diff --git a/arch/powerpc/oprofile/Kconfig b/arch/powerpc/oprofile/Kconfig new file mode 100644 --- /dev/null +++ b/arch/powerpc/oprofile/Kconfig @@ -0,0 +1,23 @@ + +menu "Profiling support" + depends on EXPERIMENTAL + +config PROFILING + bool "Profiling support (EXPERIMENTAL)" + help + Say Y here to enable the extended profiling support mechanisms used + by profilers such as OProfile. + + +config OPROFILE + tristate "OProfile system profiling (EXPERIMENTAL)" + depends on PROFILING + help + OProfile is a profiling system capable of profiling the + whole system, include the kernel, kernel modules, libraries, + and applications. + + If unsure, say N. + +endmenu + diff --git a/arch/ppc/Kconfig b/arch/ppc/Kconfig --- a/arch/ppc/Kconfig +++ b/arch/ppc/Kconfig @@ -1363,7 +1363,7 @@ endmenu source "lib/Kconfig" -source "arch/ppc/oprofile/Kconfig" +source "arch/powerpc/oprofile/Kconfig" source "arch/ppc/Kconfig.debug" diff --git a/arch/ppc/oprofile/Kconfig b/arch/ppc/oprofile/Kconfig deleted file mode 100644 --- a/arch/ppc/oprofile/Kconfig +++ /dev/null @@ -1,23 +0,0 @@ - -menu "Profiling support" - depends on EXPERIMENTAL - -config PROFILING - bool "Profiling support (EXPERIMENTAL)" - help - Say Y here to enable the extended profiling support mechanisms used - by profilers such as OProfile. - - -config OPROFILE - tristate "OProfile system profiling (EXPERIMENTAL)" - depends on PROFILING - help - OProfile is a profiling system capable of profiling the - whole system, include the kernel, kernel modules, libraries, - and applications. - - If unsure, say N. - -endmenu - diff --git a/arch/ppc64/Kconfig b/arch/ppc64/Kconfig --- a/arch/ppc64/Kconfig +++ b/arch/ppc64/Kconfig @@ -465,7 +465,7 @@ config VIOPATH depends on VIOCONS || VIODASD || VIOCD || VIOTAPE || VETH default y -source "arch/ppc64/oprofile/Kconfig" +source "arch/powerpc/oprofile/Kconfig" source "arch/ppc64/Kconfig.debug" diff --git a/arch/ppc64/oprofile/Kconfig b/arch/ppc64/oprofile/Kconfig deleted file mode 100644 --- a/arch/ppc64/oprofile/Kconfig +++ /dev/null @@ -1,23 +0,0 @@ - -menu "Profiling support" - depends on EXPERIMENTAL - -config PROFILING - bool "Profiling support (EXPERIMENTAL)" - help - Say Y here to enable the extended profiling support mechanisms used - by profilers such as OProfile. - - -config OPROFILE - tristate "OProfile system profiling (EXPERIMENTAL)" - depends on PROFILING - help - OProfile is a profiling system capable of profiling the - whole system, include the kernel, kernel modules, libraries, - and applications. - - If unsure, say N. - -endmenu - From trini at kernel.crashing.org Sun Sep 11 02:27:49 2005 From: trini at kernel.crashing.org (Tom Rini) Date: Sat, 10 Sep 2005 09:27:49 -0700 Subject: Time for linuxpowerpc-dev? In-Reply-To: <200509091225.45440.michael@ellerman.id.au> References: <200509091225.45440.michael@ellerman.id.au> Message-ID: <20050910162749.GB17038@smtp.west.cox.net> On Fri, Sep 09, 2005 at 12:25:45PM +1000, Michael Ellerman wrote: > With the arch's merging, and all this cross-posting maddness, is it time to > start a linuxpowerpc-dev mailing list? Nah, cross posting is best, until the merge is done and we can just kill ppc64*. -- Tom Rini http://gate.crashing.org/~trini/ From kumar.gala at freescale.com Sun Sep 11 03:29:07 2005 From: kumar.gala at freescale.com (Kumar Gala) Date: Sat, 10 Sep 2005 12:29:07 -0500 Subject: [patch 4/5] ppc64: Add definitions for new PTRACE calls In-Reply-To: <20050910060119.276430000@samba.org> References: <20050910060119.276430000@samba.org> Message-ID: <2EB7CE7E-6BEF-4E10-8A0A-42D39FA732CE@freescale.com> We really need further discussion on this. Book-E has a completely different HW debug model which this patch only partially comprehend. Is GDB being extended to support branch stepping? - kumar On Sep 10, 2005, at 1:01 AM, Anton Blanchard wrote: > - Add PTRACE_BRANCHSTEP. Like PTRACE_SINGLESTEP but takes an > exception at every branch. This might be worth putting in > include/linux/ptrace.h if other architectures are interested. > > - Add PTRACE_GET_DEBUGREG/PTRACE_SET_DEBUGREG. The definition is > as follows: > > /* > * Get or set a debug register. The first 16 are DABR registers and > the > * second 16 are IABR registers. > */ > #define PTRACE_GET_DEBUGREG 25 > #define PTRACE_SET_DEBUGREG 26 > > DABR == data breakpoint and IABR = instruction breakpoint in IBM > speak. We could split out the IABR into 2 more ptrace calls but I > figured there was no need and 16 DABR registers should be more > than enough (POWER4/POWER5 have one). > > - Add 2 new SIGTRAP si_codes: TRAP_HWBKPT and TRAP_BRANCH. I couldnt > find any standards on either of these so I copied what ia64 is > doing. Again this might be better placed in > include/asm-generic/siginfo.h > > Signed-off-by: Anton Blanchard > --- > > Index: build/include/asm-ppc/ptrace.h > =================================================================== > --- build.orig/include/asm-ppc/ptrace.h 2005-09-10 > 14:26:25.000000000 > +1000 > +++ build/include/asm-ppc/ptrace.h 2005-09-10 14:27:49.000000000 > +1000 > @@ -142,4 +142,13 @@ > #define PTRACE_GETEVRREGS 20 > #define PTRACE_SETEVRREGS 21 > > +#define PTRACE_BRANCHSTEP 22 > + > +/* > + * Get or set a debug register. The first 16 are DABR registers > and the > + * second 16 are IABR registers. > + */ > +#define PTRACE_GET_DEBUGREG 25 > +#define PTRACE_SET_DEBUGREG 26 > + > #endif > Index: build/include/asm-ppc64/ptrace.h > =================================================================== > --- build.orig/include/asm-ppc64/ptrace.h 2005-09-10 > 14:28:44.000000000 +1000 > +++ build/include/asm-ppc64/ptrace.h 2005-09-10 14:28:58.000000000 > +1000 > @@ -189,6 +189,15 @@ > #define PTRACE_SETEVRREGS 21 > #endif > > +#define PTRACE_BRANCHSTEP 22 > + > +/* > + * Get or set a debug register. The first 16 are DABR registers > and the > + * second 16 are IABR registers. > + */ > +#define PTRACE_GET_DEBUGREG 25 > +#define PTRACE_SET_DEBUGREG 26 > + > /* Additional PTRACE requests implemented on PowerPC. */ > #define PPC_PTRACE_GETREGS 0x99 /* Get GPRs 0 - 31 */ > #define PPC_PTRACE_SETREGS 0x98 /* Set GPRs 0 - 31 */ > Index: build/include/asm-powerpc/siginfo.h > =================================================================== > --- build.orig/include/asm-powerpc/siginfo.h 2005-09-10 > 13:29:48.000000000 +1000 > +++ build/include/asm-powerpc/siginfo.h 2005-09-10 > 13:29:54.000000000 > +1000 > @@ -15,4 +15,12 @@ > > #include > > +/* > + * SIGTRAP si_codes > + */ > +#define TRAP_BRANCH (__SI_FAULT|3) /* process taken branch > trap */ > +#define TRAP_HWBKPT (__SI_FAULT|4) /* hardware breakpoint or > watchpoint */ > +#undef NSIGTRAP > +#define NSIGTRAP 4 > + > #endif /* _ASM_POWERPC_SIGINFO_H */ > > -- > > _______________________________________________ > Linuxppc64-dev mailing list > Linuxppc64-dev at ozlabs.org > https://ozlabs.org/mailman/listinfo/linuxppc64-dev > From roland at redhat.com Sun Sep 11 05:21:37 2005 From: roland at redhat.com (Roland McGrath) Date: Sat, 10 Sep 2005 12:21:37 -0700 (PDT) Subject: [patch 4/5] ppc64: Add definitions for new PTRACE calls In-Reply-To: Anton Blanchard's message of Saturday, 10 September 2005 16:01:10 +1000 <20050910060119.276430000@samba.org> Message-ID: <20050910192137.94C44180A17@magilla.sf.frob.com> > - Add PTRACE_BRANCHSTEP. Like PTRACE_SINGLESTEP but takes an > exception at every branch. This might be worth putting in > include/linux/ptrace.h if other architectures are interested. The other machines that define this now call it PTRACE_SINGLEBLOCK (ia64, pa). (It can also be implemented on modern x86 chips, and I'll get around to that one of these days.) Thanks, Roland From hch at lst.de Sun Sep 11 05:30:10 2005 From: hch at lst.de (Christoph Hellwig) Date: Sat, 10 Sep 2005 21:30:10 +0200 Subject: [PATCH 1/4] iSeries: Remove include/asm-ppc64/iSeries/HvCallSm.h In-Reply-To: <20050911013734.7b0d111f.sfr@canb.auug.org.au> References: <20050911013515.404e46a2.sfr@canb.auug.org.au> <20050911013734.7b0d111f.sfr@canb.auug.org.au> Message-ID: <20050910193010.GA29716@lst.de> On Sun, Sep 11, 2005 at 01:37:34AM +1000, Stephen Rothwell wrote: > +#define HvCallSmGet64BitsOfAccessMap (HvCallSm + 11) Shouldn't there be a sinle header for all the HvCall constants? > + > +static inline u64 HvCallSm_get64BitsOfAccessMap(HvLpIndex lpIndex, > + u64 indexIntoBitMap) > +{ > + return HvCall2(HvCallSmGet64BitsOfAccessMap, lpIndex, indexIntoBitMap); > +} this is used only in a single place, no need for the wrapper at all. From hch at lst.de Sun Sep 11 05:31:39 2005 From: hch at lst.de (Christoph Hellwig) Date: Sat, 10 Sep 2005 21:31:39 +0200 Subject: [PATCH 3/4] iSeries: Remove include/asm-ppc64/iSeries/ItIplParmsReal.h In-Reply-To: <20050911014119.30e336cf.sfr@canb.auug.org.au> References: <20050911013515.404e46a2.sfr@canb.auug.org.au> <20050911013734.7b0d111f.sfr@canb.auug.org.au> <20050911013930.77b09243.sfr@canb.auug.org.au> <20050911014119.30e336cf.sfr@canb.auug.org.au> Message-ID: <20050910193139.GB29716@lst.de> On Sun, Sep 11, 2005 at 01:41:19AM +1000, Stephen Rothwell wrote: > It is only used in one place so incorporate it there. > > Some small white space cleanups and make xItIplParmsReal > static. In general having any interfaces to other systems in headers sounds like a good idea so no one touches it accdidentally. Shouldn't there be a single header somewhere that defines all the hypevisor interface? From benh at kernel.crashing.org Sun Sep 11 07:58:18 2005 From: benh at kernel.crashing.org (Benjamin Herrenschmidt) Date: Sun, 11 Sep 2005 07:58:18 +1000 Subject: iMac G5 frequency switching In-Reply-To: <20050909114311.GA3732@victor.rh.local> References: <20050909114311.GA3732@victor.rh.local> Message-ID: <1126389498.29803.58.camel@gaston> On Fri, 2005-09-09 at 13:43 +0200, Markus Demleitner wrote: > Hi, > > I've figured out how to switch frequencies of the iMac G5 CPU (at > least for my 1600 MHz models) and at that opportunity found that OF > puts the machine into half speed on boot, and that's what Linux got, > then. Hehe, I'm not surprised :) Good job. > This is bad news for the solution of the riddle how Apple keeps the > fans that quiet while I need to run them, since clearly it's not > because they run the machine at half speed most of the time. Running > the machine at full speed under Linux has the fans roaring even on an > idle machine, at least when you've got about 30 degrees outside > temperature. OS X keeps the thing quiet, even though not drawing > considerably less power. > > I've written the cpufreq driver as an external module for now, since > there's no "platforms" subdir in arch/ppc64 yet (which is where the > pmac_cpufreq driver resides in ppc). Here's the code: Why would you _need_ a platform subdir ? just add a pmac_cpufreq in arch/ppc64/kernel for now... > http://tucana.cl.uni-heidelberg.de/imacg5/g5-cpufreq-0.01.tar.gz > > I don't do any voltage stuff myself, mainly because OF doesn't > either. If anyone knows if I should, please let me know. OF does set voltage no ? You definitely should as this is where you save the most power. It can be done by getting the target voltage for the requested frequency divisor from the SMU partition data in the device-tree and calling the appropriate SMU function iirc (I don't have this in mind, but I figured it out a while ago, it wasn't too hard). > Apart from the functions that actually do the switch this is > completely untested, because compiling cpufreq itself into the kernel > (I've simply hacked arch/ppc64/Kconfig to source the Kconfig) yields > a kernel that locks up. I figure I could spend weeks trying to find > out why, so here's my plea to the ppc64 gods: Could anyone have a > look at why cpufreq without any cpu drivers loaded would lock the > machine at boot time? Hrm... > Two somewhat related notes: > > (a) I've set up a page with hints on running linux on the iMac G5. > If this is a duplicate effort, let me know and I'll pull the page. > > (b) On that page, I link to benh's first SMU patch as the one to > apply (from > http://ozlabs.org/pipermail/linuxppc64-dev/2005-April/003835.html). > In the meantime, benh has put out a newer SMU patch -- however, that > one won't compile with vanilla 2.6.13 (it's lacking struct of_match, > OF_ANY_MATCH and some others, and I gave up on it after fiddling for > a while), whereas the one I used does. That's an excuse to benh for > having ignored the second patch. Heheh, ok, I'll check that out. I'll be away for about a week though. I'll see if I find time to send a fixed up patch today. If not, it will have to wait. > And then a last question: > > The nap/doze stuff the G5 can do sounds nifty and might be part of > the explanation for the thermal trouble. It's G5 generic and thus > I'm wondering if anyone has given putting it into Linux any thought > already. Unless we missed something, the kernel should NAP when idle already on the G5. __setup_cpu_ppc970() will set the NAP HID bit and native_idle will be used which triggers MSR:POW. Another thing OS X does btw is, afaik, slow down the video chip... Ben. From anton at samba.org Sun Sep 11 13:40:13 2005 From: anton at samba.org (Anton Blanchard) Date: Sun, 11 Sep 2005 13:40:13 +1000 Subject: [PATCH 1/2] ppc64: zimage build fix In-Reply-To: <42FAA282.9040701@am.sony.com> References: <42FAA282.9040701@am.sony.com> Message-ID: <20050911034013.GA2016@krispykreme> Hi Geoff, > Please consider for inclusion in the post 2.6.13 patches. I get the following warnings when building current -git with the defconfig: home/anton/build/arch/ppc64/Makefile:97: target `zImage' given more than once in the same rule. /home/anton/build/arch/ppc64/Makefile:97: target `zImage.initrd' given more than once in the same rule. /home/anton/build/arch/ppc64/Makefile:97: target `zImage' given more than once in the same rule. /home/anton/build/arch/ppc64/Makefile:97: target `zImage.initrd' given more than once in the same rule. Anton > This patch makes it possible to build ppc64 kernel image files for all > targeted machines when several CONFIG_PPC_XXX machine type options are > enabled simultaneously. To accomplish this it introduces two new build > targets, zImage.rs6k and zImage.initrd.rs6, which will make the proper > ELF note header needed by pSeries machines. It falls out from these > changes that compressed zImages for the Powermac G5 can now be built. > Previously only vmlinux images could be for that machine. > > One remaining problem not addressed by this patch is how to specify the > 'make install' target when several CONFIG_PPC_XXX machine type options are > enabled simultaneously. > > Signed-off-by: Geoff Levand > > > Index: linux-2.6.13-rc6.ppc64-makefile/arch/ppc64/Makefile > =================================================================== > --- linux-2.6.13-rc6.ppc64-makefile.orig/arch/ppc64/Makefile 2005-08-10 17:30:56.000000000 -0700 > +++ linux-2.6.13-rc6.ppc64-makefile/arch/ppc64/Makefile 2005-08-10 17:34:01.000000000 -0700 > @@ -87,14 +87,15 @@ > > boot := arch/ppc64/boot > > -boottarget-$(CONFIG_PPC_PSERIES) := zImage zImage.initrd > -boottarget-$(CONFIG_PPC_MAPLE) := zImage zImage.initrd > -boottarget-$(CONFIG_PPC_ISERIES) := vmlinux.sminitrd vmlinux.initrd vmlinux.sm > -boottarget-$(CONFIG_PPC_BPA) := zImage zImage.initrd > -$(boottarget-y): vmlinux > +boottargets-$(CONFIG_PPC_PSERIES) += zImage.rs6k zImage.initrd.rs6k > +boottargets-$(CONFIG_PPC_PMAC) += zImage zImage.initrd > +boottargets-$(CONFIG_PPC_MAPLE) += zImage zImage.initrd > +boottargets-$(CONFIG_PPC_ISERIES) += vmlinux.sminitrd vmlinux.initrd vmlinux.sm > +boottargets-$(CONFIG_PPC_BPA) += zImage zImage.initrd > +$(boottargets-y): vmlinux > $(Q)$(MAKE) $(build)=$(boot) $(boot)/$@ > > -bootimage-$(CONFIG_PPC_PSERIES) := $(boot)/zImage > +bootimage-$(CONFIG_PPC_PSERIES) := $(boot)/zImage.rs6k > bootimage-$(CONFIG_PPC_PMAC) := vmlinux > bootimage-$(CONFIG_PPC_MAPLE) := $(boot)/zImage > bootimage-$(CONFIG_PPC_BPA) := zImage > @@ -103,7 +104,7 @@ > install: vmlinux > $(Q)$(MAKE) $(build)=$(boot) BOOTIMAGE=$(BOOTIMAGE) $@ > > -defaultimage-$(CONFIG_PPC_PSERIES) := zImage > +defaultimage-$(CONFIG_PPC_PSERIES) := zImage.rs6k > defaultimage-$(CONFIG_PPC_PMAC) := vmlinux > defaultimage-$(CONFIG_PPC_MAPLE) := zImage > defaultimage-$(CONFIG_PPC_ISERIES) := vmlinux > @@ -122,10 +123,12 @@ > $(call filechk,gen-asm-offsets) > > define archhelp > - echo '* zImage - Compressed kernel image (arch/$(ARCH)/boot/zImage)' > - echo ' zImage.initrd- Compressed kernel image with initrd attached,' > - echo ' sourced from arch/$(ARCH)/boot/ramdisk.image.gz' > - echo ' (arch/$(ARCH)/boot/zImage.initrd)' > + echo ' zImage - Compressed kernel image (arch/$(ARCH)/boot/zImage)' > + echo ' zImage.initrd - Compressed kernel image with initrd attached,' > + echo ' sourced from arch/$(ARCH)/boot/ramdisk.image.gz' > + echo ' (arch/$(ARCH)/boot/zImage.initrd)' > + echo ' zImage.rs6k - zImage for pSeries machines' > + echo ' zImage.initrd.rs6k- zImage with initrd for pSeries machines' > endef > > CLEAN_FILES += include/asm-ppc64/offsets.h > Index: linux-2.6.13-rc6.ppc64-makefile/arch/ppc64/boot/Makefile > =================================================================== > --- linux-2.6.13-rc6.ppc64-makefile.orig/arch/ppc64/boot/Makefile 2005-08-10 17:30:56.000000000 -0700 > +++ linux-2.6.13-rc6.ppc64-makefile/arch/ppc64/boot/Makefile 2005-08-10 17:34:01.000000000 -0700 > @@ -37,6 +37,9 @@ > quiet_cmd_bootas = BOOTAS $@ > cmd_bootas = $(CROSS32CC) -Wp,-MD,$(depfile) $(BOOTAFLAGS) -c -o $@ $< > > +quiet_cmd_bootld = BOOTLD $@ > + cmd_bootld = $(CROSS32LD) $(BOOTLFLAGS) -o $@ $(2) > + > $(patsubst %.c,%.o, $(filter %.c, $(src-boot))): %.o: %.c > $(call if_changed_dep,bootcc) > $(patsubst %.S,%.o, $(filter %.S, $(src-boot))): %.o: %.S > @@ -75,8 +78,8 @@ > --add-section=.kernel:$(strip $(patsubst $(obj)/kernel-%.o,%, $(1)))=$(patsubst %.o,%.gz, $(1)) \ > --set-section-flags=.kernel:$(strip $(patsubst $(obj)/kernel-%.o,%, $(1)))=$(OBJCOPYFLAGS) > > -quiet_cmd_addnote = ADDNOTE $@ > - cmd_addnote = $(CROSS32LD) $(BOOTLFLAGS) -o $@ $(obj-boot) && $(obj)/addnote $@ > +quiet_cmd_addnote = ADDNOTE $@ > + cmd_addnote = $(obj)/addnote $@ > > $(call gz-sec, $(required)): $(obj)/kernel-%.gz: % FORCE > $(call if_changed,gzip) > @@ -92,11 +95,19 @@ > $(call addsection, $@) > > $(obj)/zImage: obj-boot += $(call obj-sec, $(required)) > -$(obj)/zImage: $(call obj-sec, $(required)) $(obj-boot) $(obj)/addnote FORCE > - $(call if_changed,addnote) > +$(obj)/zImage: $(call obj-sec, $(required)) $(obj-boot) FORCE > + $(call cmd,bootld,$(obj-boot)) > > $(obj)/zImage.initrd: obj-boot += $(call obj-sec, $(required) $(initrd)) > -$(obj)/zImage.initrd: $(call obj-sec, $(required) $(initrd)) $(obj-boot) $(obj)/addnote FORCE > +$(obj)/zImage.initrd: $(call obj-sec, $(required) $(initrd)) $(obj-boot) FORCE > + $(call cmd,bootld,$(obj-boot)) > + > +$(obj)/zImage.rs6k: $(obj)/zImage $(obj)/addnote FORCE > + @cp -f $< $@ > + $(call if_changed,addnote) > + > +$(obj)/zImage.initrd.rs6k: $(obj)/zImage.initrd $(obj)/addnote FORCE > + @cp -f $< $@ > $(call if_changed,addnote) > > $(obj)/imagesize.c: vmlinux.strip > > _______________________________________________ > Linuxppc64-dev mailing list > Linuxppc64-dev at ozlabs.org > https://ozlabs.org/mailman/listinfo/linuxppc64-dev From anton at samba.org Mon Sep 12 12:53:21 2005 From: anton at samba.org (Anton Blanchard) Date: Mon, 12 Sep 2005 12:53:21 +1000 Subject: [patch 4/5] ppc64: Add definitions for new PTRACE calls In-Reply-To: <20050910192137.94C44180A17@magilla.sf.frob.com> References: <20050910060119.276430000@samba.org> <20050910192137.94C44180A17@magilla.sf.frob.com> Message-ID: <20050912025321.GA5382@krispykreme> > The other machines that define this now call it PTRACE_SINGLEBLOCK (ia64, pa). > (It can also be implemented on modern x86 chips, and I'll get around to > that one of these days.) OK lets leave that part out and just get the data breakpoint support in. Anton Remove PTRACE_BRANCHSTEP, we need to work on something useful to other architectures. Signed-off-by: Anton Blanchard --- Index: build/include/asm-ppc/ptrace.h =================================================================== --- build.orig/include/asm-ppc/ptrace.h 2005-09-12 12:06:11.000000000 +1000 +++ build/include/asm-ppc/ptrace.h 2005-09-12 12:06:36.000000000 +1000 @@ -142,8 +142,6 @@ #define PTRACE_GETEVRREGS 20 #define PTRACE_SETEVRREGS 21 -#define PTRACE_BRANCHSTEP 22 - /* * Get or set a debug register. The first 16 are DABR registers and the * second 16 are IABR registers. Index: build/include/asm-ppc64/ptrace.h =================================================================== --- build.orig/include/asm-ppc64/ptrace.h 2005-09-12 12:06:11.000000000 +1000 +++ build/include/asm-ppc64/ptrace.h 2005-09-12 12:06:40.000000000 +1000 @@ -189,8 +189,6 @@ #define PTRACE_SETEVRREGS 21 #endif -#define PTRACE_BRANCHSTEP 22 - /* * Get or set a debug register. The first 16 are DABR registers and the * second 16 are IABR registers. From anton at samba.org Mon Sep 12 13:12:11 2005 From: anton at samba.org (Anton Blanchard) Date: Mon, 12 Sep 2005 13:12:11 +1000 Subject: [PATCH] ppc64: xics cleanup Message-ID: <20050912031211.GB5382@krispykreme> A few xics cleanups: - Make some things static. - Be more consistent with error printing - interrupts are unsigned, error values are signed. Signed-off-by: Anton Blanchard --- Index: build/arch/ppc64/kernel/xics.c =================================================================== --- build.orig/arch/ppc64/kernel/xics.c 2005-09-05 16:11:18.000000000 +1000 +++ build/arch/ppc64/kernel/xics.c 2005-09-05 21:29:46.000000000 +1000 @@ -38,7 +38,7 @@ static void xics_end_irq(unsigned int irq); static void xics_set_affinity(unsigned int irq_nr, cpumask_t cpumask); -struct hw_interrupt_type xics_pic = { +static struct hw_interrupt_type xics_pic = { .typename = " XICS ", .startup = xics_startup, .enable = xics_enable_irq, @@ -48,7 +48,7 @@ .set_affinity = xics_set_affinity }; -struct hw_interrupt_type xics_8259_pic = { +static struct hw_interrupt_type xics_8259_pic = { .typename = " XICS/8259", .ack = xics_mask_and_ack_irq, }; @@ -89,9 +89,8 @@ static int xics_irq_8259_cascade = 0; static int xics_irq_8259_cascade_real = 0; static unsigned int default_server = 0xFF; -/* also referenced in smp.c... */ -unsigned int default_distrib_server = 0; -unsigned int interrupt_server_size = 8; +static unsigned int default_distrib_server = 0; +static unsigned int interrupt_server_size = 8; /* * XICS only has a single IPI, so encode the messages per CPU @@ -99,10 +98,10 @@ struct xics_ipi_struct xics_ipi_message[NR_CPUS] __cacheline_aligned; /* RTAS service tokens */ -int ibm_get_xive; -int ibm_set_xive; -int ibm_int_on; -int ibm_int_off; +static int ibm_get_xive; +static int ibm_set_xive; +static int ibm_int_on; +static int ibm_int_off; typedef struct { int (*xirr_info_get)(int cpu); @@ -284,16 +283,17 @@ call_status = rtas_call(ibm_set_xive, 3, 1, NULL, irq, server, DEFAULT_PRIORITY); if (call_status != 0) { - printk(KERN_ERR "xics_enable_irq: irq=%d: ibm_set_xive " - "returned %x\n", irq, call_status); + printk(KERN_ERR "xics_enable_irq: irq=%u: ibm_set_xive " + "returned %d\n", irq, call_status); + printk("set_xive %x, server %x\n", ibm_set_xive, server); return; } /* Now unmask the interrupt (often a no-op) */ call_status = rtas_call(ibm_int_on, 1, 1, NULL, irq); if (call_status != 0) { - printk(KERN_ERR "xics_enable_irq: irq=%d: ibm_int_on " - "returned %x\n", irq, call_status); + printk(KERN_ERR "xics_enable_irq: irq=%u: ibm_int_on " + "returned %d\n", irq, call_status); return; } } @@ -308,8 +308,8 @@ call_status = rtas_call(ibm_int_off, 1, 1, NULL, irq); if (call_status != 0) { - printk(KERN_ERR "xics_disable_real_irq: irq=%d: " - "ibm_int_off returned %x\n", irq, call_status); + printk(KERN_ERR "xics_disable_real_irq: irq=%u: " + "ibm_int_off returned %d\n", irq, call_status); return; } @@ -317,8 +317,8 @@ /* Have to set XIVE to 0xff to be able to remove a slot */ call_status = rtas_call(ibm_set_xive, 3, 1, NULL, irq, server, 0xff); if (call_status != 0) { - printk(KERN_ERR "xics_disable_irq: irq=%d: ibm_set_xive(0xff)" - " returned %x\n", irq, call_status); + printk(KERN_ERR "xics_disable_irq: irq=%u: ibm_set_xive(0xff)" + " returned %d\n", irq, call_status); return; } } @@ -380,7 +380,7 @@ if (irq == NO_IRQ) irq = real_irq_to_virt_slowpath(vec); if (irq == NO_IRQ) { - printk(KERN_ERR "Interrupt %d (real) is invalid," + printk(KERN_ERR "Interrupt %u (real) is invalid," " disabling it.\n", vec); xics_disable_real_irq(vec); } else @@ -622,7 +622,7 @@ status = rtas_call(ibm_get_xive, 1, 3, xics_status, irq); if (status) { - printk(KERN_ERR "xics_set_affinity: irq=%d ibm,get-xive " + printk(KERN_ERR "xics_set_affinity: irq=%u ibm,get-xive " "returns %d\n", irq, status); return; } @@ -641,7 +641,7 @@ irq, newmask, xics_status[1]); if (status) { - printk(KERN_ERR "xics_set_affinity: irq=%d ibm,set-xive " + printk(KERN_ERR "xics_set_affinity: irq=%u ibm,set-xive " "returns %d\n", irq, status); return; } @@ -720,7 +720,7 @@ status = rtas_call(ibm_get_xive, 1, 3, xics_status, irq); if (status) { - printk(KERN_ERR "migrate_irqs_away: irq=%d " + printk(KERN_ERR "migrate_irqs_away: irq=%u " "ibm,get-xive returns %d\n", virq, status); goto unlock; @@ -734,7 +734,7 @@ if (xics_status[0] != get_hard_smp_processor_id(cpu)) goto unlock; - printk(KERN_WARNING "IRQ %d affinity broken off cpu %u\n", + printk(KERN_WARNING "IRQ %u affinity broken off cpu %u\n", virq, cpu); /* Reset affinity to all cpus */ From anton at samba.org Mon Sep 12 13:14:26 2005 From: anton at samba.org (Anton Blanchard) Date: Mon, 12 Sep 2005 13:14:26 +1000 Subject: [PATCH] ppc64: indent pci code Message-ID: <20050912031426.GC5382@krispykreme> Fix up some badly indented code. Signed-off-by: Anton Blanchard --- Index: build/arch/ppc64/kernel/pmac_pci.c =================================================================== --- build.orig/arch/ppc64/kernel/pmac_pci.c 2005-09-05 16:11:18.000000000 +1000 +++ build/arch/ppc64/kernel/pmac_pci.c 2005-09-05 21:42:10.000000000 +1000 @@ -388,7 +388,7 @@ * the reg address cell, we shall fix that by killing struct * reg_property and using some accessor functions instead */ - hose->first_busno = 0xf0; + hose->first_busno = 0xf0; hose->last_busno = 0xff; has_uninorth = 1; hose->ops = ¯isc_pci_ops; @@ -473,7 +473,7 @@ continue; } cur++; - DBG("U3/HT: hole, %d end at %08lx, %d start at %08lx\n", + DBG("U3/HT: hole, %d end at %08lx, %d start at %08lx\n", cur-1, res->start - 1, cur, res->end + 1); hose->mem_resources[cur].name = np->full_name; hose->mem_resources[cur].flags = IORESOURCE_MEM; @@ -603,24 +603,24 @@ char* disp_name; int *bus_range; int primary = 1; - struct property *of_prop; + struct property *of_prop; DBG("Adding PCI host bridge %s\n", dev->full_name); - bus_range = (int *) get_property(dev, "bus-range", &len); - if (bus_range == NULL || len < 2 * sizeof(int)) { - printk(KERN_WARNING "Can't get bus-range for %s, assume bus 0\n", - dev->full_name); - } + bus_range = (int *) get_property(dev, "bus-range", &len); + if (bus_range == NULL || len < 2 * sizeof(int)) { + printk(KERN_WARNING "Can't get bus-range for %s, assume bus 0\n", + dev->full_name); + } hose = alloc_bootmem(sizeof(struct pci_controller)); if (hose == NULL) return -ENOMEM; - pci_setup_pci_controller(hose); + pci_setup_pci_controller(hose); - hose->arch_data = dev; - hose->first_busno = bus_range ? bus_range[0] : 0; - hose->last_busno = bus_range ? bus_range[1] : 0xff; + hose->arch_data = dev; + hose->first_busno = bus_range ? bus_range[0] : 0; + hose->last_busno = bus_range ? bus_range[1] : 0xff; of_prop = alloc_bootmem(sizeof(struct property) + sizeof(hose->global_number)); @@ -634,24 +634,24 @@ } disp_name = NULL; - if (device_is_compatible(dev, "u3-agp")) { - setup_u3_agp(hose); - disp_name = "U3-AGP"; - primary = 0; - } else if (device_is_compatible(dev, "u3-ht")) { - setup_u3_ht(hose); - disp_name = "U3-HT"; - primary = 1; - } - printk(KERN_INFO "Found %s PCI host bridge. Firmware bus number: %d->%d\n", - disp_name, hose->first_busno, hose->last_busno); - - /* Interpret the "ranges" property */ - /* This also maps the I/O region and sets isa_io/mem_base */ - pmac_process_bridge_OF_ranges(hose, dev, primary); + if (device_is_compatible(dev, "u3-agp")) { + setup_u3_agp(hose); + disp_name = "U3-AGP"; + primary = 0; + } else if (device_is_compatible(dev, "u3-ht")) { + setup_u3_ht(hose); + disp_name = "U3-HT"; + primary = 1; + } + printk(KERN_INFO "Found %s PCI host bridge. Firmware bus number: %d->%d\n", + disp_name, hose->first_busno, hose->last_busno); + + /* Interpret the "ranges" property */ + /* This also maps the I/O region and sets isa_io/mem_base */ + pmac_process_bridge_OF_ranges(hose, dev, primary); - /* Fixup "bus-range" OF property */ - fixup_bus_range(dev); + /* Fixup "bus-range" OF property */ + fixup_bus_range(dev); return 0; } Index: build/arch/ppc64/kernel/maple_pci.c =================================================================== --- build.orig/arch/ppc64/kernel/maple_pci.c 2005-09-05 16:11:18.000000000 +1000 +++ build/arch/ppc64/kernel/maple_pci.c 2005-09-05 21:42:10.000000000 +1000 @@ -283,7 +283,7 @@ * the reg address cell, we shall fix that by killing struct * reg_property and using some accessor functions instead */ - hose->first_busno = 0xf0; + hose->first_busno = 0xf0; hose->last_busno = 0xff; hose->ops = &u3_agp_pci_ops; hose->cfg_addr = ioremap(0xf0000000 + 0x800000, 0x1000); @@ -315,24 +315,24 @@ char* disp_name; int *bus_range; int primary = 1; - struct property *of_prop; + struct property *of_prop; DBG("Adding PCI host bridge %s\n", dev->full_name); - bus_range = (int *) get_property(dev, "bus-range", &len); - if (bus_range == NULL || len < 2 * sizeof(int)) { - printk(KERN_WARNING "Can't get bus-range for %s, assume bus 0\n", - dev->full_name); - } + bus_range = (int *) get_property(dev, "bus-range", &len); + if (bus_range == NULL || len < 2 * sizeof(int)) { + printk(KERN_WARNING "Can't get bus-range for %s, assume bus 0\n", + dev->full_name); + } hose = alloc_bootmem(sizeof(struct pci_controller)); if (hose == NULL) return -ENOMEM; - pci_setup_pci_controller(hose); + pci_setup_pci_controller(hose); - hose->arch_data = dev; - hose->first_busno = bus_range ? bus_range[0] : 0; - hose->last_busno = bus_range ? bus_range[1] : 0xff; + hose->arch_data = dev; + hose->first_busno = bus_range ? bus_range[0] : 0; + hose->last_busno = bus_range ? bus_range[1] : 0xff; of_prop = alloc_bootmem(sizeof(struct property) + sizeof(hose->global_number)); @@ -346,25 +346,25 @@ } disp_name = NULL; - if (device_is_compatible(dev, "u3-agp")) { - setup_u3_agp(hose); - disp_name = "U3-AGP"; - primary = 0; - } else if (device_is_compatible(dev, "u3-ht")) { - setup_u3_ht(hose); - disp_name = "U3-HT"; - primary = 1; - } - printk(KERN_INFO "Found %s PCI host bridge. Firmware bus number: %d->%d\n", - disp_name, hose->first_busno, hose->last_busno); - - /* Interpret the "ranges" property */ - /* This also maps the I/O region and sets isa_io/mem_base */ - pci_process_bridge_OF_ranges(hose, dev); + if (device_is_compatible(dev, "u3-agp")) { + setup_u3_agp(hose); + disp_name = "U3-AGP"; + primary = 0; + } else if (device_is_compatible(dev, "u3-ht")) { + setup_u3_ht(hose); + disp_name = "U3-HT"; + primary = 1; + } + printk(KERN_INFO "Found %s PCI host bridge. Firmware bus number: %d->%d\n", + disp_name, hose->first_busno, hose->last_busno); + + /* Interpret the "ranges" property */ + /* This also maps the I/O region and sets isa_io/mem_base */ + pci_process_bridge_OF_ranges(hose, dev); pci_setup_phb_io(hose, primary); - /* Fixup "bus-range" OF property */ - fixup_bus_range(dev); + /* Fixup "bus-range" OF property */ + fixup_bus_range(dev); return 0; } Index: build/arch/ppc64/kernel/iSeries_pci.c =================================================================== --- build.orig/arch/ppc64/kernel/iSeries_pci.c 2005-09-05 16:11:18.000000000 +1000 +++ build/arch/ppc64/kernel/iSeries_pci.c 2005-09-05 21:42:10.000000000 +1000 @@ -252,7 +252,7 @@ phb = (struct pci_controller *)kmalloc(sizeof(struct pci_controller), GFP_KERNEL); if (phb == NULL) return -ENOMEM; - pci_setup_pci_controller(phb); + pci_setup_pci_controller(phb); phb->pci_mem_offset = phb->local_number = bus; phb->first_busno = bus; From anton at samba.org Mon Sep 12 13:17:27 2005 From: anton at samba.org (Anton Blanchard) Date: Mon, 12 Sep 2005 13:17:27 +1000 Subject: [PATCH] ppc64: Fix for missing start-cpu rtas token Message-ID: <20050912031727.GD5382@krispykreme> If the rtas start-cpu token doesnt exist then presume the cpu is already spinning. If it isnt we will catch it later on when the cpu doesnt respond. Signed-off-by: Anton Blanchard --- Index: build/arch/ppc64/kernel/pSeries_smp.c =================================================================== --- build.orig/arch/ppc64/kernel/pSeries_smp.c 2005-09-05 16:11:18.000000000 +1000 +++ build/arch/ppc64/kernel/pSeries_smp.c 2005-09-05 22:26:05.000000000 +1000 @@ -272,6 +272,7 @@ unsigned long start_here = __pa((u32)*((unsigned long *) pSeries_secondary_smp_init)); unsigned int pcpu; + int start_cpu; if (cpu_isset(lcpu, of_spin_map)) /* Already started by OF and sitting in spin loop */ @@ -282,12 +283,20 @@ /* Fixup atomic count: it exited inside IRQ handler. */ paca[lcpu].__current->thread_info->preempt_count = 0; - status = rtas_call(rtas_token("start-cpu"), 3, 1, NULL, - pcpu, start_here, lcpu); + /* + * If the RTAS start-cpu token does not exist then presume the + * cpu is already spinning. + */ + start_cpu = rtas_token("start-cpu"); + if (start_cpu == RTAS_UNKNOWN_SERVICE) + return 1; + + status = rtas_call(start_cpu, 3, 1, NULL, pcpu, start_here, lcpu); if (status != 0) { printk(KERN_ERR "start-cpu failed: %i\n", status); return 0; } + return 1; } From anton at samba.org Mon Sep 12 13:19:51 2005 From: anton at samba.org (Anton Blanchard) Date: Mon, 12 Sep 2005 13:19:51 +1000 Subject: [PATCH] ppc64: Remove unused code Message-ID: <20050912031951.GE5382@krispykreme> ppc64_attention_msg and ppc64_dump_msg are not used so remove them. Signed-off-by: Anton Blanchard --- Index: build/arch/ppc64/kernel/setup.c =================================================================== --- build.orig/arch/ppc64/kernel/setup.c 2005-09-06 11:29:32.000000000 +1000 +++ build/arch/ppc64/kernel/setup.c 2005-09-06 11:29:55.000000000 +1000 @@ -1064,8 +1064,6 @@ #define PPC64_LINUX_FUNCTION 0x0f000000 #define PPC64_IPL_MESSAGE 0xc0000000 #define PPC64_TERM_MESSAGE 0xb0000000 -#define PPC64_ATTN_MESSAGE 0xa0000000 -#define PPC64_DUMP_MESSAGE 0xd0000000 static void ppc64_do_msg(unsigned int src, const char *msg) { @@ -1093,20 +1091,6 @@ printk("[terminate]%04x %s\n", src, msg); } -/* Print something that needs attention (device error, etc) */ -void ppc64_attention_msg(unsigned int src, const char *msg) -{ - ppc64_do_msg(PPC64_LINUX_FUNCTION|PPC64_ATTN_MESSAGE|src, msg); - printk("[attention]%04x %s\n", src, msg); -} - -/* Print a dump progress message. */ -void ppc64_dump_msg(unsigned int src, const char *msg) -{ - ppc64_do_msg(PPC64_LINUX_FUNCTION|PPC64_DUMP_MESSAGE|src, msg); - printk("[dump]%04x %s\n", src, msg); -} - /* This should only be called on processor 0 during calibrate decr */ void __init setup_default_decr(void) { Index: build/include/asm-ppc64/machdep.h =================================================================== --- build.orig/include/asm-ppc64/machdep.h 2005-09-06 11:29:14.000000000 +1000 +++ build/include/asm-ppc64/machdep.h 2005-09-06 11:29:55.000000000 +1000 @@ -173,10 +173,6 @@ void ppc64_boot_msg(unsigned int src, const char *msg); /* Print a termination message (print only -- does not stop the kernel) */ void ppc64_terminate_msg(unsigned int src, const char *msg); -/* Print something that needs attention (device error, etc) */ -void ppc64_attention_msg(unsigned int src, const char *msg); -/* Print a dump progress message. */ -void ppc64_dump_msg(unsigned int src, const char *msg); static inline void log_error(char *buf, unsigned int err_type, int fatal) { From mail2gvs at gmail.com Mon Sep 12 14:24:05 2005 From: mail2gvs at gmail.com (vanamali gouripeddi) Date: Mon, 12 Sep 2005 09:54:05 +0530 Subject: query Message-ID: hello we are the starters level in regard to the portig of linux on power PC. could u plz tel us the basic steps to proceed with porting of the same. thanking you vanamali From mail2gvs at gmail.com Mon Sep 12 14:29:02 2005 From: mail2gvs at gmail.com (vanamali gouripeddi) Date: Mon, 12 Sep 2005 09:59:02 +0530 Subject: query Message-ID: hello i am vanamali. we have took up the project to port linux on power PC. but as we are still at the starting level we are not able to proceed further.can u plz help us find the exact information about the procedure to port. thanking you vanamali From hollis at penguinppc.org Mon Sep 12 15:07:51 2005 From: hollis at penguinppc.org (Hollis Blanchard) Date: Mon, 12 Sep 2005 00:07:51 -0500 Subject: query In-Reply-To: References: Message-ID: <9e987ddcad543b8d99535e9fa62ea71e@penguinppc.org> On Sep 11, 2005, at 11:24 PM, vanamali gouripeddi wrote: > i am vanamali. we have took up the project to port linux on power PC. > but as we are still at the starting level we are not able to proceed > further.can u plz help us find the exact information about the > procedure to port. If you really don't know what you're doing, you may want to consider hiring outside help. I can think of at least a few companies who would be willing to assist you. If you're expecting help from this mailing list, you will need to provide some actual information in your query. -Hollis From paulus at samba.org Mon Sep 12 17:52:15 2005 From: paulus at samba.org (Paul Mackerras) Date: Mon, 12 Sep 2005 17:52:15 +1000 Subject: Please pull ppc64-2.6.git again Message-ID: <17189.13231.56454.641688@cargo.ozlabs.ibm.com> Linus, There are a few more ppc64 updates in the ppc64-2.6.git tree: rsync://rsync.kernel.org/pub/scm/linux/kernel/git/paulus/ppc64-2.6.git There are a bunch of reasonably small updates from Anton, and one larger one from me, which changes the way we set up the PCI tree (the tree of pci_dev and pci_bus structs). On powermacs and on partitioned pSeries machines we now set up that tree from the Open Firmware device tree rather than by probing. On pSeries we do this because the hypervisor doesn't let us touch the special PCI-PCI bridges. On powermacs we do this because the interrupt controller is in a PCI device, and it has always worried me that we have a window during probing where we can't get to the interrupt controller, and if an interrupt came along at just the wrong moment it could cause a crash. Thanks, Paul. arch/ppc64/kernel/iSeries_pci.c | 2 arch/ppc64/kernel/maple_pci.c | 56 ++--- arch/ppc64/kernel/pSeries_setup.c | 8 + arch/ppc64/kernel/pSeries_smp.c | 13 + arch/ppc64/kernel/pci.c | 427 ++++++++++++++++++++++++++++-------- arch/ppc64/kernel/pmac_pci.c | 58 ++--- arch/ppc64/kernel/pmac_setup.c | 13 + arch/ppc64/kernel/process.c | 34 +++ arch/ppc64/kernel/ptrace.c | 28 ++ arch/ppc64/kernel/ptrace32.c | 34 +++ arch/ppc64/kernel/ras.c | 2 arch/ppc64/kernel/setup.c | 16 - arch/ppc64/kernel/signal.c | 9 + arch/ppc64/kernel/signal32.c | 8 + arch/ppc64/kernel/xics.c | 44 ++-- arch/ppc64/mm/fault.c | 31 ++- arch/ppc64/xmon/privinst.h | 1 arch/ppc64/xmon/xmon.c | 20 -- include/asm-powerpc/siginfo.h | 8 + include/asm-ppc/ptrace.h | 7 + include/asm-ppc64/hvcall.h | 6 + include/asm-ppc64/machdep.h | 5 include/asm-ppc64/pci-bridge.h | 5 include/asm-ppc64/plpar_wrappers.h | 9 + include/asm-ppc64/processor.h | 1 include/asm-ppc64/ptrace-common.h | 92 ++++++++ include/asm-ppc64/ptrace.h | 128 ++++++----- include/asm-ppc64/system.h | 3 28 files changed, 795 insertions(+), 273 deletions(-) commit 2d909d08db7655a53f3afb31c7627c5c8c87142a Author: Anton Blanchard Date: Mon Sep 12 13:19:51 2005 +1000 [PATCH] ppc64: Remove unused code ppc64_attention_msg and ppc64_dump_msg are not used so remove them. Signed-off-by: Anton Blanchard Signed-off-by: Paul Mackerras commit 1ed2fd2d3a8d18f184ba2d06e0f03bff773f28ab Author: Anton Blanchard Date: Mon Sep 12 13:17:27 2005 +1000 [PATCH] ppc64: Fix for missing start-cpu rtas token If the rtas start-cpu token doesnt exist then presume the cpu is already spinning. If it isnt we will catch it later on when the cpu doesnt respond. Signed-off-by: Anton Blanchard Signed-off-by: Paul Mackerras commit 3238e9c9735cd5ebe30a59df1f8f5af2687344de Author: Anton Blanchard Date: Mon Sep 12 13:14:26 2005 +1000 [PATCH] ppc64: indent pci code Fix up some badly indented code. Signed-off-by: Anton Blanchard Signed-off-by: Paul Mackerras commit 26370322d8e3504db61cb8d438a9fca3b87ac0db Author: Anton Blanchard Date: Mon Sep 12 13:12:11 2005 +1000 [PATCH] ppc64: xics cleanup A few xics cleanups: - Make some things static. - Be more consistent with error printing - interrupts are unsigned, error values are signed. Signed-off-by: Anton Blanchard Signed-off-by: Paul Mackerras commit fd9648dff6f9797ecc509bcd181706a274dc074d Author: Anton Blanchard Date: Sat Sep 10 16:01:11 2005 +1000 [PATCH] ppc64: Add ptrace data breakpoint support Add hardware data breakpoint support. Signed-off-by: Anton Blanchard Signed-off-by: Paul Mackerras commit a94d308513bdb2b926b45c11d7ce7fac6d6ca865 Author: Anton Blanchard Date: Sat Sep 10 16:01:10 2005 +1000 [PATCH] ppc64: Add definitions for new PTRACE calls - Add PTRACE_GET_DEBUGREG/PTRACE_SET_DEBUGREG. The definition is as follows: /* * Get or set a debug register. The first 16 are DABR registers and the * second 16 are IABR registers. */ #define PTRACE_GET_DEBUGREG 25 #define PTRACE_SET_DEBUGREG 26 DABR == data breakpoint and IABR = instruction breakpoint in IBM speak. We could split out the IABR into 2 more ptrace calls but I figured there was no need and 16 DABR registers should be more than enough (POWER4/POWER5 have one). - Add 2 new SIGTRAP si_codes: TRAP_HWBKPT and TRAP_BRANCH. I couldnt find any standards on either of these so I copied what ia64 is doing. Again this might be better placed in include/asm-generic/siginfo.h Signed-off-by: Anton Blanchard Signed-off-by: Paul Mackerras commit df09ce4a15bac7b05356b2f00fbb600c5890b1f3 Author: Anton Blanchard Date: Sat Sep 10 16:01:09 2005 +1000 [PATCH] ppc64: Fix up some whitespace issues in ptrace32.c Fix up some whitespace issues in ptrace32.c Signed-off-by: Anton Blanchard Signed-off-by: Paul Mackerras commit a0987224dc80b3eb98cc7a135422acbda8538146 Author: Anton Blanchard Date: Sat Sep 10 16:01:08 2005 +1000 [PATCH] ppc64: ptrace cleanups - Remove the PPC_REG* defines - Wrap some more stuff with ifdef __KERNEL__ - Add missing PT_TRAP, PT_DAR, PT_DSISR defines - Add PTRACE_GETEVRREGS/PTRACE_SETEVRREGS, even though we dont use it on ppc64 we dont want to allocate them for something else. Signed-off-by: Anton Blanchard Signed-off-by: Paul Mackerras commit 962bca7f389229a30ced441d7b37f55f203006a2 Author: Robert Jennings Date: Sat Sep 10 16:01:07 2005 +1000 [PATCH] ppc64: Add PTRACE_{GET|SET}VRREGS 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. Updated with the suggestions from Anton following the lines of his code snippet. Added: - flush_altivec_to_thread calls as suggested by Anton - piecewise copy of structure to preserve 32-bit vrsave data as per Anton (I consolidated the 32 and 64bit versions with 2 helper macros - Anton) Signed-off-by: Robert C Jennings Signed-off-by: Anton Blanchard Signed-off-by: Paul Mackerras commit 4267292b0f368c1633ff3316a53b5f7fbada95f8 Author: Paul Mackerras Date: Mon Sep 12 17:17:36 2005 +1000 ppc64: Set up PCI tree from Open Firmware device tree This adds code which gives us the option on ppc64 of instantiating the PCI tree (the tree of pci_bus and pci_dev structs) from the Open Firmware device tree rather than by probing PCI configuration space. The OF device tree has a node for each PCI device and bridge in the system, with properties that tell us what addresses the firmware has configured for them and other details. There are a couple of reasons why this is needed. First, on systems with a hypervisor, there is a PCI-PCI bridge per slot under the PCI host bridges. These PCI-PCI bridges have special isolation features for virtualization. We can't write to their config space, and we are not supposed to be reading their config space either. The firmware tells us about the address ranges that they pass in the OF device tree. Secondly, on powermacs, the interrupt controller is in a PCI device that may be behind a PCI-PCI bridge. If we happened to take an interrupt just at the point when the device or a bridge on the path to it was disabled for probing, we would crash when we try to access the interrupt controller. I have implemented a platform-specific function which is called for each PCI bridge (host or PCI-PCI) to say whether the code should look in the device tree or use normal PCI probing for the devices under that bridge. On pSeries machines we use the device tree if we're running under a hypervisor, otherwise we use normal probing. On powermacs we use normal probing for the AGP bridge, since the device for the AGP bridge itself isn't shown in the device tree (at least on my G5), and the device tree for everything else. This has been tested on a dual G5 powermac, a partition on a POWER5 machine (running under the hypervisor), and a legacy iSeries partition. Signed-off-by: Paul Mackerras From will_schmidt at vnet.ibm.com Tue Sep 13 00:44:02 2005 From: will_schmidt at vnet.ibm.com (will schmidt) Date: Mon, 12 Sep 2005 09:44:02 -0500 Subject: [PATCH] ppc64: export cpu_usage_array Message-ID: <43259432.6000802@vnet.ibm.com> The per_cpu structure cpu_usage_array is used by lparcfg. Lparcfg can be built as a module, thus this symbol needs to be exported. Signed-off-by: Will Schmidt -------------- next part -------------- An embedded and charset-unspecified text was scrubbed... Name: sep12.process.diff Url: http://ozlabs.org/pipermail/linuxppc64-dev/attachments/20050912/4a3f7cd2/attachment.txt From will_schmidt at vnet.ibm.com Tue Sep 13 00:44:09 2005 From: will_schmidt at vnet.ibm.com (will schmidt) Date: Mon, 12 Sep 2005 09:44:09 -0500 Subject: [PATCH] ppc64: fix lparcfg datatype and bad math. Message-ID: <43259439.5090204@vnet.ibm.com> This patch fixes two problems with the string parsing code out of lparcfg. First, it changes the data type of a char array to be unsigned. This prevents some nasty behavior when the code is built with -fsigned-char, and one of the bytes containing size-of-string has a high-bit set. Second, it corrects a bit of bad math when determining the size of the string coming back from the get-system-parameter hcall. Signed-off-by: Will Schmidt -------------- next part -------------- An embedded and charset-unspecified text was scrubbed... Name: sep12.lparcfg.diff Url: http://ozlabs.org/pipermail/linuxppc64-dev/attachments/20050912/013a013c/attachment.txt From ntl at pobox.com Tue Sep 13 01:07:42 2005 From: ntl at pobox.com (Nathan Lynch) Date: Mon, 12 Sep 2005 10:07:42 -0500 Subject: [PATCH] ppc64: export cpu_usage_array In-Reply-To: <43259432.6000802@vnet.ibm.com> References: <43259432.6000802@vnet.ibm.com> Message-ID: <20050912150742.GF3560@otto> will schmidt wrote: > > The per_cpu structure cpu_usage_array is used by lparcfg. Lparcfg can > be built as a module, thus this symbol needs to be exported. > > Signed-off-by: Will Schmidt > > > diff --git a/arch/ppc64/kernel/process.c b/arch/ppc64/kernel/process.c > --- a/arch/ppc64/kernel/process.c > +++ b/arch/ppc64/kernel/process.c > @@ -163,6 +163,7 @@ int dump_task_altivec(struct pt_regs *re > #endif /* CONFIG_ALTIVEC */ > > DEFINE_PER_CPU(struct cpu_usage, cpu_usage_array); > +EXPORT_PER_CPU_SYMBOL(cpu_usage_array); EXPORT_PER_CPU_SYMBOL_GPL please? :) From linas at austin.ibm.com Tue Sep 13 02:06:41 2005 From: linas at austin.ibm.com (linas) Date: Mon, 12 Sep 2005 11:06:41 -0500 Subject: query In-Reply-To: References: Message-ID: <20050912160641.GR30028@austin.ibm.com> On Mon, Sep 12, 2005 at 09:59:02AM +0530, vanamali gouripeddi was heard to remark: > hello > i am vanamali. we have took up the project to port linux on power PC. > but as we are still at the starting level we are not able to proceed > further.can u plz help us find the exact information about the > procedure to port. What are you trying to port? RedHat and SuSE run on powerpc hardware, as does Debian. You can get free access to powerpc boxes, remotely, by ssh, for porting/recompliling existing applications. --linas From msdemlei at cl.uni-heidelberg.de Tue Sep 13 02:34:53 2005 From: msdemlei at cl.uni-heidelberg.de (Markus Demleitner) Date: Mon, 12 Sep 2005 18:34:53 +0200 Subject: iMac G5 frequency switching In-Reply-To: <1126389498.29803.58.camel@gaston> References: <20050909114311.GA3732@victor.rh.local> <1126389498.29803.58.camel@gaston> Message-ID: <20050912163453.GA24025@victor.rh.local> On Sun, Sep 11, 2005 at 07:58:18AM +1000, Benjamin Herrenschmidt wrote: > On Fri, 2005-09-09 at 13:43 +0200, Markus Demleitner wrote: > > I've figured out how to switch frequencies of the iMac G5 CPU (at > > least for my 1600 MHz models) and at that opportunity found that OF [...] > > I don't do any voltage stuff myself, mainly because OF doesn't > > either. If anyone knows if I should, please let me know. > > OF does set voltage no ? You definitely should as this is where you save > the most power. It can be done by getting the target voltage for the Well, let me put it this way: The OF words smu-powertune-hi and smu-powertune-low don't touch the voltage. There are, indeed, some words dealing with voltage, most prominently slew-voltage. Unfortunately, it takes three arguments and is only called in slew-(high|low)-pulsar. These words, in turn, aren't used at all but have to take to arguments, since they call slew-voltage like 5 slew-voltage. Since they're not called, I can't find out what arguments they take. On the other hand, seeing the definition ['] drop to set-frequency : slew-high-pulsar 5 slew-voltage slew-wait 5 set-frequency slew-wait ; (which means that no frequency change on the pulsar chip -- I'm told it's some kind of master clock in the machine -- takes place anyway) I get the strange feeling that the whole thing is broken in my version of OF (which is 5.2.2f1-2004-08-18). In short: I'm stumped. If some kind soul has a newer iMac G5 and would let me telnet into OF, I'd be willing to try my luck and see if there's something different in there, otherwise someone would have to dive into whatever OS X does. That someone is unlikely to be me, to be entirely frank -- I probably can't spend much more time (which I'd need to get up to speed reading ppc64 machine code) on this until some time in March 2006. Sorry. I *would* have time to explain my findings so far, as poor as they are, to anyone wanting to take up the voltage control issue on the imac G5s. So, if anyone coming across this while googling for imac G5 support in Linux feels like kernel work, drop me a mail... Thanks, Markus From jimix at watson.ibm.com Tue Sep 13 04:22:23 2005 From: jimix at watson.ibm.com (Jimi Xenidis) Date: Mon, 12 Sep 2005 14:22:23 -0400 Subject: [PATCH] Use PLATFORM_LPAR rather than PLATFORM_PSERIES_LPAR In-Reply-To: <20050910002035.GH31045@localhost.localdomain> References: <17186.2523.359820.285461@kitch0.watson.ibm.com> <20050910002035.GH31045@localhost.localdomain> Message-ID: <17189.51039.379444.334050@kitch0.watson.ibm.com> >>>>> "DG" == David Gibson writes: DG> On Fri, Sep 09, 2005 at 06:16:59PM -0400, Jimi Xenidis wrote: >> This patch allows for a both furure PLATFORM_[MAPLE|CELL]_LPAR >> platforms to share PSERIES_LPAR code. DG> I think we would be better off using new firmware_has_feature() bits DG> for this. It takes us a step closer to a kernel which can boot both DG> pSeries and iSeries and a step closer to getting rid of the magic DG> platform numbers entirely. hmm, not sure if I would equate "platform" with "firmware". Perhaps when this gets pushed into prom_init.c we could use it, but currently it is initialized too late. any other thoughts on this? -JX -- "I got an idea, an idea so smart my head would explode if I even began to know what I was talking about." -- Peter Griffin (Family Guy) From sonny at burdell.org Tue Sep 13 05:40:32 2005 From: sonny at burdell.org (Sonny Rao) Date: Mon, 12 Sep 2005 15:40:32 -0400 Subject: 2.6.13-mm3 In-Reply-To: <20050912024350.60e89eb1.akpm@osdl.org> References: <20050912024350.60e89eb1.akpm@osdl.org> Message-ID: <20050912194032.GA12426@kevlar.burdell.org> I'm getting some build errors on ppc64 in drivers/char/hvc_console.c CC drivers/char/hvc_console.o drivers/char/hvc_console.c: In function `hvc_poll': drivers/char/hvc_console.c:600: error: `count' undeclared (first use in this function) drivers/char/hvc_console.c:600: error: (Each undeclared identifier is reported only once drivers/char/hvc_console.c:600: error: for each function it appears in.) drivers/char/hvc_console.c:636: error: structure has no member named `flip' make[1]: *** [drivers/char/hvc_console.o] Error 1 make: *** [_module_drivers/char] Error 2 The count undeclared one was easy to fix but I coldn't fix the filp structure element in 2-3 minutes so I'm punting. Anyone have a patch to fix this driver? Sonny From jirislaby at gmail.com Tue Sep 13 07:06:32 2005 From: jirislaby at gmail.com (Jiri Slaby) Date: Mon, 12 Sep 2005 23:06:32 +0200 Subject: 2.6.13-mm3 In-Reply-To: <20050912194032.GA12426@kevlar.burdell.org> Message-ID: <200509122106.j8CL6WPk006092@wscnet.wsc.cz> > I'm getting some build errors on ppc64 in drivers/char/hvc_console.c > > > CC drivers/char/hvc_console.o > drivers/char/hvc_console.c: In function `hvc_poll': > drivers/char/hvc_console.c:600: error: `count' undeclared (first use in this > function) > drivers/char/hvc_console.c:600: error: (Each undeclared identifier is reported > only once > drivers/char/hvc_console.c:600: error: for each function it appears in.) > drivers/char/hvc_console.c:636: error: structure has no member named `flip' > make[1]: *** [drivers/char/hvc_console.o] Error 1 > make: *** [_module_drivers/char] Error 2 > > The count undeclared one was easy to fix but I coldn't fix the filp > structure element in 2-3 minutes so I'm punting. > > Anyone have a patch to fix this driver? Try this: --- hvc_console.c | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/char/hvc_console.c b/drivers/char/hvc_console.c --- a/drivers/char/hvc_console.c +++ b/drivers/char/hvc_console.c @@ -566,7 +566,7 @@ static int hvc_chars_in_buffer(struct tt static int hvc_poll(struct hvc_struct *hp) { struct tty_struct *tty; - int i, n, poll_mask = 0; + int i, n, count, poll_mask = 0; char buf[N_INBUF] __ALIGNED__; unsigned long flags; int read_total = 0; @@ -633,7 +633,7 @@ static int hvc_poll(struct hvc_struct *h tty_insert_flip_char(tty, buf[i], 0); } - if (tty->flip.count) + if (tty->buf->tail->count) tty_schedule_flip(tty); /* From sonny at burdell.org Tue Sep 13 07:49:45 2005 From: sonny at burdell.org (Sonny Rao) Date: Mon, 12 Sep 2005 17:49:45 -0400 Subject: 2.6.13-mm3 In-Reply-To: <200509122106.j8CL6WPk006092@wscnet.wsc.cz> References: <20050912194032.GA12426@kevlar.burdell.org> <200509122106.j8CL6WPk006092@wscnet.wsc.cz> Message-ID: <20050912214945.GA17729@kevlar.burdell.org> On Mon, Sep 12, 2005 at 11:06:32PM +0200, Jiri Slaby wrote: > > I'm getting some build errors on ppc64 in drivers/char/hvc_console.c > > > > > > CC drivers/char/hvc_console.o > > drivers/char/hvc_console.c: In function `hvc_poll': > > drivers/char/hvc_console.c:600: error: `count' undeclared (first use in this > > function) > > drivers/char/hvc_console.c:600: error: (Each undeclared identifier is reported > > only once > > drivers/char/hvc_console.c:600: error: for each function it appears in.) > > drivers/char/hvc_console.c:636: error: structure has no member named `flip' > > make[1]: *** [drivers/char/hvc_console.o] Error 1 > > make: *** [_module_drivers/char] Error 2 > > > > The count undeclared one was easy to fix but I coldn't fix the filp > > structure element in 2-3 minutes so I'm punting. > > > > Anyone have a patch to fix this driver? > > Try this: > --- Hmm, that didn't build. I made my own version based on yours, unfortunately I don't know if it boots because all my network just went down. Hopefully, someone will confirm that the fix is correct. --- linux-2.6.13-mm3/drivers/char/hvc_console.c~orig 2005-09-12 16:37:14.434077464 -0500 +++ linux-2.6.13-mm3/drivers/char/hvc_console.c 2005-09-12 16:37:25.466998360 -0500 @@ -597,7 +597,7 @@ static int hvc_poll(struct hvc_struct *h /* Read data if any */ for (;;) { - count = tty_buffer_request_room(tty, N_INBUF); + int count = tty_buffer_request_room(tty, N_INBUF); /* If flip is full, just reschedule a later read */ if (count == 0) { @@ -633,7 +633,7 @@ static int hvc_poll(struct hvc_struct *h tty_insert_flip_char(tty, buf[i], 0); } - if (tty->flip.count) + if (tty->buf.tail->used) tty_schedule_flip(tty); /* From sonny at burdell.org Tue Sep 13 08:10:23 2005 From: sonny at burdell.org (Sonny Rao) Date: Mon, 12 Sep 2005 18:10:23 -0400 Subject: 2.6.13-mm3 In-Reply-To: <20050912214945.GA17729@kevlar.burdell.org> References: <20050912194032.GA12426@kevlar.burdell.org> <200509122106.j8CL6WPk006092@wscnet.wsc.cz> <20050912214945.GA17729@kevlar.burdell.org> Message-ID: <20050912221023.GB18215@kevlar.burdell.org> On Mon, Sep 12, 2005 at 05:49:45PM -0400, Sonny Rao wrote: > On Mon, Sep 12, 2005 at 11:06:32PM +0200, Jiri Slaby wrote: > > > I'm getting some build errors on ppc64 in drivers/char/hvc_console.c > > > > > > > > > CC drivers/char/hvc_console.o > > > drivers/char/hvc_console.c: In function `hvc_poll': > > > drivers/char/hvc_console.c:600: error: `count' undeclared (first use in this > > > function) > > > drivers/char/hvc_console.c:600: error: (Each undeclared identifier is reported > > > only once > > > drivers/char/hvc_console.c:600: error: for each function it appears in.) > > > drivers/char/hvc_console.c:636: error: structure has no member named `flip' > > > make[1]: *** [drivers/char/hvc_console.o] Error 1 > > > make: *** [_module_drivers/char] Error 2 > > > > > > The count undeclared one was easy to fix but I coldn't fix the filp > > > structure element in 2-3 minutes so I'm punting. > > > > > > Anyone have a patch to fix this driver? > > > > Try this: > > --- > > Hmm, that didn't build. I made my own version based on yours, > unfortunately I don't know if it boots because all my network just went > down. Hopefully, someone will confirm that the fix is correct. > > > --- linux-2.6.13-mm3/drivers/char/hvc_console.c~orig 2005-09-12 16:37:14.434077464 -0500 > +++ linux-2.6.13-mm3/drivers/char/hvc_console.c 2005-09-12 16:37:25.466998360 -0500 > @@ -597,7 +597,7 @@ static int hvc_poll(struct hvc_struct *h > > /* Read data if any */ > for (;;) { > - count = tty_buffer_request_room(tty, N_INBUF); > + int count = tty_buffer_request_room(tty, N_INBUF); > > /* If flip is full, just reschedule a later read */ > if (count == 0) { > @@ -633,7 +633,7 @@ static int hvc_poll(struct hvc_struct *h > tty_insert_flip_char(tty, buf[i], 0); > } > > - if (tty->flip.count) > + if (tty->buf.tail->used) > tty_schedule_flip(tty); > > /* Ok so that at least started to boot (i.e. I got output to the virtual console), now my SCSI controller won't come up: ipr: IBM Power RAID SCSI Device Driver version: 2.0.14 (May 2, 2005) ipr 0001:c0:01.0: Found IOA with IRQ: 337 PCI: Unable to reserve mem region #3:8000000 at 400b8000000 for device 0001:c0:01.0 ipr 0001:c0:01.0: Couldn't map memory range of registers Trying to free nonexistent resource <400b8000000-400bfffffff> I've seen it get hang right there or try to mount root fs and then fail. Not sure if this is a PCI issue or an IPR issue, Brian? (Adding brking to cc) From paulus at samba.org Tue Sep 13 10:00:05 2005 From: paulus at samba.org (Paul Mackerras) Date: Tue, 13 Sep 2005 10:00:05 +1000 Subject: [PATCH] ppc64: fix lparcfg datatype and bad math. In-Reply-To: <43259439.5090204@vnet.ibm.com> References: <43259439.5090204@vnet.ibm.com> Message-ID: <17190.5765.922385.510390@cargo.ozlabs.ibm.com> will schmidt writes: > This patch fixes two problems with the string parsing code out of lparcfg. > First, it changes the data type of a char array to be unsigned. This > prevents some nasty behavior when the code is built with -fsigned-char, OK, making it explicitly unsigned char is good, but why would we ever build the kernel with -fsigned-char? Paul. From jirislaby at gmail.com Tue Sep 13 10:51:39 2005 From: jirislaby at gmail.com (Jiri Slaby) Date: Tue, 13 Sep 2005 02:51:39 +0200 Subject: 2.6.13-mm3 In-Reply-To: <20050912221023.GB18215@kevlar.burdell.org> References: <20050912194032.GA12426@kevlar.burdell.org> <200509122106.j8CL6WPk006092@wscnet.wsc.cz> <20050912214945.GA17729@kevlar.burdell.org> <20050912221023.GB18215@kevlar.burdell.org> Message-ID: <4326229B.6040002@gmail.com> Sonny Rao napsal(a): >On Mon, Sep 12, 2005 at 05:49:45PM -0400, Sonny Rao wrote: > > >>--- linux-2.6.13-mm3/drivers/char/hvc_console.c~orig 2005-09-12 16:37:14.434077464 -0500 >>+++ linux-2.6.13-mm3/drivers/char/hvc_console.c 2005-09-12 16:37:25.466998360 -0500 >>@@ -597,7 +597,7 @@ static int hvc_poll(struct hvc_struct *h >> >> /* Read data if any */ >> for (;;) { >>- count = tty_buffer_request_room(tty, N_INBUF); >>+ int count = tty_buffer_request_room(tty, N_INBUF); >> >> /* If flip is full, just reschedule a later read */ >> if (count == 0) { >>@@ -633,7 +633,7 @@ static int hvc_poll(struct hvc_struct *h >> tty_insert_flip_char(tty, buf[i], 0); >> } >> >>- if (tty->flip.count) >>+ if (tty->buf.tail->used) >> >> Is there any better way to gather this info? I think, that this was my bad idea. Some encapsulation needed. thanks, -- Jiri Slaby www.fi.muni.cz/~xslaby ~\-/~ jirislaby at gmail.com ~\-/~ 241B347EC88228DE51EE A49C4A73A25004CB2A10 From sonny at burdell.org Tue Sep 13 15:58:32 2005 From: sonny at burdell.org (Sonny Rao) Date: Tue, 13 Sep 2005 01:58:32 -0400 Subject: 2.6.13-mm3 In-Reply-To: <4326229B.6040002@gmail.com> References: <20050912194032.GA12426@kevlar.burdell.org> <200509122106.j8CL6WPk006092@wscnet.wsc.cz> <20050912214945.GA17729@kevlar.burdell.org> <20050912221023.GB18215@kevlar.burdell.org> <4326229B.6040002@gmail.com> Message-ID: <20050913055832.GA28971@kevlar.burdell.org> On Tue, Sep 13, 2005 at 02:51:39AM +0200, Jiri Slaby wrote: > Sonny Rao napsal(a): > > >On Mon, Sep 12, 2005 at 05:49:45PM -0400, Sonny Rao wrote: > > > > > >>--- linux-2.6.13-mm3/drivers/char/hvc_console.c~orig 2005-09-12 > >>16:37:14.434077464 -0500 > >>+++ linux-2.6.13-mm3/drivers/char/hvc_console.c 2005-09-12 > >>16:37:25.466998360 -0500 > >>@@ -597,7 +597,7 @@ static int hvc_poll(struct hvc_struct *h > >> > >> /* Read data if any */ > >> for (;;) { > >>- count = tty_buffer_request_room(tty, N_INBUF); > >>+ int count = tty_buffer_request_room(tty, N_INBUF); > >> > >> /* If flip is full, just reschedule a later read */ > >> if (count == 0) { > >>@@ -633,7 +633,7 @@ static int hvc_poll(struct hvc_struct *h > >> tty_insert_flip_char(tty, buf[i], 0); > >> } > >> > >>- if (tty->flip.count) > >>+ if (tty->buf.tail->used) > >> > >> > Is there any better way to gather this info? I think, that this was my > bad idea. Some encapsulation needed. > I agree, this is ugly as hell. I don't know if the tty stuff was ever supposed to be used this way. Given the revamp, and if this usage is legal, perhaps the addition of a generic wrapper to the API is warranted. Sonny From segher at kernel.crashing.org Tue Sep 13 19:23:02 2005 From: segher at kernel.crashing.org (Segher Boessenkool) Date: Tue, 13 Sep 2005 11:23:02 +0200 Subject: [PATCH] Use PLATFORM_LPAR rather than PLATFORM_PSERIES_LPAR In-Reply-To: <17189.51039.379444.334050@kitch0.watson.ibm.com> References: <17186.2523.359820.285461@kitch0.watson.ibm.com> <20050910002035.GH31045@localhost.localdomain> <17189.51039.379444.334050@kitch0.watson.ibm.com> Message-ID: >>> This patch allows for a both furure PLATFORM_[MAPLE|CELL]_LPAR >>> platforms to share PSERIES_LPAR code. > > DG> I think we would be better off using new firmware_has_feature() > bits > DG> for this. It takes us a step closer to a kernel which can boot > both > DG> pSeries and iSeries and a step closer to getting rid of the magic > DG> platform numbers entirely. > > hmm, not sure if I would equate "platform" with "firmware". > Perhaps when this gets pushed into prom_init.c we could use it, but > currently it is initialized too late. There _is_ no such thing as a platform; it is completely the wrong concept to do any feature tests on. Yes, put some LPAR detection code into prom_init.c, and use it from there. Care to prepare a patch for this? If not, please get your original patch in, as although it isn't perfect, it already is better than what was there before. Segher From paulus at samba.org Tue Sep 13 20:56:20 2005 From: paulus at samba.org (Paul Mackerras) Date: Tue, 13 Sep 2005 20:56:20 +1000 Subject: [PATCH] ppc64: Make eeh_init function again Message-ID: <17190.45140.291983.586619@cargo.ozlabs.ibm.com> My patch "Separate pci bits out of struct device_node" (commit 1635317facea3094ddf34082cd86797efb1d9f7e) had the unfortunate side-effect that it stopped eeh_init() from working correctly, since it needs the pointers set up by find_and_init_phbs(), but it was being called just before find_and_init_phbs(). That meant that we didn't enable EEH (pSeries PCI error recovery) on any devices, and that meant that on POWER5 systems, the hypervisor wouldn't let us enable memory or I/O space access to any devices, and their drivers got somewhat confused. This fixes it by moving the eeh_init call after find_and_init_phbs. Tested on a POWER5 partition. Signed-of-by: Paul Mackerras --- diff -urN linux-2.6/arch/ppc64/kernel/pSeries_setup.c test/arch/ppc64/kernel/pSeries_setup.c --- linux-2.6/arch/ppc64/kernel/pSeries_setup.c 2005-09-13 07:43:47.000000000 +1000 +++ test/arch/ppc64/kernel/pSeries_setup.c 2005-09-13 19:19:28.000000000 +1000 @@ -238,8 +238,8 @@ /* Find and initialize PCI host bridges */ init_pci_config_tokens(); - eeh_init(); find_and_init_phbs(); + eeh_init(); #ifdef CONFIG_DUMMY_CONSOLE conswitchp = &dummy_con; From will_schmidt at vnet.ibm.com Tue Sep 13 23:13:35 2005 From: will_schmidt at vnet.ibm.com (will schmidt) Date: Tue, 13 Sep 2005 08:13:35 -0500 Subject: [PATCH] ppc64: export cpu_usage_array In-Reply-To: <20050912150742.GF3560@otto> References: <43259432.6000802@vnet.ibm.com> <20050912150742.GF3560@otto> Message-ID: <4326D07F.2020100@vnet.ibm.com> Nathan Lynch wrote: > will schmidt wrote: > >>The per_cpu structure cpu_usage_array is used by lparcfg. Lparcfg can >>be built as a module, thus this symbol needs to be exported. >> >>Signed-off-by: Will Schmidt >> >> > >>diff --git a/arch/ppc64/kernel/process.c b/arch/ppc64/kernel/process.c >>--- a/arch/ppc64/kernel/process.c >>+++ b/arch/ppc64/kernel/process.c >>@@ -163,6 +163,7 @@ int dump_task_altivec(struct pt_regs *re >> #endif /* CONFIG_ALTIVEC */ >> >> DEFINE_PER_CPU(struct cpu_usage, cpu_usage_array); >>+EXPORT_PER_CPU_SYMBOL(cpu_usage_array); > > > EXPORT_PER_CPU_SYMBOL_GPL please? :) this will be deja vu for Nathan, as I skipped to: linuxppc64-dev last time I resent. Yeah, sure, you betcha. :-) Signed-off-by: Will Schmidt -------------- next part -------------- An embedded and charset-unspecified text was scrubbed... Name: sep12.process.gpl.diff Url: http://ozlabs.org/pipermail/linuxppc64-dev/attachments/20050913/9ab48c1e/attachment.txt From will_schmidt at vnet.ibm.com Tue Sep 13 23:19:40 2005 From: will_schmidt at vnet.ibm.com (will schmidt) Date: Tue, 13 Sep 2005 08:19:40 -0500 Subject: [PATCH] ppc64: fix lparcfg datatype and bad math. In-Reply-To: <17190.5765.922385.510390@cargo.ozlabs.ibm.com> References: <43259439.5090204@vnet.ibm.com> <17190.5765.922385.510390@cargo.ozlabs.ibm.com> Message-ID: <4326D1EC.8010107@vnet.ibm.com> Paul Mackerras wrote: > will schmidt writes: > > >>This patch fixes two problems with the string parsing code out of lparcfg. >>First, it changes the data type of a char array to be unsigned. This >>prevents some nasty behavior when the code is built with -fsigned-char, > > > OK, making it explicitly unsigned char is good, but why would we ever > build the kernel with -fsigned-char? > > Paul. I dont know why we would build with -fsigned-char. It appears that we used to build that way (at least, back in 2.4), I dont recall the discussions surrounding removing that flag, so only really mention the parm because it took a bit to figure out. :-) -Will From anton at samba.org Wed Sep 14 01:00:10 2005 From: anton at samba.org (Anton Blanchard) Date: Wed, 14 Sep 2005 01:00:10 +1000 Subject: [RFC] SCSI target for IBM Power5 LPAR In-Reply-To: <431EFFE7.6070709@us.ibm.com> References: <20050906212801.GB14057@cs.umn.edu> <20050907025932.GU6945@krispykreme> <431EFFE7.6070709@us.ibm.com> Message-ID: <20050913150009.GG26162@krispykreme> Hi, > We use MAX_SECTORS (which is actually 127.5kB) because that's the > max_sectors of the loopback device (we have a lot of users that like the > flexibility of using loopback with the ibmvscsis driver)... It can be > bumped up without any problems because there is code that splits > requests if they are larger than the target's max_sectors... > > What would you recommend? 256kB? ~256kB sounds reasonable to me and I notice that other VIO server is setting it to 256kB :) Anton From anton at samba.org Wed Sep 14 02:02:18 2005 From: anton at samba.org (Anton Blanchard) Date: Wed, 14 Sep 2005 02:02:18 +1000 Subject: [anton@samba.org: Re: [2.6.14-rc1] sym scsi boot hang] Message-ID: <20050913160218.GH26162@krispykreme> FYI for people trying to boot 2.6.14-rc1 Anton ----- Forwarded message from Anton Blanchard ----- From: Anton Blanchard To: Dipankar Sarma Cc: linux-scsi at vger.kernel.org, linux-kernel at vger.kernel.org Subject: Re: [2.6.14-rc1] sym scsi boot hang Hi, > Looks like a change between 2.6.13-git11 and 2.6.14-rc1 caused this - so > something in the last 24 hours. I just noticed a similar hang on the ibmvscsi driver. The following backout patch seems to fix it (part of the scsi merge yesterday), I'll look closer after I get some sleep. Anton diff -urN build/drivers/scsi/scsi_lib.c build2/drivers/scsi/scsi_lib.c --- build/drivers/scsi/scsi_lib.c 2005-09-13 15:13:32.000000000 +1000 +++ build2/drivers/scsi/scsi_lib.c 2005-09-14 00:44:57.000000000 +1000 @@ -97,30 +97,6 @@ } static void scsi_run_queue(struct request_queue *q); -static void scsi_release_buffers(struct scsi_cmnd *cmd); - -/* - * Function: scsi_unprep_request() - * - * Purpose: Remove all preparation done for a request, including its - * associated scsi_cmnd, so that it can be requeued. - * - * Arguments: req - request to unprepare - * - * Lock status: Assumed that no locks are held upon entry. - * - * Returns: Nothing. - */ -static void scsi_unprep_request(struct request *req) -{ - struct scsi_cmnd *cmd = req->special; - - req->flags &= ~REQ_DONTPREP; - req->special = (req->flags & REQ_SPECIAL) ? cmd->sc_request : NULL; - - scsi_release_buffers(cmd); - scsi_put_command(cmd); -} /* * Function: scsi_queue_insert() @@ -140,14 +116,12 @@ * commands. * Notes: This could be called either from an interrupt context or a * normal process context. - * Notes: Upon return, cmd is a stale pointer. */ int scsi_queue_insert(struct scsi_cmnd *cmd, int reason) { struct Scsi_Host *host = cmd->device->host; struct scsi_device *device = cmd->device; struct request_queue *q = device->request_queue; - struct request *req = cmd->request; unsigned long flags; SCSI_LOG_MLQUEUE(1, @@ -188,9 +162,8 @@ * function. The SCSI request function detects the blocked condition * and plugs the queue appropriately. */ - scsi_unprep_request(req); spin_lock_irqsave(q->queue_lock, flags); - blk_requeue_request(q, req); + blk_requeue_request(q, cmd->request); spin_unlock_irqrestore(q->queue_lock, flags); scsi_run_queue(q); @@ -366,7 +339,7 @@ int result; if (sshdr) { - sense = kmalloc(SCSI_SENSE_BUFFERSIZE, GFP_NOIO); + sense = kmalloc(SCSI_SENSE_BUFFERSIZE, GFP_KERNEL); if (!sense) return DRIVER_ERROR << 24; memset(sense, 0, SCSI_SENSE_BUFFERSIZE); @@ -579,16 +552,15 @@ * I/O errors in the middle of the request, in which case * we need to request the blocks that come after the bad * sector. - * Notes: Upon return, cmd is a stale pointer. */ static void scsi_requeue_command(struct request_queue *q, struct scsi_cmnd *cmd) { - struct request *req = cmd->request; unsigned long flags; - scsi_unprep_request(req); + cmd->request->flags &= ~REQ_DONTPREP; + spin_lock_irqsave(q->queue_lock, flags); - blk_requeue_request(q, req); + blk_requeue_request(q, cmd->request); spin_unlock_irqrestore(q->queue_lock, flags); scsi_run_queue(q); @@ -623,14 +595,13 @@ * * Lock status: Assumed that lock is not held upon entry. * - * Returns: cmd if requeue required, NULL otherwise. + * Returns: cmd if requeue done or required, NULL otherwise * * Notes: This is called for block device requests in order to * mark some number of sectors as complete. * * We are guaranteeing that the request queue will be goosed * at some point during this call. - * Notes: If cmd was requeued, upon return it will be a stale pointer. */ static struct scsi_cmnd *scsi_end_request(struct scsi_cmnd *cmd, int uptodate, int bytes, int requeue) @@ -653,15 +624,14 @@ if (!uptodate && blk_noretry_request(req)) end_that_request_chunk(req, 0, leftover); else { - if (requeue) { + if (requeue) /* * Bleah. Leftovers again. Stick the * leftovers in the front of the * queue, and goose the queue again. */ scsi_requeue_command(q, cmd); - cmd = NULL; - } + return cmd; } } @@ -887,13 +857,15 @@ * requeueing right here - we will requeue down below * when we handle the bad sectors. */ + cmd = scsi_end_request(cmd, 1, good_bytes, result == 0); /* - * If the command completed without error, then either - * finish off the rest of the command, or start a new one. + * If the command completed without error, then either finish off the + * rest of the command, or start a new one. */ - if (scsi_end_request(cmd, 1, good_bytes, result == 0) == NULL) + if (result == 0 || cmd == NULL ) { return; + } } /* * Now, if we were good little boys and girls, Santa left us a request @@ -908,7 +880,7 @@ * and quietly refuse further access. */ cmd->device->changed = 1; - scsi_end_request(cmd, 0, + cmd = scsi_end_request(cmd, 0, this_count, 1); return; } else { @@ -942,7 +914,7 @@ scsi_requeue_command(q, cmd); result = 0; } else { - scsi_end_request(cmd, 0, this_count, 1); + cmd = scsi_end_request(cmd, 0, this_count, 1); return; } break; @@ -959,7 +931,7 @@ dev_printk(KERN_INFO, &cmd->device->sdev_gendev, "Device not ready.\n"); - scsi_end_request(cmd, 0, this_count, 1); + cmd = scsi_end_request(cmd, 0, this_count, 1); return; case VOLUME_OVERFLOW: if (!(req->flags & REQ_QUIET)) { @@ -969,7 +941,7 @@ __scsi_print_command(cmd->data_cmnd); scsi_print_sense("", cmd); } - scsi_end_request(cmd, 0, block_bytes, 1); + cmd = scsi_end_request(cmd, 0, block_bytes, 1); return; default: break; @@ -1000,7 +972,7 @@ block_bytes = req->hard_cur_sectors << 9; if (!block_bytes) block_bytes = req->data_len; - scsi_end_request(cmd, 0, block_bytes, 1); + cmd = scsi_end_request(cmd, 0, block_bytes, 1); } } EXPORT_SYMBOL(scsi_io_completion); @@ -1146,7 +1118,7 @@ if (unlikely(!scsi_device_online(sdev))) { printk(KERN_ERR "scsi%d (%d:%d): rejecting I/O to offline device\n", sdev->host->host_no, sdev->id, sdev->lun); - goto kill; + return BLKPREP_KILL; } if (unlikely(sdev->sdev_state != SDEV_RUNNING)) { /* OK, we're not in a running state don't prep @@ -1156,7 +1128,7 @@ * at all allowed down */ printk(KERN_ERR "scsi%d (%d:%d): rejecting I/O to dead device\n", sdev->host->host_no, sdev->id, sdev->lun); - goto kill; + return BLKPREP_KILL; } /* OK, we only allow special commands (i.e. not * user initiated ones */ @@ -1188,11 +1160,11 @@ if(unlikely(specials_only) && !(req->flags & REQ_SPECIAL)) { if(specials_only == SDEV_QUIESCE || specials_only == SDEV_BLOCK) - goto defer; + return BLKPREP_DEFER; printk(KERN_ERR "scsi%d (%d:%d): rejecting I/O to device being removed\n", sdev->host->host_no, sdev->id, sdev->lun); - goto kill; + return BLKPREP_KILL; } @@ -1210,7 +1182,7 @@ cmd->tag = req->tag; } else { blk_dump_rq_flags(req, "SCSI bad req"); - goto kill; + return BLKPREP_KILL; } /* note the overloading of req->special. When the tag @@ -1248,13 +1220,8 @@ * required). */ ret = scsi_init_io(cmd); - switch(ret) { - case BLKPREP_KILL: - /* BLKPREP_KILL return also releases the command */ - goto kill; - case BLKPREP_DEFER: - goto defer; - } + if (ret) /* BLKPREP_KILL return also releases the command */ + return ret; /* * Initialize the actual SCSI command for this request. @@ -1264,7 +1231,7 @@ if (unlikely(!drv->init_command(cmd))) { scsi_release_buffers(cmd); scsi_put_command(cmd); - goto kill; + return BLKPREP_KILL; } } else { memcpy(cmd->cmnd, req->cmd, sizeof(cmd->cmnd)); @@ -1295,9 +1262,6 @@ if (sdev->device_busy == 0) blk_plug_device(q); return BLKPREP_DEFER; - kill: - req->errors = DID_NO_CONNECT << 16; - return BLKPREP_KILL; } /* @@ -1372,24 +1336,19 @@ } /* - * Kill a request for a dead device + * Kill requests for a dead device */ -static void scsi_kill_request(struct request *req, request_queue_t *q) +static void scsi_kill_requests(request_queue_t *q) { - struct scsi_cmnd *cmd = req->special; - - blkdev_dequeue_request(req); + struct request *req; - if (unlikely(cmd == NULL)) { - printk(KERN_CRIT "impossible request in %s.\n", - __FUNCTION__); - BUG(); + while ((req = elv_next_request(q)) != NULL) { + blkdev_dequeue_request(req); + req->flags |= REQ_QUIET; + while (end_that_request_first(req, 0, req->nr_sectors)) + ; + end_that_request_last(req); } - - scsi_init_cmd_errh(cmd); - cmd->result = DID_NO_CONNECT << 16; - atomic_inc(&cmd->device->iorequest_cnt); - __scsi_done(cmd); } /* @@ -1412,8 +1371,7 @@ if (!sdev) { printk("scsi: killing requests for dead queue\n"); - while ((req = elv_next_request(q)) != NULL) - scsi_kill_request(req, q); + scsi_kill_requests(q); return; } @@ -1440,7 +1398,11 @@ if (unlikely(!scsi_device_online(sdev))) { printk(KERN_ERR "scsi%d (%d:%d): rejecting I/O to offline device\n", sdev->host->host_no, sdev->id, sdev->lun); - scsi_kill_request(req, q); + blkdev_dequeue_request(req); + req->flags |= REQ_QUIET; + while (end_that_request_first(req, 0, req->nr_sectors)) + ; + end_that_request_last(req); continue; } @@ -1453,14 +1415,6 @@ sdev->device_busy++; spin_unlock(q->queue_lock); - cmd = req->special; - if (unlikely(cmd == NULL)) { - printk(KERN_CRIT "impossible request in %s.\n" - "please mail a stack trace to " - "linux-scsi at vger.kernel.org", - __FUNCTION__); - BUG(); - } spin_lock(shost->host_lock); if (!scsi_host_queue_ready(q, shost, sdev)) @@ -1479,6 +1433,15 @@ */ spin_unlock_irq(shost->host_lock); + cmd = req->special; + if (unlikely(cmd == NULL)) { + printk(KERN_CRIT "impossible request in %s.\n" + "please mail a stack trace to " + "linux-scsi at vger.kernel.org", + __FUNCTION__); + BUG(); + } + /* * Finally, initialize any error handling parameters, and set up * the timers for timeouts. @@ -1514,7 +1477,6 @@ * cases (host limits or settings) should run the queue at some * later time. */ - scsi_unprep_request(req); spin_lock_irq(q->queue_lock); blk_requeue_request(q, req); sdev->device_busy--; diff -urN build/drivers/scsi/scsi_priv.h build2/drivers/scsi/scsi_priv.h --- build/drivers/scsi/scsi_priv.h 2005-09-13 15:13:32.000000000 +1000 +++ build2/drivers/scsi/scsi_priv.h 2005-09-14 00:44:57.000000000 +1000 @@ -124,7 +124,6 @@ extern void scsi_sysfs_device_initialize(struct scsi_device *); extern int scsi_sysfs_target_initialize(struct scsi_device *); extern struct scsi_transport_template blank_transport_template; -extern void __scsi_remove_device(struct scsi_device *); extern struct bus_type scsi_bus_type; diff -urN build/drivers/scsi/scsi_scan.c build2/drivers/scsi/scsi_scan.c --- build/drivers/scsi/scsi_scan.c 2005-09-13 15:13:32.000000000 +1000 +++ build2/drivers/scsi/scsi_scan.c 2005-09-14 00:44:57.000000000 +1000 @@ -870,12 +870,8 @@ out_free_sdev: if (res == SCSI_SCAN_LUN_PRESENT) { if (sdevp) { - if (scsi_device_get(sdev) == 0) { - *sdevp = sdev; - } else { - __scsi_remove_device(sdev); - res = SCSI_SCAN_NO_RESPONSE; - } + scsi_device_get(sdev); + *sdevp = sdev; } } else { if (sdev->host->hostt->slave_destroy) @@ -1264,19 +1260,6 @@ } EXPORT_SYMBOL(__scsi_add_device); -int scsi_add_device(struct Scsi_Host *host, uint channel, - uint target, uint lun) -{ - struct scsi_device *sdev = - __scsi_add_device(host, channel, target, lun, NULL); - if (IS_ERR(sdev)) - return PTR_ERR(sdev); - - scsi_device_put(sdev); - return 0; -} -EXPORT_SYMBOL(scsi_add_device); - void scsi_rescan_device(struct device *dev) { struct scsi_driver *drv; @@ -1293,8 +1276,27 @@ } EXPORT_SYMBOL(scsi_rescan_device); -static void __scsi_scan_target(struct device *parent, unsigned int channel, - unsigned int id, unsigned int lun, int rescan) +/** + * scsi_scan_target - scan a target id, possibly including all LUNs on the + * target. + * @sdevsca: Scsi_Device handle for scanning + * @shost: host to scan + * @channel: channel to scan + * @id: target id to scan + * + * Description: + * Scan the target id on @shost, @channel, and @id. Scan at least LUN + * 0, and possibly all LUNs on the target id. + * + * Use the pre-allocated @sdevscan as a handle for the scanning. This + * function sets sdevscan->host, sdevscan->id and sdevscan->lun; the + * scanning functions modify sdevscan->lun. + * + * First try a REPORT LUN scan, if that does not scan the target, do a + * sequential scan of LUNs on the target id. + **/ +void scsi_scan_target(struct device *parent, unsigned int channel, + unsigned int id, unsigned int lun, int rescan) { struct Scsi_Host *shost = dev_to_shost(parent); int bflags = 0; @@ -1308,7 +1310,9 @@ */ return; + starget = scsi_alloc_target(parent, channel, id); + if (!starget) return; @@ -1354,33 +1358,6 @@ put_device(&starget->dev); } - -/** - * scsi_scan_target - scan a target id, possibly including all LUNs on the - * target. - * @parent: host to scan - * @channel: channel to scan - * @id: target id to scan - * @lun: Specific LUN to scan or SCAN_WILD_CARD - * @rescan: passed to LUN scanning routines - * - * Description: - * Scan the target id on @parent, @channel, and @id. Scan at least LUN 0, - * and possibly all LUNs on the target id. - * - * First try a REPORT LUN scan, if that does not scan the target, do a - * sequential scan of LUNs on the target id. - **/ -void scsi_scan_target(struct device *parent, unsigned int channel, - unsigned int id, unsigned int lun, int rescan) -{ - struct Scsi_Host *shost = dev_to_shost(parent); - - down(&shost->scan_mutex); - if (scsi_host_scan_allowed(shost)) - __scsi_scan_target(parent, channel, id, lun, rescan); - up(&shost->scan_mutex); -} EXPORT_SYMBOL(scsi_scan_target); static void scsi_scan_channel(struct Scsi_Host *shost, unsigned int channel, @@ -1406,12 +1383,10 @@ order_id = shost->max_id - id - 1; else order_id = id; - __scsi_scan_target(&shost->shost_gendev, channel, - order_id, lun, rescan); + scsi_scan_target(&shost->shost_gendev, channel, order_id, lun, rescan); } else - __scsi_scan_target(&shost->shost_gendev, channel, - id, lun, rescan); + scsi_scan_target(&shost->shost_gendev, channel, id, lun, rescan); } int scsi_scan_host_selected(struct Scsi_Host *shost, unsigned int channel, @@ -1509,15 +1484,12 @@ */ struct scsi_device *scsi_get_host_dev(struct Scsi_Host *shost) { - struct scsi_device *sdev = NULL; + struct scsi_device *sdev; struct scsi_target *starget; - down(&shost->scan_mutex); - if (!scsi_host_scan_allowed(shost)) - goto out; starget = scsi_alloc_target(&shost->shost_gendev, 0, shost->this_id); if (!starget) - goto out; + return NULL; sdev = scsi_alloc_sdev(starget, 0, NULL); if (sdev) { @@ -1525,8 +1497,6 @@ sdev->borken = 0; } put_device(&starget->dev); - out: - up(&shost->scan_mutex); return sdev; } EXPORT_SYMBOL(scsi_get_host_dev); diff -urN build/drivers/scsi/scsi_sysfs.c build2/drivers/scsi/scsi_sysfs.c --- build/drivers/scsi/scsi_sysfs.c 2005-09-13 15:13:32.000000000 +1000 +++ build2/drivers/scsi/scsi_sysfs.c 2005-09-14 00:44:57.000000000 +1000 @@ -653,7 +653,7 @@ error = attr_add(&sdev->sdev_gendev, sdev->host->hostt->sdev_attrs[i]); if (error) { - __scsi_remove_device(sdev); + scsi_remove_device(sdev); goto out; } } @@ -667,7 +667,7 @@ scsi_sysfs_sdev_attrs[i]); error = device_create_file(&sdev->sdev_gendev, attr); if (error) { - __scsi_remove_device(sdev); + scsi_remove_device(sdev); goto out; } } @@ -687,10 +687,17 @@ return error; } -void __scsi_remove_device(struct scsi_device *sdev) +/** + * scsi_remove_device - unregister a device from the scsi bus + * @sdev: scsi_device to unregister + **/ +void scsi_remove_device(struct scsi_device *sdev) { + struct Scsi_Host *shost = sdev->host; + + down(&shost->scan_mutex); if (scsi_device_set_state(sdev, SDEV_CANCEL) != 0) - return; + goto out; class_device_unregister(&sdev->sdev_classdev); device_del(&sdev->sdev_gendev); @@ -699,17 +706,8 @@ sdev->host->hostt->slave_destroy(sdev); transport_unregister_device(&sdev->sdev_gendev); put_device(&sdev->sdev_gendev); -} - -/** - * scsi_remove_device - unregister a device from the scsi bus - * @sdev: scsi_device to unregister - **/ -void scsi_remove_device(struct scsi_device *sdev) -{ - down(&sdev->host->scan_mutex); - __scsi_remove_device(sdev); - up(&sdev->host->scan_mutex); +out: + up(&shost->scan_mutex); } EXPORT_SYMBOL(scsi_remove_device); diff -urN build/include/scsi/scsi_device.h build2/include/scsi/scsi_device.h --- build/include/scsi/scsi_device.h 2005-09-13 15:13:32.000000000 +1000 +++ build2/include/scsi/scsi_device.h 2005-09-14 00:44:57.000000000 +1000 @@ -178,8 +178,8 @@ extern struct scsi_device *__scsi_add_device(struct Scsi_Host *, uint, uint, uint, void *hostdata); -extern int scsi_add_device(struct Scsi_Host *host, uint channel, - uint target, uint lun); +#define scsi_add_device(host, channel, target, lun) \ + __scsi_add_device(host, channel, target, lun, NULL) extern void scsi_remove_device(struct scsi_device *); extern int scsi_device_cancel(struct scsi_device *, int); - To unsubscribe from this list: send the line "unsubscribe linux-scsi" in the body of a message to majordomo at vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html ----- End forwarded message ----- From jdl at freescale.com Wed Sep 14 02:42:51 2005 From: jdl at freescale.com (Jon Loeliger) Date: Tue, 13 Sep 2005 11:42:51 -0500 Subject: PATCH Merge kmap_types.h In-Reply-To: <1126039905.25148.66.camel@cashmere.sps.mot.com> References: <1126039905.25148.66.camel@cashmere.sps.mot.com> Message-ID: <1126629771.11056.1.camel@cashmere.sps.mot.com> On Tue, 2005-09-06 at 15:51, Jon Loeliger wrote: > Here is a patch to merge the ppc and pp64 version of kmap_types.h > > Signed-off-by: Jon Loeliger > Signed-off-by: Kumar Gala > --- Paul, Any reason why this patch for merging kmap_types.h keeps slipping through cracks? Is it not applying or something like that? Some merge issue I'm missing? Thanks, jdl From jdl at freescale.com Wed Sep 14 03:06:46 2005 From: jdl at freescale.com (Jon Loeliger) Date: Tue, 13 Sep 2005 12:06:46 -0500 Subject: Merge Question on asm-ppc*/rwsem.h Message-ID: <1126631205.11056.15.camel@cashmere.sps.mot.com> Paul (or anyone, really), I am not too familiar with some of the low-level machine details that might (do!) influence some of the semaphore implementations. I was hoping I might get you to give me a quick nudge in the right direction here. Here is a brief example of the differences found in the ppc and pp64 versions of asm-ppc*/rwsem.h: (ppc is -, and ppc64 is + here) @@ -69,9 +74,7 @@ */ static inline void __down_read(struct rw_semaphore *sem) { - if (atomic_inc_return((atomic_t *)(&sem->count)) > 0) - smp_wmb(); - else + if (unlikely(atomic_inc_return((atomic_t *)(&sem->count)) <= 0)) rwsem_down_read_failed(sem); } If we add likely() to the PPC version, and then invert it, we can get effectively this: static inline void __down_read(struct rw_semaphore *sem) { if (unlikely(atomic_inc_return((atomic_t *)(&sem->count)) <= 0)) rwsem_down_read_failed(sem); #ifndef __powerpc64__ else smp_wmb(); #endif } Which begs the question, what is the "else smp_wmb();" clause really doing for us in the ppc32 case, and can we either get rid of it, or is it safe to add to the ppc64 case? Thanks, jdl From sonny at burdell.org Wed Sep 14 04:32:15 2005 From: sonny at burdell.org (Sonny Rao) Date: Tue, 13 Sep 2005 14:32:15 -0400 Subject: 2.6.13-mm3 In-Reply-To: <20050912125641.4b53553d.akpm@osdl.org> References: <20050912024350.60e89eb1.akpm@osdl.org> <20050912145435.GA4722@kevlar.burdell.org> <20050912125641.4b53553d.akpm@osdl.org> Message-ID: <20050913183215.GA28596@kevlar.burdell.org> On Mon, Sep 12, 2005 at 12:56:41PM -0700, Andrew Morton wrote: > Sonny Rao wrote: > > > > On Mon, Sep 12, 2005 at 02:43:50AM -0700, Andrew Morton wrote: > > > > > - There are several performance tuning patches here which need careful > > > attention and testing. (Does anyone do performance testing any more?) > > > > > > > > - The size of the page allocator per-cpu magazines has been increased > > > > > > - The page allocator has been changed to use higher-order allocations > > > when batch-loading the per-cpu magazines. This is intended to give > > > improved cache colouring effects however it might have the downside of > > > causing extra page allocator fragmentation. > > > > > > - The page allocator's per-cpu magazines have had their lower threshold > > > set to zero. And we can't remember why it ever had a lower threshold. > > > > > > > What would you like? The usual suspects: SDET, dbench, kernbench ? > > > > That would be a good start, thanks. The higher-order-allocations thing is > mainly targeted at big-iron numerical computing I believe. > > I've already had one report of fragmentation-derived page allocator > failures (http://bugzilla.kernel.org/show_bug.cgi?id=5229). Ok, I'm getting much further on ppc64 thanks to Anton B. So far, I need patched in the hvc console fix, Anton's SCSI fix for 2.6.14-rc1, Paulus's EEH fix, and I reverted remove-near-all-bugs-in-mm-mempolicyc.patch and convert-mempolicies-to-nodemask_t.patch I got most of the way through the boot scripts and crashed while bringing up the loopback interface. Here's the latest PPC64 crash on 2.6.13-mm3: smp_call_function on cpu 5: other cpus not responding (5) cpu 0x5: Vector: 0 at [c00000000f3b6b00] pc: 000000000000003d lr: 000000000000003d sp: c00000000f3b6a90 msr: 8000000000009032 current = 0xc000000002018050 paca = 0xc00000000048a400 pid = 1679, comm = ip enter ? for help 5:mon> t (xmon hangs here) Anyone have ideas on what to try? From sonny at burdell.org Wed Sep 14 04:46:29 2005 From: sonny at burdell.org (Sonny Rao) Date: Tue, 13 Sep 2005 14:46:29 -0400 Subject: 2.6.13-mm3 In-Reply-To: <20050913183215.GA28596@kevlar.burdell.org> References: <20050912024350.60e89eb1.akpm@osdl.org> <20050912145435.GA4722@kevlar.burdell.org> <20050912125641.4b53553d.akpm@osdl.org> <20050913183215.GA28596@kevlar.burdell.org> Message-ID: <20050913184629.GA29416@kevlar.burdell.org> On Tue, Sep 13, 2005 at 02:32:15PM -0400, Sonny Rao wrote: > On Mon, Sep 12, 2005 at 12:56:41PM -0700, Andrew Morton wrote: > > Sonny Rao wrote: > > > > > > On Mon, Sep 12, 2005 at 02:43:50AM -0700, Andrew Morton wrote: > > > > > > > - There are several performance tuning patches here which need careful > > > > attention and testing. (Does anyone do performance testing any more?) > > > > > > > > > > > - The size of the page allocator per-cpu magazines has been increased > > > > > > > > - The page allocator has been changed to use higher-order allocations > > > > when batch-loading the per-cpu magazines. This is intended to give > > > > improved cache colouring effects however it might have the downside of > > > > causing extra page allocator fragmentation. > > > > > > > > - The page allocator's per-cpu magazines have had their lower threshold > > > > set to zero. And we can't remember why it ever had a lower threshold. > > > > > > > > > > What would you like? The usual suspects: SDET, dbench, kernbench ? > > > > > > > That would be a good start, thanks. The higher-order-allocations thing is > > mainly targeted at big-iron numerical computing I believe. > > > > I've already had one report of fragmentation-derived page allocator > > failures (http://bugzilla.kernel.org/show_bug.cgi?id=5229). > > Ok, I'm getting much further on ppc64 thanks to Anton B. > > So far, I need patched in the hvc console fix, Anton's SCSI fix for > 2.6.14-rc1, Paulus's EEH fix, and I reverted > remove-near-all-bugs-in-mm-mempolicyc.patch and > convert-mempolicies-to-nodemask_t.patch > > I got most of the way through the boot scripts and crashed while > bringing up the loopback interface. > > Here's the latest PPC64 crash on 2.6.13-mm3: > > smp_call_function on cpu 5: other cpus not responding (5) > cpu 0x5: Vector: 0 at [c00000000f3b6b00] > pc: 000000000000003d > lr: 000000000000003d > sp: c00000000f3b6a90 > msr: 8000000000009032 > current = 0xc000000002018050 > paca = 0xc00000000048a400 > pid = 1679, comm = ip > enter ? for help > 5:mon> t > > (xmon hangs here) Here's another one with the traceback: 1:mon> e cpu 0x1: Vector: 0 at [c0000001ebff7860] pc: 000000000000003d lr: 000000000000003d sp: c0000001ebff77f0 msr: 8000000000009032 current = 0xc0000001ebf067f0 paca = 0xc000000000488400 pid = 1, comm = swapper 1:mon> 1:mon> t [c0000001ebff77f0] c0000000000403f8 .xmon+0xf4/0x104 (unreliable) [c0000001ebff79c0] c00000000002e6fc .smp_call_function+0x1b4/0x1e0 [c0000001ebff7a70] c000000000084d34 .smp_call_function_all_cpus+0x70/0x98 [c0000001ebff7b00] c000000000085ff4 .do_tune_cpucache+0x10c/0x68c [c0000001ebff7ce0] c0000000000867e8 .enable_cpucache+0x9c/0xec [c0000001ebff7d60] c0000000000878b8 .kmem_cache_create+0x5e0/0x8e4 [c0000001ebff7e60] c00000000045382c .as_init+0x38/0xbc [c0000001ebff7ef0] c000000000008888 .init+0x1f4/0x454 [c0000001ebff7f90] c00000000000fa48 .kernel_thread+0x4c/0x68 1:mon> I'm starting to think I'm going to have to test the above stuff on x86... (maybe someone will prove me wrong ;-)) Sonny From sjmunroe at us.ibm.com Wed Sep 14 06:19:23 2005 From: sjmunroe at us.ibm.com (Steve Munroe) Date: Tue, 13 Sep 2005 15:19:23 -0500 Subject: [PATCH] Add PTRACE_{GET|SET}VRREGS In-Reply-To: <05C56EBB-4F23-48F2-8094-B6543753267A@freescale.com> Message-ID: Changing you internal structures is OK with me. But don't change the size/alignment for PTRACE_GETVRREGS and PTRACE_SETVRREGS Steven J. Munroe Linux on Power Toolchain Architect IBM Corporation, Linux Technology Center Kumar Gala 09/09/2005 09:09 AM To Steve Munroe/Rochester/IBM at IBMUS cc Robert Jennings , Anton Blanchard , linuxppc64-dev , Paul Mackerras Subject Re: [PATCH] Add PTRACE_{GET|SET}VRREGS Steve, Can you provide any insight into Anton's comment. What I would like to see is on ppc64: struct thread_struct { ... #ifdef CONFIG_ALTIVEC /* Complete AltiVec register set */ vector128 vr[32] __attribute((aligned(16))); /* AltiVec status */ vector128 vscr __attribute((aligned(16))); unsigned long vrsave; int used_vr; /* set if process has used altivec */ #endif /* CONFIG_ALTIVEC */ }; turn into: struct thread_struct { ... #ifdef CONFIG_ALTIVEC /* Complete AltiVec register set */ vector128 vr[32] __attribute((aligned(16))); /* AltiVec status */ vector128 vscr __attribute((aligned(16))); unsigned int vrsave; int used_vr; /* set if process has used altivec */ #endif /* CONFIG_ALTIVEC */ }; (Change of unsigned long to unsigned int for vrsave). This is because vrsave is truly only 32-bits in all implementations. Is there some reason this breaks the ppc64 ABI? - kumar On Sep 9, 2005, at 1:47 AM, Anton Blanchard wrote: > > Hi Kumar, > > >> I repeat my request that we make vrsave an unsigned int instead of an >> unsigned long in thread_struct since we are touch this code anyways. >> > > Apparently the 3 word pad is there for a reason in the 64bit ABI, > Steve > Munroe would know the details. > > Anton > From jdl at freescale.com Wed Sep 14 06:38:40 2005 From: jdl at freescale.com (Jon Loeliger) Date: Tue, 13 Sep 2005 15:38:40 -0500 Subject: PATCH powerpc: Merge asm-ppc*/hardirq.h Message-ID: <1126643920.11056.53.camel@cashmere.sps.mot.com> Here is a patch to merge asm-ppc*/hardirq.h. Does anyone know of a problem in ppc64 land that will be caused by having added the jiffy_stamp field into this cacheline-aligned structure? Also, of note here, I dodged the hard question of what to do with SMP and preemption and stuff. Lots more work will have to be resolved to really answer those questions. Let's start here for now... Signed-off-by: Jon Loeliger --- diff --git a/include/asm-powerpc/hardirq.h b/include/asm-powerpc/hardirq.h new file mode 100644 --- /dev/null +++ b/include/asm-powerpc/hardirq.h @@ -0,0 +1,36 @@ +#ifndef _ASM_POWERPC_HARDIRQ_H +#define _ASM_POWERPC_HARDIRQ_H +#ifdef __KERNEL__ + +#include +#include + +#ifdef __powerpc64__ +#include +#else +#include +#include +#endif + +/* The __last_jiffy_stamp field is needed to ensure that no decrementer + * interrupt is lost on SMP machines. Since on most CPUs it is in the same + * cache line as local_irq_count, it is cheap to access and is also used on UP + * for uniformity. + */ +typedef struct { + unsigned int __softirq_pending; /* set_bit is used on this */ + unsigned int __last_jiffy_stamp; +} ____cacheline_aligned irq_cpustat_t; + +#include /* Standard mappings for irq_cpustat_t above */ + +#define last_jiffy_stamp(cpu) __IRQ_STAT((cpu), __last_jiffy_stamp) + +static inline void ack_bad_irq(int irq) +{ + printk(KERN_CRIT "illegal vector %d received!\n", irq); + BUG(); +} + +#endif /* __KERNEL__ */ +#endif /* _ASM_POWERPC_HARDIRQ_H */ diff --git a/include/asm-ppc/hardirq.h b/include/asm-ppc/hardirq.h deleted file mode 100644 --- a/include/asm-ppc/hardirq.h +++ /dev/null @@ -1,31 +0,0 @@ -#ifdef __KERNEL__ -#ifndef __ASM_HARDIRQ_H -#define __ASM_HARDIRQ_H - -#include -#include -#include -#include - -/* The __last_jiffy_stamp field is needed to ensure that no decrementer - * interrupt is lost on SMP machines. Since on most CPUs it is in the same - * cache line as local_irq_count, it is cheap to access and is also used on UP - * for uniformity. - */ -typedef struct { - unsigned long __softirq_pending; /* set_bit is used on this */ - unsigned int __last_jiffy_stamp; -} ____cacheline_aligned irq_cpustat_t; - -#include /* Standard mappings for irq_cpustat_t above */ - -#define last_jiffy_stamp(cpu) __IRQ_STAT((cpu), __last_jiffy_stamp) - -static inline void ack_bad_irq(int irq) -{ - printk(KERN_CRIT "illegal vector %d received!\n", irq); - BUG(); -} - -#endif /* __ASM_HARDIRQ_H */ -#endif /* __KERNEL__ */ diff --git a/include/asm-ppc64/hardirq.h b/include/asm-ppc64/hardirq.h deleted file mode 100644 --- a/include/asm-ppc64/hardirq.h +++ /dev/null @@ -1,27 +0,0 @@ -#ifndef __ASM_HARDIRQ_H -#define __ASM_HARDIRQ_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 -#include - -typedef struct { - unsigned int __softirq_pending; -} ____cacheline_aligned irq_cpustat_t; - -#include /* Standard mappings for irq_cpustat_t above */ - -static inline void ack_bad_irq(int irq) -{ - printk(KERN_CRIT "illegal vector %d received!\n", irq); - BUG(); -} - -#endif /* __ASM_HARDIRQ_H */ From jdl at freescale.com Wed Sep 14 06:43:22 2005 From: jdl at freescale.com (Jon Loeliger) Date: Tue, 13 Sep 2005 15:43:22 -0500 Subject: PATCH powerpc: Merge asm-ppc*/sections.h Message-ID: <1126644202.11056.59.camel@cashmere.sps.mot.com> Here is a patch to merge asm-ppc*/sections.h. If anyone knows if we can do better here, please feel free to abuse, er, let me know! Signed-off-by: Jon Loeliger --- diff --git a/include/asm-powerpc/sections.h b/include/asm-powerpc/sections.h new file mode 100644 --- /dev/null +++ b/include/asm-powerpc/sections.h @@ -0,0 +1,62 @@ +#ifndef _ASM_POWERPC_SECTIONS_H +#define _ASM_POWERPC_SECTIONS_H + +#ifdef __KERNEL__ + +#include + +#ifdef __powerpc64__ + +#define __pmac +#define __pmacdata + +#define __prep +#define __prepdata + +#define __chrp +#define __chrpdata + +#define __openfirmware +#define __openfirmwaredata + +extern char _end[]; + +static inline int in_kernel_text(unsigned long addr) +{ + if (addr >= (unsigned long)_stext && addr < (unsigned long)__init_end) + return 1; + + return 0; +} + +#else /* __powerpc64__ */ + +#define __pmac __attribute__ ((__section__ (".pmac.text"))) +#define __pmacdata __attribute__ ((__section__ (".pmac.data"))) +#define __pmacfunc(__argpmac) \ + __argpmac __pmac; \ + __argpmac + +#define __prep __attribute__ ((__section__ (".prep.text"))) +#define __prepdata __attribute__ ((__section__ (".prep.data"))) +#define __prepfunc(__argprep) \ + __argprep __prep; \ + __argprep + +#define __chrp __attribute__ ((__section__ (".chrp.text"))) +#define __chrpdata __attribute__ ((__section__ (".chrp.data"))) +#define __chrpfunc(__argchrp) \ + __argchrp __chrp; \ + __argchrp + +/* this is actually just common chrp/pmac code, not OF code -- Cort */ +#define __openfirmware __attribute__ ((__section__ (".openfirmware.text"))) +#define __openfirmwaredata __attribute__ ((__section__ (".openfirmware.data"))) +#define __openfirmwarefunc(__argopenfirmware) \ + __argopenfirmware __openfirmware; \ + __argopenfirmware + +#endif /* __powerpc64__ */ + +#endif /* __KERNEL__ */ +#endif /* _ASM_POWERPC_SECTIONS_H */ diff --git a/include/asm-ppc/sections.h b/include/asm-ppc/sections.h deleted file mode 100644 --- a/include/asm-ppc/sections.h +++ /dev/null @@ -1,33 +0,0 @@ -#ifdef __KERNEL__ -#ifndef _PPC_SECTIONS_H -#define _PPC_SECTIONS_H - -#include - -#define __pmac __attribute__ ((__section__ (".pmac.text"))) -#define __pmacdata __attribute__ ((__section__ (".pmac.data"))) -#define __pmacfunc(__argpmac) \ - __argpmac __pmac; \ - __argpmac - -#define __prep __attribute__ ((__section__ (".prep.text"))) -#define __prepdata __attribute__ ((__section__ (".prep.data"))) -#define __prepfunc(__argprep) \ - __argprep __prep; \ - __argprep - -#define __chrp __attribute__ ((__section__ (".chrp.text"))) -#define __chrpdata __attribute__ ((__section__ (".chrp.data"))) -#define __chrpfunc(__argchrp) \ - __argchrp __chrp; \ - __argchrp - -/* this is actually just common chrp/pmac code, not OF code -- Cort */ -#define __openfirmware __attribute__ ((__section__ (".openfirmware.text"))) -#define __openfirmwaredata __attribute__ ((__section__ (".openfirmware.data"))) -#define __openfirmwarefunc(__argopenfirmware) \ - __argopenfirmware __openfirmware; \ - __argopenfirmware - -#endif /* _PPC_SECTIONS_H */ -#endif /* __KERNEL__ */ diff --git a/include/asm-ppc64/sections.h b/include/asm-ppc64/sections.h deleted file mode 100644 --- a/include/asm-ppc64/sections.h +++ /dev/null @@ -1,29 +0,0 @@ -#ifndef _PPC64_SECTIONS_H -#define _PPC64_SECTIONS_H - -extern char _end[]; - -#include - -#define __pmac -#define __pmacdata - -#define __prep -#define __prepdata - -#define __chrp -#define __chrpdata - -#define __openfirmware -#define __openfirmwaredata - - -static inline int in_kernel_text(unsigned long addr) -{ - if (addr >= (unsigned long)_stext && addr < (unsigned long)__init_end) - return 1; - - return 0; -} - -#endif From arnd at arndb.de Wed Sep 14 12:35:21 2005 From: arnd at arndb.de (Arnd Bergmann) Date: Wed, 14 Sep 2005 04:35:21 +0200 Subject: PATCH powerpc: Merge asm-ppc*/sections.h In-Reply-To: <1126644202.11056.59.camel@cashmere.sps.mot.com> References: <1126644202.11056.59.camel@cashmere.sps.mot.com> Message-ID: <200509140435.21916.arnd@arndb.de> On Dinsdag 13 September 2005 22:43, Jon Loeliger wrote: > Here is a patch to merge asm-ppc*/sections.h. > > If anyone knows if we can do better here, > please feel free to abuse, er, let me know! Ok, I don't like this patch. IMHO for the architecture merge, we should have a common implementation of this, either always using per-platform sections or never using them, meaning that we get rid of this file. At the very least, the __*func() macros should go away, they are completely bogus. Using the sections in arch/powerpc has the obvious advantage that it reduces the size of the running kernel, but also has a certain amount of bug-potential or at least makes the code slightly more ugly. It is also easier to remove the feature in ppc than adding it in ppc64. The users of the ppc64 function in_kernel_text() can probably be converted to the generic is_kernel_text() function. Arnd <>< From kumar.gala at freescale.com Wed Sep 14 15:18:11 2005 From: kumar.gala at freescale.com (Kumar Gala) Date: Wed, 14 Sep 2005 00:18:11 -0500 Subject: [PATCH] Add PTRACE_{GET|SET}VRREGS In-Reply-To: References: Message-ID: On Sep 13, 2005, at 3:19 PM, Steve Munroe wrote: > Changing you internal structures is OK with me. But don't change the > size/alignment for PTRACE_GETVRREGS and PTRACE_SETVRREGS Which is the same for ppc32 and ppc64, correct? - kumar > Kumar Gala > 09/09/2005 09:09 AM > > To > Steve Munroe/Rochester/IBM at IBMUS > cc > Robert Jennings , Anton Blanchard > , linuxppc64-dev , Paul > Mackerras > Subject > Re: [PATCH] Add PTRACE_{GET|SET}VRREGS > > > > > > > Steve, > > Can you provide any insight into Anton's comment. > > What I would like to see is on ppc64: > > struct thread_struct { > ... > #ifdef CONFIG_ALTIVEC > /* Complete AltiVec register set */ > vector128 vr[32] __attribute((aligned(16))); > /* AltiVec status */ > vector128 vscr __attribute((aligned(16))); > unsigned long vrsave; > int used_vr; /* set if process has used > altivec */ > #endif /* CONFIG_ALTIVEC */ > }; > > turn into: > > struct thread_struct { > ... > #ifdef CONFIG_ALTIVEC > /* Complete AltiVec register set */ > vector128 vr[32] __attribute((aligned(16))); > /* AltiVec status */ > vector128 vscr __attribute((aligned(16))); > unsigned int vrsave; > int used_vr; /* set if process has used > altivec */ > #endif /* CONFIG_ALTIVEC */ > }; > > (Change of unsigned long to unsigned int for vrsave). This is > because vrsave is truly only 32-bits in all implementations. > > Is there some reason this breaks the ppc64 ABI? > > - kumar > > > On Sep 9, 2005, at 1:47 AM, Anton Blanchard wrote: > > >> >> Hi Kumar, >> >> >> >>> I repeat my request that we make vrsave an unsigned int instead >>> of an >>> unsigned long in thread_struct since we are touch this code anyways. >>> >>> >> >> Apparently the 3 word pad is there for a reason in the 64bit ABI, >> Steve >> Munroe would know the details. >> >> Anton >> >> > > From anton at samba.org Wed Sep 14 20:31:21 2005 From: anton at samba.org (Anton Blanchard) Date: Wed, 14 Sep 2005 20:31:21 +1000 Subject: [PATCH] hvc_console: start kernel thread before registering tty Message-ID: <20050914103121.GA30336@krispykreme> Hi, Its possible that we can write to the hvc_console tty as soon it is registered. Recently this started happening due to (what looks like) a change to the hotplug code. Unfortunately at this stage we have not started the khvcd kernel thread and oops. The solution is to start the kernel thread before registering the tty. Signed-off-by: Anton Blanchard --- Index: build/drivers/char/hvc_console.c =================================================================== --- build.orig/drivers/char/hvc_console.c 2005-09-14 13:22:31.000000000 +1000 +++ build/drivers/char/hvc_console.c 2005-09-14 18:57:16.000000000 +1000 @@ -839,9 +839,6 @@ hvc_driver->flags = TTY_DRIVER_REAL_RAW; tty_set_operations(hvc_driver, &hvc_ops); - if (tty_register_driver(hvc_driver)) - panic("Couldn't register hvc console driver\n"); - /* Always start the kthread because there can be hotplug vty adapters * added later. */ hvc_task = kthread_run(khvcd, NULL, "khvcd"); @@ -851,6 +848,9 @@ return -EIO; } + if (tty_register_driver(hvc_driver)) + panic("Couldn't register hvc console driver\n"); + return 0; } module_init(hvc_init); From hch at lst.de Wed Sep 14 21:05:06 2005 From: hch at lst.de (Christoph Hellwig) Date: Wed, 14 Sep 2005 13:05:06 +0200 Subject: PATCH powerpc: Merge asm-ppc*/hardirq.h In-Reply-To: <1126643920.11056.53.camel@cashmere.sps.mot.com> References: <1126643920.11056.53.camel@cashmere.sps.mot.com> Message-ID: <20050914110506.GA7049@lst.de> On Tue, Sep 13, 2005 at 03:38:40PM -0500, Jon Loeliger wrote: > +#ifndef _ASM_POWERPC_HARDIRQ_H > +#define _ASM_POWERPC_HARDIRQ_H > +#ifdef __KERNEL__ the __KERNEL__ ifdefs is not needed. is only included from which doesn't have anything user-visible. > + > +#include not needed. > +#include > + > +#ifdef __powerpc64__ > +#include > +#else > +#include > +#include > +#endif We shouldn't need either of these include blocks at all. > + > +/* The __last_jiffy_stamp field is needed to ensure that no decrementer > + * interrupt is lost on SMP machines. Since on most CPUs it is in the same > + * cache line as local_irq_count, it is cheap to access and is also used on UP > + * for uniformity. > + */ > +typedef struct { > + unsigned int __softirq_pending; /* set_bit is used on this */ > + unsigned int __last_jiffy_stamp; > +} ____cacheline_aligned irq_cpustat_t; I'd suggest just using a DECLARE_PER_CPU variable for last_jiffy_stamp. In facct I plan to get rid of irq_cpustat_t completely at some point. From sharada at in.ibm.com Wed Sep 14 21:46:30 2005 From: sharada at in.ibm.com (R Sharada) Date: Wed, 14 Sep 2005 17:16:30 +0530 Subject: [PATCH] - Revised patch to export kernel end, htab values In-Reply-To: <17181.14413.180481.331250@cargo.ozlabs.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> <20050902002847.GA2158@in.ibm.com> <17181.14413.180481.331250@cargo.ozlabs.ibm.com> Message-ID: <20050914114630.GA3693@in.ibm.com> Hello Paulus/Michael, I got caught up with kexec-tools work and could not come back to this earlier. The code started off, initially, under CONFIG_KEXEC, but later I removed it thinking it might not be necessary. Putting it back under CONFIG_KEXEC is perhaps the best way to ensure we are not breaking any other configurations. Here's the same patch, under ifdef CONFIG_KEXEC. Kindly consider for inclusion, if there are no objections to this. Thanks and Regards, Sharada ----------------------------------------------------------------------------- This patch exports the htab_base, htab_size, and kernel_end values into /proc/device-tree/chosen. This is required by kexec, to be able to exclude htab and kernel ranges, from the list of valid memory ranges that kexec uses for loading the kexec segments Signed-off-by: R Sharada --- 2614rc1-sharada/linux-2.6.14-rc1/arch/ppc64/kernel/setup.c | 63 +++++++++++++ 2614rc1-sharada/linux-2.6.14-rc1/include/asm-ppc64/mmu.h | 1 2 files changed, 64 insertions(+) diff -puN linux-2.6.14-rc1/arch/ppc64/kernel/setup.c~kexec-export-htab-value linux-2.6.14-rc1/arch/ppc64/kernel/setup.c --- 2614rc1/linux-2.6.14-rc1/arch/ppc64/kernel/setup.c~kexec-export-htab-value 2005-09-14 17:04:37.000000000 +0530 +++ 2614rc1-sharada/linux-2.6.14-rc1/arch/ppc64/kernel/setup.c 2005-09-14 17:05:16.000000000 +0530 @@ -1003,6 +1003,61 @@ void __init setup_syscall_map(void) count32, count64); } +#ifdef CONFIG_KEXEC +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); +} +#endif /* CONFIG_KEXEC */ + /* * Called into from start_kernel, after lock_kernel has been called. * Initializes bootmem, which is unsed to manage page allocation until @@ -1056,6 +1111,14 @@ void __init setup_arch(char **cmdline_p) } paging_init(); + + /* export htab and kernel end values into /proc/device-tree/chosen + * for kexec + */ +#ifdef CONFIG_KEXEC + export_htab_value(); + export_kernel_end(); +#endif /* CONFIG_KEXEC */ ppc64_boot_msg(0x15, "Setup Done"); } diff -puN linux-2.6.14-rc1/include/asm-ppc64/mmu.h~kexec-export-htab-value linux-2.6.14-rc1/include/asm-ppc64/mmu.h --- 2614rc1/linux-2.6.14-rc1/include/asm-ppc64/mmu.h~kexec-export-htab-value 2005-09-14 17:04:37.000000000 +0530 +++ 2614rc1-sharada/linux-2.6.14-rc1/include/asm-ppc64/mmu.h 2005-09-14 17:05:16.000000000 +0530 @@ -63,6 +63,7 @@ extern char initial_stab[]; * Hash table */ +#define HASH_GROUP_SIZE 0x80 /* size of each hash group */ #define HPTES_PER_GROUP 8 #define HPTE_V_AVPN_SHIFT 7 _ From sharada at in.ibm.com Wed Sep 14 22:44:05 2005 From: sharada at in.ibm.com (R Sharada) Date: Wed, 14 Sep 2005 18:14:05 +0530 Subject: [PATCH 0/4] kexec-tools-for-ppc64 Message-ID: <20050914124405.GA3968@in.ibm.com> Hello, After the initial RFC on the kexec-tools for ppc64, the hacks were cleaned up and this patchset now provides a much cleaner kexec-tools support for ppc64. The patch set includes the following: - create_flat_devtree.patch - get_memory_ranges.patch - build_v2wrap_from_purgatory.patch - basic_kexec_tools_for_ppc64.patch - vmlinux is the accepted elf image for the kernel - the v2wrap.S trampoline is built from within purgatory, though we still use a simple add_buffer call to load it - the tools can load a ramdisk, with a --ramdisk option - the valid range of memory for locate_hole to use, is generated from various properties within /proc/device-tree - the configure script was modified to build 64-bit as default for ppc64 - added an ld option to build purgatory as 64-bit (I am not sure if we need this. Can perhaps be cleaned up) The patch is against the kexec-tools-1.101 tarball. It however requires the kexec-tools malloc problem patch to be applied on kexec-tools-1.101 tarball, which can be found here - http://lists.osdl.org/pipermail/fastboot/2005-June/001584.html The patch also requires the following patch in the kernel to be able to obtain the valid memory ranges for kexec-tools to work. The patch for 2.6.14-rc1 is here - http://ozlabs.org/pipermail/linuxppc64-dev/2005-September/005516.html Usage Syntax: ------------- kexec -l --ramdisk= (ramdisk is optional) loads the segments (vmlinux, v2wrap+devtree, and ramdisk if provided in commanline) kexec -e boots the system kexec-style Testing: -------- The patchset has been tested on power4 p630 and power5 p550 boxes (lpar and non-lpar modes) and seen to be working. Request review, testing, comments on the patches. Thanks and Regards, Sharada From sharada at in.ibm.com Wed Sep 14 22:45:34 2005 From: sharada at in.ibm.com (R Sharada) Date: Wed, 14 Sep 2005 18:15:34 +0530 Subject: [PATCH 1/4] create flat device-tree In-Reply-To: <20050914124405.GA3968@in.ibm.com> References: <20050914124405.GA3968@in.ibm.com> Message-ID: <20050914124534.GB3968@in.ibm.com> This patch adds the functionality to create a flat device-tree from /proc/device-tree. It also adds support to modify the initrd address within the flat device-tree. Signed-off-by: R Sharada --- kexec-tools-1.101-sharada/kexec/arch/ppc64/Makefile | 3 kexec-tools-1.101-sharada/kexec/arch/ppc64/fs2dt.c | 340 +++++++++++++++ kexec-tools-1.101-sharada/kexec/arch/ppc64/kexec-ppc64.h | 13 3 files changed, 354 insertions(+), 2 deletions(-) diff -puN kexec/arch/ppc64/Makefile~create_flat_devtree kexec/arch/ppc64/Makefile --- kexec-tools-1.101/kexec/arch/ppc64/Makefile~create_flat_devtree 2005-09-14 12:56:03.000000000 +0530 +++ kexec-tools-1.101-sharada/kexec/arch/ppc64/Makefile 2005-09-14 12:56:33.000000000 +0530 @@ -2,6 +2,7 @@ # kexec ppc64 (linux booting linux) # KEXEC_C_SRCS+= kexec/arch/ppc64/kexec-elf-rel-ppc64.c -KEXEC_C_SRCS+= kexec/arch/ppc64/kexec-zImage-ppc64.c +KEXEC_C_SRCS+= kexec/arch/ppc64/kexec-zImage-ppc64.c +KEXEC_C_SRCS+= kexec/arch/ppc64/fs2dt.c KEXEC_S_SRCS+= diff -puN /dev/null kexec/arch/ppc64/fs2dt.c --- /dev/null 2005-09-09 01:53:00.469998000 +0530 +++ kexec-tools-1.101-sharada/kexec/arch/ppc64/fs2dt.c 2005-09-14 12:57:10.000000000 +0530 @@ -0,0 +1,340 @@ +/* + * fs2dt: creates a flattened device-tree + * + * Copyright (C) 2004,2005 Milton D Miller II, IBM Corporation + * Copyright (C) 2005 R Sharada (sharada at in.ibm.com), 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 (version 2 of the License). + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include "kexec-ppc64.h" + +#define MAXPATH 1024 /* max path name length */ +#define NAMESPACE 16384 /* max bytes for property names */ +#define TREEWORDS 65536 /* max 32 bit words for property values */ +#define MEMRESERVE 256 /* max number of reserved memory blocks */ + +enum { + ERR_NONE, + ERR_USAGE, + ERR_OPENDIR, + ERR_READDIR, + ERR_STAT, + ERR_OPEN, + ERR_READ, + ERR_RESERVE, +}; + +void err(const char *str, int rc) +{ + if (errno) + perror(str); + else + fprintf(stderr, "%s: unrecoverable error\n", str); + exit(rc); +} + +typedef unsigned dvt; +struct stat statbuf[1]; +char pathname[MAXPATH], *pathstart; +char propnames[NAMESPACE]; +dvt dtstruct[TREEWORDS], *dt; +unsigned long long mem_rsrv[2*MEMRESERVE]; + +extern unsigned long initrd_base; +extern unsigned long initrd_size; +static int initrd_found = 0; + +void reserve(unsigned long long where, unsigned long long length) +{ + unsigned long long *mr; + + mr = mem_rsrv; + + while(mr[1]) + mr += 2; + + mr[0] = where; + mr[1] = length; +} + +/* look for properties we need to reserve memory space for */ +void checkprop(char *name, dvt *data) +{ + static unsigned long long base, size, end; + + if ((data == NULL) && (base || size || end)) + err((void *)data, ERR_RESERVE); + else if (!strcmp(name, "linux,rtas-base")) + base = *data; + else if (!strcmp(name, "linux,initrd-start")) { + if (initrd_base) + *(unsigned long long *) data = initrd_base; + base = *(unsigned long long *)data; + initrd_found = 1; + } + else if (!strcmp(name, "linux,tce-base")) + base = *(unsigned long long *) data; + else if (!strcmp(name, "rtas-size") || + !strcmp(name, "linux,tce-size")) + size = *data; + else if (!strcmp(name, "linux,initrd-end")) { + if (initrd_size) { + *(unsigned long long *) data = initrd_base + + initrd_size; + size = initrd_size; + } else + end = *(unsigned long long *)data; + initrd_found = 1; + } + if (size && end) + err(name, ERR_RESERVE); + if (base && size) { + reserve(base, size); + base = size = 0; + } + if (base && end) { + reserve(base, end-base); + base = end = 0; + } +} + +/* + * return the property index for a property name, creating a new one + * if needed. + */ +dvt propnum(const char *name) +{ + dvt offset = 0; + + while(propnames[offset]) + if (strcmp(name, propnames+offset)) + offset += strlen(propnames+offset)+1; + else + return offset; + + strcpy(propnames+offset, name); + + return offset; +} + +/* put all properties (files) in the property structure */ +void putprops(char *fn, DIR *dir) +{ + struct dirent *dp; + + while ((dp = readdir(dir)) != NULL) { + strcpy(fn, dp->d_name); + + if (lstat(pathname, statbuf)) + err(pathname, ERR_STAT); + + /* skip initrd entries if 2nd kernel does not need them */ + if (!initrd_base && !strcmp(fn,"linux,initrd-end")) + continue; + + if (!initrd_base && !strcmp(fn,"linux,initrd-start")) + continue; + + /* + * This property will be created for each node during kexec + * boot. So, ignore it. + */ + if (!strcmp(dp->d_name, "linux,pci-domain") || + !strcmp(dp->d_name, "htab_base") || + !strcmp(dp->d_name, "htab_size") || + !strcmp(dp->d_name, "kernel_end")) + continue; + + if (S_ISREG(statbuf[0].st_mode)) { + int fd, len = statbuf[0].st_size; + + *dt++ = 3; + *dt++ = len; + *dt++ = propnum(fn); + + if ((len >= 8) && ((unsigned long)dt & 0x4)) + dt++; + + fd = open(pathname, O_RDONLY); + if (fd == -1) + err(pathname, ERR_OPEN); + if (read(fd, dt, len) != len) + err(pathname, ERR_READ); + close(fd); + + checkprop(fn, dt); + + dt += (len + 3)/4; + } + } + fn[0] = '\0'; + if(errno == ENOSYS) + errno = 0; + if (errno) + err(pathname, ERR_READDIR); + checkprop(pathname, NULL); +} + +/* + * put a node (directory) in the property structure. first properties + * then children. + */ +void putnode(void) +{ + DIR *dir; + char *dn; + struct dirent *dp; + char *basename; + + *dt++ = 1; + strcpy((void *)dt, *pathstart ? pathstart : "/"); + while(*dt) + dt++; + if (dt[-1] & 0xff) + dt++; + + dir = opendir(pathname); + + if (!dir) + err(pathname, ERR_OPENDIR); + + basename = strrchr(pathname,'/'); + + strcat(pathname, "/"); + dn = pathname + strlen(pathname); + + putprops(dn, dir); + + /* Add initrd entries to the second kernel if first kernel does not + * have and second kernel needs. + */ + if (initrd_base && !initrd_found && !strcmp(basename,"/chosen/")) { + int len = 8; + unsigned long long initrd_end; + *dt++ = 3; + *dt++ = len; + *dt++ = propnum("linux,initrd-start"); + + if ((len >= 8) && ((unsigned long)dt & 0x4)) + dt++; + + memcpy(dt,&initrd_base,len); + dt += (len + 3)/4; + + len = 8; + *dt++ = 3; + *dt++ = len; + *dt++ = propnum("linux,initrd-end"); + + initrd_end = initrd_base + initrd_size; + if ((len >= 8) && ((unsigned long)dt & 0x4)) + dt++; + + memcpy(dt,&initrd_end,8); + dt += (len + 3)/4; + + reserve(initrd_base, initrd_size); + } + + rewinddir(dir); + + while ((dp = readdir(dir)) != NULL) { + strcpy(dn, dp->d_name); + + if (!strcmp(dn, ".") || !strcmp(dn, "..")) + continue; + + if (lstat(pathname, statbuf)) + err(pathname, ERR_STAT); + + if (S_ISDIR(statbuf[0].st_mode)) + putnode(); + } + if (errno) + err(pathname, ERR_READDIR); + + *dt++ = 2; + closedir(dir); + dn[-1] = '\0'; +} + +struct bootblock bb[1]; + +int create_flatten_tree(struct kexec_info *info, unsigned char **bufp, unsigned long *sizep) +{ + unsigned long len; + unsigned long tlen; + unsigned char *buf; + unsigned long me; + + me = 0; + + strcpy(pathname, "/proc/device-tree/"); + + pathstart = pathname + strlen(pathname); + dt = dtstruct; + + putnode(); + *dt++ = 9; + + len = sizeof(bb[0]); + len += 7; len &= ~7; + + bb->off_mem_rsvmap = len; + + for (len = 1; mem_rsrv[len]; len += 2) + ; + len+= 3; + len *= sizeof(mem_rsrv[0]); + + bb->off_dt_struct = bb->off_mem_rsvmap + len; + + len = dt - dtstruct; + len *= sizeof(dvt); + bb->off_dt_strings = bb->off_dt_struct + len; + + len = propnum(""); + len += 3; len &= ~3; + bb->totalsize = bb->off_dt_strings + len; + + bb->magic = 0xd00dfeed; + bb->version = 2; + bb->last_comp_version = 2; + + reserve(me, bb->totalsize); /* patched later in kexec_load */ + + buf = (unsigned char *) realloc(*bufp, *sizep + bb->totalsize); + *bufp = buf; + memcpy(buf+(*sizep), bb, bb->off_mem_rsvmap); + tlen = *sizep + bb->off_mem_rsvmap; + memcpy(buf+tlen, mem_rsrv, bb->off_dt_struct - bb->off_mem_rsvmap); + tlen = tlen + (bb->off_dt_struct - bb->off_mem_rsvmap); + memcpy(buf+tlen, dtstruct, bb->off_dt_strings - bb->off_dt_struct); + tlen = tlen + (bb->off_dt_strings - bb->off_dt_struct); + memcpy(buf+tlen, propnames, bb->totalsize - bb->off_dt_strings); + tlen = tlen + bb->totalsize - bb->off_dt_strings; + *sizep = tlen; + return 0; +} diff -puN kexec/arch/ppc64/kexec-ppc64.h~create_flat_devtree kexec/arch/ppc64/kexec-ppc64.h --- kexec-tools-1.101/kexec/arch/ppc64/kexec-ppc64.h~create_flat_devtree 2005-09-14 12:56:03.000000000 +0530 +++ kexec-tools-1.101-sharada/kexec/arch/ppc64/kexec-ppc64.h 2005-09-14 12:56:33.000000000 +0530 @@ -6,4 +6,15 @@ int elf_ppc64_load(int argc, char **argv struct kexec_info *info); void elf_ppc64_usage(void); -#endif /* KEXEC_PPC_H */ +/* boot block version 2 as defined by the linux kernel */ +struct bootblock { + unsigned magic, + totalsize, + off_dt_struct, + off_dt_strings, + off_mem_rsvmap, + version, + last_comp_version, + boot_physid; +}; +#endif /* KEXEC_PPC64_H */ _ From sharada at in.ibm.com Wed Sep 14 22:47:29 2005 From: sharada at in.ibm.com (R Sharada) Date: Wed, 14 Sep 2005 18:17:29 +0530 Subject: [PATCH 3/4] build v2wrap from purgatory In-Reply-To: <20050914124645.GC3968@in.ibm.com> References: <20050914124405.GA3968@in.ibm.com> <20050914124534.GB3968@in.ibm.com> <20050914124645.GC3968@in.ibm.com> Message-ID: <20050914124729.GD3968@in.ibm.com> This patch builds v2wrap from within purgatory Signed-off-by: R Sharada --- kexec-tools-1.101-sharada/purgatory/Makefile | 12 + kexec-tools-1.101-sharada/purgatory/arch/ppc64/Makefile | 2 kexec-tools-1.101-sharada/purgatory/arch/ppc64/v2wrap.S | 114 ++++++++++++++++ 3 files changed, 127 insertions(+), 1 deletion(-) diff -puN purgatory/Makefile~build_v2wrap_from_purgatory purgatory/Makefile --- kexec-tools-1.101/purgatory/Makefile~build_v2wrap_from_purgatory 2005-09-14 13:08:16.000000000 +0530 +++ kexec-tools-1.101-sharada/purgatory/Makefile 2005-09-14 13:08:43.000000000 +0530 @@ -6,6 +6,11 @@ # There is probably a cleaner way to do this but for now this # should keep us from accidentially include unsafe library functions # or headers. + +ifeq ($(ARCH),ppc64) +LDFLAGS = -melf64ppc +endif + PCFLAGS:=-Wall -Os \ -I$(shell $(CC) -print-file-name=include) \ -Ipurgatory/include -Ipurgatory/arch/$(ARCH)/include \ @@ -17,9 +22,11 @@ PCFLAGS += $(call cc-option, -fnostdinc) PCFLAGS += $(call cc-option, -fno-zero-initialized-in-bss) PURGATORY_C_SRCS:= +ifneq ($(ARCH),ppc64) PURGATORY_C_SRCS += purgatory/purgatory.c PURGATORY_C_SRCS += purgatory/printf.c PURGATORY_C_SRCS += purgatory/string.c +endif PURGATORY_S_OBJS:= include purgatory/arch/$(ARCH)/Makefile @@ -54,7 +61,12 @@ $(PURGATORY_S_OBJS): $(OBJDIR)/%.o: %.S $(PURGATORY): $(PURGATORY_OBJS) $(UTIL_LIB) $(MKDIR) -p $(@D) +ifneq ($(ARCH),ppc64) $(LD) $(LDFLAGS) --no-undefined -e purgatory_start -r -o $@ $(PURGATORY_OBJS) $(UTIL_LIB) +else + $(LD) -Ttext=0 -e 0 -o $(OBJDIR)/purgatory/v2wrap.elf $(PURGATORY_OBJS) + objcopy -O binary $(OBJDIR)/purgatory/v2wrap.elf $@ +endif echo:: @echo "PURGATORY_C_SRCS $(PURGATORY_C_SRCS)" diff -puN purgatory/arch/ppc64/Makefile~build_v2wrap_from_purgatory purgatory/arch/ppc64/Makefile --- kexec-tools-1.101/purgatory/arch/ppc64/Makefile~build_v2wrap_from_purgatory 2005-09-14 13:08:16.000000000 +0530 +++ kexec-tools-1.101-sharada/purgatory/arch/ppc64/Makefile 2005-09-14 13:08:43.000000000 +0530 @@ -3,5 +3,5 @@ # PURGATORY_C_SRCS+= -PURGATORY_S_SRCS+= +PURGATORY_S_SRCS+= purgatory/arch/ppc64/v2wrap.S diff -puN /dev/null purgatory/arch/ppc64/v2wrap.S --- /dev/null 2005-09-09 01:53:00.469998000 +0530 +++ kexec-tools-1.101-sharada/purgatory/arch/ppc64/v2wrap.S 2005-09-14 13:08:43.000000000 +0530 @@ -0,0 +1,114 @@ +# +# kexec: Linux boots Linux +# +# Copyright (C) 2004 - 2005, Milton D Miller II, 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 (version 2 of the License). +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +# + +# v2wrap.S +# a wrapper to place in front of a v2 device tree +# to call a ppc64 kernel with the expected arguments +# of kernel(device-tree, phys-offset, 0) +# +# calling convention: +# r3 = physical number of this cpu (all cpus) +# r4 = address of this chunk (master only) +# master enters at start (aka first byte of this chunk) +# slaves (additional cpus), if any, enter a copy of the +# first 0x100 bytes of this code relocated to 0x0 +# +# in other words, +# a copy of the first 0x100 bytes of this code is copied to 0 +# and the slaves are sent to address 0x60 +# with r3 = their physical cpu number. + + +# look a bit like a Linux kernel here ... + .machine ppc64 + .org 0 +start: b master + tweq 0,0 +secondary_hold: + .llong 0 + + .org 0x20 # need a bit more space than after slave, +master: + std 4,secondary_hold at l(0) # bring slaves up here to this copy + sync # try to get the slaves to see this + or 1,1,1 # low priority to let other thread catchup + isync + mr 5,3 # save cpu id to r5 + addi 3,4,0x100 # r3 = boot param block + lwz 6,20(3) # fetch version number + cmpwi 0,6,2 # v2 ? + blt 80f + stw 5,28(3) # save my cpu number as boot_cpu_phys +80: b 81f + + .org 0x60 # ABI: slaves start at 60 with r3=phys +slave: ld 4,secondary_hold at l(0); + cmpdi 0,4,0 + beq slave + + # ahh, master told us where he is running from + # jump into our copy of the code up there so this code can change + addi 5,4,1f-start + mtctr 5 + bctr + + # ok, now wait for the master to tell is to go back to the new block +1: ld 5,copied at l(4) + cmpdi 0,5,0 + beq 1b + ba 0x60 + + + + .long 0 # just an eye-catcher, delete if space needed + .long 0 # just an eye-catcher, delete if space needed + +81: # master continues here + or 3,3,3 # ok back to high, lets boot + lis 6,0x1 + mtctr 6 # delay a bit for slaves to catch up +83: bdnz 83b # before we overwrite 0-100 again + + ld 4,-8(3) # kernel pointer is at -8(bb) by loader + addi 5,4,-8 # prepare copy with update form instructions + li 6,0x100/8 + mtctr 6 + li 6,-8 +85: ldu 7,8(5) + stdu 7,8(6) + bdnz 85b + + li 5,0 # r5 will be 0 for kernel + dcbst 0,5 # store dcache, flush icache + dcbst 0,6 # 0 and 0xf8 covers us with 128 byte lines + mtctr 4 # prepare branch too + sync + icbi 0,5 + icbi 0,6 + sync + isync + std 6,-16(3) # send slaves back down + bctr # start kernel + + .org 0xf0 +copied: .llong 0 +kernel: .llong 0 + .org 0x100 +__end_stub: + .equ boot_block, . - start _ From sharada at in.ibm.com Wed Sep 14 22:48:34 2005 From: sharada at in.ibm.com (R Sharada) Date: Wed, 14 Sep 2005 18:18:34 +0530 Subject: [PATCH 4/4] basic kexec tools for ppc64 In-Reply-To: <20050914124729.GD3968@in.ibm.com> References: <20050914124405.GA3968@in.ibm.com> <20050914124534.GB3968@in.ibm.com> <20050914124645.GC3968@in.ibm.com> <20050914124729.GD3968@in.ibm.com> Message-ID: <20050914124834.GE3968@in.ibm.com> This provides the basic functionality in kexec-elf-ppc64.c to load the various segments required for kexec-tools on ppc64. It also adds ppc64 arch support in build scripts and cleans up some misc error in member deferencing to allow the build to succeed. Signed-off-by: R Sharada --- kexec-tools-1.101-sharada/configure | 7 kexec-tools-1.101-sharada/kexec/arch/ppc64/kexec-elf-ppc64.c | 240 ++++++++-- kexec-tools-1.101-sharada/kexec/arch/ppc64/kexec-elf-rel-ppc64.c | 2 kexec-tools-1.101-sharada/kexec/arch/ppc64/kexec-ppc64.h | 2 4 files changed, 214 insertions(+), 37 deletions(-) diff -puN configure~basic_kexec_tools_for_ppc64 configure --- kexec-tools-1.101/configure~basic_kexec_tools_for_ppc64 2005-09-14 13:10:39.000000000 +0530 +++ kexec-tools-1.101-sharada/configure 2005-09-14 13:11:05.000000000 +0530 @@ -1384,6 +1384,9 @@ case $host_cpu in powerpc ) host_cpu="ppc" ;; + powerpc64 ) + host_cpu="ppc64" + ;; * ) host_cpu="$host_cpu" ;; @@ -1421,6 +1424,10 @@ if test "${with_gamecube+set}" = set; th EXTRA_CFLAGS="$EXTRA_CFLAGS -DCONFIG_GAMECUBE=1" fi; +# Check whether ppc64. Add -m64 for building 64-bit binary +if test "$ARCH"=ppc64; then + EXTRA_CFLAGS="$EXTRA_CFLAGS -m64" +fi; # Check whether --with-zlib or --without-zlib was given. if test "${with_zlib+set}" = set; then diff -puN kexec/arch/ppc64/kexec-elf-ppc64.c~basic_kexec_tools_for_ppc64 kexec/arch/ppc64/kexec-elf-ppc64.c --- kexec-tools-1.101/kexec/arch/ppc64/kexec-elf-ppc64.c~basic_kexec_tools_for_ppc64 2005-09-14 13:10:39.000000000 +0530 +++ kexec-tools-1.101-sharada/kexec/arch/ppc64/kexec-elf-ppc64.c 2005-09-14 13:11:05.000000000 +0530 @@ -3,6 +3,7 @@ * * Copyright (C) 2004 Adam Litke (agl at us.ibm.com) * Copyright (C) 2004 IBM Corp. + * Copyright (C) 2005 R Sharada (sharada at in.ibm.com) * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -33,45 +34,15 @@ #include "../../kexec.h" #include "../../kexec-elf.h" #include "kexec-ppc64.h" +#include #define BOOTLOADER "kexec" #define BOOTLOADER_VERSION VERSION #define MAX_COMMAND_LINE 256 -#define UPSZ(X) ((sizeof(X) + 3) & ~3) -static struct boot_notes { - Elf_Bhdr hdr; - Elf_Nhdr bl_hdr; - unsigned char bl_desc[UPSZ(BOOTLOADER)]; - Elf_Nhdr blv_hdr; - unsigned char blv_desc[UPSZ(BOOTLOADER_VERSION)]; - Elf_Nhdr cmd_hdr; - unsigned char command_line[0]; -} elf_boot_notes = { - .hdr = { - .b_signature = 0x0E1FB007, - .b_size = sizeof(elf_boot_notes), - .b_checksum = 0, - .b_records = 3, - }, - .bl_hdr = { - .n_namesz = 0, - .n_descsz = sizeof(BOOTLOADER), - .n_type = EBN_BOOTLOADER_NAME, - }, - .bl_desc = BOOTLOADER, - .blv_hdr = { - .n_namesz = 0, - .n_descsz = sizeof(BOOTLOADER_VERSION), - .n_type = EBN_BOOTLOADER_VERSION, - }, - .blv_desc = BOOTLOADER_VERSION, - .cmd_hdr = { - .n_namesz = 0, - .n_descsz = 0, - .n_type = EBN_COMMAND_LINE, - }, -}; +int create_flatten_tree(struct kexec_info *, unsigned char*, unsigned long *); +int parse_options(char *); +int setup_memory_ranges(void); int elf_ppc64_probe(const char *buf, off_t len) { @@ -94,12 +65,62 @@ int elf_ppc64_probe(const char *buf, off return result; } -int elf_ppc64_load(int argc, char **argv, const char *buf, off_t len, +int elf_ppc64_load(int argc, char **argv, const char *buf, off_t len, struct kexec_info *info) { struct mem_ehdr ehdr; + const char *command_line; + const char *input_options; + int command_line_len; + const char *ramdisk; + unsigned long *lp; + int result; + int opt; +#define OPT_APPEND (OPT_ARCH_MAX+0) +#define OPT_RAMDISK (OPT_ARCH_MAX+1) + + static const struct option options[] = { + KEXEC_ARCH_OPTIONS + { "append", 1, NULL, OPT_APPEND }, + { "ramdisk", 1, NULL, OPT_RAMDISK }, + { 0, 0, NULL, 0 }, + }; + + static const char short_options[] = KEXEC_OPT_STR ""; /* Parse command line arguments */ + initrd_base = 0; + initrd_size = 0; + command_line = 0; + input_options = 0; + ramdisk = 0; + + while ((opt = getopt_long(argc, argv, short_options, options, 0)) != -1) { + switch (opt) { + default: + /* Ignore core options */ + if (opt < OPT_ARCH_MAX) { + break; + } + case '?': + usage(); + return -1; + case OPT_APPEND: + input_options = optarg; + break; + case OPT_RAMDISK: + ramdisk = optarg; + break; + } + } + + command_line_len = 0; + if (command_line) { + command_line_len = strlen(command_line) + 1; + } + + if (input_options) + parse_options(input_options); /* Parse the Elf file */ result = build_elf_exec_info(buf, len, &ehdr); @@ -109,15 +130,162 @@ int elf_ppc64_load(int argc, char **argv } /* Load the Elf data */ + setup_memory_ranges(); + /* Load the Elf data. Physical load addresses in elf64 header do not + * show up correctly. Use user supplied address for now to patch the + * elf header + */ + unsigned long long base_addr; + struct mem_phdr *phdr; + size_t size; + + phdr = &ehdr.e_phdr[0]; + size = phdr->p_filesz; + if (size > phdr->p_memsz) { + size = phdr->p_memsz; + } + + base_addr = (unsigned long)locate_hole(info, size, 0, 0, + 0xFFFFFFFFFFFFFFFFUL, 1); + ehdr.e_phdr[0].p_paddr = base_addr; result = elf_exec_load(&ehdr, info); if (result < 0) { free_elf_info(&ehdr); return result; } - return 1; + + /* Add a ram-disk to the current image */ + if (ramdisk) { + unsigned char *ramdisk_buf = NULL; + off_t ramdisk_size = 0; + unsigned long long ramdisk_addr; + + ramdisk_buf = slurp_file(ramdisk, &ramdisk_size); + add_buffer(info, ramdisk_buf, ramdisk_size, ramdisk_size, 0, 0, + 0xFFFFFFFFFFFFFFFFUL, 1); + ramdisk_addr = info->segment[info->nr_segments-1].mem; + initrd_base = ramdisk_addr; + initrd_size = ramdisk_size; + } + + /* Add v2wrap to the current image */ + unsigned char *v2wrap_buf = NULL; + off_t v2wrap_size = 0; + unsigned int len; + unsigned char *buf; + unsigned int rsvmap_len; + unsigned long long *ptr; + struct bootblock *bb_ptr; + unsigned int devtree_size; + + v2wrap_buf = (char *) malloc(purgatory_size); + if (v2wrap_buf == NULL) { + free_elf_info(&ehdr); + return -1; + } + memcpy(v2wrap_buf, purgatory, purgatory_size); + v2wrap_size = purgatory_size; + create_flatten_tree(info, &v2wrap_buf, &v2wrap_size); + add_buffer(info, v2wrap_buf, v2wrap_size, v2wrap_size, 0, 0, + 0xFFFFFFFFFFFFFFFFUL, -1); + + /* patch reserve map address for flattened device-tree */ + base_addr = info->segment[(info->nr_segments)-1].mem; + buf = (unsigned char *)info->segment[(info->nr_segments)-1].buf; + buf = buf + 0x100; /* offset to end of v2wrap */ + bb_ptr = (struct bootblock *)buf; + rsvmap_len = bb_ptr->off_dt_struct - bb_ptr->off_mem_rsvmap; + devtree_size = bb_ptr->totalsize; + len = sizeof(struct bootblock); + len += 7; len &= ~7; + buf = buf + len; + len = rsvmap_len / (2 * sizeof(unsigned long long)); + + ptr = (unsigned long long *)buf; + ptr = ptr + 2*(len-2); + *ptr = base_addr + 0x100; + ptr++; + *ptr = (unsigned long long)devtree_size; + + unsigned int nr_segments; + nr_segments = info->nr_segments; + lp = info->segment[nr_segments-1].buf + 0x100; + lp--; + *lp = info->segment[0].mem; + info->entry = info->segment[nr_segments-1].mem; + + unsigned int i; + for (i = 0; i < nr_segments; i++) + printf("segment[i].mem:%lx\n", info->segment[i].mem); + + return 0; } void elf_ppc64_usage(void) { fprintf(stderr, "elf support is still broken\n"); } + +struct param_struct { + const char *name; + void *val; +}; +struct param_struct params; + +static char *next_arg(char *args, char **param, char **val) +{ + unsigned int i, equals = 0; + char *next; + + /* Chew any extra spaces */ + while (*args == ' ') args++; + for (i = 0; args[i]; i++) { + if (args[i] == ' ') + break; + if (equals == 0) { + if (args[i] == '=') + equals = i; + } + } + *param = args; + if (!equals) + *val = NULL; + else { + args[equals] = '\0'; + *val = args + equals + 1; + } + + if (args[i]) { + args[i] = '\0'; + next = args + i + 1; + } else + next = args + i; + return next; +} + +static int add_arg(char *param, char*val) +{ + int ret = 0; + if (strcmp(param, "initrd-base")==0) + initrd_base=strtoul(val, NULL, 0); + else if (strcmp(param, "initrd-size")==0) + initrd_size=strtoul(val, NULL, 0); + else { + printf("invalid option\n"); + ret = 1; + } + return ret; +} + +int parse_options(char *options) +{ + char *param, *val; + /* initrd-addr , initrd-size */ + while (*options) { + int ret; + options = next_arg(options, ¶m, &val); + ret = add_arg(param, val); + } + /* All parsed OK */ + return 0; +} diff -puN kexec/arch/ppc64/kexec-elf-rel-ppc64.c~basic_kexec_tools_for_ppc64 kexec/arch/ppc64/kexec-elf-rel-ppc64.c --- kexec-tools-1.101/kexec/arch/ppc64/kexec-elf-rel-ppc64.c~basic_kexec_tools_for_ppc64 2005-09-14 13:10:39.000000000 +0530 +++ kexec-tools-1.101-sharada/kexec/arch/ppc64/kexec-elf-rel-ppc64.c 2005-09-14 13:11:05.000000000 +0530 @@ -22,7 +22,7 @@ static struct mem_shdr *toc_section(cons struct mem_shdr *shdr, *shdr_end; unsigned char *strtab; strtab = ehdr->e_shdr[ehdr->e_shstrndx].sh_data; - shdr_end = &ehdr->e_shdr[ehdr->shnum]; + shdr_end = &ehdr->e_shdr[ehdr->e_shnum]; for(shdr = ehdr->e_shdr; shdr != shdr_end; shdr++) { if (strcmp(shdr->sh_name, ".toc") == 0) { return shdr; diff -puN kexec/arch/ppc64/kexec-ppc64.h~basic_kexec_tools_for_ppc64 kexec/arch/ppc64/kexec-ppc64.h --- kexec-tools-1.101/kexec/arch/ppc64/kexec-ppc64.h~basic_kexec_tools_for_ppc64 2005-09-14 13:10:39.000000000 +0530 +++ kexec-tools-1.101-sharada/kexec/arch/ppc64/kexec-ppc64.h 2005-09-14 13:11:05.000000000 +0530 @@ -6,6 +6,8 @@ int elf_ppc64_load(int argc, char **argv struct kexec_info *info); void elf_ppc64_usage(void); +unsigned long initrd_base; +unsigned long initrd_size; /* boot block version 2 as defined by the linux kernel */ struct bootblock { unsigned magic, _ From sharada at in.ibm.com Wed Sep 14 22:46:45 2005 From: sharada at in.ibm.com (R Sharada) Date: Wed, 14 Sep 2005 18:16:45 +0530 Subject: [PATCH 2/4] get memory ranges In-Reply-To: <20050914124534.GB3968@in.ibm.com> References: <20050914124405.GA3968@in.ibm.com> <20050914124534.GB3968@in.ibm.com> Message-ID: <20050914124645.GC3968@in.ibm.com> This patch adds functionality to obtain the base memory ranges from /proc/device-tree/memory at xxx nodes and exclude ranges not valid for passing into kexec-tools. It adds the functionality of the get_memory_ranges function. Signed-off-by: R Sharada --- kexec-tools-1.101-sharada/kexec/arch/ppc64/Makefile | 2 kexec-tools-1.101-sharada/kexec/arch/ppc64/kexec-ppc64.c | 526 +++++++++++++++ 2 files changed, 528 insertions(+) diff -puN kexec/arch/ppc64/Makefile~get_memory_ranges kexec/arch/ppc64/Makefile --- kexec-tools-1.101/kexec/arch/ppc64/Makefile~get_memory_ranges 2005-09-14 12:59:22.000000000 +0530 +++ kexec-tools-1.101-sharada/kexec/arch/ppc64/Makefile 2005-09-14 12:59:33.000000000 +0530 @@ -4,5 +4,7 @@ KEXEC_C_SRCS+= kexec/arch/ppc64/kexec-elf-rel-ppc64.c KEXEC_C_SRCS+= kexec/arch/ppc64/kexec-zImage-ppc64.c KEXEC_C_SRCS+= kexec/arch/ppc64/fs2dt.c +KEXEC_C_SRCS+= kexec/arch/ppc64/kexec-elf-ppc64.c +KEXEC_C_SRCS+= kexec/arch/ppc64/kexec-ppc64.c KEXEC_S_SRCS+= diff -puN /dev/null kexec/arch/ppc64/kexec-ppc64.c --- /dev/null 2005-09-09 01:53:00.469998000 +0530 +++ kexec-tools-1.101-sharada/kexec/arch/ppc64/kexec-ppc64.c 2005-09-14 13:07:10.000000000 +0530 @@ -0,0 +1,526 @@ +/* + * kexec: Linux boots Linux + * + * Copyright (C) 2003-2005 Eric Biederman (ebiederm at xmission.com) + * Copyright (C) 2005 R Sharada (sharada at in.ibm.com), 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 (version 2 of the License). + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "../../kexec.h" +#include "../../kexec-syscall.h" +#include "kexec-ppc64.h" +#include + +#define MAX_MEMORY_RANGES 64 +#define MAX_LINE 160 +#define MAXBYTES 128 +/* Platforms supported by kexec on PPC64 */ +#define PLATFORM_PSERIES 0x0100 +#define PLATFORM_PSERIES_LPAR 0x0101 + +struct exclude_range { + unsigned long long start, end; +}; +static struct exclude_range exclude_range[MAX_MEMORY_RANGES]; + +static unsigned long long rmo_top; +static unsigned int platform; +static struct memory_range memory_range[MAX_MEMORY_RANGES]; +static struct memory_range base_memory_range[MAX_MEMORY_RANGES]; +unsigned long long memory_max = 0; +static int nr_memory_ranges; +static int nr_exclude_ranges; + +/* Get base memory ranges */ +static int get_base_ranges() +{ + int local_memory_ranges = 0; + char device_tree[256] = "/proc/device-tree/"; + char fname[256]; + char buf[MAXBYTES-1]; + DIR *dir, *dmem; + FILE *file; + struct dirent *dentry, *mentry; + int n; + unsigned long long start, end; + + if ((dir = opendir(device_tree)) == NULL) { + perror(device_tree); + return -1; + } + while ((dentry = readdir(dir)) != NULL) { + if (strncmp(dentry->d_name, "memory@", 7)) + continue; + strcpy(fname, device_tree); + strcat(fname, dentry->d_name); + if ((dmem = opendir(fname)) == NULL) { + perror(fname); + closedir(dir); + return -1; + } + while ((mentry = readdir(dmem)) != NULL) { + if (strcmp(mentry->d_name, "reg")) + continue; + strcat(fname, "/reg"); + if ((file = fopen(fname, "r")) == NULL) { + perror(fname); + closedir(dmem); + closedir(dir); + return -1; + } + if ((n = fread(buf, 1, MAXBYTES, file)) < 0) { + perror(fname); + fclose(file); + closedir(dmem); + closedir(dir); + return -1; + } + if (local_memory_ranges >= MAX_MEMORY_RANGES) + break; + base_memory_range[local_memory_ranges].start = + ((unsigned long long *)buf)[0]; + base_memory_range[local_memory_ranges].end = + base_memory_range[local_memory_ranges].start + + ((unsigned long long *)buf)[1]; + base_memory_range[local_memory_ranges].type = RANGE_RAM; + local_memory_ranges++; +#if 0 + fprintf(stderr, "%016Lx-%016Lx : %x\n", memory_range[local_memory_ranges-1].start, memory_range[local_memory_ranges-1].end, memory_range[local_memory_ranges].type); +#endif + fclose(file); + } + memory_max = base_memory_range[local_memory_ranges - 1].end; + closedir(dmem); + } + closedir(dir); + nr_memory_ranges = local_memory_ranges; + fprintf(stderr, "get base memory ranges:%d\n", nr_memory_ranges); + return 0; +} + +/* Sort the exclude ranges in memory */ +static int sort_ranges() +{ + int i, j; + unsigned long long tstart, tend; + for (i = 0; i < nr_exclude_ranges - 1; i++) { + for (j = 0; j < nr_exclude_ranges - i - 1; j++) { + if (exclude_range[j].start > exclude_range[j+1].start) { + tstart = exclude_range[j].start; + tend = exclude_range[j].end; + exclude_range[j].start = exclude_range[j+1].start; + exclude_range[j].end = exclude_range[j+1].end; + exclude_range[j+1].start = tstart; + exclude_range[j+1].end = tend; + } + } + } + return 0; +} + +/* Get devtree details and create exclude_range array */ +static int get_devtree_details() +{ + unsigned long long rmo_base; + unsigned long long tce_base; + unsigned int tce_size; + char buf[MAXBYTES-1]; + char device_tree[256] = "/proc/device-tree/"; + char fname[256]; + DIR *dir, *cdir; + FILE *file; + struct dirent *dentry; + int n, i = 0; + + if ((dir = opendir(device_tree)) == NULL) { + perror(device_tree); + return -1; + } + + while ((dentry = readdir(dir)) != NULL) { + if (strncmp(dentry->d_name, "chosen", 6) && + strncmp(dentry->d_name, "memory at 0", 8) && + strncmp(dentry->d_name, "pci@", 4) && + strncmp(dentry->d_name, "rtas", 4)) + continue; + strcpy(fname, device_tree); + strcat(fname, dentry->d_name); + if ((cdir = opendir(fname)) == NULL) { + perror(fname); + closedir(dir); + return -1; + } + + if (strncmp(dentry->d_name, "chosen", 6) == 0) { + /* get platform details from /chosen node */ + strcat(fname, "/linux,platform"); + if ((file = fopen(fname, "r")) == NULL) { + perror(fname); + closedir(cdir); + closedir(dir); + return -1; + } + if (fread(&platform, sizeof(int), 1, file) != 1) { + perror(fname); + fclose(file); + closedir(cdir); + closedir(dir); + return -1; + } + fclose(file); + memset(fname, 0, sizeof(fname)); + strcpy(fname, device_tree); + strcat(fname, dentry->d_name); + strcat(fname, "/kernel_end"); + if ((file = fopen(fname, "r")) == NULL) { + perror(fname); + closedir(cdir); + closedir(dir); + return -1; + } + unsigned long long kernel_end; + if (fread(&kernel_end, sizeof(unsigned long), 1, file) != 1) { + perror(fname); + fclose(file); + closedir(cdir); + closedir(dir); + return -1; + } + /* Add kernel memory to exclude_range */ + exclude_range[i].start = 0x0UL; + exclude_range[i].end = kernel_end; + i++; + /* if LPAR, no need to read any more from /chosen */ + if (platform != PLATFORM_PSERIES) { + closedir(cdir); + continue; + } + memset(fname, 0, sizeof(fname)); + strcpy(fname, device_tree); + strcat(fname, dentry->d_name); + strcat(fname, "/htab_base"); + if ((file = fopen(fname, "r")) == NULL) { + perror(fname); + closedir(cdir); + closedir(dir); + return -1; + } + unsigned long long htab_base, htab_size; + if (fread(&htab_base, sizeof(unsigned long), 1, file) != 1) { + perror(fname); + fclose(file); + closedir(cdir); + closedir(dir); + return -1; + } + memset(fname, 0, sizeof(fname)); + strcpy(fname, device_tree); + strcat(fname, dentry->d_name); + strcat(fname, "/htab_size"); + if ((file = fopen(fname, "r")) == NULL) { + perror(fname); + closedir(cdir); + closedir(dir); + return -1; + } + if (fread(&htab_size, sizeof(unsigned long), 1, file) != 1) { + perror(fname); + fclose(file); + closedir(cdir); + closedir(dir); + return -1; + } + /* Add htab address to exclude_range - NON-LPAR only */ + exclude_range[i].start = htab_base; + exclude_range[i].end = htab_base + htab_size; + i++; + } /* chosen */ + + if (strncmp(dentry->d_name, "rtas", 4) == 0) { + strcat(fname, "/linux,rtas-base"); + if ((file = fopen(fname, "r")) == NULL) { + perror(fname); + closedir(cdir); + closedir(dir); + return -1; + } + unsigned int rtas_base, rtas_size; + if (fread(&rtas_base, sizeof(unsigned int), 1, file) != 1) { + perror(fname); + fclose(file); + closedir(cdir); + closedir(dir); + return -1; + } + memset(fname, 0, sizeof(fname)); + strcpy(fname, device_tree); + strcat(fname, dentry->d_name); + strcat(fname, "/rtas-size"); + if ((file = fopen(fname, "r")) == NULL) { + perror(fname); + closedir(cdir); + closedir(dir); + return -1; + } + if (fread(&rtas_size, sizeof(unsigned int), 1, file) != 1) { + perror(fname); + fclose(file); + closedir(cdir); + closedir(dir); + return -1; + } + closedir(cdir); + /* Add rtas to exclude_range */ + exclude_range[i].start = rtas_base; + exclude_range[i].end = rtas_base + rtas_size; + i++; + } /* rtas */ + + if (strncmp(dentry->d_name, "memory at 0", 8) == 0) { + strcat(fname, "/reg"); + if ((file = fopen(fname, "r")) == NULL) { + perror(fname); + closedir(cdir); + closedir(dir); + return -1; + } + if ((n = fread(buf, 1, MAXBYTES, file)) < 0) { + perror(fname); + fclose(file); + closedir(cdir); + closedir(dir); + return -1; + } + rmo_base = ((unsigned long long *)buf)[0]; + rmo_top = rmo_base + ((unsigned long long *)buf)[1]; + if (platform == PLATFORM_PSERIES) + if (memory_max > 0x40000000UL? (rmo_top = 0x40000000UL) : (rmo_top = memory_max)); + fclose(file); + closedir(cdir); + } /* memory */ + + if (strncmp(dentry->d_name, "pci@", 4) == 0) { + if (platform != PLATFORM_PSERIES) { + closedir(cdir); + continue; + } + strcat(fname, "/linux,tce-base"); + if ((file = fopen(fname, "r")) == NULL) { + perror(fname); + closedir(cdir); + closedir(dir); + return -1; + } + if (fread(&tce_base, sizeof(unsigned long), 1, file) != 1) { + perror(fname); + fclose(file); + closedir(cdir); + closedir(dir); + return -1; + } + memset(fname, 0, sizeof(fname)); + strcpy(fname, device_tree); + strcat(fname, dentry->d_name); + strcat(fname, "/linux,tce-size"); + if ((file = fopen(fname, "r")) == NULL) { + perror(fname); + closedir(cdir); + closedir(dir); + return -1; + } + if (fread(&tce_size, sizeof(unsigned int), 1, file) != 1) { + perror(fname); + fclose(file); + closedir(cdir); + closedir(dir); + return -1; + } + /* Add tce to exclude_range - NON-LPAR only */ + exclude_range[i].start = tce_base; + exclude_range[i].end = tce_base + tce_size; + i++; + closedir(cdir); + } /* pci */ + } + closedir(dir); + + nr_exclude_ranges = i; + + sort_ranges(); +#if 0 + int k; + for (k = 0; k < i; k++) + fprintf(stderr, "exclude_range sorted exclude_range[%d] start:%lx, end:%lx\n", k, exclude_range[k].start, exclude_range[k].end); +#endif + return 0; +} + +/* Setup a sorted list of memory ranges. */ +int setup_memory_ranges(void) +{ + int i, j = 0; + + /* Get the base list of memory ranges from /proc/device-tree/memory + * nodes. Build list of ranges to be excluded from valid memory + */ + + get_base_ranges(); + get_devtree_details(); + + for (i = 0; i < nr_exclude_ranges; i++) { + /* If first exclude range does not start with 0, include the + * first hole of valid memory from 0 - exclude_range[0].start + */ + if (i == 0) { + if (exclude_range[i].start != 0) { + memory_range[j].start = 0; + memory_range[j].end = exclude_range[i].start - 1; + memory_range[j].type = RANGE_RAM; + j++; + } + } /* i == 0 */ + /* If the last exclude range does not end at memory_max, include + * the last hole of valid memory from exclude_range[last].end - + * memory_max + */ + if (i == nr_exclude_ranges - 1) { + if (exclude_range[i].end < memory_max) { + memory_range[j].start = exclude_range[i].end + 1; + memory_range[j].end = memory_max; + memory_range[j].type = RANGE_RAM; + j++; + /* Limit the end to rmo_top */ + if (memory_range[j-1].start >= rmo_top) { + j--; + break; + } + if ((memory_range[j-1].start < rmo_top) && + (memory_range[j-1].end >= rmo_top)) { + memory_range[j-1].end = rmo_top; + break; + } + continue; + } + } /* i == nr_exclude_ranges - 1 */ + /* contiguous exclude ranges - skip */ + if (exclude_range[i+1].start == exclude_range[i].end + 1) + continue; + memory_range[j].start = exclude_range[i].end + 1; + memory_range[j].end = exclude_range[i+1].start - 1; + memory_range[j].type = RANGE_RAM; + j++; + /* Limit range to rmo_top */ + if (memory_range[j-1].start >= rmo_top) { + j--; + break; + } + if ((memory_range[j-1].start < rmo_top) && (memory_range[j-1].end >= rmo_top)) { + memory_range[j-1].end = rmo_top; + break; + } + } + nr_memory_ranges = j; + +#if 0 + int k; + for (k = 0; k < j; k++) + fprintf(stderr, "seup_memory_ranges memory_range[%d] start:%lx, end:%lx\n", k, memory_range[k].start, memory_range[k].end); +#endif + return 0; +} + +/* Return a list of valid memory ranges */ +int get_memory_ranges(struct memory_range **range, int *ranges) +{ + setup_memory_ranges(); + *range = memory_range; + *ranges = nr_memory_ranges; + fprintf(stderr, "get memory ranges:%d\n", nr_memory_ranges); + return 0; +} + +struct file_type file_type[] = { + { "elf-ppc64", elf_ppc64_probe, elf_ppc64_load, elf_ppc64_usage }, +}; +int file_types = sizeof(file_type) / sizeof(file_type[0]); + +void arch_usage(void) +{ +} + +static struct { +} arch_options = { +}; + +int arch_process_options(int argc, char **argv) +{ + static const struct option options[] = { + KEXEC_ARCH_OPTIONS + { 0, 0, NULL, 0 }, + }; + static const char short_options[] = KEXEC_ARCH_OPT_STR; + int opt; + + opterr = 0; /* Don't complain about unrecognized options here */ + while((opt = getopt_long(argc, argv, short_options, options, 0)) != -1) { + switch(opt) { + default: + break; + } + } + /* Reset getopt for the next pass; called in other source modules */ + opterr = 1; + optind = 1; + return 0; +} + +int arch_compat_trampoline(struct kexec_info *info, unsigned long *flags) +{ + int result; + struct utsname utsname; + result = uname(&utsname); + if (result < 0) { + fprintf(stderr, "uname failed: %s\n", + strerror(errno)); + return -1; + } + if (strcmp(utsname.machine, "ppc64") == 0) + { + /* We are running a 32-bit kexec-tools on 64-bit ppc64. + * So pass KEXEC_ARCH_PPC64 here + */ + *flags |= KEXEC_ARCH_PPC64; + } + else { + fprintf(stderr, "Unsupported machine type: %s\n", + utsname.machine); + return -1; + } + return 0; +} + +void arch_update_purgatory(struct kexec_info *info) +{ +} _ From jdl at freescale.com Wed Sep 14 23:41:34 2005 From: jdl at freescale.com (Jon Loeliger) Date: Wed, 14 Sep 2005 08:41:34 -0500 Subject: PATCH powerpc: Merge asm-ppc*/hardirq.h In-Reply-To: <20050914110506.GA7049@lst.de> References: <1126643920.11056.53.camel@cashmere.sps.mot.com> <20050914110506.GA7049@lst.de> Message-ID: <1126705294.14036.4.camel@cashmere.sps.mot.com> On Wed, 2005-09-14 at 06:05, Christoph Hellwig wrote: > On Tue, Sep 13, 2005 at 03:38:40PM -0500, Jon Loeliger wrote: > > +#ifndef _ASM_POWERPC_HARDIRQ_H > > +#define _ASM_POWERPC_HARDIRQ_H > > +#ifdef __KERNEL__ > > the __KERNEL__ ifdefs is not needed. is only included > from which doesn't have anything user-visible. Will do. > > + > > +#include > > not needed. > > > +#include > > + > > +#ifdef __powerpc64__ > > +#include > > +#else > > +#include > > +#include > > +#endif > > We shouldn't need either of these include blocks at all. OK. I'll do some out-ripping and verify that it all compiles still. > > + > > +/* The __last_jiffy_stamp field is needed to ensure that no decrementer > > + * interrupt is lost on SMP machines. Since on most CPUs it is in the same > > + * cache line as local_irq_count, it is cheap to access and is also used on UP > > + * for uniformity. > > + */ > > +typedef struct { > > + unsigned int __softirq_pending; /* set_bit is used on this */ > > + unsigned int __last_jiffy_stamp; > > +} ____cacheline_aligned irq_cpustat_t; > > I'd suggest just using a DECLARE_PER_CPU variable for last_jiffy_stamp. > In facct I plan to get rid of irq_cpustat_t completely at some point. Hmmm... So, I don't want to mess that up. How about I leave it as I've suggested and leave that step up to you as a follow on? Thanks, jdl From hch at lst.de Wed Sep 14 23:43:47 2005 From: hch at lst.de (Christoph Hellwig) Date: Wed, 14 Sep 2005 15:43:47 +0200 Subject: PATCH powerpc: Merge asm-ppc*/hardirq.h In-Reply-To: <1126705294.14036.4.camel@cashmere.sps.mot.com> References: <1126643920.11056.53.camel@cashmere.sps.mot.com> <20050914110506.GA7049@lst.de> <1126705294.14036.4.camel@cashmere.sps.mot.com> Message-ID: <20050914134347.GB9700@lst.de> On Wed, Sep 14, 2005 at 08:41:34AM -0500, Jon Loeliger wrote: > > I'd suggest just using a DECLARE_PER_CPU variable for last_jiffy_stamp. > > In facct I plan to get rid of irq_cpustat_t completely at some point. > > Hmmm... So, I don't want to mess that up. How about I leave it > as I've suggested and leave that step up to you as a follow on? ok. From jdl at freescale.com Wed Sep 14 23:46:28 2005 From: jdl at freescale.com (Jon Loeliger) Date: Wed, 14 Sep 2005 08:46:28 -0500 Subject: PATCH powerpc: Merge asm-ppc*/sections.h In-Reply-To: <200509140435.21916.arnd@arndb.de> References: <1126644202.11056.59.camel@cashmere.sps.mot.com> <200509140435.21916.arnd@arndb.de> Message-ID: <1126705588.14036.10.camel@cashmere.sps.mot.com> On Tue, 2005-09-13 at 21:35, Arnd Bergmann wrote: > On Dinsdag 13 September 2005 22:43, Jon Loeliger wrote: > > Here is a patch to merge asm-ppc*/sections.h. > > > > If anyone knows if we can do better here, > > please feel free to abuse, er, let me know! > > Ok, I don't like this patch. You will be pleased to know, then, that Becky and I both didn't like this patch either. :-) > IMHO for the architecture merge, we should > have a common implementation of this, either always using per-platform > sections or never using them, meaning that we get rid of this file. Yeah. > At the very least, the __*func() macros should go away, they are completely > bogus. I'll work on eliminating those (at least) and submitting a cleanup patch for that as needed. > Using the sections in arch/powerpc has the obvious advantage that it > reduces the size of the running kernel, but also has a certain amount > of bug-potential or at least makes the code slightly more ugly. > It is also easier to remove the feature in ppc than adding it in ppc64. In the Grand Scheme of Things, removing things and making them simpler seems a lofty goal. :-) Anyone know of any pitfalls that await me if I try to remove these sections, a la pmac and friends? And I assume that the obvious mappings can take place (ie, that "pmac.text" can just be placed in regular .text, etc), right? > The users of the ppc64 function in_kernel_text() can probably be converted > to the generic is_kernel_text() function. I'll peer into that a bit too. > Arnd <>< Thanks! jdl From sjmunroe at us.ibm.com Thu Sep 15 00:35:34 2005 From: sjmunroe at us.ibm.com (Steve Munroe) Date: Wed, 14 Sep 2005 09:35:34 -0500 Subject: [PATCH] Add PTRACE_{GET|SET}VRREGS In-Reply-To: Message-ID: Kumar Gala wrote on 09/14/2005 12:18:11 AM: > > On Sep 13, 2005, at 3:19 PM, Steve Munroe wrote: > > > Changing you internal structures is OK with me. But don't change the > > size/alignment for PTRACE_GETVRREGS and PTRACE_SETVRREGS > > Which is the same for ppc32 and ppc64, correct? > /* * 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. */ This definition. Steven J. Munroe Linux on Power Toolchain Architect IBM Corporation, Linux Technology Center From kumar.gala at freescale.com Thu Sep 15 01:41:26 2005 From: kumar.gala at freescale.com (Kumar Gala) Date: Wed, 14 Sep 2005 10:41:26 -0500 Subject: [PATCH] powerpc: Merged ppc_asm.h In-Reply-To: References: Message-ID: Paul, What's the status of applying this to your tree? http://patchwork.ozlabs.org/linuxppc/patch?id=2330 - kumar On Sep 9, 2005, at 3:02 PM, Gala Kumar K.-galak wrote: > Merged ppc_asm.h between ppc32 & ppc64. The majority of the file is > common between the two architectures excluding how a single GPR is > saved/restored and which GPRs are non-volatile. > > Additionally, moved the ASM_CONST macro used on ppc64 into ppc_asm.h. > > Signed-off-by: Kumar Gala > > --- > commit ba0d4d2e26509b73b7daed0c203f481d0bb06ea0 > tree fa78f19160a9174f1fec441c4f3351962c75dad4 > parent bbe4b1a6e25818f03d09f3260345bfa4442acca0 > author Kumar K. Gala Fri, 09 Sep 2005 > 15:01:18 -0500 > committer Kumar K. Gala Fri, 09 Sep 2005 > 15:01:18 -0500 > > arch/ppc/kernel/head.S | 6 - > arch/ppc/kernel/head_fsl_booke.S | 6 - > include/asm-powerpc/ppc_asm.h | 437 > ++++++++++++++++++++++++++++++++++++++ > include/asm-ppc/ppc_asm.h | 350 > ------------------------------ > include/asm-ppc64/cputable.h | 2 > include/asm-ppc64/mmu.h | 1 > include/asm-ppc64/page.h | 8 - > include/asm-ppc64/ppc_asm.h | 242 --------------------- > 8 files changed, 446 insertions(+), 606 deletions(-) > > diff --git a/arch/ppc/kernel/head.S b/arch/ppc/kernel/head.S > --- a/arch/ppc/kernel/head.S > +++ b/arch/ppc/kernel/head.S > @@ -804,7 +804,7 @@ load_up_altivec: > beq 1f > add r4,r4,r6 > addi r4,r4,THREAD /* want THREAD of last_task_used_altivec > */ > - SAVE_32VR(0,r10,r4) > + SAVE_32VRS(0,r10,r4) > mfvscr vr0 > li r10,THREAD_VSCR > stvx vr0,r10,r4 > @@ -824,7 +824,7 @@ load_up_altivec: > stw r4,THREAD_USED_VR(r5) > lvx vr0,r10,r5 > mtvscr vr0 > - REST_32VR(0,r10,r5) > + REST_32VRS(0,r10,r5) > #ifndef CONFIG_SMP > subi r4,r5,THREAD > sub r4,r4,r6 > @@ -870,7 +870,7 @@ giveup_altivec: > addi r3,r3,THREAD /* want THREAD of task */ > lwz r5,PT_REGS(r3) > cmpwi 0,r5,0 > - SAVE_32VR(0, r4, r3) > + SAVE_32VRS(0, r4, r3) > mfvscr vr0 > li r4,THREAD_VSCR > stvx vr0,r4,r3 > diff --git a/arch/ppc/kernel/head_fsl_booke.S > b/arch/ppc/kernel/head_fsl_booke.S > --- a/arch/ppc/kernel/head_fsl_booke.S > +++ b/arch/ppc/kernel/head_fsl_booke.S > @@ -853,7 +853,7 @@ load_up_spe: > cmpi 0,r4,0 > beq 1f > addi r4,r4,THREAD /* want THREAD of last_task_used_spe */ > - SAVE_32EVR(0,r10,r4) > + SAVE_32EVRS(0,r10,r4) > evxor evr10, evr10, evr10 /* clear out evr10 */ > evmwumiaa evr10, evr10, evr10 /* evr10 <- ACC = 0 * 0 + ACC */ > li r5,THREAD_ACC > @@ -873,7 +873,7 @@ load_up_spe: > stw r4,THREAD_USED_SPE(r5) > evlddx evr4,r10,r5 > evmra evr4,evr4 > - REST_32EVR(0,r10,r5) > + REST_32EVRS(0,r10,r5) > #ifndef CONFIG_SMP > subi r4,r5,THREAD > stw r4,last_task_used_spe at l(r3) > @@ -963,7 +963,7 @@ _GLOBAL(giveup_spe) > addi r3,r3,THREAD /* want THREAD of task */ > lwz r5,PT_REGS(r3) > cmpi 0,r5,0 > - SAVE_32EVR(0, r4, r3) > + SAVE_32EVRS(0, r4, r3) > evxor evr6, evr6, evr6 /* clear out evr6 */ > evmwumiaa evr6, evr6, evr6 /* evr6 <- ACC = 0 * 0 + ACC */ > li r4,THREAD_ACC > diff --git a/include/asm-powerpc/ppc_asm.h > b/include/asm-powerpc/ppc_asm.h > new file mode 100644 > --- /dev/null > +++ b/include/asm-powerpc/ppc_asm.h > @@ -0,0 +1,437 @@ > +/* > + * Copyright (C) 1995-1999 Gary Thomas, Paul Mackerras, Cort Dougan. > + */ > + > +#ifndef _ASM_POWERPC_PPC_ASM_H > +#define _ASM_POWERPC_PPC_ASM_H > + > +#ifdef __ASSEMBLY__ > + > +/* > + * Macros for storing registers into and loading registers from > + * exception frames. > + */ > +#ifdef __powerpc64__ > +#define SAVE_GPR(n, base) std n,GPR0+8*(n)(base) > +#define REST_GPR(n, base) ld n,GPR0+8*(n)(base) > +#define SAVE_NVGPRS(base) SAVE_8GPRS(14, base); SAVE_10GPRS(22, > base) > +#define REST_NVGPRS(base) REST_8GPRS(14, base); REST_10GPRS(22, > base) > +#else > +#define SAVE_GPR(n, base) stw n,GPR0+4*(n)(base) > +#define REST_GPR(n, base) lwz n,GPR0+4*(n)(base) > +#define SAVE_NVGPRS(base) SAVE_GPR(13, base); SAVE_8GPRS(14, > base); \ > + SAVE_10GPRS(22, base) > +#define REST_NVGPRS(base) REST_GPR(13, base); REST_8GPRS(14, > base); \ > + REST_10GPRS(22, base) > +#endif > + > + > +#define SAVE_2GPRS(n, base) SAVE_GPR(n, base); SAVE_GPR(n+1, base) > +#define SAVE_4GPRS(n, base) SAVE_2GPRS(n, base); SAVE_2GPRS(n+2, > base) > +#define SAVE_8GPRS(n, base) SAVE_4GPRS(n, base); SAVE_4GPRS(n+4, > base) > +#define SAVE_10GPRS(n, base) SAVE_8GPRS(n, base); SAVE_2GPRS(n+8, > base) > +#define REST_2GPRS(n, base) REST_GPR(n, base); REST_GPR(n+1, base) > +#define REST_4GPRS(n, base) REST_2GPRS(n, base); REST_2GPRS(n+2, > base) > +#define REST_8GPRS(n, base) REST_4GPRS(n, base); REST_4GPRS(n+4, > base) > +#define REST_10GPRS(n, base) REST_8GPRS(n, base); REST_2GPRS(n+8, > base) > + > +#define SAVE_FPR(n, base) stfd n,THREAD_FPR0+8*(n)(base) > +#define SAVE_2FPRS(n, base) SAVE_FPR(n, base); SAVE_FPR(n+1, base) > +#define SAVE_4FPRS(n, base) SAVE_2FPRS(n, base); SAVE_2FPRS(n+2, > base) > +#define SAVE_8FPRS(n, base) SAVE_4FPRS(n, base); SAVE_4FPRS(n+4, > base) > +#define SAVE_16FPRS(n, base) SAVE_8FPRS(n, base); SAVE_8FPRS(n+8, > base) > +#define SAVE_32FPRS(n, base) SAVE_16FPRS(n, base); SAVE_16FPRS(n > +16, > base) > +#define REST_FPR(n, base) lfd n,THREAD_FPR0+8*(n)(base) > +#define REST_2FPRS(n, base) REST_FPR(n, base); REST_FPR(n+1, base) > +#define REST_4FPRS(n, base) REST_2FPRS(n, base); REST_2FPRS(n+2, > base) > +#define REST_8FPRS(n, base) REST_4FPRS(n, base); REST_4FPRS(n+4, > base) > +#define REST_16FPRS(n, base) REST_8FPRS(n, base); REST_8FPRS(n+8, > base) > +#define REST_32FPRS(n, base) REST_16FPRS(n, base); REST_16FPRS(n > +16, > base) > + > +#define SAVE_VR(n,b,base) li b,THREAD_VR0+(16*(n)); stvx n,b,base > +#define SAVE_2VRS(n,b,base) SAVE_VR(n,b,base); SAVE_VR(n+1,b,base) > +#define SAVE_4VRS(n,b,base) SAVE_2VRS(n,b,base); > SAVE_2VRS(n+2,b,base) > +#define SAVE_8VRS(n,b,base) SAVE_4VRS(n,b,base); > SAVE_4VRS(n+4,b,base) > +#define SAVE_16VRS(n,b,base) SAVE_8VRS(n,b,base); > SAVE_8VRS(n+8,b,base) > +#define SAVE_32VRS(n,b,base) SAVE_16VRS(n,b,base); > SAVE_16VRS(n+16,b,base) > +#define REST_VR(n,b,base) li b,THREAD_VR0+(16*(n)); lvx n,b,base > +#define REST_2VRS(n,b,base) REST_VR(n,b,base); REST_VR(n+1,b,base) > +#define REST_4VRS(n,b,base) REST_2VRS(n,b,base); > REST_2VRS(n+2,b,base) > +#define REST_8VRS(n,b,base) REST_4VRS(n,b,base); > REST_4VRS(n+4,b,base) > +#define REST_16VRS(n,b,base) REST_8VRS(n,b,base); > REST_8VRS(n+8,b,base) > +#define REST_32VRS(n,b,base) REST_16VRS(n,b,base); > REST_16VRS(n+16,b,base) > + > +#define SAVE_EVR(n,s,base) evmergehi s,s,n; stw > s,THREAD_EVR0+4*(n)(base) > +#define SAVE_2EVRS(n,s,base) SAVE_EVR(n,s,base); SAVE_EVR(n > +1,s,base) > +#define SAVE_4EVRS(n,s,base) SAVE_2EVRS(n,s,base); > SAVE_2EVRS(n+2,s,base) > +#define SAVE_8EVRS(n,s,base) SAVE_4EVRS(n,s,base); > SAVE_4EVRS(n+4,s,base) > +#define SAVE_16EVRS(n,s,base) SAVE_8EVRS(n,s,base); > SAVE_8EVRS(n+8,s,base) > +#define SAVE_32EVRS(n,s,base) SAVE_16EVRS(n,s,base); > SAVE_16EVRS(n+16,s,base) > +#define REST_EVR(n,s,base) lwz s,THREAD_EVR0+4*(n)(base); > evmergelo > n,s,n > +#define REST_2EVRS(n,s,base) REST_EVR(n,s,base); REST_EVR(n > +1,s,base) > +#define REST_4EVRS(n,s,base) REST_2EVRS(n,s,base); > REST_2EVRS(n+2,s,base) > +#define REST_8EVRS(n,s,base) REST_4EVRS(n,s,base); > REST_4EVRS(n+4,s,base) > +#define REST_16EVRS(n,s,base) REST_8EVRS(n,s,base); > REST_8EVRS(n+8,s,base) > +#define REST_32EVRS(n,s,base) REST_16EVRS(n,s,base); > REST_16EVRS(n+16,s,base) > + > +/* Macros to adjust thread priority for Iseries hardware > multithreading > */ > +#define HMT_LOW or 1,1,1 > +#define HMT_MEDIUM or 2,2,2 > +#define HMT_HIGH or 3,3,3 > + > +/* handle instructions that older assemblers may not know */ > +#define RFCI .long 0x4c000066 /* rfci instruction */ > +#define RFDI .long 0x4c00004e /* rfdi instruction */ > +#define RFMCI .long 0x4c00004c /* rfmci instruction */ > + > +/* > + * LOADADDR( rn, name ) > + * loads the address of 'name' into 'rn' > + * > + * LOADBASE( rn, name ) > + * loads the address (less the low 16 bits) of 'name' into 'rn' > + * suitable for base+disp addressing > + */ > +#ifdef __powerpc64__ > +#define LOADADDR(rn,name) \ > + lis rn,name##@highest; \ > + ori rn,rn,name##@higher; \ > + rldicr rn,rn,32,31; \ > + oris rn,rn,name##@h; \ > + ori rn,rn,name##@l > + > +#define LOADBASE(rn,name) \ > + lis rn,name at highest; \ > + ori rn,rn,name at higher; \ > + rldicr rn,rn,32,31; \ > + oris rn,rn,name at ha > + > + > +#define SET_REG_TO_CONST(reg, value) \ > + lis reg,(((value)>>48)&0xFFFF); \ > + ori reg,reg,(((value)>>32)&0xFFFF); \ > + rldicr reg,reg,32,31; \ > + oris reg,reg,(((value)>>16)&0xFFFF); \ > + ori reg,reg,((value)&0xFFFF); > + > +#define SET_REG_TO_LABEL(reg, label) \ > + lis reg,(label)@highest; \ > + ori reg,reg,(label)@higher; \ > + rldicr reg,reg,32,31; \ > + oris reg,reg,(label)@h; \ > + ori reg,reg,(label)@l; > +#endif > + > +/* various errata or part fixups */ > +#ifdef CONFIG_PPC601_SYNC_FIX > +#define SYNC \ > +BEGIN_FTR_SECTION \ > + sync; \ > + isync; \ > +END_FTR_SECTION_IFSET(CPU_FTR_601) > +#define SYNC_601 \ > +BEGIN_FTR_SECTION \ > + sync; \ > +END_FTR_SECTION_IFSET(CPU_FTR_601) > +#define ISYNC_601 \ > +BEGIN_FTR_SECTION \ > + isync; \ > +END_FTR_SECTION_IFSET(CPU_FTR_601) > +#else > +#define SYNC > +#define SYNC_601 > +#define ISYNC_601 > +#endif > + > + > +#ifndef CONFIG_SMP > +#define TLBSYNC > +#else /* CONFIG_SMP */ > +/* tlbsync is not implemented on 601 */ > +#define TLBSYNC \ > +BEGIN_FTR_SECTION \ > + tlbsync; \ > + sync; \ > +END_FTR_SECTION_IFCLR(CPU_FTR_601) > +#endif > + > + > +/* > + * This instruction is not implemented on the PPC 603 or 601; > however, > on > + * the 403GCX and 405GP tlbia IS defined and tlbie is not. > + * All of these instructions exist in the 8xx, they have magical > powers, > + * and they must be used. > + */ > + > +#if !defined(CONFIG_4xx) && !defined(CONFIG_8xx) > +#define tlbia \ > + li r4,1024; \ > + mtctr r4; \ > + lis r4,KERNELBASE at h; \ > +0: tlbie r4; \ > + addi r4,r4,0x1000; \ > + bdnz 0b > +#endif > + > + > +#ifdef CONFIG_IBM405_ERR77 > +#define PPC405_ERR77(ra,rb) dcbt ra, rb; > +#define PPC405_ERR77_SYNC sync; > +#else > +#define PPC405_ERR77(ra,rb) > +#define PPC405_ERR77_SYNC > +#endif > + > + > +#ifdef CONFIG_IBM440EP_ERR42 > +#define PPC440EP_ERR42 isync > +#else > +#define PPC440EP_ERR42 > +#endif > + > + > +#if defined(CONFIG_BOOKE) > +#define tophys(rd,rs) \ > + addis rd,rs,0 > + > +#define tovirt(rd,rs) \ > + addis rd,rs,0 > + > +#elif defined(CONFIG_PPC64) > +/* PPPBBB - DRENG If KERNELBASE is always 0xC0..., > + * Then we can easily do this with one asm insn. -Peter > + */ > +#define tophys(rd,rs) \ > + lis rd,((KERNELBASE>>48)&0xFFFF); \ > + rldicr rd,rd,32,31; \ > + sub rd,rs,rd > + > +#define tovirt(rd,rs) \ > + lis rd,((KERNELBASE>>48)&0xFFFF); \ > + rldicr rd,rd,32,31; \ > + add rd,rs,rd > +#else > +/* > + * On APUS (Amiga PowerPC cpu upgrade board), we don't know the > + * physical base address of RAM at compile time. > + */ > +#define tophys(rd,rs) \ > +0: addis rd,rs,-KERNELBASE at h; \ > + .section ".vtop_fixup","aw"; \ > + .align 1; \ > + .long 0b; \ > + .previous > + > +#define tovirt(rd,rs) \ > +0: addis rd,rs,KERNELBASE at h; \ > + .section ".ptov_fixup","aw"; \ > + .align 1; \ > + .long 0b; \ > + .previous > +#endif > + > +/* > + * On 64-bit cpus, we use the rfid instruction instead of rfi, but > + * we then have to make sure we preserve the top 32 bits except for > + * the 64-bit mode bit, which we clear. > + */ > +#if defined(CONFIG_PPC64BRIDGE) > +#define FIX_SRR1(ra, rb) \ > + mr rb,ra; \ > + mfmsr ra; \ > + clrldi ra,ra,1; /* turn off 64-bit mode */ \ > + rldimi ra,rb,0,32 > +#define RFI .long 0x4c000024 /* rfid > instruction */ > +#define MTMSRD(r) .long (0x7c000164 + ((r) << 21)) /* > mtmsrd */ > +#define CLR_TOP32(r) rlwinm (r),(r),0,0,31 /* clear top > 32 bits */ > +#elif defined(CONFIG_PPC64) > +/* Insert the high 32 bits of the MSR into what will be the new > + MSR (via SRR1 and rfid) This preserves the MSR.SF and MSR.ISF > + bits. */ > + > +#define FIX_SRR1(ra, rb) \ > + mr rb,ra; \ > + mfmsr ra; \ > + rldimi ra,rb,0,32 > + > +#define CLR_TOP32(r) rlwinm (r),(r),0,0,31 /* clear top > 32 bits */ > + > +#else > +#define FIX_SRR1(ra, rb) > +#ifndef CONFIG_40x > +#define RFI rfi > +#else > +#define RFI rfi; b . /* Prevent prefetch past rfi */ > +#endif > +#define MTMSRD(r) mtmsr r > +#define CLR_TOP32(r) > +#endif > + > +/* The boring bits... */ > + > +/* Condition Register Bit Fields */ > + > +#define cr0 0 > +#define cr1 1 > +#define cr2 2 > +#define cr3 3 > +#define cr4 4 > +#define cr5 5 > +#define cr6 6 > +#define cr7 7 > + > + > +/* General Purpose Registers (GPRs) */ > + > +#define r0 0 > +#define r1 1 > +#define r2 2 > +#define r3 3 > +#define r4 4 > +#define r5 5 > +#define r6 6 > +#define r7 7 > +#define r8 8 > +#define r9 9 > +#define r10 10 > +#define r11 11 > +#define r12 12 > +#define r13 13 > +#define r14 14 > +#define r15 15 > +#define r16 16 > +#define r17 17 > +#define r18 18 > +#define r19 19 > +#define r20 20 > +#define r21 21 > +#define r22 22 > +#define r23 23 > +#define r24 24 > +#define r25 25 > +#define r26 26 > +#define r27 27 > +#define r28 28 > +#define r29 29 > +#define r30 30 > +#define r31 31 > + > + > +/* Floating Point Registers (FPRs) */ > + > +#define fr0 0 > +#define fr1 1 > +#define fr2 2 > +#define fr3 3 > +#define fr4 4 > +#define fr5 5 > +#define fr6 6 > +#define fr7 7 > +#define fr8 8 > +#define fr9 9 > +#define fr10 10 > +#define fr11 11 > +#define fr12 12 > +#define fr13 13 > +#define fr14 14 > +#define fr15 15 > +#define fr16 16 > +#define fr17 17 > +#define fr18 18 > +#define fr19 19 > +#define fr20 20 > +#define fr21 21 > +#define fr22 22 > +#define fr23 23 > +#define fr24 24 > +#define fr25 25 > +#define fr26 26 > +#define fr27 27 > +#define fr28 28 > +#define fr29 29 > +#define fr30 30 > +#define fr31 31 > + > +/* AltiVec Registers (VPRs) */ > + > +#define vr0 0 > +#define vr1 1 > +#define vr2 2 > +#define vr3 3 > +#define vr4 4 > +#define vr5 5 > +#define vr6 6 > +#define vr7 7 > +#define vr8 8 > +#define vr9 9 > +#define vr10 10 > +#define vr11 11 > +#define vr12 12 > +#define vr13 13 > +#define vr14 14 > +#define vr15 15 > +#define vr16 16 > +#define vr17 17 > +#define vr18 18 > +#define vr19 19 > +#define vr20 20 > +#define vr21 21 > +#define vr22 22 > +#define vr23 23 > +#define vr24 24 > +#define vr25 25 > +#define vr26 26 > +#define vr27 27 > +#define vr28 28 > +#define vr29 29 > +#define vr30 30 > +#define vr31 31 > + > +/* SPE Registers (EVPRs) */ > + > +#define evr0 0 > +#define evr1 1 > +#define evr2 2 > +#define evr3 3 > +#define evr4 4 > +#define evr5 5 > +#define evr6 6 > +#define evr7 7 > +#define evr8 8 > +#define evr9 9 > +#define evr10 10 > +#define evr11 11 > +#define evr12 12 > +#define evr13 13 > +#define evr14 14 > +#define evr15 15 > +#define evr16 16 > +#define evr17 17 > +#define evr18 18 > +#define evr19 19 > +#define evr20 20 > +#define evr21 21 > +#define evr22 22 > +#define evr23 23 > +#define evr24 24 > +#define evr25 25 > +#define evr26 26 > +#define evr27 27 > +#define evr28 28 > +#define evr29 29 > +#define evr30 30 > +#define evr31 31 > + > +/* some stab codes */ > +#define N_FUN 36 > +#define N_RSYM 64 > +#define N_SLINE 68 > +#define N_SO 100 > + > +#define ASM_CONST(x) x > +#else > + #define __ASM_CONST(x) x##UL > + #define ASM_CONST(x) __ASM_CONST(x) > +#endif /* __ASSEMBLY__ */ > + > +#endif /* _ASM_POWERPC_PPC_ASM_H */ > diff --git a/include/asm-ppc/ppc_asm.h b/include/asm-ppc/ppc_asm.h > deleted file mode 100644 > --- a/include/asm-ppc/ppc_asm.h > +++ /dev/null > @@ -1,350 +0,0 @@ > -/* > - * include/asm-ppc/ppc_asm.h > - * > - * Definitions used by various bits of low-level assembly code on > PowerPC. > - * > - * Copyright (C) 1995-1999 Gary Thomas, Paul Mackerras, Cort Dougan. > - * > - * 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 > - > -/* > - * Macros for storing registers into and loading registers from > - * exception frames. > - */ > -#define SAVE_GPR(n, base) stw n,GPR0+4*(n)(base) > -#define SAVE_2GPRS(n, base) SAVE_GPR(n, base); SAVE_GPR(n+1, base) > -#define SAVE_4GPRS(n, base) SAVE_2GPRS(n, base); SAVE_2GPRS(n+2, > base) > -#define SAVE_8GPRS(n, base) SAVE_4GPRS(n, base); SAVE_4GPRS(n+4, > base) > -#define SAVE_10GPRS(n, base) SAVE_8GPRS(n, base); SAVE_2GPRS(n+8, > base) > -#define REST_GPR(n, base) lwz n,GPR0+4*(n)(base) > -#define REST_2GPRS(n, base) REST_GPR(n, base); REST_GPR(n+1, base) > -#define REST_4GPRS(n, base) REST_2GPRS(n, base); REST_2GPRS(n+2, > base) > -#define REST_8GPRS(n, base) REST_4GPRS(n, base); REST_4GPRS(n+4, > base) > -#define REST_10GPRS(n, base) REST_8GPRS(n, base); REST_2GPRS(n+8, > base) > - > -#define SAVE_NVGPRS(base) SAVE_GPR(13, base); SAVE_8GPRS(14, > base); \ > - SAVE_10GPRS(22, base) > -#define REST_NVGPRS(base) REST_GPR(13, base); REST_8GPRS(14, > base); \ > - REST_10GPRS(22, base) > - > -#define SAVE_FPR(n, base) stfd n,THREAD_FPR0+8*(n)(base) > -#define SAVE_2FPRS(n, base) SAVE_FPR(n, base); SAVE_FPR(n+1, base) > -#define SAVE_4FPRS(n, base) SAVE_2FPRS(n, base); SAVE_2FPRS(n+2, > base) > -#define SAVE_8FPRS(n, base) SAVE_4FPRS(n, base); SAVE_4FPRS(n+4, > base) > -#define SAVE_16FPRS(n, base) SAVE_8FPRS(n, base); SAVE_8FPRS(n+8, > base) > -#define SAVE_32FPRS(n, base) SAVE_16FPRS(n, base); SAVE_16FPRS(n > +16, > base) > -#define REST_FPR(n, base) lfd n,THREAD_FPR0+8*(n)(base) > -#define REST_2FPRS(n, base) REST_FPR(n, base); REST_FPR(n+1, base) > -#define REST_4FPRS(n, base) REST_2FPRS(n, base); REST_2FPRS(n+2, > base) > -#define REST_8FPRS(n, base) REST_4FPRS(n, base); REST_4FPRS(n+4, > base) > -#define REST_16FPRS(n, base) REST_8FPRS(n, base); REST_8FPRS(n+8, > base) > -#define REST_32FPRS(n, base) REST_16FPRS(n, base); REST_16FPRS(n > +16, > base) > - > -#define SAVE_VR(n,b,base) li b,THREAD_VR0+(16*(n)); stvx n,b,base > -#define SAVE_2VR(n,b,base) SAVE_VR(n,b,base); SAVE_VR(n+1,b,base) > -#define SAVE_4VR(n,b,base) SAVE_2VR(n,b,base); SAVE_2VR(n > +2,b,base) > -#define SAVE_8VR(n,b,base) SAVE_4VR(n,b,base); SAVE_4VR(n > +4,b,base) > -#define SAVE_16VR(n,b,base) SAVE_8VR(n,b,base); SAVE_8VR(n > +8,b,base) > -#define SAVE_32VR(n,b,base) SAVE_16VR(n,b,base); > SAVE_16VR(n+16,b,base) > -#define REST_VR(n,b,base) li b,THREAD_VR0+(16*(n)); lvx n,b,base > -#define REST_2VR(n,b,base) REST_VR(n,b,base); REST_VR(n+1,b,base) > -#define REST_4VR(n,b,base) REST_2VR(n,b,base); REST_2VR(n > +2,b,base) > -#define REST_8VR(n,b,base) REST_4VR(n,b,base); REST_4VR(n > +4,b,base) > -#define REST_16VR(n,b,base) REST_8VR(n,b,base); REST_8VR(n > +8,b,base) > -#define REST_32VR(n,b,base) REST_16VR(n,b,base); > REST_16VR(n+16,b,base) > - > -#define SAVE_EVR(n,s,base) evmergehi s,s,n; stw > s,THREAD_EVR0+4*(n)(base) > -#define SAVE_2EVR(n,s,base) SAVE_EVR(n,s,base); SAVE_EVR(n > +1,s,base) > -#define SAVE_4EVR(n,s,base) SAVE_2EVR(n,s,base); > SAVE_2EVR(n+2,s,base) > -#define SAVE_8EVR(n,s,base) SAVE_4EVR(n,s,base); > SAVE_4EVR(n+4,s,base) > -#define SAVE_16EVR(n,s,base) SAVE_8EVR(n,s,base); > SAVE_8EVR(n+8,s,base) > -#define SAVE_32EVR(n,s,base) SAVE_16EVR(n,s,base); > SAVE_16EVR(n+16,s,base) > - > -#define REST_EVR(n,s,base) lwz s,THREAD_EVR0+4*(n)(base); > evmergelo > n,s,n > -#define REST_2EVR(n,s,base) REST_EVR(n,s,base); REST_EVR(n > +1,s,base) > -#define REST_4EVR(n,s,base) REST_2EVR(n,s,base); > REST_2EVR(n+2,s,base) > -#define REST_8EVR(n,s,base) REST_4EVR(n,s,base); > REST_4EVR(n+4,s,base) > -#define REST_16EVR(n,s,base) REST_8EVR(n,s,base); > REST_8EVR(n+8,s,base) > -#define REST_32EVR(n,s,base) REST_16EVR(n,s,base); > REST_16EVR(n+16,s,base) > - > -#ifdef CONFIG_PPC601_SYNC_FIX > -#define SYNC \ > -BEGIN_FTR_SECTION \ > - sync; \ > - isync; \ > -END_FTR_SECTION_IFSET(CPU_FTR_601) > -#define SYNC_601 \ > -BEGIN_FTR_SECTION \ > - sync; \ > -END_FTR_SECTION_IFSET(CPU_FTR_601) > -#define ISYNC_601 \ > -BEGIN_FTR_SECTION \ > - isync; \ > -END_FTR_SECTION_IFSET(CPU_FTR_601) > -#else > -#define SYNC > -#define SYNC_601 > -#define ISYNC_601 > -#endif > - > -#ifndef CONFIG_SMP > -#define TLBSYNC > -#else /* CONFIG_SMP */ > -/* tlbsync is not implemented on 601 */ > -#define TLBSYNC \ > -BEGIN_FTR_SECTION \ > - tlbsync; \ > - sync; \ > -END_FTR_SECTION_IFCLR(CPU_FTR_601) > -#endif > - > -/* > - * This instruction is not implemented on the PPC 603 or 601; > however, > on > - * the 403GCX and 405GP tlbia IS defined and tlbie is not. > - * All of these instructions exist in the 8xx, they have magical > powers, > - * and they must be used. > - */ > - > -#if !defined(CONFIG_4xx) && !defined(CONFIG_8xx) > -#define tlbia \ > - li r4,1024; \ > - mtctr r4; \ > - lis r4,KERNELBASE at h; \ > -0: tlbie r4; \ > - addi r4,r4,0x1000; \ > - bdnz 0b > -#endif > - > -#ifdef CONFIG_BOOKE > -#define tophys(rd,rs) \ > - addis rd,rs,0 > - > -#define tovirt(rd,rs) \ > - addis rd,rs,0 > - > -#else /* CONFIG_BOOKE */ > -/* > - * On APUS (Amiga PowerPC cpu upgrade board), we don't know the > - * physical base address of RAM at compile time. > - */ > -#define tophys(rd,rs) \ > -0: addis rd,rs,-KERNELBASE at h; \ > - .section ".vtop_fixup","aw"; \ > - .align 1; \ > - .long 0b; \ > - .previous > - > -#define tovirt(rd,rs) \ > -0: addis rd,rs,KERNELBASE at h; \ > - .section ".ptov_fixup","aw"; \ > - .align 1; \ > - .long 0b; \ > - .previous > -#endif /* CONFIG_BOOKE */ > - > -/* > - * On 64-bit cpus, we use the rfid instruction instead of rfi, but > - * we then have to make sure we preserve the top 32 bits except for > - * the 64-bit mode bit, which we clear. > - */ > -#ifdef CONFIG_PPC64BRIDGE > -#define FIX_SRR1(ra, rb) \ > - mr rb,ra; \ > - mfmsr ra; \ > - clrldi ra,ra,1; /* turn off 64-bit mode */ \ > - rldimi ra,rb,0,32 > -#define RFI .long 0x4c000024 /* rfid > instruction */ > -#define MTMSRD(r) .long (0x7c000164 + ((r) << 21)) /* > mtmsrd */ > -#define CLR_TOP32(r) rlwinm (r),(r),0,0,31 /* clear top > 32 bits */ > - > -#else > -#define FIX_SRR1(ra, rb) > -#ifndef CONFIG_40x > -#define RFI rfi > -#else > -#define RFI rfi; b . /* Prevent prefetch past rfi */ > -#endif > -#define MTMSRD(r) mtmsr r > -#define CLR_TOP32(r) > -#endif /* CONFIG_PPC64BRIDGE */ > - > -#define RFCI .long 0x4c000066 /* rfci instruction */ > -#define RFDI .long 0x4c00004e /* rfdi instruction */ > -#define RFMCI .long 0x4c00004c /* rfmci instruction */ > - > -#ifdef CONFIG_IBM405_ERR77 > -#define PPC405_ERR77(ra,rb) dcbt ra, rb; > -#define PPC405_ERR77_SYNC sync; > -#else > -#define PPC405_ERR77(ra,rb) > -#define PPC405_ERR77_SYNC > -#endif > - > -#ifdef CONFIG_IBM440EP_ERR42 > -#define PPC440EP_ERR42 isync > -#else > -#define PPC440EP_ERR42 > -#endif > - > -/* The boring bits... */ > - > -/* Condition Register Bit Fields */ > - > -#define cr0 0 > -#define cr1 1 > -#define cr2 2 > -#define cr3 3 > -#define cr4 4 > -#define cr5 5 > -#define cr6 6 > -#define cr7 7 > - > - > -/* General Purpose Registers (GPRs) */ > - > -#define r0 0 > -#define r1 1 > -#define r2 2 > -#define r3 3 > -#define r4 4 > -#define r5 5 > -#define r6 6 > -#define r7 7 > -#define r8 8 > -#define r9 9 > -#define r10 10 > -#define r11 11 > -#define r12 12 > -#define r13 13 > -#define r14 14 > -#define r15 15 > -#define r16 16 > -#define r17 17 > -#define r18 18 > -#define r19 19 > -#define r20 20 > -#define r21 21 > -#define r22 22 > -#define r23 23 > -#define r24 24 > -#define r25 25 > -#define r26 26 > -#define r27 27 > -#define r28 28 > -#define r29 29 > -#define r30 30 > -#define r31 31 > - > - > -/* Floating Point Registers (FPRs) */ > - > -#define fr0 0 > -#define fr1 1 > -#define fr2 2 > -#define fr3 3 > -#define fr4 4 > -#define fr5 5 > -#define fr6 6 > -#define fr7 7 > -#define fr8 8 > -#define fr9 9 > -#define fr10 10 > -#define fr11 11 > -#define fr12 12 > -#define fr13 13 > -#define fr14 14 > -#define fr15 15 > -#define fr16 16 > -#define fr17 17 > -#define fr18 18 > -#define fr19 19 > -#define fr20 20 > -#define fr21 21 > -#define fr22 22 > -#define fr23 23 > -#define fr24 24 > -#define fr25 25 > -#define fr26 26 > -#define fr27 27 > -#define fr28 28 > -#define fr29 29 > -#define fr30 30 > -#define fr31 31 > - > -#define vr0 0 > -#define vr1 1 > -#define vr2 2 > -#define vr3 3 > -#define vr4 4 > -#define vr5 5 > -#define vr6 6 > -#define vr7 7 > -#define vr8 8 > -#define vr9 9 > -#define vr10 10 > -#define vr11 11 > -#define vr12 12 > -#define vr13 13 > -#define vr14 14 > -#define vr15 15 > -#define vr16 16 > -#define vr17 17 > -#define vr18 18 > -#define vr19 19 > -#define vr20 20 > -#define vr21 21 > -#define vr22 22 > -#define vr23 23 > -#define vr24 24 > -#define vr25 25 > -#define vr26 26 > -#define vr27 27 > -#define vr28 28 > -#define vr29 29 > -#define vr30 30 > -#define vr31 31 > - > -#define evr0 0 > -#define evr1 1 > -#define evr2 2 > -#define evr3 3 > -#define evr4 4 > -#define evr5 5 > -#define evr6 6 > -#define evr7 7 > -#define evr8 8 > -#define evr9 9 > -#define evr10 10 > -#define evr11 11 > -#define evr12 12 > -#define evr13 13 > -#define evr14 14 > -#define evr15 15 > -#define evr16 16 > -#define evr17 17 > -#define evr18 18 > -#define evr19 19 > -#define evr20 20 > -#define evr21 21 > -#define evr22 22 > -#define evr23 23 > -#define evr24 24 > -#define evr25 25 > -#define evr26 26 > -#define evr27 27 > -#define evr28 28 > -#define evr29 29 > -#define evr30 30 > -#define evr31 31 > - > -/* some stab codes */ > -#define N_FUN 36 > -#define N_RSYM 64 > -#define N_SLINE 68 > -#define N_SO 100 > diff --git a/include/asm-ppc64/cputable.h b/include/asm-ppc64/ > cputable.h > --- a/include/asm-ppc64/cputable.h > +++ b/include/asm-ppc64/cputable.h > @@ -16,7 +16,7 @@ > #define __ASM_PPC_CPUTABLE_H > > #include > -#include /* for ASM_CONST */ > +#include /* for ASM_CONST */ > > /* Exposed to userland CPU features - Must match ppc32 definitions */ > #define PPC_FEATURE_32 0x80000000 > diff --git a/include/asm-ppc64/mmu.h b/include/asm-ppc64/mmu.h > --- a/include/asm-ppc64/mmu.h > +++ b/include/asm-ppc64/mmu.h > @@ -14,6 +14,7 @@ > #define _PPC64_MMU_H_ > > #include > +#include /* for ASM_CONST */ > #include > > /* > diff --git a/include/asm-ppc64/page.h b/include/asm-ppc64/page.h > --- a/include/asm-ppc64/page.h > +++ b/include/asm-ppc64/page.h > @@ -11,13 +11,7 @@ > */ > > #include > - > -#ifdef __ASSEMBLY__ > - #define ASM_CONST(x) x > -#else > - #define __ASM_CONST(x) x##UL > - #define ASM_CONST(x) __ASM_CONST(x) > -#endif > +#include /* for ASM_CONST */ > > /* PAGE_SHIFT determines the page size */ > #define PAGE_SHIFT 12 > diff --git a/include/asm-ppc64/ppc_asm.h b/include/asm-ppc64/ppc_asm.h > deleted file mode 100644 > --- a/include/asm-ppc64/ppc_asm.h > +++ /dev/null > @@ -1,242 +0,0 @@ > -/* > - * arch/ppc64/kernel/ppc_asm.h > - * > - * Definitions used by various bits of low-level assembly code on > PowerPC. > - * > - * Copyright (C) 1995-1999 Gary Thomas, Paul Mackerras, Cort Dougan. > - * > - * 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 _PPC64_PPC_ASM_H > -#define _PPC64_PPC_ASM_H > -/* > - * Macros for storing registers into and loading registers from > - * exception frames. > - */ > -#define SAVE_GPR(n, base) std n,GPR0+8*(n)(base) > -#define SAVE_2GPRS(n, base) SAVE_GPR(n, base); SAVE_GPR(n+1, base) > -#define SAVE_4GPRS(n, base) SAVE_2GPRS(n, base); SAVE_2GPRS(n+2, > base) > -#define SAVE_8GPRS(n, base) SAVE_4GPRS(n, base); SAVE_4GPRS(n+4, > base) > -#define SAVE_10GPRS(n, base) SAVE_8GPRS(n, base); SAVE_2GPRS(n+8, > base) > -#define REST_GPR(n, base) ld n,GPR0+8*(n)(base) > -#define REST_2GPRS(n, base) REST_GPR(n, base); REST_GPR(n+1, base) > -#define REST_4GPRS(n, base) REST_2GPRS(n, base); REST_2GPRS(n+2, > base) > -#define REST_8GPRS(n, base) REST_4GPRS(n, base); REST_4GPRS(n+4, > base) > -#define REST_10GPRS(n, base) REST_8GPRS(n, base); REST_2GPRS(n+8, > base) > - > -#define SAVE_NVGPRS(base) SAVE_8GPRS(14, base); SAVE_10GPRS(22, > base) > -#define REST_NVGPRS(base) REST_8GPRS(14, base); REST_10GPRS(22, > base) > - > -#define SAVE_FPR(n, base) stfd n,THREAD_FPR0+8*(n)(base) > -#define SAVE_2FPRS(n, base) SAVE_FPR(n, base); SAVE_FPR(n+1, base) > -#define SAVE_4FPRS(n, base) SAVE_2FPRS(n, base); SAVE_2FPRS(n+2, > base) > -#define SAVE_8FPRS(n, base) SAVE_4FPRS(n, base); SAVE_4FPRS(n+4, > base) > -#define SAVE_16FPRS(n, base) SAVE_8FPRS(n, base); SAVE_8FPRS(n+8, > base) > -#define SAVE_32FPRS(n, base) SAVE_16FPRS(n, base); SAVE_16FPRS(n > +16, > base) > -#define REST_FPR(n, base) lfd n,THREAD_FPR0+8*(n)(base) > -#define REST_2FPRS(n, base) REST_FPR(n, base); REST_FPR(n+1, base) > -#define REST_4FPRS(n, base) REST_2FPRS(n, base); REST_2FPRS(n+2, > base) > -#define REST_8FPRS(n, base) REST_4FPRS(n, base); REST_4FPRS(n+4, > base) > -#define REST_16FPRS(n, base) REST_8FPRS(n, base); REST_8FPRS(n+8, > base) > -#define REST_32FPRS(n, base) REST_16FPRS(n, base); REST_16FPRS(n > +16, > base) > - > -#define SAVE_VR(n,b,base) li b,THREAD_VR0+(16*(n)); stvx n,b,base > -#define SAVE_2VRS(n,b,base) SAVE_VR(n,b,base); SAVE_VR(n+1,b,base) > -#define SAVE_4VRS(n,b,base) SAVE_2VRS(n,b,base); > SAVE_2VRS(n+2,b,base) > -#define SAVE_8VRS(n,b,base) SAVE_4VRS(n,b,base); > SAVE_4VRS(n+4,b,base) > -#define SAVE_16VRS(n,b,base) SAVE_8VRS(n,b,base); > SAVE_8VRS(n+8,b,base) > -#define SAVE_32VRS(n,b,base) SAVE_16VRS(n,b,base); > SAVE_16VRS(n+16,b,base) > -#define REST_VR(n,b,base) li b,THREAD_VR0+(16*(n)); lvx n,b,base > -#define REST_2VRS(n,b,base) REST_VR(n,b,base); REST_VR(n+1,b,base) > -#define REST_4VRS(n,b,base) REST_2VRS(n,b,base); > REST_2VRS(n+2,b,base) > -#define REST_8VRS(n,b,base) REST_4VRS(n,b,base); > REST_4VRS(n+4,b,base) > -#define REST_16VRS(n,b,base) REST_8VRS(n,b,base); > REST_8VRS(n+8,b,base) > -#define REST_32VRS(n,b,base) REST_16VRS(n,b,base); > REST_16VRS(n+16,b,base) > - > -/* Macros to adjust thread priority for Iseries hardware > multithreading > */ > -#define HMT_LOW or 1,1,1 > -#define HMT_MEDIUM or 2,2,2 > -#define HMT_HIGH or 3,3,3 > - > -/* Insert the high 32 bits of the MSR into what will be the new > - MSR (via SRR1 and rfid) This preserves the MSR.SF and MSR.ISF > - bits. */ > - > -#define FIX_SRR1(ra, rb) \ > - mr rb,ra; \ > - mfmsr ra; \ > - rldimi ra,rb,0,32 > - > -#define CLR_TOP32(r) rlwinm (r),(r),0,0,31 /* clear top > 32 bits */ > - > -/* > - * LOADADDR( rn, name ) > - * loads the address of 'name' into 'rn' > - * > - * LOADBASE( rn, name ) > - * loads the address (less the low 16 bits) of 'name' into 'rn' > - * suitable for base+disp addressing > - */ > -#define LOADADDR(rn,name) \ > - lis rn,name##@highest; \ > - ori rn,rn,name##@higher; \ > - rldicr rn,rn,32,31; \ > - oris rn,rn,name##@h; \ > - ori rn,rn,name##@l > - > -#define LOADBASE(rn,name) \ > - lis rn,name at highest; \ > - ori rn,rn,name at higher; \ > - rldicr rn,rn,32,31; \ > - oris rn,rn,name at ha > - > - > -#define SET_REG_TO_CONST(reg, value) \ > - lis reg,(((value)>>48)&0xFFFF); \ > - ori reg,reg,(((value)>>32)&0xFFFF); \ > - rldicr reg,reg,32,31; \ > - oris reg,reg,(((value)>>16)&0xFFFF); \ > - ori reg,reg,((value)&0xFFFF); > - > -#define SET_REG_TO_LABEL(reg, label) \ > - lis reg,(label)@highest; \ > - ori reg,reg,(label)@higher; \ > - rldicr reg,reg,32,31; \ > - oris reg,reg,(label)@h; \ > - ori reg,reg,(label)@l; > - > - > -/* PPPBBB - DRENG If KERNELBASE is always 0xC0..., > - * Then we can easily do this with one asm insn. -Peter > - */ > -#define tophys(rd,rs) \ > - lis rd,((KERNELBASE>>48)&0xFFFF); \ > - rldicr rd,rd,32,31; \ > - sub rd,rs,rd > - > -#define tovirt(rd,rs) \ > - lis rd,((KERNELBASE>>48)&0xFFFF); \ > - rldicr rd,rd,32,31; \ > - add rd,rs,rd > - > -/* Condition Register Bit Fields */ > - > -#define cr0 0 > -#define cr1 1 > -#define cr2 2 > -#define cr3 3 > -#define cr4 4 > -#define cr5 5 > -#define cr6 6 > -#define cr7 7 > - > - > -/* General Purpose Registers (GPRs) */ > - > -#define r0 0 > -#define r1 1 > -#define r2 2 > -#define r3 3 > -#define r4 4 > -#define r5 5 > -#define r6 6 > -#define r7 7 > -#define r8 8 > -#define r9 9 > -#define r10 10 > -#define r11 11 > -#define r12 12 > -#define r13 13 > -#define r14 14 > -#define r15 15 > -#define r16 16 > -#define r17 17 > -#define r18 18 > -#define r19 19 > -#define r20 20 > -#define r21 21 > -#define r22 22 > -#define r23 23 > -#define r24 24 > -#define r25 25 > -#define r26 26 > -#define r27 27 > -#define r28 28 > -#define r29 29 > -#define r30 30 > -#define r31 31 > - > - > -/* Floating Point Registers (FPRs) */ > - > -#define fr0 0 > -#define fr1 1 > -#define fr2 2 > -#define fr3 3 > -#define fr4 4 > -#define fr5 5 > -#define fr6 6 > -#define fr7 7 > -#define fr8 8 > -#define fr9 9 > -#define fr10 10 > -#define fr11 11 > -#define fr12 12 > -#define fr13 13 > -#define fr14 14 > -#define fr15 15 > -#define fr16 16 > -#define fr17 17 > -#define fr18 18 > -#define fr19 19 > -#define fr20 20 > -#define fr21 21 > -#define fr22 22 > -#define fr23 23 > -#define fr24 24 > -#define fr25 25 > -#define fr26 26 > -#define fr27 27 > -#define fr28 28 > -#define fr29 29 > -#define fr30 30 > -#define fr31 31 > - > -#define vr0 0 > -#define vr1 1 > -#define vr2 2 > -#define vr3 3 > -#define vr4 4 > -#define vr5 5 > -#define vr6 6 > -#define vr7 7 > -#define vr8 8 > -#define vr9 9 > -#define vr10 10 > -#define vr11 11 > -#define vr12 12 > -#define vr13 13 > -#define vr14 14 > -#define vr15 15 > -#define vr16 16 > -#define vr17 17 > -#define vr18 18 > -#define vr19 19 > -#define vr20 20 > -#define vr21 21 > -#define vr22 22 > -#define vr23 23 > -#define vr24 24 > -#define vr25 25 > -#define vr26 26 > -#define vr27 27 > -#define vr28 28 > -#define vr29 29 > -#define vr30 30 > -#define vr31 31 > - > -#endif /* _PPC64_PPC_ASM_H */ > _______________________________________________ > Linuxppc64-dev mailing list > Linuxppc64-dev at ozlabs.org > https://ozlabs.org/mailman/listinfo/linuxppc64-dev > From kumar.gala at freescale.com Thu Sep 15 05:11:22 2005 From: kumar.gala at freescale.com (Kumar Gala) Date: Wed, 14 Sep 2005 14:11:22 -0500 Subject: [PATCH] powerpc: merge include/asm/cputable.h In-Reply-To: <200509090623.41889.arnd@arndb.de> References: <200509090623.41889.arnd@arndb.de> Message-ID: <06F93AF6-7AF8-4320-B9E3-CBF9EA333403@freescale.com> Arnd, I not sure I understand what the introduction of the enum's gets us. - kumar On Sep 8, 2005, at 11:23 PM, Arnd Bergmann wrote: > This is an updated version of my old patch that creates a more > optimized > version of cpu_has_feature(). This version actually combines > asm-ppc/cputable.h and asm-ppc64/cputable.h, which turned out to be > a lot more work than only the 64 bit version. > > The 64 bit parts a relatively straightforward port of my earlier work > which I tested in a number of configurations. The 32 bit parts are > not tested at all, all I did was compiling the ppc defconfig with > this. > > I think it is best if I hand the patch over to Kumar and Becky for > further testing and cleaning up the remaining bits in the new > file, as they appear to have invested some thought in it already. > This version still has a number of #ifdef __powerpc64__ that should > probably go away in the process. > > The patch also relies on having the ASM_CONST() macro in ppc_asm.h, > as proposed by Kumar Gala, so it won't work on the current git > head without that change. > > Signed-off-by: Arnd Bergmann > > -- > > clean-cg/arch/ppc/kernel/cputable.c | 401 ++++ > +---------------------- > clean-cg/arch/ppc64/Kconfig | 30 ++ > clean-cg/arch/ppc64/kernel/cputable.c | 82 +---- > clean-cg/include/asm-powerpc/cputable.h | 475 ++++++++++++++++++++ > ++++++++++++ > include/asm-ppc/cputable.h | 128 -------- > include/asm-ppc64/cputable.h | 167 ----------- > > Index: clean-cg/include/asm-ppc64/cputable.h > =================================================================== > --- clean-cg.orig/include/asm-ppc64/cputable.h > +++ /dev/null > @@ -1,167 +0,0 @@ > -/* > - * include/asm-ppc64/cputable.h > - * > - * Copyright (C) 2001 Ben. Herrenschmidt (benh at kernel.crashing.org) > - * > - * Modifications for ppc64: > - * Copyright (C) 2003 Dave Engebretsen > - * > - * 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_PPC_CPUTABLE_H > -#define __ASM_PPC_CPUTABLE_H > - > -#include > -#include /* for ASM_CONST */ > - > -/* Exposed to userland CPU features - Must match ppc32 definitions */ > -#define PPC_FEATURE_32 0x80000000 > -#define PPC_FEATURE_64 0x40000000 > -#define PPC_FEATURE_601_INSTR 0x20000000 > -#define PPC_FEATURE_HAS_ALTIVEC 0x10000000 > -#define PPC_FEATURE_HAS_FPU 0x08000000 > -#define PPC_FEATURE_HAS_MMU 0x04000000 > -#define PPC_FEATURE_HAS_4xxMAC 0x02000000 > -#define PPC_FEATURE_UNIFIED_CACHE 0x01000000 > - > -#ifdef __KERNEL__ > - > -#ifndef __ASSEMBLY__ > - > -/* This structure can grow, it's real size is used by head.S code > - * via the mkdefs mechanism. > - */ > -struct cpu_spec; > -struct op_ppc64_model; > - > -typedef void (*cpu_setup_t)(unsigned long offset, struct > cpu_spec* spec); > - > -struct cpu_spec { > - /* CPU is matched via (PVR & pvr_mask) == pvr_value */ > - unsigned int pvr_mask; > - unsigned int pvr_value; > - > - char *cpu_name; > - unsigned long cpu_features; /* Kernel features */ > - unsigned int cpu_user_features; /* Userland features */ > - > - /* cache line sizes */ > - 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 > - */ > - cpu_setup_t cpu_setup; > - > - /* 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[]; > -extern struct cpu_spec *cur_cpu_spec; > - > -static inline unsigned long cpu_has_feature(unsigned long feature) > -{ > - return cur_cpu_spec->cpu_features & feature; > -} > - > -#endif /* __ASSEMBLY__ */ > - > -/* CPU kernel features */ > - > -/* Retain the 32b definitions for the time being - use bottom half > of word */ > -#define CPU_FTR_SPLIT_ID_CACHE ASM_CONST(0x0000000000000001) > -#define CPU_FTR_L2CR ASM_CONST(0x0000000000000002) > -#define CPU_FTR_SPEC7450 ASM_CONST(0x0000000000000004) > -#define CPU_FTR_ALTIVEC ASM_CONST(0x0000000000000008) > -#define CPU_FTR_TAU ASM_CONST(0x0000000000000010) > -#define CPU_FTR_CAN_DOZE ASM_CONST(0x0000000000000020) > -#define CPU_FTR_USE_TB ASM_CONST(0x0000000000000040) > -#define CPU_FTR_604_PERF_MON ASM_CONST(0x0000000000000080) > -#define CPU_FTR_601 ASM_CONST(0x0000000000000100) > -#define CPU_FTR_HPTE_TABLE ASM_CONST(0x0000000000000200) > -#define CPU_FTR_CAN_NAP ASM_CONST(0x0000000000000400) > -#define CPU_FTR_L3CR ASM_CONST(0x0000000000000800) > -#define CPU_FTR_L3_DISABLE_NAP ASM_CONST(0x0000000000001000) > -#define CPU_FTR_NAP_DISABLE_L2_PR ASM_CONST(0x0000000000002000) > -#define CPU_FTR_DUAL_PLL_750FX ASM_CONST(0x0000000000004000) > - > -/* Add the 64b processor unique features in the top half of the > word */ > -#define CPU_FTR_SLB ASM_CONST(0x0000000100000000) > -#define CPU_FTR_16M_PAGE ASM_CONST(0x0000000200000000) > -#define CPU_FTR_TLBIEL ASM_CONST(0x0000000400000000) > -#define CPU_FTR_NOEXECUTE ASM_CONST(0x0000000800000000) > -#define CPU_FTR_NODSISRALIGN ASM_CONST(0x0000001000000000) > -#define CPU_FTR_IABR ASM_CONST(0x0000002000000000) > -#define CPU_FTR_MMCRA ASM_CONST(0x0000004000000000) > -/* 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) > -#define CPU_FTR_MMCRA_SIHV ASM_CONST(0x0000080000000000) > -#define CPU_FTR_CTRL ASM_CONST(0x0000100000000000) > - > -#ifndef __ASSEMBLY__ > - > -#define COMMON_USER_PPC64 (PPC_FEATURE_32 | PPC_FEATURE_64 | \ > - PPC_FEATURE_HAS_FPU | PPC_FEATURE_HAS_MMU) > - > -#define CPU_FTR_PPCAS_ARCH_V2_BASE (CPU_FTR_SLB | \ > - CPU_FTR_TLBIEL | > CPU_FTR_NOEXECUTE | \ > - CPU_FTR_NODSISRALIGN | CPU_FTR_CTRL) > - > -/* iSeries doesn't support large pages */ > -#ifdef CONFIG_PPC_ISERIES > -#define CPU_FTR_PPCAS_ARCH_V2 (CPU_FTR_PPCAS_ARCH_V2_BASE) > -#else > -#define CPU_FTR_PPCAS_ARCH_V2 (CPU_FTR_PPCAS_ARCH_V2_BASE | > CPU_FTR_16M_PAGE) > -#endif /* CONFIG_PPC_ISERIES */ > - > -#endif /* __ASSEMBLY */ > - > -#ifdef __ASSEMBLY__ > - > -#define BEGIN_FTR_SECTION 98: > - > -#define END_FTR_SECTION(msk, val) \ > -99: \ > - .section __ftr_fixup,"a"; \ > - .align 3; \ > - .llong msk; \ > - .llong val; \ > - .llong 98b; \ > - .llong 99b; \ > - .previous > - > -#else > - > -#define BEGIN_FTR_SECTION "98:\n" > -#define END_FTR_SECTION(msk, val) \ > -"99:\n" \ > -" .section __ftr_fixup,\"a\";\n" \ > -" .align 3;\n" \ > -" .llong "#msk";\n" \ > -" .llong "#val";\n" \ > -" .llong 98b;\n" \ > -" .llong 99b;\n" \ > -" .previous\n" > - > -#endif /* __ASSEMBLY__ */ > - > -#define END_FTR_SECTION_IFSET(msk) END_FTR_SECTION((msk), (msk)) > -#define END_FTR_SECTION_IFCLR(msk) END_FTR_SECTION((msk), 0) > - > -#endif /* __ASM_PPC_CPUTABLE_H */ > -#endif /* __KERNEL__ */ > - > Index: clean-cg/arch/ppc64/Kconfig > =================================================================== > --- clean-cg.orig/arch/ppc64/Kconfig > +++ clean-cg/arch/ppc64/Kconfig > @@ -125,6 +125,36 @@ config BPA_IIC > bool > default y > > +config CPU_POWER3 > + bool > + default y > + depends on (PPC_ISERIES || PPC_PSERIES) && !POWER4_ONLY > + > +config CPU_RS64 > + bool > + default y > + depends on (PPC_ISERIES || PPC_PSERIES) && !POWER4_ONLY > + > +config CPU_POWER4 > + bool > + default y > + depends on PPC_ISERIES || PPC_PSERIES > + > +config CPU_PPC970 > + bool > + default y > + depends on PPC_PSERIES || PPC_PMAC || PPC_MAPLE > + > +config CPU_POWER5 > + bool > + default y > + depends on PPC_PSERIES > + > +config CPU_CELL > + bool > + default y > + depends on PPC_BPA > + > # VMX is pSeries only for now until somebody writes the iSeries > # exception vectors for it > config ALTIVEC > Index: clean-cg/arch/ppc64/kernel/cputable.c > =================================================================== > --- clean-cg.orig/arch/ppc64/kernel/cputable.c > +++ clean-cg/arch/ppc64/kernel/cputable.c > @@ -37,26 +37,13 @@ extern void __setup_cpu_power4(unsigned > extern void __setup_cpu_ppc970(unsigned long offset, struct > cpu_spec* spec); > extern void __setup_cpu_be(unsigned long offset, struct cpu_spec* > spec); > > - > -/* We only set the altivec features if the kernel was compiled > with altivec > - * support > - */ > -#ifdef CONFIG_ALTIVEC > -#define CPU_FTR_ALTIVEC_COMP CPU_FTR_ALTIVEC > -#define PPC_FEATURE_HAS_ALTIVEC_COMP PPC_FEATURE_HAS_ALTIVEC > -#else > -#define CPU_FTR_ALTIVEC_COMP 0 > -#define PPC_FEATURE_HAS_ALTIVEC_COMP 0 > -#endif > - > struct cpu_spec cpu_specs[] = { > { /* Power3 */ > .pvr_mask = 0xffff0000, > .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_user_features = COMMON_USER_PPC64, > + .cpu_features = CPU_FTR_POWER3, > + .cpu_user_features = COMMON_USER_PPC64, > .icache_bsize = 128, > .dcache_bsize = 128, > .num_pmcs = 8, > @@ -70,8 +57,7 @@ struct cpu_spec cpu_specs[] = { > .pvr_mask = 0xffff0000, > .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_features = CPU_FTR_POWER3, > .cpu_user_features = COMMON_USER_PPC64, > .icache_bsize = 128, > .dcache_bsize = 128, > @@ -86,9 +72,7 @@ struct cpu_spec cpu_specs[] = { > .pvr_mask = 0xffff0000, > .pvr_value = 0x00330000, > .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_MMCRA | CPU_FTR_CTRL, > + .cpu_features = CPU_FTR_RS64, > .cpu_user_features = COMMON_USER_PPC64, > .icache_bsize = 128, > .dcache_bsize = 128, > @@ -103,9 +87,7 @@ struct cpu_spec cpu_specs[] = { > .pvr_mask = 0xffff0000, > .pvr_value = 0x00340000, > .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_MMCRA | CPU_FTR_CTRL, > + .cpu_features = CPU_FTR_RS64, > .cpu_user_features = COMMON_USER_PPC64, > .icache_bsize = 128, > .dcache_bsize = 128, > @@ -120,9 +102,7 @@ struct cpu_spec cpu_specs[] = { > .pvr_mask = 0xffff0000, > .pvr_value = 0x00360000, > .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_MMCRA | CPU_FTR_CTRL, > + .cpu_features = CPU_FTR_RS64, > .cpu_user_features = COMMON_USER_PPC64, > .icache_bsize = 128, > .dcache_bsize = 128, > @@ -137,9 +117,7 @@ struct cpu_spec cpu_specs[] = { > .pvr_mask = 0xffff0000, > .pvr_value = 0x00370000, > .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_MMCRA | CPU_FTR_CTRL, > + .cpu_features = CPU_FTR_RS64, > .cpu_user_features = COMMON_USER_PPC64, > .icache_bsize = 128, > .dcache_bsize = 128, > @@ -154,9 +132,7 @@ struct cpu_spec cpu_specs[] = { > .pvr_mask = 0xffff0000, > .pvr_value = 0x00350000, > .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_MMCRA, > + .cpu_features = CPU_FTR_POWER4, > .cpu_user_features = COMMON_USER_PPC64, > .icache_bsize = 128, > .dcache_bsize = 128, > @@ -171,9 +147,7 @@ struct cpu_spec cpu_specs[] = { > .pvr_mask = 0xffff0000, > .pvr_value = 0x00380000, > .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_MMCRA, > + .cpu_features = CPU_FTR_POWER4, > .cpu_user_features = COMMON_USER_PPC64, > .icache_bsize = 128, > .dcache_bsize = 128, > @@ -188,10 +162,7 @@ struct cpu_spec cpu_specs[] = { > .pvr_mask = 0xffff0000, > .pvr_value = 0x00390000, > .cpu_name = "PPC970", > - .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_MMCRA, > + .cpu_features = CPU_FTR_PPC970, > .cpu_user_features = COMMON_USER_PPC64 | > PPC_FEATURE_HAS_ALTIVEC_COMP, > .icache_bsize = 128, > @@ -207,10 +178,7 @@ struct cpu_spec cpu_specs[] = { > .pvr_mask = 0xffff0000, > .pvr_value = 0x003c0000, > .cpu_name = "PPC970FX", > - .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_MMCRA, > + .cpu_features = CPU_FTR_PPC970, > .cpu_user_features = COMMON_USER_PPC64 | > PPC_FEATURE_HAS_ALTIVEC_COMP, > .icache_bsize = 128, > @@ -226,10 +194,7 @@ struct cpu_spec cpu_specs[] = { > .pvr_mask = 0xffff0000, > .pvr_value = 0x00440000, > .cpu_name = "PPC970MP", > - .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_MMCRA, > + .cpu_features = CPU_FTR_PPC970, > .cpu_user_features = COMMON_USER_PPC64 | > PPC_FEATURE_HAS_ALTIVEC_COMP, > .icache_bsize = 128, > @@ -244,11 +209,7 @@ struct cpu_spec cpu_specs[] = { > .pvr_mask = 0xffff0000, > .pvr_value = 0x003a0000, > .cpu_name = "POWER5 (gr)", > - .cpu_features = CPU_FTR_SPLIT_ID_CACHE | > - CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE | > - CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_MMCRA | CPU_FTR_SMT | > - CPU_FTR_COHERENT_ICACHE | CPU_FTR_LOCKLESS_TLBIE | > - CPU_FTR_MMCRA_SIHV, > + .cpu_features = CPU_FTR_POWER5, > .cpu_user_features = COMMON_USER_PPC64, > .icache_bsize = 128, > .dcache_bsize = 128, > @@ -263,11 +224,7 @@ struct cpu_spec cpu_specs[] = { > .pvr_mask = 0xffff0000, > .pvr_value = 0x003b0000, > .cpu_name = "POWER5 (gs)", > - .cpu_features = CPU_FTR_SPLIT_ID_CACHE | > - CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE | > - CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_MMCRA | CPU_FTR_SMT | > - CPU_FTR_COHERENT_ICACHE | CPU_FTR_LOCKLESS_TLBIE | > - CPU_FTR_MMCRA_SIHV, > + .cpu_features = CPU_FTR_POWER5, > .cpu_user_features = COMMON_USER_PPC64, > .icache_bsize = 128, > .dcache_bsize = 128, > @@ -281,11 +238,8 @@ struct cpu_spec cpu_specs[] = { > { /* BE DD1.x */ > .pvr_mask = 0xffff0000, > .pvr_value = 0x00700000, > - .cpu_name = "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 | > - CPU_FTR_SMT, > + .cpu_name = "Cell Broadband Engine", > + .cpu_features = CPU_FTR_CELL, > .cpu_user_features = COMMON_USER_PPC64 | > PPC_FEATURE_HAS_ALTIVEC_COMP, > .icache_bsize = 128, > @@ -296,9 +250,7 @@ struct cpu_spec cpu_specs[] = { > .pvr_mask = 0x00000000, > .pvr_value = 0x00000000, > .cpu_name = "POWER4 (compatible)", > - .cpu_features = CPU_FTR_SPLIT_ID_CACHE | > - CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE | > - CPU_FTR_PPCAS_ARCH_V2, > + .cpu_features = CPU_FTR_COMPATIBLE, > .cpu_user_features = COMMON_USER_PPC64, > .icache_bsize = 128, > .dcache_bsize = 128, > Index: clean-cg/arch/ppc/kernel/cputable.c > =================================================================== > --- clean-cg.orig/arch/ppc/kernel/cputable.c > +++ clean-cg/arch/ppc/kernel/cputable.c > @@ -42,17 +42,6 @@ extern void __setup_cpu_generic(unsigned > #define COMMON_PPC (PPC_FEATURE_32 | PPC_FEATURE_HAS_FPU | \ > PPC_FEATURE_HAS_MMU) > > -/* We only set the altivec features if the kernel was compiled > with altivec > - * support > - */ > -#ifdef CONFIG_ALTIVEC > -#define CPU_FTR_ALTIVEC_COMP CPU_FTR_ALTIVEC > -#define PPC_FEATURE_ALTIVEC_COMP PPC_FEATURE_HAS_ALTIVEC > -#else > -#define CPU_FTR_ALTIVEC_COMP 0 > -#define PPC_FEATURE_ALTIVEC_COMP 0 > -#endif > - > /* We only set the spe features if the kernel was compiled with > * spe support > */ > @@ -62,34 +51,13 @@ extern void __setup_cpu_generic(unsigned > #define PPC_FEATURE_SPE_COMP 0 > #endif > > -/* We need to mark all pages as being coherent if we're SMP or we > - * have a 74[45]x and an MPC107 host bridge. > - */ > -#if defined(CONFIG_SMP) || defined(CONFIG_MPC10X_BRIDGE) > -#define CPU_FTR_COMMON CPU_FTR_NEED_COHERENT > -#else > -#define CPU_FTR_COMMON 0 > -#endif > - > -/* The powersave features NAP & DOZE seems to confuse BDI when > - debugging. So if a BDI is used, disable theses > - */ > -#ifndef CONFIG_BDI_SWITCH > -#define CPU_FTR_MAYBE_CAN_DOZE CPU_FTR_CAN_DOZE > -#define CPU_FTR_MAYBE_CAN_NAP CPU_FTR_CAN_NAP > -#else > -#define CPU_FTR_MAYBE_CAN_DOZE 0 > -#define CPU_FTR_MAYBE_CAN_NAP 0 > -#endif > - > struct cpu_spec cpu_specs[] = { > #if CLASSIC_PPC > { /* 601 */ > .pvr_mask = 0xffff0000, > .pvr_value = 0x00010000, > .cpu_name = "601", > - .cpu_features = CPU_FTR_COMMON | CPU_FTR_601 | > - CPU_FTR_HPTE_TABLE, > + .cpu_features = CPU_FTR_PPC601, > .cpu_user_features = COMMON_PPC | PPC_FEATURE_601_INSTR | > PPC_FEATURE_UNIFIED_CACHE, > .icache_bsize = 32, > @@ -100,9 +68,7 @@ struct cpu_spec cpu_specs[] = { > .pvr_mask = 0xffff0000, > .pvr_value = 0x00030000, > .cpu_name = "603", > - .cpu_features = CPU_FTR_COMMON | > - CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_MAYBE_CAN_DOZE | > - CPU_FTR_USE_TB | CPU_FTR_MAYBE_CAN_NAP, > + .cpu_features = CPU_FTR_603, > .cpu_user_features = COMMON_PPC, > .icache_bsize = 32, > .dcache_bsize = 32, > @@ -112,9 +78,7 @@ struct cpu_spec cpu_specs[] = { > .pvr_mask = 0xffff0000, > .pvr_value = 0x00060000, > .cpu_name = "603e", > - .cpu_features = CPU_FTR_COMMON | > - CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_MAYBE_CAN_DOZE | > - CPU_FTR_USE_TB | CPU_FTR_MAYBE_CAN_NAP, > + .cpu_features = CPU_FTR_603, > .cpu_user_features = COMMON_PPC, > .icache_bsize = 32, > .dcache_bsize = 32, > @@ -124,9 +88,7 @@ struct cpu_spec cpu_specs[] = { > .pvr_mask = 0xffff0000, > .pvr_value = 0x00070000, > .cpu_name = "603ev", > - .cpu_features = CPU_FTR_COMMON | > - CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_MAYBE_CAN_DOZE | > - CPU_FTR_USE_TB | CPU_FTR_MAYBE_CAN_NAP, > + .cpu_features = CPU_FTR_603, > .cpu_user_features = COMMON_PPC, > .icache_bsize = 32, > .dcache_bsize = 32, > @@ -136,9 +98,7 @@ struct cpu_spec cpu_specs[] = { > .pvr_mask = 0xffff0000, > .pvr_value = 0x00040000, > .cpu_name = "604", > - .cpu_features = CPU_FTR_COMMON | > - CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | > - CPU_FTR_604_PERF_MON | CPU_FTR_HPTE_TABLE, > + .cpu_features = CPU_FTR_604, > .cpu_user_features = COMMON_PPC, > .icache_bsize = 32, > .dcache_bsize = 32, > @@ -149,9 +109,7 @@ struct cpu_spec cpu_specs[] = { > .pvr_mask = 0xfffff000, > .pvr_value = 0x00090000, > .cpu_name = "604e", > - .cpu_features = CPU_FTR_COMMON | > - CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | > - CPU_FTR_604_PERF_MON | CPU_FTR_HPTE_TABLE, > + .cpu_features = CPU_FTR_604, > .cpu_user_features = COMMON_PPC, > .icache_bsize = 32, > .dcache_bsize = 32, > @@ -162,9 +120,7 @@ struct cpu_spec cpu_specs[] = { > .pvr_mask = 0xffff0000, > .pvr_value = 0x00090000, > .cpu_name = "604r", > - .cpu_features = CPU_FTR_COMMON | > - CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | > - CPU_FTR_604_PERF_MON | CPU_FTR_HPTE_TABLE, > + .cpu_features = CPU_FTR_604, > .cpu_user_features = COMMON_PPC, > .icache_bsize = 32, > .dcache_bsize = 32, > @@ -175,9 +131,7 @@ struct cpu_spec cpu_specs[] = { > .pvr_mask = 0xffff0000, > .pvr_value = 0x000a0000, > .cpu_name = "604ev", > - .cpu_features = CPU_FTR_COMMON | > - CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | > - CPU_FTR_604_PERF_MON | CPU_FTR_HPTE_TABLE, > + .cpu_features = CPU_FTR_604, > .cpu_user_features = COMMON_PPC, > .icache_bsize = 32, > .dcache_bsize = 32, > @@ -188,10 +142,7 @@ struct cpu_spec cpu_specs[] = { > .pvr_mask = 0xffffffff, > .pvr_value = 0x00084202, > .cpu_name = "740/750", > - .cpu_features = CPU_FTR_COMMON | > - CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_MAYBE_CAN_DOZE | > - CPU_FTR_USE_TB | CPU_FTR_L2CR | CPU_FTR_HPTE_TABLE | > - CPU_FTR_MAYBE_CAN_NAP, > + .cpu_features = CPU_FTR_740_NOTAU, > .cpu_user_features = COMMON_PPC, > .icache_bsize = 32, > .dcache_bsize = 32, > @@ -202,10 +153,7 @@ struct cpu_spec cpu_specs[] = { > .pvr_mask = 0xfffffff0, > .pvr_value = 0x00080100, > .cpu_name = "750CX", > - .cpu_features = CPU_FTR_COMMON | > - CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_MAYBE_CAN_DOZE | > - CPU_FTR_USE_TB | CPU_FTR_L2CR | CPU_FTR_TAU | > - CPU_FTR_HPTE_TABLE | CPU_FTR_MAYBE_CAN_NAP, > + .cpu_features = CPU_FTR_750, > .cpu_user_features = COMMON_PPC, > .icache_bsize = 32, > .dcache_bsize = 32, > @@ -216,10 +164,7 @@ struct cpu_spec cpu_specs[] = { > .pvr_mask = 0xfffffff0, > .pvr_value = 0x00082200, > .cpu_name = "750CX", > - .cpu_features = CPU_FTR_COMMON | > - CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_MAYBE_CAN_DOZE | > - CPU_FTR_USE_TB | CPU_FTR_L2CR | CPU_FTR_TAU | > - CPU_FTR_HPTE_TABLE | CPU_FTR_MAYBE_CAN_NAP, > + .cpu_features = CPU_FTR_750, > .cpu_user_features = COMMON_PPC, > .icache_bsize = 32, > .dcache_bsize = 32, > @@ -230,10 +175,7 @@ struct cpu_spec cpu_specs[] = { > .pvr_mask = 0xfffffff0, > .pvr_value = 0x00082210, > .cpu_name = "750CXe", > - .cpu_features = CPU_FTR_COMMON | > - CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_MAYBE_CAN_DOZE | > - CPU_FTR_USE_TB | CPU_FTR_L2CR | CPU_FTR_TAU | > - CPU_FTR_HPTE_TABLE | CPU_FTR_MAYBE_CAN_NAP, > + .cpu_features = CPU_FTR_750, > .cpu_user_features = COMMON_PPC, > .icache_bsize = 32, > .dcache_bsize = 32, > @@ -244,10 +186,7 @@ struct cpu_spec cpu_specs[] = { > .pvr_mask = 0xffffffff, > .pvr_value = 0x00083214, > .cpu_name = "750CXe", > - .cpu_features = CPU_FTR_COMMON | > - CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_MAYBE_CAN_DOZE | > - CPU_FTR_USE_TB | CPU_FTR_L2CR | CPU_FTR_TAU | > - CPU_FTR_HPTE_TABLE | CPU_FTR_MAYBE_CAN_NAP, > + .cpu_features = CPU_FTR_750, > .cpu_user_features = COMMON_PPC, > .icache_bsize = 32, > .dcache_bsize = 32, > @@ -258,10 +197,7 @@ struct cpu_spec cpu_specs[] = { > .pvr_mask = 0xfffff000, > .pvr_value = 0x00083000, > .cpu_name = "745/755", > - .cpu_features = CPU_FTR_COMMON | > - CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_MAYBE_CAN_DOZE | > - CPU_FTR_USE_TB | CPU_FTR_L2CR | CPU_FTR_TAU | > - CPU_FTR_HPTE_TABLE | CPU_FTR_MAYBE_CAN_NAP, > + .cpu_features = CPU_FTR_750, > .cpu_user_features = COMMON_PPC, > .icache_bsize = 32, > .dcache_bsize = 32, > @@ -272,11 +208,7 @@ struct cpu_spec cpu_specs[] = { > .pvr_mask = 0xffffff00, > .pvr_value = 0x70000100, > .cpu_name = "750FX", > - .cpu_features = CPU_FTR_COMMON | > - CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_MAYBE_CAN_DOZE | > - CPU_FTR_USE_TB | CPU_FTR_L2CR | CPU_FTR_TAU | > - CPU_FTR_HPTE_TABLE | CPU_FTR_MAYBE_CAN_NAP | > - CPU_FTR_DUAL_PLL_750FX | CPU_FTR_NO_DPM, > + .cpu_features = CPU_FTR_750FX1, > .cpu_user_features = COMMON_PPC, > .icache_bsize = 32, > .dcache_bsize = 32, > @@ -287,11 +219,7 @@ struct cpu_spec cpu_specs[] = { > .pvr_mask = 0xffffffff, > .pvr_value = 0x70000200, > .cpu_name = "750FX", > - .cpu_features = CPU_FTR_COMMON | > - CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_MAYBE_CAN_DOZE | > - CPU_FTR_USE_TB | CPU_FTR_L2CR | CPU_FTR_TAU | > - CPU_FTR_HPTE_TABLE | CPU_FTR_MAYBE_CAN_NAP | > - CPU_FTR_NO_DPM, > + .cpu_features = CPU_FTR_750FX2, > .cpu_user_features = COMMON_PPC, > .icache_bsize = 32, > .dcache_bsize = 32, > @@ -302,11 +230,7 @@ struct cpu_spec cpu_specs[] = { > .pvr_mask = 0xffff0000, > .pvr_value = 0x70000000, > .cpu_name = "750FX", > - .cpu_features = CPU_FTR_COMMON | > - CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_MAYBE_CAN_DOZE | > - CPU_FTR_USE_TB | CPU_FTR_L2CR | CPU_FTR_TAU | > - CPU_FTR_HPTE_TABLE | CPU_FTR_MAYBE_CAN_NAP | > - CPU_FTR_DUAL_PLL_750FX | CPU_FTR_HAS_HIGH_BATS, > + .cpu_features = CPU_FTR_750FX, > .cpu_user_features = COMMON_PPC, > .icache_bsize = 32, > .dcache_bsize = 32, > @@ -317,11 +241,7 @@ struct cpu_spec cpu_specs[] = { > .pvr_mask = 0xffff0000, > .pvr_value = 0x70020000, > .cpu_name = "750GX", > - .cpu_features = CPU_FTR_SPLIT_ID_CACHE | > - CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB | > - CPU_FTR_L2CR | CPU_FTR_TAU | CPU_FTR_HPTE_TABLE | > - CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_DUAL_PLL_750FX | > - CPU_FTR_HAS_HIGH_BATS, > + .cpu_features = CPU_FTR_750GX, > .cpu_user_features = COMMON_PPC, > .icache_bsize = 32, > .dcache_bsize = 32, > @@ -332,10 +252,7 @@ struct cpu_spec cpu_specs[] = { > .pvr_mask = 0xffff0000, > .pvr_value = 0x00080000, > .cpu_name = "740/750", > - .cpu_features = CPU_FTR_COMMON | > - CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_MAYBE_CAN_DOZE | > - CPU_FTR_USE_TB | CPU_FTR_L2CR | CPU_FTR_TAU | > - CPU_FTR_HPTE_TABLE | CPU_FTR_MAYBE_CAN_NAP, > + .cpu_features = CPU_FTR_740, > .cpu_user_features = COMMON_PPC, > .icache_bsize = 32, > .dcache_bsize = 32, > @@ -346,11 +263,8 @@ struct cpu_spec cpu_specs[] = { > .pvr_mask = 0xffffffff, > .pvr_value = 0x000c1101, > .cpu_name = "7400 (1.1)", > - .cpu_features = CPU_FTR_COMMON | > - CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_MAYBE_CAN_DOZE | > - CPU_FTR_USE_TB | CPU_FTR_L2CR | CPU_FTR_ALTIVEC_COMP | > - CPU_FTR_HPTE_TABLE | CPU_FTR_MAYBE_CAN_NAP, > - .cpu_user_features = COMMON_PPC | > PPC_FEATURE_ALTIVEC_COMP, > + .cpu_features = CPU_FTR_7400_NOTAU, > + .cpu_user_features = COMMON_PPC | > PPC_FEATURE_HAS_ALTIVEC_COMP, > .icache_bsize = 32, > .dcache_bsize = 32, > .num_pmcs = 4, > @@ -360,12 +274,8 @@ struct cpu_spec cpu_specs[] = { > .pvr_mask = 0xffff0000, > .pvr_value = 0x000c0000, > .cpu_name = "7400", > - .cpu_features = CPU_FTR_COMMON | > - CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_MAYBE_CAN_DOZE | > - CPU_FTR_USE_TB | CPU_FTR_L2CR | CPU_FTR_TAU | > - CPU_FTR_ALTIVEC_COMP | CPU_FTR_HPTE_TABLE | > - CPU_FTR_MAYBE_CAN_NAP, > - .cpu_user_features = COMMON_PPC | > PPC_FEATURE_ALTIVEC_COMP, > + .cpu_features = CPU_FTR_7400, > + .cpu_user_features = COMMON_PPC | > PPC_FEATURE_HAS_ALTIVEC_COMP, > .icache_bsize = 32, > .dcache_bsize = 32, > .num_pmcs = 4, > @@ -375,12 +285,8 @@ struct cpu_spec cpu_specs[] = { > .pvr_mask = 0xffff0000, > .pvr_value = 0x800c0000, > .cpu_name = "7410", > - .cpu_features = CPU_FTR_COMMON | > - CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_MAYBE_CAN_DOZE | > - CPU_FTR_USE_TB | CPU_FTR_L2CR | CPU_FTR_TAU | > - CPU_FTR_ALTIVEC_COMP | CPU_FTR_HPTE_TABLE | > - CPU_FTR_MAYBE_CAN_NAP, > - .cpu_user_features = COMMON_PPC | > PPC_FEATURE_ALTIVEC_COMP, > + .cpu_features = CPU_FTR_7400, > + .cpu_user_features = COMMON_PPC | > PPC_FEATURE_HAS_ALTIVEC_COMP, > .icache_bsize = 32, > .dcache_bsize = 32, > .num_pmcs = 4, > @@ -390,12 +296,8 @@ struct cpu_spec cpu_specs[] = { > .pvr_mask = 0xffffffff, > .pvr_value = 0x80000200, > .cpu_name = "7450", > - .cpu_features = CPU_FTR_COMMON | > - CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | > - CPU_FTR_L2CR | CPU_FTR_ALTIVEC_COMP | CPU_FTR_L3CR | > - CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 | > - CPU_FTR_NEED_COHERENT, > - .cpu_user_features = COMMON_PPC | > PPC_FEATURE_ALTIVEC_COMP, > + .cpu_features = CPU_FTR_7450_20, > + .cpu_user_features = COMMON_PPC | > PPC_FEATURE_HAS_ALTIVEC_COMP, > .icache_bsize = 32, > .dcache_bsize = 32, > .num_pmcs = 6, > @@ -405,14 +307,8 @@ struct cpu_spec cpu_specs[] = { > .pvr_mask = 0xffffffff, > .pvr_value = 0x80000201, > .cpu_name = "7450", > - .cpu_features = CPU_FTR_COMMON | > - CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | > - CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_L2CR | > - CPU_FTR_ALTIVEC_COMP | CPU_FTR_L3CR | > - CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 | > - CPU_FTR_NAP_DISABLE_L2_PR | CPU_FTR_L3_DISABLE_NAP | > - CPU_FTR_NEED_COHERENT, > - .cpu_user_features = COMMON_PPC | > PPC_FEATURE_ALTIVEC_COMP, > + .cpu_features = CPU_FTR_7450_21, > + .cpu_user_features = COMMON_PPC | > PPC_FEATURE_HAS_ALTIVEC_COMP, > .icache_bsize = 32, > .dcache_bsize = 32, > .num_pmcs = 6, > @@ -422,13 +318,8 @@ struct cpu_spec cpu_specs[] = { > .pvr_mask = 0xffff0000, > .pvr_value = 0x80000000, > .cpu_name = "7450", > - .cpu_features = CPU_FTR_COMMON | > - CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | > - CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_L2CR | > - CPU_FTR_ALTIVEC_COMP | CPU_FTR_L3CR | > - CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 | > - CPU_FTR_NAP_DISABLE_L2_PR | CPU_FTR_NEED_COHERENT, > - .cpu_user_features = COMMON_PPC | > PPC_FEATURE_ALTIVEC_COMP, > + .cpu_features = CPU_FTR_7450_23, > + .cpu_user_features = COMMON_PPC | > PPC_FEATURE_HAS_ALTIVEC_COMP, > .icache_bsize = 32, > .dcache_bsize = 32, > .num_pmcs = 6, > @@ -438,12 +329,8 @@ struct cpu_spec cpu_specs[] = { > .pvr_mask = 0xffffff00, > .pvr_value = 0x80010100, > .cpu_name = "7455", > - .cpu_features = CPU_FTR_COMMON | > - CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | > - CPU_FTR_L2CR | CPU_FTR_ALTIVEC_COMP | CPU_FTR_L3CR | > - CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 | > - CPU_FTR_HAS_HIGH_BATS | CPU_FTR_NEED_COHERENT, > - .cpu_user_features = COMMON_PPC | > PPC_FEATURE_ALTIVEC_COMP, > + .cpu_features = CPU_FTR_7455_1, > + .cpu_user_features = COMMON_PPC | > PPC_FEATURE_HAS_ALTIVEC_COMP, > .icache_bsize = 32, > .dcache_bsize = 32, > .num_pmcs = 6, > @@ -453,14 +340,8 @@ struct cpu_spec cpu_specs[] = { > .pvr_mask = 0xffffffff, > .pvr_value = 0x80010200, > .cpu_name = "7455", > - .cpu_features = CPU_FTR_COMMON | > - CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | > - CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_L2CR | > - CPU_FTR_ALTIVEC_COMP | CPU_FTR_L3CR | > - CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 | > - CPU_FTR_NAP_DISABLE_L2_PR | CPU_FTR_L3_DISABLE_NAP | > - CPU_FTR_NEED_COHERENT | CPU_FTR_HAS_HIGH_BATS, > - .cpu_user_features = COMMON_PPC | > PPC_FEATURE_ALTIVEC_COMP, > + .cpu_features = CPU_FTR_7455_20, > + .cpu_user_features = COMMON_PPC | > PPC_FEATURE_HAS_ALTIVEC_COMP, > .icache_bsize = 32, > .dcache_bsize = 32, > .num_pmcs = 6, > @@ -470,14 +351,8 @@ struct cpu_spec cpu_specs[] = { > .pvr_mask = 0xffff0000, > .pvr_value = 0x80010000, > .cpu_name = "7455", > - .cpu_features = CPU_FTR_COMMON | > - CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | > - CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_L2CR | > - CPU_FTR_ALTIVEC_COMP | CPU_FTR_L3CR | > - CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 | > - CPU_FTR_NAP_DISABLE_L2_PR | CPU_FTR_HAS_HIGH_BATS | > - CPU_FTR_NEED_COHERENT, > - .cpu_user_features = COMMON_PPC | > PPC_FEATURE_ALTIVEC_COMP, > + .cpu_features = CPU_FTR_7455, > + .cpu_user_features = COMMON_PPC | > PPC_FEATURE_HAS_ALTIVEC_COMP, > .icache_bsize = 32, > .dcache_bsize = 32, > .num_pmcs = 6, > @@ -487,14 +362,8 @@ struct cpu_spec cpu_specs[] = { > .pvr_mask = 0xffffffff, > .pvr_value = 0x80020100, > .cpu_name = "7447/7457", > - .cpu_features = CPU_FTR_COMMON | > - CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | > - CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_L2CR | > - CPU_FTR_ALTIVEC_COMP | CPU_FTR_L3CR | > - CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 | > - CPU_FTR_NAP_DISABLE_L2_PR | CPU_FTR_HAS_HIGH_BATS | > - CPU_FTR_NEED_COHERENT | CPU_FTR_NO_BTIC, > - .cpu_user_features = COMMON_PPC | > PPC_FEATURE_ALTIVEC_COMP, > + .cpu_features = CPU_FTR_7447_10, > + .cpu_user_features = COMMON_PPC | > PPC_FEATURE_HAS_ALTIVEC_COMP, > .icache_bsize = 32, > .dcache_bsize = 32, > .num_pmcs = 6, > @@ -504,14 +373,8 @@ struct cpu_spec cpu_specs[] = { > .pvr_mask = 0xffffffff, > .pvr_value = 0x80020101, > .cpu_name = "7447/7457", > - .cpu_features = CPU_FTR_COMMON | > - CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | > - CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_L2CR | > - CPU_FTR_ALTIVEC_COMP | CPU_FTR_L3CR | > - CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 | > - CPU_FTR_NAP_DISABLE_L2_PR | CPU_FTR_HAS_HIGH_BATS | > - CPU_FTR_NEED_COHERENT | CPU_FTR_NO_BTIC, > - .cpu_user_features = COMMON_PPC | > PPC_FEATURE_ALTIVEC_COMP, > + .cpu_features = CPU_FTR_7447_10, > + .cpu_user_features = COMMON_PPC | > PPC_FEATURE_HAS_ALTIVEC_COMP, > .icache_bsize = 32, > .dcache_bsize = 32, > .num_pmcs = 6, > @@ -521,14 +384,8 @@ struct cpu_spec cpu_specs[] = { > .pvr_mask = 0xffff0000, > .pvr_value = 0x80020000, > .cpu_name = "7447/7457", > - .cpu_features = CPU_FTR_COMMON | > - CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | > - CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_L2CR | > - CPU_FTR_ALTIVEC_COMP | CPU_FTR_L3CR | > - CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 | > - CPU_FTR_NAP_DISABLE_L2_PR | CPU_FTR_HAS_HIGH_BATS | > - CPU_FTR_NEED_COHERENT, > - .cpu_user_features = COMMON_PPC | > PPC_FEATURE_ALTIVEC_COMP, > + .cpu_features = CPU_FTR_7447, > + .cpu_user_features = COMMON_PPC | > PPC_FEATURE_HAS_ALTIVEC_COMP, > .icache_bsize = 32, > .dcache_bsize = 32, > .num_pmcs = 6, > @@ -538,13 +395,8 @@ struct cpu_spec cpu_specs[] = { > .pvr_mask = 0xffff0000, > .pvr_value = 0x80030000, > .cpu_name = "7447A", > - .cpu_features = CPU_FTR_COMMON | > - CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | > - CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_L2CR | > - CPU_FTR_ALTIVEC_COMP | CPU_FTR_HPTE_TABLE | > - CPU_FTR_SPEC7450 | CPU_FTR_NAP_DISABLE_L2_PR | > - CPU_FTR_HAS_HIGH_BATS | CPU_FTR_NEED_COHERENT, > - .cpu_user_features = COMMON_PPC | > PPC_FEATURE_ALTIVEC_COMP, > + .cpu_features = CPU_FTR_7447A, > + .cpu_user_features = COMMON_PPC | > PPC_FEATURE_HAS_ALTIVEC_COMP, > .icache_bsize = 32, > .dcache_bsize = 32, > .num_pmcs = 6, > @@ -554,13 +406,8 @@ struct cpu_spec cpu_specs[] = { > .pvr_mask = 0xffff0000, > .pvr_value = 0x80040000, > .cpu_name = "7448", > - .cpu_features = CPU_FTR_COMMON | > - CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | > - CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_L2CR | > - CPU_FTR_ALTIVEC_COMP | CPU_FTR_HPTE_TABLE | > - CPU_FTR_SPEC7450 | CPU_FTR_NAP_DISABLE_L2_PR | > - CPU_FTR_HAS_HIGH_BATS | CPU_FTR_NEED_COHERENT, > - .cpu_user_features = COMMON_PPC | > PPC_FEATURE_ALTIVEC_COMP, > + .cpu_features = CPU_FTR_7447A, > + .cpu_user_features = COMMON_PPC | > PPC_FEATURE_HAS_ALTIVEC_COMP, > .icache_bsize = 32, > .dcache_bsize = 32, > .num_pmcs = 6, > @@ -570,9 +417,7 @@ struct cpu_spec cpu_specs[] = { > .pvr_mask = 0x7fff0000, > .pvr_value = 0x00810000, > .cpu_name = "82xx", > - .cpu_features = CPU_FTR_COMMON | > - CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_MAYBE_CAN_DOZE | > - CPU_FTR_USE_TB, > + .cpu_features = CPU_FTR_82XX, > .cpu_user_features = COMMON_PPC, > .icache_bsize = 32, > .dcache_bsize = 32, > @@ -582,9 +427,7 @@ struct cpu_spec cpu_specs[] = { > .pvr_mask = 0x7fff0000, > .pvr_value = 0x00820000, > .cpu_name = "G2_LE", > - .cpu_features = CPU_FTR_SPLIT_ID_CACHE | > - CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB | > - CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_HAS_HIGH_BATS, > + .cpu_features = CPU_FTR_G2_LE, > .cpu_user_features = COMMON_PPC, > .icache_bsize = 32, > .dcache_bsize = 32, > @@ -594,9 +437,7 @@ struct cpu_spec cpu_specs[] = { > .pvr_mask = 0x7fff0000, > .pvr_value = 0x00830000, > .cpu_name = "e300", > - .cpu_features = CPU_FTR_SPLIT_ID_CACHE | > - CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB | > - CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_HAS_HIGH_BATS, > + .cpu_features = CPU_FTR_E300, > .cpu_user_features = COMMON_PPC, > .icache_bsize = 32, > .dcache_bsize = 32, > @@ -606,9 +447,7 @@ struct cpu_spec cpu_specs[] = { > .pvr_mask = 0x00000000, > .pvr_value = 0x00000000, > .cpu_name = "(generic PPC)", > - .cpu_features = CPU_FTR_COMMON | > - CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | > - CPU_FTR_HPTE_TABLE, > + .cpu_features = CPU_FTR_CLASSIC32, > .cpu_user_features = COMMON_PPC, > .icache_bsize = 32, > .dcache_bsize = 32, > @@ -620,9 +459,7 @@ struct cpu_spec cpu_specs[] = { > .pvr_mask = 0xffff0000, > .pvr_value = 0x00400000, > .cpu_name = "Power3 (630)", > - .cpu_features = CPU_FTR_COMMON | > - CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | > - CPU_FTR_HPTE_TABLE, > + .cpu_features = CPU_FTR_POWER3_32, > .cpu_user_features = COMMON_PPC | PPC_FEATURE_64, > .icache_bsize = 128, > .dcache_bsize = 128, > @@ -633,9 +470,7 @@ struct cpu_spec cpu_specs[] = { > .pvr_mask = 0xffff0000, > .pvr_value = 0x00410000, > .cpu_name = "Power3 (630+)", > - .cpu_features = CPU_FTR_COMMON | > - CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | > - CPU_FTR_HPTE_TABLE, > + .cpu_features = CPU_FTR_POWER3_32, > .cpu_user_features = COMMON_PPC | PPC_FEATURE_64, > .icache_bsize = 128, > .dcache_bsize = 128, > @@ -646,9 +481,7 @@ struct cpu_spec cpu_specs[] = { > .pvr_mask = 0xffff0000, > .pvr_value = 0x00360000, > .cpu_name = "I-star", > - .cpu_features = CPU_FTR_COMMON | > - CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | > - CPU_FTR_HPTE_TABLE, > + .cpu_features = CPU_FTR_POWER3_32, > .cpu_user_features = COMMON_PPC | PPC_FEATURE_64, > .icache_bsize = 128, > .dcache_bsize = 128, > @@ -659,55 +492,19 @@ struct cpu_spec cpu_specs[] = { > .pvr_mask = 0xffff0000, > .pvr_value = 0x00370000, > .cpu_name = "S-star", > - .cpu_features = CPU_FTR_COMMON | > - CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | > - CPU_FTR_HPTE_TABLE, > + .cpu_features = CPU_FTR_POWER3_32, > .cpu_user_features = COMMON_PPC | PPC_FEATURE_64, > .icache_bsize = 128, > .dcache_bsize = 128, > .num_pmcs = 8, > .cpu_setup = __setup_cpu_power3 > }, > -#endif /* CONFIG_PPC64BRIDGE */ > -#ifdef CONFIG_POWER4 > - { /* Power4 */ > - .pvr_mask = 0xffff0000, > - .pvr_value = 0x00350000, > - .cpu_name = "Power4", > - .cpu_features = CPU_FTR_COMMON | > - CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | > - CPU_FTR_HPTE_TABLE, > - .cpu_user_features = COMMON_PPC | PPC_FEATURE_64, > - .icache_bsize = 128, > - .dcache_bsize = 128, > - .num_pmcs = 8, > - .cpu_setup = __setup_cpu_power4 > - }, > - { /* PPC970 */ > - .pvr_mask = 0xffff0000, > - .pvr_value = 0x00390000, > - .cpu_name = "PPC970", > - .cpu_features = CPU_FTR_COMMON | > - CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | > - CPU_FTR_HPTE_TABLE | > - CPU_FTR_ALTIVEC_COMP | CPU_FTR_MAYBE_CAN_NAP, > - .cpu_user_features = COMMON_PPC | PPC_FEATURE_64 | > - PPC_FEATURE_ALTIVEC_COMP, > - .icache_bsize = 128, > - .dcache_bsize = 128, > - .num_pmcs = 8, > - .cpu_setup = __setup_cpu_ppc970 > - }, > { /* PPC970FX */ > .pvr_mask = 0xffff0000, > .pvr_value = 0x003c0000, > .cpu_name = "PPC970FX", > - .cpu_features = CPU_FTR_COMMON | > - CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | > - CPU_FTR_HPTE_TABLE | > - CPU_FTR_ALTIVEC_COMP | CPU_FTR_MAYBE_CAN_NAP, > - .cpu_user_features = COMMON_PPC | PPC_FEATURE_64 | > - PPC_FEATURE_ALTIVEC_COMP, > + .cpu_features = CPU_FTR_970_32, > + .cpu_user_features = COMMON_PPC | PPC_FEATURE_64 | > PPC_FEATURE_HAS_ALTIVEC_COMP, > .icache_bsize = 128, > .dcache_bsize = 128, > .num_pmcs = 8, > @@ -721,8 +518,7 @@ struct cpu_spec cpu_specs[] = { > .cpu_name = "8xx", > /* CPU_FTR_MAYBE_CAN_DOZE is possible, > * if the 8xx code is there.... */ > - .cpu_features = CPU_FTR_SPLIT_ID_CACHE | > - CPU_FTR_USE_TB, > + .cpu_features = CPU_FTR_8XX, > .cpu_user_features = PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU, > .icache_bsize = 16, > .dcache_bsize = 16, > @@ -733,8 +529,7 @@ struct cpu_spec cpu_specs[] = { > .pvr_mask = 0xffffff00, > .pvr_value = 0x00200200, > .cpu_name = "403GC", > - .cpu_features = CPU_FTR_SPLIT_ID_CACHE | > - CPU_FTR_USE_TB, > + .cpu_features = CPU_FTR_40X, > .cpu_user_features = PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU, > .icache_bsize = 16, > .dcache_bsize = 16, > @@ -743,8 +538,7 @@ struct cpu_spec cpu_specs[] = { > .pvr_mask = 0xffffff00, > .pvr_value = 0x00201400, > .cpu_name = "403GCX", > - .cpu_features = CPU_FTR_SPLIT_ID_CACHE | > - CPU_FTR_USE_TB, > + .cpu_features = CPU_FTR_40X, > .cpu_user_features = PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU, > .icache_bsize = 16, > .dcache_bsize = 16, > @@ -753,8 +547,7 @@ struct cpu_spec cpu_specs[] = { > .pvr_mask = 0xffff0000, > .pvr_value = 0x00200000, > .cpu_name = "403G ??", > - .cpu_features = CPU_FTR_SPLIT_ID_CACHE | > - CPU_FTR_USE_TB, > + .cpu_features = CPU_FTR_40X, > .cpu_user_features = PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU, > .icache_bsize = 16, > .dcache_bsize = 16, > @@ -763,8 +556,7 @@ struct cpu_spec cpu_specs[] = { > .pvr_mask = 0xffff0000, > .pvr_value = 0x40110000, > .cpu_name = "405GP", > - .cpu_features = CPU_FTR_SPLIT_ID_CACHE | > - CPU_FTR_USE_TB, > + .cpu_features = CPU_FTR_40X, > .cpu_user_features = PPC_FEATURE_32 | > PPC_FEATURE_HAS_MMU | PPC_FEATURE_HAS_4xxMAC, > .icache_bsize = 32, > @@ -774,8 +566,7 @@ struct cpu_spec cpu_specs[] = { > .pvr_mask = 0xffff0000, > .pvr_value = 0x40130000, > .cpu_name = "STB03xxx", > - .cpu_features = CPU_FTR_SPLIT_ID_CACHE | > - CPU_FTR_USE_TB, > + .cpu_features = CPU_FTR_40X, > .cpu_user_features = PPC_FEATURE_32 | > PPC_FEATURE_HAS_MMU | PPC_FEATURE_HAS_4xxMAC, > .icache_bsize = 32, > @@ -785,8 +576,7 @@ struct cpu_spec cpu_specs[] = { > .pvr_mask = 0xffff0000, > .pvr_value = 0x41810000, > .cpu_name = "STB04xxx", > - .cpu_features = CPU_FTR_SPLIT_ID_CACHE | > - CPU_FTR_USE_TB, > + .cpu_features = CPU_FTR_40X, > .cpu_user_features = PPC_FEATURE_32 | > PPC_FEATURE_HAS_MMU | PPC_FEATURE_HAS_4xxMAC, > .icache_bsize = 32, > @@ -796,8 +586,7 @@ struct cpu_spec cpu_specs[] = { > .pvr_mask = 0xffff0000, > .pvr_value = 0x41610000, > .cpu_name = "NP405L", > - .cpu_features = CPU_FTR_SPLIT_ID_CACHE | > - CPU_FTR_USE_TB, > + .cpu_features = CPU_FTR_40X, > .cpu_user_features = PPC_FEATURE_32 | > PPC_FEATURE_HAS_MMU | PPC_FEATURE_HAS_4xxMAC, > .icache_bsize = 32, > @@ -807,8 +596,7 @@ struct cpu_spec cpu_specs[] = { > .pvr_mask = 0xffff0000, > .pvr_value = 0x40B10000, > .cpu_name = "NP4GS3", > - .cpu_features = CPU_FTR_SPLIT_ID_CACHE | > - CPU_FTR_USE_TB, > + .cpu_features = CPU_FTR_40X, > .cpu_user_features = PPC_FEATURE_32 | > PPC_FEATURE_HAS_MMU | PPC_FEATURE_HAS_4xxMAC, > .icache_bsize = 32, > @@ -818,8 +606,7 @@ struct cpu_spec cpu_specs[] = { > .pvr_mask = 0xffff0000, > .pvr_value = 0x41410000, > .cpu_name = "NP405H", > - .cpu_features = CPU_FTR_SPLIT_ID_CACHE | > - CPU_FTR_USE_TB, > + .cpu_features = CPU_FTR_40X, > .cpu_user_features = PPC_FEATURE_32 | > PPC_FEATURE_HAS_MMU | PPC_FEATURE_HAS_4xxMAC, > .icache_bsize = 32, > @@ -829,8 +616,7 @@ struct cpu_spec cpu_specs[] = { > .pvr_mask = 0xffff0000, > .pvr_value = 0x50910000, > .cpu_name = "405GPr", > - .cpu_features = CPU_FTR_SPLIT_ID_CACHE | > - CPU_FTR_USE_TB, > + .cpu_features = CPU_FTR_40X, > .cpu_user_features = PPC_FEATURE_32 | > PPC_FEATURE_HAS_MMU | PPC_FEATURE_HAS_4xxMAC, > .icache_bsize = 32, > @@ -840,8 +626,7 @@ struct cpu_spec cpu_specs[] = { > .pvr_mask = 0xffff0000, > .pvr_value = 0x51510000, > .cpu_name = "STBx25xx", > - .cpu_features = CPU_FTR_SPLIT_ID_CACHE | > - CPU_FTR_USE_TB, > + .cpu_features = CPU_FTR_40X, > .cpu_user_features = PPC_FEATURE_32 | > PPC_FEATURE_HAS_MMU | PPC_FEATURE_HAS_4xxMAC, > .icache_bsize = 32, > @@ -851,8 +636,7 @@ struct cpu_spec cpu_specs[] = { > .pvr_mask = 0xffff0000, > .pvr_value = 0x41F10000, > .cpu_name = "405LP", > - .cpu_features = CPU_FTR_SPLIT_ID_CACHE | > - CPU_FTR_USE_TB, > + .cpu_features = CPU_FTR_40X, > .cpu_user_features = PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU, > .icache_bsize = 32, > .dcache_bsize = 32, > @@ -861,8 +645,7 @@ struct cpu_spec cpu_specs[] = { > .pvr_mask = 0xffff0000, > .pvr_value = 0x20010000, > .cpu_name = "Virtex-II Pro", > - .cpu_features = CPU_FTR_SPLIT_ID_CACHE | > - CPU_FTR_USE_TB, > + .cpu_features = CPU_FTR_40X, > .cpu_user_features = PPC_FEATURE_32 | > PPC_FEATURE_HAS_MMU | PPC_FEATURE_HAS_4xxMAC, > .icache_bsize = 32, > @@ -872,8 +655,7 @@ struct cpu_spec cpu_specs[] = { > .pvr_mask = 0xffff0000, > .pvr_value = 0x51210000, > .cpu_name = "405EP", > - .cpu_features = CPU_FTR_SPLIT_ID_CACHE | > - CPU_FTR_USE_TB, > + .cpu_features = CPU_FTR_40X, > .cpu_user_features = PPC_FEATURE_32 | > PPC_FEATURE_HAS_MMU | PPC_FEATURE_HAS_4xxMAC, > .icache_bsize = 32, > @@ -886,8 +668,7 @@ struct cpu_spec cpu_specs[] = { > .pvr_mask = 0xf0000fff, > .pvr_value = 0x40000850, > .cpu_name = "440EP Rev. A", > - .cpu_features = CPU_FTR_SPLIT_ID_CACHE | > - CPU_FTR_USE_TB, > + .cpu_features = CPU_FTR_44X, > .cpu_user_features = COMMON_PPC, /* 440EP has an FPU */ > .icache_bsize = 32, > .dcache_bsize = 32, > @@ -896,8 +677,7 @@ struct cpu_spec cpu_specs[] = { > .pvr_mask = 0xf0000fff, > .pvr_value = 0x400008d3, > .cpu_name = "440EP Rev. B", > - .cpu_features = CPU_FTR_SPLIT_ID_CACHE | > - CPU_FTR_USE_TB, > + .cpu_features = CPU_FTR_44X, > .cpu_user_features = COMMON_PPC, /* 440EP has an FPU */ > .icache_bsize = 32, > .dcache_bsize = 32, > @@ -906,8 +686,7 @@ struct cpu_spec cpu_specs[] = { > .pvr_mask = 0xf0000fff, > .pvr_value = 0x40000440, > .cpu_name = "440GP Rev. B", > - .cpu_features = CPU_FTR_SPLIT_ID_CACHE | > - CPU_FTR_USE_TB, > + .cpu_features = CPU_FTR_44X, > .cpu_user_features = PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU, > .icache_bsize = 32, > .dcache_bsize = 32, > @@ -916,8 +695,7 @@ struct cpu_spec cpu_specs[] = { > .pvr_mask = 0xf0000fff, > .pvr_value = 0x40000481, > .cpu_name = "440GP Rev. C", > - .cpu_features = CPU_FTR_SPLIT_ID_CACHE | > - CPU_FTR_USE_TB, > + .cpu_features = CPU_FTR_44X, > .cpu_user_features = PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU, > .icache_bsize = 32, > .dcache_bsize = 32, > @@ -926,8 +704,7 @@ struct cpu_spec cpu_specs[] = { > .pvr_mask = 0xf0000fff, > .pvr_value = 0x50000850, > .cpu_name = "440GX Rev. A", > - .cpu_features = CPU_FTR_SPLIT_ID_CACHE | > - CPU_FTR_USE_TB, > + .cpu_features = CPU_FTR_44X, > .cpu_user_features = PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU, > .icache_bsize = 32, > .dcache_bsize = 32, > @@ -936,8 +713,7 @@ struct cpu_spec cpu_specs[] = { > .pvr_mask = 0xf0000fff, > .pvr_value = 0x50000851, > .cpu_name = "440GX Rev. B", > - .cpu_features = CPU_FTR_SPLIT_ID_CACHE | > - CPU_FTR_USE_TB, > + .cpu_features = CPU_FTR_44X, > .cpu_user_features = PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU, > .icache_bsize = 32, > .dcache_bsize = 32, > @@ -946,8 +722,7 @@ struct cpu_spec cpu_specs[] = { > .pvr_mask = 0xf0000fff, > .pvr_value = 0x50000892, > .cpu_name = "440GX Rev. C", > - .cpu_features = CPU_FTR_SPLIT_ID_CACHE | > - CPU_FTR_USE_TB, > + .cpu_features = CPU_FTR_44X, > .cpu_user_features = PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU, > .icache_bsize = 32, > .dcache_bsize = 32, > @@ -956,8 +731,7 @@ struct cpu_spec cpu_specs[] = { > .pvr_mask = 0xf0000fff, > .pvr_value = 0x50000894, > .cpu_name = "440GX Rev. F", > - .cpu_features = CPU_FTR_SPLIT_ID_CACHE | > - CPU_FTR_USE_TB, > + .cpu_features = CPU_FTR_44X, > .cpu_user_features = PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU, > .icache_bsize = 32, > .dcache_bsize = 32, > @@ -966,8 +740,7 @@ struct cpu_spec cpu_specs[] = { > .pvr_mask = 0xff000fff, > .pvr_value = 0x53000891, > .cpu_name = "440SP Rev. A", > - .cpu_features = CPU_FTR_SPLIT_ID_CACHE | > - CPU_FTR_USE_TB, > + .cpu_features = CPU_FTR_44X, > .cpu_user_features = PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU, > .icache_bsize = 32, > .dcache_bsize = 32, > @@ -979,7 +752,7 @@ struct cpu_spec cpu_specs[] = { > .pvr_value = 0x81000000, > .cpu_name = "e200z5", > /* xxx - galak: add CPU_FTR_MAYBE_CAN_DOZE */ > - .cpu_features = CPU_FTR_USE_TB, > + .cpu_features = CPU_FTR_E200, > .cpu_user_features = PPC_FEATURE_32 | > PPC_FEATURE_HAS_MMU | PPC_FEATURE_HAS_EFP_SINGLE | > PPC_FEATURE_UNIFIED_CACHE, > @@ -990,7 +763,7 @@ struct cpu_spec cpu_specs[] = { > .pvr_value = 0x81100000, > .cpu_name = "e200z6", > /* xxx - galak: add CPU_FTR_MAYBE_CAN_DOZE */ > - .cpu_features = CPU_FTR_USE_TB, > + .cpu_features = CPU_FTR_E200, > .cpu_user_features = PPC_FEATURE_32 | > PPC_FEATURE_HAS_MMU | PPC_FEATURE_SPE_COMP | > PPC_FEATURE_HAS_EFP_SINGLE | > @@ -1002,8 +775,7 @@ struct cpu_spec cpu_specs[] = { > .pvr_value = 0x80200000, > .cpu_name = "e500", > /* xxx - galak: add CPU_FTR_MAYBE_CAN_DOZE */ > - .cpu_features = CPU_FTR_SPLIT_ID_CACHE | > - CPU_FTR_USE_TB, > + .cpu_features = CPU_FTR_E500, > .cpu_user_features = PPC_FEATURE_32 | > PPC_FEATURE_HAS_MMU | PPC_FEATURE_SPE_COMP | > PPC_FEATURE_HAS_EFP_SINGLE, > @@ -1016,8 +788,7 @@ struct cpu_spec cpu_specs[] = { > .pvr_value = 0x80210000, > .cpu_name = "e500v2", > /* xxx - galak: add CPU_FTR_MAYBE_CAN_DOZE */ > - .cpu_features = CPU_FTR_SPLIT_ID_CACHE | > - CPU_FTR_USE_TB | CPU_FTR_BIG_PHYS, > + .cpu_features = CPU_FTR_E500_2, > .cpu_user_features = PPC_FEATURE_32 | > PPC_FEATURE_HAS_MMU | PPC_FEATURE_SPE_COMP | > PPC_FEATURE_HAS_EFP_SINGLE | PPC_FEATURE_HAS_EFP_DOUBLE, > @@ -1031,7 +802,7 @@ struct cpu_spec cpu_specs[] = { > .pvr_mask = 0x00000000, > .pvr_value = 0x00000000, > .cpu_name = "(generic PPC)", > - .cpu_features = CPU_FTR_COMMON, > + .cpu_features = CPU_FTR_GENERIC_32, > .cpu_user_features = PPC_FEATURE_32, > .icache_bsize = 32, > .dcache_bsize = 32, > Index: clean-cg/include/asm-powerpc/cputable.h > =================================================================== > --- /dev/null > +++ clean-cg/include/asm-powerpc/cputable.h > @@ -0,0 +1,475 @@ > +#ifndef __ASM_POWERPC_CPUTABLE_H > +#define __ASM_POWERPC_CPUTABLE_H > + > +#ifdef __KERNEL__ > +#include > +#include /* for ASM_CONST */ > + > +#define PPC_FEATURE_32 0x80000000 > +#define PPC_FEATURE_64 0x40000000 > +#define PPC_FEATURE_601_INSTR 0x20000000 > +#define PPC_FEATURE_HAS_ALTIVEC 0x10000000 > +#define PPC_FEATURE_HAS_FPU 0x08000000 > +#define PPC_FEATURE_HAS_MMU 0x04000000 > +#define PPC_FEATURE_HAS_4xxMAC 0x02000000 > +#define PPC_FEATURE_UNIFIED_CACHE 0x01000000 > +#define PPC_FEATURE_HAS_SPE 0x00800000 > +#define PPC_FEATURE_HAS_EFP_SINGLE 0x00400000 > +#define PPC_FEATURE_HAS_EFP_DOUBLE 0x00200000 > + > +#ifndef __ASSEMBLY__ > + > +/* This structure can grow, it's real size is used by head.S code > + * via the mkdefs mechanism. > + */ > +struct cpu_spec; > +struct op_ppc64_model; > + > +#ifndef __powerpc64__ > +typedef void (*cpu_setup_t)(unsigned long offset, int cpu_nr, > struct cpu_spec* spec); > +#else /* __powerpc64__ */ > +typedef void (*cpu_setup_t)(unsigned long offset, struct > cpu_spec* spec); > +#endif /* __powerpc64__ */ > + > +struct cpu_spec { > + /* CPU is matched via (PVR & pvr_mask) == pvr_value */ > + unsigned int pvr_mask; > + unsigned int pvr_value; > + > + char *cpu_name; > + unsigned long cpu_features; /* Kernel features */ > + unsigned int cpu_user_features; /* Userland features */ > + > + /* cache line sizes */ > + 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 > + */ > + cpu_setup_t cpu_setup; > +#ifdef __powerpc64__ > + > + /* Used by oprofile userspace to select the right counters */ > + char *oprofile_cpu_type; > + > + /* Processor specific oprofile operations */ > + struct op_ppc64_model *oprofile_model; > +#endif /* __powerpc64__ */ > +}; > + > +extern struct cpu_spec cpu_specs[]; > + > +#ifndef __powerpc64__ > +extern struct cpu_spec *cur_cpu_spec[]; > +#else /* __powerpc64__ */ > +extern struct cpu_spec *cur_cpu_spec; > +#endif /* __powerpc64__ */ > + > +#endif /* __ASSEMBLY__ */ > + > +/* CPU kernel features */ > + > +/* Retain the 32b definitions all use bottom half of word */ > +#define CPU_FTR_SPLIT_ID_CACHE ASM_CONST(0x0000000000000001) > +#define CPU_FTR_L2CR ASM_CONST(0x0000000000000002) > +#define CPU_FTR_SPEC7450 ASM_CONST(0x0000000000000004) > +#define CPU_FTR_ALTIVEC ASM_CONST(0x0000000000000008) > +#define CPU_FTR_TAU ASM_CONST(0x0000000000000010) > +#define CPU_FTR_CAN_DOZE ASM_CONST(0x0000000000000020) > +#define CPU_FTR_USE_TB ASM_CONST(0x0000000000000040) > +#define CPU_FTR_604_PERF_MON ASM_CONST(0x0000000000000080) > +#define CPU_FTR_601 ASM_CONST(0x0000000000000100) > +#define CPU_FTR_HPTE_TABLE ASM_CONST(0x0000000000000200) > +#define CPU_FTR_CAN_NAP ASM_CONST(0x0000000000000400) > +#define CPU_FTR_L3CR ASM_CONST(0x0000000000000800) > +#define CPU_FTR_L3_DISABLE_NAP ASM_CONST(0x0000000000001000) > +#define CPU_FTR_NAP_DISABLE_L2_PR ASM_CONST(0x0000000000002000) > +#define CPU_FTR_DUAL_PLL_750FX ASM_CONST(0x0000000000004000) > +#define CPU_FTR_NO_DPM ASM_CONST(0x0000000000008000) > +#define CPU_FTR_HAS_HIGH_BATS ASM_CONST(0x0000000000010000) > +#define CPU_FTR_NEED_COHERENT ASM_CONST(0x0000000000020000) > +#define CPU_FTR_NO_BTIC ASM_CONST(0x0000000000040000) > +#define CPU_FTR_BIG_PHYS ASM_CONST(0x0000000000080000) > + > +#ifdef __powerpc64__ > +/* Add the 64b processor unique features in the top half of the > word */ > +#define CPU_FTR_SLB ASM_CONST(0x0000000100000000) > +#define CPU_FTR_16M_PAGE ASM_CONST(0x0000000200000000) > +#define CPU_FTR_TLBIEL ASM_CONST(0x0000000400000000) > +#define CPU_FTR_NOEXECUTE ASM_CONST(0x0000000800000000) > +#define CPU_FTR_NODSISRALIGN ASM_CONST(0x0000001000000000) > +#define CPU_FTR_IABR ASM_CONST(0x0000002000000000) > +#define CPU_FTR_MMCRA ASM_CONST(0x0000004000000000) > +/* 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) > +#define CPU_FTR_MMCRA_SIHV ASM_CONST(0x0000080000000000) > +#define CPU_FTR_CTRL ASM_CONST(0x0000100000000000) > +#endif > + > +#ifndef __ASSEMBLY__ > + > +#define COMMON_USER_PPC64 (PPC_FEATURE_32 | PPC_FEATURE_64 | \ > + PPC_FEATURE_HAS_FPU | PPC_FEATURE_HAS_MMU) > + > +#define CPU_FTR_PPCAS_ARCH_V2_BASE (CPU_FTR_SLB | \ > + CPU_FTR_TLBIEL | CPU_FTR_NOEXECUTE | \ > + CPU_FTR_NODSISRALIGN | CPU_FTR_CTRL) > + > +/* iSeries doesn't support large pages */ > +#ifdef CONFIG_PPC_ISERIES > +#define CPU_FTR_PPCAS_ARCH_V2 (CPU_FTR_PPCAS_ARCH_V2_BASE) > +#else > +#define CPU_FTR_PPCAS_ARCH_V2 (CPU_FTR_PPCAS_ARCH_V2_BASE | > CPU_FTR_16M_PAGE) > +#endif /* CONFIG_PPC_ISERIES */ > + > +/* We only set the altivec features if the kernel was compiled > with altivec > + * support > + */ > +#ifdef CONFIG_ALTIVEC > +#define CPU_FTR_ALTIVEC_COMP CPU_FTR_ALTIVEC > +#define PPC_FEATURE_HAS_ALTIVEC_COMP PPC_FEATURE_HAS_ALTIVEC > +#else > +#define CPU_FTR_ALTIVEC_COMP 0 > +#define PPC_FEATURE_HAS_ALTIVEC_COMP 0 > +#endif > + > +/* We need to mark all pages as being coherent if we're SMP or we > + * have a 74[45]x and an MPC107 host bridge. > + */ > +#if defined(CONFIG_SMP) || defined(CONFIG_MPC10X_BRIDGE) > +#define CPU_FTR_COMMON CPU_FTR_NEED_COHERENT > +#else > +#define CPU_FTR_COMMON 0 > +#endif > + > +/* The powersave features NAP & DOZE seems to confuse BDI when > + debugging. So if a BDI is used, disable theses > + */ > +#ifndef CONFIG_BDI_SWITCH > +#define CPU_FTR_MAYBE_CAN_DOZE CPU_FTR_CAN_DOZE > +#define CPU_FTR_MAYBE_CAN_NAP CPU_FTR_CAN_NAP > +#else > +#define CPU_FTR_MAYBE_CAN_DOZE 0 > +#define CPU_FTR_MAYBE_CAN_NAP 0 > +#endif > + > +#define CLASSIC_PPC (!defined(CONFIG_8xx) && !defined(CONFIG_4xx) > && \ > + !defined(CONFIG_POWER3) && !defined(CONFIG_POWER4) && \ > + !defined(CONFIG_BOOKE)) > + > +enum { > + CPU_FTR_PPC601 = CPU_FTR_COMMON | CPU_FTR_601 | > CPU_FTR_HPTE_TABLE, > + CPU_FTR_603 = CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | > + CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB | > + CPU_FTR_MAYBE_CAN_NAP, > + CPU_FTR_604 = CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | > + CPU_FTR_USE_TB | CPU_FTR_604_PERF_MON | CPU_FTR_HPTE_TABLE, > + CPU_FTR_740_NOTAU = CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | > + CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB | CPU_FTR_L2CR | > + CPU_FTR_HPTE_TABLE | CPU_FTR_MAYBE_CAN_NAP, > + CPU_FTR_740 = CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | > + CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB | CPU_FTR_L2CR | > + CPU_FTR_TAU | CPU_FTR_HPTE_TABLE | CPU_FTR_MAYBE_CAN_NAP, > + CPU_FTR_750 = CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | > + CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB | CPU_FTR_L2CR | > + CPU_FTR_TAU | CPU_FTR_HPTE_TABLE | CPU_FTR_MAYBE_CAN_NAP, > + CPU_FTR_750FX1 = CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | > + CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB | CPU_FTR_L2CR | > + CPU_FTR_TAU | CPU_FTR_HPTE_TABLE | CPU_FTR_MAYBE_CAN_NAP | > + CPU_FTR_DUAL_PLL_750FX | CPU_FTR_NO_DPM, > + CPU_FTR_750FX2 = CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | > + CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB | CPU_FTR_L2CR | > + CPU_FTR_TAU | CPU_FTR_HPTE_TABLE | CPU_FTR_MAYBE_CAN_NAP | > + CPU_FTR_NO_DPM, > + CPU_FTR_750FX = CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | > + CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB | CPU_FTR_L2CR | > + CPU_FTR_TAU | CPU_FTR_HPTE_TABLE | CPU_FTR_MAYBE_CAN_NAP | > + CPU_FTR_DUAL_PLL_750FX | CPU_FTR_HAS_HIGH_BATS, > + CPU_FTR_750GX = CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_MAYBE_CAN_DOZE | > + CPU_FTR_USE_TB | CPU_FTR_L2CR | CPU_FTR_TAU | > + CPU_FTR_HPTE_TABLE | CPU_FTR_MAYBE_CAN_NAP | > + CPU_FTR_DUAL_PLL_750FX | CPU_FTR_HAS_HIGH_BATS, > + CPU_FTR_7400_NOTAU = CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | > + CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB | CPU_FTR_L2CR | > + CPU_FTR_ALTIVEC_COMP | CPU_FTR_HPTE_TABLE | > + CPU_FTR_MAYBE_CAN_NAP, > + CPU_FTR_7400 = CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | > + CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB | CPU_FTR_L2CR | > + CPU_FTR_TAU | CPU_FTR_ALTIVEC_COMP | CPU_FTR_HPTE_TABLE | > + CPU_FTR_MAYBE_CAN_NAP, > + CPU_FTR_7450_20 = CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | > + CPU_FTR_USE_TB | CPU_FTR_L2CR | CPU_FTR_ALTIVEC_COMP | > + CPU_FTR_L3CR | CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 | > + CPU_FTR_NEED_COHERENT, > + CPU_FTR_7450_21 = CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | > + CPU_FTR_USE_TB | > + CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_L2CR | CPU_FTR_ALTIVEC_COMP | > + CPU_FTR_L3CR | CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 | > + CPU_FTR_NAP_DISABLE_L2_PR | CPU_FTR_L3_DISABLE_NAP | > + CPU_FTR_NEED_COHERENT, > + CPU_FTR_7450_23 = CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | > + CPU_FTR_USE_TB | > + CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_L2CR | CPU_FTR_ALTIVEC_COMP | > + CPU_FTR_L3CR | CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 | > + CPU_FTR_NAP_DISABLE_L2_PR | CPU_FTR_NEED_COHERENT, > + CPU_FTR_7455_1 = CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | > + CPU_FTR_USE_TB | > + CPU_FTR_L2CR | CPU_FTR_ALTIVEC_COMP | CPU_FTR_L3CR | > + CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 | > CPU_FTR_HAS_HIGH_BATS | > + CPU_FTR_NEED_COHERENT, > + CPU_FTR_7455_20 = CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | > + CPU_FTR_USE_TB | > + CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_L2CR | CPU_FTR_ALTIVEC_COMP | > + CPU_FTR_L3CR | CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 | > + CPU_FTR_NAP_DISABLE_L2_PR | CPU_FTR_L3_DISABLE_NAP | > + CPU_FTR_NEED_COHERENT | CPU_FTR_HAS_HIGH_BATS, > + CPU_FTR_7455 = CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | > + CPU_FTR_USE_TB | > + CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_L2CR | CPU_FTR_ALTIVEC_COMP | > + CPU_FTR_L3CR | CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 | > + CPU_FTR_NAP_DISABLE_L2_PR | CPU_FTR_HAS_HIGH_BATS | > + CPU_FTR_NEED_COHERENT, > + CPU_FTR_7447_10 = CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | > + CPU_FTR_USE_TB | > + CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_L2CR | CPU_FTR_ALTIVEC_COMP | > + CPU_FTR_L3CR | CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 | > + CPU_FTR_NAP_DISABLE_L2_PR | CPU_FTR_HAS_HIGH_BATS | > + CPU_FTR_NEED_COHERENT | CPU_FTR_NO_BTIC, > + CPU_FTR_7447 = CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | > + CPU_FTR_USE_TB | > + CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_L2CR | CPU_FTR_ALTIVEC_COMP | > + CPU_FTR_L3CR | CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 | > + CPU_FTR_NAP_DISABLE_L2_PR | CPU_FTR_HAS_HIGH_BATS | > + CPU_FTR_NEED_COHERENT, > + CPU_FTR_7447A = CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | > + CPU_FTR_USE_TB | > + CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_L2CR | CPU_FTR_ALTIVEC_COMP | > + CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 | > + CPU_FTR_NAP_DISABLE_L2_PR | CPU_FTR_HAS_HIGH_BATS | > + CPU_FTR_NEED_COHERENT, > + CPU_FTR_82XX = CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | > + CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB, > + CPU_FTR_G2_LE = CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_MAYBE_CAN_DOZE | > + CPU_FTR_USE_TB | CPU_FTR_MAYBE_CAN_NAP | > CPU_FTR_HAS_HIGH_BATS, > + CPU_FTR_E300 = CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_MAYBE_CAN_DOZE | > + CPU_FTR_USE_TB | CPU_FTR_MAYBE_CAN_NAP | > CPU_FTR_HAS_HIGH_BATS, > + CPU_FTR_CLASSIC32 = CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | > + CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE, > + CPU_FTR_POWER3_32 = CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | > + CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE, > + CPU_FTR_POWER4_32 = CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | > + CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE, > + CPU_FTR_970_32 = CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | > + CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE | CPU_FTR_ALTIVEC_COMP | > + CPU_FTR_MAYBE_CAN_NAP, > + CPU_FTR_8XX = CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB, > + CPU_FTR_40X = CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB, > + CPU_FTR_44X = CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB, > + CPU_FTR_E200 = CPU_FTR_USE_TB, > + CPU_FTR_E500 = CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB, > + CPU_FTR_E500_2 = CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | > + CPU_FTR_BIG_PHYS, > + CPU_FTR_GENERIC_32 = CPU_FTR_COMMON, > +#ifdef __powerpc64__ > + CPU_FTR_POWER3 = CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | > + CPU_FTR_HPTE_TABLE | CPU_FTR_IABR, > + CPU_FTR_RS64 = CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | > + CPU_FTR_HPTE_TABLE | CPU_FTR_IABR | > + CPU_FTR_MMCRA | CPU_FTR_CTRL, > + CPU_FTR_POWER4 = CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | > + CPU_FTR_HPTE_TABLE | CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_MMCRA, > + CPU_FTR_PPC970 = 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_MMCRA, > + CPU_FTR_POWER5 = CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | > + CPU_FTR_HPTE_TABLE | CPU_FTR_PPCAS_ARCH_V2 | > + CPU_FTR_MMCRA | CPU_FTR_SMT | > + CPU_FTR_COHERENT_ICACHE | CPU_FTR_LOCKLESS_TLBIE | > + CPU_FTR_MMCRA_SIHV, > + CPU_FTR_CELL = CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | > + CPU_FTR_HPTE_TABLE | CPU_FTR_PPCAS_ARCH_V2 | > + CPU_FTR_ALTIVEC_COMP | CPU_FTR_MMCRA | CPU_FTR_SMT, > + CPU_FTR_COMPATIBLE = CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | > + CPU_FTR_HPTE_TABLE | CPU_FTR_PPCAS_ARCH_V2, > +#endif > + CPU_FTR_POSSIBLE = > +#if CLASSIC_PPC > + CPU_FTR_601 | CPU_FTR_603 | CPU_FTR_604 | CPU_FTR_740_NOTAU | > + CPU_FTR_740 | CPU_FTR_750 | CPU_FTR_750FX1 | > + CPU_FTR_750FX2 | CPU_FTR_750FX | CPU_FTR_750GX | > + CPU_FTR_7400_NOTAU | CPU_FTR_7400 | CPU_FTR_7450_20 | > + CPU_FTR_7450_21 | CPU_FTR_7450_23 | CPU_FTR_7455_1 | > + CPU_FTR_7455_20 | CPU_FTR_7455 | CPU_FTR_7447_10 | > + CPU_FTR_7447 | CPU_FTR_7447A | CPU_FTR_82XX | > + CPU_FTR_G2_LE | CPU_FTR_E300 | CPU_FTR_CLASSIC32 | > +#else > + CPU_FTR_GENERIC_32 | > +#endif > +#ifdef CONFIG_PPC64BRIDGE > + CPU_FTR_POWER3_32 | > +#endif > +#ifdef CONFIG_POWER4 > + CPU_FTR_POWER4_32 | CPU_FTR_970_32 | > +#endif > +#ifdef CONFIG_8xx > + CPU_FTR_8XX | > +#endif > +#ifdef CONFIG_40x > + CPU_FTR_40X | > +#endif > +#ifdef CONFIG_44x > + CPU_FTR_44X | > +#endif > +#ifdef CONFIG_FSL_BOOKE > + CPU_FTR_E200 | CPU_FTR_E500 | CPU_FTR_E500_2 | > +#endif > +#ifdef CONFIG_CPU_POWER3 > + CPU_FTR_POWER3 | > +#endif > +#ifdef CONFIG_CPU_RS64 > + CPU_FTR_RS64 | > +#endif > +#ifdef CONFIG_CPU_POWER4 > + CPU_FTR_POWER4 | > +#endif > +#ifdef CONFIG_CPU_PPC970 > + CPU_FTR_PPC970 | > +#endif > +#ifdef CONFIG_CPU_POWER5 > + CPU_FTR_POWER5 | > +#endif > +#ifdef CONFIG_CPU_CELL > + CPU_FTR_CELL | > +#endif > + 0, > + CPU_FTR_ALWAYS = > +#if CLASSIC_PPC > + CPU_FTR_601 & CPU_FTR_603 & CPU_FTR_604 & CPU_FTR_740_NOTAU & > + CPU_FTR_740 & CPU_FTR_750 & CPU_FTR_750FX1 & > + CPU_FTR_750FX2 & CPU_FTR_750FX & CPU_FTR_750GX & > + CPU_FTR_7400_NOTAU & CPU_FTR_7400 & CPU_FTR_7450_20 & > + CPU_FTR_7450_21 & CPU_FTR_7450_23 & CPU_FTR_7455_1 & > + CPU_FTR_7455_20 & CPU_FTR_7455 & CPU_FTR_7447_10 & > + CPU_FTR_7447 & CPU_FTR_7447A & CPU_FTR_82XX & > + CPU_FTR_G2_LE & CPU_FTR_E300 & CPU_FTR_CLASSIC32 & > +#else > + CPU_FTR_GENERIC_32 & > +#endif > +#ifdef CONFIG_PPC64BRIDGE > + CPU_FTR_POWER3_32 & > +#endif > +#ifdef CONFIG_POWER4 > + CPU_FTR_POWER4_32 & CPU_FTR_970_32 & > +#endif > +#ifdef CONFIG_8xx > + CPU_FTR_8XX & > +#endif > +#ifdef CONFIG_40x > + CPU_FTR_40X & > +#endif > +#ifdef CONFIG_44x > + CPU_FTR_44X & > +#endif > +#ifdef CONFIG_FSL_BOOKE > + CPU_FTR_E200 & CPU_FTR_E500 & CPU_FTR_E500_2 & > +#endif > +#ifdef CONFIG_CPU_POWER3 > + CPU_FTR_POWER3 & > +#endif > +#ifdef CONFIG_CPU_RS64 > + CPU_FTR_RS64 & > +#endif > +#ifdef CONFIG_CPU_POWER4 > + CPU_FTR_POWER4 & > +#endif > +#ifdef CONFIG_CPU_PPC970 > + CPU_FTR_PPC970 & > +#endif > +#ifdef CONFIG_CPU_POWER5 > + CPU_FTR_POWER5 & > +#endif > +#ifdef CONFIG_CPU_CELL > + CPU_FTR_CELL & > +#endif > + CPU_FTR_POSSIBLE, > +}; > + > +static inline int cpu_has_feature(unsigned long feature) > +{ > + return (CPU_FTR_ALWAYS & feature) || > + (CPU_FTR_POSSIBLE > +#ifndef __powerpc64__ > + & cur_cpu_spec[0]->cpu_features > +#else > + & cur_cpu_spec->cpu_features > +#endif > + & feature); > +} > + > +#endif /* __ASSEMBLY */ > + > +#ifdef __ASSEMBLY__ > + > +#define BEGIN_FTR_SECTION 98: > + > +#ifndef __powerpc64__ > +#define END_FTR_SECTION(msk, val) \ > +99: \ > + .section __ftr_fixup,"a"; \ > + .align 2; \ > + .long msk; \ > + .long val; \ > + .long 98b; \ > + .long 99b; \ > + .previous > +#else /* __powerpc64__ */ > +#define END_FTR_SECTION(msk, val) \ > +99: \ > + .section __ftr_fixup,"a"; \ > + .align 3; \ > + .llong msk; \ > + .llong val; \ > + .llong 98b; \ > + .llong 99b; \ > + .previous > +#endif /* __powerpc64__ */ > + > +#else > + > +#define BEGIN_FTR_SECTION "98:\n" > + > +#ifndef __powerpc64__ > +#define END_FTR_SECTION(msk, val) \ > +"99:\n" \ > +" .section __ftr_fixup,\"a\";\n" \ > +" .align 2;\n" \ > +" .long "#msk";\n" \ > +" .long "#val";\n" \ > +" .long 98b;\n" \ > +" .long 99b;\n" \ > +" .previous\n" > +#else /* __powerpc64__ */ > +#define END_FTR_SECTION(msk, val) \ > +"99:\n" \ > +" .section __ftr_fixup,\"a\";\n" \ > +" .align 3;\n" \ > +" .llong "#msk";\n" \ > +" .llong "#val";\n" \ > +" .llong 98b;\n" \ > +" .llong 99b;\n" \ > +" .previous\n" > +#endif /* __powerpc64__ */ > + > +#endif /* __ASSEMBLY__ */ > + > +#define END_FTR_SECTION_IFSET(msk) END_FTR_SECTION((msk), (msk)) > +#define END_FTR_SECTION_IFCLR(msk) END_FTR_SECTION((msk), 0) > + > +#endif /* __KERNEL__ */ > +#endif /* __ASM_POWERPC_CPUTABLE_H */ > Index: clean-cg/include/asm-ppc/cputable.h > =================================================================== > --- clean-cg.orig/include/asm-ppc/cputable.h > +++ /dev/null > @@ -1,128 +0,0 @@ > -/* > - * include/asm-ppc/cputable.h > - * > - * Copyright (C) 2001 Ben. 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. > - */ > - > -#ifndef __ASM_PPC_CPUTABLE_H > -#define __ASM_PPC_CPUTABLE_H > - > -/* Exposed to userland CPU features */ > -#define PPC_FEATURE_32 0x80000000 > -#define PPC_FEATURE_64 0x40000000 > -#define PPC_FEATURE_601_INSTR 0x20000000 > -#define PPC_FEATURE_HAS_ALTIVEC 0x10000000 > -#define PPC_FEATURE_HAS_FPU 0x08000000 > -#define PPC_FEATURE_HAS_MMU 0x04000000 > -#define PPC_FEATURE_HAS_4xxMAC 0x02000000 > -#define PPC_FEATURE_UNIFIED_CACHE 0x01000000 > -#define PPC_FEATURE_HAS_SPE 0x00800000 > -#define PPC_FEATURE_HAS_EFP_SINGLE 0x00400000 > -#define PPC_FEATURE_HAS_EFP_DOUBLE 0x00200000 > - > -#ifdef __KERNEL__ > - > -#ifndef __ASSEMBLY__ > - > -/* This structure can grow, it's real size is used by head.S code > - * via the mkdefs mecanism. > - */ > -struct cpu_spec; > - > -typedef void (*cpu_setup_t)(unsigned long offset, int cpu_nr, > struct cpu_spec* spec); > - > -struct cpu_spec { > - /* CPU is matched via (PVR & pvr_mask) == pvr_value */ > - unsigned int pvr_mask; > - unsigned int pvr_value; > - > - char *cpu_name; > - unsigned int cpu_features; /* Kernel features */ > - unsigned int cpu_user_features; /* Userland features */ > - > - /* cache line sizes */ > - 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 > - */ > - cpu_setup_t cpu_setup; > -}; > - > -extern struct cpu_spec cpu_specs[]; > -extern struct cpu_spec *cur_cpu_spec[]; > - > -static inline unsigned int cpu_has_feature(unsigned int feature) > -{ > - return cur_cpu_spec[0]->cpu_features & feature; > -} > - > -#endif /* __ASSEMBLY__ */ > - > -/* CPU kernel features */ > -#define CPU_FTR_SPLIT_ID_CACHE 0x00000001 > -#define CPU_FTR_L2CR 0x00000002 > -#define CPU_FTR_SPEC7450 0x00000004 > -#define CPU_FTR_ALTIVEC 0x00000008 > -#define CPU_FTR_TAU 0x00000010 > -#define CPU_FTR_CAN_DOZE 0x00000020 > -#define CPU_FTR_USE_TB 0x00000040 > -#define CPU_FTR_604_PERF_MON 0x00000080 > -#define CPU_FTR_601 0x00000100 > -#define CPU_FTR_HPTE_TABLE 0x00000200 > -#define CPU_FTR_CAN_NAP 0x00000400 > -#define CPU_FTR_L3CR 0x00000800 > -#define CPU_FTR_L3_DISABLE_NAP 0x00001000 > -#define CPU_FTR_NAP_DISABLE_L2_PR 0x00002000 > -#define CPU_FTR_DUAL_PLL_750FX 0x00004000 > -#define CPU_FTR_NO_DPM 0x00008000 > -#define CPU_FTR_HAS_HIGH_BATS 0x00010000 > -#define CPU_FTR_NEED_COHERENT 0x00020000 > -#define CPU_FTR_NO_BTIC 0x00040000 > -#define CPU_FTR_BIG_PHYS 0x00080000 > - > -#ifdef __ASSEMBLY__ > - > -#define BEGIN_FTR_SECTION 98: > - > -#define END_FTR_SECTION(msk, val) \ > -99: \ > - .section __ftr_fixup,"a"; \ > - .align 2; \ > - .long msk; \ > - .long val; \ > - .long 98b; \ > - .long 99b; \ > - .previous > - > -#else > - > -#define BEGIN_FTR_SECTION "98:\n" > -#define END_FTR_SECTION(msk, val) \ > -"99:\n" \ > -" .section __ftr_fixup,\"a\";\n" \ > -" .align 2;\n" \ > -" .long "#msk";\n" \ > -" .long "#val";\n" \ > -" .long 98b;\n" \ > -" .long 99b;\n" \ > -" .previous\n" > - > - > -#endif /* __ASSEMBLY__ */ > - > -#define END_FTR_SECTION_IFSET(msk) END_FTR_SECTION((msk), (msk)) > -#define END_FTR_SECTION_IFCLR(msk) END_FTR_SECTION((msk), 0) > - > -#endif /* __ASM_PPC_CPUTABLE_H */ > -#endif /* __KERNEL__ */ > - > From galak at freescale.com Thu Sep 15 06:14:21 2005 From: galak at freescale.com (Kumar Gala) Date: Wed, 14 Sep 2005 15:14:21 -0500 (CDT) Subject: [PATCH] powerpc: unified signature of timer_interrupt() between ppc32/ppc64 Message-ID: On ppc64 timer_interrupt() returned a value that was never used. Changed the ppc64 version of timer_interrupt() to no longer return a value so that the signatures between ppc32 & ppc64 match. This will simplify future merging of arch/powerpc. Signed-off-by: Kumar Gala --- commit 10b5180d0bd68bd485b2c93df22bbd094a9e0a2b tree d51d9c7b17f62fdd7741c44be6207b2bcb449fc0 parent 9df7c83f98a5479a1614cc77d138820a47a062ca author Kumar K. Gala Wed, 14 Sep 2005 14:56:42 -0500 committer Kumar K. Gala Wed, 14 Sep 2005 14:56:42 -0500 arch/ppc64/kernel/time.c | 4 +--- include/asm-ppc64/hw_irq.h | 2 +- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/arch/ppc64/kernel/time.c b/arch/ppc64/kernel/time.c --- a/arch/ppc64/kernel/time.c +++ b/arch/ppc64/kernel/time.c @@ -319,7 +319,7 @@ unsigned long tb_last_stamp __cacheline_ * timer_interrupt - gets called when the decrementer overflows, * with interrupts disabled. */ -int timer_interrupt(struct pt_regs * regs) +void timer_interrupt(struct pt_regs * regs) { int next_dec; unsigned long cur_tb; @@ -377,8 +377,6 @@ int timer_interrupt(struct pt_regs * reg } irq_exit(); - - return 1; } /* diff --git a/include/asm-ppc64/hw_irq.h b/include/asm-ppc64/hw_irq.h --- a/include/asm-ppc64/hw_irq.h +++ b/include/asm-ppc64/hw_irq.h @@ -16,7 +16,7 @@ #include #include -int timer_interrupt(struct pt_regs *); +extern void timer_interrupt(struct pt_regs *); extern void ppc_irq_dispatch_handler(struct pt_regs *regs, int irq); #ifdef CONFIG_PPC_ISERIES From arnd at arndb.de Thu Sep 15 09:58:09 2005 From: arnd at arndb.de (Arnd Bergmann) Date: Thu, 15 Sep 2005 01:58:09 +0200 Subject: [PATCH] powerpc: merge include/asm/cputable.h In-Reply-To: <06F93AF6-7AF8-4320-B9E3-CBF9EA333403@freescale.com> References: <200509090623.41889.arnd@arndb.de> <06F93AF6-7AF8-4320-B9E3-CBF9EA333403@freescale.com> Message-ID: <200509150158.10511.arnd@arndb.de> On Middeweken 14 September 2005 21:11, Kumar Gala wrote: > I not sure I understand what the introduction of the enum's gets us. > It doesn't have to be an enum, it could just as well be a #define, if we find that to be better in some way (maybe compile-time). The general idea is to convert run-time checks into compile-time checks in order to improve the running kernel. If you have // start code enum { FEATURE_1 = 1, FEATURE_2 = 2, PLATFORM_1 = FEATURE_1, PLATFORM_2 = FEATURE_2, PLATFORM_3 = FEATURE_1 | FEATURE_2, FEATURE_POSSIBLE = #ifdef CONFIG_PLATFORM_1 PLATFORM_1 | #endif #ifdef CONFIG_FEATURE_2 PLATFORM_2 | #endif #ifdef CONFIG_FEATURE_3 PLATFORM_3 | #endif 0, FEATURE_ALWAYS = #ifdef CONFIG_PLATFORM_1 PLATFORM_1 & #endif #ifdef CONFIG_PLATFORM_2 PLATFORM_2 & #endif #ifdef CONFIG_PLATFORM_3 PLATFORM_3 & #endif FEATURE_POSSIBLE, }; static inline int have_feature(unsigned long feature) { return (FEATURE_ALWAYS & feature) || (FEATURE_POSSIBLE & runtime_feature & feature); } int foo(); int bar(); int main(void) { if (have_feature(FEATURE_1)) return foo(); if (have_feature(FEATURE_2)) return bar(); return 0; } // end code Then gcc will produce optimal object code for any combination of CONFIG_PLATFORM_{1,2,3}. Of course I have to admit that the header file is not exactly elegant ;-). Arnd <>< From olof at lixom.net Thu Sep 15 14:02:56 2005 From: olof at lixom.net (Olof Johansson) Date: Wed, 14 Sep 2005 23:02:56 -0500 Subject: [PATCH] PPC64: Fix recent regression Message-ID: <20050915040256.GH3493@austin.ibm.com> Hi, Please consider for 2.6.14, it broke between 2.6.13 and 2.6.14-rc1: A recent patch changed the way the LPAR bit is checked during early boot. This resulted in a polarity change in a conditional branch without changing the branch, causing at least some legacy machines to not boot. Signed-off-by: Olof Johansson Index: 2.6/arch/ppc64/kernel/head.S =================================================================== --- 2.6.orig/arch/ppc64/kernel/head.S 2005-09-14 22:01:44.000000000 -0500 +++ 2.6/arch/ppc64/kernel/head.S 2005-09-14 22:46:05.000000000 -0500 @@ -1813,7 +1813,7 @@ _STATIC(start_here_multiplatform) ld r3,0(r3) lwz r3,PLATFORM(r3) /* r3 = platform flags */ andi. r3,r3,PLATFORM_LPAR /* Test if bit 0 is set (LPAR bit) */ - bne 98f + beq 98f /* eq=1 if result is 0 */ mfspr r3,PVR srwi r3,r3,16 cmpwi r3,0x37 /* SStar */ @@ -1834,7 +1834,7 @@ _STATIC(start_here_multiplatform) lwz r3,PLATFORM(r3) /* r3 = platform flags */ /* Test if bit 0 is set (LPAR bit) */ andi. r3,r3,PLATFORM_LPAR - bne 98f + bne 98f /* eq=1 if result is 0 */ LOADADDR(r6,_SDR1) /* Only if NOT LPAR */ sub r6,r6,r26 ld r6,0(r6) /* get the value of _SDR1 */ From paypal at email.paypal.com Wed Sep 14 06:48:29 2005 From: paypal at email.paypal.com (PayPal) Date: Tue, 13 Sep 2005 15:48:29 -0500 Subject: Account Review Team Message-ID: An HTML attachment was scrubbed... URL: http://ozlabs.org/pipermail/linuxppc64-dev/attachments/20050913/43078427/attachment.htm From torvalds at osdl.org Thu Sep 15 14:16:57 2005 From: torvalds at osdl.org (Linus Torvalds) Date: Wed, 14 Sep 2005 21:16:57 -0700 (PDT) Subject: [PATCH] PPC64: Fix recent regression In-Reply-To: <20050915040256.GH3493@austin.ibm.com> References: <20050915040256.GH3493@austin.ibm.com> Message-ID: Hmm.. The patch that you say broke things changed _two_ cases of cmpldi r3,PLATFORM_PSERIES_LPAR to andi. r3,r3,PLATFORM_LPAR (and changed one "andi. r3,r3,0x1" to use the symbolic form and also become a "andi. r3,r3,PLATFORM_LPAR"). However, your patch only changes one of the two "bne"s to "beq" (and added a comment for the case where we'd just turned 0x1 into the symbolic helper value). Hmm? I won't claim to understand the code, but it looks like there's one change missing. Or maybe an explanation of why that ones polarity stays the same. Linus On Wed, 14 Sep 2005, Olof Johansson wrote: > > Please consider for 2.6.14, it broke between 2.6.13 and 2.6.14-rc1: > > A recent patch changed the way the LPAR bit is checked during early > boot. This resulted in a polarity change in a conditional branch without > changing the branch, causing at least some legacy machines to not boot. > > > Signed-off-by: Olof Johansson > > Index: 2.6/arch/ppc64/kernel/head.S > =================================================================== > --- 2.6.orig/arch/ppc64/kernel/head.S 2005-09-14 22:01:44.000000000 -0500 > +++ 2.6/arch/ppc64/kernel/head.S 2005-09-14 22:46:05.000000000 -0500 > @@ -1813,7 +1813,7 @@ _STATIC(start_here_multiplatform) > ld r3,0(r3) > lwz r3,PLATFORM(r3) /* r3 = platform flags */ > andi. r3,r3,PLATFORM_LPAR /* Test if bit 0 is set (LPAR bit) */ > - bne 98f > + beq 98f /* eq=1 if result is 0 */ > mfspr r3,PVR > srwi r3,r3,16 > cmpwi r3,0x37 /* SStar */ > @@ -1834,7 +1834,7 @@ _STATIC(start_here_multiplatform) > lwz r3,PLATFORM(r3) /* r3 = platform flags */ > /* Test if bit 0 is set (LPAR bit) */ > andi. r3,r3,PLATFORM_LPAR > - bne 98f > + bne 98f /* eq=1 if result is 0 */ > LOADADDR(r6,_SDR1) /* Only if NOT LPAR */ > sub r6,r6,r26 > ld r6,0(r6) /* get the value of _SDR1 */ > From olof at lixom.net Thu Sep 15 14:20:54 2005 From: olof at lixom.net (Olof Johansson) Date: Wed, 14 Sep 2005 23:20:54 -0500 Subject: [PATCH] PPC64: Fix recent regression In-Reply-To: References: <20050915040256.GH3493@austin.ibm.com> Message-ID: <20050915042054.GI3493@austin.ibm.com> On Wed, Sep 14, 2005 at 09:16:57PM -0700, Linus Torvalds wrote: > > Hmm.. The patch that you say broke things changed _two_ cases of > > cmpldi r3,PLATFORM_PSERIES_LPAR > > to > > andi. r3,r3,PLATFORM_LPAR > > (and changed one "andi. r3,r3,0x1" to use the symbolic form and also > become a "andi. r3,r3,PLATFORM_LPAR"). > > However, your patch only changes one of the two "bne"s to "beq" (and > added a comment for the case where we'd just turned 0x1 into the symbolic > helper value). Hmm? > > I won't claim to understand the code, but it looks like there's one change > missing. Or maybe an explanation of why that ones polarity stays the same. The reason is that the second change just changes the hard-coded 0x1 to PLATFORM_LPAR, not the kind of comparison. It got me the first time too, I changed both and couldn't understand why it still wouldn't boot. i.e. cmpldi would give eq=1 if the comparison matched, but the andi. is eq=1 if the result is 0. That's why I added the /* eq=1... */ comments. -Olof From herbert at 13thfloor.at Thu Sep 15 15:35:08 2005 From: herbert at 13thfloor.at (Herbert Poetzl) Date: Thu, 15 Sep 2005 07:35:08 +0200 Subject: [PATCH] ppc64: speedup cmpxchg In-Reply-To: <20050906030558.GK6945@krispykreme> References: <20050906030558.GK6945@krispykreme> Message-ID: <20050915053508.GC30950@MAIL.13thfloor.at> On Tue, Sep 06, 2005 at 01:05:58PM +1000, Anton Blanchard wrote: > > 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. hmm, isn't that removing an implicit typecheck? maybe adding register and/or improving gcc would be a better solution here? best, Herbert > 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 > _______________________________________________ > Linuxppc64-dev mailing list > Linuxppc64-dev at ozlabs.org > https://ozlabs.org/mailman/listinfo/linuxppc64-dev From sfr at canb.auug.org.au Thu Sep 15 16:04:30 2005 From: sfr at canb.auug.org.au (Stephen Rothwell) Date: Thu, 15 Sep 2005 16:04:30 +1000 Subject: [PATCH] powerpc: don't execute a temporary comment Message-ID: <20050915160430.550d02ed.sfr@canb.auug.org.au> Signed-off-by: Stephen Rothwell --- arch/ppc/Makefile | 2 +- arch/ppc64/Makefile | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) -- Cheers, Stephen Rothwell sfr at canb.auug.org.au http://www.canb.auug.org.au/~sfr/ 86f7688825b1f1e6fa4c43bce001b2a232f7d1bc diff --git a/arch/ppc/Makefile b/arch/ppc/Makefile --- a/arch/ppc/Makefile +++ b/arch/ppc/Makefile @@ -102,9 +102,9 @@ define archhelp @echo ' *_defconfig - Select default config from arch/$(ARCH)/ppc/configs' endef +# arch/$(ARCH)/include is a temporary hack until we have migrated to asm-powerpc archclean: $(Q)$(MAKE) $(clean)=arch/ppc/boot - # Temporary hack until we have migrated to asm-powerpc $(Q)rm -rf arch/$(ARCH)/include archprepare: checkbin diff --git a/arch/ppc64/Makefile b/arch/ppc64/Makefile --- a/arch/ppc64/Makefile +++ b/arch/ppc64/Makefile @@ -113,9 +113,9 @@ defaultimage-$(CONFIG_PPC_ISERIES) := vm KBUILD_IMAGE := $(defaultimage-y) all: $(KBUILD_IMAGE) +# arch/$(ARCH)/include is a temporary hack until we have migrated to asm-powerpc archclean: $(Q)$(MAKE) $(clean)=$(boot) - # Temporary hack until we have migrated to asm-powerpc $(Q)rm -rf arch/$(ARCH)/include From paulus at samba.org Thu Sep 15 20:54:50 2005 From: paulus at samba.org (Paul Mackerras) Date: Thu, 15 Sep 2005 20:54:50 +1000 Subject: [PATCH] powerpc: Merged ppc_asm.h In-Reply-To: References: Message-ID: <17193.21242.137018.20909@cargo.ozlabs.ibm.com> Kumar Gala writes: > What's the status of applying this to your tree? > > http://patchwork.ozlabs.org/linuxppc/patch?id=2330 I'm going to start up a ppc-merge.git tree on kernel.org soon. I don't intend to send any more 32/64 merge patches to Linus until after 2.6.14 is out. Regards, Paul. From paulus at samba.org Thu Sep 15 21:09:48 2005 From: paulus at samba.org (Paul Mackerras) Date: Thu, 15 Sep 2005 21:09:48 +1000 Subject: PATCH powerpc: Merge asm-ppc*/sections.h In-Reply-To: <1126705588.14036.10.camel@cashmere.sps.mot.com> References: <1126644202.11056.59.camel@cashmere.sps.mot.com> <200509140435.21916.arnd@arndb.de> <1126705588.14036.10.camel@cashmere.sps.mot.com> Message-ID: <17193.22140.962651.122114@cargo.ozlabs.ibm.com> Jon Loeliger writes: > In the Grand Scheme of Things, removing things and making them > simpler seems a lofty goal. :-) Anyone know of any pitfalls that > await me if I try to remove these sections, a la pmac and friends? You'll probably get most objection from the PReP users, for whom getting back a few hundred kB is a big deal. (Maybe we should just buy both of them a G5 or something. 8-) > And I assume that the obvious mappings can take place (ie, that > "pmac.text" can just be placed in regular .text, etc), right? Yes. Paul. From paulus at samba.org Thu Sep 15 21:13:08 2005 From: paulus at samba.org (Paul Mackerras) Date: Thu, 15 Sep 2005 21:13:08 +1000 Subject: [PATCH] Add PTRACE_{GET|SET}VRREGS In-Reply-To: References: Message-ID: <17193.22340.716728.682583@cargo.ozlabs.ibm.com> Kumar Gala writes: > Which is the same for ppc32 and ppc64, correct? Yes. However... 64-bit book E has a 64-bit USPRG0 register, which is the same SPR number as VRSAVE, right? So will 64-bit book E want to use the VRSAVE context switch machinery for USPRG0? As for the ptrace patch, I didn't want to include an unrelated cleanup (that of changing the type of thread_struct.vrsave) in that patch. Paul. From jimix at watson.ibm.com Thu Sep 15 22:42:19 2005 From: jimix at watson.ibm.com (Jimi Xenidis) Date: Thu, 15 Sep 2005 08:42:19 -0400 Subject: [PATCH] PPC64: Fix recent regression In-Reply-To: <20050915042054.GI3493@austin.ibm.com> References: <20050915040256.GH3493@austin.ibm.com> <20050915042054.GI3493@austin.ibm.com> Message-ID: <17193.27691.491343.74233@kitch0.watson.ibm.com> >>>>> "OJ" == Olof Johansson writes: OJ> On Wed, Sep 14, 2005 at 09:16:57PM -0700, Linus Torvalds wrote: >> >> Hmm.. The patch that you say broke things changed _two_ cases of >> >> cmpldi r3,PLATFORM_PSERIES_LPAR >> >> to >> >> andi. r3,r3,PLATFORM_LPAR >> >> (and changed one "andi. r3,r3,0x1" to use the symbolic form and also >> become a "andi. r3,r3,PLATFORM_LPAR"). Yes Linus, there were 3 changes overall, the first 2 should have had the polarity changed (my apologies). Olaf's patch only changes the first. The third is explain by Olaf's in his reply. Olaf, good catch! >> I won't claim to understand the code, but it looks like there's one change >> missing. Or maybe an explanation of why that ones polarity stays the same. Operations "addic.", "andi.", and "andis." set the CR bits to the result signed compared with 0 (which is eq=1). So perhaps a more "descriptive" mnemonic would be "bz" but thats not available. Here is a patch that hopefully explains them all wihout knowing that CR bits. Signed-off-by: Jimi Xenidis diff -r 4f2651e19e59 arch/ppc64/kernel/head.S --- a/arch/ppc64/kernel/head.S Wed Sep 14 15:48:20 2005 +++ b/arch/ppc64/kernel/head.S Thu Sep 15 08:25:47 2005 @@ -1649,7 +1649,7 @@ ld r3,0(r3) lwz r3,PLATFORM(r3) /* r3 = platform flags */ andi. r3,r3,PLATFORM_LPAR /* Test if bit 0 is set (LPAR bit) */ - bne 98f + beq 98f /* branch if result is 0 */ mfspr r3,PVR srwi r3,r3,16 cmpwi r3,0x37 /* SStar */ @@ -1813,7 +1813,7 @@ ld r3,0(r3) lwz r3,PLATFORM(r3) /* r3 = platform flags */ andi. r3,r3,PLATFORM_LPAR /* Test if bit 0 is set (LPAR bit) */ - bne 98f + beq 98f /* branch if result is 0 */ mfspr r3,PVR srwi r3,r3,16 cmpwi r3,0x37 /* SStar */ @@ -1834,7 +1834,7 @@ lwz r3,PLATFORM(r3) /* r3 = platform flags */ /* Test if bit 0 is set (LPAR bit) */ andi. r3,r3,PLATFORM_LPAR - bne 98f + bne 98f /* branch if result is !0 */ LOADADDR(r6,_SDR1) /* Only if NOT LPAR */ sub r6,r6,r26 ld r6,0(r6) /* get the value of _SDR1 */ From linville at tuxdriver.com Fri Sep 16 00:07:01 2005 From: linville at tuxdriver.com (John W. Linville) Date: Thu, 15 Sep 2005 10:07:01 -0400 Subject: [PATCH] powerpc: don't execute a temporary comment In-Reply-To: <20050915160430.550d02ed.sfr@canb.auug.org.au> References: <20050915160430.550d02ed.sfr@canb.auug.org.au> Message-ID: <20050915140659.GA17670@tuxdriver.com> On Thu, Sep 15, 2005 at 04:04:30PM +1000, Stephen Rothwell wrote: > --- a/arch/ppc/Makefile > +++ b/arch/ppc/Makefile > @@ -102,9 +102,9 @@ define archhelp > @echo ' *_defconfig - Select default config from arch/$(ARCH)/ppc/configs' > endef > > +# arch/$(ARCH)/include is a temporary hack until we have migrated to asm-powerpc > archclean: > $(Q)$(MAKE) $(clean)=arch/ppc/boot > - # Temporary hack until we have migrated to asm-powerpc > $(Q)rm -rf arch/$(ARCH)/include > > archprepare: checkbin Why is this helpful? Better in general to keep the commment near the code, no? John -- John W. Linville linville at tuxdriver.com From kumar.gala at freescale.com Fri Sep 16 00:30:04 2005 From: kumar.gala at freescale.com (Kumar Gala) Date: Thu, 15 Sep 2005 09:30:04 -0500 Subject: [PATCH] Add PTRACE_{GET|SET}VRREGS In-Reply-To: <17193.22340.716728.682583@cargo.ozlabs.ibm.com> References: <17193.22340.716728.682583@cargo.ozlabs.ibm.com> Message-ID: <51642516-8D80-47F4-9A99-FD29222DAF78@freescale.com> On Sep 15, 2005, at 6:13 AM, Paul Mackerras wrote: > Kumar Gala writes: > > >> Which is the same for ppc32 and ppc64, correct? >> > > Yes. However... 64-bit book E has a 64-bit USPRG0 register, which is > the same SPR number as VRSAVE, right? So will 64-bit book E want to > use the VRSAVE context switch machinery for USPRG0? Well, since we dont bother with USPRG0 on book-e proc's today I'm ok with considering it a 32-bit register intended for VRSAVE functionality only. > As for the ptrace patch, I didn't want to include an unrelated cleanup > (that of changing the type of thread_struct.vrsave) in that patch. Understood. - kumar From kumar.gala at freescale.com Fri Sep 16 00:56:36 2005 From: kumar.gala at freescale.com (Kumar Gala) Date: Thu, 15 Sep 2005 09:56:36 -0500 Subject: [patch 4/5] ppc64: Add definitions for new PTRACE calls In-Reply-To: <2EB7CE7E-6BEF-4E10-8A0A-42D39FA732CE@freescale.com> References: <2EB7CE7E-6BEF-4E10-8A0A-42D39FA732CE@freescale.com> Message-ID: <4D5DCE55-024C-4140-8393-31F8D528FC60@freescale.com> Paul, I'm really concerned about the fact that this got merged into linus's tree so fast w/o any further discussion. I'm concerned because we've added a public API to the kernel and there wasn't any discussion of it on list once I brought up an issue. Additionally, I'm concerned because it appears we are adding features to ppc64 only w/o concern about ppc32. We currently have 3 HW debug models on PPC from what I can tell and what has been added only comprehends one of them: 1. basic ppc32/ppc64 IABR/DABR 2. extended 603 IABR/DABR + IBCR/DBCR (ranges, additional comparison functions) 3. Book-E debug The proposed 16 IABR/DABR doesn't seem really useful in light of #2 & #3. Also, how does the debugger know how many iabr's/dabr's a given kernel supports. I'm ok if we all agree that we only support exact matches, but I do think that we need to figure out what to do about the 3 low order bits on DABR and how that would map to something on book-e. I believe Book-E data address matches are byte level matches. Also, we really should have some mechanism to report number of IABRs & DABRs that the HW supports. Anyways, I think this needs more discussion and we should remove the recently added PTRACE_GET_DEBUGREG/PTRACE_SET_DEBUGREG APIs from 2.6.14. Until we decide what this means for ALL powerpc's. - kumar On Sep 10, 2005, at 12:29 PM, Gala Kumar K.-galak wrote: > We really need further discussion on this. Book-E has a completely > different HW debug model which this patch only partially comprehend. > Is GDB being extended to support branch stepping? > > - kumar > > On Sep 10, 2005, at 1:01 AM, Anton Blanchard wrote: > > >> - Add PTRACE_BRANCHSTEP. Like PTRACE_SINGLESTEP but takes an >> exception at every branch. This might be worth putting in >> include/linux/ptrace.h if other architectures are interested. >> >> - Add PTRACE_GET_DEBUGREG/PTRACE_SET_DEBUGREG. The definition is >> as follows: >> >> /* >> * Get or set a debug register. The first 16 are DABR registers and >> the >> * second 16 are IABR registers. >> */ >> #define PTRACE_GET_DEBUGREG 25 >> #define PTRACE_SET_DEBUGREG 26 >> >> DABR == data breakpoint and IABR = instruction breakpoint in IBM >> speak. We could split out the IABR into 2 more ptrace calls but I >> figured there was no need and 16 DABR registers should be more >> than enough (POWER4/POWER5 have one). >> >> - Add 2 new SIGTRAP si_codes: TRAP_HWBKPT and TRAP_BRANCH. I couldnt >> find any standards on either of these so I copied what ia64 is >> doing. Again this might be better placed in >> include/asm-generic/siginfo.h >> >> Signed-off-by: Anton Blanchard >> --- >> >> Index: build/include/asm-ppc/ptrace.h >> =================================================================== >> --- build.orig/include/asm-ppc/ptrace.h 2005-09-10 >> 14:26:25.000000000 >> +1000 >> +++ build/include/asm-ppc/ptrace.h 2005-09-10 14:27:49.000000000 >> +1000 >> @@ -142,4 +142,13 @@ >> #define PTRACE_GETEVRREGS 20 >> #define PTRACE_SETEVRREGS 21 >> >> +#define PTRACE_BRANCHSTEP 22 >> + >> +/* >> + * Get or set a debug register. The first 16 are DABR registers >> and the >> + * second 16 are IABR registers. >> + */ >> +#define PTRACE_GET_DEBUGREG 25 >> +#define PTRACE_SET_DEBUGREG 26 >> + >> #endif >> Index: build/include/asm-ppc64/ptrace.h >> =================================================================== >> --- build.orig/include/asm-ppc64/ptrace.h 2005-09-10 >> 14:28:44.000000000 +1000 >> +++ build/include/asm-ppc64/ptrace.h 2005-09-10 14:28:58.000000000 >> +1000 >> @@ -189,6 +189,15 @@ >> #define PTRACE_SETEVRREGS 21 >> #endif >> >> +#define PTRACE_BRANCHSTEP 22 >> + >> +/* >> + * Get or set a debug register. The first 16 are DABR registers >> and the >> + * second 16 are IABR registers. >> + */ >> +#define PTRACE_GET_DEBUGREG 25 >> +#define PTRACE_SET_DEBUGREG 26 >> + >> /* Additional PTRACE requests implemented on PowerPC. */ >> #define PPC_PTRACE_GETREGS 0x99 /* Get GPRs 0 - 31 */ >> #define PPC_PTRACE_SETREGS 0x98 /* Set GPRs 0 - 31 */ >> Index: build/include/asm-powerpc/siginfo.h >> =================================================================== >> --- build.orig/include/asm-powerpc/siginfo.h 2005-09-10 >> 13:29:48.000000000 +1000 >> +++ build/include/asm-powerpc/siginfo.h 2005-09-10 >> 13:29:54.000000000 >> +1000 >> @@ -15,4 +15,12 @@ >> >> #include >> >> +/* >> + * SIGTRAP si_codes >> + */ >> +#define TRAP_BRANCH (__SI_FAULT|3) /* process taken branch >> trap */ >> +#define TRAP_HWBKPT (__SI_FAULT|4) /* hardware breakpoint or >> watchpoint */ >> +#undef NSIGTRAP >> +#define NSIGTRAP 4 >> + >> #endif /* _ASM_POWERPC_SIGINFO_H */ >> >> -- >> >> _______________________________________________ >> Linuxppc64-dev mailing list >> Linuxppc64-dev at ozlabs.org >> https://ozlabs.org/mailman/listinfo/linuxppc64-dev >> >> > > _______________________________________________ > Linuxppc64-dev mailing list > Linuxppc64-dev at ozlabs.org > https://ozlabs.org/mailman/listinfo/linuxppc64-dev > From kumar.gala at freescale.com Fri Sep 16 01:12:02 2005 From: kumar.gala at freescale.com (Kumar Gala) Date: Thu, 15 Sep 2005 10:12:02 -0500 Subject: non-inlined versions of local_irq* Message-ID: Anyone know why on ppc32 we have non-inlined versions of: extern void local_irq_enable(void); extern void local_irq_disable(void); extern void local_irq_restore(unsigned long); extern void local_save_flags_ptr(unsigned long *); From looking at the code they are never used. Just wondering if this was for debug or some other reason. - kumar From jdl at freescale.com Fri Sep 16 03:07:51 2005 From: jdl at freescale.com (Jon Loeliger) Date: Thu, 15 Sep 2005 12:07:51 -0500 Subject: PATCH powerpc: Merge asm-ppc*/sections.h In-Reply-To: <17193.22140.962651.122114@cargo.ozlabs.ibm.com> References: <1126644202.11056.59.camel@cashmere.sps.mot.com> <200509140435.21916.arnd@arndb.de> <1126705588.14036.10.camel@cashmere.sps.mot.com> <17193.22140.962651.122114@cargo.ozlabs.ibm.com> Message-ID: <1126804069.17442.32.camel@cashmere.sps.mot.com> On Thu, 2005-09-15 at 06:09, Paul Mackerras wrote: > Jon Loeliger writes: > > > In the Grand Scheme of Things, removing things and making them > > simpler seems a lofty goal. :-) Anyone know of any pitfalls that > > await me if I try to remove these sections, a la pmac and friends? > > You'll probably get most objection from the PReP users, for whom > getting back a few hundred kB is a big deal. (Maybe we should just > buy both of them a G5 or something. 8-) OK. I dug up some data. Compiled ppc32 *_defconfig across the page. Section down the left. All numbers are 4K pages. OF is the so-called "__openfirmware" section. pmac ibmchrp stx_gp3 mpc8555_cds -------------------------------------- pmac 10 7 0 0 prep 2 2 0 0 chrp 1 1 0 0 OF 2 1 0 0 init 47 46 23 32 Over in arch/ppc/mm/init.c this gets done: printk ("Freeing unused kernel memory:"); FREESEC(init); if (_machine != _MACH_Pmac) FREESEC(pmac); if (_machine != _MACH_chrp) FREESEC(chrp); if (_machine != _MACH_prep) FREESEC(prep); if (!have_of) FREESEC(openfirmware); Toss sections that don't match your _machine. Everyone tosses init section. Embedded boards will take no hit. Ppc64 currently does not have these special sections and hence will see no impact here. That is the cost of removing these section identifiers. So, is everyone prepared to live with these few pages of occasional increased image size and remove the special sections? Thanks, jdl From kumar.gala at freescale.com Fri Sep 16 03:28:18 2005 From: kumar.gala at freescale.com (Kumar Gala) Date: Thu, 15 Sep 2005 12:28:18 -0500 Subject: PATCH powerpc: Merge asm-ppc*/sections.h In-Reply-To: <17193.22140.962651.122114@cargo.ozlabs.ibm.com> References: <17193.22140.962651.122114@cargo.ozlabs.ibm.com> Message-ID: <70CB8719-62AB-487C-8FE6-9B5242319283@freescale.com> On Sep 15, 2005, at 6:09 AM, Paul Mackerras wrote: > Jon Loeliger writes: > > >> In the Grand Scheme of Things, removing things and making them >> simpler seems a lofty goal. :-) Anyone know of any pitfalls that >> await me if I try to remove these sections, a la pmac and friends? >> > > You'll probably get most objection from the PReP users, for whom > getting back a few hundred kB is a big deal. (Maybe we should just > buy both of them a G5 or something. 8-) If they care that much they should submit a patch to build a PReP specific kernel that doesn't include this stuff. And while you are buying G5's for people send one my way :) I vote that we just get ride of this sections stuff for prep, pmac, of, chrp and if we want to reduce the code size make it a compile choice to build specific kernel's that dont include the crap that the others need. (especially based on the numbers that Jon has posted for size). - kumar From kumar.gala at freescale.com Fri Sep 16 03:44:29 2005 From: kumar.gala at freescale.com (Kumar Gala) Date: Thu, 15 Sep 2005 12:44:29 -0500 Subject: [PATCH] powerpc: merge include/asm/cputable.h In-Reply-To: <200509150158.10511.arnd@arndb.de> References: <200509150158.10511.arnd@arndb.de> Message-ID: I get the idea now, how about we make CPU_FTR_ALWAYS & CPU_FTR_POSSIBLE just #defines and leave it to various sub-archs to define CPU_FTR_POSSIBLE if they want to. I see the classes of for FTR_POSSIBLE: CLASSIC_PPC, 8xx, 4xx, FSL- BOOKE, PPC64 (maybe more subclasses here). The hugh enum while useful, is just really ugly and I can't believe it's worth it for the ~60 cases we are using cpu_has_feature() in. - kumar On Sep 14, 2005, at 6:58 PM, Arnd Bergmann wrote: > On Middeweken 14 September 2005 21:11, Kumar Gala wrote: > >> I not sure I understand what the introduction of the enum's gets us. >> >> > It doesn't have to be an enum, it could just as well be a #define, > if we find that to be better in some way (maybe compile-time). > > The general idea is to convert run-time checks into compile-time > checks in order to improve the running kernel. If you have > > // start code > enum { > FEATURE_1 = 1, > FEATURE_2 = 2, > PLATFORM_1 = FEATURE_1, > PLATFORM_2 = FEATURE_2, > PLATFORM_3 = FEATURE_1 | FEATURE_2, > FEATURE_POSSIBLE = > #ifdef CONFIG_PLATFORM_1 > PLATFORM_1 | > #endif > #ifdef CONFIG_FEATURE_2 > PLATFORM_2 | > #endif > #ifdef CONFIG_FEATURE_3 > PLATFORM_3 | > #endif > 0, > FEATURE_ALWAYS = > #ifdef CONFIG_PLATFORM_1 > PLATFORM_1 & > #endif > #ifdef CONFIG_PLATFORM_2 > PLATFORM_2 & > #endif > #ifdef CONFIG_PLATFORM_3 > PLATFORM_3 & > #endif > FEATURE_POSSIBLE, > }; > > static inline int have_feature(unsigned long feature) > { > return (FEATURE_ALWAYS & feature) || > (FEATURE_POSSIBLE & runtime_feature & feature); > } > > int foo(); > int bar(); > int main(void) > { > if (have_feature(FEATURE_1)) > return foo(); > if (have_feature(FEATURE_2)) > return bar(); > return 0; > } > // end code > > Then gcc will produce optimal object code for any combination > of CONFIG_PLATFORM_{1,2,3}. Of course I have to admit that the > header file is not exactly elegant ;-). > > Arnd <>< > From paubert at iram.es Fri Sep 16 06:57:09 2005 From: paubert at iram.es (Gabriel Paubert) Date: Thu, 15 Sep 2005 22:57:09 +0200 Subject: PATCH powerpc: Merge asm-ppc*/sections.h In-Reply-To: <17193.22140.962651.122114@cargo.ozlabs.ibm.com> References: <1126644202.11056.59.camel@cashmere.sps.mot.com> <200509140435.21916.arnd@arndb.de> <1126705588.14036.10.camel@cashmere.sps.mot.com> <17193.22140.962651.122114@cargo.ozlabs.ibm.com> Message-ID: <20050915205709.GA31156@iram.es> On Thu, Sep 15, 2005 at 09:09:48PM +1000, Paul Mackerras wrote: > Jon Loeliger writes: > > > In the Grand Scheme of Things, removing things and making them > > simpler seems a lofty goal. :-) Anyone know of any pitfalls that > > await me if I try to remove these sections, a la pmac and friends? > > You'll probably get most objection from the PReP users, for whom > getting back a few hundred kB is a big deal. (Maybe we should just > buy both of them a G5 or something. 8-) Well, we have something like 20 or 25 VME machines controlling experiments here, some with only 16Mb of RAM. The lifetime of these systems is often of the order of 20 years (we shall finally get rid of our TMS9900 processors with 32kB in November, they were bought in 1982 I believe). So yes, I object strongly object if I don't have a way of removing useless PMAC code. The kernel is already very bloated compared with the 2.2 we started with, which was well below 1MB with the minimal setup: serial console, root on NFS, no swap, some locally modules to control the PCI<->VME bridge and what is behind on the VME bus. Gabriel From dan at embeddededge.com Fri Sep 16 07:21:57 2005 From: dan at embeddededge.com (Dan Malek) Date: Thu, 15 Sep 2005 17:21:57 -0400 Subject: PATCH powerpc: Merge asm-ppc*/sections.h In-Reply-To: <20050915205709.GA31156@iram.es> References: <1126644202.11056.59.camel@cashmere.sps.mot.com> <200509140435.21916.arnd@arndb.de> <1126705588.14036.10.camel@cashmere.sps.mot.com> <17193.22140.962651.122114@cargo.ozlabs.ibm.com> <20050915205709.GA31156@iram.es> Message-ID: On Sep 15, 2005, at 4:57 PM, Gabriel Paubert wrote: > So yes, I object strongly object if I don't have a way > of removing useless PMAC code. Or, any other code that isn't appropriate. People have always laughed at me for trying to save bytes here and there, but I have to say there are many, many more PowerPCs running Linux in 32M of memory than 2G of memory. Using the smallest amount of memory to solve the problem is still the norm, and when you are competing against other architectures that can run in less memory, you can't win. Of course, as Gabriel said, I also see legacy systems that want to change from another OS to Linux, but they have 16M soldered on the board (which was _way_ more than necessary to run that other OS), and that isn't going to change. Please, we have to be sensitive to configuring systems to minimize the resource requirements for Linux. Thanks. -- Dan From paulus at samba.org Fri Sep 16 08:00:35 2005 From: paulus at samba.org (Paul Mackerras) Date: Fri, 16 Sep 2005 08:00:35 +1000 Subject: PATCH powerpc: Merge asm-ppc*/sections.h In-Reply-To: <20050915205709.GA31156@iram.es> References: <1126644202.11056.59.camel@cashmere.sps.mot.com> <200509140435.21916.arnd@arndb.de> <1126705588.14036.10.camel@cashmere.sps.mot.com> <17193.22140.962651.122114@cargo.ozlabs.ibm.com> <20050915205709.GA31156@iram.es> Message-ID: <17193.61187.613745.15444@cargo.ozlabs.ibm.com> Gabriel Paubert writes: > So yes, I object strongly object if I don't have a way > of removing useless PMAC code. The kernel is already very > bloated compared with the 2.2 we started with, which was > well below 1MB with the minimal setup: serial console, root > on NFS, no swap, some locally modules to control the PCI<->VME > bridge and what is behind on the VME bus. I assume you compile custom kernels for these machines, so you're happy with using config options to remove the code you don't want? Having the .pmac.text, .prep.text etc. sections lets us remove unneeded code at runtime, but it sounds like that isn't actually the issue for you (i.e. you don't have a need to run the same kernel on both a pmac and a prep). Paul. From paubert at iram.es Fri Sep 16 08:37:02 2005 From: paubert at iram.es (Gabriel Paubert) Date: Fri, 16 Sep 2005 00:37:02 +0200 Subject: PATCH powerpc: Merge asm-ppc*/sections.h In-Reply-To: <17193.61187.613745.15444@cargo.ozlabs.ibm.com> References: <1126644202.11056.59.camel@cashmere.sps.mot.com> <200509140435.21916.arnd@arndb.de> <1126705588.14036.10.camel@cashmere.sps.mot.com> <17193.22140.962651.122114@cargo.ozlabs.ibm.com> <20050915205709.GA31156@iram.es> <17193.61187.613745.15444@cargo.ozlabs.ibm.com> Message-ID: <20050915223702.GA322@iram.es> On Fri, Sep 16, 2005 at 08:00:35AM +1000, Paul Mackerras wrote: > Gabriel Paubert writes: > > > So yes, I object strongly object if I don't have a way > > of removing useless PMAC code. The kernel is already very > > bloated compared with the 2.2 we started with, which was > > well below 1MB with the minimal setup: serial console, root > > on NFS, no swap, some locally modules to control the PCI<->VME > > bridge and what is behind on the VME bus. > > I assume you compile custom kernels for these machines, so you're > happy with using config options to remove the code you don't want? Yes, and I have no problems with it. Actually I even wrote my own bootloader, which reorganizes the host bridge memory map to make the MVME 2400/2600 have a more CHRP-like map, like the MVME5100. The reason is that people with VME systems like sparsely populated huge memory space and the 1GB IO space of Prep came in the way. Actually I announced this bootloader on these lists a long time ago; Cort Dougan (the maintainer at the time) liked it very much but I failed at pushing it. It had a few interesting features: among them it could initialize a video board by executing the BIOS since it included an x86 emulator (24kB code + data). It had a relatively clean memory management, etc... But I have no time to work on it in the next few months. > Having the .pmac.text, .prep.text etc. sections lets us remove > unneeded code at runtime, but it sounds like that isn't actually the > issue for you (i.e. you don't have a need to run the same kernel on > both a pmac and a prep). Not at all. For example my pmac kernels need usb to boot (literally), the MVME machines have CONFIG_USB off (this saves a lot). Now there are other architectures that could be merged, an example is PreP/PowerPlus/MVME5100. Gabriel From arnd at arndb.de Fri Sep 16 08:56:31 2005 From: arnd at arndb.de (Arnd Bergmann) Date: Fri, 16 Sep 2005 00:56:31 +0200 Subject: [PATCH] powerpc: merge include/asm/cputable.h In-Reply-To: References: <200509150158.10511.arnd@arndb.de> Message-ID: <200509160056.32617.arnd@arndb.de> On Dunnersdag 15 September 2005 19:44, Kumar Gala wrote: > I get the idea now, how about we make CPU_FTR_ALWAYS & > CPU_FTR_POSSIBLE just #defines and leave it to various sub-archs to > define CPU_FTR_POSSIBLE if they want to. > So you mean like: #ifdef CONFIG_PPC_PSERIES #define CPU_FTR_PSERIES_POSSIBLE (CPU_FTR_FOO | CPU_FTR_BAR) #define CPU_FTR_PSERIES_ALWAYS (CPU_FTR_FOO) #else #define CPU_FTR_PSERIES_POSSIBLE (0) #define CPU_FTR_PSERIES_ALWAYS (-1) #endif #ifdef CONFIG_PPC_PMAC #define CPU_FTR_PMAC_POSSIBLE (CPU_FTR_BAR | CPU_FTR_BAZ) #define CPU_FTR_PMAL_ALWAYS (CPU_FTR_BAZ) #else #define CPU_FTR_PMAC_POSSIBLE (0) #define CPU_FTR_PMAC_ALWAYS (-1) #endif ... #define CPU_FTR_POSSIBLE CPU_FTR_PSERIES_POSSIBLE | CPU_FTR_PMAC_POSSIBLE \ | CPU_FTR_... #define CPU_FTR_ALWAYS CPU_FTR_POSSIBLE & CPU_FTR_PSERIES_ALWAYS \ & CPU_FTR_PMAC_ALWAYS & CPU_FTR_ ... That would of course avoid having to define the features per CPU type, but at the same time make the system more error prone, because every time you add a feature to some of the CPUs, you'd have to know exactly which platform defines to change as well, and they might get out of sync. I also don't think that using the #defines here makes it any more readable than the enums, because you cannot have compile-time conditionals inside of #define. > I see the classes of for FTR_POSSIBLE: CLASSIC_PPC, 8xx, 4xx, FSL- > BOOKE, PPC64 (maybe more subclasses here). > > The hugh enum while useful, is just really ugly and I can't believe > it's worth it for the ~60 cases we are using cpu_has_feature() in. One point to consider is that we traditionally use #ifdef in the source for many places that could simply use cpu_has_feature(). E.g. most instances of #ifdef CONFIG_ALTIVEC could be replaced by cpu_has_feature(CPU_FTR_ALTIVEC) without additional run-time overhead. Arnd <>< From paulus at samba.org Fri Sep 16 08:55:57 2005 From: paulus at samba.org (Paul Mackerras) Date: Fri, 16 Sep 2005 08:55:57 +1000 Subject: [PATCH] powerpc: don't execute a temporary comment In-Reply-To: <20050915140659.GA17670@tuxdriver.com> References: <20050915160430.550d02ed.sfr@canb.auug.org.au> <20050915140659.GA17670@tuxdriver.com> Message-ID: <17193.64509.576852.408757@cargo.ozlabs.ibm.com> John W. Linville writes: > Why is this helpful? Better in general to keep the commment near the code, no? Where it was, it was a command, not a comment, so it got printed out on the screen when you did a make clean, which seemed a bit silly. Paul. From kumar.gala at freescale.com Fri Sep 16 12:22:08 2005 From: kumar.gala at freescale.com (Kumar Gala) Date: Thu, 15 Sep 2005 21:22:08 -0500 Subject: [PATCH] powerpc: merge include/asm/cputable.h In-Reply-To: <200509160056.32617.arnd@arndb.de> References: <200509160056.32617.arnd@arndb.de> Message-ID: On Sep 15, 2005, at 5:56 PM, Arnd Bergmann wrote: > On Dunnersdag 15 September 2005 19:44, Kumar Gala wrote: > > >> I get the idea now, how about we make CPU_FTR_ALWAYS & >> CPU_FTR_POSSIBLE just #defines and leave it to various sub-archs to >> define CPU_FTR_POSSIBLE if they want to. >> >> > > > So you mean like: > > #ifdef CONFIG_PPC_PSERIES > #define CPU_FTR_PSERIES_POSSIBLE (CPU_FTR_FOO | CPU_FTR_BAR) > #define CPU_FTR_PSERIES_ALWAYS (CPU_FTR_FOO) > #else > #define CPU_FTR_PSERIES_POSSIBLE (0) > #define CPU_FTR_PSERIES_ALWAYS (-1) > #endif > > #ifdef CONFIG_PPC_PMAC > #define CPU_FTR_PMAC_POSSIBLE (CPU_FTR_BAR | CPU_FTR_BAZ) > #define CPU_FTR_PMAL_ALWAYS (CPU_FTR_BAZ) > #else > #define CPU_FTR_PMAC_POSSIBLE (0) > #define CPU_FTR_PMAC_ALWAYS (-1) > #endif > > ... > > #define CPU_FTR_POSSIBLE CPU_FTR_PSERIES_POSSIBLE | > CPU_FTR_PMAC_POSSIBLE \ > | CPU_FTR_... > #define CPU_FTR_ALWAYS CPU_FTR_POSSIBLE & CPU_FTR_PSERIES_ALWAYS \ > & CPU_FTR_PMAC_ALWAYS & CPU_FTR_ ... Yes, something like that. Why do we need the CPU_FTR_ALWAYS. It seems that CPU_FTR_POSSIBLE is sufficient. I may just not understand the purpose of CPU_FTR_ALWAYS. > That would of course avoid having to define the features per CPU type, > but at the same time make the system more error prone, because every > time you add a feature to some of the CPUs, you'd have to know exactly > which platform defines to change as well, and they might get out of > sync. Well if you are adding a new FTR you better know what CPUs it belongs to otherwise how would you update the cputable today? However, I do agree it could be error prone. > I also don't think that using the #defines here makes it any more > readable than the enums, because you cannot have compile-time > conditionals > inside of #define. > > >> I see the classes of for FTR_POSSIBLE: CLASSIC_PPC, 8xx, 4xx, FSL- >> BOOKE, PPC64 (maybe more subclasses here). >> >> The hugh enum while useful, is just really ugly and I can't believe >> it's worth it for the ~60 cases we are using cpu_has_feature() in. >> > > One point to consider is that we traditionally use #ifdef in the > source for many places that could simply use cpu_has_feature(). E.g. > most instances of #ifdef CONFIG_ALTIVEC could be replaced by > cpu_has_feature(CPU_FTR_ALTIVEC) without additional run-time overhead. These should stay as CONFIG options because to reduce the code size of the kernel which is important to embedded people. - kumar From kumar.gala at freescale.com Fri Sep 16 12:22:43 2005 From: kumar.gala at freescale.com (Kumar Gala) Date: Thu, 15 Sep 2005 21:22:43 -0500 Subject: [PATCH] powerpc: don't execute a temporary comment In-Reply-To: <17193.64509.576852.408757@cargo.ozlabs.ibm.com> References: <17193.64509.576852.408757@cargo.ozlabs.ibm.com> Message-ID: We are going to send this to Linus for 2.6.14, right? - k On Sep 15, 2005, at 5:55 PM, Paul Mackerras wrote: > John W. Linville writes: > > >> Why is this helpful? Better in general to keep the commment near the >> > code, no? > > Where it was, it was a command, not a comment, so it got printed out > on the screen when you did a make clean, which seemed a bit silly. > > Paul. > _______________________________________________ > Linuxppc-dev mailing list > Linuxppc-dev at ozlabs.org > https://ozlabs.org/mailman/listinfo/linuxppc-dev > From arnd at arndb.de Fri Sep 16 13:11:38 2005 From: arnd at arndb.de (Arnd Bergmann) Date: Fri, 16 Sep 2005 05:11:38 +0200 Subject: [PATCH] powerpc: merge include/asm/cputable.h In-Reply-To: References: <200509160056.32617.arnd@arndb.de> Message-ID: <200509160511.39277.arnd@arndb.de> On Freedag 16 September 2005 04:22, Kumar Gala wrote: > > #define CPU_FTR_POSSIBLE CPU_FTR_PSERIES_POSSIBLE | > > CPU_FTR_PMAC_POSSIBLE \ > > | CPU_FTR_... > > #define CPU_FTR_ALWAYS CPU_FTR_POSSIBLE & CPU_FTR_PSERIES_ALWAYS \ > > & CPU_FTR_PMAC_ALWAYS & CPU_FTR_ ... > > Yes, something like that. Why do we need the CPU_FTR_ALWAYS. It > seems that CPU_FTR_POSSIBLE is sufficient. I may just not understand > the purpose of CPU_FTR_ALWAYS. > > > One point to consider is that we traditionally use #ifdef in the > > source for many places that could simply use cpu_has_feature(). E.g. > > most instances of #ifdef CONFIG_ALTIVEC could be replaced by > > cpu_has_feature(CPU_FTR_ALTIVEC) without additional run-time overhead. > > These should stay as CONFIG options because to reduce the code size > of the kernel which is important to embedded people. The whole point of the logic is to reduce code size, because gcc is smart enough to remove all dead code then. Consider again the definition of | static inline int have_feature(unsigned long feature) | { | return (FEATURE_ALWAYS & feature) || | (FEATURE_POSSIBLE & runtime_feature & feature); | } If the feature is part of FEATURE_ALWAYS, this will be optimized to | return 1 || FEATURE_POSSIBLE & runtime_feature & feature; and subsequently | return 1; If it is not part of FEATURE_POSSIBLE, it it equivalent to | return 0 || (0 & runtime_feature & feature); which becomes | return 0; Any code inside of | if (0) { /* ... */ } is only checked for syntax by gcc but will not end up in the object code. For the 'if(1)' case, the code gets smaller as well, because the runtime flag does not have to be dereferenced. For some places, we might prefer to replace '#ifdef CONFIG_FOO' not with have_feature(FOO), but rather with feature_possible(FOO), given a definition of static inline int have_feature(unsigned int feature) { return !!(FEATURE_POSSIBLE & feature); } which always get evaluated at compile time. Arnd <>< From arnd at arndb.de Fri Sep 16 22:16:46 2005 From: arnd at arndb.de (Arnd Bergmann) Date: Fri, 16 Sep 2005 08:16:46 -0400 Subject: [patch 00/11] spufs: latest spufs snapshot for 2.6.14-rc1 Message-ID: <20050916121646.387617000@localhost> This is an updated version of the SPU file system. Sorry for the long delay in this, I wanted to get it out much earlier. In this release, we have many new features, most of all a scheduler for running an arbitrary number of SPU threads. This release should still maintain backwards compatibility with earlier releases, unless the last patch is applied, which actually removes some of those interfaces. The next version will no longer contain these interfaces at all. Since the interfaces and the code are slowly stabilizing now, I'd like to get this into -mm soon, probably the next spufs release after this one. The next release should also move to some location under arch/powerpc rather than fs/spufs, as suggested by Pekka Engberg. Arnd <>< From arnd at arndb.de Fri Sep 16 22:16:50 2005 From: arnd at arndb.de (Arnd Bergmann) Date: Fri, 16 Sep 2005 08:16:50 -0400 Subject: [patch 04/11] spufs: add spu-side context switch code References: <20050916121646.387617000@localhost> Message-ID: <20050916123313.717045000@localhost> An embedded and charset-unspecified text was scrubbed... Name: spufs-generated-files.diff Url: http://ozlabs.org/pipermail/linuxppc64-dev/attachments/20050916/b507210e/attachment.txt From arnd at arndb.de Fri Sep 16 22:16:51 2005 From: arnd at arndb.de (Arnd Bergmann) Date: Fri, 16 Sep 2005 08:16:51 -0400 Subject: [patch 05/11] spufs: Use a system call instead of ioctl References: <20050916121646.387617000@localhost> Message-ID: <20050916123313.884887000@localhost> An embedded and charset-unspecified text was scrubbed... Name: spufs-syscall-4.diff Url: http://ozlabs.org/pipermail/linuxppc64-dev/attachments/20050916/5e8b737a/attachment.txt From arnd at arndb.de Fri Sep 16 22:16:52 2005 From: arnd at arndb.de (Arnd Bergmann) Date: Fri, 16 Sep 2005 08:16:52 -0400 Subject: [patch 06/11] spufs: allow O_ASYNC on mailbox files References: <20050916121646.387617000@localhost> Message-ID: <20050916123314.058417000@localhost> An embedded and charset-unspecified text was scrubbed... Name: spufs-fasync-2.diff Url: http://ozlabs.org/pipermail/linuxppc64-dev/attachments/20050916/fd6ca9c5/attachment.txt From arnd at arndb.de Fri Sep 16 22:16:49 2005 From: arnd at arndb.de (Arnd Bergmann) Date: Fri, 16 Sep 2005 08:16:49 -0400 Subject: [patch 03/11] spufs: kernel-side context switch code References: <20050916121646.387617000@localhost> Message-ID: <20050916123313.540947000@localhost> An embedded and charset-unspecified text was scrubbed... Name: spufs-context-3-part2.diff Url: http://ozlabs.org/pipermail/linuxppc64-dev/attachments/20050916/c1f90ec1/attachment.txt From arnd at arndb.de Fri Sep 16 22:16:55 2005 From: arnd at arndb.de (Arnd Bergmann) Date: Fri, 16 Sep 2005 08:16:55 -0400 Subject: [patch 09/11] spufs: SPU scheduler References: <20050916121646.387617000@localhost> Message-ID: <20050916123314.531162000@localhost> An embedded and charset-unspecified text was scrubbed... Name: spu-sched-5.diff Url: http://ozlabs.org/pipermail/linuxppc64-dev/attachments/20050916/b84bdbf3/attachment.txt From arnd at arndb.de Fri Sep 16 22:16:56 2005 From: arnd at arndb.de (Arnd Bergmann) Date: Fri, 16 Sep 2005 08:16:56 -0400 Subject: [patch 10/11] spufs: new entries for SPU special purpose registers. References: <20050916121646.387617000@localhost> Message-ID: <20050916123314.704421000@localhost> An embedded and charset-unspecified text was scrubbed... Name: spufs-add-sprs.diff Url: http://ozlabs.org/pipermail/linuxppc64-dev/attachments/20050916/7ab428de/attachment.txt From arnd at arndb.de Fri Sep 16 22:16:57 2005 From: arnd at arndb.de (Arnd Bergmann) Date: Fri, 16 Sep 2005 08:16:57 -0400 Subject: [patch 11/11] spufs: remove old user interfaces References: <20050916121646.387617000@localhost> Message-ID: <20050916123314.863192000@localhost> An embedded and charset-unspecified text was scrubbed... Name: spufs-remove-legacy-2.diff Url: http://ozlabs.org/pipermail/linuxppc64-dev/attachments/20050916/326cafa5/attachment.txt From arnd at arndb.de Fri Sep 16 16:57:16 2005 From: arnd at arndb.de (Arnd Bergmann) Date: Fri, 16 Sep 2005 08:57:16 +0200 Subject: [HACK] ppc64: small hacks for running on BPA hardware, v2 In-Reply-To: <200509160850.46207.arnd@arndb.de> References: <200509160850.46207.arnd@arndb.de> Message-ID: <200509160857.16682.arnd@arndb.de> This patch is not meant for inclusion in a generic kernel, but is currently needed to support the available HW. Most of the things done in here are workarounds for deficiencies in the present hardware or firmware that will be solved there in later releases. Unfortunately, the number of hacks in here is currently increasing, not decreasing, compared to the previous patch with this name. Signed-off-by: Arnd Bergmann Index: linux-cg/arch/ppc64/Kconfig =================================================================== --- linux-cg.orig/arch/ppc64/Kconfig +++ linux-cg/arch/ppc64/Kconfig @@ -225,6 +225,12 @@ config SMP If you don't know what to do here, say Y. +config BE_DD2 + bool "BE DD2.x Errata Workaround Support" + depends on PPC_BPA + ---help--- + This support enables BE DD2.x errata workarounds. + config NR_CPUS int "Maximum number of CPUs (2-128)" range 2 128 Index: linux-cg/arch/ppc64/kernel/Makefile =================================================================== --- linux-cg.orig/arch/ppc64/kernel/Makefile +++ linux-cg/arch/ppc64/kernel/Makefile @@ -33,7 +33,7 @@ obj-$(CONFIG_PPC_PSERIES) += pSeries_pci pSeries_nvram.o rtasd.o ras.o pSeries_reconfig.o \ pSeries_setup.o pSeries_iommu.o udbg_16550.o -obj-$(CONFIG_PPC_BPA) += bpa_setup.o bpa_iommu.o bpa_nvram.o \ +obj-$(CONFIG_PPC_BPA) += bpa_setup.o bpa_iommu.o bpa_nvram.o bpa_pci.o \ bpa_iic.o spider-pic.o obj-$(CONFIG_KEXEC) += machine_kexec.o Index: linux-cg/arch/ppc64/kernel/bpa_iommu.c =================================================================== --- linux-cg.orig/arch/ppc64/kernel/bpa_iommu.c +++ linux-cg/arch/ppc64/kernel/bpa_iommu.c @@ -245,8 +245,6 @@ set_iocmd_config(void __iomem *base) } /* 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 @@ -278,12 +276,22 @@ static void bpa_map_iommu(void) void __iomem *base; ioste ioste; unsigned long index; + struct device_node *node; + unsigned long *handle, ioc_mmio_base, ioc_base; + int nodelen; + + for(node = of_find_node_by_type(NULL, "cpu"); + node; + node = of_find_node_by_type(node, "cpu")) { + handle = (unsigned long *) get_property(node, "ioc-translation", &nodelen); + ioc_base = *handle + 0x1000; base = __ioremap(ioc_base, 0x1000, _PAGE_NO_CACHE); pr_debug("%lx mapped to %p\n", ioc_base, base); set_iocmd_config(base); iounmap(base); + ioc_mmio_base = *handle; base = __ioremap(ioc_mmio_base, 0x1000, _PAGE_NO_CACHE); pr_debug("%lx mapped to %p\n", ioc_mmio_base, base); @@ -302,6 +310,7 @@ static void bpa_map_iommu(void) map_iopt_entry(address)); } iounmap(base); + } } Index: linux-cg/arch/ppc64/kernel/bpa_pci.c =================================================================== --- /dev/null +++ linux-cg/arch/ppc64/kernel/bpa_pci.c @@ -0,0 +1,83 @@ +/* + * BPA specific PCI code + * + * Copyright (C) 2005 IBM Corporation, + 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 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include + +#include +#include +#include + +#include "pci.h" +#include "bpa_iic.h" + +void __init bpa_final_fixup(void) +{ + struct pci_dev *dev = NULL; + + phbs_remap_io(); + + for_each_pci_dev(dev) { + // FIXME: fix IRQ numbers for devices on second south bridge + } +} + +static void fixup_spider_ipci_irq(struct pci_dev* dev) +{ + int irq_node_offset; + pr_debug("fixup for %04x:%04x at %02x.%1x: ", dev->vendor, dev->device, + PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn)); + switch (dev->devfn) { + case PCI_DEVFN(3,0): + /* ethernet */ + dev->irq = 8; + break; + case PCI_DEVFN(5,0): + /* OHCI 0 */ + dev->irq = 10; + break; + case PCI_DEVFN(6,0): + /* OHCI 1 */ + dev->irq = 11; + break; + case PCI_DEVFN(5,1): + /* EHCI 0 */ + dev->irq = 10; + break; + case PCI_DEVFN(6,1): + /* EHCI 1 */ + dev->irq = 11; + break; + } + + irq_node_offset = IIC_NODE_STRIDE * (pci_domain_nr(dev->bus)-1); + dev->irq += irq_node_offset; + + pr_debug("irq %0x\n", dev->irq); +} + +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_TOSHIBA_2, + PCI_DEVICE_ID_TOSHIBA_SPIDER_NET, fixup_spider_ipci_irq); +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_TOSHIBA_2, + PCI_DEVICE_ID_TOSHIBA_SPIDER_OHCI, fixup_spider_ipci_irq); +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_TOSHIBA_2, + PCI_DEVICE_ID_TOSHIBA_SPIDER_EHCI, fixup_spider_ipci_irq); Index: linux-cg/arch/ppc64/kernel/bpa_setup.c =================================================================== --- linux-cg.orig/arch/ppc64/kernel/bpa_setup.c +++ linux-cg/arch/ppc64/kernel/bpa_setup.c @@ -54,6 +54,8 @@ #define DBG(fmt...) #endif +extern void bpa_final_fixup(void); + void bpa_get_cpuinfo(struct seq_file *m) { struct device_node *root; @@ -198,6 +200,7 @@ struct machdep_calls __initdata bpa_md = .setup_arch = bpa_setup_arch, .init_early = bpa_init_early, .get_cpuinfo = bpa_get_cpuinfo, + .pcibios_fixup = bpa_final_fixup, .restart = rtas_restart, .power_off = rtas_power_off, .halt = rtas_halt, Index: linux-cg/arch/ppc64/kernel/head.S =================================================================== --- linux-cg.orig/arch/ppc64/kernel/head.S +++ linux-cg/arch/ppc64/kernel/head.S @@ -304,6 +304,38 @@ label##_pSeries: \ RUNLATCH_ON(r13); \ EXCEPTION_PROLOG_PSERIES(PACA_EXGEN, label##_common) +#define WORKAROUND_EXCEPTION_PSERIES(n, label) \ + . = n; \ + .globl label##_pSeries; \ +label##_pSeries: \ + mtspr SPRG1,r21; /* save r21 */ \ + mfspr r21, SPRN_CTRLF; \ + oris r21, r21, 0x00C0; \ + mtspr SPRN_CTRLT, r21; \ + mfspr r21,SPRG1; /* restore r21 */ \ + mtspr SPRG1,r13; /* save r13 */ \ + EXCEPTION_PROLOG_PSERIES(PACA_EXGEN, label##_common) + +#define RES_EXCEPTION_PSERIES(n, label) \ + . = n; \ + .globl label##_pSeries; \ +label##_pSeries: \ + mtspr SPRG2,r20; /* use SPRG2 as scratch reg */ \ + mtspr SPRG1,r21; /* use SPRG1 as scratch reg */ \ + mfspr r20,SPRG3; /* get paca virtual address */ \ + cmpdi r20,0x0; /* if SPRG3 zero,thread */ \ + bne 20f; /* shouldn't run */ \ +18: /* Stop current Thread */ \ + andi. r21,0,0; \ + mtspr SPRN_CTRLT,r21; \ +19: \ + b 19b; /* Thread should be stopped */ \ +20: \ + HMT_MEDIUM; \ + mtspr SPRG1,r13; /* save r13 */ \ + RUNLATCH_ON(r13); \ + EXCEPTION_PROLOG_PSERIES(PACA_EXGEN, label##_common) + #define STD_EXCEPTION_ISERIES(n, label, area) \ .globl label##_iSeries; \ label##_iSeries: \ @@ -383,7 +415,11 @@ label##_common: \ .globl __start_interrupts __start_interrupts: +#ifdef CONFIG_BE_DD2 + RES_EXCEPTION_PSERIES(0x100, system_reset) +#else STD_EXCEPTION_PSERIES(0x100, system_reset) +#endif . = 0x200 _machine_check_pSeries: @@ -451,11 +487,19 @@ instruction_access_slb_pSeries: mfspr r3,SRR0 /* SRR0 is faulting address */ b .do_slb_miss /* Rel. branch works in real mode */ +#ifdef CONFIG_BE_DD2 + WORKAROUND_EXCEPTION_PSERIES(0x500, hardware_interrupt) +#else STD_EXCEPTION_PSERIES(0x500, hardware_interrupt) +#endif STD_EXCEPTION_PSERIES(0x600, alignment) STD_EXCEPTION_PSERIES(0x700, program_check) STD_EXCEPTION_PSERIES(0x800, fp_unavailable) +#ifdef CONFIG_BE_DD2 + WORKAROUND_EXCEPTION_PSERIES(0x900, decrementer) +#else STD_EXCEPTION_PSERIES(0x900, decrementer) +#endif STD_EXCEPTION_PSERIES(0xa00, trap_0a) STD_EXCEPTION_PSERIES(0xb00, trap_0b) Index: linux-cg/arch/ppc64/kernel/prom_init.c =================================================================== --- linux-cg.orig/arch/ppc64/kernel/prom_init.c +++ linux-cg/arch/ppc64/kernel/prom_init.c @@ -1367,6 +1367,8 @@ static int __init prom_find_machine_type return PLATFORM_POWERMAC; if (strstr(p, RELOC("Momentum,Maple"))) return PLATFORM_MAPLE; + if (strstr(p, RELOC("IBM,CPB"))) + return PLATFORM_BPA; i += sl + 1; } } Index: linux-cg/arch/ppc64/kernel/spider-pic.c =================================================================== --- linux-cg.orig/arch/ppc64/kernel/spider-pic.c +++ linux-cg/arch/ppc64/kernel/spider-pic.c @@ -84,10 +84,11 @@ static void __iomem *spider_get_irq_conf static void spider_enable_irq(unsigned int irq) { + int nodeid = (irq / IIC_NODE_STRIDE) * 0x10; void __iomem *cfg = spider_get_irq_config(irq); irq = spider_get_nr(irq); - out_be32(cfg, in_be32(cfg) | 0x3107000eu); + out_be32(cfg, in_be32(cfg) | 0x3107000eu | nodeid); out_be32(cfg + 4, in_be32(cfg + 4) | 0x00020000u | irq); } @@ -150,13 +151,17 @@ int spider_get_irq(unsigned long int_pen void spider_init_IRQ(void) { int node; +#if 0 struct device_node *dn; unsigned int *property; +#endif long spiderpic; + long pics[] = { 0x24000008000, 0x34000008000 }; int n; /* FIXME: detect multiple PICs as soon as the device tree has them */ - for (node = 0; node < 1; node++) { + for (node = 0; node < num_present_cpus()/2; node++) { +#if 0 dn = of_find_node_by_path("/"); n = prom_n_addr_cells(dn); property = (unsigned int *) get_property(dn, @@ -166,11 +171,14 @@ void spider_init_IRQ(void) continue; for (spiderpic = 0; n > 0; --n) spiderpic = (spiderpic << 32) + *property++; +#endif + spiderpic = pics[node]; 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); @@ -184,8 +192,6 @@ void spider_init_IRQ(void) /* Enable the interrupt detection enable bit. Do this last! */ out_be32(spider_pics[node] + TIR_DEN, - in_be32(spider_pics[node] +TIR_DEN) | 0x1); - - } + in_be32(spider_pics[node] + TIR_DEN) | 0x1); } } Index: linux-cg/include/asm-ppc64/processor.h =================================================================== --- linux-cg.orig/include/asm-ppc64/processor.h +++ linux-cg/include/asm-ppc64/processor.h @@ -453,7 +453,7 @@ struct thread_struct { .fs = KERNEL_DS, \ .fpr = {0}, \ .fpscr = 0, \ - .fpexc_mode = MSR_FE0|MSR_FE1, \ + .fpexc_mode = 0, \ } /* Index: linux-cg/include/linux/pci_ids.h =================================================================== --- linux-cg.orig/include/linux/pci_ids.h +++ linux-cg/include/linux/pci_ids.h @@ -1613,6 +1613,8 @@ #define PCI_DEVICE_ID_TOSHIBA_TX4927 0x0180 #define PCI_DEVICE_ID_TOSHIBA_TC86C001_MISC 0x0108 #define PCI_DEVICE_ID_TOSHIBA_SPIDER_NET 0x01b3 +#define PCI_DEVICE_ID_TOSHIBA_SPIDER_OHCI 0x01b6 +#define PCI_DEVICE_ID_TOSHIBA_SPIDER_EHCI 0x01b5 #define PCI_VENDOR_ID_RICOH 0x1180 #define PCI_DEVICE_ID_RICOH_RL5C465 0x0465 Index: linux-cg/arch/ppc64/kernel/spu_base.c =================================================================== --- linux-cg.orig/arch/ppc64/kernel/spu_base.c +++ linux-cg/arch/ppc64/kernel/spu_base.c @@ -578,6 +578,10 @@ static void __iomem * __init map_spe_pro prop = p; + /* FIXME: Firmware bug */ + if (strcmp (name, "priv2") == 0 && prop->len < 0x20000) + return ioremap(prop->address, 0x20000); + return ioremap(prop->address, prop->len); } From arnd at arndb.de Fri Sep 16 17:00:08 2005 From: arnd at arndb.de (Arnd Bergmann) Date: Fri, 16 Sep 2005 09:00:08 +0200 Subject: [PATCH] ppc64: add RTAS console driver, v2 In-Reply-To: <200509160857.16682.arnd@arndb.de> References: <200509160850.46207.arnd@arndb.de> <200509160857.16682.arnd@arndb.de> Message-ID: <200509160900.08534.arnd@arndb.de> The RTAS console driver can be used by all machines that abstract the system console through the {get,put}-term-char interface. It replaces the hvconsole on BPA, because we don't run under a hypervisor. This driver needs to be redone as a special case of hvconsole, so there is no point in applying the patch to generic kernels. You will however need it if you intend to run on present IBM hardware. From: Utz Bacher , Maximino Aguilar Signed-off-by: Arnd Bergmann Index: linux-2.6.13/drivers/char/Kconfig =================================================================== --- linux-2.6.13.orig/drivers/char/Kconfig 2005-09-12 21:24:45.000000000 +0200 +++ linux-2.6.13/drivers/char/Kconfig 2005-09-12 21:26:28.000000000 +0200 @@ -560,6 +560,12 @@ console. This driver allows each pSeries partition to have a console which is accessed via the HMC. +config RTASCONS + bool "RTAS firmware console support" + depends on PPC_RTAS + help + RTAS console support. + config HVCS tristate "IBM Hypervisor Virtual Console Server support" depends on PPC_PSERIES Index: linux-2.6.13/drivers/char/Makefile =================================================================== --- linux-2.6.13.orig/drivers/char/Makefile 2005-08-29 01:41:01.000000000 +0200 +++ linux-2.6.13/drivers/char/Makefile 2005-09-12 21:26:28.000000000 +0200 @@ -40,6 +40,7 @@ obj-$(CONFIG_AMIGA_BUILTIN_SERIAL) += amiserial.o obj-$(CONFIG_SX) += sx.o generic_serial.o obj-$(CONFIG_RIO) += rio/ generic_serial.o +obj-$(CONFIG_RTASCONS) += rtascons.o obj-$(CONFIG_HVC_CONSOLE) += hvc_console.o hvc_vio.o hvsi.o obj-$(CONFIG_RAW_DRIVER) += raw.o obj-$(CONFIG_SGI_SNSC) += snsc.o snsc_event.o Index: linux-2.6.13/drivers/char/rtascons.c =================================================================== --- linux-2.6.13.orig/drivers/char/rtascons.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.13/drivers/char/rtascons.c 2005-09-12 21:26:48.000000000 +0200 @@ -0,0 +1,340 @@ +/* + * console driver using RTAS calls + * + * (C) Copyright IBM Corp. 2004 + * RTAS console driver + * + * Authors: Utz Bacher + * Maximino Aguilar + * + * inspired by drivers/char/hvc_console.c + * written by Anton Blanchard and Paul Mackerras + * + * 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. + */ + +/* The whole driver assumes we only have one RTAS console. This makes + * things pretty easy. */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#define RTASCONS_MAJOR 229 +#define RTASCONS_MINOR 0 + +#define RTASCONS_SYSRQ_KEY '\x0f' + +#define RTASCONS_PUT_ATTEMPTS 16 +#define RTASCONS_PUT_DELAY 100 +#define RTASCONS_BUFFER_SIZE 4096 + +#define RTASCONS_MAX_POLL 50 +#define RTASCONS_WRITE_ROOM 200 + +#define RTASCONS_TIMEOUT ((HZ + 99) / 100) + + +static struct tty_driver *rtascons_ttydriver; + +static atomic_t rtascons_usecount = ATOMIC_INIT(0); +static struct tty_struct *rtascons_tty; + +static int rtascons_put_char_token; +static int rtascons_get_char_token; + +static spinlock_t rtascons_buffer_lock = SPIN_LOCK_UNLOCKED; +static char rtascons_buffer[RTASCONS_BUFFER_SIZE]; +static int rtascons_buffer_head = 0; +static int rtascons_buffer_used = 0; + +static int +rtascons_get_char(void) +{ + int result; + + if (rtas_call(rtascons_get_char_token, 0, 2, &result)) + result = -1; + + return result; +} + +/* assumes that rtascons_buffer_lock is held */ +static void +rtascons_flush_chars(void) +{ + int result; + int attempts = RTASCONS_PUT_ATTEMPTS; + + /* if there is more than one character to be displayed, wait a bit */ + for (; rtascons_buffer_used && attempts; udelay(RTASCONS_PUT_DELAY)) { + attempts--; + result = rtas_call(rtascons_put_char_token, 1, 1, NULL, + rtascons_buffer[rtascons_buffer_head]); + + if (!result) { + rtascons_buffer_head = (rtascons_buffer_head + 1) % + RTASCONS_BUFFER_SIZE; + rtascons_buffer_used--; + } + } +} + +static void +rtascons_put_char(char c) +{ + spin_lock(&rtascons_buffer_lock); + + if (rtascons_buffer_used >= (RTASCONS_BUFFER_SIZE / 2)) + udelay(RTASCONS_PUT_DELAY); /* slow down if buffer tends + to get full */ + + if (rtascons_buffer_used >= RTASCONS_BUFFER_SIZE) + goto out; /* we're loosing characters. */ + + /* enqueue character */ + rtascons_buffer[(rtascons_buffer_head + rtascons_buffer_used) % + RTASCONS_BUFFER_SIZE] = c; + rtascons_buffer_used++; +out: + rtascons_flush_chars(); + + spin_unlock(&rtascons_buffer_lock); +} + +static void +rtascons_print_str(const char *buf, int count) +{ + int i = 0; + while (i < count) { + rtascons_put_char(buf[i]); + if (buf[i] == '\n') + rtascons_put_char('\r'); + i++; + } +} + +static int +rtascons_open(struct tty_struct *tty, struct file *filp) +{ + /* only one console */ + if (tty->index) { + /* close will be called and that decrement */ + atomic_inc(&rtascons_usecount); + return -ENODEV; + } + + if (atomic_inc_return(&rtascons_usecount) == 1) { + rtascons_tty = tty; + } + + tty->driver_data = &rtascons_ttydriver; + + return 0; +} + +static void +rtascons_close(struct tty_struct *tty, struct file * filp) +{ + atomic_dec(&rtascons_usecount); +} + +static void +rtascons_hangup(struct tty_struct *tty) +{ +} + +static int +rtascons_write(struct tty_struct *tty, const unsigned char *buf, int count) +{ + if (!atomic_read(&rtascons_usecount)) + return 0; + + rtascons_print_str(buf, count); + + return count; +} + +static int +rtascons_write_room(struct tty_struct *tty) +{ + return RTASCONS_WRITE_ROOM; +} + +static int +rtascons_chars_in_buffer(struct tty_struct *tty) +{ + return 0; +} + +static void +rtascons_poll(void) +{ + int i; + int do_poll = RTASCONS_MAX_POLL; +#ifdef CONFIG_MAGIC_SYSRQ + static int sysrq_pressed = 0; +#endif /* CONFIG_MAGIC_SYSRQ */ + + if (!atomic_read(&rtascons_usecount)) + return; + + while (do_poll--) { + i = rtascons_get_char(); + if (i < 0) + break; + +#ifdef CONFIG_MAGIC_SYSRQ + if (i == RTASCONS_SYSRQ_KEY) { + sysrq_pressed = 1; + continue; + } else if (sysrq_pressed) { + handle_sysrq(i, NULL, rtascons_tty); + sysrq_pressed = 0; + continue; + } +#endif /* CONFIG_MAGIC_SYSRQ */ + + tty_insert_flip_char(rtascons_tty, (unsigned char) i, 0); + } + + tty_flip_buffer_push(rtascons_tty); +} + +#if defined(CONFIG_XMON) && defined(CONFIG_SMP) +extern cpumask_t cpus_in_xmon; +#else +static const cpumask_t cpus_in_xmon = CPU_MASK_NONE; +#endif + +static int +krtasconsd(void *unused) +{ + daemonize("krtasconsd"); + + for (;;) { + if (cpus_empty(cpus_in_xmon)) { + rtascons_poll(); + /* no need for atomic access */ + if (rtascons_buffer_used) { + spin_lock(&rtascons_buffer_lock); + rtascons_flush_chars(); + spin_unlock(&rtascons_buffer_lock); + } + } + + set_current_state(TASK_INTERRUPTIBLE); + schedule_timeout(RTASCONS_TIMEOUT); + } +} + +static struct tty_operations rtascons_ops = { + .open = rtascons_open, + .close = rtascons_close, + .write = rtascons_write, + .hangup = rtascons_hangup, + .write_room = rtascons_write_room, + .chars_in_buffer = rtascons_chars_in_buffer, +}; + +static int __init +rtascons_init(void) +{ + rtascons_ttydriver = alloc_tty_driver(1); + if (!rtascons_ttydriver) + return -ENOMEM; + + rtascons_ttydriver->owner = THIS_MODULE; + rtascons_ttydriver->devfs_name = "rtascons/"; + rtascons_ttydriver->driver_name = "rtascons"; + rtascons_ttydriver->name = "rtascons"; + rtascons_ttydriver->major = RTASCONS_MAJOR; + rtascons_ttydriver->minor_start = RTASCONS_MINOR; + rtascons_ttydriver->type = TTY_DRIVER_TYPE_SYSTEM; + rtascons_ttydriver->subtype = SYSTEM_TYPE_CONSOLE; + rtascons_ttydriver->init_termios = tty_std_termios; + rtascons_ttydriver->flags = TTY_DRIVER_REAL_RAW; + tty_set_operations(rtascons_ttydriver, &rtascons_ops); + + if (tty_register_driver(rtascons_ttydriver)) + panic("Couldn't register RTAS console driver\n"); + + kernel_thread(krtasconsd, NULL, CLONE_KERNEL); + + return 0; +} + +static void __exit +rtascons_exit(void) +{ +} + +static void +rtascons_print(struct console *con, const char *buf, unsigned count) +{ + rtascons_print_str(buf, count); +} + +static struct tty_driver *rtascons_device(struct console *con, int *index) +{ + *index = con->index; + return rtascons_ttydriver; +} + +static int __init +rtascons_setup(struct console *con, char *options) +{ + return (con->index); +} + +struct console rtascons_driver = { + .name = "rtas", + .write = rtascons_print, + .device = rtascons_device, + .setup = rtascons_setup, + .flags = CON_PRINTBUFFER, + .index = -1, +}; + +static int __init +rtascons_register(void) +{ + rtascons_put_char_token = rtas_token("put-term-char"); + if (rtascons_put_char_token == -1) + return -EIO; + rtascons_get_char_token = rtas_token("get-term-char"); + if (rtascons_get_char_token == -1) + return -EIO; + + register_console(&rtascons_driver); + return 0; +} + +console_initcall(rtascons_register); + +module_init(rtascons_init); +module_exit(rtascons_exit); From arnd at arndb.de Fri Sep 16 22:16:47 2005 From: arnd at arndb.de (Arnd Bergmann) Date: Fri, 16 Sep 2005 08:16:47 -0400 Subject: [patch 01/11] spufs: The SPU file system, base References: <20050916121646.387617000@localhost> Message-ID: <20050916123313.194684000@localhost> An embedded and charset-unspecified text was scrubbed... Name: spufs-9.diff Url: http://ozlabs.org/pipermail/linuxppc64-dev/attachments/20050916/02b03de5/attachment.txt From arnd at arndb.de Fri Sep 16 16:55:33 2005 From: arnd at arndb.de (Arnd Bergmann) Date: Fri, 16 Sep 2005 08:55:33 +0200 Subject: [PATCH] net: fix spider_net media detection Message-ID: <200509160855.34219.arnd@arndb.de> From: Jens Osterkamp This patch makes the driver work with any BladeCenter network switch, it used to work only with certain models. Please apply. Signed-off-by: Arnd Bergmann --- linux-2.6.13.orig/drivers/net/spider_net.c +++ linux-2.6.13/drivers/net/spider_net.c @@ -1817,6 +1817,10 @@ spider_net_setup_phy(struct spider_net_c /* LEDs active in both modes, autosense prio = fiber */ spider_net_write_phy(card->netdev, 1, MII_NCONFIG, 0x945f); + /* switch off fibre autoneg */ + spider_net_write_phy(card->netdev, 1, MII_NCONFIG, 0xfc01); + spider_net_write_phy(card->netdev, 1, 0x0b, 0x0004); + phy->def->ops->read_link(phy); pr_info("Found %s with %i Mbps, %s-duplex.\n", phy->def->name, phy->speed, phy->duplex==1 ? "Full" : "Half"); From arnd at arndb.de Fri Sep 16 22:16:48 2005 From: arnd at arndb.de (Arnd Bergmann) Date: Fri, 16 Sep 2005 08:16:48 -0400 Subject: [patch 02/11] spufs: switchable spu contexts References: <20050916121646.387617000@localhost> Message-ID: <20050916123313.373638000@localhost> An embedded and charset-unspecified text was scrubbed... Name: spufs-context-4.diff Url: http://ozlabs.org/pipermail/linuxppc64-dev/attachments/20050916/3f53f688/attachment.txt From arnd at arndb.de Fri Sep 16 22:16:53 2005 From: arnd at arndb.de (Arnd Bergmann) Date: Fri, 16 Sep 2005 08:16:53 -0400 Subject: [patch 07/11] spufs: Add a register file for the debugger References: <20050916121646.387617000@localhost> Message-ID: <20050916123314.206713000@localhost> An embedded and charset-unspecified text was scrubbed... Name: spufs-debug-3.diff Url: http://ozlabs.org/pipermail/linuxppc64-dev/attachments/20050916/13fd4fff/attachment.txt From arnd at arndb.de Fri Sep 16 22:16:54 2005 From: arnd at arndb.de (Arnd Bergmann) Date: Fri, 16 Sep 2005 08:16:54 -0400 Subject: [patch 08/11] spufs: make mem files mmappable References: <20050916121646.387617000@localhost> Message-ID: <20050916123314.366475000@localhost> An embedded and charset-unspecified text was scrubbed... Name: spu-backingstore-2.diff Url: http://ozlabs.org/pipermail/linuxppc64-dev/attachments/20050916/b6dcc5d6/attachment.txt From arnd at arndb.de Fri Sep 16 16:40:28 2005 From: arnd at arndb.de (Arnd Bergmann) Date: Fri, 16 Sep 2005 08:40:28 +0200 Subject: spufs: User space thread library In-Reply-To: <20050916121646.387617000@localhost> References: <20050916121646.387617000@localhost> Message-ID: <200509160840.31071.arnd@arndb.de> This is the user space library for using Cell SPE, for the 2.6.14-rc1 release. It is maintained by Dirk Herrendoerfer , I'm sending this out as a companion to the spufs implementation. Arnd <>< -------------- next part -------------- A non-text attachment was scrubbed... Name: libspe.tar.gz Type: application/x-tgz Size: 35615 bytes Desc: not available Url : http://ozlabs.org/pipermail/linuxppc64-dev/attachments/20050916/aa47638d/attachment.bin From jgarzik at pobox.com Fri Sep 16 17:23:26 2005 From: jgarzik at pobox.com (Jeff Garzik) Date: Fri, 16 Sep 2005 03:23:26 -0400 Subject: [PATCH] net: fix spider_net media detection In-Reply-To: <200509160855.34219.arnd@arndb.de> References: <200509160855.34219.arnd@arndb.de> Message-ID: <432A72EE.30909@pobox.com> applied From colaristide2 at o2.pl Fri Sep 16 05:23:26 2005 From: colaristide2 at o2.pl (colaristide2) Date: Fri, 16 Sep 05 05:23:26 Pacific Standard Time Subject: HELLO Message-ID: <20050916122952.1868D682E5@ozlabs.org> Hello, My name is Col(Rtd) Jon Aristide,brother to the exiled President of Haiti,(Dr.Jean Bertrand Aristide) Due to the evolution against the government of my brother caused by his political opponents in Haiti,we managed to enter a red cross airplane that was evacuating foreigners and we are presently on political assylum in Central African Repubilc(CAR) I wish to invest in Real Estate and commercial Properties and equally start a new life in your country with your assistance and cooperation.If you are in a good position to help my family,please send an e-mail to my personal address below indicating your desire to help meinvest this funds in your country and beyond. I urgently await your e-mail letter. Reply to my confidential mail box: jonaris05 at yahoo.com Best Regards and hope to meet you soon. God bless, Col Jon(Rtd). From jdl at freescale.com Sat Sep 17 00:46:18 2005 From: jdl at freescale.com (Jon Loeliger) Date: Fri, 16 Sep 2005 09:46:18 -0500 Subject: PATCH powerpc: Merge asm-ppc*/sections.h In-Reply-To: <20050915223702.GA322@iram.es> References: <1126644202.11056.59.camel@cashmere.sps.mot.com> <200509140435.21916.arnd@arndb.de> <1126705588.14036.10.camel@cashmere.sps.mot.com> <17193.22140.962651.122114@cargo.ozlabs.ibm.com> <20050915205709.GA31156@iram.es> <17193.61187.613745.15444@cargo.ozlabs.ibm.com> <20050915223702.GA322@iram.es> Message-ID: <1126881977.17442.77.camel@cashmere.sps.mot.com> On Thu, 2005-09-15 at 17:37, Gabriel Paubert wrote: > > I assume you compile custom kernels for these machines, so you're > > happy with using config options to remove the code you don't want? > > Yes, and I have no problems with it. > > > Having the .pmac.text, .prep.text etc. sections lets us remove > > unneeded code at runtime, but it sounds like that isn't actually the > > issue for you (i.e. you don't have a need to run the same kernel on > > both a pmac and a prep). > > Not at all. For example my pmac kernels need usb to boot > (literally), the MVME machines have CONFIG_USB off (this > saves a lot). > > Now there are other architectures that could be merged, > an example is PreP/PowerPlus/MVME5100. > > Gabriel Hi Gabriel, I am reading this to mean that you then have no issue with my proposed changes of removing the special handling of the .pmac, .prep, .chrp, and .openfirmware sections that really only apply to MULTIPLATFORM built images. Again, for embedded boards and for custom-built configurations, this change really should have no impact on your image size. So, were there other objects I missed? If not, I will proceed with a patch to remove these special sections so that we may merge the sections.h header file better! Thanks! jdl From jdl at freescale.com Sat Sep 17 01:45:22 2005 From: jdl at freescale.com (Jon Loeliger) Date: Fri, 16 Sep 2005 10:45:22 -0500 Subject: PATCH powerpc: Revised merge asm-ppc*/hardirq.h In-Reply-To: <1126705294.14036.4.camel@cashmere.sps.mot.com> References: <1126643920.11056.53.camel@cashmere.sps.mot.com> <20050914110506.GA7049@lst.de> <1126705294.14036.4.camel@cashmere.sps.mot.com> Message-ID: <1126885521.17442.113.camel@cashmere.sps.mot.com> This is a revised patch to merge asm-ppc*/hardirq.h. It removes some unnecessary #includes, but then requires the addition of #include in PPC32's hw_irq.h much like ppc64 already does. Furthermore, several unnecessary #includes were removed from some ppc32 boards in order to break resulting bad #include cycles. Builds pSeries_defconfig and all ppc32 platforms except the already b0rken bseip. Signed-off-by: Jon Loeliger Signed-off-by: Kumar Gala --- arch/ppc/platforms/83xx/mpc834x_sys.h | 1 - arch/ppc/platforms/85xx/mpc85xx_ads_common.h | 1 - arch/ppc/platforms/85xx/stx_gp3.h | 1 - include/asm-powerpc/hardirq.h | 24 ++++++++++++++++++++ include/asm-ppc/hardirq.h | 31 -------------------------- include/asm-ppc/hw_irq.h | 1 + include/asm-ppc64/hardirq.h | 27 ----------------------- 7 files changed, 25 insertions(+), 61 deletions(-) diff --git a/arch/ppc/platforms/83xx/mpc834x_sys.h b/arch/ppc/platforms/83xx/mpc834x_sys.h --- a/arch/ppc/platforms/83xx/mpc834x_sys.h +++ b/arch/ppc/platforms/83xx/mpc834x_sys.h @@ -19,7 +19,6 @@ #include #include -#include #include #include diff --git a/arch/ppc/platforms/85xx/mpc85xx_ads_common.h b/arch/ppc/platforms/85xx/mpc85xx_ads_common.h --- a/arch/ppc/platforms/85xx/mpc85xx_ads_common.h +++ b/arch/ppc/platforms/85xx/mpc85xx_ads_common.h @@ -19,7 +19,6 @@ #include #include -#include #include #define BOARD_CCSRBAR ((uint)0xe0000000) diff --git a/arch/ppc/platforms/85xx/stx_gp3.h b/arch/ppc/platforms/85xx/stx_gp3.h --- a/arch/ppc/platforms/85xx/stx_gp3.h +++ b/arch/ppc/platforms/85xx/stx_gp3.h @@ -21,7 +21,6 @@ #include #include -#include #include #define BOARD_CCSRBAR ((uint)0xe0000000) diff --git a/include/asm-powerpc/hardirq.h b/include/asm-powerpc/hardirq.h new file mode 100644 --- /dev/null +++ b/include/asm-powerpc/hardirq.h @@ -0,0 +1,24 @@ +#ifndef _ASM_POWERPC_HARDIRQ_H +#define _ASM_POWERPC_HARDIRQ_H + +/* The __last_jiffy_stamp field is needed to ensure that no decrementer + * interrupt is lost on SMP machines. Since on most CPUs it is in the same + * cache line as local_irq_count, it is cheap to access and is also used on UP + * for uniformity. + */ +typedef struct { + unsigned int __softirq_pending; /* set_bit is used on this */ + unsigned int __last_jiffy_stamp; +} ____cacheline_aligned irq_cpustat_t; + +#include /* Standard mappings for irq_cpustat_t above */ + +#define last_jiffy_stamp(cpu) __IRQ_STAT((cpu), __last_jiffy_stamp) + +static inline void ack_bad_irq(int irq) +{ + printk(KERN_CRIT "illegal vector %d received!\n", irq); + BUG(); +} + +#endif /* _ASM_POWERPC_HARDIRQ_H */ diff --git a/include/asm-ppc/hardirq.h b/include/asm-ppc/hardirq.h deleted file mode 100644 --- a/include/asm-ppc/hardirq.h +++ /dev/null @@ -1,31 +0,0 @@ -#ifdef __KERNEL__ -#ifndef __ASM_HARDIRQ_H -#define __ASM_HARDIRQ_H - -#include -#include -#include -#include - -/* The __last_jiffy_stamp field is needed to ensure that no decrementer - * interrupt is lost on SMP machines. Since on most CPUs it is in the same - * cache line as local_irq_count, it is cheap to access and is also used on UP - * for uniformity. - */ -typedef struct { - unsigned long __softirq_pending; /* set_bit is used on this */ - unsigned int __last_jiffy_stamp; -} ____cacheline_aligned irq_cpustat_t; - -#include /* Standard mappings for irq_cpustat_t above */ - -#define last_jiffy_stamp(cpu) __IRQ_STAT((cpu), __last_jiffy_stamp) - -static inline void ack_bad_irq(int irq) -{ - printk(KERN_CRIT "illegal vector %d received!\n", irq); - BUG(); -} - -#endif /* __ASM_HARDIRQ_H */ -#endif /* __KERNEL__ */ diff --git a/include/asm-ppc/hw_irq.h b/include/asm-ppc/hw_irq.h --- a/include/asm-ppc/hw_irq.h +++ b/include/asm-ppc/hw_irq.h @@ -7,6 +7,7 @@ #include #include +#include extern void timer_interrupt(struct pt_regs *); diff --git a/include/asm-ppc64/hardirq.h b/include/asm-ppc64/hardirq.h deleted file mode 100644 --- a/include/asm-ppc64/hardirq.h +++ /dev/null @@ -1,27 +0,0 @@ -#ifndef __ASM_HARDIRQ_H -#define __ASM_HARDIRQ_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 -#include - -typedef struct { - unsigned int __softirq_pending; -} ____cacheline_aligned irq_cpustat_t; - -#include /* Standard mappings for irq_cpustat_t above */ - -static inline void ack_bad_irq(int irq) -{ - printk(KERN_CRIT "illegal vector %d received!\n", irq); - BUG(); -} - -#endif /* __ASM_HARDIRQ_H */ From jimix at watson.ibm.com Sat Sep 17 03:21:50 2005 From: jimix at watson.ibm.com (Jimi Xenidis) Date: Fri, 16 Sep 2005 13:21:50 -0400 Subject: [PATCH] Fix Make warning about zImage multiple dependencies Message-ID: <17194.65326.779351.773644@kitch0.watson.ibm.com> The patch from http://patchwork.ozlabs.org/linuxppc64/patch?id=2022 Causes a make warning if multiple CONFIG_PPC_* cause zImage to be in the dependency line more than once. The following patch fixes it in a way that avoids complex if's, tho it may be a little obscure :) Signed-off-by: Jimi Xenidis --- a/arch/ppc64/Makefile Wed Sep 14 15:48:20 2005 +++ b/arch/ppc64/Makefile Fri Sep 16 13:08:46 2005 @@ -89,11 +89,14 @@ boot := arch/ppc64/boot -boottargets-$(CONFIG_PPC_PSERIES) += zImage zImage.initrd +use-zImage-$(CONFIG_PPC_PSERIES) = y +use-zImage-$(CONFIG_PPC_MAPLE) = y +use-zImage-$(CONFIG_PPC_BPA) = y + +boottargets-$(use-zImage-y) += zImage zImage.initrd boottargets-$(CONFIG_PPC_PMAC) += zImage.vmode zImage.initrd.vmode -boottargets-$(CONFIG_PPC_MAPLE) += zImage zImage.initrd boottargets-$(CONFIG_PPC_ISERIES) += vmlinux.sminitrd vmlinux.initrd vmlinux.sm -boottargets-$(CONFIG_PPC_BPA) += zImage zImage.initrd + $(boottargets-y): vmlinux $(Q)$(MAKE) $(build)=$(boot) $(boot)/$@ From apw at us.ibm.com Sat Sep 17 07:31:57 2005 From: apw at us.ibm.com (Amos Waterland) Date: Fri, 16 Sep 2005 17:31:57 -0400 Subject: [PATCH] fix arch/ppc64/kernel/rtc.c warnings Message-ID: <20050916213157.GA8644@kvasir.watson.ibm.com> If CONFIG_PROC_FS is not asserted, the compiler emits: arch/ppc64/kernel/rtc.c:257: warning: `rtc_read_proc' defined but not used Here is a patch to fix that. It can provide a decent space savings: text data bss dec hex filename - 2956 728 0 3684 e64 arch/ppc64/kernel/rtc.o + 2500 664 0 3164 c5c arch/ppc64/kernel/rtc.o Signed-off-by: Amos Waterland --- arch/ppc64/kernel/rtc.c | 5 +++++ 1 files changed, 5 insertions(+), 0 deletions(-) d0406aebf5994722b82afaf82561e2e969420a71 diff --git a/arch/ppc64/kernel/rtc.c b/arch/ppc64/kernel/rtc.c --- a/arch/ppc64/kernel/rtc.c +++ b/arch/ppc64/kernel/rtc.c @@ -60,8 +60,10 @@ static ssize_t rtc_read(struct file *fil static int rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg); +#ifdef CONFIG_PROC_FS static int rtc_read_proc(char *page, char **start, off_t off, int count, int *eof, void *data); +#endif /* * If this driver ever becomes modularised, it will be really nice @@ -219,6 +221,8 @@ static void __exit rtc_exit (void) module_init(rtc_init); module_exit(rtc_exit); +#ifdef CONFIG_PROC_FS + /* * Info exported via "/proc/driver/rtc". */ @@ -263,6 +267,7 @@ static int rtc_read_proc(char *page, cha if (len<0) len = 0; return len; } +#endif /* CONFIG_PROC_FS */ #ifdef CONFIG_PPC_ISERIES /* From kumar.gala at freescale.com Sat Sep 17 07:40:17 2005 From: kumar.gala at freescale.com (Kumar Gala) Date: Fri, 16 Sep 2005 16:40:17 -0500 Subject: [PATCH] powerpc: merge include/asm/cputable.h In-Reply-To: <200509160511.39277.arnd@arndb.de> References: <200509160511.39277.arnd@arndb.de> Message-ID: <17FA692D-4643-4390-AE8A-AEF6F716C5EE@freescale.com> Ok, I've given into the enum as I dont see anything better. However, I do have some questions, why introduce new Kconfig options for ppc64. It seems overkill to have specific build options for each "class" of ppc64. One could make the argument we should go do the same thing for classic ppc32. From an embedded point of view I could reduce down to the specific cpu I'm using. I really dont think we want to start doing this. If we did I would have to say we would have to add Kconfig for 601, 603, 604, 750 (740, 750, 755), 7400 (7400/7410), 7450 (744x/745x). That's six more Kconfig options I'm ok with the patch, but think we should drop the arch/ppc64/ Kconfig portion and its related effects. Also, I've changed CPU_FTR to CPU_FTRS for the "left hand side" of the enum. - kumar On Sep 15, 2005, at 10:11 PM, Arnd Bergmann wrote: > On Freedag 16 September 2005 04:22, Kumar Gala wrote: > > >>> #define CPU_FTR_POSSIBLE CPU_FTR_PSERIES_POSSIBLE | >>> CPU_FTR_PMAC_POSSIBLE \ >>> | CPU_FTR_... >>> #define CPU_FTR_ALWAYS CPU_FTR_POSSIBLE & CPU_FTR_PSERIES_ALWAYS \ >>> & CPU_FTR_PMAC_ALWAYS & CPU_FTR_ ... >>> >> >> Yes, something like that. Why do we need the CPU_FTR_ALWAYS. It >> seems that CPU_FTR_POSSIBLE is sufficient. I may just not understand >> the purpose of CPU_FTR_ALWAYS. >> >> >>> One point to consider is that we traditionally use #ifdef in the >>> source for many places that could simply use cpu_has_feature(). E.g. >>> most instances of #ifdef CONFIG_ALTIVEC could be replaced by >>> cpu_has_feature(CPU_FTR_ALTIVEC) without additional run-time >>> overhead. >>> >> >> These should stay as CONFIG options because to reduce the code size >> of the kernel which is important to embedded people. >> > > The whole point of the logic is to reduce code size, because gcc > is smart enough to remove all dead code then. > Consider again the definition of > > | static inline int have_feature(unsigned long feature) > | { > | return (FEATURE_ALWAYS & feature) || > | (FEATURE_POSSIBLE & runtime_feature & feature); > | } > > If the feature is part of FEATURE_ALWAYS, this will be optimized to > > | return 1 || FEATURE_POSSIBLE & runtime_feature & feature; > > and subsequently > > | return 1; > > If it is not part of FEATURE_POSSIBLE, it it equivalent to > > | return 0 || (0 & runtime_feature & feature); > > which becomes > > | return 0; > > > Any code inside of > > | if (0) { /* ... */ } > > is only checked for syntax by gcc but will not end up in the object > code. > For the 'if(1)' case, the code gets smaller as well, because the > runtime > flag does not have to be dereferenced. > > For some places, we might prefer to replace '#ifdef CONFIG_FOO' not > with > have_feature(FOO), but rather with feature_possible(FOO), given a > definition > of > > static inline int have_feature(unsigned int feature) > { > return !!(FEATURE_POSSIBLE & feature); > } > > which always get evaluated at compile time. > > Arnd <>< > From arnd at arndb.de Sat Sep 17 10:36:35 2005 From: arnd at arndb.de (Arnd Bergmann) Date: Sat, 17 Sep 2005 02:36:35 +0200 Subject: [PATCH] powerpc: merge include/asm/cputable.h In-Reply-To: <17FA692D-4643-4390-AE8A-AEF6F716C5EE@freescale.com> References: <200509160511.39277.arnd@arndb.de> <17FA692D-4643-4390-AE8A-AEF6F716C5EE@freescale.com> Message-ID: <200509170236.35963.> On Freedag 16 September 2005 23:40, Kumar Gala wrote: > However, I do have some questions, why introduce new Kconfig options ? > for ppc64. ?It seems overkill to have specific build options for each ? > "class" of ppc64. ?One could make the argument we should go do the ? > same thing for classic ppc32. ?From an embedded point of view I could ? > reduce down to the specific cpu I'm using. ?I really dont think we ? > want to start doing this. Note that the configuration options that my patch introduced are all autodetected from the existing platform CONFIG_PPC_ symbols, so they don't give you extra settings that might be messed up. Having the options makes the enum in cpufeatures.h more readable imho, but if you want to do a patch without them, I wont complain. > If we did I would have to say we would have to add Kconfig for 601, ? > 603, 604, 750 (740, 750, 755), 7400 (7400/7410), 7450 (744x/745x). ? > That's six more Kconfig options I actually like the idea more flexibility to which CPU optimizations you get in the kernel. These could be combined with the gcc -mcpu= argument, if there is a way for Kconfig to deduce the most generic cpu type that still supports all selected models. The easiest way to do something like this should be to add more choices to the existing "Processor Type" submenu instead of having each one selectable separately. Something tells me that the platform and CPU type selection will keep us busy for some time, because they are currently treated very differently in ppc and ppc64. Please tell me if I understand this correctly: In ppc, the user can select one out of 27 platforms and one out of seven separate sets of CPUs. All platforms except CHRP/PowerMac/PReP can only ever work with a specific CPU selection, while that one platform has the choice between 6xx/7xx/74xx/52xx/82xx/83xx, POWER3 and POWER4/970. These connections are currently not documented. In ppc64, the user has to choose between the legacy iSeries and the generic platform. Generic means any combination of pSeries, PowerMac, Cell or Maple. The only CPU selection possibility is 'any cpu' or 'Power4 or better'. In future, we will have at least a third option 'Book E' (or e700), which is incompatible with the others. With my patch applied, the kernel would automatically disable support for CPUs that are not possible with the selected platform setting. Arnd <>< From sfr at canb.auug.org.au Sat Sep 17 14:35:11 2005 From: sfr at canb.auug.org.au (Stephen Rothwell) Date: Sat, 17 Sep 2005 14:35:11 +1000 Subject: [PATCH] Fix Make warning about zImage multiple dependencies In-Reply-To: <17194.65326.779351.773644@kitch0.watson.ibm.com> References: <17194.65326.779351.773644@kitch0.watson.ibm.com> Message-ID: <20050917143511.67f0fc33.sfr@canb.auug.org.au> On Fri, 16 Sep 2005 13:21:50 -0400 Jimi Xenidis wrote: > > -boottargets-$(CONFIG_PPC_PSERIES) += zImage zImage.initrd > +use-zImage-$(CONFIG_PPC_PSERIES) = y > +use-zImage-$(CONFIG_PPC_MAPLE) = y > +use-zImage-$(CONFIG_PPC_BPA) = y > + > +boottargets-$(use-zImage-y) += zImage zImage.initrd > boottargets-$(CONFIG_PPC_PMAC) += zImage.vmode zImage.initrd.vmode > -boottargets-$(CONFIG_PPC_MAPLE) += zImage zImage.initrd > boottargets-$(CONFIG_PPC_ISERIES) += vmlinux.sminitrd vmlinux.initrd vmlinux.sm > -boottargets-$(CONFIG_PPC_BPA) += zImage zImage.initrd We are getting clever, aren't we? :-) I like it. -- 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/20050917/43bb754f/attachment.pgp From arnd at arndb.de Sat Sep 17 16:58:41 2005 From: arnd at arndb.de (Arnd Bergmann) Date: Sat, 17 Sep 2005 08:58:41 +0200 Subject: [patch 08/11] spufs: make mem files mmappable In-Reply-To: <20050916123314.366475000@localhost> References: <20050916121646.387617000@localhost> <20050916123314.366475000@localhost> Message-ID: <200509170858.41724.arnd@arndb.de> On Freedag 16 September 2005 14:16, Arnd Bergmann wrote: > This should get better as soon as extreme sparsemem gets merged. > Actually, it first got worse. The initialization for the SPU page structures broke with the inclusion of extreme sparsemem in current kernels. This patch works around that problem by further moving code around. I still need to find a way to do this in a cleaner way, but for now, it restores the basic functionality. Signed-off-by: Arnd Bergmann Index: linux-cg/include/asm-ppc64/spu.h =================================================================== --- linux-cg.orig/include/asm-ppc64/spu.h +++ linux-cg/include/asm-ppc64/spu.h @@ -167,6 +167,13 @@ static inline void unregister_spu_syscal } #endif /* MODULE */ +#if defined(CONFIG_SPARSEMEM) && defined(CONFIG_PPC_BPA) +void __init bpa_spumem_init(int early); +#else +static inline void bpa_spumem_init(int early) +{ +} +#endif /* * This defines the Local Store, Problem Area and Privlege Area of an SPU. Index: linux-cg/arch/ppc64/kernel/bpa_setup.c =================================================================== --- linux-cg.orig/arch/ppc64/kernel/bpa_setup.c +++ linux-cg/arch/ppc64/kernel/bpa_setup.c @@ -122,7 +122,7 @@ static void __init bpa_spuprop_present(s } } -static void __init bpa_spumem_init(int early) +void __init bpa_spumem_init(int early) { struct device_node *node; for (node = of_find_node_by_type(NULL, "spe"); @@ -133,10 +133,6 @@ static void __init bpa_spumem_init(int e bpa_spuprop_present(node, "priv2", early); } } -#else -static void __init bpa_spumem_init(int early) -{ -} #endif static void bpa_progress(char *s, unsigned short hex) @@ -187,8 +183,6 @@ static void __init bpa_init_early(void) ppc64_interrupt_controller = IC_BPA_IIC; - bpa_spumem_init(1); - DBG(" <- bpa_init_early()\n"); } Index: linux-cg/arch/ppc64/kernel/setup.c =================================================================== --- linux-cg.orig/arch/ppc64/kernel/setup.c +++ linux-cg/arch/ppc64/kernel/setup.c @@ -58,6 +58,7 @@ #include #include #include +#include #ifdef DEBUG #define DBG(fmt...) udbg_printf(fmt) @@ -1042,6 +1043,8 @@ void __init setup_arch(char **cmdline_p) /* set up the bootmem stuff with available memory */ do_init_bootmem(); + bpa_spumem_init(1); + sparse_init(); /* initialize the syscall map in systemcfg */ From adobriyan at gmail.com Sat Sep 17 18:10:07 2005 From: adobriyan at gmail.com (Alexey Dobriyan) Date: Sat, 17 Sep 2005 12:10:07 +0400 Subject: ppc64: BPA iommu fails to build (BUILD_BUG_ON) Message-ID: <20050917081006.GA18713@mipter.zuzino.mipt.ru> After a patch to make BUILD_BUG_ON error at compile-time went in 2.6.14-git1, arch/ppc64/kernel/bpa_iommu.c fails to build: CC arch/ppc64/kernel/bpa_iommu.o arch/ppc64/kernel/bpa_iommu.c: In function `get_iost_entry': arch/ppc64/kernel/bpa_iommu.c:102: error: size of array `type name' is negative static inline __attribute__((always_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; shift = 5; break; ... default: ((void)sizeof(char[1 - 2*!!(1)])); break; ioste = get_iost_entry(0x10000000000ul, address, 0x1000000); ^^^^^^^^^ gcc is powerpc64-unknown-linux-gnu-gcc (GCC) 3.4.4 (Gentoo 3.4.4-r1) From linuxppc at jdl.com Sun Sep 18 01:31:52 2005 From: linuxppc at jdl.com (Jon Loeliger) Date: Sat, 17 Sep 2005 10:31:52 -0500 Subject: PATCH powerpc: 00/04 Remove __pmac, etc, sections, merge sections.h Message-ID: Here is a new patch that removes all notion of the pmac, prep, chrp and openfirmware initialization sections, and then unifies the sections.h files without those __pmac, etc, sections identifiers cluttering things up. Signed-off-by: Jon Loeliger Signed-off-by: Kumar Gala --- Part 01/04 - Remove sections use from ppc arch/ppc/kernel/pci.c | 10 +- arch/ppc/kernel/setup.c | 2 arch/ppc/platforms/chrp_pci.c | 8 +- arch/ppc/platforms/chrp_setup.c | 16 ++- arch/ppc/platforms/chrp_smp.c | 2 arch/ppc/platforms/chrp_time.c | 8 +- arch/ppc/platforms/pmac_backlight.c | 16 ++- arch/ppc/platforms/pmac_cpufreq.c | 36 ++++--- arch/ppc/platforms/pmac_feature.c | 176 ++++++++++++++++++----------------- arch/ppc/platforms/pmac_nvram.c | 42 ++++---- arch/ppc/platforms/pmac_pci.c | 22 ++-- arch/ppc/platforms/pmac_pic.c | 26 +++-- arch/ppc/platforms/pmac_setup.c | 12 +- arch/ppc/platforms/pmac_smp.c | 10 +- arch/ppc/platforms/pmac_time.c | 8 +- arch/ppc/platforms/prep_pci.c | 64 ++++++------- arch/ppc/platforms/prep_setup.c | 44 ++++----- arch/ppc/platforms/residual.c | 2 arch/ppc/syslib/btext.c | 6 + arch/ppc/syslib/prep_nvram.c | 13 +-- arch/ppc/syslib/prom.c | 18 ++-- Part 02/04 - Remove sections use from ppc64 and drivers arch/ppc64/kernel/pmac_feature.c | 60 ++++++------ arch/ppc64/kernel/pmac_nvram.c | 30 +++--- arch/ppc64/kernel/pmac_pci.c | 12 +- arch/ppc64/kernel/pmac_setup.c | 10 +- arch/ppc64/kernel/pmac_smp.c | 2 arch/ppc64/kernel/pmac_time.c | 4 - drivers/ide/ppc/pmac.c | 80 ++++++++-------- drivers/macintosh/ans-lcd.c | 10 +- drivers/macintosh/mediabay.c | 56 ++++++----- drivers/macintosh/via-cuda.c | 1 drivers/macintosh/via-pmu.c | 129 +++++++++++++------------- drivers/macintosh/via-pmu68k.c | 15 +-- Part 03/04 - Remove section free() and linker script arch/ppc/kernel/vmlinux.lds.S | 26 ----- arch/ppc/mm/init.c | 12 -- Part 04/04 - Merge simplified sections.h into asm-powerpc include/asm-powerpc/sections.h | 20 ++++ include/asm-ppc/sections.h | 33 ------- include/asm-ppc64/sections.h | 29 ------ 38 files changed, 492 insertions(+), 578 deletions(-) From linuxppc at jdl.com Sun Sep 18 01:35:08 2005 From: linuxppc at jdl.com (Jon Loeliger) Date: Sat, 17 Sep 2005 10:35:08 -0500 Subject: PATCH powerpc: 01/04 Remove sections use from ppc In-Reply-To: Your message of "Sat, 17 Sep 2005 10:31:52 CDT." References: Message-ID: diff --git a/arch/ppc/kernel/pci.c b/arch/ppc/kernel/pci.c --- a/arch/ppc/kernel/pci.c +++ b/arch/ppc/kernel/pci.c @@ -644,7 +644,7 @@ pcibios_alloc_controller(void) /* * Functions below are used on OpenFirmware machines. */ -static void __openfirmware +static void make_one_node_map(struct device_node* node, u8 pci_bus) { int *bus_range; @@ -678,7 +678,7 @@ make_one_node_map(struct device_node* no } } -void __openfirmware +void pcibios_make_OF_bus_map(void) { int i; @@ -720,7 +720,7 @@ pcibios_make_OF_bus_map(void) typedef int (*pci_OF_scan_iterator)(struct device_node* node, void* data); -static struct device_node* __openfirmware +static struct device_node* scan_OF_pci_childs(struct device_node* node, pci_OF_scan_iterator filter, void* data) { struct device_node* sub_node; @@ -761,7 +761,7 @@ scan_OF_pci_childs_iterator(struct devic return 0; } -static struct device_node* __openfirmware +static struct device_node* scan_OF_childs_for_device(struct device_node* node, u8 bus, u8 dev_fn) { u8 filter_data[2] = {bus, dev_fn}; @@ -842,7 +842,7 @@ pci_find_hose_for_OF_device(struct devic return NULL; } -static int __openfirmware +static int find_OF_pci_device_filter(struct device_node* node, void* data) { return ((void *)node == data); diff --git a/arch/ppc/kernel/setup.c b/arch/ppc/kernel/setup.c --- a/arch/ppc/kernel/setup.c +++ b/arch/ppc/kernel/setup.c @@ -339,7 +339,7 @@ early_init(int r3, int r4, int r5) * Assume here that all clock rates are the same in a * smp system. -- Cort */ -int __openfirmware +int of_show_percpuinfo(struct seq_file *m, int i) { struct device_node *cpu_node; diff --git a/arch/ppc/platforms/chrp_pci.c b/arch/ppc/platforms/chrp_pci.c --- a/arch/ppc/platforms/chrp_pci.c +++ b/arch/ppc/platforms/chrp_pci.c @@ -29,7 +29,7 @@ void __iomem *gg2_pci_config_base; * limit the bus number to 3 bits */ -int __chrp gg2_read_config(struct pci_bus *bus, unsigned int devfn, int off, +int gg2_read_config(struct pci_bus *bus, unsigned int devfn, int off, int len, u32 *val) { volatile void __iomem *cfg_data; @@ -56,7 +56,7 @@ int __chrp gg2_read_config(struct pci_bu return PCIBIOS_SUCCESSFUL; } -int __chrp gg2_write_config(struct pci_bus *bus, unsigned int devfn, int off, +int gg2_write_config(struct pci_bus *bus, unsigned int devfn, int off, int len, u32 val) { volatile void __iomem *cfg_data; @@ -92,7 +92,7 @@ static struct pci_ops gg2_pci_ops = /* * Access functions for PCI config space using RTAS calls. */ -int __chrp +int rtas_read_config(struct pci_bus *bus, unsigned int devfn, int offset, int len, u32 *val) { @@ -108,7 +108,7 @@ rtas_read_config(struct pci_bus *bus, un return rval? PCIBIOS_DEVICE_NOT_FOUND: PCIBIOS_SUCCESSFUL; } -int __chrp +int rtas_write_config(struct pci_bus *bus, unsigned int devfn, int offset, int len, u32 val) { diff --git a/arch/ppc/platforms/chrp_setup.c b/arch/ppc/platforms/chrp_setup.c --- a/arch/ppc/platforms/chrp_setup.c +++ b/arch/ppc/platforms/chrp_setup.c @@ -105,7 +105,7 @@ static const char *gg2_cachemodes[4] = { "Disabled", "Write-Through", "Copy-Back", "Transparent Mode" }; -int __chrp +int chrp_show_cpuinfo(struct seq_file *m) { int i, sdramen; @@ -303,7 +303,7 @@ void __init chrp_setup_arch(void) pci_create_OF_bus_map(); } -void __chrp +void chrp_event_scan(void) { unsigned char log[1024]; @@ -314,7 +314,7 @@ chrp_event_scan(void) ppc_md.heartbeat_count = ppc_md.heartbeat_reset; } -void __chrp +void chrp_restart(char *cmd) { printk("RTAS system-reboot returned %d\n", @@ -322,7 +322,7 @@ chrp_restart(char *cmd) for (;;); } -void __chrp +void chrp_power_off(void) { /* allow power on only with power button press */ @@ -331,13 +331,13 @@ chrp_power_off(void) for (;;); } -void __chrp +void chrp_halt(void) { chrp_power_off(); } -u_int __chrp +u_int chrp_irq_canonicalize(u_int irq) { if (irq == 2) @@ -572,7 +572,7 @@ chrp_init(unsigned long r3, unsigned lon if (ppc_md.progress) ppc_md.progress("Linux/PPC "UTS_RELEASE"\n", 0x0); } -void __chrp +void rtas_display_progress(char *s, unsigned short hex) { int width; @@ -599,7 +599,7 @@ rtas_display_progress(char *s, unsigned call_rtas( "display-character", 1, 1, NULL, ' ' ); } -void __chrp +void rtas_indicator_progress(char *s, unsigned short hex) { call_rtas("set-indicator", 3, 1, NULL, 6, 0, hex); diff --git a/arch/ppc/platforms/chrp_smp.c b/arch/ppc/platforms/chrp_smp.c --- a/arch/ppc/platforms/chrp_smp.c +++ b/arch/ppc/platforms/chrp_smp.c @@ -88,7 +88,7 @@ smp_chrp_take_timebase(void) } /* CHRP with openpic */ -struct smp_ops_t chrp_smp_ops __chrpdata = { +struct smp_ops_t chrp_smp_ops = { .message_pass = smp_openpic_message_pass, .probe = smp_chrp_probe, .kick_cpu = smp_chrp_kick_cpu, diff --git a/arch/ppc/platforms/chrp_time.c b/arch/ppc/platforms/chrp_time.c --- a/arch/ppc/platforms/chrp_time.c +++ b/arch/ppc/platforms/chrp_time.c @@ -52,7 +52,7 @@ long __init chrp_time_init(void) return 0; } -int __chrp chrp_cmos_clock_read(int addr) +int chrp_cmos_clock_read(int addr) { if (nvram_as1 != 0) outb(addr>>8, nvram_as1); @@ -60,7 +60,7 @@ int __chrp chrp_cmos_clock_read(int addr return (inb(nvram_data)); } -void __chrp chrp_cmos_clock_write(unsigned long val, int addr) +void chrp_cmos_clock_write(unsigned long val, int addr) { if (nvram_as1 != 0) outb(addr>>8, nvram_as1); @@ -72,7 +72,7 @@ void __chrp chrp_cmos_clock_write(unsign /* * Set the hardware clock. -- Cort */ -int __chrp chrp_set_rtc_time(unsigned long nowtime) +int chrp_set_rtc_time(unsigned long nowtime) { unsigned char save_control, save_freq_select; struct rtc_time tm; @@ -118,7 +118,7 @@ int __chrp chrp_set_rtc_time(unsigned lo return 0; } -unsigned long __chrp chrp_get_rtc_time(void) +unsigned long chrp_get_rtc_time(void) { unsigned int year, mon, day, hour, min, sec; int uip, i; diff --git a/arch/ppc/platforms/pmac_backlight.c b/arch/ppc/platforms/pmac_backlight.c --- a/arch/ppc/platforms/pmac_backlight.c +++ b/arch/ppc/platforms/pmac_backlight.c @@ -37,7 +37,7 @@ static int backlight_req_enable = -1; static void backlight_callback(void *); static DECLARE_WORK(backlight_work, backlight_callback, NULL); -void __pmac register_backlight_controller(struct backlight_controller *ctrler, +void register_backlight_controller(struct backlight_controller *ctrler, void *data, char *type) { struct device_node* bk_node; @@ -99,7 +99,7 @@ void __pmac register_backlight_controlle } EXPORT_SYMBOL(register_backlight_controller); -void __pmac unregister_backlight_controller(struct backlight_controller +void unregister_backlight_controller(struct backlight_controller *ctrler, void *data) { /* We keep the current backlight level (for now) */ @@ -108,7 +108,7 @@ void __pmac unregister_backlight_control } EXPORT_SYMBOL(unregister_backlight_controller); -static int __pmac __set_backlight_enable(int enable) +static int __set_backlight_enable(int enable) { int rc; @@ -122,7 +122,7 @@ static int __pmac __set_backlight_enable release_console_sem(); return rc; } -int __pmac set_backlight_enable(int enable) +int set_backlight_enable(int enable) { if (!backlighter) return -ENODEV; @@ -133,7 +133,7 @@ int __pmac set_backlight_enable(int enab EXPORT_SYMBOL(set_backlight_enable); -int __pmac get_backlight_enable(void) +int get_backlight_enable(void) { if (!backlighter) return -ENODEV; @@ -141,7 +141,7 @@ int __pmac get_backlight_enable(void) } EXPORT_SYMBOL(get_backlight_enable); -static int __pmac __set_backlight_level(int level) +static int __set_backlight_level(int level) { int rc = 0; @@ -165,7 +165,7 @@ static int __pmac __set_backlight_level( } return rc; } -int __pmac set_backlight_level(int level) +int set_backlight_level(int level) { if (!backlighter) return -ENODEV; @@ -176,7 +176,7 @@ int __pmac set_backlight_level(int level EXPORT_SYMBOL(set_backlight_level); -int __pmac get_backlight_level(void) +int get_backlight_level(void) { if (!backlighter) return -ENODEV; diff --git a/arch/ppc/platforms/pmac_cpufreq.c b/arch/ppc/platforms/pmac_cpufreq.c --- a/arch/ppc/platforms/pmac_cpufreq.c +++ b/arch/ppc/platforms/pmac_cpufreq.c @@ -136,7 +136,7 @@ static inline void debug_calc_bogomips(v /* Switch CPU speed under 750FX CPU control */ -static int __pmac cpu_750fx_cpu_speed(int low_speed) +static int cpu_750fx_cpu_speed(int low_speed) { u32 hid2; @@ -172,7 +172,7 @@ static int __pmac cpu_750fx_cpu_speed(in return 0; } -static unsigned int __pmac cpu_750fx_get_cpu_speed(void) +static unsigned int cpu_750fx_get_cpu_speed(void) { if (mfspr(SPRN_HID1) & HID1_PS) return low_freq; @@ -181,7 +181,7 @@ static unsigned int __pmac cpu_750fx_get } /* Switch CPU speed using DFS */ -static int __pmac dfs_set_cpu_speed(int low_speed) +static int dfs_set_cpu_speed(int low_speed) { if (low_speed == 0) { /* ramping up, set voltage first */ @@ -205,7 +205,7 @@ static int __pmac dfs_set_cpu_speed(int return 0; } -static unsigned int __pmac dfs_get_cpu_speed(void) +static unsigned int dfs_get_cpu_speed(void) { if (mfspr(SPRN_HID1) & HID1_DFS) return low_freq; @@ -216,7 +216,7 @@ static unsigned int __pmac dfs_get_cpu_s /* Switch CPU speed using slewing GPIOs */ -static int __pmac gpios_set_cpu_speed(int low_speed) +static int gpios_set_cpu_speed(int low_speed) { int gpio, timeout = 0; @@ -258,7 +258,7 @@ static int __pmac gpios_set_cpu_speed(in /* Switch CPU speed under PMU control */ -static int __pmac pmu_set_cpu_speed(int low_speed) +static int pmu_set_cpu_speed(int low_speed) { struct adb_request req; unsigned long save_l2cr; @@ -354,7 +354,7 @@ static int __pmac pmu_set_cpu_speed(int return 0; } -static int __pmac do_set_cpu_speed(int speed_mode, int notify) +static int do_set_cpu_speed(int speed_mode, int notify) { struct cpufreq_freqs freqs; unsigned long l3cr; @@ -391,17 +391,17 @@ static int __pmac do_set_cpu_speed(int s return 0; } -static unsigned int __pmac pmac_cpufreq_get_speed(unsigned int cpu) +static unsigned int pmac_cpufreq_get_speed(unsigned int cpu) { return cur_freq; } -static int __pmac pmac_cpufreq_verify(struct cpufreq_policy *policy) +static int pmac_cpufreq_verify(struct cpufreq_policy *policy) { return cpufreq_frequency_table_verify(policy, pmac_cpu_freqs); } -static int __pmac pmac_cpufreq_target( struct cpufreq_policy *policy, +static int pmac_cpufreq_target( struct cpufreq_policy *policy, unsigned int target_freq, unsigned int relation) { @@ -414,13 +414,13 @@ static int __pmac pmac_cpufreq_target( s return do_set_cpu_speed(newstate, 1); } -unsigned int __pmac pmac_get_one_cpufreq(int i) +unsigned int pmac_get_one_cpufreq(int i) { /* Supports only one CPU for now */ return (i == 0) ? cur_freq : 0; } -static int __pmac pmac_cpufreq_cpu_init(struct cpufreq_policy *policy) +static int pmac_cpufreq_cpu_init(struct cpufreq_policy *policy) { if (policy->cpu != 0) return -ENODEV; @@ -433,7 +433,7 @@ static int __pmac pmac_cpufreq_cpu_init( return cpufreq_frequency_table_cpuinfo(policy, pmac_cpu_freqs); } -static u32 __pmac read_gpio(struct device_node *np) +static u32 read_gpio(struct device_node *np) { u32 *reg = (u32 *)get_property(np, "reg", NULL); u32 offset; @@ -452,7 +452,7 @@ static u32 __pmac read_gpio(struct devic return offset; } -static int __pmac pmac_cpufreq_suspend(struct cpufreq_policy *policy, pm_message_t pmsg) +static int pmac_cpufreq_suspend(struct cpufreq_policy *policy, pm_message_t pmsg) { /* Ok, this could be made a bit smarter, but let's be robust for now. We * always force a speed change to high speed before sleep, to make sure @@ -468,7 +468,7 @@ static int __pmac pmac_cpufreq_suspend(s return 0; } -static int __pmac pmac_cpufreq_resume(struct cpufreq_policy *policy) +static int pmac_cpufreq_resume(struct cpufreq_policy *policy) { /* If we resume, first check if we have a get() function */ if (get_speed_proc) @@ -501,7 +501,7 @@ static struct cpufreq_driver pmac_cpufre }; -static int __pmac pmac_cpufreq_init_MacRISC3(struct device_node *cpunode) +static int pmac_cpufreq_init_MacRISC3(struct device_node *cpunode) { struct device_node *volt_gpio_np = of_find_node_by_name(NULL, "voltage-gpio"); @@ -593,7 +593,7 @@ static int __pmac pmac_cpufreq_init_MacR return 0; } -static int __pmac pmac_cpufreq_init_7447A(struct device_node *cpunode) +static int pmac_cpufreq_init_7447A(struct device_node *cpunode) { struct device_node *volt_gpio_np; @@ -620,7 +620,7 @@ static int __pmac pmac_cpufreq_init_7447 return 0; } -static int __pmac pmac_cpufreq_init_750FX(struct device_node *cpunode) +static int pmac_cpufreq_init_750FX(struct device_node *cpunode) { struct device_node *volt_gpio_np; u32 pvr, *value; diff --git a/arch/ppc/platforms/pmac_feature.c b/arch/ppc/platforms/pmac_feature.c --- a/arch/ppc/platforms/pmac_feature.c +++ b/arch/ppc/platforms/pmac_feature.c @@ -63,7 +63,7 @@ extern struct device_node *k2_skiplist[2 * We use a single global lock to protect accesses. Each driver has * to take care of its own locking */ -static DEFINE_SPINLOCK(feature_lock __pmacdata); +static DEFINE_SPINLOCK(feature_lock); #define LOCK(flags) spin_lock_irqsave(&feature_lock, flags); #define UNLOCK(flags) spin_unlock_irqrestore(&feature_lock, flags); @@ -72,9 +72,9 @@ static DEFINE_SPINLOCK(feature_lock __p /* * Instance of some macio stuffs */ -struct macio_chip macio_chips[MAX_MACIO_CHIPS] __pmacdata; +struct macio_chip macio_chips[MAX_MACIO_CHIPS]; -struct macio_chip* __pmac macio_find(struct device_node* child, int type) +struct macio_chip* macio_find(struct device_node* child, int type) { while(child) { int i; @@ -89,7 +89,7 @@ struct macio_chip* __pmac macio_find(str } EXPORT_SYMBOL_GPL(macio_find); -static const char* macio_names[] __pmacdata = +static const char* macio_names[] = { "Unknown", "Grand Central", @@ -116,10 +116,10 @@ static const char* macio_names[] __pmacd #define UN_BIS(r,v) (UN_OUT((r), UN_IN(r) | (v))) #define UN_BIC(r,v) (UN_OUT((r), UN_IN(r) & ~(v))) -static struct device_node* uninorth_node __pmacdata; -static u32 __iomem * uninorth_base __pmacdata; -static u32 uninorth_rev __pmacdata; -static int uninorth_u3 __pmacdata; +static struct device_node* uninorth_node; +static u32 __iomem * uninorth_base; +static u32 uninorth_rev; +static int uninorth_u3; static void __iomem *u3_ht; /* @@ -142,13 +142,13 @@ struct pmac_mb_def struct feature_table_entry* features; unsigned long board_flags; }; -static struct pmac_mb_def pmac_mb __pmacdata; +static struct pmac_mb_def pmac_mb; /* * Here are the chip specific feature functions */ -static inline int __pmac +static inline int simple_feature_tweak(struct device_node* node, int type, int reg, u32 mask, int value) { struct macio_chip* macio; @@ -170,7 +170,7 @@ simple_feature_tweak(struct device_node* #ifndef CONFIG_POWER4 -static long __pmac +static long ohare_htw_scc_enable(struct device_node* node, long param, long value) { struct macio_chip* macio; @@ -263,21 +263,21 @@ ohare_htw_scc_enable(struct device_node* return 0; } -static long __pmac +static long ohare_floppy_enable(struct device_node* node, long param, long value) { return simple_feature_tweak(node, macio_ohare, OHARE_FCR, OH_FLOPPY_ENABLE, value); } -static long __pmac +static long ohare_mesh_enable(struct device_node* node, long param, long value) { return simple_feature_tweak(node, macio_ohare, OHARE_FCR, OH_MESH_ENABLE, value); } -static long __pmac +static long ohare_ide_enable(struct device_node* node, long param, long value) { switch(param) { @@ -298,7 +298,7 @@ ohare_ide_enable(struct device_node* nod } } -static long __pmac +static long ohare_ide_reset(struct device_node* node, long param, long value) { switch(param) { @@ -313,7 +313,7 @@ ohare_ide_reset(struct device_node* node } } -static long __pmac +static long ohare_sleep_state(struct device_node* node, long param, long value) { struct macio_chip* macio = &macio_chips[0]; @@ -329,7 +329,7 @@ ohare_sleep_state(struct device_node* no return 0; } -static long __pmac +static long heathrow_modem_enable(struct device_node* node, long param, long value) { struct macio_chip* macio; @@ -373,7 +373,7 @@ heathrow_modem_enable(struct device_node return 0; } -static long __pmac +static long heathrow_floppy_enable(struct device_node* node, long param, long value) { return simple_feature_tweak(node, macio_unknown, @@ -382,7 +382,7 @@ heathrow_floppy_enable(struct device_nod value); } -static long __pmac +static long heathrow_mesh_enable(struct device_node* node, long param, long value) { struct macio_chip* macio; @@ -411,7 +411,7 @@ heathrow_mesh_enable(struct device_node* return 0; } -static long __pmac +static long heathrow_ide_enable(struct device_node* node, long param, long value) { switch(param) { @@ -426,7 +426,7 @@ heathrow_ide_enable(struct device_node* } } -static long __pmac +static long heathrow_ide_reset(struct device_node* node, long param, long value) { switch(param) { @@ -441,7 +441,7 @@ heathrow_ide_reset(struct device_node* n } } -static long __pmac +static long heathrow_bmac_enable(struct device_node* node, long param, long value) { struct macio_chip* macio; @@ -470,7 +470,7 @@ heathrow_bmac_enable(struct device_node* return 0; } -static long __pmac +static long heathrow_sound_enable(struct device_node* node, long param, long value) { struct macio_chip* macio; @@ -501,16 +501,16 @@ heathrow_sound_enable(struct device_node return 0; } -static u32 save_fcr[6] __pmacdata; -static u32 save_mbcr __pmacdata; -static u32 save_gpio_levels[2] __pmacdata; -static u8 save_gpio_extint[KEYLARGO_GPIO_EXTINT_CNT] __pmacdata; -static u8 save_gpio_normal[KEYLARGO_GPIO_CNT] __pmacdata; -static u32 save_unin_clock_ctl __pmacdata; -static struct dbdma_regs save_dbdma[13] __pmacdata; -static struct dbdma_regs save_alt_dbdma[13] __pmacdata; +static u32 save_fcr[6]; +static u32 save_mbcr; +static u32 save_gpio_levels[2]; +static u8 save_gpio_extint[KEYLARGO_GPIO_EXTINT_CNT]; +static u8 save_gpio_normal[KEYLARGO_GPIO_CNT]; +static u32 save_unin_clock_ctl; +static struct dbdma_regs save_dbdma[13]; +static struct dbdma_regs save_alt_dbdma[13]; -static void __pmac +static void dbdma_save(struct macio_chip* macio, struct dbdma_regs* save) { int i; @@ -527,7 +527,7 @@ dbdma_save(struct macio_chip* macio, str } } -static void __pmac +static void dbdma_restore(struct macio_chip* macio, struct dbdma_regs* save) { int i; @@ -547,7 +547,7 @@ dbdma_restore(struct macio_chip* macio, } } -static void __pmac +static void heathrow_sleep(struct macio_chip* macio, int secondary) { if (secondary) { @@ -580,7 +580,7 @@ heathrow_sleep(struct macio_chip* macio, (void)MACIO_IN32(HEATHROW_FCR); } -static void __pmac +static void heathrow_wakeup(struct macio_chip* macio, int secondary) { if (secondary) { @@ -605,7 +605,7 @@ heathrow_wakeup(struct macio_chip* macio } } -static long __pmac +static long heathrow_sleep_state(struct device_node* node, long param, long value) { if ((pmac_mb.board_flags & PMAC_MB_CAN_SLEEP) == 0) @@ -622,7 +622,7 @@ heathrow_sleep_state(struct device_node* return 0; } -static long __pmac +static long core99_scc_enable(struct device_node* node, long param, long value) { struct macio_chip* macio; @@ -723,7 +723,7 @@ core99_scc_enable(struct device_node* no return 0; } -static long __pmac +static long core99_modem_enable(struct device_node* node, long param, long value) { struct macio_chip* macio; @@ -775,7 +775,7 @@ core99_modem_enable(struct device_node* return 0; } -static long __pmac +static long pangea_modem_enable(struct device_node* node, long param, long value) { struct macio_chip* macio; @@ -830,7 +830,7 @@ pangea_modem_enable(struct device_node* return 0; } -static long __pmac +static long core99_ata100_enable(struct device_node* node, long value) { unsigned long flags; @@ -860,7 +860,7 @@ core99_ata100_enable(struct device_node* return 0; } -static long __pmac +static long core99_ide_enable(struct device_node* node, long param, long value) { /* Bus ID 0 to 2 are KeyLargo based IDE, busID 3 is U2 @@ -883,7 +883,7 @@ core99_ide_enable(struct device_node* no } } -static long __pmac +static long core99_ide_reset(struct device_node* node, long param, long value) { switch(param) { @@ -901,7 +901,7 @@ core99_ide_reset(struct device_node* nod } } -static long __pmac +static long core99_gmac_enable(struct device_node* node, long param, long value) { unsigned long flags; @@ -918,7 +918,7 @@ core99_gmac_enable(struct device_node* n return 0; } -static long __pmac +static long core99_gmac_phy_reset(struct device_node* node, long param, long value) { unsigned long flags; @@ -943,7 +943,7 @@ core99_gmac_phy_reset(struct device_node return 0; } -static long __pmac +static long core99_sound_chip_enable(struct device_node* node, long param, long value) { struct macio_chip* macio; @@ -973,7 +973,7 @@ core99_sound_chip_enable(struct device_n return 0; } -static long __pmac +static long core99_airport_enable(struct device_node* node, long param, long value) { struct macio_chip* macio; @@ -1060,7 +1060,7 @@ core99_airport_enable(struct device_node } #ifdef CONFIG_SMP -static long __pmac +static long core99_reset_cpu(struct device_node* node, long param, long value) { unsigned int reset_io = 0; @@ -1104,7 +1104,7 @@ core99_reset_cpu(struct device_node* nod } #endif /* CONFIG_SMP */ -static long __pmac +static long core99_usb_enable(struct device_node* node, long param, long value) { struct macio_chip* macio; @@ -1257,7 +1257,7 @@ core99_usb_enable(struct device_node* no return 0; } -static long __pmac +static long core99_firewire_enable(struct device_node* node, long param, long value) { unsigned long flags; @@ -1284,7 +1284,7 @@ core99_firewire_enable(struct device_nod return 0; } -static long __pmac +static long core99_firewire_cable_power(struct device_node* node, long param, long value) { unsigned long flags; @@ -1315,7 +1315,7 @@ core99_firewire_cable_power(struct devic return 0; } -static long __pmac +static long intrepid_aack_delay_enable(struct device_node* node, long param, long value) { unsigned long flags; @@ -1336,7 +1336,7 @@ intrepid_aack_delay_enable(struct device #endif /* CONFIG_POWER4 */ -static long __pmac +static long core99_read_gpio(struct device_node* node, long param, long value) { struct macio_chip* macio = &macio_chips[0]; @@ -1345,7 +1345,7 @@ core99_read_gpio(struct device_node* nod } -static long __pmac +static long core99_write_gpio(struct device_node* node, long param, long value) { struct macio_chip* macio = &macio_chips[0]; @@ -1356,7 +1356,7 @@ core99_write_gpio(struct device_node* no #ifdef CONFIG_POWER4 -static long __pmac +static long g5_gmac_enable(struct device_node* node, long param, long value) { struct macio_chip* macio = &macio_chips[0]; @@ -1380,7 +1380,7 @@ g5_gmac_enable(struct device_node* node, return 0; } -static long __pmac +static long g5_fw_enable(struct device_node* node, long param, long value) { struct macio_chip* macio = &macio_chips[0]; @@ -1403,7 +1403,7 @@ g5_fw_enable(struct device_node* node, l return 0; } -static long __pmac +static long g5_mpic_enable(struct device_node* node, long param, long value) { unsigned long flags; @@ -1419,7 +1419,7 @@ g5_mpic_enable(struct device_node* node, } #ifdef CONFIG_SMP -static long __pmac +static long g5_reset_cpu(struct device_node* node, long param, long value) { unsigned int reset_io = 0; @@ -1465,7 +1465,7 @@ g5_reset_cpu(struct device_node* node, l * This takes the second CPU off the bus on dual CPU machines * running UP */ -void __pmac g5_phy_disable_cpu1(void) +void g5_phy_disable_cpu1(void) { UN_OUT(U3_API_PHY_CONFIG_1, 0); } @@ -1474,7 +1474,7 @@ void __pmac g5_phy_disable_cpu1(void) #ifndef CONFIG_POWER4 -static void __pmac +static void keylargo_shutdown(struct macio_chip* macio, int sleep_mode) { u32 temp; @@ -1528,7 +1528,7 @@ keylargo_shutdown(struct macio_chip* mac (void)MACIO_IN32(KEYLARGO_FCR0); mdelay(1); } -static void __pmac +static void pangea_shutdown(struct macio_chip* macio, int sleep_mode) { u32 temp; @@ -1562,7 +1562,7 @@ pangea_shutdown(struct macio_chip* macio (void)MACIO_IN32(KEYLARGO_FCR0); mdelay(1); } -static void __pmac +static void intrepid_shutdown(struct macio_chip* macio, int sleep_mode) { u32 temp; @@ -1591,7 +1591,7 @@ intrepid_shutdown(struct macio_chip* mac } -void __pmac pmac_tweak_clock_spreading(int enable) +void pmac_tweak_clock_spreading(int enable) { struct macio_chip* macio = &macio_chips[0]; @@ -1698,7 +1698,7 @@ void __pmac pmac_tweak_clock_spreading(i } -static int __pmac +static int core99_sleep(void) { struct macio_chip* macio; @@ -1791,7 +1791,7 @@ core99_sleep(void) return 0; } -static int __pmac +static int core99_wake_up(void) { struct macio_chip* macio; @@ -1854,7 +1854,7 @@ core99_wake_up(void) return 0; } -static long __pmac +static long core99_sleep_state(struct device_node* node, long param, long value) { /* Param == 1 means to enter the "fake sleep" mode that is @@ -1884,7 +1884,7 @@ core99_sleep_state(struct device_node* n #endif /* CONFIG_POWER4 */ -static long __pmac +static long generic_dev_can_wake(struct device_node* node, long param, long value) { /* Todo: eventually check we are really dealing with on-board @@ -1896,7 +1896,7 @@ generic_dev_can_wake(struct device_node* return 0; } -static long __pmac +static long generic_get_mb_info(struct device_node* node, long param, long value) { switch(param) { @@ -1919,7 +1919,7 @@ generic_get_mb_info(struct device_node* /* Used on any machine */ -static struct feature_table_entry any_features[] __pmacdata = { +static struct feature_table_entry any_features[] = { { PMAC_FTR_GET_MB_INFO, generic_get_mb_info }, { PMAC_FTR_DEVICE_CAN_WAKE, generic_dev_can_wake }, { 0, NULL } @@ -1931,7 +1931,7 @@ static struct feature_table_entry any_fe * 2400,3400 and 3500 series powerbooks. Some older desktops seem * to have issues with turning on/off those asic cells */ -static struct feature_table_entry ohare_features[] __pmacdata = { +static struct feature_table_entry ohare_features[] = { { PMAC_FTR_SCC_ENABLE, ohare_htw_scc_enable }, { PMAC_FTR_SWIM3_ENABLE, ohare_floppy_enable }, { PMAC_FTR_MESH_ENABLE, ohare_mesh_enable }, @@ -1945,7 +1945,7 @@ static struct feature_table_entry ohare_ * Separated as some features couldn't be properly tested * and the serial port control bits appear to confuse it. */ -static struct feature_table_entry heathrow_desktop_features[] __pmacdata = { +static struct feature_table_entry heathrow_desktop_features[] = { { PMAC_FTR_SWIM3_ENABLE, heathrow_floppy_enable }, { PMAC_FTR_MESH_ENABLE, heathrow_mesh_enable }, { PMAC_FTR_IDE_ENABLE, heathrow_ide_enable }, @@ -1957,7 +1957,7 @@ static struct feature_table_entry heathr /* Heathrow based laptop, that is the Wallstreet and mainstreet * powerbooks. */ -static struct feature_table_entry heathrow_laptop_features[] __pmacdata = { +static struct feature_table_entry heathrow_laptop_features[] = { { PMAC_FTR_SCC_ENABLE, ohare_htw_scc_enable }, { PMAC_FTR_MODEM_ENABLE, heathrow_modem_enable }, { PMAC_FTR_SWIM3_ENABLE, heathrow_floppy_enable }, @@ -1973,7 +1973,7 @@ static struct feature_table_entry heathr /* Paddington based machines * The lombard (101) powerbook, first iMac models, B&W G3 and Yikes G4. */ -static struct feature_table_entry paddington_features[] __pmacdata = { +static struct feature_table_entry paddington_features[] = { { PMAC_FTR_SCC_ENABLE, ohare_htw_scc_enable }, { PMAC_FTR_MODEM_ENABLE, heathrow_modem_enable }, { PMAC_FTR_SWIM3_ENABLE, heathrow_floppy_enable }, @@ -1991,7 +1991,7 @@ static struct feature_table_entry paddin * chipset. The pangea chipset is the "combo" UniNorth/KeyLargo * used on iBook2 & iMac "flow power". */ -static struct feature_table_entry core99_features[] __pmacdata = { +static struct feature_table_entry core99_features[] = { { PMAC_FTR_SCC_ENABLE, core99_scc_enable }, { PMAC_FTR_MODEM_ENABLE, core99_modem_enable }, { PMAC_FTR_IDE_ENABLE, core99_ide_enable }, @@ -2014,7 +2014,7 @@ static struct feature_table_entry core99 /* RackMac */ -static struct feature_table_entry rackmac_features[] __pmacdata = { +static struct feature_table_entry rackmac_features[] = { { PMAC_FTR_SCC_ENABLE, core99_scc_enable }, { PMAC_FTR_IDE_ENABLE, core99_ide_enable }, { PMAC_FTR_IDE_RESET, core99_ide_reset }, @@ -2034,7 +2034,7 @@ static struct feature_table_entry rackma /* Pangea features */ -static struct feature_table_entry pangea_features[] __pmacdata = { +static struct feature_table_entry pangea_features[] = { { PMAC_FTR_SCC_ENABLE, core99_scc_enable }, { PMAC_FTR_MODEM_ENABLE, pangea_modem_enable }, { PMAC_FTR_IDE_ENABLE, core99_ide_enable }, @@ -2054,7 +2054,7 @@ static struct feature_table_entry pangea /* Intrepid features */ -static struct feature_table_entry intrepid_features[] __pmacdata = { +static struct feature_table_entry intrepid_features[] = { { PMAC_FTR_SCC_ENABLE, core99_scc_enable }, { PMAC_FTR_MODEM_ENABLE, pangea_modem_enable }, { PMAC_FTR_IDE_ENABLE, core99_ide_enable }, @@ -2077,7 +2077,7 @@ static struct feature_table_entry intrep /* G5 features */ -static struct feature_table_entry g5_features[] __pmacdata = { +static struct feature_table_entry g5_features[] = { { PMAC_FTR_GMAC_ENABLE, g5_gmac_enable }, { PMAC_FTR_1394_ENABLE, g5_fw_enable }, { PMAC_FTR_ENABLE_MPIC, g5_mpic_enable }, @@ -2091,7 +2091,7 @@ static struct feature_table_entry g5_fea #endif /* CONFIG_POWER4 */ -static struct pmac_mb_def pmac_mb_defs[] __pmacdata = { +static struct pmac_mb_def pmac_mb_defs[] = { #ifndef CONFIG_POWER4 /* * Desktops @@ -2352,7 +2352,7 @@ static struct pmac_mb_def pmac_mb_defs[] /* * The toplevel feature_call callback */ -long __pmac +long pmac_do_feature_call(unsigned int selector, ...) { struct device_node* node; @@ -2935,8 +2935,8 @@ void __init pmac_check_ht_link(void) * Early video resume hook */ -static void (*pmac_early_vresume_proc)(void *data) __pmacdata; -static void *pmac_early_vresume_data __pmacdata; +static void (*pmac_early_vresume_proc)(void *data); +static void *pmac_early_vresume_data; void pmac_set_early_video_resume(void (*proc)(void *data), void *data) { @@ -2949,7 +2949,7 @@ void pmac_set_early_video_resume(void (* } EXPORT_SYMBOL(pmac_set_early_video_resume); -void __pmac pmac_call_early_video_resume(void) +void pmac_call_early_video_resume(void) { if (pmac_early_vresume_proc) pmac_early_vresume_proc(pmac_early_vresume_data); @@ -2959,11 +2959,11 @@ void __pmac pmac_call_early_video_resume * AGP related suspend/resume code */ -static struct pci_dev *pmac_agp_bridge __pmacdata; -static int (*pmac_agp_suspend)(struct pci_dev *bridge) __pmacdata; -static int (*pmac_agp_resume)(struct pci_dev *bridge) __pmacdata; +static struct pci_dev *pmac_agp_bridge; +static int (*pmac_agp_suspend)(struct pci_dev *bridge); +static int (*pmac_agp_resume)(struct pci_dev *bridge); -void __pmac pmac_register_agp_pm(struct pci_dev *bridge, +void pmac_register_agp_pm(struct pci_dev *bridge, int (*suspend)(struct pci_dev *bridge), int (*resume)(struct pci_dev *bridge)) { @@ -2980,7 +2980,7 @@ void __pmac pmac_register_agp_pm(struct } EXPORT_SYMBOL(pmac_register_agp_pm); -void __pmac pmac_suspend_agp_for_card(struct pci_dev *dev) +void pmac_suspend_agp_for_card(struct pci_dev *dev) { if (pmac_agp_bridge == NULL || pmac_agp_suspend == NULL) return; @@ -2990,7 +2990,7 @@ void __pmac pmac_suspend_agp_for_card(st } EXPORT_SYMBOL(pmac_suspend_agp_for_card); -void __pmac pmac_resume_agp_for_card(struct pci_dev *dev) +void pmac_resume_agp_for_card(struct pci_dev *dev) { if (pmac_agp_bridge == NULL || pmac_agp_resume == NULL) return; diff --git a/arch/ppc/platforms/pmac_nvram.c b/arch/ppc/platforms/pmac_nvram.c --- a/arch/ppc/platforms/pmac_nvram.c +++ b/arch/ppc/platforms/pmac_nvram.c @@ -88,17 +88,17 @@ extern int system_running; static int (*core99_write_bank)(int bank, u8* datas); static int (*core99_erase_bank)(int bank); -static char *nvram_image __pmacdata; +static char *nvram_image; -static unsigned char __pmac core99_nvram_read_byte(int addr) +static unsigned char core99_nvram_read_byte(int addr) { if (nvram_image == NULL) return 0xff; return nvram_image[addr]; } -static void __pmac core99_nvram_write_byte(int addr, unsigned char val) +static void core99_nvram_write_byte(int addr, unsigned char val) { if (nvram_image == NULL) return; @@ -106,18 +106,18 @@ static void __pmac core99_nvram_write_by } -static unsigned char __openfirmware direct_nvram_read_byte(int addr) +static unsigned char direct_nvram_read_byte(int addr) { return in_8(&nvram_data[(addr & (NVRAM_SIZE - 1)) * nvram_mult]); } -static void __openfirmware direct_nvram_write_byte(int addr, unsigned char val) +static void direct_nvram_write_byte(int addr, unsigned char val) { out_8(&nvram_data[(addr & (NVRAM_SIZE - 1)) * nvram_mult], val); } -static unsigned char __pmac indirect_nvram_read_byte(int addr) +static unsigned char indirect_nvram_read_byte(int addr) { unsigned char val; unsigned long flags; @@ -130,7 +130,7 @@ static unsigned char __pmac indirect_nvr return val; } -static void __pmac indirect_nvram_write_byte(int addr, unsigned char val) +static void indirect_nvram_write_byte(int addr, unsigned char val) { unsigned long flags; @@ -143,13 +143,13 @@ static void __pmac indirect_nvram_write_ #ifdef CONFIG_ADB_PMU -static void __pmac pmu_nvram_complete(struct adb_request *req) +static void pmu_nvram_complete(struct adb_request *req) { if (req->arg) complete((struct completion *)req->arg); } -static unsigned char __pmac pmu_nvram_read_byte(int addr) +static unsigned char pmu_nvram_read_byte(int addr) { struct adb_request req; DECLARE_COMPLETION(req_complete); @@ -165,7 +165,7 @@ static unsigned char __pmac pmu_nvram_re return req.reply[0]; } -static void __pmac pmu_nvram_write_byte(int addr, unsigned char val) +static void pmu_nvram_write_byte(int addr, unsigned char val) { struct adb_request req; DECLARE_COMPLETION(req_complete); @@ -183,7 +183,7 @@ static void __pmac pmu_nvram_write_byte( #endif /* CONFIG_ADB_PMU */ -static u8 __pmac chrp_checksum(struct chrp_header* hdr) +static u8 chrp_checksum(struct chrp_header* hdr) { u8 *ptr; u16 sum = hdr->signature; @@ -194,7 +194,7 @@ static u8 __pmac chrp_checksum(struct ch return sum; } -static u32 __pmac core99_calc_adler(u8 *buffer) +static u32 core99_calc_adler(u8 *buffer) { int cnt; u32 low, high; @@ -216,7 +216,7 @@ static u32 __pmac core99_calc_adler(u8 * return (high << 16) | low; } -static u32 __pmac core99_check(u8* datas) +static u32 core99_check(u8* datas) { struct core99_header* hdr99 = (struct core99_header*)datas; @@ -235,7 +235,7 @@ static u32 __pmac core99_check(u8* datas return hdr99->generation; } -static int __pmac sm_erase_bank(int bank) +static int sm_erase_bank(int bank) { int stat, i; unsigned long timeout; @@ -267,7 +267,7 @@ static int __pmac sm_erase_bank(int bank return 0; } -static int __pmac sm_write_bank(int bank, u8* datas) +static int sm_write_bank(int bank, u8* datas) { int i, stat = 0; unsigned long timeout; @@ -302,7 +302,7 @@ static int __pmac sm_write_bank(int bank return 0; } -static int __pmac amd_erase_bank(int bank) +static int amd_erase_bank(int bank) { int i, stat = 0; unsigned long timeout; @@ -349,7 +349,7 @@ static int __pmac amd_erase_bank(int ban return 0; } -static int __pmac amd_write_bank(int bank, u8* datas) +static int amd_write_bank(int bank, u8* datas) { int i, stat = 0; unsigned long timeout; @@ -430,7 +430,7 @@ static void __init lookup_partitions(voi DBG("nvram: NR partition at 0x%x\n", nvram_partitions[pmac_nvram_NR]); } -static void __pmac core99_nvram_sync(void) +static void core99_nvram_sync(void) { struct core99_header* hdr99; unsigned long flags; @@ -554,12 +554,12 @@ void __init pmac_nvram_init(void) lookup_partitions(); } -int __pmac pmac_get_partition(int partition) +int pmac_get_partition(int partition) { return nvram_partitions[partition]; } -u8 __pmac pmac_xpram_read(int xpaddr) +u8 pmac_xpram_read(int xpaddr) { int offset = nvram_partitions[pmac_nvram_XPRAM]; @@ -569,7 +569,7 @@ u8 __pmac pmac_xpram_read(int xpaddr) return ppc_md.nvram_read_val(xpaddr + offset); } -void __pmac pmac_xpram_write(int xpaddr, u8 data) +void pmac_xpram_write(int xpaddr, u8 data) { int offset = nvram_partitions[pmac_nvram_XPRAM]; diff --git a/arch/ppc/platforms/pmac_pci.c b/arch/ppc/platforms/pmac_pci.c --- a/arch/ppc/platforms/pmac_pci.c +++ b/arch/ppc/platforms/pmac_pci.c @@ -141,7 +141,7 @@ fixup_bus_range(struct device_node *brid |(((unsigned long)(off)) & 0xFCUL) \ |1UL) -static void volatile __iomem * __pmac +static void volatile __iomem * macrisc_cfg_access(struct pci_controller* hose, u8 bus, u8 dev_fn, u8 offset) { unsigned int caddr; @@ -162,7 +162,7 @@ macrisc_cfg_access(struct pci_controller return hose->cfg_data + offset; } -static int __pmac +static int macrisc_read_config(struct pci_bus *bus, unsigned int devfn, int offset, int len, u32 *val) { @@ -190,7 +190,7 @@ macrisc_read_config(struct pci_bus *bus, return PCIBIOS_SUCCESSFUL; } -static int __pmac +static int macrisc_write_config(struct pci_bus *bus, unsigned int devfn, int offset, int len, u32 val) { @@ -230,7 +230,7 @@ static struct pci_ops macrisc_pci_ops = /* * Verifiy that a specific (bus, dev_fn) exists on chaos */ -static int __pmac +static int chaos_validate_dev(struct pci_bus *bus, int devfn, int offset) { struct device_node *np; @@ -252,7 +252,7 @@ chaos_validate_dev(struct pci_bus *bus, return PCIBIOS_SUCCESSFUL; } -static int __pmac +static int chaos_read_config(struct pci_bus *bus, unsigned int devfn, int offset, int len, u32 *val) { @@ -264,7 +264,7 @@ chaos_read_config(struct pci_bus *bus, u return macrisc_read_config(bus, devfn, offset, len, val); } -static int __pmac +static int chaos_write_config(struct pci_bus *bus, unsigned int devfn, int offset, int len, u32 val) { @@ -294,7 +294,7 @@ static struct pci_ops chaos_pci_ops = + (((unsigned long)bus) << 16) \ + 0x01000000UL) -static void volatile __iomem * __pmac +static void volatile __iomem * u3_ht_cfg_access(struct pci_controller* hose, u8 bus, u8 devfn, u8 offset) { if (bus == hose->first_busno) { @@ -307,7 +307,7 @@ u3_ht_cfg_access(struct pci_controller* return hose->cfg_data + U3_HT_CFA1(bus, devfn, offset); } -static int __pmac +static int u3_ht_read_config(struct pci_bus *bus, unsigned int devfn, int offset, int len, u32 *val) { @@ -357,7 +357,7 @@ u3_ht_read_config(struct pci_bus *bus, u return PCIBIOS_SUCCESSFUL; } -static int __pmac +static int u3_ht_write_config(struct pci_bus *bus, unsigned int devfn, int offset, int len, u32 val) { @@ -899,7 +899,7 @@ pmac_pcibios_fixup(void) pcibios_fixup_OF_interrupts(); } -int __pmac +int pmac_pci_enable_device_hook(struct pci_dev *dev, int initial) { struct device_node* node; @@ -1096,7 +1096,7 @@ DECLARE_PCI_FIXUP_FINAL(PCI_ANY_ID, PCI_ * Disable second function on K2-SATA, it's broken * and disable IO BARs on first one */ -void __pmac pmac_pci_fixup_k2_sata(struct pci_dev* dev) +void pmac_pci_fixup_k2_sata(struct pci_dev* dev) { int i; u16 cmd; diff --git a/arch/ppc/platforms/pmac_pic.c b/arch/ppc/platforms/pmac_pic.c --- a/arch/ppc/platforms/pmac_pic.c +++ b/arch/ppc/platforms/pmac_pic.c @@ -53,7 +53,7 @@ struct pmac_irq_hw { }; /* Default addresses */ -static volatile struct pmac_irq_hw *pmac_irq_hw[4] __pmacdata = { +static volatile struct pmac_irq_hw *pmac_irq_hw[4] = { (struct pmac_irq_hw *) 0xf3000020, (struct pmac_irq_hw *) 0xf3000010, (struct pmac_irq_hw *) 0xf4000020, @@ -64,22 +64,22 @@ static volatile struct pmac_irq_hw *pmac #define OHARE_LEVEL_MASK 0x1ff00000 #define HEATHROW_LEVEL_MASK 0x1ff00000 -static int max_irqs __pmacdata; -static int max_real_irqs __pmacdata; -static u32 level_mask[4] __pmacdata; +static int max_irqs; +static int max_real_irqs; +static u32 level_mask[4]; -static DEFINE_SPINLOCK(pmac_pic_lock __pmacdata); +static DEFINE_SPINLOCK(pmac_pic_lock); #define GATWICK_IRQ_POOL_SIZE 10 -static struct interrupt_info gatwick_int_pool[GATWICK_IRQ_POOL_SIZE] __pmacdata; +static struct interrupt_info gatwick_int_pool[GATWICK_IRQ_POOL_SIZE]; /* * Mark an irq as "lost". This is only used on the pmac * since it can lose interrupts (see pmac_set_irq_mask). * -- Cort */ -void __pmac +void __set_lost(unsigned long irq_nr, int nokick) { if (!test_and_set_bit(irq_nr, ppc_lost_interrupts)) { @@ -89,7 +89,7 @@ __set_lost(unsigned long irq_nr, int nok } } -static void __pmac +static void pmac_mask_and_ack_irq(unsigned int irq_nr) { unsigned long bit = 1UL << (irq_nr & 0x1f); @@ -114,7 +114,7 @@ pmac_mask_and_ack_irq(unsigned int irq_n spin_unlock_irqrestore(&pmac_pic_lock, flags); } -static void __pmac pmac_set_irq_mask(unsigned int irq_nr, int nokicklost) +static void pmac_set_irq_mask(unsigned int irq_nr, int nokicklost) { unsigned long bit = 1UL << (irq_nr & 0x1f); int i = irq_nr >> 5; @@ -147,7 +147,7 @@ static void __pmac pmac_set_irq_mask(uns /* When an irq gets requested for the first client, if it's an * edge interrupt, we clear any previous one on the controller */ -static unsigned int __pmac pmac_startup_irq(unsigned int irq_nr) +static unsigned int pmac_startup_irq(unsigned int irq_nr) { unsigned long bit = 1UL << (irq_nr & 0x1f); int i = irq_nr >> 5; @@ -160,20 +160,20 @@ static unsigned int __pmac pmac_startup_ return 0; } -static void __pmac pmac_mask_irq(unsigned int irq_nr) +static void pmac_mask_irq(unsigned int irq_nr) { clear_bit(irq_nr, ppc_cached_irq_mask); pmac_set_irq_mask(irq_nr, 0); mb(); } -static void __pmac pmac_unmask_irq(unsigned int irq_nr) +static void pmac_unmask_irq(unsigned int irq_nr) { set_bit(irq_nr, ppc_cached_irq_mask); pmac_set_irq_mask(irq_nr, 0); } -static void __pmac pmac_end_irq(unsigned int irq_nr) +static void pmac_end_irq(unsigned int irq_nr) { if (!(irq_desc[irq_nr].status & (IRQ_DISABLED|IRQ_INPROGRESS)) && irq_desc[irq_nr].action) { diff --git a/arch/ppc/platforms/pmac_setup.c b/arch/ppc/platforms/pmac_setup.c --- a/arch/ppc/platforms/pmac_setup.c +++ b/arch/ppc/platforms/pmac_setup.c @@ -123,7 +123,7 @@ extern struct smp_ops_t psurge_smp_ops; extern struct smp_ops_t core99_smp_ops; #endif /* CONFIG_SMP */ -static int __pmac +static int pmac_show_cpuinfo(struct seq_file *m) { struct device_node *np; @@ -227,7 +227,7 @@ pmac_show_cpuinfo(struct seq_file *m) return 0; } -static int __openfirmware +static int pmac_show_percpuinfo(struct seq_file *m, int i) { #ifdef CONFIG_CPU_FREQ_PMAC @@ -486,7 +486,7 @@ static int pmac_late_init(void) late_initcall(pmac_late_init); /* can't be __init - can be called whenever a disk is first accessed */ -void __pmac +void note_bootable_part(dev_t dev, int part, int goodness) { static int found_boot = 0; @@ -512,7 +512,7 @@ note_bootable_part(dev_t dev, int part, } } -static void __pmac +static void pmac_restart(char *cmd) { #ifdef CONFIG_ADB_CUDA @@ -537,7 +537,7 @@ pmac_restart(char *cmd) } } -static void __pmac +static void pmac_power_off(void) { #ifdef CONFIG_ADB_CUDA @@ -562,7 +562,7 @@ pmac_power_off(void) } } -static void __pmac +static void pmac_halt(void) { pmac_power_off(); diff --git a/arch/ppc/platforms/pmac_smp.c b/arch/ppc/platforms/pmac_smp.c --- a/arch/ppc/platforms/pmac_smp.c +++ b/arch/ppc/platforms/pmac_smp.c @@ -186,7 +186,7 @@ static inline void psurge_clr_ipi(int cp */ static unsigned long psurge_smp_message[NR_CPUS]; -void __pmac psurge_smp_message_recv(struct pt_regs *regs) +void psurge_smp_message_recv(struct pt_regs *regs) { int cpu = smp_processor_id(); int msg; @@ -203,13 +203,13 @@ void __pmac psurge_smp_message_recv(stru smp_message_recv(msg, regs); } -irqreturn_t __pmac psurge_primary_intr(int irq, void *d, struct pt_regs *regs) +irqreturn_t psurge_primary_intr(int irq, void *d, struct pt_regs *regs) { psurge_smp_message_recv(regs); return IRQ_HANDLED; } -static void __pmac smp_psurge_message_pass(int target, int msg, unsigned long data, +static void smp_psurge_message_pass(int target, int msg, unsigned long data, int wait) { int i; @@ -629,7 +629,7 @@ void smp_core99_give_timebase(void) /* PowerSurge-style Macs */ -struct smp_ops_t psurge_smp_ops __pmacdata = { +struct smp_ops_t psurge_smp_ops = { .message_pass = smp_psurge_message_pass, .probe = smp_psurge_probe, .kick_cpu = smp_psurge_kick_cpu, @@ -639,7 +639,7 @@ struct smp_ops_t psurge_smp_ops __pmacda }; /* Core99 Macs (dual G4s) */ -struct smp_ops_t core99_smp_ops __pmacdata = { +struct smp_ops_t core99_smp_ops = { .message_pass = smp_openpic_message_pass, .probe = smp_core99_probe, .kick_cpu = smp_core99_kick_cpu, diff --git a/arch/ppc/platforms/pmac_time.c b/arch/ppc/platforms/pmac_time.c --- a/arch/ppc/platforms/pmac_time.c +++ b/arch/ppc/platforms/pmac_time.c @@ -77,7 +77,7 @@ pmac_time_init(void) #endif } -unsigned long __pmac +unsigned long pmac_get_rtc_time(void) { #if defined(CONFIG_ADB_CUDA) || defined(CONFIG_ADB_PMU) @@ -118,7 +118,7 @@ pmac_get_rtc_time(void) return 0; } -int __pmac +int pmac_set_rtc_time(unsigned long nowtime) { #if defined(CONFIG_ADB_CUDA) || defined(CONFIG_ADB_PMU) @@ -210,7 +210,7 @@ via_calibrate_decr(void) /* * Reset the time after a sleep. */ -static int __pmac +static int time_sleep_notify(struct pmu_sleep_notifier *self, int when) { static unsigned long time_diff; @@ -235,7 +235,7 @@ time_sleep_notify(struct pmu_sleep_notif return PBOOK_SLEEP_OK; } -static struct pmu_sleep_notifier time_sleep_notifier __pmacdata = { +static struct pmu_sleep_notifier time_sleep_notifier = { time_sleep_notify, SLEEP_LEVEL_MISC, }; #endif /* CONFIG_PM */ diff --git a/arch/ppc/platforms/prep_pci.c b/arch/ppc/platforms/prep_pci.c --- a/arch/ppc/platforms/prep_pci.c +++ b/arch/ppc/platforms/prep_pci.c @@ -43,7 +43,7 @@ static unsigned long *ProcInfo; /* Tables for known hardware */ /* Motorola PowerStackII - Utah */ -static char Utah_pci_IRQ_map[23] __prepdata = +static char Utah_pci_IRQ_map[23] = { 0, /* Slot 0 - unused */ 0, /* Slot 1 - unused */ @@ -72,7 +72,7 @@ static char Utah_pci_IRQ_map[23] __prepd 0, /* Slot 22 - unused */ }; -static char Utah_pci_IRQ_routes[] __prepdata = +static char Utah_pci_IRQ_routes[] = { 0, /* Line 0 - Unused */ 9, /* Line 1 */ @@ -84,7 +84,7 @@ static char Utah_pci_IRQ_routes[] __prep /* Motorola PowerStackII - Omaha */ /* no integrated SCSI or ethernet */ -static char Omaha_pci_IRQ_map[23] __prepdata = +static char Omaha_pci_IRQ_map[23] = { 0, /* Slot 0 - unused */ 0, /* Slot 1 - unused */ @@ -111,7 +111,7 @@ static char Omaha_pci_IRQ_map[23] __prep 0, }; -static char Omaha_pci_IRQ_routes[] __prepdata = +static char Omaha_pci_IRQ_routes[] = { 0, /* Line 0 - Unused */ 9, /* Line 1 */ @@ -121,7 +121,7 @@ static char Omaha_pci_IRQ_routes[] __pre }; /* Motorola PowerStack */ -static char Blackhawk_pci_IRQ_map[19] __prepdata = +static char Blackhawk_pci_IRQ_map[19] = { 0, /* Slot 0 - unused */ 0, /* Slot 1 - unused */ @@ -144,7 +144,7 @@ static char Blackhawk_pci_IRQ_map[19] __ 3, /* Slot P5 */ }; -static char Blackhawk_pci_IRQ_routes[] __prepdata = +static char Blackhawk_pci_IRQ_routes[] = { 0, /* Line 0 - Unused */ 9, /* Line 1 */ @@ -154,7 +154,7 @@ static char Blackhawk_pci_IRQ_routes[] _ }; /* Motorola Mesquite */ -static char Mesquite_pci_IRQ_map[23] __prepdata = +static char Mesquite_pci_IRQ_map[23] = { 0, /* Slot 0 - unused */ 0, /* Slot 1 - unused */ @@ -182,7 +182,7 @@ static char Mesquite_pci_IRQ_map[23] __p }; /* Motorola Sitka */ -static char Sitka_pci_IRQ_map[21] __prepdata = +static char Sitka_pci_IRQ_map[21] = { 0, /* Slot 0 - unused */ 0, /* Slot 1 - unused */ @@ -208,7 +208,7 @@ static char Sitka_pci_IRQ_map[21] __prep }; /* Motorola MTX */ -static char MTX_pci_IRQ_map[23] __prepdata = +static char MTX_pci_IRQ_map[23] = { 0, /* Slot 0 - unused */ 0, /* Slot 1 - unused */ @@ -237,7 +237,7 @@ static char MTX_pci_IRQ_map[23] __prepda /* Motorola MTX Plus */ /* Secondary bus interrupt routing is not supported yet */ -static char MTXplus_pci_IRQ_map[23] __prepdata = +static char MTXplus_pci_IRQ_map[23] = { 0, /* Slot 0 - unused */ 0, /* Slot 1 - unused */ @@ -264,13 +264,13 @@ static char MTXplus_pci_IRQ_map[23] __pr 0, /* Slot 22 - unused */ }; -static char Raven_pci_IRQ_routes[] __prepdata = +static char Raven_pci_IRQ_routes[] = { 0, /* This is a dummy structure */ }; /* Motorola MVME16xx */ -static char Genesis_pci_IRQ_map[16] __prepdata = +static char Genesis_pci_IRQ_map[16] = { 0, /* Slot 0 - unused */ 0, /* Slot 1 - unused */ @@ -290,7 +290,7 @@ static char Genesis_pci_IRQ_map[16] __pr 0, /* Slot 15 - unused */ }; -static char Genesis_pci_IRQ_routes[] __prepdata = +static char Genesis_pci_IRQ_routes[] = { 0, /* Line 0 - Unused */ 10, /* Line 1 */ @@ -299,7 +299,7 @@ static char Genesis_pci_IRQ_routes[] __p 15 /* Line 4 */ }; -static char Genesis2_pci_IRQ_map[23] __prepdata = +static char Genesis2_pci_IRQ_map[23] = { 0, /* Slot 0 - unused */ 0, /* Slot 1 - unused */ @@ -327,7 +327,7 @@ static char Genesis2_pci_IRQ_map[23] __p }; /* Motorola Series-E */ -static char Comet_pci_IRQ_map[23] __prepdata = +static char Comet_pci_IRQ_map[23] = { 0, /* Slot 0 - unused */ 0, /* Slot 1 - unused */ @@ -354,7 +354,7 @@ static char Comet_pci_IRQ_map[23] __prep 0, }; -static char Comet_pci_IRQ_routes[] __prepdata = +static char Comet_pci_IRQ_routes[] = { 0, /* Line 0 - Unused */ 10, /* Line 1 */ @@ -364,7 +364,7 @@ static char Comet_pci_IRQ_routes[] __pre }; /* Motorola Series-EX */ -static char Comet2_pci_IRQ_map[23] __prepdata = +static char Comet2_pci_IRQ_map[23] = { 0, /* Slot 0 - unused */ 0, /* Slot 1 - unused */ @@ -391,7 +391,7 @@ static char Comet2_pci_IRQ_map[23] __pre 0, }; -static char Comet2_pci_IRQ_routes[] __prepdata = +static char Comet2_pci_IRQ_routes[] = { 0, /* Line 0 - Unused */ 10, /* Line 1 */ @@ -405,7 +405,7 @@ static char Comet2_pci_IRQ_routes[] __pr * This is actually based on the Carolina motherboard * -- Cort */ -static char ibm8xx_pci_IRQ_map[23] __prepdata = { +static char ibm8xx_pci_IRQ_map[23] = { 0, /* Slot 0 - unused */ 0, /* Slot 1 - unused */ 0, /* Slot 2 - unused */ @@ -431,7 +431,7 @@ static char ibm8xx_pci_IRQ_map[23] __pre 2, /* Slot 22 - PCI slot 1 PCIINTx# (See below) */ }; -static char ibm8xx_pci_IRQ_routes[] __prepdata = { +static char ibm8xx_pci_IRQ_routes[] = { 0, /* Line 0 - unused */ 15, /* Line 1 */ 15, /* Line 2 */ @@ -443,7 +443,7 @@ static char ibm8xx_pci_IRQ_routes[] __pr * a 6015 ibm board * -- Cort */ -static char ibm6015_pci_IRQ_map[23] __prepdata = { +static char ibm6015_pci_IRQ_map[23] = { 0, /* Slot 0 - unused */ 0, /* Slot 1 - unused */ 0, /* Slot 2 - unused */ @@ -469,7 +469,7 @@ static char ibm6015_pci_IRQ_map[23] __pr 2, /* Slot 22 - */ }; -static char ibm6015_pci_IRQ_routes[] __prepdata = { +static char ibm6015_pci_IRQ_routes[] = { 0, /* Line 0 - unused */ 13, /* Line 1 */ 15, /* Line 2 */ @@ -479,7 +479,7 @@ static char ibm6015_pci_IRQ_routes[] __p /* IBM Nobis and Thinkpad 850 */ -static char Nobis_pci_IRQ_map[23] __prepdata ={ +static char Nobis_pci_IRQ_map[23] ={ 0, /* Slot 0 - unused */ 0, /* Slot 1 - unused */ 0, /* Slot 2 - unused */ @@ -498,7 +498,7 @@ static char Nobis_pci_IRQ_map[23] __prep 0, /* Slot 15 - unused */ }; -static char Nobis_pci_IRQ_routes[] __prepdata = { +static char Nobis_pci_IRQ_routes[] = { 0, /* Line 0 - Unused */ 13, /* Line 1 */ 13, /* Line 2 */ @@ -510,7 +510,7 @@ static char Nobis_pci_IRQ_routes[] __pre * IBM RS/6000 43p/140 -- paulus * XXX we should get all this from the residual data */ -static char ibm43p_pci_IRQ_map[23] __prepdata = { +static char ibm43p_pci_IRQ_map[23] = { 0, /* Slot 0 - unused */ 0, /* Slot 1 - unused */ 0, /* Slot 2 - unused */ @@ -536,7 +536,7 @@ static char ibm43p_pci_IRQ_map[23] __pre 1, /* Slot 22 - PCI slot 1 PCIINTx# (See below) */ }; -static char ibm43p_pci_IRQ_routes[] __prepdata = { +static char ibm43p_pci_IRQ_routes[] = { 0, /* Line 0 - unused */ 15, /* Line 1 */ 15, /* Line 2 */ @@ -559,7 +559,7 @@ struct powerplus_irq_list * are routed to OpenPIC inputs 5-8. These values are offset by * 16 in the table to reflect the Linux kernel interrupt value. */ -struct powerplus_irq_list Powerplus_pci_IRQ_list __prepdata = +struct powerplus_irq_list Powerplus_pci_IRQ_list = { {25, 26, 27, 28}, {21, 22, 23, 24} @@ -572,7 +572,7 @@ struct powerplus_irq_list Powerplus_pci_ * are routed to OpenPIC inputs 12-15. These values are offset by * 16 in the table to reflect the Linux kernel interrupt value. */ -struct powerplus_irq_list Mesquite_pci_IRQ_list __prepdata = +struct powerplus_irq_list Mesquite_pci_IRQ_list = { {24, 25, 26, 27}, {28, 29, 30, 31} @@ -582,7 +582,7 @@ struct powerplus_irq_list Mesquite_pci_I * This table represents the standard PCI swizzle defined in the * PCI bus specification. */ -static unsigned char prep_pci_intpins[4][4] __prepdata = +static unsigned char prep_pci_intpins[4][4] = { { 1, 2, 3, 4}, /* Buses 0, 4, 8, ... */ { 2, 3, 4, 1}, /* Buses 1, 5, 9, ... */ @@ -622,7 +622,7 @@ static unsigned char prep_pci_intpins[4] #define MIN_DEVNR 11 #define MAX_DEVNR 22 -static int __prep +static int prep_read_config(struct pci_bus *bus, unsigned int devfn, int offset, int len, u32 *val) { @@ -652,7 +652,7 @@ prep_read_config(struct pci_bus *bus, un return PCIBIOS_SUCCESSFUL; } -static int __prep +static int prep_write_config(struct pci_bus *bus, unsigned int devfn, int offset, int len, u32 val) { @@ -804,7 +804,7 @@ struct mot_info { void (*map_non0_bus)(struct pci_dev *); /* For boards with more than bus 0 devices. */ struct powerplus_irq_list *pci_irq_list; /* List of PCI MPIC inputs */ unsigned char secondary_bridge_devfn; /* devfn of secondary bus transparent bridge */ -} mot_info[] __prepdata = { +} mot_info[] = { {0x300, 0x00, 0x00, "MVME 2400", Genesis2_pci_IRQ_map, Raven_pci_IRQ_routes, Powerplus_Map_Non0, &Powerplus_pci_IRQ_list, 0xFF}, {0x010, 0x00, 0x00, "Genesis", Genesis_pci_IRQ_map, Genesis_pci_IRQ_routes, Powerplus_Map_Non0, &Powerplus_pci_IRQ_list, 0x00}, {0x020, 0x00, 0x00, "Powerstack (Series E)", Comet_pci_IRQ_map, Comet_pci_IRQ_routes, NULL, NULL, 0x00}, diff --git a/arch/ppc/platforms/prep_setup.c b/arch/ppc/platforms/prep_setup.c --- a/arch/ppc/platforms/prep_setup.c +++ b/arch/ppc/platforms/prep_setup.c @@ -173,7 +173,7 @@ prep_carolina_enable_l2(void) } /* cpuinfo code common to all IBM PReP */ -static void __prep +static void prep_ibm_cpuinfo(struct seq_file *m) { unsigned int equip_reg = inb(PREP_IBM_EQUIPMENT); @@ -209,14 +209,14 @@ prep_ibm_cpuinfo(struct seq_file *m) } } -static int __prep +static int prep_gen_cpuinfo(struct seq_file *m) { prep_ibm_cpuinfo(m); return 0; } -static int __prep +static int prep_sandalfoot_cpuinfo(struct seq_file *m) { unsigned int equip_reg = inb(PREP_IBM_EQUIPMENT); @@ -243,7 +243,7 @@ prep_sandalfoot_cpuinfo(struct seq_file return 0; } -static int __prep +static int prep_thinkpad_cpuinfo(struct seq_file *m) { unsigned int equip_reg = inb(PREP_IBM_EQUIPMENT); @@ -314,7 +314,7 @@ prep_thinkpad_cpuinfo(struct seq_file *m return 0; } -static int __prep +static int prep_carolina_cpuinfo(struct seq_file *m) { unsigned int equip_reg = inb(PREP_IBM_EQUIPMENT); @@ -350,7 +350,7 @@ prep_carolina_cpuinfo(struct seq_file *m return 0; } -static int __prep +static int prep_tiger1_cpuinfo(struct seq_file *m) { unsigned int l2_reg = inb(PREP_IBM_L2INFO); @@ -393,7 +393,7 @@ prep_tiger1_cpuinfo(struct seq_file *m) /* Used by all Motorola PReP */ -static int __prep +static int prep_mot_cpuinfo(struct seq_file *m) { unsigned int cachew = *((unsigned char *)CACHECRBA); @@ -454,7 +454,7 @@ no_l2: return 0; } -static void __prep +static void prep_restart(char *cmd) { #define PREP_SP92 0x92 /* Special Port 92 */ @@ -473,7 +473,7 @@ prep_restart(char *cmd) #undef PREP_SP92 } -static void __prep +static void prep_halt(void) { local_irq_disable(); /* no interrupts */ @@ -488,7 +488,7 @@ prep_halt(void) /* Carrera is the power manager in the Thinkpads. Unfortunately not much is * known about it, so we can't power down. */ -static void __prep +static void prep_carrera_poweroff(void) { prep_halt(); @@ -501,7 +501,7 @@ prep_carrera_poweroff(void) * somewhat in the IBM Carolina Technical Specification. * -Hollis */ -static void __prep +static void utah_sig87c750_setbit(unsigned int bytenum, unsigned int bitnum, int value) { /* @@ -539,7 +539,7 @@ utah_sig87c750_setbit(unsigned int byten udelay(100); /* important: let controller recover */ } -static void __prep +static void prep_sig750_poweroff(void) { /* tweak the power manager found in most IBM PRePs (except Thinkpads) */ @@ -554,7 +554,7 @@ prep_sig750_poweroff(void) /* not reached */ } -static int __prep +static int prep_show_percpuinfo(struct seq_file *m, int i) { /* PREP's without residual data will give incorrect values here */ @@ -700,12 +700,12 @@ prep_set_bat(void) /* * IBM 3-digit status LED */ -static unsigned int ibm_statusled_base __prepdata; +static unsigned int ibm_statusled_base; -static void __prep +static void ibm_statusled_progress(char *s, unsigned short hex); -static int __prep +static int ibm_statusled_panic(struct notifier_block *dummy1, unsigned long dummy2, void * dummy3) { @@ -713,13 +713,13 @@ ibm_statusled_panic(struct notifier_bloc return NOTIFY_DONE; } -static struct notifier_block ibm_statusled_block __prepdata = { +static struct notifier_block ibm_statusled_block = { ibm_statusled_panic, NULL, INT_MAX /* try to do it first */ }; -static void __prep +static void ibm_statusled_progress(char *s, unsigned short hex) { static int notifier_installed; @@ -945,7 +945,7 @@ prep_calibrate_decr(void) todc_calibrate_decr(); } -static unsigned int __prep +static unsigned int prep_irq_canonicalize(u_int irq) { if (irq == 2) @@ -996,7 +996,7 @@ prep_init_IRQ(void) /* * IDE stuff. */ -static int __prep +static int prep_ide_default_irq(unsigned long base) { switch (base) { @@ -1010,7 +1010,7 @@ prep_ide_default_irq(unsigned long base) } } -static unsigned long __prep +static unsigned long prep_ide_default_io_base(int index) { switch (index) { @@ -1055,7 +1055,7 @@ smp_prep_setup_cpu(int cpu_nr) do_openpic_setup_cpu(); } -static struct smp_ops_t prep_smp_ops __prepdata = { +static struct smp_ops_t prep_smp_ops = { smp_openpic_message_pass, smp_prep_probe, smp_prep_kick_cpu, diff --git a/arch/ppc/platforms/residual.c b/arch/ppc/platforms/residual.c --- a/arch/ppc/platforms/residual.c +++ b/arch/ppc/platforms/residual.c @@ -47,7 +47,7 @@ #include -unsigned char __res[sizeof(RESIDUAL)] __prepdata = {0,}; +unsigned char __res[sizeof(RESIDUAL)] = {0,}; RESIDUAL *res = (RESIDUAL *)&__res; char * PnP_BASE_TYPES[] __initdata = { diff --git a/arch/ppc/syslib/btext.c b/arch/ppc/syslib/btext.c --- a/arch/ppc/syslib/btext.c +++ b/arch/ppc/syslib/btext.c @@ -53,8 +53,8 @@ extern char *klimit; * chrp only uses it during early boot. */ #ifdef CONFIG_XMON -#define BTEXT __pmac -#define BTDATA __pmacdata +#define BTEXT +#define BTDATA #else #define BTEXT __init #define BTDATA __initdata @@ -187,7 +187,7 @@ btext_setup_display(int width, int heigh * changes. */ -void __openfirmware +void map_boot_text(void) { unsigned long base, offset, size; diff --git a/arch/ppc/syslib/prep_nvram.c b/arch/ppc/syslib/prep_nvram.c --- a/arch/ppc/syslib/prep_nvram.c +++ b/arch/ppc/syslib/prep_nvram.c @@ -22,14 +22,14 @@ static char nvramData[MAX_PREP_NVRAM]; static NVRAM_MAP *nvram=(NVRAM_MAP *)&nvramData[0]; -unsigned char __prep prep_nvram_read_val(int addr) +unsigned char prep_nvram_read_val(int addr) { outb(addr, PREP_NVRAM_AS0); outb(addr>>8, PREP_NVRAM_AS1); return inb(PREP_NVRAM_DATA); } -void __prep prep_nvram_write_val(int addr, +void prep_nvram_write_val(int addr, unsigned char val) { outb(addr, PREP_NVRAM_AS0); @@ -81,8 +81,7 @@ void __init init_prep_nvram(void) } } -__prep -char __prep *prep_nvram_get_var(const char *name) +char *prep_nvram_get_var(const char *name) { char *cp; int namelen; @@ -101,8 +100,7 @@ char __prep *prep_nvram_get_var(const ch return NULL; } -__prep -char __prep *prep_nvram_first_var(void) +char *prep_nvram_first_var(void) { if (nvram->Header.GELength == 0) { return NULL; @@ -112,8 +110,7 @@ char __prep *prep_nvram_first_var(void) } } -__prep -char __prep *prep_nvram_next_var(char *name) +char *prep_nvram_next_var(char *name) { char *cp; diff --git a/arch/ppc/syslib/prom.c b/arch/ppc/syslib/prom.c --- a/arch/ppc/syslib/prom.c +++ b/arch/ppc/syslib/prom.c @@ -89,7 +89,7 @@ extern char cmd_line[512]; /* XXX */ extern boot_infos_t *boot_infos; unsigned long dev_tree_size; -void __openfirmware +void phys_call_rtas(int service, int nargs, int nret, ...) { va_list list; @@ -862,7 +862,7 @@ find_type_devices(const char *type) /* * Returns all nodes linked together */ -struct device_node * __openfirmware +struct device_node * find_all_nodes(void) { struct device_node *head, **prevp, *np; @@ -1165,7 +1165,7 @@ get_property(struct device_node *np, con /* * Add a property to a node */ -void __openfirmware +void prom_add_property(struct device_node* np, struct property* prop) { struct property **next = &np->properties; @@ -1177,7 +1177,7 @@ prom_add_property(struct device_node* np } /* I quickly hacked that one, check against spec ! */ -static inline unsigned long __openfirmware +static inline unsigned long bus_space_to_resource_flags(unsigned int bus_space) { u8 space = (bus_space >> 24) & 0xf; @@ -1194,7 +1194,7 @@ bus_space_to_resource_flags(unsigned int } } -static struct resource* __openfirmware +static struct resource* find_parent_pci_resource(struct pci_dev* pdev, struct address_range *range) { unsigned long mask; @@ -1224,7 +1224,7 @@ find_parent_pci_resource(struct pci_dev* * or other nodes attached to the root node. Ultimately, put some * link to resources in the OF node. */ -struct resource* __openfirmware +struct resource* request_OF_resource(struct device_node* node, int index, const char* name_postfix) { struct pci_dev* pcidev; @@ -1280,7 +1280,7 @@ fail: return NULL; } -int __openfirmware +int release_OF_resource(struct device_node* node, int index) { struct pci_dev* pcidev; @@ -1346,7 +1346,7 @@ release_OF_resource(struct device_node* } #if 0 -void __openfirmware +void print_properties(struct device_node *np) { struct property *pp; @@ -1400,7 +1400,7 @@ print_properties(struct device_node *np) static DEFINE_SPINLOCK(rtas_lock); /* this can be called after setup -- Cort */ -int __openfirmware +int call_rtas(const char *service, int nargs, int nret, unsigned long *outputs, ...) { From linuxppc at jdl.com Sun Sep 18 01:36:54 2005 From: linuxppc at jdl.com (Jon Loeliger) Date: Sat, 17 Sep 2005 10:36:54 -0500 Subject: PATCH powerpc: 02/04 Remove sections use from ppc64 and drivers In-Reply-To: Your message of "Sat, 17 Sep 2005 10:31:52 CDT." References: Message-ID: diff --git a/arch/ppc64/kernel/pmac_feature.c b/arch/ppc64/kernel/pmac_feature.c --- a/arch/ppc64/kernel/pmac_feature.c +++ b/arch/ppc64/kernel/pmac_feature.c @@ -53,7 +53,7 @@ * We use a single global lock to protect accesses. Each driver has * to take care of its own locking */ -static DEFINE_SPINLOCK(feature_lock __pmacdata); +static DEFINE_SPINLOCK(feature_lock); #define LOCK(flags) spin_lock_irqsave(&feature_lock, flags); #define UNLOCK(flags) spin_unlock_irqrestore(&feature_lock, flags); @@ -62,9 +62,9 @@ static DEFINE_SPINLOCK(feature_lock __p /* * Instance of some macio stuffs */ -struct macio_chip macio_chips[MAX_MACIO_CHIPS] __pmacdata; +struct macio_chip macio_chips[MAX_MACIO_CHIPS] ; -struct macio_chip* __pmac macio_find(struct device_node* child, int type) +struct macio_chip* macio_find(struct device_node* child, int type) { while(child) { int i; @@ -79,7 +79,7 @@ struct macio_chip* __pmac macio_find(str } EXPORT_SYMBOL_GPL(macio_find); -static const char* macio_names[] __pmacdata = +static const char* macio_names[] = { "Unknown", "Grand Central", @@ -106,9 +106,9 @@ static const char* macio_names[] __pmacd #define UN_BIS(r,v) (UN_OUT((r), UN_IN(r) | (v))) #define UN_BIC(r,v) (UN_OUT((r), UN_IN(r) & ~(v))) -static struct device_node* uninorth_node __pmacdata; -static u32* uninorth_base __pmacdata; -static u32 uninorth_rev __pmacdata; +static struct device_node* uninorth_node; +static u32* uninorth_base; +static u32 uninorth_rev; static void *u3_ht; extern struct device_node *k2_skiplist[2]; @@ -133,14 +133,14 @@ struct pmac_mb_def struct feature_table_entry* features; unsigned long board_flags; }; -static struct pmac_mb_def pmac_mb __pmacdata; +static struct pmac_mb_def pmac_mb; /* * Here are the chip specific feature functions */ -static long __pmac g5_read_gpio(struct device_node* node, long param, long value) +static long g5_read_gpio(struct device_node* node, long param, long value) { struct macio_chip* macio = &macio_chips[0]; @@ -148,7 +148,7 @@ static long __pmac g5_read_gpio(struct d } -static long __pmac g5_write_gpio(struct device_node* node, long param, long value) +static long g5_write_gpio(struct device_node* node, long param, long value) { struct macio_chip* macio = &macio_chips[0]; @@ -156,7 +156,7 @@ static long __pmac g5_write_gpio(struct return 0; } -static long __pmac g5_gmac_enable(struct device_node* node, long param, long value) +static long g5_gmac_enable(struct device_node* node, long param, long value) { struct macio_chip* macio = &macio_chips[0]; unsigned long flags; @@ -181,7 +181,7 @@ static long __pmac g5_gmac_enable(struct return 0; } -static long __pmac g5_fw_enable(struct device_node* node, long param, long value) +static long g5_fw_enable(struct device_node* node, long param, long value) { struct macio_chip* macio = &macio_chips[0]; unsigned long flags; @@ -206,7 +206,7 @@ static long __pmac g5_fw_enable(struct d return 0; } -static long __pmac g5_mpic_enable(struct device_node* node, long param, long value) +static long g5_mpic_enable(struct device_node* node, long param, long value) { unsigned long flags; @@ -220,7 +220,7 @@ static long __pmac g5_mpic_enable(struct return 0; } -static long __pmac g5_eth_phy_reset(struct device_node* node, long param, long value) +static long g5_eth_phy_reset(struct device_node* node, long param, long value) { struct macio_chip* macio = &macio_chips[0]; struct device_node *phy; @@ -250,7 +250,7 @@ static long __pmac g5_eth_phy_reset(stru return 0; } -static long __pmac g5_i2s_enable(struct device_node *node, long param, long value) +static long g5_i2s_enable(struct device_node *node, long param, long value) { /* Very crude implementation for now */ struct macio_chip* macio = &macio_chips[0]; @@ -275,7 +275,7 @@ static long __pmac g5_i2s_enable(struct #ifdef CONFIG_SMP -static long __pmac g5_reset_cpu(struct device_node* node, long param, long value) +static long g5_reset_cpu(struct device_node* node, long param, long value) { unsigned int reset_io = 0; unsigned long flags; @@ -320,12 +320,12 @@ static long __pmac g5_reset_cpu(struct d * This takes the second CPU off the bus on dual CPU machines * running UP */ -void __pmac g5_phy_disable_cpu1(void) +void g5_phy_disable_cpu1(void) { UN_OUT(U3_API_PHY_CONFIG_1, 0); } -static long __pmac generic_get_mb_info(struct device_node* node, long param, long value) +static long generic_get_mb_info(struct device_node* node, long param, long value) { switch(param) { case PMAC_MB_INFO_MODEL: @@ -347,14 +347,14 @@ static long __pmac generic_get_mb_info(s /* Used on any machine */ -static struct feature_table_entry any_features[] __pmacdata = { +static struct feature_table_entry any_features[] = { { PMAC_FTR_GET_MB_INFO, generic_get_mb_info }, { 0, NULL } }; /* G5 features */ -static struct feature_table_entry g5_features[] __pmacdata = { +static struct feature_table_entry g5_features[] = { { PMAC_FTR_GMAC_ENABLE, g5_gmac_enable }, { PMAC_FTR_1394_ENABLE, g5_fw_enable }, { PMAC_FTR_ENABLE_MPIC, g5_mpic_enable }, @@ -368,7 +368,7 @@ static struct feature_table_entry g5_fea { 0, NULL } }; -static struct pmac_mb_def pmac_mb_defs[] __pmacdata = { +static struct pmac_mb_def pmac_mb_defs[] = { { "PowerMac7,2", "PowerMac G5", PMAC_TYPE_POWERMAC_G5, g5_features, 0, @@ -394,7 +394,7 @@ static struct pmac_mb_def pmac_mb_defs[] /* * The toplevel feature_call callback */ -long __pmac pmac_do_feature_call(unsigned int selector, ...) +long pmac_do_feature_call(unsigned int selector, ...) { struct device_node* node; long param, value; @@ -706,8 +706,8 @@ void __init pmac_check_ht_link(void) * Early video resume hook */ -static void (*pmac_early_vresume_proc)(void *data) __pmacdata; -static void *pmac_early_vresume_data __pmacdata; +static void (*pmac_early_vresume_proc)(void *data); +static void *pmac_early_vresume_data; void pmac_set_early_video_resume(void (*proc)(void *data), void *data) { @@ -725,11 +725,11 @@ EXPORT_SYMBOL(pmac_set_early_video_resum * AGP related suspend/resume code */ -static struct pci_dev *pmac_agp_bridge __pmacdata; -static int (*pmac_agp_suspend)(struct pci_dev *bridge) __pmacdata; -static int (*pmac_agp_resume)(struct pci_dev *bridge) __pmacdata; +static struct pci_dev *pmac_agp_bridge; +static int (*pmac_agp_suspend)(struct pci_dev *bridge); +static int (*pmac_agp_resume)(struct pci_dev *bridge); -void __pmac pmac_register_agp_pm(struct pci_dev *bridge, +void pmac_register_agp_pm(struct pci_dev *bridge, int (*suspend)(struct pci_dev *bridge), int (*resume)(struct pci_dev *bridge)) { @@ -746,7 +746,7 @@ void __pmac pmac_register_agp_pm(struct } EXPORT_SYMBOL(pmac_register_agp_pm); -void __pmac pmac_suspend_agp_for_card(struct pci_dev *dev) +void pmac_suspend_agp_for_card(struct pci_dev *dev) { if (pmac_agp_bridge == NULL || pmac_agp_suspend == NULL) return; @@ -756,7 +756,7 @@ void __pmac pmac_suspend_agp_for_card(st } EXPORT_SYMBOL(pmac_suspend_agp_for_card); -void __pmac pmac_resume_agp_for_card(struct pci_dev *dev) +void pmac_resume_agp_for_card(struct pci_dev *dev) { if (pmac_agp_bridge == NULL || pmac_agp_resume == NULL) return; diff --git a/arch/ppc64/kernel/pmac_nvram.c b/arch/ppc64/kernel/pmac_nvram.c --- a/arch/ppc64/kernel/pmac_nvram.c +++ b/arch/ppc64/kernel/pmac_nvram.c @@ -82,10 +82,10 @@ extern int system_running; static int (*core99_write_bank)(int bank, u8* datas); static int (*core99_erase_bank)(int bank); -static char *nvram_image __pmacdata; +static char *nvram_image; -static ssize_t __pmac core99_nvram_read(char *buf, size_t count, loff_t *index) +static ssize_t core99_nvram_read(char *buf, size_t count, loff_t *index) { int i; @@ -103,7 +103,7 @@ static ssize_t __pmac core99_nvram_read( return count; } -static ssize_t __pmac core99_nvram_write(char *buf, size_t count, loff_t *index) +static ssize_t core99_nvram_write(char *buf, size_t count, loff_t *index) { int i; @@ -121,14 +121,14 @@ static ssize_t __pmac core99_nvram_write return count; } -static ssize_t __pmac core99_nvram_size(void) +static ssize_t core99_nvram_size(void) { if (nvram_image == NULL) return -ENODEV; return NVRAM_SIZE; } -static u8 __pmac chrp_checksum(struct chrp_header* hdr) +static u8 chrp_checksum(struct chrp_header* hdr) { u8 *ptr; u16 sum = hdr->signature; @@ -139,7 +139,7 @@ static u8 __pmac chrp_checksum(struct ch return sum; } -static u32 __pmac core99_calc_adler(u8 *buffer) +static u32 core99_calc_adler(u8 *buffer) { int cnt; u32 low, high; @@ -161,7 +161,7 @@ static u32 __pmac core99_calc_adler(u8 * return (high << 16) | low; } -static u32 __pmac core99_check(u8* datas) +static u32 core99_check(u8* datas) { struct core99_header* hdr99 = (struct core99_header*)datas; @@ -180,7 +180,7 @@ static u32 __pmac core99_check(u8* datas return hdr99->generation; } -static int __pmac sm_erase_bank(int bank) +static int sm_erase_bank(int bank) { int stat, i; unsigned long timeout; @@ -212,7 +212,7 @@ static int __pmac sm_erase_bank(int bank return 0; } -static int __pmac sm_write_bank(int bank, u8* datas) +static int sm_write_bank(int bank, u8* datas) { int i, stat = 0; unsigned long timeout; @@ -247,7 +247,7 @@ static int __pmac sm_write_bank(int bank return 0; } -static int __pmac amd_erase_bank(int bank) +static int amd_erase_bank(int bank) { int i, stat = 0; unsigned long timeout; @@ -294,7 +294,7 @@ static int __pmac amd_erase_bank(int ban return 0; } -static int __pmac amd_write_bank(int bank, u8* datas) +static int amd_write_bank(int bank, u8* datas) { int i, stat = 0; unsigned long timeout; @@ -341,7 +341,7 @@ static int __pmac amd_write_bank(int ban } -static int __pmac core99_nvram_sync(void) +static int core99_nvram_sync(void) { struct core99_header* hdr99; unsigned long flags; @@ -431,7 +431,7 @@ int __init pmac_nvram_init(void) return 0; } -int __pmac pmac_get_partition(int partition) +int pmac_get_partition(int partition) { struct nvram_partition *part; const char *name; @@ -459,7 +459,7 @@ int __pmac pmac_get_partition(int partit return part->index; } -u8 __pmac pmac_xpram_read(int xpaddr) +u8 pmac_xpram_read(int xpaddr) { int offset = pmac_get_partition(pmac_nvram_XPRAM); loff_t index; @@ -476,7 +476,7 @@ u8 __pmac pmac_xpram_read(int xpaddr) return buf; } -void __pmac pmac_xpram_write(int xpaddr, u8 data) +void pmac_xpram_write(int xpaddr, u8 data) { int offset = pmac_get_partition(pmac_nvram_XPRAM); loff_t index; diff --git a/arch/ppc64/kernel/pmac_pci.c b/arch/ppc64/kernel/pmac_pci.c --- a/arch/ppc64/kernel/pmac_pci.c +++ b/arch/ppc64/kernel/pmac_pci.c @@ -121,7 +121,7 @@ static void __init fixup_bus_range(struc |(((unsigned long)(off)) & 0xFCUL) \ |1UL) -static unsigned long __pmac macrisc_cfg_access(struct pci_controller* hose, +static unsigned long macrisc_cfg_access(struct pci_controller* hose, u8 bus, u8 dev_fn, u8 offset) { unsigned int caddr; @@ -142,7 +142,7 @@ static unsigned long __pmac macrisc_cfg_ return ((unsigned long)hose->cfg_data) + offset; } -static int __pmac macrisc_read_config(struct pci_bus *bus, unsigned int devfn, +static int macrisc_read_config(struct pci_bus *bus, unsigned int devfn, int offset, int len, u32 *val) { struct pci_controller *hose; @@ -173,7 +173,7 @@ static int __pmac macrisc_read_config(st return PCIBIOS_SUCCESSFUL; } -static int __pmac macrisc_write_config(struct pci_bus *bus, unsigned int devfn, +static int macrisc_write_config(struct pci_bus *bus, unsigned int devfn, int offset, int len, u32 val) { struct pci_controller *hose; @@ -265,7 +265,7 @@ static int u3_ht_skip_device(struct pci_ + (((unsigned long)bus) << 16) \ + 0x01000000UL) -static unsigned long __pmac u3_ht_cfg_access(struct pci_controller* hose, +static unsigned long u3_ht_cfg_access(struct pci_controller* hose, u8 bus, u8 devfn, u8 offset) { if (bus == hose->first_busno) { @@ -277,7 +277,7 @@ static unsigned long __pmac u3_ht_cfg_ac return ((unsigned long)hose->cfg_data) + U3_HT_CFA1(bus, devfn, offset); } -static int __pmac u3_ht_read_config(struct pci_bus *bus, unsigned int devfn, +static int u3_ht_read_config(struct pci_bus *bus, unsigned int devfn, int offset, int len, u32 *val) { struct pci_controller *hose; @@ -327,7 +327,7 @@ static int __pmac u3_ht_read_config(stru return PCIBIOS_SUCCESSFUL; } -static int __pmac u3_ht_write_config(struct pci_bus *bus, unsigned int devfn, +static int u3_ht_write_config(struct pci_bus *bus, unsigned int devfn, int offset, int len, u32 val) { struct pci_controller *hose; diff --git a/arch/ppc64/kernel/pmac_setup.c b/arch/ppc64/kernel/pmac_setup.c --- a/arch/ppc64/kernel/pmac_setup.c +++ b/arch/ppc64/kernel/pmac_setup.c @@ -98,7 +98,7 @@ EXPORT_SYMBOL(smu_cmdbuf_abs); extern void udbg_init_scc(struct device_node *np); -static void __pmac pmac_show_cpuinfo(struct seq_file *m) +static void pmac_show_cpuinfo(struct seq_file *m) { struct device_node *np; char *pp; @@ -210,7 +210,7 @@ static int pmac_late_init(void) late_initcall(pmac_late_init); /* can't be __init - can be called whenever a disk is first accessed */ -void __pmac note_bootable_part(dev_t dev, int part, int goodness) +void note_bootable_part(dev_t dev, int part, int goodness) { extern dev_t boot_dev; char *p; @@ -231,7 +231,7 @@ void __pmac note_bootable_part(dev_t dev } } -static void __pmac pmac_restart(char *cmd) +static void pmac_restart(char *cmd) { switch(sys_ctrler) { #ifdef CONFIG_ADB_PMU @@ -250,7 +250,7 @@ static void __pmac pmac_restart(char *cm } } -static void __pmac pmac_power_off(void) +static void pmac_power_off(void) { switch(sys_ctrler) { #ifdef CONFIG_ADB_PMU @@ -268,7 +268,7 @@ static void __pmac pmac_power_off(void) } } -static void __pmac pmac_halt(void) +static void pmac_halt(void) { pmac_power_off(); } diff --git a/arch/ppc64/kernel/pmac_smp.c b/arch/ppc64/kernel/pmac_smp.c --- a/arch/ppc64/kernel/pmac_smp.c +++ b/arch/ppc64/kernel/pmac_smp.c @@ -310,7 +310,7 @@ static void __init smp_core99_setup_cpu( } } -struct smp_ops_t core99_smp_ops __pmacdata = { +struct smp_ops_t core99_smp_ops = { .message_pass = smp_mpic_message_pass, .probe = smp_core99_probe, .kick_cpu = smp_core99_kick_cpu, diff --git a/arch/ppc64/kernel/pmac_time.c b/arch/ppc64/kernel/pmac_time.c --- a/arch/ppc64/kernel/pmac_time.c +++ b/arch/ppc64/kernel/pmac_time.c @@ -51,7 +51,7 @@ extern struct timezone sys_tz; extern void to_tm(int tim, struct rtc_time * tm); -void __pmac pmac_get_rtc_time(struct rtc_time *tm) +void pmac_get_rtc_time(struct rtc_time *tm) { switch(sys_ctrler) { #ifdef CONFIG_ADB_PMU @@ -92,7 +92,7 @@ void __pmac pmac_get_rtc_time(struct rtc } } -int __pmac pmac_set_rtc_time(struct rtc_time *tm) +int pmac_set_rtc_time(struct rtc_time *tm) { switch(sys_ctrler) { #ifdef CONFIG_ADB_PMU diff --git a/drivers/ide/ppc/pmac.c b/drivers/ide/ppc/pmac.c --- a/drivers/ide/ppc/pmac.c +++ b/drivers/ide/ppc/pmac.c @@ -81,7 +81,7 @@ typedef struct pmac_ide_hwif { } pmac_ide_hwif_t; -static pmac_ide_hwif_t pmac_ide[MAX_HWIFS] __pmacdata; +static pmac_ide_hwif_t pmac_ide[MAX_HWIFS]; static int pmac_ide_count; enum { @@ -242,7 +242,7 @@ struct mdma_timings_t { int cycleTime; }; -struct mdma_timings_t mdma_timings_33[] __pmacdata = +struct mdma_timings_t mdma_timings_33[] = { { 240, 240, 480 }, { 180, 180, 360 }, @@ -255,7 +255,7 @@ struct mdma_timings_t mdma_timings_33[] { 0, 0, 0 } }; -struct mdma_timings_t mdma_timings_33k[] __pmacdata = +struct mdma_timings_t mdma_timings_33k[] = { { 240, 240, 480 }, { 180, 180, 360 }, @@ -268,7 +268,7 @@ struct mdma_timings_t mdma_timings_33k[] { 0, 0, 0 } }; -struct mdma_timings_t mdma_timings_66[] __pmacdata = +struct mdma_timings_t mdma_timings_66[] = { { 240, 240, 480 }, { 180, 180, 360 }, @@ -286,7 +286,7 @@ struct { int addrSetup; /* ??? */ int rdy2pause; int wrDataSetup; -} kl66_udma_timings[] __pmacdata = +} kl66_udma_timings[] = { { 0, 180, 120 }, /* Mode 0 */ { 0, 150, 90 }, /* 1 */ @@ -301,7 +301,7 @@ struct kauai_timing { u32 timing_reg; }; -static struct kauai_timing kauai_pio_timings[] __pmacdata = +static struct kauai_timing kauai_pio_timings[] = { { 930 , 0x08000fff }, { 600 , 0x08000a92 }, @@ -316,7 +316,7 @@ static struct kauai_timing kauai_pio_tim { 120 , 0x04000148 } }; -static struct kauai_timing kauai_mdma_timings[] __pmacdata = +static struct kauai_timing kauai_mdma_timings[] = { { 1260 , 0x00fff000 }, { 480 , 0x00618000 }, @@ -330,7 +330,7 @@ static struct kauai_timing kauai_mdma_ti { 0 , 0 }, }; -static struct kauai_timing kauai_udma_timings[] __pmacdata = +static struct kauai_timing kauai_udma_timings[] = { { 120 , 0x000070c0 }, { 90 , 0x00005d80 }, @@ -341,7 +341,7 @@ static struct kauai_timing kauai_udma_ti { 0 , 0 }, }; -static struct kauai_timing shasta_pio_timings[] __pmacdata = +static struct kauai_timing shasta_pio_timings[] = { { 930 , 0x08000fff }, { 600 , 0x0A000c97 }, @@ -356,7 +356,7 @@ static struct kauai_timing shasta_pio_ti { 120 , 0x0400010a } }; -static struct kauai_timing shasta_mdma_timings[] __pmacdata = +static struct kauai_timing shasta_mdma_timings[] = { { 1260 , 0x00fff000 }, { 480 , 0x00820800 }, @@ -370,7 +370,7 @@ static struct kauai_timing shasta_mdma_t { 0 , 0 }, }; -static struct kauai_timing shasta_udma133_timings[] __pmacdata = +static struct kauai_timing shasta_udma133_timings[] = { { 120 , 0x00035901, }, { 90 , 0x000348b1, }, @@ -522,7 +522,7 @@ pmu_hd_blink_init(void) * N.B. this can't be an initfunc, because the media-bay task can * call ide_[un]register at any time. */ -void __pmac +void pmac_ide_init_hwif_ports(hw_regs_t *hw, unsigned long data_port, unsigned long ctrl_port, int *irq) @@ -559,7 +559,7 @@ pmac_ide_init_hwif_ports(hw_regs_t *hw, * timing register when selecting that unit. This version is for * ASICs with a single timing register */ -static void __pmac +static void pmac_ide_selectproc(ide_drive_t *drive) { pmac_ide_hwif_t* pmif = (pmac_ide_hwif_t *)HWIF(drive)->hwif_data; @@ -579,7 +579,7 @@ pmac_ide_selectproc(ide_drive_t *drive) * timing register when selecting that unit. This version is for * ASICs with a dual timing register (Kauai) */ -static void __pmac +static void pmac_ide_kauai_selectproc(ide_drive_t *drive) { pmac_ide_hwif_t* pmif = (pmac_ide_hwif_t *)HWIF(drive)->hwif_data; @@ -600,7 +600,7 @@ pmac_ide_kauai_selectproc(ide_drive_t *d /* * Force an update of controller timing values for a given drive */ -static void __pmac +static void pmac_ide_do_update_timings(ide_drive_t *drive) { pmac_ide_hwif_t* pmif = (pmac_ide_hwif_t *)HWIF(drive)->hwif_data; @@ -633,7 +633,7 @@ pmac_outbsync(ide_drive_t *drive, u8 val * to sort that out sooner or later and see if I can finally get the * common version to work properly in all cases */ -static int __pmac +static int pmac_ide_do_setfeature(ide_drive_t *drive, u8 command) { ide_hwif_t *hwif = HWIF(drive); @@ -710,7 +710,7 @@ out: /* * Old tuning functions (called on hdparm -p), sets up drive PIO timings */ -static void __pmac +static void pmac_ide_tuneproc(ide_drive_t *drive, u8 pio) { ide_pio_data_t d; @@ -801,7 +801,7 @@ pmac_ide_tuneproc(ide_drive_t *drive, u8 /* * Calculate KeyLargo ATA/66 UDMA timings */ -static int __pmac +static int set_timings_udma_ata4(u32 *timings, u8 speed) { unsigned rdyToPauseTicks, wrDataSetupTicks, addrTicks; @@ -829,7 +829,7 @@ set_timings_udma_ata4(u32 *timings, u8 s /* * Calculate Kauai ATA/100 UDMA timings */ -static int __pmac +static int set_timings_udma_ata6(u32 *pio_timings, u32 *ultra_timings, u8 speed) { struct ide_timing *t = ide_timing_find_mode(speed); @@ -849,7 +849,7 @@ set_timings_udma_ata6(u32 *pio_timings, /* * Calculate Shasta ATA/133 UDMA timings */ -static int __pmac +static int set_timings_udma_shasta(u32 *pio_timings, u32 *ultra_timings, u8 speed) { struct ide_timing *t = ide_timing_find_mode(speed); @@ -869,7 +869,7 @@ set_timings_udma_shasta(u32 *pio_timings /* * Calculate MDMA timings for all cells */ -static int __pmac +static int set_timings_mdma(ide_drive_t *drive, int intf_type, u32 *timings, u32 *timings2, u8 speed, int drive_cycle_time) { @@ -1014,7 +1014,7 @@ set_timings_mdma(ide_drive_t *drive, int * our dedicated function is more precise as it uses the drive provided * cycle time value. We should probably fix this one to deal with that too... */ -static int __pmac +static int pmac_ide_tune_chipset (ide_drive_t *drive, byte speed) { int unit = (drive->select.b.unit & 0x01); @@ -1092,7 +1092,7 @@ pmac_ide_tune_chipset (ide_drive_t *driv * Blast some well known "safe" values to the timing registers at init or * wakeup from sleep time, before we do real calculation */ -static void __pmac +static void sanitize_timings(pmac_ide_hwif_t *pmif) { unsigned int value, value2 = 0; @@ -1123,13 +1123,13 @@ sanitize_timings(pmac_ide_hwif_t *pmif) pmif->timings[2] = pmif->timings[3] = value2; } -unsigned long __pmac +unsigned long pmac_ide_get_base(int index) { return pmac_ide[index].regbase; } -int __pmac +int pmac_ide_check_base(unsigned long base) { int ix; @@ -1140,7 +1140,7 @@ pmac_ide_check_base(unsigned long base) return -1; } -int __pmac +int pmac_ide_get_irq(unsigned long base) { int ix; @@ -1151,7 +1151,7 @@ pmac_ide_get_irq(unsigned long base) return 0; } -static int ide_majors[] __pmacdata = { 3, 22, 33, 34, 56, 57 }; +static int ide_majors[] = { 3, 22, 33, 34, 56, 57 }; dev_t __init pmac_find_ide_boot(char *bootdevice, int n) @@ -1701,7 +1701,7 @@ pmac_ide_probe(void) * pmac_ide_build_dmatable builds the DBDMA command list * for a transfer and sets the DBDMA channel to point to it. */ -static int __pmac +static int pmac_ide_build_dmatable(ide_drive_t *drive, struct request *rq) { struct dbdma_cmd *table; @@ -1785,7 +1785,7 @@ pmac_ide_build_dmatable(ide_drive_t *dri } /* Teardown mappings after DMA has completed. */ -static void __pmac +static void pmac_ide_destroy_dmatable (ide_drive_t *drive) { ide_hwif_t *hwif = drive->hwif; @@ -1802,7 +1802,7 @@ pmac_ide_destroy_dmatable (ide_drive_t * /* * Pick up best MDMA timing for the drive and apply it */ -static int __pmac +static int pmac_ide_mdma_enable(ide_drive_t *drive, u16 mode) { ide_hwif_t *hwif = HWIF(drive); @@ -1859,7 +1859,7 @@ pmac_ide_mdma_enable(ide_drive_t *drive, /* * Pick up best UDMA timing for the drive and apply it */ -static int __pmac +static int pmac_ide_udma_enable(ide_drive_t *drive, u16 mode) { ide_hwif_t *hwif = HWIF(drive); @@ -1915,7 +1915,7 @@ pmac_ide_udma_enable(ide_drive_t *drive, * Check what is the best DMA timing setting for the drive and * call appropriate functions to apply it. */ -static int __pmac +static int pmac_ide_dma_check(ide_drive_t *drive) { struct hd_driveid *id = drive->id; @@ -1967,7 +1967,7 @@ pmac_ide_dma_check(ide_drive_t *drive) * Prepare a DMA transfer. We build the DMA table, adjust the timings for * a read on KeyLargo ATA/66 and mark us as waiting for DMA completion */ -static int __pmac +static int pmac_ide_dma_setup(ide_drive_t *drive) { ide_hwif_t *hwif = HWIF(drive); @@ -1997,7 +1997,7 @@ pmac_ide_dma_setup(ide_drive_t *drive) return 0; } -static void __pmac +static void pmac_ide_dma_exec_cmd(ide_drive_t *drive, u8 command) { /* issue cmd to drive */ @@ -2008,7 +2008,7 @@ pmac_ide_dma_exec_cmd(ide_drive_t *drive * Kick the DMA controller into life after the DMA command has been issued * to the drive. */ -static void __pmac +static void pmac_ide_dma_start(ide_drive_t *drive) { pmac_ide_hwif_t* pmif = (pmac_ide_hwif_t *)HWIF(drive)->hwif_data; @@ -2024,7 +2024,7 @@ pmac_ide_dma_start(ide_drive_t *drive) /* * After a DMA transfer, make sure the controller is stopped */ -static int __pmac +static int pmac_ide_dma_end (ide_drive_t *drive) { pmac_ide_hwif_t* pmif = (pmac_ide_hwif_t *)HWIF(drive)->hwif_data; @@ -2052,7 +2052,7 @@ pmac_ide_dma_end (ide_drive_t *drive) * that's not implemented yet), on the other hand, we don't have shared interrupts * so it's not really a problem */ -static int __pmac +static int pmac_ide_dma_test_irq (ide_drive_t *drive) { pmac_ide_hwif_t* pmif = (pmac_ide_hwif_t *)HWIF(drive)->hwif_data; @@ -2108,19 +2108,19 @@ pmac_ide_dma_test_irq (ide_drive_t *driv return 1; } -static int __pmac +static int pmac_ide_dma_host_off (ide_drive_t *drive) { return 0; } -static int __pmac +static int pmac_ide_dma_host_on (ide_drive_t *drive) { return 0; } -static int __pmac +static int pmac_ide_dma_lostirq (ide_drive_t *drive) { pmac_ide_hwif_t* pmif = (pmac_ide_hwif_t *)HWIF(drive)->hwif_data; diff --git a/drivers/macintosh/ans-lcd.c b/drivers/macintosh/ans-lcd.c --- a/drivers/macintosh/ans-lcd.c +++ b/drivers/macintosh/ans-lcd.c @@ -27,7 +27,7 @@ static volatile unsigned char __iomem *a #undef DEBUG -static void __pmac +static void anslcd_write_byte_ctrl ( unsigned char c ) { #ifdef DEBUG @@ -43,14 +43,14 @@ anslcd_write_byte_ctrl ( unsigned char c } } -static void __pmac +static void anslcd_write_byte_data ( unsigned char c ) { out_8(anslcd_ptr + ANSLCD_DATA_IX, c); udelay(anslcd_short_delay); } -static ssize_t __pmac +static ssize_t anslcd_write( struct file * file, const char __user * buf, size_t count, loff_t *ppos ) { @@ -73,7 +73,7 @@ anslcd_write( struct file * file, const return p - buf; } -static int __pmac +static int anslcd_ioctl( struct inode * inode, struct file * file, unsigned int cmd, unsigned long arg ) { @@ -115,7 +115,7 @@ anslcd_ioctl( struct inode * inode, stru } } -static int __pmac +static int anslcd_open( struct inode * inode, struct file * file ) { return 0; diff --git a/drivers/macintosh/mediabay.c b/drivers/macintosh/mediabay.c --- a/drivers/macintosh/mediabay.c +++ b/drivers/macintosh/mediabay.c @@ -167,19 +167,19 @@ enum { * Functions for polling content of media bay */ -static u8 __pmac +static u8 ohare_mb_content(struct media_bay_info *bay) { return (MB_IN32(bay, OHARE_MBCR) >> 12) & 7; } -static u8 __pmac +static u8 heathrow_mb_content(struct media_bay_info *bay) { return (MB_IN32(bay, HEATHROW_MBCR) >> 12) & 7; } -static u8 __pmac +static u8 keylargo_mb_content(struct media_bay_info *bay) { int new_gpio; @@ -205,7 +205,7 @@ keylargo_mb_content(struct media_bay_inf * into reset state as well */ -static void __pmac +static void ohare_mb_power(struct media_bay_info* bay, int on_off) { if (on_off) { @@ -224,7 +224,7 @@ ohare_mb_power(struct media_bay_info* ba MB_BIC(bay, OHARE_MBCR, 0x00000F00); } -static void __pmac +static void heathrow_mb_power(struct media_bay_info* bay, int on_off) { if (on_off) { @@ -243,7 +243,7 @@ heathrow_mb_power(struct media_bay_info* MB_BIC(bay, HEATHROW_MBCR, 0x00000F00); } -static void __pmac +static void keylargo_mb_power(struct media_bay_info* bay, int on_off) { if (on_off) { @@ -267,7 +267,7 @@ keylargo_mb_power(struct media_bay_info* * enable the related busses */ -static int __pmac +static int ohare_mb_setup_bus(struct media_bay_info* bay, u8 device_id) { switch(device_id) { @@ -287,7 +287,7 @@ ohare_mb_setup_bus(struct media_bay_info return -ENODEV; } -static int __pmac +static int heathrow_mb_setup_bus(struct media_bay_info* bay, u8 device_id) { switch(device_id) { @@ -307,7 +307,7 @@ heathrow_mb_setup_bus(struct media_bay_i return -ENODEV; } -static int __pmac +static int keylargo_mb_setup_bus(struct media_bay_info* bay, u8 device_id) { switch(device_id) { @@ -330,43 +330,43 @@ keylargo_mb_setup_bus(struct media_bay_i * Functions for tweaking resets */ -static void __pmac +static void ohare_mb_un_reset(struct media_bay_info* bay) { MB_BIS(bay, OHARE_FCR, OH_BAY_RESET_N); } -static void __pmac keylargo_mb_init(struct media_bay_info *bay) +static void keylargo_mb_init(struct media_bay_info *bay) { MB_BIS(bay, KEYLARGO_MBCR, KL_MBCR_MB0_ENABLE); } -static void __pmac heathrow_mb_un_reset(struct media_bay_info* bay) +static void heathrow_mb_un_reset(struct media_bay_info* bay) { MB_BIS(bay, HEATHROW_FCR, HRW_BAY_RESET_N); } -static void __pmac keylargo_mb_un_reset(struct media_bay_info* bay) +static void keylargo_mb_un_reset(struct media_bay_info* bay) { MB_BIS(bay, KEYLARGO_MBCR, KL_MBCR_MB0_DEV_RESET); } -static void __pmac ohare_mb_un_reset_ide(struct media_bay_info* bay) +static void ohare_mb_un_reset_ide(struct media_bay_info* bay) { MB_BIS(bay, OHARE_FCR, OH_IDE1_RESET_N); } -static void __pmac heathrow_mb_un_reset_ide(struct media_bay_info* bay) +static void heathrow_mb_un_reset_ide(struct media_bay_info* bay) { MB_BIS(bay, HEATHROW_FCR, HRW_IDE1_RESET_N); } -static void __pmac keylargo_mb_un_reset_ide(struct media_bay_info* bay) +static void keylargo_mb_un_reset_ide(struct media_bay_info* bay) { MB_BIS(bay, KEYLARGO_FCR1, KL1_EIDE0_RESET_N); } -static inline void __pmac set_mb_power(struct media_bay_info* bay, int onoff) +static inline void set_mb_power(struct media_bay_info* bay, int onoff) { /* Power up up and assert the bay reset line */ if (onoff) { @@ -382,7 +382,7 @@ static inline void __pmac set_mb_power(s bay->timer = msecs_to_jiffies(MB_POWER_DELAY); } -static void __pmac poll_media_bay(struct media_bay_info* bay) +static void poll_media_bay(struct media_bay_info* bay) { int id = bay->ops->content(bay); @@ -415,7 +415,7 @@ static void __pmac poll_media_bay(struct } } -int __pmac check_media_bay(struct device_node *which_bay, int what) +int check_media_bay(struct device_node *which_bay, int what) { #ifdef CONFIG_BLK_DEV_IDE int i; @@ -432,7 +432,7 @@ int __pmac check_media_bay(struct device } EXPORT_SYMBOL(check_media_bay); -int __pmac check_media_bay_by_base(unsigned long base, int what) +int check_media_bay_by_base(unsigned long base, int what) { #ifdef CONFIG_BLK_DEV_IDE int i; @@ -449,7 +449,7 @@ int __pmac check_media_bay_by_base(unsig return -ENODEV; } -int __pmac media_bay_set_ide_infos(struct device_node* which_bay, unsigned long base, +int media_bay_set_ide_infos(struct device_node* which_bay, unsigned long base, int irq, int index) { #ifdef CONFIG_BLK_DEV_IDE @@ -489,7 +489,7 @@ int __pmac media_bay_set_ide_infos(struc return -ENODEV; } -static void __pmac media_bay_step(int i) +static void media_bay_step(int i) { struct media_bay_info* bay = &media_bays[i]; @@ -619,7 +619,7 @@ static void __pmac media_bay_step(int i) * with the IDE driver. It needs to be a thread because * ide_register can't be called from interrupt context. */ -static int __pmac media_bay_task(void *x) +static int media_bay_task(void *x) { int i; @@ -704,7 +704,7 @@ static int __devinit media_bay_attach(st } -static int __pmac media_bay_suspend(struct macio_dev *mdev, pm_message_t state) +static int media_bay_suspend(struct macio_dev *mdev, pm_message_t state) { struct media_bay_info *bay = macio_get_drvdata(mdev); @@ -719,7 +719,7 @@ static int __pmac media_bay_suspend(stru return 0; } -static int __pmac media_bay_resume(struct macio_dev *mdev) +static int media_bay_resume(struct macio_dev *mdev) { struct media_bay_info *bay = macio_get_drvdata(mdev); @@ -760,7 +760,7 @@ static int __pmac media_bay_resume(struc /* Definitions of "ops" structures. */ -static struct mb_ops ohare_mb_ops __pmacdata = { +static struct mb_ops ohare_mb_ops = { .name = "Ohare", .content = ohare_mb_content, .power = ohare_mb_power, @@ -769,7 +769,7 @@ static struct mb_ops ohare_mb_ops __pmac .un_reset_ide = ohare_mb_un_reset_ide, }; -static struct mb_ops heathrow_mb_ops __pmacdata = { +static struct mb_ops heathrow_mb_ops = { .name = "Heathrow", .content = heathrow_mb_content, .power = heathrow_mb_power, @@ -778,7 +778,7 @@ static struct mb_ops heathrow_mb_ops __p .un_reset_ide = heathrow_mb_un_reset_ide, }; -static struct mb_ops keylargo_mb_ops __pmacdata = { +static struct mb_ops keylargo_mb_ops = { .name = "KeyLargo", .init = keylargo_mb_init, .content = keylargo_mb_content, diff --git a/drivers/macintosh/via-cuda.c b/drivers/macintosh/via-cuda.c --- a/drivers/macintosh/via-cuda.c +++ b/drivers/macintosh/via-cuda.c @@ -37,7 +37,6 @@ static DEFINE_SPINLOCK(cuda_lock); #ifdef CONFIG_MAC #define CUDA_IRQ IRQ_MAC_ADB -#define __openfirmware #define eieio() #else #define CUDA_IRQ vias->intrs[0].line diff --git a/drivers/macintosh/via-pmu.c b/drivers/macintosh/via-pmu.c --- a/drivers/macintosh/via-pmu.c +++ b/drivers/macintosh/via-pmu.c @@ -244,7 +244,7 @@ int pmu_wink(struct adb_request *req); * - the number of response bytes which the PMU will return, or * -1 if it will send a length byte. */ -static const s8 pmu_data_len[256][2] __openfirmwaredata = { +static const s8 pmu_data_len[256][2] = { /* 0 1 2 3 4 5 6 7 */ /*00*/ {-1, 0},{-1, 0},{-1, 0},{-1, 0},{-1, 0},{-1, 0},{-1, 0},{-1, 0}, /*08*/ {-1,-1},{-1,-1},{-1,-1},{-1,-1},{-1,-1},{-1,-1},{-1,-1},{-1,-1}, @@ -295,7 +295,7 @@ static struct backlight_controller pmu_b }; #endif /* CONFIG_PMAC_BACKLIGHT */ -int __openfirmware +int find_via_pmu(void) { if (via != 0) @@ -374,7 +374,7 @@ find_via_pmu(void) } #ifdef CONFIG_ADB -static int __openfirmware +static int pmu_probe(void) { return vias == NULL? -ENODEV: 0; @@ -520,7 +520,7 @@ static int __init via_pmu_dev_init(void) device_initcall(via_pmu_dev_init); -static int __openfirmware +static int init_pmu(void) { int timeout; @@ -625,7 +625,7 @@ static void pmu_set_server_mode(int serv /* This new version of the code for 2400/3400/3500 powerbooks * is inspired from the implementation in gkrellm-pmu */ -static void __pmac +static void done_battery_state_ohare(struct adb_request* req) { /* format: @@ -713,7 +713,7 @@ done_battery_state_ohare(struct adb_requ clear_bit(0, &async_req_locks); } -static void __pmac +static void done_battery_state_smart(struct adb_request* req) { /* format: @@ -791,7 +791,7 @@ done_battery_state_smart(struct adb_requ clear_bit(0, &async_req_locks); } -static void __pmac +static void query_battery_state(void) { if (test_and_set_bit(0, &async_req_locks)) @@ -804,7 +804,7 @@ query_battery_state(void) 2, PMU_SMART_BATTERY_STATE, pmu_cur_battery+1); } -static int __pmac +static int proc_get_info(char *page, char **start, off_t off, int count, int *eof, void *data) { @@ -819,7 +819,7 @@ proc_get_info(char *page, char **start, return p - page; } -static int __pmac +static int proc_get_irqstats(char *page, char **start, off_t off, int count, int *eof, void *data) { @@ -846,7 +846,7 @@ proc_get_irqstats(char *page, char **sta return p - page; } -static int __pmac +static int proc_get_batt(char *page, char **start, off_t off, int count, int *eof, void *data) { @@ -870,7 +870,7 @@ proc_get_batt(char *page, char **start, return p - page; } -static int __pmac +static int proc_read_options(char *page, char **start, off_t off, int count, int *eof, void *data) { @@ -887,7 +887,7 @@ proc_read_options(char *page, char **sta return p - page; } -static int __pmac +static int proc_write_options(struct file *file, const char __user *buffer, unsigned long count, void *data) { @@ -934,7 +934,7 @@ proc_write_options(struct file *file, co #ifdef CONFIG_ADB /* Send an ADB command */ -static int __pmac +static int pmu_send_request(struct adb_request *req, int sync) { int i, ret; @@ -1014,7 +1014,7 @@ pmu_send_request(struct adb_request *req } /* Enable/disable autopolling */ -static int __pmac +static int pmu_adb_autopoll(int devs) { struct adb_request req; @@ -1037,7 +1037,7 @@ pmu_adb_autopoll(int devs) } /* Reset the ADB bus */ -static int __pmac +static int pmu_adb_reset_bus(void) { struct adb_request req; @@ -1072,7 +1072,7 @@ pmu_adb_reset_bus(void) #endif /* CONFIG_ADB */ /* Construct and send a pmu request */ -int __openfirmware +int pmu_request(struct adb_request *req, void (*done)(struct adb_request *), int nbytes, ...) { @@ -1098,7 +1098,7 @@ pmu_request(struct adb_request *req, voi return pmu_queue_request(req); } -int __pmac +int pmu_queue_request(struct adb_request *req) { unsigned long flags; @@ -1190,7 +1190,7 @@ pmu_done(struct adb_request *req) (*done)(req); } -static void __pmac +static void pmu_start(void) { struct adb_request *req; @@ -1214,7 +1214,7 @@ pmu_start(void) send_byte(req->data[0]); } -void __openfirmware +void pmu_poll(void) { if (!via) @@ -1224,7 +1224,7 @@ pmu_poll(void) via_pmu_interrupt(0, NULL, NULL); } -void __openfirmware +void pmu_poll_adb(void) { if (!via) @@ -1239,7 +1239,7 @@ pmu_poll_adb(void) || req_awaiting_reply)); } -void __openfirmware +void pmu_wait_complete(struct adb_request *req) { if (!via) @@ -1253,7 +1253,7 @@ pmu_wait_complete(struct adb_request *re * This is done to avoid spurrious shutdowns when we know we'll have * interrupts switched off for a long time */ -void __openfirmware +void pmu_suspend(void) { unsigned long flags; @@ -1293,7 +1293,7 @@ pmu_suspend(void) } while (1); } -void __openfirmware +void pmu_resume(void) { unsigned long flags; @@ -1323,7 +1323,7 @@ pmu_resume(void) } /* Interrupt data could be the result data from an ADB cmd */ -static void __pmac +static void pmu_handle_data(unsigned char *data, int len, struct pt_regs *regs) { unsigned char ints, pirq; @@ -1435,7 +1435,7 @@ next: goto next; } -static struct adb_request* __pmac +static struct adb_request* pmu_sr_intr(struct pt_regs *regs) { struct adb_request *req; @@ -1541,7 +1541,7 @@ pmu_sr_intr(struct pt_regs *regs) return NULL; } -static irqreturn_t __pmac +static irqreturn_t via_pmu_interrupt(int irq, void *arg, struct pt_regs *regs) { unsigned long flags; @@ -1629,7 +1629,7 @@ no_free_slot: return IRQ_RETVAL(handled); } -void __pmac +void pmu_unlock(void) { unsigned long flags; @@ -1642,7 +1642,7 @@ pmu_unlock(void) } -static irqreturn_t __pmac +static irqreturn_t gpio1_interrupt(int irq, void *arg, struct pt_regs *regs) { unsigned long flags; @@ -1663,12 +1663,12 @@ gpio1_interrupt(int irq, void *arg, stru } #ifdef CONFIG_PMAC_BACKLIGHT -static int backlight_to_bright[] __pmacdata = { +static int backlight_to_bright[] = { 0x7f, 0x46, 0x42, 0x3e, 0x3a, 0x36, 0x32, 0x2e, 0x2a, 0x26, 0x22, 0x1e, 0x1a, 0x16, 0x12, 0x0e }; -static int __openfirmware +static int pmu_set_backlight_enable(int on, int level, void* data) { struct adb_request req; @@ -1688,7 +1688,7 @@ pmu_set_backlight_enable(int on, int lev return 0; } -static void __openfirmware +static void pmu_bright_complete(struct adb_request *req) { if (req == &bright_req_1) @@ -1697,7 +1697,7 @@ pmu_bright_complete(struct adb_request * clear_bit(2, &async_req_locks); } -static int __openfirmware +static int pmu_set_backlight_level(int level, void* data) { if (vias == NULL) @@ -1717,7 +1717,7 @@ pmu_set_backlight_level(int level, void* } #endif /* CONFIG_PMAC_BACKLIGHT */ -void __pmac +void pmu_enable_irled(int on) { struct adb_request req; @@ -1732,7 +1732,7 @@ pmu_enable_irled(int on) pmu_wait_complete(&req); } -void __pmac +void pmu_restart(void) { struct adb_request req; @@ -1757,7 +1757,7 @@ pmu_restart(void) ; } -void __pmac +void pmu_shutdown(void) { struct adb_request req; @@ -2076,7 +2076,7 @@ pmu_unregister_sleep_notifier(struct pmu } /* Sleep is broadcast last-to-first */ -static int __pmac +static int broadcast_sleep(int when, int fallback) { int ret = PBOOK_SLEEP_OK; @@ -2101,7 +2101,7 @@ broadcast_sleep(int when, int fallback) } /* Wake is broadcast first-to-last */ -static int __pmac +static int broadcast_wake(void) { int ret = PBOOK_SLEEP_OK; @@ -2132,7 +2132,7 @@ static struct pci_save { } *pbook_pci_saves; static int pbook_npci_saves; -static void __pmac +static void pbook_alloc_pci_save(void) { int npci; @@ -2149,7 +2149,7 @@ pbook_alloc_pci_save(void) pbook_npci_saves = npci; } -static void __pmac +static void pbook_free_pci_save(void) { if (pbook_pci_saves == NULL) @@ -2159,7 +2159,7 @@ pbook_free_pci_save(void) pbook_npci_saves = 0; } -static void __pmac +static void pbook_pci_save(void) { struct pci_save *ps = pbook_pci_saves; @@ -2190,7 +2190,7 @@ pbook_pci_save(void) * during boot, it will be in the pci dev list. If it's disabled at this point * (and it will probably be), then you can't access it's config space. */ -static void __pmac +static void pbook_pci_restore(void) { u16 cmd; @@ -2238,7 +2238,7 @@ pbook_pci_restore(void) #ifdef DEBUG_SLEEP /* N.B. This doesn't work on the 3400 */ -void __pmac +void pmu_blink(int n) { struct adb_request req; @@ -2277,9 +2277,9 @@ pmu_blink(int n) * Put the powerbook to sleep. */ -static u32 save_via[8] __pmacdata; +static u32 save_via[8]; -static void __pmac +static void save_via_state(void) { save_via[0] = in_8(&via[ANH]); @@ -2291,7 +2291,7 @@ save_via_state(void) save_via[6] = in_8(&via[T1CL]); save_via[7] = in_8(&via[T1CH]); } -static void __pmac +static void restore_via_state(void) { out_8(&via[ANH], save_via[0]); @@ -2307,7 +2307,7 @@ restore_via_state(void) out_8(&via[IER], IER_SET | SR_INT | CB1_INT); } -static int __pmac +static int pmac_suspend_devices(void) { int ret; @@ -2397,7 +2397,7 @@ pmac_suspend_devices(void) return 0; } -static int __pmac +static int pmac_wakeup_devices(void) { mdelay(100); @@ -2436,7 +2436,7 @@ pmac_wakeup_devices(void) #define GRACKLE_NAP (1<<4) #define GRACKLE_SLEEP (1<<3) -int __pmac +int powerbook_sleep_grackle(void) { unsigned long save_l2cr; @@ -2520,7 +2520,7 @@ powerbook_sleep_grackle(void) return 0; } -static int __pmac +static int powerbook_sleep_Core99(void) { unsigned long save_l2cr; @@ -2620,7 +2620,7 @@ powerbook_sleep_Core99(void) #define PB3400_MEM_CTRL 0xf8000000 #define PB3400_MEM_CTRL_SLEEP 0x70 -static int __pmac +static int powerbook_sleep_3400(void) { int ret, i, x; @@ -2720,9 +2720,9 @@ struct pmu_private { }; static LIST_HEAD(all_pmu_pvt); -static DEFINE_SPINLOCK(all_pvt_lock __pmacdata); +static DEFINE_SPINLOCK(all_pvt_lock); -static void __pmac +static void pmu_pass_intr(unsigned char *data, int len) { struct pmu_private *pp; @@ -2751,7 +2751,7 @@ pmu_pass_intr(unsigned char *data, int l spin_unlock_irqrestore(&all_pvt_lock, flags); } -static int __pmac +static int pmu_open(struct inode *inode, struct file *file) { struct pmu_private *pp; @@ -2773,7 +2773,7 @@ pmu_open(struct inode *inode, struct fil return 0; } -static ssize_t __pmac +static ssize_t pmu_read(struct file *file, char __user *buf, size_t count, loff_t *ppos) { @@ -2825,14 +2825,14 @@ pmu_read(struct file *file, char __user return ret; } -static ssize_t __pmac +static ssize_t pmu_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos) { return 0; } -static unsigned int __pmac +static unsigned int pmu_fpoll(struct file *filp, poll_table *wait) { struct pmu_private *pp = filp->private_data; @@ -2849,7 +2849,7 @@ pmu_fpoll(struct file *filp, poll_table return mask; } -static int __pmac +static int pmu_release(struct inode *inode, struct file *file) { struct pmu_private *pp = file->private_data; @@ -2874,8 +2874,7 @@ pmu_release(struct inode *inode, struct return 0; } -/* Note: removed __openfirmware here since it causes link errors */ -static int __pmac +static int pmu_ioctl(struct inode * inode, struct file *filp, u_int cmd, u_long arg) { @@ -2957,7 +2956,7 @@ pmu_ioctl(struct inode * inode, struct f return error; } -static struct file_operations pmu_device_fops __pmacdata = { +static struct file_operations pmu_device_fops = { .read = pmu_read, .write = pmu_write, .poll = pmu_fpoll, @@ -2966,7 +2965,7 @@ static struct file_operations pmu_device .release = pmu_release, }; -static struct miscdevice pmu_device __pmacdata = { +static struct miscdevice pmu_device = { PMU_MINOR, "pmu", &pmu_device_fops }; @@ -2982,7 +2981,7 @@ device_initcall(pmu_device_init); #ifdef DEBUG_SLEEP -static inline void __pmac +static inline void polled_handshake(volatile unsigned char __iomem *via) { via[B] &= ~TREQ; eieio(); @@ -2993,7 +2992,7 @@ polled_handshake(volatile unsigned char ; } -static inline void __pmac +static inline void polled_send_byte(volatile unsigned char __iomem *via, int x) { via[ACR] |= SR_OUT | SR_EXT; eieio(); @@ -3001,7 +3000,7 @@ polled_send_byte(volatile unsigned char polled_handshake(via); } -static inline int __pmac +static inline int polled_recv_byte(volatile unsigned char __iomem *via) { int x; @@ -3013,7 +3012,7 @@ polled_recv_byte(volatile unsigned char return x; } -int __pmac +int pmu_polled_request(struct adb_request *req) { unsigned long flags; diff --git a/drivers/macintosh/via-pmu68k.c b/drivers/macintosh/via-pmu68k.c --- a/drivers/macintosh/via-pmu68k.c +++ b/drivers/macintosh/via-pmu68k.c @@ -835,7 +835,7 @@ static struct pci_save { } *pbook_pci_saves; static int n_pbook_pci_saves; -static inline void __openfirmware +static inline void pbook_pci_save(void) { int npci; @@ -863,7 +863,7 @@ pbook_pci_save(void) } } -static inline void __openfirmware +static inline void pbook_pci_restore(void) { u16 cmd; @@ -902,7 +902,7 @@ pbook_pci_restore(void) #define IRQ_ENABLE ((unsigned int *)0xf3000024) #define MEM_CTRL ((unsigned int *)0xf8000070) -int __openfirmware powerbook_sleep(void) +int powerbook_sleep(void) { int ret, i, x; static int save_backlight; @@ -1001,25 +1001,24 @@ int __openfirmware powerbook_sleep(void) /* * Support for /dev/pmu device */ -static int __openfirmware pmu_open(struct inode *inode, struct file *file) +static int pmu_open(struct inode *inode, struct file *file) { return 0; } -static ssize_t __openfirmware pmu_read(struct file *file, char *buf, +static ssize_t pmu_read(struct file *file, char *buf, size_t count, loff_t *ppos) { return 0; } -static ssize_t __openfirmware pmu_write(struct file *file, const char *buf, +static ssize_t pmu_write(struct file *file, const char *buf, size_t count, loff_t *ppos) { return 0; } -/* Note: removed __openfirmware here since it causes link errors */ -static int /*__openfirmware*/ pmu_ioctl(struct inode * inode, struct file *filp, +static int pmu_ioctl(struct inode * inode, struct file *filp, u_int cmd, u_long arg) { int error; From linuxppc at jdl.com Sun Sep 18 01:38:23 2005 From: linuxppc at jdl.com (Jon Loeliger) Date: Sat, 17 Sep 2005 10:38:23 -0500 Subject: PATCH powerpc: 03/04 Remove section free() and linker script bits In-Reply-To: Your message of "Sat, 17 Sep 2005 10:31:52 CDT." References: Message-ID: diff --git a/arch/ppc/kernel/vmlinux.lds.S b/arch/ppc/kernel/vmlinux.lds.S --- a/arch/ppc/kernel/vmlinux.lds.S +++ b/arch/ppc/kernel/vmlinux.lds.S @@ -149,32 +149,6 @@ SECTIONS . = ALIGN(4096); _sextratext = .; - __pmac_begin = .; - .pmac.text : { *(.pmac.text) } - .pmac.data : { *(.pmac.data) } - . = ALIGN(4096); - __pmac_end = .; - - . = ALIGN(4096); - __prep_begin = .; - .prep.text : { *(.prep.text) } - .prep.data : { *(.prep.data) } - . = ALIGN(4096); - __prep_end = .; - - . = ALIGN(4096); - __chrp_begin = .; - .chrp.text : { *(.chrp.text) } - .chrp.data : { *(.chrp.data) } - . = ALIGN(4096); - __chrp_end = .; - - . = ALIGN(4096); - __openfirmware_begin = .; - .openfirmware.text : { *(.openfirmware.text) } - .openfirmware.data : { *(.openfirmware.data) } - . = ALIGN(4096); - __openfirmware_end = .; _eextratext = .; __bss_start = .; diff --git a/arch/ppc/mm/init.c b/arch/ppc/mm/init.c --- a/arch/ppc/mm/init.c +++ b/arch/ppc/mm/init.c @@ -74,10 +74,6 @@ unsigned long agp_special_page; extern char _end[]; extern char etext[], _stext[]; extern char __init_begin, __init_end; -extern char __prep_begin, __prep_end; -extern char __chrp_begin, __chrp_end; -extern char __pmac_begin, __pmac_end; -extern char __openfirmware_begin, __openfirmware_end; #ifdef CONFIG_HIGHMEM pte_t *kmap_pte; @@ -167,14 +163,6 @@ void free_initmem(void) printk ("Freeing unused kernel memory:"); FREESEC(init); - if (_machine != _MACH_Pmac) - FREESEC(pmac); - if (_machine != _MACH_chrp) - FREESEC(chrp); - if (_machine != _MACH_prep) - FREESEC(prep); - if (!have_of) - FREESEC(openfirmware); printk("\n"); ppc_md.progress = NULL; #undef FREESEC From linuxppc at jdl.com Sun Sep 18 01:39:46 2005 From: linuxppc at jdl.com (Jon Loeliger) Date: Sat, 17 Sep 2005 10:39:46 -0500 Subject: PATCH powerpc: 04/04 Merge simplified sections.h into asm-powerpc In-Reply-To: Your message of "Sat, 17 Sep 2005 10:31:52 CDT." References: Message-ID: diff --git a/include/asm-powerpc/sections.h b/include/asm-powerpc/sections.h new file mode 100644 --- /dev/null +++ b/include/asm-powerpc/sections.h @@ -0,0 +1,20 @@ +#ifndef _ASM_POWERPC_SECTIONS_H +#define _ASM_POWERPC_SECTIONS_H + +#include + +#ifdef __powerpc64__ + +extern char _end[]; + +static inline int in_kernel_text(unsigned long addr) +{ + if (addr >= (unsigned long)_stext && addr < (unsigned long)__init_end) + return 1; + + return 0; +} + +#endif + +#endif /* _ASM_POWERPC_SECTIONS_H */ diff --git a/include/asm-ppc/sections.h b/include/asm-ppc/sections.h deleted file mode 100644 --- a/include/asm-ppc/sections.h +++ /dev/null @@ -1,33 +0,0 @@ -#ifdef __KERNEL__ -#ifndef _PPC_SECTIONS_H -#define _PPC_SECTIONS_H - -#include - -#define __pmac __attribute__ ((__section__ (".pmac.text"))) -#define __pmacdata __attribute__ ((__section__ (".pmac.data"))) -#define __pmacfunc(__argpmac) \ - __argpmac __pmac; \ - __argpmac - -#define __prep __attribute__ ((__section__ (".prep.text"))) -#define __prepdata __attribute__ ((__section__ (".prep.data"))) -#define __prepfunc(__argprep) \ - __argprep __prep; \ - __argprep - -#define __chrp __attribute__ ((__section__ (".chrp.text"))) -#define __chrpdata __attribute__ ((__section__ (".chrp.data"))) -#define __chrpfunc(__argchrp) \ - __argchrp __chrp; \ - __argchrp - -/* this is actually just common chrp/pmac code, not OF code -- Cort */ -#define __openfirmware __attribute__ ((__section__ (".openfirmware.text"))) -#define __openfirmwaredata __attribute__ ((__section__ (".openfirmware.data"))) -#define __openfirmwarefunc(__argopenfirmware) \ - __argopenfirmware __openfirmware; \ - __argopenfirmware - -#endif /* _PPC_SECTIONS_H */ -#endif /* __KERNEL__ */ diff --git a/include/asm-ppc64/sections.h b/include/asm-ppc64/sections.h deleted file mode 100644 --- a/include/asm-ppc64/sections.h +++ /dev/null @@ -1,29 +0,0 @@ -#ifndef _PPC64_SECTIONS_H -#define _PPC64_SECTIONS_H - -extern char _end[]; - -#include - -#define __pmac -#define __pmacdata - -#define __prep -#define __prepdata - -#define __chrp -#define __chrpdata - -#define __openfirmware -#define __openfirmwaredata - - -static inline int in_kernel_text(unsigned long addr) -{ - if (addr >= (unsigned long)_stext && addr < (unsigned long)__init_end) - return 1; - - return 0; -} - -#endif From arnd at arndb.de Sun Sep 18 03:22:13 2005 From: arnd at arndb.de (Arnd Bergmann) Date: Sat, 17 Sep 2005 19:22:13 +0200 Subject: ppc64: BPA iommu fails to build (BUILD_BUG_ON) In-Reply-To: References: Message-ID: <200509171922.14625.arnd@arndb.de> On S?nnavend 17 September 2005 10:01, Alexey Dobriyan wrote: > After a patch to make BUILD_BUG_ON error at compile-time went in > 2.6.14-git1, arch/ppc64/kernel/bpa_iommu.c fails to build This patch fixes that, I forgot to send it out with the previous updates. Please apply. Signed-off-by: Arnd Bergmann Index: linux-cg/arch/ppc64/kernel/bpa_iommu.c =================================================================== --- linux-cg.orig/arch/ppc64/kernel/bpa_iommu.c +++ linux-cg/arch/ppc64/kernel/bpa_iommu.c @@ -99,7 +99,7 @@ get_iost_entry(unsigned long iopt_base, break; default: /* not a known compile time constant */ - BUILD_BUG_ON(1); + BUG(); break; } From olof at lixom.net Sun Sep 18 06:00:46 2005 From: olof at lixom.net (Olof Johansson) Date: Sat, 17 Sep 2005 15:00:46 -0500 Subject: [PATCH] PPC64: Fix boot for some pre-POWER4 systems Message-ID: <20050917200046.GA16386@austin.ibm.com> Hi, I suggest this to be included in 2.6.14 for two reasons: 1. While the bug has been there a couple of releases, it does keep some users machines from booting and this resolves it. 2. In case of regressions caused by this patch, this is in code that is only used in non-partitioned POWER4 or older systems. PowerMac, Maple, iSeries and any POWER5 system is using other ways of determining any iommu table partitioning. I.e. it's not affecting the majority of the PPC64 user base. ---- Some RS64 systems (such as F80) have non-python host bridges with EADS. However, they have two EADS with 4 buses each under them, so the old logic that assumed no more than 7 busses per PHB failed miserably. Big thanks to Olaf Hering for helping me test this, he's got one of the few machines that broke from the previous logic. Also, to be a bit smarter at detecting the need for a PHB-level IOMMU table by checking for the presence of an ISA bus. Only PHBs with ISA bridges should need the PHB-level table. Signed-off-by: Olof Johansson Index: 2.6/arch/ppc64/kernel/pSeries_iommu.c =================================================================== --- 2.6.orig/arch/ppc64/kernel/pSeries_iommu.c 2005-09-14 17:45:56.000000000 -0500 +++ 2.6/arch/ppc64/kernel/pSeries_iommu.c 2005-09-14 18:04:02.000000000 -0500 @@ -265,8 +265,10 @@ static void iommu_table_setparms(struct tbl->it_offset = phb->dma_window_base_cur >> PAGE_SHIFT; /* Test if we are going over 2GB of DMA space */ - if (phb->dma_window_base_cur + phb->dma_window_size > (1L << 31)) + if (phb->dma_window_base_cur + phb->dma_window_size > 0x80000000ul) { + udbg_printf("PCI_DMA: Unexpected number of IOAs under this PHB.\n"); panic("PCI_DMA: Unexpected number of IOAs under this PHB.\n"); + } phb->dma_window_base_cur += phb->dma_window_size; @@ -310,92 +312,84 @@ static void iommu_table_setparms_lpar(st static void iommu_bus_setup_pSeries(struct pci_bus *bus) { - struct device_node *dn, *pdn; - struct pci_dn *pci; + struct device_node *dn; struct iommu_table *tbl; + struct device_node *isa_dn, *isa_dn_orig; + struct device_node *tmp; + struct pci_dn *pci; + int children; DBG("iommu_bus_setup_pSeries, bus %p, bus->self %p\n", bus, bus->self); - /* For each (root) bus, we carve up the available DMA space in 256MB - * pieces. Since each piece is used by one (sub) bus/device, that would - * give a maximum of 7 devices per PHB. In most cases, this is plenty. - * - * The exception is on Python PHBs (pre-POWER4). Here we don't have EADS - * bridges below the PHB to allocate the sectioned tables to, so instead - * we allocate a 1GB table at the PHB level. - */ - dn = pci_bus_to_OF_node(bus); - pci = dn->data; + pci = PCI_DN(dn); - if (!bus->self) { - /* Root bus */ - if (is_python(dn)) { - unsigned int *iohole; - - DBG("Python root bus %s\n", bus->name); - - iohole = (unsigned int *)get_property(dn, "io-hole", 0); - - if (iohole) { - /* On first bus we need to leave room for the - * ISA address space. Just skip the first 256MB - * alltogether. This leaves 768MB for the window. - */ - DBG("PHB has io-hole, reserving 256MB\n"); - pci->phb->dma_window_size = 3 << 28; - pci->phb->dma_window_base_cur = 1 << 28; - } else { - /* 1GB window by default */ - pci->phb->dma_window_size = 1 << 30; - pci->phb->dma_window_base_cur = 0; - } + if (bus->self) { + /* This is not a root bus, any setup will be done for the + * device-side of the bridge in iommu_dev_setup_pSeries(). + */ + return; + } - tbl = kmalloc(sizeof(struct iommu_table), GFP_KERNEL); + /* Check if the ISA bus on the system is under + * this PHB. + */ + isa_dn = isa_dn_orig = of_find_node_by_type(NULL, "isa"); + + while (isa_dn && isa_dn != dn) + isa_dn = isa_dn->parent; + + if (isa_dn_orig) + of_node_put(isa_dn_orig); + + /* Count number of direct PCI children of the PHB. + * All PCI device nodes have class-code property, so it's + * an easy way to find them. + */ + for (children = 0, tmp = dn->child; tmp; tmp = tmp->sibling) + if (get_property(tmp, "class-code", NULL)) + children++; + + DBG("Children: %d\n", children); + + /* Calculate amount of DMA window per slot. Each window must be + * a power of two (due to pci_alloc_consistent requirements). + * + * Keep 256MB aside for PHBs with ISA. + */ - 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 - * doesn't hurt to allocate it on other machines - * -- it'll just be unused since new tables are - * allocated on the EADS level. - * - * Allocate at offset 128MB to avoid having to deal - * with ISA holes; 128MB table for IDE is plenty. - */ - pci->phb->dma_window_size = 1 << 27; - pci->phb->dma_window_base_cur = 1 << 27; + if (!isa_dn) { + /* No ISA/IDE - just set window size and return */ + pci->phb->dma_window_size = 0x80000000ul; /* To be divided */ + + while (pci->phb->dma_window_size * children > 0x80000000ul) + pci->phb->dma_window_size >>= 1; + DBG("No ISA/IDE, window size is %x\n", pci->phb->dma_window_size); + pci->phb->dma_window_base_cur = 0; - tbl = kmalloc(sizeof(struct iommu_table), GFP_KERNEL); + return; + } - iommu_table_setparms(pci->phb, dn, tbl); - pci->iommu_table = iommu_init_table(tbl); + /* If we have ISA, then we probably have an IDE + * controller too. Allocate a 128MB table but + * skip the first 128MB to avoid stepping on ISA + * space. + */ + pci->phb->dma_window_size = 0x8000000ul; + pci->phb->dma_window_base_cur = 0x8000000ul; - /* All child buses have 256MB tables */ - pci->phb->dma_window_size = 1 << 28; - } - } else { - pdn = pci_bus_to_OF_node(bus->parent); + tbl = kmalloc(sizeof(struct iommu_table), GFP_KERNEL); - if (!bus->parent->self && !is_python(pdn)) { - struct iommu_table *tbl; - /* First child and not python means this is the EADS - * level. Allocate new table for this slot with 256MB - * window. - */ + iommu_table_setparms(pci->phb, dn, tbl); + pci->iommu_table = iommu_init_table(tbl); - tbl = kmalloc(sizeof(struct iommu_table), GFP_KERNEL); + /* Divide the rest (1.75GB) among the children */ + pci->phb->dma_window_size = 0x80000000ul; + while (pci->phb->dma_window_size * children > 0x70000000ul) + pci->phb->dma_window_size >>= 1; - iommu_table_setparms(pci->phb, dn, tbl); + DBG("ISA/IDE, window size is %x\n", pci->phb->dma_window_size); - pci->iommu_table = iommu_init_table(tbl); - } else { - /* Lower than first child or under python, use parent table */ - pci->iommu_table = PCI_DN(pdn)->iommu_table; - } - } } @@ -446,14 +440,29 @@ static void iommu_bus_setup_pSeriesLP(st static void iommu_dev_setup_pSeries(struct pci_dev *dev) { struct device_node *dn, *mydn; + struct iommu_table *tbl; DBG("iommu_dev_setup_pSeries, dev %p (%s)\n", dev, dev->pretty_name); - /* Now copy the iommu_table ptr from the bus device down to the - * pci device_node. This means get_iommu_table() won't need to search - * up the device tree to find it. - */ + mydn = dn = pci_device_to_OF_node(dev); + /* If we're the direct child of a root bus, then we need to allocate + * an iommu table ourselves. The bus setup code should have setup + * the window sizes already. + */ + if (!dev->bus->self) { + DBG(" --> first child, no bridge. Allocating iommu table.\n"); + tbl = kmalloc(sizeof(struct iommu_table), GFP_KERNEL); + iommu_table_setparms(PCI_DN(dn)->phb, dn, tbl); + PCI_DN(mydn)->iommu_table = iommu_init_table(tbl); + + return; + } + + /* If this device is further down the bus tree, search upwards until + * an already allocated iommu table is found and use that. + */ + while (dn && dn->data && PCI_DN(dn)->iommu_table == NULL) dn = dn->parent; From benh at kernel.crashing.org Sun Sep 18 11:25:35 2005 From: benh at kernel.crashing.org (Benjamin Herrenschmidt) Date: Sun, 18 Sep 2005 11:25:35 +1000 Subject: PATCH powerpc: 00/04 Remove __pmac, etc, sections, merge sections.h In-Reply-To: References: Message-ID: <1127006735.23095.4.camel@gaston> On Sat, 2005-09-17 at 10:31 -0500, Jon Loeliger wrote: > Here is a new patch that removes all notion of the pmac, prep, > chrp and openfirmware initialization sections, and then unifies > the sections.h files without those __pmac, etc, sections identifiers > cluttering things up. When did we decide to do that ? Some people are still using ppc machines with rather small memory footprint (old ones), it's handy to get rid of the code you don't need... It would make sense if we could compile CHRP/PMAC/PREP in/out (like we can do with platforms on ppc64) so that people who have tight memory requirements can build a PReP or CHRP kernel without all of the pmac code. Ben. From benh at kernel.crashing.org Sun Sep 18 11:28:35 2005 From: benh at kernel.crashing.org (Benjamin Herrenschmidt) Date: Sun, 18 Sep 2005 11:28:35 +1000 Subject: PATCH powerpc: Merge asm-ppc*/sections.h In-Reply-To: <20050915205709.GA31156@iram.es> References: <1126644202.11056.59.camel@cashmere.sps.mot.com> <200509140435.21916.arnd@arndb.de> <1126705588.14036.10.camel@cashmere.sps.mot.com> <17193.22140.962651.122114@cargo.ozlabs.ibm.com> <20050915205709.GA31156@iram.es> Message-ID: <1127006916.23095.6.camel@gaston> > So yes, I object strongly object if I don't have a way > of removing useless PMAC code. The kernel is already very > bloated compared with the 2.2 we started with, which was > well below 1MB with the minimal setup: serial console, root > on NFS, no swap, some locally modules to control the PCI<->VME > bridge and what is behind on the VME bus. I think we should have the ability to not build some platforms like we have on ppc64. That would allow you to build a PReP kernel without CHRP and PMAC code. Ben. From kumar.gala at freescale.com Mon Sep 19 03:50:30 2005 From: kumar.gala at freescale.com (Kumar Gala) Date: Sun, 18 Sep 2005 12:50:30 -0500 Subject: PATCH powerpc: 00/04 Remove __pmac, etc, sections, merge sections.h In-Reply-To: <1127006735.23095.4.camel@gaston> References: <1127006735.23095.4.camel@gaston> Message-ID: <216D7B09-CC72-482D-9C06-3416D5E02DBE@freescale.com> On Sep 17, 2005, at 8:25 PM, Benjamin Herrenschmidt wrote: > On Sat, 2005-09-17 at 10:31 -0500, Jon Loeliger wrote: > >> Here is a new patch that removes all notion of the pmac, prep, >> chrp and openfirmware initialization sections, and then unifies >> the sections.h files without those __pmac, etc, sections identifiers >> cluttering things up. >> > > When did we decide to do that ? Some people are still using ppc > machines > with rather small memory footprint (old ones), it's handy to get > rid of > the code you don't need... It would make sense if we could compile > CHRP/PMAC/PREP in/out (like we can do with platforms on ppc64) so that > people who have tight memory requirements can build a PReP or CHRP > kernel without all of the pmac code. I think the discussion earlier in this week lead us to believe this was the way to go. We can provide a simple patch to allow selecting CHRP/PMAC/PREP specifically in addition to MUTLIPLATFORM. - kumar From hch at lst.de Mon Sep 19 08:12:20 2005 From: hch at lst.de (Christoph Hellwig) Date: Mon, 19 Sep 2005 00:12:20 +0200 Subject: G5 pci probing regression Message-ID: <20050918221220.GA31975@lst.de> With current TOT the kernel crashes for me when loading the fusion driver. Investigation shows that: the crash happens on the first mmio access and was introduces between 2.6.13-git12 and 2.6.14-rc1. It looks like the OF-based PCI resource assignment changes, as a small patch like the one below makes the driver works just fine again for me: --- linux-2.6.14-rc1/arch/ppc64/kernel/pmac_setup.c 2005-09-18 23:50:26.000000000 +0200 +++ linux-2.6.14-rc1/arch/ppc64/kernel/pmac_setup.c 2005-09-18 23:50:49.000000000 +0200 @@ -483,7 +483,7 @@ /* We need to use normal PCI probing for the AGP bus, since the device for the AGP bridge isn't in the tree. */ - if (bus->self == NULL && device_is_compatible(node, "u3-agp")) +// if (bus->self == NULL && device_is_compatible(node, "u3-agp")) return PCI_PROBE_NORMAL; return PCI_PROBE_DEVTREE; From benh at kernel.crashing.org Mon Sep 19 08:13:16 2005 From: benh at kernel.crashing.org (Benjamin Herrenschmidt) Date: Mon, 19 Sep 2005 08:13:16 +1000 Subject: PATCH powerpc: 00/04 Remove __pmac, etc, sections, merge sections.h In-Reply-To: <216D7B09-CC72-482D-9C06-3416D5E02DBE@freescale.com> References: <1127006735.23095.4.camel@gaston> <216D7B09-CC72-482D-9C06-3416D5E02DBE@freescale.com> Message-ID: <1127081596.4502.8.camel@gaston> > I think the discussion earlier in this week lead us to believe this > was the way to go. We can provide a simple patch to allow selecting > CHRP/PMAC/PREP specifically in addition to MUTLIPLATFORM. It should be done like ppc64, that is MULTIPLATFORM can be built with an aribtrary "set" of platforms. In fact, I think the merged arch should trash if possible all "exclusive" CONFIG_MYBOARD stuff, but only ever do what ppc64 does, that is any combination of platforms for the same CPU family can be built at the same time. Ben. From paulus at samba.org Mon Sep 19 08:26:54 2005 From: paulus at samba.org (Paul Mackerras) Date: Mon, 19 Sep 2005 08:26:54 +1000 Subject: G5 pci probing regression In-Reply-To: <20050918221220.GA31975@lst.de> References: <20050918221220.GA31975@lst.de> Message-ID: <17197.59822.43168.956195@cargo.ozlabs.ibm.com> Christoph Hellwig writes: > With current TOT the kernel crashes for me when loading the fusion > driver. Investigation shows that: the crash happens on the first mmio > access and was introduces between 2.6.13-git12 and 2.6.14-rc1. It looks > like the OF-based PCI resource assignment changes, as a small patch like > the one below makes the driver works just fine again for me: Hmmm. Could you send me the output of lspci -v and the contents of /proc/pci, /proc/iomem and /proc/ioports with and without that change? Thanks, Paul. From paulus at samba.org Mon Sep 19 09:22:25 2005 From: paulus at samba.org (Paul Mackerras) Date: Mon, 19 Sep 2005 09:22:25 +1000 Subject: Merge Question on asm-ppc*/rwsem.h In-Reply-To: <1126631205.11056.15.camel@cashmere.sps.mot.com> References: <1126631205.11056.15.camel@cashmere.sps.mot.com> Message-ID: <17197.63153.78371.490616@cargo.ozlabs.ibm.com> Jon Loeliger writes: > Which begs the question, what is the "else smp_wmb();" clause > really doing for us in the ppc32 case, and can we either > get rid of it, or is it safe to add to the ppc64 case? I think the difference is that the atomic ops that return a value also have include a barrier on ppc64, but don't on ppc32 (although they probably should). IOW I think the merged case should follow ppc64 here. Paul. From paulus at samba.org Mon Sep 19 09:57:42 2005 From: paulus at samba.org (Paul Mackerras) Date: Mon, 19 Sep 2005 09:57:42 +1000 Subject: Git tree for the 32/64 merge Message-ID: <17197.65270.548340.377011@cargo.ozlabs.ibm.com> I have created a git tree on kernel.org as a place to accumulate the patches for the ppc32/ppc64 merge. It is at: rsync://rsync.kernel.org/pub/scm/linux/kernel/git/paulus/powerpc-merge.git It doesn't include the objects in Linus' tree; instead it has an objects/info/alternates file pointing to Linus' tree. This tree contains all the patches I found in a scan through my inbox that relate to the merge and haven't already gone to Linus. If you have a patch that should go in, please resend it. Paul. From jdl at jdl.com Mon Sep 19 12:20:04 2005 From: jdl at jdl.com (Jon Loeliger) Date: Sun, 18 Sep 2005 21:20:04 -0500 Subject: Merge Question on asm-ppc*/rwsem.h In-Reply-To: Your message of "Mon, 19 Sep 2005 09:22:25 +1000." <17197.63153.78371.490616@cargo.ozlabs.ibm.com> References: <1126631205.11056.15.camel@cashmere.sps.mot.com> <17197.63153.78371.490616@cargo.ozlabs.ibm.com> Message-ID: So sprach Paul Mackerras: > > I think the difference is that the atomic ops that return a value also > have include a barrier on ppc64, but don't on ppc32 (although they > probably should). IOW I think the merged case should follow ppc64 > here. Excellent! I will submit that patch in the style of ppc64 early this week. Thanks for the feedback, jdl From kumar.gala at freescale.com Mon Sep 19 12:36:24 2005 From: kumar.gala at freescale.com (Kumar Gala) Date: Sun, 18 Sep 2005 21:36:24 -0500 Subject: Git tree for the 32/64 merge In-Reply-To: <17197.65270.548340.377011@cargo.ozlabs.ibm.com> References: <17197.65270.548340.377011@cargo.ozlabs.ibm.com> Message-ID: <4EA4DEDF-0D49-4C60-B236-88D96AE9335B@freescale.com> Can you get this tree added to gitweb on kernel.org - kumar On Sep 18, 2005, at 6:57 PM, Paul Mackerras wrote: > I have created a git tree on kernel.org as a place to accumulate the > patches for the ppc32/ppc64 merge. It is at: > > rsync://rsync.kernel.org/pub/scm/linux/kernel/git/paulus/powerpc- > merge.g > it > > It doesn't include the objects in Linus' tree; instead it has an > objects/info/alternates file pointing to Linus' tree. > > This tree contains all the patches I found in a scan through my inbox > that relate to the merge and haven't already gone to Linus. If you > have a patch that should go in, please resend it. > > Paul. > _______________________________________________ > Linuxppc-dev mailing list > Linuxppc-dev at ozlabs.org > https://ozlabs.org/mailman/listinfo/linuxppc-dev > From jdl at jdl.com Mon Sep 19 13:27:01 2005 From: jdl at jdl.com (Jon Loeliger) Date: Sun, 18 Sep 2005 22:27:01 -0500 Subject: Git tree for the 32/64 merge In-Reply-To: Your message of "Mon, 19 Sep 2005 09:57:42 +1000." <17197.65270.548340.377011@cargo.ozlabs.ibm.com> References: <17197.65270.548340.377011@cargo.ozlabs.ibm.com> Message-ID: So, like, the other day Paul Mackerras mumbled: > > This tree contains all the patches I found in a scan through my inbox > that relate to the merge and haven't already gone to Linus. If you > have a patch that should go in, please resend it. I think you might have missed my posix_types.h merge patch of Sep 10. Would you like a repost? Thanks, jdl From cartoes at uol.com.br Mon Sep 19 14:41:52 2005 From: cartoes at uol.com.br (cartoes at uol.com.br) Date: Mon, 19 Sep 2005 00:41:52 -0400 (EDT) Subject: Cartoes UOL Message-ID: <200509190441.AAA02319@gs0.media3.net> An HTML attachment was scrubbed... URL: http://ozlabs.org/pipermail/linuxppc64-dev/attachments/20050919/deb162fb/attachment.htm From sharada at in.ibm.com Mon Sep 19 17:12:51 2005 From: sharada at in.ibm.com (R Sharada) Date: Mon, 19 Sep 2005 12:42:51 +0530 Subject: [PATCH 4/4] basic kexec tools for ppc64 (compile warning cleanups) In-Reply-To: <20050914124834.GE3968@in.ibm.com> References: <20050914124405.GA3968@in.ibm.com> <20050914124534.GB3968@in.ibm.com> <20050914124645.GC3968@in.ibm.com> <20050914124729.GD3968@in.ibm.com> <20050914124834.GE3968@in.ibm.com> Message-ID: <20050919071251.GA2792@in.ibm.com> Hello, The basic_kexec_tools_for_ppc64 had a few issues with variable redeclarations that was throwing some compile warnings on GCC 4, though I was not seeing some of those on my GCC ver 3 on SLES9. This is a revised patch, which cleans up the errors and this should compile ok on ppc64. I also cleaned up a few other compile warnings that were showing up on my system. Thanks to Michael Neuling for pointing this out. Thanks and Regards, Sharada This provides the basic functionality in kexec-elf-ppc64.c to load the various segments required for kexec-tools on ppc64. It also adds ppc64 arch support in build scripts and cleans up some misc error in member deferencing to allow the build to succeed. Signed-off-by: R Sharada --- kexec-tools-1.101-sharada/configure | 7 kexec-tools-1.101-sharada/kexec/arch/ppc64/kexec-elf-ppc64.c | 240 ++++++++-- kexec-tools-1.101-sharada/kexec/arch/ppc64/kexec-elf-rel-ppc64.c | 2 kexec-tools-1.101-sharada/kexec/arch/ppc64/kexec-ppc64.h | 2 4 files changed, 214 insertions(+), 37 deletions(-) diff -puN configure~basic_kexec_tools_for_ppc64 configure --- kexec-tools-1.101/configure~basic_kexec_tools_for_ppc64 2005-09-19 12:10:55.000000000 +0530 +++ kexec-tools-1.101-sharada/configure 2005-09-19 12:11:26.000000000 +0530 @@ -1384,6 +1384,9 @@ case $host_cpu in powerpc ) host_cpu="ppc" ;; + powerpc64 ) + host_cpu="ppc64" + ;; * ) host_cpu="$host_cpu" ;; @@ -1421,6 +1424,10 @@ if test "${with_gamecube+set}" = set; th EXTRA_CFLAGS="$EXTRA_CFLAGS -DCONFIG_GAMECUBE=1" fi; +# Check whether ppc64. Add -m64 for building 64-bit binary +if test "$ARCH"=ppc64; then + EXTRA_CFLAGS="$EXTRA_CFLAGS -m64" +fi; # Check whether --with-zlib or --without-zlib was given. if test "${with_zlib+set}" = set; then diff -puN kexec/arch/ppc64/kexec-elf-ppc64.c~basic_kexec_tools_for_ppc64 kexec/arch/ppc64/kexec-elf-ppc64.c --- kexec-tools-1.101/kexec/arch/ppc64/kexec-elf-ppc64.c~basic_kexec_tools_for_ppc64 2005-09-19 12:10:55.000000000 +0530 +++ kexec-tools-1.101-sharada/kexec/arch/ppc64/kexec-elf-ppc64.c 2005-09-19 12:13:28.000000000 +0530 @@ -3,6 +3,7 @@ * * Copyright (C) 2004 Adam Litke (agl at us.ibm.com) * Copyright (C) 2004 IBM Corp. + * Copyright (C) 2005 R Sharada (sharada at in.ibm.com) * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -33,45 +34,15 @@ #include "../../kexec.h" #include "../../kexec-elf.h" #include "kexec-ppc64.h" +#include #define BOOTLOADER "kexec" #define BOOTLOADER_VERSION VERSION #define MAX_COMMAND_LINE 256 -#define UPSZ(X) ((sizeof(X) + 3) & ~3) -static struct boot_notes { - Elf_Bhdr hdr; - Elf_Nhdr bl_hdr; - unsigned char bl_desc[UPSZ(BOOTLOADER)]; - Elf_Nhdr blv_hdr; - unsigned char blv_desc[UPSZ(BOOTLOADER_VERSION)]; - Elf_Nhdr cmd_hdr; - unsigned char command_line[0]; -} elf_boot_notes = { - .hdr = { - .b_signature = 0x0E1FB007, - .b_size = sizeof(elf_boot_notes), - .b_checksum = 0, - .b_records = 3, - }, - .bl_hdr = { - .n_namesz = 0, - .n_descsz = sizeof(BOOTLOADER), - .n_type = EBN_BOOTLOADER_NAME, - }, - .bl_desc = BOOTLOADER, - .blv_hdr = { - .n_namesz = 0, - .n_descsz = sizeof(BOOTLOADER_VERSION), - .n_type = EBN_BOOTLOADER_VERSION, - }, - .blv_desc = BOOTLOADER_VERSION, - .cmd_hdr = { - .n_namesz = 0, - .n_descsz = 0, - .n_type = EBN_COMMAND_LINE, - }, -}; +int create_flatten_tree(struct kexec_info *, unsigned char **, unsigned long *); +int parse_options(char *); +int setup_memory_ranges(void); int elf_ppc64_probe(const char *buf, off_t len) { @@ -94,12 +65,62 @@ int elf_ppc64_probe(const char *buf, off return result; } -int elf_ppc64_load(int argc, char **argv, const char *buf, off_t len, +int elf_ppc64_load(int argc, char **argv, const char *buf, off_t len, struct kexec_info *info) { struct mem_ehdr ehdr; + const char *command_line; + const char *input_options; + int command_line_len; + const char *ramdisk; + unsigned long *lp; + int result; + int opt; +#define OPT_APPEND (OPT_ARCH_MAX+0) +#define OPT_RAMDISK (OPT_ARCH_MAX+1) + + static const struct option options[] = { + KEXEC_ARCH_OPTIONS + { "append", 1, NULL, OPT_APPEND }, + { "ramdisk", 1, NULL, OPT_RAMDISK }, + { 0, 0, NULL, 0 }, + }; + + static const char short_options[] = KEXEC_OPT_STR ""; /* Parse command line arguments */ + initrd_base = 0; + initrd_size = 0; + command_line = 0; + input_options = 0; + ramdisk = 0; + + while ((opt = getopt_long(argc, argv, short_options, options, 0)) != -1) { + switch (opt) { + default: + /* Ignore core options */ + if (opt < OPT_ARCH_MAX) { + break; + } + case '?': + usage(); + return -1; + case OPT_APPEND: + input_options = optarg; + break; + case OPT_RAMDISK: + ramdisk = optarg; + break; + } + } + + command_line_len = 0; + if (command_line) { + command_line_len = strlen(command_line) + 1; + } + + if (input_options) + parse_options(input_options); /* Parse the Elf file */ result = build_elf_exec_info(buf, len, &ehdr); @@ -109,15 +130,162 @@ int elf_ppc64_load(int argc, char **argv } /* Load the Elf data */ + setup_memory_ranges(); + /* Load the Elf data. Physical load addresses in elf64 header do not + * show up correctly. Use user supplied address for now to patch the + * elf header + */ + unsigned long long base_addr; + struct mem_phdr *phdr; + size_t size; + + phdr = &ehdr.e_phdr[0]; + size = phdr->p_filesz; + if (size > phdr->p_memsz) { + size = phdr->p_memsz; + } + + base_addr = (unsigned long)locate_hole(info, size, 0, 0, + 0xFFFFFFFFFFFFFFFFUL, 1); + ehdr.e_phdr[0].p_paddr = base_addr; result = elf_exec_load(&ehdr, info); if (result < 0) { free_elf_info(&ehdr); return result; } - return 1; + + /* Add a ram-disk to the current image */ + if (ramdisk) { + unsigned char *ramdisk_buf = NULL; + off_t ramdisk_size = 0; + unsigned long long ramdisk_addr; + + ramdisk_buf = slurp_file(ramdisk, &ramdisk_size); + add_buffer(info, ramdisk_buf, ramdisk_size, ramdisk_size, 0, 0, + 0xFFFFFFFFFFFFFFFFUL, 1); + ramdisk_addr = (unsigned long long)info->segment[info->nr_segments-1].mem; + initrd_base = ramdisk_addr; + initrd_size = ramdisk_size; + } + + /* Add v2wrap to the current image */ + unsigned char *v2wrap_buf = NULL; + off_t v2wrap_size = 0; + unsigned int off_len; + unsigned char *seg_buf; + unsigned int rsvmap_len; + unsigned long long *ptr; + struct bootblock *bb_ptr; + unsigned int devtree_size; + + v2wrap_buf = (char *) malloc(purgatory_size); + if (v2wrap_buf == NULL) { + free_elf_info(&ehdr); + return -1; + } + memcpy(v2wrap_buf, purgatory, purgatory_size); + v2wrap_size = purgatory_size; + create_flatten_tree(info, &v2wrap_buf, &v2wrap_size); + add_buffer(info, v2wrap_buf, v2wrap_size, v2wrap_size, 0, 0, + 0xFFFFFFFFFFFFFFFFUL, -1); + + /* patch reserve map address for flattened device-tree */ + base_addr = (unsigned long long)info->segment[(info->nr_segments)-1].mem; + seg_buf = (unsigned char *)info->segment[(info->nr_segments)-1].buf; + seg_buf = seg_buf + 0x100; /* offset to end of v2wrap */ + bb_ptr = (struct bootblock *)seg_buf; + rsvmap_len = bb_ptr->off_dt_struct - bb_ptr->off_mem_rsvmap; + devtree_size = bb_ptr->totalsize; + off_len = sizeof(struct bootblock); + off_len += 7; off_len &= ~7; + seg_buf = seg_buf + off_len; + off_len = rsvmap_len / (2 * sizeof(unsigned long long)); + + ptr = (unsigned long long *)seg_buf; + ptr = ptr + 2*(off_len-2); + *ptr = base_addr + 0x100; + ptr++; + *ptr = (unsigned long long)devtree_size; + + unsigned int nr_segments; + nr_segments = info->nr_segments; + lp = info->segment[nr_segments-1].buf + 0x100; + lp--; + *lp = info->segment[0].mem; + info->entry = info->segment[nr_segments-1].mem; + + unsigned int i; + for (i = 0; i < nr_segments; i++) + printf("segment[i].mem:%lx\n", info->segment[i].mem); + + return 0; } void elf_ppc64_usage(void) { fprintf(stderr, "elf support is still broken\n"); } + +struct param_struct { + const char *name; + void *val; +}; +struct param_struct params; + +static char *next_arg(char *args, char **param, char **val) +{ + unsigned int i, equals = 0; + char *next; + + /* Chew any extra spaces */ + while (*args == ' ') args++; + for (i = 0; args[i]; i++) { + if (args[i] == ' ') + break; + if (equals == 0) { + if (args[i] == '=') + equals = i; + } + } + *param = args; + if (!equals) + *val = NULL; + else { + args[equals] = '\0'; + *val = args + equals + 1; + } + + if (args[i]) { + args[i] = '\0'; + next = args + i + 1; + } else + next = args + i; + return next; +} + +static int add_arg(char *param, char*val) +{ + int ret = 0; + if (strcmp(param, "initrd-base")==0) + initrd_base=strtoul(val, NULL, 0); + else if (strcmp(param, "initrd-size")==0) + initrd_size=strtoul(val, NULL, 0); + else { + printf("invalid option\n"); + ret = 1; + } + return ret; +} + +int parse_options(char *options) +{ + char *param, *val; + /* initrd-addr , initrd-size */ + while (*options) { + int ret; + options = next_arg(options, ¶m, &val); + ret = add_arg(param, val); + } + /* All parsed OK */ + return 0; +} diff -puN kexec/arch/ppc64/kexec-elf-rel-ppc64.c~basic_kexec_tools_for_ppc64 kexec/arch/ppc64/kexec-elf-rel-ppc64.c --- kexec-tools-1.101/kexec/arch/ppc64/kexec-elf-rel-ppc64.c~basic_kexec_tools_for_ppc64 2005-09-19 12:10:55.000000000 +0530 +++ kexec-tools-1.101-sharada/kexec/arch/ppc64/kexec-elf-rel-ppc64.c 2005-09-19 12:11:26.000000000 +0530 @@ -22,7 +22,7 @@ static struct mem_shdr *toc_section(cons struct mem_shdr *shdr, *shdr_end; unsigned char *strtab; strtab = ehdr->e_shdr[ehdr->e_shstrndx].sh_data; - shdr_end = &ehdr->e_shdr[ehdr->shnum]; + shdr_end = &ehdr->e_shdr[ehdr->e_shnum]; for(shdr = ehdr->e_shdr; shdr != shdr_end; shdr++) { if (strcmp(shdr->sh_name, ".toc") == 0) { return shdr; diff -puN kexec/arch/ppc64/kexec-ppc64.h~basic_kexec_tools_for_ppc64 kexec/arch/ppc64/kexec-ppc64.h --- kexec-tools-1.101/kexec/arch/ppc64/kexec-ppc64.h~basic_kexec_tools_for_ppc64 2005-09-19 12:10:55.000000000 +0530 +++ kexec-tools-1.101-sharada/kexec/arch/ppc64/kexec-ppc64.h 2005-09-19 12:11:26.000000000 +0530 @@ -6,6 +6,8 @@ int elf_ppc64_load(int argc, char **argv struct kexec_info *info); void elf_ppc64_usage(void); +unsigned long initrd_base; +unsigned long initrd_size; /* boot block version 2 as defined by the linux kernel */ struct bootblock { unsigned magic, _ From sfr at canb.auug.org.au Mon Sep 19 17:33:25 2005 From: sfr at canb.auug.org.au (Stephen Rothwell) Date: Mon, 19 Sep 2005 17:33:25 +1000 Subject: [PATCH] powerpc: Move arch/ppc*/kernel/vecemu.c to arch/powerpc Message-ID: <20050919173325.73cf7a36.sfr@canb.auug.org.au> This file is the same in both architectures so create arch/powerpc/kernel and move it there. Signed-off-by: Stephen Rothwell --- arch/powerpc/kernel/vecemu.c | 345 ++++++++++++++++++++++++++++++++++++++++++ arch/ppc/kernel/Makefile | 2 arch/ppc/kernel/vecemu.c | 345 ------------------------------------------ arch/ppc64/kernel/Makefile | 3 arch/ppc64/kernel/vecemu.c | 346 ------------------------------------------ 5 files changed, 350 insertions(+), 691 deletions(-) create mode 100644 arch/powerpc/kernel/vecemu.c delete mode 100644 arch/ppc/kernel/vecemu.c delete mode 100644 arch/ppc64/kernel/vecemu.c Compiled for ppc defconfig, iSeries (almost defconfig), pSeries defconfig and g5 defconfig. -- Cheers, Stephen Rothwell sfr at canb.auug.org.au http://www.canb.auug.org.au/~sfr/ 672ea98fe3cd3ce7371198fc000d37808667f64c diff --git a/arch/powerpc/kernel/vecemu.c b/arch/powerpc/kernel/vecemu.c new file mode 100644 --- /dev/null +++ b/arch/powerpc/kernel/vecemu.c @@ -0,0 +1,345 @@ +/* + * Routines to emulate some Altivec/VMX instructions, specifically + * those that can trap when given denormalized operands in Java mode. + */ +#include +#include +#include +#include +#include +#include + +/* Functions in vector.S */ +extern void vaddfp(vector128 *dst, vector128 *a, vector128 *b); +extern void vsubfp(vector128 *dst, vector128 *a, vector128 *b); +extern void vmaddfp(vector128 *dst, vector128 *a, vector128 *b, vector128 *c); +extern void vnmsubfp(vector128 *dst, vector128 *a, vector128 *b, vector128 *c); +extern void vrefp(vector128 *dst, vector128 *src); +extern void vrsqrtefp(vector128 *dst, vector128 *src); +extern void vexptep(vector128 *dst, vector128 *src); + +static unsigned int exp2s[8] = { + 0x800000, + 0x8b95c2, + 0x9837f0, + 0xa5fed7, + 0xb504f3, + 0xc5672a, + 0xd744fd, + 0xeac0c7 +}; + +/* + * Computes an estimate of 2^x. The `s' argument is the 32-bit + * single-precision floating-point representation of x. + */ +static unsigned int eexp2(unsigned int s) +{ + int exp, pwr; + unsigned int mant, frac; + + /* extract exponent field from input */ + exp = ((s >> 23) & 0xff) - 127; + if (exp > 7) { + /* check for NaN input */ + if (exp == 128 && (s & 0x7fffff) != 0) + return s | 0x400000; /* return QNaN */ + /* 2^-big = 0, 2^+big = +Inf */ + return (s & 0x80000000)? 0: 0x7f800000; /* 0 or +Inf */ + } + if (exp < -23) + return 0x3f800000; /* 1.0 */ + + /* convert to fixed point integer in 9.23 representation */ + pwr = (s & 0x7fffff) | 0x800000; + if (exp > 0) + pwr <<= exp; + else + pwr >>= -exp; + if (s & 0x80000000) + pwr = -pwr; + + /* extract integer part, which becomes exponent part of result */ + exp = (pwr >> 23) + 126; + if (exp >= 254) + return 0x7f800000; + if (exp < -23) + return 0; + + /* table lookup on top 3 bits of fraction to get mantissa */ + mant = exp2s[(pwr >> 20) & 7]; + + /* linear interpolation using remaining 20 bits of fraction */ + asm("mulhwu %0,%1,%2" : "=r" (frac) + : "r" (pwr << 12), "r" (0x172b83ff)); + asm("mulhwu %0,%1,%2" : "=r" (frac) : "r" (frac), "r" (mant)); + mant += frac; + + if (exp >= 0) + return mant + (exp << 23); + + /* denormalized result */ + exp = -exp; + mant += 1 << (exp - 1); + return mant >> exp; +} + +/* + * Computes an estimate of log_2(x). The `s' argument is the 32-bit + * single-precision floating-point representation of x. + */ +static unsigned int elog2(unsigned int s) +{ + int exp, mant, lz, frac; + + exp = s & 0x7f800000; + mant = s & 0x7fffff; + if (exp == 0x7f800000) { /* Inf or NaN */ + if (mant != 0) + s |= 0x400000; /* turn NaN into QNaN */ + return s; + } + if ((exp | mant) == 0) /* +0 or -0 */ + return 0xff800000; /* return -Inf */ + + if (exp == 0) { + /* denormalized */ + asm("cntlzw %0,%1" : "=r" (lz) : "r" (mant)); + mant <<= lz - 8; + exp = (-118 - lz) << 23; + } else { + mant |= 0x800000; + exp -= 127 << 23; + } + + if (mant >= 0xb504f3) { /* 2^0.5 * 2^23 */ + exp |= 0x400000; /* 0.5 * 2^23 */ + asm("mulhwu %0,%1,%2" : "=r" (mant) + : "r" (mant), "r" (0xb504f334)); /* 2^-0.5 * 2^32 */ + } + if (mant >= 0x9837f0) { /* 2^0.25 * 2^23 */ + exp |= 0x200000; /* 0.25 * 2^23 */ + asm("mulhwu %0,%1,%2" : "=r" (mant) + : "r" (mant), "r" (0xd744fccb)); /* 2^-0.25 * 2^32 */ + } + if (mant >= 0x8b95c2) { /* 2^0.125 * 2^23 */ + exp |= 0x100000; /* 0.125 * 2^23 */ + asm("mulhwu %0,%1,%2" : "=r" (mant) + : "r" (mant), "r" (0xeac0c6e8)); /* 2^-0.125 * 2^32 */ + } + if (mant > 0x800000) { /* 1.0 * 2^23 */ + /* calculate (mant - 1) * 1.381097463 */ + /* 1.381097463 == 0.125 / (2^0.125 - 1) */ + asm("mulhwu %0,%1,%2" : "=r" (frac) + : "r" ((mant - 0x800000) << 1), "r" (0xb0c7cd3a)); + exp += frac; + } + s = exp & 0x80000000; + if (exp != 0) { + if (s) + exp = -exp; + asm("cntlzw %0,%1" : "=r" (lz) : "r" (exp)); + lz = 8 - lz; + if (lz > 0) + exp >>= lz; + else if (lz < 0) + exp <<= -lz; + s += ((lz + 126) << 23) + exp; + } + return s; +} + +#define VSCR_SAT 1 + +static int ctsxs(unsigned int x, int scale, unsigned int *vscrp) +{ + int exp, mant; + + exp = (x >> 23) & 0xff; + mant = x & 0x7fffff; + if (exp == 255 && mant != 0) + return 0; /* NaN -> 0 */ + exp = exp - 127 + scale; + if (exp < 0) + return 0; /* round towards zero */ + if (exp >= 31) { + /* saturate, unless the result would be -2^31 */ + if (x + (scale << 23) != 0xcf000000) + *vscrp |= VSCR_SAT; + return (x & 0x80000000)? 0x80000000: 0x7fffffff; + } + mant |= 0x800000; + mant = (mant << 7) >> (30 - exp); + return (x & 0x80000000)? -mant: mant; +} + +static unsigned int ctuxs(unsigned int x, int scale, unsigned int *vscrp) +{ + int exp; + unsigned int mant; + + exp = (x >> 23) & 0xff; + mant = x & 0x7fffff; + if (exp == 255 && mant != 0) + return 0; /* NaN -> 0 */ + exp = exp - 127 + scale; + if (exp < 0) + return 0; /* round towards zero */ + if (x & 0x80000000) { + /* negative => saturate to 0 */ + *vscrp |= VSCR_SAT; + return 0; + } + if (exp >= 32) { + /* saturate */ + *vscrp |= VSCR_SAT; + return 0xffffffff; + } + mant |= 0x800000; + mant = (mant << 8) >> (31 - exp); + return mant; +} + +/* Round to floating integer, towards 0 */ +static unsigned int rfiz(unsigned int x) +{ + int exp; + + exp = ((x >> 23) & 0xff) - 127; + if (exp == 128 && (x & 0x7fffff) != 0) + return x | 0x400000; /* NaN -> make it a QNaN */ + if (exp >= 23) + return x; /* it's an integer already (or Inf) */ + if (exp < 0) + return x & 0x80000000; /* |x| < 1.0 rounds to 0 */ + return x & ~(0x7fffff >> exp); +} + +/* Round to floating integer, towards +/- Inf */ +static unsigned int rfii(unsigned int x) +{ + int exp, mask; + + exp = ((x >> 23) & 0xff) - 127; + if (exp == 128 && (x & 0x7fffff) != 0) + return x | 0x400000; /* NaN -> make it a QNaN */ + if (exp >= 23) + return x; /* it's an integer already (or Inf) */ + if ((x & 0x7fffffff) == 0) + return x; /* +/-0 -> +/-0 */ + if (exp < 0) + /* 0 < |x| < 1.0 rounds to +/- 1.0 */ + return (x & 0x80000000) | 0x3f800000; + mask = 0x7fffff >> exp; + /* mantissa overflows into exponent - that's OK, + it can't overflow into the sign bit */ + return (x + mask) & ~mask; +} + +/* Round to floating integer, to nearest */ +static unsigned int rfin(unsigned int x) +{ + int exp, half; + + exp = ((x >> 23) & 0xff) - 127; + if (exp == 128 && (x & 0x7fffff) != 0) + return x | 0x400000; /* NaN -> make it a QNaN */ + if (exp >= 23) + return x; /* it's an integer already (or Inf) */ + if (exp < -1) + return x & 0x80000000; /* |x| < 0.5 -> +/-0 */ + if (exp == -1) + /* 0.5 <= |x| < 1.0 rounds to +/- 1.0 */ + return (x & 0x80000000) | 0x3f800000; + half = 0x400000 >> exp; + /* add 0.5 to the magnitude and chop off the fraction bits */ + return (x + half) & ~(0x7fffff >> exp); +} + +int emulate_altivec(struct pt_regs *regs) +{ + unsigned int instr, i; + unsigned int va, vb, vc, vd; + vector128 *vrs; + + if (get_user(instr, (unsigned int __user *) regs->nip)) + return -EFAULT; + if ((instr >> 26) != 4) + return -EINVAL; /* not an altivec instruction */ + vd = (instr >> 21) & 0x1f; + va = (instr >> 16) & 0x1f; + vb = (instr >> 11) & 0x1f; + vc = (instr >> 6) & 0x1f; + + vrs = current->thread.vr; + switch (instr & 0x3f) { + case 10: + switch (vc) { + case 0: /* vaddfp */ + vaddfp(&vrs[vd], &vrs[va], &vrs[vb]); + break; + case 1: /* vsubfp */ + vsubfp(&vrs[vd], &vrs[va], &vrs[vb]); + break; + case 4: /* vrefp */ + vrefp(&vrs[vd], &vrs[vb]); + break; + case 5: /* vrsqrtefp */ + vrsqrtefp(&vrs[vd], &vrs[vb]); + break; + case 6: /* vexptefp */ + for (i = 0; i < 4; ++i) + vrs[vd].u[i] = eexp2(vrs[vb].u[i]); + break; + case 7: /* vlogefp */ + for (i = 0; i < 4; ++i) + vrs[vd].u[i] = elog2(vrs[vb].u[i]); + break; + case 8: /* vrfin */ + for (i = 0; i < 4; ++i) + vrs[vd].u[i] = rfin(vrs[vb].u[i]); + break; + case 9: /* vrfiz */ + for (i = 0; i < 4; ++i) + vrs[vd].u[i] = rfiz(vrs[vb].u[i]); + break; + case 10: /* vrfip */ + for (i = 0; i < 4; ++i) { + u32 x = vrs[vb].u[i]; + x = (x & 0x80000000)? rfiz(x): rfii(x); + vrs[vd].u[i] = x; + } + break; + case 11: /* vrfim */ + for (i = 0; i < 4; ++i) { + u32 x = vrs[vb].u[i]; + x = (x & 0x80000000)? rfii(x): rfiz(x); + vrs[vd].u[i] = x; + } + break; + case 14: /* vctuxs */ + for (i = 0; i < 4; ++i) + vrs[vd].u[i] = ctuxs(vrs[vb].u[i], va, + ¤t->thread.vscr.u[3]); + break; + case 15: /* vctsxs */ + for (i = 0; i < 4; ++i) + vrs[vd].u[i] = ctsxs(vrs[vb].u[i], va, + ¤t->thread.vscr.u[3]); + break; + default: + return -EINVAL; + } + break; + case 46: /* vmaddfp */ + vmaddfp(&vrs[vd], &vrs[va], &vrs[vb], &vrs[vc]); + break; + case 47: /* vnmsubfp */ + vnmsubfp(&vrs[vd], &vrs[va], &vrs[vb], &vrs[vc]); + break; + default: + return -EINVAL; + } + + return 0; +} diff --git a/arch/ppc/kernel/Makefile b/arch/ppc/kernel/Makefile --- a/arch/ppc/kernel/Makefile +++ b/arch/ppc/kernel/Makefile @@ -36,3 +36,5 @@ ifndef CONFIG_MATH_EMULATION obj-$(CONFIG_8xx) += softemu8xx.o endif +# These are here while we do the architecture merge +vecemu-y += ../../powerpc/kernel/vecemu.o diff --git a/arch/ppc/kernel/vecemu.c b/arch/ppc/kernel/vecemu.c deleted file mode 100644 --- a/arch/ppc/kernel/vecemu.c +++ /dev/null @@ -1,345 +0,0 @@ -/* - * Routines to emulate some Altivec/VMX instructions, specifically - * those that can trap when given denormalized operands in Java mode. - */ -#include -#include -#include -#include -#include -#include - -/* Functions in vector.S */ -extern void vaddfp(vector128 *dst, vector128 *a, vector128 *b); -extern void vsubfp(vector128 *dst, vector128 *a, vector128 *b); -extern void vmaddfp(vector128 *dst, vector128 *a, vector128 *b, vector128 *c); -extern void vnmsubfp(vector128 *dst, vector128 *a, vector128 *b, vector128 *c); -extern void vrefp(vector128 *dst, vector128 *src); -extern void vrsqrtefp(vector128 *dst, vector128 *src); -extern void vexptep(vector128 *dst, vector128 *src); - -static unsigned int exp2s[8] = { - 0x800000, - 0x8b95c2, - 0x9837f0, - 0xa5fed7, - 0xb504f3, - 0xc5672a, - 0xd744fd, - 0xeac0c7 -}; - -/* - * Computes an estimate of 2^x. The `s' argument is the 32-bit - * single-precision floating-point representation of x. - */ -static unsigned int eexp2(unsigned int s) -{ - int exp, pwr; - unsigned int mant, frac; - - /* extract exponent field from input */ - exp = ((s >> 23) & 0xff) - 127; - if (exp > 7) { - /* check for NaN input */ - if (exp == 128 && (s & 0x7fffff) != 0) - return s | 0x400000; /* return QNaN */ - /* 2^-big = 0, 2^+big = +Inf */ - return (s & 0x80000000)? 0: 0x7f800000; /* 0 or +Inf */ - } - if (exp < -23) - return 0x3f800000; /* 1.0 */ - - /* convert to fixed point integer in 9.23 representation */ - pwr = (s & 0x7fffff) | 0x800000; - if (exp > 0) - pwr <<= exp; - else - pwr >>= -exp; - if (s & 0x80000000) - pwr = -pwr; - - /* extract integer part, which becomes exponent part of result */ - exp = (pwr >> 23) + 126; - if (exp >= 254) - return 0x7f800000; - if (exp < -23) - return 0; - - /* table lookup on top 3 bits of fraction to get mantissa */ - mant = exp2s[(pwr >> 20) & 7]; - - /* linear interpolation using remaining 20 bits of fraction */ - asm("mulhwu %0,%1,%2" : "=r" (frac) - : "r" (pwr << 12), "r" (0x172b83ff)); - asm("mulhwu %0,%1,%2" : "=r" (frac) : "r" (frac), "r" (mant)); - mant += frac; - - if (exp >= 0) - return mant + (exp << 23); - - /* denormalized result */ - exp = -exp; - mant += 1 << (exp - 1); - return mant >> exp; -} - -/* - * Computes an estimate of log_2(x). The `s' argument is the 32-bit - * single-precision floating-point representation of x. - */ -static unsigned int elog2(unsigned int s) -{ - int exp, mant, lz, frac; - - exp = s & 0x7f800000; - mant = s & 0x7fffff; - if (exp == 0x7f800000) { /* Inf or NaN */ - if (mant != 0) - s |= 0x400000; /* turn NaN into QNaN */ - return s; - } - if ((exp | mant) == 0) /* +0 or -0 */ - return 0xff800000; /* return -Inf */ - - if (exp == 0) { - /* denormalized */ - asm("cntlzw %0,%1" : "=r" (lz) : "r" (mant)); - mant <<= lz - 8; - exp = (-118 - lz) << 23; - } else { - mant |= 0x800000; - exp -= 127 << 23; - } - - if (mant >= 0xb504f3) { /* 2^0.5 * 2^23 */ - exp |= 0x400000; /* 0.5 * 2^23 */ - asm("mulhwu %0,%1,%2" : "=r" (mant) - : "r" (mant), "r" (0xb504f334)); /* 2^-0.5 * 2^32 */ - } - if (mant >= 0x9837f0) { /* 2^0.25 * 2^23 */ - exp |= 0x200000; /* 0.25 * 2^23 */ - asm("mulhwu %0,%1,%2" : "=r" (mant) - : "r" (mant), "r" (0xd744fccb)); /* 2^-0.25 * 2^32 */ - } - if (mant >= 0x8b95c2) { /* 2^0.125 * 2^23 */ - exp |= 0x100000; /* 0.125 * 2^23 */ - asm("mulhwu %0,%1,%2" : "=r" (mant) - : "r" (mant), "r" (0xeac0c6e8)); /* 2^-0.125 * 2^32 */ - } - if (mant > 0x800000) { /* 1.0 * 2^23 */ - /* calculate (mant - 1) * 1.381097463 */ - /* 1.381097463 == 0.125 / (2^0.125 - 1) */ - asm("mulhwu %0,%1,%2" : "=r" (frac) - : "r" ((mant - 0x800000) << 1), "r" (0xb0c7cd3a)); - exp += frac; - } - s = exp & 0x80000000; - if (exp != 0) { - if (s) - exp = -exp; - asm("cntlzw %0,%1" : "=r" (lz) : "r" (exp)); - lz = 8 - lz; - if (lz > 0) - exp >>= lz; - else if (lz < 0) - exp <<= -lz; - s += ((lz + 126) << 23) + exp; - } - return s; -} - -#define VSCR_SAT 1 - -static int ctsxs(unsigned int x, int scale, unsigned int *vscrp) -{ - int exp, mant; - - exp = (x >> 23) & 0xff; - mant = x & 0x7fffff; - if (exp == 255 && mant != 0) - return 0; /* NaN -> 0 */ - exp = exp - 127 + scale; - if (exp < 0) - return 0; /* round towards zero */ - if (exp >= 31) { - /* saturate, unless the result would be -2^31 */ - if (x + (scale << 23) != 0xcf000000) - *vscrp |= VSCR_SAT; - return (x & 0x80000000)? 0x80000000: 0x7fffffff; - } - mant |= 0x800000; - mant = (mant << 7) >> (30 - exp); - return (x & 0x80000000)? -mant: mant; -} - -static unsigned int ctuxs(unsigned int x, int scale, unsigned int *vscrp) -{ - int exp; - unsigned int mant; - - exp = (x >> 23) & 0xff; - mant = x & 0x7fffff; - if (exp == 255 && mant != 0) - return 0; /* NaN -> 0 */ - exp = exp - 127 + scale; - if (exp < 0) - return 0; /* round towards zero */ - if (x & 0x80000000) { - /* negative => saturate to 0 */ - *vscrp |= VSCR_SAT; - return 0; - } - if (exp >= 32) { - /* saturate */ - *vscrp |= VSCR_SAT; - return 0xffffffff; - } - mant |= 0x800000; - mant = (mant << 8) >> (31 - exp); - return mant; -} - -/* Round to floating integer, towards 0 */ -static unsigned int rfiz(unsigned int x) -{ - int exp; - - exp = ((x >> 23) & 0xff) - 127; - if (exp == 128 && (x & 0x7fffff) != 0) - return x | 0x400000; /* NaN -> make it a QNaN */ - if (exp >= 23) - return x; /* it's an integer already (or Inf) */ - if (exp < 0) - return x & 0x80000000; /* |x| < 1.0 rounds to 0 */ - return x & ~(0x7fffff >> exp); -} - -/* Round to floating integer, towards +/- Inf */ -static unsigned int rfii(unsigned int x) -{ - int exp, mask; - - exp = ((x >> 23) & 0xff) - 127; - if (exp == 128 && (x & 0x7fffff) != 0) - return x | 0x400000; /* NaN -> make it a QNaN */ - if (exp >= 23) - return x; /* it's an integer already (or Inf) */ - if ((x & 0x7fffffff) == 0) - return x; /* +/-0 -> +/-0 */ - if (exp < 0) - /* 0 < |x| < 1.0 rounds to +/- 1.0 */ - return (x & 0x80000000) | 0x3f800000; - mask = 0x7fffff >> exp; - /* mantissa overflows into exponent - that's OK, - it can't overflow into the sign bit */ - return (x + mask) & ~mask; -} - -/* Round to floating integer, to nearest */ -static unsigned int rfin(unsigned int x) -{ - int exp, half; - - exp = ((x >> 23) & 0xff) - 127; - if (exp == 128 && (x & 0x7fffff) != 0) - return x | 0x400000; /* NaN -> make it a QNaN */ - if (exp >= 23) - return x; /* it's an integer already (or Inf) */ - if (exp < -1) - return x & 0x80000000; /* |x| < 0.5 -> +/-0 */ - if (exp == -1) - /* 0.5 <= |x| < 1.0 rounds to +/- 1.0 */ - return (x & 0x80000000) | 0x3f800000; - half = 0x400000 >> exp; - /* add 0.5 to the magnitude and chop off the fraction bits */ - return (x + half) & ~(0x7fffff >> exp); -} - -int emulate_altivec(struct pt_regs *regs) -{ - unsigned int instr, i; - unsigned int va, vb, vc, vd; - vector128 *vrs; - - if (get_user(instr, (unsigned int __user *) regs->nip)) - return -EFAULT; - if ((instr >> 26) != 4) - return -EINVAL; /* not an altivec instruction */ - vd = (instr >> 21) & 0x1f; - va = (instr >> 16) & 0x1f; - vb = (instr >> 11) & 0x1f; - vc = (instr >> 6) & 0x1f; - - vrs = current->thread.vr; - switch (instr & 0x3f) { - case 10: - switch (vc) { - case 0: /* vaddfp */ - vaddfp(&vrs[vd], &vrs[va], &vrs[vb]); - break; - case 1: /* vsubfp */ - vsubfp(&vrs[vd], &vrs[va], &vrs[vb]); - break; - case 4: /* vrefp */ - vrefp(&vrs[vd], &vrs[vb]); - break; - case 5: /* vrsqrtefp */ - vrsqrtefp(&vrs[vd], &vrs[vb]); - break; - case 6: /* vexptefp */ - for (i = 0; i < 4; ++i) - vrs[vd].u[i] = eexp2(vrs[vb].u[i]); - break; - case 7: /* vlogefp */ - for (i = 0; i < 4; ++i) - vrs[vd].u[i] = elog2(vrs[vb].u[i]); - break; - case 8: /* vrfin */ - for (i = 0; i < 4; ++i) - vrs[vd].u[i] = rfin(vrs[vb].u[i]); - break; - case 9: /* vrfiz */ - for (i = 0; i < 4; ++i) - vrs[vd].u[i] = rfiz(vrs[vb].u[i]); - break; - case 10: /* vrfip */ - for (i = 0; i < 4; ++i) { - u32 x = vrs[vb].u[i]; - x = (x & 0x80000000)? rfiz(x): rfii(x); - vrs[vd].u[i] = x; - } - break; - case 11: /* vrfim */ - for (i = 0; i < 4; ++i) { - u32 x = vrs[vb].u[i]; - x = (x & 0x80000000)? rfii(x): rfiz(x); - vrs[vd].u[i] = x; - } - break; - case 14: /* vctuxs */ - for (i = 0; i < 4; ++i) - vrs[vd].u[i] = ctuxs(vrs[vb].u[i], va, - ¤t->thread.vscr.u[3]); - break; - case 15: /* vctsxs */ - for (i = 0; i < 4; ++i) - vrs[vd].u[i] = ctsxs(vrs[vb].u[i], va, - ¤t->thread.vscr.u[3]); - break; - default: - return -EINVAL; - } - break; - case 46: /* vmaddfp */ - vmaddfp(&vrs[vd], &vrs[va], &vrs[vb], &vrs[vc]); - break; - case 47: /* vnmsubfp */ - vnmsubfp(&vrs[vd], &vrs[va], &vrs[vb], &vrs[vc]); - break; - default: - return -EINVAL; - } - - return 0; -} diff --git a/arch/ppc64/kernel/Makefile b/arch/ppc64/kernel/Makefile --- a/arch/ppc64/kernel/Makefile +++ b/arch/ppc64/kernel/Makefile @@ -83,3 +83,6 @@ ifeq ($(CONFIG_PPC_ISERIES),y) arch/ppc64/kernel/head.o: arch/ppc64/kernel/lparmap.s AFLAGS_head.o += -Iarch/ppc64/kernel endif + +# These are here while we do the architecture merge +vecemu-y += ../../powerpc/kernel/vecemu.o diff --git a/arch/ppc64/kernel/vecemu.c b/arch/ppc64/kernel/vecemu.c deleted file mode 100644 --- a/arch/ppc64/kernel/vecemu.c +++ /dev/null @@ -1,346 +0,0 @@ -/* - * Routines to emulate some Altivec/VMX instructions, specifically - * those that can trap when given denormalized operands in Java mode. - */ -#include -#include -#include -#include -#include -#include - -/* Functions in vector.S */ -extern void vaddfp(vector128 *dst, vector128 *a, vector128 *b); -extern void vsubfp(vector128 *dst, vector128 *a, vector128 *b); -extern void vmaddfp(vector128 *dst, vector128 *a, vector128 *b, vector128 *c); -extern void vnmsubfp(vector128 *dst, vector128 *a, vector128 *b, vector128 *c); -extern void vrefp(vector128 *dst, vector128 *src); -extern void vrsqrtefp(vector128 *dst, vector128 *src); -extern void vexptep(vector128 *dst, vector128 *src); - -static unsigned int exp2s[8] = { - 0x800000, - 0x8b95c2, - 0x9837f0, - 0xa5fed7, - 0xb504f3, - 0xc5672a, - 0xd744fd, - 0xeac0c7 -}; - -/* - * Computes an estimate of 2^x. The `s' argument is the 32-bit - * single-precision floating-point representation of x. - */ -static unsigned int eexp2(unsigned int s) -{ - int exp, pwr; - unsigned int mant, frac; - - /* extract exponent field from input */ - exp = ((s >> 23) & 0xff) - 127; - if (exp > 7) { - /* check for NaN input */ - if (exp == 128 && (s & 0x7fffff) != 0) - return s | 0x400000; /* return QNaN */ - /* 2^-big = 0, 2^+big = +Inf */ - return (s & 0x80000000)? 0: 0x7f800000; /* 0 or +Inf */ - } - if (exp < -23) - return 0x3f800000; /* 1.0 */ - - /* convert to fixed point integer in 9.23 representation */ - pwr = (s & 0x7fffff) | 0x800000; - if (exp > 0) - pwr <<= exp; - else - pwr >>= -exp; - if (s & 0x80000000) - pwr = -pwr; - - /* extract integer part, which becomes exponent part of result */ - exp = (pwr >> 23) + 126; - if (exp >= 254) - return 0x7f800000; - if (exp < -23) - return 0; - - /* table lookup on top 3 bits of fraction to get mantissa */ - mant = exp2s[(pwr >> 20) & 7]; - - /* linear interpolation using remaining 20 bits of fraction */ - asm("mulhwu %0,%1,%2" : "=r" (frac) - : "r" (pwr << 12), "r" (0x172b83ff)); - asm("mulhwu %0,%1,%2" : "=r" (frac) : "r" (frac), "r" (mant)); - mant += frac; - - if (exp >= 0) - return mant + (exp << 23); - - /* denormalized result */ - exp = -exp; - mant += 1 << (exp - 1); - return mant >> exp; -} - -/* - * Computes an estimate of log_2(x). The `s' argument is the 32-bit - * single-precision floating-point representation of x. - */ -static unsigned int elog2(unsigned int s) -{ - int exp, mant, lz, frac; - - exp = s & 0x7f800000; - mant = s & 0x7fffff; - if (exp == 0x7f800000) { /* Inf or NaN */ - if (mant != 0) - s |= 0x400000; /* turn NaN into QNaN */ - return s; - } - if ((exp | mant) == 0) /* +0 or -0 */ - return 0xff800000; /* return -Inf */ - - if (exp == 0) { - /* denormalized */ - asm("cntlzw %0,%1" : "=r" (lz) : "r" (mant)); - mant <<= lz - 8; - exp = (-118 - lz) << 23; - } else { - mant |= 0x800000; - exp -= 127 << 23; - } - - if (mant >= 0xb504f3) { /* 2^0.5 * 2^23 */ - exp |= 0x400000; /* 0.5 * 2^23 */ - asm("mulhwu %0,%1,%2" : "=r" (mant) - : "r" (mant), "r" (0xb504f334)); /* 2^-0.5 * 2^32 */ - } - if (mant >= 0x9837f0) { /* 2^0.25 * 2^23 */ - exp |= 0x200000; /* 0.25 * 2^23 */ - asm("mulhwu %0,%1,%2" : "=r" (mant) - : "r" (mant), "r" (0xd744fccb)); /* 2^-0.25 * 2^32 */ - } - if (mant >= 0x8b95c2) { /* 2^0.125 * 2^23 */ - exp |= 0x100000; /* 0.125 * 2^23 */ - asm("mulhwu %0,%1,%2" : "=r" (mant) - : "r" (mant), "r" (0xeac0c6e8)); /* 2^-0.125 * 2^32 */ - } - if (mant > 0x800000) { /* 1.0 * 2^23 */ - /* calculate (mant - 1) * 1.381097463 */ - /* 1.381097463 == 0.125 / (2^0.125 - 1) */ - asm("mulhwu %0,%1,%2" : "=r" (frac) - : "r" ((mant - 0x800000) << 1), "r" (0xb0c7cd3a)); - exp += frac; - } - s = exp & 0x80000000; - if (exp != 0) { - if (s) - exp = -exp; - asm("cntlzw %0,%1" : "=r" (lz) : "r" (exp)); - lz = 8 - lz; - if (lz > 0) - exp >>= lz; - else if (lz < 0) - exp <<= -lz; - s += ((lz + 126) << 23) + exp; - } - return s; -} - -#define VSCR_SAT 1 - -static int ctsxs(unsigned int x, int scale, unsigned int *vscrp) -{ - int exp, mant; - - exp = (x >> 23) & 0xff; - mant = x & 0x7fffff; - if (exp == 255 && mant != 0) - return 0; /* NaN -> 0 */ - exp = exp - 127 + scale; - if (exp < 0) - return 0; /* round towards zero */ - if (exp >= 31) { - /* saturate, unless the result would be -2^31 */ - if (x + (scale << 23) != 0xcf000000) - *vscrp |= VSCR_SAT; - return (x & 0x80000000)? 0x80000000: 0x7fffffff; - } - mant |= 0x800000; - mant = (mant << 7) >> (30 - exp); - return (x & 0x80000000)? -mant: mant; -} - -static unsigned int ctuxs(unsigned int x, int scale, unsigned int *vscrp) -{ - int exp; - unsigned int mant; - - exp = (x >> 23) & 0xff; - mant = x & 0x7fffff; - if (exp == 255 && mant != 0) - return 0; /* NaN -> 0 */ - exp = exp - 127 + scale; - if (exp < 0) - return 0; /* round towards zero */ - if (x & 0x80000000) { - /* negative => saturate to 0 */ - *vscrp |= VSCR_SAT; - return 0; - } - if (exp >= 32) { - /* saturate */ - *vscrp |= VSCR_SAT; - return 0xffffffff; - } - mant |= 0x800000; - mant = (mant << 8) >> (31 - exp); - return mant; -} - -/* Round to floating integer, towards 0 */ -static unsigned int rfiz(unsigned int x) -{ - int exp; - - exp = ((x >> 23) & 0xff) - 127; - if (exp == 128 && (x & 0x7fffff) != 0) - return x | 0x400000; /* NaN -> make it a QNaN */ - if (exp >= 23) - return x; /* it's an integer already (or Inf) */ - if (exp < 0) - return x & 0x80000000; /* |x| < 1.0 rounds to 0 */ - return x & ~(0x7fffff >> exp); -} - -/* Round to floating integer, towards +/- Inf */ -static unsigned int rfii(unsigned int x) -{ - int exp, mask; - - exp = ((x >> 23) & 0xff) - 127; - if (exp == 128 && (x & 0x7fffff) != 0) - return x | 0x400000; /* NaN -> make it a QNaN */ - if (exp >= 23) - return x; /* it's an integer already (or Inf) */ - if ((x & 0x7fffffff) == 0) - return x; /* +/-0 -> +/-0 */ - if (exp < 0) - /* 0 < |x| < 1.0 rounds to +/- 1.0 */ - return (x & 0x80000000) | 0x3f800000; - mask = 0x7fffff >> exp; - /* mantissa overflows into exponent - that's OK, - it can't overflow into the sign bit */ - return (x + mask) & ~mask; -} - -/* Round to floating integer, to nearest */ -static unsigned int rfin(unsigned int x) -{ - int exp, half; - - exp = ((x >> 23) & 0xff) - 127; - if (exp == 128 && (x & 0x7fffff) != 0) - return x | 0x400000; /* NaN -> make it a QNaN */ - if (exp >= 23) - return x; /* it's an integer already (or Inf) */ - if (exp < -1) - return x & 0x80000000; /* |x| < 0.5 -> +/-0 */ - if (exp == -1) - /* 0.5 <= |x| < 1.0 rounds to +/- 1.0 */ - return (x & 0x80000000) | 0x3f800000; - half = 0x400000 >> exp; - /* add 0.5 to the magnitude and chop off the fraction bits */ - return (x + half) & ~(0x7fffff >> exp); -} - -int -emulate_altivec(struct pt_regs *regs) -{ - unsigned int instr, i; - unsigned int va, vb, vc, vd; - vector128 *vrs; - - if (get_user(instr, (unsigned int __user *) regs->nip)) - return -EFAULT; - if ((instr >> 26) != 4) - return -EINVAL; /* not an altivec instruction */ - vd = (instr >> 21) & 0x1f; - va = (instr >> 16) & 0x1f; - vb = (instr >> 11) & 0x1f; - vc = (instr >> 6) & 0x1f; - - vrs = current->thread.vr; - switch (instr & 0x3f) { - case 10: - switch (vc) { - case 0: /* vaddfp */ - vaddfp(&vrs[vd], &vrs[va], &vrs[vb]); - break; - case 1: /* vsubfp */ - vsubfp(&vrs[vd], &vrs[va], &vrs[vb]); - break; - case 4: /* vrefp */ - vrefp(&vrs[vd], &vrs[vb]); - break; - case 5: /* vrsqrtefp */ - vrsqrtefp(&vrs[vd], &vrs[vb]); - break; - case 6: /* vexptefp */ - for (i = 0; i < 4; ++i) - vrs[vd].u[i] = eexp2(vrs[vb].u[i]); - break; - case 7: /* vlogefp */ - for (i = 0; i < 4; ++i) - vrs[vd].u[i] = elog2(vrs[vb].u[i]); - break; - case 8: /* vrfin */ - for (i = 0; i < 4; ++i) - vrs[vd].u[i] = rfin(vrs[vb].u[i]); - break; - case 9: /* vrfiz */ - for (i = 0; i < 4; ++i) - vrs[vd].u[i] = rfiz(vrs[vb].u[i]); - break; - case 10: /* vrfip */ - for (i = 0; i < 4; ++i) { - u32 x = vrs[vb].u[i]; - x = (x & 0x80000000)? rfiz(x): rfii(x); - vrs[vd].u[i] = x; - } - break; - case 11: /* vrfim */ - for (i = 0; i < 4; ++i) { - u32 x = vrs[vb].u[i]; - x = (x & 0x80000000)? rfii(x): rfiz(x); - vrs[vd].u[i] = x; - } - break; - case 14: /* vctuxs */ - for (i = 0; i < 4; ++i) - vrs[vd].u[i] = ctuxs(vrs[vb].u[i], va, - ¤t->thread.vscr.u[3]); - break; - case 15: /* vctsxs */ - for (i = 0; i < 4; ++i) - vrs[vd].u[i] = ctsxs(vrs[vb].u[i], va, - ¤t->thread.vscr.u[3]); - break; - default: - return -EINVAL; - } - break; - case 46: /* vmaddfp */ - vmaddfp(&vrs[vd], &vrs[va], &vrs[vb], &vrs[vc]); - break; - case 47: /* vnmsubfp */ - vnmsubfp(&vrs[vd], &vrs[va], &vrs[vb], &vrs[vc]); - break; - default: - return -EINVAL; - } - - return 0; -} From sfr at canb.auug.org.au Mon Sep 19 17:50:21 2005 From: sfr at canb.auug.org.au (Stephen Rothwell) Date: Mon, 19 Sep 2005 17:50:21 +1000 Subject: [PATCH] powerpc: Merge include/asm-ppc*/a.out.h into include/asm-powerpc Message-ID: <20050919175021.23456028.sfr@canb.auug.org.au> Signed-off-by: Stephen Rothwell --- include/asm-powerpc/a.out.h | 36 ++++++++++++++++++++++++++++++++++++ include/asm-ppc/a.out.h | 26 -------------------------- include/asm-ppc64/a.out.h | 39 --------------------------------------- 3 files changed, 36 insertions(+), 65 deletions(-) create mode 100644 include/asm-powerpc/a.out.h delete mode 100644 include/asm-ppc/a.out.h delete mode 100644 include/asm-ppc64/a.out.h -- Cheers, Stephen Rothwell sfr at canb.auug.org.au http://www.canb.auug.org.au/~sfr/ e4be8c960725725bccb547e84104e3fefca27f1 diff --git a/include/asm-powerpc/a.out.h b/include/asm-powerpc/a.out.h new file mode 100644 --- /dev/null +++ b/include/asm-powerpc/a.out.h @@ -0,0 +1,36 @@ +#ifndef _ASM_POWERPC_A_OUT_H +#define _ASM_POWERPC_A_OUT_H + +struct exec +{ + unsigned long a_info; /* Use macros N_MAGIC, etc for access */ + unsigned a_text; /* length of text, in bytes */ + unsigned a_data; /* length of data, in bytes */ + unsigned a_bss; /* length of uninitialized data area for file, in bytes */ + unsigned a_syms; /* length of symbol table data in file, in bytes */ + unsigned a_entry; /* start address */ + unsigned a_trsize; /* length of relocation info for text, in bytes */ + unsigned a_drsize; /* length of relocation info for data, in bytes */ +}; + +#define N_TRSIZE(a) ((a).a_trsize) +#define N_DRSIZE(a) ((a).a_drsize) +#define N_SYMSIZE(a) ((a).a_syms) + +#ifdef __KERNEL__ +#ifdef __powerpc64__ + +#define STACK_TOP_USER64 TASK_SIZE_USER64 +#define STACK_TOP_USER32 TASK_SIZE_USER32 + +#define STACK_TOP (test_thread_flag(TIF_32BIT) ? \ + STACK_TOP_USER32 : STACK_TOP_USER64) + +#else /* __powerpc64__ */ + +#define STACK_TOP TASK_SIZE + +#endif /* __powerpc64__ */ +#endif /* __KERNEL__ */ + +#endif /* _ASM_POWERPC_A_OUT_H */ diff --git a/include/asm-ppc/a.out.h b/include/asm-ppc/a.out.h deleted file mode 100644 --- a/include/asm-ppc/a.out.h +++ /dev/null @@ -1,26 +0,0 @@ -#ifndef __PPC_A_OUT_H__ -#define __PPC_A_OUT_H__ - -/* grabbed from the intel stuff */ -#define STACK_TOP TASK_SIZE - - -struct exec -{ - unsigned long a_info; /* Use macros N_MAGIC, etc for access */ - unsigned a_text; /* length of text, in bytes */ - unsigned a_data; /* length of data, in bytes */ - unsigned a_bss; /* length of uninitialized data area for file, in bytes */ - unsigned a_syms; /* length of symbol table data in file, in bytes */ - unsigned a_entry; /* start address */ - unsigned a_trsize; /* length of relocation info for text, in bytes */ - unsigned a_drsize; /* length of relocation info for data, in bytes */ -}; - - -#define N_TRSIZE(a) ((a).a_trsize) -#define N_DRSIZE(a) ((a).a_drsize) -#define N_SYMSIZE(a) ((a).a_syms) - - -#endif diff --git a/include/asm-ppc64/a.out.h b/include/asm-ppc64/a.out.h deleted file mode 100644 --- a/include/asm-ppc64/a.out.h +++ /dev/null @@ -1,39 +0,0 @@ -#ifndef __PPC64_A_OUT_H__ -#define __PPC64_A_OUT_H__ - -/* - * c 2001 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. - */ - -struct exec -{ - unsigned long a_info; /* Use macros N_MAGIC, etc for access */ - unsigned a_text; /* length of text, in bytes */ - unsigned a_data; /* length of data, in bytes */ - unsigned a_bss; /* length of uninitialized data area for file, in bytes */ - unsigned a_syms; /* length of symbol table data in file, in bytes */ - unsigned a_entry; /* start address */ - unsigned a_trsize; /* length of relocation info for text, in bytes */ - unsigned a_drsize; /* length of relocation info for data, in bytes */ -}; - -#define N_TRSIZE(a) ((a).a_trsize) -#define N_DRSIZE(a) ((a).a_drsize) -#define N_SYMSIZE(a) ((a).a_syms) - -#ifdef __KERNEL__ - -#define STACK_TOP_USER64 TASK_SIZE_USER64 -#define STACK_TOP_USER32 TASK_SIZE_USER32 - -#define STACK_TOP (test_thread_flag(TIF_32BIT) ? \ - STACK_TOP_USER32 : STACK_TOP_USER64) - -#endif /* __KERNEL__ */ - -#endif /* __PPC64_A_OUT_H__ */ From anton at samba.org Mon Sep 19 18:51:05 2005 From: anton at samba.org (Anton Blanchard) Date: Mon, 19 Sep 2005 18:51:05 +1000 Subject: [PATCH] ppc64: Fix issue with non zero boot cpu Message-ID: <20050919085104.GA25588@krispykreme> Hi, The new version of the flattened device tree passes the boot cpuid in the header instead of via a linux,boot-cpu property. We need to update the in kernel OF parsing code to do this, otherwise machines with a non zero boot cpuid fail to come up. Signed-off-by: Anton Blanchard --- Index: build/arch/ppc64/kernel/prom_init.c =================================================================== --- build.orig/arch/ppc64/kernel/prom_init.c 2005-09-15 17:33:46.000000000 +1000 +++ build/arch/ppc64/kernel/prom_init.c 2005-09-19 17:36:16.000000000 +1000 @@ -1711,6 +1711,7 @@ unsigned long offset = reloc_offset(); unsigned long mem_start, mem_end, room; struct boot_param_header *hdr; + struct prom_t *_prom = PTRRELOC(&prom); char *namep; u64 *rsvmap; @@ -1765,6 +1766,7 @@ RELOC(dt_struct_end) = PAGE_ALIGN(mem_start); /* Finish header */ + hdr->boot_cpuid_phys = _prom->cpu; hdr->magic = OF_DT_HEADER; hdr->totalsize = RELOC(dt_struct_end) - RELOC(dt_header_start); hdr->off_dt_struct = RELOC(dt_struct_start) - RELOC(dt_header_start); @@ -1854,7 +1856,6 @@ cpu_pkg = call_prom("instance-to-package", 1, 1, prom_cpu); - prom_setprop(cpu_pkg, "linux,boot-cpu", NULL, 0); prom_getprop(cpu_pkg, "reg", &getprop_rval, sizeof(getprop_rval)); _prom->cpu = getprop_rval; From hch at lst.de Mon Sep 19 19:51:30 2005 From: hch at lst.de (Christoph Hellwig) Date: Mon, 19 Sep 2005 11:51:30 +0200 Subject: G5 pci probing regression In-Reply-To: <17197.59822.43168.956195@cargo.ozlabs.ibm.com> References: <20050918221220.GA31975@lst.de> <17197.59822.43168.956195@cargo.ozlabs.ibm.com> Message-ID: <20050919095130.GA8549@lst.de> On Mon, Sep 19, 2005 at 08:26:54AM +1000, Paul Mackerras wrote: > Christoph Hellwig writes: > > > With current TOT the kernel crashes for me when loading the fusion > > driver. Investigation shows that: the crash happens on the first mmio > > access and was introduces between 2.6.13-git12 and 2.6.14-rc1. It looks > > like the OF-based PCI resource assignment changes, as a small patch like > > the one below makes the driver works just fine again for me: > > Hmmm. Could you send me the output of lspci -v and the contents of > /proc/pci, /proc/iomem and /proc/ioports with and without that change? sure. The -unpatched files are plain 2.6.14-rc1, the -patched ones are with my little hack. -------------- next part -------------- 80000000-9fffffff : /ht at 0,f2000000 80000000-800fffff : PCI Bus #01 80000000-8007ffff : 0001:01:07.0 80000000-8007ffff : 0.80000000:mac-io 8000002c-8000002f : 0.0000004c:fans 80000030-80000033 : 0.0000004c:fans 80000034-80000037 : 0.0000004c:fans 8000004c-8000004f : 0.0000004c:fans 80000050-8000008a : 0.00000050:gpio 80008000-800080ff : 0.00010000:i2s 80010000-80010fff : 0.00010000:i2s 80013000-80013000 : 0.00013000:ch-b 80013010-80013010 : 0.00013000:ch-b 80013020-80013020 : 0.00013020:ch-a 80013030-80013030 : 0.00013020:ch-a 80013040-80013040 : 0.00013000:ch-b 80013050-80013050 : 0.00013020:ch-a 80015000-80015fff : 0.00015000:timer 80016000-80017fff : 0.00016000:via-pmu 80018000-80018fff : 0.00018000:i2c 80040000-8007ffff : 0.00040000:mpic 80080000-80080fff : 0001:01:09.0 80080000-80080fff : ohci_hcd 80081000-80081fff : 0001:01:08.0 80081000-80081fff : ohci_hcd 80100000-801fffff : PCI Bus #02 80100000-801000ff : 0001:02:0b.2 80100000-801000ff : ehci_hcd 80101000-80101fff : 0001:02:0b.1 80101000-80101fff : ohci_hcd 80102000-80102fff : 0001:02:0b.0 80102000-80102fff : ohci_hcd 80200000-802fffff : PCI Bus #03 80200000-80200fff : 0001:03:0e.0 80200000-802007ff : ohci1394 80204000-80207fff : 0001:03:0d.0 80204000-80207fff : Kauai ATA 80300000-805fffff : PCI Bus #04 80300000-803fffff : 0001:04:0f.0 80400000-805fffff : 0001:04:0f.0 80400000-805fffff : sungem 80600000-806fffff : PCI Bus #05 80600000-80601fff : 0001:05:0c.0 80600000-80601fff : sata_svw 90000000-905fffff : PCI Bus #06 90000000-90003fff : 0001:06:03.0 90004000-90007fff : 0001:06:02.0 90010000-9001ffff : 0001:06:03.0 90020000-9002ffff : 0001:06:02.0 90200000-903fffff : 0001:06:03.0 90400000-905fffff : 0001:06:02.0 a0000000-afffffff : /pci at 0,f0000000 a0000000-a001ffff : 0000:f0:10.0 a1000000-a1ffffff : 0000:f0:10.0 a8000000-afffffff : 0000:f0:10.0 a8004000-a8183fff : offb b0000000-efffffff : /ht at 0,f2000000 f1000000-f1ffffff : /pci at 0,f0000000 -------------- next part -------------- 00000000-003fffff : /ht at 0,f2000000 00000400-000004ff : 0001:06:02.0 fffffffffd800000-fffffffffdffffff : /pci at 0,f0000000 -------------- next part -------------- PCI devices found: Bus 240, device 11, function 0: Class 0600: PCI device 106b:004b (rev 0). Master Capable. Latency=16. Bus 240, device 16, function 0: Class 0300: PCI device 10de:0321 (rev 161). IRQ 48. Master Capable. Latency=16. Min Gnt=5.Max Lat=1. Non-prefetchable 32 bit memory at 0xa1000000 [0xa1ffffff]. Prefetchable 32 bit memory at 0xa8000000 [0xafffffff]. Bus 0, device 1, function 0: Class 0604: PCI device 1022:7450 (rev 18). Master Capable. Latency=32. Bus 0, device 2, function 0: Class 0604: PCI device 1022:7450 (rev 18). Master Capable. Latency=32. Bus 0, device 3, function 0: Class 0604: PCI device 106b:0045 (rev 0). Bus 0, device 4, function 0: Class 0604: PCI device 106b:0046 (rev 0). Bus 0, device 5, function 0: Class 0604: PCI device 106b:0047 (rev 0). Bus 0, device 6, function 0: Class 0604: PCI device 106b:0048 (rev 0). Bus 0, device 7, function 0: Class 0604: PCI device 106b:0049 (rev 0). Bus 6, device 2, function 0: Class 0100: PCI device 1000:0054 (rev 0). IRQ 52. Master Capable. Latency=16. Min Gnt=64.Max Lat=10. I/O at 0x400 [0x4ff]. Non-prefetchable 64 bit memory at 0x90004000 [0x90007fff]. Non-prefetchable 64 bit memory at 0x90020000 [0x9002ffff]. Bus 6, device 3, function 0: Class 0100: PCI device 1000:0050 (rev 1). IRQ 53. Master Capable. Latency=16. Min Gnt=64.Max Lat=10. I/O at 0x0 [0xff]. Non-prefetchable 64 bit memory at 0x90000000 [0x90003fff]. Non-prefetchable 64 bit memory at 0x90010000 [0x9001ffff]. Bus 1, device 7, function 0: Class ff00: PCI device 106b:0041 (rev 96). Master Capable. Latency=16. Non-prefetchable 32 bit memory at 0x80000000 [0x8007ffff]. Bus 1, device 8, function 0: Class 0c03: PCI device 106b:0040 (rev 0). IRQ 27. Master Capable. Latency=16. Min Gnt=3.Max Lat=86. Non-prefetchable 32 bit memory at 0x80081000 [0x80081fff]. Bus 1, device 9, function 0: Class 0c03: PCI device 106b:0040 (rev 0). IRQ 28. Master Capable. Latency=16. Min Gnt=3.Max Lat=86. Non-prefetchable 32 bit memory at 0x80080000 [0x80080fff]. Bus 2, device 11, function 0: Class 0c03: PCI device 1033:0035 (rev 67). IRQ 63. Master Capable. Latency=16. Min Gnt=1.Max Lat=42. Non-prefetchable 32 bit memory at 0x80102000 [0x80102fff]. Bus 2, device 11, function 1: Class 0c03: PCI device 1033:0035 (rev 67). IRQ 63. Master Capable. Latency=16. Min Gnt=1.Max Lat=42. Non-prefetchable 32 bit memory at 0x80101000 [0x80101fff]. Bus 2, device 11, function 2: Class 0c03: PCI device 1033:00e0 (rev 4). IRQ 63. Master Capable. Latency=16. Min Gnt=16.Max Lat=34. Non-prefetchable 32 bit memory at 0x80100000 [0x801000ff]. Bus 3, device 13, function 0: Class ff00: PCI device 106b:0043 (rev 0). IRQ 39. Master Capable. Latency=32. Non-prefetchable 32 bit memory at 0x80204000 [0x80207fff]. Bus 3, device 14, function 0: Class 0c00: PCI device 106b:0042 (rev 0). IRQ 40. Master Capable. Latency=248. Min Gnt=12.Max Lat=24. Non-prefetchable 32 bit memory at 0x80200000 [0x80200fff]. Bus 4, device 15, function 0: Class 0200: PCI device 106b:004c (rev 0). IRQ 41. Master Capable. Latency=16. Min Gnt=64.Max Lat=64. Non-prefetchable 32 bit memory at 0x80400000 [0x805fffff]. Bus 5, device 12, function 0: Class 0101: PCI device 1166:0240 (rev 0). Master Capable. Latency=16. Non-prefetchable 32 bit memory at 0x80600000 [0x80601fff]. -------------- next part -------------- 80000000-9fffffff : /ht at 0,f2000000 80000000-800fffff : PCI Bus 0001:01 80000000-8007ffff : 0001:01:07.0 80000000-8007ffff : 0.80000000:mac-io 8000002c-8000002f : 0.0000004c:fans 80000030-80000033 : 0.0000004c:fans 80000034-80000037 : 0.0000004c:fans 8000004c-8000004f : 0.0000004c:fans 80000050-8000008a : 0.00000050:gpio 80008000-800080ff : 0.00010000:i2s 80010000-80010fff : 0.00010000:i2s 80013000-80013000 : 0.00013000:ch-b 80013010-80013010 : 0.00013000:ch-b 80013020-80013020 : 0.00013020:ch-a 80013030-80013030 : 0.00013020:ch-a 80013040-80013040 : 0.00013000:ch-b 80013050-80013050 : 0.00013020:ch-a 80015000-80015fff : 0.00015000:timer 80016000-80017fff : 0.00016000:via-pmu 80018000-80018fff : 0.00018000:i2c 80040000-8007ffff : 0.00040000:mpic 80080000-80080fff : 0001:01:09.0 80080000-80080fff : ohci_hcd 80081000-80081fff : 0001:01:08.0 80081000-80081fff : ohci_hcd 80100000-801fffff : PCI Bus 0001:02 80100000-801000ff : 0001:02:0b.2 80100000-801000ff : ehci_hcd 80101000-80101fff : 0001:02:0b.1 80101000-80101fff : ohci_hcd 80102000-80102fff : 0001:02:0b.0 80102000-80102fff : ohci_hcd 80200000-802fffff : PCI Bus 0001:03 80200000-80200fff : 0001:03:0e.0 80200000-802007ff : ohci1394 80204000-80207fff : 0001:03:0d.0 80204000-80207fff : Kauai ATA 80300000-805fffff : PCI Bus 0001:04 80300000-803fffff : 0001:04:0f.0 80400000-805fffff : 0001:04:0f.0 80400000-805fffff : sungem 80600000-806fffff : PCI Bus 0001:05 80600000-80601fff : 0001:05:0c.0 80600000-80601fff : sata_svw 90000000-905fffff : PCI Bus 0001:06 90000000-90003fff : 0001:06:03.0 90004000-90007fff : 0001:06:02.0 90010000-9001ffff : 0001:06:03.0 90020000-9002ffff : 0001:06:02.0 90200000-903fffff : 0001:06:03.0 90400000-905fffff : 0001:06:02.0 a0000000-afffffff : /pci at 0,f0000000 a0000000-a001ffff : 0000:f0:10.0 a1000000-a1ffffff : 0000:f0:10.0 a8000000-afffffff : 0000:f0:10.0 a8004000-a8183fff : offb b0000000-efffffff : /ht at 0,f2000000 f1000000-f1ffffff : /pci at 0,f0000000 -------------- next part -------------- 00000000-003fffff : /ht at 0,f2000000 00000400-000004ff : 0001:06:02.0 fffffffffd800000-fffffffffdffffff : /pci at 0,f0000000 -------------- next part -------------- PCI devices found: Bus 240, device 11, function 0: Class 0600: PCI device 106b:004b (rev 0). Master Capable. Latency=16. Bus 240, device 16, function 0: Class 0300: PCI device 10de:0321 (rev 161). IRQ 48. Master Capable. Latency=16. Min Gnt=5.Max Lat=1. Non-prefetchable 32 bit memory at 0xa1000000 [0xa1ffffff]. Prefetchable 32 bit memory at 0xa8000000 [0xafffffff]. Bus 0, device 1, function 0: Class 0604: PCI device 1022:7450 (rev 18). Master Capable. Latency=32. Bus 0, device 2, function 0: Class 0604: PCI device 1022:7450 (rev 18). Master Capable. Latency=32. Bus 0, device 3, function 0: Class 0604: PCI device 106b:0045 (rev 0). Bus 0, device 4, function 0: Class 0604: PCI device 106b:0046 (rev 0). Bus 0, device 5, function 0: Class 0604: PCI device 106b:0047 (rev 0). Bus 0, device 6, function 0: Class 0604: PCI device 106b:0048 (rev 0). Bus 0, device 7, function 0: Class 0604: PCI device 106b:0049 (rev 0). Bus 6, device 2, function 0: Class 0100: PCI device 1000:0054 (rev 0). IRQ 52. Master Capable. Latency=16. Min Gnt=64.Max Lat=10. Non-prefetchable 32 bit memory at 0x400 [0x4ff]. Non-prefetchable 32 bit memory at 0x90004000 [0x90007fff]. Non-prefetchable 32 bit memory at 0x90020000 [0x9002ffff]. Bus 6, device 3, function 0: Class 0100: PCI device 1000:0050 (rev 1). IRQ 53. Master Capable. Latency=16. Min Gnt=64.Max Lat=10. Non-prefetchable 32 bit memory at 0x0 [0xff]. Non-prefetchable 32 bit memory at 0x90000000 [0x90003fff]. Non-prefetchable 32 bit memory at 0x90010000 [0x9001ffff]. Bus 1, device 7, function 0: Class ff00: PCI device 106b:0041 (rev 96). IRQ -1. Master Capable. Latency=16. Non-prefetchable 32 bit memory at 0x80000000 [0x8007ffff]. Bus 1, device 8, function 0: Class 0c03: PCI device 106b:0040 (rev 0). IRQ 27. Master Capable. Latency=16. Min Gnt=3.Max Lat=86. Non-prefetchable 32 bit memory at 0x80081000 [0x80081fff]. Bus 1, device 9, function 0: Class 0c03: PCI device 106b:0040 (rev 0). IRQ 28. Master Capable. Latency=16. Min Gnt=3.Max Lat=86. Non-prefetchable 32 bit memory at 0x80080000 [0x80080fff]. Bus 2, device 11, function 0: Class 0c03: PCI device 1033:0035 (rev 67). IRQ 63. Master Capable. Latency=16. Min Gnt=1.Max Lat=42. Non-prefetchable 32 bit memory at 0x80102000 [0x80102fff]. Bus 2, device 11, function 1: Class 0c03: PCI device 1033:0035 (rev 67). IRQ 63. Master Capable. Latency=16. Min Gnt=1.Max Lat=42. Non-prefetchable 32 bit memory at 0x80101000 [0x80101fff]. Bus 2, device 11, function 2: Class 0c03: PCI device 1033:00e0 (rev 4). IRQ 63. Master Capable. Latency=16. Min Gnt=16.Max Lat=34. Non-prefetchable 32 bit memory at 0x80100000 [0x801000ff]. Bus 3, device 13, function 0: Class ff00: PCI device 106b:0043 (rev 0). IRQ 39. Master Capable. Latency=32. Non-prefetchable 32 bit memory at 0x80204000 [0x80207fff]. Bus 3, device 14, function 0: Class 0c00: PCI device 106b:0042 (rev 0). IRQ 40. Master Capable. Latency=248. Min Gnt=12.Max Lat=24. Non-prefetchable 32 bit memory at 0x80200000 [0x80200fff]. Bus 4, device 15, function 0: Class 0200: PCI device 106b:004c (rev 0). IRQ 41. Master Capable. Latency=16. Min Gnt=64.Max Lat=64. Non-prefetchable 32 bit memory at 0x80400000 [0x805fffff]. Bus 5, device 12, function 0: Class 0101: PCI device 1166:0240 (rev 0). Master Capable. Latency=16. Non-prefetchable 32 bit memory at 0x80600000 [0x80601fff]. From sfr at canb.auug.org.au Mon Sep 19 23:10:51 2005 From: sfr at canb.auug.org.au (Stephen Rothwell) Date: Mon, 19 Sep 2005 23:10:51 +1000 Subject: [PATCH 0/6] powerpc: merge arch/ppc*/oprofile directories Message-ID: <20050919231051.28fcdf30.sfr@canb.auug.org.au> This series of patches merge the arch/ppc*/oprofile directories into arch/powerpc. arch/powerpc/oprofile/Kconfig | 23 ++ arch/powerpc/oprofile/Makefile | 11 + arch/powerpc/oprofile/common.c | 227 +++++++++++++++++++-- arch/powerpc/oprofile/op_model_fsl_booke.c | 183 +++++++++++++++++ arch/powerpc/oprofile/op_model_power4.c | 309 ++++++++++++++++++++++++++++ arch/powerpc/oprofile/op_model_rs64.c | 218 ++++++++++++++++++++ arch/ppc/Kconfig | 2 arch/ppc/Makefile | 2 arch/ppc/kernel/perfmon.c | 10 arch/ppc/oprofile/Kconfig | 23 -- arch/ppc/oprofile/Makefile | 16 - arch/ppc/oprofile/common.c | 165 --------------- arch/ppc/oprofile/op_impl.h | 47 ---- arch/ppc/oprofile/op_model_fsl_booke.c | 188 ----------------- arch/ppc64/Kconfig | 2 arch/ppc64/Makefile | 2 arch/ppc64/oprofile/Kconfig | 23 -- arch/ppc64/oprofile/Makefile | 11 - arch/ppc64/oprofile/common.c | 147 ------------- arch/ppc64/oprofile/op_model_power4.c | 311 ----------------------------- arch/ppc64/oprofile/op_model_rs64.c | 220 -------------------- include/asm-powerpc/oprofile_impl.h | 123 +++++++++++ include/asm-ppc/perfmon.h | 6 include/asm-ppc64/cputable.h | 4 include/asm-ppc64/oprofile_impl.h | 121 ----------- 25 files changed, 1108 insertions(+), 1286 deletions(-) -- Cheers, Stephen Rothwell sfr at canb.auug.org.au http://www.canb.auug.org.au/~sfr/ From sfr at canb.auug.org.au Mon Sep 19 23:13:24 2005 From: sfr at canb.auug.org.au (Stephen Rothwell) Date: Mon, 19 Sep 2005 23:13:24 +1000 Subject: [PATCH 1/6] powerpc: Move arch/ppc*/oprofile/Kconfig to arch/powerpc In-Reply-To: <20050919231051.28fcdf30.sfr@canb.auug.org.au> References: <20050919231051.28fcdf30.sfr@canb.auug.org.au> Message-ID: <20050919231324.426e3dae.sfr@canb.auug.org.au> These files are identical. Signed-off-by: Stephen Rothwell --- arch/powerpc/oprofile/Kconfig | 23 +++++++++++++++++++++++ arch/ppc/Kconfig | 2 +- arch/ppc/oprofile/Kconfig | 23 ----------------------- arch/ppc64/Kconfig | 2 +- arch/ppc64/oprofile/Kconfig | 23 ----------------------- 5 files changed, 25 insertions(+), 48 deletions(-) create mode 100644 arch/powerpc/oprofile/Kconfig delete mode 100644 arch/ppc/oprofile/Kconfig delete mode 100644 arch/ppc64/oprofile/Kconfig -- Cheers, Stephen Rothwell sfr at canb.auug.org.au http://www.canb.auug.org.au/~sfr/ 51b2e663af2bae454a5e4737dfb0b7e0c4898b2f diff --git a/arch/powerpc/oprofile/Kconfig b/arch/powerpc/oprofile/Kconfig new file mode 100644 --- /dev/null +++ b/arch/powerpc/oprofile/Kconfig @@ -0,0 +1,23 @@ + +menu "Profiling support" + depends on EXPERIMENTAL + +config PROFILING + bool "Profiling support (EXPERIMENTAL)" + help + Say Y here to enable the extended profiling support mechanisms used + by profilers such as OProfile. + + +config OPROFILE + tristate "OProfile system profiling (EXPERIMENTAL)" + depends on PROFILING + help + OProfile is a profiling system capable of profiling the + whole system, include the kernel, kernel modules, libraries, + and applications. + + If unsure, say N. + +endmenu + diff --git a/arch/ppc/Kconfig b/arch/ppc/Kconfig --- a/arch/ppc/Kconfig +++ b/arch/ppc/Kconfig @@ -1370,7 +1370,7 @@ endmenu source "lib/Kconfig" -source "arch/ppc/oprofile/Kconfig" +source "arch/powerpc/oprofile/Kconfig" source "arch/ppc/Kconfig.debug" diff --git a/arch/ppc/oprofile/Kconfig b/arch/ppc/oprofile/Kconfig deleted file mode 100644 --- a/arch/ppc/oprofile/Kconfig +++ /dev/null @@ -1,23 +0,0 @@ - -menu "Profiling support" - depends on EXPERIMENTAL - -config PROFILING - bool "Profiling support (EXPERIMENTAL)" - help - Say Y here to enable the extended profiling support mechanisms used - by profilers such as OProfile. - - -config OPROFILE - tristate "OProfile system profiling (EXPERIMENTAL)" - depends on PROFILING - help - OProfile is a profiling system capable of profiling the - whole system, include the kernel, kernel modules, libraries, - and applications. - - If unsure, say N. - -endmenu - diff --git a/arch/ppc64/Kconfig b/arch/ppc64/Kconfig --- a/arch/ppc64/Kconfig +++ b/arch/ppc64/Kconfig @@ -461,7 +461,7 @@ config VIOPATH depends on VIOCONS || VIODASD || VIOCD || VIOTAPE || VETH default y -source "arch/ppc64/oprofile/Kconfig" +source "arch/powerpc/oprofile/Kconfig" source "arch/ppc64/Kconfig.debug" diff --git a/arch/ppc64/oprofile/Kconfig b/arch/ppc64/oprofile/Kconfig deleted file mode 100644 --- a/arch/ppc64/oprofile/Kconfig +++ /dev/null @@ -1,23 +0,0 @@ - -menu "Profiling support" - depends on EXPERIMENTAL - -config PROFILING - bool "Profiling support (EXPERIMENTAL)" - help - Say Y here to enable the extended profiling support mechanisms used - by profilers such as OProfile. - - -config OPROFILE - tristate "OProfile system profiling (EXPERIMENTAL)" - depends on PROFILING - help - OProfile is a profiling system capable of profiling the - whole system, include the kernel, kernel modules, libraries, - and applications. - - If unsure, say N. - -endmenu - From sfr at canb.auug.org.au Mon Sep 19 23:15:51 2005 From: sfr at canb.auug.org.au (Stephen Rothwell) Date: Mon, 19 Sep 2005 23:15:51 +1000 Subject: [PATCH 2/6] Merge arch/ppc*/oprofile/Makefile into arch/powerpc/oprofile In-Reply-To: <20050919231051.28fcdf30.sfr@canb.auug.org.au> References: <20050919231051.28fcdf30.sfr@canb.auug.org.au> Message-ID: <20050919231551.2e13b6d8.sfr@canb.auug.org.au> Signed-off-by: Stephen Rothwell --- arch/powerpc/oprofile/Makefile | 11 +++++++++++ arch/ppc/oprofile/Makefile | 15 +-------------- arch/ppc64/oprofile/Makefile | 10 +--------- 3 files changed, 13 insertions(+), 23 deletions(-) create mode 100644 arch/powerpc/oprofile/Makefile -- Cheers, Stephen Rothwell sfr at canb.auug.org.au http://www.canb.auug.org.au/~sfr/ 03447d2b4ddb0a51f7316c32c280dbc497ce8d83 diff --git a/arch/powerpc/oprofile/Makefile b/arch/powerpc/oprofile/Makefile new file mode 100644 --- /dev/null +++ b/arch/powerpc/oprofile/Makefile @@ -0,0 +1,11 @@ +obj-$(CONFIG_OPROFILE) += oprofile.o + +DRIVER_OBJS := $(addprefix ../../../drivers/oprofile/, \ + oprof.o cpu_buffer.o buffer_sync.o \ + event_buffer.o oprofile_files.o \ + oprofilefs.o oprofile_stats.o \ + timer_int.o ) + +oprofile-y := $(DRIVER_OBJS) common.o +oprofile-$(CONFIG_PPC64) += op_model_rs64.o op_model_power4.o +oprofile-$(CONFIG_FSL_BOOKE) += op_model_fsl_booke.o diff --git a/arch/ppc/oprofile/Makefile b/arch/ppc/oprofile/Makefile --- a/arch/ppc/oprofile/Makefile +++ b/arch/ppc/oprofile/Makefile @@ -1,14 +1 @@ -obj-$(CONFIG_OPROFILE) += oprofile.o - -DRIVER_OBJS := $(addprefix ../../../drivers/oprofile/, \ - oprof.o cpu_buffer.o buffer_sync.o \ - event_buffer.o oprofile_files.o \ - oprofilefs.o oprofile_stats.o \ - timer_int.o ) - -oprofile-y := $(DRIVER_OBJS) common.o - -ifeq ($(CONFIG_FSL_BOOKE),y) - oprofile-y += op_model_fsl_booke.o -endif - +include arch/powerpc/oprofile/Makefile diff --git a/arch/ppc64/oprofile/Makefile b/arch/ppc64/oprofile/Makefile --- a/arch/ppc64/oprofile/Makefile +++ b/arch/ppc64/oprofile/Makefile @@ -1,9 +1 @@ -obj-$(CONFIG_OPROFILE) += oprofile.o - -DRIVER_OBJS := $(addprefix ../../../drivers/oprofile/, \ - oprof.o cpu_buffer.o buffer_sync.o \ - event_buffer.o oprofile_files.o \ - oprofilefs.o oprofile_stats.o \ - timer_int.o ) - -oprofile-y := $(DRIVER_OBJS) common.o op_model_rs64.o op_model_power4.o +include arch/powerpc/oprofile/Makefile From sfr at canb.auug.org.au Mon Sep 19 23:18:31 2005 From: sfr at canb.auug.org.au (Stephen Rothwell) Date: Mon, 19 Sep 2005 23:18:31 +1000 Subject: [PATCH 3/6] powerpc: rename op_ppc{32, 64}_model to op_powerpc_model In-Reply-To: <20050919231051.28fcdf30.sfr@canb.auug.org.au> References: <20050919231051.28fcdf30.sfr@canb.auug.org.au> Message-ID: <20050919231831.6ffa7530.sfr@canb.auug.org.au> Signed-off-by: Stephen Rothwell --- arch/ppc/oprofile/common.c | 2 +- arch/ppc/oprofile/op_impl.h | 2 +- arch/ppc/oprofile/op_model_fsl_booke.c | 2 +- arch/ppc64/oprofile/common.c | 2 +- arch/ppc64/oprofile/op_model_power4.c | 2 +- arch/ppc64/oprofile/op_model_rs64.c | 2 +- include/asm-ppc/perfmon.h | 2 +- include/asm-ppc64/cputable.h | 4 ++-- include/asm-ppc64/oprofile_impl.h | 6 +++--- 9 files changed, 12 insertions(+), 12 deletions(-) -- Cheers, Stephen Rothwell sfr at canb.auug.org.au http://www.canb.auug.org.au/~sfr/ 2be7f59a0dbd2d2b0eb48384c64977980cca061e diff --git a/arch/ppc/oprofile/common.c b/arch/ppc/oprofile/common.c --- a/arch/ppc/oprofile/common.c +++ b/arch/ppc/oprofile/common.c @@ -25,7 +25,7 @@ #include "op_impl.h" -static struct op_ppc32_model *model; +static struct op_powerpc_model *model; static struct op_counter_config ctr[OP_MAX_COUNTER]; static struct op_system_config sys; diff --git a/arch/ppc/oprofile/op_impl.h b/arch/ppc/oprofile/op_impl.h --- a/arch/ppc/oprofile/op_impl.h +++ b/arch/ppc/oprofile/op_impl.h @@ -31,7 +31,7 @@ struct op_system_config { }; /* Per-arch configuration */ -struct op_ppc32_model { +struct op_powerpc_model { void (*reg_setup) (struct op_counter_config *, struct op_system_config *, int num_counters); diff --git a/arch/ppc/oprofile/op_model_fsl_booke.c b/arch/ppc/oprofile/op_model_fsl_booke.c --- a/arch/ppc/oprofile/op_model_fsl_booke.c +++ b/arch/ppc/oprofile/op_model_fsl_booke.c @@ -176,7 +176,7 @@ static void fsl_booke_handle_interrupt(s pmc_start_ctrs(1); } -struct op_ppc32_model op_model_fsl_booke = { +struct op_powerpc_model op_model_fsl_booke = { .reg_setup = fsl_booke_reg_setup, .start = fsl_booke_start, .stop = fsl_booke_stop, diff --git a/arch/ppc64/oprofile/common.c b/arch/ppc64/oprofile/common.c --- a/arch/ppc64/oprofile/common.c +++ b/arch/ppc64/oprofile/common.c @@ -19,7 +19,7 @@ #include #include -static struct op_ppc64_model *model; +static struct op_powerpc_model *model; static struct op_counter_config ctr[OP_MAX_COUNTER]; static struct op_system_config sys; diff --git a/arch/ppc64/oprofile/op_model_power4.c b/arch/ppc64/oprofile/op_model_power4.c --- a/arch/ppc64/oprofile/op_model_power4.c +++ b/arch/ppc64/oprofile/op_model_power4.c @@ -300,7 +300,7 @@ static void power4_handle_interrupt(stru mtspr(SPRN_MMCR0, mmcr0); } -struct op_ppc64_model op_model_power4 = { +struct op_powerpc_model op_model_power4 = { .reg_setup = power4_reg_setup, .cpu_setup = power4_cpu_setup, .start = power4_start, diff --git a/arch/ppc64/oprofile/op_model_rs64.c b/arch/ppc64/oprofile/op_model_rs64.c --- a/arch/ppc64/oprofile/op_model_rs64.c +++ b/arch/ppc64/oprofile/op_model_rs64.c @@ -209,7 +209,7 @@ static void rs64_handle_interrupt(struct mtspr(SPRN_MMCR0, mmcr0); } -struct op_ppc64_model op_model_rs64 = { +struct op_powerpc_model op_model_rs64 = { .reg_setup = rs64_reg_setup, .cpu_setup = rs64_cpu_setup, .start = rs64_start, diff --git a/include/asm-ppc/perfmon.h b/include/asm-ppc/perfmon.h --- a/include/asm-ppc/perfmon.h +++ b/include/asm-ppc/perfmon.h @@ -16,7 +16,7 @@ void pmc_start_ctrs(int enable); void pmc_stop_ctrs(void); void dump_pmcs(void); -extern struct op_ppc32_model op_model_fsl_booke; +extern struct op_powerpc_model op_model_fsl_booke; #endif #endif /* __PERFMON_H */ diff --git a/include/asm-ppc64/cputable.h b/include/asm-ppc64/cputable.h --- a/include/asm-ppc64/cputable.h +++ b/include/asm-ppc64/cputable.h @@ -36,7 +36,7 @@ * via the mkdefs mechanism. */ struct cpu_spec; -struct op_ppc64_model; +struct op_powerpc_model; typedef void (*cpu_setup_t)(unsigned long offset, struct cpu_spec* spec); @@ -65,7 +65,7 @@ struct cpu_spec { char *oprofile_cpu_type; /* Processor specific oprofile operations */ - struct op_ppc64_model *oprofile_model; + struct op_powerpc_model *oprofile_model; }; extern struct cpu_spec cpu_specs[]; diff --git a/include/asm-ppc64/oprofile_impl.h b/include/asm-ppc64/oprofile_impl.h --- a/include/asm-ppc64/oprofile_impl.h +++ b/include/asm-ppc64/oprofile_impl.h @@ -37,7 +37,7 @@ struct op_system_config { }; /* Per-arch configuration */ -struct op_ppc64_model { +struct op_powerpc_model { void (*reg_setup) (struct op_counter_config *, struct op_system_config *, int num_counters); @@ -49,8 +49,8 @@ struct op_ppc64_model { int num_counters; }; -extern struct op_ppc64_model op_model_rs64; -extern struct op_ppc64_model op_model_power4; +extern struct op_powerpc_model op_model_rs64; +extern struct op_powerpc_model op_model_power4; static inline unsigned int ctr_read(unsigned int i) { From sfr at canb.auug.org.au Mon Sep 19 23:21:15 2005 From: sfr at canb.auug.org.au (Stephen Rothwell) Date: Mon, 19 Sep 2005 23:21:15 +1000 Subject: [PATCH 4/6] powerpc: merge oprofile headers In-Reply-To: <20050919231051.28fcdf30.sfr@canb.auug.org.au> References: <20050919231051.28fcdf30.sfr@canb.auug.org.au> Message-ID: <20050919232115.3347bcad.sfr@canb.auug.org.au> Merge include/asm-ppc64/oprofile_ipml.h and arch/ppc/oprofile/op_impl.h into include/asm-powerpc/oprofile_ipml.h Signed-off-by: Stephen Rothwell --- arch/ppc/oprofile/common.c | 3 - arch/ppc/oprofile/op_impl.h | 45 ------------ arch/ppc/oprofile/op_model_fsl_booke.c | 3 - include/asm-powerpc/oprofile_impl.h | 123 ++++++++++++++++++++++++++++++++ include/asm-ppc64/oprofile_impl.h | 111 ----------------------------- 5 files changed, 125 insertions(+), 160 deletions(-) delete mode 100644 arch/ppc/oprofile/op_impl.h create mode 100644 include/asm-powerpc/oprofile_impl.h delete mode 100644 include/asm-ppc64/oprofile_impl.h -- Cheers, Stephen Rothwell sfr at canb.auug.org.au http://www.canb.auug.org.au/~sfr/ 9f08e21e6ba1a97e62f77066ac8c915149908223 diff --git a/arch/ppc/oprofile/common.c b/arch/ppc/oprofile/common.c --- a/arch/ppc/oprofile/common.c +++ b/arch/ppc/oprofile/common.c @@ -22,8 +22,7 @@ #include #include #include - -#include "op_impl.h" +#include static struct op_powerpc_model *model; diff --git a/arch/ppc/oprofile/op_impl.h b/arch/ppc/oprofile/op_impl.h deleted file mode 100644 --- a/arch/ppc/oprofile/op_impl.h +++ /dev/null @@ -1,45 +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 enabled; - unsigned long event; - unsigned long count; - unsigned long kernel; - unsigned long user; - unsigned long unit_mask; -}; - -/* System-wide configuration as set via oprofilefs. */ -struct op_system_config { - unsigned long enable_kernel; - unsigned long enable_user; -}; - -/* Per-arch configuration */ -struct op_powerpc_model { - void (*reg_setup) (struct op_counter_config *, - struct op_system_config *, - int num_counters); - void (*start) (struct op_counter_config *); - void (*stop) (void); - void (*handle_interrupt) (struct pt_regs *, - struct op_counter_config *); - int num_counters; -}; - -#endif /* OP_IMPL_H */ diff --git a/arch/ppc/oprofile/op_model_fsl_booke.c b/arch/ppc/oprofile/op_model_fsl_booke.c --- a/arch/ppc/oprofile/op_model_fsl_booke.c +++ b/arch/ppc/oprofile/op_model_fsl_booke.c @@ -25,8 +25,7 @@ #include #include #include - -#include "op_impl.h" +#include static unsigned long reset_value[OP_MAX_COUNTER]; diff --git a/include/asm-powerpc/oprofile_impl.h b/include/asm-powerpc/oprofile_impl.h new file mode 100644 --- /dev/null +++ b/include/asm-powerpc/oprofile_impl.h @@ -0,0 +1,123 @@ +/* + * 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 _ASM_POWERPC_OPROFILE_IMPL_H +#define _ASM_POWERPC_OPROFILE_IMPL_H + +#define OP_MAX_COUNTER 8 + +/* Per-counter configuration as set via oprofilefs. */ +struct op_counter_config { +#ifdef __powerpc64__ + unsigned long valid; +#endif + unsigned long enabled; + unsigned long event; + unsigned long count; + unsigned long kernel; +#ifdef __powerpc64__ + /* We dont support per counter user/kernel selection */ +#endif + unsigned long user; + unsigned long unit_mask; +}; + +/* System-wide configuration as set via oprofilefs. */ +struct op_system_config { +#ifdef __powerpc64__ + unsigned long mmcr0; + unsigned long mmcr1; + unsigned long mmcra; +#endif + unsigned long enable_kernel; + unsigned long enable_user; +#ifdef __powerpc64__ + unsigned long backtrace_spinlocks; +#endif +}; + +/* Per-arch configuration */ +struct op_powerpc_model { + void (*reg_setup) (struct op_counter_config *, + struct op_system_config *, + int num_counters); +#ifdef __powerpc64__ + void (*cpu_setup) (void *); +#endif + void (*start) (struct op_counter_config *); + void (*stop) (void); + void (*handle_interrupt) (struct pt_regs *, + struct op_counter_config *); + int num_counters; +}; + +#ifdef __powerpc64__ +extern struct op_powerpc_model op_model_rs64; +extern struct op_powerpc_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 /* __powerpc64__ */ + +#endif /* _ASM_POWERPC_OPROFILE_IMPL_H */ diff --git a/include/asm-ppc64/oprofile_impl.h b/include/asm-ppc64/oprofile_impl.h deleted file mode 100644 --- a/include/asm-ppc64/oprofile_impl.h +++ /dev/null @@ -1,111 +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_powerpc_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_powerpc_model op_model_rs64; -extern struct op_powerpc_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 From sfr at canb.auug.org.au Mon Sep 19 23:24:08 2005 From: sfr at canb.auug.org.au (Stephen Rothwell) Date: Mon, 19 Sep 2005 23:24:08 +1000 Subject: [PATCH 5/6] powerpc: merge the rest of arch/ppc*/oprofile In-Reply-To: <20050919231051.28fcdf30.sfr@canb.auug.org.au> References: <20050919231051.28fcdf30.sfr@canb.auug.org.au> Message-ID: <20050919232408.776ff437.sfr@canb.auug.org.au> - merge common.c - move model specific files - remove stub Makefiles - clean up arch/ppc*/Makefile Signed-off-by: Stephen Rothwell --- arch/powerpc/oprofile/common.c | 214 +++++++++++++++++++ arch/powerpc/oprofile/op_model_fsl_booke.c | 183 +++++++++++++++++ arch/powerpc/oprofile/op_model_power4.c | 309 ++++++++++++++++++++++++++++ arch/powerpc/oprofile/op_model_rs64.c | 218 ++++++++++++++++++++ arch/ppc/Makefile | 2 arch/ppc/oprofile/Makefile | 1 arch/ppc/oprofile/common.c | 160 -------------- arch/ppc/oprofile/op_model_fsl_booke.c | 183 ----------------- arch/ppc64/Makefile | 2 arch/ppc64/oprofile/Makefile | 1 arch/ppc64/oprofile/common.c | 145 ------------- arch/ppc64/oprofile/op_model_power4.c | 309 ---------------------------- arch/ppc64/oprofile/op_model_rs64.c | 218 -------------------- 13 files changed, 926 insertions(+), 1019 deletions(-) create mode 100644 arch/powerpc/oprofile/common.c create mode 100644 arch/powerpc/oprofile/op_model_fsl_booke.c create mode 100644 arch/powerpc/oprofile/op_model_power4.c create mode 100644 arch/powerpc/oprofile/op_model_rs64.c delete mode 100644 arch/ppc/oprofile/Makefile delete mode 100644 arch/ppc/oprofile/common.c delete mode 100644 arch/ppc/oprofile/op_model_fsl_booke.c delete mode 100644 arch/ppc64/oprofile/Makefile delete mode 100644 arch/ppc64/oprofile/common.c delete mode 100644 arch/ppc64/oprofile/op_model_power4.c delete mode 100644 arch/ppc64/oprofile/op_model_rs64.c -- Cheers, Stephen Rothwell sfr at canb.auug.org.au http://www.canb.auug.org.au/~sfr/ 6dc3424cfdea7aedd29e9aad5eb93c84f922bdd1 diff --git a/arch/powerpc/oprofile/common.c b/arch/powerpc/oprofile/common.c new file mode 100644 --- /dev/null +++ b/arch/powerpc/oprofile/common.c @@ -0,0 +1,214 @@ +/* + * PPC 64 oprofile support: + * Copyright (C) 2004 Anton Blanchard , IBM + * PPC 32 oprofile support: (based on PPC 64 support) + * Copyright (C) Freescale Semiconductor, Inc 2004 + * Author: Andy Fleming + * + * 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. + */ + +#include +#ifndef __powerpc64__ +#include +#endif /* ! __powerpc64__ */ +#include +#include +#include +#include +#include +#ifdef __powerpc64__ +#include +#else /* __powerpc64__ */ +#include +#endif /* __powerpc64__ */ +#include +#include + +static struct op_powerpc_model *model; + +static struct op_counter_config ctr[OP_MAX_COUNTER]; +static struct op_system_config sys; + +#ifndef __powerpc64__ +static char *cpu_type; +#endif /* ! __powerpc64__ */ + +static void op_handle_interrupt(struct pt_regs *regs) +{ + model->handle_interrupt(regs, ctr); +} + +static int op_powerpc_setup(void) +{ +#ifdef __powerpc64__ + int err; + + /* Grab the hardware */ + err = reserve_pmc_hardware(op_handle_interrupt); + if (err) + return err; +#else /* __powerpc64__ */ + /* Install our interrupt handler into the existing hook. */ + if (request_perfmon_irq(&op_handle_interrupt)) + return -EBUSY; + mb(); +#endif /* __powerpc64__ */ + + /* Pre-compute the values to stuff in the hardware registers. */ + model->reg_setup(ctr, &sys, model->num_counters); + + /* Configure the registers on all cpus. */ +#ifdef __powerpc64__ + on_each_cpu(model->cpu_setup, NULL, 0, 1); +#else /* __powerpc64__ */ +#if 0 + /* FIXME: Make multi-cpu work */ + on_each_cpu(model->reg_setup, NULL, 0, 1); +#endif +#endif /* __powerpc64__ */ + + return 0; +} + +static void op_powerpc_shutdown(void) +{ +#ifdef __powerpc64__ + release_pmc_hardware(); +#else /* __powerpc64__ */ + mb(); + /* Remove our interrupt handler. We may be removing this module. */ + free_perfmon_irq(); +#endif /* __powerpc64__ */ +} + +static void op_powerpc_cpu_start(void *dummy) +{ + model->start(ctr); +} + +static int op_powerpc_start(void) +{ + on_each_cpu(op_powerpc_cpu_start, NULL, 0, 1); + return 0; +} + +static inline void op_powerpc_cpu_stop(void *dummy) +{ + model->stop(); +} + +static void op_powerpc_stop(void) +{ + on_each_cpu(op_powerpc_cpu_stop, NULL, 0, 1); +} + +static int op_powerpc_create_files(struct super_block *sb, struct dentry *root) +{ + int i; + +#ifdef __powerpc64__ + /* + * There is one mmcr0, mmcr1 and mmcra for setting the events for + * all of the counters. + */ + oprofilefs_create_ulong(sb, root, "mmcr0", &sys.mmcr0); + oprofilefs_create_ulong(sb, root, "mmcr1", &sys.mmcr1); + oprofilefs_create_ulong(sb, root, "mmcra", &sys.mmcra); +#endif /* __powerpc64__ */ + + for (i = 0; i < model->num_counters; ++i) { + struct dentry *dir; + char buf[3]; + + snprintf(buf, sizeof buf, "%d", i); + dir = oprofilefs_mkdir(sb, root, buf); + + oprofilefs_create_ulong(sb, dir, "enabled", &ctr[i].enabled); + oprofilefs_create_ulong(sb, dir, "event", &ctr[i].event); + oprofilefs_create_ulong(sb, dir, "count", &ctr[i].count); +#ifdef __powerpc64__ + /* + * We dont support per counter user/kernel selection, but + * we leave the entries because userspace expects them + */ +#endif /* __powerpc64__ */ + oprofilefs_create_ulong(sb, dir, "kernel", &ctr[i].kernel); + oprofilefs_create_ulong(sb, dir, "user", &ctr[i].user); + +#ifndef __powerpc64__ + /* FIXME: Not sure if this is used */ +#endif /* ! __powerpc64__ */ + oprofilefs_create_ulong(sb, dir, "unit_mask", &ctr[i].unit_mask); + } + + oprofilefs_create_ulong(sb, root, "enable_kernel", &sys.enable_kernel); + oprofilefs_create_ulong(sb, root, "enable_user", &sys.enable_user); +#ifdef __powerpc64__ + oprofilefs_create_ulong(sb, root, "backtrace_spinlocks", + &sys.backtrace_spinlocks); +#endif /* __powerpc64__ */ + + /* Default to tracing both kernel and user */ + sys.enable_kernel = 1; + sys.enable_user = 1; +#ifdef __powerpc64__ + /* Turn on backtracing through spinlocks by default */ + sys.backtrace_spinlocks = 1; +#endif /* __powerpc64__ */ + + return 0; +} + +int __init oprofile_arch_init(struct oprofile_operations *ops) +{ +#ifndef __powerpc64__ + int cpu_id = smp_processor_id(); + +#ifdef CONFIG_FSL_BOOKE + model = &op_model_fsl_booke; +#else + return -ENODEV; +#endif + + cpu_type = kmalloc(32, GFP_KERNEL); + if (NULL == cpu_type) + return -ENOMEM; + + sprintf(cpu_type, "ppc/%s", cur_cpu_spec[cpu_id]->cpu_name); + + model->num_counters = cur_cpu_spec[cpu_id]->num_pmcs; + + ops->cpu_type = cpu_type; +#else /* __powerpc64__ */ + if (!cur_cpu_spec->oprofile_model || !cur_cpu_spec->oprofile_cpu_type) + 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; +#endif /* __powerpc64__ */ + ops->create_files = op_powerpc_create_files; + ops->setup = op_powerpc_setup; + ops->shutdown = op_powerpc_shutdown; + ops->start = op_powerpc_start; + ops->stop = op_powerpc_stop; + + printk(KERN_INFO "oprofile: using %s performance monitoring.\n", + ops->cpu_type); + + return 0; +} + +void oprofile_arch_exit(void) +{ +#ifndef __powerpc64__ + kfree(cpu_type); + cpu_type = NULL; +#endif /* ! __powerpc64__ */ +} diff --git a/arch/powerpc/oprofile/op_model_fsl_booke.c b/arch/powerpc/oprofile/op_model_fsl_booke.c new file mode 100644 --- /dev/null +++ b/arch/powerpc/oprofile/op_model_fsl_booke.c @@ -0,0 +1,183 @@ +/* + * oprofile/op_model_e500.c + * + * Freescale Book-E oprofile support, based on ppc64 oprofile support + * Copyright (C) 2004 Anton Blanchard , IBM + * + * Copyright (c) 2004 Freescale Semiconductor, Inc + * + * Author: Andy Fleming + * Maintainer: Kumar Gala + * + * 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 +#include + +static unsigned long reset_value[OP_MAX_COUNTER]; + +static int num_counters; +static int oprofile_running; + +static inline unsigned int ctr_read(unsigned int i) +{ + switch(i) { + case 0: + return mfpmr(PMRN_PMC0); + case 1: + return mfpmr(PMRN_PMC1); + case 2: + return mfpmr(PMRN_PMC2); + case 3: + return mfpmr(PMRN_PMC3); + default: + return 0; + } +} + +static inline void ctr_write(unsigned int i, unsigned int val) +{ + switch(i) { + case 0: + mtpmr(PMRN_PMC0, val); + break; + case 1: + mtpmr(PMRN_PMC1, val); + break; + case 2: + mtpmr(PMRN_PMC2, val); + break; + case 3: + mtpmr(PMRN_PMC3, val); + break; + default: + break; + } +} + + +static void fsl_booke_reg_setup(struct op_counter_config *ctr, + struct op_system_config *sys, + int num_ctrs) +{ + int i; + + num_counters = num_ctrs; + + /* freeze all counters */ + pmc_stop_ctrs(); + + /* Our counters count up, and "count" refers to + * how much before the next interrupt, and we interrupt + * on overflow. So we calculate the starting value + * which will give us "count" until overflow. + * Then we set the events on the enabled counters */ + for (i = 0; i < num_counters; ++i) { + reset_value[i] = 0x80000000UL - ctr[i].count; + + init_pmc_stop(i); + + set_pmc_event(i, ctr[i].event); + + set_pmc_user_kernel(i, ctr[i].user, ctr[i].kernel); + } +} + +static void fsl_booke_start(struct op_counter_config *ctr) +{ + int i; + + mtmsr(mfmsr() | MSR_PMM); + + for (i = 0; i < num_counters; ++i) { + if (ctr[i].enabled) { + ctr_write(i, reset_value[i]); + /* Set Each enabled counterd to only + * count when the Mark bit is not set */ + set_pmc_marked(i, 1, 0); + pmc_start_ctr(i, 1); + } else { + ctr_write(i, 0); + + /* Set the ctr to be stopped */ + pmc_start_ctr(i, 0); + } + } + + /* Clear the freeze bit, and enable the interrupt. + * The counters won't actually start until the rfi clears + * the PMM bit */ + pmc_start_ctrs(1); + + oprofile_running = 1; + + pr_debug("start on cpu %d, pmgc0 %x\n", smp_processor_id(), + mfpmr(PMRN_PMGC0)); +} + +static void fsl_booke_stop(void) +{ + /* freeze counters */ + pmc_stop_ctrs(); + + oprofile_running = 0; + + pr_debug("stop on cpu %d, pmgc0 %x\n", smp_processor_id(), + mfpmr(PMRN_PMGC0)); + + mb(); +} + + +static void fsl_booke_handle_interrupt(struct pt_regs *regs, + struct op_counter_config *ctr) +{ + unsigned long pc; + int is_kernel; + int val; + int i; + + /* set the PMM bit (see comment below) */ + mtmsr(mfmsr() | MSR_PMM); + + pc = regs->nip; + is_kernel = (pc >= KERNELBASE); + + for (i = 0; i < num_counters; ++i) { + val = ctr_read(i); + if (val < 0) { + if (oprofile_running && ctr[i].enabled) { + oprofile_add_pc(pc, is_kernel, i); + ctr_write(i, reset_value[i]); + } else { + ctr_write(i, 0); + } + } + } + + /* The freeze bit was set by the interrupt. */ + /* Clear the freeze bit, and reenable the interrupt. + * The counters won't actually start until the rfi clears + * the PMM bit */ + pmc_start_ctrs(1); +} + +struct op_powerpc_model op_model_fsl_booke = { + .reg_setup = fsl_booke_reg_setup, + .start = fsl_booke_start, + .stop = fsl_booke_stop, + .handle_interrupt = fsl_booke_handle_interrupt, +}; diff --git a/arch/powerpc/oprofile/op_model_power4.c b/arch/powerpc/oprofile/op_model_power4.c new file mode 100644 --- /dev/null +++ b/arch/powerpc/oprofile/op_model_power4.c @@ -0,0 +1,309 @@ +/* + * Copyright (C) 2004 Anton Blanchard , IBM + * + * 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 + +#define dbg(args...) + +static unsigned long reset_value[OP_MAX_COUNTER]; + +static int oprofile_running; +static int mmcra_has_sihv; + +/* mmcr values are set in power4_reg_setup, used in power4_cpu_setup */ +static u32 mmcr0_val; +static u64 mmcr1_val; +static u32 mmcra_val; + +/* + * Since we do not have an NMI, backtracing through spinlocks is + * only a best guess. In light of this, allow it to be disabled at + * runtime. + */ +static int backtrace_spinlocks; + +static void power4_reg_setup(struct op_counter_config *ctr, + struct op_system_config *sys, + int num_ctrs) +{ + int i; + + /* + * SIHV / SIPR bits are only implemented on POWER4+ (GQ) and above. + * However we disable it on all POWER4 until we verify it works + * (I was seeing some strange behaviour last time I tried). + * + * It has been verified to work on POWER5 so we enable it there. + */ + if (cpu_has_feature(CPU_FTR_MMCRA_SIHV)) + mmcra_has_sihv = 1; + + /* + * The performance counter event settings are given in the mmcr0, + * mmcr1 and mmcra values passed from the user in the + * op_system_config structure (sys variable). + */ + mmcr0_val = sys->mmcr0; + mmcr1_val = sys->mmcr1; + mmcra_val = sys->mmcra; + + backtrace_spinlocks = sys->backtrace_spinlocks; + + for (i = 0; i < cur_cpu_spec->num_pmcs; ++i) + reset_value[i] = 0x80000000UL - ctr[i].count; + + /* setup user and kernel profiling */ + if (sys->enable_kernel) + mmcr0_val &= ~MMCR0_KERNEL_DISABLE; + else + mmcr0_val |= MMCR0_KERNEL_DISABLE; + + if (sys->enable_user) + mmcr0_val &= ~MMCR0_PROBLEM_DISABLE; + else + mmcr0_val |= MMCR0_PROBLEM_DISABLE; +} + +extern void ppc64_enable_pmcs(void); + +static void power4_cpu_setup(void *unused) +{ + unsigned int mmcr0 = mmcr0_val; + unsigned long mmcra = mmcra_val; + + ppc64_enable_pmcs(); + + /* set the freeze bit */ + mmcr0 |= MMCR0_FC; + mtspr(SPRN_MMCR0, mmcr0); + + mmcr0 |= MMCR0_FCM1|MMCR0_PMXE|MMCR0_FCECE; + mmcr0 |= MMCR0_PMC1CE|MMCR0_PMCjCE; + mtspr(SPRN_MMCR0, mmcr0); + + mtspr(SPRN_MMCR1, mmcr1_val); + + mmcra |= MMCRA_SAMPLE_ENABLE; + mtspr(SPRN_MMCRA, mmcra); + + dbg("setup on cpu %d, mmcr0 %lx\n", smp_processor_id(), + mfspr(SPRN_MMCR0)); + dbg("setup on cpu %d, mmcr1 %lx\n", smp_processor_id(), + mfspr(SPRN_MMCR1)); + dbg("setup on cpu %d, mmcra %lx\n", smp_processor_id(), + mfspr(SPRN_MMCRA)); +} + +static void power4_start(struct op_counter_config *ctr) +{ + int i; + unsigned int mmcr0; + + /* set the PMM bit (see comment below) */ + mtmsrd(mfmsr() | MSR_PMM); + + for (i = 0; i < cur_cpu_spec->num_pmcs; ++i) { + if (ctr[i].enabled) { + ctr_write(i, reset_value[i]); + } else { + ctr_write(i, 0); + } + } + + mmcr0 = mfspr(SPRN_MMCR0); + + /* + * We must clear the PMAO bit on some (GQ) chips. Just do it + * all the time + */ + mmcr0 &= ~MMCR0_PMAO; + + /* + * now clear the freeze bit, counting will not start until we + * rfid from this excetion, because only at that point will + * the PMM bit be cleared + */ + mmcr0 &= ~MMCR0_FC; + mtspr(SPRN_MMCR0, mmcr0); + + oprofile_running = 1; + + dbg("start on cpu %d, mmcr0 %x\n", smp_processor_id(), mmcr0); +} + +static void power4_stop(void) +{ + unsigned int mmcr0; + + /* freeze counters */ + mmcr0 = mfspr(SPRN_MMCR0); + mmcr0 |= MMCR0_FC; + mtspr(SPRN_MMCR0, mmcr0); + + oprofile_running = 0; + + dbg("stop on cpu %d, mmcr0 %x\n", smp_processor_id(), mmcr0); + + mb(); +} + +/* Fake functions used by canonicalize_pc */ +static void __attribute_used__ hypervisor_bucket(void) +{ +} + +static void __attribute_used__ rtas_bucket(void) +{ +} + +static void __attribute_used__ kernel_unknown_bucket(void) +{ +} + +static unsigned long check_spinlock_pc(struct pt_regs *regs, + unsigned long profile_pc) +{ + unsigned long pc = instruction_pointer(regs); + + /* + * If both the SIAR (sampled instruction) and the perfmon exception + * occurred in a spinlock region then we account the sample to the + * calling function. This isnt 100% correct, we really need soft + * IRQ disable so we always get the perfmon exception at the + * point at which the SIAR is set. + */ + if (backtrace_spinlocks && in_lock_functions(pc) && + in_lock_functions(profile_pc)) + return regs->link; + else + return profile_pc; +} + +/* + * On GQ and newer the MMCRA stores the HV and PR bits at the time + * the SIAR was sampled. We use that to work out if the SIAR was sampled in + * the hypervisor, our exception vectors or RTAS. + */ +static unsigned long get_pc(struct pt_regs *regs) +{ + unsigned long pc = mfspr(SPRN_SIAR); + unsigned long mmcra; + + /* Cant do much about it */ + if (!mmcra_has_sihv) + return check_spinlock_pc(regs, pc); + + mmcra = mfspr(SPRN_MMCRA); + + /* Were we in the hypervisor? */ + if ((systemcfg->platform == PLATFORM_PSERIES_LPAR) && + (mmcra & MMCRA_SIHV)) + /* function descriptor madness */ + return *((unsigned long *)hypervisor_bucket); + + /* We were in userspace, nothing to do */ + if (mmcra & MMCRA_SIPR) + return pc; + +#ifdef CONFIG_PPC_RTAS + /* Were we in RTAS? */ + if (pc >= rtas.base && pc < (rtas.base + rtas.size)) + /* function descriptor madness */ + return *((unsigned long *)rtas_bucket); +#endif + + /* Were we in our exception vectors or SLB real mode miss handler? */ + if (pc < 0x1000000UL) + return (unsigned long)__va(pc); + + /* Not sure where we were */ + if (pc < KERNELBASE) + /* function descriptor madness */ + return *((unsigned long *)kernel_unknown_bucket); + + return check_spinlock_pc(regs, pc); +} + +static int get_kernel(unsigned long pc) +{ + int is_kernel; + + if (!mmcra_has_sihv) { + is_kernel = (pc >= KERNELBASE); + } else { + unsigned long mmcra = mfspr(SPRN_MMCRA); + is_kernel = ((mmcra & MMCRA_SIPR) == 0); + } + + return is_kernel; +} + +static void power4_handle_interrupt(struct pt_regs *regs, + struct op_counter_config *ctr) +{ + unsigned long pc; + int is_kernel; + int val; + int i; + unsigned int mmcr0; + + pc = get_pc(regs); + is_kernel = get_kernel(pc); + + /* set the PMM bit (see comment below) */ + mtmsrd(mfmsr() | MSR_PMM); + + for (i = 0; i < cur_cpu_spec->num_pmcs; ++i) { + val = ctr_read(i); + if (val < 0) { + if (oprofile_running && ctr[i].enabled) { + oprofile_add_pc(pc, is_kernel, i); + ctr_write(i, reset_value[i]); + } else { + ctr_write(i, 0); + } + } + } + + mmcr0 = mfspr(SPRN_MMCR0); + + /* reset the perfmon trigger */ + mmcr0 |= MMCR0_PMXE; + + /* + * We must clear the PMAO bit on some (GQ) chips. Just do it + * all the time + */ + mmcr0 &= ~MMCR0_PMAO; + + /* + * now clear the freeze bit, counting will not start until we + * rfid from this exception, because only at that point will + * the PMM bit be cleared + */ + mmcr0 &= ~MMCR0_FC; + mtspr(SPRN_MMCR0, mmcr0); +} + +struct op_powerpc_model op_model_power4 = { + .reg_setup = power4_reg_setup, + .cpu_setup = power4_cpu_setup, + .start = power4_start, + .stop = power4_stop, + .handle_interrupt = power4_handle_interrupt, +}; diff --git a/arch/powerpc/oprofile/op_model_rs64.c b/arch/powerpc/oprofile/op_model_rs64.c new file mode 100644 --- /dev/null +++ b/arch/powerpc/oprofile/op_model_rs64.c @@ -0,0 +1,218 @@ +/* + * Copyright (C) 2004 Anton Blanchard , IBM + * + * 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 + +#define dbg(args...) + +static void ctrl_write(unsigned int i, unsigned int val) +{ + unsigned int tmp = 0; + unsigned long shift = 0, mask = 0; + + dbg("ctrl_write %d %x\n", i, val); + + switch(i) { + case 0: + tmp = mfspr(SPRN_MMCR0); + shift = 6; + mask = 0x7F; + break; + case 1: + tmp = mfspr(SPRN_MMCR0); + shift = 0; + mask = 0x3F; + break; + case 2: + tmp = mfspr(SPRN_MMCR1); + shift = 31 - 4; + mask = 0x1F; + break; + case 3: + tmp = mfspr(SPRN_MMCR1); + shift = 31 - 9; + mask = 0x1F; + break; + case 4: + tmp = mfspr(SPRN_MMCR1); + shift = 31 - 14; + mask = 0x1F; + break; + case 5: + tmp = mfspr(SPRN_MMCR1); + shift = 31 - 19; + mask = 0x1F; + break; + case 6: + tmp = mfspr(SPRN_MMCR1); + shift = 31 - 24; + mask = 0x1F; + break; + case 7: + tmp = mfspr(SPRN_MMCR1); + shift = 31 - 28; + mask = 0xF; + break; + } + + tmp = tmp & ~(mask << shift); + tmp |= val << shift; + + switch(i) { + case 0: + case 1: + mtspr(SPRN_MMCR0, tmp); + break; + default: + mtspr(SPRN_MMCR1, tmp); + } + + dbg("ctrl_write mmcr0 %lx mmcr1 %lx\n", mfspr(SPRN_MMCR0), + mfspr(SPRN_MMCR1)); +} + +static unsigned long reset_value[OP_MAX_COUNTER]; + +static int num_counters; + +static void rs64_reg_setup(struct op_counter_config *ctr, + struct op_system_config *sys, + int num_ctrs) +{ + int i; + + num_counters = num_ctrs; + + for (i = 0; i < num_counters; ++i) + reset_value[i] = 0x80000000UL - ctr[i].count; + + /* XXX setup user and kernel profiling */ +} + +static void rs64_cpu_setup(void *unused) +{ + unsigned int mmcr0; + + /* reset MMCR0 and set the freeze bit */ + mmcr0 = MMCR0_FC; + mtspr(SPRN_MMCR0, mmcr0); + + /* reset MMCR1, MMCRA */ + mtspr(SPRN_MMCR1, 0); + + if (cpu_has_feature(CPU_FTR_MMCRA)) + mtspr(SPRN_MMCRA, 0); + + mmcr0 |= MMCR0_FCM1|MMCR0_PMXE|MMCR0_FCECE; + /* Only applies to POWER3, but should be safe on RS64 */ + mmcr0 |= MMCR0_PMC1CE|MMCR0_PMCjCE; + mtspr(SPRN_MMCR0, mmcr0); + + dbg("setup on cpu %d, mmcr0 %lx\n", smp_processor_id(), + mfspr(SPRN_MMCR0)); + dbg("setup on cpu %d, mmcr1 %lx\n", smp_processor_id(), + mfspr(SPRN_MMCR1)); +} + +static void rs64_start(struct op_counter_config *ctr) +{ + int i; + unsigned int mmcr0; + + /* set the PMM bit (see comment below) */ + mtmsrd(mfmsr() | MSR_PMM); + + for (i = 0; i < num_counters; ++i) { + if (ctr[i].enabled) { + ctr_write(i, reset_value[i]); + ctrl_write(i, ctr[i].event); + } else { + ctr_write(i, 0); + } + } + + mmcr0 = mfspr(SPRN_MMCR0); + + /* + * now clear the freeze bit, counting will not start until we + * rfid from this excetion, because only at that point will + * the PMM bit be cleared + */ + mmcr0 &= ~MMCR0_FC; + mtspr(SPRN_MMCR0, mmcr0); + + dbg("start on cpu %d, mmcr0 %x\n", smp_processor_id(), mmcr0); +} + +static void rs64_stop(void) +{ + unsigned int mmcr0; + + /* freeze counters */ + mmcr0 = mfspr(SPRN_MMCR0); + mmcr0 |= MMCR0_FC; + mtspr(SPRN_MMCR0, mmcr0); + + dbg("stop on cpu %d, mmcr0 %x\n", smp_processor_id(), mmcr0); + + mb(); +} + +static void rs64_handle_interrupt(struct pt_regs *regs, + struct op_counter_config *ctr) +{ + unsigned int mmcr0; + int val; + int i; + unsigned long pc = mfspr(SPRN_SIAR); + int is_kernel = (pc >= KERNELBASE); + + /* set the PMM bit (see comment below) */ + mtmsrd(mfmsr() | MSR_PMM); + + for (i = 0; i < num_counters; ++i) { + val = ctr_read(i); + if (val < 0) { + if (ctr[i].enabled) { + oprofile_add_pc(pc, is_kernel, i); + ctr_write(i, reset_value[i]); + } else { + ctr_write(i, 0); + } + } + } + + mmcr0 = mfspr(SPRN_MMCR0); + + /* reset the perfmon trigger */ + mmcr0 |= MMCR0_PMXE; + + /* + * now clear the freeze bit, counting will not start until we + * rfid from this exception, because only at that point will + * the PMM bit be cleared + */ + mmcr0 &= ~MMCR0_FC; + mtspr(SPRN_MMCR0, mmcr0); +} + +struct op_powerpc_model op_model_rs64 = { + .reg_setup = rs64_reg_setup, + .cpu_setup = rs64_cpu_setup, + .start = rs64_start, + .stop = rs64_stop, + .handle_interrupt = rs64_handle_interrupt, +}; diff --git a/arch/ppc/Makefile b/arch/ppc/Makefile --- a/arch/ppc/Makefile +++ b/arch/ppc/Makefile @@ -71,7 +71,7 @@ drivers-$(CONFIG_8xx) += arch/ppc/8xx_i drivers-$(CONFIG_4xx) += arch/ppc/4xx_io/ drivers-$(CONFIG_CPM2) += arch/ppc/8260_io/ -drivers-$(CONFIG_OPROFILE) += arch/ppc/oprofile/ +drivers-$(CONFIG_OPROFILE) += arch/powerpc/oprofile/ BOOT_TARGETS = zImage zImage.initrd znetboot znetboot.initrd vmlinux.sm diff --git a/arch/ppc/oprofile/Makefile b/arch/ppc/oprofile/Makefile deleted file mode 100644 --- a/arch/ppc/oprofile/Makefile +++ /dev/null @@ -1 +0,0 @@ -include arch/powerpc/oprofile/Makefile diff --git a/arch/ppc/oprofile/common.c b/arch/ppc/oprofile/common.c deleted file mode 100644 --- a/arch/ppc/oprofile/common.c +++ /dev/null @@ -1,160 +0,0 @@ -/* - * PPC 32 oprofile support - * Based on PPC64 oprofile support - * Copyright (C) 2004 Anton Blanchard , IBM - * - * Copyright (C) Freescale Semiconductor, Inc 2004 - * - * Author: Andy Fleming - * - * 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 - -static struct op_powerpc_model *model; - -static struct op_counter_config ctr[OP_MAX_COUNTER]; -static struct op_system_config sys; - -static void op_handle_interrupt(struct pt_regs *regs) -{ - model->handle_interrupt(regs, ctr); -} - -static int op_ppc32_setup(void) -{ - /* Install our interrupt handler into the existing hook. */ - if(request_perfmon_irq(&op_handle_interrupt)) - return -EBUSY; - - mb(); - - /* Pre-compute the values to stuff in the hardware registers. */ - model->reg_setup(ctr, &sys, model->num_counters); - -#if 0 - /* FIXME: Make multi-cpu work */ - /* Configure the registers on all cpus. */ - on_each_cpu(model->reg_setup, NULL, 0, 1); -#endif - - return 0; -} - -static void op_ppc32_shutdown(void) -{ - mb(); - - /* Remove our interrupt handler. We may be removing this module. */ - free_perfmon_irq(); -} - -static void op_ppc32_cpu_start(void *dummy) -{ - model->start(ctr); -} - -static int op_ppc32_start(void) -{ - on_each_cpu(op_ppc32_cpu_start, NULL, 0, 1); - return 0; -} - -static inline void op_ppc32_cpu_stop(void *dummy) -{ - model->stop(); -} - -static void op_ppc32_stop(void) -{ - on_each_cpu(op_ppc32_cpu_stop, NULL, 0, 1); -} - -static int op_ppc32_create_files(struct super_block *sb, struct dentry *root) -{ - int i; - - for (i = 0; i < model->num_counters; ++i) { - struct dentry *dir; - char buf[3]; - - snprintf(buf, sizeof buf, "%d", i); - dir = oprofilefs_mkdir(sb, root, buf); - - oprofilefs_create_ulong(sb, dir, "enabled", &ctr[i].enabled); - oprofilefs_create_ulong(sb, dir, "event", &ctr[i].event); - oprofilefs_create_ulong(sb, dir, "count", &ctr[i].count); - oprofilefs_create_ulong(sb, dir, "kernel", &ctr[i].kernel); - oprofilefs_create_ulong(sb, dir, "user", &ctr[i].user); - - /* FIXME: Not sure if this is used */ - oprofilefs_create_ulong(sb, dir, "unit_mask", &ctr[i].unit_mask); - } - - oprofilefs_create_ulong(sb, root, "enable_kernel", &sys.enable_kernel); - oprofilefs_create_ulong(sb, root, "enable_user", &sys.enable_user); - - /* Default to tracing both kernel and user */ - sys.enable_kernel = 1; - sys.enable_user = 1; - - return 0; -} - -static struct oprofile_operations oprof_ppc32_ops = { - .create_files = op_ppc32_create_files, - .setup = op_ppc32_setup, - .shutdown = op_ppc32_shutdown, - .start = op_ppc32_start, - .stop = op_ppc32_stop, - .cpu_type = NULL /* To be filled in below. */ -}; - -int __init oprofile_arch_init(struct oprofile_operations *ops) -{ - char *name; - int cpu_id = smp_processor_id(); - -#ifdef CONFIG_FSL_BOOKE - model = &op_model_fsl_booke; -#else - return -ENODEV; -#endif - - name = kmalloc(32, GFP_KERNEL); - - if (NULL == name) - return -ENOMEM; - - sprintf(name, "ppc/%s", cur_cpu_spec[cpu_id]->cpu_name); - - oprof_ppc32_ops.cpu_type = name; - - model->num_counters = cur_cpu_spec[cpu_id]->num_pmcs; - - *ops = oprof_ppc32_ops; - - printk(KERN_INFO "oprofile: using %s performance monitoring.\n", - oprof_ppc32_ops.cpu_type); - - return 0; -} - -void oprofile_arch_exit(void) -{ - kfree(oprof_ppc32_ops.cpu_type); - oprof_ppc32_ops.cpu_type = NULL; -} diff --git a/arch/ppc/oprofile/op_model_fsl_booke.c b/arch/ppc/oprofile/op_model_fsl_booke.c deleted file mode 100644 --- a/arch/ppc/oprofile/op_model_fsl_booke.c +++ /dev/null @@ -1,183 +0,0 @@ -/* - * oprofile/op_model_e500.c - * - * Freescale Book-E oprofile support, based on ppc64 oprofile support - * Copyright (C) 2004 Anton Blanchard , IBM - * - * Copyright (c) 2004 Freescale Semiconductor, Inc - * - * Author: Andy Fleming - * Maintainer: Kumar Gala - * - * 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 -#include - -static unsigned long reset_value[OP_MAX_COUNTER]; - -static int num_counters; -static int oprofile_running; - -static inline unsigned int ctr_read(unsigned int i) -{ - switch(i) { - case 0: - return mfpmr(PMRN_PMC0); - case 1: - return mfpmr(PMRN_PMC1); - case 2: - return mfpmr(PMRN_PMC2); - case 3: - return mfpmr(PMRN_PMC3); - default: - return 0; - } -} - -static inline void ctr_write(unsigned int i, unsigned int val) -{ - switch(i) { - case 0: - mtpmr(PMRN_PMC0, val); - break; - case 1: - mtpmr(PMRN_PMC1, val); - break; - case 2: - mtpmr(PMRN_PMC2, val); - break; - case 3: - mtpmr(PMRN_PMC3, val); - break; - default: - break; - } -} - - -static void fsl_booke_reg_setup(struct op_counter_config *ctr, - struct op_system_config *sys, - int num_ctrs) -{ - int i; - - num_counters = num_ctrs; - - /* freeze all counters */ - pmc_stop_ctrs(); - - /* Our counters count up, and "count" refers to - * how much before the next interrupt, and we interrupt - * on overflow. So we calculate the starting value - * which will give us "count" until overflow. - * Then we set the events on the enabled counters */ - for (i = 0; i < num_counters; ++i) { - reset_value[i] = 0x80000000UL - ctr[i].count; - - init_pmc_stop(i); - - set_pmc_event(i, ctr[i].event); - - set_pmc_user_kernel(i, ctr[i].user, ctr[i].kernel); - } -} - -static void fsl_booke_start(struct op_counter_config *ctr) -{ - int i; - - mtmsr(mfmsr() | MSR_PMM); - - for (i = 0; i < num_counters; ++i) { - if (ctr[i].enabled) { - ctr_write(i, reset_value[i]); - /* Set Each enabled counterd to only - * count when the Mark bit is not set */ - set_pmc_marked(i, 1, 0); - pmc_start_ctr(i, 1); - } else { - ctr_write(i, 0); - - /* Set the ctr to be stopped */ - pmc_start_ctr(i, 0); - } - } - - /* Clear the freeze bit, and enable the interrupt. - * The counters won't actually start until the rfi clears - * the PMM bit */ - pmc_start_ctrs(1); - - oprofile_running = 1; - - pr_debug("start on cpu %d, pmgc0 %x\n", smp_processor_id(), - mfpmr(PMRN_PMGC0)); -} - -static void fsl_booke_stop(void) -{ - /* freeze counters */ - pmc_stop_ctrs(); - - oprofile_running = 0; - - pr_debug("stop on cpu %d, pmgc0 %x\n", smp_processor_id(), - mfpmr(PMRN_PMGC0)); - - mb(); -} - - -static void fsl_booke_handle_interrupt(struct pt_regs *regs, - struct op_counter_config *ctr) -{ - unsigned long pc; - int is_kernel; - int val; - int i; - - /* set the PMM bit (see comment below) */ - mtmsr(mfmsr() | MSR_PMM); - - pc = regs->nip; - is_kernel = (pc >= KERNELBASE); - - for (i = 0; i < num_counters; ++i) { - val = ctr_read(i); - if (val < 0) { - if (oprofile_running && ctr[i].enabled) { - oprofile_add_pc(pc, is_kernel, i); - ctr_write(i, reset_value[i]); - } else { - ctr_write(i, 0); - } - } - } - - /* The freeze bit was set by the interrupt. */ - /* Clear the freeze bit, and reenable the interrupt. - * The counters won't actually start until the rfi clears - * the PMM bit */ - pmc_start_ctrs(1); -} - -struct op_powerpc_model op_model_fsl_booke = { - .reg_setup = fsl_booke_reg_setup, - .start = fsl_booke_start, - .stop = fsl_booke_stop, - .handle_interrupt = fsl_booke_handle_interrupt, -}; diff --git a/arch/ppc64/Makefile b/arch/ppc64/Makefile --- a/arch/ppc64/Makefile +++ b/arch/ppc64/Makefile @@ -85,7 +85,7 @@ libs-y += arch/ppc64/lib/ core-y += arch/ppc64/kernel/ core-y += arch/ppc64/mm/ core-$(CONFIG_XMON) += arch/ppc64/xmon/ -drivers-$(CONFIG_OPROFILE) += arch/ppc64/oprofile/ +drivers-$(CONFIG_OPROFILE) += arch/powerpc/oprofile/ boot := arch/ppc64/boot diff --git a/arch/ppc64/oprofile/Makefile b/arch/ppc64/oprofile/Makefile deleted file mode 100644 --- a/arch/ppc64/oprofile/Makefile +++ /dev/null @@ -1 +0,0 @@ -include arch/powerpc/oprofile/Makefile diff --git a/arch/ppc64/oprofile/common.c b/arch/ppc64/oprofile/common.c deleted file mode 100644 --- a/arch/ppc64/oprofile/common.c +++ /dev/null @@ -1,145 +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. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -static struct op_powerpc_model *model; - -static struct op_counter_config ctr[OP_MAX_COUNTER]; -static struct op_system_config sys; - -static void op_handle_interrupt(struct pt_regs *regs) -{ - model->handle_interrupt(regs, ctr); -} - -static int op_ppc64_setup(void) -{ - int err; - - /* Grab the hardware */ - err = reserve_pmc_hardware(op_handle_interrupt); - if (err) - return err; - - /* Pre-compute the values to stuff in the hardware registers. */ - model->reg_setup(ctr, &sys, model->num_counters); - - /* Configure the registers on all cpus. */ - on_each_cpu(model->cpu_setup, NULL, 0, 1); - - return 0; -} - -static void op_ppc64_shutdown(void) -{ - release_pmc_hardware(); -} - -static void op_ppc64_cpu_start(void *dummy) -{ - model->start(ctr); -} - -static int op_ppc64_start(void) -{ - on_each_cpu(op_ppc64_cpu_start, NULL, 0, 1); - return 0; -} - -static inline void op_ppc64_cpu_stop(void *dummy) -{ - model->stop(); -} - -static void op_ppc64_stop(void) -{ - on_each_cpu(op_ppc64_cpu_stop, NULL, 0, 1); -} - -static int op_ppc64_create_files(struct super_block *sb, struct dentry *root) -{ - int i; - - /* - * There is one mmcr0, mmcr1 and mmcra for setting the events for - * all of the counters. - */ - oprofilefs_create_ulong(sb, root, "mmcr0", &sys.mmcr0); - oprofilefs_create_ulong(sb, root, "mmcr1", &sys.mmcr1); - oprofilefs_create_ulong(sb, root, "mmcra", &sys.mmcra); - - for (i = 0; i < model->num_counters; ++i) { - struct dentry *dir; - char buf[3]; - - snprintf(buf, sizeof buf, "%d", i); - dir = oprofilefs_mkdir(sb, root, buf); - - oprofilefs_create_ulong(sb, dir, "enabled", &ctr[i].enabled); - oprofilefs_create_ulong(sb, dir, "event", &ctr[i].event); - oprofilefs_create_ulong(sb, dir, "count", &ctr[i].count); - /* - * We dont support per counter user/kernel selection, but - * we leave the entries because userspace expects them - */ - oprofilefs_create_ulong(sb, dir, "kernel", &ctr[i].kernel); - oprofilefs_create_ulong(sb, dir, "user", &ctr[i].user); - oprofilefs_create_ulong(sb, dir, "unit_mask", &ctr[i].unit_mask); - } - - oprofilefs_create_ulong(sb, root, "enable_kernel", &sys.enable_kernel); - oprofilefs_create_ulong(sb, root, "enable_user", &sys.enable_user); - oprofilefs_create_ulong(sb, root, "backtrace_spinlocks", - &sys.backtrace_spinlocks); - - /* Default to tracing both kernel and user */ - sys.enable_kernel = 1; - sys.enable_user = 1; - - /* Turn on backtracing through spinlocks by default */ - sys.backtrace_spinlocks = 1; - - return 0; -} - -int __init oprofile_arch_init(struct oprofile_operations *ops) -{ - if (!cur_cpu_spec->oprofile_model || !cur_cpu_spec->oprofile_cpu_type) - 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; - ops->create_files = op_ppc64_create_files; - ops->setup = op_ppc64_setup; - ops->shutdown = op_ppc64_shutdown; - ops->start = op_ppc64_start; - ops->stop = op_ppc64_stop; - - printk(KERN_INFO "oprofile: using %s performance monitoring.\n", - ops->cpu_type); - - return 0; -} - -void oprofile_arch_exit(void) -{ -} diff --git a/arch/ppc64/oprofile/op_model_power4.c b/arch/ppc64/oprofile/op_model_power4.c deleted file mode 100644 --- a/arch/ppc64/oprofile/op_model_power4.c +++ /dev/null @@ -1,309 +0,0 @@ -/* - * Copyright (C) 2004 Anton Blanchard , IBM - * - * 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 - -#define dbg(args...) - -static unsigned long reset_value[OP_MAX_COUNTER]; - -static int oprofile_running; -static int mmcra_has_sihv; - -/* mmcr values are set in power4_reg_setup, used in power4_cpu_setup */ -static u32 mmcr0_val; -static u64 mmcr1_val; -static u32 mmcra_val; - -/* - * Since we do not have an NMI, backtracing through spinlocks is - * only a best guess. In light of this, allow it to be disabled at - * runtime. - */ -static int backtrace_spinlocks; - -static void power4_reg_setup(struct op_counter_config *ctr, - struct op_system_config *sys, - int num_ctrs) -{ - int i; - - /* - * SIHV / SIPR bits are only implemented on POWER4+ (GQ) and above. - * However we disable it on all POWER4 until we verify it works - * (I was seeing some strange behaviour last time I tried). - * - * It has been verified to work on POWER5 so we enable it there. - */ - if (cpu_has_feature(CPU_FTR_MMCRA_SIHV)) - mmcra_has_sihv = 1; - - /* - * The performance counter event settings are given in the mmcr0, - * mmcr1 and mmcra values passed from the user in the - * op_system_config structure (sys variable). - */ - mmcr0_val = sys->mmcr0; - mmcr1_val = sys->mmcr1; - mmcra_val = sys->mmcra; - - backtrace_spinlocks = sys->backtrace_spinlocks; - - for (i = 0; i < cur_cpu_spec->num_pmcs; ++i) - reset_value[i] = 0x80000000UL - ctr[i].count; - - /* setup user and kernel profiling */ - if (sys->enable_kernel) - mmcr0_val &= ~MMCR0_KERNEL_DISABLE; - else - mmcr0_val |= MMCR0_KERNEL_DISABLE; - - if (sys->enable_user) - mmcr0_val &= ~MMCR0_PROBLEM_DISABLE; - else - mmcr0_val |= MMCR0_PROBLEM_DISABLE; -} - -extern void ppc64_enable_pmcs(void); - -static void power4_cpu_setup(void *unused) -{ - unsigned int mmcr0 = mmcr0_val; - unsigned long mmcra = mmcra_val; - - ppc64_enable_pmcs(); - - /* set the freeze bit */ - mmcr0 |= MMCR0_FC; - mtspr(SPRN_MMCR0, mmcr0); - - mmcr0 |= MMCR0_FCM1|MMCR0_PMXE|MMCR0_FCECE; - mmcr0 |= MMCR0_PMC1CE|MMCR0_PMCjCE; - mtspr(SPRN_MMCR0, mmcr0); - - mtspr(SPRN_MMCR1, mmcr1_val); - - mmcra |= MMCRA_SAMPLE_ENABLE; - mtspr(SPRN_MMCRA, mmcra); - - dbg("setup on cpu %d, mmcr0 %lx\n", smp_processor_id(), - mfspr(SPRN_MMCR0)); - dbg("setup on cpu %d, mmcr1 %lx\n", smp_processor_id(), - mfspr(SPRN_MMCR1)); - dbg("setup on cpu %d, mmcra %lx\n", smp_processor_id(), - mfspr(SPRN_MMCRA)); -} - -static void power4_start(struct op_counter_config *ctr) -{ - int i; - unsigned int mmcr0; - - /* set the PMM bit (see comment below) */ - mtmsrd(mfmsr() | MSR_PMM); - - for (i = 0; i < cur_cpu_spec->num_pmcs; ++i) { - if (ctr[i].enabled) { - ctr_write(i, reset_value[i]); - } else { - ctr_write(i, 0); - } - } - - mmcr0 = mfspr(SPRN_MMCR0); - - /* - * We must clear the PMAO bit on some (GQ) chips. Just do it - * all the time - */ - mmcr0 &= ~MMCR0_PMAO; - - /* - * now clear the freeze bit, counting will not start until we - * rfid from this excetion, because only at that point will - * the PMM bit be cleared - */ - mmcr0 &= ~MMCR0_FC; - mtspr(SPRN_MMCR0, mmcr0); - - oprofile_running = 1; - - dbg("start on cpu %d, mmcr0 %x\n", smp_processor_id(), mmcr0); -} - -static void power4_stop(void) -{ - unsigned int mmcr0; - - /* freeze counters */ - mmcr0 = mfspr(SPRN_MMCR0); - mmcr0 |= MMCR0_FC; - mtspr(SPRN_MMCR0, mmcr0); - - oprofile_running = 0; - - dbg("stop on cpu %d, mmcr0 %x\n", smp_processor_id(), mmcr0); - - mb(); -} - -/* Fake functions used by canonicalize_pc */ -static void __attribute_used__ hypervisor_bucket(void) -{ -} - -static void __attribute_used__ rtas_bucket(void) -{ -} - -static void __attribute_used__ kernel_unknown_bucket(void) -{ -} - -static unsigned long check_spinlock_pc(struct pt_regs *regs, - unsigned long profile_pc) -{ - unsigned long pc = instruction_pointer(regs); - - /* - * If both the SIAR (sampled instruction) and the perfmon exception - * occurred in a spinlock region then we account the sample to the - * calling function. This isnt 100% correct, we really need soft - * IRQ disable so we always get the perfmon exception at the - * point at which the SIAR is set. - */ - if (backtrace_spinlocks && in_lock_functions(pc) && - in_lock_functions(profile_pc)) - return regs->link; - else - return profile_pc; -} - -/* - * On GQ and newer the MMCRA stores the HV and PR bits at the time - * the SIAR was sampled. We use that to work out if the SIAR was sampled in - * the hypervisor, our exception vectors or RTAS. - */ -static unsigned long get_pc(struct pt_regs *regs) -{ - unsigned long pc = mfspr(SPRN_SIAR); - unsigned long mmcra; - - /* Cant do much about it */ - if (!mmcra_has_sihv) - return check_spinlock_pc(regs, pc); - - mmcra = mfspr(SPRN_MMCRA); - - /* Were we in the hypervisor? */ - if ((systemcfg->platform == PLATFORM_PSERIES_LPAR) && - (mmcra & MMCRA_SIHV)) - /* function descriptor madness */ - return *((unsigned long *)hypervisor_bucket); - - /* We were in userspace, nothing to do */ - if (mmcra & MMCRA_SIPR) - return pc; - -#ifdef CONFIG_PPC_RTAS - /* Were we in RTAS? */ - if (pc >= rtas.base && pc < (rtas.base + rtas.size)) - /* function descriptor madness */ - return *((unsigned long *)rtas_bucket); -#endif - - /* Were we in our exception vectors or SLB real mode miss handler? */ - if (pc < 0x1000000UL) - return (unsigned long)__va(pc); - - /* Not sure where we were */ - if (pc < KERNELBASE) - /* function descriptor madness */ - return *((unsigned long *)kernel_unknown_bucket); - - return check_spinlock_pc(regs, pc); -} - -static int get_kernel(unsigned long pc) -{ - int is_kernel; - - if (!mmcra_has_sihv) { - is_kernel = (pc >= KERNELBASE); - } else { - unsigned long mmcra = mfspr(SPRN_MMCRA); - is_kernel = ((mmcra & MMCRA_SIPR) == 0); - } - - return is_kernel; -} - -static void power4_handle_interrupt(struct pt_regs *regs, - struct op_counter_config *ctr) -{ - unsigned long pc; - int is_kernel; - int val; - int i; - unsigned int mmcr0; - - pc = get_pc(regs); - is_kernel = get_kernel(pc); - - /* set the PMM bit (see comment below) */ - mtmsrd(mfmsr() | MSR_PMM); - - for (i = 0; i < cur_cpu_spec->num_pmcs; ++i) { - val = ctr_read(i); - if (val < 0) { - if (oprofile_running && ctr[i].enabled) { - oprofile_add_pc(pc, is_kernel, i); - ctr_write(i, reset_value[i]); - } else { - ctr_write(i, 0); - } - } - } - - mmcr0 = mfspr(SPRN_MMCR0); - - /* reset the perfmon trigger */ - mmcr0 |= MMCR0_PMXE; - - /* - * We must clear the PMAO bit on some (GQ) chips. Just do it - * all the time - */ - mmcr0 &= ~MMCR0_PMAO; - - /* - * now clear the freeze bit, counting will not start until we - * rfid from this exception, because only at that point will - * the PMM bit be cleared - */ - mmcr0 &= ~MMCR0_FC; - mtspr(SPRN_MMCR0, mmcr0); -} - -struct op_powerpc_model op_model_power4 = { - .reg_setup = power4_reg_setup, - .cpu_setup = power4_cpu_setup, - .start = power4_start, - .stop = power4_stop, - .handle_interrupt = power4_handle_interrupt, -}; diff --git a/arch/ppc64/oprofile/op_model_rs64.c b/arch/ppc64/oprofile/op_model_rs64.c deleted file mode 100644 --- a/arch/ppc64/oprofile/op_model_rs64.c +++ /dev/null @@ -1,218 +0,0 @@ -/* - * Copyright (C) 2004 Anton Blanchard , IBM - * - * 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 - -#define dbg(args...) - -static void ctrl_write(unsigned int i, unsigned int val) -{ - unsigned int tmp = 0; - unsigned long shift = 0, mask = 0; - - dbg("ctrl_write %d %x\n", i, val); - - switch(i) { - case 0: - tmp = mfspr(SPRN_MMCR0); - shift = 6; - mask = 0x7F; - break; - case 1: - tmp = mfspr(SPRN_MMCR0); - shift = 0; - mask = 0x3F; - break; - case 2: - tmp = mfspr(SPRN_MMCR1); - shift = 31 - 4; - mask = 0x1F; - break; - case 3: - tmp = mfspr(SPRN_MMCR1); - shift = 31 - 9; - mask = 0x1F; - break; - case 4: - tmp = mfspr(SPRN_MMCR1); - shift = 31 - 14; - mask = 0x1F; - break; - case 5: - tmp = mfspr(SPRN_MMCR1); - shift = 31 - 19; - mask = 0x1F; - break; - case 6: - tmp = mfspr(SPRN_MMCR1); - shift = 31 - 24; - mask = 0x1F; - break; - case 7: - tmp = mfspr(SPRN_MMCR1); - shift = 31 - 28; - mask = 0xF; - break; - } - - tmp = tmp & ~(mask << shift); - tmp |= val << shift; - - switch(i) { - case 0: - case 1: - mtspr(SPRN_MMCR0, tmp); - break; - default: - mtspr(SPRN_MMCR1, tmp); - } - - dbg("ctrl_write mmcr0 %lx mmcr1 %lx\n", mfspr(SPRN_MMCR0), - mfspr(SPRN_MMCR1)); -} - -static unsigned long reset_value[OP_MAX_COUNTER]; - -static int num_counters; - -static void rs64_reg_setup(struct op_counter_config *ctr, - struct op_system_config *sys, - int num_ctrs) -{ - int i; - - num_counters = num_ctrs; - - for (i = 0; i < num_counters; ++i) - reset_value[i] = 0x80000000UL - ctr[i].count; - - /* XXX setup user and kernel profiling */ -} - -static void rs64_cpu_setup(void *unused) -{ - unsigned int mmcr0; - - /* reset MMCR0 and set the freeze bit */ - mmcr0 = MMCR0_FC; - mtspr(SPRN_MMCR0, mmcr0); - - /* reset MMCR1, MMCRA */ - mtspr(SPRN_MMCR1, 0); - - if (cpu_has_feature(CPU_FTR_MMCRA)) - mtspr(SPRN_MMCRA, 0); - - mmcr0 |= MMCR0_FCM1|MMCR0_PMXE|MMCR0_FCECE; - /* Only applies to POWER3, but should be safe on RS64 */ - mmcr0 |= MMCR0_PMC1CE|MMCR0_PMCjCE; - mtspr(SPRN_MMCR0, mmcr0); - - dbg("setup on cpu %d, mmcr0 %lx\n", smp_processor_id(), - mfspr(SPRN_MMCR0)); - dbg("setup on cpu %d, mmcr1 %lx\n", smp_processor_id(), - mfspr(SPRN_MMCR1)); -} - -static void rs64_start(struct op_counter_config *ctr) -{ - int i; - unsigned int mmcr0; - - /* set the PMM bit (see comment below) */ - mtmsrd(mfmsr() | MSR_PMM); - - for (i = 0; i < num_counters; ++i) { - if (ctr[i].enabled) { - ctr_write(i, reset_value[i]); - ctrl_write(i, ctr[i].event); - } else { - ctr_write(i, 0); - } - } - - mmcr0 = mfspr(SPRN_MMCR0); - - /* - * now clear the freeze bit, counting will not start until we - * rfid from this excetion, because only at that point will - * the PMM bit be cleared - */ - mmcr0 &= ~MMCR0_FC; - mtspr(SPRN_MMCR0, mmcr0); - - dbg("start on cpu %d, mmcr0 %x\n", smp_processor_id(), mmcr0); -} - -static void rs64_stop(void) -{ - unsigned int mmcr0; - - /* freeze counters */ - mmcr0 = mfspr(SPRN_MMCR0); - mmcr0 |= MMCR0_FC; - mtspr(SPRN_MMCR0, mmcr0); - - dbg("stop on cpu %d, mmcr0 %x\n", smp_processor_id(), mmcr0); - - mb(); -} - -static void rs64_handle_interrupt(struct pt_regs *regs, - struct op_counter_config *ctr) -{ - unsigned int mmcr0; - int val; - int i; - unsigned long pc = mfspr(SPRN_SIAR); - int is_kernel = (pc >= KERNELBASE); - - /* set the PMM bit (see comment below) */ - mtmsrd(mfmsr() | MSR_PMM); - - for (i = 0; i < num_counters; ++i) { - val = ctr_read(i); - if (val < 0) { - if (ctr[i].enabled) { - oprofile_add_pc(pc, is_kernel, i); - ctr_write(i, reset_value[i]); - } else { - ctr_write(i, 0); - } - } - } - - mmcr0 = mfspr(SPRN_MMCR0); - - /* reset the perfmon trigger */ - mmcr0 |= MMCR0_PMXE; - - /* - * now clear the freeze bit, counting will not start until we - * rfid from this exception, because only at that point will - * the PMM bit be cleared - */ - mmcr0 &= ~MMCR0_FC; - mtspr(SPRN_MMCR0, mmcr0); -} - -struct op_powerpc_model op_model_rs64 = { - .reg_setup = rs64_reg_setup, - .cpu_setup = rs64_cpu_setup, - .start = rs64_start, - .stop = rs64_stop, - .handle_interrupt = rs64_handle_interrupt, -}; From sfr at canb.auug.org.au Mon Sep 19 23:28:21 2005 From: sfr at canb.auug.org.au (Stephen Rothwell) Date: Mon, 19 Sep 2005 23:28:21 +1000 Subject: [PATCH 6/6] powerpc: reduce oprofile/common.c differences In-Reply-To: <20050919231051.28fcdf30.sfr@canb.auug.org.au> References: <20050919231051.28fcdf30.sfr@canb.auug.org.au> Message-ID: <20050919232821.7709b9f5.sfr@canb.auug.org.au> Rename and slightly modify {request,free}_perfmon_irq in the ppc code. Signed-off-by: Stephen Rothwell --- arch/powerpc/oprofile/common.c | 13 ------------- arch/ppc/kernel/perfmon.c | 10 +++++----- include/asm-ppc/perfmon.h | 4 ++-- 3 files changed, 7 insertions(+), 20 deletions(-) -- Cheers, Stephen Rothwell sfr at canb.auug.org.au http://www.canb.auug.org.au/~sfr/ b3a2095ea11906c79fd1c43819e9b9c8d4f0ab51 diff --git a/arch/powerpc/oprofile/common.c b/arch/powerpc/oprofile/common.c --- a/arch/powerpc/oprofile/common.c +++ b/arch/powerpc/oprofile/common.c @@ -46,19 +46,12 @@ static void op_handle_interrupt(struct p static int op_powerpc_setup(void) { -#ifdef __powerpc64__ int err; /* Grab the hardware */ err = reserve_pmc_hardware(op_handle_interrupt); if (err) return err; -#else /* __powerpc64__ */ - /* Install our interrupt handler into the existing hook. */ - if (request_perfmon_irq(&op_handle_interrupt)) - return -EBUSY; - mb(); -#endif /* __powerpc64__ */ /* Pre-compute the values to stuff in the hardware registers. */ model->reg_setup(ctr, &sys, model->num_counters); @@ -78,13 +71,7 @@ static int op_powerpc_setup(void) static void op_powerpc_shutdown(void) { -#ifdef __powerpc64__ release_pmc_hardware(); -#else /* __powerpc64__ */ - mb(); - /* Remove our interrupt handler. We may be removing this module. */ - free_perfmon_irq(); -#endif /* __powerpc64__ */ } static void op_powerpc_cpu_start(void *dummy) diff --git a/arch/ppc/kernel/perfmon.c b/arch/ppc/kernel/perfmon.c --- a/arch/ppc/kernel/perfmon.c +++ b/arch/ppc/kernel/perfmon.c @@ -61,7 +61,7 @@ void (*perf_irq)(struct pt_regs *) = dum /* Grab the interrupt, if it's free. * Returns 0 on success, -1 if the interrupt is taken already */ -int request_perfmon_irq(void (*handler)(struct pt_regs *)) +int reserve_pmc_hardware(void (*handler)(struct pt_regs *)) { int err = 0; @@ -71,7 +71,7 @@ int request_perfmon_irq(void (*handler)( perf_irq = handler; else { pr_info("perfmon irq already handled by %p\n", perf_irq); - err = -1; + err = -EBUSY; } spin_unlock(&perfmon_lock); @@ -79,7 +79,7 @@ int request_perfmon_irq(void (*handler)( return err; } -void free_perfmon_irq(void) +void release_pmc_hardware(void) { spin_lock(&perfmon_lock); @@ -89,5 +89,5 @@ void free_perfmon_irq(void) } EXPORT_SYMBOL(perf_irq); -EXPORT_SYMBOL(request_perfmon_irq); -EXPORT_SYMBOL(free_perfmon_irq); +EXPORT_SYMBOL(reserve_pmc_hardware); +EXPORT_SYMBOL(release_pmc_hardware); diff --git a/include/asm-ppc/perfmon.h b/include/asm-ppc/perfmon.h --- a/include/asm-ppc/perfmon.h +++ b/include/asm-ppc/perfmon.h @@ -3,8 +3,8 @@ extern void (*perf_irq)(struct pt_regs *); -int request_perfmon_irq(void (*handler)(struct pt_regs *)); -void free_perfmon_irq(void); +int reserve_pmc_hardware(void (*handler)(struct pt_regs *)); +void release_pmc_hardware(void); #ifdef CONFIG_FSL_BOOKE void init_pmc_stop(int ctr); From linuxppc at jdl.com Tue Sep 20 00:01:13 2005 From: linuxppc at jdl.com (linuxppc at jdl.com) Date: Mon, 19 Sep 2005 09:01:13 -0500 Subject: PATCH powerpc: Merge asm-ppc*/posix_types.h Message-ID: Merge asm-ppc/posix_types.h and asm-ppc64/posix_types.h. Signed-off-by: Jon Loeliger Signed-off-by: Kumar Gala --- include/asm-powerpc/posix_types.h | 129 +++++++++++++++++++++++++++++++++++++ include/asm-ppc/posix_types.h | 111 -------------------------------- include/asm-ppc64/posix_types.h | 119 ---------------------------------- 3 files changed, 129 insertions(+), 230 deletions(-) diff --git a/include/asm-powerpc/posix_types.h b/include/asm-powerpc/posix_types.h new file mode 100644 --- /dev/null +++ b/include/asm-powerpc/posix_types.h @@ -0,0 +1,129 @@ +#ifndef _ASM_POWERPC_POSIX_TYPES_H +#define _ASM_POWERPC_POSIX_TYPES_H + +/* + * This file is generally used by user-level software, so you need to + * be a little careful about namespace pollution etc. Also, we cannot + * assume GCC is being used. + */ + +typedef unsigned long __kernel_ino_t; +typedef unsigned int __kernel_mode_t; +typedef long __kernel_off_t; +typedef int __kernel_pid_t; +typedef unsigned int __kernel_uid_t; +typedef unsigned int __kernel_gid_t; +typedef long __kernel_ptrdiff_t; +typedef long __kernel_time_t; +typedef long __kernel_clock_t; +typedef int __kernel_timer_t; +typedef int __kernel_clockid_t; +typedef long __kernel_suseconds_t; +typedef int __kernel_daddr_t; +typedef char * __kernel_caddr_t; +typedef unsigned short __kernel_uid16_t; +typedef unsigned short __kernel_gid16_t; +typedef unsigned int __kernel_uid32_t; +typedef unsigned int __kernel_gid32_t; +typedef unsigned int __kernel_old_uid_t; +typedef unsigned int __kernel_old_gid_t; + +#ifdef __powerpc64__ +typedef unsigned long __kernel_nlink_t; +typedef int __kernel_ipc_pid_t; +typedef unsigned long __kernel_size_t; +typedef long __kernel_ssize_t; +typedef unsigned long __kernel_old_dev_t; +#else +typedef unsigned short __kernel_nlink_t; +typedef short __kernel_ipc_pid_t; +typedef unsigned int __kernel_size_t; +typedef int __kernel_ssize_t; +typedef unsigned int __kernel_old_dev_t; +#endif + +#ifdef __powerpc64__ +typedef long long __kernel_loff_t; +#else +#ifdef __GNUC__ +typedef long long __kernel_loff_t; +#endif +#endif + +typedef struct { + int val[2]; +} __kernel_fsid_t; + +#ifndef __GNUC__ + +#define __FD_SET(d, set) ((set)->fds_bits[__FDELT(d)] |= __FDMASK(d)) +#define __FD_CLR(d, set) ((set)->fds_bits[__FDELT(d)] &= ~__FDMASK(d)) +#define __FD_ISSET(d, set) (((set)->fds_bits[__FDELT(d)] & __FDMASK(d)) != 0) +#define __FD_ZERO(set) \ + ((void) memset ((__ptr_t) (set), 0, sizeof (__kernel_fd_set))) + +#else /* __GNUC__ */ + +#if defined(__KERNEL__) || !defined(__GLIBC__) || (__GLIBC__ < 2) \ + || (__GLIBC__ == 2 && __GLIBC_MINOR__ == 0) +/* With GNU C, use inline functions instead so args are evaluated only once: */ + +#undef __FD_SET +static __inline__ void __FD_SET(unsigned long fd, __kernel_fd_set *fdsetp) +{ + unsigned long _tmp = fd / __NFDBITS; + unsigned long _rem = fd % __NFDBITS; + fdsetp->fds_bits[_tmp] |= (1UL<<_rem); +} + +#undef __FD_CLR +static __inline__ void __FD_CLR(unsigned long fd, __kernel_fd_set *fdsetp) +{ + unsigned long _tmp = fd / __NFDBITS; + unsigned long _rem = fd % __NFDBITS; + fdsetp->fds_bits[_tmp] &= ~(1UL<<_rem); +} + +#undef __FD_ISSET +static __inline__ int __FD_ISSET(unsigned long fd, __kernel_fd_set *p) +{ + unsigned long _tmp = fd / __NFDBITS; + unsigned long _rem = fd % __NFDBITS; + return (p->fds_bits[_tmp] & (1UL<<_rem)) != 0; +} + +/* + * This will unroll the loop for the normal constant case (8 ints, + * for a 256-bit fd_set) + */ +#undef __FD_ZERO +static __inline__ void __FD_ZERO(__kernel_fd_set *p) +{ + unsigned long *tmp = (unsigned long *)p->fds_bits; + int i; + + if (__builtin_constant_p(__FDSET_LONGS)) { + switch (__FDSET_LONGS) { + case 16: + tmp[12] = 0; tmp[13] = 0; tmp[14] = 0; tmp[15] = 0; + tmp[ 8] = 0; tmp[ 9] = 0; tmp[10] = 0; tmp[11] = 0; + + case 8: + tmp[ 4] = 0; tmp[ 5] = 0; tmp[ 6] = 0; tmp[ 7] = 0; + + case 4: + tmp[ 0] = 0; tmp[ 1] = 0; tmp[ 2] = 0; tmp[ 3] = 0; + return; + } + } + i = __FDSET_LONGS; + while (i) { + i--; + *tmp = 0; + tmp++; + } +} + +#endif /* defined(__KERNEL__) || !defined(__GLIBC__) || (__GLIBC__ < 2) */ +#endif /* __GNUC__ */ +#endif /* _ASM_POWERPC_POSIX_TYPES_H */ diff --git a/include/asm-ppc/posix_types.h b/include/asm-ppc/posix_types.h deleted file mode 100644 --- a/include/asm-ppc/posix_types.h +++ /dev/null @@ -1,111 +0,0 @@ -#ifndef _PPC_POSIX_TYPES_H -#define _PPC_POSIX_TYPES_H - -/* - * This file is generally used by user-level software, so you need to - * be a little careful about namespace pollution etc. Also, we cannot - * assume GCC is being used. - */ - -typedef unsigned long __kernel_ino_t; -typedef unsigned int __kernel_mode_t; -typedef unsigned short __kernel_nlink_t; -typedef long __kernel_off_t; -typedef int __kernel_pid_t; -typedef unsigned int __kernel_uid_t; -typedef unsigned int __kernel_gid_t; -typedef unsigned int __kernel_size_t; -typedef int __kernel_ssize_t; -typedef long __kernel_ptrdiff_t; -typedef long __kernel_time_t; -typedef long __kernel_suseconds_t; -typedef long __kernel_clock_t; -typedef int __kernel_timer_t; -typedef int __kernel_clockid_t; -typedef int __kernel_daddr_t; -typedef char * __kernel_caddr_t; -typedef short __kernel_ipc_pid_t; -typedef unsigned short __kernel_uid16_t; -typedef unsigned short __kernel_gid16_t; -typedef unsigned int __kernel_uid32_t; -typedef unsigned int __kernel_gid32_t; - -typedef unsigned int __kernel_old_uid_t; -typedef unsigned int __kernel_old_gid_t; -typedef unsigned int __kernel_old_dev_t; - -#ifdef __GNUC__ -typedef long long __kernel_loff_t; -#endif - -typedef struct { - int val[2]; -} __kernel_fsid_t; - -#ifndef __GNUC__ - -#define __FD_SET(d, set) ((set)->fds_bits[__FDELT(d)] |= __FDMASK(d)) -#define __FD_CLR(d, set) ((set)->fds_bits[__FDELT(d)] &= ~__FDMASK(d)) -#define __FD_ISSET(d, set) ((set)->fds_bits[__FDELT(d)] & __FDMASK(d)) -#define __FD_ZERO(set) \ - ((void) memset ((__ptr_t) (set), 0, sizeof (__kernel_fd_set))) - -#else /* __GNUC__ */ - -#if defined(__KERNEL__) || !defined(__GLIBC__) || (__GLIBC__ < 2) \ - || (__GLIBC__ == 2 && __GLIBC_MINOR__ == 0) -/* With GNU C, use inline functions instead so args are evaluated only once: */ - -#undef __FD_SET -static __inline__ void __FD_SET(unsigned long fd, __kernel_fd_set *fdsetp) -{ - unsigned long _tmp = fd / __NFDBITS; - unsigned long _rem = fd % __NFDBITS; - fdsetp->fds_bits[_tmp] |= (1UL<<_rem); -} - -#undef __FD_CLR -static __inline__ void __FD_CLR(unsigned long fd, __kernel_fd_set *fdsetp) -{ - unsigned long _tmp = fd / __NFDBITS; - unsigned long _rem = fd % __NFDBITS; - fdsetp->fds_bits[_tmp] &= ~(1UL<<_rem); -} - -#undef __FD_ISSET -static __inline__ int __FD_ISSET(unsigned long fd, __kernel_fd_set *p) -{ - unsigned long _tmp = fd / __NFDBITS; - unsigned long _rem = fd % __NFDBITS; - return (p->fds_bits[_tmp] & (1UL<<_rem)) != 0; -} - -/* - * This will unroll the loop for the normal constant case (8 ints, - * for a 256-bit fd_set) - */ -#undef __FD_ZERO -static __inline__ void __FD_ZERO(__kernel_fd_set *p) -{ - unsigned int *tmp = (unsigned int *)p->fds_bits; - int i; - - if (__builtin_constant_p(__FDSET_LONGS)) { - switch (__FDSET_LONGS) { - case 8: - tmp[0] = 0; tmp[1] = 0; tmp[2] = 0; tmp[3] = 0; - tmp[4] = 0; tmp[5] = 0; tmp[6] = 0; tmp[7] = 0; - return; - } - } - i = __FDSET_LONGS; - while (i) { - i--; - *tmp = 0; - tmp++; - } -} - -#endif /* defined(__KERNEL__) || !defined(__GLIBC__) || (__GLIBC__ < 2) */ -#endif /* __GNUC__ */ -#endif /* _PPC_POSIX_TYPES_H */ diff --git a/include/asm-ppc64/posix_types.h b/include/asm-ppc64/posix_types.h deleted file mode 100644 --- a/include/asm-ppc64/posix_types.h +++ /dev/null @@ -1,119 +0,0 @@ -#ifndef _PPC64_POSIX_TYPES_H -#define _PPC64_POSIX_TYPES_H - -/* - * This file is generally used by user-level software, so you need to - * be a little careful about namespace pollution etc. Also, we cannot - * assume GCC is being used. - * - * 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 long __kernel_ino_t; -typedef unsigned long __kernel_nlink_t; -typedef unsigned int __kernel_mode_t; -typedef long __kernel_off_t; -typedef long long __kernel_loff_t; -typedef int __kernel_pid_t; -typedef int __kernel_ipc_pid_t; -typedef unsigned int __kernel_uid_t; -typedef unsigned int __kernel_gid_t; -typedef unsigned long __kernel_size_t; -typedef long __kernel_ssize_t; -typedef long __kernel_ptrdiff_t; -typedef long __kernel_time_t; -typedef int __kernel_timer_t; -typedef int __kernel_clockid_t; -typedef long __kernel_suseconds_t; -typedef long __kernel_clock_t; -typedef int __kernel_daddr_t; -typedef char * __kernel_caddr_t; -typedef unsigned short __kernel_uid16_t; -typedef unsigned short __kernel_gid16_t; -typedef unsigned int __kernel_uid32_t; -typedef unsigned int __kernel_gid32_t; - -typedef unsigned int __kernel_old_uid_t; -typedef unsigned int __kernel_old_gid_t; -typedef unsigned long __kernel_old_dev_t; - -typedef struct { - int val[2]; -} __kernel_fsid_t; - -#ifndef __GNUC__ - -#define __FD_SET(d, set) ((set)->fds_bits[__FDELT(d)] |= __FDMASK(d)) -#define __FD_CLR(d, set) ((set)->fds_bits[__FDELT(d)] &= ~__FDMASK(d)) -#define __FD_ISSET(d, set) (((set)->fds_bits[__FDELT(d)] & __FDMASK(d)) != 0) -#define __FD_ZERO(set) \ - ((void) memset ((__ptr_t) (set), 0, sizeof (__kernel_fd_set))) - -#else /* __GNUC__ */ - -#if defined(__KERNEL__) || !defined(__GLIBC__) || (__GLIBC__ < 2) \ - || (__GLIBC__ == 2 && __GLIBC_MINOR__ == 0) -/* With GNU C, use inline functions instead so args are evaluated only once: */ - -#undef __FD_SET -static __inline__ void __FD_SET(unsigned long fd, __kernel_fd_set *fdsetp) -{ - unsigned long _tmp = fd / __NFDBITS; - unsigned long _rem = fd % __NFDBITS; - fdsetp->fds_bits[_tmp] |= (1UL<<_rem); -} - -#undef __FD_CLR -static __inline__ void __FD_CLR(unsigned long fd, __kernel_fd_set *fdsetp) -{ - unsigned long _tmp = fd / __NFDBITS; - unsigned long _rem = fd % __NFDBITS; - fdsetp->fds_bits[_tmp] &= ~(1UL<<_rem); -} - -#undef __FD_ISSET -static __inline__ int __FD_ISSET(unsigned long fd, __kernel_fd_set *p) -{ - unsigned long _tmp = fd / __NFDBITS; - unsigned long _rem = fd % __NFDBITS; - return (p->fds_bits[_tmp] & (1UL<<_rem)) != 0; -} - -/* - * This will unroll the loop for the normal constant case (8 ints, - * for a 256-bit fd_set) - */ -#undef __FD_ZERO -static __inline__ void __FD_ZERO(__kernel_fd_set *p) -{ - unsigned long *tmp = (unsigned long *)p->fds_bits; - int i; - - if (__builtin_constant_p(__FDSET_LONGS)) { - switch (__FDSET_LONGS) { - case 16: - tmp[12] = 0; tmp[13] = 0; tmp[14] = 0; tmp[15] = 0; - tmp[ 8] = 0; tmp[ 9] = 0; tmp[10] = 0; tmp[11] = 0; - - case 8: - tmp[ 4] = 0; tmp[ 5] = 0; tmp[ 6] = 0; tmp[ 7] = 0; - - case 4: - tmp[ 0] = 0; tmp[ 1] = 0; tmp[ 2] = 0; tmp[ 3] = 0; - return; - } - } - i = __FDSET_LONGS; - while (i) { - i--; - *tmp = 0; - tmp++; - } -} - -#endif /* defined(__KERNEL__) || !defined(__GLIBC__) || (__GLIBC__ < 2) */ -#endif /* __GNUC__ */ -#endif /* _PPC64_POSIX_TYPES_H */ From kumar.gala at freescale.com Tue Sep 20 00:29:50 2005 From: kumar.gala at freescale.com (Kumar Gala) Date: Mon, 19 Sep 2005 09:29:50 -0500 Subject: Git tree for the 32/64 merge In-Reply-To: <17197.65270.548340.377011@cargo.ozlabs.ibm.com> References: <17197.65270.548340.377011@cargo.ozlabs.ibm.com> Message-ID: On Sep 18, 2005, at 6:57 PM, Paul Mackerras wrote: > I have created a git tree on kernel.org as a place to accumulate the > patches for the ppc32/ppc64 merge. It is at: > > rsync://rsync.kernel.org/pub/scm/linux/kernel/git/paulus/powerpc- > merge.g > it > > It doesn't include the objects in Linus' tree; instead it has an > objects/info/alternates file pointing to Linus' tree. > > This tree contains all the patches I found in a scan through my inbox > that relate to the merge and haven't already gone to Linus. If you > have a patch that should go in, please resend it. Paul, You pulled the wrong version of the Kconfig patch for prep/chrp/ pmac. There is a newer version that doesn't leave duplicated 'bool's in the Kconfig: http://patchwork.ozlabs.org/linuxppc/patch?id=2447 - kumar From galak at freescale.com Tue Sep 20 00:30:27 2005 From: galak at freescale.com (Kumar Gala) Date: Mon, 19 Sep 2005 09:30:27 -0500 (CDT) Subject: [PATCH] powerpc: unified signature of timer_interrupt() between ppc32/ppc64 Message-ID: On ppc64 timer_interrupt() returned a value that was never used. Changed the ppc64 version of timer_interrupt() to no longer return a value so that the signatures between ppc32 & ppc64 match. This will simplify future merging of arch/powerpc. Signed-off-by: Kumar Gala --- commit 10b5180d0bd68bd485b2c93df22bbd094a9e0a2b tree d51d9c7b17f62fdd7741c44be6207b2bcb449fc0 parent 9df7c83f98a5479a1614cc77d138820a47a062ca author Kumar K. Gala Wed, 14 Sep 2005 14:56:42 -0500 committer Kumar K. Gala Wed, 14 Sep 2005 14:56:42 -0500 arch/ppc64/kernel/time.c | 4 +--- include/asm-ppc64/hw_irq.h | 2 +- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/arch/ppc64/kernel/time.c b/arch/ppc64/kernel/time.c --- a/arch/ppc64/kernel/time.c +++ b/arch/ppc64/kernel/time.c @@ -319,7 +319,7 @@ unsigned long tb_last_stamp __cacheline_ * timer_interrupt - gets called when the decrementer overflows, * with interrupts disabled. */ -int timer_interrupt(struct pt_regs * regs) +void timer_interrupt(struct pt_regs * regs) { int next_dec; unsigned long cur_tb; @@ -377,8 +377,6 @@ int timer_interrupt(struct pt_regs * reg } irq_exit(); - - return 1; } /* diff --git a/include/asm-ppc64/hw_irq.h b/include/asm-ppc64/hw_irq.h --- a/include/asm-ppc64/hw_irq.h +++ b/include/asm-ppc64/hw_irq.h @@ -16,7 +16,7 @@ #include #include -int timer_interrupt(struct pt_regs *); +extern void timer_interrupt(struct pt_regs *); extern void ppc_irq_dispatch_handler(struct pt_regs *regs, int irq); #ifdef CONFIG_PPC_ISERIES From linuxppc at jdl.com Tue Sep 20 00:32:07 2005 From: linuxppc at jdl.com (linuxppc at jdl.com) Date: Mon, 19 Sep 2005 09:32:07 -0500 Subject: PATCH powerpc: Revised merge asm-ppc*/hardirq.h Message-ID: This is a revised patch to merge asm-ppc*/hardirq.h. It removes some unnecessary #includes, but then requires the addition of #include in PPC32's hw_irq.h much like ppc64 already does. Furthermore, several unnecessary #includes were removed from some ppc32 boards in order to break resulting bad #include cycles. Builds pSeries_defconfig and all ppc32 platforms except the already b0rken bseip. Signed-off-by: Jon Loeliger Signed-off-by: Kumar Gala --- arch/ppc/platforms/83xx/mpc834x_sys.h | 1 - arch/ppc/platforms/85xx/mpc85xx_ads_common.h | 1 - arch/ppc/platforms/85xx/stx_gp3.h | 1 - include/asm-powerpc/hardirq.h | 24 ++++++++++++++++++++ include/asm-ppc/hardirq.h | 31 -------------------------- include/asm-ppc/hw_irq.h | 1 + include/asm-ppc64/hardirq.h | 27 ----------------------- 7 files changed, 25 insertions(+), 61 deletions(-) diff --git a/arch/ppc/platforms/83xx/mpc834x_sys.h b/arch/ppc/platforms/83xx/mpc834x_sys.h --- a/arch/ppc/platforms/83xx/mpc834x_sys.h +++ b/arch/ppc/platforms/83xx/mpc834x_sys.h @@ -19,7 +19,6 @@ #include #include -#include #include #include diff --git a/arch/ppc/platforms/85xx/mpc85xx_ads_common.h b/arch/ppc/platforms/85xx/mpc85xx_ads_common.h --- a/arch/ppc/platforms/85xx/mpc85xx_ads_common.h +++ b/arch/ppc/platforms/85xx/mpc85xx_ads_common.h @@ -19,7 +19,6 @@ #include #include -#include #include #define BOARD_CCSRBAR ((uint)0xe0000000) diff --git a/arch/ppc/platforms/85xx/stx_gp3.h b/arch/ppc/platforms/85xx/stx_gp3.h --- a/arch/ppc/platforms/85xx/stx_gp3.h +++ b/arch/ppc/platforms/85xx/stx_gp3.h @@ -21,7 +21,6 @@ #include #include -#include #include #define BOARD_CCSRBAR ((uint)0xe0000000) diff --git a/include/asm-powerpc/hardirq.h b/include/asm-powerpc/hardirq.h new file mode 100644 --- /dev/null +++ b/include/asm-powerpc/hardirq.h @@ -0,0 +1,24 @@ +#ifndef _ASM_POWERPC_HARDIRQ_H +#define _ASM_POWERPC_HARDIRQ_H + +/* The __last_jiffy_stamp field is needed to ensure that no decrementer + * interrupt is lost on SMP machines. Since on most CPUs it is in the same + * cache line as local_irq_count, it is cheap to access and is also used on UP + * for uniformity. + */ +typedef struct { + unsigned int __softirq_pending; /* set_bit is used on this */ + unsigned int __last_jiffy_stamp; +} ____cacheline_aligned irq_cpustat_t; + +#include /* Standard mappings for irq_cpustat_t above */ + +#define last_jiffy_stamp(cpu) __IRQ_STAT((cpu), __last_jiffy_stamp) + +static inline void ack_bad_irq(int irq) +{ + printk(KERN_CRIT "illegal vector %d received!\n", irq); + BUG(); +} + +#endif /* _ASM_POWERPC_HARDIRQ_H */ diff --git a/include/asm-ppc/hardirq.h b/include/asm-ppc/hardirq.h deleted file mode 100644 --- a/include/asm-ppc/hardirq.h +++ /dev/null @@ -1,31 +0,0 @@ -#ifdef __KERNEL__ -#ifndef __ASM_HARDIRQ_H -#define __ASM_HARDIRQ_H - -#include -#include -#include -#include - -/* The __last_jiffy_stamp field is needed to ensure that no decrementer - * interrupt is lost on SMP machines. Since on most CPUs it is in the same - * cache line as local_irq_count, it is cheap to access and is also used on UP - * for uniformity. - */ -typedef struct { - unsigned long __softirq_pending; /* set_bit is used on this */ - unsigned int __last_jiffy_stamp; -} ____cacheline_aligned irq_cpustat_t; - -#include /* Standard mappings for irq_cpustat_t above */ - -#define last_jiffy_stamp(cpu) __IRQ_STAT((cpu), __last_jiffy_stamp) - -static inline void ack_bad_irq(int irq) -{ - printk(KERN_CRIT "illegal vector %d received!\n", irq); - BUG(); -} - -#endif /* __ASM_HARDIRQ_H */ -#endif /* __KERNEL__ */ diff --git a/include/asm-ppc/hw_irq.h b/include/asm-ppc/hw_irq.h --- a/include/asm-ppc/hw_irq.h +++ b/include/asm-ppc/hw_irq.h @@ -7,6 +7,7 @@ #include #include +#include extern void timer_interrupt(struct pt_regs *); diff --git a/include/asm-ppc64/hardirq.h b/include/asm-ppc64/hardirq.h deleted file mode 100644 --- a/include/asm-ppc64/hardirq.h +++ /dev/null @@ -1,27 +0,0 @@ -#ifndef __ASM_HARDIRQ_H -#define __ASM_HARDIRQ_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 -#include - -typedef struct { - unsigned int __softirq_pending; -} ____cacheline_aligned irq_cpustat_t; - -#include /* Standard mappings for irq_cpustat_t above */ - -static inline void ack_bad_irq(int irq) -{ - printk(KERN_CRIT "illegal vector %d received!\n", irq); - BUG(); -} - -#endif /* __ASM_HARDIRQ_H */ From jonaris0 at tsamail.co.za Mon Sep 19 08:25:30 2005 From: jonaris0 at tsamail.co.za (jonaris0) Date: Mon, 19 Sep 05 08:25:30 Pacific Standard Time Subject: HELLO Message-ID: <20050919153140.2753E6832C@ozlabs.org> Hello, My name is Col(Rtd) Jon Aristide,brother to the exiled President of Haiti,(Dr.Jean Bertrand Aristide) Due to the evolution against the government of my brother caused by his political opponents in Haiti,we managed to enter a red cross airplane that was evacuating foreigners and we are presently on political assylum in Central African Repubilc(CAR) I wish to invest in Real Estate and commercial Properties and equally start a new life in your country with your assistance and cooperation.If you are in a good position to help my family,please send an e-mail to my personal address below indicating your desire to help meinvest this funds in your country and beyond. I urgently await your e-mail letter. Reply to my confidential mail box: jonaris05 at yahoo.com Best Regards and hope to meet you soon. God bless, Col Jon(Rtd). From jonaris0 at tsamail.co.za Mon Sep 19 10:17:48 2005 From: jonaris0 at tsamail.co.za (jonaris0) Date: Mon, 19 Sep 05 10:17:48 Pacific Standard Time Subject: HELLO Message-ID: <20050919172520.62B3B6832C@ozlabs.org> Hello, My name is Col(Rtd) Jon Aristide,brother to the exiled President of Haiti,(Dr.Jean Bertrand Aristide) Due to the evolution against the government of my brother caused by his political opponents in Haiti,we managed to enter a red cross airplane that was evacuating foreigners and we are presently on political assylum in Central African Repubilc(CAR) I wish to invest in Real Estate and commercial Properties and equally start a new life in your country with your assistance and cooperation.If you are in a good position to help my family,please send an e-mail to my personal address below indicating your desire to help meinvest this funds in your country and beyond. I urgently await your e-mail letter. Reply to my confidential mail box: jonaris05 at yahoo.com Best Regards and hope to meet you soon. God bless, Col Jon(Rtd). From jdl at jdl.com Tue Sep 20 06:29:42 2005 From: jdl at jdl.com (Jon Loeliger) Date: Mon, 19 Sep 2005 15:29:42 -0500 Subject: PATCH powerpc Merge atomic.h Message-ID: Paul, There is also Arnd's patch called "[PATCH 0/3] Start the merge" from 08/29 that is really the merger of asm-ppc*/atomic.h. I repost it here for Arnd, who can NAK it or not. It is a pre-requisite patch for doing the rwsem.h merge as discussed recently. jdl This is another patch to merge the atomic.h file. It is not completely trivial and changes the semantics for 32 bit SMP systems, which previously did not do EIEIO_ON_SMP within the atomic operations. AFAICT, that was a bug in the 32 bit version, which is now fixed as a side-effect of the merge. The combined version of this file also prevents building user space applications using atomic.h on ppc64. That was already impossible on 32 bit ppc, but probably also created broken output on ppc64. Signed-off-by: Arnd Bergmann -- include/asm-ppc/atomic.h | 214 ------------------------------ include/asm-ppc64/atomic.h | 197 --------------------------- include/asm-ppc64/memory.h | 59 -------- linux-2.6.12/include/asm-powerpc/atomic.h | 209 +++++++++++++++++++++++++++++ linux-2.6.12/include/asm-powerpc/memory.h | 59 ++++++++ linux-2.6.12/include/asm-ppc/io.h | 11 - 6 files changed, 269 insertions(+), 480 deletions(-) Index: linux-2.6.12/include/asm-ppc/atomic.h =================================================================== --- linux-2.6.12.orig/include/asm-ppc/atomic.h 2005-08-29 08:04:06.000000000 +0200 +++ /dev/null 1970-01-01 00:00:00.000000000 +0000 @@ -1,214 +0,0 @@ -/* - * PowerPC atomic operations - */ - -#ifndef _ASM_PPC_ATOMIC_H_ -#define _ASM_PPC_ATOMIC_H_ - -typedef struct { volatile int counter; } atomic_t; - -#ifdef __KERNEL__ - -#define ATOMIC_INIT(i) { (i) } - -#define atomic_read(v) ((v)->counter) -#define atomic_set(v,i) (((v)->counter) = (i)) - -extern void atomic_clear_mask(unsigned long mask, unsigned long *addr); - -#ifdef CONFIG_SMP -#define SMP_SYNC "sync" -#define SMP_ISYNC "\n\tisync" -#else -#define SMP_SYNC "" -#define SMP_ISYNC -#endif - -/* Erratum #77 on the 405 means we need a sync or dcbt before every stwcx. - * The old ATOMIC_SYNC_FIX covered some but not all of this. - */ -#ifdef CONFIG_IBM405_ERR77 -#define PPC405_ERR77(ra,rb) "dcbt " #ra "," #rb ";" -#else -#define PPC405_ERR77(ra,rb) -#endif - -static __inline__ void atomic_add(int a, atomic_t *v) -{ - int t; - - __asm__ __volatile__( -"1: lwarx %0,0,%3 # atomic_add\n\ - add %0,%2,%0\n" - PPC405_ERR77(0,%3) -" stwcx. %0,0,%3 \n\ - bne- 1b" - : "=&r" (t), "=m" (v->counter) - : "r" (a), "r" (&v->counter), "m" (v->counter) - : "cc"); -} - -static __inline__ int atomic_add_return(int a, atomic_t *v) -{ - int t; - - __asm__ __volatile__( -"1: lwarx %0,0,%2 # atomic_add_return\n\ - add %0,%1,%0\n" - PPC405_ERR77(0,%2) -" stwcx. %0,0,%2 \n\ - bne- 1b" - SMP_ISYNC - : "=&r" (t) - : "r" (a), "r" (&v->counter) - : "cc", "memory"); - - return t; -} - -#define atomic_add_negative(a, v) (atomic_add_return((a), (v)) < 0) - -static __inline__ void atomic_sub(int a, atomic_t *v) -{ - int t; - - __asm__ __volatile__( -"1: lwarx %0,0,%3 # atomic_sub\n\ - subf %0,%2,%0\n" - PPC405_ERR77(0,%3) -" stwcx. %0,0,%3 \n\ - bne- 1b" - : "=&r" (t), "=m" (v->counter) - : "r" (a), "r" (&v->counter), "m" (v->counter) - : "cc"); -} - -static __inline__ int atomic_sub_return(int a, atomic_t *v) -{ - int t; - - __asm__ __volatile__( -"1: lwarx %0,0,%2 # atomic_sub_return\n\ - subf %0,%1,%0\n" - PPC405_ERR77(0,%2) -" stwcx. %0,0,%2 \n\ - bne- 1b" - SMP_ISYNC - : "=&r" (t) - : "r" (a), "r" (&v->counter) - : "cc", "memory"); - - return t; -} - -static __inline__ void atomic_inc(atomic_t *v) -{ - int t; - - __asm__ __volatile__( -"1: lwarx %0,0,%2 # atomic_inc\n\ - addic %0,%0,1\n" - PPC405_ERR77(0,%2) -" stwcx. %0,0,%2 \n\ - bne- 1b" - : "=&r" (t), "=m" (v->counter) - : "r" (&v->counter), "m" (v->counter) - : "cc"); -} - -static __inline__ int atomic_inc_return(atomic_t *v) -{ - int t; - - __asm__ __volatile__( -"1: lwarx %0,0,%1 # atomic_inc_return\n\ - addic %0,%0,1\n" - PPC405_ERR77(0,%1) -" stwcx. %0,0,%1 \n\ - bne- 1b" - SMP_ISYNC - : "=&r" (t) - : "r" (&v->counter) - : "cc", "memory"); - - return t; -} - -/* - * atomic_inc_and_test - increment and test - * @v: pointer of type atomic_t - * - * Atomically increments @v by 1 - * and returns true if the result is zero, or false for all - * other cases. - */ -#define atomic_inc_and_test(v) (atomic_inc_return(v) == 0) - -static __inline__ void atomic_dec(atomic_t *v) -{ - int t; - - __asm__ __volatile__( -"1: lwarx %0,0,%2 # atomic_dec\n\ - addic %0,%0,-1\n" - PPC405_ERR77(0,%2)\ -" stwcx. %0,0,%2\n\ - bne- 1b" - : "=&r" (t), "=m" (v->counter) - : "r" (&v->counter), "m" (v->counter) - : "cc"); -} - -static __inline__ int atomic_dec_return(atomic_t *v) -{ - int t; - - __asm__ __volatile__( -"1: lwarx %0,0,%1 # atomic_dec_return\n\ - addic %0,%0,-1\n" - PPC405_ERR77(0,%1) -" stwcx. %0,0,%1\n\ - bne- 1b" - SMP_ISYNC - : "=&r" (t) - : "r" (&v->counter) - : "cc", "memory"); - - return t; -} - -#define atomic_sub_and_test(a, v) (atomic_sub_return((a), (v)) == 0) -#define atomic_dec_and_test(v) (atomic_dec_return((v)) == 0) - -/* - * Atomically test *v and decrement if it is greater than 0. - * The function returns the old value of *v minus 1. - */ -static __inline__ int atomic_dec_if_positive(atomic_t *v) -{ - int t; - - __asm__ __volatile__( -"1: lwarx %0,0,%1 # atomic_dec_if_positive\n\ - addic. %0,%0,-1\n\ - blt- 2f\n" - PPC405_ERR77(0,%1) -" stwcx. %0,0,%1\n\ - bne- 1b" - SMP_ISYNC - "\n\ -2:" : "=&r" (t) - : "r" (&v->counter) - : "cc", "memory"); - - return t; -} - -#define __MB __asm__ __volatile__ (SMP_SYNC : : : "memory") -#define smp_mb__before_atomic_dec() __MB -#define smp_mb__after_atomic_dec() __MB -#define smp_mb__before_atomic_inc() __MB -#define smp_mb__after_atomic_inc() __MB - -#endif /* __KERNEL__ */ -#endif /* _ASM_PPC_ATOMIC_H_ */ Index: linux-2.6.12/include/asm-ppc64/memory.h =================================================================== --- linux-2.6.12.orig/include/asm-ppc64/memory.h 2005-08-29 08:04:06.000000000 +0200 +++ /dev/null 1970-01-01 00:00:00.000000000 +0000 @@ -1,59 +0,0 @@ -#ifndef _ASM_POWERPC_MEMORY_H_ -#define _ASM_POWERPC_MEMORY_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 - -/* - * Arguably the bitops and *xchg operations don't imply any memory barrier - * or SMP ordering, but in fact a lot of drivers expect them to imply - * both, since they do on x86 cpus. - */ -#ifdef CONFIG_SMP -#define EIEIO_ON_SMP "eieio\n" -#define ISYNC_ON_SMP "\n\tisync" -#else -#define EIEIO_ON_SMP -#define ISYNC_ON_SMP -#endif - -static inline void eieio(void) -{ - __asm__ __volatile__ ("eieio" : : : "memory"); -} - -static inline void isync(void) -{ - __asm__ __volatile__ ("isync" : : : "memory"); -} - -#ifdef CONFIG_SMP -#define eieio_on_smp() eieio() -#define isync_on_smp() isync() -#else -#define eieio_on_smp() __asm__ __volatile__("": : :"memory") -#define isync_on_smp() __asm__ __volatile__("": : :"memory") -#endif - -/* Macros for adjusting thread priority (hardware multi-threading) */ -#define HMT_very_low() asm volatile("or 31,31,31 # very low priority") -#define HMT_low() asm volatile("or 1,1,1 # low priority") -#define HMT_medium_low() asm volatile("or 6,6,6 # medium low priority") -#define HMT_medium() asm volatile("or 2,2,2 # medium priority") -#define HMT_medium_high() asm volatile("or 5,5,5 # medium high priority") -#define HMT_high() asm volatile("or 3,3,3 # high priority") - -#define HMT_VERY_LOW "\tor 31,31,31 # very low priority\n" -#define HMT_LOW "\tor 1,1,1 # low priority\n" -#define HMT_MEDIUM_LOW "\tor 6,6,6 # medium low priority\n" -#define HMT_MEDIUM "\tor 2,2,2 # medium priority\n" -#define HMT_MEDIUM_HIGH "\tor 5,5,5 # medium high priority\n" -#define HMT_HIGH "\tor 3,3,3 # high priority\n" - -#endif Index: linux-2.6.12/include/asm-ppc/io.h =================================================================== --- linux-2.6.12.orig/include/asm-ppc/io.h 2005-08-29 08:04:06.000000000 +0200 +++ linux-2.6.12/include/asm-ppc/io.h 2005-08-29 08:04:26.000000000 +0200 @@ -8,6 +8,7 @@ #include #include +#include #include #define SIO_CONFIG_RA 0x398 @@ -440,16 +441,6 @@ #define page_to_phys(page) (page_to_pfn(page) << PAGE_SHIFT) #define page_to_bus(page) (page_to_phys(page) + PCI_DRAM_OFFSET) -/* - * Enforce In-order Execution of I/O: - * Acts as a barrier to ensure all previous I/O accesses have - * completed before any further ones are issued. - */ -extern inline void eieio(void) -{ - __asm__ __volatile__ ("eieio" : : : "memory"); -} - /* Enforce in-order execution of data I/O. * No distinction between read/write on PPC; use eieio for all three. */ Index: linux-2.6.12/include/asm-ppc64/atomic.h =================================================================== --- linux-2.6.12.orig/include/asm-ppc64/atomic.h 2005-08-29 08:04:06.000000000 +0200 +++ /dev/null 1970-01-01 00:00:00.000000000 +0000 @@ -1,197 +0,0 @@ -/* - * PowerPC64 atomic operations - * - * Copyright (C) 2001 Paul Mackerras , IBM - * Copyright (C) 2001 Anton Blanchard , IBM - * - * 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_ATOMIC_H_ -#define _ASM_PPC64_ATOMIC_H_ - -#include - -typedef struct { volatile int counter; } atomic_t; - -#define ATOMIC_INIT(i) { (i) } - -#define atomic_read(v) ((v)->counter) -#define atomic_set(v,i) (((v)->counter) = (i)) - -static __inline__ void atomic_add(int a, atomic_t *v) -{ - int t; - - __asm__ __volatile__( -"1: lwarx %0,0,%3 # atomic_add\n\ - add %0,%2,%0\n\ - stwcx. %0,0,%3\n\ - bne- 1b" - : "=&r" (t), "=m" (v->counter) - : "r" (a), "r" (&v->counter), "m" (v->counter) - : "cc"); -} - -static __inline__ int atomic_add_return(int a, atomic_t *v) -{ - int t; - - __asm__ __volatile__( - EIEIO_ON_SMP -"1: lwarx %0,0,%2 # atomic_add_return\n\ - add %0,%1,%0\n\ - stwcx. %0,0,%2\n\ - bne- 1b" - ISYNC_ON_SMP - : "=&r" (t) - : "r" (a), "r" (&v->counter) - : "cc", "memory"); - - return t; -} - -#define atomic_add_negative(a, v) (atomic_add_return((a), (v)) < 0) - -static __inline__ void atomic_sub(int a, atomic_t *v) -{ - int t; - - __asm__ __volatile__( -"1: lwarx %0,0,%3 # atomic_sub\n\ - subf %0,%2,%0\n\ - stwcx. %0,0,%3\n\ - bne- 1b" - : "=&r" (t), "=m" (v->counter) - : "r" (a), "r" (&v->counter), "m" (v->counter) - : "cc"); -} - -static __inline__ int atomic_sub_return(int a, atomic_t *v) -{ - int t; - - __asm__ __volatile__( - EIEIO_ON_SMP -"1: lwarx %0,0,%2 # atomic_sub_return\n\ - subf %0,%1,%0\n\ - stwcx. %0,0,%2\n\ - bne- 1b" - ISYNC_ON_SMP - : "=&r" (t) - : "r" (a), "r" (&v->counter) - : "cc", "memory"); - - return t; -} - -static __inline__ void atomic_inc(atomic_t *v) -{ - int t; - - __asm__ __volatile__( -"1: lwarx %0,0,%2 # atomic_inc\n\ - addic %0,%0,1\n\ - stwcx. %0,0,%2\n\ - bne- 1b" - : "=&r" (t), "=m" (v->counter) - : "r" (&v->counter), "m" (v->counter) - : "cc"); -} - -static __inline__ int atomic_inc_return(atomic_t *v) -{ - int t; - - __asm__ __volatile__( - EIEIO_ON_SMP -"1: lwarx %0,0,%1 # atomic_inc_return\n\ - addic %0,%0,1\n\ - stwcx. %0,0,%1\n\ - bne- 1b" - ISYNC_ON_SMP - : "=&r" (t) - : "r" (&v->counter) - : "cc", "memory"); - - return t; -} - -/* - * atomic_inc_and_test - increment and test - * @v: pointer of type atomic_t - * - * Atomically increments @v by 1 - * and returns true if the result is zero, or false for all - * other cases. - */ -#define atomic_inc_and_test(v) (atomic_inc_return(v) == 0) - -static __inline__ void atomic_dec(atomic_t *v) -{ - int t; - - __asm__ __volatile__( -"1: lwarx %0,0,%2 # atomic_dec\n\ - addic %0,%0,-1\n\ - stwcx. %0,0,%2\n\ - bne- 1b" - : "=&r" (t), "=m" (v->counter) - : "r" (&v->counter), "m" (v->counter) - : "cc"); -} - -static __inline__ int atomic_dec_return(atomic_t *v) -{ - int t; - - __asm__ __volatile__( - EIEIO_ON_SMP -"1: lwarx %0,0,%1 # atomic_dec_return\n\ - addic %0,%0,-1\n\ - stwcx. %0,0,%1\n\ - bne- 1b" - ISYNC_ON_SMP - : "=&r" (t) - : "r" (&v->counter) - : "cc", "memory"); - - return t; -} - -#define atomic_sub_and_test(a, v) (atomic_sub_return((a), (v)) == 0) -#define atomic_dec_and_test(v) (atomic_dec_return((v)) == 0) - -/* - * Atomically test *v and decrement if it is greater than 0. - * The function returns the old value of *v minus 1. - */ -static __inline__ int atomic_dec_if_positive(atomic_t *v) -{ - int t; - - __asm__ __volatile__( - EIEIO_ON_SMP -"1: lwarx %0,0,%1 # atomic_dec_if_positive\n\ - addic. %0,%0,-1\n\ - blt- 2f\n\ - stwcx. %0,0,%1\n\ - bne- 1b" - ISYNC_ON_SMP - "\n\ -2:" : "=&r" (t) - : "r" (&v->counter) - : "cc", "memory"); - - return t; -} - -#define smp_mb__before_atomic_dec() smp_mb() -#define smp_mb__after_atomic_dec() smp_mb() -#define smp_mb__before_atomic_inc() smp_mb() -#define smp_mb__after_atomic_inc() smp_mb() - -#endif /* _ASM_PPC64_ATOMIC_H_ */ Index: linux-2.6.12/include/asm-powerpc/memory.h =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ linux-2.6.12/include/asm-powerpc/memory.h 2005-08-29 08:04:26.000000000 +0200 @@ -0,0 +1,59 @@ +#ifndef _ASM_PPC64_MEMORY_H_ +#define _ASM_PPC64_MEMORY_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 + +/* + * Arguably the bitops and *xchg operations don't imply any memory barrier + * or SMP ordering, but in fact a lot of drivers expect them to imply + * both, since they do on x86 cpus. + */ +#ifdef CONFIG_SMP +#define EIEIO_ON_SMP "eieio\n" +#define ISYNC_ON_SMP "\n\tisync" +#else +#define EIEIO_ON_SMP +#define ISYNC_ON_SMP +#endif + +static inline void eieio(void) +{ + __asm__ __volatile__ ("eieio" : : : "memory"); +} + +static inline void isync(void) +{ + __asm__ __volatile__ ("isync" : : : "memory"); +} + +#ifdef CONFIG_SMP +#define eieio_on_smp() eieio() +#define isync_on_smp() isync() +#else +#define eieio_on_smp() __asm__ __volatile__("": : :"memory") +#define isync_on_smp() __asm__ __volatile__("": : :"memory") +#endif + +/* Macros for adjusting thread priority (hardware multi-threading) */ +#define HMT_very_low() asm volatile("or 31,31,31 # very low priority") +#define HMT_low() asm volatile("or 1,1,1 # low priority") +#define HMT_medium_low() asm volatile("or 6,6,6 # medium low priority") +#define HMT_medium() asm volatile("or 2,2,2 # medium priority") +#define HMT_medium_high() asm volatile("or 5,5,5 # medium high priority") +#define HMT_high() asm volatile("or 3,3,3 # high priority") + +#define HMT_VERY_LOW "\tor 31,31,31 # very low priority\n" +#define HMT_LOW "\tor 1,1,1 # low priority\n" +#define HMT_MEDIUM_LOW "\tor 6,6,6 # medium low priority\n" +#define HMT_MEDIUM "\tor 2,2,2 # medium priority\n" +#define HMT_MEDIUM_HIGH "\tor 5,5,5 # medium high priority\n" +#define HMT_HIGH "\tor 3,3,3 # high priority\n" + +#endif Index: linux-2.6.12/include/asm-powerpc/atomic.h =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ linux-2.6.12/include/asm-powerpc/atomic.h 2005-08-29 08:04:26.000000000 +0200 @@ -0,0 +1,209 @@ +/* + * PowerPC atomic operations + */ + +#ifndef _ASM_POWERPC_ATOMIC_H_ +#define _ASM_POWERPC_ATOMIC_H_ + +typedef struct { volatile int counter; } atomic_t; + +#ifdef __KERNEL__ +#include + +#define ATOMIC_INIT(i) { (i) } + +#define atomic_read(v) ((v)->counter) +#define atomic_set(v,i) (((v)->counter) = (i)) + +/* Erratum #77 on the 405 means we need a sync or dcbt before every stwcx. + * The old ATOMIC_SYNC_FIX covered some but not all of this. + */ +#ifdef CONFIG_IBM405_ERR77 +#define PPC405_ERR77(ra,rb) "dcbt " #ra "," #rb ";" +#else +#define PPC405_ERR77(ra,rb) +#endif + +static __inline__ void atomic_add(int a, atomic_t *v) +{ + int t; + + __asm__ __volatile__( +"1: lwarx %0,0,%3 # atomic_add\n\ + add %0,%2,%0\n" + PPC405_ERR77(0,%3) +" stwcx. %0,0,%3 \n\ + bne- 1b" + : "=&r" (t), "=m" (v->counter) + : "r" (a), "r" (&v->counter), "m" (v->counter) + : "cc"); +} + +static __inline__ int atomic_add_return(int a, atomic_t *v) +{ + int t; + + __asm__ __volatile__( + EIEIO_ON_SMP +"1: lwarx %0,0,%2 # atomic_add_return\n\ + add %0,%1,%0\n" + PPC405_ERR77(0,%2) +" stwcx. %0,0,%2 \n\ + bne- 1b" + ISYNC_ON_SMP + : "=&r" (t) + : "r" (a), "r" (&v->counter) + : "cc", "memory"); + + return t; +} + +#define atomic_add_negative(a, v) (atomic_add_return((a), (v)) < 0) + +static __inline__ void atomic_sub(int a, atomic_t *v) +{ + int t; + + __asm__ __volatile__( +"1: lwarx %0,0,%3 # atomic_sub\n\ + subf %0,%2,%0\n" + PPC405_ERR77(0,%3) +" stwcx. %0,0,%3 \n\ + bne- 1b" + : "=&r" (t), "=m" (v->counter) + : "r" (a), "r" (&v->counter), "m" (v->counter) + : "cc"); +} + +static __inline__ int atomic_sub_return(int a, atomic_t *v) +{ + int t; + + __asm__ __volatile__( + EIEIO_ON_SMP +"1: lwarx %0,0,%2 # atomic_sub_return\n\ + subf %0,%1,%0\n" + PPC405_ERR77(0,%2) +" stwcx. %0,0,%2 \n\ + bne- 1b" + ISYNC_ON_SMP + : "=&r" (t) + : "r" (a), "r" (&v->counter) + : "cc", "memory"); + + return t; +} + +static __inline__ void atomic_inc(atomic_t *v) +{ + int t; + + __asm__ __volatile__( +"1: lwarx %0,0,%2 # atomic_inc\n\ + addic %0,%0,1\n" + PPC405_ERR77(0,%2) +" stwcx. %0,0,%2 \n\ + bne- 1b" + : "=&r" (t), "=m" (v->counter) + : "r" (&v->counter), "m" (v->counter) + : "cc"); +} + +static __inline__ int atomic_inc_return(atomic_t *v) +{ + int t; + + __asm__ __volatile__( + EIEIO_ON_SMP +"1: lwarx %0,0,%1 # atomic_inc_return\n\ + addic %0,%0,1\n" + PPC405_ERR77(0,%1) +" stwcx. %0,0,%1 \n\ + bne- 1b" + ISYNC_ON_SMP + : "=&r" (t) + : "r" (&v->counter) + : "cc", "memory"); + + return t; +} + +/* + * atomic_inc_and_test - increment and test + * @v: pointer of type atomic_t + * + * Atomically increments @v by 1 + * and returns true if the result is zero, or false for all + * other cases. + */ +#define atomic_inc_and_test(v) (atomic_inc_return(v) == 0) + +static __inline__ void atomic_dec(atomic_t *v) +{ + int t; + + __asm__ __volatile__( +"1: lwarx %0,0,%2 # atomic_dec\n\ + addic %0,%0,-1\n" + PPC405_ERR77(0,%2)\ +" stwcx. %0,0,%2\n\ + bne- 1b" + : "=&r" (t), "=m" (v->counter) + : "r" (&v->counter), "m" (v->counter) + : "cc"); +} + +static __inline__ int atomic_dec_return(atomic_t *v) +{ + int t; + + __asm__ __volatile__( + EIEIO_ON_SMP +"1: lwarx %0,0,%1 # atomic_dec_return\n\ + addic %0,%0,-1\n" + PPC405_ERR77(0,%1) +" stwcx. %0,0,%1\n\ + bne- 1b" + ISYNC_ON_SMP + : "=&r" (t) + : "r" (&v->counter) + : "cc", "memory"); + + return t; +} + +#define atomic_sub_and_test(a, v) (atomic_sub_return((a), (v)) == 0) +#define atomic_dec_and_test(v) (atomic_dec_return((v)) == 0) + +/* + * Atomically test *v and decrement if it is greater than 0. + * The function returns the old value of *v minus 1. + */ +static __inline__ int atomic_dec_if_positive(atomic_t *v) +{ + int t; + + __asm__ __volatile__( + EIEIO_ON_SMP +"1: lwarx %0,0,%1 # atomic_dec_if_positive\n\ + addic. %0,%0,-1\n\ + blt- 2f\n" + PPC405_ERR77(0,%1) +" stwcx. %0,0,%1\n\ + bne- 1b" + ISYNC_ON_SMP + "\n\ +2:" : "=&r" (t) + : "r" (&v->counter) + : "cc", "memory"); + + return t; +} + +#define smp_mb__before_atomic_dec() smp_mb() +#define smp_mb__after_atomic_dec() smp_mb() +#define smp_mb__before_atomic_inc() smp_mb() +#define smp_mb__after_atomic_inc() smp_mb() + +#endif /* __KERNEL__ */ +#endif /* _ASM_POWERPC_ATOMIC_H_ */ From jdl at jdl.com Tue Sep 20 06:52:39 2005 From: jdl at jdl.com (Jon Loeliger) Date: Mon, 19 Sep 2005 15:52:39 -0500 Subject: PATCH powerpc Merge atomic.h In-Reply-To: Your message of "Mon, 19 Sep 2005 15:29:42 CDT." References: Message-ID: So, like, the other day Jon Loeliger mumbled: > Paul, > > There is also Arnd's patch called "[PATCH 0/3] Start the merge" > from 08/29 that is really the merger of asm-ppc*/atomic.h. > > I repost it here for Arnd, who can NAK it or not. Arrrg! Scurvey dogs! Ye cannt even squeek by repostin' old patches today. Run it out the gang-plank and flush the rotten thing! Someone needs a floggin' til this applies properly. Memory.h be damned. You'll be needin' two-patches iffin you don't watcherself. jdl From sexton at mc.com Tue Sep 20 07:45:23 2005 From: sexton at mc.com (Sexton, Matt) Date: Mon, 19 Sep 2005 17:45:23 -0400 Subject: Problem with DMAing into hugetlb pages on ppc64 Message-ID: <92CB67C83EE773499A7F2F6EA7E3FC940F0E9B@ad-email1.ad.mc.com> Hi all, I originally posed this question on lkml and am reposting a slightly modified version here. On a ppc64 platform running 2.6.13-1, I'm having trouble with an IO device DMAing into a memory buffer allocated by mmap'ing a hugetlbfs file and whose physical addresses were determined by calling get_user_pages(). The DMAed data often show up in the wrong 16MB page. Specifically, I have written a driver for a PCI device that writes data into a user-allocated memory buffer. The user passes the virtual address of the buffer to the driver, which calls get_user_pages() to lock the pages and to get the page information in order to be able to build a scatter list of contiguous physical blocks to pass to the DMA engine on the device. The device then writes a known pattern to the buffer, which the user space program can verify. This process works fine on ia32 and ppc64 using malloc'ed memory. This process also works fine on ia32 when obtaining the memory by mmap'ing a file on a hugetlbfs filesystem. The huge pages [2MB in the case of ia32] are used to reduce the number of entries in the scatter list. The process doesn't work so well on ppc64 with hugetlbfs (and 16MB pages). Often, the data is written to the wrong 16MB pages, from the perspective of the user space program. The data is correct within a 16MB page - it's just written to the wrong page. Perhaps the wrong physical address is returned by get_user_pages()? Or perhaps there is some inconsistency between get_user_pages() and mmap()? [I did receive one response with test results that indicated this was not the case.] Any suggestions on what I could be doing wrong in this specific case? Any known problems with the kernel in this case? Please CC me on any replies. Thanks, Matt From bgill at freescale.com Tue Sep 20 08:01:54 2005 From: bgill at freescale.com (Becky Bruce) Date: Mon, 19 Sep 2005 17:01:54 -0500 (CDT) Subject: [PATCH] powerpc Merge bug.h Message-ID: Resending per Paul's request..... ppc32/ppc64: Merge bug.h into include/asm-powerpc This patch merges bug.h into include/asm-powerpc. Changed the data structure for bug_entry such that line is always an int on both 32 and 64-bit platforms; removed casts to int from the 64-bit trap code to reflect this. Signed-off-by: Kumar Gala Signed-off-by: Becky Bruce --- commit fcaf8560dc918048b43867d79efa5b26bd6a9a81 tree 079802fdb229c0e3721b893235e2ef912e30d7cd parent dfe2ac4994952cadc891f095668f9e582d4402b3 author Becky Bruce Fri, 09 Sep 2005 11:15:22 -0500 committer Becky Bruce Fri, 09 Sep 2005 11:15:22 -0500 arch/ppc/kernel/traps.c | 2 + arch/ppc64/kernel/traps.c | 4 +- include/asm-powerpc/bug.h | 81 +++++++++++++++++++++++++++++++++++++++++++++ include/asm-ppc/bug.h | 58 -------------------------------- include/asm-ppc64/bug.h | 69 -------------------------------------- 5 files changed, 84 insertions(+), 130 deletions(-) diff --git a/arch/ppc/kernel/traps.c b/arch/ppc/kernel/traps.c --- a/arch/ppc/kernel/traps.c +++ b/arch/ppc/kernel/traps.c @@ -553,7 +553,7 @@ extern struct bug_entry __start___bug_ta #define module_find_bug(x) NULL #endif -static struct bug_entry *find_bug(unsigned long bugaddr) +struct bug_entry *find_bug(unsigned long bugaddr) { struct bug_entry *bug; diff --git a/arch/ppc64/kernel/traps.c b/arch/ppc64/kernel/traps.c --- a/arch/ppc64/kernel/traps.c +++ b/arch/ppc64/kernel/traps.c @@ -389,12 +389,12 @@ check_bug_trap(struct pt_regs *regs) /* this is a WARN_ON rather than BUG/BUG_ON */ printk(KERN_ERR "Badness in %s at %s:%d\n", bug->function, bug->file, - (unsigned int)bug->line & ~BUG_WARNING_TRAP); + bug->line & ~BUG_WARNING_TRAP); show_stack(current, (void *)regs->gpr[1]); return 1; } printk(KERN_CRIT "kernel BUG in %s at %s:%d!\n", - bug->function, bug->file, (unsigned int)bug->line); + bug->function, bug->file, bug->line); return 0; } diff --git a/include/asm-powerpc/bug.h b/include/asm-powerpc/bug.h new file mode 100644 --- /dev/null +++ b/include/asm-powerpc/bug.h @@ -0,0 +1,81 @@ +#ifndef _ASM_POWERPC_BUG_H +#define _ASM_POWERPC_BUG_H + +/* + * Define an illegal instr to trap on the bug. + * We don't use 0 because that marks the end of a function + * in the ELF ABI. That's "Boo Boo" in case you wonder... + */ +#define BUG_OPCODE .long 0x00b00b00 /* For asm */ +#define BUG_ILLEGAL_INSTR "0x00b00b00" /* For BUG macro */ + +#ifndef __ASSEMBLY__ + +#ifdef __powerpc64__ +#define BUG_TABLE_ENTRY(label, line, file, func) \ + ".llong " #label "\n .long " #line "\n .llong " #file ", " #func "\n" +#define TRAP_OP(ra, rb) "1: tdnei " #ra ", " #rb "\n" +#define DATA_TYPE long long +#else +#define BUG_TABLE_ENTRY(label, line, file, func) \ + ".long " #label ", " #line ", " #file ", " #func "\n" +#define TRAP_OP(ra, rb) "1: twnei " #ra ", " #rb "\n" +#define DATA_TYPE int +#endif /* __powerpc64__ */ + +struct bug_entry { + unsigned long bug_addr; + int line; + const char *file; + const char *function; +}; + +struct bug_entry *find_bug(unsigned long bugaddr); + +/* + * If this bit is set in the line number it means that the trap + * is for WARN_ON rather than BUG or BUG_ON. + */ +#define BUG_WARNING_TRAP 0x1000000 + +#ifdef CONFIG_BUG + +#define BUG() do { \ + __asm__ __volatile__( \ + "1: twi 31,0,0\n" \ + ".section __bug_table,\"a\"\n\t" \ + BUG_TABLE_ENTRY(1b,%0,%1,%2) \ + ".previous" \ + : : "i" (__LINE__), "i" (__FILE__), "i" (__FUNCTION__)); \ +} while (0) + +#define BUG_ON(x) do { \ + __asm__ __volatile__( \ + TRAP_OP(%0,0) \ + ".section __bug_table,\"a\"\n\t" \ + BUG_TABLE_ENTRY(1b,%1,%2,%3) \ + ".previous" \ + : : "r" ((DATA_TYPE)(x)), "i" (__LINE__), \ + "i" (__FILE__), "i" (__FUNCTION__)); \ +} while (0) + +#define WARN_ON(x) do { \ + __asm__ __volatile__( \ + TRAP_OP(%0,0) \ + ".section __bug_table,\"a\"\n\t" \ + BUG_TABLE_ENTRY(1b,%1,%2,%3) \ + ".previous" \ + : : "r" ((DATA_TYPE)(x)), \ + "i" (__LINE__ + BUG_WARNING_TRAP), \ + "i" (__FILE__), "i" (__FUNCTION__)); \ +} while (0) + +#define HAVE_ARCH_BUG +#define HAVE_ARCH_BUG_ON +#define HAVE_ARCH_WARN_ON +#endif /* CONFIG_BUG */ +#endif /* __ASSEMBLY __ */ + +#include + +#endif /* _ASM_POWERPC_BUG_H */ diff --git a/include/asm-ppc/bug.h b/include/asm-ppc/bug.h deleted file mode 100644 --- a/include/asm-ppc/bug.h +++ /dev/null @@ -1,58 +0,0 @@ -#ifndef _PPC_BUG_H -#define _PPC_BUG_H - -struct bug_entry { - unsigned long bug_addr; - int line; - const char *file; - const char *function; -}; - -/* - * If this bit is set in the line number it means that the trap - * is for WARN_ON rather than BUG or BUG_ON. - */ -#define BUG_WARNING_TRAP 0x1000000 - -#ifdef CONFIG_BUG -#define BUG() do { \ - __asm__ __volatile__( \ - "1: twi 31,0,0\n" \ - ".section __bug_table,\"a\"\n\t" \ - " .long 1b,%0,%1,%2\n" \ - ".previous" \ - : : "i" (__LINE__), "i" (__FILE__), "i" (__FUNCTION__)); \ -} while (0) - -#define BUG_ON(x) do { \ - if (!__builtin_constant_p(x) || (x)) { \ - __asm__ __volatile__( \ - "1: twnei %0,0\n" \ - ".section __bug_table,\"a\"\n\t" \ - " .long 1b,%1,%2,%3\n" \ - ".previous" \ - : : "r" (x), "i" (__LINE__), "i" (__FILE__), \ - "i" (__FUNCTION__)); \ - } \ -} while (0) - -#define WARN_ON(x) do { \ - if (!__builtin_constant_p(x) || (x)) { \ - __asm__ __volatile__( \ - "1: twnei %0,0\n" \ - ".section __bug_table,\"a\"\n\t" \ - " .long 1b,%1,%2,%3\n" \ - ".previous" \ - : : "r" (x), "i" (__LINE__ + BUG_WARNING_TRAP), \ - "i" (__FILE__), "i" (__FUNCTION__)); \ - } \ -} while (0) - -#define HAVE_ARCH_BUG -#define HAVE_ARCH_BUG_ON -#define HAVE_ARCH_WARN_ON -#endif - -#include - -#endif diff --git a/include/asm-ppc64/bug.h b/include/asm-ppc64/bug.h deleted file mode 100644 --- a/include/asm-ppc64/bug.h +++ /dev/null @@ -1,69 +0,0 @@ -#ifndef _PPC64_BUG_H -#define _PPC64_BUG_H - -/* - * Define an illegal instr to trap on the bug. - * We don't use 0 because that marks the end of a function - * in the ELF ABI. That's "Boo Boo" in case you wonder... - */ -#define BUG_OPCODE .long 0x00b00b00 /* For asm */ -#define BUG_ILLEGAL_INSTR "0x00b00b00" /* For BUG macro */ - -#ifndef __ASSEMBLY__ - -struct bug_entry { - unsigned long bug_addr; - long line; - const char *file; - const char *function; -}; - -struct bug_entry *find_bug(unsigned long bugaddr); - -/* - * If this bit is set in the line number it means that the trap - * is for WARN_ON rather than BUG or BUG_ON. - */ -#define BUG_WARNING_TRAP 0x1000000 - -#ifdef CONFIG_BUG - -#define BUG() do { \ - __asm__ __volatile__( \ - "1: twi 31,0,0\n" \ - ".section __bug_table,\"a\"\n\t" \ - " .llong 1b,%0,%1,%2\n" \ - ".previous" \ - : : "i" (__LINE__), "i" (__FILE__), "i" (__FUNCTION__)); \ -} while (0) - -#define BUG_ON(x) do { \ - __asm__ __volatile__( \ - "1: tdnei %0,0\n" \ - ".section __bug_table,\"a\"\n\t" \ - " .llong 1b,%1,%2,%3\n" \ - ".previous" \ - : : "r" ((long long)(x)), "i" (__LINE__), \ - "i" (__FILE__), "i" (__FUNCTION__)); \ -} while (0) - -#define WARN_ON(x) do { \ - __asm__ __volatile__( \ - "1: tdnei %0,0\n" \ - ".section __bug_table,\"a\"\n\t" \ - " .llong 1b,%1,%2,%3\n" \ - ".previous" \ - : : "r" ((long long)(x)), \ - "i" (__LINE__ + BUG_WARNING_TRAP), \ - "i" (__FILE__), "i" (__FUNCTION__)); \ -} while (0) - -#define HAVE_ARCH_BUG -#define HAVE_ARCH_BUG_ON -#define HAVE_ARCH_WARN_ON -#endif -#endif - -#include - -#endif From paulus at samba.org Tue Sep 20 08:20:33 2005 From: paulus at samba.org (Paul Mackerras) Date: Tue, 20 Sep 2005 08:20:33 +1000 Subject: G5 pci probing regression In-Reply-To: <20050919095130.GA8549@lst.de> References: <20050918221220.GA31975@lst.de> <17197.59822.43168.956195@cargo.ozlabs.ibm.com> <20050919095130.GA8549@lst.de> Message-ID: <17199.14769.280974.803103@cargo.ozlabs.ibm.com> Christoph Hellwig writes: > sure. The -unpatched files are plain 2.6.14-rc1, the -patched ones are > with my little hack. Thanks. This would be the problem: --- proc-pci-patched 2005-09-20 08:08:23.000000000 +1000 +++ proc-pci-unpatched 2005-09-20 08:08:33.000000000 +1000 @@ -28,18 +28,19 @@ Class 0100: PCI device 1000:0054 (rev 0). IRQ 52. Master Capable. Latency=16. Min Gnt=64.Max Lat=10. - I/O at 0x400 [0x4ff]. - Non-prefetchable 64 bit memory at 0x90004000 [0x90007fff]. - Non-prefetchable 64 bit memory at 0x90020000 [0x9002ffff]. + Non-prefetchable 32 bit memory at 0x400 [0x4ff]. + Non-prefetchable 32 bit memory at 0x90004000 [0x90007fff]. + Non-prefetchable 32 bit memory at 0x90020000 [0x9002ffff]. The first resource being shown as memory is just a bug. I'm wondering how I tell 32-bit BARs from 64-bit BARs in the device tree, though. Could you tar up your device tree (or at least the directory for this device) and send it to me? Thanks, Paul. From linuxppc at jdl.com Tue Sep 20 08:31:54 2005 From: linuxppc at jdl.com (Jon Loeliger) Date: Mon, 19 Sep 2005 17:31:54 -0500 Subject: Add Pantelis' OF Flat Dev Tree bits? Message-ID: Avast, Cap'n Paul! Did ye wan ta add Pantelis Antoniou's patch ta support OF Flat Dev Tree to the powerpc-merge tree? His patch be dated Sep-03, but I don't think I'll be directly repostin' that booty here. jdl From hch at lst.de Tue Sep 20 08:53:33 2005 From: hch at lst.de (Christoph Hellwig) Date: Tue, 20 Sep 2005 00:53:33 +0200 Subject: G5 pci probing regression In-Reply-To: <17199.14769.280974.803103@cargo.ozlabs.ibm.com> References: <20050918221220.GA31975@lst.de> <17197.59822.43168.956195@cargo.ozlabs.ibm.com> <20050919095130.GA8549@lst.de> <17199.14769.280974.803103@cargo.ozlabs.ibm.com> Message-ID: <20050919225333.GA21782@lst.de> On Tue, Sep 20, 2005 at 08:20:33AM +1000, Paul Mackerras wrote: > The first resource being shown as memory is just a bug. I'm wondering > how I tell 32-bit BARs from 64-bit BARs in the device tree, though. > Could you tar up your device tree (or at least the directory for this > device) and send it to me? The device tree of the patched kernel is at http://verein.lst.de/~hch/device-tree-patched.tgz the unpatched one at http://verein.lst.de/~hch/device-tree-unpatched.tgz From bgill at freescale.com Tue Sep 20 10:17:27 2005 From: bgill at freescale.com (Becky Bruce) Date: Mon, 19 Sep 2005 19:17:27 -0500 (CDT) Subject: [PATCH] powerpc: Merge elf.h Message-ID: ppc/ppc64: Merge elf.h into include/asm-powerpc Merge elf.h into a single include file for 32 and 64-bit ppc platforms. This patch has been tested on 32-bit and built on 64-bit platforms. Signed-off-by: Kumar Gala Signed-off-by: Becky Bruce --- commit 4377f15fe916f0ef45e5204537be7efa2c6d1872 tree 144f0009ea0246044f1a36693512cc358fc01058 parent a374ad4968cd7b4b45443328b608b459add77a2e author Becky Bruce Mon, 19 Sep 2005 19:13:34 -0500 committer Becky Bruce Mon, 19 Sep 2005 19:13:34 -0500 include/asm-powerpc/elf.h | 414 +++++++++++++++++++++++++++++++++++++++++++++ include/asm-ppc/elf.h | 151 ---------------- include/asm-ppc64/elf.h | 387 ------------------------------------------ 3 files changed, 414 insertions(+), 538 deletions(-) diff --git a/include/asm-powerpc/elf.h b/include/asm-powerpc/elf.h new file mode 100644 --- /dev/null +++ b/include/asm-powerpc/elf.h @@ -0,0 +1,414 @@ +#ifndef _ASM_POWERPC_ELF_H +#define _ASM_POWERPC_ELF_H + +#include +#include +#include +#include + +/* PowerPC relocations defined by the ABIs */ +#define R_PPC_NONE 0 +#define R_PPC_ADDR32 1 /* 32bit absolute address */ +#define R_PPC_ADDR24 2 /* 26bit address, 2 bits ignored. */ +#define R_PPC_ADDR16 3 /* 16bit absolute address */ +#define R_PPC_ADDR16_LO 4 /* lower 16bit of absolute address */ +#define R_PPC_ADDR16_HI 5 /* high 16bit of absolute address */ +#define R_PPC_ADDR16_HA 6 /* adjusted high 16bit */ +#define R_PPC_ADDR14 7 /* 16bit address, 2 bits ignored */ +#define R_PPC_ADDR14_BRTAKEN 8 +#define R_PPC_ADDR14_BRNTAKEN 9 +#define R_PPC_REL24 10 /* PC relative 26 bit */ +#define R_PPC_REL14 11 /* PC relative 16 bit */ +#define R_PPC_REL14_BRTAKEN 12 +#define R_PPC_REL14_BRNTAKEN 13 +#define R_PPC_GOT16 14 +#define R_PPC_GOT16_LO 15 +#define R_PPC_GOT16_HI 16 +#define R_PPC_GOT16_HA 17 +#define R_PPC_PLTREL24 18 +#define R_PPC_COPY 19 +#define R_PPC_GLOB_DAT 20 +#define R_PPC_JMP_SLOT 21 +#define R_PPC_RELATIVE 22 +#define R_PPC_LOCAL24PC 23 +#define R_PPC_UADDR32 24 +#define R_PPC_UADDR16 25 +#define R_PPC_REL32 26 +#define R_PPC_PLT32 27 +#define R_PPC_PLTREL32 28 +#define R_PPC_PLT16_LO 29 +#define R_PPC_PLT16_HI 30 +#define R_PPC_PLT16_HA 31 +#define R_PPC_SDAREL16 32 +#define R_PPC_SECTOFF 33 +#define R_PPC_SECTOFF_LO 34 +#define R_PPC_SECTOFF_HI 35 +#define R_PPC_SECTOFF_HA 36 + +/* PowerPC relocations defined for the TLS access ABI. */ +#define R_PPC_TLS 67 /* none (sym+add)@tls */ +#define R_PPC_DTPMOD32 68 /* word32 (sym+add)@dtpmod */ +#define R_PPC_TPREL16 69 /* half16* (sym+add)@tprel */ +#define R_PPC_TPREL16_LO 70 /* half16 (sym+add)@tprel at l */ +#define R_PPC_TPREL16_HI 71 /* half16 (sym+add)@tprel at h */ +#define R_PPC_TPREL16_HA 72 /* half16 (sym+add)@tprel at ha */ +#define R_PPC_TPREL32 73 /* word32 (sym+add)@tprel */ +#define R_PPC_DTPREL16 74 /* half16* (sym+add)@dtprel */ +#define R_PPC_DTPREL16_LO 75 /* half16 (sym+add)@dtprel at l */ +#define R_PPC_DTPREL16_HI 76 /* half16 (sym+add)@dtprel at h */ +#define R_PPC_DTPREL16_HA 77 /* half16 (sym+add)@dtprel at ha */ +#define R_PPC_DTPREL32 78 /* word32 (sym+add)@dtprel */ +#define R_PPC_GOT_TLSGD16 79 /* half16* (sym+add)@got at tlsgd */ +#define R_PPC_GOT_TLSGD16_LO 80 /* half16 (sym+add)@got at tlsgd@l */ +#define R_PPC_GOT_TLSGD16_HI 81 /* half16 (sym+add)@got at tlsgd@h */ +#define R_PPC_GOT_TLSGD16_HA 82 /* half16 (sym+add)@got at tlsgd@ha */ +#define R_PPC_GOT_TLSLD16 83 /* half16* (sym+add)@got at tlsld */ +#define R_PPC_GOT_TLSLD16_LO 84 /* half16 (sym+add)@got at tlsld@l */ +#define R_PPC_GOT_TLSLD16_HI 85 /* half16 (sym+add)@got at tlsld@h */ +#define R_PPC_GOT_TLSLD16_HA 86 /* half16 (sym+add)@got at tlsld@ha */ +#define R_PPC_GOT_TPREL16 87 /* half16* (sym+add)@got at tprel */ +#define R_PPC_GOT_TPREL16_LO 88 /* half16 (sym+add)@got at tprel@l */ +#define R_PPC_GOT_TPREL16_HI 89 /* half16 (sym+add)@got at tprel@h */ +#define R_PPC_GOT_TPREL16_HA 90 /* half16 (sym+add)@got at tprel@ha */ +#define R_PPC_GOT_DTPREL16 91 /* half16* (sym+add)@got at dtprel */ +#define R_PPC_GOT_DTPREL16_LO 92 /* half16* (sym+add)@got at dtprel@l */ +#define R_PPC_GOT_DTPREL16_HI 93 /* half16* (sym+add)@got at dtprel@h */ +#define R_PPC_GOT_DTPREL16_HA 94 /* half16* (sym+add)@got at dtprel@ha */ + +/* keep this the last entry. */ +#define R_PPC_NUM 95 + +/* + * ELF register definitions.. + * + * 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 + +#define ELF_NGREG 48 /* includes nip, msr, lr, etc. */ +#define ELF_NFPREG 33 /* includes fpscr */ + +typedef unsigned long elf_greg_t64; +typedef elf_greg_t64 elf_gregset_t64[ELF_NGREG]; + +typedef unsigned int elf_greg_t32; +typedef elf_greg_t32 elf_gregset_t32[ELF_NGREG]; + +/* + * ELF_ARCH, CLASS, and DATA are used to set parameters in the core dumps. + */ +#ifdef __powerpc64__ +# define ELF_NVRREG32 33 /* includes vscr & vrsave stuffed together */ +# define ELF_NVRREG 34 /* includes vscr & vrsave in split vectors */ +# define ELF_GREG_TYPE elf_greg_t64 +#else +# define ELF_NEVRREG 34 /* includes acc (as 2) */ +# define ELF_NVRREG 33 /* includes vscr */ +# define ELF_GREG_TYPE elf_greg_t32 +# define ELF_ARCH EM_PPC +# define ELF_CLASS ELFCLASS32 +# define ELF_DATA ELFDATA2MSB +#endif /* __powerpc64__ */ + +#ifndef ELF_ARCH +# define ELF_ARCH EM_PPC64 +# define ELF_CLASS ELFCLASS64 +# define ELF_DATA ELFDATA2MSB + typedef elf_greg_t64 elf_greg_t; + typedef elf_gregset_t64 elf_gregset_t; +# define elf_addr_t unsigned long +#else + /* Assumption: ELF_ARCH == EM_PPC and ELF_CLASS == ELFCLASS32 */ + typedef elf_greg_t32 elf_greg_t; + typedef elf_gregset_t32 elf_gregset_t; +# define elf_addr_t u32 +#endif /* ELF_ARCH */ + +/* Floating point registers */ +typedef double elf_fpreg_t; +typedef elf_fpreg_t elf_fpregset_t[ELF_NFPREG]; + +/* Altivec registers */ +/* + * The entries with indexes 0-31 contain the corresponding vector registers. + * The entry with index 32 contains the vscr as the last word (offset 12) + * within the quadword. This allows the vscr to be stored as either a + * quadword (since it must be copied via a vector register to/from storage) + * or as a word. + * + * 64-bit kernel notes: The entry at index 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. + * + * Note that it's _not_ compatible with 32 bits ucontext which stuffs the + * vrsave along with vscr and so only uses 33 vectors for the register set + */ +typedef __vector128 elf_vrreg_t; +typedef elf_vrreg_t elf_vrregset_t[ELF_NVRREG]; +#ifdef __powerpc64__ +typedef elf_vrreg_t elf_vrregset_t32[ELF_NVRREG32]; +#endif + +/* + * This is used to ensure we don't load something for the wrong architecture. + */ +#define elf_check_arch(x) ((x)->e_machine == ELF_ARCH) + +#define USE_ELF_CORE_DUMP +#define ELF_EXEC_PAGESIZE 4096 + +/* This is the location that an ET_DYN program is loaded if exec'ed. Typical + use of this is to invoke "./ld.so someprog" to test out a new version of + the loader. We need to make sure that it is out of the way of the program + that it will "exec", and that there is sufficient room for the brk. */ + +#define ELF_ET_DYN_BASE (0x08000000) + +#ifdef __KERNEL__ + +/* Common routine for both 32-bit and 64-bit processes */ +static inline void ppc_elf_core_copy_regs(elf_gregset_t elf_regs, + struct pt_regs *regs) +{ + int i; + int gprs = sizeof(struct pt_regs)/sizeof(ELF_GREG_TYPE); + + if (gprs > ELF_NGREG) + gprs = ELF_NGREG; + + for (i=0; i < gprs; i++) + elf_regs[i] = (elf_greg_t)((ELF_GREG_TYPE *)regs)[i]; + + memset((char *)(elf_regs) + sizeof(struct pt_regs), 0, \ + sizeof(elf_gregset_t) - sizeof(struct pt_regs)); + +} +#define ELF_CORE_COPY_REGS(gregs, regs) ppc_elf_core_copy_regs(gregs, regs); + +static inline int dump_task_regs(struct task_struct *tsk, + elf_gregset_t *elf_regs) +{ + struct pt_regs *regs = tsk->thread.regs; + if (regs) + ppc_elf_core_copy_regs(*elf_regs, regs); + + return 1; +} +#define ELF_CORE_COPY_TASK_REGS(tsk, elf_regs) dump_task_regs(tsk, elf_regs) + +extern int dump_task_fpu(struct task_struct *, elf_fpregset_t *); +#define ELF_CORE_COPY_FPREGS(tsk, elf_fpregs) dump_task_fpu(tsk, elf_fpregs) + +#endif /* __KERNEL__ */ + +/* ELF_HWCAP yields a mask that user programs can use to figure out what + instruction set this cpu supports. This could be done in userspace, + but it's not easy, and we've already done it here. */ +#ifdef __powerpc64__ +# define ELF_HWCAP (cur_cpu_spec->cpu_user_features) +# define ELF_PLAT_INIT(_r, load_addr) do { \ + memset(_r->gpr, 0, sizeof(_r->gpr)); \ + _r->ctr = _r->link = _r->xer = _r->ccr = 0; \ + _r->gpr[2] = load_addr; \ +} while (0) +#else +# define ELF_HWCAP (cur_cpu_spec[0]->cpu_user_features) +#endif /* __powerpc64__ */ + +/* This yields a string that ld.so will use to load implementation + specific libraries for optimization. This is more specific in + intent than poking at uname or /proc/cpuinfo. + + For the moment, we have only optimizations for the Intel generations, + but that could change... */ + +#define ELF_PLATFORM (NULL) + +#ifdef __KERNEL__ + +#ifdef __powerpc64__ +# define SET_PERSONALITY(ex, ibcs2) \ +do { \ + unsigned long new_flags = 0; \ + if ((ex).e_ident[EI_CLASS] == ELFCLASS32) \ + new_flags = _TIF_32BIT; \ + if ((current_thread_info()->flags & _TIF_32BIT) \ + != new_flags) \ + set_thread_flag(TIF_ABI_PENDING); \ + else \ + clear_thread_flag(TIF_ABI_PENDING); \ + if (personality(current->personality) != PER_LINUX32) \ + set_personality(PER_LINUX); \ +} while (0) +/* + * An executable for which elf_read_implies_exec() returns TRUE will + * have the READ_IMPLIES_EXEC personality flag set automatically. This + * is only required to work around bugs in old 32bit toolchains. Since + * the 64bit ABI has never had these issues dont enable the workaround + * even if we have an executable stack. + */ +# define elf_read_implies_exec(ex, exec_stk) (test_thread_flag(TIF_32BIT) ? \ + (exec_stk != EXSTACK_DISABLE_X) : 0) +#else +# define SET_PERSONALITY(ex, ibcs2) set_personality((ibcs2)?PER_SVR4:PER_LINUX) +#endif /* __powerpc64__ */ + +#endif /* __KERNEL__ */ + +extern int dcache_bsize; +extern int icache_bsize; +extern int ucache_bsize; + +#ifdef __powerpc64__ +struct linux_binprm; +#define ARCH_HAS_SETUP_ADDITIONAL_PAGES /* vDSO has arch_setup_additional_pages */ +extern int arch_setup_additional_pages(struct linux_binprm *bprm, int executable_stack); +#define VDSO_AUX_ENT(a,b) NEW_AUX_ENT(a,b); +#else +#define VDSO_AUX_ENT(a,b) +#endif /* __powerpc64__ */ + +/* + * The requirements here are: + * - keep the final alignment of sp (sp & 0xf) + * - make sure the 32-bit value at the first 16 byte aligned position of + * AUXV is greater than 16 for glibc compatibility. + * AT_IGNOREPPC is used for that. + * - for compatibility with glibc ARCH_DLINFO must always be defined on PPC, + * even if DLINFO_ARCH_ITEMS goes to zero or is undefined. + */ +#define ARCH_DLINFO \ +do { \ + /* Handle glibc compatibility. */ \ + NEW_AUX_ENT(AT_IGNOREPPC, AT_IGNOREPPC); \ + NEW_AUX_ENT(AT_IGNOREPPC, AT_IGNOREPPC); \ + /* Cache size items */ \ + NEW_AUX_ENT(AT_DCACHEBSIZE, dcache_bsize); \ + NEW_AUX_ENT(AT_ICACHEBSIZE, icache_bsize); \ + NEW_AUX_ENT(AT_UCACHEBSIZE, ucache_bsize); \ + VDSO_AUX_ENT(AT_SYSINFO_EHDR, current->thread.vdso_base) \ +} while (0) + +/* PowerPC64 relocations defined by the ABIs */ +#define R_PPC64_NONE R_PPC_NONE +#define R_PPC64_ADDR32 R_PPC_ADDR32 /* 32bit absolute address. */ +#define R_PPC64_ADDR24 R_PPC_ADDR24 /* 26bit address, word aligned. */ +#define R_PPC64_ADDR16 R_PPC_ADDR16 /* 16bit absolute address. */ +#define R_PPC64_ADDR16_LO R_PPC_ADDR16_LO /* lower 16bits of abs. address. */ +#define R_PPC64_ADDR16_HI R_PPC_ADDR16_HI /* high 16bits of abs. address. */ +#define R_PPC64_ADDR16_HA R_PPC_ADDR16_HA /* adjusted high 16bits. */ +#define R_PPC64_ADDR14 R_PPC_ADDR14 /* 16bit address, word aligned. */ +#define R_PPC64_ADDR14_BRTAKEN R_PPC_ADDR14_BRTAKEN +#define R_PPC64_ADDR14_BRNTAKEN R_PPC_ADDR14_BRNTAKEN +#define R_PPC64_REL24 R_PPC_REL24 /* PC relative 26 bit, word aligned. */ +#define R_PPC64_REL14 R_PPC_REL14 /* PC relative 16 bit. */ +#define R_PPC64_REL14_BRTAKEN R_PPC_REL14_BRTAKEN +#define R_PPC64_REL14_BRNTAKEN R_PPC_REL14_BRNTAKEN +#define R_PPC64_GOT16 R_PPC_GOT16 +#define R_PPC64_GOT16_LO R_PPC_GOT16_LO +#define R_PPC64_GOT16_HI R_PPC_GOT16_HI +#define R_PPC64_GOT16_HA R_PPC_GOT16_HA + +#define R_PPC64_COPY R_PPC_COPY +#define R_PPC64_GLOB_DAT R_PPC_GLOB_DAT +#define R_PPC64_JMP_SLOT R_PPC_JMP_SLOT +#define R_PPC64_RELATIVE R_PPC_RELATIVE + +#define R_PPC64_UADDR32 R_PPC_UADDR32 +#define R_PPC64_UADDR16 R_PPC_UADDR16 +#define R_PPC64_REL32 R_PPC_REL32 +#define R_PPC64_PLT32 R_PPC_PLT32 +#define R_PPC64_PLTREL32 R_PPC_PLTREL32 +#define R_PPC64_PLT16_LO R_PPC_PLT16_LO +#define R_PPC64_PLT16_HI R_PPC_PLT16_HI +#define R_PPC64_PLT16_HA R_PPC_PLT16_HA + +#define R_PPC64_SECTOFF R_PPC_SECTOFF +#define R_PPC64_SECTOFF_LO R_PPC_SECTOFF_LO +#define R_PPC64_SECTOFF_HI R_PPC_SECTOFF_HI +#define R_PPC64_SECTOFF_HA R_PPC_SECTOFF_HA +#define R_PPC64_ADDR30 37 /* word30 (S + A - P) >> 2. */ +#define R_PPC64_ADDR64 38 /* doubleword64 S + A. */ +#define R_PPC64_ADDR16_HIGHER 39 /* half16 #higher(S + A). */ +#define R_PPC64_ADDR16_HIGHERA 40 /* half16 #highera(S + A). */ +#define R_PPC64_ADDR16_HIGHEST 41 /* half16 #highest(S + A). */ +#define R_PPC64_ADDR16_HIGHESTA 42 /* half16 #highesta(S + A). */ +#define R_PPC64_UADDR64 43 /* doubleword64 S + A. */ +#define R_PPC64_REL64 44 /* doubleword64 S + A - P. */ +#define R_PPC64_PLT64 45 /* doubleword64 L + A. */ +#define R_PPC64_PLTREL64 46 /* doubleword64 L + A - P. */ +#define R_PPC64_TOC16 47 /* half16* S + A - .TOC. */ +#define R_PPC64_TOC16_LO 48 /* half16 #lo(S + A - .TOC.). */ +#define R_PPC64_TOC16_HI 49 /* half16 #hi(S + A - .TOC.). */ +#define R_PPC64_TOC16_HA 50 /* half16 #ha(S + A - .TOC.). */ +#define R_PPC64_TOC 51 /* doubleword64 .TOC. */ +#define R_PPC64_PLTGOT16 52 /* half16* M + A. */ +#define R_PPC64_PLTGOT16_LO 53 /* half16 #lo(M + A). */ +#define R_PPC64_PLTGOT16_HI 54 /* half16 #hi(M + A). */ +#define R_PPC64_PLTGOT16_HA 55 /* half16 #ha(M + A). */ + +#define R_PPC64_ADDR16_DS 56 /* half16ds* (S + A) >> 2. */ +#define R_PPC64_ADDR16_LO_DS 57 /* half16ds #lo(S + A) >> 2. */ +#define R_PPC64_GOT16_DS 58 /* half16ds* (G + A) >> 2. */ +#define R_PPC64_GOT16_LO_DS 59 /* half16ds #lo(G + A) >> 2. */ +#define R_PPC64_PLT16_LO_DS 60 /* half16ds #lo(L + A) >> 2. */ +#define R_PPC64_SECTOFF_DS 61 /* half16ds* (R + A) >> 2. */ +#define R_PPC64_SECTOFF_LO_DS 62 /* half16ds #lo(R + A) >> 2. */ +#define R_PPC64_TOC16_DS 63 /* half16ds* (S + A - .TOC.) >> 2. */ +#define R_PPC64_TOC16_LO_DS 64 /* half16ds #lo(S + A - .TOC.) >> 2. */ +#define R_PPC64_PLTGOT16_DS 65 /* half16ds* (M + A) >> 2. */ +#define R_PPC64_PLTGOT16_LO_DS 66 /* half16ds #lo(M + A) >> 2. */ + +/* PowerPC64 relocations defined for the TLS access ABI. */ +#define R_PPC64_TLS 67 /* none (sym+add)@tls */ +#define R_PPC64_DTPMOD64 68 /* doubleword64 (sym+add)@dtpmod */ +#define R_PPC64_TPREL16 69 /* half16* (sym+add)@tprel */ +#define R_PPC64_TPREL16_LO 70 /* half16 (sym+add)@tprel at l */ +#define R_PPC64_TPREL16_HI 71 /* half16 (sym+add)@tprel at h */ +#define R_PPC64_TPREL16_HA 72 /* half16 (sym+add)@tprel at ha */ +#define R_PPC64_TPREL64 73 /* doubleword64 (sym+add)@tprel */ +#define R_PPC64_DTPREL16 74 /* half16* (sym+add)@dtprel */ +#define R_PPC64_DTPREL16_LO 75 /* half16 (sym+add)@dtprel at l */ +#define R_PPC64_DTPREL16_HI 76 /* half16 (sym+add)@dtprel at h */ +#define R_PPC64_DTPREL16_HA 77 /* half16 (sym+add)@dtprel at ha */ +#define R_PPC64_DTPREL64 78 /* doubleword64 (sym+add)@dtprel */ +#define R_PPC64_GOT_TLSGD16 79 /* half16* (sym+add)@got at tlsgd */ +#define R_PPC64_GOT_TLSGD16_LO 80 /* half16 (sym+add)@got at tlsgd@l */ +#define R_PPC64_GOT_TLSGD16_HI 81 /* half16 (sym+add)@got at tlsgd@h */ +#define R_PPC64_GOT_TLSGD16_HA 82 /* half16 (sym+add)@got at tlsgd@ha */ +#define R_PPC64_GOT_TLSLD16 83 /* half16* (sym+add)@got at tlsld */ +#define R_PPC64_GOT_TLSLD16_LO 84 /* half16 (sym+add)@got at tlsld@l */ +#define R_PPC64_GOT_TLSLD16_HI 85 /* half16 (sym+add)@got at tlsld@h */ +#define R_PPC64_GOT_TLSLD16_HA 86 /* half16 (sym+add)@got at tlsld@ha */ +#define R_PPC64_GOT_TPREL16_DS 87 /* half16ds* (sym+add)@got at tprel */ +#define R_PPC64_GOT_TPREL16_LO_DS 88 /* half16ds (sym+add)@got at tprel@l */ +#define R_PPC64_GOT_TPREL16_HI 89 /* half16 (sym+add)@got at tprel@h */ +#define R_PPC64_GOT_TPREL16_HA 90 /* half16 (sym+add)@got at tprel@ha */ +#define R_PPC64_GOT_DTPREL16_DS 91 /* half16ds* (sym+add)@got at dtprel */ +#define R_PPC64_GOT_DTPREL16_LO_DS 92 /* half16ds (sym+add)@got at dtprel@l */ +#define R_PPC64_GOT_DTPREL16_HI 93 /* half16 (sym+add)@got at dtprel@h */ +#define R_PPC64_GOT_DTPREL16_HA 94 /* half16 (sym+add)@got at dtprel@ha */ +#define R_PPC64_TPREL16_DS 95 /* half16ds* (sym+add)@tprel */ +#define R_PPC64_TPREL16_LO_DS 96 /* half16ds (sym+add)@tprel at l */ +#define R_PPC64_TPREL16_HIGHER 97 /* half16 (sym+add)@tprel at higher */ +#define R_PPC64_TPREL16_HIGHERA 98 /* half16 (sym+add)@tprel at highera */ +#define R_PPC64_TPREL16_HIGHEST 99 /* half16 (sym+add)@tprel at highest */ +#define R_PPC64_TPREL16_HIGHESTA 100 /* half16 (sym+add)@tprel at highesta */ +#define R_PPC64_DTPREL16_DS 101 /* half16ds* (sym+add)@dtprel */ +#define R_PPC64_DTPREL16_LO_DS 102 /* half16ds (sym+add)@dtprel at l */ +#define R_PPC64_DTPREL16_HIGHER 103 /* half16 (sym+add)@dtprel at higher */ +#define R_PPC64_DTPREL16_HIGHERA 104 /* half16 (sym+add)@dtprel at highera */ +#define R_PPC64_DTPREL16_HIGHEST 105 /* half16 (sym+add)@dtprel at highest */ +#define R_PPC64_DTPREL16_HIGHESTA 106 /* half16 (sym+add)@dtprel at highesta */ + +/* Keep this the last entry. */ +#define R_PPC64_NUM 107 + +#endif /* _ASM_POWERPC_ELF_H */ diff --git a/include/asm-ppc/elf.h b/include/asm-ppc/elf.h deleted file mode 100644 --- a/include/asm-ppc/elf.h +++ /dev/null @@ -1,151 +0,0 @@ -#ifndef __PPC_ELF_H -#define __PPC_ELF_H - -/* - * ELF register definitions.. - */ -#include -#include -#include -#include - -/* PowerPC relocations defined by the ABIs */ -#define R_PPC_NONE 0 -#define R_PPC_ADDR32 1 /* 32bit absolute address */ -#define R_PPC_ADDR24 2 /* 26bit address, 2 bits ignored. */ -#define R_PPC_ADDR16 3 /* 16bit absolute address */ -#define R_PPC_ADDR16_LO 4 /* lower 16bit of absolute address */ -#define R_PPC_ADDR16_HI 5 /* high 16bit of absolute address */ -#define R_PPC_ADDR16_HA 6 /* adjusted high 16bit */ -#define R_PPC_ADDR14 7 /* 16bit address, 2 bits ignored */ -#define R_PPC_ADDR14_BRTAKEN 8 -#define R_PPC_ADDR14_BRNTAKEN 9 -#define R_PPC_REL24 10 /* PC relative 26 bit */ -#define R_PPC_REL14 11 /* PC relative 16 bit */ -#define R_PPC_REL14_BRTAKEN 12 -#define R_PPC_REL14_BRNTAKEN 13 -#define R_PPC_GOT16 14 -#define R_PPC_GOT16_LO 15 -#define R_PPC_GOT16_HI 16 -#define R_PPC_GOT16_HA 17 -#define R_PPC_PLTREL24 18 -#define R_PPC_COPY 19 -#define R_PPC_GLOB_DAT 20 -#define R_PPC_JMP_SLOT 21 -#define R_PPC_RELATIVE 22 -#define R_PPC_LOCAL24PC 23 -#define R_PPC_UADDR32 24 -#define R_PPC_UADDR16 25 -#define R_PPC_REL32 26 -#define R_PPC_PLT32 27 -#define R_PPC_PLTREL32 28 -#define R_PPC_PLT16_LO 29 -#define R_PPC_PLT16_HI 30 -#define R_PPC_PLT16_HA 31 -#define R_PPC_SDAREL16 32 -#define R_PPC_SECTOFF 33 -#define R_PPC_SECTOFF_LO 34 -#define R_PPC_SECTOFF_HI 35 -#define R_PPC_SECTOFF_HA 36 -/* Keep this the last entry. */ -#define R_PPC_NUM 37 - -#define ELF_NGREG 48 /* includes nip, msr, lr, etc. */ -#define ELF_NFPREG 33 /* includes fpscr */ -#define ELF_NVRREG 33 /* includes vscr */ -#define ELF_NEVRREG 34 /* includes acc (as 2) */ - -/* - * These are used to set parameters in the core dumps. - */ -#define ELF_ARCH EM_PPC -#define ELF_CLASS ELFCLASS32 -#define ELF_DATA ELFDATA2MSB - -/* General registers */ -typedef unsigned long elf_greg_t; -typedef elf_greg_t elf_gregset_t[ELF_NGREG]; - -/* Floating point registers */ -typedef double elf_fpreg_t; -typedef elf_fpreg_t elf_fpregset_t[ELF_NFPREG]; - -/* Altivec registers */ -typedef __vector128 elf_vrreg_t; -typedef elf_vrreg_t elf_vrregset_t[ELF_NVRREG]; - -#ifdef __KERNEL__ - -struct task_struct; - -/* - * This is used to ensure we don't load something for the wrong architecture. - */ - -#define elf_check_arch(x) ((x)->e_machine == EM_PPC) - -/* This is the location that an ET_DYN program is loaded if exec'ed. Typical - use of this is to invoke "./ld.so someprog" to test out a new version of - the loader. We need to make sure that it is out of the way of the program - that it will "exec", and that there is sufficient room for the brk. */ - -#define ELF_ET_DYN_BASE (0x08000000) - -#define USE_ELF_CORE_DUMP -#define ELF_EXEC_PAGESIZE 4096 - -#define ELF_CORE_COPY_REGS(gregs, regs) \ - memcpy((gregs), (regs), sizeof(struct pt_regs)); \ - memset((char *)(gregs) + sizeof(struct pt_regs), 0, \ - sizeof(elf_gregset_t) - sizeof(struct pt_regs)); - -#define ELF_CORE_COPY_TASK_REGS(t, elfregs) \ - ((t)->thread.regs? \ - ({ ELF_CORE_COPY_REGS((elfregs), (t)->thread.regs); 1; }): 0) - -extern int dump_task_fpu(struct task_struct *t, elf_fpregset_t *fpu); -#define ELF_CORE_COPY_FPREGS(t, fpu) dump_task_fpu((t), (fpu)) - -/* This yields a mask that user programs can use to figure out what - instruction set this cpu supports. This could be done in userspace, - but it's not easy, and we've already done it here. */ - -#define ELF_HWCAP (cur_cpu_spec[0]->cpu_user_features) - -/* This yields a string that ld.so will use to load implementation - specific libraries for optimization. This is more specific in - intent than poking at uname or /proc/cpuinfo. - - For the moment, we have only optimizations for the Intel generations, - but that could change... */ - -#define ELF_PLATFORM (NULL) - -#define SET_PERSONALITY(ex, ibcs2) set_personality((ibcs2)?PER_SVR4:PER_LINUX) - -extern int dcache_bsize; -extern int icache_bsize; -extern int ucache_bsize; - -/* - * The requirements here are: - * - keep the final alignment of sp (sp & 0xf) - * - make sure the 32-bit value at the first 16 byte aligned position of - * AUXV is greater than 16 for glibc compatibility. - * AT_IGNOREPPC is used for that. - * - for compatibility with glibc ARCH_DLINFO must always be defined on PPC, - * even if DLINFO_ARCH_ITEMS goes to zero or is undefined. - */ -#define ARCH_DLINFO \ -do { \ - /* Handle glibc compatibility. */ \ - NEW_AUX_ENT(AT_IGNOREPPC, AT_IGNOREPPC); \ - NEW_AUX_ENT(AT_IGNOREPPC, AT_IGNOREPPC); \ - /* Cache size items */ \ - NEW_AUX_ENT(AT_DCACHEBSIZE, dcache_bsize); \ - NEW_AUX_ENT(AT_ICACHEBSIZE, icache_bsize); \ - NEW_AUX_ENT(AT_UCACHEBSIZE, ucache_bsize); \ - } while (0) - -#endif /* __KERNEL__ */ -#endif diff --git a/include/asm-ppc64/elf.h b/include/asm-ppc64/elf.h deleted file mode 100644 --- a/include/asm-ppc64/elf.h +++ /dev/null @@ -1,387 +0,0 @@ -#ifndef __PPC64_ELF_H -#define __PPC64_ELF_H - -#include -#include -#include -#include - -/* PowerPC relocations defined by the ABIs */ -#define R_PPC_NONE 0 -#define R_PPC_ADDR32 1 /* 32bit absolute address */ -#define R_PPC_ADDR24 2 /* 26bit address, 2 bits ignored. */ -#define R_PPC_ADDR16 3 /* 16bit absolute address */ -#define R_PPC_ADDR16_LO 4 /* lower 16bit of absolute address */ -#define R_PPC_ADDR16_HI 5 /* high 16bit of absolute address */ -#define R_PPC_ADDR16_HA 6 /* adjusted high 16bit */ -#define R_PPC_ADDR14 7 /* 16bit address, 2 bits ignored */ -#define R_PPC_ADDR14_BRTAKEN 8 -#define R_PPC_ADDR14_BRNTAKEN 9 -#define R_PPC_REL24 10 /* PC relative 26 bit */ -#define R_PPC_REL14 11 /* PC relative 16 bit */ -#define R_PPC_REL14_BRTAKEN 12 -#define R_PPC_REL14_BRNTAKEN 13 -#define R_PPC_GOT16 14 -#define R_PPC_GOT16_LO 15 -#define R_PPC_GOT16_HI 16 -#define R_PPC_GOT16_HA 17 -#define R_PPC_PLTREL24 18 -#define R_PPC_COPY 19 -#define R_PPC_GLOB_DAT 20 -#define R_PPC_JMP_SLOT 21 -#define R_PPC_RELATIVE 22 -#define R_PPC_LOCAL24PC 23 -#define R_PPC_UADDR32 24 -#define R_PPC_UADDR16 25 -#define R_PPC_REL32 26 -#define R_PPC_PLT32 27 -#define R_PPC_PLTREL32 28 -#define R_PPC_PLT16_LO 29 -#define R_PPC_PLT16_HI 30 -#define R_PPC_PLT16_HA 31 -#define R_PPC_SDAREL16 32 -#define R_PPC_SECTOFF 33 -#define R_PPC_SECTOFF_LO 34 -#define R_PPC_SECTOFF_HI 35 -#define R_PPC_SECTOFF_HA 36 - -/* PowerPC relocations defined for the TLS access ABI. */ -#define R_PPC_TLS 67 /* none (sym+add)@tls */ -#define R_PPC_DTPMOD32 68 /* word32 (sym+add)@dtpmod */ -#define R_PPC_TPREL16 69 /* half16* (sym+add)@tprel */ -#define R_PPC_TPREL16_LO 70 /* half16 (sym+add)@tprel at l */ -#define R_PPC_TPREL16_HI 71 /* half16 (sym+add)@tprel at h */ -#define R_PPC_TPREL16_HA 72 /* half16 (sym+add)@tprel at ha */ -#define R_PPC_TPREL32 73 /* word32 (sym+add)@tprel */ -#define R_PPC_DTPREL16 74 /* half16* (sym+add)@dtprel */ -#define R_PPC_DTPREL16_LO 75 /* half16 (sym+add)@dtprel at l */ -#define R_PPC_DTPREL16_HI 76 /* half16 (sym+add)@dtprel at h */ -#define R_PPC_DTPREL16_HA 77 /* half16 (sym+add)@dtprel at ha */ -#define R_PPC_DTPREL32 78 /* word32 (sym+add)@dtprel */ -#define R_PPC_GOT_TLSGD16 79 /* half16* (sym+add)@got at tlsgd */ -#define R_PPC_GOT_TLSGD16_LO 80 /* half16 (sym+add)@got at tlsgd@l */ -#define R_PPC_GOT_TLSGD16_HI 81 /* half16 (sym+add)@got at tlsgd@h */ -#define R_PPC_GOT_TLSGD16_HA 82 /* half16 (sym+add)@got at tlsgd@ha */ -#define R_PPC_GOT_TLSLD16 83 /* half16* (sym+add)@got at tlsld */ -#define R_PPC_GOT_TLSLD16_LO 84 /* half16 (sym+add)@got at tlsld@l */ -#define R_PPC_GOT_TLSLD16_HI 85 /* half16 (sym+add)@got at tlsld@h */ -#define R_PPC_GOT_TLSLD16_HA 86 /* half16 (sym+add)@got at tlsld@ha */ -#define R_PPC_GOT_TPREL16 87 /* half16* (sym+add)@got at tprel */ -#define R_PPC_GOT_TPREL16_LO 88 /* half16 (sym+add)@got at tprel@l */ -#define R_PPC_GOT_TPREL16_HI 89 /* half16 (sym+add)@got at tprel@h */ -#define R_PPC_GOT_TPREL16_HA 90 /* half16 (sym+add)@got at tprel@ha */ -#define R_PPC_GOT_DTPREL16 91 /* half16* (sym+add)@got at dtprel */ -#define R_PPC_GOT_DTPREL16_LO 92 /* half16* (sym+add)@got at dtprel@l */ -#define R_PPC_GOT_DTPREL16_HI 93 /* half16* (sym+add)@got at dtprel@h */ -#define R_PPC_GOT_DTPREL16_HA 94 /* half16* (sym+add)@got at dtprel@ha */ - -/* Keep this the last entry. */ -#define R_PPC_NUM 95 - -/* - * ELF register definitions.. - * - * 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 - -#define ELF_NGREG 48 /* includes nip, msr, lr, etc. */ -#define ELF_NFPREG 33 /* includes fpscr */ -#define ELF_NVRREG32 33 /* includes vscr & vrsave stuffed together */ -#define ELF_NVRREG 34 /* includes vscr & vrsave in split vectors */ - -typedef unsigned long elf_greg_t64; -typedef elf_greg_t64 elf_gregset_t64[ELF_NGREG]; - -typedef unsigned int elf_greg_t32; -typedef elf_greg_t32 elf_gregset_t32[ELF_NGREG]; - -/* - * These are used to set parameters in the core dumps. - */ -#ifndef ELF_ARCH -# define ELF_ARCH EM_PPC64 -# define ELF_CLASS ELFCLASS64 -# define ELF_DATA ELFDATA2MSB - typedef elf_greg_t64 elf_greg_t; - typedef elf_gregset_t64 elf_gregset_t; -# define elf_addr_t unsigned long -#else - /* Assumption: ELF_ARCH == EM_PPC and ELF_CLASS == ELFCLASS32 */ - typedef elf_greg_t32 elf_greg_t; - typedef elf_gregset_t32 elf_gregset_t; -# define elf_addr_t u32 -#endif - -typedef double elf_fpreg_t; -typedef elf_fpreg_t elf_fpregset_t[ELF_NFPREG]; - -/* Altivec registers */ -/* - * The entries with indexes 0-31 contain the corresponding vector registers. - * The entry with index 32 contains the vscr as the last word (offset 12) - * within the quadword. This allows the vscr to be stored as either a - * quadword (since it must be copied via a vector register to/from storage) - * or as a word. The entry with index 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. - * - * Note that it's _not_ compatible with 32 bits ucontext which stuffs the - * vrsave along with vscr and so only uses 33 vectors for the register set - */ -typedef __vector128 elf_vrreg_t; -typedef elf_vrreg_t elf_vrregset_t[ELF_NVRREG]; -typedef elf_vrreg_t elf_vrregset_t32[ELF_NVRREG32]; - -/* - * This is used to ensure we don't load something for the wrong architecture. - */ -#define elf_check_arch(x) ((x)->e_machine == ELF_ARCH) - -#define USE_ELF_CORE_DUMP -#define ELF_EXEC_PAGESIZE 4096 - -/* This is the location that an ET_DYN program is loaded if exec'ed. Typical - use of this is to invoke "./ld.so someprog" to test out a new version of - the loader. We need to make sure that it is out of the way of the program - that it will "exec", and that there is sufficient room for the brk. */ - -#define ELF_ET_DYN_BASE (0x08000000) - -#ifdef __KERNEL__ - -/* Common routine for both 32-bit and 64-bit processes */ -static inline void ppc64_elf_core_copy_regs(elf_gregset_t elf_regs, - struct pt_regs *regs) -{ - int i; - int gprs = sizeof(struct pt_regs)/sizeof(elf_greg_t64); - - if (gprs > ELF_NGREG) - gprs = ELF_NGREG; - - for (i=0; i < gprs; i++) - elf_regs[i] = (elf_greg_t)((elf_greg_t64 *)regs)[i]; -} -#define ELF_CORE_COPY_REGS(gregs, regs) ppc64_elf_core_copy_regs(gregs, regs); - -static inline int dump_task_regs(struct task_struct *tsk, - elf_gregset_t *elf_regs) -{ - struct pt_regs *regs = tsk->thread.regs; - if (regs) - ppc64_elf_core_copy_regs(*elf_regs, regs); - - return 1; -} -#define ELF_CORE_COPY_TASK_REGS(tsk, elf_regs) dump_task_regs(tsk, elf_regs) - -extern int dump_task_fpu(struct task_struct *, elf_fpregset_t *); -#define ELF_CORE_COPY_FPREGS(tsk, elf_fpregs) dump_task_fpu(tsk, elf_fpregs) - -/* XXX Should we define the XFPREGS using altivec ??? */ - -#endif - -/* This yields a mask that user programs can use to figure out what - instruction set this cpu supports. This could be done in userspace, - but it's not easy, and we've already done it here. */ - -#define ELF_HWCAP (cur_cpu_spec->cpu_user_features) - -/* This yields a string that ld.so will use to load implementation - specific libraries for optimization. This is more specific in - intent than poking at uname or /proc/cpuinfo. - - For the moment, we have only optimizations for the Intel generations, - but that could change... */ - -#define ELF_PLATFORM (NULL) - -#define ELF_PLAT_INIT(_r, load_addr) do { \ - memset(_r->gpr, 0, sizeof(_r->gpr)); \ - _r->ctr = _r->link = _r->xer = _r->ccr = 0; \ - _r->gpr[2] = load_addr; \ -} while (0) - -#ifdef __KERNEL__ -#define SET_PERSONALITY(ex, ibcs2) \ -do { \ - unsigned long new_flags = 0; \ - if ((ex).e_ident[EI_CLASS] == ELFCLASS32) \ - new_flags = _TIF_32BIT; \ - if ((current_thread_info()->flags & _TIF_32BIT) \ - != new_flags) \ - set_thread_flag(TIF_ABI_PENDING); \ - else \ - clear_thread_flag(TIF_ABI_PENDING); \ - if (personality(current->personality) != PER_LINUX32) \ - set_personality(PER_LINUX); \ -} while (0) - -/* - * An executable for which elf_read_implies_exec() returns TRUE will - * have the READ_IMPLIES_EXEC personality flag set automatically. This - * is only required to work around bugs in old 32bit toolchains. Since - * the 64bit ABI has never had these issues dont enable the workaround - * even if we have an executable stack. - */ -#define elf_read_implies_exec(ex, exec_stk) (test_thread_flag(TIF_32BIT) ? \ - (exec_stk != EXSTACK_DISABLE_X) : 0) - -#endif - -extern int dcache_bsize; -extern int icache_bsize; -extern int ucache_bsize; - -/* We do have an arch_setup_additional_pages for vDSO matters */ -#define ARCH_HAS_SETUP_ADDITIONAL_PAGES -struct linux_binprm; -extern int arch_setup_additional_pages(struct linux_binprm *bprm, int executable_stack); - -/* - * The requirements here are: - * - keep the final alignment of sp (sp & 0xf) - * - make sure the 32-bit value at the first 16 byte aligned position of - * AUXV is greater than 16 for glibc compatibility. - * AT_IGNOREPPC is used for that. - * - for compatibility with glibc ARCH_DLINFO must always be defined on PPC, - * even if DLINFO_ARCH_ITEMS goes to zero or is undefined. - */ -#define ARCH_DLINFO \ -do { \ - /* Handle glibc compatibility. */ \ - NEW_AUX_ENT(AT_IGNOREPPC, AT_IGNOREPPC); \ - NEW_AUX_ENT(AT_IGNOREPPC, AT_IGNOREPPC); \ - /* Cache size items */ \ - NEW_AUX_ENT(AT_DCACHEBSIZE, dcache_bsize); \ - NEW_AUX_ENT(AT_ICACHEBSIZE, icache_bsize); \ - NEW_AUX_ENT(AT_UCACHEBSIZE, ucache_bsize); \ - /* vDSO base */ \ - NEW_AUX_ENT(AT_SYSINFO_EHDR, current->thread.vdso_base); \ - } while (0) - -/* PowerPC64 relocations defined by the ABIs */ -#define R_PPC64_NONE R_PPC_NONE -#define R_PPC64_ADDR32 R_PPC_ADDR32 /* 32bit absolute address. */ -#define R_PPC64_ADDR24 R_PPC_ADDR24 /* 26bit address, word aligned. */ -#define R_PPC64_ADDR16 R_PPC_ADDR16 /* 16bit absolute address. */ -#define R_PPC64_ADDR16_LO R_PPC_ADDR16_LO /* lower 16bits of abs. address. */ -#define R_PPC64_ADDR16_HI R_PPC_ADDR16_HI /* high 16bits of abs. address. */ -#define R_PPC64_ADDR16_HA R_PPC_ADDR16_HA /* adjusted high 16bits. */ -#define R_PPC64_ADDR14 R_PPC_ADDR14 /* 16bit address, word aligned. */ -#define R_PPC64_ADDR14_BRTAKEN R_PPC_ADDR14_BRTAKEN -#define R_PPC64_ADDR14_BRNTAKEN R_PPC_ADDR14_BRNTAKEN -#define R_PPC64_REL24 R_PPC_REL24 /* PC relative 26 bit, word aligned. */ -#define R_PPC64_REL14 R_PPC_REL14 /* PC relative 16 bit. */ -#define R_PPC64_REL14_BRTAKEN R_PPC_REL14_BRTAKEN -#define R_PPC64_REL14_BRNTAKEN R_PPC_REL14_BRNTAKEN -#define R_PPC64_GOT16 R_PPC_GOT16 -#define R_PPC64_GOT16_LO R_PPC_GOT16_LO -#define R_PPC64_GOT16_HI R_PPC_GOT16_HI -#define R_PPC64_GOT16_HA R_PPC_GOT16_HA - -#define R_PPC64_COPY R_PPC_COPY -#define R_PPC64_GLOB_DAT R_PPC_GLOB_DAT -#define R_PPC64_JMP_SLOT R_PPC_JMP_SLOT -#define R_PPC64_RELATIVE R_PPC_RELATIVE - -#define R_PPC64_UADDR32 R_PPC_UADDR32 -#define R_PPC64_UADDR16 R_PPC_UADDR16 -#define R_PPC64_REL32 R_PPC_REL32 -#define R_PPC64_PLT32 R_PPC_PLT32 -#define R_PPC64_PLTREL32 R_PPC_PLTREL32 -#define R_PPC64_PLT16_LO R_PPC_PLT16_LO -#define R_PPC64_PLT16_HI R_PPC_PLT16_HI -#define R_PPC64_PLT16_HA R_PPC_PLT16_HA - -#define R_PPC64_SECTOFF R_PPC_SECTOFF -#define R_PPC64_SECTOFF_LO R_PPC_SECTOFF_LO -#define R_PPC64_SECTOFF_HI R_PPC_SECTOFF_HI -#define R_PPC64_SECTOFF_HA R_PPC_SECTOFF_HA -#define R_PPC64_ADDR30 37 /* word30 (S + A - P) >> 2. */ -#define R_PPC64_ADDR64 38 /* doubleword64 S + A. */ -#define R_PPC64_ADDR16_HIGHER 39 /* half16 #higher(S + A). */ -#define R_PPC64_ADDR16_HIGHERA 40 /* half16 #highera(S + A). */ -#define R_PPC64_ADDR16_HIGHEST 41 /* half16 #highest(S + A). */ -#define R_PPC64_ADDR16_HIGHESTA 42 /* half16 #highesta(S + A). */ -#define R_PPC64_UADDR64 43 /* doubleword64 S + A. */ -#define R_PPC64_REL64 44 /* doubleword64 S + A - P. */ -#define R_PPC64_PLT64 45 /* doubleword64 L + A. */ -#define R_PPC64_PLTREL64 46 /* doubleword64 L + A - P. */ -#define R_PPC64_TOC16 47 /* half16* S + A - .TOC. */ -#define R_PPC64_TOC16_LO 48 /* half16 #lo(S + A - .TOC.). */ -#define R_PPC64_TOC16_HI 49 /* half16 #hi(S + A - .TOC.). */ -#define R_PPC64_TOC16_HA 50 /* half16 #ha(S + A - .TOC.). */ -#define R_PPC64_TOC 51 /* doubleword64 .TOC. */ -#define R_PPC64_PLTGOT16 52 /* half16* M + A. */ -#define R_PPC64_PLTGOT16_LO 53 /* half16 #lo(M + A). */ -#define R_PPC64_PLTGOT16_HI 54 /* half16 #hi(M + A). */ -#define R_PPC64_PLTGOT16_HA 55 /* half16 #ha(M + A). */ - -#define R_PPC64_ADDR16_DS 56 /* half16ds* (S + A) >> 2. */ -#define R_PPC64_ADDR16_LO_DS 57 /* half16ds #lo(S + A) >> 2. */ -#define R_PPC64_GOT16_DS 58 /* half16ds* (G + A) >> 2. */ -#define R_PPC64_GOT16_LO_DS 59 /* half16ds #lo(G + A) >> 2. */ -#define R_PPC64_PLT16_LO_DS 60 /* half16ds #lo(L + A) >> 2. */ -#define R_PPC64_SECTOFF_DS 61 /* half16ds* (R + A) >> 2. */ -#define R_PPC64_SECTOFF_LO_DS 62 /* half16ds #lo(R + A) >> 2. */ -#define R_PPC64_TOC16_DS 63 /* half16ds* (S + A - .TOC.) >> 2. */ -#define R_PPC64_TOC16_LO_DS 64 /* half16ds #lo(S + A - .TOC.) >> 2. */ -#define R_PPC64_PLTGOT16_DS 65 /* half16ds* (M + A) >> 2. */ -#define R_PPC64_PLTGOT16_LO_DS 66 /* half16ds #lo(M + A) >> 2. */ - -/* PowerPC64 relocations defined for the TLS access ABI. */ -#define R_PPC64_TLS 67 /* none (sym+add)@tls */ -#define R_PPC64_DTPMOD64 68 /* doubleword64 (sym+add)@dtpmod */ -#define R_PPC64_TPREL16 69 /* half16* (sym+add)@tprel */ -#define R_PPC64_TPREL16_LO 70 /* half16 (sym+add)@tprel at l */ -#define R_PPC64_TPREL16_HI 71 /* half16 (sym+add)@tprel at h */ -#define R_PPC64_TPREL16_HA 72 /* half16 (sym+add)@tprel at ha */ -#define R_PPC64_TPREL64 73 /* doubleword64 (sym+add)@tprel */ -#define R_PPC64_DTPREL16 74 /* half16* (sym+add)@dtprel */ -#define R_PPC64_DTPREL16_LO 75 /* half16 (sym+add)@dtprel at l */ -#define R_PPC64_DTPREL16_HI 76 /* half16 (sym+add)@dtprel at h */ -#define R_PPC64_DTPREL16_HA 77 /* half16 (sym+add)@dtprel at ha */ -#define R_PPC64_DTPREL64 78 /* doubleword64 (sym+add)@dtprel */ -#define R_PPC64_GOT_TLSGD16 79 /* half16* (sym+add)@got at tlsgd */ -#define R_PPC64_GOT_TLSGD16_LO 80 /* half16 (sym+add)@got at tlsgd@l */ -#define R_PPC64_GOT_TLSGD16_HI 81 /* half16 (sym+add)@got at tlsgd@h */ -#define R_PPC64_GOT_TLSGD16_HA 82 /* half16 (sym+add)@got at tlsgd@ha */ -#define R_PPC64_GOT_TLSLD16 83 /* half16* (sym+add)@got at tlsld */ -#define R_PPC64_GOT_TLSLD16_LO 84 /* half16 (sym+add)@got at tlsld@l */ -#define R_PPC64_GOT_TLSLD16_HI 85 /* half16 (sym+add)@got at tlsld@h */ -#define R_PPC64_GOT_TLSLD16_HA 86 /* half16 (sym+add)@got at tlsld@ha */ -#define R_PPC64_GOT_TPREL16_DS 87 /* half16ds* (sym+add)@got at tprel */ -#define R_PPC64_GOT_TPREL16_LO_DS 88 /* half16ds (sym+add)@got at tprel@l */ -#define R_PPC64_GOT_TPREL16_HI 89 /* half16 (sym+add)@got at tprel@h */ -#define R_PPC64_GOT_TPREL16_HA 90 /* half16 (sym+add)@got at tprel@ha */ -#define R_PPC64_GOT_DTPREL16_DS 91 /* half16ds* (sym+add)@got at dtprel */ -#define R_PPC64_GOT_DTPREL16_LO_DS 92 /* half16ds (sym+add)@got at dtprel@l */ -#define R_PPC64_GOT_DTPREL16_HI 93 /* half16 (sym+add)@got at dtprel@h */ -#define R_PPC64_GOT_DTPREL16_HA 94 /* half16 (sym+add)@got at dtprel@ha */ -#define R_PPC64_TPREL16_DS 95 /* half16ds* (sym+add)@tprel */ -#define R_PPC64_TPREL16_LO_DS 96 /* half16ds (sym+add)@tprel at l */ -#define R_PPC64_TPREL16_HIGHER 97 /* half16 (sym+add)@tprel at higher */ -#define R_PPC64_TPREL16_HIGHERA 98 /* half16 (sym+add)@tprel at highera */ -#define R_PPC64_TPREL16_HIGHEST 99 /* half16 (sym+add)@tprel at highest */ -#define R_PPC64_TPREL16_HIGHESTA 100 /* half16 (sym+add)@tprel at highesta */ -#define R_PPC64_DTPREL16_DS 101 /* half16ds* (sym+add)@dtprel */ -#define R_PPC64_DTPREL16_LO_DS 102 /* half16ds (sym+add)@dtprel at l */ -#define R_PPC64_DTPREL16_HIGHER 103 /* half16 (sym+add)@dtprel at higher */ -#define R_PPC64_DTPREL16_HIGHERA 104 /* half16 (sym+add)@dtprel at highera */ -#define R_PPC64_DTPREL16_HIGHEST 105 /* half16 (sym+add)@dtprel at highest */ -#define R_PPC64_DTPREL16_HIGHESTA 106 /* half16 (sym+add)@dtprel at highesta */ - -/* Keep this the last entry. */ -#define R_PPC64_NUM 107 - -#endif /* __PPC64_ELF_H */ From paulus at samba.org Tue Sep 20 10:23:45 2005 From: paulus at samba.org (Paul Mackerras) Date: Tue, 20 Sep 2005 10:23:45 +1000 Subject: G5 pci probing regression In-Reply-To: <20050919225333.GA21782@lst.de> References: <20050918221220.GA31975@lst.de> <17197.59822.43168.956195@cargo.ozlabs.ibm.com> <20050919095130.GA8549@lst.de> <17199.14769.280974.803103@cargo.ozlabs.ibm.com> <20050919225333.GA21782@lst.de> Message-ID: <17199.22161.701821.240558@cargo.ozlabs.ibm.com> OK, this (untested) patch should fix things. I wasn't setting PCI flags in the resources, only the IORESOURCE_* flags. Please try this and let me know how it goes (without your other 1-line hack, of course). Thanks, Paul. diff -urN linux-2.6/arch/ppc64/kernel/pci.c hch/arch/ppc64/kernel/pci.c --- linux-2.6/arch/ppc64/kernel/pci.c 2005-09-13 07:43:47.000000000 +1000 +++ hch/arch/ppc64/kernel/pci.c 2005-09-20 10:20:54.000000000 +1000 @@ -246,11 +246,14 @@ unsigned int flags = 0; if (addr0 & 0x02000000) { - flags |= IORESOURCE_MEM; + flags = IORESOURCE_MEM | PCI_BASE_ADDRESS_SPACE_MEMORY; + flags |= (addr0 >> 22) & PCI_BASE_ADDRESS_MEM_TYPE_64; + flags |= (addr0 >> 28) & PCI_BASE_ADDRESS_MEM_TYPE_1M; if (addr0 & 0x40000000) - flags |= IORESOURCE_PREFETCH; + flags |= IORESOURCE_PREFETCH + | PCI_BASE_ADDRESS_MEM_PREFETCH; } else if (addr0 & 0x01000000) - flags |= IORESOURCE_IO; + flags = IORESOURCE_IO | PCI_BASE_ADDRESS_SPACE_IO; return flags; } From benh at kernel.crashing.org Tue Sep 20 13:11:12 2005 From: benh at kernel.crashing.org (Benjamin Herrenschmidt) Date: Tue, 20 Sep 2005 13:11:12 +1000 Subject: [PATCH] ppc64: SMU driver update & i2c support Message-ID: <1127185873.4386.32.camel@gaston> Hi ! This patch is a bit late (I was on vacation) but I hope will make it in 2.6.14-rc*. The SMU is the "system controller" chip used by Apple recent G5 machines including the iMac G5. It drives things like fans, i2c busses, real time clock, etc... The current kernel contains a very crude driver that doesn't do much more than reading the real time clock synchronously. This is a completely rewritten driver that provides interrupt based command queuing, a userland interface, and an i2c/smbus driver for accessing the devices hanging off the SMU i2c busses like temperature sensors. This driver is a basic block for upcoming work on thermal control for those machines, among others. Signed-off-by: Benjamin Herrenschmidt Index: linux-work/drivers/macintosh/smu.c =================================================================== --- linux-work.orig/drivers/macintosh/smu.c 2005-09-20 11:54:53.000000000 +1000 +++ linux-work/drivers/macintosh/smu.c 2005-09-20 13:05:11.000000000 +1000 @@ -8,21 +8,15 @@ */ /* - * For now, this driver includes: - * - RTC get & set - * - reboot & shutdown commands - * all synchronous with IRQ disabled (ugh) - * * TODO: - * rework in a way the PMU driver works, that is asynchronous - * with a queue of commands. I'll do that as soon as I have an - * SMU based machine at hand. Some more cleanup is needed too, - * like maybe fitting it into a platform device, etc... - * Also check what's up with cache coherency, and if we really - * can't do better than flushing the cache, maybe build a table - * of command len/reply len like the PMU driver to only flush - * what is actually necessary. - * --BenH. + * - maybe add timeout to commands ? + * - blocking version of time functions + * - polling version of i2c commands (including timer that works with + * interrutps off) + * - maybe avoid some data copies with i2c by directly using the smu cmd + * buffer and a lower level internal interface + * - understand SMU -> CPU events and implement reception of them via + * the userland interface */ #include @@ -36,6 +30,11 @@ #include #include #include +#include +#include +#include +#include +#include #include #include @@ -45,8 +44,13 @@ #include #include #include +#include +#include + +#define VERSION "0.6" +#define AUTHOR "(c) 2005 Benjamin Herrenschmidt, IBM Corp." -#define DEBUG_SMU 1 +#undef DEBUG_SMU #ifdef DEBUG_SMU #define DPRINTK(fmt, args...) do { printk(KERN_DEBUG fmt , ##args); } while (0) @@ -57,20 +61,30 @@ /* * This is the command buffer passed to the SMU hardware */ +#define SMU_MAX_DATA 254 + struct smu_cmd_buf { u8 cmd; u8 length; - u8 data[0x0FFE]; + u8 data[SMU_MAX_DATA]; }; struct smu_device { spinlock_t lock; struct device_node *of_node; - int db_ack; /* doorbell ack GPIO */ - int db_req; /* doorbell req GPIO */ + struct of_device *of_dev; + int doorbell; /* doorbell gpio */ u32 __iomem *db_buf; /* doorbell buffer */ + int db_irq; + int msg; + int msg_irq; struct smu_cmd_buf *cmd_buf; /* command buffer virtual */ u32 cmd_buf_abs; /* command buffer absolute */ + struct list_head cmd_list; + struct smu_cmd *cmd_cur; /* pending command */ + struct list_head cmd_i2c_list; + struct smu_i2c_cmd *cmd_i2c_cur; /* pending i2c command */ + struct timer_list i2c_timer; }; /* @@ -79,113 +93,243 @@ */ static struct smu_device *smu; + /* - * SMU low level communication stuff + * SMU driver low level stuff */ -static inline int smu_cmd_stat(struct smu_cmd_buf *cmd_buf, u8 cmd_ack) + +static void smu_start_cmd(void) { - rmb(); - return cmd_buf->cmd == cmd_ack && cmd_buf->length != 0; + unsigned long faddr, fend; + struct smu_cmd *cmd; + + if (list_empty(&smu->cmd_list)) + return; + + /* Fetch first command in queue */ + cmd = list_entry(smu->cmd_list.next, struct smu_cmd, link); + smu->cmd_cur = cmd; + list_del(&cmd->link); + + DPRINTK("SMU: starting cmd %x, %d bytes data\n", cmd->cmd, + cmd->data_len); + DPRINTK("SMU: data buffer: %02x %02x %02x %02x ...\n", + ((u8 *)cmd->data_buf)[0], ((u8 *)cmd->data_buf)[1], + ((u8 *)cmd->data_buf)[2], ((u8 *)cmd->data_buf)[3]); + + /* Fill the SMU command buffer */ + smu->cmd_buf->cmd = cmd->cmd; + smu->cmd_buf->length = cmd->data_len; + memcpy(smu->cmd_buf->data, cmd->data_buf, cmd->data_len); + + /* Flush command and data to RAM */ + faddr = (unsigned long)smu->cmd_buf; + fend = faddr + smu->cmd_buf->length + 2; + flush_inval_dcache_range(faddr, fend); + + /* This isn't exactly a DMA mapping here, I suspect + * the SMU is actually communicating with us via i2c to the + * northbridge or the CPU to access RAM. + */ + writel(smu->cmd_buf_abs, smu->db_buf); + + /* Ring the SMU doorbell */ + pmac_do_feature_call(PMAC_FTR_WRITE_GPIO, NULL, smu->doorbell, 4); } -static inline u8 smu_save_ack_cmd(struct smu_cmd_buf *cmd_buf) + +static irqreturn_t smu_db_intr(int irq, void *arg, struct pt_regs *regs) { - return (~cmd_buf->cmd) & 0xff; + unsigned long flags; + struct smu_cmd *cmd; + void (*done)(struct smu_cmd *cmd, void *misc) = NULL; + void *misc = NULL; + u8 gpio; + int rc = 0; + + /* SMU completed the command, well, we hope, let's make sure + * of it + */ + spin_lock_irqsave(&smu->lock, flags); + + gpio = pmac_do_feature_call(PMAC_FTR_READ_GPIO, NULL, smu->doorbell); + if ((gpio & 7) != 7) + return IRQ_HANDLED; + + cmd = smu->cmd_cur; + smu->cmd_cur = NULL; + if (cmd == NULL) + goto bail; + + if (rc == 0) { + unsigned long faddr; + int reply_len; + u8 ack; + + /* CPU might have brought back the cache line, so we need + * to flush again before peeking at the SMU response. We + * flush the entire buffer for now as we haven't read the + * reply lenght (it's only 2 cache lines anyway) + */ + faddr = (unsigned long)smu->cmd_buf; + flush_inval_dcache_range(faddr, faddr + 256); + + /* Now check ack */ + ack = (~cmd->cmd) & 0xff; + if (ack != smu->cmd_buf->cmd) { + DPRINTK("SMU: incorrect ack, want %x got %x\n", + ack, smu->cmd_buf->cmd); + rc = -EIO; + } + reply_len = rc == 0 ? smu->cmd_buf->length : 0; + DPRINTK("SMU: reply len: %d\n", reply_len); + if (reply_len > cmd->reply_len) { + printk(KERN_WARNING "SMU: reply buffer too small," + "got %d bytes for a %d bytes buffer\n", + reply_len, cmd->reply_len); + reply_len = cmd->reply_len; + } + cmd->reply_len = reply_len; + if (cmd->reply_buf && reply_len) + memcpy(cmd->reply_buf, smu->cmd_buf->data, reply_len); + } + + /* Now complete the command. Write status last in order as we lost + * ownership of the command structure as soon as it's no longer -1 + */ + done = cmd->done; + misc = cmd->misc; + mb(); + cmd->status = rc; + bail: + /* Start next command if any */ + smu_start_cmd(); + spin_unlock_irqrestore(&smu->lock, flags); + + /* Call command completion handler if any */ + if (done) + done(cmd, misc); + + /* It's an edge interrupt, nothing to do */ + return IRQ_HANDLED; } -static void smu_send_cmd(struct smu_device *dev) + +static irqreturn_t smu_msg_intr(int irq, void *arg, struct pt_regs *regs) { - /* SMU command buf is currently cacheable, we need a physical - * address. This isn't exactly a DMA mapping here, I suspect - * the SMU is actually communicating with us via i2c to the - * northbridge or the CPU to access RAM. + /* I don't quite know what to do with this one, we seem to never + * receive it, so I suspect we have to arm it someway in the SMU + * to start getting events that way. */ - writel(dev->cmd_buf_abs, dev->db_buf); - /* Ring the SMU doorbell */ - pmac_do_feature_call(PMAC_FTR_WRITE_GPIO, NULL, dev->db_req, 4); - pmac_do_feature_call(PMAC_FTR_READ_GPIO, NULL, dev->db_req, 4); + printk(KERN_INFO "SMU: message interrupt !\n"); + + /* It's an edge interrupt, nothing to do */ + return IRQ_HANDLED; } -static int smu_cmd_done(struct smu_device *dev) + +/* + * Queued command management. + * + */ + +int smu_queue_cmd(struct smu_cmd *cmd) { - unsigned long wait = 0; - int gpio; + unsigned long flags; + + if (smu == NULL) + return -ENODEV; + if (cmd->data_len > SMU_MAX_DATA || + cmd->reply_len > SMU_MAX_DATA) + return -EINVAL; - /* Check the SMU doorbell */ - do { - gpio = pmac_do_feature_call(PMAC_FTR_READ_GPIO, - NULL, dev->db_ack); - if ((gpio & 7) == 7) - return 0; - udelay(100); - } while(++wait < 10000); + cmd->status = 1; + spin_lock_irqsave(&smu->lock, flags); + list_add_tail(&cmd->link, &smu->cmd_list); + if (smu->cmd_cur == NULL) + smu_start_cmd(); + spin_unlock_irqrestore(&smu->lock, flags); - printk(KERN_ERR "SMU timeout !\n"); - return -ENXIO; + return 0; } +EXPORT_SYMBOL(smu_queue_cmd); + -static int smu_do_cmd(struct smu_device *dev) +int smu_queue_simple(struct smu_simple_cmd *scmd, u8 command, + unsigned int data_len, + void (*done)(struct smu_cmd *cmd, void *misc), + void *misc, ...) { - int rc; - u8 cmd_ack; + struct smu_cmd *cmd = &scmd->cmd; + va_list list; + int i; - DPRINTK("SMU do_cmd %02x len=%d %02x\n", - dev->cmd_buf->cmd, dev->cmd_buf->length, - dev->cmd_buf->data[0]); - - cmd_ack = smu_save_ack_cmd(dev->cmd_buf); - - /* Clear cmd_buf cache lines */ - flush_inval_dcache_range((unsigned long)dev->cmd_buf, - ((unsigned long)dev->cmd_buf) + - sizeof(struct smu_cmd_buf)); - smu_send_cmd(dev); - rc = smu_cmd_done(dev); - if (rc == 0) - rc = smu_cmd_stat(dev->cmd_buf, cmd_ack) ? 0 : -1; - - DPRINTK("SMU do_cmd %02x len=%d %02x => %d (%02x)\n", - dev->cmd_buf->cmd, dev->cmd_buf->length, - dev->cmd_buf->data[0], rc, cmd_ack); + if (data_len > sizeof(scmd->buffer)) + return -EINVAL; - return rc; + memset(scmd, 0, sizeof(*scmd)); + cmd->cmd = command; + cmd->data_len = data_len; + cmd->data_buf = scmd->buffer; + cmd->reply_len = sizeof(scmd->buffer); + cmd->reply_buf = scmd->buffer; + cmd->done = done; + cmd->misc = misc; + + va_start(list, misc); + for (i = 0; i < data_len; ++i) + scmd->buffer[i] = (u8)va_arg(list, int); + va_end(list); + + return smu_queue_cmd(cmd); } +EXPORT_SYMBOL(smu_queue_simple); -/* RTC low level commands */ -static inline int bcd2hex (int n) + +void smu_poll(void) { - return (((n & 0xf0) >> 4) * 10) + (n & 0xf); + u8 gpio; + + if (smu == NULL) + return; + + gpio = pmac_do_feature_call(PMAC_FTR_READ_GPIO, NULL, smu->doorbell); + if ((gpio & 7) == 7) + smu_db_intr(smu->db_irq, smu, NULL); } +EXPORT_SYMBOL(smu_poll); -static inline int hex2bcd (int n) + +void smu_done_complete(struct smu_cmd *cmd, void *misc) { - return ((n / 10) << 4) + (n % 10); + struct completion *comp = misc; + + complete(comp); } +EXPORT_SYMBOL(smu_done_complete); -#if 0 -static inline void smu_fill_set_pwrup_timer_cmd(struct smu_cmd_buf *cmd_buf) + +void smu_spinwait_cmd(struct smu_cmd *cmd) { - cmd_buf->cmd = 0x8e; - cmd_buf->length = 8; - cmd_buf->data[0] = 0x00; - memset(cmd_buf->data + 1, 0, 7); + while(cmd->status == 1) + smu_poll(); } +EXPORT_SYMBOL(smu_spinwait_cmd); + -static inline void smu_fill_get_pwrup_timer_cmd(struct smu_cmd_buf *cmd_buf) +/* RTC low level commands */ +static inline int bcd2hex (int n) { - cmd_buf->cmd = 0x8e; - cmd_buf->length = 1; - cmd_buf->data[0] = 0x01; + return (((n & 0xf0) >> 4) * 10) + (n & 0xf); } -static inline void smu_fill_dis_pwrup_timer_cmd(struct smu_cmd_buf *cmd_buf) + +static inline int hex2bcd (int n) { - cmd_buf->cmd = 0x8e; - cmd_buf->length = 1; - cmd_buf->data[0] = 0x02; + return ((n / 10) << 4) + (n % 10); } -#endif + static inline void smu_fill_set_rtc_cmd(struct smu_cmd_buf *cmd_buf, struct rtc_time *time) @@ -202,100 +346,96 @@ cmd_buf->data[7] = hex2bcd(time->tm_year - 100); } -static inline void smu_fill_get_rtc_cmd(struct smu_cmd_buf *cmd_buf) -{ - cmd_buf->cmd = 0x8e; - cmd_buf->length = 1; - cmd_buf->data[0] = 0x81; -} -static void smu_parse_get_rtc_reply(struct smu_cmd_buf *cmd_buf, - struct rtc_time *time) +int smu_get_rtc_time(struct rtc_time *time, int spinwait) { - time->tm_sec = bcd2hex(cmd_buf->data[0]); - time->tm_min = bcd2hex(cmd_buf->data[1]); - time->tm_hour = bcd2hex(cmd_buf->data[2]); - time->tm_wday = bcd2hex(cmd_buf->data[3]); - time->tm_mday = bcd2hex(cmd_buf->data[4]); - time->tm_mon = bcd2hex(cmd_buf->data[5]) - 1; - time->tm_year = bcd2hex(cmd_buf->data[6]) + 100; -} - -int smu_get_rtc_time(struct rtc_time *time) -{ - unsigned long flags; + struct smu_simple_cmd cmd; int rc; if (smu == NULL) return -ENODEV; memset(time, 0, sizeof(struct rtc_time)); - spin_lock_irqsave(&smu->lock, flags); - smu_fill_get_rtc_cmd(smu->cmd_buf); - rc = smu_do_cmd(smu); - if (rc == 0) - smu_parse_get_rtc_reply(smu->cmd_buf, time); - spin_unlock_irqrestore(&smu->lock, flags); + rc = smu_queue_simple(&cmd, SMU_CMD_RTC_COMMAND, 1, NULL, NULL, + SMU_CMD_RTC_GET_DATETIME); + if (rc) + return rc; + smu_spinwait_simple(&cmd); + + time->tm_sec = bcd2hex(cmd.buffer[0]); + time->tm_min = bcd2hex(cmd.buffer[1]); + time->tm_hour = bcd2hex(cmd.buffer[2]); + time->tm_wday = bcd2hex(cmd.buffer[3]); + time->tm_mday = bcd2hex(cmd.buffer[4]); + time->tm_mon = bcd2hex(cmd.buffer[5]) - 1; + time->tm_year = bcd2hex(cmd.buffer[6]) + 100; - return rc; + return 0; } -int smu_set_rtc_time(struct rtc_time *time) + +int smu_set_rtc_time(struct rtc_time *time, int spinwait) { - unsigned long flags; + struct smu_simple_cmd cmd; int rc; if (smu == NULL) return -ENODEV; - spin_lock_irqsave(&smu->lock, flags); - smu_fill_set_rtc_cmd(smu->cmd_buf, time); - rc = smu_do_cmd(smu); - spin_unlock_irqrestore(&smu->lock, flags); + rc = smu_queue_simple(&cmd, SMU_CMD_RTC_COMMAND, 8, NULL, NULL, + SMU_CMD_RTC_SET_DATETIME, + hex2bcd(time->tm_sec), + hex2bcd(time->tm_min), + hex2bcd(time->tm_hour), + time->tm_wday, + hex2bcd(time->tm_mday), + hex2bcd(time->tm_mon) + 1, + hex2bcd(time->tm_year - 100)); + if (rc) + return rc; + smu_spinwait_simple(&cmd); - return rc; + return 0; } + void smu_shutdown(void) { - const unsigned char *command = "SHUTDOWN"; - unsigned long flags; + struct smu_simple_cmd cmd; if (smu == NULL) return; - spin_lock_irqsave(&smu->lock, flags); - smu->cmd_buf->cmd = 0xaa; - smu->cmd_buf->length = strlen(command); - strcpy(smu->cmd_buf->data, command); - smu_do_cmd(smu); + if (smu_queue_simple(&cmd, SMU_CMD_POWER_COMMAND, 9, NULL, NULL, + 'S', 'H', 'U', 'T', 'D', 'O', 'W', 'N', 0)) + return; + smu_spinwait_simple(&cmd); for (;;) ; - spin_unlock_irqrestore(&smu->lock, flags); } + void smu_restart(void) { - const unsigned char *command = "RESTART"; - unsigned long flags; + struct smu_simple_cmd cmd; if (smu == NULL) return; - spin_lock_irqsave(&smu->lock, flags); - smu->cmd_buf->cmd = 0xaa; - smu->cmd_buf->length = strlen(command); - strcpy(smu->cmd_buf->data, command); - smu_do_cmd(smu); + if (smu_queue_simple(&cmd, SMU_CMD_POWER_COMMAND, 8, NULL, NULL, + 'R', 'E', 'S', 'T', 'A', 'R', 'T', 0)) + return; + smu_spinwait_simple(&cmd); for (;;) ; - spin_unlock_irqrestore(&smu->lock, flags); } + int smu_present(void) { return smu != NULL; } +EXPORT_SYMBOL(smu_present); int smu_init (void) @@ -307,6 +447,8 @@ if (np == NULL) return -ENODEV; + printk(KERN_INFO "SMU driver %s %s\n", VERSION, AUTHOR); + if (smu_cmdbuf_abs == 0) { printk(KERN_ERR "SMU: Command buffer not allocated !\n"); return -EINVAL; @@ -318,7 +460,13 @@ memset(smu, 0, sizeof(*smu)); spin_lock_init(&smu->lock); + INIT_LIST_HEAD(&smu->cmd_list); + INIT_LIST_HEAD(&smu->cmd_i2c_list); smu->of_node = np; + smu->db_irq = NO_IRQ; + smu->msg_irq = NO_IRQ; + init_timer(&smu->i2c_timer); + /* smu_cmdbuf_abs is in the low 2G of RAM, can be converted to a * 32 bits value safely */ @@ -331,8 +479,8 @@ goto fail; } data = (u32 *)get_property(np, "reg", NULL); - of_node_put(np); if (data == NULL) { + of_node_put(np); printk(KERN_ERR "SMU: Can't find doorbell GPIO address !\n"); goto fail; } @@ -341,8 +489,31 @@ * and ack. GPIOs are at 0x50, best would be to find that out * in the device-tree though. */ - smu->db_req = 0x50 + *data; - smu->db_ack = 0x50 + *data; + smu->doorbell = *data; + if (smu->doorbell < 0x50) + smu->doorbell += 0x50; + if (np->n_intrs > 0) + smu->db_irq = np->intrs[0].line; + + of_node_put(np); + + /* Now look for the smu-interrupt GPIO */ + do { + np = of_find_node_by_name(NULL, "smu-interrupt"); + if (np == NULL) + break; + data = (u32 *)get_property(np, "reg", NULL); + if (data == NULL) { + of_node_put(np); + break; + } + smu->msg = *data; + if (smu->msg < 0x50) + smu->msg += 0x50; + if (np->n_intrs > 0) + smu->msg_irq = np->intrs[0].line; + of_node_put(np); + } while(0); /* Doorbell buffer is currently hard-coded, I didn't find a proper * device-tree entry giving the address. Best would probably to use @@ -362,3 +533,584 @@ return -ENXIO; } + + +static int smu_late_init(void) +{ + if (!smu) + return 0; + + /* + * Try to request the interrupts + */ + + if (smu->db_irq != NO_IRQ) { + if (request_irq(smu->db_irq, smu_db_intr, + SA_SHIRQ, "SMU doorbell", smu) < 0) { + printk(KERN_WARNING "SMU: can't " + "request interrupt %d\n", + smu->db_irq); + smu->db_irq = NO_IRQ; + } + } + + if (smu->msg_irq != NO_IRQ) { + if (request_irq(smu->msg_irq, smu_msg_intr, + SA_SHIRQ, "SMU message", smu) < 0) { + printk(KERN_WARNING "SMU: can't " + "request interrupt %d\n", + smu->msg_irq); + smu->msg_irq = NO_IRQ; + } + } + + return 0; +} +arch_initcall(smu_late_init); + +/* + * sysfs visibility + */ + +static void smu_expose_childs(void *unused) +{ + struct device_node *np; + + for (np = NULL; (np = of_get_next_child(smu->of_node, np)) != NULL;) { + if (device_is_compatible(np, "smu-i2c")) { + char name[32]; + u32 *reg = (u32 *)get_property(np, "reg", NULL); + + if (reg == NULL) + continue; + sprintf(name, "smu-i2c-%02x", *reg); + of_platform_device_create(np, name, &smu->of_dev->dev); + } + } + +} + +static DECLARE_WORK(smu_expose_childs_work, smu_expose_childs, NULL); + +static int smu_platform_probe(struct of_device* dev, + const struct of_device_id *match) +{ + if (!smu) + return -ENODEV; + smu->of_dev = dev; + + /* + * Ok, we are matched, now expose all i2c busses. We have to defer + * that unfortunately or it would deadlock inside the device model + */ + schedule_work(&smu_expose_childs_work); + + return 0; +} + +static struct of_device_id smu_platform_match[] = +{ + { + .type = "smu", + }, + {}, +}; + +static struct of_platform_driver smu_of_platform_driver = +{ + .name = "smu", + .match_table = smu_platform_match, + .probe = smu_platform_probe, +}; + +static int __init smu_init_sysfs(void) +{ + int rc; + + /* + * Due to sysfs bogosity, a sysdev is not a real device, so + * we should in fact create both if we want sysdev semantics + * for power management. + * For now, we don't power manage machines with an SMU chip, + * I'm a bit too far from figuring out how that works with those + * new chipsets, but that will come back and bite us + */ + rc = of_register_driver(&smu_of_platform_driver); + return 0; +} + +device_initcall(smu_init_sysfs); + +struct of_device *smu_get_ofdev(void) +{ + if (!smu) + return NULL; + return smu->of_dev; +} + +EXPORT_SYMBOL_GPL(smu_get_ofdev); + +/* + * i2c interface + */ + +static void smu_i2c_complete_command(struct smu_i2c_cmd *cmd, int fail) +{ + void (*done)(struct smu_i2c_cmd *cmd, void *misc) = cmd->done; + void *misc = cmd->misc; + unsigned long flags; + + /* Check for read case */ + if (!fail && cmd->read) { + if (cmd->pdata[0] < 1) + fail = 1; + else + memcpy(cmd->info.data, &cmd->pdata[1], + cmd->info.datalen); + } + + DPRINTK("SMU: completing, success: %d\n", !fail); + + /* Update status and mark no pending i2c command with lock + * held so nobody comes in while we dequeue an eventual + * pending next i2c command + */ + spin_lock_irqsave(&smu->lock, flags); + smu->cmd_i2c_cur = NULL; + wmb(); + cmd->status = fail ? -EIO : 0; + + /* Is there another i2c command waiting ? */ + if (!list_empty(&smu->cmd_i2c_list)) { + struct smu_i2c_cmd *newcmd; + + /* Fetch it, new current, remove from list */ + newcmd = list_entry(smu->cmd_i2c_list.next, + struct smu_i2c_cmd, link); + smu->cmd_i2c_cur = newcmd; + list_del(&cmd->link); + + /* Queue with low level smu */ + list_add_tail(&cmd->scmd.link, &smu->cmd_list); + if (smu->cmd_cur == NULL) + smu_start_cmd(); + } + spin_unlock_irqrestore(&smu->lock, flags); + + /* Call command completion handler if any */ + if (done) + done(cmd, misc); + +} + + +static void smu_i2c_retry(unsigned long data) +{ + struct smu_i2c_cmd *cmd = (struct smu_i2c_cmd *)data; + + DPRINTK("SMU: i2c failure, requeuing...\n"); + + /* requeue command simply by resetting reply_len */ + cmd->pdata[0] = 0xff; + cmd->scmd.reply_len = 0x10; + smu_queue_cmd(&cmd->scmd); +} + + +static void smu_i2c_low_completion(struct smu_cmd *scmd, void *misc) +{ + struct smu_i2c_cmd *cmd = misc; + int fail = 0; + + DPRINTK("SMU: i2c compl. stage=%d status=%x pdata[0]=%x rlen: %x\n", + cmd->stage, scmd->status, cmd->pdata[0], scmd->reply_len); + + /* Check for possible status */ + if (scmd->status < 0) + fail = 1; + else if (cmd->read) { + if (cmd->stage == 0) + fail = cmd->pdata[0] != 0; + else + fail = cmd->pdata[0] >= 0x80; + } else { + fail = cmd->pdata[0] != 0; + } + + /* Handle failures by requeuing command, after 5ms interval + */ + if (fail && --cmd->retries > 0) { + DPRINTK("SMU: i2c failure, starting timer...\n"); + smu->i2c_timer.function = smu_i2c_retry; + smu->i2c_timer.data = (unsigned long)cmd; + smu->i2c_timer.expires = jiffies + msecs_to_jiffies(5); + add_timer(&smu->i2c_timer); + return; + } + + /* If failure or stage 1, command is complete */ + if (fail || cmd->stage != 0) { + smu_i2c_complete_command(cmd, fail); + return; + } + + DPRINTK("SMU: going to stage 1\n"); + + /* Ok, initial command complete, now poll status */ + scmd->reply_buf = cmd->pdata; + scmd->reply_len = 0x10; + scmd->data_buf = cmd->pdata; + scmd->data_len = 1; + cmd->pdata[0] = 0; + cmd->stage = 1; + cmd->retries = 20; + smu_queue_cmd(scmd); +} + + +int smu_queue_i2c(struct smu_i2c_cmd *cmd) +{ + unsigned long flags; + + if (smu == NULL) + return -ENODEV; + + /* Fill most fields of scmd */ + cmd->scmd.cmd = SMU_CMD_I2C_COMMAND; + cmd->scmd.done = smu_i2c_low_completion; + cmd->scmd.misc = cmd; + cmd->scmd.reply_buf = cmd->pdata; + cmd->scmd.reply_len = 0x10; + cmd->scmd.data_buf = (u8 *)(char *)&cmd->info; + cmd->scmd.status = 1; + cmd->stage = 0; + cmd->pdata[0] = 0xff; + cmd->retries = 20; + cmd->status = 1; + + /* Check transfer type, sanitize some "info" fields + * based on transfer type and do more checking + */ + cmd->info.caddr = cmd->info.devaddr; + cmd->read = cmd->info.devaddr & 0x01; + switch(cmd->info.type) { + case SMU_I2C_TRANSFER_SIMPLE: + memset(&cmd->info.sublen, 0, 4); + break; + case SMU_I2C_TRANSFER_COMBINED: + cmd->info.devaddr &= 0xfe; + case SMU_I2C_TRANSFER_STDSUB: + if (cmd->info.sublen > 3) + return -EINVAL; + break; + default: + return -EINVAL; + } + + /* Finish setting up command based on transfer direction + */ + if (cmd->read) { + if (cmd->info.datalen > SMU_I2C_READ_MAX) + return -EINVAL; + memset(cmd->info.data, 0xff, cmd->info.datalen); + cmd->scmd.data_len = 9; + } else { + if (cmd->info.datalen > SMU_I2C_WRITE_MAX) + return -EINVAL; + cmd->scmd.data_len = 9 + cmd->info.datalen; + } + + DPRINTK("SMU: i2c enqueuing command\n"); + DPRINTK("SMU: %s, len=%d bus=%x addr=%x sub0=%x type=%x\n", + cmd->read ? "read" : "write", cmd->info.datalen, + cmd->info.bus, cmd->info.caddr, + cmd->info.subaddr[0], cmd->info.type); + + + /* Enqueue command in i2c list, and if empty, enqueue also in + * main command list + */ + spin_lock_irqsave(&smu->lock, flags); + if (smu->cmd_i2c_cur == NULL) { + smu->cmd_i2c_cur = cmd; + list_add_tail(&cmd->scmd.link, &smu->cmd_list); + if (smu->cmd_cur == NULL) + smu_start_cmd(); + } else + list_add_tail(&cmd->link, &smu->cmd_i2c_list); + spin_unlock_irqrestore(&smu->lock, flags); + + return 0; +} + + + +/* + * Userland driver interface + */ + + +static LIST_HEAD(smu_clist); +static DEFINE_SPINLOCK(smu_clist_lock); + +enum smu_file_mode { + smu_file_commands, + smu_file_events, + smu_file_closing +}; + +struct smu_private +{ + struct list_head list; + enum smu_file_mode mode; + int busy; + struct smu_cmd cmd; + spinlock_t lock; + wait_queue_head_t wait; + u8 buffer[SMU_MAX_DATA]; +}; + + +static int smu_open(struct inode *inode, struct file *file) +{ + struct smu_private *pp; + unsigned long flags; + + pp = kmalloc(sizeof(struct smu_private), GFP_KERNEL); + if (pp == 0) + return -ENOMEM; + memset(pp, 0, sizeof(struct smu_private)); + spin_lock_init(&pp->lock); + pp->mode = smu_file_commands; + init_waitqueue_head(&pp->wait); + + spin_lock_irqsave(&smu_clist_lock, flags); + list_add(&pp->list, &smu_clist); + spin_unlock_irqrestore(&smu_clist_lock, flags); + file->private_data = pp; + + return 0; +} + + +static void smu_user_cmd_done(struct smu_cmd *cmd, void *misc) +{ + struct smu_private *pp = misc; + + wake_up_all(&pp->wait); +} + + +static ssize_t smu_write(struct file *file, const char __user *buf, + size_t count, loff_t *ppos) +{ + struct smu_private *pp = file->private_data; + unsigned long flags; + struct smu_user_cmd_hdr hdr; + int rc = 0; + + if (pp->busy) + return -EBUSY; + else if (copy_from_user(&hdr, buf, sizeof(hdr))) + return -EFAULT; + else if (hdr.cmdtype == SMU_CMDTYPE_WANTS_EVENTS) { + pp->mode = smu_file_events; + return 0; + } else if (hdr.cmdtype != SMU_CMDTYPE_SMU) + return -EINVAL; + else if (pp->mode != smu_file_commands) + return -EBADFD; + else if (hdr.data_len > SMU_MAX_DATA) + return -EINVAL; + + spin_lock_irqsave(&pp->lock, flags); + if (pp->busy) { + spin_unlock_irqrestore(&pp->lock, flags); + return -EBUSY; + } + pp->busy = 1; + pp->cmd.status = 1; + spin_unlock_irqrestore(&pp->lock, flags); + + if (copy_from_user(pp->buffer, buf + sizeof(hdr), hdr.data_len)) { + pp->busy = 0; + return -EFAULT; + } + + pp->cmd.cmd = hdr.cmd; + pp->cmd.data_len = hdr.data_len; + pp->cmd.reply_len = SMU_MAX_DATA; + pp->cmd.data_buf = pp->buffer; + pp->cmd.reply_buf = pp->buffer; + pp->cmd.done = smu_user_cmd_done; + pp->cmd.misc = pp; + rc = smu_queue_cmd(&pp->cmd); + if (rc < 0) + return rc; + return count; +} + + +static ssize_t smu_read_command(struct file *file, struct smu_private *pp, + char __user *buf, size_t count) +{ + DECLARE_WAITQUEUE(wait, current); + struct smu_user_reply_hdr hdr; + unsigned long flags; + int size, rc = 0; + + if (!pp->busy) + return 0; + if (count < sizeof(struct smu_user_reply_hdr)) + return -EOVERFLOW; + spin_lock_irqsave(&pp->lock, flags); + if (pp->cmd.status == 1) { + if (file->f_flags & O_NONBLOCK) + return -EAGAIN; + add_wait_queue(&pp->wait, &wait); + for (;;) { + set_current_state(TASK_INTERRUPTIBLE); + rc = 0; + if (pp->cmd.status != 1) + break; + rc = -ERESTARTSYS; + if (signal_pending(current)) + break; + spin_unlock_irqrestore(&pp->lock, flags); + schedule(); + spin_lock_irqsave(&pp->lock, flags); + } + set_current_state(TASK_RUNNING); + remove_wait_queue(&pp->wait, &wait); + } + spin_unlock_irqrestore(&pp->lock, flags); + if (rc) + return rc; + if (pp->cmd.status != 0) + pp->cmd.reply_len = 0; + size = sizeof(hdr) + pp->cmd.reply_len; + if (count < size) + size = count; + rc = size; + hdr.status = pp->cmd.status; + hdr.reply_len = pp->cmd.reply_len; + if (copy_to_user(buf, &hdr, sizeof(hdr))) + return -EFAULT; + size -= sizeof(hdr); + if (size && copy_to_user(buf + sizeof(hdr), pp->buffer, size)) + return -EFAULT; + pp->busy = 0; + + return rc; +} + + +static ssize_t smu_read_events(struct file *file, struct smu_private *pp, + char __user *buf, size_t count) +{ + /* Not implemented */ + msleep_interruptible(1000); + return 0; +} + + +static ssize_t smu_read(struct file *file, char __user *buf, + size_t count, loff_t *ppos) +{ + struct smu_private *pp = file->private_data; + + if (pp->mode == smu_file_commands) + return smu_read_command(file, pp, buf, count); + if (pp->mode == smu_file_events) + return smu_read_events(file, pp, buf, count); + + return -EBADFD; +} + +static unsigned int smu_fpoll(struct file *file, poll_table *wait) +{ + struct smu_private *pp = file->private_data; + unsigned int mask = 0; + unsigned long flags; + + if (pp == 0) + return 0; + + if (pp->mode == smu_file_commands) { + poll_wait(file, &pp->wait, wait); + + spin_lock_irqsave(&pp->lock, flags); + if (pp->busy && pp->cmd.status != 1) + mask |= POLLIN; + spin_unlock_irqrestore(&pp->lock, flags); + } if (pp->mode == smu_file_events) { + /* Not yet implemented */ + } + return mask; +} + +static int smu_release(struct inode *inode, struct file *file) +{ + struct smu_private *pp = file->private_data; + unsigned long flags; + unsigned int busy; + + if (pp == 0) + return 0; + + file->private_data = NULL; + + /* Mark file as closing to avoid races with new request */ + spin_lock_irqsave(&pp->lock, flags); + pp->mode = smu_file_closing; + busy = pp->busy; + + /* Wait for any pending request to complete */ + if (busy && pp->cmd.status == 1) { + DECLARE_WAITQUEUE(wait, current); + + add_wait_queue(&pp->wait, &wait); + for (;;) { + set_current_state(TASK_UNINTERRUPTIBLE); + if (pp->cmd.status != 1) + break; + spin_lock_irqsave(&pp->lock, flags); + schedule(); + spin_unlock_irqrestore(&pp->lock, flags); + } + set_current_state(TASK_RUNNING); + remove_wait_queue(&pp->wait, &wait); + } + spin_unlock_irqrestore(&pp->lock, flags); + + spin_lock_irqsave(&smu_clist_lock, flags); + list_del(&pp->list); + spin_unlock_irqrestore(&smu_clist_lock, flags); + kfree(pp); + + return 0; +} + + +static struct file_operations smu_device_fops __pmacdata = { + .llseek = no_llseek, + .read = smu_read, + .write = smu_write, + .poll = smu_fpoll, + .open = smu_open, + .release = smu_release, +}; + +static struct miscdevice pmu_device __pmacdata = { + MISC_DYNAMIC_MINOR, "smu", &smu_device_fops +}; + +static int smu_device_init(void) +{ + if (!smu) + return -ENODEV; + if (misc_register(&pmu_device) < 0) + printk(KERN_ERR "via-pmu: cannot register misc device.\n"); + return 0; +} +device_initcall(smu_device_init); Index: linux-work/include/asm-ppc64/smu.h =================================================================== --- linux-work.orig/include/asm-ppc64/smu.h 2005-09-20 11:54:53.000000000 +1000 +++ linux-work/include/asm-ppc64/smu.h 2005-09-20 11:57:47.000000000 +1000 @@ -1,22 +1,379 @@ +#ifndef _SMU_H +#define _SMU_H + /* * Definitions for talking to the SMU chip in newer G5 PowerMacs */ #include +#include + +/* + * Known SMU commands + * + * Most of what is below comes from looking at the Open Firmware driver, + * though this is still incomplete and could use better documentation here + * or there... + */ + + +/* + * Partition info commands + * + * I do not know what those are for at this point + */ +#define SMU_CMD_PARTITION_COMMAND 0x3e + + +/* + * Fan control + * + * This is a "mux" for fan control commands, first byte is the + * "sub" command. + */ +#define SMU_CMD_FAN_COMMAND 0x4a + + +/* + * Battery access + * + * Same command number as the PMU, could it be same syntax ? + */ +#define SMU_CMD_BATTERY_COMMAND 0x6f +#define SMU_CMD_GET_BATTERY_INFO 0x00 + +/* + * Real time clock control + * + * This is a "mux", first data byte contains the "sub" command. + * The "RTC" part of the SMU controls the date, time, powerup + * timer, but also a PRAM + * + * Dates are in BCD format on 7 bytes: + * [sec] [min] [hour] [weekday] [month day] [month] [year] + * with month being 1 based and year minus 100 + */ +#define SMU_CMD_RTC_COMMAND 0x8e +#define SMU_CMD_RTC_SET_PWRUP_TIMER 0x00 /* i: 7 bytes date */ +#define SMU_CMD_RTC_GET_PWRUP_TIMER 0x01 /* o: 7 bytes date */ +#define SMU_CMD_RTC_STOP_PWRUP_TIMER 0x02 +#define SMU_CMD_RTC_SET_PRAM_BYTE_ACC 0x20 /* i: 1 byte (address?) */ +#define SMU_CMD_RTC_SET_PRAM_AUTOINC 0x21 /* i: 1 byte (data?) */ +#define SMU_CMD_RTC_SET_PRAM_LO_BYTES 0x22 /* i: 10 bytes */ +#define SMU_CMD_RTC_SET_PRAM_HI_BYTES 0x23 /* i: 10 bytes */ +#define SMU_CMD_RTC_GET_PRAM_BYTE 0x28 /* i: 1 bytes (address?) */ +#define SMU_CMD_RTC_GET_PRAM_LO_BYTES 0x29 /* o: 10 bytes */ +#define SMU_CMD_RTC_GET_PRAM_HI_BYTES 0x2a /* o: 10 bytes */ +#define SMU_CMD_RTC_SET_DATETIME 0x80 /* i: 7 bytes date */ +#define SMU_CMD_RTC_GET_DATETIME 0x81 /* o: 7 bytes date */ + + /* + * i2c commands + * + * To issue an i2c command, first is to send a parameter block to the + * the SMU. This is a command of type 0x9a with 9 bytes of header + * eventually followed by data for a write: + * + * 0: bus number (from device-tree usually, SMU has lots of busses !) + * 1: transfer type/format (see below) + * 2: device address. For combined and combined4 type transfers, this + * is the "write" version of the address (bit 0x01 cleared) + * 3: subaddress length (0..3) + * 4: subaddress byte 0 (or only byte for subaddress length 1) + * 5: subaddress byte 1 + * 6: subaddress byte 2 + * 7: combined address (device address for combined mode data phase) + * 8: data length + * + * The transfer types are the same good old Apple ones it seems, + * that is: + * - 0x00: Simple transfer + * - 0x01: Subaddress transfer (addr write + data tx, no restart) + * - 0x02: Combined transfer (addr write + restart + data tx) + * + * This is then followed by actual data for a write. + * + * At this point, the OF driver seems to have a limitation on transfer + * sizes of 0xd bytes on reads and 0x5 bytes on writes. I do not know + * wether this is just an OF limit due to some temporary buffer size + * or if this is an SMU imposed limit. This driver has the same limitation + * for now as I use a 0x10 bytes temporary buffer as well + * + * Once that is completed, a response is expected from the SMU. This is + * obtained via a command of type 0x9a with a length of 1 byte containing + * 0 as the data byte. OF also fills the rest of the data buffer with 0xff's + * though I can't tell yet if this is actually necessary. Once this command + * is complete, at this point, all I can tell is what OF does. OF tests + * byte 0 of the reply: + * - on read, 0xfe or 0xfc : bus is busy, wait (see below) or nak ? + * - on read, 0x00 or 0x01 : reply is in buffer (after the byte 0) + * - on write, < 0 -> failure (immediate exit) + * - else, OF just exists (without error, weird) + * + * So on read, there is this wait-for-busy thing when getting a 0xfc or + * 0xfe result. OF does a loop of up to 64 retries, waiting 20ms and + * doing the above again until either the retries expire or the result + * is no longer 0xfe or 0xfc + * + * The Darwin I2C driver is less subtle though. On any non-success status + * from the response command, it waits 5ms and tries again up to 20 times, + * it doesn't differenciate between fatal errors or "busy" status. + * + * This driver provides an asynchronous paramblock based i2c command + * interface to be used either directly by low level code or by a higher + * level driver interfacing to the linux i2c layer. The current + * implementation of this relies on working timers & timer interrupts + * though, so be careful of calling context for now. This may be "fixed" + * in the future by adding a polling facility. + */ +#define SMU_CMD_I2C_COMMAND 0x9a + /* transfer types */ +#define SMU_I2C_TRANSFER_SIMPLE 0x00 +#define SMU_I2C_TRANSFER_STDSUB 0x01 +#define SMU_I2C_TRANSFER_COMBINED 0x02 + +/* + * Power supply control + * + * The "sub" command is an ASCII string in the data, the + * data lenght is that of the string. + * + * The VSLEW command can be used to get or set the voltage slewing. + * - lenght 5 (only "VSLEW") : it returns "DONE" and 3 bytes of + * reply at data offset 6, 7 and 8. + * - lenght 8 ("VSLEWxyz") has 3 additional bytes appended, and is + * used to set the voltage slewing point. The SMU replies with "DONE" + * I yet have to figure out their exact meaning of those 3 bytes in + * both cases. + * + */ +#define SMU_CMD_POWER_COMMAND 0xaa +#define SMU_CMD_POWER_RESTART "RESTART" +#define SMU_CMD_POWER_SHUTDOWN "SHUTDOWN" +#define SMU_CMD_POWER_VOLTAGE_SLEW "VSLEW" + +/* Misc commands + * + * This command seem to be a grab bag of various things + */ +#define SMU_CMD_MISC_df_COMMAND 0xdf +#define SMU_CMD_MISC_df_SET_DISPLAY_LIT 0x02 /* i: 1 byte */ +#define SMU_CMD_MISC_df_NMI_OPTION 0x04 + +/* + * Version info commands + * + * I haven't quite tried to figure out how these work + */ +#define SMU_CMD_VERSION_COMMAND 0xea + + +/* + * Misc commands + * + * This command seem to be a grab bag of various things + */ +#define SMU_CMD_MISC_ee_COMMAND 0xee +#define SMU_CMD_MISC_ee_GET_DATABLOCK_REC 0x02 +#define SMU_CMD_MISC_ee_LEDS_CTRL 0x04 /* i: 00 (00,01) [00] */ +#define SMU_CMD_MISC_ee_GET_DATA 0x05 /* i: 00 , o: ?? */ + + + +/* + * - Kernel side interface - + */ + +#ifdef __KERNEL__ + +/* + * Asynchronous SMU commands + * + * Fill up this structure and submit it via smu_queue_command(), + * and get notified by the optional done() callback, or because + * status becomes != 1 + */ + +struct smu_cmd; + +struct smu_cmd +{ + /* public */ + u8 cmd; /* command */ + int data_len; /* data len */ + int reply_len; /* reply len */ + void *data_buf; /* data buffer */ + void *reply_buf; /* reply buffer */ + int status; /* command status */ + void (*done)(struct smu_cmd *cmd, void *misc); + void *misc; + + /* private */ + struct list_head link; +}; + +/* + * Queues an SMU command, all fields have to be initialized + */ +extern int smu_queue_cmd(struct smu_cmd *cmd); + +/* + * Simple command wrapper. This structure embeds a small buffer + * to ease sending simple SMU commands from the stack + */ +struct smu_simple_cmd +{ + struct smu_cmd cmd; + u8 buffer[16]; +}; + +/* + * Queues a simple command. All fields will be initialized by that + * function + */ +extern int smu_queue_simple(struct smu_simple_cmd *scmd, u8 command, + unsigned int data_len, + void (*done)(struct smu_cmd *cmd, void *misc), + void *misc, + ...); + +/* + * Completion helper. Pass it to smu_queue_simple or as 'done' + * member to smu_queue_cmd, it will call complete() on the struct + * completion passed in the "misc" argument + */ +extern void smu_done_complete(struct smu_cmd *cmd, void *misc); /* - * Basic routines for use by architecture. To be extended as - * we understand more of the chip + * Synchronous helpers. Will spin-wait for completion of a command + */ +extern void smu_spinwait_cmd(struct smu_cmd *cmd); + +static inline void smu_spinwait_simple(struct smu_simple_cmd *scmd) +{ + smu_spinwait_cmd(&scmd->cmd); +} + +/* + * Poll routine to call if blocked with irqs off + */ +extern void smu_poll(void); + + +/* + * Init routine, presence check.... */ extern int smu_init(void); extern int smu_present(void); +struct of_device; +extern struct of_device *smu_get_ofdev(void); + + +/* + * Common command wrappers + */ extern void smu_shutdown(void); extern void smu_restart(void); -extern int smu_get_rtc_time(struct rtc_time *time); -extern int smu_set_rtc_time(struct rtc_time *time); +struct rtc_time; +extern int smu_get_rtc_time(struct rtc_time *time, int spinwait); +extern int smu_set_rtc_time(struct rtc_time *time, int spinwait); /* * SMU command buffer absolute address, exported by pmac_setup, * this is allocated very early during boot. */ extern unsigned long smu_cmdbuf_abs; + + +/* + * Kenrel asynchronous i2c interface + */ + +/* SMU i2c header, exactly matches i2c header on wire */ +struct smu_i2c_param +{ + u8 bus; /* SMU bus ID (from device tree) */ + u8 type; /* i2c transfer type */ + u8 devaddr; /* device address (includes direction) */ + u8 sublen; /* subaddress length */ + u8 subaddr[3]; /* subaddress */ + u8 caddr; /* combined address, filled by SMU driver */ + u8 datalen; /* length of transfer */ + u8 data[7]; /* data */ +}; + +#define SMU_I2C_READ_MAX 0x0d +#define SMU_I2C_WRITE_MAX 0x05 + +struct smu_i2c_cmd +{ + /* public */ + struct smu_i2c_param info; + void (*done)(struct smu_i2c_cmd *cmd, void *misc); + void *misc; + int status; /* 1 = pending, 0 = ok, <0 = fail */ + + /* private */ + struct smu_cmd scmd; + int read; + int stage; + int retries; + u8 pdata[0x10]; + struct list_head link; +}; + +/* + * Call this to queue an i2c command to the SMU. You must fill info, + * including info.data for a write, done and misc. + * For now, no polling interface is provided so you have to use completion + * callback. + */ +extern int smu_queue_i2c(struct smu_i2c_cmd *cmd); + + +#endif /* __KERNEL__ */ + +/* + * - Userland interface - + */ + +/* + * A given instance of the device can be configured for 2 different + * things at the moment: + * + * - sending SMU commands (default at open() time) + * - receiving SMU events (not yet implemented) + * + * Commands are written with write() of a command block. They can be + * "driver" commands (for example to switch to event reception mode) + * or real SMU commands. They are made of a header followed by command + * data if any. + * + * For SMU commands (not for driver commands), you can then read() back + * a reply. The reader will be blocked or not depending on how the device + * file is opened. poll() isn't implemented yet. The reply will consist + * of a header as well, followed by the reply data if any. You should + * always provide a buffer large enough for the maximum reply data, I + * recommand one page. + * + * It is illegal to send SMU commands through a file descriptor configured + * for events reception + * + */ +struct smu_user_cmd_hdr +{ + __u32 cmdtype; +#define SMU_CMDTYPE_SMU 0 /* SMU command */ +#define SMU_CMDTYPE_WANTS_EVENTS 1 /* switch fd to events mode */ + + __u8 cmd; /* SMU command byte */ + __u32 data_len; /* Lenght of data following */ +}; + +struct smu_user_reply_hdr +{ + __u32 status; /* Command status */ + __u32 reply_len; /* Lenght of data follwing */ +}; + +#endif /* _SMU_H */ Index: linux-work/arch/ppc64/kernel/pmac_time.c =================================================================== --- linux-work.orig/arch/ppc64/kernel/pmac_time.c 2005-09-20 11:54:53.000000000 +1000 +++ linux-work/arch/ppc64/kernel/pmac_time.c 2005-09-20 11:57:47.000000000 +1000 @@ -84,7 +84,7 @@ #ifdef CONFIG_PMAC_SMU case SYS_CTRLER_SMU: - smu_get_rtc_time(tm); + smu_get_rtc_time(tm, 1); break; #endif /* CONFIG_PMAC_SMU */ default: @@ -128,7 +128,7 @@ #ifdef CONFIG_PMAC_SMU case SYS_CTRLER_SMU: - return smu_set_rtc_time(tm); + return smu_set_rtc_time(tm, 1); #endif /* CONFIG_PMAC_SMU */ default: return -ENODEV; Index: linux-work/drivers/i2c/busses/i2c-pmac-smu.c =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ linux-work/drivers/i2c/busses/i2c-pmac-smu.c 2005-09-20 11:58:25.000000000 +1000 @@ -0,0 +1,316 @@ +/* + i2c Support for Apple SMU Controller + + Copyright (c) 2005 Benjamin Herrenschmidt, 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. + + 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 +#include + +static int probe; + +MODULE_AUTHOR("Benjamin Herrenschmidt "); +MODULE_DESCRIPTION("I2C driver for Apple's SMU"); +MODULE_LICENSE("GPL"); +module_param(probe, bool, 0); + + +/* Physical interface */ +struct smu_iface +{ + struct i2c_adapter adapter; + struct completion complete; + u32 busid; +}; + +static void smu_i2c_done(struct smu_i2c_cmd *cmd, void *misc) +{ + struct smu_iface *iface = misc; + complete(&iface->complete); +} + +/* + * SMBUS-type transfer entrypoint + */ +static s32 smu_smbus_xfer( struct i2c_adapter* adap, + u16 addr, + unsigned short flags, + char read_write, + u8 command, + int size, + union i2c_smbus_data* data) +{ + struct smu_iface *iface = i2c_get_adapdata(adap); + struct smu_i2c_cmd cmd; + int rc = 0; + int read = (read_write == I2C_SMBUS_READ); + + cmd.info.bus = iface->busid; + cmd.info.devaddr = (addr << 1) | (read ? 0x01 : 0x00); + + /* Prepare datas & select mode */ + switch (size) { + case I2C_SMBUS_QUICK: + cmd.info.type = SMU_I2C_TRANSFER_SIMPLE; + cmd.info.datalen = 0; + break; + case I2C_SMBUS_BYTE: + cmd.info.type = SMU_I2C_TRANSFER_SIMPLE; + cmd.info.datalen = 1; + if (!read) + cmd.info.data[0] = data->byte; + break; + case I2C_SMBUS_BYTE_DATA: + cmd.info.type = SMU_I2C_TRANSFER_STDSUB; + cmd.info.datalen = 1; + cmd.info.sublen = 1; + cmd.info.subaddr[0] = command; + cmd.info.subaddr[1] = 0; + cmd.info.subaddr[2] = 0; + if (!read) + cmd.info.data[0] = data->byte; + break; + case I2C_SMBUS_WORD_DATA: + cmd.info.type = SMU_I2C_TRANSFER_STDSUB; + cmd.info.datalen = 2; + cmd.info.sublen = 1; + cmd.info.subaddr[0] = command; + cmd.info.subaddr[1] = 0; + cmd.info.subaddr[2] = 0; + if (!read) { + cmd.info.data[0] = data->byte & 0xff; + cmd.info.data[1] = (data->byte >> 8) & 0xff; + } + break; + /* Note that these are broken vs. the expected smbus API where + * on reads, the lenght is actually returned from the function, + * but I think the current API makes no sense and I don't want + * any driver that I haven't verified for correctness to go + * anywhere near a pmac i2c bus anyway ... + */ + case I2C_SMBUS_BLOCK_DATA: + cmd.info.type = SMU_I2C_TRANSFER_STDSUB; + cmd.info.datalen = data->block[0] + 1; + if (cmd.info.datalen > 6) + return -EINVAL; + if (!read) + memcpy(cmd.info.data, data->block, cmd.info.datalen); + cmd.info.sublen = 1; + cmd.info.subaddr[0] = command; + cmd.info.subaddr[1] = 0; + cmd.info.subaddr[2] = 0; + break; + case I2C_SMBUS_I2C_BLOCK_DATA: + cmd.info.type = SMU_I2C_TRANSFER_STDSUB; + cmd.info.datalen = data->block[0]; + if (cmd.info.datalen > 7) + return -EINVAL; + if (!read) + memcpy(cmd.info.data, &data->block[1], + cmd.info.datalen); + cmd.info.sublen = 1; + cmd.info.subaddr[0] = command; + cmd.info.subaddr[1] = 0; + cmd.info.subaddr[2] = 0; + break; + + default: + return -EINVAL; + } + + /* Turn a standardsub read into a combined mode access */ + if (read_write == I2C_SMBUS_READ && + cmd.info.type == SMU_I2C_TRANSFER_STDSUB) + cmd.info.type = SMU_I2C_TRANSFER_COMBINED; + + /* Finish filling command and submit it */ + cmd.done = smu_i2c_done; + cmd.misc = iface; + rc = smu_queue_i2c(&cmd); + if (rc < 0) + return rc; + wait_for_completion(&iface->complete); + rc = cmd.status; + + if (!read || rc < 0) + return rc; + + switch (size) { + case I2C_SMBUS_BYTE: + case I2C_SMBUS_BYTE_DATA: + data->byte = cmd.info.data[0]; + break; + case I2C_SMBUS_WORD_DATA: + data->word = ((u16)cmd.info.data[1]) << 8; + data->word |= cmd.info.data[0]; + break; + /* Note that these are broken vs. the expected smbus API where + * on reads, the lenght is actually returned from the function, + * but I think the current API makes no sense and I don't want + * any driver that I haven't verified for correctness to go + * anywhere near a pmac i2c bus anyway ... + */ + case I2C_SMBUS_BLOCK_DATA: + case I2C_SMBUS_I2C_BLOCK_DATA: + memcpy(&data->block[0], cmd.info.data, cmd.info.datalen); + break; + } + + return rc; +} + +static u32 +smu_smbus_func(struct i2c_adapter * adapter) +{ + return I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE | + I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA | + I2C_FUNC_SMBUS_BLOCK_DATA; +} + +/* For now, we only handle combined mode (smbus) */ +static struct i2c_algorithm smu_algorithm = { + .smbus_xfer = smu_smbus_xfer, + .functionality = smu_smbus_func, +}; + +static int create_iface(struct device_node *np, struct device *dev) +{ + struct smu_iface* iface; + u32 *reg, busid; + int rc; + + reg = (u32 *)get_property(np, "reg", NULL); + if (reg == NULL) { + printk(KERN_ERR "i2c-pmac-smu: can't find bus number !\n"); + return -ENXIO; + } + busid = *reg; + + iface = kmalloc(sizeof(struct smu_iface), GFP_KERNEL); + if (iface == NULL) { + printk(KERN_ERR "i2c-pmac-smu: can't allocate inteface !\n"); + return -ENOMEM; + } + memset(iface, 0, sizeof(struct smu_iface)); + init_completion(&iface->complete); + iface->busid = busid; + + dev_set_drvdata(dev, iface); + + sprintf(iface->adapter.name, "smu-i2c-%02x", busid); + iface->adapter.algo = &smu_algorithm; + iface->adapter.algo_data = NULL; + iface->adapter.client_register = NULL; + iface->adapter.client_unregister = NULL; + i2c_set_adapdata(&iface->adapter, iface); + iface->adapter.dev.parent = dev; + + rc = i2c_add_adapter(&iface->adapter); + if (rc) { + printk(KERN_ERR "i2c-pamc-smu.c: Adapter %s registration " + "failed\n", iface->adapter.name); + i2c_set_adapdata(&iface->adapter, NULL); + } + + if (probe) { + unsigned char addr; + printk("Probe: "); + for (addr = 0x00; addr <= 0x7f; addr++) { + if (i2c_smbus_xfer(&iface->adapter,addr, + 0,0,0,I2C_SMBUS_QUICK,NULL) >= 0) + printk("%02x ", addr); + } + printk("\n"); + } + + printk(KERN_INFO "SMU i2c bus %x registered\n", busid); + + return 0; +} + +static int dispose_iface(struct device *dev) +{ + struct smu_iface *iface = dev_get_drvdata(dev); + int rc; + + rc = i2c_del_adapter(&iface->adapter); + i2c_set_adapdata(&iface->adapter, NULL); + /* We aren't that prepared to deal with this... */ + if (rc) + printk("i2c-pmac-smu.c: Failed to remove bus %s !\n", + iface->adapter.name); + dev_set_drvdata(dev, NULL); + kfree(iface); + + return 0; +} + + +static int create_iface_of_platform(struct of_device* dev, + const struct of_device_id *match) +{ + return create_iface(dev->node, &dev->dev); +} + + +static int dispose_iface_of_platform(struct of_device* dev) +{ + return dispose_iface(&dev->dev); +} + + +static struct of_device_id i2c_smu_match[] = +{ + { + .compatible = "smu-i2c", + }, + {}, +}; +static struct of_platform_driver i2c_smu_of_platform_driver = +{ + .name = "i2c-smu", + .match_table = i2c_smu_match, + .probe = create_iface_of_platform, + .remove = dispose_iface_of_platform +}; + + +static int __init i2c_pmac_smu_init(void) +{ + of_register_driver(&i2c_smu_of_platform_driver); + return 0; +} + + +static void __exit i2c_pmac_smu_cleanup(void) +{ + of_unregister_driver(&i2c_smu_of_platform_driver); +} + +module_init(i2c_pmac_smu_init); +module_exit(i2c_pmac_smu_cleanup); Index: linux-work/drivers/i2c/busses/Kconfig =================================================================== --- linux-work.orig/drivers/i2c/busses/Kconfig 2005-09-20 11:54:53.000000000 +1000 +++ linux-work/drivers/i2c/busses/Kconfig 2005-09-20 11:58:57.000000000 +1000 @@ -245,6 +245,18 @@ This support is also available as a module. If so, the module will be called i2c-keywest. +config I2C_PMAC_SMU + tristate "Powermac SMU I2C interface" + depends on I2C && PMAC_SMU + help + This supports the use of the I2C interface in the SMU + chip on recent Apple machines like the iMac G5. It is used + among others by the thermal control driver for those machines. + Say Y if you have such a machine. + + This support is also available as a module. If so, the module + will be called i2c-pmac-smu. + config I2C_MPC tristate "MPC107/824x/85xx/52xx" depends on I2C && PPC32 Index: linux-work/drivers/i2c/busses/Makefile =================================================================== --- linux-work.orig/drivers/i2c/busses/Makefile 2005-09-20 11:54:53.000000000 +1000 +++ linux-work/drivers/i2c/busses/Makefile 2005-09-20 11:57:47.000000000 +1000 @@ -20,6 +20,7 @@ obj-$(CONFIG_I2C_IXP2000) += i2c-ixp2000.o obj-$(CONFIG_I2C_IXP4XX) += i2c-ixp4xx.o obj-$(CONFIG_I2C_KEYWEST) += i2c-keywest.o +obj-$(CONFIG_I2C_PMAC_SMU) += i2c-pmac-smu.o obj-$(CONFIG_I2C_MPC) += i2c-mpc.o obj-$(CONFIG_I2C_MV64XXX) += i2c-mv64xxx.o obj-$(CONFIG_I2C_NFORCE2) += i2c-nforce2.o Index: linux-work/arch/ppc64/kernel/pmac_setup.c =================================================================== --- linux-work.orig/arch/ppc64/kernel/pmac_setup.c 2005-09-20 11:54:53.000000000 +1000 +++ linux-work/arch/ppc64/kernel/pmac_setup.c 2005-09-20 11:57:47.000000000 +1000 @@ -434,15 +434,23 @@ static int __init pmac_declare_of_platform_devices(void) { - struct device_node *np; + struct device_node *np, *npp; - np = find_devices("u3"); - if (np) { - for (np = np->child; np != NULL; np = np->sibling) + npp = of_find_node_by_name(NULL, "u3"); + if (npp) { + for (np = NULL; (np = of_get_next_child(npp, np)) != NULL;) { if (strncmp(np->name, "i2c", 3) == 0) { - of_platform_device_create(np, "u3-i2c"); + of_platform_device_create(np, "u3-i2c", NULL); + of_node_put(np); break; } + } + of_node_put(npp); + } + npp = of_find_node_by_type(NULL, "smu"); + if (npp) { + of_platform_device_create(npp, "smu", NULL); + of_node_put(npp); } return 0; Index: linux-work/drivers/macintosh/therm_adt746x.c =================================================================== --- linux-work.orig/drivers/macintosh/therm_adt746x.c 2005-09-20 11:54:53.000000000 +1000 +++ linux-work/drivers/macintosh/therm_adt746x.c 2005-09-20 11:57:47.000000000 +1000 @@ -599,7 +599,7 @@ sensor_location[2] = "?"; } - of_dev = of_platform_device_create(np, "temperatures"); + of_dev = of_platform_device_create(np, "temperatures", NULL); if (of_dev == NULL) { printk(KERN_ERR "Can't register temperatures device !\n"); Index: linux-work/drivers/macintosh/therm_pm72.c =================================================================== --- linux-work.orig/drivers/macintosh/therm_pm72.c 2005-09-20 11:54:53.000000000 +1000 +++ linux-work/drivers/macintosh/therm_pm72.c 2005-09-20 11:57:47.000000000 +1000 @@ -2051,7 +2051,7 @@ return -ENODEV; } } - of_dev = of_platform_device_create(np, "temperature"); + of_dev = of_platform_device_create(np, "temperature", NULL); if (of_dev == NULL) { printk(KERN_ERR "Can't register FCU platform device !\n"); return -ENODEV; Index: linux-work/arch/ppc64/kernel/of_device.c =================================================================== --- linux-work.orig/arch/ppc64/kernel/of_device.c 2005-09-20 11:54:53.000000000 +1000 +++ linux-work/arch/ppc64/kernel/of_device.c 2005-09-20 11:57:47.000000000 +1000 @@ -233,7 +233,9 @@ device_unregister(&ofdev->dev); } -struct of_device* of_platform_device_create(struct device_node *np, const char *bus_id) +struct of_device* of_platform_device_create(struct device_node *np, + const char *bus_id, + struct device *parent) { struct of_device *dev; @@ -245,7 +247,7 @@ dev->node = np; dev->dma_mask = 0xffffffffUL; dev->dev.dma_mask = &dev->dma_mask; - dev->dev.parent = NULL; + dev->dev.parent = parent; dev->dev.bus = &of_platform_bus_type; dev->dev.release = of_release_dev; @@ -259,6 +261,7 @@ return dev; } + EXPORT_SYMBOL(of_match_device); EXPORT_SYMBOL(of_platform_bus_type); EXPORT_SYMBOL(of_register_driver); Index: linux-work/arch/ppc/platforms/pmac_setup.c =================================================================== --- linux-work.orig/arch/ppc/platforms/pmac_setup.c 2005-09-20 11:54:53.000000000 +1000 +++ linux-work/arch/ppc/platforms/pmac_setup.c 2005-09-20 11:57:47.000000000 +1000 @@ -719,7 +719,8 @@ if (np) { for (np = np->child; np != NULL; np = np->sibling) if (strncmp(np->name, "i2c", 3) == 0) { - of_platform_device_create(np, "uni-n-i2c"); + of_platform_device_create(np, "uni-n-i2c", + NULL); break; } } @@ -727,17 +728,18 @@ if (np) { for (np = np->child; np != NULL; np = np->sibling) if (strncmp(np->name, "i2c", 3) == 0) { - of_platform_device_create(np, "u3-i2c"); + of_platform_device_create(np, "u3-i2c", + NULL); break; } } np = find_devices("valkyrie"); if (np) - of_platform_device_create(np, "valkyrie"); + of_platform_device_create(np, "valkyrie", NULL); np = find_devices("platinum"); if (np) - of_platform_device_create(np, "platinum"); + of_platform_device_create(np, "platinum", NULL); return 0; } Index: linux-work/include/asm-ppc/of_device.h =================================================================== --- linux-work.orig/include/asm-ppc/of_device.h 2005-09-20 11:54:53.000000000 +1000 +++ linux-work/include/asm-ppc/of_device.h 2005-09-20 11:57:47.000000000 +1000 @@ -2,6 +2,7 @@ #define __OF_DEVICE_H__ #include +#include #include /* @@ -55,7 +56,9 @@ extern void of_unregister_driver(struct of_platform_driver *drv); extern int of_device_register(struct of_device *ofdev); extern void of_device_unregister(struct of_device *ofdev); -extern struct of_device *of_platform_device_create(struct device_node *np, const char *bus_id); +extern struct of_device *of_platform_device_create(struct device_node *np, + const char *bus_id, + struct device *parent); extern void of_release_dev(struct device *dev); #endif /* __OF_DEVICE_H__ */ Index: linux-work/arch/ppc/syslib/of_device.c =================================================================== --- linux-work.orig/arch/ppc/syslib/of_device.c 2005-09-20 11:54:53.000000000 +1000 +++ linux-work/arch/ppc/syslib/of_device.c 2005-09-20 11:57:47.000000000 +1000 @@ -234,7 +234,9 @@ device_unregister(&ofdev->dev); } -struct of_device* of_platform_device_create(struct device_node *np, const char *bus_id) +struct of_device* of_platform_device_create(struct device_node *np, + const char *bus_id, + struct device *parent) { struct of_device *dev; u32 *reg; @@ -247,7 +249,7 @@ dev->node = of_node_get(np); dev->dma_mask = 0xffffffffUL; dev->dev.dma_mask = &dev->dma_mask; - dev->dev.parent = NULL; + dev->dev.parent = parent; dev->dev.bus = &of_platform_bus_type; dev->dev.release = of_release_dev; Index: linux-work/include/asm-ppc/macio.h =================================================================== --- linux-work.orig/include/asm-ppc/macio.h 2005-09-20 11:54:53.000000000 +1000 +++ linux-work/include/asm-ppc/macio.h 2005-09-20 11:57:47.000000000 +1000 @@ -1,7 +1,6 @@ #ifndef __MACIO_ASIC_H__ #define __MACIO_ASIC_H__ -#include #include extern struct bus_type macio_bus_type; From benh at kernel.crashing.org Tue Sep 20 13:28:37 2005 From: benh at kernel.crashing.org (Benjamin Herrenschmidt) Date: Tue, 20 Sep 2005 13:28:37 +1000 Subject: iMac G5 frequency switching In-Reply-To: <20050912163453.GA24025@victor.rh.local> References: <20050909114311.GA3732@victor.rh.local> <1126389498.29803.58.camel@gaston> <20050912163453.GA24025@victor.rh.local> Message-ID: <1127186918.4386.39.camel@gaston> > If some kind soul has a newer iMac G5 and would let me telnet into > OF, I'd be willing to try my luck and see if there's something > different in there, otherwise someone would have to dive into > whatever OS X does. That someone is unlikely to be me, to be > entirely frank -- I probably can't spend much more time (which I'd > need to get up to speed reading ppc64 machine code) on this until > some time in March 2006. Sorry. > > I *would* have time to explain my findings so far, as poor as they > are, to anyone wanting to take up the voltage control issue on the > imac G5s. So, if anyone coming across this while googling for imac G5 > support in Linux feels like kernel work, drop me a mail... You should read the OS X platform code. It tells you how to decode the data in the "smu-partition-*" properties of the smu node. Especially, look for "SMU_Neo2_PlatformPlugin.h" Those contain lots of useful things, including the list of "operating points". From what I've seen so far, iMac G5s don't seem to have more than one, with only one sysclk. This is in partition 0x12 (kCPU_FVT_OperatingPointsPartID) One operating point is a structure containing: - a sysclk (that is the master clock controller by the pulsar chip) - a Tmax, that is the max temperature allowed before switching to the next operating point (or overtemp if none) - the CPU core voltage setting for the 3 powertunes states (full freq, 1/2 and 1/4). Note that only 1/2 is actually supported, thus the value for 1/4 in the device-trees I've seen so far is always 0 Anyway, I'll try to spend some time this week doing a crude cpufreq driver doing proper voltage switching at least (no operating point change, first because I haven't access to a machine that has more than one operating point, and because I don't know how to deal with pulsar chips). I may also give a go to a thermal driver. Ben. From benh at kernel.crashing.org Tue Sep 20 13:43:45 2005 From: benh at kernel.crashing.org (Benjamin Herrenschmidt) Date: Tue, 20 Sep 2005 13:43:45 +1000 Subject: [PATCH] ppc64: Build zImage.vmode for G5 Message-ID: <1127187825.4386.44.camel@gaston> zImage.vmode was recently added. It's a version of zImage in which the ELF note section used by open firmware indicates that it requires a virtual mode instance of OF instead of real mode. This allows it to work with Apple OF, and thus is directly bootable (or netbootable) from OF command line. (Unfortunately, pSeries OF sort-of requires real mode and Apple OF sort-of requires virtual mode, and both tend to be unhappy if no notes section specifies the mode at all). However, we forgot to add zImage.vmode to the default G5 build. This fixes it. Signed-off-by: Benjamin Herrenschmidt Index: linux-work/arch/ppc64/Makefile =================================================================== --- linux-work.orig/arch/ppc64/Makefile 2005-09-20 09:54:18.000000000 +1000 +++ linux-work/arch/ppc64/Makefile 2005-09-20 11:57:22.000000000 +1000 @@ -107,7 +107,7 @@ $(Q)$(MAKE) $(build)=$(boot) BOOTIMAGE=$(BOOTIMAGE) $@ defaultimage-$(CONFIG_PPC_PSERIES) := zImage -defaultimage-$(CONFIG_PPC_PMAC) := vmlinux +defaultimage-$(CONFIG_PPC_PMAC) := zImage.vmode defaultimage-$(CONFIG_PPC_MAPLE) := zImage defaultimage-$(CONFIG_PPC_ISERIES) := vmlinux KBUILD_IMAGE := $(defaultimage-y) From cartoes at terra.com.br Tue Sep 20 13:08:13 2005 From: cartoes at terra.com.br (cartoes at terra.com.br) Date: Tue, 20 Sep 2005 05:08:13 +0200 Subject: Esse Cartao foi feito para voce Message-ID: <20050920030813.51261104E55@yuzu.dream.hu> An HTML attachment was scrubbed... URL: http://ozlabs.org/pipermail/linuxppc64-dev/attachments/20050920/3c932b5a/attachment.htm From benh at kernel.crashing.org Tue Sep 20 13:45:41 2005 From: benh at kernel.crashing.org (Benjamin Herrenschmidt) Date: Tue, 20 Sep 2005 13:45:41 +1000 Subject: [PATCH] ppc64: Updated Olof iommu updates 1/3 Message-ID: <1127187942.4386.47.camel@gaston> From: Olof Johansson 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-20 10:22:55.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-20 10:22:55.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-20 10:22:55.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-09-20 09:54:18.000000000 +1000 +++ linux-work/arch/ppc64/kernel/u3_iommu.c 2005-09-20 10:22:55.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-09-20 09:54:18.000000000 +1000 +++ linux-work/arch/ppc64/kernel/pSeries_iommu.c 2005-09-20 10:22:55.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-20 10:22:55.000000000 +1000 @@ -22,6 +22,7 @@ #include #include #include +#include extern struct subsystem devices_subsys; /* needed for vio_find_name() */ Index: linux-work/arch/ppc64/kernel/iSeries_iommu.c =================================================================== --- linux-work.orig/arch/ppc64/kernel/iSeries_iommu.c 2005-08-24 13:26:31.000000000 +1000 +++ linux-work/arch/ppc64/kernel/iSeries_iommu.c 2005-09-20 10:22:55.000000000 +1000 @@ -30,6 +30,7 @@ #include #include +#include #include #include #include Index: linux-work/arch/ppc64/kernel/iSeries_vio.c =================================================================== --- linux-work.orig/arch/ppc64/kernel/iSeries_vio.c 2005-09-01 13:05:12.000000000 +1000 +++ linux-work/arch/ppc64/kernel/iSeries_vio.c 2005-09-20 10:22:55.000000000 +1000 @@ -14,6 +14,7 @@ #include #include +#include #include #include #include From benh at kernel.crashing.org Tue Sep 20 13:46:44 2005 From: benh at kernel.crashing.org (Benjamin Herrenschmidt) Date: Tue, 20 Sep 2005 13:46:44 +1000 Subject: [PATCH] ppc64: Updated Olof iommu updates 2/3 Message-ID: <1127188004.4386.50.camel@gaston> From: Olof Johansson 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 20 13:47:41 2005 From: benh at kernel.crashing.org (Benjamin Herrenschmidt) Date: Tue, 20 Sep 2005 13:47:41 +1000 Subject: [PATCH] ppc64: Updated Olof misc updates 3/3 Message-ID: <1127188061.4386.51.camel@gaston> From: Olof Johansson 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-20 09:54:18.000000000 +1000 +++ linux-work/arch/ppc64/kernel/head.S 2005-09-20 13:36:29.000000000 +1000 @@ -1992,7 +1992,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-09-20 09:54:18.000000000 +1000 +++ linux-work/arch/ppc64/kernel/misc.S 2005-09-20 13:36:29.000000000 +1000 @@ -329,7 +329,7 @@ /* Flush the dcache */ ld r7,PPC64_CACHES at toc(r2) - clrrdi r3,r3,12 /* Page align */ + clrrdi r3,r3,PAGE_SHIFT /* Page align */ lwz r4,DCACHEL1LINESPERPAGE(r7) /* Get # dcache lines per page */ lwz r5,DCACHEL1LINESIZE(r7) /* Get dcache line size */ mr r6,r3 Index: linux-work/arch/ppc64/kernel/vmlinux.lds.S =================================================================== --- linux-work.orig/arch/ppc64/kernel/vmlinux.lds.S 2005-09-20 09:54:18.000000000 +1000 +++ linux-work/arch/ppc64/kernel/vmlinux.lds.S 2005-09-20 13:38:14.000000000 +1000 @@ -1,3 +1,4 @@ +#include #include OUTPUT_ARCH(powerpc:common64) @@ -17,7 +18,7 @@ LOCK_TEXT KPROBES_TEXT *(.fixup) - . = ALIGN(4096); + . = ALIGN(PAGE_SIZE); _etext = .; } @@ -43,7 +44,7 @@ /* will be freed after init */ - . = ALIGN(4096); + . = ALIGN(PAGE_SIZE); __init_begin = .; .init.text : { @@ -83,7 +84,7 @@ SECURITY_INIT - . = ALIGN(4096); + . = ALIGN(PAGE_SIZE); .init.ramfs : { __initramfs_start = .; *(.init.ramfs) @@ -96,18 +97,21 @@ __per_cpu_end = .; } + . = ALIGN(PAGE_SIZE); . = ALIGN(16384); __init_end = .; /* freed after init ends here */ /* Read/write sections */ + . = ALIGN(PAGE_SIZE); . = ALIGN(16384); /* The initial task and kernel stack */ .data.init_task : { *(.data.init_task) } + . = ALIGN(PAGE_SIZE); .data.page_aligned : { *(.data.page_aligned) } @@ -129,18 +133,18 @@ __toc_start = .; *(.got) *(.toc) - . = ALIGN(4096); + . = ALIGN(PAGE_SIZE); _edata = .; } - . = ALIGN(4096); + . = ALIGN(PAGE_SIZE); .bss : { __bss_start = .; *(.bss) __bss_stop = .; } - . = ALIGN(4096); + . = ALIGN(PAGE_SIZE); _end = . ; } Index: linux-work/include/asm-ppc64/elf.h =================================================================== --- linux-work.orig/include/asm-ppc64/elf.h 2005-09-20 09:54:26.000000000 +1000 +++ linux-work/include/asm-ppc64/elf.h 2005-09-20 13:36:54.000000000 +1000 @@ -5,6 +5,7 @@ #include #include #include +#include /* PowerPC relocations defined by the ABIs */ #define R_PPC_NONE 0 @@ -146,7 +147,7 @@ #define elf_check_arch(x) ((x)->e_machine == ELF_ARCH) #define USE_ELF_CORE_DUMP -#define ELF_EXEC_PAGESIZE 4096 +#define ELF_EXEC_PAGESIZE PAGE_SIZE /* This is the location that an ET_DYN program is loaded if exec'ed. Typical use of this is to invoke "./ld.so someprog" to test out a new version of Index: linux-work/include/asm-ppc64/thread_info.h =================================================================== --- linux-work.orig/include/asm-ppc64/thread_info.h 2005-08-24 13:26:46.000000000 +1000 +++ linux-work/include/asm-ppc64/thread_info.h 2005-09-20 13:36:29.000000000 +1000 @@ -54,9 +54,9 @@ /* thread information allocation */ -#define THREAD_ORDER 2 -#define THREAD_SIZE (PAGE_SIZE << THREAD_ORDER) -#define THREAD_SHIFT (PAGE_SHIFT + THREAD_ORDER) +#define THREAD_SHIFT 14 +#define THREAD_ORDER (THREAD_SHIFT - PAGE_SHIFT) +#define THREAD_SIZE (1 << THREAD_SHIFT) #ifdef CONFIG_DEBUG_STACK_USAGE #define alloc_thread_info(tsk) \ ({ \ Index: linux-work/include/asm-ppc64/mmu.h =================================================================== --- linux-work.orig/include/asm-ppc64/mmu.h 2005-09-07 11:09:56.000000000 +1000 +++ linux-work/include/asm-ppc64/mmu.h 2005-09-20 13:36:29.000000000 +1000 @@ -29,7 +29,7 @@ /* Location of cpu0's segment table */ #define STAB0_PAGE 0x6 -#define STAB0_PHYS_ADDR (STAB0_PAGE< This patch slightly change the TLB flush batch mecanism so that we store the full vaddr (including vsid) when adding an entry to the batch so that the flush part doesn't have to get to the context. This cleans it a bit, and paves the way to future updates like dynamic vsids. Signed-off-by: Benjamin Herrenschmidt Index: linux-work/include/asm-ppc64/tlbflush.h =================================================================== --- linux-work.orig/include/asm-ppc64/tlbflush.h 2005-09-20 13:51:36.000000000 +1000 +++ linux-work/include/asm-ppc64/tlbflush.h 2005-09-20 13:51:42.000000000 +1000 @@ -20,10 +20,8 @@ struct mm_struct; struct ppc64_tlb_batch { unsigned long index; - unsigned long context; struct mm_struct *mm; pte_t pte[PPC64_TLB_BATCH_NR]; - unsigned long addr[PPC64_TLB_BATCH_NR]; unsigned long vaddr[PPC64_TLB_BATCH_NR]; }; DECLARE_PER_CPU(struct ppc64_tlb_batch, ppc64_tlb_batch); @@ -47,8 +45,7 @@ #define flush_tlb_kernel_range(start, end) flush_tlb_pending() #define flush_tlb_pgtables(mm, start, end) do { } while (0) -extern void flush_hash_page(unsigned long context, unsigned long ea, pte_t pte, - int local); -void flush_hash_range(unsigned long context, unsigned long number, int local); +extern void flush_hash_page(unsigned long va, pte_t pte, int local); +void flush_hash_range(unsigned long number, int local); #endif /* _PPC64_TLBFLUSH_H */ Index: linux-work/arch/ppc64/mm/tlb.c =================================================================== --- linux-work.orig/arch/ppc64/mm/tlb.c 2005-09-20 13:51:36.000000000 +1000 +++ linux-work/arch/ppc64/mm/tlb.c 2005-09-20 13:51:42.000000000 +1000 @@ -128,12 +128,10 @@ void hpte_update(struct mm_struct *mm, unsigned long addr, unsigned long pte, int wrprot) { - int i; - unsigned long context = 0; struct ppc64_tlb_batch *batch = &__get_cpu_var(ppc64_tlb_batch); + unsigned long vsid; + int i; - if (REGION_ID(addr) == USER_REGION_ID) - context = mm->context.id; i = batch->index; /* @@ -143,17 +141,19 @@ * up scanning and resetting referenced bits then our batch context * will change mid stream. */ - if (unlikely(i != 0 && context != batch->context)) { + if (unlikely(i != 0 && mm != batch->mm)) { flush_tlb_pending(); i = 0; } - - if (i == 0) { - batch->context = context; + if (i == 0) batch->mm = mm; - } + if (addr < KERNELBASE) { + vsid = get_vsid(mm->context.id, addr); + WARN_ON(vsid == 0); + } else + vsid = get_kernel_vsid(addr); + batch->vaddr[i] = (vsid << 28 ) | (addr & 0x0fffffff); batch->pte[i] = __pte(pte); - batch->addr[i] = addr; batch->index = ++i; if (i >= PPC64_TLB_BATCH_NR) flush_tlb_pending(); @@ -175,10 +175,9 @@ local = 1; if (i == 1) - flush_hash_page(batch->context, batch->addr[0], batch->pte[0], - local); + flush_hash_page(batch->vaddr[0], batch->pte[0], local); else - flush_hash_range(batch->context, i, local); + flush_hash_range(i, local); batch->index = 0; put_cpu(); } Index: linux-work/arch/ppc64/mm/hash_utils.c =================================================================== --- linux-work.orig/arch/ppc64/mm/hash_utils.c 2005-09-20 13:51:36.000000000 +1000 +++ linux-work/arch/ppc64/mm/hash_utils.c 2005-09-20 13:51:42.000000000 +1000 @@ -355,18 +355,11 @@ return ret; } -void flush_hash_page(unsigned long context, unsigned long ea, pte_t pte, - int local) +void flush_hash_page(unsigned long va, pte_t pte, int local) { - unsigned long vsid, vpn, va, hash, secondary, slot; + unsigned long vpn, hash, secondary, slot; unsigned long huge = pte_huge(pte); - if (ea < KERNELBASE) - vsid = get_vsid(context, ea); - else - vsid = get_kernel_vsid(ea); - - va = (vsid << 28) | (ea & 0x0fffffff); if (huge) vpn = va >> HPAGE_SHIFT; else @@ -381,17 +374,17 @@ ppc_md.hpte_invalidate(slot, va, huge, local); } -void flush_hash_range(unsigned long context, unsigned long number, int local) +void flush_hash_range(unsigned long number, int local) { if (ppc_md.flush_hash_range) { - ppc_md.flush_hash_range(context, number, local); + ppc_md.flush_hash_range(number, local); } else { int i; - struct ppc64_tlb_batch *batch = &__get_cpu_var(ppc64_tlb_batch); + struct ppc64_tlb_batch *batch = + &__get_cpu_var(ppc64_tlb_batch); for (i = 0; i < number; i++) - flush_hash_page(context, batch->addr[i], batch->pte[i], - local); + flush_hash_page(batch->vaddr[i], batch->pte[i], local); } } Index: linux-work/include/asm-ppc64/machdep.h =================================================================== --- linux-work.orig/include/asm-ppc64/machdep.h 2005-09-20 13:51:36.000000000 +1000 +++ linux-work/include/asm-ppc64/machdep.h 2005-09-20 13:51:42.000000000 +1000 @@ -56,9 +56,8 @@ unsigned long vflags, unsigned long rflags); long (*hpte_remove)(unsigned long hpte_group); - void (*flush_hash_range)(unsigned long context, - unsigned long number, - int local); + void (*flush_hash_range)(unsigned long number, int local); + /* special for kexec, to be called in real mode, linar mapping is * destroyed as well */ void (*hpte_clear_all)(void); Index: linux-work/arch/ppc64/mm/hash_native.c =================================================================== --- linux-work.orig/arch/ppc64/mm/hash_native.c 2005-09-20 13:51:36.000000000 +1000 +++ linux-work/arch/ppc64/mm/hash_native.c 2005-09-20 13:51:42.000000000 +1000 @@ -335,10 +335,9 @@ local_irq_restore(flags); } -static void native_flush_hash_range(unsigned long context, - unsigned long number, int local) +static void native_flush_hash_range(unsigned long number, int local) { - unsigned long vsid, vpn, va, hash, secondary, slot, flags, avpn; + unsigned long va, vpn, hash, secondary, slot, flags, avpn; int i, j; hpte_t *hptep; unsigned long hpte_v; @@ -351,13 +350,7 @@ j = 0; for (i = 0; i < number; i++) { - if (batch->addr[i] < KERNELBASE) - vsid = get_vsid(context, batch->addr[i]); - else - vsid = get_kernel_vsid(batch->addr[i]); - - va = (vsid << 28) | (batch->addr[i] & 0x0fffffff); - batch->vaddr[j] = va; + va = batch->vaddr[j]; if (large) vpn = va >> HPAGE_SHIFT; else Index: linux-work/arch/ppc64/kernel/pSeries_lpar.c =================================================================== --- linux-work.orig/arch/ppc64/kernel/pSeries_lpar.c 2005-09-20 13:51:36.000000000 +1000 +++ linux-work/arch/ppc64/kernel/pSeries_lpar.c 2005-09-20 13:51:42.000000000 +1000 @@ -486,8 +486,7 @@ * Take a spinlock around flushes to avoid bouncing the hypervisor tlbie * lock. */ -void pSeries_lpar_flush_hash_range(unsigned long context, unsigned long number, - int local) +void pSeries_lpar_flush_hash_range(unsigned long number, int local) { int i; unsigned long flags = 0; @@ -498,7 +497,7 @@ spin_lock_irqsave(&pSeries_lpar_tlbie_lock, flags); for (i = 0; i < number; i++) - flush_hash_page(context, batch->addr[i], batch->pte[i], local); + flush_hash_page(batch->vaddr[i], batch->pte[i], local); if (lock_tlbie) spin_unlock_irqrestore(&pSeries_lpar_tlbie_lock, flags); From sfr at canb.auug.org.au Tue Sep 20 15:35:23 2005 From: sfr at canb.auug.org.au (Stephen Rothwell) Date: Tue, 20 Sep 2005 15:35:23 +1000 Subject: [PATCH] ppc64: Updated Olof iommu updates 2/3 In-Reply-To: <1127188004.4386.50.camel@gaston> References: <1127188004.4386.50.camel@gaston> Message-ID: <20050920153523.17e0f6d0.sfr@canb.auug.org.au> On Tue, 20 Sep 2005 13:46:44 +1000 Benjamin Herrenschmidt wrote: > > @@ -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)); ^^^^ TCE_PAGE_SIZE ? -- 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/20050920/4f865b54/attachment.pgp From olof at lixom.net Tue Sep 20 15:42:57 2005 From: olof at lixom.net (Olof Johansson) Date: Tue, 20 Sep 2005 00:42:57 -0500 Subject: [PATCH] ppc64: Updated Olof iommu updates 2/3 In-Reply-To: <20050920153523.17e0f6d0.sfr@canb.auug.org.au> References: <1127188004.4386.50.camel@gaston> <20050920153523.17e0f6d0.sfr@canb.auug.org.au> Message-ID: <20050920054256.GA12014@austin.ibm.com> On Tue, Sep 20, 2005 at 03:35:23PM +1000, Stephen Rothwell wrote: > On Tue, 20 Sep 2005 13:46:44 +1000 Benjamin Herrenschmidt wrote: > > > > @@ -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)); > ^^^^ > TCE_PAGE_SIZE ? The PAPR explicitly says page size, it's not directly related to the TCE mapping size. It's not yet been explored if the firmware will deal properly with new base page sizes so to play it safe, I hardcoded it at 4K. -Olof > _______________________________________________ > Linuxppc64-dev mailing list > Linuxppc64-dev at ozlabs.org > https://ozlabs.org/mailman/listinfo/linuxppc64-dev From benh at kernel.crashing.org Tue Sep 20 18:02:42 2005 From: benh at kernel.crashing.org (Benjamin Herrenschmidt) Date: Tue, 20 Sep 2005 18:02:42 +1000 Subject: iMac G5 frequency switching In-Reply-To: <20050909114311.GA3732@victor.rh.local> References: <20050909114311.GA3732@victor.rh.local> Message-ID: <1127203363.4386.60.camel@gaston> Ok, here is a reworked version that works on the iMac G5 1.6Ghz I have here as a patch that applies on top of today's SMU patch. It does 1/1 an 1/2 frequencies (that's all those machines support at the moment). It still lacks the voltage switch but I think I have it under control, I just don't have time today to try it. It should work on the SMU based desktops as well. It won't yet work on non-SMU based machines. The SCOM access need to be made more robust though. We need to actually wait for the freq switch to complete (reading the PSR) before setting the voltage. Index: linux-work/arch/ppc64/kernel/misc.S =================================================================== --- linux-work.orig/arch/ppc64/kernel/misc.S 2005-09-20 14:57:41.000000000 +1000 +++ linux-work/arch/ppc64/kernel/misc.S 2005-09-20 16:01:56.000000000 +1000 @@ -616,7 +616,7 @@ isync blr - /* +/* * Do an IO access in real mode */ _GLOBAL(real_writeb) @@ -649,6 +649,71 @@ #endif /* defined(CONFIG_PPC_PMAC) || defined(CONFIG_PPC_MAPLE) */ /* + * SCOM access functions for 970 (FX only for now) + * + * unsigned long scom970_read(unsigned int address); + * void scom970_write(unsigned int address, unsigned long value); + * + * The address passed in is the 24 bits register address. This code + * is 970 specific and will not check the status bits, so you should + * know what you are doing. + */ +_GLOBAL(scom970_read) + /* interrupts off */ + mfmsr r4 + rlwimi r0,r4,0,MSR_EE + mtmsrd r0,1 + + /* rotate address 8 bits left, mask out low 16 bits as they + * aren't implemented on current CPUs and must be 0'd, + * and finally or in RW bit + */ + rlwinm r3,r3,8,0,15 + ori r3,r3,0x8000 + + /* do the actual scom read */ + sync + mtspr SPRN_SCOMC,r3 + isync + mfspr r3,SPRN_SCOMD + mfspr r0,SPRN_SCOMC + sync + isync + + /* XXX: fixup result on some buggy 970's (ouch ! we lost a bit, bah + * that's the best we can do). Not implemented yet as we don't use + * the scom on any of the bogus CPUs yet, but may have to be done + * ultimately + */ + + /* restore interrupts */ + mtmsrd r4,1 + blr + + +_GLOBAL(scom970_write) + /* interrupts off */ + mfmsr r5 + rlwimi r0,r5,0,MSR_EE + mtmsrd r0,1 + + /* rotate address 8 bits left, mask out low 16 bits as they + * aren't implemented on current CPUs and must be 0'd + */ + rlwinm r3,r3,8,0,15 + + mtspr SPRN_SCOMD,r4 /* write data */ + mtspr SPRN_SCOMC,r3 /* write command */ + sync + isync + mfspr 3,SPRN_SCOMC + + /* restore interrupts */ + mtmsrd r5,1 + blr + + +/* * Create a kernel thread * kernel_thread(fn, arg, flags) */ Index: linux-work/include/asm-ppc64/processor.h =================================================================== --- linux-work.orig/include/asm-ppc64/processor.h 2005-09-20 09:54:26.000000000 +1000 +++ linux-work/include/asm-ppc64/processor.h 2005-09-20 16:00:42.000000000 +1000 @@ -177,6 +177,9 @@ #define SPRN_CTRLT 0x098 #define CTRL_RUNLATCH 0x1 +#define SPRN_SCOMC 0x114 +#define SPRN_SCOMD 0x115 + /* Performance monitor SPRs */ #define SPRN_SIAR 780 #define SPRN_SDAR 781 @@ -536,6 +539,9 @@ } } +extern unsigned long scom970_read(unsigned int address); +extern void scom970_write(unsigned int address, unsigned long value); + #endif /* __KERNEL__ */ #endif /* __ASSEMBLY__ */ Index: linux-work/arch/ppc64/Kconfig =================================================================== --- linux-work.orig/arch/ppc64/Kconfig 2005-09-20 14:57:39.000000000 +1000 +++ linux-work/arch/ppc64/Kconfig 2005-09-20 16:04:28.000000000 +1000 @@ -159,6 +159,17 @@ support. As of this writing the exact hardware interface is strongly in flux, so no good recommendation can be made. +source "drivers/cpufreq/Kconfig" + +config CPU_FREQ_PMAC + bool "Support for Apple G5" + depends on CPU_FREQ && PPC_PMAC64 + select CPU_FREQ_TABLE + help + This adds support for frequency switching on some Apple G5 + machine. This is currently very experimental and works only + on some iMac G5. + config IBMVIO depends on PPC_PSERIES || PPC_ISERIES bool Index: linux-work/arch/ppc64/kernel/Makefile =================================================================== --- linux-work.orig/arch/ppc64/kernel/Makefile 2005-09-07 11:09:56.000000000 +1000 +++ linux-work/arch/ppc64/kernel/Makefile 2005-09-20 16:05:32.000000000 +1000 @@ -60,6 +60,7 @@ obj-$(CONFIG_PPC_PMAC) += pmac_setup.o pmac_feature.o pmac_pci.o \ pmac_time.o pmac_nvram.o pmac_low_i2c.o \ udbg_scc.o +obj-$(CONFIG_CPU_FREQ_PMAC) += pmac_cpufreq.o obj-$(CONFIG_PPC_MAPLE) += maple_setup.o maple_pci.o maple_time.o \ udbg_16550.o Index: linux-work/arch/ppc64/kernel/pmac_cpufreq.c =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ linux-work/arch/ppc64/kernel/pmac_cpufreq.c 2005-09-20 18:00:40.000000000 +1000 @@ -0,0 +1,278 @@ +/* + * arch/ppc64/platforms/imacg5_cpufreq.c + * + * Copyright (C) 2002 - 2005 Benjamin Herrenschmidt + * Copyright (C) 2004 John Steele Scott + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * Well, this is actually a first stab by Markus Demleitner + * , based somewhat on pmac_cpufreq.c. + * This has been tested on the iMac G5, but since I'm not using any special + * features of that particular machine, I'd tend to assume it runs on all + * 970FX CPUs. + * + * XXXXXX: This isn't useful yet because fiddling cpufreq into the kernel + * renders it unbootable for now. See README. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#undef DEBUG + +#ifdef DEBUG +#define DBG(fmt...) printk(fmt) +#else +#define DBG(fmt...) +#endif + +/* see 970FX user manual */ + +#define SCOM_PCR 0x0aa001 /* PCR scom addr */ + +#define PCR_HILO_SELECT 0x80000000U /* 1 = PCR, 0 = PCRH */ +#define PCR_SPEED_FULL 0x00000000U /* 1:1 speed value */ +#define PCR_SPEED_HALF 0x00020000U /* 1:2 speed value */ +#define PCR_SPEED_QUARTER 0x00040000U /* 1:4 speed value */ +#define PCR_SPEED_MASK 0x000e0000U /* speed mask */ +#define PCR_SPEED_SHIFT 17 +#define PCR_FREQ_REQ_VALID 0x00010000U /* freq request valid */ +#define PCR_VOLT_REQ_VALID 0x00008000U /* volt request valid */ +#define PCR_TARGET_TIME_MASK 0x00006000U /* target time */ +#define PCR_STATLAT_MASK 0x00001f00U /* STATLAT value */ +#define PCR_SNOOPLAT_MASK 0x000000f0U /* SNOOPLAT value */ +#define PCR_SNOOPACC_MASK 0x0000000fU /* SNOOPACC value */ + +#define SCOM_PSR 0x408001 /* PSR scom addr */ + +#define PSR_CMD_RECEIVED 0x20000000U /* command received */ +#define PSR_CMD_COMPLETED 0x10000000U /* command completed */ +#define PSR_CUR_SPEED_MASK 0x03000000U /* current speed */ +#define PSR_CUR_SPEED_SHIFT 24 + +/* + * The G5 only supports two frequencies (Quarter speed is not supported) + */ +#define CPUFREQ_HIGH 0 +#define CPUFREQ_LOW 1 + +static struct cpufreq_frequency_table g5_cpu_freqs[] = { + {CPUFREQ_HIGH, 0}, + {CPUFREQ_LOW, 0}, + {0, CPUFREQ_TABLE_END}, +}; + +static struct freq_attr* g5_cpu_freqs_attr[] = { + &cpufreq_freq_attr_scaling_available_freqs, + NULL, +}; + +/* Power mode data is an array of the 32 bits PCR values to use for + * the various frequencies, retreived from the device-tree + */ +static u32 *g5_pmode_data; +static int g5_pmode_max; +static int g5_pmode_cur; + + +static struct smu_sdbp_fvt *g5_fvt_table; /* table of op. points */ +static int g5_fvt_count; /* number of op. points */ +static int g5_fvt_cur; /* current op. point */ + +/* ----------------- real hardware interface */ + +static void g5_switch_volt(int speed_mode) +{ + /* NYI */ +} + +static int g5_switch_freq(int speed_mode) +{ + /* If frequency is going up, first ramp up the voltage */ + if (speed_mode == CPUFREQ_HIGH) + g5_switch_volt(speed_mode); + + /* Clear PCR high */ + scom970_write(SCOM_PCR, 0); + /* Clear PCR low */ + scom970_write(SCOM_PCR, PCR_HILO_SELECT | 0); + /* Set PCR low */ + scom970_write(SCOM_PCR, PCR_HILO_SELECT | + g5_pmode_data[speed_mode]); + + /* If frequency is going down, last ramp the voltage */ + if (speed_mode == CPUFREQ_HIGH) + g5_switch_volt(speed_mode); + + g5_pmode_cur = speed_mode; + + return 0; +} + +static int g5_query_freq(void) +{ + u32 psr = scom970_read(SCOM_PSR); + int i; + + for (i = 0; i <= g5_pmode_max; i++) + if ((((psr >> PSR_CUR_SPEED_SHIFT) ^ + (g5_pmode_data[i] >> PCR_SPEED_SHIFT)) & 0x3) == 0) + break; + return i; +} + +/* ----------------- cpufreq bookkeeping */ +static int __pmac g5_cpufreq_verify(struct cpufreq_policy *policy) +{ + return cpufreq_frequency_table_verify(policy, g5_cpu_freqs); +} + +static int __pmac g5_cpufreq_target(struct cpufreq_policy *policy, + unsigned int target_freq, unsigned int relation) +{ + unsigned int newstate = 0; + + if (cpufreq_frequency_table_target(policy, g5_cpu_freqs, + target_freq, relation, &newstate)) + return -EINVAL; + + return g5_switch_freq(newstate); +} + +static int __pmac g5_cpufreq_cpu_init(struct cpufreq_policy *policy) +{ + if (policy->cpu != 0) + return -ENODEV; + + policy->governor = CPUFREQ_DEFAULT_GOVERNOR; + policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL; + policy->cur = g5_cpu_freqs[g5_query_freq()].frequency; + cpufreq_frequency_table_get_attr(g5_cpu_freqs, policy->cpu); + + return cpufreq_frequency_table_cpuinfo(policy, + g5_cpu_freqs); +} + + +static struct cpufreq_driver g5_cpufreq_driver = { + .name = "powermac", + .owner = THIS_MODULE, + .flags = CPUFREQ_CONST_LOOPS, + .init = g5_cpufreq_cpu_init, + .verify = g5_cpufreq_verify, + .target = g5_cpufreq_target, + .attr = g5_cpu_freqs_attr, +}; + + +static int __init g5_cpufreq_init(void) +{ + struct device_node *cpunode; + unsigned int psize, ssize; + struct smu_sdbp_header *shdr; + unsigned long max_freq; + u32 *valp; + int cur, rc = -ENODEV; + + /* Look for CPU and SMU nodes */ + cpunode = of_find_node_by_type(NULL, "cpu"); + if (!cpunode) { + DBG("No CPU node !\n"); + return -ENODEV; + } + + /* Check 970FX for now */ + valp = (u32 *)get_property(cpunode, "cpu-version", NULL); + if (!valp) { + DBG("No cpu-version property !\n"); + goto bail_noprops; + } + if (((*valp) >> 16) != 0x3c) { + DBG("Wrong CPU version: %08x\n", *valp); + goto bail_noprops; + } + + /* Look for the powertune data in the device-tree */ + g5_pmode_data = (u32 *)get_property(cpunode, "power-mode-data",&psize); + if (!g5_pmode_data) { + DBG("No power-mode-data !\n"); + goto bail_noprops; + } + g5_pmode_max = psize / sizeof(u32) - 1; + + /* Look for the FVT table */ + shdr = smu_get_sdb_partition(SMU_SDB_FVT_ID, NULL); + if (!shdr) + goto bail_noprops; + g5_fvt_table = (struct smu_sdbp_fvt *)&shdr[1]; + ssize = (shdr->len * sizeof(u32)) - sizeof(struct smu_sdbp_header); + g5_fvt_count = ssize / sizeof(struct smu_sdbp_fvt); + g5_fvt_cur = 0; + + /* Sanity checking */ + if (g5_fvt_count < 1 || g5_pmode_max < 1) + goto bail_noprops; + + /* + * From what I see, clock-frequency is always the maximal frequency. + * The current driver can not slew sysclk yet, so we really only deal + * with powertune steps for now. We also only implement full freq and + * half freq in this version. So far, I haven't yet seen a machine + * supporting anything else. + */ + valp = (u32 *)get_property(cpunode, "clock-frequency", NULL); + if (!valp) + return -ENODEV; + max_freq = (*valp)/1000; + g5_cpu_freqs[0].frequency = max_freq; + g5_cpu_freqs[1].frequency = max_freq/2; + + /* Check current frequency */ + cur = g5_query_freq(); + if (cur > 1) { + /* We don't support anything but 1:1 and 1:2, fixup ... */ + g5_switch_freq(1); + cur = 1; + } + + printk(KERN_INFO "Registering G5 CPU frequency driver\n"); + printk(KERN_INFO "Low: %d Mhz, High: %d Mhz, Cur: %d MHz\n", + g5_cpu_freqs[1].frequency/1000, + g5_cpu_freqs[0].frequency/1000, + g5_cpu_freqs[cur].frequency/1000); + + rc = cpufreq_register_driver(&g5_cpufreq_driver); + + /* We keep the CPU node on hold... hopefully, Apple G5 don't have + * hotplug CPU with a dynamic device-tree ... + */ + return rc; + + bail_noprops: + of_node_put(cpunode); + + return rc; +} + +module_init(g5_cpufreq_init); + + +MODULE_LICENSE("GPL"); Index: linux-work/drivers/macintosh/smu.c =================================================================== --- linux-work.orig/drivers/macintosh/smu.c 2005-09-20 13:05:11.000000000 +1000 +++ linux-work/drivers/macintosh/smu.c 2005-09-20 16:41:15.000000000 +1000 @@ -843,6 +843,18 @@ return 0; } +struct smu_sdbp_header *smu_get_sdb_partition(int id, unsigned int *size) +{ + char pname[32]; + + if (!smu) + return NULL; + + sprintf(pname, "sdb-partition-%02x", id); + return (struct smu_sdbp_header *)get_property(smu->of_node, + pname, size); +} +EXPORT_SYMBOL(smu_get_sdb_partition); /* Index: linux-work/include/asm-ppc64/smu.h =================================================================== --- linux-work.orig/include/asm-ppc64/smu.h 2005-09-20 11:57:47.000000000 +1000 +++ linux-work/include/asm-ppc64/smu.h 2005-09-20 17:42:51.000000000 +1000 @@ -144,7 +144,11 @@ * - lenght 8 ("VSLEWxyz") has 3 additional bytes appended, and is * used to set the voltage slewing point. The SMU replies with "DONE" * I yet have to figure out their exact meaning of those 3 bytes in - * both cases. + * both cases. They seem to be: + * x = processor mask + * y = op. point index + * z = processor freq. step index + * I haven't yet decyphered result codes * */ #define SMU_CMD_POWER_COMMAND 0xaa @@ -334,6 +338,59 @@ #endif /* __KERNEL__ */ /* + * - SMU "sdb" partitions informations - + */ + + +/* + * Partition header format + */ +struct smu_sdbp_header { + u8 id; + u8 len; + u8 version; + u8 flags; +}; + +/* + * 32 bits integers are usually encoded with 2x16 bits swapped, + * this demangles them + */ +#define SMU_U32_MIX(x) ((((x) << 16) & 0xffff0000u) | (((x) >> 16) & 0xffffu)) + +/* This is the definition of the SMU sdb-partition-0x12 table (called + * CPU F/V/T operating points in Darwin). The definition for all those + * SMU tables should be moved to some separate file + */ +#define SMU_SDB_FVT_ID 0x12 + +struct smu_sdbp_fvt { + u32 sysclk; /* Base SysClk frequency in Hz for + * this operating point + */ + u8 pad; + u8 maxtemp; /* Max temp. supported by this + * operating point + */ + + u16 volts[3]; /* CPU core voltage for the 3 + * PowerTune modes, a mode with + * 0V = not supported. + */ +}; + +#ifdef __KERNEL__ +/* + * This returns the pointer to an SMU "sdb" partition data or NULL + * if not found. The data format is described below + */ +extern struct smu_sdbp_header *smu_get_sdb_partition(int id, + unsigned int *size); + +#endif /* __KERNEL__ */ + + +/* * - Userland interface - */ @@ -376,4 +433,5 @@ __u32 reply_len; /* Lenght of data follwing */ }; + #endif /* _SMU_H */ From hch at lst.de Tue Sep 20 18:19:37 2005 From: hch at lst.de (Christoph Hellwig) Date: Tue, 20 Sep 2005 10:19:37 +0200 Subject: G5 pci probing regression In-Reply-To: <17199.22161.701821.240558@cargo.ozlabs.ibm.com> References: <20050918221220.GA31975@lst.de> <17197.59822.43168.956195@cargo.ozlabs.ibm.com> <20050919095130.GA8549@lst.de> <17199.14769.280974.803103@cargo.ozlabs.ibm.com> <20050919225333.GA21782@lst.de> <17199.22161.701821.240558@cargo.ozlabs.ibm.com> Message-ID: <20050920081937.GA29291@lst.de> On Tue, Sep 20, 2005 at 10:23:45AM +1000, Paul Mackerras wrote: > OK, this (untested) patch should fix things. I wasn't setting PCI > flags in the resources, only the IORESOURCE_* flags. Please try this > and let me know how it goes (without your other 1-line hack, of > course). Seems to work just fine with it, thanks. From ebiederm at xmission.com Wed Sep 21 03:30:32 2005 From: ebiederm at xmission.com (Eric W. Biederman) Date: Tue, 20 Sep 2005 11:30:32 -0600 Subject: [PATCH 0/4] kexec-tools-for-ppc64 In-Reply-To: <20050914124405.GA3968@in.ibm.com> (R. Sharada's message of "Wed, 14 Sep 2005 18:14:05 +0530") References: <20050914124405.GA3968@in.ibm.com> Message-ID: R Sharada writes: > Hello, > After the initial RFC on the kexec-tools for ppc64, > the hacks were cleaned up and this patchset now provides a > much cleaner kexec-tools support for ppc64. > Ack: At a first glance thing seem sane. I have been slapping some sense into the i386 and x86_64 kernels lately so I haven't had a chance to merge things and get a new release of kexec-tools out yet. Hopefully I can get to that soon. Eric From will_schmidt at vnet.ibm.com Wed Sep 21 04:12:50 2005 From: will_schmidt at vnet.ibm.com (will schmidt) Date: Tue, 20 Sep 2005 13:12:50 -0500 Subject: [PATCH] ppc64: Updated Olof iommu updates 2/3 In-Reply-To: <20050920054256.GA12014@austin.ibm.com> References: <1127188004.4386.50.camel@gaston> <20050920153523.17e0f6d0.sfr@canb.auug.org.au> <20050920054256.GA12014@austin.ibm.com> Message-ID: <43305122.6040501@vnet.ibm.com> Olof Johansson wrote: > On Tue, Sep 20, 2005 at 03:35:23PM +1000, Stephen Rothwell wrote: > >>On Tue, 20 Sep 2005 13:46:44 +1000 Benjamin Herrenschmidt wrote: >> >>>@@ -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)); >> >> ^^^^ >>TCE_PAGE_SIZE ? > > > The PAPR explicitly says page size, it's not directly related to the > TCE mapping size. It's not yet been explored if the firmware will deal > properly with new base page sizes so to play it safe, I hardcoded it > at 4K. Is it worth adding that as a /* comment */ above the line with the hardcoded 4096? > > > -Olof > > > >>_______________________________________________ >>Linuxppc64-dev mailing list >>Linuxppc64-dev at ozlabs.org >>https://ozlabs.org/mailman/listinfo/linuxppc64-dev > > > _______________________________________________ > Linuxppc64-dev mailing list > Linuxppc64-dev at ozlabs.org > https://ozlabs.org/mailman/listinfo/linuxppc64-dev From linuxppc at jdl.com Wed Sep 21 05:32:37 2005 From: linuxppc at jdl.com (linuxppc at jdl.com) Date: Tue, 20 Sep 2005 14:32:37 -0500 Subject: PATCH powerpc Merge asm-ppc*/vga.h Message-ID: Merge asm-ppc*/vga.h Signed-off-by: Jon Loeliger Signed-off-by: Kumar Gala --- include/asm-powerpc/vga.h | 54 +++++++++++++++++++++++++++++++++++++++++++++ include/asm-ppc/vga.h | 46 -------------------------------------- include/asm-ppc64/vga.h | 50 ------------------------------------------ 3 files changed, 54 insertions(+), 96 deletions(-) diff --git a/include/asm-powerpc/vga.h b/include/asm-powerpc/vga.h new file mode 100644 --- /dev/null +++ b/include/asm-powerpc/vga.h @@ -0,0 +1,54 @@ +#ifndef _ASM_POWERPC_VGA_H_ +#define _ASM_POWERPC_VGA_H_ + +#ifdef __KERNEL__ + +/* + * Access to VGA videoram + * + * (c) 1998 Martin Mares + */ + + +#include + +#include + +#if defined(CONFIG_VGA_CONSOLE) || defined(CONFIG_MDA_CONSOLE) + +#define VT_BUF_HAVE_RW +/* + * These are only needed for supporting VGA or MDA text mode, which use little + * endian byte ordering. + * In other cases, we can optimize by using native byte ordering and + * has already done the right job for us. + */ + +static inline void scr_writew(u16 val, volatile u16 *addr) +{ + st_le16(addr, val); +} + +static inline u16 scr_readw(volatile const u16 *addr) +{ + return ld_le16(addr); +} + +#define VT_BUF_HAVE_MEMCPYW +#define scr_memcpyw memcpy + +#endif /* !CONFIG_VGA_CONSOLE && !CONFIG_MDA_CONSOLE */ + +extern unsigned long vgacon_remap_base; + +#ifdef __powerpc64__ +#define VGA_MAP_MEM(x) ((unsigned long) ioremap((x), 0)) +#else +#define VGA_MAP_MEM(x) (x + vgacon_remap_base) +#endif + +#define vga_readb(x) (*(x)) +#define vga_writeb(x,y) (*(y) = (x)) + +#endif /* __KERNEL__ */ +#endif /* _ASM_POWERPC_VGA_H_ */ diff --git a/include/asm-ppc/vga.h b/include/asm-ppc/vga.h deleted file mode 100644 --- a/include/asm-ppc/vga.h +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Access to VGA videoram - * - * (c) 1998 Martin Mares - */ - -#ifdef __KERNEL__ -#ifndef _LINUX_ASM_VGA_H_ -#define _LINUX_ASM_VGA_H_ - -#include - -#include - -#if defined(CONFIG_VGA_CONSOLE) || defined(CONFIG_MDA_CONSOLE) - -#define VT_BUF_HAVE_RW -/* - * These are only needed for supporting VGA or MDA text mode, which use little - * endian byte ordering. - * In other cases, we can optimize by using native byte ordering and - * has already done the right job for us. - */ - -extern inline void scr_writew(u16 val, volatile u16 *addr) -{ - st_le16(addr, val); -} - -extern inline u16 scr_readw(volatile const u16 *addr) -{ - return ld_le16(addr); -} - -#define VT_BUF_HAVE_MEMCPYW -#define scr_memcpyw memcpy - -#endif /* !CONFIG_VGA_CONSOLE && !CONFIG_MDA_CONSOLE */ - -extern unsigned long vgacon_remap_base; -#define VGA_MAP_MEM(x) (x + vgacon_remap_base) -#define vga_readb(x) (*(x)) -#define vga_writeb(x,y) (*(y) = (x)) - -#endif -#endif /* __KERNEL__ */ diff --git a/include/asm-ppc64/vga.h b/include/asm-ppc64/vga.h deleted file mode 100644 --- a/include/asm-ppc64/vga.h +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Access to VGA videoram - * - * (c) 1998 Martin Mares - * - * 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 _LINUX_ASM_VGA_H_ -#define _LINUX_ASM_VGA_H_ - -#include - -#include - -#if defined(CONFIG_VGA_CONSOLE) || defined(CONFIG_MDA_CONSOLE) - -#define VT_BUF_HAVE_RW -/* - * These are only needed for supporting VGA or MDA text mode, which use little - * endian byte ordering. - * In other cases, we can optimize by using native byte ordering and - * has already done the right job for us. - */ - -static inline void scr_writew(u16 val, volatile u16 *addr) -{ - st_le16(addr, val); -} - -static inline u16 scr_readw(volatile const u16 *addr) -{ - return ld_le16(addr); -} - -#define VT_BUF_HAVE_MEMCPYW -#define scr_memcpyw memcpy - -#endif /* !CONFIG_VGA_CONSOLE && !CONFIG_MDA_CONSOLE */ - -extern unsigned long vgacon_remap_base; -#define VGA_MAP_MEM(x) ((unsigned long) ioremap((x), 0)) - -#define vga_readb(x) (*(x)) -#define vga_writeb(x,y) (*(y) = (x)) - -#endif From jschopp at austin.ibm.com Wed Sep 21 06:34:51 2005 From: jschopp at austin.ibm.com (Joel Schopp) Date: Tue, 20 Sep 2005 15:34:51 -0500 Subject: [PATCH] fix arch/ppc64/kernel/rtc.c warnings In-Reply-To: <20050916213157.GA8644@kvasir.watson.ibm.com> References: <20050916213157.GA8644@kvasir.watson.ibm.com> Message-ID: <4330726B.1060303@austin.ibm.com> > If CONFIG_PROC_FS is not asserted, the compiler emits: > > arch/ppc64/kernel/rtc.c:257: warning: `rtc_read_proc' defined but not used > > Here is a patch to fix that. It can provide a decent space savings: > > text data bss dec hex filename > - 2956 728 0 3684 e64 arch/ppc64/kernel/rtc.o > + 2500 664 0 3164 c5c arch/ppc64/kernel/rtc.o > > Signed-off-by: Amos Waterland > Looks good, let's merge it. Acked-by: Joel Schopp From galak at freescale.com Wed Sep 21 06:45:26 2005 From: galak at freescale.com (Kumar Gala) Date: Tue, 20 Sep 2005 15:45:26 -0500 (CDT) Subject: [PATCH] powerpc: merge include/asm-ppc*/auxvec.h into include/asm-powerpc/auxvec.h Message-ID: Signed-off-by: Kumar Gala --- commit 40ec2534f42b5d38123c41858a3c85bc2eae272b tree e13c35c52e65b3ac32a7d9bd37be9b45accb0631 parent e89b8279aafe3b896a1d1fbb4d10fbe91841d8e9 author Kumar K. Gala Tue, 20 Sep 2005 15:31:13 -0500 committer Kumar K. Gala Tue, 20 Sep 2005 15:31:13 -0500 include/asm-powerpc/auxvec.h | 19 +++++++++++++++++++ include/asm-ppc/auxvec.h | 14 -------------- include/asm-ppc64/auxvec.h | 19 ------------------- 3 files changed, 19 insertions(+), 33 deletions(-) diff --git a/include/asm-powerpc/auxvec.h b/include/asm-powerpc/auxvec.h new file mode 100644 --- /dev/null +++ b/include/asm-powerpc/auxvec.h @@ -0,0 +1,19 @@ +#ifndef _ASM_POWERPC_AUXVEC_H +#define _ASM_POWERPC_AUXVEC_H + +/* + * We need to put in some extra aux table entries to tell glibc what + * the cache block size is, so it can use the dcbz instruction safely. + */ +#define AT_DCACHEBSIZE 19 +#define AT_ICACHEBSIZE 20 +#define AT_UCACHEBSIZE 21 +/* A special ignored type value for PPC, for glibc compatibility. */ +#define AT_IGNOREPPC 22 + +/* The vDSO location. We have to use the same value as x86 for glibc's + * sake :-) + */ +#define AT_SYSINFO_EHDR 33 + +#endif diff --git a/include/asm-ppc/auxvec.h b/include/asm-ppc/auxvec.h deleted file mode 100644 --- a/include/asm-ppc/auxvec.h +++ /dev/null @@ -1,14 +0,0 @@ -#ifndef __PPC_AUXVEC_H -#define __PPC_AUXVEC_H - -/* - * We need to put in some extra aux table entries to tell glibc what - * the cache block size is, so it can use the dcbz instruction safely. - */ -#define AT_DCACHEBSIZE 19 -#define AT_ICACHEBSIZE 20 -#define AT_UCACHEBSIZE 21 -/* A special ignored type value for PPC, for glibc compatibility. */ -#define AT_IGNOREPPC 22 - -#endif diff --git a/include/asm-ppc64/auxvec.h b/include/asm-ppc64/auxvec.h deleted file mode 100644 --- a/include/asm-ppc64/auxvec.h +++ /dev/null @@ -1,19 +0,0 @@ -#ifndef __PPC64_AUXVEC_H -#define __PPC64_AUXVEC_H - -/* - * We need to put in some extra aux table entries to tell glibc what - * the cache block size is, so it can use the dcbz instruction safely. - */ -#define AT_DCACHEBSIZE 19 -#define AT_ICACHEBSIZE 20 -#define AT_UCACHEBSIZE 21 -/* A special ignored type value for PPC, for glibc compatibility. */ -#define AT_IGNOREPPC 22 - -/* The vDSO location. We have to use the same value as x86 for glibc's - * sake :-) - */ -#define AT_SYSINFO_EHDR 33 - -#endif /* __PPC64_AUXVEC_H */ From galak at freescale.com Wed Sep 21 07:33:54 2005 From: galak at freescale.com (Kumar Gala) Date: Tue, 20 Sep 2005 16:33:54 -0500 (CDT) Subject: [PATCH] powerpc: merge include/asm-ppc*/spinlock_types.h into include/asm-powerpc/spinlock_types.h[PATCH] Message-ID: Signed-off-by: Kumar Gala --- commit cb3e61d8491f6395a007687d9908bdb20fc9a0b5 tree da0514335c8f2ed2a795d4bbc7db06cfa6f728d5 parent 40ec2534f42b5d38123c41858a3c85bc2eae272b author Kumar K. Gala Tue, 20 Sep 2005 16:27:51 -0500 committer Kumar K. Gala Tue, 20 Sep 2005 16:27:51 -0500 include/asm-powerpc/spinlock_types.h | 20 ++++++++++++++++++++ include/asm-ppc/spinlock_types.h | 20 -------------------- include/asm-ppc64/spinlock_types.h | 20 -------------------- 3 files changed, 20 insertions(+), 40 deletions(-) diff --git a/include/asm-powerpc/spinlock_types.h b/include/asm-powerpc/spinlock_types.h new file mode 100644 --- /dev/null +++ b/include/asm-powerpc/spinlock_types.h @@ -0,0 +1,20 @@ +#ifndef _ASM_POWERPC_SPINLOCK_TYPES_H +#define _ASM_POWERPC_SPINLOCK_TYPES_H + +#ifndef __LINUX_SPINLOCK_TYPES_H +# error "please don't include this file directly" +#endif + +typedef struct { + volatile unsigned int slock; +} raw_spinlock_t; + +#define __RAW_SPIN_LOCK_UNLOCKED { 0 } + +typedef struct { + volatile signed int lock; +} raw_rwlock_t; + +#define __RAW_RW_LOCK_UNLOCKED { 0 } + +#endif diff --git a/include/asm-ppc/spinlock_types.h b/include/asm-ppc/spinlock_types.h deleted file mode 100644 --- a/include/asm-ppc/spinlock_types.h +++ /dev/null @@ -1,20 +0,0 @@ -#ifndef __ASM_SPINLOCK_TYPES_H -#define __ASM_SPINLOCK_TYPES_H - -#ifndef __LINUX_SPINLOCK_TYPES_H -# error "please don't include this file directly" -#endif - -typedef struct { - volatile unsigned long lock; -} raw_spinlock_t; - -#define __RAW_SPIN_LOCK_UNLOCKED { 0 } - -typedef struct { - volatile signed int lock; -} raw_rwlock_t; - -#define __RAW_RW_LOCK_UNLOCKED { 0 } - -#endif diff --git a/include/asm-ppc64/spinlock_types.h b/include/asm-ppc64/spinlock_types.h deleted file mode 100644 --- a/include/asm-ppc64/spinlock_types.h +++ /dev/null @@ -1,20 +0,0 @@ -#ifndef __ASM_SPINLOCK_TYPES_H -#define __ASM_SPINLOCK_TYPES_H - -#ifndef __LINUX_SPINLOCK_TYPES_H -# error "please don't include this file directly" -#endif - -typedef struct { - volatile unsigned int slock; -} raw_spinlock_t; - -#define __RAW_SPIN_LOCK_UNLOCKED { 0 } - -typedef struct { - volatile signed int lock; -} raw_rwlock_t; - -#define __RAW_RW_LOCK_UNLOCKED { 0 } - -#endif From galak at freescale.com Wed Sep 21 07:49:51 2005 From: galak at freescale.com (Kumar Gala) Date: Tue, 20 Sep 2005 16:49:51 -0500 (CDT) Subject: [PATCH] powerpc: merge include/asm-ppc*/statfs.h into include/asm-powerpc/statfs.h Message-ID: Signed-off-by: Kumar Gala --- commit 1288b50c0dd4747595c5e73dbff02088d8eeefcc tree a721d4dbd9605cacb1bf0ab601515c3e57db7330 parent cb3e61d8491f6395a007687d9908bdb20fc9a0b5 author Kumar K. Gala Tue, 20 Sep 2005 16:48:42 -0500 committer Kumar K. Gala Tue, 20 Sep 2005 16:48:42 -0500 include/asm-powerpc/statfs.h | 60 +++++++++++++++++++++++++++++++++++++++++ include/asm-ppc/statfs.h | 8 ------ include/asm-ppc64/statfs.h | 61 ------------------------------------------ 3 files changed, 60 insertions(+), 69 deletions(-) diff --git a/include/asm-powerpc/statfs.h b/include/asm-powerpc/statfs.h new file mode 100644 --- /dev/null +++ b/include/asm-powerpc/statfs.h @@ -0,0 +1,60 @@ +#ifndef _ASM_POWERPC_STATFS_H +#define _ASM_POWERPC_STATFS_H + +/* For ppc32 we just use the generic definitions, not so simple on ppc64 */ + +#ifndef __powerpc64__ +#include +#else + +#ifndef __KERNEL_STRICT_NAMES +#include +typedef __kernel_fsid_t fsid_t; +#endif + +/* + * We're already 64-bit, so duplicate the definition + */ +struct statfs { + long f_type; + long f_bsize; + long f_blocks; + long f_bfree; + long f_bavail; + long f_files; + long f_ffree; + __kernel_fsid_t f_fsid; + long f_namelen; + long f_frsize; + long f_spare[5]; +}; + +struct statfs64 { + long f_type; + long f_bsize; + long f_blocks; + long f_bfree; + long f_bavail; + long f_files; + long f_ffree; + __kernel_fsid_t f_fsid; + long f_namelen; + long f_frsize; + long f_spare[5]; +}; + +struct compat_statfs64 { + __u32 f_type; + __u32 f_bsize; + __u64 f_blocks; + __u64 f_bfree; + __u64 f_bavail; + __u64 f_files; + __u64 f_ffree; + __kernel_fsid_t f_fsid; + __u32 f_namelen; + __u32 f_frsize; + __u32 f_spare[5]; +}; +#endif /* ! __powerpc64__ */ +#endif diff --git a/include/asm-ppc/statfs.h b/include/asm-ppc/statfs.h deleted file mode 100644 --- a/include/asm-ppc/statfs.h +++ /dev/null @@ -1,8 +0,0 @@ -#ifndef _PPC_STATFS_H -#define _PPC_STATFS_H - -#include -#endif - - - diff --git a/include/asm-ppc64/statfs.h b/include/asm-ppc64/statfs.h deleted file mode 100644 --- a/include/asm-ppc64/statfs.h +++ /dev/null @@ -1,61 +0,0 @@ -#ifndef _PPC64_STATFS_H -#define _PPC64_STATFS_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. - */ - -#ifndef __KERNEL_STRICT_NAMES -#include -typedef __kernel_fsid_t fsid_t; -#endif - -/* - * We're already 64-bit, so duplicate the definition - */ -struct statfs { - long f_type; - long f_bsize; - long f_blocks; - long f_bfree; - long f_bavail; - long f_files; - long f_ffree; - __kernel_fsid_t f_fsid; - long f_namelen; - long f_frsize; - long f_spare[5]; -}; - -struct statfs64 { - long f_type; - long f_bsize; - long f_blocks; - long f_bfree; - long f_bavail; - long f_files; - long f_ffree; - __kernel_fsid_t f_fsid; - long f_namelen; - long f_frsize; - long f_spare[5]; -}; - -struct compat_statfs64 { - __u32 f_type; - __u32 f_bsize; - __u64 f_blocks; - __u64 f_bfree; - __u64 f_bavail; - __u64 f_files; - __u64 f_ffree; - __kernel_fsid_t f_fsid; - __u32 f_namelen; - __u32 f_frsize; - __u32 f_spare[5]; -}; - -#endif /* _PPC64_STATFS_H */ From akpm at osdl.org Wed Sep 21 09:20:43 2005 From: akpm at osdl.org (Andrew Morton) Date: Tue, 20 Sep 2005 16:20:43 -0700 Subject: [PATCH] ppc64: SMU driver update & i2c support In-Reply-To: <1127185873.4386.32.camel@gaston> References: <1127185873.4386.32.camel@gaston> Message-ID: <20050920162043.57510f13.akpm@osdl.org> Benjamin Herrenschmidt wrote: > > This patch is a bit late (I was on vacation) but I hope will make it in > 2.6.14-rc*. The SMU is the "system controller" chip used by Apple recent > G5 machines including the iMac G5. It drives things like fans, i2c > busses, real time clock, etc... The current kernel contains a very crude > driver that doesn't do much more than reading the real time clock > synchronously. This is a completely rewritten driver that provides > interrupt based command queuing, a userland interface, and an i2c/smbus > driver for accessing the devices hanging off the SMU i2c busses like > temperature sensors. This driver is a basic block for upcoming work on > thermal control for those machines, among others. Well it is officially extremely sinful of you to attempt to sneak a major driver rewrite into -rc2. Does this version have all the functionality of the earlier version? Will it break any existing userland tools? How well tested is it? Vendors may base releases on 2.6.14. Will they get grumpy about a half-finished subsystem? From benh at kernel.crashing.org Wed Sep 21 09:31:52 2005 From: benh at kernel.crashing.org (Benjamin Herrenschmidt) Date: Wed, 21 Sep 2005 09:31:52 +1000 Subject: [PATCH] ppc64: SMU driver update & i2c support In-Reply-To: <20050920162043.57510f13.akpm@osdl.org> References: <1127185873.4386.32.camel@gaston> <20050920162043.57510f13.akpm@osdl.org> Message-ID: <1127259113.4386.73.camel@gaston> On Tue, 2005-09-20 at 16:20 -0700, Andrew Morton wrote: > Well it is officially extremely sinful of you to attempt to sneak a major > driver rewrite into -rc2. Yup, my bad. I should have sent you the patch before going to vacation, got distracted. I had the rewrite around for some time now. (Bah, I didn't even notice we were past -rc1 in fact !) > Does this version have all the functionality of the earlier version? Will > it break any existing userland tools? How well tested is it? Vendors may > base releases on 2.6.14. Will they get grumpy about a half-finished > subsystem? The previous driver had pretty much no feature at all and no userland interface. All it did was read the real time clock at boot and implement writing to it via genrtc. It's pretty much adding a driver more than replacing one in fact. This driver is also only used on some recent Apple machines (iMac G5 and recent single CPU G5 desktops). This new version adds the userland interface so tools can be written in fact :) The previous one had none, so no tool breakage is to be expected. Some people have already been writing some thermal control tools based on this new version (well, a slightly earlier one that I posted to the ppc lists a while ago) which is the main reason why I'm trying to get it in 2.6.14. The only possible regression I can see here is more the addition of the "parent" parameter to the OF platform device creation which might break build of some configs. Few people use the OF platform device facility though, it's pretty much a mac only thing. I'll double check ppc32 pmac and pegasos today just in case. Ben. From paulus at samba.org Wed Sep 21 14:14:22 2005 From: paulus at samba.org (Paul Mackerras) Date: Wed, 21 Sep 2005 14:14:22 +1000 Subject: [PATCH] ppc64: Fix PCI flags when using OF device tree Message-ID: <17200.56862.72775.231440@cargo.ozlabs.ibm.com> My code to set up the PCI tree from the Open Firmware device tree was setting IORESOURCE_* flags on the resources for the devices, but not the PCI_BASE_ADDRESS_* flags. This meant that some drivers misbehaved, and /proc/pci showed the wrong types for the resources. This fixes it. Signed-off-by: Paul Mackerras --- diff -urN linux-2.6/arch/ppc64/kernel/pci.c hch/arch/ppc64/kernel/pci.c --- linux-2.6/arch/ppc64/kernel/pci.c 2005-09-13 07:43:47.000000000 +1000 +++ hch/arch/ppc64/kernel/pci.c 2005-09-20 10:20:54.000000000 +1000 @@ -246,11 +246,14 @@ unsigned int flags = 0; if (addr0 & 0x02000000) { - flags |= IORESOURCE_MEM; + flags = IORESOURCE_MEM | PCI_BASE_ADDRESS_SPACE_MEMORY; + flags |= (addr0 >> 22) & PCI_BASE_ADDRESS_MEM_TYPE_64; + flags |= (addr0 >> 28) & PCI_BASE_ADDRESS_MEM_TYPE_1M; if (addr0 & 0x40000000) - flags |= IORESOURCE_PREFETCH; + flags |= IORESOURCE_PREFETCH + | PCI_BASE_ADDRESS_MEM_PREFETCH; } else if (addr0 & 0x01000000) - flags |= IORESOURCE_IO; + flags = IORESOURCE_IO | PCI_BASE_ADDRESS_SPACE_IO; return flags; } From benh at kernel.crashing.org Wed Sep 21 15:57:28 2005 From: benh at kernel.crashing.org (Benjamin Herrenschmidt) Date: Wed, 21 Sep 2005 15:57:28 +1000 Subject: [PATCH] ppc64: iMac G5 cpufreq support Message-ID: <1127282249.4386.101.camel@gaston> This applies on top of the big SMU update posted earlier. It adds cpufreq support for iMac G5 (and SMU based desktop, though that one was untested, testers welcome). It supports full and half speed and also does voltage switching for more power savings. Next step is proper thermal control to make those fans quiet once for all ! Index: linux-work/arch/ppc64/kernel/misc.S =================================================================== --- linux-work.orig/arch/ppc64/kernel/misc.S 2005-09-20 14:57:41.000000000 +1000 +++ linux-work/arch/ppc64/kernel/misc.S 2005-09-21 13:39:11.000000000 +1000 @@ -616,7 +616,7 @@ isync blr - /* +/* * Do an IO access in real mode */ _GLOBAL(real_writeb) @@ -649,6 +649,73 @@ #endif /* defined(CONFIG_PPC_PMAC) || defined(CONFIG_PPC_MAPLE) */ /* + * SCOM access functions for 970 (FX only for now) + * + * unsigned long scom970_read(unsigned int address); + * void scom970_write(unsigned int address, unsigned long value); + * + * The address passed in is the 24 bits register address. This code + * is 970 specific and will not check the status bits, so you should + * know what you are doing. + */ +_GLOBAL(scom970_read) + /* interrupts off */ + mfmsr r4 + li r0,0 + rlwimi r0,r4,0,MSR_EE + mtmsrd r0,1 + + /* rotate address 8 bits left, mask out low 16 bits as they + * aren't implemented on current CPUs and must be 0'd, + * and finally or in RW bit + */ + rlwinm r3,r3,8,0,15 + ori r3,r3,0x8000 + + /* do the actual scom read */ + sync + mtspr SPRN_SCOMC,r3 + isync + mfspr r3,SPRN_SCOMD + mfspr r0,SPRN_SCOMC + sync + isync + + /* XXX: fixup result on some buggy 970's (ouch ! we lost a bit, bah + * that's the best we can do). Not implemented yet as we don't use + * the scom on any of the bogus CPUs yet, but may have to be done + * ultimately + */ + + /* restore interrupts */ + mtmsrd r4,1 + blr + + +_GLOBAL(scom970_write) + /* interrupts off */ + mfmsr r5 + li r0,0 + rlwimi r0,r5,0,MSR_EE + mtmsrd r0,1 + + /* rotate address 8 bits left, mask out low 16 bits as they + * aren't implemented on current CPUs and must be 0'd + */ + rlwinm r3,r3,8,0,15 + + mtspr SPRN_SCOMD,r4 /* write data */ + mtspr SPRN_SCOMC,r3 /* write command */ + sync + isync + mfspr 3,SPRN_SCOMC + + /* restore interrupts */ + mtmsrd r5,1 + blr + + +/* * Create a kernel thread * kernel_thread(fn, arg, flags) */ Index: linux-work/include/asm-ppc64/processor.h =================================================================== --- linux-work.orig/include/asm-ppc64/processor.h 2005-09-20 09:54:26.000000000 +1000 +++ linux-work/include/asm-ppc64/processor.h 2005-09-20 16:00:42.000000000 +1000 @@ -177,6 +177,9 @@ #define SPRN_CTRLT 0x098 #define CTRL_RUNLATCH 0x1 +#define SPRN_SCOMC 0x114 +#define SPRN_SCOMD 0x115 + /* Performance monitor SPRs */ #define SPRN_SIAR 780 #define SPRN_SDAR 781 @@ -536,6 +539,9 @@ } } +extern unsigned long scom970_read(unsigned int address); +extern void scom970_write(unsigned int address, unsigned long value); + #endif /* __KERNEL__ */ #endif /* __ASSEMBLY__ */ Index: linux-work/arch/ppc64/Kconfig =================================================================== --- linux-work.orig/arch/ppc64/Kconfig 2005-09-20 14:57:39.000000000 +1000 +++ linux-work/arch/ppc64/Kconfig 2005-09-20 16:04:28.000000000 +1000 @@ -159,6 +159,17 @@ support. As of this writing the exact hardware interface is strongly in flux, so no good recommendation can be made. +source "drivers/cpufreq/Kconfig" + +config CPU_FREQ_PMAC + bool "Support for Apple G5" + depends on CPU_FREQ && PPC_PMAC64 + select CPU_FREQ_TABLE + help + This adds support for frequency switching on some Apple G5 + machine. This is currently very experimental and works only + on some iMac G5. + config IBMVIO depends on PPC_PSERIES || PPC_ISERIES bool Index: linux-work/arch/ppc64/kernel/Makefile =================================================================== --- linux-work.orig/arch/ppc64/kernel/Makefile 2005-09-07 11:09:56.000000000 +1000 +++ linux-work/arch/ppc64/kernel/Makefile 2005-09-20 16:05:32.000000000 +1000 @@ -60,6 +60,7 @@ obj-$(CONFIG_PPC_PMAC) += pmac_setup.o pmac_feature.o pmac_pci.o \ pmac_time.o pmac_nvram.o pmac_low_i2c.o \ udbg_scc.o +obj-$(CONFIG_CPU_FREQ_PMAC) += pmac_cpufreq.o obj-$(CONFIG_PPC_MAPLE) += maple_setup.o maple_pci.o maple_time.o \ udbg_16550.o Index: linux-work/arch/ppc64/kernel/pmac_cpufreq.c =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ linux-work/arch/ppc64/kernel/pmac_cpufreq.c 2005-09-21 15:58:08.000000000 +1000 @@ -0,0 +1,297 @@ +/* + * Copyright (C) 2002 - 2005 Benjamin Herrenschmidt + * and Markus Demleitner + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This driver adds basic cpufreq support for SMU & 970FX based G5 Macs, + * that is iMac G5 and latest single CPU desktop. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#undef DEBUG + +#ifdef DEBUG +#define DBG(fmt...) printk(fmt) +#else +#define DBG(fmt...) +#endif + +/* see 970FX user manual */ + +#define SCOM_PCR 0x0aa001 /* PCR scom addr */ + +#define PCR_HILO_SELECT 0x80000000U /* 1 = PCR, 0 = PCRH */ +#define PCR_SPEED_FULL 0x00000000U /* 1:1 speed value */ +#define PCR_SPEED_HALF 0x00020000U /* 1:2 speed value */ +#define PCR_SPEED_QUARTER 0x00040000U /* 1:4 speed value */ +#define PCR_SPEED_MASK 0x000e0000U /* speed mask */ +#define PCR_SPEED_SHIFT 17 +#define PCR_FREQ_REQ_VALID 0x00010000U /* freq request valid */ +#define PCR_VOLT_REQ_VALID 0x00008000U /* volt request valid */ +#define PCR_TARGET_TIME_MASK 0x00006000U /* target time */ +#define PCR_STATLAT_MASK 0x00001f00U /* STATLAT value */ +#define PCR_SNOOPLAT_MASK 0x000000f0U /* SNOOPLAT value */ +#define PCR_SNOOPACC_MASK 0x0000000fU /* SNOOPACC value */ + +#define SCOM_PSR 0x408001 /* PSR scom addr */ +/* warning: PSR is a 64 bits register */ +#define PSR_CMD_RECEIVED 0x2000000000000000U /* command received */ +#define PSR_CMD_COMPLETED 0x1000000000000000U /* command completed */ +#define PSR_CUR_SPEED_MASK 0x0300000000000000U /* current speed */ +#define PSR_CUR_SPEED_SHIFT (56) + +/* + * The G5 only supports two frequencies (Quarter speed is not supported) + */ +#define CPUFREQ_HIGH 0 +#define CPUFREQ_LOW 1 + +static struct cpufreq_frequency_table g5_cpu_freqs[] = { + {CPUFREQ_HIGH, 0}, + {CPUFREQ_LOW, 0}, + {0, CPUFREQ_TABLE_END}, +}; + +static struct freq_attr* g5_cpu_freqs_attr[] = { + &cpufreq_freq_attr_scaling_available_freqs, + NULL, +}; + +/* Power mode data is an array of the 32 bits PCR values to use for + * the various frequencies, retreived from the device-tree + */ +static u32 *g5_pmode_data; +static int g5_pmode_max; +static int g5_pmode_cur; + + +static struct smu_sdbp_fvt *g5_fvt_table; /* table of op. points */ +static int g5_fvt_count; /* number of op. points */ +static int g5_fvt_cur; /* current op. point */ + +/* ----------------- real hardware interface */ + +static void g5_switch_volt(int speed_mode) +{ + struct smu_simple_cmd cmd; + + DECLARE_COMPLETION(comp); + smu_queue_simple(&cmd, SMU_CMD_POWER_COMMAND, 8, smu_done_complete, + &comp, 'V', 'S', 'L', 'E', 'W', + 0xff, g5_fvt_cur+1, speed_mode); + wait_for_completion(&comp); +} + +static int g5_switch_freq(int speed_mode) +{ + int to; + + if (g5_pmode_cur == speed_mode) + return 0; + + /* If frequency is going up, first ramp up the voltage */ + if (speed_mode < g5_pmode_cur) + g5_switch_volt(speed_mode); + + /* Clear PCR high */ + scom970_write(SCOM_PCR, 0); + /* Clear PCR low */ + scom970_write(SCOM_PCR, PCR_HILO_SELECT | 0); + /* Set PCR low */ + scom970_write(SCOM_PCR, PCR_HILO_SELECT | + g5_pmode_data[speed_mode]); + + /* Wait for completion */ + for (to = 0; to < 10; to++) { + unsigned long psr = scom970_read(SCOM_PSR); + + if ((psr & PSR_CMD_RECEIVED) == 0 && + (((psr >> PSR_CUR_SPEED_SHIFT) ^ + (g5_pmode_data[speed_mode] >> PCR_SPEED_SHIFT)) & 0x3) + == 0) + break; + if (psr & PSR_CMD_COMPLETED) + break; + udelay(100); + } + + /* If frequency is going down, last ramp the voltage */ + if (speed_mode > g5_pmode_cur) + g5_switch_volt(speed_mode); + + g5_pmode_cur = speed_mode; + ppc_proc_freq = g5_cpu_freqs[speed_mode].frequency; + + return 0; +} + +static int g5_query_freq(void) +{ + unsigned long psr = scom970_read(SCOM_PSR); + int i; + + for (i = 0; i <= g5_pmode_max; i++) + if ((((psr >> PSR_CUR_SPEED_SHIFT) ^ + (g5_pmode_data[i] >> PCR_SPEED_SHIFT)) & 0x3) == 0) + break; + return i; +} + +/* ----------------- cpufreq bookkeeping */ +static int __pmac g5_cpufreq_verify(struct cpufreq_policy *policy) +{ + return cpufreq_frequency_table_verify(policy, g5_cpu_freqs); +} + +static int __pmac g5_cpufreq_target(struct cpufreq_policy *policy, + unsigned int target_freq, unsigned int relation) +{ + unsigned int newstate = 0; + + if (cpufreq_frequency_table_target(policy, g5_cpu_freqs, + target_freq, relation, &newstate)) + return -EINVAL; + + return g5_switch_freq(newstate); +} + +static int __pmac g5_cpufreq_cpu_init(struct cpufreq_policy *policy) +{ + if (policy->cpu != 0) + return -ENODEV; + + policy->governor = CPUFREQ_DEFAULT_GOVERNOR; + policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL; + policy->cur = g5_cpu_freqs[g5_query_freq()].frequency; + cpufreq_frequency_table_get_attr(g5_cpu_freqs, policy->cpu); + + return cpufreq_frequency_table_cpuinfo(policy, + g5_cpu_freqs); +} + + +static struct cpufreq_driver g5_cpufreq_driver = { + .name = "powermac", + .owner = THIS_MODULE, + .flags = CPUFREQ_CONST_LOOPS, + .init = g5_cpufreq_cpu_init, + .verify = g5_cpufreq_verify, + .target = g5_cpufreq_target, + .attr = g5_cpu_freqs_attr, +}; + + +static int __init g5_cpufreq_init(void) +{ + struct device_node *cpunode; + unsigned int psize, ssize; + struct smu_sdbp_header *shdr; + unsigned long max_freq; + u32 *valp; + int rc = -ENODEV; + + /* Look for CPU and SMU nodes */ + cpunode = of_find_node_by_type(NULL, "cpu"); + if (!cpunode) { + DBG("No CPU node !\n"); + return -ENODEV; + } + + /* Check 970FX for now */ + valp = (u32 *)get_property(cpunode, "cpu-version", NULL); + if (!valp) { + DBG("No cpu-version property !\n"); + goto bail_noprops; + } + if (((*valp) >> 16) != 0x3c) { + DBG("Wrong CPU version: %08x\n", *valp); + goto bail_noprops; + } + + /* Look for the powertune data in the device-tree */ + g5_pmode_data = (u32 *)get_property(cpunode, "power-mode-data",&psize); + if (!g5_pmode_data) { + DBG("No power-mode-data !\n"); + goto bail_noprops; + } + g5_pmode_max = psize / sizeof(u32) - 1; + + /* Look for the FVT table */ + shdr = smu_get_sdb_partition(SMU_SDB_FVT_ID, NULL); + if (!shdr) + goto bail_noprops; + g5_fvt_table = (struct smu_sdbp_fvt *)&shdr[1]; + ssize = (shdr->len * sizeof(u32)) - sizeof(struct smu_sdbp_header); + g5_fvt_count = ssize / sizeof(struct smu_sdbp_fvt); + g5_fvt_cur = 0; + + /* Sanity checking */ + if (g5_fvt_count < 1 || g5_pmode_max < 1) + goto bail_noprops; + + /* + * From what I see, clock-frequency is always the maximal frequency. + * The current driver can not slew sysclk yet, so we really only deal + * with powertune steps for now. We also only implement full freq and + * half freq in this version. So far, I haven't yet seen a machine + * supporting anything else. + */ + valp = (u32 *)get_property(cpunode, "clock-frequency", NULL); + if (!valp) + return -ENODEV; + max_freq = (*valp)/1000; + g5_cpu_freqs[0].frequency = max_freq; + g5_cpu_freqs[1].frequency = max_freq/2; + + /* Check current frequency */ + g5_pmode_cur = g5_query_freq(); + if (g5_pmode_cur > 1) { + /* We don't support anything but 1:1 and 1:2, fixup ... */ + g5_switch_freq(1); + g5_pmode_cur = 1; + } + + printk(KERN_INFO "Registering G5 CPU frequency driver\n"); + printk(KERN_INFO "Low: %d Mhz, High: %d Mhz, Cur: %d MHz\n", + g5_cpu_freqs[1].frequency/1000, + g5_cpu_freqs[0].frequency/1000, + g5_cpu_freqs[g5_pmode_cur].frequency/1000); + + rc = cpufreq_register_driver(&g5_cpufreq_driver); + + /* We keep the CPU node on hold... hopefully, Apple G5 don't have + * hotplug CPU with a dynamic device-tree ... + */ + return rc; + + bail_noprops: + of_node_put(cpunode); + + return rc; +} + +module_init(g5_cpufreq_init); + + +MODULE_LICENSE("GPL"); Index: linux-work/drivers/macintosh/smu.c =================================================================== --- linux-work.orig/drivers/macintosh/smu.c 2005-09-20 13:05:11.000000000 +1000 +++ linux-work/drivers/macintosh/smu.c 2005-09-21 14:34:52.000000000 +1000 @@ -843,6 +843,18 @@ return 0; } +struct smu_sdbp_header *smu_get_sdb_partition(int id, unsigned int *size) +{ + char pname[32]; + + if (!smu) + return NULL; + + sprintf(pname, "sdb-partition-%02x", id); + return (struct smu_sdbp_header *)get_property(smu->of_node, + pname, size); +} +EXPORT_SYMBOL(smu_get_sdb_partition); /* Index: linux-work/include/asm-ppc64/smu.h =================================================================== --- linux-work.orig/include/asm-ppc64/smu.h 2005-09-20 11:57:47.000000000 +1000 +++ linux-work/include/asm-ppc64/smu.h 2005-09-21 14:21:13.000000000 +1000 @@ -144,7 +144,11 @@ * - lenght 8 ("VSLEWxyz") has 3 additional bytes appended, and is * used to set the voltage slewing point. The SMU replies with "DONE" * I yet have to figure out their exact meaning of those 3 bytes in - * both cases. + * both cases. They seem to be: + * x = processor mask + * y = op. point index + * z = processor freq. step index + * I haven't yet decyphered result codes * */ #define SMU_CMD_POWER_COMMAND 0xaa @@ -244,6 +248,7 @@ */ extern void smu_done_complete(struct smu_cmd *cmd, void *misc); + /* * Synchronous helpers. Will spin-wait for completion of a command */ @@ -334,6 +339,59 @@ #endif /* __KERNEL__ */ /* + * - SMU "sdb" partitions informations - + */ + + +/* + * Partition header format + */ +struct smu_sdbp_header { + __u8 id; + __u8 len; + __u8 version; + __u8 flags; +}; + +/* + * 32 bits integers are usually encoded with 2x16 bits swapped, + * this demangles them + */ +#define SMU_U32_MIX(x) ((((x) << 16) & 0xffff0000u) | (((x) >> 16) & 0xffffu)) + +/* This is the definition of the SMU sdb-partition-0x12 table (called + * CPU F/V/T operating points in Darwin). The definition for all those + * SMU tables should be moved to some separate file + */ +#define SMU_SDB_FVT_ID 0x12 + +struct smu_sdbp_fvt { + __u32 sysclk; /* Base SysClk frequency in Hz for + * this operating point + */ + __u8 pad; + __u8 maxtemp; /* Max temp. supported by this + * operating point + */ + + __u16 volts[3]; /* CPU core voltage for the 3 + * PowerTune modes, a mode with + * 0V = not supported. + */ +}; + +#ifdef __KERNEL__ +/* + * This returns the pointer to an SMU "sdb" partition data or NULL + * if not found. The data format is described below + */ +extern struct smu_sdbp_header *smu_get_sdb_partition(int id, + unsigned int *size); + +#endif /* __KERNEL__ */ + + +/* * - Userland interface - */ @@ -376,4 +434,5 @@ __u32 reply_len; /* Lenght of data follwing */ }; + #endif /* _SMU_H */ From benh at kernel.crashing.org Wed Sep 21 16:01:11 2005 From: benh at kernel.crashing.org (Benjamin Herrenschmidt) Date: Wed, 21 Sep 2005 16:01:11 +1000 Subject: [PATCH] ppc64: iMac G5 cpufreq support In-Reply-To: <1127282249.4386.101.camel@gaston> References: <1127282249.4386.101.camel@gaston> Message-ID: <1127282471.4386.104.camel@gaston> And this updated version fixes reporting of frequency in /proc/cpuinfo... This applies on top of the big SMU update posted earlier. It adds cpufreq support for iMac G5 (and SMU based desktop, though that one was untested, testers welcome). It supports full and half speed and also does voltage switching for more power savings. Next step is proper thermal control to make those fans quiet once for all ! Signed-off-by: Benjamin Herrenschmidt Index: linux-work/arch/ppc64/kernel/misc.S =================================================================== --- linux-work.orig/arch/ppc64/kernel/misc.S 2005-09-20 14:57:41.000000000 +1000 +++ linux-work/arch/ppc64/kernel/misc.S 2005-09-21 13:39:11.000000000 +1000 @@ -616,7 +616,7 @@ isync blr - /* +/* * Do an IO access in real mode */ _GLOBAL(real_writeb) @@ -649,6 +649,73 @@ #endif /* defined(CONFIG_PPC_PMAC) || defined(CONFIG_PPC_MAPLE) */ /* + * SCOM access functions for 970 (FX only for now) + * + * unsigned long scom970_read(unsigned int address); + * void scom970_write(unsigned int address, unsigned long value); + * + * The address passed in is the 24 bits register address. This code + * is 970 specific and will not check the status bits, so you should + * know what you are doing. + */ +_GLOBAL(scom970_read) + /* interrupts off */ + mfmsr r4 + li r0,0 + rlwimi r0,r4,0,MSR_EE + mtmsrd r0,1 + + /* rotate address 8 bits left, mask out low 16 bits as they + * aren't implemented on current CPUs and must be 0'd, + * and finally or in RW bit + */ + rlwinm r3,r3,8,0,15 + ori r3,r3,0x8000 + + /* do the actual scom read */ + sync + mtspr SPRN_SCOMC,r3 + isync + mfspr r3,SPRN_SCOMD + mfspr r0,SPRN_SCOMC + sync + isync + + /* XXX: fixup result on some buggy 970's (ouch ! we lost a bit, bah + * that's the best we can do). Not implemented yet as we don't use + * the scom on any of the bogus CPUs yet, but may have to be done + * ultimately + */ + + /* restore interrupts */ + mtmsrd r4,1 + blr + + +_GLOBAL(scom970_write) + /* interrupts off */ + mfmsr r5 + li r0,0 + rlwimi r0,r5,0,MSR_EE + mtmsrd r0,1 + + /* rotate address 8 bits left, mask out low 16 bits as they + * aren't implemented on current CPUs and must be 0'd + */ + rlwinm r3,r3,8,0,15 + + mtspr SPRN_SCOMD,r4 /* write data */ + mtspr SPRN_SCOMC,r3 /* write command */ + sync + isync + mfspr 3,SPRN_SCOMC + + /* restore interrupts */ + mtmsrd r5,1 + blr + + +/* * Create a kernel thread * kernel_thread(fn, arg, flags) */ Index: linux-work/include/asm-ppc64/processor.h =================================================================== --- linux-work.orig/include/asm-ppc64/processor.h 2005-09-20 09:54:26.000000000 +1000 +++ linux-work/include/asm-ppc64/processor.h 2005-09-20 16:00:42.000000000 +1000 @@ -177,6 +177,9 @@ #define SPRN_CTRLT 0x098 #define CTRL_RUNLATCH 0x1 +#define SPRN_SCOMC 0x114 +#define SPRN_SCOMD 0x115 + /* Performance monitor SPRs */ #define SPRN_SIAR 780 #define SPRN_SDAR 781 @@ -536,6 +539,9 @@ } } +extern unsigned long scom970_read(unsigned int address); +extern void scom970_write(unsigned int address, unsigned long value); + #endif /* __KERNEL__ */ #endif /* __ASSEMBLY__ */ Index: linux-work/arch/ppc64/Kconfig =================================================================== --- linux-work.orig/arch/ppc64/Kconfig 2005-09-20 14:57:39.000000000 +1000 +++ linux-work/arch/ppc64/Kconfig 2005-09-20 16:04:28.000000000 +1000 @@ -159,6 +159,17 @@ support. As of this writing the exact hardware interface is strongly in flux, so no good recommendation can be made. +source "drivers/cpufreq/Kconfig" + +config CPU_FREQ_PMAC + bool "Support for Apple G5" + depends on CPU_FREQ && PPC_PMAC64 + select CPU_FREQ_TABLE + help + This adds support for frequency switching on some Apple G5 + machine. This is currently very experimental and works only + on some iMac G5. + config IBMVIO depends on PPC_PSERIES || PPC_ISERIES bool Index: linux-work/arch/ppc64/kernel/Makefile =================================================================== --- linux-work.orig/arch/ppc64/kernel/Makefile 2005-09-07 11:09:56.000000000 +1000 +++ linux-work/arch/ppc64/kernel/Makefile 2005-09-20 16:05:32.000000000 +1000 @@ -60,6 +60,7 @@ obj-$(CONFIG_PPC_PMAC) += pmac_setup.o pmac_feature.o pmac_pci.o \ pmac_time.o pmac_nvram.o pmac_low_i2c.o \ udbg_scc.o +obj-$(CONFIG_CPU_FREQ_PMAC) += pmac_cpufreq.o obj-$(CONFIG_PPC_MAPLE) += maple_setup.o maple_pci.o maple_time.o \ udbg_16550.o Index: linux-work/arch/ppc64/kernel/pmac_cpufreq.c =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ linux-work/arch/ppc64/kernel/pmac_cpufreq.c 2005-09-21 16:00:22.000000000 +1000 @@ -0,0 +1,297 @@ +/* + * Copyright (C) 2002 - 2005 Benjamin Herrenschmidt + * and Markus Demleitner + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This driver adds basic cpufreq support for SMU & 970FX based G5 Macs, + * that is iMac G5 and latest single CPU desktop. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#undef DEBUG + +#ifdef DEBUG +#define DBG(fmt...) printk(fmt) +#else +#define DBG(fmt...) +#endif + +/* see 970FX user manual */ + +#define SCOM_PCR 0x0aa001 /* PCR scom addr */ + +#define PCR_HILO_SELECT 0x80000000U /* 1 = PCR, 0 = PCRH */ +#define PCR_SPEED_FULL 0x00000000U /* 1:1 speed value */ +#define PCR_SPEED_HALF 0x00020000U /* 1:2 speed value */ +#define PCR_SPEED_QUARTER 0x00040000U /* 1:4 speed value */ +#define PCR_SPEED_MASK 0x000e0000U /* speed mask */ +#define PCR_SPEED_SHIFT 17 +#define PCR_FREQ_REQ_VALID 0x00010000U /* freq request valid */ +#define PCR_VOLT_REQ_VALID 0x00008000U /* volt request valid */ +#define PCR_TARGET_TIME_MASK 0x00006000U /* target time */ +#define PCR_STATLAT_MASK 0x00001f00U /* STATLAT value */ +#define PCR_SNOOPLAT_MASK 0x000000f0U /* SNOOPLAT value */ +#define PCR_SNOOPACC_MASK 0x0000000fU /* SNOOPACC value */ + +#define SCOM_PSR 0x408001 /* PSR scom addr */ +/* warning: PSR is a 64 bits register */ +#define PSR_CMD_RECEIVED 0x2000000000000000U /* command received */ +#define PSR_CMD_COMPLETED 0x1000000000000000U /* command completed */ +#define PSR_CUR_SPEED_MASK 0x0300000000000000U /* current speed */ +#define PSR_CUR_SPEED_SHIFT (56) + +/* + * The G5 only supports two frequencies (Quarter speed is not supported) + */ +#define CPUFREQ_HIGH 0 +#define CPUFREQ_LOW 1 + +static struct cpufreq_frequency_table g5_cpu_freqs[] = { + {CPUFREQ_HIGH, 0}, + {CPUFREQ_LOW, 0}, + {0, CPUFREQ_TABLE_END}, +}; + +static struct freq_attr* g5_cpu_freqs_attr[] = { + &cpufreq_freq_attr_scaling_available_freqs, + NULL, +}; + +/* Power mode data is an array of the 32 bits PCR values to use for + * the various frequencies, retreived from the device-tree + */ +static u32 *g5_pmode_data; +static int g5_pmode_max; +static int g5_pmode_cur; + + +static struct smu_sdbp_fvt *g5_fvt_table; /* table of op. points */ +static int g5_fvt_count; /* number of op. points */ +static int g5_fvt_cur; /* current op. point */ + +/* ----------------- real hardware interface */ + +static void g5_switch_volt(int speed_mode) +{ + struct smu_simple_cmd cmd; + + DECLARE_COMPLETION(comp); + smu_queue_simple(&cmd, SMU_CMD_POWER_COMMAND, 8, smu_done_complete, + &comp, 'V', 'S', 'L', 'E', 'W', + 0xff, g5_fvt_cur+1, speed_mode); + wait_for_completion(&comp); +} + +static int g5_switch_freq(int speed_mode) +{ + int to; + + if (g5_pmode_cur == speed_mode) + return 0; + + /* If frequency is going up, first ramp up the voltage */ + if (speed_mode < g5_pmode_cur) + g5_switch_volt(speed_mode); + + /* Clear PCR high */ + scom970_write(SCOM_PCR, 0); + /* Clear PCR low */ + scom970_write(SCOM_PCR, PCR_HILO_SELECT | 0); + /* Set PCR low */ + scom970_write(SCOM_PCR, PCR_HILO_SELECT | + g5_pmode_data[speed_mode]); + + /* Wait for completion */ + for (to = 0; to < 10; to++) { + unsigned long psr = scom970_read(SCOM_PSR); + + if ((psr & PSR_CMD_RECEIVED) == 0 && + (((psr >> PSR_CUR_SPEED_SHIFT) ^ + (g5_pmode_data[speed_mode] >> PCR_SPEED_SHIFT)) & 0x3) + == 0) + break; + if (psr & PSR_CMD_COMPLETED) + break; + udelay(100); + } + + /* If frequency is going down, last ramp the voltage */ + if (speed_mode > g5_pmode_cur) + g5_switch_volt(speed_mode); + + g5_pmode_cur = speed_mode; + ppc_proc_freq = g5_cpu_freqs[speed_mode].frequency * 1000ul; + + return 0; +} + +static int g5_query_freq(void) +{ + unsigned long psr = scom970_read(SCOM_PSR); + int i; + + for (i = 0; i <= g5_pmode_max; i++) + if ((((psr >> PSR_CUR_SPEED_SHIFT) ^ + (g5_pmode_data[i] >> PCR_SPEED_SHIFT)) & 0x3) == 0) + break; + return i; +} + +/* ----------------- cpufreq bookkeeping */ +static int __pmac g5_cpufreq_verify(struct cpufreq_policy *policy) +{ + return cpufreq_frequency_table_verify(policy, g5_cpu_freqs); +} + +static int __pmac g5_cpufreq_target(struct cpufreq_policy *policy, + unsigned int target_freq, unsigned int relation) +{ + unsigned int newstate = 0; + + if (cpufreq_frequency_table_target(policy, g5_cpu_freqs, + target_freq, relation, &newstate)) + return -EINVAL; + + return g5_switch_freq(newstate); +} + +static int __pmac g5_cpufreq_cpu_init(struct cpufreq_policy *policy) +{ + if (policy->cpu != 0) + return -ENODEV; + + policy->governor = CPUFREQ_DEFAULT_GOVERNOR; + policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL; + policy->cur = g5_cpu_freqs[g5_query_freq()].frequency; + cpufreq_frequency_table_get_attr(g5_cpu_freqs, policy->cpu); + + return cpufreq_frequency_table_cpuinfo(policy, + g5_cpu_freqs); +} + + +static struct cpufreq_driver g5_cpufreq_driver = { + .name = "powermac", + .owner = THIS_MODULE, + .flags = CPUFREQ_CONST_LOOPS, + .init = g5_cpufreq_cpu_init, + .verify = g5_cpufreq_verify, + .target = g5_cpufreq_target, + .attr = g5_cpu_freqs_attr, +}; + + +static int __init g5_cpufreq_init(void) +{ + struct device_node *cpunode; + unsigned int psize, ssize; + struct smu_sdbp_header *shdr; + unsigned long max_freq; + u32 *valp; + int rc = -ENODEV; + + /* Look for CPU and SMU nodes */ + cpunode = of_find_node_by_type(NULL, "cpu"); + if (!cpunode) { + DBG("No CPU node !\n"); + return -ENODEV; + } + + /* Check 970FX for now */ + valp = (u32 *)get_property(cpunode, "cpu-version", NULL); + if (!valp) { + DBG("No cpu-version property !\n"); + goto bail_noprops; + } + if (((*valp) >> 16) != 0x3c) { + DBG("Wrong CPU version: %08x\n", *valp); + goto bail_noprops; + } + + /* Look for the powertune data in the device-tree */ + g5_pmode_data = (u32 *)get_property(cpunode, "power-mode-data",&psize); + if (!g5_pmode_data) { + DBG("No power-mode-data !\n"); + goto bail_noprops; + } + g5_pmode_max = psize / sizeof(u32) - 1; + + /* Look for the FVT table */ + shdr = smu_get_sdb_partition(SMU_SDB_FVT_ID, NULL); + if (!shdr) + goto bail_noprops; + g5_fvt_table = (struct smu_sdbp_fvt *)&shdr[1]; + ssize = (shdr->len * sizeof(u32)) - sizeof(struct smu_sdbp_header); + g5_fvt_count = ssize / sizeof(struct smu_sdbp_fvt); + g5_fvt_cur = 0; + + /* Sanity checking */ + if (g5_fvt_count < 1 || g5_pmode_max < 1) + goto bail_noprops; + + /* + * From what I see, clock-frequency is always the maximal frequency. + * The current driver can not slew sysclk yet, so we really only deal + * with powertune steps for now. We also only implement full freq and + * half freq in this version. So far, I haven't yet seen a machine + * supporting anything else. + */ + valp = (u32 *)get_property(cpunode, "clock-frequency", NULL); + if (!valp) + return -ENODEV; + max_freq = (*valp)/1000; + g5_cpu_freqs[0].frequency = max_freq; + g5_cpu_freqs[1].frequency = max_freq/2; + + /* Check current frequency */ + g5_pmode_cur = g5_query_freq(); + if (g5_pmode_cur > 1) { + /* We don't support anything but 1:1 and 1:2, fixup ... */ + g5_switch_freq(1); + g5_pmode_cur = 1; + } + + printk(KERN_INFO "Registering G5 CPU frequency driver\n"); + printk(KERN_INFO "Low: %d Mhz, High: %d Mhz, Cur: %d MHz\n", + g5_cpu_freqs[1].frequency/1000, + g5_cpu_freqs[0].frequency/1000, + g5_cpu_freqs[g5_pmode_cur].frequency/1000); + + rc = cpufreq_register_driver(&g5_cpufreq_driver); + + /* We keep the CPU node on hold... hopefully, Apple G5 don't have + * hotplug CPU with a dynamic device-tree ... + */ + return rc; + + bail_noprops: + of_node_put(cpunode); + + return rc; +} + +module_init(g5_cpufreq_init); + + +MODULE_LICENSE("GPL"); Index: linux-work/drivers/macintosh/smu.c =================================================================== --- linux-work.orig/drivers/macintosh/smu.c 2005-09-20 13:05:11.000000000 +1000 +++ linux-work/drivers/macintosh/smu.c 2005-09-21 14:34:52.000000000 +1000 @@ -843,6 +843,18 @@ return 0; } +struct smu_sdbp_header *smu_get_sdb_partition(int id, unsigned int *size) +{ + char pname[32]; + + if (!smu) + return NULL; + + sprintf(pname, "sdb-partition-%02x", id); + return (struct smu_sdbp_header *)get_property(smu->of_node, + pname, size); +} +EXPORT_SYMBOL(smu_get_sdb_partition); /* Index: linux-work/include/asm-ppc64/smu.h =================================================================== --- linux-work.orig/include/asm-ppc64/smu.h 2005-09-20 11:57:47.000000000 +1000 +++ linux-work/include/asm-ppc64/smu.h 2005-09-21 14:21:13.000000000 +1000 @@ -144,7 +144,11 @@ * - lenght 8 ("VSLEWxyz") has 3 additional bytes appended, and is * used to set the voltage slewing point. The SMU replies with "DONE" * I yet have to figure out their exact meaning of those 3 bytes in - * both cases. + * both cases. They seem to be: + * x = processor mask + * y = op. point index + * z = processor freq. step index + * I haven't yet decyphered result codes * */ #define SMU_CMD_POWER_COMMAND 0xaa @@ -244,6 +248,7 @@ */ extern void smu_done_complete(struct smu_cmd *cmd, void *misc); + /* * Synchronous helpers. Will spin-wait for completion of a command */ @@ -334,6 +339,59 @@ #endif /* __KERNEL__ */ /* + * - SMU "sdb" partitions informations - + */ + + +/* + * Partition header format + */ +struct smu_sdbp_header { + __u8 id; + __u8 len; + __u8 version; + __u8 flags; +}; + +/* + * 32 bits integers are usually encoded with 2x16 bits swapped, + * this demangles them + */ +#define SMU_U32_MIX(x) ((((x) << 16) & 0xffff0000u) | (((x) >> 16) & 0xffffu)) + +/* This is the definition of the SMU sdb-partition-0x12 table (called + * CPU F/V/T operating points in Darwin). The definition for all those + * SMU tables should be moved to some separate file + */ +#define SMU_SDB_FVT_ID 0x12 + +struct smu_sdbp_fvt { + __u32 sysclk; /* Base SysClk frequency in Hz for + * this operating point + */ + __u8 pad; + __u8 maxtemp; /* Max temp. supported by this + * operating point + */ + + __u16 volts[3]; /* CPU core voltage for the 3 + * PowerTune modes, a mode with + * 0V = not supported. + */ +}; + +#ifdef __KERNEL__ +/* + * This returns the pointer to an SMU "sdb" partition data or NULL + * if not found. The data format is described below + */ +extern struct smu_sdbp_header *smu_get_sdb_partition(int id, + unsigned int *size); + +#endif /* __KERNEL__ */ + + +/* * - Userland interface - */ @@ -376,4 +434,5 @@ __u32 reply_len; /* Lenght of data follwing */ }; + #endif /* _SMU_H */ From sharada at in.ibm.com Wed Sep 21 23:53:06 2005 From: sharada at in.ibm.com (R Sharada) Date: Wed, 21 Sep 2005 19:23:06 +0530 Subject: [PATCH 0/4] kexec-tools-for-ppc64 In-Reply-To: References: <20050914124405.GA3968@in.ibm.com> Message-ID: <20050921135306.GA3836@in.ibm.com> Hello Eric / All, The patch set still needs some cleanups (specially the memory_ranges code which is a bit convoluted and longish in ppc64 right now). I plan to come back to it sometime and try a cleaner approach. Besides, there are the compat issues (building it 64-bit and 32-bit on ppc64) that I have to test out and clean up, if required. However, I thought it good to have some clean working version out for scrutiny whilst it gets cleaned up further. We have started working on the kdump support for ppc64 and get them out, hopefully soon. Thanks and Regards, Sharada On Tue, Sep 20, 2005 at 11:30:32AM -0600, Eric W. Biederman wrote: > R Sharada writes: > > > Hello, > > After the initial RFC on the kexec-tools for ppc64, > > the hacks were cleaned up and this patchset now provides a > > much cleaner kexec-tools support for ppc64. > > > > Ack: At a first glance thing seem sane. > > I have been slapping some sense into the i386 and x86_64 kernels > lately so I haven't had a chance to merge things and get a > new release of kexec-tools out yet. Hopefully I can get to that > soon. > > Eric > From ebiederm at xmission.com Thu Sep 22 00:11:28 2005 From: ebiederm at xmission.com (Eric W. Biederman) Date: Wed, 21 Sep 2005 08:11:28 -0600 Subject: [PATCH 0/4] kexec-tools-for-ppc64 In-Reply-To: <20050921135306.GA3836@in.ibm.com> (R. Sharada's message of "Wed, 21 Sep 2005 19:23:06 +0530") References: <20050914124405.GA3968@in.ibm.com> <20050921135306.GA3836@in.ibm.com> Message-ID: R Sharada writes: > Hello Eric / All, > The patch set still needs some cleanups (specially the memory_ranges > code which is a bit convoluted and longish in ppc64 right now). I plan to come > back to it sometime and try a cleaner approach. > Besides, there are the compat issues (building it 64-bit and 32-bit on > ppc64) that I have to test out and clean up, if required. > However, I thought it good to have some clean working version out for > scrutiny whilst it gets cleaned up further. > We have started working on the kdump support for ppc64 and get them out, > hopefully soon. > To a large extent as long as the code just touches the ppc64 support I care a lot less about it because it won't break anyone else and it might make the code useful. My priority is till on merging the kdump patches but as that is generic infrastructure I have to be very careful. Eric From dwmw2 at infradead.org Thu Sep 22 03:14:59 2005 From: dwmw2 at infradead.org (David Woodhouse) Date: Wed, 21 Sep 2005 18:14:59 +0100 Subject: [PATCH] Avoid use of uninitialised spinlock in EEH. Message-ID: <1127322900.28995.149.camel@hades.cambridge.redhat.com> If the kernel supports both G5 and pSeries, and CONFIG_EEH is enabled, eeh_init() is (quite reasonably) never called when we boot on a G5. Yet eeh_check_failure() still gets called. We should avoid doing that if !eeh_subsystem_enabled. Signed-off-by: David Woodhouse --- linux-2.6.13/include/asm-ppc64/eeh.h~ 2005-09-21 16:36:23.000000000 +0100 +++ linux-2.6.13/include/asm-ppc64/eeh.h 2005-09-21 17:41:51.000000000 +0100 @@ -32,6 +32,8 @@ struct notifier_block; #ifdef CONFIG_EEH +extern int eeh_subsystem_enabled; + /* Values for eeh_mode bits in device_node */ #define EEH_MODE_SUPPORTED (1<<0) #define EEH_MODE_NOCHECK (1<<1) @@ -95,7 +97,7 @@ int eeh_unregister_notifier(struct notif * If this macro yields TRUE, the caller relays to eeh_check_failure() * which does further tests out of line. */ -#define EEH_POSSIBLE_ERROR(val, type) ((val) == (type)~0) +#define EEH_POSSIBLE_ERROR(val, type) (eeh_subsystem_enabled && (val) == (type)~0) /* * Reads from a device which has been isolated by EEH will return --- linux-2.6.13/arch/ppc64/kernel/eeh.c~ 2005-09-21 16:35:49.000000000 +0100 +++ linux-2.6.13/arch/ppc64/kernel/eeh.c 2005-09-21 17:40:41.000000000 +0100 @@ -99,7 +99,8 @@ static int ibm_read_slot_reset_state; static int ibm_read_slot_reset_state2; static int ibm_slot_error_detail; -static int eeh_subsystem_enabled; +int eeh_subsystem_enabled; +EXPORT_SYMBOL(eeh_subsystem_enabled); /* Buffer for reporting slot-error-detail rtas calls */ static unsigned char slot_errbuf[RTAS_ERROR_LOG_MAX]; -- dwmw2 From agl at us.ibm.com Thu Sep 22 04:22:46 2005 From: agl at us.ibm.com (Adam Litke) Date: Wed, 21 Sep 2005 13:22:46 -0500 Subject: Hugetlb HPTE hashing weirdness Message-ID: <1127326966.22154.55.camel@localhost.localdomain> I am seeing strange corruption on recent (eg. 2.6.14-rc1) kernels when using hugetlb pages. I have a simple program which does the following: 1) Mmap a hugetlbfs file 2) Test that all pages are zero 3) Write 'A' to every byte of page 0, 'B' to page 1, and so on 4) Verify that the data was written correctly Occasionally, the verify step above will fail for the first page of the mapping. We'll discover that 'J' is scribbled on the page instead of the expected 'A'. It appears that the Hardware page tables are populated with stale references from previous runs of the program. I've instrumented hash_huge_page() to see what is going on and when the program runs correctly, hash_huge_page() is called once for each time the program accesses a large page for the first time. In subsequent runs, hash_huge_page() is only called once for the first page accessed. This tells me that the hardware is using previous/stale hash entries to provide the virtual to physical address translation for the rest of the pages, thus potentially using the wrong huge page, leading to corruption. I may be mistaken, but it looks like for small pages the vsid is used as the "key" to the hardware hash table but for huge pages only the virtual page frame number (vpn) is used. Could someone explain the difference between the way huge pages and normal pages are hashed? Using only the vpn seems like it would result in false hash hits whenever separate programs map huge pages at the same virtual address. At any rate, I think this is a serious bug in hugetlb pages on ppc64 and I am surprised others haven't hit it yet. Thanks for any info you can provide to help me debug this. From galak at freescale.com Thu Sep 22 05:11:56 2005 From: galak at freescale.com (Kumar Gala) Date: Wed, 21 Sep 2005 14:11:56 -0500 (CDT) Subject: [PATCH] powerpc: merge include/asm-ppc*/checksum.h into include/asm-powerpc/checksum.h Message-ID: Signed-off-by: Kumar Gala --- commit 5bb6a54bbcd717339f737eba160b6824ec99cd27 tree b23e814e1546aeceaa58ccfafc714a8cf0a13656 parent 1288b50c0dd4747595c5e73dbff02088d8eeefcc author Kumar K. Gala Wed, 21 Sep 2005 14:10:11 -0500 committer Kumar K. Gala Wed, 21 Sep 2005 14:10:11 -0500 include/asm-powerpc/checksum.h | 132 ++++++++++++++++++++++++++++++++++++++++ include/asm-ppc/checksum.h | 107 -------------------------------- include/asm-ppc64/checksum.h | 107 -------------------------------- 3 files changed, 132 insertions(+), 214 deletions(-) diff --git a/include/asm-powerpc/checksum.h b/include/asm-powerpc/checksum.h new file mode 100644 --- /dev/null +++ b/include/asm-powerpc/checksum.h @@ -0,0 +1,132 @@ +#ifndef _ASM_POWERPC_CHECKSUM_H +#define _ASM_POWERPC_CHECKSUM_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 is a version of ip_compute_csum() optimized for IP headers, + * which always checksum on 4 octet boundaries. ihl is the number + * of 32-bit words and is always >= 5. + */ +extern unsigned short ip_fast_csum(unsigned char * iph, unsigned int ihl); + +/* + * computes the checksum of the TCP/UDP pseudo-header + * returns a 16-bit checksum, already complemented + */ +extern unsigned short csum_tcpudp_magic(unsigned long saddr, + unsigned long daddr, + unsigned short len, + unsigned short proto, + unsigned int sum); + +/* + * computes the checksum of a memory block at buff, length len, + * and adds in "sum" (32-bit) + * + * returns a 32-bit number suitable for feeding into itself + * or csum_tcpudp_magic + * + * this function must be called with even lengths, except + * for the last fragment, which may be odd + * + * it's best to have buff aligned on a 32-bit boundary + */ +extern unsigned int csum_partial(const unsigned char * buff, int len, + unsigned int sum); + +/* + * Computes the checksum of a memory block at src, length len, + * and adds in "sum" (32-bit), while copying the block to dst. + * If an access exception occurs on src or dst, it stores -EFAULT + * to *src_err or *dst_err respectively (if that pointer is not + * NULL), and, for an error on src, zeroes the rest of dst. + * + * Like csum_partial, this must be called with even lengths, + * except for the last fragment. + */ +extern unsigned int csum_partial_copy_generic(const char *src, char *dst, + int len, unsigned int sum, + int *src_err, int *dst_err); +/* + * the same as csum_partial, but copies from src to dst while it + * checksums. + */ +unsigned int csum_partial_copy_nocheck(const char *src, + char *dst, + int len, + unsigned int sum); + +#define csum_partial_copy_from_user(src, dst, len, sum, errp) \ + csum_partial_copy_generic((src), (dst), (len), (sum), (errp), NULL) + +#define csum_partial_copy_nocheck(src, dst, len, sum) \ + csum_partial_copy_generic((src), (dst), (len), (sum), NULL, NULL) + + +/* + * turns a 32-bit partial checksum (e.g. from csum_partial) into a + * 1's complement 16-bit checksum. + */ +static inline unsigned int csum_fold(unsigned int sum) +{ + unsigned int tmp; + + /* swap the two 16-bit halves of sum */ + __asm__("rlwinm %0,%1,16,0,31" : "=r" (tmp) : "r" (sum)); + /* if there is a carry from adding the two 16-bit halves, + it will carry from the lower half into the upper half, + giving us the correct sum in the upper half. */ + sum = ~(sum + tmp) >> 16; + return sum; +} + +/* + * this routine is used for miscellaneous IP-like checksums, mainly + * in icmp.c + */ +static inline unsigned short ip_compute_csum(unsigned char * buff, int len) +{ + return csum_fold(csum_partial(buff, len, 0)); +} + +#ifdef __powerpc64__ +static inline u32 csum_tcpudp_nofold(u32 saddr, + u32 daddr, + unsigned short len, + unsigned short proto, + unsigned int sum) +{ + unsigned long s = sum; + + s += saddr; + s += daddr; + s += (proto << 16) + len; + s += (s >> 32); + return (u32) s; +} +#else +static inline unsigned long csum_tcpudp_nofold(unsigned long saddr, + unsigned long daddr, + unsigned short len, + unsigned short proto, + unsigned int sum) +{ + __asm__("\n\ + addc %0,%0,%1 \n\ + adde %0,%0,%2 \n\ + adde %0,%0,%3 \n\ + addze %0,%0 \n\ + " + : "=r" (sum) + : "r" (daddr), "r"(saddr), "r"((proto<<16)+len), "0"(sum)); + return sum; +} + +#endif +#endif diff --git a/include/asm-ppc/checksum.h b/include/asm-ppc/checksum.h deleted file mode 100644 --- a/include/asm-ppc/checksum.h +++ /dev/null @@ -1,107 +0,0 @@ -#ifdef __KERNEL__ -#ifndef _PPC_CHECKSUM_H -#define _PPC_CHECKSUM_H - - -/* - * computes the checksum of a memory block at buff, length len, - * and adds in "sum" (32-bit) - * - * returns a 32-bit number suitable for feeding into itself - * or csum_tcpudp_magic - * - * this function must be called with even lengths, except - * for the last fragment, which may be odd - * - * it's best to have buff aligned on a 32-bit boundary - */ -extern unsigned int csum_partial(const unsigned char * buff, int len, - unsigned int sum); - -/* - * Computes the checksum of a memory block at src, length len, - * and adds in "sum" (32-bit), while copying the block to dst. - * If an access exception occurs on src or dst, it stores -EFAULT - * to *src_err or *dst_err respectively (if that pointer is not - * NULL), and, for an error on src, zeroes the rest of dst. - * - * Like csum_partial, this must be called with even lengths, - * except for the last fragment. - */ -extern unsigned int csum_partial_copy_generic(const char *src, char *dst, - int len, unsigned int sum, - int *src_err, int *dst_err); - -#define csum_partial_copy_from_user(src, dst, len, sum, errp) \ - csum_partial_copy_generic((__force void *)(src), (dst), (len), (sum), (errp), NULL) - -/* FIXME: this needs to be written to really do no check -- Cort */ -#define csum_partial_copy_nocheck(src, dst, len, sum) \ - csum_partial_copy_generic((src), (dst), (len), (sum), NULL, NULL) - -/* - * turns a 32-bit partial checksum (e.g. from csum_partial) into a - * 1's complement 16-bit checksum. - */ -static inline unsigned int csum_fold(unsigned int sum) -{ - unsigned int tmp; - - /* swap the two 16-bit halves of sum */ - __asm__("rlwinm %0,%1,16,0,31" : "=r" (tmp) : "r" (sum)); - /* if there is a carry from adding the two 16-bit halves, - it will carry from the lower half into the upper half, - giving us the correct sum in the upper half. */ - sum = ~(sum + tmp) >> 16; - return sum; -} - -/* - * this routine is used for miscellaneous IP-like checksums, mainly - * in icmp.c - */ -static inline unsigned short ip_compute_csum(unsigned char * buff, int len) -{ - return csum_fold(csum_partial(buff, len, 0)); -} - -/* - * FIXME: I swiped this one from the sparc and made minor modifications. - * It may not be correct. -- Cort - */ -static inline unsigned long csum_tcpudp_nofold(unsigned long saddr, - unsigned long daddr, - unsigned short len, - unsigned short proto, - unsigned int sum) -{ - __asm__("\n\ - addc %0,%0,%1 \n\ - adde %0,%0,%2 \n\ - adde %0,%0,%3 \n\ - addze %0,%0 \n\ - " - : "=r" (sum) - : "r" (daddr), "r"(saddr), "r"((proto<<16)+len), "0"(sum)); - return sum; -} - -/* - * This is a version of ip_compute_csum() optimized for IP headers, - * which always checksum on 4 octet boundaries. ihl is the number - * of 32-bit words and is always >= 5. - */ -extern unsigned short ip_fast_csum(unsigned char * iph, unsigned int ihl); - -/* - * computes the checksum of the TCP/UDP pseudo-header - * returns a 16-bit checksum, already complemented - */ -extern unsigned short csum_tcpudp_magic(unsigned long saddr, - unsigned long daddr, - unsigned short len, - unsigned short proto, - unsigned int sum); - -#endif -#endif /* __KERNEL__ */ diff --git a/include/asm-ppc64/checksum.h b/include/asm-ppc64/checksum.h deleted file mode 100644 --- a/include/asm-ppc64/checksum.h +++ /dev/null @@ -1,107 +0,0 @@ -#ifndef _PPC64_CHECKSUM_H -#define _PPC64_CHECKSUM_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 is a version of ip_compute_csum() optimized for IP headers, - * which always checksum on 4 octet boundaries. ihl is the number - * of 32-bit words and is always >= 5. - */ -extern unsigned short ip_fast_csum(unsigned char * iph, unsigned int ihl); - -/* - * computes the checksum of the TCP/UDP pseudo-header - * returns a 16-bit checksum, already complemented - */ -extern unsigned short csum_tcpudp_magic(unsigned long saddr, - unsigned long daddr, - unsigned short len, - unsigned short proto, - unsigned int sum); - -/* - * computes the checksum of a memory block at buff, length len, - * and adds in "sum" (32-bit) - * - * returns a 32-bit number suitable for feeding into itself - * or csum_tcpudp_magic - * - * this function must be called with even lengths, except - * for the last fragment, which may be odd - * - * it's best to have buff aligned on a 32-bit boundary - */ -extern unsigned int csum_partial(const unsigned char * buff, int len, - unsigned int sum); - -/* - * the same as csum_partial, but copies from src to dst while it - * checksums - */ -extern unsigned int csum_partial_copy_generic(const char *src, char *dst, - int len, unsigned int sum, - int *src_err, int *dst_err); -/* - * the same as csum_partial, but copies from src to dst while it - * checksums. - */ - -unsigned int csum_partial_copy_nocheck(const char *src, - char *dst, - int len, - unsigned int sum); - -/* - * turns a 32-bit partial checksum (e.g. from csum_partial) into a - * 1's complement 16-bit checksum. - */ -static inline unsigned int csum_fold(unsigned int sum) -{ - unsigned int tmp; - - /* swap the two 16-bit halves of sum */ - __asm__("rlwinm %0,%1,16,0,31" : "=r" (tmp) : "r" (sum)); - /* if there is a carry from adding the two 16-bit halves, - it will carry from the lower half into the upper half, - giving us the correct sum in the upper half. */ - sum = ~(sum + tmp) >> 16; - return sum; -} - -/* - * this routine is used for miscellaneous IP-like checksums, mainly - * in icmp.c - */ -static inline unsigned short ip_compute_csum(unsigned char * buff, int len) -{ - return csum_fold(csum_partial(buff, len, 0)); -} - -#define csum_partial_copy_from_user(src, dst, len, sum, errp) \ - csum_partial_copy_generic((src), (dst), (len), (sum), (errp), NULL) - -#define csum_partial_copy_nocheck(src, dst, len, sum) \ - csum_partial_copy_generic((src), (dst), (len), (sum), NULL, NULL) - -static inline u32 csum_tcpudp_nofold(u32 saddr, - u32 daddr, - unsigned short len, - unsigned short proto, - unsigned int sum) -{ - unsigned long s = sum; - - s += saddr; - s += daddr; - s += (proto << 16) + len; - s += (s >> 32); - return (u32) s; -} - -#endif From linuxppc at jdl.com Thu Sep 22 05:54:51 2005 From: linuxppc at jdl.com (Jon Loeliger) Date: Wed, 21 Sep 2005 14:54:51 -0500 Subject: PATCH powerpc Merge asm-ppc*/dma.h Message-ID: This patch merges the asm-ppc*/dma.h files. Signed-off-by: Jon Loeliger Signed-off-by: Kumar Gala --- arch/ppc/kernel/setup.c | 3 include/asm-powerpc/dma.h | 390 +++++++++++++++++++++++++++++++++++++++++++++ include/asm-ppc/dma.h | 371 ------------------------------------------- include/asm-ppc64/dma.h | 329 -------------------------------------- 4 files changed, 392 insertions(+), 701 deletions(-) diff --git a/arch/ppc/kernel/setup.c b/arch/ppc/kernel/setup.c --- a/arch/ppc/kernel/setup.c +++ b/arch/ppc/kernel/setup.c @@ -71,7 +71,8 @@ struct ide_machdep_calls ppc_ide_md; unsigned long boot_mem_size; unsigned long ISA_DMA_THRESHOLD; -unsigned long DMA_MODE_READ, DMA_MODE_WRITE; +unsigned int DMA_MODE_READ; +unsigned int DMA_MODE_WRITE; #ifdef CONFIG_PPC_MULTIPLATFORM int _machine = 0; diff --git a/include/asm-powerpc/dma.h b/include/asm-powerpc/dma.h new file mode 100644 --- /dev/null +++ b/include/asm-powerpc/dma.h @@ -0,0 +1,390 @@ +#ifndef _ASM_POWERPC_DMA_H +#define _ASM_POWERPC_DMA_H + +/* + * Defines for using and allocating dma channels. + * Written by Hennus Bergman, 1992. + * High DMA channel support & info by Hannu Savolainen + * and John Boyd, Nov. 1992. + * Changes for ppc sound by Christoph Nadig + */ + +/* + * Note: Adapted for PowerPC by Gary Thomas + * Modified by Cort Dougan + * + * None of this really applies for Power Macintoshes. There is + * basically just enough here to get kernel/dma.c to compile. + * + * There may be some comments or restrictions made here which are + * not valid for the PReP platform. Take what you read + * with a grain of salt. + */ + +#include +#include +#include +#include + +#ifndef MAX_DMA_CHANNELS +#define MAX_DMA_CHANNELS 8 +#endif + +/* The maximum address that we can perform a DMA transfer to on this platform */ +/* Doesn't really apply... */ +#define MAX_DMA_ADDRESS (~0UL) + +#if !defined(CONFIG_PPC_ISERIES) || defined(CONFIG_PCI) + +#ifdef HAVE_REALLY_SLOW_DMA_CONTROLLER +#define dma_outb outb_p +#else +#define dma_outb outb +#endif + +#define dma_inb inb + +/* + * NOTES about DMA transfers: + * + * controller 1: channels 0-3, byte operations, ports 00-1F + * controller 2: channels 4-7, word operations, ports C0-DF + * + * - ALL registers are 8 bits only, regardless of transfer size + * - channel 4 is not used - cascades 1 into 2. + * - channels 0-3 are byte - addresses/counts are for physical bytes + * - channels 5-7 are word - addresses/counts are for physical words + * - transfers must not cross physical 64K (0-3) or 128K (5-7) boundaries + * - transfer count loaded to registers is 1 less than actual count + * - controller 2 offsets are all even (2x offsets for controller 1) + * - page registers for 5-7 don't use data bit 0, represent 128K pages + * - page registers for 0-3 use bit 0, represent 64K pages + * + * On PReP, DMA transfers are limited to the lower 16MB of _physical_ memory. + * On CHRP, the W83C553F (and VLSI Tollgate?) support full 32 bit addressing. + * Note that addresses loaded into registers must be _physical_ addresses, + * not logical addresses (which may differ if paging is active). + * + * Address mapping for channels 0-3: + * + * A23 ... A16 A15 ... A8 A7 ... A0 (Physical addresses) + * | ... | | ... | | ... | + * | ... | | ... | | ... | + * | ... | | ... | | ... | + * P7 ... P0 A7 ... A0 A7 ... A0 + * | Page | Addr MSB | Addr LSB | (DMA registers) + * + * Address mapping for channels 5-7: + * + * A23 ... A17 A16 A15 ... A9 A8 A7 ... A1 A0 (Physical addresses) + * | ... | \ \ ... \ \ \ ... \ \ + * | ... | \ \ ... \ \ \ ... \ (not used) + * | ... | \ \ ... \ \ \ ... \ + * P7 ... P1 (0) A7 A6 ... A0 A7 A6 ... A0 + * | Page | Addr MSB | Addr LSB | (DMA registers) + * + * Again, channels 5-7 transfer _physical_ words (16 bits), so addresses + * and counts _must_ be word-aligned (the lowest address bit is _ignored_ at + * the hardware level, so odd-byte transfers aren't possible). + * + * Transfer count (_not # bytes_) is limited to 64K, represented as actual + * count - 1 : 64K => 0xFFFF, 1 => 0x0000. Thus, count is always 1 or more, + * and up to 128K bytes may be transferred on channels 5-7 in one operation. + * + */ + +/* see prep_setup_arch() for detailed informations */ +#if defined(CONFIG_SOUND_CS4232) && defined(CONFIG_PPC_PREP) +extern long ppc_cs4232_dma, ppc_cs4232_dma2; +#define SND_DMA1 ppc_cs4232_dma +#define SND_DMA2 ppc_cs4232_dma2 +#else +#define SND_DMA1 -1 +#define SND_DMA2 -1 +#endif + +/* 8237 DMA controllers */ +#define IO_DMA1_BASE 0x00 /* 8 bit slave DMA, channels 0..3 */ +#define IO_DMA2_BASE 0xC0 /* 16 bit master DMA, ch 4(=slave input)..7 */ + +/* DMA controller registers */ +#define DMA1_CMD_REG 0x08 /* command register (w) */ +#define DMA1_STAT_REG 0x08 /* status register (r) */ +#define DMA1_REQ_REG 0x09 /* request register (w) */ +#define DMA1_MASK_REG 0x0A /* single-channel mask (w) */ +#define DMA1_MODE_REG 0x0B /* mode register (w) */ +#define DMA1_CLEAR_FF_REG 0x0C /* clear pointer flip-flop (w) */ +#define DMA1_TEMP_REG 0x0D /* Temporary Register (r) */ +#define DMA1_RESET_REG 0x0D /* Master Clear (w) */ +#define DMA1_CLR_MASK_REG 0x0E /* Clear Mask */ +#define DMA1_MASK_ALL_REG 0x0F /* all-channels mask (w) */ + +#define DMA2_CMD_REG 0xD0 /* command register (w) */ +#define DMA2_STAT_REG 0xD0 /* status register (r) */ +#define DMA2_REQ_REG 0xD2 /* request register (w) */ +#define DMA2_MASK_REG 0xD4 /* single-channel mask (w) */ +#define DMA2_MODE_REG 0xD6 /* mode register (w) */ +#define DMA2_CLEAR_FF_REG 0xD8 /* clear pointer flip-flop (w) */ +#define DMA2_TEMP_REG 0xDA /* Temporary Register (r) */ +#define DMA2_RESET_REG 0xDA /* Master Clear (w) */ +#define DMA2_CLR_MASK_REG 0xDC /* Clear Mask */ +#define DMA2_MASK_ALL_REG 0xDE /* all-channels mask (w) */ + +#define DMA_ADDR_0 0x00 /* DMA address registers */ +#define DMA_ADDR_1 0x02 +#define DMA_ADDR_2 0x04 +#define DMA_ADDR_3 0x06 +#define DMA_ADDR_4 0xC0 +#define DMA_ADDR_5 0xC4 +#define DMA_ADDR_6 0xC8 +#define DMA_ADDR_7 0xCC + +#define DMA_CNT_0 0x01 /* DMA count registers */ +#define DMA_CNT_1 0x03 +#define DMA_CNT_2 0x05 +#define DMA_CNT_3 0x07 +#define DMA_CNT_4 0xC2 +#define DMA_CNT_5 0xC6 +#define DMA_CNT_6 0xCA +#define DMA_CNT_7 0xCE + +#define DMA_LO_PAGE_0 0x87 /* DMA page registers */ +#define DMA_LO_PAGE_1 0x83 +#define DMA_LO_PAGE_2 0x81 +#define DMA_LO_PAGE_3 0x82 +#define DMA_LO_PAGE_5 0x8B +#define DMA_LO_PAGE_6 0x89 +#define DMA_LO_PAGE_7 0x8A + +#define DMA_HI_PAGE_0 0x487 /* DMA page registers */ +#define DMA_HI_PAGE_1 0x483 +#define DMA_HI_PAGE_2 0x481 +#define DMA_HI_PAGE_3 0x482 +#define DMA_HI_PAGE_5 0x48B +#define DMA_HI_PAGE_6 0x489 +#define DMA_HI_PAGE_7 0x48A + +#define DMA1_EXT_REG 0x40B +#define DMA2_EXT_REG 0x4D6 + +#ifndef __powerpc64__ + /* in arch/ppc/kernel/setup.c -- Cort */ + extern unsigned int DMA_MODE_WRITE; + extern unsigned int DMA_MODE_READ; + extern unsigned long ISA_DMA_THRESHOLD; +#else + #define DMA_MODE_READ 0x44 /* I/O to memory, no autoinit, increment, single mode */ + #define DMA_MODE_WRITE 0x48 /* memory to I/O, no autoinit, increment, single mode */ +#endif + +#define DMA_MODE_CASCADE 0xC0 /* pass thru DREQ->HRQ, DACK<-HLDA only */ + +#define DMA_AUTOINIT 0x10 + +extern spinlock_t dma_spin_lock; + +static __inline__ unsigned long claim_dma_lock(void) +{ + unsigned long flags; + spin_lock_irqsave(&dma_spin_lock, flags); + return flags; +} + +static __inline__ void release_dma_lock(unsigned long flags) +{ + spin_unlock_irqrestore(&dma_spin_lock, flags); +} + +/* enable/disable a specific DMA channel */ +static __inline__ void enable_dma(unsigned int dmanr) +{ + unsigned char ucDmaCmd = 0x00; + + if (dmanr != 4) { + dma_outb(0, DMA2_MASK_REG); /* This may not be enabled */ + dma_outb(ucDmaCmd, DMA2_CMD_REG); /* Enable group */ + } + if (dmanr <= 3) { + dma_outb(dmanr, DMA1_MASK_REG); + dma_outb(ucDmaCmd, DMA1_CMD_REG); /* Enable group */ + } else { + dma_outb(dmanr & 3, DMA2_MASK_REG); + } +} + +static __inline__ void disable_dma(unsigned int dmanr) +{ + if (dmanr <= 3) + dma_outb(dmanr | 4, DMA1_MASK_REG); + else + dma_outb((dmanr & 3) | 4, DMA2_MASK_REG); +} + +/* Clear the 'DMA Pointer Flip Flop'. + * Write 0 for LSB/MSB, 1 for MSB/LSB access. + * Use this once to initialize the FF to a known state. + * After that, keep track of it. :-) + * --- In order to do that, the DMA routines below should --- + * --- only be used while interrupts are disabled! --- + */ +static __inline__ void clear_dma_ff(unsigned int dmanr) +{ + if (dmanr <= 3) + dma_outb(0, DMA1_CLEAR_FF_REG); + else + dma_outb(0, DMA2_CLEAR_FF_REG); +} + +/* set mode (above) for a specific DMA channel */ +static __inline__ void set_dma_mode(unsigned int dmanr, char mode) +{ + if (dmanr <= 3) + dma_outb(mode | dmanr, DMA1_MODE_REG); + else + dma_outb(mode | (dmanr & 3), DMA2_MODE_REG); +} + +/* Set only the page register bits of the transfer address. + * This is used for successive transfers when we know the contents of + * the lower 16 bits of the DMA current address register, but a 64k boundary + * may have been crossed. + */ +static __inline__ void set_dma_page(unsigned int dmanr, int pagenr) +{ + switch (dmanr) { + case 0: + dma_outb(pagenr, DMA_LO_PAGE_0); + dma_outb(pagenr >> 8, DMA_HI_PAGE_0); + break; + case 1: + dma_outb(pagenr, DMA_LO_PAGE_1); + dma_outb(pagenr >> 8, DMA_HI_PAGE_1); + break; + case 2: + dma_outb(pagenr, DMA_LO_PAGE_2); + dma_outb(pagenr >> 8, DMA_HI_PAGE_2); + break; + case 3: + dma_outb(pagenr, DMA_LO_PAGE_3); + dma_outb(pagenr >> 8, DMA_HI_PAGE_3); + break; + case 5: + if (SND_DMA1 == 5 || SND_DMA2 == 5) + dma_outb(pagenr, DMA_LO_PAGE_5); + else + dma_outb(pagenr & 0xfe, DMA_LO_PAGE_5); + dma_outb(pagenr >> 8, DMA_HI_PAGE_5); + break; + case 6: + if (SND_DMA1 == 6 || SND_DMA2 == 6) + dma_outb(pagenr, DMA_LO_PAGE_6); + else + dma_outb(pagenr & 0xfe, DMA_LO_PAGE_6); + dma_outb(pagenr >> 8, DMA_HI_PAGE_6); + break; + case 7: + if (SND_DMA1 == 7 || SND_DMA2 == 7) + dma_outb(pagenr, DMA_LO_PAGE_7); + else + dma_outb(pagenr & 0xfe, DMA_LO_PAGE_7); + dma_outb(pagenr >> 8, DMA_HI_PAGE_7); + break; + } +} + +/* Set transfer address & page bits for specific DMA channel. + * Assumes dma flipflop is clear. + */ +static __inline__ void set_dma_addr(unsigned int dmanr, unsigned int phys) +{ + if (dmanr <= 3) { + dma_outb(phys & 0xff, + ((dmanr & 3) << 1) + IO_DMA1_BASE); + dma_outb((phys >> 8) & 0xff, + ((dmanr & 3) << 1) + IO_DMA1_BASE); + } else if (dmanr == SND_DMA1 || dmanr == SND_DMA2) { + dma_outb(phys & 0xff, + ((dmanr & 3) << 2) + IO_DMA2_BASE); + dma_outb((phys >> 8) & 0xff, + ((dmanr & 3) << 2) + IO_DMA2_BASE); + dma_outb((dmanr & 3), DMA2_EXT_REG); + } else { + dma_outb((phys >> 1) & 0xff, + ((dmanr & 3) << 2) + IO_DMA2_BASE); + dma_outb((phys >> 9) & 0xff, + ((dmanr & 3) << 2) + IO_DMA2_BASE); + } + set_dma_page(dmanr, phys >> 16); +} + + +/* Set transfer size (max 64k for DMA1..3, 128k for DMA5..7) for + * a specific DMA channel. + * You must ensure the parameters are valid. + * NOTE: from a manual: "the number of transfers is one more + * than the initial word count"! This is taken into account. + * Assumes dma flip-flop is clear. + * NOTE 2: "count" represents _bytes_ and must be even for channels 5-7. + */ +static __inline__ void set_dma_count(unsigned int dmanr, unsigned int count) +{ + count--; + if (dmanr <= 3) { + dma_outb(count & 0xff, + ((dmanr & 3) << 1) + 1 + IO_DMA1_BASE); + dma_outb((count >> 8) & 0xff, + ((dmanr & 3) << 1) + 1 + IO_DMA1_BASE); + } else if (dmanr == SND_DMA1 || dmanr == SND_DMA2) { + dma_outb(count & 0xff, + ((dmanr & 3) << 2) + 2 + IO_DMA2_BASE); + dma_outb((count >> 8) & 0xff, + ((dmanr & 3) << 2) + 2 + IO_DMA2_BASE); + } else { + dma_outb((count >> 1) & 0xff, + ((dmanr & 3) << 2) + 2 + IO_DMA2_BASE); + dma_outb((count >> 9) & 0xff, + ((dmanr & 3) << 2) + 2 + IO_DMA2_BASE); + } +} + + +/* Get DMA residue count. After a DMA transfer, this + * should return zero. Reading this while a DMA transfer is + * still in progress will return unpredictable results. + * If called before the channel has been used, it may return 1. + * Otherwise, it returns the number of _bytes_ left to transfer. + * + * Assumes DMA flip-flop is clear. + */ +static __inline__ int get_dma_residue(unsigned int dmanr) +{ + unsigned int io_port = (dmanr <= 3) + ? ((dmanr & 3) << 1) + 1 + IO_DMA1_BASE + : ((dmanr & 3) << 2) + 2 + IO_DMA2_BASE; + + /* using short to get 16-bit wrap around */ + unsigned short count; + + count = 1 + dma_inb(io_port); + count += dma_inb(io_port) << 8; + + return (dmanr <= 3 || dmanr == SND_DMA1 || dmanr == SND_DMA2) + ? count : (count << 1); +} + +/* These are in kernel/dma.c: */ + +/* reserve a DMA channel */ +extern int request_dma(unsigned int dmanr, const char *device_id); +/* release it again */ +extern void free_dma(unsigned int dmanr); + +#ifdef CONFIG_PCI +extern int isa_dma_bridge_buggy; +#else +#define isa_dma_bridge_buggy (0) +#endif + +#endif /* !defined(CONFIG_PPC_ISERIES) || defined(CONFIG_PCI) */ + +#endif /* _ASM_POWERPC_DMA_H */ diff --git a/include/asm-ppc/dma.h b/include/asm-ppc/dma.h deleted file mode 100644 --- a/include/asm-ppc/dma.h +++ /dev/null @@ -1,371 +0,0 @@ -/* - * include/asm-ppc/dma.h: Defines for using and allocating dma channels. - * Written by Hennus Bergman, 1992. - * High DMA channel support & info by Hannu Savolainen - * and John Boyd, Nov. 1992. - * Changes for ppc sound by Christoph Nadig - */ - -#ifdef __KERNEL__ - -#include -#include -#include -#include - -/* - * Note: Adapted for PowerPC by Gary Thomas - * Modified by Cort Dougan - * - * None of this really applies for Power Macintoshes. There is - * basically just enough here to get kernel/dma.c to compile. - * - * There may be some comments or restrictions made here which are - * not valid for the PReP platform. Take what you read - * with a grain of salt. - */ - -#ifndef _ASM_DMA_H -#define _ASM_DMA_H - -#ifndef MAX_DMA_CHANNELS -#define MAX_DMA_CHANNELS 8 -#endif - -/* The maximum address that we can perform a DMA transfer to on this platform */ -/* Doesn't really apply... */ -#define MAX_DMA_ADDRESS 0xFFFFFFFF - -/* in arch/ppc/kernel/setup.c -- Cort */ -extern unsigned long DMA_MODE_WRITE, DMA_MODE_READ; -extern unsigned long ISA_DMA_THRESHOLD; - -#ifdef HAVE_REALLY_SLOW_DMA_CONTROLLER -#define dma_outb outb_p -#else -#define dma_outb outb -#endif - -#define dma_inb inb - -/* - * NOTES about DMA transfers: - * - * controller 1: channels 0-3, byte operations, ports 00-1F - * controller 2: channels 4-7, word operations, ports C0-DF - * - * - ALL registers are 8 bits only, regardless of transfer size - * - channel 4 is not used - cascades 1 into 2. - * - channels 0-3 are byte - addresses/counts are for physical bytes - * - channels 5-7 are word - addresses/counts are for physical words - * - transfers must not cross physical 64K (0-3) or 128K (5-7) boundaries - * - transfer count loaded to registers is 1 less than actual count - * - controller 2 offsets are all even (2x offsets for controller 1) - * - page registers for 5-7 don't use data bit 0, represent 128K pages - * - page registers for 0-3 use bit 0, represent 64K pages - * - * On PReP, DMA transfers are limited to the lower 16MB of _physical_ memory. - * On CHRP, the W83C553F (and VLSI Tollgate?) support full 32 bit addressing. - * Note that addresses loaded into registers must be _physical_ addresses, - * not logical addresses (which may differ if paging is active). - * - * Address mapping for channels 0-3: - * - * A23 ... A16 A15 ... A8 A7 ... A0 (Physical addresses) - * | ... | | ... | | ... | - * | ... | | ... | | ... | - * | ... | | ... | | ... | - * P7 ... P0 A7 ... A0 A7 ... A0 - * | Page | Addr MSB | Addr LSB | (DMA registers) - * - * Address mapping for channels 5-7: - * - * A23 ... A17 A16 A15 ... A9 A8 A7 ... A1 A0 (Physical addresses) - * | ... | \ \ ... \ \ \ ... \ \ - * | ... | \ \ ... \ \ \ ... \ (not used) - * | ... | \ \ ... \ \ \ ... \ - * P7 ... P1 (0) A7 A6 ... A0 A7 A6 ... A0 - * | Page | Addr MSB | Addr LSB | (DMA registers) - * - * Again, channels 5-7 transfer _physical_ words (16 bits), so addresses - * and counts _must_ be word-aligned (the lowest address bit is _ignored_ at - * the hardware level, so odd-byte transfers aren't possible). - * - * Transfer count (_not # bytes_) is limited to 64K, represented as actual - * count - 1 : 64K => 0xFFFF, 1 => 0x0000. Thus, count is always 1 or more, - * and up to 128K bytes may be transferred on channels 5-7 in one operation. - * - */ - -/* see prep_setup_arch() for detailed informations */ -#if defined(CONFIG_SOUND_CS4232) && defined(CONFIG_PPC_PREP) -extern long ppc_cs4232_dma, ppc_cs4232_dma2; -#define SND_DMA1 ppc_cs4232_dma -#define SND_DMA2 ppc_cs4232_dma2 -#else -#define SND_DMA1 -1 -#define SND_DMA2 -1 -#endif - -/* 8237 DMA controllers */ -#define IO_DMA1_BASE 0x00 /* 8 bit slave DMA, channels 0..3 */ -#define IO_DMA2_BASE 0xC0 /* 16 bit master DMA, ch 4(=slave input)..7 */ - -/* DMA controller registers */ -#define DMA1_CMD_REG 0x08 /* command register (w) */ -#define DMA1_STAT_REG 0x08 /* status register (r) */ -#define DMA1_REQ_REG 0x09 /* request register (w) */ -#define DMA1_MASK_REG 0x0A /* single-channel mask (w) */ -#define DMA1_MODE_REG 0x0B /* mode register (w) */ -#define DMA1_CLEAR_FF_REG 0x0C /* clear pointer flip-flop (w) */ -#define DMA1_TEMP_REG 0x0D /* Temporary Register (r) */ -#define DMA1_RESET_REG 0x0D /* Master Clear (w) */ -#define DMA1_CLR_MASK_REG 0x0E /* Clear Mask */ -#define DMA1_MASK_ALL_REG 0x0F /* all-channels mask (w) */ - -#define DMA2_CMD_REG 0xD0 /* command register (w) */ -#define DMA2_STAT_REG 0xD0 /* status register (r) */ -#define DMA2_REQ_REG 0xD2 /* request register (w) */ -#define DMA2_MASK_REG 0xD4 /* single-channel mask (w) */ -#define DMA2_MODE_REG 0xD6 /* mode register (w) */ -#define DMA2_CLEAR_FF_REG 0xD8 /* clear pointer flip-flop (w) */ -#define DMA2_TEMP_REG 0xDA /* Temporary Register (r) */ -#define DMA2_RESET_REG 0xDA /* Master Clear (w) */ -#define DMA2_CLR_MASK_REG 0xDC /* Clear Mask */ -#define DMA2_MASK_ALL_REG 0xDE /* all-channels mask (w) */ - -#define DMA_ADDR_0 0x00 /* DMA address registers */ -#define DMA_ADDR_1 0x02 -#define DMA_ADDR_2 0x04 -#define DMA_ADDR_3 0x06 -#define DMA_ADDR_4 0xC0 -#define DMA_ADDR_5 0xC4 -#define DMA_ADDR_6 0xC8 -#define DMA_ADDR_7 0xCC - -#define DMA_CNT_0 0x01 /* DMA count registers */ -#define DMA_CNT_1 0x03 -#define DMA_CNT_2 0x05 -#define DMA_CNT_3 0x07 -#define DMA_CNT_4 0xC2 -#define DMA_CNT_5 0xC6 -#define DMA_CNT_6 0xCA -#define DMA_CNT_7 0xCE - -#define DMA_LO_PAGE_0 0x87 /* DMA page registers */ -#define DMA_LO_PAGE_1 0x83 -#define DMA_LO_PAGE_2 0x81 -#define DMA_LO_PAGE_3 0x82 -#define DMA_LO_PAGE_5 0x8B -#define DMA_LO_PAGE_6 0x89 -#define DMA_LO_PAGE_7 0x8A - -#define DMA_HI_PAGE_0 0x487 /* DMA page registers */ -#define DMA_HI_PAGE_1 0x483 -#define DMA_HI_PAGE_2 0x481 -#define DMA_HI_PAGE_3 0x482 -#define DMA_HI_PAGE_5 0x48B -#define DMA_HI_PAGE_6 0x489 -#define DMA_HI_PAGE_7 0x48A - -#define DMA1_EXT_REG 0x40B -#define DMA2_EXT_REG 0x4D6 - -#define DMA_MODE_CASCADE 0xC0 /* pass thru DREQ->HRQ, DACK<-HLDA only */ -#define DMA_AUTOINIT 0x10 - -extern spinlock_t dma_spin_lock; - -static __inline__ unsigned long claim_dma_lock(void) -{ - unsigned long flags; - spin_lock_irqsave(&dma_spin_lock, flags); - return flags; -} - -static __inline__ void release_dma_lock(unsigned long flags) -{ - spin_unlock_irqrestore(&dma_spin_lock, flags); -} - -/* enable/disable a specific DMA channel */ -static __inline__ void enable_dma(unsigned int dmanr) -{ - unsigned char ucDmaCmd = 0x00; - - if (dmanr != 4) { - dma_outb(0, DMA2_MASK_REG); /* This may not be enabled */ - dma_outb(ucDmaCmd, DMA2_CMD_REG); /* Enable group */ - } - if (dmanr <= 3) { - dma_outb(dmanr, DMA1_MASK_REG); - dma_outb(ucDmaCmd, DMA1_CMD_REG); /* Enable group */ - } else - dma_outb(dmanr & 3, DMA2_MASK_REG); -} - -static __inline__ void disable_dma(unsigned int dmanr) -{ - if (dmanr <= 3) - dma_outb(dmanr | 4, DMA1_MASK_REG); - else - dma_outb((dmanr & 3) | 4, DMA2_MASK_REG); -} - -/* Clear the 'DMA Pointer Flip Flop'. - * Write 0 for LSB/MSB, 1 for MSB/LSB access. - * Use this once to initialize the FF to a known state. - * After that, keep track of it. :-) - * --- In order to do that, the DMA routines below should --- - * --- only be used while interrupts are disabled! --- - */ -static __inline__ void clear_dma_ff(unsigned int dmanr) -{ - if (dmanr <= 3) - dma_outb(0, DMA1_CLEAR_FF_REG); - else - dma_outb(0, DMA2_CLEAR_FF_REG); -} - -/* set mode (above) for a specific DMA channel */ -static __inline__ void set_dma_mode(unsigned int dmanr, char mode) -{ - if (dmanr <= 3) - dma_outb(mode | dmanr, DMA1_MODE_REG); - else - dma_outb(mode | (dmanr & 3), DMA2_MODE_REG); -} - -/* Set only the page register bits of the transfer address. - * This is used for successive transfers when we know the contents of - * the lower 16 bits of the DMA current address register, but a 64k boundary - * may have been crossed. - */ -static __inline__ void set_dma_page(unsigned int dmanr, int pagenr) -{ - switch (dmanr) { - case 0: - dma_outb(pagenr, DMA_LO_PAGE_0); - dma_outb(pagenr >> 8, DMA_HI_PAGE_0); - break; - case 1: - dma_outb(pagenr, DMA_LO_PAGE_1); - dma_outb(pagenr >> 8, DMA_HI_PAGE_1); - break; - case 2: - dma_outb(pagenr, DMA_LO_PAGE_2); - dma_outb(pagenr >> 8, DMA_HI_PAGE_2); - break; - case 3: - dma_outb(pagenr, DMA_LO_PAGE_3); - dma_outb(pagenr >> 8, DMA_HI_PAGE_3); - break; - case 5: - if (SND_DMA1 == 5 || SND_DMA2 == 5) - dma_outb(pagenr, DMA_LO_PAGE_5); - else - dma_outb(pagenr & 0xfe, DMA_LO_PAGE_5); - dma_outb(pagenr >> 8, DMA_HI_PAGE_5); - break; - case 6: - if (SND_DMA1 == 6 || SND_DMA2 == 6) - dma_outb(pagenr, DMA_LO_PAGE_6); - else - dma_outb(pagenr & 0xfe, DMA_LO_PAGE_6); - dma_outb(pagenr >> 8, DMA_HI_PAGE_6); - break; - case 7: - if (SND_DMA1 == 7 || SND_DMA2 == 7) - dma_outb(pagenr, DMA_LO_PAGE_7); - else - dma_outb(pagenr & 0xfe, DMA_LO_PAGE_7); - dma_outb(pagenr >> 8, DMA_HI_PAGE_7); - break; - } -} - -/* Set transfer address & page bits for specific DMA channel. - * Assumes dma flipflop is clear. - */ -static __inline__ void set_dma_addr(unsigned int dmanr, unsigned int phys) -{ - if (dmanr <= 3) { - dma_outb(phys & 0xff, ((dmanr & 3) << 1) + IO_DMA1_BASE); - dma_outb((phys >> 8) & 0xff, ((dmanr & 3) << 1) + IO_DMA1_BASE); - } else if (dmanr == SND_DMA1 || dmanr == SND_DMA2) { - dma_outb(phys & 0xff, ((dmanr & 3) << 2) + IO_DMA2_BASE); - dma_outb((phys >> 8) & 0xff, ((dmanr & 3) << 2) + IO_DMA2_BASE); - dma_outb((dmanr & 3), DMA2_EXT_REG); - } else { - dma_outb((phys >> 1) & 0xff, ((dmanr & 3) << 2) + IO_DMA2_BASE); - dma_outb((phys >> 9) & 0xff, ((dmanr & 3) << 2) + IO_DMA2_BASE); - } - set_dma_page(dmanr, phys >> 16); -} - -/* Set transfer size (max 64k for DMA1..3, 128k for DMA5..7) for - * a specific DMA channel. - * You must ensure the parameters are valid. - * NOTE: from a manual: "the number of transfers is one more - * than the initial word count"! This is taken into account. - * Assumes dma flip-flop is clear. - * NOTE 2: "count" represents _bytes_ and must be even for channels 5-7. - */ -static __inline__ void set_dma_count(unsigned int dmanr, unsigned int count) -{ - count--; - if (dmanr <= 3) { - dma_outb(count & 0xff, ((dmanr & 3) << 1) + 1 + IO_DMA1_BASE); - dma_outb((count >> 8) & 0xff, ((dmanr & 3) << 1) + 1 + - IO_DMA1_BASE); - } else if (dmanr == SND_DMA1 || dmanr == SND_DMA2) { - dma_outb(count & 0xff, ((dmanr & 3) << 2) + 2 + IO_DMA2_BASE); - dma_outb((count >> 8) & 0xff, ((dmanr & 3) << 2) + 2 + - IO_DMA2_BASE); - } else { - dma_outb((count >> 1) & 0xff, ((dmanr & 3) << 2) + 2 + - IO_DMA2_BASE); - dma_outb((count >> 9) & 0xff, ((dmanr & 3) << 2) + 2 + - IO_DMA2_BASE); - } -} - -/* Get DMA residue count. After a DMA transfer, this - * should return zero. Reading this while a DMA transfer is - * still in progress will return unpredictable results. - * If called before the channel has been used, it may return 1. - * Otherwise, it returns the number of _bytes_ left to transfer. - * - * Assumes DMA flip-flop is clear. - */ -static __inline__ int get_dma_residue(unsigned int dmanr) -{ - unsigned int io_port = (dmanr <= 3) ? - ((dmanr & 3) << 1) + 1 + IO_DMA1_BASE - : ((dmanr & 3) << 2) + 2 + IO_DMA2_BASE; - - /* using short to get 16-bit wrap around */ - unsigned short count; - - count = 1 + dma_inb(io_port); - count += dma_inb(io_port) << 8; - - return (dmanr <= 3 || dmanr == SND_DMA1 || dmanr == SND_DMA2) - ? count : (count << 1); - -} - -/* These are in kernel/dma.c: */ - -/* reserve a DMA channel */ -extern int request_dma(unsigned int dmanr, const char *device_id); -/* release it again */ -extern void free_dma(unsigned int dmanr); - -#ifdef CONFIG_PCI -extern int isa_dma_bridge_buggy; -#else -#define isa_dma_bridge_buggy (0) -#endif -#endif /* _ASM_DMA_H */ -#endif /* __KERNEL__ */ diff --git a/include/asm-ppc64/dma.h b/include/asm-ppc64/dma.h deleted file mode 100644 --- a/include/asm-ppc64/dma.h +++ /dev/null @@ -1,329 +0,0 @@ -/* - * linux/include/asm/dma.h: Defines for using and allocating dma channels. - * Written by Hennus Bergman, 1992. - * High DMA channel support & info by Hannu Savolainen - * and John Boyd, Nov. 1992. - * Changes for ppc sound by Christoph Nadig - * - * 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_DMA_H -#define _ASM_DMA_H - -#include -#include -#include -#include - -#ifndef MAX_DMA_CHANNELS -#define MAX_DMA_CHANNELS 8 -#endif - -/* The maximum address that we can perform a DMA transfer to on this platform */ -/* Doesn't really apply... */ -#define MAX_DMA_ADDRESS (~0UL) - -#if !defined(CONFIG_PPC_ISERIES) || defined(CONFIG_PCI) - -#define dma_outb outb -#define dma_inb inb - -/* - * NOTES about DMA transfers: - * - * controller 1: channels 0-3, byte operations, ports 00-1F - * controller 2: channels 4-7, word operations, ports C0-DF - * - * - ALL registers are 8 bits only, regardless of transfer size - * - channel 4 is not used - cascades 1 into 2. - * - channels 0-3 are byte - addresses/counts are for physical bytes - * - channels 5-7 are word - addresses/counts are for physical words - * - transfers must not cross physical 64K (0-3) or 128K (5-7) boundaries - * - transfer count loaded to registers is 1 less than actual count - * - controller 2 offsets are all even (2x offsets for controller 1) - * - page registers for 5-7 don't use data bit 0, represent 128K pages - * - page registers for 0-3 use bit 0, represent 64K pages - * - * On PReP, DMA transfers are limited to the lower 16MB of _physical_ memory. - * On CHRP, the W83C553F (and VLSI Tollgate?) support full 32 bit addressing. - * Note that addresses loaded into registers must be _physical_ addresses, - * not logical addresses (which may differ if paging is active). - * - * Address mapping for channels 0-3: - * - * A23 ... A16 A15 ... A8 A7 ... A0 (Physical addresses) - * | ... | | ... | | ... | - * | ... | | ... | | ... | - * | ... | | ... | | ... | - * P7 ... P0 A7 ... A0 A7 ... A0 - * | Page | Addr MSB | Addr LSB | (DMA registers) - * - * Address mapping for channels 5-7: - * - * A23 ... A17 A16 A15 ... A9 A8 A7 ... A1 A0 (Physical addresses) - * | ... | \ \ ... \ \ \ ... \ \ - * | ... | \ \ ... \ \ \ ... \ (not used) - * | ... | \ \ ... \ \ \ ... \ - * P7 ... P1 (0) A7 A6 ... A0 A7 A6 ... A0 - * | Page | Addr MSB | Addr LSB | (DMA registers) - * - * Again, channels 5-7 transfer _physical_ words (16 bits), so addresses - * and counts _must_ be word-aligned (the lowest address bit is _ignored_ at - * the hardware level, so odd-byte transfers aren't possible). - * - * Transfer count (_not # bytes_) is limited to 64K, represented as actual - * count - 1 : 64K => 0xFFFF, 1 => 0x0000. Thus, count is always 1 or more, - * and up to 128K bytes may be transferred on channels 5-7 in one operation. - * - */ - -/* 8237 DMA controllers */ -#define IO_DMA1_BASE 0x00 /* 8 bit slave DMA, channels 0..3 */ -#define IO_DMA2_BASE 0xC0 /* 16 bit master DMA, ch 4(=slave input)..7 */ - -/* DMA controller registers */ -#define DMA1_CMD_REG 0x08 /* command register (w) */ -#define DMA1_STAT_REG 0x08 /* status register (r) */ -#define DMA1_REQ_REG 0x09 /* request register (w) */ -#define DMA1_MASK_REG 0x0A /* single-channel mask (w) */ -#define DMA1_MODE_REG 0x0B /* mode register (w) */ -#define DMA1_CLEAR_FF_REG 0x0C /* clear pointer flip-flop (w) */ -#define DMA1_TEMP_REG 0x0D /* Temporary Register (r) */ -#define DMA1_RESET_REG 0x0D /* Master Clear (w) */ -#define DMA1_CLR_MASK_REG 0x0E /* Clear Mask */ -#define DMA1_MASK_ALL_REG 0x0F /* all-channels mask (w) */ - -#define DMA2_CMD_REG 0xD0 /* command register (w) */ -#define DMA2_STAT_REG 0xD0 /* status register (r) */ -#define DMA2_REQ_REG 0xD2 /* request register (w) */ -#define DMA2_MASK_REG 0xD4 /* single-channel mask (w) */ -#define DMA2_MODE_REG 0xD6 /* mode register (w) */ -#define DMA2_CLEAR_FF_REG 0xD8 /* clear pointer flip-flop (w) */ -#define DMA2_TEMP_REG 0xDA /* Temporary Register (r) */ -#define DMA2_RESET_REG 0xDA /* Master Clear (w) */ -#define DMA2_CLR_MASK_REG 0xDC /* Clear Mask */ -#define DMA2_MASK_ALL_REG 0xDE /* all-channels mask (w) */ - -#define DMA_ADDR_0 0x00 /* DMA address registers */ -#define DMA_ADDR_1 0x02 -#define DMA_ADDR_2 0x04 -#define DMA_ADDR_3 0x06 -#define DMA_ADDR_4 0xC0 -#define DMA_ADDR_5 0xC4 -#define DMA_ADDR_6 0xC8 -#define DMA_ADDR_7 0xCC - -#define DMA_CNT_0 0x01 /* DMA count registers */ -#define DMA_CNT_1 0x03 -#define DMA_CNT_2 0x05 -#define DMA_CNT_3 0x07 -#define DMA_CNT_4 0xC2 -#define DMA_CNT_5 0xC6 -#define DMA_CNT_6 0xCA -#define DMA_CNT_7 0xCE - -#define DMA_LO_PAGE_0 0x87 /* DMA page registers */ -#define DMA_LO_PAGE_1 0x83 -#define DMA_LO_PAGE_2 0x81 -#define DMA_LO_PAGE_3 0x82 -#define DMA_LO_PAGE_5 0x8B -#define DMA_LO_PAGE_6 0x89 -#define DMA_LO_PAGE_7 0x8A - -#define DMA_HI_PAGE_0 0x487 /* DMA page registers */ -#define DMA_HI_PAGE_1 0x483 -#define DMA_HI_PAGE_2 0x481 -#define DMA_HI_PAGE_3 0x482 -#define DMA_HI_PAGE_5 0x48B -#define DMA_HI_PAGE_6 0x489 -#define DMA_HI_PAGE_7 0x48A - -#define DMA1_EXT_REG 0x40B -#define DMA2_EXT_REG 0x4D6 - -#define DMA_MODE_READ 0x44 /* I/O to memory, no autoinit, increment, single mode */ -#define DMA_MODE_WRITE 0x48 /* memory to I/O, no autoinit, increment, single mode */ -#define DMA_MODE_CASCADE 0xC0 /* pass thru DREQ->HRQ, DACK<-HLDA only */ - -#define DMA_AUTOINIT 0x10 - -extern spinlock_t dma_spin_lock; - -static __inline__ unsigned long claim_dma_lock(void) -{ - unsigned long flags; - spin_lock_irqsave(&dma_spin_lock, flags); - return flags; -} - -static __inline__ void release_dma_lock(unsigned long flags) -{ - spin_unlock_irqrestore(&dma_spin_lock, flags); -} - -/* enable/disable a specific DMA channel */ -static __inline__ void enable_dma(unsigned int dmanr) -{ - unsigned char ucDmaCmd=0x00; - - if (dmanr != 4) - { - dma_outb(0, DMA2_MASK_REG); /* This may not be enabled */ - dma_outb(ucDmaCmd, DMA2_CMD_REG); /* Enable group */ - } - if (dmanr<=3) - { - dma_outb(dmanr, DMA1_MASK_REG); - dma_outb(ucDmaCmd, DMA1_CMD_REG); /* Enable group */ - } else - { - dma_outb(dmanr & 3, DMA2_MASK_REG); - } -} - -static __inline__ void disable_dma(unsigned int dmanr) -{ - if (dmanr<=3) - dma_outb(dmanr | 4, DMA1_MASK_REG); - else - dma_outb((dmanr & 3) | 4, DMA2_MASK_REG); -} - -/* Clear the 'DMA Pointer Flip Flop'. - * Write 0 for LSB/MSB, 1 for MSB/LSB access. - * Use this once to initialize the FF to a known state. - * After that, keep track of it. :-) - * --- In order to do that, the DMA routines below should --- - * --- only be used while interrupts are disabled! --- - */ -static __inline__ void clear_dma_ff(unsigned int dmanr) -{ - if (dmanr<=3) - dma_outb(0, DMA1_CLEAR_FF_REG); - else - dma_outb(0, DMA2_CLEAR_FF_REG); -} - -/* set mode (above) for a specific DMA channel */ -static __inline__ void set_dma_mode(unsigned int dmanr, char mode) -{ - if (dmanr<=3) - dma_outb(mode | dmanr, DMA1_MODE_REG); - else - dma_outb(mode | (dmanr&3), DMA2_MODE_REG); -} - -/* Set only the page register bits of the transfer address. - * This is used for successive transfers when we know the contents of - * the lower 16 bits of the DMA current address register, but a 64k boundary - * may have been crossed. - */ -static __inline__ void set_dma_page(unsigned int dmanr, int pagenr) -{ - switch(dmanr) { - case 0: - dma_outb(pagenr, DMA_LO_PAGE_0); - dma_outb(pagenr>>8, DMA_HI_PAGE_0); - break; - case 1: - dma_outb(pagenr, DMA_LO_PAGE_1); - dma_outb(pagenr>>8, DMA_HI_PAGE_1); - break; - case 2: - dma_outb(pagenr, DMA_LO_PAGE_2); - dma_outb(pagenr>>8, DMA_HI_PAGE_2); - break; - case 3: - dma_outb(pagenr, DMA_LO_PAGE_3); - dma_outb(pagenr>>8, DMA_HI_PAGE_3); - break; - case 5: - dma_outb(pagenr & 0xfe, DMA_LO_PAGE_5); - dma_outb(pagenr>>8, DMA_HI_PAGE_5); - break; - case 6: - dma_outb(pagenr & 0xfe, DMA_LO_PAGE_6); - dma_outb(pagenr>>8, DMA_HI_PAGE_6); - break; - case 7: - dma_outb(pagenr & 0xfe, DMA_LO_PAGE_7); - dma_outb(pagenr>>8, DMA_HI_PAGE_7); - break; - } -} - - -/* Set transfer address & page bits for specific DMA channel. - * Assumes dma flipflop is clear. - */ -static __inline__ void set_dma_addr(unsigned int dmanr, unsigned int phys) -{ - if (dmanr <= 3) { - dma_outb( phys & 0xff, ((dmanr&3)<<1) + IO_DMA1_BASE ); - dma_outb( (phys>>8) & 0xff, ((dmanr&3)<<1) + IO_DMA1_BASE ); - } else { - dma_outb( (phys>>1) & 0xff, ((dmanr&3)<<2) + IO_DMA2_BASE ); - dma_outb( (phys>>9) & 0xff, ((dmanr&3)<<2) + IO_DMA2_BASE ); - } - set_dma_page(dmanr, phys>>16); -} - - -/* Set transfer size (max 64k for DMA1..3, 128k for DMA5..7) for - * a specific DMA channel. - * You must ensure the parameters are valid. - * NOTE: from a manual: "the number of transfers is one more - * than the initial word count"! This is taken into account. - * Assumes dma flip-flop is clear. - * NOTE 2: "count" represents _bytes_ and must be even for channels 5-7. - */ -static __inline__ void set_dma_count(unsigned int dmanr, unsigned int count) -{ - count--; - if (dmanr <= 3) { - dma_outb( count & 0xff, ((dmanr&3)<<1) + 1 + IO_DMA1_BASE ); - dma_outb( (count>>8) & 0xff, ((dmanr&3)<<1) + 1 + IO_DMA1_BASE ); - } else { - dma_outb( (count>>1) & 0xff, ((dmanr&3)<<2) + 2 + IO_DMA2_BASE ); - dma_outb( (count>>9) & 0xff, ((dmanr&3)<<2) + 2 + IO_DMA2_BASE ); - } -} - - -/* Get DMA residue count. After a DMA transfer, this - * should return zero. Reading this while a DMA transfer is - * still in progress will return unpredictable results. - * If called before the channel has been used, it may return 1. - * Otherwise, it returns the number of _bytes_ left to transfer. - * - * Assumes DMA flip-flop is clear. - */ -static __inline__ int get_dma_residue(unsigned int dmanr) -{ - unsigned int io_port = (dmanr<=3)? ((dmanr&3)<<1) + 1 + IO_DMA1_BASE - : ((dmanr&3)<<2) + 2 + IO_DMA2_BASE; - - /* using short to get 16-bit wrap around */ - unsigned short count; - - count = 1 + dma_inb(io_port); - count += dma_inb(io_port) << 8; - - return (dmanr <= 3)? count : (count<<1); -} - -/* These are in kernel/dma.c: */ -extern int request_dma(unsigned int dmanr, const char * device_id); /* reserve a DMA channel */ -extern void free_dma(unsigned int dmanr); /* release it again */ - -#ifdef CONFIG_PCI -extern int isa_dma_bridge_buggy; -#else -#define isa_dma_bridge_buggy (0) -#endif -#endif /* !defined(CONFIG_PPC_ISERIES) || defined(CONFIG_PCI) */ -#endif /* _ASM_DMA_H */ From galak at freescale.com Thu Sep 22 05:56:45 2005 From: galak at freescale.com (Kumar Gala) Date: Wed, 21 Sep 2005 14:56:45 -0500 (CDT) Subject: [PATCH] powerpc: need to define __HAVE_ARCH_GATE_AREA for ppc32 Message-ID: The merging of auxvec.h into asm-powerpc introduced the AT_SYSINFO_EHDR into the ppc32 build that is used for VDSO. However, we dont use the gate mechanism for VDSO so we need to define __HAVE_ARCH_GATE_AREA. Signed-off-by: Kumar K. Gala --- commit ed88e411b2af8c41c50953e3138059fce60486f5 tree 32a15cfe1e4d8b4446552b22e42e0c85b85e16b8 parent 23e5b24d486fc63bd38b594c49240ffbac1aa474 author Kumar K. Gala Wed, 21 Sep 2005 14:55:45 -0500 committer Kumar K. Gala Wed, 21 Sep 2005 14:55:45 -0500 include/asm-ppc/page.h | 3 +++ 1 files changed, 3 insertions(+), 0 deletions(-) diff --git a/include/asm-ppc/page.h b/include/asm-ppc/page.h --- a/include/asm-ppc/page.h +++ b/include/asm-ppc/page.h @@ -160,6 +160,9 @@ extern __inline__ int get_order(unsigned return 32 - lz; } +/* We do define AT_SYSINFO_EHDR but don't use the gate mecanism */ +#define __HAVE_ARCH_GATE_AREA 1 + #endif /* __ASSEMBLY__ */ #define VM_DATA_DEFAULT_FLAGS (VM_READ | VM_WRITE | VM_EXEC | \ From kumar.gala at freescale.com Thu Sep 22 06:24:52 2005 From: kumar.gala at freescale.com (Kumar Gala) Date: Wed, 21 Sep 2005 15:24:52 -0500 Subject: [PATCH] powerpc: need to define __HAVE_ARCH_GATE_AREA for ppc32 In-Reply-To: References: Message-ID: <6319B3E6-B6F7-4730-8B21-9F3F0144767A@freescale.com> Well, this doesn't actually solve the problem since get_gate_vma and a few other things aren't actually defined yet in ppc32 land (damn the lack of VDSO). I'll send a proper patch that truly fixes ppc32 land. - kumar On Sep 21, 2005, at 2:56 PM, Gala Kumar K.-galak wrote: > The merging of auxvec.h into asm-powerpc introduced the > AT_SYSINFO_EHDR > into the ppc32 build that is used for VDSO. However, we dont use the > gate mechanism for VDSO so we need to define __HAVE_ARCH_GATE_AREA. > > Signed-off-by: Kumar K. Gala > > --- > commit ed88e411b2af8c41c50953e3138059fce60486f5 > tree 32a15cfe1e4d8b4446552b22e42e0c85b85e16b8 > parent 23e5b24d486fc63bd38b594c49240ffbac1aa474 > author Kumar K. Gala Wed, 21 Sep 2005 > 14:55:45 -0500 > committer Kumar K. Gala Wed, 21 Sep 2005 > 14:55:45 -0500 > > include/asm-ppc/page.h | 3 +++ > 1 files changed, 3 insertions(+), 0 deletions(-) > > diff --git a/include/asm-ppc/page.h b/include/asm-ppc/page.h > --- a/include/asm-ppc/page.h > +++ b/include/asm-ppc/page.h > @@ -160,6 +160,9 @@ extern __inline__ int get_order(unsigned > return 32 - lz; > } > > +/* We do define AT_SYSINFO_EHDR but don't use the gate mecanism */ > +#define __HAVE_ARCH_GATE_AREA 1 > + > #endif /* __ASSEMBLY__ */ > > #define VM_DATA_DEFAULT_FLAGS (VM_READ | VM_WRITE | VM_EXEC | \ > _______________________________________________ > Linuxppc-dev mailing list > Linuxppc-dev at ozlabs.org > https://ozlabs.org/mailman/listinfo/linuxppc-dev > From galak at freescale.com Thu Sep 22 06:44:11 2005 From: galak at freescale.com (Kumar Gala) Date: Wed, 21 Sep 2005 15:44:11 -0500 (CDT) Subject: [PATCH] powerpc: Fix compiling of ppc32 Message-ID: The merging of auxvec.h into asm-powerpc introduced the AT_SYSINFO_EHDR into the ppc32 build that is used for VDSO. However, we dont have VDSO support in the ppc32 tree at this time. Introducing this define causes a number of other things to get built with the assumption of VDSO, thus causing the compile errors for ppc32. Until we have VDSO on ppc32 we will leave AT_SYSINFO_EHDR a ppc64 only define. Signed-off-by: Kumar K. Gala --- commit 8be656b5000421a25f147e712bb19417bf677c2f tree a1ab3f3319f90b3ff8bfc4e0e12894c104a06531 parent fe759f4a2175afef92c603fe410aaf9785eb4c93 author Kumar K. Gala Wed, 21 Sep 2005 15:32:33 -0500 committer Kumar K. Gala Wed, 21 Sep 2005 15:32:33 -0500 include/asm-powerpc/auxvec.h | 2 ++ 1 files changed, 2 insertions(+), 0 deletions(-) diff --git a/include/asm-powerpc/auxvec.h b/include/asm-powerpc/auxvec.h --- a/include/asm-powerpc/auxvec.h +++ b/include/asm-powerpc/auxvec.h @@ -14,6 +14,8 @@ /* The vDSO location. We have to use the same value as x86 for glibc's * sake :-) */ +#ifdef __powerpc64__ #define AT_SYSINFO_EHDR 33 +#endif #endif From galak at freescale.com Thu Sep 22 07:52:55 2005 From: galak at freescale.com (Kumar Gala) Date: Wed, 21 Sep 2005 16:52:55 -0500 (CDT) Subject: [PATCH] powerpc: merged hw_irq.h Message-ID: Merged hw_irq.h between ppc32 & ppc64. Added support to use the Book-E wrtee[i] instructions that allow modifying MSR[EE] atomically. Additionally, added get_irq_desc() macros to ppc32 to allow mask_irq(), unmask_irq(), and ack_irq() to be common between ppc32 & ppc64. Note: because 64-bit Book-E implementations only have a 32-bit MSR the macro's for Book-E need to come before the PPC64 macro's to ensure the right thing happends for 64-bit Book-E processors. Signed-off-by: Kumar Gala --- commit 1da20f52e226c6d437107d03ff4b65b2006a0b38 tree ad911d369a3c7279ba82bb750287cff39b554474 parent 8be656b5000421a25f147e712bb19417bf677c2f author Kumar K. Gala Wed, 21 Sep 2005 16:39:21 -0500 committer Kumar K. Gala Wed, 21 Sep 2005 16:39:21 -0500 include/asm-powerpc/hw_irq.h | 115 ++++++++++++++++++++++++++++++++++++++++++ include/asm-ppc/hw_irq.h | 59 ---------------------- include/asm-ppc/irq.h | 6 ++ include/asm-ppc64/hw_irq.h | 104 -------------------------------------- 4 files changed, 121 insertions(+), 163 deletions(-) diff --git a/include/asm-powerpc/hw_irq.h b/include/asm-powerpc/hw_irq.h new file mode 100644 --- /dev/null +++ b/include/asm-powerpc/hw_irq.h @@ -0,0 +1,115 @@ +/* + * Copyright (C) 1999 Cort Dougan + */ +#ifndef _ASM_POWERPC_HW_IRQ_H +#define _ASM_POWERPC_HW_IRQ_H + +#ifdef __KERNEL__ + +#include +#include +#include +#include +#include + +extern void timer_interrupt(struct pt_regs *); +extern void ppc_irq_dispatch_handler(struct pt_regs *regs, int irq); + +#ifdef CONFIG_PPC_ISERIES + +extern unsigned long local_get_flags(void); +extern unsigned long local_irq_disable(void); +extern void local_irq_restore(unsigned long); + +#define local_irq_enable() local_irq_restore(1) +#define local_save_flags(flags) ((flags) = local_get_flags()) +#define local_irq_save(flags) ((flags) = local_irq_disable()) + +#define irqs_disabled() (local_get_flags() == 0) + +#else + +#if defined(CONFIG_BOOKE) +#define SET_MSR_EE(x) mtmsr(x) +#define local_irq_restore(flags) __asm__ __volatile__("wrtee %0" : : "r" (flags) : "memory") +#elif defined(__powerpc64__) +#define SET_MSR_EE(x) __mtmsrd(x, 1) +#define local_irq_restore(flags) do { \ + __asm__ __volatile__("": : :"memory"); \ + __mtmsrd((flags), 1); \ +} while(0) +#else +#define SET_MSR_EE(x) mtmsr(x) +#define local_irq_restore(flags) mtmsr(flags) +#endif + +static inline void local_irq_disable(void) +{ +#ifdef CONFIG_BOOKE + __asm__ __volatile__("wrteei 0": : :"memory"); +#else + unsigned long msr; + __asm__ __volatile__("": : :"memory"); + msr = mfmsr(); + SET_MSR_EE(msr & ~MSR_EE); +#endif +} + +static inline void local_irq_enable(void) +{ +#ifdef CONFIG_BOOKE + __asm__ __volatile__("wrteei 1": : :"memory"); +#else + unsigned long msr; + __asm__ __volatile__("": : :"memory"); + msr = mfmsr(); + SET_MSR_EE(msr | MSR_EE); +#endif +} + +static inline void local_irq_save_ptr(unsigned long *flags) +{ + unsigned long msr; + msr = mfmsr(); + *flags = msr; +#ifdef CONFIG_BOOKE + __asm__ __volatile__("wrteei 0": : :"memory"); +#else + SET_MSR_EE(msr & ~MSR_EE); +#endif + __asm__ __volatile__("": : :"memory"); +} + +#define local_save_flags(flags) ((flags) = mfmsr()) +#define local_irq_save(flags) local_irq_save_ptr(&flags) +#define irqs_disabled() ((mfmsr() & MSR_EE) == 0) + +#endif /* CONFIG_PPC_ISERIES */ + +#define mask_irq(irq) \ + ({ \ + irq_desc_t *desc = get_irq_desc(irq); \ + if (desc->handler && desc->handler->disable) \ + desc->handler->disable(irq); \ + }) +#define unmask_irq(irq) \ + ({ \ + irq_desc_t *desc = get_irq_desc(irq); \ + if (desc->handler && desc->handler->enable) \ + desc->handler->enable(irq); \ + }) +#define ack_irq(irq) \ + ({ \ + irq_desc_t *desc = get_irq_desc(irq); \ + if (desc->handler && desc->handler->ack) \ + desc->handler->ack(irq); \ + }) + +/* Should we handle this via lost interrupts and IPIs or should we don't care like + * we do now ? --BenH. + */ +struct hw_interrupt_type; +static inline void hw_resend_irq(struct hw_interrupt_type *h, unsigned int i) {} + +#endif /* __KERNEL__ */ +#endif /* _ASM_POWERPC_HW_IRQ_H */ diff --git a/include/asm-ppc/hw_irq.h b/include/asm-ppc/hw_irq.h deleted file mode 100644 --- a/include/asm-ppc/hw_irq.h +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright (C) 1999 Cort Dougan - */ -#ifdef __KERNEL__ -#ifndef _PPC_HW_IRQ_H -#define _PPC_HW_IRQ_H - -#include -#include -#include - -extern void timer_interrupt(struct pt_regs *); - -#define irqs_disabled() ((mfmsr() & MSR_EE) == 0) - -static inline void local_irq_disable(void) -{ - unsigned long msr; - msr = mfmsr(); - mtmsr(msr & ~MSR_EE); - __asm__ __volatile__("": : :"memory"); -} - -static inline void local_irq_enable(void) -{ - unsigned long msr; - __asm__ __volatile__("": : :"memory"); - msr = mfmsr(); - mtmsr(msr | MSR_EE); -} - -static inline void local_irq_save_ptr(unsigned long *flags) -{ - unsigned long msr; - msr = mfmsr(); - *flags = msr; - mtmsr(msr & ~MSR_EE); - __asm__ __volatile__("": : :"memory"); -} - -#define local_save_flags(flags) ((flags) = mfmsr()) -#define local_irq_save(flags) local_irq_save_ptr(&flags) -#define local_irq_restore(flags) mtmsr(flags) - -extern void do_lost_interrupts(unsigned long); - -#define mask_irq(irq) ({if (irq_desc[irq].handler && irq_desc[irq].handler->disable) irq_desc[irq].handler->disable(irq);}) -#define unmask_irq(irq) ({if (irq_desc[irq].handler && irq_desc[irq].handler->enable) irq_desc[irq].handler->enable(irq);}) -#define ack_irq(irq) ({if (irq_desc[irq].handler && irq_desc[irq].handler->ack) irq_desc[irq].handler->ack(irq);}) - -/* Should we handle this via lost interrupts and IPIs or should we don't care like - * we do now ? --BenH. - */ -struct hw_interrupt_type; -static inline void hw_resend_irq(struct hw_interrupt_type *h, unsigned int i) {} - - -#endif /* _PPC_HW_IRQ_H */ -#endif /* __KERNEL__ */ diff --git a/include/asm-ppc/irq.h b/include/asm-ppc/irq.h --- a/include/asm-ppc/irq.h +++ b/include/asm-ppc/irq.h @@ -24,6 +24,12 @@ */ #define ARCH_HAS_IRQ_PER_CPU +#define get_irq_desc(irq) (&irq_desc[(irq)]) + +/* Define a way to iterate across irqs. */ +#define for_each_irq(i) \ + for ((i) = 0; (i) < NR_IRQS; ++(i)) + #if defined(CONFIG_40x) #include diff --git a/include/asm-ppc64/hw_irq.h b/include/asm-ppc64/hw_irq.h deleted file mode 100644 --- a/include/asm-ppc64/hw_irq.h +++ /dev/null @@ -1,104 +0,0 @@ -/* - * Copyright (C) 1999 Cort Dougan - * - * Use inline IRQs where possible - Anton Blanchard - * - * 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__ -#ifndef _PPC64_HW_IRQ_H -#define _PPC64_HW_IRQ_H - -#include -#include -#include - -extern void timer_interrupt(struct pt_regs *); -extern void ppc_irq_dispatch_handler(struct pt_regs *regs, int irq); - -#ifdef CONFIG_PPC_ISERIES - -extern unsigned long local_get_flags(void); -extern unsigned long local_irq_disable(void); -extern void local_irq_restore(unsigned long); - -#define local_irq_enable() local_irq_restore(1) -#define local_save_flags(flags) ((flags) = local_get_flags()) -#define local_irq_save(flags) ((flags) = local_irq_disable()) - -#define irqs_disabled() (local_get_flags() == 0) - -#else - -#define local_save_flags(flags) ((flags) = mfmsr()) -#define local_irq_restore(flags) do { \ - __asm__ __volatile__("": : :"memory"); \ - __mtmsrd((flags), 1); \ -} while(0) - -static inline void local_irq_disable(void) -{ - unsigned long msr; - msr = mfmsr(); - __mtmsrd(msr & ~MSR_EE, 1); - __asm__ __volatile__("": : :"memory"); -} - -static inline void local_irq_enable(void) -{ - unsigned long msr; - __asm__ __volatile__("": : :"memory"); - msr = mfmsr(); - __mtmsrd(msr | MSR_EE, 1); -} - -static inline void __do_save_and_cli(unsigned long *flags) -{ - unsigned long msr; - msr = mfmsr(); - *flags = msr; - __mtmsrd(msr & ~MSR_EE, 1); - __asm__ __volatile__("": : :"memory"); -} - -#define local_irq_save(flags) __do_save_and_cli(&flags) - -#define irqs_disabled() \ -({ \ - unsigned long flags; \ - local_save_flags(flags); \ - !(flags & MSR_EE); \ -}) - -#endif /* CONFIG_PPC_ISERIES */ - -#define mask_irq(irq) \ - ({ \ - irq_desc_t *desc = get_irq_desc(irq); \ - if (desc->handler && desc->handler->disable) \ - desc->handler->disable(irq); \ - }) -#define unmask_irq(irq) \ - ({ \ - irq_desc_t *desc = get_irq_desc(irq); \ - if (desc->handler && desc->handler->enable) \ - desc->handler->enable(irq); \ - }) -#define ack_irq(irq) \ - ({ \ - irq_desc_t *desc = get_irq_desc(irq); \ - if (desc->handler && desc->handler->ack) \ - desc->handler->ack(irq); \ - }) - -/* Should we handle this via lost interrupts and IPIs or should we don't care like - * we do now ? --BenH. - */ -struct hw_interrupt_type; -static inline void hw_resend_irq(struct hw_interrupt_type *h, unsigned int i) {} - -#endif /* _PPC64_HW_IRQ_H */ -#endif /* __KERNEL__ */ From benh at kernel.crashing.org Thu Sep 22 09:27:57 2005 From: benh at kernel.crashing.org (Benjamin Herrenschmidt) Date: Thu, 22 Sep 2005 09:27:57 +1000 Subject: Hugetlb HPTE hashing weirdness In-Reply-To: <1127326966.22154.55.camel@localhost.localdomain> References: <1127326966.22154.55.camel@localhost.localdomain> Message-ID: <1127345278.15276.0.camel@gaston> > I may be mistaken, but it looks like for small pages the vsid is used as > the "key" to the hardware hash table but for huge pages only the virtual > page frame number (vpn) is used. Could someone explain the difference > between the way huge pages and normal pages are hashed? Using only the > vpn seems like it would result in false hash hits whenever separate > programs map huge pages at the same virtual address. The vsid should be used in both case, it "smells" like we may not be invalidating pages properly on exit, I'll have a look. Can you send me the test program ? Ben. From benh at kernel.crashing.org Thu Sep 22 12:01:04 2005 From: benh at kernel.crashing.org (Benjamin Herrenschmidt) Date: Thu, 22 Sep 2005 12:01:04 +1000 Subject: [PATCH] ppc64: SMU partitions & device-tree Message-ID: <1127354464.32344.10.camel@gaston> The SMU exposes various informations to the system via "partitions" (or sdb partitions). Those infos are found in properties named "sdb-partition-XX" where XX is the 2 digit hexadecimal partition ID, under the /smu node of the device-tree. Those informations contain model specific details, calibration infos for the sensors, infos used for frequency switching, etc etc etc... Unfortunately, the firmware driver for the SMU doesn't create the sdb-partition-XX for all partitions present in the SMU flash/eeprom. It only exposes a subset of them, which lacks a few that are necessary to properly implement thermal control among others (sdb-partition-0x21 which contains the calibration data for the SMU sensors for example is missing). This patch applies on top of the iMac G5 thermal control patch, and adds the ability to the SMU driver to query the SMU for missing partitions. It hooks on the smu_get_sdb_partition() function I added in the previous patch to make it able to retreive missing ones from the SMU directly. It also adds a command to use by userland programs to fetch missing partitions. Those will automatically be added to the device-tree. In order to update the device-tree, I made changes to prom_add_property() so that it now updates the proc entries as well (and gets some locking too while we are at it). I also removed the code in proc_devtree.c that tried to enforce the order of the properties & nodes as it really didn't look good and shouldn't be necessary. You should be able to create missing partitions like 0x21 or 0x5 with this tool: #include #include #include #include #include #include #include #include "smu.h" int fd; struct smu_user_cmd_hdr *chdr; unsigned char *cdata; unsigned char buffer[1024]; static int getpart(int id) { int rc; chdr->cmdtype = SMU_CMDTYPE_GET_PARTITION; chdr->cmd = id; rc = write(fd, chdr, sizeof(*chdr)); if (rc < 0) perror("error writing command"); return rc; } int main(int argc, char **argv) { chdr = (struct smu_user_cmd_hdr *)buffer; cdata = &buffer[sizeof(*chdr)]; if (argc != 2) { perror("usage: smu_createpart part_id"); return -1; } fd = open("/dev/smu", O_RDWR); if (fd == -1) { perror("can't open /dev/smu"); return -1; } return getpart(strtol(argv[1], NULL, 16)); } Signed-off-by: Benjamin Herrenschmidt Index: linux-work/drivers/macintosh/smu.c =================================================================== --- linux-work.orig/drivers/macintosh/smu.c 2005-09-21 14:34:52.000000000 +1000 +++ linux-work/drivers/macintosh/smu.c 2005-09-22 11:51:37.000000000 +1000 @@ -47,13 +47,13 @@ #include #include -#define VERSION "0.6" +#define VERSION "0.7" #define AUTHOR "(c) 2005 Benjamin Herrenschmidt, IBM Corp." #undef DEBUG_SMU #ifdef DEBUG_SMU -#define DPRINTK(fmt, args...) do { printk(KERN_DEBUG fmt , ##args); } while (0) +#define DPRINTK(fmt, args...) do { udbg_printf(KERN_DEBUG fmt , ##args); } while (0) #else #define DPRINTK(fmt, args...) do { } while (0) #endif @@ -92,7 +92,7 @@ * for now, just hard code that */ static struct smu_device *smu; - +static DECLARE_MUTEX(smu_part_access); /* * SMU driver low level stuff @@ -113,9 +113,11 @@ DPRINTK("SMU: starting cmd %x, %d bytes data\n", cmd->cmd, cmd->data_len); - DPRINTK("SMU: data buffer: %02x %02x %02x %02x ...\n", + DPRINTK("SMU: data buffer: %02x %02x %02x %02x %02x %02x %02x %02x\n", ((u8 *)cmd->data_buf)[0], ((u8 *)cmd->data_buf)[1], - ((u8 *)cmd->data_buf)[2], ((u8 *)cmd->data_buf)[3]); + ((u8 *)cmd->data_buf)[2], ((u8 *)cmd->data_buf)[3], + ((u8 *)cmd->data_buf)[4], ((u8 *)cmd->data_buf)[5], + ((u8 *)cmd->data_buf)[6], ((u8 *)cmd->data_buf)[7]); /* Fill the SMU command buffer */ smu->cmd_buf->cmd = cmd->cmd; @@ -438,7 +440,7 @@ EXPORT_SYMBOL(smu_present); -int smu_init (void) +int __init smu_init (void) { struct device_node *np; u32 *data; @@ -843,16 +845,154 @@ return 0; } -struct smu_sdbp_header *smu_get_sdb_partition(int id, unsigned int *size) +/* + * Handling of "partitions" + */ + +static int smu_read_datablock(u8 *dest, unsigned int addr, unsigned int len) +{ + DECLARE_COMPLETION(comp); + unsigned int chunk; + struct smu_cmd cmd; + int rc; + u8 params[8]; + + /* We currently use a chunk size of 0xe. We could check the + * SMU firmware version and use bigger sizes though + */ + chunk = 0xe; + + while (len) { + unsigned int clen = min(len, chunk); + + cmd.cmd = SMU_CMD_MISC_ee_COMMAND; + cmd.data_len = 7; + cmd.data_buf = params; + cmd.reply_len = chunk; + cmd.reply_buf = dest; + cmd.done = smu_done_complete; + cmd.misc = ∁ + params[0] = SMU_CMD_MISC_ee_GET_DATABLOCK_REC; + params[1] = 0x4; + *((u32 *)¶ms[2]) = addr; + params[6] = clen; + + rc = smu_queue_cmd(&cmd); + if (rc) + return rc; + wait_for_completion(&comp); + if (cmd.status != 0) + return rc; + if (cmd.reply_len != clen) { + printk(KERN_DEBUG "SMU: short read in " + "smu_read_datablock, got: %d, want: %d\n", + cmd.reply_len, clen); + return -EIO; + } + len -= clen; + addr += clen; + dest += clen; + } + return 0; +} + +static struct smu_sdbp_header *smu_create_sdb_partition(int id) +{ + DECLARE_COMPLETION(comp); + struct smu_simple_cmd cmd; + unsigned int addr, len, tlen; + struct smu_sdbp_header *hdr; + struct property *prop; + + /* First query the partition info */ + smu_queue_simple(&cmd, SMU_CMD_PARTITION_COMMAND, 2, + smu_done_complete, &comp, + SMU_CMD_PARTITION_LATEST, id); + wait_for_completion(&comp); + + /* Partition doesn't exist (or other error) */ + if (cmd.cmd.status != 0 || cmd.cmd.reply_len != 6) + return NULL; + + /* Fetch address and length from reply */ + addr = *((u16 *)cmd.buffer); + len = cmd.buffer[3] << 2; + /* Calucluate total length to allocate, including the 17 bytes + * for "sdb-partition-XX" that we append at the end of the buffer + */ + tlen = sizeof(struct property) + len + 18; + + prop = kcalloc(tlen, 1, GFP_KERNEL); + if (prop == NULL) + return NULL; + hdr = (struct smu_sdbp_header *)(prop + 1); + prop->name = ((char *)prop) + tlen - 18; + sprintf(prop->name, "sdb-partition-%02x", id); + prop->length = len; + prop->value = (unsigned char *)hdr; + prop->next = NULL; + + /* Read the datablock */ + if (smu_read_datablock((u8 *)hdr, addr, len)) { + printk(KERN_DEBUG "SMU: datablock read failed while reading " + "partition %02x !\n", id); + goto failure; + } + + /* Got it, check a few things and create the property */ + if (hdr->id != id) { + printk(KERN_DEBUG "SMU: Reading partition %02x and got " + "%02x !\n", id, hdr->id); + goto failure; + } + if (prom_add_property(smu->of_node, prop)) { + printk(KERN_DEBUG "SMU: Failed creating sdb-partition-%02x " + "property !\n", id); + goto failure; + } + + return hdr; + failure: + kfree(prop); + return NULL; +} + +/* Note: Only allowed to return error code in pointers (using ERR_PTR) + * when interruptible is 1 + */ +struct smu_sdbp_header *__smu_get_sdb_partition(int id, unsigned int *size, + int interruptible) { char pname[32]; + struct smu_sdbp_header *part; if (!smu) return NULL; sprintf(pname, "sdb-partition-%02x", id); - return (struct smu_sdbp_header *)get_property(smu->of_node, + + if (interruptible) { + int rc; + rc = down_interruptible(&smu_part_access); + if (rc) + return ERR_PTR(rc); + } else + down(&smu_part_access); + + part = (struct smu_sdbp_header *)get_property(smu->of_node, pname, size); + if (part == NULL) { + part = smu_create_sdb_partition(id); + if (part != NULL && size) + *size = part->len << 2; + } + up(&smu_part_access); + return part; +} + +struct smu_sdbp_header *smu_get_sdb_partition(int id, unsigned int *size) +{ + return __smu_get_sdb_partition(id, size, 0); } EXPORT_SYMBOL(smu_get_sdb_partition); @@ -928,6 +1068,14 @@ else if (hdr.cmdtype == SMU_CMDTYPE_WANTS_EVENTS) { pp->mode = smu_file_events; return 0; + } else if (hdr.cmdtype == SMU_CMDTYPE_GET_PARTITION) { + struct smu_sdbp_header *part; + part = __smu_get_sdb_partition(hdr.cmd, NULL, 1); + if (part == NULL) + return -EINVAL; + else if (IS_ERR(part)) + return PTR_ERR(part); + return 0; } else if (hdr.cmdtype != SMU_CMDTYPE_SMU) return -EINVAL; else if (pp->mode != smu_file_commands) Index: linux-work/include/asm-ppc64/smu.h =================================================================== --- linux-work.orig/include/asm-ppc64/smu.h 2005-09-21 14:21:13.000000000 +1000 +++ linux-work/include/asm-ppc64/smu.h 2005-09-22 11:20:30.000000000 +1000 @@ -20,10 +20,23 @@ /* * Partition info commands * - * I do not know what those are for at this point + * These commands are used to retreive the sdb-partition-XX datas from + * the SMU. The lenght is always 2. First byte is the subcommand code + * and second byte is the partition ID. + * + * The reply is 6 bytes: + * + * - 0..1 : partition address + * - 2 : a byte containing the partition ID + * - 3 : length (maybe other bits are rest of header ?) + * + * The data must then be obtained with calls to another command: + * SMU_CMD_MISC_ee_GET_DATABLOCK_REC (described below). */ #define SMU_CMD_PARTITION_COMMAND 0x3e - +#define SMU_CMD_PARTITION_LATEST 0x01 +#define SMU_CMD_PARTITION_BASE 0x02 +#define SMU_CMD_PARTITION_UPDATE 0x03 /* * Fan control @@ -176,6 +189,25 @@ * Misc commands * * This command seem to be a grab bag of various things + * + * SMU_CMD_MISC_ee_GET_DATABLOCK_REC is used, among others, to + * transfer blocks of data from the SMU. So far, I've decrypted it's + * usage to retreive partition data. In order to do that, you have to + * break your transfer in "chunks" since that command cannot transfer + * more than a chunk at a time. The chunk size used by OF is 0xe bytes, + * but it seems that the darwin driver will let you do 0x1e bytes if + * your "PMU" version is >= 0x30. You can get the "PMU" version apparently + * either in the last 16 bits of property "smu-version-pmu" or as the 16 + * bytes at offset 1 of "smu-version-info" + * + * For each chunk, the command takes 7 bytes of arguments: + * byte 0: subcommand code (0x02) + * byte 1: 0x04 (always, I don't know what it means, maybe the address + * space to use or some other nicety. It's hard coded in OF) + * byte 2..5: SMU address of the chunk (big endian 32 bits) + * byte 6: size to transfer (up to max chunk size) + * + * The data is returned directly */ #define SMU_CMD_MISC_ee_COMMAND 0xee #define SMU_CMD_MISC_ee_GET_DATABLOCK_REC 0x02 @@ -357,13 +389,13 @@ * 32 bits integers are usually encoded with 2x16 bits swapped, * this demangles them */ -#define SMU_U32_MIX(x) ((((x) << 16) & 0xffff0000u) | (((x) >> 16) & 0xffffu)) +//#define SMU_U32_MIX(x) ((((x) << 16) & 0xffff0000u) | (((x) >> 16) & 0xffffu)) /* This is the definition of the SMU sdb-partition-0x12 table (called * CPU F/V/T operating points in Darwin). The definition for all those * SMU tables should be moved to some separate file */ -#define SMU_SDB_FVT_ID 0x12 +#define SMU_SDB_FVT_ID 0x12 struct smu_sdbp_fvt { __u32 sysclk; /* Base SysClk frequency in Hz for @@ -380,6 +412,9 @@ */ }; +/* Other partitions without known structures */ +#define SMU_SDB_DEBUG_SWITCHES_ID 0x05 + #ifdef __KERNEL__ /* * This returns the pointer to an SMU "sdb" partition data or NULL @@ -417,14 +452,22 @@ * It is illegal to send SMU commands through a file descriptor configured * for events reception * + * The special SMU_CMDTYPE_GET_PARTITION command can be used to retreive + * SMU sdb-partition's from the SMU when not available. The command will also + * cause the new partition to be added to the device-tree. That command has + * a data_len of 0, you pass the partition ID in the "cmd" field. It will + * not trigger any reply and is not asynchronous. Just fetch the partition + * from the device-tree after it's done. */ struct smu_user_cmd_hdr { __u32 cmdtype; #define SMU_CMDTYPE_SMU 0 /* SMU command */ #define SMU_CMDTYPE_WANTS_EVENTS 1 /* switch fd to events mode */ +#define SMU_CMDTYPE_GET_PARTITION 2 /* retreive an sdb partition */ __u8 cmd; /* SMU command byte */ + __u8 pad[3]; /* padding */ __u32 data_len; /* Lenght of data following */ }; Index: linux-work/arch/ppc64/kernel/prom.c =================================================================== --- linux-work.orig/arch/ppc64/kernel/prom.c 2005-09-20 09:54:18.000000000 +1000 +++ linux-work/arch/ppc64/kernel/prom.c 2005-09-21 20:30:40.000000000 +1000 @@ -31,6 +31,7 @@ #include #include #include +#include #include #include @@ -1893,17 +1894,32 @@ EXPORT_SYMBOL(get_property); /* - * Add a property to a node + * Add a property to a node. */ -void +int prom_add_property(struct device_node* np, struct property* prop) { - struct property **next = &np->properties; + struct property **next; prop->next = NULL; - while (*next) + write_lock(&devtree_lock); + next = &np->properties; + while (*next) { + if (strcmp(prop->name, (*next)->name) == 0) { + /* duplicate ! don't insert it */ + write_unlock(&devtree_lock); + return -1; + } next = &(*next)->next; + } *next = prop; + write_unlock(&devtree_lock); + + /* try to add to proc as well if it was initialized */ + if (np->pde) + proc_device_tree_add_prop(np->pde, prop); + + return 0; } #if 0 Index: linux-work/fs/proc/proc_devtree.c =================================================================== --- linux-work.orig/fs/proc/proc_devtree.c 2005-08-24 13:26:37.000000000 +1000 +++ linux-work/fs/proc/proc_devtree.c 2005-09-22 11:37:51.000000000 +1000 @@ -49,6 +49,39 @@ */ /* + * Add a property to a node + */ +static struct proc_dir_entry * +__proc_device_tree_add_prop(struct proc_dir_entry *de, struct property *pp) +{ + struct proc_dir_entry *ent; + + /* + * Unfortunately proc_register puts each new entry + * at the beginning of the list. So we rearrange them. + */ + ent = create_proc_read_entry(pp->name, + strncmp(pp->name, "security-", 9) + ? S_IRUGO : S_IRUSR, de, + property_read_proc, pp); + if (ent == NULL) + return NULL; + + if (!strncmp(pp->name, "security-", 9)) + ent->size = 0; /* don't leak number of password chars */ + else + ent->size = pp->length; + + return ent; +} + + +void proc_device_tree_add_prop(struct proc_dir_entry *pde, struct property *prop) +{ + __proc_device_tree_add_prop(pde, prop); +} + +/* * Process a node, adding entries for its children and its properties. */ void proc_device_tree_add_node(struct device_node *np, @@ -57,11 +90,9 @@ struct property *pp; struct proc_dir_entry *ent; struct device_node *child; - struct proc_dir_entry *list = NULL, **lastp; const char *p; set_node_proc_entry(np, de); - lastp = &list; for (child = NULL; (child = of_get_next_child(np, child));) { p = strrchr(child->full_name, '/'); if (!p) @@ -71,9 +102,6 @@ ent = proc_mkdir(p, de); if (ent == 0) break; - *lastp = ent; - ent->next = NULL; - lastp = &ent->next; proc_device_tree_add_node(child, ent); } of_node_put(child); @@ -84,7 +112,7 @@ * properties are quite unimportant for us though, thus we * simply "skip" them here, but we do have to check. */ - for (ent = list; ent != NULL; ent = ent->next) + for (ent = de->subdir; ent != NULL; ent = ent->next) if (!strcmp(ent->name, pp->name)) break; if (ent != NULL) { @@ -94,25 +122,10 @@ continue; } - /* - * Unfortunately proc_register puts each new entry - * at the beginning of the list. So we rearrange them. - */ - ent = create_proc_read_entry(pp->name, - strncmp(pp->name, "security-", 9) - ? S_IRUGO : S_IRUSR, de, - property_read_proc, pp); + ent = __proc_device_tree_add_prop(de, pp); if (ent == 0) break; - if (!strncmp(pp->name, "security-", 9)) - ent->size = 0; /* don't leak number of password chars */ - else - ent->size = pp->length; - ent->next = NULL; - *lastp = ent; - lastp = &ent->next; } - de->subdir = list; } /* Index: linux-work/include/asm-ppc/prom.h =================================================================== --- linux-work.orig/include/asm-ppc/prom.h 2005-08-24 13:26:46.000000000 +1000 +++ linux-work/include/asm-ppc/prom.h 2005-09-21 20:14:44.000000000 +1000 @@ -93,7 +93,7 @@ extern int machine_is_compatible(const char *compat); extern unsigned char *get_property(struct device_node *node, const char *name, int *lenp); -extern void prom_add_property(struct device_node* np, struct property* prop); +extern int prom_add_property(struct device_node* np, struct property* prop); extern void prom_get_irq_senses(unsigned char *, int, int); extern int prom_n_addr_cells(struct device_node* np); extern int prom_n_size_cells(struct device_node* np); Index: linux-work/include/asm-ppc64/prom.h =================================================================== --- linux-work.orig/include/asm-ppc64/prom.h 2005-09-20 09:54:26.000000000 +1000 +++ linux-work/include/asm-ppc64/prom.h 2005-09-21 20:29:54.000000000 +1000 @@ -201,6 +201,6 @@ extern int prom_n_size_cells(struct device_node* np); extern int prom_n_intr_cells(struct device_node* np); extern void prom_get_irq_senses(unsigned char *senses, int off, int max); -extern void prom_add_property(struct device_node* np, struct property* prop); +extern int prom_add_property(struct device_node* np, struct property* prop); #endif /* _PPC64_PROM_H */ Index: linux-work/include/linux/proc_fs.h =================================================================== --- linux-work.orig/include/linux/proc_fs.h 2005-08-24 13:26:47.000000000 +1000 +++ linux-work/include/linux/proc_fs.h 2005-09-21 20:26:54.000000000 +1000 @@ -139,15 +139,12 @@ /* * proc_devtree.c */ +#ifdef CONFIG_PROC_DEVICETREE struct device_node; +struct property; extern void proc_device_tree_init(void); -#ifdef CONFIG_PROC_DEVICETREE extern void proc_device_tree_add_node(struct device_node *, struct proc_dir_entry *); -#else /* !CONFIG_PROC_DEVICETREE */ -static inline void proc_device_tree_add_node(struct device_node *np, struct proc_dir_entry *pde) -{ - return; -} +extern void proc_device_tree_add_prop(struct proc_dir_entry *pde, struct property *prop); #endif /* CONFIG_PROC_DEVICETREE */ extern struct proc_dir_entry *proc_symlink(const char *, Index: linux-work/arch/ppc/syslib/prom.c =================================================================== --- linux-work.orig/arch/ppc/syslib/prom.c 2005-08-24 13:26:31.000000000 +1000 +++ linux-work/arch/ppc/syslib/prom.c 2005-09-21 20:31:41.000000000 +1000 @@ -1165,7 +1165,7 @@ /* * Add a property to a node */ -void __openfirmware +int __openfirmware prom_add_property(struct device_node* np, struct property* prop) { struct property **next = &np->properties; @@ -1174,6 +1174,8 @@ while (*next) next = &(*next)->next; *next = prop; + + return 0; } /* I quickly hacked that one, check against spec ! */ From benh at kernel.crashing.org Thu Sep 22 15:23:24 2005 From: benh at kernel.crashing.org (Benjamin Herrenschmidt) Date: Thu, 22 Sep 2005 15:23:24 +1000 Subject: [PATCH] ppc64: iMac G5 cpufreq support In-Reply-To: <1127282471.4386.104.camel@gaston> References: <1127282249.4386.101.camel@gaston> <1127282471.4386.104.camel@gaston> Message-ID: <1127366605.32344.28.camel@gaston> And yet another version fixing some bogosity in the manipulation of MSR_EE (damn, I was tired) This applies on top of the big SMU update posted earlier. It adds cpufreq support for iMac G5 (and SMU based desktop, though that one was untested, testers welcome). It supports full and half speed and also does voltage switching for more power savings. Next step is proper thermal control to make those fans quiet once for all ! Signed-off-by: Benjamin Herrenschmidt Index: linux-work/arch/ppc64/kernel/misc.S =================================================================== --- linux-work.orig/arch/ppc64/kernel/misc.S 2005-09-22 14:09:16.000000000 +1000 +++ linux-work/arch/ppc64/kernel/misc.S 2005-09-22 15:24:27.000000000 +1000 @@ -616,7 +616,7 @@ isync blr - /* +/* * Do an IO access in real mode */ _GLOBAL(real_writeb) @@ -649,6 +649,73 @@ #endif /* defined(CONFIG_PPC_PMAC) || defined(CONFIG_PPC_MAPLE) */ /* + * SCOM access functions for 970 (FX only for now) + * + * unsigned long scom970_read(unsigned int address); + * void scom970_write(unsigned int address, unsigned long value); + * + * The address passed in is the 24 bits register address. This code + * is 970 specific and will not check the status bits, so you should + * know what you are doing. + */ +_GLOBAL(scom970_read) + /* interrupts off */ + mfmsr r4 + ori r0,r4,MSR_EE + xori r0,r0,MSR_EE + mtmsrd r0,1 + + /* rotate address 8 bits left, mask out low 16 bits as they + * aren't implemented on current CPUs and must be 0'd, + * and finally or in RW bit + */ + rlwinm r3,r3,8,0,15 + ori r3,r3,0x8000 + + /* do the actual scom read */ + sync + mtspr SPRN_SCOMC,r3 + isync + mfspr r3,SPRN_SCOMD + mfspr r0,SPRN_SCOMC + sync + isync + + /* XXX: fixup result on some buggy 970's (ouch ! we lost a bit, bah + * that's the best we can do). Not implemented yet as we don't use + * the scom on any of the bogus CPUs yet, but may have to be done + * ultimately + */ + + /* restore interrupts */ + mtmsrd r4,1 + blr + + +_GLOBAL(scom970_write) + /* interrupts off */ + mfmsr r5 + ori r0,r5,MSR_EE + xori r0,r0,MSR_EE + mtmsrd r0,1 + + /* rotate address 8 bits left, mask out low 16 bits as they + * aren't implemented on current CPUs and must be 0'd + */ + rlwinm r3,r3,8,0,15 + + mtspr SPRN_SCOMD,r4 /* write data */ + mtspr SPRN_SCOMC,r3 /* write command */ + sync + isync + mfspr 3,SPRN_SCOMC + + /* restore interrupts */ + mtmsrd r5,1 + blr + + +/* * Create a kernel thread * kernel_thread(fn, arg, flags) */ Index: linux-work/include/asm-ppc64/processor.h =================================================================== --- linux-work.orig/include/asm-ppc64/processor.h 2005-09-22 14:10:14.000000000 +1000 +++ linux-work/include/asm-ppc64/processor.h 2005-09-22 14:39:01.000000000 +1000 @@ -177,6 +177,9 @@ #define SPRN_CTRLT 0x098 #define CTRL_RUNLATCH 0x1 +#define SPRN_SCOMC 0x114 +#define SPRN_SCOMD 0x115 + /* Performance monitor SPRs */ #define SPRN_SIAR 780 #define SPRN_SDAR 781 @@ -536,6 +539,9 @@ } } +extern unsigned long scom970_read(unsigned int address); +extern void scom970_write(unsigned int address, unsigned long value); + #endif /* __KERNEL__ */ #endif /* __ASSEMBLY__ */ Index: linux-work/arch/ppc64/Kconfig =================================================================== --- linux-work.orig/arch/ppc64/Kconfig 2005-09-22 14:09:15.000000000 +1000 +++ linux-work/arch/ppc64/Kconfig 2005-09-22 15:24:26.000000000 +1000 @@ -159,6 +159,17 @@ support. As of this writing the exact hardware interface is strongly in flux, so no good recommendation can be made. +source "drivers/cpufreq/Kconfig" + +config CPU_FREQ_PMAC + bool "Support for Apple G5" + depends on CPU_FREQ && PPC_PMAC64 + select CPU_FREQ_TABLE + help + This adds support for frequency switching on some Apple G5 + machine. This is currently very experimental and works only + on some iMac G5. + config IBMVIO depends on PPC_PSERIES || PPC_ISERIES bool Index: linux-work/arch/ppc64/kernel/Makefile =================================================================== --- linux-work.orig/arch/ppc64/kernel/Makefile 2005-09-22 14:09:15.000000000 +1000 +++ linux-work/arch/ppc64/kernel/Makefile 2005-09-22 14:39:01.000000000 +1000 @@ -60,6 +60,7 @@ obj-$(CONFIG_PPC_PMAC) += pmac_setup.o pmac_feature.o pmac_pci.o \ pmac_time.o pmac_nvram.o pmac_low_i2c.o \ udbg_scc.o +obj-$(CONFIG_CPU_FREQ_PMAC) += pmac_cpufreq.o obj-$(CONFIG_PPC_MAPLE) += maple_setup.o maple_pci.o maple_time.o \ udbg_16550.o Index: linux-work/arch/ppc64/kernel/pmac_cpufreq.c =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ linux-work/arch/ppc64/kernel/pmac_cpufreq.c 2005-09-22 14:39:01.000000000 +1000 @@ -0,0 +1,297 @@ +/* + * Copyright (C) 2002 - 2005 Benjamin Herrenschmidt + * and Markus Demleitner + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This driver adds basic cpufreq support for SMU & 970FX based G5 Macs, + * that is iMac G5 and latest single CPU desktop. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#undef DEBUG + +#ifdef DEBUG +#define DBG(fmt...) printk(fmt) +#else +#define DBG(fmt...) +#endif + +/* see 970FX user manual */ + +#define SCOM_PCR 0x0aa001 /* PCR scom addr */ + +#define PCR_HILO_SELECT 0x80000000U /* 1 = PCR, 0 = PCRH */ +#define PCR_SPEED_FULL 0x00000000U /* 1:1 speed value */ +#define PCR_SPEED_HALF 0x00020000U /* 1:2 speed value */ +#define PCR_SPEED_QUARTER 0x00040000U /* 1:4 speed value */ +#define PCR_SPEED_MASK 0x000e0000U /* speed mask */ +#define PCR_SPEED_SHIFT 17 +#define PCR_FREQ_REQ_VALID 0x00010000U /* freq request valid */ +#define PCR_VOLT_REQ_VALID 0x00008000U /* volt request valid */ +#define PCR_TARGET_TIME_MASK 0x00006000U /* target time */ +#define PCR_STATLAT_MASK 0x00001f00U /* STATLAT value */ +#define PCR_SNOOPLAT_MASK 0x000000f0U /* SNOOPLAT value */ +#define PCR_SNOOPACC_MASK 0x0000000fU /* SNOOPACC value */ + +#define SCOM_PSR 0x408001 /* PSR scom addr */ +/* warning: PSR is a 64 bits register */ +#define PSR_CMD_RECEIVED 0x2000000000000000U /* command received */ +#define PSR_CMD_COMPLETED 0x1000000000000000U /* command completed */ +#define PSR_CUR_SPEED_MASK 0x0300000000000000U /* current speed */ +#define PSR_CUR_SPEED_SHIFT (56) + +/* + * The G5 only supports two frequencies (Quarter speed is not supported) + */ +#define CPUFREQ_HIGH 0 +#define CPUFREQ_LOW 1 + +static struct cpufreq_frequency_table g5_cpu_freqs[] = { + {CPUFREQ_HIGH, 0}, + {CPUFREQ_LOW, 0}, + {0, CPUFREQ_TABLE_END}, +}; + +static struct freq_attr* g5_cpu_freqs_attr[] = { + &cpufreq_freq_attr_scaling_available_freqs, + NULL, +}; + +/* Power mode data is an array of the 32 bits PCR values to use for + * the various frequencies, retreived from the device-tree + */ +static u32 *g5_pmode_data; +static int g5_pmode_max; +static int g5_pmode_cur; + + +static struct smu_sdbp_fvt *g5_fvt_table; /* table of op. points */ +static int g5_fvt_count; /* number of op. points */ +static int g5_fvt_cur; /* current op. point */ + +/* ----------------- real hardware interface */ + +static void g5_switch_volt(int speed_mode) +{ + struct smu_simple_cmd cmd; + + DECLARE_COMPLETION(comp); + smu_queue_simple(&cmd, SMU_CMD_POWER_COMMAND, 8, smu_done_complete, + &comp, 'V', 'S', 'L', 'E', 'W', + 0xff, g5_fvt_cur+1, speed_mode); + wait_for_completion(&comp); +} + +static int g5_switch_freq(int speed_mode) +{ + int to; + + if (g5_pmode_cur == speed_mode) + return 0; + + /* If frequency is going up, first ramp up the voltage */ + if (speed_mode < g5_pmode_cur) + g5_switch_volt(speed_mode); + + /* Clear PCR high */ + scom970_write(SCOM_PCR, 0); + /* Clear PCR low */ + scom970_write(SCOM_PCR, PCR_HILO_SELECT | 0); + /* Set PCR low */ + scom970_write(SCOM_PCR, PCR_HILO_SELECT | + g5_pmode_data[speed_mode]); + + /* Wait for completion */ + for (to = 0; to < 10; to++) { + unsigned long psr = scom970_read(SCOM_PSR); + + if ((psr & PSR_CMD_RECEIVED) == 0 && + (((psr >> PSR_CUR_SPEED_SHIFT) ^ + (g5_pmode_data[speed_mode] >> PCR_SPEED_SHIFT)) & 0x3) + == 0) + break; + if (psr & PSR_CMD_COMPLETED) + break; + udelay(100); + } + + /* If frequency is going down, last ramp the voltage */ + if (speed_mode > g5_pmode_cur) + g5_switch_volt(speed_mode); + + g5_pmode_cur = speed_mode; + ppc_proc_freq = g5_cpu_freqs[speed_mode].frequency * 1000ul; + + return 0; +} + +static int g5_query_freq(void) +{ + unsigned long psr = scom970_read(SCOM_PSR); + int i; + + for (i = 0; i <= g5_pmode_max; i++) + if ((((psr >> PSR_CUR_SPEED_SHIFT) ^ + (g5_pmode_data[i] >> PCR_SPEED_SHIFT)) & 0x3) == 0) + break; + return i; +} + +/* ----------------- cpufreq bookkeeping */ +static int __pmac g5_cpufreq_verify(struct cpufreq_policy *policy) +{ + return cpufreq_frequency_table_verify(policy, g5_cpu_freqs); +} + +static int __pmac g5_cpufreq_target(struct cpufreq_policy *policy, + unsigned int target_freq, unsigned int relation) +{ + unsigned int newstate = 0; + + if (cpufreq_frequency_table_target(policy, g5_cpu_freqs, + target_freq, relation, &newstate)) + return -EINVAL; + + return g5_switch_freq(newstate); +} + +static int __pmac g5_cpufreq_cpu_init(struct cpufreq_policy *policy) +{ + if (policy->cpu != 0) + return -ENODEV; + + policy->governor = CPUFREQ_DEFAULT_GOVERNOR; + policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL; + policy->cur = g5_cpu_freqs[g5_query_freq()].frequency; + cpufreq_frequency_table_get_attr(g5_cpu_freqs, policy->cpu); + + return cpufreq_frequency_table_cpuinfo(policy, + g5_cpu_freqs); +} + + +static struct cpufreq_driver g5_cpufreq_driver = { + .name = "powermac", + .owner = THIS_MODULE, + .flags = CPUFREQ_CONST_LOOPS, + .init = g5_cpufreq_cpu_init, + .verify = g5_cpufreq_verify, + .target = g5_cpufreq_target, + .attr = g5_cpu_freqs_attr, +}; + + +static int __init g5_cpufreq_init(void) +{ + struct device_node *cpunode; + unsigned int psize, ssize; + struct smu_sdbp_header *shdr; + unsigned long max_freq; + u32 *valp; + int rc = -ENODEV; + + /* Look for CPU and SMU nodes */ + cpunode = of_find_node_by_type(NULL, "cpu"); + if (!cpunode) { + DBG("No CPU node !\n"); + return -ENODEV; + } + + /* Check 970FX for now */ + valp = (u32 *)get_property(cpunode, "cpu-version", NULL); + if (!valp) { + DBG("No cpu-version property !\n"); + goto bail_noprops; + } + if (((*valp) >> 16) != 0x3c) { + DBG("Wrong CPU version: %08x\n", *valp); + goto bail_noprops; + } + + /* Look for the powertune data in the device-tree */ + g5_pmode_data = (u32 *)get_property(cpunode, "power-mode-data",&psize); + if (!g5_pmode_data) { + DBG("No power-mode-data !\n"); + goto bail_noprops; + } + g5_pmode_max = psize / sizeof(u32) - 1; + + /* Look for the FVT table */ + shdr = smu_get_sdb_partition(SMU_SDB_FVT_ID, NULL); + if (!shdr) + goto bail_noprops; + g5_fvt_table = (struct smu_sdbp_fvt *)&shdr[1]; + ssize = (shdr->len * sizeof(u32)) - sizeof(struct smu_sdbp_header); + g5_fvt_count = ssize / sizeof(struct smu_sdbp_fvt); + g5_fvt_cur = 0; + + /* Sanity checking */ + if (g5_fvt_count < 1 || g5_pmode_max < 1) + goto bail_noprops; + + /* + * From what I see, clock-frequency is always the maximal frequency. + * The current driver can not slew sysclk yet, so we really only deal + * with powertune steps for now. We also only implement full freq and + * half freq in this version. So far, I haven't yet seen a machine + * supporting anything else. + */ + valp = (u32 *)get_property(cpunode, "clock-frequency", NULL); + if (!valp) + return -ENODEV; + max_freq = (*valp)/1000; + g5_cpu_freqs[0].frequency = max_freq; + g5_cpu_freqs[1].frequency = max_freq/2; + + /* Check current frequency */ + g5_pmode_cur = g5_query_freq(); + if (g5_pmode_cur > 1) { + /* We don't support anything but 1:1 and 1:2, fixup ... */ + g5_switch_freq(1); + g5_pmode_cur = 1; + } + + printk(KERN_INFO "Registering G5 CPU frequency driver\n"); + printk(KERN_INFO "Low: %d Mhz, High: %d Mhz, Cur: %d MHz\n", + g5_cpu_freqs[1].frequency/1000, + g5_cpu_freqs[0].frequency/1000, + g5_cpu_freqs[g5_pmode_cur].frequency/1000); + + rc = cpufreq_register_driver(&g5_cpufreq_driver); + + /* We keep the CPU node on hold... hopefully, Apple G5 don't have + * hotplug CPU with a dynamic device-tree ... + */ + return rc; + + bail_noprops: + of_node_put(cpunode); + + return rc; +} + +module_init(g5_cpufreq_init); + + +MODULE_LICENSE("GPL"); Index: linux-work/drivers/macintosh/smu.c =================================================================== --- linux-work.orig/drivers/macintosh/smu.c 2005-09-22 14:39:01.000000000 +1000 +++ linux-work/drivers/macintosh/smu.c 2005-09-22 15:24:30.000000000 +1000 @@ -843,6 +843,18 @@ return 0; } +struct smu_sdbp_header *smu_get_sdb_partition(int id, unsigned int *size) +{ + char pname[32]; + + if (!smu) + return NULL; + + sprintf(pname, "sdb-partition-%02x", id); + return (struct smu_sdbp_header *)get_property(smu->of_node, + pname, size); +} +EXPORT_SYMBOL(smu_get_sdb_partition); /* Index: linux-work/include/asm-ppc64/smu.h =================================================================== --- linux-work.orig/include/asm-ppc64/smu.h 2005-09-22 14:39:01.000000000 +1000 +++ linux-work/include/asm-ppc64/smu.h 2005-09-22 15:24:30.000000000 +1000 @@ -144,7 +144,11 @@ * - lenght 8 ("VSLEWxyz") has 3 additional bytes appended, and is * used to set the voltage slewing point. The SMU replies with "DONE" * I yet have to figure out their exact meaning of those 3 bytes in - * both cases. + * both cases. They seem to be: + * x = processor mask + * y = op. point index + * z = processor freq. step index + * I haven't yet decyphered result codes * */ #define SMU_CMD_POWER_COMMAND 0xaa @@ -244,6 +248,7 @@ */ extern void smu_done_complete(struct smu_cmd *cmd, void *misc); + /* * Synchronous helpers. Will spin-wait for completion of a command */ @@ -334,6 +339,59 @@ #endif /* __KERNEL__ */ /* + * - SMU "sdb" partitions informations - + */ + + +/* + * Partition header format + */ +struct smu_sdbp_header { + __u8 id; + __u8 len; + __u8 version; + __u8 flags; +}; + +/* + * 32 bits integers are usually encoded with 2x16 bits swapped, + * this demangles them + */ +#define SMU_U32_MIX(x) ((((x) << 16) & 0xffff0000u) | (((x) >> 16) & 0xffffu)) + +/* This is the definition of the SMU sdb-partition-0x12 table (called + * CPU F/V/T operating points in Darwin). The definition for all those + * SMU tables should be moved to some separate file + */ +#define SMU_SDB_FVT_ID 0x12 + +struct smu_sdbp_fvt { + __u32 sysclk; /* Base SysClk frequency in Hz for + * this operating point + */ + __u8 pad; + __u8 maxtemp; /* Max temp. supported by this + * operating point + */ + + __u16 volts[3]; /* CPU core voltage for the 3 + * PowerTune modes, a mode with + * 0V = not supported. + */ +}; + +#ifdef __KERNEL__ +/* + * This returns the pointer to an SMU "sdb" partition data or NULL + * if not found. The data format is described below + */ +extern struct smu_sdbp_header *smu_get_sdb_partition(int id, + unsigned int *size); + +#endif /* __KERNEL__ */ + + +/* * - Userland interface - */ @@ -376,4 +434,5 @@ __u32 reply_len; /* Lenght of data follwing */ }; + #endif /* _SMU_H */ From florin at iucha.net Thu Sep 22 21:08:28 2005 From: florin at iucha.net (Florin Iucha) Date: Thu, 22 Sep 2005 06:08:28 -0500 Subject: BUG: 2.6.14-rc2 sets the wrong time in NVRAM on PowerMac G5 Message-ID: <20050922110828.GB7120@iucha.net> [I have sent the same message to LKML yesterday, with no answer.] Hello, At shutdown, kernel 2.6.14-rc2 saves the wrong value in the hardware clock, since at next bootup I get 21 August 1987. I have narrowed the range down to: 2.6.14-rc1 is good 2.6.14-rc1-git1 is bad. Also, the 2.6.14-rcX does not power off the machine at shutdown. 2.6.13 did work fine. florin at zeus$ cat /proc/cpuinfo processor : 0 cpu : PPC970FX, altivec supported clock : 2700.000000MHz revision : 3.1 processor : 1 cpu : PPC970FX, altivec supported clock : 2700.000000MHz revision : 3.1 timebase : 33333333 machine : PowerMac detected as : 336 (PowerMac G5) pmac flags : 00000000 pmac-generation : NewWorld florin at zeus$ dmesg | grep "Linux version" Linux version 2.6.14-rc2 (root at zeus) (gcc version 4.0.2 20050808 (prerelease) (Ubuntu 4.0.1-4ubuntu8)) #1 SMP Tue Sep 20 17:24:52 CDT 2005 Please let me know if you need more info, or want me to try a patch. Thank you, florin -------------- next part -------------- A non-text attachment was scrubbed... Name: not available Type: application/pgp-signature Size: 189 bytes Desc: Digital signature Url : http://ozlabs.org/pipermail/linuxppc64-dev/attachments/20050922/5fad82d1/attachment.pgp From arnd at arndb.de Thu Sep 22 22:46:55 2005 From: arnd at arndb.de (Arnd Bergmann) Date: Thu, 22 Sep 2005 14:46:55 +0200 Subject: [PATCH] Avoid use of uninitialised spinlock in EEH. In-Reply-To: <1127322900.28995.149.camel@hades.cambridge.redhat.com> References: <1127322900.28995.149.camel@hades.cambridge.redhat.com> Message-ID: <200509221446.56228.arnd@arndb.de> On Middeweken 21 September 2005 19:14, David Woodhouse wrote: > +extern int eeh_subsystem_enabled; > + How about making that a firmware feature bit? That would avoid the extra global exported symbol and be slightly more efficient for the pSeries-only configuration. Arnd <>< From agl at us.ibm.com Fri Sep 23 00:02:27 2005 From: agl at us.ibm.com (Adam Litke) Date: Thu, 22 Sep 2005 09:02:27 -0500 Subject: Hugetlb HPTE hashing weirdness In-Reply-To: <1127345278.15276.0.camel@gaston> References: <1127326966.22154.55.camel@localhost.localdomain> <1127345278.15276.0.camel@gaston> Message-ID: <1127397747.13899.9.camel@localhost.localdomain> On Thu, 2005-09-22 at 09:27 +1000, Benjamin Herrenschmidt wrote: > > I may be mistaken, but it looks like for small pages the vsid is used as > > the "key" to the hardware hash table but for huge pages only the virtual > > page frame number (vpn) is used. Could someone explain the difference > > between the way huge pages and normal pages are hashed? Using only the > > vpn seems like it would result in false hash hits whenever separate > > programs map huge pages at the same virtual address. > > The vsid should be used in both case, it "smells" like we may not be > invalidating pages properly on exit, I'll have a look. Thanks. I suppose I should mention that I've been working with David Gibson on demand faulting for huge pages (which is where I first discovered the issue). It does definitely show up (though not quite as bad) in mainline kernels too. > Can you send me the test program ? Attached is my somewhat hacky hugetlb test suite. Build it with 'make all'. I've been reproducing with: for i in `seq 1 10`; do ./mmap-gettest 1 10; done After about the third or fourth iteration, you should start to see test failures. -- Adam Litke - (agl at us.ibm.com) IBM Linux Technology Center -------------- next part -------------- A non-text attachment was scrubbed... Name: hugetlb-tests.tar.gz Type: application/x-compressed-tar Size: 9013 bytes Desc: not available Url : http://ozlabs.org/pipermail/linuxppc64-dev/attachments/20050922/7bab2ec6/attachment.bin From galak at freescale.com Fri Sep 23 01:13:31 2005 From: galak at freescale.com (Kumar Gala) Date: Thu, 22 Sep 2005 10:13:31 -0500 (CDT) Subject: [PATCH] powerpc: Fix building of power3 config on ppc32 Message-ID: The spinlock_types.h merge renamed the structure for raw_spinlock_t to match ppc64. In doing so some of the spinlock macros/functions needed to be updated to match. Apparently, this seems to only be caught when building power3. Signed-off-by: Kumar Gala --- commit faf6551d6434845fb16e28c203b2dc66d91ebd1f tree 7f14282bd0eea36376ea64ee2ab7a61aaadd1ea0 parent 613d5aafb93030cbf69943dd47c3b37bdfd5a398 author Kumar K. Gala Thu, 22 Sep 2005 10:12:03 -0500 committer Kumar K. Gala Thu, 22 Sep 2005 10:12:03 -0500 include/asm-ppc/spinlock.h | 8 ++++---- 1 files changed, 4 insertions(+), 4 deletions(-) diff --git a/include/asm-ppc/spinlock.h b/include/asm-ppc/spinlock.h --- a/include/asm-ppc/spinlock.h +++ b/include/asm-ppc/spinlock.h @@ -9,7 +9,7 @@ * (the type definitions are in asm/raw_spinlock_types.h) */ -#define __raw_spin_is_locked(x) ((x)->lock != 0) +#define __raw_spin_is_locked(x) ((x)->slock != 0) #define __raw_spin_unlock_wait(lock) \ do { while (__raw_spin_is_locked(lock)) cpu_relax(); } while (0) #define __raw_spin_lock_flags(lock, flags) __raw_spin_lock(lock) @@ -31,17 +31,17 @@ static inline void __raw_spin_lock(raw_s bne- 2b\n\ isync" : "=&r"(tmp) - : "r"(&lock->lock), "r"(1) + : "r"(&lock->slock), "r"(1) : "cr0", "memory"); } static inline void __raw_spin_unlock(raw_spinlock_t *lock) { __asm__ __volatile__("eieio # __raw_spin_unlock": : :"memory"); - lock->lock = 0; + lock->slock = 0; } -#define __raw_spin_trylock(l) (!test_and_set_bit(0,&(l)->lock)) +#define __raw_spin_trylock(l) (!test_and_set_bit(0,(volatile unsigned long *)(&(l)->slock))) /* * Read-write spinlocks, allowing multiple readers From ntl at pobox.com Fri Sep 23 01:29:21 2005 From: ntl at pobox.com (Nathan Lynch) Date: Thu, 22 Sep 2005 10:29:21 -0500 Subject: [PATCH] ppc64: SMU partitions & device-tree In-Reply-To: <1127354464.32344.10.camel@gaston> References: <1127354464.32344.10.camel@gaston> Message-ID: <20050922152921.GN3560@otto> Benjamin Herrenschmidt wrote: > In order to update the device-tree, I made changes to > prom_add_property() so that it now updates the proc entries as well > (and gets some locking too while we are at it). I also removed the > code in proc_devtree.c that tried to enforce the order of the > properties & nodes as it really didn't look good and shouldn't be > necessary. > -void > +int > prom_add_property(struct device_node* np, struct property* prop) > { > - struct property **next = &np->properties; > + struct property **next; > > prop->next = NULL; > - while (*next) > + write_lock(&devtree_lock); > + next = &np->properties; > + while (*next) { > + if (strcmp(prop->name, (*next)->name) == 0) { > + /* duplicate ! don't insert it */ > + write_unlock(&devtree_lock); > + return -1; > + } > next = &(*next)->next; > + } > *next = prop; > + write_unlock(&devtree_lock); > + > + /* try to add to proc as well if it was initialized */ > + if (np->pde) > + proc_device_tree_add_prop(np->pde, prop); > + > + return 0; > } I think this is abusing devtree_lock, which is meant to protect traversal of the device tree and not the contents of nodes. True, this serializes prom_add_property itself, and will prevent corruption of the node's property list. But I think I'd rather the SMU code take care of this itself, i.e. use its own mutex to serialize the addition of properties to /smu. From jdl at freescale.com Fri Sep 23 04:20:13 2005 From: jdl at freescale.com (Jon Loeliger) Date: Thu, 22 Sep 2005 13:20:13 -0500 Subject: PATCH powerpc Merge asm-ppc*/seccomp.h Message-ID: Merge asm-ppc*/seccomp.h. Signed-off-by: Jon Loeliger Signed-off-by: Kumar Gala --- include/asm-powerpc/seccomp.h | 21 +++++++++++++++++++++ include/asm-ppc/seccomp.h | 10 ---------- include/asm-ppc64/seccomp.h | 21 --------------------- 3 files changed, 21 insertions(+), 31 deletions(-) diff --git a/include/asm-powerpc/seccomp.h b/include/asm-powerpc/seccomp.h new file mode 100644 --- /dev/null +++ b/include/asm-powerpc/seccomp.h @@ -0,0 +1,21 @@ +#ifndef _ASM_POWERPC_SECCOMP_H + +#include + +#if defined(__powerpc64__) && !defined(TIF_32BIT) +#error "unexpected TIF_32BIT on ppc64" +#endif + +#include + +#define __NR_seccomp_read __NR_read +#define __NR_seccomp_write __NR_write +#define __NR_seccomp_exit __NR_exit +#define __NR_seccomp_sigreturn __NR_rt_sigreturn + +#define __NR_seccomp_read_32 __NR_read +#define __NR_seccomp_write_32 __NR_write +#define __NR_seccomp_exit_32 __NR_exit +#define __NR_seccomp_sigreturn_32 __NR_sigreturn + +#endif /* _ASM_POWERPC_SECCOMP_H */ diff --git a/include/asm-ppc/seccomp.h b/include/asm-ppc/seccomp.h deleted file mode 100644 --- a/include/asm-ppc/seccomp.h +++ /dev/null @@ -1,10 +0,0 @@ -#ifndef _ASM_SECCOMP_H - -#include - -#define __NR_seccomp_read __NR_read -#define __NR_seccomp_write __NR_write -#define __NR_seccomp_exit __NR_exit -#define __NR_seccomp_sigreturn __NR_rt_sigreturn - -#endif /* _ASM_SECCOMP_H */ diff --git a/include/asm-ppc64/seccomp.h b/include/asm-ppc64/seccomp.h deleted file mode 100644 --- a/include/asm-ppc64/seccomp.h +++ /dev/null @@ -1,21 +0,0 @@ -#ifndef _ASM_SECCOMP_H - -#include /* already defines TIF_32BIT */ - -#ifndef TIF_32BIT -#error "unexpected TIF_32BIT on ppc64" -#endif - -#include - -#define __NR_seccomp_read __NR_read -#define __NR_seccomp_write __NR_write -#define __NR_seccomp_exit __NR_exit -#define __NR_seccomp_sigreturn __NR_rt_sigreturn - -#define __NR_seccomp_read_32 __NR_read -#define __NR_seccomp_write_32 __NR_write -#define __NR_seccomp_exit_32 __NR_exit -#define __NR_seccomp_sigreturn_32 __NR_sigreturn - -#endif /* _ASM_SECCOMP_H */ From hch at lst.de Fri Sep 23 04:31:26 2005 From: hch at lst.de (Christoph Hellwig) Date: Thu, 22 Sep 2005 20:31:26 +0200 Subject: PATCH powerpc Merge asm-ppc*/seccomp.h In-Reply-To: References: Message-ID: <20050922183126.GA18853@lst.de> > +#include > + > +#if defined(__powerpc64__) && !defined(TIF_32BIT) > +#error "unexpected TIF_32BIT on ppc64" > +#endif just kill this check, it's rather pointless From jdl at freescale.com Fri Sep 23 04:36:52 2005 From: jdl at freescale.com (Jon Loeliger) Date: Thu, 22 Sep 2005 13:36:52 -0500 Subject: PATCH powerpc Merge asm-ppc*/seccomp.h In-Reply-To: Your message of "Thu, 22 Sep 2005 20:31:26 +0200." <20050922183126.GA18853@lst.de> References: <20050922183126.GA18853@lst.de> Message-ID: So, like, the other day Christoph Hellwig mumbled: > > +#include > > + > > +#if defined(__powerpc64__) && !defined(TIF_32BIT) > > +#error "unexpected TIF_32BIT on ppc64" > > +#endif > > just kill this check, it's rather pointless OK. But keep the #include? It's actually the part that is defining TIF_32BIT for ppc64 (indirectly through linux/thread_info.h and asm/thread_info.h). Won't those bits be needed still? jdl From miltonm at bga.com Fri Sep 23 04:44:01 2005 From: miltonm at bga.com (Milton Miller) Date: Thu, 22 Sep 2005 13:44:01 -0500 Subject: [patch 04/11] spufs: add spu-side context switch code In-Reply-To: <20050916123313.717045000@localhost> References: <20050916121646.387617000@localhost> <20050916123313.717045000@localhost> Message-ID: On Sep 16, 2005, at 5:01 PM, Arnd Bergmann wrote: > Add the source code that is used to generate spu_save_dump.h and > spu_restore_dump.h. Since a full spu tool chain is needed to > generate these files, the default remains to use the shipped > versions in order to keep the number of tools for building the > kernel down. > > From: Mark Nutter: > Signed-off-by: Arnd Bergmann > > -- > > Makefile | 49 ++++ > spu_restore.c | 336 +++++++++++++++++++++++++++++++++ > spu_restore_crt0.S | 116 +++++++++++ > spu_save.c | 195 +++++++++++++++++++ > spu_save_crt0.S | 102 ++++++++++ > spu_utils.h | 160 +++++++++++++++ > 6 files changed, 958 insertions(+) > > Index: linux-cg/fs/spufs/Makefile > =================================================================== > --- linux-cg.orig/fs/spufs/Makefile > +++ linux-cg/fs/spufs/Makefile ... > + > +# create C code from ELF executable > +cmd_hexdump = ( \ > + echo "/*" ; \ > + echo " * $*_dump.h: Copyright (C) 2005 IBM." ; \ > + echo " * Hex-dump auto generated from $*.c." ; \ > + echo " * Do not edit!" ; \ > + echo " */" ; \ > + echo "static unsigned int $*_code[] __page_aligned = {" ; \ > + hexdump -v -e '4/4 "0x%08x, " "\n"' $< ; \ > + echo "};" ; \ > + ) > $@ > +quiet_cmd_hexdump = HEXDUMP $@ > +$(obj)/%_dump.h: $(obj)/%.bin > + $(call if_changed,hexdump) > How about doing an .incbin of the generated binary? I guess the problem wouuld be shipping binary vs text file for the no tools case? One way to handle this is would be to ship headers built this way, but include them based on the KCONFIG that says build the code locally. Oh, and i guess static wouuld have to go for .incbin seperately linked. milton From miltonm at bga.com Fri Sep 23 04:44:05 2005 From: miltonm at bga.com (Milton Miller) Date: Thu, 22 Sep 2005 13:44:05 -0500 Subject: [patch 10/11] spufs: new entries for SPU special purpose registers. In-Reply-To: <20050916123314.704421000@localhost> References: <20050916121646.387617000@localhost> <20050916123314.704421000@localhost> Message-ID: <2a9e5c407bfb32944a179d255306bce2@bga.com> On Sep 16, 2005, at 5:01 PM, Arnd Bergmann wrote: > This patch implements SPUFS directory entries for various special > purpose registers. These include the SPU floating point control > register (fpcr), decrementer (decr), and machine status register > (srr0). It should now be possible to query/set all user state > from SPUFS, implement get/set_context interfaces, etc. > > From: Mark Nutter > Signed-off-by: Arnd Bergmann > > -- > > file.c | 170 > +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ > 1 files changed, 170 insertions(+) > > Index: linux-cg/fs/spufs/file.c > =================================================================== > --- linux-cg.orig/fs/spufs/file.c > +++ linux-cg/fs/spufs/file.c > @@ -223,6 +223,60 @@ static struct file_operations spufs_regs > .llseek = generic_file_llseek, > }; > > +static ssize_t > +spufs_fpcr_read(struct file *file, char __user * buffer, > + size_t size, loff_t * pos) > +{ > + struct spu_context *ctx = file->private_data; > + struct spu_lscsa *lscsa = ctx->csa.lscsa; > + int ret; > + > + spu_acquire_saved(ctx); > + if (ctx->state == SPU_STATE_LOCKED) { > + spu_release(ctx); > + return -EAGAIN; > + } > + > + ret = simple_read_from_buffer(buffer, size, pos, > + &lscsa->fpcr, sizeof(lscsa->fpcr)); > + > + spu_release(ctx); > + return ret; > +} > Another style that is frequently used throught out the kernel and often results in smaller code gen is to set ret and goto the exit path. The compiler can then reuse the function call code. Something like this (untested): +static ssize_t +spufs_fpcr_read(struct file *file, char __user * buffer, + size_t size, loff_t * pos) +{ + struct spu_context *ctx = file->private_data; + struct spu_lscsa *lscsa = ctx->csa.lscsa; + int ret; + + spu_acquire_saved(ctx); + if (ctx->state == SPU_STATE_LOCKED) { + ret = -EAGAIN; + goto release; + } + + ret = simple_read_from_buffer(buffer, size, pos, + &lscsa->fpcr, sizeof(lscsa->fpcr)); + + release: + spu_release(ctx); + return ret; +} A further changed use less pervasively puts the setting of ret before the if, so the body is a simple goto. I haven't looked at how the resulting code compares. Also, do we expect the state to be locked? Maybe that should be made unlikely(). That may also improve the resulting code. milton From geoffrey.levand at am.sony.com Fri Sep 23 04:42:32 2005 From: geoffrey.levand at am.sony.com (Geoff Levand) Date: Thu, 22 Sep 2005 11:42:32 -0700 Subject: Does iSeries actually use vmlinux.sm? Message-ID: <4332FB18.3000700@am.sony.com> I was doing some more cleanups to arch/ppc64/Makefile and I see this line in the current ppc64-2.6.git: boottargets-$(CONFIG_PPC_ISERIES) += vmlinux.sminitrd vmlinux.initrd vmlinux.sm But there is no make target to actually build vmlinux.sminitrd and vmlinux.sm, and the only way to specify they be built is to put vmlinux.sm as a target on the make command line. 'make' and 'make install' both will build just vmlinux as here: bootimage-$(CONFIG_PPC_ISERIES) := vmlinux defaultimage-$(CONFIG_PPC_ISERIES) := vmlinux My question is does PPC_ISERIES need these sm versions, and if so how to build them, and if not, does a zImage and zImage.initrd make sense as build targets for this platform? -Geoff From bgill at freescale.com Fri Sep 23 05:20:04 2005 From: bgill at freescale.com (Becky Bruce) Date: Thu, 22 Sep 2005 14:20:04 -0500 (CDT) Subject: [PATCH] powerpc: merge atomic.h, memory.h Message-ID: powerpc: Merge atomic.h and memory.h into powerpc Merged atomic.h into include/powerpc. Moved asm-style HMT_ defines from memory.h into ppc_asm.h, where there were already HMT_defines; moved c-style HMT_ defines to processor.h. Renamed memory.h to synch.h to better reflect its contents. Signed-off-by: Kumar Gala Signed-off-by: Becky Bruce Signed-off-by: Jon Loeliger --- commit ab08c88845ac6e755db2ef806c36d1e469ef4180 tree 628c01b9dcfff035603ac372fe86fe6946ec15e2 parent 1124b50f3b383405d5737663e2445171fa5828fb author Becky Bruce Thu, 22 Sep 2005 14:15:15 -0500 committer Becky Bruce Thu, 22 Sep 2005 14:15:15 -0500 include/asm-powerpc/atomic.h | 209 ++++++++++++++++++++++++++++++++++++++++ include/asm-powerpc/auxvec.h | 2 include/asm-powerpc/ppc_asm.h | 3 + include/asm-powerpc/synch.h | 51 ++++++++++ include/asm-ppc/atomic.h | 214 ----------------------------------------- include/asm-ppc/io.h | 11 -- include/asm-ppc64/atomic.h | 197 -------------------------------------- include/asm-ppc64/bitops.h | 2 include/asm-ppc64/futex.h | 2 include/asm-ppc64/io.h | 2 include/asm-ppc64/memory.h | 61 ------------ include/asm-ppc64/processor.h | 8 ++ include/asm-ppc64/system.h | 4 - 13 files changed, 279 insertions(+), 487 deletions(-) diff --git a/include/asm-powerpc/atomic.h b/include/asm-powerpc/atomic.h new file mode 100644 --- /dev/null +++ b/include/asm-powerpc/atomic.h @@ -0,0 +1,209 @@ +#ifndef _ASM_POWERPC_ATOMIC_H_ +#define _ASM_POWERPC_ATOMIC_H_ + +/* + * PowerPC atomic operations + */ + +typedef struct { volatile int counter; } atomic_t; + +#ifdef __KERNEL__ +#include + +#define ATOMIC_INIT(i) { (i) } + +#define atomic_read(v) ((v)->counter) +#define atomic_set(v,i) (((v)->counter) = (i)) + +/* Erratum #77 on the 405 means we need a sync or dcbt before every stwcx. + * The old ATOMIC_SYNC_FIX covered some but not all of this. + */ +#ifdef CONFIG_IBM405_ERR77 +#define PPC405_ERR77(ra,rb) "dcbt " #ra "," #rb ";" +#else +#define PPC405_ERR77(ra,rb) +#endif + +static __inline__ void atomic_add(int a, atomic_t *v) +{ + int t; + + __asm__ __volatile__( +"1: lwarx %0,0,%3 # atomic_add\n\ + add %0,%2,%0\n" + PPC405_ERR77(0,%3) +" stwcx. %0,0,%3 \n\ + bne- 1b" + : "=&r" (t), "=m" (v->counter) + : "r" (a), "r" (&v->counter), "m" (v->counter) + : "cc"); +} + +static __inline__ int atomic_add_return(int a, atomic_t *v) +{ + int t; + + __asm__ __volatile__( + EIEIO_ON_SMP +"1: lwarx %0,0,%2 # atomic_add_return\n\ + add %0,%1,%0\n" + PPC405_ERR77(0,%2) +" stwcx. %0,0,%2 \n\ + bne- 1b" + ISYNC_ON_SMP + : "=&r" (t) + : "r" (a), "r" (&v->counter) + : "cc", "memory"); + + return t; +} + +#define atomic_add_negative(a, v) (atomic_add_return((a), (v)) < 0) + +static __inline__ void atomic_sub(int a, atomic_t *v) +{ + int t; + + __asm__ __volatile__( +"1: lwarx %0,0,%3 # atomic_sub\n\ + subf %0,%2,%0\n" + PPC405_ERR77(0,%3) +" stwcx. %0,0,%3 \n\ + bne- 1b" + : "=&r" (t), "=m" (v->counter) + : "r" (a), "r" (&v->counter), "m" (v->counter) + : "cc"); +} + +static __inline__ int atomic_sub_return(int a, atomic_t *v) +{ + int t; + + __asm__ __volatile__( + EIEIO_ON_SMP +"1: lwarx %0,0,%2 # atomic_sub_return\n\ + subf %0,%1,%0\n" + PPC405_ERR77(0,%2) +" stwcx. %0,0,%2 \n\ + bne- 1b" + ISYNC_ON_SMP + : "=&r" (t) + : "r" (a), "r" (&v->counter) + : "cc", "memory"); + + return t; +} + +static __inline__ void atomic_inc(atomic_t *v) +{ + int t; + + __asm__ __volatile__( +"1: lwarx %0,0,%2 # atomic_inc\n\ + addic %0,%0,1\n" + PPC405_ERR77(0,%2) +" stwcx. %0,0,%2 \n\ + bne- 1b" + : "=&r" (t), "=m" (v->counter) + : "r" (&v->counter), "m" (v->counter) + : "cc"); +} + +static __inline__ int atomic_inc_return(atomic_t *v) +{ + int t; + + __asm__ __volatile__( + EIEIO_ON_SMP +"1: lwarx %0,0,%1 # atomic_inc_return\n\ + addic %0,%0,1\n" + PPC405_ERR77(0,%1) +" stwcx. %0,0,%1 \n\ + bne- 1b" + ISYNC_ON_SMP + : "=&r" (t) + : "r" (&v->counter) + : "cc", "memory"); + + return t; +} + +/* + * atomic_inc_and_test - increment and test + * @v: pointer of type atomic_t + * + * Atomically increments @v by 1 + * and returns true if the result is zero, or false for all + * other cases. + */ +#define atomic_inc_and_test(v) (atomic_inc_return(v) == 0) + +static __inline__ void atomic_dec(atomic_t *v) +{ + int t; + + __asm__ __volatile__( +"1: lwarx %0,0,%2 # atomic_dec\n\ + addic %0,%0,-1\n" + PPC405_ERR77(0,%2)\ +" stwcx. %0,0,%2\n\ + bne- 1b" + : "=&r" (t), "=m" (v->counter) + : "r" (&v->counter), "m" (v->counter) + : "cc"); +} + +static __inline__ int atomic_dec_return(atomic_t *v) +{ + int t; + + __asm__ __volatile__( + EIEIO_ON_SMP +"1: lwarx %0,0,%1 # atomic_dec_return\n\ + addic %0,%0,-1\n" + PPC405_ERR77(0,%1) +" stwcx. %0,0,%1\n\ + bne- 1b" + ISYNC_ON_SMP + : "=&r" (t) + : "r" (&v->counter) + : "cc", "memory"); + + return t; +} + +#define atomic_sub_and_test(a, v) (atomic_sub_return((a), (v)) == 0) +#define atomic_dec_and_test(v) (atomic_dec_return((v)) == 0) + +/* + * Atomically test *v and decrement if it is greater than 0. + * The function returns the old value of *v minus 1. + */ +static __inline__ int atomic_dec_if_positive(atomic_t *v) +{ + int t; + + __asm__ __volatile__( + EIEIO_ON_SMP +"1: lwarx %0,0,%1 # atomic_dec_if_positive\n\ + addic. %0,%0,-1\n\ + blt- 2f\n" + PPC405_ERR77(0,%1) +" stwcx. %0,0,%1\n\ + bne- 1b" + ISYNC_ON_SMP + "\n\ +2:" : "=&r" (t) + : "r" (&v->counter) + : "cc", "memory"); + + return t; +} + +#define smp_mb__before_atomic_dec() smp_mb() +#define smp_mb__after_atomic_dec() smp_mb() +#define smp_mb__before_atomic_inc() smp_mb() +#define smp_mb__after_atomic_inc() smp_mb() + +#endif /* __KERNEL__ */ +#endif /* _ASM_POWERPC_ATOMIC_H_ */ diff --git a/include/asm-powerpc/ppc_asm.h b/include/asm-powerpc/ppc_asm.h --- a/include/asm-powerpc/ppc_asm.h +++ b/include/asm-powerpc/ppc_asm.h @@ -75,8 +75,11 @@ #define REST_32EVRS(n,s,base) REST_16EVRS(n,s,base); REST_16EVRS(n+16,s,base) /* Macros to adjust thread priority for Iseries hardware multithreading */ +#define HMT_VERY_LOW or 31,31,31 # very low priority\n" #define HMT_LOW or 1,1,1 +#define HMT_MEDIUM_LOW or 6,6,6 # medium low priority\n" #define HMT_MEDIUM or 2,2,2 +#define HMT_MEDIUM_HIGH or 5,5,5 # medium high priority\n" #define HMT_HIGH or 3,3,3 /* handle instructions that older assemblers may not know */ diff --git a/include/asm-powerpc/synch.h b/include/asm-powerpc/synch.h new file mode 100644 --- /dev/null +++ b/include/asm-powerpc/synch.h @@ -0,0 +1,51 @@ +#ifndef _ASM_POWERPC_SYNCH_H +#define _ASM_POWERPC_SYNCH_H + +#include + +#ifdef __powerpc64__ +#define __SUBARCH_HAS_LWSYNC +#endif + +#ifdef __SUBARCH_HAS_LWSYNC +# define LWSYNC lwsync +#else +# define LWSYNC sync +#endif + + +/* + * Arguably the bitops and *xchg operations don't imply any memory barrier + * or SMP ordering, but in fact a lot of drivers expect them to imply + * both, since they do on x86 cpus. + */ +#ifdef CONFIG_SMP +#define EIEIO_ON_SMP "eieio\n" +#define ISYNC_ON_SMP "\n\tisync" +#define SYNC_ON_SMP __stringify(LWSYNC) "\n" +#else +#define EIEIO_ON_SMP +#define ISYNC_ON_SMP +#define SYNC_ON_SMP +#endif + +static inline void eieio(void) +{ + __asm__ __volatile__ ("eieio" : : : "memory"); +} + +static inline void isync(void) +{ + __asm__ __volatile__ ("isync" : : : "memory"); +} + +#ifdef CONFIG_SMP +#define eieio_on_smp() eieio() +#define isync_on_smp() isync() +#else +#define eieio_on_smp() __asm__ __volatile__("": : :"memory") +#define isync_on_smp() __asm__ __volatile__("": : :"memory") +#endif + +#endif /* _ASM_POWERPC_SYNCH_H */ + diff --git a/include/asm-ppc/atomic.h b/include/asm-ppc/atomic.h deleted file mode 100644 --- a/include/asm-ppc/atomic.h +++ /dev/null @@ -1,214 +0,0 @@ -/* - * PowerPC atomic operations - */ - -#ifndef _ASM_PPC_ATOMIC_H_ -#define _ASM_PPC_ATOMIC_H_ - -typedef struct { volatile int counter; } atomic_t; - -#ifdef __KERNEL__ - -#define ATOMIC_INIT(i) { (i) } - -#define atomic_read(v) ((v)->counter) -#define atomic_set(v,i) (((v)->counter) = (i)) - -extern void atomic_clear_mask(unsigned long mask, unsigned long *addr); - -#ifdef CONFIG_SMP -#define SMP_SYNC "sync" -#define SMP_ISYNC "\n\tisync" -#else -#define SMP_SYNC "" -#define SMP_ISYNC -#endif - -/* Erratum #77 on the 405 means we need a sync or dcbt before every stwcx. - * The old ATOMIC_SYNC_FIX covered some but not all of this. - */ -#ifdef CONFIG_IBM405_ERR77 -#define PPC405_ERR77(ra,rb) "dcbt " #ra "," #rb ";" -#else -#define PPC405_ERR77(ra,rb) -#endif - -static __inline__ void atomic_add(int a, atomic_t *v) -{ - int t; - - __asm__ __volatile__( -"1: lwarx %0,0,%3 # atomic_add\n\ - add %0,%2,%0\n" - PPC405_ERR77(0,%3) -" stwcx. %0,0,%3 \n\ - bne- 1b" - : "=&r" (t), "=m" (v->counter) - : "r" (a), "r" (&v->counter), "m" (v->counter) - : "cc"); -} - -static __inline__ int atomic_add_return(int a, atomic_t *v) -{ - int t; - - __asm__ __volatile__( -"1: lwarx %0,0,%2 # atomic_add_return\n\ - add %0,%1,%0\n" - PPC405_ERR77(0,%2) -" stwcx. %0,0,%2 \n\ - bne- 1b" - SMP_ISYNC - : "=&r" (t) - : "r" (a), "r" (&v->counter) - : "cc", "memory"); - - return t; -} - -#define atomic_add_negative(a, v) (atomic_add_return((a), (v)) < 0) - -static __inline__ void atomic_sub(int a, atomic_t *v) -{ - int t; - - __asm__ __volatile__( -"1: lwarx %0,0,%3 # atomic_sub\n\ - subf %0,%2,%0\n" - PPC405_ERR77(0,%3) -" stwcx. %0,0,%3 \n\ - bne- 1b" - : "=&r" (t), "=m" (v->counter) - : "r" (a), "r" (&v->counter), "m" (v->counter) - : "cc"); -} - -static __inline__ int atomic_sub_return(int a, atomic_t *v) -{ - int t; - - __asm__ __volatile__( -"1: lwarx %0,0,%2 # atomic_sub_return\n\ - subf %0,%1,%0\n" - PPC405_ERR77(0,%2) -" stwcx. %0,0,%2 \n\ - bne- 1b" - SMP_ISYNC - : "=&r" (t) - : "r" (a), "r" (&v->counter) - : "cc", "memory"); - - return t; -} - -static __inline__ void atomic_inc(atomic_t *v) -{ - int t; - - __asm__ __volatile__( -"1: lwarx %0,0,%2 # atomic_inc\n\ - addic %0,%0,1\n" - PPC405_ERR77(0,%2) -" stwcx. %0,0,%2 \n\ - bne- 1b" - : "=&r" (t), "=m" (v->counter) - : "r" (&v->counter), "m" (v->counter) - : "cc"); -} - -static __inline__ int atomic_inc_return(atomic_t *v) -{ - int t; - - __asm__ __volatile__( -"1: lwarx %0,0,%1 # atomic_inc_return\n\ - addic %0,%0,1\n" - PPC405_ERR77(0,%1) -" stwcx. %0,0,%1 \n\ - bne- 1b" - SMP_ISYNC - : "=&r" (t) - : "r" (&v->counter) - : "cc", "memory"); - - return t; -} - -/* - * atomic_inc_and_test - increment and test - * @v: pointer of type atomic_t - * - * Atomically increments @v by 1 - * and returns true if the result is zero, or false for all - * other cases. - */ -#define atomic_inc_and_test(v) (atomic_inc_return(v) == 0) - -static __inline__ void atomic_dec(atomic_t *v) -{ - int t; - - __asm__ __volatile__( -"1: lwarx %0,0,%2 # atomic_dec\n\ - addic %0,%0,-1\n" - PPC405_ERR77(0,%2)\ -" stwcx. %0,0,%2\n\ - bne- 1b" - : "=&r" (t), "=m" (v->counter) - : "r" (&v->counter), "m" (v->counter) - : "cc"); -} - -static __inline__ int atomic_dec_return(atomic_t *v) -{ - int t; - - __asm__ __volatile__( -"1: lwarx %0,0,%1 # atomic_dec_return\n\ - addic %0,%0,-1\n" - PPC405_ERR77(0,%1) -" stwcx. %0,0,%1\n\ - bne- 1b" - SMP_ISYNC - : "=&r" (t) - : "r" (&v->counter) - : "cc", "memory"); - - return t; -} - -#define atomic_sub_and_test(a, v) (atomic_sub_return((a), (v)) == 0) -#define atomic_dec_and_test(v) (atomic_dec_return((v)) == 0) - -/* - * Atomically test *v and decrement if it is greater than 0. - * The function returns the old value of *v minus 1. - */ -static __inline__ int atomic_dec_if_positive(atomic_t *v) -{ - int t; - - __asm__ __volatile__( -"1: lwarx %0,0,%1 # atomic_dec_if_positive\n\ - addic. %0,%0,-1\n\ - blt- 2f\n" - PPC405_ERR77(0,%1) -" stwcx. %0,0,%1\n\ - bne- 1b" - SMP_ISYNC - "\n\ -2:" : "=&r" (t) - : "r" (&v->counter) - : "cc", "memory"); - - return t; -} - -#define __MB __asm__ __volatile__ (SMP_SYNC : : : "memory") -#define smp_mb__before_atomic_dec() __MB -#define smp_mb__after_atomic_dec() __MB -#define smp_mb__before_atomic_inc() __MB -#define smp_mb__after_atomic_inc() __MB - -#endif /* __KERNEL__ */ -#endif /* _ASM_PPC_ATOMIC_H_ */ diff --git a/include/asm-ppc/io.h b/include/asm-ppc/io.h --- a/include/asm-ppc/io.h +++ b/include/asm-ppc/io.h @@ -8,6 +8,7 @@ #include #include +#include #include #define SIO_CONFIG_RA 0x398 @@ -440,16 +441,6 @@ extern inline void * phys_to_virt(unsign #define page_to_phys(page) (page_to_pfn(page) << PAGE_SHIFT) #define page_to_bus(page) (page_to_phys(page) + PCI_DRAM_OFFSET) -/* - * Enforce In-order Execution of I/O: - * Acts as a barrier to ensure all previous I/O accesses have - * completed before any further ones are issued. - */ -extern inline void eieio(void) -{ - __asm__ __volatile__ ("eieio" : : : "memory"); -} - /* Enforce in-order execution of data I/O. * No distinction between read/write on PPC; use eieio for all three. */ diff --git a/include/asm-ppc64/atomic.h b/include/asm-ppc64/atomic.h deleted file mode 100644 --- a/include/asm-ppc64/atomic.h +++ /dev/null @@ -1,197 +0,0 @@ -/* - * PowerPC64 atomic operations - * - * Copyright (C) 2001 Paul Mackerras , IBM - * Copyright (C) 2001 Anton Blanchard , IBM - * - * 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_ATOMIC_H_ -#define _ASM_PPC64_ATOMIC_H_ - -#include - -typedef struct { volatile int counter; } atomic_t; - -#define ATOMIC_INIT(i) { (i) } - -#define atomic_read(v) ((v)->counter) -#define atomic_set(v,i) (((v)->counter) = (i)) - -static __inline__ void atomic_add(int a, atomic_t *v) -{ - int t; - - __asm__ __volatile__( -"1: lwarx %0,0,%3 # atomic_add\n\ - add %0,%2,%0\n\ - stwcx. %0,0,%3\n\ - bne- 1b" - : "=&r" (t), "=m" (v->counter) - : "r" (a), "r" (&v->counter), "m" (v->counter) - : "cc"); -} - -static __inline__ int atomic_add_return(int a, atomic_t *v) -{ - int t; - - __asm__ __volatile__( - EIEIO_ON_SMP -"1: lwarx %0,0,%2 # atomic_add_return\n\ - add %0,%1,%0\n\ - stwcx. %0,0,%2\n\ - bne- 1b" - ISYNC_ON_SMP - : "=&r" (t) - : "r" (a), "r" (&v->counter) - : "cc", "memory"); - - return t; -} - -#define atomic_add_negative(a, v) (atomic_add_return((a), (v)) < 0) - -static __inline__ void atomic_sub(int a, atomic_t *v) -{ - int t; - - __asm__ __volatile__( -"1: lwarx %0,0,%3 # atomic_sub\n\ - subf %0,%2,%0\n\ - stwcx. %0,0,%3\n\ - bne- 1b" - : "=&r" (t), "=m" (v->counter) - : "r" (a), "r" (&v->counter), "m" (v->counter) - : "cc"); -} - -static __inline__ int atomic_sub_return(int a, atomic_t *v) -{ - int t; - - __asm__ __volatile__( - EIEIO_ON_SMP -"1: lwarx %0,0,%2 # atomic_sub_return\n\ - subf %0,%1,%0\n\ - stwcx. %0,0,%2\n\ - bne- 1b" - ISYNC_ON_SMP - : "=&r" (t) - : "r" (a), "r" (&v->counter) - : "cc", "memory"); - - return t; -} - -static __inline__ void atomic_inc(atomic_t *v) -{ - int t; - - __asm__ __volatile__( -"1: lwarx %0,0,%2 # atomic_inc\n\ - addic %0,%0,1\n\ - stwcx. %0,0,%2\n\ - bne- 1b" - : "=&r" (t), "=m" (v->counter) - : "r" (&v->counter), "m" (v->counter) - : "cc"); -} - -static __inline__ int atomic_inc_return(atomic_t *v) -{ - int t; - - __asm__ __volatile__( - EIEIO_ON_SMP -"1: lwarx %0,0,%1 # atomic_inc_return\n\ - addic %0,%0,1\n\ - stwcx. %0,0,%1\n\ - bne- 1b" - ISYNC_ON_SMP - : "=&r" (t) - : "r" (&v->counter) - : "cc", "memory"); - - return t; -} - -/* - * atomic_inc_and_test - increment and test - * @v: pointer of type atomic_t - * - * Atomically increments @v by 1 - * and returns true if the result is zero, or false for all - * other cases. - */ -#define atomic_inc_and_test(v) (atomic_inc_return(v) == 0) - -static __inline__ void atomic_dec(atomic_t *v) -{ - int t; - - __asm__ __volatile__( -"1: lwarx %0,0,%2 # atomic_dec\n\ - addic %0,%0,-1\n\ - stwcx. %0,0,%2\n\ - bne- 1b" - : "=&r" (t), "=m" (v->counter) - : "r" (&v->counter), "m" (v->counter) - : "cc"); -} - -static __inline__ int atomic_dec_return(atomic_t *v) -{ - int t; - - __asm__ __volatile__( - EIEIO_ON_SMP -"1: lwarx %0,0,%1 # atomic_dec_return\n\ - addic %0,%0,-1\n\ - stwcx. %0,0,%1\n\ - bne- 1b" - ISYNC_ON_SMP - : "=&r" (t) - : "r" (&v->counter) - : "cc", "memory"); - - return t; -} - -#define atomic_sub_and_test(a, v) (atomic_sub_return((a), (v)) == 0) -#define atomic_dec_and_test(v) (atomic_dec_return((v)) == 0) - -/* - * Atomically test *v and decrement if it is greater than 0. - * The function returns the old value of *v minus 1. - */ -static __inline__ int atomic_dec_if_positive(atomic_t *v) -{ - int t; - - __asm__ __volatile__( - EIEIO_ON_SMP -"1: lwarx %0,0,%1 # atomic_dec_if_positive\n\ - addic. %0,%0,-1\n\ - blt- 2f\n\ - stwcx. %0,0,%1\n\ - bne- 1b" - ISYNC_ON_SMP - "\n\ -2:" : "=&r" (t) - : "r" (&v->counter) - : "cc", "memory"); - - return t; -} - -#define smp_mb__before_atomic_dec() smp_mb() -#define smp_mb__after_atomic_dec() smp_mb() -#define smp_mb__before_atomic_inc() smp_mb() -#define smp_mb__after_atomic_inc() smp_mb() - -#endif /* _ASM_PPC64_ATOMIC_H_ */ diff --git a/include/asm-ppc64/bitops.h b/include/asm-ppc64/bitops.h --- a/include/asm-ppc64/bitops.h +++ b/include/asm-ppc64/bitops.h @@ -42,7 +42,7 @@ #ifdef __KERNEL__ -#include +#include /* * clear_bit doesn't imply a memory barrier diff --git a/include/asm-ppc64/futex.h b/include/asm-ppc64/futex.h --- a/include/asm-ppc64/futex.h +++ b/include/asm-ppc64/futex.h @@ -5,7 +5,7 @@ #include #include -#include +#include #include #define __futex_atomic_op(insn, ret, oldval, uaddr, oparg) \ diff --git a/include/asm-ppc64/io.h b/include/asm-ppc64/io.h --- a/include/asm-ppc64/io.h +++ b/include/asm-ppc64/io.h @@ -15,7 +15,7 @@ #ifdef CONFIG_PPC_ISERIES #include #endif -#include +#include #include #include diff --git a/include/asm-ppc64/memory.h b/include/asm-ppc64/memory.h deleted file mode 100644 --- a/include/asm-ppc64/memory.h +++ /dev/null @@ -1,61 +0,0 @@ -#ifndef _ASM_PPC64_MEMORY_H_ -#define _ASM_PPC64_MEMORY_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 - -/* - * Arguably the bitops and *xchg operations don't imply any memory barrier - * or SMP ordering, but in fact a lot of drivers expect them to imply - * both, since they do on x86 cpus. - */ -#ifdef CONFIG_SMP -#define EIEIO_ON_SMP "eieio\n" -#define ISYNC_ON_SMP "\n\tisync" -#define SYNC_ON_SMP "lwsync\n\t" -#else -#define EIEIO_ON_SMP -#define ISYNC_ON_SMP -#define SYNC_ON_SMP -#endif - -static inline void eieio(void) -{ - __asm__ __volatile__ ("eieio" : : : "memory"); -} - -static inline void isync(void) -{ - __asm__ __volatile__ ("isync" : : : "memory"); -} - -#ifdef CONFIG_SMP -#define eieio_on_smp() eieio() -#define isync_on_smp() isync() -#else -#define eieio_on_smp() __asm__ __volatile__("": : :"memory") -#define isync_on_smp() __asm__ __volatile__("": : :"memory") -#endif - -/* Macros for adjusting thread priority (hardware multi-threading) */ -#define HMT_very_low() asm volatile("or 31,31,31 # very low priority") -#define HMT_low() asm volatile("or 1,1,1 # low priority") -#define HMT_medium_low() asm volatile("or 6,6,6 # medium low priority") -#define HMT_medium() asm volatile("or 2,2,2 # medium priority") -#define HMT_medium_high() asm volatile("or 5,5,5 # medium high priority") -#define HMT_high() asm volatile("or 3,3,3 # high priority") - -#define HMT_VERY_LOW "\tor 31,31,31 # very low priority\n" -#define HMT_LOW "\tor 1,1,1 # low priority\n" -#define HMT_MEDIUM_LOW "\tor 6,6,6 # medium low priority\n" -#define HMT_MEDIUM "\tor 2,2,2 # medium priority\n" -#define HMT_MEDIUM_HIGH "\tor 5,5,5 # medium high priority\n" -#define HMT_HIGH "\tor 3,3,3 # high priority\n" - -#endif diff --git a/include/asm-ppc64/processor.h b/include/asm-ppc64/processor.h --- a/include/asm-ppc64/processor.h +++ b/include/asm-ppc64/processor.h @@ -368,6 +368,14 @@ GLUE(.,name): #define mfasr() ({unsigned long rval; \ asm volatile("mfasr %0" : "=r" (rval)); rval;}) +/* Macros for adjusting thread priority (hardware multi-threading) */ +#define HMT_very_low() asm volatile("or 31,31,31 # very low priority") +#define HMT_low() asm volatile("or 1,1,1 # low priority") +#define HMT_medium_low() asm volatile("or 6,6,6 # medium low priority") +#define HMT_medium() asm volatile("or 2,2,2 # medium priority") +#define HMT_medium_high() asm volatile("or 5,5,5 # medium high priority") +#define HMT_high() asm volatile("or 3,3,3 # high priority") + static inline void set_tb(unsigned int upper, unsigned int lower) { mttbl(0); diff --git a/include/asm-ppc64/system.h b/include/asm-ppc64/system.h --- a/include/asm-ppc64/system.h +++ b/include/asm-ppc64/system.h @@ -13,7 +13,7 @@ #include #include #include -#include +#include /* * Memory barrier. @@ -48,7 +48,7 @@ #ifdef CONFIG_SMP #define smp_mb() mb() #define smp_rmb() rmb() -#define smp_wmb() __asm__ __volatile__ ("eieio" : : : "memory") +#define smp_wmb() eieio() #define smp_read_barrier_depends() read_barrier_depends() #else #define smp_mb() __asm__ __volatile__("": : :"memory") From jdl at freescale.com Fri Sep 23 05:55:30 2005 From: jdl at freescale.com (Jon Loeliger) Date: Thu, 22 Sep 2005 14:55:30 -0500 Subject: PATCH powerpc Merge asm-ppc*/rwsem.h Message-ID: Merge asm-ppc*/rwsem.h into include/asm-powerpc. Removed smp_*mb() memory barriers from the ppc32 code as they are now burried in the atomic_*() functions as suggested by Paul, implemented by Arnd, and pushed out by Becky. I am not the droid you are looking for. This patch depends on Becky's atomic.h merge patch. Signed-off-by: Jon Loeliger Signed-off-by: Kumar Gala --- include/asm-powerpc/rwsem.h | 163 +++++++++++++++++++++++++++++++++++++++++ include/asm-ppc/rwsem.h | 172 ------------------------------------------- include/asm-ppc64/rwsem.h | 167 ------------------------------------------ 3 files changed, 163 insertions(+), 339 deletions(-) diff --git a/include/asm-powerpc/rwsem.h b/include/asm-powerpc/rwsem.h new file mode 100644 --- /dev/null +++ b/include/asm-powerpc/rwsem.h @@ -0,0 +1,163 @@ +#ifndef _ASM_POWERPC_RWSEM_H +#define _ASM_POWERPC_RWSEM_H + +#ifdef __KERNEL__ + +/* + * include/asm-ppc64/rwsem.h: R/W semaphores for PPC using the stuff + * in lib/rwsem.c. Adapted largely from include/asm-i386/rwsem.h + * by Paul Mackerras . + */ + +#include +#include +#include +#include + +/* + * the semaphore definition + */ +struct rw_semaphore { + /* XXX this should be able to be an atomic_t -- paulus */ + signed int count; +#define RWSEM_UNLOCKED_VALUE 0x00000000 +#define RWSEM_ACTIVE_BIAS 0x00000001 +#define RWSEM_ACTIVE_MASK 0x0000ffff +#define RWSEM_WAITING_BIAS (-0x00010000) +#define RWSEM_ACTIVE_READ_BIAS RWSEM_ACTIVE_BIAS +#define RWSEM_ACTIVE_WRITE_BIAS (RWSEM_WAITING_BIAS + RWSEM_ACTIVE_BIAS) + spinlock_t wait_lock; + struct list_head wait_list; +#if RWSEM_DEBUG + int debug; +#endif +}; + +/* + * initialisation + */ +#if RWSEM_DEBUG +#define __RWSEM_DEBUG_INIT , 0 +#else +#define __RWSEM_DEBUG_INIT /* */ +#endif + +#define __RWSEM_INITIALIZER(name) \ + { RWSEM_UNLOCKED_VALUE, SPIN_LOCK_UNLOCKED, \ + LIST_HEAD_INIT((name).wait_list) \ + __RWSEM_DEBUG_INIT } + +#define DECLARE_RWSEM(name) \ + struct rw_semaphore name = __RWSEM_INITIALIZER(name) + +extern struct rw_semaphore *rwsem_down_read_failed(struct rw_semaphore *sem); +extern struct rw_semaphore *rwsem_down_write_failed(struct rw_semaphore *sem); +extern struct rw_semaphore *rwsem_wake(struct rw_semaphore *sem); +extern struct rw_semaphore *rwsem_downgrade_wake(struct rw_semaphore *sem); + +static inline void init_rwsem(struct rw_semaphore *sem) +{ + sem->count = RWSEM_UNLOCKED_VALUE; + spin_lock_init(&sem->wait_lock); + INIT_LIST_HEAD(&sem->wait_list); +#if RWSEM_DEBUG + sem->debug = 0; +#endif +} + +/* + * lock for reading + */ +static inline void __down_read(struct rw_semaphore *sem) +{ + if (unlikely(atomic_inc_return((atomic_t *)(&sem->count)) <= 0)) + rwsem_down_read_failed(sem); +} + +static inline int __down_read_trylock(struct rw_semaphore *sem) +{ + int tmp; + + while ((tmp = sem->count) >= 0) { + if (tmp == cmpxchg(&sem->count, tmp, + tmp + RWSEM_ACTIVE_READ_BIAS)) { + return 1; + } + } + return 0; +} + +/* + * lock for writing + */ +static inline void __down_write(struct rw_semaphore *sem) +{ + int tmp; + + tmp = atomic_add_return(RWSEM_ACTIVE_WRITE_BIAS, + (atomic_t *)(&sem->count)); + if (unlikely(tmp != RWSEM_ACTIVE_WRITE_BIAS)) + rwsem_down_write_failed(sem); +} + +static inline int __down_write_trylock(struct rw_semaphore *sem) +{ + int tmp; + + tmp = cmpxchg(&sem->count, RWSEM_UNLOCKED_VALUE, + RWSEM_ACTIVE_WRITE_BIAS); + return tmp == RWSEM_UNLOCKED_VALUE; +} + +/* + * unlock after reading + */ +static inline void __up_read(struct rw_semaphore *sem) +{ + int tmp; + + tmp = atomic_dec_return((atomic_t *)(&sem->count)); + if (unlikely(tmp < -1 && (tmp & RWSEM_ACTIVE_MASK) == 0)) + rwsem_wake(sem); +} + +/* + * unlock after writing + */ +static inline void __up_write(struct rw_semaphore *sem) +{ + if (unlikely(atomic_sub_return(RWSEM_ACTIVE_WRITE_BIAS, + (atomic_t *)(&sem->count)) < 0)) + rwsem_wake(sem); +} + +/* + * implement atomic add functionality + */ +static inline void rwsem_atomic_add(int delta, struct rw_semaphore *sem) +{ + atomic_add(delta, (atomic_t *)(&sem->count)); +} + +/* + * downgrade write lock to read lock + */ +static inline void __downgrade_write(struct rw_semaphore *sem) +{ + int tmp; + + tmp = atomic_add_return(-RWSEM_WAITING_BIAS, (atomic_t *)(&sem->count)); + if (tmp < 0) + rwsem_downgrade_wake(sem); +} + +/* + * implement exchange and add functionality + */ +static inline int rwsem_atomic_update(int delta, struct rw_semaphore *sem) +{ + return atomic_add_return(delta, (atomic_t *)(&sem->count)); +} + +#endif /* __KERNEL__ */ +#endif /* _ASM_POWERPC_RWSEM_H */ diff --git a/include/asm-ppc/rwsem.h b/include/asm-ppc/rwsem.h deleted file mode 100644 --- a/include/asm-ppc/rwsem.h +++ /dev/null @@ -1,172 +0,0 @@ -/* - * include/asm-ppc/rwsem.h: R/W semaphores for PPC using the stuff - * in lib/rwsem.c. Adapted largely from include/asm-i386/rwsem.h - * by Paul Mackerras . - */ - -#ifndef _PPC_RWSEM_H -#define _PPC_RWSEM_H - -#ifdef __KERNEL__ -#include -#include -#include -#include - -/* - * the semaphore definition - */ -struct rw_semaphore { - /* XXX this should be able to be an atomic_t -- paulus */ - signed long count; -#define RWSEM_UNLOCKED_VALUE 0x00000000 -#define RWSEM_ACTIVE_BIAS 0x00000001 -#define RWSEM_ACTIVE_MASK 0x0000ffff -#define RWSEM_WAITING_BIAS (-0x00010000) -#define RWSEM_ACTIVE_READ_BIAS RWSEM_ACTIVE_BIAS -#define RWSEM_ACTIVE_WRITE_BIAS (RWSEM_WAITING_BIAS + RWSEM_ACTIVE_BIAS) - spinlock_t wait_lock; - struct list_head wait_list; -#if RWSEM_DEBUG - int debug; -#endif -}; - -/* - * initialisation - */ -#if RWSEM_DEBUG -#define __RWSEM_DEBUG_INIT , 0 -#else -#define __RWSEM_DEBUG_INIT /* */ -#endif - -#define __RWSEM_INITIALIZER(name) \ - { RWSEM_UNLOCKED_VALUE, SPIN_LOCK_UNLOCKED, \ - LIST_HEAD_INIT((name).wait_list) \ - __RWSEM_DEBUG_INIT } - -#define DECLARE_RWSEM(name) \ - struct rw_semaphore name = __RWSEM_INITIALIZER(name) - -extern struct rw_semaphore *rwsem_down_read_failed(struct rw_semaphore *sem); -extern struct rw_semaphore *rwsem_down_write_failed(struct rw_semaphore *sem); -extern struct rw_semaphore *rwsem_wake(struct rw_semaphore *sem); -extern struct rw_semaphore *rwsem_downgrade_wake(struct rw_semaphore *sem); - -static inline void init_rwsem(struct rw_semaphore *sem) -{ - sem->count = RWSEM_UNLOCKED_VALUE; - spin_lock_init(&sem->wait_lock); - INIT_LIST_HEAD(&sem->wait_list); -#if RWSEM_DEBUG - sem->debug = 0; -#endif -} - -/* - * lock for reading - */ -static inline void __down_read(struct rw_semaphore *sem) -{ - if (atomic_inc_return((atomic_t *)(&sem->count)) > 0) - smp_wmb(); - else - rwsem_down_read_failed(sem); -} - -static inline int __down_read_trylock(struct rw_semaphore *sem) -{ - int tmp; - - while ((tmp = sem->count) >= 0) { - if (tmp == cmpxchg(&sem->count, tmp, - tmp + RWSEM_ACTIVE_READ_BIAS)) { - smp_wmb(); - return 1; - } - } - return 0; -} - -/* - * lock for writing - */ -static inline void __down_write(struct rw_semaphore *sem) -{ - int tmp; - - tmp = atomic_add_return(RWSEM_ACTIVE_WRITE_BIAS, - (atomic_t *)(&sem->count)); - if (tmp == RWSEM_ACTIVE_WRITE_BIAS) - smp_wmb(); - else - rwsem_down_write_failed(sem); -} - -static inline int __down_write_trylock(struct rw_semaphore *sem) -{ - int tmp; - - tmp = cmpxchg(&sem->count, RWSEM_UNLOCKED_VALUE, - RWSEM_ACTIVE_WRITE_BIAS); - smp_wmb(); - return tmp == RWSEM_UNLOCKED_VALUE; -} - -/* - * unlock after reading - */ -static inline void __up_read(struct rw_semaphore *sem) -{ - int tmp; - - smp_wmb(); - tmp = atomic_dec_return((atomic_t *)(&sem->count)); - if (tmp < -1 && (tmp & RWSEM_ACTIVE_MASK) == 0) - rwsem_wake(sem); -} - -/* - * unlock after writing - */ -static inline void __up_write(struct rw_semaphore *sem) -{ - smp_wmb(); - if (atomic_sub_return(RWSEM_ACTIVE_WRITE_BIAS, - (atomic_t *)(&sem->count)) < 0) - rwsem_wake(sem); -} - -/* - * implement atomic add functionality - */ -static inline void rwsem_atomic_add(int delta, struct rw_semaphore *sem) -{ - atomic_add(delta, (atomic_t *)(&sem->count)); -} - -/* - * downgrade write lock to read lock - */ -static inline void __downgrade_write(struct rw_semaphore *sem) -{ - int tmp; - - smp_wmb(); - tmp = atomic_add_return(-RWSEM_WAITING_BIAS, (atomic_t *)(&sem->count)); - if (tmp < 0) - rwsem_downgrade_wake(sem); -} - -/* - * implement exchange and add functionality - */ -static inline int rwsem_atomic_update(int delta, struct rw_semaphore *sem) -{ - smp_mb(); - return atomic_add_return(delta, (atomic_t *)(&sem->count)); -} - -#endif /* __KERNEL__ */ -#endif /* _PPC_RWSEM_XADD_H */ diff --git a/include/asm-ppc64/rwsem.h b/include/asm-ppc64/rwsem.h deleted file mode 100644 --- a/include/asm-ppc64/rwsem.h +++ /dev/null @@ -1,167 +0,0 @@ -/* - * include/asm-ppc64/rwsem.h: R/W semaphores for PPC using the stuff - * in lib/rwsem.c. Adapted largely from include/asm-i386/rwsem.h - * by Paul Mackerras . - * - * 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 _PPC64_RWSEM_H -#define _PPC64_RWSEM_H - -#ifdef __KERNEL__ -#include -#include -#include -#include - -/* - * the semaphore definition - */ -struct rw_semaphore { - /* XXX this should be able to be an atomic_t -- paulus */ - signed int count; -#define RWSEM_UNLOCKED_VALUE 0x00000000 -#define RWSEM_ACTIVE_BIAS 0x00000001 -#define RWSEM_ACTIVE_MASK 0x0000ffff -#define RWSEM_WAITING_BIAS (-0x00010000) -#define RWSEM_ACTIVE_READ_BIAS RWSEM_ACTIVE_BIAS -#define RWSEM_ACTIVE_WRITE_BIAS (RWSEM_WAITING_BIAS + RWSEM_ACTIVE_BIAS) - spinlock_t wait_lock; - struct list_head wait_list; -#if RWSEM_DEBUG - int debug; -#endif -}; - -/* - * initialisation - */ -#if RWSEM_DEBUG -#define __RWSEM_DEBUG_INIT , 0 -#else -#define __RWSEM_DEBUG_INIT /* */ -#endif - -#define __RWSEM_INITIALIZER(name) \ - { RWSEM_UNLOCKED_VALUE, SPIN_LOCK_UNLOCKED, \ - LIST_HEAD_INIT((name).wait_list) \ - __RWSEM_DEBUG_INIT } - -#define DECLARE_RWSEM(name) \ - struct rw_semaphore name = __RWSEM_INITIALIZER(name) - -extern struct rw_semaphore *rwsem_down_read_failed(struct rw_semaphore *sem); -extern struct rw_semaphore *rwsem_down_write_failed(struct rw_semaphore *sem); -extern struct rw_semaphore *rwsem_wake(struct rw_semaphore *sem); -extern struct rw_semaphore *rwsem_downgrade_wake(struct rw_semaphore *sem); - -static inline void init_rwsem(struct rw_semaphore *sem) -{ - sem->count = RWSEM_UNLOCKED_VALUE; - spin_lock_init(&sem->wait_lock); - INIT_LIST_HEAD(&sem->wait_list); -#if RWSEM_DEBUG - sem->debug = 0; -#endif -} - -/* - * lock for reading - */ -static inline void __down_read(struct rw_semaphore *sem) -{ - if (unlikely(atomic_inc_return((atomic_t *)(&sem->count)) <= 0)) - rwsem_down_read_failed(sem); -} - -static inline int __down_read_trylock(struct rw_semaphore *sem) -{ - int tmp; - - while ((tmp = sem->count) >= 0) { - if (tmp == cmpxchg(&sem->count, tmp, - tmp + RWSEM_ACTIVE_READ_BIAS)) { - return 1; - } - } - return 0; -} - -/* - * lock for writing - */ -static inline void __down_write(struct rw_semaphore *sem) -{ - int tmp; - - tmp = atomic_add_return(RWSEM_ACTIVE_WRITE_BIAS, - (atomic_t *)(&sem->count)); - if (unlikely(tmp != RWSEM_ACTIVE_WRITE_BIAS)) - rwsem_down_write_failed(sem); -} - -static inline int __down_write_trylock(struct rw_semaphore *sem) -{ - int tmp; - - tmp = cmpxchg(&sem->count, RWSEM_UNLOCKED_VALUE, - RWSEM_ACTIVE_WRITE_BIAS); - return tmp == RWSEM_UNLOCKED_VALUE; -} - -/* - * unlock after reading - */ -static inline void __up_read(struct rw_semaphore *sem) -{ - int tmp; - - tmp = atomic_dec_return((atomic_t *)(&sem->count)); - if (unlikely(tmp < -1 && (tmp & RWSEM_ACTIVE_MASK) == 0)) - rwsem_wake(sem); -} - -/* - * unlock after writing - */ -static inline void __up_write(struct rw_semaphore *sem) -{ - if (unlikely(atomic_sub_return(RWSEM_ACTIVE_WRITE_BIAS, - (atomic_t *)(&sem->count)) < 0)) - rwsem_wake(sem); -} - -/* - * implement atomic add functionality - */ -static inline void rwsem_atomic_add(int delta, struct rw_semaphore *sem) -{ - atomic_add(delta, (atomic_t *)(&sem->count)); -} - -/* - * downgrade write lock to read lock - */ -static inline void __downgrade_write(struct rw_semaphore *sem) -{ - int tmp; - - tmp = atomic_add_return(-RWSEM_WAITING_BIAS, (atomic_t *)(&sem->count)); - if (tmp < 0) - rwsem_downgrade_wake(sem); -} - -/* - * implement exchange and add functionality - */ -static inline int rwsem_atomic_update(int delta, struct rw_semaphore *sem) -{ - return atomic_add_return(delta, (atomic_t *)(&sem->count)); -} - -#endif /* __KERNEL__ */ -#endif /* _PPC_RWSEM_XADD_H */ From mjw at us.ibm.com Fri Sep 23 06:10:10 2005 From: mjw at us.ibm.com (Mike Wolf) Date: Thu, 22 Sep 2005 15:10:10 -0500 Subject: Does iSeries actually use vmlinux.sm? In-Reply-To: <4332FB18.3000700@am.sony.com> References: <4332FB18.3000700@am.sony.com> Message-ID: <43330FA2.80801@us.ltcfwd.linux.ibm.com> Geoff Levand wrote: >I was doing some more cleanups to arch/ppc64/Makefile and I see >this line in the current ppc64-2.6.git: > > boottargets-$(CONFIG_PPC_ISERIES) += vmlinux.sminitrd vmlinux.initrd vmlinux.sm > >But there is no make target to actually build vmlinux.sminitrd and >vmlinux.sm, and the only way to specify they be built is to put vmlinux.sm as a >target on the make command line. 'make' and 'make install' both will build >just vmlinux as here: > > bootimage-$(CONFIG_PPC_ISERIES) := vmlinux > defaultimage-$(CONFIG_PPC_ISERIES) := vmlinux > >My question is does PPC_ISERIES need these sm versions, and if so how to build >them, and if not, does a zImage and zImage.initrd make sense as build targets >for this platform? > > They are used with internal tools to debug legacy iseries. Tools like xmon and friends dont work on legacy iseries. You build them by making an initrd and copying the initrd to arch/ppc64/boot and then doing the make vmlinux.sm or vmlinux.sminitrd. >-Geoff > >_______________________________________________ >Linuxppc64-dev mailing list >Linuxppc64-dev at ozlabs.org >https://ozlabs.org/mailman/listinfo/linuxppc64-dev > > > From geoffrey.levand at am.sony.com Fri Sep 23 07:02:23 2005 From: geoffrey.levand at am.sony.com (Geoff Levand) Date: Thu, 22 Sep 2005 14:02:23 -0700 Subject: [PATCH] ppc64: Build zImage.vmode for G5 In-Reply-To: <1127187825.4386.44.camel@gaston> References: <1127187825.4386.44.camel@gaston> Message-ID: <43331BDF.1000901@am.sony.com> Benjamin Herrenschmidt wrote: > zImage.vmode was recently added. It's a version of zImage in which the > ELF note section used by open firmware indicates that it requires a > virtual mode instance of OF instead of real mode. This allows it to work > with Apple OF, and thus is directly bootable (or netbootable) from OF > command line. (Unfortunately, pSeries OF sort-of requires real mode and > Apple OF sort-of requires virtual mode, and both tend to be unhappy if > no notes section specifies the mode at all). > > However, we forgot to add zImage.vmode to the default G5 build. This > fixes it. > > Signed-off-by: Benjamin Herrenschmidt > > Index: linux-work/arch/ppc64/Makefile > =================================================================== > --- linux-work.orig/arch/ppc64/Makefile 2005-09-20 09:54:18.000000000 +1000 > +++ linux-work/arch/ppc64/Makefile 2005-09-20 11:57:22.000000000 +1000 > @@ -107,7 +107,7 @@ > $(Q)$(MAKE) $(build)=$(boot) BOOTIMAGE=$(BOOTIMAGE) $@ > > defaultimage-$(CONFIG_PPC_PSERIES) := zImage > -defaultimage-$(CONFIG_PPC_PMAC) := vmlinux > +defaultimage-$(CONFIG_PPC_PMAC) := zImage.vmode > defaultimage-$(CONFIG_PPC_MAPLE) := zImage > defaultimage-$(CONFIG_PPC_ISERIES) := vmlinux > KBUILD_IMAGE := $(defaultimage-y) > This is really just a half fix, since if you have say both CONFIG_PPC_PSERIES and CONFIG_PPC_PMAC, 'make install' will always install zImage.vmode, even for pSeries machines. I thought we could have a default platform in Kconfig as below, but it looks messy. Any ideas how we can fix this? Remember we need to handle cross building on different machines/archs. -Geoff choice prompt "Default Platform" depends on PPC_MULTIPLATFORM config PPC_DEFAULT_PSERIES depends on PPC_PSERIES bool " IBM pSeries & new iSeries" config PPC_DEFAULT_BPA depends on PPC_BPA bool " Broadband Processor Architecture" config PPC_DEFAULT_PMAC depends on PPC_PMAC bool " Apple G5 based machines" config PPC_DEFAULT_MAPLE depends on PPC_MAPLE bool " Maple 970FX Evaluation Board" endchoice -EOF From benh at kernel.crashing.org Fri Sep 23 08:38:30 2005 From: benh at kernel.crashing.org (Benjamin Herrenschmidt) Date: Fri, 23 Sep 2005 08:38:30 +1000 Subject: [PATCH] ppc64: Build zImage.vmode for G5 In-Reply-To: <43331BDF.1000901@am.sony.com> References: <1127187825.4386.44.camel@gaston> <43331BDF.1000901@am.sony.com> Message-ID: <1127428711.25837.17.camel@gaston> On Thu, 2005-09-22 at 14:02 -0700, Geoff Levand wrote: > This is really just a half fix, since if you have say both CONFIG_PPC_PSERIES > and CONFIG_PPC_PMAC, 'make install' will always install zImage.vmode, even for > pSeries machines. > > I thought we could have a default platform in Kconfig as below, but it looks > messy. Any ideas how we can fix this? Remember we need to handle cross > building on different machines/archs. Hrm... I don't like that much... I wonder what it would take to put some intelligence in the makefile to detect the machine you are running on and do the proper install.. Ben. From benh at kernel.crashing.org Fri Sep 23 08:43:54 2005 From: benh at kernel.crashing.org (Benjamin Herrenschmidt) Date: Fri, 23 Sep 2005 08:43:54 +1000 Subject: [PATCH] ppc64: SMU partitions & device-tree In-Reply-To: <20050922152921.GN3560@otto> References: <1127354464.32344.10.camel@gaston> <20050922152921.GN3560@otto> Message-ID: <1127429034.25837.20.camel@gaston> On Thu, 2005-09-22 at 10:29 -0500, Nathan Lynch wrote: > > I think this is abusing devtree_lock, which is meant to protect > traversal of the device tree and not the contents of nodes. True, > this serializes prom_add_property itself, and will prevent corruption > of the node's property list. But I think I'd rather the SMU code take > care of this itself, i.e. use its own mutex to serialize the addition > of properties to /smu. It does, but I felt like prom_add_property() should be made a bit safer. It's definitely an abuse of the devtree_lock, but knowing how rarely prom_add_property() is to be called, I don't think it's that much of a problem, what do you think ? Ben. From benh at kernel.crashing.org Fri Sep 23 08:55:54 2005 From: benh at kernel.crashing.org (Benjamin Herrenschmidt) Date: Fri, 23 Sep 2005 08:55:54 +1000 Subject: BUG: 2.6.14-rc2 sets the wrong time in NVRAM on PowerMac G5 In-Reply-To: <20050922110828.GB7120@iucha.net> References: <20050922110828.GB7120@iucha.net> Message-ID: <1127429754.25837.32.camel@gaston> On Thu, 2005-09-22 at 06:08 -0500, Florin Iucha wrote: > > florin at zeus$ dmesg | grep "Linux version" > Linux version 2.6.14-rc2 (root at zeus) (gcc version 4.0.2 20050808 > (prerelease) (Ubuntu 4.0.1-4ubuntu8)) #1 SMP Tue Sep 20 17:24:52 > CDT 2005 Hrm... this is a PMU based machine right ? I don't think we changed anything to that code... Can you try isolating the specific patch that causes the breakage ? Ben. From benh at kernel.crashing.org Fri Sep 23 09:59:48 2005 From: benh at kernel.crashing.org (Benjamin Herrenschmidt) Date: Fri, 23 Sep 2005 09:59:48 +1000 Subject: [PATCH] ppc64: Build zImage.vmode for G5 In-Reply-To: <43334383.8@am.sony.com> References: <1127187825.4386.44.camel@gaston> <43331BDF.1000901@am.sony.com> <1127428711.25837.17.camel@gaston> <43334383.8@am.sony.com> Message-ID: <1127433589.2035.0.camel@gaston> > Host detection won't work in general. It won't handle cross building on say > a PC with INSTALL_MOD_PATH and INSTALL_PATH set. 'make install' should work > as expected in this case. That's what I meant by handle cross building. Then I don't really see a solution except installing both images all the time... yet another config option is just horrible imho. Ben. From geoffrey.levand at am.sony.com Fri Sep 23 09:51:31 2005 From: geoffrey.levand at am.sony.com (Geoff Levand) Date: Thu, 22 Sep 2005 16:51:31 -0700 Subject: [PATCH] ppc64: Build zImage.vmode for G5 In-Reply-To: <1127428711.25837.17.camel@gaston> References: <1127187825.4386.44.camel@gaston> <43331BDF.1000901@am.sony.com> <1127428711.25837.17.camel@gaston> Message-ID: <43334383.8@am.sony.com> Benjamin Herrenschmidt wrote: > On Thu, 2005-09-22 at 14:02 -0700, Geoff Levand wrote: > > >>This is really just a half fix, since if you have say both CONFIG_PPC_PSERIES >>and CONFIG_PPC_PMAC, 'make install' will always install zImage.vmode, even for >>pSeries machines. >> >>I thought we could have a default platform in Kconfig as below, but it looks >>messy. Any ideas how we can fix this? Remember we need to handle cross >>building on different machines/archs. > > > Hrm... I don't like that much... I wonder what it would take to put some > intelligence in the makefile to detect the machine you are running on > and do the proper install.. > Host detection won't work in general. It won't handle cross building on say a PC with INSTALL_MOD_PATH and INSTALL_PATH set. 'make install' should work as expected in this case. That's what I meant by handle cross building. -Geoff From arnd at arndb.de Fri Sep 23 10:26:04 2005 From: arnd at arndb.de (Arnd Bergmann) Date: Fri, 23 Sep 2005 02:26:04 +0200 Subject: [patch 10/11] spufs: new entries for SPU special purpose registers. In-Reply-To: <2a9e5c407bfb32944a179d255306bce2@bga.com> References: <20050916121646.387617000@localhost> <20050916123314.704421000@localhost> <2a9e5c407bfb32944a179d255306bce2@bga.com> Message-ID: <200509230226.04908.arnd@arndb.de> On Dunnersdag 22 September 2005 20:44, Milton Miller wrote: > Another style that is frequently used throught out the kernel and often > results in smaller code gen is to set ret and goto the exit path. The > compiler can then reuse the function call code. > > Something like this (untested): > > +static ssize_t > +spufs_fpcr_read(struct file *file, char __user * buffer, > + size_t size, loff_t * pos) > +{ > + struct spu_context *ctx = file->private_data; > + struct spu_lscsa *lscsa = ctx->csa.lscsa; > + int ret; > + > + spu_acquire_saved(ctx); > + if (ctx->state == SPU_STATE_LOCKED) { > + ret = -EAGAIN; > + goto release; > + } > + > + ret = simple_read_from_buffer(buffer, size, pos, > + &lscsa->fpcr, sizeof(lscsa->fpcr)); > + > + release: > + spu_release(ctx); > + return ret; > +} > > A further changed use less pervasively puts the setting of ret before > the if, so the body is a simple goto. I haven't looked at how the > resulting code compares. Yes, you're absolutely right here. I usually prefer that style as well and it is a trivial change. > Also, do we expect the state to be locked? Maybe that should be made > unlikely(). That may also improve the resulting code. I don't like to put unlikely()/likely() into places that are not performance critical. This function is only called for debugging purposes and _very_ slow already because of the spu_acquire_saved overhead, so I'd rather go for simplicity. Thinking about this some more, I'm also not sure if -EAGAIN makes sense in the first place. SPU_STATE_LOCKED is only used if we can't use sparsemem for dynamic mmaps of /spu/*/mem, and in that case accessing fpcr or regs will not work again on the same spu. Maybe -EINVAL is better here. Arnd <>< From anton at samba.org Fri Sep 23 12:53:44 2005 From: anton at samba.org (Anton Blanchard) Date: Fri, 23 Sep 2005 12:53:44 +1000 Subject: [PATCH] ppc64: Fix build with iommu debug enabled In-Reply-To: <20050923025231.GA19971@krispykreme> References: <20050923025231.GA19971@krispykreme> Message-ID: <20050923025344.GB19971@krispykreme> Fix build when iommu debug is enabled. Signed-off-by: Anton Blanchard --- Index: build/arch/ppc64/kernel/pSeries_iommu.c =================================================================== --- build.orig/arch/ppc64/kernel/pSeries_iommu.c 2005-09-22 11:42:10.000000000 +1000 +++ build/arch/ppc64/kernel/pSeries_iommu.c 2005-09-22 11:47:38.000000000 +1000 @@ -364,7 +364,8 @@ while (pci->phb->dma_window_size * children > 0x80000000ul) pci->phb->dma_window_size >>= 1; - DBG("No ISA/IDE, window size is %x\n", pci->phb->dma_window_size); + DBG("No ISA/IDE, window size is 0x%lx\n", + pci->phb->dma_window_size); pci->phb->dma_window_base_cur = 0; return; @@ -388,7 +389,7 @@ while (pci->phb->dma_window_size * children > 0x70000000ul) pci->phb->dma_window_size >>= 1; - DBG("ISA/IDE, window size is %x\n", pci->phb->dma_window_size); + DBG("ISA/IDE, window size is 0x%lx\n", pci->phb->dma_window_size); } @@ -442,7 +443,7 @@ struct device_node *dn, *mydn; struct iommu_table *tbl; - DBG("iommu_dev_setup_pSeries, dev %p (%s)\n", dev, dev->pretty_name); + DBG("iommu_dev_setup_pSeries, dev %p (%s)\n", dev, pci_name(dev)); mydn = dn = pci_device_to_OF_node(dev); @@ -469,7 +470,7 @@ 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); + DBG("iommu_dev_setup_pSeries, dev %p (%s) has no iommu table\n", dev, pci_name(dev)); } } @@ -503,7 +504,7 @@ int *dma_window = NULL; struct pci_dn *pci; - DBG("iommu_dev_setup_pSeriesLP, dev %p (%s)\n", dev, dev->pretty_name); + DBG("iommu_dev_setup_pSeriesLP, dev %p (%s)\n", dev, pci_name(dev)); /* dev setup for LPAR is a little tricky, since the device tree might * contain the dma-window properties per-device and not neccesarily From anton at samba.org Fri Sep 23 12:52:31 2005 From: anton at samba.org (Anton Blanchard) Date: Fri, 23 Sep 2005 12:52:31 +1000 Subject: [PATCH] ppc64: Fix LPAR regression Message-ID: <20050923025231.GA19971@krispykreme> Hi, The recent iommu fix broke booting on some POWER4 and POWER5 LPAR boxes. It looks like we have been calling the non LPAR iommu_dev_setup on LPAR machines for a while. The recent iommu fix caused that code path to fail. It looks like we just need to hook up the devices iommu_table to the parents one, so do that instead of calling iommu_dev_setup_pSeries and crossing the streams. Signed-off-by: Anton Blanchard --- Index: build/arch/ppc64/kernel/pSeries_iommu.c =================================================================== --- build.orig/arch/ppc64/kernel/pSeries_iommu.c 2005-09-23 11:37:40.000000000 +1000 +++ build/arch/ppc64/kernel/pSeries_iommu.c 2005-09-23 12:08:45.000000000 +1000 @@ -526,9 +526,8 @@ * slots on POWER4 machines. */ if (dma_window == NULL || pdn->parent == NULL) { - /* Fall back to regular (non-LPAR) dev setup */ - DBG("No dma window for device, falling back to regular setup\n"); - iommu_dev_setup_pSeries(dev); + DBG("No dma window for device, linking to parent\n"); + PCI_DN(dn)->iommu_table = PCI_DN(pdn)->iommu_table; return; } else { DBG("Found DMA window, allocating table\n"); From anton at samba.org Fri Sep 23 12:56:42 2005 From: anton at samba.org (Anton Blanchard) Date: Fri, 23 Sep 2005 12:56:42 +1000 Subject: [PATCH] ppc64: Fix 64bit ptrace DABR support Message-ID: <20050923025642.GC19971@krispykreme> Fix my stupid bug in the 64bit version of PTRACE_SET_DEBUGREG. Signed-off-by: Anton Blanchard --- Index: build/arch/ppc64/kernel/ptrace.c =================================================================== --- build.orig/arch/ppc64/kernel/ptrace.c 2005-09-15 17:33:46.000000000 +1000 +++ build/arch/ppc64/kernel/ptrace.c 2005-09-20 13:42:15.000000000 +1000 @@ -219,6 +219,7 @@ case PTRACE_SET_DEBUGREG: ret = ptrace_set_debugreg(child, addr, data); + break; case PTRACE_DETACH: ret = ptrace_detach(child, data); From benh at kernel.crashing.org Fri Sep 23 15:15:45 2005 From: benh at kernel.crashing.org (Benjamin Herrenschmidt) Date: Fri, 23 Sep 2005 15:15:45 +1000 Subject: Hugetlb HPTE hashing weirdness In-Reply-To: <1127397747.13899.9.camel@localhost.localdomain> References: <1127326966.22154.55.camel@localhost.localdomain> <1127345278.15276.0.camel@gaston> <1127397747.13899.9.camel@localhost.localdomain> Message-ID: <1127452545.27674.1.camel@gaston> > Attached is my somewhat hacky hugetlb test suite. Build it with 'make > all'. I've been reproducing with: > for i in `seq 1 10`; do ./mmap-gettest 1 10; done > After about the third or fourth iteration, you should start to see test > failures. What machine do you use ? I can reproduce the problem on a g5 here but strangely not on any LPAR machine I've tested so far (all POWER5)... I did find a bug in the hugepage code though I doubt it's the culprit, I'll test a fix on the g5. Ben. From ntl at pobox.com Fri Sep 23 15:50:12 2005 From: ntl at pobox.com (Nathan Lynch) Date: Fri, 23 Sep 2005 00:50:12 -0500 Subject: [PATCH] ppc64: SMU partitions & device-tree In-Reply-To: <1127429034.25837.20.camel@gaston> References: <1127354464.32344.10.camel@gaston> <20050922152921.GN3560@otto> <1127429034.25837.20.camel@gaston> Message-ID: <20050923055012.GP3560@otto> Benjamin Herrenschmidt wrote: > On Thu, 2005-09-22 at 10:29 -0500, Nathan Lynch wrote: > > > > > I think this is abusing devtree_lock, which is meant to protect > > traversal of the device tree and not the contents of nodes. True, > > this serializes prom_add_property itself, and will prevent corruption > > of the node's property list. But I think I'd rather the SMU code take > > care of this itself, i.e. use its own mutex to serialize the addition > > of properties to /smu. > > It does, but I felt like prom_add_property() should be made a bit safer. > It's definitely an abuse of the devtree_lock, but knowing how rarely > prom_add_property() is to be called, I don't think it's that much of a > problem, what do you think ? As long as you don't expect us to need to _remove_ properties from live nodes, I think it's ok. Otherwise we'll need something like a per-node lock. From benh at kernel.crashing.org Fri Sep 23 16:07:10 2005 From: benh at kernel.crashing.org (Benjamin Herrenschmidt) Date: Fri, 23 Sep 2005 16:07:10 +1000 Subject: [PATCH] ppc64: SMU partitions & device-tree In-Reply-To: <20050923055012.GP3560@otto> References: <1127354464.32344.10.camel@gaston> <20050922152921.GN3560@otto> <1127429034.25837.20.camel@gaston> <20050923055012.GP3560@otto> Message-ID: <1127455630.27674.10.camel@gaston> > > It does, but I felt like prom_add_property() should be made a bit safer. > > It's definitely an abuse of the devtree_lock, but knowing how rarely > > prom_add_property() is to be called, I don't think it's that much of a > > problem, what do you think ? > > As long as you don't expect us to need to _remove_ properties from > live nodes, I think it's ok. Otherwise we'll need something like a > per-node lock. Yup, I don't expect to allow any property removal, nor to have this property addition be more than an occasional matter. I just want to make 100% sure to guard against duplicate additions. In my current SMU driver, this is protected by a semaphore though, but heh... Ben. From benh at kernel.crashing.org Fri Sep 23 16:25:26 2005 From: benh at kernel.crashing.org (Benjamin Herrenschmidt) Date: Fri, 23 Sep 2005 16:25:26 +1000 Subject: [PATCH] ppc64: Fix huge pages MMU mapping bug Message-ID: <1127456726.27674.15.camel@gaston> Current kernel has a couple of sneaky bugs in the ppc64 hugetlb code that cause huge pages to be potentially left stale in the hash table and TLBs (improperly invalidated), with all the nasty consequences that can have. One is that we forgot to set the "secondary" bit in the hash PTEs when hashing a huge page in the secondary bucket (fortunately very rare). The other one is on non-LPAR machines (like Apple G5s), flush_hash_range() which is used to flush a batch of PTEs simply did not work for huge pages. Historically, our huge page code didn't batch, but this was changed without fixing this routine. This patch fixes both. Signed-off-by: Benjamin Herrenschmidt Index: linux-work/arch/ppc64/mm/hugetlbpage.c =================================================================== --- linux-work.orig/arch/ppc64/mm/hugetlbpage.c 2005-09-23 14:08:34.000000000 +1000 +++ linux-work/arch/ppc64/mm/hugetlbpage.c 2005-09-23 16:11:44.000000000 +1000 @@ -710,10 +710,13 @@ hpte_group = ((~hash & htab_hash_mask) * HPTES_PER_GROUP) & ~0x7UL; slot = ppc_md.hpte_insert(hpte_group, va, prpn, - HPTE_V_LARGE, rflags); + HPTE_V_LARGE | + HPTE_V_SECONDARY, + rflags); if (slot == -1) { if (mftb() & 0x1) - hpte_group = ((hash & htab_hash_mask) * HPTES_PER_GROUP) & ~0x7UL; + hpte_group = ((hash & htab_hash_mask) * + HPTES_PER_GROUP)&~0x7UL; ppc_md.hpte_remove(hpte_group); goto repeat; Index: linux-work/arch/ppc64/mm/hash_native.c =================================================================== --- linux-work.orig/arch/ppc64/mm/hash_native.c 2005-09-23 12:43:22.000000000 +1000 +++ linux-work/arch/ppc64/mm/hash_native.c 2005-09-23 16:13:31.000000000 +1000 @@ -343,9 +343,7 @@ hpte_t *hptep; unsigned long hpte_v; struct ppc64_tlb_batch *batch = &__get_cpu_var(ppc64_tlb_batch); - - /* XXX fix for large ptes */ - unsigned long large = 0; + unsigned long large; local_irq_save(flags); @@ -358,6 +356,7 @@ va = (vsid << 28) | (batch->addr[i] & 0x0fffffff); batch->vaddr[j] = va; + large = pte_huge(batch->pte[i]); if (large) vpn = va >> HPAGE_SHIFT; else From dhowells at redhat.com Fri Sep 23 17:32:20 2005 From: dhowells at redhat.com (David Howells) Date: Fri, 23 Sep 2005 08:32:20 +0100 Subject: PATCH powerpc Merge asm-ppc*/rwsem.h In-Reply-To: References: Message-ID: <606.1127460740@warthog.cambridge.redhat.com> Jon Loeliger wrote: > Merge asm-ppc*/rwsem.h into include/asm-powerpc. > Removed smp_*mb() memory barriers from the ppc32 code > as they are now burried in the atomic_*() functions as > suggested by Paul, implemented by Arnd, and pushed out > by Becky. I am not the droid you are looking for. rwsems on ppc64 should really be using a 64-bit counter, not a 32-bit counter, otherwise you limit the maximum number of processes to 32K-ish. The counter should be "signed long" really. David From anton at samba.org Fri Sep 23 17:44:13 2005 From: anton at samba.org (Anton Blanchard) Date: Fri, 23 Sep 2005 17:44:13 +1000 Subject: PATCH powerpc Merge asm-ppc*/rwsem.h In-Reply-To: <606.1127460740@warthog.cambridge.redhat.com> References: <606.1127460740@warthog.cambridge.redhat.com> Message-ID: <20050923074413.GD19971@krispykreme> > rwsems on ppc64 should really be using a 64-bit counter, not a 32-bit counter, > otherwise you limit the maximum number of processes to 32K-ish. > > The counter should be "signed long" really. Agreed, we should move to a 64bit count. Anton From dhowells at redhat.com Fri Sep 23 17:52:30 2005 From: dhowells at redhat.com (David Howells) Date: Fri, 23 Sep 2005 08:52:30 +0100 Subject: PATCH powerpc Merge asm-ppc*/rwsem.h In-Reply-To: <20050923074413.GD19971@krispykreme> References: <20050923074413.GD19971@krispykreme> <606.1127460740@warthog.cambridge.redhat.com> Message-ID: <1280.1127461950@warthog.cambridge.redhat.com> Anton Blanchard wrote: > > The counter should be "signed long" really. > > Agreed, we should move to a 64bit count. With a 64-bit counter, the constants should be: #define RWSEM_UNLOCKED_VALUE 0x0000000000000000L #define RWSEM_ACTIVE_BIAS 0x0000000000000001L #define RWSEM_ACTIVE_MASK 0x00000000ffffffffL #define RWSEM_WAITING_BIAS (-0x0000000100000000L) #define RWSEM_ACTIVE_READ_BIAS RWSEM_ACTIVE_BIAS #define RWSEM_ACTIVE_WRITE_BIAS (RWSEM_WAITING_BIAS + RWSEM_ACTIVE_BIAS) Just like in the asm-s390/rwsem.h. David From hch at lst.de Fri Sep 23 19:08:09 2005 From: hch at lst.de (Christoph Hellwig) Date: Fri, 23 Sep 2005 11:08:09 +0200 Subject: PATCH powerpc Merge asm-ppc*/seccomp.h In-Reply-To: References: <20050922183126.GA18853@lst.de> Message-ID: <20050923090809.GA31688@lst.de> On Thu, Sep 22, 2005 at 01:36:52PM -0500, Jon Loeliger wrote: > So, like, the other day Christoph Hellwig mumbled: > > > +#include > > > + > > > +#if defined(__powerpc64__) && !defined(TIF_32BIT) > > > +#error "unexpected TIF_32BIT on ppc64" > > > +#endif > > > > just kill this check, it's rather pointless > > OK. > > But keep the #include? It's actually the part > that is defining TIF_32BIT for ppc64 (indirectly > through linux/thread_info.h and asm/thread_info.h). > Won't those bits be needed still? I'm not sure. This header definitly doesn't need it, but I suspect seccompt.c expects to get it via this header. From jdl at freescale.com Fri Sep 23 22:52:03 2005 From: jdl at freescale.com (Jon Loeliger) Date: Fri, 23 Sep 2005 07:52:03 -0500 Subject: PATCH powerpc Merge asm-ppc*/rwsem.h In-Reply-To: Your message of "Fri, 23 Sep 2005 08:32:20 BST." <606.1127460740@warthog.cambridge.redhat.com> References: <606.1127460740@warthog.cambridge.redhat.com> Message-ID: So, like, the other day David Howells mumbled: > > rwsems on ppc64 should really be using a 64-bit counter, not a 32-bit counter > , > otherwise you limit the maximum number of processes to 32K-ish. > > The counter should be "signed long" really. No problem. I _can_ resubmit the patch with this fix. However, I am not certain that I should yet. But what do you wan to do with ppc32 land then? Leaving it a "signed long" will limit ppc32 land but not ppc64 folks. (No problem.) Or we can have it be "singed long long" for ppc32 to also get 64 bits. (Again, no problem.) Also, this begs the question of the comment from Paul: struct rw_semaphore { /* XXX this should be able to be an atomic_t -- paulus */ signed int count; Which, of course is: typedef struct { volatile int counter; } atomic_t; Changing the size of counter will cause bad sizes due to the actual treatment of count as an atomic_t. So. Should we, in fact, convert it to be an atomic_t and further dispense with the casts?: static inline void __down_write(struct rw_semaphore *sem) { int tmp; tmp = atomic_add_return(RWSEM_ACTIVE_WRITE_BIAS, (atomic_t *)(&sem->count)); And if we _do_ convert it to be an atomic_t, should _that_ be where the real type for count gets established? And finally, I've been working on merging header files under the vague guideline of "merge maintaining existing functionality/breakage". I've been trying NOT to introduce simultaneous "improvements" at the risk of breaking something. To that end, I ask if the request to make 'count' be 64-bits should be submitted as a follow on patch that stands on its own and can clean up around it as necessary? Or do you want it mixed in with this "merge" patch too? Just need to know the preferences. Thanks, jdl From jdl at freescale.com Fri Sep 23 22:54:52 2005 From: jdl at freescale.com (Jon Loeliger) Date: Fri, 23 Sep 2005 07:54:52 -0500 Subject: PATCH powerpc Merge asm-ppc*/seccomp.h In-Reply-To: Your message of "Fri, 23 Sep 2005 11:08:09 +0200." <20050923090809.GA31688@lst.de> References: <20050922183126.GA18853@lst.de> <20050923090809.GA31688@lst.de> Message-ID: So, like, the other day Christoph Hellwig mumbled: > > > > But keep the #include? It's actually the part > > that is defining TIF_32BIT for ppc64 (indirectly > > through linux/thread_info.h and asm/thread_info.h). > > Won't those bits be needed still? > > I'm not sure. This header definitly doesn't need it, but I suspect > seccompt.c expects to get it via this header. I dug around in this a bit. The nested includes here yield a fairly wide distribution of availability of TIF_32BIT. I'm hesitant to remove it in this "merge" patch, so I will leave its removal to a follow on patch/effort. New patch with #if test removed coming up. jdl From jdl at freescale.com Fri Sep 23 23:05:03 2005 From: jdl at freescale.com (Jon Loeliger) Date: Fri, 23 Sep 2005 08:05:03 -0500 Subject: PATCH powerpc Merge asm-ppc*/seccomp.h, drop TIF_32BIT check Message-ID: Merge asm-ppc*/seccomp.h. Drop TIF_32BIT check. Signed-off-by: Jon Loeliger Signed-off-by: Kumar Gala --- include/asm-powerpc/seccomp.h | 16 ++++++++++++++++ include/asm-ppc/seccomp.h | 10 ---------- include/asm-ppc64/seccomp.h | 21 --------------------- 3 files changed, 16 insertions(+), 31 deletions(-) diff --git a/include/asm-powerpc/seccomp.h b/include/asm-powerpc/seccomp.h new file mode 100644 --- /dev/null +++ b/include/asm-powerpc/seccomp.h @@ -0,0 +1,16 @@ +#ifndef _ASM_POWERPC_SECCOMP_H + +#include +#include + +#define __NR_seccomp_read __NR_read +#define __NR_seccomp_write __NR_write +#define __NR_seccomp_exit __NR_exit +#define __NR_seccomp_sigreturn __NR_rt_sigreturn + +#define __NR_seccomp_read_32 __NR_read +#define __NR_seccomp_write_32 __NR_write +#define __NR_seccomp_exit_32 __NR_exit +#define __NR_seccomp_sigreturn_32 __NR_sigreturn + +#endif /* _ASM_POWERPC_SECCOMP_H */ diff --git a/include/asm-ppc/seccomp.h b/include/asm-ppc/seccomp.h deleted file mode 100644 --- a/include/asm-ppc/seccomp.h +++ /dev/null @@ -1,10 +0,0 @@ -#ifndef _ASM_SECCOMP_H - -#include - -#define __NR_seccomp_read __NR_read -#define __NR_seccomp_write __NR_write -#define __NR_seccomp_exit __NR_exit -#define __NR_seccomp_sigreturn __NR_rt_sigreturn - -#endif /* _ASM_SECCOMP_H */ diff --git a/include/asm-ppc64/seccomp.h b/include/asm-ppc64/seccomp.h deleted file mode 100644 --- a/include/asm-ppc64/seccomp.h +++ /dev/null @@ -1,21 +0,0 @@ -#ifndef _ASM_SECCOMP_H - -#include /* already defines TIF_32BIT */ - -#ifndef TIF_32BIT -#error "unexpected TIF_32BIT on ppc64" -#endif - -#include - -#define __NR_seccomp_read __NR_read -#define __NR_seccomp_write __NR_write -#define __NR_seccomp_exit __NR_exit -#define __NR_seccomp_sigreturn __NR_rt_sigreturn - -#define __NR_seccomp_read_32 __NR_read -#define __NR_seccomp_write_32 __NR_write -#define __NR_seccomp_exit_32 __NR_exit -#define __NR_seccomp_sigreturn_32 __NR_sigreturn - -#endif /* _ASM_SECCOMP_H */ From dhowells at redhat.com Sat Sep 24 00:09:28 2005 From: dhowells at redhat.com (David Howells) Date: Fri, 23 Sep 2005 15:09:28 +0100 Subject: PATCH powerpc Merge asm-ppc*/rwsem.h In-Reply-To: References: <606.1127460740@warthog.cambridge.redhat.com> Message-ID: <23115.1127484568@warthog.cambridge.redhat.com> Jon Loeliger wrote: > No problem. I _can_ resubmit the patch with this fix. > However, I am not certain that I should yet. I'd suggest that you wait until the merge is complete, I think. > But what do you wan to do with ppc32 land then? > Leaving it a "signed long" will limit ppc32 land but > not ppc64 folks. (No problem.) I'd suggest "signed long" in both cases. A maximum of 32K processes on ppc32 is probably reasonable. > Also, this begs the question of the comment from Paul: > > struct rw_semaphore { > /* XXX this should be able to be an atomic_t -- paulus */ > signed int count; Paul can be wrong sometimes:-) Changing to atomic_t would leave the 32K process limit in place. > Changing the size of counter will cause bad sizes > due to the actual treatment of count as an atomic_t. You will not be able to use the standard atomic ops unless you increase them to 64-bits on ppc64. > And if we _do_ convert it to be an atomic_t, should _that_ > be where the real type for count gets established? You should not do that unless you increase atomic_t to 64-bits on ppc64. > And finally, I've been working on merging header files > under the vague guideline of "merge maintaining existing > functionality/breakage". I've been trying NOT to introduce > simultaneous "improvements" at the risk of breaking something. Sounds reasonable. > To that end, I ask if the request to make 'count' be 64-bits > should be submitted as a follow on patch that stands on its > own and can clean up around it as necessary? Or do you want > it mixed in with this "merge" patch too? Follow-on is fine. David From sexton at mc.com Sat Sep 24 00:27:49 2005 From: sexton at mc.com (Sexton, Matt) Date: Fri, 23 Sep 2005 10:27:49 -0400 Subject: (no subject) Message-ID: <92CB67C83EE773499A7F2F6EA7E3FC940F0E9D@ad-email1.ad.mc.com> I applied the two patches to 2.6.13-1, but am still the same kind of mapping problems. My test [as I described in an earlier e-mail] has a PCI device DMA data into a hugepage memory buffer, whose physical page addresses were obtained via get_user_pages(). The user process, which allocated the memory via mmap(), then checks the data. It's often seeing the data in the wrong page. Have there been any relevant changes since 2.6.13-1? Any suggestions for how I can provide more useful debugging information? Thanks, Matt From bgill at freescale.com Sat Sep 24 02:07:36 2005 From: bgill at freescale.com (Becky Bruce) Date: Fri, 23 Sep 2005 11:07:36 -0500 (CDT) Subject: [PATCH] powerpc: merge semaphore.h Message-ID: powerpc: Merge semaphore.h Adopted the ppc64 version of semaphore.h. The 32-bit version used smp_wmb(), but recent updates to atomic.h mean this is no longer required. The 64-bit version made use of unlikely(), which has been retained in the combined version. This patch requires the recent atomic.h patch. Signed-off-by: Becky Bruce Signed-off-by: Kumar Gala --- commit 76b1ba19ac14976b8cd288180bb939f429a70820 tree 330c84e832b71d9b803feaa340de40de689edc78 parent ab08c88845ac6e755db2ef806c36d1e469ef4180 author Becky Bruce Fri, 23 Sep 2005 11:01:14 -0500 committer Becky Bruce Fri, 23 Sep 2005 11:01:14 -0500 include/asm-powerpc/semaphore.h | 98 ++++++++++++++++++++++++++++++++++ include/asm-ppc/semaphore.h | 111 --------------------------------------- include/asm-ppc64/semaphore.h | 98 ---------------------------------- 3 files changed, 98 insertions(+), 209 deletions(-) diff --git a/include/asm-powerpc/semaphore.h b/include/asm-powerpc/semaphore.h new file mode 100644 --- /dev/null +++ b/include/asm-powerpc/semaphore.h @@ -0,0 +1,98 @@ +#ifndef _ASM_POWERPC_SEMAPHORE_H +#define _ASM_POWERPC_SEMAPHORE_H + +/* + * Remove spinlock-based RW semaphores; RW semaphore definitions are + * now in rwsem.h and we use the generic lib/rwsem.c implementation. + * Rework semaphores to use atomic_dec_if_positive. + * -- Paul Mackerras (paulus at samba.org) + */ + +#ifdef __KERNEL__ + +#include +#include +#include +#include + +struct semaphore { + /* + * Note that any negative value of count is equivalent to 0, + * but additionally indicates that some process(es) might be + * sleeping on `wait'. + */ + atomic_t count; + wait_queue_head_t wait; +}; + +#define __SEMAPHORE_INITIALIZER(name, n) \ +{ \ + .count = ATOMIC_INIT(n), \ + .wait = __WAIT_QUEUE_HEAD_INITIALIZER((name).wait) \ +} + +#define __MUTEX_INITIALIZER(name) \ + __SEMAPHORE_INITIALIZER(name, 1) + +#define __DECLARE_SEMAPHORE_GENERIC(name, count) \ + struct semaphore name = __SEMAPHORE_INITIALIZER(name,count) + +#define DECLARE_MUTEX(name) __DECLARE_SEMAPHORE_GENERIC(name, 1) +#define DECLARE_MUTEX_LOCKED(name) __DECLARE_SEMAPHORE_GENERIC(name, 0) + +static inline void sema_init (struct semaphore *sem, int val) +{ + atomic_set(&sem->count, val); + init_waitqueue_head(&sem->wait); +} + +static inline void init_MUTEX (struct semaphore *sem) +{ + sema_init(sem, 1); +} + +static inline void init_MUTEX_LOCKED (struct semaphore *sem) +{ + sema_init(sem, 0); +} + +extern void __down(struct semaphore * sem); +extern int __down_interruptible(struct semaphore * sem); +extern void __up(struct semaphore * sem); + +static inline void down(struct semaphore * sem) +{ + might_sleep(); + + /* + * Try to get the semaphore, take the slow path if we fail. + */ + if (unlikely(atomic_dec_return(&sem->count) < 0)) + __down(sem); +} + +static inline int down_interruptible(struct semaphore * sem) +{ + int ret = 0; + + might_sleep(); + + if (unlikely(atomic_dec_return(&sem->count) < 0)) + ret = __down_interruptible(sem); + return ret; +} + +static inline int down_trylock(struct semaphore * sem) +{ + return atomic_dec_if_positive(&sem->count) < 0; +} + +static inline void up(struct semaphore * sem) +{ + if (unlikely(atomic_inc_return(&sem->count) <= 0)) + __up(sem); +} + +#endif /* __KERNEL__ */ + +#endif /* _ASM_POWERPC_SEMAPHORE_H */ diff --git a/include/asm-ppc/semaphore.h b/include/asm-ppc/semaphore.h deleted file mode 100644 --- a/include/asm-ppc/semaphore.h +++ /dev/null @@ -1,111 +0,0 @@ -#ifndef _PPC_SEMAPHORE_H -#define _PPC_SEMAPHORE_H - -/* - * Swiped from asm-sparc/semaphore.h and modified - * -- Cort (cort at cs.nmt.edu) - * - * Stole some rw spinlock-based semaphore stuff from asm-alpha/semaphore.h - * -- Ani Joshi (ajoshi at unixbox.com) - * - * Remove spinlock-based RW semaphores; RW semaphore definitions are - * now in rwsem.h and we use the generic lib/rwsem.c implementation. - * Rework semaphores to use atomic_dec_if_positive. - * -- Paul Mackerras (paulus at samba.org) - */ - -#ifdef __KERNEL__ - -#include -#include -#include -#include - -struct semaphore { - /* - * Note that any negative value of count is equivalent to 0, - * but additionally indicates that some process(es) might be - * sleeping on `wait'. - */ - atomic_t count; - wait_queue_head_t wait; -}; - -#define __SEMAPHORE_INITIALIZER(name, n) \ -{ \ - .count = ATOMIC_INIT(n), \ - .wait = __WAIT_QUEUE_HEAD_INITIALIZER((name).wait) \ -} - -#define __MUTEX_INITIALIZER(name) \ - __SEMAPHORE_INITIALIZER(name, 1) - -#define __DECLARE_SEMAPHORE_GENERIC(name, count) \ - struct semaphore name = __SEMAPHORE_INITIALIZER(name,count) - -#define DECLARE_MUTEX(name) __DECLARE_SEMAPHORE_GENERIC(name, 1) -#define DECLARE_MUTEX_LOCKED(name) __DECLARE_SEMAPHORE_GENERIC(name, 0) - -static inline void sema_init (struct semaphore *sem, int val) -{ - atomic_set(&sem->count, val); - init_waitqueue_head(&sem->wait); -} - -static inline void init_MUTEX (struct semaphore *sem) -{ - sema_init(sem, 1); -} - -static inline void init_MUTEX_LOCKED (struct semaphore *sem) -{ - sema_init(sem, 0); -} - -extern void __down(struct semaphore * sem); -extern int __down_interruptible(struct semaphore * sem); -extern void __up(struct semaphore * sem); - -extern inline void down(struct semaphore * sem) -{ - might_sleep(); - - /* - * Try to get the semaphore, take the slow path if we fail. - */ - if (atomic_dec_return(&sem->count) < 0) - __down(sem); - smp_wmb(); -} - -extern inline int down_interruptible(struct semaphore * sem) -{ - int ret = 0; - - might_sleep(); - - if (atomic_dec_return(&sem->count) < 0) - ret = __down_interruptible(sem); - smp_wmb(); - return ret; -} - -extern inline int down_trylock(struct semaphore * sem) -{ - int ret; - - ret = atomic_dec_if_positive(&sem->count) < 0; - smp_wmb(); - return ret; -} - -extern inline void up(struct semaphore * sem) -{ - smp_wmb(); - if (atomic_inc_return(&sem->count) <= 0) - __up(sem); -} - -#endif /* __KERNEL__ */ - -#endif /* !(_PPC_SEMAPHORE_H) */ diff --git a/include/asm-ppc64/semaphore.h b/include/asm-ppc64/semaphore.h deleted file mode 100644 --- a/include/asm-ppc64/semaphore.h +++ /dev/null @@ -1,98 +0,0 @@ -#ifndef _PPC64_SEMAPHORE_H -#define _PPC64_SEMAPHORE_H - -/* - * Remove spinlock-based RW semaphores; RW semaphore definitions are - * now in rwsem.h and we use the generic lib/rwsem.c implementation. - * Rework semaphores to use atomic_dec_if_positive. - * -- Paul Mackerras (paulus at samba.org) - */ - -#ifdef __KERNEL__ - -#include -#include -#include -#include - -struct semaphore { - /* - * Note that any negative value of count is equivalent to 0, - * but additionally indicates that some process(es) might be - * sleeping on `wait'. - */ - atomic_t count; - wait_queue_head_t wait; -}; - -#define __SEMAPHORE_INITIALIZER(name, n) \ -{ \ - .count = ATOMIC_INIT(n), \ - .wait = __WAIT_QUEUE_HEAD_INITIALIZER((name).wait) \ -} - -#define __MUTEX_INITIALIZER(name) \ - __SEMAPHORE_INITIALIZER(name, 1) - -#define __DECLARE_SEMAPHORE_GENERIC(name, count) \ - struct semaphore name = __SEMAPHORE_INITIALIZER(name,count) - -#define DECLARE_MUTEX(name) __DECLARE_SEMAPHORE_GENERIC(name, 1) -#define DECLARE_MUTEX_LOCKED(name) __DECLARE_SEMAPHORE_GENERIC(name, 0) - -static inline void sema_init (struct semaphore *sem, int val) -{ - atomic_set(&sem->count, val); - init_waitqueue_head(&sem->wait); -} - -static inline void init_MUTEX (struct semaphore *sem) -{ - sema_init(sem, 1); -} - -static inline void init_MUTEX_LOCKED (struct semaphore *sem) -{ - sema_init(sem, 0); -} - -extern void __down(struct semaphore * sem); -extern int __down_interruptible(struct semaphore * sem); -extern void __up(struct semaphore * sem); - -static inline void down(struct semaphore * sem) -{ - might_sleep(); - - /* - * Try to get the semaphore, take the slow path if we fail. - */ - if (unlikely(atomic_dec_return(&sem->count) < 0)) - __down(sem); -} - -static inline int down_interruptible(struct semaphore * sem) -{ - int ret = 0; - - might_sleep(); - - if (unlikely(atomic_dec_return(&sem->count) < 0)) - ret = __down_interruptible(sem); - return ret; -} - -static inline int down_trylock(struct semaphore * sem) -{ - return atomic_dec_if_positive(&sem->count) < 0; -} - -static inline void up(struct semaphore * sem) -{ - if (unlikely(atomic_inc_return(&sem->count) <= 0)) - __up(sem); -} - -#endif /* __KERNEL__ */ - -#endif /* !(_PPC64_SEMAPHORE_H) */ From galak at freescale.com Sat Sep 24 02:15:27 2005 From: galak at freescale.com (Kumar Gala) Date: Fri, 23 Sep 2005 11:15:27 -0500 (CDT) Subject: [PATCH] ppc64: dont export PTRACE_{GET,SET}_DEBUGREG commands Message-ID: Paul, I would like to see this get into 2.6.14 until we close on this issue. - kumar -- Don't export to userspace until we come to a decision on how these commands are suppose to function for all variants of PowerPC with hardware debug resources. We additionally need to figure out a way to tell the debugger how many resources of each type exist. Signed-off-by: Kumar Gala --- commit 5b68986831be07fc105a3e9df2f720f238048fe4 tree 04ebab478347015a715243aeb081531e7fec29bb parent 0553f23baa3f66ce3fb9e63f0e33d171368905f6 author Kumar K. Gala Fri, 23 Sep 2005 11:13:41 -0500 committer Kumar K. Gala Fri, 23 Sep 2005 11:13:41 -0500 include/asm-ppc64/ptrace.h | 6 ++++++ 1 files changed, 6 insertions(+), 0 deletions(-) diff --git a/include/asm-ppc64/ptrace.h b/include/asm-ppc64/ptrace.h --- a/include/asm-ppc64/ptrace.h +++ b/include/asm-ppc64/ptrace.h @@ -193,8 +193,14 @@ extern unsigned long profile_pc(struct p * Get or set a debug register. The first 16 are DABR registers and the * second 16 are IABR registers. */ +#ifdef __KERNEL__ +/* + * Don't export to userspace until we decide what these are suppose to do + * for all PPCs and how to determine the actual number of breakpoint resources + */ #define PTRACE_GET_DEBUGREG 25 #define PTRACE_SET_DEBUGREG 26 +#endif /* Additional PTRACE requests implemented on PowerPC. */ #define PPC_PTRACE_GETREGS 0x99 /* Get GPRs 0 - 31 */ From kumar.gala at freescale.com Sat Sep 24 02:21:36 2005 From: kumar.gala at freescale.com (Kumar Gala) Date: Fri, 23 Sep 2005 11:21:36 -0500 Subject: moving math-emu Message-ID: Paul, I have a big patch that moves arch/ppc/math-emu to arch/powerpc/math- emu and fixes up the arch/ppc/Makefile. How do you want me to send this to you since its too big for the list or can you just make this change since its: 1. git rename arch/ppc/math-emu arch/powerpc/math-emu 2. fixup arch/ppc/Makefile so: core-$(CONFIG_MATH_EMULATION) += arch/powerpc/math-emu/ Let me know. - kumar From geoffrey.levand at am.sony.com Sat Sep 24 03:35:31 2005 From: geoffrey.levand at am.sony.com (Geoff Levand) Date: Fri, 23 Sep 2005 10:35:31 -0700 Subject: [PATCH] ppc64: Build zImage.vmode for G5 In-Reply-To: <1127433589.2035.0.camel@gaston> References: <1127433589.2035.0.camel@gaston> Message-ID: <43343CE3.1090205@am.sony.com> Benjamin Herrenschmidt wrote: >>Host detection won't work in general. It won't handle cross building > > on say > >>a PC with INSTALL_MOD_PATH and INSTALL_PATH set. 'make install' > > should work > >>as expected in this case. That's what I meant by handle cross > > building. > > Then I don't really see a solution except installing both images all the > time... yet another config option is just horrible imho. > But wait... Here's what I've come up with: +$(patsubst %,install-%,$(boottargets-y)) install-vmlinux: vmlinux + $(Q)$(MAKE) $(build)=$(boot) BOOTIMAGE=$(boot)/$(subst install-,,$@) install I think this will work. It would at least make PPC_MULTIPLATFORM usable: $ make INSTALL_MOD_PATH=/target/g5 INSTALL_PATH=/target/g5/boot install-zImage.vmode $ make INSTALL_MOD_PATH=/target/pseries INSTALL_PATH=/target/pseries/boot install-zImage I'll do some more testing and post the resulting patch. -Geoff From galak at freescale.com Sat Sep 24 05:08:58 2005 From: galak at freescale.com (Kumar Gala) Date: Fri, 23 Sep 2005 14:08:58 -0500 (CDT) Subject: [PATCH] powerpc: merged asm/cputable.h Message-ID: Merged cputable.h between ppc32 and ppc64. In doing this removed support for the BEGIN_FTR_SECTION/END_FTR_SECTION macros in C code since they dont compile correctly. C code should use cpu_has_feature(). This is based on Arnd Bergmann's initial patch. Signed-off-by: Kumar Gala --- commit a2b265b110663baeec179cd1443c86973ae4b8bb tree 1df8736108ae674ee0586624ef68deda6b381a0e parent 7b6e5f384e562218594b534460804e66408d2cb3 author Kumar K. Gala Fri, 23 Sep 2005 14:07:48 -0500 committer Kumar K. Gala Fri, 23 Sep 2005 14:07:48 -0500 arch/ppc/kernel/cputable.c | 399 ++++++++---------------------------- arch/ppc64/kernel/cputable.c | 82 ++----- include/asm-powerpc/cputable.h | 442 ++++++++++++++++++++++++++++++++++++++++ include/asm-ppc/cputable.h | 128 ------------ include/asm-ppc/mmu_context.h | 6 - include/asm-ppc64/cputable.h | 167 --------------- 6 files changed, 547 insertions(+), 677 deletions(-) diff --git a/arch/ppc/kernel/cputable.c b/arch/ppc/kernel/cputable.c --- a/arch/ppc/kernel/cputable.c +++ b/arch/ppc/kernel/cputable.c @@ -42,17 +42,6 @@ extern void __setup_cpu_generic(unsigned #define COMMON_PPC (PPC_FEATURE_32 | PPC_FEATURE_HAS_FPU | \ PPC_FEATURE_HAS_MMU) -/* We only set the altivec features if the kernel was compiled with altivec - * support - */ -#ifdef CONFIG_ALTIVEC -#define CPU_FTR_ALTIVEC_COMP CPU_FTR_ALTIVEC -#define PPC_FEATURE_ALTIVEC_COMP PPC_FEATURE_HAS_ALTIVEC -#else -#define CPU_FTR_ALTIVEC_COMP 0 -#define PPC_FEATURE_ALTIVEC_COMP 0 -#endif - /* We only set the spe features if the kernel was compiled with * spe support */ @@ -62,34 +51,13 @@ extern void __setup_cpu_generic(unsigned #define PPC_FEATURE_SPE_COMP 0 #endif -/* We need to mark all pages as being coherent if we're SMP or we - * have a 74[45]x and an MPC107 host bridge. - */ -#if defined(CONFIG_SMP) || defined(CONFIG_MPC10X_BRIDGE) -#define CPU_FTR_COMMON CPU_FTR_NEED_COHERENT -#else -#define CPU_FTR_COMMON 0 -#endif - -/* The powersave features NAP & DOZE seems to confuse BDI when - debugging. So if a BDI is used, disable theses - */ -#ifndef CONFIG_BDI_SWITCH -#define CPU_FTR_MAYBE_CAN_DOZE CPU_FTR_CAN_DOZE -#define CPU_FTR_MAYBE_CAN_NAP CPU_FTR_CAN_NAP -#else -#define CPU_FTR_MAYBE_CAN_DOZE 0 -#define CPU_FTR_MAYBE_CAN_NAP 0 -#endif - struct cpu_spec cpu_specs[] = { #if CLASSIC_PPC { /* 601 */ .pvr_mask = 0xffff0000, .pvr_value = 0x00010000, .cpu_name = "601", - .cpu_features = CPU_FTR_COMMON | CPU_FTR_601 | - CPU_FTR_HPTE_TABLE, + .cpu_features = CPU_FTRS_PPC601, .cpu_user_features = COMMON_PPC | PPC_FEATURE_601_INSTR | PPC_FEATURE_UNIFIED_CACHE, .icache_bsize = 32, @@ -100,9 +68,7 @@ struct cpu_spec cpu_specs[] = { .pvr_mask = 0xffff0000, .pvr_value = 0x00030000, .cpu_name = "603", - .cpu_features = CPU_FTR_COMMON | - CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_MAYBE_CAN_DOZE | - CPU_FTR_USE_TB | CPU_FTR_MAYBE_CAN_NAP, + .cpu_features = CPU_FTRS_603, .cpu_user_features = COMMON_PPC, .icache_bsize = 32, .dcache_bsize = 32, @@ -112,9 +78,7 @@ struct cpu_spec cpu_specs[] = { .pvr_mask = 0xffff0000, .pvr_value = 0x00060000, .cpu_name = "603e", - .cpu_features = CPU_FTR_COMMON | - CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_MAYBE_CAN_DOZE | - CPU_FTR_USE_TB | CPU_FTR_MAYBE_CAN_NAP, + .cpu_features = CPU_FTRS_603, .cpu_user_features = COMMON_PPC, .icache_bsize = 32, .dcache_bsize = 32, @@ -124,9 +88,7 @@ struct cpu_spec cpu_specs[] = { .pvr_mask = 0xffff0000, .pvr_value = 0x00070000, .cpu_name = "603ev", - .cpu_features = CPU_FTR_COMMON | - CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_MAYBE_CAN_DOZE | - CPU_FTR_USE_TB | CPU_FTR_MAYBE_CAN_NAP, + .cpu_features = CPU_FTRS_603, .cpu_user_features = COMMON_PPC, .icache_bsize = 32, .dcache_bsize = 32, @@ -136,9 +98,7 @@ struct cpu_spec cpu_specs[] = { .pvr_mask = 0xffff0000, .pvr_value = 0x00040000, .cpu_name = "604", - .cpu_features = CPU_FTR_COMMON | - CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | - CPU_FTR_604_PERF_MON | CPU_FTR_HPTE_TABLE, + .cpu_features = CPU_FTRS_604, .cpu_user_features = COMMON_PPC, .icache_bsize = 32, .dcache_bsize = 32, @@ -149,9 +109,7 @@ struct cpu_spec cpu_specs[] = { .pvr_mask = 0xfffff000, .pvr_value = 0x00090000, .cpu_name = "604e", - .cpu_features = CPU_FTR_COMMON | - CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | - CPU_FTR_604_PERF_MON | CPU_FTR_HPTE_TABLE, + .cpu_features = CPU_FTRS_604, .cpu_user_features = COMMON_PPC, .icache_bsize = 32, .dcache_bsize = 32, @@ -162,9 +120,7 @@ struct cpu_spec cpu_specs[] = { .pvr_mask = 0xffff0000, .pvr_value = 0x00090000, .cpu_name = "604r", - .cpu_features = CPU_FTR_COMMON | - CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | - CPU_FTR_604_PERF_MON | CPU_FTR_HPTE_TABLE, + .cpu_features = CPU_FTRS_604, .cpu_user_features = COMMON_PPC, .icache_bsize = 32, .dcache_bsize = 32, @@ -175,9 +131,7 @@ struct cpu_spec cpu_specs[] = { .pvr_mask = 0xffff0000, .pvr_value = 0x000a0000, .cpu_name = "604ev", - .cpu_features = CPU_FTR_COMMON | - CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | - CPU_FTR_604_PERF_MON | CPU_FTR_HPTE_TABLE, + .cpu_features = CPU_FTRS_604, .cpu_user_features = COMMON_PPC, .icache_bsize = 32, .dcache_bsize = 32, @@ -188,10 +142,7 @@ struct cpu_spec cpu_specs[] = { .pvr_mask = 0xffffffff, .pvr_value = 0x00084202, .cpu_name = "740/750", - .cpu_features = CPU_FTR_COMMON | - CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_MAYBE_CAN_DOZE | - CPU_FTR_USE_TB | CPU_FTR_L2CR | CPU_FTR_HPTE_TABLE | - CPU_FTR_MAYBE_CAN_NAP, + .cpu_features = CPU_FTRS_740_NOTAU, .cpu_user_features = COMMON_PPC, .icache_bsize = 32, .dcache_bsize = 32, @@ -202,10 +153,7 @@ struct cpu_spec cpu_specs[] = { .pvr_mask = 0xfffffff0, .pvr_value = 0x00080100, .cpu_name = "750CX", - .cpu_features = CPU_FTR_COMMON | - CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_MAYBE_CAN_DOZE | - CPU_FTR_USE_TB | CPU_FTR_L2CR | CPU_FTR_TAU | - CPU_FTR_HPTE_TABLE | CPU_FTR_MAYBE_CAN_NAP, + .cpu_features = CPU_FTRS_750, .cpu_user_features = COMMON_PPC, .icache_bsize = 32, .dcache_bsize = 32, @@ -216,10 +164,7 @@ struct cpu_spec cpu_specs[] = { .pvr_mask = 0xfffffff0, .pvr_value = 0x00082200, .cpu_name = "750CX", - .cpu_features = CPU_FTR_COMMON | - CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_MAYBE_CAN_DOZE | - CPU_FTR_USE_TB | CPU_FTR_L2CR | CPU_FTR_TAU | - CPU_FTR_HPTE_TABLE | CPU_FTR_MAYBE_CAN_NAP, + .cpu_features = CPU_FTRS_750, .cpu_user_features = COMMON_PPC, .icache_bsize = 32, .dcache_bsize = 32, @@ -230,10 +175,7 @@ struct cpu_spec cpu_specs[] = { .pvr_mask = 0xfffffff0, .pvr_value = 0x00082210, .cpu_name = "750CXe", - .cpu_features = CPU_FTR_COMMON | - CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_MAYBE_CAN_DOZE | - CPU_FTR_USE_TB | CPU_FTR_L2CR | CPU_FTR_TAU | - CPU_FTR_HPTE_TABLE | CPU_FTR_MAYBE_CAN_NAP, + .cpu_features = CPU_FTRS_750, .cpu_user_features = COMMON_PPC, .icache_bsize = 32, .dcache_bsize = 32, @@ -244,10 +186,7 @@ struct cpu_spec cpu_specs[] = { .pvr_mask = 0xffffffff, .pvr_value = 0x00083214, .cpu_name = "750CXe", - .cpu_features = CPU_FTR_COMMON | - CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_MAYBE_CAN_DOZE | - CPU_FTR_USE_TB | CPU_FTR_L2CR | CPU_FTR_TAU | - CPU_FTR_HPTE_TABLE | CPU_FTR_MAYBE_CAN_NAP, + .cpu_features = CPU_FTRS_750, .cpu_user_features = COMMON_PPC, .icache_bsize = 32, .dcache_bsize = 32, @@ -258,10 +197,7 @@ struct cpu_spec cpu_specs[] = { .pvr_mask = 0xfffff000, .pvr_value = 0x00083000, .cpu_name = "745/755", - .cpu_features = CPU_FTR_COMMON | - CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_MAYBE_CAN_DOZE | - CPU_FTR_USE_TB | CPU_FTR_L2CR | CPU_FTR_TAU | - CPU_FTR_HPTE_TABLE | CPU_FTR_MAYBE_CAN_NAP, + .cpu_features = CPU_FTRS_750, .cpu_user_features = COMMON_PPC, .icache_bsize = 32, .dcache_bsize = 32, @@ -272,11 +208,7 @@ struct cpu_spec cpu_specs[] = { .pvr_mask = 0xffffff00, .pvr_value = 0x70000100, .cpu_name = "750FX", - .cpu_features = CPU_FTR_COMMON | - CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_MAYBE_CAN_DOZE | - CPU_FTR_USE_TB | CPU_FTR_L2CR | CPU_FTR_TAU | - CPU_FTR_HPTE_TABLE | CPU_FTR_MAYBE_CAN_NAP | - CPU_FTR_DUAL_PLL_750FX | CPU_FTR_NO_DPM, + .cpu_features = CPU_FTRS_750FX1, .cpu_user_features = COMMON_PPC, .icache_bsize = 32, .dcache_bsize = 32, @@ -287,11 +219,7 @@ struct cpu_spec cpu_specs[] = { .pvr_mask = 0xffffffff, .pvr_value = 0x70000200, .cpu_name = "750FX", - .cpu_features = CPU_FTR_COMMON | - CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_MAYBE_CAN_DOZE | - CPU_FTR_USE_TB | CPU_FTR_L2CR | CPU_FTR_TAU | - CPU_FTR_HPTE_TABLE | CPU_FTR_MAYBE_CAN_NAP | - CPU_FTR_NO_DPM, + .cpu_features = CPU_FTRS_750FX2, .cpu_user_features = COMMON_PPC, .icache_bsize = 32, .dcache_bsize = 32, @@ -302,11 +230,7 @@ struct cpu_spec cpu_specs[] = { .pvr_mask = 0xffff0000, .pvr_value = 0x70000000, .cpu_name = "750FX", - .cpu_features = CPU_FTR_COMMON | - CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_MAYBE_CAN_DOZE | - CPU_FTR_USE_TB | CPU_FTR_L2CR | CPU_FTR_TAU | - CPU_FTR_HPTE_TABLE | CPU_FTR_MAYBE_CAN_NAP | - CPU_FTR_DUAL_PLL_750FX | CPU_FTR_HAS_HIGH_BATS, + .cpu_features = CPU_FTRS_750FX, .cpu_user_features = COMMON_PPC, .icache_bsize = 32, .dcache_bsize = 32, @@ -317,11 +241,7 @@ struct cpu_spec cpu_specs[] = { .pvr_mask = 0xffff0000, .pvr_value = 0x70020000, .cpu_name = "750GX", - .cpu_features = CPU_FTR_SPLIT_ID_CACHE | - CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB | - CPU_FTR_L2CR | CPU_FTR_TAU | CPU_FTR_HPTE_TABLE | - CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_DUAL_PLL_750FX | - CPU_FTR_HAS_HIGH_BATS, + .cpu_features = CPU_FTRS_750GX, .cpu_user_features = COMMON_PPC, .icache_bsize = 32, .dcache_bsize = 32, @@ -332,10 +252,7 @@ struct cpu_spec cpu_specs[] = { .pvr_mask = 0xffff0000, .pvr_value = 0x00080000, .cpu_name = "740/750", - .cpu_features = CPU_FTR_COMMON | - CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_MAYBE_CAN_DOZE | - CPU_FTR_USE_TB | CPU_FTR_L2CR | CPU_FTR_TAU | - CPU_FTR_HPTE_TABLE | CPU_FTR_MAYBE_CAN_NAP, + .cpu_features = CPU_FTRS_740, .cpu_user_features = COMMON_PPC, .icache_bsize = 32, .dcache_bsize = 32, @@ -346,11 +263,8 @@ struct cpu_spec cpu_specs[] = { .pvr_mask = 0xffffffff, .pvr_value = 0x000c1101, .cpu_name = "7400 (1.1)", - .cpu_features = CPU_FTR_COMMON | - CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_MAYBE_CAN_DOZE | - CPU_FTR_USE_TB | CPU_FTR_L2CR | CPU_FTR_ALTIVEC_COMP | - CPU_FTR_HPTE_TABLE | CPU_FTR_MAYBE_CAN_NAP, - .cpu_user_features = COMMON_PPC | PPC_FEATURE_ALTIVEC_COMP, + .cpu_features = CPU_FTRS_7400_NOTAU, + .cpu_user_features = COMMON_PPC | PPC_FEATURE_HAS_ALTIVEC_COMP, .icache_bsize = 32, .dcache_bsize = 32, .num_pmcs = 4, @@ -360,12 +274,8 @@ struct cpu_spec cpu_specs[] = { .pvr_mask = 0xffff0000, .pvr_value = 0x000c0000, .cpu_name = "7400", - .cpu_features = CPU_FTR_COMMON | - CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_MAYBE_CAN_DOZE | - CPU_FTR_USE_TB | CPU_FTR_L2CR | CPU_FTR_TAU | - CPU_FTR_ALTIVEC_COMP | CPU_FTR_HPTE_TABLE | - CPU_FTR_MAYBE_CAN_NAP, - .cpu_user_features = COMMON_PPC | PPC_FEATURE_ALTIVEC_COMP, + .cpu_features = CPU_FTRS_7400, + .cpu_user_features = COMMON_PPC | PPC_FEATURE_HAS_ALTIVEC_COMP, .icache_bsize = 32, .dcache_bsize = 32, .num_pmcs = 4, @@ -375,12 +285,8 @@ struct cpu_spec cpu_specs[] = { .pvr_mask = 0xffff0000, .pvr_value = 0x800c0000, .cpu_name = "7410", - .cpu_features = CPU_FTR_COMMON | - CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_MAYBE_CAN_DOZE | - CPU_FTR_USE_TB | CPU_FTR_L2CR | CPU_FTR_TAU | - CPU_FTR_ALTIVEC_COMP | CPU_FTR_HPTE_TABLE | - CPU_FTR_MAYBE_CAN_NAP, - .cpu_user_features = COMMON_PPC | PPC_FEATURE_ALTIVEC_COMP, + .cpu_features = CPU_FTRS_7400, + .cpu_user_features = COMMON_PPC | PPC_FEATURE_HAS_ALTIVEC_COMP, .icache_bsize = 32, .dcache_bsize = 32, .num_pmcs = 4, @@ -390,12 +296,8 @@ struct cpu_spec cpu_specs[] = { .pvr_mask = 0xffffffff, .pvr_value = 0x80000200, .cpu_name = "7450", - .cpu_features = CPU_FTR_COMMON | - CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | - CPU_FTR_L2CR | CPU_FTR_ALTIVEC_COMP | CPU_FTR_L3CR | - CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 | - CPU_FTR_NEED_COHERENT, - .cpu_user_features = COMMON_PPC | PPC_FEATURE_ALTIVEC_COMP, + .cpu_features = CPU_FTRS_7450_20, + .cpu_user_features = COMMON_PPC | PPC_FEATURE_HAS_ALTIVEC_COMP, .icache_bsize = 32, .dcache_bsize = 32, .num_pmcs = 6, @@ -405,14 +307,8 @@ struct cpu_spec cpu_specs[] = { .pvr_mask = 0xffffffff, .pvr_value = 0x80000201, .cpu_name = "7450", - .cpu_features = CPU_FTR_COMMON | - CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | - CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_L2CR | - CPU_FTR_ALTIVEC_COMP | CPU_FTR_L3CR | - CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 | - CPU_FTR_NAP_DISABLE_L2_PR | CPU_FTR_L3_DISABLE_NAP | - CPU_FTR_NEED_COHERENT, - .cpu_user_features = COMMON_PPC | PPC_FEATURE_ALTIVEC_COMP, + .cpu_features = CPU_FTRS_7450_21, + .cpu_user_features = COMMON_PPC | PPC_FEATURE_HAS_ALTIVEC_COMP, .icache_bsize = 32, .dcache_bsize = 32, .num_pmcs = 6, @@ -422,13 +318,8 @@ struct cpu_spec cpu_specs[] = { .pvr_mask = 0xffff0000, .pvr_value = 0x80000000, .cpu_name = "7450", - .cpu_features = CPU_FTR_COMMON | - CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | - CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_L2CR | - CPU_FTR_ALTIVEC_COMP | CPU_FTR_L3CR | - CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 | - CPU_FTR_NAP_DISABLE_L2_PR | CPU_FTR_NEED_COHERENT, - .cpu_user_features = COMMON_PPC | PPC_FEATURE_ALTIVEC_COMP, + .cpu_features = CPU_FTRS_7450_23, + .cpu_user_features = COMMON_PPC | PPC_FEATURE_HAS_ALTIVEC_COMP, .icache_bsize = 32, .dcache_bsize = 32, .num_pmcs = 6, @@ -438,12 +329,8 @@ struct cpu_spec cpu_specs[] = { .pvr_mask = 0xffffff00, .pvr_value = 0x80010100, .cpu_name = "7455", - .cpu_features = CPU_FTR_COMMON | - CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | - CPU_FTR_L2CR | CPU_FTR_ALTIVEC_COMP | CPU_FTR_L3CR | - CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 | - CPU_FTR_HAS_HIGH_BATS | CPU_FTR_NEED_COHERENT, - .cpu_user_features = COMMON_PPC | PPC_FEATURE_ALTIVEC_COMP, + .cpu_features = CPU_FTRS_7455_1, + .cpu_user_features = COMMON_PPC | PPC_FEATURE_HAS_ALTIVEC_COMP, .icache_bsize = 32, .dcache_bsize = 32, .num_pmcs = 6, @@ -453,14 +340,8 @@ struct cpu_spec cpu_specs[] = { .pvr_mask = 0xffffffff, .pvr_value = 0x80010200, .cpu_name = "7455", - .cpu_features = CPU_FTR_COMMON | - CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | - CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_L2CR | - CPU_FTR_ALTIVEC_COMP | CPU_FTR_L3CR | - CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 | - CPU_FTR_NAP_DISABLE_L2_PR | CPU_FTR_L3_DISABLE_NAP | - CPU_FTR_NEED_COHERENT | CPU_FTR_HAS_HIGH_BATS, - .cpu_user_features = COMMON_PPC | PPC_FEATURE_ALTIVEC_COMP, + .cpu_features = CPU_FTRS_7455_20, + .cpu_user_features = COMMON_PPC | PPC_FEATURE_HAS_ALTIVEC_COMP, .icache_bsize = 32, .dcache_bsize = 32, .num_pmcs = 6, @@ -470,14 +351,8 @@ struct cpu_spec cpu_specs[] = { .pvr_mask = 0xffff0000, .pvr_value = 0x80010000, .cpu_name = "7455", - .cpu_features = CPU_FTR_COMMON | - CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | - CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_L2CR | - CPU_FTR_ALTIVEC_COMP | CPU_FTR_L3CR | - CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 | - CPU_FTR_NAP_DISABLE_L2_PR | CPU_FTR_HAS_HIGH_BATS | - CPU_FTR_NEED_COHERENT, - .cpu_user_features = COMMON_PPC | PPC_FEATURE_ALTIVEC_COMP, + .cpu_features = CPU_FTRS_7455, + .cpu_user_features = COMMON_PPC | PPC_FEATURE_HAS_ALTIVEC_COMP, .icache_bsize = 32, .dcache_bsize = 32, .num_pmcs = 6, @@ -487,14 +362,8 @@ struct cpu_spec cpu_specs[] = { .pvr_mask = 0xffffffff, .pvr_value = 0x80020100, .cpu_name = "7447/7457", - .cpu_features = CPU_FTR_COMMON | - CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | - CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_L2CR | - CPU_FTR_ALTIVEC_COMP | CPU_FTR_L3CR | - CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 | - CPU_FTR_NAP_DISABLE_L2_PR | CPU_FTR_HAS_HIGH_BATS | - CPU_FTR_NEED_COHERENT | CPU_FTR_NO_BTIC, - .cpu_user_features = COMMON_PPC | PPC_FEATURE_ALTIVEC_COMP, + .cpu_features = CPU_FTRS_7447_10, + .cpu_user_features = COMMON_PPC | PPC_FEATURE_HAS_ALTIVEC_COMP, .icache_bsize = 32, .dcache_bsize = 32, .num_pmcs = 6, @@ -504,14 +373,8 @@ struct cpu_spec cpu_specs[] = { .pvr_mask = 0xffffffff, .pvr_value = 0x80020101, .cpu_name = "7447/7457", - .cpu_features = CPU_FTR_COMMON | - CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | - CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_L2CR | - CPU_FTR_ALTIVEC_COMP | CPU_FTR_L3CR | - CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 | - CPU_FTR_NAP_DISABLE_L2_PR | CPU_FTR_HAS_HIGH_BATS | - CPU_FTR_NEED_COHERENT | CPU_FTR_NO_BTIC, - .cpu_user_features = COMMON_PPC | PPC_FEATURE_ALTIVEC_COMP, + .cpu_features = CPU_FTRS_7447_10, + .cpu_user_features = COMMON_PPC | PPC_FEATURE_HAS_ALTIVEC_COMP, .icache_bsize = 32, .dcache_bsize = 32, .num_pmcs = 6, @@ -521,14 +384,8 @@ struct cpu_spec cpu_specs[] = { .pvr_mask = 0xffff0000, .pvr_value = 0x80020000, .cpu_name = "7447/7457", - .cpu_features = CPU_FTR_COMMON | - CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | - CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_L2CR | - CPU_FTR_ALTIVEC_COMP | CPU_FTR_L3CR | - CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 | - CPU_FTR_NAP_DISABLE_L2_PR | CPU_FTR_HAS_HIGH_BATS | - CPU_FTR_NEED_COHERENT, - .cpu_user_features = COMMON_PPC | PPC_FEATURE_ALTIVEC_COMP, + .cpu_features = CPU_FTRS_7447, + .cpu_user_features = COMMON_PPC | PPC_FEATURE_HAS_ALTIVEC_COMP, .icache_bsize = 32, .dcache_bsize = 32, .num_pmcs = 6, @@ -538,13 +395,8 @@ struct cpu_spec cpu_specs[] = { .pvr_mask = 0xffff0000, .pvr_value = 0x80030000, .cpu_name = "7447A", - .cpu_features = CPU_FTR_COMMON | - CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | - CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_L2CR | - CPU_FTR_ALTIVEC_COMP | CPU_FTR_HPTE_TABLE | - CPU_FTR_SPEC7450 | CPU_FTR_NAP_DISABLE_L2_PR | - CPU_FTR_HAS_HIGH_BATS | CPU_FTR_NEED_COHERENT, - .cpu_user_features = COMMON_PPC | PPC_FEATURE_ALTIVEC_COMP, + .cpu_features = CPU_FTRS_7447A, + .cpu_user_features = COMMON_PPC | PPC_FEATURE_HAS_ALTIVEC_COMP, .icache_bsize = 32, .dcache_bsize = 32, .num_pmcs = 6, @@ -554,13 +406,8 @@ struct cpu_spec cpu_specs[] = { .pvr_mask = 0xffff0000, .pvr_value = 0x80040000, .cpu_name = "7448", - .cpu_features = CPU_FTR_COMMON | - CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | - CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_L2CR | - CPU_FTR_ALTIVEC_COMP | CPU_FTR_HPTE_TABLE | - CPU_FTR_SPEC7450 | CPU_FTR_NAP_DISABLE_L2_PR | - CPU_FTR_HAS_HIGH_BATS | CPU_FTR_NEED_COHERENT, - .cpu_user_features = COMMON_PPC | PPC_FEATURE_ALTIVEC_COMP, + .cpu_features = CPU_FTRS_7447A, + .cpu_user_features = COMMON_PPC | PPC_FEATURE_HAS_ALTIVEC_COMP, .icache_bsize = 32, .dcache_bsize = 32, .num_pmcs = 6, @@ -570,9 +417,7 @@ struct cpu_spec cpu_specs[] = { .pvr_mask = 0x7fff0000, .pvr_value = 0x00810000, .cpu_name = "82xx", - .cpu_features = CPU_FTR_COMMON | - CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_MAYBE_CAN_DOZE | - CPU_FTR_USE_TB, + .cpu_features = CPU_FTRS_82XX, .cpu_user_features = COMMON_PPC, .icache_bsize = 32, .dcache_bsize = 32, @@ -582,9 +427,7 @@ struct cpu_spec cpu_specs[] = { .pvr_mask = 0x7fff0000, .pvr_value = 0x00820000, .cpu_name = "G2_LE", - .cpu_features = CPU_FTR_SPLIT_ID_CACHE | - CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB | - CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_HAS_HIGH_BATS, + .cpu_features = CPU_FTRS_G2_LE, .cpu_user_features = COMMON_PPC, .icache_bsize = 32, .dcache_bsize = 32, @@ -594,9 +437,7 @@ struct cpu_spec cpu_specs[] = { .pvr_mask = 0x7fff0000, .pvr_value = 0x00830000, .cpu_name = "e300", - .cpu_features = CPU_FTR_SPLIT_ID_CACHE | - CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB | - CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_HAS_HIGH_BATS, + .cpu_features = CPU_FTRS_E300, .cpu_user_features = COMMON_PPC, .icache_bsize = 32, .dcache_bsize = 32, @@ -606,9 +447,7 @@ struct cpu_spec cpu_specs[] = { .pvr_mask = 0x00000000, .pvr_value = 0x00000000, .cpu_name = "(generic PPC)", - .cpu_features = CPU_FTR_COMMON | - CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | - CPU_FTR_HPTE_TABLE, + .cpu_features = CPU_FTRS_CLASSIC32, .cpu_user_features = COMMON_PPC, .icache_bsize = 32, .dcache_bsize = 32, @@ -620,9 +459,7 @@ struct cpu_spec cpu_specs[] = { .pvr_mask = 0xffff0000, .pvr_value = 0x00400000, .cpu_name = "Power3 (630)", - .cpu_features = CPU_FTR_COMMON | - CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | - CPU_FTR_HPTE_TABLE, + .cpu_features = CPU_FTRS_POWER3_32, .cpu_user_features = COMMON_PPC | PPC_FEATURE_64, .icache_bsize = 128, .dcache_bsize = 128, @@ -633,9 +470,7 @@ struct cpu_spec cpu_specs[] = { .pvr_mask = 0xffff0000, .pvr_value = 0x00410000, .cpu_name = "Power3 (630+)", - .cpu_features = CPU_FTR_COMMON | - CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | - CPU_FTR_HPTE_TABLE, + .cpu_features = CPU_FTRS_POWER3_32, .cpu_user_features = COMMON_PPC | PPC_FEATURE_64, .icache_bsize = 128, .dcache_bsize = 128, @@ -646,9 +481,7 @@ struct cpu_spec cpu_specs[] = { .pvr_mask = 0xffff0000, .pvr_value = 0x00360000, .cpu_name = "I-star", - .cpu_features = CPU_FTR_COMMON | - CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | - CPU_FTR_HPTE_TABLE, + .cpu_features = CPU_FTRS_POWER3_32, .cpu_user_features = COMMON_PPC | PPC_FEATURE_64, .icache_bsize = 128, .dcache_bsize = 128, @@ -659,9 +492,7 @@ struct cpu_spec cpu_specs[] = { .pvr_mask = 0xffff0000, .pvr_value = 0x00370000, .cpu_name = "S-star", - .cpu_features = CPU_FTR_COMMON | - CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | - CPU_FTR_HPTE_TABLE, + .cpu_features = CPU_FTRS_POWER3_32, .cpu_user_features = COMMON_PPC | PPC_FEATURE_64, .icache_bsize = 128, .dcache_bsize = 128, @@ -670,44 +501,12 @@ struct cpu_spec cpu_specs[] = { }, #endif /* CONFIG_PPC64BRIDGE */ #ifdef CONFIG_POWER4 - { /* Power4 */ - .pvr_mask = 0xffff0000, - .pvr_value = 0x00350000, - .cpu_name = "Power4", - .cpu_features = CPU_FTR_COMMON | - CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | - CPU_FTR_HPTE_TABLE, - .cpu_user_features = COMMON_PPC | PPC_FEATURE_64, - .icache_bsize = 128, - .dcache_bsize = 128, - .num_pmcs = 8, - .cpu_setup = __setup_cpu_power4 - }, - { /* PPC970 */ - .pvr_mask = 0xffff0000, - .pvr_value = 0x00390000, - .cpu_name = "PPC970", - .cpu_features = CPU_FTR_COMMON | - CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | - CPU_FTR_HPTE_TABLE | - CPU_FTR_ALTIVEC_COMP | CPU_FTR_MAYBE_CAN_NAP, - .cpu_user_features = COMMON_PPC | PPC_FEATURE_64 | - PPC_FEATURE_ALTIVEC_COMP, - .icache_bsize = 128, - .dcache_bsize = 128, - .num_pmcs = 8, - .cpu_setup = __setup_cpu_ppc970 - }, { /* PPC970FX */ .pvr_mask = 0xffff0000, .pvr_value = 0x003c0000, .cpu_name = "PPC970FX", - .cpu_features = CPU_FTR_COMMON | - CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | - CPU_FTR_HPTE_TABLE | - CPU_FTR_ALTIVEC_COMP | CPU_FTR_MAYBE_CAN_NAP, - .cpu_user_features = COMMON_PPC | PPC_FEATURE_64 | - PPC_FEATURE_ALTIVEC_COMP, + .cpu_features = CPU_FTRS_970_32, + .cpu_user_features = COMMON_PPC | PPC_FEATURE_64 | PPC_FEATURE_HAS_ALTIVEC_COMP, .icache_bsize = 128, .dcache_bsize = 128, .num_pmcs = 8, @@ -721,8 +520,7 @@ struct cpu_spec cpu_specs[] = { .cpu_name = "8xx", /* CPU_FTR_MAYBE_CAN_DOZE is possible, * if the 8xx code is there.... */ - .cpu_features = CPU_FTR_SPLIT_ID_CACHE | - CPU_FTR_USE_TB, + .cpu_features = CPU_FTRS_8XX, .cpu_user_features = PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU, .icache_bsize = 16, .dcache_bsize = 16, @@ -733,8 +531,7 @@ struct cpu_spec cpu_specs[] = { .pvr_mask = 0xffffff00, .pvr_value = 0x00200200, .cpu_name = "403GC", - .cpu_features = CPU_FTR_SPLIT_ID_CACHE | - CPU_FTR_USE_TB, + .cpu_features = CPU_FTRS_40X, .cpu_user_features = PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU, .icache_bsize = 16, .dcache_bsize = 16, @@ -743,8 +540,7 @@ struct cpu_spec cpu_specs[] = { .pvr_mask = 0xffffff00, .pvr_value = 0x00201400, .cpu_name = "403GCX", - .cpu_features = CPU_FTR_SPLIT_ID_CACHE | - CPU_FTR_USE_TB, + .cpu_features = CPU_FTRS_40X, .cpu_user_features = PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU, .icache_bsize = 16, .dcache_bsize = 16, @@ -753,8 +549,7 @@ struct cpu_spec cpu_specs[] = { .pvr_mask = 0xffff0000, .pvr_value = 0x00200000, .cpu_name = "403G ??", - .cpu_features = CPU_FTR_SPLIT_ID_CACHE | - CPU_FTR_USE_TB, + .cpu_features = CPU_FTRS_40X, .cpu_user_features = PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU, .icache_bsize = 16, .dcache_bsize = 16, @@ -763,8 +558,7 @@ struct cpu_spec cpu_specs[] = { .pvr_mask = 0xffff0000, .pvr_value = 0x40110000, .cpu_name = "405GP", - .cpu_features = CPU_FTR_SPLIT_ID_CACHE | - CPU_FTR_USE_TB, + .cpu_features = CPU_FTRS_40X, .cpu_user_features = PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU | PPC_FEATURE_HAS_4xxMAC, .icache_bsize = 32, @@ -774,8 +568,7 @@ struct cpu_spec cpu_specs[] = { .pvr_mask = 0xffff0000, .pvr_value = 0x40130000, .cpu_name = "STB03xxx", - .cpu_features = CPU_FTR_SPLIT_ID_CACHE | - CPU_FTR_USE_TB, + .cpu_features = CPU_FTRS_40X, .cpu_user_features = PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU | PPC_FEATURE_HAS_4xxMAC, .icache_bsize = 32, @@ -785,8 +578,7 @@ struct cpu_spec cpu_specs[] = { .pvr_mask = 0xffff0000, .pvr_value = 0x41810000, .cpu_name = "STB04xxx", - .cpu_features = CPU_FTR_SPLIT_ID_CACHE | - CPU_FTR_USE_TB, + .cpu_features = CPU_FTRS_40X, .cpu_user_features = PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU | PPC_FEATURE_HAS_4xxMAC, .icache_bsize = 32, @@ -796,8 +588,7 @@ struct cpu_spec cpu_specs[] = { .pvr_mask = 0xffff0000, .pvr_value = 0x41610000, .cpu_name = "NP405L", - .cpu_features = CPU_FTR_SPLIT_ID_CACHE | - CPU_FTR_USE_TB, + .cpu_features = CPU_FTRS_40X, .cpu_user_features = PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU | PPC_FEATURE_HAS_4xxMAC, .icache_bsize = 32, @@ -807,8 +598,7 @@ struct cpu_spec cpu_specs[] = { .pvr_mask = 0xffff0000, .pvr_value = 0x40B10000, .cpu_name = "NP4GS3", - .cpu_features = CPU_FTR_SPLIT_ID_CACHE | - CPU_FTR_USE_TB, + .cpu_features = CPU_FTRS_40X, .cpu_user_features = PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU | PPC_FEATURE_HAS_4xxMAC, .icache_bsize = 32, @@ -818,8 +608,7 @@ struct cpu_spec cpu_specs[] = { .pvr_mask = 0xffff0000, .pvr_value = 0x41410000, .cpu_name = "NP405H", - .cpu_features = CPU_FTR_SPLIT_ID_CACHE | - CPU_FTR_USE_TB, + .cpu_features = CPU_FTRS_40X, .cpu_user_features = PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU | PPC_FEATURE_HAS_4xxMAC, .icache_bsize = 32, @@ -829,8 +618,7 @@ struct cpu_spec cpu_specs[] = { .pvr_mask = 0xffff0000, .pvr_value = 0x50910000, .cpu_name = "405GPr", - .cpu_features = CPU_FTR_SPLIT_ID_CACHE | - CPU_FTR_USE_TB, + .cpu_features = CPU_FTRS_40X, .cpu_user_features = PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU | PPC_FEATURE_HAS_4xxMAC, .icache_bsize = 32, @@ -840,8 +628,7 @@ struct cpu_spec cpu_specs[] = { .pvr_mask = 0xffff0000, .pvr_value = 0x51510000, .cpu_name = "STBx25xx", - .cpu_features = CPU_FTR_SPLIT_ID_CACHE | - CPU_FTR_USE_TB, + .cpu_features = CPU_FTRS_40X, .cpu_user_features = PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU | PPC_FEATURE_HAS_4xxMAC, .icache_bsize = 32, @@ -851,8 +638,7 @@ struct cpu_spec cpu_specs[] = { .pvr_mask = 0xffff0000, .pvr_value = 0x41F10000, .cpu_name = "405LP", - .cpu_features = CPU_FTR_SPLIT_ID_CACHE | - CPU_FTR_USE_TB, + .cpu_features = CPU_FTRS_40X, .cpu_user_features = PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU, .icache_bsize = 32, .dcache_bsize = 32, @@ -861,8 +647,7 @@ struct cpu_spec cpu_specs[] = { .pvr_mask = 0xffff0000, .pvr_value = 0x20010000, .cpu_name = "Virtex-II Pro", - .cpu_features = CPU_FTR_SPLIT_ID_CACHE | - CPU_FTR_USE_TB, + .cpu_features = CPU_FTRS_40X, .cpu_user_features = PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU | PPC_FEATURE_HAS_4xxMAC, .icache_bsize = 32, @@ -872,8 +657,7 @@ struct cpu_spec cpu_specs[] = { .pvr_mask = 0xffff0000, .pvr_value = 0x51210000, .cpu_name = "405EP", - .cpu_features = CPU_FTR_SPLIT_ID_CACHE | - CPU_FTR_USE_TB, + .cpu_features = CPU_FTRS_40X, .cpu_user_features = PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU | PPC_FEATURE_HAS_4xxMAC, .icache_bsize = 32, @@ -886,8 +670,7 @@ struct cpu_spec cpu_specs[] = { .pvr_mask = 0xf0000fff, .pvr_value = 0x40000850, .cpu_name = "440EP Rev. A", - .cpu_features = CPU_FTR_SPLIT_ID_CACHE | - CPU_FTR_USE_TB, + .cpu_features = CPU_FTRS_44X, .cpu_user_features = COMMON_PPC, /* 440EP has an FPU */ .icache_bsize = 32, .dcache_bsize = 32, @@ -896,8 +679,7 @@ struct cpu_spec cpu_specs[] = { .pvr_mask = 0xf0000fff, .pvr_value = 0x400008d3, .cpu_name = "440EP Rev. B", - .cpu_features = CPU_FTR_SPLIT_ID_CACHE | - CPU_FTR_USE_TB, + .cpu_features = CPU_FTRS_44X, .cpu_user_features = COMMON_PPC, /* 440EP has an FPU */ .icache_bsize = 32, .dcache_bsize = 32, @@ -906,8 +688,7 @@ struct cpu_spec cpu_specs[] = { .pvr_mask = 0xf0000fff, .pvr_value = 0x40000440, .cpu_name = "440GP Rev. B", - .cpu_features = CPU_FTR_SPLIT_ID_CACHE | - CPU_FTR_USE_TB, + .cpu_features = CPU_FTRS_44X, .cpu_user_features = PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU, .icache_bsize = 32, .dcache_bsize = 32, @@ -916,8 +697,7 @@ struct cpu_spec cpu_specs[] = { .pvr_mask = 0xf0000fff, .pvr_value = 0x40000481, .cpu_name = "440GP Rev. C", - .cpu_features = CPU_FTR_SPLIT_ID_CACHE | - CPU_FTR_USE_TB, + .cpu_features = CPU_FTRS_44X, .cpu_user_features = PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU, .icache_bsize = 32, .dcache_bsize = 32, @@ -926,8 +706,7 @@ struct cpu_spec cpu_specs[] = { .pvr_mask = 0xf0000fff, .pvr_value = 0x50000850, .cpu_name = "440GX Rev. A", - .cpu_features = CPU_FTR_SPLIT_ID_CACHE | - CPU_FTR_USE_TB, + .cpu_features = CPU_FTRS_44X, .cpu_user_features = PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU, .icache_bsize = 32, .dcache_bsize = 32, @@ -936,8 +715,7 @@ struct cpu_spec cpu_specs[] = { .pvr_mask = 0xf0000fff, .pvr_value = 0x50000851, .cpu_name = "440GX Rev. B", - .cpu_features = CPU_FTR_SPLIT_ID_CACHE | - CPU_FTR_USE_TB, + .cpu_features = CPU_FTRS_44X, .cpu_user_features = PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU, .icache_bsize = 32, .dcache_bsize = 32, @@ -946,8 +724,7 @@ struct cpu_spec cpu_specs[] = { .pvr_mask = 0xf0000fff, .pvr_value = 0x50000892, .cpu_name = "440GX Rev. C", - .cpu_features = CPU_FTR_SPLIT_ID_CACHE | - CPU_FTR_USE_TB, + .cpu_features = CPU_FTRS_44X, .cpu_user_features = PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU, .icache_bsize = 32, .dcache_bsize = 32, @@ -956,8 +733,7 @@ struct cpu_spec cpu_specs[] = { .pvr_mask = 0xf0000fff, .pvr_value = 0x50000894, .cpu_name = "440GX Rev. F", - .cpu_features = CPU_FTR_SPLIT_ID_CACHE | - CPU_FTR_USE_TB, + .cpu_features = CPU_FTRS_44X, .cpu_user_features = PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU, .icache_bsize = 32, .dcache_bsize = 32, @@ -966,8 +742,7 @@ struct cpu_spec cpu_specs[] = { .pvr_mask = 0xff000fff, .pvr_value = 0x53000891, .cpu_name = "440SP Rev. A", - .cpu_features = CPU_FTR_SPLIT_ID_CACHE | - CPU_FTR_USE_TB, + .cpu_features = CPU_FTRS_44X, .cpu_user_features = PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU, .icache_bsize = 32, .dcache_bsize = 32, @@ -979,7 +754,7 @@ struct cpu_spec cpu_specs[] = { .pvr_value = 0x81000000, .cpu_name = "e200z5", /* xxx - galak: add CPU_FTR_MAYBE_CAN_DOZE */ - .cpu_features = CPU_FTR_USE_TB, + .cpu_features = CPU_FTRS_E200, .cpu_user_features = PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU | PPC_FEATURE_HAS_EFP_SINGLE | PPC_FEATURE_UNIFIED_CACHE, @@ -990,7 +765,7 @@ struct cpu_spec cpu_specs[] = { .pvr_value = 0x81100000, .cpu_name = "e200z6", /* xxx - galak: add CPU_FTR_MAYBE_CAN_DOZE */ - .cpu_features = CPU_FTR_USE_TB, + .cpu_features = CPU_FTRS_E200, .cpu_user_features = PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU | PPC_FEATURE_SPE_COMP | PPC_FEATURE_HAS_EFP_SINGLE | @@ -1002,8 +777,7 @@ struct cpu_spec cpu_specs[] = { .pvr_value = 0x80200000, .cpu_name = "e500", /* xxx - galak: add CPU_FTR_MAYBE_CAN_DOZE */ - .cpu_features = CPU_FTR_SPLIT_ID_CACHE | - CPU_FTR_USE_TB, + .cpu_features = CPU_FTRS_E500, .cpu_user_features = PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU | PPC_FEATURE_SPE_COMP | PPC_FEATURE_HAS_EFP_SINGLE, @@ -1016,8 +790,7 @@ struct cpu_spec cpu_specs[] = { .pvr_value = 0x80210000, .cpu_name = "e500v2", /* xxx - galak: add CPU_FTR_MAYBE_CAN_DOZE */ - .cpu_features = CPU_FTR_SPLIT_ID_CACHE | - CPU_FTR_USE_TB | CPU_FTR_BIG_PHYS, + .cpu_features = CPU_FTRS_E500_2, .cpu_user_features = PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU | PPC_FEATURE_SPE_COMP | PPC_FEATURE_HAS_EFP_SINGLE | PPC_FEATURE_HAS_EFP_DOUBLE, @@ -1031,7 +804,7 @@ struct cpu_spec cpu_specs[] = { .pvr_mask = 0x00000000, .pvr_value = 0x00000000, .cpu_name = "(generic PPC)", - .cpu_features = CPU_FTR_COMMON, + .cpu_features = CPU_FTRS_GENERIC_32, .cpu_user_features = PPC_FEATURE_32, .icache_bsize = 32, .dcache_bsize = 32, diff --git a/arch/ppc64/kernel/cputable.c b/arch/ppc64/kernel/cputable.c --- a/arch/ppc64/kernel/cputable.c +++ b/arch/ppc64/kernel/cputable.c @@ -37,26 +37,13 @@ extern void __setup_cpu_power4(unsigned extern void __setup_cpu_ppc970(unsigned long offset, struct cpu_spec* spec); extern void __setup_cpu_be(unsigned long offset, struct cpu_spec* spec); - -/* We only set the altivec features if the kernel was compiled with altivec - * support - */ -#ifdef CONFIG_ALTIVEC -#define CPU_FTR_ALTIVEC_COMP CPU_FTR_ALTIVEC -#define PPC_FEATURE_HAS_ALTIVEC_COMP PPC_FEATURE_HAS_ALTIVEC -#else -#define CPU_FTR_ALTIVEC_COMP 0 -#define PPC_FEATURE_HAS_ALTIVEC_COMP 0 -#endif - struct cpu_spec cpu_specs[] = { { /* Power3 */ .pvr_mask = 0xffff0000, .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_user_features = COMMON_USER_PPC64, + .cpu_features = CPU_FTRS_POWER3, + .cpu_user_features = COMMON_USER_PPC64, .icache_bsize = 128, .dcache_bsize = 128, .num_pmcs = 8, @@ -70,8 +57,7 @@ struct cpu_spec cpu_specs[] = { .pvr_mask = 0xffff0000, .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_features = CPU_FTRS_POWER3, .cpu_user_features = COMMON_USER_PPC64, .icache_bsize = 128, .dcache_bsize = 128, @@ -86,9 +72,7 @@ struct cpu_spec cpu_specs[] = { .pvr_mask = 0xffff0000, .pvr_value = 0x00330000, .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_MMCRA | CPU_FTR_CTRL, + .cpu_features = CPU_FTRS_RS64, .cpu_user_features = COMMON_USER_PPC64, .icache_bsize = 128, .dcache_bsize = 128, @@ -103,9 +87,7 @@ struct cpu_spec cpu_specs[] = { .pvr_mask = 0xffff0000, .pvr_value = 0x00340000, .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_MMCRA | CPU_FTR_CTRL, + .cpu_features = CPU_FTRS_RS64, .cpu_user_features = COMMON_USER_PPC64, .icache_bsize = 128, .dcache_bsize = 128, @@ -120,9 +102,7 @@ struct cpu_spec cpu_specs[] = { .pvr_mask = 0xffff0000, .pvr_value = 0x00360000, .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_MMCRA | CPU_FTR_CTRL, + .cpu_features = CPU_FTRS_RS64, .cpu_user_features = COMMON_USER_PPC64, .icache_bsize = 128, .dcache_bsize = 128, @@ -137,9 +117,7 @@ struct cpu_spec cpu_specs[] = { .pvr_mask = 0xffff0000, .pvr_value = 0x00370000, .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_MMCRA | CPU_FTR_CTRL, + .cpu_features = CPU_FTRS_RS64, .cpu_user_features = COMMON_USER_PPC64, .icache_bsize = 128, .dcache_bsize = 128, @@ -154,9 +132,7 @@ struct cpu_spec cpu_specs[] = { .pvr_mask = 0xffff0000, .pvr_value = 0x00350000, .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_MMCRA, + .cpu_features = CPU_FTRS_POWER4, .cpu_user_features = COMMON_USER_PPC64, .icache_bsize = 128, .dcache_bsize = 128, @@ -171,9 +147,7 @@ struct cpu_spec cpu_specs[] = { .pvr_mask = 0xffff0000, .pvr_value = 0x00380000, .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_MMCRA, + .cpu_features = CPU_FTRS_POWER4, .cpu_user_features = COMMON_USER_PPC64, .icache_bsize = 128, .dcache_bsize = 128, @@ -188,10 +162,7 @@ struct cpu_spec cpu_specs[] = { .pvr_mask = 0xffff0000, .pvr_value = 0x00390000, .cpu_name = "PPC970", - .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_MMCRA, + .cpu_features = CPU_FTRS_PPC970, .cpu_user_features = COMMON_USER_PPC64 | PPC_FEATURE_HAS_ALTIVEC_COMP, .icache_bsize = 128, @@ -207,10 +178,7 @@ struct cpu_spec cpu_specs[] = { .pvr_mask = 0xffff0000, .pvr_value = 0x003c0000, .cpu_name = "PPC970FX", - .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_MMCRA, + .cpu_features = CPU_FTRS_PPC970, .cpu_user_features = COMMON_USER_PPC64 | PPC_FEATURE_HAS_ALTIVEC_COMP, .icache_bsize = 128, @@ -226,10 +194,7 @@ struct cpu_spec cpu_specs[] = { .pvr_mask = 0xffff0000, .pvr_value = 0x00440000, .cpu_name = "PPC970MP", - .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_MMCRA, + .cpu_features = CPU_FTRS_PPC970, .cpu_user_features = COMMON_USER_PPC64 | PPC_FEATURE_HAS_ALTIVEC_COMP, .icache_bsize = 128, @@ -244,11 +209,7 @@ struct cpu_spec cpu_specs[] = { .pvr_mask = 0xffff0000, .pvr_value = 0x003a0000, .cpu_name = "POWER5 (gr)", - .cpu_features = CPU_FTR_SPLIT_ID_CACHE | - CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE | - CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_MMCRA | CPU_FTR_SMT | - CPU_FTR_COHERENT_ICACHE | CPU_FTR_LOCKLESS_TLBIE | - CPU_FTR_MMCRA_SIHV, + .cpu_features = CPU_FTRS_POWER5, .cpu_user_features = COMMON_USER_PPC64, .icache_bsize = 128, .dcache_bsize = 128, @@ -263,11 +224,7 @@ struct cpu_spec cpu_specs[] = { .pvr_mask = 0xffff0000, .pvr_value = 0x003b0000, .cpu_name = "POWER5 (gs)", - .cpu_features = CPU_FTR_SPLIT_ID_CACHE | - CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE | - CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_MMCRA | CPU_FTR_SMT | - CPU_FTR_COHERENT_ICACHE | CPU_FTR_LOCKLESS_TLBIE | - CPU_FTR_MMCRA_SIHV, + .cpu_features = CPU_FTRS_POWER5, .cpu_user_features = COMMON_USER_PPC64, .icache_bsize = 128, .dcache_bsize = 128, @@ -281,11 +238,8 @@ struct cpu_spec cpu_specs[] = { { /* BE DD1.x */ .pvr_mask = 0xffff0000, .pvr_value = 0x00700000, - .cpu_name = "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 | - CPU_FTR_SMT, + .cpu_name = "Cell Broadband Engine", + .cpu_features = CPU_FTRS_CELL, .cpu_user_features = COMMON_USER_PPC64 | PPC_FEATURE_HAS_ALTIVEC_COMP, .icache_bsize = 128, @@ -296,9 +250,7 @@ struct cpu_spec cpu_specs[] = { .pvr_mask = 0x00000000, .pvr_value = 0x00000000, .cpu_name = "POWER4 (compatible)", - .cpu_features = CPU_FTR_SPLIT_ID_CACHE | - CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE | - CPU_FTR_PPCAS_ARCH_V2, + .cpu_features = CPU_FTRS_COMPATIBLE, .cpu_user_features = COMMON_USER_PPC64, .icache_bsize = 128, .dcache_bsize = 128, diff --git a/include/asm-powerpc/cputable.h b/include/asm-powerpc/cputable.h new file mode 100644 --- /dev/null +++ b/include/asm-powerpc/cputable.h @@ -0,0 +1,442 @@ +#ifndef __ASM_POWERPC_CPUTABLE_H +#define __ASM_POWERPC_CPUTABLE_H + +#include +#include /* for ASM_CONST */ + +#define PPC_FEATURE_32 0x80000000 +#define PPC_FEATURE_64 0x40000000 +#define PPC_FEATURE_601_INSTR 0x20000000 +#define PPC_FEATURE_HAS_ALTIVEC 0x10000000 +#define PPC_FEATURE_HAS_FPU 0x08000000 +#define PPC_FEATURE_HAS_MMU 0x04000000 +#define PPC_FEATURE_HAS_4xxMAC 0x02000000 +#define PPC_FEATURE_UNIFIED_CACHE 0x01000000 +#define PPC_FEATURE_HAS_SPE 0x00800000 +#define PPC_FEATURE_HAS_EFP_SINGLE 0x00400000 +#define PPC_FEATURE_HAS_EFP_DOUBLE 0x00200000 + +#ifdef __KERNEL__ +#ifndef __ASSEMBLY__ + +/* This structure can grow, it's real size is used by head.S code + * via the mkdefs mechanism. + */ +struct cpu_spec; +struct op_powerpc_model; + +#ifdef __powerpc64__ +typedef void (*cpu_setup_t)(unsigned long offset, struct cpu_spec* spec); +#else /* __powerpc64__ */ +typedef void (*cpu_setup_t)(unsigned long offset, int cpu_nr, struct cpu_spec* spec); +#endif /* __powerpc64__ */ + +struct cpu_spec { + /* CPU is matched via (PVR & pvr_mask) == pvr_value */ + unsigned int pvr_mask; + unsigned int pvr_value; + + char *cpu_name; + unsigned long cpu_features; /* Kernel features */ + unsigned int cpu_user_features; /* Userland features */ + + /* cache line sizes */ + 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 + */ + cpu_setup_t cpu_setup; +#ifdef __powerpc64__ + + /* Used by oprofile userspace to select the right counters */ + char *oprofile_cpu_type; + + /* Processor specific oprofile operations */ + struct op_powerpc_model *oprofile_model; +#endif /* __powerpc64__ */ +}; + +extern struct cpu_spec cpu_specs[]; + +#ifdef __powerpc64__ +extern struct cpu_spec *cur_cpu_spec; +#else /* __powerpc64__ */ +extern struct cpu_spec *cur_cpu_spec[]; +#endif /* __powerpc64__ */ + +#endif /* __ASSEMBLY__ */ + +/* CPU kernel features */ + +/* Retain the 32b definitions all use bottom half of word */ +#define CPU_FTR_SPLIT_ID_CACHE ASM_CONST(0x0000000000000001) +#define CPU_FTR_L2CR ASM_CONST(0x0000000000000002) +#define CPU_FTR_SPEC7450 ASM_CONST(0x0000000000000004) +#define CPU_FTR_ALTIVEC ASM_CONST(0x0000000000000008) +#define CPU_FTR_TAU ASM_CONST(0x0000000000000010) +#define CPU_FTR_CAN_DOZE ASM_CONST(0x0000000000000020) +#define CPU_FTR_USE_TB ASM_CONST(0x0000000000000040) +#define CPU_FTR_604_PERF_MON ASM_CONST(0x0000000000000080) +#define CPU_FTR_601 ASM_CONST(0x0000000000000100) +#define CPU_FTR_HPTE_TABLE ASM_CONST(0x0000000000000200) +#define CPU_FTR_CAN_NAP ASM_CONST(0x0000000000000400) +#define CPU_FTR_L3CR ASM_CONST(0x0000000000000800) +#define CPU_FTR_L3_DISABLE_NAP ASM_CONST(0x0000000000001000) +#define CPU_FTR_NAP_DISABLE_L2_PR ASM_CONST(0x0000000000002000) +#define CPU_FTR_DUAL_PLL_750FX ASM_CONST(0x0000000000004000) +#define CPU_FTR_NO_DPM ASM_CONST(0x0000000000008000) +#define CPU_FTR_HAS_HIGH_BATS ASM_CONST(0x0000000000010000) +#define CPU_FTR_NEED_COHERENT ASM_CONST(0x0000000000020000) +#define CPU_FTR_NO_BTIC ASM_CONST(0x0000000000040000) +#define CPU_FTR_BIG_PHYS ASM_CONST(0x0000000000080000) + +#ifdef __powerpc64__ +/* Add the 64b processor unique features in the top half of the word */ +#define CPU_FTR_SLB ASM_CONST(0x0000000100000000) +#define CPU_FTR_16M_PAGE ASM_CONST(0x0000000200000000) +#define CPU_FTR_TLBIEL ASM_CONST(0x0000000400000000) +#define CPU_FTR_NOEXECUTE ASM_CONST(0x0000000800000000) +#define CPU_FTR_NODSISRALIGN ASM_CONST(0x0000001000000000) +#define CPU_FTR_IABR ASM_CONST(0x0000002000000000) +#define CPU_FTR_MMCRA ASM_CONST(0x0000004000000000) +#define CPU_FTR_CTRL 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) +#define CPU_FTR_MMCRA_SIHV ASM_CONST(0x0000080000000000) +#else +/* ensure on 32b processors the flags are available for compiling but + * don't do anything */ +#define CPU_FTR_SLB ASM_CONST(0x0) +#define CPU_FTR_16M_PAGE ASM_CONST(0x0) +#define CPU_FTR_TLBIEL ASM_CONST(0x0) +#define CPU_FTR_NOEXECUTE ASM_CONST(0x0) +#define CPU_FTR_NODSISRALIGN ASM_CONST(0x0) +#define CPU_FTR_IABR ASM_CONST(0x0) +#define CPU_FTR_MMCRA ASM_CONST(0x0) +#define CPU_FTR_CTRL ASM_CONST(0x0) +#define CPU_FTR_SMT ASM_CONST(0x0) +#define CPU_FTR_COHERENT_ICACHE ASM_CONST(0x0) +#define CPU_FTR_LOCKLESS_TLBIE ASM_CONST(0x0) +#define CPU_FTR_MMCRA_SIHV ASM_CONST(0x0) +#endif + +#ifndef __ASSEMBLY__ + +#define COMMON_USER_PPC64 (PPC_FEATURE_32 | PPC_FEATURE_64 | \ + PPC_FEATURE_HAS_FPU | PPC_FEATURE_HAS_MMU) + +#define CPU_FTR_PPCAS_ARCH_V2_BASE (CPU_FTR_SLB | \ + CPU_FTR_TLBIEL | CPU_FTR_NOEXECUTE | \ + CPU_FTR_NODSISRALIGN | CPU_FTR_CTRL) + +/* iSeries doesn't support large pages */ +#ifdef CONFIG_PPC_ISERIES +#define CPU_FTR_PPCAS_ARCH_V2 (CPU_FTR_PPCAS_ARCH_V2_BASE) +#else +#define CPU_FTR_PPCAS_ARCH_V2 (CPU_FTR_PPCAS_ARCH_V2_BASE | CPU_FTR_16M_PAGE) +#endif /* CONFIG_PPC_ISERIES */ + +/* We only set the altivec features if the kernel was compiled with altivec + * support + */ +#ifdef CONFIG_ALTIVEC +#define CPU_FTR_ALTIVEC_COMP CPU_FTR_ALTIVEC +#define PPC_FEATURE_HAS_ALTIVEC_COMP PPC_FEATURE_HAS_ALTIVEC +#else +#define CPU_FTR_ALTIVEC_COMP 0 +#define PPC_FEATURE_HAS_ALTIVEC_COMP 0 +#endif + +/* We need to mark all pages as being coherent if we're SMP or we + * have a 74[45]x and an MPC107 host bridge. + */ +#if defined(CONFIG_SMP) || defined(CONFIG_MPC10X_BRIDGE) +#define CPU_FTR_COMMON CPU_FTR_NEED_COHERENT +#else +#define CPU_FTR_COMMON 0 +#endif + +/* The powersave features NAP & DOZE seems to confuse BDI when + debugging. So if a BDI is used, disable theses + */ +#ifndef CONFIG_BDI_SWITCH +#define CPU_FTR_MAYBE_CAN_DOZE CPU_FTR_CAN_DOZE +#define CPU_FTR_MAYBE_CAN_NAP CPU_FTR_CAN_NAP +#else +#define CPU_FTR_MAYBE_CAN_DOZE 0 +#define CPU_FTR_MAYBE_CAN_NAP 0 +#endif + +#define CLASSIC_PPC (!defined(CONFIG_8xx) && !defined(CONFIG_4xx) && \ + !defined(CONFIG_POWER3) && !defined(CONFIG_POWER4) && \ + !defined(CONFIG_BOOKE)) + +enum { + CPU_FTRS_PPC601 = CPU_FTR_COMMON | CPU_FTR_601 | CPU_FTR_HPTE_TABLE, + CPU_FTRS_603 = CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | + CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB | + CPU_FTR_MAYBE_CAN_NAP, + CPU_FTRS_604 = CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | + CPU_FTR_USE_TB | CPU_FTR_604_PERF_MON | CPU_FTR_HPTE_TABLE, + CPU_FTRS_740_NOTAU = CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | + CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB | CPU_FTR_L2CR | + CPU_FTR_HPTE_TABLE | CPU_FTR_MAYBE_CAN_NAP, + CPU_FTRS_740 = CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | + CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB | CPU_FTR_L2CR | + CPU_FTR_TAU | CPU_FTR_HPTE_TABLE | CPU_FTR_MAYBE_CAN_NAP, + CPU_FTRS_750 = CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | + CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB | CPU_FTR_L2CR | + CPU_FTR_TAU | CPU_FTR_HPTE_TABLE | CPU_FTR_MAYBE_CAN_NAP, + CPU_FTRS_750FX1 = CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | + CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB | CPU_FTR_L2CR | + CPU_FTR_TAU | CPU_FTR_HPTE_TABLE | CPU_FTR_MAYBE_CAN_NAP | + CPU_FTR_DUAL_PLL_750FX | CPU_FTR_NO_DPM, + CPU_FTRS_750FX2 = CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | + CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB | CPU_FTR_L2CR | + CPU_FTR_TAU | CPU_FTR_HPTE_TABLE | CPU_FTR_MAYBE_CAN_NAP | + CPU_FTR_NO_DPM, + CPU_FTRS_750FX = CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | + CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB | CPU_FTR_L2CR | + CPU_FTR_TAU | CPU_FTR_HPTE_TABLE | CPU_FTR_MAYBE_CAN_NAP | + CPU_FTR_DUAL_PLL_750FX | CPU_FTR_HAS_HIGH_BATS, + CPU_FTRS_750GX = CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_MAYBE_CAN_DOZE | + CPU_FTR_USE_TB | CPU_FTR_L2CR | CPU_FTR_TAU | + CPU_FTR_HPTE_TABLE | CPU_FTR_MAYBE_CAN_NAP | + CPU_FTR_DUAL_PLL_750FX | CPU_FTR_HAS_HIGH_BATS, + CPU_FTRS_7400_NOTAU = CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | + CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB | CPU_FTR_L2CR | + CPU_FTR_ALTIVEC_COMP | CPU_FTR_HPTE_TABLE | + CPU_FTR_MAYBE_CAN_NAP, + CPU_FTRS_7400 = CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | + CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB | CPU_FTR_L2CR | + CPU_FTR_TAU | CPU_FTR_ALTIVEC_COMP | CPU_FTR_HPTE_TABLE | + CPU_FTR_MAYBE_CAN_NAP, + CPU_FTRS_7450_20 = CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | + CPU_FTR_USE_TB | CPU_FTR_L2CR | CPU_FTR_ALTIVEC_COMP | + CPU_FTR_L3CR | CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 | + CPU_FTR_NEED_COHERENT, + CPU_FTRS_7450_21 = CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | + CPU_FTR_USE_TB | + CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_L2CR | CPU_FTR_ALTIVEC_COMP | + CPU_FTR_L3CR | CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 | + CPU_FTR_NAP_DISABLE_L2_PR | CPU_FTR_L3_DISABLE_NAP | + CPU_FTR_NEED_COHERENT, + CPU_FTRS_7450_23 = CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | + CPU_FTR_USE_TB | + CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_L2CR | CPU_FTR_ALTIVEC_COMP | + CPU_FTR_L3CR | CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 | + CPU_FTR_NAP_DISABLE_L2_PR | CPU_FTR_NEED_COHERENT, + CPU_FTRS_7455_1 = CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | + CPU_FTR_USE_TB | + CPU_FTR_L2CR | CPU_FTR_ALTIVEC_COMP | CPU_FTR_L3CR | + CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 | CPU_FTR_HAS_HIGH_BATS | + CPU_FTR_NEED_COHERENT, + CPU_FTRS_7455_20 = CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | + CPU_FTR_USE_TB | + CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_L2CR | CPU_FTR_ALTIVEC_COMP | + CPU_FTR_L3CR | CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 | + CPU_FTR_NAP_DISABLE_L2_PR | CPU_FTR_L3_DISABLE_NAP | + CPU_FTR_NEED_COHERENT | CPU_FTR_HAS_HIGH_BATS, + CPU_FTRS_7455 = CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | + CPU_FTR_USE_TB | + CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_L2CR | CPU_FTR_ALTIVEC_COMP | + CPU_FTR_L3CR | CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 | + CPU_FTR_NAP_DISABLE_L2_PR | CPU_FTR_HAS_HIGH_BATS | + CPU_FTR_NEED_COHERENT, + CPU_FTRS_7447_10 = CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | + CPU_FTR_USE_TB | + CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_L2CR | CPU_FTR_ALTIVEC_COMP | + CPU_FTR_L3CR | CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 | + CPU_FTR_NAP_DISABLE_L2_PR | CPU_FTR_HAS_HIGH_BATS | + CPU_FTR_NEED_COHERENT | CPU_FTR_NO_BTIC, + CPU_FTRS_7447 = CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | + CPU_FTR_USE_TB | + CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_L2CR | CPU_FTR_ALTIVEC_COMP | + CPU_FTR_L3CR | CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 | + CPU_FTR_NAP_DISABLE_L2_PR | CPU_FTR_HAS_HIGH_BATS | + CPU_FTR_NEED_COHERENT, + CPU_FTRS_7447A = CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | + CPU_FTR_USE_TB | + CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_L2CR | CPU_FTR_ALTIVEC_COMP | + CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 | + CPU_FTR_NAP_DISABLE_L2_PR | CPU_FTR_HAS_HIGH_BATS | + CPU_FTR_NEED_COHERENT, + CPU_FTRS_82XX = CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | + CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB, + CPU_FTRS_G2_LE = CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_MAYBE_CAN_DOZE | + CPU_FTR_USE_TB | CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_HAS_HIGH_BATS, + CPU_FTRS_E300 = CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_MAYBE_CAN_DOZE | + CPU_FTR_USE_TB | CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_HAS_HIGH_BATS, + CPU_FTRS_CLASSIC32 = CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | + CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE, + CPU_FTRS_POWER3_32 = CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | + CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE, + CPU_FTRS_POWER4_32 = CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | + CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE, + CPU_FTRS_970_32 = CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | + CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE | CPU_FTR_ALTIVEC_COMP | + CPU_FTR_MAYBE_CAN_NAP, + CPU_FTRS_8XX = CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB, + CPU_FTRS_40X = CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB, + CPU_FTRS_44X = CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB, + CPU_FTRS_E200 = CPU_FTR_USE_TB, + CPU_FTRS_E500 = CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB, + CPU_FTRS_E500_2 = CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | + CPU_FTR_BIG_PHYS, + CPU_FTRS_GENERIC_32 = CPU_FTR_COMMON, +#ifdef __powerpc64__ + CPU_FTRS_POWER3 = CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | + CPU_FTR_HPTE_TABLE | CPU_FTR_IABR, + CPU_FTRS_RS64 = CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | + CPU_FTR_HPTE_TABLE | CPU_FTR_IABR | + CPU_FTR_MMCRA | CPU_FTR_CTRL, + CPU_FTRS_POWER4 = CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | + CPU_FTR_HPTE_TABLE | CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_MMCRA, + CPU_FTRS_PPC970 = 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_MMCRA, + CPU_FTRS_POWER5 = CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | + CPU_FTR_HPTE_TABLE | CPU_FTR_PPCAS_ARCH_V2 | + CPU_FTR_MMCRA | CPU_FTR_SMT | + CPU_FTR_COHERENT_ICACHE | CPU_FTR_LOCKLESS_TLBIE | + CPU_FTR_MMCRA_SIHV, + CPU_FTRS_CELL = CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | + CPU_FTR_HPTE_TABLE | CPU_FTR_PPCAS_ARCH_V2 | + CPU_FTR_ALTIVEC_COMP | CPU_FTR_MMCRA | CPU_FTR_SMT, + CPU_FTRS_COMPATIBLE = CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | + CPU_FTR_HPTE_TABLE | CPU_FTR_PPCAS_ARCH_V2, +#endif + + CPU_FTRS_POSSIBLE = +#if CLASSIC_PPC + CPU_FTRS_PPC601 | CPU_FTRS_603 | CPU_FTRS_604 | CPU_FTRS_740_NOTAU | + CPU_FTRS_740 | CPU_FTRS_750 | CPU_FTRS_750FX1 | + CPU_FTRS_750FX2 | CPU_FTRS_750FX | CPU_FTRS_750GX | + CPU_FTRS_7400_NOTAU | CPU_FTRS_7400 | CPU_FTRS_7450_20 | + CPU_FTRS_7450_21 | CPU_FTRS_7450_23 | CPU_FTRS_7455_1 | + CPU_FTRS_7455_20 | CPU_FTRS_7455 | CPU_FTRS_7447_10 | + CPU_FTRS_7447 | CPU_FTRS_7447A | CPU_FTRS_82XX | + CPU_FTRS_G2_LE | CPU_FTRS_E300 | CPU_FTRS_CLASSIC32 | +#else + CPU_FTRS_GENERIC_32 | +#endif +#ifdef CONFIG_PPC64BRIDGE + CPU_FTRS_POWER3_32 | +#endif +#ifdef CONFIG_POWER4 + CPU_FTRS_POWER4_32 | CPU_FTRS_970_32 | +#endif +#ifdef CONFIG_8xx + CPU_FTRS_8XX | +#endif +#ifdef CONFIG_40x + CPU_FTRS_40X | +#endif +#ifdef CONFIG_44x + CPU_FTRS_44X | +#endif +#ifdef CONFIG_E200 + CPU_FTRS_E200 | +#endif +#ifdef CONFIG_E500 + CPU_FTRS_E500 | CPU_FTRS_E500_2 | +#endif +#ifdef __powerpc64__ + CPU_FTRS_POWER3 | CPU_FTRS_RS64 | CPU_FTRS_POWER4 | + CPU_FTRS_PPC970 | CPU_FTRS_POWER5 | CPU_FTRS_CELL | +#endif + 0, + + CPU_FTRS_ALWAYS = +#if CLASSIC_PPC + CPU_FTRS_PPC601 & CPU_FTRS_603 & CPU_FTRS_604 & CPU_FTRS_740_NOTAU & + CPU_FTRS_740 & CPU_FTRS_750 & CPU_FTRS_750FX1 & + CPU_FTRS_750FX2 & CPU_FTRS_750FX & CPU_FTRS_750GX & + CPU_FTRS_7400_NOTAU & CPU_FTRS_7400 & CPU_FTRS_7450_20 & + CPU_FTRS_7450_21 & CPU_FTRS_7450_23 & CPU_FTRS_7455_1 & + CPU_FTRS_7455_20 & CPU_FTRS_7455 & CPU_FTRS_7447_10 & + CPU_FTRS_7447 & CPU_FTRS_7447A & CPU_FTRS_82XX & + CPU_FTRS_G2_LE & CPU_FTRS_E300 & CPU_FTRS_CLASSIC32 & +#else + CPU_FTRS_GENERIC_32 & +#endif +#ifdef CONFIG_PPC64BRIDGE + CPU_FTRS_POWER3_32 & +#endif +#ifdef CONFIG_POWER4 + CPU_FTRS_POWER4_32 & CPU_FTRS_970_32 & +#endif +#ifdef CONFIG_8xx + CPU_FTRS_8XX & +#endif +#ifdef CONFIG_40x + CPU_FTRS_40X & +#endif +#ifdef CONFIG_44x + CPU_FTRS_44X & +#endif +#ifdef CONFIG_E200 + CPU_FTRS_E200 & +#endif +#ifdef CONFIG_E500 + CPU_FTRS_E500 & CPU_FTRS_E500_2 & +#endif +#ifdef __powerpc64__ + CPU_FTRS_POWER3 & CPU_FTRS_RS64 & CPU_FTRS_POWER4 & + CPU_FTRS_PPC970 & CPU_FTRS_POWER5 & CPU_FTRS_CELL & +#endif + CPU_FTRS_POSSIBLE, +}; + +static inline int cpu_has_feature(unsigned long feature) +{ + return (CPU_FTRS_ALWAYS & feature) || + (CPU_FTRS_POSSIBLE +#ifndef __powerpc64__ + & cur_cpu_spec[0]->cpu_features +#else + & cur_cpu_spec->cpu_features +#endif + & feature); +} + +#endif /* !__ASSEMBLY__ */ + +#ifdef __ASSEMBLY__ + +#define BEGIN_FTR_SECTION 98: + +#ifndef __powerpc64__ +#define END_FTR_SECTION(msk, val) \ +99: \ + .section __ftr_fixup,"a"; \ + .align 2; \ + .long msk; \ + .long val; \ + .long 98b; \ + .long 99b; \ + .previous +#else /* __powerpc64__ */ +#define END_FTR_SECTION(msk, val) \ +99: \ + .section __ftr_fixup,"a"; \ + .align 3; \ + .llong msk; \ + .llong val; \ + .llong 98b; \ + .llong 99b; \ + .previous +#endif /* __powerpc64__ */ + +#define END_FTR_SECTION_IFSET(msk) END_FTR_SECTION((msk), (msk)) +#define END_FTR_SECTION_IFCLR(msk) END_FTR_SECTION((msk), 0) +#endif /* __ASSEMBLY__ */ + +#endif /* __KERNEL__ */ +#endif /* __ASM_POWERPC_CPUTABLE_H */ diff --git a/include/asm-ppc/cputable.h b/include/asm-ppc/cputable.h deleted file mode 100644 --- a/include/asm-ppc/cputable.h +++ /dev/null @@ -1,128 +0,0 @@ -/* - * include/asm-ppc/cputable.h - * - * Copyright (C) 2001 Ben. 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. - */ - -#ifndef __ASM_PPC_CPUTABLE_H -#define __ASM_PPC_CPUTABLE_H - -/* Exposed to userland CPU features */ -#define PPC_FEATURE_32 0x80000000 -#define PPC_FEATURE_64 0x40000000 -#define PPC_FEATURE_601_INSTR 0x20000000 -#define PPC_FEATURE_HAS_ALTIVEC 0x10000000 -#define PPC_FEATURE_HAS_FPU 0x08000000 -#define PPC_FEATURE_HAS_MMU 0x04000000 -#define PPC_FEATURE_HAS_4xxMAC 0x02000000 -#define PPC_FEATURE_UNIFIED_CACHE 0x01000000 -#define PPC_FEATURE_HAS_SPE 0x00800000 -#define PPC_FEATURE_HAS_EFP_SINGLE 0x00400000 -#define PPC_FEATURE_HAS_EFP_DOUBLE 0x00200000 - -#ifdef __KERNEL__ - -#ifndef __ASSEMBLY__ - -/* This structure can grow, it's real size is used by head.S code - * via the mkdefs mecanism. - */ -struct cpu_spec; - -typedef void (*cpu_setup_t)(unsigned long offset, int cpu_nr, struct cpu_spec* spec); - -struct cpu_spec { - /* CPU is matched via (PVR & pvr_mask) == pvr_value */ - unsigned int pvr_mask; - unsigned int pvr_value; - - char *cpu_name; - unsigned int cpu_features; /* Kernel features */ - unsigned int cpu_user_features; /* Userland features */ - - /* cache line sizes */ - 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 - */ - cpu_setup_t cpu_setup; -}; - -extern struct cpu_spec cpu_specs[]; -extern struct cpu_spec *cur_cpu_spec[]; - -static inline unsigned int cpu_has_feature(unsigned int feature) -{ - return cur_cpu_spec[0]->cpu_features & feature; -} - -#endif /* __ASSEMBLY__ */ - -/* CPU kernel features */ -#define CPU_FTR_SPLIT_ID_CACHE 0x00000001 -#define CPU_FTR_L2CR 0x00000002 -#define CPU_FTR_SPEC7450 0x00000004 -#define CPU_FTR_ALTIVEC 0x00000008 -#define CPU_FTR_TAU 0x00000010 -#define CPU_FTR_CAN_DOZE 0x00000020 -#define CPU_FTR_USE_TB 0x00000040 -#define CPU_FTR_604_PERF_MON 0x00000080 -#define CPU_FTR_601 0x00000100 -#define CPU_FTR_HPTE_TABLE 0x00000200 -#define CPU_FTR_CAN_NAP 0x00000400 -#define CPU_FTR_L3CR 0x00000800 -#define CPU_FTR_L3_DISABLE_NAP 0x00001000 -#define CPU_FTR_NAP_DISABLE_L2_PR 0x00002000 -#define CPU_FTR_DUAL_PLL_750FX 0x00004000 -#define CPU_FTR_NO_DPM 0x00008000 -#define CPU_FTR_HAS_HIGH_BATS 0x00010000 -#define CPU_FTR_NEED_COHERENT 0x00020000 -#define CPU_FTR_NO_BTIC 0x00040000 -#define CPU_FTR_BIG_PHYS 0x00080000 - -#ifdef __ASSEMBLY__ - -#define BEGIN_FTR_SECTION 98: - -#define END_FTR_SECTION(msk, val) \ -99: \ - .section __ftr_fixup,"a"; \ - .align 2; \ - .long msk; \ - .long val; \ - .long 98b; \ - .long 99b; \ - .previous - -#else - -#define BEGIN_FTR_SECTION "98:\n" -#define END_FTR_SECTION(msk, val) \ -"99:\n" \ -" .section __ftr_fixup,\"a\";\n" \ -" .align 2;\n" \ -" .long "#msk";\n" \ -" .long "#val";\n" \ -" .long 98b;\n" \ -" .long 99b;\n" \ -" .previous\n" - - -#endif /* __ASSEMBLY__ */ - -#define END_FTR_SECTION_IFSET(msk) END_FTR_SECTION((msk), (msk)) -#define END_FTR_SECTION_IFCLR(msk) END_FTR_SECTION((msk), 0) - -#endif /* __ASM_PPC_CPUTABLE_H */ -#endif /* __KERNEL__ */ - diff --git a/include/asm-ppc/mmu_context.h b/include/asm-ppc/mmu_context.h --- a/include/asm-ppc/mmu_context.h +++ b/include/asm-ppc/mmu_context.h @@ -164,13 +164,11 @@ static inline void switch_mm(struct mm_s struct task_struct *tsk) { #ifdef CONFIG_ALTIVEC - asm volatile ( - BEGIN_FTR_SECTION - "dssall;\n" + if (cpu_has_feature(CPU_FTR_ALTIVEC)) + asm volatile ("dssall;\n" #ifndef CONFIG_POWER4 "sync;\n" /* G4 needs a sync here, G5 apparently not */ #endif - END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC) : : ); #endif /* CONFIG_ALTIVEC */ diff --git a/include/asm-ppc64/cputable.h b/include/asm-ppc64/cputable.h deleted file mode 100644 --- a/include/asm-ppc64/cputable.h +++ /dev/null @@ -1,167 +0,0 @@ -/* - * include/asm-ppc64/cputable.h - * - * Copyright (C) 2001 Ben. Herrenschmidt (benh at kernel.crashing.org) - * - * Modifications for ppc64: - * Copyright (C) 2003 Dave Engebretsen - * - * 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_PPC_CPUTABLE_H -#define __ASM_PPC_CPUTABLE_H - -#include -#include /* for ASM_CONST */ - -/* Exposed to userland CPU features - Must match ppc32 definitions */ -#define PPC_FEATURE_32 0x80000000 -#define PPC_FEATURE_64 0x40000000 -#define PPC_FEATURE_601_INSTR 0x20000000 -#define PPC_FEATURE_HAS_ALTIVEC 0x10000000 -#define PPC_FEATURE_HAS_FPU 0x08000000 -#define PPC_FEATURE_HAS_MMU 0x04000000 -#define PPC_FEATURE_HAS_4xxMAC 0x02000000 -#define PPC_FEATURE_UNIFIED_CACHE 0x01000000 - -#ifdef __KERNEL__ - -#ifndef __ASSEMBLY__ - -/* This structure can grow, it's real size is used by head.S code - * via the mkdefs mechanism. - */ -struct cpu_spec; -struct op_powerpc_model; - -typedef void (*cpu_setup_t)(unsigned long offset, struct cpu_spec* spec); - -struct cpu_spec { - /* CPU is matched via (PVR & pvr_mask) == pvr_value */ - unsigned int pvr_mask; - unsigned int pvr_value; - - char *cpu_name; - unsigned long cpu_features; /* Kernel features */ - unsigned int cpu_user_features; /* Userland features */ - - /* cache line sizes */ - 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 - */ - cpu_setup_t cpu_setup; - - /* Used by oprofile userspace to select the right counters */ - char *oprofile_cpu_type; - - /* Processor specific oprofile operations */ - struct op_powerpc_model *oprofile_model; -}; - -extern struct cpu_spec cpu_specs[]; -extern struct cpu_spec *cur_cpu_spec; - -static inline unsigned long cpu_has_feature(unsigned long feature) -{ - return cur_cpu_spec->cpu_features & feature; -} - -#endif /* __ASSEMBLY__ */ - -/* CPU kernel features */ - -/* Retain the 32b definitions for the time being - use bottom half of word */ -#define CPU_FTR_SPLIT_ID_CACHE ASM_CONST(0x0000000000000001) -#define CPU_FTR_L2CR ASM_CONST(0x0000000000000002) -#define CPU_FTR_SPEC7450 ASM_CONST(0x0000000000000004) -#define CPU_FTR_ALTIVEC ASM_CONST(0x0000000000000008) -#define CPU_FTR_TAU ASM_CONST(0x0000000000000010) -#define CPU_FTR_CAN_DOZE ASM_CONST(0x0000000000000020) -#define CPU_FTR_USE_TB ASM_CONST(0x0000000000000040) -#define CPU_FTR_604_PERF_MON ASM_CONST(0x0000000000000080) -#define CPU_FTR_601 ASM_CONST(0x0000000000000100) -#define CPU_FTR_HPTE_TABLE ASM_CONST(0x0000000000000200) -#define CPU_FTR_CAN_NAP ASM_CONST(0x0000000000000400) -#define CPU_FTR_L3CR ASM_CONST(0x0000000000000800) -#define CPU_FTR_L3_DISABLE_NAP ASM_CONST(0x0000000000001000) -#define CPU_FTR_NAP_DISABLE_L2_PR ASM_CONST(0x0000000000002000) -#define CPU_FTR_DUAL_PLL_750FX ASM_CONST(0x0000000000004000) - -/* Add the 64b processor unique features in the top half of the word */ -#define CPU_FTR_SLB ASM_CONST(0x0000000100000000) -#define CPU_FTR_16M_PAGE ASM_CONST(0x0000000200000000) -#define CPU_FTR_TLBIEL ASM_CONST(0x0000000400000000) -#define CPU_FTR_NOEXECUTE ASM_CONST(0x0000000800000000) -#define CPU_FTR_NODSISRALIGN ASM_CONST(0x0000001000000000) -#define CPU_FTR_IABR ASM_CONST(0x0000002000000000) -#define CPU_FTR_MMCRA ASM_CONST(0x0000004000000000) -/* 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) -#define CPU_FTR_MMCRA_SIHV ASM_CONST(0x0000080000000000) -#define CPU_FTR_CTRL ASM_CONST(0x0000100000000000) - -#ifndef __ASSEMBLY__ - -#define COMMON_USER_PPC64 (PPC_FEATURE_32 | PPC_FEATURE_64 | \ - PPC_FEATURE_HAS_FPU | PPC_FEATURE_HAS_MMU) - -#define CPU_FTR_PPCAS_ARCH_V2_BASE (CPU_FTR_SLB | \ - CPU_FTR_TLBIEL | CPU_FTR_NOEXECUTE | \ - CPU_FTR_NODSISRALIGN | CPU_FTR_CTRL) - -/* iSeries doesn't support large pages */ -#ifdef CONFIG_PPC_ISERIES -#define CPU_FTR_PPCAS_ARCH_V2 (CPU_FTR_PPCAS_ARCH_V2_BASE) -#else -#define CPU_FTR_PPCAS_ARCH_V2 (CPU_FTR_PPCAS_ARCH_V2_BASE | CPU_FTR_16M_PAGE) -#endif /* CONFIG_PPC_ISERIES */ - -#endif /* __ASSEMBLY */ - -#ifdef __ASSEMBLY__ - -#define BEGIN_FTR_SECTION 98: - -#define END_FTR_SECTION(msk, val) \ -99: \ - .section __ftr_fixup,"a"; \ - .align 3; \ - .llong msk; \ - .llong val; \ - .llong 98b; \ - .llong 99b; \ - .previous - -#else - -#define BEGIN_FTR_SECTION "98:\n" -#define END_FTR_SECTION(msk, val) \ -"99:\n" \ -" .section __ftr_fixup,\"a\";\n" \ -" .align 3;\n" \ -" .llong "#msk";\n" \ -" .llong "#val";\n" \ -" .llong 98b;\n" \ -" .llong 99b;\n" \ -" .previous\n" - -#endif /* __ASSEMBLY__ */ - -#define END_FTR_SECTION_IFSET(msk) END_FTR_SECTION((msk), (msk)) -#define END_FTR_SECTION_IFCLR(msk) END_FTR_SECTION((msk), 0) - -#endif /* __ASM_PPC_CPUTABLE_H */ -#endif /* __KERNEL__ */ - From geoffrey.levand at am.sony.com Sat Sep 24 06:13:57 2005 From: geoffrey.levand at am.sony.com (Geoff Levand) Date: Fri, 23 Sep 2005 13:13:57 -0700 Subject: [PATCH] Fix Make warning about zImage multiple dependencies In-Reply-To: <17194.65326.779351.773644@kitch0.watson.ibm.com> References: <17194.65326.779351.773644@kitch0.watson.ibm.com> Message-ID: <43346205.1000609@am.sony.com> Paul, This is against the current in kernel.org's ppc64-2.6.git. It fixes the minor problem below and adds better multi-platform image build support. Please apply. Jimi Xenidis wrote: > The patch from > http://patchwork.ozlabs.org/linuxppc64/patch?id=2022 > > Causes a make warning if multiple CONFIG_PPC_* cause zImage to be in > the dependency line more than once. > > The following patch fixes it in a way that avoids complex if's, tho it > may be a little obscure :) > I took Jimi's idea and did some more rework to better handle when multiple CONFIG_PPC_ options are selected. Now it is possible to build a multi-platform image and specify which platform to install: $ make INSTALL_MOD_PATH=/target/g5 INSTALL_PATH=/target/g5/boot install-zImage.vmode $ make INSTALL_MOD_PATH=/target/pseries INSTALL_PATH=/target/pseries/boot install-zImage I also added some descriptive comments and lines for 'make help'. -Geoff Parts-by: Jimi Xenidis Signed-off-by: Geoff Levand Index: ppc64-2.6.git.makefile/arch/ppc64/Makefile =================================================================== --- ppc64-2.6.git.makefile.orig/arch/ppc64/Makefile 2005-09-23 12:29:57.000000000 -0700 +++ ppc64-2.6.git.makefile/arch/ppc64/Makefile 2005-09-23 13:06:21.000000000 -0700 @@ -89,29 +89,46 @@ boot := arch/ppc64/boot -boottargets-$(CONFIG_PPC_PSERIES) += zImage zImage.initrd -boottargets-$(CONFIG_PPC_PMAC) += zImage.vmode zImage.initrd.vmode -boottargets-$(CONFIG_PPC_MAPLE) += zImage zImage.initrd -boottargets-$(CONFIG_PPC_ISERIES) += vmlinux.sminitrd vmlinux.initrd vmlinux.sm -boottargets-$(CONFIG_PPC_BPA) += zImage zImage.initrd -$(boottargets-y): vmlinux - $(Q)$(MAKE) $(build)=$(boot) $(boot)/$@ +# To assure a usable image is built these should accend in order +# of dependence. +defaultimage-$(CONFIG_PPC_ISERIES) := vmlinux +defaultimage-$(CONFIG_PPC_PMAC) := vmlinux +defaultimage-$(CONFIG_PPC_PSERIES) := zImage +defaultimage-$(CONFIG_PPC_MAPLE) := zImage +KBUILD_IMAGE := $(defaultimage-y) +all: vmlinux $(KBUILD_IMAGE) +# Note that there is a problem with this target when multiple +# CONFIG_PPC_ options are selected. +bootimage-$(CONFIG_PPC_BPA) := $(boot)/zImage bootimage-$(CONFIG_PPC_PSERIES) := $(boot)/zImage -bootimage-$(CONFIG_PPC_PMAC) := vmlinux +bootimage-$(CONFIG_PPC_PMAC) := $(boot)/zImage.vmode bootimage-$(CONFIG_PPC_MAPLE) := $(boot)/zImage -bootimage-$(CONFIG_PPC_BPA) := zImage bootimage-$(CONFIG_PPC_ISERIES) := vmlinux BOOTIMAGE := $(bootimage-y) install: vmlinux $(Q)$(MAKE) $(build)=$(boot) BOOTIMAGE=$(BOOTIMAGE) $@ -defaultimage-$(CONFIG_PPC_PSERIES) := zImage -defaultimage-$(CONFIG_PPC_PMAC) := vmlinux -defaultimage-$(CONFIG_PPC_MAPLE) := zImage -defaultimage-$(CONFIG_PPC_ISERIES) := vmlinux -KBUILD_IMAGE := $(defaultimage-y) -all: $(KBUILD_IMAGE) +# These targets handle build and install when multiple CONFIG_PPC_ +# options are selected. +make-zImage-$(CONFIG_PPC_PSERIES) = y +make-zImage-$(CONFIG_PPC_MAPLE) = y +make-zImage-$(CONFIG_PPC_BPA) = y +make-vmode-$(CONFIG_PPC_PMAC) = y +make-vmlinux.sm-$(CONFIG_PPC_ISERIES) = y + +boottargets-$(make-vmlinux.sm-y) += vmlinux.sminitrd vmlinux.initrd vmlinux.sm +boottargets-$(make-vmode-y) += zImage.vmode zImage.initrd.vmode +boottargets-$(make-zImage-y) += zImage zImage.initrd + +$(boottargets-y): vmlinux + $(Q)$(MAKE) $(build)=$(boot) $(boot)/$@ + +install-vmlinux: vmlinux + $(Q)$(MAKE) $(build)=$(boot) BOOTIMAGE=vmlinux install + +$(patsubst %,install-%,$(boottargets-y)): vmlinux + $(Q)$(MAKE) $(build)=$(boot) BOOTIMAGE=$(boot)/$(subst install-,,$@) install archclean: $(Q)$(MAKE) $(clean)=$(boot) @@ -126,10 +143,16 @@ $(Q)ln -fsn $(srctree)/include/asm-powerpc arch/$(ARCH)/include/asm define archhelp - echo ' zImage.vmode - Compressed kernel image (arch/$(ARCH)/boot/zImage.vmode)' - echo ' zImage.initrd.vmode - Compressed kernel image with initrd attached,' - echo ' sourced from arch/$(ARCH)/boot/ramdisk.image.gz' - echo ' (arch/$(ARCH)/boot/zImage.initrd.vmode)' - echo ' zImage - zImage for pSeries machines' - echo ' zImage.initrd - zImage with initrd for pSeries machines' + echo ' zImage.vmode - Compressed kernel image suitable for PowerMac' + echo ' machines ($(boot)/zImage.vmode)' + echo ' zImage.initrd.vmode - Compressed kernel image with initrd attached,' + echo ' sourced from $(boot)/ramdisk.image.gz' + echo ' ($(boot)/zImage.initrd.vmode)' + echo ' zImage - zImage for pSeries machines' + echo ' zImage.initrd - zImage with initrd for pSeries machines' + echo '' + echo ' install-zImage.vmode - Install $(boot)/zImage.vmode' + echo ' install-zImage.initrd.vmode - Install $(boot)/zImage.initrd.vmode' + echo ' install-zImage - Install $(boot)/zImage' + echo ' install-zImage.initrd - Install $(boot)/zImage.initrd' endef From paulus at samba.org Sat Sep 24 10:04:12 2005 From: paulus at samba.org (Paul Mackerras) Date: Sat, 24 Sep 2005 10:04:12 +1000 Subject: [PATCH] powerpc: merged asm/cputable.h In-Reply-To: References: Message-ID: <17204.38908.767118.59625@cargo.ozlabs.ibm.com> Kumar Gala writes: > +#ifdef __powerpc64__ > +extern struct cpu_spec *cur_cpu_spec; > +#else /* __powerpc64__ */ > +extern struct cpu_spec *cur_cpu_spec[]; > +#endif /* __powerpc64__ */ I would like to see this unified - it makes no sense for them to be different. We are unlikely to support asymmetric multiprocessing any time soon, so let's go with the single cur_cpu_spec pointer (a la ppc64). Paul. From paulus at samba.org Sat Sep 24 10:46:33 2005 From: paulus at samba.org (Paul Mackerras) Date: Sat, 24 Sep 2005 10:46:33 +1000 Subject: PATCH powerpc Merge asm-ppc*/rwsem.h In-Reply-To: <606.1127460740@warthog.cambridge.redhat.com> References: <606.1127460740@warthog.cambridge.redhat.com> Message-ID: <17204.41449.162199.476757@cargo.ozlabs.ibm.com> David Howells writes: > rwsems on ppc64 should really be using a 64-bit counter, not a 32-bit counter, > otherwise you limit the maximum number of processes to 32K-ish. > > The counter should be "signed long" really. It has long annoyed me that we waste half the bits in the rwsem counter, just because you assume a lowest-common-denominator set of atomic ops. IIRC your implementation replaced the earlier ppc implementation which had a 32-bit counter and didn't have the 32k process limit. I'd have to study it in more detail, but I strongly suspect that with an atomic operation that did something like *p = max(*p, limit) + inc atomically (or alternatively a min), we could increase the limit to at least 1G processes with a 32-bit counter, without needing to change your common slow-path implementation. Such an atomic op is easy to implement with load-and-reserve / store-conditional instructions. Look at __sem_update_count in arch/ppc64/kernel/semaphore.c for an example. Paul. From sfr at canb.auug.org.au Sat Sep 24 10:48:27 2005 From: sfr at canb.auug.org.au (Stephen Rothwell) Date: Sat, 24 Sep 2005 10:48:27 +1000 Subject: [PATCH] powerpc: merged asm/cputable.h In-Reply-To: <17204.38908.767118.59625@cargo.ozlabs.ibm.com> References: <17204.38908.767118.59625@cargo.ozlabs.ibm.com> Message-ID: <20050924104827.114939ca.sfr@canb.auug.org.au> On Sat, 24 Sep 2005 10:04:12 +1000 Paul Mackerras wrote: > > Kumar Gala writes: > > > +#ifdef __powerpc64__ > > +extern struct cpu_spec *cur_cpu_spec; > > +#else /* __powerpc64__ */ > > +extern struct cpu_spec *cur_cpu_spec[]; > > +#endif /* __powerpc64__ */ > > I would like to see this unified - it makes no sense for them to be > different. We are unlikely to support asymmetric multiprocessing any > time soon, so let's go with the single cur_cpu_spec pointer (a la > ppc64). Michael Ellerman also has a patch that makes this a struct (i.e. not a pointer) which allows us to mark the array of cpuspec's that we test against at boot time as __init. Maybe he could do the ppc32 single cpu_spec as part of that. -- 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/20050924/2b13e385/attachment.pgp From sonny at burdell.org Sat Sep 24 11:41:07 2005 From: sonny at burdell.org (Sonny Rao) Date: Fri, 23 Sep 2005 21:41:07 -0400 Subject: [PATCH] ppc64: iMac G5 cpufreq support In-Reply-To: <1127366605.32344.28.camel@gaston> References: <1127282249.4386.101.camel@gaston> <1127282471.4386.104.camel@gaston> <1127366605.32344.28.camel@gaston> Message-ID: <20050924014107.GA1228@kevlar.burdell.org> On Thu, Sep 22, 2005 at 03:23:24PM +1000, Benjamin Herrenschmidt wrote: > And yet another version fixing some bogosity in the manipulation of > MSR_EE (damn, I was tired) > > This applies on top of the big SMU update posted earlier. It adds > cpufreq support for iMac G5 (and SMU based desktop, though that one was > untested, testers welcome). It supports full and half speed and also > does voltage switching for more power savings. > > Next step is proper thermal control to make those fans quiet once for > all ! http://www.alphaworks.ibm.com/tech/powerscale4ppc?open&S_TACT=105AGX59&S_CMP=GR How does the info in the above link relate to your work on this? From benh at kernel.crashing.org Sat Sep 24 15:33:47 2005 From: benh at kernel.crashing.org (Benjamin Herrenschmidt) Date: Sat, 24 Sep 2005 15:33:47 +1000 Subject: [PATCH] ppc64: iMac G5 cpufreq support In-Reply-To: <20050924014107.GA1228@kevlar.burdell.org> References: <1127282249.4386.101.camel@gaston> <1127282471.4386.104.camel@gaston> <1127366605.32344.28.camel@gaston> <20050924014107.GA1228@kevlar.burdell.org> Message-ID: <1127540028.27674.28.camel@gaston> > http://www.alphaworks.ibm.com/tech/powerscale4ppc?open&S_TACT=105AGX59&S_CMP=GR > > How does the info in the above link relate to your work on this? Well, I use the mecanism described in the above link, that is the 970FX ability to switch to 1/2 frequency (we don't use 1/4 on those machines, it doesn't seem to be supported by the HW in some way, possibly a northbridge issue). Ben. From aw-confirm at eBay.com Sun Sep 25 00:02:42 2005 From: aw-confirm at eBay.com (Administrator) Date: Sat, 24 Sep 2005 17:02:42 +0300 Subject: eBay: Notification! Message-ID: An HTML attachment was scrubbed... URL: http://ozlabs.org/pipermail/linuxppc64-dev/attachments/20050924/96c1e036/attachment.htm From segher at kernel.crashing.org Sun Sep 25 00:58:01 2005 From: segher at kernel.crashing.org (Segher Boessenkool) Date: Sat, 24 Sep 2005 16:58:01 +0200 Subject: G5 pci probing regression In-Reply-To: <17199.22161.701821.240558@cargo.ozlabs.ibm.com> References: <20050918221220.GA31975@lst.de> <17197.59822.43168.956195@cargo.ozlabs.ibm.com> <20050919095130.GA8549@lst.de> <17199.14769.280974.803103@cargo.ozlabs.ibm.com> <20050919225333.GA21782@lst.de> <17199.22161.701821.240558@cargo.ozlabs.ibm.com> Message-ID: <119e2acc995eb0363b5afb95e409e2a5@kernel.crashing.org> > if (addr0 & 0x02000000) { > - flags |= IORESOURCE_MEM; > + flags = IORESOURCE_MEM | PCI_BASE_ADDRESS_SPACE_MEMORY; > + flags |= (addr0 >> 22) & PCI_BASE_ADDRESS_MEM_TYPE_64; > + flags |= (addr0 >> 28) & PCI_BASE_ADDRESS_MEM_TYPE_1M; > Could you please write those last two lines as if (addr0 & 0x01000000) flags |= PCI_BASE_ADDRESS_MEM_TYPE_64; if (addr0 & 0x20000000) flags |= PCI_BASE_ADDRESS_MEM_TYPE_1M; because it took me a moment to figure out what is going on here (I almost thought _I_ wrote that code!) Segher From segher at kernel.crashing.org Fri Sep 23 06:26:30 2005 From: segher at kernel.crashing.org (Segher Boessenkool) Date: Thu, 22 Sep 2005 22:26:30 +0200 Subject: [PATCH] ppc64: iMac G5 cpufreq support In-Reply-To: <1127366605.32344.28.camel@gaston> References: <1127282249.4386.101.camel@gaston> <1127282471.4386.104.camel@gaston> <1127366605.32344.28.camel@gaston> Message-ID: > +_GLOBAL(scom970_read) > + /* interrupts off */ > + mfmsr r4 > + ori r0,r4,MSR_EE > + xori r0,r0,MSR_EE > + mtmsrd r0,1 > + > + /* rotate address 8 bits left, mask out low 16 bits as they > + * aren't implemented on current CPUs and must be 0'd, Comment is bogus (the low 16 bits _do_ have a defined function; the high 16 bits are the high 16 bits of the SCOM address; the low 7 bits of the 23-bit SCOM address are always zero and not implemented in this register; what you are _actually_ doing here is passing in the serial SCOM address and the parity bit, and shifting it and clearing out the parity bit so it is the right format for the SCOMC register). > + * and finally or in RW bit > + */ > + rlwinm r3,r3,8,0,15 > + ori r3,r3,0x8000 > + > + /* do the actual scom read */ > + sync > + mtspr SPRN_SCOMC,r3 > + isync > + mfspr r3,SPRN_SCOMD > + mfspr r0,SPRN_SCOMC > + sync > + isync Instead: mtspr SPRN_SCOMC,r3 isync mfspr r3,SPRN_SCOMD mfspr r0,SPRN_SCOMC > +_GLOBAL(scom970_write) [snip] > + mtspr SPRN_SCOMD,r4 /* write data */ > + mtspr SPRN_SCOMC,r3 /* write command */ > + sync > + isync > + mfspr 3,SPRN_SCOMC Instead: mtspr SPRN_SCOMD,r4 /* write data */ isync mtspr SPRN_SCOMC,r3 /* write command */ isync mfspr 3,SPRN_SCOMC Cheers, Segher From kumar.gala at freescale.com Sun Sep 25 01:35:03 2005 From: kumar.gala at freescale.com (Kumar Gala) Date: Sat, 24 Sep 2005 10:35:03 -0500 Subject: [PATCH] powerpc: merged asm/cputable.h In-Reply-To: <20050924104827.114939ca.sfr@canb.auug.org.au> References: <17204.38908.767118.59625@cargo.ozlabs.ibm.com> <20050924104827.114939ca.sfr@canb.auug.org.au> Message-ID: On Sep 23, 2005, at 7:48 PM, Stephen Rothwell wrote: > On Sat, 24 Sep 2005 10:04:12 +1000 Paul Mackerras > wrote: > >> >> Kumar Gala writes: >> >> >>> +#ifdef __powerpc64__ >>> +extern struct cpu_spec *cur_cpu_spec; >>> +#else /* __powerpc64__ */ >>> +extern struct cpu_spec *cur_cpu_spec[]; >>> +#endif /* __powerpc64__ */ >>> >> >> I would like to see this unified - it makes no sense for them to be >> different. We are unlikely to support asymmetric multiprocessing any >> time soon, so let's go with the single cur_cpu_spec pointer (a la >> ppc64). >> > > Michael Ellerman also has a patch that makes this a struct (i.e. not a > pointer) which allows us to mark the array of cpuspec's that we test > against at boot time as __init. Maybe he could do the ppc32 single > cpu_spec as part of that. I'm all for unifying this as well. If Michael can post his patch I'll look at fixing up this issue. Let's merge the current patch and follow it up with an update that includes this fix and Michael's work. - kumar From benh at kernel.crashing.org Sun Sep 25 08:05:27 2005 From: benh at kernel.crashing.org (Benjamin Herrenschmidt) Date: Sun, 25 Sep 2005 08:05:27 +1000 Subject: [PATCH] ppc64: iMac G5 cpufreq support In-Reply-To: References: <1127282249.4386.101.camel@gaston> <1127282471.4386.104.camel@gaston> <1127366605.32344.28.camel@gaston> Message-ID: <1127599527.27674.42.camel@gaston> > Comment is bogus (the low 16 bits _do_ have a defined > function; the high 16 bits are the high 16 bits of the > SCOM address; the low 7 bits of the 23-bit SCOM address > are always zero and not implemented in this register; > what you are _actually_ doing here is passing in the > serial SCOM address and the parity bit, and shifting it > and clearing out the parity bit so it is the right format > for the SCOMC register). Yah, I know what I'm doing thanks :) The comment is a bit misleading indeed. It should read something like clear out the low 8 bits of the address (including parity) as they aren't supported by the SCOMC and always zero. > mtspr SPRN_SCOMC,r3 > isync > mfspr r3,SPRN_SCOMD > mfspr r0,SPRN_SCOMC You just removed a few sync's... > Instead: > mtspr SPRN_SCOMD,r4 /* write data */ > isync > mtspr SPRN_SCOMC,r3 /* write command */ > isync > mfspr 3,SPRN_SCOMC Here; you also just changed a few isync's ... oh well, I'll have a look. I did the sync based on apple stuff, I suspect a sync before would still be usedful to make sure pending memory accesses are completed, not specifically for the frequency change, but in general as the SCOM can be used to manipulate the L2 cache among others and I may use it to put the cache in direct mode for flushing one of these days. Ben. From segher at kernel.crashing.org Mon Sep 26 02:50:19 2005 From: segher at kernel.crashing.org (Segher Boessenkool) Date: Sun, 25 Sep 2005 18:50:19 +0200 Subject: [PATCH] ppc64: iMac G5 cpufreq support In-Reply-To: <1127599527.27674.42.camel@gaston> References: <1127282249.4386.101.camel@gaston> <1127282471.4386.104.camel@gaston> <1127366605.32344.28.camel@gaston> <1127599527.27674.42.camel@gaston> Message-ID: <3c4dce79b0cd0c12ca1dfa6672657794@kernel.crashing.org> > Yah, I know what I'm doing thanks :) The comment is a bit > misleading indeed. Yes I know you know what you're doing; namely, you're typing misleading comments ;-P > You just removed a few sync's... > Here; you also just changed a few isync's ... I removed some unnecessary sync's; but the important thing is, after *every* mtspr SCOM[CD], you need an isync. So I added those. Segher From michael at ellerman.id.au Mon Sep 26 11:57:36 2005 From: michael at ellerman.id.au (Michael Ellerman) Date: Mon, 26 Sep 2005 11:57:36 +1000 Subject: [PATCH] powerpc: merged asm/cputable.h In-Reply-To: References: <20050924104827.114939ca.sfr@canb.auug.org.au> Message-ID: <200509261157.37514.michael@ellerman.id.au> On Sun, 25 Sep 2005 01:35, Kumar Gala wrote: > On Sep 23, 2005, at 7:48 PM, Stephen Rothwell wrote: > > On Sat, 24 Sep 2005 10:04:12 +1000 Paul Mackerras > > > > wrote: > >> Kumar Gala writes: > >>> +#ifdef __powerpc64__ > >>> +extern struct cpu_spec *cur_cpu_spec; > >>> +#else /* __powerpc64__ */ > >>> +extern struct cpu_spec *cur_cpu_spec[]; > >>> +#endif /* __powerpc64__ */ > >> > >> I would like to see this unified - it makes no sense for them to be > >> different. We are unlikely to support asymmetric multiprocessing any > >> time soon, so let's go with the single cur_cpu_spec pointer (a la > >> ppc64). > > > > Michael Ellerman also has a patch that makes this a struct (i.e. not a > > pointer) which allows us to mark the array of cpuspec's that we test > > against at boot time as __init. Maybe he could do the ppc32 single > > cpu_spec as part of that. > > I'm all for unifying this as well. If Michael can post his patch > I'll look at fixing up this issue. Let's merge the current patch and > follow it up with an update that includes this fix and Michael's work. Here's a version of my patch updated to apply on top of the merge tree. It'll be a lot cleaner when ppc32 has a single cur_cpu_spec, as we'll be able to remove a lot of the #ifdefs. cheers Signed-off-by: Michael Ellerman --- arch/powerpc/oprofile/common.c | 8 +++---- arch/powerpc/oprofile/op_model_power4.c | 6 ++--- arch/ppc64/kernel/asm-offsets.c | 4 --- arch/ppc64/kernel/cputable.c | 33 ++++++++++++++++++++++++++------ arch/ppc64/kernel/head.S | 11 ---------- arch/ppc64/kernel/idle_power4.S | 5 +--- arch/ppc64/kernel/misc.S | 32 ------------------------------- arch/ppc64/kernel/prom.c | 12 +++++------ arch/ppc64/kernel/setup.c | 8 +++---- arch/ppc64/kernel/sysfs.c | 32 +++++++++++++++---------------- include/asm-powerpc/cputable.h | 24 +++++++++++++++++------ include/asm-powerpc/elf.h | 2 - Index: kexec/include/asm-powerpc/cputable.h =================================================================== --- kexec.orig/include/asm-powerpc/cputable.h +++ kexec/include/asm-powerpc/cputable.h @@ -26,7 +26,7 @@ struct cpu_spec; struct op_powerpc_model; #ifdef __powerpc64__ -typedef void (*cpu_setup_t)(unsigned long offset, struct cpu_spec* spec); +typedef void (*cpu_setup_t)(struct cpu_spec* spec); #else /* __powerpc64__ */ typedef void (*cpu_setup_t)(unsigned long offset, int cpu_nr, struct cpu_spec* spec); #endif /* __powerpc64__ */ @@ -61,10 +61,10 @@ struct cpu_spec { #endif /* __powerpc64__ */ }; -extern struct cpu_spec cpu_specs[]; +extern void identify_cpu(void); #ifdef __powerpc64__ -extern struct cpu_spec *cur_cpu_spec; +extern struct cpu_spec cur_cpu_spec; #else /* __powerpc64__ */ extern struct cpu_spec *cur_cpu_spec[]; #endif /* __powerpc64__ */ @@ -398,14 +398,26 @@ static inline int cpu_has_feature(unsign { return (CPU_FTRS_ALWAYS & feature) || (CPU_FTRS_POSSIBLE -#ifndef __powerpc64__ - & cur_cpu_spec[0]->cpu_features +#ifdef __powerpc64__ + & cur_cpu_spec.cpu_features #else - & cur_cpu_spec->cpu_features + & cur_cpu_spec[0].cpu_features #endif & feature); } +#ifdef __powerpc64__ +static inline void cpu_set_feature(unsigned long feature) +{ + cur_cpu_spec.cpu_features |= feature; +} + +static inline void cpu_unset_feature(unsigned long feature) +{ + cur_cpu_spec.cpu_features &= ~feature; +} +#endif + #endif /* !__ASSEMBLY__ */ #ifdef __ASSEMBLY__ Index: kexec/arch/ppc64/kernel/cputable.c =================================================================== --- kexec.orig/arch/ppc64/kernel/cputable.c +++ kexec/arch/ppc64/kernel/cputable.c @@ -22,7 +22,7 @@ #include #include -struct cpu_spec* cur_cpu_spec = NULL; +struct cpu_spec cur_cpu_spec; EXPORT_SYMBOL(cur_cpu_spec); /* NOTE: @@ -32,12 +32,12 @@ EXPORT_SYMBOL(cur_cpu_spec); * part of the cputable though. That has to be fixed for both ppc32 * and ppc64 */ -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_power3(struct cpu_spec* spec); +extern void __setup_cpu_power4(struct cpu_spec* spec); +extern void __setup_cpu_ppc970(struct cpu_spec* spec); +extern void __setup_cpu_be(struct cpu_spec* spec); -struct cpu_spec cpu_specs[] = { +static __initdata struct cpu_spec cpu_specs[] = { { /* Power3 */ .pvr_mask = 0xffff0000, .pvr_value = 0x00400000, @@ -258,3 +258,24 @@ struct cpu_spec cpu_specs[] = { .cpu_setup = __setup_cpu_power4, } }; + +void __init identify_cpu(void) +{ + unsigned int pvr, mask, value; + int i; + + pvr = mfspr(SPRN_PVR); + + /* We rely on the default match at the end of the cpu_spec array */ + for (i = 0; ; i++) { + mask = cpu_specs[i].pvr_mask; + value = cpu_specs[i].pvr_value; + + if ((pvr & mask) == value) + break; + } + + cur_cpu_spec = cpu_specs[i]; + + cur_cpu_spec.cpu_setup(&cur_cpu_spec); +} Index: kexec/arch/ppc64/kernel/asm-offsets.c =================================================================== --- kexec.orig/arch/ppc64/kernel/asm-offsets.c +++ kexec/arch/ppc64/kernel/asm-offsets.c @@ -165,11 +165,7 @@ int main(void) DEFINE(CLONE_UNTRACED, CLONE_UNTRACED); /* About the CPU features table */ - DEFINE(CPU_SPEC_ENTRY_SIZE, sizeof(struct cpu_spec)); - DEFINE(CPU_SPEC_PVR_MASK, offsetof(struct cpu_spec, pvr_mask)); - DEFINE(CPU_SPEC_PVR_VALUE, offsetof(struct cpu_spec, pvr_value)); DEFINE(CPU_SPEC_FEATURES, offsetof(struct cpu_spec, cpu_features)); - DEFINE(CPU_SPEC_SETUP, offsetof(struct cpu_spec, cpu_setup)); /* systemcfg offsets for use by vdso */ DEFINE(CFG_TB_ORIG_STAMP, offsetof(struct systemcfg, tb_orig_stamp)); Index: kexec/arch/ppc64/kernel/head.S =================================================================== --- kexec.orig/arch/ppc64/kernel/head.S +++ kexec/arch/ppc64/kernel/head.S @@ -1354,15 +1354,11 @@ _STATIC(__start_initialization_iSeries) li r0,0 stdu r0,-STACK_FRAME_OVERHEAD(r1) - LOADADDR(r3,cpu_specs) - LOADADDR(r4,cur_cpu_spec) - li r5,0 - bl .identify_cpu - LOADADDR(r2,__toc_start) addi r2,r2,0x4000 addi r2,r2,0x4000 + bl .identify_cpu bl .iSeries_early_setup /* relocation is on at this point */ @@ -1771,11 +1767,6 @@ _STATIC(start_here_multiplatform) addi r2,r2,0x4000 sub r2,r2,r26 - LOADADDR(r3,cpu_specs) - sub r3,r3,r26 - LOADADDR(r4,cur_cpu_spec) - sub r4,r4,r26 - mr r5,r26 bl .identify_cpu /* Save some low level config HIDs of CPU0 to be copied to Index: kexec/arch/ppc64/kernel/misc.S =================================================================== --- kexec.orig/arch/ppc64/kernel/misc.S +++ kexec/arch/ppc64/kernel/misc.S @@ -508,35 +508,6 @@ _GLOBAL(cvt_df) blr /* - * identify_cpu and calls setup_cpu - * In: r3 = base of the cpu_specs array - * r4 = address of cur_cpu_spec - * r5 = relocation offset - */ -_GLOBAL(identify_cpu) - mfpvr r7 -1: - lwz r8,CPU_SPEC_PVR_MASK(r3) - and r8,r8,r7 - lwz r9,CPU_SPEC_PVR_VALUE(r3) - cmplw 0,r9,r8 - beq 1f - addi r3,r3,CPU_SPEC_ENTRY_SIZE - b 1b -1: - add r0,r3,r5 - std r0,0(r4) - ld r4,CPU_SPEC_SETUP(r3) - sub r4,r4,r5 - ld r4,0(r4) - sub r4,r4,r5 - mtctr r4 - /* Calling convention for cpu setup is r3=offset, r4=cur_cpu_spec */ - mr r4,r3 - mr r3,r5 - bctr - -/* * do_cpu_ftr_fixups - goes through the list of CPU feature fixups * and writes nop's over sections of code that don't apply for this cpu. * r3 = data offset (not changed) @@ -545,9 +516,8 @@ _GLOBAL(do_cpu_ftr_fixups) /* Get CPU 0 features */ LOADADDR(r6,cur_cpu_spec) sub r6,r6,r3 - ld r4,0(r6) + ld r4,CPU_SPEC_FEATURES(r6) sub r4,r4,r3 - ld r4,CPU_SPEC_FEATURES(r4) /* Get the fixup table */ LOADADDR(r6,__start___ftr_fixup) sub r6,r6,r3 Index: kexec/arch/ppc64/kernel/idle_power4.S =================================================================== --- kexec.orig/arch/ppc64/kernel/idle_power4.S +++ kexec/arch/ppc64/kernel/idle_power4.S @@ -38,9 +38,8 @@ END_FTR_SECTION_IFCLR(CPU_FTR_CAN_NAP) /* We must dynamically check for the NAP feature as it * can be cleared by CPU init after the fixups are done */ - LOADBASE(r3,cur_cpu_spec) - ld r4,cur_cpu_spec at l(r3) - ld r4,CPU_SPEC_FEATURES(r4) + LOADADDR(r3,cur_cpu_spec) + ld r4,CPU_SPEC_FEATURES(r3) andi. r0,r4,CPU_FTR_CAN_NAP beqlr /* Now check if user or arch enabled NAP mode */ Index: kexec/arch/ppc64/kernel/prom.c =================================================================== --- kexec.orig/arch/ppc64/kernel/prom.c +++ kexec/arch/ppc64/kernel/prom.c @@ -1032,15 +1032,15 @@ static int __init early_init_dt_scan_cpu /* Check if we have a VMX and eventually update CPU features */ prop = (u32 *)get_flat_dt_prop(node, "ibm,vmx", NULL); if (prop && (*prop) > 0) { - cur_cpu_spec->cpu_features |= CPU_FTR_ALTIVEC; - cur_cpu_spec->cpu_user_features |= PPC_FEATURE_HAS_ALTIVEC; + cpu_set_feature(CPU_FTR_ALTIVEC); + cpu_set_feature(PPC_FEATURE_HAS_ALTIVEC); } /* Same goes for Apple's "altivec" property */ prop = (u32 *)get_flat_dt_prop(node, "altivec", NULL); if (prop) { - cur_cpu_spec->cpu_features |= CPU_FTR_ALTIVEC; - cur_cpu_spec->cpu_user_features |= PPC_FEATURE_HAS_ALTIVEC; + cpu_set_feature(CPU_FTR_ALTIVEC); + cpu_set_feature(PPC_FEATURE_HAS_ALTIVEC); } #endif /* CONFIG_ALTIVEC */ @@ -1051,9 +1051,9 @@ static int __init early_init_dt_scan_cpu */ prop = (u32 *)get_flat_dt_prop(node, "ibm,ppc-interrupt-server#s", &size); - cur_cpu_spec->cpu_features &= ~CPU_FTR_SMT; + cpu_unset_feature(CPU_FTR_SMT); if (prop && ((size / sizeof(u32)) > 1)) - cur_cpu_spec->cpu_features |= CPU_FTR_SMT; + cpu_set_feature(CPU_FTR_SMT); return 0; } Index: kexec/arch/ppc64/kernel/setup.c =================================================================== --- kexec.orig/arch/ppc64/kernel/setup.c +++ kexec/arch/ppc64/kernel/setup.c @@ -448,7 +448,7 @@ static void __init initialize_cache_info } size = 0; - lsize = cur_cpu_spec->dcache_bsize; + lsize = cur_cpu_spec.dcache_bsize; sizep = (u32 *)get_property(np, "d-cache-size", NULL); if (sizep != NULL) size = *sizep; @@ -466,7 +466,7 @@ static void __init initialize_cache_info ppc64_caches.dlines_per_page = PAGE_SIZE / lsize; size = 0; - lsize = cur_cpu_spec->icache_bsize; + lsize = cur_cpu_spec.icache_bsize; sizep = (u32 *)get_property(np, "i-cache-size", NULL); if (sizep != NULL) size = *sizep; @@ -736,8 +736,8 @@ static int show_cpuinfo(struct seq_file seq_printf(m, "processor\t: %lu\n", cpu_id); seq_printf(m, "cpu\t\t: "); - if (cur_cpu_spec->pvr_mask) - seq_printf(m, "%s", cur_cpu_spec->cpu_name); + if (cur_cpu_spec.pvr_mask) + seq_printf(m, "%s", cur_cpu_spec.cpu_name); else seq_printf(m, "unknown (%08x)", pvr); Index: kexec/arch/ppc64/kernel/sysfs.c =================================================================== --- kexec.orig/arch/ppc64/kernel/sysfs.c +++ kexec/arch/ppc64/kernel/sysfs.c @@ -215,21 +215,21 @@ static void register_cpu_online(unsigned if (cpu_has_feature(CPU_FTR_MMCRA)) sysdev_create_file(s, &attr_mmcra); - if (cur_cpu_spec->num_pmcs >= 1) + if (cur_cpu_spec.num_pmcs >= 1) sysdev_create_file(s, &attr_pmc1); - if (cur_cpu_spec->num_pmcs >= 2) + if (cur_cpu_spec.num_pmcs >= 2) sysdev_create_file(s, &attr_pmc2); - if (cur_cpu_spec->num_pmcs >= 3) + if (cur_cpu_spec.num_pmcs >= 3) sysdev_create_file(s, &attr_pmc3); - if (cur_cpu_spec->num_pmcs >= 4) + if (cur_cpu_spec.num_pmcs >= 4) sysdev_create_file(s, &attr_pmc4); - if (cur_cpu_spec->num_pmcs >= 5) + if (cur_cpu_spec.num_pmcs >= 5) sysdev_create_file(s, &attr_pmc5); - if (cur_cpu_spec->num_pmcs >= 6) + if (cur_cpu_spec.num_pmcs >= 6) sysdev_create_file(s, &attr_pmc6); - if (cur_cpu_spec->num_pmcs >= 7) + if (cur_cpu_spec.num_pmcs >= 7) sysdev_create_file(s, &attr_pmc7); - if (cur_cpu_spec->num_pmcs >= 8) + if (cur_cpu_spec.num_pmcs >= 8) sysdev_create_file(s, &attr_pmc8); if (cpu_has_feature(CPU_FTR_SMT)) @@ -257,21 +257,21 @@ static void unregister_cpu_online(unsign if (cpu_has_feature(CPU_FTR_MMCRA)) sysdev_remove_file(s, &attr_mmcra); - if (cur_cpu_spec->num_pmcs >= 1) + if (cur_cpu_spec.num_pmcs >= 1) sysdev_remove_file(s, &attr_pmc1); - if (cur_cpu_spec->num_pmcs >= 2) + if (cur_cpu_spec.num_pmcs >= 2) sysdev_remove_file(s, &attr_pmc2); - if (cur_cpu_spec->num_pmcs >= 3) + if (cur_cpu_spec.num_pmcs >= 3) sysdev_remove_file(s, &attr_pmc3); - if (cur_cpu_spec->num_pmcs >= 4) + if (cur_cpu_spec.num_pmcs >= 4) sysdev_remove_file(s, &attr_pmc4); - if (cur_cpu_spec->num_pmcs >= 5) + if (cur_cpu_spec.num_pmcs >= 5) sysdev_remove_file(s, &attr_pmc5); - if (cur_cpu_spec->num_pmcs >= 6) + if (cur_cpu_spec.num_pmcs >= 6) sysdev_remove_file(s, &attr_pmc6); - if (cur_cpu_spec->num_pmcs >= 7) + if (cur_cpu_spec.num_pmcs >= 7) sysdev_remove_file(s, &attr_pmc7); - if (cur_cpu_spec->num_pmcs >= 8) + if (cur_cpu_spec.num_pmcs >= 8) sysdev_remove_file(s, &attr_pmc8); if (cpu_has_feature(CPU_FTR_SMT)) Index: kexec/arch/powerpc/oprofile/common.c =================================================================== --- kexec.orig/arch/powerpc/oprofile/common.c +++ kexec/arch/powerpc/oprofile/common.c @@ -173,12 +173,12 @@ int __init oprofile_arch_init(struct opr ops->cpu_type = cpu_type; #else /* __powerpc64__ */ - if (!cur_cpu_spec->oprofile_model || !cur_cpu_spec->oprofile_cpu_type) + if (!cur_cpu_spec.oprofile_model || !cur_cpu_spec.oprofile_cpu_type) return -ENODEV; - model = cur_cpu_spec->oprofile_model; - model->num_counters = cur_cpu_spec->num_pmcs; + model = cur_cpu_spec.oprofile_model; + model->num_counters = cur_cpu_spec.num_pmcs; - ops->cpu_type = cur_cpu_spec->oprofile_cpu_type; + ops->cpu_type = cur_cpu_spec.oprofile_cpu_type; #endif /* __powerpc64__ */ ops->create_files = op_powerpc_create_files; ops->setup = op_powerpc_setup; Index: kexec/arch/powerpc/oprofile/op_model_power4.c =================================================================== --- kexec.orig/arch/powerpc/oprofile/op_model_power4.c +++ kexec/arch/powerpc/oprofile/op_model_power4.c @@ -64,7 +64,7 @@ static void power4_reg_setup(struct op_c backtrace_spinlocks = sys->backtrace_spinlocks; - for (i = 0; i < cur_cpu_spec->num_pmcs; ++i) + for (i = 0; i < cur_cpu_spec.num_pmcs; ++i) reset_value[i] = 0x80000000UL - ctr[i].count; /* setup user and kernel profiling */ @@ -117,7 +117,7 @@ static void power4_start(struct op_count /* set the PMM bit (see comment below) */ mtmsrd(mfmsr() | MSR_PMM); - for (i = 0; i < cur_cpu_spec->num_pmcs; ++i) { + for (i = 0; i < cur_cpu_spec.num_pmcs; ++i) { if (ctr[i].enabled) { ctr_write(i, reset_value[i]); } else { @@ -268,7 +268,7 @@ static void power4_handle_interrupt(stru /* set the PMM bit (see comment below) */ mtmsrd(mfmsr() | MSR_PMM); - for (i = 0; i < cur_cpu_spec->num_pmcs; ++i) { + for (i = 0; i < cur_cpu_spec.num_pmcs; ++i) { val = ctr_read(i); if (val < 0) { if (oprofile_running && ctr[i].enabled) { Index: kexec/include/asm-powerpc/elf.h =================================================================== --- kexec.orig/include/asm-powerpc/elf.h +++ kexec/include/asm-powerpc/elf.h @@ -213,7 +213,7 @@ extern int dump_task_fpu(struct task_str instruction set this cpu supports. This could be done in userspace, but it's not easy, and we've already done it here. */ #ifdef __powerpc64__ -# define ELF_HWCAP (cur_cpu_spec->cpu_user_features) +# define ELF_HWCAP (cur_cpu_spec.cpu_user_features) # define ELF_PLAT_INIT(_r, load_addr) do { \ memset(_r->gpr, 0, sizeof(_r->gpr)); \ _r->ctr = _r->link = _r->xer = _r->ccr = 0; \ From dhowells at redhat.com Mon Sep 26 21:38:21 2005 From: dhowells at redhat.com (David Howells) Date: Mon, 26 Sep 2005 12:38:21 +0100 Subject: PATCH powerpc Merge asm-ppc*/rwsem.h In-Reply-To: <17204.41449.162199.476757@cargo.ozlabs.ibm.com> References: <17204.41449.162199.476757@cargo.ozlabs.ibm.com> <606.1127460740@warthog.cambridge.redhat.com> Message-ID: <25552.1127734701@warthog.cambridge.redhat.com> Paul Mackerras wrote: > > > rwsems on ppc64 should really be using a 64-bit counter, not a 32-bit > > counter, otherwise you limit the maximum number of processes to 32K-ish. > > > > The counter should be "signed long" really. > > It has long annoyed me that we waste half the bits in the rwsem > counter, just because you assume a lowest-common-denominator set of > atomic ops. IIRC your implementation replaced the earlier ppc > implementation which had a 32-bit counter and didn't have the 32k > process limit. And also didn't work, at least not on i386. > I'd have to study it in more detail, but I strongly suspect that with > an atomic operation that did something like > > *p = max(*p, limit) + inc There is no requirement for an arch to use the XADD-based algorithm for doing this - that's optimised for use with the i386/x86_64 XADD instruction. That can be emulated by cmpxchg or load-locked/store-conditional type constructs like MIPS, Alpha and ppc have. > atomically (or alternatively a min), we could increase the limit to at > least 1G processes with a 32-bit counter, without needing to change > your common slow-path implementation. I think you'd probably need a different slow-path for what you want. My XADD optimised slow patch assumes that certain values represent certain states, and if you're using different values, then it won't necessarily work. This is why the thing is contingent on CONFIG_RWSEM_XCHGADD_ALGORITHM. > Such an atomic op is easy to implement with load-and-reserve / > store-conditional instructions. Look at __sem_update_count in > arch/ppc64/kernel/semaphore.c for an example. So that does (I think): do { int old_count = load_reserve(&sem->count); int tmp = old_count >> 31; // not sure about this: 31 or 1? tmp = old_count & ~tmp; tmp = tmp + incr; } while (!conditionally_assign(&sem->count, tmp)); PPC asm makes my head hurt; in particular the description of the SRAWI instruction I've got is a delight to behold, and is inconsistent with the description of the SRAW instruction:-/ I'm guessing it does a shift by 31 to leave tmp filled with copies of bit 0 (the sign bit) of old_count. The manual suggests the shift is 32-N (or 1 in this case) which would seem odd. I see how it works, then. What's "limit" in this formula: > *p = max(*p, limit) + inc Is it the maximum number of processes that may hold readlocks? Or maybe the negated quantity thereof. It's hard to see immediately how this will work. The counter has to represent several things: (1) The number of active readers (max N) or the number of active writers (max 1). (2) Whether or not there is potential contention. I do this with my XADD algorithm by splitting the word into two halves: MSH = #active_writers + #failed_writers + #sleepers LSH = #active_readers + #active_writers + #failed_contenders Basically, the counter is a lock additional to the spinlock. Perhaps you could do something like this: COUNT MEANING ======================= ========================================== 0 Not in use 0x00000001 - 0x7fffffff N readers 0x80000000 last active reader or writer done, contention 0x80000001 - 0xffffffff N active readers or writers, contention So up_read() and up_write() would decrement the count. If the result reaches 0x80000000 then you have to perform contention resolution. down_read() would increment the count if >= 0, or attempt to sleep otherwise. down_write() would just set the sign bit of the count and sleep if != 0, or set the count to 0x80000001 and return. We could also divide the space in two, and use the second most significant bit (0x40000000) to record the fact that there are sleeping contenders or to record which type of lock is actually active. However, I think there's a problem with doing that, and that is: COUNT PROCESS 0 PROCESS 1 ======== ====================== ================================ 00000000 down_read() 00000001 -->down_write() lwarx stwcx [set sign bit] 80000001 -->down_write_slow() -->up_read() lwarx stwcx [dec] 80000000 -->up_read_slow() -->lock sem->wait_lock <--lock sem->wait_lock -->lock sem->wait_lock count indicated contention but nothing on sem->wait_list - do we leave the count unaltered? - do we clear the count? - do we set the count to 0x80000001? If we leave the count set to 0x80000000, then the down_write_slow() when it runs won't be able to tell whether it got sem->wait_lock before or after down_read_slow() did. In one case it should go to sleep and in the other it should claim the lock. If we set the count to 0x80000001, then the case where _two_ CPUs are contending with the releaser may _both_ think they have the lock, and in any case can't tell the difference between that and a sleeping process just having been woken up and given a writelock. If we clear the count, then other processes may be able to queue jump (which isn't necessarily a problem since spinlocks aren't fair anyway, though they could be made so). down_write_slow() would have to attempt to take the lock again, though this time it would already have the spinlock. But what might happen is that: COUNT PROCESS 0 PROCESS 1 PROCESS 2 ======== ====================== =============== =============== 80000000 -->lock sem->wait_lock count indicated contention but nothing on sem->wait_list - do we clear the count? 00000000 down_write() 80000001 unlock sem->wait_lock <--up_read_slow() <--up_read() <--lock sem->wait_lock lwarx stwcx [set sign bit] 80000001 -->up_write() lwarx stwcx [dec] 80000000 -->up_write_slow() -->lock sem->wait_lock list_add_tail() unlock sem->wait_lock sleep <--lock sem->wait_lock dequeue process 1 set count 80000001 unlock sem->wait_lock <--up_write_slow() <--up_write() wake <--up_write_slow() <--up_write() Ummm... that does seem to work. I think their may be a multi-process race in there somewhere, but I can't work it out if there is; just as long as up_write() always does contention resolution. The down side of this is that you always have to get the spinlock in up_write, unlike in the XADD implementation where the counter includes a contention counter. I think downgrade_write() should simply be a matter of: whilst holding the spinlock, set the counter to the number of outstanding reads, and only set the sign bit if there's a sleeping writer left at the front of the queue. Should interruptible rwsems arrive, then I think just dequeuing the aborted down op should be enough. Leave the contention counter with the sign bit set as it'll sort itself out later. David From customer at creditunion1.org Mon Sep 26 21:12:29 2005 From: customer at creditunion1.org (customer at creditunion1.org) Date: Mon, 26 Sep 2005 18:12:29 +0700 Subject: Credit Union 1 Informs You! Message-ID: <200509261112.j8QBCTj8030970@ftp.khan.in.th> An HTML attachment was scrubbed... URL: http://ozlabs.org/pipermail/linuxppc64-dev/attachments/20050926/0b9e57d0/attachment.htm From florin at iucha.net Tue Sep 27 01:44:15 2005 From: florin at iucha.net (Florin Iucha) Date: Mon, 26 Sep 2005 10:44:15 -0500 Subject: BUG: 2.6.14-rc2 sets the wrong time in NVRAM on PowerMac G5 In-Reply-To: <1127429754.25837.32.camel@gaston> References: <20050922110828.GB7120@iucha.net> <1127429754.25837.32.camel@gaston> Message-ID: <20050926154415.GD7120@iucha.net> On Fri, Sep 23, 2005 at 08:55:54AM +1000, Benjamin Herrenschmidt wrote: > > florin at zeus$ dmesg | grep "Linux version" > > Linux version 2.6.14-rc2 (root at zeus) (gcc version 4.0.2 20050808 > > (prerelease) (Ubuntu 4.0.1-4ubuntu8)) #1 SMP Tue Sep 20 17:24:52 > > CDT 2005 > > Hrm... this is a PMU based machine right ? I believe it is. It is the newest PMac that Apple sells. > I don't think we changed > anything to that code... Can you try isolating the specific patch that > causes the breakage ? It is quite elusive. It sometimes happens when rebooting from Mac to Linux, or when cold-booting. I have tried to find a pattern, but I can't. The only "solid" thing is that it does not happen at all with 2.6.14-rc1 or 2.6.13. Another datapoint: with Ubuntu kernel linux-image-2.6.12-7-powerpc64-smp the machine real time clock is fine, with the kernel linux-image-2.6.12-8-powerpc64-smp it goes into the future (Apr 2037)! florin -------------- next part -------------- A non-text attachment was scrubbed... Name: not available Type: application/pgp-signature Size: 189 bytes Desc: Digital signature Url : http://ozlabs.org/pipermail/linuxppc64-dev/attachments/20050926/f539444b/attachment.pgp From agl at us.ibm.com Tue Sep 27 02:08:50 2005 From: agl at us.ibm.com (Adam Litke) Date: Mon, 26 Sep 2005 11:08:50 -0500 Subject: Hugetlb HPTE hashing weirdness In-Reply-To: <1127452545.27674.1.camel@gaston> References: <1127326966.22154.55.camel@localhost.localdomain> <1127345278.15276.0.camel@gaston> <1127397747.13899.9.camel@localhost.localdomain> <1127452545.27674.1.camel@gaston> Message-ID: <1127750930.19250.6.camel@localhost.localdomain> On Fri, 2005-09-23 at 15:15 +1000, Benjamin Herrenschmidt wrote: > > Attached is my somewhat hacky hugetlb test suite. Build it with 'make > > all'. I've been reproducing with: > > for i in `seq 1 10`; do ./mmap-gettest 1 10; done > > After about the third or fourth iteration, you should start to see test > > failures. > > What machine do you use ? I've been doing my testing on a p650 in bare metal mode. Do you need any other specific info? > I can reproduce the problem on a g5 here but strangely not on any LPAR > machine I've tested so far (all POWER5)... > > I did find a bug in the hugepage code though I doubt it's the culprit, > I'll test a fix on the g5. That patch (as included in 2.6.14-rc2-git5) makes the problem disappear for the prefault case but it is still broken for demand faulting. Seems some HPTEs are still not flushed. I'll try on some LPAR systems and see if I can reproduce there. -- Adam Litke - (agl at us.ibm.com) IBM Linux Technology Center From bgill at freescale.com Tue Sep 27 02:21:18 2005 From: bgill at freescale.com (Becky Bruce) Date: Mon, 26 Sep 2005 11:21:18 -0500 (CDT) Subject: [PATCH] powerpc: merge ipcbuf.h Message-ID: powerpc: Merge ipcbuf.h Merged ipcbuf.h into include/asm-powerpc. The type of a couple of __unused fields in the ipc64_perm struct has been changed to long long so we get a 64-bit quantity on both 32/64 ppcs. The pad field is now called __pad1 on both platforms. The "seq" structure member is now an int, so we get 32-bits on both platforms as well (previously, it was a long on ppc32). The size of the structure on both platforms is the same as it always was. Also, updated include/asm-ppc64/compat.h to match the new structure definition. Builds cleanly on several different 32/64-bit platforms with no new warnings. Signed-off-by: Becky Bruce Signed-off-by: Kumar Gala --- commit 62cba170a9d2629791c9e9ceebb9c679f81fb3fb tree 848d43a4a62930af1ed7181088d2b428d4b40b2d parent 76b1ba19ac14976b8cd288180bb939f429a70820 author Becky Bruce Mon, 26 Sep 2005 11:17:55 -0500 committer Becky Bruce Mon, 26 Sep 2005 11:17:55 -0500 include/asm-powerpc/ipcbuf.h | 28 ++++++++++++++++++++++++++++ include/asm-ppc/ipcbuf.h | 29 ----------------------------- include/asm-ppc64/compat.h | 6 +++--- include/asm-ppc64/ipcbuf.h | 28 ---------------------------- 4 files changed, 31 insertions(+), 60 deletions(-) diff --git a/include/asm-powerpc/ipcbuf.h b/include/asm-powerpc/ipcbuf.h new file mode 100644 --- /dev/null +++ b/include/asm-powerpc/ipcbuf.h @@ -0,0 +1,28 @@ +#ifndef _ASM_POWERPC_IPCBUF_H +#define _ASM_POWERPC_IPCBUF_H + +/* + * The ipc64_perm structure for the PPC is identical to kern_ipc_perm + * as we have always had 32-bit UIDs and GIDs in the 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. + */ + +struct ipc64_perm +{ + __kernel_key_t key; + __kernel_uid_t uid; + __kernel_gid_t gid; + __kernel_uid_t cuid; + __kernel_gid_t cgid; + __kernel_mode_t mode; + unsigned int seq; + unsigned int __pad1; + unsigned long long __unused1; + unsigned long long __unused2; +}; + +#endif /* _ASM_POWERPC_IPCBUF_H */ diff --git a/include/asm-ppc/ipcbuf.h b/include/asm-ppc/ipcbuf.h deleted file mode 100644 --- a/include/asm-ppc/ipcbuf.h +++ /dev/null @@ -1,29 +0,0 @@ -#ifndef __PPC_IPCBUF_H__ -#define __PPC_IPCBUF_H__ - -/* - * The ipc64_perm 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: - * - 1 32-bit value to fill up for 8-byte alignment - * - 2 miscellaneous 64-bit values (so that this structure matches - * PPC64 ipc64_perm) - */ - -struct ipc64_perm -{ - __kernel_key_t key; - __kernel_uid_t uid; - __kernel_gid_t gid; - __kernel_uid_t cuid; - __kernel_gid_t cgid; - __kernel_mode_t mode; - unsigned long seq; - unsigned int __pad2; - unsigned long long __unused1; - unsigned long long __unused2; -}; - -#endif /* __PPC_IPCBUF_H__ */ diff --git a/include/asm-ppc64/compat.h b/include/asm-ppc64/compat.h --- a/include/asm-ppc64/compat.h +++ b/include/asm-ppc64/compat.h @@ -152,9 +152,9 @@ struct compat_ipc64_perm { __compat_gid_t cgid; compat_mode_t mode; unsigned int seq; - unsigned int __pad2; - unsigned long __unused1; /* yes they really are 64bit pads */ - unsigned long __unused2; + unsigned int __pad1; + unsigned long long __unused1; /* yes they really are 64bit pads */ + unsigned long long __unused2; }; struct compat_semid64_ds { diff --git a/include/asm-ppc64/ipcbuf.h b/include/asm-ppc64/ipcbuf.h deleted file mode 100644 --- a/include/asm-ppc64/ipcbuf.h +++ /dev/null @@ -1,28 +0,0 @@ -#ifndef __PPC64_IPCBUF_H__ -#define __PPC64_IPCBUF_H__ - -/* - * The ipc64_perm structure for the PPC is identical to kern_ipc_perm - * as we have always had 32-bit UIDs and GIDs in the 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. - */ - -struct ipc64_perm -{ - __kernel_key_t key; - __kernel_uid_t uid; - __kernel_gid_t gid; - __kernel_uid_t cuid; - __kernel_gid_t cgid; - __kernel_mode_t mode; - unsigned int seq; - unsigned int __pad1; - unsigned long __unused1; - unsigned long __unused2; -}; - -#endif /* __PPC64_IPCBUF_H__ */ From kravetz at us.ibm.com Tue Sep 27 03:07:07 2005 From: kravetz at us.ibm.com (Mike Kravetz) Date: Mon, 26 Sep 2005 10:07:07 -0700 Subject: 2.6.14-rc2 build error Message-ID: <20050926170707.GB6207@w-mikek2.ibm.com> > make defconfig > make zImage ... arch/ppc64/kernel/bpa_iommu.c: In function `get_iost_entry': arch/ppc64/kernel/bpa_iommu.c:102: error: size of array `type name' is negative make[1]: *** [arch/ppc64/kernel/bpa_iommu.o] Error 1 make: *** [arch/ppc64/kernel] Error 2 ... This is in linux-2.6.14-rc2. Fix seems like it should be easy enough. Has someone already fixed this? -- Mike From seminara at us.ibm.com Tue Sep 27 03:11:42 2005 From: seminara at us.ibm.com (Mary R Seminara) Date: Mon, 26 Sep 2005 13:11:42 -0400 Subject: Mary R Seminara/Watson/IBM is out of the office. Message-ID: I will be out of the office starting 09/26/2005 and will not return until 10/03/2005. From arnd at arndb.de Tue Sep 27 03:20:29 2005 From: arnd at arndb.de (Arnd Bergmann) Date: Mon, 26 Sep 2005 19:20:29 +0200 Subject: 2.6.14-rc2 build error In-Reply-To: <20050926170707.GB6207@w-mikek2.ibm.com> References: <20050926170707.GB6207@w-mikek2.ibm.com> Message-ID: <200509261920.29580.arnd@arndb.de> On Maandag 26 September 2005 19:07, Mike Kravetz wrote: > This is in linux-2.6.14-rc2. Fix seems like it should be easy enough. > Has someone already fixed this? > Yes, see http://patchwork.ozlabs.org/linuxppc64/patch?id=2436 Arnd <>< From geoffrey.levand at am.sony.com Tue Sep 27 04:52:16 2005 From: geoffrey.levand at am.sony.com (Geoff Levand) Date: Mon, 26 Sep 2005 11:52:16 -0700 Subject: rounding up CPUs on debug exception Message-ID: <43384360.1040808@am.sony.com> When kgdb handles a debugging exception (trap or trace for ppc) it tries to stop execution on the other CPUs as soon as possible so that changes in the system state from the time of the exception are minimized. The i386 code (below) uses the inter-processor interrupt features of the APIC interrupt controller to send a high priority NMI to the other CPUs. An NMI is needed here, since another CPU may be waiting with interrupts disabled on a spin lock the current cpu holds. void kgdb_roundup_cpus(unsigned long flags) { send_IPI_allbutself(APIC_DM_NMI); } I need something similar to support SMP on ppc64. Can anyone suggest something? -Geoff From arnd at arndb.de Tue Sep 27 05:09:22 2005 From: arnd at arndb.de (Arnd Bergmann) Date: Mon, 26 Sep 2005 21:09:22 +0200 Subject: rounding up CPUs on debug exception In-Reply-To: <43384360.1040808@am.sony.com> References: <43384360.1040808@am.sony.com> Message-ID: <200509262109.23115.arnd@arndb.de> On Maandag 26 September 2005 20:52, Geoff Levand wrote: > void kgdb_roundup_cpus(unsigned long flags) > { > send_IPI_allbutself(APIC_DM_NMI); > } > > I need something similar to support SMP on ppc64. Can anyone > suggest something? > The architecture independent function for this is smp_call_function(), as defined in arch/ppc64/kernel/smp.c Arnd <>< From haren at us.ibm.com Tue Sep 27 05:18:20 2005 From: haren at us.ibm.com (Haren Myneni) Date: Mon, 26 Sep 2005 12:18:20 -0700 Subject: rounding up CPUs on debug exception In-Reply-To: <43384360.1040808@am.sony.com> References: <43384360.1040808@am.sony.com> Message-ID: <4338497C.4000601@us.ibm.com> Geoff Levand wrote: >When kgdb handles a debugging exception (trap or trace for ppc) it >tries to stop execution on the other CPUs as soon as possible so >that changes in the system state from the time of the exception >are minimized. The i386 code (below) uses the inter-processor >interrupt features of the APIC interrupt controller to send a >high priority NMI to the other CPUs. An NMI is needed here, >since another CPU may be waiting with interrupts disabled on a >spin lock the current cpu holds. > >void kgdb_roundup_cpus(unsigned long flags) >{ > send_IPI_allbutself(APIC_DM_NMI); >} > >I need something similar to support SMP on ppc64. Can anyone >suggest something? > > Unfortunately, there is no software NMI support on PPC64. It would be better to have this feature. However, the user can do soft-reset manually to bring all CPUs into debugger as xmon does. For this, kgdb has to be modified such it handles the re-entrant of CPUs which are already responded to an IPI. I believe, you can re-use some functions (long_jmp and set_jmp) defined for xmon. Thanks Haren >-Geoff > >_______________________________________________ >Linuxppc64-dev mailing list >Linuxppc64-dev at ozlabs.org >https://ozlabs.org/mailman/listinfo/linuxppc64-dev > > > From geoffrey.levand at am.sony.com Tue Sep 27 06:51:22 2005 From: geoffrey.levand at am.sony.com (Geoff Levand) Date: Mon, 26 Sep 2005 13:51:22 -0700 Subject: rounding up CPUs on debug exception In-Reply-To: <200509262109.23115.arnd@arndb.de> References: <200509262109.23115.arnd@arndb.de> Message-ID: <43385F4A.9090102@am.sony.com> Arnd Bergmann wrote: > On Maandag 26 September 2005 20:52, Geoff Levand wrote: > > >>void kgdb_roundup_cpus(unsigned long flags) >>{ >> send_IPI_allbutself(APIC_DM_NMI); >>} >> >>I need something similar to support SMP on ppc64. Can anyone >>suggest something? >> > > The architecture independent function for this is > smp_call_function(), as defined in arch/ppc64/kernel/smp.c > >From what I understand, the smp_call_function() will block while the other cpu has interrupts disabled. Ideally we want to halt that cpu before it does anything else. Also, if the other cpu is waiting on a spin lock the current cpu holds, there will be a deadlock. BTW, the current implementation uses smp_call_function() and the system hangs occasionally on the call to smp_call_function(). -Geoff From benh at kernel.crashing.org Tue Sep 27 07:18:49 2005 From: benh at kernel.crashing.org (Benjamin Herrenschmidt) Date: Tue, 27 Sep 2005 07:18:49 +1000 Subject: Hugetlb HPTE hashing weirdness In-Reply-To: <1127750930.19250.6.camel@localhost.localdomain> References: <1127326966.22154.55.camel@localhost.localdomain> <1127345278.15276.0.camel@gaston> <1127397747.13899.9.camel@localhost.localdomain> <1127452545.27674.1.camel@gaston> <1127750930.19250.6.camel@localhost.localdomain> Message-ID: <1127769529.15882.78.camel@gaston> > That patch (as included in 2.6.14-rc2-git5) makes the problem disappear > for the prefault case but it is still broken for demand faulting. Seems > some HPTEs are still not flushed. I'll try on some LPAR systems and see > if I can reproduce there. I haven't tried demand faulting, do you have a test case ? Ben. From benh at kernel.crashing.org Tue Sep 27 07:23:40 2005 From: benh at kernel.crashing.org (Benjamin Herrenschmidt) Date: Tue, 27 Sep 2005 07:23:40 +1000 Subject: BUG: 2.6.14-rc2 sets the wrong time in NVRAM on PowerMac G5 In-Reply-To: <20050926154415.GD7120@iucha.net> References: <20050922110828.GB7120@iucha.net> <1127429754.25837.32.camel@gaston> <20050926154415.GD7120@iucha.net> Message-ID: <1127769820.15882.83.camel@gaston> > It is quite elusive. It sometimes happens when rebooting from Mac to > Linux, or when cold-booting. I have tried to find a pattern, but I > can't. The only "solid" thing is that it does not happen at all with > 2.6.14-rc1 or 2.6.13. > > Another datapoint: with Ubuntu kernel linux-image-2.6.12-7-powerpc64-smp > the machine real time clock is fine, with the kernel > linux-image-2.6.12-8-powerpc64-smp it goes into the future (Apr 2037)! Please send me a tarball of /proc/device-tree. Also, maybe you can try getting a diff of those two ubuntu kernels ? Ben. From agl at us.ibm.com Tue Sep 27 07:31:45 2005 From: agl at us.ibm.com (Adam Litke) Date: Mon, 26 Sep 2005 16:31:45 -0500 Subject: Hugetlb HPTE hashing weirdness In-Reply-To: <1127769529.15882.78.camel@gaston> References: <1127326966.22154.55.camel@localhost.localdomain> <1127345278.15276.0.camel@gaston> <1127397747.13899.9.camel@localhost.localdomain> <1127452545.27674.1.camel@gaston> <1127750930.19250.6.camel@localhost.localdomain> <1127769529.15882.78.camel@gaston> Message-ID: <1127770305.8373.12.camel@localhost.localdomain> On Tue, 2005-09-27 at 07:18 +1000, Benjamin Herrenschmidt wrote: > > That patch (as included in 2.6.14-rc2-git5) makes the problem disappear > > for the prefault case but it is still broken for demand faulting. Seems > > some HPTEs are still not flushed. I'll try on some LPAR systems and see > > if I can reproduce there. > > I haven't tried demand faulting, do you have a test case ? I am working on a kernel patch (with David Gibson) to support it. I've attached the patch below. The test case is to run the same thing (./mmap-gettest 1 10) repeatedly with the kernel patch applied. Version 3 (Thu, 08 Sep 2005) Organized logic in hugetlb_pte_fault() by breaking out find_get_page/alloc_huge_page logic into separate function Removed a few more paranoid checks < Fixed tlb flushing in a race case < (thanks Yanmin Zhang) Version 2 (Wed, 17 Aug 2005) Removed spurious WARN_ON() Patches added earlier in the series: Check for p?d_none() in arch/i386/mm/hugetlbpage.c:huge_pte_offset() Move i386 stale pte check into huge_pte_alloc() Initial Post (Fri, 05 Aug 2005) Below is a patch to implement demand faulting for huge pages. The main motivation for changing from prefaulting to demand faulting is so that huge page memory areas can be allocated according to NUMA policy. Thanks to consolidated hugetlb code, switching the behavior requires changing only one fault handler. The bulk of the patch just moves the logic from hugelb_prefault() to hugetlb_pte_fault(). Diffed against 2.6.14-rc2-git5 Signed-off-by: Adam Litke --- fs/hugetlbfs/inode.c | 6 - include/linux/hugetlb.h | 2 mm/hugetlb.c | 154 +++++++++++++++++++++++++++++------------------- mm/memory.c | 2 4 files changed, 98 insertions(+), 66 deletions(-) diff -upN reference/fs/hugetlbfs/inode.c current/fs/hugetlbfs/inode.c --- reference/fs/hugetlbfs/inode.c +++ current/fs/hugetlbfs/inode.c @@ -48,7 +48,6 @@ int sysctl_hugetlb_shm_group; static int hugetlbfs_file_mmap(struct file *file, struct vm_area_struct *vma) { struct inode *inode = file->f_dentry->d_inode; - struct address_space *mapping = inode->i_mapping; loff_t len, vma_len; int ret; @@ -79,10 +78,7 @@ static int hugetlbfs_file_mmap(struct fi if (!(vma->vm_flags & VM_WRITE) && len > inode->i_size) goto out; - ret = hugetlb_prefault(mapping, vma); - if (ret) - goto out; - + ret = 0; if (inode->i_size < len) inode->i_size = len; out: diff -upN reference/include/linux/hugetlb.h current/include/linux/hugetlb.h --- reference/include/linux/hugetlb.h +++ current/include/linux/hugetlb.h @@ -25,6 +25,8 @@ int is_hugepage_mem_enough(size_t); unsigned long hugetlb_total_pages(void); struct page *alloc_huge_page(void); void free_huge_page(struct page *); +int hugetlb_fault(struct mm_struct *mm, struct vm_area_struct * vma, + unsigned long address, int write_access); extern unsigned long max_huge_pages; extern const unsigned long hugetlb_zero, hugetlb_infinity; diff -upN reference/mm/hugetlb.c current/mm/hugetlb.c --- reference/mm/hugetlb.c +++ current/mm/hugetlb.c @@ -274,21 +274,22 @@ int copy_hugetlb_page_range(struct mm_st { pte_t *src_pte, *dst_pte, entry; struct page *ptepage; - unsigned long addr = vma->vm_start; + unsigned long addr; unsigned long end = vma->vm_end; - while (addr < end) { + for (addr = vma->vm_start; addr < end; addr += HPAGE_SIZE) { + src_pte = huge_pte_offset(src, addr); + if (!src_pte || pte_none(*src_pte)) + continue; + dst_pte = huge_pte_alloc(dst, addr); if (!dst_pte) goto nomem; - src_pte = huge_pte_offset(src, addr); - BUG_ON(!src_pte || pte_none(*src_pte)); /* prefaulted */ entry = *src_pte; ptepage = pte_page(entry); get_page(ptepage); add_mm_counter(dst, rss, HPAGE_SIZE / PAGE_SIZE); set_huge_pte_at(dst, addr, dst_pte, entry); - addr += HPAGE_SIZE; } return 0; @@ -338,61 +339,6 @@ void zap_hugepage_range(struct vm_area_s spin_unlock(&mm->page_table_lock); } -int hugetlb_prefault(struct address_space *mapping, struct vm_area_struct *vma) -{ - struct mm_struct *mm = current->mm; - unsigned long addr; - int ret = 0; - - WARN_ON(!is_vm_hugetlb_page(vma)); - BUG_ON(vma->vm_start & ~HPAGE_MASK); - BUG_ON(vma->vm_end & ~HPAGE_MASK); - - hugetlb_prefault_arch_hook(mm); - - spin_lock(&mm->page_table_lock); - for (addr = vma->vm_start; addr < vma->vm_end; addr += HPAGE_SIZE) { - unsigned long idx; - pte_t *pte = huge_pte_alloc(mm, addr); - struct page *page; - - if (!pte) { - ret = -ENOMEM; - goto out; - } - - idx = ((addr - vma->vm_start) >> HPAGE_SHIFT) - + (vma->vm_pgoff >> (HPAGE_SHIFT - PAGE_SHIFT)); - page = find_get_page(mapping, idx); - if (!page) { - /* charge the fs quota first */ - if (hugetlb_get_quota(mapping)) { - ret = -ENOMEM; - goto out; - } - page = alloc_huge_page(); - if (!page) { - hugetlb_put_quota(mapping); - ret = -ENOMEM; - goto out; - } - ret = add_to_page_cache(page, mapping, idx, GFP_ATOMIC); - if (! ret) { - unlock_page(page); - } else { - hugetlb_put_quota(mapping); - free_huge_page(page); - goto out; - } - } - add_mm_counter(mm, rss, HPAGE_SIZE / PAGE_SIZE); - set_huge_pte_at(mm, addr, pte, make_huge_pte(vma, page)); - } -out: - spin_unlock(&mm->page_table_lock); - return ret; -} - int follow_hugetlb_page(struct mm_struct *mm, struct vm_area_struct *vma, struct page **pages, struct vm_area_struct **vmas, unsigned long *position, int *length, int i) @@ -440,3 +386,91 @@ int follow_hugetlb_page(struct mm_struct return i; } + +static struct page *find_get_huge_page(struct address_space *mapping, + unsigned long idx) +{ + struct page *page = NULL; + +retry: + page = find_get_page(mapping, idx); + if (page) + goto out; + + if (hugetlb_get_quota(mapping)) + goto out; + page = alloc_huge_page(); + if (!page) { + hugetlb_put_quota(mapping); + goto out; + } + + if (add_to_page_cache(page, mapping, idx, GFP_ATOMIC)) { + put_page(page); + hugetlb_put_quota(mapping); + goto retry; + } + unlock_page(page); +out: + return page; +} + +static int hugetlb_pte_fault(struct mm_struct *mm, struct vm_area_struct *vma, + unsigned long address, int write_access) +{ + int ret = VM_FAULT_MINOR; + unsigned long idx; + pte_t *pte; + struct page *page; + struct address_space *mapping; + + BUG_ON(vma->vm_start & ~HPAGE_MASK); + BUG_ON(vma->vm_end & ~HPAGE_MASK); + BUG_ON(!vma->vm_file); + + pte = huge_pte_offset(mm, address); + if (!pte) { + ret = VM_FAULT_SIGBUS; + goto out; + } + if (!pte_none(*pte)) + goto out; + + mapping = vma->vm_file->f_mapping; + idx = ((address - vma->vm_start) >> HPAGE_SHIFT) + + (vma->vm_pgoff >> (HPAGE_SHIFT - PAGE_SHIFT)); + + page = find_get_huge_page(mapping, idx); + if (!page) { + ret = VM_FAULT_SIGBUS; + goto out; + } + + add_mm_counter(mm, rss, HPAGE_SIZE / PAGE_SIZE); + set_huge_pte_at(mm, address, pte, make_huge_pte(vma, page)); +out: + return ret; +} + +int hugetlb_fault(struct mm_struct *mm, struct vm_area_struct *vma, + unsigned long address, int write_access) +{ + pte_t *ptep; + int rc = VM_FAULT_MINOR; + + spin_lock(&mm->page_table_lock); + + ptep = huge_pte_alloc(mm, address); + if (!ptep) { + rc = VM_FAULT_SIGBUS; + goto out; + } + if (pte_none(*ptep)) + rc = hugetlb_pte_fault(mm, vma, address, write_access); +out: + if (rc == VM_FAULT_MINOR) + flush_tlb_page(vma, address); + + spin_unlock(&mm->page_table_lock); + return rc; +} diff -upN reference/mm/memory.c current/mm/memory.c --- reference/mm/memory.c +++ current/mm/memory.c @@ -2041,7 +2041,7 @@ int __handle_mm_fault(struct mm_struct * inc_page_state(pgfault); if (is_vm_hugetlb_page(vma)) - return VM_FAULT_SIGBUS; /* mapping truncation does this. */ + return hugetlb_fault(mm, vma, address, write_access); /* * We need the page table lock to synchronize with kswapd -- Adam Litke - (agl at us.ibm.com) IBM Linux Technology Center From benh at kernel.crashing.org Tue Sep 27 07:34:26 2005 From: benh at kernel.crashing.org (Benjamin Herrenschmidt) Date: Tue, 27 Sep 2005 07:34:26 +1000 Subject: rounding up CPUs on debug exception In-Reply-To: <43385F4A.9090102@am.sony.com> References: <200509262109.23115.arnd@arndb.de> <43385F4A.9090102@am.sony.com> Message-ID: <1127770466.15882.88.camel@gaston> > >From what I understand, the smp_call_function() will block > while the other cpu has interrupts disabled. Ideally we > want to halt that cpu before it does anything else. Also, if > the other cpu is waiting on a spin lock the current cpu > holds, there will be a deadlock. > > BTW, the current implementation uses smp_call_function() and > the system hangs occasionally on the call to smp_call_function(). There is no NMI generically available. On some machines, you can trigger a system reset (0x100) exception but that isn't always recoverable. Ben. From benh at kernel.crashing.org Tue Sep 27 07:46:09 2005 From: benh at kernel.crashing.org (Benjamin Herrenschmidt) Date: Tue, 27 Sep 2005 07:46:09 +1000 Subject: Hugetlb HPTE hashing weirdness In-Reply-To: <1127770305.8373.12.camel@localhost.localdomain> References: <1127326966.22154.55.camel@localhost.localdomain> <1127345278.15276.0.camel@gaston> <1127397747.13899.9.camel@localhost.localdomain> <1127452545.27674.1.camel@gaston> <1127750930.19250.6.camel@localhost.localdomain> <1127769529.15882.78.camel@gaston> <1127770305.8373.12.camel@localhost.localdomain> Message-ID: <1127771170.15882.90.camel@gaston> On Mon, 2005-09-26 at 16:31 -0500, Adam Litke wrote: > On Tue, 2005-09-27 at 07:18 +1000, Benjamin Herrenschmidt wrote: > > > That patch (as included in 2.6.14-rc2-git5) makes the problem disappear > > > for the prefault case but it is still broken for demand faulting. Seems > > > some HPTEs are still not flushed. I'll try on some LPAR systems and see > > > if I can reproduce there. > > > > I haven't tried demand faulting, do you have a test case ? > > I am working on a kernel patch (with David Gibson) to support it. I've > attached the patch below. The test case is to run the same thing > (./mmap-gettest 1 10) repeatedly with the kernel patch applied. Ok, I'll have a look, thanks Ben. From agl at us.ibm.com Tue Sep 27 08:21:14 2005 From: agl at us.ibm.com (Adam Litke) Date: Mon, 26 Sep 2005 17:21:14 -0500 Subject: Hugetlb HPTE hashing weirdness In-Reply-To: <1127452545.27674.1.camel@gaston> References: <1127326966.22154.55.camel@localhost.localdomain> <1127345278.15276.0.camel@gaston> <1127397747.13899.9.camel@localhost.localdomain> <1127452545.27674.1.camel@gaston> Message-ID: <1127773274.8373.18.camel@localhost.localdomain> On Fri, 2005-09-23 at 15:15 +1000, Benjamin Herrenschmidt wrote: > > Attached is my somewhat hacky hugetlb test suite. Build it with 'make > > all'. I've been reproducing with: > > for i in `seq 1 10`; do ./mmap-gettest 1 10; done > > After about the third or fourth iteration, you should start to see test > > failures. > > What machine do you use ? > > I can reproduce the problem on a g5 here but strangely not on any LPAR > machine I've tested so far (all POWER5)... OK, another data point. I've tested on a Power5 (p570) and I don't see the bug. So it must be Power4-specific. -- Adam Litke - (agl at us.ibm.com) IBM Linux Technology Center From benh at kernel.crashing.org Tue Sep 27 08:23:04 2005 From: benh at kernel.crashing.org (Benjamin Herrenschmidt) Date: Tue, 27 Sep 2005 08:23:04 +1000 Subject: Hugetlb HPTE hashing weirdness In-Reply-To: <1127773274.8373.18.camel@localhost.localdomain> References: <1127326966.22154.55.camel@localhost.localdomain> <1127345278.15276.0.camel@gaston> <1127397747.13899.9.camel@localhost.localdomain> <1127452545.27674.1.camel@gaston> <1127773274.8373.18.camel@localhost.localdomain> Message-ID: <1127773384.15882.93.camel@gaston> On Mon, 2005-09-26 at 17:21 -0500, Adam Litke wrote: > On Fri, 2005-09-23 at 15:15 +1000, Benjamin Herrenschmidt wrote: > > > Attached is my somewhat hacky hugetlb test suite. Build it with 'make > > > all'. I've been reproducing with: > > > for i in `seq 1 10`; do ./mmap-gettest 1 10; done > > > After about the third or fourth iteration, you should start to see test > > > failures. > > > > What machine do you use ? > > > > I can reproduce the problem on a g5 here but strangely not on any LPAR > > machine I've tested so far (all POWER5)... > > OK, another data point. I've tested on a Power5 (p570) and I don't see > the bug. So it must be Power4-specific. Either that, or non-LPAR specific. The previous problem, for which I pushed a patch, was specific to non-LPAR hash management code. Ben. From benh at kernel.crashing.org Tue Sep 27 08:45:54 2005 From: benh at kernel.crashing.org (Benjamin Herrenschmidt) Date: Tue, 27 Sep 2005 08:45:54 +1000 Subject: [PATCH] powerpc: merged asm/cputable.h In-Reply-To: <200509261157.37514.michael@ellerman.id.au> References: <20050924104827.114939ca.sfr@canb.auug.org.au> <200509261157.37514.michael@ellerman.id.au> Message-ID: <1127774755.15882.104.camel@gaston> On Mon, 2005-09-26 at 11:57 +1000, Michael Ellerman wrote: > Here's a version of my patch updated to apply on top of the merge tree. > It'll be a lot cleaner when ppc32 has a single cur_cpu_spec, as we'll > be able to remove a lot of the #ifdefs. There is a small issue here: You turn identify_cpu into C code. However, on ppc32, this is called with the kernel not yet relocated (before prom_init even !). Same with the feature fixup. On ppc32, in order to run C code that early, it needs to be in -mrelocatable bits of code (like prom_init) or use RELOC macros (ugh !). This puts some light on the fact that we do things quite differently here between ppc32 and ppc64. On ppc64, the call to identify CPU is done after kernel is relocated (after prom_init), and before early_setup, though the call to fixup the feature sections is done later, after the initial parsing of the flat device-tree, where we can "adjust" some features based on firmware properties. We might want to sync a bit what ppc32 and ppc64 do here, however, that will/would require some changes in the way we manipulate some MMU bits. On ppc32, we first create a temporary initial mapping, using BATs on 6xx, using other mecanisms on other CPUs, that covers kernel text & data (not much more). This could be "equivalent" of the ppc64 bit that runs in real mode. (Though we have to be careful there if we do something like unpacking the device-tree, that has to be done -after- final translation is turned on with full access to the linear mapping). Also, the ppc64 bits calls indentify_cpu from asm on the primary CPU at least. I don't think that is strictly necessary, at least not any more. It could be done instead at the beginning of early_setup. Ben. From michael at ellerman.id.au Tue Sep 27 09:05:24 2005 From: michael at ellerman.id.au (Michael Ellerman) Date: Tue, 27 Sep 2005 09:05:24 +1000 Subject: [PATCH] powerpc: merged asm/cputable.h In-Reply-To: <1127774755.15882.104.camel@gaston> References: <200509261157.37514.michael@ellerman.id.au> <1127774755.15882.104.camel@gaston> Message-ID: <200509270905.29545.michael@ellerman.id.au> On Tue, 27 Sep 2005 08:45, Benjamin Herrenschmidt wrote: > On Mon, 2005-09-26 at 11:57 +1000, Michael Ellerman wrote: > > Here's a version of my patch updated to apply on top of the merge tree. > > It'll be a lot cleaner when ppc32 has a single cur_cpu_spec, as we'll > > be able to remove a lot of the #ifdefs. > > There is a small issue here: You turn identify_cpu into C code. However, > on ppc32, this is called with the kernel not yet relocated (before > prom_init even !). Same with the feature fixup. On ppc32, in order to > run C code that early, it needs to be in -mrelocatable bits of code > (like prom_init) or use RELOC macros (ugh !). We could keep the bulk of the patch (turn cur_cpu_spec into a struct) but still do identify_cpu() in asm, although it would seem like a step backward. Do people think it's "better" to have one unified asm implementation, or one in asm for ppc32 and one in C for ppc64? cheers -- Michael Ellerman IBM OzLabs email: michael:ellerman.id.au inmsg: mpe:jabber.org wwweb: http://michael.ellerman.id.au phone: +61 2 6212 1183 (tie line 70 21183) We do not inherit the earth from our ancestors, we borrow it from our children. - S.M.A.R.T Person -------------- 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/20050927/5e00afb8/attachment.pgp From kumar.gala at freescale.com Tue Sep 27 09:22:08 2005 From: kumar.gala at freescale.com (Kumar Gala) Date: Mon, 26 Sep 2005 18:22:08 -0500 Subject: [PATCH] powerpc: merged asm/cputable.h In-Reply-To: <1127774755.15882.104.camel@gaston> References: <20050924104827.114939ca.sfr@canb.auug.org.au> <200509261157.37514.michael@ellerman.id.au> <1127774755.15882.104.camel@gaston> Message-ID: <65BBD07F-B465-45E0-9422-9015D1FBF93A@freescale.com> On Sep 26, 2005, at 5:45 PM, Benjamin Herrenschmidt wrote: > On Mon, 2005-09-26 at 11:57 +1000, Michael Ellerman wrote: > > >> Here's a version of my patch updated to apply on top of the merge >> > tree. > >> It'll be a lot cleaner when ppc32 has a single cur_cpu_spec, as we'll >> be able to remove a lot of the #ifdefs. >> > > There is a small issue here: You turn identify_cpu into C code. > However, > on ppc32, this is called with the kernel not yet relocated (before > prom_init even !). Same with the feature fixup. On ppc32, in order to > run C code that early, it needs to be in -mrelocatable bits of code > (like prom_init) or use RELOC macros (ugh !). What's the pain in building cputable.c as -mrelocatable on ppc32 for now? > This puts some light on the fact that we do things quite differently > here between ppc32 and ppc64. On ppc64, the call to identify CPU is > done > after kernel is relocated (after prom_init), and before early_setup, > though the call to fixup the feature sections is done later, after the > initial parsing of the flat device-tree, where we can "adjust" some > features based on firmware properties. > > We might want to sync a bit what ppc32 and ppc64 do here, however, > that > will/would require some changes in the way we manipulate some MMU > bits. > > On ppc32, we first create a temporary initial mapping, using BATs on > 6xx, using other mecanisms on other CPUs, that covers kernel text & > data > (not much more). This could be "equivalent" of the ppc64 bit that runs > in real mode. (Though we have to be careful there if we do something > like unpacking the device-tree, that has to be done -after- final > translation is turned on with full access to the linear mapping). > > Also, the ppc64 bits calls indentify_cpu from asm on the primary > CPU at > least. I don't think that is strictly necessary, at least not any > more. > It could be done instead at the beginning of early_setup. At the end of the day we should have the same init path for everything. We have to deal with the fact that some processors are not going to have "real mode" to run in. Anything Book-E 32 or 64- bit is going to fall into this case. - kumar From benh at kernel.crashing.org Tue Sep 27 09:31:31 2005 From: benh at kernel.crashing.org (Benjamin Herrenschmidt) Date: Tue, 27 Sep 2005 09:31:31 +1000 Subject: [PATCH] powerpc: merged asm/cputable.h In-Reply-To: <200509270905.29545.michael@ellerman.id.au> References: <200509261157.37514.michael@ellerman.id.au> <1127774755.15882.104.camel@gaston> <200509270905.29545.michael@ellerman.id.au> Message-ID: <1127777491.15882.106.camel@gaston> > > There is a small issue here: You turn identify_cpu into C code. However, > > on ppc32, this is called with the kernel not yet relocated (before > > prom_init even !). Same with the feature fixup. On ppc32, in order to > > run C code that early, it needs to be in -mrelocatable bits of code > > (like prom_init) or use RELOC macros (ugh !). > > We could keep the bulk of the patch (turn cur_cpu_spec into a struct) but > still do identify_cpu() in asm, although it would seem like a step backward. We can do it in C in ppc32 if we use proper RELOC() macros, or do it in an -mrelocatable piece of code like prom_init (but I'd like to avoid that). > Do people think it's "better" to have one unified asm implementation, or one > in asm for ppc32 and one in C for ppc64? We should only need one implementation for both I suppose. Ben From benh at kernel.crashing.org Tue Sep 27 09:38:43 2005 From: benh at kernel.crashing.org (Benjamin Herrenschmidt) Date: Tue, 27 Sep 2005 09:38:43 +1000 Subject: [PATCH] powerpc: merged asm/cputable.h In-Reply-To: <65BBD07F-B465-45E0-9422-9015D1FBF93A@freescale.com> References: <20050924104827.114939ca.sfr@canb.auug.org.au> <200509261157.37514.michael@ellerman.id.au> <1127774755.15882.104.camel@gaston> <65BBD07F-B465-45E0-9422-9015D1FBF93A@freescale.com> Message-ID: <1127777923.15882.114.camel@gaston> > At the end of the day we should have the same init path for > everything. We have to deal with the fact that some processors are > not going to have "real mode" to run in. Anything Book-E 32 or 64- > bit is going to fall into this case. I know, and real mode isn't necessarily useable on others, my point was, there is this "pre-mmu-init" phase when we run into a kind of reduced mmu environment but no need to use RELOC's or -mrelocatable. That is: - on ppc64, real mode - on CONFIG_6xx, memory mapped by BATs over first 16M or so - on others, typically, bolted TLB entries during early asm This "pre-init" phase has common characteristics, that is - we can run code without reloc's as explained above - we can't access much memory above kernel text/data. on ppc64, it ranges from all memory (lucky) to the limit of the RMO on lpar which tend to get smaller. In fact, pSeries might even lose real mode sooner or later and get into a similar "bolted initial mapping" case. This is when early_setup() is run on ppc64. This is when machine_init() and MMU_init() are called on ppc32. Those do fundamentally the same thing. Some pre-init, typically based on device-tree bits & pieces, and choosing the "right" ppc_md. They could be merged to look like the ppc64 version. The main issue is that ppc32 does a bit too much there (like finish_device_tree which should be done later like ppc64). There is bits & pieces there that should be moved around a bit, including in platform code (ppc_md.probe() should replace {pmac,chrp,...}_init() for example). Ben. From paulus at samba.org Tue Sep 27 09:58:17 2005 From: paulus at samba.org (Paul Mackerras) Date: Tue, 27 Sep 2005 09:58:17 +1000 Subject: rounding up CPUs on debug exception In-Reply-To: <43384360.1040808@am.sony.com> References: <43384360.1040808@am.sony.com> Message-ID: <17208.35609.992828.773554@cargo.ozlabs.ibm.com> Geoff Levand writes: > When kgdb handles a debugging exception (trap or trace for ppc) it > tries to stop execution on the other CPUs as soon as possible so > that changes in the system state from the time of the exception > are minimized. The i386 code (below) uses the inter-processor > interrupt features of the APIC interrupt controller to send a > high priority NMI to the other CPUs. An NMI is needed here, > since another CPU may be waiting with interrupts disabled on a > spin lock the current cpu holds. Xmon uses smp_send_debugger_break(MSG_ALL_BUT_SELF) for this. It isn't an NMI, just a regular IPI, though. Paul. From paulus at samba.org Tue Sep 27 10:25:38 2005 From: paulus at samba.org (Paul Mackerras) Date: Tue, 27 Sep 2005 10:25:38 +1000 Subject: Starting the arch/powerpc merge Message-ID: <17208.37250.577664.621993@cargo.ozlabs.ibm.com> I have pushed a commit to the powerpc-merge.git tree which gets us far enough to be able to build a 32-bit powermac kernel with ARCH=powerpc. It's still very rough in places, and it uses bits out of arch/ppc/kernel and arch/ppc/syslib, but it is a start. Of course, this means that we are about to bump up against the really hard bits of the merge. Things like * converting ppc32 to use the lmb infrastructure * introducing the device-tree flattening/unflattening to ppc32 * working out how to deal with the early hash table initialization that POWER4 needs on ppc32 * reconciling the fact that ppc64 needs RELOC in the prom_init code, whereas ppc32 doesn't; but ppc64 doesn't need RELOC when running with the MMU off but ppc32 does (or needs -mrelocatable). I look forward to people sending me patches to push this on a bit further, and in particular to populate arch/powerpc/platforms a bit more. :) Paul. From benh at kernel.crashing.org Tue Sep 27 11:56:37 2005 From: benh at kernel.crashing.org (Benjamin Herrenschmidt) Date: Tue, 27 Sep 2005 11:56:37 +1000 Subject: [PATCH] ppc64: More hugepage fixes Message-ID: <1127786197.15882.118.camel@gaston> My previous patch fixing invalidation of huge PTEs wasn't good enough, we still had an issue if a PTE invalidation batch contained both small and large pages. This patch fixes this by making sure the batch is flushed if the page size fed to it changes. Signed-off-by: Benjamin Herrenschmidt Index: linux-work/arch/ppc64/mm/hash_native.c =================================================================== --- linux-work.orig/arch/ppc64/mm/hash_native.c 2005-09-27 11:43:27.000000000 +1000 +++ linux-work/arch/ppc64/mm/hash_native.c 2005-09-27 11:48:06.000000000 +1000 @@ -343,7 +343,7 @@ hpte_t *hptep; unsigned long hpte_v; struct ppc64_tlb_batch *batch = &__get_cpu_var(ppc64_tlb_batch); - unsigned long large; + unsigned long large = batch->large; local_irq_save(flags); @@ -356,7 +356,6 @@ va = (vsid << 28) | (batch->addr[i] & 0x0fffffff); batch->vaddr[j] = va; - large = pte_huge(batch->pte[i]); if (large) vpn = va >> HPAGE_SHIFT; else @@ -406,7 +405,7 @@ asm volatile("ptesync":::"memory"); for (i = 0; i < j; i++) - __tlbie(batch->vaddr[i], 0); + __tlbie(batch->vaddr[i], large); asm volatile("eieio; tlbsync; ptesync":::"memory"); Index: linux-work/arch/ppc64/mm/tlb.c =================================================================== --- linux-work.orig/arch/ppc64/mm/tlb.c 2005-09-27 11:43:27.000000000 +1000 +++ linux-work/arch/ppc64/mm/tlb.c 2005-09-27 11:47:35.000000000 +1000 @@ -143,7 +143,8 @@ * up scanning and resetting referenced bits then our batch context * will change mid stream. */ - if (unlikely(i != 0 && context != batch->context)) { + if (i != 0 && (context != batch->context || + batch->large != pte_huge(pte))) { flush_tlb_pending(); i = 0; } @@ -151,6 +152,7 @@ if (i == 0) { batch->context = context; batch->mm = mm; + batch->large = pte_huge(pte); } batch->pte[i] = __pte(pte); batch->addr[i] = addr; Index: linux-work/include/asm-ppc64/tlbflush.h =================================================================== --- linux-work.orig/include/asm-ppc64/tlbflush.h 2005-09-27 11:43:27.000000000 +1000 +++ linux-work/include/asm-ppc64/tlbflush.h 2005-09-27 11:45:09.000000000 +1000 @@ -25,6 +25,7 @@ pte_t pte[PPC64_TLB_BATCH_NR]; unsigned long addr[PPC64_TLB_BATCH_NR]; unsigned long vaddr[PPC64_TLB_BATCH_NR]; + unsigned int large; }; DECLARE_PER_CPU(struct ppc64_tlb_batch, ppc64_tlb_batch); From haveblue at us.ibm.com Tue Sep 27 12:33:31 2005 From: haveblue at us.ibm.com (Dave Hansen) Date: Mon, 26 Sep 2005 19:33:31 -0700 Subject: [PATCH] ppc64: More hugepage fixes In-Reply-To: <1127786197.15882.118.camel@gaston> References: <1127786197.15882.118.camel@gaston> Message-ID: <1127788411.10315.43.camel@localhost> On Tue, 2005-09-27 at 11:56 +1000, Benjamin Herrenschmidt wrote: > My previous patch fixing invalidation of huge PTEs wasn't good enough, > we still had an issue if a PTE invalidation batch contained both small > and large pages. This patch fixes this by making sure the batch is > flushed if the page size fed to it changes. (It always helps when you include 'diff -p' output; it makes patches much easier to read) I'm curious, what's the actual bug? __tlbie itself doesn't seem like it would do too much differently if called for large or small pages because all it does is align the vaddr differently. I don't know where it would even get an unaligned address from unless somebody sticks one in one of the batch->addrs. If the addresses are aligned, I don't see how this patch would help. Or, is it required that you must sync with: asm volatile("eieio; tlbsync; ptesync":::"memory"); between tlbie's of large and small pages. -- Dave From kumar.gala at freescale.com Tue Sep 27 13:39:56 2005 From: kumar.gala at freescale.com (Kumar Gala) Date: Mon, 26 Sep 2005 22:39:56 -0500 Subject: Starting the arch/powerpc merge In-Reply-To: <17208.37250.577664.621993@cargo.ozlabs.ibm.com> References: <17208.37250.577664.621993@cargo.ozlabs.ibm.com> Message-ID: <660EDD16-DB29-4168-8399-A0F4FA407CF5@freescale.com> On Sep 26, 2005, at 7:25 PM, Paul Mackerras wrote: > I have pushed a commit to the powerpc-merge.git tree which gets us far > enough to be able to build a 32-bit powermac kernel with > ARCH=powerpc. It's still very rough in places, and it uses bits out > of arch/ppc/kernel and arch/ppc/syslib, but it is a start. > > Of course, this means that we are about to bump up against the really > hard bits of the merge. Things like > > * converting ppc32 to use the lmb infrastructure > * introducing the device-tree flattening/unflattening to ppc32 > * working out how to deal with the early hash table initialization > that POWER4 needs on ppc32 > * reconciling the fact that ppc64 needs RELOC in the prom_init code, > whereas ppc32 doesn't; but ppc64 doesn't need RELOC when running > with the MMU off but ppc32 does (or needs -mrelocatable). > > I look forward to people sending me patches to push this on a bit > further, and in particular to populate arch/powerpc/platforms a bit > more. :) You have duplicated files between arch/ppc/ and arch/powerpc. Do you plan on cleaning this up are should we make sure we "fix" both? - kumar From benh at kernel.crashing.org Tue Sep 27 13:45:12 2005 From: benh at kernel.crashing.org (Benjamin Herrenschmidt) Date: Tue, 27 Sep 2005 13:45:12 +1000 Subject: [PATCH] ppc64: More hugepage fixes In-Reply-To: <1127788411.10315.43.camel@localhost> References: <1127786197.15882.118.camel@gaston> <1127788411.10315.43.camel@localhost> Message-ID: <1127792712.15882.122.camel@gaston> > I'm curious, what's the actual bug? > > __tlbie itself doesn't seem like it would do too much differently if > called for large or small pages because all it does is align the vaddr > differently. No, it also passes a different second argument to the asm tlbie instruction. It needs the value of the L bit. So we could fail to invalidate the TLB entries. > I don't know where it would even get an unaligned address > from unless somebody sticks one in one of the batch->addrs. That indeed shouldn't happen afaik. > If the addresses are aligned, I don't see how this patch would help. The missing L bit :) > Or, is it required that you must sync with: > > asm volatile("eieio; tlbsync; ptesync":::"memory"); > > between tlbie's of large and small pages. No. There is also the fact that we must not allow large pages to use tlbiel (there is a test for that too). It might actually work with more recent CPUs but that code can't deal with that. I have some rework of the low level code in that area that will be coming soon that addresses it in a more generic way. This fix is the "simple" one for now. Ben. From benh at kernel.crashing.org Tue Sep 27 13:50:19 2005 From: benh at kernel.crashing.org (Benjamin Herrenschmidt) Date: Tue, 27 Sep 2005 13:50:19 +1000 Subject: BUG: 2.6.14-rc2 sets the wrong time in NVRAM on PowerMac G5 In-Reply-To: <1127790420.8858.3.camel@localhost.localdomain> References: <20050922110828.GB7120@iucha.net> <1127429754.25837.32.camel@gaston> <20050926154415.GD7120@iucha.net> <1127769820.15882.83.camel@gaston> <1127790420.8858.3.camel@localhost.localdomain> Message-ID: <1127793019.15882.123.camel@gaston> On Mon, 2005-09-26 at 22:07 -0500, Florin Iucha wrote: > It happened again: > mac - good date/time > 2.6.14-rc1 - good date/time > 2.6.14-rc1-git1 - bad date/time : (Fri Aug 28 06:16:49 CDT 1987) > 2.6.14-rc1 - good date/time I have no idea what's up at this point. I'm currently running a top-of-tree git on a very similar G5 machine without such problem. Can you try - pulling a more recent -git tree and checking - building with an older compiler (gcc-3.4.x for example) Thanks, Ben. From sfr at canb.auug.org.au Tue Sep 27 14:09:39 2005 From: sfr at canb.auug.org.au (Stephen Rothwell) Date: Tue, 27 Sep 2005 14:09:39 +1000 Subject: [PATCH] ppc64 g5: merge tree build fix Message-ID: <20050927140939.2279a933.sfr@canb.auug.org.au> We removed __pmacdata in the merge. Signed-off-by: Stephen Rothwell --- drivers/macintosh/smu.c | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) -- Cheers, Stephen Rothwell sfr at canb.auug.org.au http://www.canb.auug.org.au/~sfr/ 1b05b6c7386f0d2d9dc5c45a61865ee5768c6780 diff --git a/drivers/macintosh/smu.c b/drivers/macintosh/smu.c --- a/drivers/macintosh/smu.c +++ b/drivers/macintosh/smu.c @@ -1092,7 +1092,7 @@ static int smu_release(struct inode *ino } -static struct file_operations smu_device_fops __pmacdata = { +static struct file_operations smu_device_fops = { .llseek = no_llseek, .read = smu_read, .write = smu_write, @@ -1101,7 +1101,7 @@ static struct file_operations smu_device .release = smu_release, }; -static struct miscdevice pmu_device __pmacdata = { +static struct miscdevice pmu_device = { MISC_DYNAMIC_MINOR, "smu", &smu_device_fops }; From sfr at canb.auug.org.au Tue Sep 27 15:38:40 2005 From: sfr at canb.auug.org.au (Stephen Rothwell) Date: Tue, 27 Sep 2005 15:38:40 +1000 Subject: Starting the arch/powerpc merge In-Reply-To: <660EDD16-DB29-4168-8399-A0F4FA407CF5@freescale.com> References: <17208.37250.577664.621993@cargo.ozlabs.ibm.com> <660EDD16-DB29-4168-8399-A0F4FA407CF5@freescale.com> Message-ID: <20050927153840.575d00e1.sfr@canb.auug.org.au> On Mon, 26 Sep 2005 22:39:56 -0500 Kumar Gala wrote: > > You have duplicated files between arch/ppc/ and arch/powerpc. Do you > plan on cleaning this up are should we make sure we "fix" both? I have done a patch that fixed most of those (but not all). It will be in the merge tree when Paulus next pushes it out. -- 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/20050927/5414291f/attachment.pgp From hch at lst.de Tue Sep 27 18:23:24 2005 From: hch at lst.de (Christoph Hellwig) Date: Tue, 27 Sep 2005 10:23:24 +0200 Subject: Starting the arch/powerpc merge In-Reply-To: <17208.37250.577664.621993@cargo.ozlabs.ibm.com> References: <17208.37250.577664.621993@cargo.ozlabs.ibm.com> Message-ID: <20050927082324.GA11437@lst.de> On Tue, Sep 27, 2005 at 10:25:38AM +1000, Paul Mackerras wrote: > * working out how to deal with the early hash table initialization > that POWER4 needs on ppc32 What about just dropping POWER3/4 support in 32bit mode? From paulus at samba.org Tue Sep 27 18:30:41 2005 From: paulus at samba.org (Paul Mackerras) Date: Tue, 27 Sep 2005 18:30:41 +1000 Subject: Starting the arch/powerpc merge In-Reply-To: <20050927082324.GA11437@lst.de> References: <17208.37250.577664.621993@cargo.ozlabs.ibm.com> <20050927082324.GA11437@lst.de> Message-ID: <17209.817.732159.375607@cargo.ozlabs.ibm.com> Christoph Hellwig writes: > What about just dropping POWER3/4 support in 32bit mode? Yes... I'm getting very close to deciding to do that. In fact POWER3 isn't too bad, since it still has BATs, but POWER4/PPC970 would be tricky. Does anyone on these lists have any major objections if we drop support for 32-bit kernels on POWER3 and POWER4/PPC970? Paul. From anton at samba.org Tue Sep 27 18:46:43 2005 From: anton at samba.org (Anton Blanchard) Date: Tue, 27 Sep 2005 18:46:43 +1000 Subject: [PATCH] ppc64: Add missing barrier() in kexec code Message-ID: <20050927084643.GG19971@krispykreme> Hi, Mikey and I were testing kexec and hit a lockup. It turns out gcc 4.0 optimises the kexec_prepare_cpus loop so we avoid reloading paca.hw_cpu_id. A gcc barrier() fixes the problem. Signed-off-by: Anton Blanchard --- Index: build/arch/ppc64/kernel/machine_kexec.c =================================================================== --- build.orig/arch/ppc64/kernel/machine_kexec.c 2005-09-14 13:22:30.000000000 +1000 +++ build/arch/ppc64/kernel/machine_kexec.c 2005-09-15 11:58:07.000000000 +1000 @@ -205,6 +205,7 @@ continue; while (paca[i].hw_cpu_id != -1) { + barrier(); if (!cpu_possible(i)) { printk("kexec: cpu %d hw_cpu_id %d is not" " possible, ignoring\n", From holindho at cs.helsinki.fi Tue Sep 27 19:16:12 2005 From: holindho at cs.helsinki.fi (Heikki Lindholm) Date: Tue, 27 Sep 2005 12:16:12 +0300 Subject: Starting the arch/powerpc merge In-Reply-To: <17209.817.732159.375607@cargo.ozlabs.ibm.com> References: <17208.37250.577664.621993@cargo.ozlabs.ibm.com> <20050927082324.GA11437@lst.de> <17209.817.732159.375607@cargo.ozlabs.ibm.com> Message-ID: <43390DDC.7090701@cs.helsinki.fi> Paul Mackerras kirjoitti: > Christoph Hellwig writes: > > >>What about just dropping POWER3/4 support in 32bit mode? > > > Yes... I'm getting very close to deciding to do that. In fact POWER3 > isn't too bad, since it still has BATs, but POWER4/PPC970 would be > tricky. > > Does anyone on these lists have any major objections if we drop > support for 32-bit kernels on POWER3 and POWER4/PPC970? I think it was Kumar Gala who already asked this a while ago. For me, 32-bit kernel on a 970 has been useful "initial stage" of gradually porting kernel stuff over to real 64-bit, but if I'm the only user and keeping the support is a nuisance, go ahead and drop it. -- Heikki Lindholm From panto at intracom.gr Tue Sep 27 19:26:38 2005 From: panto at intracom.gr (Pantelis Antoniou) Date: Tue, 27 Sep 2005 12:26:38 +0300 Subject: Starting the arch/powerpc merge In-Reply-To: <43390DDC.7090701@cs.helsinki.fi> References: <17208.37250.577664.621993@cargo.ozlabs.ibm.com> <20050927082324.GA11437@lst.de> <17209.817.732159.375607@cargo.ozlabs.ibm.com> <43390DDC.7090701@cs.helsinki.fi> Message-ID: <4339104E.7050705@intracom.gr> Heikki Lindholm wrote: > Paul Mackerras kirjoitti: > >> Christoph Hellwig writes: >> >> >>> What about just dropping POWER3/4 support in 32bit mode? >> >> >> >> Yes... I'm getting very close to deciding to do that. In fact POWER3 >> isn't too bad, since it still has BATs, but POWER4/PPC970 would be >> tricky. >> >> Does anyone on these lists have any major objections if we drop >> support for 32-bit kernels on POWER3 and POWER4/PPC970? > > > I think it was Kumar Gala who already asked this a while ago. For me, > 32-bit kernel on a 970 has been useful "initial stage" of gradually > porting kernel stuff over to real 64-bit, but if I'm the only user and > keeping the support is a nuisance, go ahead and drop it. > > -- Heikki Lindholm Count me in too; using a 970 in 32 bit mode, because of gentoo X.org problems in 64 bit mode. Regards Pantelis From paulus at samba.org Tue Sep 27 19:55:03 2005 From: paulus at samba.org (Paul Mackerras) Date: Tue, 27 Sep 2005 19:55:03 +1000 Subject: Starting the arch/powerpc merge In-Reply-To: <4339104E.7050705@intracom.gr> References: <17208.37250.577664.621993@cargo.ozlabs.ibm.com> <20050927082324.GA11437@lst.de> <17209.817.732159.375607@cargo.ozlabs.ibm.com> <43390DDC.7090701@cs.helsinki.fi> <4339104E.7050705@intracom.gr> Message-ID: <17209.5879.121421.718258@cargo.ozlabs.ibm.com> Pantelis Antoniou writes: > Count me in too; using a 970 in 32 bit mode, because of gentoo X.org > problems in 64 bit mode. I'm using an X.org server on a ppc64 kernel, and it all works, including DRI. Both 32-bit and 64-bit X server and clients work. We now have the 32-bit ioctl compatibility sorted out in the kernel DRM. So I don't think X is a reason to run a 32-bit kernel any more. What X.org problems do you see with a 64-bit kernel? Paul. From paulus at samba.org Tue Sep 27 19:56:20 2005 From: paulus at samba.org (Paul Mackerras) Date: Tue, 27 Sep 2005 19:56:20 +1000 Subject: Starting the arch/powerpc merge In-Reply-To: <660EDD16-DB29-4168-8399-A0F4FA407CF5@freescale.com> References: <17208.37250.577664.621993@cargo.ozlabs.ibm.com> <660EDD16-DB29-4168-8399-A0F4FA407CF5@freescale.com> Message-ID: <17209.5956.458201.760202@cargo.ozlabs.ibm.com> Kumar Gala writes: > You have duplicated files between arch/ppc/ and arch/powerpc. Do you > plan on cleaning this up are should we make sure we "fix" both? I did that deliberately so that I could hack the merged version without worrying about whether I would break the compile with ARCH=ppc or ARCH=ppc64. If it turns out that the merged version of some file is sufficiently similar to the ppc version, we can then delete the ppc version and just use the merged version. Paul. From panto at intracom.gr Tue Sep 27 19:51:25 2005 From: panto at intracom.gr (Pantelis Antoniou) Date: Tue, 27 Sep 2005 12:51:25 +0300 Subject: Starting the arch/powerpc merge In-Reply-To: <17209.5879.121421.718258@cargo.ozlabs.ibm.com> References: <17208.37250.577664.621993@cargo.ozlabs.ibm.com> <20050927082324.GA11437@lst.de> <17209.817.732159.375607@cargo.ozlabs.ibm.com> <43390DDC.7090701@cs.helsinki.fi> <4339104E.7050705@intracom.gr> <17209.5879.121421.718258@cargo.ozlabs.ibm.com> Message-ID: <4339161D.4010607@intracom.gr> Paul Mackerras wrote: > Pantelis Antoniou writes: > > >>Count me in too; using a 970 in 32 bit mode, because of gentoo X.org >>problems in 64 bit mode. > > > I'm using an X.org server on a ppc64 kernel, and it all works, > including DRI. Both 32-bit and 64-bit X server and clients work. We > now have the 32-bit ioctl compatibility sorted out in the kernel DRM. > So I don't think X is a reason to run a 32-bit kernel any more. > > What X.org problems do you see with a 64-bit kernel? > > Paul. > > > I didn't really tried a very recent kernel, I tried it about a month ago, and it didn't work. Could be a gentoo problem for all I know. Since I don't have time to debug these kind of problems, it's really nice to know that it now works :). No worries then. Regards Pantelis From dostrow at gentoo.org Wed Sep 28 01:43:46 2005 From: dostrow at gentoo.org (Daniel Ostrow) Date: Tue, 27 Sep 2005 11:43:46 -0400 Subject: Starting the arch/powerpc merge Message-ID: <1127835826.7811.27.camel@Memoria.anyarch.net> >Pantelis Antoniou writes: > >> Count me in too; using a 970 in 32 bit mode, because of gentoo X.org >> problems in 64 bit mode. > >I'm using an X.org server on a ppc64 kernel, and it all works, >including DRI. Both 32-bit and 64-bit X server and clients work. We >now have the 32-bit ioctl compatibility sorted out in the kernel DRM. >So I don't think X is a reason to run a 32-bit kernel any more. > >What X.org problems do you see with a 64-bit kernel? > >Paul. Speaking as a member of the Gentoo/PPC64 team I'm also curious what issues you are having...the only open issues that I am aware of have to do with the recent r7 X.org prereleases...both modular and monolithic. If that is what you are talking about then yeah there are issues...but more then likely they are on the X.org side not the kernels. Anything in the 6.8.2 range (which is what is stable) has been working fine for a long long time under a pure 64-bit env. Thanks, -- Daniel Ostrow Gentoo Foundation Board of Trustees Gentoo/{PPC,PPC64,DevRel} dostrow at gentoo.org From cfriesen at nortel.com Wed Sep 28 02:43:38 2005 From: cfriesen at nortel.com (Christopher Friesen) Date: Tue, 27 Sep 2005 10:43:38 -0600 Subject: Starting the arch/powerpc merge In-Reply-To: <1127835826.7811.27.camel@Memoria.anyarch.net> References: <1127835826.7811.27.camel@Memoria.anyarch.net> Message-ID: <433976BA.6010206@nortel.com> Daniel Ostrow wrote: > Anything in > the 6.8.2 range (which is what is stable) has been working fine for a > long long time under a pure 64-bit env. What about mixed 32-bit userspace and 64-bit kernel? Chris From dostrow at gentoo.org Wed Sep 28 03:29:43 2005 From: dostrow at gentoo.org (Daniel Ostrow) Date: Tue, 27 Sep 2005 13:29:43 -0400 Subject: Starting the arch/powerpc merge In-Reply-To: <433976BA.6010206@nortel.com> References: <1127835826.7811.27.camel@Memoria.anyarch.net> <433976BA.6010206@nortel.com> Message-ID: <1127842184.7811.61.camel@Memoria.anyarch.net> On Tue, 2005-09-27 at 10:43 -0600, Christopher Friesen wrote: > Daniel Ostrow wrote: > > Anything in > > the 6.8.2 range (which is what is stable) has been working fine for a > > long long time under a pure 64-bit env. > > What about mixed 32-bit userspace and 64-bit kernel? > > Chris > The way I set that up is still young...and has some issues (most of which should be fixed by the ppc && ppc64 -> powerpc merge). From what I have tested, it does work perfectly fine with 6.8.2...I haven't run into any issues. I maintain that profile so if there are issues please take them off this list...feel free to send them to ppc64 at gentoo.org or open a bug at bugs.gentoo.org and assign it to the ppc64 group. I'll see it either way. Thanks, -- Daniel Ostrow Gentoo Foundation Board of Trustees Gentoo/{PPC,PPC64,DevRel} dostrow at gentoo.org From agl at us.ibm.com Wed Sep 28 04:07:55 2005 From: agl at us.ibm.com (Adam Litke) Date: Tue, 27 Sep 2005 13:07:55 -0500 Subject: [PATCH] ppc64: More hugepage fixes In-Reply-To: <1127786197.15882.118.camel@gaston> References: <1127786197.15882.118.camel@gaston> Message-ID: <1127844475.8373.36.camel@localhost.localdomain> On Tue, 2005-09-27 at 11:56 +1000, Benjamin Herrenschmidt wrote: > My previous patch fixing invalidation of huge PTEs wasn't good enough, > we still had an issue if a PTE invalidation batch contained both small > and large pages. This patch fixes this by making sure the batch is > flushed if the page size fed to it changes. Great! Thanks Ben. This fixes the corruption I reported earlier. -- Adam Litke - (agl at us.ibm.com) IBM Linux Technology Center From bgill at freescale.com Wed Sep 28 05:28:56 2005 From: bgill at freescale.com (Becky Bruce) Date: Tue, 27 Sep 2005 14:28:56 -0500 (CDT) Subject: [PATCH] powerpc: merge byteorder.h Message-ID: powerpc: Merge byteorder.h Essentially adopts the 64-bit version of this file. The 32-bit version had been using unsigned ints for arguments/return values that were actually only 16 bits - the new file uses __u16 for these items as in the 64-bit version of the header. The order of some of the asm constraints in the 64-bit version was slightly different than the 32-bit version, but they produce identical code. Signed-off-by: Becky Bruce Signed-off-by: Kumar Gala --- commit 01344596fdecbe2b97e122b6a50570a19218cd2f tree ccdf20534198e69459d95f21b8f45aafc00e8238 parent d407c9f3f6f3c84d9daec257f9a2550aacbd2892 author Becky Bruce Tue, 27 Sep 2005 14:04:44 -0500 committer Becky Bruce Tue, 27 Sep 2005 14:04:44 -0500 include/asm-powerpc/byteorder.h | 89 +++++++++++++++++++++++++++++++++++++++ include/asm-ppc/byteorder.h | 76 --------------------------------- include/asm-ppc64/byteorder.h | 86 -------------------------------------- 3 files changed, 89 insertions(+), 162 deletions(-) diff --git a/include/asm-powerpc/byteorder.h b/include/asm-powerpc/byteorder.h new file mode 100644 --- /dev/null +++ b/include/asm-powerpc/byteorder.h @@ -0,0 +1,89 @@ +#ifndef _ASM_POWERPC_BYTEORDER_H +#define _ASM_POWERPC_BYTEORDER_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 + +#ifdef __GNUC__ +#ifdef __KERNEL__ + +static __inline__ __u16 ld_le16(const volatile __u16 *addr) +{ + __u16 val; + + __asm__ __volatile__ ("lhbrx %0,0,%1" : "=r" (val) : "r" (addr), "m" (*addr)); + return val; +} + +static __inline__ void st_le16(volatile __u16 *addr, const __u16 val) +{ + __asm__ __volatile__ ("sthbrx %1,0,%2" : "=m" (*addr) : "r" (val), "r" (addr)); +} + +static __inline__ __u32 ld_le32(const volatile __u32 *addr) +{ + __u32 val; + + __asm__ __volatile__ ("lwbrx %0,0,%1" : "=r" (val) : "r" (addr), "m" (*addr)); + return val; +} + +static __inline__ void st_le32(volatile __u32 *addr, const __u32 val) +{ + __asm__ __volatile__ ("stwbrx %1,0,%2" : "=m" (*addr) : "r" (val), "r" (addr)); +} + +static __inline__ __attribute_const__ __u16 ___arch__swab16(__u16 value) +{ + __u16 result; + + __asm__("rlwimi %0,%1,8,16,23" + : "=r" (result) + : "r" (value), "0" (value >> 8)); + return result; +} + +static __inline__ __attribute_const__ __u32 ___arch__swab32(__u32 value) +{ + __u32 result; + + __asm__("rlwimi %0,%1,24,16,23\n\t" + "rlwimi %0,%1,8,8,15\n\t" + "rlwimi %0,%1,24,0,7" + : "=r" (result) + : "r" (value), "0" (value >> 24)); + return result; +} + +#define __arch__swab16(x) ___arch__swab16(x) +#define __arch__swab32(x) ___arch__swab32(x) + +/* The same, but returns converted value from the location pointer by addr. */ +#define __arch__swab16p(addr) ld_le16(addr) +#define __arch__swab32p(addr) ld_le32(addr) + +/* The same, but do the conversion in situ, ie. put the value back to addr. */ +#define __arch__swab16s(addr) st_le16(addr,*addr) +#define __arch__swab32s(addr) st_le32(addr,*addr) + +#endif /* __KERNEL__ */ + +#ifndef __STRICT_ANSI__ +#define __BYTEORDER_HAS_U64__ +#ifndef __powerpc64__ +#define __SWAB_64_THRU_32__ +#endif /* __powerpc64__ */ +#endif /* __STRICT_ANSI__ */ + +#endif /* __GNUC__ */ + +#include + +#endif /* _ASM_POWERPC_BYTEORDER_H */ diff --git a/include/asm-ppc/byteorder.h b/include/asm-ppc/byteorder.h deleted file mode 100644 --- a/include/asm-ppc/byteorder.h +++ /dev/null @@ -1,76 +0,0 @@ -#ifndef _PPC_BYTEORDER_H -#define _PPC_BYTEORDER_H - -#include -#include - -#ifdef __GNUC__ -#ifdef __KERNEL__ - -extern __inline__ unsigned ld_le16(const volatile unsigned short *addr) -{ - unsigned val; - - __asm__ __volatile__ ("lhbrx %0,0,%1" : "=r" (val) : "r" (addr), "m" (*addr)); - return val; -} - -extern __inline__ void st_le16(volatile unsigned short *addr, const unsigned val) -{ - __asm__ __volatile__ ("sthbrx %1,0,%2" : "=m" (*addr) : "r" (val), "r" (addr)); -} - -extern __inline__ unsigned ld_le32(const volatile unsigned *addr) -{ - unsigned val; - - __asm__ __volatile__ ("lwbrx %0,0,%1" : "=r" (val) : "r" (addr), "m" (*addr)); - return val; -} - -extern __inline__ void st_le32(volatile unsigned *addr, const unsigned val) -{ - __asm__ __volatile__ ("stwbrx %1,0,%2" : "=m" (*addr) : "r" (val), "r" (addr)); -} - -static __inline__ __attribute_const__ __u16 ___arch__swab16(__u16 value) -{ - __u16 result; - - __asm__("rlwimi %0,%2,8,16,23" : "=&r" (result) : "0" (value >> 8), "r" (value)); - return result; -} - -static __inline__ __attribute_const__ __u32 ___arch__swab32(__u32 value) -{ - __u32 result; - - __asm__("rlwimi %0,%2,24,16,23" : "=&r" (result) : "0" (value>>24), "r" (value)); - __asm__("rlwimi %0,%2,8,8,15" : "=&r" (result) : "0" (result), "r" (value)); - __asm__("rlwimi %0,%2,24,0,7" : "=&r" (result) : "0" (result), "r" (value)); - - return result; -} -#define __arch__swab32(x) ___arch__swab32(x) -#define __arch__swab16(x) ___arch__swab16(x) - -/* The same, but returns converted value from the location pointer by addr. */ -#define __arch__swab16p(addr) ld_le16(addr) -#define __arch__swab32p(addr) ld_le32(addr) - -/* The same, but do the conversion in situ, ie. put the value back to addr. */ -#define __arch__swab16s(addr) st_le16(addr,*addr) -#define __arch__swab32s(addr) st_le32(addr,*addr) - -#endif /* __KERNEL__ */ - -#if !defined(__STRICT_ANSI__) || defined(__KERNEL__) -# define __BYTEORDER_HAS_U64__ -# define __SWAB_64_THRU_32__ -#endif - -#endif /* __GNUC__ */ - -#include - -#endif /* _PPC_BYTEORDER_H */ diff --git a/include/asm-ppc64/byteorder.h b/include/asm-ppc64/byteorder.h deleted file mode 100644 --- a/include/asm-ppc64/byteorder.h +++ /dev/null @@ -1,86 +0,0 @@ -#ifndef _PPC64_BYTEORDER_H -#define _PPC64_BYTEORDER_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 - -#ifdef __GNUC__ -#ifdef __KERNEL__ - -static __inline__ __u16 ld_le16(const volatile __u16 *addr) -{ - __u16 val; - - __asm__ __volatile__ ("lhbrx %0,0,%1" : "=r" (val) : "r" (addr), "m" (*addr)); - return val; -} - -static __inline__ void st_le16(volatile __u16 *addr, const __u16 val) -{ - __asm__ __volatile__ ("sthbrx %1,0,%2" : "=m" (*addr) : "r" (val), "r" (addr)); -} - -static __inline__ __u32 ld_le32(const volatile __u32 *addr) -{ - __u32 val; - - __asm__ __volatile__ ("lwbrx %0,0,%1" : "=r" (val) : "r" (addr), "m" (*addr)); - return val; -} - -static __inline__ void st_le32(volatile __u32 *addr, const __u32 val) -{ - __asm__ __volatile__ ("stwbrx %1,0,%2" : "=m" (*addr) : "r" (val), "r" (addr)); -} - -static __inline__ __attribute_const__ __u16 ___arch__swab16(__u16 value) -{ - __u16 result; - - __asm__("rlwimi %0,%1,8,16,23" - : "=r" (result) - : "r" (value), "0" (value >> 8)); - return result; -} - -static __inline__ __attribute_const__ __u32 ___arch__swab32(__u32 value) -{ - __u32 result; - - __asm__("rlwimi %0,%1,24,16,23\n\t" - "rlwimi %0,%1,8,8,15\n\t" - "rlwimi %0,%1,24,0,7" - : "=r" (result) - : "r" (value), "0" (value >> 24)); - return result; -} - -#define __arch__swab16(x) ___arch__swab16(x) -#define __arch__swab32(x) ___arch__swab32(x) - -/* The same, but returns converted value from the location pointer by addr. */ -#define __arch__swab16p(addr) ld_le16(addr) -#define __arch__swab32p(addr) ld_le32(addr) - -/* The same, but do the conversion in situ, ie. put the value back to addr. */ -#define __arch__swab16s(addr) st_le16(addr,*addr) -#define __arch__swab32s(addr) st_le32(addr,*addr) - -#endif /* __KERNEL__ */ - -#ifndef __STRICT_ANSI__ -#define __BYTEORDER_HAS_U64__ -#endif - -#endif /* __GNUC__ */ - -#include - -#endif /* _PPC64_BYTEORDER_H */ From galak at freescale.com Wed Sep 28 06:13:12 2005 From: galak at freescale.com (Kumar Gala) Date: Tue, 27 Sep 2005 15:13:12 -0500 (CDT) Subject: [PATCH] powerpc: make cur_cpu_spec a single pointer instead of an array on ppc32 Message-ID: If someone can test this on ppc32 and ppc32/SMP that would be helpful. I tried this out on a 834x (603 core) and it works ok, but would like to make sure it works on pmac & pmac/SMP. Also, this requires the previous patch that unifies cputable.h - kumar --- Changed ppc32 so that cur_cpu_spec is just a single pointer for all CPUs. Additionally, made call_setup_cpu check to see if the cpu_setup pointer is NULL or not before calling the function. This lets remove the dummy cpu_setup calls that just return. Signed-off-by: Kumar Gala --- commit 5624cf5d26b1c9318daceb92b605096cac58e206 tree 5ce3efa2a7c170406834f5d84786d1e1597cc87c parent 1545c0ecc0c5f6bd96a1882e782f8a1f3c67179b author Kumar K. Gala Tue, 27 Sep 2005 15:11:13 -0500 committer Kumar K. Gala Tue, 27 Sep 2005 15:11:13 -0500 arch/powerpc/kernel/head.S | 6 ----- arch/powerpc/oprofile/common.c | 6 ++--- arch/powerpc/platforms/powermac/pmac_setup.c | 2 +- arch/ppc/kernel/cpu_setup_6xx.S | 2 -- arch/ppc/kernel/cpu_setup_power4.S | 2 -- arch/ppc/kernel/cputable.c | 33 ++++++++++---------------- arch/ppc/kernel/head.S | 6 ----- arch/ppc/kernel/misc.S | 22 ++++++++--------- arch/ppc/kernel/setup.c | 14 ++++++----- arch/ppc/platforms/4xx/ebony.c | 2 +- arch/ppc/platforms/pmac_setup.c | 2 +- arch/ppc/platforms/radstone_ppc7d.c | 8 +++--- arch/ppc/syslib/ibm440gx_common.c | 6 ++--- include/asm-powerpc/cputable.h | 16 ------------- include/asm-powerpc/elf.h | 4 +-- 15 files changed, 43 insertions(+), 88 deletions(-) diff --git a/arch/powerpc/kernel/head.S b/arch/powerpc/kernel/head.S --- a/arch/powerpc/kernel/head.S +++ b/arch/powerpc/kernel/head.S @@ -1059,7 +1059,6 @@ __secondary_start: lis r3,-KERNELBASE at h mr r4,r24 - bl identify_cpu bl call_setup_cpu /* Call setup_cpu for this CPU */ #ifdef CONFIG_6xx lis r3,-KERNELBASE at h @@ -1109,11 +1108,6 @@ __secondary_start: * Those generic dummy functions are kept for CPUs not * included in CONFIG_6xx */ -_GLOBAL(__setup_cpu_power3) - blr -_GLOBAL(__setup_cpu_generic) - blr - #if !defined(CONFIG_6xx) && !defined(CONFIG_POWER4) _GLOBAL(__save_cpu_setup) blr diff --git a/arch/powerpc/oprofile/common.c b/arch/powerpc/oprofile/common.c --- a/arch/powerpc/oprofile/common.c +++ b/arch/powerpc/oprofile/common.c @@ -155,8 +155,6 @@ static int op_powerpc_create_files(struc int __init oprofile_arch_init(struct oprofile_operations *ops) { #ifndef __powerpc64__ - int cpu_id = smp_processor_id(); - #ifdef CONFIG_FSL_BOOKE model = &op_model_fsl_booke; #else @@ -167,9 +165,9 @@ int __init oprofile_arch_init(struct opr if (NULL == cpu_type) return -ENOMEM; - sprintf(cpu_type, "ppc/%s", cur_cpu_spec[cpu_id]->cpu_name); + sprintf(cpu_type, "ppc/%s", cur_cpu_spec->cpu_name); - model->num_counters = cur_cpu_spec[cpu_id]->num_pmcs; + model->num_counters = cur_cpu_spec->num_pmcs; ops->cpu_type = cpu_type; #else /* __powerpc64__ */ diff --git a/arch/powerpc/platforms/powermac/pmac_setup.c b/arch/powerpc/platforms/powermac/pmac_setup.c --- a/arch/powerpc/platforms/powermac/pmac_setup.c +++ b/arch/powerpc/platforms/powermac/pmac_setup.c @@ -445,7 +445,7 @@ static int pmac_pm_enter(suspend_state_t enable_kernel_fp(); #ifdef CONFIG_ALTIVEC - if (cur_cpu_spec[0]->cpu_features & CPU_FTR_ALTIVEC) + if (cur_cpu_spec->cpu_features & CPU_FTR_ALTIVEC) enable_kernel_altivec(); #endif /* CONFIG_ALTIVEC */ diff --git a/arch/ppc/kernel/cpu_setup_6xx.S b/arch/ppc/kernel/cpu_setup_6xx.S --- a/arch/ppc/kernel/cpu_setup_6xx.S +++ b/arch/ppc/kernel/cpu_setup_6xx.S @@ -17,8 +17,6 @@ #include #include -_GLOBAL(__setup_cpu_601) - blr _GLOBAL(__setup_cpu_603) b setup_common_caches _GLOBAL(__setup_cpu_604) diff --git a/arch/ppc/kernel/cpu_setup_power4.S b/arch/ppc/kernel/cpu_setup_power4.S --- a/arch/ppc/kernel/cpu_setup_power4.S +++ b/arch/ppc/kernel/cpu_setup_power4.S @@ -63,8 +63,6 @@ _GLOBAL(__970_cpu_preinit) isync blr -_GLOBAL(__setup_cpu_power4) - blr _GLOBAL(__setup_cpu_ppc970) mfspr r0,SPRN_HID0 li r11,5 /* clear DOZE and SLEEP */ diff --git a/arch/ppc/kernel/cputable.c b/arch/ppc/kernel/cputable.c --- a/arch/ppc/kernel/cputable.c +++ b/arch/ppc/kernel/cputable.c @@ -14,23 +14,22 @@ #include #include #include +#include + +#include #include -struct cpu_spec* cur_cpu_spec[NR_CPUS]; +struct cpu_spec* cur_cpu_spec = NULL; -extern void __setup_cpu_601(unsigned long offset, int cpu_nr, struct cpu_spec* spec); -extern void __setup_cpu_603(unsigned long offset, int cpu_nr, struct cpu_spec* spec); -extern void __setup_cpu_604(unsigned long offset, int cpu_nr, struct cpu_spec* spec); -extern void __setup_cpu_750(unsigned long offset, int cpu_nr, struct cpu_spec* spec); -extern void __setup_cpu_750cx(unsigned long offset, int cpu_nr, struct cpu_spec* spec); -extern void __setup_cpu_750fx(unsigned long offset, int cpu_nr, struct cpu_spec* spec); -extern void __setup_cpu_7400(unsigned long offset, int cpu_nr, struct cpu_spec* spec); -extern void __setup_cpu_7410(unsigned long offset, int cpu_nr, struct cpu_spec* spec); -extern void __setup_cpu_745x(unsigned long offset, int cpu_nr, struct cpu_spec* spec); -extern void __setup_cpu_power3(unsigned long offset, int cpu_nr, struct cpu_spec* spec); -extern void __setup_cpu_power4(unsigned long offset, int cpu_nr, struct cpu_spec* spec); -extern void __setup_cpu_ppc970(unsigned long offset, int cpu_nr, struct cpu_spec* spec); -extern void __setup_cpu_generic(unsigned long offset, int cpu_nr, struct cpu_spec* spec); +extern void __setup_cpu_603(unsigned long offset, struct cpu_spec* spec); +extern void __setup_cpu_604(unsigned long offset, struct cpu_spec* spec); +extern void __setup_cpu_750(unsigned long offset, struct cpu_spec* spec); +extern void __setup_cpu_750cx(unsigned long offset, struct cpu_spec* spec); +extern void __setup_cpu_750fx(unsigned long offset, struct cpu_spec* spec); +extern void __setup_cpu_7400(unsigned long offset, struct cpu_spec* spec); +extern void __setup_cpu_7410(unsigned long offset, struct cpu_spec* spec); +extern void __setup_cpu_745x(unsigned long offset, struct cpu_spec* spec); +extern void __setup_cpu_ppc970(unsigned long offset, struct cpu_spec* spec); #define CLASSIC_PPC (!defined(CONFIG_8xx) && !defined(CONFIG_4xx) && \ !defined(CONFIG_POWER3) && !defined(CONFIG_POWER4) && \ @@ -62,7 +61,6 @@ struct cpu_spec cpu_specs[] = { PPC_FEATURE_UNIFIED_CACHE, .icache_bsize = 32, .dcache_bsize = 32, - .cpu_setup = __setup_cpu_601 }, { /* 603 */ .pvr_mask = 0xffff0000, @@ -451,7 +449,6 @@ struct cpu_spec cpu_specs[] = { .cpu_user_features = COMMON_PPC, .icache_bsize = 32, .dcache_bsize = 32, - .cpu_setup = __setup_cpu_generic }, #endif /* CLASSIC_PPC */ #ifdef CONFIG_PPC64BRIDGE @@ -464,7 +461,6 @@ struct cpu_spec cpu_specs[] = { .icache_bsize = 128, .dcache_bsize = 128, .num_pmcs = 8, - .cpu_setup = __setup_cpu_power3 }, { /* Power3+ */ .pvr_mask = 0xffff0000, @@ -475,7 +471,6 @@ struct cpu_spec cpu_specs[] = { .icache_bsize = 128, .dcache_bsize = 128, .num_pmcs = 8, - .cpu_setup = __setup_cpu_power3 }, { /* I-star */ .pvr_mask = 0xffff0000, @@ -486,7 +481,6 @@ struct cpu_spec cpu_specs[] = { .icache_bsize = 128, .dcache_bsize = 128, .num_pmcs = 8, - .cpu_setup = __setup_cpu_power3 }, { /* S-star */ .pvr_mask = 0xffff0000, @@ -497,7 +491,6 @@ struct cpu_spec cpu_specs[] = { .icache_bsize = 128, .dcache_bsize = 128, .num_pmcs = 8, - .cpu_setup = __setup_cpu_power3 }, #endif /* CONFIG_PPC64BRIDGE */ #ifdef CONFIG_POWER4 diff --git a/arch/ppc/kernel/head.S b/arch/ppc/kernel/head.S --- a/arch/ppc/kernel/head.S +++ b/arch/ppc/kernel/head.S @@ -1059,7 +1059,6 @@ __secondary_start: lis r3,-KERNELBASE at h mr r4,r24 - bl identify_cpu bl call_setup_cpu /* Call setup_cpu for this CPU */ #ifdef CONFIG_6xx lis r3,-KERNELBASE at h @@ -1109,11 +1108,6 @@ __secondary_start: * Those generic dummy functions are kept for CPUs not * included in CONFIG_6xx */ -_GLOBAL(__setup_cpu_power3) - blr -_GLOBAL(__setup_cpu_generic) - blr - #if !defined(CONFIG_6xx) && !defined(CONFIG_POWER4) _GLOBAL(__save_cpu_setup) blr diff --git a/arch/ppc/kernel/misc.S b/arch/ppc/kernel/misc.S --- a/arch/ppc/kernel/misc.S +++ b/arch/ppc/kernel/misc.S @@ -125,9 +125,8 @@ _GLOBAL(identify_cpu) 1: addis r6,r3,cur_cpu_spec at ha addi r6,r6,cur_cpu_spec at l - slwi r4,r4,2 sub r8,r8,r3 - stwx r8,r4,r6 + stw r8,0(r6) blr /* @@ -186,19 +185,18 @@ _GLOBAL(do_cpu_ftr_fixups) * * Setup function is called with: * r3 = data offset - * r4 = CPU number - * r5 = ptr to CPU spec (relocated) + * r4 = ptr to CPU spec (relocated) */ _GLOBAL(call_setup_cpu) - addis r5,r3,cur_cpu_spec at ha - addi r5,r5,cur_cpu_spec at l - slwi r4,r24,2 - lwzx r5,r4,r5 + addis r4,r3,cur_cpu_spec at ha + addi r4,r4,cur_cpu_spec at l + lwz r4,0(r4) + add r4,r4,r3 + lwz r5,CPU_SPEC_SETUP(r4) + cmpi 0,r5,0 add r5,r5,r3 - lwz r6,CPU_SPEC_SETUP(r5) - add r6,r6,r3 - mtctr r6 - mr r4,r24 + beqlr + mtctr r5 bctr #if defined(CONFIG_CPU_FREQ_PMAC) && defined(CONFIG_6xx) diff --git a/arch/ppc/kernel/setup.c b/arch/ppc/kernel/setup.c --- a/arch/ppc/kernel/setup.c +++ b/arch/ppc/kernel/setup.c @@ -188,18 +188,18 @@ int show_cpuinfo(struct seq_file *m, voi seq_printf(m, "processor\t: %d\n", i); seq_printf(m, "cpu\t\t: "); - if (cur_cpu_spec[i]->pvr_mask) - seq_printf(m, "%s", cur_cpu_spec[i]->cpu_name); + if (cur_cpu_spec->pvr_mask) + seq_printf(m, "%s", cur_cpu_spec->cpu_name); else seq_printf(m, "unknown (%08x)", pvr); #ifdef CONFIG_ALTIVEC - if (cur_cpu_spec[i]->cpu_features & CPU_FTR_ALTIVEC) + if (cur_cpu_spec->cpu_features & CPU_FTR_ALTIVEC) seq_printf(m, ", altivec supported"); #endif seq_printf(m, "\n"); #ifdef CONFIG_TAU - if (cur_cpu_spec[i]->cpu_features & CPU_FTR_TAU) { + if (cur_cpu_spec->cpu_features & CPU_FTR_TAU) { #ifdef CONFIG_TAU_AVERAGE /* more straightforward, but potentially misleading */ seq_printf(m, "temperature \t: %u C (uncalibrated)\n", @@ -754,12 +754,12 @@ void __init setup_arch(char **cmdline_p) * for a possibly more accurate value. */ if (cpu_has_feature(CPU_FTR_SPLIT_ID_CACHE)) { - dcache_bsize = cur_cpu_spec[0]->dcache_bsize; - icache_bsize = cur_cpu_spec[0]->icache_bsize; + dcache_bsize = cur_cpu_spec->dcache_bsize; + icache_bsize = cur_cpu_spec->icache_bsize; ucache_bsize = 0; } else ucache_bsize = dcache_bsize = icache_bsize - = cur_cpu_spec[0]->dcache_bsize; + = cur_cpu_spec->dcache_bsize; /* reboot on panic */ panic_timeout = 180; diff --git a/arch/ppc/platforms/4xx/ebony.c b/arch/ppc/platforms/4xx/ebony.c --- a/arch/ppc/platforms/4xx/ebony.c +++ b/arch/ppc/platforms/4xx/ebony.c @@ -91,7 +91,7 @@ ebony_calibrate_decr(void) * on Rev. C silicon then errata forces us to * use the internal clock. */ - if (strcmp(cur_cpu_spec[0]->cpu_name, "440GP Rev. B") == 0) + if (strcmp(cur_cpu_spec->cpu_name, "440GP Rev. B") == 0) freq = EBONY_440GP_RB_SYSCLK; else freq = EBONY_440GP_RC_SYSCLK; diff --git a/arch/ppc/platforms/pmac_setup.c b/arch/ppc/platforms/pmac_setup.c --- a/arch/ppc/platforms/pmac_setup.c +++ b/arch/ppc/platforms/pmac_setup.c @@ -448,7 +448,7 @@ static int pmac_pm_enter(suspend_state_t enable_kernel_fp(); #ifdef CONFIG_ALTIVEC - if (cur_cpu_spec[0]->cpu_features & CPU_FTR_ALTIVEC) + if (cur_cpu_spec->cpu_features & CPU_FTR_ALTIVEC) enable_kernel_altivec(); #endif /* CONFIG_ALTIVEC */ diff --git a/arch/ppc/platforms/radstone_ppc7d.c b/arch/ppc/platforms/radstone_ppc7d.c --- a/arch/ppc/platforms/radstone_ppc7d.c +++ b/arch/ppc/platforms/radstone_ppc7d.c @@ -1185,18 +1185,18 @@ static void __init ppc7d_setup_arch(void ROOT_DEV = Root_HDA1; #endif - if ((cur_cpu_spec[0]->cpu_features & CPU_FTR_SPEC7450) || - (cur_cpu_spec[0]->cpu_features & CPU_FTR_L3CR)) + if ((cur_cpu_spec->cpu_features & CPU_FTR_SPEC7450) || + (cur_cpu_spec->cpu_features & CPU_FTR_L3CR)) /* 745x is different. We only want to pass along enable. */ _set_L2CR(L2CR_L2E); - else if (cur_cpu_spec[0]->cpu_features & CPU_FTR_L2CR) + else if (cur_cpu_spec->cpu_features & CPU_FTR_L2CR) /* All modules have 1MB of L2. We also assume that an * L2 divisor of 3 will work. */ _set_L2CR(L2CR_L2E | L2CR_L2SIZ_1MB | L2CR_L2CLK_DIV3 | L2CR_L2RAM_PIPE | L2CR_L2OH_1_0 | L2CR_L2DF); - if (cur_cpu_spec[0]->cpu_features & CPU_FTR_L3CR) + if (cur_cpu_spec->cpu_features & CPU_FTR_L3CR) /* No L3 cache */ _set_L3CR(0); diff --git a/arch/ppc/syslib/ibm440gx_common.c b/arch/ppc/syslib/ibm440gx_common.c --- a/arch/ppc/syslib/ibm440gx_common.c +++ b/arch/ppc/syslib/ibm440gx_common.c @@ -236,9 +236,9 @@ void __init ibm440gx_l2c_setup(struct ib /* Disable L2C on rev.A, rev.B and 800MHz version of rev.C, enable it on all other revisions */ - if (strcmp(cur_cpu_spec[0]->cpu_name, "440GX Rev. A") == 0 || - strcmp(cur_cpu_spec[0]->cpu_name, "440GX Rev. B") == 0 - || (strcmp(cur_cpu_spec[0]->cpu_name, "440GX Rev. C") + if (strcmp(cur_cpu_spec->cpu_name, "440GX Rev. A") == 0 || + strcmp(cur_cpu_spec->cpu_name, "440GX Rev. B") == 0 + || (strcmp(cur_cpu_spec->cpu_name, "440GX Rev. C") == 0 && p->cpu > 667000000)) ibm440gx_l2c_disable(); else diff --git a/include/asm-powerpc/cputable.h b/include/asm-powerpc/cputable.h --- a/include/asm-powerpc/cputable.h +++ b/include/asm-powerpc/cputable.h @@ -25,11 +25,7 @@ struct cpu_spec; struct op_powerpc_model; -#ifdef __powerpc64__ typedef void (*cpu_setup_t)(unsigned long offset, struct cpu_spec* spec); -#else /* __powerpc64__ */ -typedef void (*cpu_setup_t)(unsigned long offset, int cpu_nr, struct cpu_spec* spec); -#endif /* __powerpc64__ */ struct cpu_spec { /* CPU is matched via (PVR & pvr_mask) == pvr_value */ @@ -51,23 +47,15 @@ struct cpu_spec { * BHT, SPD, etc... from head.S before branching to identify_machine */ cpu_setup_t cpu_setup; -#ifdef __powerpc64__ /* Used by oprofile userspace to select the right counters */ char *oprofile_cpu_type; /* Processor specific oprofile operations */ struct op_powerpc_model *oprofile_model; -#endif /* __powerpc64__ */ }; -extern struct cpu_spec cpu_specs[]; - -#ifdef __powerpc64__ extern struct cpu_spec *cur_cpu_spec; -#else /* __powerpc64__ */ -extern struct cpu_spec *cur_cpu_spec[]; -#endif /* __powerpc64__ */ #endif /* __ASSEMBLY__ */ @@ -398,11 +386,7 @@ static inline int cpu_has_feature(unsign { return (CPU_FTRS_ALWAYS & feature) || (CPU_FTRS_POSSIBLE -#ifndef __powerpc64__ - & cur_cpu_spec[0]->cpu_features -#else & cur_cpu_spec->cpu_features -#endif & feature); } diff --git a/include/asm-powerpc/elf.h b/include/asm-powerpc/elf.h --- a/include/asm-powerpc/elf.h +++ b/include/asm-powerpc/elf.h @@ -212,15 +212,13 @@ extern int dump_task_fpu(struct task_str /* ELF_HWCAP yields a mask that user programs can use to figure out what instruction set this cpu supports. This could be done in userspace, but it's not easy, and we've already done it here. */ -#ifdef __powerpc64__ # define ELF_HWCAP (cur_cpu_spec->cpu_user_features) +#ifdef __powerpc64__ # define ELF_PLAT_INIT(_r, load_addr) do { \ memset(_r->gpr, 0, sizeof(_r->gpr)); \ _r->ctr = _r->link = _r->xer = _r->ccr = 0; \ _r->gpr[2] = load_addr; \ } while (0) -#else -# define ELF_HWCAP (cur_cpu_spec[0]->cpu_user_features) #endif /* __powerpc64__ */ /* This yields a string that ld.so will use to load implementation From paubert at iram.es Wed Sep 28 07:15:34 2005 From: paubert at iram.es (Gabriel Paubert) Date: Tue, 27 Sep 2005 23:15:34 +0200 Subject: [PATCH] powerpc: merge byteorder.h In-Reply-To: References: Message-ID: <20050927211534.GA32173@iram.es> On Tue, Sep 27, 2005 at 02:28:56PM -0500, Becky Bruce wrote: > powerpc: Merge byteorder.h > > Essentially adopts the 64-bit version of this file. The 32-bit version had > been using unsigned ints for arguments/return values that were actually > only 16 bits - the new file uses __u16 for these items as in the 64-bit > version of the header. The order of some of the asm constraints > in the 64-bit version was slightly different than the 32-bit version, > but they produce identical code. > > Signed-off-by: Becky Bruce > Signed-off-by: Kumar Gala > > --- > commit 01344596fdecbe2b97e122b6a50570a19218cd2f > tree ccdf20534198e69459d95f21b8f45aafc00e8238 > parent d407c9f3f6f3c84d9daec257f9a2550aacbd2892 > author Becky Bruce Tue, 27 Sep 2005 14:04:44 -0500 > committer Becky Bruce Tue, 27 Sep 2005 14:04:44 -0500 > > include/asm-powerpc/byteorder.h | 89 +++++++++++++++++++++++++++++++++++++++ > include/asm-ppc/byteorder.h | 76 --------------------------------- > include/asm-ppc64/byteorder.h | 86 -------------------------------------- > 3 files changed, 89 insertions(+), 162 deletions(-) > > diff --git a/include/asm-powerpc/byteorder.h b/include/asm-powerpc/byteorder.h > new file mode 100644 > --- /dev/null > +++ b/include/asm-powerpc/byteorder.h > @@ -0,0 +1,89 @@ > +#ifndef _ASM_POWERPC_BYTEORDER_H > +#define _ASM_POWERPC_BYTEORDER_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 > + > +#ifdef __GNUC__ > +#ifdef __KERNEL__ > + > +static __inline__ __u16 ld_le16(const volatile __u16 *addr) > +{ > + __u16 val; > + > + __asm__ __volatile__ ("lhbrx %0,0,%1" : "=r" (val) : "r" (addr), "m" (*addr)); > + return val; > +} > + > +static __inline__ void st_le16(volatile __u16 *addr, const __u16 val) > +{ > + __asm__ __volatile__ ("sthbrx %1,0,%2" : "=m" (*addr) : "r" (val), "r" (addr)); > +} > + > +static __inline__ __u32 ld_le32(const volatile __u32 *addr) > +{ > + __u32 val; > + > + __asm__ __volatile__ ("lwbrx %0,0,%1" : "=r" (val) : "r" (addr), "m" (*addr)); > + return val; > +} > + > +static __inline__ void st_le32(volatile __u32 *addr, const __u32 val) > +{ > + __asm__ __volatile__ ("stwbrx %1,0,%2" : "=m" (*addr) : "r" (val), "r" (addr)); > +} > + > +static __inline__ __attribute_const__ __u16 ___arch__swab16(__u16 value) > +{ > + __u16 result; > + > + __asm__("rlwimi %0,%1,8,16,23" > + : "=r" (result) > + : "r" (value), "0" (value >> 8)); > + return result; > +} This needs 2 registers where one is enough and often adds a truncation to 16 bit of results in the generated code. Consider instead: __u32 result; __asm__(" rlwimi %0,%0,16,8,15 # ??12->?212\n" : =r(result) : "0"(value)); return (__u16)(result>>8); GCC will combine the result>>8 with the truncation to the lower sixteen bits, often saving one instruction. This will likely generate worse code if you really need to keep both the original value and the swapped one, but this should not be the common case. > + > +static __inline__ __attribute_const__ __u32 ___arch__swab32(__u32 value) > +{ > + __u32 result; > + > + __asm__("rlwimi %0,%1,24,16,23\n\t" > + "rlwimi %0,%1,8,8,15\n\t" > + "rlwimi %0,%1,24,0,7" > + : "=r" (result) > + : "r" (value), "0" (value >> 24)); > + return result; > +} That one can be improved too, in only needs one rotlwi (rlwinm withou any mask) and 2 rlwimi: __asm__(" rotlwi %0,%1,8 # 1234 -> 2341\n" " rlwimi %0,%1,24,0,7 \n" " rlwimi %0,%1,24,16,23 \n" : "=&r" (result) : r(value)) Notes: - reformat as you like, but I prefer the tab at the beginning of every line, otherwise the assembly output does not look right. I always add a \n at the end just in case (do all versions of GCC add it or not?). - the earlyclobber (&) is really necessary otherwise GCC might allocate the same register for input and output for __arch_swab32. What should really be implemented in GCC is a recognizer for the manipulations that can easily be mapped to a single rlwimi instruction. But it is too complex for the standard combiner IIRC. Regards, Gabriel From benh at kernel.crashing.org Wed Sep 28 10:05:14 2005 From: benh at kernel.crashing.org (Benjamin Herrenschmidt) Date: Wed, 28 Sep 2005 10:05:14 +1000 Subject: Starting the arch/powerpc merge In-Reply-To: <17209.817.732159.375607@cargo.ozlabs.ibm.com> References: <17208.37250.577664.621993@cargo.ozlabs.ibm.com> <20050927082324.GA11437@lst.de> <17209.817.732159.375607@cargo.ozlabs.ibm.com> Message-ID: <1127865914.6102.0.camel@gaston> On Tue, 2005-09-27 at 18:30 +1000, Paul Mackerras wrote: > Christoph Hellwig writes: > > > What about just dropping POWER3/4 support in 32bit mode? > > Yes... I'm getting very close to deciding to do that. In fact POWER3 > isn't too bad, since it still has BATs, but POWER4/PPC970 would be > tricky. > > Does anyone on these lists have any major objections if we drop > support for 32-bit kernels on POWER3 and POWER4/PPC970? I've stopped supporting G5 on 32 bits kernel for some time now, I have absolutely no problem just dropping the POWER4 support in 32 bits kernel in the merged tree. Ben. From benh at kernel.crashing.org Wed Sep 28 10:07:08 2005 From: benh at kernel.crashing.org (Benjamin Herrenschmidt) Date: Wed, 28 Sep 2005 10:07:08 +1000 Subject: Starting the arch/powerpc merge In-Reply-To: <1127842184.7811.61.camel@Memoria.anyarch.net> References: <1127835826.7811.27.camel@Memoria.anyarch.net> <433976BA.6010206@nortel.com> <1127842184.7811.61.camel@Memoria.anyarch.net> Message-ID: <1127866028.6102.2.camel@gaston> > The way I set that up is still young...and has some issues (most of > which should be fixed by the ppc && ppc64 -> powerpc merge). From what I > have tested, it does work perfectly fine with 6.8.2...I haven't run into > any issues. I maintain that profile so if there are issues please take > them off this list...feel free to send them to ppc64 at gentoo.org or open > a bug at bugs.gentoo.org and assign it to the ppc64 group. I'll see it > either way. I'm running a 32 bits X.org 6.8.99 from CVS with the r300 DRI stuff etc... on a G5 with 64 bits kernel without trouble. Paulus did the same with a 64 bits X. Ben. From benh at kernel.crashing.org Wed Sep 28 11:45:45 2005 From: benh at kernel.crashing.org (Benjamin Herrenschmidt) Date: Wed, 28 Sep 2005 11:45:45 +1000 Subject: new iMac G5 user, need infos Message-ID: <1127871945.6102.6.camel@gaston> Hi ! Is there somebody around with access to one of the new iMac G5 models ? (PowerMac8,2). I would need a dump of the open firmware device-tree on these machines (tarball of /proc/device-tree) Thanks ! Ben. From sfr at canb.auug.org.au Wed Sep 28 16:33:33 2005 From: sfr at canb.auug.org.au (Stephen Rothwell) Date: Wed, 28 Sep 2005 16:33:33 +1000 Subject: [PATCH 0/19] ppc64 iSeries: move most of the iSeries files to powerpc/plaforms Message-ID: <20050928163333.02799419.sfr@canb.auug.org.au> This patch set moves almost all the iSeries sepcific code from arch/ppc64/kernel to arch/powerpc/platforms/iseries. The last patch removes iSeries_Device_Node, using device_node and pci_dn instead. -- Cheers, Stephen Rothwell sfr at canb.auug.org.au http://www.canb.auug.org.au/~sfr/ arch/powerpc/platforms/Makefile | 11 arch/powerpc/platforms/iseries/Makefile | 29 arch/powerpc/platforms/iseries/htab.c | 256 +++++ arch/powerpc/platforms/iseries/hvcall.S | 93 + arch/powerpc/platforms/iseries/hvcall.c | 70 - arch/powerpc/platforms/iseries/hvlog.c | 35 arch/powerpc/platforms/iseries/hvlpconfig.c | 26 arch/powerpc/platforms/iseries/iommu.c | 204 ++++ arch/powerpc/platforms/iseries/irq.c | 365 +++++++ arch/powerpc/platforms/iseries/ksyms.c | 27 arch/powerpc/platforms/iseries/lpardata.c | 227 ++++ arch/powerpc/platforms/iseries/lpevents.c | 329 ++++++- arch/powerpc/platforms/iseries/mf.c | 1316 ++++++++++++++++++++++++++++ arch/powerpc/platforms/iseries/misc.S | 55 + arch/powerpc/platforms/iseries/pci.c | 994 ++++++++++++++++++++- arch/powerpc/platforms/iseries/proc.c | 115 ++ arch/powerpc/platforms/iseries/setup.c | 1006 +++++++++++++++++++++ arch/powerpc/platforms/iseries/setup.h | 24 arch/powerpc/platforms/iseries/smp.c | 121 ++ arch/powerpc/platforms/iseries/vio.c | 156 +++ arch/powerpc/platforms/iseries/viopath.c | 672 ++++++++++++++ arch/powerpc/platforms/iseries/vpdinfo.c | 268 +++++ arch/ppc64/Makefile | 1 arch/ppc64/kernel/HvCall.c | 36 arch/ppc64/kernel/HvLpConfig.c | 27 arch/ppc64/kernel/HvLpEvent.c | 88 - arch/ppc64/kernel/ItLpQueue.c | 262 ----- arch/ppc64/kernel/LparData.c | 227 ---- arch/ppc64/kernel/Makefile | 34 arch/ppc64/kernel/bpa_iommu.c | 2 arch/ppc64/kernel/bpa_setup.c | 2 arch/ppc64/kernel/eeh.c | 2 arch/ppc64/kernel/head.S | 2 arch/ppc64/kernel/hvCall.S | 98 -- arch/ppc64/kernel/iSeries_VpdInfo.c | 268 ----- arch/ppc64/kernel/iSeries_htab.c | 255 ----- arch/ppc64/kernel/iSeries_iommu.c | 177 --- arch/ppc64/kernel/iSeries_irq.c | 366 ------- arch/ppc64/kernel/iSeries_pci.c | 905 ------------------- arch/ppc64/kernel/iSeries_proc.c | 113 -- arch/ppc64/kernel/iSeries_setup.c | 1007 --------------------- arch/ppc64/kernel/iSeries_setup.h | 26 arch/ppc64/kernel/iSeries_smp.c | 121 -- arch/ppc64/kernel/iSeries_vio.c | 156 --- arch/ppc64/kernel/maple_pci.c | 3 arch/ppc64/kernel/mf.c | 1281 --------------------------- arch/ppc64/kernel/misc.S | 38 arch/ppc64/kernel/pSeries_iommu.c | 2 arch/ppc64/kernel/pSeries_pci.c | 3 arch/ppc64/kernel/pSeries_setup.c | 2 arch/ppc64/kernel/pci.c | 3 arch/ppc64/kernel/pci.h | 54 - arch/ppc64/kernel/pci_direct_iommu.c | 3 arch/ppc64/kernel/pci_dn.c | 3 arch/ppc64/kernel/pci_iommu.c | 8 arch/ppc64/kernel/pmac_pci.c | 2 arch/ppc64/kernel/ppc_ksyms.c | 20 arch/ppc64/kernel/rtas_pci.c | 3 arch/ppc64/kernel/rtc.c | 37 arch/ppc64/kernel/sys_ppc32.c | 3 arch/ppc64/kernel/u3_iommu.c | 3 arch/ppc64/kernel/viopath.c | 673 -------------- include/asm-powerpc/ppc-pci.h | 54 + include/asm-ppc64/iSeries/iSeries_pci.h | 30 include/asm-ppc64/iommu.h | 4 include/asm-ppc64/pci-bridge.h | 10 include/asm-ppc64/prom.h | 3 67 files changed, 6397 insertions(+), 6419 deletions(-) From sfr at canb.auug.org.au Wed Sep 28 16:35:18 2005 From: sfr at canb.auug.org.au (Stephen Rothwell) Date: Wed, 28 Sep 2005 16:35:18 +1000 Subject: [PATCH 1/19] powerpc: Create arch/powerpc/platforms/iseries In-Reply-To: <20050928163333.02799419.sfr@canb.auug.org.au> References: <20050928163333.02799419.sfr@canb.auug.org.au> Message-ID: <20050928163518.21d43852.sfr@canb.auug.org.au> I also move arch/ppc64/kernel/HvCall.c to arch/powerpc/platforms/iseries/hvcall.c. Signed-off-by: Stephen Rothwell --- arch/powerpc/platforms/Makefile | 9 ++++---- arch/powerpc/platforms/iseries/Makefile | 1 + arch/powerpc/platforms/iseries/hvcall.c | 35 ++++++++++++++++++++++++++++++ arch/ppc64/Makefile | 1 + arch/ppc64/kernel/HvCall.c | 36 ------------------------------- arch/ppc64/kernel/Makefile | 2 +- 6 files changed, 43 insertions(+), 41 deletions(-) create mode 100644 arch/powerpc/platforms/iseries/Makefile create mode 100644 arch/powerpc/platforms/iseries/hvcall.c delete mode 100644 arch/ppc64/kernel/HvCall.c -- Cheers, Stephen Rothwell sfr at canb.auug.org.au http://www.canb.auug.org.au/~sfr/ ba0dd617a3e23321a14cb38ff7ad6f796ba32c34 diff --git a/arch/powerpc/platforms/Makefile b/arch/powerpc/platforms/Makefile --- a/arch/powerpc/platforms/Makefile +++ b/arch/powerpc/platforms/Makefile @@ -1,4 +1,5 @@ -obj-$(CONFIG_PPC_PMAC) += powermac/ -obj-$(CONFIG_4xx) += 4xx/ -obj-$(CONFIG_83xx) += 83xx/ -obj-$(CONFIG_85xx) += 85xx/ +obj-$(CONFIG_PPC_PMAC) += powermac/ +obj-$(CONFIG_4xx) += 4xx/ +obj-$(CONFIG_83xx) += 83xx/ +obj-$(CONFIG_85xx) += 85xx/ +obj-$(CONFIG_PPC_ISERIES) += iseries/ diff --git a/arch/powerpc/platforms/iseries/Makefile b/arch/powerpc/platforms/iseries/Makefile new file mode 100644 --- /dev/null +++ b/arch/powerpc/platforms/iseries/Makefile @@ -0,0 +1 @@ +obj-$(CONFIG_PPC_ISERIES) += hvcall.o diff --git a/arch/powerpc/platforms/iseries/hvcall.c b/arch/powerpc/platforms/iseries/hvcall.c new file mode 100644 --- /dev/null +++ b/arch/powerpc/platforms/iseries/hvcall.c @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2001 Mike Corrigan 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. + */ + +#include +#include +#include +#include +#include + + +void HvCall_writeLogBuffer(const void *buffer, u64 len) +{ + struct HvLpBufferList hv_buf; + u64 left_this_page; + u64 cur = virt_to_abs(buffer); + + while (len) { + hv_buf.addr = cur; + left_this_page = ((cur & PAGE_MASK) + PAGE_SIZE) - cur; + if (left_this_page > len) + left_this_page = len; + hv_buf.len = left_this_page; + len -= left_this_page; + HvCall2(HvCallBaseWriteLogBuffer, + virt_to_abs(&hv_buf), + left_this_page); + cur = (cur & PAGE_MASK) + PAGE_SIZE; + } +} diff --git a/arch/ppc64/Makefile b/arch/ppc64/Makefile --- a/arch/ppc64/Makefile +++ b/arch/ppc64/Makefile @@ -84,6 +84,7 @@ head-y := arch/ppc64/kernel/head.o libs-y += arch/ppc64/lib/ core-y += arch/ppc64/kernel/ core-y += arch/ppc64/mm/ +core-y += arch/powerpc/platforms/ core-$(CONFIG_XMON) += arch/ppc64/xmon/ drivers-$(CONFIG_OPROFILE) += arch/powerpc/oprofile/ diff --git a/arch/ppc64/kernel/HvCall.c b/arch/ppc64/kernel/HvCall.c deleted file mode 100644 --- a/arch/ppc64/kernel/HvCall.c +++ /dev/null @@ -1,36 +0,0 @@ -/* - * HvCall.c - * Copyright (C) 2001 Mike Corrigan 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. - */ - -#include -#include -#include -#include -#include - - -void HvCall_writeLogBuffer(const void *buffer, u64 len) -{ - struct HvLpBufferList hv_buf; - u64 left_this_page; - u64 cur = virt_to_abs(buffer); - - while (len) { - hv_buf.addr = cur; - left_this_page = ((cur & PAGE_MASK) + PAGE_SIZE) - cur; - if (left_this_page > len) - left_this_page = len; - hv_buf.len = left_this_page; - len -= left_this_page; - HvCall2(HvCallBaseWriteLogBuffer, - virt_to_abs(&hv_buf), - left_this_page); - cur = (cur & PAGE_MASK) + PAGE_SIZE; - } -} diff --git a/arch/ppc64/kernel/Makefile b/arch/ppc64/kernel/Makefile --- a/arch/ppc64/kernel/Makefile +++ b/arch/ppc64/kernel/Makefile @@ -22,7 +22,7 @@ pci-obj-$(CONFIG_PPC_MULTIPLATFORM) += p obj-$(CONFIG_PCI) += pci.o pci_iommu.o iomap.o $(pci-obj-y) -obj-$(CONFIG_PPC_ISERIES) += HvCall.o HvLpConfig.o LparData.o \ +obj-$(CONFIG_PPC_ISERIES) += HvLpConfig.o LparData.o \ iSeries_setup.o ItLpQueue.o hvCall.o \ mf.o HvLpEvent.o iSeries_proc.o iSeries_htab.o \ iSeries_iommu.o From sfr at canb.auug.org.au Wed Sep 28 16:44:28 2005 From: sfr at canb.auug.org.au (Stephen Rothwell) Date: Wed, 28 Sep 2005 16:44:28 +1000 Subject: [PATCH 2/19] powerpc: Move HvLpConfig.c to powerpc arch In-Reply-To: <20050928163333.02799419.sfr@canb.auug.org.au> References: <20050928163333.02799419.sfr@canb.auug.org.au> Message-ID: <20050928164428.05e174f8.sfr@canb.auug.org.au> Also rename it to hvlpconfig.c Signed-off-by: Stephen Rothwell --- arch/powerpc/platforms/iseries/Makefile | 2 +- arch/powerpc/platforms/iseries/hvlpconfig.c | 26 ++++++++++++++++++++++++++ arch/ppc64/kernel/HvLpConfig.c | 27 --------------------------- arch/ppc64/kernel/Makefile | 2 +- 4 files changed, 28 insertions(+), 29 deletions(-) create mode 100644 arch/powerpc/platforms/iseries/hvlpconfig.c delete mode 100644 arch/ppc64/kernel/HvLpConfig.c -- Cheers, Stephen Rothwell sfr at canb.auug.org.au http://www.canb.auug.org.au/~sfr/ acdbec1b8974f61b0cb69ebe57916f8721b2f3d7 diff --git a/arch/powerpc/platforms/iseries/Makefile b/arch/powerpc/platforms/iseries/Makefile --- a/arch/powerpc/platforms/iseries/Makefile +++ b/arch/powerpc/platforms/iseries/Makefile @@ -1 +1 @@ -obj-$(CONFIG_PPC_ISERIES) += hvcall.o +obj-$(CONFIG_PPC_ISERIES) += hvcall.o hvlpconfig.o diff --git a/arch/powerpc/platforms/iseries/hvlpconfig.c b/arch/powerpc/platforms/iseries/hvlpconfig.c new file mode 100644 --- /dev/null +++ b/arch/powerpc/platforms/iseries/hvlpconfig.c @@ -0,0 +1,26 @@ +/* + * Copyright (C) 2001 Kyle A. Lucke, 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 + */ + +#include +#include + +HvLpIndex HvLpConfig_getLpIndex_outline(void) +{ + return HvLpConfig_getLpIndex(); +} +EXPORT_SYMBOL(HvLpConfig_getLpIndex_outline); diff --git a/arch/ppc64/kernel/HvLpConfig.c b/arch/ppc64/kernel/HvLpConfig.c deleted file mode 100644 --- a/arch/ppc64/kernel/HvLpConfig.c +++ /dev/null @@ -1,27 +0,0 @@ -/* - * HvLpConfig.c - * Copyright (C) 2001 Kyle A. Lucke, 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 - */ - -#include -#include - -HvLpIndex HvLpConfig_getLpIndex_outline(void) -{ - return HvLpConfig_getLpIndex(); -} -EXPORT_SYMBOL(HvLpConfig_getLpIndex_outline); diff --git a/arch/ppc64/kernel/Makefile b/arch/ppc64/kernel/Makefile --- a/arch/ppc64/kernel/Makefile +++ b/arch/ppc64/kernel/Makefile @@ -22,7 +22,7 @@ pci-obj-$(CONFIG_PPC_MULTIPLATFORM) += p obj-$(CONFIG_PCI) += pci.o pci_iommu.o iomap.o $(pci-obj-y) -obj-$(CONFIG_PPC_ISERIES) += HvLpConfig.o LparData.o \ +obj-$(CONFIG_PPC_ISERIES) += LparData.o \ iSeries_setup.o ItLpQueue.o hvCall.o \ mf.o HvLpEvent.o iSeries_proc.o iSeries_htab.o \ iSeries_iommu.o From sfr at canb.auug.org.au Wed Sep 28 16:45:24 2005 From: sfr at canb.auug.org.au (Stephen Rothwell) Date: Wed, 28 Sep 2005 16:45:24 +1000 Subject: [PATCH 3/19] powerpc: Move LparData.c to powerpc platforms In-Reply-To: <20050928163333.02799419.sfr@canb.auug.org.au> References: <20050928163333.02799419.sfr@canb.auug.org.au> Message-ID: <20050928164524.17fcf9dc.sfr@canb.auug.org.au> Also rename it to lpardata.c Signed-off-by: Stephen Rothwell --- arch/powerpc/platforms/iseries/Makefile | 2 arch/powerpc/platforms/iseries/lpardata.c | 227 +++++++++++++++++++++++++++++ arch/ppc64/kernel/LparData.c | 227 ----------------------------- arch/ppc64/kernel/Makefile | 3 arch/ppc64/kernel/head.S | 2 5 files changed, 230 insertions(+), 231 deletions(-) create mode 100644 arch/powerpc/platforms/iseries/lpardata.c delete mode 100644 arch/ppc64/kernel/LparData.c -- Cheers, Stephen Rothwell sfr at canb.auug.org.au http://www.canb.auug.org.au/~sfr/ 2960eb661a82131b9492cdd1b6500a5f74ccc394 diff --git a/arch/powerpc/platforms/iseries/Makefile b/arch/powerpc/platforms/iseries/Makefile --- a/arch/powerpc/platforms/iseries/Makefile +++ b/arch/powerpc/platforms/iseries/Makefile @@ -1 +1 @@ -obj-$(CONFIG_PPC_ISERIES) += hvcall.o hvlpconfig.o +obj-$(CONFIG_PPC_ISERIES) += hvcall.o hvlpconfig.o lpardata.o diff --git a/arch/powerpc/platforms/iseries/lpardata.c b/arch/powerpc/platforms/iseries/lpardata.c new file mode 100644 --- /dev/null +++ b/arch/powerpc/platforms/iseries/lpardata.c @@ -0,0 +1,227 @@ +/* + * Copyright 2001 Mike Corrigan, 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +/* The HvReleaseData is the root of the information shared between + * the hypervisor and Linux. + */ +struct HvReleaseData hvReleaseData = { + .xDesc = 0xc8a5d9c4, /* "HvRD" ebcdic */ + .xSize = sizeof(struct HvReleaseData), + .xVpdAreasPtrOffset = offsetof(struct naca_struct, xItVpdAreas), + .xSlicNacaAddr = &naca, /* 64-bit Naca address */ + .xMsNucDataOffset = LPARMAP_PHYS, + .xFlags = HVREL_TAGSINACTIVE /* tags inactive */ + /* 64 bit */ + /* shared processors */ + /* HMT allowed */ + | 6, /* TEMP: This allows non-GA driver */ + .xVrmIndex = 4, /* We are v5r2m0 */ + .xMinSupportedPlicVrmIndex = 3, /* v5r1m0 */ + .xMinCompatablePlicVrmIndex = 3, /* v5r1m0 */ + .xVrmName = { 0xd3, 0x89, 0x95, 0xa4, /* "Linux 2.4.64" ebcdic */ + 0xa7, 0x40, 0xf2, 0x4b, + 0xf4, 0x4b, 0xf6, 0xf4 }, +}; + +/* + * The NACA. The first dword of the naca is required by the iSeries + * hypervisor to point to itVpdAreas. The hypervisor finds the NACA + * through the pointer in hvReleaseData. + */ +struct naca_struct naca = { + .xItVpdAreas = &itVpdAreas, + .xRamDisk = 0, + .xRamDiskSize = 0, +}; + +extern void system_reset_iSeries(void); +extern void machine_check_iSeries(void); +extern void data_access_iSeries(void); +extern void instruction_access_iSeries(void); +extern void hardware_interrupt_iSeries(void); +extern void alignment_iSeries(void); +extern void program_check_iSeries(void); +extern void fp_unavailable_iSeries(void); +extern void decrementer_iSeries(void); +extern void trap_0a_iSeries(void); +extern void trap_0b_iSeries(void); +extern void system_call_iSeries(void); +extern void single_step_iSeries(void); +extern void trap_0e_iSeries(void); +extern void performance_monitor_iSeries(void); +extern void data_access_slb_iSeries(void); +extern void instruction_access_slb_iSeries(void); + +struct ItLpNaca itLpNaca = { + .xDesc = 0xd397d581, /* "LpNa" ebcdic */ + .xSize = 0x0400, /* size of ItLpNaca */ + .xIntHdlrOffset = 0x0300, /* offset to int array */ + .xMaxIntHdlrEntries = 19, /* # ents */ + .xPrimaryLpIndex = 0, /* Part # of primary */ + .xServiceLpIndex = 0, /* Part # of serv */ + .xLpIndex = 0, /* Part # of me */ + .xMaxLpQueues = 0, /* # of LP queues */ + .xLpQueueOffset = 0x100, /* offset of start of LP queues */ + .xPirEnvironMode = 0, /* Piranha stuff */ + .xPirConsoleMode = 0, + .xPirDasdMode = 0, + .xLparInstalled = 0, + .xSysPartitioned = 0, + .xHwSyncedTBs = 0, + .xIntProcUtilHmt = 0, + .xSpVpdFormat = 0, + .xIntProcRatio = 0, + .xPlicVrmIndex = 0, /* VRM index of PLIC */ + .xMinSupportedSlicVrmInd = 0, /* min supported SLIC */ + .xMinCompatableSlicVrmInd = 0, /* min compat SLIC */ + .xLoadAreaAddr = 0, /* 64-bit addr of load area */ + .xLoadAreaChunks = 0, /* chunks for load area */ + .xPaseSysCallCRMask = 0, /* PASE mask */ + .xSlicSegmentTablePtr = 0, /* seg table */ + .xOldLpQueue = { 0 }, /* Old LP Queue */ + .xInterruptHdlr = { + (u64)system_reset_iSeries, /* 0x100 System Reset */ + (u64)machine_check_iSeries, /* 0x200 Machine Check */ + (u64)data_access_iSeries, /* 0x300 Data Access */ + (u64)instruction_access_iSeries, /* 0x400 Instruction Access */ + (u64)hardware_interrupt_iSeries, /* 0x500 External */ + (u64)alignment_iSeries, /* 0x600 Alignment */ + (u64)program_check_iSeries, /* 0x700 Program Check */ + (u64)fp_unavailable_iSeries, /* 0x800 FP Unavailable */ + (u64)decrementer_iSeries, /* 0x900 Decrementer */ + (u64)trap_0a_iSeries, /* 0xa00 Trap 0A */ + (u64)trap_0b_iSeries, /* 0xb00 Trap 0B */ + (u64)system_call_iSeries, /* 0xc00 System Call */ + (u64)single_step_iSeries, /* 0xd00 Single Step */ + (u64)trap_0e_iSeries, /* 0xe00 Trap 0E */ + (u64)performance_monitor_iSeries,/* 0xf00 Performance Monitor */ + 0, /* int 0x1000 */ + 0, /* int 0x1010 */ + 0, /* int 0x1020 CPU ctls */ + (u64)hardware_interrupt_iSeries, /* SC Ret Hdlr */ + (u64)data_access_slb_iSeries, /* 0x380 D-SLB */ + (u64)instruction_access_slb_iSeries /* 0x480 I-SLB */ + } +}; +EXPORT_SYMBOL(itLpNaca); + +/* May be filled in by the hypervisor so cannot end up in the BSS */ +struct ItIplParmsReal xItIplParmsReal __attribute__((__section__(".data"))); + +/* May be filled in by the hypervisor so cannot end up in the BSS */ +struct ItExtVpdPanel xItExtVpdPanel __attribute__((__section__(".data"))); +EXPORT_SYMBOL(xItExtVpdPanel); + +#define maxPhysicalProcessors 32 + +struct IoHriProcessorVpd xIoHriProcessorVpd[maxPhysicalProcessors] = { + { + .xInstCacheOperandSize = 32, + .xDataCacheOperandSize = 32, + .xProcFreq = 50000000, + .xTimeBaseFreq = 50000000, + .xPVR = 0x3600 + } +}; + +/* Space for Main Store Vpd 27,200 bytes */ +/* May be filled in by the hypervisor so cannot end up in the BSS */ +u64 xMsVpd[3400] __attribute__((__section__(".data"))); + +/* Space for Recovery Log Buffer */ +/* May be filled in by the hypervisor so cannot end up in the BSS */ +u64 xRecoveryLogBuffer[32] __attribute__((__section__(".data"))); + +struct SpCommArea xSpCommArea = { + .xDesc = 0xE2D7C3C2, + .xFormat = 1, +}; + +/* The LparMap data is now located at offset 0x6000 in head.S + * It was put there so that the HvReleaseData could address it + * with a 32-bit offset as required by the iSeries hypervisor + * + * The Naca has a pointer to the ItVpdAreas. The hypervisor finds + * the Naca via the HvReleaseData area. The HvReleaseData has the + * offset into the Naca of the pointer to the ItVpdAreas. + */ +struct ItVpdAreas itVpdAreas = { + .xSlicDesc = 0xc9a3e5c1, /* "ItVA" */ + .xSlicSize = sizeof(struct ItVpdAreas), + .xSlicVpdEntries = ItVpdMaxEntries, /* # VPD array entries */ + .xSlicDmaEntries = ItDmaMaxEntries, /* # DMA array entries */ + .xSlicMaxLogicalProcs = NR_CPUS * 2, /* Max logical procs */ + .xSlicMaxPhysicalProcs = maxPhysicalProcessors, /* Max physical procs */ + .xSlicDmaToksOffset = offsetof(struct ItVpdAreas, xPlicDmaToks), + .xSlicVpdAdrsOffset = offsetof(struct ItVpdAreas, xSlicVpdAdrs), + .xSlicDmaLensOffset = offsetof(struct ItVpdAreas, xPlicDmaLens), + .xSlicVpdLensOffset = offsetof(struct ItVpdAreas, xSlicVpdLens), + .xSlicMaxSlotLabels = 0, /* max slot labels */ + .xSlicMaxLpQueues = 1, /* max LP queues */ + .xPlicDmaLens = { 0 }, /* DMA lengths */ + .xPlicDmaToks = { 0 }, /* DMA tokens */ + .xSlicVpdLens = { /* VPD lengths */ + 0,0,0, /* 0 - 2 */ + sizeof(xItExtVpdPanel), /* 3 Extended VPD */ + sizeof(struct paca_struct), /* 4 length of Paca */ + 0, /* 5 */ + sizeof(struct ItIplParmsReal),/* 6 length of IPL parms */ + 26992, /* 7 length of MS VPD */ + 0, /* 8 */ + sizeof(struct ItLpNaca),/* 9 length of LP Naca */ + 0, /* 10 */ + 256, /* 11 length of Recovery Log Buf */ + sizeof(struct SpCommArea), /* 12 length of SP Comm Area */ + 0,0,0, /* 13 - 15 */ + sizeof(struct IoHriProcessorVpd),/* 16 length of Proc Vpd */ + 0,0,0,0,0,0, /* 17 - 22 */ + sizeof(struct hvlpevent_queue), /* 23 length of Lp Queue */ + 0,0 /* 24 - 25 */ + }, + .xSlicVpdAdrs = { /* VPD addresses */ + 0,0,0, /* 0 - 2 */ + &xItExtVpdPanel, /* 3 Extended VPD */ + &paca[0], /* 4 first Paca */ + 0, /* 5 */ + &xItIplParmsReal, /* 6 IPL parms */ + &xMsVpd, /* 7 MS Vpd */ + 0, /* 8 */ + &itLpNaca, /* 9 LpNaca */ + 0, /* 10 */ + &xRecoveryLogBuffer, /* 11 Recovery Log Buffer */ + &xSpCommArea, /* 12 SP Comm Area */ + 0,0,0, /* 13 - 15 */ + &xIoHriProcessorVpd, /* 16 Proc Vpd */ + 0,0,0,0,0,0, /* 17 - 22 */ + &hvlpevent_queue, /* 23 Lp Queue */ + 0,0 + } +}; diff --git a/arch/ppc64/kernel/LparData.c b/arch/ppc64/kernel/LparData.c deleted file mode 100644 --- a/arch/ppc64/kernel/LparData.c +++ /dev/null @@ -1,227 +0,0 @@ -/* - * Copyright 2001 Mike Corrigan, 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 -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - - -/* The HvReleaseData is the root of the information shared between - * the hypervisor and Linux. - */ -struct HvReleaseData hvReleaseData = { - .xDesc = 0xc8a5d9c4, /* "HvRD" ebcdic */ - .xSize = sizeof(struct HvReleaseData), - .xVpdAreasPtrOffset = offsetof(struct naca_struct, xItVpdAreas), - .xSlicNacaAddr = &naca, /* 64-bit Naca address */ - .xMsNucDataOffset = LPARMAP_PHYS, - .xFlags = HVREL_TAGSINACTIVE /* tags inactive */ - /* 64 bit */ - /* shared processors */ - /* HMT allowed */ - | 6, /* TEMP: This allows non-GA driver */ - .xVrmIndex = 4, /* We are v5r2m0 */ - .xMinSupportedPlicVrmIndex = 3, /* v5r1m0 */ - .xMinCompatablePlicVrmIndex = 3, /* v5r1m0 */ - .xVrmName = { 0xd3, 0x89, 0x95, 0xa4, /* "Linux 2.4.64" ebcdic */ - 0xa7, 0x40, 0xf2, 0x4b, - 0xf4, 0x4b, 0xf6, 0xf4 }, -}; - -/* - * The NACA. The first dword of the naca is required by the iSeries - * hypervisor to point to itVpdAreas. The hypervisor finds the NACA - * through the pointer in hvReleaseData. - */ -struct naca_struct naca = { - .xItVpdAreas = &itVpdAreas, - .xRamDisk = 0, - .xRamDiskSize = 0, -}; - -extern void system_reset_iSeries(void); -extern void machine_check_iSeries(void); -extern void data_access_iSeries(void); -extern void instruction_access_iSeries(void); -extern void hardware_interrupt_iSeries(void); -extern void alignment_iSeries(void); -extern void program_check_iSeries(void); -extern void fp_unavailable_iSeries(void); -extern void decrementer_iSeries(void); -extern void trap_0a_iSeries(void); -extern void trap_0b_iSeries(void); -extern void system_call_iSeries(void); -extern void single_step_iSeries(void); -extern void trap_0e_iSeries(void); -extern void performance_monitor_iSeries(void); -extern void data_access_slb_iSeries(void); -extern void instruction_access_slb_iSeries(void); - -struct ItLpNaca itLpNaca = { - .xDesc = 0xd397d581, /* "LpNa" ebcdic */ - .xSize = 0x0400, /* size of ItLpNaca */ - .xIntHdlrOffset = 0x0300, /* offset to int array */ - .xMaxIntHdlrEntries = 19, /* # ents */ - .xPrimaryLpIndex = 0, /* Part # of primary */ - .xServiceLpIndex = 0, /* Part # of serv */ - .xLpIndex = 0, /* Part # of me */ - .xMaxLpQueues = 0, /* # of LP queues */ - .xLpQueueOffset = 0x100, /* offset of start of LP queues */ - .xPirEnvironMode = 0, /* Piranha stuff */ - .xPirConsoleMode = 0, - .xPirDasdMode = 0, - .xLparInstalled = 0, - .xSysPartitioned = 0, - .xHwSyncedTBs = 0, - .xIntProcUtilHmt = 0, - .xSpVpdFormat = 0, - .xIntProcRatio = 0, - .xPlicVrmIndex = 0, /* VRM index of PLIC */ - .xMinSupportedSlicVrmInd = 0, /* min supported SLIC */ - .xMinCompatableSlicVrmInd = 0, /* min compat SLIC */ - .xLoadAreaAddr = 0, /* 64-bit addr of load area */ - .xLoadAreaChunks = 0, /* chunks for load area */ - .xPaseSysCallCRMask = 0, /* PASE mask */ - .xSlicSegmentTablePtr = 0, /* seg table */ - .xOldLpQueue = { 0 }, /* Old LP Queue */ - .xInterruptHdlr = { - (u64)system_reset_iSeries, /* 0x100 System Reset */ - (u64)machine_check_iSeries, /* 0x200 Machine Check */ - (u64)data_access_iSeries, /* 0x300 Data Access */ - (u64)instruction_access_iSeries, /* 0x400 Instruction Access */ - (u64)hardware_interrupt_iSeries, /* 0x500 External */ - (u64)alignment_iSeries, /* 0x600 Alignment */ - (u64)program_check_iSeries, /* 0x700 Program Check */ - (u64)fp_unavailable_iSeries, /* 0x800 FP Unavailable */ - (u64)decrementer_iSeries, /* 0x900 Decrementer */ - (u64)trap_0a_iSeries, /* 0xa00 Trap 0A */ - (u64)trap_0b_iSeries, /* 0xb00 Trap 0B */ - (u64)system_call_iSeries, /* 0xc00 System Call */ - (u64)single_step_iSeries, /* 0xd00 Single Step */ - (u64)trap_0e_iSeries, /* 0xe00 Trap 0E */ - (u64)performance_monitor_iSeries,/* 0xf00 Performance Monitor */ - 0, /* int 0x1000 */ - 0, /* int 0x1010 */ - 0, /* int 0x1020 CPU ctls */ - (u64)hardware_interrupt_iSeries, /* SC Ret Hdlr */ - (u64)data_access_slb_iSeries, /* 0x380 D-SLB */ - (u64)instruction_access_slb_iSeries /* 0x480 I-SLB */ - } -}; -EXPORT_SYMBOL(itLpNaca); - -/* May be filled in by the hypervisor so cannot end up in the BSS */ -struct ItIplParmsReal xItIplParmsReal __attribute__((__section__(".data"))); - -/* May be filled in by the hypervisor so cannot end up in the BSS */ -struct ItExtVpdPanel xItExtVpdPanel __attribute__((__section__(".data"))); -EXPORT_SYMBOL(xItExtVpdPanel); - -#define maxPhysicalProcessors 32 - -struct IoHriProcessorVpd xIoHriProcessorVpd[maxPhysicalProcessors] = { - { - .xInstCacheOperandSize = 32, - .xDataCacheOperandSize = 32, - .xProcFreq = 50000000, - .xTimeBaseFreq = 50000000, - .xPVR = 0x3600 - } -}; - -/* Space for Main Store Vpd 27,200 bytes */ -/* May be filled in by the hypervisor so cannot end up in the BSS */ -u64 xMsVpd[3400] __attribute__((__section__(".data"))); - -/* Space for Recovery Log Buffer */ -/* May be filled in by the hypervisor so cannot end up in the BSS */ -u64 xRecoveryLogBuffer[32] __attribute__((__section__(".data"))); - -struct SpCommArea xSpCommArea = { - .xDesc = 0xE2D7C3C2, - .xFormat = 1, -}; - -/* The LparMap data is now located at offset 0x6000 in head.S - * It was put there so that the HvReleaseData could address it - * with a 32-bit offset as required by the iSeries hypervisor - * - * The Naca has a pointer to the ItVpdAreas. The hypervisor finds - * the Naca via the HvReleaseData area. The HvReleaseData has the - * offset into the Naca of the pointer to the ItVpdAreas. - */ -struct ItVpdAreas itVpdAreas = { - .xSlicDesc = 0xc9a3e5c1, /* "ItVA" */ - .xSlicSize = sizeof(struct ItVpdAreas), - .xSlicVpdEntries = ItVpdMaxEntries, /* # VPD array entries */ - .xSlicDmaEntries = ItDmaMaxEntries, /* # DMA array entries */ - .xSlicMaxLogicalProcs = NR_CPUS * 2, /* Max logical procs */ - .xSlicMaxPhysicalProcs = maxPhysicalProcessors, /* Max physical procs */ - .xSlicDmaToksOffset = offsetof(struct ItVpdAreas, xPlicDmaToks), - .xSlicVpdAdrsOffset = offsetof(struct ItVpdAreas, xSlicVpdAdrs), - .xSlicDmaLensOffset = offsetof(struct ItVpdAreas, xPlicDmaLens), - .xSlicVpdLensOffset = offsetof(struct ItVpdAreas, xSlicVpdLens), - .xSlicMaxSlotLabels = 0, /* max slot labels */ - .xSlicMaxLpQueues = 1, /* max LP queues */ - .xPlicDmaLens = { 0 }, /* DMA lengths */ - .xPlicDmaToks = { 0 }, /* DMA tokens */ - .xSlicVpdLens = { /* VPD lengths */ - 0,0,0, /* 0 - 2 */ - sizeof(xItExtVpdPanel), /* 3 Extended VPD */ - sizeof(struct paca_struct), /* 4 length of Paca */ - 0, /* 5 */ - sizeof(struct ItIplParmsReal),/* 6 length of IPL parms */ - 26992, /* 7 length of MS VPD */ - 0, /* 8 */ - sizeof(struct ItLpNaca),/* 9 length of LP Naca */ - 0, /* 10 */ - 256, /* 11 length of Recovery Log Buf */ - sizeof(struct SpCommArea), /* 12 length of SP Comm Area */ - 0,0,0, /* 13 - 15 */ - sizeof(struct IoHriProcessorVpd),/* 16 length of Proc Vpd */ - 0,0,0,0,0,0, /* 17 - 22 */ - sizeof(struct hvlpevent_queue), /* 23 length of Lp Queue */ - 0,0 /* 24 - 25 */ - }, - .xSlicVpdAdrs = { /* VPD addresses */ - 0,0,0, /* 0 - 2 */ - &xItExtVpdPanel, /* 3 Extended VPD */ - &paca[0], /* 4 first Paca */ - 0, /* 5 */ - &xItIplParmsReal, /* 6 IPL parms */ - &xMsVpd, /* 7 MS Vpd */ - 0, /* 8 */ - &itLpNaca, /* 9 LpNaca */ - 0, /* 10 */ - &xRecoveryLogBuffer, /* 11 Recovery Log Buffer */ - &xSpCommArea, /* 12 SP Comm Area */ - 0,0,0, /* 13 - 15 */ - &xIoHriProcessorVpd, /* 16 Proc Vpd */ - 0,0,0,0,0,0, /* 17 - 22 */ - &hvlpevent_queue, /* 23 Lp Queue */ - 0,0 - } -}; diff --git a/arch/ppc64/kernel/Makefile b/arch/ppc64/kernel/Makefile --- a/arch/ppc64/kernel/Makefile +++ b/arch/ppc64/kernel/Makefile @@ -22,8 +22,7 @@ pci-obj-$(CONFIG_PPC_MULTIPLATFORM) += p obj-$(CONFIG_PCI) += pci.o pci_iommu.o iomap.o $(pci-obj-y) -obj-$(CONFIG_PPC_ISERIES) += LparData.o \ - iSeries_setup.o ItLpQueue.o hvCall.o \ +obj-$(CONFIG_PPC_ISERIES) += iSeries_setup.o ItLpQueue.o hvCall.o \ mf.o HvLpEvent.o iSeries_proc.o iSeries_htab.o \ iSeries_iommu.o diff --git a/arch/ppc64/kernel/head.S b/arch/ppc64/kernel/head.S --- a/arch/ppc64/kernel/head.S +++ b/arch/ppc64/kernel/head.S @@ -1253,7 +1253,7 @@ unrecov_slb: * * On iSeries, the hypervisor must fill in at least one entry before * we get control (with relocate on). The address is give to the hv - * as a page number (see xLparMap in LparData.c), so this must be at a + * as a page number (see xLparMap in lpardata.c), so this must be at a * fixed address (the linker can't compute (u64)&initial_stab >> * PAGE_SHIFT). */ From sfr at canb.auug.org.au Wed Sep 28 16:46:46 2005 From: sfr at canb.auug.org.au (Stephen Rothwell) Date: Wed, 28 Sep 2005 16:46:46 +1000 Subject: [PATCH 4/19] powerpc: move iSeries_setup.[ch] and mf.c into platforms/iseries In-Reply-To: <20050928163333.02799419.sfr@canb.auug.org.au> References: <20050928163333.02799419.sfr@canb.auug.org.au> Message-ID: <20050928164646.3eca808b.sfr@canb.auug.org.au> iSeries_setup.c becomes setup.c iSeries_setup.h becomes setup.h mf.c retains its name Also moved iSeries_[gs]et_rtc_time and iSeries_get_boot_time into mf.c since they are just small wrappers around mf_ functions. Signed-off-by: Stephen Rothwell --- arch/powerpc/platforms/iseries/Makefile | 2 arch/powerpc/platforms/iseries/mf.c | 1316 +++++++++++++++++++++++++++++++ arch/powerpc/platforms/iseries/setup.c | 1006 ++++++++++++++++++++++++ arch/powerpc/platforms/iseries/setup.h | 24 + arch/ppc64/kernel/Makefile | 4 arch/ppc64/kernel/iSeries_setup.c | 1007 ------------------------ arch/ppc64/kernel/iSeries_setup.h | 26 - arch/ppc64/kernel/mf.c | 1281 ------------------------------ arch/ppc64/kernel/rtc.c | 37 - 9 files changed, 2349 insertions(+), 2354 deletions(-) create mode 100644 arch/powerpc/platforms/iseries/mf.c create mode 100644 arch/powerpc/platforms/iseries/setup.c create mode 100644 arch/powerpc/platforms/iseries/setup.h delete mode 100644 arch/ppc64/kernel/iSeries_setup.c delete mode 100644 arch/ppc64/kernel/iSeries_setup.h delete mode 100644 arch/ppc64/kernel/mf.c This patch is too large for the mailing list but is available from http://ozlabs.org/~sfr/0004-powerpc-move-iSeries_setup.-ch-and-mf.c-into-platforms-iseries.txt -- Cheers, Stephen Rothwell sfr at canb.auug.org.au http://www.canb.auug.org.au/~sfr/ From sfr at canb.auug.org.au Wed Sep 28 16:48:19 2005 From: sfr at canb.auug.org.au (Stephen Rothwell) Date: Wed, 28 Sep 2005 16:48:19 +1000 Subject: [PATCH 5/19] powerpc: move ItLpQueue.c to powerpc/platforms/iseries In-Reply-To: <20050928163333.02799419.sfr@canb.auug.org.au> References: <20050928163333.02799419.sfr@canb.auug.org.au> Message-ID: <20050928164819.6a3d5a4d.sfr@canb.auug.org.au> And rename it to lpevents.c. Signed-off-by: Stephen Rothwell --- arch/powerpc/platforms/iseries/Makefile | 2 arch/powerpc/platforms/iseries/lpevents.c | 261 +++++++++++++++++++++++++++++ arch/ppc64/kernel/ItLpQueue.c | 262 ----------------------------- arch/ppc64/kernel/Makefile | 2 4 files changed, 263 insertions(+), 264 deletions(-) create mode 100644 arch/powerpc/platforms/iseries/lpevents.c delete mode 100644 arch/ppc64/kernel/ItLpQueue.c -- Cheers, Stephen Rothwell sfr at canb.auug.org.au http://www.canb.auug.org.au/~sfr/ 2952bc7c896ec76a20e18321e2be40a694a73a78 diff --git a/arch/powerpc/platforms/iseries/Makefile b/arch/powerpc/platforms/iseries/Makefile --- a/arch/powerpc/platforms/iseries/Makefile +++ b/arch/powerpc/platforms/iseries/Makefile @@ -1 +1 @@ -obj-y += hvcall.o hvlpconfig.o lpardata.o setup.o mf.o +obj-y += hvcall.o hvlpconfig.o lpardata.o setup.o mf.o lpevents.o diff --git a/arch/powerpc/platforms/iseries/lpevents.c b/arch/powerpc/platforms/iseries/lpevents.c new file mode 100644 --- /dev/null +++ b/arch/powerpc/platforms/iseries/lpevents.c @@ -0,0 +1,261 @@ +/* + * Copyright (C) 2001 Mike Corrigan 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. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * The LpQueue is used to pass event data from the hypervisor to + * the partition. This is where I/O interrupt events are communicated. + * + * It is written to by the hypervisor so cannot end up in the BSS. + */ +struct hvlpevent_queue hvlpevent_queue __attribute__((__section__(".data"))); + +DEFINE_PER_CPU(unsigned long[HvLpEvent_Type_NumTypes], hvlpevent_counts); + +static char *event_types[HvLpEvent_Type_NumTypes] = { + "Hypervisor", + "Machine Facilities", + "Session Manager", + "SPD I/O", + "Virtual Bus", + "PCI I/O", + "RIO I/O", + "Virtual Lan", + "Virtual I/O" +}; + +/* Array of LpEvent handler functions */ +extern LpEventHandler lpEventHandler[HvLpEvent_Type_NumTypes]; + +static struct HvLpEvent * get_next_hvlpevent(void) +{ + struct HvLpEvent * event; + event = (struct HvLpEvent *)hvlpevent_queue.xSlicCurEventPtr; + + if (event->xFlags.xValid) { + /* rmb() needed only for weakly consistent machines (regatta) */ + rmb(); + /* Set pointer to next potential event */ + hvlpevent_queue.xSlicCurEventPtr += ((event->xSizeMinus1 + + LpEventAlign) / LpEventAlign) * LpEventAlign; + + /* Wrap to beginning if no room at end */ + if (hvlpevent_queue.xSlicCurEventPtr > + hvlpevent_queue.xSlicLastValidEventPtr) { + hvlpevent_queue.xSlicCurEventPtr = + hvlpevent_queue.xSlicEventStackPtr; + } + } else { + event = NULL; + } + + return event; +} + +static unsigned long spread_lpevents = NR_CPUS; + +int hvlpevent_is_pending(void) +{ + struct HvLpEvent *next_event; + + if (smp_processor_id() >= spread_lpevents) + return 0; + + next_event = (struct HvLpEvent *)hvlpevent_queue.xSlicCurEventPtr; + + return next_event->xFlags.xValid | + hvlpevent_queue.xPlicOverflowIntPending; +} + +static void hvlpevent_clear_valid(struct HvLpEvent * event) +{ + /* Tell the Hypervisor that we're done with this event. + * Also clear bits within this event that might look like valid bits. + * ie. on 64-byte boundaries. + */ + struct HvLpEvent *tmp; + unsigned extra = ((event->xSizeMinus1 + LpEventAlign) / + LpEventAlign) - 1; + + switch (extra) { + case 3: + tmp = (struct HvLpEvent*)((char*)event + 3 * LpEventAlign); + tmp->xFlags.xValid = 0; + case 2: + tmp = (struct HvLpEvent*)((char*)event + 2 * LpEventAlign); + tmp->xFlags.xValid = 0; + case 1: + tmp = (struct HvLpEvent*)((char*)event + 1 * LpEventAlign); + tmp->xFlags.xValid = 0; + } + + mb(); + + event->xFlags.xValid = 0; +} + +void process_hvlpevents(struct pt_regs *regs) +{ + struct HvLpEvent * event; + + /* If we have recursed, just return */ + if (!spin_trylock(&hvlpevent_queue.lock)) + return; + + for (;;) { + event = get_next_hvlpevent(); + if (event) { + /* Call appropriate handler here, passing + * a pointer to the LpEvent. The handler + * must make a copy of the LpEvent if it + * needs it in a bottom half. (perhaps for + * an ACK) + * + * Handlers are responsible for ACK processing + * + * The Hypervisor guarantees that LpEvents will + * only be delivered with types that we have + * registered for, so no type check is necessary + * here! + */ + if (event->xType < HvLpEvent_Type_NumTypes) + __get_cpu_var(hvlpevent_counts)[event->xType]++; + if (event->xType < HvLpEvent_Type_NumTypes && + lpEventHandler[event->xType]) + lpEventHandler[event->xType](event, regs); + else + printk(KERN_INFO "Unexpected Lp Event type=%d\n", event->xType ); + + hvlpevent_clear_valid(event); + } else if (hvlpevent_queue.xPlicOverflowIntPending) + /* + * No more valid events. If overflow events are + * pending process them + */ + HvCallEvent_getOverflowLpEvents(hvlpevent_queue.xIndex); + else + break; + } + + spin_unlock(&hvlpevent_queue.lock); +} + +static int set_spread_lpevents(char *str) +{ + unsigned long val = simple_strtoul(str, NULL, 0); + + /* + * The parameter is the number of processors to share in processing + * lp events. + */ + if (( val > 0) && (val <= NR_CPUS)) { + spread_lpevents = val; + printk("lpevent processing spread over %ld processors\n", val); + } else { + printk("invalid spread_lpevents %ld\n", val); + } + + return 1; +} +__setup("spread_lpevents=", set_spread_lpevents); + +void setup_hvlpevent_queue(void) +{ + void *eventStack; + + /* + * Allocate a page for the Event Stack. The Hypervisor needs the + * absolute real address, so we subtract out the KERNELBASE and add + * in the absolute real address of the kernel load area. + */ + eventStack = alloc_bootmem_pages(LpEventStackSize); + memset(eventStack, 0, LpEventStackSize); + + /* Invoke the hypervisor to initialize the event stack */ + HvCallEvent_setLpEventStack(0, eventStack, LpEventStackSize); + + hvlpevent_queue.xSlicEventStackPtr = (char *)eventStack; + hvlpevent_queue.xSlicCurEventPtr = (char *)eventStack; + hvlpevent_queue.xSlicLastValidEventPtr = (char *)eventStack + + (LpEventStackSize - LpEventMaxSize); + hvlpevent_queue.xIndex = 0; +} + +static int proc_lpevents_show(struct seq_file *m, void *v) +{ + int cpu, i; + unsigned long sum; + static unsigned long cpu_totals[NR_CPUS]; + + /* FIXME: do we care that there's no locking here? */ + sum = 0; + for_each_online_cpu(cpu) { + cpu_totals[cpu] = 0; + for (i = 0; i < HvLpEvent_Type_NumTypes; i++) { + cpu_totals[cpu] += per_cpu(hvlpevent_counts, cpu)[i]; + } + sum += cpu_totals[cpu]; + } + + seq_printf(m, "LpEventQueue 0\n"); + seq_printf(m, " events processed:\t%lu\n", sum); + + for (i = 0; i < HvLpEvent_Type_NumTypes; ++i) { + sum = 0; + for_each_online_cpu(cpu) { + sum += per_cpu(hvlpevent_counts, cpu)[i]; + } + + seq_printf(m, " %-20s %10lu\n", event_types[i], sum); + } + + seq_printf(m, "\n events processed by processor:\n"); + + for_each_online_cpu(cpu) { + seq_printf(m, " CPU%02d %10lu\n", cpu, cpu_totals[cpu]); + } + + return 0; +} + +static int proc_lpevents_open(struct inode *inode, struct file *file) +{ + return single_open(file, proc_lpevents_show, NULL); +} + +static struct file_operations proc_lpevents_operations = { + .open = proc_lpevents_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + +static int __init proc_lpevents_init(void) +{ + struct proc_dir_entry *e; + + e = create_proc_entry("iSeries/lpevents", S_IFREG|S_IRUGO, NULL); + if (e) + e->proc_fops = &proc_lpevents_operations; + + return 0; +} +__initcall(proc_lpevents_init); + diff --git a/arch/ppc64/kernel/ItLpQueue.c b/arch/ppc64/kernel/ItLpQueue.c deleted file mode 100644 --- a/arch/ppc64/kernel/ItLpQueue.c +++ /dev/null @@ -1,262 +0,0 @@ -/* - * ItLpQueue.c - * Copyright (C) 2001 Mike Corrigan 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. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/* - * The LpQueue is used to pass event data from the hypervisor to - * the partition. This is where I/O interrupt events are communicated. - * - * It is written to by the hypervisor so cannot end up in the BSS. - */ -struct hvlpevent_queue hvlpevent_queue __attribute__((__section__(".data"))); - -DEFINE_PER_CPU(unsigned long[HvLpEvent_Type_NumTypes], hvlpevent_counts); - -static char *event_types[HvLpEvent_Type_NumTypes] = { - "Hypervisor", - "Machine Facilities", - "Session Manager", - "SPD I/O", - "Virtual Bus", - "PCI I/O", - "RIO I/O", - "Virtual Lan", - "Virtual I/O" -}; - -/* Array of LpEvent handler functions */ -extern LpEventHandler lpEventHandler[HvLpEvent_Type_NumTypes]; - -static struct HvLpEvent * get_next_hvlpevent(void) -{ - struct HvLpEvent * event; - event = (struct HvLpEvent *)hvlpevent_queue.xSlicCurEventPtr; - - if (event->xFlags.xValid) { - /* rmb() needed only for weakly consistent machines (regatta) */ - rmb(); - /* Set pointer to next potential event */ - hvlpevent_queue.xSlicCurEventPtr += ((event->xSizeMinus1 + - LpEventAlign) / LpEventAlign) * LpEventAlign; - - /* Wrap to beginning if no room at end */ - if (hvlpevent_queue.xSlicCurEventPtr > - hvlpevent_queue.xSlicLastValidEventPtr) { - hvlpevent_queue.xSlicCurEventPtr = - hvlpevent_queue.xSlicEventStackPtr; - } - } else { - event = NULL; - } - - return event; -} - -static unsigned long spread_lpevents = NR_CPUS; - -int hvlpevent_is_pending(void) -{ - struct HvLpEvent *next_event; - - if (smp_processor_id() >= spread_lpevents) - return 0; - - next_event = (struct HvLpEvent *)hvlpevent_queue.xSlicCurEventPtr; - - return next_event->xFlags.xValid | - hvlpevent_queue.xPlicOverflowIntPending; -} - -static void hvlpevent_clear_valid(struct HvLpEvent * event) -{ - /* Tell the Hypervisor that we're done with this event. - * Also clear bits within this event that might look like valid bits. - * ie. on 64-byte boundaries. - */ - struct HvLpEvent *tmp; - unsigned extra = ((event->xSizeMinus1 + LpEventAlign) / - LpEventAlign) - 1; - - switch (extra) { - case 3: - tmp = (struct HvLpEvent*)((char*)event + 3 * LpEventAlign); - tmp->xFlags.xValid = 0; - case 2: - tmp = (struct HvLpEvent*)((char*)event + 2 * LpEventAlign); - tmp->xFlags.xValid = 0; - case 1: - tmp = (struct HvLpEvent*)((char*)event + 1 * LpEventAlign); - tmp->xFlags.xValid = 0; - } - - mb(); - - event->xFlags.xValid = 0; -} - -void process_hvlpevents(struct pt_regs *regs) -{ - struct HvLpEvent * event; - - /* If we have recursed, just return */ - if (!spin_trylock(&hvlpevent_queue.lock)) - return; - - for (;;) { - event = get_next_hvlpevent(); - if (event) { - /* Call appropriate handler here, passing - * a pointer to the LpEvent. The handler - * must make a copy of the LpEvent if it - * needs it in a bottom half. (perhaps for - * an ACK) - * - * Handlers are responsible for ACK processing - * - * The Hypervisor guarantees that LpEvents will - * only be delivered with types that we have - * registered for, so no type check is necessary - * here! - */ - if (event->xType < HvLpEvent_Type_NumTypes) - __get_cpu_var(hvlpevent_counts)[event->xType]++; - if (event->xType < HvLpEvent_Type_NumTypes && - lpEventHandler[event->xType]) - lpEventHandler[event->xType](event, regs); - else - printk(KERN_INFO "Unexpected Lp Event type=%d\n", event->xType ); - - hvlpevent_clear_valid(event); - } else if (hvlpevent_queue.xPlicOverflowIntPending) - /* - * No more valid events. If overflow events are - * pending process them - */ - HvCallEvent_getOverflowLpEvents(hvlpevent_queue.xIndex); - else - break; - } - - spin_unlock(&hvlpevent_queue.lock); -} - -static int set_spread_lpevents(char *str) -{ - unsigned long val = simple_strtoul(str, NULL, 0); - - /* - * The parameter is the number of processors to share in processing - * lp events. - */ - if (( val > 0) && (val <= NR_CPUS)) { - spread_lpevents = val; - printk("lpevent processing spread over %ld processors\n", val); - } else { - printk("invalid spread_lpevents %ld\n", val); - } - - return 1; -} -__setup("spread_lpevents=", set_spread_lpevents); - -void setup_hvlpevent_queue(void) -{ - void *eventStack; - - /* - * Allocate a page for the Event Stack. The Hypervisor needs the - * absolute real address, so we subtract out the KERNELBASE and add - * in the absolute real address of the kernel load area. - */ - eventStack = alloc_bootmem_pages(LpEventStackSize); - memset(eventStack, 0, LpEventStackSize); - - /* Invoke the hypervisor to initialize the event stack */ - HvCallEvent_setLpEventStack(0, eventStack, LpEventStackSize); - - hvlpevent_queue.xSlicEventStackPtr = (char *)eventStack; - hvlpevent_queue.xSlicCurEventPtr = (char *)eventStack; - hvlpevent_queue.xSlicLastValidEventPtr = (char *)eventStack + - (LpEventStackSize - LpEventMaxSize); - hvlpevent_queue.xIndex = 0; -} - -static int proc_lpevents_show(struct seq_file *m, void *v) -{ - int cpu, i; - unsigned long sum; - static unsigned long cpu_totals[NR_CPUS]; - - /* FIXME: do we care that there's no locking here? */ - sum = 0; - for_each_online_cpu(cpu) { - cpu_totals[cpu] = 0; - for (i = 0; i < HvLpEvent_Type_NumTypes; i++) { - cpu_totals[cpu] += per_cpu(hvlpevent_counts, cpu)[i]; - } - sum += cpu_totals[cpu]; - } - - seq_printf(m, "LpEventQueue 0\n"); - seq_printf(m, " events processed:\t%lu\n", sum); - - for (i = 0; i < HvLpEvent_Type_NumTypes; ++i) { - sum = 0; - for_each_online_cpu(cpu) { - sum += per_cpu(hvlpevent_counts, cpu)[i]; - } - - seq_printf(m, " %-20s %10lu\n", event_types[i], sum); - } - - seq_printf(m, "\n events processed by processor:\n"); - - for_each_online_cpu(cpu) { - seq_printf(m, " CPU%02d %10lu\n", cpu, cpu_totals[cpu]); - } - - return 0; -} - -static int proc_lpevents_open(struct inode *inode, struct file *file) -{ - return single_open(file, proc_lpevents_show, NULL); -} - -static struct file_operations proc_lpevents_operations = { - .open = proc_lpevents_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, -}; - -static int __init proc_lpevents_init(void) -{ - struct proc_dir_entry *e; - - e = create_proc_entry("iSeries/lpevents", S_IFREG|S_IRUGO, NULL); - if (e) - e->proc_fops = &proc_lpevents_operations; - - return 0; -} -__initcall(proc_lpevents_init); - diff --git a/arch/ppc64/kernel/Makefile b/arch/ppc64/kernel/Makefile --- a/arch/ppc64/kernel/Makefile +++ b/arch/ppc64/kernel/Makefile @@ -22,7 +22,7 @@ pci-obj-$(CONFIG_PPC_MULTIPLATFORM) += p obj-$(CONFIG_PCI) += pci.o pci_iommu.o iomap.o $(pci-obj-y) -obj-$(CONFIG_PPC_ISERIES) += ItLpQueue.o hvCall.o \ +obj-$(CONFIG_PPC_ISERIES) += hvCall.o \ HvLpEvent.o iSeries_proc.o iSeries_htab.o \ iSeries_iommu.o From sfr at canb.auug.org.au Wed Sep 28 16:49:52 2005 From: sfr at canb.auug.org.au (Stephen Rothwell) Date: Wed, 28 Sep 2005 16:49:52 +1000 Subject: [PATCH 6/19] powerpc: move hvCall.S to powerpc/platforms/iseries In-Reply-To: <20050928163333.02799419.sfr@canb.auug.org.au> References: <20050928163333.02799419.sfr@canb.auug.org.au> Message-ID: <20050928164952.4954c336.sfr@canb.auug.org.au> Rename it to hvcall.S and (so I can do that) rename hvcall.c to hvlog.c - a more appropriate name. Do some white space cleanups. Signed-off-by: Stephen Rothwell --- arch/powerpc/platforms/iseries/Makefile | 2 - arch/powerpc/platforms/iseries/hvcall.S | 93 +++++++++++++++++++++++++++++ arch/powerpc/platforms/iseries/hvcall.c | 35 ----------- arch/powerpc/platforms/iseries/hvlog.c | 35 +++++++++++ arch/ppc64/kernel/Makefile | 3 - arch/ppc64/kernel/hvCall.S | 98 ------------------------------- 6 files changed, 130 insertions(+), 136 deletions(-) create mode 100644 arch/powerpc/platforms/iseries/hvcall.S delete mode 100644 arch/powerpc/platforms/iseries/hvcall.c create mode 100644 arch/powerpc/platforms/iseries/hvlog.c delete mode 100644 arch/ppc64/kernel/hvCall.S -- Cheers, Stephen Rothwell sfr at canb.auug.org.au http://www.canb.auug.org.au/~sfr/ 99a2379cdddcc4e8579e70deb80479450ed65d49 diff --git a/arch/powerpc/platforms/iseries/Makefile b/arch/powerpc/platforms/iseries/Makefile --- a/arch/powerpc/platforms/iseries/Makefile +++ b/arch/powerpc/platforms/iseries/Makefile @@ -1 +1 @@ -obj-y += hvcall.o hvlpconfig.o lpardata.o setup.o mf.o lpevents.o +obj-y += hvlog.o hvlpconfig.o lpardata.o setup.o mf.o lpevents.o hvcall.o diff --git a/arch/powerpc/platforms/iseries/hvcall.S b/arch/powerpc/platforms/iseries/hvcall.S new file mode 100644 --- /dev/null +++ b/arch/powerpc/platforms/iseries/hvcall.S @@ -0,0 +1,93 @@ +/* + * This file contains the code to perform calls to the + * iSeries LPAR hypervisor + * + * 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 + + .text + +/* + * Hypervisor call + * + * Invoke the iSeries hypervisor via the System Call instruction + * Parameters are passed to this routine in registers r3 - r10 + * + * r3 contains the HV function to be called + * r4-r10 contain the operands to the hypervisor function + * + */ + +_GLOBAL(HvCall) +_GLOBAL(HvCall0) +_GLOBAL(HvCall1) +_GLOBAL(HvCall2) +_GLOBAL(HvCall3) +_GLOBAL(HvCall4) +_GLOBAL(HvCall5) +_GLOBAL(HvCall6) +_GLOBAL(HvCall7) + + + mfcr r0 + std r0,-8(r1) + stdu r1,-(STACK_FRAME_OVERHEAD+16)(r1) + + /* r0 = 0xffffffffffffffff indicates a hypervisor call */ + + li r0,-1 + + /* Invoke the hypervisor */ + + sc + + ld r1,0(r1) + ld r0,-8(r1) + mtcrf 0xff,r0 + + /* return to caller, return value in r3 */ + + blr + +_GLOBAL(HvCall0Ret16) +_GLOBAL(HvCall1Ret16) +_GLOBAL(HvCall2Ret16) +_GLOBAL(HvCall3Ret16) +_GLOBAL(HvCall4Ret16) +_GLOBAL(HvCall5Ret16) +_GLOBAL(HvCall6Ret16) +_GLOBAL(HvCall7Ret16) + + mfcr r0 + std r0,-8(r1) + std r31,-16(r1) + stdu r1,-(STACK_FRAME_OVERHEAD+32)(r1) + + mr r31,r4 + li r0,-1 + mr r4,r5 + mr r5,r6 + mr r6,r7 + mr r7,r8 + mr r8,r9 + mr r9,r10 + + sc + + std r3,0(r31) + std r4,8(r31) + + mr r3,r5 + + ld r1,0(r1) + ld r0,-8(r1) + mtcrf 0xff,r0 + ld r31,-16(r1) + + blr diff --git a/arch/powerpc/platforms/iseries/hvcall.c b/arch/powerpc/platforms/iseries/hvcall.c deleted file mode 100644 --- a/arch/powerpc/platforms/iseries/hvcall.c +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright (C) 2001 Mike Corrigan 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. - */ - -#include -#include -#include -#include -#include - - -void HvCall_writeLogBuffer(const void *buffer, u64 len) -{ - struct HvLpBufferList hv_buf; - u64 left_this_page; - u64 cur = virt_to_abs(buffer); - - while (len) { - hv_buf.addr = cur; - left_this_page = ((cur & PAGE_MASK) + PAGE_SIZE) - cur; - if (left_this_page > len) - left_this_page = len; - hv_buf.len = left_this_page; - len -= left_this_page; - HvCall2(HvCallBaseWriteLogBuffer, - virt_to_abs(&hv_buf), - left_this_page); - cur = (cur & PAGE_MASK) + PAGE_SIZE; - } -} diff --git a/arch/powerpc/platforms/iseries/hvlog.c b/arch/powerpc/platforms/iseries/hvlog.c new file mode 100644 --- /dev/null +++ b/arch/powerpc/platforms/iseries/hvlog.c @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2001 Mike Corrigan 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. + */ + +#include +#include +#include +#include +#include + + +void HvCall_writeLogBuffer(const void *buffer, u64 len) +{ + struct HvLpBufferList hv_buf; + u64 left_this_page; + u64 cur = virt_to_abs(buffer); + + while (len) { + hv_buf.addr = cur; + left_this_page = ((cur & PAGE_MASK) + PAGE_SIZE) - cur; + if (left_this_page > len) + left_this_page = len; + hv_buf.len = left_this_page; + len -= left_this_page; + HvCall2(HvCallBaseWriteLogBuffer, + virt_to_abs(&hv_buf), + left_this_page); + cur = (cur & PAGE_MASK) + PAGE_SIZE; + } +} diff --git a/arch/ppc64/kernel/Makefile b/arch/ppc64/kernel/Makefile --- a/arch/ppc64/kernel/Makefile +++ b/arch/ppc64/kernel/Makefile @@ -22,8 +22,7 @@ pci-obj-$(CONFIG_PPC_MULTIPLATFORM) += p obj-$(CONFIG_PCI) += pci.o pci_iommu.o iomap.o $(pci-obj-y) -obj-$(CONFIG_PPC_ISERIES) += hvCall.o \ - HvLpEvent.o iSeries_proc.o iSeries_htab.o \ +obj-$(CONFIG_PPC_ISERIES) += HvLpEvent.o iSeries_proc.o iSeries_htab.o \ iSeries_iommu.o obj-$(CONFIG_PPC_MULTIPLATFORM) += nvram.o i8259.o prom_init.o diff --git a/arch/ppc64/kernel/hvCall.S b/arch/ppc64/kernel/hvCall.S deleted file mode 100644 --- a/arch/ppc64/kernel/hvCall.S +++ /dev/null @@ -1,98 +0,0 @@ -/* - * arch/ppc64/kernel/hvCall.S - * - * - * This file contains the code to perform calls to the - * iSeries LPAR hypervisor - * - * 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 - - .text - -/* - * Hypervisor call - * - * Invoke the iSeries hypervisor via the System Call instruction - * Parameters are passed to this routine in registers r3 - r10 - * - * r3 contains the HV function to be called - * r4-r10 contain the operands to the hypervisor function - * - */ - -_GLOBAL(HvCall) -_GLOBAL(HvCall0) -_GLOBAL(HvCall1) -_GLOBAL(HvCall2) -_GLOBAL(HvCall3) -_GLOBAL(HvCall4) -_GLOBAL(HvCall5) -_GLOBAL(HvCall6) -_GLOBAL(HvCall7) - - - mfcr r0 - std r0,-8(r1) - stdu r1,-(STACK_FRAME_OVERHEAD+16)(r1) - - /* r0 = 0xffffffffffffffff indicates a hypervisor call */ - - li r0,-1 - - /* Invoke the hypervisor */ - - sc - - ld r1,0(r1) - ld r0,-8(r1) - mtcrf 0xff,r0 - - /* return to caller, return value in r3 */ - - blr - -_GLOBAL(HvCall0Ret16) -_GLOBAL(HvCall1Ret16) -_GLOBAL(HvCall2Ret16) -_GLOBAL(HvCall3Ret16) -_GLOBAL(HvCall4Ret16) -_GLOBAL(HvCall5Ret16) -_GLOBAL(HvCall6Ret16) -_GLOBAL(HvCall7Ret16) - - mfcr r0 - std r0,-8(r1) - std r31,-16(r1) - stdu r1,-(STACK_FRAME_OVERHEAD+32)(r1) - - mr r31,r4 - li r0,-1 - mr r4,r5 - mr r5,r6 - mr r6,r7 - mr r7,r8 - mr r8,r9 - mr r9,r10 - - sc - - std r3,0(r31) - std r4,8(r31) - - mr r3,r5 - - ld r1,0(r1) - ld r0,-8(r1) - mtcrf 0xff,r0 - ld r31,-16(r1) - - blr - - From sfr at canb.auug.org.au Wed Sep 28 16:51:05 2005 From: sfr at canb.auug.org.au (Stephen Rothwell) Date: Wed, 28 Sep 2005 16:51:05 +1000 Subject: [PATCH 7/19] powerpc: Merge HvLpEvent.c into lpevents.c In-Reply-To: <20050928163333.02799419.sfr@canb.auug.org.au> References: <20050928163333.02799419.sfr@canb.auug.org.au> Message-ID: <20050928165105.37aae52f.sfr@canb.auug.org.au> These two files were intimately connected, so just merge them. Signed-off-by: Stephen Rothwell --- arch/powerpc/platforms/iseries/lpevents.c | 68 ++++++++++++++++++++++ arch/ppc64/kernel/HvLpEvent.c | 88 ----------------------------- arch/ppc64/kernel/Makefile | 2 - 3 files changed, 68 insertions(+), 90 deletions(-) delete mode 100644 arch/ppc64/kernel/HvLpEvent.c -- Cheers, Stephen Rothwell sfr at canb.auug.org.au http://www.canb.auug.org.au/~sfr/ 544cbbaed4de962fb0e831e8799ab01c448ff37d diff --git a/arch/powerpc/platforms/iseries/lpevents.c b/arch/powerpc/platforms/iseries/lpevents.c --- a/arch/powerpc/platforms/iseries/lpevents.c +++ b/arch/powerpc/platforms/iseries/lpevents.c @@ -18,6 +18,7 @@ #include #include #include +#include /* * The LpQueue is used to pass event data from the hypervisor to @@ -42,7 +43,8 @@ static char *event_types[HvLpEvent_Type_ }; /* Array of LpEvent handler functions */ -extern LpEventHandler lpEventHandler[HvLpEvent_Type_NumTypes]; +static LpEventHandler lpEventHandler[HvLpEvent_Type_NumTypes]; +static unsigned lpEventHandlerPaths[HvLpEvent_Type_NumTypes]; static struct HvLpEvent * get_next_hvlpevent(void) { @@ -198,6 +200,70 @@ void setup_hvlpevent_queue(void) hvlpevent_queue.xIndex = 0; } +/* Register a handler for an LpEvent type */ +int HvLpEvent_registerHandler(HvLpEvent_Type eventType, LpEventHandler handler) +{ + if (eventType < HvLpEvent_Type_NumTypes) { + lpEventHandler[eventType] = handler; + return 0; + } + return 1; +} +EXPORT_SYMBOL(HvLpEvent_registerHandler); + +int HvLpEvent_unregisterHandler(HvLpEvent_Type eventType) +{ + might_sleep(); + + if (eventType < HvLpEvent_Type_NumTypes) { + if (!lpEventHandlerPaths[eventType]) { + lpEventHandler[eventType] = NULL; + /* + * We now sleep until all other CPUs have scheduled. + * This ensures that the deletion is seen by all + * other CPUs, and that the deleted handler isn't + * still running on another CPU when we return. + */ + synchronize_rcu(); + return 0; + } + } + return 1; +} +EXPORT_SYMBOL(HvLpEvent_unregisterHandler); + +/* + * lpIndex is the partition index of the target partition. + * needed only for VirtualIo, VirtualLan and SessionMgr. Zero + * indicates to use our partition index - for the other types. + */ +int HvLpEvent_openPath(HvLpEvent_Type eventType, HvLpIndex lpIndex) +{ + if ((eventType < HvLpEvent_Type_NumTypes) && + lpEventHandler[eventType]) { + if (lpIndex == 0) + lpIndex = itLpNaca.xLpIndex; + HvCallEvent_openLpEventPath(lpIndex, eventType); + ++lpEventHandlerPaths[eventType]; + return 0; + } + return 1; +} + +int HvLpEvent_closePath(HvLpEvent_Type eventType, HvLpIndex lpIndex) +{ + if ((eventType < HvLpEvent_Type_NumTypes) && + lpEventHandler[eventType] && + lpEventHandlerPaths[eventType]) { + if (lpIndex == 0) + lpIndex = itLpNaca.xLpIndex; + HvCallEvent_closeLpEventPath(lpIndex, eventType); + --lpEventHandlerPaths[eventType]; + return 0; + } + return 1; +} + static int proc_lpevents_show(struct seq_file *m, void *v) { int cpu, i; diff --git a/arch/ppc64/kernel/HvLpEvent.c b/arch/ppc64/kernel/HvLpEvent.c deleted file mode 100644 --- a/arch/ppc64/kernel/HvLpEvent.c +++ /dev/null @@ -1,88 +0,0 @@ -/* - * Copyright 2001 Mike Corrigan 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 - -/* Array of LpEvent handler functions */ -LpEventHandler lpEventHandler[HvLpEvent_Type_NumTypes]; -unsigned lpEventHandlerPaths[HvLpEvent_Type_NumTypes]; - -/* Register a handler for an LpEvent type */ - -int HvLpEvent_registerHandler( HvLpEvent_Type eventType, LpEventHandler handler ) -{ - int rc = 1; - if ( eventType < HvLpEvent_Type_NumTypes ) { - lpEventHandler[eventType] = handler; - rc = 0; - } - return rc; - -} - -int HvLpEvent_unregisterHandler( HvLpEvent_Type eventType ) -{ - int rc = 1; - - might_sleep(); - - if ( eventType < HvLpEvent_Type_NumTypes ) { - if ( !lpEventHandlerPaths[eventType] ) { - lpEventHandler[eventType] = NULL; - rc = 0; - - /* We now sleep until all other CPUs have scheduled. This ensures that - * the deletion is seen by all other CPUs, and that the deleted handler - * isn't still running on another CPU when we return. */ - synchronize_rcu(); - } - } - return rc; -} -EXPORT_SYMBOL(HvLpEvent_registerHandler); -EXPORT_SYMBOL(HvLpEvent_unregisterHandler); - -/* (lpIndex is the partition index of the target partition. - * needed only for VirtualIo, VirtualLan and SessionMgr. Zero - * indicates to use our partition index - for the other types) - */ -int HvLpEvent_openPath( HvLpEvent_Type eventType, HvLpIndex lpIndex ) -{ - int rc = 1; - if ( eventType < HvLpEvent_Type_NumTypes && - lpEventHandler[eventType] ) { - if ( lpIndex == 0 ) - lpIndex = itLpNaca.xLpIndex; - HvCallEvent_openLpEventPath( lpIndex, eventType ); - ++lpEventHandlerPaths[eventType]; - rc = 0; - } - return rc; -} - -int HvLpEvent_closePath( HvLpEvent_Type eventType, HvLpIndex lpIndex ) -{ - int rc = 1; - if ( eventType < HvLpEvent_Type_NumTypes && - lpEventHandler[eventType] && - lpEventHandlerPaths[eventType] ) { - if ( lpIndex == 0 ) - lpIndex = itLpNaca.xLpIndex; - HvCallEvent_closeLpEventPath( lpIndex, eventType ); - --lpEventHandlerPaths[eventType]; - rc = 0; - } - return rc; -} - diff --git a/arch/ppc64/kernel/Makefile b/arch/ppc64/kernel/Makefile --- a/arch/ppc64/kernel/Makefile +++ b/arch/ppc64/kernel/Makefile @@ -22,7 +22,7 @@ pci-obj-$(CONFIG_PPC_MULTIPLATFORM) += p obj-$(CONFIG_PCI) += pci.o pci_iommu.o iomap.o $(pci-obj-y) -obj-$(CONFIG_PPC_ISERIES) += HvLpEvent.o iSeries_proc.o iSeries_htab.o \ +obj-$(CONFIG_PPC_ISERIES) += iSeries_proc.o iSeries_htab.o \ iSeries_iommu.o obj-$(CONFIG_PPC_MULTIPLATFORM) += nvram.o i8259.o prom_init.o From sfr at canb.auug.org.au Wed Sep 28 16:52:41 2005 From: sfr at canb.auug.org.au (Stephen Rothwell) Date: Wed, 28 Sep 2005 16:52:41 +1000 Subject: [PATCH 8/19] powerpc: move iSeries_proc.c to powerpc/platforms/iseries In-Reply-To: <20050928163333.02799419.sfr@canb.auug.org.au> References: <20050928163333.02799419.sfr@canb.auug.org.au> Message-ID: <20050928165241.28505aa0.sfr@canb.auug.org.au> And renamed it to proc.c Signed-off-by: Stephen Rothwell --- arch/powerpc/platforms/iseries/Makefile | 3 + arch/powerpc/platforms/iseries/proc.c | 115 +++++++++++++++++++++++++++++++ arch/ppc64/kernel/Makefile | 2 - arch/ppc64/kernel/iSeries_proc.c | 113 ------------------------------ 4 files changed, 118 insertions(+), 115 deletions(-) create mode 100644 arch/powerpc/platforms/iseries/proc.c delete mode 100644 arch/ppc64/kernel/iSeries_proc.c -- Cheers, Stephen Rothwell sfr at canb.auug.org.au http://www.canb.auug.org.au/~sfr/ cb5c7980ab16c461a883ec7899675be57798d285 diff --git a/arch/powerpc/platforms/iseries/Makefile b/arch/powerpc/platforms/iseries/Makefile --- a/arch/powerpc/platforms/iseries/Makefile +++ b/arch/powerpc/platforms/iseries/Makefile @@ -1 +1,2 @@ -obj-y += hvlog.o hvlpconfig.o lpardata.o setup.o mf.o lpevents.o hvcall.o +obj-y += hvlog.o hvlpconfig.o lpardata.o setup.o mf.o lpevents.o \ + hvcall.o proc.o diff --git a/arch/powerpc/platforms/iseries/proc.c b/arch/powerpc/platforms/iseries/proc.c new file mode 100644 --- /dev/null +++ b/arch/powerpc/platforms/iseries/proc.c @@ -0,0 +1,115 @@ +/* + * Copyright (C) 2001 Kyle A. Lucke IBM Corporation + * Copyright (C) 2001 Mike Corrigan & Dave Engebretsen 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 + */ +#include +#include +#include +#include /* for HZ */ +#include +#include +#include +#include +#include +#include +#include +#include + +static int __init iseries_proc_create(void) +{ + struct proc_dir_entry *e = proc_mkdir("iSeries", 0); + if (!e) + return 1; + + return 0; +} +core_initcall(iseries_proc_create); + +static unsigned long startTitan = 0; +static unsigned long startTb = 0; + +static int proc_titantod_show(struct seq_file *m, void *v) +{ + unsigned long tb0, titan_tod; + + tb0 = get_tb(); + titan_tod = HvCallXm_loadTod(); + + seq_printf(m, "Titan\n" ); + seq_printf(m, " time base = %016lx\n", tb0); + seq_printf(m, " titan tod = %016lx\n", titan_tod); + seq_printf(m, " xProcFreq = %016x\n", + xIoHriProcessorVpd[0].xProcFreq); + seq_printf(m, " xTimeBaseFreq = %016x\n", + xIoHriProcessorVpd[0].xTimeBaseFreq); + seq_printf(m, " tb_ticks_per_jiffy = %lu\n", tb_ticks_per_jiffy); + seq_printf(m, " tb_ticks_per_usec = %lu\n", tb_ticks_per_usec); + + if (!startTitan) { + startTitan = titan_tod; + startTb = tb0; + } else { + unsigned long titan_usec = (titan_tod - startTitan) >> 12; + unsigned long tb_ticks = (tb0 - startTb); + unsigned long titan_jiffies = titan_usec / (1000000/HZ); + unsigned long titan_jiff_usec = titan_jiffies * (1000000/HZ); + unsigned long titan_jiff_rem_usec = + titan_usec - titan_jiff_usec; + unsigned long tb_jiffies = tb_ticks / tb_ticks_per_jiffy; + unsigned long tb_jiff_ticks = tb_jiffies * tb_ticks_per_jiffy; + unsigned long tb_jiff_rem_ticks = tb_ticks - tb_jiff_ticks; + unsigned long tb_jiff_rem_usec = + tb_jiff_rem_ticks / tb_ticks_per_usec; + unsigned long new_tb_ticks_per_jiffy = + (tb_ticks * (1000000/HZ))/titan_usec; + + seq_printf(m, " titan elapsed = %lu uSec\n", titan_usec); + seq_printf(m, " tb elapsed = %lu ticks\n", tb_ticks); + seq_printf(m, " titan jiffies = %lu.%04lu \n", titan_jiffies, + titan_jiff_rem_usec); + seq_printf(m, " tb jiffies = %lu.%04lu\n", tb_jiffies, + tb_jiff_rem_usec); + seq_printf(m, " new tb_ticks_per_jiffy = %lu\n", + new_tb_ticks_per_jiffy); + } + + return 0; +} + +static int proc_titantod_open(struct inode *inode, struct file *file) +{ + return single_open(file, proc_titantod_show, NULL); +} + +static struct file_operations proc_titantod_operations = { + .open = proc_titantod_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + +static int __init iseries_proc_init(void) +{ + struct proc_dir_entry *e; + + e = create_proc_entry("iSeries/titanTod", S_IFREG|S_IRUGO, NULL); + if (e) + e->proc_fops = &proc_titantod_operations; + + return 0; +} +__initcall(iseries_proc_init); diff --git a/arch/ppc64/kernel/Makefile b/arch/ppc64/kernel/Makefile --- a/arch/ppc64/kernel/Makefile +++ b/arch/ppc64/kernel/Makefile @@ -22,7 +22,7 @@ pci-obj-$(CONFIG_PPC_MULTIPLATFORM) += p obj-$(CONFIG_PCI) += pci.o pci_iommu.o iomap.o $(pci-obj-y) -obj-$(CONFIG_PPC_ISERIES) += iSeries_proc.o iSeries_htab.o \ +obj-$(CONFIG_PPC_ISERIES) += iSeries_htab.o \ iSeries_iommu.o obj-$(CONFIG_PPC_MULTIPLATFORM) += nvram.o i8259.o prom_init.o diff --git a/arch/ppc64/kernel/iSeries_proc.c b/arch/ppc64/kernel/iSeries_proc.c deleted file mode 100644 --- a/arch/ppc64/kernel/iSeries_proc.c +++ /dev/null @@ -1,113 +0,0 @@ -/* - * iSeries_proc.c - * Copyright (C) 2001 Kyle A. Lucke IBM Corporation - * Copyright (C) 2001 Mike Corrigan & Dave Engebretsen 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 - */ -#include -#include -#include -#include /* for HZ */ -#include -#include -#include -#include -#include -#include -#include -#include - -static int __init iseries_proc_create(void) -{ - struct proc_dir_entry *e = proc_mkdir("iSeries", 0); - if (!e) - return 1; - - return 0; -} -core_initcall(iseries_proc_create); - -static unsigned long startTitan = 0; -static unsigned long startTb = 0; - -static int proc_titantod_show(struct seq_file *m, void *v) -{ - unsigned long tb0, titan_tod; - - tb0 = get_tb(); - titan_tod = HvCallXm_loadTod(); - - seq_printf(m, "Titan\n" ); - seq_printf(m, " time base = %016lx\n", tb0); - seq_printf(m, " titan tod = %016lx\n", titan_tod); - seq_printf(m, " xProcFreq = %016x\n", - xIoHriProcessorVpd[0].xProcFreq); - seq_printf(m, " xTimeBaseFreq = %016x\n", - xIoHriProcessorVpd[0].xTimeBaseFreq); - seq_printf(m, " tb_ticks_per_jiffy = %lu\n", tb_ticks_per_jiffy); - seq_printf(m, " tb_ticks_per_usec = %lu\n", tb_ticks_per_usec); - - if (!startTitan) { - startTitan = titan_tod; - startTb = tb0; - } else { - unsigned long titan_usec = (titan_tod - startTitan) >> 12; - unsigned long tb_ticks = (tb0 - startTb); - unsigned long titan_jiffies = titan_usec / (1000000/HZ); - unsigned long titan_jiff_usec = titan_jiffies * (1000000/HZ); - unsigned long titan_jiff_rem_usec = titan_usec - titan_jiff_usec; - unsigned long tb_jiffies = tb_ticks / tb_ticks_per_jiffy; - unsigned long tb_jiff_ticks = tb_jiffies * tb_ticks_per_jiffy; - unsigned long tb_jiff_rem_ticks = tb_ticks - tb_jiff_ticks; - unsigned long tb_jiff_rem_usec = tb_jiff_rem_ticks / tb_ticks_per_usec; - unsigned long new_tb_ticks_per_jiffy = (tb_ticks * (1000000/HZ))/titan_usec; - - seq_printf(m, " titan elapsed = %lu uSec\n", titan_usec); - seq_printf(m, " tb elapsed = %lu ticks\n", tb_ticks); - seq_printf(m, " titan jiffies = %lu.%04lu \n", titan_jiffies, - titan_jiff_rem_usec); - seq_printf(m, " tb jiffies = %lu.%04lu\n", tb_jiffies, - tb_jiff_rem_usec); - seq_printf(m, " new tb_ticks_per_jiffy = %lu\n", - new_tb_ticks_per_jiffy); - } - - return 0; -} - -static int proc_titantod_open(struct inode *inode, struct file *file) -{ - return single_open(file, proc_titantod_show, NULL); -} - -static struct file_operations proc_titantod_operations = { - .open = proc_titantod_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, -}; - -static int __init iseries_proc_init(void) -{ - struct proc_dir_entry *e; - - e = create_proc_entry("iSeries/titanTod", S_IFREG|S_IRUGO, NULL); - if (e) - e->proc_fops = &proc_titantod_operations; - - return 0; -} -__initcall(iseries_proc_init); From sfr at canb.auug.org.au Wed Sep 28 16:53:44 2005 From: sfr at canb.auug.org.au (Stephen Rothwell) Date: Wed, 28 Sep 2005 16:53:44 +1000 Subject: [PATCH 9/19] powerpc: Move iSeries_htab.c to powerpc/platforms/iseries In-Reply-To: <20050928163333.02799419.sfr@canb.auug.org.au> References: <20050928163333.02799419.sfr@canb.auug.org.au> Message-ID: <20050928165344.1993eb5b.sfr@canb.auug.org.au> And rename it to htab.c Signed-off-by: Stephen Rothwell --- arch/powerpc/platforms/iseries/Makefile | 2 arch/powerpc/platforms/iseries/htab.c | 256 +++++++++++++++++++++++++++++++ arch/ppc64/kernel/Makefile | 3 arch/ppc64/kernel/iSeries_htab.c | 255 ------------------------------- 4 files changed, 258 insertions(+), 258 deletions(-) create mode 100644 arch/powerpc/platforms/iseries/htab.c delete mode 100644 arch/ppc64/kernel/iSeries_htab.c -- Cheers, Stephen Rothwell sfr at canb.auug.org.au http://www.canb.auug.org.au/~sfr/ e508f438e0c152dcd1fbec5104e9c0ee28f352d4 diff --git a/arch/powerpc/platforms/iseries/Makefile b/arch/powerpc/platforms/iseries/Makefile --- a/arch/powerpc/platforms/iseries/Makefile +++ b/arch/powerpc/platforms/iseries/Makefile @@ -1,2 +1,2 @@ obj-y += hvlog.o hvlpconfig.o lpardata.o setup.o mf.o lpevents.o \ - hvcall.o proc.o + hvcall.o proc.o htab.o diff --git a/arch/powerpc/platforms/iseries/htab.c b/arch/powerpc/platforms/iseries/htab.c new file mode 100644 --- /dev/null +++ b/arch/powerpc/platforms/iseries/htab.c @@ -0,0 +1,256 @@ +/* + * iSeries hashtable management. + * Derived from pSeries_htab.c + * + * SMP scalability work: + * Copyright (C) 2001 Anton Blanchard , IBM + * + * 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 + +static spinlock_t iSeries_hlocks[64] __cacheline_aligned_in_smp = + { [0 ... 63] = SPIN_LOCK_UNLOCKED}; + +/* + * Very primitive algorithm for picking up a lock + */ +static inline void iSeries_hlock(unsigned long slot) +{ + if (slot & 0x8) + slot = ~slot; + spin_lock(&iSeries_hlocks[(slot >> 4) & 0x3f]); +} + +static inline void iSeries_hunlock(unsigned long slot) +{ + if (slot & 0x8) + slot = ~slot; + spin_unlock(&iSeries_hlocks[(slot >> 4) & 0x3f]); +} + +static long iSeries_hpte_insert(unsigned long hpte_group, unsigned long va, + unsigned long prpn, unsigned long vflags, + unsigned long rflags) +{ + unsigned long arpn; + long slot; + hpte_t lhpte; + int secondary = 0; + + /* + * The hypervisor tries both primary and secondary. + * If we are being called to insert in the secondary, + * it means we have already tried both primary and secondary, + * so we return failure immediately. + */ + if (vflags & HPTE_V_SECONDARY) + return -1; + + iSeries_hlock(hpte_group); + + slot = HvCallHpt_findValid(&lhpte, va >> PAGE_SHIFT); + BUG_ON(lhpte.v & HPTE_V_VALID); + + if (slot == -1) { /* No available entry found in either group */ + iSeries_hunlock(hpte_group); + return -1; + } + + if (slot < 0) { /* MSB set means secondary group */ + vflags |= HPTE_V_VALID; + secondary = 1; + slot &= 0x7fffffffffffffff; + } + + arpn = phys_to_abs(prpn << PAGE_SHIFT) >> PAGE_SHIFT; + + lhpte.v = (va >> 23) << HPTE_V_AVPN_SHIFT | vflags | HPTE_V_VALID; + lhpte.r = (arpn << HPTE_R_RPN_SHIFT) | rflags; + + /* Now fill in the actual HPTE */ + HvCallHpt_addValidate(slot, secondary, &lhpte); + + iSeries_hunlock(hpte_group); + + return (secondary << 3) | (slot & 7); +} + +long iSeries_hpte_bolt_or_insert(unsigned long hpte_group, + unsigned long va, unsigned long prpn, unsigned long vflags, + unsigned long rflags) +{ + long slot; + hpte_t lhpte; + + slot = HvCallHpt_findValid(&lhpte, va >> PAGE_SHIFT); + + if (lhpte.v & HPTE_V_VALID) { + /* Bolt the existing HPTE */ + HvCallHpt_setSwBits(slot, 0x10, 0); + HvCallHpt_setPp(slot, PP_RWXX); + return 0; + } + + return iSeries_hpte_insert(hpte_group, va, prpn, vflags, rflags); +} + +static unsigned long iSeries_hpte_getword0(unsigned long slot) +{ + hpte_t hpte; + + HvCallHpt_get(&hpte, slot); + return hpte.v; +} + +static long iSeries_hpte_remove(unsigned long hpte_group) +{ + unsigned long slot_offset; + int i; + unsigned long hpte_v; + + /* Pick a random slot to start at */ + slot_offset = mftb() & 0x7; + + iSeries_hlock(hpte_group); + + for (i = 0; i < HPTES_PER_GROUP; i++) { + hpte_v = iSeries_hpte_getword0(hpte_group + slot_offset); + + if (! (hpte_v & HPTE_V_BOLTED)) { + HvCallHpt_invalidateSetSwBitsGet(hpte_group + + slot_offset, 0, 0); + iSeries_hunlock(hpte_group); + return i; + } + + slot_offset++; + slot_offset &= 0x7; + } + + iSeries_hunlock(hpte_group); + + return -1; +} + +/* + * The HyperVisor expects the "flags" argument in this form: + * bits 0..59 : reserved + * bit 60 : N + * bits 61..63 : PP2,PP1,PP0 + */ +static long iSeries_hpte_updatepp(unsigned long slot, unsigned long newpp, + unsigned long va, int large, int local) +{ + hpte_t hpte; + unsigned long avpn = va >> 23; + + iSeries_hlock(slot); + + HvCallHpt_get(&hpte, slot); + if ((HPTE_V_AVPN_VAL(hpte.v) == avpn) && (hpte.v & HPTE_V_VALID)) { + /* + * Hypervisor expects bits as NPPP, which is + * different from how they are mapped in our PP. + */ + HvCallHpt_setPp(slot, (newpp & 0x3) | ((newpp & 0x4) << 1)); + iSeries_hunlock(slot); + return 0; + } + iSeries_hunlock(slot); + + return -1; +} + +/* + * Functions used to find the PTE for a particular virtual address. + * Only used during boot when bolting pages. + * + * Input : vpn : virtual page number + * Output: PTE index within the page table of the entry + * -1 on failure + */ +static long iSeries_hpte_find(unsigned long vpn) +{ + hpte_t hpte; + long slot; + + /* + * The HvCallHpt_findValid interface is as follows: + * 0xffffffffffffffff : No entry found. + * 0x00000000xxxxxxxx : Entry found in primary group, slot x + * 0x80000000xxxxxxxx : Entry found in secondary group, slot x + */ + slot = HvCallHpt_findValid(&hpte, vpn); + if (hpte.v & HPTE_V_VALID) { + if (slot < 0) { + slot &= 0x7fffffffffffffff; + slot = -slot; + } + } else + slot = -1; + return slot; +} + +/* + * Update the page protection bits. Intended to be used to create + * guard pages for kernel data structures on pages which are bolted + * in the HPT. Assumes pages being operated on will not be stolen. + * Does not work on large pages. + * + * No need to lock here because we should be the only user. + */ +static void iSeries_hpte_updateboltedpp(unsigned long newpp, unsigned long ea) +{ + unsigned long vsid,va,vpn; + long slot; + + vsid = get_kernel_vsid(ea); + va = (vsid << 28) | (ea & 0x0fffffff); + vpn = va >> PAGE_SHIFT; + slot = iSeries_hpte_find(vpn); + if (slot == -1) + panic("updateboltedpp: Could not find page to bolt\n"); + HvCallHpt_setPp(slot, newpp); +} + +static void iSeries_hpte_invalidate(unsigned long slot, unsigned long va, + int large, int local) +{ + unsigned long hpte_v; + unsigned long avpn = va >> 23; + unsigned long flags; + + local_irq_save(flags); + + iSeries_hlock(slot); + + hpte_v = iSeries_hpte_getword0(slot); + + if ((HPTE_V_AVPN_VAL(hpte_v) == avpn) && (hpte_v & HPTE_V_VALID)) + HvCallHpt_invalidateSetSwBitsGet(slot, 0, 0); + + iSeries_hunlock(slot); + + local_irq_restore(flags); +} + +void hpte_init_iSeries(void) +{ + ppc_md.hpte_invalidate = iSeries_hpte_invalidate; + ppc_md.hpte_updatepp = iSeries_hpte_updatepp; + ppc_md.hpte_updateboltedpp = iSeries_hpte_updateboltedpp; + ppc_md.hpte_insert = iSeries_hpte_insert; + ppc_md.hpte_remove = iSeries_hpte_remove; + + htab_finish_init(); +} diff --git a/arch/ppc64/kernel/Makefile b/arch/ppc64/kernel/Makefile --- a/arch/ppc64/kernel/Makefile +++ b/arch/ppc64/kernel/Makefile @@ -22,8 +22,7 @@ pci-obj-$(CONFIG_PPC_MULTIPLATFORM) += p obj-$(CONFIG_PCI) += pci.o pci_iommu.o iomap.o $(pci-obj-y) -obj-$(CONFIG_PPC_ISERIES) += iSeries_htab.o \ - iSeries_iommu.o +obj-$(CONFIG_PPC_ISERIES) += iSeries_iommu.o obj-$(CONFIG_PPC_MULTIPLATFORM) += nvram.o i8259.o prom_init.o diff --git a/arch/ppc64/kernel/iSeries_htab.c b/arch/ppc64/kernel/iSeries_htab.c deleted file mode 100644 --- a/arch/ppc64/kernel/iSeries_htab.c +++ /dev/null @@ -1,255 +0,0 @@ -/* - * iSeries hashtable management. - * Derived from pSeries_htab.c - * - * SMP scalability work: - * Copyright (C) 2001 Anton Blanchard , IBM - * - * 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 - -static spinlock_t iSeries_hlocks[64] __cacheline_aligned_in_smp = { [0 ... 63] = SPIN_LOCK_UNLOCKED}; - -/* - * Very primitive algorithm for picking up a lock - */ -static inline void iSeries_hlock(unsigned long slot) -{ - if (slot & 0x8) - slot = ~slot; - spin_lock(&iSeries_hlocks[(slot >> 4) & 0x3f]); -} - -static inline void iSeries_hunlock(unsigned long slot) -{ - if (slot & 0x8) - slot = ~slot; - spin_unlock(&iSeries_hlocks[(slot >> 4) & 0x3f]); -} - -static long iSeries_hpte_insert(unsigned long hpte_group, unsigned long va, - unsigned long prpn, unsigned long vflags, - unsigned long rflags) -{ - unsigned long arpn; - long slot; - hpte_t lhpte; - int secondary = 0; - - /* - * The hypervisor tries both primary and secondary. - * If we are being called to insert in the secondary, - * it means we have already tried both primary and secondary, - * so we return failure immediately. - */ - if (vflags & HPTE_V_SECONDARY) - return -1; - - iSeries_hlock(hpte_group); - - slot = HvCallHpt_findValid(&lhpte, va >> PAGE_SHIFT); - BUG_ON(lhpte.v & HPTE_V_VALID); - - if (slot == -1) { /* No available entry found in either group */ - iSeries_hunlock(hpte_group); - return -1; - } - - if (slot < 0) { /* MSB set means secondary group */ - vflags |= HPTE_V_VALID; - secondary = 1; - slot &= 0x7fffffffffffffff; - } - - arpn = phys_to_abs(prpn << PAGE_SHIFT) >> PAGE_SHIFT; - - lhpte.v = (va >> 23) << HPTE_V_AVPN_SHIFT | vflags | HPTE_V_VALID; - lhpte.r = (arpn << HPTE_R_RPN_SHIFT) | rflags; - - /* Now fill in the actual HPTE */ - HvCallHpt_addValidate(slot, secondary, &lhpte); - - iSeries_hunlock(hpte_group); - - return (secondary << 3) | (slot & 7); -} - -long iSeries_hpte_bolt_or_insert(unsigned long hpte_group, - unsigned long va, unsigned long prpn, unsigned long vflags, - unsigned long rflags) -{ - long slot; - hpte_t lhpte; - - slot = HvCallHpt_findValid(&lhpte, va >> PAGE_SHIFT); - - if (lhpte.v & HPTE_V_VALID) { - /* Bolt the existing HPTE */ - HvCallHpt_setSwBits(slot, 0x10, 0); - HvCallHpt_setPp(slot, PP_RWXX); - return 0; - } - - return iSeries_hpte_insert(hpte_group, va, prpn, vflags, rflags); -} - -static unsigned long iSeries_hpte_getword0(unsigned long slot) -{ - hpte_t hpte; - - HvCallHpt_get(&hpte, slot); - return hpte.v; -} - -static long iSeries_hpte_remove(unsigned long hpte_group) -{ - unsigned long slot_offset; - int i; - unsigned long hpte_v; - - /* Pick a random slot to start at */ - slot_offset = mftb() & 0x7; - - iSeries_hlock(hpte_group); - - for (i = 0; i < HPTES_PER_GROUP; i++) { - hpte_v = iSeries_hpte_getword0(hpte_group + slot_offset); - - if (! (hpte_v & HPTE_V_BOLTED)) { - HvCallHpt_invalidateSetSwBitsGet(hpte_group + - slot_offset, 0, 0); - iSeries_hunlock(hpte_group); - return i; - } - - slot_offset++; - slot_offset &= 0x7; - } - - iSeries_hunlock(hpte_group); - - return -1; -} - -/* - * The HyperVisor expects the "flags" argument in this form: - * bits 0..59 : reserved - * bit 60 : N - * bits 61..63 : PP2,PP1,PP0 - */ -static long iSeries_hpte_updatepp(unsigned long slot, unsigned long newpp, - unsigned long va, int large, int local) -{ - hpte_t hpte; - unsigned long avpn = va >> 23; - - iSeries_hlock(slot); - - HvCallHpt_get(&hpte, slot); - if ((HPTE_V_AVPN_VAL(hpte.v) == avpn) && (hpte.v & HPTE_V_VALID)) { - /* - * Hypervisor expects bits as NPPP, which is - * different from how they are mapped in our PP. - */ - HvCallHpt_setPp(slot, (newpp & 0x3) | ((newpp & 0x4) << 1)); - iSeries_hunlock(slot); - return 0; - } - iSeries_hunlock(slot); - - return -1; -} - -/* - * Functions used to find the PTE for a particular virtual address. - * Only used during boot when bolting pages. - * - * Input : vpn : virtual page number - * Output: PTE index within the page table of the entry - * -1 on failure - */ -static long iSeries_hpte_find(unsigned long vpn) -{ - hpte_t hpte; - long slot; - - /* - * The HvCallHpt_findValid interface is as follows: - * 0xffffffffffffffff : No entry found. - * 0x00000000xxxxxxxx : Entry found in primary group, slot x - * 0x80000000xxxxxxxx : Entry found in secondary group, slot x - */ - slot = HvCallHpt_findValid(&hpte, vpn); - if (hpte.v & HPTE_V_VALID) { - if (slot < 0) { - slot &= 0x7fffffffffffffff; - slot = -slot; - } - } else - slot = -1; - return slot; -} - -/* - * Update the page protection bits. Intended to be used to create - * guard pages for kernel data structures on pages which are bolted - * in the HPT. Assumes pages being operated on will not be stolen. - * Does not work on large pages. - * - * No need to lock here because we should be the only user. - */ -static void iSeries_hpte_updateboltedpp(unsigned long newpp, unsigned long ea) -{ - unsigned long vsid,va,vpn; - long slot; - - vsid = get_kernel_vsid(ea); - va = (vsid << 28) | (ea & 0x0fffffff); - vpn = va >> PAGE_SHIFT; - slot = iSeries_hpte_find(vpn); - if (slot == -1) - panic("updateboltedpp: Could not find page to bolt\n"); - HvCallHpt_setPp(slot, newpp); -} - -static void iSeries_hpte_invalidate(unsigned long slot, unsigned long va, - int large, int local) -{ - unsigned long hpte_v; - unsigned long avpn = va >> 23; - unsigned long flags; - - local_irq_save(flags); - - iSeries_hlock(slot); - - hpte_v = iSeries_hpte_getword0(slot); - - if ((HPTE_V_AVPN_VAL(hpte_v) == avpn) && (hpte_v & HPTE_V_VALID)) - HvCallHpt_invalidateSetSwBitsGet(slot, 0, 0); - - iSeries_hunlock(slot); - - local_irq_restore(flags); -} - -void hpte_init_iSeries(void) -{ - ppc_md.hpte_invalidate = iSeries_hpte_invalidate; - ppc_md.hpte_updatepp = iSeries_hpte_updatepp; - ppc_md.hpte_updateboltedpp = iSeries_hpte_updateboltedpp; - ppc_md.hpte_insert = iSeries_hpte_insert; - ppc_md.hpte_remove = iSeries_hpte_remove; - - htab_finish_init(); -} From sfr at canb.auug.org.au Wed Sep 28 16:54:37 2005 From: sfr at canb.auug.org.au (Stephen Rothwell) Date: Wed, 28 Sep 2005 16:54:37 +1000 Subject: [PATCH 10/19] powerpc: Move iSeries_iommu.c to powerpc/platforms/iseries In-Reply-To: <20050928163333.02799419.sfr@canb.auug.org.au> References: <20050928163333.02799419.sfr@canb.auug.org.au> Message-ID: <20050928165437.4f9f963a.sfr@canb.auug.org.au> And rename it to iommu.c Signed-off-by: Stephen Rothwell --- arch/powerpc/platforms/iseries/Makefile | 2 arch/powerpc/platforms/iseries/iommu.c | 175 +++++++++++++++++++++++++++++++ arch/ppc64/kernel/Makefile | 2 arch/ppc64/kernel/iSeries_iommu.c | 177 ------------------------------- 4 files changed, 176 insertions(+), 180 deletions(-) create mode 100644 arch/powerpc/platforms/iseries/iommu.c delete mode 100644 arch/ppc64/kernel/iSeries_iommu.c -- Cheers, Stephen Rothwell sfr at canb.auug.org.au http://www.canb.auug.org.au/~sfr/ cc14d430837e8854bd160275ad71d887a8a98488 diff --git a/arch/powerpc/platforms/iseries/Makefile b/arch/powerpc/platforms/iseries/Makefile --- a/arch/powerpc/platforms/iseries/Makefile +++ b/arch/powerpc/platforms/iseries/Makefile @@ -1,2 +1,2 @@ obj-y += hvlog.o hvlpconfig.o lpardata.o setup.o mf.o lpevents.o \ - hvcall.o proc.o htab.o + hvcall.o proc.o htab.o iommu.o diff --git a/arch/powerpc/platforms/iseries/iommu.c b/arch/powerpc/platforms/iseries/iommu.c new file mode 100644 --- /dev/null +++ b/arch/powerpc/platforms/iseries/iommu.c @@ -0,0 +1,175 @@ +/* + * Copyright (C) 2001 Mike Corrigan & Dave Engebretsen, IBM Corporation + * + * Rewrite, cleanup: + * + * Copyright (C) 2004 Olof Johansson , IBM Corporation + * + * Dynamic DMA mapping support, iSeries-specific parts. + * + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include + +#include +#include +#include +#include +#include + +extern struct list_head iSeries_Global_Device_List; + + +static void tce_build_iSeries(struct iommu_table *tbl, long index, long npages, + unsigned long uaddr, enum dma_data_direction direction) +{ + u64 rc; + union tce_entry tce; + + while (npages--) { + tce.te_word = 0; + tce.te_bits.tb_rpn = virt_to_abs(uaddr) >> PAGE_SHIFT; + + if (tbl->it_type == TCE_VB) { + /* Virtual Bus */ + tce.te_bits.tb_valid = 1; + tce.te_bits.tb_allio = 1; + if (direction != DMA_TO_DEVICE) + tce.te_bits.tb_rdwr = 1; + } else { + /* PCI Bus */ + tce.te_bits.tb_rdwr = 1; /* Read allowed */ + if (direction != DMA_TO_DEVICE) + tce.te_bits.tb_pciwr = 1; + } + + rc = HvCallXm_setTce((u64)tbl->it_index, (u64)index, + tce.te_word); + if (rc) + panic("PCI_DMA: HvCallXm_setTce failed, Rc: 0x%lx\n", + rc); + index++; + uaddr += PAGE_SIZE; + } +} + +static void tce_free_iSeries(struct iommu_table *tbl, long index, long npages) +{ + u64 rc; + + while (npages--) { + rc = HvCallXm_setTce((u64)tbl->it_index, (u64)index, 0); + if (rc) + panic("PCI_DMA: HvCallXm_setTce failed, Rc: 0x%lx\n", + rc); + index++; + } +} + +#ifdef CONFIG_PCI +/* + * This function compares the known tables to find an iommu_table + * that has already been built for hardware TCEs. + */ +static struct iommu_table *iommu_table_find(struct iommu_table * tbl) +{ + struct iSeries_Device_Node *dp; + + list_for_each_entry(dp, &iSeries_Global_Device_List, Device_List) { + if ((dp->iommu_table != NULL) && + (dp->iommu_table->it_type == TCE_PCI) && + (dp->iommu_table->it_offset == tbl->it_offset) && + (dp->iommu_table->it_index == tbl->it_index) && + (dp->iommu_table->it_size == tbl->it_size)) + return dp->iommu_table; + } + return NULL; +} + +/* + * Call Hv with the architected data structure to get TCE table info. + * info. Put the returned data into the Linux representation of the + * TCE table data. + * The Hardware Tce table comes in three flavors. + * 1. TCE table shared between Buses. + * 2. TCE table per Bus. + * 3. TCE Table per IOA. + */ +static void iommu_table_getparms(struct iSeries_Device_Node* dn, + struct iommu_table* tbl) +{ + struct iommu_table_cb *parms; + + parms = kmalloc(sizeof(*parms), GFP_KERNEL); + if (parms == NULL) + panic("PCI_DMA: TCE Table Allocation failed."); + + memset(parms, 0, sizeof(*parms)); + + parms->itc_busno = ISERIES_BUS(dn); + parms->itc_slotno = dn->LogicalSlot; + parms->itc_virtbus = 0; + + HvCallXm_getTceTableParms(ISERIES_HV_ADDR(parms)); + + if (parms->itc_size == 0) + panic("PCI_DMA: parms->size is zero, parms is 0x%p", parms); + + /* itc_size is in pages worth of table, it_size is in # of entries */ + tbl->it_size = (parms->itc_size * PAGE_SIZE) / sizeof(union tce_entry); + tbl->it_busno = parms->itc_busno; + tbl->it_offset = parms->itc_offset; + tbl->it_index = parms->itc_index; + tbl->it_blocksize = 1; + tbl->it_type = TCE_PCI; + + kfree(parms); +} + + +void iommu_devnode_init_iSeries(struct iSeries_Device_Node *dn) +{ + struct iommu_table *tbl; + + tbl = kmalloc(sizeof(struct iommu_table), GFP_KERNEL); + + iommu_table_getparms(dn, tbl); + + /* Look for existing tce table */ + dn->iommu_table = iommu_table_find(tbl); + if (dn->iommu_table == NULL) + dn->iommu_table = iommu_init_table(tbl); + else + kfree(tbl); +} +#endif + +static void iommu_dev_setup_iSeries(struct pci_dev *dev) { } +static void iommu_bus_setup_iSeries(struct pci_bus *bus) { } + +void iommu_init_early_iSeries(void) +{ + ppc_md.tce_build = tce_build_iSeries; + ppc_md.tce_free = tce_free_iSeries; + + ppc_md.iommu_dev_setup = iommu_dev_setup_iSeries; + ppc_md.iommu_bus_setup = iommu_bus_setup_iSeries; + + pci_iommu_init(); +} diff --git a/arch/ppc64/kernel/Makefile b/arch/ppc64/kernel/Makefile --- a/arch/ppc64/kernel/Makefile +++ b/arch/ppc64/kernel/Makefile @@ -22,8 +22,6 @@ pci-obj-$(CONFIG_PPC_MULTIPLATFORM) += p obj-$(CONFIG_PCI) += pci.o pci_iommu.o iomap.o $(pci-obj-y) -obj-$(CONFIG_PPC_ISERIES) += iSeries_iommu.o - obj-$(CONFIG_PPC_MULTIPLATFORM) += nvram.o i8259.o prom_init.o obj-$(CONFIG_PPC_PSERIES) += pSeries_pci.o pSeries_lpar.o pSeries_hvCall.o \ diff --git a/arch/ppc64/kernel/iSeries_iommu.c b/arch/ppc64/kernel/iSeries_iommu.c deleted file mode 100644 --- a/arch/ppc64/kernel/iSeries_iommu.c +++ /dev/null @@ -1,177 +0,0 @@ -/* - * arch/ppc64/kernel/iSeries_iommu.c - * - * Copyright (C) 2001 Mike Corrigan & Dave Engebretsen, IBM Corporation - * - * Rewrite, cleanup: - * - * Copyright (C) 2004 Olof Johansson , IBM Corporation - * - * Dynamic DMA mapping support, iSeries-specific parts. - * - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include -#include -#include - -#include -#include -#include -#include -#include - -extern struct list_head iSeries_Global_Device_List; - - -static void tce_build_iSeries(struct iommu_table *tbl, long index, long npages, - unsigned long uaddr, enum dma_data_direction direction) -{ - u64 rc; - union tce_entry tce; - - while (npages--) { - tce.te_word = 0; - tce.te_bits.tb_rpn = virt_to_abs(uaddr) >> PAGE_SHIFT; - - if (tbl->it_type == TCE_VB) { - /* Virtual Bus */ - tce.te_bits.tb_valid = 1; - tce.te_bits.tb_allio = 1; - if (direction != DMA_TO_DEVICE) - tce.te_bits.tb_rdwr = 1; - } else { - /* PCI Bus */ - tce.te_bits.tb_rdwr = 1; /* Read allowed */ - if (direction != DMA_TO_DEVICE) - tce.te_bits.tb_pciwr = 1; - } - - rc = HvCallXm_setTce((u64)tbl->it_index, (u64)index, - tce.te_word); - if (rc) - panic("PCI_DMA: HvCallXm_setTce failed, Rc: 0x%lx\n", - rc); - index++; - uaddr += PAGE_SIZE; - } -} - -static void tce_free_iSeries(struct iommu_table *tbl, long index, long npages) -{ - u64 rc; - - while (npages--) { - rc = HvCallXm_setTce((u64)tbl->it_index, (u64)index, 0); - if (rc) - panic("PCI_DMA: HvCallXm_setTce failed, Rc: 0x%lx\n", - rc); - index++; - } -} - -#ifdef CONFIG_PCI -/* - * This function compares the known tables to find an iommu_table - * that has already been built for hardware TCEs. - */ -static struct iommu_table *iommu_table_find(struct iommu_table * tbl) -{ - struct iSeries_Device_Node *dp; - - list_for_each_entry(dp, &iSeries_Global_Device_List, Device_List) { - if ((dp->iommu_table != NULL) && - (dp->iommu_table->it_type == TCE_PCI) && - (dp->iommu_table->it_offset == tbl->it_offset) && - (dp->iommu_table->it_index == tbl->it_index) && - (dp->iommu_table->it_size == tbl->it_size)) - return dp->iommu_table; - } - return NULL; -} - -/* - * Call Hv with the architected data structure to get TCE table info. - * info. Put the returned data into the Linux representation of the - * TCE table data. - * The Hardware Tce table comes in three flavors. - * 1. TCE table shared between Buses. - * 2. TCE table per Bus. - * 3. TCE Table per IOA. - */ -static void iommu_table_getparms(struct iSeries_Device_Node* dn, - struct iommu_table* tbl) -{ - struct iommu_table_cb *parms; - - parms = kmalloc(sizeof(*parms), GFP_KERNEL); - if (parms == NULL) - panic("PCI_DMA: TCE Table Allocation failed."); - - memset(parms, 0, sizeof(*parms)); - - parms->itc_busno = ISERIES_BUS(dn); - parms->itc_slotno = dn->LogicalSlot; - parms->itc_virtbus = 0; - - HvCallXm_getTceTableParms(ISERIES_HV_ADDR(parms)); - - if (parms->itc_size == 0) - panic("PCI_DMA: parms->size is zero, parms is 0x%p", parms); - - /* itc_size is in pages worth of table, it_size is in # of entries */ - tbl->it_size = (parms->itc_size * PAGE_SIZE) / sizeof(union tce_entry); - tbl->it_busno = parms->itc_busno; - tbl->it_offset = parms->itc_offset; - tbl->it_index = parms->itc_index; - tbl->it_blocksize = 1; - tbl->it_type = TCE_PCI; - - kfree(parms); -} - - -void iommu_devnode_init_iSeries(struct iSeries_Device_Node *dn) -{ - struct iommu_table *tbl; - - tbl = kmalloc(sizeof(struct iommu_table), GFP_KERNEL); - - iommu_table_getparms(dn, tbl); - - /* Look for existing tce table */ - dn->iommu_table = iommu_table_find(tbl); - if (dn->iommu_table == NULL) - dn->iommu_table = iommu_init_table(tbl); - else - kfree(tbl); -} -#endif - -static void iommu_dev_setup_iSeries(struct pci_dev *dev) { } -static void iommu_bus_setup_iSeries(struct pci_bus *bus) { } - -void iommu_init_early_iSeries(void) -{ - ppc_md.tce_build = tce_build_iSeries; - ppc_md.tce_free = tce_free_iSeries; - - ppc_md.iommu_dev_setup = iommu_dev_setup_iSeries; - ppc_md.iommu_bus_setup = iommu_bus_setup_iSeries; - - pci_iommu_init(); -} From sfr at canb.auug.org.au Wed Sep 28 16:56:13 2005 From: sfr at canb.auug.org.au (Stephen Rothwell) Date: Wed, 28 Sep 2005 16:56:13 +1000 Subject: [PATCH 11/19] powerpc: Move iSeries_pci.c to powerpc/platform/iseries In-Reply-To: <20050928163333.02799419.sfr@canb.auug.org.au> References: <20050928163333.02799419.sfr@canb.auug.org.au> Message-ID: <20050928165613.5c2a7471.sfr@canb.auug.org.au> and rename it to pci.c. This also required moving arch/ppc64/kernel/pci.h into include/asm-powerpc (called ppc-pci.h. Signed-off-by: Stephen Rothwell --- arch/powerpc/platforms/iseries/Makefile | 1 arch/powerpc/platforms/iseries/pci.c | 903 +++++++++++++++++++++++++++++++ arch/ppc64/kernel/Makefile | 2 arch/ppc64/kernel/bpa_iommu.c | 2 arch/ppc64/kernel/bpa_setup.c | 2 arch/ppc64/kernel/eeh.c | 2 arch/ppc64/kernel/iSeries_pci.c | 905 ------------------------------- arch/ppc64/kernel/maple_pci.c | 3 arch/ppc64/kernel/pSeries_iommu.c | 2 arch/ppc64/kernel/pSeries_pci.c | 3 arch/ppc64/kernel/pSeries_setup.c | 2 arch/ppc64/kernel/pci.c | 3 arch/ppc64/kernel/pci.h | 54 -- arch/ppc64/kernel/pci_direct_iommu.c | 3 arch/ppc64/kernel/pci_dn.c | 3 arch/ppc64/kernel/pci_iommu.c | 2 arch/ppc64/kernel/pmac_pci.c | 2 arch/ppc64/kernel/rtas_pci.c | 3 arch/ppc64/kernel/sys_ppc32.c | 3 arch/ppc64/kernel/u3_iommu.c | 3 include/asm-powerpc/ppc-pci.h | 54 ++ 21 files changed, 974 insertions(+), 983 deletions(-) create mode 100644 arch/powerpc/platforms/iseries/pci.c delete mode 100644 arch/ppc64/kernel/iSeries_pci.c delete mode 100644 arch/ppc64/kernel/pci.h create mode 100644 include/asm-powerpc/ppc-pci.h -- Cheers, Stephen Rothwell sfr at canb.auug.org.au http://www.canb.auug.org.au/~sfr/ d387899f3f7092edbafe16d69ea9737846473e99 diff --git a/arch/powerpc/platforms/iseries/Makefile b/arch/powerpc/platforms/iseries/Makefile --- a/arch/powerpc/platforms/iseries/Makefile +++ b/arch/powerpc/platforms/iseries/Makefile @@ -1,2 +1,3 @@ obj-y += hvlog.o hvlpconfig.o lpardata.o setup.o mf.o lpevents.o \ hvcall.o proc.o htab.o iommu.o +obj-$(CONFIG_PCI) += pci.o diff --git a/arch/powerpc/platforms/iseries/pci.c b/arch/powerpc/platforms/iseries/pci.c new file mode 100644 --- /dev/null +++ b/arch/powerpc/platforms/iseries/pci.c @@ -0,0 +1,903 @@ +/* + * Copyright (C) 2001 Allan Trautman, IBM Corporation + * + * iSeries specific routines for PCI. + * + * Based on code from pci.c and iSeries_pci.c 32bit + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include + +extern unsigned long io_page_mask; + +/* + * Forward declares of prototypes. + */ +static struct iSeries_Device_Node *find_Device_Node(int bus, int devfn); +static void scan_PHB_slots(struct pci_controller *Phb); +static void scan_EADS_bridge(HvBusNumber Bus, HvSubBusNumber SubBus, int IdSel); +static int scan_bridge_slot(HvBusNumber Bus, struct HvCallPci_BridgeInfo *Info); + +LIST_HEAD(iSeries_Global_Device_List); + +static int DeviceCount; + +/* Counters and control flags. */ +static long Pci_Io_Read_Count; +static long Pci_Io_Write_Count; +#if 0 +static long Pci_Cfg_Read_Count; +static long Pci_Cfg_Write_Count; +#endif +static long Pci_Error_Count; + +static int Pci_Retry_Max = 3; /* Only retry 3 times */ +static int Pci_Error_Flag = 1; /* Set Retry Error on. */ + +static struct pci_ops iSeries_pci_ops; + +/* + * Table defines + * Each Entry size is 4 MB * 1024 Entries = 4GB I/O address space. + */ +#define IOMM_TABLE_MAX_ENTRIES 1024 +#define IOMM_TABLE_ENTRY_SIZE 0x0000000000400000UL +#define BASE_IO_MEMORY 0xE000000000000000UL + +static unsigned long max_io_memory = 0xE000000000000000UL; +static long current_iomm_table_entry; + +/* + * Lookup Tables. + */ +static struct iSeries_Device_Node **iomm_table; +static u8 *iobar_table; + +/* + * Static and Global variables + */ +static char *pci_io_text = "iSeries PCI I/O"; +static DEFINE_SPINLOCK(iomm_table_lock); + +/* + * iomm_table_initialize + * + * Allocates and initalizes the Address Translation Table and Bar + * Tables to get them ready for use. Must be called before any + * I/O space is handed out to the device BARs. + */ +static void iomm_table_initialize(void) +{ + spin_lock(&iomm_table_lock); + iomm_table = kmalloc(sizeof(*iomm_table) * IOMM_TABLE_MAX_ENTRIES, + GFP_KERNEL); + iobar_table = kmalloc(sizeof(*iobar_table) * IOMM_TABLE_MAX_ENTRIES, + GFP_KERNEL); + spin_unlock(&iomm_table_lock); + if ((iomm_table == NULL) || (iobar_table == NULL)) + panic("PCI: I/O tables allocation failed.\n"); +} + +/* + * iomm_table_allocate_entry + * + * Adds pci_dev entry in address translation table + * + * - Allocates the number of entries required in table base on BAR + * size. + * - Allocates starting at BASE_IO_MEMORY and increases. + * - The size is round up to be a multiple of entry size. + * - CurrentIndex is incremented to keep track of the last entry. + * - Builds the resource entry for allocated BARs. + */ +static void iomm_table_allocate_entry(struct pci_dev *dev, int bar_num) +{ + struct resource *bar_res = &dev->resource[bar_num]; + long bar_size = pci_resource_len(dev, bar_num); + + /* + * No space to allocate, quick exit, skip Allocation. + */ + if (bar_size == 0) + return; + /* + * Set Resource values. + */ + spin_lock(&iomm_table_lock); + bar_res->name = pci_io_text; + bar_res->start = + IOMM_TABLE_ENTRY_SIZE * current_iomm_table_entry; + bar_res->start += BASE_IO_MEMORY; + bar_res->end = bar_res->start + bar_size - 1; + /* + * Allocate the number of table entries needed for BAR. + */ + while (bar_size > 0 ) { + iomm_table[current_iomm_table_entry] = dev->sysdata; + iobar_table[current_iomm_table_entry] = bar_num; + bar_size -= IOMM_TABLE_ENTRY_SIZE; + ++current_iomm_table_entry; + } + max_io_memory = BASE_IO_MEMORY + + (IOMM_TABLE_ENTRY_SIZE * current_iomm_table_entry); + spin_unlock(&iomm_table_lock); +} + +/* + * allocate_device_bars + * + * - Allocates ALL pci_dev BAR's and updates the resources with the + * BAR value. BARS with zero length will have the resources + * The HvCallPci_getBarParms is used to get the size of the BAR + * space. It calls iomm_table_allocate_entry to allocate + * each entry. + * - Loops through The Bar resources(0 - 5) including the ROM + * is resource(6). + */ +static void allocate_device_bars(struct pci_dev *dev) +{ + struct resource *bar_res; + int bar_num; + + for (bar_num = 0; bar_num <= PCI_ROM_RESOURCE; ++bar_num) { + bar_res = &dev->resource[bar_num]; + iomm_table_allocate_entry(dev, bar_num); + } +} + +/* + * Log error information to system console. + * Filter out the device not there errors. + * PCI: EADs Connect Failed 0x18.58.10 Rc: 0x00xx + * PCI: Read Vendor Failed 0x18.58.10 Rc: 0x00xx + * PCI: Connect Bus Unit Failed 0x18.58.10 Rc: 0x00xx + */ +static void pci_Log_Error(char *Error_Text, int Bus, int SubBus, + int AgentId, int HvRc) +{ + if (HvRc == 0x0302) + return; + printk(KERN_ERR "PCI: %s Failed: 0x%02X.%02X.%02X Rc: 0x%04X", + Error_Text, Bus, SubBus, AgentId, HvRc); +} + +/* + * build_device_node(u16 Bus, int SubBus, u8 DevFn) + */ +static struct iSeries_Device_Node *build_device_node(HvBusNumber Bus, + HvSubBusNumber SubBus, int AgentId, int Function) +{ + struct iSeries_Device_Node *node; + + PPCDBG(PPCDBG_BUSWALK, + "-build_device_node 0x%02X.%02X.%02X Function: %02X\n", + Bus, SubBus, AgentId, Function); + + node = kmalloc(sizeof(struct iSeries_Device_Node), GFP_KERNEL); + if (node == NULL) + return NULL; + + memset(node, 0, sizeof(struct iSeries_Device_Node)); + list_add_tail(&node->Device_List, &iSeries_Global_Device_List); +#if 0 + node->DsaAddr = ((u64)Bus << 48) + ((u64)SubBus << 40) + ((u64)0x10 << 32); +#endif + node->DsaAddr.DsaAddr = 0; + node->DsaAddr.Dsa.busNumber = Bus; + node->DsaAddr.Dsa.subBusNumber = SubBus; + node->DsaAddr.Dsa.deviceId = 0x10; + node->DevFn = PCI_DEVFN(ISERIES_ENCODE_DEVICE(AgentId), Function); + return node; +} + +/* + * unsigned long __init find_and_init_phbs(void) + * + * Description: + * This function checks for all possible system PCI host bridges that connect + * PCI buses. The system hypervisor is queried as to the guest partition + * ownership status. A pci_controller is built for any bus which is partially + * owned or fully owned by this guest partition. + */ +unsigned long __init find_and_init_phbs(void) +{ + struct pci_controller *phb; + HvBusNumber bus; + + PPCDBG(PPCDBG_BUSWALK, "find_and_init_phbs Entry\n"); + + /* Check all possible buses. */ + for (bus = 0; bus < 256; bus++) { + int ret = HvCallXm_testBus(bus); + if (ret == 0) { + printk("bus %d appears to exist\n", bus); + + phb = (struct pci_controller *)kmalloc(sizeof(struct pci_controller), GFP_KERNEL); + if (phb == NULL) + return -ENOMEM; + pci_setup_pci_controller(phb); + + phb->pci_mem_offset = phb->local_number = bus; + phb->first_busno = bus; + phb->last_busno = bus; + phb->ops = &iSeries_pci_ops; + + PPCDBG(PPCDBG_BUSWALK, "PCI:Create iSeries pci_controller(%p), Bus: %04X\n", + phb, bus); + + /* Find and connect the devices. */ + scan_PHB_slots(phb); + } + /* + * Check for Unexpected Return code, a clue that something + * has gone wrong. + */ + else if (ret != 0x0301) + printk(KERN_ERR "Unexpected Return on Probe(0x%04X): 0x%04X", + bus, ret); + } + return 0; +} + +/* + * iSeries_pcibios_init + * + * Chance to initialize and structures or variable before PCI Bus walk. + */ +void iSeries_pcibios_init(void) +{ + PPCDBG(PPCDBG_BUSWALK, "iSeries_pcibios_init Entry.\n"); + iomm_table_initialize(); + find_and_init_phbs(); + io_page_mask = -1; + PPCDBG(PPCDBG_BUSWALK, "iSeries_pcibios_init Exit.\n"); +} + +/* + * iSeries_pci_final_fixup(void) + */ +void __init iSeries_pci_final_fixup(void) +{ + struct pci_dev *pdev = NULL; + struct iSeries_Device_Node *node; + int DeviceCount = 0; + + PPCDBG(PPCDBG_BUSWALK, "iSeries_pcibios_fixup Entry.\n"); + + /* Fix up at the device node and pci_dev relationship */ + mf_display_src(0xC9000100); + + printk("pcibios_final_fixup\n"); + for_each_pci_dev(pdev) { + node = find_Device_Node(pdev->bus->number, pdev->devfn); + printk("pci dev %p (%x.%x), node %p\n", pdev, + pdev->bus->number, pdev->devfn, node); + + if (node != NULL) { + ++DeviceCount; + pdev->sysdata = (void *)node; + node->PciDev = pdev; + PPCDBG(PPCDBG_BUSWALK, + "pdev 0x%p <==> DevNode 0x%p\n", + pdev, node); + allocate_device_bars(pdev); + iSeries_Device_Information(pdev, DeviceCount); + iommu_devnode_init_iSeries(node); + } else + printk("PCI: Device Tree not found for 0x%016lX\n", + (unsigned long)pdev); + pdev->irq = node->Irq; + } + iSeries_activate_IRQs(); + mf_display_src(0xC9000200); +} + +void pcibios_fixup_bus(struct pci_bus *PciBus) +{ + PPCDBG(PPCDBG_BUSWALK, "iSeries_pcibios_fixup_bus(0x%04X) Entry.\n", + PciBus->number); +} + +void pcibios_fixup_resources(struct pci_dev *pdev) +{ + PPCDBG(PPCDBG_BUSWALK, "fixup_resources pdev %p\n", pdev); +} + +/* + * Loop through each node function to find usable EADs bridges. + */ +static void scan_PHB_slots(struct pci_controller *Phb) +{ + struct HvCallPci_DeviceInfo *DevInfo; + HvBusNumber bus = Phb->local_number; /* System Bus */ + const HvSubBusNumber SubBus = 0; /* EADs is always 0. */ + int HvRc = 0; + int IdSel; + const int MaxAgents = 8; + + DevInfo = (struct HvCallPci_DeviceInfo*) + kmalloc(sizeof(struct HvCallPci_DeviceInfo), GFP_KERNEL); + if (DevInfo == NULL) + return; + + /* + * Probe for EADs Bridges + */ + for (IdSel = 1; IdSel < MaxAgents; ++IdSel) { + HvRc = HvCallPci_getDeviceInfo(bus, SubBus, IdSel, + ISERIES_HV_ADDR(DevInfo), + sizeof(struct HvCallPci_DeviceInfo)); + if (HvRc == 0) { + if (DevInfo->deviceType == HvCallPci_NodeDevice) + scan_EADS_bridge(bus, SubBus, IdSel); + else + printk("PCI: Invalid System Configuration(0x%02X)" + " for bus 0x%02x id 0x%02x.\n", + DevInfo->deviceType, bus, IdSel); + } + else + pci_Log_Error("getDeviceInfo", bus, SubBus, IdSel, HvRc); + } + kfree(DevInfo); +} + +static void scan_EADS_bridge(HvBusNumber bus, HvSubBusNumber SubBus, + int IdSel) +{ + struct HvCallPci_BridgeInfo *BridgeInfo; + HvAgentId AgentId; + int Function; + int HvRc; + + BridgeInfo = (struct HvCallPci_BridgeInfo *) + kmalloc(sizeof(struct HvCallPci_BridgeInfo), GFP_KERNEL); + if (BridgeInfo == NULL) + return; + + /* Note: hvSubBus and irq is always be 0 at this level! */ + for (Function = 0; Function < 8; ++Function) { + AgentId = ISERIES_PCI_AGENTID(IdSel, Function); + HvRc = HvCallXm_connectBusUnit(bus, SubBus, AgentId, 0); + if (HvRc == 0) { + printk("found device at bus %d idsel %d func %d (AgentId %x)\n", + bus, IdSel, Function, AgentId); + /* Connect EADs: 0x18.00.12 = 0x00 */ + PPCDBG(PPCDBG_BUSWALK, + "PCI:Connect EADs: 0x%02X.%02X.%02X\n", + bus, SubBus, AgentId); + HvRc = HvCallPci_getBusUnitInfo(bus, SubBus, AgentId, + ISERIES_HV_ADDR(BridgeInfo), + sizeof(struct HvCallPci_BridgeInfo)); + if (HvRc == 0) { + printk("bridge info: type %x subbus %x maxAgents %x maxsubbus %x logslot %x\n", + BridgeInfo->busUnitInfo.deviceType, + BridgeInfo->subBusNumber, + BridgeInfo->maxAgents, + BridgeInfo->maxSubBusNumber, + BridgeInfo->logicalSlotNumber); + PPCDBG(PPCDBG_BUSWALK, + "PCI: BridgeInfo, Type:0x%02X, SubBus:0x%02X, MaxAgents:0x%02X, MaxSubBus: 0x%02X, LSlot: 0x%02X\n", + BridgeInfo->busUnitInfo.deviceType, + BridgeInfo->subBusNumber, + BridgeInfo->maxAgents, + BridgeInfo->maxSubBusNumber, + BridgeInfo->logicalSlotNumber); + + if (BridgeInfo->busUnitInfo.deviceType == + HvCallPci_BridgeDevice) { + /* Scan_Bridge_Slot...: 0x18.00.12 */ + scan_bridge_slot(bus, BridgeInfo); + } else + printk("PCI: Invalid Bridge Configuration(0x%02X)", + BridgeInfo->busUnitInfo.deviceType); + } + } else if (HvRc != 0x000B) + pci_Log_Error("EADs Connect", + bus, SubBus, AgentId, HvRc); + } + kfree(BridgeInfo); +} + +/* + * This assumes that the node slot is always on the primary bus! + */ +static int scan_bridge_slot(HvBusNumber Bus, + struct HvCallPci_BridgeInfo *BridgeInfo) +{ + struct iSeries_Device_Node *node; + HvSubBusNumber SubBus = BridgeInfo->subBusNumber; + u16 VendorId = 0; + int HvRc = 0; + u8 Irq = 0; + int IdSel = ISERIES_GET_DEVICE_FROM_SUBBUS(SubBus); + int Function = ISERIES_GET_FUNCTION_FROM_SUBBUS(SubBus); + HvAgentId EADsIdSel = ISERIES_PCI_AGENTID(IdSel, Function); + + /* iSeries_allocate_IRQ.: 0x18.00.12(0xA3) */ + Irq = iSeries_allocate_IRQ(Bus, 0, EADsIdSel); + PPCDBG(PPCDBG_BUSWALK, + "PCI:- allocate and assign IRQ 0x%02X.%02X.%02X = 0x%02X\n", + Bus, 0, EADsIdSel, Irq); + + /* + * Connect all functions of any device found. + */ + for (IdSel = 1; IdSel <= BridgeInfo->maxAgents; ++IdSel) { + for (Function = 0; Function < 8; ++Function) { + HvAgentId AgentId = ISERIES_PCI_AGENTID(IdSel, Function); + HvRc = HvCallXm_connectBusUnit(Bus, SubBus, + AgentId, Irq); + if (HvRc != 0) { + pci_Log_Error("Connect Bus Unit", + Bus, SubBus, AgentId, HvRc); + continue; + } + + HvRc = HvCallPci_configLoad16(Bus, SubBus, AgentId, + PCI_VENDOR_ID, &VendorId); + if (HvRc != 0) { + pci_Log_Error("Read Vendor", + Bus, SubBus, AgentId, HvRc); + continue; + } + printk("read vendor ID: %x\n", VendorId); + + /* FoundDevice: 0x18.28.10 = 0x12AE */ + PPCDBG(PPCDBG_BUSWALK, + "PCI:- FoundDevice: 0x%02X.%02X.%02X = 0x%04X, irq %d\n", + Bus, SubBus, AgentId, VendorId, Irq); + HvRc = HvCallPci_configStore8(Bus, SubBus, AgentId, + PCI_INTERRUPT_LINE, Irq); + if (HvRc != 0) + pci_Log_Error("PciCfgStore Irq Failed!", + Bus, SubBus, AgentId, HvRc); + + ++DeviceCount; + node = build_device_node(Bus, SubBus, EADsIdSel, Function); + node->Irq = Irq; + node->LogicalSlot = BridgeInfo->logicalSlotNumber; + + } /* for (Function = 0; Function < 8; ++Function) */ + } /* for (IdSel = 1; IdSel <= MaxAgents; ++IdSel) */ + return HvRc; +} + +/* + * I/0 Memory copy MUST use mmio commands on iSeries + * To do; For performance, include the hv call directly + */ +void iSeries_memset_io(volatile void __iomem *dest, char c, size_t Count) +{ + u8 ByteValue = c; + long NumberOfBytes = Count; + + while (NumberOfBytes > 0) { + iSeries_Write_Byte(ByteValue, dest++); + -- NumberOfBytes; + } +} +EXPORT_SYMBOL(iSeries_memset_io); + +void iSeries_memcpy_toio(volatile void __iomem *dest, void *source, size_t count) +{ + char *src = source; + long NumberOfBytes = count; + + while (NumberOfBytes > 0) { + iSeries_Write_Byte(*src++, dest++); + -- NumberOfBytes; + } +} +EXPORT_SYMBOL(iSeries_memcpy_toio); + +void iSeries_memcpy_fromio(void *dest, const volatile void __iomem *src, size_t count) +{ + char *dst = dest; + long NumberOfBytes = count; + + while (NumberOfBytes > 0) { + *dst++ = iSeries_Read_Byte(src++); + -- NumberOfBytes; + } +} +EXPORT_SYMBOL(iSeries_memcpy_fromio); + +/* + * Look down the chain to find the matching Device Device + */ +static struct iSeries_Device_Node *find_Device_Node(int bus, int devfn) +{ + struct list_head *pos; + + list_for_each(pos, &iSeries_Global_Device_List) { + struct iSeries_Device_Node *node = + list_entry(pos, struct iSeries_Device_Node, Device_List); + + if ((bus == ISERIES_BUS(node)) && (devfn == node->DevFn)) + return node; + } + return NULL; +} + +#if 0 +/* + * Returns the device node for the passed pci_dev + * Sanity Check Node PciDev to passed pci_dev + * If none is found, returns a NULL which the client must handle. + */ +static struct iSeries_Device_Node *get_Device_Node(struct pci_dev *pdev) +{ + struct iSeries_Device_Node *node; + + node = pdev->sysdata; + if (node == NULL || node->PciDev != pdev) + node = find_Device_Node(pdev->bus->number, pdev->devfn); + return node; +} +#endif + +/* + * Config space read and write functions. + * For now at least, we look for the device node for the bus and devfn + * that we are asked to access. It may be possible to translate the devfn + * to a subbus and deviceid more directly. + */ +static u64 hv_cfg_read_func[4] = { + HvCallPciConfigLoad8, HvCallPciConfigLoad16, + HvCallPciConfigLoad32, HvCallPciConfigLoad32 +}; + +static u64 hv_cfg_write_func[4] = { + HvCallPciConfigStore8, HvCallPciConfigStore16, + HvCallPciConfigStore32, HvCallPciConfigStore32 +}; + +/* + * Read PCI config space + */ +static int iSeries_pci_read_config(struct pci_bus *bus, unsigned int devfn, + int offset, int size, u32 *val) +{ + struct iSeries_Device_Node *node = find_Device_Node(bus->number, devfn); + u64 fn; + struct HvCallPci_LoadReturn ret; + + if (node == NULL) + return PCIBIOS_DEVICE_NOT_FOUND; + if (offset > 255) { + *val = ~0; + return PCIBIOS_BAD_REGISTER_NUMBER; + } + + fn = hv_cfg_read_func[(size - 1) & 3]; + HvCall3Ret16(fn, &ret, node->DsaAddr.DsaAddr, offset, 0); + + if (ret.rc != 0) { + *val = ~0; + return PCIBIOS_DEVICE_NOT_FOUND; /* or something */ + } + + *val = ret.value; + return 0; +} + +/* + * Write PCI config space + */ + +static int iSeries_pci_write_config(struct pci_bus *bus, unsigned int devfn, + int offset, int size, u32 val) +{ + struct iSeries_Device_Node *node = find_Device_Node(bus->number, devfn); + u64 fn; + u64 ret; + + if (node == NULL) + return PCIBIOS_DEVICE_NOT_FOUND; + if (offset > 255) + return PCIBIOS_BAD_REGISTER_NUMBER; + + fn = hv_cfg_write_func[(size - 1) & 3]; + ret = HvCall4(fn, node->DsaAddr.DsaAddr, offset, val, 0); + + if (ret != 0) + return PCIBIOS_DEVICE_NOT_FOUND; + + return 0; +} + +static struct pci_ops iSeries_pci_ops = { + .read = iSeries_pci_read_config, + .write = iSeries_pci_write_config +}; + +/* + * Check Return Code + * -> On Failure, print and log information. + * Increment Retry Count, if exceeds max, panic partition. + * + * PCI: Device 23.90 ReadL I/O Error( 0): 0x1234 + * PCI: Device 23.90 ReadL Retry( 1) + * PCI: Device 23.90 ReadL Retry Successful(1) + */ +static int CheckReturnCode(char *TextHdr, struct iSeries_Device_Node *DevNode, + int *retry, u64 ret) +{ + if (ret != 0) { + ++Pci_Error_Count; + (*retry)++; + printk("PCI: %s: Device 0x%04X:%02X I/O Error(%2d): 0x%04X\n", + TextHdr, DevNode->DsaAddr.Dsa.busNumber, DevNode->DevFn, + *retry, (int)ret); + /* + * Bump the retry and check for retry count exceeded. + * If, Exceeded, panic the system. + */ + if (((*retry) > Pci_Retry_Max) && + (Pci_Error_Flag > 0)) { + mf_display_src(0xB6000103); + panic_timeout = 0; + panic("PCI: Hardware I/O Error, SRC B6000103, " + "Automatic Reboot Disabled.\n"); + } + return -1; /* Retry Try */ + } + return 0; +} + +/* + * Translate the I/O Address into a device node, bar, and bar offset. + * Note: Make sure the passed variable end up on the stack to avoid + * the exposure of being device global. + */ +static inline struct iSeries_Device_Node *xlate_iomm_address( + const volatile void __iomem *IoAddress, + u64 *dsaptr, u64 *BarOffsetPtr) +{ + unsigned long OrigIoAddr; + unsigned long BaseIoAddr; + unsigned long TableIndex; + struct iSeries_Device_Node *DevNode; + + OrigIoAddr = (unsigned long __force)IoAddress; + if ((OrigIoAddr < BASE_IO_MEMORY) || (OrigIoAddr >= max_io_memory)) + return NULL; + BaseIoAddr = OrigIoAddr - BASE_IO_MEMORY; + TableIndex = BaseIoAddr / IOMM_TABLE_ENTRY_SIZE; + DevNode = iomm_table[TableIndex]; + + if (DevNode != NULL) { + int barnum = iobar_table[TableIndex]; + *dsaptr = DevNode->DsaAddr.DsaAddr | (barnum << 24); + *BarOffsetPtr = BaseIoAddr % IOMM_TABLE_ENTRY_SIZE; + } else + panic("PCI: Invalid PCI IoAddress detected!\n"); + return DevNode; +} + +/* + * Read MM I/O Instructions for the iSeries + * On MM I/O error, all ones are returned and iSeries_pci_IoError is cal + * else, data is returned in big Endian format. + * + * iSeries_Read_Byte = Read Byte ( 8 bit) + * iSeries_Read_Word = Read Word (16 bit) + * iSeries_Read_Long = Read Long (32 bit) + */ +u8 iSeries_Read_Byte(const volatile void __iomem *IoAddress) +{ + u64 BarOffset; + u64 dsa; + int retry = 0; + struct HvCallPci_LoadReturn ret; + struct iSeries_Device_Node *DevNode = + xlate_iomm_address(IoAddress, &dsa, &BarOffset); + + if (DevNode == NULL) { + static unsigned long last_jiffies; + static int num_printed; + + if ((jiffies - last_jiffies) > 60 * HZ) { + last_jiffies = jiffies; + num_printed = 0; + } + if (num_printed++ < 10) + printk(KERN_ERR "iSeries_Read_Byte: invalid access at IO address %p\n", IoAddress); + return 0xff; + } + do { + ++Pci_Io_Read_Count; + HvCall3Ret16(HvCallPciBarLoad8, &ret, dsa, BarOffset, 0); + } while (CheckReturnCode("RDB", DevNode, &retry, ret.rc) != 0); + + return (u8)ret.value; +} +EXPORT_SYMBOL(iSeries_Read_Byte); + +u16 iSeries_Read_Word(const volatile void __iomem *IoAddress) +{ + u64 BarOffset; + u64 dsa; + int retry = 0; + struct HvCallPci_LoadReturn ret; + struct iSeries_Device_Node *DevNode = + xlate_iomm_address(IoAddress, &dsa, &BarOffset); + + if (DevNode == NULL) { + static unsigned long last_jiffies; + static int num_printed; + + if ((jiffies - last_jiffies) > 60 * HZ) { + last_jiffies = jiffies; + num_printed = 0; + } + if (num_printed++ < 10) + printk(KERN_ERR "iSeries_Read_Word: invalid access at IO address %p\n", IoAddress); + return 0xffff; + } + do { + ++Pci_Io_Read_Count; + HvCall3Ret16(HvCallPciBarLoad16, &ret, dsa, + BarOffset, 0); + } while (CheckReturnCode("RDW", DevNode, &retry, ret.rc) != 0); + + return swab16((u16)ret.value); +} +EXPORT_SYMBOL(iSeries_Read_Word); + +u32 iSeries_Read_Long(const volatile void __iomem *IoAddress) +{ + u64 BarOffset; + u64 dsa; + int retry = 0; + struct HvCallPci_LoadReturn ret; + struct iSeries_Device_Node *DevNode = + xlate_iomm_address(IoAddress, &dsa, &BarOffset); + + if (DevNode == NULL) { + static unsigned long last_jiffies; + static int num_printed; + + if ((jiffies - last_jiffies) > 60 * HZ) { + last_jiffies = jiffies; + num_printed = 0; + } + if (num_printed++ < 10) + printk(KERN_ERR "iSeries_Read_Long: invalid access at IO address %p\n", IoAddress); + return 0xffffffff; + } + do { + ++Pci_Io_Read_Count; + HvCall3Ret16(HvCallPciBarLoad32, &ret, dsa, + BarOffset, 0); + } while (CheckReturnCode("RDL", DevNode, &retry, ret.rc) != 0); + + return swab32((u32)ret.value); +} +EXPORT_SYMBOL(iSeries_Read_Long); + +/* + * Write MM I/O Instructions for the iSeries + * + * iSeries_Write_Byte = Write Byte (8 bit) + * iSeries_Write_Word = Write Word(16 bit) + * iSeries_Write_Long = Write Long(32 bit) + */ +void iSeries_Write_Byte(u8 data, volatile void __iomem *IoAddress) +{ + u64 BarOffset; + u64 dsa; + int retry = 0; + u64 rc; + struct iSeries_Device_Node *DevNode = + xlate_iomm_address(IoAddress, &dsa, &BarOffset); + + if (DevNode == NULL) { + static unsigned long last_jiffies; + static int num_printed; + + if ((jiffies - last_jiffies) > 60 * HZ) { + last_jiffies = jiffies; + num_printed = 0; + } + if (num_printed++ < 10) + printk(KERN_ERR "iSeries_Write_Byte: invalid access at IO address %p\n", IoAddress); + return; + } + do { + ++Pci_Io_Write_Count; + rc = HvCall4(HvCallPciBarStore8, dsa, BarOffset, data, 0); + } while (CheckReturnCode("WWB", DevNode, &retry, rc) != 0); +} +EXPORT_SYMBOL(iSeries_Write_Byte); + +void iSeries_Write_Word(u16 data, volatile void __iomem *IoAddress) +{ + u64 BarOffset; + u64 dsa; + int retry = 0; + u64 rc; + struct iSeries_Device_Node *DevNode = + xlate_iomm_address(IoAddress, &dsa, &BarOffset); + + if (DevNode == NULL) { + static unsigned long last_jiffies; + static int num_printed; + + if ((jiffies - last_jiffies) > 60 * HZ) { + last_jiffies = jiffies; + num_printed = 0; + } + if (num_printed++ < 10) + printk(KERN_ERR "iSeries_Write_Word: invalid access at IO address %p\n", IoAddress); + return; + } + do { + ++Pci_Io_Write_Count; + rc = HvCall4(HvCallPciBarStore16, dsa, BarOffset, swab16(data), 0); + } while (CheckReturnCode("WWW", DevNode, &retry, rc) != 0); +} +EXPORT_SYMBOL(iSeries_Write_Word); + +void iSeries_Write_Long(u32 data, volatile void __iomem *IoAddress) +{ + u64 BarOffset; + u64 dsa; + int retry = 0; + u64 rc; + struct iSeries_Device_Node *DevNode = + xlate_iomm_address(IoAddress, &dsa, &BarOffset); + + if (DevNode == NULL) { + static unsigned long last_jiffies; + static int num_printed; + + if ((jiffies - last_jiffies) > 60 * HZ) { + last_jiffies = jiffies; + num_printed = 0; + } + if (num_printed++ < 10) + printk(KERN_ERR "iSeries_Write_Long: invalid access at IO address %p\n", IoAddress); + return; + } + do { + ++Pci_Io_Write_Count; + rc = HvCall4(HvCallPciBarStore32, dsa, BarOffset, swab32(data), 0); + } while (CheckReturnCode("WWL", DevNode, &retry, rc) != 0); +} +EXPORT_SYMBOL(iSeries_Write_Long); diff --git a/arch/ppc64/kernel/Makefile b/arch/ppc64/kernel/Makefile --- a/arch/ppc64/kernel/Makefile +++ b/arch/ppc64/kernel/Makefile @@ -16,7 +16,7 @@ obj-y += vdso32/ vdso64/ obj-$(CONFIG_PPC_OF) += of_device.o -pci-obj-$(CONFIG_PPC_ISERIES) += iSeries_pci.o iSeries_irq.o \ +pci-obj-$(CONFIG_PPC_ISERIES) += iSeries_irq.o \ iSeries_VpdInfo.o pci-obj-$(CONFIG_PPC_MULTIPLATFORM) += pci_dn.o pci_direct_iommu.o diff --git a/arch/ppc64/kernel/bpa_iommu.c b/arch/ppc64/kernel/bpa_iommu.c --- a/arch/ppc64/kernel/bpa_iommu.c +++ b/arch/ppc64/kernel/bpa_iommu.c @@ -39,8 +39,8 @@ #include #include #include +#include -#include "pci.h" #include "bpa_iommu.h" static inline unsigned long diff --git a/arch/ppc64/kernel/bpa_setup.c b/arch/ppc64/kernel/bpa_setup.c --- a/arch/ppc64/kernel/bpa_setup.c +++ b/arch/ppc64/kernel/bpa_setup.c @@ -43,8 +43,8 @@ #include #include #include +#include -#include "pci.h" #include "bpa_iic.h" #include "bpa_iommu.h" diff --git a/arch/ppc64/kernel/eeh.c b/arch/ppc64/kernel/eeh.c --- a/arch/ppc64/kernel/eeh.c +++ b/arch/ppc64/kernel/eeh.c @@ -33,7 +33,7 @@ #include #include #include -#include "pci.h" +#include #undef DEBUG diff --git a/arch/ppc64/kernel/iSeries_pci.c b/arch/ppc64/kernel/iSeries_pci.c deleted file mode 100644 --- a/arch/ppc64/kernel/iSeries_pci.c +++ /dev/null @@ -1,905 +0,0 @@ -/* - * iSeries_pci.c - * - * Copyright (C) 2001 Allan Trautman, IBM Corporation - * - * iSeries specific routines for PCI. - * - * Based on code from pci.c and iSeries_pci.c 32bit - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#include "pci.h" - -extern unsigned long io_page_mask; - -/* - * Forward declares of prototypes. - */ -static struct iSeries_Device_Node *find_Device_Node(int bus, int devfn); -static void scan_PHB_slots(struct pci_controller *Phb); -static void scan_EADS_bridge(HvBusNumber Bus, HvSubBusNumber SubBus, int IdSel); -static int scan_bridge_slot(HvBusNumber Bus, struct HvCallPci_BridgeInfo *Info); - -LIST_HEAD(iSeries_Global_Device_List); - -static int DeviceCount; - -/* Counters and control flags. */ -static long Pci_Io_Read_Count; -static long Pci_Io_Write_Count; -#if 0 -static long Pci_Cfg_Read_Count; -static long Pci_Cfg_Write_Count; -#endif -static long Pci_Error_Count; - -static int Pci_Retry_Max = 3; /* Only retry 3 times */ -static int Pci_Error_Flag = 1; /* Set Retry Error on. */ - -static struct pci_ops iSeries_pci_ops; - -/* - * Table defines - * Each Entry size is 4 MB * 1024 Entries = 4GB I/O address space. - */ -#define IOMM_TABLE_MAX_ENTRIES 1024 -#define IOMM_TABLE_ENTRY_SIZE 0x0000000000400000UL -#define BASE_IO_MEMORY 0xE000000000000000UL - -static unsigned long max_io_memory = 0xE000000000000000UL; -static long current_iomm_table_entry; - -/* - * Lookup Tables. - */ -static struct iSeries_Device_Node **iomm_table; -static u8 *iobar_table; - -/* - * Static and Global variables - */ -static char *pci_io_text = "iSeries PCI I/O"; -static DEFINE_SPINLOCK(iomm_table_lock); - -/* - * iomm_table_initialize - * - * Allocates and initalizes the Address Translation Table and Bar - * Tables to get them ready for use. Must be called before any - * I/O space is handed out to the device BARs. - */ -static void iomm_table_initialize(void) -{ - spin_lock(&iomm_table_lock); - iomm_table = kmalloc(sizeof(*iomm_table) * IOMM_TABLE_MAX_ENTRIES, - GFP_KERNEL); - iobar_table = kmalloc(sizeof(*iobar_table) * IOMM_TABLE_MAX_ENTRIES, - GFP_KERNEL); - spin_unlock(&iomm_table_lock); - if ((iomm_table == NULL) || (iobar_table == NULL)) - panic("PCI: I/O tables allocation failed.\n"); -} - -/* - * iomm_table_allocate_entry - * - * Adds pci_dev entry in address translation table - * - * - Allocates the number of entries required in table base on BAR - * size. - * - Allocates starting at BASE_IO_MEMORY and increases. - * - The size is round up to be a multiple of entry size. - * - CurrentIndex is incremented to keep track of the last entry. - * - Builds the resource entry for allocated BARs. - */ -static void iomm_table_allocate_entry(struct pci_dev *dev, int bar_num) -{ - struct resource *bar_res = &dev->resource[bar_num]; - long bar_size = pci_resource_len(dev, bar_num); - - /* - * No space to allocate, quick exit, skip Allocation. - */ - if (bar_size == 0) - return; - /* - * Set Resource values. - */ - spin_lock(&iomm_table_lock); - bar_res->name = pci_io_text; - bar_res->start = - IOMM_TABLE_ENTRY_SIZE * current_iomm_table_entry; - bar_res->start += BASE_IO_MEMORY; - bar_res->end = bar_res->start + bar_size - 1; - /* - * Allocate the number of table entries needed for BAR. - */ - while (bar_size > 0 ) { - iomm_table[current_iomm_table_entry] = dev->sysdata; - iobar_table[current_iomm_table_entry] = bar_num; - bar_size -= IOMM_TABLE_ENTRY_SIZE; - ++current_iomm_table_entry; - } - max_io_memory = BASE_IO_MEMORY + - (IOMM_TABLE_ENTRY_SIZE * current_iomm_table_entry); - spin_unlock(&iomm_table_lock); -} - -/* - * allocate_device_bars - * - * - Allocates ALL pci_dev BAR's and updates the resources with the - * BAR value. BARS with zero length will have the resources - * The HvCallPci_getBarParms is used to get the size of the BAR - * space. It calls iomm_table_allocate_entry to allocate - * each entry. - * - Loops through The Bar resources(0 - 5) including the ROM - * is resource(6). - */ -static void allocate_device_bars(struct pci_dev *dev) -{ - struct resource *bar_res; - int bar_num; - - for (bar_num = 0; bar_num <= PCI_ROM_RESOURCE; ++bar_num) { - bar_res = &dev->resource[bar_num]; - iomm_table_allocate_entry(dev, bar_num); - } -} - -/* - * Log error information to system console. - * Filter out the device not there errors. - * PCI: EADs Connect Failed 0x18.58.10 Rc: 0x00xx - * PCI: Read Vendor Failed 0x18.58.10 Rc: 0x00xx - * PCI: Connect Bus Unit Failed 0x18.58.10 Rc: 0x00xx - */ -static void pci_Log_Error(char *Error_Text, int Bus, int SubBus, - int AgentId, int HvRc) -{ - if (HvRc == 0x0302) - return; - printk(KERN_ERR "PCI: %s Failed: 0x%02X.%02X.%02X Rc: 0x%04X", - Error_Text, Bus, SubBus, AgentId, HvRc); -} - -/* - * build_device_node(u16 Bus, int SubBus, u8 DevFn) - */ -static struct iSeries_Device_Node *build_device_node(HvBusNumber Bus, - HvSubBusNumber SubBus, int AgentId, int Function) -{ - struct iSeries_Device_Node *node; - - PPCDBG(PPCDBG_BUSWALK, - "-build_device_node 0x%02X.%02X.%02X Function: %02X\n", - Bus, SubBus, AgentId, Function); - - node = kmalloc(sizeof(struct iSeries_Device_Node), GFP_KERNEL); - if (node == NULL) - return NULL; - - memset(node, 0, sizeof(struct iSeries_Device_Node)); - list_add_tail(&node->Device_List, &iSeries_Global_Device_List); -#if 0 - node->DsaAddr = ((u64)Bus << 48) + ((u64)SubBus << 40) + ((u64)0x10 << 32); -#endif - node->DsaAddr.DsaAddr = 0; - node->DsaAddr.Dsa.busNumber = Bus; - node->DsaAddr.Dsa.subBusNumber = SubBus; - node->DsaAddr.Dsa.deviceId = 0x10; - node->DevFn = PCI_DEVFN(ISERIES_ENCODE_DEVICE(AgentId), Function); - return node; -} - -/* - * unsigned long __init find_and_init_phbs(void) - * - * Description: - * This function checks for all possible system PCI host bridges that connect - * PCI buses. The system hypervisor is queried as to the guest partition - * ownership status. A pci_controller is built for any bus which is partially - * owned or fully owned by this guest partition. - */ -unsigned long __init find_and_init_phbs(void) -{ - struct pci_controller *phb; - HvBusNumber bus; - - PPCDBG(PPCDBG_BUSWALK, "find_and_init_phbs Entry\n"); - - /* Check all possible buses. */ - for (bus = 0; bus < 256; bus++) { - int ret = HvCallXm_testBus(bus); - if (ret == 0) { - printk("bus %d appears to exist\n", bus); - - phb = (struct pci_controller *)kmalloc(sizeof(struct pci_controller), GFP_KERNEL); - if (phb == NULL) - return -ENOMEM; - pci_setup_pci_controller(phb); - - phb->pci_mem_offset = phb->local_number = bus; - phb->first_busno = bus; - phb->last_busno = bus; - phb->ops = &iSeries_pci_ops; - - PPCDBG(PPCDBG_BUSWALK, "PCI:Create iSeries pci_controller(%p), Bus: %04X\n", - phb, bus); - - /* Find and connect the devices. */ - scan_PHB_slots(phb); - } - /* - * Check for Unexpected Return code, a clue that something - * has gone wrong. - */ - else if (ret != 0x0301) - printk(KERN_ERR "Unexpected Return on Probe(0x%04X): 0x%04X", - bus, ret); - } - return 0; -} - -/* - * iSeries_pcibios_init - * - * Chance to initialize and structures or variable before PCI Bus walk. - */ -void iSeries_pcibios_init(void) -{ - PPCDBG(PPCDBG_BUSWALK, "iSeries_pcibios_init Entry.\n"); - iomm_table_initialize(); - find_and_init_phbs(); - io_page_mask = -1; - PPCDBG(PPCDBG_BUSWALK, "iSeries_pcibios_init Exit.\n"); -} - -/* - * iSeries_pci_final_fixup(void) - */ -void __init iSeries_pci_final_fixup(void) -{ - struct pci_dev *pdev = NULL; - struct iSeries_Device_Node *node; - int DeviceCount = 0; - - PPCDBG(PPCDBG_BUSWALK, "iSeries_pcibios_fixup Entry.\n"); - - /* Fix up at the device node and pci_dev relationship */ - mf_display_src(0xC9000100); - - printk("pcibios_final_fixup\n"); - for_each_pci_dev(pdev) { - node = find_Device_Node(pdev->bus->number, pdev->devfn); - printk("pci dev %p (%x.%x), node %p\n", pdev, - pdev->bus->number, pdev->devfn, node); - - if (node != NULL) { - ++DeviceCount; - pdev->sysdata = (void *)node; - node->PciDev = pdev; - PPCDBG(PPCDBG_BUSWALK, - "pdev 0x%p <==> DevNode 0x%p\n", - pdev, node); - allocate_device_bars(pdev); - iSeries_Device_Information(pdev, DeviceCount); - iommu_devnode_init_iSeries(node); - } else - printk("PCI: Device Tree not found for 0x%016lX\n", - (unsigned long)pdev); - pdev->irq = node->Irq; - } - iSeries_activate_IRQs(); - mf_display_src(0xC9000200); -} - -void pcibios_fixup_bus(struct pci_bus *PciBus) -{ - PPCDBG(PPCDBG_BUSWALK, "iSeries_pcibios_fixup_bus(0x%04X) Entry.\n", - PciBus->number); -} - -void pcibios_fixup_resources(struct pci_dev *pdev) -{ - PPCDBG(PPCDBG_BUSWALK, "fixup_resources pdev %p\n", pdev); -} - -/* - * Loop through each node function to find usable EADs bridges. - */ -static void scan_PHB_slots(struct pci_controller *Phb) -{ - struct HvCallPci_DeviceInfo *DevInfo; - HvBusNumber bus = Phb->local_number; /* System Bus */ - const HvSubBusNumber SubBus = 0; /* EADs is always 0. */ - int HvRc = 0; - int IdSel; - const int MaxAgents = 8; - - DevInfo = (struct HvCallPci_DeviceInfo*) - kmalloc(sizeof(struct HvCallPci_DeviceInfo), GFP_KERNEL); - if (DevInfo == NULL) - return; - - /* - * Probe for EADs Bridges - */ - for (IdSel = 1; IdSel < MaxAgents; ++IdSel) { - HvRc = HvCallPci_getDeviceInfo(bus, SubBus, IdSel, - ISERIES_HV_ADDR(DevInfo), - sizeof(struct HvCallPci_DeviceInfo)); - if (HvRc == 0) { - if (DevInfo->deviceType == HvCallPci_NodeDevice) - scan_EADS_bridge(bus, SubBus, IdSel); - else - printk("PCI: Invalid System Configuration(0x%02X)" - " for bus 0x%02x id 0x%02x.\n", - DevInfo->deviceType, bus, IdSel); - } - else - pci_Log_Error("getDeviceInfo", bus, SubBus, IdSel, HvRc); - } - kfree(DevInfo); -} - -static void scan_EADS_bridge(HvBusNumber bus, HvSubBusNumber SubBus, - int IdSel) -{ - struct HvCallPci_BridgeInfo *BridgeInfo; - HvAgentId AgentId; - int Function; - int HvRc; - - BridgeInfo = (struct HvCallPci_BridgeInfo *) - kmalloc(sizeof(struct HvCallPci_BridgeInfo), GFP_KERNEL); - if (BridgeInfo == NULL) - return; - - /* Note: hvSubBus and irq is always be 0 at this level! */ - for (Function = 0; Function < 8; ++Function) { - AgentId = ISERIES_PCI_AGENTID(IdSel, Function); - HvRc = HvCallXm_connectBusUnit(bus, SubBus, AgentId, 0); - if (HvRc == 0) { - printk("found device at bus %d idsel %d func %d (AgentId %x)\n", - bus, IdSel, Function, AgentId); - /* Connect EADs: 0x18.00.12 = 0x00 */ - PPCDBG(PPCDBG_BUSWALK, - "PCI:Connect EADs: 0x%02X.%02X.%02X\n", - bus, SubBus, AgentId); - HvRc = HvCallPci_getBusUnitInfo(bus, SubBus, AgentId, - ISERIES_HV_ADDR(BridgeInfo), - sizeof(struct HvCallPci_BridgeInfo)); - if (HvRc == 0) { - printk("bridge info: type %x subbus %x maxAgents %x maxsubbus %x logslot %x\n", - BridgeInfo->busUnitInfo.deviceType, - BridgeInfo->subBusNumber, - BridgeInfo->maxAgents, - BridgeInfo->maxSubBusNumber, - BridgeInfo->logicalSlotNumber); - PPCDBG(PPCDBG_BUSWALK, - "PCI: BridgeInfo, Type:0x%02X, SubBus:0x%02X, MaxAgents:0x%02X, MaxSubBus: 0x%02X, LSlot: 0x%02X\n", - BridgeInfo->busUnitInfo.deviceType, - BridgeInfo->subBusNumber, - BridgeInfo->maxAgents, - BridgeInfo->maxSubBusNumber, - BridgeInfo->logicalSlotNumber); - - if (BridgeInfo->busUnitInfo.deviceType == - HvCallPci_BridgeDevice) { - /* Scan_Bridge_Slot...: 0x18.00.12 */ - scan_bridge_slot(bus, BridgeInfo); - } else - printk("PCI: Invalid Bridge Configuration(0x%02X)", - BridgeInfo->busUnitInfo.deviceType); - } - } else if (HvRc != 0x000B) - pci_Log_Error("EADs Connect", - bus, SubBus, AgentId, HvRc); - } - kfree(BridgeInfo); -} - -/* - * This assumes that the node slot is always on the primary bus! - */ -static int scan_bridge_slot(HvBusNumber Bus, - struct HvCallPci_BridgeInfo *BridgeInfo) -{ - struct iSeries_Device_Node *node; - HvSubBusNumber SubBus = BridgeInfo->subBusNumber; - u16 VendorId = 0; - int HvRc = 0; - u8 Irq = 0; - int IdSel = ISERIES_GET_DEVICE_FROM_SUBBUS(SubBus); - int Function = ISERIES_GET_FUNCTION_FROM_SUBBUS(SubBus); - HvAgentId EADsIdSel = ISERIES_PCI_AGENTID(IdSel, Function); - - /* iSeries_allocate_IRQ.: 0x18.00.12(0xA3) */ - Irq = iSeries_allocate_IRQ(Bus, 0, EADsIdSel); - PPCDBG(PPCDBG_BUSWALK, - "PCI:- allocate and assign IRQ 0x%02X.%02X.%02X = 0x%02X\n", - Bus, 0, EADsIdSel, Irq); - - /* - * Connect all functions of any device found. - */ - for (IdSel = 1; IdSel <= BridgeInfo->maxAgents; ++IdSel) { - for (Function = 0; Function < 8; ++Function) { - HvAgentId AgentId = ISERIES_PCI_AGENTID(IdSel, Function); - HvRc = HvCallXm_connectBusUnit(Bus, SubBus, - AgentId, Irq); - if (HvRc != 0) { - pci_Log_Error("Connect Bus Unit", - Bus, SubBus, AgentId, HvRc); - continue; - } - - HvRc = HvCallPci_configLoad16(Bus, SubBus, AgentId, - PCI_VENDOR_ID, &VendorId); - if (HvRc != 0) { - pci_Log_Error("Read Vendor", - Bus, SubBus, AgentId, HvRc); - continue; - } - printk("read vendor ID: %x\n", VendorId); - - /* FoundDevice: 0x18.28.10 = 0x12AE */ - PPCDBG(PPCDBG_BUSWALK, - "PCI:- FoundDevice: 0x%02X.%02X.%02X = 0x%04X, irq %d\n", - Bus, SubBus, AgentId, VendorId, Irq); - HvRc = HvCallPci_configStore8(Bus, SubBus, AgentId, - PCI_INTERRUPT_LINE, Irq); - if (HvRc != 0) - pci_Log_Error("PciCfgStore Irq Failed!", - Bus, SubBus, AgentId, HvRc); - - ++DeviceCount; - node = build_device_node(Bus, SubBus, EADsIdSel, Function); - node->Irq = Irq; - node->LogicalSlot = BridgeInfo->logicalSlotNumber; - - } /* for (Function = 0; Function < 8; ++Function) */ - } /* for (IdSel = 1; IdSel <= MaxAgents; ++IdSel) */ - return HvRc; -} - -/* - * I/0 Memory copy MUST use mmio commands on iSeries - * To do; For performance, include the hv call directly - */ -void iSeries_memset_io(volatile void __iomem *dest, char c, size_t Count) -{ - u8 ByteValue = c; - long NumberOfBytes = Count; - - while (NumberOfBytes > 0) { - iSeries_Write_Byte(ByteValue, dest++); - -- NumberOfBytes; - } -} -EXPORT_SYMBOL(iSeries_memset_io); - -void iSeries_memcpy_toio(volatile void __iomem *dest, void *source, size_t count) -{ - char *src = source; - long NumberOfBytes = count; - - while (NumberOfBytes > 0) { - iSeries_Write_Byte(*src++, dest++); - -- NumberOfBytes; - } -} -EXPORT_SYMBOL(iSeries_memcpy_toio); - -void iSeries_memcpy_fromio(void *dest, const volatile void __iomem *src, size_t count) -{ - char *dst = dest; - long NumberOfBytes = count; - - while (NumberOfBytes > 0) { - *dst++ = iSeries_Read_Byte(src++); - -- NumberOfBytes; - } -} -EXPORT_SYMBOL(iSeries_memcpy_fromio); - -/* - * Look down the chain to find the matching Device Device - */ -static struct iSeries_Device_Node *find_Device_Node(int bus, int devfn) -{ - struct list_head *pos; - - list_for_each(pos, &iSeries_Global_Device_List) { - struct iSeries_Device_Node *node = - list_entry(pos, struct iSeries_Device_Node, Device_List); - - if ((bus == ISERIES_BUS(node)) && (devfn == node->DevFn)) - return node; - } - return NULL; -} - -#if 0 -/* - * Returns the device node for the passed pci_dev - * Sanity Check Node PciDev to passed pci_dev - * If none is found, returns a NULL which the client must handle. - */ -static struct iSeries_Device_Node *get_Device_Node(struct pci_dev *pdev) -{ - struct iSeries_Device_Node *node; - - node = pdev->sysdata; - if (node == NULL || node->PciDev != pdev) - node = find_Device_Node(pdev->bus->number, pdev->devfn); - return node; -} -#endif - -/* - * Config space read and write functions. - * For now at least, we look for the device node for the bus and devfn - * that we are asked to access. It may be possible to translate the devfn - * to a subbus and deviceid more directly. - */ -static u64 hv_cfg_read_func[4] = { - HvCallPciConfigLoad8, HvCallPciConfigLoad16, - HvCallPciConfigLoad32, HvCallPciConfigLoad32 -}; - -static u64 hv_cfg_write_func[4] = { - HvCallPciConfigStore8, HvCallPciConfigStore16, - HvCallPciConfigStore32, HvCallPciConfigStore32 -}; - -/* - * Read PCI config space - */ -static int iSeries_pci_read_config(struct pci_bus *bus, unsigned int devfn, - int offset, int size, u32 *val) -{ - struct iSeries_Device_Node *node = find_Device_Node(bus->number, devfn); - u64 fn; - struct HvCallPci_LoadReturn ret; - - if (node == NULL) - return PCIBIOS_DEVICE_NOT_FOUND; - if (offset > 255) { - *val = ~0; - return PCIBIOS_BAD_REGISTER_NUMBER; - } - - fn = hv_cfg_read_func[(size - 1) & 3]; - HvCall3Ret16(fn, &ret, node->DsaAddr.DsaAddr, offset, 0); - - if (ret.rc != 0) { - *val = ~0; - return PCIBIOS_DEVICE_NOT_FOUND; /* or something */ - } - - *val = ret.value; - return 0; -} - -/* - * Write PCI config space - */ - -static int iSeries_pci_write_config(struct pci_bus *bus, unsigned int devfn, - int offset, int size, u32 val) -{ - struct iSeries_Device_Node *node = find_Device_Node(bus->number, devfn); - u64 fn; - u64 ret; - - if (node == NULL) - return PCIBIOS_DEVICE_NOT_FOUND; - if (offset > 255) - return PCIBIOS_BAD_REGISTER_NUMBER; - - fn = hv_cfg_write_func[(size - 1) & 3]; - ret = HvCall4(fn, node->DsaAddr.DsaAddr, offset, val, 0); - - if (ret != 0) - return PCIBIOS_DEVICE_NOT_FOUND; - - return 0; -} - -static struct pci_ops iSeries_pci_ops = { - .read = iSeries_pci_read_config, - .write = iSeries_pci_write_config -}; - -/* - * Check Return Code - * -> On Failure, print and log information. - * Increment Retry Count, if exceeds max, panic partition. - * - * PCI: Device 23.90 ReadL I/O Error( 0): 0x1234 - * PCI: Device 23.90 ReadL Retry( 1) - * PCI: Device 23.90 ReadL Retry Successful(1) - */ -static int CheckReturnCode(char *TextHdr, struct iSeries_Device_Node *DevNode, - int *retry, u64 ret) -{ - if (ret != 0) { - ++Pci_Error_Count; - (*retry)++; - printk("PCI: %s: Device 0x%04X:%02X I/O Error(%2d): 0x%04X\n", - TextHdr, DevNode->DsaAddr.Dsa.busNumber, DevNode->DevFn, - *retry, (int)ret); - /* - * Bump the retry and check for retry count exceeded. - * If, Exceeded, panic the system. - */ - if (((*retry) > Pci_Retry_Max) && - (Pci_Error_Flag > 0)) { - mf_display_src(0xB6000103); - panic_timeout = 0; - panic("PCI: Hardware I/O Error, SRC B6000103, " - "Automatic Reboot Disabled.\n"); - } - return -1; /* Retry Try */ - } - return 0; -} - -/* - * Translate the I/O Address into a device node, bar, and bar offset. - * Note: Make sure the passed variable end up on the stack to avoid - * the exposure of being device global. - */ -static inline struct iSeries_Device_Node *xlate_iomm_address( - const volatile void __iomem *IoAddress, - u64 *dsaptr, u64 *BarOffsetPtr) -{ - unsigned long OrigIoAddr; - unsigned long BaseIoAddr; - unsigned long TableIndex; - struct iSeries_Device_Node *DevNode; - - OrigIoAddr = (unsigned long __force)IoAddress; - if ((OrigIoAddr < BASE_IO_MEMORY) || (OrigIoAddr >= max_io_memory)) - return NULL; - BaseIoAddr = OrigIoAddr - BASE_IO_MEMORY; - TableIndex = BaseIoAddr / IOMM_TABLE_ENTRY_SIZE; - DevNode = iomm_table[TableIndex]; - - if (DevNode != NULL) { - int barnum = iobar_table[TableIndex]; - *dsaptr = DevNode->DsaAddr.DsaAddr | (barnum << 24); - *BarOffsetPtr = BaseIoAddr % IOMM_TABLE_ENTRY_SIZE; - } else - panic("PCI: Invalid PCI IoAddress detected!\n"); - return DevNode; -} - -/* - * Read MM I/O Instructions for the iSeries - * On MM I/O error, all ones are returned and iSeries_pci_IoError is cal - * else, data is returned in big Endian format. - * - * iSeries_Read_Byte = Read Byte ( 8 bit) - * iSeries_Read_Word = Read Word (16 bit) - * iSeries_Read_Long = Read Long (32 bit) - */ -u8 iSeries_Read_Byte(const volatile void __iomem *IoAddress) -{ - u64 BarOffset; - u64 dsa; - int retry = 0; - struct HvCallPci_LoadReturn ret; - struct iSeries_Device_Node *DevNode = - xlate_iomm_address(IoAddress, &dsa, &BarOffset); - - if (DevNode == NULL) { - static unsigned long last_jiffies; - static int num_printed; - - if ((jiffies - last_jiffies) > 60 * HZ) { - last_jiffies = jiffies; - num_printed = 0; - } - if (num_printed++ < 10) - printk(KERN_ERR "iSeries_Read_Byte: invalid access at IO address %p\n", IoAddress); - return 0xff; - } - do { - ++Pci_Io_Read_Count; - HvCall3Ret16(HvCallPciBarLoad8, &ret, dsa, BarOffset, 0); - } while (CheckReturnCode("RDB", DevNode, &retry, ret.rc) != 0); - - return (u8)ret.value; -} -EXPORT_SYMBOL(iSeries_Read_Byte); - -u16 iSeries_Read_Word(const volatile void __iomem *IoAddress) -{ - u64 BarOffset; - u64 dsa; - int retry = 0; - struct HvCallPci_LoadReturn ret; - struct iSeries_Device_Node *DevNode = - xlate_iomm_address(IoAddress, &dsa, &BarOffset); - - if (DevNode == NULL) { - static unsigned long last_jiffies; - static int num_printed; - - if ((jiffies - last_jiffies) > 60 * HZ) { - last_jiffies = jiffies; - num_printed = 0; - } - if (num_printed++ < 10) - printk(KERN_ERR "iSeries_Read_Word: invalid access at IO address %p\n", IoAddress); - return 0xffff; - } - do { - ++Pci_Io_Read_Count; - HvCall3Ret16(HvCallPciBarLoad16, &ret, dsa, - BarOffset, 0); - } while (CheckReturnCode("RDW", DevNode, &retry, ret.rc) != 0); - - return swab16((u16)ret.value); -} -EXPORT_SYMBOL(iSeries_Read_Word); - -u32 iSeries_Read_Long(const volatile void __iomem *IoAddress) -{ - u64 BarOffset; - u64 dsa; - int retry = 0; - struct HvCallPci_LoadReturn ret; - struct iSeries_Device_Node *DevNode = - xlate_iomm_address(IoAddress, &dsa, &BarOffset); - - if (DevNode == NULL) { - static unsigned long last_jiffies; - static int num_printed; - - if ((jiffies - last_jiffies) > 60 * HZ) { - last_jiffies = jiffies; - num_printed = 0; - } - if (num_printed++ < 10) - printk(KERN_ERR "iSeries_Read_Long: invalid access at IO address %p\n", IoAddress); - return 0xffffffff; - } - do { - ++Pci_Io_Read_Count; - HvCall3Ret16(HvCallPciBarLoad32, &ret, dsa, - BarOffset, 0); - } while (CheckReturnCode("RDL", DevNode, &retry, ret.rc) != 0); - - return swab32((u32)ret.value); -} -EXPORT_SYMBOL(iSeries_Read_Long); - -/* - * Write MM I/O Instructions for the iSeries - * - * iSeries_Write_Byte = Write Byte (8 bit) - * iSeries_Write_Word = Write Word(16 bit) - * iSeries_Write_Long = Write Long(32 bit) - */ -void iSeries_Write_Byte(u8 data, volatile void __iomem *IoAddress) -{ - u64 BarOffset; - u64 dsa; - int retry = 0; - u64 rc; - struct iSeries_Device_Node *DevNode = - xlate_iomm_address(IoAddress, &dsa, &BarOffset); - - if (DevNode == NULL) { - static unsigned long last_jiffies; - static int num_printed; - - if ((jiffies - last_jiffies) > 60 * HZ) { - last_jiffies = jiffies; - num_printed = 0; - } - if (num_printed++ < 10) - printk(KERN_ERR "iSeries_Write_Byte: invalid access at IO address %p\n", IoAddress); - return; - } - do { - ++Pci_Io_Write_Count; - rc = HvCall4(HvCallPciBarStore8, dsa, BarOffset, data, 0); - } while (CheckReturnCode("WWB", DevNode, &retry, rc) != 0); -} -EXPORT_SYMBOL(iSeries_Write_Byte); - -void iSeries_Write_Word(u16 data, volatile void __iomem *IoAddress) -{ - u64 BarOffset; - u64 dsa; - int retry = 0; - u64 rc; - struct iSeries_Device_Node *DevNode = - xlate_iomm_address(IoAddress, &dsa, &BarOffset); - - if (DevNode == NULL) { - static unsigned long last_jiffies; - static int num_printed; - - if ((jiffies - last_jiffies) > 60 * HZ) { - last_jiffies = jiffies; - num_printed = 0; - } - if (num_printed++ < 10) - printk(KERN_ERR "iSeries_Write_Word: invalid access at IO address %p\n", IoAddress); - return; - } - do { - ++Pci_Io_Write_Count; - rc = HvCall4(HvCallPciBarStore16, dsa, BarOffset, swab16(data), 0); - } while (CheckReturnCode("WWW", DevNode, &retry, rc) != 0); -} -EXPORT_SYMBOL(iSeries_Write_Word); - -void iSeries_Write_Long(u32 data, volatile void __iomem *IoAddress) -{ - u64 BarOffset; - u64 dsa; - int retry = 0; - u64 rc; - struct iSeries_Device_Node *DevNode = - xlate_iomm_address(IoAddress, &dsa, &BarOffset); - - if (DevNode == NULL) { - static unsigned long last_jiffies; - static int num_printed; - - if ((jiffies - last_jiffies) > 60 * HZ) { - last_jiffies = jiffies; - num_printed = 0; - } - if (num_printed++ < 10) - printk(KERN_ERR "iSeries_Write_Long: invalid access at IO address %p\n", IoAddress); - return; - } - do { - ++Pci_Io_Write_Count; - rc = HvCall4(HvCallPciBarStore32, dsa, BarOffset, swab32(data), 0); - } while (CheckReturnCode("WWL", DevNode, &retry, rc) != 0); -} -EXPORT_SYMBOL(iSeries_Write_Long); diff --git a/arch/ppc64/kernel/maple_pci.c b/arch/ppc64/kernel/maple_pci.c --- a/arch/ppc64/kernel/maple_pci.c +++ b/arch/ppc64/kernel/maple_pci.c @@ -23,8 +23,7 @@ #include #include #include - -#include "pci.h" +#include #ifdef DEBUG #define DBG(x...) printk(x) diff --git a/arch/ppc64/kernel/pSeries_iommu.c b/arch/ppc64/kernel/pSeries_iommu.c --- a/arch/ppc64/kernel/pSeries_iommu.c +++ b/arch/ppc64/kernel/pSeries_iommu.c @@ -47,7 +47,7 @@ #include #include #include -#include "pci.h" +#include #define DBG(fmt...) diff --git a/arch/ppc64/kernel/pSeries_pci.c b/arch/ppc64/kernel/pSeries_pci.c --- a/arch/ppc64/kernel/pSeries_pci.c +++ b/arch/ppc64/kernel/pSeries_pci.c @@ -29,8 +29,7 @@ #include #include - -#include "pci.h" +#include static int __initdata s7a_workaround = -1; diff --git a/arch/ppc64/kernel/pSeries_setup.c b/arch/ppc64/kernel/pSeries_setup.c --- a/arch/ppc64/kernel/pSeries_setup.c +++ b/arch/ppc64/kernel/pSeries_setup.c @@ -63,9 +63,9 @@ #include #include #include +#include #include "i8259.h" -#include "pci.h" #ifdef DEBUG #define DBG(fmt...) udbg_printf(fmt) diff --git a/arch/ppc64/kernel/pci.c b/arch/ppc64/kernel/pci.c --- a/arch/ppc64/kernel/pci.c +++ b/arch/ppc64/kernel/pci.c @@ -31,8 +31,7 @@ #include #include #include - -#include "pci.h" +#include #ifdef DEBUG #define DBG(fmt...) udbg_printf(fmt) diff --git a/arch/ppc64/kernel/pci.h b/arch/ppc64/kernel/pci.h deleted file mode 100644 --- a/arch/ppc64/kernel/pci.h +++ /dev/null @@ -1,54 +0,0 @@ -/* - * c 2001 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. - */ -#ifndef __PPC_KERNEL_PCI_H__ -#define __PPC_KERNEL_PCI_H__ - -#include -#include - -extern unsigned long isa_io_base; - -extern void pci_setup_pci_controller(struct pci_controller *hose); -extern void pci_setup_phb_io(struct pci_controller *hose, int primary); -extern void pci_setup_phb_io_dynamic(struct pci_controller *hose, int primary); - - -extern struct list_head hose_list; -extern int global_phb_number; - -extern unsigned long find_and_init_phbs(void); - -extern struct pci_dev *ppc64_isabridge_dev; /* may be NULL if no ISA bus */ - -/* PCI device_node operations */ -struct device_node; -typedef void *(*traverse_func)(struct device_node *me, void *data); -void *traverse_pci_devices(struct device_node *start, traverse_func pre, - void *data); - -void pci_devs_phb_init(void); -void pci_devs_phb_init_dynamic(struct pci_controller *phb); - -/* PCI address cache management routines */ -void pci_addr_cache_insert_device(struct pci_dev *dev); -void pci_addr_cache_remove_device(struct pci_dev *dev); - -/* From rtas_pci.h */ -void init_pci_config_tokens (void); -unsigned long get_phb_buid (struct device_node *); - -/* From pSeries_pci.h */ -extern void pSeries_final_fixup(void); -extern void pSeries_irq_bus_setup(struct pci_bus *bus); - -extern unsigned long pci_probe_only; -extern unsigned long pci_assign_all_buses; -extern int pci_read_irq_line(struct pci_dev *pci_dev); - -#endif /* __PPC_KERNEL_PCI_H__ */ diff --git a/arch/ppc64/kernel/pci_direct_iommu.c b/arch/ppc64/kernel/pci_direct_iommu.c --- a/arch/ppc64/kernel/pci_direct_iommu.c +++ b/arch/ppc64/kernel/pci_direct_iommu.c @@ -27,8 +27,7 @@ #include #include #include - -#include "pci.h" +#include static void *pci_direct_alloc_coherent(struct device *hwdev, size_t size, dma_addr_t *dma_handle, unsigned int __nocast flag) diff --git a/arch/ppc64/kernel/pci_dn.c b/arch/ppc64/kernel/pci_dn.c --- a/arch/ppc64/kernel/pci_dn.c +++ b/arch/ppc64/kernel/pci_dn.c @@ -30,8 +30,7 @@ #include #include #include - -#include "pci.h" +#include /* * Traverse_func that inits the PCI fields of the device node. diff --git a/arch/ppc64/kernel/pci_iommu.c b/arch/ppc64/kernel/pci_iommu.c --- a/arch/ppc64/kernel/pci_iommu.c +++ b/arch/ppc64/kernel/pci_iommu.c @@ -37,7 +37,7 @@ #include #include #include -#include "pci.h" +#include #ifdef CONFIG_PPC_ISERIES #include diff --git a/arch/ppc64/kernel/pmac_pci.c b/arch/ppc64/kernel/pmac_pci.c --- a/arch/ppc64/kernel/pmac_pci.c +++ b/arch/ppc64/kernel/pmac_pci.c @@ -27,8 +27,8 @@ #include #include #include +#include -#include "pci.h" #include "pmac.h" #define DEBUG diff --git a/arch/ppc64/kernel/rtas_pci.c b/arch/ppc64/kernel/rtas_pci.c --- a/arch/ppc64/kernel/rtas_pci.c +++ b/arch/ppc64/kernel/rtas_pci.c @@ -39,8 +39,7 @@ #include #include #include - -#include "pci.h" +#include /* RTAS tokens */ static int read_pci_config; diff --git a/arch/ppc64/kernel/sys_ppc32.c b/arch/ppc64/kernel/sys_ppc32.c --- a/arch/ppc64/kernel/sys_ppc32.c +++ b/arch/ppc64/kernel/sys_ppc32.c @@ -53,8 +53,7 @@ #include #include #include - -#include "pci.h" +#include /* readdir & getdents */ #define NAME_OFFSET(de) ((int) ((de)->d_name - (char __user *) (de))) diff --git a/arch/ppc64/kernel/u3_iommu.c b/arch/ppc64/kernel/u3_iommu.c --- a/arch/ppc64/kernel/u3_iommu.c +++ b/arch/ppc64/kernel/u3_iommu.c @@ -45,8 +45,7 @@ #include #include #include - -#include "pci.h" +#include extern int iommu_force_on; diff --git a/include/asm-powerpc/ppc-pci.h b/include/asm-powerpc/ppc-pci.h new file mode 100644 --- /dev/null +++ b/include/asm-powerpc/ppc-pci.h @@ -0,0 +1,54 @@ +/* + * c 2001 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. + */ +#ifndef _ASM_POWERPC_PPC_PCI_H +#define _ASM_POWERPC_PPC_PCI_H + +#include +#include + +extern unsigned long isa_io_base; + +extern void pci_setup_pci_controller(struct pci_controller *hose); +extern void pci_setup_phb_io(struct pci_controller *hose, int primary); +extern void pci_setup_phb_io_dynamic(struct pci_controller *hose, int primary); + + +extern struct list_head hose_list; +extern int global_phb_number; + +extern unsigned long find_and_init_phbs(void); + +extern struct pci_dev *ppc64_isabridge_dev; /* may be NULL if no ISA bus */ + +/* PCI device_node operations */ +struct device_node; +typedef void *(*traverse_func)(struct device_node *me, void *data); +void *traverse_pci_devices(struct device_node *start, traverse_func pre, + void *data); + +void pci_devs_phb_init(void); +void pci_devs_phb_init_dynamic(struct pci_controller *phb); + +/* PCI address cache management routines */ +void pci_addr_cache_insert_device(struct pci_dev *dev); +void pci_addr_cache_remove_device(struct pci_dev *dev); + +/* From rtas_pci.h */ +void init_pci_config_tokens (void); +unsigned long get_phb_buid (struct device_node *); + +/* From pSeries_pci.h */ +extern void pSeries_final_fixup(void); +extern void pSeries_irq_bus_setup(struct pci_bus *bus); + +extern unsigned long pci_probe_only; +extern unsigned long pci_assign_all_buses; +extern int pci_read_irq_line(struct pci_dev *pci_dev); + +#endif /* _ASM_POWERPC_PPC_PCI_H */ From sfr at canb.auug.org.au Wed Sep 28 16:57:10 2005 From: sfr at canb.auug.org.au (Stephen Rothwell) Date: Wed, 28 Sep 2005 16:57:10 +1000 Subject: [PATCH 12/19] powerpc: Move iSeries_irq.c to powerpc/platorms/iseries In-Reply-To: <20050928163333.02799419.sfr@canb.auug.org.au> References: <20050928163333.02799419.sfr@canb.auug.org.au> Message-ID: <20050928165710.0bfac922.sfr@canb.auug.org.au> And rename it to irq.c. Signed-off-by: Stephen Rothwell --- arch/powerpc/platforms/iseries/Makefile | 2 arch/powerpc/platforms/iseries/irq.c | 365 +++++++++++++++++++++++++++++++ arch/ppc64/kernel/Makefile | 3 arch/ppc64/kernel/iSeries_irq.c | 366 ------------------------------- 4 files changed, 367 insertions(+), 369 deletions(-) create mode 100644 arch/powerpc/platforms/iseries/irq.c delete mode 100644 arch/ppc64/kernel/iSeries_irq.c -- Cheers, Stephen Rothwell sfr at canb.auug.org.au http://www.canb.auug.org.au/~sfr/ cb4cf8056ead24ef0595859952319e2a608d5e07 diff --git a/arch/powerpc/platforms/iseries/Makefile b/arch/powerpc/platforms/iseries/Makefile --- a/arch/powerpc/platforms/iseries/Makefile +++ b/arch/powerpc/platforms/iseries/Makefile @@ -1,3 +1,3 @@ obj-y += hvlog.o hvlpconfig.o lpardata.o setup.o mf.o lpevents.o \ hvcall.o proc.o htab.o iommu.o -obj-$(CONFIG_PCI) += pci.o +obj-$(CONFIG_PCI) += pci.o irq.o diff --git a/arch/powerpc/platforms/iseries/irq.c b/arch/powerpc/platforms/iseries/irq.c new file mode 100644 --- /dev/null +++ b/arch/powerpc/platforms/iseries/irq.c @@ -0,0 +1,365 @@ +/* + * This module supports the iSeries PCI bus interrupt handling + * Copyright (C) 20yy + * Copyright (C) 2004-2005 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 + * + * Change Activity: + * Created, December 13, 2000 by Wayne Holm + * End Change Activity + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +/* This maps virtual irq numbers to real irqs */ +unsigned int virt_irq_to_real_map[NR_IRQS]; + +/* The next available virtual irq number */ +/* Note: the pcnet32 driver assumes irq numbers < 2 aren't valid. :( */ +static int next_virtual_irq = 2; + +static long Pci_Interrupt_Count; +static long Pci_Event_Count; + +enum XmPciLpEvent_Subtype { + XmPciLpEvent_BusCreated = 0, // PHB has been created + XmPciLpEvent_BusError = 1, // PHB has failed + XmPciLpEvent_BusFailed = 2, // Msg to Secondary, Primary failed bus + XmPciLpEvent_NodeFailed = 4, // Multi-adapter bridge has failed + XmPciLpEvent_NodeRecovered = 5, // Multi-adapter bridge has recovered + XmPciLpEvent_BusRecovered = 12, // PHB has been recovered + XmPciLpEvent_UnQuiesceBus = 18, // Secondary bus unqiescing + XmPciLpEvent_BridgeError = 21, // Bridge Error + XmPciLpEvent_SlotInterrupt = 22 // Slot interrupt +}; + +struct XmPciLpEvent_BusInterrupt { + HvBusNumber busNumber; + HvSubBusNumber subBusNumber; +}; + +struct XmPciLpEvent_NodeInterrupt { + HvBusNumber busNumber; + HvSubBusNumber subBusNumber; + HvAgentId deviceId; +}; + +struct XmPciLpEvent { + struct HvLpEvent hvLpEvent; + + union { + u64 alignData; // Align on an 8-byte boundary + + struct { + u32 fisr; + HvBusNumber busNumber; + HvSubBusNumber subBusNumber; + HvAgentId deviceId; + } slotInterrupt; + + struct XmPciLpEvent_BusInterrupt busFailed; + struct XmPciLpEvent_BusInterrupt busRecovered; + struct XmPciLpEvent_BusInterrupt busCreated; + + struct XmPciLpEvent_NodeInterrupt nodeFailed; + struct XmPciLpEvent_NodeInterrupt nodeRecovered; + + } eventData; + +}; + +static void intReceived(struct XmPciLpEvent *eventParm, + struct pt_regs *regsParm) +{ + int irq; + + ++Pci_Interrupt_Count; + + switch (eventParm->hvLpEvent.xSubtype) { + case XmPciLpEvent_SlotInterrupt: + irq = eventParm->hvLpEvent.xCorrelationToken; + /* Dispatch the interrupt handlers for this irq */ + ppc_irq_dispatch_handler(regsParm, irq); + HvCallPci_eoi(eventParm->eventData.slotInterrupt.busNumber, + eventParm->eventData.slotInterrupt.subBusNumber, + eventParm->eventData.slotInterrupt.deviceId); + break; + /* Ignore error recovery events for now */ + case XmPciLpEvent_BusCreated: + printk(KERN_INFO "intReceived: system bus %d created\n", + eventParm->eventData.busCreated.busNumber); + break; + case XmPciLpEvent_BusError: + case XmPciLpEvent_BusFailed: + printk(KERN_INFO "intReceived: system bus %d failed\n", + eventParm->eventData.busFailed.busNumber); + break; + case XmPciLpEvent_BusRecovered: + case XmPciLpEvent_UnQuiesceBus: + printk(KERN_INFO "intReceived: system bus %d recovered\n", + eventParm->eventData.busRecovered.busNumber); + break; + case XmPciLpEvent_NodeFailed: + case XmPciLpEvent_BridgeError: + printk(KERN_INFO + "intReceived: multi-adapter bridge %d/%d/%d failed\n", + eventParm->eventData.nodeFailed.busNumber, + eventParm->eventData.nodeFailed.subBusNumber, + eventParm->eventData.nodeFailed.deviceId); + break; + case XmPciLpEvent_NodeRecovered: + printk(KERN_INFO + "intReceived: multi-adapter bridge %d/%d/%d recovered\n", + eventParm->eventData.nodeRecovered.busNumber, + eventParm->eventData.nodeRecovered.subBusNumber, + eventParm->eventData.nodeRecovered.deviceId); + break; + default: + printk(KERN_ERR + "intReceived: unrecognized event subtype 0x%x\n", + eventParm->hvLpEvent.xSubtype); + break; + } +} + +static void XmPciLpEvent_handler(struct HvLpEvent *eventParm, + struct pt_regs *regsParm) +{ +#ifdef CONFIG_PCI + ++Pci_Event_Count; + + if (eventParm && (eventParm->xType == HvLpEvent_Type_PciIo)) { + switch (eventParm->xFlags.xFunction) { + case HvLpEvent_Function_Int: + intReceived((struct XmPciLpEvent *)eventParm, regsParm); + break; + case HvLpEvent_Function_Ack: + printk(KERN_ERR + "XmPciLpEvent_handler: unexpected ack received\n"); + break; + default: + printk(KERN_ERR + "XmPciLpEvent_handler: unexpected event function %d\n", + (int)eventParm->xFlags.xFunction); + break; + } + } else if (eventParm) + printk(KERN_ERR + "XmPciLpEvent_handler: Unrecognized PCI event type 0x%x\n", + (int)eventParm->xType); + else + printk(KERN_ERR "XmPciLpEvent_handler: NULL event received\n"); +#endif +} + +/* + * This is called by init_IRQ. set in ppc_md.init_IRQ by iSeries_setup.c + * It must be called before the bus walk. + */ +void __init iSeries_init_IRQ(void) +{ + /* Register PCI event handler and open an event path */ + int xRc; + + xRc = HvLpEvent_registerHandler(HvLpEvent_Type_PciIo, + &XmPciLpEvent_handler); + if (xRc == 0) { + xRc = HvLpEvent_openPath(HvLpEvent_Type_PciIo, 0); + if (xRc != 0) + printk(KERN_ERR "iSeries_init_IRQ: open event path " + "failed with rc 0x%x\n", xRc); + } else + printk(KERN_ERR "iSeries_init_IRQ: register handler " + "failed with rc 0x%x\n", xRc); +} + +#define REAL_IRQ_TO_BUS(irq) ((((irq) >> 6) & 0xff) + 1) +#define REAL_IRQ_TO_IDSEL(irq) ((((irq) >> 3) & 7) + 1) +#define REAL_IRQ_TO_FUNC(irq) ((irq) & 7) + +/* + * This will be called by device drivers (via enable_IRQ) + * to enable INTA in the bridge interrupt status register. + */ +static void iSeries_enable_IRQ(unsigned int irq) +{ + u32 bus, deviceId, function, mask; + const u32 subBus = 0; + unsigned int rirq = virt_irq_to_real_map[irq]; + + /* The IRQ has already been locked by the caller */ + bus = REAL_IRQ_TO_BUS(rirq); + function = REAL_IRQ_TO_FUNC(rirq); + deviceId = (REAL_IRQ_TO_IDSEL(rirq) << 4) + function; + + /* Unmask secondary INTA */ + mask = 0x80000000; + HvCallPci_unmaskInterrupts(bus, subBus, deviceId, mask); + PPCDBG(PPCDBG_BUSWALK, "iSeries_enable_IRQ 0x%02X.%02X.%02X 0x%04X\n", + bus, subBus, deviceId, irq); +} + +/* This is called by iSeries_activate_IRQs */ +static unsigned int iSeries_startup_IRQ(unsigned int irq) +{ + u32 bus, deviceId, function, mask; + const u32 subBus = 0; + unsigned int rirq = virt_irq_to_real_map[irq]; + + bus = REAL_IRQ_TO_BUS(rirq); + function = REAL_IRQ_TO_FUNC(rirq); + deviceId = (REAL_IRQ_TO_IDSEL(rirq) << 4) + function; + + /* Link the IRQ number to the bridge */ + HvCallXm_connectBusUnit(bus, subBus, deviceId, irq); + + /* Unmask bridge interrupts in the FISR */ + mask = 0x01010000 << function; + HvCallPci_unmaskFisr(bus, subBus, deviceId, mask); + iSeries_enable_IRQ(irq); + return 0; +} + +/* + * This is called out of iSeries_fixup to activate interrupt + * generation for usable slots + */ +void __init iSeries_activate_IRQs() +{ + int irq; + unsigned long flags; + + for_each_irq (irq) { + irq_desc_t *desc = get_irq_desc(irq); + + if (desc && desc->handler && desc->handler->startup) { + spin_lock_irqsave(&desc->lock, flags); + desc->handler->startup(irq); + spin_unlock_irqrestore(&desc->lock, flags); + } + } +} + +/* this is not called anywhere currently */ +static void iSeries_shutdown_IRQ(unsigned int irq) +{ + u32 bus, deviceId, function, mask; + const u32 subBus = 0; + unsigned int rirq = virt_irq_to_real_map[irq]; + + /* irq should be locked by the caller */ + bus = REAL_IRQ_TO_BUS(rirq); + function = REAL_IRQ_TO_FUNC(rirq); + deviceId = (REAL_IRQ_TO_IDSEL(rirq) << 4) + function; + + /* Invalidate the IRQ number in the bridge */ + HvCallXm_connectBusUnit(bus, subBus, deviceId, 0); + + /* Mask bridge interrupts in the FISR */ + mask = 0x01010000 << function; + HvCallPci_maskFisr(bus, subBus, deviceId, mask); +} + +/* + * This will be called by device drivers (via disable_IRQ) + * to disable INTA in the bridge interrupt status register. + */ +static void iSeries_disable_IRQ(unsigned int irq) +{ + u32 bus, deviceId, function, mask; + const u32 subBus = 0; + unsigned int rirq = virt_irq_to_real_map[irq]; + + /* The IRQ has already been locked by the caller */ + bus = REAL_IRQ_TO_BUS(rirq); + function = REAL_IRQ_TO_FUNC(rirq); + deviceId = (REAL_IRQ_TO_IDSEL(rirq) << 4) + function; + + /* Mask secondary INTA */ + mask = 0x80000000; + HvCallPci_maskInterrupts(bus, subBus, deviceId, mask); + PPCDBG(PPCDBG_BUSWALK, "iSeries_disable_IRQ 0x%02X.%02X.%02X 0x%04X\n", + bus, subBus, deviceId, irq); +} + +/* + * Need to define this so ppc_irq_dispatch_handler will NOT call + * enable_IRQ at the end of interrupt handling. However, this does + * nothing because there is not enough information provided to do + * the EOI HvCall. This is done by XmPciLpEvent.c + */ +static void iSeries_end_IRQ(unsigned int irq) +{ +} + +static hw_irq_controller iSeries_IRQ_handler = { + .typename = "iSeries irq controller", + .startup = iSeries_startup_IRQ, + .shutdown = iSeries_shutdown_IRQ, + .enable = iSeries_enable_IRQ, + .disable = iSeries_disable_IRQ, + .end = iSeries_end_IRQ +}; + +/* + * This is called out of iSeries_scan_slot to allocate an IRQ for an EADS slot + * It calculates the irq value for the slot. + * Note that subBusNumber is always 0 (at the moment at least). + */ +int __init iSeries_allocate_IRQ(HvBusNumber busNumber, + HvSubBusNumber subBusNumber, HvAgentId deviceId) +{ + unsigned int realirq, virtirq; + u8 idsel = (deviceId >> 4); + u8 function = deviceId & 7; + + virtirq = next_virtual_irq++; + realirq = ((busNumber - 1) << 6) + ((idsel - 1) << 3) + function; + virt_irq_to_real_map[virtirq] = realirq; + + irq_desc[virtirq].handler = &iSeries_IRQ_handler; + return virtirq; +} + +int virt_irq_create_mapping(unsigned int real_irq) +{ + BUG(); /* Don't call this on iSeries, yet */ + + return 0; +} + +void virt_irq_init(void) +{ + return; +} diff --git a/arch/ppc64/kernel/Makefile b/arch/ppc64/kernel/Makefile --- a/arch/ppc64/kernel/Makefile +++ b/arch/ppc64/kernel/Makefile @@ -16,8 +16,7 @@ obj-y += vdso32/ vdso64/ obj-$(CONFIG_PPC_OF) += of_device.o -pci-obj-$(CONFIG_PPC_ISERIES) += iSeries_irq.o \ - iSeries_VpdInfo.o +pci-obj-$(CONFIG_PPC_ISERIES) += iSeries_VpdInfo.o pci-obj-$(CONFIG_PPC_MULTIPLATFORM) += pci_dn.o pci_direct_iommu.o obj-$(CONFIG_PCI) += pci.o pci_iommu.o iomap.o $(pci-obj-y) diff --git a/arch/ppc64/kernel/iSeries_irq.c b/arch/ppc64/kernel/iSeries_irq.c deleted file mode 100644 --- a/arch/ppc64/kernel/iSeries_irq.c +++ /dev/null @@ -1,366 +0,0 @@ -/* - * This module supports the iSeries PCI bus interrupt handling - * Copyright (C) 20yy - * Copyright (C) 2004-2005 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 - * - * Change Activity: - * Created, December 13, 2000 by Wayne Holm - * End Change Activity - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -/* This maps virtual irq numbers to real irqs */ -unsigned int virt_irq_to_real_map[NR_IRQS]; - -/* The next available virtual irq number */ -/* Note: the pcnet32 driver assumes irq numbers < 2 aren't valid. :( */ -static int next_virtual_irq = 2; - -static long Pci_Interrupt_Count; -static long Pci_Event_Count; - -enum XmPciLpEvent_Subtype { - XmPciLpEvent_BusCreated = 0, // PHB has been created - XmPciLpEvent_BusError = 1, // PHB has failed - XmPciLpEvent_BusFailed = 2, // Msg to Secondary, Primary failed bus - XmPciLpEvent_NodeFailed = 4, // Multi-adapter bridge has failed - XmPciLpEvent_NodeRecovered = 5, // Multi-adapter bridge has recovered - XmPciLpEvent_BusRecovered = 12, // PHB has been recovered - XmPciLpEvent_UnQuiesceBus = 18, // Secondary bus unqiescing - XmPciLpEvent_BridgeError = 21, // Bridge Error - XmPciLpEvent_SlotInterrupt = 22 // Slot interrupt -}; - -struct XmPciLpEvent_BusInterrupt { - HvBusNumber busNumber; - HvSubBusNumber subBusNumber; -}; - -struct XmPciLpEvent_NodeInterrupt { - HvBusNumber busNumber; - HvSubBusNumber subBusNumber; - HvAgentId deviceId; -}; - -struct XmPciLpEvent { - struct HvLpEvent hvLpEvent; - - union { - u64 alignData; // Align on an 8-byte boundary - - struct { - u32 fisr; - HvBusNumber busNumber; - HvSubBusNumber subBusNumber; - HvAgentId deviceId; - } slotInterrupt; - - struct XmPciLpEvent_BusInterrupt busFailed; - struct XmPciLpEvent_BusInterrupt busRecovered; - struct XmPciLpEvent_BusInterrupt busCreated; - - struct XmPciLpEvent_NodeInterrupt nodeFailed; - struct XmPciLpEvent_NodeInterrupt nodeRecovered; - - } eventData; - -}; - -static void intReceived(struct XmPciLpEvent *eventParm, - struct pt_regs *regsParm) -{ - int irq; - - ++Pci_Interrupt_Count; - - switch (eventParm->hvLpEvent.xSubtype) { - case XmPciLpEvent_SlotInterrupt: - irq = eventParm->hvLpEvent.xCorrelationToken; - /* Dispatch the interrupt handlers for this irq */ - ppc_irq_dispatch_handler(regsParm, irq); - HvCallPci_eoi(eventParm->eventData.slotInterrupt.busNumber, - eventParm->eventData.slotInterrupt.subBusNumber, - eventParm->eventData.slotInterrupt.deviceId); - break; - /* Ignore error recovery events for now */ - case XmPciLpEvent_BusCreated: - printk(KERN_INFO "intReceived: system bus %d created\n", - eventParm->eventData.busCreated.busNumber); - break; - case XmPciLpEvent_BusError: - case XmPciLpEvent_BusFailed: - printk(KERN_INFO "intReceived: system bus %d failed\n", - eventParm->eventData.busFailed.busNumber); - break; - case XmPciLpEvent_BusRecovered: - case XmPciLpEvent_UnQuiesceBus: - printk(KERN_INFO "intReceived: system bus %d recovered\n", - eventParm->eventData.busRecovered.busNumber); - break; - case XmPciLpEvent_NodeFailed: - case XmPciLpEvent_BridgeError: - printk(KERN_INFO - "intReceived: multi-adapter bridge %d/%d/%d failed\n", - eventParm->eventData.nodeFailed.busNumber, - eventParm->eventData.nodeFailed.subBusNumber, - eventParm->eventData.nodeFailed.deviceId); - break; - case XmPciLpEvent_NodeRecovered: - printk(KERN_INFO - "intReceived: multi-adapter bridge %d/%d/%d recovered\n", - eventParm->eventData.nodeRecovered.busNumber, - eventParm->eventData.nodeRecovered.subBusNumber, - eventParm->eventData.nodeRecovered.deviceId); - break; - default: - printk(KERN_ERR - "intReceived: unrecognized event subtype 0x%x\n", - eventParm->hvLpEvent.xSubtype); - break; - } -} - -static void XmPciLpEvent_handler(struct HvLpEvent *eventParm, - struct pt_regs *regsParm) -{ -#ifdef CONFIG_PCI - ++Pci_Event_Count; - - if (eventParm && (eventParm->xType == HvLpEvent_Type_PciIo)) { - switch (eventParm->xFlags.xFunction) { - case HvLpEvent_Function_Int: - intReceived((struct XmPciLpEvent *)eventParm, regsParm); - break; - case HvLpEvent_Function_Ack: - printk(KERN_ERR - "XmPciLpEvent_handler: unexpected ack received\n"); - break; - default: - printk(KERN_ERR - "XmPciLpEvent_handler: unexpected event function %d\n", - (int)eventParm->xFlags.xFunction); - break; - } - } else if (eventParm) - printk(KERN_ERR - "XmPciLpEvent_handler: Unrecognized PCI event type 0x%x\n", - (int)eventParm->xType); - else - printk(KERN_ERR "XmPciLpEvent_handler: NULL event received\n"); -#endif -} - -/* - * This is called by init_IRQ. set in ppc_md.init_IRQ by iSeries_setup.c - * It must be called before the bus walk. - */ -void __init iSeries_init_IRQ(void) -{ - /* Register PCI event handler and open an event path */ - int xRc; - - xRc = HvLpEvent_registerHandler(HvLpEvent_Type_PciIo, - &XmPciLpEvent_handler); - if (xRc == 0) { - xRc = HvLpEvent_openPath(HvLpEvent_Type_PciIo, 0); - if (xRc != 0) - printk(KERN_ERR "iSeries_init_IRQ: open event path " - "failed with rc 0x%x\n", xRc); - } else - printk(KERN_ERR "iSeries_init_IRQ: register handler " - "failed with rc 0x%x\n", xRc); -} - -#define REAL_IRQ_TO_BUS(irq) ((((irq) >> 6) & 0xff) + 1) -#define REAL_IRQ_TO_IDSEL(irq) ((((irq) >> 3) & 7) + 1) -#define REAL_IRQ_TO_FUNC(irq) ((irq) & 7) - -/* - * This will be called by device drivers (via enable_IRQ) - * to enable INTA in the bridge interrupt status register. - */ -static void iSeries_enable_IRQ(unsigned int irq) -{ - u32 bus, deviceId, function, mask; - const u32 subBus = 0; - unsigned int rirq = virt_irq_to_real_map[irq]; - - /* The IRQ has already been locked by the caller */ - bus = REAL_IRQ_TO_BUS(rirq); - function = REAL_IRQ_TO_FUNC(rirq); - deviceId = (REAL_IRQ_TO_IDSEL(rirq) << 4) + function; - - /* Unmask secondary INTA */ - mask = 0x80000000; - HvCallPci_unmaskInterrupts(bus, subBus, deviceId, mask); - PPCDBG(PPCDBG_BUSWALK, "iSeries_enable_IRQ 0x%02X.%02X.%02X 0x%04X\n", - bus, subBus, deviceId, irq); -} - -/* This is called by iSeries_activate_IRQs */ -static unsigned int iSeries_startup_IRQ(unsigned int irq) -{ - u32 bus, deviceId, function, mask; - const u32 subBus = 0; - unsigned int rirq = virt_irq_to_real_map[irq]; - - bus = REAL_IRQ_TO_BUS(rirq); - function = REAL_IRQ_TO_FUNC(rirq); - deviceId = (REAL_IRQ_TO_IDSEL(rirq) << 4) + function; - - /* Link the IRQ number to the bridge */ - HvCallXm_connectBusUnit(bus, subBus, deviceId, irq); - - /* Unmask bridge interrupts in the FISR */ - mask = 0x01010000 << function; - HvCallPci_unmaskFisr(bus, subBus, deviceId, mask); - iSeries_enable_IRQ(irq); - return 0; -} - -/* - * This is called out of iSeries_fixup to activate interrupt - * generation for usable slots - */ -void __init iSeries_activate_IRQs() -{ - int irq; - unsigned long flags; - - for_each_irq (irq) { - irq_desc_t *desc = get_irq_desc(irq); - - if (desc && desc->handler && desc->handler->startup) { - spin_lock_irqsave(&desc->lock, flags); - desc->handler->startup(irq); - spin_unlock_irqrestore(&desc->lock, flags); - } - } -} - -/* this is not called anywhere currently */ -static void iSeries_shutdown_IRQ(unsigned int irq) -{ - u32 bus, deviceId, function, mask; - const u32 subBus = 0; - unsigned int rirq = virt_irq_to_real_map[irq]; - - /* irq should be locked by the caller */ - bus = REAL_IRQ_TO_BUS(rirq); - function = REAL_IRQ_TO_FUNC(rirq); - deviceId = (REAL_IRQ_TO_IDSEL(rirq) << 4) + function; - - /* Invalidate the IRQ number in the bridge */ - HvCallXm_connectBusUnit(bus, subBus, deviceId, 0); - - /* Mask bridge interrupts in the FISR */ - mask = 0x01010000 << function; - HvCallPci_maskFisr(bus, subBus, deviceId, mask); -} - -/* - * This will be called by device drivers (via disable_IRQ) - * to disable INTA in the bridge interrupt status register. - */ -static void iSeries_disable_IRQ(unsigned int irq) -{ - u32 bus, deviceId, function, mask; - const u32 subBus = 0; - unsigned int rirq = virt_irq_to_real_map[irq]; - - /* The IRQ has already been locked by the caller */ - bus = REAL_IRQ_TO_BUS(rirq); - function = REAL_IRQ_TO_FUNC(rirq); - deviceId = (REAL_IRQ_TO_IDSEL(rirq) << 4) + function; - - /* Mask secondary INTA */ - mask = 0x80000000; - HvCallPci_maskInterrupts(bus, subBus, deviceId, mask); - PPCDBG(PPCDBG_BUSWALK, "iSeries_disable_IRQ 0x%02X.%02X.%02X 0x%04X\n", - bus, subBus, deviceId, irq); -} - -/* - * Need to define this so ppc_irq_dispatch_handler will NOT call - * enable_IRQ at the end of interrupt handling. However, this does - * nothing because there is not enough information provided to do - * the EOI HvCall. This is done by XmPciLpEvent.c - */ -static void iSeries_end_IRQ(unsigned int irq) -{ -} - -static hw_irq_controller iSeries_IRQ_handler = { - .typename = "iSeries irq controller", - .startup = iSeries_startup_IRQ, - .shutdown = iSeries_shutdown_IRQ, - .enable = iSeries_enable_IRQ, - .disable = iSeries_disable_IRQ, - .end = iSeries_end_IRQ -}; - -/* - * This is called out of iSeries_scan_slot to allocate an IRQ for an EADS slot - * It calculates the irq value for the slot. - * Note that subBusNumber is always 0 (at the moment at least). - */ -int __init iSeries_allocate_IRQ(HvBusNumber busNumber, - HvSubBusNumber subBusNumber, HvAgentId deviceId) -{ - unsigned int realirq, virtirq; - u8 idsel = (deviceId >> 4); - u8 function = deviceId & 7; - - virtirq = next_virtual_irq++; - realirq = ((busNumber - 1) << 6) + ((idsel - 1) << 3) + function; - virt_irq_to_real_map[virtirq] = realirq; - - irq_desc[virtirq].handler = &iSeries_IRQ_handler; - return virtirq; -} - -int virt_irq_create_mapping(unsigned int real_irq) -{ - BUG(); /* Don't call this on iSeries, yet */ - - return 0; -} - -void virt_irq_init(void) -{ - return; -} - From sfr at canb.auug.org.au Wed Sep 28 16:58:27 2005 From: sfr at canb.auug.org.au (Stephen Rothwell) Date: Wed, 28 Sep 2005 16:58:27 +1000 Subject: [PATCH 13/19] powerpc: Move iSeries_VpdInfo.c to powerpc/platforms/iseries In-Reply-To: <20050928163333.02799419.sfr@canb.auug.org.au> References: <20050928163333.02799419.sfr@canb.auug.org.au> Message-ID: <20050928165827.51692c17.sfr@canb.auug.org.au> And rename it to vpdinfo.c. Signed-off-by: Stephen Rothwell --- arch/powerpc/platforms/iseries/Makefile | 2 arch/powerpc/platforms/iseries/vpdinfo.c | 266 ++++++++++++++++++++++++++++++ arch/ppc64/kernel/Makefile | 1 arch/ppc64/kernel/iSeries_VpdInfo.c | 268 ------------------------------ 4 files changed, 267 insertions(+), 270 deletions(-) create mode 100644 arch/powerpc/platforms/iseries/vpdinfo.c delete mode 100644 arch/ppc64/kernel/iSeries_VpdInfo.c -- Cheers, Stephen Rothwell sfr at canb.auug.org.au http://www.canb.auug.org.au/~sfr/ da3420fcd62a8967c14a586355e322253a1504a8 diff --git a/arch/powerpc/platforms/iseries/Makefile b/arch/powerpc/platforms/iseries/Makefile --- a/arch/powerpc/platforms/iseries/Makefile +++ b/arch/powerpc/platforms/iseries/Makefile @@ -1,3 +1,3 @@ obj-y += hvlog.o hvlpconfig.o lpardata.o setup.o mf.o lpevents.o \ hvcall.o proc.o htab.o iommu.o -obj-$(CONFIG_PCI) += pci.o irq.o +obj-$(CONFIG_PCI) += pci.o irq.o vpdinfo.o diff --git a/arch/powerpc/platforms/iseries/vpdinfo.c b/arch/powerpc/platforms/iseries/vpdinfo.c new file mode 100644 --- /dev/null +++ b/arch/powerpc/platforms/iseries/vpdinfo.c @@ -0,0 +1,266 @@ +/* + * This code gets the card location of the hardware + * Copyright (C) 2001 + * Copyright (C) 2005 Stephen Rothwel, 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. + * + * 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 + * + * Change Activity: + * Created, Feb 2, 2001 + * Ported to ppc64, August 20, 2001 + * End Change Activity + */ +#include +#include +#include +#include +#include + +#include +#include +#include + +/* + * Size of Bus VPD data + */ +#define BUS_VPDSIZE 1024 + +/* + * Bus Vpd Tags + */ +#define VpdEndOfAreaTag 0x79 +#define VpdIdStringTag 0x82 +#define VpdVendorAreaTag 0x84 + +/* + * Mfg Area Tags + */ +#define VpdFruFrameId 0x4649 // "FI" +#define VpdSlotMapFormat 0x4D46 // "MF" +#define VpdSlotMap 0x534D // "SM" + +/* + * Structures of the areas + */ +struct MfgVpdAreaStruct { + u16 Tag; + u8 TagLength; + u8 AreaData1; + u8 AreaData2; +}; +typedef struct MfgVpdAreaStruct MfgArea; +#define MFG_ENTRY_SIZE 3 + +struct SlotMapStruct { + u8 AgentId; + u8 SecondaryAgentId; + u8 PhbId; + char CardLocation[3]; + char Parms[8]; + char Reserved[2]; +}; +typedef struct SlotMapStruct SlotMap; +#define SLOT_ENTRY_SIZE 16 + +/* + * Parse the Slot Area + */ +static void __init iSeries_Parse_SlotArea(SlotMap *MapPtr, int MapLen, + HvAgentId agent, u8 *PhbId, char card[4]) +{ + int SlotMapLen = MapLen; + SlotMap *SlotMapPtr = MapPtr; + + /* + * Parse Slot label until we find the one requested + */ + while (SlotMapLen > 0) { + if (SlotMapPtr->AgentId == agent) { + /* + * If Phb wasn't found, grab the entry first one found. + */ + if (*PhbId == 0xff) + *PhbId = SlotMapPtr->PhbId; + /* Found it, extract the data. */ + if (SlotMapPtr->PhbId == *PhbId) { + memcpy(card, &SlotMapPtr->CardLocation, 3); + card[3] = 0; + break; + } + } + /* Point to the next Slot */ + SlotMapPtr = (SlotMap *)((char *)SlotMapPtr + SLOT_ENTRY_SIZE); + SlotMapLen -= SLOT_ENTRY_SIZE; + } +} + +/* + * Parse the Mfg Area + */ +static void __init iSeries_Parse_MfgArea(u8 *AreaData, int AreaLen, + HvAgentId agent, u8 *PhbId, + u8 *frame, char card[4]) +{ + MfgArea *MfgAreaPtr = (MfgArea *)AreaData; + int MfgAreaLen = AreaLen; + u16 SlotMapFmt = 0; + + /* Parse Mfg Data */ + while (MfgAreaLen > 0) { + int MfgTagLen = MfgAreaPtr->TagLength; + /* Frame ID (FI 4649020310 ) */ + if (MfgAreaPtr->Tag == VpdFruFrameId) /* FI */ + *frame = MfgAreaPtr->AreaData1; + /* Slot Map Format (MF 4D46020004 ) */ + else if (MfgAreaPtr->Tag == VpdSlotMapFormat) /* MF */ + SlotMapFmt = (MfgAreaPtr->AreaData1 * 256) + + MfgAreaPtr->AreaData2; + /* Slot Map (SM 534D90 */ + else if (MfgAreaPtr->Tag == VpdSlotMap) { /* SM */ + SlotMap *SlotMapPtr; + + if (SlotMapFmt == 0x1004) + SlotMapPtr = (SlotMap *)((char *)MfgAreaPtr + + MFG_ENTRY_SIZE + 1); + else + SlotMapPtr = (SlotMap *)((char *)MfgAreaPtr + + MFG_ENTRY_SIZE); + iSeries_Parse_SlotArea(SlotMapPtr, MfgTagLen, + agent, PhbId, card); + } + /* + * Point to the next Mfg Area + * Use defined size, sizeof give wrong answer + */ + MfgAreaPtr = (MfgArea *)((char *)MfgAreaPtr + MfgTagLen + + MFG_ENTRY_SIZE); + MfgAreaLen -= (MfgTagLen + MFG_ENTRY_SIZE); + } +} + +/* + * Look for "BUS".. Data is not Null terminated. + * PHBID of 0xFF indicates PHB was not found in VPD Data. + */ +static int __init iSeries_Parse_PhbId(u8 *AreaPtr, int AreaLength) +{ + u8 *PhbPtr = AreaPtr; + int DataLen = AreaLength; + char PhbId = 0xFF; + + while (DataLen > 0) { + if ((*PhbPtr == 'B') && (*(PhbPtr + 1) == 'U') + && (*(PhbPtr + 2) == 'S')) { + PhbPtr += 3; + while (*PhbPtr == ' ') + ++PhbPtr; + PhbId = (*PhbPtr & 0x0F); + break; + } + ++PhbPtr; + --DataLen; + } + return PhbId; +} + +/* + * Parse out the VPD Areas + */ +static void __init iSeries_Parse_Vpd(u8 *VpdData, int VpdDataLen, + HvAgentId agent, u8 *frame, char card[4]) +{ + u8 *TagPtr = VpdData; + int DataLen = VpdDataLen - 3; + u8 PhbId; + + while ((*TagPtr != VpdEndOfAreaTag) && (DataLen > 0)) { + int AreaLen = *(TagPtr + 1) + (*(TagPtr + 2) * 256); + u8 *AreaData = TagPtr + 3; + + if (*TagPtr == VpdIdStringTag) + PhbId = iSeries_Parse_PhbId(AreaData, AreaLen); + else if (*TagPtr == VpdVendorAreaTag) + iSeries_Parse_MfgArea(AreaData, AreaLen, + agent, &PhbId, frame, card); + /* Point to next Area. */ + TagPtr = AreaData + AreaLen; + DataLen -= AreaLen; + } +} + +static void __init iSeries_Get_Location_Code(u16 bus, HvAgentId agent, + u8 *frame, char card[4]) +{ + int BusVpdLen = 0; + u8 *BusVpdPtr = kmalloc(BUS_VPDSIZE, GFP_KERNEL); + + if (BusVpdPtr == NULL) { + printk("PCI: Bus VPD Buffer allocation failure.\n"); + return; + } + BusVpdLen = HvCallPci_getBusVpd(bus, ISERIES_HV_ADDR(BusVpdPtr), + BUS_VPDSIZE); + if (BusVpdLen == 0) { + printk("PCI: Bus VPD Buffer zero length.\n"); + goto out_free; + } + /* printk("PCI: BusVpdPtr: %p, %d\n",BusVpdPtr, BusVpdLen); */ + /* Make sure this is what I think it is */ + if (*BusVpdPtr != VpdIdStringTag) { /* 0x82 */ + printk("PCI: Bus VPD Buffer missing starting tag.\n"); + goto out_free; + } + iSeries_Parse_Vpd(BusVpdPtr, BusVpdLen, agent, frame, card); +out_free: + kfree(BusVpdPtr); +} + +/* + * Prints the device information. + * - Pass in pci_dev* pointer to the device. + * - Pass in the device count + * + * Format: + * PCI: Bus 0, Device 26, Vendor 0x12AE Frame 1, Card C10 Ethernet + * controller + */ +void __init iSeries_Device_Information(struct pci_dev *PciDev, int count) +{ + struct iSeries_Device_Node *DevNode = PciDev->sysdata; + u16 bus; + u8 frame; + char card[4]; + HvSubBusNumber subbus; + HvAgentId agent; + + if (DevNode == NULL) { + printk("%d. PCI: iSeries_Device_Information DevNode is NULL\n", + count); + return; + } + + bus = ISERIES_BUS(DevNode); + subbus = ISERIES_SUBBUS(DevNode); + agent = ISERIES_PCI_AGENTID(ISERIES_GET_DEVICE_FROM_SUBBUS(subbus), + ISERIES_GET_FUNCTION_FROM_SUBBUS(subbus)); + iSeries_Get_Location_Code(bus, agent, &frame, card); + + printk("%d. PCI: Bus%3d, Device%3d, Vendor %04X Frame%3d, Card %4s ", + count, bus, PCI_SLOT(PciDev->devfn), PciDev->vendor, + frame, card); + printk("0x%04X\n", (int)(PciDev->class >> 8)); +} diff --git a/arch/ppc64/kernel/Makefile b/arch/ppc64/kernel/Makefile --- a/arch/ppc64/kernel/Makefile +++ b/arch/ppc64/kernel/Makefile @@ -16,7 +16,6 @@ obj-y += vdso32/ vdso64/ obj-$(CONFIG_PPC_OF) += of_device.o -pci-obj-$(CONFIG_PPC_ISERIES) += iSeries_VpdInfo.o pci-obj-$(CONFIG_PPC_MULTIPLATFORM) += pci_dn.o pci_direct_iommu.o obj-$(CONFIG_PCI) += pci.o pci_iommu.o iomap.o $(pci-obj-y) diff --git a/arch/ppc64/kernel/iSeries_VpdInfo.c b/arch/ppc64/kernel/iSeries_VpdInfo.c deleted file mode 100644 --- a/arch/ppc64/kernel/iSeries_VpdInfo.c +++ /dev/null @@ -1,268 +0,0 @@ -/* - * File iSeries_vpdInfo.c created by Allan Trautman on Fri Feb 2 2001. - * - * This code gets the card location of the hardware - * Copyright (C) 2001 - * Copyright (C) 2005 Stephen Rothwel, 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. - * - * 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 - * - * Change Activity: - * Created, Feb 2, 2001 - * Ported to ppc64, August 20, 2001 - * End Change Activity - */ -#include -#include -#include -#include -#include - -#include -#include -#include - -/* - * Size of Bus VPD data - */ -#define BUS_VPDSIZE 1024 - -/* - * Bus Vpd Tags - */ -#define VpdEndOfAreaTag 0x79 -#define VpdIdStringTag 0x82 -#define VpdVendorAreaTag 0x84 - -/* - * Mfg Area Tags - */ -#define VpdFruFrameId 0x4649 // "FI" -#define VpdSlotMapFormat 0x4D46 // "MF" -#define VpdSlotMap 0x534D // "SM" - -/* - * Structures of the areas - */ -struct MfgVpdAreaStruct { - u16 Tag; - u8 TagLength; - u8 AreaData1; - u8 AreaData2; -}; -typedef struct MfgVpdAreaStruct MfgArea; -#define MFG_ENTRY_SIZE 3 - -struct SlotMapStruct { - u8 AgentId; - u8 SecondaryAgentId; - u8 PhbId; - char CardLocation[3]; - char Parms[8]; - char Reserved[2]; -}; -typedef struct SlotMapStruct SlotMap; -#define SLOT_ENTRY_SIZE 16 - -/* - * Parse the Slot Area - */ -static void __init iSeries_Parse_SlotArea(SlotMap *MapPtr, int MapLen, - HvAgentId agent, u8 *PhbId, char card[4]) -{ - int SlotMapLen = MapLen; - SlotMap *SlotMapPtr = MapPtr; - - /* - * Parse Slot label until we find the one requested - */ - while (SlotMapLen > 0) { - if (SlotMapPtr->AgentId == agent) { - /* - * If Phb wasn't found, grab the entry first one found. - */ - if (*PhbId == 0xff) - *PhbId = SlotMapPtr->PhbId; - /* Found it, extract the data. */ - if (SlotMapPtr->PhbId == *PhbId) { - memcpy(card, &SlotMapPtr->CardLocation, 3); - card[3] = 0; - break; - } - } - /* Point to the next Slot */ - SlotMapPtr = (SlotMap *)((char *)SlotMapPtr + SLOT_ENTRY_SIZE); - SlotMapLen -= SLOT_ENTRY_SIZE; - } -} - -/* - * Parse the Mfg Area - */ -static void __init iSeries_Parse_MfgArea(u8 *AreaData, int AreaLen, - HvAgentId agent, u8 *PhbId, - u8 *frame, char card[4]) -{ - MfgArea *MfgAreaPtr = (MfgArea *)AreaData; - int MfgAreaLen = AreaLen; - u16 SlotMapFmt = 0; - - /* Parse Mfg Data */ - while (MfgAreaLen > 0) { - int MfgTagLen = MfgAreaPtr->TagLength; - /* Frame ID (FI 4649020310 ) */ - if (MfgAreaPtr->Tag == VpdFruFrameId) /* FI */ - *frame = MfgAreaPtr->AreaData1; - /* Slot Map Format (MF 4D46020004 ) */ - else if (MfgAreaPtr->Tag == VpdSlotMapFormat) /* MF */ - SlotMapFmt = (MfgAreaPtr->AreaData1 * 256) - + MfgAreaPtr->AreaData2; - /* Slot Map (SM 534D90 */ - else if (MfgAreaPtr->Tag == VpdSlotMap) { /* SM */ - SlotMap *SlotMapPtr; - - if (SlotMapFmt == 0x1004) - SlotMapPtr = (SlotMap *)((char *)MfgAreaPtr - + MFG_ENTRY_SIZE + 1); - else - SlotMapPtr = (SlotMap *)((char *)MfgAreaPtr - + MFG_ENTRY_SIZE); - iSeries_Parse_SlotArea(SlotMapPtr, MfgTagLen, - agent, PhbId, card); - } - /* - * Point to the next Mfg Area - * Use defined size, sizeof give wrong answer - */ - MfgAreaPtr = (MfgArea *)((char *)MfgAreaPtr + MfgTagLen - + MFG_ENTRY_SIZE); - MfgAreaLen -= (MfgTagLen + MFG_ENTRY_SIZE); - } -} - -/* - * Look for "BUS".. Data is not Null terminated. - * PHBID of 0xFF indicates PHB was not found in VPD Data. - */ -static int __init iSeries_Parse_PhbId(u8 *AreaPtr, int AreaLength) -{ - u8 *PhbPtr = AreaPtr; - int DataLen = AreaLength; - char PhbId = 0xFF; - - while (DataLen > 0) { - if ((*PhbPtr == 'B') && (*(PhbPtr + 1) == 'U') - && (*(PhbPtr + 2) == 'S')) { - PhbPtr += 3; - while (*PhbPtr == ' ') - ++PhbPtr; - PhbId = (*PhbPtr & 0x0F); - break; - } - ++PhbPtr; - --DataLen; - } - return PhbId; -} - -/* - * Parse out the VPD Areas - */ -static void __init iSeries_Parse_Vpd(u8 *VpdData, int VpdDataLen, - HvAgentId agent, u8 *frame, char card[4]) -{ - u8 *TagPtr = VpdData; - int DataLen = VpdDataLen - 3; - u8 PhbId; - - while ((*TagPtr != VpdEndOfAreaTag) && (DataLen > 0)) { - int AreaLen = *(TagPtr + 1) + (*(TagPtr + 2) * 256); - u8 *AreaData = TagPtr + 3; - - if (*TagPtr == VpdIdStringTag) - PhbId = iSeries_Parse_PhbId(AreaData, AreaLen); - else if (*TagPtr == VpdVendorAreaTag) - iSeries_Parse_MfgArea(AreaData, AreaLen, - agent, &PhbId, frame, card); - /* Point to next Area. */ - TagPtr = AreaData + AreaLen; - DataLen -= AreaLen; - } -} - -static void __init iSeries_Get_Location_Code(u16 bus, HvAgentId agent, - u8 *frame, char card[4]) -{ - int BusVpdLen = 0; - u8 *BusVpdPtr = kmalloc(BUS_VPDSIZE, GFP_KERNEL); - - if (BusVpdPtr == NULL) { - printk("PCI: Bus VPD Buffer allocation failure.\n"); - return; - } - BusVpdLen = HvCallPci_getBusVpd(bus, ISERIES_HV_ADDR(BusVpdPtr), - BUS_VPDSIZE); - if (BusVpdLen == 0) { - printk("PCI: Bus VPD Buffer zero length.\n"); - goto out_free; - } - /* printk("PCI: BusVpdPtr: %p, %d\n",BusVpdPtr, BusVpdLen); */ - /* Make sure this is what I think it is */ - if (*BusVpdPtr != VpdIdStringTag) { /* 0x82 */ - printk("PCI: Bus VPD Buffer missing starting tag.\n"); - goto out_free; - } - iSeries_Parse_Vpd(BusVpdPtr, BusVpdLen, agent, frame, card); -out_free: - kfree(BusVpdPtr); -} - -/* - * Prints the device information. - * - Pass in pci_dev* pointer to the device. - * - Pass in the device count - * - * Format: - * PCI: Bus 0, Device 26, Vendor 0x12AE Frame 1, Card C10 Ethernet - * controller - */ -void __init iSeries_Device_Information(struct pci_dev *PciDev, int count) -{ - struct iSeries_Device_Node *DevNode = PciDev->sysdata; - u16 bus; - u8 frame; - char card[4]; - HvSubBusNumber subbus; - HvAgentId agent; - - if (DevNode == NULL) { - printk("%d. PCI: iSeries_Device_Information DevNode is NULL\n", - count); - return; - } - - bus = ISERIES_BUS(DevNode); - subbus = ISERIES_SUBBUS(DevNode); - agent = ISERIES_PCI_AGENTID(ISERIES_GET_DEVICE_FROM_SUBBUS(subbus), - ISERIES_GET_FUNCTION_FROM_SUBBUS(subbus)); - iSeries_Get_Location_Code(bus, agent, &frame, card); - - printk("%d. PCI: Bus%3d, Device%3d, Vendor %04X Frame%3d, Card %4s ", - count, bus, PCI_SLOT(PciDev->devfn), PciDev->vendor, - frame, card); - printk("0x%04X\n", (int)(PciDev->class >> 8)); -} From sfr at canb.auug.org.au Wed Sep 28 16:59:25 2005 From: sfr at canb.auug.org.au (Stephen Rothwell) Date: Wed, 28 Sep 2005 16:59:25 +1000 Subject: [PATCH 14/19] powerpc: Move iSeries_vio.c to powerpc/platforms/iseries In-Reply-To: <20050928163333.02799419.sfr@canb.auug.org.au> References: <20050928163333.02799419.sfr@canb.auug.org.au> Message-ID: <20050928165925.2a2e26a1.sfr@canb.auug.org.au> And rename it to vio.c. Signed-off-by: Stephen Rothwell --- arch/powerpc/platforms/iseries/Makefile | 1 arch/powerpc/platforms/iseries/vio.c | 156 +++++++++++++++++++++++++++++++ arch/ppc64/kernel/Makefile | 1 arch/ppc64/kernel/iSeries_vio.c | 156 ------------------------------- 4 files changed, 157 insertions(+), 157 deletions(-) create mode 100644 arch/powerpc/platforms/iseries/vio.c delete mode 100644 arch/ppc64/kernel/iSeries_vio.c -- Cheers, Stephen Rothwell sfr at canb.auug.org.au http://www.canb.auug.org.au/~sfr/ ed7f2c05de956da72baf066701ac642f7215dbf5 diff --git a/arch/powerpc/platforms/iseries/Makefile b/arch/powerpc/platforms/iseries/Makefile --- a/arch/powerpc/platforms/iseries/Makefile +++ b/arch/powerpc/platforms/iseries/Makefile @@ -1,3 +1,4 @@ obj-y += hvlog.o hvlpconfig.o lpardata.o setup.o mf.o lpevents.o \ hvcall.o proc.o htab.o iommu.o obj-$(CONFIG_PCI) += pci.o irq.o vpdinfo.o +obj-$(CONFIG_IBMVIO) += vio.o diff --git a/arch/powerpc/platforms/iseries/vio.c b/arch/powerpc/platforms/iseries/vio.c new file mode 100644 --- /dev/null +++ b/arch/powerpc/platforms/iseries/vio.c @@ -0,0 +1,156 @@ +/* + * IBM PowerPC iSeries Virtual I/O Infrastructure Support. + * + * Copyright (c) 2005 Stephen Rothwell, 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 +#include +#include + +struct device *iSeries_vio_dev = &vio_bus_device.dev; +EXPORT_SYMBOL(iSeries_vio_dev); + +static struct iommu_table veth_iommu_table; +static struct iommu_table vio_iommu_table; + +static void __init iommu_vio_init(void) +{ + struct iommu_table *t; + struct iommu_table_cb cb; + unsigned long cbp; + unsigned long itc_entries; + + cb.itc_busno = 255; /* Bus 255 is the virtual bus */ + cb.itc_virtbus = 0xff; /* Ask for virtual bus */ + + cbp = virt_to_abs(&cb); + HvCallXm_getTceTableParms(cbp); + + itc_entries = cb.itc_size * PAGE_SIZE / sizeof(union tce_entry); + veth_iommu_table.it_size = itc_entries / 2; + veth_iommu_table.it_busno = cb.itc_busno; + veth_iommu_table.it_offset = cb.itc_offset; + veth_iommu_table.it_index = cb.itc_index; + veth_iommu_table.it_type = TCE_VB; + veth_iommu_table.it_blocksize = 1; + + t = iommu_init_table(&veth_iommu_table); + + if (!t) + printk("Virtual Bus VETH TCE table failed.\n"); + + vio_iommu_table.it_size = itc_entries - veth_iommu_table.it_size; + vio_iommu_table.it_busno = cb.itc_busno; + vio_iommu_table.it_offset = cb.itc_offset + + veth_iommu_table.it_size; + vio_iommu_table.it_index = cb.itc_index; + vio_iommu_table.it_type = TCE_VB; + vio_iommu_table.it_blocksize = 1; + + t = iommu_init_table(&vio_iommu_table); + + if (!t) + printk("Virtual Bus VIO TCE table failed.\n"); +} + +/** + * vio_register_device_iseries: - Register a new iSeries vio device. + * @voidev: The device to register. + */ +static struct vio_dev *__init vio_register_device_iseries(char *type, + uint32_t unit_num) +{ + struct vio_dev *viodev; + + /* allocate a vio_dev for this device */ + viodev = kmalloc(sizeof(struct vio_dev), GFP_KERNEL); + if (!viodev) + return NULL; + memset(viodev, 0, sizeof(struct vio_dev)); + + snprintf(viodev->dev.bus_id, BUS_ID_SIZE, "%s%d", type, unit_num); + + viodev->name = viodev->dev.bus_id; + viodev->type = type; + viodev->unit_address = unit_num; + viodev->iommu_table = &vio_iommu_table; + if (vio_register_device(viodev) == NULL) { + kfree(viodev); + return NULL; + } + return viodev; +} + +void __init probe_bus_iseries(void) +{ + HvLpIndexMap vlan_map; + struct vio_dev *viodev; + int i; + + /* there is only one of each of these */ + vio_register_device_iseries("viocons", 0); + vio_register_device_iseries("vscsi", 0); + + vlan_map = HvLpConfig_getVirtualLanIndexMap(); + for (i = 0; i < HVMAXARCHITECTEDVIRTUALLANS; i++) { + if ((vlan_map & (0x8000 >> i)) == 0) + continue; + viodev = vio_register_device_iseries("vlan", i); + /* veth is special and has it own iommu_table */ + viodev->iommu_table = &veth_iommu_table; + } + for (i = 0; i < HVMAXARCHITECTEDVIRTUALDISKS; i++) + vio_register_device_iseries("viodasd", i); + for (i = 0; i < HVMAXARCHITECTEDVIRTUALCDROMS; i++) + vio_register_device_iseries("viocd", i); + for (i = 0; i < HVMAXARCHITECTEDVIRTUALTAPES; i++) + vio_register_device_iseries("viotape", i); +} + +/** + * vio_match_device_iseries: - Tell if a iSeries VIO device matches a + * vio_device_id + */ +static int vio_match_device_iseries(const struct vio_device_id *id, + const struct vio_dev *dev) +{ + return strncmp(dev->type, id->type, strlen(id->type)) == 0; +} + +static struct vio_bus_ops vio_bus_ops_iseries = { + .match = vio_match_device_iseries, +}; + +/** + * vio_bus_init_iseries: - Initialize the iSeries virtual IO bus + */ +static int __init vio_bus_init_iseries(void) +{ + int err; + + err = vio_bus_init(&vio_bus_ops_iseries); + if (err == 0) { + iommu_vio_init(); + vio_bus_device.iommu_table = &vio_iommu_table; + iSeries_vio_dev = &vio_bus_device.dev; + probe_bus_iseries(); + } + return err; +} + +__initcall(vio_bus_init_iseries); diff --git a/arch/ppc64/kernel/Makefile b/arch/ppc64/kernel/Makefile --- a/arch/ppc64/kernel/Makefile +++ b/arch/ppc64/kernel/Makefile @@ -45,7 +45,6 @@ obj-$(CONFIG_BOOTX_TEXT) += btext.o obj-$(CONFIG_HVCS) += hvcserver.o vio-obj-$(CONFIG_PPC_PSERIES) += pSeries_vio.o -vio-obj-$(CONFIG_PPC_ISERIES) += iSeries_vio.o obj-$(CONFIG_IBMVIO) += vio.o $(vio-obj-y) obj-$(CONFIG_XICS) += xics.o obj-$(CONFIG_MPIC) += mpic.o diff --git a/arch/ppc64/kernel/iSeries_vio.c b/arch/ppc64/kernel/iSeries_vio.c deleted file mode 100644 --- a/arch/ppc64/kernel/iSeries_vio.c +++ /dev/null @@ -1,156 +0,0 @@ -/* - * IBM PowerPC iSeries Virtual I/O Infrastructure Support. - * - * Copyright (c) 2005 Stephen Rothwell, 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 -#include -#include - -struct device *iSeries_vio_dev = &vio_bus_device.dev; -EXPORT_SYMBOL(iSeries_vio_dev); - -static struct iommu_table veth_iommu_table; -static struct iommu_table vio_iommu_table; - -static void __init iommu_vio_init(void) -{ - struct iommu_table *t; - struct iommu_table_cb cb; - unsigned long cbp; - unsigned long itc_entries; - - cb.itc_busno = 255; /* Bus 255 is the virtual bus */ - cb.itc_virtbus = 0xff; /* Ask for virtual bus */ - - cbp = virt_to_abs(&cb); - HvCallXm_getTceTableParms(cbp); - - itc_entries = cb.itc_size * PAGE_SIZE / sizeof(union tce_entry); - veth_iommu_table.it_size = itc_entries / 2; - veth_iommu_table.it_busno = cb.itc_busno; - veth_iommu_table.it_offset = cb.itc_offset; - veth_iommu_table.it_index = cb.itc_index; - veth_iommu_table.it_type = TCE_VB; - veth_iommu_table.it_blocksize = 1; - - t = iommu_init_table(&veth_iommu_table); - - if (!t) - printk("Virtual Bus VETH TCE table failed.\n"); - - vio_iommu_table.it_size = itc_entries - veth_iommu_table.it_size; - vio_iommu_table.it_busno = cb.itc_busno; - vio_iommu_table.it_offset = cb.itc_offset + - veth_iommu_table.it_size; - vio_iommu_table.it_index = cb.itc_index; - vio_iommu_table.it_type = TCE_VB; - vio_iommu_table.it_blocksize = 1; - - t = iommu_init_table(&vio_iommu_table); - - if (!t) - printk("Virtual Bus VIO TCE table failed.\n"); -} - -/** - * vio_register_device_iseries: - Register a new iSeries vio device. - * @voidev: The device to register. - */ -static struct vio_dev *__init vio_register_device_iseries(char *type, - uint32_t unit_num) -{ - struct vio_dev *viodev; - - /* allocate a vio_dev for this device */ - viodev = kmalloc(sizeof(struct vio_dev), GFP_KERNEL); - if (!viodev) - return NULL; - memset(viodev, 0, sizeof(struct vio_dev)); - - snprintf(viodev->dev.bus_id, BUS_ID_SIZE, "%s%d", type, unit_num); - - viodev->name = viodev->dev.bus_id; - viodev->type = type; - viodev->unit_address = unit_num; - viodev->iommu_table = &vio_iommu_table; - if (vio_register_device(viodev) == NULL) { - kfree(viodev); - return NULL; - } - return viodev; -} - -void __init probe_bus_iseries(void) -{ - HvLpIndexMap vlan_map; - struct vio_dev *viodev; - int i; - - /* there is only one of each of these */ - vio_register_device_iseries("viocons", 0); - vio_register_device_iseries("vscsi", 0); - - vlan_map = HvLpConfig_getVirtualLanIndexMap(); - for (i = 0; i < HVMAXARCHITECTEDVIRTUALLANS; i++) { - if ((vlan_map & (0x8000 >> i)) == 0) - continue; - viodev = vio_register_device_iseries("vlan", i); - /* veth is special and has it own iommu_table */ - viodev->iommu_table = &veth_iommu_table; - } - for (i = 0; i < HVMAXARCHITECTEDVIRTUALDISKS; i++) - vio_register_device_iseries("viodasd", i); - for (i = 0; i < HVMAXARCHITECTEDVIRTUALCDROMS; i++) - vio_register_device_iseries("viocd", i); - for (i = 0; i < HVMAXARCHITECTEDVIRTUALTAPES; i++) - vio_register_device_iseries("viotape", i); -} - -/** - * vio_match_device_iseries: - Tell if a iSeries VIO device matches a - * vio_device_id - */ -static int vio_match_device_iseries(const struct vio_device_id *id, - const struct vio_dev *dev) -{ - return strncmp(dev->type, id->type, strlen(id->type)) == 0; -} - -static struct vio_bus_ops vio_bus_ops_iseries = { - .match = vio_match_device_iseries, -}; - -/** - * vio_bus_init_iseries: - Initialize the iSeries virtual IO bus - */ -static int __init vio_bus_init_iseries(void) -{ - int err; - - err = vio_bus_init(&vio_bus_ops_iseries); - if (err == 0) { - iommu_vio_init(); - vio_bus_device.iommu_table = &vio_iommu_table; - iSeries_vio_dev = &vio_bus_device.dev; - probe_bus_iseries(); - } - return err; -} - -__initcall(vio_bus_init_iseries); From sfr at canb.auug.org.au Wed Sep 28 17:00:18 2005 From: sfr at canb.auug.org.au (Stephen Rothwell) Date: Wed, 28 Sep 2005 17:00:18 +1000 Subject: [PATCH 15/19] powerpc: Move iSeries_smp.c to powerpc/platforms/iseries In-Reply-To: <20050928163333.02799419.sfr@canb.auug.org.au> References: <20050928163333.02799419.sfr@canb.auug.org.au> Message-ID: <20050928170018.549e560a.sfr@canb.auug.org.au> And rename it to smp.c. Signed-off-by: Stephen Rothwell --- arch/powerpc/platforms/iseries/Makefile | 1 arch/powerpc/platforms/iseries/smp.c | 121 +++++++++++++++++++++++++++++++ arch/ppc64/kernel/Makefile | 1 arch/ppc64/kernel/iSeries_smp.c | 121 ------------------------------- 4 files changed, 122 insertions(+), 122 deletions(-) create mode 100644 arch/powerpc/platforms/iseries/smp.c delete mode 100644 arch/ppc64/kernel/iSeries_smp.c -- Cheers, Stephen Rothwell sfr at canb.auug.org.au http://www.canb.auug.org.au/~sfr/ b6b8681843f9eaee12f8c30ffac399f7b2601ab3 diff --git a/arch/powerpc/platforms/iseries/Makefile b/arch/powerpc/platforms/iseries/Makefile --- a/arch/powerpc/platforms/iseries/Makefile +++ b/arch/powerpc/platforms/iseries/Makefile @@ -2,3 +2,4 @@ obj-y += hvlog.o hvlpconfig.o lpardata.o hvcall.o proc.o htab.o iommu.o obj-$(CONFIG_PCI) += pci.o irq.o vpdinfo.o obj-$(CONFIG_IBMVIO) += vio.o +obj-$(CONFIG_SMP) += smp.o diff --git a/arch/powerpc/platforms/iseries/smp.c b/arch/powerpc/platforms/iseries/smp.c new file mode 100644 --- /dev/null +++ b/arch/powerpc/platforms/iseries/smp.c @@ -0,0 +1,121 @@ +/* + * SMP support for iSeries machines. + * + * Dave Engebretsen, Peter Bergner, and + * Mike Corrigan {engebret|bergner|mikec}@us.ibm.com + * + * Plus various changes from other IBM teams... + * + * 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 + +static unsigned long iSeries_smp_message[NR_CPUS]; + +void iSeries_smp_message_recv(struct pt_regs *regs) +{ + int cpu = smp_processor_id(); + int msg; + + if (num_online_cpus() < 2) + return; + + for (msg = 0; msg < 4; msg++) + if (test_and_clear_bit(msg, &iSeries_smp_message[cpu])) + smp_message_recv(msg, regs); +} + +static inline void smp_iSeries_do_message(int cpu, int msg) +{ + set_bit(msg, &iSeries_smp_message[cpu]); + HvCall_sendIPI(&(paca[cpu])); +} + +static void smp_iSeries_message_pass(int target, int msg) +{ + int i; + + if (target < NR_CPUS) + smp_iSeries_do_message(target, msg); + else { + for_each_online_cpu(i) { + if ((target == MSG_ALL_BUT_SELF) && + (i == smp_processor_id())) + continue; + smp_iSeries_do_message(i, msg); + } + } +} + +static int smp_iSeries_probe(void) +{ + return cpus_weight(cpu_possible_map); +} + +static void smp_iSeries_kick_cpu(int nr) +{ + BUG_ON((nr < 0) || (nr >= NR_CPUS)); + + /* Verify that our partition has a processor nr */ + if (paca[nr].lppaca.dyn_proc_status >= 2) + return; + + /* The processor is currently spinning, waiting + * for the cpu_start field to become non-zero + * After we set cpu_start, the processor will + * continue on to secondary_start in iSeries_head.S + */ + paca[nr].cpu_start = 1; +} + +static void __devinit smp_iSeries_setup_cpu(int nr) +{ +} + +static struct smp_ops_t iSeries_smp_ops = { + .message_pass = smp_iSeries_message_pass, + .probe = smp_iSeries_probe, + .kick_cpu = smp_iSeries_kick_cpu, + .setup_cpu = smp_iSeries_setup_cpu, +}; + +/* This is called very early. */ +void __init smp_init_iSeries(void) +{ + smp_ops = &iSeries_smp_ops; +} diff --git a/arch/ppc64/kernel/Makefile b/arch/ppc64/kernel/Makefile --- a/arch/ppc64/kernel/Makefile +++ b/arch/ppc64/kernel/Makefile @@ -60,7 +60,6 @@ obj-$(CONFIG_U3_DART) += u3_iommu.o 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_MAPLE) += smp-tbsync.o diff --git a/arch/ppc64/kernel/iSeries_smp.c b/arch/ppc64/kernel/iSeries_smp.c deleted file mode 100644 --- a/arch/ppc64/kernel/iSeries_smp.c +++ /dev/null @@ -1,121 +0,0 @@ -/* - * SMP support for iSeries machines. - * - * Dave Engebretsen, Peter Bergner, and - * Mike Corrigan {engebret|bergner|mikec}@us.ibm.com - * - * Plus various changes from other IBM teams... - * - * 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 - -static unsigned long iSeries_smp_message[NR_CPUS]; - -void iSeries_smp_message_recv( struct pt_regs * regs ) -{ - int cpu = smp_processor_id(); - int msg; - - if ( num_online_cpus() < 2 ) - return; - - for ( msg = 0; msg < 4; ++msg ) - if ( test_and_clear_bit( msg, &iSeries_smp_message[cpu] ) ) - smp_message_recv( msg, regs ); -} - -static inline void smp_iSeries_do_message(int cpu, int msg) -{ - set_bit(msg, &iSeries_smp_message[cpu]); - HvCall_sendIPI(&(paca[cpu])); -} - -static void smp_iSeries_message_pass(int target, int msg) -{ - int i; - - if (target < NR_CPUS) - smp_iSeries_do_message(target, msg); - else { - for_each_online_cpu(i) { - if (target == MSG_ALL_BUT_SELF - && i == smp_processor_id()) - continue; - smp_iSeries_do_message(i, msg); - } - } -} - -static int smp_iSeries_probe(void) -{ - return cpus_weight(cpu_possible_map); -} - -static void smp_iSeries_kick_cpu(int nr) -{ - BUG_ON(nr < 0 || nr >= NR_CPUS); - - /* Verify that our partition has a processor nr */ - if (paca[nr].lppaca.dyn_proc_status >= 2) - return; - - /* The processor is currently spinning, waiting - * for the cpu_start field to become non-zero - * After we set cpu_start, the processor will - * continue on to secondary_start in iSeries_head.S - */ - paca[nr].cpu_start = 1; -} - -static void __devinit smp_iSeries_setup_cpu(int nr) -{ -} - -static struct smp_ops_t iSeries_smp_ops = { - .message_pass = smp_iSeries_message_pass, - .probe = smp_iSeries_probe, - .kick_cpu = smp_iSeries_kick_cpu, - .setup_cpu = smp_iSeries_setup_cpu, -}; - -/* This is called very early. */ -void __init smp_init_iSeries(void) -{ - smp_ops = &iSeries_smp_ops; -} From sfr at canb.auug.org.au Wed Sep 28 17:01:28 2005 From: sfr at canb.auug.org.au (Stephen Rothwell) Date: Wed, 28 Sep 2005 17:01:28 +1000 Subject: [PATCH 16/19] powerpc: Move viopath.c to powerpc/platforms/iseries In-Reply-To: <20050928163333.02799419.sfr@canb.auug.org.au> References: <20050928163333.02799419.sfr@canb.auug.org.au> Message-ID: <20050928170128.3b9b51b1.sfr@canb.auug.org.au> Signed-off-by: Stephen Rothwell --- arch/powerpc/platforms/iseries/Makefile | 1 arch/powerpc/platforms/iseries/viopath.c | 672 ++++++++++++++++++++++++++++++ arch/ppc64/kernel/Makefile | 1 arch/ppc64/kernel/viopath.c | 673 ------------------------------ 4 files changed, 673 insertions(+), 674 deletions(-) create mode 100644 arch/powerpc/platforms/iseries/viopath.c delete mode 100644 arch/ppc64/kernel/viopath.c -- Cheers, Stephen Rothwell sfr at canb.auug.org.au http://www.canb.auug.org.au/~sfr/ d223e721b743787fad71f6aef5e860176214c8f9 diff --git a/arch/powerpc/platforms/iseries/Makefile b/arch/powerpc/platforms/iseries/Makefile --- a/arch/powerpc/platforms/iseries/Makefile +++ b/arch/powerpc/platforms/iseries/Makefile @@ -3,3 +3,4 @@ obj-y += hvlog.o hvlpconfig.o lpardata.o obj-$(CONFIG_PCI) += pci.o irq.o vpdinfo.o obj-$(CONFIG_IBMVIO) += vio.o obj-$(CONFIG_SMP) += smp.o +obj-$(CONFIG_VIOPATH) += viopath.o diff --git a/arch/powerpc/platforms/iseries/viopath.c b/arch/powerpc/platforms/iseries/viopath.c new file mode 100644 --- /dev/null +++ b/arch/powerpc/platforms/iseries/viopath.c @@ -0,0 +1,672 @@ +/* -*- linux-c -*- + * + * iSeries Virtual I/O Message Path code + * + * Authors: Dave Boutcher + * Ryan Arnold + * Colin Devilbiss + * + * (C) Copyright 2000-2005 IBM Corporation + * + * This code is used by the iSeries virtual disk, cd, + * tape, and console to communicate with OS/400 in another + * partition. + * + * 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) anyu later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +/* Status of the path to each other partition in the system. + * This is overkill, since we will only ever establish connections + * to our hosting partition and the primary partition on the system. + * But this allows for other support in the future. + */ +static struct viopathStatus { + int isOpen; /* Did we open the path? */ + int isActive; /* Do we have a mon msg outstanding */ + int users[VIO_MAX_SUBTYPES]; + HvLpInstanceId mSourceInst; + HvLpInstanceId mTargetInst; + int numberAllocated; +} viopathStatus[HVMAXARCHITECTEDLPS]; + +static DEFINE_SPINLOCK(statuslock); + +/* + * For each kind of event we allocate a buffer that is + * guaranteed not to cross a page boundary + */ +static unsigned char event_buffer[VIO_MAX_SUBTYPES * 256] __page_aligned; +static atomic_t event_buffer_available[VIO_MAX_SUBTYPES]; +static int event_buffer_initialised; + +static void handleMonitorEvent(struct HvLpEvent *event); + +/* + * We use this structure to handle asynchronous responses. The caller + * blocks on the semaphore and the handler posts the semaphore. However, + * if system_state is not SYSTEM_RUNNING, then wait_atomic is used ... + */ +struct alloc_parms { + struct semaphore sem; + int number; + atomic_t wait_atomic; + int used_wait_atomic; +}; + +/* Put a sequence number in each mon msg. The value is not + * important. Start at something other than 0 just for + * readability. wrapping this is ok. + */ +static u8 viomonseq = 22; + +/* Our hosting logical partition. We get this at startup + * time, and different modules access this variable directly. + */ +HvLpIndex viopath_hostLp = HvLpIndexInvalid; +EXPORT_SYMBOL(viopath_hostLp); +HvLpIndex viopath_ourLp = HvLpIndexInvalid; +EXPORT_SYMBOL(viopath_ourLp); + +/* For each kind of incoming event we set a pointer to a + * routine to call. + */ +static vio_event_handler_t *vio_handler[VIO_MAX_SUBTYPES]; + +#define VIOPATH_KERN_WARN KERN_WARNING "viopath: " +#define VIOPATH_KERN_INFO KERN_INFO "viopath: " + +static int proc_viopath_show(struct seq_file *m, void *v) +{ + char *buf; + u16 vlanMap; + dma_addr_t handle; + HvLpEvent_Rc hvrc; + DECLARE_MUTEX_LOCKED(Semaphore); + + buf = kmalloc(PAGE_SIZE, GFP_KERNEL); + if (!buf) + return 0; + memset(buf, 0, PAGE_SIZE); + + handle = dma_map_single(iSeries_vio_dev, buf, PAGE_SIZE, + DMA_FROM_DEVICE); + + hvrc = HvCallEvent_signalLpEventFast(viopath_hostLp, + HvLpEvent_Type_VirtualIo, + viomajorsubtype_config | vioconfigget, + HvLpEvent_AckInd_DoAck, HvLpEvent_AckType_ImmediateAck, + viopath_sourceinst(viopath_hostLp), + viopath_targetinst(viopath_hostLp), + (u64)(unsigned long)&Semaphore, VIOVERSION << 16, + ((u64)handle) << 32, PAGE_SIZE, 0, 0); + + if (hvrc != HvLpEvent_Rc_Good) + printk(VIOPATH_KERN_WARN "hv error on op %d\n", (int)hvrc); + + down(&Semaphore); + + vlanMap = HvLpConfig_getVirtualLanIndexMap(); + + buf[PAGE_SIZE-1] = '\0'; + seq_printf(m, "%s", buf); + seq_printf(m, "AVAILABLE_VETH=%x\n", vlanMap); + seq_printf(m, "SRLNBR=%c%c%c%c%c%c%c\n", + e2a(xItExtVpdPanel.mfgID[2]), + e2a(xItExtVpdPanel.mfgID[3]), + e2a(xItExtVpdPanel.systemSerial[1]), + e2a(xItExtVpdPanel.systemSerial[2]), + e2a(xItExtVpdPanel.systemSerial[3]), + e2a(xItExtVpdPanel.systemSerial[4]), + e2a(xItExtVpdPanel.systemSerial[5])); + + dma_unmap_single(iSeries_vio_dev, handle, PAGE_SIZE, DMA_FROM_DEVICE); + kfree(buf); + + return 0; +} + +static int proc_viopath_open(struct inode *inode, struct file *file) +{ + return single_open(file, proc_viopath_show, NULL); +} + +static struct file_operations proc_viopath_operations = { + .open = proc_viopath_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + +static int __init vio_proc_init(void) +{ + struct proc_dir_entry *e; + + e = create_proc_entry("iSeries/config", 0, NULL); + if (e) + e->proc_fops = &proc_viopath_operations; + + return 0; +} +__initcall(vio_proc_init); + +/* See if a given LP is active. Allow for invalid lps to be passed in + * and just return invalid + */ +int viopath_isactive(HvLpIndex lp) +{ + if (lp == HvLpIndexInvalid) + return 0; + if (lp < HVMAXARCHITECTEDLPS) + return viopathStatus[lp].isActive; + else + return 0; +} +EXPORT_SYMBOL(viopath_isactive); + +/* + * We cache the source and target instance ids for each + * partition. + */ +HvLpInstanceId viopath_sourceinst(HvLpIndex lp) +{ + return viopathStatus[lp].mSourceInst; +} +EXPORT_SYMBOL(viopath_sourceinst); + +HvLpInstanceId viopath_targetinst(HvLpIndex lp) +{ + return viopathStatus[lp].mTargetInst; +} +EXPORT_SYMBOL(viopath_targetinst); + +/* + * Send a monitor message. This is a message with the acknowledge + * bit on that the other side will NOT explicitly acknowledge. When + * the other side goes down, the hypervisor will acknowledge any + * outstanding messages....so we will know when the other side dies. + */ +static void sendMonMsg(HvLpIndex remoteLp) +{ + HvLpEvent_Rc hvrc; + + viopathStatus[remoteLp].mSourceInst = + HvCallEvent_getSourceLpInstanceId(remoteLp, + HvLpEvent_Type_VirtualIo); + viopathStatus[remoteLp].mTargetInst = + HvCallEvent_getTargetLpInstanceId(remoteLp, + HvLpEvent_Type_VirtualIo); + + /* + * Deliberately ignore the return code here. if we call this + * more than once, we don't care. + */ + vio_setHandler(viomajorsubtype_monitor, handleMonitorEvent); + + hvrc = HvCallEvent_signalLpEventFast(remoteLp, HvLpEvent_Type_VirtualIo, + viomajorsubtype_monitor, HvLpEvent_AckInd_DoAck, + HvLpEvent_AckType_DeferredAck, + viopathStatus[remoteLp].mSourceInst, + viopathStatus[remoteLp].mTargetInst, + viomonseq++, 0, 0, 0, 0, 0); + + if (hvrc == HvLpEvent_Rc_Good) + viopathStatus[remoteLp].isActive = 1; + else { + printk(VIOPATH_KERN_WARN "could not connect to partition %d\n", + remoteLp); + viopathStatus[remoteLp].isActive = 0; + } +} + +static void handleMonitorEvent(struct HvLpEvent *event) +{ + HvLpIndex remoteLp; + int i; + + /* + * This handler is _also_ called as part of the loop + * at the end of this routine, so it must be able to + * ignore NULL events... + */ + if (!event) + return; + + /* + * First see if this is just a normal monitor message from the + * other partition + */ + if (event->xFlags.xFunction == HvLpEvent_Function_Int) { + remoteLp = event->xSourceLp; + if (!viopathStatus[remoteLp].isActive) + sendMonMsg(remoteLp); + return; + } + + /* + * This path is for an acknowledgement; the other partition + * died + */ + remoteLp = event->xTargetLp; + if ((event->xSourceInstanceId != viopathStatus[remoteLp].mSourceInst) || + (event->xTargetInstanceId != viopathStatus[remoteLp].mTargetInst)) { + printk(VIOPATH_KERN_WARN "ignoring ack....mismatched instances\n"); + return; + } + + printk(VIOPATH_KERN_WARN "partition %d ended\n", remoteLp); + + viopathStatus[remoteLp].isActive = 0; + + /* + * For each active handler, pass them a NULL + * message to indicate that the other partition + * died + */ + for (i = 0; i < VIO_MAX_SUBTYPES; i++) { + if (vio_handler[i] != NULL) + (*vio_handler[i])(NULL); + } +} + +int vio_setHandler(int subtype, vio_event_handler_t *beh) +{ + subtype = subtype >> VIOMAJOR_SUBTYPE_SHIFT; + if ((subtype < 0) || (subtype >= VIO_MAX_SUBTYPES)) + return -EINVAL; + if (vio_handler[subtype] != NULL) + return -EBUSY; + vio_handler[subtype] = beh; + return 0; +} +EXPORT_SYMBOL(vio_setHandler); + +int vio_clearHandler(int subtype) +{ + subtype = subtype >> VIOMAJOR_SUBTYPE_SHIFT; + if ((subtype < 0) || (subtype >= VIO_MAX_SUBTYPES)) + return -EINVAL; + if (vio_handler[subtype] == NULL) + return -EAGAIN; + vio_handler[subtype] = NULL; + return 0; +} +EXPORT_SYMBOL(vio_clearHandler); + +static void handleConfig(struct HvLpEvent *event) +{ + if (!event) + return; + if (event->xFlags.xFunction == HvLpEvent_Function_Int) { + printk(VIOPATH_KERN_WARN + "unexpected config request from partition %d", + event->xSourceLp); + + if ((event->xFlags.xFunction == HvLpEvent_Function_Int) && + (event->xFlags.xAckInd == HvLpEvent_AckInd_DoAck)) { + event->xRc = HvLpEvent_Rc_InvalidSubtype; + HvCallEvent_ackLpEvent(event); + } + return; + } + + up((struct semaphore *)event->xCorrelationToken); +} + +/* + * Initialization of the hosting partition + */ +void vio_set_hostlp(void) +{ + /* + * If this has already been set then we DON'T want to either change + * it or re-register the proc file system + */ + if (viopath_hostLp != HvLpIndexInvalid) + return; + + /* + * Figure out our hosting partition. This isn't allowed to change + * while we're active + */ + viopath_ourLp = HvLpConfig_getLpIndex(); + viopath_hostLp = HvLpConfig_getHostingLpIndex(viopath_ourLp); + + if (viopath_hostLp != HvLpIndexInvalid) + vio_setHandler(viomajorsubtype_config, handleConfig); +} +EXPORT_SYMBOL(vio_set_hostlp); + +static void vio_handleEvent(struct HvLpEvent *event, struct pt_regs *regs) +{ + HvLpIndex remoteLp; + int subtype = (event->xSubtype & VIOMAJOR_SUBTYPE_MASK) + >> VIOMAJOR_SUBTYPE_SHIFT; + + if (event->xFlags.xFunction == HvLpEvent_Function_Int) { + remoteLp = event->xSourceLp; + /* + * The isActive is checked because if the hosting partition + * went down and came back up it would not be active but it + * would have different source and target instances, in which + * case we'd want to reset them. This case really protects + * against an unauthorized active partition sending interrupts + * or acks to this linux partition. + */ + if (viopathStatus[remoteLp].isActive + && (event->xSourceInstanceId != + viopathStatus[remoteLp].mTargetInst)) { + printk(VIOPATH_KERN_WARN + "message from invalid partition. " + "int msg rcvd, source inst (%d) doesnt match (%d)\n", + viopathStatus[remoteLp].mTargetInst, + event->xSourceInstanceId); + return; + } + + if (viopathStatus[remoteLp].isActive + && (event->xTargetInstanceId != + viopathStatus[remoteLp].mSourceInst)) { + printk(VIOPATH_KERN_WARN + "message from invalid partition. " + "int msg rcvd, target inst (%d) doesnt match (%d)\n", + viopathStatus[remoteLp].mSourceInst, + event->xTargetInstanceId); + return; + } + } else { + remoteLp = event->xTargetLp; + if (event->xSourceInstanceId != + viopathStatus[remoteLp].mSourceInst) { + printk(VIOPATH_KERN_WARN + "message from invalid partition. " + "ack msg rcvd, source inst (%d) doesnt match (%d)\n", + viopathStatus[remoteLp].mSourceInst, + event->xSourceInstanceId); + return; + } + + if (event->xTargetInstanceId != + viopathStatus[remoteLp].mTargetInst) { + printk(VIOPATH_KERN_WARN + "message from invalid partition. " + "viopath: ack msg rcvd, target inst (%d) doesnt match (%d)\n", + viopathStatus[remoteLp].mTargetInst, + event->xTargetInstanceId); + return; + } + } + + if (vio_handler[subtype] == NULL) { + printk(VIOPATH_KERN_WARN + "unexpected virtual io event subtype %d from partition %d\n", + event->xSubtype, remoteLp); + /* No handler. Ack if necessary */ + if ((event->xFlags.xFunction == HvLpEvent_Function_Int) && + (event->xFlags.xAckInd == HvLpEvent_AckInd_DoAck)) { + event->xRc = HvLpEvent_Rc_InvalidSubtype; + HvCallEvent_ackLpEvent(event); + } + return; + } + + /* This innocuous little line is where all the real work happens */ + (*vio_handler[subtype])(event); +} + +static void viopath_donealloc(void *parm, int number) +{ + struct alloc_parms *parmsp = parm; + + parmsp->number = number; + if (parmsp->used_wait_atomic) + atomic_set(&parmsp->wait_atomic, 0); + else + up(&parmsp->sem); +} + +static int allocateEvents(HvLpIndex remoteLp, int numEvents) +{ + struct alloc_parms parms; + + if (system_state != SYSTEM_RUNNING) { + parms.used_wait_atomic = 1; + atomic_set(&parms.wait_atomic, 1); + } else { + parms.used_wait_atomic = 0; + init_MUTEX_LOCKED(&parms.sem); + } + mf_allocate_lp_events(remoteLp, HvLpEvent_Type_VirtualIo, 250, /* It would be nice to put a real number here! */ + numEvents, &viopath_donealloc, &parms); + if (system_state != SYSTEM_RUNNING) { + while (atomic_read(&parms.wait_atomic)) + mb(); + } else + down(&parms.sem); + return parms.number; +} + +int viopath_open(HvLpIndex remoteLp, int subtype, int numReq) +{ + int i; + unsigned long flags; + int tempNumAllocated; + + if ((remoteLp >= HVMAXARCHITECTEDLPS) || (remoteLp == HvLpIndexInvalid)) + return -EINVAL; + + subtype = subtype >> VIOMAJOR_SUBTYPE_SHIFT; + if ((subtype < 0) || (subtype >= VIO_MAX_SUBTYPES)) + return -EINVAL; + + spin_lock_irqsave(&statuslock, flags); + + if (!event_buffer_initialised) { + for (i = 0; i < VIO_MAX_SUBTYPES; i++) + atomic_set(&event_buffer_available[i], 1); + event_buffer_initialised = 1; + } + + viopathStatus[remoteLp].users[subtype]++; + + if (!viopathStatus[remoteLp].isOpen) { + viopathStatus[remoteLp].isOpen = 1; + HvCallEvent_openLpEventPath(remoteLp, HvLpEvent_Type_VirtualIo); + + /* + * Don't hold the spinlock during an operation that + * can sleep. + */ + spin_unlock_irqrestore(&statuslock, flags); + tempNumAllocated = allocateEvents(remoteLp, 1); + spin_lock_irqsave(&statuslock, flags); + + viopathStatus[remoteLp].numberAllocated += tempNumAllocated; + + if (viopathStatus[remoteLp].numberAllocated == 0) { + HvCallEvent_closeLpEventPath(remoteLp, + HvLpEvent_Type_VirtualIo); + + spin_unlock_irqrestore(&statuslock, flags); + return -ENOMEM; + } + + viopathStatus[remoteLp].mSourceInst = + HvCallEvent_getSourceLpInstanceId(remoteLp, + HvLpEvent_Type_VirtualIo); + viopathStatus[remoteLp].mTargetInst = + HvCallEvent_getTargetLpInstanceId(remoteLp, + HvLpEvent_Type_VirtualIo); + HvLpEvent_registerHandler(HvLpEvent_Type_VirtualIo, + &vio_handleEvent); + sendMonMsg(remoteLp); + printk(VIOPATH_KERN_INFO "opening connection to partition %d, " + "setting sinst %d, tinst %d\n", + remoteLp, viopathStatus[remoteLp].mSourceInst, + viopathStatus[remoteLp].mTargetInst); + } + + spin_unlock_irqrestore(&statuslock, flags); + tempNumAllocated = allocateEvents(remoteLp, numReq); + spin_lock_irqsave(&statuslock, flags); + viopathStatus[remoteLp].numberAllocated += tempNumAllocated; + spin_unlock_irqrestore(&statuslock, flags); + + return 0; +} +EXPORT_SYMBOL(viopath_open); + +int viopath_close(HvLpIndex remoteLp, int subtype, int numReq) +{ + unsigned long flags; + int i; + int numOpen; + struct alloc_parms parms; + + if ((remoteLp >= HVMAXARCHITECTEDLPS) || (remoteLp == HvLpIndexInvalid)) + return -EINVAL; + + subtype = subtype >> VIOMAJOR_SUBTYPE_SHIFT; + if ((subtype < 0) || (subtype >= VIO_MAX_SUBTYPES)) + return -EINVAL; + + spin_lock_irqsave(&statuslock, flags); + /* + * If the viopath_close somehow gets called before a + * viopath_open it could decrement to -1 which is a non + * recoverable state so we'll prevent this from + * happening. + */ + if (viopathStatus[remoteLp].users[subtype] > 0) + viopathStatus[remoteLp].users[subtype]--; + + spin_unlock_irqrestore(&statuslock, flags); + + parms.used_wait_atomic = 0; + init_MUTEX_LOCKED(&parms.sem); + mf_deallocate_lp_events(remoteLp, HvLpEvent_Type_VirtualIo, + numReq, &viopath_donealloc, &parms); + down(&parms.sem); + + spin_lock_irqsave(&statuslock, flags); + for (i = 0, numOpen = 0; i < VIO_MAX_SUBTYPES; i++) + numOpen += viopathStatus[remoteLp].users[i]; + + if ((viopathStatus[remoteLp].isOpen) && (numOpen == 0)) { + printk(VIOPATH_KERN_INFO "closing connection to partition %d", + remoteLp); + + HvCallEvent_closeLpEventPath(remoteLp, + HvLpEvent_Type_VirtualIo); + viopathStatus[remoteLp].isOpen = 0; + viopathStatus[remoteLp].isActive = 0; + + for (i = 0; i < VIO_MAX_SUBTYPES; i++) + atomic_set(&event_buffer_available[i], 0); + event_buffer_initialised = 0; + } + spin_unlock_irqrestore(&statuslock, flags); + return 0; +} +EXPORT_SYMBOL(viopath_close); + +void *vio_get_event_buffer(int subtype) +{ + subtype = subtype >> VIOMAJOR_SUBTYPE_SHIFT; + if ((subtype < 0) || (subtype >= VIO_MAX_SUBTYPES)) + return NULL; + + if (atomic_dec_if_positive(&event_buffer_available[subtype]) == 0) + return &event_buffer[subtype * 256]; + else + return NULL; +} +EXPORT_SYMBOL(vio_get_event_buffer); + +void vio_free_event_buffer(int subtype, void *buffer) +{ + subtype = subtype >> VIOMAJOR_SUBTYPE_SHIFT; + if ((subtype < 0) || (subtype >= VIO_MAX_SUBTYPES)) { + printk(VIOPATH_KERN_WARN + "unexpected subtype %d freeing event buffer\n", subtype); + return; + } + + if (atomic_read(&event_buffer_available[subtype]) != 0) { + printk(VIOPATH_KERN_WARN + "freeing unallocated event buffer, subtype %d\n", + subtype); + return; + } + + if (buffer != &event_buffer[subtype * 256]) { + printk(VIOPATH_KERN_WARN + "freeing invalid event buffer, subtype %d\n", subtype); + } + + atomic_set(&event_buffer_available[subtype], 1); +} +EXPORT_SYMBOL(vio_free_event_buffer); + +static const struct vio_error_entry vio_no_error = + { 0, 0, "Non-VIO Error" }; +static const struct vio_error_entry vio_unknown_error = + { 0, EIO, "Unknown Error" }; + +static const struct vio_error_entry vio_default_errors[] = { + {0x0001, EIO, "No Connection"}, + {0x0002, EIO, "No Receiver"}, + {0x0003, EIO, "No Buffer Available"}, + {0x0004, EBADRQC, "Invalid Message Type"}, + {0x0000, 0, NULL}, +}; + +const struct vio_error_entry *vio_lookup_rc( + const struct vio_error_entry *local_table, u16 rc) +{ + const struct vio_error_entry *cur; + + if (!rc) + return &vio_no_error; + if (local_table) + for (cur = local_table; cur->rc; ++cur) + if (cur->rc == rc) + return cur; + for (cur = vio_default_errors; cur->rc; ++cur) + if (cur->rc == rc) + return cur; + return &vio_unknown_error; +} +EXPORT_SYMBOL(vio_lookup_rc); diff --git a/arch/ppc64/kernel/Makefile b/arch/ppc64/kernel/Makefile --- a/arch/ppc64/kernel/Makefile +++ b/arch/ppc64/kernel/Makefile @@ -38,7 +38,6 @@ obj-$(CONFIG_MODULES) += module.o ppc_k obj-$(CONFIG_PPC_RTAS) += rtas.o rtas_pci.o obj-$(CONFIG_RTAS_PROC) += rtas-proc.o obj-$(CONFIG_SCANLOG) += scanlog.o -obj-$(CONFIG_VIOPATH) += viopath.o obj-$(CONFIG_LPARCFG) += lparcfg.o obj-$(CONFIG_HVC_CONSOLE) += hvconsole.o obj-$(CONFIG_BOOTX_TEXT) += btext.o diff --git a/arch/ppc64/kernel/viopath.c b/arch/ppc64/kernel/viopath.c deleted file mode 100644 --- a/arch/ppc64/kernel/viopath.c +++ /dev/null @@ -1,673 +0,0 @@ -/* -*- linux-c -*- - * arch/ppc64/kernel/viopath.c - * - * iSeries Virtual I/O Message Path code - * - * Authors: Dave Boutcher - * Ryan Arnold - * Colin Devilbiss - * - * (C) Copyright 2000-2003 IBM Corporation - * - * This code is used by the iSeries virtual disk, cd, - * tape, and console to communicate with OS/400 in another - * partition. - * - * 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) anyu later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -/* Status of the path to each other partition in the system. - * This is overkill, since we will only ever establish connections - * to our hosting partition and the primary partition on the system. - * But this allows for other support in the future. - */ -static struct viopathStatus { - int isOpen; /* Did we open the path? */ - int isActive; /* Do we have a mon msg outstanding */ - int users[VIO_MAX_SUBTYPES]; - HvLpInstanceId mSourceInst; - HvLpInstanceId mTargetInst; - int numberAllocated; -} viopathStatus[HVMAXARCHITECTEDLPS]; - -static DEFINE_SPINLOCK(statuslock); - -/* - * For each kind of event we allocate a buffer that is - * guaranteed not to cross a page boundary - */ -static unsigned char event_buffer[VIO_MAX_SUBTYPES * 256] __page_aligned; -static atomic_t event_buffer_available[VIO_MAX_SUBTYPES]; -static int event_buffer_initialised; - -static void handleMonitorEvent(struct HvLpEvent *event); - -/* - * We use this structure to handle asynchronous responses. The caller - * blocks on the semaphore and the handler posts the semaphore. However, - * if system_state is not SYSTEM_RUNNING, then wait_atomic is used ... - */ -struct alloc_parms { - struct semaphore sem; - int number; - atomic_t wait_atomic; - int used_wait_atomic; -}; - -/* Put a sequence number in each mon msg. The value is not - * important. Start at something other than 0 just for - * readability. wrapping this is ok. - */ -static u8 viomonseq = 22; - -/* Our hosting logical partition. We get this at startup - * time, and different modules access this variable directly. - */ -HvLpIndex viopath_hostLp = HvLpIndexInvalid; -EXPORT_SYMBOL(viopath_hostLp); -HvLpIndex viopath_ourLp = HvLpIndexInvalid; -EXPORT_SYMBOL(viopath_ourLp); - -/* For each kind of incoming event we set a pointer to a - * routine to call. - */ -static vio_event_handler_t *vio_handler[VIO_MAX_SUBTYPES]; - -#define VIOPATH_KERN_WARN KERN_WARNING "viopath: " -#define VIOPATH_KERN_INFO KERN_INFO "viopath: " - -static int proc_viopath_show(struct seq_file *m, void *v) -{ - char *buf; - u16 vlanMap; - dma_addr_t handle; - HvLpEvent_Rc hvrc; - DECLARE_MUTEX_LOCKED(Semaphore); - - buf = kmalloc(PAGE_SIZE, GFP_KERNEL); - if (!buf) - return 0; - memset(buf, 0, PAGE_SIZE); - - handle = dma_map_single(iSeries_vio_dev, buf, PAGE_SIZE, - DMA_FROM_DEVICE); - - hvrc = HvCallEvent_signalLpEventFast(viopath_hostLp, - HvLpEvent_Type_VirtualIo, - viomajorsubtype_config | vioconfigget, - HvLpEvent_AckInd_DoAck, HvLpEvent_AckType_ImmediateAck, - viopath_sourceinst(viopath_hostLp), - viopath_targetinst(viopath_hostLp), - (u64)(unsigned long)&Semaphore, VIOVERSION << 16, - ((u64)handle) << 32, PAGE_SIZE, 0, 0); - - if (hvrc != HvLpEvent_Rc_Good) - printk(VIOPATH_KERN_WARN "hv error on op %d\n", (int)hvrc); - - down(&Semaphore); - - vlanMap = HvLpConfig_getVirtualLanIndexMap(); - - buf[PAGE_SIZE-1] = '\0'; - seq_printf(m, "%s", buf); - seq_printf(m, "AVAILABLE_VETH=%x\n", vlanMap); - seq_printf(m, "SRLNBR=%c%c%c%c%c%c%c\n", - e2a(xItExtVpdPanel.mfgID[2]), - e2a(xItExtVpdPanel.mfgID[3]), - e2a(xItExtVpdPanel.systemSerial[1]), - e2a(xItExtVpdPanel.systemSerial[2]), - e2a(xItExtVpdPanel.systemSerial[3]), - e2a(xItExtVpdPanel.systemSerial[4]), - e2a(xItExtVpdPanel.systemSerial[5])); - - dma_unmap_single(iSeries_vio_dev, handle, PAGE_SIZE, DMA_FROM_DEVICE); - kfree(buf); - - return 0; -} - -static int proc_viopath_open(struct inode *inode, struct file *file) -{ - return single_open(file, proc_viopath_show, NULL); -} - -static struct file_operations proc_viopath_operations = { - .open = proc_viopath_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, -}; - -static int __init vio_proc_init(void) -{ - struct proc_dir_entry *e; - - e = create_proc_entry("iSeries/config", 0, NULL); - if (e) - e->proc_fops = &proc_viopath_operations; - - return 0; -} -__initcall(vio_proc_init); - -/* See if a given LP is active. Allow for invalid lps to be passed in - * and just return invalid - */ -int viopath_isactive(HvLpIndex lp) -{ - if (lp == HvLpIndexInvalid) - return 0; - if (lp < HVMAXARCHITECTEDLPS) - return viopathStatus[lp].isActive; - else - return 0; -} -EXPORT_SYMBOL(viopath_isactive); - -/* - * We cache the source and target instance ids for each - * partition. - */ -HvLpInstanceId viopath_sourceinst(HvLpIndex lp) -{ - return viopathStatus[lp].mSourceInst; -} -EXPORT_SYMBOL(viopath_sourceinst); - -HvLpInstanceId viopath_targetinst(HvLpIndex lp) -{ - return viopathStatus[lp].mTargetInst; -} -EXPORT_SYMBOL(viopath_targetinst); - -/* - * Send a monitor message. This is a message with the acknowledge - * bit on that the other side will NOT explicitly acknowledge. When - * the other side goes down, the hypervisor will acknowledge any - * outstanding messages....so we will know when the other side dies. - */ -static void sendMonMsg(HvLpIndex remoteLp) -{ - HvLpEvent_Rc hvrc; - - viopathStatus[remoteLp].mSourceInst = - HvCallEvent_getSourceLpInstanceId(remoteLp, - HvLpEvent_Type_VirtualIo); - viopathStatus[remoteLp].mTargetInst = - HvCallEvent_getTargetLpInstanceId(remoteLp, - HvLpEvent_Type_VirtualIo); - - /* - * Deliberately ignore the return code here. if we call this - * more than once, we don't care. - */ - vio_setHandler(viomajorsubtype_monitor, handleMonitorEvent); - - hvrc = HvCallEvent_signalLpEventFast(remoteLp, HvLpEvent_Type_VirtualIo, - viomajorsubtype_monitor, HvLpEvent_AckInd_DoAck, - HvLpEvent_AckType_DeferredAck, - viopathStatus[remoteLp].mSourceInst, - viopathStatus[remoteLp].mTargetInst, - viomonseq++, 0, 0, 0, 0, 0); - - if (hvrc == HvLpEvent_Rc_Good) - viopathStatus[remoteLp].isActive = 1; - else { - printk(VIOPATH_KERN_WARN "could not connect to partition %d\n", - remoteLp); - viopathStatus[remoteLp].isActive = 0; - } -} - -static void handleMonitorEvent(struct HvLpEvent *event) -{ - HvLpIndex remoteLp; - int i; - - /* - * This handler is _also_ called as part of the loop - * at the end of this routine, so it must be able to - * ignore NULL events... - */ - if (!event) - return; - - /* - * First see if this is just a normal monitor message from the - * other partition - */ - if (event->xFlags.xFunction == HvLpEvent_Function_Int) { - remoteLp = event->xSourceLp; - if (!viopathStatus[remoteLp].isActive) - sendMonMsg(remoteLp); - return; - } - - /* - * This path is for an acknowledgement; the other partition - * died - */ - remoteLp = event->xTargetLp; - if ((event->xSourceInstanceId != viopathStatus[remoteLp].mSourceInst) || - (event->xTargetInstanceId != viopathStatus[remoteLp].mTargetInst)) { - printk(VIOPATH_KERN_WARN "ignoring ack....mismatched instances\n"); - return; - } - - printk(VIOPATH_KERN_WARN "partition %d ended\n", remoteLp); - - viopathStatus[remoteLp].isActive = 0; - - /* - * For each active handler, pass them a NULL - * message to indicate that the other partition - * died - */ - for (i = 0; i < VIO_MAX_SUBTYPES; i++) { - if (vio_handler[i] != NULL) - (*vio_handler[i])(NULL); - } -} - -int vio_setHandler(int subtype, vio_event_handler_t *beh) -{ - subtype = subtype >> VIOMAJOR_SUBTYPE_SHIFT; - if ((subtype < 0) || (subtype >= VIO_MAX_SUBTYPES)) - return -EINVAL; - if (vio_handler[subtype] != NULL) - return -EBUSY; - vio_handler[subtype] = beh; - return 0; -} -EXPORT_SYMBOL(vio_setHandler); - -int vio_clearHandler(int subtype) -{ - subtype = subtype >> VIOMAJOR_SUBTYPE_SHIFT; - if ((subtype < 0) || (subtype >= VIO_MAX_SUBTYPES)) - return -EINVAL; - if (vio_handler[subtype] == NULL) - return -EAGAIN; - vio_handler[subtype] = NULL; - return 0; -} -EXPORT_SYMBOL(vio_clearHandler); - -static void handleConfig(struct HvLpEvent *event) -{ - if (!event) - return; - if (event->xFlags.xFunction == HvLpEvent_Function_Int) { - printk(VIOPATH_KERN_WARN - "unexpected config request from partition %d", - event->xSourceLp); - - if ((event->xFlags.xFunction == HvLpEvent_Function_Int) && - (event->xFlags.xAckInd == HvLpEvent_AckInd_DoAck)) { - event->xRc = HvLpEvent_Rc_InvalidSubtype; - HvCallEvent_ackLpEvent(event); - } - return; - } - - up((struct semaphore *)event->xCorrelationToken); -} - -/* - * Initialization of the hosting partition - */ -void vio_set_hostlp(void) -{ - /* - * If this has already been set then we DON'T want to either change - * it or re-register the proc file system - */ - if (viopath_hostLp != HvLpIndexInvalid) - return; - - /* - * Figure out our hosting partition. This isn't allowed to change - * while we're active - */ - viopath_ourLp = HvLpConfig_getLpIndex(); - viopath_hostLp = HvLpConfig_getHostingLpIndex(viopath_ourLp); - - if (viopath_hostLp != HvLpIndexInvalid) - vio_setHandler(viomajorsubtype_config, handleConfig); -} -EXPORT_SYMBOL(vio_set_hostlp); - -static void vio_handleEvent(struct HvLpEvent *event, struct pt_regs *regs) -{ - HvLpIndex remoteLp; - int subtype = (event->xSubtype & VIOMAJOR_SUBTYPE_MASK) - >> VIOMAJOR_SUBTYPE_SHIFT; - - if (event->xFlags.xFunction == HvLpEvent_Function_Int) { - remoteLp = event->xSourceLp; - /* - * The isActive is checked because if the hosting partition - * went down and came back up it would not be active but it - * would have different source and target instances, in which - * case we'd want to reset them. This case really protects - * against an unauthorized active partition sending interrupts - * or acks to this linux partition. - */ - if (viopathStatus[remoteLp].isActive - && (event->xSourceInstanceId != - viopathStatus[remoteLp].mTargetInst)) { - printk(VIOPATH_KERN_WARN - "message from invalid partition. " - "int msg rcvd, source inst (%d) doesnt match (%d)\n", - viopathStatus[remoteLp].mTargetInst, - event->xSourceInstanceId); - return; - } - - if (viopathStatus[remoteLp].isActive - && (event->xTargetInstanceId != - viopathStatus[remoteLp].mSourceInst)) { - printk(VIOPATH_KERN_WARN - "message from invalid partition. " - "int msg rcvd, target inst (%d) doesnt match (%d)\n", - viopathStatus[remoteLp].mSourceInst, - event->xTargetInstanceId); - return; - } - } else { - remoteLp = event->xTargetLp; - if (event->xSourceInstanceId != - viopathStatus[remoteLp].mSourceInst) { - printk(VIOPATH_KERN_WARN - "message from invalid partition. " - "ack msg rcvd, source inst (%d) doesnt match (%d)\n", - viopathStatus[remoteLp].mSourceInst, - event->xSourceInstanceId); - return; - } - - if (event->xTargetInstanceId != - viopathStatus[remoteLp].mTargetInst) { - printk(VIOPATH_KERN_WARN - "message from invalid partition. " - "viopath: ack msg rcvd, target inst (%d) doesnt match (%d)\n", - viopathStatus[remoteLp].mTargetInst, - event->xTargetInstanceId); - return; - } - } - - if (vio_handler[subtype] == NULL) { - printk(VIOPATH_KERN_WARN - "unexpected virtual io event subtype %d from partition %d\n", - event->xSubtype, remoteLp); - /* No handler. Ack if necessary */ - if ((event->xFlags.xFunction == HvLpEvent_Function_Int) && - (event->xFlags.xAckInd == HvLpEvent_AckInd_DoAck)) { - event->xRc = HvLpEvent_Rc_InvalidSubtype; - HvCallEvent_ackLpEvent(event); - } - return; - } - - /* This innocuous little line is where all the real work happens */ - (*vio_handler[subtype])(event); -} - -static void viopath_donealloc(void *parm, int number) -{ - struct alloc_parms *parmsp = parm; - - parmsp->number = number; - if (parmsp->used_wait_atomic) - atomic_set(&parmsp->wait_atomic, 0); - else - up(&parmsp->sem); -} - -static int allocateEvents(HvLpIndex remoteLp, int numEvents) -{ - struct alloc_parms parms; - - if (system_state != SYSTEM_RUNNING) { - parms.used_wait_atomic = 1; - atomic_set(&parms.wait_atomic, 1); - } else { - parms.used_wait_atomic = 0; - init_MUTEX_LOCKED(&parms.sem); - } - mf_allocate_lp_events(remoteLp, HvLpEvent_Type_VirtualIo, 250, /* It would be nice to put a real number here! */ - numEvents, &viopath_donealloc, &parms); - if (system_state != SYSTEM_RUNNING) { - while (atomic_read(&parms.wait_atomic)) - mb(); - } else - down(&parms.sem); - return parms.number; -} - -int viopath_open(HvLpIndex remoteLp, int subtype, int numReq) -{ - int i; - unsigned long flags; - int tempNumAllocated; - - if ((remoteLp >= HVMAXARCHITECTEDLPS) || (remoteLp == HvLpIndexInvalid)) - return -EINVAL; - - subtype = subtype >> VIOMAJOR_SUBTYPE_SHIFT; - if ((subtype < 0) || (subtype >= VIO_MAX_SUBTYPES)) - return -EINVAL; - - spin_lock_irqsave(&statuslock, flags); - - if (!event_buffer_initialised) { - for (i = 0; i < VIO_MAX_SUBTYPES; i++) - atomic_set(&event_buffer_available[i], 1); - event_buffer_initialised = 1; - } - - viopathStatus[remoteLp].users[subtype]++; - - if (!viopathStatus[remoteLp].isOpen) { - viopathStatus[remoteLp].isOpen = 1; - HvCallEvent_openLpEventPath(remoteLp, HvLpEvent_Type_VirtualIo); - - /* - * Don't hold the spinlock during an operation that - * can sleep. - */ - spin_unlock_irqrestore(&statuslock, flags); - tempNumAllocated = allocateEvents(remoteLp, 1); - spin_lock_irqsave(&statuslock, flags); - - viopathStatus[remoteLp].numberAllocated += tempNumAllocated; - - if (viopathStatus[remoteLp].numberAllocated == 0) { - HvCallEvent_closeLpEventPath(remoteLp, - HvLpEvent_Type_VirtualIo); - - spin_unlock_irqrestore(&statuslock, flags); - return -ENOMEM; - } - - viopathStatus[remoteLp].mSourceInst = - HvCallEvent_getSourceLpInstanceId(remoteLp, - HvLpEvent_Type_VirtualIo); - viopathStatus[remoteLp].mTargetInst = - HvCallEvent_getTargetLpInstanceId(remoteLp, - HvLpEvent_Type_VirtualIo); - HvLpEvent_registerHandler(HvLpEvent_Type_VirtualIo, - &vio_handleEvent); - sendMonMsg(remoteLp); - printk(VIOPATH_KERN_INFO "opening connection to partition %d, " - "setting sinst %d, tinst %d\n", - remoteLp, viopathStatus[remoteLp].mSourceInst, - viopathStatus[remoteLp].mTargetInst); - } - - spin_unlock_irqrestore(&statuslock, flags); - tempNumAllocated = allocateEvents(remoteLp, numReq); - spin_lock_irqsave(&statuslock, flags); - viopathStatus[remoteLp].numberAllocated += tempNumAllocated; - spin_unlock_irqrestore(&statuslock, flags); - - return 0; -} -EXPORT_SYMBOL(viopath_open); - -int viopath_close(HvLpIndex remoteLp, int subtype, int numReq) -{ - unsigned long flags; - int i; - int numOpen; - struct alloc_parms parms; - - if ((remoteLp >= HVMAXARCHITECTEDLPS) || (remoteLp == HvLpIndexInvalid)) - return -EINVAL; - - subtype = subtype >> VIOMAJOR_SUBTYPE_SHIFT; - if ((subtype < 0) || (subtype >= VIO_MAX_SUBTYPES)) - return -EINVAL; - - spin_lock_irqsave(&statuslock, flags); - /* - * If the viopath_close somehow gets called before a - * viopath_open it could decrement to -1 which is a non - * recoverable state so we'll prevent this from - * happening. - */ - if (viopathStatus[remoteLp].users[subtype] > 0) - viopathStatus[remoteLp].users[subtype]--; - - spin_unlock_irqrestore(&statuslock, flags); - - parms.used_wait_atomic = 0; - init_MUTEX_LOCKED(&parms.sem); - mf_deallocate_lp_events(remoteLp, HvLpEvent_Type_VirtualIo, - numReq, &viopath_donealloc, &parms); - down(&parms.sem); - - spin_lock_irqsave(&statuslock, flags); - for (i = 0, numOpen = 0; i < VIO_MAX_SUBTYPES; i++) - numOpen += viopathStatus[remoteLp].users[i]; - - if ((viopathStatus[remoteLp].isOpen) && (numOpen == 0)) { - printk(VIOPATH_KERN_INFO "closing connection to partition %d", - remoteLp); - - HvCallEvent_closeLpEventPath(remoteLp, - HvLpEvent_Type_VirtualIo); - viopathStatus[remoteLp].isOpen = 0; - viopathStatus[remoteLp].isActive = 0; - - for (i = 0; i < VIO_MAX_SUBTYPES; i++) - atomic_set(&event_buffer_available[i], 0); - event_buffer_initialised = 0; - } - spin_unlock_irqrestore(&statuslock, flags); - return 0; -} -EXPORT_SYMBOL(viopath_close); - -void *vio_get_event_buffer(int subtype) -{ - subtype = subtype >> VIOMAJOR_SUBTYPE_SHIFT; - if ((subtype < 0) || (subtype >= VIO_MAX_SUBTYPES)) - return NULL; - - if (atomic_dec_if_positive(&event_buffer_available[subtype]) == 0) - return &event_buffer[subtype * 256]; - else - return NULL; -} -EXPORT_SYMBOL(vio_get_event_buffer); - -void vio_free_event_buffer(int subtype, void *buffer) -{ - subtype = subtype >> VIOMAJOR_SUBTYPE_SHIFT; - if ((subtype < 0) || (subtype >= VIO_MAX_SUBTYPES)) { - printk(VIOPATH_KERN_WARN - "unexpected subtype %d freeing event buffer\n", subtype); - return; - } - - if (atomic_read(&event_buffer_available[subtype]) != 0) { - printk(VIOPATH_KERN_WARN - "freeing unallocated event buffer, subtype %d\n", - subtype); - return; - } - - if (buffer != &event_buffer[subtype * 256]) { - printk(VIOPATH_KERN_WARN - "freeing invalid event buffer, subtype %d\n", subtype); - } - - atomic_set(&event_buffer_available[subtype], 1); -} -EXPORT_SYMBOL(vio_free_event_buffer); - -static const struct vio_error_entry vio_no_error = - { 0, 0, "Non-VIO Error" }; -static const struct vio_error_entry vio_unknown_error = - { 0, EIO, "Unknown Error" }; - -static const struct vio_error_entry vio_default_errors[] = { - {0x0001, EIO, "No Connection"}, - {0x0002, EIO, "No Receiver"}, - {0x0003, EIO, "No Buffer Available"}, - {0x0004, EBADRQC, "Invalid Message Type"}, - {0x0000, 0, NULL}, -}; - -const struct vio_error_entry *vio_lookup_rc( - const struct vio_error_entry *local_table, u16 rc) -{ - const struct vio_error_entry *cur; - - if (!rc) - return &vio_no_error; - if (local_table) - for (cur = local_table; cur->rc; ++cur) - if (cur->rc == rc) - return cur; - for (cur = vio_default_errors; cur->rc; ++cur) - if (cur->rc == rc) - return cur; - return &vio_unknown_error; -} -EXPORT_SYMBOL(vio_lookup_rc); From sfr at canb.auug.org.au Wed Sep 28 17:02:57 2005 From: sfr at canb.auug.org.au (Stephen Rothwell) Date: Wed, 28 Sep 2005 17:02:57 +1000 Subject: [PATCH 17/19] powerpc: Make powerpc pmac 32 bit build again In-Reply-To: <20050928163333.02799419.sfr@canb.auug.org.au> References: <20050928163333.02799419.sfr@canb.auug.org.au> Message-ID: <20050928170257.47dcafcf.sfr@canb.auug.org.au> Until we fix up the 64bit powermac merge. Signed-off-by: Stephen Rothwell --- arch/powerpc/platforms/Makefile | 2 ++ 1 files changed, 2 insertions(+), 0 deletions(-) -- Cheers, Stephen Rothwell sfr at canb.auug.org.au http://www.canb.auug.org.au/~sfr/ 7b875f4dc345dc5f6a2c3bd0e1f90bfee46b2258 diff --git a/arch/powerpc/platforms/Makefile b/arch/powerpc/platforms/Makefile --- a/arch/powerpc/platforms/Makefile +++ b/arch/powerpc/platforms/Makefile @@ -1,4 +1,6 @@ +ifeq ($(CONFIG_PPC32),y) obj-$(CONFIG_PPC_PMAC) += powermac/ +endif obj-$(CONFIG_4xx) += 4xx/ obj-$(CONFIG_83xx) += 83xx/ obj-$(CONFIG_85xx) += 85xx/ From sfr at canb.auug.org.au Wed Sep 28 17:04:41 2005 From: sfr at canb.auug.org.au (Stephen Rothwell) Date: Wed, 28 Sep 2005 17:04:41 +1000 Subject: [PATCH 18/19] powerpc: move more iSeries code In-Reply-To: <20050928163333.02799419.sfr@canb.auug.org.au> References: <20050928163333.02799419.sfr@canb.auug.org.au> Message-ID: <20050928170441.2f34fa7c.sfr@canb.auug.org.au> Move the iSeries specific parts of misc.S and ppc_ksyms.c into powerpc/platforms/iseries. Signed-off-by: Stephen Rothwell --- arch/powerpc/platforms/iseries/Makefile | 3 +- arch/powerpc/platforms/iseries/ksyms.c | 27 +++++++++++++++ arch/powerpc/platforms/iseries/misc.S | 55 +++++++++++++++++++++++++++++++ arch/ppc64/kernel/misc.S | 38 --------------------- arch/ppc64/kernel/ppc_ksyms.c | 20 ----------- 5 files changed, 84 insertions(+), 59 deletions(-) create mode 100644 arch/powerpc/platforms/iseries/ksyms.c create mode 100644 arch/powerpc/platforms/iseries/misc.S -- Cheers, Stephen Rothwell sfr at canb.auug.org.au http://www.canb.auug.org.au/~sfr/ c111d0bda8437d146ccf5101970801fe4ff23ed8 diff --git a/arch/powerpc/platforms/iseries/Makefile b/arch/powerpc/platforms/iseries/Makefile --- a/arch/powerpc/platforms/iseries/Makefile +++ b/arch/powerpc/platforms/iseries/Makefile @@ -1,6 +1,7 @@ obj-y += hvlog.o hvlpconfig.o lpardata.o setup.o mf.o lpevents.o \ - hvcall.o proc.o htab.o iommu.o + hvcall.o proc.o htab.o iommu.o misc.o obj-$(CONFIG_PCI) += pci.o irq.o vpdinfo.o obj-$(CONFIG_IBMVIO) += vio.o obj-$(CONFIG_SMP) += smp.o obj-$(CONFIG_VIOPATH) += viopath.o +obj-$(CONFIG_MODULES) += ksyms.o diff --git a/arch/powerpc/platforms/iseries/ksyms.c b/arch/powerpc/platforms/iseries/ksyms.c new file mode 100644 --- /dev/null +++ b/arch/powerpc/platforms/iseries/ksyms.c @@ -0,0 +1,27 @@ +/* + * (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 + +EXPORT_SYMBOL(HvCall0); +EXPORT_SYMBOL(HvCall1); +EXPORT_SYMBOL(HvCall2); +EXPORT_SYMBOL(HvCall3); +EXPORT_SYMBOL(HvCall4); +EXPORT_SYMBOL(HvCall5); +EXPORT_SYMBOL(HvCall6); +EXPORT_SYMBOL(HvCall7); + +#ifdef CONFIG_SMP +EXPORT_SYMBOL(local_get_flags); +EXPORT_SYMBOL(local_irq_disable); +EXPORT_SYMBOL(local_irq_restore); +#endif diff --git a/arch/powerpc/platforms/iseries/misc.S b/arch/powerpc/platforms/iseries/misc.S new file mode 100644 --- /dev/null +++ b/arch/powerpc/platforms/iseries/misc.S @@ -0,0 +1,55 @@ +/* + * This file contains miscellaneous low-level functions. + * Copyright (C) 1995-2005 IBM Corp + * + * Largely rewritten by Cort Dougan (cort at cs.nmt.edu) + * and Paul Mackerras. + * Adapted for iSeries by Mike Corrigan (mikejc at us.ibm.com) + * PPC64 updates by Dave Engebretsen (engebret at us.ibm.com) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + +#include +#include + + .text + +/* unsigned long local_save_flags(void) */ +_GLOBAL(local_get_flags) + lbz r3,PACAPROCENABLED(r13) + blr + +/* unsigned long local_irq_disable(void) */ +_GLOBAL(local_irq_disable) + lbz r3,PACAPROCENABLED(r13) + li r4,0 + stb r4,PACAPROCENABLED(r13) + blr /* Done */ + +/* void local_irq_restore(unsigned long flags) */ +_GLOBAL(local_irq_restore) + lbz r5,PACAPROCENABLED(r13) + /* Check if things are setup the way we want _already_. */ + cmpw 0,r3,r5 + beqlr + /* are we enabling interrupts? */ + cmpdi 0,r3,0 + stb r3,PACAPROCENABLED(r13) + beqlr + /* Check pending interrupts */ + /* A decrementer, IPI or PMC interrupt may have occurred + * while we were in the hypervisor (which enables) */ + ld r4,PACALPPACA+LPPACAANYINT(r13) + cmpdi r4,0 + beqlr + + /* + * Handle pending interrupts in interrupt context + */ + li r0,0x5555 + sc + blr diff --git a/arch/ppc64/kernel/misc.S b/arch/ppc64/kernel/misc.S --- a/arch/ppc64/kernel/misc.S +++ b/arch/ppc64/kernel/misc.S @@ -64,44 +64,6 @@ _GLOBAL(get_srr1) _GLOBAL(get_sp) mr r3,r1 blr - -#ifdef CONFIG_PPC_ISERIES -/* unsigned long local_save_flags(void) */ -_GLOBAL(local_get_flags) - lbz r3,PACAPROCENABLED(r13) - blr - -/* unsigned long local_irq_disable(void) */ -_GLOBAL(local_irq_disable) - lbz r3,PACAPROCENABLED(r13) - li r4,0 - stb r4,PACAPROCENABLED(r13) - blr /* Done */ - -/* void local_irq_restore(unsigned long flags) */ -_GLOBAL(local_irq_restore) - lbz r5,PACAPROCENABLED(r13) - /* Check if things are setup the way we want _already_. */ - cmpw 0,r3,r5 - beqlr - /* are we enabling interrupts? */ - cmpdi 0,r3,0 - stb r3,PACAPROCENABLED(r13) - beqlr - /* Check pending interrupts */ - /* A decrementer, IPI or PMC interrupt may have occurred - * while we were in the hypervisor (which enables) */ - ld r4,PACALPPACA+LPPACAANYINT(r13) - cmpdi r4,0 - beqlr - - /* - * Handle pending interrupts in interrupt context - */ - li r0,0x5555 - sc - blr -#endif /* CONFIG_PPC_ISERIES */ #ifdef CONFIG_IRQSTACKS _GLOBAL(call_do_softirq) diff --git a/arch/ppc64/kernel/ppc_ksyms.c b/arch/ppc64/kernel/ppc_ksyms.c --- a/arch/ppc64/kernel/ppc_ksyms.c +++ b/arch/ppc64/kernel/ppc_ksyms.c @@ -19,7 +19,6 @@ #include #include #include -#include EXPORT_SYMBOL(strcpy); EXPORT_SYMBOL(strncpy); @@ -46,17 +45,6 @@ EXPORT_SYMBOL(__strnlen_user); EXPORT_SYMBOL(reloc_offset); -#ifdef CONFIG_PPC_ISERIES -EXPORT_SYMBOL(HvCall0); -EXPORT_SYMBOL(HvCall1); -EXPORT_SYMBOL(HvCall2); -EXPORT_SYMBOL(HvCall3); -EXPORT_SYMBOL(HvCall4); -EXPORT_SYMBOL(HvCall5); -EXPORT_SYMBOL(HvCall6); -EXPORT_SYMBOL(HvCall7); -#endif - EXPORT_SYMBOL(_insb); EXPORT_SYMBOL(_outsb); EXPORT_SYMBOL(_insw); @@ -77,14 +65,6 @@ EXPORT_SYMBOL(giveup_altivec); EXPORT_SYMBOL(__flush_icache_range); EXPORT_SYMBOL(flush_dcache_range); -#ifdef CONFIG_SMP -#ifdef CONFIG_PPC_ISERIES -EXPORT_SYMBOL(local_get_flags); -EXPORT_SYMBOL(local_irq_disable); -EXPORT_SYMBOL(local_irq_restore); -#endif -#endif - EXPORT_SYMBOL(memcpy); EXPORT_SYMBOL(memset); EXPORT_SYMBOL(memmove); From sfr at canb.auug.org.au Wed Sep 28 17:05:36 2005 From: sfr at canb.auug.org.au (Stephen Rothwell) Date: Wed, 28 Sep 2005 17:05:36 +1000 Subject: [PATCH 19/19] ppc64 iSeries: use device_node instead of iSeries_Device_node In-Reply-To: <20050928163333.02799419.sfr@canb.auug.org.au> References: <20050928163333.02799419.sfr@canb.auug.org.au> Message-ID: <20050928170536.295271c8.sfr@canb.auug.org.au> There needs to be more cleanup after this. Signed-off-by: Stephen Rothwell --- arch/powerpc/platforms/iseries/iommu.c | 29 +++++----- arch/powerpc/platforms/iseries/pci.c | 91 ++++++++++++++++-------------- arch/powerpc/platforms/iseries/vpdinfo.c | 2 - arch/ppc64/kernel/pci_iommu.c | 6 -- include/asm-ppc64/iSeries/iSeries_pci.h | 30 ++-------- include/asm-ppc64/iommu.h | 4 + include/asm-ppc64/pci-bridge.h | 10 +++ include/asm-ppc64/prom.h | 3 + 8 files changed, 88 insertions(+), 87 deletions(-) -- Cheers, Stephen Rothwell sfr at canb.auug.org.au http://www.canb.auug.org.au/~sfr/ 252e75a51d40757928d692b3d339e66838294b4b diff --git a/arch/powerpc/platforms/iseries/iommu.c b/arch/powerpc/platforms/iseries/iommu.c --- a/arch/powerpc/platforms/iseries/iommu.c +++ b/arch/powerpc/platforms/iseries/iommu.c @@ -89,15 +89,17 @@ static void tce_free_iSeries(struct iomm */ static struct iommu_table *iommu_table_find(struct iommu_table * tbl) { - struct iSeries_Device_Node *dp; + struct device_node *dp; list_for_each_entry(dp, &iSeries_Global_Device_List, Device_List) { - if ((dp->iommu_table != NULL) && - (dp->iommu_table->it_type == TCE_PCI) && - (dp->iommu_table->it_offset == tbl->it_offset) && - (dp->iommu_table->it_index == tbl->it_index) && - (dp->iommu_table->it_size == tbl->it_size)) - return dp->iommu_table; + struct iommu_table *it = PCI_DN(dp)->iommu_table; + + if ((it != NULL) && + (it->it_type == TCE_PCI) && + (it->it_offset == tbl->it_offset) && + (it->it_index == tbl->it_index) && + (it->it_size == tbl->it_size)) + return it; } return NULL; } @@ -111,7 +113,7 @@ static struct iommu_table *iommu_table_f * 2. TCE table per Bus. * 3. TCE Table per IOA. */ -static void iommu_table_getparms(struct iSeries_Device_Node* dn, +static void iommu_table_getparms(struct device_node *dn, struct iommu_table* tbl) { struct iommu_table_cb *parms; @@ -123,7 +125,7 @@ static void iommu_table_getparms(struct memset(parms, 0, sizeof(*parms)); parms->itc_busno = ISERIES_BUS(dn); - parms->itc_slotno = dn->LogicalSlot; + parms->itc_slotno = PCI_DN(dn)->LogicalSlot; parms->itc_virtbus = 0; HvCallXm_getTceTableParms(ISERIES_HV_ADDR(parms)); @@ -143,18 +145,19 @@ static void iommu_table_getparms(struct } -void iommu_devnode_init_iSeries(struct iSeries_Device_Node *dn) +void iommu_devnode_init_iSeries(struct device_node *dn) { struct iommu_table *tbl; + struct pci_dn *pdn = PCI_DN(dn); tbl = kmalloc(sizeof(struct iommu_table), GFP_KERNEL); iommu_table_getparms(dn, tbl); /* Look for existing tce table */ - dn->iommu_table = iommu_table_find(tbl); - if (dn->iommu_table == NULL) - dn->iommu_table = iommu_init_table(tbl); + pdn->iommu_table = iommu_table_find(tbl); + if (pdn->iommu_table == NULL) + pdn->iommu_table = iommu_init_table(tbl); else kfree(tbl); } diff --git a/arch/powerpc/platforms/iseries/pci.c b/arch/powerpc/platforms/iseries/pci.c --- a/arch/powerpc/platforms/iseries/pci.c +++ b/arch/powerpc/platforms/iseries/pci.c @@ -48,7 +48,7 @@ extern unsigned long io_page_mask; /* * Forward declares of prototypes. */ -static struct iSeries_Device_Node *find_Device_Node(int bus, int devfn); +static struct device_node *find_Device_Node(int bus, int devfn); static void scan_PHB_slots(struct pci_controller *Phb); static void scan_EADS_bridge(HvBusNumber Bus, HvSubBusNumber SubBus, int IdSel); static int scan_bridge_slot(HvBusNumber Bus, struct HvCallPci_BridgeInfo *Info); @@ -85,7 +85,7 @@ static long current_iomm_table_entry; /* * Lookup Tables. */ -static struct iSeries_Device_Node **iomm_table; +static struct device_node **iomm_table; static u8 *iobar_table; /* @@ -199,29 +199,35 @@ static void pci_Log_Error(char *Error_Te /* * build_device_node(u16 Bus, int SubBus, u8 DevFn) */ -static struct iSeries_Device_Node *build_device_node(HvBusNumber Bus, +static struct device_node *build_device_node(HvBusNumber Bus, HvSubBusNumber SubBus, int AgentId, int Function) { - struct iSeries_Device_Node *node; + struct device_node *node; + struct pci_dn *pdn; PPCDBG(PPCDBG_BUSWALK, "-build_device_node 0x%02X.%02X.%02X Function: %02X\n", Bus, SubBus, AgentId, Function); - node = kmalloc(sizeof(struct iSeries_Device_Node), GFP_KERNEL); + node = kmalloc(sizeof(struct device_node), GFP_KERNEL); if (node == NULL) return NULL; - - memset(node, 0, sizeof(struct iSeries_Device_Node)); + memset(node, 0, sizeof(struct device_node)); + pdn = kzalloc(sizeof(*pdn), GFP_KERNEL); + if (pdn == NULL) { + kfree(node); + return NULL; + } + node->data = pdn; list_add_tail(&node->Device_List, &iSeries_Global_Device_List); #if 0 - node->DsaAddr = ((u64)Bus << 48) + ((u64)SubBus << 40) + ((u64)0x10 << 32); + pdn->DsaAddr = ((u64)Bus << 48) + ((u64)SubBus << 40) + ((u64)0x10 << 32); #endif - node->DsaAddr.DsaAddr = 0; - node->DsaAddr.Dsa.busNumber = Bus; - node->DsaAddr.Dsa.subBusNumber = SubBus; - node->DsaAddr.Dsa.deviceId = 0x10; - node->DevFn = PCI_DEVFN(ISERIES_ENCODE_DEVICE(AgentId), Function); + pdn->DsaAddr.DsaAddr = 0; + pdn->DsaAddr.Dsa.busNumber = Bus; + pdn->DsaAddr.Dsa.subBusNumber = SubBus; + pdn->DsaAddr.Dsa.deviceId = 0x10; + pdn->devfn = PCI_DEVFN(ISERIES_ENCODE_DEVICE(AgentId), Function); return node; } @@ -294,7 +300,7 @@ void iSeries_pcibios_init(void) void __init iSeries_pci_final_fixup(void) { struct pci_dev *pdev = NULL; - struct iSeries_Device_Node *node; + struct device_node *node; int DeviceCount = 0; PPCDBG(PPCDBG_BUSWALK, "iSeries_pcibios_fixup Entry.\n"); @@ -311,7 +317,7 @@ void __init iSeries_pci_final_fixup(void if (node != NULL) { ++DeviceCount; pdev->sysdata = (void *)node; - node->PciDev = pdev; + PCI_DN(node)->pcidev = pdev; PPCDBG(PPCDBG_BUSWALK, "pdev 0x%p <==> DevNode 0x%p\n", pdev, node); @@ -321,7 +327,7 @@ void __init iSeries_pci_final_fixup(void } else printk("PCI: Device Tree not found for 0x%016lX\n", (unsigned long)pdev); - pdev->irq = node->Irq; + pdev->irq = PCI_DN(node)->Irq; } iSeries_activate_IRQs(); mf_display_src(0xC9000200); @@ -439,7 +445,7 @@ static void scan_EADS_bridge(HvBusNumber static int scan_bridge_slot(HvBusNumber Bus, struct HvCallPci_BridgeInfo *BridgeInfo) { - struct iSeries_Device_Node *node; + struct device_node *node; HvSubBusNumber SubBus = BridgeInfo->subBusNumber; u16 VendorId = 0; int HvRc = 0; @@ -489,8 +495,8 @@ static int scan_bridge_slot(HvBusNumber ++DeviceCount; node = build_device_node(Bus, SubBus, EADsIdSel, Function); - node->Irq = Irq; - node->LogicalSlot = BridgeInfo->logicalSlotNumber; + PCI_DN(node)->Irq = Irq; + PCI_DN(node)->LogicalSlot = BridgeInfo->logicalSlotNumber; } /* for (Function = 0; Function < 8; ++Function) */ } /* for (IdSel = 1; IdSel <= MaxAgents; ++IdSel) */ @@ -540,15 +546,16 @@ EXPORT_SYMBOL(iSeries_memcpy_fromio); /* * Look down the chain to find the matching Device Device */ -static struct iSeries_Device_Node *find_Device_Node(int bus, int devfn) +static struct device_node *find_Device_Node(int bus, int devfn) { struct list_head *pos; list_for_each(pos, &iSeries_Global_Device_List) { - struct iSeries_Device_Node *node = - list_entry(pos, struct iSeries_Device_Node, Device_List); + struct device_node *node = + list_entry(pos, struct device_node, Device_List); - if ((bus == ISERIES_BUS(node)) && (devfn == node->DevFn)) + if ((bus == ISERIES_BUS(node)) && + (devfn == PCI_DN(node)->devfn)) return node; } return NULL; @@ -560,12 +567,12 @@ static struct iSeries_Device_Node *find_ * Sanity Check Node PciDev to passed pci_dev * If none is found, returns a NULL which the client must handle. */ -static struct iSeries_Device_Node *get_Device_Node(struct pci_dev *pdev) +static struct device_node *get_Device_Node(struct pci_dev *pdev) { - struct iSeries_Device_Node *node; + struct device_node *node; node = pdev->sysdata; - if (node == NULL || node->PciDev != pdev) + if (node == NULL || PCI_DN(node)->pcidev != pdev) node = find_Device_Node(pdev->bus->number, pdev->devfn); return node; } @@ -593,7 +600,7 @@ static u64 hv_cfg_write_func[4] = { static int iSeries_pci_read_config(struct pci_bus *bus, unsigned int devfn, int offset, int size, u32 *val) { - struct iSeries_Device_Node *node = find_Device_Node(bus->number, devfn); + struct device_node *node = find_Device_Node(bus->number, devfn); u64 fn; struct HvCallPci_LoadReturn ret; @@ -605,7 +612,7 @@ static int iSeries_pci_read_config(struc } fn = hv_cfg_read_func[(size - 1) & 3]; - HvCall3Ret16(fn, &ret, node->DsaAddr.DsaAddr, offset, 0); + HvCall3Ret16(fn, &ret, PCI_DN(node)->DsaAddr.DsaAddr, offset, 0); if (ret.rc != 0) { *val = ~0; @@ -623,7 +630,7 @@ static int iSeries_pci_read_config(struc static int iSeries_pci_write_config(struct pci_bus *bus, unsigned int devfn, int offset, int size, u32 val) { - struct iSeries_Device_Node *node = find_Device_Node(bus->number, devfn); + struct device_node *node = find_Device_Node(bus->number, devfn); u64 fn; u64 ret; @@ -633,7 +640,7 @@ static int iSeries_pci_write_config(stru return PCIBIOS_BAD_REGISTER_NUMBER; fn = hv_cfg_write_func[(size - 1) & 3]; - ret = HvCall4(fn, node->DsaAddr.DsaAddr, offset, val, 0); + ret = HvCall4(fn, PCI_DN(node)->DsaAddr.DsaAddr, offset, val, 0); if (ret != 0) return PCIBIOS_DEVICE_NOT_FOUND; @@ -655,14 +662,16 @@ static struct pci_ops iSeries_pci_ops = * PCI: Device 23.90 ReadL Retry( 1) * PCI: Device 23.90 ReadL Retry Successful(1) */ -static int CheckReturnCode(char *TextHdr, struct iSeries_Device_Node *DevNode, +static int CheckReturnCode(char *TextHdr, struct device_node *DevNode, int *retry, u64 ret) { if (ret != 0) { + struct pci_dn *pdn = PCI_DN(DevNode); + ++Pci_Error_Count; (*retry)++; printk("PCI: %s: Device 0x%04X:%02X I/O Error(%2d): 0x%04X\n", - TextHdr, DevNode->DsaAddr.Dsa.busNumber, DevNode->DevFn, + TextHdr, pdn->DsaAddr.Dsa.busNumber, pdn->devfn, *retry, (int)ret); /* * Bump the retry and check for retry count exceeded. @@ -685,14 +694,14 @@ static int CheckReturnCode(char *TextHdr * Note: Make sure the passed variable end up on the stack to avoid * the exposure of being device global. */ -static inline struct iSeries_Device_Node *xlate_iomm_address( +static inline struct device_node *xlate_iomm_address( const volatile void __iomem *IoAddress, u64 *dsaptr, u64 *BarOffsetPtr) { unsigned long OrigIoAddr; unsigned long BaseIoAddr; unsigned long TableIndex; - struct iSeries_Device_Node *DevNode; + struct device_node *DevNode; OrigIoAddr = (unsigned long __force)IoAddress; if ((OrigIoAddr < BASE_IO_MEMORY) || (OrigIoAddr >= max_io_memory)) @@ -703,7 +712,7 @@ static inline struct iSeries_Device_Node if (DevNode != NULL) { int barnum = iobar_table[TableIndex]; - *dsaptr = DevNode->DsaAddr.DsaAddr | (barnum << 24); + *dsaptr = PCI_DN(DevNode)->DsaAddr.DsaAddr | (barnum << 24); *BarOffsetPtr = BaseIoAddr % IOMM_TABLE_ENTRY_SIZE; } else panic("PCI: Invalid PCI IoAddress detected!\n"); @@ -725,7 +734,7 @@ u8 iSeries_Read_Byte(const volatile void u64 dsa; int retry = 0; struct HvCallPci_LoadReturn ret; - struct iSeries_Device_Node *DevNode = + struct device_node *DevNode = xlate_iomm_address(IoAddress, &dsa, &BarOffset); if (DevNode == NULL) { @@ -755,7 +764,7 @@ u16 iSeries_Read_Word(const volatile voi u64 dsa; int retry = 0; struct HvCallPci_LoadReturn ret; - struct iSeries_Device_Node *DevNode = + struct device_node *DevNode = xlate_iomm_address(IoAddress, &dsa, &BarOffset); if (DevNode == NULL) { @@ -786,7 +795,7 @@ u32 iSeries_Read_Long(const volatile voi u64 dsa; int retry = 0; struct HvCallPci_LoadReturn ret; - struct iSeries_Device_Node *DevNode = + struct device_node *DevNode = xlate_iomm_address(IoAddress, &dsa, &BarOffset); if (DevNode == NULL) { @@ -824,7 +833,7 @@ void iSeries_Write_Byte(u8 data, volatil u64 dsa; int retry = 0; u64 rc; - struct iSeries_Device_Node *DevNode = + struct device_node *DevNode = xlate_iomm_address(IoAddress, &dsa, &BarOffset); if (DevNode == NULL) { @@ -852,7 +861,7 @@ void iSeries_Write_Word(u16 data, volati u64 dsa; int retry = 0; u64 rc; - struct iSeries_Device_Node *DevNode = + struct device_node *DevNode = xlate_iomm_address(IoAddress, &dsa, &BarOffset); if (DevNode == NULL) { @@ -880,7 +889,7 @@ void iSeries_Write_Long(u32 data, volati u64 dsa; int retry = 0; u64 rc; - struct iSeries_Device_Node *DevNode = + struct device_node *DevNode = xlate_iomm_address(IoAddress, &dsa, &BarOffset); if (DevNode == NULL) { diff --git a/arch/powerpc/platforms/iseries/vpdinfo.c b/arch/powerpc/platforms/iseries/vpdinfo.c --- a/arch/powerpc/platforms/iseries/vpdinfo.c +++ b/arch/powerpc/platforms/iseries/vpdinfo.c @@ -240,7 +240,7 @@ out_free: */ void __init iSeries_Device_Information(struct pci_dev *PciDev, int count) { - struct iSeries_Device_Node *DevNode = PciDev->sysdata; + struct device_node *DevNode = PciDev->sysdata; u16 bus; u8 frame; char card[4]; diff --git a/arch/ppc64/kernel/pci_iommu.c b/arch/ppc64/kernel/pci_iommu.c --- a/arch/ppc64/kernel/pci_iommu.c +++ b/arch/ppc64/kernel/pci_iommu.c @@ -61,13 +61,7 @@ static inline struct iommu_table *devnod } else pdev = to_pci_dev(dev); -#ifdef CONFIG_PPC_ISERIES - return ISERIES_DEVNODE(pdev)->iommu_table; -#endif /* CONFIG_PPC_ISERIES */ - -#ifdef CONFIG_PPC_MULTIPLATFORM return PCI_DN(PCI_GET_DN(pdev))->iommu_table; -#endif /* CONFIG_PPC_MULTIPLATFORM */ } diff --git a/include/asm-ppc64/iSeries/iSeries_pci.h b/include/asm-ppc64/iSeries/iSeries_pci.h --- a/include/asm-ppc64/iSeries/iSeries_pci.h +++ b/include/asm-ppc64/iSeries/iSeries_pci.h @@ -30,21 +30,19 @@ * End Change Activity */ -#include #include +#include +#include struct pci_dev; /* For Forward Reference */ -struct iSeries_Device_Node; /* - * Gets iSeries Bus, SubBus, DevFn using iSeries_Device_Node structure + * Gets iSeries Bus, SubBus, DevFn using device_node structure */ -#define ISERIES_BUS(DevPtr) DevPtr->DsaAddr.Dsa.busNumber -#define ISERIES_SUBBUS(DevPtr) DevPtr->DsaAddr.Dsa.subBusNumber -#define ISERIES_DEVICE(DevPtr) DevPtr->DsaAddr.Dsa.deviceId -#define ISERIES_DSA(DevPtr) DevPtr->DsaAddr.DsaAddr -#define ISERIES_DEVNODE(PciDev) ((struct iSeries_Device_Node *)PciDev->sysdata) +#define ISERIES_BUS(DevPtr) PCI_DN(DevPtr)->DsaAddr.Dsa.busNumber +#define ISERIES_SUBBUS(DevPtr) PCI_DN(DevPtr)->DsaAddr.Dsa.subBusNumber +#define ISERIES_DEVNODE(PciDev) ((struct device_node *)PciDev->sysdata) #define EADsMaxAgents 7 @@ -67,22 +65,6 @@ struct iSeries_Device_Node; #define ISERIES_HV_ADDR(virtaddr) \ (0x8000000000000000 | virt_to_abs(virtaddr)) -/* - * iSeries Device Information - */ -struct iSeries_Device_Node { - struct list_head Device_List; - struct pci_dev *PciDev; - union HvDsaMap DsaAddr; /* Direct Select Address */ - /* busNumber, subBusNumber, */ - /* deviceId, barNumber */ - int DevFn; /* Linux devfn */ - int Irq; /* Assigned IRQ */ - int Flags; /* Possible flags(disable/bist)*/ - u8 LogicalSlot; /* Hv Slot Index for Tces */ - struct iommu_table *iommu_table;/* Device TCE Table */ -}; - extern void iSeries_Device_Information(struct pci_dev*, int); #endif /* _ISERIES_64_PCI_H */ diff --git a/include/asm-ppc64/iommu.h b/include/asm-ppc64/iommu.h --- a/include/asm-ppc64/iommu.h +++ b/include/asm-ppc64/iommu.h @@ -49,6 +49,7 @@ struct iommu_table { }; struct scatterlist; +struct device_node; #ifdef CONFIG_PPC_MULTIPLATFORM @@ -70,9 +71,8 @@ extern void iommu_devnode_init_pSeries(s #ifdef CONFIG_PPC_ISERIES -struct iSeries_Device_Node; /* Creates table for an individual device node */ -extern void iommu_devnode_init_iSeries(struct iSeries_Device_Node *dn); +extern void iommu_devnode_init_iSeries(struct device_node *dn); #endif /* CONFIG_PPC_ISERIES */ diff --git a/include/asm-ppc64/pci-bridge.h b/include/asm-ppc64/pci-bridge.h --- a/include/asm-ppc64/pci-bridge.h +++ b/include/asm-ppc64/pci-bridge.h @@ -4,6 +4,8 @@ #include +#include + /* * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -71,6 +73,14 @@ struct pci_dn { 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 */ +#ifdef CONFIG_PPC_ISERIES + union HvDsaMap DsaAddr; /* Direct Select Address */ + /* busNumber, subBusNumber, */ + /* deviceId, barNumber */ + int Irq; /* Assigned IRQ */ + int Flags; /* Possible flags(disable/bist)*/ + u8 LogicalSlot; /* Hv Slot Index for Tces */ +#endif u32 config_space[16]; /* saved PCI config space */ }; diff --git a/include/asm-ppc64/prom.h b/include/asm-ppc64/prom.h --- a/include/asm-ppc64/prom.h +++ b/include/asm-ppc64/prom.h @@ -137,6 +137,9 @@ struct device_node { struct kref kref; unsigned long _flags; void *data; +#ifdef CONFIG_PPC_ISERIES + struct list_head Device_List; +#endif }; extern struct device_node *of_chosen; From gsbarb at br.ibm.com Thu Sep 29 04:25:20 2005 From: gsbarb at br.ibm.com (Gustavo Sverzut Barbieri) Date: Wed, 28 Sep 2005 15:25:20 -0300 Subject: [PATCH 2/2] Cleanup loops using lmb regions Message-ID: <200509281525.25320.gsbarb@br.ibm.com> This is the major change, it changes loops using lmb.region to use the new macros: for_each_lmb_region() for_each_lmb_region_reversed() As Dave already told me in private, although this is a cleanup, it adds code. I couldn't avoid it since some places like lmb_coalesce_regions() start counting from position != 0. Any ideas are welcome. PS: It was only tested on OpenPower 720. -- Gustavo Sverzut Barbieri ------------------------ LTC - Brazil -------------- next part -------------- Subject: [PATCH 2/2] Cleanup loops using lmb regions --- arch/ppc64/kernel/lmb.c | 154 ++++++++++++++++++++++++++------------------ arch/ppc64/mm/hash_utils.c | 9 +-- arch/ppc64/mm/init.c | 63 +++++++----------- arch/ppc64/mm/numa.c | 8 +- include/asm-ppc64/lmb.h | 33 +++++++-- 5 files changed, 148 insertions(+), 119 deletions(-) 97f36e75ea988eaa6d4b6cfdaf568799fdcf2672 diff --git a/arch/ppc64/kernel/lmb.c b/arch/ppc64/kernel/lmb.c --- a/arch/ppc64/kernel/lmb.c +++ b/arch/ppc64/kernel/lmb.c @@ -22,34 +22,45 @@ struct lmb lmb; +static inline int +lmb_region_valid(struct lmb_region *region, struct lmb_property *property) +{ + return ((property >= region->region) && + (lmb_region_index(region, property) < region->cnt)); +} + + #undef DEBUG void lmb_dump_all(void) { #ifdef DEBUG - unsigned long i; + struct lmb_property *prop; udbg_printf("lmb_dump_all:\n"); udbg_printf(" memory.cnt = 0x%lx\n", lmb.memory.cnt); udbg_printf(" memory.size = 0x%lx\n", lmb.memory.size); - for (i=0; i < lmb.memory.cnt ;i++) { + + for_each_lmb_region(lmb.memory, prop) { + unsigned long i = lmb_region_index(&(lmb.memory), prop); udbg_printf(" memory.region[0x%x].base = 0x%lx\n", - i, lmb.memory.region[i].base); + i, prop->base); udbg_printf(" .size = 0x%lx\n", - lmb.memory.region[i].size); + prop->size); } udbg_printf("\n reserved.cnt = 0x%lx\n", lmb.reserved.cnt); udbg_printf(" reserved.size = 0x%lx\n", lmb.reserved.size); - for (i=0; i < lmb.reserved.cnt ;i++) { + for_each_lmb_region(lmb.reserved, prop) { + unsigned long i = lmb_region_index(&(lmb.reserved), prop); udbg_printf(" reserved.region[0x%x].base = 0x%lx\n", - i, lmb.reserved.region[i].base); + i, prop->base); udbg_printf(" .size = 0x%lx\n", - lmb.reserved.region[i].size); + prop->size); } #endif /* DEBUG */ } @@ -88,12 +99,24 @@ lmb_regions_adjacent(struct lmb_region * static void __init lmb_coalesce_regions(struct lmb_region *rgn, unsigned long r1, unsigned long r2) { - unsigned long i; - - rgn->region[r1].size += rgn->region[r2].size; - for (i=r2; i < rgn->cnt-1; i++) { - rgn->region[i].base = rgn->region[i+1].base; - rgn->region[i].size = rgn->region[i+1].size; + struct lmb_property *prop; + struct lmb_property *p1 = &rgn->region[r1]; + struct lmb_property *p2 = &rgn->region[r2]; + + BUG_ON(p1->base >= p2->base); + + p1->size += p2->size; + + for_each_lmb_region(*rgn, prop) { + if (prop < p2) + continue; /* start action just from r2 to the end */ + else { + struct lmb_property *next_prop = prop + 1; + if (lmb_region_valid(rgn, next_prop)) { + prop->base = next_prop->base; + prop->size = next_prop->size; + } + } } rgn->cnt--; } @@ -119,12 +142,12 @@ lmb_init(void) void __init lmb_analyze(void) { - int i; + struct lmb_property *prop; lmb.memory.size = 0; - for (i = 0; i < lmb.memory.cnt; i++) - lmb.memory.size += lmb.memory.region[i].size; + for_each_lmb_region(lmb.memory, prop) + lmb.memory.size += prop->size; } /* This routine called with relocation disabled. */ @@ -133,26 +156,26 @@ lmb_add_region(struct lmb_region *rgn, u { unsigned long i, coalesced = 0; long adjacent; + struct lmb_property *prop; /* First try and coalesce this LMB with another. */ - for (i=0; i < rgn->cnt; i++) { - unsigned long rgnbase = rgn->region[i].base; - unsigned long rgnsize = rgn->region[i].size; - - adjacent = lmb_addrs_adjacent(base,size,rgnbase,rgnsize); + for_each_lmb_region(*rgn, prop) { + adjacent = lmb_addrs_adjacent(base, size, + prop->base, prop->size); if ( adjacent > 0 ) { - rgn->region[i].base -= size; - rgn->region[i].size += size; + prop->base -= size; + prop->size += size; coalesced++; break; } else if ( adjacent < 0 ) { - rgn->region[i].size += size; + prop->size += size; coalesced++; break; } } + i = lmb_region_index(rgn, prop); if ((i < rgn->cnt-1) && lmb_regions_adjacent(rgn, i, i+1) ) { lmb_coalesce_regions(rgn, i, i+1); coalesced++; @@ -165,13 +188,14 @@ lmb_add_region(struct lmb_region *rgn, u } /* Couldn't coalesce the LMB, so add it to the sorted table. */ - for (i=rgn->cnt-1; i >= 0; i--) { - if (base < rgn->region[i].base) { - rgn->region[i+1].base = rgn->region[i].base; - rgn->region[i+1].size = rgn->region[i].size; + for_each_lmb_region_reversed(*rgn, prop) { + struct lmb_property *next_prop = prop + 1; + if (base < prop->base) { + next_prop->base = prop->base; + next_prop->size = prop->size; } else { - rgn->region[i+1].base = base; - rgn->region[i+1].size = size; + next_prop->base = base; + next_prop->size = size; break; } } @@ -205,17 +229,14 @@ lmb_reserve(unsigned long base, unsigned long __init lmb_overlaps_region(struct lmb_region *rgn, unsigned long base, unsigned long size) { - unsigned long i; + struct lmb_property *prop; - for (i=0; i < rgn->cnt; i++) { - unsigned long rgnbase = rgn->region[i].base; - unsigned long rgnsize = rgn->region[i].size; - if ( lmb_addrs_overlap(base,size,rgnbase,rgnsize) ) { - break; - } + for_each_lmb_region(*rgn, prop) { + if (lmb_addrs_overlap(base, size, prop->base, prop->size)) + return lmb_region_index(rgn, prop); } - return (i < rgn->cnt) ? i : -1; + return -1; } unsigned long __init @@ -227,35 +248,39 @@ lmb_alloc(unsigned long size, unsigned l unsigned long __init lmb_alloc_base(unsigned long size, unsigned long align, unsigned long max_addr) { - long i, j; unsigned long base = 0; + struct lmb_property *prop; - for (i=lmb.memory.cnt-1; i >= 0; i--) { - unsigned long lmbbase = lmb.memory.region[i].base; - unsigned long lmbsize = lmb.memory.region[i].size; + for_each_lmb_region_reversed(lmb.memory, prop) { + unsigned long addr; + unsigned long end = prop->base + prop->size; if ( max_addr == LMB_ALLOC_ANYWHERE ) - base = _ALIGN_DOWN(lmbbase+lmbsize-size, align); - else if ( lmbbase < max_addr ) - base = _ALIGN_DOWN(min(lmbbase+lmbsize,max_addr)-size, align); + addr = end; + else if (prop->base < max_addr) + addr = min(end, max_addr); else continue; - while ( (lmbbase <= base) && - ((j = lmb_overlaps_region(&lmb.reserved,base,size)) >= 0) ) { - base = _ALIGN_DOWN(lmb.reserved.region[j].base-size, align); - } + base = _ALIGN_DOWN(addr - size, align); - if ( (base != 0) && (lmbbase <= base) ) - break; - } + while (base >= prop->base) { + long j =lmb_overlaps_region(&lmb.reserved, base, size); - if ( i < 0 ) - return 0; + if (j < 0) + break; + + addr = lmb.reserved.region[j].base; + base = _ALIGN_DOWN(addr - size, align); + } - lmb_add_region(&lmb.reserved, base, size); + if ((base != 0) && (base >= prop->base)) { + lmb_add_region(&lmb.reserved, base, size); + return base; + } + } - return base; + return 0; } /* You must call lmb_analyze() before this. */ @@ -280,20 +305,21 @@ lmb_end_of_DRAM(void) void __init lmb_enforce_memory_limit(void) { extern unsigned long memory_limit; - unsigned long i, limit; + unsigned long limit; + struct lmb_property *prop; if (! memory_limit) return; limit = memory_limit; - for (i = 0; i < lmb.memory.cnt; i++) { - if (limit > lmb.memory.region[i].size) { - limit -= lmb.memory.region[i].size; - continue; + for_each_lmb_region(lmb.memory, prop) { + if (limit <= prop->size) { + long i = lmb_region_index(&(lmb.memory), prop); + prop->size = limit; + lmb.memory.cnt = i + 1; + break; } - lmb.memory.region[i].size = limit; - lmb.memory.cnt = i + 1; - break; + limit -= prop->size; } } diff --git a/arch/ppc64/mm/hash_utils.c b/arch/ppc64/mm/hash_utils.c --- a/arch/ppc64/mm/hash_utils.c +++ b/arch/ppc64/mm/hash_utils.c @@ -152,9 +152,10 @@ void __init htab_initialize(void) unsigned long table, htab_size_bytes; unsigned long pteg_count; unsigned long mode_rw; - int i, use_largepages = 0; + int use_largepages = 0; unsigned long base = 0, size = 0; extern unsigned long tce_alloc_start, tce_alloc_end; + struct lmb_property *prop; DBG(" -> htab_initialize()\n"); @@ -209,9 +210,9 @@ void __init htab_initialize(void) use_largepages = 1; /* create bolted the linear mapping in the hash table */ - for (i=0; i < lmb.memory.cnt; i++) { - base = lmb.memory.region[i].base + KERNELBASE; - size = lmb.memory.region[i].size; + for_each_lmb_region(lmb.memory, prop) { + base = prop->base + KERNELBASE; + size = prop->size; DBG("creating mapping for region: %lx : %lx\n", base, size); diff --git a/arch/ppc64/mm/init.c b/arch/ppc64/mm/init.c --- a/arch/ppc64/mm/init.c +++ b/arch/ppc64/mm/init.c @@ -462,7 +462,7 @@ void destroy_context(struct mm_struct *m void __init mm_init_ppc64(void) { #ifndef CONFIG_PPC_ISERIES - unsigned long i; + struct lmb_property *prop, *prev_prop=NULL; #endif ppc64_boot_msg(0x100, "MM Init"); @@ -480,17 +480,16 @@ void __init mm_init_ppc64(void) */ #ifndef CONFIG_PPC_ISERIES - for (i = 1; i < lmb.memory.cnt; i++) { - unsigned long base, prevbase, prevsize; - - prevbase = lmb.memory.region[i-1].base; - prevsize = lmb.memory.region[i-1].size; - base = lmb.memory.region[i].base; - if (base > (prevbase + prevsize)) { - io_hole_start = prevbase + prevsize; - io_hole_size = base - (prevbase + prevsize); - break; + for_each_lmb_region(lmb.memory, prop) { + if (prev_prop != NULL) { + unsigned long end = prev_prop->base + prev_prop->size; + if (prop->base > end) { + io_hole_start = end; + io_hole_size = prop->base - io_hole_start; + break; + } } + prev_prop = prop; } #endif /* CONFIG_PPC_ISERIES */ if (io_hole_start) @@ -506,18 +505,13 @@ void __init mm_init_ppc64(void) */ int page_is_ram(unsigned long pfn) { - int i; unsigned long paddr = (pfn << PAGE_SHIFT); + struct lmb_property *prop; - for (i=0; i < lmb.memory.cnt; i++) { - unsigned long base; - - base = lmb.memory.region[i].base; - - if ((paddr >= base) && - (paddr < (base + lmb.memory.region[i].size))) { + for_each_lmb_region(lmb.memory, prop) { + if ((paddr >= prop->base) && + (paddr < (prop->base + prop->size))) return 1; - } } return 0; @@ -531,10 +525,10 @@ EXPORT_SYMBOL(page_is_ram); #ifndef CONFIG_NEED_MULTIPLE_NODES void __init do_init_bootmem(void) { - unsigned long i; unsigned long start, bootmap_pages; unsigned long total_pages = lmb_end_of_DRAM() >> PAGE_SHIFT; int boot_mapsize; + struct lmb_property *prop; /* * Find an area to use for the bootmem bitmap. Calculate the size of @@ -553,18 +547,15 @@ void __init do_init_bootmem(void) /* Add all physical memory to the bootmem map, mark each area * present. */ - for (i=0; i < lmb.memory.cnt; i++) - free_bootmem(lmb.memory.region[i].base, - lmb_size_bytes(&lmb.memory, i)); + for_each_lmb_region(lmb.memory, prop) + free_bootmem(prop->base, lmb_size_bytes(prop)); /* reserve the sections we're already using */ - for (i=0; i < lmb.reserved.cnt; i++) - reserve_bootmem(lmb.reserved.region[i].base, - lmb_size_bytes(&lmb.reserved, i)); - - for (i=0; i < lmb.memory.cnt; i++) - memory_present(0, lmb_start_pfn(&lmb.memory, i), - lmb_end_pfn(&lmb.memory, i)); + for_each_lmb_region(lmb.reserved, prop) + reserve_bootmem(prop->base, lmb_size_bytes(prop)); + + for_each_lmb_region(lmb.memory, prop) + memory_present(0, lmb_start_pfn(prop), lmb_end_pfn(prop)); } /* @@ -599,21 +590,17 @@ static struct kcore_list kcore_vmem; static int __init setup_kcore(void) { - int i; + struct lmb_property *prop; - for (i=0; i < lmb.memory.cnt; i++) { - unsigned long base, size; + for_each_lmb_region(lmb.memory, prop) { struct kcore_list *kcore_mem; - base = lmb.memory.region[i].base; - size = lmb.memory.region[i].size; - /* GFP_ATOMIC to avoid might_sleep warnings during boot */ kcore_mem = kmalloc(sizeof(struct kcore_list), GFP_ATOMIC); if (!kcore_mem) panic("mem_init: kmalloc failed\n"); - kclist_add(kcore_mem, __va(base), size); + kclist_add(kcore_mem, __va(prop->base), prop->size); } kclist_add(&kcore_vmem, (void *)VMALLOC_START, VMALLOC_END-VMALLOC_START); diff --git a/arch/ppc64/mm/numa.c b/arch/ppc64/mm/numa.c --- a/arch/ppc64/mm/numa.c +++ b/arch/ppc64/mm/numa.c @@ -581,9 +581,9 @@ void __init do_init_bootmem(void) for_each_online_node(nid) { unsigned long start_paddr, end_paddr; - int i; unsigned long bootmem_paddr; unsigned long bootmap_pages; + struct lmb_property *prop; start_paddr = init_node_data[nid].node_start_pfn * PAGE_SIZE; end_paddr = init_node_data[nid].node_end_pfn * PAGE_SIZE; @@ -667,9 +667,9 @@ new_range: /* * Mark reserved regions on this node */ - for (i = 0; i < lmb.reserved.cnt; i++) { - unsigned long physbase = lmb.reserved.region[i].base; - unsigned long size = lmb.reserved.region[i].size; + for_each_lmb_region(lmb.reserved, prop) { + unsigned long physbase = prop->base; + unsigned long size = prop->size; if (pa_to_nid(physbase) != nid && pa_to_nid(physbase+size-1) != nid) diff --git a/include/asm-ppc64/lmb.h b/include/asm-ppc64/lmb.h --- a/include/asm-ppc64/lmb.h +++ b/include/asm-ppc64/lmb.h @@ -57,25 +57,40 @@ extern void lmb_dump_all(void); extern unsigned long io_hole_start; static inline unsigned long -lmb_size_bytes(struct lmb_region *type, unsigned long region_nr) +lmb_size_bytes(struct lmb_property *prop) { - return type->region[region_nr].size; + return prop->size; } static inline unsigned long -lmb_size_pages(struct lmb_region *type, unsigned long region_nr) +lmb_size_pages(struct lmb_property *prop) { - return lmb_size_bytes(type, region_nr) >> PAGE_SHIFT; + return lmb_size_bytes(prop) >> PAGE_SHIFT; } static inline unsigned long -lmb_start_pfn(struct lmb_region *type, unsigned long region_nr) +lmb_start_pfn(struct lmb_property *prop) { - return type->region[region_nr].base >> PAGE_SHIFT; + return prop->base >> PAGE_SHIFT; } static inline unsigned long -lmb_end_pfn(struct lmb_region *type, unsigned long region_nr) +lmb_end_pfn(struct lmb_property *prop) { - return lmb_start_pfn(type, region_nr) + - lmb_size_pages(type, region_nr); + return lmb_start_pfn(prop) + lmb_size_pages(prop); } +static inline long +lmb_region_index(struct lmb_region *region, struct lmb_property *prop) +{ + return (prop - region->region); +} + +#define for_each_lmb_region(lmb_region, itr) \ + for ((itr) = (lmb_region).region; \ + (itr) < (lmb_region).region + (lmb_region).cnt; \ + (itr)++) + +#define for_each_lmb_region_reversed(lmb_region, itr) \ + for ((itr) = (lmb_region).region + ((lmb_region).cnt - 1); \ + (itr) >= (lmb_region).region; \ + (itr)--) + #endif /* _PPC64_LMB_H */ -------------- 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/20050928/be30904c/attachment.pgp From gsbarb at br.ibm.com Thu Sep 29 04:10:25 2005 From: gsbarb at br.ibm.com (Gustavo Sverzut Barbieri) Date: Wed, 28 Sep 2005 15:10:25 -0300 Subject: [PATCH 1/2] Unify numa_memory_lookup_table allocation and setup. Message-ID: <200509281510.30531.gsbarb@br.ibm.com> Here are some patches to clean up lmb.c, numa.c and init.c, as requested by Dave Hansen. This patch unify duplicated code under setup_numa_memory_lookup_table() -- Gustavo Sverzut Barbieri ------------------------ LTC - Brazil -------------- next part -------------- Subject: [PATCH 1/2] Unify numa_memory_lookup_table allocation and setup. --- arch/ppc64/mm/numa.c | 30 +++++++++++++++--------------- 1 files changed, 15 insertions(+), 15 deletions(-) db3ba0826755c6213a94eeae53a55ef178e5418b diff --git a/arch/ppc64/mm/numa.c b/arch/ppc64/mm/numa.c --- a/arch/ppc64/mm/numa.c +++ b/arch/ppc64/mm/numa.c @@ -58,6 +58,18 @@ EXPORT_SYMBOL(numa_memory_lookup_table); EXPORT_SYMBOL(numa_cpumask_lookup_table); EXPORT_SYMBOL(nr_cpus_in_node); +static inline void setup_numa_memory_lookup_table(void) +{ + long i; + long entries = lmb_end_of_DRAM() >> MEMORY_INCREMENT_SHIFT; + + numa_memory_lookup_table = + (char *)abs_to_virt(lmb_alloc(entries * sizeof(char), 1)); + + for (i = 0; i < entries ; i++) + numa_memory_lookup_table[i] = ARRAY_INITIALISER; +} + static inline void map_cpu_to_node(int cpu, int node) { numa_cpu_lookup_table[cpu] = node; @@ -320,7 +332,6 @@ static int __init parse_numa_properties( struct device_node *memory = NULL; int addr_cells, size_cells; int max_domain = 0; - long entries = lmb_end_of_DRAM() >> MEMORY_INCREMENT_SHIFT; unsigned long i; if (numa_enabled == 0) { @@ -328,12 +339,7 @@ static int __init parse_numa_properties( return -1; } - numa_memory_lookup_table = - (char *)abs_to_virt(lmb_alloc(entries * sizeof(char), 1)); - memset(numa_memory_lookup_table, 0, entries * sizeof(char)); - - for (i = 0; i < entries ; i++) - numa_memory_lookup_table[i] = ARRAY_INITIALISER; + setup_numa_memory_lookup_table(); min_common_depth = find_min_common_depth(); @@ -462,14 +468,8 @@ static void __init setup_nonnuma(void) printk(KERN_INFO "Memory hole size: %ldMB\n", (top_of_ram - total_ram) >> 20); - if (!numa_memory_lookup_table) { - long entries = top_of_ram >> MEMORY_INCREMENT_SHIFT; - numa_memory_lookup_table = - (char *)abs_to_virt(lmb_alloc(entries * sizeof(char), 1)); - memset(numa_memory_lookup_table, 0, entries * sizeof(char)); - for (i = 0; i < entries ; i++) - numa_memory_lookup_table[i] = ARRAY_INITIALISER; - } + if (!numa_memory_lookup_table) + setup_numa_memory_lookup_table(); map_cpu_to_node(boot_cpuid, 0); -------------- 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/20050928/a64dca09/attachment.pgp From haveblue at us.ibm.com Thu Sep 29 06:44:18 2005 From: haveblue at us.ibm.com (Dave Hansen) Date: Wed, 28 Sep 2005 13:44:18 -0700 Subject: [PATCH 1/2] Unify numa_memory_lookup_table allocation and setup. In-Reply-To: <200509281510.30531.gsbarb@br.ibm.com> References: <200509281510.30531.gsbarb@br.ibm.com> Message-ID: <1127940258.17242.24.camel@localhost> On Wed, 2005-09-28 at 15:10 -0300, Gustavo Sverzut Barbieri wrote: > Here are some patches to clean up lmb.c, numa.c and init.c, as requested by > Dave Hansen. Let me elaborate a bit. I created _another_ loop to run through all of the LMBs in the NUMA init code a few weeks back for memory_present() calls. I thought this this is a decent way to atone for that messy code. This first patch is a pretty simple cleanup. The LMB macro patch certainly makes some of the code more readable. But, it might not be worth it to use the macro in lmb.c. It just seems to make it more complicated. Any thoughts? -- Dave From uk_nationalottory at hotmail.com Thu Sep 29 08:47:34 2005 From: uk_nationalottory at hotmail.com (uk_nationalottory) Date: Wed, 28 Sep 2005 22:47:34 -0000 Subject: CONGRATULATIONS YOU HAVE WON!!! Message-ID: <20050928224715.56BDD67B48@ozlabs.org> Irish Lottery Headquarters: Customer Service Irish Sweepstake Lottery an Affiliate of watergate inc. 28 TANFIELD ROAD, CROYDON.IRELAND Tel/Fax:447040121118 Ref: IRSL/941OYI/02 Batch: 12/25/DC34 WINNING NOTIFICATION: We happily announce to you the draw of the IRISH Sweepstake Lottery International programs held on the 27th of September 2005 in London. Your Name and e-mail address attached to ticket number: 564 75600545 188 with Serial number 5388/02 drew the lucky numbers: 31-6-26-13-35-7,which subsequently won you the lottery in the 2nd category. You are therefore, been approved to claim a total sum of 8,500,000.00 (eight million, five hundred thousand pounds) in cash credited to file KPC/9080118308/02.This is from a total cash prize of 125 Million pounds, shared amongst the first Fifty (50) lucky winners in this category. Please note that your lucky winning number falls within our European booklet representative office in Europe as indicated in our play coupon. In view of this, your 8,500,000.00 (eight million, five hundred thousand pounds) would be released to you by our affiliate bank in London. Our agent will immediately commence the process to facilitate the release of your funds to you as soon as you make contact with him .All participants were selected randomly from World Wide Web site through computer draw system and extracted from over 100,000 companies. This promotion takes place annually. For security reasons, you are advised to keep your winning information confidential till your claims is processed and your money remitted to you in whatever manner you deem fit to claim your prize. This is a part of our precautionary measure to avoid double claiming and unwarranted abuse of this program by some unscrupulous elements. Please be warned. To file for your claim, please contact The Officer In charge with the below details for processing of your claims. OFFICER: DR SANTOS MILTON fiduciaryofficer at yahoo.co.uk To avoid unnecessary delays and complications, please quote your reference/batch numbers in any correspondences with us or our designated agent. Congratulations once more from all members and staffs of this program. Thank you for being part of our promotional lottery program. click here: http://news.bbc.co.uk/1/hi/world/europe/4746057.stm http://observer.guardian.co.uk/international/story/0,6903,1539836,00.html Sincerely, JOANNA SMITH. Zonal Coordinator IRELAND From viro at ftp.linux.org.uk Thu Sep 29 09:17:49 2005 From: viro at ftp.linux.org.uk (Al Viro) Date: Thu, 29 Sep 2005 00:17:49 +0100 Subject: [PATCH] ppc64 get_user annotations Message-ID: <20050928231749.GI7992@ftp.linux.org.uk> long is not uintptr_t, unsigned long is. Signed-off-by: Al Viro ---- diff -urN RC14-rc2-git6-proc_mkdir/include/asm-ppc64/uaccess.h RC14-rc2-git6-ppc64-user/include/asm-ppc64/uaccess.h --- RC14-rc2-git6-proc_mkdir/include/asm-ppc64/uaccess.h 2005-09-08 10:07:30.000000000 -0400 +++ RC14-rc2-git6-ppc64-user/include/asm-ppc64/uaccess.h 2005-09-28 13:02:25.000000000 -0400 @@ -164,7 +164,8 @@ #define __get_user_nocheck(x,ptr,size) \ ({ \ - long __gu_err, __gu_val; \ + long __gu_err; \ + unsigned long __gu_val; \ might_sleep(); \ __get_user_size(__gu_val,(ptr),(size),__gu_err,-EFAULT);\ (x) = (__typeof__(*(ptr)))__gu_val; \ @@ -173,7 +174,8 @@ #define __get_user_check(x,ptr,size) \ ({ \ - long __gu_err = -EFAULT, __gu_val = 0; \ + long __gu_err = -EFAULT; \ + unsigned long __gu_val = 0; \ const __typeof__(*(ptr)) __user *__gu_addr = (ptr); \ might_sleep(); \ if (access_ok(VERIFY_READ,__gu_addr,size)) \ From gsbarb at br.ibm.com Thu Sep 29 10:05:25 2005 From: gsbarb at br.ibm.com (gsbarb at br.ibm.com) Date: Wed, 28 Sep 2005 21:05:25 -0300 Subject: [PATCH 1/2] Unify numa_memory_lookup_table allocation and setup. In-Reply-To: <1127940258.17242.24.camel@localhost> Message-ID: Dave Hansen wrote on 28/09/2005 17:44:18: > On Wed, 2005-09-28 at 15:10 -0300, Gustavo Sverzut Barbieri wrote: > > Here are some patches to clean up lmb.c, numa.c and init.c, as requested by > > Dave Hansen. > > Let me elaborate a bit. I created _another_ loop to run through all of > the LMBs in the NUMA init code a few weeks back for memory_present() > calls. I thought this this is a decent way to atone for that messy > code. > > This first patch is a pretty simple cleanup. > > The LMB macro patch certainly makes some of the code more readable. > But, it might not be worth it to use the macro in lmb.c. It just seems > to make it more complicated. Any thoughts? I could use that macro just where it loops from 0 to "cnt", with that we can leave the _reversed() version out and leave coalesce and the other one unchanged. Maybe leave the _reversed() (it's used in 2 places). PS: If this mail doesn't respect any internet standards, it's because it was sent by Lotus Notes. Sorry, my imap account is still in progress! Cheers from Brazil, --- Gustavo Sverzut Barbieri -------------- next part -------------- An HTML attachment was scrubbed... URL: http://ozlabs.org/pipermail/linuxppc64-dev/attachments/20050928/26462a3c/attachment.htm From linas at austin.ibm.com Thu Sep 29 10:27:45 2005 From: linas at austin.ibm.com (linas) Date: Wed, 28 Sep 2005 19:27:45 -0500 Subject: [PATCH] ppc64: switch several rtas functions to use the new struct pci_dn structure Message-ID: <20050929002745.GJ29826@austin.ibm.com> This patch changes the rtas_pci interface to use the new struct pci_dn structure for two routines that work with pci device nodes. This patch also does some minor janitorial work: it uses some handy macros and cleans up some trailing whitespace in the affected file. Signed-off-by: Linas Vepstas Index: linux-2.6.14-rc2-git6/arch/ppc64/kernel/eeh.c =================================================================== --- linux-2.6.14-rc2-git6.orig/arch/ppc64/kernel/eeh.c 2005-09-28 15:05:51.000000000 -0500 +++ linux-2.6.14-rc2-git6/arch/ppc64/kernel/eeh.c 2005-09-28 18:34:15.973686155 -0500 @@ -71,10 +71,6 @@ * and sent out for processing. */ -/** Bus Unit ID macros; get low and hi 32-bits of the 64-bit BUID */ -#define BUID_HI(buid) ((buid) >> 32) -#define BUID_LO(buid) ((buid) & 0xffffffff) - /* EEH event workqueue setup. */ static DEFINE_SPINLOCK(eeh_eventlist_lock); LIST_HEAD(eeh_eventlist); Index: linux-2.6.14-rc2-git6/arch/ppc64/kernel/pci.h =================================================================== --- linux-2.6.14-rc2-git6.orig/arch/ppc64/kernel/pci.h 2005-09-28 15:05:51.000000000 -0500 +++ linux-2.6.14-rc2-git6/arch/ppc64/kernel/pci.h 2005-09-28 18:34:15.985684472 -0500 @@ -26,6 +26,10 @@ extern struct pci_dev *ppc64_isabridge_dev; /* may be NULL if no ISA bus */ +/** Bus Unit ID macros; get low and hi 32-bits of the 64-bit BUID */ +#define BUID_HI(buid) ((buid) >> 32) +#define BUID_LO(buid) ((buid) & 0xffffffff) + /* PCI device_node operations */ struct device_node; typedef void *(*traverse_func)(struct device_node *me, void *data); Index: linux-2.6.14-rc2-git6/arch/ppc64/kernel/rtas_pci.c =================================================================== --- linux-2.6.14-rc2-git6.orig/arch/ppc64/kernel/rtas_pci.c 2005-09-28 15:05:51.000000000 -0500 +++ linux-2.6.14-rc2-git6/arch/ppc64/kernel/rtas_pci.c 2005-09-28 18:34:15.974686014 -0500 @@ -5,19 +5,19 @@ * Copyright (C) 2003 Anton Blanchard , IBM * * RTAS specific routines for PCI. - * + * * Based on code from pci.c, chrp_pci.c and pSeries_pci.c * * 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 @@ -48,7 +48,7 @@ static int ibm_read_pci_config; static int ibm_write_pci_config; -static int config_access_valid(struct pci_dn *dn, int where) +static inline int config_access_valid(struct pci_dn *dn, int where) { if (where < 256) return 1; @@ -73,16 +73,14 @@ return 0; } -static int rtas_read_config(struct device_node *dn, int where, int size, u32 *val) +static int rtas_read_config(struct pci_dn *pdn, int where, int size, u32 *val) { int returnval = -1; unsigned long buid, addr; int ret; - struct pci_dn *pdn; - if (!dn || !dn->data) + if (!pdn) return PCIBIOS_DEVICE_NOT_FOUND; - pdn = dn->data; if (!config_access_valid(pdn, where)) return PCIBIOS_BAD_REGISTER_NUMBER; @@ -91,7 +89,7 @@ buid = pdn->phb->buid; if (buid) { ret = rtas_call(ibm_read_pci_config, 4, 2, &returnval, - addr, buid >> 32, buid & 0xffffffff, size); + addr, BUID_HI(buid), BUID_LO(buid), size); } else { ret = rtas_call(read_pci_config, 2, 2, &returnval, addr, size); } @@ -101,7 +99,7 @@ return PCIBIOS_DEVICE_NOT_FOUND; if (returnval == EEH_IO_ERROR_VALUE(size) && - eeh_dn_check_failure (dn, NULL)) + eeh_dn_check_failure (pdn->node, NULL)) return PCIBIOS_DEVICE_NOT_FOUND; return PCIBIOS_SUCCESSFUL; @@ -119,23 +117,23 @@ busdn = bus->sysdata; /* must be a phb */ /* Search only direct children of the bus */ - for (dn = busdn->child; dn; dn = dn->sibling) - if (dn->data && PCI_DN(dn)->devfn == devfn + for (dn = busdn->child; dn; dn = dn->sibling) { + struct pci_dn *pdn = PCI_DN(dn); + if (pdn && pdn->devfn == devfn && of_device_available(dn)) - return rtas_read_config(dn, where, size, val); + return rtas_read_config(pdn, where, size, val); + } return PCIBIOS_DEVICE_NOT_FOUND; } -int rtas_write_config(struct device_node *dn, int where, int size, u32 val) +int rtas_write_config(struct pci_dn *pdn, int where, int size, u32 val) { unsigned long buid, addr; int ret; - struct pci_dn *pdn; - if (!dn || !dn->data) + if (!pdn) return PCIBIOS_DEVICE_NOT_FOUND; - pdn = dn->data; if (!config_access_valid(pdn, where)) return PCIBIOS_BAD_REGISTER_NUMBER; @@ -143,7 +141,8 @@ (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); + ret = rtas_call(ibm_write_pci_config, 5, 1, NULL, addr, + BUID_HI(buid), BUID_LO(buid), size, (ulong) val); } else { ret = rtas_call(write_pci_config, 3, 1, NULL, addr, size, (ulong)val); } @@ -166,10 +165,12 @@ busdn = bus->sysdata; /* must be a phb */ /* Search only direct children of the bus */ - for (dn = busdn->child; dn; dn = dn->sibling) - if (dn->data && PCI_DN(dn)->devfn == devfn + for (dn = busdn->child; dn; dn = dn->sibling) { + struct pci_dn *pdn = PCI_DN(dn); + if (pdn && pdn->devfn == devfn && of_device_available(dn)) - return rtas_write_config(dn, where, size, val); + return rtas_write_config(pdn, where, size, val); + } return PCIBIOS_DEVICE_NOT_FOUND; } @@ -222,7 +223,7 @@ /* Python's register file is 1 MB in size. */ chip_regs = ioremap(reg_struct.address & ~(0xfffffUL), 0x100000); - /* + /* * Firmware doesn't always clear this bit which is critical * for good performance - Anton */ @@ -293,7 +294,7 @@ if (bus_range == NULL || len < 2 * sizeof(int)) { return 1; } - + phb->first_busno = bus_range[0]; phb->last_busno = bus_range[1]; Index: linux-2.6.14-rc2-git6/include/asm/rtas.h =================================================================== --- linux-2.6.14-rc2-git6.orig/include/asm/rtas.h 2005-09-28 19:04:19.886691007 -0500 +++ linux-2.6.14-rc2-git6/include/asm/rtas.h 2005-09-28 19:04:40.825754075 -0500 @@ -246,6 +246,4 @@ #define GLOBAL_INTERRUPT_QUEUE 9005 -extern int rtas_write_config(struct device_node *dn, int where, int size, u32 val); - #endif /* _PPC64_RTAS_H */ From linas at austin.ibm.com Thu Sep 29 10:33:38 2005 From: linas at austin.ibm.com (linas) Date: Wed, 28 Sep 2005 19:33:38 -0500 Subject: [PATCH] ppc64 PCI Hotplug: cleanup unsymmetric API routines Message-ID: <20050929003338.GK29826@austin.ibm.com> This is a minor patch to the ppc64 PCI hotplug code; it makes the call to rpaphp_unconfig_pci_adapter() symmetric with respect to the call to rpaphp_config_pci_adapter(). I discussed this with John Rose, who had provided the last round of changes for these functions; he appearently had this patch but somehow failed to mail it out. Tested. (added/removed device). Signed-off-by: Linas Vepstas Index: linux-2.6.14-rc2-git6/drivers/pci/hotplug/rpaphp_pci.c =================================================================== --- linux-2.6.14-rc2-git6.orig/drivers/pci/hotplug/rpaphp_pci.c 2005-09-28 19:04:19.886691007 -0500 +++ linux-2.6.14-rc2-git6/drivers/pci/hotplug/rpaphp_pci.c 2005-09-28 19:11:16.134306452 -0500 @@ -319,20 +319,15 @@ return; } -int rpaphp_unconfig_pci_adapter(struct slot *slot) +int rpaphp_unconfig_pci_adapter(struct pci_bus *bus) { struct pci_dev *dev, *tmp; - int retval = 0; - list_for_each_entry_safe(dev, tmp, slot->pci_devs, bus_list) { + list_for_each_entry_safe(dev, tmp, &bus->devices, bus_list) { rpaphp_eeh_remove_bus_device(dev); pci_remove_bus_device(dev); } - - slot->state = NOT_CONFIGURED; - info("%s: devices in slot[%s] unconfigured.\n", __FUNCTION__, - slot->name); - return retval; + return 0; } static int setup_pci_hotplug_slot_info(struct slot *slot) Index: linux-2.6.14-rc2-git6/drivers/pci/hotplug/rpaphp_core.c =================================================================== --- linux-2.6.14-rc2-git6.orig/drivers/pci/hotplug/rpaphp_core.c 2005-09-28 19:04:19.886691007 -0500 +++ linux-2.6.14-rc2-git6/drivers/pci/hotplug/rpaphp_core.c 2005-09-28 19:11:16.135306311 -0500 @@ -426,8 +426,11 @@ dbg("DISABLING SLOT %s\n", slot->name); down(&rpaphp_sem); - retval = rpaphp_unconfig_pci_adapter(slot); + retval = rpaphp_unconfig_pci_adapter(slot->bus); up(&rpaphp_sem); + slot->state = NOT_CONFIGURED; + info("%s: devices in slot[%s] unconfigured.\n", __FUNCTION__, + slot->name); exit: dbg("%s - Exit: rc[%d]\n", __FUNCTION__, retval); return retval; Index: linux-2.6.14-rc2-git6/drivers/pci/hotplug/rpaphp.h =================================================================== --- linux-2.6.14-rc2-git6.orig/drivers/pci/hotplug/rpaphp.h 2005-09-28 19:04:19.886691007 -0500 +++ linux-2.6.14-rc2-git6/drivers/pci/hotplug/rpaphp.h 2005-09-28 19:11:16.136306171 -0500 @@ -92,9 +92,10 @@ extern int rpaphp_claim_resource(struct pci_dev *dev, int resource); extern int rpaphp_enable_pci_slot(struct slot *slot); extern int register_pci_slot(struct slot *slot); -extern int rpaphp_unconfig_pci_adapter(struct slot *slot); extern int rpaphp_get_pci_adapter_status(struct slot *slot, int is_init, u8 * value); + extern int rpaphp_config_pci_adapter(struct pci_bus *bus); +extern int rpaphp_unconfig_pci_adapter(struct pci_bus *bus); /* rpaphp_core.c */ extern int rpaphp_add_slot(struct device_node *dn); From paulus at samba.org Thu Sep 29 10:35:30 2005 From: paulus at samba.org (Paul Mackerras) Date: Thu, 29 Sep 2005 10:35:30 +1000 Subject: [PATCH 1/2] Unify numa_memory_lookup_table allocation and setup. In-Reply-To: <1127940258.17242.24.camel@localhost> References: <200509281510.30531.gsbarb@br.ibm.com> <1127940258.17242.24.camel@localhost> Message-ID: <17211.14034.464959.496574@cargo.ozlabs.ibm.com> Dave Hansen writes: > The LMB macro patch certainly makes some of the code more readable. > But, it might not be worth it to use the macro in lmb.c. It just seems > to make it more complicated. Any thoughts? It does seem to make it more complicated. IMO, when we have a file such as lmb.c whose purpose is to present an abstraction to the rest of the kernel, there is no point in abstracting further within that, and in fact it actually obscures things - when you go looking at how the abstraction is implemented, you want to see how the abstraction is implemented, not some further abstraction. The for_each_lmb_region macro would be useful if we expected random users of the lmb stuff to need to go iterating through lmb regions. Since all such iterations are confined to lmb.c, I don't think the patch is helpful. Paul. From linuxppc at jdl.com Thu Sep 29 12:07:35 2005 From: linuxppc at jdl.com (Jon Loeliger) Date: Wed, 28 Sep 2005 21:07:35 -0500 Subject: Merge conflicts in ppc64/mm/{hash_native.c,tlb.c} Message-ID: So both linux-2.6 top-of-GIT and Paul's merge tree top-of-GIT have applied different changes to ppc64/mm/{hash_native.c,tlb.c} within hours of each other. With the net result that a pull of linus' tree followed by a pull of Paul's merge tree yields Git merge conflicts. I haven't got a clue where you guys are headed with this code. Any chance of having Ben or Paul taking a quick peek at it? Or maybe silently send me the "Don't be dumb; do this..." mail? :-) Thanks, jdl From linuxppc at jdl.com Thu Sep 29 12:15:29 2005 From: linuxppc at jdl.com (Jon Loeliger) Date: Wed, 28 Sep 2005 21:15:29 -0500 Subject: RFC on mem_pieces to LMB work Message-ID: Paul, How would you like to accept some work on converting mem_pieces to LMB? 1) Add LMB to ppc32. Convert users of mem_pieces to LMB in ppc32. Rip mem_pieces out. Later merging will go easier now that mem_pieces is toast. 2) Introduce LMB into arch/powerpc/mm/ Rip mem_pieces out of arch/powerpc/mm As platforms are added to arch/powerpc force LMB-ness on them. 3) Move a platform (MPC 8555 CDS) to arch/powerpc Make it build in arch/powerpc Accept incremental patches that convert it from mem_pieces to LMB Preferences? Thanks, jdl From paulus at samba.org Thu Sep 29 13:42:10 2005 From: paulus at samba.org (Paul Mackerras) Date: Thu, 29 Sep 2005 13:42:10 +1000 Subject: RFC on mem_pieces to LMB work In-Reply-To: References: Message-ID: <17211.25234.160085.163327@cargo.ozlabs.ibm.com> Jon Loeliger writes: > How would you like to accept some work on converting > mem_pieces to LMB? I started to look at this but got sidetracked on some other stuff. Your option 2 looks like what I was thinking of. Of course, since everybody has a device tree with at least one /memory node (right? :) we can just populate the LMB struct from the device tree unconditionally. (This point led me to looking at the patches for importing the flattened device tree into ppc32.) Paul. From paulus at samba.org Thu Sep 29 13:39:16 2005 From: paulus at samba.org (Paul Mackerras) Date: Thu, 29 Sep 2005 13:39:16 +1000 Subject: Merge conflicts in ppc64/mm/{hash_native.c,tlb.c} In-Reply-To: References: Message-ID: <17211.25060.419702.871039@cargo.ozlabs.ibm.com> Jon Loeliger writes: > So both linux-2.6 top-of-GIT and Paul's merge tree top-of-GIT > have applied different changes to ppc64/mm/{hash_native.c,tlb.c} > within hours of each other. With the net result that a pull > of linus' tree followed by a pull of Paul's merge tree yields > Git merge conflicts. Ben's hugepage fixes clashed with Ben's virtual-addr-in-batch patch. I have done the merge and resolved the conflict and pushed it out. It should be on kernel.org soon. Paul. From benh at kernel.crashing.org Thu Sep 29 16:54:30 2005 From: benh at kernel.crashing.org (Benjamin Herrenschmidt) Date: Thu, 29 Sep 2005 16:54:30 +1000 Subject: [PATCH] ppc64: SMU driver: locking mistake Message-ID: <1127976870.6102.38.camel@gaston> The SMU driver has a small mistake in the locking of the interrupt code, if polled access and interrupt access race, interrupt may take a lock and return without releasing it. This fixes it. With that patch, the driver is rock solid with my experimental thermal control (which bangs it pretty hard) racing with real time clock and cpufreq handling. Signed-off-by: Benjamin Herrenschmidt Index: linux-work/drivers/macintosh/smu.c =================================================================== --- linux-work.orig/drivers/macintosh/smu.c 2005-09-29 16:51:57.000000000 +1000 +++ linux-work/drivers/macintosh/smu.c 2005-09-29 16:52:37.000000000 +1000 @@ -155,8 +155,10 @@ spin_lock_irqsave(&smu->lock, flags); gpio = pmac_do_feature_call(PMAC_FTR_READ_GPIO, NULL, smu->doorbell); - if ((gpio & 7) != 7) + if ((gpio & 7) != 7) { + spin_unlock_irqrestore(&smu->lock, flags); return IRQ_HANDLED; + } cmd = smu->cmd_cur; smu->cmd_cur = NULL; From benh at kernel.crashing.org Thu Sep 29 17:20:31 2005 From: benh at kernel.crashing.org (Benjamin Herrenschmidt) Date: Thu, 29 Sep 2005 17:20:31 +1000 Subject: iMac G5: experimental thermal & cpufreq support Message-ID: <1127978432.6102.53.camel@gaston> Hi ! I now have some experimental thermal control and cpufreq support for iMac G5. I have not _yet_ implemented support for the SMU based single CPU desktops (PowerMac9,1), those will have to wait a little bit more (not too much hopefully, but I need potential testers to contact me as I lack hardware access). At this point, it should work on PowerMac8,1 (iMacG5 rev A) and PowerMac8,2 (iMacG5 rev B). WARNING: This is really a 'first shot'. There is no overtemp detection, so be careful. The driver doesn't yet have a sysfs interface for you to read the temperature, but I left it with verbose debugging enabled in the kernel log so you can see what's going on with the 2 control loops (the System one which ticks every 5 seconds and the CPU one which ticks every second). Please tell me if it appears to behave properly. On my iMac G5 rev A, the target temperature for the CPU is set by the firmware at 78 degree C with a max at about 83 degree. If I put load on the CPU, the CPU appears to properly ramp up slowly to 82 then go down and stabilize at 78 while the driver slowly ramps the fans up. The algorithm itself is extracted from darwin. However, it's a rather complex modified version of the PID algorithm, and thus it could use some review to make sure I got everything right. The thermal control is also part of a new infrastructure I have written called "windfarm" that splits the whole thing into several modules (though I have only tested with everything built in at this point). Ultimately, it should be possible to port the existing Desktop G5 and Xserver thermal driver to the new infrastructure provided that the appropriate sensor & control modules are written. The old thermal driver uses pretty much the same 2 kind of PID control loops as provided by the windfarm_pid helper. I would encourage people doing thermal control on other machines (laptops, etc...) to also use the new infrastructure. Ok, now the patches. You need to appy them in proper order. First of all, it all is on top of current -git as of yesterday. I won't guarantee they will apply on anything more ancient. First, you need a fix that is currently pending in -mm (and should be in 2.6.14 before it's final) : http://gate.crashing.org/~benh/ppc64-smu-fix.diff Then, you can apply the patch that adds cpufreq support for the iMac G5 (and possibly the SMU based desktop, though not tested) http://gate.crashing.org/~benh/ppc64-fx-freq-scaling.diff Then apply those 2 patches in that order: http://gate.crashing.org/~benh/ppc64-smu-partitions.diff http://gate.crashing.org/~benh/ppc64-smu-thermal-control.diff That's it. Now enable: CONFIG_WINDFARM_SMU and CONFIG_I2C_PMAC_SMU If you are using modules, you may have to manually load the whole bunch, especially the i2c SMU one which isn't requested (yet). And let me know :) Regards, Ben. From pochini at shiny.it Thu Sep 29 17:20:52 2005 From: pochini at shiny.it (Giuliano Pochini) Date: Thu, 29 Sep 2005 09:20:52 +0200 (CEST) Subject: Starting the arch/powerpc merge In-Reply-To: <1127865914.6102.0.camel@gaston> Message-ID: On 28-Sep-2005 Benjamin Herrenschmidt wrote: > On Tue, 2005-09-27 at 18:30 +1000, Paul Mackerras wrote: >> Christoph Hellwig writes: >> >> > What about just dropping POWER3/4 support in 32bit mode? >> >> Yes... I'm getting very close to deciding to do that. In fact POWER3 >> isn't too bad, since it still has BATs, but POWER4/PPC970 would be >> tricky. >> >> Does anyone on these lists have any major objections if we drop >> support for 32-bit kernels on POWER3 and POWER4/PPC970? > > I've stopped supporting G5 on 32 bits kernel for some time now, I have > absolutely no problem just dropping the POWER4 support in 32 bits kernel > in the merged tree. Out of curiosity, is there any advantage in using a 32 bits kernel on ppc64 over a 64 bits kernel ? Speed ? Complexity ? Compatibility ? Memory ? -- Giuliano. From anton at samba.org Thu Sep 29 17:22:15 2005 From: anton at samba.org (Anton Blanchard) Date: Thu, 29 Sep 2005 17:22:15 +1000 Subject: [PATCH 1/2] Unify numa_memory_lookup_table allocation and setup. In-Reply-To: <200509281510.30531.gsbarb@br.ibm.com> References: <200509281510.30531.gsbarb@br.ibm.com> Message-ID: <20050929072214.GH19971@krispykreme> Hi, > Here are some patches to clean up lmb.c, numa.c and init.c, as requested by > Dave Hansen. > > This patch unify duplicated code under setup_numa_memory_lookup_table() Ive done some work to remove numa_memory_lookup_table completely when we switch over to sparsemem. Im hoping to get them into 2.6.15. I'll post what I have so far. Anton From anton at samba.org Thu Sep 29 17:26:16 2005 From: anton at samba.org (Anton Blanchard) Date: Thu, 29 Sep 2005 17:26:16 +1000 Subject: [PATCH 1/3]: Remove kvaddr_to_nid and local_mapnr In-Reply-To: <20050929072214.GH19971@krispykreme> References: <200509281510.30531.gsbarb@br.ibm.com> <20050929072214.GH19971@krispykreme> Message-ID: <20050929072615.GI19971@krispykreme> local_mapnr wasnt used anywhere and kvaddr_to_nid was used in one spot. Signed-off-by: Anton Blanchard --- Index: build/arch/alpha/mm/numa.c =================================================================== --- build.orig/arch/alpha/mm/numa.c 2005-09-13 12:48:54.000000000 +1000 +++ build/arch/alpha/mm/numa.c 2005-09-13 12:49:25.000000000 +1000 @@ -279,7 +279,7 @@ initrd_end, phys_to_virt(PFN_PHYS(max_low_pfn))); } else { - nid = kvaddr_to_nid(initrd_start); + nid = pa_to_nid(__pa(initrd_start)); reserve_bootmem_node(NODE_DATA(nid), virt_to_phys((void *)initrd_start), INITRD_SIZE); Index: build/include/asm-alpha/mmzone.h =================================================================== --- build.orig/include/asm-alpha/mmzone.h 2005-09-13 12:48:54.000000000 +1000 +++ build/include/asm-alpha/mmzone.h 2005-09-13 12:49:25.000000000 +1000 @@ -32,8 +32,6 @@ #define pa_to_nid(pa) alpha_pa_to_nid(pa) #define NODE_DATA(nid) (&node_data[(nid)]) -#define node_localnr(pfn, nid) ((pfn) - NODE_DATA(nid)->node_start_pfn) - #if 1 #define PLAT_NODE_DATA_LOCALNR(p, n) \ (((p) >> PAGE_SHIFT) - PLAT_NODE_DATA(n)->gendata.node_start_pfn) @@ -49,28 +47,14 @@ #ifdef CONFIG_DISCONTIGMEM +#define node_localnr(pfn, nid) ((pfn) - NODE_DATA(nid)->node_start_pfn) + /* * Following are macros that each numa implementation must define. */ -/* - * Given a kernel address, find the home node of the underlying memory. - */ -#define kvaddr_to_nid(kaddr) pa_to_nid(__pa(kaddr)) #define node_start_pfn(nid) (NODE_DATA(nid)->node_start_pfn) -#define local_mapnr(kvaddr) \ - ((__pa(kvaddr) >> PAGE_SHIFT) - node_start_pfn(kvaddr_to_nid(kvaddr))) - -/* - * Given a kaddr, LOCAL_BASE_ADDR finds the owning node of the memory - * and returns the kaddr corresponding to first physical page in the - * node's mem_map. - */ -#define LOCAL_BASE_ADDR(kaddr) \ - ((unsigned long)__va(NODE_DATA(kvaddr_to_nid(kaddr))->node_start_pfn \ - << PAGE_SHIFT)) - /* XXX: FIXME -- wli */ #define kern_addr_valid(kaddr) (0) @@ -106,8 +90,9 @@ #define pfn_to_page(pfn) \ ({ \ - unsigned long kaddr = (unsigned long)__va((pfn) << PAGE_SHIFT); \ - (NODE_DATA(kvaddr_to_nid(kaddr))->node_mem_map + local_mapnr(kaddr)); \ + unsigned long __tmp = pfn; \ + (NODE_DATA(pfn_to_nid(__tmp))->node_mem_map + \ + node_localnr(__tmp, pfn_to_nid(__tmp))); \ }) #define page_to_pfn(page) \ Index: build/include/asm-i386/mmzone.h =================================================================== --- build.orig/include/asm-i386/mmzone.h 2005-09-13 12:48:54.000000000 +1000 +++ build/include/asm-i386/mmzone.h 2005-09-13 12:49:25.000000000 +1000 @@ -76,11 +76,6 @@ * Following are macros that each numa implmentation must define. */ -/* - * Given a kernel address, find the home node of the underlying memory. - */ -#define kvaddr_to_nid(kaddr) pfn_to_nid(__pa(kaddr) >> PAGE_SHIFT) - #define node_start_pfn(nid) (NODE_DATA(nid)->node_start_pfn) #define node_end_pfn(nid) \ ({ \ @@ -88,12 +83,6 @@ __pgdat->node_start_pfn + __pgdat->node_spanned_pages; \ }) -#define local_mapnr(kvaddr) \ -({ \ - unsigned long __pfn = __pa(kvaddr) >> PAGE_SHIFT; \ - (__pfn - node_start_pfn(pfn_to_nid(__pfn))); \ -}) - /* XXX: FIXME -- wli */ #define kern_addr_valid(kaddr) (0) Index: build/include/asm-mips/mmzone.h =================================================================== --- build.orig/include/asm-mips/mmzone.h 2005-09-13 12:48:54.000000000 +1000 +++ build/include/asm-mips/mmzone.h 2005-09-13 12:49:25.000000000 +1000 @@ -10,7 +10,6 @@ #ifdef CONFIG_DISCONTIGMEM -#define kvaddr_to_nid(kvaddr) pa_to_nid(__pa(kvaddr)) #define pfn_to_nid(pfn) pa_to_nid((pfn) << PAGE_SHIFT) #define pfn_valid(pfn) \ Index: build/include/asm-parisc/mmzone.h =================================================================== --- build.orig/include/asm-parisc/mmzone.h 2005-09-13 12:48:54.000000000 +1000 +++ build/include/asm-parisc/mmzone.h 2005-09-13 12:49:25.000000000 +1000 @@ -14,11 +14,6 @@ #define NODE_DATA(nid) (&node_data[nid].pg_data) -/* - * Given a kernel address, find the home node of the underlying memory. - */ -#define kvaddr_to_nid(kaddr) pfn_to_nid(__pa(kaddr) >> PAGE_SHIFT) - #define node_start_pfn(nid) (NODE_DATA(nid)->node_start_pfn) #define node_end_pfn(nid) \ ({ \ @@ -27,12 +22,6 @@ }) #define node_localnr(pfn, nid) ((pfn) - node_start_pfn(nid)) -#define local_mapnr(kvaddr) \ -({ \ - unsigned long __pfn = __pa(kvaddr) >> PAGE_SHIFT; \ - (__pfn - node_start_pfn(pfn_to_nid(__pfn))); \ -}) - #define pfn_to_page(pfn) \ ({ \ unsigned long __pfn = (pfn); \ Index: build/include/asm-ppc64/mmzone.h =================================================================== --- build.orig/include/asm-ppc64/mmzone.h 2005-09-13 12:48:54.000000000 +1000 +++ build/include/asm-ppc64/mmzone.h 2005-09-13 12:49:25.000000000 +1000 @@ -58,8 +58,6 @@ return nid; } -#define node_localnr(pfn, nid) ((pfn) - NODE_DATA(nid)->node_start_pfn) - /* * Following are macros that each numa implmentation must define. */ @@ -67,15 +65,9 @@ #define node_start_pfn(nid) (NODE_DATA(nid)->node_start_pfn) #define node_end_pfn(nid) (NODE_DATA(nid)->node_end_pfn) -#define local_mapnr(kvaddr) \ - ( (__pa(kvaddr) >> PAGE_SHIFT) - node_start_pfn(kvaddr_to_nid(kvaddr)) - #ifdef CONFIG_DISCONTIGMEM -/* - * Given a kernel address, find the home node of the underlying memory. - */ -#define kvaddr_to_nid(kaddr) pa_to_nid(__pa(kaddr)) +#define node_localnr(pfn, nid) ((pfn) - NODE_DATA(nid)->node_start_pfn) #define pfn_to_nid(pfn) pa_to_nid((unsigned long)(pfn) << PAGE_SHIFT) Index: build/include/asm-x86_64/mmzone.h =================================================================== --- build.orig/include/asm-x86_64/mmzone.h 2005-09-13 12:48:54.000000000 +1000 +++ build/include/asm-x86_64/mmzone.h 2005-09-13 12:49:25.000000000 +1000 @@ -39,7 +39,6 @@ #ifdef CONFIG_DISCONTIGMEM #define pfn_to_nid(pfn) phys_to_nid((unsigned long)(pfn) << PAGE_SHIFT) -#define kvaddr_to_nid(kaddr) phys_to_nid(__pa(kaddr)) /* AK: this currently doesn't deal with invalid addresses. We'll see if the 2.5 kernel doesn't pass them @@ -57,7 +56,5 @@ nid__ != 0xff && (pfn) >= node_start_pfn(nid__) && (pfn) < node_end_pfn(nid__); })) #endif -#define local_mapnr(kvaddr) \ - ( (__pa(kvaddr) >> PAGE_SHIFT) - node_start_pfn(kvaddr_to_nid(kvaddr)) ) #endif #endif Index: build/include/linux/mmzone.h =================================================================== --- build.orig/include/linux/mmzone.h 2005-09-13 12:48:54.000000000 +1000 +++ build/include/linux/mmzone.h 2005-09-13 12:49:25.000000000 +1000 @@ -542,11 +542,6 @@ return valid_section(__nr_to_section(nr)); } -/* - * Given a kernel address, find the home node of the underlying memory. - */ -#define kvaddr_to_nid(kaddr) pfn_to_nid(__pa(kaddr) >> PAGE_SHIFT) - static inline struct mem_section *__pfn_to_section(unsigned long pfn) { return __nr_to_section(pfn_to_section_nr(pfn)); Index: build/include/asm-m32r/mmzone.h =================================================================== --- build.orig/include/asm-m32r/mmzone.h 2005-09-13 12:48:54.000000000 +1000 +++ build/include/asm-m32r/mmzone.h 2005-09-13 12:49:25.000000000 +1000 @@ -21,12 +21,6 @@ __pgdat->node_start_pfn + __pgdat->node_spanned_pages - 1; \ }) -#define local_mapnr(kvaddr) \ -({ \ - unsigned long __pfn = __pa(kvaddr) >> PAGE_SHIFT; \ - (__pfn - node_start_pfn(pfn_to_nid(__pfn))); \ -}) - #define pfn_to_page(pfn) \ ({ \ unsigned long __pfn = pfn; \ From anton at samba.org Thu Sep 29 17:27:53 2005 From: anton at samba.org (Anton Blanchard) Date: Thu, 29 Sep 2005 17:27:53 +1000 Subject: [PATCH 2/3]: ppc64: use generic nr_cpus_node In-Reply-To: <20050929072615.GI19971@krispykreme> References: <200509281510.30531.gsbarb@br.ibm.com> <20050929072214.GH19971@krispykreme> <20050929072615.GI19971@krispykreme> Message-ID: <20050929072753.GJ19971@krispykreme> Remove the ppc64 specific nr_cpus_node and use the generic version instead. Signed-off-by: Anton Blanchard --- Index: build/include/asm-powerpc/topology.h =================================================================== --- build.orig/include/asm-powerpc/topology.h 2005-09-10 12:40:58.000000000 +1000 +++ build/include/asm-powerpc/topology.h 2005-09-10 13:13:07.000000000 +1000 @@ -37,8 +37,6 @@ #define pcibus_to_node(node) (-1) #define pcibus_to_cpumask(bus) (cpu_online_map) -#define nr_cpus_node(node) (nr_cpus_in_node[node]) - /* sched_domains SD_NODE_INIT for PPC64 machines */ #define SD_NODE_INIT (struct sched_domain) { \ .span = CPU_MASK_NONE, \ Index: build/arch/ppc64/mm/numa.c =================================================================== --- build.orig/arch/ppc64/mm/numa.c 2005-09-10 12:40:54.000000000 +1000 +++ build/arch/ppc64/mm/numa.c 2005-09-10 13:13:07.000000000 +1000 @@ -36,7 +36,6 @@ ARRAY_INITIALISER}; char *numa_memory_lookup_table; cpumask_t numa_cpumask_lookup_table[MAX_NUMNODES]; -int nr_cpus_in_node[MAX_NUMNODES] = { [0 ... (MAX_NUMNODES -1)] = 0}; struct pglist_data *node_data[MAX_NUMNODES]; bootmem_data_t __initdata plat_node_bdata[MAX_NUMNODES]; @@ -56,14 +55,12 @@ EXPORT_SYMBOL(numa_cpu_lookup_table); EXPORT_SYMBOL(numa_memory_lookup_table); EXPORT_SYMBOL(numa_cpumask_lookup_table); -EXPORT_SYMBOL(nr_cpus_in_node); static inline void map_cpu_to_node(int cpu, int node) { numa_cpu_lookup_table[cpu] = node; if (!(cpu_isset(cpu, numa_cpumask_lookup_table[node]))) { cpu_set(cpu, numa_cpumask_lookup_table[node]); - nr_cpus_in_node[node]++; } } @@ -76,7 +73,6 @@ if (cpu_isset(cpu, numa_cpumask_lookup_table[node])) { cpu_clear(cpu, numa_cpumask_lookup_table[node]); - nr_cpus_in_node[node]--; } else { printk(KERN_ERR "WARNING: cpu %lu not found in node %d\n", cpu, node); Index: build/include/asm-ppc64/mmzone.h =================================================================== --- build.orig/include/asm-ppc64/mmzone.h 2005-09-10 13:12:32.000000000 +1000 +++ build/include/asm-ppc64/mmzone.h 2005-09-10 13:13:07.000000000 +1000 @@ -32,7 +32,6 @@ extern int numa_cpu_lookup_table[]; extern char *numa_memory_lookup_table; extern cpumask_t numa_cpumask_lookup_table[]; -extern int nr_cpus_in_node[]; /* 16MB regions */ #define MEMORY_INCREMENT_SHIFT 24 From anton at samba.org Thu Sep 29 17:35:50 2005 From: anton at samba.org (Anton Blanchard) Date: Thu, 29 Sep 2005 17:35:50 +1000 Subject: [PATCH 3/3]: ppc64: convert to sparsemem In-Reply-To: <20050929072753.GJ19971@krispykreme> References: <200509281510.30531.gsbarb@br.ibm.com> <20050929072214.GH19971@krispykreme> <20050929072615.GI19971@krispykreme> <20050929072753.GJ19971@krispykreme> Message-ID: <20050929073550.GK19971@krispykreme> Convert to sparsemem and remove all the discontigmem code in the process. This has a few advantages: - The old numa_memory_lookup_table can go away - All the arch specific discontigmem magic can go away We also remove the triple pass of memory properties and instead create a list of per node extents that we iterate through. Signed-off-by: Anton Blanchard --- Index: build/arch/ppc64/mm/numa.c =================================================================== --- build.orig/arch/ppc64/mm/numa.c 2005-09-26 16:42:11.000000000 +1000 +++ build/arch/ppc64/mm/numa.c 2005-09-26 16:42:12.000000000 +1000 @@ -17,51 +17,121 @@ #include #include #include +#include #include -#include -#include static int numa_enabled = 1; static int numa_debug; #define dbg(args...) if (numa_debug) { printk(KERN_INFO args); } -#ifdef DEBUG_NUMA -#define ARRAY_INITIALISER -1 -#else -#define ARRAY_INITIALISER 0 -#endif - -int numa_cpu_lookup_table[NR_CPUS] = { [ 0 ... (NR_CPUS - 1)] = - ARRAY_INITIALISER}; -char *numa_memory_lookup_table; +int numa_cpu_lookup_table[NR_CPUS]; cpumask_t numa_cpumask_lookup_table[MAX_NUMNODES]; - struct pglist_data *node_data[MAX_NUMNODES]; -bootmem_data_t __initdata plat_node_bdata[MAX_NUMNODES]; + +EXPORT_SYMBOL(numa_cpu_lookup_table); +EXPORT_SYMBOL(numa_cpumask_lookup_table); +EXPORT_SYMBOL(node_data); + +static bootmem_data_t __initdata plat_node_bdata[MAX_NUMNODES]; static int min_common_depth; /* - * We need somewhere to store start/span for each node until we have + * We need somewhere to store start/end/node for each region until we have * allocated the real node_data structures. */ +#define MAX_REGIONS (MAX_LMB_REGIONS*2) static struct { - unsigned long node_start_pfn; - unsigned long node_end_pfn; - unsigned long node_present_pages; -} init_node_data[MAX_NUMNODES] __initdata; + unsigned long start_pfn; + unsigned long end_pfn; + int nid; +} init_node_data[MAX_REGIONS] __initdata; -EXPORT_SYMBOL(node_data); -EXPORT_SYMBOL(numa_cpu_lookup_table); -EXPORT_SYMBOL(numa_memory_lookup_table); -EXPORT_SYMBOL(numa_cpumask_lookup_table); +int __init early_pfn_to_nid(unsigned long pfn) +{ + unsigned int i; + + for (i = 0; init_node_data[i].end_pfn; i++) { + unsigned long start_pfn = init_node_data[i].start_pfn; + unsigned long end_pfn = init_node_data[i].end_pfn; + + if ((start_pfn <= pfn) && (pfn < end_pfn)) + return init_node_data[i].nid; + } + + return -1; +} + +void __init add_region(unsigned int nid, unsigned long start_pfn, + unsigned long pages) +{ + unsigned int i; + + dbg("add_region nid %d start_pfn 0x%lx pages 0x%lx\n", + nid, start_pfn, pages); + + for (i = 0; init_node_data[i].end_pfn; i++) { + if (init_node_data[i].nid != nid) + continue; + if (init_node_data[i].end_pfn == start_pfn) { + init_node_data[i].end_pfn += pages; + return; + } + if (init_node_data[i].start_pfn == (start_pfn + pages)) { + init_node_data[i].start_pfn -= pages; + return; + } + } + + /* + * Leave last entry NULL so we dont iterate off the end (we use + * entry.end_pfn to terminate the walk). + */ + if (i >= (MAX_REGIONS - 1)) { + printk(KERN_ERR "WARNING: too many memory regions in " + "numa code, truncating\n"); + return; + } + + init_node_data[i].start_pfn = start_pfn; + init_node_data[i].end_pfn = start_pfn + pages; + init_node_data[i].nid = nid; +} + +/* We assume init_node_data has no overlapping regions */ +void __init get_region(unsigned int nid, unsigned long *start_pfn, + unsigned long *end_pfn, unsigned long *pages_present) +{ + unsigned int i; + + *start_pfn = -1UL; + *end_pfn = *pages_present = 0; + + for (i = 0; init_node_data[i].end_pfn; i++) { + if (init_node_data[i].nid != nid) + continue; + + *pages_present += init_node_data[i].end_pfn - + init_node_data[i].start_pfn; + + if (init_node_data[i].start_pfn < *start_pfn) + *start_pfn = init_node_data[i].start_pfn; + + if (init_node_data[i].end_pfn > *end_pfn) + *end_pfn = init_node_data[i].end_pfn; + } + + /* We didnt find a matching region, return start/end as 0 */ + if (*start_pfn == -1UL) + start_pfn = 0; +} static inline void map_cpu_to_node(int cpu, int node) { numa_cpu_lookup_table[cpu] = node; - if (!(cpu_isset(cpu, numa_cpumask_lookup_table[node]))) { + + if (!(cpu_isset(cpu, numa_cpumask_lookup_table[node]))) cpu_set(cpu, numa_cpumask_lookup_table[node]); - } } #ifdef CONFIG_HOTPLUG_CPU @@ -80,7 +150,7 @@ } #endif /* CONFIG_HOTPLUG_CPU */ -static struct device_node * __devinit find_cpu_node(unsigned int cpu) +static struct device_node *find_cpu_node(unsigned int cpu) { unsigned int hw_cpuid = get_hard_smp_processor_id(cpu); struct device_node *cpu_node = NULL; @@ -207,7 +277,7 @@ return rc; } -static unsigned long read_n_cells(int n, unsigned int **buf) +static unsigned long __init read_n_cells(int n, unsigned int **buf) { unsigned long result = 0; @@ -289,7 +359,8 @@ * or zero. If the returned value of size is 0 the region should be * discarded as it lies wholy above the memory limit. */ -static unsigned long __init numa_enforce_memory_limit(unsigned long start, unsigned long size) +static unsigned long __init numa_enforce_memory_limit(unsigned long start, + unsigned long size) { /* * We use lmb_end_of_DRAM() in here instead of memory_limit because @@ -315,8 +386,7 @@ struct device_node *cpu = NULL; struct device_node *memory = NULL; int addr_cells, size_cells; - int max_domain = 0; - long entries = lmb_end_of_DRAM() >> MEMORY_INCREMENT_SHIFT; + int max_domain; unsigned long i; if (numa_enabled == 0) { @@ -324,13 +394,6 @@ return -1; } - numa_memory_lookup_table = - (char *)abs_to_virt(lmb_alloc(entries * sizeof(char), 1)); - memset(numa_memory_lookup_table, 0, entries * sizeof(char)); - - for (i = 0; i < entries ; i++) - numa_memory_lookup_table[i] = ARRAY_INITIALISER; - min_common_depth = find_min_common_depth(); dbg("NUMA associativity depth for CPU/Memory: %d\n", min_common_depth); @@ -382,9 +445,6 @@ start = read_n_cells(addr_cells, &memcell_buf); size = read_n_cells(size_cells, &memcell_buf); - start = _ALIGN_DOWN(start, MEMORY_INCREMENT); - size = _ALIGN_UP(size, MEMORY_INCREMENT); - numa_domain = of_node_numa_domain(memory); if (numa_domain >= MAX_NUMNODES) { @@ -398,44 +458,15 @@ if (max_domain < numa_domain) max_domain = numa_domain; - if (! (size = numa_enforce_memory_limit(start, size))) { + if (!(size = numa_enforce_memory_limit(start, size))) { if (--ranges) goto new_range; else continue; } - /* - * Initialize new node struct, or add to an existing one. - */ - if (init_node_data[numa_domain].node_end_pfn) { - if ((start / PAGE_SIZE) < - init_node_data[numa_domain].node_start_pfn) - init_node_data[numa_domain].node_start_pfn = - start / PAGE_SIZE; - if (((start / PAGE_SIZE) + (size / PAGE_SIZE)) > - init_node_data[numa_domain].node_end_pfn) - init_node_data[numa_domain].node_end_pfn = - (start / PAGE_SIZE) + - (size / PAGE_SIZE); - - init_node_data[numa_domain].node_present_pages += - size / PAGE_SIZE; - } else { - node_set_online(numa_domain); - - init_node_data[numa_domain].node_start_pfn = - start / PAGE_SIZE; - init_node_data[numa_domain].node_end_pfn = - init_node_data[numa_domain].node_start_pfn + - size / PAGE_SIZE; - init_node_data[numa_domain].node_present_pages = - size / PAGE_SIZE; - } - - for (i = start ; i < (start+size); i += MEMORY_INCREMENT) - numa_memory_lookup_table[i >> MEMORY_INCREMENT_SHIFT] = - numa_domain; + add_region(numa_domain, start >> PAGE_SHIFT, + size >> PAGE_SHIFT); if (--ranges) goto new_range; @@ -451,32 +482,15 @@ { unsigned long top_of_ram = lmb_end_of_DRAM(); unsigned long total_ram = lmb_phys_mem_size(); - unsigned long i; printk(KERN_INFO "Top of RAM: 0x%lx, Total RAM: 0x%lx\n", top_of_ram, total_ram); printk(KERN_INFO "Memory hole size: %ldMB\n", (top_of_ram - total_ram) >> 20); - if (!numa_memory_lookup_table) { - long entries = top_of_ram >> MEMORY_INCREMENT_SHIFT; - numa_memory_lookup_table = - (char *)abs_to_virt(lmb_alloc(entries * sizeof(char), 1)); - memset(numa_memory_lookup_table, 0, entries * sizeof(char)); - for (i = 0; i < entries ; i++) - numa_memory_lookup_table[i] = ARRAY_INITIALISER; - } - map_cpu_to_node(boot_cpuid, 0); - + add_region(0, 0, lmb_end_of_DRAM() >> PAGE_SHIFT); node_set_online(0); - - init_node_data[0].node_start_pfn = 0; - init_node_data[0].node_end_pfn = lmb_end_of_DRAM() / PAGE_SIZE; - init_node_data[0].node_present_pages = total_ram / PAGE_SIZE; - - for (i = 0 ; i < top_of_ram; i += MEMORY_INCREMENT) - numa_memory_lookup_table[i >> MEMORY_INCREMENT_SHIFT] = 0; } static void __init dump_numa_topology(void) @@ -494,8 +508,9 @@ count = 0; - for (i = 0; i < lmb_end_of_DRAM(); i += MEMORY_INCREMENT) { - if (numa_memory_lookup_table[i >> MEMORY_INCREMENT_SHIFT] == node) { + for (i = 0; i < lmb_end_of_DRAM(); + i += (1 << SECTION_SIZE_BITS)) { + if (early_pfn_to_nid(i >> PAGE_SHIFT) == node) { if (count == 0) printk(" 0x%lx", i); ++count; @@ -520,10 +535,12 @@ * * Returns the physical address of the memory. */ -static unsigned long careful_allocation(int nid, unsigned long size, - unsigned long align, unsigned long end) +static void __init *careful_allocation(int nid, unsigned long size, + unsigned long align, + unsigned long end_pfn) { - unsigned long ret = lmb_alloc_base(size, align, end); + int new_nid; + unsigned long ret = lmb_alloc_base(size, align, end_pfn << PAGE_SHIFT); /* retry over all memory */ if (!ret) @@ -537,28 +554,27 @@ * If the memory came from a previously allocated node, we must * retry with the bootmem allocator. */ - if (pa_to_nid(ret) < nid) { - nid = pa_to_nid(ret); - ret = (unsigned long)__alloc_bootmem_node(NODE_DATA(nid), + new_nid = early_pfn_to_nid(ret >> PAGE_SHIFT); + if (new_nid < nid) { + ret = (unsigned long)__alloc_bootmem_node(NODE_DATA(new_nid), size, align, 0); if (!ret) panic("numa.c: cannot allocate %lu bytes on node %d", - size, nid); + size, new_nid); - ret = virt_to_abs(ret); + ret = __pa(ret); dbg("alloc_bootmem %lx %lx\n", ret, size); } - return ret; + return (void *)ret; } void __init do_init_bootmem(void) { int nid; - int addr_cells, size_cells; - struct device_node *memory = NULL; + unsigned int i; static struct notifier_block ppc64_numa_nb = { .notifier_call = cpu_numa_callback, .priority = 1 /* Must run before sched domains notifier. */ @@ -576,99 +592,66 @@ register_cpu_notifier(&ppc64_numa_nb); for_each_online_node(nid) { - unsigned long start_paddr, end_paddr; - int i; + unsigned long start_pfn, end_pfn, pages_present; unsigned long bootmem_paddr; unsigned long bootmap_pages; - start_paddr = init_node_data[nid].node_start_pfn * PAGE_SIZE; - end_paddr = init_node_data[nid].node_end_pfn * PAGE_SIZE; + get_region(nid, &start_pfn, &end_pfn, &pages_present); /* Allocate the node structure node local if possible */ - NODE_DATA(nid) = (struct pglist_data *)careful_allocation(nid, + NODE_DATA(nid) = careful_allocation(nid, sizeof(struct pglist_data), - SMP_CACHE_BYTES, end_paddr); - NODE_DATA(nid) = abs_to_virt(NODE_DATA(nid)); + SMP_CACHE_BYTES, end_pfn); + NODE_DATA(nid) = __va(NODE_DATA(nid)); memset(NODE_DATA(nid), 0, sizeof(struct pglist_data)); dbg("node %d\n", nid); dbg("NODE_DATA() = %p\n", NODE_DATA(nid)); NODE_DATA(nid)->bdata = &plat_node_bdata[nid]; - NODE_DATA(nid)->node_start_pfn = - init_node_data[nid].node_start_pfn; - NODE_DATA(nid)->node_spanned_pages = - end_paddr - start_paddr; + NODE_DATA(nid)->node_start_pfn = start_pfn; + NODE_DATA(nid)->node_spanned_pages = end_pfn - start_pfn; if (NODE_DATA(nid)->node_spanned_pages == 0) continue; - dbg("start_paddr = %lx\n", start_paddr); - dbg("end_paddr = %lx\n", end_paddr); + dbg("start_paddr = %lx\n", start_pfn << PAGE_SHIFT); + dbg("end_paddr = %lx\n", end_pfn << PAGE_SHIFT); - bootmap_pages = bootmem_bootmap_pages((end_paddr - start_paddr) >> PAGE_SHIFT); + bootmap_pages = bootmem_bootmap_pages(end_pfn - start_pfn); + bootmem_paddr = (unsigned long)careful_allocation(nid, + bootmap_pages << PAGE_SHIFT, + PAGE_SIZE, end_pfn); + memset(__va(bootmem_paddr), 0, bootmap_pages << PAGE_SHIFT); - bootmem_paddr = careful_allocation(nid, - bootmap_pages << PAGE_SHIFT, - PAGE_SIZE, end_paddr); - memset(abs_to_virt(bootmem_paddr), 0, - bootmap_pages << PAGE_SHIFT); dbg("bootmap_paddr = %lx\n", bootmem_paddr); init_bootmem_node(NODE_DATA(nid), bootmem_paddr >> PAGE_SHIFT, - start_paddr >> PAGE_SHIFT, - end_paddr >> PAGE_SHIFT); - - /* - * We need to do another scan of all memory sections to - * associate memory with the correct node. - */ - addr_cells = get_mem_addr_cells(); - size_cells = get_mem_size_cells(); - memory = NULL; - while ((memory = of_find_node_by_type(memory, "memory")) != NULL) { - unsigned long mem_start, mem_size; - int numa_domain, ranges; - unsigned int *memcell_buf; - unsigned int len; - - memcell_buf = (unsigned int *)get_property(memory, "reg", &len); - if (!memcell_buf || len <= 0) - continue; + start_pfn, end_pfn); - ranges = memory->n_addrs; /* ranges in cell */ -new_range: - mem_start = read_n_cells(addr_cells, &memcell_buf); - mem_size = read_n_cells(size_cells, &memcell_buf); - if (numa_enabled) { - numa_domain = of_node_numa_domain(memory); - if (numa_domain >= MAX_NUMNODES) - numa_domain = 0; - } else - numa_domain = 0; + /* Add free regions on this node */ + for (i = 0; init_node_data[i].end_pfn; i++) { + unsigned long start, end; - if (numa_domain != nid) + if (init_node_data[i].nid != nid) continue; - mem_size = numa_enforce_memory_limit(mem_start, mem_size); - if (mem_size) { - dbg("free_bootmem %lx %lx\n", mem_start, mem_size); - free_bootmem_node(NODE_DATA(nid), mem_start, mem_size); - } + start = init_node_data[i].start_pfn << PAGE_SHIFT; + end = init_node_data[i].end_pfn << PAGE_SHIFT; - if (--ranges) /* process all ranges in cell */ - goto new_range; + dbg("free_bootmem %lx %lx\n", start, end - start); + free_bootmem_node(NODE_DATA(nid), start, end - start); } - /* - * Mark reserved regions on this node - */ + /* Mark reserved regions on this node */ for (i = 0; i < lmb.reserved.cnt; i++) { unsigned long physbase = lmb.reserved.region[i].base; unsigned long size = lmb.reserved.region[i].size; + unsigned long start_paddr = start_pfn << PAGE_SHIFT; + unsigned long end_paddr = end_pfn << PAGE_SHIFT; - if (pa_to_nid(physbase) != nid && - pa_to_nid(physbase+size-1) != nid) + if (early_pfn_to_nid(physbase >> PAGE_SHIFT) != nid && + early_pfn_to_nid((physbase+size-1) >> PAGE_SHIFT) != nid) continue; if (physbase < end_paddr && @@ -688,46 +671,19 @@ size); } } - /* - * This loop may look famaliar, but we have to do it again - * after marking our reserved memory to mark memory present - * for sparsemem. - */ - addr_cells = get_mem_addr_cells(); - size_cells = get_mem_size_cells(); - memory = NULL; - while ((memory = of_find_node_by_type(memory, "memory")) != NULL) { - unsigned long mem_start, mem_size; - int numa_domain, ranges; - unsigned int *memcell_buf; - unsigned int len; - memcell_buf = (unsigned int *)get_property(memory, "reg", &len); - if (!memcell_buf || len <= 0) - continue; + /* Add regions into sparsemem */ + for (i = 0; init_node_data[i].end_pfn; i++) { + unsigned long start, end; - ranges = memory->n_addrs; /* ranges in cell */ -new_range2: - mem_start = read_n_cells(addr_cells, &memcell_buf); - mem_size = read_n_cells(size_cells, &memcell_buf); - if (numa_enabled) { - numa_domain = of_node_numa_domain(memory); - if (numa_domain >= MAX_NUMNODES) - numa_domain = 0; - } else - numa_domain = 0; - - if (numa_domain != nid) + if (init_node_data[i].nid != nid) continue; - mem_size = numa_enforce_memory_limit(mem_start, mem_size); - memory_present(numa_domain, mem_start >> PAGE_SHIFT, - (mem_start + mem_size) >> PAGE_SHIFT); + start = init_node_data[i].start_pfn; + end = init_node_data[i].end_pfn; - if (--ranges) /* process all ranges in cell */ - goto new_range2; + memory_present(nid, start, end); } - } } @@ -741,21 +697,18 @@ memset(zholes_size, 0, sizeof(zholes_size)); for_each_online_node(nid) { - unsigned long start_pfn; - unsigned long end_pfn; + unsigned long start_pfn, end_pfn, pages_present; - start_pfn = init_node_data[nid].node_start_pfn; - end_pfn = init_node_data[nid].node_end_pfn; + get_region(nid, &start_pfn, &end_pfn, &pages_present); zones_size[ZONE_DMA] = end_pfn - start_pfn; - zholes_size[ZONE_DMA] = zones_size[ZONE_DMA] - - init_node_data[nid].node_present_pages; + zholes_size[ZONE_DMA] = zones_size[ZONE_DMA] - pages_present; dbg("free_area_init node %d %lx %lx (hole: %lx)\n", nid, zones_size[ZONE_DMA], start_pfn, zholes_size[ZONE_DMA]); - free_area_init_node(nid, NODE_DATA(nid), zones_size, - start_pfn, zholes_size); + free_area_init_node(nid, NODE_DATA(nid), zones_size, start_pfn, + zholes_size); } } Index: build/include/asm-ppc64/mmzone.h =================================================================== --- build.orig/include/asm-ppc64/mmzone.h 2005-09-26 16:42:11.000000000 +1000 +++ build/include/asm-ppc64/mmzone.h 2005-09-26 16:42:12.000000000 +1000 @@ -8,15 +8,14 @@ #define _ASM_MMZONE_H_ #include -#include -/* generic non-linear memory support: +/* + * generic non-linear memory support: * * 1) we will not split memory into more chunks than will fit into the * flags field of the struct page */ - #ifdef CONFIG_NEED_MULTIPLE_NODES extern struct pglist_data *node_data[]; @@ -30,33 +29,8 @@ */ extern int numa_cpu_lookup_table[]; -extern char *numa_memory_lookup_table; extern cpumask_t numa_cpumask_lookup_table[]; -/* 16MB regions */ -#define MEMORY_INCREMENT_SHIFT 24 -#define MEMORY_INCREMENT (1UL << MEMORY_INCREMENT_SHIFT) - -/* NUMA debugging, will not work on a DLPAR machine */ -#undef DEBUG_NUMA - -static inline int pa_to_nid(unsigned long pa) -{ - int nid; - - nid = numa_memory_lookup_table[pa >> MEMORY_INCREMENT_SHIFT]; - -#ifdef DEBUG_NUMA - /* the physical address passed in is not in the map for the system */ - if (nid == -1) { - printk("bad address: %lx\n", pa); - BUG(); - } -#endif - - return nid; -} - /* * Following are macros that each numa implmentation must define. */ @@ -64,36 +38,10 @@ #define node_start_pfn(nid) (NODE_DATA(nid)->node_start_pfn) #define node_end_pfn(nid) (NODE_DATA(nid)->node_end_pfn) -#ifdef CONFIG_DISCONTIGMEM - -#define node_localnr(pfn, nid) ((pfn) - NODE_DATA(nid)->node_start_pfn) - -#define pfn_to_nid(pfn) pa_to_nid((unsigned long)(pfn) << PAGE_SHIFT) - -/* Written this way to avoid evaluating arguments twice */ -#define discontigmem_pfn_to_page(pfn) \ -({ \ - unsigned long __tmp = pfn; \ - (NODE_DATA(pfn_to_nid(__tmp))->node_mem_map + \ - node_localnr(__tmp, pfn_to_nid(__tmp))); \ -}) - -#define discontigmem_page_to_pfn(p) \ -({ \ - struct page *__tmp = p; \ - (((__tmp) - page_zone(__tmp)->zone_mem_map) + \ - page_zone(__tmp)->zone_start_pfn); \ -}) - -/* XXX fix for discontiguous physical memory */ -#define discontigmem_pfn_valid(pfn) ((pfn) < num_physpages) - -#endif /* CONFIG_DISCONTIGMEM */ - #endif /* CONFIG_NEED_MULTIPLE_NODES */ #ifdef CONFIG_HAVE_ARCH_EARLY_PFN_TO_NID -#define early_pfn_to_nid(pfn) pa_to_nid(((unsigned long)pfn) << PAGE_SHIFT) +extern int __init early_pfn_to_nid(unsigned long pfn); #endif #endif /* _ASM_MMZONE_H_ */ Index: build/arch/ppc64/Kconfig =================================================================== --- build.orig/arch/ppc64/Kconfig 2005-09-21 10:41:47.000000000 +1000 +++ build/arch/ppc64/Kconfig 2005-09-26 16:42:12.000000000 +1000 @@ -238,23 +238,14 @@ def_bool y config ARCH_FLATMEM_ENABLE - def_bool y - depends on !NUMA - -config ARCH_DISCONTIGMEM_ENABLE - def_bool y - depends on SMP && PPC_PSERIES - -config ARCH_DISCONTIGMEM_DEFAULT def_bool y - depends on ARCH_DISCONTIGMEM_ENABLE -config ARCH_FLATMEM_ENABLE +config ARCH_SPARSEMEM_ENABLE def_bool y -config ARCH_SPARSEMEM_ENABLE +config ARCH_SPARSEMEM_DEFAULT def_bool y - depends on ARCH_DISCONTIGMEM_ENABLE + depends on PPC_PSERIES source "mm/Kconfig" @@ -276,7 +267,8 @@ config NUMA bool "NUMA support" - default y if DISCONTIGMEM || SPARSEMEM + depends on SPARSEMEM + default y if SPARSEMEM config SCHED_SMT bool "SMT (Hyperthreading) scheduler support" Index: build/include/asm-powerpc/topology.h =================================================================== --- build.orig/include/asm-powerpc/topology.h 2005-09-26 16:42:11.000000000 +1000 +++ build/include/asm-powerpc/topology.h 2005-09-26 16:42:12.000000000 +1000 @@ -9,15 +9,7 @@ static inline int cpu_to_node(int cpu) { - int node; - - node = numa_cpu_lookup_table[cpu]; - -#ifdef DEBUG_NUMA - BUG_ON(node == -1); -#endif - - return node; + return numa_cpu_lookup_table[cpu]; } #define parent_node(node) (node) Index: build/include/asm-ppc64/page.h =================================================================== --- build.orig/include/asm-ppc64/page.h 2005-09-15 17:33:49.000000000 +1000 +++ build/include/asm-ppc64/page.h 2005-09-26 16:42:12.000000000 +1000 @@ -208,11 +208,6 @@ #define __va(x) ((void *)((unsigned long)(x) + KERNELBASE)) -#ifdef CONFIG_DISCONTIGMEM -#define page_to_pfn(page) discontigmem_page_to_pfn(page) -#define pfn_to_page(pfn) discontigmem_pfn_to_page(pfn) -#define pfn_valid(pfn) discontigmem_pfn_valid(pfn) -#endif #ifdef CONFIG_FLATMEM #define pfn_to_page(pfn) (mem_map + (pfn)) #define page_to_pfn(page) ((unsigned long)((page) - mem_map)) From benh at kernel.crashing.org Thu Sep 29 18:40:29 2005 From: benh at kernel.crashing.org (Benjamin Herrenschmidt) Date: Thu, 29 Sep 2005 18:40:29 +1000 Subject: iMac G5: experimental thermal & cpufreq support In-Reply-To: <1127978432.6102.53.camel@gaston> References: <1127978432.6102.53.camel@gaston> Message-ID: <1127983229.6102.60.camel@gaston> On Thu, 2005-09-29 at 17:20 +1000, Benjamin Herrenschmidt wrote: > http://gate.crashing.org/~benh/ppc64-smu-thermal-control.diff You may want to re-download this one if you got it already, I just fixed a bug in the calculations of the CPU control loop. It's now getting results much more consistant with OS X. I still have to add some overtemp handling and I'll remove the debug stuff and work on supporting the PowerMac9,1 desktop model. Ben. From linuxppc at jdl.com Thu Sep 29 21:52:44 2005 From: linuxppc at jdl.com (Jon Loeliger) Date: Thu, 29 Sep 2005 06:52:44 -0500 Subject: Merge conflicts in ppc64/mm/{hash_native.c,tlb.c} In-Reply-To: Your message of "Thu, 29 Sep 2005 13:39:16 +1000." <17211.25060.419702.871039@cargo.ozlabs.ibm.com> References: <17211.25060.419702.871039@cargo.ozlabs.ibm.com> Message-ID: So, like, the other day Paul Mackerras mumbled: > > Ben's hugepage fixes clashed with Ben's virtual-addr-in-batch patch. > I have done the merge and resolved the conflict and pushed it out. It > should be on kernel.org soon. Excellent! Thanks. jdl From jdl at freescale.com Fri Sep 30 00:50:01 2005 From: jdl at freescale.com (Jon Loeliger) Date: Thu, 29 Sep 2005 09:50:01 -0500 Subject: Reminder of outstanding merge patchs Message-ID: <1128005401.11404.107.camel@cashmere.sps.mot.com> Paul, Just wanted to toss a reminder out here for you regarding two merge patches that might be crack-slippers: 09/19 powerpc Revised merge asm-ppc*/hardirq.h 09/20 powerpc Merge asm-ppc*/vga.h Thanks, jdl From arndb at de.ibm.com Fri Sep 30 08:00:09 2005 From: arndb at de.ibm.com (Arnd Bergmann) Date: Thu, 29 Sep 2005 18:00:09 -0400 Subject: [patch 0/8] spufs release for 2.6.13 Message-ID: <20050929220009.146368000@localhost> This is the current patch set that we have been testing on the Cell Blade with the 2.6.13 kernel. Parts of this have already been included in 2.6.14-rc or are superceded by recent developments that I have already posted for -rc2. The patch set is not meant for review or for even inclusion in a mainline kernel but rather as a reference of what we are running ourselves. It also provides a base level for our friends at http://www.bsc.es/projects/deepcomputing/linuxoncell/ so they can build a distribution kernel from it. Arnd <>< -- From arndb at de.ibm.com Fri Sep 30 08:00:10 2005 From: arndb at de.ibm.com (Arnd Bergmann) Date: Thu, 29 Sep 2005 18:00:10 -0400 Subject: [patch 1/8] spufs release for 2.6.13 References: <20050929220009.146368000@localhost> Message-ID: <20050929220038.517790000@localhost> An embedded and charset-unspecified text was scrubbed... Name: spufs-9.diff Url: http://ozlabs.org/pipermail/linuxppc64-dev/attachments/20050929/eaaf77cd/attachment.txt From arndb at de.ibm.com Fri Sep 30 08:00:13 2005 From: arndb at de.ibm.com (Arnd Bergmann) Date: Thu, 29 Sep 2005 18:00:13 -0400 Subject: [patch 4/8] spufs release for 2.6.13 References: <20050929220009.146368000@localhost> Message-ID: <20050929220039.048885000@localhost> An embedded and charset-unspecified text was scrubbed... Name: spufs-generated-files-2.diff Url: http://ozlabs.org/pipermail/linuxppc64-dev/attachments/20050929/5c241784/attachment.txt From arndb at de.ibm.com Fri Sep 30 08:00:14 2005 From: arndb at de.ibm.com (Arnd Bergmann) Date: Thu, 29 Sep 2005 18:00:14 -0400 Subject: [patch 5/8] spufs release for 2.6.13 References: <20050929220009.146368000@localhost> Message-ID: <20050929220039.221724000@localhost> An embedded and charset-unspecified text was scrubbed... Name: spufs-debug-4.diff Url: http://ozlabs.org/pipermail/linuxppc64-dev/attachments/20050929/c4b7d48a/attachment.txt From arndb at de.ibm.com Fri Sep 30 08:00:17 2005 From: arndb at de.ibm.com (Arnd Bergmann) Date: Thu, 29 Sep 2005 18:00:17 -0400 Subject: [patch 8/8] spufs release for 2.6.13 References: <20050929220009.146368000@localhost> Message-ID: <20050929220039.739560000@localhost> An embedded and charset-unspecified text was scrubbed... Name: bpa-random-hacks-2.diff Url: http://ozlabs.org/pipermail/linuxppc64-dev/attachments/20050929/b5760e7a/attachment.txt From arndb at de.ibm.com Fri Sep 30 08:00:12 2005 From: arndb at de.ibm.com (Arnd Bergmann) Date: Thu, 29 Sep 2005 18:00:12 -0400 Subject: [patch 3/8] spufs release for 2.6.13 References: <20050929220009.146368000@localhost> Message-ID: <20050929220038.871643000@localhost> An embedded and charset-unspecified text was scrubbed... Name: spufs-context-3-part2.diff Url: http://ozlabs.org/pipermail/linuxppc64-dev/attachments/20050929/dcb00961/attachment.txt From arndb at de.ibm.com Fri Sep 30 08:00:11 2005 From: arndb at de.ibm.com (Arnd Bergmann) Date: Thu, 29 Sep 2005 18:00:11 -0400 Subject: [patch 2/8] spufs release for 2.6.13 References: <20050929220009.146368000@localhost> Message-ID: <20050929220038.694757000@localhost> An embedded and charset-unspecified text was scrubbed... Name: spufs-context-5.diff Url: http://ozlabs.org/pipermail/linuxppc64-dev/attachments/20050929/2cf059b1/attachment.txt From arndb at de.ibm.com Fri Sep 30 08:00:15 2005 From: arndb at de.ibm.com (Arnd Bergmann) Date: Thu, 29 Sep 2005 18:00:15 -0400 Subject: [patch 6/8] spufs release for 2.6.13 References: <20050929220009.146368000@localhost> Message-ID: <20050929220039.390920000@localhost> An embedded and charset-unspecified text was scrubbed... Name: net-add-driver-for-the-nic-on-cell-blades-2.patch Url: http://ozlabs.org/pipermail/linuxppc64-dev/attachments/20050929/da3563dd/attachment.txt From arndb at de.ibm.com Fri Sep 30 08:00:16 2005 From: arndb at de.ibm.com (Arnd Bergmann) Date: Thu, 29 Sep 2005 18:00:16 -0400 Subject: [patch 7/8] spufs release for 2.6.13 References: <20050929220009.146368000@localhost> Message-ID: <20050929220039.571046000@localhost> An embedded and charset-unspecified text was scrubbed... Name: rtascons-2.diff Url: http://ozlabs.org/pipermail/linuxppc64-dev/attachments/20050929/3ae4b619/attachment.txt From geoffrey.levand at am.sony.com Fri Sep 30 02:55:11 2005 From: geoffrey.levand at am.sony.com (Geoff Levand) Date: Thu, 29 Sep 2005 09:55:11 -0700 Subject: rounding up CPUs on debug exception In-Reply-To: <17208.35609.992828.773554@cargo.ozlabs.ibm.com> References: <43384360.1040808@am.sony.com> <17208.35609.992828.773554@cargo.ozlabs.ibm.com> Message-ID: <433C1C6F.1070307@am.sony.com> Paul Mackerras wrote: > Geoff Levand writes: > > >>When kgdb handles a debugging exception (trap or trace for ppc) it >>tries to stop execution on the other CPUs as soon as possible so >>that changes in the system state from the time of the exception >>are minimized. The i386 code (below) uses the inter-processor >>interrupt features of the APIC interrupt controller to send a >>high priority NMI to the other CPUs. An NMI is needed here, >>since another CPU may be waiting with interrupts disabled on a >>spin lock the current cpu holds. > > > Xmon uses smp_send_debugger_break(MSG_ALL_BUT_SELF) for this. It > isn't an NMI, just a regular IPI, though. > Thanks for the tip. I used this and it works OK, although it seems take a long time to sync under some conditions. I noticed in your 'hotplug cpu on powermacs' post that powermacs have the soft-reset pin connected to a GPIO port. When I have some time I'll look into using this to send an NMI to the orher CPU's. -Geoff From haveblue at us.ibm.com Fri Sep 30 03:08:58 2005 From: haveblue at us.ibm.com (Dave Hansen) Date: Thu, 29 Sep 2005 10:08:58 -0700 Subject: [PATCH 1/3]: Remove kvaddr_to_nid and local_mapnr In-Reply-To: <20050929072615.GI19971@krispykreme> References: <200509281510.30531.gsbarb@br.ibm.com> <20050929072214.GH19971@krispykreme> <20050929072615.GI19971@krispykreme> Message-ID: <1128013738.5906.11.camel@localhost> On Thu, 2005-09-29 at 17:26 +1000, Anton Blanchard wrote: > local_mapnr wasnt used anywhere and kvaddr_to_nid was used in one spot. This conflicts a bit with something of mine that's in -mm right now: http://www.kernel.org/pub/linux/kernel/people/akpm/patches/2.6/2.6.14-rc2/2.6.14-rc2-mm1/broken-out/memory-hotplug-prep-kill-local_mapnr.patch But, your patch seems to be more pervasive, at least on ppc64. I'll see how this merges on top of what I have already. -- Dave From geoffrey.levand at am.sony.com Fri Sep 30 03:22:55 2005 From: geoffrey.levand at am.sony.com (Geoff Levand) Date: Thu, 29 Sep 2005 10:22:55 -0700 Subject: kgdb for ppc64 now available Message-ID: <433C22EF.8050007@am.sony.com> For those interested, kgdb now supports ppc64 SMP. On powermac only an Ethernet connection is supported currently, but generic 8250 UART PCI cards will be supported soon. Patches against 2.6.13 are available from CVS at sourceforge: cvs -d:pserver:anonymous at cvs.sourceforge.net:/cvsroot/kgdb login cvs -z3 -d:pserver:anonymous at cvs.sourceforge.net:/cvsroot/kgdb co -P kgdb-2 or if your firewall blocks this: cvs -d:pserver:anonymous at cvs.sourceforge.net:443/cvsroot/kgdb login cvs -z3 -d::pserver:anonymous at cvs-pserver.sourceforge.net:443/cvsroot/kgdb co -P kgdb-2 Press the Enter when prompted for a password. -Geoff From haveblue at us.ibm.com Fri Sep 30 03:32:53 2005 From: haveblue at us.ibm.com (Dave Hansen) Date: Thu, 29 Sep 2005 10:32:53 -0700 Subject: [PATCH 1/3]: Remove kvaddr_to_nid and local_mapnr In-Reply-To: <1128013738.5906.11.camel@localhost> References: <200509281510.30531.gsbarb@br.ibm.com> <20050929072214.GH19971@krispykreme> <20050929072615.GI19971@krispykreme> <1128013738.5906.11.camel@localhost> Message-ID: <1128015173.5906.13.camel@localhost> On Thu, 2005-09-29 at 10:08 -0700, Dave Hansen wrote: > On Thu, 2005-09-29 at 17:26 +1000, Anton Blanchard wrote: > > local_mapnr wasnt used anywhere and kvaddr_to_nid was used in one spot. > > This conflicts a bit with something of mine that's in -mm right now: > > http://www.kernel.org/pub/linux/kernel/people/akpm/patches/2.6/2.6.14-rc2/2.6.14-rc2-mm1/broken-out/memory-hotplug-prep-kill-local_mapnr.patch > > But, your patch seems to be more pervasive, at least on ppc64. I'll see > how this merges on top of what I have already. Here's a really stupid merged up version. I think it's equivalent. -- Dave -------------- next part -------------- A non-text attachment was scrubbed... Name: PATCH_1-3-_Remove_kvaddr_to_nid_and_local_mapnr-.patch Type: text/x-patch Size: 7912 bytes Desc: not available Url : http://ozlabs.org/pipermail/linuxppc64-dev/attachments/20050929/79cf42e0/attachment.bin From geoffrey.levand at am.sony.com Fri Sep 30 04:24:12 2005 From: geoffrey.levand at am.sony.com (Geoff Levand) Date: Thu, 29 Sep 2005 11:24:12 -0700 Subject: spufs: User space thread library In-Reply-To: <200509160840.31071.arnd@arndb.de> References: <200509160840.31071.arnd@arndb.de> Message-ID: <433C314C.80409@am.sony.com> Arnd Bergmann wrote: > This is the user space library for using Cell SPE, for the > 2.6.14-rc1 release. > > It is maintained by Dirk Herrendoerfer , I'm > sending this out as a companion to the spufs implementation. > I noticed some parts of the package are not very cross-build friendly. Have you thought about using an autoconf based build system? -Geoff From jdl at freescale.com Fri Sep 30 05:40:47 2005 From: jdl at freescale.com (Jon Loeliger) Date: Thu, 29 Sep 2005 14:40:47 -0500 Subject: Reminder of outstanding merge patchs In-Reply-To: <1128005401.11404.107.camel@cashmere.sps.mot.com> References: <1128005401.11404.107.camel@cashmere.sps.mot.com> Message-ID: <1128022846.14595.11.camel@cashmere.sps.mot.com> On Thu, 2005-09-29 at 09:50, Jon Loeliger wrote: > Paul, > > Just wanted to toss a reminder out here for you > regarding two merge patches that might be crack-slippers: > > 09/19 powerpc Revised merge asm-ppc*/hardirq.h > 09/20 powerpc Merge asm-ppc*/vga.h Hmmm. It has been suggested that these _have_ been merged and I'm the one slipping through the cracks here... jdl From arnd at arndb.de Fri Sep 30 08:14:21 2005 From: arnd at arndb.de (Arnd Bergmann) Date: Fri, 30 Sep 2005 00:14:21 +0200 Subject: spufs: User space thread library In-Reply-To: <433C314C.80409@am.sony.com> References: <200509160840.31071.arnd@arndb.de> <433C314C.80409@am.sony.com> Message-ID: <200509300014.21756.arnd@arndb.de> On Dunnersdag 29 September 2005 20:24, Geoff Levand wrote: > I noticed some parts of the package are not very cross-build > friendly. ?Have you thought about using an autoconf based > build system? > I think we now have some very rudimentary cross build support in our internal version, basically just setting CROSS and DESTDIR to some predefined values when not building on a ppc64 system. A patch to add a configure.ac is certainly welcome ;-) Arnd <>< From benh at kernel.crashing.org Fri Sep 30 08:21:54 2005 From: benh at kernel.crashing.org (Benjamin Herrenschmidt) Date: Fri, 30 Sep 2005 08:21:54 +1000 Subject: kgdb for ppc64 now available In-Reply-To: <433C22EF.8050007@am.sony.com> References: <433C22EF.8050007@am.sony.com> Message-ID: <1128032514.6102.74.camel@gaston> On Thu, 2005-09-29 at 10:22 -0700, Geoff Levand wrote: > For those interested, kgdb now supports ppc64 SMP. On powermac > only an Ethernet connection is supported currently, but generic > 8250 UART PCI cards will be supported soon. It should be fairly trivial to support the SCC of the powermacs. You can access it with a serial port adapter from www.geethree.com, it's handy as it also works with OF. > Patches against 2.6.13 are available from CVS at sourceforge: > > cvs -d:pserver:anonymous at cvs.sourceforge.net:/cvsroot/kgdb login > cvs -z3 -d:pserver:anonymous at cvs.sourceforge.net:/cvsroot/kgdb co -P kgdb-2 > > or if your firewall blocks this: > > cvs -d:pserver:anonymous at cvs.sourceforge.net:443/cvsroot/kgdb login > cvs -z3 -d::pserver:anonymous at cvs-pserver.sourceforge.net:443/cvsroot/kgdb co -P kgdb-2 > > Press the Enter when prompted for a password. > > -Geoff > > _______________________________________________ > Linuxppc64-dev mailing list > Linuxppc64-dev at ozlabs.org > https://ozlabs.org/mailman/listinfo/linuxppc64-dev From geoffrey.levand at am.sony.com Fri Sep 30 09:28:02 2005 From: geoffrey.levand at am.sony.com (Geoff Levand) Date: Thu, 29 Sep 2005 16:28:02 -0700 Subject: iMac G5: experimental thermal & cpufreq support In-Reply-To: <1127978432.6102.53.camel@gaston> References: <1127978432.6102.53.camel@gaston> Message-ID: <433C7882.20000@am.sony.com> Benjamin Herrenschmidt wrote: > The algorithm itself is extracted from darwin. However, it's a rather > complex modified version of the PID algorithm, and thus it could use > some review to make sure I got everything right. > As we are already in the digital domain, I would think it would be more savvy to use a digital controller than try to simulate an analog controller... Why don't you abstract the control algorithm such that you can plug in others as they are developed. -Geoff From benh at kernel.crashing.org Fri Sep 30 10:26:59 2005 From: benh at kernel.crashing.org (Benjamin Herrenschmidt) Date: Fri, 30 Sep 2005 10:26:59 +1000 Subject: iMac G5: experimental thermal & cpufreq support In-Reply-To: <433C7882.20000@am.sony.com> References: <1127978432.6102.53.camel@gaston> <433C7882.20000@am.sony.com> Message-ID: <1128040019.31197.3.camel@gaston> On Thu, 2005-09-29 at 16:28 -0700, Geoff Levand wrote: > Benjamin Herrenschmidt wrote: > > The algorithm itself is extracted from darwin. However, it's a rather > > complex modified version of the PID algorithm, and thus it could use > > some review to make sure I got everything right. > > > > As we are already in the digital domain, I would think it would be > more savvy to use a digital controller than try to simulate an > analog controller... Why don't you abstract the control algorithm > such that you can plug in others as they are developed. Because I don't know much about those control algorithms, and all the calibration data provided by the firmware is in the form of factors for these algorithms, I wouldn't know how to "unmangle" them to use with different ones. Actually, the control algorithms (PID and modified PID) are in a "helper", so it's fairly easy for the platform module to use whatever it wants, feel free to submit other algorithms :) But for Apple machines, I'd rather use what I have calibration data for, unless you can produce something that works without any... Ben. From linas at austin.ibm.com Fri Sep 30 10:48:00 2005 From: linas at austin.ibm.com (linas) Date: Thu, 29 Sep 2005 19:48:00 -0500 Subject: [PATCH 0/7] ppc64: Assorted minor EEH cleanups Message-ID: <20050930004800.GL29826@austin.ibm.com> The following seven patches perform a variety of cleanups and restructurings of the EEH code, in preparation for the addition of code that will recover from EEH events. The frst few patches are nearly janitorial, mostly tweaking whitespace; alhough the later patches are more serious and actually fix bugs. These are all small, and should be easy to review. I beleive that these patches should not be controversial in any way, and thus should be ready to be applied. They compile but (ahem) are not tested, as I just now discovered that I cannot even boot 2.6.14-rc2-git6 in any shape or form; it panics complaining of "junk in gzipped archive". Of course, I am of the firmest conviction that my patches are spotless, and need no testing, anyway. So there. :) Signed-off-by: Linas Vepstas --linas From linas at austin.ibm.com Fri Sep 30 10:51:41 2005 From: linas at austin.ibm.com (linas) Date: Thu, 29 Sep 2005 19:51:41 -0500 Subject: [PATCH 1/7] ppc64: EEH typos, include files, macros, whitespace In-Reply-To: <20050930004800.GL29826@austin.ibm.com> References: <20050930004800.GL29826@austin.ibm.com> Message-ID: <20050930005141.GA6173@austin.ibm.com> 01-eeh-minor-cleanup.patch This patch performs some minor cleanup of the eeh.c file, including: -- trim some trailing whitespace -- remove extraneous #includes -- use the macro PCI_DN uniformly, instead of the void pointer chase. -- typos in comments -- improved debug printk's Signed-off-by: Linas Vepstas Index: linux-2.6.14-rc2-git6/arch/ppc64/kernel/eeh.c =================================================================== --- linux-2.6.14-rc2-git6.orig/arch/ppc64/kernel/eeh.c 2005-09-29 11:03:52.084426836 -0500 +++ linux-2.6.14-rc2-git6/arch/ppc64/kernel/eeh.c 2005-09-29 13:09:10.306972480 -0500 @@ -1,32 +1,31 @@ /* * eeh.c * Copyright (C) 2001 Dave Engebretsen & Todd Inglett 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 */ -#include #include #include -#include #include #include #include #include #include #include +#include #include #include #include @@ -49,8 +48,8 @@ * were "empty": all reads return 0xff's and all writes are silently * ignored. EEH slot isolation events can be triggered by parity * errors on the address or data busses (e.g. during posted writes), - * which in turn might be caused by dust, vibration, humidity, - * radioactivity or plain-old failed hardware. + * which in turn might be caused by low voltage on the bus, dust, + * vibration, humidity, radioactivity or plain-old failed hardware. * * Note, however, that one of the leading causes of EEH slot * freeze events are buggy device drivers, buggy device microcode, @@ -256,18 +255,17 @@ dn = pci_device_to_OF_node(dev); if (!dn) { - printk(KERN_WARNING "PCI: no pci dn found for dev=%s\n", - pci_name(dev)); + printk(KERN_WARNING "PCI: no pci dn found for dev=%s\n", pci_name(dev)); return; } /* Skip any devices for which EEH is not enabled. */ - pdn = dn->data; + pdn = PCI_DN(dn); 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\n", - pci_name(dev)); + printk(KERN_INFO "PCI: skip building address cache for=%s - %s\n", + pci_name(dev), pdn->node->full_name); #endif return; } @@ -410,16 +408,16 @@ * @dn: device node to read * @rets: array to return results in */ -static int read_slot_reset_state(struct device_node *dn, int rets[]) +static int read_slot_reset_state(struct pci_dn *pdn, 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; outputs = 4; } else { token = ibm_read_slot_reset_state; + rets[2] = 0; /* fake PE Unavailable info */ outputs = 3; } @@ -496,7 +494,7 @@ /** * eeh_token_to_phys - convert EEH address token to phys address - * @token i/o token, should be address in the form 0xE.... + * @token i/o token, should be address in the form 0xA.... */ static inline unsigned long eeh_token_to_phys(unsigned long token) { @@ -522,7 +520,7 @@ * will query firmware for the EEH status. * * Returns 0 if there has not been an EEH error; otherwise returns - * a non-zero value and queues up a solt isolation event notification. + * a non-zero value and queues up a slot isolation event notification. * * It is safe to call this routine in an interrupt context. */ @@ -542,7 +540,7 @@ if (!dn) return 0; - pdn = dn->data; + pdn = PCI_DN(dn); /* Access to IO BARs might get this far and still not want checking. */ if (!pdn->eeh_capable || !(pdn->eeh_mode & EEH_MODE_SUPPORTED) || @@ -562,7 +560,7 @@ atomic_inc(&eeh_fail_count); if (atomic_read(&eeh_fail_count) >= EEH_MAX_FAILS) { /* re-read the slot reset state */ - if (read_slot_reset_state(dn, rets) != 0) + if (read_slot_reset_state(pdn, rets) != 0) rets[0] = -1; /* reset state unknown */ eeh_panic(dev, rets[0]); } @@ -576,7 +574,7 @@ * function zero of a multi-function device. * In any case they must share a common PHB. */ - ret = read_slot_reset_state(dn, rets); + ret = read_slot_reset_state(pdn, rets); if (!(ret == 0 && rets[1] == 1 && (rets[0] == 2 || rets[0] == 4))) { __get_cpu_var(false_positives)++; return 0; @@ -635,7 +633,6 @@ * @token i/o token, should be address in the form 0xA.... * @val value, should be all 1's (XXX why do we need this arg??) * - * Check for an eeh failure at the given token address. * Check for an EEH failure at the given token address. Call this * routine if the result of a read was all 0xff's and you want to * find out if this is due to an EEH slot freeze event. This routine @@ -680,7 +677,7 @@ u32 *device_id = (u32 *)get_property(dn, "device-id", NULL); u32 *regs; int enable; - struct pci_dn *pdn = dn->data; + struct pci_dn *pdn = PCI_DN(dn); pdn->eeh_mode = 0; @@ -732,7 +729,7 @@ /* 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->data + if (dn->parent && PCI_DN(dn->parent) && (PCI_DN(dn->parent)->eeh_mode & EEH_MODE_SUPPORTED)) { /* Parent supports EEH. */ pdn->eeh_mode |= EEH_MODE_SUPPORTED; @@ -745,7 +742,7 @@ dn->full_name); } - return NULL; + return NULL; } /* @@ -793,13 +790,11 @@ 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 || phb->data == NULL) + if (buid == 0 || PCI_DN(phb) == 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); @@ -828,11 +823,13 @@ struct pci_controller *phb; struct eeh_early_enable_info info; - if (!dn || !dn->data) + if (!dn || !PCI_DN(dn)) return; phb = PCI_DN(dn)->phb; if (NULL == phb || 0 == phb->buid) { - printk(KERN_WARNING "EEH: Expected buid but found none\n"); + printk(KERN_WARNING "EEH: Expected buid but found none for %s\n", + dn->full_name); + dump_stack(); return; } From linas at austin.ibm.com Fri Sep 30 10:53:14 2005 From: linas at austin.ibm.com (linas) Date: Thu, 29 Sep 2005 19:53:14 -0500 Subject: [PATCH 2/7] ppc64: EEH PCI address cache cleanups In-Reply-To: <20050930004800.GL29826@austin.ibm.com> References: <20050930004800.GL29826@austin.ibm.com> Message-ID: <20050930005313.GB6173@austin.ibm.com> 02-eeh-addr-cache-cleanup.patch This is a minor patch to clean up a buglet related to the PCI address cache. (The buglet doesn't manifes itself unless there are also bugs elsewhere, which is why its minor.). Also: -- Improved debug printing. -- Declare some private routines as static -- Adds reference counting to struct pci_dn->pcidev structure Signed-off-by: Linas Vepstas Index: linux-2.6.14-rc2-git6/arch/ppc64/kernel/eeh.c =================================================================== --- linux-2.6.14-rc2-git6.orig/arch/ppc64/kernel/eeh.c 2005-09-29 13:09:10.306972480 -0500 +++ linux-2.6.14-rc2-git6/arch/ppc64/kernel/eeh.c 2005-09-29 13:41:44.868689967 -0500 @@ -219,9 +219,9 @@ while (*p) { parent = *p; piar = rb_entry(parent, struct pci_io_addr_range, rb_node); - if (alo < piar->addr_lo) { + if (ahi < piar->addr_lo) { p = &parent->rb_left; - } else if (ahi > piar->addr_hi) { + } else if (alo > piar->addr_hi) { p = &parent->rb_right; } else { if (dev != piar->pcidev || @@ -240,6 +240,11 @@ piar->pcidev = dev; piar->flags = flags; +#ifdef DEBUG + printk(KERN_DEBUG "PIAR: insert range=[%lx:%lx] dev=%s\n", + alo, ahi, pci_name (dev)); +#endif + rb_link_node(&piar->rb_node, parent, p); rb_insert_color(&piar->rb_node, &pci_io_addr_cache_root.rb_root); @@ -301,7 +306,7 @@ * we maintain a cache of devices that can be quickly searched. * This routine adds a device to that cache. */ -void pci_addr_cache_insert_device(struct pci_dev *dev) +static void pci_addr_cache_insert_device(struct pci_dev *dev) { unsigned long flags; @@ -344,7 +349,7 @@ * the tree multiple times (once per resource). * But so what; device removal doesn't need to be that fast. */ -void pci_addr_cache_remove_device(struct pci_dev *dev) +static void pci_addr_cache_remove_device(struct pci_dev *dev) { unsigned long flags; @@ -366,6 +371,9 @@ { struct pci_dev *dev = NULL; + if (!eeh_subsystem_enabled) + return; + spin_lock_init(&pci_io_addr_cache_root.piar_lock); while ((dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) { @@ -837,7 +845,7 @@ info.buid_lo = BUID_LO(phb->buid); early_enable_eeh(dn, &info); } -EXPORT_SYMBOL(eeh_add_device_early); +EXPORT_SYMBOL_GPL(eeh_add_device_early); /** * eeh_add_device_late - perform EEH initialization for the indicated pci device @@ -848,6 +856,8 @@ */ void eeh_add_device_late(struct pci_dev *dev) { + struct device_node *dn; + if (!dev || !eeh_subsystem_enabled) return; @@ -855,9 +865,13 @@ printk(KERN_DEBUG "EEH: adding device %s\n", pci_name(dev)); #endif + pci_dev_get (dev); + dn = pci_device_to_OF_node(dev); + PCI_DN(dn)->pcidev = dev; + pci_addr_cache_insert_device (dev); } -EXPORT_SYMBOL(eeh_add_device_late); +EXPORT_SYMBOL_GPL(eeh_add_device_late); /** * eeh_remove_device - undo EEH setup for the indicated pci device @@ -868,6 +882,7 @@ */ void eeh_remove_device(struct pci_dev *dev) { + struct device_node *dn; if (!dev || !eeh_subsystem_enabled) return; @@ -876,8 +891,12 @@ printk(KERN_DEBUG "EEH: remove device %s\n", pci_name(dev)); #endif pci_addr_cache_remove_device(dev); + + dn = pci_device_to_OF_node(dev); + PCI_DN(dn)->pcidev = NULL; + pci_dev_put (dev); } -EXPORT_SYMBOL(eeh_remove_device); +EXPORT_SYMBOL_GPL(eeh_remove_device); static int proc_eeh_show(struct seq_file *m, void *v) { Index: linux-2.6.14-rc2-git6/arch/ppc64/kernel/pci.h =================================================================== --- linux-2.6.14-rc2-git6.orig/arch/ppc64/kernel/pci.h 2005-09-29 13:09:10.306972480 -0500 +++ linux-2.6.14-rc2-git6/arch/ppc64/kernel/pci.h 2005-09-29 13:36:08.550882158 -0500 @@ -39,10 +39,6 @@ void pci_devs_phb_init(void); void pci_devs_phb_init_dynamic(struct pci_controller *phb); -/* PCI address cache management routines */ -void pci_addr_cache_insert_device(struct pci_dev *dev); -void pci_addr_cache_remove_device(struct pci_dev *dev); - /* From rtas_pci.h */ void init_pci_config_tokens (void); unsigned long get_phb_buid (struct device_node *); From linas at austin.ibm.com Fri Sep 30 10:54:51 2005 From: linas at austin.ibm.com (linas) Date: Thu, 29 Sep 2005 19:54:51 -0500 Subject: [PATCH 3/7] ppc64: EEH Add event/internal state statistics In-Reply-To: <20050930004800.GL29826@austin.ibm.com> References: <20050930004800.GL29826@austin.ibm.com> Message-ID: <20050930005451.GC6173@austin.ibm.com> 03-eeh-statistics.patch This minor patch adds some statistics-gathering counters that allow the behaviour of the EEH subsystem o be monitored. While far from perfect, it does provide a rudimentary device that makes understanding of the current state of the system a bit easier. Signed-off-by: Linas Vepstas Index: linux-2.6.14-rc2-git6/arch/ppc64/kernel/eeh.c =================================================================== --- linux-2.6.14-rc2-git6.orig/arch/ppc64/kernel/eeh.c 2005-09-29 13:52:08.188222887 -0500 +++ linux-2.6.14-rc2-git6/arch/ppc64/kernel/eeh.c 2005-09-29 16:05:53.025549160 -0500 @@ -102,6 +102,10 @@ static int eeh_error_buf_size; /* System monitoring statistics */ +static DEFINE_PER_CPU(unsigned long, no_device); +static DEFINE_PER_CPU(unsigned long, no_dn); +static DEFINE_PER_CPU(unsigned long, no_cfg_addr); +static DEFINE_PER_CPU(unsigned long, ignored_check); static DEFINE_PER_CPU(unsigned long, total_mmio_ffs); static DEFINE_PER_CPU(unsigned long, false_positives); static DEFINE_PER_CPU(unsigned long, ignored_failures); @@ -493,8 +497,6 @@ notifier_call_chain (&eeh_notifier_chain, EEH_NOTIFY_FREEZE, event); - __get_cpu_var(slot_resets)++; - pci_dev_put(event->dev); kfree(event); } @@ -546,17 +548,24 @@ if (!eeh_subsystem_enabled) return 0; - if (!dn) + if (!dn) { + __get_cpu_var(no_dn)++; return 0; + } pdn = PCI_DN(dn); /* Access to IO BARs might get this far and still not want checking. */ if (!pdn->eeh_capable || !(pdn->eeh_mode & EEH_MODE_SUPPORTED) || pdn->eeh_mode & EEH_MODE_NOCHECK) { + __get_cpu_var(ignored_check)++; +#ifdef DEBUG + printk ("EEH:ignored check for %s %s\n", pci_name (dev), dn->full_name); +#endif return 0; } if (!pdn->eeh_config_addr) { + __get_cpu_var(no_cfg_addr)++; return 0; } @@ -590,6 +599,7 @@ /* prevent repeated reports of this failure */ pdn->eeh_mode |= EEH_MODE_ISOLATED; + __get_cpu_var(slot_resets)++; reset_state = rets[0]; @@ -657,8 +667,10 @@ /* Finding the phys addr + pci device; this is pretty quick. */ addr = eeh_token_to_phys((unsigned long __force) token); dev = pci_get_device_by_addr(addr); - if (!dev) + if (!dev) { + __get_cpu_var(no_device)++; return val; + } dn = pci_device_to_OF_node(dev); eeh_dn_check_failure (dn, dev); @@ -903,12 +915,17 @@ unsigned int cpu; unsigned long ffs = 0, positives = 0, failures = 0; unsigned long resets = 0; + unsigned long no_dev = 0, no_dn = 0, no_cfg = 0, no_check = 0; for_each_cpu(cpu) { ffs += per_cpu(total_mmio_ffs, cpu); positives += per_cpu(false_positives, cpu); failures += per_cpu(ignored_failures, cpu); resets += per_cpu(slot_resets, cpu); + no_dev += per_cpu(no_device, cpu); + no_dn += per_cpu(no_dn, cpu); + no_cfg += per_cpu(no_cfg_addr, cpu); + no_check += per_cpu(ignored_check, cpu); } if (0 == eeh_subsystem_enabled) { @@ -916,13 +933,17 @@ seq_printf(m, "eeh_total_mmio_ffs=%ld\n", ffs); } else { seq_printf(m, "EEH Subsystem is enabled\n"); - seq_printf(m, "eeh_total_mmio_ffs=%ld\n" - "eeh_false_positives=%ld\n" - "eeh_ignored_failures=%ld\n" - "eeh_slot_resets=%ld\n" - "eeh_fail_count=%d\n", - ffs, positives, failures, resets, - eeh_fail_count.counter); + seq_printf(m, + "no device=%ld\n" + "no device node=%ld\n" + "no config address=%ld\n" + "check not wanted=%ld\n" + "eeh_total_mmio_ffs=%ld\n" + "eeh_false_positives=%ld\n" + "eeh_ignored_failures=%ld\n" + "eeh_slot_resets=%ld\n", + no_dev, no_dn, no_cfg, no_check, + ffs, positives, failures, resets); } return 0; From linas at austin.ibm.com Fri Sep 30 10:56:50 2005 From: linas at austin.ibm.com (linas) Date: Thu, 29 Sep 2005 19:56:50 -0500 Subject: [PATCH 4/7] ppc64: EEH PCI slot error details abstraction In-Reply-To: <20050930004800.GL29826@austin.ibm.com> References: <20050930004800.GL29826@austin.ibm.com> Message-ID: <20050930005650.GD6173@austin.ibm.com> 04-eeh-slot-error-detail.patch This patch encapsulates a section of code that reports the EEH event. The new subroutine can be used in several places to report the eror. Signed-off-by: Linas Vepstas Index: linux-2.6.14-rc2-git6/arch/ppc64/kernel/eeh.c =================================================================== --- linux-2.6.14-rc2-git6.orig/arch/ppc64/kernel/eeh.c 2005-09-29 16:05:53.025549160 -0500 +++ linux-2.6.14-rc2-git6/arch/ppc64/kernel/eeh.c 2005-09-29 16:06:25.583986100 -0500 @@ -397,6 +397,28 @@ /* --------------------------------------------------------------- */ /* Above lies the PCI Address Cache. Below lies the EEH event infrastructure */ +void eeh_slot_error_detail (struct pci_dn *pdn, int severity) +{ + unsigned long flags; + int rc; + + /* Log the error with the rtas logger */ + spin_lock_irqsave(&slot_errbuf_lock, flags); + memset(slot_errbuf, 0, eeh_error_buf_size); + + rc = rtas_call(ibm_slot_error_detail, + 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, + severity); + + if (rc == 0) + log_error(slot_errbuf, ERR_TYPE_RTAS_LOG, 0); + spin_unlock_irqrestore(&slot_errbuf_lock, flags); +} + /** * eeh_register_notifier - Register to find out about EEH events. * @nb: notifier block to callback on events @@ -454,9 +476,12 @@ * Since the panic_on_oops sysctl is used to halt the system * in light of potential corruption, we can use it here. */ - if (panic_on_oops) + if (panic_on_oops) { + struct device_node *dn = pci_device_to_OF_node(dev); + eeh_slot_error_detail (PCI_DN(dn), 2 /* Permanent Error */); panic("EEH: MMIO failure (%d) on device:%s\n", reset_state, pci_name(dev)); + } else { __get_cpu_var(ignored_failures)++; printk(KERN_INFO "EEH: Ignored MMIO failure (%d) on device:%s\n", @@ -539,7 +564,7 @@ int ret; int rets[3]; unsigned long flags; - int rc, reset_state; + int reset_state; struct eeh_event *event; struct pci_dn *pdn; @@ -603,20 +628,7 @@ reset_state = rets[0]; - spin_lock_irqsave(&slot_errbuf_lock, flags); - memset(slot_errbuf, 0, eeh_error_buf_size); - - rc = rtas_call(ibm_slot_error_detail, - 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 */); - - if (rc == 0) - log_error(slot_errbuf, ERR_TYPE_RTAS_LOG, 0); - spin_unlock_irqrestore(&slot_errbuf_lock, flags); + eeh_slot_error_detail (pdn, 1 /* Temporary Error */); printk(KERN_INFO "EEH: MMIO failure (%d) on device: %s %s\n", rets[0], dn->name, dn->full_name); @@ -783,6 +795,8 @@ struct device_node *phb, *np; struct eeh_early_enable_info info; + spin_lock_init(&slot_errbuf_lock); + np = of_find_node_by_path("/rtas"); if (np == NULL) return; From linas at austin.ibm.com Fri Sep 30 10:58:27 2005 From: linas at austin.ibm.com (linas) Date: Thu, 29 Sep 2005 19:58:27 -0500 Subject: [PATCH 5/7] ppc64: EEH handle empty PCI slot failure In-Reply-To: <20050930004800.GL29826@austin.ibm.com> References: <20050930004800.GL29826@austin.ibm.com> Message-ID: <20050930005827.GE6173@austin.ibm.com> 05-eeh-empty-slot-error.patch Performing PCI config-space reads to empty PCI slots can lead to reports of "permanent failure" from the firmware. Ignore permanent failures on empty slots. Signed-off-by: Linas Vepstas Index: linux-2.6.14-rc2-git6/arch/ppc64/kernel/eeh.c =================================================================== --- linux-2.6.14-rc2-git6.orig/arch/ppc64/kernel/eeh.c 2005-09-29 16:06:25.583986100 -0500 +++ linux-2.6.14-rc2-git6/arch/ppc64/kernel/eeh.c 2005-09-29 16:06:33.567867154 -0500 @@ -617,7 +617,32 @@ * In any case they must share a common PHB. */ ret = read_slot_reset_state(pdn, rets); - if (!(ret == 0 && rets[1] == 1 && (rets[0] == 2 || rets[0] == 4))) { + + /* If the call to firmware failed, punt */ + if (ret != 0) { + printk(KERN_WARNING "EEH: read_slot_reset_state() failed; rc=%d dn=%s\n", + ret, dn->full_name); + __get_cpu_var(false_positives)++; + return 0; + } + + /* If EEH is not supported on this device, punt. */ + if (rets[1] != 1) { + printk(KERN_WARNING "EEH: event on unsupported device, rc=%d dn=%s\n", + ret, dn->full_name); + __get_cpu_var(false_positives)++; + return 0; + } + + /* If not the kind of error we know about, punt. */ + if (rets[0] != 2 && rets[0] != 4 && rets[0] != 5) { + __get_cpu_var(false_positives)++; + return 0; + } + + /* Note that config-io to empty slots may fail; + * we recognize empty because they don't have children. */ + if ((rets[0] == 5) && (dn->child == NULL)) { __get_cpu_var(false_positives)++; return 0; } @@ -650,7 +675,7 @@ /* Most EEH events are due to device driver bugs. Having * a stack trace will help the device-driver authors figure * out what happened. So print that out. */ - dump_stack(); + if (rets[0] != 5) dump_stack(); schedule_work(&eeh_event_wq); return 0; From linas at austin.ibm.com Fri Sep 30 11:00:38 2005 From: linas at austin.ibm.com (linas) Date: Thu, 29 Sep 2005 20:00:38 -0500 Subject: [PATCH 6/7] ppc64: EEH Avoid racing reports of errors In-Reply-To: <20050930004800.GL29826@austin.ibm.com> References: <20050930004800.GL29826@austin.ibm.com> Message-ID: <20050930010038.GF6173@austin.ibm.com> 06-eeh-report-race.patch When a PCI slot is isolated, all PCI functions under that slot are affected. If hese functions have separate device drivers, the EEH isolation event might be reported multiple times. This patch adds a lock to prevent the racing of such multiple reports. It also marks every device under the slot as having experienced an EEH event, so that multiple reports may be recognized more easily. Signed-off-by: Linas Vepstas Index: linux-2.6.14-rc2-git6/arch/ppc64/kernel/eeh.c =================================================================== --- linux-2.6.14-rc2-git6.orig/arch/ppc64/kernel/eeh.c 2005-09-29 16:06:33.567867154 -0500 +++ linux-2.6.14-rc2-git6/arch/ppc64/kernel/eeh.c 2005-09-29 16:06:39.106090510 -0500 @@ -96,6 +96,9 @@ static int eeh_subsystem_enabled; +/* Lock to avoid races due to multiple reports of an error */ +static DEFINE_SPINLOCK(confirm_error_lock); + /* Buffer for reporting slot-error-detail rtas calls */ static unsigned char slot_errbuf[RTAS_ERROR_LOG_MAX]; static DEFINE_SPINLOCK(slot_errbuf_lock); @@ -544,6 +547,55 @@ return pa | (token & (PAGE_SIZE-1)); } +/** + * Return the "partitionable endpoint" (pe) under which this device lies + */ +static struct device_node * find_device_pe(struct device_node *dn) +{ + while ((dn->parent) && PCI_DN(dn->parent) && + (PCI_DN(dn->parent)->eeh_mode & EEH_MODE_SUPPORTED)) { + dn = dn->parent; + } + return dn; +} + +/** Mark all devices that are peers of this device as failed. + * Mark the device driver too, so that it can see the failure + * immediately; this is critical, since some drivers poll + * status registers in interrupts ... If a driver is polling, + * and the slot is frozen, then the driver can deadlock in + * an interrupt context, which is bad. + */ + +static inline void __eeh_mark_slot (struct device_node *dn) +{ + while (dn) { + PCI_DN(dn)->eeh_mode |= EEH_MODE_ISOLATED; + + if (dn->child) + __eeh_mark_slot (dn->child); + dn = dn->sibling; + } +} + +static inline void __eeh_clear_slot (struct device_node *dn) +{ + while (dn) { + PCI_DN(dn)->eeh_mode &= ~EEH_MODE_ISOLATED; + if (dn->child) + __eeh_clear_slot (dn->child); + dn = dn->sibling; + } +} + +static inline void eeh_clear_slot (struct device_node *dn) +{ + unsigned long flags; + spin_lock_irqsave(&confirm_error_lock, flags); + __eeh_clear_slot (dn); + spin_unlock_irqrestore(&confirm_error_lock, flags); +} + /** * eeh_dn_check_failure - check if all 1's data is due to EEH slot freeze * @dn device node @@ -567,6 +619,8 @@ int reset_state; struct eeh_event *event; struct pci_dn *pdn; + struct device_node *pe_dn; + int rc = 0; __get_cpu_var(total_mmio_ffs)++; @@ -594,10 +648,14 @@ return 0; } - /* - * If we already have a pending isolation event for this - * slot, we know it's bad already, we don't need to check... + /* If we already have a pending isolation event for this + * slot, we know it's bad already, we don't need to check. + * Do this checking under a lock; as multiple PCI devices + * in one slot might report errors simultaneously, and we + * only want one error recovery routine running. */ + spin_lock_irqsave(&confirm_error_lock, flags); + rc = 1; if (pdn->eeh_mode & EEH_MODE_ISOLATED) { atomic_inc(&eeh_fail_count); if (atomic_read(&eeh_fail_count) >= EEH_MAX_FAILS) { @@ -606,7 +664,7 @@ rets[0] = -1; /* reset state unknown */ eeh_panic(dev, rets[0]); } - return 0; + goto dn_unlock; } /* @@ -623,7 +681,8 @@ printk(KERN_WARNING "EEH: read_slot_reset_state() failed; rc=%d dn=%s\n", ret, dn->full_name); __get_cpu_var(false_positives)++; - return 0; + rc = 0; + goto dn_unlock; } /* If EEH is not supported on this device, punt. */ @@ -631,25 +690,33 @@ printk(KERN_WARNING "EEH: event on unsupported device, rc=%d dn=%s\n", ret, dn->full_name); __get_cpu_var(false_positives)++; - return 0; + rc = 0; + goto dn_unlock; } /* If not the kind of error we know about, punt. */ if (rets[0] != 2 && rets[0] != 4 && rets[0] != 5) { __get_cpu_var(false_positives)++; - return 0; + rc = 0; + goto dn_unlock; } /* Note that config-io to empty slots may fail; * we recognize empty because they don't have children. */ if ((rets[0] == 5) && (dn->child == NULL)) { __get_cpu_var(false_positives)++; - return 0; + rc = 0; + goto dn_unlock; } - /* prevent repeated reports of this failure */ - pdn->eeh_mode |= EEH_MODE_ISOLATED; - __get_cpu_var(slot_resets)++; + __get_cpu_var(slot_resets)++; + + /* Avoid repeated reports of this failure, including problems + * with other functions on this device, and functions under + * bridges. */ + pe_dn = find_device_pe (dn); + __eeh_mark_slot (pe_dn); + spin_unlock_irqrestore(&confirm_error_lock, flags); reset_state = rets[0]; @@ -678,10 +745,14 @@ if (rets[0] != 5) dump_stack(); schedule_work(&eeh_event_wq); - return 0; + return 1; + +dn_unlock: + spin_unlock_irqrestore(&confirm_error_lock, flags); + return rc; } -EXPORT_SYMBOL(eeh_dn_check_failure); +EXPORT_SYMBOL_GPL(eeh_dn_check_failure); /** * eeh_check_failure - check if all 1's data is due to EEH slot freeze @@ -820,6 +891,7 @@ struct device_node *phb, *np; struct eeh_early_enable_info info; + spin_lock_init(&confirm_error_lock); spin_lock_init(&slot_errbuf_lock); np = of_find_node_by_path("/rtas"); From linas at austin.ibm.com Fri Sep 30 11:02:28 2005 From: linas at austin.ibm.com (linas) Date: Thu, 29 Sep 2005 20:02:28 -0500 Subject: [PATCH 7/7] ppc64: EEH Halt if bad drivers spin in error condition In-Reply-To: <20050930004800.GL29826@austin.ibm.com> References: <20050930004800.GL29826@austin.ibm.com> Message-ID: <20050930010228.GG6173@austin.ibm.com> 07-eeh-spin-counter.patch One an EEH event is triggers, all further I/O to a device is blocked (until reset). Bad device drivers may end up spinning in their interrupt handlers, trying to read an interrupt status register that will never change state. This patch moves that spin counter to a per-device structure, and adds some diagnostic prints to help locate the bad driver. Signed-off-by: Linas Vepstas Index: linux-2.6.14-rc2-git6/arch/ppc64/kernel/eeh.c =================================================================== --- linux-2.6.14-rc2-git6.orig/arch/ppc64/kernel/eeh.c 2005-09-29 16:29:00.726884805 -0500 +++ linux-2.6.14-rc2-git6/arch/ppc64/kernel/eeh.c 2005-09-29 16:32:05.550949258 -0500 @@ -78,14 +78,12 @@ static struct notifier_block *eeh_notifier_chain; -/* - * If a device driver keeps reading an MMIO register in an interrupt +/* If a device driver keeps reading an MMIO register in an interrupt * handler after a slot isolation event has occurred, we assume it * is broken and panic. This sets the threshold for how many read * attempts we allow before panicking. */ -#define EEH_MAX_FAILS 1000 -static atomic_t eeh_fail_count; +#define EEH_MAX_FAILS 100000 /* RTAS tokens */ static int ibm_set_eeh_option; @@ -521,7 +519,6 @@ "%s\n", event->reset_state, pci_name(event->dev)); - atomic_set(&eeh_fail_count, 0); notifier_call_chain (&eeh_notifier_chain, EEH_NOTIFY_FREEZE, event); @@ -657,12 +654,18 @@ spin_lock_irqsave(&confirm_error_lock, flags); rc = 1; if (pdn->eeh_mode & EEH_MODE_ISOLATED) { - atomic_inc(&eeh_fail_count); - if (atomic_read(&eeh_fail_count) >= EEH_MAX_FAILS) { + pdn->eeh_check_count ++; + if (pdn->eeh_check_count >= EEH_MAX_FAILS) { + printk (KERN_ERR "EEH: Device driver ignored %d bad reads, panicing\n", + pdn->eeh_check_count); + dump_stack(); + /* re-read the slot reset state */ if (read_slot_reset_state(pdn, rets) != 0) rets[0] = -1; /* reset state unknown */ - eeh_panic(dev, rets[0]); + + /* If we are here, then we hit an infinite loop. Stop. */ + panic("EEH: MMIO halt (%d) on device:%s\n", rets[0], pci_name(dev)); } goto dn_unlock; } @@ -808,6 +811,8 @@ struct pci_dn *pdn = PCI_DN(dn); pdn->eeh_mode = 0; + pdn->eeh_check_count = 0; + pdn->eeh_freeze_count = 0; if (status && strcmp(status, "ok") != 0) return NULL; /* ignore devices with bad status */ From dean at bong.com.au Fri Sep 30 11:00:43 2005 From: dean at bong.com.au (Dean Hamstead) Date: Fri, 30 Sep 2005 11:00:43 +1000 (EST) Subject: iMac G5: experimental thermal & cpufreq support In-Reply-To: <1128040019.31197.3.camel@gaston> References: <1127978432.6102.53.camel@gaston> <433C7882.20000@am.sony.com> <1128040019.31197.3.camel@gaston> Message-ID: <2805.203.91.245.98.1128042043.squirrel@webmail.bong.com.au> Although i dont have an imac g5, i think that in general ben is on the right track. its better to have something in place than nothing. not putting down the feedback, but im not sure just how much fiddling people will really want, and its not a huge audience. which brings me back to the point of just getting something in place and then people can change it as IMO linux kernel code is more likely to be fiddled with (and better 'documentation' - whatever that is) than darwin code. go ben, keep working hard. and keep chasing the mpeg decoder in the ati cards of apple ibook and friends! Dean On Fri, September 30, 2005 10:26 am, Benjamin Herrenschmidt said: > On Thu, 2005-09-29 at 16:28 -0700, Geoff Levand wrote: >> Benjamin Herrenschmidt wrote: >> > The algorithm itself is extracted from darwin. However, it's a rather >> > complex modified version of the PID algorithm, and thus it could use >> > some review to make sure I got everything right. >> > >> >> As we are already in the digital domain, I would think it would be >> more savvy to use a digital controller than try to simulate an >> analog controller... Why don't you abstract the control algorithm >> such that you can plug in others as they are developed. > > Because I don't know much about those control algorithms, and all the > calibration data provided by the firmware is in the form of factors for > these algorithms, I wouldn't know how to "unmangle" them to use with > different ones. > > Actually, the control algorithms (PID and modified PID) are in a > "helper", so it's fairly easy for the platform module to use whatever it > wants, feel free to submit other algorithms :) But for Apple machines, > I'd rather use what I have calibration data for, unless you can produce > something that works without any... > > Ben. > > > -- > To UNSUBSCRIBE, email to debian-powerpc-REQUEST at lists.debian.org > with a subject of "unsubscribe". Trouble? Contact > listmaster at lists.debian.org > > From viro at ftp.linux.org.uk Fri Sep 30 12:36:50 2005 From: viro at ftp.linux.org.uk (Al Viro) Date: Fri, 30 Sep 2005 03:36:50 +0100 Subject: [PATCH] bogus BUILD_BUG_ON() in bpa_iommu Message-ID: <20050930023650.GC7992@ftp.linux.org.uk> BUILD_BUG_ON(1) is asking for trouble (and getting it) when used in that manner - dead code elimination happens after we parse it and invalid type is invalid type, dead code or not. It might be version-dependent, but at least 4.0.1 refuses to accept that. Signed-off-by: Al Viro ---- diff -urN RC14-rc2-git6-base/arch/ppc64/kernel/bpa_iommu.c current/arch/ppc64/kernel/bpa_iommu.c --- RC14-rc2-git6-base/arch/ppc64/kernel/bpa_iommu.c 2005-09-26 00:02:29.000000000 -0400 +++ current/arch/ppc64/kernel/bpa_iommu.c 2005-09-15 14:22:33.000000000 -0400 @@ -99,7 +99,11 @@ break; default: /* not a known compile time constant */ - BUILD_BUG_ON(1); + { + /* BUILD_BUG_ON() is not usable here */ + extern void __get_iost_entry_bad_page_size(void); + __get_iost_entry_bad_page_size(); + } break; } From dwm at maxeymade.com Fri Sep 30 14:49:09 2005 From: dwm at maxeymade.com (Doug Maxey) Date: Thu, 29 Sep 2005 23:49:09 -0500 Subject: [PATCH 7/7] ppc64: EEH Halt if bad drivers spin in error condition In-Reply-To: <20050930010228.GG6173@austin.ibm.com> Message-ID: <200509300449.j8U4n94d014765@falcon30.maxeymade.com> On Thu, 29 Sep 2005 20:02:28 CDT, linas wrote: > >07-eeh-spin-counter.patch > >One an EEH event is triggers, all further I/O to a device is blocked (until >reset). Bad device drivers may end up spinning in their interrupt handlers, >trying to read an interrupt status register that will never change state. >This patch moves that spin counter to a per-device structure, and adds >some diagnostic prints to help locate the bad driver. > Which struct gets the element? ++doug From lishun at cn.ibm.com Fri Sep 30 16:13:13 2005 From: lishun at cn.ibm.com (Shun Li) Date: Fri, 30 Sep 2005 14:13:13 +0800 Subject: Shun Li is out of the office. Message-ID: I will be out of the office starting 2005-09-30 and will not return until 2005-10-09. I am out off office from 9/30-10/09 for vacation and Chinese National Day. Will have no mail process from 10/1-10/04, pls contact me through +86-13522042228 for urgent case. -------------- next part -------------- An HTML attachment was scrubbed... URL: http://ozlabs.org/pipermail/linuxppc64-dev/attachments/20050930/6d7f0c6a/attachment.htm From benh at kernel.crashing.org Fri Sep 30 17:12:12 2005 From: benh at kernel.crashing.org (Benjamin Herrenschmidt) Date: Fri, 30 Sep 2005 17:12:12 +1000 Subject: iMac G5: experimental thermal & cpufreq support In-Reply-To: <1127983229.6102.60.camel@gaston> References: <1127978432.6102.53.camel@gaston> <1127983229.6102.60.camel@gaston> Message-ID: <1128064333.31197.18.camel@gaston> On Thu, 2005-09-29 at 18:40 +1000, Benjamin Herrenschmidt wrote: > On Thu, 2005-09-29 at 17:20 +1000, Benjamin Herrenschmidt wrote: > > > http://gate.crashing.org/~benh/ppc64-smu-thermal-control.diff > > You may want to re-download this one if you got it already, I just fixed > a bug in the calculations of the CPU control loop. It's now getting > results much more consistant with OS X. I still have to add some > overtemp handling and I'll remove the debug stuff and work on supporting > the PowerMac9,1 desktop model. Ok, I've updated it. News are: - It now requires cpufreq support (it won't start if the cpufreq clamp sensor isn't loaded). I also changed the Kconfig stuff a bit, you'll need to enable 2 options now - It has some totally untested support for PowerMac9,1 - It has overtemp support (will slow CPU down and blow fans full speed if the machine goes overtemp) - It has some basic sysfs interface to read values in /sys/devices/platform/windfarm.0 - DEBUG is disabled by default Enjoy ! Ben. From msdemlei at cl.uni-heidelberg.de Fri Sep 30 20:22:59 2005 From: msdemlei at cl.uni-heidelberg.de (Markus Demleitner) Date: Fri, 30 Sep 2005 12:22:59 +0200 Subject: iMac G5: experimental thermal & cpufreq support In-Reply-To: <20050929075150.37C99683BA@ozlabs.org> References: <20050929075150.37C99683BA@ozlabs.org> Message-ID: <20050930102259.GA20038@victor.rh.local> On Thu, Sep 29, 2005 at 05:51:50PM +1000, linuxppc64-dev-request at ozlabs.org wrote: > I now have some experimental thermal control and cpufreq support for > iMac G5. I have not _yet_ implemented support for the SMU based single > CPU desktops (PowerMac9,1), those will have to wait a little bit more > (not too much hopefully, but I need potential testers to contact me as I > lack hardware access). At this point, it should work on PowerMac8,1 > (iMacG5 rev A) and PowerMac8,2 (iMacG5 rev B). First data on cpufreq support: Power consumption on idle for a 1600 MHz iMac G5 is down to about 50 Watts with the powersave governor from about 74 Watts without voltage control (ok, display off in both instances). Thanks, Ben. U Heidelberg owes you for saving it quite a bit of electricity. For some reason the conservative and ondemand governors don't work as I'd expect them to from my x86 experience. I hope I'll be able to look into the matter next week. Thermal control has various little problems for me (like windfarm_lm75_sensor: Unknown parameter `windfarm_pid') that I don't have time to figure out right now, either (another todo for next week). At least my little hack (http://tucana.cl.uni-heidelberg.de/imacg5/) still works with the new patches. Nitpick: I had to enable SMP in .config to get the cpufreq support built (otherwise boot_cpuid, get_hard_smp_processor_id and friends are undefined). That doesn't feel quite right. Thanks all, Markus From benh at kernel.crashing.org Fri Sep 30 22:07:06 2005 From: benh at kernel.crashing.org (Benjamin Herrenschmidt) Date: Fri, 30 Sep 2005 22:07:06 +1000 Subject: iMac G5: experimental thermal & cpufreq support In-Reply-To: <20050930102259.GA20038@victor.rh.local> References: <20050929075150.37C99683BA@ozlabs.org> <20050930102259.GA20038@victor.rh.local> Message-ID: <1128082026.31197.40.camel@gaston> > First data on cpufreq support: Power consumption on idle for a 1600 > MHz iMac G5 is down to about 50 Watts with the powersave governor > from about 74 Watts without voltage control (ok, display off in both > instances). Thanks, Ben. U Heidelberg owes you for saving it quite > a bit of electricity. How did you measure it btw ? The CPU itself appears to eat about 4 watts when idle on half speed and about 10 watts when idle on full speed. It appears to max out at about 11W on half speed on load and about 30W on load at full speed ,though I suppose it would be possible to write specific code that eats more power (using altivec for example). > For some reason the conservative and ondemand governors don't work as > I'd expect them to from my x86 experience. I hope I'll be able to > look into the matter next week. I just fixed more bugs in there, get the latest thermal control patch, it also fixes issue with the cpufreq. Not sure it will fix your problems though. > Thermal control has various little problems for me (like > windfarm_lm75_sensor: Unknown parameter `windfarm_pid') that I don't > have time to figure out right now, either (another todo for next > week). Ugh ? the lm75 sensor has nothing to do with the PID code ... What is the exact error you get ? (compile time ? runtime ?) > At least my little hack > (http://tucana.cl.uni-heidelberg.de/imacg5/) still works with the new > patches. > > Nitpick: I had to enable SMP in .config to get the cpufreq support > built (otherwise boot_cpuid, get_hard_smp_processor_id and friends > are undefined). That doesn't feel quite right. Hrm... Ok, I must admit that a !SMP g5 kernel is something I haven't tried for a long time :) I'll have a look. Thanks for testing ! Regards, Ben. From anton at samba.org Fri Sep 30 16:32:34 2005 From: anton at samba.org (Anton Blanchard) Date: Fri, 30 Sep 2005 16:32:34 +1000 Subject: kgdb for ppc64 now available In-Reply-To: <433C22EF.8050007@am.sony.com> References: <433C22EF.8050007@am.sony.com> Message-ID: <20050930063234.GA4763@krispykreme> Hi, > For those interested, kgdb now supports ppc64 SMP. On powermac only > an Ethernet connection is supported currently, but generic 8250 UART > PCI cards will be supported soon. Nice! A few comments: + { 0x0300, 0x0b /* SIGSEGV */ }, /* data access */ + { 0x0400, 0x0a /* SIGBUS */ }, /* instruction access */ 0x380 data segment miss is not in the list of traps. + return kgdb_handle_exception(0, computeSignal(regs->trap), 0, regs); We should use TRAP(regs) instead of regs->trap since the bottom bits may not be zero for an exception that only saves a partial register set. @@ -2,7 +2,7 @@ # Makefile for the linux ppc64 kernel. # -EXTRA_CFLAGS += -mno-minimal-toc +#EXTRA_CFLAGS += -mno-minimal-toc extra-y := head.o vmlinux.lds obj-y := setup.o entry.o traps.o irq.o idle.o dma.o \ Is there a problem with compiling arch/ppc64/kernel -mno-minimal-toc? I notice x86-64 is using the new die hooks, Im about to convert xmon over to it and once that is done it will make sense to move kgdb and kdb across. In regs_to_gdb_regs it would be nice to send out the dar, dsisr and perhaps softe (used on iseries and will be useful once we go to soft interrupt disable on pseries). Even though we already get the trap number delived to gdb via the signal number, it would be useful to dump it in the regs since the bottom bits are important (to work out if only a partial register set has been saved). That leaves orig_gpr3 and result as the only pt_regs not dumped. + /* vr registers not used by kernel, leave zero */ + ptr += 64; Now that we use altivec in the kernel a bit, it might make sense to dump these registers. Not sure yet. Index: linux-2.6.13/arch/ppc64/mm/fault.c @@ -306,6 +307,13 @@ void bad_page_fault(struct pt_regs *regs regs->nip = entry->fixup; return; } +#ifdef CONFIG_KGDB + if (atomic_read(&debugger_active) && kgdb_may_fault) { + /* Restore our previous state. */ + kgdb_fault_longjmp(kgdb_fault_jmp_regs); + /* Not reached. */ + } +#endif We might need a new notify_die hook to cover this case. We could use hardware data breakpoint support in kgdb. Eventually it would be nice to be able to select debuggers at boot/runtime. Anton From sfr at canb.auug.org.au Fri Sep 30 23:36:02 2005 From: sfr at canb.auug.org.au (Stephen Rothwell) Date: Fri, 30 Sep 2005 23:36:02 +1000 Subject: [PATCH 0/9] more merge changes Message-ID: <20050930233602.138b6e27.sfr@canb.auug.org.au> Another series of patches to continue the merge. These are some tidyups and moving of more code and lead to enough merged for ppc64 legacy iSeries to build and boot with ARCH=powerpc. There is still a lot left to merge, though. As an aside, this leads to a machine that says this: igosouth:~# uname -a Linux igosouth 2.6.14-rc2sfr #1 SMP Fri Sep 30 17:16:03 EST 2005 powerpc GNU/Linux i.e. it identifies itself as powerpc not ppc64. Which benh points out will probably break all sorts of things :-) I have built this for (my configs) pSeries, iSeries, g5, ARCH=ppc, ARCH=powerpc ppc32 pmac, ARCH=powerpc iSeries and booted the ARCH=powerpc iSeries kernel. So hopefully I haven't broken too much. Paulus, I will let you know where you can find my git tree in a separate email. -- Cheers, Stephen Rothwell sfr at canb.auug.org.au http://www.canb.auug.org.au/~sfr/ arch/powerpc/Kconfig | 12 + arch/powerpc/Kconfig.debug | 2 arch/powerpc/Makefile | 28 +-- arch/powerpc/kernel/Makefile | 20 +- arch/powerpc/kernel/asm-offsets.c | 220 +++++++++++++------------ arch/powerpc/kernel/head_64.S | 9 - arch/powerpc/kernel/idle_power4.S | 5 arch/powerpc/kernel/vmlinux.lds | 174 ------------------- arch/powerpc/kernel/vmlinux.lds.S | 190 ++++++++++++++++++++- arch/powerpc/platforms/iseries/call_sm.h | 7 arch/powerpc/platforms/iseries/ipl_parms.h | 7 arch/powerpc/platforms/iseries/irq.c | 3 arch/powerpc/platforms/iseries/irq.h | 8 arch/powerpc/platforms/iseries/lpardata.c | 10 - arch/powerpc/platforms/iseries/lpevents.c | 2 arch/powerpc/platforms/iseries/main_store.h | 7 arch/powerpc/platforms/iseries/pci.c | 3 arch/powerpc/platforms/iseries/proc.c | 5 arch/powerpc/platforms/iseries/processor_vpd.h | 7 arch/powerpc/platforms/iseries/release_data.h | 7 arch/powerpc/platforms/iseries/setup.c | 10 - arch/powerpc/platforms/iseries/spcomm_area.h | 7 arch/powerpc/platforms/iseries/vpd_areas.h | 7 arch/ppc/kernel/Makefile | 2 arch/ppc/kernel/fpu.S | 133 --------------- arch/ppc/kernel/vector.S | 217 ------------------------ arch/ppc64/Makefile | 2 arch/ppc64/kernel/Makefile | 16 - arch/ppc64/kernel/vector.S | 172 ------------------- include/asm-powerpc/system.h | 4 include/asm-ppc64/iSeries/iSeries_irq.h | 8 31 files changed, 406 insertions(+), 898 deletions(-) -------------- 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/20050930/4ef249be/attachment.pgp From sfr at canb.auug.org.au Fri Sep 30 23:49:59 2005 From: sfr at canb.auug.org.au (Stephen Rothwell) Date: Fri, 30 Sep 2005 23:49:59 +1000 Subject: [PATCH 2/9] powerpc: merge asm-offsets.c In-Reply-To: <20050930233602.138b6e27.sfr@canb.auug.org.au> References: <20050930233602.138b6e27.sfr@canb.auug.org.au> Message-ID: <20050930234959.52c939ef.sfr@canb.auug.org.au> I needed more merged to make iSeries build. I also rearranged it into a bit more logical arrangement where the referneces to each structure are all together. Signed-off-by: Stephen Rothwell --- arch/powerpc/kernel/asm-offsets.c | 220 ++++++++++++++++++++----------------- 1 files changed, 117 insertions(+), 103 deletions(-) -- Cheers, Stephen Rothwell sfr at canb.auug.org.au http://www.canb.auug.org.au/~sfr/ d1dead5c5f016ebadb4b87c2c9fa13dfc2c99bf0 diff --git a/arch/powerpc/kernel/asm-offsets.c b/arch/powerpc/kernel/asm-offsets.c --- a/arch/powerpc/kernel/asm-offsets.c +++ b/arch/powerpc/kernel/asm-offsets.c @@ -20,17 +20,20 @@ #include #include #include -#include -#include #include #include +#ifdef CONFIG_PPC64 #include #include +#else +#include +#include +#endif + #include #include #include #include - #include #include #ifdef CONFIG_PPC64 @@ -50,63 +53,117 @@ int main(void) { - /* thread struct on stack */ - DEFINE(TI_FLAGS, offsetof(struct thread_info, flags)); - DEFINE(TI_PREEMPT, offsetof(struct thread_info, preempt_count)); - DEFINE(TI_CPU, offsetof(struct thread_info, cpu)); -#ifdef CONFIG_PPC32 - DEFINE(TI_LOCAL_FLAGS, offsetof(struct thread_info, local_flags)); -#endif + DEFINE(THREAD, offsetof(struct task_struct, thread)); + DEFINE(MM, offsetof(struct task_struct, mm)); #ifdef CONFIG_PPC64 - DEFINE(TI_SC_NOERR, offsetof(struct thread_info, syscall_noerror)); DEFINE(THREAD_SHIFT, THREAD_SHIFT); -#endif DEFINE(THREAD_SIZE, THREAD_SIZE); - - /* task_struct->thread */ - DEFINE(THREAD, offsetof(struct task_struct, thread)); + DEFINE(AUDITCONTEXT, offsetof(struct task_struct, audit_context)); +#else DEFINE(THREAD_INFO, offsetof(struct task_struct, thread_info)); - DEFINE(MM, offsetof(struct task_struct, mm)); DEFINE(PTRACE, offsetof(struct task_struct, ptrace)); +#endif /* CONFIG_PPC64 */ + DEFINE(KSP, offsetof(struct thread_struct, ksp)); - DEFINE(PGDIR, offsetof(struct thread_struct, pgdir)); - DEFINE(LAST_SYSCALL, offsetof(struct thread_struct, last_syscall)); DEFINE(PT_REGS, offsetof(struct thread_struct, regs)); DEFINE(THREAD_FPEXC_MODE, offsetof(struct thread_struct, fpexc_mode)); DEFINE(THREAD_FPR0, offsetof(struct thread_struct, fpr[0])); DEFINE(THREAD_FPSCR, offsetof(struct thread_struct, fpscr)); -#if defined(CONFIG_4xx) || defined(CONFIG_BOOKE) - DEFINE(THREAD_DBCR0, offsetof(struct thread_struct, dbcr0)); - DEFINE(PT_PTRACED, PT_PTRACED); -#endif -#ifdef CONFIG_PPC64 - DEFINE(KSP_VSID, offsetof(struct thread_struct, ksp_vsid)); -#endif - #ifdef CONFIG_ALTIVEC DEFINE(THREAD_VR0, offsetof(struct thread_struct, vr[0])); DEFINE(THREAD_VRSAVE, offsetof(struct thread_struct, vrsave)); DEFINE(THREAD_VSCR, offsetof(struct thread_struct, vscr)); DEFINE(THREAD_USED_VR, offsetof(struct thread_struct, used_vr)); #endif /* CONFIG_ALTIVEC */ +#ifdef CONFIG_PPC64 + DEFINE(KSP_VSID, offsetof(struct thread_struct, ksp_vsid)); +#else /* CONFIG_PPC64 */ + DEFINE(PGDIR, offsetof(struct thread_struct, pgdir)); + DEFINE(LAST_SYSCALL, offsetof(struct thread_struct, last_syscall)); +#if defined(CONFIG_4xx) || defined(CONFIG_BOOKE) + DEFINE(THREAD_DBCR0, offsetof(struct thread_struct, dbcr0)); + DEFINE(PT_PTRACED, PT_PTRACED); +#endif #ifdef CONFIG_SPE DEFINE(THREAD_EVR0, offsetof(struct thread_struct, evr[0])); DEFINE(THREAD_ACC, offsetof(struct thread_struct, acc)); DEFINE(THREAD_SPEFSCR, offsetof(struct thread_struct, spefscr)); DEFINE(THREAD_USED_SPE, offsetof(struct thread_struct, used_spe)); #endif /* CONFIG_SPE */ +#endif /* CONFIG_PPC64 */ + + DEFINE(TI_FLAGS, offsetof(struct thread_info, flags)); + DEFINE(TI_PREEMPT, offsetof(struct thread_info, preempt_count)); +#ifdef CONFIG_PPC64 + DEFINE(TI_SC_NOERR, offsetof(struct thread_info, syscall_noerror)); +#else + DEFINE(TI_TASK, offsetof(struct thread_info, task)); + DEFINE(TI_EXECDOMAIN, offsetof(struct thread_info, exec_domain)); + DEFINE(TI_LOCAL_FLAGS, offsetof(struct thread_info, local_flags)); + DEFINE(TI_CPU, offsetof(struct thread_info, cpu)); +#endif /* CONFIG_PPC64 */ + +#ifdef CONFIG_PPC64 + DEFINE(DCACHEL1LINESIZE, offsetof(struct ppc64_caches, dline_size)); + DEFINE(DCACHEL1LOGLINESIZE, offsetof(struct ppc64_caches, log_dline_size)); + DEFINE(DCACHEL1LINESPERPAGE, offsetof(struct ppc64_caches, dlines_per_page)); + DEFINE(ICACHEL1LINESIZE, offsetof(struct ppc64_caches, iline_size)); + DEFINE(ICACHEL1LOGLINESIZE, offsetof(struct ppc64_caches, log_iline_size)); + DEFINE(ICACHEL1LINESPERPAGE, offsetof(struct ppc64_caches, ilines_per_page)); + DEFINE(PLATFORM, offsetof(struct systemcfg, platform)); + + /* paca */ + DEFINE(PACA_SIZE, sizeof(struct paca_struct)); + DEFINE(PACAPACAINDEX, offsetof(struct paca_struct, paca_index)); + DEFINE(PACAPROCSTART, offsetof(struct paca_struct, cpu_start)); + DEFINE(PACAKSAVE, offsetof(struct paca_struct, kstack)); + DEFINE(PACACURRENT, offsetof(struct paca_struct, __current)); + DEFINE(PACASAVEDMSR, offsetof(struct paca_struct, saved_msr)); + DEFINE(PACASTABREAL, offsetof(struct paca_struct, stab_real)); + DEFINE(PACASTABVIRT, offsetof(struct paca_struct, stab_addr)); + DEFINE(PACASTABRR, offsetof(struct paca_struct, stab_rr)); + DEFINE(PACAR1, offsetof(struct paca_struct, saved_r1)); + DEFINE(PACATOC, offsetof(struct paca_struct, kernel_toc)); + DEFINE(PACAPROCENABLED, offsetof(struct paca_struct, proc_enabled)); + DEFINE(PACASLBCACHE, offsetof(struct paca_struct, slb_cache)); + DEFINE(PACASLBCACHEPTR, offsetof(struct paca_struct, slb_cache_ptr)); + DEFINE(PACACONTEXTID, offsetof(struct paca_struct, context.id)); +#ifdef CONFIG_HUGETLB_PAGE + DEFINE(PACALOWHTLBAREAS, offsetof(struct paca_struct, context.low_htlb_areas)); + DEFINE(PACAHIGHHTLBAREAS, offsetof(struct paca_struct, context.high_htlb_areas)); +#endif /* CONFIG_HUGETLB_PAGE */ + DEFINE(PACADEFAULTDECR, offsetof(struct paca_struct, default_decr)); + DEFINE(PACA_EXGEN, offsetof(struct paca_struct, exgen)); + DEFINE(PACA_EXMC, offsetof(struct paca_struct, exmc)); + DEFINE(PACA_EXSLB, offsetof(struct paca_struct, exslb)); + DEFINE(PACA_EXDSI, offsetof(struct paca_struct, exdsi)); + DEFINE(PACAEMERGSP, offsetof(struct paca_struct, emergency_sp)); + DEFINE(PACALPPACA, offsetof(struct paca_struct, lppaca)); + DEFINE(PACAHWCPUID, offsetof(struct paca_struct, hw_cpu_id)); + + DEFINE(LPPACASRR0, offsetof(struct lppaca, saved_srr0)); + DEFINE(LPPACASRR1, offsetof(struct lppaca, saved_srr1)); + DEFINE(LPPACAANYINT, offsetof(struct lppaca, int_dword.any_int)); + DEFINE(LPPACADECRINT, offsetof(struct lppaca, int_dword.fields.decr_int)); + + /* RTAS */ + DEFINE(RTASBASE, offsetof(struct rtas_t, base)); + DEFINE(RTASENTRY, offsetof(struct rtas_t, entry)); +#endif /* CONFIG_PPC64 */ + /* Interrupt register frame */ DEFINE(STACK_FRAME_OVERHEAD, STACK_FRAME_OVERHEAD); #ifndef CONFIG_PPC64 DEFINE(INT_FRAME_SIZE, STACK_FRAME_OVERHEAD + sizeof(struct pt_regs)); -#else +#else /* CONFIG_PPC64 */ DEFINE(SWITCH_FRAME_SIZE, STACK_FRAME_OVERHEAD + sizeof(struct pt_regs)); - /* 288 = # of volatile regs, int & fp, for leaf routines */ /* which do not stack a frame. See the PPC64 ABI. */ DEFINE(INT_FRAME_SIZE, STACK_FRAME_OVERHEAD + sizeof(struct pt_regs) + 288); -#endif - /* in fact we only use gpr0 - gpr9 and gpr20 - gpr23 */ + /* Create extra stack space for SRR0 and SRR1 when calling prom/rtas. */ + DEFINE(PROM_FRAME_SIZE, STACK_FRAME_OVERHEAD + sizeof(struct pt_regs) + 16); + DEFINE(RTAS_FRAME_SIZE, STACK_FRAME_OVERHEAD + sizeof(struct pt_regs) + 16); +#endif /* CONFIG_PPC64 */ DEFINE(GPR0, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[0])); DEFINE(GPR1, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[1])); DEFINE(GPR2, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[2])); @@ -121,6 +178,7 @@ int main(void) DEFINE(GPR11, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[11])); DEFINE(GPR12, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[12])); DEFINE(GPR13, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[13])); +#ifndef CONFIG_PPC64 DEFINE(GPR14, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[14])); DEFINE(GPR15, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[15])); DEFINE(GPR16, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[16])); @@ -139,6 +197,7 @@ int main(void) DEFINE(GPR29, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[29])); DEFINE(GPR30, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[30])); DEFINE(GPR31, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[31])); +#endif /* CONFIG_PPC64 */ /* * Note: these symbols include _ because they overlap with special * register names @@ -148,23 +207,37 @@ int main(void) DEFINE(_CTR, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, ctr)); DEFINE(_LINK, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, link)); DEFINE(_CCR, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, ccr)); - DEFINE(_MQ, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, mq)); DEFINE(_XER, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, xer)); DEFINE(_DAR, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, dar)); DEFINE(_DSISR, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, dsisr)); - /* The PowerPC 400-class & Book-E processors have neither the DAR nor the DSISR - * SPRs. Hence, we overload them to hold the similar DEAR and ESR SPRs - * for such processors. For critical interrupts we use them to - * hold SRR0 and SRR1. + DEFINE(ORIG_GPR3, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, orig_gpr3)); + DEFINE(RESULT, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, result)); +#ifndef CONFIG_PPC64 + DEFINE(_MQ, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, mq)); + /* + * The PowerPC 400-class & Book-E processors have neither the DAR + * nor the DSISR SPRs. Hence, we overload them to hold the similar + * DEAR and ESR SPRs for such processors. For critical interrupts + * we use them to hold SRR0 and SRR1. */ DEFINE(_DEAR, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, dar)); DEFINE(_ESR, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, dsisr)); - DEFINE(ORIG_GPR3, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, orig_gpr3)); - DEFINE(RESULT, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, result)); DEFINE(TRAP, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, trap)); +#else /* CONFIG_PPC64 */ + DEFINE(_TRAP, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, trap)); + DEFINE(SOFTE, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, softe)); + + /* These _only_ to be used with {PROM,RTAS}_FRAME_SIZE!!! */ + DEFINE(_SRR0, STACK_FRAME_OVERHEAD+sizeof(struct pt_regs)); + DEFINE(_SRR1, STACK_FRAME_OVERHEAD+sizeof(struct pt_regs)+8); +#endif /* CONFIG_PPC64 */ + DEFINE(CLONE_VM, CLONE_VM); DEFINE(CLONE_UNTRACED, CLONE_UNTRACED); + +#ifndef CONFIG_PPC64 DEFINE(MM_PGD, offsetof(struct mm_struct, pgd)); +#endif /* ! CONFIG_PPC64 */ /* About the CPU features table */ DEFINE(CPU_SPEC_ENTRY_SIZE, sizeof(struct cpu_spec)); @@ -173,66 +246,13 @@ int main(void) DEFINE(CPU_SPEC_FEATURES, offsetof(struct cpu_spec, cpu_features)); DEFINE(CPU_SPEC_SETUP, offsetof(struct cpu_spec, cpu_setup)); -#ifdef CONFIG_PPC64 - DEFINE(MM, offsetof(struct task_struct, mm)); - DEFINE(AUDITCONTEXT, offsetof(struct task_struct, audit_context)); - - DEFINE(DCACHEL1LINESIZE, offsetof(struct ppc64_caches, dline_size)); - DEFINE(DCACHEL1LOGLINESIZE, offsetof(struct ppc64_caches, log_dline_size)); - DEFINE(DCACHEL1LINESPERPAGE, offsetof(struct ppc64_caches, dlines_per_page)); - DEFINE(ICACHEL1LINESIZE, offsetof(struct ppc64_caches, iline_size)); - DEFINE(ICACHEL1LOGLINESIZE, offsetof(struct ppc64_caches, log_iline_size)); - DEFINE(ICACHEL1LINESPERPAGE, offsetof(struct ppc64_caches, ilines_per_page)); - DEFINE(PLATFORM, offsetof(struct systemcfg, platform)); - - /* paca */ - DEFINE(PACA_SIZE, sizeof(struct paca_struct)); - DEFINE(PACAPACAINDEX, offsetof(struct paca_struct, paca_index)); - DEFINE(PACAPROCSTART, offsetof(struct paca_struct, cpu_start)); - DEFINE(PACAKSAVE, offsetof(struct paca_struct, kstack)); - DEFINE(PACACURRENT, offsetof(struct paca_struct, __current)); - DEFINE(PACASAVEDMSR, offsetof(struct paca_struct, saved_msr)); - DEFINE(PACASTABREAL, offsetof(struct paca_struct, stab_real)); - DEFINE(PACASTABVIRT, offsetof(struct paca_struct, stab_addr)); - DEFINE(PACASTABRR, offsetof(struct paca_struct, stab_rr)); - DEFINE(PACAR1, offsetof(struct paca_struct, saved_r1)); - DEFINE(PACATOC, offsetof(struct paca_struct, kernel_toc)); - DEFINE(PACAPROCENABLED, offsetof(struct paca_struct, proc_enabled)); - DEFINE(PACASLBCACHE, offsetof(struct paca_struct, slb_cache)); - DEFINE(PACASLBCACHEPTR, offsetof(struct paca_struct, slb_cache_ptr)); - DEFINE(PACACONTEXTID, offsetof(struct paca_struct, context.id)); -#ifdef CONFIG_HUGETLB_PAGE - DEFINE(PACALOWHTLBAREAS, offsetof(struct paca_struct, context.low_htlb_areas)); - DEFINE(PACAHIGHHTLBAREAS, offsetof(struct paca_struct, context.high_htlb_areas)); -#endif /* CONFIG_HUGETLB_PAGE */ - DEFINE(PACADEFAULTDECR, offsetof(struct paca_struct, default_decr)); - DEFINE(PACA_EXGEN, offsetof(struct paca_struct, exgen)); - DEFINE(PACA_EXMC, offsetof(struct paca_struct, exmc)); - DEFINE(PACA_EXSLB, offsetof(struct paca_struct, exslb)); - DEFINE(PACA_EXDSI, offsetof(struct paca_struct, exdsi)); - DEFINE(PACAEMERGSP, offsetof(struct paca_struct, emergency_sp)); - DEFINE(PACALPPACA, offsetof(struct paca_struct, lppaca)); - DEFINE(PACAHWCPUID, offsetof(struct paca_struct, hw_cpu_id)); - DEFINE(LPPACASRR0, offsetof(struct lppaca, saved_srr0)); - DEFINE(LPPACASRR1, offsetof(struct lppaca, saved_srr1)); - DEFINE(LPPACAANYINT, offsetof(struct lppaca, int_dword.any_int)); - DEFINE(LPPACADECRINT, offsetof(struct lppaca, int_dword.fields.decr_int)); - - /* RTAS */ - DEFINE(RTASBASE, offsetof(struct rtas_t, base)); - DEFINE(RTASENTRY, offsetof(struct rtas_t, entry)); - - DEFINE(_TRAP, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, trap)); - DEFINE(SOFTE, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, softe)); - - /* Create extra stack space for SRR0 and SRR1 when calling prom/rtas. */ - DEFINE(PROM_FRAME_SIZE, STACK_FRAME_OVERHEAD + sizeof(struct pt_regs) + 16); - DEFINE(RTAS_FRAME_SIZE, STACK_FRAME_OVERHEAD + sizeof(struct pt_regs) + 16); - - /* These _only_ to be used with {PROM,RTAS}_FRAME_SIZE!!! */ - DEFINE(_SRR0, STACK_FRAME_OVERHEAD+sizeof(struct pt_regs)); - DEFINE(_SRR1, STACK_FRAME_OVERHEAD+sizeof(struct pt_regs)+8); +#ifndef CONFIG_PPC64 + DEFINE(pbe_address, offsetof(struct pbe, address)); + DEFINE(pbe_orig_address, offsetof(struct pbe, orig_address)); + DEFINE(pbe_next, offsetof(struct pbe, next)); + DEFINE(NUM_USER_SEGMENTS, TASK_SIZE>>28); +#else /* CONFIG_PPC64 */ /* systemcfg offsets for use by vdso */ DEFINE(CFG_TB_ORIG_STAMP, offsetof(struct systemcfg, tb_orig_stamp)); DEFINE(CFG_TB_TICKS_PER_SEC, offsetof(struct systemcfg, tb_ticks_per_sec)); @@ -251,12 +271,6 @@ int main(void) DEFINE(TVAL32_TV_USEC, offsetof(struct compat_timeval, tv_usec)); DEFINE(TZONE_TZ_MINWEST, offsetof(struct timezone, tz_minuteswest)); DEFINE(TZONE_TZ_DSTTIME, offsetof(struct timezone, tz_dsttime)); -#endif - - DEFINE(pbe_address, offsetof(struct pbe, address)); - DEFINE(pbe_orig_address, offsetof(struct pbe, orig_address)); - DEFINE(pbe_next, offsetof(struct pbe, next)); - - DEFINE(NUM_USER_SEGMENTS, TASK_SIZE>>28); +#endif /* CONFIG_PPC64 */ return 0; } From sfr at canb.auug.org.au Fri Sep 30 23:44:46 2005 From: sfr at canb.auug.org.au (Stephen Rothwell) Date: Fri, 30 Sep 2005 23:44:46 +1000 Subject: [PATCH 1/9] ppc64 iseries: move some iSeries include files In-Reply-To: <20050930233602.138b6e27.sfr@canb.auug.org.au> References: <20050930233602.138b6e27.sfr@canb.auug.org.au> Message-ID: <20050930234446.6207aa27.sfr@canb.auug.org.au> These files are only referenced from within arch/powerpc/platforms/iseries, so move them there. We also remove the StudLy Caps from the names. Signed-off-by: Stephen Rothwell --- arch/powerpc/platforms/iseries/call_sm.h | 37 +++++ arch/powerpc/platforms/iseries/ipl_parms.h | 70 ++++++++++ arch/powerpc/platforms/iseries/irq.c | 3 arch/powerpc/platforms/iseries/irq.h | 8 + arch/powerpc/platforms/iseries/lpardata.c | 10 + arch/powerpc/platforms/iseries/main_store.h | 165 ++++++++++++++++++++++++ arch/powerpc/platforms/iseries/pci.c | 3 arch/powerpc/platforms/iseries/proc.c | 5 - arch/powerpc/platforms/iseries/processor_vpd.h | 85 ++++++++++++ arch/powerpc/platforms/iseries/release_data.h | 63 +++++++++ arch/powerpc/platforms/iseries/setup.c | 10 + arch/powerpc/platforms/iseries/spcomm_area.h | 36 +++++ arch/powerpc/platforms/iseries/vpd_areas.h | 88 +++++++++++++ include/asm-ppc64/iSeries/HvCallSm.h | 38 ----- include/asm-ppc64/iSeries/HvReleaseData.h | 64 --------- include/asm-ppc64/iSeries/IoHriMainStore.h | 166 ------------------------ include/asm-ppc64/iSeries/IoHriProcessorVpd.h | 86 ------------ include/asm-ppc64/iSeries/ItIplParmsReal.h | 71 ---------- include/asm-ppc64/iSeries/ItSpCommArea.h | 37 ----- include/asm-ppc64/iSeries/ItVpdAreas.h | 89 ------------- include/asm-ppc64/iSeries/iSeries_irq.h | 8 - 21 files changed, 569 insertions(+), 573 deletions(-) create mode 100644 arch/powerpc/platforms/iseries/call_sm.h create mode 100644 arch/powerpc/platforms/iseries/ipl_parms.h create mode 100644 arch/powerpc/platforms/iseries/irq.h create mode 100644 arch/powerpc/platforms/iseries/main_store.h create mode 100644 arch/powerpc/platforms/iseries/processor_vpd.h create mode 100644 arch/powerpc/platforms/iseries/release_data.h create mode 100644 arch/powerpc/platforms/iseries/spcomm_area.h create mode 100644 arch/powerpc/platforms/iseries/vpd_areas.h delete mode 100644 include/asm-ppc64/iSeries/HvCallSm.h delete mode 100644 include/asm-ppc64/iSeries/HvReleaseData.h delete mode 100644 include/asm-ppc64/iSeries/IoHriMainStore.h delete mode 100644 include/asm-ppc64/iSeries/IoHriProcessorVpd.h delete mode 100644 include/asm-ppc64/iSeries/ItIplParmsReal.h delete mode 100644 include/asm-ppc64/iSeries/ItSpCommArea.h delete mode 100644 include/asm-ppc64/iSeries/ItVpdAreas.h delete mode 100644 include/asm-ppc64/iSeries/iSeries_irq.h -- Cheers, Stephen Rothwell sfr at canb.auug.org.au http://www.canb.auug.org.au/~sfr/ b08567cb680686cdea9e362c0ccf0a08d77b9f0c diff --git a/arch/powerpc/platforms/iseries/call_sm.h b/arch/powerpc/platforms/iseries/call_sm.h new file mode 100644 --- /dev/null +++ b/arch/powerpc/platforms/iseries/call_sm.h @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2001 Mike Corrigan 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 _ISERIES_CALL_SM_H +#define _ISERIES_CALL_SM_H + +/* + * This file contains the "hypervisor call" interface which is used to + * drive the hypervisor from the OS. + */ + +#include +#include + +#define HvCallSmGet64BitsOfAccessMap HvCallSm + 11 + +static inline u64 HvCallSm_get64BitsOfAccessMap(HvLpIndex lpIndex, + u64 indexIntoBitMap) +{ + return HvCall2(HvCallSmGet64BitsOfAccessMap, lpIndex, indexIntoBitMap); +} + +#endif /* _ISERIES_CALL_SM_H */ diff --git a/arch/powerpc/platforms/iseries/ipl_parms.h b/arch/powerpc/platforms/iseries/ipl_parms.h new file mode 100644 --- /dev/null +++ b/arch/powerpc/platforms/iseries/ipl_parms.h @@ -0,0 +1,70 @@ +/* + * Copyright (C) 2001 Mike Corrigan 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 _ISERIES_IPL_PARMS_H +#define _ISERIES_IPL_PARMS_H + +/* + * This struct maps the IPL Parameters DMA'd from the SP. + * + * Warning: + * This data must map in exactly 64 bytes and match the architecture for + * the IPL parms + */ + +#include + +struct ItIplParmsReal { + u8 xFormat; // Defines format of IplParms x00-x00 + u8 xRsvd01:6; // Reserved x01-x01 + u8 xAlternateSearch:1; // Alternate search indicator ... + u8 xUaSupplied:1; // UA Supplied on programmed IPL... + u8 xLsUaFormat; // Format byte for UA x02-x02 + u8 xRsvd02; // Reserved x03-x03 + u32 xLsUa; // LS UA x04-x07 + u32 xUnusedLsLid; // First OS LID to load x08-x0B + u16 xLsBusNumber; // LS Bus Number x0C-x0D + u8 xLsCardAdr; // LS Card Address x0E-x0E + u8 xLsBoardAdr; // LS Board Address x0F-x0F + u32 xRsvd03; // Reserved x10-x13 + u8 xSpcnPresent:1; // SPCN present x14-x14 + u8 xCpmPresent:1; // CPM present ... + u8 xRsvd04:6; // Reserved ... + u8 xRsvd05:4; // Reserved x15-x15 + u8 xKeyLock:4; // Keylock setting ... + u8 xRsvd06:6; // Reserved x16-x16 + u8 xIplMode:2; // Ipl mode (A|B|C|D) ... + u8 xHwIplType; // Fast v slow v slow EC HW IPL x17-x17 + u16 xCpmEnabledIpl:1; // CPM in effect when IPL initiatedx18-x19 + u16 xPowerOnResetIpl:1; // Indicate POR condition ... + u16 xMainStorePreserved:1; // Main Storage is preserved ... + u16 xRsvd07:13; // Reserved ... + u16 xIplSource:16; // Ipl source x1A-x1B + u8 xIplReason:8; // Reason for this IPL x1C-x1C + u8 xRsvd08; // Reserved x1D-x1D + u16 xRsvd09; // Reserved x1E-x1F + u16 xSysBoxType; // System Box Type x20-x21 + u16 xSysProcType; // System Processor Type x22-x23 + u32 xRsvd10; // Reserved x24-x27 + u64 xRsvd11; // Reserved x28-x2F + u64 xRsvd12; // Reserved x30-x37 + u64 xRsvd13; // Reserved x38-x3F +}; + +extern struct ItIplParmsReal xItIplParmsReal; + +#endif /* _ISERIES_IPL_PARMS_H */ diff --git a/arch/powerpc/platforms/iseries/irq.c b/arch/powerpc/platforms/iseries/irq.c --- a/arch/powerpc/platforms/iseries/irq.c +++ b/arch/powerpc/platforms/iseries/irq.c @@ -40,7 +40,8 @@ #include #include #include -#include + +#include "irq.h" /* This maps virtual irq numbers to real irqs */ unsigned int virt_irq_to_real_map[NR_IRQS]; diff --git a/arch/powerpc/platforms/iseries/irq.h b/arch/powerpc/platforms/iseries/irq.h new file mode 100644 --- /dev/null +++ b/arch/powerpc/platforms/iseries/irq.h @@ -0,0 +1,8 @@ +#ifndef _ISERIES_IRQ_H +#define _ISERIES_IRQ_H + +extern void iSeries_init_IRQ(void); +extern int iSeries_allocate_IRQ(HvBusNumber, HvSubBusNumber, HvAgentId); +extern void iSeries_activate_IRQs(void); + +#endif /* _ISERIES_IRQ_H */ diff --git a/arch/powerpc/platforms/iseries/lpardata.c b/arch/powerpc/platforms/iseries/lpardata.c --- a/arch/powerpc/platforms/iseries/lpardata.c +++ b/arch/powerpc/platforms/iseries/lpardata.c @@ -19,15 +19,15 @@ #include #include #include -#include #include -#include -#include #include #include -#include -#include +#include "vpd_areas.h" +#include "spcomm_area.h" +#include "ipl_parms.h" +#include "processor_vpd.h" +#include "release_data.h" /* The HvReleaseData is the root of the information shared between * the hypervisor and Linux. diff --git a/arch/powerpc/platforms/iseries/main_store.h b/arch/powerpc/platforms/iseries/main_store.h new file mode 100644 --- /dev/null +++ b/arch/powerpc/platforms/iseries/main_store.h @@ -0,0 +1,165 @@ +/* + * Copyright (C) 2001 Mike Corrigan 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 _ISERIES_MAIN_STORE_H +#define _ISERIES_MAIN_STORE_H + +/* Main Store Vpd for Condor,iStar,sStar */ +struct IoHriMainStoreSegment4 { + u8 msArea0Exists:1; + u8 msArea1Exists:1; + u8 msArea2Exists:1; + u8 msArea3Exists:1; + u8 reserved1:4; + u8 reserved2; + + u8 msArea0Functional:1; + u8 msArea1Functional:1; + u8 msArea2Functional:1; + u8 msArea3Functional:1; + u8 reserved3:4; + u8 reserved4; + + u32 totalMainStore; + + u64 msArea0Ptr; + u64 msArea1Ptr; + u64 msArea2Ptr; + u64 msArea3Ptr; + + u32 cardProductionLevel; + + u32 msAdrHole; + + u8 msArea0HasRiserVpd:1; + u8 msArea1HasRiserVpd:1; + u8 msArea2HasRiserVpd:1; + u8 msArea3HasRiserVpd:1; + u8 reserved5:4; + u8 reserved6; + u16 reserved7; + + u8 reserved8[28]; + + u64 nonInterleavedBlocksStartAdr; + u64 nonInterleavedBlocksEndAdr; +}; + +/* Main Store VPD for Power4 */ +struct IoHriMainStoreChipInfo1 { + u32 chipMfgID __attribute((packed)); + char chipECLevel[4] __attribute((packed)); +}; + +struct IoHriMainStoreVpdIdData { + char typeNumber[4]; + char modelNumber[4]; + char partNumber[12]; + char serialNumber[12]; +}; + +struct IoHriMainStoreVpdFruData { + char fruLabel[8] __attribute((packed)); + u8 numberOfSlots __attribute((packed)); + u8 pluggingType __attribute((packed)); + u16 slotMapIndex __attribute((packed)); +}; + +struct IoHriMainStoreAdrRangeBlock { + void *blockStart __attribute((packed)); + void *blockEnd __attribute((packed)); + u32 blockProcChipId __attribute((packed)); +}; + +#define MaxAreaAdrRangeBlocks 4 + +struct IoHriMainStoreArea4 { + u32 msVpdFormat __attribute((packed)); + u8 containedVpdType __attribute((packed)); + u8 reserved1 __attribute((packed)); + u16 reserved2 __attribute((packed)); + + u64 msExists __attribute((packed)); + u64 msFunctional __attribute((packed)); + + u32 memorySize __attribute((packed)); + u32 procNodeId __attribute((packed)); + + u32 numAdrRangeBlocks __attribute((packed)); + struct IoHriMainStoreAdrRangeBlock xAdrRangeBlock[MaxAreaAdrRangeBlocks] __attribute((packed)); + + struct IoHriMainStoreChipInfo1 chipInfo0 __attribute((packed)); + struct IoHriMainStoreChipInfo1 chipInfo1 __attribute((packed)); + struct IoHriMainStoreChipInfo1 chipInfo2 __attribute((packed)); + struct IoHriMainStoreChipInfo1 chipInfo3 __attribute((packed)); + struct IoHriMainStoreChipInfo1 chipInfo4 __attribute((packed)); + struct IoHriMainStoreChipInfo1 chipInfo5 __attribute((packed)); + struct IoHriMainStoreChipInfo1 chipInfo6 __attribute((packed)); + struct IoHriMainStoreChipInfo1 chipInfo7 __attribute((packed)); + + void *msRamAreaArray __attribute((packed)); + u32 msRamAreaArrayNumEntries __attribute((packed)); + u32 msRamAreaArrayEntrySize __attribute((packed)); + + u32 numaDimmExists __attribute((packed)); + u32 numaDimmFunctional __attribute((packed)); + void *numaDimmArray __attribute((packed)); + u32 numaDimmArrayNumEntries __attribute((packed)); + u32 numaDimmArrayEntrySize __attribute((packed)); + + struct IoHriMainStoreVpdIdData idData __attribute((packed)); + + u64 powerData __attribute((packed)); + u64 cardAssemblyPartNum __attribute((packed)); + u64 chipSerialNum __attribute((packed)); + + u64 reserved3 __attribute((packed)); + char reserved4[16] __attribute((packed)); + + struct IoHriMainStoreVpdFruData fruData __attribute((packed)); + + u8 vpdPortNum __attribute((packed)); + u8 reserved5 __attribute((packed)); + u8 frameId __attribute((packed)); + u8 rackUnit __attribute((packed)); + char asciiKeywordVpd[256] __attribute((packed)); + u32 reserved6 __attribute((packed)); +}; + + +struct IoHriMainStoreSegment5 { + u16 reserved1; + u8 reserved2; + u8 msVpdFormat; + + u32 totalMainStore; + u64 maxConfiguredMsAdr; + + struct IoHriMainStoreArea4 *msAreaArray; + u32 msAreaArrayNumEntries; + u32 msAreaArrayEntrySize; + + u32 msAreaExists; + u32 msAreaFunctional; + + u64 reserved3; +}; + +extern u64 xMsVpd[]; + +#endif /* _ISERIES_MAIN_STORE_H */ diff --git a/arch/powerpc/platforms/iseries/pci.c b/arch/powerpc/platforms/iseries/pci.c --- a/arch/powerpc/platforms/iseries/pci.c +++ b/arch/powerpc/platforms/iseries/pci.c @@ -37,12 +37,13 @@ #include #include -#include #include #include #include +#include "irq.h" + extern unsigned long io_page_mask; /* diff --git a/arch/powerpc/platforms/iseries/proc.c b/arch/powerpc/platforms/iseries/proc.c --- a/arch/powerpc/platforms/iseries/proc.c +++ b/arch/powerpc/platforms/iseries/proc.c @@ -26,8 +26,9 @@ #include #include #include -#include -#include + +#include "processor_vpd.h" +#include "main_store.h" static int __init iseries_proc_create(void) { diff --git a/arch/powerpc/platforms/iseries/processor_vpd.h b/arch/powerpc/platforms/iseries/processor_vpd.h new file mode 100644 --- /dev/null +++ b/arch/powerpc/platforms/iseries/processor_vpd.h @@ -0,0 +1,85 @@ +/* + * Copyright (C) 2001 Mike Corrigan 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 _ISERIES_PROCESSOR_VPD_H +#define _ISERIES_PROCESSOR_VPD_H + +#include + +/* + * This struct maps Processor Vpd that is DMAd to SLIC by CSP + */ +struct IoHriProcessorVpd { + u8 xFormat; // VPD format indicator x00-x00 + u8 xProcStatus:8; // Processor State x01-x01 + u8 xSecondaryThreadCount; // Secondary thread cnt x02-x02 + u8 xSrcType:1; // Src Type x03-x03 + u8 xSrcSoft:1; // Src stay soft ... + u8 xSrcParable:1; // Src parable ... + u8 xRsvd1:5; // Reserved ... + u16 xHvPhysicalProcIndex; // Hypervisor physical proc index04-x05 + u16 xRsvd2; // Reserved x06-x07 + u32 xHwNodeId; // Hardware node id x08-x0B + u32 xHwProcId; // Hardware processor id x0C-x0F + + u32 xTypeNum; // Card Type/CCIN number x10-x13 + u32 xModelNum; // Model/Feature number x14-x17 + u64 xSerialNum; // Serial number x18-x1F + char xPartNum[12]; // Book Part or FPU number x20-x2B + char xMfgID[4]; // Manufacturing ID x2C-x2F + + u32 xProcFreq; // Processor Frequency x30-x33 + u32 xTimeBaseFreq; // Time Base Frequency x34-x37 + + u32 xChipEcLevel; // Chip EC Levels x38-x3B + u32 xProcIdReg; // PIR SPR value x3C-x3F + u32 xPVR; // PVR value x40-x43 + u8 xRsvd3[12]; // Reserved x44-x4F + + u32 xInstCacheSize; // Instruction cache size in KB x50-x53 + u32 xInstBlockSize; // Instruction cache block size x54-x57 + u32 xDataCacheOperandSize; // Data cache operand size x58-x5B + u32 xInstCacheOperandSize; // Inst cache operand size x5C-x5F + + u32 xDataL1CacheSizeKB; // L1 data cache size in KB x60-x63 + u32 xDataL1CacheLineSize; // L1 data cache block size x64-x67 + u64 xRsvd4; // Reserved x68-x6F + + u32 xDataL2CacheSizeKB; // L2 data cache size in KB x70-x73 + u32 xDataL2CacheLineSize; // L2 data cache block size x74-x77 + u64 xRsvd5; // Reserved x78-x7F + + u32 xDataL3CacheSizeKB; // L3 data cache size in KB x80-x83 + u32 xDataL3CacheLineSize; // L3 data cache block size x84-x87 + u64 xRsvd6; // Reserved x88-x8F + + u64 xFruLabel; // Card Location Label x90-x97 + u8 xSlotsOnCard; // Slots on card (0=no slots) x98-x98 + u8 xPartLocFlag; // Location flag (0-pluggable 1-imbedded) x99-x99 + u16 xSlotMapIndex; // Index in slot map table x9A-x9B + u8 xSmartCardPortNo; // Smart card port number x9C-x9C + u8 xRsvd7; // Reserved x9D-x9D + u16 xFrameIdAndRackUnit; // Frame ID and rack unit adr x9E-x9F + + u8 xRsvd8[24]; // Reserved xA0-xB7 + + char xProcSrc[72]; // CSP format SRC xB8-xFF +}; + +extern struct IoHriProcessorVpd xIoHriProcessorVpd[]; + +#endif /* _ISERIES_PROCESSOR_VPD_H */ diff --git a/arch/powerpc/platforms/iseries/release_data.h b/arch/powerpc/platforms/iseries/release_data.h new file mode 100644 --- /dev/null +++ b/arch/powerpc/platforms/iseries/release_data.h @@ -0,0 +1,63 @@ +/* + * Copyright (C) 2001 Mike Corrigan 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 _ISERIES_RELEASE_DATA_H +#define _ISERIES_RELEASE_DATA_H + +/* + * This control block contains the critical information about the + * release so that it can be changed in the future (ie, the virtual + * address of the OS's NACA). + */ +#include +#include + +/* + * When we IPL a secondary partition, we will check if if the + * secondary xMinPlicVrmIndex > the primary xVrmIndex. + * If it is then this tells PLIC that this secondary is not + * supported running on this "old" of a level of PLIC. + * + * Likewise, we will compare the primary xMinSlicVrmIndex to + * the secondary xVrmIndex. + * If the primary xMinSlicVrmDelta > secondary xVrmDelta then we + * know that this PLIC does not support running an OS "that old". + */ + +#define HVREL_TAGSINACTIVE 0x8000 +#define HVREL_32BIT 0x4000 +#define HVREL_NOSHAREDPROCS 0x2000 +#define HVREL_NOHMT 0x1000 + +struct HvReleaseData { + u32 xDesc; /* Descriptor "HvRD" ebcdic x00-x03 */ + u16 xSize; /* Size of this control block x04-x05 */ + u16 xVpdAreasPtrOffset; /* Offset in NACA of ItVpdAreas x06-x07 */ + struct naca_struct *xSlicNacaAddr; /* Virt addr of SLIC NACA x08-x0F */ + u32 xMsNucDataOffset; /* Offset of Linux Mapping Data x10-x13 */ + u32 xRsvd1; /* Reserved x14-x17 */ + u16 xFlags; + u16 xVrmIndex; /* VRM Index of OS image x1A-x1B */ + u16 xMinSupportedPlicVrmIndex; /* Min PLIC level (soft) x1C-x1D */ + u16 xMinCompatablePlicVrmIndex; /* Min PLIC levelP (hard) x1E-x1F */ + char xVrmName[12]; /* Displayable name x20-x2B */ + char xRsvd3[20]; /* Reserved x2C-x3F */ +}; + +extern struct HvReleaseData hvReleaseData; + +#endif /* _ISERIES_RELEASE_DATA_H */ diff --git a/arch/powerpc/platforms/iseries/setup.c b/arch/powerpc/platforms/iseries/setup.c --- a/arch/powerpc/platforms/iseries/setup.c +++ b/arch/powerpc/platforms/iseries/setup.c @@ -48,18 +48,18 @@ #include #include #include -#include #include #include -#include #include #include -#include -#include -#include #include #include "setup.h" +#include "irq.h" +#include "vpd_areas.h" +#include "processor_vpd.h" +#include "main_store.h" +#include "call_sm.h" extern void hvlog(char *fmt, ...); diff --git a/arch/powerpc/platforms/iseries/spcomm_area.h b/arch/powerpc/platforms/iseries/spcomm_area.h new file mode 100644 --- /dev/null +++ b/arch/powerpc/platforms/iseries/spcomm_area.h @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2001 Mike Corrigan 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 _ISERIES_SPCOMM_AREA_H +#define _ISERIES_SPCOMM_AREA_H + + +struct SpCommArea { + u32 xDesc; // Descriptor (only in new formats) 000-003 + u8 xFormat; // Format (only in new formats) 004-004 + u8 xRsvd1[11]; // Reserved 005-00F + u64 xRawTbAtIplStart; // Raw HW TB value when IPL is started 010-017 + u64 xRawTodAtIplStart; // Raw HW TOD value when IPL is started 018-01F + u64 xBcdTimeAtIplStart; // BCD time when IPL is started 020-027 + u64 xBcdTimeAtOsStart; // BCD time when OS passed control 028-02F + u8 xRsvd2[80]; // Reserved 030-07F +}; + +extern struct SpCommArea xSpCommArea; + +#endif /* _ISERIES_SPCOMM_AREA_H */ diff --git a/arch/powerpc/platforms/iseries/vpd_areas.h b/arch/powerpc/platforms/iseries/vpd_areas.h new file mode 100644 --- /dev/null +++ b/arch/powerpc/platforms/iseries/vpd_areas.h @@ -0,0 +1,88 @@ +/* + * Copyright (C) 2001 Mike Corrigan 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 _ISERIES_VPD_AREAS_H +#define _ISERIES_VPD_AREAS_H + +/* + * This file defines the address and length of all of the VPD area passed to + * the OS from PLIC (most of which start from the SP). + */ + +#include + +/* VPD Entry index is carved in stone - cannot be changed (easily). */ +#define ItVpdCecVpd 0 +#define ItVpdDynamicSpace 1 +#define ItVpdExtVpd 2 +#define ItVpdExtVpdOnPanel 3 +#define ItVpdFirstPaca 4 +#define ItVpdIoVpd 5 +#define ItVpdIplParms 6 +#define ItVpdMsVpd 7 +#define ItVpdPanelVpd 8 +#define ItVpdLpNaca 9 +#define ItVpdBackplaneAndMaybeClockCardVpd 10 +#define ItVpdRecoveryLogBuffer 11 +#define ItVpdSpCommArea 12 +#define ItVpdSpLogBuffer 13 +#define ItVpdSpLogBufferSave 14 +#define ItVpdSpCardVpd 15 +#define ItVpdFirstProcVpd 16 +#define ItVpdApModelVpd 17 +#define ItVpdClockCardVpd 18 +#define ItVpdBusExtCardVpd 19 +#define ItVpdProcCapacityVpd 20 +#define ItVpdInteractiveCapacityVpd 21 +#define ItVpdFirstSlotLabel 22 +#define ItVpdFirstLpQueue 23 +#define ItVpdFirstL3CacheVpd 24 +#define ItVpdFirstProcFruVpd 25 + +#define ItVpdMaxEntries 26 + +#define ItDmaMaxEntries 10 + +#define ItVpdAreasMaxSlotLabels 192 + + +struct ItVpdAreas { + u32 xSlicDesc; // Descriptor 000-003 + u16 xSlicSize; // Size of this control block 004-005 + u16 xPlicAdjustVpdLens:1; // Flag to indicate new interface006-007 + u16 xRsvd1:15; // Reserved bits ... + u16 xSlicVpdEntries; // Number of VPD entries 008-009 + u16 xSlicDmaEntries; // Number of DMA entries 00A-00B + u16 xSlicMaxLogicalProcs; // Maximum logical processors 00C-00D + u16 xSlicMaxPhysicalProcs; // Maximum physical processors 00E-00F + u16 xSlicDmaToksOffset; // Offset into this of array 010-011 + u16 xSlicVpdAdrsOffset; // Offset into this of array 012-013 + u16 xSlicDmaLensOffset; // Offset into this of array 014-015 + u16 xSlicVpdLensOffset; // Offset into this of array 016-017 + u16 xSlicMaxSlotLabels; // Maximum number of slot labels018-019 + u16 xSlicMaxLpQueues; // Maximum number of LP Queues 01A-01B + u8 xRsvd2[4]; // Reserved 01C-01F + u64 xRsvd3[12]; // Reserved 020-07F + u32 xPlicDmaLens[ItDmaMaxEntries];// Array of DMA lengths 080-0A7 + u32 xPlicDmaToks[ItDmaMaxEntries];// Array of DMA tokens 0A8-0CF + u32 xSlicVpdLens[ItVpdMaxEntries];// Array of VPD lengths 0D0-12F + void *xSlicVpdAdrs[ItVpdMaxEntries];// Array of VPD buffers 130-1EF +}; + +extern struct ItVpdAreas itVpdAreas; + +#endif /* _ISERIES_VPD_AREAS_H */ diff --git a/include/asm-ppc64/iSeries/HvCallSm.h b/include/asm-ppc64/iSeries/HvCallSm.h deleted file mode 100644 --- a/include/asm-ppc64/iSeries/HvCallSm.h +++ /dev/null @@ -1,38 +0,0 @@ -/* - * HvCallSm.h - * Copyright (C) 2001 Mike Corrigan 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 _HVCALLSM_H -#define _HVCALLSM_H - -/* - * This file contains the "hypervisor call" interface which is used to - * drive the hypervisor from the OS. - */ - -#include -#include - -#define HvCallSmGet64BitsOfAccessMap HvCallSm + 11 - -static inline u64 HvCallSm_get64BitsOfAccessMap(HvLpIndex lpIndex, - u64 indexIntoBitMap) -{ - return HvCall2(HvCallSmGet64BitsOfAccessMap, lpIndex, indexIntoBitMap); -} - -#endif /* _HVCALLSM_H */ diff --git a/include/asm-ppc64/iSeries/HvReleaseData.h b/include/asm-ppc64/iSeries/HvReleaseData.h deleted file mode 100644 --- a/include/asm-ppc64/iSeries/HvReleaseData.h +++ /dev/null @@ -1,64 +0,0 @@ -/* - * HvReleaseData.h - * Copyright (C) 2001 Mike Corrigan 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 _HVRELEASEDATA_H -#define _HVRELEASEDATA_H - -/* - * This control block contains the critical information about the - * release so that it can be changed in the future (ie, the virtual - * address of the OS's NACA). - */ -#include -#include - -/* - * When we IPL a secondary partition, we will check if if the - * secondary xMinPlicVrmIndex > the primary xVrmIndex. - * If it is then this tells PLIC that this secondary is not - * supported running on this "old" of a level of PLIC. - * - * Likewise, we will compare the primary xMinSlicVrmIndex to - * the secondary xVrmIndex. - * If the primary xMinSlicVrmDelta > secondary xVrmDelta then we - * know that this PLIC does not support running an OS "that old". - */ - -#define HVREL_TAGSINACTIVE 0x8000 -#define HVREL_32BIT 0x4000 -#define HVREL_NOSHAREDPROCS 0x2000 -#define HVREL_NOHMT 0x1000 - -struct HvReleaseData { - u32 xDesc; /* Descriptor "HvRD" ebcdic x00-x03 */ - u16 xSize; /* Size of this control block x04-x05 */ - u16 xVpdAreasPtrOffset; /* Offset in NACA of ItVpdAreas x06-x07 */ - struct naca_struct *xSlicNacaAddr; /* Virt addr of SLIC NACA x08-x0F */ - u32 xMsNucDataOffset; /* Offset of Linux Mapping Data x10-x13 */ - u32 xRsvd1; /* Reserved x14-x17 */ - u16 xFlags; - u16 xVrmIndex; /* VRM Index of OS image x1A-x1B */ - u16 xMinSupportedPlicVrmIndex; /* Min PLIC level (soft) x1C-x1D */ - u16 xMinCompatablePlicVrmIndex; /* Min PLIC levelP (hard) x1E-x1F */ - char xVrmName[12]; /* Displayable name x20-x2B */ - char xRsvd3[20]; /* Reserved x2C-x3F */ -}; - -extern struct HvReleaseData hvReleaseData; - -#endif /* _HVRELEASEDATA_H */ diff --git a/include/asm-ppc64/iSeries/IoHriMainStore.h b/include/asm-ppc64/iSeries/IoHriMainStore.h deleted file mode 100644 --- a/include/asm-ppc64/iSeries/IoHriMainStore.h +++ /dev/null @@ -1,166 +0,0 @@ -/* - * IoHriMainStore.h - * Copyright (C) 2001 Mike Corrigan 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 _IOHRIMAINSTORE_H -#define _IOHRIMAINSTORE_H - -/* Main Store Vpd for Condor,iStar,sStar */ -struct IoHriMainStoreSegment4 { - u8 msArea0Exists:1; - u8 msArea1Exists:1; - u8 msArea2Exists:1; - u8 msArea3Exists:1; - u8 reserved1:4; - u8 reserved2; - - u8 msArea0Functional:1; - u8 msArea1Functional:1; - u8 msArea2Functional:1; - u8 msArea3Functional:1; - u8 reserved3:4; - u8 reserved4; - - u32 totalMainStore; - - u64 msArea0Ptr; - u64 msArea1Ptr; - u64 msArea2Ptr; - u64 msArea3Ptr; - - u32 cardProductionLevel; - - u32 msAdrHole; - - u8 msArea0HasRiserVpd:1; - u8 msArea1HasRiserVpd:1; - u8 msArea2HasRiserVpd:1; - u8 msArea3HasRiserVpd:1; - u8 reserved5:4; - u8 reserved6; - u16 reserved7; - - u8 reserved8[28]; - - u64 nonInterleavedBlocksStartAdr; - u64 nonInterleavedBlocksEndAdr; -}; - -/* Main Store VPD for Power4 */ -struct IoHriMainStoreChipInfo1 { - u32 chipMfgID __attribute((packed)); - char chipECLevel[4] __attribute((packed)); -}; - -struct IoHriMainStoreVpdIdData { - char typeNumber[4]; - char modelNumber[4]; - char partNumber[12]; - char serialNumber[12]; -}; - -struct IoHriMainStoreVpdFruData { - char fruLabel[8] __attribute((packed)); - u8 numberOfSlots __attribute((packed)); - u8 pluggingType __attribute((packed)); - u16 slotMapIndex __attribute((packed)); -}; - -struct IoHriMainStoreAdrRangeBlock { - void *blockStart __attribute((packed)); - void *blockEnd __attribute((packed)); - u32 blockProcChipId __attribute((packed)); -}; - -#define MaxAreaAdrRangeBlocks 4 - -struct IoHriMainStoreArea4 { - u32 msVpdFormat __attribute((packed)); - u8 containedVpdType __attribute((packed)); - u8 reserved1 __attribute((packed)); - u16 reserved2 __attribute((packed)); - - u64 msExists __attribute((packed)); - u64 msFunctional __attribute((packed)); - - u32 memorySize __attribute((packed)); - u32 procNodeId __attribute((packed)); - - u32 numAdrRangeBlocks __attribute((packed)); - struct IoHriMainStoreAdrRangeBlock xAdrRangeBlock[MaxAreaAdrRangeBlocks] __attribute((packed)); - - struct IoHriMainStoreChipInfo1 chipInfo0 __attribute((packed)); - struct IoHriMainStoreChipInfo1 chipInfo1 __attribute((packed)); - struct IoHriMainStoreChipInfo1 chipInfo2 __attribute((packed)); - struct IoHriMainStoreChipInfo1 chipInfo3 __attribute((packed)); - struct IoHriMainStoreChipInfo1 chipInfo4 __attribute((packed)); - struct IoHriMainStoreChipInfo1 chipInfo5 __attribute((packed)); - struct IoHriMainStoreChipInfo1 chipInfo6 __attribute((packed)); - struct IoHriMainStoreChipInfo1 chipInfo7 __attribute((packed)); - - void *msRamAreaArray __attribute((packed)); - u32 msRamAreaArrayNumEntries __attribute((packed)); - u32 msRamAreaArrayEntrySize __attribute((packed)); - - u32 numaDimmExists __attribute((packed)); - u32 numaDimmFunctional __attribute((packed)); - void *numaDimmArray __attribute((packed)); - u32 numaDimmArrayNumEntries __attribute((packed)); - u32 numaDimmArrayEntrySize __attribute((packed)); - - struct IoHriMainStoreVpdIdData idData __attribute((packed)); - - u64 powerData __attribute((packed)); - u64 cardAssemblyPartNum __attribute((packed)); - u64 chipSerialNum __attribute((packed)); - - u64 reserved3 __attribute((packed)); - char reserved4[16] __attribute((packed)); - - struct IoHriMainStoreVpdFruData fruData __attribute((packed)); - - u8 vpdPortNum __attribute((packed)); - u8 reserved5 __attribute((packed)); - u8 frameId __attribute((packed)); - u8 rackUnit __attribute((packed)); - char asciiKeywordVpd[256] __attribute((packed)); - u32 reserved6 __attribute((packed)); -}; - - -struct IoHriMainStoreSegment5 { - u16 reserved1; - u8 reserved2; - u8 msVpdFormat; - - u32 totalMainStore; - u64 maxConfiguredMsAdr; - - struct IoHriMainStoreArea4 *msAreaArray; - u32 msAreaArrayNumEntries; - u32 msAreaArrayEntrySize; - - u32 msAreaExists; - u32 msAreaFunctional; - - u64 reserved3; -}; - -extern u64 xMsVpd[]; - -#endif /* _IOHRIMAINSTORE_H */ diff --git a/include/asm-ppc64/iSeries/IoHriProcessorVpd.h b/include/asm-ppc64/iSeries/IoHriProcessorVpd.h deleted file mode 100644 --- a/include/asm-ppc64/iSeries/IoHriProcessorVpd.h +++ /dev/null @@ -1,86 +0,0 @@ -/* - * IoHriProcessorVpd.h - * Copyright (C) 2001 Mike Corrigan 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 _IOHRIPROCESSORVPD_H -#define _IOHRIPROCESSORVPD_H - -#include - -/* - * This struct maps Processor Vpd that is DMAd to SLIC by CSP - */ -struct IoHriProcessorVpd { - u8 xFormat; // VPD format indicator x00-x00 - u8 xProcStatus:8; // Processor State x01-x01 - u8 xSecondaryThreadCount; // Secondary thread cnt x02-x02 - u8 xSrcType:1; // Src Type x03-x03 - u8 xSrcSoft:1; // Src stay soft ... - u8 xSrcParable:1; // Src parable ... - u8 xRsvd1:5; // Reserved ... - u16 xHvPhysicalProcIndex; // Hypervisor physical proc index04-x05 - u16 xRsvd2; // Reserved x06-x07 - u32 xHwNodeId; // Hardware node id x08-x0B - u32 xHwProcId; // Hardware processor id x0C-x0F - - u32 xTypeNum; // Card Type/CCIN number x10-x13 - u32 xModelNum; // Model/Feature number x14-x17 - u64 xSerialNum; // Serial number x18-x1F - char xPartNum[12]; // Book Part or FPU number x20-x2B - char xMfgID[4]; // Manufacturing ID x2C-x2F - - u32 xProcFreq; // Processor Frequency x30-x33 - u32 xTimeBaseFreq; // Time Base Frequency x34-x37 - - u32 xChipEcLevel; // Chip EC Levels x38-x3B - u32 xProcIdReg; // PIR SPR value x3C-x3F - u32 xPVR; // PVR value x40-x43 - u8 xRsvd3[12]; // Reserved x44-x4F - - u32 xInstCacheSize; // Instruction cache size in KB x50-x53 - u32 xInstBlockSize; // Instruction cache block size x54-x57 - u32 xDataCacheOperandSize; // Data cache operand size x58-x5B - u32 xInstCacheOperandSize; // Inst cache operand size x5C-x5F - - u32 xDataL1CacheSizeKB; // L1 data cache size in KB x60-x63 - u32 xDataL1CacheLineSize; // L1 data cache block size x64-x67 - u64 xRsvd4; // Reserved x68-x6F - - u32 xDataL2CacheSizeKB; // L2 data cache size in KB x70-x73 - u32 xDataL2CacheLineSize; // L2 data cache block size x74-x77 - u64 xRsvd5; // Reserved x78-x7F - - u32 xDataL3CacheSizeKB; // L3 data cache size in KB x80-x83 - u32 xDataL3CacheLineSize; // L3 data cache block size x84-x87 - u64 xRsvd6; // Reserved x88-x8F - - u64 xFruLabel; // Card Location Label x90-x97 - u8 xSlotsOnCard; // Slots on card (0=no slots) x98-x98 - u8 xPartLocFlag; // Location flag (0-pluggable 1-imbedded) x99-x99 - u16 xSlotMapIndex; // Index in slot map table x9A-x9B - u8 xSmartCardPortNo; // Smart card port number x9C-x9C - u8 xRsvd7; // Reserved x9D-x9D - u16 xFrameIdAndRackUnit; // Frame ID and rack unit adr x9E-x9F - - u8 xRsvd8[24]; // Reserved xA0-xB7 - - char xProcSrc[72]; // CSP format SRC xB8-xFF -}; - -extern struct IoHriProcessorVpd xIoHriProcessorVpd[]; - -#endif /* _IOHRIPROCESSORVPD_H */ diff --git a/include/asm-ppc64/iSeries/ItIplParmsReal.h b/include/asm-ppc64/iSeries/ItIplParmsReal.h deleted file mode 100644 --- a/include/asm-ppc64/iSeries/ItIplParmsReal.h +++ /dev/null @@ -1,71 +0,0 @@ -/* - * ItIplParmsReal.h - * Copyright (C) 2001 Mike Corrigan 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 _ITIPLPARMSREAL_H -#define _ITIPLPARMSREAL_H - -/* - * This struct maps the IPL Parameters DMA'd from the SP. - * - * Warning: - * This data must map in exactly 64 bytes and match the architecture for - * the IPL parms - */ - -#include - -struct ItIplParmsReal { - u8 xFormat; // Defines format of IplParms x00-x00 - u8 xRsvd01:6; // Reserved x01-x01 - u8 xAlternateSearch:1; // Alternate search indicator ... - u8 xUaSupplied:1; // UA Supplied on programmed IPL... - u8 xLsUaFormat; // Format byte for UA x02-x02 - u8 xRsvd02; // Reserved x03-x03 - u32 xLsUa; // LS UA x04-x07 - u32 xUnusedLsLid; // First OS LID to load x08-x0B - u16 xLsBusNumber; // LS Bus Number x0C-x0D - u8 xLsCardAdr; // LS Card Address x0E-x0E - u8 xLsBoardAdr; // LS Board Address x0F-x0F - u32 xRsvd03; // Reserved x10-x13 - u8 xSpcnPresent:1; // SPCN present x14-x14 - u8 xCpmPresent:1; // CPM present ... - u8 xRsvd04:6; // Reserved ... - u8 xRsvd05:4; // Reserved x15-x15 - u8 xKeyLock:4; // Keylock setting ... - u8 xRsvd06:6; // Reserved x16-x16 - u8 xIplMode:2; // Ipl mode (A|B|C|D) ... - u8 xHwIplType; // Fast v slow v slow EC HW IPL x17-x17 - u16 xCpmEnabledIpl:1; // CPM in effect when IPL initiatedx18-x19 - u16 xPowerOnResetIpl:1; // Indicate POR condition ... - u16 xMainStorePreserved:1; // Main Storage is preserved ... - u16 xRsvd07:13; // Reserved ... - u16 xIplSource:16; // Ipl source x1A-x1B - u8 xIplReason:8; // Reason for this IPL x1C-x1C - u8 xRsvd08; // Reserved x1D-x1D - u16 xRsvd09; // Reserved x1E-x1F - u16 xSysBoxType; // System Box Type x20-x21 - u16 xSysProcType; // System Processor Type x22-x23 - u32 xRsvd10; // Reserved x24-x27 - u64 xRsvd11; // Reserved x28-x2F - u64 xRsvd12; // Reserved x30-x37 - u64 xRsvd13; // Reserved x38-x3F -}; - -extern struct ItIplParmsReal xItIplParmsReal; - -#endif /* _ITIPLPARMSREAL_H */ diff --git a/include/asm-ppc64/iSeries/ItSpCommArea.h b/include/asm-ppc64/iSeries/ItSpCommArea.h deleted file mode 100644 --- a/include/asm-ppc64/iSeries/ItSpCommArea.h +++ /dev/null @@ -1,37 +0,0 @@ -/* - * ItSpCommArea.h - * Copyright (C) 2001 Mike Corrigan 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 _ITSPCOMMAREA_H -#define _ITSPCOMMAREA_H - - -struct SpCommArea { - u32 xDesc; // Descriptor (only in new formats) 000-003 - u8 xFormat; // Format (only in new formats) 004-004 - u8 xRsvd1[11]; // Reserved 005-00F - u64 xRawTbAtIplStart; // Raw HW TB value when IPL is started 010-017 - u64 xRawTodAtIplStart; // Raw HW TOD value when IPL is started 018-01F - u64 xBcdTimeAtIplStart; // BCD time when IPL is started 020-027 - u64 xBcdTimeAtOsStart; // BCD time when OS passed control 028-02F - u8 xRsvd2[80]; // Reserved 030-07F -}; - -extern struct SpCommArea xSpCommArea; - -#endif /* _ITSPCOMMAREA_H */ diff --git a/include/asm-ppc64/iSeries/ItVpdAreas.h b/include/asm-ppc64/iSeries/ItVpdAreas.h deleted file mode 100644 --- a/include/asm-ppc64/iSeries/ItVpdAreas.h +++ /dev/null @@ -1,89 +0,0 @@ -/* - * ItVpdAreas.h - * Copyright (C) 2001 Mike Corrigan 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 _ITVPDAREAS_H -#define _ITVPDAREAS_H - -/* - * This file defines the address and length of all of the VPD area passed to - * the OS from PLIC (most of which start from the SP). - */ - -#include - -/* VPD Entry index is carved in stone - cannot be changed (easily). */ -#define ItVpdCecVpd 0 -#define ItVpdDynamicSpace 1 -#define ItVpdExtVpd 2 -#define ItVpdExtVpdOnPanel 3 -#define ItVpdFirstPaca 4 -#define ItVpdIoVpd 5 -#define ItVpdIplParms 6 -#define ItVpdMsVpd 7 -#define ItVpdPanelVpd 8 -#define ItVpdLpNaca 9 -#define ItVpdBackplaneAndMaybeClockCardVpd 10 -#define ItVpdRecoveryLogBuffer 11 -#define ItVpdSpCommArea 12 -#define ItVpdSpLogBuffer 13 -#define ItVpdSpLogBufferSave 14 -#define ItVpdSpCardVpd 15 -#define ItVpdFirstProcVpd 16 -#define ItVpdApModelVpd 17 -#define ItVpdClockCardVpd 18 -#define ItVpdBusExtCardVpd 19 -#define ItVpdProcCapacityVpd 20 -#define ItVpdInteractiveCapacityVpd 21 -#define ItVpdFirstSlotLabel 22 -#define ItVpdFirstLpQueue 23 -#define ItVpdFirstL3CacheVpd 24 -#define ItVpdFirstProcFruVpd 25 - -#define ItVpdMaxEntries 26 - -#define ItDmaMaxEntries 10 - -#define ItVpdAreasMaxSlotLabels 192 - - -struct ItVpdAreas { - u32 xSlicDesc; // Descriptor 000-003 - u16 xSlicSize; // Size of this control block 004-005 - u16 xPlicAdjustVpdLens:1; // Flag to indicate new interface006-007 - u16 xRsvd1:15; // Reserved bits ... - u16 xSlicVpdEntries; // Number of VPD entries 008-009 - u16 xSlicDmaEntries; // Number of DMA entries 00A-00B - u16 xSlicMaxLogicalProcs; // Maximum logical processors 00C-00D - u16 xSlicMaxPhysicalProcs; // Maximum physical processors 00E-00F - u16 xSlicDmaToksOffset; // Offset into this of array 010-011 - u16 xSlicVpdAdrsOffset; // Offset into this of array 012-013 - u16 xSlicDmaLensOffset; // Offset into this of array 014-015 - u16 xSlicVpdLensOffset; // Offset into this of array 016-017 - u16 xSlicMaxSlotLabels; // Maximum number of slot labels018-019 - u16 xSlicMaxLpQueues; // Maximum number of LP Queues 01A-01B - u8 xRsvd2[4]; // Reserved 01C-01F - u64 xRsvd3[12]; // Reserved 020-07F - u32 xPlicDmaLens[ItDmaMaxEntries];// Array of DMA lengths 080-0A7 - u32 xPlicDmaToks[ItDmaMaxEntries];// Array of DMA tokens 0A8-0CF - u32 xSlicVpdLens[ItVpdMaxEntries];// Array of VPD lengths 0D0-12F - void *xSlicVpdAdrs[ItVpdMaxEntries];// Array of VPD buffers 130-1EF -}; - -extern struct ItVpdAreas itVpdAreas; - -#endif /* _ITVPDAREAS_H */ diff --git a/include/asm-ppc64/iSeries/iSeries_irq.h b/include/asm-ppc64/iSeries/iSeries_irq.h deleted file mode 100644 --- a/include/asm-ppc64/iSeries/iSeries_irq.h +++ /dev/null @@ -1,8 +0,0 @@ -#ifndef __ISERIES_IRQ_H__ -#define __ISERIES_IRQ_H__ - -extern void iSeries_init_IRQ(void); -extern int iSeries_allocate_IRQ(HvBusNumber, HvSubBusNumber, HvAgentId); -extern void iSeries_activate_IRQs(void); - -#endif /* __ISERIES_IRQ_H__ */ From sfr at canb.auug.org.au Fri Sep 30 23:52:34 2005 From: sfr at canb.auug.org.au (Stephen Rothwell) Date: Fri, 30 Sep 2005 23:52:34 +1000 Subject: [PATCH 3/9] powerpc: remove old vector.S files In-Reply-To: <20050930233602.138b6e27.sfr@canb.auug.org.au> References: <20050930233602.138b6e27.sfr@canb.auug.org.au> Message-ID: <20050930235234.2c07aeec.sfr@canb.auug.org.au> Update old kernel/Makefiles to cope Signed-off-by: Stephen Rothwell --- arch/ppc/kernel/Makefile | 1 arch/ppc/kernel/vector.S | 217 -------------------------------------------- arch/ppc64/kernel/Makefile | 1 arch/ppc64/kernel/vector.S | 172 ----------------------------------- 4 files changed, 2 insertions(+), 389 deletions(-) delete mode 100644 arch/ppc/kernel/vector.S delete mode 100644 arch/ppc64/kernel/vector.S -- Cheers, Stephen Rothwell sfr at canb.auug.org.au http://www.canb.auug.org.au/~sfr/ dcff1b170b43d9b8cb83e275cb3451dfd261c23e diff --git a/arch/ppc/kernel/Makefile b/arch/ppc/kernel/Makefile --- a/arch/ppc/kernel/Makefile +++ b/arch/ppc/kernel/Makefile @@ -38,6 +38,7 @@ endif # These are here while we do the architecture merge vecemu-y += ../../powerpc/kernel/vecemu.o +vector-y += ../../powerpc/kernel/vector.o else obj-y := entry.o irq.o idle.o time.o misc.o \ diff --git a/arch/ppc/kernel/vector.S b/arch/ppc/kernel/vector.S deleted file mode 100644 --- a/arch/ppc/kernel/vector.S +++ /dev/null @@ -1,217 +0,0 @@ -#include -#include - -/* - * The routines below are in assembler so we can closely control the - * usage of floating-point registers. These routines must be called - * with preempt disabled. - */ - .data -fpzero: - .long 0 -fpone: - .long 0x3f800000 /* 1.0 in single-precision FP */ -fphalf: - .long 0x3f000000 /* 0.5 in single-precision FP */ - - .text -/* - * Internal routine to enable floating point and set FPSCR to 0. - * Don't call it from C; it doesn't use the normal calling convention. - */ -fpenable: - mfmsr r10 - ori r11,r10,MSR_FP - mtmsr r11 - isync - stfd fr0,24(r1) - stfd fr1,16(r1) - stfd fr31,8(r1) - lis r11,fpzero at ha - mffs fr31 - lfs fr1,fpzero at l(r11) - mtfsf 0xff,fr1 - blr - -fpdisable: - mtfsf 0xff,fr31 - lfd fr31,8(r1) - lfd fr1,16(r1) - lfd fr0,24(r1) - mtmsr r10 - isync - blr - -/* - * Vector add, floating point. - */ - .globl vaddfp -vaddfp: - stwu r1,-32(r1) - mflr r0 - stw r0,36(r1) - bl fpenable - li r0,4 - mtctr r0 - li r6,0 -1: lfsx fr0,r4,r6 - lfsx fr1,r5,r6 - fadds fr0,fr0,fr1 - stfsx fr0,r3,r6 - addi r6,r6,4 - bdnz 1b - bl fpdisable - lwz r0,36(r1) - mtlr r0 - addi r1,r1,32 - blr - -/* - * Vector subtract, floating point. - */ - .globl vsubfp -vsubfp: - stwu r1,-32(r1) - mflr r0 - stw r0,36(r1) - bl fpenable - li r0,4 - mtctr r0 - li r6,0 -1: lfsx fr0,r4,r6 - lfsx fr1,r5,r6 - fsubs fr0,fr0,fr1 - stfsx fr0,r3,r6 - addi r6,r6,4 - bdnz 1b - bl fpdisable - lwz r0,36(r1) - mtlr r0 - addi r1,r1,32 - blr - -/* - * Vector multiply and add, floating point. - */ - .globl vmaddfp -vmaddfp: - stwu r1,-48(r1) - mflr r0 - stw r0,52(r1) - bl fpenable - stfd fr2,32(r1) - li r0,4 - mtctr r0 - li r7,0 -1: lfsx fr0,r4,r7 - lfsx fr1,r5,r7 - lfsx fr2,r6,r7 - fmadds fr0,fr0,fr2,fr1 - stfsx fr0,r3,r7 - addi r7,r7,4 - bdnz 1b - lfd fr2,32(r1) - bl fpdisable - lwz r0,52(r1) - mtlr r0 - addi r1,r1,48 - blr - -/* - * Vector negative multiply and subtract, floating point. - */ - .globl vnmsubfp -vnmsubfp: - stwu r1,-48(r1) - mflr r0 - stw r0,52(r1) - bl fpenable - stfd fr2,32(r1) - li r0,4 - mtctr r0 - li r7,0 -1: lfsx fr0,r4,r7 - lfsx fr1,r5,r7 - lfsx fr2,r6,r7 - fnmsubs fr0,fr0,fr2,fr1 - stfsx fr0,r3,r7 - addi r7,r7,4 - bdnz 1b - lfd fr2,32(r1) - bl fpdisable - lwz r0,52(r1) - mtlr r0 - addi r1,r1,48 - blr - -/* - * Vector reciprocal estimate. We just compute 1.0/x. - * r3 -> destination, r4 -> source. - */ - .globl vrefp -vrefp: - stwu r1,-32(r1) - mflr r0 - stw r0,36(r1) - bl fpenable - lis r9,fpone at ha - li r0,4 - lfs fr1,fpone at l(r9) - mtctr r0 - li r6,0 -1: lfsx fr0,r4,r6 - fdivs fr0,fr1,fr0 - stfsx fr0,r3,r6 - addi r6,r6,4 - bdnz 1b - bl fpdisable - lwz r0,36(r1) - mtlr r0 - addi r1,r1,32 - blr - -/* - * Vector reciprocal square-root estimate, floating point. - * We use the frsqrte instruction for the initial estimate followed - * by 2 iterations of Newton-Raphson to get sufficient accuracy. - * r3 -> destination, r4 -> source. - */ - .globl vrsqrtefp -vrsqrtefp: - stwu r1,-48(r1) - mflr r0 - stw r0,52(r1) - bl fpenable - stfd fr2,32(r1) - stfd fr3,40(r1) - stfd fr4,48(r1) - stfd fr5,56(r1) - lis r9,fpone at ha - lis r8,fphalf at ha - li r0,4 - lfs fr4,fpone at l(r9) - lfs fr5,fphalf at l(r8) - mtctr r0 - li r6,0 -1: lfsx fr0,r4,r6 - frsqrte fr1,fr0 /* r = frsqrte(s) */ - fmuls fr3,fr1,fr0 /* r * s */ - fmuls fr2,fr1,fr5 /* r * 0.5 */ - fnmsubs fr3,fr1,fr3,fr4 /* 1 - s * r * r */ - fmadds fr1,fr2,fr3,fr1 /* r = r + 0.5 * r * (1 - s * r * r) */ - fmuls fr3,fr1,fr0 /* r * s */ - fmuls fr2,fr1,fr5 /* r * 0.5 */ - fnmsubs fr3,fr1,fr3,fr4 /* 1 - s * r * r */ - fmadds fr1,fr2,fr3,fr1 /* r = r + 0.5 * r * (1 - s * r * r) */ - stfsx fr1,r3,r6 - addi r6,r6,4 - bdnz 1b - lfd fr5,56(r1) - lfd fr4,48(r1) - lfd fr3,40(r1) - lfd fr2,32(r1) - bl fpdisable - lwz r0,36(r1) - mtlr r0 - addi r1,r1,32 - blr diff --git a/arch/ppc64/kernel/Makefile b/arch/ppc64/kernel/Makefile --- a/arch/ppc64/kernel/Makefile +++ b/arch/ppc64/kernel/Makefile @@ -76,3 +76,4 @@ endif # These are here while we do the architecture merge vecemu-y += ../../powerpc/kernel/vecemu.o +vector-y += ../../powerpc/kernel/vector.o diff --git a/arch/ppc64/kernel/vector.S b/arch/ppc64/kernel/vector.S deleted file mode 100644 --- a/arch/ppc64/kernel/vector.S +++ /dev/null @@ -1,172 +0,0 @@ -#include -#include - -/* - * The routines below are in assembler so we can closely control the - * usage of floating-point registers. These routines must be called - * with preempt disabled. - */ - .section ".toc","aw" -fpzero: - .tc FD_0_0[TC],0 -fpone: - .tc FD_3ff00000_0[TC],0x3ff0000000000000 /* 1.0 */ -fphalf: - .tc FD_3fe00000_0[TC],0x3fe0000000000000 /* 0.5 */ - - .text -/* - * Internal routine to enable floating point and set FPSCR to 0. - * Don't call it from C; it doesn't use the normal calling convention. - */ -fpenable: - mfmsr r10 - ori r11,r10,MSR_FP - mtmsr r11 - isync - stfd fr31,-8(r1) - stfd fr0,-16(r1) - stfd fr1,-24(r1) - mffs fr31 - lfd fr1,fpzero at toc(r2) - mtfsf 0xff,fr1 - blr - -fpdisable: - mtlr r12 - mtfsf 0xff,fr31 - lfd fr1,-24(r1) - lfd fr0,-16(r1) - lfd fr31,-8(r1) - mtmsr r10 - isync - blr - -/* - * Vector add, floating point. - */ -_GLOBAL(vaddfp) - mflr r12 - bl fpenable - li r0,4 - mtctr r0 - li r6,0 -1: lfsx fr0,r4,r6 - lfsx fr1,r5,r6 - fadds fr0,fr0,fr1 - stfsx fr0,r3,r6 - addi r6,r6,4 - bdnz 1b - b fpdisable - -/* - * Vector subtract, floating point. - */ -_GLOBAL(vsubfp) - mflr r12 - bl fpenable - li r0,4 - mtctr r0 - li r6,0 -1: lfsx fr0,r4,r6 - lfsx fr1,r5,r6 - fsubs fr0,fr0,fr1 - stfsx fr0,r3,r6 - addi r6,r6,4 - bdnz 1b - b fpdisable - -/* - * Vector multiply and add, floating point. - */ -_GLOBAL(vmaddfp) - mflr r12 - bl fpenable - stfd fr2,-32(r1) - li r0,4 - mtctr r0 - li r7,0 -1: lfsx fr0,r4,r7 - lfsx fr1,r5,r7 - lfsx fr2,r6,r7 - fmadds fr0,fr0,fr2,fr1 - stfsx fr0,r3,r7 - addi r7,r7,4 - bdnz 1b - lfd fr2,-32(r1) - b fpdisable - -/* - * Vector negative multiply and subtract, floating point. - */ -_GLOBAL(vnmsubfp) - mflr r12 - bl fpenable - stfd fr2,-32(r1) - li r0,4 - mtctr r0 - li r7,0 -1: lfsx fr0,r4,r7 - lfsx fr1,r5,r7 - lfsx fr2,r6,r7 - fnmsubs fr0,fr0,fr2,fr1 - stfsx fr0,r3,r7 - addi r7,r7,4 - bdnz 1b - lfd fr2,-32(r1) - b fpdisable - -/* - * Vector reciprocal estimate. We just compute 1.0/x. - * r3 -> destination, r4 -> source. - */ -_GLOBAL(vrefp) - mflr r12 - bl fpenable - li r0,4 - lfd fr1,fpone at toc(r2) - mtctr r0 - li r6,0 -1: lfsx fr0,r4,r6 - fdivs fr0,fr1,fr0 - stfsx fr0,r3,r6 - addi r6,r6,4 - bdnz 1b - b fpdisable - -/* - * Vector reciprocal square-root estimate, floating point. - * We use the frsqrte instruction for the initial estimate followed - * by 2 iterations of Newton-Raphson to get sufficient accuracy. - * r3 -> destination, r4 -> source. - */ -_GLOBAL(vrsqrtefp) - mflr r12 - bl fpenable - stfd fr2,-32(r1) - stfd fr3,-40(r1) - stfd fr4,-48(r1) - stfd fr5,-56(r1) - li r0,4 - lfd fr4,fpone at toc(r2) - lfd fr5,fphalf at toc(r2) - mtctr r0 - li r6,0 -1: lfsx fr0,r4,r6 - frsqrte fr1,fr0 /* r = frsqrte(s) */ - fmuls fr3,fr1,fr0 /* r * s */ - fmuls fr2,fr1,fr5 /* r * 0.5 */ - fnmsubs fr3,fr1,fr3,fr4 /* 1 - s * r * r */ - fmadds fr1,fr2,fr3,fr1 /* r = r + 0.5 * r * (1 - s * r * r) */ - fmuls fr3,fr1,fr0 /* r * s */ - fmuls fr2,fr1,fr5 /* r * 0.5 */ - fnmsubs fr3,fr1,fr3,fr4 /* 1 - s * r * r */ - fmadds fr1,fr2,fr3,fr1 /* r = r + 0.5 * r * (1 - s * r * r) */ - stfsx fr1,r3,r6 - addi r6,r6,4 - bdnz 1b - lfd fr5,-56(r1) - lfd fr4,-48(r1) - lfd fr3,-40(r1) - lfd fr2,-32(r1) - b fpdisable From sfr at canb.auug.org.au Fri Sep 30 23:55:17 2005 From: sfr at canb.auug.org.au (Stephen Rothwell) Date: Fri, 30 Sep 2005 23:55:17 +1000 Subject: [PATCH 4/9] powerpc: more cleanup of powerpc/kernel In-Reply-To: <20050930233602.138b6e27.sfr@canb.auug.org.au> References: <20050930233602.138b6e27.sfr@canb.auug.org.au> Message-ID: <20050930235517.47c497fb.sfr@canb.auug.org.au> Update head_64.S from arch/ppc64 Remove arch/ppc/kernel/fpu.S Signed-off-by: Stephen Rothwell --- arch/powerpc/kernel/head_64.S | 9 ++- arch/ppc/kernel/Makefile | 1 arch/ppc/kernel/fpu.S | 133 ----------------------------------------- 3 files changed, 7 insertions(+), 136 deletions(-) delete mode 100644 arch/ppc/kernel/fpu.S -- Cheers, Stephen Rothwell sfr at canb.auug.org.au http://www.canb.auug.org.au/~sfr/ ee400b63f37120987bd12a2fada850c6212d7563 diff --git a/arch/powerpc/kernel/head_64.S b/arch/powerpc/kernel/head_64.S --- a/arch/powerpc/kernel/head_64.S +++ b/arch/powerpc/kernel/head_64.S @@ -1253,7 +1253,7 @@ unrecov_slb: * * On iSeries, the hypervisor must fill in at least one entry before * we get control (with relocate on). The address is give to the hv - * as a page number (see xLparMap in LparData.c), so this must be at a + * as a page number (see xLparMap in lpardata.c), so this must be at a * fixed address (the linker can't compute (u64)&initial_stab >> * PAGE_SHIFT). */ @@ -1364,6 +1364,7 @@ _STATIC(__start_initialization_iSeries) addi r2,r2,0x4000 bl .iSeries_early_setup + bl .early_setup /* relocation is on at this point */ @@ -1970,20 +1971,22 @@ _GLOBAL(hmt_start_secondary) blr #endif -#if defined(CONFIG_KEXEC) || (defined(CONFIG_SMP) && !defined(CONFIG_PPC_ISERIES)) +#if defined(CONFIG_KEXEC) || defined(CONFIG_SMP) _GLOBAL(smp_release_cpus) /* All secondary cpus are spinning on a common * spinloop, release them all now so they can start * to spin on their individual paca spinloops. * For non SMP kernels, the secondary cpus never * get out of the common spinloop. + * XXX This does nothing useful on iSeries, secondaries are + * already waiting on their paca. */ li r3,1 LOADADDR(r5,__secondary_hold_spinloop) std r3,0(r5) sync blr -#endif /* CONFIG_SMP && !CONFIG_PPC_ISERIES */ +#endif /* CONFIG_SMP */ /* diff --git a/arch/ppc/kernel/Makefile b/arch/ppc/kernel/Makefile --- a/arch/ppc/kernel/Makefile +++ b/arch/ppc/kernel/Makefile @@ -39,6 +39,7 @@ endif # These are here while we do the architecture merge vecemu-y += ../../powerpc/kernel/vecemu.o vector-y += ../../powerpc/kernel/vector.o +fpu-y += ../../powerpc/kernel/fpu.o else obj-y := entry.o irq.o idle.o time.o misc.o \ diff --git a/arch/ppc/kernel/fpu.S b/arch/ppc/kernel/fpu.S deleted file mode 100644 --- a/arch/ppc/kernel/fpu.S +++ /dev/null @@ -1,133 +0,0 @@ -/* - * FPU support code, moved here from head.S so that it can be used - * by chips which use other head-whatever.S files. - * - * 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 - -/* - * This task wants to use the FPU now. - * On UP, disable FP for the task which had the FPU previously, - * and save its floating-point registers in its thread_struct. - * Load up this task's FP registers from its thread_struct, - * enable the FPU for the current task and return to the task. - */ - .globl load_up_fpu -load_up_fpu: - mfmsr r5 - ori r5,r5,MSR_FP -#ifdef CONFIG_PPC64BRIDGE - clrldi r5,r5,1 /* turn off 64-bit mode */ -#endif /* CONFIG_PPC64BRIDGE */ - SYNC - MTMSRD(r5) /* enable use of fpu now */ - isync -/* - * For SMP, we don't do lazy FPU switching because it just gets too - * horrendously complex, especially when a task switches from one CPU - * to another. Instead we call giveup_fpu in switch_to. - */ -#ifndef CONFIG_SMP - tophys(r6,0) /* get __pa constant */ - addis r3,r6,last_task_used_math at ha - lwz r4,last_task_used_math at l(r3) - cmpwi 0,r4,0 - beq 1f - add r4,r4,r6 - addi r4,r4,THREAD /* want last_task_used_math->thread */ - SAVE_32FPRS(0, r4) - mffs fr0 - stfd fr0,THREAD_FPSCR-4(r4) - lwz r5,PT_REGS(r4) - add r5,r5,r6 - lwz r4,_MSR-STACK_FRAME_OVERHEAD(r5) - li r10,MSR_FP|MSR_FE0|MSR_FE1 - andc r4,r4,r10 /* disable FP for previous task */ - stw r4,_MSR-STACK_FRAME_OVERHEAD(r5) -1: -#endif /* CONFIG_SMP */ - /* enable use of FP after return */ - mfspr r5,SPRN_SPRG3 /* current task's THREAD (phys) */ - lwz r4,THREAD_FPEXC_MODE(r5) - ori r9,r9,MSR_FP /* enable FP for current */ - or r9,r9,r4 - lfd fr0,THREAD_FPSCR-4(r5) - mtfsf 0xff,fr0 - REST_32FPRS(0, r5) -#ifndef CONFIG_SMP - subi r4,r5,THREAD - sub r4,r4,r6 - stw r4,last_task_used_math at l(r3) -#endif /* CONFIG_SMP */ - /* restore registers and return */ - /* we haven't used ctr or xer or lr */ - b fast_exception_return - -/* - * FP unavailable trap from kernel - print a message, but let - * the task use FP in the kernel until it returns to user mode. - */ - .globl KernelFP -KernelFP: - lwz r3,_MSR(r1) - ori r3,r3,MSR_FP - stw r3,_MSR(r1) /* enable use of FP after return */ - lis r3,86f at h - ori r3,r3,86f at l - mr r4,r2 /* current */ - lwz r5,_NIP(r1) - bl printk - b ret_from_except -86: .string "floating point used in kernel (task=%p, pc=%x)\n" - .align 4,0 - -/* - * giveup_fpu(tsk) - * Disable FP for the task given as the argument, - * and save the floating-point registers in its thread_struct. - * Enables the FPU for use in the kernel on return. - */ - .globl giveup_fpu -giveup_fpu: - mfmsr r5 - ori r5,r5,MSR_FP - SYNC_601 - ISYNC_601 - MTMSRD(r5) /* enable use of fpu now */ - SYNC_601 - isync - cmpwi 0,r3,0 - beqlr- /* if no previous owner, done */ - addi r3,r3,THREAD /* want THREAD of task */ - lwz r5,PT_REGS(r3) - cmpwi 0,r5,0 - SAVE_32FPRS(0, r3) - mffs fr0 - stfd fr0,THREAD_FPSCR-4(r3) - beq 1f - lwz r4,_MSR-STACK_FRAME_OVERHEAD(r5) - li r3,MSR_FP|MSR_FE0|MSR_FE1 - andc r4,r4,r3 /* disable FP for previous task */ - stw r4,_MSR-STACK_FRAME_OVERHEAD(r5) -1: -#ifndef CONFIG_SMP - li r5,0 - lis r4,last_task_used_math at ha - stw r5,last_task_used_math at l(r4) -#endif /* CONFIG_SMP */ - blr From sfr at canb.auug.org.au Fri Sep 30 23:56:53 2005 From: sfr at canb.auug.org.au (Stephen Rothwell) Date: Fri, 30 Sep 2005 23:56:53 +1000 Subject: [PATCH 5/9] powerpc: Move lparmap.c to powerpc/platforms In-Reply-To: <20050930233602.138b6e27.sfr@canb.auug.org.au> References: <20050930233602.138b6e27.sfr@canb.auug.org.au> Message-ID: <20050930235653.28c52e00.sfr@canb.auug.org.au> Signed-off-by: Stephen Rothwell --- arch/powerpc/platforms/iseries/lparmap.c | 31 ++++++++++++++++++++++++++++++ arch/ppc64/kernel/Makefile | 4 ++-- arch/ppc64/kernel/lparmap.c | 31 ------------------------------ 3 files changed, 33 insertions(+), 33 deletions(-) create mode 100644 arch/powerpc/platforms/iseries/lparmap.c delete mode 100644 arch/ppc64/kernel/lparmap.c -- Cheers, Stephen Rothwell sfr at canb.auug.org.au http://www.canb.auug.org.au/~sfr/ d96024c688b59d4d1e60dbb0e226964eb758aa01 diff --git a/arch/powerpc/platforms/iseries/lparmap.c b/arch/powerpc/platforms/iseries/lparmap.c new file mode 100644 --- /dev/null +++ b/arch/powerpc/platforms/iseries/lparmap.c @@ -0,0 +1,31 @@ +/* + * Copyright (C) 2005 Stephen Rothwell 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 + +const struct LparMap __attribute__((__section__(".text"))) xLparMap = { + .xNumberEsids = HvEsidsToMap, + .xNumberRanges = HvRangesToMap, + .xSegmentTableOffs = STAB0_PAGE, + + .xEsids = { + { .xKernelEsid = GET_ESID(KERNELBASE), + .xKernelVsid = KERNEL_VSID(KERNELBASE), }, + { .xKernelEsid = GET_ESID(VMALLOCBASE), + .xKernelVsid = KERNEL_VSID(VMALLOCBASE), }, + }, + + .xRanges = { + { .xPages = HvPagesToMap, + .xOffset = 0, + .xVPN = KERNEL_VSID(KERNELBASE) << (SID_SHIFT - PAGE_SHIFT), + }, + }, +}; diff --git a/arch/ppc64/kernel/Makefile b/arch/ppc64/kernel/Makefile --- a/arch/ppc64/kernel/Makefile +++ b/arch/ppc64/kernel/Makefile @@ -70,8 +70,8 @@ obj-$(CONFIG_KPROBES) += kprobes.o CFLAGS_ioctl32.o += -Ifs/ ifeq ($(CONFIG_PPC_ISERIES),y) -arch/ppc64/kernel/head.o: arch/ppc64/kernel/lparmap.s -AFLAGS_head.o += -Iarch/ppc64/kernel +arch/ppc64/kernel/head.o: arch/powerpc/platforms/iseries/lparmap.s +AFLAGS_head.o += -Iarch/powerpc/platforms/iseries endif # These are here while we do the architecture merge diff --git a/arch/ppc64/kernel/lparmap.c b/arch/ppc64/kernel/lparmap.c deleted file mode 100644 --- a/arch/ppc64/kernel/lparmap.c +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright (C) 2005 Stephen Rothwell 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 - -const struct LparMap __attribute__((__section__(".text"))) xLparMap = { - .xNumberEsids = HvEsidsToMap, - .xNumberRanges = HvRangesToMap, - .xSegmentTableOffs = STAB0_PAGE, - - .xEsids = { - { .xKernelEsid = GET_ESID(KERNELBASE), - .xKernelVsid = KERNEL_VSID(KERNELBASE), }, - { .xKernelEsid = GET_ESID(VMALLOCBASE), - .xKernelVsid = KERNEL_VSID(VMALLOCBASE), }, - }, - - .xRanges = { - { .xPages = HvPagesToMap, - .xOffset = 0, - .xVPN = KERNEL_VSID(KERNELBASE) << (SID_SHIFT - PAGE_SHIFT), - }, - }, -};