Changeset View
Changeset View
Standalone View
Standalone View
sys/x86/cpufreq/hwpstate_amd.c
| Show First 20 Lines • Show All 141 Lines • ▼ Show 20 Lines | struct hwpstate_setting { | ||||
| int pstate_id; /* P-State id */ | int pstate_id; /* P-State id */ | ||||
| }; | }; | ||||
| enum hwpstate_flags { | enum hwpstate_flags { | ||||
| PSTATE_CPPC = 1, | PSTATE_CPPC = 1, | ||||
| }; | }; | ||||
| struct hwpstate_softc { | struct hwpstate_softc { | ||||
| device_t dev; | device_t dev; | ||||
| struct hwpstate_setting hwpstate_settings[AMD_10H_11H_MAX_STATES]; | u_int flags; | ||||
| union { | |||||
| struct { | |||||
| struct hwpstate_setting | |||||
| hwpstate_settings[AMD_10H_11H_MAX_STATES]; | |||||
| int cfnum; | int cfnum; | ||||
| uint32_t flags; | |||||
| uint64_t req; | |||||
| }; | }; | ||||
| struct { | |||||
| uint64_t request; | |||||
| } cppc; | |||||
| }; | |||||
| }; | |||||
| static void hwpstate_identify(driver_t *driver, device_t parent); | static void hwpstate_identify(driver_t *driver, device_t parent); | ||||
| static int hwpstate_probe(device_t dev); | static int hwpstate_probe(device_t dev); | ||||
| static int hwpstate_attach(device_t dev); | static int hwpstate_attach(device_t dev); | ||||
| static int hwpstate_detach(device_t dev); | static int hwpstate_detach(device_t dev); | ||||
| static int hwpstate_set(device_t dev, const struct cf_setting *cf); | static int hwpstate_set(device_t dev, const struct cf_setting *cf); | ||||
| static int hwpstate_get(device_t dev, struct cf_setting *cf); | static int hwpstate_get(device_t dev, struct cf_setting *cf); | ||||
| static int hwpstate_settings(device_t dev, struct cf_setting *sets, int *count); | static int hwpstate_settings(device_t dev, struct cf_setting *sets, int *count); | ||||
| ▲ Show 20 Lines • Show All 152 Lines • ▼ Show 20 Lines | |||||
| } | } | ||||
| static void | static void | ||||
| set_epp(device_t hwp_device, u_int val) | set_epp(device_t hwp_device, u_int val) | ||||
| { | { | ||||
| struct hwpstate_softc *sc; | struct hwpstate_softc *sc; | ||||
| sc = device_get_softc(hwp_device); | sc = device_get_softc(hwp_device); | ||||
| if (BITS_VALUE(AMD_CPPC_REQUEST_EPP_BITS, sc->req) == val) | if (BITS_VALUE(AMD_CPPC_REQUEST_EPP_BITS, sc->cppc.request) == val) | ||||
| return; | return; | ||||
| SET_BITS_VALUE(sc->req, AMD_CPPC_REQUEST_EPP_BITS, val); | SET_BITS_VALUE(sc->cppc.request, AMD_CPPC_REQUEST_EPP_BITS, val); | ||||
| x86_msr_op(MSR_AMD_CPPC_REQUEST, | x86_msr_op(MSR_AMD_CPPC_REQUEST, | ||||
| MSR_OP_RENDEZVOUS_ONE | MSR_OP_WRITE | | MSR_OP_RENDEZVOUS_ONE | MSR_OP_WRITE | | ||||
| MSR_OP_CPUID(cpu_get_pcpu(hwp_device)->pc_cpuid), | MSR_OP_CPUID(cpu_get_pcpu(hwp_device)->pc_cpuid), | ||||
| sc->req, NULL); | sc->cppc.request, NULL); | ||||
| } | } | ||||
| static int | static int | ||||
| sysctl_epp_handler(SYSCTL_HANDLER_ARGS) | sysctl_epp_handler(SYSCTL_HANDLER_ARGS) | ||||
| { | { | ||||
| device_t dev, hwp_dev; | device_t dev, hwp_dev; | ||||
| devclass_t dc; | devclass_t dc; | ||||
| struct hwpstate_softc *sc; | struct hwpstate_softc *sc; | ||||
| const u_int max_epp = | const u_int max_epp = | ||||
| BITS_VALUE(AMD_CPPC_REQUEST_EPP_BITS, (uint64_t)-1); | BITS_VALUE(AMD_CPPC_REQUEST_EPP_BITS, (uint64_t)-1); | ||||
| u_int val; | u_int val; | ||||
| int error = 0; | int error = 0; | ||||
| int cpu; | int cpu; | ||||
| dev = oidp->oid_arg1; | dev = oidp->oid_arg1; | ||||
| sc = device_get_softc(dev); | sc = device_get_softc(dev); | ||||
| /* Sysctl knob does not exist if PSTATE_CPPC is not set. */ | /* Sysctl knob does not exist if PSTATE_CPPC is not set. */ | ||||
| check_cppc_enabled(sc, __func__); | check_cppc_enabled(sc, __func__); | ||||
| val = BITS_VALUE(AMD_CPPC_REQUEST_EPP_BITS, sc->req) * 100 / | val = BITS_VALUE(AMD_CPPC_REQUEST_EPP_BITS, sc->cppc.request) * 100 / | ||||
| max_epp; | max_epp; | ||||
| error = sysctl_handle_int(oidp, &val, 0, req); | error = sysctl_handle_int(oidp, &val, 0, req); | ||||
| if (error != 0 || req->newptr == NULL) | if (error != 0 || req->newptr == NULL) | ||||
| goto end; | goto end; | ||||
| if (val > 100) { | if (val > 100) { | ||||
| error = EINVAL; | error = EINVAL; | ||||
| goto end; | goto end; | ||||
| } | } | ||||
| ▲ Show 20 Lines • Show All 264 Lines • ▼ Show 20 Lines | amd_set_autonomous_hwp_cb(void *args) | ||||
| sc = device_get_softc(dev); | sc = device_get_softc(dev); | ||||
| ret = wrmsr_safe(MSR_AMD_CPPC_ENABLE, 1); | ret = wrmsr_safe(MSR_AMD_CPPC_ENABLE, 1); | ||||
| if (ret != 0) { | if (ret != 0) { | ||||
| device_printf(dev, "Failed to enable cppc for cpu%d (%d)\n", | device_printf(dev, "Failed to enable cppc for cpu%d (%d)\n", | ||||
| curcpu, ret); | curcpu, ret); | ||||
| req->res = ret; | req->res = ret; | ||||
| } | } | ||||
| ret = rdmsr_safe(MSR_AMD_CPPC_REQUEST, &sc->req); | ret = rdmsr_safe(MSR_AMD_CPPC_REQUEST, &sc->cppc.request); | ||||
| if (ret != 0) { | if (ret != 0) { | ||||
| device_printf(dev, | device_printf(dev, | ||||
| "Failed to read CPPC request MSR for cpu%d (%d)\n", curcpu, | "Failed to read CPPC request MSR for cpu%d (%d)\n", curcpu, | ||||
| ret); | ret); | ||||
| req->res = ret; | req->res = ret; | ||||
| } | } | ||||
| ret = rdmsr_safe(MSR_AMD_CPPC_CAPS_1, &caps); | ret = rdmsr_safe(MSR_AMD_CPPC_CAPS_1, &caps); | ||||
| if (ret != 0) { | if (ret != 0) { | ||||
| device_printf(dev, | device_printf(dev, | ||||
| "Failed to read HWP capabilities MSR for cpu%d (%d)\n", | "Failed to read HWP capabilities MSR for cpu%d (%d)\n", | ||||
| curcpu, ret); | curcpu, ret); | ||||
| req->res = ret; | req->res = ret; | ||||
| return; | return; | ||||
| } | } | ||||
| /* | /* | ||||
| * In Intel's reference manual, the default value of EPP is 0x80u which | * In Intel's reference manual, the default value of EPP is 0x80u which | ||||
| * is the balanced mode. For consistency, we set the same value in AMD's | * is the balanced mode. For consistency, we set the same value in AMD's | ||||
| * CPPC driver. | * CPPC driver. | ||||
| */ | */ | ||||
| SET_BITS_VALUE(sc->req, AMD_CPPC_REQUEST_EPP_BITS, 0x80); | SET_BITS_VALUE(sc->cppc.request, AMD_CPPC_REQUEST_EPP_BITS, 0x80); | ||||
| SET_BITS_VALUE(sc->req, AMD_CPPC_REQUEST_MIN_PERF_BITS, | SET_BITS_VALUE(sc->cppc.request, AMD_CPPC_REQUEST_MIN_PERF_BITS, | ||||
| BITS_VALUE(AMD_CPPC_CAPS_1_LOWEST_PERF_BITS, caps)); | BITS_VALUE(AMD_CPPC_CAPS_1_LOWEST_PERF_BITS, caps)); | ||||
| SET_BITS_VALUE(sc->req, AMD_CPPC_REQUEST_MAX_PERF_BITS, | SET_BITS_VALUE(sc->cppc.request, AMD_CPPC_REQUEST_MAX_PERF_BITS, | ||||
| BITS_VALUE(AMD_CPPC_CAPS_1_HIGHEST_PERF_BITS, caps)); | BITS_VALUE(AMD_CPPC_CAPS_1_HIGHEST_PERF_BITS, caps)); | ||||
| /* enable autonomous mode by setting desired performance to 0 */ | /* enable autonomous mode by setting desired performance to 0 */ | ||||
| SET_BITS_VALUE(sc->req, AMD_CPPC_REQUEST_DES_PERF_BITS, 0); | SET_BITS_VALUE(sc->cppc.request, AMD_CPPC_REQUEST_DES_PERF_BITS, 0); | ||||
| ret = wrmsr_safe(MSR_AMD_CPPC_REQUEST, sc->req); | ret = wrmsr_safe(MSR_AMD_CPPC_REQUEST, sc->cppc.request); | ||||
| if (ret) { | if (ret) { | ||||
| device_printf(dev, "Failed to setup autonomous HWP for cpu%d\n", | device_printf(dev, "Failed to setup autonomous HWP for cpu%d\n", | ||||
| curcpu); | curcpu); | ||||
| req->res = ret; | req->res = ret; | ||||
| return; | return; | ||||
| } | } | ||||
| req->res = 0; | req->res = 0; | ||||
| } | } | ||||
| ▲ Show 20 Lines • Show All 288 Lines • Show Last 20 Lines | |||||