1 /* 2 * Intel(R) Trace Hub driver core 3 * 4 * Copyright (C) 2014-2015 Intel Corporation. 5 * 6 * This program is free software; you can redistribute it and/or modify it 7 * under the terms and conditions of the GNU General Public License, 8 * version 2, as published by the Free Software Foundation. 9 * 10 * This program is distributed in the hope it will be useful, but WITHOUT 11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 13 * more details. 14 */ 15 16 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 17 18 #include <linux/types.h> 19 #include <linux/module.h> 20 #include <linux/device.h> 21 #include <linux/sysfs.h> 22 #include <linux/kdev_t.h> 23 #include <linux/debugfs.h> 24 #include <linux/idr.h> 25 #include <linux/pci.h> 26 #include <linux/pm_runtime.h> 27 #include <linux/dma-mapping.h> 28 29 #include "intel_th.h" 30 #include "debug.h" 31 32 static bool host_mode __read_mostly; 33 module_param(host_mode, bool, 0444); 34 35 static DEFINE_IDA(intel_th_ida); 36 37 static int intel_th_match(struct device *dev, struct device_driver *driver) 38 { 39 struct intel_th_driver *thdrv = to_intel_th_driver(driver); 40 struct intel_th_device *thdev = to_intel_th_device(dev); 41 42 if (thdev->type == INTEL_TH_SWITCH && 43 (!thdrv->enable || !thdrv->disable)) 44 return 0; 45 46 return !strcmp(thdev->name, driver->name); 47 } 48 49 static int intel_th_child_remove(struct device *dev, void *data) 50 { 51 device_release_driver(dev); 52 53 return 0; 54 } 55 56 static int intel_th_probe(struct device *dev) 57 { 58 struct intel_th_driver *thdrv = to_intel_th_driver(dev->driver); 59 struct intel_th_device *thdev = to_intel_th_device(dev); 60 struct intel_th_driver *hubdrv; 61 struct intel_th_device *hub = NULL; 62 int ret; 63 64 if (thdev->type == INTEL_TH_SWITCH) 65 hub = thdev; 66 else if (dev->parent) 67 hub = to_intel_th_device(dev->parent); 68 69 if (!hub || !hub->dev.driver) 70 return -EPROBE_DEFER; 71 72 hubdrv = to_intel_th_driver(hub->dev.driver); 73 74 pm_runtime_set_active(dev); 75 pm_runtime_no_callbacks(dev); 76 pm_runtime_enable(dev); 77 78 ret = thdrv->probe(to_intel_th_device(dev)); 79 if (ret) 80 goto out_pm; 81 82 if (thdrv->attr_group) { 83 ret = sysfs_create_group(&thdev->dev.kobj, thdrv->attr_group); 84 if (ret) 85 goto out; 86 } 87 88 if (thdev->type == INTEL_TH_OUTPUT && 89 !intel_th_output_assigned(thdev)) 90 /* does not talk to hardware */ 91 ret = hubdrv->assign(hub, thdev); 92 93 out: 94 if (ret) 95 thdrv->remove(thdev); 96 97 out_pm: 98 if (ret) 99 pm_runtime_disable(dev); 100 101 return ret; 102 } 103 104 static int intel_th_remove(struct device *dev) 105 { 106 struct intel_th_driver *thdrv = to_intel_th_driver(dev->driver); 107 struct intel_th_device *thdev = to_intel_th_device(dev); 108 struct intel_th_device *hub = to_intel_th_device(dev->parent); 109 int err; 110 111 if (thdev->type == INTEL_TH_SWITCH) { 112 err = device_for_each_child(dev, thdev, intel_th_child_remove); 113 if (err) 114 return err; 115 } 116 117 if (thdrv->attr_group) 118 sysfs_remove_group(&thdev->dev.kobj, thdrv->attr_group); 119 120 pm_runtime_get_sync(dev); 121 122 thdrv->remove(thdev); 123 124 if (intel_th_output_assigned(thdev)) { 125 struct intel_th_driver *hubdrv = 126 to_intel_th_driver(dev->parent->driver); 127 128 if (hub->dev.driver) 129 /* does not talk to hardware */ 130 hubdrv->unassign(hub, thdev); 131 } 132 133 pm_runtime_disable(dev); 134 pm_runtime_set_active(dev); 135 pm_runtime_enable(dev); 136 137 return 0; 138 } 139 140 static struct bus_type intel_th_bus = { 141 .name = "intel_th", 142 .dev_attrs = NULL, 143 .match = intel_th_match, 144 .probe = intel_th_probe, 145 .remove = intel_th_remove, 146 }; 147 148 static void intel_th_device_free(struct intel_th_device *thdev); 149 150 static void intel_th_device_release(struct device *dev) 151 { 152 intel_th_device_free(to_intel_th_device(dev)); 153 } 154 155 static struct device_type intel_th_source_device_type = { 156 .name = "intel_th_source_device", 157 .release = intel_th_device_release, 158 }; 159 160 static struct intel_th *to_intel_th(struct intel_th_device *thdev) 161 { 162 /* 163 * subdevice tree is flat: if this one is not a switch, its 164 * parent must be 165 */ 166 if (thdev->type != INTEL_TH_SWITCH) 167 thdev = to_intel_th_hub(thdev); 168 169 if (WARN_ON_ONCE(!thdev || thdev->type != INTEL_TH_SWITCH)) 170 return NULL; 171 172 return dev_get_drvdata(thdev->dev.parent); 173 } 174 175 static char *intel_th_output_devnode(struct device *dev, umode_t *mode, 176 kuid_t *uid, kgid_t *gid) 177 { 178 struct intel_th_device *thdev = to_intel_th_device(dev); 179 struct intel_th *th = to_intel_th(thdev); 180 char *node; 181 182 if (thdev->id >= 0) 183 node = kasprintf(GFP_KERNEL, "intel_th%d/%s%d", th->id, 184 thdev->name, thdev->id); 185 else 186 node = kasprintf(GFP_KERNEL, "intel_th%d/%s", th->id, 187 thdev->name); 188 189 return node; 190 } 191 192 static ssize_t port_show(struct device *dev, struct device_attribute *attr, 193 char *buf) 194 { 195 struct intel_th_device *thdev = to_intel_th_device(dev); 196 197 if (thdev->output.port >= 0) 198 return scnprintf(buf, PAGE_SIZE, "%u\n", thdev->output.port); 199 200 return scnprintf(buf, PAGE_SIZE, "unassigned\n"); 201 } 202 203 static DEVICE_ATTR_RO(port); 204 205 static int intel_th_output_activate(struct intel_th_device *thdev) 206 { 207 struct intel_th_driver *thdrv = 208 to_intel_th_driver_or_null(thdev->dev.driver); 209 int ret = 0; 210 211 if (!thdrv) 212 return -ENODEV; 213 214 if (!try_module_get(thdrv->driver.owner)) 215 return -ENODEV; 216 217 pm_runtime_get_sync(&thdev->dev); 218 219 if (thdrv->activate) 220 ret = thdrv->activate(thdev); 221 else 222 intel_th_trace_enable(thdev); 223 224 if (ret) { 225 pm_runtime_put(&thdev->dev); 226 module_put(thdrv->driver.owner); 227 } 228 229 return ret; 230 } 231 232 static void intel_th_output_deactivate(struct intel_th_device *thdev) 233 { 234 struct intel_th_driver *thdrv = 235 to_intel_th_driver_or_null(thdev->dev.driver); 236 237 if (!thdrv) 238 return; 239 240 if (thdrv->deactivate) 241 thdrv->deactivate(thdev); 242 else 243 intel_th_trace_disable(thdev); 244 245 pm_runtime_put(&thdev->dev); 246 module_put(thdrv->driver.owner); 247 } 248 249 static ssize_t active_show(struct device *dev, struct device_attribute *attr, 250 char *buf) 251 { 252 struct intel_th_device *thdev = to_intel_th_device(dev); 253 254 return scnprintf(buf, PAGE_SIZE, "%d\n", thdev->output.active); 255 } 256 257 static ssize_t active_store(struct device *dev, struct device_attribute *attr, 258 const char *buf, size_t size) 259 { 260 struct intel_th_device *thdev = to_intel_th_device(dev); 261 unsigned long val; 262 int ret; 263 264 ret = kstrtoul(buf, 10, &val); 265 if (ret) 266 return ret; 267 268 if (!!val != thdev->output.active) { 269 if (val) 270 ret = intel_th_output_activate(thdev); 271 else 272 intel_th_output_deactivate(thdev); 273 } 274 275 return ret ? ret : size; 276 } 277 278 static DEVICE_ATTR_RW(active); 279 280 static struct attribute *intel_th_output_attrs[] = { 281 &dev_attr_port.attr, 282 &dev_attr_active.attr, 283 NULL, 284 }; 285 286 ATTRIBUTE_GROUPS(intel_th_output); 287 288 static struct device_type intel_th_output_device_type = { 289 .name = "intel_th_output_device", 290 .groups = intel_th_output_groups, 291 .release = intel_th_device_release, 292 .devnode = intel_th_output_devnode, 293 }; 294 295 static struct device_type intel_th_switch_device_type = { 296 .name = "intel_th_switch_device", 297 .release = intel_th_device_release, 298 }; 299 300 static struct device_type *intel_th_device_type[] = { 301 [INTEL_TH_SOURCE] = &intel_th_source_device_type, 302 [INTEL_TH_OUTPUT] = &intel_th_output_device_type, 303 [INTEL_TH_SWITCH] = &intel_th_switch_device_type, 304 }; 305 306 int intel_th_driver_register(struct intel_th_driver *thdrv) 307 { 308 if (!thdrv->probe || !thdrv->remove) 309 return -EINVAL; 310 311 thdrv->driver.bus = &intel_th_bus; 312 313 return driver_register(&thdrv->driver); 314 } 315 EXPORT_SYMBOL_GPL(intel_th_driver_register); 316 317 void intel_th_driver_unregister(struct intel_th_driver *thdrv) 318 { 319 driver_unregister(&thdrv->driver); 320 } 321 EXPORT_SYMBOL_GPL(intel_th_driver_unregister); 322 323 static struct intel_th_device * 324 intel_th_device_alloc(struct intel_th *th, unsigned int type, const char *name, 325 int id) 326 { 327 struct device *parent; 328 struct intel_th_device *thdev; 329 330 if (type == INTEL_TH_SWITCH) 331 parent = th->dev; 332 else 333 parent = &th->hub->dev; 334 335 thdev = kzalloc(sizeof(*thdev) + strlen(name) + 1, GFP_KERNEL); 336 if (!thdev) 337 return NULL; 338 339 thdev->id = id; 340 thdev->type = type; 341 342 strcpy(thdev->name, name); 343 device_initialize(&thdev->dev); 344 thdev->dev.bus = &intel_th_bus; 345 thdev->dev.type = intel_th_device_type[type]; 346 thdev->dev.parent = parent; 347 thdev->dev.dma_mask = parent->dma_mask; 348 thdev->dev.dma_parms = parent->dma_parms; 349 dma_set_coherent_mask(&thdev->dev, parent->coherent_dma_mask); 350 if (id >= 0) 351 dev_set_name(&thdev->dev, "%d-%s%d", th->id, name, id); 352 else 353 dev_set_name(&thdev->dev, "%d-%s", th->id, name); 354 355 return thdev; 356 } 357 358 static int intel_th_device_add_resources(struct intel_th_device *thdev, 359 struct resource *res, int nres) 360 { 361 struct resource *r; 362 363 r = kmemdup(res, sizeof(*res) * nres, GFP_KERNEL); 364 if (!r) 365 return -ENOMEM; 366 367 thdev->resource = r; 368 thdev->num_resources = nres; 369 370 return 0; 371 } 372 373 static void intel_th_device_remove(struct intel_th_device *thdev) 374 { 375 device_del(&thdev->dev); 376 put_device(&thdev->dev); 377 } 378 379 static void intel_th_device_free(struct intel_th_device *thdev) 380 { 381 kfree(thdev->resource); 382 kfree(thdev); 383 } 384 385 /* 386 * Intel(R) Trace Hub subdevices 387 */ 388 static const struct intel_th_subdevice { 389 const char *name; 390 struct resource res[3]; 391 unsigned nres; 392 unsigned type; 393 unsigned otype; 394 unsigned scrpd; 395 int id; 396 } intel_th_subdevices[TH_SUBDEVICE_MAX] = { 397 { 398 .nres = 1, 399 .res = { 400 { 401 .start = REG_GTH_OFFSET, 402 .end = REG_GTH_OFFSET + REG_GTH_LENGTH - 1, 403 .flags = IORESOURCE_MEM, 404 }, 405 }, 406 .name = "gth", 407 .type = INTEL_TH_SWITCH, 408 .id = -1, 409 }, 410 { 411 .nres = 2, 412 .res = { 413 { 414 .start = REG_MSU_OFFSET, 415 .end = REG_MSU_OFFSET + REG_MSU_LENGTH - 1, 416 .flags = IORESOURCE_MEM, 417 }, 418 { 419 .start = BUF_MSU_OFFSET, 420 .end = BUF_MSU_OFFSET + BUF_MSU_LENGTH - 1, 421 .flags = IORESOURCE_MEM, 422 }, 423 }, 424 .name = "msc", 425 .id = 0, 426 .type = INTEL_TH_OUTPUT, 427 .otype = GTH_MSU, 428 .scrpd = SCRPD_MEM_IS_PRIM_DEST | SCRPD_MSC0_IS_ENABLED, 429 }, 430 { 431 .nres = 2, 432 .res = { 433 { 434 .start = REG_MSU_OFFSET, 435 .end = REG_MSU_OFFSET + REG_MSU_LENGTH - 1, 436 .flags = IORESOURCE_MEM, 437 }, 438 { 439 .start = BUF_MSU_OFFSET, 440 .end = BUF_MSU_OFFSET + BUF_MSU_LENGTH - 1, 441 .flags = IORESOURCE_MEM, 442 }, 443 }, 444 .name = "msc", 445 .id = 1, 446 .type = INTEL_TH_OUTPUT, 447 .otype = GTH_MSU, 448 .scrpd = SCRPD_MEM_IS_PRIM_DEST | SCRPD_MSC1_IS_ENABLED, 449 }, 450 { 451 .nres = 2, 452 .res = { 453 { 454 .start = REG_STH_OFFSET, 455 .end = REG_STH_OFFSET + REG_STH_LENGTH - 1, 456 .flags = IORESOURCE_MEM, 457 }, 458 { 459 .start = TH_MMIO_SW, 460 .end = 0, 461 .flags = IORESOURCE_MEM, 462 }, 463 }, 464 .id = -1, 465 .name = "sth", 466 .type = INTEL_TH_SOURCE, 467 }, 468 { 469 .nres = 1, 470 .res = { 471 { 472 .start = REG_PTI_OFFSET, 473 .end = REG_PTI_OFFSET + REG_PTI_LENGTH - 1, 474 .flags = IORESOURCE_MEM, 475 }, 476 }, 477 .id = -1, 478 .name = "pti", 479 .type = INTEL_TH_OUTPUT, 480 .otype = GTH_PTI, 481 .scrpd = SCRPD_PTI_IS_PRIM_DEST, 482 }, 483 { 484 .nres = 1, 485 .res = { 486 { 487 .start = REG_DCIH_OFFSET, 488 .end = REG_DCIH_OFFSET + REG_DCIH_LENGTH - 1, 489 .flags = IORESOURCE_MEM, 490 }, 491 }, 492 .id = -1, 493 .name = "dcih", 494 .type = INTEL_TH_OUTPUT, 495 }, 496 }; 497 498 #ifdef CONFIG_MODULES 499 static void __intel_th_request_hub_module(struct work_struct *work) 500 { 501 struct intel_th *th = container_of(work, struct intel_th, 502 request_module_work); 503 504 request_module("intel_th_%s", th->hub->name); 505 } 506 507 static int intel_th_request_hub_module(struct intel_th *th) 508 { 509 INIT_WORK(&th->request_module_work, __intel_th_request_hub_module); 510 schedule_work(&th->request_module_work); 511 512 return 0; 513 } 514 515 static void intel_th_request_hub_module_flush(struct intel_th *th) 516 { 517 flush_work(&th->request_module_work); 518 } 519 #else 520 static inline int intel_th_request_hub_module(struct intel_th *th) 521 { 522 return -EINVAL; 523 } 524 525 static inline void intel_th_request_hub_module_flush(struct intel_th *th) 526 { 527 } 528 #endif /* CONFIG_MODULES */ 529 530 static int intel_th_populate(struct intel_th *th, struct resource *devres, 531 unsigned int ndevres, int irq) 532 { 533 struct resource res[3]; 534 unsigned int req = 0; 535 int src, dst, err; 536 537 /* create devices for each intel_th_subdevice */ 538 for (src = 0, dst = 0; src < ARRAY_SIZE(intel_th_subdevices); src++) { 539 const struct intel_th_subdevice *subdev = 540 &intel_th_subdevices[src]; 541 struct intel_th_device *thdev; 542 int r; 543 544 /* only allow SOURCE and SWITCH devices in host mode */ 545 if (host_mode && subdev->type == INTEL_TH_OUTPUT) 546 continue; 547 548 thdev = intel_th_device_alloc(th, subdev->type, subdev->name, 549 subdev->id); 550 if (!thdev) { 551 err = -ENOMEM; 552 goto kill_subdevs; 553 } 554 555 memcpy(res, subdev->res, 556 sizeof(struct resource) * subdev->nres); 557 558 for (r = 0; r < subdev->nres; r++) { 559 int bar = TH_MMIO_CONFIG; 560 561 /* 562 * Take .end == 0 to mean 'take the whole bar', 563 * .start then tells us which bar it is. Default to 564 * TH_MMIO_CONFIG. 565 */ 566 if (!res[r].end && res[r].flags == IORESOURCE_MEM) { 567 bar = res[r].start; 568 res[r].start = 0; 569 res[r].end = resource_size(&devres[bar]) - 1; 570 } 571 572 if (res[r].flags & IORESOURCE_MEM) { 573 res[r].start += devres[bar].start; 574 res[r].end += devres[bar].start; 575 576 dev_dbg(th->dev, "%s:%d @ %pR\n", 577 subdev->name, r, &res[r]); 578 } else if (res[r].flags & IORESOURCE_IRQ) { 579 res[r].start = irq; 580 } 581 } 582 583 err = intel_th_device_add_resources(thdev, res, subdev->nres); 584 if (err) { 585 put_device(&thdev->dev); 586 goto kill_subdevs; 587 } 588 589 if (subdev->type == INTEL_TH_OUTPUT) { 590 thdev->dev.devt = MKDEV(th->major, dst); 591 thdev->output.type = subdev->otype; 592 thdev->output.port = -1; 593 thdev->output.scratchpad = subdev->scrpd; 594 } else if (subdev->type == INTEL_TH_SWITCH) { 595 thdev->host_mode = host_mode; 596 } 597 598 err = device_add(&thdev->dev); 599 if (err) { 600 put_device(&thdev->dev); 601 goto kill_subdevs; 602 } 603 604 /* need switch driver to be loaded to enumerate the rest */ 605 if (subdev->type == INTEL_TH_SWITCH && !req) { 606 th->hub = thdev; 607 err = intel_th_request_hub_module(th); 608 if (!err) 609 req++; 610 } 611 612 th->thdev[dst++] = thdev; 613 } 614 615 return 0; 616 617 kill_subdevs: 618 for (; dst >= 0; dst--) 619 intel_th_device_remove(th->thdev[dst]); 620 621 return err; 622 } 623 624 static int match_devt(struct device *dev, void *data) 625 { 626 dev_t devt = (dev_t)(unsigned long)data; 627 628 return dev->devt == devt; 629 } 630 631 static int intel_th_output_open(struct inode *inode, struct file *file) 632 { 633 const struct file_operations *fops; 634 struct intel_th_driver *thdrv; 635 struct device *dev; 636 int err; 637 638 dev = bus_find_device(&intel_th_bus, NULL, 639 (void *)(unsigned long)inode->i_rdev, 640 match_devt); 641 if (!dev || !dev->driver) 642 return -ENODEV; 643 644 thdrv = to_intel_th_driver(dev->driver); 645 fops = fops_get(thdrv->fops); 646 if (!fops) 647 return -ENODEV; 648 649 replace_fops(file, fops); 650 651 file->private_data = to_intel_th_device(dev); 652 653 if (file->f_op->open) { 654 err = file->f_op->open(inode, file); 655 return err; 656 } 657 658 return 0; 659 } 660 661 static const struct file_operations intel_th_output_fops = { 662 .open = intel_th_output_open, 663 .llseek = noop_llseek, 664 }; 665 666 /** 667 * intel_th_alloc() - allocate a new Intel TH device and its subdevices 668 * @dev: parent device 669 * @devres: parent's resources 670 * @ndevres: number of resources 671 * @irq: irq number 672 */ 673 struct intel_th * 674 intel_th_alloc(struct device *dev, struct resource *devres, 675 unsigned int ndevres, int irq) 676 { 677 struct intel_th *th; 678 int err; 679 680 th = kzalloc(sizeof(*th), GFP_KERNEL); 681 if (!th) 682 return ERR_PTR(-ENOMEM); 683 684 th->id = ida_simple_get(&intel_th_ida, 0, 0, GFP_KERNEL); 685 if (th->id < 0) { 686 err = th->id; 687 goto err_alloc; 688 } 689 690 th->major = __register_chrdev(0, 0, TH_POSSIBLE_OUTPUTS, 691 "intel_th/output", &intel_th_output_fops); 692 if (th->major < 0) { 693 err = th->major; 694 goto err_ida; 695 } 696 th->dev = dev; 697 698 dev_set_drvdata(dev, th); 699 700 pm_runtime_no_callbacks(dev); 701 pm_runtime_put(dev); 702 pm_runtime_allow(dev); 703 704 err = intel_th_populate(th, devres, ndevres, irq); 705 if (err) 706 goto err_chrdev; 707 708 return th; 709 710 err_chrdev: 711 pm_runtime_forbid(dev); 712 713 __unregister_chrdev(th->major, 0, TH_POSSIBLE_OUTPUTS, 714 "intel_th/output"); 715 716 err_ida: 717 ida_simple_remove(&intel_th_ida, th->id); 718 719 err_alloc: 720 kfree(th); 721 722 return ERR_PTR(err); 723 } 724 EXPORT_SYMBOL_GPL(intel_th_alloc); 725 726 void intel_th_free(struct intel_th *th) 727 { 728 int i; 729 730 intel_th_request_hub_module_flush(th); 731 for (i = 0; i < TH_SUBDEVICE_MAX; i++) 732 if (th->thdev[i] && th->thdev[i] != th->hub) 733 intel_th_device_remove(th->thdev[i]); 734 735 intel_th_device_remove(th->hub); 736 737 pm_runtime_get_sync(th->dev); 738 pm_runtime_forbid(th->dev); 739 740 __unregister_chrdev(th->major, 0, TH_POSSIBLE_OUTPUTS, 741 "intel_th/output"); 742 743 ida_simple_remove(&intel_th_ida, th->id); 744 745 kfree(th); 746 } 747 EXPORT_SYMBOL_GPL(intel_th_free); 748 749 /** 750 * intel_th_trace_enable() - enable tracing for an output device 751 * @thdev: output device that requests tracing be enabled 752 */ 753 int intel_th_trace_enable(struct intel_th_device *thdev) 754 { 755 struct intel_th_device *hub = to_intel_th_device(thdev->dev.parent); 756 struct intel_th_driver *hubdrv = to_intel_th_driver(hub->dev.driver); 757 758 if (WARN_ON_ONCE(hub->type != INTEL_TH_SWITCH)) 759 return -EINVAL; 760 761 if (WARN_ON_ONCE(thdev->type != INTEL_TH_OUTPUT)) 762 return -EINVAL; 763 764 pm_runtime_get_sync(&thdev->dev); 765 hubdrv->enable(hub, &thdev->output); 766 767 return 0; 768 } 769 EXPORT_SYMBOL_GPL(intel_th_trace_enable); 770 771 /** 772 * intel_th_trace_disable() - disable tracing for an output device 773 * @thdev: output device that requests tracing be disabled 774 */ 775 int intel_th_trace_disable(struct intel_th_device *thdev) 776 { 777 struct intel_th_device *hub = to_intel_th_device(thdev->dev.parent); 778 struct intel_th_driver *hubdrv = to_intel_th_driver(hub->dev.driver); 779 780 WARN_ON_ONCE(hub->type != INTEL_TH_SWITCH); 781 if (WARN_ON_ONCE(thdev->type != INTEL_TH_OUTPUT)) 782 return -EINVAL; 783 784 hubdrv->disable(hub, &thdev->output); 785 pm_runtime_put(&thdev->dev); 786 787 return 0; 788 } 789 EXPORT_SYMBOL_GPL(intel_th_trace_disable); 790 791 int intel_th_set_output(struct intel_th_device *thdev, 792 unsigned int master) 793 { 794 struct intel_th_device *hub = to_intel_th_device(thdev->dev.parent); 795 struct intel_th_driver *hubdrv = to_intel_th_driver(hub->dev.driver); 796 797 if (!hubdrv->set_output) 798 return -ENOTSUPP; 799 800 return hubdrv->set_output(hub, master); 801 } 802 EXPORT_SYMBOL_GPL(intel_th_set_output); 803 804 static int __init intel_th_init(void) 805 { 806 intel_th_debug_init(); 807 808 return bus_register(&intel_th_bus); 809 } 810 subsys_initcall(intel_th_init); 811 812 static void __exit intel_th_exit(void) 813 { 814 intel_th_debug_done(); 815 816 bus_unregister(&intel_th_bus); 817 } 818 module_exit(intel_th_exit); 819 820 MODULE_LICENSE("GPL v2"); 821 MODULE_DESCRIPTION("Intel(R) Trace Hub controller driver"); 822 MODULE_AUTHOR("Alexander Shishkin <alexander.shishkin@linux.intel.com>"); 823