aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/fpga/dfl.c
diff options
context:
space:
mode:
authorWu Hao <hao.wu@intel.com>2018-06-29 20:53:17 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2018-07-15 07:55:45 -0400
commit6e8fd6e493bfca83021cc6a8fd86d7f69bd14fc6 (patch)
treeaf3fbc09c6a38add8eac0c811ee6b80c624f3b7f /drivers/fpga/dfl.c
parent5b57d02a2f94bb04c6b36932412f7f3b1bb38518 (diff)
fpga: dfl: add dfl_fpga_port_ops support.
In some cases, other DFL driver modules may need to access some port operations, e.g. disable / enable port for partial reconfiguration in FME module. In order to avoid dependency between port and FME modules, this patch introduces the dfl_fpga_port_ops support in DFL framework. A global dfl_fpga_port_ops list is added in the DFL framework, and it allows other DFL modules to use these port operations registered to this list, even in virtualization case, the port platform device is turned into VF / guest VM and hidden in host, the registered port_ops is still usable. It resolves the dependency issues between modules, but once get port ops API returns a valid port ops, that means related port driver module has been module_get to prevent from unexpected unload, and put port ops API must be invoked after use. These APIs introduced by this patch is listed below: * dfl_fpga_port_ops_add add one port ops to the global list. * dfl_fpga_port_ops_del del one port ops from the global list. * dfl_fpga_port_ops_get / dfl_fpga_port_ops_put get/put the port ops before/after use. Signed-off-by: Wu Hao <hao.wu@intel.com> Acked-by: Alan Tull <atull@kernel.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/fpga/dfl.c')
-rw-r--r--drivers/fpga/dfl.c79
1 files changed, 79 insertions, 0 deletions
diff --git a/drivers/fpga/dfl.c b/drivers/fpga/dfl.c
index e2c72c5dd9e6..421668ab613e 100644
--- a/drivers/fpga/dfl.c
+++ b/drivers/fpga/dfl.c
@@ -136,6 +136,85 @@ static enum dfl_id_type dfh_id_to_type(u32 id)
136 return DFL_ID_MAX; 136 return DFL_ID_MAX;
137} 137}
138 138
139/*
140 * introduce a global port_ops list, it allows port drivers to register ops
141 * in such list, then other feature devices (e.g. FME), could use the port
142 * functions even related port platform device is hidden. Below is one example,
143 * in virtualization case of PCIe-based FPGA DFL device, when SRIOV is
144 * enabled, port (and it's AFU) is turned into VF and port platform device
145 * is hidden from system but it's still required to access port to finish FPGA
146 * reconfiguration function in FME.
147 */
148
149static DEFINE_MUTEX(dfl_port_ops_mutex);
150static LIST_HEAD(dfl_port_ops_list);
151
152/**
153 * dfl_fpga_port_ops_get - get matched port ops from the global list
154 * @pdev: platform device to match with associated port ops.
155 * Return: matched port ops on success, NULL otherwise.
156 *
157 * Please note that must dfl_fpga_port_ops_put after use the port_ops.
158 */
159struct dfl_fpga_port_ops *dfl_fpga_port_ops_get(struct platform_device *pdev)
160{
161 struct dfl_fpga_port_ops *ops = NULL;
162
163 mutex_lock(&dfl_port_ops_mutex);
164 if (list_empty(&dfl_port_ops_list))
165 goto done;
166
167 list_for_each_entry(ops, &dfl_port_ops_list, node) {
168 /* match port_ops using the name of platform device */
169 if (!strcmp(pdev->name, ops->name)) {
170 if (!try_module_get(ops->owner))
171 ops = NULL;
172 goto done;
173 }
174 }
175
176 ops = NULL;
177done:
178 mutex_unlock(&dfl_port_ops_mutex);
179 return ops;
180}
181EXPORT_SYMBOL_GPL(dfl_fpga_port_ops_get);
182
183/**
184 * dfl_fpga_port_ops_put - put port ops
185 * @ops: port ops.
186 */
187void dfl_fpga_port_ops_put(struct dfl_fpga_port_ops *ops)
188{
189 if (ops && ops->owner)
190 module_put(ops->owner);
191}
192EXPORT_SYMBOL_GPL(dfl_fpga_port_ops_put);
193
194/**
195 * dfl_fpga_port_ops_add - add port_ops to global list
196 * @ops: port ops to add.
197 */
198void dfl_fpga_port_ops_add(struct dfl_fpga_port_ops *ops)
199{
200 mutex_lock(&dfl_port_ops_mutex);
201 list_add_tail(&ops->node, &dfl_port_ops_list);
202 mutex_unlock(&dfl_port_ops_mutex);
203}
204EXPORT_SYMBOL_GPL(dfl_fpga_port_ops_add);
205
206/**
207 * dfl_fpga_port_ops_del - remove port_ops from global list
208 * @ops: port ops to del.
209 */
210void dfl_fpga_port_ops_del(struct dfl_fpga_port_ops *ops)
211{
212 mutex_lock(&dfl_port_ops_mutex);
213 list_del(&ops->node);
214 mutex_unlock(&dfl_port_ops_mutex);
215}
216EXPORT_SYMBOL_GPL(dfl_fpga_port_ops_del);
217
139/** 218/**
140 * dfl_fpga_dev_feature_uinit - uinit for sub features of dfl feature device 219 * dfl_fpga_dev_feature_uinit - uinit for sub features of dfl feature device
141 * @pdev: feature device. 220 * @pdev: feature device.