Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 23 Dec 2012 12:06:12 +0000 (UTC)
From:      Andriy Gapon <avg@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-8@freebsd.org
Subject:   svn commit: r244615 - stable/8/sys/dev/acpica
Message-ID:  <201212231206.qBNC6CBI088390@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: avg
Date: Sun Dec 23 12:06:12 2012
New Revision: 244615
URL: http://svnweb.freebsd.org/changeset/base/244615

Log:
  MFC r243760: acpi_cpu: change cpu_disable_idle to be a per-cpu flag

Modified:
  stable/8/sys/dev/acpica/acpi_cpu.c
Directory Properties:
  stable/8/sys/   (props changed)
  stable/8/sys/dev/   (props changed)
  stable/8/sys/dev/acpica/   (props changed)

Modified: stable/8/sys/dev/acpica/acpi_cpu.c
==============================================================================
--- stable/8/sys/dev/acpica/acpi_cpu.c	Sun Dec 23 12:06:00 2012	(r244614)
+++ stable/8/sys/dev/acpica/acpi_cpu.c	Sun Dec 23 12:06:12 2012	(r244615)
@@ -87,6 +87,7 @@ struct acpi_cpu_softc {
     struct sysctl_oid	*cpu_sysctl_tree;
     int			 cpu_cx_lowest;
     int			 cpu_cx_lowest_lim;
+    int			 cpu_disable_idle; /* Disable entry to idle function */
     char 		 cpu_cx_supported[64];
     int			 cpu_rid;
 };
@@ -134,9 +135,6 @@ static uint32_t		 cpu_smi_cmd;	/* Value 
 static uint8_t		 cpu_cst_cnt;	/* Indicate we are _CST aware. */
 static int		 cpu_quirks;	/* Indicate any hardware bugs. */
 
-/* Runtime state. */
-static int		 cpu_disable_idle; /* Disable entry to idle function */
-
 /* Values for sysctl. */
 static struct sysctl_ctx_list cpu_sysctl_ctx;
 static struct sysctl_oid *cpu_sysctl_tree;
@@ -415,6 +413,39 @@ acpi_cpu_postattach(void *unused __unuse
 SYSINIT(acpi_cpu, SI_SUB_CONFIGURE, SI_ORDER_MIDDLE,
     acpi_cpu_postattach, NULL);
 
+static void
+disable_idle(struct acpi_cpu_softc *sc)
+{
+    cpuset_t cpuset;
+
+    CPU_SETOF(sc->cpu_pcpu->pc_cpuid, &cpuset);
+    sc->cpu_disable_idle = TRUE;
+
+    /*
+     * Ensure that the CPU is not in idle state or in acpi_cpu_idle().
+     * Note that this code depends on the fact that the rendezvous IPI
+     * can not penetrate context where interrupts are disabled and acpi_cpu_idle
+     * is called and executed in such a context with interrupts being re-enabled
+     * right before return.
+     */
+    smp_rendezvous_cpus(cpuset, smp_no_rendevous_barrier, NULL,
+	smp_no_rendevous_barrier, NULL);
+}
+
+static void
+enable_idle(struct acpi_cpu_softc *sc)
+{
+
+    sc->cpu_disable_idle = FALSE;
+}
+
+static int
+is_idle_disabled(struct acpi_cpu_softc *sc)
+{
+
+    return (sc->cpu_disable_idle);
+}
+
 /*
  * Disable any entry to the idle function during suspend and re-enable it
  * during resume.
@@ -427,7 +458,7 @@ acpi_cpu_suspend(device_t dev)
     error = bus_generic_suspend(dev);
     if (error)
 	return (error);
-    cpu_disable_idle = TRUE;
+    disable_idle(device_get_softc(dev));
     return (0);
 }
 
@@ -435,7 +466,7 @@ static int
 acpi_cpu_resume(device_t dev)
 {
 
-    cpu_disable_idle = FALSE;
+    enable_idle(device_get_softc(dev));
     return (bus_generic_resume(dev));
 }
 
@@ -561,12 +592,14 @@ acpi_cpu_shutdown(device_t dev)
     bus_generic_shutdown(dev);
 
     /*
-     * Disable any entry to the idle function.  There is a small race where
-     * an idle thread have passed this check but not gone to sleep.  This
-     * is ok since device_shutdown() does not free the softc, otherwise
-     * we'd have to be sure all threads were evicted before returning.
+     * Disable any entry to the idle function.
+     */
+    disable_idle(device_get_softc(dev));
+
+    /*
+     * CPU devices are not truely detached and remain referenced,
+     * so their resources are not freed.
      */
-    cpu_disable_idle = TRUE;
 
     return_VALUE (0);
 }
@@ -847,7 +880,10 @@ acpi_cpu_startup(void *arg)
 
     /* Take over idling from cpu_idle_default(). */
     cpu_cx_lowest_lim = 0;
-    cpu_disable_idle = FALSE;
+    for (i = 0; i < cpu_ndevices; i++) {
+	sc = device_get_softc(cpu_devices[i]);
+	enable_idle(sc);
+    }
     cpu_idle_hook = acpi_cpu_idle;
 }
 
@@ -917,12 +953,6 @@ acpi_cpu_idle()
     uint32_t	start_time, end_time;
     int		bm_active, cx_next_idx, i;
 
-    /* If disabled, return immediately. */
-    if (cpu_disable_idle) {
-	ACPI_ENABLE_IRQS();
-	return;
-    }
-
     /*
      * Look up our CPU id to get our softc.  If it's NULL, we'll use C1
      * since there is no ACPI processor object for this CPU.  This occurs
@@ -934,6 +964,12 @@ acpi_cpu_idle()
 	return;
     }
 
+    /* If disabled, return immediately. */
+    if (is_idle_disabled(sc)) {
+	ACPI_ENABLE_IRQS();
+	return;
+    }
+
     /* Find the lowest state that has small enough latency. */
     cx_next_idx = 0;
     for (i = sc->cpu_cx_lowest; i >= 0; i--) {



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201212231206.qBNC6CBI088390>