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