kern_cpu.c (1196826af5daa03fe50b8225aa42b3f53d72a7ce) kern_cpu.c (67c8649f7fb5783bd325211ad1edaf06018fcb3e)
1/*-
2 * Copyright (c) 2004-2005 Nate Lawson (SDG)
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright

--- 48 unchanged lines hidden (view full) ---

57
58struct cpufreq_softc {
59 struct cf_level curr_level;
60 int curr_priority;
61 struct cf_level saved_level;
62 int saved_priority;
63 struct cf_level_lst all_levels;
64 int all_count;
1/*-
2 * Copyright (c) 2004-2005 Nate Lawson (SDG)
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright

--- 48 unchanged lines hidden (view full) ---

57
58struct cpufreq_softc {
59 struct cf_level curr_level;
60 int curr_priority;
61 struct cf_level saved_level;
62 int saved_priority;
63 struct cf_level_lst all_levels;
64 int all_count;
65 int max_mhz;
65 device_t dev;
66 struct sysctl_ctx_list sysctl_ctx;
67};
68
69struct cf_setting_array {
70 struct cf_setting sets[MAX_SETTINGS];
71 int count;
72 TAILQ_ENTRY(cf_setting_array) link;

--- 45 unchanged lines hidden (view full) ---

118
119 sc = device_get_softc(dev);
120 parent = device_get_parent(dev);
121 sc->dev = dev;
122 sysctl_ctx_init(&sc->sysctl_ctx);
123 TAILQ_INIT(&sc->all_levels);
124 sc->curr_level.total_set.freq = CPUFREQ_VAL_UNKNOWN;
125 sc->saved_level.total_set.freq = CPUFREQ_VAL_UNKNOWN;
66 device_t dev;
67 struct sysctl_ctx_list sysctl_ctx;
68};
69
70struct cf_setting_array {
71 struct cf_setting sets[MAX_SETTINGS];
72 int count;
73 TAILQ_ENTRY(cf_setting_array) link;

--- 45 unchanged lines hidden (view full) ---

119
120 sc = device_get_softc(dev);
121 parent = device_get_parent(dev);
122 sc->dev = dev;
123 sysctl_ctx_init(&sc->sysctl_ctx);
124 TAILQ_INIT(&sc->all_levels);
125 sc->curr_level.total_set.freq = CPUFREQ_VAL_UNKNOWN;
126 sc->saved_level.total_set.freq = CPUFREQ_VAL_UNKNOWN;
127 sc->max_mhz = CPUFREQ_VAL_UNKNOWN;
126
127 /*
128 * Only initialize one set of sysctls for all CPUs. In the future,
129 * if multiple CPUs can have different settings, we can move these
130 * sysctls to be under every CPU instead of just the first one.
131 */
132 numdevs = devclass_get_count(cpufreq_dc);
133 if (numdevs > 1)

--- 291 unchanged lines hidden (view full) ---

425 default:
426 error = EINVAL;
427 break;
428 }
429 if (error)
430 goto out;
431 }
432
128
129 /*
130 * Only initialize one set of sysctls for all CPUs. In the future,
131 * if multiple CPUs can have different settings, we can move these
132 * sysctls to be under every CPU instead of just the first one.
133 */
134 numdevs = devclass_get_count(cpufreq_dc);
135 if (numdevs > 1)

--- 291 unchanged lines hidden (view full) ---

427 default:
428 error = EINVAL;
429 break;
430 }
431 if (error)
432 goto out;
433 }
434
433 /* If there are no absolute levels, create a fake one at 100%. */
435 /*
436 * If there are no absolute levels, create a fake one at 100%. We
437 * then cache the clockrate for later use as our base frequency.
438 *
439 * XXX This assumes that the first time through, if we only have
440 * relative drivers, the CPU is currently running at 100%.
441 */
434 if (TAILQ_EMPTY(&sc->all_levels)) {
442 if (TAILQ_EMPTY(&sc->all_levels)) {
435 bzero(&sets[0], sizeof(*sets));
436 pc = cpu_get_pcpu(dev);
437 if (pc == NULL) {
438 error = ENXIO;
439 goto out;
443 if (sc->max_mhz == CPUFREQ_VAL_UNKNOWN) {
444 pc = cpu_get_pcpu(dev);
445 cpu_est_clockrate(pc->pc_cpuid, &rate);
446 sc->max_mhz = rate / 1000000;
440 }
447 }
441 cpu_est_clockrate(pc->pc_cpuid, &rate);
442 sets[0].freq = rate / 1000000;
448 memset(&sets[0], CPUFREQ_VAL_UNKNOWN, sizeof(*sets));
449 sets[0].freq = sc->max_mhz;
450 sets[0].dev = NULL;
443 error = cpufreq_insert_abs(sc, sets, 1);
444 if (error)
445 goto out;
446 }
447
448 /* Create a combined list of absolute + relative levels. */
449 TAILQ_FOREACH(set_arr, &rel_sets, link)
450 cpufreq_expand_set(sc, set_arr);

--- 281 unchanged lines hidden (view full) ---

732 free(levels, M_TEMP);
733 sbuf_delete(&sb);
734 return (error);
735}
736
737int
738cpufreq_register(device_t dev)
739{
451 error = cpufreq_insert_abs(sc, sets, 1);
452 if (error)
453 goto out;
454 }
455
456 /* Create a combined list of absolute + relative levels. */
457 TAILQ_FOREACH(set_arr, &rel_sets, link)
458 cpufreq_expand_set(sc, set_arr);

--- 281 unchanged lines hidden (view full) ---

740 free(levels, M_TEMP);
741 sbuf_delete(&sb);
742 return (error);
743}
744
745int
746cpufreq_register(device_t dev)
747{
748 struct cpufreq_softc *sc;
740 device_t cf_dev, cpu_dev;
741
742 /*
743 * Add only one cpufreq device to each CPU. Currently, all CPUs
744 * must offer the same levels and be switched at the same time.
745 */
746 cpu_dev = device_get_parent(dev);
749 device_t cf_dev, cpu_dev;
750
751 /*
752 * Add only one cpufreq device to each CPU. Currently, all CPUs
753 * must offer the same levels and be switched at the same time.
754 */
755 cpu_dev = device_get_parent(dev);
747 if (device_find_child(cpu_dev, "cpufreq", -1))
756 if ((cf_dev = device_find_child(cpu_dev, "cpufreq", -1))) {
757 sc = device_get_softc(cf_dev);
758 sc->max_mhz = CPUFREQ_VAL_UNKNOWN;
748 return (0);
759 return (0);
760 }
749
750 /* Add the child device and possibly sysctls. */
751 cf_dev = BUS_ADD_CHILD(cpu_dev, 0, "cpufreq", -1);
752 if (cf_dev == NULL)
753 return (ENOMEM);
754 device_quiet(cf_dev);
755
756 return (device_probe_and_attach(cf_dev));

--- 9 unchanged lines hidden (view full) ---

766 /*
767 * If this is the last cpufreq child device, remove the control
768 * device as well. We identify cpufreq children by calling a method
769 * they support.
770 */
771 error = device_get_children(device_get_parent(dev), &devs, &devcount);
772 if (error)
773 return (error);
761
762 /* Add the child device and possibly sysctls. */
763 cf_dev = BUS_ADD_CHILD(cpu_dev, 0, "cpufreq", -1);
764 if (cf_dev == NULL)
765 return (ENOMEM);
766 device_quiet(cf_dev);
767
768 return (device_probe_and_attach(cf_dev));

--- 9 unchanged lines hidden (view full) ---

778 /*
779 * If this is the last cpufreq child device, remove the control
780 * device as well. We identify cpufreq children by calling a method
781 * they support.
782 */
783 error = device_get_children(device_get_parent(dev), &devs, &devcount);
784 if (error)
785 return (error);
774 cf_dev = devclass_get_device(cpufreq_dc, 0);
786 cf_dev = device_find_child(device_get_parent(dev), "cpufreq", -1);
775 cfcount = 0;
776 for (i = 0; i < devcount; i++) {
777 if (!device_is_attached(devs[i]))
778 continue;
779 count = 1;
780 if (CPUFREQ_DRV_SETTINGS(devs[i], &set, &count, &type) == 0)
781 cfcount++;
782 }
783 if (cfcount <= 1)
784 device_delete_child(device_get_parent(cf_dev), cf_dev);
785 free(devs, M_TEMP);
786
787 return (0);
788}
787 cfcount = 0;
788 for (i = 0; i < devcount; i++) {
789 if (!device_is_attached(devs[i]))
790 continue;
791 count = 1;
792 if (CPUFREQ_DRV_SETTINGS(devs[i], &set, &count, &type) == 0)
793 cfcount++;
794 }
795 if (cfcount <= 1)
796 device_delete_child(device_get_parent(cf_dev), cf_dev);
797 free(devs, M_TEMP);
798
799 return (0);
800}