patch-2.4.0-prerelease linux/drivers/acpi/cpu.c

Next file: linux/drivers/acpi/dispatcher/Makefile
Previous file: linux/drivers/acpi/common/cmxface.c
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.4.0-test12/linux/drivers/acpi/cpu.c linux/drivers/acpi/cpu.c
@@ -37,55 +37,65 @@
 static int acpi_c2_tested = 0;
 static int acpi_c3_tested = 0;
 static int acpi_max_c_state = 1;
+static int acpi_pm_tmr_len;
 
 /*
  * Clear busmaster activity flag
  */
 static inline void
-acpi_clear_bm_activity(struct acpi_facp *facp)
+acpi_clear_bm_activity(void)
 {
-	acpi_write_pm1_status(facp, ACPI_BM);
+	acpi_hw_register_bit_access(ACPI_WRITE, ACPI_MTX_LOCK, BM_STS, 0);
 }
 
 /*
  * Returns 1 if there has been busmaster activity
  */
 static inline int
-acpi_bm_activity(struct acpi_facp *facp)
+acpi_bm_activity(void)
 {
-	return acpi_read_pm1_status(facp) & ACPI_BM;
+	return acpi_hw_register_bit_access(ACPI_READ, ACPI_MTX_LOCK, BM_STS);
 }
 
 /*
  * Set system to sleep through busmaster requests
  */
 static void
-acpi_sleep_on_busmaster(struct acpi_facp *facp)
+acpi_sleep_on_busmaster(void)
 {
-	u32 pm1_cntr = acpi_read_pm1_control(facp);
-	if (pm1_cntr & ACPI_BM_RLD) {
-		pm1_cntr &= ~ACPI_BM_RLD;
-		acpi_write_pm1_control(facp, pm1_cntr);
-	}
+	acpi_hw_register_bit_access (ACPI_WRITE, ACPI_MTX_LOCK, BM_RLD, 1);
 }
 
 /*
  * Set system to wake on busmaster requests
  */
 static void
-acpi_wake_on_busmaster(struct acpi_facp *facp)
+acpi_wake_on_busmaster(void)
 {
-	u32 pm1_cntr = acpi_read_pm1_control(facp);
-	if (!(pm1_cntr & ACPI_BM_RLD)) {
-		pm1_cntr |= ACPI_BM_RLD;
-		acpi_write_pm1_control(facp, pm1_cntr);
-	}
-	acpi_clear_bm_activity(facp);
+	acpi_hw_register_bit_access (ACPI_WRITE, ACPI_MTX_LOCK, BM_RLD, 0);
 }
 
-/* The ACPI timer is just the low 24 bits */
-#define TIME_BEGIN(tmr) inl(tmr)
-#define TIME_END(tmr, begin) ((inl(tmr) - (begin)) & 0x00ffffff)
+u32
+acpi_read_pm_timer(void)
+{
+	return acpi_hw_register_read(ACPI_MTX_LOCK, PM_TIMER);
+}
+
+/*
+ * Do a compare, accounting for 24/32bit rollover
+ */
+static u32
+acpi_compare_pm_timers(u32 first, u32 second)
+{
+	if (first < second) {
+		return (second - first);
+	} else {
+		if (acpi_pm_tmr_len == 24)
+			return (second + (0xFFFFFF - first));
+		else
+			return (second + (0xFFFFFFFF - first));
+	}
+}
 
 /*
  * Idle loop (uniprocessor only)
@@ -94,11 +104,11 @@
 acpi_idle(void)
 {
 	static int sleep_level = 1;
-	struct acpi_facp *facp = &acpi_facp;
+	FADT_DESCRIPTOR *fadt = &acpi_fadt;
 
-	if (!facp
-	    || facp->hdr.signature != ACPI_FACP_SIG
-	    || !facp->pm_tmr
+	if (!fadt
+	    || (STRNCMP(fadt->header.signature, ACPI_FADT_SIGNATURE, ACPI_SIG_LEN) != 0)
+	    || !fadt->Xpm_tmr_blk.address
 	    || !acpi_pblk)
 		goto not_initialized;
 
@@ -116,110 +126,108 @@
       sleep3:
 	sleep_level = 3;
 	if (!acpi_c3_tested) {
-		printk(KERN_DEBUG "ACPI C3 works\n");
+		DEBUG_PRINT(ACPI_INFO, ("C3 works\n"));
 		acpi_c3_tested = 1;
 	}
-	acpi_wake_on_busmaster(facp);
-	if (facp->pm2_cnt)
+	acpi_wake_on_busmaster();
+	if (fadt->Xpm2_cnt_blk.address)
 		goto sleep3_with_arbiter;
 
 	for (;;) {
 		unsigned long time;
-		unsigned int pm_tmr = facp->pm_tmr;
-
+		unsigned long diff;
+		
 		__cli();
 		if (current->need_resched)
 			goto out;
-		if (acpi_bm_activity(facp))
+		if (acpi_bm_activity())
 			goto sleep2;
 
-		time = TIME_BEGIN(pm_tmr);
+		time = acpi_read_pm_timer();
 		inb(acpi_pblk + ACPI_P_LVL3);
 		/* Dummy read, force synchronization with the PMU */
-		inl(pm_tmr);
-		time = TIME_END(pm_tmr, time);
+		acpi_read_pm_timer();
+		diff = acpi_compare_pm_timers(time, acpi_read_pm_timer());
 
 		__sti();
-		if (time < acpi_c3_exit_latency)
+		if (diff < acpi_c3_exit_latency)
 			goto sleep2;
 	}
 
       sleep3_with_arbiter:
 	for (;;) {
 		unsigned long time;
-		u8 arbiter;
-		unsigned int pm2_cntr = facp->pm2_cnt;
-		unsigned int pm_tmr = facp->pm_tmr;
+		unsigned long diff;
 
 		__cli();
 		if (current->need_resched)
 			goto out;
-		if (acpi_bm_activity(facp))
+		if (acpi_bm_activity())
 			goto sleep2;
 
-		time = TIME_BEGIN(pm_tmr);
-		arbiter = inb(pm2_cntr) & ~ACPI_ARB_DIS;
+		time = acpi_read_pm_timer();
+		
 		/* Disable arbiter, park on CPU */
-		outb(arbiter | ACPI_ARB_DIS, pm2_cntr);
+		acpi_hw_register_bit_access(ACPI_WRITE, ACPI_MTX_LOCK, ARB_DIS, 1);
 		inb(acpi_pblk + ACPI_P_LVL3);
 		/* Dummy read, force synchronization with the PMU */
-		inl(pm_tmr);
-		time = TIME_END(pm_tmr, time);
+		acpi_read_pm_timer();
+		diff = acpi_compare_pm_timers(time, acpi_read_pm_timer());
 		/* Enable arbiter again.. */
-		outb(arbiter, pm2_cntr);
+		acpi_hw_register_bit_access(ACPI_WRITE, ACPI_MTX_LOCK, ARB_DIS, 0);
 
 		__sti();
-		if (time < acpi_c3_exit_latency)
+		if (diff < acpi_c3_exit_latency)
 			goto sleep2;
 	}
 
       sleep2:
 	sleep_level = 2;
 	if (!acpi_c2_tested) {
-		printk(KERN_DEBUG "ACPI C2 works\n");
+		DEBUG_PRINT(ACPI_INFO, ("C2 works\n"));
 		acpi_c2_tested = 1;
 	}
-	acpi_wake_on_busmaster(facp);	/* Required to track BM activity.. */
+	acpi_wake_on_busmaster();	/* Required to track BM activity.. */
 	for (;;) {
 		unsigned long time;
-		unsigned int pm_tmr = facp->pm_tmr;
+		unsigned long diff;
 
 		__cli();
 		if (current->need_resched)
 			goto out;
 
-		time = TIME_BEGIN(pm_tmr);
+		time = acpi_read_pm_timer();
 		inb(acpi_pblk + ACPI_P_LVL2);
 		/* Dummy read, force synchronization with the PMU */
-		inl(pm_tmr);
-		time = TIME_END(pm_tmr, time);
+		acpi_read_pm_timer();
+		diff = acpi_compare_pm_timers(time, acpi_read_pm_timer());
 
 		__sti();
-		if (time < acpi_c2_exit_latency)
+		if (diff < acpi_c2_exit_latency)
 			goto sleep1;
-		if (acpi_bm_activity(facp)) {
-			acpi_clear_bm_activity(facp);
+		if (acpi_bm_activity()) {
+			acpi_clear_bm_activity();
 			continue;
 		}
-		if (time > acpi_c3_enter_latency
+		if (diff > acpi_c3_enter_latency
 		    && acpi_max_c_state >= 3)
 			goto sleep3;
 	}
 
       sleep1:
 	sleep_level = 1;
-	acpi_sleep_on_busmaster(facp);
+	acpi_sleep_on_busmaster();
 	for (;;) {
 		unsigned long time;
-		unsigned int pm_tmr = facp->pm_tmr;
+		unsigned long diff;
 
 		__cli();
 		if (current->need_resched)
 			goto out;
-		time = TIME_BEGIN(pm_tmr);
+		time = acpi_read_pm_timer();
 		safe_halt();
-		time = TIME_END(pm_tmr, time);
-		if (time > acpi_c2_enter_latency
+		diff = acpi_compare_pm_timers(time, acpi_read_pm_timer());
+		if (diff > acpi_c2_enter_latency
 		    && acpi_max_c_state >= 2)
 			goto sleep2;
 	}
@@ -240,7 +248,7 @@
  * Get processor information
  */
 static ACPI_STATUS
-acpi_find_cpu(ACPI_HANDLE handle, u32 level, void *ctx, void **value)
+acpi_found_cpu(ACPI_HANDLE handle, u32 level, void *ctx, void **value)
 {
 	ACPI_OBJECT obj;
 	ACPI_CX_STATE lat[4];
@@ -253,10 +261,11 @@
 	if (!ACPI_SUCCESS(acpi_evaluate_object(handle, NULL, NULL, &buf)))
 		return AE_OK;
 
-	printk(KERN_INFO "ACPI: PBLK %d @ 0x%04x:%d\n",
-	       obj.processor.proc_id,
-	       obj.processor.pblk_address,
-	       obj.processor.pblk_length);
+	DEBUG_PRINT(ACPI_INFO, ("PBLK %d @ 0x%04x:%d\n",
+			obj.processor.proc_id,
+			obj.processor.pblk_address,
+			obj.processor.pblk_length));
+
 	if (acpi_pblk != ACPI_INVALID
 	    || !obj.processor.pblk_address
 	    || obj.processor.pblk_length != 6)
@@ -270,19 +279,16 @@
 		return AE_OK;
 
 	if (lat[2].latency < MAX_CX_STATE_LATENCY) {
-		printk(KERN_INFO "ACPI: C2");
+		printk(KERN_INFO "ACPI: System firmware supports: C2");
 		acpi_c2_exit_latency = lat[2].latency;
 		acpi_max_c_state = 2;
 	
 		if (lat[3].latency < MAX_CX_STATE_LATENCY) {
-			printk(", C3 supported\n");
+			printk(" C3");
 			acpi_c3_exit_latency = lat[3].latency;
 			acpi_max_c_state = 3;
 		}
-		else {
-			printk(" supported\n");
-		}
-			
+		printk("\n");
 	}
 
 	memset(throttle, 0, sizeof(throttle));
@@ -296,9 +302,29 @@
 		if (throttle[i].percent_of_clock)
 			count++;
 	}
+
+	/* 0% throttled really doesn't count */
 	count--;
-	if (count > 0)
-		printk(KERN_INFO "ACPI: %d throttling states\n", count);
+
+	if (count > 0) {
+		DEBUG_PRINT(ACPI_INFO, ("%d throttling states\n", count));
+	}
+
+	return AE_OK;
+}
+
+static int
+acpi_pm_timer_init(void)
+{
+	FADT_DESCRIPTOR *fadt = &acpi_fadt;
+
+	if (fadt->tmr_val_ext) {
+		acpi_pm_tmr_len = 32;
+	} else {
+		acpi_pm_tmr_len = 24;
+	}
+
+	DEBUG_PRINT(ACPI_INFO, ("PM Timer width: %d bits\n", acpi_pm_tmr_len));
 
 	return AE_OK;
 }
@@ -309,9 +335,12 @@
 	acpi_walk_namespace(ACPI_TYPE_PROCESSOR,
 			    ACPI_ROOT_OBJECT,
 			    ACPI_UINT32_MAX,
-			    acpi_find_cpu,
+			    acpi_found_cpu,
 			    NULL,
 			    NULL);
+
+	acpi_pm_timer_init();
+
 
 #ifdef CONFIG_SMP
 	if (smp_num_cpus == 1)

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)