Received: by 2002:ac0:a5a6:0:0:0:0:0 with SMTP id m35-v6csp948901imm; Wed, 26 Sep 2018 09:13:39 -0700 (PDT) X-Google-Smtp-Source: ACcGV60onpGdePV8n1iB2pZ+mYzF2avz896KSdA6uQnpsul82cK3t5fapJOt39vOzf6WLrTnWnxC X-Received: by 2002:a63:a362:: with SMTP id v34-v6mr6383932pgn.261.1537978419924; Wed, 26 Sep 2018 09:13:39 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1537978419; cv=none; d=google.com; s=arc-20160816; b=AFN11N6xOaUjOCNu6ub3/ZGePGdfAasGBS4gFjdakm7FIqqbrB5VFAyaJbrNBP3F9Q shhBPrOT9EOhlF1gSpqJWJHGpBDsSf4XShcyzvN6+wlX7Xx7dE4HQzfoxSduHBuDzVPU P5Pq25OIQDhzN2okmm+k607ek3w3RwlQSApzySPm8hlOWi61j9gDsluc0sbTcKQYsf5V VI5fTYQX4JVNHpX2ix4Av6QIlrwGGMPhfGr0YyVuxp1XABGUJXNvvU1W2wWixcD3Yu4p SRWnON20mSrhb/U8zb37Ys9gUZwxmIXZRM9QEGvwjPIsF+5s3kywanMdTSCOvYktFgZP 71fQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:references:in-reply-to:message-id:date :subject:cc:to:from:dkim-signature; bh=AMUgQvFCzrrsREohLT7LJLpkYnHESWkcSe388f1/1wg=; b=nFfvG/hGGZFMe9rWNUR1qdgQQQTdgUau5dfwJycjnvHVkNlDR02FRoPQcNo4Ht1rYj xH2xlLZMDXX0Ryd/y3yuZ9STWO7n598Y/E6Ew2Wr5ewXBQix4WifCRn/u+W9S0TlGmYx uzQk2rRVjFHvOW8TBC+yS/TqW57dj9y6lC6Ka+wJG2JsRxJ4tLuKpLaxvkpLnTST6/2T +ckMB3PMCD6yZV5R+ng26rzMVeTASrc/S6tlFTAExQpFwdi8Bwz8rpzBmFFeDH8ZuM/M MOhssYq4o4XUNfarWhHjAF0a7NSZva96bQiKHlO9A6tmoUtu5zE3LtHBHA0z8se/XqqJ zbHA== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@kernel.org header.s=default header.b=lhhMT4Gj; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id a63-v6si645229pla.123.2018.09.26.09.13.24; Wed, 26 Sep 2018 09:13:39 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=pass header.i=@kernel.org header.s=default header.b=lhhMT4Gj; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728539AbeIZW0K (ORCPT + 99 others); Wed, 26 Sep 2018 18:26:10 -0400 Received: from mail.kernel.org ([198.145.29.99]:54468 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727442AbeIZW0J (ORCPT ); Wed, 26 Sep 2018 18:26:09 -0400 Received: from localhost.localdomain (user-0ccsrjt.cable.mindspring.com [24.206.110.125]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-SHA256 (128/128 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPSA id 6D7622152E; Wed, 26 Sep 2018 16:12:28 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1537978349; bh=MEGtOYbblTY0JaUOyi6qfuBLH13Etk4/WsYNMvOX7OU=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=lhhMT4GjQ5Qji0g/pCN+uTZuNC8jZFpZObA/KFs9k6bQRqcNW7jZ71M9xH8QYZ/pj wgXE3iqfy4L5Xoyg5HMuNQBJ/ryGLzq0w03Nk7JgcUhOftweq6UbTc/7rcJkXszHpC T3s0WNq7j6b7Hnx795ekAAdbRKQj6Sv9ZFA1Udhg= From: Alan Tull To: Moritz Fischer , Jonathan Corbet Cc: Randy Dunlap , Federico Vaga , linux-kernel@vger.kernel.org, linux-fpga@vger.kernel.org, linux-doc@vger.kernel.org, Alan Tull Subject: [PATCH v3 1/4] fpga: mgr: add devm_fpga_mgr_create Date: Wed, 26 Sep 2018 11:12:19 -0500 Message-Id: <1537978342-17697-2-git-send-email-atull@kernel.org> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1537978342-17697-1-git-send-email-atull@kernel.org> References: <1537978342-17697-1-git-send-email-atull@kernel.org> Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Add devm_fpga_mgr_create() which is the managed version of fpga_mgr_create(). Change current FPGA manager drivers to use devm_fpga_mgr_create() Signed-off-by: Alan Tull Suggested-by: Federico Vaga --- v2: add suggested-by v3: remove some unclear documentation about fpga_mgr_unregister --- Documentation/driver-api/fpga/fpga-mgr.rst | 13 +++--- drivers/fpga/altera-cvp.c | 8 ++-- drivers/fpga/altera-pr-ip-core.c | 9 +---- drivers/fpga/altera-ps-spi.c | 11 ++--- drivers/fpga/dfl-fme-mgr.c | 11 ++--- drivers/fpga/fpga-mgr.c | 64 ++++++++++++++++++++++++++---- drivers/fpga/ice40-spi.c | 10 ++--- drivers/fpga/machxo2-spi.c | 11 ++--- drivers/fpga/socfpga-a10.c | 5 +-- drivers/fpga/socfpga.c | 10 ++--- drivers/fpga/ts73xx-fpga.c | 11 ++--- drivers/fpga/xilinx-spi.c | 12 ++---- drivers/fpga/zynq-fpga.c | 5 +-- include/linux/fpga/fpga-mgr.h | 4 ++ 14 files changed, 97 insertions(+), 87 deletions(-) diff --git a/Documentation/driver-api/fpga/fpga-mgr.rst b/Documentation/driver-api/fpga/fpga-mgr.rst index 82b6dbb..db8885e 100644 --- a/Documentation/driver-api/fpga/fpga-mgr.rst +++ b/Documentation/driver-api/fpga/fpga-mgr.rst @@ -49,18 +49,14 @@ probe function calls fpga_mgr_register(), such as:: * them in priv */ - mgr = fpga_mgr_create(dev, "Altera SOCFPGA FPGA Manager", - &socfpga_fpga_ops, priv); + mgr = devm_fpga_mgr_create(dev, "Altera SOCFPGA FPGA Manager", + &socfpga_fpga_ops, priv); if (!mgr) return -ENOMEM; platform_set_drvdata(pdev, mgr); - ret = fpga_mgr_register(mgr); - if (ret) - fpga_mgr_free(mgr); - - return ret; + return fpga_mgr_register(mgr); } static int socfpga_fpga_remove(struct platform_device *pdev) @@ -170,6 +166,9 @@ API for implementing a new FPGA Manager driver :functions: fpga_manager_ops .. kernel-doc:: drivers/fpga/fpga-mgr.c + :functions: devm_fpga_mgr_create + +.. kernel-doc:: drivers/fpga/fpga-mgr.c :functions: fpga_mgr_create .. kernel-doc:: drivers/fpga/fpga-mgr.c diff --git a/drivers/fpga/altera-cvp.c b/drivers/fpga/altera-cvp.c index 7fa7936..610a155 100644 --- a/drivers/fpga/altera-cvp.c +++ b/drivers/fpga/altera-cvp.c @@ -453,8 +453,8 @@ 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 = fpga_mgr_create(&pdev->dev, conf->mgr_name, - &altera_cvp_ops, conf); + mgr = devm_fpga_mgr_create(&pdev->dev, conf->mgr_name, + &altera_cvp_ops, conf); if (!mgr) { ret = -ENOMEM; goto err_unmap; @@ -463,10 +463,8 @@ static int altera_cvp_probe(struct pci_dev *pdev, pci_set_drvdata(pdev, mgr); ret = fpga_mgr_register(mgr); - if (ret) { - fpga_mgr_free(mgr); + if (ret) goto err_unmap; - } ret = driver_create_file(&altera_cvp_driver.driver, &driver_attr_chkcfg); diff --git a/drivers/fpga/altera-pr-ip-core.c b/drivers/fpga/altera-pr-ip-core.c index 65e0b6a..a7a3bf0 100644 --- a/drivers/fpga/altera-pr-ip-core.c +++ b/drivers/fpga/altera-pr-ip-core.c @@ -177,7 +177,6 @@ int alt_pr_register(struct device *dev, void __iomem *reg_base) { struct alt_pr_priv *priv; struct fpga_manager *mgr; - int ret; u32 val; priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); @@ -192,17 +191,13 @@ 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 = fpga_mgr_create(dev, dev_name(dev), &alt_pr_ops, priv); + mgr = devm_fpga_mgr_create(dev, dev_name(dev), &alt_pr_ops, priv); if (!mgr) return -ENOMEM; dev_set_drvdata(dev, mgr); - ret = fpga_mgr_register(mgr); - if (ret) - fpga_mgr_free(mgr); - - return ret; + return fpga_mgr_register(mgr); } EXPORT_SYMBOL_GPL(alt_pr_register); diff --git a/drivers/fpga/altera-ps-spi.c b/drivers/fpga/altera-ps-spi.c index 24b25c6..33aafda 100644 --- a/drivers/fpga/altera-ps-spi.c +++ b/drivers/fpga/altera-ps-spi.c @@ -239,7 +239,6 @@ static int altera_ps_probe(struct spi_device *spi) struct altera_ps_conf *conf; const struct of_device_id *of_id; struct fpga_manager *mgr; - int ret; conf = devm_kzalloc(&spi->dev, sizeof(*conf), GFP_KERNEL); if (!conf) @@ -275,18 +274,14 @@ 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 = fpga_mgr_create(&spi->dev, conf->mgr_name, - &altera_ps_ops, conf); + mgr = devm_fpga_mgr_create(&spi->dev, conf->mgr_name, + &altera_ps_ops, conf); if (!mgr) return -ENOMEM; spi_set_drvdata(spi, mgr); - ret = fpga_mgr_register(mgr); - if (ret) - fpga_mgr_free(mgr); - - return ret; + return fpga_mgr_register(mgr); } static int altera_ps_remove(struct spi_device *spi) diff --git a/drivers/fpga/dfl-fme-mgr.c b/drivers/fpga/dfl-fme-mgr.c index 9f045d0..76f3770 100644 --- a/drivers/fpga/dfl-fme-mgr.c +++ b/drivers/fpga/dfl-fme-mgr.c @@ -287,7 +287,6 @@ static int fme_mgr_probe(struct platform_device *pdev) struct fme_mgr_priv *priv; struct fpga_manager *mgr; struct resource *res; - int ret; priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); if (!priv) @@ -309,19 +308,15 @@ static int fme_mgr_probe(struct platform_device *pdev) fme_mgr_get_compat_id(priv->ioaddr, compat_id); - mgr = fpga_mgr_create(dev, "DFL FME FPGA Manager", - &fme_mgr_ops, priv); + mgr = devm_fpga_mgr_create(dev, "DFL FME FPGA Manager", + &fme_mgr_ops, priv); if (!mgr) return -ENOMEM; mgr->compat_id = compat_id; platform_set_drvdata(pdev, mgr); - ret = fpga_mgr_register(mgr); - if (ret) - fpga_mgr_free(mgr); - - return ret; + return fpga_mgr_register(mgr); } static int fme_mgr_remove(struct platform_device *pdev) diff --git a/drivers/fpga/fpga-mgr.c b/drivers/fpga/fpga-mgr.c index a41b07e..c386681 100644 --- a/drivers/fpga/fpga-mgr.c +++ b/drivers/fpga/fpga-mgr.c @@ -558,6 +558,9 @@ EXPORT_SYMBOL_GPL(fpga_mgr_unlock); * @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. + * * Return: pointer to struct fpga_manager or NULL */ struct fpga_manager *fpga_mgr_create(struct device *dev, const char *name, @@ -618,8 +621,8 @@ struct fpga_manager *fpga_mgr_create(struct device *dev, const char *name, EXPORT_SYMBOL_GPL(fpga_mgr_create); /** - * fpga_mgr_free - deallocate a FPGA manager - * @mgr: fpga manager struct created by fpga_mgr_create + * fpga_mgr_free - free a FPGA manager created with fpga_mgr_create() + * @mgr: fpga manager struct */ void fpga_mgr_free(struct fpga_manager *mgr) { @@ -628,9 +631,55 @@ void fpga_mgr_free(struct fpga_manager *mgr) } EXPORT_SYMBOL_GPL(fpga_mgr_free); +static void devm_fpga_mgr_release(struct device *dev, void *res) +{ + struct fpga_manager *mgr = *(struct fpga_manager **)res; + + fpga_mgr_free(mgr); +} + +/** + * devm_fpga_mgr_create - create and initialize a managed FPGA manager struct + * @dev: 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 a 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 *dev, const char *name, + const struct fpga_manager_ops *mops, + void *priv) +{ + struct fpga_manager **ptr, *mgr; + + ptr = devres_alloc(devm_fpga_mgr_release, sizeof(*ptr), GFP_KERNEL); + if (!ptr) + return NULL; + + mgr = fpga_mgr_create(dev, name, mops, priv); + if (!mgr) { + devres_free(ptr); + } else { + *ptr = mgr; + devres_add(dev, ptr); + } + + return mgr; +} +EXPORT_SYMBOL_GPL(devm_fpga_mgr_create); + /** * fpga_mgr_register - register a FPGA manager - * @mgr: fpga manager struct created by fpga_mgr_create + * @mgr: fpga manager struct * * Return: 0 on success, negative error code otherwise. */ @@ -661,8 +710,10 @@ int fpga_mgr_register(struct fpga_manager *mgr) EXPORT_SYMBOL_GPL(fpga_mgr_register); /** - * fpga_mgr_unregister - unregister and free a FPGA manager - * @mgr: fpga manager struct + * fpga_mgr_unregister - unregister a FPGA manager + * @mgr: fpga manager struct + * + * This function is intended for use in a FPGA manager driver's remove function. */ void fpga_mgr_unregister(struct fpga_manager *mgr) { @@ -681,9 +732,6 @@ EXPORT_SYMBOL_GPL(fpga_mgr_unregister); static void fpga_mgr_dev_release(struct device *dev) { - struct fpga_manager *mgr = to_fpga_manager(dev); - - fpga_mgr_free(mgr); } static int __init fpga_mgr_class_init(void) diff --git a/drivers/fpga/ice40-spi.c b/drivers/fpga/ice40-spi.c index 5981c7e..6154661 100644 --- a/drivers/fpga/ice40-spi.c +++ b/drivers/fpga/ice40-spi.c @@ -175,18 +175,14 @@ static int ice40_fpga_probe(struct spi_device *spi) return ret; } - mgr = fpga_mgr_create(dev, "Lattice iCE40 FPGA Manager", - &ice40_fpga_ops, priv); + mgr = devm_fpga_mgr_create(dev, "Lattice iCE40 FPGA Manager", + &ice40_fpga_ops, priv); if (!mgr) return -ENOMEM; spi_set_drvdata(spi, mgr); - ret = fpga_mgr_register(mgr); - if (ret) - fpga_mgr_free(mgr); - - return ret; + return fpga_mgr_register(mgr); } static int ice40_fpga_remove(struct spi_device *spi) diff --git a/drivers/fpga/machxo2-spi.c b/drivers/fpga/machxo2-spi.c index a582e00..4d8a876 100644 --- a/drivers/fpga/machxo2-spi.c +++ b/drivers/fpga/machxo2-spi.c @@ -356,25 +356,20 @@ static int machxo2_spi_probe(struct spi_device *spi) { struct device *dev = &spi->dev; struct fpga_manager *mgr; - int ret; if (spi->max_speed_hz > MACHXO2_MAX_SPEED) { dev_err(dev, "Speed is too high\n"); return -EINVAL; } - mgr = fpga_mgr_create(dev, "Lattice MachXO2 SPI FPGA Manager", - &machxo2_ops, spi); + mgr = devm_fpga_mgr_create(dev, "Lattice MachXO2 SPI FPGA Manager", + &machxo2_ops, spi); if (!mgr) return -ENOMEM; spi_set_drvdata(spi, mgr); - ret = fpga_mgr_register(mgr); - if (ret) - fpga_mgr_free(mgr); - - return ret; + return fpga_mgr_register(mgr); } static int machxo2_spi_remove(struct spi_device *spi) diff --git a/drivers/fpga/socfpga-a10.c b/drivers/fpga/socfpga-a10.c index be30c48..573d88b 100644 --- a/drivers/fpga/socfpga-a10.c +++ b/drivers/fpga/socfpga-a10.c @@ -508,8 +508,8 @@ static int socfpga_a10_fpga_probe(struct platform_device *pdev) return -EBUSY; } - mgr = fpga_mgr_create(dev, "SoCFPGA Arria10 FPGA Manager", - &socfpga_a10_fpga_mgr_ops, priv); + mgr = devm_fpga_mgr_create(dev, "SoCFPGA Arria10 FPGA Manager", + &socfpga_a10_fpga_mgr_ops, priv); if (!mgr) return -ENOMEM; @@ -517,7 +517,6 @@ static int socfpga_a10_fpga_probe(struct platform_device *pdev) ret = fpga_mgr_register(mgr); if (ret) { - fpga_mgr_free(mgr); clk_disable_unprepare(priv->clk); return ret; } diff --git a/drivers/fpga/socfpga.c b/drivers/fpga/socfpga.c index 959d71f..4a8a2fc 100644 --- a/drivers/fpga/socfpga.c +++ b/drivers/fpga/socfpga.c @@ -571,18 +571,14 @@ static int socfpga_fpga_probe(struct platform_device *pdev) if (ret) return ret; - mgr = fpga_mgr_create(dev, "Altera SOCFPGA FPGA Manager", - &socfpga_fpga_ops, priv); + mgr = devm_fpga_mgr_create(dev, "Altera SOCFPGA FPGA Manager", + &socfpga_fpga_ops, priv); if (!mgr) return -ENOMEM; platform_set_drvdata(pdev, mgr); - ret = fpga_mgr_register(mgr); - if (ret) - fpga_mgr_free(mgr); - - return ret; + return fpga_mgr_register(mgr); } static int socfpga_fpga_remove(struct platform_device *pdev) diff --git a/drivers/fpga/ts73xx-fpga.c b/drivers/fpga/ts73xx-fpga.c index 08efd18..dc22a58 100644 --- a/drivers/fpga/ts73xx-fpga.c +++ b/drivers/fpga/ts73xx-fpga.c @@ -118,7 +118,6 @@ static int ts73xx_fpga_probe(struct platform_device *pdev) struct ts73xx_fpga_priv *priv; struct fpga_manager *mgr; struct resource *res; - int ret; priv = devm_kzalloc(kdev, sizeof(*priv), GFP_KERNEL); if (!priv) @@ -133,18 +132,14 @@ static int ts73xx_fpga_probe(struct platform_device *pdev) return PTR_ERR(priv->io_base); } - mgr = fpga_mgr_create(kdev, "TS-73xx FPGA Manager", - &ts73xx_fpga_ops, priv); + mgr = devm_fpga_mgr_create(kdev, "TS-73xx FPGA Manager", + &ts73xx_fpga_ops, priv); if (!mgr) return -ENOMEM; platform_set_drvdata(pdev, mgr); - ret = fpga_mgr_register(mgr); - if (ret) - fpga_mgr_free(mgr); - - return ret; + return fpga_mgr_register(mgr); } static int ts73xx_fpga_remove(struct platform_device *pdev) diff --git a/drivers/fpga/xilinx-spi.c b/drivers/fpga/xilinx-spi.c index 8d19459..469486b 100644 --- a/drivers/fpga/xilinx-spi.c +++ b/drivers/fpga/xilinx-spi.c @@ -144,7 +144,6 @@ static int xilinx_spi_probe(struct spi_device *spi) { struct xilinx_spi_conf *conf; struct fpga_manager *mgr; - int ret; conf = devm_kzalloc(&spi->dev, sizeof(*conf), GFP_KERNEL); if (!conf) @@ -167,18 +166,15 @@ static int xilinx_spi_probe(struct spi_device *spi) return PTR_ERR(conf->done); } - mgr = fpga_mgr_create(&spi->dev, "Xilinx Slave Serial FPGA Manager", - &xilinx_spi_ops, conf); + mgr = devm_fpga_mgr_create(&spi->dev, + "Xilinx Slave Serial FPGA Manager", + &xilinx_spi_ops, conf); if (!mgr) return -ENOMEM; spi_set_drvdata(spi, mgr); - ret = fpga_mgr_register(mgr); - if (ret) - fpga_mgr_free(mgr); - - return ret; + return fpga_mgr_register(mgr); } static int xilinx_spi_remove(struct spi_device *spi) diff --git a/drivers/fpga/zynq-fpga.c b/drivers/fpga/zynq-fpga.c index 3110e00..bb82efe 100644 --- a/drivers/fpga/zynq-fpga.c +++ b/drivers/fpga/zynq-fpga.c @@ -614,8 +614,8 @@ static int zynq_fpga_probe(struct platform_device *pdev) clk_disable(priv->clk); - mgr = fpga_mgr_create(dev, "Xilinx Zynq FPGA Manager", - &zynq_fpga_ops, priv); + mgr = devm_fpga_mgr_create(dev, "Xilinx Zynq FPGA Manager", + &zynq_fpga_ops, priv); if (!mgr) return -ENOMEM; @@ -624,7 +624,6 @@ static int zynq_fpga_probe(struct platform_device *pdev) err = fpga_mgr_register(mgr); if (err) { dev_err(dev, "unable to register FPGA manager\n"); - fpga_mgr_free(mgr); clk_unprepare(priv->clk); return err; } diff --git a/include/linux/fpga/fpga-mgr.h b/include/linux/fpga/fpga-mgr.h index 8ab5df7..e8ca62b 100644 --- a/include/linux/fpga/fpga-mgr.h +++ b/include/linux/fpga/fpga-mgr.h @@ -198,4 +198,8 @@ void fpga_mgr_free(struct fpga_manager *mgr); int fpga_mgr_register(struct fpga_manager *mgr); void fpga_mgr_unregister(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); + #endif /*_LINUX_FPGA_MGR_H */ -- 2.7.4