[RFC PATCH 3/8] mei: Add IAF mei component
Maarten Lankhorst
dev at lankhorst.se
Fri Jun 13 13:45:22 UTC 2025
>From the backport repository.
Signed-off-by: Maarten Lankhorst <dev at lankhorst.se>
---
drivers/misc/mei/Kconfig | 1 +
drivers/misc/mei/Makefile | 1 +
drivers/misc/mei/iaf/Kconfig | 12 +
drivers/misc/mei/iaf/Makefile | 7 +
drivers/misc/mei/iaf/mei_iaf.c | 292 +++++++++++++++++++++
drivers/misc/mei/mkhi.h | 2 +
include/drm/intel/i915_mei_iaf_interface.h | 25 ++
7 files changed, 340 insertions(+)
create mode 100644 drivers/misc/mei/iaf/Kconfig
create mode 100644 drivers/misc/mei/iaf/Makefile
create mode 100644 drivers/misc/mei/iaf/mei_iaf.c
create mode 100644 include/drm/intel/i915_mei_iaf_interface.h
diff --git a/drivers/misc/mei/Kconfig b/drivers/misc/mei/Kconfig
index 7575fee96cc6a..60b2cfa27ebaa 100644
--- a/drivers/misc/mei/Kconfig
+++ b/drivers/misc/mei/Kconfig
@@ -84,5 +84,6 @@ config INTEL_MEI_VSC
source "drivers/misc/mei/hdcp/Kconfig"
source "drivers/misc/mei/pxp/Kconfig"
source "drivers/misc/mei/gsc_proxy/Kconfig"
+source "drivers/misc/mei/iaf/Kconfig"
endif
diff --git a/drivers/misc/mei/Makefile b/drivers/misc/mei/Makefile
index 6f9fdbf1a4959..8be787f8ecd41 100644
--- a/drivers/misc/mei/Makefile
+++ b/drivers/misc/mei/Makefile
@@ -31,6 +31,7 @@ CFLAGS_mei-trace.o = -I$(src)
obj-$(CONFIG_INTEL_MEI_HDCP) += hdcp/
obj-$(CONFIG_INTEL_MEI_PXP) += pxp/
obj-$(CONFIG_INTEL_MEI_GSC_PROXY) += gsc_proxy/
+obj-$(CONFIG_INTEL_MEI_IAF) += iaf/
obj-$(CONFIG_INTEL_MEI_VSC_HW) += mei-vsc-hw.o
mei-vsc-hw-y := vsc-tp.o
diff --git a/drivers/misc/mei/iaf/Kconfig b/drivers/misc/mei/iaf/Kconfig
new file mode 100644
index 0000000000000..4d131df6cf79f
--- /dev/null
+++ b/drivers/misc/mei/iaf/Kconfig
@@ -0,0 +1,12 @@
+# SPDX-License-Identifier: GPL-2.0
+# Copyright (c) 2020-2021, Intel Corporation. All rights reserved.
+#
+config INTEL_MEI_IAF
+ tristate "Intel Accelerator Fabric services of ME Interface"
+ depends on m
+ select INTEL_MEI_ME
+ depends on DRM_XE
+ help
+ MEI Support for IAF Services on Intel graphics card.
+
+ Enables the ME FW services required for IAF support.
diff --git a/drivers/misc/mei/iaf/Makefile b/drivers/misc/mei/iaf/Makefile
new file mode 100644
index 0000000000000..1130cbc9c0ccb
--- /dev/null
+++ b/drivers/misc/mei/iaf/Makefile
@@ -0,0 +1,7 @@
+# SPDX-License-Identifier: GPL-2.0
+#
+# Copyright (c) 2020-2021, Intel Corporation. All rights reserved.
+#
+# Makefile - IAF client driver for Intel MEI Bus Driver.
+
+obj-$(CONFIG_INTEL_MEI_IAF) += mei_iaf.o
diff --git a/drivers/misc/mei/iaf/mei_iaf.c b/drivers/misc/mei/iaf/mei_iaf.c
new file mode 100644
index 0000000000000..ad138ffe2b663
--- /dev/null
+++ b/drivers/misc/mei/iaf/mei_iaf.c
@@ -0,0 +1,292 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright © 2020-2021 Intel Corporation
+ */
+
+/**
+ * DOC: MEI_IAF Client Driver
+ *
+ * The IAF (Intel Accelerator Fabric) component driver acts as an interface
+ * between IAF i915 driver and GSC. The only api this interface provides is
+ * the 'commit svn' call.
+ */
+
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/uuid.h>
+#include <linux/mei_cl_bus.h>
+#include <linux/component.h>
+#include <drm/drm_connector.h>
+#include <drm/intel/i915_component.h>
+#include <drm/intel/i915_mei_iaf_interface.h>
+
+#include "../mkhi.h"
+
+#define MCA_ARBSVN_COMMIT_COMMAND_ID 0x1B
+
+enum arbsvn_nvar_usage {
+ ARBSVN_NVAR_USAGE_FW_MIN_VER = 0,
+ ARBSVN_NVAR_USAGE_MAX
+};
+
+struct mca_arbsvn_commit_req {
+ struct mkhi_msg_hdr mkhi_header;
+ u8 usage_id;
+ u8 reserved0;
+ u16 reserved1;
+} __packed;
+
+struct mca_arbsvn_commit_resp {
+ struct mkhi_msg_hdr mkhi_header;
+};
+
+#define MCA_OK 0x0 /* on successful commit */
+#define MCA_INVALID_INPUT 0xb /* if usage id is invalid */
+/* if disabled in the file or any other error (generic, reading or writing file) */
+#define MCA_ARB_SVN_DISABLED 0x20
+/* SVN was not updated, same value */
+#define MCA_ARB_SVN_SAME 0x28
+/* SVN was not updated, older value */
+#define MCA_ARB_SVN_SMALLER 0x29
+
+static int get_error_code(const struct device *dev, u8 result)
+{
+ int ret;
+
+ switch (result) {
+ case MCA_OK:
+ ret = 0;
+ break;
+ case MCA_ARB_SVN_DISABLED:
+ dev_dbg(dev, "Arb Svn disabled (error code 0x%x)\n",
+ MCA_ARB_SVN_DISABLED);
+ ret = -ENOENT;
+ break;
+ case MCA_INVALID_INPUT:
+ dev_err(dev, "Wrong usage id(error code 0x%x)\n",
+ MCA_INVALID_INPUT);
+ ret = -EINVAL;
+ break;
+ case MCA_ARB_SVN_SAME:
+ dev_dbg(dev, "SVN was not updated, same value(error code 0x%x)\n",
+ MCA_ARB_SVN_SAME);
+ ret = -EACCES;
+ break;
+ case MCA_ARB_SVN_SMALLER:
+ dev_dbg(dev, "SVN was not updated, older value(error code 0x%x)\n",
+ MCA_ARB_SVN_SMALLER);
+ ret = -EBADF;
+ break;
+ default:
+ dev_err(dev, "Unknown error code 0x%x\n", result);
+ ret = -EIO;
+ }
+
+ return ret;
+}
+
+static int mei_iaf_check_response(const struct device *dev,
+ struct mkhi_msg_hdr *hdr)
+{
+ if (hdr->group_id != MCHI_GROUP_ID) {
+ dev_err(dev, "Mismatch group id: 0x%x instead of 0x%x\n",
+ hdr->group_id, MCHI_GROUP_ID);
+ return -EINVAL;
+ }
+
+ if (hdr->command != (MCA_ARBSVN_COMMIT_COMMAND_ID | 0x80)) {
+ dev_err(dev, "Mismatch command: 0x%x instead of 0x%x\n",
+ hdr->command, MCA_ARBSVN_COMMIT_COMMAND_ID | 0x80);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+/**
+ * mei_iaf_commit_svn() - Commits current SVN.
+ * @dev: device corresponding to the mei_cl_device
+ * Return: 0 on Success
+ * * -EINVAL : Invalid usage id parameter
+ * * -ENOENT : ARB SVN is disabled in the file or any other error
+ * (generic, reading or writing file)
+ * * -EIO : Unknown I/O error
+ */
+static int mei_iaf_commit_svn(const struct device *dev)
+{
+ struct mei_cl_device *cldev;
+ struct mca_arbsvn_commit_req commit_req = { };
+ struct mca_arbsvn_commit_resp commit_resp = { };
+ int ret;
+
+ dev_dbg(dev, "in %s\n", __func__);
+
+ if (!dev)
+ return -EINVAL;
+
+ cldev = to_mei_cl_device(dev);
+
+ dev_dbg(dev, "after to_mei_cl_device cldev %p\n", cldev);
+
+ ret = mei_cldev_enable(cldev);
+ if (ret < 0) {
+ dev_dbg(dev, "mei_cldev_enable Failed. %d\n", ret);
+ return -EBUSY;
+ }
+
+ dev_dbg(dev, "after mei_cldev_enable, ret=%d\n", ret);
+ commit_req.mkhi_header.group_id = MCHI_GROUP_ID;
+ commit_req.mkhi_header.command = MCA_ARBSVN_COMMIT_COMMAND_ID;
+ commit_req.usage_id = ARBSVN_NVAR_USAGE_FW_MIN_VER;
+
+ ret = mei_cldev_send(cldev, (u8 *)&commit_req, sizeof(commit_req));
+ if (ret < 0) {
+ dev_err(dev, "mei_cldev_send failed. %d\n", ret);
+ goto end;
+ }
+ dev_dbg(dev, "after send, ret=%d\n", ret);
+ print_hex_dump_debug("sent svn commit message: ", DUMP_PREFIX_OFFSET,
+ 16, 1, (u8 *)&commit_req, ret, false);
+
+ ret = mei_cldev_recv(cldev, (u8 *)&commit_resp, sizeof(commit_resp));
+ if (ret < 0) {
+ dev_err(dev, "mei_cldev_recv failed. %d\n", ret);
+ goto end;
+ }
+ dev_dbg(dev, "after recv, ret=%d\n", ret);
+ print_hex_dump_debug("mei_iaf_commit_response ", DUMP_PREFIX_OFFSET,
+ 16, 1, (u8 *)&commit_resp, ret, false);
+
+ ret = mei_iaf_check_response(dev, &commit_resp.mkhi_header);
+ if (ret) {
+ dev_err(dev, "bad result response from the firmware: 0x%x\n",
+ *(uint32_t *)&commit_resp.mkhi_header);
+ goto end;
+ }
+ dev_dbg(dev, "after check_response\n");
+ ret = get_error_code(dev, commit_resp.mkhi_header.result);
+
+end:
+ dev_dbg(dev, "returning with %d\n", ret);
+ mei_cldev_disable(cldev);
+ return ret;
+}
+
+static const struct i915_iaf_component_ops mei_iaf_ops = {
+ .owner = THIS_MODULE,
+ .commit_svn = mei_iaf_commit_svn,
+};
+
+static int mei_component_master_bind(struct device *dev)
+{
+ int ret;
+
+ dev_dbg(dev, "mei_iaf_ops addr %p\n", &mei_iaf_ops);
+
+ ret = component_bind_all(dev, (void *)&mei_iaf_ops);
+ if (ret < 0)
+ return ret;
+
+ return 0;
+}
+
+static void mei_component_master_unbind(struct device *dev)
+{
+ dev_dbg(dev, "in %s\n", __func__);
+ component_unbind_all(dev, (void *)&mei_iaf_ops);
+}
+
+static const struct component_master_ops mei_component_master_ops = {
+ .bind = mei_component_master_bind,
+ .unbind = mei_component_master_unbind,
+};
+
+/**
+ * mei_iaf_component_match - compare function for matching mei iaf.
+ *
+ * The function checks if the driver is i915, the subcomponent is IAF
+ * and the parent of iaf and the grand parent of mei_if are the same
+ * i915 device.
+ *
+ * @dev: master device
+ * @subcomponent: subcomponent to match (I915_COMPONENT_IAF)
+ * @data: compare data (mei iaf device)
+ *
+ * Return:
+ * * 1 - if components match
+ * * 0 - otherwise
+ */
+static int mei_iaf_component_match(struct device *dev, int subcomponent,
+ void *data)
+{
+ struct device *base = data;
+
+ if (subcomponent != I915_COMPONENT_IAF ||
+ !dev->driver || strcmp(dev->driver->name, "iaf"))
+ return 0;
+
+ base = base->parent;
+ if (!base)
+ return 0;
+
+ base = base->parent;
+ dev = dev->parent;
+
+ return (base && dev && dev == base);
+}
+
+static int mei_iaf_probe(struct mei_cl_device *cldev,
+ const struct mei_cl_device_id *id)
+{
+ struct component_match *master_match;
+ int ret;
+
+ master_match = NULL;
+ component_match_add_typed(&cldev->dev, &master_match,
+ mei_iaf_component_match, &cldev->dev);
+ if (IS_ERR_OR_NULL(master_match)) {
+ ret = -ENOMEM;
+ goto err_exit;
+ }
+
+ ret = component_master_add_with_match(&cldev->dev,
+ &mei_component_master_ops,
+ master_match);
+ if (ret < 0) {
+ dev_err(&cldev->dev, "Master comp add failed %d\n", ret);
+ goto err_exit;
+ }
+
+ return 0;
+
+err_exit:
+ return ret;
+}
+
+static void mei_iaf_remove(struct mei_cl_device *cldev)
+{
+ component_master_del(&cldev->dev, &mei_component_master_ops);
+}
+
+/* fe2af7a6-ef22-4b45-872f-176b0bbc8b43: MCHIF GUID */
+#define MEI_GUID_MCHIF UUID_LE(0xfe2af7a6, 0xef22, 0x4b45, \
+ 0x87, 0x2f, 0x17, 0x6b, 0x0b, 0xbc, 0x8b, 0x43)
+
+static struct mei_cl_device_id mei_iaf_tbl[] = {
+ { .uuid = MEI_GUID_MCHIF, .version = MEI_CL_VERSION_ANY },
+ { }
+};
+MODULE_DEVICE_TABLE(mei, mei_iaf_tbl);
+
+static struct mei_cl_driver mei_iaf_driver = {
+ .id_table = mei_iaf_tbl,
+ .name = KBUILD_MODNAME,
+ .probe = mei_iaf_probe,
+ .remove = mei_iaf_remove,
+};
+
+module_mei_cl_driver(mei_iaf_driver);
+
+MODULE_AUTHOR("Intel Corporation");
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("MEI IAF");
diff --git a/drivers/misc/mei/mkhi.h b/drivers/misc/mei/mkhi.h
index 1473ea4896662..63d9f02e7341f 100644
--- a/drivers/misc/mei/mkhi.h
+++ b/drivers/misc/mei/mkhi.h
@@ -16,6 +16,8 @@
#define MKHI_GEN_GROUP_ID 0xFF
#define MKHI_GEN_GET_FW_VERSION_CMD 0x2
+#define MCHI_GROUP_ID 0xA
+
#define MKHI_GROUP_ID_GFX 0x30
#define MKHI_GFX_RESET_WARN_CMD_REQ 0x0
#define MKHI_GFX_MEMORY_READY_CMD_REQ 0x1
diff --git a/include/drm/intel/i915_mei_iaf_interface.h b/include/drm/intel/i915_mei_iaf_interface.h
new file mode 100644
index 0000000000000..dde938dd0ea2c
--- /dev/null
+++ b/include/drm/intel/i915_mei_iaf_interface.h
@@ -0,0 +1,25 @@
+/* SPDX-License-Identifier: (GPL-2.0+) */
+/*
+ * Copyright © 2020-2021 Intel Corporation
+ */
+
+#ifndef _I915_MEI_IAF_INTERFACE_H_
+#define _I915_MEI_IAF_INTERFACE_H_
+
+#include <linux/device.h>
+
+/**
+ * struct i915_iaf_component_ops- ops for IAF services.
+ * @owner: Module providing the ops
+ * @commit_svn: commits current FW SVN
+ */
+struct i915_iaf_component_ops {
+ /**
+ * @owner: mei_iaf module
+ */
+ struct module *owner;
+
+ int (*commit_svn)(const struct device *dev);
+};
+
+#endif /* _I915_MEI_IAF_INTERFACE_H_ */
--
2.45.2
More information about the dri-devel
mailing list