From patchwork Mon Jul 18 09:14:19 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Anup Patel X-Patchwork-Id: 9234251 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 8E4AA607FF for ; Mon, 18 Jul 2016 09:21:30 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 7BF4A26253 for ; Mon, 18 Jul 2016 09:21:30 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 6FEC7254F7; Mon, 18 Jul 2016 09:21:30 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-4.1 required=2.0 tests=BAYES_00,DKIM_SIGNED, RCVD_IN_DNSWL_MED, T_DKIM_INVALID autolearn=unavailable version=3.3.1 Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.9]) (using TLSv1.2 with cipher AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id 94BD2254F7 for ; Mon, 18 Jul 2016 09:21:29 +0000 (UTC) Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.85_2 #1 (Red Hat Linux)) id 1bP4hu-0004RS-EK; Mon, 18 Jul 2016 09:19:22 +0000 Received: from mail-pa0-x234.google.com ([2607:f8b0:400e:c03::234]) by bombadil.infradead.org with esmtps (Exim 4.85_2 #1 (Red Hat Linux)) id 1bP4eC-000114-Vy for linux-arm-kernel@lists.infradead.org; Mon, 18 Jul 2016 09:15:44 +0000 Received: by mail-pa0-x234.google.com with SMTP id fi15so58811076pac.1 for ; Mon, 18 Jul 2016 02:15:12 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=broadcom.com; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=9H5PDmg5/P4bJg3s4dOVM0rmqJY9pzH1xDXePQdATcY=; b=Bd77eR8I8GWway6nR6JxL/mD9mJ0RFXODemUevgXAXMeH+TRjHhoEvhIvcsJhA96Dw /w6Ng/Z98Owg3ZTmipljrDcPc4cB9Ehx2WIIaJKGcIdm9R1G4OwJyMJ/9kO6dreszH/Y 69nhoTtYnrzf3M6LbNutBvDpmdI1RyH/ZRTAA= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=9H5PDmg5/P4bJg3s4dOVM0rmqJY9pzH1xDXePQdATcY=; b=MQeb1gqNgvbUPR0NQKGTFaS4HFS0ZK6jr/89S8R4E2KJ2zEH9jMIDoJwI9alNF30eg 49NxD25SQUmmfKGI8ruJV0MjW1E8i3kZ5T4nDXSzM/yEefLxPlGSVMgZ2i/y7DiQRgPE DLTokUkbogLUDbFmL1RuMDOioivOSmCwoLYNcrLcBoz0Fc1BsRVTq5AhY46ALZCg9084 dTJw+9/wmOQ/kItOEIPRGB8JbhVbUzTQjbwQbDxAj7fv7gyJ3t+PJxYnOLme+TyCLnUE D16UIU93qN0NE2GKcKB3xiPF6IUCBaMnExfmoiTl3kA4Qyabz3aGp7nEehzLHCbraxv8 oarQ== X-Gm-Message-State: ALyK8tIF3OAPUxbIEVCC+YTbW9Qqm3dGaLJ0owb2s46ms+crx97qWJod0bmwXeSCXj3VZUjv X-Received: by 10.66.27.243 with SMTP id w19mr54345715pag.112.1468833311479; Mon, 18 Jul 2016 02:15:11 -0700 (PDT) Received: from anup-HP-Compaq-8100-Elite-CMT-PC.ban.broadcom.com ([202.140.56.34]) by smtp.gmail.com with ESMTPSA id z1sm2883269pab.19.2016.07.18.02.15.06 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Mon, 18 Jul 2016 02:15:10 -0700 (PDT) From: Anup Patel To: "Hans J. Koch" , Greg Kroah-Hartman , Jonathan Corbet Subject: [PATCH v2 7/8] uio: bind uio_dmem_genirq via OF Date: Mon, 18 Jul 2016 14:44:19 +0530 Message-Id: <1468833260-5305-8-git-send-email-anup.patel@broadcom.com> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1468833260-5305-1-git-send-email-anup.patel@broadcom.com> References: <1468833260-5305-1-git-send-email-anup.patel@broadcom.com> X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20160718_021533_386372_561F5347 X-CRM114-Status: GOOD ( 22.63 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.20 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Mark Rutland , devicetree@vger.kernel.org, Anup Patel , Scott Branden , linux-doc@vger.kernel.org, Ray Jui , Russell King - ARM Linux , linux-kernel@vger.kernel.org, Rob Herring , bcm-kernel-feedback-list@broadcom.com, Ankit Jindal , linux-arm-kernel@lists.infradead.org, Jan Viktorin MIME-Version: 1.0 Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org X-Virus-Scanned: ClamAV using ClamSMTP From: Jan Viktorin The uio_dmem_genirq works in a similar ways as uio_pdrv_genirq now. It accepts the of_id module parameter to specify UIO compatible string as module parameter. There are few other module parameters to specify number bits in DMA mask and sizes dynamic regions. Following are the newly added module parameters: 1) of_id: The UIO compatible string to be used for DT probing 2) dmem_dma_bits: This is the number of DMA mask bits for UIO device. 3) dmem_sizes: This is a formatted string specifying sizes of dynamic required by some of the UIO devices. Below are few examples of formatted string for dmem_sizes: a) UIO dmem device with 3 dynamic regions: uio_dmem_genirq.dmem_sizes=abc:4K,16K,4M b) Two UIO dmem devices with different number of dynamic regions: uio_dmem_genirq.dmem_sizes=abc:4K,16K,4M;xyz:8K Signed-off-by: Jan Viktorin Signed-off-by: Anup Patel --- drivers/uio/uio_dmem_genirq.c | 162 +++++++++++++++++++++++++++++++++++------- 1 file changed, 135 insertions(+), 27 deletions(-) diff --git a/drivers/uio/uio_dmem_genirq.c b/drivers/uio/uio_dmem_genirq.c index a4d6d81..1db2559 100644 --- a/drivers/uio/uio_dmem_genirq.c +++ b/drivers/uio/uio_dmem_genirq.c @@ -12,6 +12,27 @@ * the Free Software Foundation. */ +/* + * For DeviceTree based platform devices, the compatible string, the DMA mask + * bits and sizes of dynamic regions are derived from kernel command-line. + * + * The format for specifying dynamic region sizes in kernel command line + * is as follows: + * + * uio_dmem_genirq.dmem_sizes := [;] + * := :[,] + * := name as shown in /sys/class/uio/uioX/name + * := standard linux memsize + * + * Examples: + * + * 1) UIO dmem device with 3 dynamic regions: + * uio_dmem_genirq.dmem_sizes=abc:4K,16K,4M + * + * 2) Two UIO dmem devices with different number of dynamic regions: + * uio_dmem_genirq.dmem_sizes=abc:4K,16K,4M;xyz:8K + */ + #include #include #include @@ -144,46 +165,134 @@ static int uio_dmem_genirq_irqcontrol(struct uio_info *dev_info, s32 irq_on) return 0; } +static unsigned int uio_dmem_dma_bits = 32; +static char uio_dmem_sizes[256]; + +static int uio_dmem_genirq_alloc_platdata(struct platform_device *pdev) +{ + int ret, name_len; + u32 regions = 0; + char *s, *name, *sz; + char *sizes_str = NULL, *sizes_endstr = NULL; + struct uio_dmem_genirq_pdata pdata; + unsigned long long sizes[MAX_UIO_MAPS]; + + memset(&pdata, 0, sizeof(pdata)); + + /* Set DMA coherent mask */ + if (uio_dmem_dma_bits > 64) + uio_dmem_dma_bits = 64; + ret = dma_set_coherent_mask(&pdev->dev, + DMA_BIT_MASK(uio_dmem_dma_bits)); + if (ret) { + dev_err(&pdev->dev, "Unable to dma_set_coherent_mask\n"); + return ret; + } + + /* Find-out start and end of sizes list */ + s = uio_dmem_sizes; + while (*s != '\0') { + name = s; + s = strchr(s, ':'); + if (!s) + break; + name_len = s - name; + s++; + if (*s == '\0') + break; + sz = s; + s = strchr(s, ';'); + if (!s) + s = &uio_dmem_sizes[strlen(uio_dmem_sizes)]; + if (strncmp(name, pdev->dev.of_node->name, name_len) == 0) { + sizes_str = sz; + sizes_endstr = s; + break; + } + s++; + } + + /* Parse dynamic regions from sizes list */ + regions = 0; + sizes[0] = 0; + while (sizes_str && sizes_endstr && + (sizes_str < sizes_endstr) && + (*sizes_str != '\0') && + (*sizes_str != ';') && + (regions < MAX_UIO_MAPS)) { + if (*sizes_str == ',') { + sizes_str++; + continue; + } + sizes[regions] = memparse(sizes_str, &sizes_str); + if (sizes[regions]) + regions++; + } + + /* Populate platform data */ + pdata.num_dynamic_regions = regions; + pdata.dynamic_region_sizes = devm_kzalloc(&pdev->dev, + sizeof(*pdata.dynamic_region_sizes) * + pdata.num_dynamic_regions, GFP_KERNEL); + if (!pdata.dynamic_region_sizes) { + dev_err(&pdev->dev, "Unable to alloc dynamic_region_sizes\n"); + ret = -ENOMEM; + return ret; + } + + while (regions--) + pdata.dynamic_region_sizes[regions] = sizes[regions]; + + pdata.uioinfo.name = pdev->dev.of_node->name; + pdata.uioinfo.version = "devicetree"; + + return platform_device_add_data(pdev, &pdata, sizeof(pdata)); +} + static int uio_dmem_genirq_probe(struct platform_device *pdev) { - struct uio_dmem_genirq_pdata *pdata = dev_get_platdata(&pdev->dev); - struct uio_info *uioinfo = &pdata->uioinfo; - struct uio_dmem_genirq_platdata *priv; - struct uio_mem *uiomem; - int ret = -EINVAL; int i; + int ret = -EINVAL; + struct uio_mem *uiomem; + struct uio_info *uioinfo; + struct uio_dmem_genirq_pdata *pdata; + struct uio_dmem_genirq_platdata *priv; if (pdev->dev.of_node) { - /* alloc uioinfo for one device */ - uioinfo = kzalloc(sizeof(*uioinfo), GFP_KERNEL); - if (!uioinfo) { - ret = -ENOMEM; - dev_err(&pdev->dev, "unable to kmalloc\n"); + ret = uio_dmem_genirq_alloc_platdata(pdev); + if (ret) goto bad2; - } - uioinfo->name = pdev->dev.of_node->name; - uioinfo->version = "devicetree"; } + pdata = dev_get_platdata(&pdev->dev); + uioinfo = &pdata->uioinfo; + if (!uioinfo || !uioinfo->name || !uioinfo->version) { dev_err(&pdev->dev, "missing platform_data\n"); - goto bad0; + goto bad2; } if (uioinfo->handler || uioinfo->irqcontrol || uioinfo->irq_flags & IRQF_SHARED) { dev_err(&pdev->dev, "interrupt configuration error\n"); - goto bad0; + goto bad2; } priv = kzalloc(sizeof(*priv), GFP_KERNEL); if (!priv) { ret = -ENOMEM; dev_err(&pdev->dev, "unable to kmalloc\n"); - goto bad0; + goto bad2; } - dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32)); + if (!pdev->dev.of_node) { + ret = dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32)); + if (ret) { + dev_err(&pdev->dev, + "unable to dma_set_coherent_mask\n"); + goto bad1; + } + } priv->uioinfo = uioinfo; spin_lock_init(&priv->lock); @@ -278,10 +387,6 @@ static int uio_dmem_genirq_probe(struct platform_device *pdev) return 0; bad1: kfree(priv); - bad0: - /* kfree uioinfo for OF */ - if (pdev->dev.of_node) - kfree(uioinfo); bad2: return ret; } @@ -296,10 +401,6 @@ static int uio_dmem_genirq_remove(struct platform_device *pdev) priv->uioinfo->handler = NULL; priv->uioinfo->irqcontrol = NULL; - /* kfree uioinfo for OF */ - if (pdev->dev.of_node) - kfree(priv->uioinfo); - kfree(priv); return 0; } @@ -327,10 +428,17 @@ static const struct dev_pm_ops uio_dmem_genirq_dev_pm_ops = { }; #ifdef CONFIG_OF -static const struct of_device_id uio_of_genirq_match[] = { - { /* empty for now */ }, +static struct of_device_id uio_of_genirq_match[] = { + { /* This is filled with module_parm */ }, + { /* end of list */ }, }; MODULE_DEVICE_TABLE(of, uio_of_genirq_match); +module_param_string(of_id, uio_of_genirq_match[0].compatible, 128, 0); +MODULE_PARM_DESC(of_id, "Openfirmware id of the device to be handled by uio"); +module_param_named(dmem_dma_bits, uio_dmem_dma_bits, uint, 0); +MODULE_PARM_DESC(dmem_dma_bits, "Number of bits in DMA mask"); +module_param_string(dmem_sizes, uio_dmem_sizes, 256, 0); +MODULE_PARM_DESC(dmem_sizes, "Comma separated dynamic region sizes"); #endif static struct platform_driver uio_dmem_genirq = {