void octeon_wdt_nmi_stage3()

in octeon-wdt-main.c [210:300]


void octeon_wdt_nmi_stage3(u64 reg[32])
{
	u64 i;

	unsigned int coreid = cvmx_get_core_num();
	/*
	 * Save status and cause early to get them before any changes
	 * might happen.
	 */
	u64 cp0_cause = read_c0_cause();
	u64 cp0_status = read_c0_status();
	u64 cp0_error_epc = read_c0_errorepc();
	u64 cp0_epc = read_c0_epc();

	/* Delay so output from all cores output is not jumbled together. */
	udelay(85000 * coreid);

	octeon_wdt_write_string("\r\n*** NMI Watchdog interrupt on Core 0x");
	octeon_wdt_write_hex(coreid, 2);
	octeon_wdt_write_string(" ***\r\n");
	for (i = 0; i < 32; i++) {
		octeon_wdt_write_string("\t");
		octeon_wdt_write_string(reg_name[i]);
		octeon_wdt_write_string("\t0x");
		octeon_wdt_write_hex(reg[i], 16);
		if (i & 1)
			octeon_wdt_write_string("\r\n");
	}
	octeon_wdt_write_string("\terr_epc\t0x");
	octeon_wdt_write_hex(cp0_error_epc, 16);

	octeon_wdt_write_string("\tepc\t0x");
	octeon_wdt_write_hex(cp0_epc, 16);
	octeon_wdt_write_string("\r\n");

	octeon_wdt_write_string("\tstatus\t0x");
	octeon_wdt_write_hex(cp0_status, 16);
	octeon_wdt_write_string("\tcause\t0x");
	octeon_wdt_write_hex(cp0_cause, 16);
	octeon_wdt_write_string("\r\n");

	/* The CIU register is different for each Octeon model. */
	if (OCTEON_IS_MODEL(OCTEON_CN68XX)) {
		octeon_wdt_write_string("\tsrc_wd\t0x");
		octeon_wdt_write_hex(cvmx_read_csr(CVMX_CIU2_SRC_PPX_IP2_WDOG(coreid)), 16);
		octeon_wdt_write_string("\ten_wd\t0x");
		octeon_wdt_write_hex(cvmx_read_csr(CVMX_CIU2_EN_PPX_IP2_WDOG(coreid)), 16);
		octeon_wdt_write_string("\r\n");
		octeon_wdt_write_string("\tsrc_rml\t0x");
		octeon_wdt_write_hex(cvmx_read_csr(CVMX_CIU2_SRC_PPX_IP2_RML(coreid)), 16);
		octeon_wdt_write_string("\ten_rml\t0x");
		octeon_wdt_write_hex(cvmx_read_csr(CVMX_CIU2_EN_PPX_IP2_RML(coreid)), 16);
		octeon_wdt_write_string("\r\n");
		octeon_wdt_write_string("\tsum\t0x");
		octeon_wdt_write_hex(cvmx_read_csr(CVMX_CIU2_SUM_PPX_IP2(coreid)), 16);
		octeon_wdt_write_string("\r\n");
	} else if (!octeon_has_feature(OCTEON_FEATURE_CIU3)) {
		octeon_wdt_write_string("\tsum0\t0x");
		octeon_wdt_write_hex(cvmx_read_csr(CVMX_CIU_INTX_SUM0(coreid * 2)), 16);
		octeon_wdt_write_string("\ten0\t0x");
		octeon_wdt_write_hex(cvmx_read_csr(CVMX_CIU_INTX_EN0(coreid * 2)), 16);
		octeon_wdt_write_string("\r\n");
	}

	octeon_wdt_write_string("*** Chip soft reset soon ***\r\n");

	/*
	 * G-30204: We must trigger a soft reset before watchdog
	 * does an incomplete job of doing it.
	 */
	if (OCTEON_IS_OCTEON3() && !OCTEON_IS_MODEL(OCTEON_CN70XX)) {
		u64 scr;
		unsigned int node = cvmx_get_node_num();
		unsigned int lcore = cvmx_get_local_core_num();
		union cvmx_ciu_wdogx ciu_wdog;

		/*
		 * Wait for other cores to print out information, but
		 * not too long.  Do the soft reset before watchdog
		 * can trigger it.
		 */
		do {
			ciu_wdog.u64 = cvmx_read_csr_node(node, CVMX_CIU_WDOGX(lcore));
		} while (ciu_wdog.s.cnt > 0x10000);

		scr = cvmx_read_csr_node(0, CVMX_GSERX_SCRATCH(0));
		scr |= 1 << 11; /* Indicate watchdog in bit 11 */
		cvmx_write_csr_node(0, CVMX_GSERX_SCRATCH(0), scr);
		cvmx_write_csr_node(0, CVMX_RST_SOFT_RST, 1);
	}
}