コード例 #1
0
ファイル: acpi_cmbat.c プロジェクト: juanfra684/DragonFlyBSD
static void
acpi_cmbat_get_bst(void *arg)
{
    struct acpi_cmbat_softc *sc;
    ACPI_STATUS	as;
    ACPI_OBJECT	*res;
    ACPI_HANDLE	h;
    ACPI_BUFFER	bst_buffer;
    device_t dev;

    ACPI_SERIAL_ASSERT(cmbat);

    dev = arg;
    sc = device_get_softc(dev);
    h = acpi_get_handle(dev);
    bst_buffer.Pointer = NULL;
    bst_buffer.Length = ACPI_ALLOCATE_BUFFER;

    if (!acpi_cmbat_info_expired(&sc->bst_lastupdated))
	goto end;

    as = AcpiEvaluateObject(h, "_BST", NULL, &bst_buffer);
    if (ACPI_FAILURE(as)) {
	ACPI_VPRINT(dev, acpi_device_get_parent_softc(dev),
		    "error fetching current battery status -- %s\n",
		    AcpiFormatException(as));
	goto end;
    }

    res = (ACPI_OBJECT *)bst_buffer.Pointer;
    if (!ACPI_PKG_VALID(res, 4)) {
	ACPI_VPRINT(dev, acpi_device_get_parent_softc(dev),
		    "battery status corrupted\n");
	goto end;
    }

    if (acpi_PkgInt32(res, 0, &sc->bst.state) != 0)
	goto end;
    if (acpi_PkgInt32(res, 1, &sc->bst.rate) != 0)
	goto end;
    if (acpi_PkgInt32(res, 2, &sc->bst.cap) != 0)
	goto end;
    if (acpi_PkgInt32(res, 3, &sc->bst.volt) != 0)
	goto end;
    acpi_cmbat_info_updated(&sc->bst_lastupdated);

    /* XXX If all batteries are critical, perhaps we should suspend. */
    if (sc->bst.state & ACPI_BATT_STAT_CRITICAL) {
    	if ((sc->flags & ACPI_BATT_STAT_CRITICAL) == 0) {
	    sc->flags |= ACPI_BATT_STAT_CRITICAL;
	    device_printf(dev, "critically low charge!\n");
	}
    } else
	sc->flags &= ~ACPI_BATT_STAT_CRITICAL;

end:
    if (bst_buffer.Pointer != NULL)
	AcpiOsFree(bst_buffer.Pointer);
}
コード例 #2
0
ファイル: acpi_ec.c プロジェクト: AhmadTux/DragonFlyBSD
static int
acpi_ec_probe(device_t dev)
{
    ACPI_BUFFER buf;
    ACPI_HANDLE h;
    ACPI_OBJECT *obj;
    ACPI_STATUS status;
    device_t	peer;
    char	desc[64];
    int		ecdt;
    int		ret;
    struct acpi_ec_params *params;
    static char *ec_ids[] = { "PNP0C09", NULL };

    /* Check that this is a device and that EC is not disabled. */
    if (acpi_get_type(dev) != ACPI_TYPE_DEVICE || acpi_disabled("ec"))
	return (ENXIO);

    /*
     * If probed via ECDT, set description and continue.  Otherwise,
     * we can access the namespace and make sure this is not a
     * duplicate probe.
     */
    ret = ENXIO;
    ecdt = 0;
    buf.Pointer = NULL;
    buf.Length = ACPI_ALLOCATE_BUFFER;
    params = acpi_get_private(dev);
    if (params != NULL) {
	ecdt = 1;
	ret = 0;
    } else if (ACPI_ID_PROBE(device_get_parent(dev), dev, ec_ids)) {
	params = kmalloc(sizeof(struct acpi_ec_params), M_TEMP,
			M_WAITOK | M_ZERO);
	h = acpi_get_handle(dev);

	/*
	 * Read the unit ID to check for duplicate attach and the
	 * global lock value to see if we should acquire it when
	 * accessing the EC.
	 */
	status = acpi_GetInteger(h, "_UID", &params->uid);
	if (ACPI_FAILURE(status))
	    params->uid = 0;
	status = acpi_GetInteger(h, "_GLK", &params->glk);
	if (ACPI_FAILURE(status))
	    params->glk = 0;

	/*
	 * Evaluate the _GPE method to find the GPE bit used by the EC to
	 * signal status (SCI).  If it's a package, it contains a reference
	 * and GPE bit, similar to _PRW.
	 */
	status = AcpiEvaluateObject(h, "_GPE", NULL, &buf);
	if (ACPI_FAILURE(status)) {
	    device_printf(dev, "can't evaluate _GPE - %s\n",
			  AcpiFormatException(status));
	    goto out;
	}
	obj = (ACPI_OBJECT *)buf.Pointer;
	if (obj == NULL)
	    goto out;

	switch (obj->Type) {
	case ACPI_TYPE_INTEGER:
	    params->gpe_handle = NULL;
	    params->gpe_bit = obj->Integer.Value;
	    break;
	case ACPI_TYPE_PACKAGE:
	    if (!ACPI_PKG_VALID(obj, 2))
		goto out;
	    params->gpe_handle =
		acpi_GetReference(NULL, &obj->Package.Elements[0]);
	    if (params->gpe_handle == NULL ||
		acpi_PkgInt32(obj, 1, &params->gpe_bit) != 0)
		goto out;
	    break;
	default:
	    device_printf(dev, "_GPE has invalid type %d\n", obj->Type);
	    goto out;
	}

	/* Store the values we got from the namespace for attach. */
	acpi_set_private(dev, params);

	/*
	 * Check for a duplicate probe.  This can happen when a probe
	 * via ECDT succeeded already.  If this is a duplicate, disable
	 * this device.
	 */
	peer = devclass_get_device(acpi_ec_devclass, params->uid);
	if (peer == NULL || !device_is_alive(peer))
	    ret = 0;
	else
	    device_disable(dev);
    }

out:
    if (ret == 0) {
	ksnprintf(desc, sizeof(desc), "Embedded Controller: GPE %#x%s%s",
		 params->gpe_bit, (params->glk) ? ", GLK" : "",
		 ecdt ? ", ECDT" : "");
	device_set_desc_copy(dev, desc);
    }

    if (ret > 0 && params)
	kfree(params, M_TEMP);
    if (buf.Pointer)
	AcpiOsFree(buf.Pointer);
    return (ret);
}
コード例 #3
0
/*
 * Parse a _CST package and set up its Cx states.  Since the _CST object
 * can change dynamically, our notify handler may call this function
 * to clean up and probe the new _CST package.
 */
static int
acpi_cpu_cx_cst(struct acpi_cpu_softc *sc)
{
    struct	 acpi_cx *cx_ptr;
    ACPI_STATUS	 status;
    ACPI_BUFFER	 buf;
    ACPI_OBJECT	*top;
    ACPI_OBJECT	*pkg;
    uint32_t	 count;
    int		 i;

    ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__);

    buf.Pointer = NULL;
    buf.Length = ACPI_ALLOCATE_BUFFER;
    status = AcpiEvaluateObject(sc->cpu_handle, "_CST", NULL, &buf);
    if (ACPI_FAILURE(status))
	return (ENXIO);

    /* _CST is a package with a count and at least one Cx package. */
    top = (ACPI_OBJECT *)buf.Pointer;
    if (!ACPI_PKG_VALID(top, 2) || acpi_PkgInt32(top, 0, &count) != 0) {
	device_printf(sc->cpu_dev, "invalid _CST package\n");
	AcpiOsFree(buf.Pointer);
	return (ENXIO);
    }
    if (count != top->Package.Count - 1) {
	device_printf(sc->cpu_dev, "invalid _CST state count (%d != %d)\n",
	       count, top->Package.Count - 1);
	count = top->Package.Count - 1;
    }
    if (count > MAX_CX_STATES) {
	device_printf(sc->cpu_dev, "_CST has too many states (%d)\n", count);
	count = MAX_CX_STATES;
    }

    /* Set up all valid states. */
    sc->cpu_cx_count = 0;
    cx_ptr = sc->cpu_cx_states;
    for (i = 0; i < count; i++) {
	pkg = &top->Package.Elements[i + 1];
	if (!ACPI_PKG_VALID(pkg, 4) ||
	    acpi_PkgInt32(pkg, 1, &cx_ptr->type) != 0 ||
	    acpi_PkgInt32(pkg, 2, &cx_ptr->trans_lat) != 0 ||
	    acpi_PkgInt32(pkg, 3, &cx_ptr->power) != 0) {

	    device_printf(sc->cpu_dev, "skipping invalid Cx state package\n");
	    continue;
	}

	/* Validate the state to see if we should use it. */
	switch (cx_ptr->type) {
	case ACPI_STATE_C1:
	    sc->cpu_non_c3 = i;
	    cx_ptr++;
	    sc->cpu_cx_count++;
	    continue;
	case ACPI_STATE_C2:
	    if (cx_ptr->trans_lat > 100) {
		ACPI_DEBUG_PRINT((ACPI_DB_INFO,
				 "acpi_cpu%d: C2[%d] not available.\n",
				 device_get_unit(sc->cpu_dev), i));
		continue;
	    }
	    sc->cpu_non_c3 = i;
	    break;
	case ACPI_STATE_C3:
	default:
	    if (cx_ptr->trans_lat > 1000 ||
		(cpu_quirks & CPU_QUIRK_NO_C3) != 0) {

		ACPI_DEBUG_PRINT((ACPI_DB_INFO,
				 "acpi_cpu%d: C3[%d] not available.\n",
				 device_get_unit(sc->cpu_dev), i));
		continue;
	    }
	    break;
	}

#ifdef notyet
	/* Free up any previous register. */
	if (cx_ptr->p_lvlx != NULL) {
	    bus_release_resource(sc->cpu_dev, 0, 0, cx_ptr->p_lvlx);
	    cx_ptr->p_lvlx = NULL;
	}
#endif

	/* Allocate the control register for C2 or C3. */
	acpi_PkgGas(sc->cpu_dev, pkg, 0, &cx_ptr->res_type, &sc->cpu_rid,
	    &cx_ptr->p_lvlx, RF_SHAREABLE);
	if (cx_ptr->p_lvlx) {
	    sc->cpu_rid++;
	    ACPI_DEBUG_PRINT((ACPI_DB_INFO,
			     "acpi_cpu%d: Got C%d - %d latency\n",
			     device_get_unit(sc->cpu_dev), cx_ptr->type,
			     cx_ptr->trans_lat));
	    cx_ptr++;
	    sc->cpu_cx_count++;
	}
    }
    AcpiOsFree(buf.Pointer);

    return (0);
}
コード例 #4
0
ファイル: acpi_cmbat.c プロジェクト: dcui/FreeBSD-9.3_kernel
static void
acpi_cmbat_get_bif(void *arg)
{
    struct acpi_cmbat_softc *sc;
    ACPI_STATUS	as;
    ACPI_OBJECT	*res;
    ACPI_HANDLE	h;
    ACPI_BUFFER	bif_buffer;
    device_t dev;

    ACPI_SERIAL_ASSERT(cmbat);

    dev = arg;
    sc = device_get_softc(dev);
    h = acpi_get_handle(dev);
    bif_buffer.Pointer = NULL;
    bif_buffer.Length = ACPI_ALLOCATE_BUFFER;

    as = AcpiEvaluateObject(h, "_BIF", NULL, &bif_buffer);
    if (ACPI_FAILURE(as)) {
	ACPI_VPRINT(dev, acpi_device_get_parent_softc(dev),
		    "error fetching current battery info -- %s\n",
		    AcpiFormatException(as));
	goto end;
    }

    res = (ACPI_OBJECT *)bif_buffer.Pointer;
    if (!ACPI_PKG_VALID(res, 13)) {
	ACPI_VPRINT(dev, acpi_device_get_parent_softc(dev),
		    "battery info corrupted\n");
	goto end;
    }

    if (acpi_PkgInt32(res, 0, &sc->bif.units) != 0)
	goto end;
    if (acpi_PkgInt32(res, 1, &sc->bif.dcap) != 0)
	goto end;
    if (acpi_PkgInt32(res, 2, &sc->bif.lfcap) != 0)
	goto end;
    if (acpi_PkgInt32(res, 3, &sc->bif.btech) != 0)
	goto end;
    if (acpi_PkgInt32(res, 4, &sc->bif.dvol) != 0)
	goto end;
    if (acpi_PkgInt32(res, 5, &sc->bif.wcap) != 0)
	goto end;
    if (acpi_PkgInt32(res, 6, &sc->bif.lcap) != 0)
	goto end;
    if (acpi_PkgInt32(res, 7, &sc->bif.gra1) != 0)
	goto end;
    if (acpi_PkgInt32(res, 8, &sc->bif.gra2) != 0)
	goto end;
    if (acpi_PkgStr(res,  9, sc->bif.model, ACPI_CMBAT_MAXSTRLEN) != 0)
	goto end;
    if (acpi_PkgStr(res, 10, sc->bif.serial, ACPI_CMBAT_MAXSTRLEN) != 0)
	goto end;
    if (acpi_PkgStr(res, 11, sc->bif.type, ACPI_CMBAT_MAXSTRLEN) != 0)
	goto end;
    if (acpi_PkgStr(res, 12, sc->bif.oeminfo, ACPI_CMBAT_MAXSTRLEN) != 0)
	goto end;

end:
    if (bif_buffer.Pointer != NULL)
	AcpiOsFree(bif_buffer.Pointer);
}
コード例 #5
0
ファイル: acpi_perf.c プロジェクト: MattDooner/freebsd-west
/* Probe and setup any valid performance states (Px). */
static int
acpi_perf_evaluate(device_t dev)
{
	struct acpi_perf_softc *sc;
	ACPI_BUFFER buf;
	ACPI_OBJECT *pkg, *res;
	ACPI_STATUS status;
	int count, error, i, j;
	static int once = 1;
	uint32_t *p;

	/* Get the control values and parameters for each state. */
	error = ENXIO;
	sc = device_get_softc(dev);
	buf.Pointer = NULL;
	buf.Length = ACPI_ALLOCATE_BUFFER;
	status = AcpiEvaluateObject(sc->handle, "_PSS", NULL, &buf);
	if (ACPI_FAILURE(status))
		return (ENXIO);

	pkg = (ACPI_OBJECT *)buf.Pointer;
	if (!ACPI_PKG_VALID(pkg, 1)) {
		device_printf(dev, "invalid top level _PSS package\n");
		goto out;
	}
	sc->px_count = pkg->Package.Count;

	sc->px_states = malloc(sc->px_count * sizeof(struct acpi_px),
	    M_ACPIPERF, M_WAITOK | M_ZERO);
	if (sc->px_states == NULL)
		goto out;

	/*
	 * Each state is a package of {CoreFreq, Power, TransitionLatency,
	 * BusMasterLatency, ControlVal, StatusVal}, sorted from highest
	 * performance to lowest.
	 */
	count = 0;
	for (i = 0; i < sc->px_count; i++) {
		res = &pkg->Package.Elements[i];
		if (!ACPI_PKG_VALID(res, 6)) {
			if (once) {
				once = 0;
				device_printf(dev, "invalid _PSS package\n");
			}
			continue;
		}

		/* Parse the rest of the package into the struct. */
		p = &sc->px_states[count].core_freq;
		for (j = 0; j < 6; j++, p++)
			acpi_PkgInt32(res, j, p);

		/*
		 * Check for some impossible frequencies that some systems
		 * use to indicate they don't actually support this Px state.
		 */
		if (sc->px_states[count].core_freq == 0 ||
		    sc->px_states[count].core_freq == 9999 ||
		    sc->px_states[count].core_freq == 0x9999 ||
		    sc->px_states[count].core_freq >= 0xffff)
			continue;

		/* Check for duplicate entries */
		if (count > 0 &&
		    sc->px_states[count - 1].core_freq ==
			sc->px_states[count].core_freq)
			continue;

		count++;
	}
	sc->px_count = count;

	/* No valid Px state found so give up. */
	if (count == 0)
		goto out;
	AcpiOsFree(buf.Pointer);

	/* Get the control and status registers (one of each). */
	buf.Pointer = NULL;
	buf.Length = ACPI_ALLOCATE_BUFFER;
	status = AcpiEvaluateObject(sc->handle, "_PCT", NULL, &buf);
	if (ACPI_FAILURE(status))
		goto out;

	/* Check the package of two registers, each a Buffer in GAS format. */
	pkg = (ACPI_OBJECT *)buf.Pointer;
	if (!ACPI_PKG_VALID(pkg, 2)) {
		device_printf(dev, "invalid perf register package\n");
		goto out;
	}

	error = acpi_PkgGas(sc->dev, pkg, 0, &sc->perf_ctrl_type, &sc->px_rid,
	    &sc->perf_ctrl, 0);
	if (error) {
		/*
		 * If the register is of type FFixedHW, we can only return
		 * info, we can't get or set new settings.
		 */
		if (error == EOPNOTSUPP) {
			sc->info_only = TRUE;
			error = 0;
		} else
			device_printf(dev, "failed in PERF_CTL attach\n");
		goto out;
	}
	sc->px_rid++;

	error = acpi_PkgGas(sc->dev, pkg, 1, &sc->perf_sts_type, &sc->px_rid,
	    &sc->perf_status, 0);
	if (error) {
		if (error == EOPNOTSUPP) {
			sc->info_only = TRUE;
			error = 0;
		} else
			device_printf(dev, "failed in PERF_STATUS attach\n");
		goto out;
	}
	sc->px_rid++;

	/* Get our current limit and register for notifies. */
	acpi_px_available(sc);
	AcpiInstallNotifyHandler(sc->handle, ACPI_DEVICE_NOTIFY,
	    acpi_px_notify, sc);
	error = 0;

out:
	if (error) {
		if (sc->px_states) {
			free(sc->px_states, M_ACPIPERF);
			sc->px_states = NULL;
		}
		if (sc->perf_ctrl) {
			bus_release_resource(sc->dev, sc->perf_ctrl_type, 0,
			    sc->perf_ctrl);
			bus_delete_resource(sc->dev, sc->perf_ctrl_type, 0);
			sc->perf_ctrl = NULL;
		}
		if (sc->perf_status) {
			bus_release_resource(sc->dev, sc->perf_sts_type, 1,
			    sc->perf_status);
			bus_delete_resource(sc->dev, sc->perf_sts_type, 1);
			sc->perf_status = NULL;
		}
		sc->px_rid = 0;
		sc->px_count = 0;
	}
	if (buf.Pointer)
		AcpiOsFree(buf.Pointer);
	return (error);
}
コード例 #6
0
ファイル: acpi_cpu_cstate.c プロジェクト: wan721/DragonFlyBSD
/*
 * Parse a _CST package and set up its Cx states.  Since the _CST object
 * can change dynamically, our notify handler may call this function
 * to clean up and probe the new _CST package.
 */
static int
acpi_cst_cx_probe_cst(struct acpi_cst_softc *sc, int reprobe)
{
    struct	 acpi_cst_cx *cx_ptr;
    ACPI_STATUS	 status;
    ACPI_BUFFER	 buf;
    ACPI_OBJECT	*top;
    ACPI_OBJECT	*pkg;
    uint32_t	 count;
    int		 i;

    ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__);

#ifdef INVARIANTS
    if (reprobe)
	KKASSERT(&curthread->td_msgport == netisr_cpuport(sc->cst_cpuid));
#endif

    buf.Pointer = NULL;
    buf.Length = ACPI_ALLOCATE_BUFFER;
    status = AcpiEvaluateObject(sc->cst_handle, "_CST", NULL, &buf);
    if (ACPI_FAILURE(status))
	return (ENXIO);

    /* _CST is a package with a count and at least one Cx package. */
    top = (ACPI_OBJECT *)buf.Pointer;
    if (!ACPI_PKG_VALID(top, 2) || acpi_PkgInt32(top, 0, &count) != 0) {
	device_printf(sc->cst_dev, "invalid _CST package\n");
	AcpiOsFree(buf.Pointer);
	return (ENXIO);
    }
    if (count != top->Package.Count - 1) {
	device_printf(sc->cst_dev, "invalid _CST state count (%d != %d)\n",
	       count, top->Package.Count - 1);
	count = top->Package.Count - 1;
    }
    if (count > MAX_CX_STATES) {
	device_printf(sc->cst_dev, "_CST has too many states (%d)\n", count);
	count = MAX_CX_STATES;
    }

    sc->cst_flags |= ACPI_CST_FLAG_PROBING | ACPI_CST_FLAG_MATCH_HT;
    cpu_sfence();

    /*
     * Free all previously allocated resources
     *
     * NOTE: It is needed for _CST reprobing.
     */
    acpi_cst_free_resource(sc, 0);

    /* Set up all valid states. */
    sc->cst_cx_count = 0;
    cx_ptr = sc->cst_cx_states;
    for (i = 0; i < count; i++) {
	int error;

	pkg = &top->Package.Elements[i + 1];
	if (!ACPI_PKG_VALID(pkg, 4) ||
	    acpi_PkgInt32(pkg, 1, &cx_ptr->type) != 0 ||
	    acpi_PkgInt32(pkg, 2, &cx_ptr->trans_lat) != 0 ||
	    acpi_PkgInt32(pkg, 3, &cx_ptr->power) != 0) {

	    device_printf(sc->cst_dev, "skipping invalid Cx state package\n");
	    continue;
	}

	/* Validate the state to see if we should use it. */
	switch (cx_ptr->type) {
	case ACPI_STATE_C1:
	    sc->cst_non_c3 = i;
	    cx_ptr->enter = acpi_cst_c1_halt_enter;
	    error = acpi_cst_cx_setup(cx_ptr);
	    if (error)
		panic("C1 CST HALT setup failed: %d", error);
	    if (sc->cst_cx_count != 0) {
		/*
		 * C1 is not the first C-state; something really stupid
		 * is going on ...
		 */
		sc->cst_flags &= ~ACPI_CST_FLAG_MATCH_HT;
	    }
	    cx_ptr++;
	    sc->cst_cx_count++;
	    continue;
	case ACPI_STATE_C2:
	    sc->cst_non_c3 = i;
	    break;
	case ACPI_STATE_C3:
	default:
	    if ((acpi_cst_quirks & ACPI_CST_QUIRK_NO_C3) != 0) {
		ACPI_DEBUG_PRINT((ACPI_DB_INFO,
				 "cpu_cst%d: C3[%d] not available.\n",
				 device_get_unit(sc->cst_dev), i));
		continue;
	    }
	    break;
	}

	/*
	 * Allocate the control register for C2 or C3(+).
	 */
	KASSERT(cx_ptr->res == NULL, ("still has res"));
	acpi_PkgRawGas(pkg, 0, &cx_ptr->gas);

	/*
	 * We match number of C2/C3 for hyperthreads, only if the
	 * register is "Fixed Hardware", e.g. on most of the Intel
	 * CPUs.  We don't have much to do for the rest of the
	 * register types.
	 */
	if (cx_ptr->gas.SpaceId != ACPI_ADR_SPACE_FIXED_HARDWARE)
	    sc->cst_flags &= ~ACPI_CST_FLAG_MATCH_HT;

	cx_ptr->rid = sc->cst_parent->cpu_next_rid;
	acpi_bus_alloc_gas(sc->cst_dev, &cx_ptr->res_type, &cx_ptr->rid,
	    &cx_ptr->gas, &cx_ptr->res, RF_SHAREABLE);
	if (cx_ptr->res != NULL) {
	    sc->cst_parent->cpu_next_rid++;
	    ACPI_DEBUG_PRINT((ACPI_DB_INFO,
			     "cpu_cst%d: Got C%d - %d latency\n",
			     device_get_unit(sc->cst_dev), cx_ptr->type,
			     cx_ptr->trans_lat));
	    cx_ptr->enter = acpi_cst_cx_io_enter;
	    cx_ptr->btag = rman_get_bustag(cx_ptr->res);
	    cx_ptr->bhand = rman_get_bushandle(cx_ptr->res);
	    error = acpi_cst_cx_setup(cx_ptr);
	    if (error)
		panic("C%d CST I/O setup failed: %d", cx_ptr->type, error);
	    cx_ptr++;
	    sc->cst_cx_count++;
	} else {
	    error = acpi_cst_cx_setup(cx_ptr);
	    if (!error) {
		KASSERT(cx_ptr->enter != NULL,
		    ("C%d enter is not set", cx_ptr->type));
		cx_ptr++;
		sc->cst_cx_count++;
	    }
	}
    }
    AcpiOsFree(buf.Pointer);

    if (sc->cst_flags & ACPI_CST_FLAG_MATCH_HT) {
	cpumask_t mask;

	mask = get_cpumask_from_level(sc->cst_cpuid, CORE_LEVEL);
	if (CPUMASK_TESTNZERO(mask)) {
	    int cpu;

	    for (cpu = 0; cpu < ncpus; ++cpu) {
		struct acpi_cst_softc *sc1 = acpi_cst_softc[cpu];

		if (sc1 == NULL || sc1 == sc ||
		    (sc1->cst_flags & ACPI_CST_FLAG_ATTACHED) == 0 ||
		    (sc1->cst_flags & ACPI_CST_FLAG_MATCH_HT) == 0)
		    continue;
		if (!CPUMASK_TESTBIT(mask, sc1->cst_cpuid))
		    continue;

		if (sc1->cst_cx_count != sc->cst_cx_count) {
		    struct acpi_cst_softc *src_sc, *dst_sc;

		    if (bootverbose) {
			device_printf(sc->cst_dev,
			    "inconstent C-state count: %d, %s has %d\n",
			    sc->cst_cx_count,
			    device_get_nameunit(sc1->cst_dev),
			    sc1->cst_cx_count);
		    }
		    if (sc1->cst_cx_count > sc->cst_cx_count) {
			src_sc = sc1;
			dst_sc = sc;
		    } else {
			src_sc = sc;
			dst_sc = sc1;
		    }
		    acpi_cst_copy(dst_sc, src_sc);
		}
	    }
	}
    }

    if (reprobe) {
	/* If there are C3(+) states, always enable bus master wakeup */
	if ((acpi_cst_quirks & ACPI_CST_QUIRK_NO_BM) == 0) {
	    for (i = 0; i < sc->cst_cx_count; ++i) {
		struct acpi_cst_cx *cx = &sc->cst_cx_states[i];

		if (cx->type >= ACPI_STATE_C3) {
		    AcpiWriteBitRegister(ACPI_BITREG_BUS_MASTER_RLD, 1);
		    break;
		}
	    }
	}

	/* Fix up the lowest Cx being used */
	acpi_cst_set_lowest_oncpu(sc, sc->cst_cx_lowest_req);
    }

    /*
     * Cache the lowest non-C3 state.
     * NOTE: must after cst_cx_lowest is set.
     */
    acpi_cst_non_c3(sc);

    cpu_sfence();
    sc->cst_flags &= ~ACPI_CST_FLAG_PROBING;

    return (0);
}