From patchwork Sat Aug 17 08:54:52 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Linus Walleij X-Patchwork-Id: 2845978 Return-Path: X-Original-To: patchwork-linux-arm@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork2.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.19.201]) by patchwork2.web.kernel.org (Postfix) with ESMTP id C63CBBF546 for ; Sat, 17 Aug 2013 08:55:48 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 9E4512021E for ; Sat, 17 Aug 2013 08:55:47 +0000 (UTC) Received: from casper.infradead.org (casper.infradead.org [85.118.1.10]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 785A02021F for ; Sat, 17 Aug 2013 08:55:46 +0000 (UTC) Received: from merlin.infradead.org ([2001:4978:20e::2]) by casper.infradead.org with esmtps (Exim 4.80.1 #2 (Red Hat Linux)) id 1VAcIE-0000m3-99; Sat, 17 Aug 2013 08:55:30 +0000 Received: from localhost ([::1] helo=merlin.infradead.org) by merlin.infradead.org with esmtp (Exim 4.80.1 #2 (Red Hat Linux)) id 1VAcIC-0002ns-58; Sat, 17 Aug 2013 08:55:28 +0000 Received: from mail-la0-f51.google.com ([209.85.215.51]) by merlin.infradead.org with esmtps (Exim 4.80.1 #2 (Red Hat Linux)) id 1VAcI8-0002nN-96 for linux-arm-kernel@lists.infradead.org; Sat, 17 Aug 2013 08:55:25 +0000 Received: by mail-la0-f51.google.com with SMTP id es20so2198488lab.10 for ; Sat, 17 Aug 2013 01:55:01 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20120113; h=x-gm-message-state:from:to:cc:subject:date:message-id; bh=vgxxqaVwHIT9l9BbsfPbhhpjSxNbGpK0koZW6V6303A=; b=g329+2WvidSRIhh3F+kHKn5YWeRmomnABEYYu90KWa1QqYlf7w0/7ERwHDihZtFhBc LNcWeo/F41GG955uosNB2pcprPDGd+VjCbr17imirS9f0DnN3KieY/Lly4EyiF5pswwh UOgpRXCW3yeFkhaklvdQKyUZPruDeL0nRFT/MKQyx5H/vEceBtBGe/OnHv3CrO1ZkHHN PbU88lMtQgaOJbpBIh6c+EIw4SotJZntoy3VL1UHzLPJTratHl8b4DueYABIRUBlnU5L bmaao0UppFxAXBwGcumZubqfia3ZISkaef0TH2T6IPLMyDxQEXYgIH7wxOhisLf7MyHx DfUA== X-Gm-Message-State: ALoCoQkX5+TzrEAEDv2KHfUSgtIlOdFhltSmtvZIfkpZhtWpqWOgOkp0UgcGm7YcMC1XP45aMyip X-Received: by 10.112.18.232 with SMTP id z8mr1840828lbd.23.1376729701697; Sat, 17 Aug 2013 01:55:01 -0700 (PDT) Received: from localhost.localdomain (c83-249-210-71.bredband.comhem.se. [83.249.210.71]) by mx.google.com with ESMTPSA id l10sm581565lbh.13.1969.12.31.16.00.00 (version=TLSv1.2 cipher=RC4-SHA bits=128/128); Sat, 17 Aug 2013 01:55:00 -0700 (PDT) From: Linus Walleij To: linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org Subject: [PATCH] pinctrl: queue GPIO request instead of defering Date: Sat, 17 Aug 2013 10:54:52 +0200 Message-Id: <1376729692-21108-1-git-send-email-linus.walleij@linaro.org> X-Mailer: git-send-email 1.8.1.4 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20130817_045524_602214_49B6D7E1 X-CRM114-Status: GOOD ( 21.70 ) X-Spam-Score: -2.6 (--) Cc: Lars Poeschel , Linus Walleij , Stephen Warren , Haojian Zhuang , Javier Martinez Canillas X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org X-Spam-Status: No, score=-6.9 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_MED, RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP We currently defer probing of the caller if a pinctrl GPIO request comes in before the range mapping a certain GPIO to a certain pin controller is available. If this pinctrl_gpio_request() is done for a GPIO driver adding the range from the gpiochip side (as is recommended) they can end up with a circular dependency: the GPIO driver needs the pin controller to be ready and the pin controller need the GPIO driver to be ready. This also happens if pin controllers and GPIO controllers compiled as modules are inserted in a certain order. To break this circular dependence, queue any requests coming to the framework until the range is ready, instead of deferring the probe of the caller. On the Nomadik we get this situation with the pinctrl driver when moving to requesting GPIOs off the gpiochip right after it has been added, and with this patch the boot dilemma is sorted out nicely, as can be seen in this condensed bootlog: pinctrl core: initialized pinctrl subsystem gpio 101e4000.gpio: at address cc852000 gpio 101e5000.gpio: at address cc854000 gpio 101e6000.gpio: at address cc856000 pinctrl core: queueing pinctrl request for GPIO 104 gpio 101e7000.gpio: at address cc858000 pinctrl core: requested queued GPIO 104 pinctrl-nomadik pinctrl.0: initialized Nomadik pin control driver Cc: Haojian Zhuang Cc: Lars Poeschel Cc: Javier Martinez Canillas Signed-off-by: Linus Walleij --- Some testing of this would be appreciated, especially for HiSilicon etc that already have some complicated GPIO ranges. --- drivers/pinctrl/core.c | 73 +++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 70 insertions(+), 3 deletions(-) diff --git a/drivers/pinctrl/core.c b/drivers/pinctrl/core.c index 2a00239..59cbf41 100644 --- a/drivers/pinctrl/core.c +++ b/drivers/pinctrl/core.c @@ -404,9 +404,11 @@ static int pinctrl_get_device_gpio_range(unsigned gpio, } } - return -EPROBE_DEFER; + return -EINVAL; } +static void pinctrl_process_queued_gpio_requests(void); + /** * pinctrl_add_gpio_range() - register a GPIO range for a controller * @pctldev: pin controller device to add the range to @@ -421,6 +423,8 @@ void pinctrl_add_gpio_range(struct pinctrl_dev *pctldev, mutex_lock(&pctldev->mutex); list_add_tail(&range->node, &pctldev->gpio_ranges); mutex_unlock(&pctldev->mutex); + /* Maybe we have outstanding GPIO requests for this range? */ + pinctrl_process_queued_gpio_requests(); } EXPORT_SYMBOL_GPL(pinctrl_add_gpio_range); @@ -534,6 +538,16 @@ int pinctrl_get_group_selector(struct pinctrl_dev *pctldev, return -EINVAL; } +/* + * Queued GPIO requests are stored in this list. + */ +struct pinctrl_gpio_req { + struct list_head node; + int gpio; +}; + +static LIST_HEAD(pinctrl_queued_gpio_requests); + /** * pinctrl_request_gpio() - request a single pin to be used in as GPIO * @gpio: the GPIO pin number from the GPIO subsystem number space @@ -551,9 +565,26 @@ int pinctrl_request_gpio(unsigned gpio) ret = pinctrl_get_device_gpio_range(gpio, &pctldev, &range); if (ret) { + /* Maybe this pin does not have a pinctrl back-end at all? */ if (pinctrl_ready_for_gpio_range(gpio)) - ret = 0; - return ret; + return 0; + /* + * We get to this point if pinctrl_request_gpio() is called + * from a GPIO driver which does not yet have a registered + * pinctrl driver backend, and thus no ranges are defined for + * it. This could happen during system start up or if we're + * probing pin controllers as modules. Queue the request and + * handle it when and if the range arrives. + */ + struct pinctrl_gpio_req *req = + kzalloc(sizeof(struct pinctrl_gpio_req), GFP_KERNEL); + + if (!req) + return -ENOMEM; + req->gpio = gpio; + list_add_tail(&req->node, &pinctrl_queued_gpio_requests); + pr_info("queueing pinctrl request for GPIO %d\n", req->gpio); + return 0; } /* Convert to the pin controllers number space */ @@ -566,6 +597,42 @@ int pinctrl_request_gpio(unsigned gpio) EXPORT_SYMBOL_GPL(pinctrl_request_gpio); /** + * pinctrl_process_queued_gpio_requests() - process queued GPIO requests + * + * This is called whenever a new GPIO range is added to see if some GPIO + * driver has outstanding requests to GPIOs in the range, and then these + * get processed at this point. + */ +static void pinctrl_process_queued_gpio_requests(void) +{ + struct list_head *node, *tmp; + + list_for_each_safe(node, tmp, &pinctrl_queued_gpio_requests) { + struct pinctrl_gpio_req *req = + list_entry(node, struct pinctrl_gpio_req, node); + struct pinctrl_dev *pctldev; + struct pinctrl_gpio_range *range; + int pin; + int ret; + + ret = pinctrl_get_device_gpio_range(req->gpio, &pctldev, &range); + if (ret) + continue; + + /* Convert to the pin controllers number space */ + pin = gpio_to_pin(range, req->gpio); + ret = pinmux_request_gpio(pctldev, range, pin, req->gpio); + + if (ret) + pr_err("failed to request queued GPIO %d\n", req->gpio); + else + pr_info("requested queued GPIO %d\n", req->gpio); + list_del(node); + kfree(req); + } +} + +/** * pinctrl_free_gpio() - free control on a single pin, currently used as GPIO * @gpio: the GPIO pin number from the GPIO subsystem number space *