Received: by 2002:ac0:a5a6:0:0:0:0:0 with SMTP id m35-v6csp1828368imm; Mon, 3 Sep 2018 10:29:05 -0700 (PDT) X-Google-Smtp-Source: ANB0VdbfExGoozaGtJhBcS/KCw8WNs7I1RROJ2Pvx2k4zfTVUDPnR6AA5+IS8IAGeYzPp7gqoa90 X-Received: by 2002:a62:83ca:: with SMTP id h193-v6mr30491163pfe.123.1535995745418; Mon, 03 Sep 2018 10:29:05 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1535995745; cv=none; d=google.com; s=arc-20160816; b=RMswe+6Hll4EEG/uVXT55tYvO0c+catII09Kdq2vU2cvWYh/tGa/GFsVxhwhVfDGc6 MiUBTZJ3VQWqmrpm69Sycc+3K7mGoIA6qnnZK3c6l6ajhLdReVWWFl134r6op32xqgSL jr9SDXYT1ijcIexBGftiXpIIJwLpNkMY4apQJM04EdWOuLuGSj7IWITnBl5HibVHRq39 K856tGOnfDBMIKN6XCf0mX/8CAPCCbkErv9M2WMcXMNgWxP+t3fFjCSrsXjolf6lOxk+ fjlmuuGIqfqf/id8IRdzktwbX/YdEw29fXzw4dy1zP8qC5k1gk593sBzyr+K0O4ANO9z FZjQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:mime-version:user-agent:references :in-reply-to:message-id:date:subject:cc:to:from :arc-authentication-results; bh=HOUWLzt6X5FOB2EUSrd9CIHs2avmn8cT6RO3Fb2Wrw8=; b=sFElHJA6/uHQwaTs+wiYUxlh/VcuFiMhCtTkvmnbddSzsgj85tl2vRSLLfO3wJ/DeA arP+HBgAxQerNGSU8OaMg8OrE6emoSf4H2RlDB4ZBXNPIsPO8reDZsCZ3yGeKXJZlZb4 tbmxq84iPrbzMFircnoMZPjzeUe8IX5pe33ohcIbDEqHkXb6byreb8d2kcZvI8VI3cXV 5IX4qV4fgai4hvBY+d/tOd5UBJgWAO0gqjk+uncuIverrHRd/ndjsV1vQvu1IZ85Ox46 pniOmzMJsLj2sfNPHxSkx0+DWvix8VPhMdb8bb0OZKepRh3Eo66/GCGR6ieSFzOqeOEz kXMw== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id t9-v6si18030884pgr.244.2018.09.03.10.28.50; Mon, 03 Sep 2018 10:29:05 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1730971AbeICVsS (ORCPT + 99 others); Mon, 3 Sep 2018 17:48:18 -0400 Received: from mail.linuxfoundation.org ([140.211.169.12]:46106 "EHLO mail.linuxfoundation.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1730923AbeICVsR (ORCPT ); Mon, 3 Sep 2018 17:48:17 -0400 Received: from localhost (ip-213-127-74-90.ip.prioritytelecom.net [213.127.74.90]) by mail.linuxfoundation.org (Postfix) with ESMTPSA id 05EFBD09; Mon, 3 Sep 2018 17:19:28 +0000 (UTC) From: Greg Kroah-Hartman To: linux-kernel@vger.kernel.org Cc: Greg Kroah-Hartman , stable@vger.kernel.org, Benjamin Tissoires , Hans de Goede , Andy Shevchenko , Mika Westerberg , Linus Walleij , Sasha Levin Subject: [PATCH 4.14 077/165] gpiolib-acpi: make sure we trigger edge events at least once on boot Date: Mon, 3 Sep 2018 18:56:03 +0200 Message-Id: <20180903165658.957028042@linuxfoundation.org> X-Mailer: git-send-email 2.18.0 In-Reply-To: <20180903165655.003605184@linuxfoundation.org> References: <20180903165655.003605184@linuxfoundation.org> User-Agent: quilt/0.65 X-stable: review MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org 4.14-stable review patch. If anyone has any objections, please let me know. ------------------ From: Benjamin Tissoires [ Upstream commit ca876c7483b697b498868b1f575997191b077885 ] On some systems using edge triggered ACPI Event Interrupts, the initial state at boot is not setup by the firmware, instead relying on the edge irq event handler running at least once to setup the initial state. 2 known examples of this are: 1) The Surface 3 has its _LID state controlled by an ACPI operation region triggered by a GPIO event: OperationRegion (GPOR, GeneralPurposeIo, Zero, One) Field (GPOR, ByteAcc, NoLock, Preserve) { Connection ( GpioIo (Shared, PullNone, 0x0000, 0x0000, IoRestrictionNone, "\\_SB.GPO0", 0x00, ResourceConsumer, , ) { // Pin list 0x004C } ), HELD, 1 } Method (_E4C, 0, Serialized) // _Exx: Edge-Triggered GPE { If ((HELD == One)) { ^^LID.LIDB = One } Else { ^^LID.LIDB = Zero Notify (LID, 0x80) // Status Change } Notify (^^PCI0.SPI1.NTRG, One) // Device Check } Currently, the state of LIDB is wrong until the user actually closes or open the cover. We need to trigger the GPIO event once to update the internal ACPI state. Coincidentally, this also enables the Surface 2 integrated HID sensor hub which also requires an ACPI gpio operation region to start initialization. 2) Various Bay Trail based tablets come with an external USB mux and TI T1210B USB phy to enable USB gadget mode. The mux is controlled by a GPIO which is controlled by an edge triggered ACPI Event Interrupt which monitors the micro-USB ID pin. When the tablet is connected to a PC (or no cable is plugged in), the ID pin is high and the tablet should be in gadget mode. But the GPIO controlling the mux is initialized by the firmware so that the USB data lines are muxed to the host controller. This means that if the user wants to use gadget mode, the user needs to first plug in a host-cable to force the ID pin low and then unplug it and connect the tablet to a PC, to get the ACPI event handler to run and switch the mux to device mode, This commit fixes both by running the event-handler once on boot. Note that the running of the event-handler is done from a late_initcall, this is done because the handler AML code may rely on OperationRegions registered by other builtin drivers. This avoids errors like these: [ 0.133026] ACPI Error: No handler for Region [XSCG] ((____ptrval____)) [GenericSerialBus] (20180531/evregion-132) [ 0.133036] ACPI Error: Region GenericSerialBus (ID=9) has no handler (20180531/exfldio-265) [ 0.133046] ACPI Error: Method parse/execution failed \_SB.GPO2._E12, AE_NOT_EXIST (20180531/psparse-516) Signed-off-by: Benjamin Tissoires [hdegoede: Document BYT USB mux reliance on initial trigger] [hdegoede: Run event handler from a late_initcall, rather then immediately] Signed-off-by: Hans de Goede Reviewed-by: Andy Shevchenko Acked-by: Mika Westerberg Signed-off-by: Linus Walleij Signed-off-by: Sasha Levin Signed-off-by: Greg Kroah-Hartman --- drivers/gpio/gpiolib-acpi.c | 56 +++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 55 insertions(+), 1 deletion(-) --- a/drivers/gpio/gpiolib-acpi.c +++ b/drivers/gpio/gpiolib-acpi.c @@ -25,6 +25,7 @@ struct acpi_gpio_event { struct list_head node; + struct list_head initial_sync_list; acpi_handle handle; unsigned int pin; unsigned int irq; @@ -50,6 +51,9 @@ struct acpi_gpio_chip { struct list_head events; }; +static LIST_HEAD(acpi_gpio_initial_sync_list); +static DEFINE_MUTEX(acpi_gpio_initial_sync_list_lock); + static int acpi_gpiochip_find(struct gpio_chip *gc, void *data) { if (!gc->parent) @@ -142,6 +146,21 @@ static struct gpio_desc *acpi_get_gpiod( return gpiochip_get_desc(chip, offset); } +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; @@ -193,7 +212,7 @@ static acpi_status acpi_gpiochip_request irq_handler_t handler = NULL; struct gpio_desc *desc; unsigned long irqflags; - int ret, pin, irq; + int ret, pin, irq, value; if (!acpi_gpio_get_irq_resource(ares, &agpio)) return AE_OK; @@ -228,6 +247,8 @@ static acpi_status acpi_gpiochip_request gpiod_direction_input(desc); + value = gpiod_get_value(desc); + ret = gpiochip_lock_as_irq(chip, pin); if (ret) { dev_err(chip->parent, "Failed to lock GPIO as interrupt\n"); @@ -269,6 +290,7 @@ static acpi_status acpi_gpiochip_request 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); @@ -283,6 +305,18 @@ static acpi_status acpi_gpiochip_request enable_irq_wake(irq); list_add_tail(&event->node, &acpi_gpio->events); + + /* + * Make sure we trigger the initial state of the IRQ when using RISING + * or FALLING. Note we run the handlers on late_init, the AML code + * 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); + return AE_OK; fail_free_event: @@ -355,6 +389,8 @@ void acpi_gpiochip_free_interrupts(struc 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); @@ -1210,3 +1246,21 @@ bool acpi_can_fallback_to_crs(struct acp return con_id == NULL; } + +/* Sync the initial state of handlers after all builtin drivers have probed */ +static int acpi_gpio_initial_sync(void) +{ + struct acpi_gpio_event *event, *ep; + + 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); + } + mutex_unlock(&acpi_gpio_initial_sync_list_lock); + + return 0; +} +/* We must use _sync so that this runs after the first deferred_probe run */ +late_initcall_sync(acpi_gpio_initial_sync);