Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/paulus/powerpc
* 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/paulus/powerpc: [RAPIDIO] Change RapidIO doorbell source and target ID field to 16-bit [RAPIDIO] Add RapidIO connection info print out and re-training for broken connections [RAPIDIO] Add serial RapidIO controller support, which includes MPC8548, MPC8641 [RAPIDIO] Add RapidIO node probing into MPC86xx_HPCN board id table [RAPIDIO] Add RapidIO node into MPC8641HPCN dts file [RAPIDIO] Auto-probe the RapidIO system size [RAPIDIO] Add OF-tree support to RapidIO controller driver [RAPIDIO] Add RapidIO multi mport support [RAPIDIO] Move include/asm-ppc/rio.h to asm-powerpc [RAPIDIO] Add RapidIO option to kernel configuration [RAPIDIO] Change RIO function mpc85xx_ to fsl_ [POWERPC] Provide walk_memory_resource() for powerpc [POWERPC] Update lmb data structures for hotplug memory add/remove [POWERPC] Hotplug memory remove notifications for powerpc [POWERPC] windfarm: Add PowerMac 12,1 support [POWERPC] Fix building of pmac32 when CONFIG_NVRAM=m [POWERPC] Add IRQSTACKS support on ppc32 [POWERPC] Use __always_inline for xchg* and cmpxchg* [POWERPC] Add fast little-endian switch system call
This commit is contained in:
commit
867a89e0b7
|
@ -608,6 +608,19 @@ source "drivers/pcmcia/Kconfig"
|
|||
|
||||
source "drivers/pci/hotplug/Kconfig"
|
||||
|
||||
config HAS_RAPIDIO
|
||||
bool
|
||||
default n
|
||||
|
||||
config RAPIDIO
|
||||
bool "RapidIO support"
|
||||
depends on HAS_RAPIDIO
|
||||
help
|
||||
If you say Y here, the kernel will include drivers and
|
||||
infrastructure code to support RapidIO interconnect devices.
|
||||
|
||||
source "drivers/rapidio/Kconfig"
|
||||
|
||||
endmenu
|
||||
|
||||
menu "Advanced setup"
|
||||
|
|
|
@ -118,7 +118,6 @@ config XMON_DISASSEMBLY
|
|||
|
||||
config IRQSTACKS
|
||||
bool "Use separate kernel stacks when processing interrupts"
|
||||
depends on PPC64
|
||||
help
|
||||
If you say Y here the kernel will use separate kernel stacks
|
||||
for handling hard and soft interrupts. This can help avoid
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
serial1 = &serial1;
|
||||
pci0 = &pci0;
|
||||
pci1 = &pci1;
|
||||
rapidio0 = &rapidio0;
|
||||
};
|
||||
|
||||
cpus {
|
||||
|
@ -500,4 +501,15 @@
|
|||
0x0 0x00100000>;
|
||||
};
|
||||
};
|
||||
rapidio0: rapidio@f80c0000 {
|
||||
#address-cells = <2>;
|
||||
#size-cells = <2>;
|
||||
compatible = "fsl,rapidio-delta";
|
||||
reg = <0xf80c0000 0x20000>;
|
||||
ranges = <0 0 0xc0000000 0 0x20000000>;
|
||||
interrupt-parent = <&mpic>;
|
||||
/* err_irq bell_outb_irq bell_inb_irq
|
||||
msg1_tx_irq msg1_rx_irq msg2_tx_irq msg2_rx_irq */
|
||||
interrupts = <48 2 49 2 50 2 53 2 54 2 55 2 56 2>;
|
||||
};
|
||||
};
|
||||
|
|
|
@ -696,6 +696,7 @@ CONFIG_WINDFARM=y
|
|||
CONFIG_WINDFARM_PM81=y
|
||||
CONFIG_WINDFARM_PM91=y
|
||||
CONFIG_WINDFARM_PM112=y
|
||||
CONFIG_WINDFARM_PM121=y
|
||||
# CONFIG_PMAC_RACKMETER is not set
|
||||
CONFIG_NETDEVICES=y
|
||||
# CONFIG_NETDEVICES_MULTIQUEUE is not set
|
||||
|
|
|
@ -73,7 +73,6 @@ pci64-$(CONFIG_PPC64) += pci_dn.o isa-bridge.o
|
|||
obj-$(CONFIG_PCI) += pci_$(CONFIG_WORD_SIZE).o $(pci64-y) \
|
||||
pci-common.o
|
||||
obj-$(CONFIG_PCI_MSI) += msi.o
|
||||
obj-$(CONFIG_RAPIDIO) += rio.o
|
||||
obj-$(CONFIG_KEXEC) += machine_kexec.o crash.o \
|
||||
machine_kexec_$(CONFIG_WORD_SIZE).o
|
||||
obj-$(CONFIG_AUDIT) += audit.o
|
||||
|
|
|
@ -63,6 +63,7 @@ int main(void)
|
|||
#endif /* CONFIG_PPC64 */
|
||||
|
||||
DEFINE(KSP, offsetof(struct thread_struct, ksp));
|
||||
DEFINE(KSP_LIMIT, offsetof(struct thread_struct, ksp_limit));
|
||||
DEFINE(PT_REGS, offsetof(struct thread_struct, regs));
|
||||
DEFINE(THREAD_FPEXC_MODE, offsetof(struct thread_struct, fpexc_mode));
|
||||
DEFINE(THREAD_FPR0, offsetof(struct thread_struct, fpr[0]));
|
||||
|
|
|
@ -137,11 +137,12 @@ transfer_to_handler:
|
|||
2: /* if from kernel, check interrupted DOZE/NAP mode and
|
||||
* check for stack overflow
|
||||
*/
|
||||
lwz r9,THREAD_INFO-THREAD(r12)
|
||||
cmplw r1,r9 /* if r1 <= current->thread_info */
|
||||
lwz r9,KSP_LIMIT(r12)
|
||||
cmplw r1,r9 /* if r1 <= ksp_limit */
|
||||
ble- stack_ovf /* then the kernel stack overflowed */
|
||||
5:
|
||||
#ifdef CONFIG_6xx
|
||||
rlwinm r9,r1,0,0,31-THREAD_SHIFT
|
||||
tophys(r9,r9) /* check local flags */
|
||||
lwz r12,TI_LOCAL_FLAGS(r9)
|
||||
mtcrf 0x01,r12
|
||||
|
|
|
@ -239,6 +239,10 @@ instruction_access_slb_pSeries:
|
|||
.globl system_call_pSeries
|
||||
system_call_pSeries:
|
||||
HMT_MEDIUM
|
||||
BEGIN_FTR_SECTION
|
||||
cmpdi r0,0x1ebe
|
||||
beq- 1f
|
||||
END_FTR_SECTION_IFSET(CPU_FTR_REAL_LE)
|
||||
mr r9,r13
|
||||
mfmsr r10
|
||||
mfspr r13,SPRN_SPRG3
|
||||
|
@ -253,6 +257,13 @@ system_call_pSeries:
|
|||
rfid
|
||||
b . /* prevent speculative execution */
|
||||
|
||||
/* Fast LE/BE switch system call */
|
||||
1: mfspr r12,SPRN_SRR1
|
||||
xori r12,r12,MSR_LE
|
||||
mtspr SPRN_SRR1,r12
|
||||
rfid /* return to userspace */
|
||||
b .
|
||||
|
||||
STD_EXCEPTION_PSERIES(0xd00, single_step)
|
||||
STD_EXCEPTION_PSERIES(0xe00, trap_0e)
|
||||
|
||||
|
|
|
@ -307,6 +307,7 @@ void do_IRQ(struct pt_regs *regs)
|
|||
if (curtp != irqtp) {
|
||||
struct irq_desc *desc = irq_desc + irq;
|
||||
void *handler = desc->handle_irq;
|
||||
unsigned long saved_sp_limit = current->thread.ksp_limit;
|
||||
if (handler == NULL)
|
||||
handler = &__do_IRQ;
|
||||
irqtp->task = curtp->task;
|
||||
|
@ -319,7 +320,10 @@ void do_IRQ(struct pt_regs *regs)
|
|||
(irqtp->preempt_count & ~SOFTIRQ_MASK) |
|
||||
(curtp->preempt_count & SOFTIRQ_MASK);
|
||||
|
||||
current->thread.ksp_limit = (unsigned long)irqtp +
|
||||
_ALIGN_UP(sizeof(struct thread_info), 16);
|
||||
call_handle_irq(irq, desc, irqtp, handler);
|
||||
current->thread.ksp_limit = saved_sp_limit;
|
||||
irqtp->task = NULL;
|
||||
|
||||
|
||||
|
@ -352,9 +356,7 @@ void __init init_IRQ(void)
|
|||
{
|
||||
if (ppc_md.init_IRQ)
|
||||
ppc_md.init_IRQ();
|
||||
#ifdef CONFIG_PPC64
|
||||
irq_ctx_init();
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
@ -383,11 +385,15 @@ void irq_ctx_init(void)
|
|||
static inline void do_softirq_onstack(void)
|
||||
{
|
||||
struct thread_info *curtp, *irqtp;
|
||||
unsigned long saved_sp_limit = current->thread.ksp_limit;
|
||||
|
||||
curtp = current_thread_info();
|
||||
irqtp = softirq_ctx[smp_processor_id()];
|
||||
irqtp->task = curtp->task;
|
||||
current->thread.ksp_limit = (unsigned long)irqtp +
|
||||
_ALIGN_UP(sizeof(struct thread_info), 16);
|
||||
call_do_softirq(irqtp);
|
||||
current->thread.ksp_limit = saved_sp_limit;
|
||||
irqtp->task = NULL;
|
||||
}
|
||||
|
||||
|
|
|
@ -32,6 +32,31 @@
|
|||
|
||||
.text
|
||||
|
||||
#ifdef CONFIG_IRQSTACKS
|
||||
_GLOBAL(call_do_softirq)
|
||||
mflr r0
|
||||
stw r0,4(r1)
|
||||
stwu r1,THREAD_SIZE-STACK_FRAME_OVERHEAD(r3)
|
||||
mr r1,r3
|
||||
bl __do_softirq
|
||||
lwz r1,0(r1)
|
||||
lwz r0,4(r1)
|
||||
mtlr r0
|
||||
blr
|
||||
|
||||
_GLOBAL(call_handle_irq)
|
||||
mflr r0
|
||||
stw r0,4(r1)
|
||||
mtctr r6
|
||||
stwu r1,THREAD_SIZE-STACK_FRAME_OVERHEAD(r5)
|
||||
mr r1,r5
|
||||
bctrl
|
||||
lwz r1,0(r1)
|
||||
lwz r0,4(r1)
|
||||
mtlr r0
|
||||
blr
|
||||
#endif /* CONFIG_IRQSTACKS */
|
||||
|
||||
/*
|
||||
* This returns the high 64 bits of the product of two 64-bit numbers.
|
||||
*/
|
||||
|
|
|
@ -589,6 +589,8 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long usp,
|
|||
kregs = (struct pt_regs *) sp;
|
||||
sp -= STACK_FRAME_OVERHEAD;
|
||||
p->thread.ksp = sp;
|
||||
p->thread.ksp_limit = (unsigned long)task_stack_page(p) +
|
||||
_ALIGN_UP(sizeof(struct thread_info), 16);
|
||||
|
||||
#ifdef CONFIG_PPC64
|
||||
if (cpu_has_feature(CPU_FTR_SLB)) {
|
||||
|
|
|
@ -1,52 +0,0 @@
|
|||
/*
|
||||
* RapidIO PPC32 support
|
||||
*
|
||||
* Copyright 2005 MontaVista Software, Inc.
|
||||
* Matt Porter <mporter@kernel.crashing.org>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version.
|
||||
*/
|
||||
|
||||
#include <linux/init.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/rio.h>
|
||||
|
||||
#include <asm/rio.h>
|
||||
|
||||
/**
|
||||
* platform_rio_init - Do platform specific RIO init
|
||||
*
|
||||
* Any platform specific initialization of RapdIO
|
||||
* hardware is done here as well as registration
|
||||
* of any active master ports in the system.
|
||||
*/
|
||||
void __attribute__ ((weak))
|
||||
platform_rio_init(void)
|
||||
{
|
||||
printk(KERN_WARNING "RIO: No platform_rio_init() present\n");
|
||||
}
|
||||
|
||||
/**
|
||||
* ppc_rio_init - Do PPC32 RIO init
|
||||
*
|
||||
* Calls platform-specific RIO init code and then calls
|
||||
* rio_init_mports() to initialize any master ports that
|
||||
* have been registered with the RIO subsystem.
|
||||
*/
|
||||
static int __init ppc_rio_init(void)
|
||||
{
|
||||
printk(KERN_INFO "RIO: RapidIO init\n");
|
||||
|
||||
/* Platform specific initialization */
|
||||
platform_rio_init();
|
||||
|
||||
/* Enumerate all registered ports */
|
||||
rio_init_mports();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
subsys_initcall(ppc_rio_init);
|
|
@ -16,6 +16,7 @@
|
|||
#include <linux/root_dev.h>
|
||||
#include <linux/cpu.h>
|
||||
#include <linux/console.h>
|
||||
#include <linux/lmb.h>
|
||||
|
||||
#include <asm/io.h>
|
||||
#include <asm/prom.h>
|
||||
|
@ -229,6 +230,24 @@ int __init ppc_init(void)
|
|||
|
||||
arch_initcall(ppc_init);
|
||||
|
||||
#ifdef CONFIG_IRQSTACKS
|
||||
static void __init irqstack_early_init(void)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
/* interrupt stacks must be in lowmem, we get that for free on ppc32
|
||||
* as the lmb is limited to lowmem by LMB_REAL_LIMIT */
|
||||
for_each_possible_cpu(i) {
|
||||
softirq_ctx[i] = (struct thread_info *)
|
||||
__va(lmb_alloc(THREAD_SIZE, THREAD_SIZE));
|
||||
hardirq_ctx[i] = (struct thread_info *)
|
||||
__va(lmb_alloc(THREAD_SIZE, THREAD_SIZE));
|
||||
}
|
||||
}
|
||||
#else
|
||||
#define irqstack_early_init()
|
||||
#endif
|
||||
|
||||
/* Warning, IO base is not yet inited */
|
||||
void __init setup_arch(char **cmdline_p)
|
||||
{
|
||||
|
@ -286,6 +305,8 @@ void __init setup_arch(char **cmdline_p)
|
|||
init_mm.end_data = (unsigned long) _edata;
|
||||
init_mm.brk = klimit;
|
||||
|
||||
irqstack_early_init();
|
||||
|
||||
/* set up the bootmem stuff with available memory */
|
||||
do_init_bootmem();
|
||||
if ( ppc_md.progress ) ppc_md.progress("setup_arch: bootmem", 0x3eab);
|
||||
|
|
|
@ -154,19 +154,35 @@ out:
|
|||
|
||||
/*
|
||||
* walk_memory_resource() needs to make sure there is no holes in a given
|
||||
* memory range. On PPC64, since this range comes from /sysfs, the range
|
||||
* is guaranteed to be valid, non-overlapping and can not contain any
|
||||
* holes. By the time we get here (memory add or remove), /proc/device-tree
|
||||
* is updated and correct. Only reason we need to check against device-tree
|
||||
* would be if we allow user-land to specify a memory range through a
|
||||
* system call/ioctl etc. instead of doing offline/online through /sysfs.
|
||||
* memory range. PPC64 does not maintain the memory layout in /proc/iomem.
|
||||
* Instead it maintains it in lmb.memory structures. Walk through the
|
||||
* memory regions, find holes and callback for contiguous regions.
|
||||
*/
|
||||
int
|
||||
walk_memory_resource(unsigned long start_pfn, unsigned long nr_pages, void *arg,
|
||||
int (*func)(unsigned long, unsigned long, void *))
|
||||
{
|
||||
return (*func)(start_pfn, nr_pages, arg);
|
||||
struct lmb_property res;
|
||||
unsigned long pfn, len;
|
||||
u64 end;
|
||||
int ret = -1;
|
||||
|
||||
res.base = (u64) start_pfn << PAGE_SHIFT;
|
||||
res.size = (u64) nr_pages << PAGE_SHIFT;
|
||||
|
||||
end = res.base + res.size - 1;
|
||||
while ((res.base < end) && (lmb_find(&res) >= 0)) {
|
||||
pfn = (unsigned long)(res.base >> PAGE_SHIFT);
|
||||
len = (unsigned long)(res.size >> PAGE_SHIFT);
|
||||
ret = (*func)(pfn, len, arg);
|
||||
if (ret)
|
||||
break;
|
||||
res.base += (res.size + 1);
|
||||
res.size = (end - res.base + 1);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(walk_memory_resource);
|
||||
|
||||
#endif /* CONFIG_MEMORY_HOTPLUG */
|
||||
|
||||
|
|
|
@ -8,6 +8,7 @@ config MPC8641_HPCN
|
|||
select PPC_I8259
|
||||
select DEFAULT_UIMAGE
|
||||
select FSL_ULI1575
|
||||
select HAS_RAPIDIO
|
||||
help
|
||||
This option enables support for the MPC8641 HPCN board.
|
||||
|
||||
|
|
|
@ -221,6 +221,7 @@ mpc86xx_time_init(void)
|
|||
|
||||
static __initdata struct of_device_id of_bus_ids[] = {
|
||||
{ .compatible = "simple-bus", },
|
||||
{ .compatible = "fsl,rapidio-delta", },
|
||||
{},
|
||||
};
|
||||
|
||||
|
|
|
@ -6,7 +6,10 @@ obj-y += pic.o setup.o time.o feature.o pci.o \
|
|||
obj-$(CONFIG_PMAC_BACKLIGHT) += backlight.o
|
||||
obj-$(CONFIG_CPU_FREQ_PMAC) += cpufreq_32.o
|
||||
obj-$(CONFIG_CPU_FREQ_PMAC64) += cpufreq_64.o
|
||||
obj-$(CONFIG_NVRAM) += nvram.o
|
||||
# CONFIG_NVRAM is an arch. independant tristate symbol, for pmac32 we really
|
||||
# need this to be a bool. Cheat here and pretend CONFIG_NVRAM=m is really
|
||||
# CONFIG_NVRAM=y
|
||||
obj-$(CONFIG_NVRAM:m=y) += nvram.o
|
||||
# ppc64 pmac doesn't define CONFIG_NVRAM but needs nvram stuff
|
||||
obj-$(CONFIG_PPC64) += nvram.o
|
||||
obj-$(CONFIG_PPC32) += bootx_init.o
|
||||
|
|
|
@ -337,7 +337,8 @@ static void __init pmac_setup_arch(void)
|
|||
find_via_pmu();
|
||||
smu_init();
|
||||
|
||||
#if defined(CONFIG_NVRAM) || defined(CONFIG_PPC64)
|
||||
#if defined(CONFIG_NVRAM) || defined(CONFIG_NVRAM_MODULE) || \
|
||||
defined(CONFIG_PPC64)
|
||||
pmac_nvram_init();
|
||||
#endif
|
||||
|
||||
|
|
|
@ -18,6 +18,7 @@ obj-$(CONFIG_PCI) += pci.o pci_dlpar.o
|
|||
obj-$(CONFIG_PCI_MSI) += msi.o
|
||||
|
||||
obj-$(CONFIG_HOTPLUG_CPU) += hotplug-cpu.o
|
||||
obj-$(CONFIG_MEMORY_HOTPLUG) += hotplug-memory.o
|
||||
|
||||
obj-$(CONFIG_HVC_CONSOLE) += hvconsole.o
|
||||
obj-$(CONFIG_HVCS) += hvcserver.o
|
||||
|
|
|
@ -0,0 +1,141 @@
|
|||
/*
|
||||
* pseries Memory Hotplug infrastructure.
|
||||
*
|
||||
* Copyright (C) 2008 Badari Pulavarty, IBM Corporation
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version
|
||||
* 2 of the License, or (at your option) any later version.
|
||||
*/
|
||||
|
||||
#include <linux/of.h>
|
||||
#include <linux/lmb.h>
|
||||
#include <asm/firmware.h>
|
||||
#include <asm/machdep.h>
|
||||
#include <asm/pSeries_reconfig.h>
|
||||
|
||||
static int pseries_remove_memory(struct device_node *np)
|
||||
{
|
||||
const char *type;
|
||||
const unsigned int *my_index;
|
||||
const unsigned int *regs;
|
||||
u64 start_pfn, start;
|
||||
struct zone *zone;
|
||||
int ret = -EINVAL;
|
||||
|
||||
/*
|
||||
* Check to see if we are actually removing memory
|
||||
*/
|
||||
type = of_get_property(np, "device_type", NULL);
|
||||
if (type == NULL || strcmp(type, "memory") != 0)
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* Find the memory index and size of the removing section
|
||||
*/
|
||||
my_index = of_get_property(np, "ibm,my-drc-index", NULL);
|
||||
if (!my_index)
|
||||
return ret;
|
||||
|
||||
regs = of_get_property(np, "reg", NULL);
|
||||
if (!regs)
|
||||
return ret;
|
||||
|
||||
start_pfn = section_nr_to_pfn(*my_index & 0xffff);
|
||||
zone = page_zone(pfn_to_page(start_pfn));
|
||||
|
||||
/*
|
||||
* Remove section mappings and sysfs entries for the
|
||||
* section of the memory we are removing.
|
||||
*
|
||||
* NOTE: Ideally, this should be done in generic code like
|
||||
* remove_memory(). But remove_memory() gets called by writing
|
||||
* to sysfs "state" file and we can't remove sysfs entries
|
||||
* while writing to it. So we have to defer it to here.
|
||||
*/
|
||||
ret = __remove_pages(zone, start_pfn, regs[3] >> PAGE_SHIFT);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/*
|
||||
* Update memory regions for memory remove
|
||||
*/
|
||||
lmb_remove(start_pfn << PAGE_SHIFT, regs[3]);
|
||||
|
||||
/*
|
||||
* Remove htab bolted mappings for this section of memory
|
||||
*/
|
||||
start = (unsigned long)__va(start_pfn << PAGE_SHIFT);
|
||||
ret = remove_section_mapping(start, start + regs[3]);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int pseries_add_memory(struct device_node *np)
|
||||
{
|
||||
const char *type;
|
||||
const unsigned int *my_index;
|
||||
const unsigned int *regs;
|
||||
u64 start_pfn;
|
||||
int ret = -EINVAL;
|
||||
|
||||
/*
|
||||
* Check to see if we are actually adding memory
|
||||
*/
|
||||
type = of_get_property(np, "device_type", NULL);
|
||||
if (type == NULL || strcmp(type, "memory") != 0)
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* Find the memory index and size of the added section
|
||||
*/
|
||||
my_index = of_get_property(np, "ibm,my-drc-index", NULL);
|
||||
if (!my_index)
|
||||
return ret;
|
||||
|
||||
regs = of_get_property(np, "reg", NULL);
|
||||
if (!regs)
|
||||
return ret;
|
||||
|
||||
start_pfn = section_nr_to_pfn(*my_index & 0xffff);
|
||||
|
||||
/*
|
||||
* Update memory region to represent the memory add
|
||||
*/
|
||||
lmb_add(start_pfn << PAGE_SHIFT, regs[3]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int pseries_memory_notifier(struct notifier_block *nb,
|
||||
unsigned long action, void *node)
|
||||
{
|
||||
int err = NOTIFY_OK;
|
||||
|
||||
switch (action) {
|
||||
case PSERIES_RECONFIG_ADD:
|
||||
if (pseries_add_memory(node))
|
||||
err = NOTIFY_BAD;
|
||||
break;
|
||||
case PSERIES_RECONFIG_REMOVE:
|
||||
if (pseries_remove_memory(node))
|
||||
err = NOTIFY_BAD;
|
||||
break;
|
||||
default:
|
||||
err = NOTIFY_DONE;
|
||||
break;
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
static struct notifier_block pseries_mem_nb = {
|
||||
.notifier_call = pseries_memory_notifier,
|
||||
};
|
||||
|
||||
static int __init pseries_memory_hotplug_init(void)
|
||||
{
|
||||
if (firmware_has_feature(FW_FEATURE_LPAR))
|
||||
pSeries_reconfig_notifier_register(&pseries_mem_nb);
|
||||
|
||||
return 0;
|
||||
}
|
||||
machine_device_initcall(pseries, pseries_memory_hotplug_init);
|
File diff suppressed because it is too large
Load Diff
|
@ -1,20 +0,0 @@
|
|||
/*
|
||||
* MPC85xx RapidIO definitions
|
||||
*
|
||||
* Copyright 2005 MontaVista Software, Inc.
|
||||
* Matt Porter <mporter@kernel.crashing.org>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version.
|
||||
*/
|
||||
|
||||
#ifndef __PPC_SYSLIB_PPC85XX_RIO_H
|
||||
#define __PPC_SYSLIB_PPC85XX_RIO_H
|
||||
|
||||
#include <linux/init.h>
|
||||
|
||||
extern void mpc85xx_rio_setup(int law_start, int law_size);
|
||||
|
||||
#endif /* __PPC_SYSLIB_PPC85XX_RIO_H */
|
|
@ -234,6 +234,14 @@ config WINDFARM_PM112
|
|||
which are the recent dual and quad G5 machines using the
|
||||
970MP dual-core processor.
|
||||
|
||||
config WINDFARM_PM121
|
||||
tristate "Support for thermal management on PowerMac12,1"
|
||||
depends on WINDFARM && I2C && PMAC_SMU
|
||||
select I2C_POWERMAC
|
||||
help
|
||||
This driver provides thermal control for the PowerMac12,1
|
||||
which is the iMac G5 (iSight).
|
||||
|
||||
config ANSLCD
|
||||
tristate "Support for ANS LCD display"
|
||||
depends on ADB_CUDA && PPC_PMAC
|
||||
|
|
|
@ -42,4 +42,9 @@ obj-$(CONFIG_WINDFARM_PM112) += windfarm_pm112.o windfarm_smu_sat.o \
|
|||
windfarm_smu_sensors.o \
|
||||
windfarm_max6690_sensor.o \
|
||||
windfarm_lm75_sensor.o windfarm_pid.o
|
||||
obj-$(CONFIG_WINDFARM_PM121) += windfarm_pm121.o windfarm_smu_sat.o \
|
||||
windfarm_smu_controls.o \
|
||||
windfarm_smu_sensors.o \
|
||||
windfarm_max6690_sensor.o \
|
||||
windfarm_lm75_sensor.o windfarm_pid.o
|
||||
obj-$(CONFIG_PMAC_RACKMETER) += rack-meter.o
|
||||
|
|
|
@ -127,6 +127,12 @@ static struct wf_lm75_sensor *wf_lm75_create(struct i2c_adapter *adapter,
|
|||
*/
|
||||
if (!strcmp(loc, "Hard drive") || !strcmp(loc, "DRIVE BAY"))
|
||||
lm->sens.name = "hd-temp";
|
||||
else if (!strcmp(loc, "Incoming Air Temp"))
|
||||
lm->sens.name = "incoming-air-temp";
|
||||
else if (!strcmp(loc, "ODD Temp"))
|
||||
lm->sens.name = "optical-drive-temp";
|
||||
else if (!strcmp(loc, "HD Temp"))
|
||||
lm->sens.name = "hard-drive-temp";
|
||||
else
|
||||
goto fail;
|
||||
|
||||
|
|
|
@ -77,18 +77,28 @@ static struct wf_sensor_ops wf_max6690_ops = {
|
|||
.owner = THIS_MODULE,
|
||||
};
|
||||
|
||||
static void wf_max6690_create(struct i2c_adapter *adapter, u8 addr)
|
||||
static void wf_max6690_create(struct i2c_adapter *adapter, u8 addr,
|
||||
const char *loc)
|
||||
{
|
||||
struct wf_6690_sensor *max;
|
||||
char *name = "backside-temp";
|
||||
char *name;
|
||||
|
||||
max = kzalloc(sizeof(struct wf_6690_sensor), GFP_KERNEL);
|
||||
if (max == NULL) {
|
||||
printk(KERN_ERR "windfarm: Couldn't create MAX6690 sensor %s: "
|
||||
"no memory\n", name);
|
||||
"no memory\n", loc);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!strcmp(loc, "BACKSIDE"))
|
||||
name = "backside-temp";
|
||||
else if (!strcmp(loc, "NB Ambient"))
|
||||
name = "north-bridge-temp";
|
||||
else if (!strcmp(loc, "GPU Ambient"))
|
||||
name = "gpu-temp";
|
||||
else
|
||||
goto fail;
|
||||
|
||||
max->sens.ops = &wf_max6690_ops;
|
||||
max->sens.name = name;
|
||||
max->i2c.addr = addr >> 1;
|
||||
|
@ -138,9 +148,7 @@ static int wf_max6690_attach(struct i2c_adapter *adapter)
|
|||
if (loc == NULL || addr == 0)
|
||||
continue;
|
||||
printk("found max6690, loc=%s addr=0x%02x\n", loc, addr);
|
||||
if (strcmp(loc, "BACKSIDE"))
|
||||
continue;
|
||||
wf_max6690_create(adapter, addr);
|
||||
wf_max6690_create(adapter, addr, loc);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -218,6 +218,10 @@ static struct smu_fan_control *smu_fan_create(struct device_node *node,
|
|||
fct->ctrl.name = "cpu-fan";
|
||||
else if (!strcmp(l, "Hard Drive") || !strcmp(l, "Hard drive"))
|
||||
fct->ctrl.name = "drive-bay-fan";
|
||||
else if (!strcmp(l, "HDD Fan")) /* seen on iMac G5 iSight */
|
||||
fct->ctrl.name = "hard-drive-fan";
|
||||
else if (!strcmp(l, "ODD Fan")) /* same */
|
||||
fct->ctrl.name = "optical-drive-fan";
|
||||
|
||||
/* Unrecognized fan, bail out */
|
||||
if (fct->ctrl.name == NULL)
|
||||
|
|
|
@ -77,7 +77,7 @@ static int rionet_capable = 1;
|
|||
* could be made into a hash table to save memory depending
|
||||
* on system trade-offs.
|
||||
*/
|
||||
static struct rio_dev *rionet_active[RIO_MAX_ROUTE_ENTRIES];
|
||||
static struct rio_dev **rionet_active;
|
||||
|
||||
#define is_rionet_capable(pef, src_ops, dst_ops) \
|
||||
((pef & RIO_PEF_INB_MBOX) && \
|
||||
|
@ -195,7 +195,8 @@ static int rionet_start_xmit(struct sk_buff *skb, struct net_device *ndev)
|
|||
}
|
||||
|
||||
if (eth->h_dest[0] & 0x01) {
|
||||
for (i = 0; i < RIO_MAX_ROUTE_ENTRIES; i++)
|
||||
for (i = 0; i < RIO_MAX_ROUTE_ENTRIES(rnet->mport->sys_size);
|
||||
i++)
|
||||
if (rionet_active[i])
|
||||
rionet_queue_tx_msg(skb, ndev,
|
||||
rionet_active[i]);
|
||||
|
@ -385,6 +386,8 @@ static void rionet_remove(struct rio_dev *rdev)
|
|||
struct net_device *ndev = NULL;
|
||||
struct rionet_peer *peer, *tmp;
|
||||
|
||||
free_pages((unsigned long)rionet_active, rdev->net->hport->sys_size ?
|
||||
__ilog2(sizeof(void *)) + 4 : 0);
|
||||
unregister_netdev(ndev);
|
||||
kfree(ndev);
|
||||
|
||||
|
@ -443,6 +446,15 @@ static int rionet_setup_netdev(struct rio_mport *mport)
|
|||
goto out;
|
||||
}
|
||||
|
||||
rionet_active = (struct rio_dev **)__get_free_pages(GFP_KERNEL,
|
||||
mport->sys_size ? __ilog2(sizeof(void *)) + 4 : 0);
|
||||
if (!rionet_active) {
|
||||
rc = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
memset((void *)rionet_active, 0, sizeof(void *) *
|
||||
RIO_MAX_ROUTE_ENTRIES(mport->sys_size));
|
||||
|
||||
/* Set up private area */
|
||||
rnet = (struct rionet_private *)ndev->priv;
|
||||
rnet->mport = mport;
|
||||
|
|
|
@ -1,14 +1,6 @@
|
|||
#
|
||||
# RapidIO configuration
|
||||
#
|
||||
config RAPIDIO_8_BIT_TRANSPORT
|
||||
bool "8-bit transport addressing"
|
||||
depends on RAPIDIO
|
||||
---help---
|
||||
By default, the kernel assumes a 16-bit addressed RapidIO
|
||||
network. By selecting this option, the kernel will support
|
||||
an 8-bit addressed network.
|
||||
|
||||
config RAPIDIO_DISC_TIMEOUT
|
||||
int "Discovery timeout duration (seconds)"
|
||||
depends on RAPIDIO
|
||||
|
|
|
@ -48,7 +48,7 @@ int __rio_local_read_config_##size \
|
|||
u32 data = 0; \
|
||||
if (RIO_##size##_BAD) return RIO_BAD_SIZE; \
|
||||
spin_lock_irqsave(&rio_config_lock, flags); \
|
||||
res = mport->ops->lcread(mport->id, offset, len, &data); \
|
||||
res = mport->ops->lcread(mport, mport->id, offset, len, &data); \
|
||||
*value = (type)data; \
|
||||
spin_unlock_irqrestore(&rio_config_lock, flags); \
|
||||
return res; \
|
||||
|
@ -71,7 +71,7 @@ int __rio_local_write_config_##size \
|
|||
unsigned long flags; \
|
||||
if (RIO_##size##_BAD) return RIO_BAD_SIZE; \
|
||||
spin_lock_irqsave(&rio_config_lock, flags); \
|
||||
res = mport->ops->lcwrite(mport->id, offset, len, value); \
|
||||
res = mport->ops->lcwrite(mport, mport->id, offset, len, value);\
|
||||
spin_unlock_irqrestore(&rio_config_lock, flags); \
|
||||
return res; \
|
||||
}
|
||||
|
@ -108,7 +108,7 @@ int rio_mport_read_config_##size \
|
|||
u32 data = 0; \
|
||||
if (RIO_##size##_BAD) return RIO_BAD_SIZE; \
|
||||
spin_lock_irqsave(&rio_config_lock, flags); \
|
||||
res = mport->ops->cread(mport->id, destid, hopcount, offset, len, &data); \
|
||||
res = mport->ops->cread(mport, mport->id, destid, hopcount, offset, len, &data); \
|
||||
*value = (type)data; \
|
||||
spin_unlock_irqrestore(&rio_config_lock, flags); \
|
||||
return res; \
|
||||
|
@ -131,7 +131,7 @@ int rio_mport_write_config_##size \
|
|||
unsigned long flags; \
|
||||
if (RIO_##size##_BAD) return RIO_BAD_SIZE; \
|
||||
spin_lock_irqsave(&rio_config_lock, flags); \
|
||||
res = mport->ops->cwrite(mport->id, destid, hopcount, offset, len, value); \
|
||||
res = mport->ops->cwrite(mport, mport->id, destid, hopcount, offset, len, value); \
|
||||
spin_unlock_irqrestore(&rio_config_lock, flags); \
|
||||
return res; \
|
||||
}
|
||||
|
@ -166,7 +166,7 @@ int rio_mport_send_doorbell(struct rio_mport *mport, u16 destid, u16 data)
|
|||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&rio_doorbell_lock, flags);
|
||||
res = mport->ops->dsend(mport->id, destid, data);
|
||||
res = mport->ops->dsend(mport, mport->id, destid, data);
|
||||
spin_unlock_irqrestore(&rio_doorbell_lock, flags);
|
||||
|
||||
return res;
|
||||
|
|
|
@ -73,7 +73,7 @@ static u16 rio_get_device_id(struct rio_mport *port, u16 destid, u8 hopcount)
|
|||
|
||||
rio_mport_read_config_32(port, destid, hopcount, RIO_DID_CSR, &result);
|
||||
|
||||
return RIO_GET_DID(result);
|
||||
return RIO_GET_DID(port->sys_size, result);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -88,7 +88,7 @@ static u16 rio_get_device_id(struct rio_mport *port, u16 destid, u8 hopcount)
|
|||
static void rio_set_device_id(struct rio_mport *port, u16 destid, u8 hopcount, u16 did)
|
||||
{
|
||||
rio_mport_write_config_32(port, destid, hopcount, RIO_DID_CSR,
|
||||
RIO_SET_DID(did));
|
||||
RIO_SET_DID(port->sys_size, did));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -100,7 +100,8 @@ static void rio_set_device_id(struct rio_mport *port, u16 destid, u8 hopcount, u
|
|||
*/
|
||||
static void rio_local_set_device_id(struct rio_mport *port, u16 did)
|
||||
{
|
||||
rio_local_write_config_32(port, RIO_DID_CSR, RIO_SET_DID(did));
|
||||
rio_local_write_config_32(port, RIO_DID_CSR, RIO_SET_DID(port->sys_size,
|
||||
did));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -350,8 +351,18 @@ static struct rio_dev *rio_setup_device(struct rio_net *net,
|
|||
rswitch->switchid = next_switchid;
|
||||
rswitch->hopcount = hopcount;
|
||||
rswitch->destid = destid;
|
||||
rswitch->route_table = kzalloc(sizeof(u8)*
|
||||
RIO_MAX_ROUTE_ENTRIES(port->sys_size),
|
||||
GFP_KERNEL);
|
||||
if (!rswitch->route_table) {
|
||||
kfree(rdev);
|
||||
rdev = NULL;
|
||||
kfree(rswitch);
|
||||
goto out;
|
||||
}
|
||||
/* Initialize switch route table */
|
||||
for (rdid = 0; rdid < RIO_MAX_ROUTE_ENTRIES; rdid++)
|
||||
for (rdid = 0; rdid < RIO_MAX_ROUTE_ENTRIES(port->sys_size);
|
||||
rdid++)
|
||||
rswitch->route_table[rdid] = RIO_INVALID_ROUTE;
|
||||
rdev->rswitch = rswitch;
|
||||
sprintf(rio_name(rdev), "%02x:s:%04x", rdev->net->id,
|
||||
|
@ -480,7 +491,7 @@ static u16 rio_get_host_deviceid_lock(struct rio_mport *port, u8 hopcount)
|
|||
{
|
||||
u32 result;
|
||||
|
||||
rio_mport_read_config_32(port, RIO_ANY_DESTID, hopcount,
|
||||
rio_mport_read_config_32(port, RIO_ANY_DESTID(port->sys_size), hopcount,
|
||||
RIO_HOST_DID_LOCK_CSR, &result);
|
||||
|
||||
return (u16) (result & 0xffff);
|
||||
|
@ -571,14 +582,16 @@ static int rio_enum_peer(struct rio_net *net, struct rio_mport *port,
|
|||
}
|
||||
|
||||
/* Attempt to acquire device lock */
|
||||
rio_mport_write_config_32(port, RIO_ANY_DESTID, hopcount,
|
||||
rio_mport_write_config_32(port, RIO_ANY_DESTID(port->sys_size),
|
||||
hopcount,
|
||||
RIO_HOST_DID_LOCK_CSR, port->host_deviceid);
|
||||
while ((tmp = rio_get_host_deviceid_lock(port, hopcount))
|
||||
< port->host_deviceid) {
|
||||
/* Delay a bit */
|
||||
mdelay(1);
|
||||
/* Attempt to acquire device lock again */
|
||||
rio_mport_write_config_32(port, RIO_ANY_DESTID, hopcount,
|
||||
rio_mport_write_config_32(port, RIO_ANY_DESTID(port->sys_size),
|
||||
hopcount,
|
||||
RIO_HOST_DID_LOCK_CSR,
|
||||
port->host_deviceid);
|
||||
}
|
||||
|
@ -590,7 +603,9 @@ static int rio_enum_peer(struct rio_net *net, struct rio_mport *port,
|
|||
}
|
||||
|
||||
/* Setup new RIO device */
|
||||
if ((rdev = rio_setup_device(net, port, RIO_ANY_DESTID, hopcount, 1))) {
|
||||
rdev = rio_setup_device(net, port, RIO_ANY_DESTID(port->sys_size),
|
||||
hopcount, 1);
|
||||
if (rdev) {
|
||||
/* Add device to the global and bus/net specific list. */
|
||||
list_add_tail(&rdev->net_list, &net->devices);
|
||||
} else
|
||||
|
@ -598,7 +613,8 @@ static int rio_enum_peer(struct rio_net *net, struct rio_mport *port,
|
|||
|
||||
if (rio_is_switch(rdev)) {
|
||||
next_switchid++;
|
||||
sw_inport = rio_get_swpinfo_inport(port, RIO_ANY_DESTID, hopcount);
|
||||
sw_inport = rio_get_swpinfo_inport(port,
|
||||
RIO_ANY_DESTID(port->sys_size), hopcount);
|
||||
rio_route_add_entry(port, rdev->rswitch, RIO_GLOBAL_TABLE,
|
||||
port->host_deviceid, sw_inport);
|
||||
rdev->rswitch->route_table[port->host_deviceid] = sw_inport;
|
||||
|
@ -612,7 +628,8 @@ static int rio_enum_peer(struct rio_net *net, struct rio_mport *port,
|
|||
}
|
||||
|
||||
num_ports =
|
||||
rio_get_swpinfo_tports(port, RIO_ANY_DESTID, hopcount);
|
||||
rio_get_swpinfo_tports(port, RIO_ANY_DESTID(port->sys_size),
|
||||
hopcount);
|
||||
pr_debug(
|
||||
"RIO: found %s (vid %4.4x did %4.4x) with %d ports\n",
|
||||
rio_name(rdev), rdev->vid, rdev->did, num_ports);
|
||||
|
@ -624,13 +641,15 @@ static int rio_enum_peer(struct rio_net *net, struct rio_mport *port,
|
|||
cur_destid = next_destid;
|
||||
|
||||
if (rio_sport_is_active
|
||||
(port, RIO_ANY_DESTID, hopcount, port_num)) {
|
||||
(port, RIO_ANY_DESTID(port->sys_size), hopcount,
|
||||
port_num)) {
|
||||
pr_debug(
|
||||
"RIO: scanning device on port %d\n",
|
||||
port_num);
|
||||
rio_route_add_entry(port, rdev->rswitch,
|
||||
RIO_GLOBAL_TABLE,
|
||||
RIO_ANY_DESTID, port_num);
|
||||
RIO_GLOBAL_TABLE,
|
||||
RIO_ANY_DESTID(port->sys_size),
|
||||
port_num);
|
||||
|
||||
if (rio_enum_peer(net, port, hopcount + 1) < 0)
|
||||
return -1;
|
||||
|
@ -735,7 +754,8 @@ rio_disc_peer(struct rio_net *net, struct rio_mport *port, u16 destid,
|
|||
pr_debug(
|
||||
"RIO: scanning device on port %d\n",
|
||||
port_num);
|
||||
for (ndestid = 0; ndestid < RIO_ANY_DESTID;
|
||||
for (ndestid = 0;
|
||||
ndestid < RIO_ANY_DESTID(port->sys_size);
|
||||
ndestid++) {
|
||||
rio_route_get_entry(port, rdev->rswitch,
|
||||
RIO_GLOBAL_TABLE,
|
||||
|
@ -917,7 +937,9 @@ static void rio_build_route_tables(void)
|
|||
|
||||
list_for_each_entry(rdev, &rio_devices, global_list)
|
||||
if (rio_is_switch(rdev))
|
||||
for (i = 0; i < RIO_MAX_ROUTE_ENTRIES; i++) {
|
||||
for (i = 0;
|
||||
i < RIO_MAX_ROUTE_ENTRIES(rdev->net->hport->sys_size);
|
||||
i++) {
|
||||
if (rio_route_get_entry
|
||||
(rdev->net->hport, rdev->rswitch, RIO_GLOBAL_TABLE,
|
||||
i, &sport) < 0)
|
||||
|
@ -981,7 +1003,8 @@ int rio_disc_mport(struct rio_mport *mport)
|
|||
del_timer_sync(&rio_enum_timer);
|
||||
|
||||
pr_debug("done\n");
|
||||
if (rio_disc_peer(net, mport, RIO_ANY_DESTID, 0) < 0) {
|
||||
if (rio_disc_peer(net, mport, RIO_ANY_DESTID(mport->sys_size),
|
||||
0) < 0) {
|
||||
printk(KERN_INFO
|
||||
"RIO: master port %d device has failed discovery\n",
|
||||
mport->id);
|
||||
|
|
|
@ -43,7 +43,8 @@ static ssize_t routes_show(struct device *dev, struct device_attribute *attr, ch
|
|||
if (!rdev->rswitch)
|
||||
goto out;
|
||||
|
||||
for (i = 0; i < RIO_MAX_ROUTE_ENTRIES; i++) {
|
||||
for (i = 0; i < RIO_MAX_ROUTE_ENTRIES(rdev->net->hport->sys_size);
|
||||
i++) {
|
||||
if (rdev->rswitch->route_table[i] == RIO_INVALID_ROUTE)
|
||||
continue;
|
||||
str +=
|
||||
|
|
|
@ -43,7 +43,7 @@ u16 rio_local_get_device_id(struct rio_mport *port)
|
|||
|
||||
rio_local_read_config_32(port, RIO_DID_CSR, &result);
|
||||
|
||||
return (RIO_GET_DID(result));
|
||||
return (RIO_GET_DID(port->sys_size, result));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -51,10 +51,5 @@ extern struct rio_route_ops __end_rio_route_ops[];
|
|||
DECLARE_RIO_ROUTE_SECTION(.rio_route_ops, \
|
||||
vid, did, add_hook, get_hook)
|
||||
|
||||
#ifdef CONFIG_RAPIDIO_8_BIT_TRANSPORT
|
||||
#define RIO_GET_DID(x) ((x & 0x00ff0000) >> 16)
|
||||
#define RIO_SET_DID(x) ((x & 0x000000ff) << 16)
|
||||
#else
|
||||
#define RIO_GET_DID(x) (x & 0xffff)
|
||||
#define RIO_SET_DID(x) (x & 0xffff)
|
||||
#endif
|
||||
#define RIO_GET_DID(size, x) (size ? (x & 0xffff) : ((x & 0x00ff0000) >> 16))
|
||||
#define RIO_SET_DID(size, x) (size ? (x & 0xffff) : ((x & 0x000000ff) << 16))
|
||||
|
|
|
@ -138,6 +138,8 @@ typedef struct {
|
|||
|
||||
struct thread_struct {
|
||||
unsigned long ksp; /* Kernel stack pointer */
|
||||
unsigned long ksp_limit; /* if ksp <= ksp_limit stack overflow */
|
||||
|
||||
#ifdef CONFIG_PPC64
|
||||
unsigned long ksp_vsid;
|
||||
#endif
|
||||
|
@ -182,11 +184,14 @@ struct thread_struct {
|
|||
#define ARCH_MIN_TASKALIGN 16
|
||||
|
||||
#define INIT_SP (sizeof(init_stack) + (unsigned long) &init_stack)
|
||||
#define INIT_SP_LIMIT \
|
||||
(_ALIGN_UP(sizeof(init_thread_info), 16) + (unsigned long) &init_stack)
|
||||
|
||||
|
||||
#ifdef CONFIG_PPC32
|
||||
#define INIT_THREAD { \
|
||||
.ksp = INIT_SP, \
|
||||
.ksp_limit = INIT_SP_LIMIT, \
|
||||
.fs = KERNEL_DS, \
|
||||
.pgdir = swapper_pg_dir, \
|
||||
.fpexc_mode = MSR_FE0 | MSR_FE1, \
|
||||
|
@ -194,6 +199,7 @@ struct thread_struct {
|
|||
#else
|
||||
#define INIT_THREAD { \
|
||||
.ksp = INIT_SP, \
|
||||
.ksp_limit = INIT_SP_LIMIT, \
|
||||
.regs = (struct pt_regs *)INIT_SP - 1, /* XXX bogus, I think */ \
|
||||
.fs = KERNEL_DS, \
|
||||
.fpr = {0}, \
|
||||
|
|
|
@ -204,7 +204,7 @@ extern int powersave_nap; /* set if nap mode can be used in idle loop */
|
|||
* Changes the memory location '*ptr' to be val and returns
|
||||
* the previous value stored there.
|
||||
*/
|
||||
static __inline__ unsigned long
|
||||
static __always_inline unsigned long
|
||||
__xchg_u32(volatile void *p, unsigned long val)
|
||||
{
|
||||
unsigned long prev;
|
||||
|
@ -229,7 +229,7 @@ __xchg_u32(volatile void *p, unsigned long val)
|
|||
* Changes the memory location '*ptr' to be val and returns
|
||||
* the previous value stored there.
|
||||
*/
|
||||
static __inline__ unsigned long
|
||||
static __always_inline unsigned long
|
||||
__xchg_u32_local(volatile void *p, unsigned long val)
|
||||
{
|
||||
unsigned long prev;
|
||||
|
@ -247,7 +247,7 @@ __xchg_u32_local(volatile void *p, unsigned long val)
|
|||
}
|
||||
|
||||
#ifdef CONFIG_PPC64
|
||||
static __inline__ unsigned long
|
||||
static __always_inline unsigned long
|
||||
__xchg_u64(volatile void *p, unsigned long val)
|
||||
{
|
||||
unsigned long prev;
|
||||
|
@ -266,7 +266,7 @@ __xchg_u64(volatile void *p, unsigned long val)
|
|||
return prev;
|
||||
}
|
||||
|
||||
static __inline__ unsigned long
|
||||
static __always_inline unsigned long
|
||||
__xchg_u64_local(volatile void *p, unsigned long val)
|
||||
{
|
||||
unsigned long prev;
|
||||
|
@ -290,7 +290,7 @@ __xchg_u64_local(volatile void *p, unsigned long val)
|
|||
*/
|
||||
extern void __xchg_called_with_bad_pointer(void);
|
||||
|
||||
static __inline__ unsigned long
|
||||
static __always_inline unsigned long
|
||||
__xchg(volatile void *ptr, unsigned long x, unsigned int size)
|
||||
{
|
||||
switch (size) {
|
||||
|
@ -305,7 +305,7 @@ __xchg(volatile void *ptr, unsigned long x, unsigned int size)
|
|||
return x;
|
||||
}
|
||||
|
||||
static __inline__ unsigned long
|
||||
static __always_inline unsigned long
|
||||
__xchg_local(volatile void *ptr, unsigned long x, unsigned int size)
|
||||
{
|
||||
switch (size) {
|
||||
|
@ -338,7 +338,7 @@ __xchg_local(volatile void *ptr, unsigned long x, unsigned int size)
|
|||
*/
|
||||
#define __HAVE_ARCH_CMPXCHG 1
|
||||
|
||||
static __inline__ unsigned long
|
||||
static __always_inline unsigned long
|
||||
__cmpxchg_u32(volatile unsigned int *p, unsigned long old, unsigned long new)
|
||||
{
|
||||
unsigned int prev;
|
||||
|
@ -361,7 +361,7 @@ __cmpxchg_u32(volatile unsigned int *p, unsigned long old, unsigned long new)
|
|||
return prev;
|
||||
}
|
||||
|
||||
static __inline__ unsigned long
|
||||
static __always_inline unsigned long
|
||||
__cmpxchg_u32_local(volatile unsigned int *p, unsigned long old,
|
||||
unsigned long new)
|
||||
{
|
||||
|
@ -384,7 +384,7 @@ __cmpxchg_u32_local(volatile unsigned int *p, unsigned long old,
|
|||
}
|
||||
|
||||
#ifdef CONFIG_PPC64
|
||||
static __inline__ unsigned long
|
||||
static __always_inline unsigned long
|
||||
__cmpxchg_u64(volatile unsigned long *p, unsigned long old, unsigned long new)
|
||||
{
|
||||
unsigned long prev;
|
||||
|
@ -406,7 +406,7 @@ __cmpxchg_u64(volatile unsigned long *p, unsigned long old, unsigned long new)
|
|||
return prev;
|
||||
}
|
||||
|
||||
static __inline__ unsigned long
|
||||
static __always_inline unsigned long
|
||||
__cmpxchg_u64_local(volatile unsigned long *p, unsigned long old,
|
||||
unsigned long new)
|
||||
{
|
||||
|
@ -432,7 +432,7 @@ __cmpxchg_u64_local(volatile unsigned long *p, unsigned long old,
|
|||
if something tries to do an invalid cmpxchg(). */
|
||||
extern void __cmpxchg_called_with_bad_pointer(void);
|
||||
|
||||
static __inline__ unsigned long
|
||||
static __always_inline unsigned long
|
||||
__cmpxchg(volatile void *ptr, unsigned long old, unsigned long new,
|
||||
unsigned int size)
|
||||
{
|
||||
|
@ -448,7 +448,7 @@ __cmpxchg(volatile void *ptr, unsigned long old, unsigned long new,
|
|||
return old;
|
||||
}
|
||||
|
||||
static __inline__ unsigned long
|
||||
static __always_inline unsigned long
|
||||
__cmpxchg_local(volatile void *ptr, unsigned long old, unsigned long new,
|
||||
unsigned int size)
|
||||
{
|
||||
|
|
|
@ -40,7 +40,8 @@ extern struct lmb lmb;
|
|||
|
||||
extern void __init lmb_init(void);
|
||||
extern void __init lmb_analyze(void);
|
||||
extern long __init lmb_add(u64 base, u64 size);
|
||||
extern long lmb_add(u64 base, u64 size);
|
||||
extern long lmb_remove(u64 base, u64 size);
|
||||
extern long __init lmb_reserve(u64 base, u64 size);
|
||||
extern u64 __init lmb_alloc_nid(u64 size, u64 align, int nid,
|
||||
u64 (*nid_range)(u64, u64, int *));
|
||||
|
@ -53,6 +54,7 @@ extern u64 __init lmb_phys_mem_size(void);
|
|||
extern u64 __init lmb_end_of_DRAM(void);
|
||||
extern void __init lmb_enforce_memory_limit(u64 memory_limit);
|
||||
extern int __init lmb_is_reserved(u64 addr);
|
||||
extern int lmb_find(struct lmb_property *res);
|
||||
|
||||
extern void lmb_dump_all(void);
|
||||
|
||||
|
|
|
@ -23,7 +23,6 @@
|
|||
#include <linux/device.h>
|
||||
#include <linux/rio_regs.h>
|
||||
|
||||
#define RIO_ANY_DESTID 0xff
|
||||
#define RIO_NO_HOPCOUNT -1
|
||||
#define RIO_INVALID_DESTID 0xffff
|
||||
|
||||
|
@ -39,11 +38,8 @@
|
|||
entry is invalid (no route
|
||||
exists for the device ID) */
|
||||
|
||||
#ifdef CONFIG_RAPIDIO_8_BIT_TRANSPORT
|
||||
#define RIO_MAX_ROUTE_ENTRIES (1 << 8)
|
||||
#else
|
||||
#define RIO_MAX_ROUTE_ENTRIES (1 << 16)
|
||||
#endif
|
||||
#define RIO_MAX_ROUTE_ENTRIES(size) (size ? (1 << 16) : (1 << 8))
|
||||
#define RIO_ANY_DESTID(size) (size ? 0xffff : 0xff)
|
||||
|
||||
#define RIO_MAX_MBOX 4
|
||||
#define RIO_MAX_MSG_SIZE 0x1000
|
||||
|
@ -149,6 +145,11 @@ struct rio_dbell {
|
|||
void *dev_id;
|
||||
};
|
||||
|
||||
enum rio_phy_type {
|
||||
RIO_PHY_PARALLEL,
|
||||
RIO_PHY_SERIAL,
|
||||
};
|
||||
|
||||
/**
|
||||
* struct rio_mport - RIO master port info
|
||||
* @dbells: List of doorbell events
|
||||
|
@ -163,6 +164,7 @@ struct rio_dbell {
|
|||
* @id: Port ID, unique among all ports
|
||||
* @index: Port index, unique among all port interfaces of the same type
|
||||
* @name: Port name string
|
||||
* @priv: Master port private data
|
||||
*/
|
||||
struct rio_mport {
|
||||
struct list_head dbells; /* list of doorbell events */
|
||||
|
@ -177,7 +179,13 @@ struct rio_mport {
|
|||
unsigned char id; /* port ID, unique among all ports */
|
||||
unsigned char index; /* port index, unique among all port
|
||||
interfaces of the same type */
|
||||
unsigned int sys_size; /* RapidIO common transport system size.
|
||||
* 0 - Small size. 256 devices.
|
||||
* 1 - Large size, 65536 devices.
|
||||
*/
|
||||
enum rio_phy_type phy_type; /* RapidIO phy type */
|
||||
unsigned char name[40];
|
||||
void *priv; /* Master port private data */
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -211,7 +219,7 @@ struct rio_switch {
|
|||
u16 switchid;
|
||||
u16 hopcount;
|
||||
u16 destid;
|
||||
u8 route_table[RIO_MAX_ROUTE_ENTRIES];
|
||||
u8 *route_table;
|
||||
int (*add_entry) (struct rio_mport * mport, u16 destid, u8 hopcount,
|
||||
u16 table, u16 route_destid, u8 route_port);
|
||||
int (*get_entry) (struct rio_mport * mport, u16 destid, u8 hopcount,
|
||||
|
@ -229,13 +237,15 @@ struct rio_switch {
|
|||
* @dsend: Callback to send a doorbell message.
|
||||
*/
|
||||
struct rio_ops {
|
||||
int (*lcread) (int index, u32 offset, int len, u32 * data);
|
||||
int (*lcwrite) (int index, u32 offset, int len, u32 data);
|
||||
int (*cread) (int index, u16 destid, u8 hopcount, u32 offset, int len,
|
||||
u32 * data);
|
||||
int (*cwrite) (int index, u16 destid, u8 hopcount, u32 offset, int len,
|
||||
u32 data);
|
||||
int (*dsend) (int index, u16 destid, u16 data);
|
||||
int (*lcread) (struct rio_mport *mport, int index, u32 offset, int len,
|
||||
u32 *data);
|
||||
int (*lcwrite) (struct rio_mport *mport, int index, u32 offset, int len,
|
||||
u32 data);
|
||||
int (*cread) (struct rio_mport *mport, int index, u16 destid,
|
||||
u8 hopcount, u32 offset, int len, u32 *data);
|
||||
int (*cwrite) (struct rio_mport *mport, int index, u16 destid,
|
||||
u8 hopcount, u32 offset, int len, u32 data);
|
||||
int (*dsend) (struct rio_mport *mport, int index, u16 destid, u16 data);
|
||||
};
|
||||
|
||||
#define RIO_RESOURCE_MEM 0x00000100
|
||||
|
|
99
lib/lmb.c
99
lib/lmb.c
|
@ -46,14 +46,13 @@ void lmb_dump_all(void)
|
|||
#endif /* DEBUG */
|
||||
}
|
||||
|
||||
static unsigned long __init lmb_addrs_overlap(u64 base1, u64 size1,
|
||||
u64 base2, u64 size2)
|
||||
static unsigned long lmb_addrs_overlap(u64 base1, u64 size1, u64 base2,
|
||||
u64 size2)
|
||||
{
|
||||
return ((base1 < (base2 + size2)) && (base2 < (base1 + size1)));
|
||||
}
|
||||
|
||||
static long __init lmb_addrs_adjacent(u64 base1, u64 size1,
|
||||
u64 base2, u64 size2)
|
||||
static long lmb_addrs_adjacent(u64 base1, u64 size1, u64 base2, u64 size2)
|
||||
{
|
||||
if (base2 == base1 + size1)
|
||||
return 1;
|
||||
|
@ -63,7 +62,7 @@ static long __init lmb_addrs_adjacent(u64 base1, u64 size1,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static long __init lmb_regions_adjacent(struct lmb_region *rgn,
|
||||
static long lmb_regions_adjacent(struct lmb_region *rgn,
|
||||
unsigned long r1, unsigned long r2)
|
||||
{
|
||||
u64 base1 = rgn->region[r1].base;
|
||||
|
@ -74,7 +73,7 @@ static long __init lmb_regions_adjacent(struct lmb_region *rgn,
|
|||
return lmb_addrs_adjacent(base1, size1, base2, size2);
|
||||
}
|
||||
|
||||
static void __init lmb_remove_region(struct lmb_region *rgn, unsigned long r)
|
||||
static void lmb_remove_region(struct lmb_region *rgn, unsigned long r)
|
||||
{
|
||||
unsigned long i;
|
||||
|
||||
|
@ -86,7 +85,7 @@ static void __init lmb_remove_region(struct lmb_region *rgn, unsigned long r)
|
|||
}
|
||||
|
||||
/* Assumption: base addr of region 1 < base addr of region 2 */
|
||||
static void __init lmb_coalesce_regions(struct lmb_region *rgn,
|
||||
static void lmb_coalesce_regions(struct lmb_region *rgn,
|
||||
unsigned long r1, unsigned long r2)
|
||||
{
|
||||
rgn->region[r1].size += rgn->region[r2].size;
|
||||
|
@ -118,7 +117,7 @@ void __init lmb_analyze(void)
|
|||
lmb.memory.size += lmb.memory.region[i].size;
|
||||
}
|
||||
|
||||
static long __init lmb_add_region(struct lmb_region *rgn, u64 base, u64 size)
|
||||
static long lmb_add_region(struct lmb_region *rgn, u64 base, u64 size)
|
||||
{
|
||||
unsigned long coalesced = 0;
|
||||
long adjacent, i;
|
||||
|
@ -182,7 +181,7 @@ static long __init lmb_add_region(struct lmb_region *rgn, u64 base, u64 size)
|
|||
return 0;
|
||||
}
|
||||
|
||||
long __init lmb_add(u64 base, u64 size)
|
||||
long lmb_add(u64 base, u64 size)
|
||||
{
|
||||
struct lmb_region *_rgn = &lmb.memory;
|
||||
|
||||
|
@ -194,6 +193,55 @@ long __init lmb_add(u64 base, u64 size)
|
|||
|
||||
}
|
||||
|
||||
long lmb_remove(u64 base, u64 size)
|
||||
{
|
||||
struct lmb_region *rgn = &(lmb.memory);
|
||||
u64 rgnbegin, rgnend;
|
||||
u64 end = base + size;
|
||||
int i;
|
||||
|
||||
rgnbegin = rgnend = 0; /* supress gcc warnings */
|
||||
|
||||
/* Find the region where (base, size) belongs to */
|
||||
for (i=0; i < rgn->cnt; i++) {
|
||||
rgnbegin = rgn->region[i].base;
|
||||
rgnend = rgnbegin + rgn->region[i].size;
|
||||
|
||||
if ((rgnbegin <= base) && (end <= rgnend))
|
||||
break;
|
||||
}
|
||||
|
||||
/* Didn't find the region */
|
||||
if (i == rgn->cnt)
|
||||
return -1;
|
||||
|
||||
/* Check to see if we are removing entire region */
|
||||
if ((rgnbegin == base) && (rgnend == end)) {
|
||||
lmb_remove_region(rgn, i);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Check to see if region is matching at the front */
|
||||
if (rgnbegin == base) {
|
||||
rgn->region[i].base = end;
|
||||
rgn->region[i].size -= size;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Check to see if the region is matching at the end */
|
||||
if (rgnend == end) {
|
||||
rgn->region[i].size -= size;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* We need to split the entry - adjust the current one to the
|
||||
* beginging of the hole and add the region after hole.
|
||||
*/
|
||||
rgn->region[i].size = base - rgn->region[i].base;
|
||||
return lmb_add_region(rgn, end, rgnend - end);
|
||||
}
|
||||
|
||||
long __init lmb_reserve(u64 base, u64 size)
|
||||
{
|
||||
struct lmb_region *_rgn = &lmb.reserved;
|
||||
|
@ -426,3 +474,36 @@ int __init lmb_is_reserved(u64 addr)
|
|||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Given a <base, len>, find which memory regions belong to this range.
|
||||
* Adjust the request and return a contiguous chunk.
|
||||
*/
|
||||
int lmb_find(struct lmb_property *res)
|
||||
{
|
||||
int i;
|
||||
u64 rstart, rend;
|
||||
|
||||
rstart = res->base;
|
||||
rend = rstart + res->size - 1;
|
||||
|
||||
for (i = 0; i < lmb.memory.cnt; i++) {
|
||||
u64 start = lmb.memory.region[i].base;
|
||||
u64 end = start + lmb.memory.region[i].size - 1;
|
||||
|
||||
if (start > rend)
|
||||
return -1;
|
||||
|
||||
if ((end >= rstart) && (start < rend)) {
|
||||
/* adjust the request */
|
||||
if (rstart < start)
|
||||
rstart = start;
|
||||
if (rend > end)
|
||||
rend = end;
|
||||
res->base = rstart;
|
||||
res->size = rend - rstart + 1;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue