Ejemplo n.º 1
0
static void pnv_kexec_wait_secondaries_down(void)
{
	int my_cpu, i, notified = -1;

	my_cpu = get_cpu();

	for_each_online_cpu(i) {
		uint8_t status;
		int64_t rc;

		if (i == my_cpu)
			continue;

		for (;;) {
			rc = opal_query_cpu_status(get_hard_smp_processor_id(i),
						   &status);
			if (rc != OPAL_SUCCESS || status != OPAL_THREAD_STARTED)
				break;
			barrier();
			if (i != notified) {
				printk(KERN_INFO "kexec: waiting for cpu %d "
				       "(physical %d) to enter OPAL\n",
				       i, paca[i].hw_cpu_id);
				notified = i;
			}
		}
	}
}
Ejemplo n.º 2
0
static void pnv_kexec_wait_secondaries_down(void)
{
	int my_cpu, i, notified = -1;

	my_cpu = get_cpu();

	for_each_online_cpu(i) {
		uint8_t status;
		int64_t rc, timeout = 1000;

		if (i == my_cpu)
			continue;

		for (;;) {
			rc = opal_query_cpu_status(get_hard_smp_processor_id(i),
						   &status);
			if (rc != OPAL_SUCCESS || status != OPAL_THREAD_STARTED)
				break;
			barrier();
			if (i != notified) {
				printk(KERN_INFO "kexec: waiting for cpu %d "
				       "(physical %d) to enter OPAL\n",
				       i, paca[i].hw_cpu_id);
				notified = i;
			}

			/*
			 * On crash secondaries might be unreachable or hung,
			 * so timeout if we've waited too long
			 * */
			mdelay(1);
			if (timeout-- == 0) {
				printk(KERN_ERR "kexec: timed out waiting for "
				       "cpu %d (physical %d) to enter OPAL\n",
				       i, paca[i].hw_cpu_id);
				break;
			}
		}
	}
}
Ejemplo n.º 3
0
int pnv_smp_kick_cpu(int nr)
{
	unsigned int pcpu = get_hard_smp_processor_id(nr);
	unsigned long start_here = __pa(*((unsigned long *)
					  generic_secondary_smp_init));
	long rc;

	BUG_ON(nr < 0 || nr >= NR_CPUS);

	/*
	 * If we already started or OPALv2 is not supported, we just
	 * kick the CPU via the PACA
	 */
	if (paca[nr].cpu_start || !firmware_has_feature(FW_FEATURE_OPALv2))
		goto kick;

	/*
	 * At this point, the CPU can either be spinning on the way in
	 * from kexec or be inside OPAL waiting to be started for the
	 * first time. OPAL v3 allows us to query OPAL to know if it
	 * has the CPUs, so we do that
	 */
	if (firmware_has_feature(FW_FEATURE_OPALv3)) {
		uint8_t status;

		rc = opal_query_cpu_status(pcpu, &status);
		if (rc != OPAL_SUCCESS) {
			pr_warn("OPAL Error %ld querying CPU %d state\n",
				rc, nr);
			return -ENODEV;
		}

		/*
		 * Already started, just kick it, probably coming from
		 * kexec and spinning
		 */
		if (status == OPAL_THREAD_STARTED)
			goto kick;

		/*
		 * Available/inactive, let's kick it
		 */
		if (status == OPAL_THREAD_INACTIVE) {
			pr_devel("OPAL: Starting CPU %d (HW 0x%x)...\n",
				 nr, pcpu);
			rc = opal_start_cpu(pcpu, start_here);
			if (rc != OPAL_SUCCESS) {
				pr_warn("OPAL Error %ld starting CPU %d\n",
					rc, nr);
				return -ENODEV;
			}
		} else {
			/*
			 * An unavailable CPU (or any other unknown status)
			 * shouldn't be started. It should also
			 * not be in the possible map but currently it can
			 * happen
			 */
			pr_devel("OPAL: CPU %d (HW 0x%x) is unavailable"
				 " (status %d)...\n", nr, pcpu, status);
			return -ENODEV;
		}
	} else {
		/*
		 * On OPAL v2, we just kick it and hope for the best,
		 * we must not test the error from opal_start_cpu() or
		 * we would fail to get CPUs from kexec.
		 */
		opal_start_cpu(pcpu, start_here);
	}
 kick:
	return smp_generic_kick_cpu(nr);
}