stable.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Sasha Levin <Alexander.Levin@microsoft.com>
To: "stable@vger.kernel.org" <stable@vger.kernel.org>,
	"linux-kernel@vger.kernel.org" <linux-kernel@vger.kernel.org>
Cc: Hans de Goede <hdegoede@redhat.com>,
	Linus Walleij <linus.walleij@linaro.org>,
	Sasha Levin <Alexander.Levin@microsoft.com>
Subject: [PATCH AUTOSEL 4.18 25/76] gpiolib-acpi: Register GpioInt ACPI event handlers from a late_initcall
Date: Mon, 24 Sep 2018 14:48:16 +0000	[thread overview]
Message-ID: <20180924144751.164410-25-alexander.levin@microsoft.com> (raw)
In-Reply-To: <20180924144751.164410-1-alexander.levin@microsoft.com>

From: Hans de Goede <hdegoede@redhat.com>

[ Upstream commit 78d3a92edbfb02e8cb83173cad84c3f2d5e1f070 ]

GpioInt ACPI event handlers may see there IRQ triggered immediately
after requesting the IRQ (esp. level triggered ones). This means that they
may run before any other (builtin) drivers have had a chance to register
their OpRegion handlers, leading to errors like this:

[    1.133274] ACPI Error: No handler for Region [PMOP] ((____ptrval____)) [UserDefinedRegion] (20180531/evregion-132)
[    1.133286] ACPI Error: Region UserDefinedRegion (ID=141) has no handler (20180531/exfldio-265)
[    1.133297] ACPI Error: Method parse/execution failed \_SB.GPO2._L01, AE_NOT_EXIST (20180531/psparse-516)

We already defer the manual initial trigger of edge triggered interrupts
by running it from a late_initcall handler, this commit replaces this with
deferring the entire acpi_gpiochip_request_interrupts() call till then,
fixing the problem of some OpRegions not being registered yet.

Note that this removes the need to have a list of edge triggered handlers
which need to run, since the entire acpi_gpiochip_request_interrupts() call
is now delayed, acpi_gpiochip_request_interrupt() can call these directly
now.

Acked-by: Mika Westerberg <mika.westerberg@linux.intel.com>
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
Signed-off-by: Sasha Levin <alexander.levin@microsoft.com>
---
 drivers/gpio/gpiolib-acpi.c | 84 +++++++++++++++++++++----------------
 1 file changed, 49 insertions(+), 35 deletions(-)

diff --git a/drivers/gpio/gpiolib-acpi.c b/drivers/gpio/gpiolib-acpi.c
index 7da51b5186c0..a3e43cacd78e 100644
--- a/drivers/gpio/gpiolib-acpi.c
+++ b/drivers/gpio/gpiolib-acpi.c
@@ -25,7 +25,6 @@
 
 struct acpi_gpio_event {
 	struct list_head node;
-	struct list_head initial_sync_list;
 	acpi_handle handle;
 	unsigned int pin;
 	unsigned int irq;
@@ -49,10 +48,19 @@ struct acpi_gpio_chip {
 	struct mutex conn_lock;
 	struct gpio_chip *chip;
 	struct list_head events;
+	struct list_head deferred_req_irqs_list_entry;
 };
 
-static LIST_HEAD(acpi_gpio_initial_sync_list);
-static DEFINE_MUTEX(acpi_gpio_initial_sync_list_lock);
+/*
+ * For gpiochips which call acpi_gpiochip_request_interrupts() before late_init
+ * (so builtin drivers) we register the ACPI GpioInt event handlers from a
+ * late_initcall_sync handler, so that other builtin drivers can register their
+ * OpRegions before the event handlers can run.  This list contains gpiochips
+ * for which the acpi_gpiochip_request_interrupts() has been deferred.
+ */
+static DEFINE_MUTEX(acpi_gpio_deferred_req_irqs_lock);
+static LIST_HEAD(acpi_gpio_deferred_req_irqs_list);
+static bool acpi_gpio_deferred_req_irqs_done;
 
 static int acpi_gpiochip_find(struct gpio_chip *gc, void *data)
 {
@@ -89,21 +97,6 @@ static struct gpio_desc *acpi_get_gpiod(char *path, int pin)
 	return gpiochip_get_desc(chip, pin);
 }
 
-static void acpi_gpio_add_to_initial_sync_list(struct acpi_gpio_event *event)
-{
-	mutex_lock(&acpi_gpio_initial_sync_list_lock);
-	list_add(&event->initial_sync_list, &acpi_gpio_initial_sync_list);
-	mutex_unlock(&acpi_gpio_initial_sync_list_lock);
-}
-
-static void acpi_gpio_del_from_initial_sync_list(struct acpi_gpio_event *event)
-{
-	mutex_lock(&acpi_gpio_initial_sync_list_lock);
-	if (!list_empty(&event->initial_sync_list))
-		list_del_init(&event->initial_sync_list);
-	mutex_unlock(&acpi_gpio_initial_sync_list_lock);
-}
-
 static irqreturn_t acpi_gpio_irq_handler(int irq, void *data)
 {
 	struct acpi_gpio_event *event = data;
@@ -229,7 +222,6 @@ static acpi_status acpi_gpiochip_request_interrupt(struct acpi_resource *ares,
 	event->irq = irq;
 	event->pin = pin;
 	event->desc = desc;
-	INIT_LIST_HEAD(&event->initial_sync_list);
 
 	ret = request_threaded_irq(event->irq, NULL, handler, irqflags,
 				   "ACPI:Event", event);
@@ -251,10 +243,9 @@ static acpi_status acpi_gpiochip_request_interrupt(struct acpi_resource *ares,
 	 * may refer to OperationRegions from other (builtin) drivers which
 	 * may be probed after us.
 	 */
-	if (handler == acpi_gpio_irq_handler &&
-	    (((irqflags & IRQF_TRIGGER_RISING) && value == 1) ||
-	     ((irqflags & IRQF_TRIGGER_FALLING) && value == 0)))
-		acpi_gpio_add_to_initial_sync_list(event);
+	if (((irqflags & IRQF_TRIGGER_RISING) && value == 1) ||
+	    ((irqflags & IRQF_TRIGGER_FALLING) && value == 0))
+		handler(event->irq, event);
 
 	return AE_OK;
 
@@ -283,6 +274,7 @@ void acpi_gpiochip_request_interrupts(struct gpio_chip *chip)
 	struct acpi_gpio_chip *acpi_gpio;
 	acpi_handle handle;
 	acpi_status status;
+	bool defer;
 
 	if (!chip->parent || !chip->to_irq)
 		return;
@@ -295,6 +287,16 @@ void acpi_gpiochip_request_interrupts(struct gpio_chip *chip)
 	if (ACPI_FAILURE(status))
 		return;
 
+	mutex_lock(&acpi_gpio_deferred_req_irqs_lock);
+	defer = !acpi_gpio_deferred_req_irqs_done;
+	if (defer)
+		list_add(&acpi_gpio->deferred_req_irqs_list_entry,
+			 &acpi_gpio_deferred_req_irqs_list);
+	mutex_unlock(&acpi_gpio_deferred_req_irqs_lock);
+
+	if (defer)
+		return;
+
 	acpi_walk_resources(handle, "_AEI",
 			    acpi_gpiochip_request_interrupt, acpi_gpio);
 }
@@ -325,11 +327,14 @@ void acpi_gpiochip_free_interrupts(struct gpio_chip *chip)
 	if (ACPI_FAILURE(status))
 		return;
 
+	mutex_lock(&acpi_gpio_deferred_req_irqs_lock);
+	if (!list_empty(&acpi_gpio->deferred_req_irqs_list_entry))
+		list_del_init(&acpi_gpio->deferred_req_irqs_list_entry);
+	mutex_unlock(&acpi_gpio_deferred_req_irqs_lock);
+
 	list_for_each_entry_safe_reverse(event, ep, &acpi_gpio->events, node) {
 		struct gpio_desc *desc;
 
-		acpi_gpio_del_from_initial_sync_list(event);
-
 		if (irqd_is_wakeup_set(irq_get_irq_data(event->irq)))
 			disable_irq_wake(event->irq);
 
@@ -1049,6 +1054,7 @@ void acpi_gpiochip_add(struct gpio_chip *chip)
 
 	acpi_gpio->chip = chip;
 	INIT_LIST_HEAD(&acpi_gpio->events);
+	INIT_LIST_HEAD(&acpi_gpio->deferred_req_irqs_list_entry);
 
 	status = acpi_attach_data(handle, acpi_gpio_chip_dh, acpi_gpio);
 	if (ACPI_FAILURE(status)) {
@@ -1195,20 +1201,28 @@ bool acpi_can_fallback_to_crs(struct acpi_device *adev, const char *con_id)
 	return con_id == NULL;
 }
 
-/* Sync the initial state of handlers after all builtin drivers have probed */
-static int acpi_gpio_initial_sync(void)
+/* Run deferred acpi_gpiochip_request_interrupts() */
+static int acpi_gpio_handle_deferred_request_interrupts(void)
 {
-	struct acpi_gpio_event *event, *ep;
+	struct acpi_gpio_chip *acpi_gpio, *tmp;
+
+	mutex_lock(&acpi_gpio_deferred_req_irqs_lock);
+	list_for_each_entry_safe(acpi_gpio, tmp,
+				 &acpi_gpio_deferred_req_irqs_list,
+				 deferred_req_irqs_list_entry) {
+		acpi_handle handle;
 
-	mutex_lock(&acpi_gpio_initial_sync_list_lock);
-	list_for_each_entry_safe(event, ep, &acpi_gpio_initial_sync_list,
-				 initial_sync_list) {
-		acpi_evaluate_object(event->handle, NULL, NULL, NULL);
-		list_del_init(&event->initial_sync_list);
+		handle = ACPI_HANDLE(acpi_gpio->chip->parent);
+		acpi_walk_resources(handle, "_AEI",
+				    acpi_gpiochip_request_interrupt, acpi_gpio);
+
+		list_del_init(&acpi_gpio->deferred_req_irqs_list_entry);
 	}
-	mutex_unlock(&acpi_gpio_initial_sync_list_lock);
+
+	acpi_gpio_deferred_req_irqs_done = true;
+	mutex_unlock(&acpi_gpio_deferred_req_irqs_lock);
 
 	return 0;
 }
 /* We must use _sync so that this runs after the first deferred_probe run */
-late_initcall_sync(acpi_gpio_initial_sync);
+late_initcall_sync(acpi_gpio_handle_deferred_request_interrupts);
-- 
2.17.1

  parent reply	other threads:[~2018-09-24 20:51 UTC|newest]

Thread overview: 75+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2018-09-24 14:48 [PATCH AUTOSEL 4.18 01/76] mac80211: Run TXQ teardown code before de-registering interfaces Sasha Levin
2018-09-24 14:48 ` [PATCH AUTOSEL 4.18 02/76] mac80211_hwsim: require at least one channel Sasha Levin
2018-09-24 14:48 ` [PATCH AUTOSEL 4.18 03/76] Btrfs: fix unexpected failure of nocow buffered writes after snapshotting when low on space Sasha Levin
2018-09-24 14:48 ` [PATCH AUTOSEL 4.18 04/76] KVM: PPC: Book3S HV: Don't truncate HPTE index in xlate function Sasha Levin
2018-09-24 14:48 ` [PATCH AUTOSEL 4.18 05/76] cfg80211: remove division by size of sizeof(struct ieee80211_wmm_rule) Sasha Levin
2018-09-24 14:48 ` [PATCH AUTOSEL 4.18 06/76] btrfs: btrfs_shrink_device should call commit transaction at the end Sasha Levin
2018-09-24 14:48 ` [PATCH AUTOSEL 4.18 08/76] scsi: csiostor: fix incorrect port capabilities Sasha Levin
2018-09-24 14:48 ` [PATCH AUTOSEL 4.18 07/76] scsi: csiostor: add a check for NULL pointer after kmalloc() Sasha Levin
2018-09-24 14:48 ` [PATCH AUTOSEL 4.18 09/76] scsi: libata: Add missing newline at end of file Sasha Levin
2018-09-24 14:48 ` [PATCH AUTOSEL 4.18 10/76] scsi: aacraid: fix a signedness bug Sasha Levin
2018-09-24 14:48 ` [PATCH AUTOSEL 4.18 11/76] bpf, sockmap: fix potential use after free in bpf_tcp_close Sasha Levin
2018-09-24 14:48 ` [PATCH AUTOSEL 4.18 13/76] bpf: sockmap, decrement copied count correctly in redirect error case Sasha Levin
2018-09-24 14:48 ` [PATCH AUTOSEL 4.18 12/76] bpf, sockmap: fix psock refcount leak in bpf_tcp_recvmsg Sasha Levin
2018-09-24 14:48 ` [PATCH AUTOSEL 4.18 15/76] mac80211_hwsim: correct use of IEEE80211_VHT_CAP_RXSTBC_X Sasha Levin
2018-09-24 14:48 ` [PATCH AUTOSEL 4.18 14/76] mac80211: " Sasha Levin
2018-09-24 14:48 ` [PATCH AUTOSEL 4.18 16/76] cfg80211: make wmm_rule part of the reg_rule structure Sasha Levin
2018-09-24 14:48 ` [PATCH AUTOSEL 4.18 17/76] mac80211_hwsim: Fix possible Spectre-v1 for hwsim_world_regdom_custom Sasha Levin
2018-09-24 14:48 ` [PATCH AUTOSEL 4.18 18/76] nl80211: Fix nla_put_u8 to u16 for NL80211_WMMR_TXOP Sasha Levin
2018-09-24 14:48 ` [PATCH AUTOSEL 4.18 19/76] nl80211: Pass center frequency in kHz instead of MHz Sasha Levin
2018-09-24 14:48 ` [PATCH AUTOSEL 4.18 20/76] bpf: fix several offset tests in bpf_msg_pull_data Sasha Levin
2018-09-24 14:48 ` [PATCH AUTOSEL 4.18 21/76] gpio: adp5588: Fix sleep-in-atomic-context bug Sasha Levin
2018-09-24 14:48 ` [PATCH AUTOSEL 4.18 23/76] mac80211: avoid kernel panic when building AMSDU from non-linear SKB Sasha Levin
2018-09-24 14:48 ` [PATCH AUTOSEL 4.18 22/76] mac80211: mesh: fix HWMP sequence numbering to follow standard Sasha Levin
2018-09-24 14:48 ` [PATCH AUTOSEL 4.18 24/76] gpiolib: acpi: Switch to cansleep version of GPIO library call Sasha Levin
2018-09-24 14:48 ` Sasha Levin [this message]
2018-09-24 14:48 ` [PATCH AUTOSEL 4.18 26/76] gpio: dwapb: Fix error handling in dwapb_gpio_probe() Sasha Levin
2018-09-24 14:48 ` [PATCH AUTOSEL 4.18 27/76] bpf: fix msg->data/data_end after sg shift repair in bpf_msg_pull_data Sasha Levin
2018-09-24 14:48 ` [PATCH AUTOSEL 4.18 29/76] bpf: fix sg shift repair start offset " Sasha Levin
2018-09-24 14:48 ` [PATCH AUTOSEL 4.18 28/76] bpf: fix shift upon scatterlist ring wrap-around " Sasha Levin
2018-09-24 14:48 ` [PATCH AUTOSEL 4.18 31/76] net: hns: add the code for cleaning pkt in chip Sasha Levin
2018-09-24 14:48 ` [PATCH AUTOSEL 4.18 32/76] net: hns: add netif_carrier_off before change speed and duplex Sasha Levin
2018-09-24 14:48 ` [PATCH AUTOSEL 4.18 33/76] sh_eth: Add R7S9210 support Sasha Levin
2018-09-24 14:48 ` [PATCH AUTOSEL 4.18 34/76] net: mvpp2: initialize port of_node pointer Sasha Levin
2018-09-24 14:48 ` [PATCH AUTOSEL 4.18 35/76] tc-testing: add test-cases for numeric and invalid control action Sasha Levin
2018-09-24 14:48 ` [PATCH AUTOSEL 4.18 36/76] cfg80211: nl80211_update_ft_ies() to validate NL80211_ATTR_IE Sasha Levin
2018-09-24 14:48 ` [PATCH AUTOSEL 4.18 37/76] mac80211: do not convert to A-MSDU if frag/subframe limited Sasha Levin
2018-09-24 14:48 ` [PATCH AUTOSEL 4.18 38/76] mac80211: always account for A-MSDU header changes Sasha Levin
2018-09-24 14:48 ` [PATCH AUTOSEL 4.18 39/76] tools/kvm_stat: fix python3 issues Sasha Levin
2018-09-24 14:48 ` [PATCH AUTOSEL 4.18 40/76] tools/kvm_stat: fix handling of invalid paths in debugfs provider Sasha Levin
2018-09-24 14:48 ` [PATCH AUTOSEL 4.18 41/76] tools/kvm_stat: fix updates for dead guests Sasha Levin
2018-09-24 14:48 ` [PATCH AUTOSEL 4.18 42/76] gpio: Fix crash due to registration race Sasha Levin
2018-09-24 14:48 ` [PATCH AUTOSEL 4.18 43/76] ARC: atomics: unbork atomic_fetch_##op() Sasha Levin
2018-09-24 14:48 ` [PATCH AUTOSEL 4.18 44/76] Revert "blk-throttle: fix race between blkcg_bio_issue_check() and cgroup_rmdir()" Sasha Levin
2018-09-24 14:48 ` [PATCH AUTOSEL 4.18 45/76] md/raid5-cache: disable reshape completely Sasha Levin
2018-09-24 14:48 ` [PATCH AUTOSEL 4.18 46/76] RAID10 BUG_ON in raise_barrier when force is true and conf->barrier is 0 Sasha Levin
2018-09-24 14:48 ` [PATCH AUTOSEL 4.18 47/76] selftests: pmtu: maximum MTU for vti4 is 2^16-1-20 Sasha Levin
2018-09-24 14:48 ` [PATCH AUTOSEL 4.18 49/76] ibmvnic: Include missing return code checks in reset function Sasha Levin
2018-09-24 14:48 ` [PATCH AUTOSEL 4.18 48/76] selftests: pmtu: detect correct binary to ping ipv6 addresses Sasha Levin
2018-09-24 14:48 ` [PATCH AUTOSEL 4.18 50/76] bpf: Fix bpf_msg_pull_data() Sasha Levin
2018-09-24 14:48 ` [PATCH AUTOSEL 4.18 51/76] bpf: avoid misuse of psock when TCP_ULP_BPF collides with another ULP Sasha Levin
2018-09-24 14:48 ` [PATCH AUTOSEL 4.18 52/76] net: ethernet: cpsw-phy-sel: prefer phandle for phy sel Sasha Levin
2018-09-24 14:48 ` [PATCH AUTOSEL 4.18 53/76] i2c: uniphier: issue STOP only for last message or I2C_M_STOP Sasha Levin
2018-09-24 14:48 ` [PATCH AUTOSEL 4.18 54/76] i2c: uniphier-f: " Sasha Levin
2018-09-24 14:48 ` [PATCH AUTOSEL 4.18 56/76] fs/cifs: don't translate SFM_SLASH (U+F026) to backslash Sasha Levin
2018-09-24 14:48 ` [PATCH AUTOSEL 4.18 55/76] net: cadence: Fix a sleep-in-atomic-context bug in macb_halt_tx() Sasha Levin
2018-09-24 14:48 ` [PATCH AUTOSEL 4.18 57/76] mac80211: fix an off-by-one issue in A-MSDU max_subframe computation Sasha Levin
2018-09-24 14:48 ` [PATCH AUTOSEL 4.18 58/76] cfg80211: fix a type issue in ieee80211_chandef_to_operating_class() Sasha Levin
2018-09-24 14:48 ` [PATCH AUTOSEL 4.18 60/76] mac80211: fix a race between restart and CSA flows Sasha Levin
2018-09-24 14:48 ` [PATCH AUTOSEL 4.18 59/76] mac80211: fix WMM TXOP calculation Sasha Levin
2018-09-24 14:48 ` [PATCH AUTOSEL 4.18 61/76] mac80211: Fix station bandwidth setting after channel switch Sasha Levin
2018-09-24 14:48 ` [PATCH AUTOSEL 4.18 62/76] mac80211: don't Tx a deauth frame if the AP forbade Tx Sasha Levin
2018-09-24 14:48 ` [PATCH AUTOSEL 4.18 64/76] fsnotify: fix ignore mask logic in fsnotify() Sasha Levin
2018-09-24 14:48 ` [PATCH AUTOSEL 4.18 63/76] mac80211: shorten the IBSS debug messages Sasha Levin
2018-09-24 14:48 ` [PATCH AUTOSEL 4.18 65/76] net/ibm/emac: wrong emac_calc_base call was used by typo Sasha Levin
2018-09-24 14:48 ` [PATCH AUTOSEL 4.18 66/76] nds32: fix logic for module Sasha Levin
2018-09-24 14:48 ` [PATCH AUTOSEL 4.18 67/76] nds32: add NULL entry to the end of_device_id array Sasha Levin
2018-09-24 14:48 ` [PATCH AUTOSEL 4.18 68/76] nds32: Fix empty call trace Sasha Levin
2018-09-24 14:48 ` [PATCH AUTOSEL 4.18 69/76] nds32: Fix get_user/put_user macro expand pointer problem Sasha Levin
2018-09-24 14:48 ` [PATCH AUTOSEL 4.18 70/76] nds32: fix build error because of wrong semicolon Sasha Levin
2018-09-24 14:48 ` [PATCH AUTOSEL 4.18 72/76] tools/vm/page-types.c: fix "defined but not used" warning Sasha Levin
2018-09-24 14:48 ` [PATCH AUTOSEL 4.18 71/76] tools/vm/slabinfo.c: fix sign-compare warning Sasha Levin
2018-09-24 14:48 ` [PATCH AUTOSEL 4.18 73/76] nds32: linker script: GCOV kernel may refers data in __exit Sasha Levin
2018-09-24 14:48 ` [PATCH AUTOSEL 4.18 74/76] ceph: avoid a use-after-free in ceph_destroy_options() Sasha Levin
2018-09-24 14:48 ` [PATCH AUTOSEL 4.18 75/76] firmware: arm_scmi: fix divide by zero when sustained_perf_level is zero Sasha Levin
2018-09-24 14:48 ` [PATCH AUTOSEL 4.18 76/76] afs: Fix cell specification to permit an empty address list Sasha Levin

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20180924144751.164410-25-alexander.levin@microsoft.com \
    --to=alexander.levin@microsoft.com \
    --cc=hdegoede@redhat.com \
    --cc=linus.walleij@linaro.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=stable@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).