Skip to content

Commit 5b57d02

Browse files
Xiao Guangronggregkh
authored andcommitted
fpga: dfl: add feature device infrastructure
This patch abstracts the common operations of the sub features and defines the feature_ops data structure, including init, uinit and ioctl function pointers. And this patch adds some common helper functions for FME and AFU drivers, e.g. dfl_feature_dev_use_begin/end which are used to ensure exclusive usage of the feature device file. Signed-off-by: Tim Whisonant <[email protected]> Signed-off-by: Enno Luebbers <[email protected]> Signed-off-by: Shiva Rao <[email protected]> Signed-off-by: Christopher Rauer <[email protected]> Signed-off-by: Kang Luwei <[email protected]> Signed-off-by: Zhang Yi <[email protected]> Signed-off-by: Xiao Guangrong <[email protected]> Signed-off-by: Wu Hao <[email protected]> Acked-by: Alan Tull <[email protected]> Signed-off-by: Greg Kroah-Hartman <[email protected]>
1 parent 5d56e11 commit 5b57d02

File tree

2 files changed

+152
-1
lines changed

2 files changed

+152
-1
lines changed

drivers/fpga/dfl.c

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,77 @@ static enum dfl_id_type dfh_id_to_type(u32 id)
136136
return DFL_ID_MAX;
137137
}
138138

139+
/**
140+
* dfl_fpga_dev_feature_uinit - uinit for sub features of dfl feature device
141+
* @pdev: feature device.
142+
*/
143+
void dfl_fpga_dev_feature_uinit(struct platform_device *pdev)
144+
{
145+
struct dfl_feature_platform_data *pdata = dev_get_platdata(&pdev->dev);
146+
struct dfl_feature *feature;
147+
148+
dfl_fpga_dev_for_each_feature(pdata, feature)
149+
if (feature->ops) {
150+
feature->ops->uinit(pdev, feature);
151+
feature->ops = NULL;
152+
}
153+
}
154+
EXPORT_SYMBOL_GPL(dfl_fpga_dev_feature_uinit);
155+
156+
static int dfl_feature_instance_init(struct platform_device *pdev,
157+
struct dfl_feature_platform_data *pdata,
158+
struct dfl_feature *feature,
159+
struct dfl_feature_driver *drv)
160+
{
161+
int ret;
162+
163+
ret = drv->ops->init(pdev, feature);
164+
if (ret)
165+
return ret;
166+
167+
feature->ops = drv->ops;
168+
169+
return ret;
170+
}
171+
172+
/**
173+
* dfl_fpga_dev_feature_init - init for sub features of dfl feature device
174+
* @pdev: feature device.
175+
* @feature_drvs: drvs for sub features.
176+
*
177+
* This function will match sub features with given feature drvs list and
178+
* use matched drv to init related sub feature.
179+
*
180+
* Return: 0 on success, negative error code otherwise.
181+
*/
182+
int dfl_fpga_dev_feature_init(struct platform_device *pdev,
183+
struct dfl_feature_driver *feature_drvs)
184+
{
185+
struct dfl_feature_platform_data *pdata = dev_get_platdata(&pdev->dev);
186+
struct dfl_feature_driver *drv = feature_drvs;
187+
struct dfl_feature *feature;
188+
int ret;
189+
190+
while (drv->ops) {
191+
dfl_fpga_dev_for_each_feature(pdata, feature) {
192+
/* match feature and drv using id */
193+
if (feature->id == drv->id) {
194+
ret = dfl_feature_instance_init(pdev, pdata,
195+
feature, drv);
196+
if (ret)
197+
goto exit;
198+
}
199+
}
200+
drv++;
201+
}
202+
203+
return 0;
204+
exit:
205+
dfl_fpga_dev_feature_uinit(pdev);
206+
return ret;
207+
}
208+
EXPORT_SYMBOL_GPL(dfl_fpga_dev_feature_init);
209+
139210
static void dfl_chardev_uinit(void)
140211
{
141212
int i;

drivers/fpga/dfl.h

Lines changed: 81 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,17 @@
131131
#define PORT_CTRL_LATENCY BIT_ULL(2)
132132
#define PORT_CTRL_SFTRST_ACK BIT_ULL(4) /* HW ack for reset */
133133

134+
/**
135+
* struct dfl_feature_driver - sub feature's driver
136+
*
137+
* @id: sub feature id.
138+
* @ops: ops of this sub feature.
139+
*/
140+
struct dfl_feature_driver {
141+
u64 id;
142+
const struct dfl_feature_ops *ops;
143+
};
144+
134145
/**
135146
* struct dfl_feature - sub feature of the feature devices
136147
*
@@ -139,13 +150,17 @@
139150
* this index is used to find its mmio resource from the
140151
* feature dev (platform device)'s reources.
141152
* @ioaddr: mapped mmio resource address.
153+
* @ops: ops of this sub feature.
142154
*/
143155
struct dfl_feature {
144156
u64 id;
145157
int resource_index;
146158
void __iomem *ioaddr;
159+
const struct dfl_feature_ops *ops;
147160
};
148161

162+
#define DEV_STATUS_IN_USE 0
163+
149164
/**
150165
* struct dfl_feature_platform_data - platform data for feature devices
151166
*
@@ -156,6 +171,8 @@ struct dfl_feature {
156171
* @dfl_cdev: ptr to container device.
157172
* @disable_count: count for port disable.
158173
* @num: number for sub features.
174+
* @dev_status: dev status (e.g. DEV_STATUS_IN_USE).
175+
* @private: ptr to feature dev private data.
159176
* @features: sub features of this feature dev.
160177
*/
161178
struct dfl_feature_platform_data {
@@ -165,11 +182,49 @@ struct dfl_feature_platform_data {
165182
struct platform_device *dev;
166183
struct dfl_fpga_cdev *dfl_cdev;
167184
unsigned int disable_count;
168-
185+
unsigned long dev_status;
186+
void *private;
169187
int num;
170188
struct dfl_feature features[0];
171189
};
172190

191+
static inline
192+
int dfl_feature_dev_use_begin(struct dfl_feature_platform_data *pdata)
193+
{
194+
/* Test and set IN_USE flags to ensure file is exclusively used */
195+
if (test_and_set_bit_lock(DEV_STATUS_IN_USE, &pdata->dev_status))
196+
return -EBUSY;
197+
198+
return 0;
199+
}
200+
201+
static inline
202+
void dfl_feature_dev_use_end(struct dfl_feature_platform_data *pdata)
203+
{
204+
clear_bit_unlock(DEV_STATUS_IN_USE, &pdata->dev_status);
205+
}
206+
207+
static inline
208+
void dfl_fpga_pdata_set_private(struct dfl_feature_platform_data *pdata,
209+
void *private)
210+
{
211+
pdata->private = private;
212+
}
213+
214+
static inline
215+
void *dfl_fpga_pdata_get_private(struct dfl_feature_platform_data *pdata)
216+
{
217+
return pdata->private;
218+
}
219+
220+
struct dfl_feature_ops {
221+
int (*init)(struct platform_device *pdev, struct dfl_feature *feature);
222+
void (*uinit)(struct platform_device *pdev,
223+
struct dfl_feature *feature);
224+
long (*ioctl)(struct platform_device *pdev, struct dfl_feature *feature,
225+
unsigned int cmd, unsigned long arg);
226+
};
227+
173228
#define DFL_FPGA_FEATURE_DEV_FME "dfl-fme"
174229
#define DFL_FPGA_FEATURE_DEV_PORT "dfl-port"
175230

@@ -179,11 +234,25 @@ static inline int dfl_feature_platform_data_size(const int num)
179234
num * sizeof(struct dfl_feature);
180235
}
181236

237+
void dfl_fpga_dev_feature_uinit(struct platform_device *pdev);
238+
int dfl_fpga_dev_feature_init(struct platform_device *pdev,
239+
struct dfl_feature_driver *feature_drvs);
240+
182241
int dfl_fpga_dev_ops_register(struct platform_device *pdev,
183242
const struct file_operations *fops,
184243
struct module *owner);
185244
void dfl_fpga_dev_ops_unregister(struct platform_device *pdev);
186245

246+
static inline
247+
struct platform_device *dfl_fpga_inode_to_feature_dev(struct inode *inode)
248+
{
249+
struct dfl_feature_platform_data *pdata;
250+
251+
pdata = container_of(inode->i_cdev, struct dfl_feature_platform_data,
252+
cdev);
253+
return pdata->dev;
254+
}
255+
187256
#define dfl_fpga_dev_for_each_feature(pdata, feature) \
188257
for ((feature) = (pdata)->features; \
189258
(feature) < (pdata)->features + (pdata)->num; (feature)++)
@@ -213,6 +282,17 @@ void __iomem *dfl_get_feature_ioaddr_by_id(struct device *dev, u64 id)
213282
return NULL;
214283
}
215284

285+
static inline bool is_dfl_feature_present(struct device *dev, u64 id)
286+
{
287+
return !!dfl_get_feature_ioaddr_by_id(dev, id);
288+
}
289+
290+
static inline
291+
struct device *dfl_fpga_pdata_to_parent(struct dfl_feature_platform_data *pdata)
292+
{
293+
return pdata->dev->dev.parent->parent;
294+
}
295+
216296
static inline bool dfl_feature_is_fme(void __iomem *base)
217297
{
218298
u64 v = readq(base + DFH);

0 commit comments

Comments
 (0)