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