From patchwork Mon Aug 8 05:52:36 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Anup Patel X-Patchwork-Id: 9266695 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 DD9BC60839 for ; Mon, 8 Aug 2016 05:57:15 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id CE30626E69 for ; Mon, 8 Aug 2016 05:57:15 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id C29EC27813; Mon, 8 Aug 2016 05:57:15 +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 2533926E69 for ; Mon, 8 Aug 2016 05:57:15 +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 1bWdXP-000364-DQ; Mon, 08 Aug 2016 05:55:47 +0000 Received: from mail-pa0-x22f.google.com ([2607:f8b0:400e:c03::22f]) by bombadil.infradead.org with esmtps (Exim 4.85_2 #1 (Red Hat Linux)) id 1bWdWH-0000t9-NY for linux-arm-kernel@lists.infradead.org; Mon, 08 Aug 2016 05:54:43 +0000 Received: by mail-pa0-x22f.google.com with SMTP id fi15so110612623pac.1 for ; Sun, 07 Aug 2016 22:54:17 -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=J24ZniRlWTi+uXJppceiZWeoyL0u2/dT+mck0wXh1uERqmimGFhdXNdUu5GP3eLqHQ Eb4nNAYvJT/1B3S46Q4tvNsgGk/F47+B+CLk8/D6PP3hO+QG1jsd5jwCAcbtz2gziaPd X0E5xFRK6Wb/CRK9ensQ/4Y6ut7zkQxp8nH3Y= 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=BYNhcRlP5idblVRWFEqCnqocz+N7oW7BjJOb5P+57yQYuwV5/OsFA6fFkGIxNJJ64M jDru+kEuZr+xmFjehm5+TGzQNQ1gmXNFOwvkZHPp5vgwtwMVn+ISX3DKyFAsJhkMhU8N OGyaiiKj51ONCvAW1fP8XiaejmLxzFxtPHhlCMIr7BnhhR5qBaZSDdmnudGTouJkGIuM GfKxhWKFqt63vvnA1XO1ZKZToIfKiCGODIqpGIFVsVbTsYYGPZnVkg4q5atkXn7aY+cv UIU3DxMGgv3SOHFSIHfH/OtjrU1tk4HimT8NFoE2O93odtGp7e3CYOf6hSVE85nzRGsY Cw7Q== X-Gm-Message-State: AEkoouucXzoBUdUPy9zEAfiV9+nL5pa8ekdzJ2sNZvKPRPNZ8hAf8r8dVkC8BQLsmEH6vRDk X-Received: by 10.67.7.229 with SMTP id df5mr9387118pad.6.1470635656352; Sun, 07 Aug 2016 22:54:16 -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 u72sm44404402pfa.31.2016.08.07.22.54.07 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Sun, 07 Aug 2016 22:54:15 -0700 (PDT) From: Anup Patel To: Greg Kroah-Hartman , Jonathan Corbet Subject: [PATCH RESEND v2 7/8] uio: bind uio_dmem_genirq via OF Date: Mon, 8 Aug 2016 11:22:36 +0530 Message-Id: <1470635557-13416-8-git-send-email-anup.patel@broadcom.com> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1470635557-13416-1-git-send-email-anup.patel@broadcom.com> References: <1470635557-13416-1-git-send-email-anup.patel@broadcom.com> X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20160807_225438_051257_05D766DE X-CRM114-Status: GOOD ( 22.57 ) 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 = {