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