f89b199230dc717971469696ed2a653bd5d79b58
[cascardo/linux.git] / drivers / staging / greybus / connection.c
1 /*
2  * Greybus connections
3  *
4  * Copyright 2014 Google Inc.
5  * Copyright 2014 Linaro Ltd.
6  *
7  * Released under the GPLv2 only.
8  */
9
10 #include <linux/workqueue.h>
11
12 #include "greybus.h"
13
14 #define GB_CONNECTION_TS_KFIFO_ELEMENTS 2
15 #define GB_CONNECTION_TS_KFIFO_LEN \
16         (GB_CONNECTION_TS_KFIFO_ELEMENTS * sizeof(struct timeval))
17
18 static DEFINE_SPINLOCK(gb_connections_lock);
19
20 /* This is only used at initialization time; no locking is required. */
21 static struct gb_connection *
22 gb_connection_intf_find(struct gb_interface *intf, u16 cport_id)
23 {
24         struct greybus_host_device *hd = intf->hd;
25         struct gb_connection *connection;
26
27         list_for_each_entry(connection, &hd->connections, hd_links)
28                 if (connection->bundle->intf == intf &&
29                                 connection->intf_cport_id == cport_id)
30                         return connection;
31         return NULL;
32 }
33
34 static struct gb_connection *
35 gb_connection_hd_find(struct greybus_host_device *hd, u16 cport_id)
36 {
37         struct gb_connection *connection;
38         unsigned long flags;
39
40         spin_lock_irqsave(&gb_connections_lock, flags);
41         list_for_each_entry(connection, &hd->connections, hd_links)
42                 if (connection->hd_cport_id == cport_id)
43                         goto found;
44         connection = NULL;
45 found:
46         spin_unlock_irqrestore(&gb_connections_lock, flags);
47
48         return connection;
49 }
50
51 /*
52  * Callback from the host driver to let us know that data has been
53  * received on the bundle.
54  */
55 void greybus_data_rcvd(struct greybus_host_device *hd, u16 cport_id,
56                         u8 *data, size_t length)
57 {
58         struct gb_connection *connection;
59
60         connection = gb_connection_hd_find(hd, cport_id);
61         if (!connection) {
62                 dev_err(hd->parent,
63                         "nonexistent connection (%zu bytes dropped)\n", length);
64                 return;
65         }
66         gb_connection_recv(connection, data, length);
67 }
68 EXPORT_SYMBOL_GPL(greybus_data_rcvd);
69
70 void gb_connection_push_timestamp(struct gb_connection *connection)
71 {
72         struct timeval tv;
73
74         do_gettimeofday(&tv);
75         kfifo_in_locked(&connection->ts_kfifo, (void *)&tv,
76                         sizeof(struct timeval), &connection->lock);
77 }
78 EXPORT_SYMBOL_GPL(gb_connection_push_timestamp);
79
80 int gb_connection_pop_timestamp(struct gb_connection *connection,
81                                 struct timeval *tv)
82 {
83         int retval;
84
85         if (!kfifo_len(&connection->ts_kfifo))
86                 return -ENOMEM;
87         retval = kfifo_out_locked(&connection->ts_kfifo, (void *)tv,
88                                   sizeof(*tv), &connection->lock);
89         return retval;
90 }
91 EXPORT_SYMBOL_GPL(gb_connection_pop_timestamp);
92
93 static ssize_t state_show(struct device *dev, struct device_attribute *attr,
94                           char *buf)
95 {
96         struct gb_connection *connection = to_gb_connection(dev);
97         enum gb_connection_state state;
98
99         spin_lock_irq(&connection->lock);
100         state = connection->state;
101         spin_unlock_irq(&connection->lock);
102
103         return sprintf(buf, "%d\n", state);
104 }
105 static DEVICE_ATTR_RO(state);
106
107 static ssize_t
108 protocol_id_show(struct device *dev, struct device_attribute *attr, char *buf)
109 {
110         struct gb_connection *connection = to_gb_connection(dev);
111
112         if (connection->protocol)
113                 return sprintf(buf, "%d\n", connection->protocol->id);
114         else
115                 return -EINVAL;
116 }
117 static DEVICE_ATTR_RO(protocol_id);
118
119 static struct attribute *connection_attrs[] = {
120         &dev_attr_state.attr,
121         &dev_attr_protocol_id.attr,
122         NULL,
123 };
124
125 ATTRIBUTE_GROUPS(connection);
126
127 static void gb_connection_release(struct device *dev)
128 {
129         struct gb_connection *connection = to_gb_connection(dev);
130
131         destroy_workqueue(connection->wq);
132         kfifo_free(&connection->ts_kfifo);
133         kfree(connection);
134 }
135
136 struct device_type greybus_connection_type = {
137         .name =         "greybus_connection",
138         .release =      gb_connection_release,
139 };
140
141
142 int svc_update_connection(struct gb_interface *intf,
143                           struct gb_connection *connection)
144 {
145         struct gb_bundle *bundle;
146
147         bundle = gb_bundle_create(intf, GB_SVC_BUNDLE_ID, GREYBUS_CLASS_SVC);
148         if (!bundle)
149                 return -EINVAL;
150
151         device_del(&connection->dev);
152         connection->bundle = bundle;
153         connection->dev.parent = &bundle->dev;
154         dev_set_name(&connection->dev, "%s:%d", dev_name(&bundle->dev),
155                      GB_SVC_CPORT_ID);
156
157         WARN_ON(device_add(&connection->dev));
158
159         spin_lock_irq(&gb_connections_lock);
160         list_add(&connection->bundle_links, &bundle->connections);
161         spin_unlock_irq(&gb_connections_lock);
162
163         return 0;
164 }
165
166 /*
167  * Set up a Greybus connection, representing the bidirectional link
168  * between a CPort on a (local) Greybus host device and a CPort on
169  * another Greybus module.
170  *
171  * A connection also maintains the state of operations sent over the
172  * connection.
173  *
174  * Returns a pointer to the new connection if successful, or a null
175  * pointer otherwise.
176  */
177 struct gb_connection *
178 gb_connection_create_range(struct greybus_host_device *hd,
179                            struct gb_bundle *bundle, struct device *parent,
180                            u16 cport_id, u8 protocol_id, u32 ida_start,
181                            u32 ida_end)
182 {
183         struct gb_connection *connection;
184         struct ida *id_map = &hd->cport_id_map;
185         int hd_cport_id;
186         int retval;
187         u8 major = 0;
188         u8 minor = 1;
189
190         /*
191          * If a manifest tries to reuse a cport, reject it.  We
192          * initialize connections serially so we don't need to worry
193          * about holding the connection lock.
194          */
195         if (bundle && gb_connection_intf_find(bundle->intf, cport_id)) {
196                 pr_err("duplicate interface cport id 0x%04hx\n", cport_id);
197                 return NULL;
198         }
199
200         hd_cport_id = ida_simple_get(id_map, ida_start, ida_end, GFP_KERNEL);
201         if (hd_cport_id < 0)
202                 return NULL;
203
204         connection = kzalloc(sizeof(*connection), GFP_KERNEL);
205         if (!connection)
206                 goto err_remove_ida;
207
208         connection->hd_cport_id = hd_cport_id;
209         connection->intf_cport_id = cport_id;
210         connection->hd = hd;
211
212         connection->protocol_id = protocol_id;
213         connection->major = major;
214         connection->minor = minor;
215
216         connection->bundle = bundle;
217         connection->state = GB_CONNECTION_STATE_DISABLED;
218
219         atomic_set(&connection->op_cycle, 0);
220         spin_lock_init(&connection->lock);
221         INIT_LIST_HEAD(&connection->operations);
222
223         connection->wq = alloc_workqueue("%s:%d", WQ_UNBOUND, 1,
224                                          dev_name(parent), cport_id);
225         if (!connection->wq)
226                 goto err_free_connection;
227
228         if (kfifo_alloc(&connection->ts_kfifo, GB_CONNECTION_TS_KFIFO_LEN,
229                         GFP_KERNEL))
230                 goto err_destroy_wq;
231
232         connection->dev.parent = parent;
233         connection->dev.bus = &greybus_bus_type;
234         connection->dev.type = &greybus_connection_type;
235         connection->dev.groups = connection_groups;
236         device_initialize(&connection->dev);
237         dev_set_name(&connection->dev, "%s:%d",
238                      dev_name(parent), cport_id);
239
240         retval = device_add(&connection->dev);
241         if (retval) {
242                 connection->hd_cport_id = CPORT_ID_BAD;
243                 put_device(&connection->dev);
244
245                 pr_err("failed to add connection device for cport 0x%04hx\n",
246                         cport_id);
247
248                 goto err_remove_ida;
249         }
250
251         spin_lock_irq(&gb_connections_lock);
252         list_add(&connection->hd_links, &hd->connections);
253
254         if (bundle)
255                 list_add(&connection->bundle_links, &bundle->connections);
256         else
257                 INIT_LIST_HEAD(&connection->bundle_links);
258
259         spin_unlock_irq(&gb_connections_lock);
260
261         if (hd_cport_id != GB_SVC_CPORT_ID) {
262                 gb_svc_connection_create(hd->svc,
263                                          hd->endo->ap_intf_id, hd_cport_id,
264                                          bundle->intf->interface_id, cport_id);
265         }
266
267         gb_connection_bind_protocol(connection);
268         if (!connection->protocol)
269                 dev_warn(&connection->dev,
270                          "protocol 0x%02hhx handler not found\n", protocol_id);
271
272         return connection;
273
274 err_destroy_wq:
275         destroy_workqueue(connection->wq);
276 err_free_connection:
277         kfree(connection);
278 err_remove_ida:
279         ida_simple_remove(id_map, hd_cport_id);
280
281         return NULL;
282 }
283
284 struct gb_connection *gb_connection_create(struct gb_bundle *bundle,
285                                 u16 cport_id, u8 protocol_id)
286 {
287         return gb_connection_create_range(bundle->intf->hd, bundle,
288                                           &bundle->dev, cport_id, protocol_id,
289                                           0, bundle->intf->hd->num_cports - 1);
290 }
291
292 /*
293  * Cancel all active operations on a connection.
294  *
295  * Should only be called during connection tear down.
296  */
297 static void gb_connection_cancel_operations(struct gb_connection *connection,
298                                                 int errno)
299 {
300         struct gb_operation *operation;
301
302         spin_lock_irq(&connection->lock);
303         while (!list_empty(&connection->operations)) {
304                 operation = list_last_entry(&connection->operations,
305                                                 struct gb_operation, links);
306                 gb_operation_get(operation);
307                 spin_unlock_irq(&connection->lock);
308
309                 if (gb_operation_is_incoming(operation))
310                         gb_operation_cancel_incoming(operation, errno);
311                 else
312                         gb_operation_cancel(operation, errno);
313
314                 gb_operation_put(operation);
315
316                 spin_lock_irq(&connection->lock);
317         }
318         spin_unlock_irq(&connection->lock);
319 }
320
321 /*
322  * Tear down a previously set up connection.
323  */
324 void gb_connection_destroy(struct gb_connection *connection)
325 {
326         struct ida *id_map;
327
328         if (WARN_ON(!connection))
329                 return;
330
331         spin_lock_irq(&gb_connections_lock);
332         list_del(&connection->bundle_links);
333         list_del(&connection->hd_links);
334         spin_unlock_irq(&gb_connections_lock);
335
336         if (connection->protocol)
337                 gb_protocol_put(connection->protocol);
338         connection->protocol = NULL;
339
340         id_map = &connection->hd->cport_id_map;
341         ida_simple_remove(id_map, connection->hd_cport_id);
342         connection->hd_cport_id = CPORT_ID_BAD;
343
344         device_unregister(&connection->dev);
345 }
346
347 static void gb_connection_disconnected(struct gb_connection *connection)
348 {
349         struct gb_control *control;
350         int cport_id = connection->intf_cport_id;
351         int ret;
352
353         /*
354          * Inform Interface about In-active CPorts. We don't need to do this
355          * operation for control cport.
356          */
357         if ((cport_id == GB_CONTROL_CPORT_ID) ||
358             (connection->hd_cport_id == GB_SVC_CPORT_ID))
359                 return;
360
361         control = connection->bundle->intf->control;
362
363         ret = gb_control_disconnected_operation(control, cport_id);
364         if (ret)
365                 dev_warn(&connection->dev,
366                         "Failed to disconnect CPort-%d (%d)\n", cport_id, ret);
367 }
368
369 static int gb_connection_init(struct gb_connection *connection)
370 {
371         int cport_id = connection->intf_cport_id;
372         int ret;
373
374         if (!connection->protocol) {
375                 dev_warn(&connection->dev, "init without protocol.\n");
376                 return 0;
377         }
378
379         /*
380          * Inform Interface about Active CPorts. We don't need to do this
381          * operation for control cport.
382          */
383         if (cport_id != GB_CONTROL_CPORT_ID &&
384             connection->hd_cport_id != GB_SVC_CPORT_ID) {
385                 struct gb_control *control = connection->bundle->intf->control;
386
387                 ret = gb_control_connected_operation(control, cport_id);
388                 if (ret) {
389                         dev_err(&connection->dev,
390                                 "Failed to connect CPort-%d (%d)\n",
391                                 cport_id, ret);
392                         return 0;
393                 }
394         }
395
396         /* Need to enable the connection to initialize it */
397         spin_lock_irq(&connection->lock);
398         connection->state = GB_CONNECTION_STATE_ENABLED;
399         spin_unlock_irq(&connection->lock);
400
401         /*
402          * Request protocol version supported by the module. We don't need to do
403          * this for SVC as that is initiated by the SVC.
404          */
405         if (connection->hd_cport_id != GB_SVC_CPORT_ID) {
406                 ret = gb_protocol_get_version(connection);
407                 if (ret) {
408                         dev_err(&connection->dev,
409                                 "Failed to get version CPort-%d (%d)\n",
410                                 cport_id, ret);
411                         goto disconnect;
412                 }
413         }
414
415         ret = connection->protocol->connection_init(connection);
416         if (!ret)
417                 return 0;
418
419 disconnect:
420         spin_lock_irq(&connection->lock);
421         connection->state = GB_CONNECTION_STATE_ERROR;
422         spin_unlock_irq(&connection->lock);
423
424         gb_connection_disconnected(connection);
425         return ret;
426 }
427
428 void gb_connection_exit(struct gb_connection *connection)
429 {
430         if (!connection->protocol) {
431                 dev_warn(&connection->dev, "exit without protocol.\n");
432                 return;
433         }
434
435         spin_lock_irq(&connection->lock);
436         if (connection->state != GB_CONNECTION_STATE_ENABLED) {
437                 spin_unlock_irq(&connection->lock);
438                 return;
439         }
440         connection->state = GB_CONNECTION_STATE_DESTROYING;
441         spin_unlock_irq(&connection->lock);
442
443         gb_connection_cancel_operations(connection, -ESHUTDOWN);
444
445         connection->protocol->connection_exit(connection);
446         gb_connection_disconnected(connection);
447 }
448
449 void gb_hd_connections_exit(struct greybus_host_device *hd)
450 {
451         struct gb_connection *connection;
452
453         list_for_each_entry(connection, &hd->connections, hd_links) {
454                 gb_connection_exit(connection);
455                 gb_connection_destroy(connection);
456         }
457 }
458
459 void gb_connection_bind_protocol(struct gb_connection *connection)
460 {
461         struct gb_protocol *protocol;
462
463         /* If we already have a protocol bound here, just return */
464         if (connection->protocol)
465                 return;
466
467         protocol = gb_protocol_get(connection->protocol_id,
468                                    connection->major,
469                                    connection->minor);
470         if (!protocol)
471                 return;
472         connection->protocol = protocol;
473
474         /*
475          * If we have a valid device_id for the interface block, then we have an
476          * active device, so bring up the connection at the same time.
477          */
478         if ((!connection->bundle &&
479              connection->hd_cport_id == GB_SVC_CPORT_ID) ||
480             connection->bundle->intf->device_id != GB_DEVICE_ID_BAD)
481                 gb_connection_init(connection);
482 }