Commit 6e98ee75 authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'master' of master.kernel.org:/pub/scm/linux/kernel/git/davem/sparc-2.6

* 'master' of master.kernel.org:/pub/scm/linux/kernel/git/davem/sparc-2.6:
  [SPARC64]: Fill holes in hypervisor APIs and fix KTSB registry.
  [SPARC64]: Fix two bugs wrt. kernel 4MB TSB.
  [SPARC]: Mark as emulating cmpxchg, add appropriate depends for DRM.
  [SPARC]: Emulate cmpxchg like parisc
  [SPARC64]: Fix _PAGE_EXEC_4U check in sun4u I-TLB miss handler.
  [SPARC]: Linux always started with 9600 8N1
  [SPARC64]: arch/sparc64/time.c doesn't compile on Ultra 1 (no PCI)
  [SPARC64]: Eliminate NR_CPUS limitations.
  [SPARC64]: Use machine description and OBP properly for cpu probing.
  [SPARC64]: Negotiate hypervisor API for PCI services.
  [SPARC64]: Report proper system soft state to the hypervisor.
  [SPARC64]: Fix typo in sun4v_hvapi_register error handling.
  [SCSI] ESP: Kill SCSI_ESP_CORE and link directly just like jazz_esp
  [SCSI] jazz_esp: Converted to use esp_core.
  [SPARC64]: PCI device scan is way too verbose by default.
  [SERIAL] sunzilog: section mismatch fix
  [SPARC32]: Removes mismatch section warnigs in sparc time.c file
  [SPARC64]: Don't be picky about virtual-dma values on sun4v.
  [SPARC64]: Kill unused DIE_PAGE_FAULT enum value.
  [SCSI] pluto: Use wait_for_completion_timeout.
parents 486b4ce1 7db35f31
......@@ -178,6 +178,13 @@ config ARCH_HAS_ILOG2_U64
bool
default n
config EMULATED_CMPXCHG
bool
default y
help
Sparc32 does not have a CAS instruction like sparc64. cmpxchg()
is emulated, and therefore it is not completely atomic.
config SUN_PM
bool
default y
......
......@@ -148,7 +148,7 @@ irqreturn_t timer_interrupt(int irq, void *dev_id)
}
/* Kick start a stopped clock (procedure from the Sun NVRAM/hostid FAQ). */
static void __init kick_start_clock(void)
static void __devinit kick_start_clock(void)
{
struct mostek48t02 *regs = (struct mostek48t02 *)mstk48t02_regs;
unsigned char sec;
......@@ -223,7 +223,7 @@ static __inline__ int has_low_battery(void)
return (data1 == data2); /* Was the write blocked? */
}
static void __init mostek_set_system_time(void)
static void __devinit mostek_set_system_time(void)
{
unsigned int year, mon, day, hour, min, sec;
struct mostek48t02 *mregs;
......
......@@ -2,6 +2,7 @@
* atomic32.c: 32-bit atomic_t implementation
*
* Copyright (C) 2004 Keith M Wesolowski
* Copyright (C) 2007 Kyle McMartin
*
* Based on asm-parisc/atomic.h Copyright (C) 2000 Philipp Rumpf
*/
......@@ -117,3 +118,17 @@ unsigned long ___change_bit(unsigned long *addr, unsigned long mask)
return old & mask;
}
EXPORT_SYMBOL(___change_bit);
unsigned long __cmpxchg_u32(volatile u32 *ptr, u32 old, u32 new)
{
unsigned long flags;
u32 prev;
spin_lock_irqsave(ATOMIC_HASH(addr), flags);
if ((prev = *ptr) == old)
*ptr = new;
spin_unlock_irqrestore(ATOMIC_HASH(addr), flags);
return (unsigned long)prev;
}
EXPORT_SYMBOL(__cmpxchg_u32);
......@@ -147,10 +147,10 @@ config SMP
If you don't know what to do here, say N.
config NR_CPUS
int "Maximum number of CPUs (2-64)"
range 2 64
int "Maximum number of CPUs (2-1024)"
range 2 1024
depends on SMP
default "32"
default "64"
source "drivers/cpufreq/Kconfig"
......
......@@ -8,11 +8,11 @@ EXTRA_CFLAGS := -Werror
extra-y := head.o init_task.o vmlinux.lds
obj-y := process.o setup.o cpu.o idprom.o \
traps.o devices.o auxio.o una_asm.o \
traps.o auxio.o una_asm.o \
irq.o ptrace.o time.o sys_sparc.o signal.o \
unaligned.o central.o pci.o starfire.o semaphore.o \
power.o sbus.o iommu_common.o sparc64_ksyms.o chmc.o \
visemul.o prom.o of_device.o hvapi.o
visemul.o prom.o of_device.o hvapi.o sstate.o mdesc.o
obj-$(CONFIG_STACKTRACE) += stacktrace.o
obj-$(CONFIG_PCI) += ebus.o isa.o pci_common.o pci_iommu.o \
......
/* devices.c: Initial scan of the prom device tree for important
* Sparc device nodes which we need to find.
*
* Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
*/
#include <linux/kernel.h>
#include <linux/threads.h>
#include <linux/init.h>
#include <linux/ioport.h>
#include <linux/string.h>
#include <linux/spinlock.h>
#include <linux/errno.h>
#include <linux/bootmem.h>
#include <asm/page.h>
#include <asm/oplib.h>
#include <asm/system.h>
#include <asm/smp.h>
#include <asm/spitfire.h>
#include <asm/timer.h>
#include <asm/cpudata.h>
/* Used to synchronize accesses to NatSemi SUPER I/O chip configure
* operations in asm/ns87303.h
*/
DEFINE_SPINLOCK(ns87303_lock);
extern void cpu_probe(void);
extern void central_probe(void);
static const char *cpu_mid_prop(void)
{
if (tlb_type == spitfire)
return "upa-portid";
return "portid";
}
static int get_cpu_mid(struct device_node *dp)
{
struct property *prop;
if (tlb_type == hypervisor) {
struct linux_prom64_registers *reg;
int len;
prop = of_find_property(dp, "cpuid", &len);
if (prop && len == 4)
return *(int *) prop->value;
prop = of_find_property(dp, "reg", NULL);
reg = prop->value;
return (reg[0].phys_addr >> 32) & 0x0fffffffUL;
} else {
const char *prop_name = cpu_mid_prop();
prop = of_find_property(dp, prop_name, NULL);
if (prop)
return *(int *) prop->value;
return 0;
}
}
static int check_cpu_node(struct device_node *dp, int *cur_inst,
int (*compare)(struct device_node *, int, void *),
void *compare_arg,
struct device_node **dev_node, int *mid)
{
if (!compare(dp, *cur_inst, compare_arg)) {
if (dev_node)
*dev_node = dp;
if (mid)
*mid = get_cpu_mid(dp);
return 0;
}
(*cur_inst)++;
return -ENODEV;
}
static int __cpu_find_by(int (*compare)(struct device_node *, int, void *),
void *compare_arg,
struct device_node **dev_node, int *mid)
{
struct device_node *dp;
int cur_inst;
cur_inst = 0;
for_each_node_by_type(dp, "cpu") {
int err = check_cpu_node(dp, &cur_inst,
compare, compare_arg,
dev_node, mid);
if (err == 0)
return 0;
}
return -ENODEV;
}
static int cpu_instance_compare(struct device_node *dp, int instance, void *_arg)
{
int desired_instance = (int) (long) _arg;
if (instance == desired_instance)
return 0;
return -ENODEV;
}
int cpu_find_by_instance(int instance, struct device_node **dev_node, int *mid)
{
return __cpu_find_by(cpu_instance_compare, (void *)(long)instance,
dev_node, mid);
}
static int cpu_mid_compare(struct device_node *dp, int instance, void *_arg)
{
int desired_mid = (int) (long) _arg;
int this_mid;
this_mid = get_cpu_mid(dp);
if (this_mid == desired_mid)
return 0;
return -ENODEV;
}
int cpu_find_by_mid(int mid, struct device_node **dev_node)
{
return __cpu_find_by(cpu_mid_compare, (void *)(long)mid,
dev_node, NULL);
}
void __init device_scan(void)
{
/* FIX ME FAST... -DaveM */
ioport_resource.end = 0xffffffffffffffffUL;
prom_printf("Booting Linux...\n");
#ifndef CONFIG_SMP
{
struct device_node *dp;
int err, def;
err = cpu_find_by_instance(0, &dp, NULL);
if (err) {
prom_printf("No cpu nodes, cannot continue\n");
prom_halt();
}
cpu_data(0).clock_tick =
of_getintprop_default(dp, "clock-frequency", 0);
def = ((tlb_type == hypervisor) ?
(8 * 1024) :
(16 * 1024));
cpu_data(0).dcache_size = of_getintprop_default(dp,
"dcache-size",
def);
def = 32;
cpu_data(0).dcache_line_size =
of_getintprop_default(dp, "dcache-line-size", def);
def = 16 * 1024;
cpu_data(0).icache_size = of_getintprop_default(dp,
"icache-size",
def);
def = 32;
cpu_data(0).icache_line_size =
of_getintprop_default(dp, "icache-line-size", def);
def = ((tlb_type == hypervisor) ?
(3 * 1024 * 1024) :
(4 * 1024 * 1024));
cpu_data(0).ecache_size = of_getintprop_default(dp,
"ecache-size",
def);
def = 64;
cpu_data(0).ecache_line_size =
of_getintprop_default(dp, "ecache-line-size", def);
printk("CPU[0]: Caches "
"D[sz(%d):line_sz(%d)] "
"I[sz(%d):line_sz(%d)] "
"E[sz(%d):line_sz(%d)]\n",
cpu_data(0).dcache_size, cpu_data(0).dcache_line_size,
cpu_data(0).icache_size, cpu_data(0).icache_line_size,
cpu_data(0).ecache_size, cpu_data(0).ecache_line_size);
}
#endif
central_probe();
cpu_probe();
}
This diff is collapsed.
......@@ -523,7 +523,7 @@ tlb_fixup_done:
#else
mov 0, %o0
#endif
stb %o0, [%g6 + TI_CPU]
sth %o0, [%g6 + TI_CPU]
/* Off we go.... */
call start_kernel
......@@ -653,33 +653,54 @@ setup_tba:
restore
sparc64_boot_end:
#include "ktlb.S"
#include "tsb.S"
#include "etrap.S"
#include "rtrap.S"
#include "winfixup.S"
#include "entry.S"
#include "sun4v_tlb_miss.S"
#include "sun4v_ivec.S"
#include "ktlb.S"
#include "tsb.S"
/*
* The following skip makes sure the trap table in ttable.S is aligned
* on a 32K boundary as required by the v9 specs for TBA register.
*
* We align to a 32K boundary, then we have the 32K kernel TSB,
* then the 32K aligned trap table.
* the 64K kernel 4MB TSB, and then the 32K aligned trap table.
*/
1:
.skip 0x4000 + _start - 1b
! 0x0000000000408000
.globl swapper_tsb
swapper_tsb:
.skip (32 * 1024)
! 0x0000000000408000
.globl swapper_4m_tsb
swapper_4m_tsb:
.skip (64 * 1024)
! 0x0000000000420000
/* Some care needs to be exercised if you try to move the
* location of the trap table relative to other things. For
* one thing there are br* instructions in some of the
* trap table entires which branch back to code in ktlb.S
* Those instructions can only handle a signed 16-bit
* displacement.
*
* There is a binutils bug (bugzilla #4558) which causes
* the relocation overflow checks for such instructions to
* not be done correctly. So bintuils will not notice the
* error and will instead write junk into the relocation and
* you'll have an unbootable kernel.
*/
#include "ttable.S"
! 0x0000000000428000
#include "systbls.S"
.data
......
......@@ -9,6 +9,7 @@
#include <asm/hypervisor.h>
#include <asm/oplib.h>
#include <asm/sstate.h>
/* If the hypervisor indicates that the API setting
* calls are unsupported, by returning HV_EBADTRAP or
......@@ -107,7 +108,7 @@ int sun4v_hvapi_register(unsigned long group, unsigned long major,
p->minor = actual_minor;
ret = 0;
} else if (hv_ret == HV_EBADTRAP ||
HV_ENOTSUPPORTED) {
hv_ret == HV_ENOTSUPPORTED) {
if (p->flags & FLAG_PRE_API) {
if (major == 1) {
p->major = 1;
......@@ -179,6 +180,8 @@ void __init sun4v_hvapi_init(void)
if (sun4v_hvapi_register(group, major, &minor))
goto bad;
sun4v_sstate_init();
return;
bad:
......
......@@ -171,8 +171,6 @@ int show_interrupts(struct seq_file *p, void *v)
return 0;
}
extern unsigned long real_hard_smp_processor_id(void);
static unsigned int sun4u_compute_tid(unsigned long imap, unsigned long cpuid)
{
unsigned int tid;
......@@ -694,9 +692,20 @@ void init_irqwork_curcpu(void)
trap_block[cpu].irq_worklist = 0;
}
static void __cpuinit register_one_mondo(unsigned long paddr, unsigned long type)
/* Please be very careful with register_one_mondo() and
* sun4v_register_mondo_queues().
*
* On SMP this gets invoked from the CPU trampoline before
* the cpu has fully taken over the trap table from OBP,
* and it's kernel stack + %g6 thread register state is
* not fully cooked yet.
*
* Therefore you cannot make any OBP calls, not even prom_printf,
* from these two routines.
*/
static void __cpuinit register_one_mondo(unsigned long paddr, unsigned long type, unsigned long qmask)
{
unsigned long num_entries = 128;
unsigned long num_entries = (qmask + 1) / 64;
unsigned long status;
status = sun4v_cpu_qconf(type, paddr, num_entries);
......@@ -711,44 +720,58 @@ static void __cpuinit sun4v_register_mondo_queues(int this_cpu)
{
struct trap_per_cpu *tb = &trap_block[this_cpu];
register_one_mondo(tb->cpu_mondo_pa, HV_CPU_QUEUE_CPU_MONDO);
register_one_mondo(tb->dev_mondo_pa, HV_CPU_QUEUE_DEVICE_MONDO);
register_one_mondo(tb->resum_mondo_pa, HV_CPU_QUEUE_RES_ERROR);
register_one_mondo(tb->nonresum_mondo_pa, HV_CPU_QUEUE_NONRES_ERROR);
register_one_mondo(tb->cpu_mondo_pa, HV_CPU_QUEUE_CPU_MONDO,
tb->cpu_mondo_qmask);
register_one_mondo(tb->dev_mondo_pa, HV_CPU_QUEUE_DEVICE_MONDO,
tb->dev_mondo_qmask);
register_one_mondo(tb->resum_mondo_pa, HV_CPU_QUEUE_RES_ERROR,
tb->resum_qmask);
register_one_mondo(tb->nonresum_mondo_pa, HV_CPU_QUEUE_NONRES_ERROR,
tb->nonresum_qmask);
}
static void __cpuinit alloc_one_mondo(unsigned long *pa_ptr, int use_bootmem)
static void __cpuinit alloc_one_mondo(unsigned long *pa_ptr, unsigned long qmask, int use_bootmem)
{
void *page;
unsigned long size = PAGE_ALIGN(qmask + 1);
unsigned long order = get_order(size);
void *p = NULL;
if (use_bootmem)
page = alloc_bootmem_low_pages(PAGE_SIZE);
else
page = (void *) get_zeroed_page(GFP_ATOMIC);
if (use_bootmem) {
p = __alloc_bootmem_low(size, size, 0);
} else {
struct page *page = alloc_pages(GFP_ATOMIC | __GFP_ZERO, order);
if (page)
p = page_address(page);
}
if (!page) {
if (!p) {
prom_printf("SUN4V: Error, cannot allocate mondo queue.\n");
prom_halt();
}
*pa_ptr = __pa(page);
*pa_ptr = __pa(p);
}
static void __cpuinit alloc_one_kbuf(unsigned long *pa_ptr, int use_bootmem)
static void __cpuinit alloc_one_kbuf(unsigned long *pa_ptr, unsigned long qmask, int use_bootmem)
{
void *page;
unsigned long size = PAGE_ALIGN(qmask + 1);
unsigned long order = get_order(size);
void *p = NULL;
if (use_bootmem)
page = alloc_bootmem_low_pages(PAGE_SIZE);
else
page = (void *) get_zeroed_page(GFP_ATOMIC);
if (use_bootmem) {
p = __alloc_bootmem_low(size, size, 0);
} else {
struct page *page = alloc_pages(GFP_ATOMIC | __GFP_ZERO, order);
if (page)
p = page_address(page);
}
if (!page) {
if (!p) {
prom_printf("SUN4V: Error, cannot allocate kbuf page.\n");
prom_halt();
}
*pa_ptr = __pa(page);
*pa_ptr = __pa(p);
}
static void __cpuinit init_cpu_send_mondo_info(struct trap_per_cpu *tb, int use_bootmem)
......@@ -779,12 +802,12 @@ void __cpuinit sun4v_init_mondo_queues(int use_bootmem, int cpu, int alloc, int
struct trap_per_cpu *tb = &trap_block[cpu];
if (alloc) {
alloc_one_mondo(&tb->cpu_mondo_pa, use_bootmem);
alloc_one_mondo(&tb->dev_mondo_pa, use_bootmem);
alloc_one_mondo(&tb->resum_mondo_pa, use_bootmem);
alloc_one_kbuf(&tb->resum_kernel_buf_pa, use_bootmem);
alloc_one_mondo(&tb->nonresum_mondo_pa, use_bootmem);
alloc_one_kbuf(&tb->nonresum_kernel_buf_pa, use_bootmem);
alloc_one_mondo(&tb->cpu_mondo_pa, tb->cpu_mondo_qmask, use_bootmem);
alloc_one_mondo(&tb->dev_mondo_pa, tb->dev_mondo_qmask, use_bootmem);
alloc_one_mondo(&tb->resum_mondo_pa, tb->resum_qmask, use_bootmem);
alloc_one_kbuf(&tb->resum_kernel_buf_pa, tb->resum_qmask, use_bootmem);
alloc_one_mondo(&tb->nonresum_mondo_pa, tb->nonresum_qmask, use_bootmem);
alloc_one_kbuf(&tb->nonresum_kernel_buf_pa, tb->nonresum_qmask, use_bootmem);
init_cpu_send_mondo_info(tb, use_bootmem);
}
......
......@@ -11,12 +11,12 @@
/* ITLB ** ICACHE line 2: TSB compare and TLB load */
bne,pn %xcc, tsb_miss_itlb ! Miss
mov FAULT_CODE_ITLB, %g3
andcc %g5, _PAGE_EXEC_4U, %g0 ! Executable?
sethi %hi(_PAGE_EXEC_4U), %g4
andcc %g5, %g4, %g0 ! Executable?
be,pn %xcc, tsb_do_fault
nop ! Delay slot, fill me
stxa %g5, [%g0] ASI_ITLB_DATA_IN ! Load TLB
retry ! Trap done
nop
/* ITLB ** ICACHE line 3: */
nop
......
This diff is collapsed.
......@@ -306,6 +306,20 @@ static void __init pci_controller_probe(void)
pci_controller_scan(pci_controller_init);
}
static int ofpci_verbose;
static int __init ofpci_debug(char *str)
{
int val = 0;
get_option(&str, &val);
if (val)
ofpci_verbose = 1;
return 1;
}
__setup("ofpci_debug=", ofpci_debug);
static unsigned long pci_parse_of_flags(u32 addr0)
{
unsigned long flags = 0;
......@@ -337,7 +351,9 @@ static void pci_parse_of_addrs(struct of_device *op,
addrs = of_get_property(node, "assigned-addresses", &proplen);
if (!addrs)
return;
printk(" parse addresses (%d bytes) @ %p\n", proplen, addrs);
if (ofpci_verbose)
printk(" parse addresses (%d bytes) @ %p\n",
proplen, addrs);
op_res = &op->resource[0];
for (; proplen >= 20; proplen -= 20, addrs += 5, op_res++) {
struct resource *res;
......@@ -348,8 +364,9 @@ static void pci_parse_of_addrs(struct of_device *op,
if (!flags)
continue;
i = addrs[0] & 0xff;
printk(" start: %lx, end: %lx, i: %x\n",
op_res->start, op_res->end, i);
if (ofpci_verbose)
printk(" start: %lx, end: %lx, i: %x\n",
op_res->start, op_res->end, i);
if (PCI_BASE_ADDRESS_0 <= i && i <= PCI_BASE_ADDRESS_5) {
res = &dev->resource[(i - PCI_BASE_ADDRESS_0) >> 2];
......@@ -393,8 +410,9 @@ struct pci_dev *of_create_pci_dev(struct pci_pbm_info *pbm,
if (type == NULL)
type = "";
printk(" create device, devfn: %x, type: %s hostcontroller(%d)\n",
devfn, type, host_controller);
if (ofpci_verbose)
printk(" create device, devfn: %x, type: %s\n",
devfn, type);
dev->bus = bus;
dev->sysdata = node;
......@@ -434,8 +452,9 @@ struct pci_dev *of_create_pci_dev(struct pci_pbm_info *pbm,
sprintf(pci_name(dev), "%04x:%02x:%02x.%d", pci_domain_nr(bus),
dev->bus->number, PCI_SLOT(devfn), PCI_FUNC(devfn));
}
printk(" class: 0x%x device name: %s\n",
dev->class, pci_name(dev));
if (ofpci_verbose)
printk(" class: 0x%x device name: %s\n",
dev->class, pci_name(dev));
/* I have seen IDE devices which will not respond to
* the bmdma simplex check reads if bus mastering is
......@@ -469,7 +488,8 @@ struct pci_dev *of_create_pci_dev(struct pci_pbm_info *pbm,
}
pci_parse_of_addrs(sd->op, node, dev);
printk(" adding to system ...\n");
if (ofpci_verbose)
printk(" adding to system ...\n");
pci_device_add(dev, bus);
......@@ -547,7 +567,8 @@ static void __devinit of_scan_pci_bridge(struct pci_pbm_info *pbm,
unsigned int flags;
u64 size;
printk("of_scan_pci_bridge(%s)\n", node->full_name);
if (ofpci_verbose)
printk("of_scan_pci_bridge(%s)\n", node->full_name);
/* parse bus-range property */
busrange = of_get_property(node, "bus-range", &len);
......@@ -632,7 +653,8 @@ static void __devinit of_scan_pci_bridge(struct pci_pbm_info *pbm,
simba_cont:
sprintf(bus->name, "PCI Bus %04x:%02x", pci_domain_nr(bus),
bus->number);
printk(" bus name: %s\n", bus->name);
if (ofpci_verbose)
printk(" bus name: %s\n", bus->name);
pci_of_scan_bus(pbm, node, bus);
}
......@@ -646,12 +668,14 @@ static void __devinit pci_of_scan_bus(struct pci_pbm_info *pbm,
int reglen, devfn;
struct pci_dev *dev;
printk("PCI: scan_bus[%s] bus no %d\n",
node->full_name, bus->number);
if (ofpci_verbose)
printk("PCI: scan_bus[%s] bus no %d\n",
node->full_name, bus->number);
child = NULL;
while ((child = of_get_next_child(node, child)) != NULL) {
printk(" * %s\n", child->full_name);
if (ofpci_verbose)
printk(" * %s\n", child->full_name);
reg = of_get_property(child, "reg", &reglen);
if (reg == NULL || reglen < 20)
continue;
......@@ -661,7 +685,9 @@ static void __devinit pci_of_scan_bus(struct pci_pbm_info *pbm,
dev = of_create_pci_dev(pbm, child, bus, devfn, 0);
if (!dev)
continue;
printk("PCI: dev header type: %x\n", dev->hdr_type);
if (ofpci_verbose)
printk("PCI: dev header type: %x\n",
dev->hdr_type);
if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE ||
dev->hdr_type == PCI_HEADER_TYPE_CARDBUS)
......
......@@ -762,9 +762,10 @@ void sabre_init(struct device_node *dp, char *model_name)
/* Of course, Sun has to encode things a thousand
* different ways, inconsistently.
*/
cpu_find_by_instance(0, &dp, NULL);
if (!strcmp(dp->name, "SUNW,UltraSPARC-IIe"))
hummingbird_p = 1;
for_each_node_by_type(dp, "cpu") {
if (!strcmp(dp->name, "SUNW,UltraSPARC-IIe"))
hummingbird_p = 1;
}
}
}
......
......@@ -12,6 +12,7 @@
#include <linux/percpu.h>
#include <linux/irq.h>
#include <linux/msi.h>
#include <linux/log2.h>
#include <asm/iommu.h>
#include <asm/irq.h>
......@@ -26,6 +27,9 @@
#include "pci_sun4v.h"
static unsigned long vpci_major = 1;
static unsigned long vpci_minor = 1;
#define PGLIST_NENTS (PAGE_SIZE / sizeof(u64))
struct iommu_batch {
......@@ -638,9 +642,8 @@ static void pci_sun4v_iommu_init(struct pci_pbm_info *pbm)
{
struct iommu *iommu = pbm->iommu;
struct property *prop;
unsigned long num_tsb_entries, sz;
unsigned long num_tsb_entries, sz, tsbsize;
u32 vdma[2], dma_mask, dma_offset;
int tsbsize;
prop = of_find_property(pbm->prom_node, "virtual-dma", NULL);
if (prop) {
......@@ -654,31 +657,15 @@ static void pci_sun4v_iommu_init(struct pci_pbm_info *pbm)
vdma[1] = 0x80000000;
}
dma_mask = vdma[0];
switch (vdma[1]) {
case 0x20000000:
dma_mask |= 0x1fffffff;
tsbsize = 64;
break;
case 0x40000000:
dma_mask |= 0x3fffffff;
tsbsize = 128;
break;
case 0x80000000:
dma_mask |= 0x7fffffff;
tsbsize = 256;
break;
default:
prom_printf("PCI-SUN4V: strange virtual-dma size.\n");
prom_halt();
if ((vdma[0] | vdma[1]) & ~IO_PAGE_MASK) {
prom_printf("PCI-SUN4V: strange virtual-dma[%08x:%08x].\n",
vdma[0], vdma[1]);
prom_halt();
};
tsbsize *= (8 * 1024);
num_tsb_entries = tsbsize / sizeof(iopte_t);
dma_mask = (roundup_pow_of_two(vdma[1]) - 1UL);
num_tsb_entries = vdma[1] / IO_PAGE_SIZE;
tsbsize = num_tsb_entries * sizeof(iopte_t);
dma_offset = vdma[0];
......@@ -689,7 +676,7 @@ static void pci_sun4v_iommu_init(struct pci_pbm_info *pbm)
iommu->dma_addr_mask = dma_mask;
/* Allocate and initialize the free area map. */
sz = num_tsb_entries / 8;
sz = (num_tsb_entries + 7) / 8;
sz = (sz + 7UL) & ~7UL;
iommu->arena.map = kzalloc(sz, GFP_KERNEL);
if (!iommu->arena.map) {
......@@ -1178,6 +1165,7 @@ static void pci_sun4v_pbm_init(struct pci_controller_info *p, struct device_node
void sun4v_pci_init(struct device_node *dp, char *model_name)
{
static int hvapi_negotiated = 0;
struct pci_controller_info *p;
struct pci_pbm_info *pbm;
struct iommu *iommu;
......@@ -1186,6 +1174,20 @@ void sun4v_pci_init(struct device_node *dp, char *model_name)
u32 devhandle;
int i;
if (!hvapi_negotiated++) {
int err = sun4v_hvapi_register(HV_GRP_PCI,
vpci_major,
&vpci_minor);
if (err) {
prom_printf("SUN4V_PCI: Could not register hvapi, "
"err=%d\n", err);
prom_halt();
}
printk("SUN4V_PCI: Registered hvapi major[%lu] minor[%lu]\n",
vpci_major, vpci_minor);
}
prop = of_find_property(dp, "reg", NULL);
regs = prop->value;
......
......@@ -19,6 +19,7 @@
#include <asm/prom.h>
#include <asm/of_device.h>
#include <asm/io.h>
#include <asm/sstate.h>
#include <linux/unistd.h>
......@@ -53,6 +54,7 @@ static void (*poweroff_method)(void) = machine_alt_power_off;
void machine_power_off(void)
{
sstate_poweroff();
if (!serial_console || scons_pwroff) {
#ifdef CONFIG_PCI
if (power_reg) {
......
......@@ -45,6 +45,7 @@
#include <asm/mmu_context.h>
#include <asm/unistd.h>
#include <asm/hypervisor.h>
#include <asm/sstate.h>
/* #define VERBOSE_SHOWREGS */
......@@ -106,6 +107,7 @@ extern void (*prom_keyboard)(void);
void machine_halt(void)
{
sstate_halt();
if (!serial_console && prom_palette)
prom_palette (1);
if (prom_keyboard)
......@@ -116,6 +118,7 @@ void machine_halt(void)
void machine_alt_power_off(void)
{
sstate_poweroff();
if (!serial_console && prom_palette)
prom_palette(1);
if (prom_keyboard)
......@@ -128,6 +131,7 @@ void machine_restart(char * cmd)
{
char *p;
sstate_reboot();
p = strchr (reboot_command, '\n');
if (p) *p = 0;
if (!serial_console && prom_palette)
......
......@@ -28,6 +28,7 @@
#include <asm/irq.h>
#include <asm/asi.h>
#include <asm/upa.h>
#include <asm/smp.h>
static struct device_node *allnodes;
......@@ -1665,6 +1666,150 @@ static struct device_node * __init build_tree(struct device_node *parent, phandl
return ret;
}
static const char *get_mid_prop(void)
{
return (tlb_type == spitfire ? "upa-portid" : "portid");
}
struct device_node *of_find_node_by_cpuid(int cpuid)
{
struct device_node *dp;
const char *mid_prop = get_mid_prop();
for_each_node_by_type(dp, "cpu") {
int id = of_getintprop_default(dp, mid_prop, -1);
const char *this_mid_prop = mid_prop;
if (id < 0) {
this_mid_prop = "cpuid";
id = of_getintprop_default(dp, this_mid_prop, -1);
}
if (id < 0) {
prom_printf("OF: Serious problem, cpu lacks "
"%s property", this_mid_prop);
prom_halt();
}
if (cpuid == id)
return dp;
}
return NULL;
}
static void __init of_fill_in_cpu_data(void)
{
struct device_node *dp;
const char *mid_prop = get_mid_prop();
ncpus_probed = 0;
for_each_node_by_type(dp, "cpu") {
int cpuid = of_getintprop_default(dp, mid_prop, -1);
const char *this_mid_prop = mid_prop;
struct device_node *portid_parent;
int portid = -1;
portid_parent = NULL;
if (cpuid < 0) {
this_mid_prop = "cpuid";
cpuid = of_getintprop_default(dp, this_mid_prop, -1);
if (cpuid >= 0) {
int limit = 2;
portid_parent = dp;
while (limit--) {
portid_parent = portid_parent->parent;
if (!portid_parent)
break;
portid = of_getintprop_default(portid_parent,
"portid", -1);
if (portid >= 0)
break;
}
}
}
if (cpuid < 0) {
prom_printf("OF: Serious problem, cpu lacks "
"%s property", this_mid_prop);
prom_halt();
}
ncpus_probed++;
#ifdef CONFIG_SMP
if (cpuid >= NR_CPUS)
continue;
#else
/* On uniprocessor we only want the values for the
* real physical cpu the kernel booted onto, however
* cpu_data() only has one entry at index 0.
*/
if (cpuid != real_hard_smp_processor_id())
continue;
cpuid = 0;
#endif
cpu_data(cpuid).clock_tick =
of_getintprop_default(dp, "clock-frequency", 0);
if (portid_parent) {
cpu_data(cpuid).dcache_size =
of_getintprop_default(dp, "l1-dcache-size",
16 * 1024);
cpu_data(cpuid).dcache_line_size =
of_getintprop_default(dp, "l1-dcache-line-size",
32);
cpu_data(cpuid).icache_size =
of_getintprop_default(dp, "l1-icache-size",
8 * 1024);
cpu_data(cpuid).icache_line_size =
of_getintprop_default(dp, "l1-icache-line-size",
32);
cpu_data(cpuid).ecache_size =
of_getintprop_default(dp, "l2-cache-size", 0);
cpu_data(cpuid).ecache_line_size =
of_getintprop_default(dp, "l2-cache-line-size", 0);
if (!cpu_data(cpuid).ecache_size ||
!cpu_data(cpuid).ecache_line_size) {
cpu_data(cpuid).ecache_size =
of_getintprop_default(portid_parent,
"l2-cache-size",
(4 * 1024 * 1024));
cpu_data(cpuid).ecache_line_size =
of_getintprop_default(portid_parent,
"l2-cache-line-size", 64);
}
cpu_data(cpuid).core_id = portid + 1;
} else {
cpu_data(cpuid).dcache_size =
of_getintprop_default(dp, "dcache-size", 16 * 1024);
cpu_data(cpuid).dcache_line_size =
of_getintprop_default(dp, "dcache-line-size", 32);
cpu_data(cpuid).icache_size =
of_getintprop_default(dp, "icache-size", 16 * 1024);
cpu_data(cpuid).icache_line_size =
of_getintprop_default(dp, "icache-line-size", 32);
cpu_data(cpuid).ecache_size =
of_getintprop_default(dp, "ecache-size",
(4 * 1024 * 1024));
cpu_data(cpuid).ecache_line_size =
of_getintprop_default(dp, "ecache-line-size", 64);
cpu_data(cpuid).core_id = 0;
}
#ifdef CONFIG_SMP
cpu_set(cpuid, cpu_present_map);
cpu_set(cpuid, phys_cpu_present_map);
#endif
}
smp_fill_in_sib_core_maps();
}
void __init prom_build_devicetree(void)
{
struct device_node **nextp;
......@@ -1679,4 +1824,7 @@ void __init prom_build_devicetree(void)
&nextp);
printk("PROM: Built device tree with %u bytes of memory.\n",
prom_early_allocated);
if (tlb_type != hypervisor)
of_fill_in_cpu_data();
}
......@@ -46,11 +46,17 @@
#include <asm/sections.h>
#include <asm/setup.h>
#include <asm/mmu.h>
#include <asm/ns87303.h>
#ifdef CONFIG_IP_PNP
#include <net/ipconfig.h>
#endif
/* Used to synchronize accesses to NatSemi SUPER I/O chip configure
* operations in asm/ns87303.h
*/
DEFINE_SPINLOCK(ns87303_lock);
struct screen_info screen_info = {
0, 0, /* orig-x, orig-y */
0, /* unused */
......@@ -370,8 +376,6 @@ void __init setup_arch(char **cmdline_p)
init_cur_cpu_trap(current_thread_info());
paging_init();
smp_setup_cpu_possible_map();
}
static int __init set_preferred_console(void)
......@@ -424,7 +428,7 @@ extern void mmu_info(struct seq_file *);
unsigned int dcache_parity_tl1_occurred;
unsigned int icache_parity_tl1_occurred;
static int ncpus_probed;
int ncpus_probed;
static int show_cpuinfo(struct seq_file *m, void *__unused)
{
......@@ -516,14 +520,6 @@ static int __init topology_init(void)
err = -ENOMEM;
/* Count the number of physically present processors in
* the machine, even on uniprocessor, so that /proc/cpuinfo
* output is consistent with 2.4.x
*/
ncpus_probed = 0;
while (!cpu_find_by_instance(ncpus_probed, NULL, NULL))
ncpus_probed++;
for_each_possible_cpu(i) {
struct cpu *p = kzalloc(sizeof(*p), GFP_KERNEL);
if (p) {
......
......@@ -40,6 +40,7 @@
#include <asm/tlb.h>
#include <asm/sections.h>
#include <asm/prom.h>
#include <asm/mdesc.h>
extern void calibrate_delay(void);
......@@ -75,53 +76,6 @@ void smp_bogo(struct seq_file *m)
i, cpu_data(i).clock_tick);
}
void __init smp_store_cpu_info(int id)
{
struct device_node *dp;
int def;
cpu_data(id).udelay_val = loops_per_jiffy;
cpu_find_by_mid(id, &dp);
cpu_data(id).clock_tick =
of_getintprop_default(dp, "clock-frequency", 0);
def = ((tlb_type == hypervisor) ? (8 * 1024) : (16 * 1024));
cpu_data(id).dcache_size =
of_getintprop_default(dp, "dcache-size", def);
def = 32;
cpu_data(id).dcache_line_size =
of_getintprop_default(dp, "dcache-line-size", def);
def = 16 * 1024;
cpu_data(id).icache_size =
of_getintprop_default(dp, "icache-size", def);
def = 32;
cpu_data(id).icache_line_size =
of_getintprop_default(dp, "icache-line-size", def);
def = ((tlb_type == hypervisor) ?
(3 * 1024 * 1024) :
(4 * 1024 * 1024));
cpu_data(id).ecache_size =
of_getintprop_default(dp, "ecache-size", def);
def = 64;
cpu_data(id).ecache_line_size =
of_getintprop_default(dp, "ecache-line-size", def);
printk("CPU[%d]: Caches "
"D[sz(%d):line_sz(%d)] "
"I[sz(%d):line_sz(%d)] "
"E[sz(%d):line_sz(%d)]\n",
id,
cpu_data(id).dcache_size, cpu_data(id).dcache_line_size,
cpu_data(id).icache_size, cpu_data(id).icache_line_size,
cpu_data(id).ecache_size, cpu_data(id).ecache_line_size);
}
extern void setup_sparc64_timer(void);
static volatile unsigned long callin_flag = 0;
......@@ -145,7 +99,7 @@ void __init smp_callin(void)
local_irq_enable();
calibrate_delay();
smp_store_cpu_info(cpuid);
cpu_data(cpuid).udelay_val = loops_per_jiffy;
callin_flag = 1;
__asm__ __volatile__("membar #Sync\n\t"
"flush %%g6" : : : "memory");
......@@ -340,9 +294,8 @@ static int __devinit smp_boot_one_cpu(unsigned int cpu)
prom_startcpu_cpuid(cpu, entry, cookie);
} else {
struct device_node *dp;
struct device_node *dp = of_find_node_by_cpuid(cpu);
cpu_find_by_mid(cpu, &dp);
prom_startcpu(dp->node, entry, cookie);
}
......@@ -447,7 +400,7 @@ static __inline__ void spitfire_xcall_deliver(u64 data0, u64 data1, u64 data2, c
static void cheetah_xcall_deliver(u64 data0, u64 data1, u64 data2, cpumask_t mask)
{
u64 pstate, ver;
int nack_busy_id, is_jbus;
int nack_busy_id, is_jbus, need_more;
if (cpus_empty(mask))
return;
......@@ -463,6 +416,7 @@ static void cheetah_xcall_deliver(u64 data0, u64 data1, u64 data2, cpumask_t mas
__asm__ __volatile__("rdpr %%pstate, %0" : "=r" (pstate));
retry:
need_more = 0;
__asm__ __volatile__("wrpr %0, %1, %%pstate\n\t"
: : "r" (pstate), "i" (PSTATE_IE));
......@@ -491,6 +445,10 @@ static void cheetah_xcall_deliver(u64 data0, u64 data1, u64 data2, cpumask_t mas
: /* no outputs */
: "r" (target), "i" (ASI_INTR_W));
nack_busy_id++;
if (nack_busy_id == 32) {
need_more = 1;
break;
}
}
}
......@@ -507,6 +465,16 @@ static void cheetah_xcall_deliver(u64 data0, u64 data1, u64 data2, cpumask_t mas
if (dispatch_stat == 0UL) {
__asm__ __volatile__("wrpr %0, 0x0, %%pstate"
: : "r" (pstate));
if (unlikely(need_more)) {
int i, cnt = 0;
for_each_cpu_mask(i, mask) {
cpu_clear(i, mask);
cnt++;
if (cnt == 32)
break;
}
goto retry;
}
return;
}
if (!--stuck)
......@@ -544,6 +512,8 @@ static void cheetah_xcall_deliver(u64 data0, u64 data1, u64 data2, cpumask_t mas
if ((dispatch_stat & check_mask) == 0)
cpu_clear(i, mask);
this_busy_nack += 2;
if (this_busy_nack == 64)
break;
}
goto retry;
......@@ -1191,23 +1161,14 @@ int setup_profiling_timer(unsigned int multiplier)
static void __init smp_tune_scheduling(void)
{
struct device_node *dp;
int instance;
unsigned int def, smallest = ~0U;
def = ((tlb_type == hypervisor) ?
(3 * 1024 * 1024) :
(4 * 1024 * 1024));
unsigned int smallest = ~0U;
int i;
instance = 0;
while (!cpu_find_by_instance(instance, &dp, NULL)) {
unsigned int val;
for (i = 0; i < NR_CPUS; i++) {
unsigned int val = cpu_data(i).ecache_size;
val = of_getintprop_default(dp, "ecache-size", def);
if (val < smallest)
if (val && val < smallest)
smallest = val;
instance++;
}
/* Any value less than 256K is nonsense. */
......@@ -1230,58 +1191,42 @@ void __init smp_prepare_cpus(unsigned int max_cpus)
int i;
if (num_possible_cpus() > max_cpus) {
int instance, mid;
instance = 0;
while (!cpu_find_by_instance(instance, NULL, &mid)) {
if (mid != boot_cpu_id) {
cpu_clear(mid, phys_cpu_present_map);
cpu_clear(mid, cpu_present_map);
for_each_possible_cpu(i) {
if (i != boot_cpu_id) {
cpu_clear(i, phys_cpu_present_map);
cpu_clear(i, cpu_present_map);
if (num_possible_cpus() <= max_cpus)
break;
}
instance++;
}
}
for_each_possible_cpu(i) {
if (tlb_type == hypervisor) {
int j;
/* XXX get this mapping from machine description */
for_each_possible_cpu(j) {
if ((j >> 2) == (i >> 2))
cpu_set(j, cpu_sibling_map[i]);
}
} else {
cpu_set(i, cpu_sibling_map[i]);
}
}
smp_store_cpu_info(boot_cpu_id);
cpu_data(boot_cpu_id).udelay_val = loops_per_jiffy;
smp_tune_scheduling();
}
/* Set this up early so that things like the scheduler can init
* properly. We use the same cpu mask for both the present and
* possible cpu map.
*/
void __init smp_setup_cpu_possible_map(void)
void __devinit smp_prepare_boot_cpu(void)
{
int instance, mid;
instance = 0;
while (!cpu_find_by_instance(instance, NULL, &mid)) {
if (mid < NR_CPUS) {
cpu_set(mid, phys_cpu_present_map);
cpu_set(mid, cpu_present_map);
}
instance++;
}
}
void __devinit smp_prepare_boot_cpu(void)
void __devinit smp_fill_in_sib_core_maps(void)
{
unsigned int i;
for_each_possible_cpu(i) {
unsigned int j;
if (cpu_data(i).core_id == 0) {
cpu_set(i, cpu_sibling_map[i]);
continue;
}
for_each_possible_cpu(j) {
if (cpu_data(i).core_id ==
cpu_data(j).core_id)
cpu_set(j, cpu_sibling_map[i]);
}
}
}
int __cpuinit __cpu_up(unsigned int cpu)
......@@ -1337,7 +1282,7 @@ unsigned long __per_cpu_shift __read_mostly;
EXPORT_SYMBOL(__per_cpu_base);
EXPORT_SYMBOL(__per_cpu_shift);
void __init setup_per_cpu_areas(void)
void __init real_setup_per_cpu_areas(void)
{
unsigned long goal, size, i;
char *ptr;
......
/* sstate.c: System soft state support.
*
* Copyright (C) 2007 David S. Miller <davem@davemloft.net>
*/
#include <linux/kernel.h>
#include <linux/notifier.h>
#include <linux/init.h>
#include <asm/hypervisor.h>
#include <asm/sstate.h>
#include <asm/oplib.h>
#include <asm/head.h>
#include <asm/io.h>
static int hv_supports_soft_state;
static unsigned long kimage_addr_to_ra(const char *p)
{
unsigned long val = (unsigned long) p;
return kern_base + (val - KERNBASE);
}
static void do_set_sstate(unsigned long state, const char *msg)
{
unsigned long err;
if (!hv_supports_soft_state)
return;
err = sun4v_mach_set_soft_state(state, kimage_addr_to_ra(msg));
if (err) {
printk(KERN_WARNING "SSTATE: Failed to set soft-state to "
"state[%lx] msg[%s], err=%lu\n",
state, msg, err);
}
}
static const char booting_msg[32] __attribute__((aligned(32))) =
"Linux booting";
static const char running_msg[32] __attribute__((aligned(32))) =
"Linux running";
static const char halting_msg[32] __attribute__((aligned(32))) =
"Linux halting";
static const char poweroff_msg[32] __attribute__((aligned(32))) =
"Linux powering off";
static const char rebooting_msg[32] __attribute__((aligned(32))) =
"Linux rebooting";
static const char panicing_msg[32] __attribute__((aligned(32))) =
"Linux panicing";
void sstate_booting(void)
{
do_set_sstate(HV_SOFT_STATE_TRANSITION, booting_msg);
}
void sstate_running(void)
{
do_set_sstate(HV_SOFT_STATE_NORMAL, running_msg);
}
void sstate_halt(void)
{
do_set_sstate(HV_SOFT_STATE_TRANSITION, halting_msg);
}
void sstate_poweroff(void)
{
do_set_sstate(HV_SOFT_STATE_TRANSITION, poweroff_msg);
}
void sstate_reboot(void)
{
do_set_sstate(HV_SOFT_STATE_TRANSITION, rebooting_msg);
}
static int sstate_panic_event(struct notifier_block *n, unsigned long event, void *ptr)
{
do_set_sstate(HV_SOFT_STATE_TRANSITION, panicing_msg);
return NOTIFY_DONE;
}
static struct notifier_block sstate_panic_block = {
.notifier_call = sstate_panic_event,
.priority = INT_MAX,
};
void __init sun4v_sstate_init(void)
{
unsigned long major, minor;
major = 1;
minor = 0;
if (sun4v_hvapi_register(HV_GRP_SOFT_STATE, major, &minor))
return;
hv_supports_soft_state = 1;
prom_sun4v_guest_soft_state();
atomic_notifier_chain_register(&panic_notifier_list,
&sstate_panic_block);
}
......@@ -22,12 +22,12 @@ sun4v_cpu_mondo:
be,pn %xcc, sun4v_cpu_mondo_queue_empty
nop
/* Get &trap_block[smp_processor_id()] into %g3. */
ldxa [%g0] ASI_SCRATCHPAD, %g3
sub %g3, TRAP_PER_CPU_FAULT_INFO, %g3
/* Get &trap_block[smp_processor_id()] into %g4. */
ldxa [%g0] ASI_SCRATCHPAD, %g4
sub %g4, TRAP_PER_CPU_FAULT_INFO, %g4
/* Get CPU mondo queue base phys address into %g7. */
ldx [%g3 + TRAP_PER_CPU_CPU_MONDO_PA], %g7
ldx [%g4 + TRAP_PER_CPU_CPU_MONDO_PA], %g7
/* Now get the cross-call arguments and handler PC, same
* layout as sun4u:
......@@ -47,8 +47,7 @@ sun4v_cpu_mondo:
add %g2, 0x40 - 0x8 - 0x8, %g2
/* Update queue head pointer. */
sethi %hi(8192 - 1), %g4
or %g4, %lo(8192 - 1), %g4
lduw [%g4 + TRAP_PER_CPU_CPU_MONDO_QMASK], %g4
and %g2, %g4, %g2
mov INTRQ_CPU_MONDO_HEAD, %g4
......@@ -71,12 +70,12 @@ sun4v_dev_mondo:
be,pn %xcc, sun4v_dev_mondo_queue_empty
nop
/* Get &trap_block[smp_processor_id()] into %g3. */
ldxa [%g0] ASI_SCRATCHPAD, %g3
sub %g3, TRAP_PER_CPU_FAULT_INFO, %g3
/* Get &trap_block[smp_processor_id()] into %g4. */
ldxa [%g0] ASI_SCRATCHPAD, %g4
sub %g4, TRAP_PER_CPU_FAULT_INFO, %g4
/* Get DEV mondo queue base phys address into %g5. */
ldx [%g3 + TRAP_PER_CPU_DEV_MONDO_PA], %g5
ldx [%g4 + TRAP_PER_CPU_DEV_MONDO_PA], %g5
/* Load IVEC into %g3. */
ldxa [%g5 + %g2] ASI_PHYS_USE_EC, %g3
......@@ -90,8 +89,7 @@ sun4v_dev_mondo:
*/
/* Update queue head pointer, this frees up some registers. */
sethi %hi(8192 - 1), %g4
or %g4, %lo(8192 - 1), %g4
lduw [%g4 + TRAP_PER_CPU_DEV_MONDO_QMASK], %g4
and %g2, %g4, %g2
mov INTRQ_DEVICE_MONDO_HEAD, %g4
......@@ -143,6 +141,8 @@ sun4v_res_mondo:
brnz,pn %g1, sun4v_res_mondo_queue_full
nop
lduw [%g3 + TRAP_PER_CPU_RESUM_QMASK], %g4
/* Remember this entry's offset in %g1. */
mov %g2, %g1
......@@ -173,8 +173,6 @@ sun4v_res_mondo:
add %g2, 0x08, %g2
/* Update queue head pointer. */
sethi %hi(8192 - 1), %g4
or %g4, %lo(8192 - 1), %g4
and %g2, %g4, %g2
mov INTRQ_RESUM_MONDO_HEAD, %g4
......@@ -254,6 +252,8 @@ sun4v_nonres_mondo:
brnz,pn %g1, sun4v_nonres_mondo_queue_full
nop
lduw [%g3 + TRAP_PER_CPU_NONRESUM_QMASK], %g4
/* Remember this entry's offset in %g1. */
mov %g2, %g1
......@@ -284,8 +284,6 @@ sun4v_nonres_mondo:
add %g2, 0x08, %g2
/* Update queue head pointer. */
sethi %hi(8192 - 1), %g4
or %g4, %lo(8192 - 1), %g4
and %g2, %g4, %g2
mov INTRQ_NONRESUM_MONDO_HEAD, %g4
......
......@@ -680,22 +680,14 @@ static int starfire_set_time(u32 val)
static u32 hypervisor_get_time(void)
{
register unsigned long func asm("%o5");
register unsigned long arg0 asm("%o0");
register unsigned long arg1 asm("%o1");
unsigned long ret, time;
int retries = 10000;
retry:
func = HV_FAST_TOD_GET;
arg0 = 0;
arg1 = 0;
__asm__ __volatile__("ta %6"
: "=&r" (func), "=&r" (arg0), "=&r" (arg1)
: "0" (func), "1" (arg0), "2" (arg1),
"i" (HV_FAST_TRAP));
if (arg0 == HV_EOK)
return arg1;
if (arg0 == HV_EWOULDBLOCK) {
ret = sun4v_tod_get(&time);
if (ret == HV_EOK)
return time;
if (ret == HV_EWOULDBLOCK) {
if (--retries > 0) {
udelay(100);
goto retry;
......@@ -709,20 +701,14 @@ static u32 hypervisor_get_time(void)
static int hypervisor_set_time(u32 secs)
{
register unsigned long func asm("%o5");
register unsigned long arg0 asm("%o0");
unsigned long ret;
int retries = 10000;
retry:
func = HV_FAST_TOD_SET;
arg0 = secs;
__asm__ __volatile__("ta %4"
: "=&r" (func), "=&r" (arg0)
: "0" (func), "1" (arg0),
"i" (HV_FAST_TRAP));
if (arg0 == HV_EOK)
ret = sun4v_tod_set(secs);
if (ret == HV_EOK)
return 0;
if (arg0 == HV_EWOULDBLOCK) {
if (ret == HV_EWOULDBLOCK) {
if (--retries > 0) {
udelay(100);
goto retry;
......@@ -862,7 +848,6 @@ fs_initcall(clock_init);
static unsigned long sparc64_init_timers(void)
{
struct device_node *dp;
struct property *prop;
unsigned long clock;
#ifdef CONFIG_SMP
extern void smp_tick_init(void);
......@@ -879,17 +864,15 @@ static unsigned long sparc64_init_timers(void)
if (manuf == 0x17 && impl == 0x13) {
/* Hummingbird, aka Ultra-IIe */
tick_ops = &hbtick_operations;
prop = of_find_property(dp, "stick-frequency", NULL);
clock = of_getintprop_default(dp, "stick-frequency", 0);
} else {
tick_ops = &tick_operations;
cpu_find_by_instance(0, &dp, NULL);
prop = of_find_property(dp, "clock-frequency", NULL);
clock = local_cpu_data().clock_tick;
}
} else {
tick_ops = &stick_operations;
prop = of_find_property(dp, "stick-frequency", NULL);
clock = of_getintprop_default(dp, "stick-frequency", 0);
}
clock = *(unsigned int *) prop->value;
#ifdef CONFIG_SMP
smp_tick_init();
......@@ -1365,6 +1348,7 @@ static int hypervisor_set_rtc_time(struct rtc_time *time)
return hypervisor_set_time(seconds);
}
#ifdef CONFIG_PCI
static void bq4802_get_rtc_time(struct rtc_time *time)
{
unsigned char val = readb(bq4802_regs + 0x0e);
......@@ -1436,6 +1420,7 @@ static int bq4802_set_rtc_time(struct rtc_time *time)
return 0;
}
#endif /* CONFIG_PCI */
struct mini_rtc_ops {
void (*get_rtc_time)(struct rtc_time *);
......@@ -1452,10 +1437,12 @@ static struct mini_rtc_ops hypervisor_rtc_ops = {
.set_rtc_time = hypervisor_set_rtc_time,
};
#ifdef CONFIG_PCI
static struct mini_rtc_ops bq4802_rtc_ops = {
.get_rtc_time = bq4802_get_rtc_time,
.set_rtc_time = bq4802_set_rtc_time,
};
#endif /* CONFIG_PCI */
static struct mini_rtc_ops *mini_rtc_ops;
......@@ -1579,8 +1566,10 @@ static int __init rtc_mini_init(void)
mini_rtc_ops = &hypervisor_rtc_ops;
else if (this_is_starfire)
mini_rtc_ops = &starfire_rtc_ops;
#ifdef CONFIG_PCI
else if (bq4802_regs)
mini_rtc_ops = &bq4802_rtc_ops;
#endif /* CONFIG_PCI */
else
return -ENODEV;
......
......@@ -795,8 +795,7 @@ extern unsigned int cheetah_deferred_trap_vector[], cheetah_deferred_trap_vector
void __init cheetah_ecache_flush_init(void)
{
unsigned long largest_size, smallest_linesize, order, ver;
struct device_node *dp;
int i, instance, sz;
int i, sz;
/* Scan all cpu device tree nodes, note two values:
* 1) largest E-cache size
......@@ -805,18 +804,20 @@ void __init cheetah_ecache_flush_init(void)
largest_size = 0UL;
smallest_linesize = ~0UL;
instance = 0;
while (!cpu_find_by_instance(instance, &dp, NULL)) {
for (i = 0; i < NR_CPUS; i++) {
unsigned long val;
val = of_getintprop_default(dp, "ecache-size",
(2 * 1024 * 1024));
val = cpu_data(i).ecache_size;
if (!val)
continue;
if (val > largest_size)
largest_size = val;
val = of_getintprop_default(dp, "ecache-line-size", 64);
val = cpu_data(i).ecache_line_size;
if (val < smallest_linesize)
smallest_linesize = val;
instance++;
}
if (largest_size == 0UL || smallest_linesize == ~0UL) {
......@@ -2564,7 +2565,15 @@ void __init trap_init(void)
(TRAP_PER_CPU_TSB_HUGE_TEMP !=
offsetof(struct trap_per_cpu, tsb_huge_temp)) ||
(TRAP_PER_CPU_IRQ_WORKLIST !=
offsetof(struct trap_per_cpu, irq_worklist)))
offsetof(struct trap_per_cpu, irq_worklist)) ||
(TRAP_PER_CPU_CPU_MONDO_QMASK !=
offsetof(struct trap_per_cpu, cpu_mondo_qmask)) ||
(TRAP_PER_CPU_DEV_MONDO_QMASK !=
offsetof(struct trap_per_cpu, dev_mondo_qmask)) ||
(TRAP_PER_CPU_RESUM_QMASK !=
offsetof(struct trap_per_cpu, resum_qmask)) ||
(TRAP_PER_CPU_NONRESUM_QMASK !=
offsetof(struct trap_per_cpu, nonresum_qmask)))
trap_per_cpu_offsets_are_bolixed_dave();
if ((TSB_CONFIG_TSB !=
......
......@@ -23,6 +23,7 @@
#include <linux/kprobes.h>
#include <linux/cache.h>
#include <linux/sort.h>
#include <linux/percpu.h>
#include <asm/head.h>
#include <asm/system.h>
......@@ -43,8 +44,8 @@
#include <asm/tsb.h>
#include <asm/hypervisor.h>
#include <asm/prom.h>
extern void device_scan(void);
#include <asm/sstate.h>
#include <asm/mdesc.h>
#define MAX_PHYS_ADDRESS (1UL << 42UL)
#define KPTE_BITMAP_CHUNK_SZ (256UL * 1024UL * 1024UL)
......@@ -60,8 +61,11 @@ unsigned long kern_linear_pte_xor[2] __read_mostly;
unsigned long kpte_linear_bitmap[KPTE_BITMAP_BYTES / sizeof(unsigned long)];
#ifndef CONFIG_DEBUG_PAGEALLOC
/* A special kernel TSB for 4MB and 256MB linear mappings. */
struct tsb swapper_4m_tsb[KERNEL_TSB4M_NENTRIES];
/* A special kernel TSB for 4MB and 256MB linear mappings.
* Space is allocated for this right after the trap table
* in arch/sparc64/kernel/head.S
*/
extern struct tsb swapper_4m_tsb[KERNEL_TSB4M_NENTRIES];
#endif
#define MAX_BANKS 32
......@@ -190,12 +194,9 @@ inline void flush_dcache_page_impl(struct page *page)
}
#define PG_dcache_dirty PG_arch_1
#define PG_dcache_cpu_shift 24UL
#define PG_dcache_cpu_mask (256UL - 1UL)
#if NR_CPUS > 256
#error D-cache dirty tracking and thread_info->cpu need fixing for > 256 cpus
#endif
#define PG_dcache_cpu_shift 32UL
#define PG_dcache_cpu_mask \
((1UL<<ilog2(roundup_pow_of_two(NR_CPUS)))-1UL)
#define dcache_dirty_cpu(page) \
(((page)->flags >> PG_dcache_cpu_shift) & PG_dcache_cpu_mask)
......@@ -557,26 +558,11 @@ static void __init hypervisor_tlb_lock(unsigned long vaddr,
unsigned long pte,
unsigned long mmu)
{
register unsigned long func asm("%o5");
register unsigned long arg0 asm("%o0");
register unsigned long arg1 asm("%o1");
register unsigned long arg2 asm("%o2");
register unsigned long arg3 asm("%o3");
func = HV_FAST_MMU_MAP_PERM_ADDR;
arg0 = vaddr;
arg1 = 0;
arg2 = pte;
arg3 = mmu;
__asm__ __volatile__("ta 0x80"
: "=&r" (func), "=&r" (arg0),
"=&r" (arg1), "=&r" (arg2),
"=&r" (arg3)
: "0" (func), "1" (arg0), "2" (arg1),
"3" (arg2), "4" (arg3));
if (arg0 != 0) {
unsigned long ret = sun4v_mmu_map_perm_addr(vaddr, 0, pte, mmu);
if (ret != 0) {
prom_printf("hypervisor_tlb_lock[%lx:%lx:%lx:%lx]: "
"errors with %lx\n", vaddr, 0, pte, mmu, arg0);
"errors with %lx\n", vaddr, 0, pte, mmu, ret);
prom_halt();
}
}
......@@ -1313,20 +1299,16 @@ static void __init sun4v_ktsb_init(void)
void __cpuinit sun4v_ktsb_register(void)
{
register unsigned long func asm("%o5");
register unsigned long arg0 asm("%o0");
register unsigned long arg1 asm("%o1");
unsigned long pa;
unsigned long pa, ret;
pa = kern_base + ((unsigned long)&ktsb_descr[0] - KERNBASE);
func = HV_FAST_MMU_TSB_CTX0;
arg0 = NUM_KTSB_DESCR;
arg1 = pa;
__asm__ __volatile__("ta %6"
: "=&r" (func), "=&r" (arg0), "=&r" (arg1)
: "0" (func), "1" (arg0), "2" (arg1),
"i" (HV_FAST_TRAP));
ret = sun4v_mmu_tsb_ctx0(NUM_KTSB_DESCR, pa);
if (ret != 0) {
prom_printf("hypervisor_mmu_tsb_ctx0[%lx]: "
"errors with %lx\n", pa, ret);
prom_halt();
}
}
/* paging_init() sets up the page tables */
......@@ -1334,6 +1316,9 @@ void __cpuinit sun4v_ktsb_register(void)
extern void cheetah_ecache_flush_init(void);
extern void sun4v_patch_tlb_handlers(void);
extern void cpu_probe(void);
extern void central_probe(void);
static unsigned long last_valid_pfn;
pgd_t swapper_pg_dir[2048];
......@@ -1345,9 +1330,24 @@ void __init paging_init(void)
unsigned long end_pfn, pages_avail, shift, phys_base;
unsigned long real_end, i;
/* These build time checkes make sure that the dcache_dirty_cpu()
* page->flags usage will work.
*
* When a page gets marked as dcache-dirty, we store the
* cpu number starting at bit 32 in the page->flags. Also,
* functions like clear_dcache_dirty_cpu use the cpu mask
* in 13-bit signed-immediate instruction fields.
*/
BUILD_BUG_ON(FLAGS_RESERVED != 32);
BUILD_BUG_ON(SECTIONS_WIDTH + NODES_WIDTH + ZONES_WIDTH +
ilog2(roundup_pow_of_two(NR_CPUS)) > FLAGS_RESERVED);
BUILD_BUG_ON(NR_CPUS > 4096);
kern_base = (prom_boot_mapping_phys_low >> 22UL) << 22UL;
kern_size = (unsigned long)&_end - (unsigned long)KERNBASE;
sstate_booting();
/* Invalidate both kernel TSBs. */
memset(swapper_tsb, 0x40, sizeof(swapper_tsb));
#ifndef CONFIG_DEBUG_PAGEALLOC
......@@ -1416,8 +1416,13 @@ void __init paging_init(void)
kernel_physical_mapping_init();
real_setup_per_cpu_areas();
prom_build_devicetree();
if (tlb_type == hypervisor)
sun4v_mdesc_init();
{
unsigned long zones_size[MAX_NR_ZONES];
unsigned long zholes_size[MAX_NR_ZONES];
......@@ -1434,7 +1439,10 @@ void __init paging_init(void)
zholes_size);
}
device_scan();
prom_printf("Booting Linux...\n");
central_probe();
cpu_probe();
}
static void __init taint_real_pages(void)
......
......@@ -15,6 +15,25 @@
#include <asm/oplib.h>
#include <asm/system.h>
int prom_service_exists(const char *service_name)
{
int err = p1275_cmd("test", P1275_ARG(0, P1275_ARG_IN_STRING) |
P1275_INOUT(1, 1), service_name);
if (err)
return 0;
return 1;
}
void prom_sun4v_guest_soft_state(void)
{
const char *svc = "SUNW,soft-state-supported";
if (!prom_service_exists(svc))
return;
p1275_cmd(svc, P1275_INOUT(0, 0));
}
/* Reset and reboot the machine with the command 'bcommand'. */
void prom_reboot(const char *bcommand)
{
......
......@@ -6,7 +6,7 @@
#
config DRM
tristate "Direct Rendering Manager (XFree86 4.1.0 and higher DRI support)"
depends on (AGP || AGP=n) && PCI
depends on (AGP || AGP=n) && PCI && !EMULATED_CMPXCHG
help
Kernel-level support for the Direct Rendering Infrastructure (DRI)
introduced in XFree86 4.0. If you say Y here, you need to select
......
......@@ -1753,23 +1753,9 @@ config SUN3X_ESP
The ESP was an on-board SCSI controller used on Sun 3/80
machines. Say Y here to compile in support for it.
config SCSI_ESP_CORE
tristate "ESP Scsi Driver Core"
depends on SCSI
select SCSI_SPI_ATTRS
help
This is a core driver for NCR53c9x based scsi chipsets,
also known as "ESP" for Emulex Scsi Processor or
Enhanced Scsi Processor. This driver does not exist by
itself, there are front-end drivers which, when enabled,
select and enable this driver. One example is SCSI_SUNESP.
These front-end drivers provide probing, DMA, and register
access support for the core driver.
config SCSI_SUNESP
tristate "Sparc ESP Scsi Driver"
depends on SBUS && SCSI
select SCSI_ESP_CORE
help
This is the driver for the Sun ESP SCSI host adapter. The ESP
chipset is present in most SPARC SBUS-based computers.
......
......@@ -106,8 +106,7 @@ obj-$(CONFIG_MEGARAID_LEGACY) += megaraid.o
obj-$(CONFIG_MEGARAID_NEWGEN) += megaraid/
obj-$(CONFIG_MEGARAID_SAS) += megaraid/
obj-$(CONFIG_SCSI_ACARD) += atp870u.o
obj-$(CONFIG_SCSI_ESP_CORE) += esp_scsi.o
obj-$(CONFIG_SCSI_SUNESP) += sun_esp.o
obj-$(CONFIG_SCSI_SUNESP) += esp_scsi.o sun_esp.o
obj-$(CONFIG_SCSI_GDTH) += gdth.o
obj-$(CONFIG_SCSI_INITIO) += initio.o
obj-$(CONFIG_SCSI_INIA100) += a100u2w.o
......@@ -121,7 +120,7 @@ obj-$(CONFIG_BLK_DEV_3W_XXXX_RAID) += 3w-xxxx.o
obj-$(CONFIG_SCSI_3W_9XXX) += 3w-9xxx.o
obj-$(CONFIG_SCSI_PPA) += ppa.o
obj-$(CONFIG_SCSI_IMM) += imm.o
obj-$(CONFIG_JAZZ_ESP) += NCR53C9x.o jazz_esp.o
obj-$(CONFIG_JAZZ_ESP) += esp_scsi.o jazz_esp.o
obj-$(CONFIG_SUN3X_ESP) += NCR53C9x.o sun3x_esp.o
obj-$(CONFIG_SCSI_FCAL) += fcal.o
obj-$(CONFIG_SCSI_LASI700) += 53c700.o lasi700.o
......
This diff is collapsed.
......@@ -4,6 +4,7 @@
*
*/
#include <linux/completion.h>
#include <linux/kernel.h>
#include <linux/delay.h>
#include <linux/types.h>
......@@ -50,16 +51,10 @@ static struct ctrl_inquiry {
} *fcs __initdata;
static int fcscount __initdata = 0;
static atomic_t fcss __initdata = ATOMIC_INIT(0);
DECLARE_MUTEX_LOCKED(fc_sem);
static DECLARE_COMPLETION(fc_detect_complete);
static int pluto_encode_addr(Scsi_Cmnd *SCpnt, u16 *addr, fc_channel *fc, fcp_cmnd *fcmd);
static void __init pluto_detect_timeout(unsigned long data)
{
PLND(("Timeout\n"))
up(&fc_sem);
}
static void __init pluto_detect_done(Scsi_Cmnd *SCpnt)
{
/* Do nothing */
......@@ -69,7 +64,7 @@ static void __init pluto_detect_scsi_done(Scsi_Cmnd *SCpnt)
{
PLND(("Detect done %08lx\n", (long)SCpnt))
if (atomic_dec_and_test (&fcss))
up(&fc_sem);
complete(&fc_detect_complete);
}
int pluto_slave_configure(struct scsi_device *device)
......@@ -96,7 +91,6 @@ int __init pluto_detect(struct scsi_host_template *tpnt)
int i, retry, nplutos;
fc_channel *fc;
struct scsi_device dev;
DEFINE_TIMER(fc_timer, pluto_detect_timeout, 0, 0);
tpnt->proc_name = "pluto";
fcscount = 0;
......@@ -187,15 +181,11 @@ int __init pluto_detect(struct scsi_host_template *tpnt)
}
}
fc_timer.expires = jiffies + 10 * HZ;
add_timer(&fc_timer);
down(&fc_sem);
wait_for_completion_timeout(&fc_detect_complete, 10 * HZ);
PLND(("Woken up\n"))
if (!atomic_read(&fcss))
break; /* All fc channels have answered us */
}
del_timer_sync(&fc_timer);
PLND(("Finished search\n"))
for (i = 0, nplutos = 0; i < fcscount; i++) {
......
......@@ -30,9 +30,9 @@ void
sunserial_console_termios(struct console *con)
{
char mode[16], buf[16], *s;
char *mode_prop = "ttyX-mode";
char *cd_prop = "ttyX-ignore-cd";
char *dtr_prop = "ttyX-rts-dtr-off";
char mode_prop[] = "ttyX-mode";
char cd_prop[] = "ttyX-ignore-cd";
char dtr_prop[] = "ttyX-rts-dtr-off";
char *ssp_console_modes_prop = "ssp-console-modes";
int baud, bits, stop, cflag;
char parity;
......
......@@ -1239,7 +1239,7 @@ static inline struct console *SUNZILOG_CONSOLE(void)
#define SUNZILOG_CONSOLE() (NULL)
#endif
static void __init sunzilog_init_kbdms(struct uart_sunzilog_port *up, int channel)
static void __devinit sunzilog_init_kbdms(struct uart_sunzilog_port *up, int channel)
{
int baud, brg;
......@@ -1259,7 +1259,7 @@ static void __init sunzilog_init_kbdms(struct uart_sunzilog_port *up, int channe
}
#ifdef CONFIG_SERIO
static void __init sunzilog_register_serio(struct uart_sunzilog_port *up)
static void __devinit sunzilog_register_serio(struct uart_sunzilog_port *up)
{
struct serio *serio = &up->serio;
......
......@@ -2,6 +2,7 @@
*
* Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
* Copyright (C) 2000 Anton Blanchard (anton@linuxcare.com.au)
* Copyright (C) 2007 Kyle McMartin (kyle@parisc-linux.org)
*
* Additions by Keith M Wesolowski (wesolows@foobazco.org) based
* on asm-parisc/atomic.h Copyright (C) 2000 Philipp Rumpf <prumpf@tux.org>.
......@@ -10,11 +11,48 @@
#ifndef __ARCH_SPARC_ATOMIC__
#define __ARCH_SPARC_ATOMIC__
#include <linux/types.h>
typedef struct { volatile int counter; } atomic_t;
#ifdef __KERNEL__
/* Emulate cmpxchg() the same way we emulate atomics,
* by hashing the object address and indexing into an array
* of spinlocks to get a bit of performance...
*
* See arch/sparc/lib/atomic32.c for implementation.
*
* Cribbed from <asm-parisc/atomic.h>
*/
#define __HAVE_ARCH_CMPXCHG 1
/* bug catcher for when unsupported size is used - won't link */
extern void __cmpxchg_called_with_bad_pointer(void);
/* we only need to support cmpxchg of a u32 on sparc */
extern unsigned long __cmpxchg_u32(volatile u32 *m, u32 old, u32 new_);
/* don't worry...optimizer will get rid of most of this */
static __inline__ unsigned long
__cmpxchg(volatile void *ptr, unsigned long old, unsigned long new_, int size)
{
switch(size) {
case 4:
return __cmpxchg_u32((u32 *)ptr, (u32)old, (u32)new_);
default:
__cmpxchg_called_with_bad_pointer();
break;
}
return old;
}
#define cmpxchg(ptr,o,n) ({ \
__typeof__(*(ptr)) _o_ = (o); \
__typeof__(*(ptr)) _n_ = (n); \
(__typeof__(*(ptr))) __cmpxchg((ptr), (unsigned long)_o_, \
(unsigned long)_n_, sizeof(*(ptr))); \
})
#define ATOMIC_INIT(i) { (i) }
extern int __atomic_add_return(int, atomic_t *);
......
/* $Id: bugs.h,v 1.1 1996/12/26 13:25:20 davem Exp $
* include/asm-sparc64/bugs.h: Sparc probes for various bugs.
/* bugs.h: Sparc64 probes for various bugs.
*
* Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
* Copyright (C) 1996, 2007 David S. Miller (davem@davemloft.net)
*/
#include <asm/sstate.h>
extern unsigned long loops_per_jiffy;
......@@ -12,4 +11,5 @@ static void __init check_bugs(void)
#ifndef CONFIG_SMP
cpu_data(0).udelay_val = loops_per_jiffy;
#endif
sstate_running();
}
......@@ -17,11 +17,11 @@
typedef struct {
/* Dcache line 1 */
unsigned int __softirq_pending; /* must be 1st, see rtrap.S */
unsigned int __pad0_1;
unsigned int __pad0_2;
unsigned int __pad1;
unsigned int __pad0;
unsigned long clock_tick; /* %tick's per second */
unsigned long udelay_val;
unsigned int __pad1;
unsigned int __pad2;
/* Dcache line 2, rarely used */
unsigned int dcache_size;
......@@ -30,8 +30,8 @@ typedef struct {
unsigned int icache_line_size;
unsigned int ecache_size;
unsigned int ecache_line_size;
int core_id;
unsigned int __pad3;
unsigned int __pad4;
} cpuinfo_sparc;
DECLARE_PER_CPU(cpuinfo_sparc, __cpu_data);
......@@ -76,12 +76,18 @@ struct trap_per_cpu {
/* Dcache line 8: IRQ work list, and keep trap_block a power-of-2 in size. */
unsigned int irq_worklist;
unsigned int __pad1;
unsigned long __pad2[3];
unsigned int cpu_mondo_qmask;
unsigned int dev_mondo_qmask;
unsigned int resum_qmask;
unsigned int nonresum_qmask;
unsigned int __pad2[3];
} __attribute__((aligned(64)));
extern struct trap_per_cpu trap_block[NR_CPUS];
extern void init_cur_cpu_trap(struct thread_info *);
extern void setup_tba(void);
extern int ncpus_probed;
extern unsigned long real_hard_smp_processor_id(void);
struct cpuid_patch_entry {
unsigned int addr;
......@@ -122,6 +128,10 @@ extern struct sun4v_2insn_patch_entry __sun4v_2insn_patch,
#define TRAP_PER_CPU_TSB_HUGE 0xd0
#define TRAP_PER_CPU_TSB_HUGE_TEMP 0xd8
#define TRAP_PER_CPU_IRQ_WORKLIST 0xe0
#define TRAP_PER_CPU_CPU_MONDO_QMASK 0xe4
#define TRAP_PER_CPU_DEV_MONDO_QMASK 0xe8
#define TRAP_PER_CPU_RESUM_QMASK 0xec
#define TRAP_PER_CPU_NONRESUM_QMASK 0xf0
#define TRAP_BLOCK_SZ_SHIFT 8
......@@ -192,7 +202,7 @@ extern struct sun4v_2insn_patch_entry __sun4v_2insn_patch,
* the calculations done by the macro mid-stream.
*/
#define LOAD_PER_CPU_BASE(DEST, THR, REG1, REG2, REG3) \
ldub [THR + TI_CPU], REG1; \
lduh [THR + TI_CPU], REG1; \
sethi %hi(__per_cpu_shift), REG3; \
sethi %hi(__per_cpu_base), REG2; \
ldx [REG3 + %lo(__per_cpu_shift)], REG3; \
......
This diff is collapsed.
......@@ -32,7 +32,6 @@ enum die_val {
DIE_TRAP,
DIE_TRAP_TL1,
DIE_CALL,
DIE_PAGE_FAULT,
};
#endif
#ifndef _SPARC64_MDESC_H
#define _SPARC64_MDESC_H
#include <linux/types.h>
#include <asm/prom.h>
struct mdesc_node;
struct mdesc_arc {
const char *name;
struct mdesc_node *arc;
};
struct mdesc_node {
const char *name;
u64 node;
unsigned int unique_id;
unsigned int num_arcs;
struct property *properties;
struct mdesc_node *hash_next;
struct mdesc_node *allnodes_next;
struct mdesc_arc arcs[0];
};
extern struct mdesc_node *md_find_node_by_name(struct mdesc_node *from,
const char *name);
#define md_for_each_node_by_name(__mn, __name) \
for (__mn = md_find_node_by_name(NULL, __name); __mn; \
__mn = md_find_node_by_name(__mn, __name))
extern struct property *md_find_property(const struct mdesc_node *mp,
const char *name,
int *lenp);
extern const void *md_get_property(const struct mdesc_node *mp,
const char *name,
int *lenp);
extern void sun4v_mdesc_init(void);
#endif
......@@ -316,11 +316,8 @@ extern int prom_setprop(int node, const char *prop_name, char *prop_value,
extern int prom_pathtoinode(const char *path);
extern int prom_inst2pkg(int);
/* CPU probing helpers. */
struct device_node;
int cpu_find_by_instance(int instance, struct device_node **dev_node, int *mid);
int cpu_find_by_mid(int mid, struct device_node **prom_node);
extern int prom_service_exists(const char *service_name);
extern void prom_sun4v_guest_soft_state(void);
/* Client interface level routines. */
extern void prom_set_trap_table(unsigned long tba);
......
......@@ -5,7 +5,8 @@
#ifdef CONFIG_SMP
extern void setup_per_cpu_areas(void);
#define setup_per_cpu_areas() do { } while (0)
extern void real_setup_per_cpu_areas(void);
extern unsigned long __per_cpu_base;
extern unsigned long __per_cpu_shift;
......@@ -34,6 +35,7 @@ do { \
} while (0)
#else /* ! SMP */
#define real_setup_per_cpu_areas() do { } while (0)
#define DEFINE_PER_CPU(type, name) \
__typeof__(type) per_cpu__##name
......
......@@ -90,6 +90,7 @@ extern struct device_node *of_find_compatible_node(struct device_node *from,
const char *type, const char *compat);
extern struct device_node *of_find_node_by_path(const char *path);
extern struct device_node *of_find_node_by_phandle(phandle handle);
extern struct device_node *of_find_node_by_cpuid(int cpuid);
extern struct device_node *of_get_parent(const struct device_node *node);
extern struct device_node *of_get_next_child(const struct device_node *node,
struct device_node *prev);
......
......@@ -41,7 +41,7 @@ extern cpumask_t cpu_sibling_map[NR_CPUS];
extern int hard_smp_processor_id(void);
#define raw_smp_processor_id() (current_thread_info()->cpu)
extern void smp_setup_cpu_possible_map(void);
extern void smp_fill_in_sib_core_maps(void);
extern unsigned char boot_cpu_id;
#endif /* !(__ASSEMBLY__) */
......@@ -49,7 +49,7 @@ extern unsigned char boot_cpu_id;
#else
#define hard_smp_processor_id() 0
#define smp_setup_cpu_possible_map() do { } while (0)
#define smp_fill_in_sib_core_maps() do { } while (0)
#define boot_cpu_id (0)
#endif /* !(CONFIG_SMP) */
......
#ifndef _SPARC64_SSTATE_H
#define _SPARC64_SSTATE_H
extern void sstate_booting(void);
extern void sstate_running(void);
extern void sstate_halt(void);
extern void sstate_poweroff(void);
extern void sstate_panic(void);
extern void sstate_reboot(void);
extern void sun4v_sstate_init(void);
#endif /* _SPARC64_SSTATE_H */
......@@ -38,8 +38,8 @@ struct thread_info {
/* D$ line 1 */
struct task_struct *task;
unsigned long flags;
__u8 cpu;
__u8 fpsaved[7];
__u8 pad;
unsigned long ksp;
/* D$ line 2 */
......@@ -49,7 +49,7 @@ struct thread_info {
int preempt_count; /* 0 => preemptable, <0 => BUG */
__u8 new_child;
__u8 syscall_noerror;
__u16 __pad;
__u16 cpu;
unsigned long *utraps;
......@@ -83,8 +83,7 @@ struct thread_info {
#define TI_CURRENT_DS (TI_FLAGS + TI_FLAG_BYTE_CURRENT_DS)
#define TI_FPDEPTH (TI_FLAGS + TI_FLAG_BYTE_FPDEPTH)
#define TI_WSAVED (TI_FLAGS + TI_FLAG_BYTE_WSAVED)
#define TI_CPU 0x00000010
#define TI_FPSAVED 0x00000011
#define TI_FPSAVED 0x00000010
#define TI_KSP 0x00000018
#define TI_FAULT_ADDR 0x00000020
#define TI_KREGS 0x00000028
......@@ -92,6 +91,7 @@ struct thread_info {
#define TI_PRE_COUNT 0x00000038
#define TI_NEW_CHILD 0x0000003c
#define TI_SYS_NOERROR 0x0000003d
#define TI_CPU 0x0000003e
#define TI_UTRAPS 0x00000040
#define TI_REG_WINDOW 0x00000048
#define TI_RWIN_SPTRS 0x000003c8
......
......@@ -6,4 +6,7 @@
#include <asm-generic/topology.h>
#define topology_core_id(cpu) (cpu_data(cpu).core_id)
#define topology_thread_siblings(cpu) (cpu_sibling_map[cpu])
#endif /* _ASM_SPARC64_TOPOLOGY_H */
......@@ -271,7 +271,7 @@ extern struct tsb_phys_patch_entry __tsb_phys_patch, __tsb_phys_patch_end;
#define KERN_TSB4M_LOOKUP_TL1(TAG, REG1, REG2, REG3, REG4, OK_LABEL) \
sethi %hi(swapper_4m_tsb), REG1; \
or REG1, %lo(swapper_4m_tsb), REG1; \
and TAG, (KERNEL_TSB_NENTRIES - 1), REG2; \
and TAG, (KERNEL_TSB4M_NENTRIES - 1), REG2; \
sllx REG2, 4, REG2; \
add REG1, REG2, REG2; \
KTSB_LOAD_QUAD(REG2, REG3); \
......
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