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