From patchwork Fri Jul 9 18:45:09 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Tom Rix X-Patchwork-Id: 12367815 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-17.4 required=3.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER, INCLUDES_PATCH,MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 585B8C07E99 for ; Fri, 9 Jul 2021 18:47:25 +0000 (UTC) Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 29906613B7 for ; Fri, 9 Jul 2021 18:47:25 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 29906613B7 Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=redhat.com Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender: Content-Transfer-Encoding:Content-Type:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To: Message-Id:Date:Subject:Cc:To:From:Reply-To:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Owner; bh=nF+avZHIWDVZaJYLVftYWgCEUz8Mw0y+RfeXCmXpmhU=; b=Pk6HX/RdYG8UiG 01Nbje1hWY5WFPoOyzGAbsMpAQFalksisZPzUBUPft6dRkZyV0fZWLyC0VvRQqMsetW639Pbou1Qg MqDvtpzJzMxokGdUL6Hj8OeAxi3eMufz4JG05RlHqcVj11tT3Luuk5NUbRiQmQ7UFiAgazBxSBaxM I8Q5hUlgTqNPt7IHcBrG2szr7ACTO98PPIp398mwDBsK9/6eoe8w77E9D0rSuWA1rzqY7FKOC/qQ6 TlLLA3RY3s1TRUyFqL2Q22RUkNE5abkt9psWxdrJW5gADC/S5jEiZ3WRkQlI3xfZASA8has1N9fvy rWNywXX7aP6cGKYSbehA==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.94.2 #2 (Red Hat Linux)) id 1m1vVP-002K6A-Eh; Fri, 09 Jul 2021 18:45:43 +0000 Received: from us-smtp-delivery-124.mimecast.com ([170.10.133.124]) by bombadil.infradead.org with esmtps (Exim 4.94.2 #2 (Red Hat Linux)) id 1m1vVG-002K4y-HH for linux-arm-kernel@lists.infradead.org; Fri, 09 Jul 2021 18:45:38 +0000 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1625856333; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=ZE+8I+fCwfENmMykXhY87Q7jxn2ECw/J1dlCjcQ+Uls=; b=I4IK5fzC8XG/7raG350Jp6f56ildEMhEsWkWsX7SpMYwSb5uS5eZrGEbUM1K34R9C8LOn4 /6jMMh1paddeeyzEVBPw58SAQhHh4TDKvBQ9yoz8mKaycEdP7F9fpVBxlAaYEoaOngcYQB zYRcOaT+Moz7gozB7IqcoPsDYlw1zBw= Received: from mail-oi1-f197.google.com (mail-oi1-f197.google.com [209.85.167.197]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-332-6wnKRR_FMwuNXW_4K9F1GQ-1; Fri, 09 Jul 2021 14:45:30 -0400 X-MC-Unique: 6wnKRR_FMwuNXW_4K9F1GQ-1 Received: by mail-oi1-f197.google.com with SMTP id o15-20020a0568080f8fb029023dd6814af4so7228138oiw.9 for ; Fri, 09 Jul 2021 11:45:30 -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:mime-version:content-transfer-encoding; bh=ZE+8I+fCwfENmMykXhY87Q7jxn2ECw/J1dlCjcQ+Uls=; b=NWohxUXdzGiEn8XrOd4+lip4nSoSzqlCcKPmVyPk1gk9TQUBry/5tA4lZqcMHNSkXM YKHkEgBdF+Y5RFG0qKmaKU9/Bb5R52CLocnnYV+8xqEHdbTgXW1I7KBNi5gqD0ubSNuI xx77iuRP+WOcHRxYaiqdrCEYOH+wct14I3QV/S14vsn7YyoyuNcLI6gh+XVyrRf9Z2A5 vXmpZvn7jhIcS4N433cWMLiu4bv2NR5bGBDc5SnBiskBAzL+GvgrukU7YIlEGJrByqE+ eHlF2hKnI2LkoI+ISalpE21I9WaX788zwYXCPtOfrMBWPnGF/bbmXvrDX7YPo0KtQsPu 2dBA== X-Gm-Message-State: AOAM531K0mGR8i3ZrMvRFJ2Tb74mNw51NuYKYZCVmGBY6xZFV2BbRGrX PI4XeHsxKCsPptprGyKAZpT3a5n1mn+bysWT6ykvbvK9m1ZLbjp3FcIl9niHOYPborvD2m7v2qO +DOmZWbo+DWXYOnonrQO+xvza9AWzJq1Jnhw= X-Received: by 2002:a05:6830:24a6:: with SMTP id v6mr27364620ots.116.1625856327905; Fri, 09 Jul 2021 11:45:27 -0700 (PDT) X-Google-Smtp-Source: ABdhPJwdRIyXJ2DESf9uOweCiMLi6c6iJom9u6aaW6CW/mSaNlMzgsZYVjyiKhROcO4KzpqR3nXyEw== X-Received: by 2002:a05:6830:24a6:: with SMTP id v6mr27364558ots.116.1625856326800; Fri, 09 Jul 2021 11:45:26 -0700 (PDT) Received: from localhost.localdomain.com (075-142-250-213.res.spectrum.com. [75.142.250.213]) by smtp.gmail.com with ESMTPSA id a44sm1145482ooj.12.2021.07.09.11.45.25 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 09 Jul 2021 11:45:26 -0700 (PDT) From: trix@redhat.com To: mdf@kernel.org, corbet@lwn.net, hao.wu@intel.com, michal.simek@xilinx.com Cc: linux-fpga@vger.kernel.org, linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org, Russ Weight , Tom Rix , Xu Yilun Subject: [RFC PATCH v10 1/3] fpga: mgr: Use standard dev_release for class driver Date: Fri, 9 Jul 2021 11:45:09 -0700 Message-Id: <20210709184511.2521508-3-trix@redhat.com> X-Mailer: git-send-email 2.26.3 In-Reply-To: <20210709184511.2521508-1-trix@redhat.com> References: <20210709184511.2521508-1-trix@redhat.com> MIME-Version: 1.0 Authentication-Results: relay.mimecast.com; auth=pass smtp.auth=CUSA124A263 smtp.mailfrom=trix@redhat.com X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20210709_114535_400558_4065FA5F X-CRM114-Status: GOOD ( 27.20 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org From: Russ Weight The FPGA manager class driver data structure is being treated as a managed resource instead of using the standard dev_release call-back function to release the class data structure. This change removes the managed resource code for the freeing of the class data structure and combines the create() and register() functions into a single register() function. The devm_fpga_mgr_register() function is retained Signed-off-by: Russ Weight Signed-off-by: Tom Rix Reviewed-by: Xu Yilun --- Documentation/driver-api/fpga/fpga-mgr.rst | 23 +-- drivers/fpga/altera-cvp.c | 12 +- drivers/fpga/altera-pr-ip-core.c | 7 +- drivers/fpga/altera-ps-spi.c | 9 +- drivers/fpga/dfl-fme-mgr.c | 10 +- drivers/fpga/fpga-mgr.c | 166 ++++++--------------- drivers/fpga/ice40-spi.c | 9 +- drivers/fpga/machxo2-spi.c | 9 +- drivers/fpga/socfpga-a10.c | 16 +- drivers/fpga/socfpga.c | 9 +- drivers/fpga/stratix10-soc.c | 16 +- drivers/fpga/ts73xx-fpga.c | 9 +- drivers/fpga/xilinx-spi.c | 11 +- drivers/fpga/zynq-fpga.c | 16 +- drivers/fpga/zynqmp-fpga.c | 9 +- include/linux/fpga/fpga-mgr.h | 16 +- 16 files changed, 111 insertions(+), 236 deletions(-) diff --git a/Documentation/driver-api/fpga/fpga-mgr.rst b/Documentation/driver-api/fpga/fpga-mgr.rst index 917ee22db429d..86488aa9391a5 100644 --- a/Documentation/driver-api/fpga/fpga-mgr.rst +++ b/Documentation/driver-api/fpga/fpga-mgr.rst @@ -49,14 +49,14 @@ probe function calls fpga_mgr_register(), such as:: * them in priv */ - mgr = devm_fpga_mgr_create(dev, "Altera SOCFPGA FPGA Manager", - &socfpga_fpga_ops, priv); - if (!mgr) - return -ENOMEM; + mgr = fpga_mgr_register(dev, "Altera SOCFPGA FPGA Manager", + &socfpga_fpga_ops, priv); + if (IS_ERR(mgr)) + return PTR_ERR(mgr); platform_set_drvdata(pdev, mgr); - return fpga_mgr_register(mgr); + return 0; } static int socfpga_fpga_remove(struct platform_device *pdev) @@ -68,6 +68,11 @@ probe function calls fpga_mgr_register(), such as:: return 0; } +Alternatively, the probe function could call the resource managed register +functions devm_fpga_mgr_register(). When these functions are used, the +parameter syntax is the same, but the call to fpga_mgr_unregister() should +be removed. In the above example, the socfpga_fpga_remove() function would +not be required. The ops will implement whatever device specific register writes are needed to do the programming sequence for this particular FPGA. These ops return 0 for @@ -104,8 +109,8 @@ API for implementing a new FPGA Manager driver * ``fpga_mgr_states`` — Values for :c:expr:`fpga_manager->state`. * struct fpga_manager — the FPGA manager struct * struct fpga_manager_ops — Low level FPGA manager driver ops -* devm_fpga_mgr_create() — Allocate and init a manager struct -* fpga_mgr_register() — Register an FPGA manager +* fpga_mgr_register() — Create and register an FPGA manager +* devm_fpga_mgr_register() — Resource managed version of fpga_mgr_register() * fpga_mgr_unregister() — Unregister an FPGA manager .. kernel-doc:: include/linux/fpga/fpga-mgr.h @@ -118,10 +123,10 @@ API for implementing a new FPGA Manager driver :functions: fpga_manager_ops .. kernel-doc:: drivers/fpga/fpga-mgr.c - :functions: devm_fpga_mgr_create + :functions: fpga_mgr_register .. kernel-doc:: drivers/fpga/fpga-mgr.c - :functions: fpga_mgr_register + :functions: devm_fpga_mgr_register .. kernel-doc:: drivers/fpga/fpga-mgr.c :functions: fpga_mgr_unregister diff --git a/drivers/fpga/altera-cvp.c b/drivers/fpga/altera-cvp.c index 4e0edb60bfba6..b61020ceb0a1e 100644 --- a/drivers/fpga/altera-cvp.c +++ b/drivers/fpga/altera-cvp.c @@ -652,19 +652,15 @@ static int altera_cvp_probe(struct pci_dev *pdev, snprintf(conf->mgr_name, sizeof(conf->mgr_name), "%s @%s", ALTERA_CVP_MGR_NAME, pci_name(pdev)); - mgr = devm_fpga_mgr_create(&pdev->dev, conf->mgr_name, - &altera_cvp_ops, conf); - if (!mgr) { - ret = -ENOMEM; + mgr = fpga_mgr_register(&pdev->dev, conf->mgr_name, + &altera_cvp_ops, conf); + if (IS_ERR(mgr)) { + ret = PTR_ERR(mgr); goto err_unmap; } pci_set_drvdata(pdev, mgr); - ret = fpga_mgr_register(mgr); - if (ret) - goto err_unmap; - return 0; err_unmap: diff --git a/drivers/fpga/altera-pr-ip-core.c b/drivers/fpga/altera-pr-ip-core.c index dfdf21ed34c4e..be0667968d33b 100644 --- a/drivers/fpga/altera-pr-ip-core.c +++ b/drivers/fpga/altera-pr-ip-core.c @@ -191,11 +191,8 @@ int alt_pr_register(struct device *dev, void __iomem *reg_base) (val & ALT_PR_CSR_STATUS_MSK) >> ALT_PR_CSR_STATUS_SFT, (int)(val & ALT_PR_CSR_PR_START)); - mgr = devm_fpga_mgr_create(dev, dev_name(dev), &alt_pr_ops, priv); - if (!mgr) - return -ENOMEM; - - return devm_fpga_mgr_register(dev, mgr); + mgr = devm_fpga_mgr_register(dev, dev_name(dev), &alt_pr_ops, priv); + return PTR_ERR_OR_ZERO(mgr); } EXPORT_SYMBOL_GPL(alt_pr_register); diff --git a/drivers/fpga/altera-ps-spi.c b/drivers/fpga/altera-ps-spi.c index 23bfd4d1ad0f7..5e1e009dba896 100644 --- a/drivers/fpga/altera-ps-spi.c +++ b/drivers/fpga/altera-ps-spi.c @@ -302,12 +302,9 @@ static int altera_ps_probe(struct spi_device *spi) snprintf(conf->mgr_name, sizeof(conf->mgr_name), "%s %s", dev_driver_string(&spi->dev), dev_name(&spi->dev)); - mgr = devm_fpga_mgr_create(&spi->dev, conf->mgr_name, - &altera_ps_ops, conf); - if (!mgr) - return -ENOMEM; - - return devm_fpga_mgr_register(&spi->dev, mgr); + mgr = devm_fpga_mgr_register(&spi->dev, conf->mgr_name, + &altera_ps_ops, conf); + return PTR_ERR_OR_ZERO(mgr); } static const struct spi_device_id altera_ps_spi_ids[] = { diff --git a/drivers/fpga/dfl-fme-mgr.c b/drivers/fpga/dfl-fme-mgr.c index 8c5423eeffe75..da509c4c029f6 100644 --- a/drivers/fpga/dfl-fme-mgr.c +++ b/drivers/fpga/dfl-fme-mgr.c @@ -313,12 +313,12 @@ static int fme_mgr_probe(struct platform_device *pdev) _fme_mgr_get_compat_id(priv->ioaddr, &priv->compat_id); - mgr = devm_fpga_mgr_create(dev, "DFL FME FPGA Manager", - &fme_mgr_ops, priv); - if (!mgr) - return -ENOMEM; + mgr = devm_fpga_mgr_register(dev, "DFL FME FPGA Manager", + &fme_mgr_ops, priv); + if (IS_ERR(mgr)) + return PTR_ERR(mgr); - return devm_fpga_mgr_register(dev, mgr); + return 0; } static struct platform_driver fme_mgr_driver = { diff --git a/drivers/fpga/fpga-mgr.c b/drivers/fpga/fpga-mgr.c index ecb4c3c795fa5..e240a23df79ff 100644 --- a/drivers/fpga/fpga-mgr.c +++ b/drivers/fpga/fpga-mgr.c @@ -550,20 +550,20 @@ void fpga_mgr_unlock(struct fpga_manager *mgr) EXPORT_SYMBOL_GPL(fpga_mgr_unlock); /** - * fpga_mgr_create - create and initialize an FPGA manager struct + * fpga_mgr_register - create and register an FPGA Manager device * @parent: fpga manager device from pdev * @name: fpga manager name * @mops: pointer to structure of fpga manager ops * @priv: fpga manager private data * - * The caller of this function is responsible for freeing the struct with - * fpga_mgr_free(). Using devm_fpga_mgr_create() instead is recommended. + * The caller of this function is responsible for calling fpga_mgr_unregister(). + * Using devm_fpga_mgr_register() instead is recommended. * - * Return: pointer to struct fpga_manager or NULL + * Return: pointer to struct fpga_manager pointer or ERR_PTR() */ -struct fpga_manager *fpga_mgr_create(struct device *parent, const char *name, - const struct fpga_manager_ops *mops, - void *priv) +struct fpga_manager * +fpga_mgr_register(struct device *parent, const char *name, + const struct fpga_manager_ops *mops, void *priv) { struct fpga_manager *mgr; int id, ret; @@ -572,21 +572,23 @@ struct fpga_manager *fpga_mgr_create(struct device *parent, const char *name, !mops->write_init || (!mops->write && !mops->write_sg) || (mops->write && mops->write_sg)) { dev_err(parent, "Attempt to register without fpga_manager_ops\n"); - return NULL; + return ERR_PTR(-EINVAL); } if (!name || !strlen(name)) { dev_err(parent, "Attempt to register with no name!\n"); - return NULL; + return ERR_PTR(-EINVAL); } mgr = kzalloc(sizeof(*mgr), GFP_KERNEL); if (!mgr) - return NULL; + return ERR_PTR(-ENOMEM); id = ida_simple_get(&fpga_mgr_ida, 0, 0, GFP_KERNEL); - if (id < 0) + if (id < 0) { + ret = id; goto error_kfree; + } mutex_init(&mgr->ref_mutex); @@ -594,7 +596,6 @@ struct fpga_manager *fpga_mgr_create(struct device *parent, const char *name, mgr->mops = mops; mgr->priv = priv; - device_initialize(&mgr->dev); mgr->dev.class = fpga_mgr_class; mgr->dev.groups = mops->groups; mgr->dev.parent = parent; @@ -605,84 +606,6 @@ struct fpga_manager *fpga_mgr_create(struct device *parent, const char *name, if (ret) goto error_device; - return mgr; - -error_device: - ida_simple_remove(&fpga_mgr_ida, id); -error_kfree: - kfree(mgr); - - return NULL; -} -EXPORT_SYMBOL_GPL(fpga_mgr_create); - -/** - * fpga_mgr_free - free an FPGA manager created with fpga_mgr_create() - * @mgr: fpga manager struct - */ -void fpga_mgr_free(struct fpga_manager *mgr) -{ - ida_simple_remove(&fpga_mgr_ida, mgr->dev.id); - kfree(mgr); -} -EXPORT_SYMBOL_GPL(fpga_mgr_free); - -static void devm_fpga_mgr_release(struct device *dev, void *res) -{ - struct fpga_mgr_devres *dr = res; - - fpga_mgr_free(dr->mgr); -} - -/** - * devm_fpga_mgr_create - create and initialize a managed FPGA manager struct - * @parent: fpga manager device from pdev - * @name: fpga manager name - * @mops: pointer to structure of fpga manager ops - * @priv: fpga manager private data - * - * This function is intended for use in an FPGA manager driver's probe function. - * After the manager driver creates the manager struct with - * devm_fpga_mgr_create(), it should register it with fpga_mgr_register(). The - * manager driver's remove function should call fpga_mgr_unregister(). The - * manager struct allocated with this function will be freed automatically on - * driver detach. This includes the case of a probe function returning error - * before calling fpga_mgr_register(), the struct will still get cleaned up. - * - * Return: pointer to struct fpga_manager or NULL - */ -struct fpga_manager *devm_fpga_mgr_create(struct device *parent, const char *name, - const struct fpga_manager_ops *mops, - void *priv) -{ - struct fpga_mgr_devres *dr; - - dr = devres_alloc(devm_fpga_mgr_release, sizeof(*dr), GFP_KERNEL); - if (!dr) - return NULL; - - dr->mgr = fpga_mgr_create(parent, name, mops, priv); - if (!dr->mgr) { - devres_free(dr); - return NULL; - } - - devres_add(parent, dr); - - return dr->mgr; -} -EXPORT_SYMBOL_GPL(devm_fpga_mgr_create); - -/** - * fpga_mgr_register - register an FPGA manager - * @mgr: fpga manager struct - * - * Return: 0 on success, negative error code otherwise. - */ -int fpga_mgr_register(struct fpga_manager *mgr) -{ - int ret; - /* * Initialize framework state by requesting low level driver read state * from device. FPGA may be in reset mode or may have been programmed @@ -690,18 +613,20 @@ int fpga_mgr_register(struct fpga_manager *mgr) */ mgr->state = mgr->mops->state(mgr); - ret = device_add(&mgr->dev); - if (ret) - goto error_device; - - dev_info(&mgr->dev, "%s registered\n", mgr->name); + ret = device_register(&mgr->dev); + if (ret) { + put_device(&mgr->dev); + return ERR_PTR(ret); + } - return 0; + return mgr; error_device: - ida_simple_remove(&fpga_mgr_ida, mgr->dev.id); + ida_simple_remove(&fpga_mgr_ida, id); +error_kfree: + kfree(mgr); - return ret; + return ERR_PTR(ret); } EXPORT_SYMBOL_GPL(fpga_mgr_register); @@ -726,14 +651,6 @@ void fpga_mgr_unregister(struct fpga_manager *mgr) } EXPORT_SYMBOL_GPL(fpga_mgr_unregister); -static int fpga_mgr_devres_match(struct device *dev, void *res, - void *match_data) -{ - struct fpga_mgr_devres *dr = res; - - return match_data == dr->mgr; -} - static void devm_fpga_mgr_unregister(struct device *dev, void *res) { struct fpga_mgr_devres *dr = res; @@ -743,44 +660,45 @@ static void devm_fpga_mgr_unregister(struct device *dev, void *res) /** * devm_fpga_mgr_register - resource managed variant of fpga_mgr_register() - * @dev: managing device for this FPGA manager - * @mgr: fpga manager struct + * @parent: fpga manager device from pdev + * @info: parameters for fpga manager + * @name: fpga manager name + * @mops: pointer to structure of fpga manager ops + * @priv: fpga manager private data * * This is the devres variant of fpga_mgr_register() for which the unregister * function will be called automatically when the managing device is detached. */ -int devm_fpga_mgr_register(struct device *dev, struct fpga_manager *mgr) +struct fpga_manager * +devm_fpga_mgr_register(struct device *parent, const char *name, + const struct fpga_manager_ops *mops, void *priv) { struct fpga_mgr_devres *dr; - int ret; - - /* - * Make sure that the struct fpga_manager * that is passed in is - * managed itself. - */ - if (WARN_ON(!devres_find(dev, devm_fpga_mgr_release, - fpga_mgr_devres_match, mgr))) - return -EINVAL; + struct fpga_manager *mgr; dr = devres_alloc(devm_fpga_mgr_unregister, sizeof(*dr), GFP_KERNEL); if (!dr) - return -ENOMEM; + return ERR_PTR(-ENOMEM); - ret = fpga_mgr_register(mgr); - if (ret) { + mgr = fpga_mgr_register(parent, name, mops, priv); + if (IS_ERR(mgr)) { devres_free(dr); - return ret; + return mgr; } dr->mgr = mgr; - devres_add(dev, dr); + devres_add(parent, dr); - return 0; + return mgr; } EXPORT_SYMBOL_GPL(devm_fpga_mgr_register); static void fpga_mgr_dev_release(struct device *dev) { + struct fpga_manager *mgr = to_fpga_manager(dev); + + ida_simple_remove(&fpga_mgr_ida, mgr->dev.id); + kfree(mgr); } static int __init fpga_mgr_class_init(void) diff --git a/drivers/fpga/ice40-spi.c b/drivers/fpga/ice40-spi.c index 69dec5af23c36..b7591912248fc 100644 --- a/drivers/fpga/ice40-spi.c +++ b/drivers/fpga/ice40-spi.c @@ -178,12 +178,9 @@ static int ice40_fpga_probe(struct spi_device *spi) return ret; } - mgr = devm_fpga_mgr_create(dev, "Lattice iCE40 FPGA Manager", - &ice40_fpga_ops, priv); - if (!mgr) - return -ENOMEM; - - return devm_fpga_mgr_register(dev, mgr); + mgr = devm_fpga_mgr_register(dev, "Lattice iCE40 FPGA Manager", + &ice40_fpga_ops, priv); + return PTR_ERR_OR_ZERO(mgr); } static const struct of_device_id ice40_fpga_of_match[] = { diff --git a/drivers/fpga/machxo2-spi.c b/drivers/fpga/machxo2-spi.c index 1afb41aa20d71..8469dfb5dd219 100644 --- a/drivers/fpga/machxo2-spi.c +++ b/drivers/fpga/machxo2-spi.c @@ -366,12 +366,9 @@ static int machxo2_spi_probe(struct spi_device *spi) return -EINVAL; } - mgr = devm_fpga_mgr_create(dev, "Lattice MachXO2 SPI FPGA Manager", - &machxo2_ops, spi); - if (!mgr) - return -ENOMEM; - - return devm_fpga_mgr_register(dev, mgr); + mgr = devm_fpga_mgr_register(dev, "Lattice MachXO2 SPI FPGA Manager", + &machxo2_ops, spi); + return PTR_ERR_OR_ZERO(mgr); } #ifdef CONFIG_OF diff --git a/drivers/fpga/socfpga-a10.c b/drivers/fpga/socfpga-a10.c index 573d88bdf7307..ac8e89b8a5cc9 100644 --- a/drivers/fpga/socfpga-a10.c +++ b/drivers/fpga/socfpga-a10.c @@ -508,19 +508,15 @@ static int socfpga_a10_fpga_probe(struct platform_device *pdev) return -EBUSY; } - mgr = devm_fpga_mgr_create(dev, "SoCFPGA Arria10 FPGA Manager", - &socfpga_a10_fpga_mgr_ops, priv); - if (!mgr) - return -ENOMEM; - - platform_set_drvdata(pdev, mgr); - - ret = fpga_mgr_register(mgr); - if (ret) { + mgr = fpga_mgr_register(dev, "SoCFPGA Arria10 FPGA Manager", + &socfpga_a10_fpga_mgr_ops, priv); + if (IS_ERR(mgr)) { clk_disable_unprepare(priv->clk); - return ret; + return PTR_ERR(mgr); } + platform_set_drvdata(pdev, mgr); + return 0; } diff --git a/drivers/fpga/socfpga.c b/drivers/fpga/socfpga.c index 1f467173fc1f3..7e0741f996968 100644 --- a/drivers/fpga/socfpga.c +++ b/drivers/fpga/socfpga.c @@ -571,12 +571,9 @@ static int socfpga_fpga_probe(struct platform_device *pdev) if (ret) return ret; - mgr = devm_fpga_mgr_create(dev, "Altera SOCFPGA FPGA Manager", - &socfpga_fpga_ops, priv); - if (!mgr) - return -ENOMEM; - - return devm_fpga_mgr_register(dev, mgr); + mgr = devm_fpga_mgr_register(dev, "Altera SOCFPGA FPGA Manager", + &socfpga_fpga_ops, priv); + return PTR_ERR_OR_ZERO(mgr); } #ifdef CONFIG_OF diff --git a/drivers/fpga/stratix10-soc.c b/drivers/fpga/stratix10-soc.c index a2cea500f7cc6..9155e888a133e 100644 --- a/drivers/fpga/stratix10-soc.c +++ b/drivers/fpga/stratix10-soc.c @@ -425,18 +425,11 @@ static int s10_probe(struct platform_device *pdev) init_completion(&priv->status_return_completion); - mgr = fpga_mgr_create(dev, "Stratix10 SOC FPGA Manager", - &s10_ops, priv); - if (!mgr) { - dev_err(dev, "unable to create FPGA manager\n"); - ret = -ENOMEM; - goto probe_err; - } - - ret = fpga_mgr_register(mgr); - if (ret) { + mgr = fpga_mgr_register(dev, "Stratix10 SOC FPGA Manager", + &s10_ops, priv); + if (IS_ERR(mgr)) { dev_err(dev, "unable to register FPGA manager\n"); - fpga_mgr_free(mgr); + ret = PTR_ERR(mgr); goto probe_err; } @@ -454,7 +447,6 @@ static int s10_remove(struct platform_device *pdev) struct s10_priv *priv = mgr->priv; fpga_mgr_unregister(mgr); - fpga_mgr_free(mgr); stratix10_svc_free_channel(priv->chan); return 0; diff --git a/drivers/fpga/ts73xx-fpga.c b/drivers/fpga/ts73xx-fpga.c index 101f016c6ed8c..fd52de20ddb2b 100644 --- a/drivers/fpga/ts73xx-fpga.c +++ b/drivers/fpga/ts73xx-fpga.c @@ -122,12 +122,9 @@ static int ts73xx_fpga_probe(struct platform_device *pdev) if (IS_ERR(priv->io_base)) return PTR_ERR(priv->io_base); - mgr = devm_fpga_mgr_create(kdev, "TS-73xx FPGA Manager", - &ts73xx_fpga_ops, priv); - if (!mgr) - return -ENOMEM; - - return devm_fpga_mgr_register(kdev, mgr); + mgr = devm_fpga_mgr_register(kdev, "TS-73xx FPGA Manager", + &ts73xx_fpga_ops, priv); + return PTR_ERR_OR_ZERO(mgr); } static struct platform_driver ts73xx_fpga_driver = { diff --git a/drivers/fpga/xilinx-spi.c b/drivers/fpga/xilinx-spi.c index fee4d0abf6bfe..db23626f9ab27 100644 --- a/drivers/fpga/xilinx-spi.c +++ b/drivers/fpga/xilinx-spi.c @@ -247,13 +247,10 @@ static int xilinx_spi_probe(struct spi_device *spi) return dev_err_probe(&spi->dev, PTR_ERR(conf->done), "Failed to get DONE gpio\n"); - mgr = devm_fpga_mgr_create(&spi->dev, - "Xilinx Slave Serial FPGA Manager", - &xilinx_spi_ops, conf); - if (!mgr) - return -ENOMEM; - - return devm_fpga_mgr_register(&spi->dev, mgr); + mgr = devm_fpga_mgr_register(&spi->dev, + "Xilinx Slave Serial FPGA Manager", + &xilinx_spi_ops, conf); + return PTR_ERR_OR_ZERO(mgr); } static const struct of_device_id xlnx_spi_of_match[] = { diff --git a/drivers/fpga/zynq-fpga.c b/drivers/fpga/zynq-fpga.c index 07fa8d9ec6750..74bbb9710f4ee 100644 --- a/drivers/fpga/zynq-fpga.c +++ b/drivers/fpga/zynq-fpga.c @@ -609,20 +609,16 @@ static int zynq_fpga_probe(struct platform_device *pdev) clk_disable(priv->clk); - mgr = devm_fpga_mgr_create(dev, "Xilinx Zynq FPGA Manager", - &zynq_fpga_ops, priv); - if (!mgr) - return -ENOMEM; - - platform_set_drvdata(pdev, mgr); - - err = fpga_mgr_register(mgr); - if (err) { + mgr = fpga_mgr_register(dev, "Xilinx Zynq FPGA Manager", + &zynq_fpga_ops, priv); + if (IS_ERR(mgr)) { dev_err(dev, "unable to register FPGA manager\n"); clk_unprepare(priv->clk); - return err; + return PTR_ERR(mgr); } + platform_set_drvdata(pdev, mgr); + return 0; } diff --git a/drivers/fpga/zynqmp-fpga.c b/drivers/fpga/zynqmp-fpga.c index 125743c9797ff..975bdc4d0a65e 100644 --- a/drivers/fpga/zynqmp-fpga.c +++ b/drivers/fpga/zynqmp-fpga.c @@ -102,12 +102,9 @@ static int zynqmp_fpga_probe(struct platform_device *pdev) priv->dev = dev; - mgr = devm_fpga_mgr_create(dev, "Xilinx ZynqMP FPGA Manager", - &zynqmp_fpga_ops, priv); - if (!mgr) - return -ENOMEM; - - return devm_fpga_mgr_register(dev, mgr); + mgr = devm_fpga_mgr_register(dev, "Xilinx ZynqMP FPGA Manager", + &zynqmp_fpga_ops, priv); + return PTR_ERR_OR_ZERO(mgr); } static const struct of_device_id zynqmp_fpga_of_match[] = { diff --git a/include/linux/fpga/fpga-mgr.h b/include/linux/fpga/fpga-mgr.h index ebdea215a8643..cd852d4e17839 100644 --- a/include/linux/fpga/fpga-mgr.h +++ b/include/linux/fpga/fpga-mgr.h @@ -178,17 +178,13 @@ struct fpga_manager *fpga_mgr_get(struct device *dev); void fpga_mgr_put(struct fpga_manager *mgr); -struct fpga_manager *fpga_mgr_create(struct device *dev, const char *name, - const struct fpga_manager_ops *mops, - void *priv); -void fpga_mgr_free(struct fpga_manager *mgr); -int fpga_mgr_register(struct fpga_manager *mgr); +struct fpga_manager * +fpga_mgr_register(struct device *parent, const char *name, + const struct fpga_manager_ops *mops, void *priv); void fpga_mgr_unregister(struct fpga_manager *mgr); -int devm_fpga_mgr_register(struct device *dev, struct fpga_manager *mgr); - -struct fpga_manager *devm_fpga_mgr_create(struct device *dev, const char *name, - const struct fpga_manager_ops *mops, - void *priv); +struct fpga_manager * +devm_fpga_mgr_register(struct device *parent, const char *name, + const struct fpga_manager_ops *mops, void *priv); #endif /*_LINUX_FPGA_MGR_H */ From patchwork Fri Jul 9 18:46:24 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Tom Rix X-Patchwork-Id: 12367835 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-17.4 required=3.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER, INCLUDES_PATCH,MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 60ECFC07E99 for ; Fri, 9 Jul 2021 18:48:20 +0000 (UTC) Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 29D15613B7 for ; Fri, 9 Jul 2021 18:48:20 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 29D15613B7 Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=redhat.com Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender: Content-Transfer-Encoding:Content-Type:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:MIME-Version:Message-Id:Date:Subject:Cc :To:From:Reply-To:Content-ID:Content-Description:Resent-Date:Resent-From: Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:In-Reply-To:References: List-Owner; bh=iEg+0Xuvl5c86RN4Y71pgqmlIffZBRThPYYEi9ZwTuM=; b=AZZwHSMfXFMsIw EBC4ypkQKx03qE+VZjeh8GItowbeQmx1ZjSw1b/xijZ4PljC66MvDMIINRJ9HdCWIsTDOoZCVAOpB ll8UuXkjprzuf6rWXJ8xwhZViU1FkLCXzKpDm+5e9giTkajVNduf6oLsoVox8k3HJrxQXR+Rlxly8 bNwmwV0BJLdLr10WO3FPAUYVPTUdgLxrcw8WpI+OXHQJ7IIm+SdpoBOTBEMtZlZAnr0j/VATk+P8r +mmEr/Vgslvl2LJII9iuY1FDnZHJcfDETQ2foXmdopxBL6KJKBWdZSJsAd976PGfQFegEsurqIJvN /oeq4rsbyMTdNCJ4wF/Q==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.94.2 #2 (Red Hat Linux)) id 1m1vWL-002KIs-3k; Fri, 09 Jul 2021 18:46:41 +0000 Received: from us-smtp-delivery-124.mimecast.com ([216.205.24.124]) by bombadil.infradead.org with esmtps (Exim 4.94.2 #2 (Red Hat Linux)) id 1m1vWG-002KHD-Pf for linux-arm-kernel@lists.infradead.org; Fri, 09 Jul 2021 18:46:39 +0000 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1625856395; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=zs305fSgOIpwBUwyxoV06D5N+pPR0pzJgrOMpwSsZcQ=; b=JkoLZLE6vv/TFAzDrlxdoTOwoLwrPL8Gu+JPPXQJQJ9Ym9GNzuaHjEEr0Dhp48HPYQKKFh aNkoCBp5xQ584XJxF0CMGgIYe056faN4sLQPby8bitj9iHVB/fASAAJK42G4P6L0GDSmOV 4sWqiu72MQSnRXfvYmPWbvk42OMZjVM= Received: from mail-oo1-f72.google.com (mail-oo1-f72.google.com [209.85.161.72]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-109-Spu7ZhReMGugO7luRnhjZA-1; Fri, 09 Jul 2021 14:46:34 -0400 X-MC-Unique: Spu7ZhReMGugO7luRnhjZA-1 Received: by mail-oo1-f72.google.com with SMTP id e25-20020a4ab9990000b029024aa2670b1cso6028153oop.21 for ; Fri, 09 Jul 2021 11:46:34 -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:mime-version :content-transfer-encoding; bh=zs305fSgOIpwBUwyxoV06D5N+pPR0pzJgrOMpwSsZcQ=; b=cc6sU/mJGk3r+SwRkcZ35AHTmtwEr5pxNR9caLGVDhnKC2iaqehXBNMPkerLKPnk+M GM2Y9BSc2IFMBOvOhQb0gApaP0yVWBcZTsmEcqbbkCxC/F3NJ4KUGmjbC0U6fjTU7ARM JH8q2NNXcirxG0H1lYceQ2lpuj0+lRjnzbpQgvDKv1dh4BesKzXWsvSI55nXNotINY1a geWni2vWLfOs4OPwDv5o3gRBN1CvcbYb8OZZDp6CgK+wWiYo9Eznv3ekQd+Ico9nhscq sqT74RPaSw09eZmvkaLZCw5tk/Hoy4bd4LJnlTnjx/Dp/0nropVu21fMvgkSA3EO0K+p uBQQ== X-Gm-Message-State: AOAM531a1Gl8puX185gGWP9VTkQHP1D4j/MmRyyn/HsL7s7GDzaLXoO2 omLjr2TmkQbOPfXuXEcb42eQe+gFlEt1XcwhLVEOWYnSX2TO2TAU/jYtYTE8MXvcd7OpTVTOx6M pZAiKHHpb/L/9xWDtdVBG7BHcN0T67WIWa90= X-Received: by 2002:aca:ac56:: with SMTP id v83mr24688238oie.178.1625856393896; Fri, 09 Jul 2021 11:46:33 -0700 (PDT) X-Google-Smtp-Source: ABdhPJyQoY3lLhGCPXuBrfIZlHf4LBNGDrj5opH2RMTGDYa5nR+h1WiTlX/2LBWkFQaE+45NVvAnkQ== X-Received: by 2002:aca:ac56:: with SMTP id v83mr24688220oie.178.1625856393658; Fri, 09 Jul 2021 11:46:33 -0700 (PDT) Received: from localhost.localdomain.com (075-142-250-213.res.spectrum.com. [75.142.250.213]) by smtp.gmail.com with ESMTPSA id l8sm1365245otk.81.2021.07.09.11.46.32 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 09 Jul 2021 11:46:33 -0700 (PDT) From: trix@redhat.com To: mdf@kernel.org, corbet@lwn.net, hao.wu@intel.com, michal.simek@xilinx.com Cc: linux-fpga@vger.kernel.org, linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org, Russ Weight , Xu Yilun , Tom Rix Subject: [RFC PATCH v10 2/3] fpga: bridge: Use standard dev_release for class driver Date: Fri, 9 Jul 2021 11:46:24 -0700 Message-Id: <20210709184624.2521751-1-trix@redhat.com> X-Mailer: git-send-email 2.26.3 MIME-Version: 1.0 Authentication-Results: relay.mimecast.com; auth=pass smtp.auth=CUSA124A263 smtp.mailfrom=trix@redhat.com X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20210709_114637_078139_12F6FDCB X-CRM114-Status: GOOD ( 26.69 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org From: Russ Weight The FPGA bridge class driver data structure is being treated as a managed resource instead of using the standard dev_release call-back function to release the class data structure. This change removes the managed resource code and combines the create() and register() functions into a single register() function. Signed-off-by: Russ Weight Reviewed-by: Xu Yilun Reviewed-by: Tom Rix --- Documentation/driver-api/fpga/fpga-bridge.rst | 12 +- drivers/fpga/altera-fpga2sdram.c | 12 +- drivers/fpga/altera-freeze-bridge.c | 10 +- drivers/fpga/altera-hps2fpga.c | 12 +- drivers/fpga/dfl-fme-br.c | 10 +- drivers/fpga/fpga-bridge.c | 122 ++++-------------- drivers/fpga/xilinx-pr-decoupler.c | 17 +-- include/linux/fpga/fpga-bridge.h | 30 +++-- 8 files changed, 77 insertions(+), 148 deletions(-) diff --git a/Documentation/driver-api/fpga/fpga-bridge.rst b/Documentation/driver-api/fpga/fpga-bridge.rst index 198aadafd3e7d..6042085340953 100644 --- a/Documentation/driver-api/fpga/fpga-bridge.rst +++ b/Documentation/driver-api/fpga/fpga-bridge.rst @@ -4,11 +4,10 @@ FPGA Bridge API to implement a new FPGA bridge ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -* struct fpga_bridge — The FPGA Bridge structure -* struct fpga_bridge_ops — Low level Bridge driver ops -* devm_fpga_bridge_create() — Allocate and init a bridge struct -* fpga_bridge_register() — Register a bridge -* fpga_bridge_unregister() — Unregister a bridge +* struct fpga_bridge - The FPGA Bridge structure +* struct fpga_bridge_ops - Low level Bridge driver ops +* fpga_bridge_register() - Create and register a bridge +* fpga_bridge_unregister() - Unregister a bridge .. kernel-doc:: include/linux/fpga/fpga-bridge.h :functions: fpga_bridge @@ -16,9 +15,6 @@ API to implement a new FPGA bridge .. kernel-doc:: include/linux/fpga/fpga-bridge.h :functions: fpga_bridge_ops -.. kernel-doc:: drivers/fpga/fpga-bridge.c - :functions: devm_fpga_bridge_create - .. kernel-doc:: drivers/fpga/fpga-bridge.c :functions: fpga_bridge_register diff --git a/drivers/fpga/altera-fpga2sdram.c b/drivers/fpga/altera-fpga2sdram.c index a78e49c63c640..66063507116b7 100644 --- a/drivers/fpga/altera-fpga2sdram.c +++ b/drivers/fpga/altera-fpga2sdram.c @@ -121,17 +121,13 @@ 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); - br = devm_fpga_bridge_create(dev, F2S_BRIDGE_NAME, - &altera_fpga2sdram_br_ops, priv); - if (!br) - return -ENOMEM; + br = fpga_bridge_register(dev, F2S_BRIDGE_NAME, + &altera_fpga2sdram_br_ops, priv); + if (IS_ERR(br)) + return PTR_ERR(mgr); platform_set_drvdata(pdev, br); - ret = fpga_bridge_register(br); - if (ret) - return ret; - dev_info(dev, "driver initialized with handoff %08x\n", priv->mask); if (!of_property_read_u32(dev->of_node, "bridge-enable", &enable)) { diff --git a/drivers/fpga/altera-freeze-bridge.c b/drivers/fpga/altera-freeze-bridge.c index dd58c4aea92ea..bfbfa43cd05bc 100644 --- a/drivers/fpga/altera-freeze-bridge.c +++ b/drivers/fpga/altera-freeze-bridge.c @@ -244,14 +244,14 @@ static int altera_freeze_br_probe(struct platform_device *pdev) priv->base_addr = base_addr; - br = devm_fpga_bridge_create(dev, FREEZE_BRIDGE_NAME, - &altera_freeze_br_br_ops, priv); - if (!br) - return -ENOMEM; + br = fpga_bridge_register(dev, FREEZE_BRIDGE_NAME, + &altera_freeze_br_br_ops, priv); + if (IS_ERR(br)) + return PTR_ERR(br); platform_set_drvdata(pdev, br); - return fpga_bridge_register(br); + return 0; } static int altera_freeze_br_remove(struct platform_device *pdev) diff --git a/drivers/fpga/altera-hps2fpga.c b/drivers/fpga/altera-hps2fpga.c index 77b95f2518216..aa758426c22bc 100644 --- a/drivers/fpga/altera-hps2fpga.c +++ b/drivers/fpga/altera-hps2fpga.c @@ -180,19 +180,15 @@ static int alt_fpga_bridge_probe(struct platform_device *pdev) } } - br = devm_fpga_bridge_create(dev, priv->name, - &altera_hps2fpga_br_ops, priv); - if (!br) { - ret = -ENOMEM; + br = fpga_bridge_register(dev, priv->name, + &altera_hps2fpga_br_ops, priv); + if (IS_ERR(br)) { + ret = PTR_ERR(br); goto err; } platform_set_drvdata(pdev, br); - ret = fpga_bridge_register(br); - if (ret) - goto err; - return 0; err: diff --git a/drivers/fpga/dfl-fme-br.c b/drivers/fpga/dfl-fme-br.c index 3ff9f3a687ce5..808d1f4d76df8 100644 --- a/drivers/fpga/dfl-fme-br.c +++ b/drivers/fpga/dfl-fme-br.c @@ -68,14 +68,14 @@ static int fme_br_probe(struct platform_device *pdev) priv->pdata = dev_get_platdata(dev); - br = devm_fpga_bridge_create(dev, "DFL FPGA FME Bridge", - &fme_bridge_ops, priv); - if (!br) - return -ENOMEM; + br = fpga_bridge_register(dev, "DFL FPGA FME Bridge", + &fme_bridge_ops, priv); + if (IS_ERR(br)) + return PTR_ERR(br); platform_set_drvdata(pdev, br); - return fpga_bridge_register(br); + return 0; } static int fme_br_remove(struct platform_device *pdev) diff --git a/drivers/fpga/fpga-bridge.c b/drivers/fpga/fpga-bridge.c index 2bfb2ff869305..16ae053afc30f 100644 --- a/drivers/fpga/fpga-bridge.c +++ b/drivers/fpga/fpga-bridge.c @@ -312,36 +312,41 @@ static struct attribute *fpga_bridge_attrs[] = { ATTRIBUTE_GROUPS(fpga_bridge); /** - * fpga_bridge_create - create and initialize a struct fpga_bridge + * fpga_bridge_register - create and register an FPGA Bridge device * @parent: FPGA bridge device from pdev * @name: FPGA bridge name * @br_ops: pointer to structure of fpga bridge ops * @priv: FPGA bridge private data * - * The caller of this function is responsible for freeing the bridge with - * fpga_bridge_free(). Using devm_fpga_bridge_create() instead is recommended. - * - * Return: struct fpga_bridge or NULL + * Return: struct fpga_bridge pointer or ERR_PTR() */ -struct fpga_bridge *fpga_bridge_create(struct device *parent, const char *name, - const struct fpga_bridge_ops *br_ops, - void *priv) +struct fpga_bridge * +fpga_bridge_register(struct device *parent, const char *name, + const struct fpga_bridge_ops *br_ops, + void *priv) { struct fpga_bridge *bridge; int id, ret; + if (!br_ops) { + dev_err(parent, "Attempt to register without fpga_bridge_ops\n"); + return ERR_PTR(-EINVAL); + } + if (!name || !strlen(name)) { dev_err(parent, "Attempt to register with no name!\n"); - return NULL; + return ERR_PTR(-EINVAL); } bridge = kzalloc(sizeof(*bridge), GFP_KERNEL); if (!bridge) - return NULL; + return ERR_PTR(-ENOMEM); id = ida_simple_get(&fpga_bridge_ida, 0, 0, GFP_KERNEL); - if (id < 0) + if (id < 0) { + ret = id; goto error_kfree; + } mutex_init(&bridge->mutex); INIT_LIST_HEAD(&bridge->node); @@ -350,17 +355,23 @@ struct fpga_bridge *fpga_bridge_create(struct device *parent, const char *name, bridge->br_ops = br_ops; bridge->priv = priv; - device_initialize(&bridge->dev); bridge->dev.groups = br_ops->groups; bridge->dev.class = fpga_bridge_class; bridge->dev.parent = parent; bridge->dev.of_node = parent->of_node; bridge->dev.id = id; + of_platform_populate(bridge->dev.of_node, NULL, NULL, &bridge->dev); ret = dev_set_name(&bridge->dev, "br%d", id); if (ret) goto error_device; + ret = device_register(&bridge->dev); + if (ret) { + put_device(&bridge->dev); + return ERR_PTR(ret); + } + return bridge; error_device: @@ -368,88 +379,7 @@ struct fpga_bridge *fpga_bridge_create(struct device *parent, const char *name, error_kfree: kfree(bridge); - return NULL; -} -EXPORT_SYMBOL_GPL(fpga_bridge_create); - -/** - * fpga_bridge_free - free an fpga bridge created by fpga_bridge_create() - * @bridge: FPGA bridge struct - */ -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); - -static void devm_fpga_bridge_release(struct device *dev, void *res) -{ - struct fpga_bridge *bridge = *(struct fpga_bridge **)res; - - fpga_bridge_free(bridge); -} - -/** - * devm_fpga_bridge_create - create and init a managed struct fpga_bridge - * @parent: FPGA bridge device from pdev - * @name: FPGA bridge name - * @br_ops: pointer to structure of fpga bridge ops - * @priv: FPGA bridge private data - * - * This function is intended for use in an FPGA bridge driver's probe function. - * After the bridge driver creates the struct with devm_fpga_bridge_create(), it - * should register the bridge with fpga_bridge_register(). The bridge driver's - * remove function should call fpga_bridge_unregister(). The bridge struct - * allocated with this function will be freed automatically on driver detach. - * This includes the case of a probe function returning error before calling - * fpga_bridge_register(), the struct will still get cleaned up. - * - * Return: struct fpga_bridge or NULL - */ -struct fpga_bridge -*devm_fpga_bridge_create(struct device *parent, const char *name, - const struct fpga_bridge_ops *br_ops, void *priv) -{ - struct fpga_bridge **ptr, *bridge; - - ptr = devres_alloc(devm_fpga_bridge_release, sizeof(*ptr), GFP_KERNEL); - if (!ptr) - return NULL; - - bridge = fpga_bridge_create(parent, name, br_ops, priv); - if (!bridge) { - devres_free(ptr); - } else { - *ptr = bridge; - devres_add(parent, ptr); - } - - return bridge; -} -EXPORT_SYMBOL_GPL(devm_fpga_bridge_create); - -/** - * fpga_bridge_register - register an FPGA bridge - * - * @bridge: FPGA bridge struct - * - * 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; + return ERR_PTR(ret); } EXPORT_SYMBOL_GPL(fpga_bridge_register); @@ -475,6 +405,10 @@ EXPORT_SYMBOL_GPL(fpga_bridge_unregister); 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); } 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 ea2bde6e5bc4e..c004e52b94646 100644 --- a/drivers/fpga/xilinx-pr-decoupler.c +++ b/drivers/fpga/xilinx-pr-decoupler.c @@ -138,22 +138,17 @@ static int xlnx_pr_decoupler_probe(struct platform_device *pdev) clk_disable(priv->clk); - br = devm_fpga_bridge_create(&pdev->dev, priv->ipconfig->name, - &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) { + br = fpga_bridge_register(&pdev->dev, priv->ipconfig->name, + &xlnx_pr_decoupler_br_ops, priv); + if (IS_ERR(br)) { + err = PTR_ERR(br); dev_err(&pdev->dev, "unable to register %s", priv->ipconfig->name); goto err_clk; } + platform_set_drvdata(pdev, br); + return 0; err_clk: diff --git a/include/linux/fpga/fpga-bridge.h b/include/linux/fpga/fpga-bridge.h index 6c3c28806ff13..223da48a6d18b 100644 --- a/include/linux/fpga/fpga-bridge.h +++ b/include/linux/fpga/fpga-bridge.h @@ -22,6 +22,23 @@ struct fpga_bridge_ops { const struct attribute_group **groups; }; +/** + * struct fpga_bridge_info - collection of parameters an FPGA Bridge + * @name: fpga bridge name + * @br_ops: pointer to structure of fpga bridge ops + * @priv: fpga bridge private data + * + * fpga_bridge_info contains parameters for the register function. These + * are separated into an info structure because they some are optional + * others could be added to in the future. The info structure facilitates + * maintaining a stable API. + */ +struct fpga_bridge_info { + const char *name; + const struct fpga_bridge_ops *br_ops; + void *priv; +}; + /** * struct fpga_bridge - FPGA bridge structure * @name: name of low level FPGA bridge @@ -62,15 +79,10 @@ int of_fpga_bridge_get_to_list(struct device_node *np, struct fpga_image_info *info, struct list_head *bridge_list); -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); +struct fpga_bridge * +fpga_bridge_register(struct device *parent, const char *name, + const struct fpga_bridge_ops *br_ops, + void *priv); void fpga_bridge_unregister(struct fpga_bridge *br); -struct fpga_bridge -*devm_fpga_bridge_create(struct device *dev, const char *name, - const struct fpga_bridge_ops *br_ops, void *priv); - #endif /* _LINUX_FPGA_BRIDGE_H */