]> err.no Git - linux-2.6/commitdiff
Merge master.kernel.org:/pub/scm/linux/kernel/git/willy/parisc-2.6
authorLinus Torvalds <torvalds@g5.osdl.org>
Wed, 4 Oct 2006 15:18:34 +0000 (08:18 -0700)
committerLinus Torvalds <torvalds@g5.osdl.org>
Wed, 4 Oct 2006 15:18:34 +0000 (08:18 -0700)
* master.kernel.org:/pub/scm/linux/kernel/git/willy/parisc-2.6: (41 commits)
  [PARISC] Kill wall_jiffies use
  [PARISC] Honour "panic_on_oops" sysctl
  [PARISC] Fix fs/binfmt_som.c
  [PARISC] Export clear_user_page to modules
  [PARISC] Make DMA routines more stubby
  [PARISC] Define pci_get_legacy_ide_irq
  [PARISC] Fix CONFIG_DEBUG_SPINLOCK
  [PARISC] Fix HPUX compat compile with current GCC
  [PARISC] Fix iounmap compile warning
  [PARISC] Add support for Quicksilver AGPGART
  [PARISC] Move LBA and SBA register defines to the common ropes.h
  [PARISC] Create shared <asm/ropes.h> header
  [PARISC] Stash the lba_device in its struct device drvdata
  [PARISC] Generalize IS_ASTRO et al to take a parisc_device like
  [PARISC] Pretty print the name of the lba type on kernel boot
  [PARISC] Remove some obsolete comments and I checked that Reo is similar to Ike
  [PARISC] Add hardware found in the rp8400
  [PARISC] Allow nested interrupts
  [PARISC] Further updates to timer_interrupt()
  [PARISC] remove halftick and copy clocktick to local var (gcc can optimize usage)
  ...

45 files changed:
arch/parisc/Kconfig
arch/parisc/hpux/fs.c
arch/parisc/kernel/binfmt_elf32.c
arch/parisc/kernel/cache.c
arch/parisc/kernel/entry.S
arch/parisc/kernel/hardware.c
arch/parisc/kernel/irq.c
arch/parisc/kernel/processor.c
arch/parisc/kernel/signal.c
arch/parisc/kernel/smp.c
arch/parisc/kernel/sys_parisc.c
arch/parisc/kernel/syscall_table.S
arch/parisc/kernel/time.c
arch/parisc/kernel/traps.c
arch/parisc/mm/init.c
arch/parisc/mm/ioremap.c
drivers/char/agp/Kconfig
drivers/char/agp/Makefile
drivers/char/agp/parisc-agp.c [new file with mode: 0644]
drivers/parisc/iosapic.c
drivers/parisc/lba_pci.c
drivers/parisc/sba_iommu.c
drivers/serial/8250_gsc.c
drivers/serial/Kconfig
fs/binfmt_som.c
include/asm-parisc/agp.h [new file with mode: 0644]
include/asm-parisc/assembly.h
include/asm-parisc/cacheflush.h
include/asm-parisc/compat.h
include/asm-parisc/dma.h
include/asm-parisc/futex.h
include/asm-parisc/io.h
include/asm-parisc/iosapic.h [deleted file]
include/asm-parisc/irq.h
include/asm-parisc/mckinley.h [new file with mode: 0644]
include/asm-parisc/page.h
include/asm-parisc/param.h
include/asm-parisc/parisc-device.h
include/asm-parisc/pci.h
include/asm-parisc/prefetch.h [new file with mode: 0644]
include/asm-parisc/processor.h
include/asm-parisc/ropes.h [new file with mode: 0644]
include/asm-parisc/serial.h
include/asm-parisc/spinlock.h
include/linux/debug_locks.h

index 6dd0ea8f88e0a49c273e3f04734efc3e42abb0d5..d2101237442e8bbfa345788f4b49c950d6848a17 100644 (file)
@@ -127,7 +127,7 @@ config PA11
 
 config PREFETCH
        def_bool y
-       depends on PA8X00
+       depends on PA8X00 || PA7200
 
 config 64BIT
        bool "64-bit kernel"
index 6e79dbf3f6bdf7e205ccccc5e6e2674c9e8c6b54..2d58b92b57e368094635d1d4431bdcb782ed6d40 100644 (file)
@@ -96,7 +96,7 @@ static int filldir(void * __buf, const char * name, int namlen, loff_t offset,
        put_user(namlen, &dirent->d_namlen);
        copy_to_user(dirent->d_name, name, namlen);
        put_user(0, dirent->d_name + namlen);
-       ((char *) dirent) += reclen;
+       dirent = (void __user *)dirent + reclen;
        buf->current_dir = dirent;
        buf->count -= reclen;
        return 0;
index d1833f164bbeaad34084dc92cfc82882e6759efb..1e64e7b88110157df77334416f7d8a703bea4449 100644 (file)
@@ -87,7 +87,7 @@ struct elf_prpsinfo32
  */
 
 #define SET_PERSONALITY(ex, ibcs2) \
-       current->personality = PER_LINUX32; \
+       set_thread_flag(TIF_32BIT); \
        current->thread.map_base = DEFAULT_MAP_BASE32; \
        current->thread.task_size = DEFAULT_TASK_SIZE32 \
 
@@ -102,25 +102,3 @@ cputime_to_compat_timeval(const cputime_t cputime, struct compat_timeval *value)
 }
 
 #include "../../../fs/binfmt_elf.c"
-
-/* Set up a separate execution domain for ELF32 binaries running
- * on an ELF64 kernel */
-
-static struct exec_domain parisc32_exec_domain = { 
-       .name = "Linux/ELF32",
-       .pers_low = PER_LINUX32,
-       .pers_high = PER_LINUX32,
-};      
-
-static int __init parisc32_exec_init(void)
-{
-       /* steal the identity signal mappings from the default domain */
-       parisc32_exec_domain.signal_map = default_exec_domain.signal_map;
-       parisc32_exec_domain.signal_invmap = default_exec_domain.signal_invmap;
-
-       register_exec_domain(&parisc32_exec_domain);
-
-       return 0;
-}
-
-__initcall(parisc32_exec_init);
index bc7c4a4e26a1e24f53b62b735bf820baac104635..0be51e92a2fc62f1e82387249d3dbead462606d7 100644 (file)
@@ -35,15 +35,12 @@ int icache_stride __read_mostly;
 EXPORT_SYMBOL(dcache_stride);
 
 
-#if defined(CONFIG_SMP)
 /* On some machines (e.g. ones with the Merced bus), there can be
  * only a single PxTLB broadcast at a time; this must be guaranteed
  * by software.  We put a spinlock around all TLB flushes  to
  * ensure this.
  */
 DEFINE_SPINLOCK(pa_tlb_lock);
-EXPORT_SYMBOL(pa_tlb_lock);
-#endif
 
 struct pdc_cache_info cache_info __read_mostly;
 #ifndef CONFIG_PA20
@@ -91,7 +88,8 @@ update_mmu_cache(struct vm_area_struct *vma, unsigned long address, pte_t pte)
 
                flush_kernel_dcache_page(page);
                clear_bit(PG_dcache_dirty, &page->flags);
-       }
+       } else if (parisc_requires_coherency())
+               flush_kernel_dcache_page(page);
 }
 
 void
@@ -370,3 +368,45 @@ void parisc_setup_cache_timing(void)
 
        printk(KERN_INFO "Setting cache flush threshold to %x (%d CPUs online)\n", parisc_cache_flush_threshold, num_online_cpus());
 }
+
+extern void purge_kernel_dcache_page(unsigned long);
+extern void clear_user_page_asm(void *page, unsigned long vaddr);
+
+void clear_user_page(void *page, unsigned long vaddr, struct page *pg)
+{
+       purge_kernel_dcache_page((unsigned long)page);
+       purge_tlb_start();
+       pdtlb_kernel(page);
+       purge_tlb_end();
+       clear_user_page_asm(page, vaddr);
+}
+EXPORT_SYMBOL(clear_user_page);
+
+void flush_kernel_dcache_page_addr(void *addr)
+{
+       flush_kernel_dcache_page_asm(addr);
+       purge_tlb_start();
+       pdtlb_kernel(addr);
+       purge_tlb_end();
+}
+EXPORT_SYMBOL(flush_kernel_dcache_page_addr);
+
+void copy_user_page(void *vto, void *vfrom, unsigned long vaddr,
+                   struct page *pg)
+{
+       /* no coherency needed (all in kmap/kunmap) */
+       copy_user_page_asm(vto, vfrom);
+       if (!parisc_requires_coherency())
+               flush_kernel_dcache_page_asm(vto);
+}
+EXPORT_SYMBOL(copy_user_page);
+
+#ifdef CONFIG_PA8X00
+
+void kunmap_parisc(void *addr)
+{
+       if (parisc_requires_coherency())
+               flush_kernel_dcache_page_addr(addr);
+}
+EXPORT_SYMBOL(kunmap_parisc);
+#endif
index 192357a3b9fe0e7c7502ebc64884b4f06a99b464..340b5e8d67bad1197b75b4ec5320a932575f21e4 100644 (file)
@@ -30,6 +30,7 @@
 
 
 #include <asm/psw.h>
+#include <asm/cache.h>         /* for L1_CACHE_SHIFT */
 #include <asm/assembly.h>      /* for LDREG/STREG defines */
 #include <asm/pgtable.h>
 #include <asm/signal.h>
        bb,>=,n         \pmd,_PxD_PRESENT_BIT,\fault
        DEP             %r0,31,PxD_FLAG_SHIFT,\pmd /* clear flags */
        copy            \pmd,%r9
-#ifdef CONFIG_64BIT
-       shld            %r9,PxD_VALUE_SHIFT,\pmd
-#else
-       shlw            %r9,PxD_VALUE_SHIFT,\pmd
-#endif
+       SHLREG          %r9,PxD_VALUE_SHIFT,\pmd
        EXTR            \va,31-PAGE_SHIFT,ASM_BITS_PER_PTE,\index
        DEP             %r0,31,PAGE_SHIFT,\pmd  /* clear offset */
        shladd          \index,BITS_PER_PTE_ENTRY,\pmd,\pmd
@@ -970,11 +967,7 @@ intr_return:
        /* shift left ____cacheline_aligned (aka L1_CACHE_BYTES) amount
        ** irq_stat[] is defined using ____cacheline_aligned.
        */
-#ifdef CONFIG_64BIT
-       shld    %r1, 6, %r20
-#else
-       shlw    %r1, 5, %r20
-#endif
+       SHLREG  %r1,L1_CACHE_SHIFT,%r20
        add     %r19,%r20,%r19  /* now have &irq_stat[smp_processor_id()] */
 #endif /* CONFIG_SMP */
 
@@ -1076,7 +1069,7 @@ intr_do_preempt:
        BL      preempt_schedule_irq, %r2
        nop
 
-       b       intr_restore            /* ssm PSW_SM_I done by intr_restore */
+       b,n     intr_restore            /* ssm PSW_SM_I done by intr_restore */
 #endif /* CONFIG_PREEMPT */
 
        .import do_signal,code
@@ -2115,11 +2108,7 @@ syscall_check_bh:
        ldw     TI_CPU-THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r26 /* cpu # */
 
        /* shift left ____cacheline_aligned (aka L1_CACHE_BYTES) bits */
-#ifdef CONFIG_64BIT
-       shld    %r26, 6, %r20
-#else
-       shlw    %r26, 5, %r20
-#endif
+       SHLREG  %r26,L1_CACHE_SHIFT,%r20
        add     %r19,%r20,%r19  /* now have &irq_stat[smp_processor_id()] */
 #endif /* CONFIG_SMP */
 
index 3058bffd8a2c80bfcb1a0f42ca0579a63d792071..18ba4cb9159b22a2d3ae1f3462e3761336a76a97 100644 (file)
@@ -231,6 +231,7 @@ static struct hp_hardware hp_hardware_list[] __initdata = {
        {HPHW_NPROC,0x5E6,0x4,0x91,"Keystone/Matterhorn W2 650"},
        {HPHW_NPROC,0x5E7,0x4,0x91,"Caribe W2 800"},
        {HPHW_NPROC,0x5E8,0x4,0x91,"Pikes Peak W2"},
+       {HPHW_NPROC,0x5EB,0x4,0x91,"Perf/Leone 875 W2+"},
        {HPHW_NPROC,0x5FF,0x4,0x91,"Hitachi W"},
        {HPHW_NPROC,0x600,0x4,0x81,"Gecko (712/60)"},
        {HPHW_NPROC,0x601,0x4,0x81,"Gecko 80 (712/80)"},
@@ -584,8 +585,10 @@ static struct hp_hardware hp_hardware_list[] __initdata = {
        {HPHW_CONSOLE, 0x01A, 0x0001F, 0x00, "Jason/Anole 64 Null Console"}, 
        {HPHW_CONSOLE, 0x01B, 0x0001F, 0x00, "Jason/Anole 100 Null Console"}, 
        {HPHW_FABRIC, 0x004, 0x000AA, 0x80, "Halfdome DNA Central Agent"}, 
+       {HPHW_FABRIC, 0x005, 0x000AA, 0x80, "Keystone DNA Central Agent"},
        {HPHW_FABRIC, 0x007, 0x000AA, 0x80, "Caribe DNA Central Agent"}, 
        {HPHW_FABRIC, 0x004, 0x000AB, 0x00, "Halfdome TOGO Fabric Crossbar"}, 
+       {HPHW_FABRIC, 0x005, 0x000AB, 0x00, "Keystone TOGO Fabric Crossbar"},
        {HPHW_FABRIC, 0x004, 0x000AC, 0x00, "Halfdome Sakura Fabric Router"}, 
        {HPHW_FIO, 0x025, 0x0002E, 0x80, "Armyknife Optional X.25"}, 
        {HPHW_FIO, 0x004, 0x0004F, 0x0, "8-Port X.25 EISA-ACC (AMSO)"}, 
index 5b8803cc3d69498c1bc916cee4bfd4467d14b61f..9bdd0197ceb777f555efc995e1581c17d2167938 100644 (file)
@@ -45,6 +45,17 @@ extern irqreturn_t ipi_interrupt(int, void *, struct pt_regs *);
 */
 static volatile unsigned long cpu_eiem = 0;
 
+/*
+** ack bitmap ... habitually set to 1, but reset to zero
+** between ->ack() and ->end() of the interrupt to prevent
+** re-interruption of a processing interrupt.
+*/
+static volatile unsigned long global_ack_eiem = ~0UL;
+/*
+** Local bitmap, same as above but for per-cpu interrupts
+*/
+static DEFINE_PER_CPU(unsigned long, local_ack_eiem) = ~0UL;
+
 static void cpu_disable_irq(unsigned int irq)
 {
        unsigned long eirr_bit = EIEM_MASK(irq);
@@ -62,13 +73,6 @@ static void cpu_enable_irq(unsigned int irq)
 
        cpu_eiem |= eirr_bit;
 
-       /* FIXME: while our interrupts aren't nested, we cannot reset
-        * the eiem mask if we're already in an interrupt.  Once we
-        * implement nested interrupts, this can go away
-        */
-       if (!in_interrupt())
-               set_eiem(cpu_eiem);
-
        /* This is just a simple NOP IPI.  But what it does is cause
         * all the other CPUs to do a set_eiem(cpu_eiem) at the end
         * of the interrupt handler */
@@ -84,13 +88,45 @@ static unsigned int cpu_startup_irq(unsigned int irq)
 void no_ack_irq(unsigned int irq) { }
 void no_end_irq(unsigned int irq) { }
 
+void cpu_ack_irq(unsigned int irq)
+{
+       unsigned long mask = EIEM_MASK(irq);
+       int cpu = smp_processor_id();
+
+       /* Clear in EIEM so we can no longer process */
+       if (CHECK_IRQ_PER_CPU(irq_desc[irq].status))
+               per_cpu(local_ack_eiem, cpu) &= ~mask;
+       else
+               global_ack_eiem &= ~mask;
+
+       /* disable the interrupt */
+       set_eiem(cpu_eiem & global_ack_eiem & per_cpu(local_ack_eiem, cpu));
+       /* and now ack it */
+       mtctl(mask, 23);
+}
+
+void cpu_end_irq(unsigned int irq)
+{
+       unsigned long mask = EIEM_MASK(irq);
+       int cpu = smp_processor_id();
+
+       /* set it in the eiems---it's no longer in process */
+       if (CHECK_IRQ_PER_CPU(irq_desc[irq].status))
+               per_cpu(local_ack_eiem, cpu) |= mask;
+       else
+               global_ack_eiem |= mask;
+
+       /* enable the interrupt */
+       set_eiem(cpu_eiem & global_ack_eiem & per_cpu(local_ack_eiem, cpu));
+}
+
 #ifdef CONFIG_SMP
 int cpu_check_affinity(unsigned int irq, cpumask_t *dest)
 {
        int cpu_dest;
 
        /* timer and ipi have to always be received on all CPUs */
-       if (irq == TIMER_IRQ || irq == IPI_IRQ) {
+       if (CHECK_IRQ_PER_CPU(irq)) {
                /* Bad linux design decision.  The mask has already
                 * been set; we must reset it */
                irq_desc[irq].affinity = CPU_MASK_ALL;
@@ -119,8 +155,8 @@ static struct hw_interrupt_type cpu_interrupt_type = {
        .shutdown       = cpu_disable_irq,
        .enable         = cpu_enable_irq,
        .disable        = cpu_disable_irq,
-       .ack            = no_ack_irq,
-       .end            = no_end_irq,
+       .ack            = cpu_ack_irq,
+       .end            = cpu_end_irq,
 #ifdef CONFIG_SMP
        .set_affinity   = cpu_set_affinity_irq,
 #endif
@@ -209,7 +245,7 @@ int show_interrupts(struct seq_file *p, void *v)
 ** Then use that to get the Transaction address and data.
 */
 
-int cpu_claim_irq(unsigned int irq, struct hw_interrupt_type *type, void *data)
+int cpu_claim_irq(unsigned int irq, struct irq_chip *type, void *data)
 {
        if (irq_desc[irq].action)
                return -EBUSY;
@@ -298,82 +334,69 @@ unsigned int txn_alloc_data(unsigned int virt_irq)
        return virt_irq - CPU_IRQ_BASE;
 }
 
+static inline int eirr_to_irq(unsigned long eirr)
+{
+#ifdef CONFIG_64BIT
+       int bit = fls64(eirr);
+#else
+       int bit = fls(eirr);
+#endif
+       return (BITS_PER_LONG - bit) + TIMER_IRQ;
+}
+
 /* ONLY called from entry.S:intr_extint() */
 void do_cpu_irq_mask(struct pt_regs *regs)
 {
        unsigned long eirr_val;
-
-       irq_enter();
-
-       /*
-        * Don't allow TIMER or IPI nested interrupts.
-        * Allowing any single interrupt to nest can lead to that CPU
-        * handling interrupts with all enabled interrupts unmasked.
-        */
-       set_eiem(0UL);
-
-       /* 1) only process IRQs that are enabled/unmasked (cpu_eiem)
-        * 2) We loop here on EIRR contents in order to avoid
-        *    nested interrupts or having to take another interrupt
-        *    when we could have just handled it right away.
-        */
-       for (;;) {
-               unsigned long bit = (1UL << (BITS_PER_LONG - 1));
-               unsigned int irq;
-               eirr_val = mfctl(23) & cpu_eiem;
-               if (!eirr_val)
-                       break;
-
-               mtctl(eirr_val, 23); /* reset bits we are going to process */
-
-               /* Work our way from MSb to LSb...same order we alloc EIRs */
-               for (irq = TIMER_IRQ; eirr_val && bit; bit>>=1, irq++) {
+       int irq, cpu = smp_processor_id();
 #ifdef CONFIG_SMP
-                       cpumask_t dest = irq_desc[irq].affinity;
+       cpumask_t dest;
 #endif
-                       if (!(bit & eirr_val))
-                               continue;
 
-                       /* clear bit in mask - can exit loop sooner */
-                       eirr_val &= ~bit;
+       local_irq_disable();
+       irq_enter();
 
-#ifdef CONFIG_SMP
-                       /* FIXME: because generic set affinity mucks
-                        * with the affinity before sending it to us
-                        * we can get the situation where the affinity is
-                        * wrong for our CPU type interrupts */
-                       if (irq != TIMER_IRQ && irq != IPI_IRQ &&
-                           !cpu_isset(smp_processor_id(), dest)) {
-                               int cpu = first_cpu(dest);
-
-                               printk(KERN_DEBUG "redirecting irq %d from CPU %d to %d\n",
-                                      irq, smp_processor_id(), cpu);
-                               gsc_writel(irq + CPU_IRQ_BASE,
-                                          cpu_data[cpu].hpa);
-                               continue;
-                       }
-#endif
+       eirr_val = mfctl(23) & cpu_eiem & global_ack_eiem &
+               per_cpu(local_ack_eiem, cpu);
+       if (!eirr_val)
+               goto set_out;
+       irq = eirr_to_irq(eirr_val);
 
-                       __do_IRQ(irq, regs);
-               }
+#ifdef CONFIG_SMP
+       dest = irq_desc[irq].affinity;
+       if (CHECK_IRQ_PER_CPU(irq_desc[irq].status) &&
+           !cpu_isset(smp_processor_id(), dest)) {
+               int cpu = first_cpu(dest);
+
+               printk(KERN_DEBUG "redirecting irq %d from CPU %d to %d\n",
+                      irq, smp_processor_id(), cpu);
+               gsc_writel(irq + CPU_IRQ_BASE,
+                          cpu_data[cpu].hpa);
+               goto set_out;
        }
+#endif
+       __do_IRQ(irq, regs);
 
-       set_eiem(cpu_eiem);     /* restore original mask */
+ out:
        irq_exit();
-}
+       return;
 
+ set_out:
+       set_eiem(cpu_eiem & global_ack_eiem & per_cpu(local_ack_eiem, cpu));
+       goto out;
+}
 
 static struct irqaction timer_action = {
        .handler = timer_interrupt,
        .name = "timer",
-       .flags = IRQF_DISABLED,
+       .flags = IRQF_DISABLED | IRQF_TIMER | IRQF_PERCPU,
 };
 
 #ifdef CONFIG_SMP
 static struct irqaction ipi_action = {
        .handler = ipi_interrupt,
        .name = "IPI",
-       .flags = IRQF_DISABLED,
+       .flags = IRQF_DISABLED | IRQF_PERCPU,
 };
 #endif
 
index 99d7fca9310475c51e89520b64cffa1e63fecf58..fb81e5687e7c8a69c456a816c179cc26840d3239 100644 (file)
@@ -143,8 +143,9 @@ static int __init processor_probe(struct parisc_device *dev)
        p = &cpu_data[cpuid];
        boot_cpu_data.cpu_count++;
 
-       /* initialize counters */
-       memset(p, 0, sizeof(struct cpuinfo_parisc));
+       /* initialize counters - CPU 0 gets it_value set in time_init() */
+       if (cpuid)
+               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 */
index bb83880c5ee3458bd9940b96e527bf9146cb96e9..ee6653edeb7a1b83da64572c03d9d0620319558f 100644 (file)
@@ -26,7 +26,6 @@
 #include <linux/stddef.h>
 #include <linux/compat.h>
 #include <linux/elf.h>
-#include <linux/personality.h>
 #include <asm/ucontext.h>
 #include <asm/rt_sigframe.h>
 #include <asm/uaccess.h>
@@ -433,13 +432,13 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
        if (in_syscall) {
                regs->gr[31] = haddr;
 #ifdef __LP64__
-               if (personality(current->personality) == PER_LINUX)
+               if (!test_thread_flag(TIF_32BIT))
                        sigframe_size |= 1;
 #endif
        } else {
                unsigned long psw = USER_PSW;
 #ifdef __LP64__
-               if (personality(current->personality) == PER_LINUX)
+               if (!test_thread_flag(TIF_32BIT))
                        psw |= PSW_W;
 #endif
 
index 98e40959a564815df35e2d57272c3deb0e2d2d8c..faad338f310ed12f8dddc4f4824b40c61edde298 100644 (file)
@@ -262,6 +262,9 @@ ipi_interrupt(int irq, void *dev_id, struct pt_regs *regs)
                                        this_cpu, which);
                                return IRQ_NONE;
                        } /* Switch */
+               /* let in any pending interrupts */
+               local_irq_enable();
+               local_irq_disable();
                } /* while (ops) */
        }
        return IRQ_HANDLED;
@@ -430,8 +433,9 @@ smp_do_timer(struct pt_regs *regs)
 static void __init
 smp_cpu_init(int cpunum)
 {
-       extern int init_per_cpu(int);  /* arch/parisc/kernel/setup.c */
+       extern int init_per_cpu(int);  /* arch/parisc/kernel/processor.c */
        extern void init_IRQ(void);    /* arch/parisc/kernel/irq.c */
+       extern void start_cpu_itimer(void); /* arch/parisc/kernel/time.c */
 
        /* Set modes and Enable floating point coprocessor */
        (void) init_per_cpu(cpunum);
@@ -457,6 +461,7 @@ smp_cpu_init(int cpunum)
        enter_lazy_tlb(&init_mm, current);
 
        init_IRQ();   /* make sure no IRQ's are enabled or pending */
+       start_cpu_itimer();
 }
 
 
index 8b5df98e2b3158a229226cdb233e43349c950e4c..1db5588ceacf7474ebba8d947b6b7c31da09a906 100644 (file)
@@ -31,6 +31,8 @@
 #include <linux/shm.h>
 #include <linux/smp_lock.h>
 #include <linux/syscalls.h>
+#include <linux/utsname.h>
+#include <linux/personality.h>
 
 int sys_pipe(int __user *fildes)
 {
@@ -248,3 +250,46 @@ asmlinkage int sys_free_hugepages(unsigned long addr)
 {
        return -EINVAL;
 }
+
+long parisc_personality(unsigned long personality)
+{
+       long err;
+
+       if (personality(current->personality) == PER_LINUX32
+           && personality == PER_LINUX)
+               personality = PER_LINUX32;
+
+       err = sys_personality(personality);
+       if (err == PER_LINUX32)
+               err = PER_LINUX;
+
+       return err;
+}
+
+static inline int override_machine(char __user *mach) {
+#ifdef CONFIG_COMPAT
+       if (personality(current->personality) == PER_LINUX32) {
+               if (__put_user(0, mach + 6) ||
+                   __put_user(0, mach + 7))
+                       return -EFAULT;
+       }
+
+       return 0;
+#else /*!CONFIG_COMPAT*/
+       return 0;
+#endif /*CONFIG_COMPAT*/
+}
+
+long parisc_newuname(struct new_utsname __user *utsname)
+{
+       int err = 0;
+
+       down_read(&uts_sem);
+       if (copy_to_user(utsname, &system_utsname, sizeof(*utsname)))
+               err = -EFAULT;
+       up_read(&uts_sem);
+
+       err = override_machine(utsname->machine);
+
+       return (long)err;
+}
index e27b432f90a8628a5eb2c397d7b1e2ff7f4be8cf..701d66a596e8855d22ab3ddaa4a889b68b4500ce 100644 (file)
        ENTRY_SAME(socketpair)
        ENTRY_SAME(setpgid)
        ENTRY_SAME(send)
-       ENTRY_SAME(newuname)
+       ENTRY_OURS(newuname)
        ENTRY_SAME(umask)               /* 60 */
        ENTRY_SAME(chroot)
        ENTRY_SAME(ustat)
        ENTRY_SAME(fchdir)
        ENTRY_SAME(bdflush)
        ENTRY_SAME(sysfs)               /* 135 */
-       ENTRY_SAME(personality)
+       ENTRY_OURS(personality)
        ENTRY_SAME(ni_syscall)  /* for afs_syscall */
        ENTRY_SAME(setfsuid)
        ENTRY_SAME(setfsgid)
index ab641d67f5516fc6fb494799edce9db1f13f08d0..b3496b592a2d7db687793899388a4db9ce73f064 100644 (file)
@@ -32,8 +32,7 @@
 
 #include <linux/timex.h>
 
-static long clocktick __read_mostly;   /* timer cycles per tick */
-static long halftick __read_mostly;
+static unsigned long clocktick __read_mostly;  /* timer cycles per tick */
 
 #ifdef CONFIG_SMP
 extern void smp_do_timer(struct pt_regs *regs);
@@ -41,46 +40,106 @@ extern void smp_do_timer(struct pt_regs *regs);
 
 irqreturn_t timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
-       long now;
-       long next_tick;
-       int nticks;
-       int cpu = smp_processor_id();
+       unsigned long now;
+       unsigned long next_tick;
+       unsigned long cycles_elapsed;
+       unsigned long cycles_remainder;
+       unsigned int cpu = smp_processor_id();
+
+       /* gcc can optimize for "read-only" case with a local clocktick */
+       unsigned long cpt = clocktick;
 
        profile_tick(CPU_PROFILING, regs);
 
-       now = mfctl(16);
-       /* initialize next_tick to time at last clocktick */
+       /* Initialize next_tick to the expected tick time. */
        next_tick = cpu_data[cpu].it_value;
 
-       /* since time passes between the interrupt and the mfctl()
-        * above, it is never true that last_tick + clocktick == now.  If we
-        * never miss a clocktick, we could set next_tick = last_tick + clocktick
-        * but maybe we'll miss ticks, hence the loop.
-        *
-        * Variables are *signed*.
+       /* Get current interval timer.
+        * CR16 reads as 64 bits in CPU wide mode.
+        * CR16 reads as 32 bits in CPU narrow mode.
         */
+       now = mfctl(16);
+
+       cycles_elapsed = now - next_tick;
 
-       nticks = 0;
-       while((next_tick - now) < halftick) {
-               next_tick += clocktick;
-               nticks++;
+       if ((cycles_elapsed >> 5) < cpt) {
+               /* use "cheap" math (add/subtract) instead
+                * of the more expensive div/mul method
+                */
+               cycles_remainder = cycles_elapsed;
+               while (cycles_remainder > cpt) {
+                       cycles_remainder -= cpt;
+               }
+       } else {
+               cycles_remainder = cycles_elapsed % cpt;
        }
-       mtctl(next_tick, 16);
+
+       /* Can we differentiate between "early CR16" (aka Scenario 1) and
+        * "long delay" (aka Scenario 3)? I don't think so.
+        *
+        * We expected timer_interrupt to be delivered at least a few hundred
+        * cycles after the IT fires. But it's arbitrary how much time passes
+        * before we call it "late". I've picked one second.
+        */
+/* aproximate HZ with shifts. Intended math is "(elapsed/clocktick) > HZ" */
+#if HZ == 1000
+       if (cycles_elapsed > (cpt << 10) )
+#elif HZ == 250
+       if (cycles_elapsed > (cpt << 8) )
+#elif HZ == 100
+       if (cycles_elapsed > (cpt << 7) )
+#else
+#warn WTF is HZ set to anyway?
+       if (cycles_elapsed > (HZ * cpt) )
+#endif
+       {
+               /* Scenario 3: very long delay?  bad in any case */
+               printk (KERN_CRIT "timer_interrupt(CPU %d): delayed!"
+                       " cycles %lX rem %lX "
+                       " next/now %lX/%lX\n",
+                       cpu,
+                       cycles_elapsed, cycles_remainder,
+                       next_tick, now );
+       }
+
+       /* convert from "division remainder" to "remainder of clock tick" */
+       cycles_remainder = cpt - cycles_remainder;
+
+       /* Determine when (in CR16 cycles) next IT interrupt will fire.
+        * We want IT to fire modulo clocktick even if we miss/skip some.
+        * But those interrupts don't in fact get delivered that regularly.
+        */
+       next_tick = now + cycles_remainder;
+
        cpu_data[cpu].it_value = next_tick;
 
-       while (nticks--) {
+       /* Skip one clocktick on purpose if we are likely to miss next_tick.
+        * We want to avoid the new next_tick being less than CR16.
+        * If that happened, itimer wouldn't fire until CR16 wrapped.
+        * We'll catch the tick we missed on the tick after that.
+        */
+       if (!(cycles_remainder >> 13))
+               next_tick += cpt;
+
+       /* Program the IT when to deliver the next interrupt. */
+        /* Only bottom 32-bits of next_tick are written to cr16.  */
+       mtctl(next_tick, 16);
+
+
+       /* Done mucking with unreliable delivery of interrupts.
+        * Go do system house keeping.
+        */
 #ifdef CONFIG_SMP
-               smp_do_timer(regs);
+       smp_do_timer(regs);
 #else
-               update_process_times(user_mode(regs));
+       update_process_times(user_mode(regs));
 #endif
-               if (cpu == 0) {
-                       write_seqlock(&xtime_lock);
-                       do_timer(1);
-                       write_sequnlock(&xtime_lock);
-               }
+       if (cpu == 0) {
+               write_seqlock(&xtime_lock);
+               do_timer(regs);
+               write_sequnlock(&xtime_lock);
        }
-    
+
        /* check soft power switch status */
        if (cpu == 0 && !atomic_read(&power_tasklet.count))
                tasklet_schedule(&power_tasklet);
@@ -106,14 +165,12 @@ unsigned long profile_pc(struct pt_regs *regs)
 EXPORT_SYMBOL(profile_pc);
 
 
-/*** converted from ia64 ***/
 /*
  * Return the number of micro-seconds that elapsed since the last
  * update to wall time (aka xtime).  The xtime_lock
  * must be at least read-locked when calling this routine.
  */
-static inline unsigned long
-gettimeoffset (void)
+static inline unsigned long gettimeoffset (void)
 {
 #ifndef CONFIG_SMP
        /*
@@ -121,21 +178,44 @@ gettimeoffset (void)
         *    Once parisc-linux learns the cr16 difference between processors,
         *    this could be made to work.
         */
-       long last_tick;
-       long elapsed_cycles;
-
-       /* it_value is the intended time of the next tick */
-       last_tick = cpu_data[smp_processor_id()].it_value;
-
-       /* Subtract one tick and account for possible difference between
-        * when we expected the tick and when it actually arrived.
-        * (aka wall vs real)
-        */
-       last_tick -= clocktick * (jiffies - wall_jiffies + 1);
-       elapsed_cycles = mfctl(16) - last_tick;
+       unsigned long now;
+       unsigned long prev_tick;
+       unsigned long next_tick;
+       unsigned long elapsed_cycles;
+       unsigned long usec;
+       unsigned long cpuid = smp_processor_id();
+       unsigned long cpt = clocktick;
+
+       next_tick = cpu_data[cpuid].it_value;
+       now = mfctl(16);        /* Read the hardware interval timer.  */
+
+       prev_tick = next_tick - cpt;
+
+       /* Assume Scenario 1: "now" is later than prev_tick.  */
+       elapsed_cycles = now - prev_tick;
+
+/* aproximate HZ with shifts. Intended math is "(elapsed/clocktick) > HZ" */
+#if HZ == 1000
+       if (elapsed_cycles > (cpt << 10) )
+#elif HZ == 250
+       if (elapsed_cycles > (cpt << 8) )
+#elif HZ == 100
+       if (elapsed_cycles > (cpt << 7) )
+#else
+#warn WTF is HZ set to anyway?
+       if (elapsed_cycles > (HZ * cpt) )
+#endif
+       {
+               /* Scenario 3: clock ticks are missing. */
+               printk (KERN_CRIT "gettimeoffset(CPU %ld): missing %ld ticks!"
+                       " cycles %lX prev/now/next %lX/%lX/%lX  clock %lX\n",
+                       cpuid, elapsed_cycles / cpt,
+                       elapsed_cycles, prev_tick, now, next_tick, cpt);
+       }
 
-       /* the precision of this math could be improved */
-       return elapsed_cycles / (PAGE0->mem_10msec / 10000);
+       /* FIXME: Can we improve the precision? Not with PAGE0. */
+       usec = (elapsed_cycles * 10000) / PAGE0->mem_10msec;
+       return usec;
 #else
        return 0;
 #endif
@@ -146,6 +226,7 @@ do_gettimeofday (struct timeval *tv)
 {
        unsigned long flags, seq, usec, sec;
 
+       /* Hold xtime_lock and adjust timeval.  */
        do {
                seq = read_seqbegin_irqsave(&xtime_lock, flags);
                usec = gettimeoffset();
@@ -153,25 +234,13 @@ do_gettimeofday (struct timeval *tv)
                usec += (xtime.tv_nsec / 1000);
        } while (read_seqretry_irqrestore(&xtime_lock, seq, flags));
 
-       if (unlikely(usec > LONG_MAX)) {
-               /* This can happen if the gettimeoffset adjustment is
-                * negative and xtime.tv_nsec is smaller than the
-                * adjustment */
-               printk(KERN_ERR "do_gettimeofday() spurious xtime.tv_nsec of %ld\n", usec);
-               usec += USEC_PER_SEC;
-               --sec;
-               /* This should never happen, it means the negative
-                * time adjustment was more than a second, so there's
-                * something seriously wrong */
-               BUG_ON(usec > LONG_MAX);
-       }
-
-
+       /* Move adjusted usec's into sec's.  */
        while (usec >= USEC_PER_SEC) {
                usec -= USEC_PER_SEC;
                ++sec;
        }
 
+       /* Return adjusted result.  */
        tv->tv_sec = sec;
        tv->tv_usec = usec;
 }
@@ -223,22 +292,23 @@ unsigned long long sched_clock(void)
 }
 
 
+void __init start_cpu_itimer(void)
+{
+       unsigned int cpu = smp_processor_id();
+       unsigned long next_tick = mfctl(16) + clocktick;
+
+       mtctl(next_tick, 16);           /* kick off Interval Timer (CR16) */
+
+       cpu_data[cpu].it_value = next_tick;
+}
+
 void __init time_init(void)
 {
-       unsigned long next_tick;
        static struct pdc_tod tod_data;
 
        clocktick = (100 * PAGE0->mem_10msec) / HZ;
-       halftick = clocktick / 2;
 
-       /* Setup clock interrupt timing */
-
-       next_tick = mfctl(16);
-       next_tick += clocktick;
-       cpu_data[smp_processor_id()].it_value = next_tick;
-
-       /* kick off Itimer (CR16) */
-       mtctl(next_tick, 16);
+       start_cpu_itimer();     /* get CPU 0 started */
 
        if(pdc_tod_read(&tod_data) == 0) {
                write_seqlock_irq(&xtime_lock);
index 77b28cb8aca6f1cecab831f219308c787869e729..65cd6ca32fed57b689f8a2dec3449dd620e3f098 100644 (file)
@@ -16,6 +16,7 @@
 #include <linux/errno.h>
 #include <linux/ptrace.h>
 #include <linux/timer.h>
+#include <linux/delay.h>
 #include <linux/mm.h>
 #include <linux/module.h>
 #include <linux/smp.h>
@@ -245,6 +246,15 @@ void die_if_kernel(char *str, struct pt_regs *regs, long err)
                current->comm, current->pid, str, err);
        show_regs(regs);
 
+       if (in_interrupt())
+               panic("Fatal exception in interrupt");
+
+       if (panic_on_oops) {
+               printk(KERN_EMERG "Fatal exception: panic in 5 seconds\n");
+               ssleep(5);
+               panic("Fatal exception");
+       }
+
        /* Wot's wrong wif bein' racy? */
        if (current->thread.flags & PARISC_KERNEL_DEATH) {
                printk(KERN_CRIT "%s() recursion detected.\n", __FUNCTION__);
index 25ad28d63e88398c057ddf259f262f49ea09a01f..0667f2b4f9775b13ab6fbc527884de52022bfa34 100644 (file)
 
 DEFINE_PER_CPU(struct mmu_gather, mmu_gathers);
 
-extern char _text;     /* start of kernel code, defined by linker */
 extern int  data_start;
-extern char _end;      /* end of BSS, defined by linker */
-extern char __init_begin, __init_end;
 
 #ifdef CONFIG_DISCONTIGMEM
 struct node_map_data node_data[MAX_NUMNODES] __read_mostly;
@@ -319,8 +316,8 @@ static void __init setup_bootmem(void)
 
        reserve_bootmem_node(NODE_DATA(0), 0UL,
                        (unsigned long)(PAGE0->mem_free + PDC_CONSOLE_IO_IODC_SIZE));
-       reserve_bootmem_node(NODE_DATA(0),__pa((unsigned long)&_text),
-                       (unsigned long)(&_end - &_text));
+       reserve_bootmem_node(NODE_DATA(0), __pa((unsigned long)_text),
+                       (unsigned long)(_end - _text));
        reserve_bootmem_node(NODE_DATA(0), (bootmap_start_pfn << PAGE_SHIFT),
                        ((bootmap_pfn - bootmap_start_pfn) << PAGE_SHIFT));
 
@@ -355,8 +352,8 @@ static void __init setup_bootmem(void)
 #endif
 
        data_resource.start =  virt_to_phys(&data_start);
-       data_resource.end = virt_to_phys(&_end)-1;
-       code_resource.start = virt_to_phys(&_text);
+       data_resource.end = virt_to_phys(_end) - 1;
+       code_resource.start = virt_to_phys(_text);
        code_resource.end = virt_to_phys(&data_start)-1;
 
        /* We don't know which region the kernel will be in, so try
@@ -385,12 +382,12 @@ void free_initmem(void)
         */
        local_irq_disable();
 
-       memset(&__init_begin, 0x00, 
-               (unsigned long)&__init_end - (unsigned long)&__init_begin);
+       memset(__init_begin, 0x00,
+               (unsigned long)__init_end - (unsigned long)__init_begin);
 
        flush_data_cache();
        asm volatile("sync" : : );
-       flush_icache_range((unsigned long)&__init_begin, (unsigned long)&__init_end);
+       flush_icache_range((unsigned long)__init_begin, (unsigned long)__init_end);
        asm volatile("sync" : : );
 
        local_irq_enable();
@@ -398,8 +395,8 @@ void free_initmem(void)
        
        /* align __init_begin and __init_end to page size,
           ignoring linker script where we might have tried to save RAM */
-       init_begin = PAGE_ALIGN((unsigned long)(&__init_begin));
-       init_end   = PAGE_ALIGN((unsigned long)(&__init_end));
+       init_begin = PAGE_ALIGN((unsigned long)(__init_begin));
+       init_end   = PAGE_ALIGN((unsigned long)(__init_end));
        for (addr = init_begin; addr < init_end; addr += PAGE_SIZE) {
                ClearPageReserved(virt_to_page(addr));
                init_page_count(virt_to_page(addr));
@@ -578,7 +575,7 @@ static void __init map_pages(unsigned long start_vaddr, unsigned long start_padd
        extern const unsigned long fault_vector_20;
        extern void * const linux_gateway_page;
 
-       ro_start = __pa((unsigned long)&_text);
+       ro_start = __pa((unsigned long)_text);
        ro_end   = __pa((unsigned long)&data_start);
        fv_addr  = __pa((unsigned long)&fault_vector_20) & PAGE_MASK;
        gw_addr  = __pa((unsigned long)&linux_gateway_page) & PAGE_MASK;
index 27384567a1d0a12e3719c7c9631c362e75e6636a..47a1d2ac941968086d089320ab86aaedb4f3c68f 100644 (file)
@@ -188,7 +188,7 @@ void __iomem * __ioremap(unsigned long phys_addr, unsigned long size, unsigned l
 }
 EXPORT_SYMBOL(__ioremap);
 
-void iounmap(void __iomem *addr)
+void iounmap(const volatile void __iomem *addr)
 {
        if (addr > high_memory)
                return vfree((void *) (PAGE_MASK & (unsigned long __force) addr));
index 22f8cf218cc6443a1af9f523ae49dfc47fe56340..c603bf2915803e0e9d243b6d82d5db317780b473 100644 (file)
@@ -1,6 +1,6 @@
 config AGP
        tristate "/dev/agpgart (AGP Support)"
-       depends on ALPHA || IA64 || PPC || X86
+       depends on ALPHA || IA64 || PARISC || PPC || X86
        depends on PCI
        ---help---
          AGP (Accelerated Graphics Port) is a bus system mainly used to
@@ -122,6 +122,14 @@ config AGP_HP_ZX1
          This option gives you AGP GART support for the HP ZX1 chipset
          for IA64 processors.
 
+config AGP_PARISC
+       tristate "HP Quicksilver AGP support"
+       depends on AGP && PARISC && 64BIT
+       help
+         This option gives you AGP GART support for the HP Quicksilver
+         AGP bus adapter on HP PA-RISC machines (Ok, just on the C8000
+         workstation...)
+
 config AGP_ALPHA_CORE
        tristate "Alpha AGP support"
        depends on AGP && (ALPHA_GENERIC || ALPHA_TITAN || ALPHA_MARVEL)
index d33a22f2fa0b9b2fa509517789884e119294851f..3e581603d0a822b9bab9a95b2f55ae056ffb3b05 100644 (file)
@@ -8,6 +8,7 @@ obj-$(CONFIG_AGP_AMD64)         += amd64-agp.o
 obj-$(CONFIG_AGP_ALPHA_CORE)   += alpha-agp.o
 obj-$(CONFIG_AGP_EFFICEON)     += efficeon-agp.o
 obj-$(CONFIG_AGP_HP_ZX1)       += hp-agp.o
+obj-$(CONFIG_AGP_PARISC)       += parisc-agp.o
 obj-$(CONFIG_AGP_I460)         += i460-agp.o
 obj-$(CONFIG_AGP_INTEL)                += intel-agp.o
 obj-$(CONFIG_AGP_NVIDIA)       += nvidia-agp.o
diff --git a/drivers/char/agp/parisc-agp.c b/drivers/char/agp/parisc-agp.c
new file mode 100644 (file)
index 0000000..17c50b0
--- /dev/null
@@ -0,0 +1,416 @@
+/*
+ * HP Quicksilver AGP GART routines
+ *
+ * Copyright (c) 2006, Kyle McMartin <kyle@parisc-linux.org>
+ *
+ * Based on drivers/char/agpgart/hp-agp.c which is
+ * (c) Copyright 2002, 2003 Hewlett-Packard Development Company, L.P.
+ *     Bjorn Helgaas <bjorn.helgaas@hp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+#include <linux/klist.h>
+#include <linux/agp_backend.h>
+
+#include <asm-parisc/parisc-device.h>
+#include <asm-parisc/ropes.h>
+
+#include "agp.h"
+
+#define DRVNAME        "quicksilver"
+#define DRVPFX DRVNAME ": "
+
+#ifndef log2
+#define log2(x)                ffz(~(x))
+#endif
+
+#define AGP8X_MODE_BIT         3
+#define AGP8X_MODE             (1 << AGP8X_MODE_BIT)
+
+static struct _parisc_agp_info {
+       void __iomem *ioc_regs;
+       void __iomem *lba_regs;
+
+       int lba_cap_offset;
+
+       u64 *gatt;
+       u64 gatt_entries;
+
+       u64 gart_base;
+       u64 gart_size;
+
+       int io_page_size;
+       int io_pages_per_kpage;
+} parisc_agp_info;
+
+static struct gatt_mask parisc_agp_masks[] =
+{
+        {
+               .mask = SBA_PDIR_VALID_BIT,
+               .type = 0
+       }
+};
+
+static struct aper_size_info_fixed parisc_agp_sizes[] =
+{
+        {0, 0, 0},              /* filled in by parisc_agp_fetch_size() */
+};
+
+static int
+parisc_agp_fetch_size(void)
+{
+       int size;
+
+       size = parisc_agp_info.gart_size / MB(1);
+       parisc_agp_sizes[0].size = size;
+       agp_bridge->current_size = (void *) &parisc_agp_sizes[0];
+
+       return size;
+}
+
+static int
+parisc_agp_configure(void)
+{
+       struct _parisc_agp_info *info = &parisc_agp_info;
+
+       agp_bridge->gart_bus_addr = info->gart_base;
+       agp_bridge->capndx = info->lba_cap_offset;
+       agp_bridge->mode = readl(info->lba_regs+info->lba_cap_offset+PCI_AGP_STATUS);
+
+       return 0;
+}
+
+static void
+parisc_agp_tlbflush(struct agp_memory *mem)
+{
+       struct _parisc_agp_info *info = &parisc_agp_info;
+
+       writeq(info->gart_base | log2(info->gart_size), info->ioc_regs+IOC_PCOM);
+       readq(info->ioc_regs+IOC_PCOM); /* flush */
+}
+
+static int
+parisc_agp_create_gatt_table(struct agp_bridge_data *bridge)
+{
+       struct _parisc_agp_info *info = &parisc_agp_info;
+       int i;
+
+       for (i = 0; i < info->gatt_entries; i++) {
+               info->gatt[i] = (unsigned long)agp_bridge->scratch_page;
+       }
+
+       return 0;
+}
+
+static int
+parisc_agp_free_gatt_table(struct agp_bridge_data *bridge)
+{
+       struct _parisc_agp_info *info = &parisc_agp_info;
+
+       info->gatt[0] = SBA_AGPGART_COOKIE;
+
+       return 0;
+}
+
+static int
+parisc_agp_insert_memory(struct agp_memory *mem, off_t pg_start, int type)
+{
+       struct _parisc_agp_info *info = &parisc_agp_info;
+       int i, k;
+       off_t j, io_pg_start;
+       int io_pg_count;
+
+       if (type != 0 || mem->type != 0) {
+               return -EINVAL;
+       }
+
+       io_pg_start = info->io_pages_per_kpage * pg_start;
+       io_pg_count = info->io_pages_per_kpage * mem->page_count;
+       if ((io_pg_start + io_pg_count) > info->gatt_entries) {
+               return -EINVAL;
+       }
+
+       j = io_pg_start;
+       while (j < (io_pg_start + io_pg_count)) {
+               if (info->gatt[j])
+                       return -EBUSY;
+               j++;
+       }
+
+       if (mem->is_flushed == FALSE) {
+               global_cache_flush();
+               mem->is_flushed = TRUE;
+       }
+
+       for (i = 0, j = io_pg_start; i < mem->page_count; i++) {
+               unsigned long paddr;
+
+               paddr = mem->memory[i];
+               for (k = 0;
+                    k < info->io_pages_per_kpage;
+                    k++, j++, paddr += info->io_page_size) {
+                       info->gatt[j] =
+                               agp_bridge->driver->mask_memory(agp_bridge,
+                                       paddr, type);
+               }
+       }
+
+       agp_bridge->driver->tlb_flush(mem);
+
+       return 0;
+}
+
+static int
+parisc_agp_remove_memory(struct agp_memory *mem, off_t pg_start, int type)
+{
+       struct _parisc_agp_info *info = &parisc_agp_info;
+       int i, io_pg_start, io_pg_count;
+
+       if (type != 0 || mem->type != 0) {
+               return -EINVAL;
+       }
+
+       io_pg_start = info->io_pages_per_kpage * pg_start;
+       io_pg_count = info->io_pages_per_kpage * mem->page_count;
+       for (i = io_pg_start; i < io_pg_count + io_pg_start; i++) {
+               info->gatt[i] = agp_bridge->scratch_page;
+       }
+
+       agp_bridge->driver->tlb_flush(mem);
+       return 0;
+}
+
+static unsigned long
+parisc_agp_mask_memory(struct agp_bridge_data *bridge,
+                   unsigned long addr, int type)
+{
+       return SBA_PDIR_VALID_BIT | addr;
+}
+
+static void
+parisc_agp_enable(struct agp_bridge_data *bridge, u32 mode)
+{
+       struct _parisc_agp_info *info = &parisc_agp_info;
+       u32 command;
+
+       command = readl(info->lba_regs + info->lba_cap_offset + PCI_AGP_STATUS);
+
+       command = agp_collect_device_status(bridge, mode, command);
+       command |= 0x00000100;
+
+       writel(command, info->lba_regs + info->lba_cap_offset + PCI_AGP_COMMAND);
+
+       agp_device_command(command, (mode & AGP8X_MODE) != 0);
+}
+
+struct agp_bridge_driver parisc_agp_driver = {
+       .owner                  = THIS_MODULE,
+       .size_type              = FIXED_APER_SIZE,
+       .configure              = parisc_agp_configure,
+       .fetch_size             = parisc_agp_fetch_size,
+       .tlb_flush              = parisc_agp_tlbflush,
+       .mask_memory            = parisc_agp_mask_memory,
+       .masks                  = parisc_agp_masks,
+       .agp_enable             = parisc_agp_enable,
+       .cache_flush            = global_cache_flush,
+       .create_gatt_table      = parisc_agp_create_gatt_table,
+       .free_gatt_table        = parisc_agp_free_gatt_table,
+       .insert_memory          = parisc_agp_insert_memory,
+       .remove_memory          = parisc_agp_remove_memory,
+       .alloc_by_type          = agp_generic_alloc_by_type,
+       .free_by_type           = agp_generic_free_by_type,
+       .agp_alloc_page         = agp_generic_alloc_page,
+       .agp_destroy_page       = agp_generic_destroy_page,
+       .cant_use_aperture      = 1,
+};
+
+static int __init
+agp_ioc_init(void __iomem *ioc_regs)
+{
+       struct _parisc_agp_info *info = &parisc_agp_info;
+        u64 *iova_base, *io_pdir, io_tlb_ps;
+        int io_tlb_shift;
+
+        printk(KERN_INFO DRVPFX "IO PDIR shared with sba_iommu\n");
+
+        info->ioc_regs = ioc_regs;
+
+        io_tlb_ps = readq(info->ioc_regs+IOC_TCNFG);
+        switch (io_tlb_ps) {
+        case 0: io_tlb_shift = 12; break;
+        case 1: io_tlb_shift = 13; break;
+        case 2: io_tlb_shift = 14; break;
+        case 3: io_tlb_shift = 16; break;
+        default:
+                printk(KERN_ERR DRVPFX "Invalid IOTLB page size "
+                       "configuration 0x%llx\n", io_tlb_ps);
+                info->gatt = NULL;
+                info->gatt_entries = 0;
+                return -ENODEV;
+        }
+        info->io_page_size = 1 << io_tlb_shift;
+        info->io_pages_per_kpage = PAGE_SIZE / info->io_page_size;
+
+        iova_base = readq(info->ioc_regs+IOC_IBASE) & ~0x1;
+        info->gart_base = iova_base + PLUTO_IOVA_SIZE - PLUTO_GART_SIZE;
+
+        info->gart_size = PLUTO_GART_SIZE;
+        info->gatt_entries = info->gart_size / info->io_page_size;
+
+        io_pdir = phys_to_virt(readq(info->ioc_regs+IOC_PDIR_BASE));
+        info->gatt = &io_pdir[(PLUTO_IOVA_SIZE/2) >> PAGE_SHIFT];
+
+        if (info->gatt[0] != SBA_AGPGART_COOKIE) {
+                info->gatt = NULL;
+                info->gatt_entries = 0;
+                printk(KERN_ERR DRVPFX "No reserved IO PDIR entry found; "
+                       "GART disabled\n");
+                return -ENODEV;
+        }
+
+        return 0;
+}
+
+static int
+lba_find_capability(int cap)
+{
+       struct _parisc_agp_info *info = &parisc_agp_info;
+        u16 status;
+        u8 pos, id;
+        int ttl = 48;
+
+        status = readw(info->lba_regs + PCI_STATUS);
+        if (!(status & PCI_STATUS_CAP_LIST))
+                return 0;
+        pos = readb(info->lba_regs + PCI_CAPABILITY_LIST);
+        while (ttl-- && pos >= 0x40) {
+                pos &= ~3;
+                id = readb(info->lba_regs + pos + PCI_CAP_LIST_ID);
+                if (id == 0xff)
+                        break;
+                if (id == cap)
+                        return pos;
+                pos = readb(info->lba_regs + pos + PCI_CAP_LIST_NEXT);
+        }
+        return 0;
+}
+
+static int __init
+agp_lba_init(void __iomem *lba_hpa)
+{
+       struct _parisc_agp_info *info = &parisc_agp_info;
+        int cap;
+
+       info->lba_regs = lba_hpa;
+        info->lba_cap_offset = lba_find_capability(PCI_CAP_ID_AGP);
+
+        cap = readl(lba_hpa + info->lba_cap_offset) & 0xff;
+        if (cap != PCI_CAP_ID_AGP) {
+                printk(KERN_ERR DRVPFX "Invalid capability ID 0x%02x at 0x%x\n",
+                       cap, info->lba_cap_offset);
+                return -ENODEV;
+        }
+
+        return 0;
+}
+
+static int __init
+parisc_agp_setup(void __iomem *ioc_hpa, void __iomem *lba_hpa)
+{
+       struct pci_dev *fake_bridge_dev = NULL;
+       struct agp_bridge_data *bridge;
+       int error = 0;
+
+       fake_bridge_dev = kmalloc(sizeof (struct pci_dev), GFP_KERNEL);
+       if (!fake_bridge_dev) {
+               error = -ENOMEM;
+               goto fail;
+       }
+
+       error = agp_ioc_init(ioc_hpa);
+       if (error)
+               goto fail;
+
+       error = agp_lba_init(lba_hpa);
+       if (error)
+               goto fail;
+
+       bridge = agp_alloc_bridge();
+       if (!bridge) {
+               error = -ENOMEM;
+               goto fail;
+       }
+       bridge->driver = &parisc_agp_driver;
+
+       fake_bridge_dev->vendor = PCI_VENDOR_ID_HP;
+       fake_bridge_dev->device = PCI_DEVICE_ID_HP_PCIX_LBA;
+       bridge->dev = fake_bridge_dev;
+
+       error = agp_add_bridge(bridge);
+
+fail:
+       return error;
+}
+
+static struct device *next_device(struct klist_iter *i) {
+       struct klist_node * n = klist_next(i);
+       return n ? container_of(n, struct device, knode_parent) : NULL;
+}
+
+static int
+parisc_agp_init(void)
+{
+       extern struct sba_device *sba_list;
+
+       int err = -1;
+       struct parisc_device *sba = NULL, *lba = NULL;
+       struct lba_device *lbadev = NULL;
+       struct device *dev = NULL;
+       struct klist_iter i;
+
+       if (!sba_list)
+               goto out;
+
+       /* Find our parent Pluto */
+       sba = sba_list->dev;
+       if (!IS_PLUTO(sba)) {
+               printk(KERN_INFO DRVPFX "No Pluto found, so no AGPGART for you.\n");
+               goto out;
+       }
+
+       /* Now search our Pluto for our precious AGP device... */
+       klist_iter_init(&sba->dev.klist_children, &i);
+       while ((dev = next_device(&i))) {
+               struct parisc_device *padev = to_parisc_device(dev);
+               if (IS_QUICKSILVER(padev))
+                       lba = padev;
+       }
+       klist_iter_exit(&i);
+
+       if (!lba) {
+               printk(KERN_INFO DRVPFX "No AGP devices found.\n");
+               goto out;
+       }
+
+       lbadev = parisc_get_drvdata(lba);
+
+       /* w00t, let's go find our cookies... */
+       parisc_agp_setup(sba_list->ioc[0].ioc_hpa, lbadev->hba.base_addr);
+
+       return 0;
+
+out:
+       return err;
+}
+
+module_init(parisc_agp_init);
+
+MODULE_AUTHOR("Kyle McMartin <kyle@parisc-linux.org>");
+MODULE_LICENSE("GPL");
index 1fbda77cefc29bfb0bbe820314feabce0d2c9700..c2949b4367e51b5c632ee765c7b799b2f6ba1211 100644 (file)
 #include <asm/superio.h>
 #endif
 
-#include <asm/iosapic.h>
+#include <asm/ropes.h>
 #include "./iosapic_private.h"
 
 #define MODULE_NAME "iosapic"
@@ -692,6 +692,7 @@ static void iosapic_end_irq(unsigned int irq)
        DBG(KERN_DEBUG "end_irq(%d): eoi(%p, 0x%x)\n", irq,
                        vi->eoi_addr, vi->eoi_data);
        iosapic_eoi(vi->eoi_addr, vi->eoi_data);
+       cpu_end_irq(irq);
 }
 
 static unsigned int iosapic_startup_irq(unsigned int irq)
@@ -728,7 +729,7 @@ static struct hw_interrupt_type iosapic_interrupt_type = {
        .shutdown =     iosapic_disable_irq,
        .enable =       iosapic_enable_irq,
        .disable =      iosapic_disable_irq,
-       .ack =          no_ack_irq,
+       .ack =          cpu_ack_irq,
        .end =          iosapic_end_irq,
 #ifdef CONFIG_SMP
        .set_affinity = iosapic_set_affinity_irq,
index 3fe4a77fa16a2301f0cb5a3ff96a51bb0c27ca18..ba6769934c771718035f8ed35c2a99c89021afce 100644 (file)
@@ -46,9 +46,9 @@
 #include <asm/page.h>
 #include <asm/system.h>
 
+#include <asm/ropes.h>
 #include <asm/hardware.h>      /* for register_parisc_driver() stuff */
 #include <asm/parisc-device.h>
-#include <asm/iosapic.h>       /* for iosapic_register() */
 #include <asm/io.h>            /* read/write stuff */
 
 #undef DEBUG_LBA       /* general stuff */
 
 #define MODULE_NAME "LBA"
 
-#define LBA_FUNC_ID    0x0000  /* function id */
-#define LBA_FCLASS     0x0008  /* function class, bist, header, rev... */
-#define LBA_CAPABLE    0x0030  /* capabilities register */
-
-#define LBA_PCI_CFG_ADDR       0x0040  /* poke CFG address here */
-#define LBA_PCI_CFG_DATA       0x0048  /* read or write data here */
-
-#define LBA_PMC_MTLT   0x0050  /* Firmware sets this - read only. */
-#define LBA_FW_SCRATCH 0x0058  /* Firmware writes the PCI bus number here. */
-#define LBA_ERROR_ADDR 0x0070  /* On error, address gets logged here */
-
-#define LBA_ARB_MASK   0x0080  /* bit 0 enable arbitration. PAT/PDC enables */
-#define LBA_ARB_PRI    0x0088  /* firmware sets this. */
-#define LBA_ARB_MODE   0x0090  /* firmware sets this. */
-#define LBA_ARB_MTLT   0x0098  /* firmware sets this. */
-
-#define LBA_MOD_ID     0x0100  /* Module ID. PDC_PAT_CELL reports 4 */
-
-#define LBA_STAT_CTL   0x0108  /* Status & Control */
-#define   LBA_BUS_RESET                0x01    /*  Deassert PCI Bus Reset Signal */
-#define   CLEAR_ERRLOG         0x10    /*  "Clear Error Log" cmd */
-#define   CLEAR_ERRLOG_ENABLE  0x20    /*  "Clear Error Log" Enable */
-#define   HF_ENABLE    0x40    /*    enable HF mode (default is -1 mode) */
-
-#define LBA_LMMIO_BASE 0x0200  /* < 4GB I/O address range */
-#define LBA_LMMIO_MASK 0x0208
-
-#define LBA_GMMIO_BASE 0x0210  /* > 4GB I/O address range */
-#define LBA_GMMIO_MASK 0x0218
-
-#define LBA_WLMMIO_BASE        0x0220  /* All < 4GB ranges under the same *SBA* */
-#define LBA_WLMMIO_MASK        0x0228
-
-#define LBA_WGMMIO_BASE        0x0230  /* All > 4GB ranges under the same *SBA* */
-#define LBA_WGMMIO_MASK        0x0238
-
-#define LBA_IOS_BASE   0x0240  /* I/O port space for this LBA */
-#define LBA_IOS_MASK   0x0248
-
-#define LBA_ELMMIO_BASE        0x0250  /* Extra LMMIO range */
-#define LBA_ELMMIO_MASK        0x0258
-
-#define LBA_EIOS_BASE  0x0260  /* Extra I/O port space */
-#define LBA_EIOS_MASK  0x0268
-
-#define LBA_GLOBAL_MASK        0x0270  /* Mercury only: Global Address Mask */
-#define LBA_DMA_CTL    0x0278  /* firmware sets this */
-
-#define LBA_IBASE      0x0300  /* SBA DMA support */
-#define LBA_IMASK      0x0308
-
-/* FIXME: ignore DMA Hint stuff until we can measure performance */
-#define LBA_HINT_CFG   0x0310
-#define LBA_HINT_BASE  0x0380  /* 14 registers at every 8 bytes. */
-
-#define LBA_BUS_MODE   0x0620
-
-/* ERROR regs are needed for config cycle kluges */
-#define LBA_ERROR_CONFIG 0x0680
-#define     LBA_SMART_MODE 0x20
-#define LBA_ERROR_STATUS 0x0688
-#define LBA_ROPE_CTL     0x06A0
-
-#define LBA_IOSAPIC_BASE       0x800 /* Offset of IRQ logic */
-
 /* non-postable I/O port space, densely packed */
 #define LBA_PORT_BASE  (PCI_F_EXTEND | 0xfee00000UL)
 static void __iomem *astro_iop_base __read_mostly;
 
-#define ELROY_HVERS    0x782
-#define MERCURY_HVERS  0x783
-#define QUICKSILVER_HVERS      0x784
-
-static inline int IS_ELROY(struct parisc_device *d)
-{
-       return (d->id.hversion == ELROY_HVERS);
-}
-
-static inline int IS_MERCURY(struct parisc_device *d)
-{
-       return (d->id.hversion == MERCURY_HVERS);
-}
-
-static inline int IS_QUICKSILVER(struct parisc_device *d)
-{
-       return (d->id.hversion == QUICKSILVER_HVERS);
-}
-
-
-/*
-** lba_device: Per instance Elroy data structure
-*/
-struct lba_device {
-       struct pci_hba_data hba;
-
-       spinlock_t      lba_lock;
-       void            *iosapic_obj;
-
-#ifdef CONFIG_64BIT
-       void __iomem *  iop_base;    /* PA_VIEW - for IO port accessor funcs */
-#endif
-
-       int             flags;       /* state/functionality enabled */
-       int             hw_rev;      /* HW revision of chip */
-};
-
-
 static u32 lba_t32;
 
 /* lba flags */
@@ -1542,8 +1439,8 @@ lba_driver_probe(struct parisc_device *dev)
                default: version = "TR4+";
                }
 
-               printk(KERN_INFO "%s version %s (0x%x) found at 0x%lx\n",
-                       MODULE_NAME, version, func_class & 0xf, dev->hpa.start);
+               printk(KERN_INFO "Elroy version %s (0x%x) found at 0x%lx\n",
+                      version, func_class & 0xf, dev->hpa.start);
 
                if (func_class < 2) {
                        printk(KERN_WARNING "Can't support LBA older than "
@@ -1563,14 +1460,18 @@ lba_driver_probe(struct parisc_device *dev)
                }
 
        } else if (IS_MERCURY(dev) || IS_QUICKSILVER(dev)) {
+               int major, minor;
+
                func_class &= 0xff;
-               version = kmalloc(6, GFP_KERNEL);
-               snprintf(version, 6, "TR%d.%d",(func_class >> 4),(func_class & 0xf));
+               major = func_class >> 4, minor = func_class & 0xf;
+
                /* We could use one printk for both Elroy and Mercury,
                  * but for the mask for func_class.
                  */ 
-               printk(KERN_INFO "%s version %s (0x%x) found at 0x%lx\n",
-                      MODULE_NAME, version, func_class & 0xff, dev->hpa.start);
+               printk(KERN_INFO "%s version TR%d.%d (0x%x) found at 0x%lx\n",
+                      IS_MERCURY(dev) ? "Mercury" : "Quicksilver", major,
+                      minor, func_class, dev->hpa.start);
+
                cfg_ops = &mercury_cfg_ops;
        } else {
                printk(KERN_ERR "Unknown LBA found at 0x%lx\n", dev->hpa.start);
@@ -1600,6 +1501,7 @@ lba_driver_probe(struct parisc_device *dev)
        lba_dev->hba.dev = dev;
        lba_dev->iosapic_obj = tmp_obj;  /* save interrupt handle */
        lba_dev->hba.iommu = sba_get_iommu(dev);  /* get iommu data */
+       parisc_set_drvdata(dev, lba_dev);
 
        /* ------------ Second : initialize common stuff ---------- */
        pci_bios = &lba_bios_ops;
index 8b47328155112ee1631aec5d47e300e5464971c7..294c1117098d69d6a0a9c13e26cd9f4727fbf528 100644 (file)
 #include <linux/proc_fs.h>
 #include <linux/seq_file.h>
 
+#include <asm/ropes.h>
+#include <asm/mckinley.h>      /* for proc_mckinley_root */
 #include <asm/runway.h>                /* for proc_runway_root */
 #include <asm/pdc.h>           /* for PDC_MODEL_* */
 #include <asm/pdcpat.h>                /* for is_pdc_pat() */
 #include <asm/parisc-device.h>
 
-
-/* declared in arch/parisc/kernel/setup.c */
-extern struct proc_dir_entry * proc_mckinley_root;
-
 #define MODULE_NAME "SBA"
 
-#ifdef CONFIG_PROC_FS
-/* depends on proc fs support. But costs CPU performance */
-#undef SBA_COLLECT_STATS
-#endif
-
 /*
 ** The number of debug flags is a clue - this code is fragile.
 ** Don't even think about messing with it unless you have
@@ -92,202 +85,12 @@ extern struct proc_dir_entry * proc_mckinley_root;
 #define DBG_RES(x...)
 #endif
 
-#if defined(CONFIG_64BIT)
-/* "low end" PA8800 machines use ZX1 chipset: PAT PDC and only run 64-bit */
-#define ZX1_SUPPORT
-#endif
-
 #define SBA_INLINE     __inline__
 
-
-/*
-** The number of pdir entries to "free" before issueing
-** a read to PCOM register to flush out PCOM writes.
-** Interacts with allocation granularity (ie 4 or 8 entries
-** allocated and free'd/purged at a time might make this
-** less interesting).
-*/
-#define DELAYED_RESOURCE_CNT   16
-
 #define DEFAULT_DMA_HINT_REG   0
 
-#define ASTRO_RUNWAY_PORT      0x582
-#define IKE_MERCED_PORT                0x803
-#define REO_MERCED_PORT                0x804
-#define REOG_MERCED_PORT       0x805
-#define PLUTO_MCKINLEY_PORT    0x880
-
-#define SBA_FUNC_ID    0x0000  /* function id */
-#define SBA_FCLASS     0x0008  /* function class, bist, header, rev... */
-
-#define IS_ASTRO(id)           ((id)->hversion == ASTRO_RUNWAY_PORT)
-#define IS_IKE(id)             ((id)->hversion == IKE_MERCED_PORT)
-#define IS_PLUTO(id)           ((id)->hversion == PLUTO_MCKINLEY_PORT)
-
-#define SBA_FUNC_SIZE 4096   /* SBA configuration function reg set */
-
-#define ASTRO_IOC_OFFSET       (32 * SBA_FUNC_SIZE)
-#define PLUTO_IOC_OFFSET       (1 * SBA_FUNC_SIZE)
-/* Ike's IOC's occupy functions 2 and 3 */
-#define IKE_IOC_OFFSET(p)      ((p+2) * SBA_FUNC_SIZE)
-
-#define IOC_CTRL          0x8  /* IOC_CTRL offset */
-#define IOC_CTRL_TC       (1 << 0) /* TOC Enable */
-#define IOC_CTRL_CE       (1 << 1) /* Coalesce Enable */
-#define IOC_CTRL_DE       (1 << 2) /* Dillon Enable */
-#define IOC_CTRL_RM       (1 << 8) /* Real Mode */
-#define IOC_CTRL_NC       (1 << 9) /* Non Coherent Mode */
-#define IOC_CTRL_D4       (1 << 11) /* Disable 4-byte coalescing */
-#define IOC_CTRL_DD       (1 << 13) /* Disable distr. LMMIO range coalescing */
-
-#define MAX_IOC                2       /* per Ike. Pluto/Astro only have 1. */
-
-#define ROPES_PER_IOC  8       /* per Ike half or Pluto/Astro */
-
-
-/*
-** Offsets into MBIB (Function 0 on Ike and hopefully Astro)
-** Firmware programs this stuff. Don't touch it.
-*/
-#define LMMIO_DIRECT0_BASE  0x300
-#define LMMIO_DIRECT0_MASK  0x308
-#define LMMIO_DIRECT0_ROUTE 0x310
-
-#define LMMIO_DIST_BASE  0x360
-#define LMMIO_DIST_MASK  0x368
-#define LMMIO_DIST_ROUTE 0x370
-
-#define IOS_DIST_BASE  0x390
-#define IOS_DIST_MASK  0x398
-#define IOS_DIST_ROUTE 0x3A0
-
-#define IOS_DIRECT_BASE        0x3C0
-#define IOS_DIRECT_MASK        0x3C8
-#define IOS_DIRECT_ROUTE 0x3D0
-
-/*
-** Offsets into I/O TLB (Function 2 and 3 on Ike)
-*/
-#define ROPE0_CTL      0x200  /* "regbus pci0" */
-#define ROPE1_CTL      0x208
-#define ROPE2_CTL      0x210
-#define ROPE3_CTL      0x218
-#define ROPE4_CTL      0x220
-#define ROPE5_CTL      0x228
-#define ROPE6_CTL      0x230
-#define ROPE7_CTL      0x238
-
-#define IOC_ROPE0_CFG  0x500   /* pluto only */
-#define   IOC_ROPE_AO    0x10  /* Allow "Relaxed Ordering" */
-
-
-
-#define HF_ENABLE      0x40
-
-
-#define IOC_IBASE      0x300   /* IO TLB */
-#define IOC_IMASK      0x308
-#define IOC_PCOM       0x310
-#define IOC_TCNFG      0x318
-#define IOC_PDIR_BASE  0x320
-
-/* AGP GART driver looks for this */
-#define SBA_IOMMU_COOKIE    0x0000badbadc0ffeeUL
-
-
-/*
-** IOC supports 4/8/16/64KB page sizes (see TCNFG register)
-** It's safer (avoid memory corruption) to keep DMA page mappings
-** equivalently sized to VM PAGE_SIZE.
-**
-** We really can't avoid generating a new mapping for each
-** page since the Virtual Coherence Index has to be generated
-** and updated for each page.
-**
-** PAGE_SIZE could be greater than IOVP_SIZE. But not the inverse.
-*/
-#define IOVP_SIZE      PAGE_SIZE
-#define IOVP_SHIFT     PAGE_SHIFT
-#define IOVP_MASK      PAGE_MASK
-
-#define SBA_PERF_CFG   0x708   /* Performance Counter stuff */
-#define SBA_PERF_MASK1 0x718
-#define SBA_PERF_MASK2 0x730
-
-
-/*
-** Offsets into PCI Performance Counters (functions 12 and 13)
-** Controlled by PERF registers in function 2 & 3 respectively.
-*/
-#define SBA_PERF_CNT1  0x200
-#define SBA_PERF_CNT2  0x208
-#define SBA_PERF_CNT3  0x210
-
-
-struct ioc {
-       void __iomem    *ioc_hpa;       /* I/O MMU base address */
-       char            *res_map;       /* resource map, bit == pdir entry */
-       u64             *pdir_base;     /* physical base address */
-       unsigned long   ibase;  /* pdir IOV Space base - shared w/lba_pci */
-       unsigned long   imask;  /* pdir IOV Space mask - shared w/lba_pci */
-#ifdef ZX1_SUPPORT
-       unsigned long   iovp_mask;      /* help convert IOVA to IOVP */
-#endif
-       unsigned long   *res_hint;      /* next avail IOVP - circular search */
-       spinlock_t      res_lock;
-       unsigned int    res_bitshift;   /* from the LEFT! */
-       unsigned int    res_size;       /* size of resource map in bytes */
-#ifdef SBA_HINT_SUPPORT
-/* FIXME : DMA HINTs not used */
-       unsigned long   hint_mask_pdir; /* bits used for DMA hints */
-       unsigned int    hint_shift_pdir;
-#endif
-#if DELAYED_RESOURCE_CNT > 0
-       int saved_cnt;
-       struct sba_dma_pair {
-               dma_addr_t      iova;
-               size_t          size;
-       } saved[DELAYED_RESOURCE_CNT];
-#endif
-
-#ifdef SBA_COLLECT_STATS
-#define SBA_SEARCH_SAMPLE      0x100
-       unsigned long avg_search[SBA_SEARCH_SAMPLE];
-       unsigned long avg_idx;  /* current index into avg_search */
-       unsigned long used_pages;
-       unsigned long msingle_calls;
-       unsigned long msingle_pages;
-       unsigned long msg_calls;
-       unsigned long msg_pages;
-       unsigned long usingle_calls;
-       unsigned long usingle_pages;
-       unsigned long usg_calls;
-       unsigned long usg_pages;
-#endif
-
-       /* STUFF We don't need in performance path */
-       unsigned int    pdir_size;      /* in bytes, determined by IOV Space size */
-};
-
-struct sba_device {
-       struct sba_device       *next;  /* list of SBA's in system */
-       struct parisc_device    *dev;   /* dev found in bus walk */
-       struct parisc_device_id *iodc;  /* data about dev from firmware */
-       const char              *name;
-       void __iomem            *sba_hpa; /* base address */
-       spinlock_t              sba_lock;
-       unsigned int            flags;  /* state/functionality enabled */
-       unsigned int            hw_rev;  /* HW revision of chip */
-
-       struct resource         chip_resv; /* MMIO reserved for chip */
-       struct resource         iommu_resv; /* MMIO reserved for iommu */
-
-       unsigned int            num_ioc;  /* number of on-board IOC's */
-       struct ioc              ioc[MAX_IOC];
-};
-
-
-static struct sba_device *sba_list;
+struct sba_device *sba_list;
+EXPORT_SYMBOL_GPL(sba_list);
 
 static unsigned long ioc_needs_fdc = 0;
 
@@ -300,8 +103,14 @@ static unsigned long piranha_bad_128k = 0;
 /* Looks nice and keeps the compiler happy */
 #define SBA_DEV(d) ((struct sba_device *) (d))
 
+#ifdef CONFIG_AGP_PARISC
+#define SBA_AGP_SUPPORT
+#endif /*CONFIG_AGP_PARISC*/
+
 #ifdef SBA_AGP_SUPPORT
-static int reserve_sba_gart = 1;
+static int sba_reserve_agpgart = 1;
+module_param(sba_reserve_agpgart, int, 1);
+MODULE_PARM_DESC(sba_reserve_agpgart, "Reserve half of IO pdir as AGPGART");
 #endif
 
 #define ROUNDUP(x,y) ((x + ((y)-1)) & ~((y)-1))
@@ -741,7 +550,7 @@ sba_io_pdir_entry(u64 *pdir_ptr, space_t sid, unsigned long vba,
        asm("lci 0(%%sr1, %1), %0" : "=r" (ci) : "r" (vba));
        pa |= (ci >> 12) & 0xff;  /* move CI (8 bits) into lowest byte */
 
-       pa |= 0x8000000000000000ULL;    /* set "valid" bit */
+       pa |= SBA_PDIR_VALID_BIT;       /* set "valid" bit */
        *pdir_ptr = cpu_to_le64(pa);    /* swap and store into I/O Pdir */
 
        /*
@@ -1498,6 +1307,10 @@ sba_ioc_init_pluto(struct parisc_device *sba, struct ioc *ioc, int ioc_num)
        WRITE_REG(ioc->ibase | 31, ioc->ioc_hpa + IOC_PCOM);
 
 #ifdef SBA_AGP_SUPPORT
+{
+       struct klist_iter i;
+       struct device *dev = NULL;
+
        /*
        ** If an AGP device is present, only use half of the IOV space
        ** for PCI DMA.  Unfortunately we can't know ahead of time
@@ -1506,20 +1319,22 @@ sba_ioc_init_pluto(struct parisc_device *sba, struct ioc *ioc, int ioc_num)
        ** We program the next pdir index after we stop w/ a key for
        ** the GART code to handshake on.
        */
-       device=NULL;
-       for (lba = sba->child; lba; lba = lba->sibling) {
+       klist_iter_init(&sba->dev.klist_children, &i);
+       while (dev = next_device(&i)) {
+               struct parisc_device *lba = to_parisc_device(dev);
                if (IS_QUICKSILVER(lba))
-                       break;
+                       agp_found = 1;
        }
+       klist_iter_exit(&sba->dev.klist_children, &i);
 
-       if (lba) {
-               DBG_INIT("%s: Reserving half of IOVA space for AGP GART support\n", __FUNCTION__);
+       if (agp_found && sba_reserve_agpgart) {
+               printk(KERN_INFO "%s: reserving %dMb of IOVA space for agpgart\n",
+                      __FUNCTION__, (iova_space_size/2) >> 20);
                ioc->pdir_size /= 2;
-               ((u64 *)ioc->pdir_base)[PDIR_INDEX(iova_space_size/2)] = SBA_IOMMU_COOKIE;
-       } else {
-               DBG_INIT("%s: No GART needed - no AGP controller found\n", __FUNCTION__);
+               ioc->pdir_base[PDIR_INDEX(iova_space_size/2)] = SBA_AGPGART_COOKIE;
        }
-#endif /* 0 */
+}
+#endif /*SBA_AGP_SUPPORT*/
 
 }
 
@@ -1701,7 +1516,7 @@ printk("sba_hw_init(): mem_boot 0x%x 0x%x 0x%x 0x%x\n", PAGE0->mem_boot.hpa,
        }
 #endif
 
-       if (!IS_PLUTO(sba_dev->iodc)) {
+       if (!IS_PLUTO(sba_dev->dev)) {
                ioc_ctl = READ_REG(sba_dev->sba_hpa+IOC_CTRL);
                DBG_INIT("%s() hpa 0x%lx ioc_ctl 0x%Lx ->",
                        __FUNCTION__, sba_dev->sba_hpa, ioc_ctl);
@@ -1718,9 +1533,8 @@ printk("sba_hw_init(): mem_boot 0x%x 0x%x 0x%x 0x%x\n", PAGE0->mem_boot.hpa,
 #endif
        } /* if !PLUTO */
 
-       if (IS_ASTRO(sba_dev->iodc)) {
+       if (IS_ASTRO(sba_dev->dev)) {
                int err;
-               /* PAT_PDC (L-class) also reports the same goofy base */
                sba_dev->ioc[0].ioc_hpa = ioc_remap(sba_dev, ASTRO_IOC_OFFSET);
                num_ioc = 1;
 
@@ -1730,13 +1544,9 @@ printk("sba_hw_init(): mem_boot 0x%x 0x%x 0x%x 0x%x\n", PAGE0->mem_boot.hpa,
                err = request_resource(&iomem_resource, &(sba_dev->chip_resv));
                BUG_ON(err < 0);
 
-       } else if (IS_PLUTO(sba_dev->iodc)) {
+       } else if (IS_PLUTO(sba_dev->dev)) {
                int err;
 
-               /* We use a negative value for IOC HPA so it gets 
-                 * corrected when we add it with IKE's IOC offset.
-                * Doesnt look clean, but fewer code. 
-                 */
                sba_dev->ioc[0].ioc_hpa = ioc_remap(sba_dev, PLUTO_IOC_OFFSET);
                num_ioc = 1;
 
@@ -1752,14 +1562,14 @@ printk("sba_hw_init(): mem_boot 0x%x 0x%x 0x%x 0x%x\n", PAGE0->mem_boot.hpa,
                err = request_resource(&iomem_resource, &(sba_dev->iommu_resv));
                WARN_ON(err < 0);
        } else {
-               /* IS_IKE (ie N-class, L3000, L1500) */
+               /* IKE, REO */
                sba_dev->ioc[0].ioc_hpa = ioc_remap(sba_dev, IKE_IOC_OFFSET(0));
                sba_dev->ioc[1].ioc_hpa = ioc_remap(sba_dev, IKE_IOC_OFFSET(1));
                num_ioc = 2;
 
                /* TODO - LOOKUP Ike/Stretch chipset mem map */
        }
-       /* XXX: What about Reo? */
+       /* XXX: What about Reo Grande? */
 
        sba_dev->num_ioc = num_ioc;
        for (i = 0; i < num_ioc; i++) {
@@ -1774,7 +1584,7 @@ printk("sba_hw_init(): mem_boot 0x%x 0x%x 0x%x 0x%x\n", PAGE0->mem_boot.hpa,
                         * Overrides bit 1 in DMA Hint Sets.
                         * Improves netperf UDP_STREAM by ~10% for bcm5701.
                         */
-                       if (IS_PLUTO(sba_dev->iodc)) {
+                       if (IS_PLUTO(sba_dev->dev)) {
                                void __iomem *rope_cfg;
                                unsigned long cfg_val;
 
@@ -1803,7 +1613,7 @@ printk("sba_hw_init(): mem_boot 0x%x 0x%x 0x%x 0x%x\n", PAGE0->mem_boot.hpa,
                                READ_REG(sba_dev->ioc[i].ioc_hpa + 0x400)
                        );
 
-               if (IS_PLUTO(sba_dev->iodc)) {
+               if (IS_PLUTO(sba_dev->dev)) {
                        sba_ioc_init_pluto(sba_dev->dev, &(sba_dev->ioc[i]), i);
                } else {
                        sba_ioc_init(sba_dev->dev, &(sba_dev->ioc[i]), i);
@@ -2067,7 +1877,7 @@ sba_driver_callback(struct parisc_device *dev)
        /* Read HW Rev First */
        func_class = READ_REG(sba_addr + SBA_FCLASS);
 
-       if (IS_ASTRO(&dev->id)) {
+       if (IS_ASTRO(dev)) {
                unsigned long fclass;
                static char astro_rev[]="Astro ?.?";
 
@@ -2078,11 +1888,11 @@ sba_driver_callback(struct parisc_device *dev)
                astro_rev[8] = '0' + (char) ((fclass & 0x18) >> 3);
                version = astro_rev;
 
-       } else if (IS_IKE(&dev->id)) {
+       } else if (IS_IKE(dev)) {
                static char ike_rev[] = "Ike rev ?";
                ike_rev[8] = '0' + (char) (func_class & 0xff);
                version = ike_rev;
-       } else if (IS_PLUTO(&dev->id)) {
+       } else if (IS_PLUTO(dev)) {
                static char pluto_rev[]="Pluto ?.?";
                pluto_rev[6] = '0' + (char) ((func_class & 0xf0) >> 4); 
                pluto_rev[8] = '0' + (char) (func_class & 0x0f); 
@@ -2097,7 +1907,7 @@ sba_driver_callback(struct parisc_device *dev)
                global_ioc_cnt = count_parisc_driver(&sba_driver);
 
                /* Astro and Pluto have one IOC per SBA */
-               if ((!IS_ASTRO(&dev->id)) || (!IS_PLUTO(&dev->id)))
+               if ((!IS_ASTRO(dev)) || (!IS_PLUTO(dev)))
                        global_ioc_cnt *= 2;
        }
 
@@ -2117,7 +1927,6 @@ sba_driver_callback(struct parisc_device *dev)
 
        sba_dev->dev = dev;
        sba_dev->hw_rev = func_class;
-       sba_dev->iodc = &dev->id;
        sba_dev->name = dev->name;
        sba_dev->sba_hpa = sba_addr;
 
index 1ebe6b585d2d57d3c44b4d52bcceebb3b5fdfd78..c5d0addfda4f9404d97ffb9f39c46b9f5e79a7c8 100644 (file)
@@ -22,7 +22,6 @@
 #include <asm/hardware.h>
 #include <asm/parisc-device.h>
 #include <asm/io.h>
-#include <asm/serial.h> /* for LASI_BASE_BAUD */
 
 #include "8250.h"
 
@@ -54,7 +53,8 @@ serial_init_chip(struct parisc_device *dev)
 
        memset(&port, 0, sizeof(port));
        port.iotype     = UPIO_MEM;
-       port.uartclk    = LASI_BASE_BAUD * 16;
+       /* 7.272727MHz on Lasi.  Assumed the same for Dino, Wax and Timi. */
+       port.uartclk    = 7272727;
        port.mapbase    = address;
        port.membase    = ioremap_nocache(address, 16);
        port.irq        = dev->irq;
index 653098bc2dd51ca5c2dedb89751cd90a0bab22b8..8edee745888a7371ab653534ed8e865ae4a83ccf 100644 (file)
@@ -556,10 +556,11 @@ config SERIAL_MUX
        default y
        ---help---
          Saying Y here will enable the hardware MUX serial driver for
-         the Nova and K class systems.  The hardware MUX is not 8250/16550 
-         compatible therefore the /dev/ttyB0 device is shared between the 
-         Serial MUX and the PDC software console.  The following steps 
-         need to be completed to use the Serial MUX:
+         the Nova, K class systems and D class with a 'remote control card'.
+         The hardware MUX is not 8250/16550 compatible therefore the
+         /dev/ttyB0 device is shared between the Serial MUX and the PDC
+         software console. The following steps need to be completed to use
+         the Serial MUX:
 
            1. create the device entry (mknod /dev/ttyB0 c 11 0)
            2. Edit the /etc/inittab to start a getty listening on /dev/ttyB0
index 32b5d625ce9c7c311835139eea61e8b98896a7b1..5bcdaaf4eae082f26adb82f0d2fe843dd4fc6ad1 100644 (file)
@@ -29,6 +29,7 @@
 #include <linux/personality.h>
 #include <linux/init.h>
 
+#include <asm/a.out.h>
 #include <asm/uaccess.h>
 #include <asm/pgtable.h>
 
@@ -194,6 +195,7 @@ load_som_binary(struct linux_binprm * bprm, struct pt_regs * regs)
        unsigned long som_entry;
        struct som_hdr *som_ex;
        struct som_exec_auxhdr *hpuxhdr;
+       struct files_struct *files;
 
        /* Get the exec-header */
        som_ex = (struct som_hdr *) bprm->buf;
@@ -208,15 +210,27 @@ load_som_binary(struct linux_binprm * bprm, struct pt_regs * regs)
        size = som_ex->aux_header_size;
        if (size > SOM_PAGESIZE)
                goto out;
-       hpuxhdr = (struct som_exec_auxhdr *) kmalloc(size, GFP_KERNEL);
+       hpuxhdr = kmalloc(size, GFP_KERNEL);
        if (!hpuxhdr)
                goto out;
 
        retval = kernel_read(bprm->file, som_ex->aux_header_location,
                        (char *) hpuxhdr, size);
+       if (retval != size) {
+               if (retval >= 0)
+                       retval = -EIO;
+               goto out_free;
+       }
+
+       files = current->files; /* Refcounted so ok */
+       retval = unshare_files();
        if (retval < 0)
                goto out_free;
-#error "Fix security hole before enabling me"
+       if (files == current->files) {
+               put_files_struct(files);
+               files = NULL;
+       }
+
        retval = get_unused_fd();
        if (retval < 0)
                goto out_free;
diff --git a/include/asm-parisc/agp.h b/include/asm-parisc/agp.h
new file mode 100644 (file)
index 0000000..9f61d4e
--- /dev/null
@@ -0,0 +1,25 @@
+#ifndef _ASM_PARISC_AGP_H
+#define _ASM_PARISC_AGP_H
+
+/*
+ * PARISC specific AGP definitions.
+ * Copyright (c) 2006 Kyle McMartin <kyle@parisc-linux.org>
+ *
+ */
+
+#define map_page_into_agp(page)                /* nothing */
+#define unmap_page_from_agp(page)      /* nothing */
+#define flush_agp_mappings()           /* nothing */
+#define flush_agp_cache()              mb()
+
+/* Convert a physical address to an address suitable for the GART. */
+#define phys_to_gart(x) (x)
+#define gart_to_phys(x) (x)
+
+/* GATT allocation. Returns/accepts GATT kernel virtual address. */
+#define alloc_gatt_pages(order)                \
+       ((char *)__get_free_pages(GFP_KERNEL, (order)))
+#define free_gatt_pages(table, order)  \
+       free_pages((unsigned long)(table), (order))
+
+#endif /* _ASM_PARISC_AGP_H */
index 1a7bfe699e0ccc5a33b5ab1a3c65e9b0822b780f..5a1e0e8b1c32d7843b77eccddc4049a46b27777c 100644 (file)
@@ -29,7 +29,8 @@
 #define LDREGX  ldd,s
 #define LDREGM ldd,mb
 #define STREGM std,ma
-#define SHRREG  shrd
+#define SHRREG shrd
+#define SHLREG shld
 #define RP_OFFSET      16
 #define FRAME_SIZE     128
 #define CALLEE_REG_FRAME_SIZE  144
@@ -39,7 +40,8 @@
 #define LDREGX  ldwx,s
 #define LDREGM ldwm
 #define STREGM stwm
-#define SHRREG  shr
+#define SHRREG shr
+#define SHLREG shlw
 #define RP_OFFSET      20
 #define FRAME_SIZE     64
 #define CALLEE_REG_FRAME_SIZE  128
index 0b459cdfbd6ffbe79d1b70781069d83949f1803e..2bc41f2e0271c21813c6c62273af0875a36db0df 100644 (file)
@@ -191,16 +191,38 @@ flush_anon_page(struct page *page, unsigned long vmaddr)
 }
 #define ARCH_HAS_FLUSH_ANON_PAGE
 
-static inline void
-flush_kernel_dcache_page(struct page *page)
+#define ARCH_HAS_FLUSH_KERNEL_DCACHE_PAGE
+void flush_kernel_dcache_page_addr(void *addr);
+static inline void flush_kernel_dcache_page(struct page *page)
 {
-       flush_kernel_dcache_page_asm(page_address(page));
+       flush_kernel_dcache_page_addr(page_address(page));
 }
-#define ARCH_HAS_FLUSH_KERNEL_DCACHE_PAGE
 
 #ifdef CONFIG_DEBUG_RODATA
 void mark_rodata_ro(void);
 #endif
 
+#ifdef CONFIG_PA8X00
+/* Only pa8800, pa8900 needs this */
+#define ARCH_HAS_KMAP
+
+void kunmap_parisc(void *addr);
+
+static inline void *kmap(struct page *page)
+{
+       might_sleep();
+       return page_address(page);
+}
+
+#define kunmap(page)                   kunmap_parisc(page_address(page))
+
+#define kmap_atomic(page, idx)         page_address(page)
+
+#define kunmap_atomic(addr, idx)       kunmap_parisc(addr)
+
+#define kmap_atomic_pfn(pfn, idx)      page_address(pfn_to_page(pfn))
+#define kmap_atomic_to_page(ptr)       virt_to_page(ptr)
+#endif
+
 #endif /* _PARISC_CACHEFLUSH_H */
 
index 71b4eeea205a1a85eda581179fd97b46eeee0e83..fe8579023531d5a8e8788eea06c7f672f161fa36 100644 (file)
@@ -5,7 +5,7 @@
  */
 #include <linux/types.h>
 #include <linux/sched.h>
-#include <linux/personality.h>
+#include <linux/thread_info.h>
 
 #define COMPAT_USER_HZ 100
 
@@ -152,7 +152,7 @@ static __inline__ void __user *compat_alloc_user_space(long len)
 
 static inline int __is_compat_task(struct task_struct *t)
 {
-       return personality(t->personality) == PER_LINUX32;
+       return test_ti_thread_flag(t->thread_info, TIF_32BIT);
 }
 
 static inline int is_compat_task(void)
index 9979c3cb37454a23e53a3d7ce2d300a8bd11a3f7..da2cf373e31c54af3e746e95d87d08656299b518 100644 (file)
 #define DMA2_MASK_ALL_REG       0xDE    /* all-channels mask (w) */
 #define DMA2_EXT_MODE_REG      (0x400 | DMA2_MODE_REG)
 
-extern spinlock_t dma_spin_lock;
-
 static __inline__ unsigned long claim_dma_lock(void)
 {
-       unsigned long flags;
-       spin_lock_irqsave(&dma_spin_lock, flags);
-       return flags;
+       return 0;
 }
 
 static __inline__ void release_dma_lock(unsigned long flags)
 {
-       spin_unlock_irqrestore(&dma_spin_lock, flags);
 }
 
 
index 6a332a9f099c2eafbf78ee5f79056a349d41a775..d84bbb283fd17c7a8e9fb92d4a30a660efe86263 100644 (file)
@@ -1,6 +1,71 @@
-#ifndef _ASM_FUTEX_H
-#define _ASM_FUTEX_H
+#ifndef _ASM_PARISC_FUTEX_H
+#define _ASM_PARISC_FUTEX_H
 
-#include <asm-generic/futex.h>
+#ifdef __KERNEL__
 
+#include <linux/futex.h>
+#include <asm/errno.h>
+#include <asm/uaccess.h>
+
+static inline int
+futex_atomic_op_inuser (int encoded_op, int __user *uaddr)
+{
+       int op = (encoded_op >> 28) & 7;
+       int cmp = (encoded_op >> 24) & 15;
+       int oparg = (encoded_op << 8) >> 20;
+       int cmparg = (encoded_op << 20) >> 20;
+       int oldval = 0, ret;
+       if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
+               oparg = 1 << oparg;
+
+       if (! access_ok (VERIFY_WRITE, uaddr, sizeof(int)))
+               return -EFAULT;
+
+       inc_preempt_count();
+
+       switch (op) {
+       case FUTEX_OP_SET:
+       case FUTEX_OP_ADD:
+       case FUTEX_OP_OR:
+       case FUTEX_OP_ANDN:
+       case FUTEX_OP_XOR:
+       default:
+               ret = -ENOSYS;
+       }
+
+       dec_preempt_count();
+
+       if (!ret) {
+               switch (cmp) {
+               case FUTEX_OP_CMP_EQ: ret = (oldval == cmparg); break;
+               case FUTEX_OP_CMP_NE: ret = (oldval != cmparg); break;
+               case FUTEX_OP_CMP_LT: ret = (oldval < cmparg); break;
+               case FUTEX_OP_CMP_GE: ret = (oldval >= cmparg); break;
+               case FUTEX_OP_CMP_LE: ret = (oldval <= cmparg); break;
+               case FUTEX_OP_CMP_GT: ret = (oldval > cmparg); break;
+               default: ret = -ENOSYS;
+               }
+       }
+       return ret;
+}
+
+/* Non-atomic version */
+static inline int
+futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval, int newval)
+{
+       int err = 0;
+       int uval;
+
+       if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int)))
+               return -EFAULT;
+
+       err = get_user(uval, uaddr);
+       if (err) return -EFAULT;
+       if (uval == oldval)
+               err = put_user(newval, uaddr);
+       if (err) return -EFAULT;
+       return uval;
+}
+
+#endif
 #endif
index b9eb245b88749f16ea144fac741942041f30dc27..c1963ce19dd26df0fa7fd3977a0f6592e769dae6 100644 (file)
@@ -134,7 +134,7 @@ extern inline void __iomem * ioremap(unsigned long offset, unsigned long size)
 }
 #define ioremap_nocache(off, sz)       ioremap((off), (sz))
 
-extern void iounmap(void __iomem *addr);
+extern void iounmap(const volatile void __iomem *addr);
 
 static inline unsigned char __raw_readb(const volatile void __iomem *addr)
 {
diff --git a/include/asm-parisc/iosapic.h b/include/asm-parisc/iosapic.h
deleted file mode 100644 (file)
index 613390e..0000000
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
-** This file is private to iosapic driver.
-** If stuff needs to be used by another driver, move it to a common file.
-**
-** WARNING: fields most data structures here are ordered to make sure
-**          they pack nicely for 64-bit compilation. (ie sizeof(long) == 8)
-*/
-
-
-/*
-** I/O SAPIC init function
-** Caller knows where an I/O SAPIC is. LBA has an integrated I/O SAPIC.
-** Call setup as part of per instance initialization.
-** (ie *not* init_module() function unless only one is present.)
-** fixup_irq is to initialize PCI IRQ line support and
-** virtualize pcidev->irq value. To be called by pci_fixup_bus().
-*/
-extern void *iosapic_register(unsigned long hpa);
-extern int iosapic_fixup_irq(void *obj, struct pci_dev *pcidev);
-
-
-#ifdef __IA64__
-/*
-** PA: PIB (Processor Interrupt Block) is handled by Runway bus adapter.
-**     and is hardcoded to 0xfeeNNNN0 where NNNN is id_eid field.
-**
-** IA64: PIB is handled by "Local SAPIC" (integrated in the processor).
-*/
-struct local_sapic_info {
-       struct local_sapic_info *lsi_next;      /* point to next CPU info */
-       int                     *lsi_cpu_id;    /* point to logical CPU id */
-       unsigned long           *lsi_id_eid;    /* point to IA-64 CPU id */
-       int                     *lsi_status;    /* point to CPU status   */
-       void                    *lsi_private;   /* point to special info */
-};
-
-/*
-** "root" data structure which ties everything together.
-** Should always be able to start with sapic_root and locate
-** the desired information.
-*/
-struct sapic_info {
-       struct sapic_info       *si_next;       /* info is per cell */
-       int                     si_cellid;      /* cell id */
-       unsigned int            si_status;       /* status  */
-       char                    *si_pib_base;   /* intr blk base address */
-       local_sapic_info_t      *si_local_info;
-       io_sapic_info_t         *si_io_info;
-       extint_info_t           *si_extint_info;/* External Intr info      */
-};
-
-#endif /* IA64 */
-
index 5cae260615a22a74d14075d529a47419e9d02137..399c81981ed5a2081e8a4a32dff54c341d2036af 100644 (file)
@@ -31,7 +31,7 @@ static __inline__ int irq_canonicalize(int irq)
        return (irq == 2) ? 9 : irq;
 }
 
-struct hw_interrupt_type;
+struct irq_chip;
 
 /*
  * Some useful "we don't have to do anything here" handlers.  Should
@@ -39,6 +39,8 @@ struct hw_interrupt_type;
  */
 void no_ack_irq(unsigned int irq);
 void no_end_irq(unsigned int irq);
+void cpu_ack_irq(unsigned int irq);
+void cpu_end_irq(unsigned int irq);
 
 extern int txn_alloc_irq(unsigned int nbits);
 extern int txn_claim_irq(int);
@@ -46,7 +48,7 @@ extern unsigned int txn_alloc_data(unsigned int);
 extern unsigned long txn_alloc_addr(unsigned int);
 extern unsigned long txn_affinity_addr(unsigned int irq, int cpu);
 
-extern int cpu_claim_irq(unsigned int irq, struct hw_interrupt_type *, void *);
+extern int cpu_claim_irq(unsigned int irq, struct irq_chip *, void *);
 extern int cpu_check_affinity(unsigned int irq, cpumask_t *dest);
 
 /* soft power switch support (power.c) */
diff --git a/include/asm-parisc/mckinley.h b/include/asm-parisc/mckinley.h
new file mode 100644 (file)
index 0000000..d1ea6f1
--- /dev/null
@@ -0,0 +1,9 @@
+#ifndef ASM_PARISC_MCKINLEY_H
+#define ASM_PARISC_MCKINLEY_H
+#ifdef __KERNEL__
+
+/* declared in arch/parisc/kernel/setup.c */
+extern struct proc_dir_entry * proc_mckinley_root;
+
+#endif /*__KERNEL__*/
+#endif /*ASM_PARISC_MCKINLEY_H*/
index 57d6d82756dd678d54a7f261859730f8c998e3bb..3567208191e37d09f47199a26a0a223dce1b6c28 100644 (file)
 
 struct page;
 
-extern void purge_kernel_dcache_page(unsigned long);
-extern void copy_user_page_asm(void *to, void *from);
-extern void clear_user_page_asm(void *page, unsigned long vaddr);
-
-static inline void
-copy_user_page(void *vto, void *vfrom, unsigned long vaddr, struct page *pg)
-{
-       copy_user_page_asm(vto, vfrom);
-       flush_kernel_dcache_page_asm(vto);
-       /* XXX: ppc flushes icache too, should we? */
-}
-
-static inline void
-clear_user_page(void *page, unsigned long vaddr, struct page *pg)
-{
-       purge_kernel_dcache_page((unsigned long)page);
-       clear_user_page_asm(page, vaddr);
-}
+void copy_user_page_asm(void *to, void *from);
+void copy_user_page(void *vto, void *vfrom, unsigned long vaddr,
+                          struct page *pg);
+void clear_user_page(void *page, unsigned long vaddr, struct page *pg);
 
 /*
  * These are used to make use of C type-checking..
index 07cb9b93cfe25e30bf449f47ac2275fdf6ac9781..32e03d8778587806cb001c9f6b98df3f1763e256 100644 (file)
@@ -2,13 +2,9 @@
 #define _ASMPARISC_PARAM_H
 
 #ifdef __KERNEL__
-# ifdef CONFIG_PA20
-#  define HZ           1000            /* Faster machines */
-# else
-#  define HZ           100             /* Internal kernel timer frequency */
-# endif
-# define USER_HZ       100             /* .. some user interfaces are in "ticks" */
-# define CLOCKS_PER_SEC        (USER_HZ)       /* like times() */
+#define HZ             CONFIG_HZ
+#define USER_HZ                100             /* some user API use "ticks" */
+#define CLOCKS_PER_SEC (USER_HZ)       /* like times() */
 #endif
 
 #ifndef HZ
index 1d247e32a6088e180284e5fb7be23ed8ce83f464..e12624d8941d69cbc6bb35bb70d452d70642b428 100644 (file)
@@ -1,3 +1,6 @@
+#ifndef _ASM_PARISC_PARISC_DEVICE_H_
+#define _ASM_PARISC_PARISC_DEVICE_H_
+
 #include <linux/device.h>
 
 struct parisc_device {
@@ -57,3 +60,5 @@ parisc_get_drvdata(struct parisc_device *d)
 }
 
 extern struct bus_type parisc_bus_type;
+
+#endif /*_ASM_PARISC_PARISC_DEVICE_H_*/
index 8b631f47eb257b90a8a472bd8ed1cbf290d07631..7b8ad118d2feec1b9b307d442cbe666abdb2640e 100644 (file)
@@ -293,4 +293,9 @@ static inline void pcibios_penalize_isa_irq(int irq, int active)
        /* We don't need to penalize isa irq's */
 }
 
+static inline int pci_get_legacy_ide_irq(struct pci_dev *dev, int channel)
+{
+       return channel ? 15 : 14;
+}
+
 #endif /* __ASM_PARISC_PCI_H */
diff --git a/include/asm-parisc/prefetch.h b/include/asm-parisc/prefetch.h
new file mode 100644 (file)
index 0000000..5d02172
--- /dev/null
@@ -0,0 +1,39 @@
+/*
+ * include/asm-parisc/prefetch.h
+ *
+ * PA 2.0 defines data prefetch instructions on page 6-11 of the Kane book.
+ * In addition, many implementations do hardware prefetching of both
+ * instructions and data.
+ *
+ * PA7300LC (page 14-4 of the ERS) also implements prefetching by a load
+ * to gr0 but not in a way that Linux can use.  If the load would cause an
+ * interruption (eg due to prefetching 0), it is suppressed on PA2.0
+ * processors, but not on 7300LC.
+ *
+ */
+
+#ifndef __ASM_PARISC_PREFETCH_H
+#define __ASM_PARISC_PREFETCH_H
+
+#ifndef __ASSEMBLY__
+#ifdef CONFIG_PREFETCH
+
+#define ARCH_HAS_PREFETCH
+extern inline void prefetch(const void *addr)
+{
+       __asm__("ldw 0(%0), %%r0" : : "r" (addr));
+}
+
+/* LDD is a PA2.0 addition. */
+#ifdef CONFIG_PA20
+#define ARCH_HAS_PREFETCHW
+extern inline void prefetchw(const void *addr)
+{
+       __asm__("ldd 0(%0), %%r0" : : "r" (addr));
+}
+#endif /* CONFIG_PA20 */
+
+#endif /* CONFIG_PREFETCH */
+#endif /* __ASSEMBLY__ */
+
+#endif /* __ASM_PARISC_PROCESSOR_H */
index b73626f040dace5eb8d091636be645ed564864a0..fd7866dc8c83462b2d8a3274ac4118b5315de8d2 100644 (file)
@@ -9,6 +9,8 @@
 #define __ASM_PARISC_PROCESSOR_H
 
 #ifndef __ASSEMBLY__
+#include <asm/prefetch.h>      /* lockdep.h needs <linux/prefetch.h> */
+
 #include <linux/threads.h>
 #include <linux/spinlock_types.h>
 
@@ -276,7 +278,7 @@ on downward growing arches, it looks like this:
  */
 
 #ifdef __LP64__
-#define USER_WIDE_MODE (personality(current->personality) == PER_LINUX)
+#define USER_WIDE_MODE (!test_thread_flag(TIF_32BIT))
 #else
 #define USER_WIDE_MODE 0
 #endif
@@ -328,33 +330,20 @@ extern unsigned long get_wchan(struct task_struct *p);
 #define KSTK_EIP(tsk)  ((tsk)->thread.regs.iaoq[0])
 #define KSTK_ESP(tsk)  ((tsk)->thread.regs.gr[30])
 
+#define cpu_relax()    barrier()
 
-/*
- * PA 2.0 defines data prefetch instructions on page 6-11 of the Kane book.
- * In addition, many implementations do hardware prefetching of both
- * instructions and data.
- *
- * PA7300LC (page 14-4 of the ERS) also implements prefetching by a load
- * to gr0 but not in a way that Linux can use.  If the load would cause an
- * interruption (eg due to prefetching 0), it is suppressed on PA2.0
- * processors, but not on 7300LC.
- */
-#ifdef  CONFIG_PREFETCH
-#define ARCH_HAS_PREFETCH
-#define ARCH_HAS_PREFETCHW
-
-extern inline void prefetch(const void *addr)
-{
-       __asm__("ldw 0(%0), %%r0" : : "r" (addr));
-}
-
-extern inline void prefetchw(const void *addr)
+/* Used as a macro to identify the combined VIPT/PIPT cached
+ * CPUs which require a guarantee of coherency (no inequivalent
+ * aliases with different data, whether clean or not) to operate */
+static inline int parisc_requires_coherency(void)
 {
-       __asm__("ldd 0(%0), %%r0" : : "r" (addr));
-}
+#ifdef CONFIG_PA8X00
+       /* FIXME: also pa8900 - when we see one */
+       return boot_cpu_data.cpu_type == mako;
+#else
+       return 0;
 #endif
-
-#define cpu_relax()    barrier()
+}
 
 #endif /* __ASSEMBLY__ */
 
diff --git a/include/asm-parisc/ropes.h b/include/asm-parisc/ropes.h
new file mode 100644 (file)
index 0000000..5542dd0
--- /dev/null
@@ -0,0 +1,322 @@
+#ifndef _ASM_PARISC_ROPES_H_
+#define _ASM_PARISC_ROPES_H_
+
+#include <asm-parisc/parisc-device.h>
+
+#ifdef CONFIG_64BIT
+/* "low end" PA8800 machines use ZX1 chipset: PAT PDC and only run 64-bit */
+#define ZX1_SUPPORT
+#endif
+
+#ifdef CONFIG_PROC_FS
+/* depends on proc fs support. But costs CPU performance */
+#undef SBA_COLLECT_STATS
+#endif
+
+/*
+** The number of pdir entries to "free" before issueing
+** a read to PCOM register to flush out PCOM writes.
+** Interacts with allocation granularity (ie 4 or 8 entries
+** allocated and free'd/purged at a time might make this
+** less interesting).
+*/
+#define DELAYED_RESOURCE_CNT   16
+
+#define MAX_IOC                2       /* per Ike. Pluto/Astro only have 1. */
+#define ROPES_PER_IOC  8       /* per Ike half or Pluto/Astro */
+
+struct ioc {
+       void __iomem    *ioc_hpa;       /* I/O MMU base address */
+       char            *res_map;       /* resource map, bit == pdir entry */
+       u64             *pdir_base;     /* physical base address */
+       unsigned long   ibase;          /* pdir IOV Space base - shared w/lba_pci */
+       unsigned long   imask;          /* pdir IOV Space mask - shared w/lba_pci */
+#ifdef ZX1_SUPPORT
+       unsigned long   iovp_mask;      /* help convert IOVA to IOVP */
+#endif
+       unsigned long   *res_hint;      /* next avail IOVP - circular search */
+       spinlock_t      res_lock;
+       unsigned int    res_bitshift;   /* from the LEFT! */
+       unsigned int    res_size;       /* size of resource map in bytes */
+#ifdef SBA_HINT_SUPPORT
+/* FIXME : DMA HINTs not used */
+       unsigned long   hint_mask_pdir; /* bits used for DMA hints */
+       unsigned int    hint_shift_pdir;
+#endif
+#if DELAYED_RESOURCE_CNT > 0
+       int             saved_cnt;
+       struct sba_dma_pair {
+                       dma_addr_t      iova;
+                       size_t          size;
+        } saved[DELAYED_RESOURCE_CNT];
+#endif
+
+#ifdef SBA_COLLECT_STATS
+#define SBA_SEARCH_SAMPLE      0x100
+       unsigned long   avg_search[SBA_SEARCH_SAMPLE];
+       unsigned long   avg_idx;        /* current index into avg_search */
+       unsigned long   used_pages;
+       unsigned long   msingle_calls;
+       unsigned long   msingle_pages;
+       unsigned long   msg_calls;
+       unsigned long   msg_pages;
+       unsigned long   usingle_calls;
+       unsigned long   usingle_pages;
+       unsigned long   usg_calls;
+       unsigned long   usg_pages;
+#endif
+        /* STUFF We don't need in performance path */
+       unsigned int    pdir_size;      /* in bytes, determined by IOV Space size */
+};
+
+struct sba_device {
+       struct sba_device       *next;  /* list of SBA's in system */
+       struct parisc_device    *dev;   /* dev found in bus walk */
+       const char              *name;
+       void __iomem            *sba_hpa; /* base address */
+       spinlock_t              sba_lock;
+       unsigned int            flags;  /* state/functionality enabled */
+       unsigned int            hw_rev;  /* HW revision of chip */
+
+       struct resource         chip_resv; /* MMIO reserved for chip */
+       struct resource         iommu_resv; /* MMIO reserved for iommu */
+
+       unsigned int            num_ioc;  /* number of on-board IOC's */
+       struct ioc              ioc[MAX_IOC];
+};
+
+#define ASTRO_RUNWAY_PORT      0x582
+#define IKE_MERCED_PORT                0x803
+#define REO_MERCED_PORT                0x804
+#define REOG_MERCED_PORT       0x805
+#define PLUTO_MCKINLEY_PORT    0x880
+
+static inline int IS_ASTRO(struct parisc_device *d) {
+       return d->id.hversion == ASTRO_RUNWAY_PORT;
+}
+
+static inline int IS_IKE(struct parisc_device *d) {
+       return d->id.hversion == IKE_MERCED_PORT;
+}
+
+static inline int IS_PLUTO(struct parisc_device *d) {
+       return d->id.hversion == PLUTO_MCKINLEY_PORT;
+}
+
+#define PLUTO_IOVA_BASE        (1UL*1024*1024*1024)    /* 1GB */
+#define PLUTO_IOVA_SIZE        (1UL*1024*1024*1024)    /* 1GB */
+#define PLUTO_GART_SIZE        (PLUTO_IOVA_SIZE / 2)
+
+#define SBA_PDIR_VALID_BIT     0x8000000000000000ULL
+
+#define SBA_AGPGART_COOKIE     0x0000badbadc0ffeeULL
+
+#define SBA_FUNC_ID    0x0000  /* function id */
+#define SBA_FCLASS     0x0008  /* function class, bist, header, rev... */
+
+#define SBA_FUNC_SIZE 4096   /* SBA configuration function reg set */
+
+#define ASTRO_IOC_OFFSET       (32 * SBA_FUNC_SIZE)
+#define PLUTO_IOC_OFFSET       (1 * SBA_FUNC_SIZE)
+/* Ike's IOC's occupy functions 2 and 3 */
+#define IKE_IOC_OFFSET(p)      ((p+2) * SBA_FUNC_SIZE)
+
+#define IOC_CTRL          0x8  /* IOC_CTRL offset */
+#define IOC_CTRL_TC       (1 << 0) /* TOC Enable */
+#define IOC_CTRL_CE       (1 << 1) /* Coalesce Enable */
+#define IOC_CTRL_DE       (1 << 2) /* Dillon Enable */
+#define IOC_CTRL_RM       (1 << 8) /* Real Mode */
+#define IOC_CTRL_NC       (1 << 9) /* Non Coherent Mode */
+#define IOC_CTRL_D4       (1 << 11) /* Disable 4-byte coalescing */
+#define IOC_CTRL_DD       (1 << 13) /* Disable distr. LMMIO range coalescing */
+
+/*
+** Offsets into MBIB (Function 0 on Ike and hopefully Astro)
+** Firmware programs this stuff. Don't touch it.
+*/
+#define LMMIO_DIRECT0_BASE  0x300
+#define LMMIO_DIRECT0_MASK  0x308
+#define LMMIO_DIRECT0_ROUTE 0x310
+
+#define LMMIO_DIST_BASE  0x360
+#define LMMIO_DIST_MASK  0x368
+#define LMMIO_DIST_ROUTE 0x370
+
+#define IOS_DIST_BASE  0x390
+#define IOS_DIST_MASK  0x398
+#define IOS_DIST_ROUTE 0x3A0
+
+#define IOS_DIRECT_BASE        0x3C0
+#define IOS_DIRECT_MASK        0x3C8
+#define IOS_DIRECT_ROUTE 0x3D0
+
+/*
+** Offsets into I/O TLB (Function 2 and 3 on Ike)
+*/
+#define ROPE0_CTL      0x200  /* "regbus pci0" */
+#define ROPE1_CTL      0x208
+#define ROPE2_CTL      0x210
+#define ROPE3_CTL      0x218
+#define ROPE4_CTL      0x220
+#define ROPE5_CTL      0x228
+#define ROPE6_CTL      0x230
+#define ROPE7_CTL      0x238
+
+#define IOC_ROPE0_CFG  0x500   /* pluto only */
+#define   IOC_ROPE_AO    0x10  /* Allow "Relaxed Ordering" */
+
+#define HF_ENABLE      0x40
+
+#define IOC_IBASE      0x300   /* IO TLB */
+#define IOC_IMASK      0x308
+#define IOC_PCOM       0x310
+#define IOC_TCNFG      0x318
+#define IOC_PDIR_BASE  0x320
+
+/*
+** IOC supports 4/8/16/64KB page sizes (see TCNFG register)
+** It's safer (avoid memory corruption) to keep DMA page mappings
+** equivalently sized to VM PAGE_SIZE.
+**
+** We really can't avoid generating a new mapping for each
+** page since the Virtual Coherence Index has to be generated
+** and updated for each page.
+**
+** PAGE_SIZE could be greater than IOVP_SIZE. But not the inverse.
+*/
+#define IOVP_SIZE      PAGE_SIZE
+#define IOVP_SHIFT     PAGE_SHIFT
+#define IOVP_MASK      PAGE_MASK
+
+#define SBA_PERF_CFG   0x708   /* Performance Counter stuff */
+#define SBA_PERF_MASK1 0x718
+#define SBA_PERF_MASK2 0x730
+
+/*
+** Offsets into PCI Performance Counters (functions 12 and 13)
+** Controlled by PERF registers in function 2 & 3 respectively.
+*/
+#define SBA_PERF_CNT1  0x200
+#define SBA_PERF_CNT2  0x208
+#define SBA_PERF_CNT3  0x210
+
+/*
+** lba_device: Per instance Elroy data structure
+*/
+struct lba_device {
+       struct pci_hba_data     hba;
+
+       spinlock_t              lba_lock;
+       void                    *iosapic_obj;
+
+#ifdef CONFIG_64BIT
+       void __iomem            *iop_base;      /* PA_VIEW - for IO port accessor funcs */
+#endif
+
+       int                     flags;          /* state/functionality enabled */
+       int                     hw_rev;         /* HW revision of chip */
+};
+
+#define ELROY_HVERS            0x782
+#define MERCURY_HVERS          0x783
+#define QUICKSILVER_HVERS      0x784
+
+static inline int IS_ELROY(struct parisc_device *d) {
+       return (d->id.hversion == ELROY_HVERS);
+}
+
+static inline int IS_MERCURY(struct parisc_device *d) {
+       return (d->id.hversion == MERCURY_HVERS);
+}
+
+static inline int IS_QUICKSILVER(struct parisc_device *d) {
+       return (d->id.hversion == QUICKSILVER_HVERS);
+}
+
+static inline int agp_mode_mercury(void __iomem *hpa) {
+       u64 bus_mode;
+
+       bus_mode = readl(hpa + 0x0620);
+       if (bus_mode & 1)
+               return 1;
+
+       return 0;
+}
+
+/*
+** I/O SAPIC init function
+** Caller knows where an I/O SAPIC is. LBA has an integrated I/O SAPIC.
+** Call setup as part of per instance initialization.
+** (ie *not* init_module() function unless only one is present.)
+** fixup_irq is to initialize PCI IRQ line support and
+** virtualize pcidev->irq value. To be called by pci_fixup_bus().
+*/
+extern void *iosapic_register(unsigned long hpa);
+extern int iosapic_fixup_irq(void *obj, struct pci_dev *pcidev);
+
+#define LBA_FUNC_ID    0x0000  /* function id */
+#define LBA_FCLASS     0x0008  /* function class, bist, header, rev... */
+#define LBA_CAPABLE    0x0030  /* capabilities register */
+
+#define LBA_PCI_CFG_ADDR       0x0040  /* poke CFG address here */
+#define LBA_PCI_CFG_DATA       0x0048  /* read or write data here */
+
+#define LBA_PMC_MTLT   0x0050  /* Firmware sets this - read only. */
+#define LBA_FW_SCRATCH 0x0058  /* Firmware writes the PCI bus number here. */
+#define LBA_ERROR_ADDR 0x0070  /* On error, address gets logged here */
+
+#define LBA_ARB_MASK   0x0080  /* bit 0 enable arbitration. PAT/PDC enables */
+#define LBA_ARB_PRI    0x0088  /* firmware sets this. */
+#define LBA_ARB_MODE   0x0090  /* firmware sets this. */
+#define LBA_ARB_MTLT   0x0098  /* firmware sets this. */
+
+#define LBA_MOD_ID     0x0100  /* Module ID. PDC_PAT_CELL reports 4 */
+
+#define LBA_STAT_CTL   0x0108  /* Status & Control */
+#define   LBA_BUS_RESET                0x01    /*  Deassert PCI Bus Reset Signal */
+#define   CLEAR_ERRLOG         0x10    /*  "Clear Error Log" cmd */
+#define   CLEAR_ERRLOG_ENABLE  0x20    /*  "Clear Error Log" Enable */
+#define   HF_ENABLE    0x40    /*    enable HF mode (default is -1 mode) */
+
+#define LBA_LMMIO_BASE 0x0200  /* < 4GB I/O address range */
+#define LBA_LMMIO_MASK 0x0208
+
+#define LBA_GMMIO_BASE 0x0210  /* > 4GB I/O address range */
+#define LBA_GMMIO_MASK 0x0218
+
+#define LBA_WLMMIO_BASE        0x0220  /* All < 4GB ranges under the same *SBA* */
+#define LBA_WLMMIO_MASK        0x0228
+
+#define LBA_WGMMIO_BASE        0x0230  /* All > 4GB ranges under the same *SBA* */
+#define LBA_WGMMIO_MASK        0x0238
+
+#define LBA_IOS_BASE   0x0240  /* I/O port space for this LBA */
+#define LBA_IOS_MASK   0x0248
+
+#define LBA_ELMMIO_BASE        0x0250  /* Extra LMMIO range */
+#define LBA_ELMMIO_MASK        0x0258
+
+#define LBA_EIOS_BASE  0x0260  /* Extra I/O port space */
+#define LBA_EIOS_MASK  0x0268
+
+#define LBA_GLOBAL_MASK        0x0270  /* Mercury only: Global Address Mask */
+#define LBA_DMA_CTL    0x0278  /* firmware sets this */
+
+#define LBA_IBASE      0x0300  /* SBA DMA support */
+#define LBA_IMASK      0x0308
+
+/* FIXME: ignore DMA Hint stuff until we can measure performance */
+#define LBA_HINT_CFG   0x0310
+#define LBA_HINT_BASE  0x0380  /* 14 registers at every 8 bytes. */
+
+#define LBA_BUS_MODE   0x0620
+
+/* ERROR regs are needed for config cycle kluges */
+#define LBA_ERROR_CONFIG 0x0680
+#define     LBA_SMART_MODE 0x20
+#define LBA_ERROR_STATUS 0x0688
+#define LBA_ROPE_CTL     0x06A0
+
+#define LBA_IOSAPIC_BASE       0x800 /* Offset of IRQ logic */
+
+#endif /*_ASM_PARISC_ROPES_H_*/
index 82fd820d684f090137e5a6c53d7c1adfb7fea263..d7e3cc60dbc3693a3b8ce475fbd128bb9563a284 100644 (file)
@@ -3,20 +3,8 @@
  */
 
 /*
- * This assumes you have a 7.272727 MHz clock for your UART.
- * The documentation implies a 40Mhz clock, and elsewhere a 7Mhz clock
- * Clarified: 7.2727MHz on LASI. Not yet clarified for DINO
+ * This is used for 16550-compatible UARTs
  */
+#define BASE_BAUD ( 1843200 / 16 )
 
-#define LASI_BASE_BAUD ( 7272727 / 16 )
-#define BASE_BAUD  LASI_BASE_BAUD
-
-/*
- * We don't use the ISA probing code, so these entries are just to reserve
- * space.  Some example (maximal) configurations:
- * - 712 w/ additional Lasi & RJ16 ports: 4
- * - J5k w/ PCI serial cards: 2 + 4 * card ~= 34
- * A500 w/ PCI serial cards: 5 + 4 * card ~= 17
- */
 #define SERIAL_PORT_DFNS
index e1825530365d3d1724b925fabb54a125429cd564..f3d2090a18dc316e5a4cbd388abb32e94717b764 100644 (file)
@@ -56,50 +56,79 @@ static inline int __raw_spin_trylock(raw_spinlock_t *x)
 }
 
 /*
- * Read-write spinlocks, allowing multiple readers
- * but only one writer.
+ * Read-write spinlocks, allowing multiple readers but only one writer.
+ * Linux rwlocks are unfair to writers; they can be starved for an indefinite
+ * time by readers.  With care, they can also be taken in interrupt context.
+ *
+ * In the PA-RISC implementation, we have a spinlock and a counter.
+ * Readers use the lock to serialise their access to the counter (which
+ * records how many readers currently hold the lock).
+ * Writers hold the spinlock, preventing any readers or other writers from
+ * grabbing the rwlock.
  */
 
-#define __raw_read_trylock(lock) generic__raw_read_trylock(lock)
-
-/* read_lock, read_unlock are pretty straightforward.  Of course it somehow
- * sucks we end up saving/restoring flags twice for read_lock_irqsave aso. */
-
+/* Note that we have to ensure interrupts are disabled in case we're
+ * interrupted by some other code that wants to grab the same read lock */
 static  __inline__ void __raw_read_lock(raw_rwlock_t *rw)
 {
-       __raw_spin_lock(&rw->lock);
-
+       unsigned long flags;
+       local_irq_save(flags);
+       __raw_spin_lock_flags(&rw->lock, flags);
        rw->counter++;
-
        __raw_spin_unlock(&rw->lock);
+       local_irq_restore(flags);
 }
 
+/* Note that we have to ensure interrupts are disabled in case we're
+ * interrupted by some other code that wants to grab the same read lock */
 static  __inline__ void __raw_read_unlock(raw_rwlock_t *rw)
 {
-       __raw_spin_lock(&rw->lock);
-
+       unsigned long flags;
+       local_irq_save(flags);
+       __raw_spin_lock_flags(&rw->lock, flags);
        rw->counter--;
-
        __raw_spin_unlock(&rw->lock);
+       local_irq_restore(flags);
 }
 
-/* write_lock is less trivial.  We optimistically grab the lock and check
- * if we surprised any readers.  If so we release the lock and wait till
- * they're all gone before trying again
- *
- * Also note that we don't use the _irqsave / _irqrestore suffixes here.
- * If we're called with interrupts enabled and we've got readers (or other
- * writers) in interrupt handlers someone fucked up and we'd dead-lock
- * sooner or later anyway.   prumpf */
+/* Note that we have to ensure interrupts are disabled in case we're
+ * interrupted by some other code that wants to grab the same read lock */
+static __inline__ int __raw_read_trylock(raw_rwlock_t *rw)
+{
+       unsigned long flags;
+ retry:
+       local_irq_save(flags);
+       if (__raw_spin_trylock(&rw->lock)) {
+               rw->counter++;
+               __raw_spin_unlock(&rw->lock);
+               local_irq_restore(flags);
+               return 1;
+       }
 
-static  __inline__ void __raw_write_lock(raw_rwlock_t *rw)
+       local_irq_restore(flags);
+       /* If write-locked, we fail to acquire the lock */
+       if (rw->counter < 0)
+               return 0;
+
+       /* Wait until we have a realistic chance at the lock */
+       while (__raw_spin_is_locked(&rw->lock) && rw->counter >= 0)
+               cpu_relax();
+
+       goto retry;
+}
+
+/* Note that we have to ensure interrupts are disabled in case we're
+ * interrupted by some other code that wants to read_trylock() this lock */
+static __inline__ void __raw_write_lock(raw_rwlock_t *rw)
 {
+       unsigned long flags;
 retry:
-       __raw_spin_lock(&rw->lock);
+       local_irq_save(flags);
+       __raw_spin_lock_flags(&rw->lock, flags);
 
-       if(rw->counter != 0) {
-               /* this basically never happens */
+       if (rw->counter != 0) {
                __raw_spin_unlock(&rw->lock);
+               local_irq_restore(flags);
 
                while (rw->counter != 0)
                        cpu_relax();
@@ -107,31 +136,37 @@ retry:
                goto retry;
        }
 
-       /* got it.  now leave without unlocking */
-       rw->counter = -1; /* remember we are locked */
+       rw->counter = -1; /* mark as write-locked */
+       mb();
+       local_irq_restore(flags);
 }
 
-/* write_unlock is absolutely trivial - we don't have to wait for anything */
-
-static  __inline__ void __raw_write_unlock(raw_rwlock_t *rw)
+static __inline__ void __raw_write_unlock(raw_rwlock_t *rw)
 {
        rw->counter = 0;
        __raw_spin_unlock(&rw->lock);
 }
 
-static  __inline__ int __raw_write_trylock(raw_rwlock_t *rw)
+/* Note that we have to ensure interrupts are disabled in case we're
+ * interrupted by some other code that wants to read_trylock() this lock */
+static __inline__ int __raw_write_trylock(raw_rwlock_t *rw)
 {
-       __raw_spin_lock(&rw->lock);
-       if (rw->counter != 0) {
-               /* this basically never happens */
-               __raw_spin_unlock(&rw->lock);
-
-               return 0;
+       unsigned long flags;
+       int result = 0;
+
+       local_irq_save(flags);
+       if (__raw_spin_trylock(&rw->lock)) {
+               if (rw->counter == 0) {
+                       rw->counter = -1;
+                       result = 1;
+               } else {
+                       /* Read-locked.  Oh well. */
+                       __raw_spin_unlock(&rw->lock);
+               }
        }
+       local_irq_restore(flags);
 
-       /* got it.  now leave without unlocking */
-       rw->counter = -1; /* remember we are locked */
-       return 1;
+       return result;
 }
 
 /*
index 88dafa246d87a968b61163ad500dd7da2d5bb812..952bee79a8f30902328277a6d16920a53e4da12f 100644 (file)
@@ -43,6 +43,8 @@ extern int debug_locks_off(void);
 # define locking_selftest()    do { } while (0)
 #endif
 
+struct task_struct;
+
 #ifdef CONFIG_LOCKDEP
 extern void debug_show_all_locks(void);
 extern void debug_show_held_locks(struct task_struct *task);