root/arch/i386/i386/mp_setperf.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. mp_setperf
  2. i386_setperf_ipi
  3. mp_setperf_init

    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 }

/* [<][>][^][v][top][bottom][index][help] */