xref: /openbmc/linux/drivers/greybus/connection.c (revision 55fd7e02)
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Greybus connections
4  *
5  * Copyright 2014 Google Inc.
6  * Copyright 2014 Linaro Ltd.
7  */
8 
9 #include <linux/workqueue.h>
10 #include <linux/greybus.h>
11 
12 #include "greybus_trace.h"
13 
14 #define GB_CONNECTION_CPORT_QUIESCE_TIMEOUT	1000
15 
16 static void gb_connection_kref_release(struct kref *kref);
17 
18 static DEFINE_SPINLOCK(gb_connections_lock);
19 static DEFINE_MUTEX(gb_connection_mutex);
20 
21 /* Caller holds gb_connection_mutex. */
22 static bool gb_connection_cport_in_use(struct gb_interface *intf, u16 cport_id)
23 {
24 	struct gb_host_device *hd = intf->hd;
25 	struct gb_connection *connection;
26 
27 	list_for_each_entry(connection, &hd->connections, hd_links) {
28 		if (connection->intf == intf &&
29 		    connection->intf_cport_id == cport_id)
30 			return true;
31 	}
32 
33 	return false;
34 }
35 
36 static void gb_connection_get(struct gb_connection *connection)
37 {
38 	kref_get(&connection->kref);
39 
40 	trace_gb_connection_get(connection);
41 }
42 
43 static void gb_connection_put(struct gb_connection *connection)
44 {
45 	trace_gb_connection_put(connection);
46 
47 	kref_put(&connection->kref, gb_connection_kref_release);
48 }
49 
50 /*
51  * Returns a reference-counted pointer to the connection if found.
52  */
53 static struct gb_connection *
54 gb_connection_hd_find(struct gb_host_device *hd, u16 cport_id)
55 {
56 	struct gb_connection *connection;
57 	unsigned long flags;
58 
59 	spin_lock_irqsave(&gb_connections_lock, flags);
60 	list_for_each_entry(connection, &hd->connections, hd_links)
61 		if (connection->hd_cport_id == cport_id) {
62 			gb_connection_get(connection);
63 			goto found;
64 		}
65 	connection = NULL;
66 found:
67 	spin_unlock_irqrestore(&gb_connections_lock, flags);
68 
69 	return connection;
70 }
71 
72 /*
73  * Callback from the host driver to let us know that data has been
74  * received on the bundle.
75  */
76 void greybus_data_rcvd(struct gb_host_device *hd, u16 cport_id,
77 		       u8 *data, size_t length)
78 {
79 	struct gb_connection *connection;
80 
81 	trace_gb_hd_in(hd);
82 
83 	connection = gb_connection_hd_find(hd, cport_id);
84 	if (!connection) {
85 		dev_err(&hd->dev,
86 			"nonexistent connection (%zu bytes dropped)\n", length);
87 		return;
88 	}
89 	gb_connection_recv(connection, data, length);
90 	gb_connection_put(connection);
91 }
92 EXPORT_SYMBOL_GPL(greybus_data_rcvd);
93 
94 static void gb_connection_kref_release(struct kref *kref)
95 {
96 	struct gb_connection *connection;
97 
98 	connection = container_of(kref, struct gb_connection, kref);
99 
100 	trace_gb_connection_release(connection);
101 
102 	kfree(connection);
103 }
104 
105 static void gb_connection_init_name(struct gb_connection *connection)
106 {
107 	u16 hd_cport_id = connection->hd_cport_id;
108 	u16 cport_id = 0;
109 	u8 intf_id = 0;
110 
111 	if (connection->intf) {
112 		intf_id = connection->intf->interface_id;
113 		cport_id = connection->intf_cport_id;
114 	}
115 
116 	snprintf(connection->name, sizeof(connection->name),
117 		 "%u/%u:%u", hd_cport_id, intf_id, cport_id);
118 }
119 
120 /*
121  * _gb_connection_create() - create a Greybus connection
122  * @hd:			host device of the connection
123  * @hd_cport_id:	host-device cport id, or -1 for dynamic allocation
124  * @intf:		remote interface, or NULL for static connections
125  * @bundle:		remote-interface bundle (may be NULL)
126  * @cport_id:		remote-interface cport id, or 0 for static connections
127  * @handler:		request handler (may be NULL)
128  * @flags:		connection flags
129  *
130  * Create a Greybus connection, representing the bidirectional link
131  * between a CPort on a (local) Greybus host device and a CPort on
132  * another Greybus interface.
133  *
134  * A connection also maintains the state of operations sent over the
135  * connection.
136  *
137  * Serialised against concurrent create and destroy using the
138  * gb_connection_mutex.
139  *
140  * Return: A pointer to the new connection if successful, or an ERR_PTR
141  * otherwise.
142  */
143 static struct gb_connection *
144 _gb_connection_create(struct gb_host_device *hd, int hd_cport_id,
145 		      struct gb_interface *intf,
146 		      struct gb_bundle *bundle, int cport_id,
147 		      gb_request_handler_t handler,
148 		      unsigned long flags)
149 {
150 	struct gb_connection *connection;
151 	int ret;
152 
153 	mutex_lock(&gb_connection_mutex);
154 
155 	if (intf && gb_connection_cport_in_use(intf, cport_id)) {
156 		dev_err(&intf->dev, "cport %u already in use\n", cport_id);
157 		ret = -EBUSY;
158 		goto err_unlock;
159 	}
160 
161 	ret = gb_hd_cport_allocate(hd, hd_cport_id, flags);
162 	if (ret < 0) {
163 		dev_err(&hd->dev, "failed to allocate cport: %d\n", ret);
164 		goto err_unlock;
165 	}
166 	hd_cport_id = ret;
167 
168 	connection = kzalloc(sizeof(*connection), GFP_KERNEL);
169 	if (!connection) {
170 		ret = -ENOMEM;
171 		goto err_hd_cport_release;
172 	}
173 
174 	connection->hd_cport_id = hd_cport_id;
175 	connection->intf_cport_id = cport_id;
176 	connection->hd = hd;
177 	connection->intf = intf;
178 	connection->bundle = bundle;
179 	connection->handler = handler;
180 	connection->flags = flags;
181 	if (intf && (intf->quirks & GB_INTERFACE_QUIRK_NO_CPORT_FEATURES))
182 		connection->flags |= GB_CONNECTION_FLAG_NO_FLOWCTRL;
183 	connection->state = GB_CONNECTION_STATE_DISABLED;
184 
185 	atomic_set(&connection->op_cycle, 0);
186 	mutex_init(&connection->mutex);
187 	spin_lock_init(&connection->lock);
188 	INIT_LIST_HEAD(&connection->operations);
189 
190 	connection->wq = alloc_workqueue("%s:%d", WQ_UNBOUND, 1,
191 					 dev_name(&hd->dev), hd_cport_id);
192 	if (!connection->wq) {
193 		ret = -ENOMEM;
194 		goto err_free_connection;
195 	}
196 
197 	kref_init(&connection->kref);
198 
199 	gb_connection_init_name(connection);
200 
201 	spin_lock_irq(&gb_connections_lock);
202 	list_add(&connection->hd_links, &hd->connections);
203 
204 	if (bundle)
205 		list_add(&connection->bundle_links, &bundle->connections);
206 	else
207 		INIT_LIST_HEAD(&connection->bundle_links);
208 
209 	spin_unlock_irq(&gb_connections_lock);
210 
211 	mutex_unlock(&gb_connection_mutex);
212 
213 	trace_gb_connection_create(connection);
214 
215 	return connection;
216 
217 err_free_connection:
218 	kfree(connection);
219 err_hd_cport_release:
220 	gb_hd_cport_release(hd, hd_cport_id);
221 err_unlock:
222 	mutex_unlock(&gb_connection_mutex);
223 
224 	return ERR_PTR(ret);
225 }
226 
227 struct gb_connection *
228 gb_connection_create_static(struct gb_host_device *hd, u16 hd_cport_id,
229 			    gb_request_handler_t handler)
230 {
231 	return _gb_connection_create(hd, hd_cport_id, NULL, NULL, 0, handler,
232 				     GB_CONNECTION_FLAG_HIGH_PRIO);
233 }
234 
235 struct gb_connection *
236 gb_connection_create_control(struct gb_interface *intf)
237 {
238 	return _gb_connection_create(intf->hd, -1, intf, NULL, 0, NULL,
239 				     GB_CONNECTION_FLAG_CONTROL |
240 				     GB_CONNECTION_FLAG_HIGH_PRIO);
241 }
242 
243 struct gb_connection *
244 gb_connection_create(struct gb_bundle *bundle, u16 cport_id,
245 		     gb_request_handler_t handler)
246 {
247 	struct gb_interface *intf = bundle->intf;
248 
249 	return _gb_connection_create(intf->hd, -1, intf, bundle, cport_id,
250 				     handler, 0);
251 }
252 EXPORT_SYMBOL_GPL(gb_connection_create);
253 
254 struct gb_connection *
255 gb_connection_create_flags(struct gb_bundle *bundle, u16 cport_id,
256 			   gb_request_handler_t handler,
257 			   unsigned long flags)
258 {
259 	struct gb_interface *intf = bundle->intf;
260 
261 	if (WARN_ON_ONCE(flags & GB_CONNECTION_FLAG_CORE_MASK))
262 		flags &= ~GB_CONNECTION_FLAG_CORE_MASK;
263 
264 	return _gb_connection_create(intf->hd, -1, intf, bundle, cport_id,
265 				     handler, flags);
266 }
267 EXPORT_SYMBOL_GPL(gb_connection_create_flags);
268 
269 struct gb_connection *
270 gb_connection_create_offloaded(struct gb_bundle *bundle, u16 cport_id,
271 			       unsigned long flags)
272 {
273 	flags |= GB_CONNECTION_FLAG_OFFLOADED;
274 
275 	return gb_connection_create_flags(bundle, cport_id, NULL, flags);
276 }
277 EXPORT_SYMBOL_GPL(gb_connection_create_offloaded);
278 
279 static int gb_connection_hd_cport_enable(struct gb_connection *connection)
280 {
281 	struct gb_host_device *hd = connection->hd;
282 	int ret;
283 
284 	if (!hd->driver->cport_enable)
285 		return 0;
286 
287 	ret = hd->driver->cport_enable(hd, connection->hd_cport_id,
288 				       connection->flags);
289 	if (ret) {
290 		dev_err(&hd->dev, "%s: failed to enable host cport: %d\n",
291 			connection->name, ret);
292 		return ret;
293 	}
294 
295 	return 0;
296 }
297 
298 static void gb_connection_hd_cport_disable(struct gb_connection *connection)
299 {
300 	struct gb_host_device *hd = connection->hd;
301 	int ret;
302 
303 	if (!hd->driver->cport_disable)
304 		return;
305 
306 	ret = hd->driver->cport_disable(hd, connection->hd_cport_id);
307 	if (ret) {
308 		dev_err(&hd->dev, "%s: failed to disable host cport: %d\n",
309 			connection->name, ret);
310 	}
311 }
312 
313 static int gb_connection_hd_cport_connected(struct gb_connection *connection)
314 {
315 	struct gb_host_device *hd = connection->hd;
316 	int ret;
317 
318 	if (!hd->driver->cport_connected)
319 		return 0;
320 
321 	ret = hd->driver->cport_connected(hd, connection->hd_cport_id);
322 	if (ret) {
323 		dev_err(&hd->dev, "%s: failed to set connected state: %d\n",
324 			connection->name, ret);
325 		return ret;
326 	}
327 
328 	return 0;
329 }
330 
331 static int gb_connection_hd_cport_flush(struct gb_connection *connection)
332 {
333 	struct gb_host_device *hd = connection->hd;
334 	int ret;
335 
336 	if (!hd->driver->cport_flush)
337 		return 0;
338 
339 	ret = hd->driver->cport_flush(hd, connection->hd_cport_id);
340 	if (ret) {
341 		dev_err(&hd->dev, "%s: failed to flush host cport: %d\n",
342 			connection->name, ret);
343 		return ret;
344 	}
345 
346 	return 0;
347 }
348 
349 static int gb_connection_hd_cport_quiesce(struct gb_connection *connection)
350 {
351 	struct gb_host_device *hd = connection->hd;
352 	size_t peer_space;
353 	int ret;
354 
355 	if (!hd->driver->cport_quiesce)
356 		return 0;
357 
358 	peer_space = sizeof(struct gb_operation_msg_hdr) +
359 			sizeof(struct gb_cport_shutdown_request);
360 
361 	if (connection->mode_switch)
362 		peer_space += sizeof(struct gb_operation_msg_hdr);
363 
364 	ret = hd->driver->cport_quiesce(hd, connection->hd_cport_id,
365 					peer_space,
366 					GB_CONNECTION_CPORT_QUIESCE_TIMEOUT);
367 	if (ret) {
368 		dev_err(&hd->dev, "%s: failed to quiesce host cport: %d\n",
369 			connection->name, ret);
370 		return ret;
371 	}
372 
373 	return 0;
374 }
375 
376 static int gb_connection_hd_cport_clear(struct gb_connection *connection)
377 {
378 	struct gb_host_device *hd = connection->hd;
379 	int ret;
380 
381 	if (!hd->driver->cport_clear)
382 		return 0;
383 
384 	ret = hd->driver->cport_clear(hd, connection->hd_cport_id);
385 	if (ret) {
386 		dev_err(&hd->dev, "%s: failed to clear host cport: %d\n",
387 			connection->name, ret);
388 		return ret;
389 	}
390 
391 	return 0;
392 }
393 
394 /*
395  * Request the SVC to create a connection from AP's cport to interface's
396  * cport.
397  */
398 static int
399 gb_connection_svc_connection_create(struct gb_connection *connection)
400 {
401 	struct gb_host_device *hd = connection->hd;
402 	struct gb_interface *intf;
403 	u8 cport_flags;
404 	int ret;
405 
406 	if (gb_connection_is_static(connection))
407 		return 0;
408 
409 	intf = connection->intf;
410 
411 	/*
412 	 * Enable either E2EFC or CSD, unless no flow control is requested.
413 	 */
414 	cport_flags = GB_SVC_CPORT_FLAG_CSV_N;
415 	if (gb_connection_flow_control_disabled(connection)) {
416 		cport_flags |= GB_SVC_CPORT_FLAG_CSD_N;
417 	} else if (gb_connection_e2efc_enabled(connection)) {
418 		cport_flags |= GB_SVC_CPORT_FLAG_CSD_N |
419 				GB_SVC_CPORT_FLAG_E2EFC;
420 	}
421 
422 	ret = gb_svc_connection_create(hd->svc,
423 				       hd->svc->ap_intf_id,
424 				       connection->hd_cport_id,
425 				       intf->interface_id,
426 				       connection->intf_cport_id,
427 				       cport_flags);
428 	if (ret) {
429 		dev_err(&connection->hd->dev,
430 			"%s: failed to create svc connection: %d\n",
431 			connection->name, ret);
432 		return ret;
433 	}
434 
435 	return 0;
436 }
437 
438 static void
439 gb_connection_svc_connection_destroy(struct gb_connection *connection)
440 {
441 	if (gb_connection_is_static(connection))
442 		return;
443 
444 	gb_svc_connection_destroy(connection->hd->svc,
445 				  connection->hd->svc->ap_intf_id,
446 				  connection->hd_cport_id,
447 				  connection->intf->interface_id,
448 				  connection->intf_cport_id);
449 }
450 
451 /* Inform Interface about active CPorts */
452 static int gb_connection_control_connected(struct gb_connection *connection)
453 {
454 	struct gb_control *control;
455 	u16 cport_id = connection->intf_cport_id;
456 	int ret;
457 
458 	if (gb_connection_is_static(connection))
459 		return 0;
460 
461 	if (gb_connection_is_control(connection))
462 		return 0;
463 
464 	control = connection->intf->control;
465 
466 	ret = gb_control_connected_operation(control, cport_id);
467 	if (ret) {
468 		dev_err(&connection->bundle->dev,
469 			"failed to connect cport: %d\n", ret);
470 		return ret;
471 	}
472 
473 	return 0;
474 }
475 
476 static void
477 gb_connection_control_disconnecting(struct gb_connection *connection)
478 {
479 	struct gb_control *control;
480 	u16 cport_id = connection->intf_cport_id;
481 	int ret;
482 
483 	if (gb_connection_is_static(connection))
484 		return;
485 
486 	control = connection->intf->control;
487 
488 	ret = gb_control_disconnecting_operation(control, cport_id);
489 	if (ret) {
490 		dev_err(&connection->hd->dev,
491 			"%s: failed to send disconnecting: %d\n",
492 			connection->name, ret);
493 	}
494 }
495 
496 static void
497 gb_connection_control_disconnected(struct gb_connection *connection)
498 {
499 	struct gb_control *control;
500 	u16 cport_id = connection->intf_cport_id;
501 	int ret;
502 
503 	if (gb_connection_is_static(connection))
504 		return;
505 
506 	control = connection->intf->control;
507 
508 	if (gb_connection_is_control(connection)) {
509 		if (connection->mode_switch) {
510 			ret = gb_control_mode_switch_operation(control);
511 			if (ret) {
512 				/*
513 				 * Allow mode switch to time out waiting for
514 				 * mailbox event.
515 				 */
516 				return;
517 			}
518 		}
519 
520 		return;
521 	}
522 
523 	ret = gb_control_disconnected_operation(control, cport_id);
524 	if (ret) {
525 		dev_warn(&connection->bundle->dev,
526 			 "failed to disconnect cport: %d\n", ret);
527 	}
528 }
529 
530 static int gb_connection_shutdown_operation(struct gb_connection *connection,
531 					    u8 phase)
532 {
533 	struct gb_cport_shutdown_request *req;
534 	struct gb_operation *operation;
535 	int ret;
536 
537 	operation = gb_operation_create_core(connection,
538 					     GB_REQUEST_TYPE_CPORT_SHUTDOWN,
539 					     sizeof(*req), 0, 0,
540 					     GFP_KERNEL);
541 	if (!operation)
542 		return -ENOMEM;
543 
544 	req = operation->request->payload;
545 	req->phase = phase;
546 
547 	ret = gb_operation_request_send_sync(operation);
548 
549 	gb_operation_put(operation);
550 
551 	return ret;
552 }
553 
554 static int gb_connection_cport_shutdown(struct gb_connection *connection,
555 					u8 phase)
556 {
557 	struct gb_host_device *hd = connection->hd;
558 	const struct gb_hd_driver *drv = hd->driver;
559 	int ret;
560 
561 	if (gb_connection_is_static(connection))
562 		return 0;
563 
564 	if (gb_connection_is_offloaded(connection)) {
565 		if (!drv->cport_shutdown)
566 			return 0;
567 
568 		ret = drv->cport_shutdown(hd, connection->hd_cport_id, phase,
569 					  GB_OPERATION_TIMEOUT_DEFAULT);
570 	} else {
571 		ret = gb_connection_shutdown_operation(connection, phase);
572 	}
573 
574 	if (ret) {
575 		dev_err(&hd->dev, "%s: failed to send cport shutdown (phase %d): %d\n",
576 			connection->name, phase, ret);
577 		return ret;
578 	}
579 
580 	return 0;
581 }
582 
583 static int
584 gb_connection_cport_shutdown_phase_1(struct gb_connection *connection)
585 {
586 	return gb_connection_cport_shutdown(connection, 1);
587 }
588 
589 static int
590 gb_connection_cport_shutdown_phase_2(struct gb_connection *connection)
591 {
592 	return gb_connection_cport_shutdown(connection, 2);
593 }
594 
595 /*
596  * Cancel all active operations on a connection.
597  *
598  * Locking: Called with connection lock held and state set to DISABLED or
599  * DISCONNECTING.
600  */
601 static void gb_connection_cancel_operations(struct gb_connection *connection,
602 					    int errno)
603 	__must_hold(&connection->lock)
604 {
605 	struct gb_operation *operation;
606 
607 	while (!list_empty(&connection->operations)) {
608 		operation = list_last_entry(&connection->operations,
609 					    struct gb_operation, links);
610 		gb_operation_get(operation);
611 		spin_unlock_irq(&connection->lock);
612 
613 		if (gb_operation_is_incoming(operation))
614 			gb_operation_cancel_incoming(operation, errno);
615 		else
616 			gb_operation_cancel(operation, errno);
617 
618 		gb_operation_put(operation);
619 
620 		spin_lock_irq(&connection->lock);
621 	}
622 }
623 
624 /*
625  * Cancel all active incoming operations on a connection.
626  *
627  * Locking: Called with connection lock held and state set to ENABLED_TX.
628  */
629 static void
630 gb_connection_flush_incoming_operations(struct gb_connection *connection,
631 					int errno)
632 	__must_hold(&connection->lock)
633 {
634 	struct gb_operation *operation;
635 	bool incoming;
636 
637 	while (!list_empty(&connection->operations)) {
638 		incoming = false;
639 		list_for_each_entry(operation, &connection->operations,
640 				    links) {
641 			if (gb_operation_is_incoming(operation)) {
642 				gb_operation_get(operation);
643 				incoming = true;
644 				break;
645 			}
646 		}
647 
648 		if (!incoming)
649 			break;
650 
651 		spin_unlock_irq(&connection->lock);
652 
653 		/* FIXME: flush, not cancel? */
654 		gb_operation_cancel_incoming(operation, errno);
655 		gb_operation_put(operation);
656 
657 		spin_lock_irq(&connection->lock);
658 	}
659 }
660 
661 /*
662  * _gb_connection_enable() - enable a connection
663  * @connection:		connection to enable
664  * @rx:			whether to enable incoming requests
665  *
666  * Connection-enable helper for DISABLED->ENABLED, DISABLED->ENABLED_TX, and
667  * ENABLED_TX->ENABLED state transitions.
668  *
669  * Locking: Caller holds connection->mutex.
670  */
671 static int _gb_connection_enable(struct gb_connection *connection, bool rx)
672 {
673 	int ret;
674 
675 	/* Handle ENABLED_TX -> ENABLED transitions. */
676 	if (connection->state == GB_CONNECTION_STATE_ENABLED_TX) {
677 		if (!(connection->handler && rx))
678 			return 0;
679 
680 		spin_lock_irq(&connection->lock);
681 		connection->state = GB_CONNECTION_STATE_ENABLED;
682 		spin_unlock_irq(&connection->lock);
683 
684 		return 0;
685 	}
686 
687 	ret = gb_connection_hd_cport_enable(connection);
688 	if (ret)
689 		return ret;
690 
691 	ret = gb_connection_svc_connection_create(connection);
692 	if (ret)
693 		goto err_hd_cport_clear;
694 
695 	ret = gb_connection_hd_cport_connected(connection);
696 	if (ret)
697 		goto err_svc_connection_destroy;
698 
699 	spin_lock_irq(&connection->lock);
700 	if (connection->handler && rx)
701 		connection->state = GB_CONNECTION_STATE_ENABLED;
702 	else
703 		connection->state = GB_CONNECTION_STATE_ENABLED_TX;
704 	spin_unlock_irq(&connection->lock);
705 
706 	ret = gb_connection_control_connected(connection);
707 	if (ret)
708 		goto err_control_disconnecting;
709 
710 	return 0;
711 
712 err_control_disconnecting:
713 	spin_lock_irq(&connection->lock);
714 	connection->state = GB_CONNECTION_STATE_DISCONNECTING;
715 	gb_connection_cancel_operations(connection, -ESHUTDOWN);
716 	spin_unlock_irq(&connection->lock);
717 
718 	/* Transmit queue should already be empty. */
719 	gb_connection_hd_cport_flush(connection);
720 
721 	gb_connection_control_disconnecting(connection);
722 	gb_connection_cport_shutdown_phase_1(connection);
723 	gb_connection_hd_cport_quiesce(connection);
724 	gb_connection_cport_shutdown_phase_2(connection);
725 	gb_connection_control_disconnected(connection);
726 	connection->state = GB_CONNECTION_STATE_DISABLED;
727 err_svc_connection_destroy:
728 	gb_connection_svc_connection_destroy(connection);
729 err_hd_cport_clear:
730 	gb_connection_hd_cport_clear(connection);
731 
732 	gb_connection_hd_cport_disable(connection);
733 
734 	return ret;
735 }
736 
737 int gb_connection_enable(struct gb_connection *connection)
738 {
739 	int ret = 0;
740 
741 	mutex_lock(&connection->mutex);
742 
743 	if (connection->state == GB_CONNECTION_STATE_ENABLED)
744 		goto out_unlock;
745 
746 	ret = _gb_connection_enable(connection, true);
747 	if (!ret)
748 		trace_gb_connection_enable(connection);
749 
750 out_unlock:
751 	mutex_unlock(&connection->mutex);
752 
753 	return ret;
754 }
755 EXPORT_SYMBOL_GPL(gb_connection_enable);
756 
757 int gb_connection_enable_tx(struct gb_connection *connection)
758 {
759 	int ret = 0;
760 
761 	mutex_lock(&connection->mutex);
762 
763 	if (connection->state == GB_CONNECTION_STATE_ENABLED) {
764 		ret = -EINVAL;
765 		goto out_unlock;
766 	}
767 
768 	if (connection->state == GB_CONNECTION_STATE_ENABLED_TX)
769 		goto out_unlock;
770 
771 	ret = _gb_connection_enable(connection, false);
772 	if (!ret)
773 		trace_gb_connection_enable(connection);
774 
775 out_unlock:
776 	mutex_unlock(&connection->mutex);
777 
778 	return ret;
779 }
780 EXPORT_SYMBOL_GPL(gb_connection_enable_tx);
781 
782 void gb_connection_disable_rx(struct gb_connection *connection)
783 {
784 	mutex_lock(&connection->mutex);
785 
786 	spin_lock_irq(&connection->lock);
787 	if (connection->state != GB_CONNECTION_STATE_ENABLED) {
788 		spin_unlock_irq(&connection->lock);
789 		goto out_unlock;
790 	}
791 	connection->state = GB_CONNECTION_STATE_ENABLED_TX;
792 	gb_connection_flush_incoming_operations(connection, -ESHUTDOWN);
793 	spin_unlock_irq(&connection->lock);
794 
795 	trace_gb_connection_disable(connection);
796 
797 out_unlock:
798 	mutex_unlock(&connection->mutex);
799 }
800 EXPORT_SYMBOL_GPL(gb_connection_disable_rx);
801 
802 void gb_connection_mode_switch_prepare(struct gb_connection *connection)
803 {
804 	connection->mode_switch = true;
805 }
806 
807 void gb_connection_mode_switch_complete(struct gb_connection *connection)
808 {
809 	gb_connection_svc_connection_destroy(connection);
810 	gb_connection_hd_cport_clear(connection);
811 
812 	gb_connection_hd_cport_disable(connection);
813 
814 	connection->mode_switch = false;
815 }
816 
817 void gb_connection_disable(struct gb_connection *connection)
818 {
819 	mutex_lock(&connection->mutex);
820 
821 	if (connection->state == GB_CONNECTION_STATE_DISABLED)
822 		goto out_unlock;
823 
824 	trace_gb_connection_disable(connection);
825 
826 	spin_lock_irq(&connection->lock);
827 	connection->state = GB_CONNECTION_STATE_DISCONNECTING;
828 	gb_connection_cancel_operations(connection, -ESHUTDOWN);
829 	spin_unlock_irq(&connection->lock);
830 
831 	gb_connection_hd_cport_flush(connection);
832 
833 	gb_connection_control_disconnecting(connection);
834 	gb_connection_cport_shutdown_phase_1(connection);
835 	gb_connection_hd_cport_quiesce(connection);
836 	gb_connection_cport_shutdown_phase_2(connection);
837 	gb_connection_control_disconnected(connection);
838 
839 	connection->state = GB_CONNECTION_STATE_DISABLED;
840 
841 	/* control-connection tear down is deferred when mode switching */
842 	if (!connection->mode_switch) {
843 		gb_connection_svc_connection_destroy(connection);
844 		gb_connection_hd_cport_clear(connection);
845 
846 		gb_connection_hd_cport_disable(connection);
847 	}
848 
849 out_unlock:
850 	mutex_unlock(&connection->mutex);
851 }
852 EXPORT_SYMBOL_GPL(gb_connection_disable);
853 
854 /* Disable a connection without communicating with the remote end. */
855 void gb_connection_disable_forced(struct gb_connection *connection)
856 {
857 	mutex_lock(&connection->mutex);
858 
859 	if (connection->state == GB_CONNECTION_STATE_DISABLED)
860 		goto out_unlock;
861 
862 	trace_gb_connection_disable(connection);
863 
864 	spin_lock_irq(&connection->lock);
865 	connection->state = GB_CONNECTION_STATE_DISABLED;
866 	gb_connection_cancel_operations(connection, -ESHUTDOWN);
867 	spin_unlock_irq(&connection->lock);
868 
869 	gb_connection_hd_cport_flush(connection);
870 
871 	gb_connection_svc_connection_destroy(connection);
872 	gb_connection_hd_cport_clear(connection);
873 
874 	gb_connection_hd_cport_disable(connection);
875 out_unlock:
876 	mutex_unlock(&connection->mutex);
877 }
878 EXPORT_SYMBOL_GPL(gb_connection_disable_forced);
879 
880 /* Caller must have disabled the connection before destroying it. */
881 void gb_connection_destroy(struct gb_connection *connection)
882 {
883 	if (!connection)
884 		return;
885 
886 	if (WARN_ON(connection->state != GB_CONNECTION_STATE_DISABLED))
887 		gb_connection_disable(connection);
888 
889 	mutex_lock(&gb_connection_mutex);
890 
891 	spin_lock_irq(&gb_connections_lock);
892 	list_del(&connection->bundle_links);
893 	list_del(&connection->hd_links);
894 	spin_unlock_irq(&gb_connections_lock);
895 
896 	destroy_workqueue(connection->wq);
897 
898 	gb_hd_cport_release(connection->hd, connection->hd_cport_id);
899 	connection->hd_cport_id = CPORT_ID_BAD;
900 
901 	mutex_unlock(&gb_connection_mutex);
902 
903 	gb_connection_put(connection);
904 }
905 EXPORT_SYMBOL_GPL(gb_connection_destroy);
906 
907 void gb_connection_latency_tag_enable(struct gb_connection *connection)
908 {
909 	struct gb_host_device *hd = connection->hd;
910 	int ret;
911 
912 	if (!hd->driver->latency_tag_enable)
913 		return;
914 
915 	ret = hd->driver->latency_tag_enable(hd, connection->hd_cport_id);
916 	if (ret) {
917 		dev_err(&connection->hd->dev,
918 			"%s: failed to enable latency tag: %d\n",
919 			connection->name, ret);
920 	}
921 }
922 EXPORT_SYMBOL_GPL(gb_connection_latency_tag_enable);
923 
924 void gb_connection_latency_tag_disable(struct gb_connection *connection)
925 {
926 	struct gb_host_device *hd = connection->hd;
927 	int ret;
928 
929 	if (!hd->driver->latency_tag_disable)
930 		return;
931 
932 	ret = hd->driver->latency_tag_disable(hd, connection->hd_cport_id);
933 	if (ret) {
934 		dev_err(&connection->hd->dev,
935 			"%s: failed to disable latency tag: %d\n",
936 			connection->name, ret);
937 	}
938 }
939 EXPORT_SYMBOL_GPL(gb_connection_latency_tag_disable);
940