Commit 5047887c authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'merge' of git://git.kernel.org/pub/scm/linux/kernel/git/benh/powerpc

* 'merge' of git://git.kernel.org/pub/scm/linux/kernel/git/benh/powerpc: (34 commits)
  powerpc: Wireup new syscalls
  Move update_mmu_cache() declaration from tlbflush.h to pgtable.h
  powerpc/pseries: Remove kmalloc call in handling writes to lparcfg
  powerpc/pseries: Update arch vector to indicate support for CMO
  ibmvfc: Add support for collaborative memory overcommit
  ibmvscsi: driver enablement for CMO
  ibmveth: enable driver for CMO
  ibmveth: Automatically enable larger rx buffer pools for larger mtu
  powerpc/pseries: Verify CMO memory entitlement updates with virtual I/O
  powerpc/pseries: vio bus support for CMO
  powerpc/pseries: iommu enablement for CMO
  powerpc/pseries: Add CMO paging statistics
  powerpc/pseries: Add collaborative memory manager
  powerpc/pseries: Utilities to set firmware page state
  powerpc/pseries: Enable CMO feature during platform setup
  powerpc/pseries: Split retrieval of processor entitlement data into a helper routine
  powerpc/pseries: Add memory entitlement capabilities to /proc/ppc64/lparcfg
  powerpc/pseries: Split processor entitlement retrieval and gathering to helper routines
  powerpc/pseries: Remove extraneous error reporting for hcall failures in lparcfg
  powerpc: Fix compile error with binutils 2.15
  ...

Fixed up conflict in arch/powerpc/platforms/52xx/Kconfig manually.
parents 996abf05 973b7d83
...@@ -59,6 +59,7 @@ Table of Contents ...@@ -59,6 +59,7 @@ Table of Contents
p) Freescale Synchronous Serial Interface p) Freescale Synchronous Serial Interface
q) USB EHCI controllers q) USB EHCI controllers
r) MDIO on GPIOs r) MDIO on GPIOs
s) SPI busses
VII - Marvell Discovery mv64[345]6x System Controller chips VII - Marvell Discovery mv64[345]6x System Controller chips
1) The /system-controller node 1) The /system-controller node
...@@ -1883,6 +1884,62 @@ platforms are moved over to use the flattened-device-tree model. ...@@ -1883,6 +1884,62 @@ platforms are moved over to use the flattened-device-tree model.
&qe_pio_c 6>; &qe_pio_c 6>;
}; };
s) SPI (Serial Peripheral Interface) busses
SPI busses can be described with a node for the SPI master device
and a set of child nodes for each SPI slave on the bus. For this
discussion, it is assumed that the system's SPI controller is in
SPI master mode. This binding does not describe SPI controllers
in slave mode.
The SPI master node requires the following properties:
- #address-cells - number of cells required to define a chip select
address on the SPI bus.
- #size-cells - should be zero.
- compatible - name of SPI bus controller following generic names
recommended practice.
No other properties are required in the SPI bus node. It is assumed
that a driver for an SPI bus device will understand that it is an SPI bus.
However, the binding does not attempt to define the specific method for
assigning chip select numbers. Since SPI chip select configuration is
flexible and non-standardized, it is left out of this binding with the
assumption that board specific platform code will be used to manage
chip selects. Individual drivers can define additional properties to
support describing the chip select layout.
SPI slave nodes must be children of the SPI master node and can
contain the following properties.
- reg - (required) chip select address of device.
- compatible - (required) name of SPI device following generic names
recommended practice
- spi-max-frequency - (required) Maximum SPI clocking speed of device in Hz
- spi-cpol - (optional) Empty property indicating device requires
inverse clock polarity (CPOL) mode
- spi-cpha - (optional) Empty property indicating device requires
shifted clock phase (CPHA) mode
SPI example for an MPC5200 SPI bus:
spi@f00 {
#address-cells = <1>;
#size-cells = <0>;
compatible = "fsl,mpc5200b-spi","fsl,mpc5200-spi";
reg = <0xf00 0x20>;
interrupts = <2 13 0 2 14 0>;
interrupt-parent = <&mpc5200_pic>;
ethernet-switch@0 {
compatible = "micrel,ks8995m";
spi-max-frequency = <1000000>;
reg = <0>;
};
codec@1 {
compatible = "ti,tlv320aic26";
spi-max-frequency = <100000>;
reg = <1>;
};
};
VII - Marvell Discovery mv64[345]6x System Controller chips VII - Marvell Discovery mv64[345]6x System Controller chips
=========================================================== ===========================================================
......
...@@ -23,6 +23,9 @@ ...@@ -23,6 +23,9 @@
struct cpu_spec* cur_cpu_spec = NULL; struct cpu_spec* cur_cpu_spec = NULL;
EXPORT_SYMBOL(cur_cpu_spec); EXPORT_SYMBOL(cur_cpu_spec);
/* The platform string corresponding to the real PVR */
const char *powerpc_base_platform;
/* NOTE: /* NOTE:
* Unlike ppc32, ppc64 will only call this once for the boot CPU, it's * Unlike ppc32, ppc64 will only call this once for the boot CPU, it's
* the responsibility of the appropriate CPU save/restore functions to * the responsibility of the appropriate CPU save/restore functions to
...@@ -1652,6 +1655,14 @@ struct cpu_spec * __init identify_cpu(unsigned long offset, unsigned int pvr) ...@@ -1652,6 +1655,14 @@ struct cpu_spec * __init identify_cpu(unsigned long offset, unsigned int pvr)
} else } else
*t = *s; *t = *s;
*PTRRELOC(&cur_cpu_spec) = &the_cpu_spec; *PTRRELOC(&cur_cpu_spec) = &the_cpu_spec;
/*
* Set the base platform string once; assumes
* we're called with real pvr first.
*/
if (powerpc_base_platform == NULL)
powerpc_base_platform = t->platform;
#if defined(CONFIG_PPC64) || defined(CONFIG_BOOKE) #if defined(CONFIG_PPC64) || defined(CONFIG_BOOKE)
/* ppc64 and booke expect identify_cpu to also call /* ppc64 and booke expect identify_cpu to also call
* setup_cpu for that processor. I will consolidate * setup_cpu for that processor. I will consolidate
......
...@@ -148,7 +148,7 @@ transfer_to_handler: ...@@ -148,7 +148,7 @@ transfer_to_handler:
/* Check to see if the dbcr0 register is set up to debug. Use the /* Check to see if the dbcr0 register is set up to debug. Use the
internal debug mode bit to do this. */ internal debug mode bit to do this. */
lwz r12,THREAD_DBCR0(r12) lwz r12,THREAD_DBCR0(r12)
andis. r12,r12,DBCR0_IDM@h andis. r12,r12,(DBCR0_IDM | DBSR_DAC1R | DBSR_DAC1W)@h
beq+ 3f beq+ 3f
/* From user and task is ptraced - load up global dbcr0 */ /* From user and task is ptraced - load up global dbcr0 */
li r12,-1 /* clear all pending debug events */ li r12,-1 /* clear all pending debug events */
...@@ -292,7 +292,7 @@ syscall_exit_cont: ...@@ -292,7 +292,7 @@ syscall_exit_cont:
/* If the process has its own DBCR0 value, load it up. The internal /* If the process has its own DBCR0 value, load it up. The internal
debug mode bit tells us that dbcr0 should be loaded. */ debug mode bit tells us that dbcr0 should be loaded. */
lwz r0,THREAD+THREAD_DBCR0(r2) lwz r0,THREAD+THREAD_DBCR0(r2)
andis. r10,r0,DBCR0_IDM@h andis. r10,r0,(DBCR0_IDM | DBSR_DAC1R | DBSR_DAC1W)@h
bnel- load_dbcr0 bnel- load_dbcr0
#endif #endif
#ifdef CONFIG_44x #ifdef CONFIG_44x
...@@ -720,7 +720,7 @@ restore_user: ...@@ -720,7 +720,7 @@ restore_user:
/* Check whether this process has its own DBCR0 value. The internal /* Check whether this process has its own DBCR0 value. The internal
debug mode bit tells us that dbcr0 should be loaded. */ debug mode bit tells us that dbcr0 should be loaded. */
lwz r0,THREAD+THREAD_DBCR0(r2) lwz r0,THREAD+THREAD_DBCR0(r2)
andis. r10,r0,DBCR0_IDM@h andis. r10,r0,(DBCR0_IDM | DBSR_DAC1R | DBSR_DAC1W)@h
bnel- load_dbcr0 bnel- load_dbcr0
#endif #endif
......
...@@ -49,6 +49,8 @@ static int novmerge = 1; ...@@ -49,6 +49,8 @@ static int novmerge = 1;
static int protect4gb = 1; static int protect4gb = 1;
static void __iommu_free(struct iommu_table *, dma_addr_t, unsigned int);
static inline unsigned long iommu_num_pages(unsigned long vaddr, static inline unsigned long iommu_num_pages(unsigned long vaddr,
unsigned long slen) unsigned long slen)
{ {
...@@ -191,6 +193,7 @@ static dma_addr_t iommu_alloc(struct device *dev, struct iommu_table *tbl, ...@@ -191,6 +193,7 @@ static dma_addr_t iommu_alloc(struct device *dev, struct iommu_table *tbl,
{ {
unsigned long entry, flags; unsigned long entry, flags;
dma_addr_t ret = DMA_ERROR_CODE; dma_addr_t ret = DMA_ERROR_CODE;
int build_fail;
spin_lock_irqsave(&(tbl->it_lock), flags); spin_lock_irqsave(&(tbl->it_lock), flags);
...@@ -205,9 +208,21 @@ static dma_addr_t iommu_alloc(struct device *dev, struct iommu_table *tbl, ...@@ -205,9 +208,21 @@ static dma_addr_t iommu_alloc(struct device *dev, struct iommu_table *tbl,
ret = entry << IOMMU_PAGE_SHIFT; /* Set the return dma address */ ret = entry << IOMMU_PAGE_SHIFT; /* Set the return dma address */
/* Put the TCEs in the HW table */ /* Put the TCEs in the HW table */
ppc_md.tce_build(tbl, entry, npages, (unsigned long)page & IOMMU_PAGE_MASK, build_fail = ppc_md.tce_build(tbl, entry, npages,
(unsigned long)page & IOMMU_PAGE_MASK,
direction, attrs); direction, attrs);
/* ppc_md.tce_build() only returns non-zero for transient errors.
* Clean up the table bitmap in this case and return
* DMA_ERROR_CODE. For all other errors the functionality is
* not altered.
*/
if (unlikely(build_fail)) {
__iommu_free(tbl, ret, npages);
spin_unlock_irqrestore(&(tbl->it_lock), flags);
return DMA_ERROR_CODE;
}
/* Flush/invalidate TLB caches if necessary */ /* Flush/invalidate TLB caches if necessary */
if (ppc_md.tce_flush) if (ppc_md.tce_flush)
...@@ -276,7 +291,7 @@ int iommu_map_sg(struct device *dev, struct iommu_table *tbl, ...@@ -276,7 +291,7 @@ int iommu_map_sg(struct device *dev, struct iommu_table *tbl,
dma_addr_t dma_next = 0, dma_addr; dma_addr_t dma_next = 0, dma_addr;
unsigned long flags; unsigned long flags;
struct scatterlist *s, *outs, *segstart; struct scatterlist *s, *outs, *segstart;
int outcount, incount, i; int outcount, incount, i, build_fail = 0;
unsigned int align; unsigned int align;
unsigned long handle; unsigned long handle;
unsigned int max_seg_size; unsigned int max_seg_size;
...@@ -337,8 +352,11 @@ int iommu_map_sg(struct device *dev, struct iommu_table *tbl, ...@@ -337,8 +352,11 @@ int iommu_map_sg(struct device *dev, struct iommu_table *tbl,
npages, entry, dma_addr); npages, entry, dma_addr);
/* Insert into HW table */ /* Insert into HW table */
ppc_md.tce_build(tbl, entry, npages, vaddr & IOMMU_PAGE_MASK, build_fail = ppc_md.tce_build(tbl, entry, npages,
vaddr & IOMMU_PAGE_MASK,
direction, attrs); direction, attrs);
if(unlikely(build_fail))
goto failure;
/* If we are in an open segment, try merging */ /* If we are in an open segment, try merging */
if (segstart != s) { if (segstart != s) {
......
This diff is collapsed.
...@@ -47,6 +47,8 @@ ...@@ -47,6 +47,8 @@
#ifdef CONFIG_PPC64 #ifdef CONFIG_PPC64
#include <asm/firmware.h> #include <asm/firmware.h>
#endif #endif
#include <linux/kprobes.h>
#include <linux/kdebug.h>
extern unsigned long _get_SP(void); extern unsigned long _get_SP(void);
...@@ -239,6 +241,35 @@ void discard_lazy_cpu_state(void) ...@@ -239,6 +241,35 @@ void discard_lazy_cpu_state(void)
} }
#endif /* CONFIG_SMP */ #endif /* CONFIG_SMP */
void do_dabr(struct pt_regs *regs, unsigned long address,
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 DAC and struct entries. One shot trigger */
#if (defined(CONFIG_44x) || defined(CONFIG_BOOKE))
mtspr(SPRN_DBCR0, mfspr(SPRN_DBCR0) & ~(DBSR_DAC1R | DBSR_DAC1W
| DBCR0_IDM));
#endif
/* 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 *)address;
force_sig_info(SIGTRAP, &info, current);
}
static DEFINE_PER_CPU(unsigned long, current_dabr); static DEFINE_PER_CPU(unsigned long, current_dabr);
int set_dabr(unsigned long dabr) int set_dabr(unsigned long dabr)
...@@ -254,6 +285,11 @@ int set_dabr(unsigned long dabr) ...@@ -254,6 +285,11 @@ int set_dabr(unsigned long dabr)
#if defined(CONFIG_PPC64) || defined(CONFIG_6xx) #if defined(CONFIG_PPC64) || defined(CONFIG_6xx)
mtspr(SPRN_DABR, dabr); mtspr(SPRN_DABR, dabr);
#endif #endif
#if defined(CONFIG_44x) || defined(CONFIG_BOOKE)
mtspr(SPRN_DAC1, dabr);
#endif
return 0; return 0;
} }
...@@ -337,6 +373,12 @@ struct task_struct *__switch_to(struct task_struct *prev, ...@@ -337,6 +373,12 @@ struct task_struct *__switch_to(struct task_struct *prev,
if (unlikely(__get_cpu_var(current_dabr) != new->thread.dabr)) if (unlikely(__get_cpu_var(current_dabr) != new->thread.dabr))
set_dabr(new->thread.dabr); set_dabr(new->thread.dabr);
#if defined(CONFIG_44x) || defined(CONFIG_BOOKE)
/* If new thread DAC (HW breakpoint) is the same then leave it */
if (new->thread.dabr)
set_dabr(new->thread.dabr);
#endif
new_thread = &new->thread; new_thread = &new->thread;
old_thread = &current->thread; old_thread = &current->thread;
...@@ -525,6 +567,10 @@ void flush_thread(void) ...@@ -525,6 +567,10 @@ void flush_thread(void)
if (current->thread.dabr) { if (current->thread.dabr) {
current->thread.dabr = 0; current->thread.dabr = 0;
set_dabr(0); set_dabr(0);
#if defined(CONFIG_44x) || defined(CONFIG_BOOKE)
current->thread.dbcr0 &= ~(DBSR_DAC1R | DBSR_DAC1W);
#endif
} }
} }
......
...@@ -643,6 +643,11 @@ static void __init early_cmdline_parse(void) ...@@ -643,6 +643,11 @@ static void __init early_cmdline_parse(void)
#else #else
#define OV5_MSI 0x00 #define OV5_MSI 0x00
#endif /* CONFIG_PCI_MSI */ #endif /* CONFIG_PCI_MSI */
#ifdef CONFIG_PPC_SMLPAR
#define OV5_CMO 0x80 /* Cooperative Memory Overcommitment */
#else
#define OV5_CMO 0x00
#endif
/* /*
* The architecture vector has an array of PVR mask/value pairs, * The architecture vector has an array of PVR mask/value pairs,
...@@ -687,10 +692,12 @@ static unsigned char ibm_architecture_vec[] = { ...@@ -687,10 +692,12 @@ static unsigned char ibm_architecture_vec[] = {
0, /* don't halt */ 0, /* don't halt */
/* option vector 5: PAPR/OF options */ /* option vector 5: PAPR/OF options */
3 - 2, /* length */ 5 - 2, /* length */
0, /* don't ignore, don't halt */ 0, /* don't ignore, don't halt */
OV5_LPAR | OV5_SPLPAR | OV5_LARGE_PAGES | OV5_DRCONF_MEMORY | OV5_LPAR | OV5_SPLPAR | OV5_LARGE_PAGES | OV5_DRCONF_MEMORY |
OV5_DONATE_DEDICATE_CPU | OV5_MSI, OV5_DONATE_DEDICATE_CPU | OV5_MSI,
0,
OV5_CMO,
}; };
/* Old method - ELF header with PT_NOTE sections */ /* Old method - ELF header with PT_NOTE sections */
......
...@@ -703,7 +703,7 @@ void user_enable_single_step(struct task_struct *task) ...@@ -703,7 +703,7 @@ void user_enable_single_step(struct task_struct *task)
if (regs != NULL) { if (regs != NULL) {
#if defined(CONFIG_40x) || defined(CONFIG_BOOKE) #if defined(CONFIG_40x) || defined(CONFIG_BOOKE)
task->thread.dbcr0 = DBCR0_IDM | DBCR0_IC; task->thread.dbcr0 |= DBCR0_IDM | DBCR0_IC;
regs->msr |= MSR_DE; regs->msr |= MSR_DE;
#else #else
regs->msr |= MSR_SE; regs->msr |= MSR_SE;
...@@ -716,9 +716,16 @@ void user_disable_single_step(struct task_struct *task) ...@@ -716,9 +716,16 @@ void user_disable_single_step(struct task_struct *task)
{ {
struct pt_regs *regs = task->thread.regs; struct pt_regs *regs = task->thread.regs;
#if defined(CONFIG_44x) || defined(CONFIG_BOOKE)
/* If DAC then do not single step, skip */
if (task->thread.dabr)
return;
#endif
if (regs != NULL) { if (regs != NULL) {
#if defined(CONFIG_40x) || defined(CONFIG_BOOKE) #if defined(CONFIG_40x) || defined(CONFIG_BOOKE)
task->thread.dbcr0 = 0; task->thread.dbcr0 &= ~(DBCR0_IC | DBCR0_IDM);
regs->msr &= ~MSR_DE; regs->msr &= ~MSR_DE;
#else #else
regs->msr &= ~MSR_SE; regs->msr &= ~MSR_SE;
...@@ -727,22 +734,75 @@ void user_disable_single_step(struct task_struct *task) ...@@ -727,22 +734,75 @@ void user_disable_single_step(struct task_struct *task)
clear_tsk_thread_flag(task, TIF_SINGLESTEP); clear_tsk_thread_flag(task, TIF_SINGLESTEP);
} }
static int ptrace_set_debugreg(struct task_struct *task, unsigned long addr, int ptrace_set_debugreg(struct task_struct *task, unsigned long addr,
unsigned long data) unsigned long data)
{ {
/* We only support one DABR and no IABRS at the moment */ /* For ppc64 we support one DABR and no IABR's at the moment (ppc64).
* For embedded processors we support one DAC and no IAC's at the
* moment.
*/
if (addr > 0) if (addr > 0)
return -EINVAL; return -EINVAL;
/* The bottom 3 bits are flags */
if ((data & ~0x7UL) >= TASK_SIZE) if ((data & ~0x7UL) >= TASK_SIZE)
return -EIO; return -EIO;
/* Ensure translation is on */ #ifdef CONFIG_PPC64
/* For processors using DABR (i.e. 970), the bottom 3 bits are flags.
* It was assumed, on previous implementations, that 3 bits were
* passed together with the data address, fitting the design of the
* DABR register, as follows:
*
* bit 0: Read flag
* bit 1: Write flag
* bit 2: Breakpoint translation
*
* Thus, we use them here as so.
*/
/* Ensure breakpoint translation bit is set */
if (data && !(data & DABR_TRANSLATION)) if (data && !(data & DABR_TRANSLATION))
return -EIO; return -EIO;
/* Move contents to the DABR register */
task->thread.dabr = data; task->thread.dabr = data;
#endif
#if defined(CONFIG_44x) || defined(CONFIG_BOOKE)
/* As described above, it was assumed 3 bits were passed with the data
* address, but we will assume only the mode bits will be passed
* as to not cause alignment restrictions for DAC-based processors.
*/
/* DAC's hold the whole address without any mode flags */
task->thread.dabr = data & ~0x3UL;
if (task->thread.dabr == 0) {
task->thread.dbcr0 &= ~(DBSR_DAC1R | DBSR_DAC1W | DBCR0_IDM);
task->thread.regs->msr &= ~MSR_DE;
return 0;
}
/* Read or Write bits must be set */
if (!(data & 0x3UL))
return -EINVAL;
/* Set the Internal Debugging flag (IDM bit 1) for the DBCR0
register */
task->thread.dbcr0 = DBCR0_IDM;
/* Check for write and read flags and set DBCR0
accordingly */
if (data & 0x1UL)
task->thread.dbcr0 |= DBSR_DAC1R;
if (data & 0x2UL)
task->thread.dbcr0 |= DBSR_DAC1W;
task->thread.regs->msr |= MSR_DE;
#endif
return 0; return 0;
} }
......
...@@ -145,8 +145,12 @@ int do_signal(sigset_t *oldset, struct pt_regs *regs) ...@@ -145,8 +145,12 @@ int do_signal(sigset_t *oldset, struct pt_regs *regs)
* user space. The DABR will have been cleared if it * user space. The DABR will have been cleared if it
* triggered inside the kernel. * triggered inside the kernel.
*/ */
if (current->thread.dabr) if (current->thread.dabr) {
set_dabr(current->thread.dabr); set_dabr(current->thread.dabr);
#if defined(CONFIG_44x) || defined(CONFIG_BOOKE)
mtspr(SPRN_DBCR0, current->thread.dbcr0);
#endif
}
if (is32) { if (is32) {
if (ka.sa.sa_flags & SA_SIGINFO) if (ka.sa.sa_flags & SA_SIGINFO)
......
...@@ -529,7 +529,8 @@ static void register_nodes(void) ...@@ -529,7 +529,8 @@ static void register_nodes(void)
#endif #endif
/* Only valid if CPU is present. */ /* Only valid if CPU is present. */
static ssize_t show_physical_id(struct sys_device *dev, char *buf) static ssize_t show_physical_id(struct sys_device *dev,
struct sysdev_attribute *attr, char *buf)
{ {
struct cpu *cpu = container_of(dev, struct cpu, sysdev); struct cpu *cpu = container_of(dev, struct cpu, sysdev);
......
...@@ -1067,6 +1067,22 @@ void __kprobes DebugException(struct pt_regs *regs, unsigned long debug_status) ...@@ -1067,6 +1067,22 @@ void __kprobes DebugException(struct pt_regs *regs, unsigned long debug_status)
} }
_exception(SIGTRAP, regs, TRAP_TRACE, regs->nip); _exception(SIGTRAP, regs, TRAP_TRACE, regs->nip);
} else if (debug_status & (DBSR_DAC1R | DBSR_DAC1W)) {
regs->msr &= ~MSR_DE;
if (user_mode(regs)) {
current->thread.dbcr0 &= ~(DBSR_DAC1R | DBSR_DAC1W |
DBCR0_IDM);
} else {
/* Disable DAC interupts */
mtspr(SPRN_DBCR0, mfspr(SPRN_DBCR0) & ~(DBSR_DAC1R |
DBSR_DAC1W | DBCR0_IDM));
/* Clear the DAC event */
mtspr(SPRN_DBSR, (DBSR_DAC1R | DBSR_DAC1W));
}
/* Setup and send the trap to the handler */
do_dabr(regs, mfspr(SPRN_DAC1), debug_status);
} }
} }
#endif /* CONFIG_4xx || CONFIG_BOOKE */ #endif /* CONFIG_4xx || CONFIG_BOOKE */
......
This diff is collapsed.
...@@ -85,7 +85,7 @@ SECTIONS ...@@ -85,7 +85,7 @@ SECTIONS
/* The dummy segment contents for the bug workaround mentioned above /* The dummy segment contents for the bug workaround mentioned above
near PHDRS. */ near PHDRS. */
.dummy : { .dummy : AT(ADDR(.dummy) - LOAD_OFFSET) {
LONG(0xf177) LONG(0xf177)
} :kernel :dummy } :kernel :dummy
......
...@@ -100,31 +100,6 @@ static int store_updates_sp(struct pt_regs *regs) ...@@ -100,31 +100,6 @@ static int store_updates_sp(struct pt_regs *regs)
return 0; return 0;
} }
#if !(defined(CONFIG_4xx) || defined(CONFIG_BOOKE))
static void do_dabr(struct pt_regs *regs, unsigned long address,
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 *)address;
force_sig_info(SIGTRAP, &info, current);
}
#endif /* !(CONFIG_4xx || CONFIG_BOOKE)*/
/* /*
* For 600- and 800-family processors, the error_code parameter is DSISR * For 600- and 800-family processors, the error_code parameter is DSISR
* for a data fault, SRR1 for an instruction fault. For 400-family processors * for a data fault, SRR1 for an instruction fault. For 400-family processors
......
config PPC_MPC52xx config PPC_MPC52xx
bool "52xx-based boards" bool "52xx-based boards"
depends on PPC_MULTIPLATFORM && PPC32 depends on PPC_MULTIPLATFORM && PPC32
select FSL_SOC
select PPC_CLOCK select PPC_CLOCK
select PPC_PCI_CHOICE select PPC_PCI_CHOICE
...@@ -49,5 +48,6 @@ config PPC_MPC5200_GPIO ...@@ -49,5 +48,6 @@ config PPC_MPC5200_GPIO
bool "MPC5200 GPIO support" bool "MPC5200 GPIO support"
depends on PPC_MPC52xx depends on PPC_MPC52xx
select ARCH_REQUIRE_GPIOLIB select ARCH_REQUIRE_GPIOLIB
select GENERIC_GPIO
help help
Enable gpiolib support for mpc5200 based boards Enable gpiolib support for mpc5200 based boards
...@@ -172,7 +172,7 @@ static void invalidate_tce_cache(struct cbe_iommu *iommu, unsigned long *pte, ...@@ -172,7 +172,7 @@ static void invalidate_tce_cache(struct cbe_iommu *iommu, unsigned long *pte,
} }
} }
static void tce_build_cell(struct iommu_table *tbl, long index, long npages, static int tce_build_cell(struct iommu_table *tbl, long index, long npages,
unsigned long uaddr, enum dma_data_direction direction, unsigned long uaddr, enum dma_data_direction direction,
struct dma_attrs *attrs) struct dma_attrs *attrs)
{ {
...@@ -213,6 +213,7 @@ static void tce_build_cell(struct iommu_table *tbl, long index, long npages, ...@@ -213,6 +213,7 @@ static void tce_build_cell(struct iommu_table *tbl, long index, long npages,
pr_debug("tce_build_cell(index=%lx,n=%lx,dir=%d,base_pte=%lx)\n", pr_debug("tce_build_cell(index=%lx,n=%lx,dir=%d,base_pte=%lx)\n",
index, npages, direction, base_pte); index, npages, direction, base_pte);
return 0;
} }
static void tce_free_cell(struct iommu_table *tbl, long index, long npages) static void tce_free_cell(struct iommu_table *tbl, long index, long npages)
...@@ -1150,12 +1151,23 @@ static int iommu_fixed_disabled; ...@@ -1150,12 +1151,23 @@ static int iommu_fixed_disabled;
static int __init setup_iommu_fixed(char *str) static int __init setup_iommu_fixed(char *str)
{ {
struct device_node *pciep;
if (strcmp(str, "off") == 0) if (strcmp(str, "off") == 0)
iommu_fixed_disabled = 1; iommu_fixed_disabled = 1;
else if (strcmp(str, "weak") == 0) /* If we can find a pcie-endpoint in the device tree assume that
* we're on a triblade or a CAB so by default the fixed mapping
* should be set to be weakly ordered; but only if the boot
* option WASN'T set for strong ordering
*/
pciep = of_find_node_by_type(NULL, "pcie-endpoint");
if (strcmp(str, "weak") == 0 || (pciep && strcmp(str, "strong") != 0))
iommu_fixed_is_weak = 1; iommu_fixed_is_weak = 1;
of_node_put(pciep);
return 1; return 1;
} }
__setup("iommu_fixed=", setup_iommu_fixed); __setup("iommu_fixed=", setup_iommu_fixed);
......
...@@ -312,10 +312,27 @@ static struct spu *aff_ref_location(struct spu_context *ctx, int mem_aff, ...@@ -312,10 +312,27 @@ static struct spu *aff_ref_location(struct spu_context *ctx, int mem_aff,
*/ */
node = cpu_to_node(raw_smp_processor_id()); node = cpu_to_node(raw_smp_processor_id());
for (n = 0; n < MAX_NUMNODES; n++, node++) { for (n = 0; n < MAX_NUMNODES; n++, node++) {
int available_spus;
node = (node < MAX_NUMNODES) ? node : 0; node = (node < MAX_NUMNODES) ? node : 0;
if (!node_allowed(ctx, node)) if (!node_allowed(ctx, node))
continue; continue;
available_spus = 0;
mutex_lock(&cbe_spu_info[node].list_mutex); mutex_lock(&cbe_spu_info[node].list_mutex);
list_for_each_entry(spu, &cbe_spu_info[node].spus, cbe_list) {
if (spu->ctx && spu->ctx->gang
&& spu->ctx->aff_offset == 0)
available_spus -=
(spu->ctx->gang->contexts - 1);
else
available_spus++;
}
if (available_spus < ctx->gang->contexts) {
mutex_unlock(&cbe_spu_info[node].list_mutex);
continue;
}
list_for_each_entry(spu, &cbe_spu_info[node].spus, cbe_list) { list_for_each_entry(spu, &cbe_spu_info[node].spus, cbe_list) {
if ((!mem_aff || spu->has_mem_affinity) && if ((!mem_aff || spu->has_mem_affinity) &&
sched_spu(spu)) { sched_spu(spu)) {
...@@ -389,6 +406,9 @@ static int has_affinity(struct spu_context *ctx) ...@@ -389,6 +406,9 @@ static int has_affinity(struct spu_context *ctx)
if (list_empty(&ctx->aff_list)) if (list_empty(&ctx->aff_list))
return 0; return 0;
if (atomic_read(&ctx->gang->aff_sched_count) == 0)
ctx->gang->aff_ref_spu = NULL;
if (!gang->aff_ref_spu) { if (!gang->aff_ref_spu) {
if (!(gang->aff_flags & AFF_MERGED)) if (!(gang->aff_flags & AFF_MERGED))
aff_merge_remaining_ctxs(gang); aff_merge_remaining_ctxs(gang);
...@@ -416,14 +436,8 @@ static void spu_unbind_context(struct spu *spu, struct spu_context *ctx) ...@@ -416,14 +436,8 @@ static void spu_unbind_context(struct spu *spu, struct spu_context *ctx)
if (spu->ctx->flags & SPU_CREATE_NOSCHED) if (spu->ctx->flags & SPU_CREATE_NOSCHED)
atomic_dec(&cbe_spu_info[spu->node].reserved_spus); atomic_dec(&cbe_spu_info[spu->node].reserved_spus);
if (ctx->gang){ if (ctx->gang)
mutex_lock(&ctx->gang->aff_mutex); atomic_dec_if_positive(&ctx->gang->aff_sched_count);
if (has_affinity(ctx)) {
if (atomic_dec_and_test(&ctx->gang->aff_sched_count))
ctx->gang->aff_ref_spu = NULL;
}
mutex_unlock(&ctx->gang->aff_mutex);
}
spu_switch_notify(spu, NULL); spu_switch_notify(spu, NULL);
spu_unmap_mappings(ctx); spu_unmap_mappings(ctx);
...@@ -562,10 +576,7 @@ static struct spu *spu_get_idle(struct spu_context *ctx) ...@@ -562,10 +576,7 @@ static struct spu *spu_get_idle(struct spu_context *ctx)
goto found; goto found;
mutex_unlock(&cbe_spu_info[node].list_mutex); mutex_unlock(&cbe_spu_info[node].list_mutex);
mutex_lock(&ctx->gang->aff_mutex); atomic_dec(&ctx->gang->aff_sched_count);
if (atomic_dec_and_test(&ctx->gang->aff_sched_count))
ctx->gang->aff_ref_spu = NULL;
mutex_unlock(&ctx->gang->aff_mutex);
goto not_found; goto not_found;
} }
mutex_unlock(&ctx->gang->aff_mutex); mutex_unlock(&ctx->gang->aff_mutex);
......
...@@ -196,8 +196,7 @@ static int __init sputrace_init(void) ...@@ -196,8 +196,7 @@ static int __init sputrace_init(void)
struct proc_dir_entry *entry; struct proc_dir_entry *entry;
int i, error = -ENOMEM; int i, error = -ENOMEM;
sputrace_log = kcalloc(sizeof(struct sputrace), sputrace_log = kcalloc(bufsize, sizeof(struct sputrace), GFP_KERNEL);
bufsize, GFP_KERNEL);
if (!sputrace_log) if (!sputrace_log)
goto out; goto out;
......
...@@ -41,7 +41,7 @@ ...@@ -41,7 +41,7 @@
#include <asm/iseries/hv_call_event.h> #include <asm/iseries/hv_call_event.h>
#include <asm/iseries/iommu.h> #include <asm/iseries/iommu.h>
static void tce_build_iSeries(struct iommu_table *tbl, long index, long npages, static int tce_build_iSeries(struct iommu_table *tbl, long index, long npages,
unsigned long uaddr, enum dma_data_direction direction, unsigned long uaddr, enum dma_data_direction direction,
struct dma_attrs *attrs) struct dma_attrs *attrs)
{ {
...@@ -71,6 +71,7 @@ static void tce_build_iSeries(struct iommu_table *tbl, long index, long npages, ...@@ -71,6 +71,7 @@ static void tce_build_iSeries(struct iommu_table *tbl, long index, long npages,
index++; index++;
uaddr += TCE_PAGE_SIZE; uaddr += TCE_PAGE_SIZE;
} }
return 0;
} }
static void tce_free_iSeries(struct iommu_table *tbl, long index, long npages) static void tce_free_iSeries(struct iommu_table *tbl, long index, long npages)
......
...@@ -83,7 +83,7 @@ static u32 *iob_l2_base; ...@@ -83,7 +83,7 @@ static u32 *iob_l2_base;
static struct iommu_table iommu_table_iobmap; static struct iommu_table iommu_table_iobmap;
static int iommu_table_iobmap_inited; static int iommu_table_iobmap_inited;
static void iobmap_build(struct iommu_table *tbl, long index, static int iobmap_build(struct iommu_table *tbl, long index,
long npages, unsigned long uaddr, long npages, unsigned long uaddr,
enum dma_data_direction direction, enum dma_data_direction direction,
struct dma_attrs *attrs) struct dma_attrs *attrs)
...@@ -108,6 +108,7 @@ static void iobmap_build(struct iommu_table *tbl, long index, ...@@ -108,6 +108,7 @@ static void iobmap_build(struct iommu_table *tbl, long index,
uaddr += IOBMAP_PAGE_SIZE; uaddr += IOBMAP_PAGE_SIZE;
bus_addr += IOBMAP_PAGE_SIZE; bus_addr += IOBMAP_PAGE_SIZE;
} }
return 0;
} }
......
...@@ -40,3 +40,26 @@ config PPC_PSERIES_DEBUG ...@@ -40,3 +40,26 @@ config PPC_PSERIES_DEBUG
depends on PPC_PSERIES && PPC_EARLY_DEBUG depends on PPC_PSERIES && PPC_EARLY_DEBUG
bool "Enable extra debug logging in platforms/pseries" bool "Enable extra debug logging in platforms/pseries"
default y default y
config PPC_SMLPAR
bool "Support for shared-memory logical partitions"
depends on PPC_PSERIES
select LPARCFG
default n
help
Select this option to enable shared memory partition support.
With this option a system running in an LPAR can be given more
memory than physically available and will allow firmware to
balance memory across many LPARs.
config CMM
tristate "Collaborative memory management"
depends on PPC_SMLPAR
default y
help
Select this option, if you want to enable the kernel interface
to reduce the memory size of the system. This is accomplished
by allocating pages of memory and put them "on hold". This only
makes sense for a system running in an LPAR where the unused pages
will be reused for other LPARs. The interface allows firmware to
balance memory across many LPARs.
...@@ -24,3 +24,4 @@ obj-$(CONFIG_HVC_CONSOLE) += hvconsole.o ...@@ -24,3 +24,4 @@ obj-$(CONFIG_HVC_CONSOLE) += hvconsole.o
obj-$(CONFIG_HVCS) += hvcserver.o obj-$(CONFIG_HVCS) += hvcserver.o
obj-$(CONFIG_HCALL_STATS) += hvCall_inst.o obj-$(CONFIG_HCALL_STATS) += hvCall_inst.o
obj-$(CONFIG_PHYP_DUMP) += phyp_dump.o obj-$(CONFIG_PHYP_DUMP) += phyp_dump.o
obj-$(CONFIG_CMM) += cmm.o
This diff is collapsed.
...@@ -48,7 +48,7 @@ ...@@ -48,7 +48,7 @@
#include "plpar_wrappers.h" #include "plpar_wrappers.h"
static void tce_build_pSeries(struct iommu_table *tbl, long index, static int tce_build_pSeries(struct iommu_table *tbl, long index,
long npages, unsigned long uaddr, long npages, unsigned long uaddr,
enum dma_data_direction direction, enum dma_data_direction direction,
struct dma_attrs *attrs) struct dma_attrs *attrs)
...@@ -72,6 +72,7 @@ static void tce_build_pSeries(struct iommu_table *tbl, long index, ...@@ -72,6 +72,7 @@ static void tce_build_pSeries(struct iommu_table *tbl, long index,
uaddr += TCE_PAGE_SIZE; uaddr += TCE_PAGE_SIZE;
tcep++; tcep++;
} }
return 0;
} }
...@@ -94,14 +95,19 @@ static unsigned long tce_get_pseries(struct iommu_table *tbl, long index) ...@@ -94,14 +95,19 @@ static unsigned long tce_get_pseries(struct iommu_table *tbl, long index)
return *tcep; return *tcep;
} }
static void tce_build_pSeriesLP(struct iommu_table *tbl, long tcenum, static void tce_free_pSeriesLP(struct iommu_table*, long, long);
static void tce_freemulti_pSeriesLP(struct iommu_table*, long, long);
static int tce_build_pSeriesLP(struct iommu_table *tbl, long tcenum,
long npages, unsigned long uaddr, long npages, unsigned long uaddr,
enum dma_data_direction direction, enum dma_data_direction direction,
struct dma_attrs *attrs) struct dma_attrs *attrs)
{ {
u64 rc; u64 rc = 0;
u64 proto_tce, tce; u64 proto_tce, tce;
u64 rpn; u64 rpn;
int ret = 0;
long tcenum_start = tcenum, npages_start = npages;
rpn = (virt_to_abs(uaddr)) >> TCE_SHIFT; rpn = (virt_to_abs(uaddr)) >> TCE_SHIFT;
proto_tce = TCE_PCI_READ; proto_tce = TCE_PCI_READ;
...@@ -112,6 +118,13 @@ static void tce_build_pSeriesLP(struct iommu_table *tbl, long tcenum, ...@@ -112,6 +118,13 @@ static void tce_build_pSeriesLP(struct iommu_table *tbl, long tcenum,
tce = proto_tce | (rpn & TCE_RPN_MASK) << TCE_RPN_SHIFT; tce = proto_tce | (rpn & TCE_RPN_MASK) << TCE_RPN_SHIFT;
rc = plpar_tce_put((u64)tbl->it_index, (u64)tcenum << 12, tce); rc = plpar_tce_put((u64)tbl->it_index, (u64)tcenum << 12, tce);
if (unlikely(rc == H_NOT_ENOUGH_RESOURCES)) {
ret = (int)rc;
tce_free_pSeriesLP(tbl, tcenum_start,
(npages_start - (npages + 1)));
break;
}
if (rc && printk_ratelimit()) { if (rc && printk_ratelimit()) {
printk("tce_build_pSeriesLP: plpar_tce_put failed. rc=%ld\n", rc); printk("tce_build_pSeriesLP: plpar_tce_put failed. rc=%ld\n", rc);
printk("\tindex = 0x%lx\n", (u64)tbl->it_index); printk("\tindex = 0x%lx\n", (u64)tbl->it_index);
...@@ -123,25 +136,27 @@ static void tce_build_pSeriesLP(struct iommu_table *tbl, long tcenum, ...@@ -123,25 +136,27 @@ static void tce_build_pSeriesLP(struct iommu_table *tbl, long tcenum,
tcenum++; tcenum++;
rpn++; rpn++;
} }
return ret;
} }
static DEFINE_PER_CPU(u64 *, tce_page) = NULL; static DEFINE_PER_CPU(u64 *, tce_page) = NULL;
static void tce_buildmulti_pSeriesLP(struct iommu_table *tbl, long tcenum, static int tce_buildmulti_pSeriesLP(struct iommu_table *tbl, long tcenum,
long npages, unsigned long uaddr, long npages, unsigned long uaddr,
enum dma_data_direction direction, enum dma_data_direction direction,
struct dma_attrs *attrs) struct dma_attrs *attrs)
{ {
u64 rc; u64 rc = 0;
u64 proto_tce; u64 proto_tce;
u64 *tcep; u64 *tcep;
u64 rpn; u64 rpn;
long l, limit; long l, limit;
long tcenum_start = tcenum, npages_start = npages;
int ret = 0;
if (npages == 1) { if (npages == 1) {
tce_build_pSeriesLP(tbl, tcenum, npages, uaddr, return tce_build_pSeriesLP(tbl, tcenum, npages, uaddr,
direction, attrs); direction, attrs);
return;
} }
tcep = __get_cpu_var(tce_page); tcep = __get_cpu_var(tce_page);
...@@ -153,9 +168,8 @@ static void tce_buildmulti_pSeriesLP(struct iommu_table *tbl, long tcenum, ...@@ -153,9 +168,8 @@ static void tce_buildmulti_pSeriesLP(struct iommu_table *tbl, long tcenum,
tcep = (u64 *)__get_free_page(GFP_ATOMIC); tcep = (u64 *)__get_free_page(GFP_ATOMIC);
/* If allocation fails, fall back to the loop implementation */ /* If allocation fails, fall back to the loop implementation */
if (!tcep) { if (!tcep) {
tce_build_pSeriesLP(tbl, tcenum, npages, uaddr, return tce_build_pSeriesLP(tbl, tcenum, npages, uaddr,
direction, attrs); direction, attrs);
return;
} }
__get_cpu_var(tce_page) = tcep; __get_cpu_var(tce_page) = tcep;
} }
...@@ -187,6 +201,13 @@ static void tce_buildmulti_pSeriesLP(struct iommu_table *tbl, long tcenum, ...@@ -187,6 +201,13 @@ static void tce_buildmulti_pSeriesLP(struct iommu_table *tbl, long tcenum,
tcenum += limit; tcenum += limit;
} while (npages > 0 && !rc); } while (npages > 0 && !rc);
if (unlikely(rc == H_NOT_ENOUGH_RESOURCES)) {
ret = (int)rc;
tce_freemulti_pSeriesLP(tbl, tcenum_start,
(npages_start - (npages + limit)));
return ret;
}
if (rc && printk_ratelimit()) { if (rc && printk_ratelimit()) {
printk("tce_buildmulti_pSeriesLP: plpar_tce_put failed. rc=%ld\n", rc); printk("tce_buildmulti_pSeriesLP: plpar_tce_put failed. rc=%ld\n", rc);
printk("\tindex = 0x%lx\n", (u64)tbl->it_index); printk("\tindex = 0x%lx\n", (u64)tbl->it_index);
...@@ -194,6 +215,7 @@ static void tce_buildmulti_pSeriesLP(struct iommu_table *tbl, long tcenum, ...@@ -194,6 +215,7 @@ static void tce_buildmulti_pSeriesLP(struct iommu_table *tbl, long tcenum,
printk("\ttce[0] val = 0x%lx\n", tcep[0]); printk("\ttce[0] val = 0x%lx\n", tcep[0]);
show_stack(current, (unsigned long *)__get_SP()); show_stack(current, (unsigned long *)__get_SP());
} }
return ret;
} }
static void tce_free_pSeriesLP(struct iommu_table *tbl, long tcenum, long npages) static void tce_free_pSeriesLP(struct iommu_table *tbl, long tcenum, long npages)
......
...@@ -42,6 +42,16 @@ static inline long register_slb_shadow(unsigned long cpu, unsigned long vpa) ...@@ -42,6 +42,16 @@ static inline long register_slb_shadow(unsigned long cpu, unsigned long vpa)
return vpa_call(0x3, cpu, vpa); return vpa_call(0x3, cpu, vpa);
} }
static inline long plpar_page_set_loaned(unsigned long vpa)
{
return plpar_hcall_norets(H_PAGE_INIT, H_PAGE_SET_LOANED, vpa, 0);
}
static inline long plpar_page_set_active(unsigned long vpa)
{
return plpar_hcall_norets(H_PAGE_INIT, H_PAGE_SET_ACTIVE, vpa, 0);
}
extern void vpa_init(int cpu); extern void vpa_init(int cpu);
static inline long plpar_pte_enter(unsigned long flags, static inline long plpar_pte_enter(unsigned long flags,
......
...@@ -314,6 +314,76 @@ static int pseries_set_xdabr(unsigned long dabr) ...@@ -314,6 +314,76 @@ static int pseries_set_xdabr(unsigned long dabr)
H_DABRX_KERNEL | H_DABRX_USER); H_DABRX_KERNEL | H_DABRX_USER);
} }
#define CMO_CHARACTERISTICS_TOKEN 44
#define CMO_MAXLENGTH 1026
/**
* fw_cmo_feature_init - FW_FEATURE_CMO is not stored in ibm,hypertas-functions,
* handle that here. (Stolen from parse_system_parameter_string)
*/
void pSeries_cmo_feature_init(void)
{
char *ptr, *key, *value, *end;
int call_status;
int PrPSP = -1;
int SecPSP = -1;
pr_debug(" -> fw_cmo_feature_init()\n");
spin_lock(&rtas_data_buf_lock);
memset(rtas_data_buf, 0, RTAS_DATA_BUF_SIZE);
call_status = rtas_call(rtas_token("ibm,get-system-parameter"), 3, 1,
NULL,
CMO_CHARACTERISTICS_TOKEN,
__pa(rtas_data_buf),
RTAS_DATA_BUF_SIZE);
if (call_status != 0) {
spin_unlock(&rtas_data_buf_lock);
pr_debug("CMO not available\n");
pr_debug(" <- fw_cmo_feature_init()\n");
return;
}
end = rtas_data_buf + CMO_MAXLENGTH - 2;
ptr = rtas_data_buf + 2; /* step over strlen value */
key = value = ptr;
while (*ptr && (ptr <= end)) {
/* Separate the key and value by replacing '=' with '\0' and
* point the value at the string after the '='
*/
if (ptr[0] == '=') {
ptr[0] = '\0';
value = ptr + 1;
} else if (ptr[0] == '\0' || ptr[0] == ',') {
/* Terminate the string containing the key/value pair */
ptr[0] = '\0';
if (key == value) {
pr_debug("Malformed key/value pair\n");
/* Never found a '=', end processing */
break;
}
if (0 == strcmp(key, "PrPSP"))
PrPSP = simple_strtol(value, NULL, 10);
else if (0 == strcmp(key, "SecPSP"))
SecPSP = simple_strtol(value, NULL, 10);
value = key = ptr + 1;
}
ptr++;
}
if (PrPSP != -1 || SecPSP != -1) {
pr_info("CMO enabled\n");
pr_debug("CMO enabled, PrPSP=%d, SecPSP=%d\n", PrPSP, SecPSP);
powerpc_firmware_features |= FW_FEATURE_CMO;
} else
pr_debug("CMO not enabled, PrPSP=%d, SecPSP=%d\n", PrPSP, SecPSP);
spin_unlock(&rtas_data_buf_lock);
pr_debug(" <- fw_cmo_feature_init()\n");
}
/* /*
* Early initialization. Relocation is on but do not reference unbolted pages * Early initialization. Relocation is on but do not reference unbolted pages
*/ */
...@@ -329,6 +399,7 @@ static void __init pSeries_init_early(void) ...@@ -329,6 +399,7 @@ static void __init pSeries_init_early(void)
else if (firmware_has_feature(FW_FEATURE_XDABR)) else if (firmware_has_feature(FW_FEATURE_XDABR))
ppc_md.set_dabr = pseries_set_xdabr; ppc_md.set_dabr = pseries_set_xdabr;
pSeries_cmo_feature_init();
iommu_init_early_pSeries(); iommu_init_early_pSeries();
pr_debug(" <- pSeries_init_early()\n"); pr_debug(" <- pSeries_init_early()\n");
......
...@@ -147,7 +147,7 @@ static void dart_flush(struct iommu_table *tbl) ...@@ -147,7 +147,7 @@ static void dart_flush(struct iommu_table *tbl)
} }
} }
static void dart_build(struct iommu_table *tbl, long index, static int dart_build(struct iommu_table *tbl, long index,
long npages, unsigned long uaddr, long npages, unsigned long uaddr,
enum dma_data_direction direction, enum dma_data_direction direction,
struct dma_attrs *attrs) struct dma_attrs *attrs)
...@@ -184,6 +184,7 @@ static void dart_build(struct iommu_table *tbl, long index, ...@@ -184,6 +184,7 @@ static void dart_build(struct iommu_table *tbl, long index,
} else { } else {
dart_dirty = 1; dart_dirty = 1;
} }
return 0;
} }
......
This diff is collapsed.
...@@ -93,9 +93,12 @@ static inline long h_illan_attributes(unsigned long unit_address, ...@@ -93,9 +93,12 @@ static inline long h_illan_attributes(unsigned long unit_address,
plpar_hcall_norets(H_CHANGE_LOGICAL_LAN_MAC, ua, mac) plpar_hcall_norets(H_CHANGE_LOGICAL_LAN_MAC, ua, mac)
#define IbmVethNumBufferPools 5 #define IbmVethNumBufferPools 5
#define IBMVETH_IO_ENTITLEMENT_DEFAULT 4243456 /* MTU of 1500 needs 4.2Mb */
#define IBMVETH_BUFF_OH 22 /* Overhead: 14 ethernet header + 8 opaque handle */ #define IBMVETH_BUFF_OH 22 /* Overhead: 14 ethernet header + 8 opaque handle */
#define IBMVETH_MAX_MTU 68 #define IBMVETH_MAX_MTU 68
#define IBMVETH_MAX_POOL_COUNT 4096 #define IBMVETH_MAX_POOL_COUNT 4096
#define IBMVETH_BUFF_LIST_SIZE 4096
#define IBMVETH_FILT_LIST_SIZE 4096
#define IBMVETH_MAX_BUF_SIZE (1024 * 128) #define IBMVETH_MAX_BUF_SIZE (1024 * 128)
static int pool_size[] = { 512, 1024 * 2, 1024 * 16, 1024 * 32, 1024 * 64 }; static int pool_size[] = { 512, 1024 * 2, 1024 * 16, 1024 * 32, 1024 * 64 };
...@@ -143,6 +146,8 @@ struct ibmveth_adapter { ...@@ -143,6 +146,8 @@ struct ibmveth_adapter {
struct ibmveth_rx_q rx_queue; struct ibmveth_rx_q rx_queue;
int pool_config; int pool_config;
int rx_csum; int rx_csum;
void *bounce_buffer;
dma_addr_t bounce_buffer_dma;
/* adapter specific stats */ /* adapter specific stats */
u64 replenish_task_cycles; u64 replenish_task_cycles;
......
...@@ -91,8 +91,6 @@ void of_register_i2c_devices(struct i2c_adapter *adap, ...@@ -91,8 +91,6 @@ void of_register_i2c_devices(struct i2c_adapter *adap,
} }
info.irq = irq_of_parse_and_map(node, 0); info.irq = irq_of_parse_and_map(node, 0);
if (info.irq == NO_IRQ)
info.irq = -1;
if (of_find_i2c_driver(node, &info) < 0) { if (of_find_i2c_driver(node, &info) < 0) {
irq_dispose_mapping(info.irq); irq_dispose_mapping(info.irq);
......
...@@ -3819,6 +3819,20 @@ static int ibmvfc_remove(struct vio_dev *vdev) ...@@ -3819,6 +3819,20 @@ static int ibmvfc_remove(struct vio_dev *vdev)
return 0; return 0;
} }
/**
* ibmvfc_get_desired_dma - Calculate DMA resources needed by the driver
* @vdev: vio device struct
*
* Return value:
* Number of bytes the driver will need to DMA map at the same time in
* order to perform well.
*/
static unsigned long ibmvfc_get_desired_dma(struct vio_dev *vdev)
{
unsigned long pool_dma = max_requests * sizeof(union ibmvfc_iu);
return pool_dma + ((512 * 1024) * driver_template.cmd_per_lun);
}
static struct vio_device_id ibmvfc_device_table[] __devinitdata = { static struct vio_device_id ibmvfc_device_table[] __devinitdata = {
{"fcp", "IBM,vfc-client"}, {"fcp", "IBM,vfc-client"},
{ "", "" } { "", "" }
...@@ -3829,6 +3843,7 @@ static struct vio_driver ibmvfc_driver = { ...@@ -3829,6 +3843,7 @@ static struct vio_driver ibmvfc_driver = {
.id_table = ibmvfc_device_table, .id_table = ibmvfc_device_table,
.probe = ibmvfc_probe, .probe = ibmvfc_probe,
.remove = ibmvfc_remove, .remove = ibmvfc_remove,
.get_desired_dma = ibmvfc_get_desired_dma,
.driver = { .driver = {
.name = IBMVFC_NAME, .name = IBMVFC_NAME,
.owner = THIS_MODULE, .owner = THIS_MODULE,
......
...@@ -72,6 +72,7 @@ ...@@ -72,6 +72,7 @@
#include <linux/delay.h> #include <linux/delay.h>
#include <asm/firmware.h> #include <asm/firmware.h>
#include <asm/vio.h> #include <asm/vio.h>
#include <asm/firmware.h>
#include <scsi/scsi.h> #include <scsi/scsi.h>
#include <scsi/scsi_cmnd.h> #include <scsi/scsi_cmnd.h>
#include <scsi/scsi_host.h> #include <scsi/scsi_host.h>
...@@ -426,8 +427,10 @@ static int map_sg_data(struct scsi_cmnd *cmd, ...@@ -426,8 +427,10 @@ static int map_sg_data(struct scsi_cmnd *cmd,
SG_ALL * sizeof(struct srp_direct_buf), SG_ALL * sizeof(struct srp_direct_buf),
&evt_struct->ext_list_token, 0); &evt_struct->ext_list_token, 0);
if (!evt_struct->ext_list) { if (!evt_struct->ext_list) {
if (!firmware_has_feature(FW_FEATURE_CMO))
sdev_printk(KERN_ERR, cmd->device, sdev_printk(KERN_ERR, cmd->device,
"Can't allocate memory for indirect table\n"); "Can't allocate memory "
"for indirect table\n");
return 0; return 0;
} }
} }
...@@ -743,7 +746,9 @@ static int ibmvscsi_queuecommand(struct scsi_cmnd *cmnd, ...@@ -743,7 +746,9 @@ static int ibmvscsi_queuecommand(struct scsi_cmnd *cmnd,
srp_cmd->lun = ((u64) lun) << 48; srp_cmd->lun = ((u64) lun) << 48;
if (!map_data_for_srp_cmd(cmnd, evt_struct, srp_cmd, hostdata->dev)) { if (!map_data_for_srp_cmd(cmnd, evt_struct, srp_cmd, hostdata->dev)) {
sdev_printk(KERN_ERR, cmnd->device, "couldn't convert cmd to srp_cmd\n"); if (!firmware_has_feature(FW_FEATURE_CMO))
sdev_printk(KERN_ERR, cmnd->device,
"couldn't convert cmd to srp_cmd\n");
free_event_struct(&hostdata->pool, evt_struct); free_event_struct(&hostdata->pool, evt_struct);
return SCSI_MLQUEUE_HOST_BUSY; return SCSI_MLQUEUE_HOST_BUSY;
} }
...@@ -855,7 +860,10 @@ static void send_mad_adapter_info(struct ibmvscsi_host_data *hostdata) ...@@ -855,7 +860,10 @@ static void send_mad_adapter_info(struct ibmvscsi_host_data *hostdata)
DMA_BIDIRECTIONAL); DMA_BIDIRECTIONAL);
if (dma_mapping_error(req->buffer)) { if (dma_mapping_error(req->buffer)) {
dev_err(hostdata->dev, "Unable to map request_buffer for adapter_info!\n"); if (!firmware_has_feature(FW_FEATURE_CMO))
dev_err(hostdata->dev,
"Unable to map request_buffer for "
"adapter_info!\n");
free_event_struct(&hostdata->pool, evt_struct); free_event_struct(&hostdata->pool, evt_struct);
return; return;
} }
...@@ -1400,7 +1408,9 @@ static int ibmvscsi_do_host_config(struct ibmvscsi_host_data *hostdata, ...@@ -1400,7 +1408,9 @@ static int ibmvscsi_do_host_config(struct ibmvscsi_host_data *hostdata,
DMA_BIDIRECTIONAL); DMA_BIDIRECTIONAL);
if (dma_mapping_error(host_config->buffer)) { if (dma_mapping_error(host_config->buffer)) {
dev_err(hostdata->dev, "dma_mapping error getting host config\n"); if (!firmware_has_feature(FW_FEATURE_CMO))
dev_err(hostdata->dev,
"dma_mapping error getting host config\n");
free_event_struct(&hostdata->pool, evt_struct); free_event_struct(&hostdata->pool, evt_struct);
return -1; return -1;
} }
...@@ -1604,7 +1614,7 @@ static struct scsi_host_template driver_template = { ...@@ -1604,7 +1614,7 @@ static struct scsi_host_template driver_template = {
.eh_host_reset_handler = ibmvscsi_eh_host_reset_handler, .eh_host_reset_handler = ibmvscsi_eh_host_reset_handler,
.slave_configure = ibmvscsi_slave_configure, .slave_configure = ibmvscsi_slave_configure,
.change_queue_depth = ibmvscsi_change_queue_depth, .change_queue_depth = ibmvscsi_change_queue_depth,
.cmd_per_lun = 16, .cmd_per_lun = IBMVSCSI_CMDS_PER_LUN_DEFAULT,
.can_queue = IBMVSCSI_MAX_REQUESTS_DEFAULT, .can_queue = IBMVSCSI_MAX_REQUESTS_DEFAULT,
.this_id = -1, .this_id = -1,
.sg_tablesize = SG_ALL, .sg_tablesize = SG_ALL,
...@@ -1612,6 +1622,26 @@ static struct scsi_host_template driver_template = { ...@@ -1612,6 +1622,26 @@ static struct scsi_host_template driver_template = {
.shost_attrs = ibmvscsi_attrs, .shost_attrs = ibmvscsi_attrs,
}; };
/**
* ibmvscsi_get_desired_dma - Calculate IO memory desired by the driver
*
* @vdev: struct vio_dev for the device whose desired IO mem is to be returned
*
* Return value:
* Number of bytes of IO data the driver will need to perform well.
*/
static unsigned long ibmvscsi_get_desired_dma(struct vio_dev *vdev)
{
/* iu_storage data allocated in initialize_event_pool */
unsigned long desired_io = max_requests * sizeof(union viosrp_iu);
/* add io space for sg data */
desired_io += (IBMVSCSI_MAX_SECTORS_DEFAULT *
IBMVSCSI_CMDS_PER_LUN_DEFAULT);
return desired_io;
}
/** /**
* Called by bus code for each adapter * Called by bus code for each adapter
*/ */
...@@ -1641,7 +1671,7 @@ static int ibmvscsi_probe(struct vio_dev *vdev, const struct vio_device_id *id) ...@@ -1641,7 +1671,7 @@ static int ibmvscsi_probe(struct vio_dev *vdev, const struct vio_device_id *id)
hostdata->host = host; hostdata->host = host;
hostdata->dev = dev; hostdata->dev = dev;
atomic_set(&hostdata->request_limit, -1); atomic_set(&hostdata->request_limit, -1);
hostdata->host->max_sectors = 32 * 8; /* default max I/O 32 pages */ hostdata->host->max_sectors = IBMVSCSI_MAX_SECTORS_DEFAULT;
rc = ibmvscsi_ops->init_crq_queue(&hostdata->queue, hostdata, max_requests); rc = ibmvscsi_ops->init_crq_queue(&hostdata->queue, hostdata, max_requests);
if (rc != 0 && rc != H_RESOURCE) { if (rc != 0 && rc != H_RESOURCE) {
...@@ -1735,6 +1765,7 @@ static struct vio_driver ibmvscsi_driver = { ...@@ -1735,6 +1765,7 @@ static struct vio_driver ibmvscsi_driver = {
.id_table = ibmvscsi_device_table, .id_table = ibmvscsi_device_table,
.probe = ibmvscsi_probe, .probe = ibmvscsi_probe,
.remove = ibmvscsi_remove, .remove = ibmvscsi_remove,
.get_desired_dma = ibmvscsi_get_desired_dma,
.driver = { .driver = {
.name = "ibmvscsi", .name = "ibmvscsi",
.owner = THIS_MODULE, .owner = THIS_MODULE,
......
...@@ -45,6 +45,8 @@ struct Scsi_Host; ...@@ -45,6 +45,8 @@ struct Scsi_Host;
#define MAX_INDIRECT_BUFS 10 #define MAX_INDIRECT_BUFS 10
#define IBMVSCSI_MAX_REQUESTS_DEFAULT 100 #define IBMVSCSI_MAX_REQUESTS_DEFAULT 100
#define IBMVSCSI_CMDS_PER_LUN_DEFAULT 16
#define IBMVSCSI_MAX_SECTORS_DEFAULT 256 /* 32 * 8 = default max I/O 32 pages */
#define IBMVSCSI_MAX_CMDS_PER_LUN 64 #define IBMVSCSI_MAX_CMDS_PER_LUN 64
/* ------------------------------------------------------------ /* ------------------------------------------------------------
......
...@@ -131,6 +131,15 @@ static int padzero(unsigned long elf_bss) ...@@ -131,6 +131,15 @@ static int padzero(unsigned long elf_bss)
#define STACK_ALLOC(sp, len) ({ sp -= len ; sp; }) #define STACK_ALLOC(sp, len) ({ sp -= len ; sp; })
#endif #endif
#ifndef ELF_BASE_PLATFORM
/*
* AT_BASE_PLATFORM indicates the "real" hardware/microarchitecture.
* If the arch defines ELF_BASE_PLATFORM (in asm/elf.h), the value
* will be copied to the user stack in the same manner as AT_PLATFORM.
*/
#define ELF_BASE_PLATFORM NULL
#endif
static int static int
create_elf_tables(struct linux_binprm *bprm, struct elfhdr *exec, create_elf_tables(struct linux_binprm *bprm, struct elfhdr *exec,
unsigned long load_addr, unsigned long interp_load_addr) unsigned long load_addr, unsigned long interp_load_addr)
...@@ -142,7 +151,9 @@ create_elf_tables(struct linux_binprm *bprm, struct elfhdr *exec, ...@@ -142,7 +151,9 @@ create_elf_tables(struct linux_binprm *bprm, struct elfhdr *exec,
elf_addr_t __user *envp; elf_addr_t __user *envp;
elf_addr_t __user *sp; elf_addr_t __user *sp;
elf_addr_t __user *u_platform; elf_addr_t __user *u_platform;
elf_addr_t __user *u_base_platform;
const char *k_platform = ELF_PLATFORM; const char *k_platform = ELF_PLATFORM;
const char *k_base_platform = ELF_BASE_PLATFORM;
int items; int items;
elf_addr_t *elf_info; elf_addr_t *elf_info;
int ei_index = 0; int ei_index = 0;
...@@ -172,6 +183,19 @@ create_elf_tables(struct linux_binprm *bprm, struct elfhdr *exec, ...@@ -172,6 +183,19 @@ create_elf_tables(struct linux_binprm *bprm, struct elfhdr *exec,
return -EFAULT; return -EFAULT;
} }
/*
* If this architecture has a "base" platform capability
* string, copy it to userspace.
*/
u_base_platform = NULL;
if (k_base_platform) {
size_t len = strlen(k_base_platform) + 1;
u_base_platform = (elf_addr_t __user *)STACK_ALLOC(p, len);
if (__copy_to_user(u_base_platform, k_base_platform, len))
return -EFAULT;
}
/* Create the ELF interpreter info */ /* Create the ELF interpreter info */
elf_info = (elf_addr_t *)current->mm->saved_auxv; elf_info = (elf_addr_t *)current->mm->saved_auxv;
/* update AT_VECTOR_SIZE_BASE if the number of NEW_AUX_ENT() changes */ /* update AT_VECTOR_SIZE_BASE if the number of NEW_AUX_ENT() changes */
...@@ -209,6 +233,10 @@ create_elf_tables(struct linux_binprm *bprm, struct elfhdr *exec, ...@@ -209,6 +233,10 @@ create_elf_tables(struct linux_binprm *bprm, struct elfhdr *exec,
NEW_AUX_ENT(AT_PLATFORM, NEW_AUX_ENT(AT_PLATFORM,
(elf_addr_t)(unsigned long)u_platform); (elf_addr_t)(unsigned long)u_platform);
} }
if (k_base_platform) {
NEW_AUX_ENT(AT_BASE_PLATFORM,
(elf_addr_t)(unsigned long)u_base_platform);
}
if (bprm->interp_flags & BINPRM_FLAGS_EXECFD) { if (bprm->interp_flags & BINPRM_FLAGS_EXECFD) {
NEW_AUX_ENT(AT_EXECFD, bprm->interp_data); NEW_AUX_ENT(AT_EXECFD, bprm->interp_data);
} }
......
...@@ -127,6 +127,8 @@ extern struct cpu_spec *identify_cpu(unsigned long offset, unsigned int pvr); ...@@ -127,6 +127,8 @@ extern struct cpu_spec *identify_cpu(unsigned long offset, unsigned int pvr);
extern void do_feature_fixups(unsigned long value, void *fixup_start, extern void do_feature_fixups(unsigned long value, void *fixup_start,
void *fixup_end); void *fixup_end);
extern const char *powerpc_base_platform;
#endif /* __ASSEMBLY__ */ #endif /* __ASSEMBLY__ */
/* CPU kernel features */ /* CPU kernel features */
......
...@@ -217,6 +217,14 @@ typedef elf_vrregset_t elf_fpxregset_t; ...@@ -217,6 +217,14 @@ typedef elf_vrregset_t elf_fpxregset_t;
#define ELF_PLATFORM (cur_cpu_spec->platform) #define ELF_PLATFORM (cur_cpu_spec->platform)
/* While ELF_PLATFORM indicates the ISA supported by the platform, it
* may not accurately reflect the underlying behavior of the hardware
* (as in the case of running in Power5+ compatibility mode on a
* Power6 machine). ELF_BASE_PLATFORM allows ld.so to load libraries
* that are tuned for the real hardware.
*/
#define ELF_BASE_PLATFORM (powerpc_base_platform)
#ifdef __powerpc64__ #ifdef __powerpc64__
# define ELF_PLAT_INIT(_r, load_addr) do { \ # define ELF_PLAT_INIT(_r, load_addr) do { \
_r->gpr[2] = load_addr; \ _r->gpr[2] = load_addr; \
......
...@@ -46,6 +46,7 @@ ...@@ -46,6 +46,7 @@
#define FW_FEATURE_PS3_LV1 ASM_CONST(0x0000000000800000) #define FW_FEATURE_PS3_LV1 ASM_CONST(0x0000000000800000)
#define FW_FEATURE_BEAT ASM_CONST(0x0000000001000000) #define FW_FEATURE_BEAT ASM_CONST(0x0000000001000000)
#define FW_FEATURE_BULK_REMOVE ASM_CONST(0x0000000002000000) #define FW_FEATURE_BULK_REMOVE ASM_CONST(0x0000000002000000)
#define FW_FEATURE_CMO ASM_CONST(0x0000000004000000)
#ifndef __ASSEMBLY__ #ifndef __ASSEMBLY__
...@@ -58,7 +59,7 @@ enum { ...@@ -58,7 +59,7 @@ enum {
FW_FEATURE_MIGRATE | FW_FEATURE_PERFMON | FW_FEATURE_CRQ | FW_FEATURE_MIGRATE | FW_FEATURE_PERFMON | FW_FEATURE_CRQ |
FW_FEATURE_VIO | FW_FEATURE_RDMA | FW_FEATURE_LLAN | FW_FEATURE_VIO | FW_FEATURE_RDMA | FW_FEATURE_LLAN |
FW_FEATURE_BULK | FW_FEATURE_XDABR | FW_FEATURE_MULTITCE | FW_FEATURE_BULK | FW_FEATURE_XDABR | FW_FEATURE_MULTITCE |
FW_FEATURE_SPLPAR | FW_FEATURE_LPAR, FW_FEATURE_SPLPAR | FW_FEATURE_LPAR | FW_FEATURE_CMO,
FW_FEATURE_PSERIES_ALWAYS = 0, FW_FEATURE_PSERIES_ALWAYS = 0,
FW_FEATURE_ISERIES_POSSIBLE = FW_FEATURE_ISERIES | FW_FEATURE_LPAR, FW_FEATURE_ISERIES_POSSIBLE = FW_FEATURE_ISERIES | FW_FEATURE_LPAR,
FW_FEATURE_ISERIES_ALWAYS = FW_FEATURE_ISERIES | FW_FEATURE_LPAR, FW_FEATURE_ISERIES_ALWAYS = FW_FEATURE_ISERIES | FW_FEATURE_LPAR,
......
...@@ -92,6 +92,11 @@ ...@@ -92,6 +92,11 @@
#define H_EXACT (1UL<<(63-24)) /* Use exact PTE or return H_PTEG_FULL */ #define H_EXACT (1UL<<(63-24)) /* Use exact PTE or return H_PTEG_FULL */
#define H_R_XLATE (1UL<<(63-25)) /* include a valid logical page num in the pte if the valid bit is set */ #define H_R_XLATE (1UL<<(63-25)) /* include a valid logical page num in the pte if the valid bit is set */
#define H_READ_4 (1UL<<(63-26)) /* Return 4 PTEs */ #define H_READ_4 (1UL<<(63-26)) /* Return 4 PTEs */
#define H_PAGE_STATE_CHANGE (1UL<<(63-28))
#define H_PAGE_UNUSED ((1UL<<(63-29)) | (1UL<<(63-30)))
#define H_PAGE_SET_UNUSED (H_PAGE_STATE_CHANGE | H_PAGE_UNUSED)
#define H_PAGE_SET_LOANED (H_PAGE_SET_UNUSED | (1UL<<(63-31)))
#define H_PAGE_SET_ACTIVE H_PAGE_STATE_CHANGE
#define H_AVPN (1UL<<(63-32)) /* An avpn is provided as a sanity test */ #define H_AVPN (1UL<<(63-32)) /* An avpn is provided as a sanity test */
#define H_ANDCOND (1UL<<(63-33)) #define H_ANDCOND (1UL<<(63-33))
#define H_ICACHE_INVALIDATE (1UL<<(63-40)) /* icbi, etc. (ignored for IO pages) */ #define H_ICACHE_INVALIDATE (1UL<<(63-40)) /* icbi, etc. (ignored for IO pages) */
...@@ -210,7 +215,9 @@ ...@@ -210,7 +215,9 @@
#define H_JOIN 0x298 #define H_JOIN 0x298
#define H_VASI_STATE 0x2A4 #define H_VASI_STATE 0x2A4
#define H_ENABLE_CRQ 0x2B0 #define H_ENABLE_CRQ 0x2B0
#define MAX_HCALL_OPCODE H_ENABLE_CRQ #define H_SET_MPP 0x2D0
#define H_GET_MPP 0x2D4
#define MAX_HCALL_OPCODE H_GET_MPP
#ifndef __ASSEMBLY__ #ifndef __ASSEMBLY__
...@@ -270,6 +277,20 @@ struct hcall_stats { ...@@ -270,6 +277,20 @@ struct hcall_stats {
}; };
#define HCALL_STAT_ARRAY_SIZE ((MAX_HCALL_OPCODE >> 2) + 1) #define HCALL_STAT_ARRAY_SIZE ((MAX_HCALL_OPCODE >> 2) + 1)
struct hvcall_mpp_data {
unsigned long entitled_mem;
unsigned long mapped_mem;
unsigned short group_num;
unsigned short pool_num;
unsigned char mem_weight;
unsigned char unallocated_mem_weight;
unsigned long unallocated_entitlement; /* value in bytes */
unsigned long pool_size;
signed long loan_request;
unsigned long backing_mem;
};
int h_get_mpp(struct hvcall_mpp_data *);
#endif /* __ASSEMBLY__ */ #endif /* __ASSEMBLY__ */
#endif /* __KERNEL__ */ #endif /* __KERNEL__ */
#endif /* _ASM_POWERPC_HVCALL_H */ #endif /* _ASM_POWERPC_HVCALL_H */
...@@ -125,7 +125,10 @@ struct lppaca { ...@@ -125,7 +125,10 @@ struct lppaca {
// NOTE: This value will ALWAYS be zero for dedicated processors and // NOTE: This value will ALWAYS be zero for dedicated processors and
// will NEVER be zero for shared processors (ie, initialized to a 1). // will NEVER be zero for shared processors (ie, initialized to a 1).
volatile u32 yield_count; // PLIC increments each dispatchx00-x03 volatile u32 yield_count; // PLIC increments each dispatchx00-x03
u8 reserved6[124]; // Reserved x04-x7F u32 reserved6;
volatile u64 cmo_faults; // CMO page fault count x08-x0F
volatile u64 cmo_fault_time; // CMO page fault time x10-x17
u8 reserved7[104]; // Reserved x18-x7F
//============================================================================= //=============================================================================
// CACHE_LINE_4-5 0x0180 - 0x027F Contains PMC interrupt data // CACHE_LINE_4-5 0x0180 - 0x027F Contains PMC interrupt data
......
...@@ -76,7 +76,7 @@ struct machdep_calls { ...@@ -76,7 +76,7 @@ struct machdep_calls {
* destroyed as well */ * destroyed as well */
void (*hpte_clear_all)(void); void (*hpte_clear_all)(void);
void (*tce_build)(struct iommu_table * tbl, int (*tce_build)(struct iommu_table *tbl,
long index, long index,
long npages, long npages,
unsigned long uaddr, unsigned long uaddr,
......
...@@ -60,10 +60,12 @@ ...@@ -60,10 +60,12 @@
#define MPC52xx_PSC_RXTX_FIFO_ALARM 0x0002 #define MPC52xx_PSC_RXTX_FIFO_ALARM 0x0002
#define MPC52xx_PSC_RXTX_FIFO_EMPTY 0x0001 #define MPC52xx_PSC_RXTX_FIFO_EMPTY 0x0001
/* PSC interrupt mask bits */ /* PSC interrupt status/mask bits */
#define MPC52xx_PSC_IMR_TXRDY 0x0100 #define MPC52xx_PSC_IMR_TXRDY 0x0100
#define MPC52xx_PSC_IMR_RXRDY 0x0200 #define MPC52xx_PSC_IMR_RXRDY 0x0200
#define MPC52xx_PSC_IMR_DB 0x0400 #define MPC52xx_PSC_IMR_DB 0x0400
#define MPC52xx_PSC_IMR_TXEMP 0x0800
#define MPC52xx_PSC_IMR_ORERR 0x1000
#define MPC52xx_PSC_IMR_IPC 0x8000 #define MPC52xx_PSC_IMR_IPC 0x8000
/* PSC input port change bit */ /* PSC input port change bit */
...@@ -92,6 +94,34 @@ ...@@ -92,6 +94,34 @@
#define MPC52xx_PSC_RFNUM_MASK 0x01ff #define MPC52xx_PSC_RFNUM_MASK 0x01ff
#define MPC52xx_PSC_SICR_DTS1 (1 << 29)
#define MPC52xx_PSC_SICR_SHDR (1 << 28)
#define MPC52xx_PSC_SICR_SIM_MASK (0xf << 24)
#define MPC52xx_PSC_SICR_SIM_UART (0x0 << 24)
#define MPC52xx_PSC_SICR_SIM_UART_DCD (0x8 << 24)
#define MPC52xx_PSC_SICR_SIM_CODEC_8 (0x1 << 24)
#define MPC52xx_PSC_SICR_SIM_CODEC_16 (0x2 << 24)
#define MPC52xx_PSC_SICR_SIM_AC97 (0x3 << 24)
#define MPC52xx_PSC_SICR_SIM_SIR (0x8 << 24)
#define MPC52xx_PSC_SICR_SIM_SIR_DCD (0xc << 24)
#define MPC52xx_PSC_SICR_SIM_MIR (0x5 << 24)
#define MPC52xx_PSC_SICR_SIM_FIR (0x6 << 24)
#define MPC52xx_PSC_SICR_SIM_CODEC_24 (0x7 << 24)
#define MPC52xx_PSC_SICR_SIM_CODEC_32 (0xf << 24)
#define MPC52xx_PSC_SICR_GENCLK (1 << 23)
#define MPC52xx_PSC_SICR_I2S (1 << 22)
#define MPC52xx_PSC_SICR_CLKPOL (1 << 21)
#define MPC52xx_PSC_SICR_SYNCPOL (1 << 20)
#define MPC52xx_PSC_SICR_CELLSLAVE (1 << 19)
#define MPC52xx_PSC_SICR_CELL2XCLK (1 << 18)
#define MPC52xx_PSC_SICR_ESAI (1 << 17)
#define MPC52xx_PSC_SICR_ENAC97 (1 << 16)
#define MPC52xx_PSC_SICR_SPI (1 << 15)
#define MPC52xx_PSC_SICR_MSTR (1 << 14)
#define MPC52xx_PSC_SICR_CPOL (1 << 13)
#define MPC52xx_PSC_SICR_CPHA (1 << 12)
#define MPC52xx_PSC_SICR_USEEOF (1 << 11)
#define MPC52xx_PSC_SICR_DISABLEEOF (1 << 10)
/* Structure of the hardware registers */ /* Structure of the hardware registers */
struct mpc52xx_psc { struct mpc52xx_psc {
...@@ -132,8 +162,12 @@ struct mpc52xx_psc { ...@@ -132,8 +162,12 @@ struct mpc52xx_psc {
u8 reserved5[3]; u8 reserved5[3];
u8 ctlr; /* PSC + 0x1c */ u8 ctlr; /* PSC + 0x1c */
u8 reserved6[3]; u8 reserved6[3];
u16 ccr; /* PSC + 0x20 */ /* BitClkDiv field of CCR is byte swapped in
u8 reserved7[14]; * the hardware for mpc5200/b compatibility */
u32 ccr; /* PSC + 0x20 */
u32 ac97_slots; /* PSC + 0x24 */
u32 ac97_cmd; /* PSC + 0x28 */
u32 ac97_data; /* PSC + 0x2c */
u8 ivr; /* PSC + 0x30 */ u8 ivr; /* PSC + 0x30 */
u8 reserved8[3]; u8 reserved8[3];
u8 ip; /* PSC + 0x34 */ u8 ip; /* PSC + 0x34 */
......
...@@ -38,6 +38,19 @@ extern void paging_init(void); ...@@ -38,6 +38,19 @@ extern void paging_init(void);
remap_pfn_range(vma, vaddr, pfn, size, prot) remap_pfn_range(vma, vaddr, pfn, size, prot)
#include <asm-generic/pgtable.h> #include <asm-generic/pgtable.h>
/*
* This gets called at the end of handling a page fault, when
* the kernel has put a new PTE into the page table for the process.
* We use it to ensure coherency between the i-cache and d-cache
* for the page which has just been mapped in.
* On machines which use an MMU hash table, we use this to put a
* corresponding HPTE into the hash table ahead of time, instead of
* waiting for the inevitable extra hash-table miss exception.
*/
extern void update_mmu_cache(struct vm_area_struct *, unsigned long, pte_t);
#endif /* __ASSEMBLY__ */ #endif /* __ASSEMBLY__ */
#endif /* __KERNEL__ */ #endif /* __KERNEL__ */
......
...@@ -31,6 +31,7 @@ asmlinkage int sys_vfork(unsigned long p1, unsigned long p2, ...@@ -31,6 +31,7 @@ asmlinkage int sys_vfork(unsigned long p1, unsigned long p2,
unsigned long p3, unsigned long p4, unsigned long p5, unsigned long p3, unsigned long p4, unsigned long p5,
unsigned long p6, struct pt_regs *regs); unsigned long p6, struct pt_regs *regs);
asmlinkage long sys_pipe(int __user *fildes); asmlinkage long sys_pipe(int __user *fildes);
asmlinkage long sys_pipe2(int __user *fildes, int flags);
asmlinkage long sys_rt_sigaction(int sig, asmlinkage long sys_rt_sigaction(int sig,
const struct sigaction __user *act, const struct sigaction __user *act,
struct sigaction __user *oact, size_t sigsetsize); struct sigaction __user *oact, size_t sigsetsize);
......
...@@ -316,3 +316,9 @@ COMPAT_SYS(fallocate) ...@@ -316,3 +316,9 @@ COMPAT_SYS(fallocate)
SYSCALL(subpage_prot) SYSCALL(subpage_prot)
COMPAT_SYS_SPU(timerfd_settime) COMPAT_SYS_SPU(timerfd_settime)
COMPAT_SYS_SPU(timerfd_gettime) COMPAT_SYS_SPU(timerfd_gettime)
COMPAT_SYS_SPU(signalfd4)
SYSCALL_SPU(eventfd2)
SYSCALL_SPU(epoll_create1)
SYSCALL_SPU(dup3)
SYSCALL_SPU(pipe2)
SYSCALL(inotify_init1)
...@@ -110,6 +110,8 @@ static inline int debugger_fault_handler(struct pt_regs *regs) { return 0; } ...@@ -110,6 +110,8 @@ static inline int debugger_fault_handler(struct pt_regs *regs) { return 0; }
#endif #endif
extern int set_dabr(unsigned long dabr); extern int set_dabr(unsigned long dabr);
extern void do_dabr(struct pt_regs *regs, unsigned long address,
unsigned long error_code);
extern void print_backtrace(unsigned long *); extern void print_backtrace(unsigned long *);
extern void show_regs(struct pt_regs * regs); extern void show_regs(struct pt_regs * regs);
extern void flush_instruction_cache(void); extern void flush_instruction_cache(void);
......
...@@ -162,16 +162,5 @@ extern void __flush_hash_table_range(struct mm_struct *mm, unsigned long start, ...@@ -162,16 +162,5 @@ extern void __flush_hash_table_range(struct mm_struct *mm, unsigned long start,
#endif #endif
/*
* This gets called at the end of handling a page fault, when
* the kernel has put a new PTE into the page table for the process.
* We use it to ensure coherency between the i-cache and d-cache
* for the page which has just been mapped in.
* On machines which use an MMU hash table, we use this to put a
* corresponding HPTE into the hash table ahead of time, instead of
* waiting for the inevitable extra hash-table miss exception.
*/
extern void update_mmu_cache(struct vm_area_struct *, unsigned long, pte_t);
#endif /*__KERNEL__ */ #endif /*__KERNEL__ */
#endif /* _ASM_POWERPC_TLBFLUSH_H */ #endif /* _ASM_POWERPC_TLBFLUSH_H */
...@@ -335,10 +335,16 @@ ...@@ -335,10 +335,16 @@
#define __NR_subpage_prot 310 #define __NR_subpage_prot 310
#define __NR_timerfd_settime 311 #define __NR_timerfd_settime 311
#define __NR_timerfd_gettime 312 #define __NR_timerfd_gettime 312
#define __NR_signalfd4 313
#define __NR_eventfd2 314
#define __NR_epoll_create1 315
#define __NR_dup3 316
#define __NR_pipe2 317
#define __NR_inotify_init1 318
#ifdef __KERNEL__ #ifdef __KERNEL__
#define __NR_syscalls 313 #define __NR_syscalls 319
#define __NR__exit __NR_exit #define __NR__exit __NR_exit
#define NR_syscalls __NR_syscalls #define NR_syscalls __NR_syscalls
......
...@@ -39,16 +39,32 @@ ...@@ -39,16 +39,32 @@
#define VIO_IRQ_DISABLE 0UL #define VIO_IRQ_DISABLE 0UL
#define VIO_IRQ_ENABLE 1UL #define VIO_IRQ_ENABLE 1UL
/*
* VIO CMO minimum entitlement for all devices and spare entitlement
*/
#define VIO_CMO_MIN_ENT 1562624
struct iommu_table; struct iommu_table;
/* /**
* The vio_dev structure is used to describe virtual I/O devices. * vio_dev - This structure is used to describe virtual I/O devices.
*
* @desired: set from return of driver's get_desired_dma() function
* @entitled: bytes of IO data that has been reserved for this device.
* @allocated: bytes of IO data currently in use by the device.
* @allocs_failed: number of DMA failures due to insufficient entitlement.
*/ */
struct vio_dev { struct vio_dev {
const char *name; const char *name;
const char *type; const char *type;
uint32_t unit_address; uint32_t unit_address;
unsigned int irq; unsigned int irq;
struct {
size_t desired;
size_t entitled;
size_t allocated;
atomic_t allocs_failed;
} cmo;
struct device dev; struct device dev;
}; };
...@@ -56,12 +72,19 @@ struct vio_driver { ...@@ -56,12 +72,19 @@ struct vio_driver {
const struct vio_device_id *id_table; const struct vio_device_id *id_table;
int (*probe)(struct vio_dev *dev, const struct vio_device_id *id); int (*probe)(struct vio_dev *dev, const struct vio_device_id *id);
int (*remove)(struct vio_dev *dev); int (*remove)(struct vio_dev *dev);
/* A driver must have a get_desired_dma() function to
* be loaded in a CMO environment if it uses DMA.
*/
unsigned long (*get_desired_dma)(struct vio_dev *dev);
struct device_driver driver; struct device_driver driver;
}; };
extern int vio_register_driver(struct vio_driver *drv); extern int vio_register_driver(struct vio_driver *drv);
extern void vio_unregister_driver(struct vio_driver *drv); extern void vio_unregister_driver(struct vio_driver *drv);
extern int vio_cmo_entitlement_update(size_t);
extern void vio_cmo_set_dev_desired(struct vio_dev *viodev, size_t desired);
extern void __devinit vio_unregister_device(struct vio_dev *dev); extern void __devinit vio_unregister_device(struct vio_dev *dev);
struct device_node; struct device_node;
......
...@@ -26,9 +26,13 @@ ...@@ -26,9 +26,13 @@
#define AT_SECURE 23 /* secure mode boolean */ #define AT_SECURE 23 /* secure mode boolean */
#define AT_BASE_PLATFORM 24 /* string identifying real platform, may
* differ from AT_PLATFORM. */
#define AT_EXECFN 31 /* filename of program */ #define AT_EXECFN 31 /* filename of program */
#ifdef __KERNEL__ #ifdef __KERNEL__
#define AT_VECTOR_SIZE_BASE 17 /* NEW_AUX_ENT entries in auxiliary table */ #define AT_VECTOR_SIZE_BASE 18 /* NEW_AUX_ENT entries in auxiliary table */
/* number of "#define AT_.*" above, minus {AT_NULL, AT_IGNORE, AT_NOTELF} */ /* number of "#define AT_.*" above, minus {AT_NULL, AT_IGNORE, AT_NOTELF} */
#endif #endif
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment