|
@@ -998,3 +998,163 @@ marvel_process_io_error(struct ev7_lf_subpackets *lf_subpackets, int print)
|
|
marvel_print_pox_err(io->ports[i].pox_first_err,
|
|
marvel_print_pox_err(io->ports[i].pox_first_err,
|
|
&io->ports[i]);
|
|
&io->ports[i]);
|
|
|
|
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+#endif /* CONFIG_VERBOSE_MCHECK */
|
|
|
|
+
|
|
|
|
+ return status;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static int
|
|
|
|
+marvel_process_logout_frame(struct ev7_lf_subpackets *lf_subpackets, int print)
|
|
|
|
+{
|
|
|
|
+ int status = MCHK_DISPOSITION_UNKNOWN_ERROR;
|
|
|
|
+
|
|
|
|
+ /*
|
|
|
|
+ * I/O error?
|
|
|
|
+ */
|
|
|
|
+#define EV7__RBOX_INT__IO_ERROR__MASK 0x20000400ul
|
|
|
|
+ if (lf_subpackets->logout &&
|
|
|
|
+ (lf_subpackets->logout->rbox_int & 0x20000400ul))
|
|
|
|
+ status = marvel_process_io_error(lf_subpackets, print);
|
|
|
|
+
|
|
|
|
+ /*
|
|
|
|
+ * Probing behind PCI-X bridges can cause machine checks on
|
|
|
|
+ * Marvel when the probe is handled by the bridge as a split
|
|
|
|
+ * completion transaction. The symptom is an ERROR_RESPONSE
|
|
|
|
+ * to a CONFIG address. Since these errors will happen in
|
|
|
|
+ * normal operation, dismiss them.
|
|
|
|
+ *
|
|
|
|
+ * Dismiss if:
|
|
|
|
+ * C_STAT = 0x14 (Error Response)
|
|
|
|
+ * C_STS<3> = 0 (C_ADDR valid)
|
|
|
|
+ * C_ADDR<42> = 1 (I/O)
|
|
|
|
+ * C_ADDR<31:22> = 111110xxb (PCI Config space)
|
|
|
|
+ */
|
|
|
|
+ if (lf_subpackets->ev7 &&
|
|
|
|
+ (lf_subpackets->ev7->c_stat == 0x14) &&
|
|
|
|
+ !(lf_subpackets->ev7->c_sts & 0x8) &&
|
|
|
|
+ ((lf_subpackets->ev7->c_addr & 0x400ff000000ul)
|
|
|
|
+ == 0x400fe000000ul))
|
|
|
|
+ status = MCHK_DISPOSITION_DISMISS;
|
|
|
|
+
|
|
|
|
+ return status;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+void
|
|
|
|
+marvel_machine_check(unsigned long vector, unsigned long la_ptr)
|
|
|
|
+{
|
|
|
|
+ struct el_subpacket *el_ptr = (struct el_subpacket *)la_ptr;
|
|
|
|
+ int (*process_frame)(struct ev7_lf_subpackets *, int) = NULL;
|
|
|
|
+ struct ev7_lf_subpackets subpacket_collection = { NULL, };
|
|
|
|
+ struct ev7_pal_io_subpacket scratch_io_packet = { 0, };
|
|
|
|
+ struct ev7_lf_subpackets *lf_subpackets = NULL;
|
|
|
|
+ int disposition = MCHK_DISPOSITION_UNKNOWN_ERROR;
|
|
|
|
+ char *saved_err_prefix = err_print_prefix;
|
|
|
|
+ char *error_type = NULL;
|
|
|
|
+
|
|
|
|
+ /*
|
|
|
|
+ * Sync the processor
|
|
|
|
+ */
|
|
|
|
+ mb();
|
|
|
|
+ draina();
|
|
|
|
+
|
|
|
|
+ switch(vector) {
|
|
|
|
+ case SCB_Q_SYSEVENT:
|
|
|
|
+ process_frame = marvel_process_680_frame;
|
|
|
|
+ error_type = "System Event";
|
|
|
|
+ break;
|
|
|
|
+
|
|
|
|
+ case SCB_Q_SYSMCHK:
|
|
|
|
+ process_frame = marvel_process_logout_frame;
|
|
|
|
+ error_type = "System Uncorrectable Error";
|
|
|
|
+ break;
|
|
|
|
+
|
|
|
|
+ case SCB_Q_SYSERR:
|
|
|
|
+ process_frame = marvel_process_logout_frame;
|
|
|
|
+ error_type = "System Correctable Error";
|
|
|
|
+ break;
|
|
|
|
+
|
|
|
|
+ default:
|
|
|
|
+ /* Don't know it - pass it up. */
|
|
|
|
+ ev7_machine_check(vector, la_ptr);
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /*
|
|
|
|
+ * A system event or error has occurred, handle it here.
|
|
|
|
+ *
|
|
|
|
+ * Any errors in the logout frame have already been cleared by the
|
|
|
|
+ * PALcode, so just parse it.
|
|
|
|
+ */
|
|
|
|
+ err_print_prefix = KERN_CRIT;
|
|
|
|
+
|
|
|
|
+ /*
|
|
|
|
+ * Parse the logout frame without printing first. If the only error(s)
|
|
|
|
+ * found are classified as "dismissable", then just dismiss them and
|
|
|
|
+ * don't print any message
|
|
|
|
+ */
|
|
|
|
+ lf_subpackets =
|
|
|
|
+ ev7_collect_logout_frame_subpackets(el_ptr,
|
|
|
|
+ &subpacket_collection);
|
|
|
|
+ if (process_frame && lf_subpackets && lf_subpackets->logout) {
|
|
|
|
+ /*
|
|
|
|
+ * We might not have the correct (or any) I/O subpacket.
|
|
|
|
+ * [ See marvel_process_io_error() for explanation. ]
|
|
|
|
+ * If we don't have one, point the io subpacket in
|
|
|
|
+ * lf_subpackets at scratch_io_packet so that
|
|
|
|
+ * marvel_find_io7_with_error() will have someplace to
|
|
|
|
+ * store the info.
|
|
|
|
+ */
|
|
|
|
+ if (!lf_subpackets->io)
|
|
|
|
+ lf_subpackets->io = &scratch_io_packet;
|
|
|
|
+
|
|
|
|
+ /*
|
|
|
|
+ * Default io_pid to the processor reporting the error
|
|
|
|
+ * [this will get changed in marvel_find_io7_with_error()
|
|
|
|
+ * if a different one is needed]
|
|
|
|
+ */
|
|
|
|
+ lf_subpackets->io_pid = lf_subpackets->logout->whami;
|
|
|
|
+
|
|
|
|
+ /*
|
|
|
|
+ * Evaluate the frames.
|
|
|
|
+ */
|
|
|
|
+ disposition = process_frame(lf_subpackets, 0);
|
|
|
|
+ }
|
|
|
|
+ switch(disposition) {
|
|
|
|
+ case MCHK_DISPOSITION_DISMISS:
|
|
|
|
+ /* Nothing to do. */
|
|
|
|
+ break;
|
|
|
|
+
|
|
|
|
+ case MCHK_DISPOSITION_REPORT:
|
|
|
|
+ /* Recognized error, report it. */
|
|
|
|
+ printk("%s*%s (Vector 0x%x) reported on CPU %d\n",
|
|
|
|
+ err_print_prefix, error_type,
|
|
|
|
+ (unsigned int)vector, (int)smp_processor_id());
|
|
|
|
+ el_print_timestamp(&lf_subpackets->logout->timestamp);
|
|
|
|
+ process_frame(lf_subpackets, 1);
|
|
|
|
+ break;
|
|
|
|
+
|
|
|
|
+ default:
|
|
|
|
+ /* Unknown - dump the annotated subpackets. */
|
|
|
|
+ printk("%s*%s (Vector 0x%x) reported on CPU %d\n",
|
|
|
|
+ err_print_prefix, error_type,
|
|
|
|
+ (unsigned int)vector, (int)smp_processor_id());
|
|
|
|
+ el_process_subpacket(el_ptr);
|
|
|
|
+ break;
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ err_print_prefix = saved_err_prefix;
|
|
|
|
+
|
|
|
|
+ /* Release the logout frame. */
|
|
|
|
+ wrmces(0x7);
|
|
|
|
+ mb();
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+void __init
|
|
|
|
+marvel_register_error_handlers(void)
|
|
|
|
+{
|
|
|
|
+ ev7_register_error_handlers();
|
|
|
|
+}
|