aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/fpga/fpga-region.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/fpga/fpga-region.c')
-rw-r--r--drivers/fpga/fpga-region.c91
1 files changed, 64 insertions, 27 deletions
diff --git a/drivers/fpga/fpga-region.c b/drivers/fpga/fpga-region.c
index edab2a2e03ef..6d214d75c7be 100644
--- a/drivers/fpga/fpga-region.c
+++ b/drivers/fpga/fpga-region.c
@@ -1,22 +1,10 @@
1// SPDX-License-Identifier: GPL-2.0
1/* 2/*
2 * FPGA Region - Device Tree support for FPGA programming under Linux 3 * FPGA Region - Device Tree support for FPGA programming under Linux
3 * 4 *
4 * Copyright (C) 2013-2016 Altera Corporation 5 * Copyright (C) 2013-2016 Altera Corporation
5 * Copyright (C) 2017 Intel Corporation 6 * Copyright (C) 2017 Intel Corporation
6 *
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms and conditions of the GNU General Public License,
9 * version 2, as published by the Free Software Foundation.
10 *
11 * This program is distributed in the hope it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
14 * more details.
15 *
16 * You should have received a copy of the GNU General Public License along with
17 * this program. If not, see <http://www.gnu.org/licenses/>.
18 */ 7 */
19
20#include <linux/fpga/fpga-bridge.h> 8#include <linux/fpga/fpga-bridge.h>
21#include <linux/fpga/fpga-mgr.h> 9#include <linux/fpga/fpga-mgr.h>
22#include <linux/fpga/fpga-region.h> 10#include <linux/fpga/fpga-region.h>
@@ -93,8 +81,16 @@ static void fpga_region_put(struct fpga_region *region)
93 81
94/** 82/**
95 * fpga_region_program_fpga - program FPGA 83 * fpga_region_program_fpga - program FPGA
84 *
96 * @region: FPGA region 85 * @region: FPGA region
86 *
97 * Program an FPGA using fpga image info (region->info). 87 * Program an FPGA using fpga image info (region->info).
88 * If the region has a get_bridges function, the exclusive reference for the
89 * bridges will be held if programming succeeds. This is intended to prevent
90 * reprogramming the region until the caller considers it safe to do so.
91 * The caller will need to call fpga_bridges_put() before attempting to
92 * reprogram the region.
93 *
98 * Return 0 for success or negative error code. 94 * Return 0 for success or negative error code.
99 */ 95 */
100int fpga_region_program_fpga(struct fpga_region *region) 96int fpga_region_program_fpga(struct fpga_region *region)
@@ -162,45 +158,86 @@ err_put_region:
162} 158}
163EXPORT_SYMBOL_GPL(fpga_region_program_fpga); 159EXPORT_SYMBOL_GPL(fpga_region_program_fpga);
164 160
165int fpga_region_register(struct device *dev, struct fpga_region *region) 161/**
162 * fpga_region_create - alloc and init a struct fpga_region
163 * @dev: device parent
164 * @mgr: manager that programs this region
165 * @get_bridges: optional function to get bridges to a list
166 *
167 * Return: struct fpga_region or NULL
168 */
169struct fpga_region
170*fpga_region_create(struct device *dev,
171 struct fpga_manager *mgr,
172 int (*get_bridges)(struct fpga_region *))
166{ 173{
174 struct fpga_region *region;
167 int id, ret = 0; 175 int id, ret = 0;
168 176
177 region = kzalloc(sizeof(*region), GFP_KERNEL);
178 if (!region)
179 return NULL;
180
169 id = ida_simple_get(&fpga_region_ida, 0, 0, GFP_KERNEL); 181 id = ida_simple_get(&fpga_region_ida, 0, 0, GFP_KERNEL);
170 if (id < 0) 182 if (id < 0)
171 return id; 183 goto err_free;
172 184
185 region->mgr = mgr;
186 region->get_bridges = get_bridges;
173 mutex_init(&region->mutex); 187 mutex_init(&region->mutex);
174 INIT_LIST_HEAD(&region->bridge_list); 188 INIT_LIST_HEAD(&region->bridge_list);
189
175 device_initialize(&region->dev); 190 device_initialize(&region->dev);
176 region->dev.groups = region->groups;
177 region->dev.class = fpga_region_class; 191 region->dev.class = fpga_region_class;
178 region->dev.parent = dev; 192 region->dev.parent = dev;
179 region->dev.of_node = dev->of_node; 193 region->dev.of_node = dev->of_node;
180 region->dev.id = id; 194 region->dev.id = id;
181 dev_set_drvdata(dev, region);
182 195
183 ret = dev_set_name(&region->dev, "region%d", id); 196 ret = dev_set_name(&region->dev, "region%d", id);
184 if (ret) 197 if (ret)
185 goto err_remove; 198 goto err_remove;
186 199
187 ret = device_add(&region->dev); 200 return region;
188 if (ret)
189 goto err_remove;
190
191 return 0;
192 201
193err_remove: 202err_remove:
194 ida_simple_remove(&fpga_region_ida, id); 203 ida_simple_remove(&fpga_region_ida, id);
195 return ret; 204err_free:
205 kfree(region);
206
207 return NULL;
208}
209EXPORT_SYMBOL_GPL(fpga_region_create);
210
211/**
212 * fpga_region_free - free a struct fpga_region
213 * @region: FPGA region created by fpga_region_create
214 */
215void fpga_region_free(struct fpga_region *region)
216{
217 ida_simple_remove(&fpga_region_ida, region->dev.id);
218 kfree(region);
219}
220EXPORT_SYMBOL_GPL(fpga_region_free);
221
222/**
223 * fpga_region_register - register a FPGA region
224 * @region: FPGA region created by fpga_region_create
225 * Return: 0 or -errno
226 */
227int fpga_region_register(struct fpga_region *region)
228{
229 return device_add(&region->dev);
230
196} 231}
197EXPORT_SYMBOL_GPL(fpga_region_register); 232EXPORT_SYMBOL_GPL(fpga_region_register);
198 233
199int fpga_region_unregister(struct fpga_region *region) 234/**
235 * fpga_region_unregister - unregister and free a FPGA region
236 * @region: FPGA region
237 */
238void fpga_region_unregister(struct fpga_region *region)
200{ 239{
201 device_unregister(&region->dev); 240 device_unregister(&region->dev);
202
203 return 0;
204} 241}
205EXPORT_SYMBOL_GPL(fpga_region_unregister); 242EXPORT_SYMBOL_GPL(fpga_region_unregister);
206 243
@@ -208,7 +245,7 @@ static void fpga_region_dev_release(struct device *dev)
208{ 245{
209 struct fpga_region *region = to_fpga_region(dev); 246 struct fpga_region *region = to_fpga_region(dev);
210 247
211 ida_simple_remove(&fpga_region_ida, region->dev.id); 248 fpga_region_free(region);
212} 249}
213 250
214/** 251/**