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