root/drivers/fpga/fpga-region.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. fpga_region_class_find
  2. fpga_region_get
  3. fpga_region_put
  4. fpga_region_program_fpga
  5. compat_id_show
  6. fpga_region_create
  7. fpga_region_free
  8. devm_fpga_region_release
  9. devm_fpga_region_create
  10. fpga_region_register
  11. fpga_region_unregister
  12. fpga_region_dev_release
  13. fpga_region_init
  14. fpga_region_exit

   1 // SPDX-License-Identifier: GPL-2.0
   2 /*
   3  * FPGA Region - Device Tree support for FPGA programming under Linux
   4  *
   5  *  Copyright (C) 2013-2016 Altera Corporation
   6  *  Copyright (C) 2017 Intel Corporation
   7  */
   8 #include <linux/fpga/fpga-bridge.h>
   9 #include <linux/fpga/fpga-mgr.h>
  10 #include <linux/fpga/fpga-region.h>
  11 #include <linux/idr.h>
  12 #include <linux/kernel.h>
  13 #include <linux/list.h>
  14 #include <linux/module.h>
  15 #include <linux/slab.h>
  16 #include <linux/spinlock.h>
  17 
  18 static DEFINE_IDA(fpga_region_ida);
  19 static struct class *fpga_region_class;
  20 
  21 struct fpga_region *fpga_region_class_find(
  22         struct device *start, const void *data,
  23         int (*match)(struct device *, const void *))
  24 {
  25         struct device *dev;
  26 
  27         dev = class_find_device(fpga_region_class, start, data, match);
  28         if (!dev)
  29                 return NULL;
  30 
  31         return to_fpga_region(dev);
  32 }
  33 EXPORT_SYMBOL_GPL(fpga_region_class_find);
  34 
  35 /**
  36  * fpga_region_get - get an exclusive reference to a fpga region
  37  * @region: FPGA Region struct
  38  *
  39  * Caller should call fpga_region_put() when done with region.
  40  *
  41  * Return fpga_region struct if successful.
  42  * Return -EBUSY if someone already has a reference to the region.
  43  * Return -ENODEV if @np is not a FPGA Region.
  44  */
  45 static struct fpga_region *fpga_region_get(struct fpga_region *region)
  46 {
  47         struct device *dev = &region->dev;
  48 
  49         if (!mutex_trylock(&region->mutex)) {
  50                 dev_dbg(dev, "%s: FPGA Region already in use\n", __func__);
  51                 return ERR_PTR(-EBUSY);
  52         }
  53 
  54         get_device(dev);
  55         if (!try_module_get(dev->parent->driver->owner)) {
  56                 put_device(dev);
  57                 mutex_unlock(&region->mutex);
  58                 return ERR_PTR(-ENODEV);
  59         }
  60 
  61         dev_dbg(dev, "get\n");
  62 
  63         return region;
  64 }
  65 
  66 /**
  67  * fpga_region_put - release a reference to a region
  68  *
  69  * @region: FPGA region
  70  */
  71 static void fpga_region_put(struct fpga_region *region)
  72 {
  73         struct device *dev = &region->dev;
  74 
  75         dev_dbg(dev, "put\n");
  76 
  77         module_put(dev->parent->driver->owner);
  78         put_device(dev);
  79         mutex_unlock(&region->mutex);
  80 }
  81 
  82 /**
  83  * fpga_region_program_fpga - program FPGA
  84  *
  85  * @region: FPGA region
  86  *
  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  *
  94  * Return 0 for success or negative error code.
  95  */
  96 int fpga_region_program_fpga(struct fpga_region *region)
  97 {
  98         struct device *dev = &region->dev;
  99         struct fpga_image_info *info = region->info;
 100         int ret;
 101 
 102         region = fpga_region_get(region);
 103         if (IS_ERR(region)) {
 104                 dev_err(dev, "failed to get FPGA region\n");
 105                 return PTR_ERR(region);
 106         }
 107 
 108         ret = fpga_mgr_lock(region->mgr);
 109         if (ret) {
 110                 dev_err(dev, "FPGA manager is busy\n");
 111                 goto err_put_region;
 112         }
 113 
 114         /*
 115          * In some cases, we already have a list of bridges in the
 116          * fpga region struct.  Or we don't have any bridges.
 117          */
 118         if (region->get_bridges) {
 119                 ret = region->get_bridges(region);
 120                 if (ret) {
 121                         dev_err(dev, "failed to get fpga region bridges\n");
 122                         goto err_unlock_mgr;
 123                 }
 124         }
 125 
 126         ret = fpga_bridges_disable(&region->bridge_list);
 127         if (ret) {
 128                 dev_err(dev, "failed to disable bridges\n");
 129                 goto err_put_br;
 130         }
 131 
 132         ret = fpga_mgr_load(region->mgr, info);
 133         if (ret) {
 134                 dev_err(dev, "failed to load FPGA image\n");
 135                 goto err_put_br;
 136         }
 137 
 138         ret = fpga_bridges_enable(&region->bridge_list);
 139         if (ret) {
 140                 dev_err(dev, "failed to enable region bridges\n");
 141                 goto err_put_br;
 142         }
 143 
 144         fpga_mgr_unlock(region->mgr);
 145         fpga_region_put(region);
 146 
 147         return 0;
 148 
 149 err_put_br:
 150         if (region->get_bridges)
 151                 fpga_bridges_put(&region->bridge_list);
 152 err_unlock_mgr:
 153         fpga_mgr_unlock(region->mgr);
 154 err_put_region:
 155         fpga_region_put(region);
 156 
 157         return ret;
 158 }
 159 EXPORT_SYMBOL_GPL(fpga_region_program_fpga);
 160 
 161 static ssize_t compat_id_show(struct device *dev,
 162                               struct device_attribute *attr, char *buf)
 163 {
 164         struct fpga_region *region = to_fpga_region(dev);
 165 
 166         if (!region->compat_id)
 167                 return -ENOENT;
 168 
 169         return sprintf(buf, "%016llx%016llx\n",
 170                        (unsigned long long)region->compat_id->id_h,
 171                        (unsigned long long)region->compat_id->id_l);
 172 }
 173 
 174 static DEVICE_ATTR_RO(compat_id);
 175 
 176 static struct attribute *fpga_region_attrs[] = {
 177         &dev_attr_compat_id.attr,
 178         NULL,
 179 };
 180 ATTRIBUTE_GROUPS(fpga_region);
 181 
 182 /**
 183  * fpga_region_create - alloc and init a struct fpga_region
 184  * @dev: device parent
 185  * @mgr: manager that programs this region
 186  * @get_bridges: optional function to get bridges to a list
 187  *
 188  * The caller of this function is responsible for freeing the resulting region
 189  * struct with fpga_region_free().  Using devm_fpga_region_create() instead is
 190  * recommended.
 191  *
 192  * Return: struct fpga_region or NULL
 193  */
 194 struct fpga_region
 195 *fpga_region_create(struct device *dev,
 196                     struct fpga_manager *mgr,
 197                     int (*get_bridges)(struct fpga_region *))
 198 {
 199         struct fpga_region *region;
 200         int id, ret = 0;
 201 
 202         region = kzalloc(sizeof(*region), GFP_KERNEL);
 203         if (!region)
 204                 return NULL;
 205 
 206         id = ida_simple_get(&fpga_region_ida, 0, 0, GFP_KERNEL);
 207         if (id < 0)
 208                 goto err_free;
 209 
 210         region->mgr = mgr;
 211         region->get_bridges = get_bridges;
 212         mutex_init(&region->mutex);
 213         INIT_LIST_HEAD(&region->bridge_list);
 214 
 215         device_initialize(&region->dev);
 216         region->dev.class = fpga_region_class;
 217         region->dev.parent = dev;
 218         region->dev.of_node = dev->of_node;
 219         region->dev.id = id;
 220 
 221         ret = dev_set_name(&region->dev, "region%d", id);
 222         if (ret)
 223                 goto err_remove;
 224 
 225         return region;
 226 
 227 err_remove:
 228         ida_simple_remove(&fpga_region_ida, id);
 229 err_free:
 230         kfree(region);
 231 
 232         return NULL;
 233 }
 234 EXPORT_SYMBOL_GPL(fpga_region_create);
 235 
 236 /**
 237  * fpga_region_free - free a FPGA region created by fpga_region_create()
 238  * @region: FPGA region
 239  */
 240 void fpga_region_free(struct fpga_region *region)
 241 {
 242         ida_simple_remove(&fpga_region_ida, region->dev.id);
 243         kfree(region);
 244 }
 245 EXPORT_SYMBOL_GPL(fpga_region_free);
 246 
 247 static void devm_fpga_region_release(struct device *dev, void *res)
 248 {
 249         struct fpga_region *region = *(struct fpga_region **)res;
 250 
 251         fpga_region_free(region);
 252 }
 253 
 254 /**
 255  * devm_fpga_region_create - create and initialize a managed FPGA region struct
 256  * @dev: device parent
 257  * @mgr: manager that programs this region
 258  * @get_bridges: optional function to get bridges to a list
 259  *
 260  * This function is intended for use in a FPGA region driver's probe function.
 261  * After the region driver creates the region struct with
 262  * devm_fpga_region_create(), it should register it with fpga_region_register().
 263  * The region driver's remove function should call fpga_region_unregister().
 264  * The region struct allocated with this function will be freed automatically on
 265  * driver detach.  This includes the case of a probe function returning error
 266  * before calling fpga_region_register(), the struct will still get cleaned up.
 267  *
 268  * Return: struct fpga_region or NULL
 269  */
 270 struct fpga_region
 271 *devm_fpga_region_create(struct device *dev,
 272                          struct fpga_manager *mgr,
 273                          int (*get_bridges)(struct fpga_region *))
 274 {
 275         struct fpga_region **ptr, *region;
 276 
 277         ptr = devres_alloc(devm_fpga_region_release, sizeof(*ptr), GFP_KERNEL);
 278         if (!ptr)
 279                 return NULL;
 280 
 281         region = fpga_region_create(dev, mgr, get_bridges);
 282         if (!region) {
 283                 devres_free(ptr);
 284         } else {
 285                 *ptr = region;
 286                 devres_add(dev, ptr);
 287         }
 288 
 289         return region;
 290 }
 291 EXPORT_SYMBOL_GPL(devm_fpga_region_create);
 292 
 293 /**
 294  * fpga_region_register - register a FPGA region
 295  * @region: FPGA region
 296  *
 297  * Return: 0 or -errno
 298  */
 299 int fpga_region_register(struct fpga_region *region)
 300 {
 301         return device_add(&region->dev);
 302 }
 303 EXPORT_SYMBOL_GPL(fpga_region_register);
 304 
 305 /**
 306  * fpga_region_unregister - unregister a FPGA region
 307  * @region: FPGA region
 308  *
 309  * This function is intended for use in a FPGA region driver's remove function.
 310  */
 311 void fpga_region_unregister(struct fpga_region *region)
 312 {
 313         device_unregister(&region->dev);
 314 }
 315 EXPORT_SYMBOL_GPL(fpga_region_unregister);
 316 
 317 static void fpga_region_dev_release(struct device *dev)
 318 {
 319 }
 320 
 321 /**
 322  * fpga_region_init - init function for fpga_region class
 323  * Creates the fpga_region class and registers a reconfig notifier.
 324  */
 325 static int __init fpga_region_init(void)
 326 {
 327         fpga_region_class = class_create(THIS_MODULE, "fpga_region");
 328         if (IS_ERR(fpga_region_class))
 329                 return PTR_ERR(fpga_region_class);
 330 
 331         fpga_region_class->dev_groups = fpga_region_groups;
 332         fpga_region_class->dev_release = fpga_region_dev_release;
 333 
 334         return 0;
 335 }
 336 
 337 static void __exit fpga_region_exit(void)
 338 {
 339         class_destroy(fpga_region_class);
 340         ida_destroy(&fpga_region_ida);
 341 }
 342 
 343 subsys_initcall(fpga_region_init);
 344 module_exit(fpga_region_exit);
 345 
 346 MODULE_DESCRIPTION("FPGA Region");
 347 MODULE_AUTHOR("Alan Tull <atull@kernel.org>");
 348 MODULE_LICENSE("GPL v2");

/* [<][>][^][v][top][bottom][index][help] */