greybus: Add flags to struct gb_protocol
[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         gb_connection_bind_protocol(connection);
262         if (!connection->protocol)
263                 dev_warn(&connection->dev,
264                          "protocol 0x%02hhx handler not found\n", protocol_id);
265
266         return connection;
267
268 err_destroy_wq:
269         destroy_workqueue(connection->wq);
270 err_free_connection:
271         kfree(connection);
272 err_remove_ida:
273         ida_simple_remove(id_map, hd_cport_id);
274
275         return NULL;
276 }
277
278 struct gb_connection *gb_connection_create(struct gb_bundle *bundle,
279                                 u16 cport_id, u8 protocol_id)
280 {
281         return gb_connection_create_range(bundle->intf->hd, bundle,
282                                           &bundle->dev, cport_id, protocol_id,
283                                           0, bundle->intf->hd->num_cports - 1);
284 }
285
286 /*
287  * Cancel all active operations on a connection.
288  *
289  * Should only be called during connection tear down.
290  */
291 static void gb_connection_cancel_operations(struct gb_connection *connection,
292                                                 int errno)
293 {
294         struct gb_operation *operation;
295
296         spin_lock_irq(&connection->lock);
297         while (!list_empty(&connection->operations)) {
298                 operation = list_last_entry(&connection->operations,
299                                                 struct gb_operation, links);
300                 gb_operation_get(operation);
301                 spin_unlock_irq(&connection->lock);
302
303                 if (gb_operation_is_incoming(operation))
304                         gb_operation_cancel_incoming(operation, errno);
305                 else
306                         gb_operation_cancel(operation, errno);
307
308                 gb_operation_put(operation);
309
310                 spin_lock_irq(&connection->lock);
311         }
312         spin_unlock_irq(&connection->lock);
313 }
314
315 static void
316 gb_connection_svc_connection_destroy(struct gb_connection *connection)
317 {
318         if (connection->protocol->flags & GB_PROTOCOL_SKIP_SVC_CONNECTION)
319                 return;
320
321         if (connection->hd->driver->connection_destroy)
322                 connection->hd->driver->connection_destroy(connection);
323
324         gb_svc_connection_destroy(connection->hd->svc,
325                                   connection->hd->endo->ap_intf_id,
326                                   connection->hd_cport_id,
327                                   connection->bundle->intf->interface_id,
328                                   connection->intf_cport_id);
329 }
330
331 static void gb_connection_disconnected(struct gb_connection *connection)
332 {
333         struct gb_control *control;
334         int cport_id = connection->intf_cport_id;
335         int ret;
336
337         /* Inform Interface about inactive CPorts */
338         if (connection->protocol->flags & GB_PROTOCOL_SKIP_CONTROL_DISCONNECTED)
339                 return;
340
341         control = connection->bundle->intf->control;
342
343         ret = gb_control_disconnected_operation(control, cport_id);
344         if (ret)
345                 dev_warn(&connection->dev,
346                         "Failed to disconnect CPort-%d (%d)\n", cport_id, ret);
347 }
348
349 static int gb_connection_init(struct gb_connection *connection)
350 {
351         int cport_id = connection->intf_cport_id;
352         struct greybus_host_device *hd = connection->hd;
353         struct gb_protocol *protocol = connection->protocol;
354         int ret;
355
356         /*
357          * Request the SVC to create a connection from AP's cport to interface's
358          * cport.
359          */
360         if (!(protocol->flags & GB_PROTOCOL_SKIP_SVC_CONNECTION)) {
361                 ret = gb_svc_connection_create(hd->svc,
362                                 hd->endo->ap_intf_id, connection->hd_cport_id,
363                                 connection->bundle->intf->interface_id,
364                                 cport_id);
365                 if (ret) {
366                         dev_err(&connection->dev,
367                                 "%s: Failed to create svc connection (%d)\n",
368                                 __func__, ret);
369                         return ret;
370                 }
371
372                 if (hd->driver->connection_create)
373                         hd->driver->connection_create(connection);
374         }
375         /* Inform Interface about active CPorts */
376         if (!(protocol->flags & GB_PROTOCOL_SKIP_CONTROL_CONNECTED)) {
377                 struct gb_control *control = connection->bundle->intf->control;
378
379                 ret = gb_control_connected_operation(control, cport_id);
380                 if (ret) {
381                         dev_err(&connection->dev,
382                                 "Failed to connect CPort-%d (%d)\n",
383                                 cport_id, ret);
384                         goto svc_destroy;
385                 }
386         }
387
388         /* Need to enable the connection to initialize it */
389         spin_lock_irq(&connection->lock);
390         connection->state = GB_CONNECTION_STATE_ENABLED;
391         spin_unlock_irq(&connection->lock);
392
393         /*
394          * Request protocol version supported by the module. We don't need to do
395          * this for SVC as that is initiated by the SVC.
396          */
397         if (!(protocol->flags & GB_PROTOCOL_SKIP_VERSION)) {
398                 ret = gb_protocol_get_version(connection);
399                 if (ret) {
400                         dev_err(&connection->dev,
401                                 "Failed to get version CPort-%d (%d)\n",
402                                 cport_id, ret);
403                         goto disconnect;
404                 }
405         }
406
407         ret = protocol->connection_init(connection);
408         if (!ret)
409                 return 0;
410
411 disconnect:
412         spin_lock_irq(&connection->lock);
413         connection->state = GB_CONNECTION_STATE_ERROR;
414         spin_unlock_irq(&connection->lock);
415
416         gb_connection_disconnected(connection);
417 svc_destroy:
418         gb_connection_svc_connection_destroy(connection);
419
420         return ret;
421 }
422
423 static void gb_connection_exit(struct gb_connection *connection)
424 {
425         if (!connection->protocol)
426                 return;
427
428         spin_lock_irq(&connection->lock);
429         if (connection->state != GB_CONNECTION_STATE_ENABLED) {
430                 spin_unlock_irq(&connection->lock);
431                 return;
432         }
433         connection->state = GB_CONNECTION_STATE_DESTROYING;
434         spin_unlock_irq(&connection->lock);
435
436         gb_connection_cancel_operations(connection, -ESHUTDOWN);
437
438         connection->protocol->connection_exit(connection);
439         gb_connection_disconnected(connection);
440         gb_connection_svc_connection_destroy(connection);
441 }
442
443 /*
444  * Tear down a previously set up connection.
445  */
446 void gb_connection_destroy(struct gb_connection *connection)
447 {
448         struct ida *id_map;
449
450         if (WARN_ON(!connection))
451                 return;
452
453         gb_connection_exit(connection);
454
455         spin_lock_irq(&gb_connections_lock);
456         list_del(&connection->bundle_links);
457         list_del(&connection->hd_links);
458         spin_unlock_irq(&gb_connections_lock);
459
460         if (connection->protocol)
461                 gb_protocol_put(connection->protocol);
462         connection->protocol = NULL;
463
464         id_map = &connection->hd->cport_id_map;
465         ida_simple_remove(id_map, connection->hd_cport_id);
466         connection->hd_cport_id = CPORT_ID_BAD;
467
468         device_unregister(&connection->dev);
469 }
470
471 void gb_hd_connections_exit(struct greybus_host_device *hd)
472 {
473         struct gb_connection *connection;
474
475         list_for_each_entry(connection, &hd->connections, hd_links)
476                 gb_connection_destroy(connection);
477 }
478
479 int gb_connection_bind_protocol(struct gb_connection *connection)
480 {
481         struct gb_protocol *protocol;
482         int ret;
483
484         /* If we already have a protocol bound here, just return */
485         if (connection->protocol)
486                 return 0;
487
488         protocol = gb_protocol_get(connection->protocol_id,
489                                    connection->major,
490                                    connection->minor);
491         if (!protocol)
492                 return 0;
493         connection->protocol = protocol;
494
495         /*
496          * If we have a valid device_id for the interface block, then we have an
497          * active device, so bring up the connection at the same time.
498          */
499         if ((!connection->bundle &&
500              protocol->flags & GB_PROTOCOL_NO_BUNDLE) ||
501             connection->bundle->intf->device_id != GB_DEVICE_ID_BAD) {
502                 ret = gb_connection_init(connection);
503                 if (ret) {
504                         gb_protocol_put(protocol);
505                         connection->protocol = NULL;
506                         return ret;
507                 }
508         }
509
510         return 0;
511 }