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