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