From patchwork Fri Apr 27 01:26:04 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Moritz Fischer X-Patchwork-Id: 10367297 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 47A8D60386 for ; Fri, 27 Apr 2018 01:29:26 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 32D28292BD for ; Fri, 27 Apr 2018 01:29:26 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 262EF292C0; Fri, 27 Apr 2018 01:29:26 +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=-2.9 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,MAILING_LIST_MULTI autolearn=unavailable version=3.3.1 Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id 559A2292BD for ; Fri, 27 Apr 2018 01:29:25 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20170209; h=Sender: Content-Transfer-Encoding:Content-Type:MIME-Version:Cc:List-Subscribe: List-Help:List-Post:List-Archive:List-Unsubscribe:List-Id:References: In-Reply-To:Message-Id:Date:Subject:To:From:Reply-To:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:List-Owner; bh=TBbQ5KjDCmbnAZQnaJ+r1se+B+gpexQkzlomVuwg1qo=; b=jsqg2qlepu4+j1u6QZ3CO+Xegu T1B8BhkUe0jm1qyQEqqTWwOlIZM87ApRKA8oCt0ajtcH1JNvuBh25mJtNkxJUakL7C9Dk8nNnjiJ0 WvIe4GEWfFV8+tBoFiQfMywNVFRX6ClS8NQEYH2WIvnArBe0nlM7S0YhE7+eZgpogmDq/0F4Bhsrf h2u8Kd4TeTrkaye8Pom23ZsJ8W3h4ZLwDVM4psMIGmgKiYSLnmKQVBZRAjY5yXUECMEGc7vhTnnLO m7079IRFEHG5SAkdEzi+8dQPUJSrYbrOj56Td8XWci8jbpvPvwZ/+9IZKlhsyubxollpzIA9T6lu0 JuS/T33g==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.90_1 #2 (Red Hat Linux)) id 1fBsCJ-0002WI-Vg; Fri, 27 Apr 2018 01:29:16 +0000 Received: from mail-oi0-f65.google.com ([209.85.218.65]) by bombadil.infradead.org with esmtps (Exim 4.90_1 #2 (Red Hat Linux)) id 1fBs9f-0001CL-9f for linux-arm-kernel@lists.infradead.org; Fri, 27 Apr 2018 01:26:33 +0000 Received: by mail-oi0-f65.google.com with SMTP id 11-v6so227159ois.8 for ; Thu, 26 Apr 2018 18:26:20 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=fwGePodZbPrwaKOpjpCzXLQXw34bN1jobeXnJPRCBnQ=; b=KGiBJv11+hQcc2Vawm1MvAWAf0WOAwsLu0wJ2t6ns+6yjO0XYXNsDLz1/MBwlUTNDe FlLzXf4b60t3D3ReLokkwbHNgUmNdiXPmatKYKBWiPDladLr+vFw5BxkA3TMQ722E43r uaXTU7q5jo1pEt4D9PwMCr9zTAUxtz2Y4PemsJv4Qtfu9OqNVbyjBgPlh7mJkFQLW+3L Wp3F7m1Inyq5TUC3f+2DUeMxxcGoZEPsLs5FG3Nlk45G60o+4fBD1DeD3tIlEXkNqVtt L9tP1vQ39naJ9sLoLlNUee6/4pY11h7KPRs1rTOPVS9y3WVx+egv9asYGTZ9Pq8immAD VLIQ== X-Gm-Message-State: ALQs6tAJPzX6wUdEZwzZuxNd2N2413PB9HFAip7xMsSwHP91kIViLywn EZP1fV/bJsAr5wshz324Tgj7NA== X-Google-Smtp-Source: AB8JxZq28cuIfL3u7CA/R72llBWyRoMK78Jo0SoMXWJygGjLrI+vzEUZJuZMNof75/OtsqASUXeJOg== X-Received: by 2002:aca:6243:: with SMTP id w64-v6mr207525oib.26.1524792379823; Thu, 26 Apr 2018 18:26:19 -0700 (PDT) Received: from localhost ([130.164.62.82]) by smtp.gmail.com with ESMTPSA id d201-v6sm145715oig.18.2018.04.26.18.26.18 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Thu, 26 Apr 2018 18:26:18 -0700 (PDT) From: Moritz Fischer To: linux-kernel@vger.kernel.org Subject: [PATCH 3/4] fpga: bridge: change api, don't use drvdata Date: Thu, 26 Apr 2018 18:26:04 -0700 Message-Id: <20180427012605.28981-4-mdf@kernel.org> X-Mailer: git-send-email 2.17.0 In-Reply-To: <20180427012605.28981-1-mdf@kernel.org> References: <20180427012605.28981-1-mdf@kernel.org> X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20180426_182631_397006_488CCB3A X-CRM114-Status: GOOD ( 22.49 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: corbet@lwn.net, linux-fpga@vger.kernel.org, atull@kernel.org, linux-doc@vger.kernel.org, michal.simek@xilinx.com, Moritz Fischer , linux-arm-kernel@lists.infradead.org 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: Alan Tull Change fpga_bridge_register to not set drvdata. This is to support the case where a PCIe device can have more than one bridge. Add API functions to create/free the fpga bridge struct. Change fpga_bridge_register/unregister to take FPGA bridge struct as the only parameter. struct fpga_bridge *fpga_bridge_create(struct device *dev, const char *name, const struct fpga_bridge_ops *br_ops, void *priv); void fpga_bridge_free(struct fpga_bridge *br); int fpga_bridge_register(struct fpga_bridge *br); void fpga_bridge_unregister(struct fpga_bridge *br); Update the drivers that call fpga_bridge_register with the new API. Signed-off-by: Alan Tull Reported-by: Jiuyue Ma Signed-off-by: Moritz Fischer --- drivers/fpga/altera-fpga2sdram.c | 21 ++++++--- drivers/fpga/altera-freeze-bridge.c | 22 +++++++-- drivers/fpga/altera-hps2fpga.c | 24 +++++++--- drivers/fpga/fpga-bridge.c | 70 +++++++++++++++++++---------- drivers/fpga/xilinx-pr-decoupler.c | 22 ++++++--- include/linux/fpga/fpga-bridge.h | 9 ++-- 6 files changed, 123 insertions(+), 45 deletions(-) diff --git a/drivers/fpga/altera-fpga2sdram.c b/drivers/fpga/altera-fpga2sdram.c index d4eeb74388da..5a29ab6e3b28 100644 --- a/drivers/fpga/altera-fpga2sdram.c +++ b/drivers/fpga/altera-fpga2sdram.c @@ -106,6 +106,7 @@ static int alt_fpga_bridge_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct alt_fpga2sdram_data *priv; + struct fpga_bridge *br; u32 enable; struct regmap *sysmgr; int ret = 0; @@ -131,10 +132,18 @@ static int alt_fpga_bridge_probe(struct platform_device *pdev) /* Get f2s bridge configuration saved in handoff register */ regmap_read(sysmgr, SYSMGR_ISWGRP_HANDOFF3, &priv->mask); - ret = fpga_bridge_register(dev, F2S_BRIDGE_NAME, - &altera_fpga2sdram_br_ops, priv); - if (ret) + br = fpga_bridge_create(dev, F2S_BRIDGE_NAME, + &altera_fpga2sdram_br_ops, priv); + if (!br) + return -ENOMEM; + + platform_set_drvdata(pdev, br); + + ret = fpga_bridge_register(br); + if (ret) { + fpga_bridge_free(br); return ret; + } dev_info(dev, "driver initialized with handoff %08x\n", priv->mask); @@ -146,7 +155,7 @@ static int alt_fpga_bridge_probe(struct platform_device *pdev) (enable ? "enabling" : "disabling")); ret = _alt_fpga2sdram_enable_set(priv, enable); if (ret) { - fpga_bridge_unregister(&pdev->dev); + fpga_bridge_unregister(br); return ret; } } @@ -157,7 +166,9 @@ static int alt_fpga_bridge_probe(struct platform_device *pdev) static int alt_fpga_bridge_remove(struct platform_device *pdev) { - fpga_bridge_unregister(&pdev->dev); + struct fpga_bridge *br = platform_get_drvdata(pdev); + + fpga_bridge_unregister(br); return 0; } diff --git a/drivers/fpga/altera-freeze-bridge.c b/drivers/fpga/altera-freeze-bridge.c index 6159cfcf78a2..fa4b693cf4be 100644 --- a/drivers/fpga/altera-freeze-bridge.c +++ b/drivers/fpga/altera-freeze-bridge.c @@ -221,8 +221,10 @@ static int altera_freeze_br_probe(struct platform_device *pdev) struct device_node *np = pdev->dev.of_node; void __iomem *base_addr; struct altera_freeze_br_data *priv; + struct fpga_bridge *br; struct resource *res; u32 status, revision; + int ret; if (!np) return -ENODEV; @@ -254,13 +256,27 @@ static int altera_freeze_br_probe(struct platform_device *pdev) priv->base_addr = base_addr; - return fpga_bridge_register(dev, FREEZE_BRIDGE_NAME, - &altera_freeze_br_br_ops, priv); + br = fpga_bridge_create(dev, FREEZE_BRIDGE_NAME, + &altera_freeze_br_br_ops, priv); + if (!br) + return -ENOMEM; + + platform_set_drvdata(pdev, br); + + ret = fpga_bridge_register(br); + if (ret) { + fpga_bridge_free(br); + return ret; + } + + return 0; } static int altera_freeze_br_remove(struct platform_device *pdev) { - fpga_bridge_unregister(&pdev->dev); + struct fpga_bridge *br = platform_get_drvdata(pdev); + + fpga_bridge_unregister(br); return 0; } diff --git a/drivers/fpga/altera-hps2fpga.c b/drivers/fpga/altera-hps2fpga.c index 406d2f10741f..e4d39f0a7572 100644 --- a/drivers/fpga/altera-hps2fpga.c +++ b/drivers/fpga/altera-hps2fpga.c @@ -139,6 +139,7 @@ static int alt_fpga_bridge_probe(struct platform_device *pdev) struct device *dev = &pdev->dev; struct altera_hps2fpga_data *priv; const struct of_device_id *of_id; + struct fpga_bridge *br; u32 enable; int ret; @@ -190,11 +191,24 @@ static int alt_fpga_bridge_probe(struct platform_device *pdev) } } - ret = fpga_bridge_register(dev, priv->name, &altera_hps2fpga_br_ops, - priv); -err: + br = fpga_bridge_create(dev, priv->name, &altera_hps2fpga_br_ops, priv); + if (!br) { + ret = -ENOMEM; + goto err; + } + + platform_set_drvdata(pdev, br); + + ret = fpga_bridge_register(br); if (ret) - clk_disable_unprepare(priv->clk); + goto err_free; + + return 0; + +err_free: + fpga_bridge_free(br); +err: + clk_disable_unprepare(priv->clk); return ret; } @@ -204,7 +218,7 @@ static int alt_fpga_bridge_remove(struct platform_device *pdev) struct fpga_bridge *bridge = platform_get_drvdata(pdev); struct altera_hps2fpga_data *priv = bridge->priv; - fpga_bridge_unregister(&pdev->dev); + fpga_bridge_unregister(bridge); clk_disable_unprepare(priv->clk); diff --git a/drivers/fpga/fpga-bridge.c b/drivers/fpga/fpga-bridge.c index 31bd2c59c305..2db1573507eb 100644 --- a/drivers/fpga/fpga-bridge.c +++ b/drivers/fpga/fpga-bridge.c @@ -328,28 +328,29 @@ static struct attribute *fpga_bridge_attrs[] = { ATTRIBUTE_GROUPS(fpga_bridge); /** - * fpga_bridge_register - register a fpga bridge driver + * fpga_bridge_create - create and initialize a struct fpga_bridge * @dev: FPGA bridge device from pdev * @name: FPGA bridge name * @br_ops: pointer to structure of fpga bridge ops * @priv: FPGA bridge private data * - * Return: 0 for success, error code otherwise. + * Return: struct fpga_bridge or NULL */ -int fpga_bridge_register(struct device *dev, const char *name, - const struct fpga_bridge_ops *br_ops, void *priv) +struct fpga_bridge *fpga_bridge_create(struct device *dev, const char *name, + const struct fpga_bridge_ops *br_ops, + void *priv) { struct fpga_bridge *bridge; int id, ret = 0; if (!name || !strlen(name)) { dev_err(dev, "Attempt to register with no name!\n"); - return -EINVAL; + return NULL; } bridge = kzalloc(sizeof(*bridge), GFP_KERNEL); if (!bridge) - return -ENOMEM; + return NULL; id = ida_simple_get(&fpga_bridge_ida, 0, 0, GFP_KERNEL); if (id < 0) { @@ -370,40 +371,62 @@ int fpga_bridge_register(struct device *dev, const char *name, bridge->dev.parent = dev; bridge->dev.of_node = dev->of_node; bridge->dev.id = id; - dev_set_drvdata(dev, bridge); ret = dev_set_name(&bridge->dev, "br%d", id); if (ret) goto error_device; - ret = device_add(&bridge->dev); - if (ret) - goto error_device; - - of_platform_populate(dev->of_node, NULL, NULL, dev); - - dev_info(bridge->dev.parent, "fpga bridge [%s] registered\n", - bridge->name); - - return 0; + return bridge; error_device: ida_simple_remove(&fpga_bridge_ida, id); error_kfree: kfree(bridge); - return ret; + return NULL; +} +EXPORT_SYMBOL_GPL(fpga_bridge_create); + +/** + * fpga_bridge_free - free a fpga bridge and its id + * @bridge: FPGA bridge struct created by fpga_bridge_create + */ +void fpga_bridge_free(struct fpga_bridge *bridge) +{ + ida_simple_remove(&fpga_bridge_ida, bridge->dev.id); + kfree(bridge); +} +EXPORT_SYMBOL_GPL(fpga_bridge_free); + +/** + * fpga_bridge_register - register a fpga bridge + * @bridge: FPGA bridge struct created by fpga_bridge_create + * + * Return: 0 for success, error code otherwise. + */ +int fpga_bridge_register(struct fpga_bridge *bridge) +{ + struct device *dev = &bridge->dev; + int ret; + + ret = device_add(dev); + if (ret) + return ret; + + of_platform_populate(dev->of_node, NULL, NULL, dev); + + dev_info(dev->parent, "fpga bridge [%s] registered\n", bridge->name); + + return 0; } EXPORT_SYMBOL_GPL(fpga_bridge_register); /** * fpga_bridge_unregister - unregister a fpga bridge driver - * @dev: FPGA bridge device from pdev + * @bridge: FPGA bridge struct created by fpga_bridge_create */ -void fpga_bridge_unregister(struct device *dev) +void fpga_bridge_unregister(struct fpga_bridge *bridge) { - struct fpga_bridge *bridge = dev_get_drvdata(dev); - /* * If the low level driver provides a method for putting bridge into * a desired state upon unregister, do it. @@ -419,8 +442,7 @@ static void fpga_bridge_dev_release(struct device *dev) { struct fpga_bridge *bridge = to_fpga_bridge(dev); - ida_simple_remove(&fpga_bridge_ida, bridge->dev.id); - kfree(bridge); + fpga_bridge_free(bridge); } static int __init fpga_bridge_dev_init(void) diff --git a/drivers/fpga/xilinx-pr-decoupler.c b/drivers/fpga/xilinx-pr-decoupler.c index 0d7743089414..07ba1539e82c 100644 --- a/drivers/fpga/xilinx-pr-decoupler.c +++ b/drivers/fpga/xilinx-pr-decoupler.c @@ -94,6 +94,7 @@ MODULE_DEVICE_TABLE(of, xlnx_pr_decoupler_of_match); static int xlnx_pr_decoupler_probe(struct platform_device *pdev) { struct xlnx_pr_decoupler_data *priv; + struct fpga_bridge *br; int err; struct resource *res; @@ -120,16 +121,27 @@ static int xlnx_pr_decoupler_probe(struct platform_device *pdev) clk_disable(priv->clk); - err = fpga_bridge_register(&pdev->dev, "Xilinx PR Decoupler", - &xlnx_pr_decoupler_br_ops, priv); + br = fpga_bridge_create(&pdev->dev, "Xilinx PR Decoupler", + &xlnx_pr_decoupler_br_ops, priv); + if (!br) { + err = -ENOMEM; + goto err_clk; + } + + platform_set_drvdata(pdev, br); + err = fpga_bridge_register(br); if (err) { dev_err(&pdev->dev, "unable to register Xilinx PR Decoupler"); - clk_unprepare(priv->clk); - return err; + goto err_clk; } return 0; + +err_clk: + clk_unprepare(priv->clk); + + return err; } static int xlnx_pr_decoupler_remove(struct platform_device *pdev) @@ -137,7 +149,7 @@ static int xlnx_pr_decoupler_remove(struct platform_device *pdev) struct fpga_bridge *bridge = platform_get_drvdata(pdev); struct xlnx_pr_decoupler_data *p = bridge->priv; - fpga_bridge_unregister(&pdev->dev); + fpga_bridge_unregister(bridge); clk_unprepare(p->clk); diff --git a/include/linux/fpga/fpga-bridge.h b/include/linux/fpga/fpga-bridge.h index 3694821a6d2d..ce550fcf6360 100644 --- a/include/linux/fpga/fpga-bridge.h +++ b/include/linux/fpga/fpga-bridge.h @@ -62,8 +62,11 @@ int of_fpga_bridge_get_to_list(struct device_node *np, struct fpga_image_info *info, struct list_head *bridge_list); -int fpga_bridge_register(struct device *dev, const char *name, - const struct fpga_bridge_ops *br_ops, void *priv); -void fpga_bridge_unregister(struct device *dev); +struct fpga_bridge *fpga_bridge_create(struct device *dev, const char *name, + const struct fpga_bridge_ops *br_ops, + void *priv); +void fpga_bridge_free(struct fpga_bridge *br); +int fpga_bridge_register(struct fpga_bridge *br); +void fpga_bridge_unregister(struct fpga_bridge *br); #endif /* _LINUX_FPGA_BRIDGE_H */