|
@@ -514,3 +514,110 @@ t2_pci_tbi(struct pci_controller *hose, dma_addr_t start, dma_addr_t end)
|
|
|
*(vulp)T2_IOCSR; /* read it back to make sure */
|
|
|
|
|
|
/* clear the TLB Clear bit */
|
|
|
+ *(vulp)T2_IOCSR = t2_iocsr & ~(0x1UL << 28);
|
|
|
+ mb();
|
|
|
+ *(vulp)T2_IOCSR; /* read it back to make sure */
|
|
|
+}
|
|
|
+
|
|
|
+#define SIC_SEIC (1UL << 33) /* System Event Clear */
|
|
|
+
|
|
|
+static void
|
|
|
+t2_clear_errors(int cpu)
|
|
|
+{
|
|
|
+ struct sable_cpu_csr *cpu_regs;
|
|
|
+
|
|
|
+ cpu_regs = (struct sable_cpu_csr *)T2_CPUn_BASE(cpu);
|
|
|
+
|
|
|
+ cpu_regs->sic &= ~SIC_SEIC;
|
|
|
+
|
|
|
+ /* Clear CPU errors. */
|
|
|
+ cpu_regs->bcce |= cpu_regs->bcce;
|
|
|
+ cpu_regs->cbe |= cpu_regs->cbe;
|
|
|
+ cpu_regs->bcue |= cpu_regs->bcue;
|
|
|
+ cpu_regs->dter |= cpu_regs->dter;
|
|
|
+
|
|
|
+ *(vulp)T2_CERR1 |= *(vulp)T2_CERR1;
|
|
|
+ *(vulp)T2_PERR1 |= *(vulp)T2_PERR1;
|
|
|
+
|
|
|
+ mb();
|
|
|
+ mb(); /* magic */
|
|
|
+}
|
|
|
+
|
|
|
+/*
|
|
|
+ * SABLE seems to have a "broadcast" style machine check, in that all
|
|
|
+ * CPUs receive it. And, the issuing CPU, in the case of PCI Config
|
|
|
+ * space read/write faults, will also receive a second mcheck, upon
|
|
|
+ * lowering IPL during completion processing in pci_read_config_byte()
|
|
|
+ * et al.
|
|
|
+ *
|
|
|
+ * Hence all the taken/expected/any_expected/last_taken stuff...
|
|
|
+ */
|
|
|
+void
|
|
|
+t2_machine_check(unsigned long vector, unsigned long la_ptr)
|
|
|
+{
|
|
|
+ int cpu = smp_processor_id();
|
|
|
+#ifdef CONFIG_VERBOSE_MCHECK
|
|
|
+ struct el_common *mchk_header = (struct el_common *)la_ptr;
|
|
|
+#endif
|
|
|
+
|
|
|
+ /* Clear the error before any reporting. */
|
|
|
+ mb();
|
|
|
+ mb(); /* magic */
|
|
|
+ draina();
|
|
|
+ t2_clear_errors(cpu);
|
|
|
+
|
|
|
+ /* This should not actually be done until the logout frame is
|
|
|
+ examined, but, since we don't do that, go on and do this... */
|
|
|
+ wrmces(0x7);
|
|
|
+ mb();
|
|
|
+
|
|
|
+ /* Now, do testing for the anomalous conditions. */
|
|
|
+ if (!mcheck_expected(cpu) && t2_mcheck_any_expected) {
|
|
|
+ /*
|
|
|
+ * FUNKY: Received mcheck on a CPU and not
|
|
|
+ * expecting it, but another CPU is expecting one.
|
|
|
+ *
|
|
|
+ * Just dismiss it for now on this CPU...
|
|
|
+ */
|
|
|
+#ifdef CONFIG_VERBOSE_MCHECK
|
|
|
+ if (alpha_verbose_mcheck > 1) {
|
|
|
+ printk("t2_machine_check(cpu%d): any_expected 0x%x -"
|
|
|
+ " (assumed) spurious -"
|
|
|
+ " code 0x%x\n", cpu, t2_mcheck_any_expected,
|
|
|
+ (unsigned int)mchk_header->code);
|
|
|
+ }
|
|
|
+#endif
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!mcheck_expected(cpu) && !t2_mcheck_any_expected) {
|
|
|
+ if (t2_mcheck_last_taken & (1 << cpu)) {
|
|
|
+#ifdef CONFIG_VERBOSE_MCHECK
|
|
|
+ if (alpha_verbose_mcheck > 1) {
|
|
|
+ printk("t2_machine_check(cpu%d): last_taken 0x%x - "
|
|
|
+ "unexpected mcheck - code 0x%x\n",
|
|
|
+ cpu, t2_mcheck_last_taken,
|
|
|
+ (unsigned int)mchk_header->code);
|
|
|
+ }
|
|
|
+#endif
|
|
|
+ t2_mcheck_last_taken = 0;
|
|
|
+ mb();
|
|
|
+ return;
|
|
|
+ } else {
|
|
|
+ t2_mcheck_last_taken = 0;
|
|
|
+ mb();
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+#ifdef CONFIG_VERBOSE_MCHECK
|
|
|
+ if (alpha_verbose_mcheck > 1) {
|
|
|
+ printk("%s t2_mcheck(cpu%d): last_taken 0x%x - "
|
|
|
+ "any_expected 0x%x - code 0x%x\n",
|
|
|
+ (mcheck_expected(cpu) ? "EX" : "UN"), cpu,
|
|
|
+ t2_mcheck_last_taken, t2_mcheck_any_expected,
|
|
|
+ (unsigned int)mchk_header->code);
|
|
|
+ }
|
|
|
+#endif
|
|
|
+
|
|
|
+ process_mcheck_info(vector, la_ptr, "T2", mcheck_expected(cpu));
|
|
|
+}
|