Commit e0292b9d authored by David Mosberger's avatar David Mosberger

ia64: Sync with 2.5.64.

parents 236b5445 9b3ed4c1
......@@ -4,7 +4,7 @@
-----------------------------------
Started: 13-Jan-2003
Last update: 24-Jan-2003
Last update: 11-Feb-2003
David Mosberger-Tang
<davidm@hpl.hp.com>
......@@ -42,9 +42,9 @@ In contrast, fsys-mode has the following special properties:
can disable interrupts and avoid all other interruption-sources
to avoid preemption)
- neither the memory nor the register stack can be trusted while
- neither the memory-stack nor the register-stack can be trusted while
in fsys-mode (they point to the user-level stacks, which may
be invalid)
be invalid, or completely bogus addresses)
In summary, fsys-mode is much more similar to running in user-mode
than it is to running in kernel-mode. Of course, given that the
......
......@@ -26,7 +26,7 @@ config SWAP
bool
default y
config RWSEM_GENERIC_SPINLOCK
config RWSEM_XCHGADD_ALGORITHM
bool
default y
......@@ -424,6 +424,18 @@ config SMP
If you don't know what to do here, say N.
config PREEMPT
bool "Preemptible Kernel"
help
This option reduces the latency of the kernel when reacting to
real-time or interactive events by allowing a low priority process to
be preempted even if it is in kernel mode executing a system call.
This allows applications to run more reliably even when the system is
under load.
Say Y here if you are building a kernel for a desktop, embedded
or real-time system. Say N if you are unsure.
config IA32_SUPPORT
bool "Support running of Linux/x86 binaries"
help
......@@ -875,6 +887,12 @@ config DEBUG_SPINLOCK
best used in conjunction with the NMI watchdog so that spinlock
deadlocks are also debuggable.
config DEBUG_SPINLOCK_SLEEP
bool "Sleep-inside-spinlock checking"
help
If you say Y here, various routines which may sleep will become very
noisy if they are called with a spinlock held.
config IA64_DEBUG_CMPXCHG
bool "Turn on compare-and-exchange bug checking (slow!)"
depends on DEBUG_KERNEL
......
......@@ -52,18 +52,19 @@ core-$(CONFIG_IA64_GENERIC) += arch/ia64/dig/ arch/ia64/hp/common/ arch/ia64/hp
core-$(CONFIG_IA64_HP_ZX1) += arch/ia64/dig/
core-$(CONFIG_IA64_SGI_SN) += arch/ia64/sn/kernel/ \
arch/ia64/sn/io/ \
arch/ia64/sn/io/sn2/ \
arch/ia64/sn/io/sn2/pcibr/ \
arch/ia64/sn/kernel/sn2/
drivers-$(CONFIG_PCI) += arch/ia64/pci/
drivers-$(CONFIG_IA64_HP_SIM) += arch/ia64/hp/sim/
drivers-$(CONFIG_IA64_HP_ZX1) += arch/ia64/hp/common/ arch/ia64/hp/zx1/
drivers-$(CONFIG_IA64_SGI_SN) += arch/ia64/sn/fakeprom/
boot := arch/ia64/boot
tools := arch/ia64/tools
.PHONY: boot compressed include/asm-ia64/offsets.h
all: vmlinux
all: prepare vmlinux
compressed: vmlinux.gz
......
......@@ -156,7 +156,7 @@ simscsi_readwrite (Scsi_Cmnd *sc, int mode, unsigned long offset, unsigned long
if (sc->request_bufflen < req.len)
return;
stat.fd = desc[sc->target];
stat.fd = desc[sc->device->id];
if (DBG)
printk("simscsi_%s @ %lx (off %lx)\n",
mode == SSC_READ ? "read":"write", req.addr, offset);
......@@ -178,7 +178,7 @@ simscsi_sg_readwrite (Scsi_Cmnd *sc, int mode, unsigned long offset)
struct disk_stat stat;
struct disk_req req;
stat.fd = desc[sc->target];
stat.fd = desc[sc->device->id];
while (list_len) {
req.addr = __pa(page_address(sl->page) + sl->offset);
......@@ -259,6 +259,7 @@ simscsi_readwrite10 (Scsi_Cmnd *sc, int mode)
int
simscsi_queuecommand (Scsi_Cmnd *sc, void (*done)(Scsi_Cmnd *))
{
unsigned int target_id = sc->device->id;
char fname[MAX_ROOT_LEN+16];
size_t disk_size;
char *buf;
......@@ -267,21 +268,21 @@ simscsi_queuecommand (Scsi_Cmnd *sc, void (*done)(Scsi_Cmnd *))
if (DBG)
printk("simscsi_queuecommand: target=%d,cmnd=%u,sc=%lu,sp=%lx,done=%p\n",
sc->target, sc->cmnd[0], sc->serial_number, sp, done);
target_id, sc->cmnd[0], sc->serial_number, sp, done);
#endif
sc->result = DID_BAD_TARGET << 16;
sc->scsi_done = done;
if (sc->target <= 15 && sc->lun == 0) {
if (target_id <= 15 && sc->device->lun == 0) {
switch (sc->cmnd[0]) {
case INQUIRY:
if (sc->request_bufflen < 35) {
break;
}
sprintf (fname, "%s%c", simscsi_root, 'a' + sc->target);
desc[sc->target] = ia64_ssc(__pa(fname), SSC_READ_ACCESS|SSC_WRITE_ACCESS,
0, 0, SSC_OPEN);
if (desc[sc->target] < 0) {
sprintf (fname, "%s%c", simscsi_root, 'a' + target_id);
desc[target_id] = ia64_ssc(__pa(fname), SSC_READ_ACCESS|SSC_WRITE_ACCESS,
0, 0, SSC_OPEN);
if (desc[target_id] < 0) {
/* disk doesn't exist... */
break;
}
......@@ -303,37 +304,37 @@ simscsi_queuecommand (Scsi_Cmnd *sc, void (*done)(Scsi_Cmnd *))
break;
case READ_6:
if (desc[sc->target] < 0 )
if (desc[target_id] < 0 )
break;
simscsi_readwrite6(sc, SSC_READ);
break;
case READ_10:
if (desc[sc->target] < 0 )
if (desc[target_id] < 0 )
break;
simscsi_readwrite10(sc, SSC_READ);
break;
case WRITE_6:
if (desc[sc->target] < 0)
if (desc[target_id] < 0)
break;
simscsi_readwrite6(sc, SSC_WRITE);
break;
case WRITE_10:
if (desc[sc->target] < 0)
if (desc[target_id] < 0)
break;
simscsi_readwrite10(sc, SSC_WRITE);
break;
case READ_CAPACITY:
if (desc[sc->target] < 0 || sc->request_bufflen < 8) {
if (desc[target_id] < 0 || sc->request_bufflen < 8) {
break;
}
buf = sc->request_buffer;
disk_size = simscsi_get_disk_size(desc[sc->target]);
disk_size = simscsi_get_disk_size(desc[target_id]);
/* pretend to be a 1GB disk (partition table contains real stuff): */
buf[0] = (disk_size >> 24) & 0xff;
......
......@@ -63,7 +63,6 @@ extern void ia64_ssc_connect_irq (long intr, long irq);
static char *serial_name = "SimSerial driver";
static char *serial_version = "0.6";
static spinlock_t serial_lock = SPIN_LOCK_UNLOCKED;
/*
* This has been extracted from asm/serial.h. We need one eventually but
......@@ -235,14 +234,14 @@ static void rs_put_char(struct tty_struct *tty, unsigned char ch)
if (!tty || !info->xmit.buf) return;
spin_lock_irqsave(&serial_lock, flags);
local_irq_save(flags);
if (CIRC_SPACE(info->xmit.head, info->xmit.tail, SERIAL_XMIT_SIZE) == 0) {
spin_unlock_irqrestore(&serial_lock, flags);
local_irq_restore(flags);
return;
}
info->xmit.buf[info->xmit.head] = ch;
info->xmit.head = (info->xmit.head + 1) & (SERIAL_XMIT_SIZE-1);
spin_unlock_irqrestore(&serial_lock, flags);
local_irq_restore(flags);
}
static _INLINE_ void transmit_chars(struct async_struct *info, int *intr_done)
......@@ -250,7 +249,8 @@ static _INLINE_ void transmit_chars(struct async_struct *info, int *intr_done)
int count;
unsigned long flags;
spin_lock_irqsave(&serial_lock, flags);
local_irq_save(flags);
if (info->x_char) {
char c = info->x_char;
......@@ -293,7 +293,7 @@ static _INLINE_ void transmit_chars(struct async_struct *info, int *intr_done)
info->xmit.tail += count;
}
out:
spin_unlock_irqrestore(&serial_lock, flags);
local_irq_restore(flags);
}
static void rs_flush_chars(struct tty_struct *tty)
......@@ -334,7 +334,7 @@ static int rs_write(struct tty_struct * tty, int from_user,
break;
}
spin_lock_irqsave(&serial_lock, flags);
local_irq_save(flags);
{
c1 = CIRC_SPACE_TO_END(info->xmit.head, info->xmit.tail,
SERIAL_XMIT_SIZE);
......@@ -344,7 +344,7 @@ static int rs_write(struct tty_struct * tty, int from_user,
info->xmit.head = ((info->xmit.head + c) &
(SERIAL_XMIT_SIZE-1));
}
spin_unlock_irqrestore(&serial_lock, flags);
local_irq_restore(flags);
buf += c;
count -= c;
......@@ -352,7 +352,7 @@ static int rs_write(struct tty_struct * tty, int from_user,
}
up(&tmp_buf_sem);
} else {
spin_lock_irqsave(&serial_lock, flags);
local_irq_save(flags);
while (1) {
c = CIRC_SPACE_TO_END(info->xmit.head, info->xmit.tail, SERIAL_XMIT_SIZE);
if (count < c)
......@@ -367,7 +367,7 @@ static int rs_write(struct tty_struct * tty, int from_user,
count -= c;
ret += c;
}
spin_unlock_irqrestore(&serial_lock, flags);
local_irq_restore(flags);
}
/*
* Hey, we transmit directly from here in our case
......@@ -398,9 +398,9 @@ static void rs_flush_buffer(struct tty_struct *tty)
struct async_struct *info = (struct async_struct *)tty->driver_data;
unsigned long flags;
spin_lock_irqsave(&serial_lock, flags);
local_irq_save(flags);
info->xmit.head = info->xmit.tail = 0;
spin_unlock_irqrestore(&serial_lock, flags);
local_irq_restore(flags);
wake_up_interruptible(&tty->write_wait);
......@@ -573,7 +573,7 @@ static void shutdown(struct async_struct * info)
state->irq);
#endif
spin_lock_irqsave(&serial_lock, flags);
local_irq_save(flags);
{
/*
* First unlink the serial port from the IRQ chain...
......@@ -611,7 +611,7 @@ static void shutdown(struct async_struct * info)
info->flags &= ~ASYNC_INITIALIZED;
}
spin_unlock_irqrestore(&serial_lock, flags);
local_irq_restore(flags);
}
/*
......@@ -634,13 +634,13 @@ static void rs_close(struct tty_struct *tty, struct file * filp)
state = info->state;
spin_lock_irqsave(&serial_lock, flags);
local_irq_save(flags);
if (tty_hung_up_p(filp)) {
#ifdef SIMSERIAL_DEBUG
printk("rs_close: hung_up\n");
#endif
MOD_DEC_USE_COUNT;
spin_unlock_irqrestore(&serial_lock, flags);
local_irq_restore(flags);
return;
}
#ifdef SIMSERIAL_DEBUG
......@@ -665,11 +665,11 @@ static void rs_close(struct tty_struct *tty, struct file * filp)
}
if (state->count) {
MOD_DEC_USE_COUNT;
spin_unlock_irqrestore(&serial_lock, flags);
local_irq_restore(flags);
return;
}
info->flags |= ASYNC_CLOSING;
spin_unlock_irqrestore(&serial_lock, flags);
local_irq_restore(flags);
/*
* Now we wait for the transmit buffer to clear; and we notify
......@@ -776,7 +776,7 @@ startup(struct async_struct *info)
if (!page)
return -ENOMEM;
spin_lock_irqsave(&serial_lock, flags);
local_irq_save(flags);
if (info->flags & ASYNC_INITIALIZED) {
free_page(page);
......@@ -857,11 +857,11 @@ startup(struct async_struct *info)
}
info->flags |= ASYNC_INITIALIZED;
spin_unlock_irqrestore(&serial_lock, flags);
local_irq_restore(flags);
return 0;
errout:
spin_unlock_irqrestore(&serial_lock, flags);
local_irq_restore(flags);
return retval;
}
......
......@@ -93,7 +93,7 @@ ia32_load_state (struct task_struct *t)
{
unsigned long eflag, fsr, fcr, fir, fdr, csd, ssd, tssd;
struct pt_regs *regs = ia64_task_regs(t);
int nr = smp_processor_id(); /* LDT and TSS depend on CPU number: */
int nr = get_cpu(); /* LDT and TSS depend on CPU number: */
eflag = t->thread.eflag;
fsr = t->thread.fsr;
......@@ -119,6 +119,7 @@ ia32_load_state (struct task_struct *t)
regs->r17 = (_TSS(nr) << 48) | (_LDT(nr) << 32) | (__u32) regs->r17;
regs->r30 = load_desc(_LDT(nr)); /* LDTD */
put_cpu();
}
/*
......
......@@ -3433,8 +3433,12 @@ struct sysinfo32 {
u32 bufferram;
u32 totalswap;
u32 freeswap;
unsigned short procs;
char _f[22];
u16 procs;
u16 pad;
u32 totalhigh;
u32 freehigh;
u32 mem_unit;
char _f[8];
};
asmlinkage long
......@@ -3463,6 +3467,9 @@ sys32_sysinfo (struct sysinfo32 *info)
err |= __put_user(s.totalswap, &info->totalswap);
err |= __put_user(s.freeswap, &info->freeswap);
err |= __put_user(s.procs, &info->procs);
err |= __put_user (s.totalhigh, &info->totalhigh);
err |= __put_user (s.freehigh, &info->freehigh);
err |= __put_user (s.mem_unit, &info->mem_unit);
if (err)
return -EFAULT;
return ret;
......
......@@ -55,6 +55,7 @@ asm (".weak iosapic_register_intr");
asm (".weak iosapic_override_isa_irq");
asm (".weak iosapic_register_platform_intr");
asm (".weak iosapic_init");
asm (".weak iosapic_system_init");
asm (".weak iosapic_version");
void (*pm_idle) (void);
......@@ -290,40 +291,6 @@ acpi_parse_lapic_nmi (acpi_table_entry_header *header)
}
static int __init
acpi_find_iosapic (unsigned int gsi, u32 *gsi_base, char **iosapic_address)
{
struct acpi_table_iosapic *iosapic;
int ver;
int max_pin;
char *p;
char *end;
if (!gsi_base || !iosapic_address)
return -ENODEV;
p = (char *) (acpi_madt + 1);
end = p + (acpi_madt->header.length - sizeof(struct acpi_table_madt));
while (p < end) {
if (*p == ACPI_MADT_IOSAPIC) {
iosapic = (struct acpi_table_iosapic *) p;
*gsi_base = iosapic->global_irq_base;
*iosapic_address = ioremap(iosapic->address, 0);
ver = iosapic_version(*iosapic_address);
max_pin = (ver >> 16) & 0xff;
if ((gsi - *gsi_base) <= max_pin)
return 0; /* Found it! */
}
p += p[1];
}
return -ENODEV;
}
static int __init
acpi_parse_iosapic (acpi_table_entry_header *header)
{
......@@ -335,16 +302,9 @@ acpi_parse_iosapic (acpi_table_entry_header *header)
acpi_table_print_madt_entry(header);
if (iosapic_init) {
#ifndef CONFIG_ITANIUM
/* PCAT_COMPAT flag indicates dual-8259 setup */
iosapic_init(iosapic->address, iosapic->global_irq_base,
acpi_madt->flags.pcat_compat);
#else
/* Firmware on old Itanium systems is broken */
iosapic_init(iosapic->address, iosapic->global_irq_base, 1);
#endif
}
if (iosapic_init)
iosapic_init(iosapic->address, iosapic->global_irq_base);
return 0;
}
......@@ -354,8 +314,6 @@ acpi_parse_plat_int_src (acpi_table_entry_header *header)
{
struct acpi_table_plat_int_src *plintsrc;
int vector;
u32 gsi_base;
char *iosapic_address;
plintsrc = (struct acpi_table_plat_int_src *) header;
if (!plintsrc)
......@@ -368,11 +326,6 @@ acpi_parse_plat_int_src (acpi_table_entry_header *header)
return -ENODEV;
}
if (acpi_find_iosapic(plintsrc->global_irq, &gsi_base, &iosapic_address)) {
printk(KERN_WARNING PREFIX "IOSAPIC not found\n");
return -ENODEV;
}
/*
* Get vector assignment for this interrupt, set attributes,
* and program the IOSAPIC routing table.
......@@ -382,10 +335,8 @@ acpi_parse_plat_int_src (acpi_table_entry_header *header)
plintsrc->iosapic_vector,
plintsrc->eid,
plintsrc->id,
(plintsrc->flags.polarity == 1) ? 1 : 0,
(plintsrc->flags.trigger == 1) ? 1 : 0,
gsi_base,
iosapic_address);
(plintsrc->flags.polarity == 1) ? IOSAPIC_POL_HIGH : IOSAPIC_POL_LOW,
(plintsrc->flags.trigger == 1) ? IOSAPIC_EDGE : IOSAPIC_LEVEL);
platform_intr_list[plintsrc->type] = vector;
return 0;
......@@ -408,8 +359,8 @@ acpi_parse_int_src_ovr (acpi_table_entry_header *header)
return 0;
iosapic_override_isa_irq(p->bus_irq, p->global_irq,
(p->flags.polarity == 1) ? 1 : 0,
(p->flags.trigger == 1) ? 1 : 0);
(p->flags.polarity == 1) ? IOSAPIC_POL_HIGH : IOSAPIC_POL_LOW,
(p->flags.trigger == 1) ? IOSAPIC_EDGE : IOSAPIC_LEVEL);
return 0;
}
......@@ -439,7 +390,13 @@ acpi_parse_madt (unsigned long phys_addr, unsigned long size)
acpi_madt = (struct acpi_table_madt *) __va(phys_addr);
/* remember the value for reference after free_initmem() */
#ifdef CONFIG_ITANIUM
has_8259 = 1; /* Firmware on old Itanium systems is broken */
#else
has_8259 = acpi_madt->flags.pcat_compat;
#endif
if (iosapic_system_init)
iosapic_system_init(has_8259);
/* Get base address of IPI Message Block */
......@@ -639,8 +596,7 @@ acpi_parse_fadt (unsigned long phys_addr, unsigned long size)
{
struct acpi_table_header *fadt_header;
struct fadt_descriptor_rev2 *fadt;
u32 sci_irq, gsi_base;
char *iosapic_address;
u32 sci_irq;
if (!phys_addr || !size)
return -EINVAL;
......@@ -662,8 +618,7 @@ acpi_parse_fadt (unsigned long phys_addr, unsigned long size)
if (has_8259 && sci_irq < 16)
return 0; /* legacy, no setup required */
if (!acpi_find_iosapic(sci_irq, &gsi_base, &iosapic_address))
iosapic_register_intr(sci_irq, 0, 0, gsi_base, iosapic_address);
iosapic_register_intr(sci_irq, IOSAPIC_POL_LOW, IOSAPIC_LEVEL);
return 0;
}
......@@ -717,8 +672,6 @@ acpi_parse_spcr (unsigned long phys_addr, unsigned long size)
if ((spcr->base_addr.space_id != ACPI_SERIAL_PCICONF_SPACE) &&
(spcr->int_type == ACPI_SERIAL_INT_SAPIC))
{
u32 gsi_base;
char *iosapic_address;
int vector;
/* We have a UART in memory space with an SAPIC interrupt */
......@@ -728,11 +681,7 @@ acpi_parse_spcr (unsigned long phys_addr, unsigned long size)
(spcr->global_int[1] << 8) |
(spcr->global_int[0]) );
/* Which iosapic does this interrupt belong to? */
if (!acpi_find_iosapic(gsi, &gsi_base, &iosapic_address))
vector = iosapic_register_intr(gsi, 1, 1,
gsi_base, iosapic_address);
vector = iosapic_register_intr(gsi, IOSAPIC_POL_HIGH, IOSAPIC_EDGE);
}
return 0;
}
......@@ -741,7 +690,7 @@ acpi_parse_spcr (unsigned long phys_addr, unsigned long size)
int __init
acpi_boot_init (char *cmdline)
acpi_boot_init (void)
{
/*
......@@ -888,12 +837,10 @@ acpi_irq_to_vector (u32 irq)
return gsi_to_vector(irq);
}
int __init
int
acpi_register_irq (u32 gsi, u32 polarity, u32 trigger)
{
int vector = 0;
u32 irq_base;
char *iosapic_address;
if (acpi_madt->flags.pcat_compat && (gsi < 16))
return isa_irq_to_vector(gsi);
......@@ -901,12 +848,9 @@ acpi_register_irq (u32 gsi, u32 polarity, u32 trigger)
if (!iosapic_register_intr)
return 0;
/* Find the IOSAPIC */
if (!acpi_find_iosapic(gsi, &irq_base, &iosapic_address)) {
/* Turn it on */
vector = iosapic_register_intr (gsi, polarity, trigger,
irq_base, iosapic_address);
}
/* Turn it on */
vector = iosapic_register_intr (gsi, polarity ? IOSAPIC_POL_HIGH : IOSAPIC_POL_LOW,
trigger ? IOSAPIC_EDGE : IOSAPIC_LEVEL);
return vector;
}
......
......@@ -586,10 +586,21 @@ GLOBAL_ENTRY(ia64_leave_kernel)
// work.need_resched etc. mustn't get changed by this CPU before it returns to
// user- or fsys-mode:
(pUStk) cmp.eq.unc p6,p0=r0,r0 // p6 <- pUStk
#ifdef CONFIG_PREEMPT
rsm psr.i // disable interrupts
adds r17=TI_FLAGS+IA64_TASK_SIZE,r13
(pKStk) adds r20=TI_PRE_COUNT+IA64_TASK_SIZE,r13
;;
(pKStk) ld4 r21=[r20] // preempt_count ->r21
;;
(pKStk) cmp4.eq p6,p0=r21,r0 // p6 <- preempt_count == 0
;;
#else /* CONFIG_PREEMPT */
(pUStk) rsm psr.i
;;
(pUStk) adds r17=TI_FLAGS+IA64_TASK_SIZE,r13
;;
#endif /* CONFIG_PREEMPT */
.work_processed:
(p6) ld4 r18=[r17] // load current_thread_info()->flags
adds r2=PT(R8)+16,r12
......@@ -701,7 +712,7 @@ GLOBAL_ENTRY(ia64_leave_kernel)
* NOTE: alloc, loadrs, and cover can't be predicated.
*/
(pNonSys) br.cond.dpnt dont_preserve_current_frame
cover // add current frame into dirty partition
cover // add current frame into dirty partition and set cr.ifs
;;
mov r19=ar.bsp // get new backing store pointer
sub r16=r16,r18 // krbs = old bsp - size of dirty partition
......@@ -727,7 +738,7 @@ dont_preserve_current_frame:
# define Nregs 14
#endif
alloc loc0=ar.pfs,2,Nregs-2,2,0
shr.u loc1=r18,9 // RNaTslots <= dirtySize / (64*8) + 1
shr.u loc1=r18,9 // RNaTslots <= floor(dirtySize / (64*8))
sub r17=r17,r18 // r17 = (physStackedSize + 8) - dirtySize
;;
mov ar.rsc=r19 // load ar.rsc to be used for "loadrs"
......@@ -774,13 +785,13 @@ rse_clear_invalid:
;;
mov loc3=0
mov loc4=0
mov loc9=0
mov loc5=0
mov loc6=0
mov loc7=0
(pRecurse) br.call.sptk.many b6=rse_clear_invalid
;;
mov loc7=0
mov loc8=0
mov loc9=0
cmp.ne pReturn,p0=r0,in1 // if recursion count != 0, we need to do a br.ret
mov loc10=0
mov loc11=0
......@@ -810,15 +821,27 @@ skip_rbs_switch:
.work_pending:
tbit.z p6,p0=r18,TIF_NEED_RESCHED // current_thread_info()->need_resched==0?
(p6) br.cond.sptk.few .notify
#ifdef CONFIG_PREEMPT
(pKStk) dep r21=-1,r0,PREEMPT_ACTIVE_BIT,1
;;
(pKStk) st4 [r20]=r21
ssm psr.i // enable interrupts
#endif
#if __GNUC__ < 3
br.call.spnt.many rp=invoke_schedule
#else
br.call.spnt.many rp=schedule
#endif
.ret9: cmp.eq p6,p0=r0,r0 // p6 <- 1
rsm psr.i
rsm psr.i // disable interrupts
;;
adds r17=TI_FLAGS+IA64_TASK_SIZE,r13
#if CONFIG_PREEMPT
(pKStk) adds r20=TI_PRE_COUNT+IA64_TASK_SIZE,r13
;;
(pKStk) st4 [r20]=r0 // preempt_count() <- 0
#endif
br.cond.sptk.many .work_processed // re-check
.notify:
......@@ -904,13 +927,14 @@ ENTRY(notify_resume_user)
mov r9=ar.unat
mov loc0=rp // save return address
mov out0=0 // there is no "oldset"
adds out1=0,sp // out1=&sigscratch
adds out1=8,sp // out1=&sigscratch->ar_pfs
(pSys) mov out2=1 // out2==1 => we're in a syscall
;;
(pNonSys) mov out2=0 // out2==0 => not a syscall
.fframe 16
.spillpsp ar.unat, 16 // (note that offset is relative to psp+0x10!)
st8 [sp]=r9,-16 // allocate space for ar.unat and save it
st8 [out1]=loc1,-8 // save ar.pfs, out1=&sigscratch
.body
br.call.sptk.many rp=do_notify_resume_user
.ret15: .restore sp
......@@ -931,11 +955,12 @@ GLOBAL_ENTRY(sys_rt_sigsuspend)
mov loc0=rp // save return address
mov out0=in0 // mask
mov out1=in1 // sigsetsize
adds out2=0,sp // out2=&sigscratch
adds out2=8,sp // out2=&sigscratch->ar_pfs
;;
.fframe 16
.spillpsp ar.unat, 16 // (note that offset is relative to psp+0x10!)
st8 [sp]=r9,-16 // allocate space for ar.unat and save it
st8 [out2]=loc1,-8 // save ar.pfs, out2=&sigscratch
.body
br.call.sptk.many rp=ia64_rt_sigsuspend
.ret17: .restore sp
......@@ -1242,7 +1267,7 @@ sys_call_table:
data8 sys_sched_setaffinity
data8 sys_sched_getaffinity
data8 sys_set_tid_address
data8 ia64_ni_syscall
data8 sys_fadvise64
data8 ia64_ni_syscall // 1235
data8 sys_exit_group
data8 sys_lookup_dcookie
......
......@@ -3,11 +3,16 @@
*
* Copyright (C) 2003 Hewlett-Packard Co
* David Mosberger-Tang <davidm@hpl.hp.com>
*
* 18-Feb-03 louisk Implement fsys_gettimeofday().
* 28-Feb-03 davidm Fixed several bugs in fsys_gettimeofday(). Tuned it some more,
* probably broke it along the way... ;-)
*/
#include <asm/asmmacro.h>
#include <asm/errno.h>
#include <asm/offsets.h>
#include <asm/percpu.h>
#include <asm/thread_info.h>
/*
......@@ -123,6 +128,183 @@ ENTRY(fsys_set_tid_address)
br.ret.sptk.many b6
END(fsys_set_tid_address)
/*
* Note 1: This routine uses floating-point registers, but only with registers that
* operate on integers. Because of that, we don't need to set ar.fpsr to the
* kernel default value.
*
* Note 2: For now, we will assume that all CPUs run at the same clock-frequency.
* If that wasn't the case, we would have to disable preemption (e.g.,
* by disabling interrupts) between reading the ITC and reading
* local_cpu_data->nsec_per_cyc.
*
* Note 3: On platforms where the ITC-drift bit is set in the SAL feature vector,
* we ought to either skip the ITC-based interpolation or run an ntp-like
* daemon to keep the ITCs from drifting too far apart.
*/
ENTRY(fsys_gettimeofday)
add r9=TI_FLAGS+IA64_TASK_SIZE,r16
movl r3=THIS_CPU(cpu_info)
mov.m r31=ar.itc // put time stamp into r31 (ITC) == now (35 cyc)
movl r19=xtime // xtime is a timespec struct
;;
#ifdef CONFIG_SMP
movl r10=__per_cpu_offset
;;
ld8 r10=[r10] // r10 <- __per_cpu_offset[0]
movl r21=cpu_info__per_cpu
;;
add r10=r21, r10 // r10 <- &cpu_data(time_keeper_id)
#else
mov r10=r3
#endif
ld4 r9=[r9]
movl r17=xtime_lock
;;
// r32, r33 should contain the 2 args of gettimeofday
adds r21=IA64_CPUINFO_ITM_NEXT_OFFSET, r10
mov r2=-1
tnat.nz p6,p7=r32 // guard against NaT args
;;
adds r10=IA64_CPUINFO_ITM_DELTA_OFFSET, r10
(p7) tnat.nz p6,p0=r33
(p6) br.cond.spnt.few .fail
adds r8=IA64_CPUINFO_NSEC_PER_CYC_OFFSET, r3
movl r24=2361183241434822607 // for division hack (only for / 1000)
;;
ldf8 f7=[r10] // f7 now contains itm_delta
setf.sig f11=r2
adds r10=8, r32
adds r20=IA64_TIMESPEC_TV_NSEC_OFFSET, r19 // r20 = &xtime->tv_nsec
movl r26=jiffies
setf.sig f9=r24 // f9 is used for division hack
movl r27=wall_jiffies
and r9=TIF_ALLWORK_MASK,r9
movl r25=last_nsec_offset
;;
/*
* Verify that we have permission to write to struct timeval. Note:
* Another thread might unmap the mapping before we actually get
* to store the result. That's OK as long as the stores are also
* protect by EX().
*/
EX(.fail, probe.w.fault r32, 3) // this must come _after_ NaT-check
EX(.fail, probe.w.fault r10, 3) // this must come _after_ NaT-check
nop 0
ldf8 f10=[r8] // f10 <- local_cpu_data->nsec_per_cyc value
cmp.ne p8, p0=0, r9
(p8) br.spnt.many fsys_fallback_syscall
;;
.retry: // *** seq = read_seqbegin(&xtime_lock); ***
ld4.acq r23=[r17] // since &xtime_lock == &xtime_lock->sequence
ld8 r14=[r25] // r14 (old) = last_nsec_offset
ld8 r28=[r26] // r28 = jiffies
ld8 r29=[r27] // r29 = wall_jiffies
;;
ldf8 f8=[r21] // f8 now contains itm_next
sub r28=r29, r28, 1 // r28 now contains "-(lost + 1)"
tbit.nz p9, p10=r23, 0 // p9 <- is_odd(r23), p10 <- is_even(r23)
;;
ld8 r2=[r19] // r2 = sec = xtime.tv_sec
ld8 r29=[r20] // r29 = nsec = xtime.tv_nsec
setf.sig f6=r28 // f6 <- -(lost + 1) (6 cyc)
;;
mf
xma.l f8=f6, f7, f8 // f8 (last_tick) <- -(lost + 1)*itm_delta + itm_next (5 cyc)
nop 0
setf.sig f12=r31 // f12 <- ITC (6 cyc)
// *** if (unlikely(read_seqretry(&xtime_lock, seq))) continue; ***
ld4 r24=[r17] // r24 = xtime_lock->sequence (re-read)
nop 0
;;
mov r31=ar.itc // re-read ITC in case we .retry (35 cyc)
xma.l f8=f11, f8, f12 // f8 (elapsed_cycles) <- (-1*last_tick + now) = (now - last_tick)
nop 0
;;
getf.sig r18=f8 // r18 <- (now - last_tick)
xmpy.l f8=f8, f10 // f8 <- elapsed_cycles*nsec_per_cyc (5 cyc)
add r3=r29, r14 // r3 = (nsec + old)
;;
cmp.lt p7, p8=r18, r0 // if now < last_tick, set p7 = 1, p8 = 0
getf.sig r18=f8 // r18 = elapsed_cycles*nsec_per_cyc (6 cyc)
nop 0
;;
(p10) cmp.ne p9, p0=r23, r24 // if xtime_lock->sequence != seq, set p9
shr.u r18=r18, IA64_NSEC_PER_CYC_SHIFT // r18 <- offset
(p9) br.spnt.many .retry
;;
mov ar.ccv=r14 // ar.ccv = old (1 cyc)
cmp.leu p7, p8=r18, r14 // if (offset <= old), set p7 = 1, p8 = 0
;;
(p8) cmpxchg8.rel r24=[r25], r18, ar.ccv // compare-and-exchange (atomic!)
(p8) add r3=r29, r18 // r3 = (nsec + offset)
;;
shr.u r3=r3, 3 // initiate dividing r3 by 1000
;;
setf.sig f8=r3 // (6 cyc)
mov r10=1000000 // r10 = 1000000
;;
(p8) cmp.ne.unc p9, p0=r24, r14
xmpy.hu f6=f8, f9 // (5 cyc)
(p9) br.spnt.many .retry
;;
getf.sig r3=f6 // (6 cyc)
;;
shr.u r3=r3, 4 // end of division, r3 is divided by 1000 (=usec)
;;
1: cmp.geu p7, p0=r3, r10 // while (usec >= 1000000)
;;
(p7) sub r3=r3, r10 // usec -= 1000000
(p7) adds r2=1, r2 // ++sec
(p7) br.spnt.many 1b
// finally: r2 = sec, r3 = usec
EX(.fail, st8 [r32]=r2)
adds r9=8, r32
mov r8=r0 // success
;;
EX(.fail, st8 [r9]=r3) // store them in the timeval struct
mov r10=0
MCKINLEY_E9_WORKAROUND
br.ret.sptk.many b6 // return to caller
/*
* Note: We are NOT clearing the scratch registers here. Since the only things
* in those registers are time-related variables and some addresses (which
* can be obtained from System.map), none of this should be security-sensitive
* and we should be fine.
*/
.fail: adds r8=EINVAL, r0 // r8 = EINVAL
adds r10=-1, r0 // r10 = -1
MCKINLEY_E9_WORKAROUND
br.ret.spnt.many b6 // return with r8 set to EINVAL
END(fsys_gettimeofday)
.rodata
.align 8
.globl fsyscall_table
......@@ -190,7 +372,7 @@ fsyscall_table:
data8 fsys_fallback_syscall // setrlimit
data8 fsys_fallback_syscall // getrlimit // 1085
data8 fsys_fallback_syscall // getrusage
data8 fsys_fallback_syscall // gettimeofday
data8 fsys_gettimeofday // gettimeofday
data8 fsys_fallback_syscall // settimeofday
data8 fsys_fallback_syscall // select
data8 fsys_fallback_syscall // poll // 1090
......
......@@ -145,11 +145,12 @@ END(fsys_fallback_syscall)
*/
#define SIGTRAMP_SAVES \
.unwabi @svr4, 's' // mark this as a sigtramp handler (saves scratch regs) \
.savesp ar.unat, UNAT_OFF+SIGCONTEXT_OFF \
.savesp ar.fpsr, FPSR_OFF+SIGCONTEXT_OFF \
.savesp pr, PR_OFF+SIGCONTEXT_OFF \
.savesp rp, RP_OFF+SIGCONTEXT_OFF \
.unwabi @svr4, 's'; /* mark this as a sigtramp handler (saves scratch regs) */ \
.savesp ar.unat, UNAT_OFF+SIGCONTEXT_OFF; \
.savesp ar.fpsr, FPSR_OFF+SIGCONTEXT_OFF; \
.savesp pr, PR_OFF+SIGCONTEXT_OFF; \
.savesp rp, RP_OFF+SIGCONTEXT_OFF; \
.savesp ar.pfs, CFM_OFF+SIGCONTEXT_OFF; \
.vframesp SP_OFF+SIGCONTEXT_OFF
GLOBAL_ENTRY(ia64_sigtramp)
......@@ -173,9 +174,7 @@ GLOBAL_ENTRY(ia64_sigtramp)
.spillsp.p p8, ar.rnat, RNAT_OFF+SIGCONTEXT_OFF
(p8) br.cond.spnt setup_rbs // yup -> (clobbers r14, r15, and r16)
back_from_setup_rbs:
.spillreg ar.pfs, r8
alloc r8=ar.pfs,0,0,3,0 // get CFM0, EC0, and CPL0 into r8
alloc r8=ar.pfs,0,0,3,0
ld8 out0=[base0],16 // load arg0 (signum)
adds base1=(ARG1_OFF-(RBS_BASE_OFF+SIGCONTEXT_OFF)),base1
;;
......@@ -184,17 +183,12 @@ back_from_setup_rbs:
;;
ld8 out2=[base0] // load arg2 (sigcontextp)
ld8 gp=[r17] // get signal handler's global pointer
adds base0=(BSP_OFF+SIGCONTEXT_OFF),sp
;;
.spillsp ar.bsp, BSP_OFF+SIGCONTEXT_OFF
st8 [base0]=r9,(CFM_OFF-BSP_OFF) // save sc_ar_bsp
dep r8=0,r8,38,26 // clear EC0, CPL0 and reserved bits
adds base1=(FR6_OFF+16+SIGCONTEXT_OFF),sp
;;
.spillsp ar.pfs, CFM_OFF+SIGCONTEXT_OFF
st8 [base0]=r8 // save CFM0
st8 [base0]=r9 // save sc_ar_bsp
adds base0=(FR6_OFF+SIGCONTEXT_OFF),sp
adds base1=(FR6_OFF+16+SIGCONTEXT_OFF),sp
;;
stf.spill [base0]=f6,32
stf.spill [base1]=f7,32
......@@ -217,7 +211,6 @@ back_from_setup_rbs:
ld8 r15=[base0],(CFM_OFF-BSP_OFF) // fetch sc_ar_bsp and advance to CFM_OFF
mov r14=ar.bsp
;;
ld8 r8=[base0] // restore (perhaps modified) CFM0, EC0, and CPL0
cmp.ne p8,p0=r14,r15 // do we need to restore the rbs?
(p8) br.cond.spnt restore_rbs // yup -> (clobbers r14-r18, f6 & f7)
;;
......
......@@ -17,6 +17,7 @@
static struct fs_struct init_fs = INIT_FS;
static struct files_struct init_files = INIT_FILES;
static struct signal_struct init_signals = INIT_SIGNALS(init_signals);
static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand);
struct mm_struct init_mm = INIT_MM(init_mm);
/*
......
This diff is collapsed.
......@@ -340,12 +340,14 @@ unsigned int do_IRQ(unsigned long irq, struct pt_regs *regs)
* 0 return value means that this irq is already being
* handled by some other CPU. (or is disabled)
*/
int cpu = smp_processor_id();
int cpu;
irq_desc_t *desc = irq_desc(irq);
struct irqaction * action;
unsigned int status;
irq_enter();
cpu = smp_processor_id();
kstat_cpu(cpu).irqs[irq]++;
if (desc->status & IRQ_PER_CPU) {
......
......@@ -10,19 +10,6 @@
struct ia64_machine_vector ia64_mv;
/*
* Most platforms use this routine for mapping page frame addresses into a memory map
* index.
*
* Note: we can't use __pa() because map_nr_dense(X) MUST map to something >= max_mapnr if
* X is outside the identity mapped kernel space.
*/
unsigned long
map_nr_dense (unsigned long addr)
{
return (addr - PAGE_OFFSET) >> PAGE_SHIFT;
}
static struct ia64_machine_vector *
lookup_machvec (const char *name)
{
......
......@@ -825,7 +825,7 @@ ia64_init_handler (struct pt_regs *regs)
plog_ptr=(ia64_err_rec_t *)IA64_LOG_CURR_BUFFER(SAL_INFO_TYPE_INIT);
proc_ptr = &plog_ptr->proc_err;
ia64_process_min_state_save(&proc_ptr->processor_static_info.min_state_area);
ia64_process_min_state_save(&SAL_LPI_PSI_INFO(proc_ptr)->min_state_area);
/* Clear the INIT SAL logs now that they have been saved in the OS buffer */
ia64_sal_clear_state_info(SAL_INFO_TYPE_INIT);
......@@ -1620,7 +1620,7 @@ ia64_log_proc_dev_err_info_print (sal_log_processor_info_t *slpi,
* absent. Also, current implementations only allocate space for number of
* elements used. So we walk the data pointer from here on.
*/
p_data = &slpi->cache_check_info[0];
p_data = &slpi->info[0];
/* Print the cache check information if any*/
for (i = 0 ; i < slpi->valid.num_cache_check; i++, p_data++)
......
......@@ -341,11 +341,11 @@ vm_info(char *page)
return 0;
}
p += sprintf(p, "\nTLB walker : %s implemented\n" \
p += sprintf(p, "\nTLB walker : %simplemented\n" \
"Number of DTR : %d\n" \
"Number of ITR : %d\n" \
"TLB insertable page sizes : ",
vm_info_1.pal_vm_info_1_s.vw ? "\b":"not",
vm_info_1.pal_vm_info_1_s.vw ? "" : "not ",
vm_info_1.pal_vm_info_1_s.max_dtr_entry+1,
vm_info_1.pal_vm_info_1_s.max_itr_entry+1);
......@@ -894,11 +894,13 @@ palinfo_read_entry(char *page, char **start, off_t off, int count, int *eof, voi
* in SMP mode, we may need to call another CPU to get correct
* information. PAL, by definition, is processor specific
*/
if (f->req_cpu == smp_processor_id())
if (f->req_cpu == get_cpu())
len = (*palinfo_entries[f->func_id].proc_read)(page);
else
len = palinfo_handle_smp(f, page);
put_cpu();
if (len <= off+count) *eof = 1;
*start = page + off;
......
This diff is collapsed.
/*
* Kernel support for the ptrace() and syscall tracing interfaces.
*
* Copyright (C) 1999-2002 Hewlett-Packard Co
* Copyright (C) 1999-2003 Hewlett-Packard Co
* David Mosberger-Tang <davidm@hpl.hp.com>
*
* Derived from the x86 and Alpha versions. Most of the code in here
......@@ -1235,19 +1235,12 @@ sys_ptrace (long request, pid_t pid, unsigned long addr, unsigned long data,
ret = 0;
goto out_tsk;
case PTRACE_GETSIGINFO:
ret = -EIO;
if (!access_ok(VERIFY_WRITE, data, sizeof (siginfo_t)) || !child->thread.siginfo)
goto out_tsk;
ret = copy_siginfo_to_user((siginfo_t *) data, child->thread.siginfo);
case PTRACE_OLD_GETSIGINFO: /* for backwards-compatibility */
ret = ptrace_request(child, PTRACE_GETSIGINFO, addr, data);
goto out_tsk;
case PTRACE_SETSIGINFO:
ret = -EIO;
if (!access_ok(VERIFY_READ, data, sizeof (siginfo_t))
|| child->thread.siginfo == 0)
goto out_tsk;
ret = copy_siginfo_from_user(child->thread.siginfo, (siginfo_t *) data);
case PTRACE_OLD_SETSIGINFO: /* for backwards-compatibility */
ret = ptrace_request(child, PTRACE_SETSIGINFO, addr, data);
goto out_tsk;
case PTRACE_SYSCALL: /* continue and stop at next (return from) syscall */
......
......@@ -363,7 +363,7 @@ setup_arch (char **cmdline_p)
#ifdef CONFIG_ACPI_BOOT
/* Initialize the ACPI boot-time table parser */
acpi_table_init(*cmdline_p);
acpi_table_init();
# ifdef CONFIG_ACPI_NUMA
acpi_numa_init();
# endif
......@@ -422,7 +422,7 @@ setup_arch (char **cmdline_p)
cpu_init(); /* initialize the bootstrap CPU */
#ifdef CONFIG_ACPI_BOOT
acpi_boot_init(*cmdline_p);
acpi_boot_init();
#endif
#ifdef CONFIG_SERIAL_HCDP
if (efi.hcdp) {
......
struct sigscratch {
unsigned long scratch_unat; /* ar.unat for the general registers saved in pt */
unsigned long pad;
unsigned long ar_pfs; /* for syscalls, the user-level function-state */
struct pt_regs pt;
};
......
......@@ -315,7 +315,7 @@ ia64_rt_sigreturn (struct sigscratch *scr)
static long
setup_sigcontext (struct sigcontext *sc, sigset_t *mask, struct sigscratch *scr)
{
unsigned long flags = 0, ifs, nat;
unsigned long flags = 0, ifs, cfm, nat;
long err;
ifs = scr->pt.cr_ifs;
......@@ -325,7 +325,9 @@ setup_sigcontext (struct sigcontext *sc, sigset_t *mask, struct sigscratch *scr)
if ((ifs & (1UL << 63)) == 0) {
/* if cr_ifs isn't valid, we got here through a syscall */
flags |= IA64_SC_FLAG_IN_SYSCALL;
}
cfm = scr->ar_pfs & ((1UL << 38) - 1);
} else
cfm = ifs & ((1UL << 38) - 1);
ia64_flush_fph(current);
if ((current->thread.flags & IA64_THREAD_FPH_VALID)) {
flags |= IA64_SC_FLAG_FPH_VALID;
......@@ -344,6 +346,7 @@ setup_sigcontext (struct sigcontext *sc, sigset_t *mask, struct sigscratch *scr)
err |= __put_user(nat, &sc->sc_nat);
err |= PUT_SIGSET(mask, &sc->sc_mask);
err |= __put_user(cfm, &sc->sc_cfm);
err |= __put_user(scr->pt.cr_ipsr & IA64_PSR_UM, &sc->sc_um);
err |= __put_user(scr->pt.ar_rsc, &sc->sc_ar_rsc);
err |= __put_user(scr->pt.ar_ccv, &sc->sc_ar_ccv);
......@@ -422,6 +425,15 @@ setup_frame (int sig, struct k_sigaction *ka, siginfo_t *info, sigset_t *set,
scr->pt.ar_fpsr = FPSR_DEFAULT; /* reset fpsr for signal handler */
scr->pt.cr_iip = tramp_addr;
ia64_psr(&scr->pt)->ri = 0; /* start executing in first slot */
/*
* Force the interruption function mask to zero. This has no effect when a
* system-call got interrupted by a signal (since, in that case, scr->pt_cr_ifs is
* ignored), but it has the desirable effect of making it possible to deliver a
* signal with an incomplete register frame (which happens when a mandatory RSE
* load faults). Furthermore, it has no negative effect on the getting the user's
* dirty partition preserved, because that's governed by scr->pt.loadrs.
*/
scr->pt.cr_ifs = (1UL << 63);
/*
* Note: this affects only the NaT bits of the scratch regs (the ones saved in
......@@ -522,7 +534,7 @@ ia64_do_signal (sigset_t *oldset, struct sigscratch *scr, long in_syscall)
if (signr <= 0)
break;
ka = &current->sig->action[signr - 1];
ka = &current->sighand->action[signr - 1];
if (restart) {
switch (errno) {
......
......@@ -90,7 +90,7 @@ stop_this_cpu (void)
void
handle_IPI (int irq, void *dev_id, struct pt_regs *regs)
{
int this_cpu = smp_processor_id();
int this_cpu = get_cpu();
unsigned long *pending_ipis = &__get_cpu_var(ipi_operation);
unsigned long ops;
......@@ -146,8 +146,12 @@ handle_IPI (int irq, void *dev_id, struct pt_regs *regs)
} while (ops);
mb(); /* Order data access and bit testing. */
}
put_cpu();
}
/*
* Called with preeemption disabled
*/
static inline void
send_IPI_single (int dest_cpu, int op)
{
......@@ -155,6 +159,9 @@ send_IPI_single (int dest_cpu, int op)
platform_send_ipi(dest_cpu, IA64_IPI_VECTOR, IA64_IPI_DM_INT, 0);
}
/*
* Called with preeemption disabled
*/
static inline void
send_IPI_allbutself (int op)
{
......@@ -166,6 +173,9 @@ send_IPI_allbutself (int op)
}
}
/*
* Called with preeemption disabled
*/
static inline void
send_IPI_all (int op)
{
......@@ -176,12 +186,18 @@ send_IPI_all (int op)
send_IPI_single(i, op);
}
/*
* Called with preeemption disabled
*/
static inline void
send_IPI_self (int op)
{
send_IPI_single(smp_processor_id(), op);
}
/*
* Called with preeemption disabled
*/
void
smp_send_reschedule (int cpu)
{
......@@ -197,12 +213,15 @@ void
smp_send_reschedule_all (void)
{
int i;
int cpu = get_cpu(); /* disable preemption */
for (i = 0; i < NR_CPUS; i++)
if (cpu_online(i) && i != smp_processor_id())
if (cpu_online(i) && i != cpu)
smp_send_reschedule(i);
put_cpu();
}
void
smp_flush_tlb_all (void)
{
......@@ -247,9 +266,11 @@ smp_call_function_single (int cpuid, void (*func) (void *info), void *info, int
{
struct call_data_struct data;
int cpus = 1;
int me = get_cpu(); /* prevent preemption and reschedule on another processor */
if (cpuid == smp_processor_id()) {
if (cpuid == me) {
printk("%s: trying to call self\n", __FUNCTION__);
put_cpu();
return -EBUSY;
}
......@@ -276,6 +297,7 @@ smp_call_function_single (int cpuid, void (*func) (void *info), void *info, int
call_data = NULL;
spin_unlock_bh(&call_lock);
put_cpu();
return 0;
}
......
......@@ -33,17 +33,8 @@ arch_get_unmapped_area (struct file *filp, unsigned long addr, unsigned long len
return -ENOMEM;
#ifdef CONFIG_HUGETLB_PAGE
#define COLOR_HALIGN(addr) ((addr + HPAGE_SIZE - 1) & ~(HPAGE_SIZE - 1))
#define TASK_HPAGE_BASE ((REGION_HPAGE << REGION_SHIFT) | HPAGE_SIZE)
if (filp && is_file_hugepages(filp)) {
if ((REGION_NUMBER(addr) != REGION_HPAGE) || (addr & (HPAGE_SIZE -1)))
addr = TASK_HPAGE_BASE;
addr = COLOR_HALIGN(addr);
}
else {
if (REGION_NUMBER(addr) == REGION_HPAGE)
addr = 0;
}
if (REGION_NUMBER(addr) == REGION_HPAGE)
addr = 0;
#endif
if (!addr)
addr = TASK_UNMAPPED_BASE;
......
......@@ -25,7 +25,7 @@
#include <asm/system.h>
extern unsigned long wall_jiffies;
extern unsigned long last_time_offset;
extern unsigned long last_nsec_offset;
u64 jiffies_64 = INITIAL_JIFFIES;
......@@ -74,13 +74,13 @@ gettimeoffset (void)
- (lost + 1)*cpu_data(time_keeper_id)->itm_delta);
now = ia64_get_itc();
if ((long) (now - last_tick) < 0) {
if (unlikely((long) (now - last_tick) < 0)) {
printk(KERN_ERR "CPU %d: now < last_tick (now=0x%lx,last_tick=0x%lx)!\n",
smp_processor_id(), now, last_tick);
return last_time_offset;
return last_nsec_offset;
}
elapsed_cycles = now - last_tick;
return (elapsed_cycles*local_cpu_data->usec_per_cyc) >> IA64_USEC_PER_CYC_SHIFT;
return (elapsed_cycles*local_cpu_data->nsec_per_cyc) >> IA64_NSEC_PER_CYC_SHIFT;
}
void
......@@ -115,30 +115,55 @@ do_settimeofday (struct timeval *tv)
void
do_gettimeofday (struct timeval *tv)
{
unsigned long seq, usec, sec, old;
unsigned long seq, nsec, usec, sec, old, offset;
do {
while (1) {
seq = read_seqbegin(&xtime_lock);
usec = gettimeoffset();
{
old = last_nsec_offset;
offset = gettimeoffset();
sec = xtime.tv_sec;
nsec = xtime.tv_nsec;
}
if (unlikely(read_seqretry(&xtime_lock, seq)))
continue;
/*
* Ensure time never goes backwards, even when ITC on
* different CPUs are not perfectly synchronized.
* Ensure that for any pair of causally ordered gettimeofday() calls, time
* never goes backwards (even when ITC on different CPUs are not perfectly
* synchronized). (A pair of concurrent calls to gettimeofday() is by
* definition non-causal and hence it makes no sense to talk about
* time-continuity for such calls.)
*
* Doing this in a lock-free and race-free manner is tricky. Here is why
* it works (most of the time): read_seqretry() just succeeded, which
* implies we calculated a consistent (valid) value for "offset". If the
* cmpxchg() below succeeds, we further know that last_nsec_offset still
* has the same value as at the beginning of the loop, so there was
* presumably no timer-tick or other updates to last_nsec_offset in the
* meantime. This isn't 100% true though: there _is_ a possibility of a
* timer-tick occurring right right after read_seqretry() and then getting
* zero or more other readers which will set last_nsec_offset to the same
* value as the one we read at the beginning of the loop. If this
* happens, we'll end up returning a slightly newer time than we ought to
* (the jump forward is at most "offset" nano-seconds). There is no
* danger of causing time to go backwards, though, so we are safe in that
* sense. We could make the probability of this unlucky case occurring
* arbitrarily small by encoding a version number in last_nsec_offset, but
* even without versioning, the probability of this unlucky case should be
* so small that we won't worry about it.
*/
do {
old = last_time_offset;
if (usec <= old) {
usec = old;
break;
}
} while (cmpxchg(&last_time_offset, old, usec) != old);
if (offset <= old) {
offset = old;
break;
} else if (likely(cmpxchg(&last_nsec_offset, old, offset) == old))
break;
sec = xtime.tv_sec;
usec += xtime.tv_nsec / 1000;
} while (read_seqend(&xtime_lock, seq));
/* someone else beat us to updating last_nsec_offset; try again */
}
usec = (nsec + offset) / 1000;
while (usec >= 1000000) {
while (unlikely(usec >= 1000000)) {
usec -= 1000000;
++sec;
}
......@@ -278,7 +303,7 @@ ia64_init_itm (void)
local_cpu_data->proc_freq = (platform_base_freq*proc_ratio.num)/proc_ratio.den;
local_cpu_data->itc_freq = itc_freq;
local_cpu_data->cyc_per_usec = (itc_freq + 500000) / 1000000;
local_cpu_data->usec_per_cyc = ((1000000UL<<IA64_USEC_PER_CYC_SHIFT)
local_cpu_data->nsec_per_cyc = ((1000000000UL<<IA64_NSEC_PER_CYC_SHIFT)
+ itc_freq/2)/itc_freq;
/* Setup the CPU local timer tick */
......
This diff is collapsed.
......@@ -137,7 +137,8 @@ enum unw_insn_opcode {
UNW_INSN_SETNAT_MEMSTK, /* s[dst+1].nat.type = MEMSTK;
s[dst+1].nat.off = *s.pri_unat - s[dst] */
UNW_INSN_SETNAT_TYPE, /* s[dst+1].nat.type = val */
UNW_INSN_LOAD /* s[dst] = *s[val] */
UNW_INSN_LOAD, /* s[dst] = *s[val] */
UNW_INSN_MOVE_SCRATCH, /* s[dst] = scratch reg "val" */
};
struct unw_insn {
......
......@@ -55,7 +55,7 @@ ia64_do_page_fault (unsigned long address, unsigned long isr, struct pt_regs *re
/*
* If we're in an interrupt or have no user context, we must not take the fault..
*/
if (in_interrupt() || !mm)
if (in_atomic() || !mm)
goto no_context;
down_read(&mm->mmap_sem);
......@@ -79,7 +79,7 @@ ia64_do_page_fault (unsigned long address, unsigned long isr, struct pt_regs *re
# if (((1 << VM_READ_BIT) != VM_READ || (1 << VM_WRITE_BIT) != VM_WRITE) \
|| (1 << VM_EXEC_BIT) != VM_EXEC)
# error File is out of sync with <linux/mm.h>. Pleaes update.
# error File is out of sync with <linux/mm.h>. Please update.
# endif
mask = ( (((isr >> IA64_ISR_X_BIT) & 1UL) << VM_EXEC_BIT)
......
......@@ -19,6 +19,8 @@
#include <linux/sysctl.h>
#define TASK_HPAGE_BASE (REGION_HPAGE << REGION_SHIFT)
static long htlbpagemem;
int htlbpage_max;
static long htlbzone_pages;
......@@ -98,7 +100,6 @@ set_huge_pte (struct mm_struct *mm, struct vm_area_struct *vma,
set_pte(page_table, entry);
return;
}
/*
* This function checks for proper alignment of input addr and len parameters.
*/
......@@ -108,6 +109,20 @@ int is_aligned_hugepage_range(unsigned long addr, unsigned long len)
return -EINVAL;
if (addr & ~HPAGE_MASK)
return -EINVAL;
if (REGION_NUMBER(addr) != REGION_HPAGE)
return -EINVAL;
return 0;
}
/* This function checks if the address and address+len falls out of HugeTLB region. It
* return -EINVAL if any part of address range falls in HugeTLB region.
*/
int is_invalid_hugepage_range(unsigned long addr, unsigned long len)
{
if (REGION_NUMBER(addr) == REGION_HPAGE)
return -EINVAL;
if (REGION_NUMBER(addr+len) == REGION_HPAGE)
return -EINVAL;
return 0;
}
......@@ -173,6 +188,39 @@ follow_hugetlb_page(struct mm_struct *mm, struct vm_area_struct *vma,
return i;
}
struct vm_area_struct *hugepage_vma(struct mm_struct *mm, unsigned long addr)
{
if (mm->used_hugetlb) {
if (REGION_NUMBER(addr) == REGION_HPAGE) {
struct vm_area_struct *vma = find_vma(mm, addr);
if (vma && is_vm_hugetlb_page(vma))
return vma;
}
}
return NULL;
}
struct page *follow_huge_addr(struct mm_struct *mm, struct vm_area_struct *vma, unsigned long addr, int write)
{
struct page *page;
pte_t *ptep;
ptep = huge_pte_offset(mm, addr);
page = pte_page(*ptep);
page += ((addr & ~HPAGE_MASK) >> PAGE_SHIFT);
get_page(page);
return page;
}
int pmd_huge(pmd_t pmd)
{
return 0;
}
struct page *
follow_huge_pmd(struct mm_struct *mm, unsigned long address, pmd_t *pmd, int write)
{
return NULL;
}
void free_huge_page(struct page *page)
{
BUG_ON(page_count(page));
......@@ -204,8 +252,6 @@ void unmap_hugepage_range(struct vm_area_struct *vma, unsigned long start, unsig
BUG_ON(start & (HPAGE_SIZE - 1));
BUG_ON(end & (HPAGE_SIZE - 1));
spin_lock(&htlbpage_lock);
spin_unlock(&htlbpage_lock);
for (address = start; address < end; address += HPAGE_SIZE) {
pte = huge_pte_offset(mm, address);
if (pte_none(*pte))
......@@ -257,8 +303,12 @@ int hugetlb_prefault(struct address_space *mapping, struct vm_area_struct *vma)
ret = -ENOMEM;
goto out;
}
add_to_page_cache(page, mapping, idx, GFP_ATOMIC);
ret = add_to_page_cache(page, mapping, idx, GFP_ATOMIC);
unlock_page(page);
if (ret) {
free_huge_page(page);
goto out;
}
}
set_huge_pte(mm, vma, page, pte, vma->vm_flags & VM_WRITE);
}
......@@ -267,6 +317,29 @@ int hugetlb_prefault(struct address_space *mapping, struct vm_area_struct *vma)
return ret;
}
unsigned long hugetlb_get_unmapped_area(struct file *file, unsigned long addr, unsigned long len,
unsigned long pgoff, unsigned long flags)
{
struct vm_area_struct *vmm;
if (len > RGN_MAP_LIMIT)
return -ENOMEM;
if (len & ~HPAGE_MASK)
return -EINVAL;
/* This code assumes that REGION_HPAGE != 0. */
if ((REGION_NUMBER(addr) != REGION_HPAGE) || (addr & (HPAGE_SIZE - 1)))
addr = TASK_HPAGE_BASE;
else
addr = ALIGN(addr, HPAGE_SIZE);
for (vmm = find_vma(current->mm, addr); ; vmm = vmm->vm_next) {
/* At this point: (!vmm || addr < vmm->vm_end). */
if (REGION_OFFSET(addr) + len > RGN_MAP_LIMIT)
return -ENOMEM;
if (!vmm || (addr + len) <= vmm->vm_start)
return addr;
addr = ALIGN(vmm->vm_end, HPAGE_SIZE);
}
}
void update_and_free_page(struct page *page)
{
int j;
......@@ -302,8 +375,8 @@ int try_to_free_low(int count)
break;
}
page = list_entry(p, struct page, list);
if ((page_zone(page))->name[0] != 'H') // Look for non-Highmem
map = page;
if (!PageHighMem(page))
map = page;
}
if (map) {
list_del(&map->list);
......@@ -317,8 +390,8 @@ int try_to_free_low(int count)
int set_hugetlb_mem_size(int count)
{
int j, lcount;
struct page *page, *map;
int lcount;
struct page *page ;
extern long htlbzone_pages;
extern struct list_head htlbpage_freelist;
......@@ -417,5 +490,4 @@ static struct page *hugetlb_nopage(struct vm_area_struct * area, unsigned long a
struct vm_operations_struct hugetlb_vm_ops = {
.nopage = hugetlb_nopage,
.close = zap_hugetlb_resources,
};
......@@ -81,9 +81,13 @@ wrap_mmu_context (struct mm_struct *mm)
}
read_unlock(&tasklist_lock);
/* can't call flush_tlb_all() here because of race condition with O(1) scheduler [EF] */
for (i = 0; i < NR_CPUS; ++i)
if (i != smp_processor_id())
per_cpu(ia64_need_tlb_flush, i) = 1;
{
int cpu = get_cpu(); /* prevent preemption/migration */
for (i = 0; i < NR_CPUS; ++i)
if (i != cpu)
per_cpu(ia64_need_tlb_flush, i) = 1;
put_cpu();
}
local_flush_tlb_all();
}
......
......@@ -272,3 +272,76 @@ pci_mmap_page_range (struct pci_dev *dev, struct vm_area_struct *vma,
return 0;
}
/**
* pci_cacheline_size - determine cacheline size for PCI devices
* @dev: void
*
* We want to use the line-size of the outer-most cache. We assume
* that this line-size is the same for all CPUs.
*
* Code mostly taken from arch/ia64/kernel/palinfo.c:cache_info().
*
* RETURNS: An appropriate -ERRNO error value on eror, or zero for success.
*/
static unsigned long
pci_cacheline_size (void)
{
u64 levels, unique_caches;
s64 status;
pal_cache_config_info_t cci;
static u8 cacheline_size;
if (cacheline_size)
return cacheline_size;
status = ia64_pal_cache_summary(&levels, &unique_caches);
if (status != 0) {
printk(KERN_ERR "%s: ia64_pal_cache_summary() failed (status=%ld)\n",
__FUNCTION__, status);
return SMP_CACHE_BYTES;
}
status = ia64_pal_cache_config_info(levels - 1, /* cache_type (data_or_unified)= */ 2,
&cci);
if (status != 0) {
printk(KERN_ERR "%s: ia64_pal_cache_config_info() failed (status=%ld)\n",
__FUNCTION__, status);
return SMP_CACHE_BYTES;
}
cacheline_size = 1 << cci.pcci_line_size;
return cacheline_size;
}
/**
* pcibios_prep_mwi - helper function for drivers/pci/pci.c:pci_set_mwi()
* @dev: the PCI device for which MWI is enabled
*
* For ia64, we can get the cacheline sizes from PAL.
*
* RETURNS: An appropriate -ERRNO error value on eror, or zero for success.
*/
int
pcibios_prep_mwi (struct pci_dev *dev)
{
unsigned long desired_linesize, current_linesize;
int rc = 0;
u8 pci_linesize;
desired_linesize = pci_cacheline_size();
pci_read_config_byte(dev, PCI_CACHE_LINE_SIZE, &pci_linesize);
current_linesize = 4 * pci_linesize;
if (desired_linesize != current_linesize) {
printk(KERN_WARNING "PCI: slot %s has incorrect PCI cache line size of %lu bytes,",
dev->slot_name, current_linesize);
if (current_linesize > desired_linesize) {
printk(" expected %lu bytes instead\n", desired_linesize);
rc = -EINVAL;
} else {
printk(" correcting to %lu\n", desired_linesize);
pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, desired_linesize / 4);
}
}
return rc;
}
......@@ -17,6 +17,6 @@ obj-$(CONFIG_IA64_SGI_SN) += stubs.o sgi_if.o xswitch.o klgraph_hack.o \
hcl.o labelcl.o invent.o sgi_io_sim.o \
klgraph_hack.o hcl_util.o cdl.o hubdev.o hubspc.o \
alenlist.o pci.o pci_dma.o ate_utils.o \
ifconfig_net.o io.o ifconfig_bus.o
ifconfig_net.o io.o ioconfig_bus.o
obj-$(CONFIG_PCIBA) += pciba.o
/* $Id$
*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*
* ioconfig_bus - SGI's Persistent PCI Bus Numbering.
*
* Copyright (C) 1992-1997, 2000-2003 Silicon Graphics, Inc. All rights reserved.
*/
#include <linux/types.h>
#include <linux/slab.h>
#include <linux/ctype.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/pci.h>
#include <asm/sn/sgi.h>
#include <linux/devfs_fs.h>
#include <linux/devfs_fs_kernel.h>
#include <asm/io.h>
#include <asm/sn/iograph.h>
#include <asm/sn/invent.h>
#include <asm/sn/hcl.h>
#include <asm/sn/labelcl.h>
#include <asm//sn/sn_sal.h>
#include <asm/sn/addrs.h>
#include <asm/sn/ioconfig_bus.h>
#define SGI_IOCONFIG_BUS "SGI-PERSISTENT PCI BUS NUMBERING"
#define SGI_IOCONFIG_BUS_VERSION "1.0"
/*
* Some Global definitions.
*/
devfs_handle_t ioconfig_bus_handle = NULL;
unsigned long ioconfig_bus_debug = 0;
#ifdef IOCONFIG_BUS_DEBUG
#define DBG(x...) printk(x)
#else
#define DBG(x...)
#endif
u64 ioconfig_file = 0;
u64 ioconfig_file_size = 0;
u64 ioconfig_activated = 0;
char ioconfig_kernopts[128];
/*
* For debugging purpose .. hardcode a table ..
*/
struct ascii_moduleid *ioconfig_bus_table;
u64 ioconfig_bus_table_size = 0;
int free_entry = 0;
int new_entry = 0;
int next_basebus_number = 0;
void
ioconfig_get_busnum(char *io_moduleid, int *bus_num)
{
struct ascii_moduleid *temp;
int index;
DBG("ioconfig_get_busnum io_moduleid %s\n", io_moduleid);
*bus_num = -1;
temp = ioconfig_bus_table;
for (index = 0; index < free_entry; temp++, index++) {
if ( (io_moduleid[0] == temp->io_moduleid[0]) &&
(io_moduleid[1] == temp->io_moduleid[1]) &&
(io_moduleid[2] == temp->io_moduleid[2]) &&
(io_moduleid[4] == temp->io_moduleid[4]) &&
(io_moduleid[5] == temp->io_moduleid[5]) ) {
*bus_num = index * 0x10;
return;
}
}
/*
* New IO Brick encountered.
*/
if (((int)io_moduleid[0]) == 0) {
DBG("ioconfig_get_busnum: Invalid Module Id given %s\n", io_moduleid);
return;
}
io_moduleid[3] = '#';
strcpy((char *)&(ioconfig_bus_table[free_entry].io_moduleid), io_moduleid);
*bus_num = free_entry * 0x10;
free_entry++;
}
void
dump_ioconfig_table()
{
int index = 0;
struct ascii_moduleid *temp;
temp = ioconfig_bus_table;
while (index < free_entry) {
DBG("ASSCI Module ID %s\n", temp->io_moduleid);
temp++;
index++;
}
}
/*
* nextline
* This routine returns the nextline in the buffer.
*/
int nextline(char *buffer, char **next, char *line)
{
char *temp;
if (buffer[0] == 0x0) {
return(0);
}
temp = buffer;
while (*temp != 0) {
*line = *temp;
if (*temp != '\n'){
*line = *temp;
temp++; line++;
} else
break;
}
if (*temp == 0)
*next = temp;
else
*next = ++temp;
return(1);
}
/*
* build_pcibus_name
* This routine parses the ioconfig contents read into
* memory by ioconfig command in EFI and builds the
* persistent pci bus naming table.
*/
void
build_moduleid_table(char *file_contents, struct ascii_moduleid *table)
{
/*
* Read the whole file into memory.
*/
int rc;
char *name;
char *temp;
char *next;
char *current;
char *line;
struct ascii_moduleid *moduleid;
line = kmalloc(256, GFP_KERNEL);
memset(line, 0,256);
name = kmalloc(125, GFP_KERNEL);
memset(name, 0, 125);
moduleid = table;
current = file_contents;
while (nextline(current, &next, line)){
DBG("current 0x%lx next 0x%lx\n", current, next);
temp = line;
/*
* Skip all leading Blank lines ..
*/
while (isspace(*temp))
if (*temp != '\n')
temp++;
else
break;
if (*temp == '\n') {
current = next;
memset(line, 0, 256);
continue;
}
/*
* Skip comment lines
*/
if (*temp == '#') {
current = next;
memset(line, 0, 256);
continue;
}
/*
* Get the next free entry in the table.
*/
rc = sscanf(temp, "%s", name);
strcpy(&moduleid->io_moduleid[0], name);
DBG("Found %s\n", name);
moduleid++;
free_entry++;
current = next;
memset(line, 0, 256);
}
new_entry = free_entry;
kfree(line);
kfree(name);
return;
}
void
ioconfig_bus_init(void)
{
struct ia64_sal_retval ret_stuff;
u64 *temp;
int cnode;
DBG("ioconfig_bus_init called.\n");
for (cnode = 0; cnode < numnodes; cnode++) {
nasid_t nasid;
/*
* Make SAL call to get the address of the bus configuration table.
*/
ret_stuff.status = (uint64_t)0;
ret_stuff.v0 = (uint64_t)0;
ret_stuff.v1 = (uint64_t)0;
ret_stuff.v2 = (uint64_t)0;
nasid = COMPACT_TO_NASID_NODEID(cnode);
SAL_CALL(ret_stuff, SN_SAL_BUS_CONFIG, 0, nasid, 0, 0, 0, 0, 0);
temp = (u64 *)TO_NODE_CAC(nasid, ret_stuff.v0);
ioconfig_file = *temp;
DBG("ioconfig_bus_init: Nasid %d ret_stuff.v0 0x%lx\n", nasid,
ret_stuff.v0);
if (ioconfig_file) {
ioconfig_file_size = ret_stuff.v1;
ioconfig_file = (ioconfig_file | CACHEABLE_MEM_SPACE);
ioconfig_activated = 1;
break;
}
}
DBG("ioconfig_bus_init: ret_stuff.v0 %p ioconfig_file %p %d\n",
ret_stuff.v0, (void *)ioconfig_file, (int)ioconfig_file_size);
ioconfig_bus_table = kmalloc( 512, GFP_KERNEL );
memset(ioconfig_bus_table, 0, 512);
/*
* If ioconfig options are given on the bootline .. take it.
*/
if (*ioconfig_kernopts != '\0') {
/*
* ioconfig="..." kernel options given.
*/
DBG("ioconfig_bus_init: Kernel Options given.\n");
(void) build_moduleid_table((char *)ioconfig_kernopts, ioconfig_bus_table);
(void) dump_ioconfig_table(ioconfig_bus_table);
return;
}
if (ioconfig_activated) {
DBG("ioconfig_bus_init: ioconfig file given.\n");
(void) build_moduleid_table((char *)ioconfig_file, ioconfig_bus_table);
(void) dump_ioconfig_table(ioconfig_bus_table);
} else {
DBG("ioconfig_bus_init: ioconfig command not executed in prom\n");
}
}
void
ioconfig_bus_new_entries(void)
{
int index = 0;
struct ascii_moduleid *temp;
if ((ioconfig_activated) && (free_entry > new_entry)) {
printk("### Please add the following new IO Bricks Module ID \n");
printk("### to your Persistent Bus Numbering Config File\n");
} else
return;
index = new_entry;
temp = &ioconfig_bus_table[index];
while (index < free_entry) {
printk("%s\n", temp);
temp++;
index++;
}
printk("### End\n");
}
static int ioconfig_bus_ioctl(struct inode * inode, struct file * file,
unsigned int cmd, unsigned long arg)
{
struct ioconfig_parm parm;
/*
* Copy in the parameters.
*/
copy_from_user(&parm, (char *)arg, sizeof(struct ioconfig_parm));
parm.number = free_entry - new_entry;
parm.ioconfig_activated = ioconfig_activated;
copy_to_user((char *)arg, &parm, sizeof(struct ioconfig_parm));
copy_to_user((char *)parm.buffer, &ioconfig_bus_table[new_entry], sizeof(struct ascii_moduleid) * (free_entry - new_entry));
return 0;
}
/*
* ioconfig_bus_open - Opens the special device node "/dev/hw/.ioconfig_bus".
*/
static int ioconfig_bus_open(struct inode * inode, struct file * filp)
{
if (ioconfig_bus_debug) {
DBG("ioconfig_bus_open called.\n");
}
return(0);
}
/*
* ioconfig_bus_close - Closes the special device node "/dev/hw/.ioconfig_bus".
*/
static int ioconfig_bus_close(struct inode * inode, struct file * filp)
{
if (ioconfig_bus_debug) {
DBG("ioconfig_bus_close called.\n");
}
return(0);
}
struct file_operations ioconfig_bus_fops = {
ioctl:ioconfig_bus_ioctl,
open:ioconfig_bus_open, /* open */
release:ioconfig_bus_close /* release */
};
/*
* init_ifconfig_bus() - Boot time initialization. Ensure that it is called
* after devfs has been initialized.
*
*/
int init_ioconfig_bus(void)
{
ioconfig_bus_handle = NULL;
ioconfig_bus_handle = hwgraph_register(hwgraph_root, ".ioconfig_bus",
0, DEVFS_FL_AUTO_DEVNUM,
0, 0,
S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP, 0, 0,
&ioconfig_bus_fops, NULL);
if (ioconfig_bus_handle == NULL) {
panic("Unable to create SGI PERSISTENT BUS NUMBERING Driver.\n");
}
return(0);
}
static int __init ioconfig_bus_setup (char *str)
{
char *temp;
DBG("ioconfig_bus_setup: Kernel Options %s\n", str);
temp = (char *)ioconfig_kernopts;
memset(temp, 0, 128);
while ( (*str != '\0') && !isspace (*str) ) {
if (*str == ',') {
*temp = '\n';
temp++;
str++;
continue;
}
*temp = *str;
temp++;
str++;
}
return(0);
}
__setup("ioconfig=", ioconfig_bus_setup);
#
# This file is subject to the terms and conditions of the GNU General Public
# License. See the file "COPYING" in the main directory of this archive
# for more details.
#
# Copyright (C) 2002-2003 Silicon Graphics, Inc. All Rights Reserved.
#
# Makefile for the sn2 specific io routines.
EXTRA_CFLAGS := -DLITTLE_ENDIAN
obj-y += bte_error.o geo_op.o klconflib.o klgraph.o l1.o \
l1_command.o ml_iograph.o ml_SN_init.o ml_SN_intr.o module.o \
pci_bus_cvlink.o pciio.o pic.o sgi_io_init.o shub.o shuberror.o \
shub_intr.o shubio.o xbow.o xtalk.o
obj-$(CONFIG_KDB) += kdba_io.o
obj-$(CONFIG_SHUB_1_0_SPECIFIC) += efi-rtc.o
/* $Id$
*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*
* Copyright (C) 1992 - 1997, 2000-2003 Silicon Graphics, Inc. All rights reserved.
*/
/*
* @doc file m:hwcfg
* DESCRIPTION:
*
* This file contains routines for manipulating and generating
* Geographic IDs. They are in a file by themself since they have
* no dependencies on other modules.
*
* ORIGIN:
*
* New for SN2
*/
#include <linux/types.h>
#include <linux/slab.h>
#include <linux/interrupt.h>
#include <asm/smp.h>
#include <asm/irq.h>
#include <asm/hw_irq.h>
#include <asm/sn/types.h>
#include <asm/sn/sgi.h>
#include <asm/sn/iograph.h>
#include <asm/sn/invent.h>
#include <asm/sn/hcl.h>
#include <asm/sn/labelcl.h>
#include <asm/sn/io.h>
#include <asm/sn/sn_private.h>
#include <asm/sn/klconfig.h>
#include <asm/sn/sn_cpuid.h>
#include <asm/sn/pci/pciio.h>
#include <asm/sn/pci/pcibr.h>
#include <asm/sn/xtalk/xtalk.h>
#include <asm/sn/pci/pcibr_private.h>
#include <asm/sn/intr.h>
#include <asm/sn/sn2/shub_mmr_t.h>
#include <asm/sn/sn2/shubio.h>
#include <asm/sal.h>
#include <asm/sn/sn_sal.h>
#include <asm/sn/module.h>
#include <asm/sn/geo.h>
/********** Global functions and data (visible outside the module) ***********/
/*
* @doc gf:geo_module
*
* moduleid_t geo_module(geoid_t g)
*
* DESCRIPTION:
*
* Return the moduleid component of a geoid.
*
* INTERNALS:
*
* Return INVALID_MODULE for an invalid geoid. Otherwise extract the
* moduleid from the structure, and return it.
*
* ORIGIN:
*
* New for SN2
*/
moduleid_t
geo_module(geoid_t g)
{
if (g.any.type == GEO_TYPE_INVALID)
return INVALID_MODULE;
else
return g.any.module;
}
/*
* @doc gf:geo_slab
*
* slabid_t geo_slab(geoid_t g)
*
* DESCRIPTION:
*
* Return the slabid component of a geoid.
*
* INTERNALS:
*
* Return INVALID_SLAB for an invalid geoid. Otherwise extract the
* slabid from the structure, and return it.
*
* ORIGIN:
*
* New for SN2
*/
slabid_t
geo_slab(geoid_t g)
{
if (g.any.type == GEO_TYPE_INVALID)
return INVALID_SLAB;
else
return g.any.slab;
}
/*
* @doc gf:geo_type
*
* geo_type_t geo_type(geoid_t g)
*
* DESCRIPTION:
*
* Return the type component of a geoid.
*
* INTERNALS:
*
* Extract the type from the structure, and return it.
*
* ORIGIN:
*
* New for SN2
*/
geo_type_t
geo_type(geoid_t g)
{
return g.any.type;
}
/*
* @doc gf:geo_valid
*
* int geo_valid(geoid_t g)
*
* DESCRIPTION:
*
* Return nonzero if g has a valid geoid type.
*
* INTERNALS:
*
* Test the type against GEO_TYPE_INVALID, and return the result.
*
* ORIGIN:
*
* New for SN2
*/
int
geo_valid(geoid_t g)
{
return g.any.type != GEO_TYPE_INVALID;
}
/*
* @doc gf:geo_cmp
*
* int geo_cmp(geoid_t g0, geoid_t g1)
*
* DESCRIPTION:
*
* Compare two geoid_t values, from the coarsest field to the finest.
* The comparison should be consistent with the physical locations of
* of the hardware named by the geoids.
*
* INTERNALS:
*
* First compare the module, then the slab, type, and type-specific fields.
*
* ORIGIN:
*
* New for SN2
*/
int
geo_cmp(geoid_t g0, geoid_t g1)
{
int rv;
/* Compare the common fields */
rv = MODULE_CMP(geo_module(g0), geo_module(g1));
if (rv != 0)
return rv;
rv = geo_slab(g0) - geo_slab(g1);
if (rv != 0)
return rv;
/* Within a slab, sort by type */
rv = geo_type(g0) - geo_type(g1);
if (rv != 0)
return rv;
switch(geo_type(g0)) {
case GEO_TYPE_CPU:
rv = g0.cpu.slice - g1.cpu.slice;
break;
case GEO_TYPE_IOCARD:
rv = g0.pcicard.bus - g1.pcicard.bus;
if (rv) break;
rv = SLOTNUM_GETSLOT(g0.pcicard.slot) -
SLOTNUM_GETSLOT(g1.pcicard.slot);
break;
case GEO_TYPE_MEM:
rv = g0.mem.membus - g1.mem.membus;
if (rv) break;
rv = g0.mem.memslot - g1.mem.memslot;
break;
default:
rv = 0;
}
return rv;
}
/*
* @doc gf:geo_new
*
* geoid_t geo_new(geo_type_t type, ...)
*
* DESCRIPTION:
*
* Generate a new geoid_t value of the given type from its components.
* Expected calling sequences:
* \@itemize \@bullet
* \@item
* \@code\{geo_new(GEO_TYPE_INVALID)\}
* \@item
* \@code\{geo_new(GEO_TYPE_MODULE, moduleid_t m)\}
* \@item
* \@code\{geo_new(GEO_TYPE_NODE, moduleid_t m, slabid_t s)\}
* \@item
* \@code\{geo_new(GEO_TYPE_RTR, moduleid_t m, slabid_t s)\}
* \@item
* \@code\{geo_new(GEO_TYPE_IOCNTL, moduleid_t m, slabid_t s)\}
* \@item
* \@code\{geo_new(GEO_TYPE_IOCARD, moduleid_t m, slabid_t s, char bus, slotid_t slot)\}
* \@item
* \@code\{geo_new(GEO_TYPE_CPU, moduleid_t m, slabid_t s, char slice)\}
* \@item
* \@code\{geo_new(GEO_TYPE_MEM, moduleid_t m, slabid_t s, char membus, char slot)\}
* \@end itemize
*
* Invalid types return a GEO_TYPE_INVALID geoid_t.
*
* INTERNALS:
*
* Use the type to determine which fields to expect. Write the fields into
* a new geoid_t and return it. Note: scalars smaller than an "int" are
* promoted to "int" by the "..." operator, so we need extra casts on "char",
* "slotid_t", and "slabid_t".
*
* ORIGIN:
*
* New for SN2
*/
geoid_t
geo_new(geo_type_t type, ...)
{
va_list al;
geoid_t g;
memset(&g, 0, sizeof(g));
va_start(al, type);
/* Make sure the type is sane */
if (type >= GEO_TYPE_MAX)
type = GEO_TYPE_INVALID;
g.any.type = type;
if (type == GEO_TYPE_INVALID)
goto done; /* invalid geoids have no components at all */
g.any.module = va_arg(al, moduleid_t);
if (type == GEO_TYPE_MODULE)
goto done;
g.any.slab = (slabid_t)va_arg(al, int);
/* Some types have additional components */
switch(type) {
case GEO_TYPE_CPU:
g.cpu.slice = (char)va_arg(al, int);
break;
case GEO_TYPE_IOCARD:
g.pcicard.bus = (char)va_arg(al, int);
g.pcicard.slot = (slotid_t)va_arg(al, int);
break;
case GEO_TYPE_MEM:
g.mem.membus = (char)va_arg(al, int);
g.mem.memslot = (char)va_arg(al, int);
break;
default:
break;
}
done:
va_end(al);
return g;
}
This diff is collapsed.
This diff is collapsed.
/* $Id$
*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*
* Copyright (C) 1992-1997, 2000-2003 Silicon Graphics, Inc. All rights reserved.
*/
/* In general, this file is organized in a hierarchy from lower-level
* to higher-level layers, as follows:
*
* UART routines
* Bedrock/L1 "PPP-like" protocol implementation
* System controller "message" interface (allows multiplexing
* of various kinds of requests and responses with
* console I/O)
* Console interface:
* "l1_cons", the glue that allows the L1 to act
* as the system console for the stdio libraries
*
* Routines making use of the system controller "message"-style interface
* can be found in l1_command.c.
*/
#include <linux/types.h>
#include <linux/config.h>
#include <linux/slab.h>
#include <linux/spinlock.h>
#include <linux/delay.h>
#include <asm/sn/sgi.h>
#include <asm/sn/io.h>
#include <asm/sn/iograph.h>
#include <asm/sn/invent.h>
#include <asm/sn/hcl.h>
#include <asm/sn/hcl_util.h>
#include <asm/sn/labelcl.h>
#include <asm/sn/eeprom.h>
#include <asm/sn/router.h>
#include <asm/sn/module.h>
#include <asm/sn/ksys/l1.h>
#include <asm/sn/nodepda.h>
#include <asm/sn/clksupport.h>
#include <asm/sn/sn_sal.h>
#include <asm/sn/sn_cpuid.h>
#include <asm/sn/uart16550.h>
#include <asm/sn/simulator.h>
#define UART_BAUD_RATE 57600
int
get_L1_baud(void)
{
return UART_BAUD_RATE;
}
/* Return the current interrupt level */
int
l1_get_intr_value( void )
{
return(0);
}
/* Disconnect the callup functions - throw away interrupts */
void
l1_unconnect_intr(void)
{
}
/* Set up uart interrupt handling for this node's uart */
void
l1_connect_intr(void *rx_notify, void *tx_notify)
{
#if 0
// Will need code here for sn2 - something like this
console_nodepda = NODEPDA(NASID_TO_COMPACT_NODEID(get_master_nasid());
intr_connect_level(console_nodepda->node_first_cpu,
SGI_UART_VECTOR, INTPEND0_MAXMASK,
dummy_intr_func);
request_irq(SGI_UART_VECTOR | (console_nodepda->node_first_cpu << 8),
intr_func, SA_INTERRUPT | SA_SHIRQ,
"l1_protocol_driver", (void *)sc);
#endif
}
/* These are functions to use from serial_in/out when in protocol
* mode to send and receive uart control regs. These are external
* interfaces into the protocol driver.
*/
void
l1_control_out(int offset, int value)
{
/* quietly ignore unless simulator */
if ( IS_RUNNING_ON_SIMULATOR() ) {
extern u64 master_node_bedrock_address;
if ( master_node_bedrock_address != (u64)0 ) {
writeb(value, (unsigned long)master_node_bedrock_address +
(offset<< 3));
}
return;
}
}
/* Console input exported interface. Return a register value. */
int
l1_control_in_polled(int offset)
{
static int l1_control_in_local(int);
return(l1_control_in_local(offset));
}
int
l1_control_in(int offset)
{
static int l1_control_in_local(int);
return(l1_control_in_local(offset));
}
static int
l1_control_in_local(int offset)
{
int sal_call_status = 0, input;
int ret = 0;
if ( IS_RUNNING_ON_SIMULATOR() ) {
extern u64 master_node_bedrock_address;
ret = readb((unsigned long)master_node_bedrock_address +
(offset<< 3));
return(ret);
}
if ( offset == REG_LSR ) {
ret = (LSR_XHRE | LSR_XSRE); /* can send anytime */
sal_call_status = ia64_sn_console_check(&input);
if ( !sal_call_status && input ) {
/* input pending */
ret |= LSR_RCA;
}
}
return(ret);
}
/*
* Console input exported interface. Return a character (if one is available)
*/
int
l1_serial_in_polled(void)
{
static int l1_serial_in_local(void);
return(l1_serial_in_local());
}
int
l1_serial_in(void)
{
static int l1_serial_in_local(void);
if ( IS_RUNNING_ON_SIMULATOR() ) {
extern u64 master_node_bedrock_address;
return(readb((unsigned long)master_node_bedrock_address + (REG_DAT<< 3)));
}
return(l1_serial_in_local());
}
static int
l1_serial_in_local(void)
{
int ch;
if ( IS_RUNNING_ON_SIMULATOR() ) {
extern u64 master_node_bedrock_address;
return(readb((unsigned long)master_node_bedrock_address + (REG_DAT<< 3)));
}
if ( !(ia64_sn_console_getc(&ch)) )
return(ch);
else
return(0);
}
/* Console output exported interface. Write message to the console. */
int
l1_serial_out( char *str, int len )
{
int counter = len;
/* Ignore empty messages */
if ( len == 0 )
return(len);
#if defined(CONFIG_IA64_EARLY_PRINTK)
/* Need to setup SAL calls so the PROM calls will work */
{
static int inited;
void early_sn_setup(void);
if(!inited) {
inited=1;
early_sn_setup();
}
}
#endif
if ( IS_RUNNING_ON_SIMULATOR() ) {
extern u64 master_node_bedrock_address;
void early_sn_setup(void);
if (!master_node_bedrock_address)
early_sn_setup();
if ( master_node_bedrock_address != (u64)0 ) {
#ifdef FLAG_DIRECT_CONSOLE_WRITES
/* This is an easy way to pre-pend the output to know whether the output
* was done via sal or directly */
writeb('[', (unsigned long)master_node_bedrock_address + (REG_DAT<< 3));
writeb('+', (unsigned long)master_node_bedrock_address + (REG_DAT<< 3));
writeb(']', (unsigned long)master_node_bedrock_address + (REG_DAT<< 3));
writeb(' ', (unsigned long)master_node_bedrock_address + (REG_DAT<< 3));
#endif /* FLAG_DIRECT_CONSOLE_WRITES */
while ( counter > 0 ) {
writeb(*str, (unsigned long)master_node_bedrock_address + (REG_DAT<< 3));
counter--;
str++;
}
}
return(len);
}
/* Attempt to write things out thru the sal */
if ( ia64_sn_console_putb(str, len) )
return(0);
return((counter <= 0) ? 0 : (len - counter));
}
/* $Id$
*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*
* Copyright (c) 1992-1997,2000-2003 Silicon Graphics, Inc. All rights reserved.
*/
#include <linux/types.h>
#include <linux/slab.h>
#include <asm/sn/sgi.h>
#include <asm/sn/io.h>
#include <asm/sn/iograph.h>
#include <asm/sn/invent.h>
#include <asm/sn/hcl.h>
#include <asm/sn/hcl_util.h>
#include <asm/sn/labelcl.h>
#include <asm/sn/eeprom.h>
#include <asm/sn/router.h>
#include <asm/sn/module.h>
#include <asm/sn/ksys/l1.h>
#include <asm/sn/nodepda.h>
#include <asm/sn/clksupport.h>
#include <asm/sn/sn_cpuid.h>
#include <asm/sn/sn_sal.h>
#include <linux/ctype.h>
#define ELSC_TIMEOUT 1000000 /* ELSC response timeout (usec) */
#define LOCK_TIMEOUT 5000000 /* Hub lock timeout (usec) */
#define hub_cpu_get() 0
#define LBYTE(caddr) (*(char *) caddr)
extern char *bcopy(const char * src, char * dest, int count);
#define LDEBUG 0
/*
* ELSC data is in NVRAM page 7 at the following offsets.
*/
#define NVRAM_MAGIC_AD 0x700 /* magic number used for init */
#define NVRAM_PASS_WD 0x701 /* password (4 bytes in length) */
#define NVRAM_DBG1 0x705 /* virtual XOR debug switches */
#define NVRAM_DBG2 0x706 /* physical XOR debug switches */
#define NVRAM_CFG 0x707 /* ELSC Configuration info */
#define NVRAM_MODULE 0x708 /* system module number */
#define NVRAM_BIST_FLG 0x709 /* BIST flags (2 bits per nodeboard) */
#define NVRAM_PARTITION 0x70a /* module's partition id */
#define NVRAM_DOMAIN 0x70b /* module's domain id */
#define NVRAM_CLUSTER 0x70c /* module's cluster id */
#define NVRAM_CELL 0x70d /* module's cellid */
#define NVRAM_MAGIC_NO 0x37 /* value of magic number */
#define NVRAM_SIZE 16 /* 16 bytes in nvram */
/* elsc_display_line writes up to 12 characters to either the top or bottom
* line of the L1 display. line points to a buffer containing the message
* to be displayed. The zero-based line number is specified by lnum (so
* lnum == 0 specifies the top line and lnum == 1 specifies the bottom).
* Lines longer than 12 characters, or line numbers not less than
* L1_DISPLAY_LINES, cause elsc_display_line to return an error.
*/
int elsc_display_line(nasid_t nasid, char *line, int lnum)
{
return 0;
}
/*
* iobrick routines
*/
/* iobrick_rack_bay_type_get fills in the three int * arguments with the
* rack number, bay number and brick type of the L1 being addressed. Note
* that if the L1 operation fails and this function returns an error value,
* garbage may be written to brick_type.
*/
int iobrick_rack_bay_type_get( nasid_t nasid, uint *rack,
uint *bay, uint *brick_type )
{
int result = 0;
if ( ia64_sn_sysctl_iobrick_module_get(nasid, &result) )
return( ELSC_ERROR_CMD_SEND );
*rack = (result & L1_ADDR_RACK_MASK) >> L1_ADDR_RACK_SHFT;
*bay = (result & L1_ADDR_BAY_MASK) >> L1_ADDR_BAY_SHFT;
*brick_type = (result & L1_ADDR_TYPE_MASK) >> L1_ADDR_TYPE_SHFT;
*brick_type = toupper(*brick_type);
return 0;
}
int iomoduleid_get(nasid_t nasid)
{
int result = 0;
if ( ia64_sn_sysctl_iobrick_module_get(nasid, &result) )
return( ELSC_ERROR_CMD_SEND );
return result;
}
int iobrick_module_get(nasid_t nasid)
{
uint rnum, rack, bay, brick_type, t;
int ret;
/* construct module ID from rack and slot info */
if ((ret = iobrick_rack_bay_type_get(nasid, &rnum, &bay, &brick_type)) < 0)
return ret;
if (bay > MODULE_BPOS_MASK >> MODULE_BPOS_SHFT)
return ELSC_ERROR_MODULE;
/* Build a moduleid_t-compatible rack number */
rack = 0;
t = rnum / 100; /* rack class (CPU/IO) */
if (t > RACK_CLASS_MASK(rack) >> RACK_CLASS_SHFT(rack))
return ELSC_ERROR_MODULE;
RACK_ADD_CLASS(rack, t);
rnum %= 100;
t = rnum / 10; /* rack group */
if (t > RACK_GROUP_MASK(rack) >> RACK_GROUP_SHFT(rack))
return ELSC_ERROR_MODULE;
RACK_ADD_GROUP(rack, t);
t = rnum % 10; /* rack number (one-based) */
if (t-1 > RACK_NUM_MASK(rack) >> RACK_NUM_SHFT(rack))
return ELSC_ERROR_MODULE;
RACK_ADD_NUM(rack, t);
switch( brick_type ) {
case 'I':
brick_type = MODULE_IBRICK; break;
case 'P':
brick_type = MODULE_PBRICK; break;
case 'X':
brick_type = MODULE_XBRICK; break;
}
ret = RBT_TO_MODULE(rack, bay, brick_type);
return ret;
}
/*
* iobrick_module_get_nasid() returns a module_id which has the brick
* type encoded in bits 15-12, but this is not the true brick type...
* The module_id returned by iobrick_module_get_nasid() is modified
* to make a PEBRICKs & PXBRICKs look like a PBRICK. So this routine
* iobrick_type_get_nasid() returns the true unmodified brick type.
*/
int
iobrick_type_get_nasid(nasid_t nasid)
{
uint rack, bay, type;
int t, ret;
extern char brick_types[];
if ((ret = iobrick_rack_bay_type_get(nasid, &rack, &bay, &type)) < 0) {
return ret;
}
/* convert brick_type to lower case */
if ((type >= 'A') && (type <= 'Z'))
type = type - 'A' + 'a';
/* convert to a module.h brick type */
for( t = 0; t < MAX_BRICK_TYPES; t++ ) {
if( brick_types[t] == type )
return t;
}
return -1; /* unknown brick */
}
int iobrick_module_get_nasid(nasid_t nasid)
{
int io_moduleid;
#ifdef PIC_LATER
uint rack, bay;
if (PEBRICK_NODE(nasid)) {
if (peer_iobrick_rack_bay_get(nasid, &rack, &bay)) {
printf("Could not read rack and bay location "
"of PEBrick at nasid %d\n", nasid);
}
io_moduleid = peer_iobrick_module_get(sc, rack, bay);
}
#endif /* PIC_LATER */
io_moduleid = iobrick_module_get(nasid);
return io_moduleid;
}
/* $Id$
*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*
* Copyright (C) 1992 - 1997, 2000-2003 Silicon Graphics, Inc. All rights reserved.
*/
#include <linux/types.h>
#include <linux/slab.h>
#include <linux/bootmem.h>
#include <asm/sn/sgi.h>
#include <asm/sn/io.h>
#include <asm/sn/iograph.h>
#include <asm/sn/invent.h>
#include <asm/sn/hcl.h>
#include <asm/sn/labelcl.h>
#include <asm/sn/sn_private.h>
#include <asm/sn/klconfig.h>
#include <asm/sn/sn_cpuid.h>
#include <asm/sn/snconfig.h>
extern int numcpus;
extern char arg_maxnodes[];
extern cpuid_t master_procid;
extern int hasmetarouter;
int maxcpus;
cpumask_t boot_cpumask;
hubreg_t region_mask = 0;
extern xwidgetnum_t hub_widget_id(nasid_t);
extern int valid_icache_reasons; /* Reasons to flush the icache */
extern int valid_dcache_reasons; /* Reasons to flush the dcache */
extern u_char miniroot;
extern volatile int need_utlbmiss_patch;
extern void iograph_early_init(void);
nasid_t master_nasid = INVALID_NASID; /* This is the partition master nasid */
nasid_t master_baseio_nasid = INVALID_NASID; /* This is the master base I/O nasid */
/*
* mlreset(void)
* very early machine reset - at this point NO interrupts have been
* enabled; nor is memory, tlb, p0, etc setup.
*
* slave is zero when mlreset is called for the master processor and
* is nonzero thereafter.
*/
void
mlreset(int slave)
{
/*
* We are the master cpu and node.
*/
master_nasid = get_nasid();
set_master_bridge_base();
/* We're the master processor */
master_procid = smp_processor_id();
master_nasid = cpuid_to_nasid(master_procid);
/*
* master_nasid we get back better be same as one from
* get_nasid()
*/
ASSERT_ALWAYS(master_nasid == get_nasid());
/* early initialization of iograph */
iograph_early_init();
/* Initialize Hub Pseudodriver Management */
hubdev_init();
}
/* XXX - Move the meat of this to intr.c ? */
/*
* Set up the platform-dependent fields in the nodepda.
*/
void init_platform_nodepda(nodepda_t *npda, cnodeid_t node)
{
hubinfo_t hubinfo;
extern void router_map_init(nodepda_t *);
extern void router_queue_init(nodepda_t *,cnodeid_t);
extern void intr_init_vecblk(nodepda_t *, cnodeid_t, int);
/* Allocate per-node platform-dependent data */
hubinfo = (hubinfo_t)alloc_bootmem_node(NODE_DATA(node), sizeof(struct hubinfo_s));
npda->pdinfo = (void *)hubinfo;
hubinfo->h_nodepda = npda;
hubinfo->h_cnodeid = node;
hubinfo->h_nasid = COMPACT_TO_NASID_NODEID(node);
spin_lock_init(&hubinfo->h_crblock);
hubinfo->h_widgetid = hub_widget_id(hubinfo->h_nasid);
npda->xbow_peer = INVALID_NASID;
/*
* Initialize the linked list of
* router info pointers to the dependent routers
*/
npda->npda_rip_first = NULL;
/*
* npda_rip_last always points to the place
* where the next element is to be inserted
* into the list
*/
npda->npda_rip_last = &npda->npda_rip_first;
npda->geoid.any.type = GEO_TYPE_INVALID;
mutex_init_locked(&npda->xbow_sema); /* init it locked? */
}
/* XXX - Move the interrupt stuff to intr.c ? */
/*
* Set up the platform-dependent fields in the processor pda.
* Must be done _after_ init_platform_nodepda().
* If we need a lock here, something else is wrong!
*/
void init_platform_pda(cpuid_t cpu)
{
}
void
update_node_information(cnodeid_t cnodeid)
{
nodepda_t *npda = NODEPDA(cnodeid);
nodepda_router_info_t *npda_rip;
/* Go through the list of router info
* structures and copy some frequently
* accessed info from the info hanging
* off the corresponding router vertices
*/
npda_rip = npda->npda_rip_first;
while(npda_rip) {
if (npda_rip->router_infop) {
npda_rip->router_portmask =
npda_rip->router_infop->ri_portmask;
npda_rip->router_slot =
npda_rip->router_infop->ri_slotnum;
} else {
/* No router, no ports. */
npda_rip->router_portmask = 0;
}
npda_rip = npda_rip->router_next;
}
}
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
#
# This file is subject to the terms and conditions of the GNU General Public
# License. See the file "COPYING" in the main directory of this archive
# for more details.
#
# Copyright (C) 2002-2003 Silicon Graphics, Inc. All Rights Reserved.
#
# Makefile for the sn2 specific pci bridge routines.
EXTRA_CFLAGS := -DLITTLE_ENDIAN
ifdef CONFIG_IA64_SGI_SN2
EXTRA_CFLAGS += -DSHUB_SWAP_WAR
endif
obj-$(CONFIG_IA64_SGI_SN2) += pcibr_dvr.o pcibr_ate.o pcibr_config.o \
pcibr_dvr.o pcibr_hints.o \
pcibr_intr.o pcibr_rrb.o pcibr_slot.o \
pcibr_error.o
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
/*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*
* Copyright (C) 2000-2003 Silicon Graphics, Inc. All rights reserved.
*/
#include <asm/io.h>
#include <linux/module.h>
extern void * sn_io_addr(unsigned long port); /* defined in sn[12]/iomv.c */
/**
* sn_inb - read a byte from a port
* @port: port to read from
*
* Reads a byte from @port and returns it to the caller.
*/
unsigned int
sn_inb (unsigned long port)
{
volatile unsigned char *addr = sn_io_addr(port);
unsigned char ret;
ret = *addr;
__ia64_mf_a();
return ret;
}
/**
* sn_inw - read a word from a port
* @port: port to read from
*
* Reads a word from @port and returns it to the caller.
*/
unsigned int
sn_inw (unsigned long port)
{
volatile unsigned short *addr = sn_io_addr(port);
unsigned short ret;
ret = *addr;
__ia64_mf_a();
return ret;
}
/**
* sn_inl - read a word from a port
* @port: port to read from
*
* Reads a word from @port and returns it to the caller.
*/
unsigned int
sn_inl (unsigned long port)
{
volatile unsigned int *addr = sn_io_addr(port);
unsigned int ret;
ret = *addr;
__ia64_mf_a();
return ret;
}
/**
* sn_outb - write a byte to a port
* @port: port to write to
* @val: value to write
*
* Writes @val to @port.
*/
void
sn_outb (unsigned char val, unsigned long port)
{
volatile unsigned char *addr = sn_io_addr(port);
*addr = val;
}
/**
* sn_outw - write a word to a port
* @port: port to write to
* @val: value to write
*
* Writes @val to @port.
*/
void
sn_outw (unsigned short val, unsigned long port)
{
volatile unsigned short *addr = sn_io_addr(port);
*addr = val;
}
/**
* sn_outl - write a word to a port
* @port: port to write to
* @val: value to write
*
* Writes @val to @port.
*/
void
sn_outl (unsigned int val, unsigned long port)
{
volatile unsigned int *addr = sn_io_addr(port);
*addr = val;
}
EXPORT_SYMBOL(sn_inb);
EXPORT_SYMBOL(sn_inw);
EXPORT_SYMBOL(sn_inl);
EXPORT_SYMBOL(sn_outb);
EXPORT_SYMBOL(sn_outw);
EXPORT_SYMBOL(sn_outl);
......@@ -40,7 +40,10 @@
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/smp_lock.h>
#include <linux/acpi.h>
#ifdef CONFIG_KDB
#include <linux/kdb.h>
#endif
#include <asm/machvec.h>
#include <asm/page.h>
......@@ -53,7 +56,6 @@
#include <asm/irq.h>
#include <asm/hw_irq.h>
#include <asm/acpi-ext.h>
#include <asm/smp.h>
#include <asm/sn/sn_cpuid.h>
......
......@@ -267,7 +267,7 @@ sn_setup(char **cmdline_p)
/* PROM has wrong value on SN1 */
sn_rtc_cycles_per_second = 990177;
#endif
sn_rtc_usec_per_cyc = ((1000000UL<<IA64_USEC_PER_CYC_SHIFT)
sn_rtc_usec_per_cyc = ((1000000000UL<<IA64_NSEC_PER_CYC_SHIFT)
+ sn_rtc_cycles_per_second/2) / sn_rtc_cycles_per_second;
for (i=0;i<NR_CPUS;i++)
......
......@@ -32,5 +32,7 @@
# http://oss.sgi.com/projects/GenInfo/NoticeExplan
#
EXTRA_CFLAGS := -DLITTLE_ENDIAN
obj-y += cache.o iomv.o ptc_deadlock.o sn2_smp.o \
sn_proc_fs.o
This diff is collapsed.
This diff is collapsed.
......@@ -10,7 +10,7 @@
* gets translated into an assembly file which, in turn, is processed
* by awk to generate offsets.h. So if you make any changes to this
* file, be sure to verify that the awk procedure still works (see
* prin_offsets.awk).
* print_offsets.awk).
*/
#include <linux/config.h>
......@@ -170,6 +170,12 @@ tab[] =
/* for assembly files which can't include sched.h: */
{ "IA64_CLONE_VFORK", CLONE_VFORK },
{ "IA64_CLONE_VM", CLONE_VM },
/* used by fsys_gettimeofday in arch/ia64/kernel/fsys.S */
{ "IA64_CPUINFO_ITM_DELTA_OFFSET", offsetof (struct cpuinfo_ia64, itm_delta) },
{ "IA64_CPUINFO_ITM_NEXT_OFFSET", offsetof (struct cpuinfo_ia64, itm_next) },
{ "IA64_CPUINFO_NSEC_PER_CYC_OFFSET", offsetof (struct cpuinfo_ia64, nsec_per_cyc) },
{ "IA64_TIMESPEC_TV_NSEC_OFFSET", offsetof (struct timespec, tv_nsec) },
};
static const char *tabs = "\t\t\t\t\t\t\t\t\t\t";
......
......@@ -32,18 +32,18 @@
*
* - bits 0-7 are the preemption count (max preemption depth: 256)
* - bits 8-15 are the softirq count (max # of softirqs: 256)
* - bits 16-31 are the hardirq count (max # of hardirqs: 65536)
* - bits 16-29 are the hardirq count (max # of hardirqs: 16384)
*
* - (bit 63 is the PREEMPT_ACTIVE flag---not currently implemented.)
*
* PREEMPT_MASK: 0x000000ff
* SOFTIRQ_MASK: 0x0000ff00
* HARDIRQ_MASK: 0xffff0000
* HARDIRQ_MASK: 0x3fff0000
*/
#define PREEMPT_BITS 8
#define SOFTIRQ_BITS 8
#define HARDIRQ_BITS 16
#define HARDIRQ_BITS 14
#define PREEMPT_SHIFT 0
#define SOFTIRQ_SHIFT (PREEMPT_SHIFT + PREEMPT_BITS)
......@@ -83,13 +83,13 @@
#define hardirq_trylock() (!in_interrupt())
#define hardirq_endlock() do { } while (0)
#define in_atomic() (preempt_count() != 0)
#define irq_enter() (preempt_count() += HARDIRQ_OFFSET)
#if CONFIG_PREEMPT
# error CONFIG_PREEMT currently not supported.
# define in_atomic() ((preempt_count() & ~PREEMPT_ACTIVE) != kernel_locked())
# define IRQ_EXIT_OFFSET (HARDIRQ_OFFSET-1)
#else
# define in_atomic() (preempt_count() != 0)
# define IRQ_EXIT_OFFSET HARDIRQ_OFFSET
#endif
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
......@@ -3,8 +3,6 @@
extern ia64_mv_setup_t dig_setup;
extern ia64_mv_irq_init_t dig_irq_init;
extern ia64_mv_pci_fixup_t iosapic_pci_fixup;
extern ia64_mv_map_nr_t map_nr_dense;
/*
* This stuff has dual use!
......
......@@ -3,7 +3,6 @@
extern ia64_mv_setup_t hpsim_setup;
extern ia64_mv_irq_init_t hpsim_irq_init;
extern ia64_mv_map_nr_t map_nr_dense;
/*
* This stuff has dual use!
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
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