summaryrefslogtreecommitdiffstats
path: root/drivers/platform/x86
diff options
context:
space:
mode:
authorDavid E. Box <david.e.box@linux.intel.com>2022-02-11 17:32:50 -0800
committerHans de Goede <hdegoede@redhat.com>2022-02-14 11:45:20 +0100
commit2546c60004309ede8e2d1d5341e0decd90e057bf (patch)
treee7fb3cd51509c07d555a6625bb5da31c231859cd /drivers/platform/x86
parentae707d0eb707b5fc658e870dbd8b21887b0a5240 (diff)
downloadlinux-stable-2546c60004309ede8e2d1d5341e0decd90e057bf.tar.gz
linux-stable-2546c60004309ede8e2d1d5341e0decd90e057bf.tar.bz2
linux-stable-2546c60004309ede8e2d1d5341e0decd90e057bf.zip
platform/x86: Add Intel Software Defined Silicon driver
Intel Software Defined Silicon (SDSi) is a post manufacturing mechanism for activating additional silicon features. Features are enabled through a license activation process. The SDSi driver provides a per socket, sysfs attribute interface for applications to perform 3 main provisioning functions: 1. Provision an Authentication Key Certificate (AKC), a key written to internal NVRAM that is used to authenticate a capability specific activation payload. 2. Provision a Capability Activation Payload (CAP), a token authenticated using the AKC and applied to the CPU configuration to activate a new feature. 3. Read the SDSi State Certificate, containing the CPU configuration state. The operations perform function specific mailbox commands that forward the requests to SDSi hardware to perform authentication of the payloads and enable the silicon configuration (to be made available after power cycling). The SDSi device itself is enumerated as an auxiliary device from the intel_vsec driver and as such has a build dependency on CONFIG_INTEL_VSEC. Link: https://github.com/intel/intel-sdsi Signed-off-by: David E. Box <david.e.box@linux.intel.com> Reviewed-by: Mark Gross <markgross@kernel.org> Link: https://lore.kernel.org/r/20220212013252.1293396-2-david.e.box@linux.intel.com Reviewed-by: Hans de Goede <hdegoede@redhat.com> Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Diffstat (limited to 'drivers/platform/x86')
-rw-r--r--drivers/platform/x86/intel/Kconfig12
-rw-r--r--drivers/platform/x86/intel/Makefile2
-rw-r--r--drivers/platform/x86/intel/sdsi.c574
-rw-r--r--drivers/platform/x86/intel/vsec.c12
4 files changed, 599 insertions, 1 deletions
diff --git a/drivers/platform/x86/intel/Kconfig b/drivers/platform/x86/intel/Kconfig
index 2d9b49eed33d..205ebb513b58 100644
--- a/drivers/platform/x86/intel/Kconfig
+++ b/drivers/platform/x86/intel/Kconfig
@@ -153,6 +153,18 @@ config INTEL_RST
firmware will copy the memory contents back to RAM and resume the OS
as usual.
+config INTEL_SDSI
+ tristate "Intel Software Defined Silicon Driver"
+ depends on INTEL_VSEC
+ depends on X86_64
+ help
+ This driver enables access to the Intel Software Defined Silicon
+ interface used to provision silicon features with an authentication
+ certificate and capability license.
+
+ To compile this driver as a module, choose M here: the module will
+ be called intel_sdsi.
+
config INTEL_SMARTCONNECT
tristate "Intel Smart Connect disabling driver"
depends on ACPI
diff --git a/drivers/platform/x86/intel/Makefile b/drivers/platform/x86/intel/Makefile
index 053edc457ccb..1a5cdba4c2d2 100644
--- a/drivers/platform/x86/intel/Makefile
+++ b/drivers/platform/x86/intel/Makefile
@@ -25,6 +25,8 @@ intel_int0002_vgpio-y := int0002_vgpio.o
obj-$(CONFIG_INTEL_INT0002_VGPIO) += intel_int0002_vgpio.o
intel_oaktrail-y := oaktrail.o
obj-$(CONFIG_INTEL_OAKTRAIL) += intel_oaktrail.o
+intel_sdsi-y := sdsi.o
+obj-$(CONFIG_INTEL_SDSI) += intel_sdsi.o
intel_vsec-y := vsec.o
obj-$(CONFIG_INTEL_VSEC) += intel_vsec.o
diff --git a/drivers/platform/x86/intel/sdsi.c b/drivers/platform/x86/intel/sdsi.c
new file mode 100644
index 000000000000..11d14cc0ff0a
--- /dev/null
+++ b/drivers/platform/x86/intel/sdsi.c
@@ -0,0 +1,574 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Intel Software Defined Silicon driver
+ *
+ * Copyright (c) 2022, Intel Corporation.
+ * All Rights Reserved.
+ *
+ * Author: "David E. Box" <david.e.box@linux.intel.com>
+ */
+
+#include <linux/auxiliary_bus.h>
+#include <linux/bits.h>
+#include <linux/bitfield.h>
+#include <linux/device.h>
+#include <linux/iopoll.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/slab.h>
+#include <linux/sysfs.h>
+#include <linux/types.h>
+#include <linux/uaccess.h>
+
+#include "vsec.h"
+
+#define ACCESS_TYPE_BARID 2
+#define ACCESS_TYPE_LOCAL 3
+
+#define SDSI_MIN_SIZE_DWORDS 276
+#define SDSI_SIZE_CONTROL 8
+#define SDSI_SIZE_MAILBOX 1024
+#define SDSI_SIZE_REGS 72
+#define SDSI_SIZE_CMD sizeof(u64)
+
+/*
+ * Write messages are currently up to the size of the mailbox
+ * while read messages are up to 4 times the size of the
+ * mailbox, sent in packets
+ */
+#define SDSI_SIZE_WRITE_MSG SDSI_SIZE_MAILBOX
+#define SDSI_SIZE_READ_MSG (SDSI_SIZE_MAILBOX * 4)
+
+#define SDSI_ENABLED_FEATURES_OFFSET 16
+#define SDSI_ENABLED BIT(3)
+#define SDSI_SOCKET_ID_OFFSET 64
+#define SDSI_SOCKET_ID GENMASK(3, 0)
+
+#define SDSI_MBOX_CMD_SUCCESS 0x40
+#define SDSI_MBOX_CMD_TIMEOUT 0x80
+
+#define MBOX_TIMEOUT_US 2000
+#define MBOX_TIMEOUT_ACQUIRE_US 1000
+#define MBOX_POLLING_PERIOD_US 100
+#define MBOX_MAX_PACKETS 4
+
+#define MBOX_OWNER_NONE 0x00
+#define MBOX_OWNER_INBAND 0x01
+
+#define CTRL_RUN_BUSY BIT(0)
+#define CTRL_READ_WRITE BIT(1)
+#define CTRL_SOM BIT(2)
+#define CTRL_EOM BIT(3)
+#define CTRL_OWNER GENMASK(5, 4)
+#define CTRL_COMPLETE BIT(6)
+#define CTRL_READY BIT(7)
+#define CTRL_STATUS GENMASK(15, 8)
+#define CTRL_PACKET_SIZE GENMASK(31, 16)
+#define CTRL_MSG_SIZE GENMASK(63, 48)
+
+#define DISC_TABLE_SIZE 12
+#define DT_ACCESS_TYPE GENMASK(3, 0)
+#define DT_SIZE GENMASK(27, 12)
+#define DT_TBIR GENMASK(2, 0)
+#define DT_OFFSET(v) ((v) & GENMASK(31, 3))
+
+enum sdsi_command {
+ SDSI_CMD_PROVISION_AKC = 0x04,
+ SDSI_CMD_PROVISION_CAP = 0x08,
+ SDSI_CMD_READ_STATE = 0x10,
+};
+
+struct sdsi_mbox_info {
+ u64 *payload;
+ u64 *buffer;
+ int size;
+};
+
+struct disc_table {
+ u32 access_info;
+ u32 guid;
+ u32 offset;
+};
+
+struct sdsi_priv {
+ struct mutex mb_lock; /* Mailbox access lock */
+ struct device *dev;
+ void __iomem *control_addr;
+ void __iomem *mbox_addr;
+ void __iomem *regs_addr;
+ u32 guid;
+ bool sdsi_enabled;
+};
+
+/* SDSi mailbox operations must be performed using 64bit mov instructions */
+static __always_inline void
+sdsi_memcpy64_toio(u64 __iomem *to, const u64 *from, size_t count_bytes)
+{
+ size_t count = count_bytes / sizeof(*to);
+ int i;
+
+ for (i = 0; i < count; i++)
+ writeq(from[i], &to[i]);
+}
+
+static __always_inline void
+sdsi_memcpy64_fromio(u64 *to, const u64 __iomem *from, size_t count_bytes)
+{
+ size_t count = count_bytes / sizeof(*to);
+ int i;
+
+ for (i = 0; i < count; i++)
+ to[i] = readq(&from[i]);
+}
+
+static inline void sdsi_complete_transaction(struct sdsi_priv *priv)
+{
+ u64 control = FIELD_PREP(CTRL_COMPLETE, 1);
+
+ lockdep_assert_held(&priv->mb_lock);
+ writeq(control, priv->control_addr);
+}
+
+static int sdsi_status_to_errno(u32 status)
+{
+ switch (status) {
+ case SDSI_MBOX_CMD_SUCCESS:
+ return 0;
+ case SDSI_MBOX_CMD_TIMEOUT:
+ return -ETIMEDOUT;
+ default:
+ return -EIO;
+ }
+}
+
+static int sdsi_mbox_cmd_read(struct sdsi_priv *priv, struct sdsi_mbox_info *info,
+ size_t *data_size)
+{
+ struct device *dev = priv->dev;
+ u32 total, loop, eom, status, message_size;
+ u64 control;
+ int ret;
+
+ lockdep_assert_held(&priv->mb_lock);
+
+ /* Format and send the read command */
+ control = FIELD_PREP(CTRL_EOM, 1) |
+ FIELD_PREP(CTRL_SOM, 1) |
+ FIELD_PREP(CTRL_RUN_BUSY, 1) |
+ FIELD_PREP(CTRL_PACKET_SIZE, info->size);
+ writeq(control, priv->control_addr);
+
+ /* For reads, data sizes that are larger than the mailbox size are read in packets. */
+ total = 0;
+ loop = 0;
+ do {
+ int offset = SDSI_SIZE_MAILBOX * loop;
+ void __iomem *addr = priv->mbox_addr + offset;
+ u64 *buf = info->buffer + offset / SDSI_SIZE_CMD;
+ u32 packet_size;
+
+ /* Poll on ready bit */
+ ret = readq_poll_timeout(priv->control_addr, control, control & CTRL_READY,
+ MBOX_POLLING_PERIOD_US, MBOX_TIMEOUT_US);
+ if (ret)
+ break;
+
+ eom = FIELD_GET(CTRL_EOM, control);
+ status = FIELD_GET(CTRL_STATUS, control);
+ packet_size = FIELD_GET(CTRL_PACKET_SIZE, control);
+ message_size = FIELD_GET(CTRL_MSG_SIZE, control);
+
+ ret = sdsi_status_to_errno(status);
+ if (ret)
+ break;
+
+ /* Only the last packet can be less than the mailbox size. */
+ if (!eom && packet_size != SDSI_SIZE_MAILBOX) {
+ dev_err(dev, "Invalid packet size\n");
+ ret = -EPROTO;
+ break;
+ }
+
+ if (packet_size > SDSI_SIZE_MAILBOX) {
+ dev_err(dev, "Packet size too large\n");
+ ret = -EPROTO;
+ break;
+ }
+
+ sdsi_memcpy64_fromio(buf, addr, round_up(packet_size, SDSI_SIZE_CMD));
+
+ total += packet_size;
+
+ sdsi_complete_transaction(priv);
+ } while (!eom && ++loop < MBOX_MAX_PACKETS);
+
+ if (ret) {
+ sdsi_complete_transaction(priv);
+ return ret;
+ }
+
+ if (!eom) {
+ dev_err(dev, "Exceeded read attempts\n");
+ return -EPROTO;
+ }
+
+ /* Message size check is only valid for multi-packet transfers */
+ if (loop && total != message_size)
+ dev_warn(dev, "Read count %u differs from expected count %u\n",
+ total, message_size);
+
+ *data_size = total;
+
+ return 0;
+}
+
+static int sdsi_mbox_cmd_write(struct sdsi_priv *priv, struct sdsi_mbox_info *info)
+{
+ u64 control;
+ u32 status;
+ int ret;
+
+ lockdep_assert_held(&priv->mb_lock);
+
+ /* Write rest of the payload */
+ sdsi_memcpy64_toio(priv->mbox_addr + SDSI_SIZE_CMD, info->payload + 1,
+ info->size - SDSI_SIZE_CMD);
+
+ /* Format and send the write command */
+ control = FIELD_PREP(CTRL_EOM, 1) |
+ FIELD_PREP(CTRL_SOM, 1) |
+ FIELD_PREP(CTRL_RUN_BUSY, 1) |
+ FIELD_PREP(CTRL_READ_WRITE, 1) |
+ FIELD_PREP(CTRL_PACKET_SIZE, info->size);
+ writeq(control, priv->control_addr);
+
+ /* Poll on run_busy bit */
+ ret = readq_poll_timeout(priv->control_addr, control, !(control & CTRL_RUN_BUSY),
+ MBOX_POLLING_PERIOD_US, MBOX_TIMEOUT_US);
+
+ if (ret)
+ goto release_mbox;
+
+ status = FIELD_GET(CTRL_STATUS, control);
+ ret = sdsi_status_to_errno(status);
+
+release_mbox:
+ sdsi_complete_transaction(priv);
+
+ return ret;
+}
+
+static int sdsi_mbox_acquire(struct sdsi_priv *priv, struct sdsi_mbox_info *info)
+{
+ u64 control;
+ u32 owner;
+ int ret;
+
+ lockdep_assert_held(&priv->mb_lock);
+
+ /* Check mailbox is available */
+ control = readq(priv->control_addr);
+ owner = FIELD_GET(CTRL_OWNER, control);
+ if (owner != MBOX_OWNER_NONE)
+ return -EBUSY;
+
+ /* Write first qword of payload */
+ writeq(info->payload[0], priv->mbox_addr);
+
+ /* Check for ownership */
+ ret = readq_poll_timeout(priv->control_addr, control,
+ FIELD_GET(CTRL_OWNER, control) & MBOX_OWNER_INBAND,
+ MBOX_POLLING_PERIOD_US, MBOX_TIMEOUT_ACQUIRE_US);
+
+ return ret;
+}
+
+static int sdsi_mbox_write(struct sdsi_priv *priv, struct sdsi_mbox_info *info)
+{
+ int ret;
+
+ lockdep_assert_held(&priv->mb_lock);
+
+ ret = sdsi_mbox_acquire(priv, info);
+ if (ret)
+ return ret;
+
+ return sdsi_mbox_cmd_write(priv, info);
+}
+
+static int sdsi_mbox_read(struct sdsi_priv *priv, struct sdsi_mbox_info *info, size_t *data_size)
+{
+ int ret;
+
+ lockdep_assert_held(&priv->mb_lock);
+
+ ret = sdsi_mbox_acquire(priv, info);
+ if (ret)
+ return ret;
+
+ return sdsi_mbox_cmd_read(priv, info, data_size);
+}
+
+static ssize_t sdsi_provision(struct sdsi_priv *priv, char *buf, size_t count,
+ enum sdsi_command command)
+{
+ struct sdsi_mbox_info info;
+ int ret;
+
+ if (!priv->sdsi_enabled)
+ return -EPERM;
+
+ if (count > (SDSI_SIZE_WRITE_MSG - SDSI_SIZE_CMD))
+ return -EOVERFLOW;
+
+ /* Qword aligned message + command qword */
+ info.size = round_up(count, SDSI_SIZE_CMD) + SDSI_SIZE_CMD;
+
+ info.payload = kzalloc(info.size, GFP_KERNEL);
+ if (!info.payload)
+ return -ENOMEM;
+
+ /* Copy message to payload buffer */
+ memcpy(info.payload, buf, count);
+
+ /* Command is last qword of payload buffer */
+ info.payload[(info.size - SDSI_SIZE_CMD) / SDSI_SIZE_CMD] = command;
+
+ ret = mutex_lock_interruptible(&priv->mb_lock);
+ if (ret)
+ goto free_payload;
+ ret = sdsi_mbox_write(priv, &info);
+ mutex_unlock(&priv->mb_lock);
+
+free_payload:
+ kfree(info.payload);
+
+ if (ret)
+ return ret;
+
+ return count;
+}
+
+static ssize_t provision_akc_write(struct file *filp, struct kobject *kobj,
+ struct bin_attribute *attr, char *buf, loff_t off,
+ size_t count)
+{
+ struct device *dev = kobj_to_dev(kobj);
+ struct sdsi_priv *priv = dev_get_drvdata(dev);
+
+ if (off)
+ return -ESPIPE;
+
+ return sdsi_provision(priv, buf, count, SDSI_CMD_PROVISION_AKC);
+}
+static BIN_ATTR_WO(provision_akc, SDSI_SIZE_WRITE_MSG);
+
+static ssize_t provision_cap_write(struct file *filp, struct kobject *kobj,
+ struct bin_attribute *attr, char *buf, loff_t off,
+ size_t count)
+{
+ struct device *dev = kobj_to_dev(kobj);
+ struct sdsi_priv *priv = dev_get_drvdata(dev);
+
+ if (off)
+ return -ESPIPE;
+
+ return sdsi_provision(priv, buf, count, SDSI_CMD_PROVISION_CAP);
+}
+static BIN_ATTR_WO(provision_cap, SDSI_SIZE_WRITE_MSG);
+
+static long state_certificate_read(struct file *filp, struct kobject *kobj,
+ struct bin_attribute *attr, char *buf, loff_t off,
+ size_t count)
+{
+ struct device *dev = kobj_to_dev(kobj);
+ struct sdsi_priv *priv = dev_get_drvdata(dev);
+ u64 command = SDSI_CMD_READ_STATE;
+ struct sdsi_mbox_info info;
+ size_t size;
+ int ret;
+
+ if (!priv->sdsi_enabled)
+ return -EPERM;
+
+ if (off)
+ return 0;
+
+ /* Buffer for return data */
+ info.buffer = kmalloc(SDSI_SIZE_READ_MSG, GFP_KERNEL);
+ if (!info.buffer)
+ return -ENOMEM;
+
+ info.payload = &command;
+ info.size = sizeof(command);
+
+ ret = mutex_lock_interruptible(&priv->mb_lock);
+ if (ret)
+ goto free_buffer;
+ ret = sdsi_mbox_read(priv, &info, &size);
+ mutex_unlock(&priv->mb_lock);
+ if (ret < 0)
+ goto free_buffer;
+
+ if (size > count)
+ size = count;
+
+ memcpy(buf, info.buffer, size);
+
+free_buffer:
+ kfree(info.buffer);
+
+ if (ret)
+ return ret;
+
+ return size;
+}
+static BIN_ATTR(state_certificate, 0400, state_certificate_read, NULL, SDSI_SIZE_READ_MSG);
+
+static ssize_t registers_read(struct file *filp, struct kobject *kobj,
+ struct bin_attribute *attr, char *buf, loff_t off,
+ size_t count)
+{
+ struct device *dev = kobj_to_dev(kobj);
+ struct sdsi_priv *priv = dev_get_drvdata(dev);
+ void __iomem *addr = priv->regs_addr;
+
+ memcpy_fromio(buf, addr + off, count);
+
+ return count;
+}
+static BIN_ATTR(registers, 0400, registers_read, NULL, SDSI_SIZE_REGS);
+
+static struct bin_attribute *sdsi_bin_attrs[] = {
+ &bin_attr_registers,
+ &bin_attr_state_certificate,
+ &bin_attr_provision_akc,
+ &bin_attr_provision_cap,
+ NULL
+};
+
+static ssize_t guid_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ struct sdsi_priv *priv = dev_get_drvdata(dev);
+
+ return sysfs_emit(buf, "0x%x\n", priv->guid);
+}
+static DEVICE_ATTR_RO(guid);
+
+static struct attribute *sdsi_attrs[] = {
+ &dev_attr_guid.attr,
+ NULL
+};
+
+static const struct attribute_group sdsi_group = {
+ .attrs = sdsi_attrs,
+ .bin_attrs = sdsi_bin_attrs,
+};
+__ATTRIBUTE_GROUPS(sdsi);
+
+static int sdsi_map_mbox_registers(struct sdsi_priv *priv, struct pci_dev *parent,
+ struct disc_table *disc_table, struct resource *disc_res)
+{
+ u32 access_type = FIELD_GET(DT_ACCESS_TYPE, disc_table->access_info);
+ u32 size = FIELD_GET(DT_SIZE, disc_table->access_info);
+ u32 tbir = FIELD_GET(DT_TBIR, disc_table->offset);
+ u32 offset = DT_OFFSET(disc_table->offset);
+ u32 features_offset;
+ struct resource res = {};
+
+ /* Starting location of SDSi MMIO region based on access type */
+ switch (access_type) {
+ case ACCESS_TYPE_LOCAL:
+ if (tbir) {
+ dev_err(priv->dev, "Unsupported BAR index %u for access type %u\n",
+ tbir, access_type);
+ return -EINVAL;
+ }
+
+ /*
+ * For access_type LOCAL, the base address is as follows:
+ * base address = end of discovery region + base offset + 1
+ */
+ res.start = disc_res->end + offset + 1;
+ break;
+
+ case ACCESS_TYPE_BARID:
+ res.start = pci_resource_start(parent, tbir) + offset;
+ break;
+
+ default:
+ dev_err(priv->dev, "Unrecognized access_type %u\n", access_type);
+ return -EINVAL;
+ }
+
+ res.end = res.start + size * sizeof(u32) - 1;
+ res.flags = IORESOURCE_MEM;
+
+ priv->control_addr = devm_ioremap_resource(priv->dev, &res);
+ if (IS_ERR(priv->control_addr))
+ return PTR_ERR(priv->control_addr);
+
+ priv->mbox_addr = priv->control_addr + SDSI_SIZE_CONTROL;
+ priv->regs_addr = priv->mbox_addr + SDSI_SIZE_MAILBOX;
+
+ features_offset = readq(priv->regs_addr + SDSI_ENABLED_FEATURES_OFFSET);
+ priv->sdsi_enabled = !!(features_offset & SDSI_ENABLED);
+
+ return 0;
+}
+
+static int sdsi_probe(struct auxiliary_device *auxdev, const struct auxiliary_device_id *id)
+{
+ struct intel_vsec_device *intel_cap_dev = auxdev_to_ivdev(auxdev);
+ struct disc_table disc_table;
+ struct resource *disc_res;
+ void __iomem *disc_addr;
+ struct sdsi_priv *priv;
+ int ret;
+
+ priv = devm_kzalloc(&auxdev->dev, sizeof(*priv), GFP_KERNEL);
+ if (!priv)
+ return -ENOMEM;
+
+ priv->dev = &auxdev->dev;
+ mutex_init(&priv->mb_lock);
+ auxiliary_set_drvdata(auxdev, priv);
+
+ /* Get the SDSi discovery table */
+ disc_res = &intel_cap_dev->resource[0];
+ disc_addr = devm_ioremap_resource(&auxdev->dev, disc_res);
+ if (IS_ERR(disc_addr))
+ return PTR_ERR(disc_addr);
+
+ memcpy_fromio(&disc_table, disc_addr, DISC_TABLE_SIZE);
+
+ priv->guid = disc_table.guid;
+
+ /* Map the SDSi mailbox registers */
+ ret = sdsi_map_mbox_registers(priv, intel_cap_dev->pcidev, &disc_table, disc_res);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
+static const struct auxiliary_device_id sdsi_aux_id_table[] = {
+ { .name = "intel_vsec.sdsi" },
+ {}
+};
+MODULE_DEVICE_TABLE(auxiliary, sdsi_aux_id_table);
+
+static struct auxiliary_driver sdsi_aux_driver = {
+ .driver = {
+ .dev_groups = sdsi_groups,
+ },
+ .id_table = sdsi_aux_id_table,
+ .probe = sdsi_probe,
+ /* No remove. All resources are handled under devm */
+};
+module_auxiliary_driver(sdsi_aux_driver);
+
+MODULE_AUTHOR("David E. Box <david.e.box@linux.intel.com>");
+MODULE_DESCRIPTION("Intel Software Defined Silicon driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/platform/x86/intel/vsec.c b/drivers/platform/x86/intel/vsec.c
index c3bdd75ed690..bed436bf181f 100644
--- a/drivers/platform/x86/intel/vsec.c
+++ b/drivers/platform/x86/intel/vsec.c
@@ -32,6 +32,7 @@
#define TABLE_OFFSET_SHIFT 3
static DEFINE_IDA(intel_vsec_ida);
+static DEFINE_IDA(intel_vsec_sdsi_ida);
/**
* struct intel_vsec_header - Common fields of Intel VSEC and DVSEC registers.
@@ -63,12 +64,14 @@ enum intel_vsec_id {
VSEC_ID_TELEMETRY = 2,
VSEC_ID_WATCHER = 3,
VSEC_ID_CRASHLOG = 4,
+ VSEC_ID_SDSI = 65,
};
static enum intel_vsec_id intel_vsec_allow_list[] = {
VSEC_ID_TELEMETRY,
VSEC_ID_WATCHER,
VSEC_ID_CRASHLOG,
+ VSEC_ID_SDSI,
};
static const char *intel_vsec_name(enum intel_vsec_id id)
@@ -83,6 +86,9 @@ static const char *intel_vsec_name(enum intel_vsec_id id)
case VSEC_ID_CRASHLOG:
return "crashlog";
+ case VSEC_ID_SDSI:
+ return "sdsi";
+
default:
return NULL;
}
@@ -211,7 +217,11 @@ static int intel_vsec_add_dev(struct pci_dev *pdev, struct intel_vsec_header *he
intel_vsec_dev->resource = res;
intel_vsec_dev->num_resources = header->num_entries;
intel_vsec_dev->quirks = quirks;
- intel_vsec_dev->ida = &intel_vsec_ida;
+
+ if (header->id == VSEC_ID_SDSI)
+ intel_vsec_dev->ida = &intel_vsec_sdsi_ida;
+ else
+ intel_vsec_dev->ida = &intel_vsec_ida;
return intel_vsec_add_aux(pdev, intel_vsec_dev, intel_vsec_name(header->id));
}