greybus: connection: clean up svc-connection creation
[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 ssize_t
120 ap_cport_id_show(struct device *dev, struct device_attribute *attr, char *buf)
121 {
122         struct gb_connection *connection = to_gb_connection(dev);
123         return sprintf(buf, "%hu\n", connection->hd_cport_id);
124 }
125 static DEVICE_ATTR_RO(ap_cport_id);
126
127 static struct attribute *connection_attrs[] = {
128         &dev_attr_state.attr,
129         &dev_attr_protocol_id.attr,
130         &dev_attr_ap_cport_id.attr,
131         NULL,
132 };
133
134 ATTRIBUTE_GROUPS(connection);
135
136 static void gb_connection_release(struct device *dev)
137 {
138         struct gb_connection *connection = to_gb_connection(dev);
139
140         destroy_workqueue(connection->wq);
141         kfifo_free(&connection->ts_kfifo);
142         kfree(connection);
143 }
144
145 struct device_type greybus_connection_type = {
146         .name =         "greybus_connection",
147         .release =      gb_connection_release,
148 };
149
150
151 int svc_update_connection(struct gb_interface *intf,
152                           struct gb_connection *connection)
153 {
154         struct gb_bundle *bundle;
155
156         bundle = gb_bundle_create(intf, GB_SVC_BUNDLE_ID, GREYBUS_CLASS_SVC);
157         if (!bundle)
158                 return -EINVAL;
159
160         device_del(&connection->dev);
161         connection->bundle = bundle;
162         connection->dev.parent = &bundle->dev;
163         dev_set_name(&connection->dev, "%s:%d", dev_name(&bundle->dev),
164                      GB_SVC_CPORT_ID);
165
166         WARN_ON(device_add(&connection->dev));
167
168         spin_lock_irq(&gb_connections_lock);
169         list_add(&connection->bundle_links, &bundle->connections);
170         spin_unlock_irq(&gb_connections_lock);
171
172         return 0;
173 }
174
175 /*
176  * Set up a Greybus connection, representing the bidirectional link
177  * between a CPort on a (local) Greybus host device and a CPort on
178  * another Greybus module.
179  *
180  * A connection also maintains the state of operations sent over the
181  * connection.
182  *
183  * Returns a pointer to the new connection if successful, or a null
184  * pointer otherwise.
185  */
186 struct gb_connection *
187 gb_connection_create_range(struct greybus_host_device *hd,
188                            struct gb_bundle *bundle, struct device *parent,
189                            u16 cport_id, u8 protocol_id, u32 ida_start,
190                            u32 ida_end)
191 {
192         struct gb_connection *connection;
193         struct ida *id_map = &hd->cport_id_map;
194         int hd_cport_id;
195         int retval;
196         u8 major = 0;
197         u8 minor = 1;
198
199         /*
200          * If a manifest tries to reuse a cport, reject it.  We
201          * initialize connections serially so we don't need to worry
202          * about holding the connection lock.
203          */
204         if (bundle && gb_connection_intf_find(bundle->intf, cport_id)) {
205                 pr_err("duplicate interface cport id 0x%04hx\n", cport_id);
206                 return NULL;
207         }
208
209         hd_cport_id = ida_simple_get(id_map, ida_start, ida_end, GFP_KERNEL);
210         if (hd_cport_id < 0)
211                 return NULL;
212
213         connection = kzalloc(sizeof(*connection), GFP_KERNEL);
214         if (!connection)
215                 goto err_remove_ida;
216
217         connection->hd_cport_id = hd_cport_id;
218         connection->intf_cport_id = cport_id;
219         connection->hd = hd;
220
221         connection->protocol_id = protocol_id;
222         connection->major = major;
223         connection->minor = minor;
224
225         connection->bundle = bundle;
226         connection->state = GB_CONNECTION_STATE_DISABLED;
227
228         atomic_set(&connection->op_cycle, 0);
229         spin_lock_init(&connection->lock);
230         INIT_LIST_HEAD(&connection->operations);
231
232         connection->wq = alloc_workqueue("%s:%d", WQ_UNBOUND, 1,
233                                          dev_name(parent), cport_id);
234         if (!connection->wq)
235                 goto err_free_connection;
236
237         if (kfifo_alloc(&connection->ts_kfifo, GB_CONNECTION_TS_KFIFO_LEN,
238                         GFP_KERNEL))
239                 goto err_destroy_wq;
240
241         connection->dev.parent = parent;
242         connection->dev.bus = &greybus_bus_type;
243         connection->dev.type = &greybus_connection_type;
244         connection->dev.groups = connection_groups;
245         device_initialize(&connection->dev);
246         dev_set_name(&connection->dev, "%s:%d",
247                      dev_name(parent), cport_id);
248
249         retval = device_add(&connection->dev);
250         if (retval) {
251                 connection->hd_cport_id = CPORT_ID_BAD;
252                 put_device(&connection->dev);
253
254                 pr_err("failed to add connection device for cport 0x%04hx\n",
255                         cport_id);
256
257                 goto err_remove_ida;
258         }
259
260         spin_lock_irq(&gb_connections_lock);
261         list_add(&connection->hd_links, &hd->connections);
262
263         if (bundle)
264                 list_add(&connection->bundle_links, &bundle->connections);
265         else
266                 INIT_LIST_HEAD(&connection->bundle_links);
267
268         spin_unlock_irq(&gb_connections_lock);
269
270         gb_connection_bind_protocol(connection);
271         if (!connection->protocol)
272                 dev_warn(&connection->dev,
273                          "protocol 0x%02hhx handler not found\n", protocol_id);
274
275         return connection;
276
277 err_destroy_wq:
278         destroy_workqueue(connection->wq);
279 err_free_connection:
280         kfree(connection);
281 err_remove_ida:
282         ida_simple_remove(id_map, hd_cport_id);
283
284         return NULL;
285 }
286
287 struct gb_connection *gb_connection_create(struct gb_bundle *bundle,
288                                 u16 cport_id, u8 protocol_id)
289 {
290         return gb_connection_create_range(bundle->intf->hd, bundle,
291                                           &bundle->dev, cport_id, protocol_id,
292                                           0, bundle->intf->hd->num_cports - 1);
293 }
294
295 /*
296  * Cancel all active operations on a connection.
297  *
298  * Should only be called during connection tear down.
299  */
300 static void gb_connection_cancel_operations(struct gb_connection *connection,
301                                                 int errno)
302 {
303         struct gb_operation *operation;
304
305         spin_lock_irq(&connection->lock);
306         while (!list_empty(&connection->operations)) {
307                 operation = list_last_entry(&connection->operations,
308                                                 struct gb_operation, links);
309                 gb_operation_get(operation);
310                 spin_unlock_irq(&connection->lock);
311
312                 if (gb_operation_is_incoming(operation))
313                         gb_operation_cancel_incoming(operation, errno);
314                 else
315                         gb_operation_cancel(operation, errno);
316
317                 gb_operation_put(operation);
318
319                 spin_lock_irq(&connection->lock);
320         }
321         spin_unlock_irq(&connection->lock);
322 }
323
324 /*
325  * Request the SVC to create a connection from AP's cport to interface's
326  * cport.
327  */
328 static int
329 gb_connection_svc_connection_create(struct gb_connection *connection)
330 {
331         struct greybus_host_device *hd = connection->hd;
332         struct gb_protocol *protocol = connection->protocol;
333         int ret;
334
335         if (protocol->flags & GB_PROTOCOL_SKIP_SVC_CONNECTION)
336                 return 0;
337
338         ret = gb_svc_connection_create(hd->svc,
339                         hd->endo->ap_intf_id,
340                         connection->hd_cport_id,
341                         connection->bundle->intf->interface_id,
342                         connection->intf_cport_id);
343         if (ret) {
344                 dev_err(&connection->dev,
345                                 "failed to create svc connection: %d\n", ret);
346                 return ret;
347         }
348
349         if (hd->driver->connection_create)
350                 hd->driver->connection_create(connection);
351
352         return 0;
353 }
354
355 static void
356 gb_connection_svc_connection_destroy(struct gb_connection *connection)
357 {
358         if (connection->protocol->flags & GB_PROTOCOL_SKIP_SVC_CONNECTION)
359                 return;
360
361         if (connection->hd->driver->connection_destroy)
362                 connection->hd->driver->connection_destroy(connection);
363
364         gb_svc_connection_destroy(connection->hd->svc,
365                                   connection->hd->endo->ap_intf_id,
366                                   connection->hd_cport_id,
367                                   connection->bundle->intf->interface_id,
368                                   connection->intf_cport_id);
369 }
370
371 static void gb_connection_disconnected(struct gb_connection *connection)
372 {
373         struct gb_control *control;
374         int cport_id = connection->intf_cport_id;
375         int ret;
376
377         /* Inform Interface about inactive CPorts */
378         if (connection->protocol->flags & GB_PROTOCOL_SKIP_CONTROL_DISCONNECTED)
379                 return;
380
381         control = connection->bundle->intf->control;
382
383         ret = gb_control_disconnected_operation(control, cport_id);
384         if (ret)
385                 dev_warn(&connection->dev,
386                         "Failed to disconnect CPort-%d (%d)\n", cport_id, ret);
387 }
388
389 static int gb_connection_init(struct gb_connection *connection)
390 {
391         int cport_id = connection->intf_cport_id;
392         struct gb_protocol *protocol = connection->protocol;
393         int ret;
394
395         ret = gb_connection_svc_connection_create(connection);
396         if (ret)
397                 return ret;
398
399         /* Inform Interface about active CPorts */
400         if (!(protocol->flags & GB_PROTOCOL_SKIP_CONTROL_CONNECTED)) {
401                 struct gb_control *control = connection->bundle->intf->control;
402
403                 ret = gb_control_connected_operation(control, cport_id);
404                 if (ret) {
405                         dev_err(&connection->dev,
406                                 "Failed to connect CPort-%d (%d)\n",
407                                 cport_id, ret);
408                         goto svc_destroy;
409                 }
410         }
411
412         /* Need to enable the connection to initialize it */
413         spin_lock_irq(&connection->lock);
414         connection->state = GB_CONNECTION_STATE_ENABLED;
415         spin_unlock_irq(&connection->lock);
416
417         /*
418          * Request protocol version supported by the module. We don't need to do
419          * this for SVC as that is initiated by the SVC.
420          */
421         if (!(protocol->flags & GB_PROTOCOL_SKIP_VERSION)) {
422                 ret = gb_protocol_get_version(connection);
423                 if (ret) {
424                         dev_err(&connection->dev,
425                                 "Failed to get version CPort-%d (%d)\n",
426                                 cport_id, ret);
427                         goto disconnect;
428                 }
429         }
430
431         ret = protocol->connection_init(connection);
432         if (!ret)
433                 return 0;
434
435 disconnect:
436         spin_lock_irq(&connection->lock);
437         connection->state = GB_CONNECTION_STATE_ERROR;
438         spin_unlock_irq(&connection->lock);
439
440         gb_connection_disconnected(connection);
441 svc_destroy:
442         gb_connection_svc_connection_destroy(connection);
443
444         return ret;
445 }
446
447 static void gb_connection_exit(struct gb_connection *connection)
448 {
449         if (!connection->protocol)
450                 return;
451
452         spin_lock_irq(&connection->lock);
453         if (connection->state != GB_CONNECTION_STATE_ENABLED) {
454                 spin_unlock_irq(&connection->lock);
455                 return;
456         }
457         connection->state = GB_CONNECTION_STATE_DESTROYING;
458         spin_unlock_irq(&connection->lock);
459
460         gb_connection_cancel_operations(connection, -ESHUTDOWN);
461
462         connection->protocol->connection_exit(connection);
463         gb_connection_disconnected(connection);
464         gb_connection_svc_connection_destroy(connection);
465 }
466
467 /*
468  * Tear down a previously set up connection.
469  */
470 void gb_connection_destroy(struct gb_connection *connection)
471 {
472         struct ida *id_map;
473
474         if (WARN_ON(!connection))
475                 return;
476
477         gb_connection_exit(connection);
478
479         spin_lock_irq(&gb_connections_lock);
480         list_del(&connection->bundle_links);
481         list_del(&connection->hd_links);
482         spin_unlock_irq(&gb_connections_lock);
483
484         if (connection->protocol)
485                 gb_protocol_put(connection->protocol);
486         connection->protocol = NULL;
487
488         id_map = &connection->hd->cport_id_map;
489         ida_simple_remove(id_map, connection->hd_cport_id);
490         connection->hd_cport_id = CPORT_ID_BAD;
491
492         device_unregister(&connection->dev);
493 }
494
495 void gb_hd_connections_exit(struct greybus_host_device *hd)
496 {
497         struct gb_connection *connection;
498
499         list_for_each_entry(connection, &hd->connections, hd_links)
500                 gb_connection_destroy(connection);
501 }
502
503 int gb_connection_bind_protocol(struct gb_connection *connection)
504 {
505         struct gb_protocol *protocol;
506         int ret;
507
508         /* If we already have a protocol bound here, just return */
509         if (connection->protocol)
510                 return 0;
511
512         protocol = gb_protocol_get(connection->protocol_id,
513                                    connection->major,
514                                    connection->minor);
515         if (!protocol)
516                 return 0;
517         connection->protocol = protocol;
518
519         /*
520          * If we have a valid device_id for the interface block, then we have an
521          * active device, so bring up the connection at the same time.
522          */
523         if ((!connection->bundle &&
524              protocol->flags & GB_PROTOCOL_NO_BUNDLE) ||
525             connection->bundle->intf->device_id != GB_DEVICE_ID_BAD) {
526                 ret = gb_connection_init(connection);
527                 if (ret) {
528                         gb_protocol_put(protocol);
529                         connection->protocol = NULL;
530                         return ret;
531                 }
532         }
533
534         return 0;
535 }