* Used by the cpufreq core, this function will populate *level with the current * frequency as either determined by a cached value sc->curr_level, or in the * case the lower level driver has set the CPUFREQ_FLAG_UNCACHED flag, it will * obtain the frequency from the driver itself. */
| 452 | * obtain the frequency from the driver itself. |
| 453 | */ |
| 454 | static int |
| 455 | cf_get_method(device_t dev, struct cf_level *level) |
| 456 | { |
| 457 | struct cpufreq_softc *sc; |
| 458 | struct cf_level *levels; |
| 459 | struct cf_setting *curr_set; |
| 460 | struct pcpu *pc; |
| 461 | int bdiff, count, diff, error, i, type; |
| 462 | uint64_t rate; |
| 463 | |
| 464 | sc = device_get_softc(dev); |
| 465 | error = 0; |
| 466 | levels = NULL; |
| 467 | |
| 468 | /* |
| 469 | * If we already know the current frequency, and the driver didn't ask |
| 470 | * for uncached usage, we're done. |
| 471 | */ |
| 472 | CF_MTX_LOCK(&sc->lock); |
| 473 | curr_set = &sc->curr_level.total_set; |
| 474 | error = CPUFREQ_DRV_TYPE(sc->cf_drv_dev, &type); |
| 475 | if (error == 0 && (type & CPUFREQ_FLAG_UNCACHED)) { |
| 476 | struct cf_setting set; |
| 477 | |
| 478 | /* |
| 479 | * If the driver wants to always report back the real frequency, |
| 480 | * first try the driver and if that fails, fall back to |
| 481 | * estimating. |
| 482 | */ |
| 483 | if (CPUFREQ_DRV_GET(sc->cf_drv_dev, &set) == 0) { |
| 484 | sc->curr_level.total_set = set; |
| 485 | CF_DEBUG("get returning immediate freq %d\n", |
| 486 | curr_set->freq); |
| 487 | goto out; |
| 488 | } |
| 489 | } else if (curr_set->freq != CPUFREQ_VAL_UNKNOWN) { |
| 490 | CF_DEBUG("get returning known freq %d\n", curr_set->freq); |
| 491 | error = 0; |
| 492 | goto out; |
| 493 | } |
| 494 | CF_MTX_UNLOCK(&sc->lock); |
| 495 | |
| 496 | /* |
| 497 | * We need to figure out the current level. Loop through every |
| 498 | * driver, getting the current setting. Then, attempt to get a best |
| 499 | * match of settings against each level. |
| 500 | */ |
| 501 | count = CF_MAX_LEVELS; |
| 502 | levels = malloc(count * sizeof(*levels), M_TEMP, M_NOWAIT); |
| 503 | if (levels == NULL) |
| 504 | return (ENOMEM); |
| 505 | error = CPUFREQ_LEVELS(sc->dev, levels, &count); |
| 506 | if (error) { |
| 507 | if (error == E2BIG) |
| 508 | printf("cpufreq: need to increase CF_MAX_LEVELS\n"); |
| 509 | free(levels, M_TEMP); |
| 510 | return (error); |
| 511 | } |
nothing calls this directly
no test coverage detected