aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichał Winiarski <michal.winiarski@intel.com>2017-12-13 17:13:46 -0500
committerChris Wilson <chris@chris-wilson.co.uk>2017-12-14 03:06:52 -0500
commit1bbbca0db722d137ed426368bff42b17808ad11e (patch)
treea9637f211966ac853e0a7a485616ce27c07d7777
parent6ca9a2beb54a385c8cc5e39a9d2ef49945896c64 (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.c51
-rw-r--r--drivers/gpu/drm/i915/intel_guc.h2
-rw-r--r--drivers/gpu/drm/i915/intel_guc_submission.c37
-rw-r--r--drivers/gpu/drm/i915/intel_uc.c10
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
72static 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
93static 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
99int 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
115void 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
72static u32 get_gt_type(struct drm_i915_private *dev_priv) 123static 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)
119void intel_guc_init_early(struct intel_guc *guc); 119void intel_guc_init_early(struct intel_guc *guc);
120void intel_guc_init_send_regs(struct intel_guc *guc); 120void intel_guc_init_send_regs(struct intel_guc *guc);
121void intel_guc_init_params(struct intel_guc *guc); 121void intel_guc_init_params(struct intel_guc *guc);
122int intel_guc_init(struct intel_guc *guc);
123void intel_guc_fini(struct intel_guc *guc);
122int intel_guc_send_nop(struct intel_guc *guc, const u32 *action, u32 len); 124int intel_guc_send_nop(struct intel_guc *guc, const u32 *action, u32 len);
123int intel_guc_send_mmio(struct intel_guc *guc, const u32 *action, u32 len); 125int intel_guc_send_mmio(struct intel_guc *guc, const u32 *action, u32 len);
124int intel_guc_sample_forcewake(struct intel_guc *guc); 126int 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
450static 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
471static 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 */
478static void guc_wq_item_append(struct intel_guc_client *client, 451static 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);
1305err_log: 1273err_log:
1306 intel_guc_log_destroy(guc); 1274 intel_guc_log_destroy(guc);
1307err_shared_data:
1308 guc_shared_data_destroy(guc);
1309err_stage_desc_pool: 1275err_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);
300err_guc: 302err_guc:
301 i915_ggtt_disable_guc(dev_priv); 303 intel_guc_fini(guc);
302err_out: 304err_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}