Commit 867a89e0 authored by Linus Torvalds's avatar Linus Torvalds

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
parents 44473d99 6c39103c
...@@ -608,6 +608,19 @@ source "drivers/pcmcia/Kconfig" ...@@ -608,6 +608,19 @@ source "drivers/pcmcia/Kconfig"
source "drivers/pci/hotplug/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 endmenu
menu "Advanced setup" menu "Advanced setup"
......
...@@ -118,7 +118,6 @@ config XMON_DISASSEMBLY ...@@ -118,7 +118,6 @@ config XMON_DISASSEMBLY
config IRQSTACKS config IRQSTACKS
bool "Use separate kernel stacks when processing interrupts" bool "Use separate kernel stacks when processing interrupts"
depends on PPC64
help help
If you say Y here the kernel will use separate kernel stacks If you say Y here the kernel will use separate kernel stacks
for handling hard and soft interrupts. This can help avoid for handling hard and soft interrupts. This can help avoid
......
...@@ -26,6 +26,7 @@ aliases { ...@@ -26,6 +26,7 @@ aliases {
serial1 = &serial1; serial1 = &serial1;
pci0 = &pci0; pci0 = &pci0;
pci1 = &pci1; pci1 = &pci1;
rapidio0 = &rapidio0;
}; };
cpus { cpus {
...@@ -500,4 +501,15 @@ pcie@0 { ...@@ -500,4 +501,15 @@ pcie@0 {
0x0 0x00100000>; 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 ...@@ -696,6 +696,7 @@ CONFIG_WINDFARM=y
CONFIG_WINDFARM_PM81=y CONFIG_WINDFARM_PM81=y
CONFIG_WINDFARM_PM91=y CONFIG_WINDFARM_PM91=y
CONFIG_WINDFARM_PM112=y CONFIG_WINDFARM_PM112=y
CONFIG_WINDFARM_PM121=y
# CONFIG_PMAC_RACKMETER is not set # CONFIG_PMAC_RACKMETER is not set
CONFIG_NETDEVICES=y CONFIG_NETDEVICES=y
# CONFIG_NETDEVICES_MULTIQUEUE is not set # CONFIG_NETDEVICES_MULTIQUEUE is not set
......
...@@ -73,7 +73,6 @@ pci64-$(CONFIG_PPC64) += pci_dn.o isa-bridge.o ...@@ -73,7 +73,6 @@ pci64-$(CONFIG_PPC64) += pci_dn.o isa-bridge.o
obj-$(CONFIG_PCI) += pci_$(CONFIG_WORD_SIZE).o $(pci64-y) \ obj-$(CONFIG_PCI) += pci_$(CONFIG_WORD_SIZE).o $(pci64-y) \
pci-common.o pci-common.o
obj-$(CONFIG_PCI_MSI) += msi.o obj-$(CONFIG_PCI_MSI) += msi.o
obj-$(CONFIG_RAPIDIO) += rio.o
obj-$(CONFIG_KEXEC) += machine_kexec.o crash.o \ obj-$(CONFIG_KEXEC) += machine_kexec.o crash.o \
machine_kexec_$(CONFIG_WORD_SIZE).o machine_kexec_$(CONFIG_WORD_SIZE).o
obj-$(CONFIG_AUDIT) += audit.o obj-$(CONFIG_AUDIT) += audit.o
......
...@@ -63,6 +63,7 @@ int main(void) ...@@ -63,6 +63,7 @@ int main(void)
#endif /* CONFIG_PPC64 */ #endif /* CONFIG_PPC64 */
DEFINE(KSP, offsetof(struct thread_struct, ksp)); 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(PT_REGS, offsetof(struct thread_struct, regs));
DEFINE(THREAD_FPEXC_MODE, offsetof(struct thread_struct, fpexc_mode)); DEFINE(THREAD_FPEXC_MODE, offsetof(struct thread_struct, fpexc_mode));
DEFINE(THREAD_FPR0, offsetof(struct thread_struct, fpr[0])); DEFINE(THREAD_FPR0, offsetof(struct thread_struct, fpr[0]));
......
...@@ -137,11 +137,12 @@ transfer_to_handler: ...@@ -137,11 +137,12 @@ transfer_to_handler:
2: /* if from kernel, check interrupted DOZE/NAP mode and 2: /* if from kernel, check interrupted DOZE/NAP mode and
* check for stack overflow * check for stack overflow
*/ */
lwz r9,THREAD_INFO-THREAD(r12) lwz r9,KSP_LIMIT(r12)
cmplw r1,r9 /* if r1 <= current->thread_info */ cmplw r1,r9 /* if r1 <= ksp_limit */
ble- stack_ovf /* then the kernel stack overflowed */ ble- stack_ovf /* then the kernel stack overflowed */
5: 5:
#ifdef CONFIG_6xx #ifdef CONFIG_6xx
rlwinm r9,r1,0,0,31-THREAD_SHIFT
tophys(r9,r9) /* check local flags */ tophys(r9,r9) /* check local flags */
lwz r12,TI_LOCAL_FLAGS(r9) lwz r12,TI_LOCAL_FLAGS(r9)
mtcrf 0x01,r12 mtcrf 0x01,r12
......
...@@ -239,6 +239,10 @@ instruction_access_slb_pSeries: ...@@ -239,6 +239,10 @@ instruction_access_slb_pSeries:
.globl system_call_pSeries .globl system_call_pSeries
system_call_pSeries: system_call_pSeries:
HMT_MEDIUM HMT_MEDIUM
BEGIN_FTR_SECTION
cmpdi r0,0x1ebe
beq- 1f
END_FTR_SECTION_IFSET(CPU_FTR_REAL_LE)
mr r9,r13 mr r9,r13
mfmsr r10 mfmsr r10
mfspr r13,SPRN_SPRG3 mfspr r13,SPRN_SPRG3
...@@ -253,6 +257,13 @@ system_call_pSeries: ...@@ -253,6 +257,13 @@ system_call_pSeries:
rfid rfid
b . /* prevent speculative execution */ 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(0xd00, single_step)
STD_EXCEPTION_PSERIES(0xe00, trap_0e) STD_EXCEPTION_PSERIES(0xe00, trap_0e)
......
...@@ -307,6 +307,7 @@ void do_IRQ(struct pt_regs *regs) ...@@ -307,6 +307,7 @@ void do_IRQ(struct pt_regs *regs)
if (curtp != irqtp) { if (curtp != irqtp) {
struct irq_desc *desc = irq_desc + irq; struct irq_desc *desc = irq_desc + irq;
void *handler = desc->handle_irq; void *handler = desc->handle_irq;
unsigned long saved_sp_limit = current->thread.ksp_limit;
if (handler == NULL) if (handler == NULL)
handler = &__do_IRQ; handler = &__do_IRQ;
irqtp->task = curtp->task; irqtp->task = curtp->task;
...@@ -319,7 +320,10 @@ void do_IRQ(struct pt_regs *regs) ...@@ -319,7 +320,10 @@ void do_IRQ(struct pt_regs *regs)
(irqtp->preempt_count & ~SOFTIRQ_MASK) | (irqtp->preempt_count & ~SOFTIRQ_MASK) |
(curtp->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); call_handle_irq(irq, desc, irqtp, handler);
current->thread.ksp_limit = saved_sp_limit;
irqtp->task = NULL; irqtp->task = NULL;
...@@ -352,9 +356,7 @@ void __init init_IRQ(void) ...@@ -352,9 +356,7 @@ void __init init_IRQ(void)
{ {
if (ppc_md.init_IRQ) if (ppc_md.init_IRQ)
ppc_md.init_IRQ(); ppc_md.init_IRQ();
#ifdef CONFIG_PPC64
irq_ctx_init(); irq_ctx_init();
#endif
} }
...@@ -383,11 +385,15 @@ void irq_ctx_init(void) ...@@ -383,11 +385,15 @@ void irq_ctx_init(void)
static inline void do_softirq_onstack(void) static inline void do_softirq_onstack(void)
{ {
struct thread_info *curtp, *irqtp; struct thread_info *curtp, *irqtp;
unsigned long saved_sp_limit = current->thread.ksp_limit;
curtp = current_thread_info(); curtp = current_thread_info();
irqtp = softirq_ctx[smp_processor_id()]; irqtp = softirq_ctx[smp_processor_id()];
irqtp->task = curtp->task; irqtp->task = curtp->task;
current->thread.ksp_limit = (unsigned long)irqtp +
_ALIGN_UP(sizeof(struct thread_info), 16);
call_do_softirq(irqtp); call_do_softirq(irqtp);
current->thread.ksp_limit = saved_sp_limit;
irqtp->task = NULL; irqtp->task = NULL;
} }
......
...@@ -32,6 +32,31 @@ ...@@ -32,6 +32,31 @@
.text .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. * 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, ...@@ -589,6 +589,8 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long usp,
kregs = (struct pt_regs *) sp; kregs = (struct pt_regs *) sp;
sp -= STACK_FRAME_OVERHEAD; sp -= STACK_FRAME_OVERHEAD;
p->thread.ksp = sp; p->thread.ksp = sp;
p->thread.ksp_limit = (unsigned long)task_stack_page(p) +
_ALIGN_UP(sizeof(struct thread_info), 16);
#ifdef CONFIG_PPC64 #ifdef CONFIG_PPC64
if (cpu_has_feature(CPU_FTR_SLB)) { if (cpu_has_feature(CPU_FTR_SLB)) {
......
/*
* 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 @@ ...@@ -16,6 +16,7 @@
#include <linux/root_dev.h> #include <linux/root_dev.h>
#include <linux/cpu.h> #include <linux/cpu.h>
#include <linux/console.h> #include <linux/console.h>
#include <linux/lmb.h>
#include <asm/io.h> #include <asm/io.h>
#include <asm/prom.h> #include <asm/prom.h>
...@@ -229,6 +230,24 @@ int __init ppc_init(void) ...@@ -229,6 +230,24 @@ int __init ppc_init(void)
arch_initcall(ppc_init); 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 */ /* Warning, IO base is not yet inited */
void __init setup_arch(char **cmdline_p) void __init setup_arch(char **cmdline_p)
{ {
...@@ -286,6 +305,8 @@ 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.end_data = (unsigned long) _edata;
init_mm.brk = klimit; init_mm.brk = klimit;
irqstack_early_init();
/* set up the bootmem stuff with available memory */ /* set up the bootmem stuff with available memory */
do_init_bootmem(); do_init_bootmem();
if ( ppc_md.progress ) ppc_md.progress("setup_arch: bootmem", 0x3eab); if ( ppc_md.progress ) ppc_md.progress("setup_arch: bootmem", 0x3eab);
......
...@@ -154,19 +154,35 @@ int remove_memory(u64 start, u64 size) ...@@ -154,19 +154,35 @@ int remove_memory(u64 start, u64 size)
/* /*
* walk_memory_resource() needs to make sure there is no holes in a given * 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 * memory range. PPC64 does not maintain the memory layout in /proc/iomem.
* is guaranteed to be valid, non-overlapping and can not contain any * Instead it maintains it in lmb.memory structures. Walk through the
* holes. By the time we get here (memory add or remove), /proc/device-tree * memory regions, find holes and callback for contiguous regions.
* 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.
*/ */
int int
walk_memory_resource(unsigned long start_pfn, unsigned long nr_pages, void *arg, walk_memory_resource(unsigned long start_pfn, unsigned long nr_pages, void *arg,
int (*func)(unsigned long, unsigned long, void *)) 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 */ #endif /* CONFIG_MEMORY_HOTPLUG */
......
...@@ -8,6 +8,7 @@ config MPC8641_HPCN ...@@ -8,6 +8,7 @@ config MPC8641_HPCN
select PPC_I8259 select PPC_I8259
select DEFAULT_UIMAGE select DEFAULT_UIMAGE
select FSL_ULI1575 select FSL_ULI1575
select HAS_RAPIDIO
help help
This option enables support for the MPC8641 HPCN board. This option enables support for the MPC8641 HPCN board.
......
...@@ -221,6 +221,7 @@ mpc86xx_time_init(void) ...@@ -221,6 +221,7 @@ mpc86xx_time_init(void)
static __initdata struct of_device_id of_bus_ids[] = { static __initdata struct of_device_id of_bus_ids[] = {
{ .compatible = "simple-bus", }, { .compatible = "simple-bus", },
{ .compatible = "fsl,rapidio-delta", },
{}, {},
}; };
......
...@@ -6,7 +6,10 @@ obj-y += pic.o setup.o time.o feature.o pci.o \ ...@@ -6,7 +6,10 @@ obj-y += pic.o setup.o time.o feature.o pci.o \
obj-$(CONFIG_PMAC_BACKLIGHT) += backlight.o obj-$(CONFIG_PMAC_BACKLIGHT) += backlight.o
obj-$(CONFIG_CPU_FREQ_PMAC) += cpufreq_32.o obj-$(CONFIG_CPU_FREQ_PMAC) += cpufreq_32.o
obj-$(CONFIG_CPU_FREQ_PMAC64) += cpufreq_64.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 # ppc64 pmac doesn't define CONFIG_NVRAM but needs nvram stuff
obj-$(CONFIG_PPC64) += nvram.o obj-$(CONFIG_PPC64) += nvram.o
obj-$(CONFIG_PPC32) += bootx_init.o obj-$(CONFIG_PPC32) += bootx_init.o
......
...@@ -337,7 +337,8 @@ static void __init pmac_setup_arch(void) ...@@ -337,7 +337,8 @@ static void __init pmac_setup_arch(void)
find_via_pmu(); find_via_pmu();
smu_init(); smu_init();
#if defined(CONFIG_NVRAM) || defined(CONFIG_PPC64) #if defined(CONFIG_NVRAM) || defined(CONFIG_NVRAM_MODULE) || \
defined(CONFIG_PPC64)
pmac_nvram_init(); pmac_nvram_init();
#endif #endif
......
...@@ -18,6 +18,7 @@ obj-$(CONFIG_PCI) += pci.o pci_dlpar.o ...@@ -18,6 +18,7 @@ obj-$(CONFIG_PCI) += pci.o pci_dlpar.o
obj-$(CONFIG_PCI_MSI) += msi.o obj-$(CONFIG_PCI_MSI) += msi.o
obj-$(CONFIG_HOTPLUG_CPU) += hotplug-cpu.o obj-$(CONFIG_HOTPLUG_CPU) += hotplug-cpu.o
obj-$(CONFIG_MEMORY_HOTPLUG) += hotplug-memory.o
obj-$(CONFIG_HVC_CONSOLE) += hvconsole.o obj-$(CONFIG_HVC_CONSOLE) += hvconsole.o
obj-$(CONFIG_HVCS) += hvcserver.o obj-$(CONFIG_HVCS) += hvcserver.o
......
/*
* 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);
This diff is collapsed.
/*
* 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 ...@@ -234,6 +234,14 @@ config WINDFARM_PM112
which are the recent dual and quad G5 machines using the which are the recent dual and quad G5 machines using the
970MP dual-core processor. 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 config ANSLCD
tristate "Support for ANS LCD display" tristate "Support for ANS LCD display"
depends on ADB_CUDA && PPC_PMAC depends on ADB_CUDA && PPC_PMAC
......
...@@ -42,4 +42,9 @@ obj-$(CONFIG_WINDFARM_PM112) += windfarm_pm112.o windfarm_smu_sat.o \ ...@@ -42,4 +42,9 @@ obj-$(CONFIG_WINDFARM_PM112) += windfarm_pm112.o windfarm_smu_sat.o \
windfarm_smu_sensors.o \ windfarm_smu_sensors.o \
windfarm_max6690_sensor.o \ windfarm_max6690_sensor.o \
windfarm_lm75_sensor.o windfarm_pid.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 obj-$(CONFIG_PMAC_RACKMETER) += rack-meter.o
...@@ -127,6 +127,12 @@ static struct wf_lm75_sensor *wf_lm75_create(struct i2c_adapter *adapter, ...@@ -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")) if (!strcmp(loc, "Hard drive") || !strcmp(loc, "DRIVE BAY"))
lm->sens.name = "hd-temp"; 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 else
goto fail; goto fail;
......
...@@ -77,18 +77,28 @@ static struct wf_sensor_ops wf_max6690_ops = { ...@@ -77,18 +77,28 @@ static struct wf_sensor_ops wf_max6690_ops = {
.owner = THIS_MODULE, .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; struct wf_6690_sensor *max;
char *name = "backside-temp"; char *name;
max = kzalloc(sizeof(struct wf_6690_sensor), GFP_KERNEL); max = kzalloc(sizeof(struct wf_6690_sensor), GFP_KERNEL);
if (max == NULL) { if (max == NULL) {
printk(KERN_ERR "windfarm: Couldn't create MAX6690 sensor %s: " printk(KERN_ERR "windfarm: Couldn't create MAX6690 sensor %s: "
"no memory\n", name); "no memory\n", loc);
return; 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.ops = &wf_max6690_ops;
max->sens.name = name; max->sens.name = name;
max->i2c.addr = addr >> 1; max->i2c.addr = addr >> 1;
...@@ -138,9 +148,7 @@ static int wf_max6690_attach(struct i2c_adapter *adapter) ...@@ -138,9 +148,7 @@ static int wf_max6690_attach(struct i2c_adapter *adapter)
if (loc == NULL || addr == 0) if (loc == NULL || addr == 0)
continue; continue;
printk("found max6690, loc=%s addr=0x%02x\n", loc, addr); printk("found max6690, loc=%s addr=0x%02x\n", loc, addr);
if (strcmp(loc, "BACKSIDE")) wf_max6690_create(adapter, addr, loc);
continue;
wf_max6690_create(adapter, addr);
} }
return 0; return 0;
......
This diff is collapsed.
...@@ -218,6 +218,10 @@ static struct smu_fan_control *smu_fan_create(struct device_node *node, ...@@ -218,6 +218,10 @@ static struct smu_fan_control *smu_fan_create(struct device_node *node,
fct->ctrl.name = "cpu-fan"; fct->ctrl.name = "cpu-fan";
else if (!strcmp(l, "Hard Drive") || !strcmp(l, "Hard drive")) else if (!strcmp(l, "Hard Drive") || !strcmp(l, "Hard drive"))
fct->ctrl.name = "drive-bay-fan"; 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 */ /* Unrecognized fan, bail out */
if (fct->ctrl.name == NULL) if (fct->ctrl.name == NULL)
......
...@@ -77,7 +77,7 @@ static int rionet_capable = 1; ...@@ -77,7 +77,7 @@ static int rionet_capable = 1;
* could be made into a hash table to save memory depending * could be made into a hash table to save memory depending
* on system trade-offs. * 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) \ #define is_rionet_capable(pef, src_ops, dst_ops) \
((pef & RIO_PEF_INB_MBOX) && \ ((pef & RIO_PEF_INB_MBOX) && \
...@@ -195,7 +195,8 @@ static int rionet_start_xmit(struct sk_buff *skb, struct net_device *ndev) ...@@ -195,7 +195,8 @@ static int rionet_start_xmit(struct sk_buff *skb, struct net_device *ndev)
} }
if (eth->h_dest[0] & 0x01) { 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]) if (rionet_active[i])
rionet_queue_tx_msg(skb, ndev, rionet_queue_tx_msg(skb, ndev,
rionet_active[i]); rionet_active[i]);
...@@ -385,6 +386,8 @@ static void rionet_remove(struct rio_dev *rdev) ...@@ -385,6 +386,8 @@ static void rionet_remove(struct rio_dev *rdev)
struct net_device *ndev = NULL; struct net_device *ndev = NULL;
struct rionet_peer *peer, *tmp; struct rionet_peer *peer, *tmp;
free_pages((unsigned long)rionet_active, rdev->net->hport->sys_size ?
__ilog2(sizeof(void *)) + 4 : 0);
unregister_netdev(ndev); unregister_netdev(ndev);
kfree(ndev); kfree(ndev);
...@@ -443,6 +446,15 @@ static int rionet_setup_netdev(struct rio_mport *mport) ...@@ -443,6 +446,15 @@ static int rionet_setup_netdev(struct rio_mport *mport)
goto out; 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 */ /* Set up private area */
rnet = (struct rionet_private *)ndev->priv; rnet = (struct rionet_private *)ndev->priv;
rnet->mport = mport; rnet->mport = mport;
......
# #
# RapidIO configuration # 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 config RAPIDIO_DISC_TIMEOUT
int "Discovery timeout duration (seconds)" int "Discovery timeout duration (seconds)"
depends on RAPIDIO depends on RAPIDIO
......
...@@ -48,7 +48,7 @@ int __rio_local_read_config_##size \ ...@@ -48,7 +48,7 @@ int __rio_local_read_config_##size \
u32 data = 0; \ u32 data = 0; \
if (RIO_##size##_BAD) return RIO_BAD_SIZE; \ if (RIO_##size##_BAD) return RIO_BAD_SIZE; \
spin_lock_irqsave(&rio_config_lock, flags); \ 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; \ *value = (type)data; \
spin_unlock_irqrestore(&rio_config_lock, flags); \ spin_unlock_irqrestore(&rio_config_lock, flags); \
return res; \ return res; \
...@@ -71,7 +71,7 @@ int __rio_local_write_config_##size \ ...@@ -71,7 +71,7 @@ int __rio_local_write_config_##size \
unsigned long flags; \ unsigned long flags; \
if (RIO_##size##_BAD) return RIO_BAD_SIZE; \ if (RIO_##size##_BAD) return RIO_BAD_SIZE; \
spin_lock_irqsave(&rio_config_lock, flags); \ 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); \ spin_unlock_irqrestore(&rio_config_lock, flags); \
return res; \ return res; \
} }
...@@ -108,7 +108,7 @@ int rio_mport_read_config_##size \ ...@@ -108,7 +108,7 @@ int rio_mport_read_config_##size \
u32 data = 0; \ u32 data = 0; \
if (RIO_##size##_BAD) return RIO_BAD_SIZE; \ if (RIO_##size##_BAD) return RIO_BAD_SIZE; \
spin_lock_irqsave(&rio_config_lock, flags); \ 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; \ *value = (type)data; \
spin_unlock_irqrestore(&rio_config_lock, flags); \ spin_unlock_irqrestore(&rio_config_lock, flags); \
return res; \ return res; \
...@@ -131,7 +131,7 @@ int rio_mport_write_config_##size \ ...@@ -131,7 +131,7 @@ int rio_mport_write_config_##size \
unsigned long flags; \ unsigned long flags; \
if (RIO_##size##_BAD) return RIO_BAD_SIZE; \ if (RIO_##size##_BAD) return RIO_BAD_SIZE; \
spin_lock_irqsave(&rio_config_lock, flags); \ 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); \ spin_unlock_irqrestore(&rio_config_lock, flags); \
return res; \ return res; \
} }
...@@ -166,7 +166,7 @@ int rio_mport_send_doorbell(struct rio_mport *mport, u16 destid, u16 data) ...@@ -166,7 +166,7 @@ int rio_mport_send_doorbell(struct rio_mport *mport, u16 destid, u16 data)
unsigned long flags; unsigned long flags;
spin_lock_irqsave(&rio_doorbell_lock, 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); spin_unlock_irqrestore(&rio_doorbell_lock, flags);
return res; return res;
......
...@@ -73,7 +73,7 @@ static u16 rio_get_device_id(struct rio_mport *port, u16 destid, u8 hopcount) ...@@ -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); 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) ...@@ -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) 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_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 ...@@ -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) 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, ...@@ -350,8 +351,18 @@ static struct rio_dev *rio_setup_device(struct rio_net *net,
rswitch->switchid = next_switchid; rswitch->switchid = next_switchid;
rswitch->hopcount = hopcount; rswitch->hopcount = hopcount;
rswitch->destid = destid; 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 */ /* 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; rswitch->route_table[rdid] = RIO_INVALID_ROUTE;
rdev->rswitch = rswitch; rdev->rswitch = rswitch;
sprintf(rio_name(rdev), "%02x:s:%04x", rdev->net->id, 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) ...@@ -480,7 +491,7 @@ static u16 rio_get_host_deviceid_lock(struct rio_mport *port, u8 hopcount)
{ {
u32 result; 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); RIO_HOST_DID_LOCK_CSR, &result);
return (u16) (result & 0xffff); return (u16) (result & 0xffff);
...@@ -571,14 +582,16 @@ static int rio_enum_peer(struct rio_net *net, struct rio_mport *port, ...@@ -571,14 +582,16 @@ static int rio_enum_peer(struct rio_net *net, struct rio_mport *port,
} }
/* Attempt to acquire device lock */ /* 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); RIO_HOST_DID_LOCK_CSR, port->host_deviceid);
while ((tmp = rio_get_host_deviceid_lock(port, hopcount)) while ((tmp = rio_get_host_deviceid_lock(port, hopcount))
< port->host_deviceid) { < port->host_deviceid) {
/* Delay a bit */ /* Delay a bit */
mdelay(1); mdelay(1);
/* Attempt to acquire device lock again */ /* 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, RIO_HOST_DID_LOCK_CSR,
port->host_deviceid); port->host_deviceid);
} }
...@@ -590,7 +603,9 @@ static int rio_enum_peer(struct rio_net *net, struct rio_mport *port, ...@@ -590,7 +603,9 @@ static int rio_enum_peer(struct rio_net *net, struct rio_mport *port,
} }
/* Setup new RIO device */ /* 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. */ /* Add device to the global and bus/net specific list. */
list_add_tail(&rdev->net_list, &net->devices); list_add_tail(&rdev->net_list, &net->devices);
} else } else
...@@ -598,7 +613,8 @@ static int rio_enum_peer(struct rio_net *net, struct rio_mport *port, ...@@ -598,7 +613,8 @@ static int rio_enum_peer(struct rio_net *net, struct rio_mport *port,
if (rio_is_switch(rdev)) { if (rio_is_switch(rdev)) {
next_switchid++; 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, rio_route_add_entry(port, rdev->rswitch, RIO_GLOBAL_TABLE,
port->host_deviceid, sw_inport); port->host_deviceid, sw_inport);
rdev->rswitch->route_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, ...@@ -612,7 +628,8 @@ static int rio_enum_peer(struct rio_net *net, struct rio_mport *port,
} }
num_ports = 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( pr_debug(
"RIO: found %s (vid %4.4x did %4.4x) with %d ports\n", "RIO: found %s (vid %4.4x did %4.4x) with %d ports\n",
rio_name(rdev), rdev->vid, rdev->did, num_ports); 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, ...@@ -624,13 +641,15 @@ static int rio_enum_peer(struct rio_net *net, struct rio_mport *port,
cur_destid = next_destid; cur_destid = next_destid;
if (rio_sport_is_active if (rio_sport_is_active
(port, RIO_ANY_DESTID, hopcount, port_num)) { (port, RIO_ANY_DESTID(port->sys_size), hopcount,
port_num)) {
pr_debug( pr_debug(
"RIO: scanning device on port %d\n", "RIO: scanning device on port %d\n",
port_num); port_num);
rio_route_add_entry(port, rdev->rswitch, rio_route_add_entry(port, rdev->rswitch,
RIO_GLOBAL_TABLE, RIO_GLOBAL_TABLE,
RIO_ANY_DESTID, port_num); RIO_ANY_DESTID(port->sys_size),
port_num);
if (rio_enum_peer(net, port, hopcount + 1) < 0) if (rio_enum_peer(net, port, hopcount + 1) < 0)
return -1; return -1;
...@@ -735,7 +754,8 @@ rio_disc_peer(struct rio_net *net, struct rio_mport *port, u16 destid, ...@@ -735,7 +754,8 @@ rio_disc_peer(struct rio_net *net, struct rio_mport *port, u16 destid,
pr_debug( pr_debug(
"RIO: scanning device on port %d\n", "RIO: scanning device on port %d\n",
port_num); port_num);
for (ndestid = 0; ndestid < RIO_ANY_DESTID; for (ndestid = 0;
ndestid < RIO_ANY_DESTID(port->sys_size);
ndestid++) { ndestid++) {
rio_route_get_entry(port, rdev->rswitch, rio_route_get_entry(port, rdev->rswitch,
RIO_GLOBAL_TABLE, RIO_GLOBAL_TABLE,
...@@ -917,7 +937,9 @@ static void rio_build_route_tables(void) ...@@ -917,7 +937,9 @@ static void rio_build_route_tables(void)
list_for_each_entry(rdev, &rio_devices, global_list) list_for_each_entry(rdev, &rio_devices, global_list)
if (rio_is_switch(rdev)) 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 if (rio_route_get_entry
(rdev->net->hport, rdev->rswitch, RIO_GLOBAL_TABLE, (rdev->net->hport, rdev->rswitch, RIO_GLOBAL_TABLE,
i, &sport) < 0) i, &sport) < 0)
...@@ -981,7 +1003,8 @@ int rio_disc_mport(struct rio_mport *mport) ...@@ -981,7 +1003,8 @@ int rio_disc_mport(struct rio_mport *mport)
del_timer_sync(&rio_enum_timer); del_timer_sync(&rio_enum_timer);
pr_debug("done\n"); 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 printk(KERN_INFO
"RIO: master port %d device has failed discovery\n", "RIO: master port %d device has failed discovery\n",
mport->id); mport->id);
......
...@@ -43,7 +43,8 @@ static ssize_t routes_show(struct device *dev, struct device_attribute *attr, ch ...@@ -43,7 +43,8 @@ static ssize_t routes_show(struct device *dev, struct device_attribute *attr, ch
if (!rdev->rswitch) if (!rdev->rswitch)
goto out; 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) if (rdev->rswitch->route_table[i] == RIO_INVALID_ROUTE)
continue; continue;
str += str +=
......
...@@ -43,7 +43,7 @@ u16 rio_local_get_device_id(struct rio_mport *port) ...@@ -43,7 +43,7 @@ u16 rio_local_get_device_id(struct rio_mport *port)
rio_local_read_config_32(port, RIO_DID_CSR, &result); 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[]; ...@@ -51,10 +51,5 @@ extern struct rio_route_ops __end_rio_route_ops[];
DECLARE_RIO_ROUTE_SECTION(.rio_route_ops, \ DECLARE_RIO_ROUTE_SECTION(.rio_route_ops, \
vid, did, add_hook, get_hook) vid, did, add_hook, get_hook)
#ifdef CONFIG_RAPIDIO_8_BIT_TRANSPORT #define RIO_GET_DID(size, x) (size ? (x & 0xffff) : ((x & 0x00ff0000) >> 16))
#define RIO_GET_DID(x) ((x & 0x00ff0000) >> 16) #define RIO_SET_DID(size, x) (size ? (x & 0xffff) : ((x & 0x000000ff) << 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
...@@ -138,6 +138,8 @@ typedef struct { ...@@ -138,6 +138,8 @@ typedef struct {
struct thread_struct { struct thread_struct {
unsigned long ksp; /* Kernel stack pointer */ unsigned long ksp; /* Kernel stack pointer */
unsigned long ksp_limit; /* if ksp <= ksp_limit stack overflow */
#ifdef CONFIG_PPC64 #ifdef CONFIG_PPC64
unsigned long ksp_vsid; unsigned long ksp_vsid;
#endif #endif
...@@ -182,11 +184,14 @@ struct thread_struct { ...@@ -182,11 +184,14 @@ struct thread_struct {
#define ARCH_MIN_TASKALIGN 16 #define ARCH_MIN_TASKALIGN 16
#define INIT_SP (sizeof(init_stack) + (unsigned long) &init_stack) #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 #ifdef CONFIG_PPC32
#define INIT_THREAD { \ #define INIT_THREAD { \
.ksp = INIT_SP, \ .ksp = INIT_SP, \
.ksp_limit = INIT_SP_LIMIT, \
.fs = KERNEL_DS, \ .fs = KERNEL_DS, \
.pgdir = swapper_pg_dir, \ .pgdir = swapper_pg_dir, \
.fpexc_mode = MSR_FE0 | MSR_FE1, \ .fpexc_mode = MSR_FE0 | MSR_FE1, \
...@@ -194,6 +199,7 @@ struct thread_struct { ...@@ -194,6 +199,7 @@ struct thread_struct {
#else #else
#define INIT_THREAD { \ #define INIT_THREAD { \
.ksp = INIT_SP, \ .ksp = INIT_SP, \
.ksp_limit = INIT_SP_LIMIT, \
.regs = (struct pt_regs *)INIT_SP - 1, /* XXX bogus, I think */ \ .regs = (struct pt_regs *)INIT_SP - 1, /* XXX bogus, I think */ \
.fs = KERNEL_DS, \ .fs = KERNEL_DS, \
.fpr = {0}, \ .fpr = {0}, \
......
...@@ -204,7 +204,7 @@ extern int powersave_nap; /* set if nap mode can be used in idle loop */ ...@@ -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 * Changes the memory location '*ptr' to be val and returns
* the previous value stored there. * the previous value stored there.
*/ */
static __inline__ unsigned long static __always_inline unsigned long
__xchg_u32(volatile void *p, unsigned long val) __xchg_u32(volatile void *p, unsigned long val)
{ {
unsigned long prev; unsigned long prev;
...@@ -229,7 +229,7 @@ __xchg_u32(volatile void *p, unsigned long val) ...@@ -229,7 +229,7 @@ __xchg_u32(volatile void *p, unsigned long val)
* Changes the memory location '*ptr' to be val and returns * Changes the memory location '*ptr' to be val and returns
* the previous value stored there. * the previous value stored there.
*/ */
static __inline__ unsigned long static __always_inline unsigned long
__xchg_u32_local(volatile void *p, unsigned long val) __xchg_u32_local(volatile void *p, unsigned long val)
{ {
unsigned long prev; unsigned long prev;
...@@ -247,7 +247,7 @@ __xchg_u32_local(volatile void *p, unsigned long val) ...@@ -247,7 +247,7 @@ __xchg_u32_local(volatile void *p, unsigned long val)
} }
#ifdef CONFIG_PPC64 #ifdef CONFIG_PPC64
static __inline__ unsigned long static __always_inline unsigned long
__xchg_u64(volatile void *p, unsigned long val) __xchg_u64(volatile void *p, unsigned long val)
{ {
unsigned long prev; unsigned long prev;
...@@ -266,7 +266,7 @@ __xchg_u64(volatile void *p, unsigned long val) ...@@ -266,7 +266,7 @@ __xchg_u64(volatile void *p, unsigned long val)
return prev; return prev;
} }
static __inline__ unsigned long static __always_inline unsigned long
__xchg_u64_local(volatile void *p, unsigned long val) __xchg_u64_local(volatile void *p, unsigned long val)
{ {
unsigned long prev; unsigned long prev;
...@@ -290,7 +290,7 @@ __xchg_u64_local(volatile void *p, unsigned long val) ...@@ -290,7 +290,7 @@ __xchg_u64_local(volatile void *p, unsigned long val)
*/ */
extern void __xchg_called_with_bad_pointer(void); 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) __xchg(volatile void *ptr, unsigned long x, unsigned int size)
{ {
switch (size) { switch (size) {
...@@ -305,7 +305,7 @@ __xchg(volatile void *ptr, unsigned long x, unsigned int size) ...@@ -305,7 +305,7 @@ __xchg(volatile void *ptr, unsigned long x, unsigned int size)
return x; return x;
} }
static __inline__ unsigned long static __always_inline unsigned long
__xchg_local(volatile void *ptr, unsigned long x, unsigned int size) __xchg_local(volatile void *ptr, unsigned long x, unsigned int size)
{ {
switch (size) { switch (size) {
...@@ -338,7 +338,7 @@ __xchg_local(volatile void *ptr, unsigned long x, unsigned int size) ...@@ -338,7 +338,7 @@ __xchg_local(volatile void *ptr, unsigned long x, unsigned int size)
*/ */
#define __HAVE_ARCH_CMPXCHG 1 #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) __cmpxchg_u32(volatile unsigned int *p, unsigned long old, unsigned long new)
{ {
unsigned int prev; unsigned int prev;
...@@ -361,7 +361,7 @@ __cmpxchg_u32(volatile unsigned int *p, unsigned long old, unsigned long new) ...@@ -361,7 +361,7 @@ __cmpxchg_u32(volatile unsigned int *p, unsigned long old, unsigned long new)
return prev; return prev;
} }
static __inline__ unsigned long static __always_inline unsigned long
__cmpxchg_u32_local(volatile unsigned int *p, unsigned long old, __cmpxchg_u32_local(volatile unsigned int *p, unsigned long old,
unsigned long new) unsigned long new)
{ {
...@@ -384,7 +384,7 @@ __cmpxchg_u32_local(volatile unsigned int *p, unsigned long old, ...@@ -384,7 +384,7 @@ __cmpxchg_u32_local(volatile unsigned int *p, unsigned long old,
} }
#ifdef CONFIG_PPC64 #ifdef CONFIG_PPC64
static __inline__ unsigned long static __always_inline unsigned long
__cmpxchg_u64(volatile unsigned long *p, unsigned long old, unsigned long new) __cmpxchg_u64(volatile unsigned long *p, unsigned long old, unsigned long new)
{ {
unsigned long prev; unsigned long prev;
...@@ -406,7 +406,7 @@ __cmpxchg_u64(volatile unsigned long *p, unsigned long old, unsigned long new) ...@@ -406,7 +406,7 @@ __cmpxchg_u64(volatile unsigned long *p, unsigned long old, unsigned long new)
return prev; return prev;
} }
static __inline__ unsigned long static __always_inline unsigned long
__cmpxchg_u64_local(volatile unsigned long *p, unsigned long old, __cmpxchg_u64_local(volatile unsigned long *p, unsigned long old,
unsigned long new) unsigned long new)
{ {
...@@ -432,7 +432,7 @@ __cmpxchg_u64_local(volatile unsigned long *p, unsigned long old, ...@@ -432,7 +432,7 @@ __cmpxchg_u64_local(volatile unsigned long *p, unsigned long old,
if something tries to do an invalid cmpxchg(). */ if something tries to do an invalid cmpxchg(). */
extern void __cmpxchg_called_with_bad_pointer(void); 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, __cmpxchg(volatile void *ptr, unsigned long old, unsigned long new,
unsigned int size) unsigned int size)
{ {
...@@ -448,7 +448,7 @@ __cmpxchg(volatile void *ptr, unsigned long old, unsigned long new, ...@@ -448,7 +448,7 @@ __cmpxchg(volatile void *ptr, unsigned long old, unsigned long new,
return old; return old;
} }
static __inline__ unsigned long static __always_inline unsigned long
__cmpxchg_local(volatile void *ptr, unsigned long old, unsigned long new, __cmpxchg_local(volatile void *ptr, unsigned long old, unsigned long new,
unsigned int size) unsigned int size)
{ {
......
...@@ -40,7 +40,8 @@ extern struct lmb lmb; ...@@ -40,7 +40,8 @@ extern struct lmb lmb;
extern void __init lmb_init(void); extern void __init lmb_init(void);
extern void __init lmb_analyze(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 long __init lmb_reserve(u64 base, u64 size);
extern u64 __init lmb_alloc_nid(u64 size, u64 align, int nid, extern u64 __init lmb_alloc_nid(u64 size, u64 align, int nid,
u64 (*nid_range)(u64, u64, int *)); u64 (*nid_range)(u64, u64, int *));
...@@ -53,6 +54,7 @@ extern u64 __init lmb_phys_mem_size(void); ...@@ -53,6 +54,7 @@ extern u64 __init lmb_phys_mem_size(void);
extern u64 __init lmb_end_of_DRAM(void); extern u64 __init lmb_end_of_DRAM(void);
extern void __init lmb_enforce_memory_limit(u64 memory_limit); extern void __init lmb_enforce_memory_limit(u64 memory_limit);
extern int __init lmb_is_reserved(u64 addr); extern int __init lmb_is_reserved(u64 addr);
extern int lmb_find(struct lmb_property *res);
extern void lmb_dump_all(void); extern void lmb_dump_all(void);
......
...@@ -23,7 +23,6 @@ ...@@ -23,7 +23,6 @@
#include <linux/device.h> #include <linux/device.h>
#include <linux/rio_regs.h> #include <linux/rio_regs.h>
#define RIO_ANY_DESTID 0xff
#define RIO_NO_HOPCOUNT -1 #define RIO_NO_HOPCOUNT -1
#define RIO_INVALID_DESTID 0xffff #define RIO_INVALID_DESTID 0xffff
...@@ -39,11 +38,8 @@ ...@@ -39,11 +38,8 @@
entry is invalid (no route entry is invalid (no route
exists for the device ID) */ exists for the device ID) */
#ifdef CONFIG_RAPIDIO_8_BIT_TRANSPORT #define RIO_MAX_ROUTE_ENTRIES(size) (size ? (1 << 16) : (1 << 8))
#define RIO_MAX_ROUTE_ENTRIES (1 << 8) #define RIO_ANY_DESTID(size) (size ? 0xffff : 0xff)
#else
#define RIO_MAX_ROUTE_ENTRIES (1 << 16)
#endif
#define RIO_MAX_MBOX 4 #define RIO_MAX_MBOX 4
#define RIO_MAX_MSG_SIZE 0x1000 #define RIO_MAX_MSG_SIZE 0x1000
...@@ -149,6 +145,11 @@ struct rio_dbell { ...@@ -149,6 +145,11 @@ struct rio_dbell {
void *dev_id; void *dev_id;
}; };
enum rio_phy_type {
RIO_PHY_PARALLEL,
RIO_PHY_SERIAL,
};
/** /**
* struct rio_mport - RIO master port info * struct rio_mport - RIO master port info
* @dbells: List of doorbell events * @dbells: List of doorbell events
...@@ -163,6 +164,7 @@ struct rio_dbell { ...@@ -163,6 +164,7 @@ struct rio_dbell {
* @id: Port ID, unique among all ports * @id: Port ID, unique among all ports
* @index: Port index, unique among all port interfaces of the same type * @index: Port index, unique among all port interfaces of the same type
* @name: Port name string * @name: Port name string
* @priv: Master port private data
*/ */
struct rio_mport { struct rio_mport {
struct list_head dbells; /* list of doorbell events */ struct list_head dbells; /* list of doorbell events */
...@@ -177,7 +179,13 @@ struct rio_mport { ...@@ -177,7 +179,13 @@ struct rio_mport {
unsigned char id; /* port ID, unique among all ports */ unsigned char id; /* port ID, unique among all ports */
unsigned char index; /* port index, unique among all port unsigned char index; /* port index, unique among all port
interfaces of the same type */ 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]; unsigned char name[40];
void *priv; /* Master port private data */
}; };
/** /**
...@@ -211,7 +219,7 @@ struct rio_switch { ...@@ -211,7 +219,7 @@ struct rio_switch {
u16 switchid; u16 switchid;
u16 hopcount; u16 hopcount;
u16 destid; u16 destid;
u8 route_table[RIO_MAX_ROUTE_ENTRIES]; u8 *route_table;
int (*add_entry) (struct rio_mport * mport, u16 destid, u8 hopcount, int (*add_entry) (struct rio_mport * mport, u16 destid, u8 hopcount,
u16 table, u16 route_destid, u8 route_port); u16 table, u16 route_destid, u8 route_port);
int (*get_entry) (struct rio_mport * mport, u16 destid, u8 hopcount, int (*get_entry) (struct rio_mport * mport, u16 destid, u8 hopcount,
...@@ -229,13 +237,15 @@ struct rio_switch { ...@@ -229,13 +237,15 @@ struct rio_switch {
* @dsend: Callback to send a doorbell message. * @dsend: Callback to send a doorbell message.
*/ */
struct rio_ops { struct rio_ops {
int (*lcread) (int index, u32 offset, int len, u32 * data); int (*lcread) (struct rio_mport *mport, int index, u32 offset, int len,
int (*lcwrite) (int index, u32 offset, int len, u32 data); u32 *data);
int (*cread) (int index, u16 destid, u8 hopcount, u32 offset, int len, int (*lcwrite) (struct rio_mport *mport, int index, u32 offset, int len,
u32 * data); u32 data);
int (*cwrite) (int index, u16 destid, u8 hopcount, u32 offset, int len, int (*cread) (struct rio_mport *mport, int index, u16 destid,
u32 data); u8 hopcount, u32 offset, int len, u32 *data);
int (*dsend) (int index, u16 destid, u16 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 #define RIO_RESOURCE_MEM 0x00000100
......
...@@ -46,14 +46,13 @@ void lmb_dump_all(void) ...@@ -46,14 +46,13 @@ void lmb_dump_all(void)
#endif /* DEBUG */ #endif /* DEBUG */
} }
static unsigned long __init lmb_addrs_overlap(u64 base1, u64 size1, static unsigned long lmb_addrs_overlap(u64 base1, u64 size1, u64 base2,
u64 base2, u64 size2) u64 size2)
{ {
return ((base1 < (base2 + size2)) && (base2 < (base1 + size1))); return ((base1 < (base2 + size2)) && (base2 < (base1 + size1)));
} }
static long __init lmb_addrs_adjacent(u64 base1, u64 size1, static long lmb_addrs_adjacent(u64 base1, u64 size1, u64 base2, u64 size2)
u64 base2, u64 size2)
{ {
if (base2 == base1 + size1) if (base2 == base1 + size1)
return 1; return 1;
...@@ -63,7 +62,7 @@ static long __init lmb_addrs_adjacent(u64 base1, u64 size1, ...@@ -63,7 +62,7 @@ static long __init lmb_addrs_adjacent(u64 base1, u64 size1,
return 0; 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) unsigned long r1, unsigned long r2)
{ {
u64 base1 = rgn->region[r1].base; u64 base1 = rgn->region[r1].base;
...@@ -74,7 +73,7 @@ static long __init lmb_regions_adjacent(struct lmb_region *rgn, ...@@ -74,7 +73,7 @@ static long __init lmb_regions_adjacent(struct lmb_region *rgn,
return lmb_addrs_adjacent(base1, size1, base2, size2); 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; unsigned long i;
...@@ -86,7 +85,7 @@ static void __init lmb_remove_region(struct lmb_region *rgn, unsigned long r) ...@@ -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 */ /* 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) unsigned long r1, unsigned long r2)
{ {
rgn->region[r1].size += rgn->region[r2].size; rgn->region[r1].size += rgn->region[r2].size;
...@@ -118,7 +117,7 @@ void __init lmb_analyze(void) ...@@ -118,7 +117,7 @@ void __init lmb_analyze(void)
lmb.memory.size += lmb.memory.region[i].size; 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; unsigned long coalesced = 0;
long adjacent, i; long adjacent, i;
...@@ -182,7 +181,7 @@ static long __init lmb_add_region(struct lmb_region *rgn, u64 base, u64 size) ...@@ -182,7 +181,7 @@ static long __init lmb_add_region(struct lmb_region *rgn, u64 base, u64 size)
return 0; return 0;
} }
long __init lmb_add(u64 base, u64 size) long lmb_add(u64 base, u64 size)
{ {
struct lmb_region *_rgn = &lmb.memory; struct lmb_region *_rgn = &lmb.memory;
...@@ -194,6 +193,55 @@ long __init lmb_add(u64 base, u64 size) ...@@ -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) long __init lmb_reserve(u64 base, u64 size)
{ {
struct lmb_region *_rgn = &lmb.reserved; struct lmb_region *_rgn = &lmb.reserved;
...@@ -426,3 +474,36 @@ int __init lmb_is_reserved(u64 addr) ...@@ -426,3 +474,36 @@ int __init lmb_is_reserved(u64 addr)
} }
return 0; 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;
}
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