Annotation of sys/arch/i386/i386/mp_setperf.c, Revision 1.1.1.1
1.1 nbrk 1: /* $OpenBSD: mp_setperf.c,v 1.2 2007/05/01 04:18:32 gwk Exp $ */
2: /*
3: * Copyright (c) 2007 Gordon Willem Klok <gwk@openbsd.org>
4: *
5: * Permission to use, copy, modify, and distribute this software for any
6: * purpose with or without fee is hereby granted, provided that the above
7: * copyright notice and this permission notice appear in all copies.
8: *
9: * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10: * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11: * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12: * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13: * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14: * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15: * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16: */
17:
18: #include <sys/param.h>
19: #include <sys/systm.h>
20: #include <sys/sysctl.h>
21: #include <sys/mutex.h>
22:
23: #include <machine/cpu.h>
24:
25: #include <machine/intr.h>
26:
27: struct mutex setperf_mp_mutex = MUTEX_INITIALIZER(IPL_HIGH);
28:
29: /* underlying setperf mechanism e.g. k8_powernow_setperf() */
30: void (*ul_setperf)(int);
31:
32: #define MP_SETPERF_STEADY 0 /* steady state - normal operation */
33: #define MP_SETPERF_INTRANSIT 1 /* in transition */
34: #define MP_SETPERF_PROCEED 2 /* proceed with transition */
35: #define MP_SETPERF_FINISH 3 /* return from IPI */
36:
37:
38: /* protected by setperf_mp_mutex */
39: volatile int mp_setperf_state = MP_SETPERF_STEADY;
40: volatile int mp_perflevel;
41:
42: void mp_setperf(int);
43:
44: void
45: mp_setperf(int level)
46: {
47: CPU_INFO_ITERATOR cii;
48: struct cpu_info *ci;
49: int notready, s;
50:
51: if (mp_setperf_state == MP_SETPERF_STEADY) {
52: mtx_enter(&setperf_mp_mutex);
53: mp_perflevel = level;
54:
55: curcpu()->ci_setperf_state = CI_SETPERF_INTRANSIT;
56: /* ask all other processors to drop what they are doing */
57: CPU_INFO_FOREACH(cii, ci) {
58: if (ci->ci_setperf_state != CI_SETPERF_INTRANSIT) {
59: ci->ci_setperf_state =
60: CI_SETPERF_SHOULDSTOP;
61: i386_send_ipi(ci, I386_IPI_SETPERF);
62: }
63: }
64:
65:
66: /* Loop until all processors report ready */
67: do {
68: CPU_INFO_FOREACH(cii, ci) {
69: if ((notready = (ci->ci_setperf_state
70: != CI_SETPERF_INTRANSIT)))
71: break;
72: }
73: } while (notready);
74:
75: mp_setperf_state = MP_SETPERF_PROCEED; /* release the hounds */
76:
77: s = splipi();
78:
79: ul_setperf(mp_perflevel);
80:
81: splx(s);
82:
83: curcpu()->ci_setperf_state = CI_SETPERF_DONE;
84: /* Loop until all processors report done */
85: do {
86: CPU_INFO_FOREACH(cii, ci) {
87: if ((notready = (ci->ci_setperf_state
88: != CI_SETPERF_DONE)))
89: break;
90: }
91: } while (notready);
92:
93: mp_setperf_state = MP_SETPERF_FINISH;
94: /* delay a little for potential straglers */
95: DELAY(2);
96: curcpu()->ci_setperf_state = CI_SETPERF_READY;
97: mp_setperf_state = MP_SETPERF_STEADY; /* restore normallity */
98: mtx_leave(&setperf_mp_mutex);
99: }
100:
101: }
102:
103: void
104: i386_setperf_ipi(struct cpu_info *ci)
105: {
106:
107: if (ci->ci_setperf_state == CI_SETPERF_SHOULDSTOP)
108: ci->ci_setperf_state = CI_SETPERF_INTRANSIT;
109:
110: while (mp_setperf_state != MP_SETPERF_PROCEED)
111: ;
112:
113: ul_setperf(mp_perflevel);
114:
115: ci->ci_setperf_state = CI_SETPERF_DONE;
116:
117: while (mp_setperf_state != MP_SETPERF_FINISH)
118: ;
119: ci->ci_setperf_state = CI_SETPERF_READY;
120: }
121:
122: void
123: mp_setperf_init()
124: {
125: CPU_INFO_ITERATOR cii;
126: struct cpu_info *ci;
127:
128:
129: if (!cpu_setperf)
130: return;
131: ul_setperf = cpu_setperf;
132:
133: cpu_setperf = mp_setperf;
134:
135: CPU_INFO_FOREACH(cii, ci) {
136: ci->ci_setperf_state = CI_SETPERF_READY;
137: }
138: mtx_init(&setperf_mp_mutex, IPL_HIGH);
139: }
CVSweb