From patchwork Mon Feb 23 20:16:39 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jorge Ramirez-Ortiz X-Patchwork-Id: 44913 Return-Path: X-Original-To: linaro@patches.linaro.org Delivered-To: linaro@patches.linaro.org Received: from mail-wi0-f199.google.com (mail-wi0-f199.google.com [209.85.212.199]) by ip-10-151-82-157.ec2.internal (Postfix) with ESMTPS id C8E4D2029F for ; Mon, 23 Feb 2015 20:19:07 +0000 (UTC) Received: by mail-wi0-f199.google.com with SMTP id bs8sf11580259wib.2 for ; Mon, 23 Feb 2015 12:19:07 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:delivered-to:from:to:subject:date:message-id :precedence:list-id:list-unsubscribe:list-archive:list-post :list-help:list-subscribe:mime-version:content-type :content-transfer-encoding:sender:errors-to:x-original-sender :x-original-authentication-results:mailing-list; bh=wnd/Gf0n5Wm4dWmZH6QKDOFdrq1ARMqfOjvHxQKDCi4=; b=k5kwP/8QF5NWlHHg8Plz/HQlYWERxo5rBFsL2hxw0hEB0zUSQIcuFMwQ0Kvv0Y4IxG NoHM4jE5Z1VrOuQrpMVHnGe5ojfGVcs2riMvtAXTeLwYPZMFdWh9hsGqgm3BVAF2NPeD I2RYw3o7TsGSSgLE81an3dcoxFajdOLVRZ4ovlO3TS7eVTVR3mVreycKVTIC9KgsSw0u 3y68K3qAbMqRg48VOQLdqASRdoOzF5Ed5OTLtoTmxOjSKaJdjkpOUJYev0gVbbm8UV1y 9LfhUh6CCrqwzJk+YMiVFbGgQo/yLt0i6UxSCUXlSs/evldUc7C9bcz+qTLCLlkrmnVV aVHQ== X-Gm-Message-State: ALoCoQncDlrE8QlU5aW3cr5qrwPa5rRk0xgF5zhzvciRMPc0dEdc7NJOwGzg13+nfKyRwY1pefBy X-Received: by 10.152.37.200 with SMTP id a8mr1613436lak.5.1424722746988; Mon, 23 Feb 2015 12:19:06 -0800 (PST) X-BeenThere: patchwork-forward@linaro.org Received: by 10.152.5.166 with SMTP id t6ls336483lat.83.gmail; Mon, 23 Feb 2015 12:19:06 -0800 (PST) X-Received: by 10.152.206.7 with SMTP id lk7mr758194lac.37.1424722746844; Mon, 23 Feb 2015 12:19:06 -0800 (PST) Received: from mail-la0-f42.google.com (mail-la0-f42.google.com. [209.85.215.42]) by mx.google.com with ESMTPS id dk7si24378254lac.109.2015.02.23.12.19.06 for (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Mon, 23 Feb 2015 12:19:06 -0800 (PST) Received-SPF: pass (google.com: domain of patch+caf_=patchwork-forward=linaro.org@linaro.org designates 209.85.215.42 as permitted sender) client-ip=209.85.215.42; Received: by labhz20 with SMTP id hz20so20950613lab.0 for ; Mon, 23 Feb 2015 12:19:06 -0800 (PST) X-Received: by 10.112.42.225 with SMTP id r1mr11284915lbl.72.1424722746737; Mon, 23 Feb 2015 12:19:06 -0800 (PST) X-Forwarded-To: patchwork-forward@linaro.org X-Forwarded-For: patch@linaro.org patchwork-forward@linaro.org Delivered-To: patch@linaro.org Received: by 10.112.35.133 with SMTP id h5csp1491867lbj; Mon, 23 Feb 2015 12:19:05 -0800 (PST) X-Received: by 10.66.190.163 with SMTP id gr3mr22476897pac.117.1424722744891; Mon, 23 Feb 2015 12:19:04 -0800 (PST) Received: from bombadil.infradead.org (bombadil.infradead.org. [2001:1868:205::9]) by mx.google.com with ESMTPS id lz6si15722340pdb.173.2015.02.23.12.19.04 for (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Mon, 23 Feb 2015 12:19:04 -0800 (PST) Received-SPF: none (google.com: linux-arm-kernel-bounces+patch=linaro.org@lists.infradead.org does not designate permitted sender hosts) client-ip=2001:1868:205::9; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.80.1 #2 (Red Hat Linux)) id 1YPzRW-0006Nf-Rq; Mon, 23 Feb 2015 20:17:26 +0000 Received: from mail-qc0-f173.google.com ([209.85.216.173]) by bombadil.infradead.org with esmtps (Exim 4.80.1 #2 (Red Hat Linux)) id 1YPzRQ-0006JL-SK for linux-arm-kernel@lists.infradead.org; Mon, 23 Feb 2015 20:17:22 +0000 Received: by qcwb13 with SMTP id b13so13131301qcw.7 for ; Mon, 23 Feb 2015 12:16:52 -0800 (PST) X-Received: by 10.140.44.134 with SMTP id g6mr26759597qga.85.1424722611898; Mon, 23 Feb 2015 12:16:51 -0800 (PST) Received: from localhost.localdomain (cpe-67-247-86-207.rochester.res.rr.com. [67.247.86.207]) by mx.google.com with ESMTPSA id d19sm18117565qhc.42.2015.02.23.12.16.50 (version=TLSv1.2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Mon, 23 Feb 2015 12:16:51 -0800 (PST) From: Jorge Ramirez-Ortiz To: jorge.ramirez-ortiz@linaro.org, linux@arm.linux.org.uk, linux-arm-kernel@lists.infradead.org, robh@kernel.org Subject: [PATCH] drivers/tty: amba-pl011: defer driver probing if external dma is not ready. Date: Mon, 23 Feb 2015 15:16:39 -0500 Message-Id: <1424722599-9215-1-git-send-email-jorge.ramirez-ortiz@linaro.org> X-Mailer: git-send-email 1.9.1 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20150223_121722_271582_72831B8F X-CRM114-Status: GOOD ( 19.32 ) X-Spam-Score: -0.7 (/) X-Spam-Report: SpamAssassin version 3.4.0 on bombadil.infradead.org summary: Content analysis details: (-0.7 points) pts rule name description ---- ---------------------- -------------------------------------------------- -0.7 RCVD_IN_DNSWL_LOW RBL: Sender listed at http://www.dnswl.org/, low trust [209.85.216.173 listed in list.dnswl.org] -0.0 SPF_PASS SPF: sender matches SPF record -0.0 RCVD_IN_MSPIKE_H3 RBL: Good reputation (+3) [209.85.216.173 listed in wl.mailspike.net] -0.0 RCVD_IN_MSPIKE_WL Mailspike good senders X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.18-1 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+patch=linaro.org@lists.infradead.org X-Removed-Original-Auth: Dkim didn't pass. X-Original-Sender: jorge.ramirez-ortiz@linaro.org X-Original-Authentication-Results: mx.google.com; spf=pass (google.com: domain of patch+caf_=patchwork-forward=linaro.org@linaro.org designates 209.85.215.42 as permitted sender) smtp.mail=patch+caf_=patchwork-forward=linaro.org@linaro.org Mailing-list: list patchwork-forward@linaro.org; contact patchwork-forward+owners@linaro.org X-Google-Group-Id: 836684582541 This patch addresses a race condition that happens when device_initcall(pl011_dma_initicall) is executed before all the devices have been probed - this issue was observed on an hisi_6220 SoC (HiKey board from Linaro). The proposed implementation uses deferred driver probing to wait for the DMA controller to be registered. Signed-off-by: Jorge Ramirez-Ortiz --- drivers/tty/serial/amba-pl011.c | 70 +++++++++++------------------------------ 1 file changed, 18 insertions(+), 52 deletions(-) diff --git a/drivers/tty/serial/amba-pl011.c b/drivers/tty/serial/amba-pl011.c index 8d94c19..40219e5 100644 --- a/drivers/tty/serial/amba-pl011.c +++ b/drivers/tty/serial/amba-pl011.c @@ -29,6 +29,7 @@ * and hooked into this driver. */ +#define pr_fmt(fmt) "amba-pl011: "fmt #if defined(CONFIG_SERIAL_AMBA_PL011_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) #define SUPPORT_SYSRQ @@ -261,7 +262,7 @@ static void pl011_sgbuf_free(struct dma_chan *chan, struct pl011_sgbuf *sg, } } -static void pl011_dma_probe_initcall(struct device *dev, struct uart_amba_port *uap) +static int pl011_dma_probe(struct device *dev, struct uart_amba_port *uap) { /* DMA is the sole user of the platform data right now */ struct amba_pl011_data *plat = dev_get_platdata(uap->port.dev); @@ -275,13 +276,17 @@ static void pl011_dma_probe_initcall(struct device *dev, struct uart_amba_port * struct dma_chan *chan; dma_cap_mask_t mask; - chan = dma_request_slave_channel(dev, "tx"); + chan = dma_request_slave_channel_reason(dev, "tx"); + if (IS_ERR(chan)) { + + /* the dma driver has not been initialized yet */ + if (PTR_ERR(chan) == -EPROBE_DEFER) + return -EPROBE_DEFER; - if (!chan) { /* We need platform data */ if (!plat || !plat->dma_filter) { dev_info(uap->port.dev, "no DMA platform data\n"); - return; + return 0; } /* Try to acquire a generic DMA engine slave TX channel */ @@ -292,7 +297,7 @@ static void pl011_dma_probe_initcall(struct device *dev, struct uart_amba_port * plat->dma_tx_param); if (!chan) { dev_err(uap->port.dev, "no TX DMA channel!\n"); - return; + return 0; } } @@ -310,7 +315,7 @@ static void pl011_dma_probe_initcall(struct device *dev, struct uart_amba_port * if (!chan) { dev_err(uap->port.dev, "no RX DMA channel!\n"); - return; + return 0; } } @@ -383,54 +388,10 @@ static void pl011_dma_probe_initcall(struct device *dev, struct uart_amba_port * dev_info(uap->port.dev, "DMA channel RX %s\n", dma_chan_name(uap->dmarx.chan)); } -} - -#ifndef MODULE -/* - * Stack up the UARTs and let the above initcall be done at device - * initcall time, because the serial driver is called as an arch - * initcall, and at this time the DMA subsystem is not yet registered. - * At this point the driver will switch over to using DMA where desired. - */ -struct dma_uap { - struct list_head node; - struct uart_amba_port *uap; - struct device *dev; -}; - -static LIST_HEAD(pl011_dma_uarts); - -static int __init pl011_dma_initcall(void) -{ - struct list_head *node, *tmp; - list_for_each_safe(node, tmp, &pl011_dma_uarts) { - struct dma_uap *dmau = list_entry(node, struct dma_uap, node); - pl011_dma_probe_initcall(dmau->dev, dmau->uap); - list_del(node); - kfree(dmau); - } return 0; } -device_initcall(pl011_dma_initcall); - -static void pl011_dma_probe(struct device *dev, struct uart_amba_port *uap) -{ - struct dma_uap *dmau = kzalloc(sizeof(struct dma_uap), GFP_KERNEL); - if (dmau) { - dmau->uap = uap; - dmau->dev = dev; - list_add_tail(&dmau->node, &pl011_dma_uarts); - } -} -#else -static void pl011_dma_probe(struct device *dev, struct uart_amba_port *uap) -{ - pl011_dma_probe_initcall(dev, uap); -} -#endif - static void pl011_dma_remove(struct uart_amba_port *uap) { /* TODO: remove the initcall if it has not yet executed */ @@ -1142,8 +1103,9 @@ static inline bool pl011_dma_rx_running(struct uart_amba_port *uap) #else /* Blank functions if the DMA engine is not available */ -static inline void pl011_dma_probe(struct device *dev, struct uart_amba_port *uap) +static int pl011_dma_probe(struct device *dev, struct uart_amba_port *uap) { + return 0; } static inline void pl011_dma_remove(struct uart_amba_port *uap) @@ -2218,7 +2180,11 @@ static int pl011_probe(struct amba_device *dev, const struct amba_id *id) uap->port.ops = &amba_pl011_pops; uap->port.flags = UPF_BOOT_AUTOCONF; uap->port.line = i; - pl011_dma_probe(&dev->dev, uap); + ret = pl011_dma_probe(&dev->dev, uap); + if (ret) { + devm_kfree(&dev->dev, uap); + return ret; + } /* Ensure interrupts from this UART are masked and cleared */ writew(0, uap->port.membase + UART011_IMSC);