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