]> bbs.cooldavid.org Git - net-next-2.6.git/blobdiff - arch/ia64/kernel/mca.c
Pull miscellaneous into release branch
[net-next-2.6.git] / arch / ia64 / kernel / mca.c
index 1ae512910870da963c3cfe6fe9695dd443bf821d..e51bced3b0fad2b6bbbb050cc0ac828ba6b68c15 100644 (file)
@@ -98,6 +98,7 @@
 
 #include <asm/irq.h>
 #include <asm/hw_irq.h>
+#include <asm/tlb.h>
 
 #include "mca_drv.h"
 #include "entry.h"
@@ -113,6 +114,7 @@ DEFINE_PER_CPU(u64, ia64_mca_data); /* == __per_cpu_mca[smp_processor_id()] */
 DEFINE_PER_CPU(u64, ia64_mca_per_cpu_pte); /* PTE to map per-CPU area */
 DEFINE_PER_CPU(u64, ia64_mca_pal_pte);     /* PTE to map PAL code */
 DEFINE_PER_CPU(u64, ia64_mca_pal_base);    /* vaddr PAL code granule */
+DEFINE_PER_CPU(u64, ia64_mca_tr_reload);   /* Flag for TR reload */
 
 unsigned long __per_cpu_mca[NR_CPUS];
 
@@ -1184,6 +1186,49 @@ all_in:
        return;
 }
 
+/*  mca_insert_tr
+ *
+ *  Switch rid when TR reload and needed!
+ *  iord: 1: itr, 2: itr;
+ *
+*/
+static void mca_insert_tr(u64 iord)
+{
+
+       int i;
+       u64 old_rr;
+       struct ia64_tr_entry *p;
+       unsigned long psr;
+       int cpu = smp_processor_id();
+
+       psr = ia64_clear_ic();
+       for (i = IA64_TR_ALLOC_BASE; i < IA64_TR_ALLOC_MAX; i++) {
+               p = &__per_cpu_idtrs[cpu][iord-1][i];
+               if (p->pte & 0x1) {
+                       old_rr = ia64_get_rr(p->ifa);
+                       if (old_rr != p->rr) {
+                               ia64_set_rr(p->ifa, p->rr);
+                               ia64_srlz_d();
+                       }
+                       ia64_ptr(iord, p->ifa, p->itir >> 2);
+                       ia64_srlz_i();
+                       if (iord & 0x1) {
+                               ia64_itr(0x1, i, p->ifa, p->pte, p->itir >> 2);
+                               ia64_srlz_i();
+                       }
+                       if (iord & 0x2) {
+                               ia64_itr(0x2, i, p->ifa, p->pte, p->itir >> 2);
+                               ia64_srlz_i();
+                       }
+                       if (old_rr != p->rr) {
+                               ia64_set_rr(p->ifa, old_rr);
+                               ia64_srlz_d();
+                       }
+               }
+       }
+       ia64_set_psr(psr);
+}
+
 /*
  * ia64_mca_handler
  *
@@ -1270,6 +1315,11 @@ ia64_mca_handler(struct pt_regs *regs, struct switch_stack *sw,
                ia64_mlogbuf_finish(1);
        }
 
+       if (__get_cpu_var(ia64_mca_tr_reload)) {
+               mca_insert_tr(0x1); /*Reload dynamic itrs*/
+               mca_insert_tr(0x2); /*Reload dynamic itrs*/
+       }
+
        if (notify_die(DIE_MCA_MONARCH_LEAVE, "MCA", regs, (long)&nd, 0, recover)
                        == NOTIFY_STOP)
                ia64_mca_spin(__func__);