linux/drivers/thunderbolt/domain.c
<<
>>
Prefs
   1/*
   2 * Thunderbolt bus support
   3 *
   4 * Copyright (C) 2017, Intel Corporation
   5 * Author:  Mika Westerberg <mika.westerberg@linux.intel.com>
   6 *
   7 * This program is free software; you can redistribute it and/or modify
   8 * it under the terms of the GNU General Public License version 2 as
   9 * published by the Free Software Foundation.
  10 */
  11
  12#include <linux/device.h>
  13#include <linux/idr.h>
  14#include <linux/module.h>
  15#include <linux/pm_runtime.h>
  16#include <linux/slab.h>
  17#include <linux/random.h>
  18#include <crypto/hash.h>
  19
  20#include "tb.h"
  21
  22static DEFINE_IDA(tb_domain_ida);
  23
  24static bool match_service_id(const struct tb_service_id *id,
  25                             const struct tb_service *svc)
  26{
  27        if (id->match_flags & TBSVC_MATCH_PROTOCOL_KEY) {
  28                if (strcmp(id->protocol_key, svc->key))
  29                        return false;
  30        }
  31
  32        if (id->match_flags & TBSVC_MATCH_PROTOCOL_ID) {
  33                if (id->protocol_id != svc->prtcid)
  34                        return false;
  35        }
  36
  37        if (id->match_flags & TBSVC_MATCH_PROTOCOL_VERSION) {
  38                if (id->protocol_version != svc->prtcvers)
  39                        return false;
  40        }
  41
  42        if (id->match_flags & TBSVC_MATCH_PROTOCOL_VERSION) {
  43                if (id->protocol_revision != svc->prtcrevs)
  44                        return false;
  45        }
  46
  47        return true;
  48}
  49
  50static const struct tb_service_id *__tb_service_match(struct device *dev,
  51                                                      struct device_driver *drv)
  52{
  53        struct tb_service_driver *driver;
  54        const struct tb_service_id *ids;
  55        struct tb_service *svc;
  56
  57        svc = tb_to_service(dev);
  58        if (!svc)
  59                return NULL;
  60
  61        driver = container_of(drv, struct tb_service_driver, driver);
  62        if (!driver->id_table)
  63                return NULL;
  64
  65        for (ids = driver->id_table; ids->match_flags != 0; ids++) {
  66                if (match_service_id(ids, svc))
  67                        return ids;
  68        }
  69
  70        return NULL;
  71}
  72
  73static int tb_service_match(struct device *dev, struct device_driver *drv)
  74{
  75        return !!__tb_service_match(dev, drv);
  76}
  77
  78static int tb_service_probe(struct device *dev)
  79{
  80        struct tb_service *svc = tb_to_service(dev);
  81        struct tb_service_driver *driver;
  82        const struct tb_service_id *id;
  83
  84        driver = container_of(dev->driver, struct tb_service_driver, driver);
  85        id = __tb_service_match(dev, &driver->driver);
  86
  87        return driver->probe(svc, id);
  88}
  89
  90static int tb_service_remove(struct device *dev)
  91{
  92        struct tb_service *svc = tb_to_service(dev);
  93        struct tb_service_driver *driver;
  94
  95        driver = container_of(dev->driver, struct tb_service_driver, driver);
  96        if (driver->remove)
  97                driver->remove(svc);
  98
  99        return 0;
 100}
 101
 102static void tb_service_shutdown(struct device *dev)
 103{
 104        struct tb_service_driver *driver;
 105        struct tb_service *svc;
 106
 107        svc = tb_to_service(dev);
 108        if (!svc || !dev->driver)
 109                return;
 110
 111        driver = container_of(dev->driver, struct tb_service_driver, driver);
 112        if (driver->shutdown)
 113                driver->shutdown(svc);
 114}
 115
 116static const char * const tb_security_names[] = {
 117        [TB_SECURITY_NONE] = "none",
 118        [TB_SECURITY_USER] = "user",
 119        [TB_SECURITY_SECURE] = "secure",
 120        [TB_SECURITY_DPONLY] = "dponly",
 121        [TB_SECURITY_USBONLY] = "usbonly",
 122};
 123
 124static ssize_t boot_acl_show(struct device *dev, struct device_attribute *attr,
 125                             char *buf)
 126{
 127        struct tb *tb = container_of(dev, struct tb, dev);
 128        uuid_t *uuids;
 129        ssize_t ret;
 130        int i;
 131
 132        uuids = kcalloc(tb->nboot_acl, sizeof(uuid_t), GFP_KERNEL);
 133        if (!uuids)
 134                return -ENOMEM;
 135
 136        pm_runtime_get_sync(&tb->dev);
 137
 138        if (mutex_lock_interruptible(&tb->lock)) {
 139                ret = -ERESTARTSYS;
 140                goto out;
 141        }
 142        ret = tb->cm_ops->get_boot_acl(tb, uuids, tb->nboot_acl);
 143        if (ret) {
 144                mutex_unlock(&tb->lock);
 145                goto out;
 146        }
 147        mutex_unlock(&tb->lock);
 148
 149        for (ret = 0, i = 0; i < tb->nboot_acl; i++) {
 150                if (!uuid_is_null(&uuids[i]))
 151                        ret += snprintf(buf + ret, PAGE_SIZE - ret, "%pUb",
 152                                        &uuids[i]);
 153
 154                ret += snprintf(buf + ret, PAGE_SIZE - ret, "%s",
 155                               i < tb->nboot_acl - 1 ? "," : "\n");
 156        }
 157
 158out:
 159        pm_runtime_mark_last_busy(&tb->dev);
 160        pm_runtime_put_autosuspend(&tb->dev);
 161        kfree(uuids);
 162
 163        return ret;
 164}
 165
 166static ssize_t boot_acl_store(struct device *dev, struct device_attribute *attr,
 167                              const char *buf, size_t count)
 168{
 169        struct tb *tb = container_of(dev, struct tb, dev);
 170        char *str, *s, *uuid_str;
 171        ssize_t ret = 0;
 172        uuid_t *acl;
 173        int i = 0;
 174
 175        /*
 176         * Make sure the value is not bigger than tb->nboot_acl * UUID
 177         * length + commas and optional "\n". Also the smallest allowable
 178         * string is tb->nboot_acl * ",".
 179         */
 180        if (count > (UUID_STRING_LEN + 1) * tb->nboot_acl + 1)
 181                return -EINVAL;
 182        if (count < tb->nboot_acl - 1)
 183                return -EINVAL;
 184
 185        str = kstrdup(buf, GFP_KERNEL);
 186        if (!str)
 187                return -ENOMEM;
 188
 189        acl = kcalloc(tb->nboot_acl, sizeof(uuid_t), GFP_KERNEL);
 190        if (!acl) {
 191                ret = -ENOMEM;
 192                goto err_free_str;
 193        }
 194
 195        uuid_str = strim(str);
 196        while ((s = strsep(&uuid_str, ",")) != NULL && i < tb->nboot_acl) {
 197                size_t len = strlen(s);
 198
 199                if (len) {
 200                        if (len != UUID_STRING_LEN) {
 201                                ret = -EINVAL;
 202                                goto err_free_acl;
 203                        }
 204                        ret = uuid_parse(s, &acl[i]);
 205                        if (ret)
 206                                goto err_free_acl;
 207                }
 208
 209                i++;
 210        }
 211
 212        if (s || i < tb->nboot_acl) {
 213                ret = -EINVAL;
 214                goto err_free_acl;
 215        }
 216
 217        pm_runtime_get_sync(&tb->dev);
 218
 219        if (mutex_lock_interruptible(&tb->lock)) {
 220                ret = -ERESTARTSYS;
 221                goto err_rpm_put;
 222        }
 223        ret = tb->cm_ops->set_boot_acl(tb, acl, tb->nboot_acl);
 224        if (!ret) {
 225                /* Notify userspace about the change */
 226                kobject_uevent(&tb->dev.kobj, KOBJ_CHANGE);
 227        }
 228        mutex_unlock(&tb->lock);
 229
 230err_rpm_put:
 231        pm_runtime_mark_last_busy(&tb->dev);
 232        pm_runtime_put_autosuspend(&tb->dev);
 233err_free_acl:
 234        kfree(acl);
 235err_free_str:
 236        kfree(str);
 237
 238        return ret ?: count;
 239}
 240static DEVICE_ATTR_RW(boot_acl);
 241
 242static ssize_t security_show(struct device *dev, struct device_attribute *attr,
 243                             char *buf)
 244{
 245        struct tb *tb = container_of(dev, struct tb, dev);
 246        const char *name = "unknown";
 247
 248        if (tb->security_level < ARRAY_SIZE(tb_security_names))
 249                name = tb_security_names[tb->security_level];
 250
 251        return sprintf(buf, "%s\n", name);
 252}
 253static DEVICE_ATTR_RO(security);
 254
 255static struct attribute *domain_attrs[] = {
 256        &dev_attr_boot_acl.attr,
 257        &dev_attr_security.attr,
 258        NULL,
 259};
 260
 261static umode_t domain_attr_is_visible(struct kobject *kobj,
 262                                      struct attribute *attr, int n)
 263{
 264        struct device *dev = container_of(kobj, struct device, kobj);
 265        struct tb *tb = container_of(dev, struct tb, dev);
 266
 267        if (attr == &dev_attr_boot_acl.attr) {
 268                if (tb->nboot_acl &&
 269                    tb->cm_ops->get_boot_acl &&
 270                    tb->cm_ops->set_boot_acl)
 271                        return attr->mode;
 272                return 0;
 273        }
 274
 275        return attr->mode;
 276}
 277
 278static struct attribute_group domain_attr_group = {
 279        .is_visible = domain_attr_is_visible,
 280        .attrs = domain_attrs,
 281};
 282
 283static const struct attribute_group *domain_attr_groups[] = {
 284        &domain_attr_group,
 285        NULL,
 286};
 287
 288struct bus_type tb_bus_type = {
 289        .name = "thunderbolt",
 290        .match = tb_service_match,
 291        .probe = tb_service_probe,
 292        .remove = tb_service_remove,
 293        .shutdown = tb_service_shutdown,
 294};
 295
 296static void tb_domain_release(struct device *dev)
 297{
 298        struct tb *tb = container_of(dev, struct tb, dev);
 299
 300        tb_ctl_free(tb->ctl);
 301        destroy_workqueue(tb->wq);
 302        ida_simple_remove(&tb_domain_ida, tb->index);
 303        mutex_destroy(&tb->lock);
 304        kfree(tb);
 305}
 306
 307struct device_type tb_domain_type = {
 308        .name = "thunderbolt_domain",
 309        .release = tb_domain_release,
 310};
 311
 312/**
 313 * tb_domain_alloc() - Allocate a domain
 314 * @nhi: Pointer to the host controller
 315 * @privsize: Size of the connection manager private data
 316 *
 317 * Allocates and initializes a new Thunderbolt domain. Connection
 318 * managers are expected to call this and then fill in @cm_ops
 319 * accordingly.
 320 *
 321 * Call tb_domain_put() to release the domain before it has been added
 322 * to the system.
 323 *
 324 * Return: allocated domain structure on %NULL in case of error
 325 */
 326struct tb *tb_domain_alloc(struct tb_nhi *nhi, size_t privsize)
 327{
 328        struct tb *tb;
 329
 330        /*
 331         * Make sure the structure sizes map with that the hardware
 332         * expects because bit-fields are being used.
 333         */
 334        BUILD_BUG_ON(sizeof(struct tb_regs_switch_header) != 5 * 4);
 335        BUILD_BUG_ON(sizeof(struct tb_regs_port_header) != 8 * 4);
 336        BUILD_BUG_ON(sizeof(struct tb_regs_hop) != 2 * 4);
 337
 338        tb = kzalloc(sizeof(*tb) + privsize, GFP_KERNEL);
 339        if (!tb)
 340                return NULL;
 341
 342        tb->nhi = nhi;
 343        mutex_init(&tb->lock);
 344
 345        tb->index = ida_simple_get(&tb_domain_ida, 0, 0, GFP_KERNEL);
 346        if (tb->index < 0)
 347                goto err_free;
 348
 349        tb->wq = alloc_ordered_workqueue("thunderbolt%d", 0, tb->index);
 350        if (!tb->wq)
 351                goto err_remove_ida;
 352
 353        tb->dev.parent = &nhi->pdev->dev;
 354        tb->dev.bus = &tb_bus_type;
 355        tb->dev.type = &tb_domain_type;
 356        tb->dev.groups = domain_attr_groups;
 357        dev_set_name(&tb->dev, "domain%d", tb->index);
 358        device_initialize(&tb->dev);
 359
 360        return tb;
 361
 362err_remove_ida:
 363        ida_simple_remove(&tb_domain_ida, tb->index);
 364err_free:
 365        kfree(tb);
 366
 367        return NULL;
 368}
 369
 370static bool tb_domain_event_cb(void *data, enum tb_cfg_pkg_type type,
 371                               const void *buf, size_t size)
 372{
 373        struct tb *tb = data;
 374
 375        if (!tb->cm_ops->handle_event) {
 376                tb_warn(tb, "domain does not have event handler\n");
 377                return true;
 378        }
 379
 380        switch (type) {
 381        case TB_CFG_PKG_XDOMAIN_REQ:
 382        case TB_CFG_PKG_XDOMAIN_RESP:
 383                return tb_xdomain_handle_request(tb, type, buf, size);
 384
 385        default:
 386                tb->cm_ops->handle_event(tb, type, buf, size);
 387        }
 388
 389        return true;
 390}
 391
 392/**
 393 * tb_domain_add() - Add domain to the system
 394 * @tb: Domain to add
 395 *
 396 * Starts the domain and adds it to the system. Hotplugging devices will
 397 * work after this has been returned successfully. In order to remove
 398 * and release the domain after this function has been called, call
 399 * tb_domain_remove().
 400 *
 401 * Return: %0 in case of success and negative errno in case of error
 402 */
 403int tb_domain_add(struct tb *tb)
 404{
 405        int ret;
 406
 407        if (WARN_ON(!tb->cm_ops))
 408                return -EINVAL;
 409
 410        mutex_lock(&tb->lock);
 411
 412        tb->ctl = tb_ctl_alloc(tb->nhi, tb_domain_event_cb, tb);
 413        if (!tb->ctl) {
 414                ret = -ENOMEM;
 415                goto err_unlock;
 416        }
 417
 418        /*
 419         * tb_schedule_hotplug_handler may be called as soon as the config
 420         * channel is started. Thats why we have to hold the lock here.
 421         */
 422        tb_ctl_start(tb->ctl);
 423
 424        if (tb->cm_ops->driver_ready) {
 425                ret = tb->cm_ops->driver_ready(tb);
 426                if (ret)
 427                        goto err_ctl_stop;
 428        }
 429
 430        ret = device_add(&tb->dev);
 431        if (ret)
 432                goto err_ctl_stop;
 433
 434        /* Start the domain */
 435        if (tb->cm_ops->start) {
 436                ret = tb->cm_ops->start(tb);
 437                if (ret)
 438                        goto err_domain_del;
 439        }
 440
 441        /* This starts event processing */
 442        mutex_unlock(&tb->lock);
 443
 444        pm_runtime_no_callbacks(&tb->dev);
 445        pm_runtime_set_active(&tb->dev);
 446        pm_runtime_enable(&tb->dev);
 447        pm_runtime_set_autosuspend_delay(&tb->dev, TB_AUTOSUSPEND_DELAY);
 448        pm_runtime_mark_last_busy(&tb->dev);
 449        pm_runtime_use_autosuspend(&tb->dev);
 450
 451        return 0;
 452
 453err_domain_del:
 454        device_del(&tb->dev);
 455err_ctl_stop:
 456        tb_ctl_stop(tb->ctl);
 457err_unlock:
 458        mutex_unlock(&tb->lock);
 459
 460        return ret;
 461}
 462
 463/**
 464 * tb_domain_remove() - Removes and releases a domain
 465 * @tb: Domain to remove
 466 *
 467 * Stops the domain, removes it from the system and releases all
 468 * resources once the last reference has been released.
 469 */
 470void tb_domain_remove(struct tb *tb)
 471{
 472        mutex_lock(&tb->lock);
 473        if (tb->cm_ops->stop)
 474                tb->cm_ops->stop(tb);
 475        /* Stop the domain control traffic */
 476        tb_ctl_stop(tb->ctl);
 477        mutex_unlock(&tb->lock);
 478
 479        flush_workqueue(tb->wq);
 480        device_unregister(&tb->dev);
 481}
 482
 483/**
 484 * tb_domain_suspend_noirq() - Suspend a domain
 485 * @tb: Domain to suspend
 486 *
 487 * Suspends all devices in the domain and stops the control channel.
 488 */
 489int tb_domain_suspend_noirq(struct tb *tb)
 490{
 491        int ret = 0;
 492
 493        /*
 494         * The control channel interrupt is left enabled during suspend
 495         * and taking the lock here prevents any events happening before
 496         * we actually have stopped the domain and the control channel.
 497         */
 498        mutex_lock(&tb->lock);
 499        if (tb->cm_ops->suspend_noirq)
 500                ret = tb->cm_ops->suspend_noirq(tb);
 501        if (!ret)
 502                tb_ctl_stop(tb->ctl);
 503        mutex_unlock(&tb->lock);
 504
 505        return ret;
 506}
 507
 508/**
 509 * tb_domain_resume_noirq() - Resume a domain
 510 * @tb: Domain to resume
 511 *
 512 * Re-starts the control channel, and resumes all devices connected to
 513 * the domain.
 514 */
 515int tb_domain_resume_noirq(struct tb *tb)
 516{
 517        int ret = 0;
 518
 519        mutex_lock(&tb->lock);
 520        tb_ctl_start(tb->ctl);
 521        if (tb->cm_ops->resume_noirq)
 522                ret = tb->cm_ops->resume_noirq(tb);
 523        mutex_unlock(&tb->lock);
 524
 525        return ret;
 526}
 527
 528int tb_domain_suspend(struct tb *tb)
 529{
 530        return tb->cm_ops->suspend ? tb->cm_ops->suspend(tb) : 0;
 531}
 532
 533void tb_domain_complete(struct tb *tb)
 534{
 535        if (tb->cm_ops->complete)
 536                tb->cm_ops->complete(tb);
 537}
 538
 539int tb_domain_runtime_suspend(struct tb *tb)
 540{
 541        if (tb->cm_ops->runtime_suspend) {
 542                int ret = tb->cm_ops->runtime_suspend(tb);
 543                if (ret)
 544                        return ret;
 545        }
 546        tb_ctl_stop(tb->ctl);
 547        return 0;
 548}
 549
 550int tb_domain_runtime_resume(struct tb *tb)
 551{
 552        tb_ctl_start(tb->ctl);
 553        if (tb->cm_ops->runtime_resume) {
 554                int ret = tb->cm_ops->runtime_resume(tb);
 555                if (ret)
 556                        return ret;
 557        }
 558        return 0;
 559}
 560
 561/**
 562 * tb_domain_approve_switch() - Approve switch
 563 * @tb: Domain the switch belongs to
 564 * @sw: Switch to approve
 565 *
 566 * This will approve switch by connection manager specific means. In
 567 * case of success the connection manager will create tunnels for all
 568 * supported protocols.
 569 */
 570int tb_domain_approve_switch(struct tb *tb, struct tb_switch *sw)
 571{
 572        struct tb_switch *parent_sw;
 573
 574        if (!tb->cm_ops->approve_switch)
 575                return -EPERM;
 576
 577        /* The parent switch must be authorized before this one */
 578        parent_sw = tb_to_switch(sw->dev.parent);
 579        if (!parent_sw || !parent_sw->authorized)
 580                return -EINVAL;
 581
 582        return tb->cm_ops->approve_switch(tb, sw);
 583}
 584
 585/**
 586 * tb_domain_approve_switch_key() - Approve switch and add key
 587 * @tb: Domain the switch belongs to
 588 * @sw: Switch to approve
 589 *
 590 * For switches that support secure connect, this function first adds
 591 * key to the switch NVM using connection manager specific means. If
 592 * adding the key is successful, the switch is approved and connected.
 593 *
 594 * Return: %0 on success and negative errno in case of failure.
 595 */
 596int tb_domain_approve_switch_key(struct tb *tb, struct tb_switch *sw)
 597{
 598        struct tb_switch *parent_sw;
 599        int ret;
 600
 601        if (!tb->cm_ops->approve_switch || !tb->cm_ops->add_switch_key)
 602                return -EPERM;
 603
 604        /* The parent switch must be authorized before this one */
 605        parent_sw = tb_to_switch(sw->dev.parent);
 606        if (!parent_sw || !parent_sw->authorized)
 607                return -EINVAL;
 608
 609        ret = tb->cm_ops->add_switch_key(tb, sw);
 610        if (ret)
 611                return ret;
 612
 613        return tb->cm_ops->approve_switch(tb, sw);
 614}
 615
 616/**
 617 * tb_domain_challenge_switch_key() - Challenge and approve switch
 618 * @tb: Domain the switch belongs to
 619 * @sw: Switch to approve
 620 *
 621 * For switches that support secure connect, this function generates
 622 * random challenge and sends it to the switch. The switch responds to
 623 * this and if the response matches our random challenge, the switch is
 624 * approved and connected.
 625 *
 626 * Return: %0 on success and negative errno in case of failure.
 627 */
 628int tb_domain_challenge_switch_key(struct tb *tb, struct tb_switch *sw)
 629{
 630        u8 challenge[TB_SWITCH_KEY_SIZE];
 631        u8 response[TB_SWITCH_KEY_SIZE];
 632        u8 hmac[TB_SWITCH_KEY_SIZE];
 633        struct tb_switch *parent_sw;
 634        struct crypto_shash *tfm;
 635        struct shash_desc *shash;
 636        int ret;
 637
 638        if (!tb->cm_ops->approve_switch || !tb->cm_ops->challenge_switch_key)
 639                return -EPERM;
 640
 641        /* The parent switch must be authorized before this one */
 642        parent_sw = tb_to_switch(sw->dev.parent);
 643        if (!parent_sw || !parent_sw->authorized)
 644                return -EINVAL;
 645
 646        get_random_bytes(challenge, sizeof(challenge));
 647        ret = tb->cm_ops->challenge_switch_key(tb, sw, challenge, response);
 648        if (ret)
 649                return ret;
 650
 651        tfm = crypto_alloc_shash("hmac(sha256)", 0, 0);
 652        if (IS_ERR(tfm))
 653                return PTR_ERR(tfm);
 654
 655        ret = crypto_shash_setkey(tfm, sw->key, TB_SWITCH_KEY_SIZE);
 656        if (ret)
 657                goto err_free_tfm;
 658
 659        shash = kzalloc(sizeof(*shash) + crypto_shash_descsize(tfm),
 660                        GFP_KERNEL);
 661        if (!shash) {
 662                ret = -ENOMEM;
 663                goto err_free_tfm;
 664        }
 665
 666        shash->tfm = tfm;
 667        shash->flags = CRYPTO_TFM_REQ_MAY_SLEEP;
 668
 669        memset(hmac, 0, sizeof(hmac));
 670        ret = crypto_shash_digest(shash, challenge, sizeof(hmac), hmac);
 671        if (ret)
 672                goto err_free_shash;
 673
 674        /* The returned HMAC must match the one we calculated */
 675        if (memcmp(response, hmac, sizeof(hmac))) {
 676                ret = -EKEYREJECTED;
 677                goto err_free_shash;
 678        }
 679
 680        crypto_free_shash(tfm);
 681        kfree(shash);
 682
 683        return tb->cm_ops->approve_switch(tb, sw);
 684
 685err_free_shash:
 686        kfree(shash);
 687err_free_tfm:
 688        crypto_free_shash(tfm);
 689
 690        return ret;
 691}
 692
 693/**
 694 * tb_domain_disconnect_pcie_paths() - Disconnect all PCIe paths
 695 * @tb: Domain whose PCIe paths to disconnect
 696 *
 697 * This needs to be called in preparation for NVM upgrade of the host
 698 * controller. Makes sure all PCIe paths are disconnected.
 699 *
 700 * Return %0 on success and negative errno in case of error.
 701 */
 702int tb_domain_disconnect_pcie_paths(struct tb *tb)
 703{
 704        if (!tb->cm_ops->disconnect_pcie_paths)
 705                return -EPERM;
 706
 707        return tb->cm_ops->disconnect_pcie_paths(tb);
 708}
 709
 710/**
 711 * tb_domain_approve_xdomain_paths() - Enable DMA paths for XDomain
 712 * @tb: Domain enabling the DMA paths
 713 * @xd: XDomain DMA paths are created to
 714 *
 715 * Calls connection manager specific method to enable DMA paths to the
 716 * XDomain in question.
 717 *
 718 * Return: 0% in case of success and negative errno otherwise. In
 719 * particular returns %-ENOTSUPP if the connection manager
 720 * implementation does not support XDomains.
 721 */
 722int tb_domain_approve_xdomain_paths(struct tb *tb, struct tb_xdomain *xd)
 723{
 724        if (!tb->cm_ops->approve_xdomain_paths)
 725                return -ENOTSUPP;
 726
 727        return tb->cm_ops->approve_xdomain_paths(tb, xd);
 728}
 729
 730/**
 731 * tb_domain_disconnect_xdomain_paths() - Disable DMA paths for XDomain
 732 * @tb: Domain disabling the DMA paths
 733 * @xd: XDomain whose DMA paths are disconnected
 734 *
 735 * Calls connection manager specific method to disconnect DMA paths to
 736 * the XDomain in question.
 737 *
 738 * Return: 0% in case of success and negative errno otherwise. In
 739 * particular returns %-ENOTSUPP if the connection manager
 740 * implementation does not support XDomains.
 741 */
 742int tb_domain_disconnect_xdomain_paths(struct tb *tb, struct tb_xdomain *xd)
 743{
 744        if (!tb->cm_ops->disconnect_xdomain_paths)
 745                return -ENOTSUPP;
 746
 747        return tb->cm_ops->disconnect_xdomain_paths(tb, xd);
 748}
 749
 750static int disconnect_xdomain(struct device *dev, void *data)
 751{
 752        struct tb_xdomain *xd;
 753        struct tb *tb = data;
 754        int ret = 0;
 755
 756        xd = tb_to_xdomain(dev);
 757        if (xd && xd->tb == tb)
 758                ret = tb_xdomain_disable_paths(xd);
 759
 760        return ret;
 761}
 762
 763/**
 764 * tb_domain_disconnect_all_paths() - Disconnect all paths for the domain
 765 * @tb: Domain whose paths are disconnected
 766 *
 767 * This function can be used to disconnect all paths (PCIe, XDomain) for
 768 * example in preparation for host NVM firmware upgrade. After this is
 769 * called the paths cannot be established without resetting the switch.
 770 *
 771 * Return: %0 in case of success and negative errno otherwise.
 772 */
 773int tb_domain_disconnect_all_paths(struct tb *tb)
 774{
 775        int ret;
 776
 777        ret = tb_domain_disconnect_pcie_paths(tb);
 778        if (ret)
 779                return ret;
 780
 781        return bus_for_each_dev(&tb_bus_type, NULL, tb, disconnect_xdomain);
 782}
 783
 784int tb_domain_init(void)
 785{
 786        int ret;
 787
 788        ret = tb_xdomain_init();
 789        if (ret)
 790                return ret;
 791        ret = bus_register(&tb_bus_type);
 792        if (ret)
 793                tb_xdomain_exit();
 794
 795        return ret;
 796}
 797
 798void tb_domain_exit(void)
 799{
 800        bus_unregister(&tb_bus_type);
 801        ida_destroy(&tb_domain_ida);
 802        tb_switch_exit();
 803        tb_xdomain_exit();
 804}
 805