*/
#include <linux/component.h>
+#include <linux/kfifo.h>
#include <linux/of_graph.h>
#include <linux/of_reserved_mem.h>
* matching system handles this for us.
*/
struct endpoint_list {
- struct device_node *node;
- struct list_head list;
+ DECLARE_KFIFO(fifo, struct device_node *, 16);
};
-static bool node_is_in_list(struct list_head *endpoints,
- struct device_node *node)
-{
- struct endpoint_list *endpoint;
-
- list_for_each_entry(endpoint, endpoints, list)
- if (endpoint->node == node)
- return true;
-
- return false;
-}
-
static int sun4i_drv_add_endpoints(struct device *dev,
- struct list_head *endpoints,
+ struct endpoint_list *list,
struct component_match **match,
struct device_node *node)
{
struct device_node *port, *ep, *remote;
- struct endpoint_list *endpoint;
int count = 0;
/*
}
}
- /* skip downstream node if it is already in the queue */
- if (node_is_in_list(endpoints, remote))
- continue;
-
- /* Add downstream nodes to the queue */
- endpoint = kzalloc(sizeof(*endpoint), GFP_KERNEL);
- if (!endpoint) {
- of_node_put(remote);
- return -ENOMEM;
- }
-
- endpoint->node = remote;
- list_add_tail(&endpoint->list, endpoints);
+ kfifo_put(&list->fifo, remote);
}
return count;
static int sun4i_drv_probe(struct platform_device *pdev)
{
struct component_match *match = NULL;
- struct device_node *np = pdev->dev.of_node;
- struct endpoint_list *endpoint, *endpoint_temp;
+ struct device_node *np = pdev->dev.of_node, *endpoint;
+ struct endpoint_list list;
int i, ret, count = 0;
- LIST_HEAD(endpoints);
+
+ INIT_KFIFO(list.fifo);
for (i = 0;; i++) {
struct device_node *pipeline = of_parse_phandle(np,
if (!pipeline)
break;
- endpoint = kzalloc(sizeof(*endpoint), GFP_KERNEL);
- if (!endpoint) {
- ret = -ENOMEM;
- goto err_free_endpoints;
- }
-
- endpoint->node = pipeline;
- list_add_tail(&endpoint->list, &endpoints);
+ kfifo_put(&list.fifo, pipeline);
}
- list_for_each_entry_safe(endpoint, endpoint_temp, &endpoints, list) {
+ while (kfifo_get(&list.fifo, &endpoint)) {
/* process this endpoint */
- ret = sun4i_drv_add_endpoints(&pdev->dev, &endpoints, &match,
- endpoint->node);
+ ret = sun4i_drv_add_endpoints(&pdev->dev, &list, &match,
+ endpoint);
/* sun4i_drv_add_endpoints can fail to allocate memory */
if (ret < 0)
- goto err_free_endpoints;
+ return ret;
count += ret;
-
- /* delete and cleanup the current entry */
- list_del(&endpoint->list);
- of_node_put(endpoint->node);
- kfree(endpoint);
}
if (count)
match);
else
return 0;
-
-err_free_endpoints:
- list_for_each_entry_safe(endpoint, endpoint_temp, &endpoints, list) {
- list_del(&endpoint->list);
- of_node_put(endpoint->node);
- kfree(endpoint);
- }
-
- return ret;
}
static int sun4i_drv_remove(struct platform_device *pdev)