Commit b38743e0 authored by David Mosberger's avatar David Mosberger

Merge tiger.hpl.hp.com:/data1/bk/vanilla/linux-2.5

into tiger.hpl.hp.com:/data1/bk/lia64/to-linus-2.5
parents 4eabfbb6 402b94c8
......@@ -47,8 +47,10 @@
/*
** This option allows cards capable of 64bit DMA to bypass the IOMMU. If
** not defined, all DMA will be 32bit and go through the TLB.
** There's potentially a conflict in the bio merge code with us
** advertising an iommu, but then bypassing it. Disabled for now.
*/
#define ALLOW_IOV_BYPASS
#undef ALLOW_IOV_BYPASS
/*
** If a device prefetches beyond the end of a valid pdir entry, it will cause
......
......@@ -39,7 +39,7 @@ hpsim_irq_init (void)
int i;
for (i = 0; i < NR_IRQS; ++i) {
idesc = irq_desc(i);
idesc = irq_descp(i);
if (idesc->handler == &no_irq_type)
idesc->handler = &irq_type_hp_sim;
}
......
......@@ -350,6 +350,7 @@ simscsi_queuecommand (Scsi_Cmnd *sc, void (*done)(Scsi_Cmnd *))
break;
case MODE_SENSE:
case MODE_SENSE_10:
/* sd.c uses this to determine whether disk does write-caching. */
memset(sc->request_buffer, 0, 128);
sc->result = GOOD;
......
......@@ -420,7 +420,12 @@ ia32_do_mmap (struct file *file, unsigned long addr, unsigned long len, int prot
return addr;
if (len > IA32_PAGE_OFFSET || addr > IA32_PAGE_OFFSET - len)
{
if (flags & MAP_FIXED)
return -ENOMEM;
else
return -EINVAL;
}
if (OFFSET4K(offset))
return -EINVAL;
......@@ -519,7 +524,7 @@ sys32_munmap (unsigned int start, unsigned int len)
#if PAGE_SHIFT <= IA32_PAGE_SHIFT
ret = sys_munmap(start, end - start);
#else
if (start > end)
if (start >= end)
return -EINVAL;
start = PAGE_ALIGN(start);
......@@ -1275,7 +1280,7 @@ semctl32 (int first, int second, int third, void *uptr)
static int
do_sys32_msgsnd (int first, int second, int third, void *uptr)
{
struct msgbuf *p = kmalloc(second + sizeof(struct msgbuf) + 4, GFP_USER);
struct msgbuf *p = kmalloc(second + sizeof(struct msgbuf), GFP_USER);
struct msgbuf32 *up = (struct msgbuf32 *)uptr;
mm_segment_t old_fs;
int err;
......@@ -1317,12 +1322,12 @@ do_sys32_msgrcv (int first, int second, int msgtyp, int third, int version, void
msgtyp = ipck.msgtyp;
}
err = -ENOMEM;
p = kmalloc(second + sizeof(struct msgbuf) + 4, GFP_USER);
p = kmalloc(second + sizeof(struct msgbuf), GFP_USER);
if (!p)
goto out;
old_fs = get_fs();
set_fs(KERNEL_DS);
err = sys_msgrcv(first, p, second + 4, msgtyp, third);
err = sys_msgrcv(first, p, second, msgtyp, third);
set_fs(old_fs);
if (err < 0)
goto free_then_out;
......@@ -2542,13 +2547,31 @@ asmlinkage long
sys32_sysinfo (struct sysinfo32 *info)
{
extern asmlinkage long sys_sysinfo (struct sysinfo *);
mm_segment_t old_fs = get_fs();
struct sysinfo s;
long ret, err;
int bitcount = 0;
mm_segment_t old_fs = get_fs();
set_fs(KERNEL_DS);
ret = sys_sysinfo(&s);
set_fs(old_fs);
/* Check to see if any memory value is too large for 32-bit and
* scale down if needed.
*/
if ((s.totalram >> 32) || (s.totalswap >> 32)) {
while (s.mem_unit < PAGE_SIZE) {
s.mem_unit <<= 1;
bitcount++;
}
s.totalram >>= bitcount;
s.freeram >>= bitcount;
s.sharedram >>= bitcount;
s.bufferram >>= bitcount;
s.totalswap >>= bitcount;
s.freeswap >>= bitcount;
s.totalhigh >>= bitcount;
s.freehigh >>= bitcount;
}
if (!access_ok(VERIFY_WRITE, info, sizeof(*info)))
return -EFAULT;
......
......@@ -199,13 +199,15 @@ ia64_decrement_ip (struct pt_regs *regs)
* rnat0/rnat1 gets its value from sw->ar_rnat.
*/
static unsigned long
get_rnat (struct pt_regs *pt, struct switch_stack *sw,
get_rnat (struct task_struct *task, struct switch_stack *sw,
unsigned long *krbs, unsigned long *urnat_addr, unsigned long *urbs_end)
{
unsigned long rnat0 = 0, rnat1 = 0, urnat = 0, *slot0_kaddr, umask = 0, mask, m;
unsigned long *kbsp, *ubspstore, *rnat0_kaddr, *rnat1_kaddr, shift;
long num_regs, nbits;
struct pt_regs *pt;
pt = ia64_task_regs(task);
kbsp = (unsigned long *) sw->ar_bspstore;
ubspstore = (unsigned long *) pt->ar_bspstore;
......@@ -254,21 +256,41 @@ get_rnat (struct pt_regs *pt, struct switch_stack *sw,
* The reverse of get_rnat.
*/
static void
put_rnat (struct pt_regs *pt, struct switch_stack *sw,
put_rnat (struct task_struct *task, struct switch_stack *sw,
unsigned long *krbs, unsigned long *urnat_addr, unsigned long urnat,
unsigned long *urbs_end)
{
unsigned long rnat0 = 0, rnat1 = 0, *slot0_kaddr, umask = 0, mask, m;
unsigned long *kbsp, *ubspstore, *rnat0_kaddr, *rnat1_kaddr, shift;
long num_regs, nbits;
struct pt_regs *pt;
unsigned long cfm, *urbs_kargs;
struct unw_frame_info info;
pt = ia64_task_regs(task);
kbsp = (unsigned long *) sw->ar_bspstore;
ubspstore = (unsigned long *) pt->ar_bspstore;
if (urbs_end < urnat_addr)
nbits = ia64_rse_num_regs(urnat_addr - 63, urbs_end);
else
urbs_kargs = urbs_end;
if ((long)pt->cr_ifs >= 0) {
/*
* If entered via syscall, don't allow user to set rnat bits
* for syscall args.
*/
unw_init_from_blocked_task(&info,task);
if (unw_unwind_to_user(&info) == 0) {
unw_get_cfm(&info,&cfm);
urbs_kargs = ia64_rse_skip_regs(urbs_end,-(cfm & 0x7f));
}
}
if (urbs_kargs >= urnat_addr)
nbits = 63;
else {
if ((urnat_addr - 63) >= urbs_kargs)
return;
nbits = ia64_rse_num_regs(urnat_addr - 63, urbs_kargs);
}
mask = (1UL << nbits) - 1;
/*
......@@ -339,7 +361,7 @@ ia64_peek (struct task_struct *child, struct switch_stack *child_stack, unsigned
* read the corresponding bits in the kernel RBS.
*/
rnat_addr = ia64_rse_rnat_addr(laddr);
ret = get_rnat(child_regs, child_stack, krbs, rnat_addr, urbs_end);
ret = get_rnat(child, child_stack, krbs, rnat_addr, urbs_end);
if (laddr == rnat_addr) {
/* return NaT collection word itself */
......@@ -390,7 +412,7 @@ ia64_poke (struct task_struct *child, struct switch_stack *child_stack, unsigned
* => write the corresponding bits in the kernel RBS.
*/
if (ia64_rse_is_rnat_slot(laddr))
put_rnat(child_regs, child_stack, krbs, laddr, val, urbs_end);
put_rnat(child, child_stack, krbs, laddr, val, urbs_end);
else {
if (laddr < urbs_end) {
regnum = ia64_rse_num_regs(bspstore, laddr);
......
......@@ -26,8 +26,9 @@ arch_get_unmapped_area (struct file *filp, unsigned long addr, unsigned long len
unsigned long pgoff, unsigned long flags)
{
long map_shared = (flags & MAP_SHARED);
unsigned long align_mask = PAGE_SIZE - 1;
struct vm_area_struct * vmm;
unsigned long start_addr, align_mask = PAGE_SIZE - 1;
struct mm_struct *mm = current->mm;
struct vm_area_struct *vma;
if (len > RGN_MAP_LIMIT)
return -ENOMEM;
......@@ -37,7 +38,7 @@ arch_get_unmapped_area (struct file *filp, unsigned long addr, unsigned long len
addr = 0;
#endif
if (!addr)
addr = TASK_UNMAPPED_BASE;
addr = mm->free_area_cache;
if (map_shared && (TASK_SIZE > 0xfffffffful))
/*
......@@ -48,17 +49,25 @@ arch_get_unmapped_area (struct file *filp, unsigned long addr, unsigned long len
*/
align_mask = SHMLBA - 1;
addr = (addr + align_mask) & ~align_mask;
full_search:
start_addr = addr = (addr + align_mask) & ~align_mask;
for (vmm = find_vma(current->mm, addr); ; vmm = vmm->vm_next) {
/* At this point: (!vmm || addr < vmm->vm_end). */
if (TASK_SIZE - len < addr)
return -ENOMEM;
if (REGION_OFFSET(addr) + len > RGN_MAP_LIMIT) /* no risk of overflow here... */
for (vma = find_vma(mm, addr); ; vma = vma->vm_next) {
/* At this point: (!vma || addr < vma->vm_end). */
if (TASK_SIZE - len < addr || RGN_MAP_LIMIT - len < REGION_OFFSET(addr)) {
if (start_addr != TASK_UNMAPPED_BASE) {
/* Start a new search --- just in case we missed some holes. */
addr = TASK_UNMAPPED_BASE;
goto full_search;
}
return -ENOMEM;
if (!vmm || addr + len <= vmm->vm_start)
}
if (!vma || addr + len <= vma->vm_start) {
/* Remember the address where we stopped this search: */
mm->free_area_cache = addr + len;
return addr;
addr = (vmm->vm_end + align_mask) & ~align_mask;
}
addr = (vma->vm_end + align_mask) & ~align_mask;
}
}
......
......@@ -58,15 +58,9 @@
#ifdef UNW_DEBUG
static unsigned int unw_debug_level = UNW_DEBUG;
# ifdef CONFIG_KDB
# include <linux/kdb.h>
# define UNW_DEBUG_ON(n) (unw_debug_level >= n && !KDB_IS_RUNNING())
# define UNW_DPRINT(n, ...) if (UNW_DEBUG_ON(n)) kdb_printf(__VA_ARGS__)
# else /* !CONFIG_KDB */
# define UNW_DEBUG_ON(n) unw_debug_level >= n
/* Do not code a printk level, not all debug lines end in newline */
# define UNW_DPRINT(n, ...) if (UNW_DEBUG_ON(n)) printk(__VA_ARGS__)
# endif /* CONFIG_KDB */
# define inline
#else /* !UNW_DEBUG */
# define UNW_DEBUG_ON(n) 0
......@@ -2124,7 +2118,7 @@ unw_remove_unwind_table (void *handle)
kfree(table);
}
static void __init
static int __init
create_gate_table (void)
{
const struct unw_table_entry *entry, *start, *end;
......@@ -2142,7 +2136,7 @@ create_gate_table (void)
if (!punw) {
printk("%s: failed to find gate DSO's unwind table!\n", __FUNCTION__);
return;
return 0;
}
start = (const struct unw_table_entry *) punw->p_vaddr;
......@@ -2159,7 +2153,7 @@ create_gate_table (void)
if (!unw.gate_table) {
unw.gate_table_size = 0;
printk(KERN_ERR "%s: unable to create unwind data for gate page!\n", __FUNCTION__);
return;
return 0;
}
unw.gate_table_size = size;
......@@ -2176,6 +2170,7 @@ create_gate_table (void)
lp[2] = info - (char *) unw.gate_table; /* info */
}
*lp = 0; /* end-of-table marker */
return 0;
}
__initcall(create_gate_table);
......
......@@ -121,7 +121,7 @@ ia64_init_addr_space (void)
vma = kmem_cache_alloc(vm_area_cachep, SLAB_KERNEL);
if (vma) {
vma->vm_mm = current->mm;
vma->vm_start = current->thread.rbs_bot;
vma->vm_start = current->thread.rbs_bot & PAGE_MASK;
vma->vm_end = vma->vm_start + PAGE_SIZE;
vma->vm_page_prot = protection_map[VM_DATA_DEFAULT_FLAGS & 0x7];
vma->vm_flags = VM_READ|VM_WRITE|VM_MAYREAD|VM_MAYWRITE|VM_GROWSUP;
......
......@@ -11,5 +11,5 @@
EXTRA_CFLAGS := -DLITTLE_ENDIAN
obj-y += sgi_if.o xswitch.o sgi_io_sim.o cdl.o ate_utils.o \
obj-y += sgi_if.o xswitch.o sgi_io_sim.o cdl.o \
io.o machvec/ drivers/ platform_init/ sn2/ hwgfs/
/* $Id: ate_utils.c,v 1.1 2002/02/28 17:31:25 marcelo Exp $
*
* 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/addrs.h>
#include <asm/sn/arch.h>
#include <asm/sn/iograph.h>
#include <asm/sn/invent.h>
#include <asm/sn/io.h>
#include <asm/sn/hcl.h>
#include <asm/sn/labelcl.h>
#include <asm/sn/xtalk/xwidget.h>
#include <asm/sn/pci/bridge.h>
#include <asm/sn/pci/pciio.h>
#include <asm/sn/pci/pcibr.h>
#include <asm/sn/pci/pcibr_private.h>
#include <asm/sn/pci/pci_defs.h>
#include <asm/sn/prio.h>
#include <asm/sn/ioerror_handling.h>
#include <asm/sn/xtalk/xbow.h>
#include <asm/sn/ioc3.h>
#include <asm/sn/sn_private.h>
#include <asm/sn/ate_utils.h>
/*
* Allocate the map needed to allocate the ATE entries.
*/
struct map *
atemapalloc(ulong_t mapsiz)
{
struct map *mp;
ulong_t size;
struct a {
spinlock_t lock;
sv_t sema;
} *sync;
if (mapsiz == 0)
return(NULL);
size = sizeof(struct map) * (mapsiz + 2);
if ((mp = (struct map *) kmalloc(size, GFP_KERNEL)) == NULL)
return(NULL);
memset(mp, 0x0, size);
sync = kmalloc(sizeof(struct a), GFP_KERNEL);
if (sync == NULL) {
kfree(mp);
return(NULL);
}
memset(sync, 0x0, sizeof(struct a));
mutex_spinlock_init(&sync->lock);
sv_init( &(sync->sema), &(sync->lock), SV_MON_SPIN | SV_ORDER_FIFO /*| SV_INTS*/);
mp[1].m_size = (unsigned long) &sync->lock;
mp[1].m_addr = (unsigned long) &sync->sema;
mapsize(mp) = mapsiz - 1;
return(mp);
}
/*
* free a map structure previously allocated via rmallocmap().
*/
void
atemapfree(struct map *mp)
{
struct a {
spinlock_t lock;
sv_t sema;
};
/* ASSERT(sv_waitq(mapout(mp)) == 0); */
/* sv_destroy(mapout(mp)); */
spin_lock_destroy(maplock(mp));
kfree((void *)mp[1].m_size);
kfree(mp);
}
/*
* Allocate 'size' units from the given map.
* Return the base of the allocated space.
* In a map, the addresses are increasing and the
* list is terminated by a 0 size.
* Algorithm is first-fit.
*/
ulong_t
atealloc(
struct map *mp,
size_t size)
{
register unsigned int a;
register struct map *bp;
register unsigned long s;
ASSERT(size >= 0);
if (size == 0)
return((ulong_t) NULL);
s = mutex_spinlock(maplock(mp));
for (bp = mapstart(mp); bp->m_size; bp++) {
if (bp->m_size >= size) {
a = bp->m_addr;
bp->m_addr += size;
if ((bp->m_size -= size) == 0) {
do {
bp++;
(bp-1)->m_addr = bp->m_addr;
} while ((((bp-1)->m_size) = (bp->m_size)));
mapsize(mp)++;
}
ASSERT(bp->m_size < 0x80000000);
mutex_spinunlock(maplock(mp), s);
return(a);
}
}
/*
* We did not get what we need .. we cannot sleep ..
*/
mutex_spinunlock(maplock(mp), s);
return(0);
}
/*
* Free the previously allocated space a of size units into the specified map.
* Sort ``a'' into map and combine on one or both ends if possible.
* Returns 0 on success, 1 on failure.
*/
void
atefree(struct map *mp, size_t size, ulong_t a)
{
register struct map *bp;
register unsigned int t;
register unsigned long s;
ASSERT(size >= 0);
if (size == 0)
return;
bp = mapstart(mp);
s = mutex_spinlock(maplock(mp));
for ( ; bp->m_addr<=a && bp->m_size!=0; bp++)
;
if (bp>mapstart(mp) && (bp-1)->m_addr+(bp-1)->m_size == a) {
(bp-1)->m_size += size;
if (bp->m_addr) {
/* m_addr==0 end of map table */
ASSERT(a+size <= bp->m_addr);
if (a+size == bp->m_addr) {
/* compress adjacent map addr entries */
(bp-1)->m_size += bp->m_size;
while (bp->m_size) {
bp++;
(bp-1)->m_addr = bp->m_addr;
(bp-1)->m_size = bp->m_size;
}
mapsize(mp)++;
}
}
} else {
if (a+size == bp->m_addr && bp->m_size) {
bp->m_addr -= size;
bp->m_size += size;
} else {
ASSERT(size);
if (mapsize(mp) == 0) {
mutex_spinunlock(maplock(mp), s);
printk("atefree : map overflow 0x%p Lost 0x%lx items at 0x%lx",
(void *)mp, size, a) ;
return ;
}
do {
t = bp->m_addr;
bp->m_addr = a;
a = t;
t = bp->m_size;
bp->m_size = size;
bp++;
} while ((size = t));
mapsize(mp)--;
}
}
mutex_spinunlock(maplock(mp), s);
/*
* wake up everyone waiting for space
*/
if (mapout(mp))
;
/* sv_broadcast(mapout(mp)); */
}
......@@ -190,7 +190,7 @@ static int hwgfs_fill_super(struct super_block * sb, void * data, int silent)
}
static struct super_block *hwgfs_get_sb(struct file_system_type *fs_type,
int flags, char *dev_name, void *data)
int flags, const char *dev_name, void *data)
{
return get_sb_single(fs_type, flags, data, hwgfs_fill_super);
}
......
......@@ -26,8 +26,12 @@ void *
sn_io_addr(unsigned long port)
{
if (!IS_RUNNING_ON_SIMULATOR()) {
/* On sn2, legacy I/O ports don't point at anything */
if (port < 64*1024)
return 0;
return( (void *) (port | __IA64_UNCACHED_OFFSET));
} else {
/* but the simulator uses them... */
unsigned long io_base;
unsigned long addr;
......
......@@ -153,8 +153,7 @@ sn_pci_alloc_consistent(struct pci_dev *hwdev, size_t size, dma_addr_t *dma_hand
*dma_handle = 0;
/* We can't easily support < 32 bit devices */
if (IS_PCI32L(hwdev))
if (hwdev->dma_mask < 0xffffffffUL)
return NULL;
/*
......@@ -173,8 +172,6 @@ sn_pci_alloc_consistent(struct pci_dev *hwdev, size_t size, dma_addr_t *dma_hand
if(!(cpuaddr = (void *)__get_free_pages(GFP_ATOMIC, get_order(size))))
return NULL;
memset(cpuaddr, 0, size); /* have to zero it out */
/* physical addr. of the memory we just got */
phys_addr = __pa(cpuaddr);
......@@ -188,6 +185,16 @@ sn_pci_alloc_consistent(struct pci_dev *hwdev, size_t size, dma_addr_t *dma_hand
((IS_PIC_DEVICE(hwdev)) ? 0 : PCIIO_BYTE_STREAM) |
PCIIO_DMA_CMD);
/*
* If this device is in PCI-X mode, the system would have
* automatically allocated a 64Bits DMA Address. Error out if the
* device cannot support DAC.
*/
if (*dma_handle > hwdev->consistent_dma_mask) {
free_pages((unsigned long) cpuaddr, get_order(size));
return NULL;
}
/*
* It is a 32 bit card and we cannot do direct mapping,
* so we try to use an ATE.
......
......@@ -55,46 +55,6 @@ snia_kmem_zalloc_node(register size_t size, register int flags, cnodeid_t node)
}
#define xtod(c) ((c) <= '9' ? '0' - (c) : 'a' - (c) - 10)
long
atoi(register char *p)
{
register long n;
register int c, neg = 0;
if (p == NULL)
return 0;
if (!isdigit(c = *p)) {
while (isspace(c))
c = *++p;
switch (c) {
case '-':
neg++;
case '+': /* fall-through */
c = *++p;
}
if (!isdigit(c))
return (0);
}
if (c == '0' && *(p + 1) == 'x') {
p += 2;
c = *p;
n = xtod(c);
while ((c = *++p) && isxdigit(c)) {
n *= 16; /* two steps to avoid unnecessary overflow */
n += xtod(c); /* accum neg to avoid surprises at MAX */
}
} else {
n = '0' - c;
while ((c = *++p) && isdigit(c)) {
n *= 10; /* two steps to avoid unnecessary overflow */
n += '0' - c; /* accum neg to avoid surprises at MAX */
}
}
return (neg ? n : -n);
}
/*
* print_register() allows formatted printing of bit fields. individual
* bit fields are described by a struct reg_desc, multiple bit fields within
......
......@@ -12,7 +12,7 @@
EXTRA_CFLAGS := -DLITTLE_ENDIAN
obj-y += pcibr/ ml_SN_intr.o shub_intr.o shuberror.o shub.o bte_error.o \
pic.o geo_op.o l1.o l1_command.o klconflib.o klgraph.o ml_SN_init.o \
pic.o geo_op.o l1_command.o klconflib.o klgraph.o ml_SN_init.o \
ml_iograph.o module.o pciio.o xbow.o xtalk.o shubio.o
obj-$(CONFIG_KDB) += kdba_io.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.
*/
/* 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 <linux/interrupt.h>
#include <asm/io.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/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
static int L1_connected; /* non-zero when interrupts are enabled */
int
get_L1_baud(void)
{
return UART_BAUD_RATE;
}
/* Return the current interrupt level */
int
l1_get_intr_value( void )
{
cpuid_t intr_cpuid;
nasid_t console_nasid;
int major, minor;
extern nasid_t get_console_nasid(void);
/* if it is an old prom, run in poll mode */
major = sn_sal_rev_major();
minor = sn_sal_rev_minor();
if ( (major < 1) || ((major == 1) && (minor < 10)) ) {
/* before version 1.10 doesn't work */
return (0);
}
console_nasid = get_console_nasid();
intr_cpuid = NODEPDA(NASID_TO_COMPACT_NODEID(console_nasid))->node_first_cpu;
return CPU_VECTOR_TO_IRQ(intr_cpuid, SGI_UART_VECTOR);
}
/* Disconnect the callup functions - throw away interrupts */
void
l1_unconnect_intr(void)
{
}
/* Set up uart interrupt handling for this node's uart */
int
l1_connect_intr(void *intr_func, void *arg, struct pt_regs *ep)
{
cpuid_t intr_cpuid;
nasid_t console_nasid;
unsigned int console_irq;
int result;
extern int intr_connect_level(cpuid_t, int, ilvl_t, intr_func_t);
extern nasid_t get_console_nasid(void);
/* don't call to connect multiple times - we DON'T support changing the handler */
if ( !L1_connected ) {
L1_connected++;
console_nasid = get_console_nasid();
intr_cpuid = NODEPDA(NASID_TO_COMPACT_NODEID(console_nasid))->node_first_cpu;
console_irq = CPU_VECTOR_TO_IRQ(intr_cpuid, SGI_UART_VECTOR);
result = intr_connect_level(intr_cpuid, SGI_UART_VECTOR,
0 /*not used*/, 0 /*not used*/);
if (result != SGI_UART_VECTOR) {
if (result < 0)
printk(KERN_WARNING "L1 console driver : intr_connect_level failed %d\n", result);
else
printk(KERN_WARNING "L1 console driver : intr_connect_level returns wrong bit %d\n", result);
return (-1);
}
result = request_irq(console_irq, intr_func, SA_INTERRUPT,
"SGI L1 console driver", (void *)arg);
if (result < 0) {
printk(KERN_WARNING "L1 console driver : request_irq failed %d\n", result);
return (-1);
}
/* ask SAL to turn on interrupts in the UART itself */
ia64_sn_console_intr_enable(SAL_CONSOLE_INTR_RECV);
}
return (0);
}
/* 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 tmp;
/* 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);
int counter = len;
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 ( L1_connected )
tmp = ia64_sn_console_xmit_chars(str, len);
else
tmp = ia64_sn_console_putb(str, len);
return ((tmp < 0) ? 0 : tmp);
}
......@@ -262,18 +262,3 @@ io_module_init(void)
if (nserial == 0)
DPRINTF(KERN_WARNING "io_module_init: No serial number found.\n");
}
int
get_kmod_info(cmoduleid_t cmod, module_info_t *mod_info)
{
if (cmod < 0 || cmod >= nummodules)
return -EINVAL;
mod_info->mod_num = modules[cmod]->id;
ia64_sn_sys_serial_get(mod_info->serial_str);
mod_info->serial_num = ia64_sn_partition_serial_get();
return 0;
}
......@@ -30,19 +30,6 @@
#include <asm/sn/io.h>
#include <asm/sn/sn_private.h>
#ifdef __ia64
uint64_t atealloc(struct map *mp, size_t size);
void atefree(struct map *mp, size_t size, uint64_t a);
void atemapfree(struct map *mp);
struct map *atemapalloc(uint64_t mapsiz);
#define rmallocmap atemapalloc
#define rmfreemap atemapfree
#define rmfree atefree
#define rmalloc atealloc
#endif
#ifndef LOCAL
#define LOCAL static
#endif
......@@ -165,32 +152,55 @@ pcibr_init_ext_ate_ram(bridge_t *bridge)
int
pcibr_ate_alloc(pcibr_soft_t pcibr_soft, int count)
{
int index = 0;
int status = 0;
struct resource *new_res;
struct resource **allocated_res;
new_res = (struct resource *) kmalloc( sizeof(struct resource), GFP_ATOMIC);
memset(new_res, 0, sizeof(*new_res));
status = allocate_resource( &pcibr_soft->bs_int_ate_resource, new_res,
count, pcibr_soft->bs_int_ate_resource.start,
pcibr_soft->bs_int_ate_resource.end, 1,
NULL, NULL);
if ( status && (pcibr_soft->bs_ext_ate_resource.end != 0) ) {
status = allocate_resource( &pcibr_soft->bs_ext_ate_resource, new_res,
count, pcibr_soft->bs_ext_ate_resource.start,
pcibr_soft->bs_ext_ate_resource.end, 1,
NULL, NULL);
if (status) {
new_res->start = -1;
}
}
index = (int) rmalloc(pcibr_soft->bs_int_ate_map, (size_t) count);
if (status) {
/* Failed to allocate */
kfree(new_res);
return -1;
}
if (!index && pcibr_soft->bs_ext_ate_map)
index = (int) rmalloc(pcibr_soft->bs_ext_ate_map, (size_t) count);
/* Save the resource for freeing */
allocated_res = (struct resource **)(((unsigned long)pcibr_soft->bs_allocated_ate_res) + new_res->start * sizeof( unsigned long));
*allocated_res = new_res;
/* rmalloc manages resources in the 1..n
* range, with 0 being failure.
* pcibr_ate_alloc manages resources
* in the 0..n-1 range, with -1 being failure.
*/
return index - 1;
return new_res->start;
}
void
pcibr_ate_free(pcibr_soft_t pcibr_soft, int index, int count)
/* Who says there's no such thing as a free meal? :-) */
{
/* note the "+1" since rmalloc handles 1..n but
* we start counting ATEs at zero.
*/
rmfree((index < pcibr_soft->bs_int_ate_size)
? pcibr_soft->bs_int_ate_map
: pcibr_soft->bs_ext_ate_map,
count, index + 1);
struct resource **allocated_res;
int status = 0;
allocated_res = (struct resource **)(((unsigned long)pcibr_soft->bs_allocated_ate_res) + index * sizeof(unsigned long));
status = release_resource(*allocated_res);
if (status)
BUG(); /* Ouch .. */
kfree(*allocated_res);
}
/*
......
......@@ -12,6 +12,7 @@
#include <linux/module.h>
#include <linux/string.h>
#include <linux/interrupt.h>
#include <linux/ioport.h>
#include <asm/sn/sgi.h>
#include <asm/sn/sn_sal.h>
#include <asm/sn/sn_cpuid.h>
......@@ -34,13 +35,6 @@
#include <asm/sn/io.h>
#include <asm/sn/sn_private.h>
#ifdef __ia64
#define rmallocmap atemapalloc
#define rmfreemap atemapfree
#define rmfree atefree
#define rmalloc atealloc
#endif
/*
* global variables to toggle the different levels of pcibr debugging.
* -pcibr_debug_mask is the mask of the different types of debugging
......@@ -933,7 +927,7 @@ pcibr_bus_cnvlink(vertex_hdl_t f_c)
xp = strstr(dst, "/"EDGE_LBL_XTALK"/");
if (xp == NULL)
return 0;
widgetnum = atoi(xp+7);
widgetnum = simple_strtoul(xp+7, NULL, 0);
if (widgetnum < XBOW_PORT_8 || widgetnum > XBOW_PORT_F)
return 0;
......@@ -1494,18 +1488,21 @@ pcibr_attach2(vertex_hdl_t xconn_vhdl, bridge_t *bridge,
/* we always have 128 ATEs (512 for Xbridge) inside the chip
* even if disabled for debugging.
*/
pcibr_soft->bs_int_ate_map = rmallocmap(pcibr_soft->bs_int_ate_size);
pcibr_ate_free(pcibr_soft, 0, pcibr_soft->bs_int_ate_size);
pcibr_soft->bs_int_ate_resource.start = 0;
pcibr_soft->bs_int_ate_resource.end = pcibr_soft->bs_int_ate_size - 1;
if (num_entries > pcibr_soft->bs_int_ate_size) {
#if PCIBR_ATE_NOTBOTH /* for debug -- forces us to use external ates */
printk("pcibr_attach: disabling internal ATEs.\n");
pcibr_ate_alloc(pcibr_soft, pcibr_soft->bs_int_ate_size);
#endif
pcibr_soft->bs_ext_ate_map = rmallocmap(num_entries);
pcibr_ate_free(pcibr_soft, pcibr_soft->bs_int_ate_size,
num_entries - pcibr_soft->bs_int_ate_size);
pcibr_soft->bs_ext_ate_resource.start = pcibr_soft->bs_int_ate_size;
pcibr_soft->bs_ext_ate_resource.end = num_entries;
}
pcibr_soft->bs_allocated_ate_res = (void *) kmalloc(pcibr_soft->bs_int_ate_size * sizeof(unsigned long), GFP_KERNEL);
memset(pcibr_soft->bs_allocated_ate_res, 0x0, pcibr_soft->bs_int_ate_size * sizeof(unsigned long));
PCIBR_DEBUG_ALWAYS((PCIBR_DEBUG_ATE, pcibr_vhdl,
"pcibr_attach2: %d ATEs, %d internal & %d external\n",
num_entries ? num_entries : pcibr_soft->bs_int_ate_size,
......@@ -1716,10 +1713,10 @@ pcibr_attach2(vertex_hdl_t xconn_vhdl, bridge_t *bridge,
{
pciio_win_map_t win_map_p;
iopaddr_t prom_base_addr = pcibr_soft->bs_xid << 24;
int prom_base_size = 0x1000000;
iopaddr_t prom_base_limit = prom_base_addr + prom_base_size;
int status;
struct resource *res;
/* Allocate resource maps based on bus page size; for I/O and memory
* space, free all pages except those in the base area and in the
......@@ -1729,35 +1726,38 @@ pcibr_attach2(vertex_hdl_t xconn_vhdl, bridge_t *bridge,
* the widget number and s is the device register offset for the slot.
*/
win_map_p = &pcibr_soft->bs_io_win_map;
pciio_device_win_map_new(win_map_p,
PCIBR_BUS_IO_MAX + 1,
PCIBR_BUS_IO_PAGE);
pciio_device_win_populate(win_map_p,
PCIBR_BUS_IO_BASE,
prom_base_addr - PCIBR_BUS_IO_BASE);
pciio_device_win_populate(win_map_p,
prom_base_limit,
(PCIBR_BUS_IO_MAX + 1) - prom_base_limit);
win_map_p = &pcibr_soft->bs_swin_map;
pciio_device_win_map_new(win_map_p,
PCIBR_BUS_SWIN_MAX + 1,
PCIBR_BUS_SWIN_PAGE);
pciio_device_win_populate(win_map_p,
PCIBR_BUS_SWIN_BASE,
(PCIBR_BUS_SWIN_MAX + 1) - PCIBR_BUS_SWIN_PAGE);
win_map_p = &pcibr_soft->bs_mem_win_map;
pciio_device_win_map_new(win_map_p,
PCIBR_BUS_MEM_MAX + 1,
PCIBR_BUS_MEM_PAGE);
pciio_device_win_populate(win_map_p,
PCIBR_BUS_MEM_BASE,
prom_base_addr - PCIBR_BUS_MEM_BASE);
pciio_device_win_populate(win_map_p,
prom_base_limit,
(PCIBR_BUS_MEM_MAX + 1) - prom_base_limit);
/* Setup the Bus's PCI IO Root Resource. */
pcibr_soft->bs_io_win_root_resource.start = PCIBR_BUS_IO_BASE;
pcibr_soft->bs_io_win_root_resource.end = 0xffffffff;
res = (struct resource *) kmalloc( sizeof(struct resource), KM_NOSLEEP);
if (!res)
panic("PCIBR:Unable to allocate resource structure\n");
/* Block off the range used by PROM. */
res->start = prom_base_addr;
res->end = prom_base_addr + (prom_base_size - 1);
status = request_resource(&pcibr_soft->bs_io_win_root_resource, res);
if (status)
panic("PCIBR:Unable to request_resource()\n");
/* Setup the Small Window Root Resource */
pcibr_soft->bs_swin_root_resource.start = _PAGESZ;
pcibr_soft->bs_swin_root_resource.end = 0x000FFFFF;
/* Setup the Bus's PCI Memory Root Resource */
pcibr_soft->bs_mem_win_root_resource.start = 0x200000;
pcibr_soft->bs_mem_win_root_resource.end = 0xffffffff;
res = (struct resource *) kmalloc( sizeof(struct resource), KM_NOSLEEP);
if (!res)
panic("PCIBR:Unable to allocate resource structure\n");
/* Block off the range used by PROM. */
res->start = prom_base_addr;
res->end = prom_base_addr + (prom_base_size - 1);;
status = request_resource(&pcibr_soft->bs_mem_win_root_resource, res);
if (status)
panic("PCIBR:Unable to request_resource()\n");
}
/* build "no-slot" connection point
......@@ -1940,15 +1940,6 @@ pcibr_detach(vertex_hdl_t xconn)
spin_lock_destroy(&pcibr_soft->bs_lock);
kfree(pcibr_soft->bs_name);
/* Error handler gets unregistered when the widget info is
* cleaned
*/
/* Free the soft ATE maps */
if (pcibr_soft->bs_int_ate_map)
rmfreemap(pcibr_soft->bs_int_ate_map);
if (pcibr_soft->bs_ext_ate_map)
rmfreemap(pcibr_soft->bs_ext_ate_map);
/* Disconnect the error interrupt and free the xtalk resources
* associated with it.
*/
......@@ -4188,14 +4179,14 @@ pcibr_debug(uint32_t type, vertex_hdl_t vhdl, char *format, ...)
cp = strstr(hwpath, "/xtalk/");
if (cp) {
cp += strlen("/xtalk/");
widget = atoi(cp);
widget = simple_strtoul(cp, NULL, 0);
}
}
if (pcibr_debug_slot != -1) {
cp = strstr(hwpath, "/pci/");
if (cp) {
cp += strlen("/pci/");
slot = atoi(cp);
slot = simple_strtoul(cp, NULL, 0);
}
}
}
......@@ -4214,9 +4205,15 @@ pcibr_debug(uint32_t type, vertex_hdl_t vhdl, char *format, ...)
* Since we have a variable length argument list, we
* need to call printk this way rather than directly
*/
{
char buffer[500];
va_start(ap, format);
printk(format, ap);
vsnprintf(buffer, 500, format, ap);
va_end(ap);
buffer[499] = (char)0; /* just to be safe */
printk("%s", buffer);
}
}
}
}
......
......@@ -31,11 +31,6 @@
#include <asm/sn/sn_private.h>
#ifdef __ia64
#define rmallocmap atemapalloc
#define rmfreemap atemapfree
#define rmfree atefree
#define rmalloc atealloc
inline int
compare_and_swap_ptr(void **location, void *old_ptr, void *new_ptr)
{
......
......@@ -700,10 +700,10 @@ pcibr_slot_initial_rrb_alloc(vertex_hdl_t pcibr_vhdl,
pcibr_soft = pcibr_soft_get(pcibr_vhdl);
if (!pcibr_soft)
return(EINVAL);
return(-EINVAL);
if (!PCIBR_VALID_SLOT(pcibr_soft, slot))
return(EINVAL);
return(-EINVAL);
bridge = pcibr_soft->bs_base;
......@@ -741,7 +741,13 @@ pcibr_slot_initial_rrb_alloc(vertex_hdl_t pcibr_vhdl,
pcibr_soft->bs_rrb_valid[slot][3] = chan[3];
return(ENODEV);
return(-ENODEV);
}
/* Give back any assigned to empty slots */
if ((pcibr_info->f_vendor == PCIIO_VENDOR_ID_NONE) && !pcibr_soft->bs_slot[slot].has_host) {
do_pcibr_rrb_free_all(pcibr_soft, bridge, slot);
return(-ENODEV);
}
for (vchan = 0; vchan < vchan_total; vchan++)
......
......@@ -30,15 +30,6 @@
#include <asm/sn/ioc3.h>
#include <asm/sn/io.h>
#include <asm/sn/sn_private.h>
#include <asm/sn/ate_utils.h>
#ifdef __ia64
#define rmallocmap atemapalloc
#define rmfreemap atemapfree
#define rmfree atefree
#define rmalloc atealloc
#endif
extern pcibr_info_t pcibr_info_get(vertex_hdl_t);
extern int pcibr_widget_to_bus(vertex_hdl_t pcibr_vhdl);
......@@ -142,7 +133,7 @@ pcibr_slot_startup(vertex_hdl_t pcibr_vhdl, pcibr_slot_req_t reqp)
error = pcibr_slot_attach(pcibr_vhdl, slot, D_PCI_HOT_PLUG_ATTACH,
l1_msg, &tmp_up_resp.resp_sub_errno);
strlcpy(tmp_up_resp.resp_l1_msg, l1_msg, L1_QSIZE);
strncpy(tmp_up_resp.resp_l1_msg, l1_msg, L1_QSIZE);
tmp_up_resp.resp_l1_msg[L1_QSIZE] = '\0';
if (COPYOUT(&tmp_up_resp, reqp->req_respp.up, reqp->req_size)) {
......@@ -228,8 +219,8 @@ pcibr_slot_shutdown(vertex_hdl_t pcibr_vhdl, pcibr_slot_req_t reqp)
error = pcibr_slot_detach(pcibr_vhdl, slot, D_PCI_HOT_PLUG_DETACH,
l1_msg, &tmp_down_resp.resp_sub_errno);
strlcpy(tmp_down_resp.resp_l1_msg, l1_msg,
sizeof(tmp_down_resp.resp_l1_msg));
strncpy(tmp_down_resp.resp_l1_msg, l1_msg, L1_QSIZE);
tmp_down_resp.resp_l1_msg[L1_QSIZE] = '\0';
shutdown_copyout:
......@@ -1877,30 +1868,36 @@ pcibr_bus_addr_alloc(pcibr_soft_t pcibr_soft, pciio_win_info_t win_info_p,
pciio_space_t space, int start, int size, int align)
{
pciio_win_map_t win_map_p;
struct resource *root_resource = NULL;
iopaddr_t iopaddr = 0;
switch (space) {
case PCIIO_SPACE_IO:
win_map_p = &pcibr_soft->bs_io_win_map;
root_resource = &pcibr_soft->bs_io_win_root_resource;
break;
case PCIIO_SPACE_MEM:
win_map_p = &pcibr_soft->bs_swin_map;
root_resource = &pcibr_soft->bs_swin_root_resource;
break;
case PCIIO_SPACE_MEM32:
win_map_p = &pcibr_soft->bs_mem_win_map;
root_resource = &pcibr_soft->bs_mem_win_root_resource;
break;
default:
return 0;
}
return pciio_device_win_alloc(win_map_p,
iopaddr = pciio_device_win_alloc(root_resource,
win_info_p
? &win_info_p->w_win_alloc
: NULL,
start, size, align);
return(iopaddr);
}
......
......@@ -28,16 +28,8 @@
#include <asm/sn/sn_sal.h>
#include <asm/sn/io.h>
#include <asm/sn/pci/pci_bus_cvlink.h>
#include <asm/sn/ate_utils.h>
#include <asm/sn/simulator.h>
#ifdef __ia64
#define rmallocmap atemapalloc
#define rmfreemap atemapfree
#define rmfree atefree
#define rmalloc atealloc
#endif
#define DEBUG_PCIIO
#undef DEBUG_PCIIO /* turn this on for yet more console output */
......@@ -1313,61 +1305,6 @@ pciio_device_detach(vertex_hdl_t pconn,
return(0);
}
/* SN2 */
/*
* Allocate (if necessary) and initialize a PCI window mapping structure.
*/
pciio_win_map_t
pciio_device_win_map_new(pciio_win_map_t win_map,
size_t region_size,
size_t page_size)
{
ASSERT((page_size & (page_size - 1)) == 0);
ASSERT((region_size & (page_size - 1)) == 0);
if (win_map == NULL)
NEW(win_map);
/*
* The map array tracks the free ``pages'' in the region. The worst
* case scenario is when every other page in the region is free --
* e.i. maximum fragmentation. This leads to (max pages + 1) / 2 + 1
* map entries. The first "+1" handles the divide by 2 rounding; the
* second handles the need for an end marker sentinel.
*/
win_map->wm_map = rmallocmap((region_size / page_size + 1) / 2 + 1);
win_map->wm_page_size = page_size;
ASSERT(win_map->wm_map != NULL);
return win_map;
}
/*
* Free resources associated with a PCI window mapping structure.
*/
extern void
pciio_device_win_map_free(pciio_win_map_t win_map)
{
rmfreemap(win_map->wm_map);
bzero(win_map, sizeof *win_map);
}
/*
* Populate window map with specified free range.
*/
void
pciio_device_win_populate(pciio_win_map_t win_map,
iopaddr_t ioaddr,
size_t size)
{
ASSERT((size & (win_map->wm_page_size - 1)) == 0);
ASSERT((ioaddr & (win_map->wm_page_size - 1)) == 0);
rmfree(win_map->wm_map,
size / win_map->wm_page_size,
(unsigned long)ioaddr / win_map->wm_page_size);
}
/*
* Allocate space from the specified PCI window mapping resource. On
* success record information about the allocation in the supplied window
......@@ -1385,94 +1322,36 @@ pciio_device_win_populate(pciio_win_map_t win_map,
* and alignment.
*/
iopaddr_t
pciio_device_win_alloc(pciio_win_map_t win_map,
pciio_device_win_alloc(struct resource *root_resource,
pciio_win_alloc_t win_alloc,
size_t start, size_t size, size_t align)
{
unsigned long base;
#ifdef PIC_LATER
ASSERT((size & (size - 1)) == 0);
ASSERT((align & (align - 1)) == 0);
struct resource *new_res;
int status = 0;
/*
* Convert size and alignment to pages. If size is greated than the
* requested alignment, we bump the alignment up to size; otherwise
* convert the size into a multiple of the alignment request.
*/
size = (size + win_map->wm_page_size - 1) / win_map->wm_page_size;
align = align / win_map->wm_page_size;
if (size > align)
align = size;
else
size = (size + align - 1) & ~(align - 1);
/* XXXX */
base = rmalloc_align(win_map->wm_map, size, align, VM_NOSLEEP);
if (base == RMALLOC_FAIL)
return((iopaddr_t)NULL);
#else
int index_page, index_page_align;
int align_pages, size_pages;
int alloc_pages, free_pages;
int addr_align;
/* Convert PCI bus alignment from bytes to pages */
align_pages = align / win_map->wm_page_size;
/* Convert PCI request from bytes to pages */
size_pages = (size / win_map->wm_page_size) +
((size % win_map->wm_page_size) ? 1 : 0);
/* Align address with the larger of the size or the requested slot align */
if (size_pages > align_pages)
align_pages = size_pages;
/*
* Avoid wasting space by aligning - 1; this will prevent crossing
* another alignment boundary.
*/
alloc_pages = size_pages + (align_pages - 1);
/* Allocate PCI bus space in pages */
index_page = (int) rmalloc(win_map->wm_map,
(size_t) alloc_pages);
new_res = (struct resource *) kmalloc( sizeof(struct resource), KM_NOSLEEP);
/* Error if no PCI bus address space available */
if (!index_page)
return 0;
/* PCI bus address index starts at 0 */
index_page--;
/* Align the page offset as requested */
index_page_align = (index_page + (align_pages - 1)) -
((index_page + (align_pages - 1)) % align_pages);
free_pages = (align_pages - 1) - (index_page_align - index_page);
/* Free unused PCI bus pages adjusting the index to start at 1 */
rmfree(win_map->wm_map,
free_pages,
(index_page_align + 1) + size_pages);
/* Return aligned PCI bus space in bytes */
addr_align = (index_page_align * win_map->wm_page_size);
base = index_page;
size = alloc_pages - free_pages;
#endif /* PIC_LATER */
status = allocate_resource( root_resource, new_res,
size, align /* Min start addr. */,
root_resource->end, align,
NULL, NULL);
if (status) {
kfree(new_res);
return((iopaddr_t) NULL);
}
/*
* If a window allocation cookie has been supplied, use it to keep
* track of all the allocated space assigned to this window.
*/
if (win_alloc) {
win_alloc->wa_map = win_map;
win_alloc->wa_base = base;
win_alloc->wa_resource = new_res;
win_alloc->wa_base = new_res->start;
win_alloc->wa_pages = size;
}
return base * win_map->wm_page_size;
return new_res->start;;
}
/*
......@@ -1482,10 +1361,16 @@ pciio_device_win_alloc(pciio_win_map_t win_map,
void
pciio_device_win_free(pciio_win_alloc_t win_alloc)
{
if (win_alloc->wa_pages)
rmfree(win_alloc->wa_map->wm_map,
win_alloc->wa_pages,
win_alloc->wa_base);
int status = 0;
if (win_alloc->wa_resource) {
status = release_resource(win_alloc->wa_resource);
if (!status)
kfree(win_alloc->wa_resource);
else
BUG();
}
}
/*
......
......@@ -15,6 +15,7 @@
#include <asm/smp.h>
#include <asm/irq.h>
#include <asm/hw_irq.h>
#include <asm/system.h>
#include <asm/sn/sgi.h>
#include <asm/sn/iograph.h>
#include <asm/sn/invent.h>
......@@ -485,10 +486,13 @@ sn_linkstats_get(char *page)
static int __init
linkstatd_init(void)
{
if (!ia64_platform_is("sn2"))
return -ENODEV;
spin_lock_init(&sn_linkstats_lock);
sn_linkstats = kmalloc(numnodes * sizeof(struct s_linkstats), GFP_KERNEL);
sn_linkstats_reset(60000UL); /* default 60 second update interval */
kernel_thread(linkstatd_thread, NULL, CLONE_FS | CLONE_FILES);
kernel_thread(linkstatd_thread, NULL, CLONE_FS | CLONE_FILES | CLONE_SIGHAND);
return 0;
}
......
......@@ -155,7 +155,7 @@ hubii_eint_init(cnodeid_t cnode)
rv = intr_connect_level(intr_cpu, SGI_II_ERROR, 0, NULL);
request_irq(SGI_II_ERROR, hubii_eint_handler, SA_SHIRQ, "SN_hub_error", (void *)hub_v);
irq_desc(bit)->status |= SN2_IRQ_PER_HUB;
irq_descp(bit)->status |= SN2_IRQ_PER_HUB;
ASSERT_ALWAYS(rv >= 0);
hubio_eint.ii_iidsr_regval = 0;
hubio_eint.ii_iidsr_fld_s.i_enable = 1;
......
......@@ -34,6 +34,7 @@
#include <linux/init.h>
#include <linux/sched.h>
#include <linux/vmalloc.h>
#include <asm/current.h>
#include <linux/irq.h>
#include <linux/interrupt.h>
......@@ -218,6 +219,8 @@ register_pcibr_intr(int irq, pcibr_intr_t intr) {
if (pcibr_intr_list == NULL) {
pcibr_intr_list = kmalloc(sizeof(struct pcibr_intr_list_t *) * NR_IRQS, GFP_KERNEL);
if (pcibr_intr_list == NULL)
pcibr_intr_list = vmalloc(sizeof(struct pcibr_intr_list_t *) * NR_IRQS);
if (pcibr_intr_list == NULL) panic("Could not allocate memory for pcibr_intr_list\n");
memset( (void *)pcibr_intr_list, 0, sizeof(struct pcibr_intr_list_t *) * NR_IRQS);
}
......
......@@ -50,6 +50,7 @@
#include <linux/acpi.h>
#include <linux/compiler.h>
#include <linux/sched.h>
#include <linux/root_dev.h>
#include <asm/io.h>
#include <asm/sal.h>
......@@ -80,6 +81,7 @@ DEFINE_PER_CPU(struct pda_s, pda_percpu);
extern void bte_init_node (nodepda_t *, cnodeid_t);
extern void bte_init_cpu (void);
extern void sn_timer_init(void);
extern unsigned long last_time_offset;
extern void (*ia64_mark_idle)(int);
extern void snidle(int);
......@@ -145,7 +147,7 @@ char drive_info[4*16];
* Sets up an initial console to aid debugging. Intended primarily
* for bringup. See start_kernel() in init/main.c.
*/
#if defined(CONFIG_IA64_EARLY_PRINTK) || defined(CONFIG_IA64_SGI_SN_SIM)
#if defined(CONFIG_IA64_EARLY_PRINTK_SGI_SN) || defined(CONFIG_IA64_SGI_SN_SIM)
void __init
early_sn_setup(void)
......@@ -187,7 +189,7 @@ early_sn_setup(void)
printk(KERN_DEBUG "early_sn_setup: setting master_node_bedrock_address to 0x%lx\n", master_node_bedrock_address);
}
}
#endif /* CONFIG_IA64_EARLY_PRINTK */
#endif /* CONFIG_IA64_EARLY_PRINTK_SGI_SN */
#ifdef CONFIG_IA64_MCA
extern int platform_intr_list[];
......@@ -288,6 +290,12 @@ sn_setup(char **cmdline_p)
master_node_bedrock_address);
}
/*
* we set the default root device to /dev/hda
* to make simulation easy
*/
ROOT_DEV = Root_HDA1;
/*
* Create the PDAs and NODEPDAs for all the cpus.
*/
......
......@@ -12,6 +12,7 @@
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/proc_fs.h>
#include <asm/system.h>
#include <asm/io.h>
#include <asm/sn/simulator.h>
......@@ -312,6 +313,9 @@ prominfo_init(void)
nasid_t nasid;
char name[NODE_NAME_LEN];
if (!ia64_platform_is("sn2"))
return 0;
TRACE();
DPRINTK("running on cpu %d\n", smp_processor_id());
......
......@@ -5,7 +5,7 @@
#include <asm/system.h>
#include <asm/pgtable.h>
#define LOAD_OFFSET KERNEL_START + KERNEL_TR_PAGE_SIZE
#define LOAD_OFFSET (KERNEL_START - KERNEL_TR_PAGE_SIZE)
#include <asm-generic/vmlinux.lds.h>
OUTPUT_FORMAT("elf64-ia64-little")
......
#ifndef _ASM_IA64_SN_ATE_UTILS_H
#define _ASM_IA64_SN_ATE_UTILS_H
/* $Id: ate_utils.h,v 1.1 2002/02/28 17:31:25 marcelo Exp $
*
* 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.
*/
/*
* struct map X[] .m_size .m_addr
* --- ------------ -----------
* [0] mapsize(X) unused
* # X[] unused
* [1] map lock * mapwant sv_t *
* map access wait for free map space
*
* mapstart(X)-> [2] # units unit number
* : : :
* [ ] 0
*/
#include <linux/types.h>
#define ulong_t uint64_t
struct map
{
unsigned long m_size; /* number of units available */
unsigned long m_addr; /* address of first available unit */
};
#define mapstart(X) &X[2] /* start of map array */
#define mapsize(X) X[0].m_size /* number of empty slots */
/* remaining in map array */
#define maplock(X) (((spinlock_t *) X[1].m_size))
#define mapout(X) ((sv_t *) X[1].m_addr)
extern ulong_t atealloc(struct map *, size_t);
extern struct map *atemapalloc(ulong_t);
extern void atefree(struct map *, size_t, ulong_t);
extern void atemapfree(struct map *);
#endif /* _ASM_IA64_SN_ATE_UTILS_H */
......@@ -29,12 +29,18 @@
#include <asm/sn/addrs.h>
typedef long clkreg_t;
extern unsigned long sn_rtc_cycles_per_second;
extern unsigned long sn_rtc_usec_per_cyc;
extern unsigned long sn_rtc_per_itc;
extern unsigned long sn_rtc_delta;
#include <asm/sn/addrs.h>
#include <asm/sn/sn2/addrs.h>
#include <asm/sn/sn2/shubio.h>
#include <asm/sn/sn2/shub_mmr.h>
#define RTC_MASK SH_RTC_MASK
#define RTC_COUNTER_ADDR ((clkreg_t*)LOCAL_MMR_ADDR(SH_RTC))
#define RTC_COMPARE_A_ADDR ((clkreg_t*)LOCAL_MMR_ADDR(SH_RTC))
#define RTC_COMPARE_B_ADDR ((clkreg_t*)LOCAL_MMR_ADDR(SH_RTC))
......@@ -43,6 +49,7 @@ extern unsigned long sn_rtc_cycles_per_second;
#define RTC_INT_ENABLED_A_ADDR ((clkreg_t*)LOCAL_MMR_ADDR(SH_RTC))
#define RTC_INT_ENABLED_B_ADDR ((clkreg_t*)LOCAL_MMR_ADDR(SH_RTC))
#define SN_RTC_PER_ITC_SHIFT 34
#define GET_RTC_COUNTER() (*RTC_COUNTER_ADDR)
#define rtc_time() GET_RTC_COUNTER()
......
......@@ -68,13 +68,15 @@ typedef struct {
/*
* The following APIs are externalized to the kernel to allocate/free fetchop variables.
* fetchop_kalloc_one - Allocate/initialize 1 fetchop variable on the specified cnode.
* fetchop_kfree_one - Free a previously allocated fetchop variable
* The following APIs are externalized to the kernel to allocate/free pages of
* fetchop variables.
* fetchop_kalloc_page - Allocate/initialize 1 fetchop page on the
* specified cnode.
* fetchop_kfree_page - Free a previously allocated fetchop page
*/
unsigned long fetchop_kalloc_one(int nid);
void fetchop_kfree_one(unsigned long maddr);
unsigned long fetchop_kalloc_page(int nid);
void fetchop_kfree_page(unsigned long maddr);
#endif /* __KERNEL__ */
......
......@@ -14,7 +14,6 @@ extern "C" {
#include <linux/config.h>
#include <asm/sn/systeminfo.h>
#include <asm/sn/klconfig.h>
#include <asm/sn/ksys/elsc.h>
......@@ -193,8 +192,6 @@ extern int nummodules;
extern module_t *module_lookup(moduleid_t id);
extern int get_kmod_info(cmoduleid_t cmod,
module_info_t *mod_info);
extern int get_kmod_sys_snum(cmoduleid_t cmod,
char *snum);
......
......@@ -307,7 +307,7 @@ struct pcibr_intr_wrap_s {
*/
#define PV854697 (~0) /* PIC: write 64bit regs as 64bits. permanent */
#define PV854827 (~0) /* PIC: fake widget 0xf presence bit. permanent */
#define PV855271 (~0) /* PIC: use virt chan iff 64-bit device. permanent */
#define PV855271 (1 << 1) /* PIC: PIC: use virt chan iff 64-bit device. */
#define PV855272 (1 << 1) /* PIC: runaway interrupt WAR */
#define PV856155 (1 << 1) /* PIC: arbitration WAR */
#define PV856864 (1 << 1) /* PIC: lower timeout to free TNUMs quicker */
......@@ -367,8 +367,9 @@ struct pcibr_soft_s {
iopaddr_t bs_dir_xbase; /* xtalk address for 32-bit PCI direct map */
xwidgetnum_t bs_dir_xport; /* xtalk port for 32-bit PCI direct map */
struct map *bs_int_ate_map; /* rmalloc map for internal ATEs */
struct map *bs_ext_ate_map; /* rmalloc map for external ATEs */
struct resource bs_int_ate_resource;/* root resource for internal ATEs */
struct resource bs_ext_ate_resource;/* root resource for external ATEs */
void *bs_allocated_ate_res;/* resource struct allocated */
short bs_int_ate_size; /* number of internal ates */
short bs_bridge_type; /* see defines above */
short bs_bridge_mode; /* see defines above */
......@@ -592,6 +593,10 @@ struct pcibr_soft_s {
struct pciio_win_map_s bs_swin_map; /* Small window addr space */
struct pciio_win_map_s bs_mem_win_map; /* Memory addr space */
struct resource bs_io_win_root_resource; /* I/O addr space */
struct resource bs_swin_root_resource; /* Small window addr space */
struct resource bs_mem_win_root_resource; /* Memory addr space */
int bs_bus_addr_status; /* Bus space status */
#define PCIBR_BUS_ADDR_MEM_FREED 1 /* Reserved PROM mem addr freed */
......
......@@ -14,6 +14,7 @@
*/
#include <linux/config.h>
#include <linux/ioport.h>
#include <asm/sn/ioerror.h>
#include <asm/sn/driver.h>
#include <asm/sn/hcl.h>
......@@ -632,7 +633,7 @@ pciio_device_win_populate(pciio_win_map_t win_map, /* win map */
/* allocate window from mapping resource */
extern iopaddr_t
pciio_device_win_alloc(pciio_win_map_t win_map, /* win map */
pciio_device_win_alloc(struct resource * res,
pciio_win_alloc_t win_alloc, /* opaque allocation cookie */
size_t start, /* start unit, or 0 */
size_t size, /* size of allocation */
......
......@@ -89,7 +89,7 @@ struct pciio_win_map_s {
* Opaque structure used to keep track of window allocation information.
*/
struct pciio_win_alloc_s {
pciio_win_map_t wa_map; /* window map allocation is from */
struct resource *wa_resource; /* window map allocation resource */
unsigned long wa_base; /* allocation starting page number */
size_t wa_pages; /* number of pages in allocation */
};
......
......@@ -28,64 +28,76 @@ extern void sn_dma_flush(unsigned long);
static inline unsigned int
__sn_inb (unsigned long port)
{
volatile unsigned char *addr = sn_io_addr(port);
unsigned char ret;
volatile unsigned char *addr;
unsigned char ret = -1;
if ((addr = sn_io_addr(port))) {
ret = *addr;
__sn_mf_a();
sn_dma_flush((unsigned long)addr);
}
return ret;
}
static inline unsigned int
__sn_inw (unsigned long port)
{
volatile unsigned short *addr = sn_io_addr(port);
unsigned short ret;
volatile unsigned short *addr;
unsigned short ret = -1;
if ((addr = sn_io_addr(port))) {
ret = *addr;
__sn_mf_a();
sn_dma_flush((unsigned long)addr);
}
return ret;
}
static inline unsigned int
__sn_inl (unsigned long port)
{
volatile unsigned int *addr = sn_io_addr(port);
unsigned int ret;
volatile unsigned int *addr;
unsigned int ret = -1;
if ((addr = sn_io_addr(port))) {
ret = *addr;
__sn_mf_a();
sn_dma_flush((unsigned long)addr);
}
return ret;
}
static inline void
__sn_outb (unsigned char val, unsigned long port)
{
volatile unsigned char *addr = sn_io_addr(port);
volatile unsigned char *addr;
if ((addr = sn_io_addr(port))) {
*addr = val;
sn_mmiob();
}
}
static inline void
__sn_outw (unsigned short val, unsigned long port)
{
volatile unsigned short *addr = sn_io_addr(port);
volatile unsigned short *addr;
if ((addr = sn_io_addr(port))) {
*addr = val;
sn_mmiob();
}
}
static inline void
__sn_outl (unsigned int val, unsigned long port)
{
volatile unsigned int *addr = sn_io_addr(port);
volatile unsigned int *addr;
if ((addr = sn_io_addr(port))) {
*addr = val;
sn_mmiob();
}
}
/*
......
......@@ -27,6 +27,9 @@
#define SN_SAL_LOG_CE 0x02000006
#define SN_SAL_REGISTER_CE 0x02000007
#define SN_SAL_GET_PARTITION_ADDR 0x02000009
#define SN_SAL_XP_ADDR_REGION 0x0200000f
#define SN_SAL_NO_FAULT_ZONE_VIRTUAL 0x02000010
#define SN_SAL_NO_FAULT_ZONE_PHYSICAL 0x02000011
#define SN_SAL_PRINT_ERROR 0x02000012
#define SN_SAL_CONSOLE_PUTC 0x02000021
#define SN_SAL_CONSOLE_GETC 0x02000022
......@@ -50,6 +53,7 @@
#define SN_SAL_SYSTEM_POWER_DOWN 0x0200003b
#define SN_SAL_GET_MASTER_BASEIO_NASID 0x0200003c
#define SN_SAL_COHERENCE 0x0200003d
#define SN_SAL_MEMPROTECT 0x0200003e
#define SN_SAL_SYSCTL_FRU_CAPTURE 0x0200003f
......@@ -513,16 +517,67 @@ sn_local_partid(void) {
}
}
/*
* Register or unregister a physical address range being referenced across
* a partition boundary for which certain SAL errors should be scanned for,
* cleaned up and ignored. This is of value for kernel partitioning code only.
* Values for the operation argument:
* 1 = register this address range with SAL
* 0 = unregister this address range with SAL
*
* SAL maintains a reference count on an address range in case it is registered
* multiple times.
*
* On success, returns the reference count of the address range after the SAL
* call has performed the current registration/unregistration. Returns a
* negative value if an error occurred.
*/
static inline int
sn_register_xp_addr_region(u64 paddr, u64 len, int operation)
{
struct ia64_sal_retval ret_stuff;
SAL_CALL(ret_stuff, SN_SAL_XP_ADDR_REGION, paddr, len, (u64)operation,
0, 0, 0, 0);
return ret_stuff.status;
}
/*
* Register or unregister an instruction range for which SAL errors should
* be ignored. If an error occurs while in the registered range, SAL jumps
* to return_addr after ignoring the error. Values for the operation argument:
* 1 = register this instruction range with SAL
* 0 = unregister this instruction range with SAL
*
* Returns 0 on success, or a negative value if an error occurred.
*/
static inline int
sn_register_nofault_code(u64 start_addr, u64 end_addr, u64 return_addr,
int virtual, int operation)
{
struct ia64_sal_retval ret_stuff;
u64 call;
if (virtual) {
call = SN_SAL_NO_FAULT_ZONE_VIRTUAL;
} else {
call = SN_SAL_NO_FAULT_ZONE_PHYSICAL;
}
SAL_CALL(ret_stuff, call, start_addr, end_addr, return_addr, (u64)1,
0, 0, 0);
return ret_stuff.status;
}
/*
* Change or query the coherence domain for this partition. Each cpu-based
* nasid is represented by a bit in an array of 64-bit words:
* 0 = not in this partition's coherency domain
* 1 = in this partition's coherency domain
* It is not possible for the local system's nasids to be removed from
* the coherency domain.
*
* It is not possible for the local system's nasids to be removed from
* the coherency domain. Purpose of the domain arguments:
* new_domain = set the coherence domain to the given nasids
* old_domain = return the current coherence domain
*
* Returns 0 on success, or a negative value if an error occurred.
*/
static inline int
sn_change_coherence(u64 *new_domain, u64 *old_domain)
......@@ -533,6 +588,26 @@ sn_change_coherence(u64 *new_domain, u64 *old_domain)
return ret_stuff.status;
}
/*
* Change memory access protections for a physical address range.
* nasid_array is not used on Altix, but may be in future architectures.
* Available memory protection access classes are defined after the function.
*/
static inline int
sn_change_memprotect(u64 paddr, u64 len, u64 perms, u64 *nasid_array)
{
struct ia64_sal_retval ret_stuff;
SAL_CALL(ret_stuff, SN_SAL_MEMPROTECT, paddr, len, nasid_array,
perms, 0, 0, 0);
return ret_stuff.status;
}
#define SN_MEMPROT_ACCESS_CLASS_0 0x14a080
#define SN_MEMPROT_ACCESS_CLASS_1 0x2520c2
#define SN_MEMPROT_ACCESS_CLASS_2 0x14a1ca
#define SN_MEMPROT_ACCESS_CLASS_3 0x14a290
#define SN_MEMPROT_ACCESS_CLASS_6 0x084080
#define SN_MEMPROT_ACCESS_CLASS_7 0x021080
/*
* Turns off system power.
*/
......
/* $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.
*/
#ifndef _ASM_IA64_SN_SYSTEMINFO_H
#define _ASM_IA64_SN_SYSTEMINFO_H
#include <linux/types.h>
#ifdef __cplusplus
extern "C" {
#endif
#define MAX_SERIAL_SIZE 16
typedef struct module_info_s {
uint64_t serial_num;
int mod_num;
char serial_str[MAX_SERIAL_SIZE];
} module_info_t;
/*
* Commands to sysinfo()
*/
#define SI_SYSNAME 1 /* return name of operating system */
#define SI_HOSTNAME 2 /* return name of node */
#define SI_RELEASE 3 /* return release of operating system */
#define SI_VERSION 4 /* return version field of utsname */
#define SI_MACHINE 5 /* return kind of machine */
#define SI_ARCHITECTURE 6 /* return instruction set arch */
#define SI_HW_SERIAL 7 /* return hardware serial number */
#define SI_HW_PROVIDER 8 /* return hardware manufacturer */
#define SI_SRPC_DOMAIN 9 /* return secure RPC domain */
#define SI_INITTAB_NAME 10 /* return name of inittab file used */
#define _MIPS_SI_VENDOR 100 /* return system provider */
#define _MIPS_SI_OS_PROVIDER 101 /* return OS manufacturer */
#define _MIPS_SI_OS_NAME 102 /* return OS name */
#define _MIPS_SI_HW_NAME 103 /* return system name */
#define _MIPS_SI_NUM_PROCESSORS 104 /* return number of processors */
#define _MIPS_SI_HOSTID 105 /* return hostid */
#define _MIPS_SI_OSREL_MAJ 106 /* return OS major release number */
#define _MIPS_SI_OSREL_MIN 107 /* return OS minor release number */
#define _MIPS_SI_OSREL_PATCH 108 /* return OS release number */
#define _MIPS_SI_PROCESSORS 109 /* return CPU revison id */
#define _MIPS_SI_AVAIL_PROCESSORS 110 /* return number of available processors */
#define _MIPS_SI_SERIAL 111
/*
* These commands are unpublished interfaces to sysinfo().
*/
#define SI_SET_HOSTNAME 258 /* set name of node */
/* -unpublished option */
#define SI_SET_SRPC_DOMAIN 265 /* set secure RPC domain */
/* -unpublished option */
#if !defined(__KERNEL__)
int sysinfo(int, char *, long);
int get_num_modules(void);
int get_module_info(int, module_info_t *, size_t);
#endif
#ifdef __cplusplus
}
#endif
#endif /* _ASM_IA64_SN_SYSTEMINFO_H */
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