Received: by 2002:ac0:a5a6:0:0:0:0:0 with SMTP id m35-v6csp3040472imm; Tue, 4 Sep 2018 14:24:28 -0700 (PDT) X-Google-Smtp-Source: ANB0VdZ+vU+FQsJVjr8KqEpH9VsqwyzyJaAzwMeGLZspqKznJ0TGqA12OG1hkjwqsfgezhA5LGaG X-Received: by 2002:a62:c288:: with SMTP id w8-v6mr36896496pfk.92.1536096268577; Tue, 04 Sep 2018 14:24:28 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1536096268; cv=none; d=google.com; s=arc-20160816; b=gc7A1SSrFyB/kRi1KFZXHHH0Rv+0NJgmQlaOjsmBJLWcAQQhR2JO137LEzkuBKWMzc MqFXvltm4r7eqzkk/2y0xYh4TM5cNYt7b/mGp3kgSvVLtcDQDl3kglyKSqJofo5jf7Gj VOTsTQajr43uxLhNXVgmLDsBHRRKps9hRuEeR0qBgHJQzGN6MF7IqBv3TuFWuceoP0BU AEQgysSn+bxjlMco8Yn2J+aVhszarFB02pZXjlioQ2l9APeH5ZocwGzOleb66IP/1HPA 2srpFPMX5J+WaFyk3gmEWmRjllbUbMi9cKwieYqf+uL/e/bu3xfPa20aYQiEU4mO5Q2F X/LQ== 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:arc-authentication-results; bh=OD4kPvmaSBqllYVnx/7h7+edBo4Kh3mf7kGJAua8Xl8=; b=E+KiMVnYlPf8KpiSx6qWQzPiQrK1PAJI9ly+4buifwswZL4DYJ2Hji64mWqPlc+0aF QVfvyAYaX19XahbmhN4TalEX05rBz9Lis/zHT/h9QirKZR4HYlUxZKG546ePXi8B7/2y XLWcH6UkrGkSO3f3Igpp+CZVjvoaALVdCDRtNmJGH+4wdKX86p02bGh+oR2TjAHbLwej jMKExDaKmVZ2OYD3ccxGXERQYVPZKc7+dG5djJFB9wTJFogr9chkQK9io5tjnNW2e2q9 qKLnHhntLHLrlJk3IIZeH7dRQy0rKQj8skSwBhMWvgUM4pECnAdS5RQXNnpVQGXnSwPu lM3g== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@kernel.org header.s=default header.b=VTvGZT2p; 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 j24-v6si22569195pfk.203.2018.09.04.14.24.13; Tue, 04 Sep 2018 14:24:28 -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=VTvGZT2p; 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 S1727489AbeIEBtn (ORCPT + 99 others); Tue, 4 Sep 2018 21:49:43 -0400 Received: from mail.kernel.org ([198.145.29.99]:56092 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727258AbeIEBtl (ORCPT ); Tue, 4 Sep 2018 21:49:41 -0400 Received: from localhost.localdomain (unknown [136.62.81.41]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-SHA256 (128/128 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPSA id 4DC0A20867; Tue, 4 Sep 2018 21:22:45 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1536096165; bh=aZxJa9EwC2odA6ZDwQBJIVN9fEVpkXZh1r+aESjIn5c=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=VTvGZT2pRygiK9YCMKHVcUYA+G+cxR2mQ55ZMh+l3tr+Kz+O7ud00u7mjER2A/Dnz kh95swN0j7PHMLjWhAX9kJLJZfND2YZzGa946FZVllTU7YeQBNkix1a/T1Yti12ia6 7gttOu/R86LqMOvqBDAHbDk9BqeNJ/RY07jN55yw= From: Alan Tull To: Moritz Fischer , Jonathan Corbet Cc: Randy Dunlap , linux-kernel@vger.kernel.org, linux-fpga@vger.kernel.org, linux-doc@vger.kernel.org, Alan Tull Subject: [PATCH v2 4/8] fpga: add devm_fpga_region_create Date: Tue, 4 Sep 2018 16:22:33 -0500 Message-Id: <20180904212237.3078-5-atull@kernel.org> X-Mailer: git-send-email 2.16.2 In-Reply-To: <20180904212237.3078-1-atull@kernel.org> References: <20180904212237.3078-1-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_region_create() which is the managed version of fpga_region_create(). Change current region drivers to use devm_fpga_region_create(). Signed-off-by: Alan Tull Suggested-by: Federico Vaga --- v2: add suggested-by --- Documentation/driver-api/fpga/fpga-region.rst | 3 ++ drivers/fpga/dfl-fme-region.c | 6 +-- drivers/fpga/dfl.c | 6 +-- drivers/fpga/fpga-region.c | 68 +++++++++++++++++++++++---- drivers/fpga/of-fpga-region.c | 6 +-- include/linux/fpga/fpga-region.h | 4 ++ 6 files changed, 73 insertions(+), 20 deletions(-) diff --git a/Documentation/driver-api/fpga/fpga-region.rst b/Documentation/driver-api/fpga/fpga-region.rst index f30333c..dc9f75c 100644 --- a/Documentation/driver-api/fpga/fpga-region.rst +++ b/Documentation/driver-api/fpga/fpga-region.rst @@ -90,6 +90,9 @@ API to add a new FPGA region :functions: fpga_region .. kernel-doc:: drivers/fpga/fpga-region.c + :functions: devm_fpga_region_create + +.. kernel-doc:: drivers/fpga/fpga-region.c :functions: fpga_region_create .. kernel-doc:: drivers/fpga/fpga-region.c diff --git a/drivers/fpga/dfl-fme-region.c b/drivers/fpga/dfl-fme-region.c index 51a5ac2..ec134ec 100644 --- a/drivers/fpga/dfl-fme-region.c +++ b/drivers/fpga/dfl-fme-region.c @@ -39,7 +39,7 @@ static int fme_region_probe(struct platform_device *pdev) if (IS_ERR(mgr)) return -EPROBE_DEFER; - region = fpga_region_create(dev, mgr, fme_region_get_bridges); + region = devm_fpga_region_create(dev, mgr, fme_region_get_bridges); if (!region) { ret = -ENOMEM; goto eprobe_mgr_put; @@ -51,14 +51,12 @@ static int fme_region_probe(struct platform_device *pdev) ret = fpga_region_register(region); if (ret) - goto region_free; + goto eprobe_mgr_put; dev_dbg(dev, "DFL FME FPGA Region probed\n"); return 0; -region_free: - fpga_region_free(region); eprobe_mgr_put: fpga_mgr_put(mgr); return ret; diff --git a/drivers/fpga/dfl.c b/drivers/fpga/dfl.c index a9b521b..2c09e50 100644 --- a/drivers/fpga/dfl.c +++ b/drivers/fpga/dfl.c @@ -899,7 +899,7 @@ dfl_fpga_feature_devs_enumerate(struct dfl_fpga_enum_info *info) if (!cdev) return ERR_PTR(-ENOMEM); - cdev->region = fpga_region_create(info->dev, NULL, NULL); + cdev->region = devm_fpga_region_create(info->dev, NULL, NULL); if (!cdev->region) { ret = -ENOMEM; goto free_cdev_exit; @@ -911,7 +911,7 @@ dfl_fpga_feature_devs_enumerate(struct dfl_fpga_enum_info *info) ret = fpga_region_register(cdev->region); if (ret) - goto free_region_exit; + goto free_cdev_exit; /* create and init build info for enumeration */ binfo = devm_kzalloc(info->dev, sizeof(*binfo), GFP_KERNEL); @@ -942,8 +942,6 @@ dfl_fpga_feature_devs_enumerate(struct dfl_fpga_enum_info *info) unregister_region_exit: fpga_region_unregister(cdev->region); -free_region_exit: - fpga_region_free(cdev->region); free_cdev_exit: devm_kfree(info->dev, cdev); return ERR_PTR(ret); diff --git a/drivers/fpga/fpga-region.c b/drivers/fpga/fpga-region.c index 0d65220..56f773d 100644 --- a/drivers/fpga/fpga-region.c +++ b/drivers/fpga/fpga-region.c @@ -185,6 +185,10 @@ ATTRIBUTE_GROUPS(fpga_region); * @mgr: manager that programs this region * @get_bridges: optional function to get bridges to a list * + * The caller of this function is responsible for freeing the resulting region + * struct with fpga_region_free(). Using devm_fpga_region_create() instead is + * recommended. + * * Return: struct fpga_region or NULL */ struct fpga_region @@ -230,8 +234,8 @@ struct fpga_region EXPORT_SYMBOL_GPL(fpga_region_create); /** - * fpga_region_free - free a struct fpga_region - * @region: FPGA region created by fpga_region_create + * fpga_region_free - free a FPGA region created by fpga_region_create() + * @region: FPGA region */ void fpga_region_free(struct fpga_region *region) { @@ -240,21 +244,72 @@ void fpga_region_free(struct fpga_region *region) } EXPORT_SYMBOL_GPL(fpga_region_free); +static void devm_fpga_region_release(struct device *dev, void *res) +{ + struct fpga_region *region = *(struct fpga_region **)res; + + fpga_region_free(region); +} + +/** + * devm_fpga_region_create - create and initialize a managed FPGA region struct + * @dev: device parent + * @mgr: manager that programs this region + * @get_bridges: optional function to get bridges to a list + * + * This function is intended for use in a FPGA region driver's probe function. + * After the region driver creates the region struct with + * devm_fpga_region_create(), it should register it with fpga_region_register(). + * The region driver's remove function should call fpga_region_unregister(). + * The region 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_region_register(), the struct will still get cleaned up. + * + * Return: struct fpga_region or NULL + */ +struct fpga_region +*devm_fpga_region_create(struct device *dev, + struct fpga_manager *mgr, + int (*get_bridges)(struct fpga_region *)) +{ + struct fpga_region **ptr, *region; + + ptr = devres_alloc(devm_fpga_region_release, sizeof(*ptr), GFP_KERNEL); + if (!ptr) + return NULL; + + region = fpga_region_create(dev, mgr, get_bridges); + if (!region) { + devres_free(ptr); + } else { + *ptr = region; + devres_add(dev, ptr); + } + + return region; +} +EXPORT_SYMBOL_GPL(devm_fpga_region_create); + /** * fpga_region_register - register a FPGA region - * @region: FPGA region created by fpga_region_create + * @region: FPGA region + * * Return: 0 or -errno */ int fpga_region_register(struct fpga_region *region) { return device_add(®ion->dev); - } EXPORT_SYMBOL_GPL(fpga_region_register); /** - * fpga_region_unregister - unregister and free a FPGA region + * fpga_region_unregister - unregister a FPGA region * @region: FPGA region + * + * This function is intended for use in a FPGA region driver's remove function. + * If the region was created by devm_fpga_region_create(), it will be + * automatically freed. If the region was created by fpga_region_create(), the + * caller is responsible for freeing it with fpga_region_free(). */ void fpga_region_unregister(struct fpga_region *region) { @@ -264,9 +319,6 @@ EXPORT_SYMBOL_GPL(fpga_region_unregister); static void fpga_region_dev_release(struct device *dev) { - struct fpga_region *region = to_fpga_region(dev); - - fpga_region_free(region); } /** diff --git a/drivers/fpga/of-fpga-region.c b/drivers/fpga/of-fpga-region.c index 052a134..122286f 100644 --- a/drivers/fpga/of-fpga-region.c +++ b/drivers/fpga/of-fpga-region.c @@ -410,7 +410,7 @@ static int of_fpga_region_probe(struct platform_device *pdev) if (IS_ERR(mgr)) return -EPROBE_DEFER; - region = fpga_region_create(dev, mgr, of_fpga_region_get_bridges); + region = devm_fpga_region_create(dev, mgr, of_fpga_region_get_bridges); if (!region) { ret = -ENOMEM; goto eprobe_mgr_put; @@ -418,7 +418,7 @@ static int of_fpga_region_probe(struct platform_device *pdev) ret = fpga_region_register(region); if (ret) - goto eprobe_free; + goto eprobe_mgr_put; of_platform_populate(np, fpga_region_of_match, NULL, ®ion->dev); dev_set_drvdata(dev, region); @@ -427,8 +427,6 @@ static int of_fpga_region_probe(struct platform_device *pdev) return 0; -eprobe_free: - fpga_region_free(region); eprobe_mgr_put: fpga_mgr_put(mgr); return ret; diff --git a/include/linux/fpga/fpga-region.h b/include/linux/fpga/fpga-region.h index 0521b7f..27cb706 100644 --- a/include/linux/fpga/fpga-region.h +++ b/include/linux/fpga/fpga-region.h @@ -44,4 +44,8 @@ void fpga_region_free(struct fpga_region *region); int fpga_region_register(struct fpga_region *region); void fpga_region_unregister(struct fpga_region *region); +struct fpga_region +*devm_fpga_region_create(struct device *dev, struct fpga_manager *mgr, + int (*get_bridges)(struct fpga_region *)); + #endif /* _FPGA_REGION_H */ -- 2.7.4