summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLv Zheng <lv.zheng@intel.com>2016-08-04 04:43:39 -0400
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>2016-08-12 21:09:33 -0400
commit2af52c2bd20c50e80b121e15cd50a579e364485a (patch)
tree3bc9e680c4c65462569794ce2ce5c269d2767c38
parent9556ec4ec1d3575090f1f110c558169c5f0973a9 (diff)
ACPICA: Events: Introduce acpi_mask_gpe() to implement GPE masking mechanism
ACPICA commit 23a417ca406a527e7ae1710893e59a8b6db30e14 There is a facility in Linux, developers can control the enabling/disabling of a GPE via /sys/firmware/acpi/interrupts/gpexx. This is mainly for debugging purposes. But many users expect to use this facility to implement quirks to mask a specific GPE when there is a gap in Linux causing this GPE to flood. This is not working correctly because currently this facility invokes enabling/disabling counting based GPE driver APIs: acpi_enable_gpe()/acpi_disable_gpe() and the GPE drivers can still affect the count to mess up the GPE masking purposes. However, most of the IRQ chip designs allow masking/unmasking IRQs via a masking bit which is different from the enabled bit to achieve the same purpose. But the GPE hardware doesn't contain such a feature, this brings the trouble. In this patch, we introduce a software mechanism to implement the GPE masking feature, and acpi_mask_gpe() are provided to the OSPMs to mask/unmask GPEs in the above mentioned situation instead of acpi_enable_gpe()/acpi_disable_gpe(). ACPICA BZ 1102. Lv Zheng. Link: https://github.com/acpica/acpica/commit/23a417ca Link: https://bugs.acpica.org/show_bug.cgi?id=1102 Signed-off-by: Lv Zheng <lv.zheng@intel.com> Signed-off-by: Bob Moore <robert.moore@intel.com> Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
-rw-r--r--drivers/acpi/acpica/acevents.h3
-rw-r--r--drivers/acpi/acpica/aclocal.h2
-rw-r--r--drivers/acpi/acpica/evgpe.c57
-rw-r--r--drivers/acpi/acpica/evxfgpe.c43
-rw-r--r--drivers/acpi/acpica/hwgpe.c23
-rw-r--r--include/acpi/acpixf.h4
-rw-r--r--include/acpi/actypes.h39
7 files changed, 148 insertions, 23 deletions
diff --git a/drivers/acpi/acpica/acevents.h b/drivers/acpi/acpica/acevents.h
index 77af91cf46d4..92fa47c6498c 100644
--- a/drivers/acpi/acpica/acevents.h
+++ b/drivers/acpi/acpica/acevents.h
@@ -86,6 +86,9 @@ acpi_ev_update_gpe_enable_mask(struct acpi_gpe_event_info *gpe_event_info);
86acpi_status acpi_ev_enable_gpe(struct acpi_gpe_event_info *gpe_event_info); 86acpi_status acpi_ev_enable_gpe(struct acpi_gpe_event_info *gpe_event_info);
87 87
88acpi_status 88acpi_status
89acpi_ev_mask_gpe(struct acpi_gpe_event_info *gpe_event_info, u8 is_masked);
90
91acpi_status
89acpi_ev_add_gpe_reference(struct acpi_gpe_event_info *gpe_event_info); 92acpi_ev_add_gpe_reference(struct acpi_gpe_event_info *gpe_event_info);
90 93
91acpi_status 94acpi_status
diff --git a/drivers/acpi/acpica/aclocal.h b/drivers/acpi/acpica/aclocal.h
index 13331d70dea0..dff1207a6078 100644
--- a/drivers/acpi/acpica/aclocal.h
+++ b/drivers/acpi/acpica/aclocal.h
@@ -484,6 +484,7 @@ struct acpi_gpe_event_info {
484 u8 flags; /* Misc info about this GPE */ 484 u8 flags; /* Misc info about this GPE */
485 u8 gpe_number; /* This GPE */ 485 u8 gpe_number; /* This GPE */
486 u8 runtime_count; /* References to a run GPE */ 486 u8 runtime_count; /* References to a run GPE */
487 u8 disable_for_dispatch; /* Masked during dispatching */
487}; 488};
488 489
489/* Information about a GPE register pair, one per each status/enable pair in an array */ 490/* Information about a GPE register pair, one per each status/enable pair in an array */
@@ -494,6 +495,7 @@ struct acpi_gpe_register_info {
494 u16 base_gpe_number; /* Base GPE number for this register */ 495 u16 base_gpe_number; /* Base GPE number for this register */
495 u8 enable_for_wake; /* GPEs to keep enabled when sleeping */ 496 u8 enable_for_wake; /* GPEs to keep enabled when sleeping */
496 u8 enable_for_run; /* GPEs to keep enabled when running */ 497 u8 enable_for_run; /* GPEs to keep enabled when running */
498 u8 mask_for_run; /* GPEs to keep masked when running */
497 u8 enable_mask; /* Current mask of enabled GPEs */ 499 u8 enable_mask; /* Current mask of enabled GPEs */
498}; 500};
499 501
diff --git a/drivers/acpi/acpica/evgpe.c b/drivers/acpi/acpica/evgpe.c
index 4b4949ce05bc..bdb10bee13ce 100644
--- a/drivers/acpi/acpica/evgpe.c
+++ b/drivers/acpi/acpica/evgpe.c
@@ -130,6 +130,60 @@ acpi_status acpi_ev_enable_gpe(struct acpi_gpe_event_info *gpe_event_info)
130 130
131/******************************************************************************* 131/*******************************************************************************
132 * 132 *
133 * FUNCTION: acpi_ev_mask_gpe
134 *
135 * PARAMETERS: gpe_event_info - GPE to be blocked/unblocked
136 * is_masked - Whether the GPE is masked or not
137 *
138 * RETURN: Status
139 *
140 * DESCRIPTION: Unconditionally mask/unmask a GPE during runtime.
141 *
142 ******************************************************************************/
143
144acpi_status
145acpi_ev_mask_gpe(struct acpi_gpe_event_info *gpe_event_info, u8 is_masked)
146{
147 struct acpi_gpe_register_info *gpe_register_info;
148 u32 register_bit;
149
150 ACPI_FUNCTION_TRACE(ev_mask_gpe);
151
152 gpe_register_info = gpe_event_info->register_info;
153 if (!gpe_register_info) {
154 return_ACPI_STATUS(AE_NOT_EXIST);
155 }
156
157 register_bit = acpi_hw_get_gpe_register_bit(gpe_event_info);
158
159 /* Perform the action */
160
161 if (is_masked) {
162 if (register_bit & gpe_register_info->mask_for_run) {
163 return_ACPI_STATUS(AE_BAD_PARAMETER);
164 }
165
166 (void)acpi_hw_low_set_gpe(gpe_event_info, ACPI_GPE_DISABLE);
167 ACPI_SET_BIT(gpe_register_info->mask_for_run, (u8)register_bit);
168 } else {
169 if (!(register_bit & gpe_register_info->mask_for_run)) {
170 return_ACPI_STATUS(AE_BAD_PARAMETER);
171 }
172
173 ACPI_CLEAR_BIT(gpe_register_info->mask_for_run,
174 (u8)register_bit);
175 if (gpe_event_info->runtime_count
176 && !gpe_event_info->disable_for_dispatch) {
177 (void)acpi_hw_low_set_gpe(gpe_event_info,
178 ACPI_GPE_ENABLE);
179 }
180 }
181
182 return_ACPI_STATUS(AE_OK);
183}
184
185/*******************************************************************************
186 *
133 * FUNCTION: acpi_ev_add_gpe_reference 187 * FUNCTION: acpi_ev_add_gpe_reference
134 * 188 *
135 * PARAMETERS: gpe_event_info - Add a reference to this GPE 189 * PARAMETERS: gpe_event_info - Add a reference to this GPE
@@ -674,6 +728,7 @@ acpi_status acpi_ev_finish_gpe(struct acpi_gpe_event_info *gpe_event_info)
674 * in the event_info. 728 * in the event_info.
675 */ 729 */
676 (void)acpi_hw_low_set_gpe(gpe_event_info, ACPI_GPE_CONDITIONAL_ENABLE); 730 (void)acpi_hw_low_set_gpe(gpe_event_info, ACPI_GPE_CONDITIONAL_ENABLE);
731 gpe_event_info->disable_for_dispatch = FALSE;
677 return (AE_OK); 732 return (AE_OK);
678} 733}
679 734
@@ -737,6 +792,8 @@ acpi_ev_gpe_dispatch(struct acpi_namespace_node *gpe_device,
737 } 792 }
738 } 793 }
739 794
795 gpe_event_info->disable_for_dispatch = TRUE;
796
740 /* 797 /*
741 * Dispatch the GPE to either an installed handler or the control 798 * Dispatch the GPE to either an installed handler or the control
742 * method associated with this GPE (_Lxx or _Exx). If a handler 799 * method associated with this GPE (_Lxx or _Exx). If a handler
diff --git a/drivers/acpi/acpica/evxfgpe.c b/drivers/acpi/acpica/evxfgpe.c
index 17cfef721d00..d7a3b2775505 100644
--- a/drivers/acpi/acpica/evxfgpe.c
+++ b/drivers/acpi/acpica/evxfgpe.c
@@ -235,11 +235,13 @@ acpi_status acpi_set_gpe(acpi_handle gpe_device, u32 gpe_number, u8 action)
235 case ACPI_GPE_ENABLE: 235 case ACPI_GPE_ENABLE:
236 236
237 status = acpi_hw_low_set_gpe(gpe_event_info, ACPI_GPE_ENABLE); 237 status = acpi_hw_low_set_gpe(gpe_event_info, ACPI_GPE_ENABLE);
238 gpe_event_info->disable_for_dispatch = FALSE;
238 break; 239 break;
239 240
240 case ACPI_GPE_DISABLE: 241 case ACPI_GPE_DISABLE:
241 242
242 status = acpi_hw_low_set_gpe(gpe_event_info, ACPI_GPE_DISABLE); 243 status = acpi_hw_low_set_gpe(gpe_event_info, ACPI_GPE_DISABLE);
244 gpe_event_info->disable_for_dispatch = TRUE;
243 break; 245 break;
244 246
245 default: 247 default:
@@ -257,6 +259,47 @@ ACPI_EXPORT_SYMBOL(acpi_set_gpe)
257 259
258/******************************************************************************* 260/*******************************************************************************
259 * 261 *
262 * FUNCTION: acpi_mask_gpe
263 *
264 * PARAMETERS: gpe_device - Parent GPE Device. NULL for GPE0/GPE1
265 * gpe_number - GPE level within the GPE block
266 * is_masked - Whether the GPE is masked or not
267 *
268 * RETURN: Status
269 *
270 * DESCRIPTION: Unconditionally mask/unmask the an individual GPE, ex., to
271 * prevent a GPE flooding.
272 *
273 ******************************************************************************/
274acpi_status acpi_mask_gpe(acpi_handle gpe_device, u32 gpe_number, u8 is_masked)
275{
276 struct acpi_gpe_event_info *gpe_event_info;
277 acpi_status status;
278 acpi_cpu_flags flags;
279
280 ACPI_FUNCTION_TRACE(acpi_mask_gpe);
281
282 flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
283
284 /* Ensure that we have a valid GPE number */
285
286 gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number);
287 if (!gpe_event_info) {
288 status = AE_BAD_PARAMETER;
289 goto unlock_and_exit;
290 }
291
292 status = acpi_ev_mask_gpe(gpe_event_info, is_masked);
293
294unlock_and_exit:
295 acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
296 return_ACPI_STATUS(status);
297}
298
299ACPI_EXPORT_SYMBOL(acpi_mask_gpe)
300
301/*******************************************************************************
302 *
260 * FUNCTION: acpi_mark_gpe_for_wake 303 * FUNCTION: acpi_mark_gpe_for_wake
261 * 304 *
262 * PARAMETERS: gpe_device - Parent GPE Device. NULL for GPE0/GPE1 305 * PARAMETERS: gpe_device - Parent GPE Device. NULL for GPE0/GPE1
diff --git a/drivers/acpi/acpica/hwgpe.c b/drivers/acpi/acpica/hwgpe.c
index bdecd5e76e87..76b0e350f5bb 100644
--- a/drivers/acpi/acpica/hwgpe.c
+++ b/drivers/acpi/acpica/hwgpe.c
@@ -98,7 +98,7 @@ acpi_status
98acpi_hw_low_set_gpe(struct acpi_gpe_event_info *gpe_event_info, u32 action) 98acpi_hw_low_set_gpe(struct acpi_gpe_event_info *gpe_event_info, u32 action)
99{ 99{
100 struct acpi_gpe_register_info *gpe_register_info; 100 struct acpi_gpe_register_info *gpe_register_info;
101 acpi_status status; 101 acpi_status status = AE_OK;
102 u32 enable_mask; 102 u32 enable_mask;
103 u32 register_bit; 103 u32 register_bit;
104 104
@@ -148,9 +148,14 @@ acpi_hw_low_set_gpe(struct acpi_gpe_event_info *gpe_event_info, u32 action)
148 return (AE_BAD_PARAMETER); 148 return (AE_BAD_PARAMETER);
149 } 149 }
150 150
151 /* Write the updated enable mask */ 151 if (!(register_bit & gpe_register_info->mask_for_run)) {
152 152
153 status = acpi_hw_write(enable_mask, &gpe_register_info->enable_address); 153 /* Write the updated enable mask */
154
155 status =
156 acpi_hw_write(enable_mask,
157 &gpe_register_info->enable_address);
158 }
154 return (status); 159 return (status);
155} 160}
156 161
@@ -242,6 +247,12 @@ acpi_hw_get_gpe_status(struct acpi_gpe_event_info *gpe_event_info,
242 local_event_status |= ACPI_EVENT_FLAG_ENABLED; 247 local_event_status |= ACPI_EVENT_FLAG_ENABLED;
243 } 248 }
244 249
250 /* GPE currently masked? (masked for runtime?) */
251
252 if (register_bit & gpe_register_info->mask_for_run) {
253 local_event_status |= ACPI_EVENT_FLAG_MASKED;
254 }
255
245 /* GPE enabled for wake? */ 256 /* GPE enabled for wake? */
246 257
247 if (register_bit & gpe_register_info->enable_for_wake) { 258 if (register_bit & gpe_register_info->enable_for_wake) {
@@ -397,6 +408,7 @@ acpi_hw_enable_runtime_gpe_block(struct acpi_gpe_xrupt_info *gpe_xrupt_info,
397 u32 i; 408 u32 i;
398 acpi_status status; 409 acpi_status status;
399 struct acpi_gpe_register_info *gpe_register_info; 410 struct acpi_gpe_register_info *gpe_register_info;
411 u8 enable_mask;
400 412
401 /* NOTE: assumes that all GPEs are currently disabled */ 413 /* NOTE: assumes that all GPEs are currently disabled */
402 414
@@ -410,9 +422,10 @@ acpi_hw_enable_runtime_gpe_block(struct acpi_gpe_xrupt_info *gpe_xrupt_info,
410 422
411 /* Enable all "runtime" GPEs in this register */ 423 /* Enable all "runtime" GPEs in this register */
412 424
425 enable_mask = gpe_register_info->enable_for_run &
426 ~gpe_register_info->mask_for_run;
413 status = 427 status =
414 acpi_hw_gpe_enable_write(gpe_register_info->enable_for_run, 428 acpi_hw_gpe_enable_write(enable_mask, gpe_register_info);
415 gpe_register_info);
416 if (ACPI_FAILURE(status)) { 429 if (ACPI_FAILURE(status)) {
417 return (status); 430 return (status);
418 } 431 }
diff --git a/include/acpi/acpixf.h b/include/acpi/acpixf.h
index 875964dea539..c2d4b9c9f8a4 100644
--- a/include/acpi/acpixf.h
+++ b/include/acpi/acpixf.h
@@ -736,6 +736,10 @@ ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status
736 u32 gpe_number)) 736 u32 gpe_number))
737 737
738ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status 738ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status
739 acpi_mask_gpe(acpi_handle gpe_device,
740 u32 gpe_number, u8 is_masked))
741
742ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status
739 acpi_mark_gpe_for_wake(acpi_handle gpe_device, 743 acpi_mark_gpe_for_wake(acpi_handle gpe_device,
740 u32 gpe_number)) 744 u32 gpe_number))
741 745
diff --git a/include/acpi/actypes.h b/include/acpi/actypes.h
index cb389efd321c..fa4bd6ad5d24 100644
--- a/include/acpi/actypes.h
+++ b/include/acpi/actypes.h
@@ -732,16 +732,17 @@ typedef u32 acpi_event_type;
732 * The encoding of acpi_event_status is illustrated below. 732 * The encoding of acpi_event_status is illustrated below.
733 * Note that a set bit (1) indicates the property is TRUE 733 * Note that a set bit (1) indicates the property is TRUE
734 * (e.g. if bit 0 is set then the event is enabled). 734 * (e.g. if bit 0 is set then the event is enabled).
735 * +-------------+-+-+-+-+-+ 735 * +-------------+-+-+-+-+-+-+
736 * | Bits 31:5 |4|3|2|1|0| 736 * | Bits 31:6 |5|4|3|2|1|0|
737 * +-------------+-+-+-+-+-+ 737 * +-------------+-+-+-+-+-+-+
738 * | | | | | | 738 * | | | | | | |
739 * | | | | | +- Enabled? 739 * | | | | | | +- Enabled?
740 * | | | | +--- Enabled for wake? 740 * | | | | | +--- Enabled for wake?
741 * | | | +----- Status bit set? 741 * | | | | +----- Status bit set?
742 * | | +------- Enable bit set? 742 * | | | +------- Enable bit set?
743 * | +--------- Has a handler? 743 * | | +--------- Has a handler?
744 * +--------------- <Reserved> 744 * | +----------- Masked?
745 * +----------------- <Reserved>
745 */ 746 */
746typedef u32 acpi_event_status; 747typedef u32 acpi_event_status;
747 748
@@ -751,6 +752,7 @@ typedef u32 acpi_event_status;
751#define ACPI_EVENT_FLAG_STATUS_SET (acpi_event_status) 0x04 752#define ACPI_EVENT_FLAG_STATUS_SET (acpi_event_status) 0x04
752#define ACPI_EVENT_FLAG_ENABLE_SET (acpi_event_status) 0x08 753#define ACPI_EVENT_FLAG_ENABLE_SET (acpi_event_status) 0x08
753#define ACPI_EVENT_FLAG_HAS_HANDLER (acpi_event_status) 0x10 754#define ACPI_EVENT_FLAG_HAS_HANDLER (acpi_event_status) 0x10
755#define ACPI_EVENT_FLAG_MASKED (acpi_event_status) 0x20
754#define ACPI_EVENT_FLAG_SET ACPI_EVENT_FLAG_STATUS_SET 756#define ACPI_EVENT_FLAG_SET ACPI_EVENT_FLAG_STATUS_SET
755 757
756/* Actions for acpi_set_gpe, acpi_gpe_wakeup, acpi_hw_low_set_gpe */ 758/* Actions for acpi_set_gpe, acpi_gpe_wakeup, acpi_hw_low_set_gpe */
@@ -761,14 +763,15 @@ typedef u32 acpi_event_status;
761 763
762/* 764/*
763 * GPE info flags - Per GPE 765 * GPE info flags - Per GPE
764 * +-------+-+-+---+ 766 * +---+-+-+-+---+
765 * | 7:5 |4|3|2:0| 767 * |7:6|5|4|3|2:0|
766 * +-------+-+-+---+ 768 * +---+-+-+-+---+
767 * | | | | 769 * | | | | |
768 * | | | +-- Type of dispatch:to method, handler, notify, or none 770 * | | | | +-- Type of dispatch:to method, handler, notify, or none
769 * | | +----- Interrupt type: edge or level triggered 771 * | | | +----- Interrupt type: edge or level triggered
770 * | +------- Is a Wake GPE 772 * | | +------- Is a Wake GPE
771 * +------------ <Reserved> 773 * | +--------- Is GPE masked by the software GPE masking machanism
774 * +------------ <Reserved>
772 */ 775 */
773#define ACPI_GPE_DISPATCH_NONE (u8) 0x00 776#define ACPI_GPE_DISPATCH_NONE (u8) 0x00
774#define ACPI_GPE_DISPATCH_METHOD (u8) 0x01 777#define ACPI_GPE_DISPATCH_METHOD (u8) 0x01