root/drivers/greybus/connection.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. gb_connection_cport_in_use
  2. gb_connection_get
  3. gb_connection_put
  4. gb_connection_hd_find
  5. greybus_data_rcvd
  6. gb_connection_kref_release
  7. gb_connection_init_name
  8. _gb_connection_create
  9. gb_connection_create_static
  10. gb_connection_create_control
  11. gb_connection_create
  12. gb_connection_create_flags
  13. gb_connection_create_offloaded
  14. gb_connection_hd_cport_enable
  15. gb_connection_hd_cport_disable
  16. gb_connection_hd_cport_connected
  17. gb_connection_hd_cport_flush
  18. gb_connection_hd_cport_quiesce
  19. gb_connection_hd_cport_clear
  20. gb_connection_svc_connection_create
  21. gb_connection_svc_connection_destroy
  22. gb_connection_control_connected
  23. gb_connection_control_disconnecting
  24. gb_connection_control_disconnected
  25. gb_connection_shutdown_operation
  26. gb_connection_cport_shutdown
  27. gb_connection_cport_shutdown_phase_1
  28. gb_connection_cport_shutdown_phase_2
  29. gb_connection_cancel_operations
  30. gb_connection_flush_incoming_operations
  31. _gb_connection_enable
  32. gb_connection_enable
  33. gb_connection_enable_tx
  34. gb_connection_disable_rx
  35. gb_connection_mode_switch_prepare
  36. gb_connection_mode_switch_complete
  37. gb_connection_disable
  38. gb_connection_disable_forced
  39. gb_connection_destroy
  40. gb_connection_latency_tag_enable
  41. gb_connection_latency_tag_disable

   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         if (!hd->driver->cport_quiesce)
 365                 return 0;
 366 
 367         ret = hd->driver->cport_quiesce(hd, connection->hd_cport_id,
 368                                         peer_space,
 369                                         GB_CONNECTION_CPORT_QUIESCE_TIMEOUT);
 370         if (ret) {
 371                 dev_err(&hd->dev, "%s: failed to quiesce host cport: %d\n",
 372                         connection->name, ret);
 373                 return ret;
 374         }
 375 
 376         return 0;
 377 }
 378 
 379 static int gb_connection_hd_cport_clear(struct gb_connection *connection)
 380 {
 381         struct gb_host_device *hd = connection->hd;
 382         int ret;
 383 
 384         if (!hd->driver->cport_clear)
 385                 return 0;
 386 
 387         ret = hd->driver->cport_clear(hd, connection->hd_cport_id);
 388         if (ret) {
 389                 dev_err(&hd->dev, "%s: failed to clear host cport: %d\n",
 390                         connection->name, ret);
 391                 return ret;
 392         }
 393 
 394         return 0;
 395 }
 396 
 397 /*
 398  * Request the SVC to create a connection from AP's cport to interface's
 399  * cport.
 400  */
 401 static int
 402 gb_connection_svc_connection_create(struct gb_connection *connection)
 403 {
 404         struct gb_host_device *hd = connection->hd;
 405         struct gb_interface *intf;
 406         u8 cport_flags;
 407         int ret;
 408 
 409         if (gb_connection_is_static(connection))
 410                 return 0;
 411 
 412         intf = connection->intf;
 413 
 414         /*
 415          * Enable either E2EFC or CSD, unless no flow control is requested.
 416          */
 417         cport_flags = GB_SVC_CPORT_FLAG_CSV_N;
 418         if (gb_connection_flow_control_disabled(connection)) {
 419                 cport_flags |= GB_SVC_CPORT_FLAG_CSD_N;
 420         } else if (gb_connection_e2efc_enabled(connection)) {
 421                 cport_flags |= GB_SVC_CPORT_FLAG_CSD_N |
 422                                 GB_SVC_CPORT_FLAG_E2EFC;
 423         }
 424 
 425         ret = gb_svc_connection_create(hd->svc,
 426                                        hd->svc->ap_intf_id,
 427                                        connection->hd_cport_id,
 428                                        intf->interface_id,
 429                                        connection->intf_cport_id,
 430                                        cport_flags);
 431         if (ret) {
 432                 dev_err(&connection->hd->dev,
 433                         "%s: failed to create svc connection: %d\n",
 434                         connection->name, ret);
 435                 return ret;
 436         }
 437 
 438         return 0;
 439 }
 440 
 441 static void
 442 gb_connection_svc_connection_destroy(struct gb_connection *connection)
 443 {
 444         if (gb_connection_is_static(connection))
 445                 return;
 446 
 447         gb_svc_connection_destroy(connection->hd->svc,
 448                                   connection->hd->svc->ap_intf_id,
 449                                   connection->hd_cport_id,
 450                                   connection->intf->interface_id,
 451                                   connection->intf_cport_id);
 452 }
 453 
 454 /* Inform Interface about active CPorts */
 455 static int gb_connection_control_connected(struct gb_connection *connection)
 456 {
 457         struct gb_control *control;
 458         u16 cport_id = connection->intf_cport_id;
 459         int ret;
 460 
 461         if (gb_connection_is_static(connection))
 462                 return 0;
 463 
 464         if (gb_connection_is_control(connection))
 465                 return 0;
 466 
 467         control = connection->intf->control;
 468 
 469         ret = gb_control_connected_operation(control, cport_id);
 470         if (ret) {
 471                 dev_err(&connection->bundle->dev,
 472                         "failed to connect cport: %d\n", ret);
 473                 return ret;
 474         }
 475 
 476         return 0;
 477 }
 478 
 479 static void
 480 gb_connection_control_disconnecting(struct gb_connection *connection)
 481 {
 482         struct gb_control *control;
 483         u16 cport_id = connection->intf_cport_id;
 484         int ret;
 485 
 486         if (gb_connection_is_static(connection))
 487                 return;
 488 
 489         control = connection->intf->control;
 490 
 491         ret = gb_control_disconnecting_operation(control, cport_id);
 492         if (ret) {
 493                 dev_err(&connection->hd->dev,
 494                         "%s: failed to send disconnecting: %d\n",
 495                         connection->name, ret);
 496         }
 497 }
 498 
 499 static void
 500 gb_connection_control_disconnected(struct gb_connection *connection)
 501 {
 502         struct gb_control *control;
 503         u16 cport_id = connection->intf_cport_id;
 504         int ret;
 505 
 506         if (gb_connection_is_static(connection))
 507                 return;
 508 
 509         control = connection->intf->control;
 510 
 511         if (gb_connection_is_control(connection)) {
 512                 if (connection->mode_switch) {
 513                         ret = gb_control_mode_switch_operation(control);
 514                         if (ret) {
 515                                 /*
 516                                  * Allow mode switch to time out waiting for
 517                                  * mailbox event.
 518                                  */
 519                                 return;
 520                         }
 521                 }
 522 
 523                 return;
 524         }
 525 
 526         ret = gb_control_disconnected_operation(control, cport_id);
 527         if (ret) {
 528                 dev_warn(&connection->bundle->dev,
 529                          "failed to disconnect cport: %d\n", ret);
 530         }
 531 }
 532 
 533 static int gb_connection_shutdown_operation(struct gb_connection *connection,
 534                                             u8 phase)
 535 {
 536         struct gb_cport_shutdown_request *req;
 537         struct gb_operation *operation;
 538         int ret;
 539 
 540         operation = gb_operation_create_core(connection,
 541                                              GB_REQUEST_TYPE_CPORT_SHUTDOWN,
 542                                              sizeof(*req), 0, 0,
 543                                              GFP_KERNEL);
 544         if (!operation)
 545                 return -ENOMEM;
 546 
 547         req = operation->request->payload;
 548         req->phase = phase;
 549 
 550         ret = gb_operation_request_send_sync(operation);
 551 
 552         gb_operation_put(operation);
 553 
 554         return ret;
 555 }
 556 
 557 static int gb_connection_cport_shutdown(struct gb_connection *connection,
 558                                         u8 phase)
 559 {
 560         struct gb_host_device *hd = connection->hd;
 561         const struct gb_hd_driver *drv = hd->driver;
 562         int ret;
 563 
 564         if (gb_connection_is_static(connection))
 565                 return 0;
 566 
 567         if (gb_connection_is_offloaded(connection)) {
 568                 if (!drv->cport_shutdown)
 569                         return 0;
 570 
 571                 ret = drv->cport_shutdown(hd, connection->hd_cport_id, phase,
 572                                           GB_OPERATION_TIMEOUT_DEFAULT);
 573         } else {
 574                 ret = gb_connection_shutdown_operation(connection, phase);
 575         }
 576 
 577         if (ret) {
 578                 dev_err(&hd->dev, "%s: failed to send cport shutdown (phase %d): %d\n",
 579                         connection->name, phase, ret);
 580                 return ret;
 581         }
 582 
 583         return 0;
 584 }
 585 
 586 static int
 587 gb_connection_cport_shutdown_phase_1(struct gb_connection *connection)
 588 {
 589         return gb_connection_cport_shutdown(connection, 1);
 590 }
 591 
 592 static int
 593 gb_connection_cport_shutdown_phase_2(struct gb_connection *connection)
 594 {
 595         return gb_connection_cport_shutdown(connection, 2);
 596 }
 597 
 598 /*
 599  * Cancel all active operations on a connection.
 600  *
 601  * Locking: Called with connection lock held and state set to DISABLED or
 602  * DISCONNECTING.
 603  */
 604 static void gb_connection_cancel_operations(struct gb_connection *connection,
 605                                             int errno)
 606         __must_hold(&connection->lock)
 607 {
 608         struct gb_operation *operation;
 609 
 610         while (!list_empty(&connection->operations)) {
 611                 operation = list_last_entry(&connection->operations,
 612                                             struct gb_operation, links);
 613                 gb_operation_get(operation);
 614                 spin_unlock_irq(&connection->lock);
 615 
 616                 if (gb_operation_is_incoming(operation))
 617                         gb_operation_cancel_incoming(operation, errno);
 618                 else
 619                         gb_operation_cancel(operation, errno);
 620 
 621                 gb_operation_put(operation);
 622 
 623                 spin_lock_irq(&connection->lock);
 624         }
 625 }
 626 
 627 /*
 628  * Cancel all active incoming operations on a connection.
 629  *
 630  * Locking: Called with connection lock held and state set to ENABLED_TX.
 631  */
 632 static void
 633 gb_connection_flush_incoming_operations(struct gb_connection *connection,
 634                                         int errno)
 635         __must_hold(&connection->lock)
 636 {
 637         struct gb_operation *operation;
 638         bool incoming;
 639 
 640         while (!list_empty(&connection->operations)) {
 641                 incoming = false;
 642                 list_for_each_entry(operation, &connection->operations,
 643                                     links) {
 644                         if (gb_operation_is_incoming(operation)) {
 645                                 gb_operation_get(operation);
 646                                 incoming = true;
 647                                 break;
 648                         }
 649                 }
 650 
 651                 if (!incoming)
 652                         break;
 653 
 654                 spin_unlock_irq(&connection->lock);
 655 
 656                 /* FIXME: flush, not cancel? */
 657                 gb_operation_cancel_incoming(operation, errno);
 658                 gb_operation_put(operation);
 659 
 660                 spin_lock_irq(&connection->lock);
 661         }
 662 }
 663 
 664 /*
 665  * _gb_connection_enable() - enable a connection
 666  * @connection:         connection to enable
 667  * @rx:                 whether to enable incoming requests
 668  *
 669  * Connection-enable helper for DISABLED->ENABLED, DISABLED->ENABLED_TX, and
 670  * ENABLED_TX->ENABLED state transitions.
 671  *
 672  * Locking: Caller holds connection->mutex.
 673  */
 674 static int _gb_connection_enable(struct gb_connection *connection, bool rx)
 675 {
 676         int ret;
 677 
 678         /* Handle ENABLED_TX -> ENABLED transitions. */
 679         if (connection->state == GB_CONNECTION_STATE_ENABLED_TX) {
 680                 if (!(connection->handler && rx))
 681                         return 0;
 682 
 683                 spin_lock_irq(&connection->lock);
 684                 connection->state = GB_CONNECTION_STATE_ENABLED;
 685                 spin_unlock_irq(&connection->lock);
 686 
 687                 return 0;
 688         }
 689 
 690         ret = gb_connection_hd_cport_enable(connection);
 691         if (ret)
 692                 return ret;
 693 
 694         ret = gb_connection_svc_connection_create(connection);
 695         if (ret)
 696                 goto err_hd_cport_clear;
 697 
 698         ret = gb_connection_hd_cport_connected(connection);
 699         if (ret)
 700                 goto err_svc_connection_destroy;
 701 
 702         spin_lock_irq(&connection->lock);
 703         if (connection->handler && rx)
 704                 connection->state = GB_CONNECTION_STATE_ENABLED;
 705         else
 706                 connection->state = GB_CONNECTION_STATE_ENABLED_TX;
 707         spin_unlock_irq(&connection->lock);
 708 
 709         ret = gb_connection_control_connected(connection);
 710         if (ret)
 711                 goto err_control_disconnecting;
 712 
 713         return 0;
 714 
 715 err_control_disconnecting:
 716         spin_lock_irq(&connection->lock);
 717         connection->state = GB_CONNECTION_STATE_DISCONNECTING;
 718         gb_connection_cancel_operations(connection, -ESHUTDOWN);
 719         spin_unlock_irq(&connection->lock);
 720 
 721         /* Transmit queue should already be empty. */
 722         gb_connection_hd_cport_flush(connection);
 723 
 724         gb_connection_control_disconnecting(connection);
 725         gb_connection_cport_shutdown_phase_1(connection);
 726         gb_connection_hd_cport_quiesce(connection);
 727         gb_connection_cport_shutdown_phase_2(connection);
 728         gb_connection_control_disconnected(connection);
 729         connection->state = GB_CONNECTION_STATE_DISABLED;
 730 err_svc_connection_destroy:
 731         gb_connection_svc_connection_destroy(connection);
 732 err_hd_cport_clear:
 733         gb_connection_hd_cport_clear(connection);
 734 
 735         gb_connection_hd_cport_disable(connection);
 736 
 737         return ret;
 738 }
 739 
 740 int gb_connection_enable(struct gb_connection *connection)
 741 {
 742         int ret = 0;
 743 
 744         mutex_lock(&connection->mutex);
 745 
 746         if (connection->state == GB_CONNECTION_STATE_ENABLED)
 747                 goto out_unlock;
 748 
 749         ret = _gb_connection_enable(connection, true);
 750         if (!ret)
 751                 trace_gb_connection_enable(connection);
 752 
 753 out_unlock:
 754         mutex_unlock(&connection->mutex);
 755 
 756         return ret;
 757 }
 758 EXPORT_SYMBOL_GPL(gb_connection_enable);
 759 
 760 int gb_connection_enable_tx(struct gb_connection *connection)
 761 {
 762         int ret = 0;
 763 
 764         mutex_lock(&connection->mutex);
 765 
 766         if (connection->state == GB_CONNECTION_STATE_ENABLED) {
 767                 ret = -EINVAL;
 768                 goto out_unlock;
 769         }
 770 
 771         if (connection->state == GB_CONNECTION_STATE_ENABLED_TX)
 772                 goto out_unlock;
 773 
 774         ret = _gb_connection_enable(connection, false);
 775         if (!ret)
 776                 trace_gb_connection_enable(connection);
 777 
 778 out_unlock:
 779         mutex_unlock(&connection->mutex);
 780 
 781         return ret;
 782 }
 783 EXPORT_SYMBOL_GPL(gb_connection_enable_tx);
 784 
 785 void gb_connection_disable_rx(struct gb_connection *connection)
 786 {
 787         mutex_lock(&connection->mutex);
 788 
 789         spin_lock_irq(&connection->lock);
 790         if (connection->state != GB_CONNECTION_STATE_ENABLED) {
 791                 spin_unlock_irq(&connection->lock);
 792                 goto out_unlock;
 793         }
 794         connection->state = GB_CONNECTION_STATE_ENABLED_TX;
 795         gb_connection_flush_incoming_operations(connection, -ESHUTDOWN);
 796         spin_unlock_irq(&connection->lock);
 797 
 798         trace_gb_connection_disable(connection);
 799 
 800 out_unlock:
 801         mutex_unlock(&connection->mutex);
 802 }
 803 EXPORT_SYMBOL_GPL(gb_connection_disable_rx);
 804 
 805 void gb_connection_mode_switch_prepare(struct gb_connection *connection)
 806 {
 807         connection->mode_switch = true;
 808 }
 809 
 810 void gb_connection_mode_switch_complete(struct gb_connection *connection)
 811 {
 812         gb_connection_svc_connection_destroy(connection);
 813         gb_connection_hd_cport_clear(connection);
 814 
 815         gb_connection_hd_cport_disable(connection);
 816 
 817         connection->mode_switch = false;
 818 }
 819 
 820 void gb_connection_disable(struct gb_connection *connection)
 821 {
 822         mutex_lock(&connection->mutex);
 823 
 824         if (connection->state == GB_CONNECTION_STATE_DISABLED)
 825                 goto out_unlock;
 826 
 827         trace_gb_connection_disable(connection);
 828 
 829         spin_lock_irq(&connection->lock);
 830         connection->state = GB_CONNECTION_STATE_DISCONNECTING;
 831         gb_connection_cancel_operations(connection, -ESHUTDOWN);
 832         spin_unlock_irq(&connection->lock);
 833 
 834         gb_connection_hd_cport_flush(connection);
 835 
 836         gb_connection_control_disconnecting(connection);
 837         gb_connection_cport_shutdown_phase_1(connection);
 838         gb_connection_hd_cport_quiesce(connection);
 839         gb_connection_cport_shutdown_phase_2(connection);
 840         gb_connection_control_disconnected(connection);
 841 
 842         connection->state = GB_CONNECTION_STATE_DISABLED;
 843 
 844         /* control-connection tear down is deferred when mode switching */
 845         if (!connection->mode_switch) {
 846                 gb_connection_svc_connection_destroy(connection);
 847                 gb_connection_hd_cport_clear(connection);
 848 
 849                 gb_connection_hd_cport_disable(connection);
 850         }
 851 
 852 out_unlock:
 853         mutex_unlock(&connection->mutex);
 854 }
 855 EXPORT_SYMBOL_GPL(gb_connection_disable);
 856 
 857 /* Disable a connection without communicating with the remote end. */
 858 void gb_connection_disable_forced(struct gb_connection *connection)
 859 {
 860         mutex_lock(&connection->mutex);
 861 
 862         if (connection->state == GB_CONNECTION_STATE_DISABLED)
 863                 goto out_unlock;
 864 
 865         trace_gb_connection_disable(connection);
 866 
 867         spin_lock_irq(&connection->lock);
 868         connection->state = GB_CONNECTION_STATE_DISABLED;
 869         gb_connection_cancel_operations(connection, -ESHUTDOWN);
 870         spin_unlock_irq(&connection->lock);
 871 
 872         gb_connection_hd_cport_flush(connection);
 873 
 874         gb_connection_svc_connection_destroy(connection);
 875         gb_connection_hd_cport_clear(connection);
 876 
 877         gb_connection_hd_cport_disable(connection);
 878 out_unlock:
 879         mutex_unlock(&connection->mutex);
 880 }
 881 EXPORT_SYMBOL_GPL(gb_connection_disable_forced);
 882 
 883 /* Caller must have disabled the connection before destroying it. */
 884 void gb_connection_destroy(struct gb_connection *connection)
 885 {
 886         if (!connection)
 887                 return;
 888 
 889         if (WARN_ON(connection->state != GB_CONNECTION_STATE_DISABLED))
 890                 gb_connection_disable(connection);
 891 
 892         mutex_lock(&gb_connection_mutex);
 893 
 894         spin_lock_irq(&gb_connections_lock);
 895         list_del(&connection->bundle_links);
 896         list_del(&connection->hd_links);
 897         spin_unlock_irq(&gb_connections_lock);
 898 
 899         destroy_workqueue(connection->wq);
 900 
 901         gb_hd_cport_release(connection->hd, connection->hd_cport_id);
 902         connection->hd_cport_id = CPORT_ID_BAD;
 903 
 904         mutex_unlock(&gb_connection_mutex);
 905 
 906         gb_connection_put(connection);
 907 }
 908 EXPORT_SYMBOL_GPL(gb_connection_destroy);
 909 
 910 void gb_connection_latency_tag_enable(struct gb_connection *connection)
 911 {
 912         struct gb_host_device *hd = connection->hd;
 913         int ret;
 914 
 915         if (!hd->driver->latency_tag_enable)
 916                 return;
 917 
 918         ret = hd->driver->latency_tag_enable(hd, connection->hd_cport_id);
 919         if (ret) {
 920                 dev_err(&connection->hd->dev,
 921                         "%s: failed to enable latency tag: %d\n",
 922                         connection->name, ret);
 923         }
 924 }
 925 EXPORT_SYMBOL_GPL(gb_connection_latency_tag_enable);
 926 
 927 void gb_connection_latency_tag_disable(struct gb_connection *connection)
 928 {
 929         struct gb_host_device *hd = connection->hd;
 930         int ret;
 931 
 932         if (!hd->driver->latency_tag_disable)
 933                 return;
 934 
 935         ret = hd->driver->latency_tag_disable(hd, connection->hd_cport_id);
 936         if (ret) {
 937                 dev_err(&connection->hd->dev,
 938                         "%s: failed to disable latency tag: %d\n",
 939                         connection->name, ret);
 940         }
 941 }
 942 EXPORT_SYMBOL_GPL(gb_connection_latency_tag_disable);

/* [<][>][^][v][top][bottom][index][help] */