| .. | .. |
|---|
| 1 | +// SPDX-License-Identifier: GPL-2.0 |
|---|
| 1 | 2 | /* |
|---|
| 2 | 3 | * Thunderbolt XDomain discovery protocol support |
|---|
| 3 | 4 | * |
|---|
| 4 | 5 | * Copyright (C) 2017, Intel Corporation |
|---|
| 5 | 6 | * Authors: Michael Jamet <michael.jamet@intel.com> |
|---|
| 6 | 7 | * Mika Westerberg <mika.westerberg@linux.intel.com> |
|---|
| 7 | | - * |
|---|
| 8 | | - * This program is free software; you can redistribute it and/or modify |
|---|
| 9 | | - * it under the terms of the GNU General Public License version 2 as |
|---|
| 10 | | - * published by the Free Software Foundation. |
|---|
| 11 | 8 | */ |
|---|
| 12 | 9 | |
|---|
| 13 | 10 | #include <linux/device.h> |
|---|
| .. | .. |
|---|
| 21 | 18 | #include "tb.h" |
|---|
| 22 | 19 | |
|---|
| 23 | 20 | #define XDOMAIN_DEFAULT_TIMEOUT 5000 /* ms */ |
|---|
| 21 | +#define XDOMAIN_UUID_RETRIES 10 |
|---|
| 24 | 22 | #define XDOMAIN_PROPERTIES_RETRIES 60 |
|---|
| 25 | 23 | #define XDOMAIN_PROPERTIES_CHANGED_RETRIES 10 |
|---|
| 26 | 24 | |
|---|
| .. | .. |
|---|
| 223 | 221 | } |
|---|
| 224 | 222 | |
|---|
| 225 | 223 | return 0; |
|---|
| 224 | +} |
|---|
| 225 | + |
|---|
| 226 | +static int tb_xdp_uuid_request(struct tb_ctl *ctl, u64 route, int retry, |
|---|
| 227 | + uuid_t *uuid) |
|---|
| 228 | +{ |
|---|
| 229 | + struct tb_xdp_uuid_response res; |
|---|
| 230 | + struct tb_xdp_uuid req; |
|---|
| 231 | + int ret; |
|---|
| 232 | + |
|---|
| 233 | + memset(&req, 0, sizeof(req)); |
|---|
| 234 | + tb_xdp_fill_header(&req.hdr, route, retry % 4, UUID_REQUEST, |
|---|
| 235 | + sizeof(req)); |
|---|
| 236 | + |
|---|
| 237 | + memset(&res, 0, sizeof(res)); |
|---|
| 238 | + ret = __tb_xdomain_request(ctl, &req, sizeof(req), |
|---|
| 239 | + TB_CFG_PKG_XDOMAIN_REQ, &res, sizeof(res), |
|---|
| 240 | + TB_CFG_PKG_XDOMAIN_RESP, |
|---|
| 241 | + XDOMAIN_DEFAULT_TIMEOUT); |
|---|
| 242 | + if (ret) |
|---|
| 243 | + return ret; |
|---|
| 244 | + |
|---|
| 245 | + ret = tb_xdp_handle_error(&res.hdr); |
|---|
| 246 | + if (ret) |
|---|
| 247 | + return ret; |
|---|
| 248 | + |
|---|
| 249 | + uuid_copy(uuid, &res.src_uuid); |
|---|
| 250 | + return 0; |
|---|
| 251 | +} |
|---|
| 252 | + |
|---|
| 253 | +static int tb_xdp_uuid_response(struct tb_ctl *ctl, u64 route, u8 sequence, |
|---|
| 254 | + const uuid_t *uuid) |
|---|
| 255 | +{ |
|---|
| 256 | + struct tb_xdp_uuid_response res; |
|---|
| 257 | + |
|---|
| 258 | + memset(&res, 0, sizeof(res)); |
|---|
| 259 | + tb_xdp_fill_header(&res.hdr, route, sequence, UUID_RESPONSE, |
|---|
| 260 | + sizeof(res)); |
|---|
| 261 | + |
|---|
| 262 | + uuid_copy(&res.src_uuid, uuid); |
|---|
| 263 | + res.src_route_hi = upper_32_bits(route); |
|---|
| 264 | + res.src_route_lo = lower_32_bits(route); |
|---|
| 265 | + |
|---|
| 266 | + return __tb_xdomain_response(ctl, &res, sizeof(res), |
|---|
| 267 | + TB_CFG_PKG_XDOMAIN_RESP); |
|---|
| 226 | 268 | } |
|---|
| 227 | 269 | |
|---|
| 228 | 270 | static int tb_xdp_error_response(struct tb_ctl *ctl, u64 route, u8 sequence, |
|---|
| .. | .. |
|---|
| 459 | 501 | } |
|---|
| 460 | 502 | EXPORT_SYMBOL_GPL(tb_unregister_protocol_handler); |
|---|
| 461 | 503 | |
|---|
| 504 | +static int rebuild_property_block(void) |
|---|
| 505 | +{ |
|---|
| 506 | + u32 *block, len; |
|---|
| 507 | + int ret; |
|---|
| 508 | + |
|---|
| 509 | + ret = tb_property_format_dir(xdomain_property_dir, NULL, 0); |
|---|
| 510 | + if (ret < 0) |
|---|
| 511 | + return ret; |
|---|
| 512 | + |
|---|
| 513 | + len = ret; |
|---|
| 514 | + |
|---|
| 515 | + block = kcalloc(len, sizeof(u32), GFP_KERNEL); |
|---|
| 516 | + if (!block) |
|---|
| 517 | + return -ENOMEM; |
|---|
| 518 | + |
|---|
| 519 | + ret = tb_property_format_dir(xdomain_property_dir, block, len); |
|---|
| 520 | + if (ret) { |
|---|
| 521 | + kfree(block); |
|---|
| 522 | + return ret; |
|---|
| 523 | + } |
|---|
| 524 | + |
|---|
| 525 | + kfree(xdomain_property_block); |
|---|
| 526 | + xdomain_property_block = block; |
|---|
| 527 | + xdomain_property_block_len = len; |
|---|
| 528 | + xdomain_property_block_gen++; |
|---|
| 529 | + |
|---|
| 530 | + return 0; |
|---|
| 531 | +} |
|---|
| 532 | + |
|---|
| 533 | +static void finalize_property_block(void) |
|---|
| 534 | +{ |
|---|
| 535 | + const struct tb_property *nodename; |
|---|
| 536 | + |
|---|
| 537 | + /* |
|---|
| 538 | + * On first XDomain connection we set up the the system |
|---|
| 539 | + * nodename. This delayed here because userspace may not have it |
|---|
| 540 | + * set when the driver is first probed. |
|---|
| 541 | + */ |
|---|
| 542 | + mutex_lock(&xdomain_lock); |
|---|
| 543 | + nodename = tb_property_find(xdomain_property_dir, "deviceid", |
|---|
| 544 | + TB_PROPERTY_TYPE_TEXT); |
|---|
| 545 | + if (!nodename) { |
|---|
| 546 | + tb_property_add_text(xdomain_property_dir, "deviceid", |
|---|
| 547 | + utsname()->nodename); |
|---|
| 548 | + rebuild_property_block(); |
|---|
| 549 | + } |
|---|
| 550 | + mutex_unlock(&xdomain_lock); |
|---|
| 551 | +} |
|---|
| 552 | + |
|---|
| 462 | 553 | static void tb_xdp_handle_request(struct work_struct *work) |
|---|
| 463 | 554 | { |
|---|
| 464 | 555 | struct xdomain_request_work *xw = container_of(work, typeof(*xw), work); |
|---|
| .. | .. |
|---|
| 486 | 577 | tb_xdp_error_response(ctl, route, sequence, ERROR_NOT_READY); |
|---|
| 487 | 578 | goto out; |
|---|
| 488 | 579 | } |
|---|
| 580 | + |
|---|
| 581 | + finalize_property_block(); |
|---|
| 489 | 582 | |
|---|
| 490 | 583 | switch (pkg->type) { |
|---|
| 491 | 584 | case PROPERTIES_REQUEST: |
|---|
| .. | .. |
|---|
| 515 | 608 | break; |
|---|
| 516 | 609 | } |
|---|
| 517 | 610 | |
|---|
| 611 | + case UUID_REQUEST_OLD: |
|---|
| 612 | + case UUID_REQUEST: |
|---|
| 613 | + ret = tb_xdp_uuid_response(ctl, route, sequence, uuid); |
|---|
| 614 | + break; |
|---|
| 615 | + |
|---|
| 518 | 616 | default: |
|---|
| 617 | + tb_xdp_error_response(ctl, route, sequence, |
|---|
| 618 | + ERROR_NOT_SUPPORTED); |
|---|
| 519 | 619 | break; |
|---|
| 520 | 620 | } |
|---|
| 521 | 621 | |
|---|
| .. | .. |
|---|
| 527 | 627 | out: |
|---|
| 528 | 628 | kfree(xw->pkg); |
|---|
| 529 | 629 | kfree(xw); |
|---|
| 630 | + |
|---|
| 631 | + tb_domain_put(tb); |
|---|
| 530 | 632 | } |
|---|
| 531 | 633 | |
|---|
| 532 | | -static void |
|---|
| 634 | +static bool |
|---|
| 533 | 635 | tb_xdp_schedule_request(struct tb *tb, const struct tb_xdp_header *hdr, |
|---|
| 534 | 636 | size_t size) |
|---|
| 535 | 637 | { |
|---|
| .. | .. |
|---|
| 537 | 639 | |
|---|
| 538 | 640 | xw = kmalloc(sizeof(*xw), GFP_KERNEL); |
|---|
| 539 | 641 | if (!xw) |
|---|
| 540 | | - return; |
|---|
| 642 | + return false; |
|---|
| 541 | 643 | |
|---|
| 542 | 644 | INIT_WORK(&xw->work, tb_xdp_handle_request); |
|---|
| 543 | 645 | xw->pkg = kmemdup(hdr, size, GFP_KERNEL); |
|---|
| 544 | | - xw->tb = tb; |
|---|
| 646 | + if (!xw->pkg) { |
|---|
| 647 | + kfree(xw); |
|---|
| 648 | + return false; |
|---|
| 649 | + } |
|---|
| 650 | + xw->tb = tb_domain_get(tb); |
|---|
| 545 | 651 | |
|---|
| 546 | | - queue_work(tb->wq, &xw->work); |
|---|
| 652 | + schedule_work(&xw->work); |
|---|
| 653 | + return true; |
|---|
| 547 | 654 | } |
|---|
| 548 | 655 | |
|---|
| 549 | 656 | /** |
|---|
| .. | .. |
|---|
| 580 | 687 | * It should be null terminated but anything else is pretty much |
|---|
| 581 | 688 | * allowed. |
|---|
| 582 | 689 | */ |
|---|
| 583 | | - return sprintf(buf, "%*pEp\n", (int)strlen(svc->key), svc->key); |
|---|
| 690 | + return sprintf(buf, "%*pE\n", (int)strlen(svc->key), svc->key); |
|---|
| 584 | 691 | } |
|---|
| 585 | 692 | static DEVICE_ATTR_RO(key); |
|---|
| 586 | 693 | |
|---|
| .. | .. |
|---|
| 836 | 943 | } |
|---|
| 837 | 944 | } |
|---|
| 838 | 945 | |
|---|
| 946 | +static void tb_xdomain_get_uuid(struct work_struct *work) |
|---|
| 947 | +{ |
|---|
| 948 | + struct tb_xdomain *xd = container_of(work, typeof(*xd), |
|---|
| 949 | + get_uuid_work.work); |
|---|
| 950 | + struct tb *tb = xd->tb; |
|---|
| 951 | + uuid_t uuid; |
|---|
| 952 | + int ret; |
|---|
| 953 | + |
|---|
| 954 | + ret = tb_xdp_uuid_request(tb->ctl, xd->route, xd->uuid_retries, &uuid); |
|---|
| 955 | + if (ret < 0) { |
|---|
| 956 | + if (xd->uuid_retries-- > 0) { |
|---|
| 957 | + queue_delayed_work(xd->tb->wq, &xd->get_uuid_work, |
|---|
| 958 | + msecs_to_jiffies(100)); |
|---|
| 959 | + } else { |
|---|
| 960 | + dev_dbg(&xd->dev, "failed to read remote UUID\n"); |
|---|
| 961 | + } |
|---|
| 962 | + return; |
|---|
| 963 | + } |
|---|
| 964 | + |
|---|
| 965 | + if (uuid_equal(&uuid, xd->local_uuid)) { |
|---|
| 966 | + dev_dbg(&xd->dev, "intra-domain loop detected\n"); |
|---|
| 967 | + return; |
|---|
| 968 | + } |
|---|
| 969 | + |
|---|
| 970 | + /* |
|---|
| 971 | + * If the UUID is different, there is another domain connected |
|---|
| 972 | + * so mark this one unplugged and wait for the connection |
|---|
| 973 | + * manager to replace it. |
|---|
| 974 | + */ |
|---|
| 975 | + if (xd->remote_uuid && !uuid_equal(&uuid, xd->remote_uuid)) { |
|---|
| 976 | + dev_dbg(&xd->dev, "remote UUID is different, unplugging\n"); |
|---|
| 977 | + xd->is_unplugged = true; |
|---|
| 978 | + return; |
|---|
| 979 | + } |
|---|
| 980 | + |
|---|
| 981 | + /* First time fill in the missing UUID */ |
|---|
| 982 | + if (!xd->remote_uuid) { |
|---|
| 983 | + xd->remote_uuid = kmemdup(&uuid, sizeof(uuid_t), GFP_KERNEL); |
|---|
| 984 | + if (!xd->remote_uuid) |
|---|
| 985 | + return; |
|---|
| 986 | + } |
|---|
| 987 | + |
|---|
| 988 | + /* Now we can start the normal properties exchange */ |
|---|
| 989 | + queue_delayed_work(xd->tb->wq, &xd->properties_changed_work, |
|---|
| 990 | + msecs_to_jiffies(100)); |
|---|
| 991 | + queue_delayed_work(xd->tb->wq, &xd->get_properties_work, |
|---|
| 992 | + msecs_to_jiffies(1000)); |
|---|
| 993 | +} |
|---|
| 994 | + |
|---|
| 839 | 995 | static void tb_xdomain_get_properties(struct work_struct *work) |
|---|
| 840 | 996 | { |
|---|
| 841 | 997 | struct tb_xdomain *xd = container_of(work, typeof(*xd), |
|---|
| .. | .. |
|---|
| 1042 | 1198 | |
|---|
| 1043 | 1199 | static void start_handshake(struct tb_xdomain *xd) |
|---|
| 1044 | 1200 | { |
|---|
| 1201 | + xd->uuid_retries = XDOMAIN_UUID_RETRIES; |
|---|
| 1045 | 1202 | xd->properties_retries = XDOMAIN_PROPERTIES_RETRIES; |
|---|
| 1046 | 1203 | xd->properties_changed_retries = XDOMAIN_PROPERTIES_CHANGED_RETRIES; |
|---|
| 1047 | 1204 | |
|---|
| 1048 | | - /* Start exchanging properties with the other host */ |
|---|
| 1049 | | - queue_delayed_work(xd->tb->wq, &xd->properties_changed_work, |
|---|
| 1050 | | - msecs_to_jiffies(100)); |
|---|
| 1051 | | - queue_delayed_work(xd->tb->wq, &xd->get_properties_work, |
|---|
| 1052 | | - msecs_to_jiffies(1000)); |
|---|
| 1205 | + if (xd->needs_uuid) { |
|---|
| 1206 | + queue_delayed_work(xd->tb->wq, &xd->get_uuid_work, |
|---|
| 1207 | + msecs_to_jiffies(100)); |
|---|
| 1208 | + } else { |
|---|
| 1209 | + /* Start exchanging properties with the other host */ |
|---|
| 1210 | + queue_delayed_work(xd->tb->wq, &xd->properties_changed_work, |
|---|
| 1211 | + msecs_to_jiffies(100)); |
|---|
| 1212 | + queue_delayed_work(xd->tb->wq, &xd->get_properties_work, |
|---|
| 1213 | + msecs_to_jiffies(1000)); |
|---|
| 1214 | + } |
|---|
| 1053 | 1215 | } |
|---|
| 1054 | 1216 | |
|---|
| 1055 | 1217 | static void stop_handshake(struct tb_xdomain *xd) |
|---|
| 1056 | 1218 | { |
|---|
| 1219 | + xd->uuid_retries = 0; |
|---|
| 1057 | 1220 | xd->properties_retries = 0; |
|---|
| 1058 | 1221 | xd->properties_changed_retries = 0; |
|---|
| 1059 | 1222 | |
|---|
| 1223 | + cancel_delayed_work_sync(&xd->get_uuid_work); |
|---|
| 1060 | 1224 | cancel_delayed_work_sync(&xd->get_properties_work); |
|---|
| 1061 | 1225 | cancel_delayed_work_sync(&xd->properties_changed_work); |
|---|
| 1062 | 1226 | } |
|---|
| .. | .. |
|---|
| 1099 | 1263 | * other domain is reached). |
|---|
| 1100 | 1264 | * @route: Route string used to reach the other domain |
|---|
| 1101 | 1265 | * @local_uuid: Our local domain UUID |
|---|
| 1102 | | - * @remote_uuid: UUID of the other domain |
|---|
| 1266 | + * @remote_uuid: UUID of the other domain (optional) |
|---|
| 1103 | 1267 | * |
|---|
| 1104 | 1268 | * Allocates new XDomain structure and returns pointer to that. The |
|---|
| 1105 | 1269 | * object must be released by calling tb_xdomain_put(). |
|---|
| .. | .. |
|---|
| 1108 | 1272 | u64 route, const uuid_t *local_uuid, |
|---|
| 1109 | 1273 | const uuid_t *remote_uuid) |
|---|
| 1110 | 1274 | { |
|---|
| 1275 | + struct tb_switch *parent_sw = tb_to_switch(parent); |
|---|
| 1111 | 1276 | struct tb_xdomain *xd; |
|---|
| 1277 | + struct tb_port *down; |
|---|
| 1278 | + |
|---|
| 1279 | + /* Make sure the downstream domain is accessible */ |
|---|
| 1280 | + down = tb_port_at(route, parent_sw); |
|---|
| 1281 | + tb_port_unlock(down); |
|---|
| 1112 | 1282 | |
|---|
| 1113 | 1283 | xd = kzalloc(sizeof(*xd), GFP_KERNEL); |
|---|
| 1114 | 1284 | if (!xd) |
|---|
| .. | .. |
|---|
| 1118 | 1288 | xd->route = route; |
|---|
| 1119 | 1289 | ida_init(&xd->service_ids); |
|---|
| 1120 | 1290 | mutex_init(&xd->lock); |
|---|
| 1291 | + INIT_DELAYED_WORK(&xd->get_uuid_work, tb_xdomain_get_uuid); |
|---|
| 1121 | 1292 | INIT_DELAYED_WORK(&xd->get_properties_work, tb_xdomain_get_properties); |
|---|
| 1122 | 1293 | INIT_DELAYED_WORK(&xd->properties_changed_work, |
|---|
| 1123 | 1294 | tb_xdomain_properties_changed); |
|---|
| .. | .. |
|---|
| 1126 | 1297 | if (!xd->local_uuid) |
|---|
| 1127 | 1298 | goto err_free; |
|---|
| 1128 | 1299 | |
|---|
| 1129 | | - xd->remote_uuid = kmemdup(remote_uuid, sizeof(uuid_t), GFP_KERNEL); |
|---|
| 1130 | | - if (!xd->remote_uuid) |
|---|
| 1131 | | - goto err_free_local_uuid; |
|---|
| 1300 | + if (remote_uuid) { |
|---|
| 1301 | + xd->remote_uuid = kmemdup(remote_uuid, sizeof(uuid_t), |
|---|
| 1302 | + GFP_KERNEL); |
|---|
| 1303 | + if (!xd->remote_uuid) |
|---|
| 1304 | + goto err_free_local_uuid; |
|---|
| 1305 | + } else { |
|---|
| 1306 | + xd->needs_uuid = true; |
|---|
| 1307 | + } |
|---|
| 1132 | 1308 | |
|---|
| 1133 | 1309 | device_initialize(&xd->dev); |
|---|
| 1134 | 1310 | xd->dev.parent = get_device(parent); |
|---|
| .. | .. |
|---|
| 1286 | 1462 | static struct tb_xdomain *switch_find_xdomain(struct tb_switch *sw, |
|---|
| 1287 | 1463 | const struct tb_xdomain_lookup *lookup) |
|---|
| 1288 | 1464 | { |
|---|
| 1289 | | - int i; |
|---|
| 1465 | + struct tb_port *port; |
|---|
| 1290 | 1466 | |
|---|
| 1291 | | - for (i = 1; i <= sw->config.max_port_number; i++) { |
|---|
| 1292 | | - struct tb_port *port = &sw->ports[i]; |
|---|
| 1467 | + tb_switch_for_each_port(sw, port) { |
|---|
| 1293 | 1468 | struct tb_xdomain *xd; |
|---|
| 1294 | | - |
|---|
| 1295 | | - if (tb_is_upstream_port(port)) |
|---|
| 1296 | | - continue; |
|---|
| 1297 | 1469 | |
|---|
| 1298 | 1470 | if (port->xdomain) { |
|---|
| 1299 | 1471 | xd = port->xdomain; |
|---|
| 1300 | 1472 | |
|---|
| 1301 | 1473 | if (lookup->uuid) { |
|---|
| 1302 | | - if (uuid_equal(xd->remote_uuid, lookup->uuid)) |
|---|
| 1474 | + if (xd->remote_uuid && |
|---|
| 1475 | + uuid_equal(xd->remote_uuid, lookup->uuid)) |
|---|
| 1303 | 1476 | return xd; |
|---|
| 1304 | 1477 | } else if (lookup->link && |
|---|
| 1305 | 1478 | lookup->link == xd->link && |
|---|
| .. | .. |
|---|
| 1309 | 1482 | lookup->route == xd->route) { |
|---|
| 1310 | 1483 | return xd; |
|---|
| 1311 | 1484 | } |
|---|
| 1312 | | - } else if (port->remote) { |
|---|
| 1485 | + } else if (tb_port_has_remote(port)) { |
|---|
| 1313 | 1486 | xd = switch_find_xdomain(port->remote->sw, lookup); |
|---|
| 1314 | 1487 | if (xd) |
|---|
| 1315 | 1488 | return xd; |
|---|
| .. | .. |
|---|
| 1426 | 1599 | * handlers in turn. |
|---|
| 1427 | 1600 | */ |
|---|
| 1428 | 1601 | if (uuid_equal(&hdr->uuid, &tb_xdp_uuid)) { |
|---|
| 1429 | | - if (type == TB_CFG_PKG_XDOMAIN_REQ) { |
|---|
| 1430 | | - tb_xdp_schedule_request(tb, hdr, size); |
|---|
| 1431 | | - return true; |
|---|
| 1432 | | - } |
|---|
| 1602 | + if (type == TB_CFG_PKG_XDOMAIN_REQ) |
|---|
| 1603 | + return tb_xdp_schedule_request(tb, hdr, size); |
|---|
| 1433 | 1604 | return false; |
|---|
| 1434 | 1605 | } |
|---|
| 1435 | 1606 | |
|---|
| .. | .. |
|---|
| 1448 | 1619 | mutex_unlock(&xdomain_lock); |
|---|
| 1449 | 1620 | |
|---|
| 1450 | 1621 | return ret > 0; |
|---|
| 1451 | | -} |
|---|
| 1452 | | - |
|---|
| 1453 | | -static int rebuild_property_block(void) |
|---|
| 1454 | | -{ |
|---|
| 1455 | | - u32 *block, len; |
|---|
| 1456 | | - int ret; |
|---|
| 1457 | | - |
|---|
| 1458 | | - ret = tb_property_format_dir(xdomain_property_dir, NULL, 0); |
|---|
| 1459 | | - if (ret < 0) |
|---|
| 1460 | | - return ret; |
|---|
| 1461 | | - |
|---|
| 1462 | | - len = ret; |
|---|
| 1463 | | - |
|---|
| 1464 | | - block = kcalloc(len, sizeof(u32), GFP_KERNEL); |
|---|
| 1465 | | - if (!block) |
|---|
| 1466 | | - return -ENOMEM; |
|---|
| 1467 | | - |
|---|
| 1468 | | - ret = tb_property_format_dir(xdomain_property_dir, block, len); |
|---|
| 1469 | | - if (ret) { |
|---|
| 1470 | | - kfree(block); |
|---|
| 1471 | | - return ret; |
|---|
| 1472 | | - } |
|---|
| 1473 | | - |
|---|
| 1474 | | - kfree(xdomain_property_block); |
|---|
| 1475 | | - xdomain_property_block = block; |
|---|
| 1476 | | - xdomain_property_block_len = len; |
|---|
| 1477 | | - xdomain_property_block_gen++; |
|---|
| 1478 | | - |
|---|
| 1479 | | - return 0; |
|---|
| 1480 | 1622 | } |
|---|
| 1481 | 1623 | |
|---|
| 1482 | 1624 | static int update_xdomain(struct device *dev, void *data) |
|---|
| .. | .. |
|---|
| 1583 | 1725 | |
|---|
| 1584 | 1726 | int tb_xdomain_init(void) |
|---|
| 1585 | 1727 | { |
|---|
| 1586 | | - int ret; |
|---|
| 1587 | | - |
|---|
| 1588 | 1728 | xdomain_property_dir = tb_property_create_dir(NULL); |
|---|
| 1589 | 1729 | if (!xdomain_property_dir) |
|---|
| 1590 | 1730 | return -ENOMEM; |
|---|
| .. | .. |
|---|
| 1593 | 1733 | * Initialize standard set of properties without any service |
|---|
| 1594 | 1734 | * directories. Those will be added by service drivers |
|---|
| 1595 | 1735 | * themselves when they are loaded. |
|---|
| 1736 | + * |
|---|
| 1737 | + * We also add node name later when first connection is made. |
|---|
| 1596 | 1738 | */ |
|---|
| 1597 | 1739 | tb_property_add_immediate(xdomain_property_dir, "vendorid", |
|---|
| 1598 | 1740 | PCI_VENDOR_ID_INTEL); |
|---|
| 1599 | 1741 | tb_property_add_text(xdomain_property_dir, "vendorid", "Intel Corp."); |
|---|
| 1600 | 1742 | tb_property_add_immediate(xdomain_property_dir, "deviceid", 0x1); |
|---|
| 1601 | | - tb_property_add_text(xdomain_property_dir, "deviceid", |
|---|
| 1602 | | - utsname()->nodename); |
|---|
| 1603 | 1743 | tb_property_add_immediate(xdomain_property_dir, "devicerv", 0x80000100); |
|---|
| 1604 | 1744 | |
|---|
| 1605 | | - ret = rebuild_property_block(); |
|---|
| 1606 | | - if (ret) { |
|---|
| 1607 | | - tb_property_free_dir(xdomain_property_dir); |
|---|
| 1608 | | - xdomain_property_dir = NULL; |
|---|
| 1609 | | - } |
|---|
| 1610 | | - |
|---|
| 1611 | | - return ret; |
|---|
| 1745 | + return 0; |
|---|
| 1612 | 1746 | } |
|---|
| 1613 | 1747 | |
|---|
| 1614 | 1748 | void tb_xdomain_exit(void) |
|---|