Skip to content

Commit 1e3dc1d

Browse files
Tomas Winklerdceraolo
authored andcommitted
drm/i915/gsc: add gsc as a mei auxiliary device
GSC is a graphics system controller, it provides a chassis controller for graphics discrete cards. There are two MEI interfaces in GSC: HECI1 and HECI2. Both interfaces are on the BAR0 at offsets 0x00258000 and 0x00259000. GSC is a GT Engine (class 4: instance 6). HECI1 interrupt is signaled via bit 15 and HECI2 via bit 14 in the interrupt register. This patch exports GSC as auxiliary device for mei driver to bind to for HECI2 interface and prepares for HECI1 interface as it will follow up soon. CC: Rodrigo Vivi <[email protected]> Signed-off-by: Tomas Winkler <[email protected]> Signed-off-by: Vitaly Lubart <[email protected]> Signed-off-by: Alexander Usyskin <[email protected]> Acked-by: Tvrtko Ursulin <[email protected]> Reviewed-by: Daniele Ceraolo Spurio <[email protected]> Signed-off-by: Daniele Ceraolo Spurio <[email protected]> Link: https://patchwork.freedesktop.org/patch/msgid/[email protected]
1 parent e1e1f4e commit 1e3dc1d

File tree

15 files changed

+303
-1
lines changed

15 files changed

+303
-1
lines changed

MAINTAINERS

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9996,6 +9996,7 @@ S: Supported
99969996
F: Documentation/driver-api/mei/*
99979997
F: drivers/misc/mei/
99989998
F: drivers/watchdog/mei_wdt.c
9999+
F: include/linux/mei_aux.h
999910000
F: include/linux/mei_cl_bus.h
1000010001
F: include/uapi/linux/mei.h
1000110002
F: samples/mei/*

drivers/gpu/drm/i915/Kconfig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ config DRM_I915
3030
select VMAP_PFN
3131
select DRM_TTM
3232
select DRM_BUDDY
33+
select AUXILIARY_BUS
3334
help
3435
Choose this option if you have a system that has "Intel Graphics
3536
Media Accelerator" or "HD Graphics" integrated graphics,

drivers/gpu/drm/i915/Makefile

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -204,6 +204,9 @@ i915-y += gt/uc/intel_uc.o \
204204
gt/uc/intel_huc_debugfs.o \
205205
gt/uc/intel_huc_fw.o
206206

207+
# graphics system controller (GSC) support
208+
i915-y += gt/intel_gsc.o
209+
207210
# modesetting core code
208211
i915-y += \
209212
display/hsw_ips.o \

drivers/gpu/drm/i915/gt/intel_gsc.c

Lines changed: 204 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,204 @@
1+
// SPDX-License-Identifier: MIT
2+
/*
3+
* Copyright(c) 2019-2022, Intel Corporation. All rights reserved.
4+
*/
5+
6+
#include <linux/irq.h>
7+
#include <linux/mei_aux.h>
8+
#include "i915_drv.h"
9+
#include "i915_reg.h"
10+
#include "gt/intel_gsc.h"
11+
#include "gt/intel_gt.h"
12+
13+
#define GSC_BAR_LENGTH 0x00000FFC
14+
15+
static void gsc_irq_mask(struct irq_data *d)
16+
{
17+
/* generic irq handling */
18+
}
19+
20+
static void gsc_irq_unmask(struct irq_data *d)
21+
{
22+
/* generic irq handling */
23+
}
24+
25+
static struct irq_chip gsc_irq_chip = {
26+
.name = "gsc_irq_chip",
27+
.irq_mask = gsc_irq_mask,
28+
.irq_unmask = gsc_irq_unmask,
29+
};
30+
31+
static int gsc_irq_init(int irq)
32+
{
33+
irq_set_chip_and_handler_name(irq, &gsc_irq_chip,
34+
handle_simple_irq, "gsc_irq_handler");
35+
36+
return irq_set_chip_data(irq, NULL);
37+
}
38+
39+
struct gsc_def {
40+
const char *name;
41+
unsigned long bar;
42+
size_t bar_size;
43+
};
44+
45+
/* gsc resources and definitions (HECI1 and HECI2) */
46+
static const struct gsc_def gsc_def_dg1[] = {
47+
{
48+
/* HECI1 not yet implemented. */
49+
},
50+
{
51+
.name = "mei-gscfi",
52+
.bar = DG1_GSC_HECI2_BASE,
53+
.bar_size = GSC_BAR_LENGTH,
54+
}
55+
};
56+
57+
static void gsc_release_dev(struct device *dev)
58+
{
59+
struct auxiliary_device *aux_dev = to_auxiliary_dev(dev);
60+
struct mei_aux_device *adev = auxiliary_dev_to_mei_aux_dev(aux_dev);
61+
62+
kfree(adev);
63+
}
64+
65+
static void gsc_destroy_one(struct intel_gsc_intf *intf)
66+
{
67+
if (intf->adev) {
68+
auxiliary_device_delete(&intf->adev->aux_dev);
69+
auxiliary_device_uninit(&intf->adev->aux_dev);
70+
intf->adev = NULL;
71+
}
72+
if (intf->irq >= 0)
73+
irq_free_desc(intf->irq);
74+
intf->irq = -1;
75+
}
76+
77+
static void gsc_init_one(struct drm_i915_private *i915,
78+
struct intel_gsc_intf *intf,
79+
unsigned int intf_id)
80+
{
81+
struct pci_dev *pdev = to_pci_dev(i915->drm.dev);
82+
struct mei_aux_device *adev;
83+
struct auxiliary_device *aux_dev;
84+
const struct gsc_def *def;
85+
int ret;
86+
87+
intf->irq = -1;
88+
intf->id = intf_id;
89+
90+
if (intf_id == 0 && !HAS_HECI_PXP(i915))
91+
return;
92+
93+
def = &gsc_def_dg1[intf_id];
94+
95+
if (!def->name) {
96+
drm_warn_once(&i915->drm, "HECI%d is not implemented!\n", intf_id + 1);
97+
return;
98+
}
99+
100+
intf->irq = irq_alloc_desc(0);
101+
if (intf->irq < 0) {
102+
drm_err(&i915->drm, "gsc irq error %d\n", intf->irq);
103+
return;
104+
}
105+
106+
ret = gsc_irq_init(intf->irq);
107+
if (ret < 0) {
108+
drm_err(&i915->drm, "gsc irq init failed %d\n", ret);
109+
goto fail;
110+
}
111+
112+
adev = kzalloc(sizeof(*adev), GFP_KERNEL);
113+
if (!adev)
114+
goto fail;
115+
116+
adev->irq = intf->irq;
117+
adev->bar.parent = &pdev->resource[0];
118+
adev->bar.start = def->bar + pdev->resource[0].start;
119+
adev->bar.end = adev->bar.start + def->bar_size - 1;
120+
adev->bar.flags = IORESOURCE_MEM;
121+
adev->bar.desc = IORES_DESC_NONE;
122+
123+
aux_dev = &adev->aux_dev;
124+
aux_dev->name = def->name;
125+
aux_dev->id = (pci_domain_nr(pdev->bus) << 16) |
126+
PCI_DEVID(pdev->bus->number, pdev->devfn);
127+
aux_dev->dev.parent = &pdev->dev;
128+
aux_dev->dev.release = gsc_release_dev;
129+
130+
ret = auxiliary_device_init(aux_dev);
131+
if (ret < 0) {
132+
drm_err(&i915->drm, "gsc aux init failed %d\n", ret);
133+
kfree(adev);
134+
goto fail;
135+
}
136+
137+
ret = auxiliary_device_add(aux_dev);
138+
if (ret < 0) {
139+
drm_err(&i915->drm, "gsc aux add failed %d\n", ret);
140+
/* adev will be freed with the put_device() and .release sequence */
141+
auxiliary_device_uninit(aux_dev);
142+
goto fail;
143+
}
144+
intf->adev = adev;
145+
146+
return;
147+
fail:
148+
gsc_destroy_one(intf);
149+
}
150+
151+
static void gsc_irq_handler(struct intel_gt *gt, unsigned int intf_id)
152+
{
153+
int ret;
154+
155+
if (intf_id >= INTEL_GSC_NUM_INTERFACES) {
156+
drm_warn_once(&gt->i915->drm, "GSC irq: intf_id %d is out of range", intf_id);
157+
return;
158+
}
159+
160+
if (!HAS_HECI_GSC(gt->i915)) {
161+
drm_warn_once(&gt->i915->drm, "GSC irq: not supported");
162+
return;
163+
}
164+
165+
if (gt->gsc.intf[intf_id].irq < 0) {
166+
drm_err_ratelimited(&gt->i915->drm, "GSC irq: irq not set");
167+
return;
168+
}
169+
170+
ret = generic_handle_irq(gt->gsc.intf[intf_id].irq);
171+
if (ret)
172+
drm_err_ratelimited(&gt->i915->drm, "error handling GSC irq: %d\n", ret);
173+
}
174+
175+
void intel_gsc_irq_handler(struct intel_gt *gt, u32 iir)
176+
{
177+
if (iir & GSC_IRQ_INTF(0))
178+
gsc_irq_handler(gt, 0);
179+
if (iir & GSC_IRQ_INTF(1))
180+
gsc_irq_handler(gt, 1);
181+
}
182+
183+
void intel_gsc_init(struct intel_gsc *gsc, struct drm_i915_private *i915)
184+
{
185+
unsigned int i;
186+
187+
if (!HAS_HECI_GSC(i915))
188+
return;
189+
190+
for (i = 0; i < INTEL_GSC_NUM_INTERFACES; i++)
191+
gsc_init_one(i915, &gsc->intf[i], i);
192+
}
193+
194+
void intel_gsc_fini(struct intel_gsc *gsc)
195+
{
196+
struct intel_gt *gt = gsc_to_gt(gsc);
197+
unsigned int i;
198+
199+
if (!HAS_HECI_GSC(gt->i915))
200+
return;
201+
202+
for (i = 0; i < INTEL_GSC_NUM_INTERFACES; i++)
203+
gsc_destroy_one(&gsc->intf[i]);
204+
}

drivers/gpu/drm/i915/gt/intel_gsc.h

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
/* SPDX-License-Identifier: MIT */
2+
/*
3+
* Copyright(c) 2019-2022, Intel Corporation. All rights reserved.
4+
*/
5+
#ifndef __INTEL_GSC_DEV_H__
6+
#define __INTEL_GSC_DEV_H__
7+
8+
#include <linux/types.h>
9+
10+
struct drm_i915_private;
11+
struct intel_gt;
12+
struct mei_aux_device;
13+
14+
#define INTEL_GSC_NUM_INTERFACES 2
15+
/*
16+
* The HECI1 bit corresponds to bit15 and HECI2 to bit14.
17+
* The reason for this is to allow growth for more interfaces in the future.
18+
*/
19+
#define GSC_IRQ_INTF(_x) BIT(15 - (_x))
20+
21+
/**
22+
* struct intel_gsc - graphics security controller
23+
* @intf : gsc interface
24+
*/
25+
struct intel_gsc {
26+
struct intel_gsc_intf {
27+
struct mei_aux_device *adev;
28+
int irq;
29+
unsigned int id;
30+
} intf[INTEL_GSC_NUM_INTERFACES];
31+
};
32+
33+
void intel_gsc_init(struct intel_gsc *gsc, struct drm_i915_private *dev_priv);
34+
void intel_gsc_fini(struct intel_gsc *gsc);
35+
void intel_gsc_irq_handler(struct intel_gt *gt, u32 iir);
36+
37+
#endif /* __INTEL_GSC_DEV_H__ */

drivers/gpu/drm/i915/gt/intel_gt.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -456,6 +456,8 @@ void intel_gt_chipset_flush(struct intel_gt *gt)
456456

457457
void intel_gt_driver_register(struct intel_gt *gt)
458458
{
459+
intel_gsc_init(&gt->gsc, gt->i915);
460+
459461
intel_rps_driver_register(&gt->rps);
460462

461463
intel_gt_debugfs_register(gt);
@@ -784,6 +786,7 @@ void intel_gt_driver_unregister(struct intel_gt *gt)
784786
intel_wakeref_t wakeref;
785787

786788
intel_rps_driver_unregister(&gt->rps);
789+
intel_gsc_fini(&gt->gsc);
787790

788791
intel_pxp_fini(&gt->pxp);
789792

drivers/gpu/drm/i915/gt/intel_gt.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,11 @@ static inline struct intel_gt *huc_to_gt(struct intel_huc *huc)
4646
return container_of(huc, struct intel_gt, uc.huc);
4747
}
4848

49+
static inline struct intel_gt *gsc_to_gt(struct intel_gsc *gsc)
50+
{
51+
return container_of(gsc, struct intel_gt, gsc);
52+
}
53+
4954
void intel_root_gt_init_early(struct drm_i915_private *i915);
5055
int intel_gt_assign_ggtt(struct intel_gt *gt);
5156
int intel_gt_init_mmio(struct intel_gt *gt);

drivers/gpu/drm/i915/gt/intel_gt_irq.c

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,9 @@ gen11_other_irq_handler(struct intel_gt *gt, const u8 instance,
6868
if (instance == OTHER_KCR_INSTANCE)
6969
return intel_pxp_irq_handler(&gt->pxp, iir);
7070

71+
if (instance == OTHER_GSC_INSTANCE)
72+
return intel_gsc_irq_handler(gt, iir);
73+
7174
WARN_ONCE(1, "unhandled other interrupt instance=0x%x, iir=0x%x\n",
7275
instance, iir);
7376
}
@@ -184,6 +187,8 @@ void gen11_gt_irq_reset(struct intel_gt *gt)
184187
intel_uncore_write(uncore, GEN11_VCS_VECS_INTR_ENABLE, 0);
185188
if (CCS_MASK(gt))
186189
intel_uncore_write(uncore, GEN12_CCS_RSVD_INTR_ENABLE, 0);
190+
if (HAS_HECI_GSC(gt->i915))
191+
intel_uncore_write(uncore, GEN11_GUNIT_CSME_INTR_ENABLE, 0);
187192

188193
/* Restore masks irqs on RCS, BCS, VCS and VECS engines. */
189194
intel_uncore_write(uncore, GEN11_RCS0_RSVD_INTR_MASK, ~0);
@@ -201,6 +206,8 @@ void gen11_gt_irq_reset(struct intel_gt *gt)
201206
intel_uncore_write(uncore, GEN12_CCS0_CCS1_INTR_MASK, ~0);
202207
if (HAS_ENGINE(gt, CCS2) || HAS_ENGINE(gt, CCS3))
203208
intel_uncore_write(uncore, GEN12_CCS2_CCS3_INTR_MASK, ~0);
209+
if (HAS_HECI_GSC(gt->i915))
210+
intel_uncore_write(uncore, GEN11_GUNIT_CSME_INTR_MASK, ~0);
204211

205212
intel_uncore_write(uncore, GEN11_GPM_WGBOXPERF_INTR_ENABLE, 0);
206213
intel_uncore_write(uncore, GEN11_GPM_WGBOXPERF_INTR_MASK, ~0);
@@ -215,6 +222,7 @@ void gen11_gt_irq_postinstall(struct intel_gt *gt)
215222
{
216223
struct intel_uncore *uncore = gt->uncore;
217224
u32 irqs = GT_RENDER_USER_INTERRUPT;
225+
const u32 gsc_mask = GSC_IRQ_INTF(0) | GSC_IRQ_INTF(1);
218226
u32 dmask;
219227
u32 smask;
220228

@@ -233,6 +241,9 @@ void gen11_gt_irq_postinstall(struct intel_gt *gt)
233241
intel_uncore_write(uncore, GEN11_VCS_VECS_INTR_ENABLE, dmask);
234242
if (CCS_MASK(gt))
235243
intel_uncore_write(uncore, GEN12_CCS_RSVD_INTR_ENABLE, smask);
244+
if (HAS_HECI_GSC(gt->i915))
245+
intel_uncore_write(uncore, GEN11_GUNIT_CSME_INTR_ENABLE,
246+
gsc_mask);
236247

237248
/* Unmask irqs on RCS, BCS, VCS and VECS engines. */
238249
intel_uncore_write(uncore, GEN11_RCS0_RSVD_INTR_MASK, ~smask);
@@ -250,6 +261,8 @@ void gen11_gt_irq_postinstall(struct intel_gt *gt)
250261
intel_uncore_write(uncore, GEN12_CCS0_CCS1_INTR_MASK, ~dmask);
251262
if (HAS_ENGINE(gt, CCS2) || HAS_ENGINE(gt, CCS3))
252263
intel_uncore_write(uncore, GEN12_CCS2_CCS3_INTR_MASK, ~dmask);
264+
if (HAS_HECI_GSC(gt->i915))
265+
intel_uncore_write(uncore, GEN11_GUNIT_CSME_INTR_MASK, ~gsc_mask);
253266

254267
/*
255268
* RPS interrupts will get enabled/disabled on demand when RPS itself

drivers/gpu/drm/i915/gt/intel_gt_regs.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1502,6 +1502,7 @@
15021502
#define OTHER_GUC_INSTANCE 0
15031503
#define OTHER_GTPM_INSTANCE 1
15041504
#define OTHER_KCR_INSTANCE 4
1505+
#define OTHER_GSC_INSTANCE 6
15051506

15061507
#define GEN11_IIR_REG_SELECTOR(x) _MMIO(0x190070 + ((x) * 4))
15071508

drivers/gpu/drm/i915/gt/intel_gt_types.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
#include <linux/workqueue.h>
1717

1818
#include "uc/intel_uc.h"
19+
#include "intel_gsc.h"
1920

2021
#include "i915_vma.h"
2122
#include "intel_engine_types.h"
@@ -73,6 +74,7 @@ struct intel_gt {
7374
struct i915_ggtt *ggtt;
7475

7576
struct intel_uc uc;
77+
struct intel_gsc gsc;
7678

7779
struct mutex tlb_invalidate_lock;
7880

0 commit comments

Comments
 (0)