linux/drivers/fpga/fpga-bridge.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/*
   3 * FPGA Bridge Framework Driver
   4 *
   5 *  Copyright (C) 2013-2016 Altera Corporation, All Rights Reserved.
   6 *  Copyright (C) 2017 Intel Corporation
   7 */
   8#include <linux/fpga/fpga-bridge.h>
   9#include <linux/idr.h>
  10#include <linux/kernel.h>
  11#include <linux/module.h>
  12#include <linux/of_platform.h>
  13#include <linux/slab.h>
  14#include <linux/spinlock.h>
  15
  16static DEFINE_IDA(fpga_bridge_ida);
  17static struct class *fpga_bridge_class;
  18
  19/* Lock for adding/removing bridges to linked lists*/
  20static DEFINE_SPINLOCK(bridge_list_lock);
  21
  22/**
  23 * fpga_bridge_enable - Enable transactions on the bridge
  24 *
  25 * @bridge: FPGA bridge
  26 *
  27 * Return: 0 for success, error code otherwise.
  28 */
  29int fpga_bridge_enable(struct fpga_bridge *bridge)
  30{
  31        dev_dbg(&bridge->dev, "enable\n");
  32
  33        if (bridge->br_ops && bridge->br_ops->enable_set)
  34                return bridge->br_ops->enable_set(bridge, 1);
  35
  36        return 0;
  37}
  38EXPORT_SYMBOL_GPL(fpga_bridge_enable);
  39
  40/**
  41 * fpga_bridge_disable - Disable transactions on the bridge
  42 *
  43 * @bridge: FPGA bridge
  44 *
  45 * Return: 0 for success, error code otherwise.
  46 */
  47int fpga_bridge_disable(struct fpga_bridge *bridge)
  48{
  49        dev_dbg(&bridge->dev, "disable\n");
  50
  51        if (bridge->br_ops && bridge->br_ops->enable_set)
  52                return bridge->br_ops->enable_set(bridge, 0);
  53
  54        return 0;
  55}
  56EXPORT_SYMBOL_GPL(fpga_bridge_disable);
  57
  58static struct fpga_bridge *__fpga_bridge_get(struct device *dev,
  59                                             struct fpga_image_info *info)
  60{
  61        struct fpga_bridge *bridge;
  62        int ret = -ENODEV;
  63
  64        bridge = to_fpga_bridge(dev);
  65
  66        bridge->info = info;
  67
  68        if (!mutex_trylock(&bridge->mutex)) {
  69                ret = -EBUSY;
  70                goto err_dev;
  71        }
  72
  73        if (!try_module_get(dev->parent->driver->owner))
  74                goto err_ll_mod;
  75
  76        dev_dbg(&bridge->dev, "get\n");
  77
  78        return bridge;
  79
  80err_ll_mod:
  81        mutex_unlock(&bridge->mutex);
  82err_dev:
  83        put_device(dev);
  84        return ERR_PTR(ret);
  85}
  86
  87/**
  88 * of_fpga_bridge_get - get an exclusive reference to an fpga bridge
  89 *
  90 * @np: node pointer of an FPGA bridge
  91 * @info: fpga image specific information
  92 *
  93 * Return fpga_bridge struct if successful.
  94 * Return -EBUSY if someone already has a reference to the bridge.
  95 * Return -ENODEV if @np is not an FPGA Bridge.
  96 */
  97struct fpga_bridge *of_fpga_bridge_get(struct device_node *np,
  98                                       struct fpga_image_info *info)
  99{
 100        struct device *dev;
 101
 102        dev = class_find_device_by_of_node(fpga_bridge_class, np);
 103        if (!dev)
 104                return ERR_PTR(-ENODEV);
 105
 106        return __fpga_bridge_get(dev, info);
 107}
 108EXPORT_SYMBOL_GPL(of_fpga_bridge_get);
 109
 110static int fpga_bridge_dev_match(struct device *dev, const void *data)
 111{
 112        return dev->parent == data;
 113}
 114
 115/**
 116 * fpga_bridge_get - get an exclusive reference to an fpga bridge
 117 * @dev:        parent device that fpga bridge was registered with
 118 * @info:       fpga manager info
 119 *
 120 * Given a device, get an exclusive reference to an fpga bridge.
 121 *
 122 * Return: fpga bridge struct or IS_ERR() condition containing error code.
 123 */
 124struct fpga_bridge *fpga_bridge_get(struct device *dev,
 125                                    struct fpga_image_info *info)
 126{
 127        struct device *bridge_dev;
 128
 129        bridge_dev = class_find_device(fpga_bridge_class, NULL, dev,
 130                                       fpga_bridge_dev_match);
 131        if (!bridge_dev)
 132                return ERR_PTR(-ENODEV);
 133
 134        return __fpga_bridge_get(bridge_dev, info);
 135}
 136EXPORT_SYMBOL_GPL(fpga_bridge_get);
 137
 138/**
 139 * fpga_bridge_put - release a reference to a bridge
 140 *
 141 * @bridge: FPGA bridge
 142 */
 143void fpga_bridge_put(struct fpga_bridge *bridge)
 144{
 145        dev_dbg(&bridge->dev, "put\n");
 146
 147        bridge->info = NULL;
 148        module_put(bridge->dev.parent->driver->owner);
 149        mutex_unlock(&bridge->mutex);
 150        put_device(&bridge->dev);
 151}
 152EXPORT_SYMBOL_GPL(fpga_bridge_put);
 153
 154/**
 155 * fpga_bridges_enable - enable bridges in a list
 156 * @bridge_list: list of FPGA bridges
 157 *
 158 * Enable each bridge in the list.  If list is empty, do nothing.
 159 *
 160 * Return 0 for success or empty bridge list; return error code otherwise.
 161 */
 162int fpga_bridges_enable(struct list_head *bridge_list)
 163{
 164        struct fpga_bridge *bridge;
 165        int ret;
 166
 167        list_for_each_entry(bridge, bridge_list, node) {
 168                ret = fpga_bridge_enable(bridge);
 169                if (ret)
 170                        return ret;
 171        }
 172
 173        return 0;
 174}
 175EXPORT_SYMBOL_GPL(fpga_bridges_enable);
 176
 177/**
 178 * fpga_bridges_disable - disable bridges in a list
 179 *
 180 * @bridge_list: list of FPGA bridges
 181 *
 182 * Disable each bridge in the list.  If list is empty, do nothing.
 183 *
 184 * Return 0 for success or empty bridge list; return error code otherwise.
 185 */
 186int fpga_bridges_disable(struct list_head *bridge_list)
 187{
 188        struct fpga_bridge *bridge;
 189        int ret;
 190
 191        list_for_each_entry(bridge, bridge_list, node) {
 192                ret = fpga_bridge_disable(bridge);
 193                if (ret)
 194                        return ret;
 195        }
 196
 197        return 0;
 198}
 199EXPORT_SYMBOL_GPL(fpga_bridges_disable);
 200
 201/**
 202 * fpga_bridges_put - put bridges
 203 *
 204 * @bridge_list: list of FPGA bridges
 205 *
 206 * For each bridge in the list, put the bridge and remove it from the list.
 207 * If list is empty, do nothing.
 208 */
 209void fpga_bridges_put(struct list_head *bridge_list)
 210{
 211        struct fpga_bridge *bridge, *next;
 212        unsigned long flags;
 213
 214        list_for_each_entry_safe(bridge, next, bridge_list, node) {
 215                fpga_bridge_put(bridge);
 216
 217                spin_lock_irqsave(&bridge_list_lock, flags);
 218                list_del(&bridge->node);
 219                spin_unlock_irqrestore(&bridge_list_lock, flags);
 220        }
 221}
 222EXPORT_SYMBOL_GPL(fpga_bridges_put);
 223
 224/**
 225 * of_fpga_bridge_get_to_list - get a bridge, add it to a list
 226 *
 227 * @np: node pointer of an FPGA bridge
 228 * @info: fpga image specific information
 229 * @bridge_list: list of FPGA bridges
 230 *
 231 * Get an exclusive reference to the bridge and it to the list.
 232 *
 233 * Return 0 for success, error code from of_fpga_bridge_get() otherwise.
 234 */
 235int of_fpga_bridge_get_to_list(struct device_node *np,
 236                               struct fpga_image_info *info,
 237                               struct list_head *bridge_list)
 238{
 239        struct fpga_bridge *bridge;
 240        unsigned long flags;
 241
 242        bridge = of_fpga_bridge_get(np, info);
 243        if (IS_ERR(bridge))
 244                return PTR_ERR(bridge);
 245
 246        spin_lock_irqsave(&bridge_list_lock, flags);
 247        list_add(&bridge->node, bridge_list);
 248        spin_unlock_irqrestore(&bridge_list_lock, flags);
 249
 250        return 0;
 251}
 252EXPORT_SYMBOL_GPL(of_fpga_bridge_get_to_list);
 253
 254/**
 255 * fpga_bridge_get_to_list - given device, get a bridge, add it to a list
 256 *
 257 * @dev: FPGA bridge device
 258 * @info: fpga image specific information
 259 * @bridge_list: list of FPGA bridges
 260 *
 261 * Get an exclusive reference to the bridge and it to the list.
 262 *
 263 * Return 0 for success, error code from fpga_bridge_get() otherwise.
 264 */
 265int fpga_bridge_get_to_list(struct device *dev,
 266                            struct fpga_image_info *info,
 267                            struct list_head *bridge_list)
 268{
 269        struct fpga_bridge *bridge;
 270        unsigned long flags;
 271
 272        bridge = fpga_bridge_get(dev, info);
 273        if (IS_ERR(bridge))
 274                return PTR_ERR(bridge);
 275
 276        spin_lock_irqsave(&bridge_list_lock, flags);
 277        list_add(&bridge->node, bridge_list);
 278        spin_unlock_irqrestore(&bridge_list_lock, flags);
 279
 280        return 0;
 281}
 282EXPORT_SYMBOL_GPL(fpga_bridge_get_to_list);
 283
 284static ssize_t name_show(struct device *dev,
 285                         struct device_attribute *attr, char *buf)
 286{
 287        struct fpga_bridge *bridge = to_fpga_bridge(dev);
 288
 289        return sprintf(buf, "%s\n", bridge->name);
 290}
 291
 292static ssize_t state_show(struct device *dev,
 293                          struct device_attribute *attr, char *buf)
 294{
 295        struct fpga_bridge *bridge = to_fpga_bridge(dev);
 296        int enable = 1;
 297
 298        if (bridge->br_ops && bridge->br_ops->enable_show)
 299                enable = bridge->br_ops->enable_show(bridge);
 300
 301        return sprintf(buf, "%s\n", enable ? "enabled" : "disabled");
 302}
 303
 304static DEVICE_ATTR_RO(name);
 305static DEVICE_ATTR_RO(state);
 306
 307static struct attribute *fpga_bridge_attrs[] = {
 308        &dev_attr_name.attr,
 309        &dev_attr_state.attr,
 310        NULL,
 311};
 312ATTRIBUTE_GROUPS(fpga_bridge);
 313
 314/**
 315 * fpga_bridge_register - create and register an FPGA Bridge device
 316 * @parent:     FPGA bridge device from pdev
 317 * @name:       FPGA bridge name
 318 * @br_ops:     pointer to structure of fpga bridge ops
 319 * @priv:       FPGA bridge private data
 320 *
 321 * Return: struct fpga_bridge pointer or ERR_PTR()
 322 */
 323struct fpga_bridge *
 324fpga_bridge_register(struct device *parent, const char *name,
 325                     const struct fpga_bridge_ops *br_ops,
 326                     void *priv)
 327{
 328        struct fpga_bridge *bridge;
 329        int id, ret;
 330
 331        if (!br_ops) {
 332                dev_err(parent, "Attempt to register without fpga_bridge_ops\n");
 333                return ERR_PTR(-EINVAL);
 334        }
 335
 336        if (!name || !strlen(name)) {
 337                dev_err(parent, "Attempt to register with no name!\n");
 338                return ERR_PTR(-EINVAL);
 339        }
 340
 341        bridge = kzalloc(sizeof(*bridge), GFP_KERNEL);
 342        if (!bridge)
 343                return ERR_PTR(-ENOMEM);
 344
 345        id = ida_simple_get(&fpga_bridge_ida, 0, 0, GFP_KERNEL);
 346        if (id < 0) {
 347                ret = id;
 348                goto error_kfree;
 349        }
 350
 351        mutex_init(&bridge->mutex);
 352        INIT_LIST_HEAD(&bridge->node);
 353
 354        bridge->name = name;
 355        bridge->br_ops = br_ops;
 356        bridge->priv = priv;
 357
 358        bridge->dev.groups = br_ops->groups;
 359        bridge->dev.class = fpga_bridge_class;
 360        bridge->dev.parent = parent;
 361        bridge->dev.of_node = parent->of_node;
 362        bridge->dev.id = id;
 363        of_platform_populate(bridge->dev.of_node, NULL, NULL, &bridge->dev);
 364
 365        ret = dev_set_name(&bridge->dev, "br%d", id);
 366        if (ret)
 367                goto error_device;
 368
 369        ret = device_register(&bridge->dev);
 370        if (ret) {
 371                put_device(&bridge->dev);
 372                return ERR_PTR(ret);
 373        }
 374
 375        return bridge;
 376
 377error_device:
 378        ida_simple_remove(&fpga_bridge_ida, id);
 379error_kfree:
 380        kfree(bridge);
 381
 382        return ERR_PTR(ret);
 383}
 384EXPORT_SYMBOL_GPL(fpga_bridge_register);
 385
 386/**
 387 * fpga_bridge_unregister - unregister an FPGA bridge
 388 *
 389 * @bridge: FPGA bridge struct
 390 *
 391 * This function is intended for use in an FPGA bridge driver's remove function.
 392 */
 393void fpga_bridge_unregister(struct fpga_bridge *bridge)
 394{
 395        /*
 396         * If the low level driver provides a method for putting bridge into
 397         * a desired state upon unregister, do it.
 398         */
 399        if (bridge->br_ops && bridge->br_ops->fpga_bridge_remove)
 400                bridge->br_ops->fpga_bridge_remove(bridge);
 401
 402        device_unregister(&bridge->dev);
 403}
 404EXPORT_SYMBOL_GPL(fpga_bridge_unregister);
 405
 406static void fpga_bridge_dev_release(struct device *dev)
 407{
 408        struct fpga_bridge *bridge = to_fpga_bridge(dev);
 409
 410        ida_simple_remove(&fpga_bridge_ida, bridge->dev.id);
 411        kfree(bridge);
 412}
 413
 414static int __init fpga_bridge_dev_init(void)
 415{
 416        fpga_bridge_class = class_create(THIS_MODULE, "fpga_bridge");
 417        if (IS_ERR(fpga_bridge_class))
 418                return PTR_ERR(fpga_bridge_class);
 419
 420        fpga_bridge_class->dev_groups = fpga_bridge_groups;
 421        fpga_bridge_class->dev_release = fpga_bridge_dev_release;
 422
 423        return 0;
 424}
 425
 426static void __exit fpga_bridge_dev_exit(void)
 427{
 428        class_destroy(fpga_bridge_class);
 429        ida_destroy(&fpga_bridge_ida);
 430}
 431
 432MODULE_DESCRIPTION("FPGA Bridge Driver");
 433MODULE_AUTHOR("Alan Tull <atull@kernel.org>");
 434MODULE_LICENSE("GPL v2");
 435
 436subsys_initcall(fpga_bridge_dev_init);
 437module_exit(fpga_bridge_dev_exit);
 438