greybus: Merge branch 'master' into driver_model_rework
[cascardo/linux.git] / drivers / staging / greybus / connection.c
1 /*
2  * Greybus connections
3  *
4  * Copyright 2014 Google Inc.
5  *
6  * Released under the GPLv2 only.
7  */
8
9 #include <linux/atomic.h>
10
11 #include "kernel_ver.h"
12 #include "greybus.h"
13
14 static DEFINE_SPINLOCK(gb_connections_lock);
15
16 static void _gb_hd_connection_insert(struct greybus_host_device *hd,
17                                         struct gb_connection *connection)
18 {
19         struct rb_root *root = &hd->connections;
20         struct rb_node *node = &connection->hd_node;
21         struct rb_node **link = &root->rb_node;
22         struct rb_node *above = NULL;
23         u16 cport_id = connection->hd_cport_id;
24
25         while (*link) {
26                 struct gb_connection *connection;
27
28                 above = *link;
29                 connection = rb_entry(above, struct gb_connection, hd_node);
30                 if (connection->hd_cport_id > cport_id)
31                         link = &above->rb_left;
32                 else if (connection->hd_cport_id < cport_id)
33                         link = &above->rb_right;
34         }
35         rb_link_node(node, above, link);
36         rb_insert_color(node, root);
37 }
38
39 static void _gb_hd_connection_remove(struct gb_connection *connection)
40 {
41         rb_erase(&connection->hd_node, &connection->hd->connections);
42 }
43
44 struct gb_connection *gb_hd_connection_find(struct greybus_host_device *hd,
45                                                 u16 cport_id)
46 {
47         struct gb_connection *connection = NULL;
48         struct rb_node *node;
49
50         spin_lock_irq(&gb_connections_lock);
51         node = hd->connections.rb_node;
52         while (node) {
53                 connection = rb_entry(node, struct gb_connection, hd_node);
54                 if (connection->hd_cport_id > cport_id)
55                         node = node->rb_left;
56                 else if (connection->hd_cport_id < cport_id)
57                         node = node->rb_right;
58                 else
59                         goto found;
60         }
61         connection = NULL;
62  found:
63         spin_unlock_irq(&gb_connections_lock);
64
65         return connection;
66 }
67
68 /*
69  * Allocate an available CPort Id for use for the host side of the
70  * given connection.  The lowest-available id is returned, so the
71  * first call is guaranteed to allocate CPort Id 0.
72  *
73  * Assigns the connection's hd_cport_id and returns true if successful.
74  * Returns false otherwise.
75  */
76 static bool gb_connection_hd_cport_id_alloc(struct gb_connection *connection)
77 {
78         struct ida *ida = &connection->hd->cport_id_map;
79         int id;
80
81         spin_lock(&connection->hd->cport_id_map_lock);
82         id = ida_simple_get(ida, 0, HOST_DEV_CPORT_ID_MAX, GFP_KERNEL);
83         spin_unlock(&connection->hd->cport_id_map_lock);
84         if (id < 0)
85                 return false;
86
87         connection->hd_cport_id = (u16)id;
88
89         return true;
90 }
91
92 /*
93  * Free a previously-allocated CPort Id on the given host device.
94  */
95 static void gb_connection_hd_cport_id_free(struct gb_connection *connection)
96 {
97         struct ida *ida = &connection->hd->cport_id_map;
98
99         spin_lock(&connection->hd->cport_id_map_lock);
100         ida_simple_remove(ida, connection->hd_cport_id);
101         spin_unlock(&connection->hd->cport_id_map_lock);
102         connection->hd_cport_id = CPORT_ID_BAD;
103 }
104
105 static ssize_t state_show(struct device *dev, struct device_attribute *attr,
106                           char *buf)
107 {
108         struct gb_connection *connection = to_gb_connection(dev);
109
110         return sprintf(buf, "%d", connection->state);
111 }
112 static DEVICE_ATTR_RO(state);
113
114 static ssize_t protocol_show(struct device *dev, struct device_attribute *attr,
115                              char *buf)
116 {
117         struct gb_connection *connection = to_gb_connection(dev);
118
119         return sprintf(buf, "%d", connection->protocol);
120 }
121 static DEVICE_ATTR_RO(protocol);
122
123 static struct attribute *connection_attrs[] = {
124         &dev_attr_state.attr,
125         &dev_attr_protocol.attr,
126         NULL,
127 };
128
129 ATTRIBUTE_GROUPS(connection);
130
131 static void gb_connection_release(struct device *dev)
132 {
133         struct gb_connection *connection = to_gb_connection(dev);
134
135         kfree(connection);
136 }
137
138 static struct device_type greybus_connection_type = {
139         .name =         "greybus_connection",
140         .release =      gb_connection_release,
141 };
142
143 /*
144  * Set up a Greybus connection, representing the bidirectional link
145  * between a CPort on a (local) Greybus host device and a CPort on
146  * another Greybus module.
147  *
148  * A connection also maintains the state of operations sent over the
149  * connection.
150  *
151  * Returns a pointer to the new connection if successful, or a null
152  * pointer otherwise.
153  */
154 struct gb_connection *gb_connection_create(struct gb_interface *interface,
155                                 u16 cport_id, enum greybus_protocol protocol)
156 {
157         struct gb_connection *connection;
158         struct greybus_host_device *hd;
159         int retval;
160
161         connection = kzalloc(sizeof(*connection), GFP_KERNEL);
162         if (!connection)
163                 return NULL;
164
165         hd = interface->gmod->hd;
166         connection->hd = hd;                    /* XXX refcount? */
167         if (!gb_connection_hd_cport_id_alloc(connection)) {
168                 /* kref_put(connection->hd); */
169                 kfree(connection);
170                 return NULL;
171         }
172
173         connection->interface = interface;
174         connection->interface_cport_id = cport_id;
175         connection->protocol = protocol;
176         connection->state = GB_CONNECTION_STATE_DISABLED;
177
178         connection->dev.parent = &interface->dev;
179         connection->dev.driver = NULL;
180         connection->dev.bus = &greybus_bus_type;
181         connection->dev.type = &greybus_connection_type;
182         connection->dev.groups = connection_groups;
183         device_initialize(&connection->dev);
184         dev_set_name(&connection->dev, "%s:%d",
185                      dev_name(&interface->dev), cport_id);
186
187         retval = device_add(&connection->dev);
188         if (retval) {
189                 kfree(connection);
190                 return NULL;
191         }
192
193         spin_lock_irq(&gb_connections_lock);
194         _gb_hd_connection_insert(hd, connection);
195         list_add_tail(&connection->interface_links, &interface->connections);
196         spin_unlock_irq(&gb_connections_lock);
197
198         INIT_LIST_HEAD(&connection->operations);
199         connection->pending = RB_ROOT;
200         atomic_set(&connection->op_cycle, 0);
201
202         return connection;
203 }
204
205 /*
206  * Tear down a previously set up connection.
207  */
208 void gb_connection_destroy(struct gb_connection *connection)
209 {
210         struct gb_operation *operation;
211         struct gb_operation *next;
212
213         if (WARN_ON(!connection))
214                 return;
215
216         /* XXX Need to wait for any outstanding requests to complete */
217         WARN_ON(!list_empty(&connection->operations));
218
219         list_for_each_entry_safe(operation, next, &connection->operations,
220                                         links) {
221                 gb_operation_cancel(operation);
222         }
223         spin_lock_irq(&gb_connections_lock);
224         list_del(&connection->interface_links);
225         _gb_hd_connection_remove(connection);
226         spin_unlock_irq(&gb_connections_lock);
227
228         gb_connection_hd_cport_id_free(connection);
229
230         device_del(&connection->dev);
231 }
232
233 u16 gb_connection_operation_id(struct gb_connection *connection)
234 {
235         return (u16)(atomic_inc_return(&connection->op_cycle) & (int)U16_MAX);
236 }
237
238 void gb_connection_err(struct gb_connection *connection, const char *fmt, ...)
239 {
240         struct va_format vaf;
241         va_list args;
242
243         va_start(args, fmt);
244
245         vaf.fmt = fmt;
246         vaf.va = &args;
247
248         pr_err("greybus: [%hhu:%hhu:%hu]: %pV\n",
249                 connection->interface->gmod->module_id,
250                 connection->interface->id,
251                 connection->interface_cport_id, &vaf);
252
253         va_end(args);
254 }
255
256 /*
257  * XXX Protocols should have a set of function pointers:
258  *      ->init (called here, to initialize the device)
259  *      ->input_handler
260  *      ->exit (reverse of init)
261  */
262 int gb_connection_init(struct gb_connection *connection)
263 {
264         int ret;
265
266         /* Need to enable the connection to initialize it */
267         connection->state = GB_CONNECTION_STATE_ENABLED;
268         switch (connection->protocol) {
269         case GREYBUS_PROTOCOL_I2C:
270                 connection->handler = &gb_i2c_connection_handler;
271                 break;
272         case GREYBUS_PROTOCOL_GPIO:
273                 connection->handler = &gb_gpio_connection_handler;
274                 break;
275         case GREYBUS_PROTOCOL_BATTERY:
276                 connection->handler = &gb_battery_connection_handler;
277                 break;
278         case GREYBUS_PROTOCOL_UART:
279                 connection->handler = &gb_uart_connection_handler;
280                 break;
281         case GREYBUS_PROTOCOL_CONTROL:
282         case GREYBUS_PROTOCOL_AP:
283         case GREYBUS_PROTOCOL_HID:
284         case GREYBUS_PROTOCOL_LED:
285         case GREYBUS_PROTOCOL_VENDOR:
286         default:
287                 gb_connection_err(connection, "unimplemented protocol %u",
288                         (u32)connection->protocol);
289                 ret = -ENXIO;
290                 break;
291         }
292
293         if (ret)
294                 connection->state = GB_CONNECTION_STATE_ERROR;
295
296         return ret;
297 }
298
299 void gb_connection_exit(struct gb_connection *connection)
300 {
301         if (!connection->handler) {
302                 gb_connection_err(connection, "uninitialized connection");
303                 return;
304         }
305         connection->state = GB_CONNECTION_STATE_DESTROYING;
306         connection->handler->connection_exit(connection);
307 }