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: 19277 Return-Path: X-Original-To: linaro@patches.linaro.org Delivered-To: linaro@patches.linaro.org Received: from mail-qe0-f72.google.com (mail-qe0-f72.google.com [209.85.128.72]) by ip-10-151-82-157.ec2.internal (Postfix) with ESMTPS id 44B9A248D9 for ; Sat, 17 Aug 2013 08:55:05 +0000 (UTC) Received: by mail-qe0-f72.google.com with SMTP id b10sf3124380qen.11 for ; Sat, 17 Aug 2013 01:55:04 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20120113; h=mime-version:x-gm-message-state:delivered-to:from:to:cc:subject :date:message-id:x-original-sender:x-original-authentication-results :precedence:mailing-list:list-id:list-post:list-help:list-archive :list-unsubscribe; bh=vgxxqaVwHIT9l9BbsfPbhhpjSxNbGpK0koZW6V6303A=; b=lyjCNZWsMLdZNOIlE6BoFVvwo4t1OlyUBg5ytaNPsSeDfFI/2KJvjmsAY8NU3gJT94 yG8UbblCu1efc5wMH+mmh3KTkPYKkutds7KS9JQMIl4QZ8xJTxwhTrS6L7oDH5De/60e wfjwru+oT8WmNIlmgZ5jdv3ob8ng7fX+qkhv+WHHCl9e+PsJ1kM6vLuEqlf33h/2l0Hy 6/FXN6LtkGWAJmh6GHk2nNawz0dl8JxT9s0W6Oa6amlbZWKhD0dpNBqd2n/tIv4TCDcl DlypajcrT7oPbgq0n+D50w8aDc9qZctdkC2stx1a2UplcI26UjC9R45BYD8SAJ38Bau6 avIw== X-Received: by 10.224.137.137 with SMTP id w9mr2155337qat.6.1376729704373; Sat, 17 Aug 2013 01:55:04 -0700 (PDT) MIME-Version: 1.0 X-BeenThere: patchwork-forward@linaro.org Received: by 10.49.104.177 with SMTP id gf17ls1053255qeb.4.gmail; Sat, 17 Aug 2013 01:55:04 -0700 (PDT) X-Received: by 10.220.237.208 with SMTP id kp16mr2137758vcb.4.1376729704206; Sat, 17 Aug 2013 01:55:04 -0700 (PDT) Received: from mail-vb0-f48.google.com (mail-vb0-f48.google.com [209.85.212.48]) by mx.google.com with ESMTPS id vv9si421808vec.5.1969.12.31.16.00.00 (version=TLSv1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Sat, 17 Aug 2013 01:55:04 -0700 (PDT) Received-SPF: neutral (google.com: 209.85.212.48 is neither permitted nor denied by best guess record for domain of patch+caf_=patchwork-forward=linaro.org@linaro.org) client-ip=209.85.212.48; Received: by mail-vb0-f48.google.com with SMTP id w16so2148994vbf.21 for ; Sat, 17 Aug 2013 01:55:04 -0700 (PDT) X-Gm-Message-State: ALoCoQnoJELuZYYY+J0zgWINmavQc2bkqH1UFYP5P3Hd/7z30MRMW17Fqnb1WmzBS+1ZaJQCaWXp X-Received: by 10.58.201.227 with SMTP id kd3mr2213669vec.14.1376729704046; Sat, 17 Aug 2013 01:55:04 -0700 (PDT) X-Forwarded-To: patchwork-forward@linaro.org X-Forwarded-For: patch@linaro.org patchwork-forward@linaro.org Delivered-To: patches@linaro.org Received: by 10.220.174.196 with SMTP id u4csp306vcz; Sat, 17 Aug 2013 01:55:03 -0700 (PDT) X-Received: by 10.152.116.109 with SMTP id jv13mr580267lab.30.1376729702531; Sat, 17 Aug 2013 01:55:02 -0700 (PDT) Received: from mail-la0-f52.google.com (mail-la0-f52.google.com [209.85.215.52]) by mx.google.com with ESMTPS id y3si709247lbq.158.1969.12.31.16.00.00 (version=TLSv1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Sat, 17 Aug 2013 01:55:02 -0700 (PDT) Received-SPF: neutral (google.com: 209.85.215.52 is neither permitted nor denied by best guess record for domain of linus.walleij@linaro.org) client-ip=209.85.215.52; Received: by mail-la0-f52.google.com with SMTP id ev20so2179628lab.11 for ; Sat, 17 Aug 2013 01:55:01 -0700 (PDT) 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 Cc: Stephen Warren , Linus Walleij , Haojian Zhuang , Lars Poeschel , Javier Martinez Canillas 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-Removed-Original-Auth: Dkim didn't pass. X-Original-Sender: linus.walleij@linaro.org X-Original-Authentication-Results: mx.google.com; spf=neutral (google.com: 209.85.212.48 is neither permitted nor denied by best guess record for domain of patch+caf_=patchwork-forward=linaro.org@linaro.org) smtp.mail=patch+caf_=patchwork-forward=linaro.org@linaro.org Precedence: list Mailing-list: list patchwork-forward@linaro.org; contact patchwork-forward+owners@linaro.org List-ID: X-Google-Group-Id: 836684582541 List-Post: , List-Help: , List-Archive: List-Unsubscribe: , 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 *