1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Intel Vendor Specific Extended Capabilities auxiliary bus driver 4 * 5 * Copyright (c) 2021, Intel Corporation. 6 * All Rights Reserved. 7 * 8 * Author: David E. Box <david.e.box@linux.intel.com> 9 * 10 * This driver discovers and creates auxiliary devices for Intel defined PCIe 11 * "Vendor Specific" and "Designated Vendor Specific" Extended Capabilities, 12 * VSEC and DVSEC respectively. The driver supports features on specific PCIe 13 * endpoints that exist primarily to expose them. 14 */ 15 16 #include <linux/auxiliary_bus.h> 17 #include <linux/bits.h> 18 #include <linux/bitops.h> 19 #include <linux/bug.h> 20 #include <linux/cleanup.h> 21 #include <linux/delay.h> 22 #include <linux/idr.h> 23 #include <linux/log2.h> 24 #include <linux/intel_vsec.h> 25 #include <linux/kernel.h> 26 #include <linux/module.h> 27 #include <linux/overflow.h> 28 #include <linux/pci.h> 29 #include <linux/string.h> 30 #include <linux/types.h> 31 32 #define PMT_XA_START 0 33 #define PMT_XA_MAX INT_MAX 34 #define PMT_XA_LIMIT XA_LIMIT(PMT_XA_START, PMT_XA_MAX) 35 36 static DEFINE_IDA(intel_vsec_ida); 37 static DEFINE_IDA(intel_vsec_sdsi_ida); 38 static DEFINE_XARRAY_ALLOC(auxdev_array); 39 40 enum vsec_device_state { 41 STATE_NOT_FOUND, 42 STATE_REGISTERED, 43 STATE_SKIP, 44 }; 45 46 struct vsec_priv { 47 const struct intel_vsec_platform_info *info; 48 struct device *suppliers[VSEC_FEATURE_COUNT]; 49 struct oobmsm_plat_info plat_info; 50 enum vsec_device_state state[VSEC_FEATURE_COUNT]; 51 unsigned long found_caps; 52 }; 53 54 static const char *intel_vsec_name(enum intel_vsec_id id) 55 { 56 switch (id) { 57 case VSEC_ID_TELEMETRY: 58 return "telemetry"; 59 60 case VSEC_ID_WATCHER: 61 return "watcher"; 62 63 case VSEC_ID_CRASHLOG: 64 return "crashlog"; 65 66 case VSEC_ID_SDSI: 67 return "sdsi"; 68 69 case VSEC_ID_TPMI: 70 return "tpmi"; 71 72 case VSEC_ID_DISCOVERY: 73 return "discovery"; 74 75 default: 76 return NULL; 77 } 78 } 79 80 static bool intel_vsec_supported(u16 id, unsigned long caps) 81 { 82 switch (id) { 83 case VSEC_ID_TELEMETRY: 84 return !!(caps & VSEC_CAP_TELEMETRY); 85 case VSEC_ID_WATCHER: 86 return !!(caps & VSEC_CAP_WATCHER); 87 case VSEC_ID_CRASHLOG: 88 return !!(caps & VSEC_CAP_CRASHLOG); 89 case VSEC_ID_SDSI: 90 return !!(caps & VSEC_CAP_SDSI); 91 case VSEC_ID_TPMI: 92 return !!(caps & VSEC_CAP_TPMI); 93 case VSEC_ID_DISCOVERY: 94 return !!(caps & VSEC_CAP_DISCOVERY); 95 default: 96 return false; 97 } 98 } 99 100 static void intel_vsec_remove_aux(void *data) 101 { 102 auxiliary_device_delete(data); 103 auxiliary_device_uninit(data); 104 } 105 106 static void intel_vsec_dev_free(struct intel_vsec_device *intel_vsec_dev) 107 { 108 kfree(intel_vsec_dev->acpi_disc); 109 kfree(intel_vsec_dev); 110 } 111 112 static void intel_vsec_dev_release(struct device *dev) 113 { 114 struct intel_vsec_device *intel_vsec_dev = dev_to_ivdev(dev); 115 116 xa_erase(&auxdev_array, intel_vsec_dev->id); 117 118 ida_free(intel_vsec_dev->ida, intel_vsec_dev->auxdev.id); 119 120 intel_vsec_dev_free(intel_vsec_dev); 121 } 122 123 static const struct vsec_feature_dependency * 124 get_consumer_dependencies(struct vsec_priv *priv, int cap_id) 125 { 126 const struct vsec_feature_dependency *deps = priv->info->deps; 127 int consumer_id = priv->info->num_deps; 128 129 if (!deps) 130 return NULL; 131 132 while (consumer_id--) 133 if (deps[consumer_id].feature == BIT(cap_id)) 134 return &deps[consumer_id]; 135 136 return NULL; 137 } 138 139 static bool vsec_driver_present(int cap_id) 140 { 141 unsigned long bit = BIT(cap_id); 142 143 switch (bit) { 144 case VSEC_CAP_TELEMETRY: 145 return IS_ENABLED(CONFIG_INTEL_PMT_TELEMETRY); 146 case VSEC_CAP_WATCHER: 147 return IS_ENABLED(CONFIG_INTEL_PMT_WATCHER); 148 case VSEC_CAP_CRASHLOG: 149 return IS_ENABLED(CONFIG_INTEL_PMT_CRASHLOG); 150 case VSEC_CAP_SDSI: 151 return IS_ENABLED(CONFIG_INTEL_SDSI); 152 case VSEC_CAP_TPMI: 153 return IS_ENABLED(CONFIG_INTEL_TPMI); 154 case VSEC_CAP_DISCOVERY: 155 return IS_ENABLED(CONFIG_INTEL_PMT_DISCOVERY); 156 default: 157 return false; 158 } 159 } 160 161 /* 162 * Although pci_device_id table is available in the pdev, this prototype is 163 * necessary because the code using it can be called by an exported API that 164 * might pass a different pdev. 165 */ 166 static const struct pci_device_id intel_vsec_pci_ids[]; 167 168 static int intel_vsec_link_devices(struct device *parent, struct device *dev, 169 int consumer_id) 170 { 171 const struct vsec_feature_dependency *deps; 172 enum vsec_device_state *state; 173 struct device **suppliers; 174 struct vsec_priv *priv; 175 struct pci_dev *pdev; 176 int supplier_id; 177 178 if (!consumer_id) 179 return 0; 180 181 if (!dev_is_pci(parent)) 182 return 0; 183 184 pdev = to_pci_dev(parent); 185 if (!pci_match_id(intel_vsec_pci_ids, pdev)) 186 return 0; 187 188 priv = pci_get_drvdata(pdev); 189 state = priv->state; 190 suppliers = priv->suppliers; 191 192 priv->suppliers[consumer_id] = dev; 193 194 deps = get_consumer_dependencies(priv, consumer_id); 195 if (!deps) 196 return 0; 197 198 for_each_set_bit(supplier_id, &deps->supplier_bitmap, VSEC_FEATURE_COUNT) { 199 struct device_link *link; 200 201 if (state[supplier_id] != STATE_REGISTERED || 202 !vsec_driver_present(supplier_id)) 203 continue; 204 205 if (!suppliers[supplier_id]) { 206 dev_err(dev, "Bad supplier list\n"); 207 return -EINVAL; 208 } 209 210 link = device_link_add(dev, suppliers[supplier_id], 211 DL_FLAG_AUTOPROBE_CONSUMER); 212 if (!link) 213 return -EINVAL; 214 } 215 216 return 0; 217 } 218 219 int intel_vsec_add_aux(struct device *parent, 220 struct intel_vsec_device *intel_vsec_dev, 221 const char *name) 222 { 223 struct auxiliary_device *auxdev = &intel_vsec_dev->auxdev; 224 int ret, id; 225 226 if (!parent) { 227 intel_vsec_dev_free(intel_vsec_dev); 228 return -EINVAL; 229 } 230 231 ret = xa_alloc(&auxdev_array, &intel_vsec_dev->id, intel_vsec_dev, 232 PMT_XA_LIMIT, GFP_KERNEL); 233 if (ret < 0) { 234 intel_vsec_dev_free(intel_vsec_dev); 235 return ret; 236 } 237 238 id = ida_alloc(intel_vsec_dev->ida, GFP_KERNEL); 239 if (id < 0) { 240 xa_erase(&auxdev_array, intel_vsec_dev->id); 241 intel_vsec_dev_free(intel_vsec_dev); 242 return id; 243 } 244 245 auxdev->id = id; 246 auxdev->name = name; 247 auxdev->dev.parent = parent; 248 auxdev->dev.release = intel_vsec_dev_release; 249 250 ret = auxiliary_device_init(auxdev); 251 if (ret < 0) { 252 intel_vsec_dev_release(&auxdev->dev); 253 return ret; 254 } 255 256 /* 257 * Assign a name now to ensure that the device link doesn't contain 258 * a null string for the consumer name. This is a problem when a supplier 259 * supplies more than one consumer and can lead to a duplicate name error 260 * when the link is created in sysfs. 261 */ 262 ret = dev_set_name(&auxdev->dev, "%s.%s.%d", KBUILD_MODNAME, auxdev->name, 263 auxdev->id); 264 if (ret) 265 goto cleanup_aux; 266 267 ret = intel_vsec_link_devices(parent, &auxdev->dev, intel_vsec_dev->cap_id); 268 if (ret) 269 goto cleanup_aux; 270 271 ret = auxiliary_device_add(auxdev); 272 if (ret) 273 goto cleanup_aux; 274 275 return devm_add_action_or_reset(parent, intel_vsec_remove_aux, 276 auxdev); 277 278 cleanup_aux: 279 auxiliary_device_uninit(auxdev); 280 return ret; 281 } 282 EXPORT_SYMBOL_NS_GPL(intel_vsec_add_aux, "INTEL_VSEC"); 283 284 static int intel_vsec_add_dev(struct device *dev, struct intel_vsec_header *header, 285 const struct intel_vsec_platform_info *info, 286 unsigned long cap_id, u64 base_addr) 287 { 288 struct intel_vsec_device __free(kfree) *intel_vsec_dev = NULL; 289 struct resource *res; 290 struct resource *tmp; 291 struct device *parent; 292 unsigned long quirks = info->quirks; 293 int i; 294 295 if (info->parent) 296 parent = info->parent; 297 else 298 parent = dev; 299 300 if (!intel_vsec_supported(header->id, info->caps)) 301 return -EINVAL; 302 303 if (!header->num_entries) { 304 dev_dbg(dev, "Invalid 0 entry count for header id %d\n", header->id); 305 return -EINVAL; 306 } 307 308 if (!header->entry_size) { 309 dev_dbg(dev, "Invalid 0 entry size for header id %d\n", header->id); 310 return -EINVAL; 311 } 312 313 intel_vsec_dev = kzalloc_flex(*intel_vsec_dev, resource, header->num_entries); 314 if (!intel_vsec_dev) 315 return -ENOMEM; 316 317 intel_vsec_dev->num_resources = header->num_entries; 318 res = intel_vsec_dev->resource; 319 320 if (quirks & VSEC_QUIRK_TABLE_SHIFT) 321 header->offset >>= TABLE_OFFSET_SHIFT; 322 323 /* 324 * The DVSEC/VSEC contains the starting offset and count for a block of 325 * discovery tables. Create a resource array of these tables to the 326 * auxiliary device driver. 327 */ 328 for (i = 0, tmp = res; i < header->num_entries; i++, tmp++) { 329 /* 330 * Skip resource mapping check for ACPI-based discovery 331 * since those tables are read from _DSD, not MMIO. 332 */ 333 if (info->src == INTEL_VSEC_DISC_ACPI) 334 break; 335 336 tmp->start = base_addr + header->offset + i * (header->entry_size * sizeof(u32)); 337 tmp->end = tmp->start + (header->entry_size * sizeof(u32)) - 1; 338 tmp->flags = IORESOURCE_MEM; 339 340 /* Check resource is not in use */ 341 if (!request_mem_region(tmp->start, resource_size(tmp), "")) 342 return -EBUSY; 343 344 release_mem_region(tmp->start, resource_size(tmp)); 345 } 346 347 intel_vsec_dev->dev = dev; 348 intel_vsec_dev->quirks = info->quirks; 349 intel_vsec_dev->base_addr = info->base_addr; 350 intel_vsec_dev->priv_data = info->priv_data; 351 intel_vsec_dev->cap_id = cap_id; 352 intel_vsec_dev->src = info->src; 353 354 if (info->src == INTEL_VSEC_DISC_ACPI) { 355 size_t bytes; 356 357 if (check_mul_overflow(intel_vsec_dev->num_resources, 358 sizeof(*info->acpi_disc), &bytes)) 359 return -EOVERFLOW; 360 361 intel_vsec_dev->acpi_disc = kmemdup(info->acpi_disc, bytes, GFP_KERNEL); 362 if (!intel_vsec_dev->acpi_disc) 363 return -ENOMEM; 364 } 365 366 if (header->id == VSEC_ID_SDSI) 367 intel_vsec_dev->ida = &intel_vsec_sdsi_ida; 368 else 369 intel_vsec_dev->ida = &intel_vsec_ida; 370 371 /* 372 * Pass the ownership of intel_vsec_dev and resource within it to 373 * intel_vsec_add_aux() 374 */ 375 return intel_vsec_add_aux(parent, no_free_ptr(intel_vsec_dev), 376 intel_vsec_name(header->id)); 377 } 378 379 static bool suppliers_ready(struct vsec_priv *priv, 380 const struct vsec_feature_dependency *consumer_deps, 381 int cap_id) 382 { 383 enum vsec_device_state *state = priv->state; 384 int supplier_id; 385 386 if (WARN_ON_ONCE(consumer_deps->feature != BIT(cap_id))) 387 return false; 388 389 /* 390 * Verify that all required suppliers have been found. Return false 391 * immediately if any are still missing. 392 */ 393 for_each_set_bit(supplier_id, &consumer_deps->supplier_bitmap, VSEC_FEATURE_COUNT) { 394 if (state[supplier_id] == STATE_SKIP) 395 continue; 396 397 if (state[supplier_id] == STATE_NOT_FOUND) 398 return false; 399 } 400 401 /* 402 * All suppliers have been found and the consumer is ready to be 403 * registered. 404 */ 405 return true; 406 } 407 408 static int get_cap_id(u32 header_id, unsigned long *cap_id) 409 { 410 switch (header_id) { 411 case VSEC_ID_TELEMETRY: 412 *cap_id = ilog2(VSEC_CAP_TELEMETRY); 413 break; 414 case VSEC_ID_WATCHER: 415 *cap_id = ilog2(VSEC_CAP_WATCHER); 416 break; 417 case VSEC_ID_CRASHLOG: 418 *cap_id = ilog2(VSEC_CAP_CRASHLOG); 419 break; 420 case VSEC_ID_SDSI: 421 *cap_id = ilog2(VSEC_CAP_SDSI); 422 break; 423 case VSEC_ID_TPMI: 424 *cap_id = ilog2(VSEC_CAP_TPMI); 425 break; 426 case VSEC_ID_DISCOVERY: 427 *cap_id = ilog2(VSEC_CAP_DISCOVERY); 428 break; 429 default: 430 return -EINVAL; 431 } 432 433 return 0; 434 } 435 436 static int intel_vsec_register_device(struct device *dev, 437 struct intel_vsec_header *header, 438 const struct intel_vsec_platform_info *info, 439 u64 base_addr) 440 { 441 const struct vsec_feature_dependency *consumer_deps; 442 struct vsec_priv *priv; 443 struct pci_dev *pdev; 444 unsigned long cap_id; 445 int ret; 446 447 ret = get_cap_id(header->id, &cap_id); 448 if (ret) 449 return ret; 450 451 /* 452 * Only track dependencies for devices probed by the VSEC driver. 453 * For others using the exported APIs, add the device directly. 454 */ 455 if (!dev_is_pci(dev)) 456 return intel_vsec_add_dev(dev, header, info, cap_id, base_addr); 457 458 pdev = to_pci_dev(dev); 459 if (!pci_match_id(intel_vsec_pci_ids, pdev)) 460 return intel_vsec_add_dev(dev, header, info, cap_id, base_addr); 461 462 priv = pci_get_drvdata(pdev); 463 if (priv->state[cap_id] == STATE_REGISTERED || 464 priv->state[cap_id] == STATE_SKIP) 465 return -EEXIST; 466 467 priv->found_caps |= BIT(cap_id); 468 469 if (!vsec_driver_present(cap_id)) { 470 priv->state[cap_id] = STATE_SKIP; 471 return -ENODEV; 472 } 473 474 consumer_deps = get_consumer_dependencies(priv, cap_id); 475 if (!consumer_deps || suppliers_ready(priv, consumer_deps, cap_id)) { 476 ret = intel_vsec_add_dev(dev, header, info, cap_id, base_addr); 477 if (ret) 478 priv->state[cap_id] = STATE_SKIP; 479 else 480 priv->state[cap_id] = STATE_REGISTERED; 481 482 return ret; 483 } 484 485 return -EAGAIN; 486 } 487 488 static int intel_vsec_walk_header(struct device *dev, 489 const struct intel_vsec_platform_info *info) 490 { 491 struct intel_vsec_header **header = info->headers; 492 u64 base_addr; 493 int ret; 494 495 for ( ; *header; header++) { 496 if (info->base_addr) { 497 base_addr = info->base_addr; 498 } else { 499 struct pci_dev *pdev; 500 501 if (!dev_is_pci(dev)) { 502 dev_err(dev, "non-PCI device without a base address\n"); 503 return -EINVAL; 504 } 505 506 pdev = to_pci_dev(dev); 507 base_addr = pci_resource_start(pdev, (*header)->tbir); 508 } 509 510 ret = intel_vsec_register_device(dev, *header, info, base_addr); 511 if (ret) 512 return ret; 513 } 514 515 return 0; 516 } 517 518 static bool intel_vsec_walk_dvsec(struct pci_dev *pdev, 519 const struct intel_vsec_platform_info *info) 520 { 521 bool have_devices = false; 522 int pos = 0; 523 524 do { 525 struct intel_vsec_header header; 526 u32 table, hdr; 527 u16 vid; 528 int ret; 529 530 pos = pci_find_next_ext_capability(pdev, pos, PCI_EXT_CAP_ID_DVSEC); 531 if (!pos) 532 break; 533 534 pci_read_config_dword(pdev, pos + PCI_DVSEC_HEADER1, &hdr); 535 vid = PCI_DVSEC_HEADER1_VID(hdr); 536 if (vid != PCI_VENDOR_ID_INTEL) 537 continue; 538 539 /* Support only revision 1 */ 540 header.rev = PCI_DVSEC_HEADER1_REV(hdr); 541 if (header.rev != 1) { 542 dev_info(&pdev->dev, "Unsupported DVSEC revision %d\n", header.rev); 543 continue; 544 } 545 546 header.length = PCI_DVSEC_HEADER1_LEN(hdr); 547 548 pci_read_config_byte(pdev, pos + INTEL_DVSEC_ENTRIES, &header.num_entries); 549 pci_read_config_byte(pdev, pos + INTEL_DVSEC_SIZE, &header.entry_size); 550 pci_read_config_dword(pdev, pos + INTEL_DVSEC_TABLE, &table); 551 552 header.tbir = INTEL_DVSEC_TABLE_BAR(table); 553 header.offset = INTEL_DVSEC_TABLE_OFFSET(table); 554 555 pci_read_config_dword(pdev, pos + PCI_DVSEC_HEADER2, &hdr); 556 header.id = PCI_DVSEC_HEADER2_ID(hdr); 557 558 ret = intel_vsec_register_device(&pdev->dev, &header, info, 559 pci_resource_start(pdev, header.tbir)); 560 if (ret) 561 continue; 562 563 have_devices = true; 564 } while (true); 565 566 return have_devices; 567 } 568 569 static bool intel_vsec_walk_vsec(struct pci_dev *pdev, 570 const struct intel_vsec_platform_info *info) 571 { 572 bool have_devices = false; 573 int pos = 0; 574 575 do { 576 struct intel_vsec_header header; 577 u32 table, hdr; 578 int ret; 579 580 pos = pci_find_next_ext_capability(pdev, pos, PCI_EXT_CAP_ID_VNDR); 581 if (!pos) 582 break; 583 584 pci_read_config_dword(pdev, pos + PCI_VNDR_HEADER, &hdr); 585 586 /* Support only revision 1 */ 587 header.rev = PCI_VNDR_HEADER_REV(hdr); 588 if (header.rev != 1) { 589 dev_info(&pdev->dev, "Unsupported VSEC revision %d\n", header.rev); 590 continue; 591 } 592 593 header.id = PCI_VNDR_HEADER_ID(hdr); 594 header.length = PCI_VNDR_HEADER_LEN(hdr); 595 596 /* entry, size, and table offset are the same as DVSEC */ 597 pci_read_config_byte(pdev, pos + INTEL_DVSEC_ENTRIES, &header.num_entries); 598 pci_read_config_byte(pdev, pos + INTEL_DVSEC_SIZE, &header.entry_size); 599 pci_read_config_dword(pdev, pos + INTEL_DVSEC_TABLE, &table); 600 601 header.tbir = INTEL_DVSEC_TABLE_BAR(table); 602 header.offset = INTEL_DVSEC_TABLE_OFFSET(table); 603 604 ret = intel_vsec_register_device(&pdev->dev, &header, info, 605 pci_resource_start(pdev, header.tbir)); 606 if (ret) 607 continue; 608 609 have_devices = true; 610 } while (true); 611 612 return have_devices; 613 } 614 615 int intel_vsec_register(struct device *dev, 616 const struct intel_vsec_platform_info *info) 617 { 618 if (!dev || !info || !info->headers) 619 return -EINVAL; 620 621 return intel_vsec_walk_header(dev, info); 622 } 623 EXPORT_SYMBOL_NS_GPL(intel_vsec_register, "INTEL_VSEC"); 624 625 static bool intel_vsec_get_features(struct pci_dev *pdev, 626 const struct intel_vsec_platform_info *info) 627 { 628 bool found = false; 629 630 /* 631 * Both DVSEC and VSEC capabilities can exist on the same device, 632 * so both intel_vsec_walk_dvsec() and intel_vsec_walk_vsec() must be 633 * called independently. Additionally, intel_vsec_walk_header() is 634 * needed for devices that do not have VSEC/DVSEC but provide the 635 * information via device_data. 636 */ 637 if (intel_vsec_walk_dvsec(pdev, info)) 638 found = true; 639 640 if (intel_vsec_walk_vsec(pdev, info)) 641 found = true; 642 643 if (info && (info->quirks & VSEC_QUIRK_NO_DVSEC) && 644 intel_vsec_walk_header(&pdev->dev, info)) 645 found = true; 646 647 return found; 648 } 649 650 static void intel_vsec_skip_missing_dependencies(struct pci_dev *pdev) 651 { 652 struct vsec_priv *priv = pci_get_drvdata(pdev); 653 const struct vsec_feature_dependency *deps = priv->info->deps; 654 int consumer_id = priv->info->num_deps; 655 656 while (consumer_id--) { 657 int supplier_id; 658 659 deps = &priv->info->deps[consumer_id]; 660 661 for_each_set_bit(supplier_id, &deps->supplier_bitmap, VSEC_FEATURE_COUNT) { 662 if (!(BIT(supplier_id) & priv->found_caps)) 663 priv->state[supplier_id] = STATE_SKIP; 664 } 665 } 666 } 667 668 static int intel_vsec_pci_init(struct pci_dev *pdev) 669 { 670 struct vsec_priv *priv = pci_get_drvdata(pdev); 671 const struct intel_vsec_platform_info *info = priv->info; 672 int run_once = 0; 673 bool found_any = false; 674 int num_caps; 675 676 num_caps = hweight_long(info->caps); 677 while (num_caps--) { 678 found_any |= intel_vsec_get_features(pdev, info); 679 680 if (priv->found_caps == info->caps) 681 break; 682 683 if (!run_once) { 684 intel_vsec_skip_missing_dependencies(pdev); 685 run_once = 1; 686 } 687 } 688 689 if (!found_any) 690 return -ENODEV; 691 692 return 0; 693 } 694 695 static int intel_vsec_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) 696 { 697 const struct intel_vsec_platform_info *info; 698 struct vsec_priv *priv; 699 int ret; 700 701 ret = pcim_enable_device(pdev); 702 if (ret) 703 return ret; 704 705 pci_save_state(pdev); 706 info = (const struct intel_vsec_platform_info *)id->driver_data; 707 if (!info) 708 return -EINVAL; 709 710 priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); 711 if (!priv) 712 return -ENOMEM; 713 714 priv->info = info; 715 pci_set_drvdata(pdev, priv); 716 717 return intel_vsec_pci_init(pdev); 718 } 719 720 int intel_vsec_set_mapping(struct oobmsm_plat_info *plat_info, 721 struct intel_vsec_device *vsec_dev) 722 { 723 struct vsec_priv *priv; 724 725 if (!dev_is_pci(vsec_dev->dev)) 726 return -ENODEV; 727 728 priv = pci_get_drvdata(to_pci_dev(vsec_dev->dev)); 729 if (!priv) 730 return -EINVAL; 731 732 priv->plat_info = *plat_info; 733 734 return 0; 735 } 736 EXPORT_SYMBOL_NS_GPL(intel_vsec_set_mapping, "INTEL_VSEC"); 737 738 struct oobmsm_plat_info *intel_vsec_get_mapping(struct pci_dev *pdev) 739 { 740 struct vsec_priv *priv; 741 742 if (!pci_match_id(intel_vsec_pci_ids, pdev)) 743 return ERR_PTR(-EINVAL); 744 745 priv = pci_get_drvdata(pdev); 746 if (!priv) 747 return ERR_PTR(-EINVAL); 748 749 return &priv->plat_info; 750 } 751 EXPORT_SYMBOL_NS_GPL(intel_vsec_get_mapping, "INTEL_VSEC"); 752 753 /* DG1 info */ 754 static struct intel_vsec_header dg1_header = { 755 .length = 0x10, 756 .id = 2, 757 .num_entries = 1, 758 .entry_size = 3, 759 .tbir = 0, 760 .offset = 0x466000, 761 }; 762 763 static struct intel_vsec_header *dg1_headers[] = { 764 &dg1_header, 765 NULL 766 }; 767 768 static const struct intel_vsec_platform_info dg1_info = { 769 .caps = VSEC_CAP_TELEMETRY, 770 .headers = dg1_headers, 771 .quirks = VSEC_QUIRK_NO_DVSEC | VSEC_QUIRK_EARLY_HW, 772 }; 773 774 /* MTL info */ 775 static const struct intel_vsec_platform_info mtl_info = { 776 .caps = VSEC_CAP_TELEMETRY, 777 }; 778 779 static const struct vsec_feature_dependency oobmsm_deps[] = { 780 { 781 .feature = VSEC_CAP_TELEMETRY, 782 .supplier_bitmap = VSEC_CAP_DISCOVERY | VSEC_CAP_TPMI, 783 }, 784 }; 785 786 /* OOBMSM info */ 787 static const struct intel_vsec_platform_info oobmsm_info = { 788 .caps = VSEC_CAP_TELEMETRY | VSEC_CAP_SDSI | VSEC_CAP_TPMI | 789 VSEC_CAP_DISCOVERY, 790 .deps = oobmsm_deps, 791 .num_deps = ARRAY_SIZE(oobmsm_deps), 792 }; 793 794 /* DMR OOBMSM info */ 795 static const struct intel_vsec_platform_info dmr_oobmsm_info = { 796 .caps = VSEC_CAP_TELEMETRY | VSEC_CAP_TPMI | VSEC_CAP_DISCOVERY, 797 .deps = oobmsm_deps, 798 .num_deps = ARRAY_SIZE(oobmsm_deps), 799 }; 800 801 /* TGL info */ 802 static const struct intel_vsec_platform_info tgl_info = { 803 .caps = VSEC_CAP_TELEMETRY, 804 .quirks = VSEC_QUIRK_TABLE_SHIFT | VSEC_QUIRK_EARLY_HW, 805 }; 806 807 /* LNL info */ 808 static const struct intel_vsec_platform_info lnl_info = { 809 .caps = VSEC_CAP_TELEMETRY | VSEC_CAP_WATCHER, 810 }; 811 812 #define PCI_DEVICE_ID_INTEL_VSEC_ADL 0x467d 813 #define PCI_DEVICE_ID_INTEL_VSEC_DG1 0x490e 814 #define PCI_DEVICE_ID_INTEL_VSEC_MTL_M 0x7d0d 815 #define PCI_DEVICE_ID_INTEL_VSEC_MTL_S 0xad0d 816 #define PCI_DEVICE_ID_INTEL_VSEC_OOBMSM 0x09a7 817 #define PCI_DEVICE_ID_INTEL_VSEC_OOBMSM_DMR 0x09a1 818 #define PCI_DEVICE_ID_INTEL_VSEC_RPL 0xa77d 819 #define PCI_DEVICE_ID_INTEL_VSEC_TGL 0x9a0d 820 #define PCI_DEVICE_ID_INTEL_VSEC_LNL_M 0x647d 821 #define PCI_DEVICE_ID_INTEL_VSEC_PTL 0xb07d 822 #define PCI_DEVICE_ID_INTEL_VSEC_WCL 0xfd7d 823 #define PCI_DEVICE_ID_INTEL_VSEC_NVL 0xd70d 824 static const struct pci_device_id intel_vsec_pci_ids[] = { 825 { PCI_DEVICE_DATA(INTEL, VSEC_ADL, &tgl_info) }, 826 { PCI_DEVICE_DATA(INTEL, VSEC_DG1, &dg1_info) }, 827 { PCI_DEVICE_DATA(INTEL, VSEC_MTL_M, &mtl_info) }, 828 { PCI_DEVICE_DATA(INTEL, VSEC_MTL_S, &mtl_info) }, 829 { PCI_DEVICE_DATA(INTEL, VSEC_OOBMSM, &oobmsm_info) }, 830 { PCI_DEVICE_DATA(INTEL, VSEC_OOBMSM_DMR, &dmr_oobmsm_info) }, 831 { PCI_DEVICE_DATA(INTEL, VSEC_RPL, &tgl_info) }, 832 { PCI_DEVICE_DATA(INTEL, VSEC_TGL, &tgl_info) }, 833 { PCI_DEVICE_DATA(INTEL, VSEC_LNL_M, &lnl_info) }, 834 { PCI_DEVICE_DATA(INTEL, VSEC_PTL, &mtl_info) }, 835 { PCI_DEVICE_DATA(INTEL, VSEC_WCL, &mtl_info) }, 836 { PCI_DEVICE_DATA(INTEL, VSEC_NVL, &mtl_info) }, 837 { } 838 }; 839 MODULE_DEVICE_TABLE(pci, intel_vsec_pci_ids); 840 841 static pci_ers_result_t intel_vsec_pci_error_detected(struct pci_dev *pdev, 842 pci_channel_state_t state) 843 { 844 pci_ers_result_t status = PCI_ERS_RESULT_NEED_RESET; 845 846 dev_info(&pdev->dev, "PCI error detected, state %d", state); 847 848 if (state == pci_channel_io_perm_failure) 849 status = PCI_ERS_RESULT_DISCONNECT; 850 else 851 pci_disable_device(pdev); 852 853 return status; 854 } 855 856 static pci_ers_result_t intel_vsec_pci_slot_reset(struct pci_dev *pdev) 857 { 858 struct intel_vsec_device *intel_vsec_dev; 859 pci_ers_result_t status = PCI_ERS_RESULT_DISCONNECT; 860 unsigned long index; 861 862 dev_info(&pdev->dev, "Resetting PCI slot\n"); 863 864 msleep(2000); 865 if (pci_enable_device(pdev)) { 866 dev_info(&pdev->dev, 867 "Failed to re-enable PCI device after reset.\n"); 868 goto out; 869 } 870 871 status = PCI_ERS_RESULT_RECOVERED; 872 873 xa_for_each(&auxdev_array, index, intel_vsec_dev) { 874 /* check if pdev doesn't match */ 875 if (&pdev->dev != intel_vsec_dev->dev) 876 continue; 877 devm_release_action(&pdev->dev, intel_vsec_remove_aux, 878 &intel_vsec_dev->auxdev); 879 } 880 pci_restore_state(pdev); 881 intel_vsec_pci_init(pdev); 882 883 out: 884 return status; 885 } 886 887 static void intel_vsec_pci_resume(struct pci_dev *pdev) 888 { 889 dev_info(&pdev->dev, "Done resuming PCI device\n"); 890 } 891 892 static const struct pci_error_handlers intel_vsec_pci_err_handlers = { 893 .error_detected = intel_vsec_pci_error_detected, 894 .slot_reset = intel_vsec_pci_slot_reset, 895 .resume = intel_vsec_pci_resume, 896 }; 897 898 static struct pci_driver intel_vsec_pci_driver = { 899 .name = "intel_vsec", 900 .id_table = intel_vsec_pci_ids, 901 .probe = intel_vsec_pci_probe, 902 .err_handler = &intel_vsec_pci_err_handlers, 903 }; 904 module_pci_driver(intel_vsec_pci_driver); 905 906 MODULE_AUTHOR("David E. Box <david.e.box@linux.intel.com>"); 907 MODULE_DESCRIPTION("Intel Extended Capabilities auxiliary bus driver"); 908 MODULE_LICENSE("GPL v2"); 909