Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 4b1c46a3 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
* 'merge' of git://git.kernel.org/pub/scm/linux/kernel/git/paulus/powerpc:
  [POWERPC] Make alignment exception always check exception table
  [POWERPC] Disallow kprobes on emulate_step and branch_taken
  [POWERPC] Make mmiowb's io_sync preempt safe
  [POWERPC] Make high hugepage areas preempt safe
  [POWERPC] Make current preempt-safe
  [POWERPC] qe_lib: qe_issue_cmd writes wrong value to CECDR
  [POWERPC] Use 4kB iommu pages even on 64kB-page systems
  [POWERPC] Fix oprofile support for e500 in arch/powerpc
  [POWERPC] Fix rmb() for e500-based machines it
  [POWERPC] Fix various offb issues
parents 30574b61 4393c4f6
Loading
Loading
Loading
Loading
+0 −1
Original line number Diff line number Diff line
@@ -38,7 +38,6 @@ obj-$(CONFIG_6xx) += idle_6xx.o l2cr_6xx.o cpu_setup_6xx.o
obj-$(CONFIG_TAU)		+= tau_6xx.o
obj32-$(CONFIG_SOFTWARE_SUSPEND) += swsusp_32.o
obj32-$(CONFIG_MODULES)		+= module_32.o
obj-$(CONFIG_E500)		+= perfmon_fsl_booke.o

ifeq ($(CONFIG_PPC_MERGE),y)

+1 −1
Original line number Diff line number Diff line
@@ -182,7 +182,7 @@ int btext_initialize(struct device_node *np)
	prop = get_property(np, "linux,bootx-linebytes", NULL);
	if (prop == NULL)
		prop = get_property(np, "linebytes", NULL);
	if (prop)
	if (prop && *prop != 0xffffffffu)
		pitch = *prop;
	if (pitch == 1)
		pitch = 0x1000;
+45 −32
Original line number Diff line number Diff line
@@ -47,6 +47,17 @@ static int novmerge = 0;
static int novmerge = 1;
#endif

static inline unsigned long iommu_num_pages(unsigned long vaddr,
					    unsigned long slen)
{
	unsigned long npages;

	npages = IOMMU_PAGE_ALIGN(vaddr + slen) - (vaddr & IOMMU_PAGE_MASK);
	npages >>= IOMMU_PAGE_SHIFT;

	return npages;
}

static int __init setup_iommu(char *str)
{
	if (!strcmp(str, "novmerge"))
@@ -178,10 +189,10 @@ static dma_addr_t iommu_alloc(struct iommu_table *tbl, void *page,
	}

	entry += tbl->it_offset;	/* Offset into real TCE table */
	ret = entry << PAGE_SHIFT;	/* Set the return dma address */
	ret = entry << IOMMU_PAGE_SHIFT;	/* Set the return dma address */

	/* Put the TCEs in the HW table */
	ppc_md.tce_build(tbl, entry, npages, (unsigned long)page & PAGE_MASK,
	ppc_md.tce_build(tbl, entry, npages, (unsigned long)page & IOMMU_PAGE_MASK,
			 direction);


@@ -203,7 +214,7 @@ static void __iommu_free(struct iommu_table *tbl, dma_addr_t dma_addr,
	unsigned long entry, free_entry;
	unsigned long i;

	entry = dma_addr >> PAGE_SHIFT;
	entry = dma_addr >> IOMMU_PAGE_SHIFT;
	free_entry = entry - tbl->it_offset;

	if (((free_entry + npages) > tbl->it_size) ||
@@ -270,7 +281,7 @@ int iommu_map_sg(struct device *dev, struct iommu_table *tbl,
	/* Init first segment length for backout at failure */
	outs->dma_length = 0;

	DBG("mapping %d elements:\n", nelems);
	DBG("sg mapping %d elements:\n", nelems);

	spin_lock_irqsave(&(tbl->it_lock), flags);

@@ -285,9 +296,8 @@ int iommu_map_sg(struct device *dev, struct iommu_table *tbl,
		}
		/* Allocate iommu entries for that segment */
		vaddr = (unsigned long)page_address(s->page) + s->offset;
		npages = PAGE_ALIGN(vaddr + slen) - (vaddr & PAGE_MASK);
		npages >>= PAGE_SHIFT;
		entry = iommu_range_alloc(tbl, npages, &handle, mask >> PAGE_SHIFT, 0);
		npages = iommu_num_pages(vaddr, slen);
		entry = iommu_range_alloc(tbl, npages, &handle, mask >> IOMMU_PAGE_SHIFT, 0);

		DBG("  - vaddr: %lx, size: %lx\n", vaddr, slen);

@@ -301,14 +311,14 @@ int iommu_map_sg(struct device *dev, struct iommu_table *tbl,

		/* Convert entry to a dma_addr_t */
		entry += tbl->it_offset;
		dma_addr = entry << PAGE_SHIFT;
		dma_addr |= s->offset;
		dma_addr = entry << IOMMU_PAGE_SHIFT;
		dma_addr |= (s->offset & ~IOMMU_PAGE_MASK);

		DBG("  - %lx pages, entry: %lx, dma_addr: %lx\n",
		DBG("  - %lu pages, entry: %lx, dma_addr: %lx\n",
			    npages, entry, dma_addr);

		/* Insert into HW table */
		ppc_md.tce_build(tbl, entry, npages, vaddr & PAGE_MASK, direction);
		ppc_md.tce_build(tbl, entry, npages, vaddr & IOMMU_PAGE_MASK, direction);

		/* If we are in an open segment, try merging */
		if (segstart != s) {
@@ -323,7 +333,7 @@ int iommu_map_sg(struct device *dev, struct iommu_table *tbl,
				DBG("    can't merge, new segment.\n");
			} else {
				outs->dma_length += s->length;
				DBG("    merged, new len: %lx\n", outs->dma_length);
				DBG("    merged, new len: %ux\n", outs->dma_length);
			}
		}

@@ -367,9 +377,8 @@ int iommu_map_sg(struct device *dev, struct iommu_table *tbl,
		if (s->dma_length != 0) {
			unsigned long vaddr, npages;

			vaddr = s->dma_address & PAGE_MASK;
			npages = (PAGE_ALIGN(s->dma_address + s->dma_length) - vaddr)
				>> PAGE_SHIFT;
			vaddr = s->dma_address & IOMMU_PAGE_MASK;
			npages = iommu_num_pages(s->dma_address, s->dma_length);
			__iommu_free(tbl, vaddr, npages);
			s->dma_address = DMA_ERROR_CODE;
			s->dma_length = 0;
@@ -398,8 +407,7 @@ void iommu_unmap_sg(struct iommu_table *tbl, struct scatterlist *sglist,

		if (sglist->dma_length == 0)
			break;
		npages = (PAGE_ALIGN(dma_handle + sglist->dma_length)
			  - (dma_handle & PAGE_MASK)) >> PAGE_SHIFT;
		npages = iommu_num_pages(dma_handle,sglist->dma_length);
		__iommu_free(tbl, dma_handle, npages);
		sglist++;
	}
@@ -532,12 +540,11 @@ dma_addr_t iommu_map_single(struct iommu_table *tbl, void *vaddr,
	BUG_ON(direction == DMA_NONE);

	uaddr = (unsigned long)vaddr;
	npages = PAGE_ALIGN(uaddr + size) - (uaddr & PAGE_MASK);
	npages >>= PAGE_SHIFT;
	npages = iommu_num_pages(uaddr, size);

	if (tbl) {
		dma_handle = iommu_alloc(tbl, vaddr, npages, direction,
					 mask >> PAGE_SHIFT, 0);
					 mask >> IOMMU_PAGE_SHIFT, 0);
		if (dma_handle == DMA_ERROR_CODE) {
			if (printk_ratelimit())  {
				printk(KERN_INFO "iommu_alloc failed, "
@@ -545,7 +552,7 @@ dma_addr_t iommu_map_single(struct iommu_table *tbl, void *vaddr,
						tbl, vaddr, npages);
			}
		} else
			dma_handle |= (uaddr & ~PAGE_MASK);
			dma_handle |= (uaddr & ~IOMMU_PAGE_MASK);
	}

	return dma_handle;
@@ -554,11 +561,14 @@ dma_addr_t iommu_map_single(struct iommu_table *tbl, void *vaddr,
void iommu_unmap_single(struct iommu_table *tbl, dma_addr_t dma_handle,
		size_t size, enum dma_data_direction direction)
{
	unsigned int npages;

	BUG_ON(direction == DMA_NONE);

	if (tbl)
		iommu_free(tbl, dma_handle, (PAGE_ALIGN(dma_handle + size) -
					(dma_handle & PAGE_MASK)) >> PAGE_SHIFT);
	if (tbl) {
		npages = iommu_num_pages(dma_handle, size);
		iommu_free(tbl, dma_handle, npages);
	}
}

/* Allocates a contiguous real buffer and creates mappings over it.
@@ -570,11 +580,11 @@ void *iommu_alloc_coherent(struct iommu_table *tbl, size_t size,
{
	void *ret = NULL;
	dma_addr_t mapping;
	unsigned int npages, order;
	unsigned int order;
	unsigned int nio_pages, io_order;
	struct page *page;

	size = PAGE_ALIGN(size);
	npages = size >> PAGE_SHIFT;
	order = get_order(size);

 	/*
@@ -598,8 +608,10 @@ void *iommu_alloc_coherent(struct iommu_table *tbl, size_t size,
	memset(ret, 0, size);

	/* Set up tces to cover the allocated range */
	mapping = iommu_alloc(tbl, ret, npages, DMA_BIDIRECTIONAL,
			      mask >> PAGE_SHIFT, order);
	nio_pages = size >> IOMMU_PAGE_SHIFT;
	io_order = get_iommu_order(size);
	mapping = iommu_alloc(tbl, ret, nio_pages, DMA_BIDIRECTIONAL,
			      mask >> IOMMU_PAGE_SHIFT, io_order);
	if (mapping == DMA_ERROR_CODE) {
		free_pages((unsigned long)ret, order);
		return NULL;
@@ -611,12 +623,13 @@ void *iommu_alloc_coherent(struct iommu_table *tbl, size_t size,
void iommu_free_coherent(struct iommu_table *tbl, size_t size,
			 void *vaddr, dma_addr_t dma_handle)
{
	unsigned int npages;

	if (tbl) {
		unsigned int nio_pages;

		size = PAGE_ALIGN(size);
		nio_pages = size >> IOMMU_PAGE_SHIFT;
		iommu_free(tbl, dma_handle, nio_pages);
		size = PAGE_ALIGN(size);
		npages = size >> PAGE_SHIFT;
		iommu_free(tbl, dma_handle, npages);
		free_pages((unsigned long)vaddr, get_order(size));
	}
}
+0 −221
Original line number Diff line number Diff line
/* arch/powerpc/kernel/perfmon_fsl_booke.c
 * Freescale Book-E Performance Monitor code
 *
 * Author: Andy Fleming
 * Copyright (c) 2004 Freescale Semiconductor, Inc
 *
 *  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 <linux/errno.h>
#include <linux/sched.h>
#include <linux/kernel.h>
#include <linux/mm.h>
#include <linux/stddef.h>
#include <linux/unistd.h>
#include <linux/ptrace.h>
#include <linux/slab.h>
#include <linux/user.h>
#include <linux/a.out.h>
#include <linux/interrupt.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/prctl.h>

#include <asm/pgtable.h>
#include <asm/uaccess.h>
#include <asm/system.h>
#include <asm/io.h>
#include <asm/reg.h>
#include <asm/xmon.h>
#include <asm/pmc.h>

static inline u32 get_pmlca(int ctr);
static inline void set_pmlca(int ctr, u32 pmlca);

static inline u32 get_pmlca(int ctr)
{
	u32 pmlca;

	switch (ctr) {
		case 0:
			pmlca = mfpmr(PMRN_PMLCA0);
			break;
		case 1:
			pmlca = mfpmr(PMRN_PMLCA1);
			break;
		case 2:
			pmlca = mfpmr(PMRN_PMLCA2);
			break;
		case 3:
			pmlca = mfpmr(PMRN_PMLCA3);
			break;
		default:
			panic("Bad ctr number\n");
	}

	return pmlca;
}

static inline void set_pmlca(int ctr, u32 pmlca)
{
	switch (ctr) {
		case 0:
			mtpmr(PMRN_PMLCA0, pmlca);
			break;
		case 1:
			mtpmr(PMRN_PMLCA1, pmlca);
			break;
		case 2:
			mtpmr(PMRN_PMLCA2, pmlca);
			break;
		case 3:
			mtpmr(PMRN_PMLCA3, pmlca);
			break;
		default:
			panic("Bad ctr number\n");
	}
}

void init_pmc_stop(int ctr)
{
	u32 pmlca = (PMLCA_FC | PMLCA_FCS | PMLCA_FCU |
			PMLCA_FCM1 | PMLCA_FCM0);
	u32 pmlcb = 0;

	switch (ctr) {
		case 0:
			mtpmr(PMRN_PMLCA0, pmlca);
			mtpmr(PMRN_PMLCB0, pmlcb);
			break;
		case 1:
			mtpmr(PMRN_PMLCA1, pmlca);
			mtpmr(PMRN_PMLCB1, pmlcb);
			break;
		case 2:
			mtpmr(PMRN_PMLCA2, pmlca);
			mtpmr(PMRN_PMLCB2, pmlcb);
			break;
		case 3:
			mtpmr(PMRN_PMLCA3, pmlca);
			mtpmr(PMRN_PMLCB3, pmlcb);
			break;
		default:
			panic("Bad ctr number!\n");
	}
}

void set_pmc_event(int ctr, int event)
{
	u32 pmlca;

	pmlca = get_pmlca(ctr);

	pmlca = (pmlca & ~PMLCA_EVENT_MASK) |
		((event << PMLCA_EVENT_SHIFT) &
		 PMLCA_EVENT_MASK);

	set_pmlca(ctr, pmlca);
}

void set_pmc_user_kernel(int ctr, int user, int kernel)
{
	u32 pmlca;

	pmlca = get_pmlca(ctr);

	if(user)
		pmlca &= ~PMLCA_FCU;
	else
		pmlca |= PMLCA_FCU;

	if(kernel)
		pmlca &= ~PMLCA_FCS;
	else
		pmlca |= PMLCA_FCS;

	set_pmlca(ctr, pmlca);
}

void set_pmc_marked(int ctr, int mark0, int mark1)
{
	u32 pmlca = get_pmlca(ctr);

	if(mark0)
		pmlca &= ~PMLCA_FCM0;
	else
		pmlca |= PMLCA_FCM0;

	if(mark1)
		pmlca &= ~PMLCA_FCM1;
	else
		pmlca |= PMLCA_FCM1;

	set_pmlca(ctr, pmlca);
}

void pmc_start_ctr(int ctr, int enable)
{
	u32 pmlca = get_pmlca(ctr);

	pmlca &= ~PMLCA_FC;

	if (enable)
		pmlca |= PMLCA_CE;
	else
		pmlca &= ~PMLCA_CE;

	set_pmlca(ctr, pmlca);
}

void pmc_start_ctrs(int enable)
{
	u32 pmgc0 = mfpmr(PMRN_PMGC0);

	pmgc0 &= ~PMGC0_FAC;
	pmgc0 |= PMGC0_FCECE;

	if (enable)
		pmgc0 |= PMGC0_PMIE;
	else
		pmgc0 &= ~PMGC0_PMIE;

	mtpmr(PMRN_PMGC0, pmgc0);
}

void pmc_stop_ctrs(void)
{
	u32 pmgc0 = mfpmr(PMRN_PMGC0);

	pmgc0 |= PMGC0_FAC;

	pmgc0 &= ~(PMGC0_PMIE | PMGC0_FCECE);

	mtpmr(PMRN_PMGC0, pmgc0);
}

void dump_pmcs(void)
{
	printk("pmgc0: %x\n", mfpmr(PMRN_PMGC0));
	printk("pmc\t\tpmlca\t\tpmlcb\n");
	printk("%8x\t%8x\t%8x\n", mfpmr(PMRN_PMC0),
			mfpmr(PMRN_PMLCA0), mfpmr(PMRN_PMLCB0));
	printk("%8x\t%8x\t%8x\n", mfpmr(PMRN_PMC1),
			mfpmr(PMRN_PMLCA1), mfpmr(PMRN_PMLCB1));
	printk("%8x\t%8x\t%8x\n", mfpmr(PMRN_PMC2),
			mfpmr(PMRN_PMLCA2), mfpmr(PMRN_PMLCB2));
	printk("%8x\t%8x\t%8x\n", mfpmr(PMRN_PMC3),
			mfpmr(PMRN_PMLCA3), mfpmr(PMRN_PMLCB3));
}

EXPORT_SYMBOL(init_pmc_stop);
EXPORT_SYMBOL(set_pmc_event);
EXPORT_SYMBOL(set_pmc_user_kernel);
EXPORT_SYMBOL(set_pmc_marked);
EXPORT_SYMBOL(pmc_start_ctr);
EXPORT_SYMBOL(pmc_start_ctrs);
EXPORT_SYMBOL(pmc_stop_ctrs);
EXPORT_SYMBOL(dump_pmcs);
+1 −1
Original line number Diff line number Diff line
@@ -71,7 +71,7 @@ int reserve_pmc_hardware(perf_irq_t new_perf_irq)
	}

	pmc_owner_caller = __builtin_return_address(0);
	perf_irq = new_perf_irq ? : dummy_perf;
	perf_irq = new_perf_irq ? new_perf_irq : dummy_perf;

 out:
	spin_unlock(&pmc_owner_lock);
Loading