diff options
author | Michał Winiarski <michal.winiarski@intel.com> | 2017-12-13 17:13:46 -0500 |
---|---|---|
committer | Chris Wilson <chris@chris-wilson.co.uk> | 2017-12-14 03:06:52 -0500 |
commit | 1bbbca0db722d137ed426368bff42b17808ad11e (patch) | |
tree | a9637f211966ac853e0a7a485616ce27c07d7777 | |
parent | 6ca9a2beb54a385c8cc5e39a9d2ef49945896c64 (diff) |
drm/i915/guc: Move shared data allocation away from submission path
We need shared data for actions (e.g. guc suspend/resume), and we're
using those with GuC submission disabled.
Let's introduce intel_guc_init and move shared data alloc there.
This fixes GPF during module unload with HuC, but without GuC submission:
BUG: unable to handle kernel NULL pointer dereference at 000000005aee7809
IP: intel_guc_suspend+0x34/0x140 [i915]
PGD 0 P4D 0
Oops: 0000 [#1] PREEMPT SMP
Modules linked in: i915(O-) netconsole x86_pkg_temp_thermal
intel_powerclamp coretemp crct10dif_pclmul crc32_pclmul ghash_clmulni_intel
mei_me i2c_i801 mei prime_numbers [last unloaded: i915]
CPU: 2 PID: 2794 Comm: rmmod Tainted: G U W O 4.15.0-rc2+ #297
Hardware name: /NUC6i5SYB, BIOS SYSKLi35.86A.0054.2016.0930.1102 09/30/2016
task: 0000000055945c61 task.stack: 00000000264ccb43
RIP: 0010:intel_guc_suspend+0x34/0x140 [i915]
RSP: 0018:ffffc90000483df8 EFLAGS: 00010286
RAX: 0000000000000000 RBX: ffff880829180000 RCX: 0000000000000000
RDX: 0000000000000006 RSI: ffff880844c2c938 RDI: ffff880844c2c000
RBP: ffff880829180000 R08: 00000000a29c58c1 R09: 0000000000000000
R10: 0000000000000000 R11: 0000000000000000 R12: ffffffffa040ba40
R13: ffffffffa040bab0 R14: ffff88084a195060 R15: 000055df3ef357a0
FS: 00007ff43c043740(0000) GS:ffff88084e200000(0000) knlGS:0000000000000000
CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: 00000000000000f9 CR3: 000000083f179005 CR4: 00000000003606e0
Call Trace:
i915_gem_suspend+0x9d/0x130 [i915]
? i915_driver_unload+0x68/0x180 [i915]
i915_driver_unload+0x70/0x180 [i915]
i915_pci_remove+0x15/0x20 [i915]
pci_device_remove+0x36/0xb0
device_release_driver_internal+0x15f/0x220
driver_detach+0x3a/0x80
bus_remove_driver+0x58/0xd0
pci_unregister_driver+0x29/0x90
SyS_delete_module+0x150/0x1e0
entry_SYSCALL_64_fastpath+0x23/0x9a
RIP: 0033:0x7ff43b51b5c7
RSP: 002b:00007ffe6825a758 EFLAGS: 00000206 ORIG_RAX: 00000000000000b0
RAX: ffffffffffffffda RBX: 0000000000000003 RCX: 00007ff43b51b5c7
RDX: 000000000000000a RSI: 0000000000000800 RDI: 000055df3ef35808
RBP: 0000000000000000 R08: 00007ffe682596d1 R09: 0000000000000000
R10: 00007ff43b594880 R11: 0000000000000206 R12: 000055df3ef357a0
R13: 00007ffe68259740 R14: 000055df3ef35260 R15: 000055df3ef357a0
Code: 00 00 02 74 03 31 c0 c3 53 48 89 fb 48 83 ec 10 e8 52 0f
f8 ff 48 b8 01 05 00 00 02 00 00 00 48 89 44 24 04 48 8b 83 00 12 00 00 <f6> 80
f9 00 00 00 01 0f 84 a7 00 00 00 f6 80 98 00 00 00 01 0f
RIP: intel_guc_suspend+0x34/0x140 [i915] RSP: ffffc90000483df8
CR2: 00000000000000f9
---[ end trace 23a192a61d937a3e ]---
Fixes: b8e5eb960b28 ("drm/i915/guc: Allocate separate shared data object for GuC communication")
Signed-off-by: Michał Winiarski <michal.winiarski@intel.com>
Cc: Chris Wilson <chris@chris-wilson.co.uk>
Cc: Joonas Lahtinen <joonas.lahtinen@linux.intel.com>
Cc: Michal Wajdeczko <michal.wajdeczko@intel.com>
Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk>
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Link: https://patchwork.freedesktop.org/patch/msgid/20171213221352.7173-1-michal.winiarski@intel.com
-rw-r--r-- | drivers/gpu/drm/i915/intel_guc.c | 51 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/intel_guc.h | 2 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/intel_guc_submission.c | 37 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/intel_uc.c | 10 |
4 files changed, 60 insertions, 40 deletions
diff --git a/drivers/gpu/drm/i915/intel_guc.c b/drivers/gpu/drm/i915/intel_guc.c index 177ee69ca9b1..92ed22f38fc4 100644 --- a/drivers/gpu/drm/i915/intel_guc.c +++ b/drivers/gpu/drm/i915/intel_guc.c | |||
@@ -69,6 +69,57 @@ void intel_guc_init_early(struct intel_guc *guc) | |||
69 | guc->notify = gen8_guc_raise_irq; | 69 | guc->notify = gen8_guc_raise_irq; |
70 | } | 70 | } |
71 | 71 | ||
72 | static int guc_shared_data_create(struct intel_guc *guc) | ||
73 | { | ||
74 | struct i915_vma *vma; | ||
75 | void *vaddr; | ||
76 | |||
77 | vma = intel_guc_allocate_vma(guc, PAGE_SIZE); | ||
78 | if (IS_ERR(vma)) | ||
79 | return PTR_ERR(vma); | ||
80 | |||
81 | vaddr = i915_gem_object_pin_map(vma->obj, I915_MAP_WB); | ||
82 | if (IS_ERR(vaddr)) { | ||
83 | i915_vma_unpin_and_release(&vma); | ||
84 | return PTR_ERR(vaddr); | ||
85 | } | ||
86 | |||
87 | guc->shared_data = vma; | ||
88 | guc->shared_data_vaddr = vaddr; | ||
89 | |||
90 | return 0; | ||
91 | } | ||
92 | |||
93 | static void guc_shared_data_destroy(struct intel_guc *guc) | ||
94 | { | ||
95 | i915_gem_object_unpin_map(guc->shared_data->obj); | ||
96 | i915_vma_unpin_and_release(&guc->shared_data); | ||
97 | } | ||
98 | |||
99 | int intel_guc_init(struct intel_guc *guc) | ||
100 | { | ||
101 | struct drm_i915_private *dev_priv = guc_to_i915(guc); | ||
102 | int ret; | ||
103 | |||
104 | ret = guc_shared_data_create(guc); | ||
105 | if (ret) | ||
106 | return ret; | ||
107 | GEM_BUG_ON(!guc->shared_data); | ||
108 | |||
109 | /* We need to notify the guc whenever we change the GGTT */ | ||
110 | i915_ggtt_enable_guc(dev_priv); | ||
111 | |||
112 | return 0; | ||
113 | } | ||
114 | |||
115 | void intel_guc_fini(struct intel_guc *guc) | ||
116 | { | ||
117 | struct drm_i915_private *dev_priv = guc_to_i915(guc); | ||
118 | |||
119 | i915_ggtt_disable_guc(dev_priv); | ||
120 | guc_shared_data_destroy(guc); | ||
121 | } | ||
122 | |||
72 | static u32 get_gt_type(struct drm_i915_private *dev_priv) | 123 | static u32 get_gt_type(struct drm_i915_private *dev_priv) |
73 | { | 124 | { |
74 | /* XXX: GT type based on PCI device ID? field seems unused by fw */ | 125 | /* XXX: GT type based on PCI device ID? field seems unused by fw */ |
diff --git a/drivers/gpu/drm/i915/intel_guc.h b/drivers/gpu/drm/i915/intel_guc.h index 59856726d2bc..81659e223e11 100644 --- a/drivers/gpu/drm/i915/intel_guc.h +++ b/drivers/gpu/drm/i915/intel_guc.h | |||
@@ -119,6 +119,8 @@ static inline u32 guc_ggtt_offset(struct i915_vma *vma) | |||
119 | void intel_guc_init_early(struct intel_guc *guc); | 119 | void intel_guc_init_early(struct intel_guc *guc); |
120 | void intel_guc_init_send_regs(struct intel_guc *guc); | 120 | void intel_guc_init_send_regs(struct intel_guc *guc); |
121 | void intel_guc_init_params(struct intel_guc *guc); | 121 | void intel_guc_init_params(struct intel_guc *guc); |
122 | int intel_guc_init(struct intel_guc *guc); | ||
123 | void intel_guc_fini(struct intel_guc *guc); | ||
122 | int intel_guc_send_nop(struct intel_guc *guc, const u32 *action, u32 len); | 124 | int intel_guc_send_nop(struct intel_guc *guc, const u32 *action, u32 len); |
123 | int intel_guc_send_mmio(struct intel_guc *guc, const u32 *action, u32 len); | 125 | int intel_guc_send_mmio(struct intel_guc *guc, const u32 *action, u32 len); |
124 | int intel_guc_sample_forcewake(struct intel_guc *guc); | 126 | int intel_guc_sample_forcewake(struct intel_guc *guc); |
diff --git a/drivers/gpu/drm/i915/intel_guc_submission.c b/drivers/gpu/drm/i915/intel_guc_submission.c index 912ff143d531..c020560c395e 100644 --- a/drivers/gpu/drm/i915/intel_guc_submission.c +++ b/drivers/gpu/drm/i915/intel_guc_submission.c | |||
@@ -447,33 +447,6 @@ static void guc_stage_desc_fini(struct intel_guc *guc, | |||
447 | memset(desc, 0, sizeof(*desc)); | 447 | memset(desc, 0, sizeof(*desc)); |
448 | } | 448 | } |
449 | 449 | ||
450 | static int guc_shared_data_create(struct intel_guc *guc) | ||
451 | { | ||
452 | struct i915_vma *vma; | ||
453 | void *vaddr; | ||
454 | |||
455 | vma = intel_guc_allocate_vma(guc, PAGE_SIZE); | ||
456 | if (IS_ERR(vma)) | ||
457 | return PTR_ERR(vma); | ||
458 | |||
459 | vaddr = i915_gem_object_pin_map(vma->obj, I915_MAP_WB); | ||
460 | if (IS_ERR(vaddr)) { | ||
461 | i915_vma_unpin_and_release(&vma); | ||
462 | return PTR_ERR(vaddr); | ||
463 | } | ||
464 | |||
465 | guc->shared_data = vma; | ||
466 | guc->shared_data_vaddr = vaddr; | ||
467 | |||
468 | return 0; | ||
469 | } | ||
470 | |||
471 | static void guc_shared_data_destroy(struct intel_guc *guc) | ||
472 | { | ||
473 | i915_gem_object_unpin_map(guc->shared_data->obj); | ||
474 | i915_vma_unpin_and_release(&guc->shared_data); | ||
475 | } | ||
476 | |||
477 | /* Construct a Work Item and append it to the GuC's Work Queue */ | 450 | /* Construct a Work Item and append it to the GuC's Work Queue */ |
478 | static void guc_wq_item_append(struct intel_guc_client *client, | 451 | static void guc_wq_item_append(struct intel_guc_client *client, |
479 | u32 target_engine, u32 context_desc, | 452 | u32 target_engine, u32 context_desc, |
@@ -1279,14 +1252,9 @@ int intel_guc_submission_init(struct intel_guc *guc) | |||
1279 | */ | 1252 | */ |
1280 | GEM_BUG_ON(!guc->stage_desc_pool); | 1253 | GEM_BUG_ON(!guc->stage_desc_pool); |
1281 | 1254 | ||
1282 | ret = guc_shared_data_create(guc); | ||
1283 | if (ret) | ||
1284 | goto err_stage_desc_pool; | ||
1285 | GEM_BUG_ON(!guc->shared_data); | ||
1286 | |||
1287 | ret = intel_guc_log_create(guc); | 1255 | ret = intel_guc_log_create(guc); |
1288 | if (ret < 0) | 1256 | if (ret < 0) |
1289 | goto err_shared_data; | 1257 | goto err_stage_desc_pool; |
1290 | 1258 | ||
1291 | ret = guc_preempt_work_create(guc); | 1259 | ret = guc_preempt_work_create(guc); |
1292 | if (ret) | 1260 | if (ret) |
@@ -1304,8 +1272,6 @@ err_wq: | |||
1304 | guc_preempt_work_destroy(guc); | 1272 | guc_preempt_work_destroy(guc); |
1305 | err_log: | 1273 | err_log: |
1306 | intel_guc_log_destroy(guc); | 1274 | intel_guc_log_destroy(guc); |
1307 | err_shared_data: | ||
1308 | guc_shared_data_destroy(guc); | ||
1309 | err_stage_desc_pool: | 1275 | err_stage_desc_pool: |
1310 | guc_stage_desc_pool_destroy(guc); | 1276 | guc_stage_desc_pool_destroy(guc); |
1311 | return ret; | 1277 | return ret; |
@@ -1316,7 +1282,6 @@ void intel_guc_submission_fini(struct intel_guc *guc) | |||
1316 | guc_ads_destroy(guc); | 1282 | guc_ads_destroy(guc); |
1317 | guc_preempt_work_destroy(guc); | 1283 | guc_preempt_work_destroy(guc); |
1318 | intel_guc_log_destroy(guc); | 1284 | intel_guc_log_destroy(guc); |
1319 | guc_shared_data_destroy(guc); | ||
1320 | guc_stage_desc_pool_destroy(guc); | 1285 | guc_stage_desc_pool_destroy(guc); |
1321 | } | 1286 | } |
1322 | 1287 | ||
diff --git a/drivers/gpu/drm/i915/intel_uc.c b/drivers/gpu/drm/i915/intel_uc.c index 461047c86e0d..3040a0e00142 100644 --- a/drivers/gpu/drm/i915/intel_uc.c +++ b/drivers/gpu/drm/i915/intel_uc.c | |||
@@ -24,6 +24,7 @@ | |||
24 | 24 | ||
25 | #include "intel_uc.h" | 25 | #include "intel_uc.h" |
26 | #include "intel_guc_submission.h" | 26 | #include "intel_guc_submission.h" |
27 | #include "intel_guc.h" | ||
27 | #include "i915_drv.h" | 28 | #include "i915_drv.h" |
28 | 29 | ||
29 | /* Reset GuC providing us with fresh state for both GuC and HuC. | 30 | /* Reset GuC providing us with fresh state for both GuC and HuC. |
@@ -204,8 +205,9 @@ int intel_uc_init_hw(struct drm_i915_private *dev_priv) | |||
204 | guc_disable_communication(guc); | 205 | guc_disable_communication(guc); |
205 | gen9_reset_guc_interrupts(dev_priv); | 206 | gen9_reset_guc_interrupts(dev_priv); |
206 | 207 | ||
207 | /* We need to notify the guc whenever we change the GGTT */ | 208 | ret = intel_guc_init(guc); |
208 | i915_ggtt_enable_guc(dev_priv); | 209 | if (ret) |
210 | goto err_out; | ||
209 | 211 | ||
210 | if (USES_GUC_SUBMISSION(dev_priv)) { | 212 | if (USES_GUC_SUBMISSION(dev_priv)) { |
211 | /* | 213 | /* |
@@ -298,7 +300,7 @@ err_submission: | |||
298 | if (USES_GUC_SUBMISSION(dev_priv)) | 300 | if (USES_GUC_SUBMISSION(dev_priv)) |
299 | intel_guc_submission_fini(guc); | 301 | intel_guc_submission_fini(guc); |
300 | err_guc: | 302 | err_guc: |
301 | i915_ggtt_disable_guc(dev_priv); | 303 | intel_guc_fini(guc); |
302 | err_out: | 304 | err_out: |
303 | /* | 305 | /* |
304 | * Note that there is no fallback as either user explicitly asked for | 306 | * Note that there is no fallback as either user explicitly asked for |
@@ -330,5 +332,5 @@ void intel_uc_fini_hw(struct drm_i915_private *dev_priv) | |||
330 | intel_guc_submission_fini(guc); | 332 | intel_guc_submission_fini(guc); |
331 | } | 333 | } |
332 | 334 | ||
333 | i915_ggtt_disable_guc(dev_priv); | 335 | intel_guc_fini(guc); |
334 | } | 336 | } |