lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <201005282247.43261.rjw@sisk.pl>
Date:	Fri, 28 May 2010 22:47:43 +0200
From:	"Rafael J. Wysocki" <rjw@...k.pl>
To:	Len Brown <lenb@...nel.org>
Cc:	ACPI Devel Maling List <linux-acpi@...r.kernel.org>,
	LKML <linux-kernel@...r.kernel.org>,
	Matthew Garrett <mjg59@...f.ucam.org>,
	"Moore, Robert" <robert.moore@...el.com>
Subject: [PATCH 2/2] ACPI / ACPICA: Allow GPEs to be force disabled via sysfs

After the GPE reference counting patches (commits
9630bdd9b15d2f489c646d8bc04b60e53eb5ec78 and
cbbc0de700e61d0cdc854d435dbc2ef148de0e00), the sysfs interface
allowing user space to disable/enable GPEs doesn't work correctly,
because a GPE disabled this way may be re-enabled shortly by
acpi_ev_asynch_enable_gpe() if its bit is set in its register's
enable_for_run mask.

To fix this, introduce two new action values for acpi_set_gpe(),
ACPI_GPE_FORCE_ENABLE and ACPI_GPE_FORCE_DISABLE, such that if
acpi_set_gpe() is called with ACPI_GPE_FORCE_DISABLE, the GPE is
force disabled and can only be re-enabled by calling acpi_set_gpe()
with ACPI_GPE_FORCE_ENABLE.  Use these new values in the sysfs
interface for disabling/enabling GPEs.

Signed-off-by: Rafael J. Wysocki <rjw@...k.pl>
---
 drivers/acpi/acpica/evgpe.c    |    5 ++++-
 drivers/acpi/acpica/evxfevnt.c |   24 ++++++++++++++++++++++++
 drivers/acpi/system.c          |    6 ++++--
 include/acpi/actypes.h         |   19 ++++++++++++-------
 4 files changed, 44 insertions(+), 10 deletions(-)

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);

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ