diff mbox

[2/2] ACPI / ACPICA: Allow GPEs to be force disabled via sysfs

Message ID 201005282247.43261.rjw@sisk.pl (mailing list archive)
State New, archived
Headers show

Commit Message

Rafael Wysocki May 28, 2010, 8:47 p.m. UTC
None
diff mbox

Patch

Index: linux-2.6/include/acpi/actypes.h
===================================================================
--- linux-2.6.orig/include/acpi/actypes.h
+++ linux-2.6/include/acpi/actypes.h
@@ -668,6 +668,8 @@  typedef u32 acpi_event_status;
 #define ACPI_GPE_ENABLE                 0
 #define ACPI_GPE_DISABLE                1
 #define ACPI_GPE_CHECK_AND_ENABLE       2
+#define ACPI_GPE_FORCE_ENABLE           3
+#define ACPI_GPE_FORCE_DISABLE          4
 
 /* gpe_types for acpi_enable_gpe and acpi_disable_gpe */
 
@@ -677,13 +679,14 @@  typedef u32 acpi_event_status;
 
 /*
  * GPE info flags - Per GPE
- * +-------+---+-+-+
- * |  7:4  |3:2|1|0|
- * +-------+---+-+-+
- *     |     |  | |
- *     |     |  | +--- Interrupt type: edge or level triggered
- *     |     |  +----- GPE can wake the system
- *     |     +-------- Type of dispatch:to method, handler, or none
+ * +-------+-+---+-+-+
+ * |  7:5  |4|3:2|1|0|
+ * +-------+-+---+-+-+
+ *     |    |  |  | |
+ *     |    |  |  | +--- Interrupt type: edge or level triggered
+ *     |    |  |  +----- GPE can wake the system
+ *     |    |  +-------- Type of dispatch:to method, handler, or none
+ *     |    +----------- GPE has been forcibly disabled
  *     +-------------- <Reserved>
  */
 #define ACPI_GPE_XRUPT_TYPE_MASK        (u8) 0x01
@@ -697,6 +700,8 @@  typedef u32 acpi_event_status;
 #define ACPI_GPE_DISPATCH_METHOD        (u8) 0x08
 #define ACPI_GPE_DISPATCH_NOT_USED      (u8) 0x00
 
+#define ACPI_GPE_FORCE_DISABLED		(u8) 0x10
+
 /*
  * Flags for GPE and Lock interfaces
  */
Index: linux-2.6/drivers/acpi/acpica/evgpe.c
===================================================================
--- linux-2.6.orig/drivers/acpi/acpica/evgpe.c
+++ linux-2.6/drivers/acpi/acpica/evgpe.c
@@ -417,7 +417,10 @@  static void acpi_ev_asynch_enable_gpe(vo
 	}
 
 	/* Enable this GPE */
-	(void)acpi_hw_low_set_gpe(gpe_event_info, ACPI_GPE_CHECK_AND_ENABLE);
+	if (!(gpe_event_info->flags & ACPI_GPE_FORCE_DISABLED)) {
+		(void)acpi_hw_low_set_gpe(gpe_event_info,
+					  ACPI_GPE_CHECK_AND_ENABLE);
+	}
 	return_VOID;
 }
 
Index: linux-2.6/drivers/acpi/acpica/evxfevnt.c
===================================================================
--- linux-2.6.orig/drivers/acpi/acpica/evxfevnt.c
+++ linux-2.6/drivers/acpi/acpica/evxfevnt.c
@@ -281,10 +281,24 @@  acpi_status acpi_set_gpe(acpi_handle gpe
 		status = acpi_clear_and_enable_gpe(gpe_event_info);
 		break;
 
+	case ACPI_GPE_FORCE_ENABLE:
+		status = acpi_clear_and_enable_gpe(gpe_event_info);
+		if (ACPI_SUCCESS(status)) {
+			gpe_event_info->flags &= ~(ACPI_GPE_FORCE_DISABLED);
+		}
+		break;
+
 	case ACPI_GPE_DISABLE:
 		status = acpi_hw_low_set_gpe(gpe_event_info, ACPI_GPE_DISABLE);
 		break;
 
+	case ACPI_GPE_FORCE_DISABLE:
+		status = acpi_hw_low_set_gpe(gpe_event_info, ACPI_GPE_DISABLE);
+		if (ACPI_SUCCESS(status)) {
+			gpe_event_info->flags |= ACPI_GPE_FORCE_DISABLED;
+		}
+		break;
+
 	default:
 		status = AE_BAD_PARAMETER;
 		break;
@@ -337,6 +351,11 @@  acpi_status acpi_enable_gpe(acpi_handle 
 		goto unlock_and_exit;
 	}
 
+	if (gpe_event_info->flags & ACPI_GPE_FORCE_DISABLED) {
+		status = AE_ERROR;
+		goto unlock_and_exit;
+	}
+
 	if (gpe_type & ACPI_GPE_TYPE_RUNTIME) {
 		if (gpe_event_info->runtime_count == ACPI_UINT8_MAX) {
 			status = AE_LIMIT;	/* Too many references */
@@ -426,6 +445,11 @@  acpi_status acpi_disable_gpe(acpi_handle
 		goto unlock_and_exit;
 	}
 
+	if (gpe_event_info->flags & ACPI_GPE_FORCE_DISABLED) {
+		status = AE_ERROR;
+		goto unlock_and_exit;
+	}
+
 	/* Hardware-disable a runtime GPE on removal of the last reference */
 
 	if (gpe_type & ACPI_GPE_TYPE_RUNTIME) {
Index: linux-2.6/drivers/acpi/system.c
===================================================================
--- linux-2.6.orig/drivers/acpi/system.c
+++ linux-2.6/drivers/acpi/system.c
@@ -388,10 +388,12 @@  static ssize_t counter_set(struct kobjec
 	if (index < num_gpes) {
 		if (!strcmp(buf, "disable\n") &&
 				(status & ACPI_EVENT_FLAG_ENABLED))
-			result = acpi_set_gpe(handle, index, ACPI_GPE_DISABLE);
+			result = acpi_set_gpe(handle, index,
+						ACPI_GPE_FORCE_DISABLE);
 		else if (!strcmp(buf, "enable\n") &&
 				!(status & ACPI_EVENT_FLAG_ENABLED))
-			result = acpi_set_gpe(handle, index, ACPI_GPE_ENABLE);
+			result = acpi_set_gpe(handle, index,
+						ACPI_GPE_FORCE_ENABLE);
 		else if (!strcmp(buf, "clear\n") &&
 				(status & ACPI_EVENT_FLAG_SET))
 			result = acpi_clear_gpe(handle, index);