Introduce a new method, cpufreq_drv_type(), that returns the type of the

driver.  This used to be handled by cpufreq_drv_settings() but it's
useful to get the type/flags separately from getting the settings.
(For example, you don't have to pass an array of cf_setting just to find
the driver type.)

Use this new method in our in-tree drivers to detect reliably if acpi_perf
is present and owns the hardware.  This simplifies logic in drivers as well
as fixing a bug introduced in my last commit where too many drivers attached.
This commit is contained in:
Nate Lawson 2005-02-18 00:23:36 +00:00
parent 7643c37cf2
commit e94a0c1a18
5 changed files with 67 additions and 23 deletions

View File

@ -101,9 +101,10 @@ static void acpi_px_available(struct acpi_perf_softc *sc);
static void acpi_px_startup(void *arg);
static void acpi_px_notify(ACPI_HANDLE h, UINT32 notify, void *context);
static int acpi_px_settings(device_t dev, struct cf_setting *sets,
int *count, int *type);
int *count);
static int acpi_px_set(device_t dev, const struct cf_setting *set);
static int acpi_px_get(device_t dev, struct cf_setting *set);
static int acpi_px_type(device_t dev, int *type);
static device_method_t acpi_perf_methods[] = {
/* Device interface */
@ -115,6 +116,7 @@ static device_method_t acpi_perf_methods[] = {
/* cpufreq interface */
DEVMETHOD(cpufreq_drv_set, acpi_px_set),
DEVMETHOD(cpufreq_drv_get, acpi_px_get),
DEVMETHOD(cpufreq_drv_type, acpi_px_type),
DEVMETHOD(cpufreq_drv_settings, acpi_px_settings),
{0, 0}
};
@ -392,7 +394,7 @@ acpi_px_to_set(device_t dev, struct acpi_px *px, struct cf_setting *set)
}
static int
acpi_px_settings(device_t dev, struct cf_setting *sets, int *count, int *type)
acpi_px_settings(device_t dev, struct cf_setting *sets, int *count)
{
struct acpi_perf_softc *sc;
int x, y;
@ -408,9 +410,6 @@ acpi_px_settings(device_t dev, struct cf_setting *sets, int *count, int *type)
for (x = sc->px_max_avail; x < sc->px_count; x++, y++)
acpi_px_to_set(dev, &sc->px_states[x], &sets[y]);
*count = sc->px_count - sc->px_max_avail;
*type = CPUFREQ_TYPE_ABSOLUTE;
if (sc->info_only)
*type |= CPUFREQ_FLAG_INFO_ONLY;
return (0);
}
@ -502,3 +501,18 @@ acpi_px_get(device_t dev, struct cf_setting *set)
return (0);
}
static int
acpi_px_type(device_t dev, int *type)
{
struct acpi_perf_softc *sc;
if (type == NULL)
return (EINVAL);
sc = device_get_softc(dev);
*type = CPUFREQ_TYPE_ABSOLUTE;
if (sc->info_only)
*type |= CPUFREQ_FLAG_INFO_ONLY;
return (0);
}

View File

@ -97,9 +97,10 @@ static int acpi_throttle_attach(device_t dev);
static int acpi_throttle_evaluate(struct acpi_throttle_softc *sc);
static int acpi_throttle_quirks(struct acpi_throttle_softc *sc);
static int acpi_thr_settings(device_t dev, struct cf_setting *sets,
int *count, int *type);
int *count);
static int acpi_thr_set(device_t dev, const struct cf_setting *set);
static int acpi_thr_get(device_t dev, struct cf_setting *set);
static int acpi_thr_type(device_t dev, int *type);
static device_method_t acpi_throttle_methods[] = {
/* Device interface */
@ -110,6 +111,7 @@ static device_method_t acpi_throttle_methods[] = {
/* cpufreq interface */
DEVMETHOD(cpufreq_drv_set, acpi_thr_set),
DEVMETHOD(cpufreq_drv_get, acpi_thr_get),
DEVMETHOD(cpufreq_drv_type, acpi_thr_type),
DEVMETHOD(cpufreq_drv_settings, acpi_thr_settings),
{0, 0}
};
@ -320,7 +322,7 @@ acpi_throttle_quirks(struct acpi_throttle_softc *sc)
}
static int
acpi_thr_settings(device_t dev, struct cf_setting *sets, int *count, int *type)
acpi_thr_settings(device_t dev, struct cf_setting *sets, int *count)
{
struct acpi_throttle_softc *sc;
int i, speed;
@ -338,7 +340,6 @@ acpi_thr_settings(device_t dev, struct cf_setting *sets, int *count, int *type)
sets[i].dev = dev;
}
*count = CPU_MAX_SPEED;
*type = CPUFREQ_TYPE_RELATIVE;
return (0);
}
@ -409,3 +410,14 @@ acpi_thr_get(device_t dev, struct cf_setting *set)
return (0);
}
static int
acpi_thr_type(device_t dev, int *type)
{
if (type == NULL)
return (EINVAL);
*type = CPUFREQ_TYPE_RELATIVE;
return (0);
}

View File

@ -97,9 +97,10 @@ static int ichss_probe(device_t dev);
static int ichss_attach(device_t dev);
static int ichss_detach(device_t dev);
static int ichss_settings(device_t dev, struct cf_setting *sets,
int *count, int *type);
int *count);
static int ichss_set(device_t dev, const struct cf_setting *set);
static int ichss_get(device_t dev, struct cf_setting *set);
static int ichss_type(device_t dev, int *type);
static device_method_t ichss_methods[] = {
/* Device interface */
@ -110,6 +111,7 @@ static device_method_t ichss_methods[] = {
/* cpufreq interface */
DEVMETHOD(cpufreq_drv_set, ichss_set),
DEVMETHOD(cpufreq_drv_get, ichss_get),
DEVMETHOD(cpufreq_drv_type, ichss_type),
DEVMETHOD(cpufreq_drv_settings, ichss_settings),
{0, 0}
};
@ -209,9 +211,8 @@ ichss_pci_probe(device_t dev)
static int
ichss_probe(device_t dev)
{
struct cf_setting set;
device_t perf_dev;
int count, type;
int error, type;
/*
* If the ACPI perf driver has attached and is not just offering
@ -219,10 +220,8 @@ ichss_probe(device_t dev)
*/
perf_dev = device_find_child(device_get_parent(dev), "acpi_perf", -1);
if (perf_dev && device_is_attached(perf_dev)) {
type = 0;
count = 1;
CPUFREQ_DRV_SETTINGS(perf_dev, &set, &count, &type);
if ((type & CPUFREQ_FLAG_INFO_ONLY) == 0)
error = CPUFREQ_DRV_TYPE(perf_dev, &type);
if (error == 0 && (type & CPUFREQ_FLAG_INFO_ONLY) == 0)
return (ENXIO);
}
@ -275,7 +274,7 @@ ichss_detach(device_t dev)
}
static int
ichss_settings(device_t dev, struct cf_setting *sets, int *count, int *type)
ichss_settings(device_t dev, struct cf_setting *sets, int *count)
{
struct ichss_softc *sc;
struct cf_setting set;
@ -304,7 +303,6 @@ ichss_settings(device_t dev, struct cf_setting *sets, int *count, int *type)
bcopy(sc->sets, sets, sizeof(sc->sets));
*count = 2;
*type = CPUFREQ_TYPE_ABSOLUTE;
return (0);
}
@ -382,3 +380,14 @@ ichss_get(device_t dev, struct cf_setting *set)
return (0);
}
static int
ichss_type(device_t dev, int *type)
{
if (type == NULL)
return (EINVAL);
*type = CPUFREQ_TYPE_ABSOLUTE;
return (0);
}

View File

@ -88,5 +88,13 @@ METHOD int drv_settings {
device_t dev;
struct cf_setting *sets;
int *count;
};
#
# Get an individual driver's type.
#
METHOD int drv_type {
device_t dev;
int *type;
};

View File

@ -404,9 +404,12 @@ cf_levels_method(device_t dev, struct cf_level *levels, int *count)
* Get settings, skipping drivers that offer no settings or
* provide settings for informational purposes only.
*/
error = CPUFREQ_DRV_TYPE(devs[i], &type);
if (error || (type & CPUFREQ_FLAG_INFO_ONLY))
continue;
set_count = MAX_SETTINGS;
error = CPUFREQ_DRV_SETTINGS(devs[i], sets, &set_count, &type);
if (error || set_count == 0 || (type & CPUFREQ_FLAG_INFO_ONLY))
error = CPUFREQ_DRV_SETTINGS(devs[i], sets, &set_count);
if (error || set_count == 0)
continue;
/* Add the settings to our absolute/relative lists. */
@ -772,8 +775,7 @@ int
cpufreq_unregister(device_t dev)
{
device_t cf_dev, *devs;
int cfcount, count, devcount, error, i, type;
struct cf_setting set;
int cfcount, devcount, error, i, type;
/*
* If this is the last cpufreq child device, remove the control
@ -788,8 +790,7 @@ cpufreq_unregister(device_t dev)
for (i = 0; i < devcount; i++) {
if (!device_is_attached(devs[i]))
continue;
count = 1;
if (CPUFREQ_DRV_SETTINGS(devs[i], &set, &count, &type) == 0)
if (CPUFREQ_DRV_TYPE(devs[i], &type) == 0)
cfcount++;
}
if (cfcount <= 1)