Skip to content

Commit 98086f3

Browse files
committed
jesd204: collect all devices on framework init
The overall mode of operation for the framework will be that upon initialization, the framework will collect all data (from device-trees) for all JESD204 devices, and build internal representations for all of them, and their respective links/topologies. That way, when the kernel probes these devices, the JESD204 framework can update states for these devices, links &topologies and can catch various errors/omissions that drivers may have. This makes it easier to see which device in a topology (of JESD204 devices) has updated/initialized and which error-ed. Signed-off-by: Alexandru Ardelean <[email protected]>
1 parent c85fbbd commit 98086f3

File tree

3 files changed

+156
-0
lines changed

3 files changed

+156
-0
lines changed

drivers/jesd204/jesd204-core.c

Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,14 +9,120 @@
99

1010
#include <linux/kernel.h>
1111
#include <linux/module.h>
12+
#include <linux/device.h>
13+
#include <linux/of.h>
14+
#include <linux/slab.h>
15+
16+
#include "jesd204-priv.h"
17+
18+
static DEFINE_MUTEX(jesd204_device_list_lock);
19+
static LIST_HEAD(jesd204_device_list);
20+
21+
static unsigned int jesd204_device_count;
22+
23+
static struct jesd204_dev *jesd204_dev_alloc(struct device_node *np)
24+
{
25+
struct jesd204_dev *jdev;
26+
27+
jdev = kzalloc(sizeof(*jdev), GFP_KERNEL);
28+
if (!jdev)
29+
return ERR_PTR(-ENOMEM);
30+
31+
kref_get(&jdev->ref);
32+
33+
jdev->np = of_node_get(np);
34+
kref_init(&jdev->ref);
35+
36+
list_add(&jdev->list, &jesd204_device_list);
37+
jesd204_device_count++;
38+
39+
return jdev;
40+
}
41+
42+
static int jesd204_of_create_devices(void)
43+
{
44+
struct jesd204_dev *jdev;
45+
struct device_node *np;
46+
int ret;
47+
48+
mutex_lock(&jesd204_device_list_lock);
49+
50+
ret = 0;
51+
for_each_node_with_property(np, "jesd204-device") {
52+
jdev = jesd204_dev_alloc(np);
53+
if (IS_ERR(jdev)) {
54+
ret = PTR_ERR(jdev);
55+
goto unlock;
56+
}
57+
}
58+
59+
unlock:
60+
mutex_unlock(&jesd204_device_list_lock);
61+
62+
return ret;
63+
}
64+
65+
static void jesd204_of_unregister_devices(void)
66+
{
67+
struct jesd204_dev *jdev, *j;
68+
69+
list_for_each_entry_safe(jdev, j, &jesd204_device_list, list) {
70+
jesd204_dev_unregister(jdev);
71+
}
72+
}
73+
74+
/* Free memory allocated. */
75+
static void __jesd204_dev_release(struct kref *ref)
76+
{
77+
struct jesd204_dev *jdev = container_of(ref, struct jesd204_dev, ref);
78+
79+
mutex_lock(&jesd204_device_list_lock);
80+
81+
list_del(&jdev->list);
82+
of_node_put(jdev->np);
83+
84+
kfree(jdev);
85+
86+
jesd204_device_count--;
87+
88+
mutex_unlock(&jesd204_device_list_lock);
89+
}
90+
91+
/**
92+
* jesd204_dev_unregister() - unregister a device from the JESD204 subsystem
93+
* @jdev: Device structure representing the device.
94+
**/
95+
void jesd204_dev_unregister(struct jesd204_dev *jdev)
96+
{
97+
if (IS_ERR_OR_NULL(jdev))
98+
return;
99+
100+
kref_put(&jdev->ref, __jesd204_dev_release);
101+
}
102+
EXPORT_SYMBOL(jesd204_dev_unregister);
12103

13104
static int __init jesd204_init(void)
14105
{
106+
int ret;
107+
108+
mutex_init(&jesd204_device_list_lock);
109+
110+
ret = jesd204_of_create_devices();
111+
if (ret < 0)
112+
goto error_unreg_devices;
113+
15114
return 0;
115+
116+
error_unreg_devices:
117+
jesd204_of_unregister_devices();
118+
pr_err("framework error: %d\n", ret);
119+
return ret;
16120
}
17121

18122
static void __exit jesd204_exit(void)
19123
{
124+
jesd204_of_unregister_devices();
125+
mutex_destroy(&jesd204_device_list_lock);
20126
}
21127

22128
subsys_initcall(jesd204_init);

drivers/jesd204/jesd204-priv.h

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
/* SPDX-License-Identifier: GPL-2.0+ */
2+
/**
3+
* The JESD204 framework
4+
*
5+
* Copyright (c) 2019 Analog Devices Inc.
6+
*/
7+
8+
#ifndef _JESD204_PRIV_H_
9+
#define _JESD204_PRIV_H_
10+
11+
#include <linux/jesd204/jesd204.h>
12+
13+
struct jesd204_dev;
14+
15+
/**
16+
* struct jesd204_dev - JESD204 device
17+
* @list list entry for the framework to keep a list of devices
18+
* @np reference in the device-tree for this JESD204 device
19+
* @ref ref count for this JESD204 device
20+
*/
21+
struct jesd204_dev {
22+
struct list_head list;
23+
24+
struct device_node *np;
25+
struct kref ref;
26+
};
27+
28+
#endif /* _JESD204_PRIV_H_ */

include/linux/jesd204/jesd204.h

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
/* SPDX-License-Identifier: GPL-2.0+ */
2+
/**
3+
* The JESD204 framework
4+
*
5+
* Copyright (c) 2019 Analog Devices Inc.
6+
*/
7+
#ifndef _JESD204_H_
8+
#define _JESD204_H_
9+
10+
struct jesd204_dev;
11+
12+
#if IS_ENABLED(CONFIG_JESD204)
13+
14+
void jesd204_dev_unregister(struct jesd204_dev *jdev);
15+
16+
#else /* !IS_ENABLED(CONFIG_JESD204) */
17+
18+
static inline void jesd204_dev_unregister(struct jesd204_dev *jdev) {}
19+
20+
#endif /* IS_ENABLED(CONFIG_JESD204) */
21+
22+
#endif

0 commit comments

Comments
 (0)