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