]> git.karo-electronics.de Git - karo-tx-linux.git/blob - drivers/staging/greybus/interface.c
greybus: interface: add gb_interface_find()
[karo-tx-linux.git] / drivers / staging / greybus / interface.c
1 /*
2  * Greybus interfaces
3  *
4  * Copyright 2014 Google Inc.
5  *
6  * Released under the GPLv2 only.
7  */
8
9 #include "greybus.h"
10
11 /* XXX This could be per-host device or per-module */
12 static DEFINE_SPINLOCK(gb_interfaces_lock);
13
14 /*
15  * A Greybus interface represents a UniPro device present on a
16  * module.  For Project Ara, each active Interface Block on a module
17  * implements a UniPro device, and therefore a Greybus interface.  A
18  * Greybus module has at least one interface, but can have two (or
19  * even more).
20  *
21  * Create a gb_interface structure to represent a discovered
22  * interface.  Returns a pointer to the new interface or a null
23  * pointer if a failure occurs due to memory exhaustion.
24  */
25 struct gb_interface *
26 gb_interface_create(struct gb_module *gmod, u8 interface_id)
27 {
28         struct gb_interface *interface;
29
30         interface = kzalloc(sizeof(*interface), GFP_KERNEL);
31         if (!interface)
32                 return NULL;
33
34         interface->gmod = gmod;         /* XXX refcount? */
35         interface->id = interface_id;
36         INIT_LIST_HEAD(&interface->connections);
37
38         spin_lock_irq(&gb_interfaces_lock);
39         list_add_tail(&interface->links, &gmod->interfaces);
40         spin_unlock_irq(&gb_interfaces_lock);
41
42         return interface;
43 }
44
45 /*
46  * Tear down a previously set up interface.
47  */
48 void gb_interface_destroy(struct gb_interface *interface)
49 {
50         if (WARN_ON(!interface))
51                 return;
52
53         spin_lock_irq(&gb_interfaces_lock);
54         list_del(&interface->links);
55         spin_unlock_irq(&gb_interfaces_lock);
56
57         gb_interface_connections_exit(interface);
58
59         /* kref_put(gmod); */
60         kfree(interface);
61 }
62
63 struct gb_interface *gb_interface_find(struct gb_module *module,
64                                       u8 interface_id)
65 {
66         struct gb_interface *interface;
67
68         list_for_each_entry(interface, &module->interfaces, links)
69                 if (interface->id == interface_id)
70                         return interface;
71
72         return NULL;
73 }
74
75 int gb_interface_connections_init(struct gb_interface *interface)
76 {
77         struct gb_connection *connection;
78         int ret = 0;
79
80         list_for_each_entry(connection, &interface->connections,
81                         interface_links) {
82                 ret = gb_connection_init(connection);
83                 if (ret)
84                         break;
85         }
86
87         return ret;
88 }
89
90 void gb_interface_connections_exit(struct gb_interface *interface)
91 {
92         struct gb_connection *connection;
93         struct gb_connection *next;
94
95         list_for_each_entry_safe(connection, next, &interface->connections,
96                         interface_links) {
97                 gb_connection_exit(connection);
98                 gb_connection_destroy(connection);
99         }
100 }