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