Skip to content

Commit

Permalink
Merge branch 'merge' of git://git.kernel.org/pub/scm/linux/kernel/git…
Browse files Browse the repository at this point in the history
…/benh/powerpc

* 'merge' of git://git.kernel.org/pub/scm/linux/kernel/git/benh/powerpc:
  Fix build of cpm_uart due to core changes
  powerpc/8xx: Fix regression introduced by cache coherency rewrite
  powerpc/4xx: Fix erroneous xmon warning on PowerPC 4xx
  powerpc/mm: Fix 40x and 8xx vs. _PAGE_SPECIAL
  powerpc: Cleanup linker script using new linker script macros.
  powerpc: Fix ibm,client-architecture-support printout
  powerpc: Increase NODES_SHIFT on 64bit from 4 to 8
  powerpc/perf_counter: Fix vdso detection
  powerpc: Move 64bit heap above 1TB on machines with 1TB segments
  powerpc: Change archdata dma_data to a union
  powerpc: Rename get_dma_direct_offset get_dma_offset
  powerpc/mm: Remove duplicated #include
  powerpc/book3e-64: Remove duplicated #include
  powerpc: Check for unsupported relocs when using CONFIG_RELOCATABLE
  powerpc/pmc: Don't access lppaca on Book3E
  powerpc: kmalloc failure ignored in vio_build_iommu_table()
  hvc_console: Provide (un)locked version for hvc_resize()
  • Loading branch information
Linus Torvalds committed Sep 25, 2009
2 parents 06aab5a + 09dd3fc commit 8e44e43
Show file tree
Hide file tree
Showing 31 changed files with 222 additions and 65 deletions.
6 changes: 6 additions & 0 deletions arch/powerpc/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -385,9 +385,15 @@ config NUMA

config NODES_SHIFT
int
default "8" if PPC64
default "4"
depends on NEED_MULTIPLE_NODES

config MAX_ACTIVE_REGIONS
int
default "256" if PPC64
default "32"

config ARCH_SELECT_MEMORY_MODEL
def_bool y
depends on PPC64
Expand Down
11 changes: 11 additions & 0 deletions arch/powerpc/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,17 @@ PHONY += $(BOOT_TARGETS)

boot := arch/$(ARCH)/boot

ifeq ($(CONFIG_RELOCATABLE),y)
quiet_cmd_relocs_check = CALL $<
cmd_relocs_check = perl $< "$(OBJDUMP)" "$(obj)/vmlinux"

PHONY += relocs_check
relocs_check: arch/powerpc/relocs_check.pl vmlinux
$(call cmd,relocs_check)

zImage: relocs_check
endif

$(BOOT_TARGETS): vmlinux
$(Q)$(MAKE) ARCH=ppc64 $(build)=$(boot) $(patsubst %,$(boot)/%,$@)

Expand Down
11 changes: 10 additions & 1 deletion arch/powerpc/include/asm/device.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,16 @@ struct dev_archdata {

/* DMA operations on that device */
struct dma_map_ops *dma_ops;
void *dma_data;

/*
* When an iommu is in use, dma_data is used as a ptr to the base of the
* iommu_table. Otherwise, it is a simple numerical offset.
*/
union {
dma_addr_t dma_offset;
void *iommu_table_base;
} dma_data;

#ifdef CONFIG_SWIOTLB
dma_addr_t max_direct_dma_addr;
#endif
Expand Down
27 changes: 24 additions & 3 deletions arch/powerpc/include/asm/dma-mapping.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@ extern void *dma_direct_alloc_coherent(struct device *dev, size_t size,
extern void dma_direct_free_coherent(struct device *dev, size_t size,
void *vaddr, dma_addr_t dma_handle);

extern unsigned long get_dma_direct_offset(struct device *dev);

#ifdef CONFIG_NOT_COHERENT_CACHE
/*
Expand Down Expand Up @@ -90,6 +89,28 @@ static inline void set_dma_ops(struct device *dev, struct dma_map_ops *ops)
dev->archdata.dma_ops = ops;
}

/*
* get_dma_offset()
*
* Get the dma offset on configurations where the dma address can be determined
* from the physical address by looking at a simple offset. Direct dma and
* swiotlb use this function, but it is typically not used by implementations
* with an iommu.
*/
static inline dma_addr_t get_dma_offset(struct device *dev)
{
if (dev)
return dev->archdata.dma_data.dma_offset;

return PCI_DRAM_OFFSET;
}

static inline void set_dma_offset(struct device *dev, dma_addr_t off)
{
if (dev)
dev->archdata.dma_data.dma_offset = off;
}

/* this will be removed soon */
#define flush_write_buffers()

Expand Down Expand Up @@ -181,12 +202,12 @@ static inline bool dma_capable(struct device *dev, dma_addr_t addr, size_t size)

static inline dma_addr_t phys_to_dma(struct device *dev, phys_addr_t paddr)
{
return paddr + get_dma_direct_offset(dev);
return paddr + get_dma_offset(dev);
}

static inline phys_addr_t dma_to_phys(struct device *dev, dma_addr_t daddr)
{
return daddr - get_dma_direct_offset(dev);
return daddr - get_dma_offset(dev);
}

#define dma_alloc_noncoherent(d, s, h, f) dma_alloc_coherent(d, s, h, f)
Expand Down
10 changes: 10 additions & 0 deletions arch/powerpc/include/asm/iommu.h
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,16 @@ struct iommu_table {

struct scatterlist;

static inline void set_iommu_table_base(struct device *dev, void *base)
{
dev->archdata.dma_data.iommu_table_base = base;
}

static inline void *get_iommu_table_base(struct device *dev)
{
return dev->archdata.dma_data.iommu_table_base;
}

/* Frees table for an individual device node */
extern void iommu_free_table(struct iommu_table *tbl, const char *node_name);

Expand Down
2 changes: 1 addition & 1 deletion arch/powerpc/include/asm/pmc.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ int reserve_pmc_hardware(perf_irq_t new_perf_irq);
void release_pmc_hardware(void);
void ppc_enable_pmcs(void);

#ifdef CONFIG_PPC64
#ifdef CONFIG_PPC_BOOK3S_64
#include <asm/lppaca.h>

static inline void ppc_set_pmu_inuse(int inuse)
Expand Down
1 change: 1 addition & 0 deletions arch/powerpc/include/asm/pte-40x.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@
#define _PAGE_NO_CACHE 0x004 /* I: caching is inhibited */
#define _PAGE_WRITETHRU 0x008 /* W: caching is write-through */
#define _PAGE_USER 0x010 /* matches one of the zone permission bits */
#define _PAGE_SPECIAL 0x020 /* software: Special page */
#define _PAGE_RW 0x040 /* software: Writes permitted */
#define _PAGE_DIRTY 0x080 /* software: dirty page */
#define _PAGE_HWWRITE 0x100 /* hardware: Dirty & RW, set in exception */
Expand Down
1 change: 1 addition & 0 deletions arch/powerpc/include/asm/pte-8xx.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
#define _PAGE_FILE 0x0002 /* when !present: nonlinear file mapping */
#define _PAGE_NO_CACHE 0x0002 /* I: cache inhibit */
#define _PAGE_SHARED 0x0004 /* No ASID (context) compare */
#define _PAGE_SPECIAL 0x0008 /* SW entry, forced to 0 by the TLB miss */

/* These five software bits must be masked out when the entry is loaded
* into the TLB.
Expand Down
5 changes: 0 additions & 5 deletions arch/powerpc/include/asm/pte-common.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,6 @@
#ifndef _PAGE_WRITETHRU
#define _PAGE_WRITETHRU 0
#endif
#ifndef _PAGE_SPECIAL
#define _PAGE_SPECIAL 0
#endif
#ifndef _PAGE_4K_PFN
#define _PAGE_4K_PFN 0
#endif
Expand Down Expand Up @@ -179,7 +176,5 @@ extern unsigned long bad_call_to_PMD_PAGE_SIZE(void);
#define HAVE_PAGE_AGP

/* Advertise support for _PAGE_SPECIAL */
#ifdef _PAGE_SPECIAL
#define __HAVE_ARCH_PTE_SPECIAL
#endif

16 changes: 8 additions & 8 deletions arch/powerpc/kernel/dma-iommu.c
Original file line number Diff line number Diff line change
Expand Up @@ -18,15 +18,15 @@
static void *dma_iommu_alloc_coherent(struct device *dev, size_t size,
dma_addr_t *dma_handle, gfp_t flag)
{
return iommu_alloc_coherent(dev, dev->archdata.dma_data, size,
return iommu_alloc_coherent(dev, get_iommu_table_base(dev), size,
dma_handle, device_to_mask(dev), flag,
dev_to_node(dev));
}

static void dma_iommu_free_coherent(struct device *dev, size_t size,
void *vaddr, dma_addr_t dma_handle)
{
iommu_free_coherent(dev->archdata.dma_data, size, vaddr, dma_handle);
iommu_free_coherent(get_iommu_table_base(dev), size, vaddr, dma_handle);
}

/* Creates TCEs for a user provided buffer. The user buffer must be
Expand All @@ -39,16 +39,16 @@ static dma_addr_t dma_iommu_map_page(struct device *dev, struct page *page,
enum dma_data_direction direction,
struct dma_attrs *attrs)
{
return iommu_map_page(dev, dev->archdata.dma_data, page, offset, size,
device_to_mask(dev), direction, attrs);
return iommu_map_page(dev, get_iommu_table_base(dev), page, offset,
size, device_to_mask(dev), direction, attrs);
}


static void dma_iommu_unmap_page(struct device *dev, dma_addr_t dma_handle,
size_t size, enum dma_data_direction direction,
struct dma_attrs *attrs)
{
iommu_unmap_page(dev->archdata.dma_data, dma_handle, size, direction,
iommu_unmap_page(get_iommu_table_base(dev), dma_handle, size, direction,
attrs);
}

Expand All @@ -57,22 +57,22 @@ static int dma_iommu_map_sg(struct device *dev, struct scatterlist *sglist,
int nelems, enum dma_data_direction direction,
struct dma_attrs *attrs)
{
return iommu_map_sg(dev, dev->archdata.dma_data, sglist, nelems,
return iommu_map_sg(dev, get_iommu_table_base(dev), sglist, nelems,
device_to_mask(dev), direction, attrs);
}

static void dma_iommu_unmap_sg(struct device *dev, struct scatterlist *sglist,
int nelems, enum dma_data_direction direction,
struct dma_attrs *attrs)
{
iommu_unmap_sg(dev->archdata.dma_data, sglist, nelems, direction,
iommu_unmap_sg(get_iommu_table_base(dev), sglist, nelems, direction,
attrs);
}

/* We support DMA to/from any memory page via the iommu */
static int dma_iommu_dma_supported(struct device *dev, u64 mask)
{
struct iommu_table *tbl = dev->archdata.dma_data;
struct iommu_table *tbl = get_iommu_table_base(dev);

if (!tbl || tbl->it_offset > mask) {
printk(KERN_INFO
Expand Down
15 changes: 4 additions & 11 deletions arch/powerpc/kernel/dma.c
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,6 @@
* default the offset is PCI_DRAM_OFFSET.
*/

unsigned long get_dma_direct_offset(struct device *dev)
{
if (dev)
return (unsigned long)dev->archdata.dma_data;

return PCI_DRAM_OFFSET;
}

void *dma_direct_alloc_coherent(struct device *dev, size_t size,
dma_addr_t *dma_handle, gfp_t flag)
Expand All @@ -37,7 +30,7 @@ void *dma_direct_alloc_coherent(struct device *dev, size_t size,
ret = __dma_alloc_coherent(dev, size, dma_handle, flag);
if (ret == NULL)
return NULL;
*dma_handle += get_dma_direct_offset(dev);
*dma_handle += get_dma_offset(dev);
return ret;
#else
struct page *page;
Expand All @@ -51,7 +44,7 @@ void *dma_direct_alloc_coherent(struct device *dev, size_t size,
return NULL;
ret = page_address(page);
memset(ret, 0, size);
*dma_handle = virt_to_abs(ret) + get_dma_direct_offset(dev);
*dma_handle = virt_to_abs(ret) + get_dma_offset(dev);

return ret;
#endif
Expand All @@ -75,7 +68,7 @@ static int dma_direct_map_sg(struct device *dev, struct scatterlist *sgl,
int i;

for_each_sg(sgl, sg, nents, i) {
sg->dma_address = sg_phys(sg) + get_dma_direct_offset(dev);
sg->dma_address = sg_phys(sg) + get_dma_offset(dev);
sg->dma_length = sg->length;
__dma_sync_page(sg_page(sg), sg->offset, sg->length, direction);
}
Expand Down Expand Up @@ -110,7 +103,7 @@ static inline dma_addr_t dma_direct_map_page(struct device *dev,
{
BUG_ON(dir == DMA_NONE);
__dma_sync_page(page, offset, size, dir);
return page_to_phys(page) + offset + get_dma_direct_offset(dev);
return page_to_phys(page) + offset + get_dma_offset(dev);
}

static inline void dma_direct_unmap_page(struct device *dev,
Expand Down
1 change: 0 additions & 1 deletion arch/powerpc/kernel/exceptions-64e.S
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@
#include <asm/cputable.h>
#include <asm/setup.h>
#include <asm/thread_info.h>
#include <asm/reg.h>
#include <asm/exception-64e.h>
#include <asm/bug.h>
#include <asm/irqflags.h>
Expand Down
2 changes: 1 addition & 1 deletion arch/powerpc/kernel/pci-common.c
Original file line number Diff line number Diff line change
Expand Up @@ -1117,7 +1117,7 @@ void __devinit pcibios_setup_bus_devices(struct pci_bus *bus)

/* Hook up default DMA ops */
sd->dma_ops = pci_dma_ops;
sd->dma_data = (void *)PCI_DRAM_OFFSET;
set_dma_offset(&dev->dev, PCI_DRAM_OFFSET);

/* Additional platform DMA/iommu setup */
if (ppc_md.pci_dma_dev_setup)
Expand Down
17 changes: 16 additions & 1 deletion arch/powerpc/kernel/process.c
Original file line number Diff line number Diff line change
Expand Up @@ -1165,7 +1165,22 @@ static inline unsigned long brk_rnd(void)

unsigned long arch_randomize_brk(struct mm_struct *mm)
{
unsigned long ret = PAGE_ALIGN(mm->brk + brk_rnd());
unsigned long base = mm->brk;
unsigned long ret;

#ifdef CONFIG_PPC64
/*
* If we are using 1TB segments and we are allowed to randomise
* the heap, we can put it above 1TB so it is backed by a 1TB
* segment. Otherwise the heap will be in the bottom 1TB
* which always uses 256MB segments and this may result in a
* performance penalty.
*/
if (!is_32bit_task() && (mmu_highuser_ssize == MMU_SEGSIZE_1T))
base = max_t(unsigned long, mm->brk, 1UL << SID_SHIFT_1T);
#endif

ret = PAGE_ALIGN(base + brk_rnd());

if (ret < mm->brk)
return mm->brk;
Expand Down
3 changes: 2 additions & 1 deletion arch/powerpc/kernel/prom_init.c
Original file line number Diff line number Diff line change
Expand Up @@ -800,7 +800,7 @@ static void __init prom_send_capabilities(void)
root = call_prom("open", 1, 1, ADDR("/"));
if (root != 0) {
/* try calling the ibm,client-architecture-support method */
prom_printf("Calling ibm,client-architecture...");
prom_printf("Calling ibm,client-architecture-support...");
if (call_prom_ret("call-method", 3, 2, &ret,
ADDR("ibm,client-architecture-support"),
root,
Expand All @@ -814,6 +814,7 @@ static void __init prom_send_capabilities(void)
return;
}
call_prom("close", 1, 0, root);
prom_printf(" not implemented\n");
}

/* no ibm,client-architecture-support call, try the old way */
Expand Down
14 changes: 10 additions & 4 deletions arch/powerpc/kernel/vdso.c
Original file line number Diff line number Diff line change
Expand Up @@ -240,6 +240,13 @@ int arch_setup_additional_pages(struct linux_binprm *bprm, int uses_interp)
goto fail_mmapsem;
}

/*
* Put vDSO base into mm struct. We need to do this before calling
* install_special_mapping or the perf counter mmap tracking code
* will fail to recognise it as a vDSO (since arch_vma_name fails).
*/
current->mm->context.vdso_base = vdso_base;

/*
* our vma flags don't have VM_WRITE so by default, the process isn't
* allowed to write those pages.
Expand All @@ -260,11 +267,10 @@ int arch_setup_additional_pages(struct linux_binprm *bprm, int uses_interp)
VM_MAYREAD|VM_MAYWRITE|VM_MAYEXEC|
VM_ALWAYSDUMP,
vdso_pagelist);
if (rc)
if (rc) {
current->mm->context.vdso_base = 0;
goto fail_mmapsem;

/* Put vDSO base into mm struct */
current->mm->context.vdso_base = vdso_base;
}

up_write(&mm->mmap_sem);
return 0;
Expand Down
4 changes: 3 additions & 1 deletion arch/powerpc/kernel/vio.c
Original file line number Diff line number Diff line change
Expand Up @@ -1054,6 +1054,8 @@ static struct iommu_table *vio_build_iommu_table(struct vio_dev *dev)
return NULL;

tbl = kmalloc(sizeof(*tbl), GFP_KERNEL);
if (tbl == NULL)
return NULL;

of_parse_dma_window(dev->dev.archdata.of_node, dma_window,
&tbl->it_index, &offset, &size);
Expand Down Expand Up @@ -1233,7 +1235,7 @@ struct vio_dev *vio_register_device_node(struct device_node *of_node)
vio_cmo_set_dma_ops(viodev);
else
viodev->dev.archdata.dma_ops = &dma_iommu_ops;
viodev->dev.archdata.dma_data = vio_build_iommu_table(viodev);
set_iommu_table_base(&viodev->dev, vio_build_iommu_table(viodev));
set_dev_node(&viodev->dev, of_node_to_nid(of_node));

/* init generic 'struct device' fields: */
Expand Down
Loading

0 comments on commit 8e44e43

Please sign in to comment.