Commit 9ff05b1b authored by Matthew Wilcox's avatar Matthew Wilcox Committed by Linus Torvalds

[PATCH] parisc arch update

This update covers a lot of changes to arch/parisc and parisc-specific
drivers.

 - irq_return_t changes
 - more work on the module loader (James Bottomley)
 - rewrite of led.c by Helge Deller
 - many miscellaneous updates
parent 20904d25
......@@ -103,11 +103,6 @@ config PARISC64
enable this option otherwise. The 64bit kernel is significantly bigger
and slower than the 32bit one.
config COMPAT
bool
depends on PARISC64
default y
config PDC_NARROW
bool "32-bit firmware"
depends on PARISC64
......@@ -145,6 +140,14 @@ config PREEMPT
# bool "Preemptible Kernel"
default n
config COMPAT
bool
depends on PARISC64
default y
config HPUX
bool "Support for HP-UX binaries"
config NR_CPUS
int "Maximum number of CPUs (2-32)"
depends on SMP
......@@ -165,6 +168,7 @@ config KCORE_ELF
config BINFMT_SOM
tristate "Kernel support for SOM binaries"
depends on HPUX
help
SOM is a binary executable format inherited from HP/UX. Say Y here
to be able to load and execute SOM binaries directly.
......
......@@ -57,8 +57,10 @@ head-$(CONFIG_PARISC64) := arch/parisc/kernel/head64.o
CFLAGS += $(cflags-y)
core-y += $(addprefix arch/parisc/, kernel/pdc_cons.o kernel/process.o \
mm/ kernel/ hpux/ math-emu/ kernel/init_task.o )
kernel-y := mm/ kernel/ math-emu/ kernel/init_task.o
kernel-$(CONFIG_HPUX) += hpux/
core-y += $(addprefix arch/parisc/, $(kernel-y))
libs-y += arch/parisc/lib/ `$(CC) -print-libgcc-file-name`
drivers-$(CONFIG_OPROFILE) += arch/parisc/oprofile/
......
......@@ -4,8 +4,7 @@
head-y := head.o
head-$(CONFIG_PARISC64) := head64.o
extra-y := init_task.o pdc_cons.o process.o \
unaligned.o $(head-y)
extra-y := init_task.o $(head-y)
AFLAGS_entry.o := -traditional
AFLAGS_pacache.o := -traditional
......@@ -14,7 +13,7 @@ obj-y := cache.o pacache.o setup.o traps.o time.o irq.o \
pa7300lc.o syscall.o entry.o sys_parisc.o firmware.o \
ptrace.o hardware.o inventory.o drivers.o semaphore.o \
signal.o hpmc.o real2.o parisc_ksyms.o unaligned.o \
processor.o pdc_chassis.o
process.o processor.o pdc_cons.o pdc_chassis.o
obj-$(CONFIG_SMP) += smp.o
obj-$(CONFIG_PA11) += pci-dma.o
......
......@@ -546,7 +546,7 @@ __kernel_thread:
LDREG -PT_SZ_ALGN-RP_OFFSET(%r30), %r2
ldo -PT_SZ_ALGN(%r30), %r30
bv %r0(%r2)
ldw TASK_PID(%r28), %r28
nop
/*
* Child Returns here
......
......@@ -1785,9 +1785,6 @@ static int do_atm_ioctl(unsigned int fd, unsigned int cmd32, unsigned long arg)
return -EINVAL;
}
#ifdef CONFIG_GENRTC
#endif
#if defined(CONFIG_DRM) || defined(CONFIG_DRM_MODULE)
/* This really belongs in include/linux/drm.h -DaveM */
#include "../../../drivers/char/drm/drm.h"
......
......@@ -43,8 +43,8 @@
#undef DEBUG_IRQ
#undef PARISC_IRQ_CR16_COUNTS
extern void timer_interrupt(int, void *, struct pt_regs *);
extern void ipi_interrupt(int, void *, struct pt_regs *);
extern irqreturn_t timer_interrupt(int, void *, struct pt_regs *);
extern irqreturn_t ipi_interrupt(int, void *, struct pt_regs *);
#ifdef DEBUG_IRQ
#define DBG_IRQ(irq, x) if ((irq) != TIMER_IRQ) printk x
......@@ -583,7 +583,7 @@ struct irq_region *alloc_irq_region( int count, struct irq_region_ops *ops,
/* FIXME: SMP, flags, bottom halves, rest */
int request_irq(unsigned int irq,
void (*handler)(int, void *, struct pt_regs *),
irqreturn_t (*handler)(int, void *, struct pt_regs *),
unsigned long irqflags,
const char * devname,
void *dev_id)
......
......@@ -27,12 +27,39 @@
#include <linux/string.h>
#include <linux/kernel.h>
#if 1
#if 0
#define DEBUGP printk
#else
#define DEBUGP(fmt...)
#endif
#define CHECK_RELOC(val, bits) \
if ( ( !((val) & (1<<((bits)-1))) && ((val)>>(bits)) != 0 ) || \
( ((val) & (1<<((bits)-1))) && ((val)>>(bits)) != (((__typeof__(val))(~0))>>((bits)+2)))) { \
printk(KERN_ERR "module %s relocation of symbol %s is out of range (0x%lx in %d bits)\n", \
me->name, strtab + sym->st_name, (unsigned long)val, bits); \
return -ENOEXEC; \
}
/* three functions to determine where in the module core
* or init pieces the location is */
static inline int is_init(struct module *me, void *loc)
{
return (loc >= me->module_init &&
loc <= (me->module_init + me->init_size));
}
static inline int is_core(struct module *me, void *loc)
{
return (loc >= me->module_core &&
loc <= (me->module_core + me->core_size));
}
static inline int is_local(struct module *me, void *loc)
{
return is_init(me, loc) || is_core(me, loc);
}
#ifndef __LP64__
struct got_entry {
......@@ -40,8 +67,8 @@ struct got_entry {
};
struct fdesc_entry {
Elf32_Addr gp;
Elf32_Addr addr;
Elf32_Addr gp;
};
struct stub_entry {
......@@ -54,8 +81,8 @@ struct got_entry {
struct fdesc_entry {
Elf64_Addr dummy[2];
Elf64_Addr gp;
Elf64_Addr addr;
Elf64_Addr gp;
};
struct stub_entry {
......@@ -167,7 +194,7 @@ static inline unsigned long count_gots(const Elf_Rela *rela, unsigned long n)
static inline unsigned long count_fdescs(const Elf_Rela *rela, unsigned long n)
{
unsigned long cnt = 3; /* 3 for finalize */
unsigned long cnt = 0;
for (; n > 0; n--, rela++)
{
......@@ -211,7 +238,7 @@ int module_frob_arch_sections(CONST Elf_Ehdr *hdr,
CONST char *secstrings,
struct module *me)
{
unsigned long gots = 0, fdescs = 0, stubs = 0;
unsigned long gots = 0, fdescs = 0, stubs = 0, init_stubs = 0;
unsigned int i;
for (i = 1; i < hdr->e_shnum; i++) {
......@@ -228,6 +255,10 @@ int module_frob_arch_sections(CONST Elf_Ehdr *hdr,
*/
gots += count_gots(rels, nrels);
fdescs += count_fdescs(rels, nrels);
if(strncmp(secstrings + sechdrs[i].sh_name,
".rela.init", 10) == 0)
init_stubs += count_stubs(rels, nrels);
else
stubs += count_stubs(rels, nrels);
}
......@@ -238,16 +269,26 @@ int module_frob_arch_sections(CONST Elf_Ehdr *hdr,
me->core_size = ALIGN(me->core_size, 16);
me->arch.fdesc_offset = me->core_size;
me->core_size += stubs * sizeof(struct fdesc_entry);
me->core_size += fdescs * sizeof(struct fdesc_entry);
me->core_size = ALIGN(me->core_size, 16);
me->arch.stub_offset = me->core_size;
me->core_size += stubs * sizeof(struct stub_entry);
me->init_size = ALIGN(me->init_size, 16);
me->arch.init_stub_offset = me->init_size;
me->init_size += init_stubs * sizeof(struct stub_entry);
me->arch.got_max = gots;
me->arch.fdesc_max = fdescs;
me->arch.stub_max = stubs;
me->arch.init_stub_max = init_stubs;
return 0;
}
static Elf_Addr get_got(struct module *me, unsigned long value, long addend)
#ifdef __LP64__
static Elf64_Word get_got(struct module *me, unsigned long value, long addend)
{
unsigned int i;
struct got_entry *got;
......@@ -261,10 +302,14 @@ static Elf_Addr get_got(struct module *me, unsigned long value, long addend)
if (got[i].addr == value)
return i * sizeof(struct got_entry);
BUG_ON(++me->arch.got_count > me->arch.got_max);
got[i].addr = value;
return i * sizeof(struct got_entry);
}
#endif /* __LP64__ */
#ifdef __LP64__
static Elf_Addr get_fdesc(struct module *me, unsigned long value)
{
struct fdesc_entry *fdesc = me->module_core + me->arch.fdesc_offset;
......@@ -281,32 +326,46 @@ static Elf_Addr get_fdesc(struct module *me, unsigned long value)
fdesc++;
}
BUG_ON(++me->arch.fdesc_count > me->arch.fdesc_max);
/* Create new one */
fdesc->addr = value;
fdesc->gp = (Elf_Addr)me->module_core + me->arch.got_offset;
return (Elf_Addr)fdesc;
}
#endif /* __LP64__ */
static Elf_Addr get_stub(struct module *me, unsigned long value, long addend,
int millicode)
int millicode, int init_section)
{
unsigned long i;
struct stub_entry *stub;
if(init_section) {
i = me->arch.init_stub_count++;
BUG_ON(me->arch.init_stub_count > me->arch.init_stub_max);
stub = me->module_init + me->arch.init_stub_offset +
i * sizeof(struct stub_entry);
} else {
i = me->arch.stub_count++;
BUG_ON(me->arch.stub_count > me->arch.stub_max);
stub = me->module_core + me->arch.stub_offset +
i * sizeof(struct stub_entry);
}
#ifndef __LP64__
/* for 32-bit the stub looks like this:
* ldil L'XXX,%r1
* be,n R'XXX(%sr4,%r1)
*/
//value = *(unsigned long *)((value + addend) & ~3); /* why? */
stub->insns[0] = 0x20200000; /* ldil L'XXX,%r1 */
stub->insns[1] = 0xe0202002; /* be,n R'XXX(%sr4,%r1) */
stub->insns[0] |= reassemble_21(lrsel(value, addend));
stub->insns[1] |= reassemble_17(rrsel(value, addend) / 4);
#else
/* for 64-bit we have two kinds of stubs:
* for normal function calls:
......@@ -328,7 +387,7 @@ static Elf_Addr get_stub(struct module *me, unsigned long value, long addend,
stub->insns[2] = 0xe820d000; /* bve (%r1) */
stub->insns[3] = 0x537b0030; /* ldd 18(%dp),%dp */
stub->insns[0] |= reassemble_21(get_got(me, value, addend));
stub->insns[0] |= reassemble_14(rrsel(get_got(me, value, addend),0));
}
else
{
......@@ -371,6 +430,7 @@ int apply_relocate_add(Elf_Shdr *sechdrs,
Elf32_Addr val;
Elf32_Sword addend;
Elf32_Addr dot;
//unsigned long dp = (unsigned long)$global$;
register unsigned long dp asm ("r27");
DEBUGP("Applying relocate section %u to %u\n", relsec,
......@@ -387,7 +447,8 @@ int apply_relocate_add(Elf_Shdr *sechdrs,
me->name, strtab + sym->st_name);
return -ENOENT;
}
dot = (sechdrs[relsec].sh_addr + rel->r_offset) & ~0x03;
//dot = (sechdrs[relsec].sh_addr + rel->r_offset) & ~0x03;
dot = (Elf32_Addr)loc & ~0x03;
val = sym->st_value;
addend = rel[i].r_addend;
......@@ -422,11 +483,13 @@ int apply_relocate_add(Elf_Shdr *sechdrs,
break;
case R_PARISC_DIR21L:
/* left 21 bits of effective address */
*loc = mask(*loc, 21) | reassemble_21(lrsel(val, addend));
val = lrsel(val, addend);
*loc = mask(*loc, 21) | reassemble_21(val);
break;
case R_PARISC_DIR14R:
/* right 14 bits of effective address */
*loc = mask(*loc, 14) | reassemble_14(rrsel(val, addend));
val = rrsel(val, addend);
*loc = mask(*loc, 14) | reassemble_14(val);
break;
case R_PARISC_SEGREL32:
/* 32-bit segment relative address */
......@@ -435,23 +498,27 @@ int apply_relocate_add(Elf_Shdr *sechdrs,
break;
case R_PARISC_DPREL21L:
/* left 21 bit of relative address */
val -= dp;
*loc = mask(*loc, 21) | reassemble_21(lrsel(val, addend) - dp);
val = lrsel(val - dp, addend);
*loc = mask(*loc, 21) | reassemble_21(val);
break;
case R_PARISC_DPREL14R:
/* right 14 bit of relative address */
val -= dp;
*loc = mask(*loc, 14) | reassemble_14(rrsel(val, addend) - dp);
val = rrsel(val - dp, addend);
*loc = mask(*loc, 14) | reassemble_14(val);
break;
case R_PARISC_PCREL17F:
/* 17-bit PC relative address */
val = get_stub(me, val, addend, 0) - dot - 8;
*loc = (*loc&0x1f1ffd) | reassemble_17(val);
val = get_stub(me, val, addend, 0, is_init(me, loc));
val = (val - dot - 8)/4;
CHECK_RELOC(val, 17)
*loc = (*loc & ~0x1f1ffd) | reassemble_17(val);
break;
case R_PARISC_PCREL22F:
/* 22-bit PC relative address; only defined for pa20 */
val = get_stub(me, val, addend, 0) - dot - 8;
*loc = (*loc&0x3ff1ffd) | reassemble_22(val);
val = get_stub(me, val, addend, 0, is_init(me, loc));
val = (val - dot - 8)/4;
CHECK_RELOC(val, 22);
*loc = (*loc & ~0x3ff1ffd) | reassemble_22(val);
break;
default:
......@@ -475,6 +542,7 @@ int apply_relocate_add(Elf_Shdr *sechdrs,
Elf64_Rela *rel = (void *)sechdrs[relsec].sh_addr;
Elf64_Sym *sym;
Elf64_Word *loc;
Elf64_Xword *loc64;
Elf64_Addr val;
Elf64_Sxword addend;
Elf64_Addr dot;
......@@ -493,14 +561,16 @@ int apply_relocate_add(Elf_Shdr *sechdrs,
me->name, strtab + sym->st_name);
return -ENOENT;
}
dot = (sechdrs[relsec].sh_addr + rel->r_offset) & ~0x03;
//dot = (sechdrs[relsec].sh_addr + rel->r_offset) & ~0x03;
dot = (Elf64_Addr)loc & ~0x03;
loc64 = (Elf64_Xword *)loc;
val = sym->st_value;
addend = rel[i].r_addend;
#if 1
#if 0
#define r(t) ELF64_R_TYPE(rel[i].r_info)==t ? #t :
DEBUGP("Symbol %s loc %p val 0x%Lx addend 0x%Lx: %s\n",
printk("Symbol %s loc %p val 0x%Lx addend 0x%Lx: %s\n",
strtab + sym->st_name,
loc, val, addend,
r(R_PARISC_LTOFF14R)
......@@ -516,24 +586,56 @@ int apply_relocate_add(Elf_Shdr *sechdrs,
switch (ELF64_R_TYPE(rel[i].r_info)) {
case R_PARISC_LTOFF21L:
/* LT-relative; left 21 bits */
*loc = mask(*loc, 21) | reassemble_21(get_got(me, val, addend));
val = get_got(me, val, addend);
DEBUGP("LTOFF21L Symbol %s loc %p val %lx\n",
strtab + sym->st_name,
loc, val);
val = lrsel(val, 0);
*loc = mask(*loc, 21) | reassemble_21(val);
break;
case R_PARISC_LTOFF14R:
/* L(ltoff(val+addend)) */
/* LT-relative; right 14 bits */
*loc = mask(*loc, 14) | reassemble_14(get_got(me, val, addend));
val = get_got(me, val, addend);
val = rrsel(val, 0);
DEBUGP("LTOFF14R Symbol %s loc %p val %lx\n",
strtab + sym->st_name,
loc, val);
*loc = mask(*loc, 14) | reassemble_14(val);
break;
case R_PARISC_PCREL22F:
/* PC-relative; 22 bits */
if (strncmp(strtab + sym->st_name, "$$", 2) == 0)
val = get_stub(me, val, addend, 1) - dot - 8;
DEBUGP("PCREL22F Symbol %s loc %p val %lx\n",
strtab + sym->st_name,
loc, val);
/* can we reach it locally? */
if(!is_local(me, (void *)val)) {
if (strncmp(strtab + sym->st_name, "$$", 2)
== 0)
val = get_stub(me, val, addend, 1,
is_init(me, loc));
else
val = get_stub(me, val, addend, 0) - dot - 8;
*loc = (*loc&0x3ff1ffd) | reassemble_22(val);
val = get_stub(me, val, addend, 0,
is_init(me, loc));
}
/* FIXME: local symbols work as long as the
* core and init pieces aren't separated too
* far. If this is ever broken, you will trip
* the check below. The way to fix it would
* be to generate local stubs to go between init
* and core */
if((Elf64_Sxword)(val - dot - 8) > 0x800000 -1 ||
(Elf64_Sxword)(val - dot - 8) < -0x800000) {
printk(KERN_ERR "Module %s, symbol %s is out of range for PCREL22F relocation\n",
me->name, strtab + sym->st_name);
return -ENOEXEC;
}
val = (val - dot - 8)/4;
*loc = (*loc & ~0x3ff1ffd) | reassemble_22(val);
break;
case R_PARISC_DIR64:
/* 64-bit effective address */
*loc = fsel(val, addend);
*loc64 = val + addend;
break;
case R_PARISC_SEGREL32:
/* 32-bit segment relative address */
......@@ -542,7 +644,17 @@ int apply_relocate_add(Elf_Shdr *sechdrs,
break;
case R_PARISC_FPTR64:
/* 64-bit function address */
*loc = get_fdesc(me, val+addend);
if(is_local(me, (void *)(val + addend))) {
*loc64 = get_fdesc(me, val+addend);
} else {
/* if the symbol is not local to this
* module then val+addend is a pointer
* to the function descriptor */
DEBUGP("Non local FPTR64 Symbol %s loc %p val %lx\n",
strtab + sym->st_name,
loc, val);
*loc64 = val + addend;
}
break;
default:
......@@ -559,13 +671,26 @@ int module_finalize(const Elf_Ehdr *hdr,
const Elf_Shdr *sechdrs,
struct module *me)
{
#ifdef __LP64__
me->init = (void *)get_fdesc(me, (Elf_Addr)me->init);
#ifdef CONFIG_MODULE_UNLOAD
if (me->exit)
me->exit = (void *)get_fdesc(me, (Elf_Addr)me->exit);
#endif
#ifdef DEBUG
struct fdesc_entry *entry;
u32 *addr;
entry = (struct fdesc_entry *)me->init;
printk("FINALIZE, ->init FPTR is %p, GP %lx ADDR %lx\n", entry,
entry->gp, entry->addr);
addr = (u32 *)entry->addr;
printk("INSNS: %x %x %x %x\n",
addr[0], addr[1], addr[2], addr[3]);
printk("stubs used %ld, stubs max %ld\n"
"init_stubs used %ld, init stubs max %ld\n"
"got entries used %ld, gots max %ld\n"
"fdescs used %ld, fdescs max %ld\n",
me->arch.stub_count, me->arch.stub_max,
me->arch.init_stub_count, me->arch.init_stub_max,
me->arch.got_count, me->arch.got_max,
me->arch.fdesc_count, me->arch.fdesc_max);
#endif
return 0;
}
......
......@@ -7,22 +7,24 @@
#include <linux/kernel.h>
#include <linux/string.h>
EXPORT_SYMBOL_NOVERS(memscan);
EXPORT_SYMBOL_NOVERS(memset);
EXPORT_SYMBOL(memchr);
EXPORT_SYMBOL(memcmp);
EXPORT_SYMBOL_NOVERS(memcpy);
EXPORT_SYMBOL(memcpy);
EXPORT_SYMBOL(memmove);
EXPORT_SYMBOL(memscan);
EXPORT_SYMBOL(memset);
EXPORT_SYMBOL(strcat);
EXPORT_SYMBOL(strchr);
EXPORT_SYMBOL(strrchr);
EXPORT_SYMBOL(strcmp);
EXPORT_SYMBOL(strcpy);
EXPORT_SYMBOL(strlen);
EXPORT_SYMBOL(strnlen);
EXPORT_SYMBOL(strncat);
EXPORT_SYMBOL(strncmp);
EXPORT_SYMBOL(strncpy);
EXPORT_SYMBOL(strnlen);
EXPORT_SYMBOL(strrchr);
EXPORT_SYMBOL(strstr);
EXPORT_SYMBOL(strpbrk);
#include <asm/hardware.h> /* struct parisc_device for asm/pci.h */
#include <linux/pci.h>
......@@ -39,7 +41,6 @@ EXPORT_SYMBOL(disable_irq);
#include <asm/processor.h>
EXPORT_SYMBOL(kernel_thread);
EXPORT_SYMBOL(boot_cpu_data);
EXPORT_SYMBOL(map_hpux_gateway_page);
#ifdef CONFIG_EISA
EXPORT_SYMBOL(EISA_bus);
#endif
......@@ -72,12 +73,16 @@ EXPORT_SYMBOL(lclear_user);
#ifndef __LP64__
/* Needed so insmod can set dp value */
extern int $global$;
EXPORT_SYMBOL_NOVERS($global$);
EXPORT_SYMBOL($global$);
#endif
EXPORT_SYMBOL(register_parisc_driver);
EXPORT_SYMBOL(unregister_parisc_driver);
EXPORT_SYMBOL(print_pci_hwpath);
EXPORT_SYMBOL(print_pa_hwpath);
EXPORT_SYMBOL(pdc_iodc_read);
EXPORT_SYMBOL(pdc_tod_read);
EXPORT_SYMBOL(pdc_tod_set);
#include <asm/io.h>
EXPORT_SYMBOL(__ioremap);
......@@ -105,7 +110,12 @@ EXPORT_SYMBOL(outsl);
#include <asm/cache.h>
EXPORT_SYMBOL(flush_kernel_dcache_range_asm);
EXPORT_SYMBOL(flush_kernel_dcache_page);
EXPORT_SYMBOL(flush_data_cache_local);
EXPORT_SYMBOL(flush_kernel_icache_range_asm);
EXPORT_SYMBOL(__flush_dcache_page);
EXPORT_SYMBOL(flush_all_caches);
EXPORT_SYMBOL(dcache_stride);
EXPORT_SYMBOL(flush_cache_all_local);
#include <asm/unistd.h>
extern long sys_open(const char *, int, int);
......@@ -131,6 +141,7 @@ EXPORT_SYMBOL(csum_partial_copy_from_user);
EXPORT_SYMBOL(pdc_add_valid);
EXPORT_SYMBOL(pdc_lan_station_id);
EXPORT_SYMBOL(pdc_get_initiator);
EXPORT_SYMBOL(pdc_sti_call);
extern void $$divI(void);
extern void $$divU(void);
......@@ -156,39 +167,39 @@ extern void $$divI_12(void);
extern void $$divI_14(void);
extern void $$divI_15(void);
EXPORT_SYMBOL_NOVERS($$divI);
EXPORT_SYMBOL_NOVERS($$divU);
EXPORT_SYMBOL_NOVERS($$remI);
EXPORT_SYMBOL_NOVERS($$remU);
EXPORT_SYMBOL_NOVERS($$mulI);
EXPORT_SYMBOL_NOVERS($$divU_3);
EXPORT_SYMBOL_NOVERS($$divU_5);
EXPORT_SYMBOL_NOVERS($$divU_6);
EXPORT_SYMBOL_NOVERS($$divU_9);
EXPORT_SYMBOL_NOVERS($$divU_10);
EXPORT_SYMBOL_NOVERS($$divU_12);
EXPORT_SYMBOL_NOVERS($$divU_7);
EXPORT_SYMBOL_NOVERS($$divU_14);
EXPORT_SYMBOL_NOVERS($$divU_15);
EXPORT_SYMBOL_NOVERS($$divI_3);
EXPORT_SYMBOL_NOVERS($$divI_5);
EXPORT_SYMBOL_NOVERS($$divI_6);
EXPORT_SYMBOL_NOVERS($$divI_7);
EXPORT_SYMBOL_NOVERS($$divI_9);
EXPORT_SYMBOL_NOVERS($$divI_10);
EXPORT_SYMBOL_NOVERS($$divI_12);
EXPORT_SYMBOL_NOVERS($$divI_14);
EXPORT_SYMBOL_NOVERS($$divI_15);
EXPORT_SYMBOL($$divI);
EXPORT_SYMBOL($$divU);
EXPORT_SYMBOL($$remI);
EXPORT_SYMBOL($$remU);
EXPORT_SYMBOL($$mulI);
EXPORT_SYMBOL($$divU_3);
EXPORT_SYMBOL($$divU_5);
EXPORT_SYMBOL($$divU_6);
EXPORT_SYMBOL($$divU_9);
EXPORT_SYMBOL($$divU_10);
EXPORT_SYMBOL($$divU_12);
EXPORT_SYMBOL($$divU_7);
EXPORT_SYMBOL($$divU_14);
EXPORT_SYMBOL($$divU_15);
EXPORT_SYMBOL($$divI_3);
EXPORT_SYMBOL($$divI_5);
EXPORT_SYMBOL($$divI_6);
EXPORT_SYMBOL($$divI_7);
EXPORT_SYMBOL($$divI_9);
EXPORT_SYMBOL($$divI_10);
EXPORT_SYMBOL($$divI_12);
EXPORT_SYMBOL($$divI_14);
EXPORT_SYMBOL($$divI_15);
extern void __ashrdi3(void);
extern void __ashldi3(void);
extern void __lshrdi3(void);
extern void __muldi3(void);
EXPORT_SYMBOL_NOVERS(__ashrdi3);
EXPORT_SYMBOL_NOVERS(__ashldi3);
EXPORT_SYMBOL_NOVERS(__lshrdi3);
EXPORT_SYMBOL_NOVERS(__muldi3);
EXPORT_SYMBOL(__ashrdi3);
EXPORT_SYMBOL(__ashldi3);
EXPORT_SYMBOL(__lshrdi3);
EXPORT_SYMBOL(__muldi3);
#ifdef __LP64__
extern void __divdi3(void);
......@@ -196,16 +207,16 @@ extern void __udivdi3(void);
extern void __umoddi3(void);
extern void __moddi3(void);
EXPORT_SYMBOL_NOVERS(__divdi3);
EXPORT_SYMBOL_NOVERS(__udivdi3);
EXPORT_SYMBOL_NOVERS(__umoddi3);
EXPORT_SYMBOL_NOVERS(__moddi3);
EXPORT_SYMBOL(__divdi3);
EXPORT_SYMBOL(__udivdi3);
EXPORT_SYMBOL(__umoddi3);
EXPORT_SYMBOL(__moddi3);
#endif
#ifndef __LP64__
extern void $$dyncall(void);
EXPORT_SYMBOL_NOVERS($$dyncall);
EXPORT_SYMBOL($$dyncall);
#endif
#include <asm/pgtable.h>
EXPORT_SYMBOL_NOVERS(vmalloc_start);
EXPORT_SYMBOL(vmalloc_start);
......@@ -24,6 +24,7 @@
#include <linux/sched.h>
#include <linux/interrupt.h>
#include <linux/major.h>
#include <linux/tty.h>
#include <asm/page.h>
#include <asm/types.h>
#include <asm/system.h>
......@@ -52,12 +53,24 @@ static int pdc_console_setup(struct console *co, char *options)
return 0;
}
#if defined(CONFIG_PDC_CONSOLE) || defined(CONFIG_SERIAL_MUX)
#if defined(CONFIG_PDC_CONSOLE)
#define PDC_CONSOLE_DEVICE pdc_console_device
static kdev_t pdc_console_device (struct console *c)
static struct tty_driver * pdc_console_device (struct console *c, int *index)
{
extern struct tty_driver console_driver;
*index = c->index ? c->index-1 : fg_console;
return &console_driver;
}
#elif defined(CONFIG_SERIAL_MUX)
#warning CONFIG_SERIAL_MUX
#define PDC_CONSOLE_DEVICE pdc_console_device
#warning "FIXME - should be: static struct tty_driver * pdc_console_device (struct console *c, int *index)"
static kdev_t pdc_console_device (struct console *c, int *index)
{
return mk_kdev(MUX_MAJOR, 0);
}
#else
#define PDC_CONSOLE_DEVICE NULL
#endif
......
......@@ -10,33 +10,23 @@
#define __KERNEL_SYSCALLS__
#include <stdarg.h>
#include <linux/elf.h>
#include <linux/errno.h>
#include <linux/sched.h>
#include <linux/kernel.h>
#include <linux/mm.h>
#include <linux/smp.h>
#include <linux/smp_lock.h>
#include <linux/personality.h>
#include <linux/ptrace.h>
#include <linux/sched.h>
#include <linux/stddef.h>
#include <linux/unistd.h>
#include <linux/ptrace.h>
#include <linux/slab.h>
#include <linux/vmalloc.h>
#include <linux/interrupt.h>
#include <linux/reboot.h>
#include <linux/init.h>
#include <linux/version.h>
#include <linux/elf.h>
#include <linux/personality.h>
#include <asm/machdep.h>
#include <asm/offsets.h>
#include <asm/uaccess.h>
#include <asm/pgtable.h>
#include <asm/pgalloc.h>
#include <asm/system.h>
#include <asm/io.h>
#include <asm/processor.h>
#include <asm/offsets.h>
#include <asm/pdc.h>
#include <asm/pdc_chassis.h>
#include <asm/pgalloc.h>
#include <asm/uaccess.h>
int hlt_counter;
......@@ -224,18 +214,14 @@ int
sys_clone(unsigned long clone_flags, unsigned long usp,
struct pt_regs *regs)
{
struct task_struct *p;
int *user_tid = (int *)regs->gr[26];
p = do_fork(clone_flags & ~CLONE_IDLETASK, usp, regs, 0, user_tid, NULL);
return IS_ERR(p) ? PTR_ERR(p) : p->pid;
return do_fork(clone_flags & ~CLONE_IDLETASK, usp, regs, 0, user_tid, NULL);
}
int
sys_vfork(struct pt_regs *regs)
{
struct task_struct *p;
p = do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs->gr[30], regs, 0, NULL, NULL);
return IS_ERR(p) ? PTR_ERR(p) : p->pid;
return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs->gr[30], regs, 0, NULL, NULL);
}
int
......@@ -251,7 +237,9 @@ copy_thread(int nr, unsigned long clone_flags, unsigned long usp,
* Make them const so the compiler knows they live in .text */
extern void * const ret_from_kernel_thread;
extern void * const child_return;
#ifdef CONFIG_HPUX
extern void * const hpux_child_return;
#endif
*cregs = *pregs;
......@@ -295,7 +283,11 @@ copy_thread(int nr, unsigned long clone_flags, unsigned long usp,
+ (pregs->gr[21] & (INIT_THREAD_SIZE - 1));
cregs->gr[30] = usp;
if (p->personality == PER_HPUX) {
#ifdef CONFIG_HPUX
cregs->kpc = (unsigned long) &hpux_child_return;
#else
BUG();
#endif
} else {
cregs->kpc = (unsigned long) &child_return;
}
......
......@@ -145,6 +145,7 @@ static int __init processor_probe(struct parisc_device *dev)
/* initialize counters */
memset(p, 0, sizeof(struct cpuinfo_parisc));
p->loops_per_jiffy = loops_per_jiffy;
p->dev = dev; /* Save IODC data in case we need it */
p->hpa = dev->hpa; /* save CPU hpa */
p->cpuid = cpuid; /* save CPU id */
......@@ -356,8 +357,8 @@ show_cpuinfo (struct seq_file *m, void *v)
show_cache_info(m);
seq_printf(m, "bogomips\t: %lu.%02lu\n",
loops_per_jiffy / (500000 / HZ),
(loops_per_jiffy / (5000 / HZ)) % 100);
cpu_data[n].loops_per_jiffy / (500000 / HZ),
(cpu_data[n].loops_per_jiffy / (5000 / HZ)) % 100);
seq_printf(m, "software id\t: %ld\n\n",
boot_cpu_data.pdc.model.sw_id);
......
......@@ -309,7 +309,8 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
}
#endif
#if CACHE_FLUSHING_IS_NOT_BROKEN
#undef CACHE_FLUSHING_IS_NOT_BROKEN
#ifdef CACHE_FLUSHING_IS_NOT_BROKEN
flush_user_icache_range((unsigned long) &frame->tramp[0],
(unsigned long) &frame->tramp[4]);
#else
......
......@@ -147,7 +147,7 @@ halt_processor(void)
}
void
irqreturn_t
ipi_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
int this_cpu = smp_processor_id();
......@@ -256,7 +256,7 @@ ipi_interrupt(int irq, void *dev_id, struct pt_regs *regs)
} /* Switch */
} /* while (ops) */
}
return;
return IRQ_HANDLED;
}
......@@ -515,14 +515,14 @@ static struct task_struct *fork_by_hand(void)
* don't care about the regs settings since
* we'll never reschedule the forked task.
*/
return do_fork(CLONE_VM|CLONE_IDLETASK, 0, &regs, 0, NULL, NULL);
return copy_process(CLONE_VM|CLONE_IDLETASK, 0, &regs, 0, NULL, NULL);
}
/*
* Bring one cpu online.
*/
static int smp_boot_one_cpu(int cpuid, int cpunum)
static int __init smp_boot_one_cpu(int cpuid, int cpunum)
{
struct task_struct *idle;
long timeout;
......@@ -537,9 +537,11 @@ static int smp_boot_one_cpu(int cpuid, int cpunum)
* Sheesh . . .
*/
if ((idle = fork_by_hand()) == 0)
idle = fork_by_hand();
if (IS_ERR(idle))
panic("SMP: fork failed for CPU:%d", cpuid);
wake_up_forked_process(idle);
init_idle(idle, cpunum);
unhash_process(idle);
idle->thread_info->cpu = cpunum;
......@@ -613,7 +615,7 @@ static int smp_boot_one_cpu(int cpuid, int cpunum)
void __init smp_boot_cpus(void)
{
int i, cpu_count = 1;
unsigned long bogosum = loops_per_jiffy; /* Count Monarch */
unsigned long bogosum = cpu_data[0].loops_per_jiffy; /* Count Monarch */
/* REVISIT - assumes first CPU reported by PAT PDC is BSP */
int bootstrap_processor=cpu_data[0].cpuid; /* CPU ID of BSP */
......@@ -650,7 +652,7 @@ void __init smp_boot_cpus(void)
if (smp_boot_one_cpu(cpu_data[i].cpuid, cpu_count) < 0)
continue;
bogosum += loops_per_jiffy;
bogosum += cpu_data[i].loops_per_jiffy;
cpu_count++; /* Count good CPUs only... */
cpu_present_mask |= 1UL << i;
......
......@@ -30,10 +30,7 @@
#include <linux/slab.h>
#include <linux/uio.h>
#include <linux/nfs_fs.h>
#include <linux/smb_fs.h>
#include <linux/smb_mount.h>
#include <linux/ncp_fs.h>
#include <linux/quota.h>
#include <linux/sunrpc/svc.h>
#include <linux/nfsd/nfsd.h>
#include <linux/nfsd/cache.h>
......@@ -42,11 +39,6 @@
#include <linux/poll.h>
#include <linux/personality.h>
#include <linux/stat.h>
#include <linux/filter.h> /* for setsockopt() */
#include <linux/icmpv6.h> /* for setsockopt() */
#include <linux/netfilter_ipv4/ip_queue.h> /* for setsockopt() */
#include <linux/netfilter_ipv4/ip_tables.h> /* for setsockopt() */
#include <linux/netfilter_ipv6/ip6_tables.h> /* for setsockopt() */
#include <linux/highmem.h>
#include <linux/highuid.h>
#include <linux/mman.h>
......@@ -62,9 +54,6 @@
#include "sys32.h"
#define A(__x) ((unsigned long)(__x))
#undef DEBUG
#ifdef DEBUG
......@@ -73,34 +62,6 @@
#define DBG(x)
#endif
/* For this source file, we want overflow handling. */
#undef high2lowuid
#undef high2lowgid
#undef low2highuid
#undef low2highgid
#undef SET_UID16
#undef SET_GID16
#undef NEW_TO_OLD_UID
#undef NEW_TO_OLD_GID
#undef SET_OLDSTAT_UID
#undef SET_OLDSTAT_GID
#undef SET_STAT_UID
#undef SET_STAT_GID
#define high2lowuid(uid) ((uid) > 65535) ? (u16)overflowuid : (u16)(uid)
#define high2lowgid(gid) ((gid) > 65535) ? (u16)overflowgid : (u16)(gid)
#define low2highuid(uid) ((uid) == (u16)-1) ? (uid_t)-1 : (uid_t)(uid)
#define low2highgid(gid) ((gid) == (u16)-1) ? (gid_t)-1 : (gid_t)(gid)
#define SET_UID16(var, uid) var = high2lowuid(uid)
#define SET_GID16(var, gid) var = high2lowgid(gid)
#define NEW_TO_OLD_UID(uid) high2lowuid(uid)
#define NEW_TO_OLD_GID(gid) high2lowgid(gid)
#define SET_OLDSTAT_UID(stat, uid) (stat).st_uid = high2lowuid(uid)
#define SET_OLDSTAT_GID(stat, gid) (stat).st_gid = high2lowgid(gid)
#define SET_STAT_UID(stat, uid) (stat).st_uid = high2lowuid(uid)
#define SET_STAT_GID(stat, gid) (stat).st_gid = high2lowgid(gid)
/*
* count32() counts the number of arguments/envelopes. It is basically
* a copy of count() from fs/exec.c, except that it works
......@@ -145,7 +106,7 @@ static int copy_strings32(int argc, u32 *argv, struct linux_binprm *bprm)
if (get_user(str, argv + argc) ||
!str ||
!(len = strnlen_user((char *)A(str), bprm->p)))
!(len = strnlen_user((char *)compat_ptr(str), bprm->p)))
return -EFAULT;
if (bprm->p < len)
......@@ -181,7 +142,7 @@ static int copy_strings32(int argc, u32 *argv, struct linux_binprm *bprm)
if (new)
memset(kaddr+offset+len, 0, PAGE_SIZE-offset-len);
}
err = copy_from_user(kaddr + offset, (char *)A(str), bytes_to_copy);
err = copy_from_user(kaddr + offset, (char *)compat_ptr(str), bytes_to_copy);
flush_dcache_page(page);
kunmap(page);
......@@ -784,7 +745,7 @@ do_readv_writev32(int type, struct file *file, const struct compat_iovec *vector
__get_user(len, &vector->iov_len);
__get_user(buf, &vector->iov_base);
tot_len += len;
ivp->iov_base = (void *)A(buf);
ivp->iov_base = compat_ptr(buf);
ivp->iov_len = (compat_size_t) len;
vector++;
ivp++;
......@@ -1215,67 +1176,6 @@ asmlinkage int sys32_nfsservctl(int cmd, void *argp, void *resp)
return ret;
}
#include <linux/quota.h>
struct dqblk32 {
__u32 dqb_bhardlimit;
__u32 dqb_bsoftlimit;
__u32 dqb_curblocks;
__u32 dqb_ihardlimit;
__u32 dqb_isoftlimit;
__u32 dqb_curinodes;
compat_time_t dqb_btime;
compat_time_t dqb_itime;
};
asmlinkage int sys32_quotactl(int cmd, const char *special, int id, unsigned long addr)
{
#if 0
extern int sys_quotactl(int cmd, const char *special, int id, caddr_t addr);
int cmds = cmd >> SUBCMDSHIFT;
int err;
struct dqblk d;
char *spec;
switch (cmds) {
case Q_GETQUOTA:
break;
case Q_SETQUOTA:
case Q_SETUSE:
case Q_SETQLIM:
if (copy_from_user (&d, (struct dqblk32 *)addr,
sizeof (struct dqblk32)))
return -EFAULT;
d.dqb_itime = ((struct dqblk32 *)&d)->dqb_itime;
d.dqb_btime = ((struct dqblk32 *)&d)->dqb_btime;
break;
default:
return sys_quotactl(cmd, special,
id, (caddr_t)addr);
}
spec = getname (special);
err = PTR_ERR(spec);
if (IS_ERR(spec)) return err;
KERNEL_SYSCALL(err, sys_quotactl, cmd, (const char *)spec, id, (caddr_t)&d);
putname (spec);
if (cmds == Q_GETQUOTA) {
__kernel_time_t b = d.dqb_btime, i = d.dqb_itime;
((struct dqblk32 *)&d)->dqb_itime = i;
((struct dqblk32 *)&d)->dqb_btime = b;
if (copy_to_user ((struct dqblk32 *)addr, &d,
sizeof (struct dqblk32)))
return -EFAULT;
}
return err;
#endif
/* TODO */
BUG();
return -EINVAL;
}
extern asmlinkage ssize_t sys_sendfile64(int out_fd, int in_fd, loff_t *offset, size_t count);
typedef long __kernel_loff_t32; /* move this to asm/posix_types.h? */
......
......@@ -496,7 +496,7 @@ sys_call_table:
ENTRY_SAME(delete_module)
ENTRY_SAME(ni_syscall) /* 130: get_kernel_syms */
/* time_t inside struct dqblk */
ENTRY_DIFF(quotactl) /* -- FIXME, doesn't work */
ENTRY_SAME(quotactl)
ENTRY_SAME(getpgid)
ENTRY_SAME(fchdir)
ENTRY_SAME(bdflush)
......
......@@ -76,7 +76,7 @@ parisc_do_profile(struct pt_regs *regs)
atomic_inc((atomic_t *)&prof_buffer[pc]);
}
void timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
irqreturn_t timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
long now;
long next_tick;
......@@ -127,6 +127,8 @@ void timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
/* check soft power switch status */
if (cpu == 0 && !atomic_read(&power_tasklet.count))
tasklet_schedule(&power_tasklet);
return IRQ_HANDLED;
}
/*** converted from ia64 ***/
......
......@@ -114,6 +114,12 @@ void show_regs(struct pt_regs *regs)
printk("%s CPU: %8d CR30: " RFMT " CR31: " RFMT "\n",
level, current_thread_info()->cpu, cr30, cr31);
printk("%s ORIG_R28: " RFMT "\n", level, regs->orig_r28);
printk(level);
print_symbol(" IAOQ[0]: %s\n", regs->iaoq[0]);
printk(level);
print_symbol(" IAOQ[1]: %s\n", regs->iaoq[1]);
printk(level);
print_symbol(" RP(r2): %s\n", regs->gr[2]);
}
......
......@@ -10,6 +10,7 @@
#include <linux/config.h>
#include <linux/module.h>
#include <linux/mm.h>
#include <linux/bootmem.h>
#include <linux/delay.h>
......@@ -666,6 +667,7 @@ static void __init gateway_init(void)
PAGE_SIZE, PAGE_GATEWAY);
}
#ifdef CONFIG_HPUX
void
map_hpux_gateway_page(struct task_struct *tsk, struct mm_struct *mm)
{
......@@ -734,6 +736,8 @@ map_hpux_gateway_page(struct task_struct *tsk, struct mm_struct *mm)
pg_table = (pte_t *) __va(pg_table) + start_pte;
set_pte(pg_table, __mk_pte(address, PAGE_GATEWAY));
}
EXPORT_SYMBOL(map_hpux_gateway_page);
#endif
extern void flush_tlb_all_local(void);
......
......@@ -7,9 +7,10 @@
* @author John Levon <levon@movementarian.org>
*/
#include <linux/errno.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/oprofile.h>
#include <linux/init.h>
extern void timer_init(struct oprofile_operations ** ops);
......
......@@ -125,4 +125,27 @@ config CHASSIS_LCD_LED
If unsure, say Y.
config HOTPLUG
bool "Support for hot-pluggable devices"
---help---
Say Y here if you want to plug devices into your computer while
the system is running, and be able to use them quickly. In many
cases, the devices can likewise be unplugged at any time too.
One well known example of this is PCMCIA- or PC-cards, credit-card
size devices such as network cards, modems or hard drives which are
plugged into slots found on all modern laptop computers. Another
example, used on modern desktops as well as laptops, is USB.
Enable HOTPLUG and KMOD, and build a modular kernel. Get agent
software (at <http://linux-hotplug.sourceforge.net/>) and install it.
Then your kernel will automatically call out to a user mode "policy
agent" (/sbin/hotplug) to load modules and set up software needed
to use devices as you hotplug them.
source "drivers/pcmcia/Kconfig"
source "drivers/pci/hotplug/Kconfig"
endmenu
......@@ -381,7 +381,7 @@ static struct irq_region_ops dino_irq_ops = {
* ilr_loop counter is a kluge to prevent a "stuck" IRQ line from
* wedging the CPU. Could be removed or made optional at some point.
*/
static void
static irqreturn_t
dino_isr(int irq, void *intr_dev, struct pt_regs *regs)
{
struct dino_device *dino_dev = DINO_DEV(intr_dev);
......@@ -441,7 +441,9 @@ dino_isr(int irq, void *intr_dev, struct pt_regs *regs)
if (--ilr_loop > 0)
goto ilr_again;
printk("Dino %lx: stuck interrupt %d\n", dino_dev->hba.base_addr, mask);
return IRQ_NONE;
}
return IRQ_HANDLED;
}
static int dino_choose_irq(struct parisc_device *dev)
......
......@@ -213,7 +213,7 @@ static struct irq_region eisa_irq_region = {
.action = action,
};
static void eisa_irq(int _, void *intr_dev, struct pt_regs *regs)
static irqreturn_t eisa_irq(int _, void *intr_dev, struct pt_regs *regs)
{
extern void do_irq(struct irqaction *a, int i, struct pt_regs *p);
int irq = gsc_readb(0xfc01f000); /* EISA supports 16 irqs */
......@@ -262,11 +262,13 @@ static void eisa_irq(int _, void *intr_dev, struct pt_regs *regs)
eisa_out8(master_mask, 0x21);
}
spin_unlock_irqrestore(&eisa_irq_lock, flags);
return IRQ_HANDLED;
}
static void dummy_irq2_handler(int _, void *dev, struct pt_regs *regs)
static irqreturn_t dummy_irq2_handler(int _, void *dev, struct pt_regs *regs)
{
printk(KERN_ALERT "eisa: uhh, irq2?\n");
return IRQ_HANDLED;
}
static void init_eisa_pic(void)
......
......@@ -4,6 +4,7 @@
#include <linux/kernel.h>
#include <linux/miscdevice.h>
#include <linux/slab.h>
#include <linux/fs.h>
#include <asm/io.h>
#include <asm/uaccess.h>
#include <asm/eisa_eeprom.h>
......
......@@ -79,7 +79,7 @@ EXPORT_SYMBOL(gsc_claim_irq);
#define GSC_MASK_IRQ(x) (1<<(GSC_FIX_IRQ(x)))
/* Common interrupt demultiplexer used by Asp, Lasi & Wax. */
void busdev_barked(int busdev_irq, void *dev, struct pt_regs *regs)
irqreturn_t busdev_barked(int busdev_irq, void *dev, struct pt_regs *regs)
{
unsigned long irq;
struct busdevice *busdev = (struct busdevice *) dev;
......@@ -101,6 +101,7 @@ void busdev_barked(int busdev_irq, void *dev, struct pt_regs *regs)
do_irq_mask(irq, busdev->busdev_region, regs);
}
return IRQ_HANDLED;
}
static void
......
......@@ -43,4 +43,4 @@ int gsc_common_irqsetup(struct parisc_device *parent, struct busdevice *busdev);
extern int gsc_alloc_irq(struct gsc_irq *dev); /* dev needs an irq */
extern int gsc_claim_irq(struct gsc_irq *dev, int irq); /* dev needs this irq */
void busdev_barked(int busdev_irq, void *dev, struct pt_regs *regs);
irqreturn_t busdev_barked(int busdev_irq, void *dev, struct pt_regs *regs);
......@@ -605,7 +605,7 @@ iosapic_xlate_pin(struct iosapic_info *isi, struct pci_dev *pcidev)
}
static void
static irqreturn_t
iosapic_interrupt(int irq, void *dev_id, struct pt_regs * regs)
{
struct vector_info *vi = (struct vector_info *)dev_id;
......@@ -623,6 +623,8 @@ iosapic_interrupt(int irq, void *dev_id, struct pt_regs * regs)
** I/O SAPIC must always issue EOI.
*/
IOSAPIC_EOI(vi->vi_eoi_addr, vi->vi_eoi_data);
return IRQ_HANDLED;
}
......
......@@ -3,7 +3,7 @@
*
* (c) Copyright 2000 Red Hat Software
* (c) Copyright 2000 Helge Deller <hdeller@redhat.com>
* (c) Copyright 2001-2002 Helge Deller <deller@gmx.de>
* (c) Copyright 2001-2003 Helge Deller <deller@gmx.de>
* (c) Copyright 2001 Randolph Chung <tausq@debian.org>
*
* This program is free software; you can redistribute it and/or modify
......@@ -13,7 +13,7 @@
*
* TODO:
* - speed-up calculations with inlined assembler
* - interface to write to second row of LCD from /proc
* - interface to write to second row of LCD from /proc (if technically possible)
*/
#include <linux/config.h>
......@@ -22,10 +22,11 @@
#include <linux/init.h>
#include <linux/types.h>
#include <linux/ioport.h>
#include <linux/bitops.h>
#include <linux/version.h>
#include <linux/delay.h>
#include <linux/netdevice.h>
#include <linux/inetdevice.h>
#include <linux/in.h>
#include <linux/interrupt.h>
#include <linux/kernel_stat.h>
#include <linux/reboot.h>
......@@ -59,10 +60,6 @@ static char lcd_text[32];
#endif
#define CALC_ADD(val, comp, add) \
(val<=(comp/8) ? add/16 : val<=(comp/4) ? add/8 : val<=(comp/2) ? add/4 : add)
struct lcd_block {
unsigned char command; /* stores the command byte */
unsigned char on; /* value for turning LED on */
......@@ -341,93 +338,81 @@ static void led_LCD_driver(unsigned char leds)
/*
**
** led_get_net_stats()
**
** calculate the TX- & RX-troughput on the network interfaces in
** the system for usage in the LED code
** led_get_net_activity()
**
** calculate if there was TX- or RX-troughput on the network interfaces
** (analog to dev_get_info() from net/core/dev.c)
**
*/
static unsigned long led_net_rx_counter, led_net_tx_counter;
static void led_get_net_stats(int addvalue)
static __inline__ int led_get_net_activity(void)
{
#ifdef CONFIG_NET
#ifndef CONFIG_NET
return 0;
#else
static unsigned long rx_total_last, tx_total_last;
unsigned long rx_total, tx_total;
struct net_device *dev;
struct net_device_stats *stats;
int retval;
rx_total = tx_total = 0;
/* we are running as a tasklet, so locking dev_base
/* we are running as tasklet, so locking dev_base
* for reading should be OK */
read_lock(&dev_base_lock);
for (dev = dev_base; dev != NULL; dev = dev->next) {
if (dev->get_stats) {
for (dev = dev_base; dev; dev = dev->next) {
struct net_device_stats *stats;
struct in_device *in_dev = __in_dev_get(dev);
if (!in_dev || !in_dev->ifa_list)
continue;
if (LOOPBACK(in_dev->ifa_list->ifa_local))
continue;
if (!dev->get_stats)
continue;
stats = dev->get_stats(dev);
rx_total += stats->rx_packets;
tx_total += stats->tx_packets;
}
}
read_unlock(&dev_base_lock);
rx_total -= rx_total_last;
tx_total -= tx_total_last;
retval = 0;
if (rx_total)
led_net_rx_counter += CALC_ADD(rx_total, tx_total, addvalue);
if (rx_total != rx_total_last) {
rx_total_last = rx_total;
retval |= LED_LAN_RCV;
}
if (tx_total)
led_net_tx_counter += CALC_ADD(tx_total, rx_total, addvalue);
if (tx_total != tx_total_last) {
tx_total_last = tx_total;
retval |= LED_LAN_TX;
}
rx_total_last += rx_total;
tx_total_last += tx_total;
return retval;
#endif
}
/*
**
** led_get_diskio_stats()
** led_get_diskio_activity()
**
** calculate the disk-io througput in the system
** (analog to linux/fs/proc/proc_misc.c)
** calculate if there was disk-io in the system
**
*/
static unsigned long led_diskio_counter;
static void led_get_diskio_stats(int addvalue)
static __inline__ int led_get_diskio_activity(void)
{
static unsigned int diskio_total_last, diskio_max;
int major, disk, total;
static unsigned long last_pgpgin, last_pgpgout;
struct page_state pgstat;
int changed;
total = 0;
#if 0
/*
* this section will no longer work in 2.5, as we no longer
* have either kstat.dk_drive nor DK_MAX_*. It can probably
* be rewritten to use the per-disk statistics now kept in the
* gendisk, but since I have no HP machines to test it on, I'm
* not really up to that. ricklind@us.ibm.com 11/7/02
*/
for (major = 0; major < DK_MAX_MAJOR; major++) {
for (disk = 0; disk < DK_MAX_DISK; disk++)
total += dkstat.drive[major][disk];
}
total -= diskio_total_last;
if (total) {
if (total >= diskio_max) {
led_diskio_counter += addvalue;
diskio_max = total; /* new maximum value found */
} else
led_diskio_counter += CALC_ADD(total, diskio_max, addvalue);
}
#endif
get_full_page_state(&pgstat); /* get no of sectors in & out */
/* Just use a very simple calculation here. Do not care about overflow,
since we only want to know if there was activity or not. */
changed = (pgstat.pgpgin != last_pgpgin) || (pgstat.pgpgout != last_pgpgout);
last_pgpgin = pgstat.pgpgin;
last_pgpgout = pgstat.pgpgout;
diskio_total_last += total;
return (changed ? LED_DISK_IO : 0);
}
......@@ -443,16 +428,23 @@ static void led_get_diskio_stats(int addvalue)
- optimizations
*/
static unsigned char currentleds; /* stores current value of the LEDs */
#define HEARTBEAT_LEN (HZ*6/100)
#define HEARTBEAT_2ND_RANGE_START (HZ*22/100)
#define HEARTBEAT_2ND_RANGE_END (HEARTBEAT_2ND_RANGE_START + HEARTBEAT_LEN)
#if HZ==100
#define NORMALIZED_COUNT(count) (count)
#else
#warning "Untested situation HZ != 100 !!"
#define NORMALIZED_COUNT(count) (count/(HZ/100))
#endif
static void led_tasklet_func(unsigned long unused)
{
static unsigned int count, count_HZ;
static unsigned char lastleds;
unsigned char currentleds; /* stores current value of the LEDs */
static unsigned long count; /* static incremented value, not wrapped */
static unsigned long count_HZ; /* counter in range 0..HZ */
/* exit if not initialized */
if (!led_func_ptr)
......@@ -463,6 +455,8 @@ static void led_tasklet_func(unsigned long unused)
if (++count_HZ == HZ)
count_HZ = 0;
currentleds = lastleds;
if (led_heartbeat)
{
/* flash heartbeat-LED like a real heart (2 x short then a long delay) */
......@@ -473,40 +467,23 @@ static void led_tasklet_func(unsigned long unused)
currentleds &= ~LED_HEARTBEAT;
}
/* gather network and diskio statistics and flash LEDs respectively */
if (led_lanrxtx)
/* look for network activity and flash LEDs respectively */
if (led_lanrxtx && ((NORMALIZED_COUNT(count)+(8/2)) & 7) == 0)
{
if ((count & 31) == 0)
led_get_net_stats(30);
if (led_net_rx_counter) {
led_net_rx_counter--;
currentleds |= LED_LAN_RCV;
currentleds &= ~(LED_LAN_RCV | LED_LAN_TX);
currentleds |= led_get_net_activity();
}
else
currentleds &= ~LED_LAN_RCV;
if (led_net_tx_counter) {
led_net_tx_counter--;
currentleds |= LED_LAN_TX;
}
else
currentleds &= ~LED_LAN_TX;
}
if (led_diskio)
/* avoid to calculate diskio-stats at same irq as netio-stats */
if (led_diskio && (NORMALIZED_COUNT(count) & 7) == 0)
{
/* avoid to calculate diskio-stats at same irq as netio-stats ! */
if ((count & 31) == 15)
led_get_diskio_stats(30);
if (led_diskio_counter) {
led_diskio_counter--;
currentleds |= LED_DISK_IO;
}
else
currentleds &= ~LED_DISK_IO;
currentleds |= led_get_diskio_activity();
}
/* blink all LEDs twice a second if we got an Oops (HPMC) */
if (oops_in_progress) {
currentleds = (count_HZ<=(HZ/2)) ? 0 : 0xff;
}
/* update the LCD/LEDs */
......
......@@ -90,7 +90,7 @@ superio_inform_irq(int irq)
sio_dev.iosapic_irq = irq;
}
static void
static irqreturn_t
superio_interrupt(int irq, void *devp, struct pt_regs *regs)
{
struct superio_device *sio = (struct superio_device *)devp;
......@@ -107,7 +107,7 @@ superio_interrupt(int irq, void *devp, struct pt_regs *regs)
/* HACK: need to investigate why this happens if SMP enabled */
BUG(); /* This shouldn't happen */
#endif
return;
return IRQ_HANDLED;
}
/* Check to see which device is interrupting */
......@@ -117,7 +117,7 @@ superio_interrupt(int irq, void *devp, struct pt_regs *regs)
if (local_irq == 2 || local_irq > 7) {
printk(KERN_ERR "SuperIO: slave interrupted!\n");
BUG();
return;
return IRQ_HANDLED;
}
if (local_irq == 7) {
......@@ -128,7 +128,7 @@ superio_interrupt(int irq, void *devp, struct pt_regs *regs)
results = inb(IC_PIC1+0);
if ((results & 0x80) == 0) { /* if ISR7 not set: spurious */
printk(KERN_WARNING "SuperIO: spurious interrupt!\n");
return;
return IRQ_HANDLED;
}
}
......@@ -141,7 +141,7 @@ superio_interrupt(int irq, void *devp, struct pt_regs *regs)
/* set EOI */
outb((OCW2_SEOI|local_irq),IC_PIC1 + 0);
return;
return IRQ_HANDLED;
}
/* Initialize Super I/O device */
......
......@@ -81,9 +81,10 @@ static int clear_epp_timeout(struct parport *pb)
* of these are in parport_gsc.h.
*/
static void parport_gsc_interrupt(int irq, void *dev_id, struct pt_regs *regs)
static irqreturn_t parport_gsc_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
parport_generic_irq(irq, (struct parport *) dev_id, regs);
return IRQ_HANDLED;
}
void parport_gsc_write_data(struct parport *p, unsigned char d)
......
......@@ -1076,3 +1076,9 @@ struct sti_struct * sti_get_rom(unsigned int index)
return sti_roms[index-1];
}
EXPORT_SYMBOL(sti_get_rom);
MODULE_AUTHOR("Philipp Rumpf, Helge Deller, Thomas Bogendoerfer");
MODULE_DESCRIPTION("Core STI driver for HP's NGLE series graphics cards in HP PARISC machines");
MODULE_LICENSE("GPL v2");
......@@ -66,6 +66,7 @@
#include <linux/pci.h>
#include <asm/grfioctl.h> /* for HP-UX compatibility */
#include <asm/uaccess.h>
#include "sticore.h"
......@@ -111,6 +112,7 @@ struct stifb_info {
int deviceSpecificConfig;
};
static int __initdata bpp = 8; /* parameter from modprobe */
static int __initdata stifb_force_bpp[MAX_STI_ROMS];
/* ------------------- chipset specific functions -------------------------- */
......@@ -1336,6 +1338,8 @@ stifb_init(void)
sti = sti_get_rom(i);
if (!sti)
break;
if (bpp > 0)
stifb_force_bpp[i] = bpp;
stifb_init_fb(sti, stifb_force_bpp[i]);
}
return 0;
......@@ -1355,8 +1359,14 @@ stifb_cleanup(void)
sti = sti_get_rom(i);
if (!sti)
break;
if (sti->info)
if (sti->info) {
struct fb_info *info = sti->info;
unregister_framebuffer(sti->info);
release_mem_region(info->fix.mmio_start, info->fix.mmio_len);
release_mem_region(info->fix.smem_start, info->fix.smem_len);
fb_dealloc_cmap(&info->cmap);
kfree(info);
}
sti->info = NULL;
}
}
......@@ -1372,9 +1382,10 @@ stifb_setup(char *options)
if (strncmp(options, "bpp", 3) == 0) {
options += 3;
for (i = 0; i < MAX_STI_ROMS; i++) {
if (*options++ == ':')
if (*options++ == ':') {
stifb_force_bpp[i] = simple_strtoul(options, &options, 10);
else
bpp = -1;
} else
break;
}
}
......@@ -1390,7 +1401,7 @@ module_exit(stifb_cleanup);
MODULE_AUTHOR("Helge Deller <deller@gmx.de>, Thomas Bogendoerfer <tsbogend@alpha.franken.de>");
MODULE_DESCRIPTION("Framebuffer driver for HP's NGLE series graphics cards in HP PARISC machines");
MODULE_LICENSE("GPL");
MODULE_LICENSE("GPL v2");
MODULE_PARM(bpp, "i");
MODULE_PARM_DESC(mem, "Bits per pixel (default: 8)");
......
......@@ -4,6 +4,7 @@
* Architecture specific compatibility types
*/
#include <linux/types.h>
#include <linux/sched.h>
#define COMPAT_USER_HZ 100
......@@ -124,4 +125,12 @@ static inline void *compat_ptr(compat_uptr_t uptr)
return (void *)(unsigned long)uptr;
}
static __inline__ void *compat_alloc_user_space(long len)
{
struct pt_regs *regs = &current->thread.regs;
unsigned long usp = regs->gr[30];
return (void *)(usp + len);
}
#endif /* _ASM_PARISC_COMPAT_H */
......@@ -178,10 +178,11 @@
#define PF_HP_SBP 0x08000000
/*
* The following definitions are those for 32-bit ELF binaries on a 32-bit kernel
* and for 64-bit binaries on a 64-bit kernel. To run 32-bit binaries on a 64-bit
* kernel, arch/parisc64/kernel/binfmt_elf32.c defines these macros appropriately
* and then #includes binfmt_elf.c, which then includes this file.
* The following definitions are those for 32-bit ELF binaries on a 32-bit
* kernel and for 64-bit binaries on a 64-bit kernel. To run 32-bit binaries
* on a 64-bit kernel, arch/parisc64/kernel/binfmt_elf32.c defines these
* macros appropriately and then #includes binfmt_elf.c, which then includes
* this file.
*/
#ifndef ELF_CLASS
......@@ -267,6 +268,8 @@ typedef elf_greg_t elf_gregset_t[ELF_NGREG];
typedef double elf_fpreg_t;
typedef elf_fpreg_t elf_fpregset_t[ELF_NFPREG];
struct task_struct;
extern int dump_task_fpu (struct task_struct *, elf_fpregset_t *);
#define ELF_CORE_COPY_FPREGS(tsk, elf_fpregs) dump_task_fpu(tsk, elf_fpregs)
......
......@@ -4,9 +4,16 @@
/*
* Allocate a 8 Mb temporary mapping area for copy_user_page/clear_user_page.
* This area needs to be aligned on a 8 Mb boundary.
*
* FIXME:
*
* For PA-RISC, this has no meaning. It is starting to be used on x86
* for vsyscalls. PA will probably do this using space registers.
*/
/* This TMPALIAS_MAP_START reserves some of the memory where the
* FIXMAP region is on x86. It's only real use is to constrain
* VMALLOC_END (see pktable.h) */
#define TMPALIAS_MAP_START (__PAGE_OFFSET - 0x01000000)
#define FIXADDR_START ((unsigned long)TMPALIAS_MAP_START)
#endif
......@@ -24,10 +24,10 @@
struct mod_arch_specific
{
unsigned long got_offset;
unsigned long fdesc_offset, fdesc_count;
unsigned long stub_offset;
unsigned long stub_count;
unsigned long got_offset, got_count, got_max;
unsigned long fdesc_offset, fdesc_count, fdesc_max;
unsigned long stub_offset, stub_count, stub_max;
unsigned long init_stub_offset, init_stub_count, init_stub_max;
};
#endif /* _ASM_PARISC_MODULE_H */
......@@ -35,7 +35,7 @@
*/
int pdc_chassis_send_status(int message);
void __init parisc_pdc_chassis_init(void);
void parisc_pdc_chassis_init(void);
/*
......
......@@ -109,7 +109,8 @@ extern void *vmalloc_start;
#define PCXL_DMA_MAP_SIZE (8*1024*1024)
#define VMALLOC_START ((unsigned long)vmalloc_start)
#define VMALLOC_VMADDR(x) ((unsigned long)(x))
#define VMALLOC_END (FIXADDR_START)
/* this is a fixmap remnant, see fixmap.h */
#define VMALLOC_END (TMPALIAS_MAP_START)
#endif
/* NB: The tlb miss handlers make certain assumptions about the order */
......@@ -122,6 +123,7 @@ extern void *vmalloc_start;
#define _PAGE_GATEWAY_BIT 28 /* (0x008) privilege promotion allowed */
#define _PAGE_DMB_BIT 27 /* (0x010) Data Memory Break enable (B bit) */
#define _PAGE_DIRTY_BIT 26 /* (0x020) Page Dirty (D bit) */
#define _PAGE_FILE_BIT _PAGE_DIRTY_BIT /* overload this bit */
#define _PAGE_REFTRAP_BIT 25 /* (0x040) Page Ref. Trap enable (T bit) */
#define _PAGE_NO_CACHE_BIT 24 /* (0x080) Uncached Page (U bit) */
#define _PAGE_ACCESSED_BIT 23 /* (0x100) Software: Page Accessed */
......@@ -135,6 +137,17 @@ extern void *vmalloc_start;
#define xlate_pabit(x) (31 - x)
/* this defines the shift to the usable bits in the PTE it is set so
* that the valid bits _PAGE_PRESENT_BIT and _PAGE_USER_BIT are set
* to zero */
#define PTE_SHIFT xlate_pabit(_PAGE_USER_BIT)
/* this is how many bits may be used by the file functions */
#define PTE_FILE_MAX_BITS (BITS_PER_LONG - PTE_SHIFT)
#define pte_to_pgoff(pte) (pte_val(pte) >> PTE_SHIFT)
#define pgoff_to_pte(off) ((pte_t) { ((off) << PTE_SHIFT) | _PAGE_FILE })
#define _PAGE_READ (1 << xlate_pabit(_PAGE_READ_BIT))
#define _PAGE_WRITE (1 << xlate_pabit(_PAGE_WRITE_BIT))
#define _PAGE_RW (_PAGE_READ | _PAGE_WRITE)
......@@ -148,6 +161,7 @@ extern void *vmalloc_start;
#define _PAGE_PRESENT (1 << xlate_pabit(_PAGE_PRESENT_BIT))
#define _PAGE_FLUSH (1 << xlate_pabit(_PAGE_FLUSH_BIT))
#define _PAGE_USER (1 << xlate_pabit(_PAGE_USER_BIT))
#define _PAGE_FILE (1 << xlate_pabit(_PAGE_FILE_BIT))
#define _PAGE_TABLE (_PAGE_PRESENT | _PAGE_READ | _PAGE_WRITE | _PAGE_DIRTY | _PAGE_ACCESSED)
#define _PAGE_CHG_MASK (PAGE_MASK | _PAGE_ACCESSED | _PAGE_DIRTY)
......@@ -256,6 +270,8 @@ extern inline int pte_read(pte_t pte) { return pte_val(pte) & _PAGE_READ; }
extern inline int pte_dirty(pte_t pte) { return pte_val(pte) & _PAGE_DIRTY; }
extern inline int pte_young(pte_t pte) { return pte_val(pte) & _PAGE_ACCESSED; }
extern inline int pte_write(pte_t pte) { return pte_val(pte) & _PAGE_WRITE; }
extern inline int pte_file(pte_t pte) { return pte_val(pte) & _PAGE_FILE; }
extern inline int pte_user(pte_t pte) { return pte_val(pte) & _PAGE_USER; }
extern inline pte_t pte_rdprotect(pte_t pte) { pte_val(pte) &= ~_PAGE_READ; return pte; }
extern inline pte_t pte_mkclean(pte_t pte) { pte_val(pte) &= ~_PAGE_DIRTY; return pte; }
......
......@@ -92,6 +92,7 @@ struct cpuinfo_parisc {
unsigned long fp_model;
unsigned int state;
struct parisc_device *dev;
unsigned long loops_per_jiffy;
};
extern struct system_cpuinfo_parisc boot_cpu_data;
......
......@@ -7,7 +7,6 @@
#define _ASMPARISC_TIMEX_H
#include <asm/system.h>
#include <linux/time.h>
#define CLOCK_TICK_RATE 1193180 /* Underlying HZ */
......
......@@ -720,6 +720,7 @@
#define __NR_epoll_ctl (__NR_Linux + 225)
#define __NR_epoll_wait (__NR_Linux + 226)
#define __NR_remap_file_pages (__NR_Linux + 227)
#define __NR_semtimedop (__NR_Linux + 228)
#define __NR_Linux_syscalls 228
......
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