Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/drivers/greybus/connection.c
26278 views
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_ordered_workqueue("%s:%d", 0, dev_name(&hd->dev),
191
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
941