Skip to content

Commit 1dd924f

Browse files
ausyskindceraolo
authored andcommitted
mei: gsc_proxy: add gsc proxy driver
Add GSC proxy driver. It to allows messaging between GSC component on Intel graphics card and CSE device. Cc: Alan Previn <alan.previn.teres.alexis@intel.com> Signed-off-by: Alexander Usyskin <alexander.usyskin@intel.com> Signed-off-by: Tomas Winkler <tomas.winkler@intel.com> Signed-off-by: Daniele Ceraolo Spurio <daniele.ceraolospurio@intel.com> Acked-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> Reviewed-by: Alan Previn <alan.previn.teres.alexis@intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20230502163854.317653-3-daniele.ceraolospurio@intel.com
1 parent e7b05d9 commit 1dd924f

File tree

5 files changed

+231
-1
lines changed

5 files changed

+231
-1
lines changed

drivers/misc/mei/Kconfig

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,4 +62,4 @@ config INTEL_MEI_GSC
6262

6363
source "drivers/misc/mei/hdcp/Kconfig"
6464
source "drivers/misc/mei/pxp/Kconfig"
65-
65+
source "drivers/misc/mei/gsc_proxy/Kconfig"

drivers/misc/mei/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,3 +30,4 @@ CFLAGS_mei-trace.o = -I$(src)
3030

3131
obj-$(CONFIG_INTEL_MEI_HDCP) += hdcp/
3232
obj-$(CONFIG_INTEL_MEI_PXP) += pxp/
33+
obj-$(CONFIG_INTEL_MEI_GSC_PROXY) += gsc_proxy/

drivers/misc/mei/gsc_proxy/Kconfig

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
# SPDX-License-Identifier: GPL-2.0
2+
# Copyright (c) 2022-2023, Intel Corporation. All rights reserved.
3+
#
4+
config INTEL_MEI_GSC_PROXY
5+
tristate "Intel GSC Proxy services of ME Interface"
6+
select INTEL_MEI_ME
7+
depends on DRM_I915
8+
help
9+
MEI Support for GSC Proxy Services on Intel platforms.
10+
11+
MEI GSC proxy enables messaging between GSC service on
12+
Intel graphics card and services on CSE (MEI) firmware
13+
residing SoC or PCH.
14+
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
# SPDX-License-Identifier: GPL-2.0
2+
#
3+
# Copyright (c) 2022-2023, Intel Corporation. All rights reserved.
4+
#
5+
# Makefile - GSC Proxy client driver for Intel MEI Bus Driver.
6+
7+
obj-$(CONFIG_INTEL_MEI_GSC_PROXY) += mei_gsc_proxy.o
Lines changed: 208 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,208 @@
1+
// SPDX-License-Identifier: GPL-2.0
2+
/*
3+
* Copyright (c) 2022-2023 Intel Corporation
4+
*/
5+
6+
/**
7+
* DOC: MEI_GSC_PROXY Client Driver
8+
*
9+
* The mei_gsc_proxy driver acts as a translation layer between
10+
* proxy user (I915) and ME FW by proxying messages to ME FW
11+
*/
12+
13+
#include <linux/component.h>
14+
#include <linux/mei_cl_bus.h>
15+
#include <linux/module.h>
16+
#include <linux/pci.h>
17+
#include <linux/slab.h>
18+
#include <linux/uuid.h>
19+
#include <drm/drm_connector.h>
20+
#include <drm/i915_component.h>
21+
#include <drm/i915_gsc_proxy_mei_interface.h>
22+
23+
/**
24+
* mei_gsc_proxy_send - Sends a proxy message to ME FW.
25+
* @dev: device corresponding to the mei_cl_device
26+
* @buf: a message buffer to send
27+
* @size: size of the message
28+
* Return: bytes sent on Success, <0 on Failure
29+
*/
30+
static int mei_gsc_proxy_send(struct device *dev, const void *buf, size_t size)
31+
{
32+
ssize_t ret;
33+
34+
if (!dev || !buf)
35+
return -EINVAL;
36+
37+
ret = mei_cldev_send(to_mei_cl_device(dev), buf, size);
38+
if (ret < 0)
39+
dev_dbg(dev, "mei_cldev_send failed. %zd\n", ret);
40+
41+
return ret;
42+
}
43+
44+
/**
45+
* mei_gsc_proxy_recv - Receives a proxy message from ME FW.
46+
* @dev: device corresponding to the mei_cl_device
47+
* @buf: a message buffer to contain the received message
48+
* @size: size of the buffer
49+
* Return: bytes received on Success, <0 on Failure
50+
*/
51+
static int mei_gsc_proxy_recv(struct device *dev, void *buf, size_t size)
52+
{
53+
ssize_t ret;
54+
55+
if (!dev || !buf)
56+
return -EINVAL;
57+
58+
ret = mei_cldev_recv(to_mei_cl_device(dev), buf, size);
59+
if (ret < 0)
60+
dev_dbg(dev, "mei_cldev_recv failed. %zd\n", ret);
61+
62+
return ret;
63+
}
64+
65+
static const struct i915_gsc_proxy_component_ops mei_gsc_proxy_ops = {
66+
.owner = THIS_MODULE,
67+
.send = mei_gsc_proxy_send,
68+
.recv = mei_gsc_proxy_recv,
69+
};
70+
71+
static int mei_component_master_bind(struct device *dev)
72+
{
73+
struct mei_cl_device *cldev = to_mei_cl_device(dev);
74+
struct i915_gsc_proxy_component *comp_master = mei_cldev_get_drvdata(cldev);
75+
76+
comp_master->ops = &mei_gsc_proxy_ops;
77+
comp_master->mei_dev = dev;
78+
return component_bind_all(dev, comp_master);
79+
}
80+
81+
static void mei_component_master_unbind(struct device *dev)
82+
{
83+
struct mei_cl_device *cldev = to_mei_cl_device(dev);
84+
struct i915_gsc_proxy_component *comp_master = mei_cldev_get_drvdata(cldev);
85+
86+
component_unbind_all(dev, comp_master);
87+
}
88+
89+
static const struct component_master_ops mei_component_master_ops = {
90+
.bind = mei_component_master_bind,
91+
.unbind = mei_component_master_unbind,
92+
};
93+
94+
/**
95+
* mei_gsc_proxy_component_match - compare function for matching mei.
96+
*
97+
* The function checks if the device is pci device and
98+
* Intel VGA adapter, the subcomponent is SW Proxy
99+
* and the parent of MEI PCI and the parent of VGA are the same PCH device.
100+
*
101+
* @dev: master device
102+
* @subcomponent: subcomponent to match (I915_COMPONENT_SWPROXY)
103+
* @data: compare data (mei pci parent)
104+
*
105+
* Return:
106+
* * 1 - if components match
107+
* * 0 - otherwise
108+
*/
109+
static int mei_gsc_proxy_component_match(struct device *dev, int subcomponent,
110+
void *data)
111+
{
112+
struct pci_dev *pdev;
113+
114+
if (!dev_is_pci(dev))
115+
return 0;
116+
117+
pdev = to_pci_dev(dev);
118+
119+
if (pdev->class != (PCI_CLASS_DISPLAY_VGA << 8) ||
120+
pdev->vendor != PCI_VENDOR_ID_INTEL)
121+
return 0;
122+
123+
if (subcomponent != I915_COMPONENT_GSC_PROXY)
124+
return 0;
125+
126+
return component_compare_dev(dev->parent, ((struct device *)data)->parent);
127+
}
128+
129+
static int mei_gsc_proxy_probe(struct mei_cl_device *cldev,
130+
const struct mei_cl_device_id *id)
131+
{
132+
struct i915_gsc_proxy_component *comp_master;
133+
struct component_match *master_match = NULL;
134+
int ret;
135+
136+
ret = mei_cldev_enable(cldev);
137+
if (ret < 0) {
138+
dev_err(&cldev->dev, "mei_cldev_enable Failed. %d\n", ret);
139+
goto enable_err_exit;
140+
}
141+
142+
comp_master = kzalloc(sizeof(*comp_master), GFP_KERNEL);
143+
if (!comp_master) {
144+
ret = -ENOMEM;
145+
goto err_exit;
146+
}
147+
148+
component_match_add_typed(&cldev->dev, &master_match,
149+
mei_gsc_proxy_component_match, cldev->dev.parent);
150+
if (IS_ERR_OR_NULL(master_match)) {
151+
ret = -ENOMEM;
152+
goto err_exit;
153+
}
154+
155+
mei_cldev_set_drvdata(cldev, comp_master);
156+
ret = component_master_add_with_match(&cldev->dev,
157+
&mei_component_master_ops,
158+
master_match);
159+
if (ret < 0) {
160+
dev_err(&cldev->dev, "Master comp add failed %d\n", ret);
161+
goto err_exit;
162+
}
163+
164+
return 0;
165+
166+
err_exit:
167+
mei_cldev_set_drvdata(cldev, NULL);
168+
kfree(comp_master);
169+
mei_cldev_disable(cldev);
170+
enable_err_exit:
171+
return ret;
172+
}
173+
174+
static void mei_gsc_proxy_remove(struct mei_cl_device *cldev)
175+
{
176+
struct i915_gsc_proxy_component *comp_master = mei_cldev_get_drvdata(cldev);
177+
int ret;
178+
179+
component_master_del(&cldev->dev, &mei_component_master_ops);
180+
kfree(comp_master);
181+
mei_cldev_set_drvdata(cldev, NULL);
182+
183+
ret = mei_cldev_disable(cldev);
184+
if (ret)
185+
dev_warn(&cldev->dev, "mei_cldev_disable() failed %d\n", ret);
186+
}
187+
188+
#define MEI_UUID_GSC_PROXY UUID_LE(0xf73db04, 0x97ab, 0x4125, \
189+
0xb8, 0x93, 0xe9, 0x4, 0xad, 0xd, 0x54, 0x64)
190+
191+
static struct mei_cl_device_id mei_gsc_proxy_tbl[] = {
192+
{ .uuid = MEI_UUID_GSC_PROXY, .version = MEI_CL_VERSION_ANY },
193+
{ }
194+
};
195+
MODULE_DEVICE_TABLE(mei, mei_gsc_proxy_tbl);
196+
197+
static struct mei_cl_driver mei_gsc_proxy_driver = {
198+
.id_table = mei_gsc_proxy_tbl,
199+
.name = KBUILD_MODNAME,
200+
.probe = mei_gsc_proxy_probe,
201+
.remove = mei_gsc_proxy_remove,
202+
};
203+
204+
module_mei_cl_driver(mei_gsc_proxy_driver);
205+
206+
MODULE_AUTHOR("Intel Corporation");
207+
MODULE_LICENSE("GPL");
208+
MODULE_DESCRIPTION("MEI GSC PROXY");

0 commit comments

Comments
 (0)