Re: [Intel-gfx] [PATCH] drm/i915: Release the forgotten connector reference
On ke, 2017-02-01 at 19:58 +, Chris Wilson wrote: > The reference was gained in > intel_modeset_update_connector_atomic_state() [called from > intel_modeset_setup_hw_state()] and is never lost if no client ever > performs a modeset. > > [ 649.836069] WARNING: CPU: 6 PID: 8865 at > drivers/gpu/drm/drm_mode_config.c:424 drm_mode_config_cleanup+0x21b/0x290 > [drm] > [ 649.836078] Modules linked in: i915(-) intel_gtt drm_kms_helper > cfbfillrect syscopyarea cfbimgblt sysfillrect sysimgblt fb_sys_fops > cfbcopyarea drm > [ 649.836099] CPU: 6 PID: 8865 Comm: drv_selftest Not tainted 4.10.0-rc6+ > #908 > [ 649.836106] Hardware name: Intel Corporation 2012 Client Platform/Emerald > Lake 2, BIOS ACRVMBY1.86C.0078.P00.1201161002 01/16/2012 > [ 649.836114] Call Trace: > [ 649.836125] dump_stack+0x4d/0x6f > [ 649.836136] __warn+0xc1/0xe0 > [ 649.836144] warn_slowpath_null+0x18/0x20 > [ 649.836163] drm_mode_config_cleanup+0x21b/0x290 [drm] > [ 649.836213] intel_modeset_cleanup+0x59/0xa0 [i915] > [ 649.836242] i915_driver_unload+0x84/0x170 [i915] > [ 649.836277] i915_pci_remove+0x14/0x20 [i915] > [ 649.836287] pci_device_remove+0x28/0x60 > [ 649.836301] device_release_driver_internal+0x132/0x1d0 > [ 649.836313] driver_detach+0x3a/0x80 > [ 649.836324] bus_remove_driver+0x47/0xa0 > [ 649.836335] driver_unregister+0x27/0x50 > [ 649.836344] pci_unregister_driver+0x34/0xa0 > [ 649.836387] i915_exit+0x1a/0x71 [i915] > [ 649.836401] SyS_delete_module+0x173/0x1c0 > [ 649.836413] entry_SYSCALL_64_fastpath+0x17/0x98 > [ 649.836422] RIP: 0033:0x7f8d5a841ee7 > [ 649.836432] RSP: 002b:7fff89161a28 EFLAGS: 0206 ORIG_RAX: > 00b0 > [ 649.836448] RAX: ffda RBX: 55f6cd1db5c0 RCX: > 7f8d5a841ee7 > [ 649.836458] RDX: RSI: 0800 RDI: > 55f6cd1da7b8 > [ 649.836467] RBP: 7f8d5aaee440 R08: R09: > 7fff89161a58 > [ 649.836476] R10: 0062 R11: 0206 R12: > > [ 649.836486] R13: 55f6cd1d9010 R14: 003a R15: > 7fff891609f0 > [ 649.836514] ---[ end trace 0e529da316e2a3d1 ]--- > [ 649.836536] [drm:drm_mode_config_cleanup [drm]] *ERROR* connector VGA-1 > leaked! > > Signed-off-by: Chris Wilson Reviewed-by: Joonas Lahtinen Regards, Joonas -- Joonas Lahtinen Open Source Technology Center Intel Corporation ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/intel-gfx
Re: [Intel-gfx] [PATCH] drm/i915: Release the forgotten connector reference
On Thu, Feb 02, 2017 at 10:08:57AM +0200, Joonas Lahtinen wrote: > On ke, 2017-02-01 at 19:58 +, Chris Wilson wrote: > > The reference was gained in > > intel_modeset_update_connector_atomic_state() [called from > > intel_modeset_setup_hw_state()] and is never lost if no client ever > > performs a modeset. > > > > [ 649.836069] WARNING: CPU: 6 PID: 8865 at > > drivers/gpu/drm/drm_mode_config.c:424 drm_mode_config_cleanup+0x21b/0x290 > > [drm] > > [ 649.836078] Modules linked in: i915(-) intel_gtt drm_kms_helper > > cfbfillrect syscopyarea cfbimgblt sysfillrect sysimgblt fb_sys_fops > > cfbcopyarea drm > > [ 649.836099] CPU: 6 PID: 8865 Comm: drv_selftest Not tainted 4.10.0-rc6+ > > #908 > > [ 649.836106] Hardware name: Intel Corporation 2012 Client > > Platform/Emerald Lake 2, BIOS ACRVMBY1.86C.0078.P00.1201161002 01/16/2012 > > [ 649.836114] Call Trace: > > [ 649.836125] dump_stack+0x4d/0x6f > > [ 649.836136] __warn+0xc1/0xe0 > > [ 649.836144] warn_slowpath_null+0x18/0x20 > > [ 649.836163] drm_mode_config_cleanup+0x21b/0x290 [drm] > > [ 649.836213] intel_modeset_cleanup+0x59/0xa0 [i915] > > [ 649.836242] i915_driver_unload+0x84/0x170 [i915] > > [ 649.836277] i915_pci_remove+0x14/0x20 [i915] > > [ 649.836287] pci_device_remove+0x28/0x60 > > [ 649.836301] device_release_driver_internal+0x132/0x1d0 > > [ 649.836313] driver_detach+0x3a/0x80 > > [ 649.836324] bus_remove_driver+0x47/0xa0 > > [ 649.836335] driver_unregister+0x27/0x50 > > [ 649.836344] pci_unregister_driver+0x34/0xa0 > > [ 649.836387] i915_exit+0x1a/0x71 [i915] > > [ 649.836401] SyS_delete_module+0x173/0x1c0 > > [ 649.836413] entry_SYSCALL_64_fastpath+0x17/0x98 > > [ 649.836422] RIP: 0033:0x7f8d5a841ee7 > > [ 649.836432] RSP: 002b:7fff89161a28 EFLAGS: 0206 ORIG_RAX: > > 00b0 > > [ 649.836448] RAX: ffda RBX: 55f6cd1db5c0 RCX: > > 7f8d5a841ee7 > > [ 649.836458] RDX: RSI: 0800 RDI: > > 55f6cd1da7b8 > > [ 649.836467] RBP: 7f8d5aaee440 R08: R09: > > 7fff89161a58 > > [ 649.836476] R10: 0062 R11: 0206 R12: > > > > [ 649.836486] R13: 55f6cd1d9010 R14: 003a R15: > > 7fff891609f0 > > [ 649.836514] ---[ end trace 0e529da316e2a3d1 ]--- > > [ 649.836536] [drm:drm_mode_config_cleanup [drm]] *ERROR* connector VGA-1 > > leaked! > > > > Signed-off-by: Chris Wilson > > Reviewed-by: Joonas Lahtinen I'm hoping that this won't be required after Maarten's force disable all CRTC on unload. We will see. -Chris -- Chris Wilson, Intel Open Source Technology Centre ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/intel-gfx
Re: [Intel-gfx] [PATCH] drm/i915: Release the forgotten connector reference
On Wed, Feb 01, 2017 at 07:58:31PM +, Chris Wilson wrote: > The reference was gained in > intel_modeset_update_connector_atomic_state() [called from > intel_modeset_setup_hw_state()] and is never lost if no client ever > performs a modeset. > > [ 649.836069] WARNING: CPU: 6 PID: 8865 at > drivers/gpu/drm/drm_mode_config.c:424 drm_mode_config_cleanup+0x21b/0x290 > [drm] > [ 649.836078] Modules linked in: i915(-) intel_gtt drm_kms_helper > cfbfillrect syscopyarea cfbimgblt sysfillrect sysimgblt fb_sys_fops > cfbcopyarea drm > [ 649.836099] CPU: 6 PID: 8865 Comm: drv_selftest Not tainted 4.10.0-rc6+ > #908 > [ 649.836106] Hardware name: Intel Corporation 2012 Client Platform/Emerald > Lake 2, BIOS ACRVMBY1.86C.0078.P00.1201161002 01/16/2012 > [ 649.836114] Call Trace: > [ 649.836125] dump_stack+0x4d/0x6f > [ 649.836136] __warn+0xc1/0xe0 > [ 649.836144] warn_slowpath_null+0x18/0x20 > [ 649.836163] drm_mode_config_cleanup+0x21b/0x290 [drm] > [ 649.836213] intel_modeset_cleanup+0x59/0xa0 [i915] > [ 649.836242] i915_driver_unload+0x84/0x170 [i915] > [ 649.836277] i915_pci_remove+0x14/0x20 [i915] > [ 649.836287] pci_device_remove+0x28/0x60 > [ 649.836301] device_release_driver_internal+0x132/0x1d0 > [ 649.836313] driver_detach+0x3a/0x80 > [ 649.836324] bus_remove_driver+0x47/0xa0 > [ 649.836335] driver_unregister+0x27/0x50 > [ 649.836344] pci_unregister_driver+0x34/0xa0 > [ 649.836387] i915_exit+0x1a/0x71 [i915] > [ 649.836401] SyS_delete_module+0x173/0x1c0 > [ 649.836413] entry_SYSCALL_64_fastpath+0x17/0x98 > [ 649.836422] RIP: 0033:0x7f8d5a841ee7 > [ 649.836432] RSP: 002b:7fff89161a28 EFLAGS: 0206 ORIG_RAX: > 00b0 > [ 649.836448] RAX: ffda RBX: 55f6cd1db5c0 RCX: > 7f8d5a841ee7 > [ 649.836458] RDX: RSI: 0800 RDI: > 55f6cd1da7b8 > [ 649.836467] RBP: 7f8d5aaee440 R08: R09: > 7fff89161a58 > [ 649.836476] R10: 0062 R11: 0206 R12: > > [ 649.836486] R13: 55f6cd1d9010 R14: 003a R15: > 7fff891609f0 > [ 649.836514] ---[ end trace 0e529da316e2a3d1 ]--- > [ 649.836536] [drm:drm_mode_config_cleanup [drm]] *ERROR* connector VGA-1 > leaked! > > Signed-off-by: Chris Wilson Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=95004 -Chris -- Chris Wilson, Intel Open Source Technology Centre ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/intel-gfx
[Intel-gfx] ✓ Fi.CI.BAT: success for drm/i915: Enable atomic support by default on supported platforms.
== Series Details == Series: drm/i915: Enable atomic support by default on supported platforms. URL : https://patchwork.freedesktop.org/series/18970/ State : success == Summary == Series 18970v1 drm/i915: Enable atomic support by default on supported platforms. https://patchwork.freedesktop.org/api/1.0/series/18970/revisions/1/mbox/ Test kms_cursor_legacy: Subgroup basic-busy-flip-before-cursor-atomic: skip -> PASS (fi-bxt-j4205) skip -> PASS (fi-skl-6260u) skip -> PASS (fi-skl-6700hq) skip -> PASS (fi-skl-6770hq) skip -> PASS (fi-snb-2520m) skip -> PASS (fi-ivb-3520m) skip -> PASS (fi-ivb-3770) skip -> PASS (fi-snb-2600) skip -> PASS (fi-skl-6700k) skip -> PASS (fi-kbl-7500u) skip -> PASS (fi-bdw-5557u) skip -> PASS (fi-hsw-4770) skip -> PASS (fi-hsw-4770r) Subgroup basic-flip-after-cursor-atomic: skip -> PASS (fi-bxt-j4205) skip -> PASS (fi-skl-6260u) skip -> PASS (fi-skl-6700hq) skip -> PASS (fi-skl-6770hq) skip -> PASS (fi-snb-2520m) skip -> PASS (fi-ivb-3520m) skip -> PASS (fi-ivb-3770) skip -> PASS (fi-snb-2600) skip -> PASS (fi-skl-6700k) skip -> PASS (fi-kbl-7500u) skip -> PASS (fi-bdw-5557u) skip -> PASS (fi-hsw-4770) skip -> PASS (fi-hsw-4770r) Subgroup basic-flip-before-cursor-atomic: skip -> PASS (fi-bxt-j4205) skip -> PASS (fi-skl-6260u) skip -> PASS (fi-skl-6700hq) skip -> PASS (fi-skl-6770hq) skip -> PASS (fi-snb-2520m) skip -> PASS (fi-ivb-3520m) skip -> PASS (fi-ivb-3770) skip -> PASS (fi-snb-2600) skip -> PASS (fi-skl-6700k) skip -> PASS (fi-kbl-7500u) skip -> PASS (fi-bdw-5557u) skip -> PASS (fi-hsw-4770) skip -> PASS (fi-hsw-4770r) fi-bdw-5557u total:247 pass:236 dwarn:0 dfail:0 fail:0 skip:11 fi-bsw-n3050 total:247 pass:208 dwarn:0 dfail:0 fail:0 skip:39 fi-bxt-j4205 total:247 pass:228 dwarn:0 dfail:0 fail:0 skip:19 fi-bxt-t5700 total:78 pass:65 dwarn:0 dfail:0 fail:0 skip:12 fi-byt-j1900 total:247 pass:220 dwarn:0 dfail:0 fail:0 skip:27 fi-byt-n2820 total:247 pass:216 dwarn:0 dfail:0 fail:0 skip:31 fi-hsw-4770 total:247 pass:231 dwarn:0 dfail:0 fail:0 skip:16 fi-hsw-4770r total:247 pass:231 dwarn:0 dfail:0 fail:0 skip:16 fi-ivb-3520m total:247 pass:229 dwarn:0 dfail:0 fail:0 skip:18 fi-ivb-3770 total:247 pass:229 dwarn:0 dfail:0 fail:0 skip:18 fi-kbl-7500u total:247 pass:227 dwarn:0 dfail:0 fail:2 skip:18 fi-skl-6260u total:247 pass:237 dwarn:0 dfail:0 fail:0 skip:10 fi-skl-6700hqtotal:247 pass:230 dwarn:0 dfail:0 fail:0 skip:17 fi-skl-6700k total:247 pass:225 dwarn:4 dfail:0 fail:0 skip:18 fi-skl-6770hqtotal:247 pass:237 dwarn:0 dfail:0 fail:0 skip:10 fi-snb-2520m total:247 pass:219 dwarn:0 dfail:0 fail:0 skip:28 fi-snb-2600 total:247 pass:218 dwarn:0 dfail:0 fail:0 skip:29 a0cc425b0034c42eb3830f7dd612ac2a132a874c drm-tip: 2017y-02m-01d-17h-17m-34s UTC integration manifest b519f7f drm/i915: Enable atomic support by default on supported platforms. == Logs == For more details see: https://intel-gfx-ci.01.org/CI/Patchwork_3670/ ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/intel-gfx
Re: [Intel-gfx] [PATCH v1½ 07/13] drm/i915/dp: cache common rates with sink rates
On Thu, 02 Feb 2017, "Pandiyan, Dhinakaran" wrote: > On Thu, 2017-01-26 at 21:44 +0200, Jani Nikula wrote: >> Now that source rates are static and sink rates are updated whenever >> DPCD is updated, we can do and cache the intersection of them whenever >> sink rates are updated. This reduces code complexity, as we don't have >> to keep calling the functions to intersect. We also get rid of several >> common rates arrays on stack. >> >> Limiting the common rates by a max link rate can be done by picking the >> first N elements of the cached common rates. >> >> Cc: Manasi Navare >> Cc: Ville Syrjälä >> Signed-off-by: Jani Nikula >> --- >> drivers/gpu/drm/i915/intel_dp.c | 66 >> ++-- >> drivers/gpu/drm/i915/intel_drv.h | 3 ++ >> 2 files changed, 40 insertions(+), 29 deletions(-) >> >> diff --git a/drivers/gpu/drm/i915/intel_dp.c >> b/drivers/gpu/drm/i915/intel_dp.c >> index f163391e61fa..7d3ff92000c3 100644 >> --- a/drivers/gpu/drm/i915/intel_dp.c >> +++ b/drivers/gpu/drm/i915/intel_dp.c >> @@ -283,17 +283,29 @@ static int intel_dp_find_rate(const int *rates, int >> len, int rate) >> return -1; >> } >> >> -static int intel_dp_common_rates(struct intel_dp *intel_dp, >> - int *common_rates) >> +static void intel_dp_set_common_rates(struct intel_dp *intel_dp) >> { >> -int max_rate = intel_dp->max_sink_link_rate; >> -int i, common_len; >> +WARN_ON(!intel_dp->num_source_rates || !intel_dp->num_sink_rates); >> >> -common_len = intersect_rates(intel_dp->source_rates, >> - intel_dp->num_source_rates, >> - intel_dp->sink_rates, >> - intel_dp->num_sink_rates, >> - common_rates); >> +intel_dp->num_common_rates = intersect_rates(intel_dp->source_rates, >> + intel_dp->num_source_rates, >> + intel_dp->sink_rates, >> + intel_dp->num_sink_rates, >> + intel_dp->common_rates); > > > Do we need to pass all these args given that all of them are now > available in intel_dp and intersect_rates() is not used anywhere else? My reasoning is that with this interface intersect_rates remains generic, independent of intel_dp or anything else, and you can be sure it's stateless. BR, Jani. > > -DK >> + >> +/* Paranoia, there should always be something in common. */ >> +if (WARN_ON(intel_dp->num_common_rates == 0)) { >> +intel_dp->common_rates[0] = default_rates[0]; >> +intel_dp->num_common_rates = 1; >> +} >> +} >> + >> +/* get length of common rates potentially limited by max_rate */ >> +static int intel_dp_common_len_rate_limit(struct intel_dp *intel_dp, >> + int max_rate) >> +{ >> +const int *common_rates = intel_dp->common_rates; >> +int i, common_len = intel_dp->num_common_rates; >> >> /* Limit results by potentially reduced max rate */ >> for (i = 0; i < common_len; i++) { >> @@ -304,25 +316,23 @@ static int intel_dp_common_rates(struct intel_dp >> *intel_dp, >> return 0; >> } >> >> -static int intel_dp_link_rate_index(struct intel_dp *intel_dp, >> -int *common_rates, int link_rate) >> +static int intel_dp_link_rate_index(struct intel_dp *intel_dp, int >> link_rate) >> { >> int common_len; >> >> -common_len = intel_dp_common_rates(intel_dp, common_rates); >> +common_len = intel_dp_common_len_rate_limit(intel_dp, >> + >> intel_dp->max_sink_link_rate); >> >> -return intel_dp_find_rate(common_rates, common_len, link_rate); >> +return intel_dp_find_rate(intel_dp->common_rates, common_len, >> link_rate); >> } >> >> int intel_dp_get_link_train_fallback_values(struct intel_dp *intel_dp, >> int link_rate, uint8_t lane_count) >> { >> -int common_rates[DP_MAX_SUPPORTED_RATES]; >> +const int *common_rates = intel_dp->common_rates; >> int link_rate_index; >> >> -link_rate_index = intel_dp_link_rate_index(intel_dp, >> - common_rates, >> - link_rate); >> +link_rate_index = intel_dp_link_rate_index(intel_dp, link_rate); >> if (link_rate_index > 0) { >> intel_dp->max_sink_link_rate = common_rates[link_rate_index - >> 1]; >> intel_dp->max_sink_lane_count = lane_count; >> @@ -1509,8 +1519,6 @@ static void snprintf_int_array(char *str, size_t len, >> >> static void intel_dp_print_rates(struct intel_dp *intel_dp) >> { >> -int common_len; >> -int common_rates[DP_MAX_SUPPORTED_RATES]; >> char str[128]; /* FIXME: too
Re: [Intel-gfx] [PATCH v1½ 12/13] drm/i915/dp: localize link rate index variable more
On Thu, 02 Feb 2017, Manasi Navare wrote: > On Thu, Jan 26, 2017 at 09:44:26PM +0200, Jani Nikula wrote: >> Localize link_rate_index to the if block, and rename to just index to >> reduce indent. >> >> Cc: Manasi Navare >> Cc: Ville Syrjälä >> Signed-off-by: Jani Nikula >> --- >> drivers/gpu/drm/i915/intel_dp.c | 13 +++-- >> 1 file changed, 7 insertions(+), 6 deletions(-) >> >> diff --git a/drivers/gpu/drm/i915/intel_dp.c >> b/drivers/gpu/drm/i915/intel_dp.c >> index 7704d32286a3..429dc70c251a 100644 >> --- a/drivers/gpu/drm/i915/intel_dp.c >> +++ b/drivers/gpu/drm/i915/intel_dp.c >> @@ -1639,7 +1639,6 @@ intel_dp_compute_config(struct intel_encoder *encoder, >> /* Conveniently, the link BW constants become indices with a shift...*/ >> int min_clock = 0; >> int max_clock; >> -int link_rate_index; >> int bpp, mode_rate; >> int link_avail, link_clock; >> const int *common_rates = intel_dp->common_rates; >> @@ -1684,11 +1683,13 @@ intel_dp_compute_config(struct intel_encoder >> *encoder, >> >> /* Use values requested by Compliance Test Request */ >> if (intel_dp->compliance.test_type == DP_TEST_LINK_TRAINING) { >> -link_rate_index = intel_dp_find_rate(intel_dp->common_rates, >> - intel_dp->num_common_rates, >> - >> intel_dp->compliance.test_link_rate); > > Can we not pass just the common_rates as an argument to this function > since common_rates is already assigned intel_dp->common_rates. Do you mean just pass intel_dp to intel_dp_find_rate? If yes, I think this keeps intel_dp_find_rate generic, independent of intel_dp or anything else, and you can be sure it's stateless (same as intersect_rates). If you don't mean that, I don't know what you mean... please explain. BR, Jani. > > Regards > Manasi > > >> -if (link_rate_index >= 0) >> -min_clock = max_clock = link_rate_index; >> +int index; >> + >> +index = intel_dp_find_rate(intel_dp->common_rates, >> + intel_dp->num_common_rates, >> + intel_dp->compliance.test_link_rate); >> +if (index >= 0) >> +min_clock = max_clock = index; >> min_lane_count = max_lane_count = >> intel_dp->compliance.test_lane_count; >> } >> DRM_DEBUG_KMS("DP link computation with max lane count %i " >> -- >> 2.1.4 >> > ___ > Intel-gfx mailing list > Intel-gfx@lists.freedesktop.org > https://lists.freedesktop.org/mailman/listinfo/intel-gfx -- Jani Nikula, Intel Open Source Technology Center ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/intel-gfx
Re: [Intel-gfx] [PATCH v1½ 03/13] drm/i915/dp: rename rate_to_index() to intel_dp_find_rate() and reuse
On Wed, 01 Feb 2017, "Pandiyan, Dhinakaran" wrote: > On Thu, 2017-01-26 at 21:44 +0200, Jani Nikula wrote: >> Rename the function, move it at the top, and reuse in >> intel_dp_link_rate_index(). If there was a reason in the past to use >> reverse search order here, there isn't now. >> >> Cc: Manasi Navare >> Cc: Ville Syrjälä >> Signed-off-by: Jani Nikula >> --- >> drivers/gpu/drm/i915/intel_dp.c | 33 ++--- >> 1 file changed, 14 insertions(+), 19 deletions(-) >> >> diff --git a/drivers/gpu/drm/i915/intel_dp.c >> b/drivers/gpu/drm/i915/intel_dp.c >> index 1d66737a3a0f..f3068ff670a1 100644 >> --- a/drivers/gpu/drm/i915/intel_dp.c >> +++ b/drivers/gpu/drm/i915/intel_dp.c >> @@ -266,6 +266,17 @@ static int intersect_rates(const int *source_rates, int >> source_len, >> return k; >> } >> >> +static int intel_dp_find_rate(const int *rates, int len, int rate) > > I wonder if the function name can be more intuitive. The argument is > rate and the function name indicates it also returns rate. I can't tell > what the function does by it's name. Feel free to ignore this comment as > I might be missing some context. Naming is hard. intel_dp_rate_index? BR, Jani. > > -DK > >> +{ >> +int i; >> + >> +for (i = 0; i < len; i++) >> +if (rate == rates[i]) >> +return i; >> + >> +return -1; >> +} >> + >> static int intel_dp_common_rates(struct intel_dp *intel_dp, >> int *common_rates) >> { >> @@ -284,15 +295,10 @@ static int intel_dp_link_rate_index(struct intel_dp >> *intel_dp, >> int *common_rates, int link_rate) >> { >> int common_len; >> -int index; >> >> common_len = intel_dp_common_rates(intel_dp, common_rates); >> -for (index = 0; index < common_len; index++) { >> -if (link_rate == common_rates[common_len - index - 1]) >> -return common_len - index - 1; >> -} >> >> -return -1; >> +return intel_dp_find_rate(common_rates, common_len, link_rate); >> } >> >> int intel_dp_get_link_train_fallback_values(struct intel_dp *intel_dp, >> @@ -1542,17 +1548,6 @@ bool intel_dp_read_desc(struct intel_dp *intel_dp) >> return true; >> } >> >> -static int rate_to_index(const int *rates, int len, int rate) >> -{ >> -int i; >> - >> -for (i = 0; i < len; i++) >> -if (rate == rates[i]) >> -return i; >> - >> -return -1; >> -} >> - >> int >> intel_dp_max_link_rate(struct intel_dp *intel_dp) >> { >> @@ -1568,8 +1563,8 @@ intel_dp_max_link_rate(struct intel_dp *intel_dp) >> >> int intel_dp_rate_select(struct intel_dp *intel_dp, int rate) >> { >> -int i = rate_to_index(intel_dp->sink_rates, intel_dp->num_sink_rates, >> - rate); >> +int i = intel_dp_find_rate(intel_dp->sink_rates, >> + intel_dp->num_sink_rates, rate); >> >> if (WARN_ON(i < 0)) >> i = 0; > -- Jani Nikula, Intel Open Source Technology Center ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/intel-gfx
[Intel-gfx] [PATCH v2 4/5] drm/i915: Capture module parameters for the GPU error state
They include useful material such as what mode the VM address space is running in, what submission mode, extra quirks, etc. v2: Undef the right macro, use type specific pretty printers Signed-off-by: Chris Wilson Reviewed-by: Joonas Lahtinen #v1 --- drivers/gpu/drm/i915/i915_drv.h | 1 + drivers/gpu/drm/i915/i915_gpu_error.c | 48 ++- 2 files changed, 42 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 15b6c75ebade..5bcde9395126 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -904,6 +904,7 @@ struct drm_i915_error_state { u32 reset_count; u32 suspend_count; struct intel_device_info device_info; + struct i915_params params; /* Generic register state */ u32 eir; diff --git a/drivers/gpu/drm/i915/i915_gpu_error.c b/drivers/gpu/drm/i915/i915_gpu_error.c index 5283fe815a4d..58b6296372bf 100644 --- a/drivers/gpu/drm/i915/i915_gpu_error.c +++ b/drivers/gpu/drm/i915/i915_gpu_error.c @@ -546,6 +546,35 @@ static void err_print_capabilities(struct drm_i915_error_state_buf *m, #undef PRINT_FLAG } +static void err_param_bool(struct drm_i915_error_state_buf *m, + const char *name, + param_bool x) +{ + err_printf(m, "%s: %s\n", name, yesno(x)); +} + +static void err_param_int(struct drm_i915_error_state_buf *m, + const char *name, + param_int x) +{ + err_printf(m, "%s: %d\n", name, x); +} + +static void err_param_uint(struct drm_i915_error_state_buf *m, + const char *name, + param_uint x) +{ + err_printf(m, "%s: %u\n", name, x); +} + +static void err_print_params(struct drm_i915_error_state_buf *m, +const struct i915_params *p) +{ +#define PRINT(T, x) err_##T(m, #x, p->x); + I915_PARAMS_FOR_EACH(PRINT); +#undef PRINT +} + int i915_error_state_to_str(struct drm_i915_error_state_buf *m, const struct i915_error_state_file_priv *error_priv) { @@ -568,7 +597,6 @@ int i915_error_state_to_str(struct drm_i915_error_state_buf *m, error->boottime.tv_sec, error->boottime.tv_usec); err_printf(m, "Uptime: %ld s %ld us\n", error->uptime.tv_sec, error->uptime.tv_usec); - err_print_capabilities(m, &error->device_info); for (i = 0; i < ARRAY_SIZE(error->engine); i++) { if (error->engine[i].hangcheck_stalled && @@ -588,6 +616,7 @@ int i915_error_state_to_str(struct drm_i915_error_state_buf *m, err_printf(m, "PCI Subsystem: %04x:%04x\n", pdev->subsystem_vendor, pdev->subsystem_device); + err_printf(m, "IOMMU enabled?: %d\n", error->iommu); if (HAS_CSR(dev_priv)) { @@ -730,6 +759,9 @@ int i915_error_state_to_str(struct drm_i915_error_state_buf *m, if (error->display) intel_display_print_error_state(m, dev_priv, error->display); + err_print_capabilities(m, &error->device_info); + err_print_params(m, &error->params); + out: if (m->bytes == 0 && m->err) return m->err; @@ -1587,6 +1619,14 @@ static int capture(void *data) { struct drm_i915_error_state *error = data; + do_gettimeofday(&error->time); + error->boottime = ktime_to_timeval(ktime_get_boottime()); + error->uptime = + ktime_to_timeval(ktime_sub(ktime_get(), + error->i915->gt.last_init_time)); + + error->params = i915; + i915_capture_gen_state(error->i915, error); i915_capture_reg_state(error->i915, error); i915_gem_record_fences(error->i915, error); @@ -1595,12 +1635,6 @@ static int capture(void *data) i915_capture_pinned_buffers(error->i915, error); i915_gem_capture_guc_log_buffer(error->i915, error); - do_gettimeofday(&error->time); - error->boottime = ktime_to_timeval(ktime_get_boottime()); - error->uptime = - ktime_to_timeval(ktime_sub(ktime_get(), - error->i915->gt.last_init_time)); - error->overlay = intel_overlay_capture_error_state(error->i915); error->display = intel_display_capture_error_state(error->i915); -- 2.11.0 ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/intel-gfx
[Intel-gfx] [PATCH v2 3/5] drm/i915: Use bool i915_param.alpha_support
The alpha_support module option can only take one of two values, so assign it to a boolean type. The only advantage is in pretty printing via /sys/module/i915/parameters/alpha_support and elsewhere. Signed-off-by: Chris Wilson Cc: Jani Nikula Cc: Rodrigo Vivi Cc: Daniel Vetter --- drivers/gpu/drm/i915/i915_params.c | 2 +- drivers/gpu/drm/i915/i915_params.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_params.c b/drivers/gpu/drm/i915/i915_params.c index 0e280fbd52f1..c2679fa7ed11 100644 --- a/drivers/gpu/drm/i915/i915_params.c +++ b/drivers/gpu/drm/i915/i915_params.c @@ -145,7 +145,7 @@ MODULE_PARM_DESC(enable_psr, "Enable PSR " "(0=disabled, 1=enabled - link mode chosen per-platform, 2=force link-standby mode, 3=force link-off mode) " "Default: -1 (use per-chip default)"); -module_param_named_unsafe(alpha_support, i915.alpha_support, int, 0400); +module_param_named_unsafe(alpha_support, i915.alpha_support, bool, 0400); MODULE_PARM_DESC(alpha_support, "Enable alpha quality driver support for latest hardware. " "See also CONFIG_DRM_I915_ALPHA_SUPPORT."); diff --git a/drivers/gpu/drm/i915/i915_params.h b/drivers/gpu/drm/i915/i915_params.h index 668f88a79842..87ac6ed995d3 100644 --- a/drivers/gpu/drm/i915/i915_params.h +++ b/drivers/gpu/drm/i915/i915_params.h @@ -44,7 +44,6 @@ typedef unsigned int param_uint; func(param_int, enable_ppgtt); \ func(param_int, enable_execlists); \ func(param_int, enable_psr); \ - func(param_uint, alpha_support); \ func(param_int, disable_power_well); \ func(param_int, enable_ips); \ func(param_int, invert_brightness); \ @@ -56,6 +55,7 @@ typedef unsigned int param_uint; func(param_int, edp_vswing); \ func(param_uint, inject_load_failure); \ /* leave bools at the end to not create holes */ \ + func(param_bool, alpha_support); \ func(param_bool, enable_cmd_parser); \ func(param_bool, enable_hangcheck); \ func(param_bool, fastboot); \ -- 2.11.0 ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/intel-gfx
[Intel-gfx] [PATCH v2 5/5] drm/i915: Show the current i915_params in debugfs/i915_capabilites
Alongside the hw capabilities, it is useful to know which of those have been overridden by the user setting module parameters. Signed-off-by: Chris Wilson --- drivers/gpu/drm/i915/i915_debugfs.c | 20 1 file changed, 20 insertions(+) diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index 3ae06568df7b..1568cc4286c0 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -61,6 +61,21 @@ drm_add_fake_info_node(struct drm_minor *minor, return 0; } +static void seq_param_bool(struct seq_file *m, const char *name, param_bool x) +{ + seq_printf(m, "i915.%s=%s\n", name, yesno(x)); +} + +static void seq_param_int(struct seq_file *m, const char *name, param_int x) +{ + seq_printf(m, "i915.%s=%d\n", name, x); +} + +static void seq_param_uint(struct seq_file *m, const char *name, param_uint x) +{ + seq_printf(m, "i915.%s=%u\n", name, x); +} + static int i915_capabilities(struct seq_file *m, void *data) { struct drm_i915_private *dev_priv = node_to_i915(m->private); @@ -69,10 +84,15 @@ static int i915_capabilities(struct seq_file *m, void *data) seq_printf(m, "gen: %d\n", INTEL_GEN(dev_priv)); seq_printf(m, "platform: %s\n", intel_platform_name(info->platform)); seq_printf(m, "pch: %d\n", INTEL_PCH_TYPE(dev_priv)); + #define PRINT_FLAG(x) seq_printf(m, #x ": %s\n", yesno(info->x)) DEV_INFO_FOR_EACH_FLAG(PRINT_FLAG); #undef PRINT_FLAG +#define PRINT(T, x) seq_##T(m, #x, i915.x); + I915_PARAMS_FOR_EACH(PRINT); +#undef PRINT + return 0; } -- 2.11.0 ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/intel-gfx
[Intel-gfx] [PATCH v2 1/5] drm/i915: Generate i915_params {} using a macro
I want to print the struct from the error state and so would like to use the existing struct definition as the template ala DEV_INFO* v2: Use MEMBER() rather than p(). Signed-off-by: Chris Wilson Reviewed-by: Joonas Lahtinen --- drivers/gpu/drm/i915/i915_params.h | 81 -- 1 file changed, 43 insertions(+), 38 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_params.h b/drivers/gpu/drm/i915/i915_params.h index 8e433de04679..9a8c60342a82 100644 --- a/drivers/gpu/drm/i915/i915_params.h +++ b/drivers/gpu/drm/i915/i915_params.h @@ -27,46 +27,51 @@ #include /* for __read_mostly */ +#define I915_PARAMS_FOR_EACH(func) \ + func(int, modeset); \ + func(int, panel_ignore_lid); \ + func(int, semaphores); \ + func(int, lvds_channel_mode); \ + func(int, panel_use_ssc); \ + func(int, vbt_sdvo_panel_type); \ + func(int, enable_rc6); \ + func(int, enable_dc); \ + func(int, enable_fbc); \ + func(int, enable_ppgtt); \ + func(int, enable_execlists); \ + func(int, enable_psr); \ + func(unsigned int, alpha_support); \ + func(int, disable_power_well); \ + func(int, enable_ips); \ + func(int, invert_brightness); \ + func(int, enable_guc_loading); \ + func(int, enable_guc_submission); \ + func(int, guc_log_level); \ + func(int, use_mmio_flip); \ + func(int, mmio_debug); \ + func(int, edp_vswing); \ + func(unsigned int, inject_load_failure); \ + /* leave bools at the end to not create holes */ \ + func(bool, enable_cmd_parser); \ + func(bool, enable_hangcheck); \ + func(bool, fastboot); \ + func(bool, prefault_disable); \ + func(bool, load_detect_test); \ + func(bool, force_reset_modeset_test); \ + func(bool, reset); \ + func(bool, error_capture); \ + func(bool, disable_display); \ + func(bool, verbose_state_checks); \ + func(bool, nuclear_pageflip); \ + func(bool, enable_dp_mst); \ + func(bool, enable_dpcd_backlight); \ + func(bool, enable_gvt) + +#define MEMBER(T, member) T member struct i915_params { - int modeset; - int panel_ignore_lid; - int semaphores; - int lvds_channel_mode; - int panel_use_ssc; - int vbt_sdvo_panel_type; - int enable_rc6; - int enable_dc; - int enable_fbc; - int enable_ppgtt; - int enable_execlists; - int enable_psr; - unsigned int alpha_support; - int disable_power_well; - int enable_ips; - int invert_brightness; - int enable_guc_loading; - int enable_guc_submission; - int guc_log_level; - int use_mmio_flip; - int mmio_debug; - int edp_vswing; - unsigned int inject_load_failure; - /* leave bools at the end to not create holes */ - bool enable_cmd_parser; - bool enable_hangcheck; - bool fastboot; - bool prefault_disable; - bool load_detect_test; - bool force_reset_modeset_test; - bool reset; - bool error_capture; - bool disable_display; - bool verbose_state_checks; - bool nuclear_pageflip; - bool enable_dp_mst; - bool enable_dpcd_backlight; - bool enable_gvt; + I915_PARAMS_FOR_EACH(MEMBER); }; +#undef MEMBER extern struct i915_params i915 __read_mostly; -- 2.11.0 ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/intel-gfx
[Intel-gfx] [PATCH v2 2/5] drm/i915: Convert i915_params to use shortnames for its types
In order to specialise a pretty printer for different types of module parameters using macro construction, the type names must be a single word. Use typedefs to construct the parameters using the modparams type shortnames. Signed-off-by: Chris Wilson --- drivers/gpu/drm/i915/i915_params.h | 78 -- 1 file changed, 41 insertions(+), 37 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_params.h b/drivers/gpu/drm/i915/i915_params.h index 9a8c60342a82..668f88a79842 100644 --- a/drivers/gpu/drm/i915/i915_params.h +++ b/drivers/gpu/drm/i915/i915_params.h @@ -27,45 +27,49 @@ #include /* for __read_mostly */ +typedef bool param_bool; +typedef int param_int; +typedef unsigned int param_uint; + #define I915_PARAMS_FOR_EACH(func) \ - func(int, modeset); \ - func(int, panel_ignore_lid); \ - func(int, semaphores); \ - func(int, lvds_channel_mode); \ - func(int, panel_use_ssc); \ - func(int, vbt_sdvo_panel_type); \ - func(int, enable_rc6); \ - func(int, enable_dc); \ - func(int, enable_fbc); \ - func(int, enable_ppgtt); \ - func(int, enable_execlists); \ - func(int, enable_psr); \ - func(unsigned int, alpha_support); \ - func(int, disable_power_well); \ - func(int, enable_ips); \ - func(int, invert_brightness); \ - func(int, enable_guc_loading); \ - func(int, enable_guc_submission); \ - func(int, guc_log_level); \ - func(int, use_mmio_flip); \ - func(int, mmio_debug); \ - func(int, edp_vswing); \ - func(unsigned int, inject_load_failure); \ + func(param_int, modeset); \ + func(param_int, panel_ignore_lid); \ + func(param_int, semaphores); \ + func(param_int, lvds_channel_mode); \ + func(param_int, panel_use_ssc); \ + func(param_int, vbt_sdvo_panel_type); \ + func(param_int, enable_rc6); \ + func(param_int, enable_dc); \ + func(param_int, enable_fbc); \ + func(param_int, enable_ppgtt); \ + func(param_int, enable_execlists); \ + func(param_int, enable_psr); \ + func(param_uint, alpha_support); \ + func(param_int, disable_power_well); \ + func(param_int, enable_ips); \ + func(param_int, invert_brightness); \ + func(param_int, enable_guc_loading); \ + func(param_int, enable_guc_submission); \ + func(param_int, guc_log_level); \ + func(param_int, use_mmio_flip); \ + func(param_int, mmio_debug); \ + func(param_int, edp_vswing); \ + func(param_uint, inject_load_failure); \ /* leave bools at the end to not create holes */ \ - func(bool, enable_cmd_parser); \ - func(bool, enable_hangcheck); \ - func(bool, fastboot); \ - func(bool, prefault_disable); \ - func(bool, load_detect_test); \ - func(bool, force_reset_modeset_test); \ - func(bool, reset); \ - func(bool, error_capture); \ - func(bool, disable_display); \ - func(bool, verbose_state_checks); \ - func(bool, nuclear_pageflip); \ - func(bool, enable_dp_mst); \ - func(bool, enable_dpcd_backlight); \ - func(bool, enable_gvt) + func(param_bool, enable_cmd_parser); \ + func(param_bool, enable_hangcheck); \ + func(param_bool, fastboot); \ + func(param_bool, prefault_disable); \ + func(param_bool, load_detect_test); \ + func(param_bool, force_reset_modeset_test); \ + func(param_bool, reset); \ + func(param_bool, error_capture); \ + func(param_bool, disable_display); \ + func(param_bool, verbose_state_checks); \ + func(param_bool, nuclear_pageflip); \ + func(param_bool, enable_dp_mst); \ + func(param_bool, enable_dpcd_backlight); \ + func(param_bool, enable_gvt) #define MEMBER(T, member) T member struct i915_params { -- 2.11.0 ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/intel-gfx
[Intel-gfx] [PATCH 01/46] drm: Provide a driver hook for drm_dev_release()
Some state is coupled into the device lifetime outside of the load/unload timeframe and requires teardown during final unreference from drm_dev_release(). For example, dmabufs hold both a device and module reference and may live longer than expected (i.e. the current pattern of the driver tearing down its state and then releasing a reference to the drm device) and yet touch driver private state when destroyed. v2: Export drm_dev_fini() and move the responsibility for finalizing the drm_device and freeing it to the release callback. (If no callback is provided, the core will call drm_dev_fini() and kfree(dev) as before.) v3: Remember to add drm_dev_fini() to drm_drv.h v4: Tidy language for kerneldoc v5: Cross reference from drm_dev_init() to note that driver->release() allows for arbitrary embedding. Signed-off-by: Chris Wilson Cc: Laurent Pinchart Cc: Daniel Vetter --- drivers/gpu/drm/drm_drv.c | 65 --- include/drm/drm_drv.h | 13 ++ 2 files changed, 58 insertions(+), 20 deletions(-) diff --git a/drivers/gpu/drm/drm_drv.c b/drivers/gpu/drm/drm_drv.c index a8ce3179c07c..fe611d601916 100644 --- a/drivers/gpu/drm/drm_drv.c +++ b/drivers/gpu/drm/drm_drv.c @@ -465,7 +465,10 @@ static void drm_fs_inode_free(struct inode *inode) * that do embed &struct drm_device it must be placed first in the overall * structure, and the overall structure must be allocated using kmalloc(): The * drm core's release function unconditionally calls kfree() on the @dev pointer - * when the final reference is released. + * when the final reference is released. To override this behaviour, and so + * allow embedding of the drm_device inside the driver's device struct at an + * arbitrary offset, you must supply a driver->release() callback and control + * the finalization explicitly. * * RETURNS: * 0 on success, or error code on failure. @@ -553,6 +556,41 @@ int drm_dev_init(struct drm_device *dev, EXPORT_SYMBOL(drm_dev_init); /** + * drm_dev_fini - Finalize a dead DRM device + * @dev: DRM device + * + * Finalize a dead DRM device. This is the converse to drm_dev_init() and + * frees up all state allocated by it. All driver state should be finalized + * first. Note that this function does not free the @dev, that is left to the + * caller. + * + * The ref-count of @dev must be zero, and drm_dev_fini() should only be called + * from a drm_driver->release() callback. + */ +void drm_dev_fini(struct drm_device *dev) +{ + drm_vblank_cleanup(dev); + + if (drm_core_check_feature(dev, DRIVER_GEM)) + drm_gem_destroy(dev); + + drm_legacy_ctxbitmap_cleanup(dev); + drm_ht_remove(&dev->map_hash); + drm_fs_inode_free(dev->anon_inode); + + drm_minor_free(dev, DRM_MINOR_PRIMARY); + drm_minor_free(dev, DRM_MINOR_RENDER); + drm_minor_free(dev, DRM_MINOR_CONTROL); + + mutex_destroy(&dev->master_mutex); + mutex_destroy(&dev->ctxlist_mutex); + mutex_destroy(&dev->filelist_mutex); + mutex_destroy(&dev->struct_mutex); + kfree(dev->unique); +} +EXPORT_SYMBOL(drm_dev_fini); + +/** * drm_dev_alloc - Allocate new DRM device * @driver: DRM driver to allocate device for * @parent: Parent device object @@ -598,25 +636,12 @@ static void drm_dev_release(struct kref *ref) { struct drm_device *dev = container_of(ref, struct drm_device, ref); - drm_vblank_cleanup(dev); - - if (drm_core_check_feature(dev, DRIVER_GEM)) - drm_gem_destroy(dev); - - drm_legacy_ctxbitmap_cleanup(dev); - drm_ht_remove(&dev->map_hash); - drm_fs_inode_free(dev->anon_inode); - - drm_minor_free(dev, DRM_MINOR_PRIMARY); - drm_minor_free(dev, DRM_MINOR_RENDER); - drm_minor_free(dev, DRM_MINOR_CONTROL); - - mutex_destroy(&dev->master_mutex); - mutex_destroy(&dev->ctxlist_mutex); - mutex_destroy(&dev->filelist_mutex); - mutex_destroy(&dev->struct_mutex); - kfree(dev->unique); - kfree(dev); + if (dev->driver->release) { + dev->driver->release(dev); + } else { + drm_dev_fini(dev); + kfree(dev); + } } /** diff --git a/include/drm/drm_drv.h b/include/drm/drm_drv.h index 732e85652d1e..d0d2fa83d06c 100644 --- a/include/drm/drm_drv.h +++ b/include/drm/drm_drv.h @@ -102,6 +102,17 @@ struct drm_driver { * */ void (*unload) (struct drm_device *); + + /** +* @release: +* +* Optional callback for destroying device state after the final +* reference is released, i.e. the device is being destroyed. Drivers +* using this callback are responsible for calling drm_dev_fini() +* to finalize the device and then freeing the struct themselves. +*/ + void (*release) (struct drm_device *); + int (*set_busid)(struct drm_device *dev, struct drm_master *master); /** @@ -437,6
[Intel-gfx] [PATCH 04/46] drm/i915: Flush the freed object queue on device release
As dmabufs may live beyond the PCI device removal, we need to flush the freed object worker on device release, and include a warning in case there is a leak. Signed-off-by: Chris Wilson --- drivers/gpu/drm/i915/i915_gem.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 6c7a83bbd068..88065fd55147 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -4625,7 +4625,9 @@ i915_gem_load_init(struct drm_i915_private *dev_priv) void i915_gem_load_cleanup(struct drm_i915_private *dev_priv) { + i915_gem_drain_freed_objects(dev_priv); WARN_ON(!llist_empty(&dev_priv->mm.free_list)); + WARN_ON(dev_priv->mm.object_count); mutex_lock(&dev_priv->drm.struct_mutex); i915_gem_timeline_fini(&dev_priv->gt.global_timeline); -- 2.11.0 ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/intel-gfx
[Intel-gfx] [PATCH 09/46] drm/i915: Add unit tests for the breadcrumb rbtree, wakeups
Third retroactive test, make sure that the seqno waiters are woken. v2: Smattering of comments, rearrange code Signed-off-by: Chris Wilson --- drivers/gpu/drm/i915/selftests/intel_breadcrumbs.c | 201 + 1 file changed, 201 insertions(+) diff --git a/drivers/gpu/drm/i915/selftests/intel_breadcrumbs.c b/drivers/gpu/drm/i915/selftests/intel_breadcrumbs.c index 32a27e56c353..fb368eb37660 100644 --- a/drivers/gpu/drm/i915/selftests/intel_breadcrumbs.c +++ b/drivers/gpu/drm/i915/selftests/intel_breadcrumbs.c @@ -259,11 +259,212 @@ static int igt_insert_complete(void *arg) return err; } +struct igt_wakeup { + struct task_struct *tsk; + atomic_t *ready, *set, *done; + struct intel_engine_cs *engine; + unsigned long flags; +#define STOP 0 +#define IDLE 1 + wait_queue_head_t *wq; + u32 seqno; +}; + +static int wait_atomic(atomic_t *p) +{ + schedule(); + return 0; +} + +static int wait_atomic_timeout(atomic_t *p) +{ + return schedule_timeout(10 * HZ) ? 0 : -ETIMEDOUT; +} + +static bool wait_for_ready(struct igt_wakeup *w) +{ + DEFINE_WAIT(ready); + + if (atomic_dec_and_test(w->done)) + wake_up_atomic_t(w->done); + + if (test_bit(STOP, &w->flags)) + goto out; + + set_bit(IDLE, &w->flags); + for (;;) { + prepare_to_wait(w->wq, &ready, TASK_INTERRUPTIBLE); + if (atomic_read(w->ready) == 0) + break; + + schedule(); + } + finish_wait(w->wq, &ready); + clear_bit(IDLE, &w->flags); + +out: + if (atomic_dec_and_test(w->set)) + wake_up_atomic_t(w->set); + + return !test_bit(STOP, &w->flags); +} + +static int igt_wakeup_thread(void *arg) +{ + struct igt_wakeup *w = arg; + struct intel_wait wait; + + while (wait_for_ready(w)) { + GEM_BUG_ON(kthread_should_stop()); + + intel_wait_init(&wait, w->seqno); + intel_engine_add_wait(w->engine, &wait); + for (;;) { + set_current_state(TASK_UNINTERRUPTIBLE); + if (i915_seqno_passed(intel_engine_get_seqno(w->engine), + w->seqno)) + break; + + if (test_bit(STOP, &w->flags)) /* emergency escape */ + break; + + schedule(); + } + intel_engine_remove_wait(w->engine, &wait); + __set_current_state(TASK_RUNNING); + } + + return 0; +} + +static void igt_wake_all_sync(atomic_t *ready, + atomic_t *set, + atomic_t *done, + wait_queue_head_t *wq, + int count) +{ + atomic_set(set, count); + atomic_set(ready, 0); + wake_up_all(wq); + + wait_on_atomic_t(set, wait_atomic, TASK_UNINTERRUPTIBLE); + atomic_set(ready, count); + atomic_set(done, count); +} + +static int igt_wakeup(void *arg) +{ + I915_RND_STATE(prng); + const int state = TASK_UNINTERRUPTIBLE; + struct intel_engine_cs *engine = arg; + struct igt_wakeup *waiters; + DECLARE_WAIT_QUEUE_HEAD_ONSTACK(wq); + const int count = 4096; + const u32 max_seqno = count / 4; + atomic_t ready, set, done; + int err = -ENOMEM; + int n, step; + + mock_engine_reset(engine); + + waiters = drm_malloc_gfp(count, sizeof(*waiters), GFP_TEMPORARY); + if (!waiters) + goto out_engines; + + /* Create a large number of threads, each waiting on a random seqno. +* Multiple waiters will be waiting for the same seqno. +*/ + atomic_set(&ready, count); + for (n = 0; n < count; n++) { + waiters[n].wq = &wq; + waiters[n].ready = &ready; + waiters[n].set = &set; + waiters[n].done = &done; + waiters[n].engine = engine; + waiters[n].flags = BIT(IDLE); + + waiters[n].tsk = kthread_run(igt_wakeup_thread, &waiters[n], +"i915/igt:%d", n); + if (IS_ERR(waiters[n].tsk)) + goto out_waiters; + + get_task_struct(waiters[n].tsk); + } + + for (step = 1; step <= max_seqno; step <<= 1) { + u32 seqno; + + /* The waiter threads start paused as we assign them a random +* seqno and reset the engine. Once the engine is reset, +* we signal that the threads may begin their wait upon their +* seqno. +*/ + for (n = 0; n < count; n++) { + GEM_BUG_ON(!test_bit(IDLE, &waiters[n].flags)); + waiters[n].seqno = +
[Intel-gfx] [PATCH 06/46] drm/i915: Add some selftests for sg_table manipulation
Start exercising the scattergather lists, especially looking at iteration after coalescing. v2: Comment on the peculiarity of table construction (i.e. why this sg_table might be interesting). v3: Added one __func__ to identify expect_pfn_sg() Signed-off-by: Chris Wilson Cc: Tvrtko Ursulin --- drivers/gpu/drm/i915/i915_gem.c| 11 +- .../gpu/drm/i915/selftests/i915_mock_selftests.h | 1 + drivers/gpu/drm/i915/selftests/scatterlist.c | 331 + 3 files changed, 340 insertions(+), 3 deletions(-) create mode 100644 drivers/gpu/drm/i915/selftests/scatterlist.c diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 88065fd55147..fc54a8eb3fe5 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -2216,17 +2216,17 @@ void __i915_gem_object_put_pages(struct drm_i915_gem_object *obj, mutex_unlock(&obj->mm.lock); } -static void i915_sg_trim(struct sg_table *orig_st) +static bool i915_sg_trim(struct sg_table *orig_st) { struct sg_table new_st; struct scatterlist *sg, *new_sg; unsigned int i; if (orig_st->nents == orig_st->orig_nents) - return; + return false; if (sg_alloc_table(&new_st, orig_st->nents, GFP_KERNEL | __GFP_NOWARN)) - return; + return false; new_sg = new_st.sgl; for_each_sg(orig_st->sgl, sg, orig_st->nents, i) { @@ -2239,6 +2239,7 @@ static void i915_sg_trim(struct sg_table *orig_st) sg_free_table(orig_st); *orig_st = new_st; + return true; } static struct sg_table * @@ -4967,3 +4968,7 @@ i915_gem_object_get_dma_address(struct drm_i915_gem_object *obj, sg = i915_gem_object_get_sg(obj, n, &offset); return sg_dma_address(sg) + (offset << PAGE_SHIFT); } + +#if IS_ENABLED(CONFIG_DRM_I915_SELFTEST) +#include "selftests/scatterlist.c" +#endif diff --git a/drivers/gpu/drm/i915/selftests/i915_mock_selftests.h b/drivers/gpu/drm/i915/selftests/i915_mock_selftests.h index 69e97a2ba4a6..5f0bdda42ed8 100644 --- a/drivers/gpu/drm/i915/selftests/i915_mock_selftests.h +++ b/drivers/gpu/drm/i915/selftests/i915_mock_selftests.h @@ -9,3 +9,4 @@ * Tests are executed in order by igt/drv_selftest */ selftest(sanitycheck, i915_mock_sanitycheck) /* keep first (igt selfcheck) */ +selftest(scatterlist, scatterlist_mock_selftests) diff --git a/drivers/gpu/drm/i915/selftests/scatterlist.c b/drivers/gpu/drm/i915/selftests/scatterlist.c new file mode 100644 index ..fa5bd09c863f --- /dev/null +++ b/drivers/gpu/drm/i915/selftests/scatterlist.c @@ -0,0 +1,331 @@ +/* + * Copyright © 2016 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +#include +#include + +#include "../i915_selftest.h" + +#define PFN_BIAS (1 << 10) + +struct pfn_table { + struct sg_table st; + unsigned long start, end; +}; + +typedef unsigned int (*npages_fn_t)(unsigned long n, + unsigned long count, + struct rnd_state *rnd); + +static noinline int expect_pfn_sg(struct pfn_table *pt, + npages_fn_t npages_fn, + struct rnd_state *rnd, + const char *who, + unsigned long timeout) +{ + struct scatterlist *sg; + unsigned long pfn, n; + + pfn = pt->start; + for_each_sg(pt->st.sgl, sg, pt->st.nents, n) { + struct page *page = sg_page(sg); + unsigned int npages = npages_fn(n, pt->st.nents, rnd); + + if (page_to_pfn(page) != pfn) { + pr_err("%s: %s left pages out of order, expected pfn %lu, found pfn %lu (using for_each_sg)\n", + __func__, who, pfn, page_to_pfn(page)
[Intel-gfx] [PATCH 10/46] drm/i915: Mock the GEM device for self-testing
A simulacrum of drm_i915_private to let us pretend interactions with the device. v2: Tidy init error paths Signed-off-by: Chris Wilson Reviewed-by: Matthew Auld --- drivers/gpu/drm/i915/i915_drv.c | 4 + drivers/gpu/drm/i915/i915_gem.c | 1 + drivers/gpu/drm/i915/selftests/mock_drm.c| 54 drivers/gpu/drm/i915/selftests/mock_drm.h| 31 +++ drivers/gpu/drm/i915/selftests/mock_gem_device.c | 104 +++ drivers/gpu/drm/i915/selftests/mock_gem_device.h | 8 ++ drivers/gpu/drm/i915/selftests/mock_gem_object.h | 8 ++ 7 files changed, 210 insertions(+) create mode 100644 drivers/gpu/drm/i915/selftests/mock_drm.c create mode 100644 drivers/gpu/drm/i915/selftests/mock_drm.h create mode 100644 drivers/gpu/drm/i915/selftests/mock_gem_device.c create mode 100644 drivers/gpu/drm/i915/selftests/mock_gem_device.h create mode 100644 drivers/gpu/drm/i915/selftests/mock_gem_object.h diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index 8bba6c4eb4ed..13307f641e5a 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -2639,3 +2639,7 @@ static struct drm_driver driver = { .minor = DRIVER_MINOR, .patchlevel = DRIVER_PATCHLEVEL, }; + +#if IS_ENABLED(CONFIG_DRM_I915_SELFTEST) +#include "selftests/mock_drm.c" +#endif diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index fc54a8eb3fe5..778a659a7836 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -4971,4 +4971,5 @@ i915_gem_object_get_dma_address(struct drm_i915_gem_object *obj, #if IS_ENABLED(CONFIG_DRM_I915_SELFTEST) #include "selftests/scatterlist.c" +#include "selftests/mock_gem_device.c" #endif diff --git a/drivers/gpu/drm/i915/selftests/mock_drm.c b/drivers/gpu/drm/i915/selftests/mock_drm.c new file mode 100644 index ..113dec05c7dc --- /dev/null +++ b/drivers/gpu/drm/i915/selftests/mock_drm.c @@ -0,0 +1,54 @@ +/* + * Copyright © 2017 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + * + */ + +#include "mock_drm.h" + +static inline struct inode fake_inode(struct drm_i915_private *i915) +{ + return (struct inode){ .i_rdev = i915->drm.primary->index }; +} + +struct drm_file *mock_file(struct drm_i915_private *i915) +{ + struct inode inode = fake_inode(i915); + struct file filp = {}; + struct drm_file *file; + int err; + + err = drm_open(&inode, &filp); + if (unlikely(err)) + return ERR_PTR(err); + + file = filp.private_data; + file->authenticated = true; + return file; +} + +void mock_file_free(struct drm_i915_private *i915, struct drm_file *file) +{ + struct inode inode = fake_inode(i915); + struct file filp = { .private_data = file }; + + drm_release(&inode, &filp); +} diff --git a/drivers/gpu/drm/i915/selftests/mock_drm.h b/drivers/gpu/drm/i915/selftests/mock_drm.h new file mode 100644 index ..b39beee9f8f6 --- /dev/null +++ b/drivers/gpu/drm/i915/selftests/mock_drm.h @@ -0,0 +1,31 @@ +/* + * Copyright © 2017 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS O
[Intel-gfx] [PATCH 08/46] drm/i915: Add unit tests for the breadcrumb rbtree, completion
Second retroactive test, make sure that the waiters are removed from the global wait-tree when their seqno completes. Signed-off-by: Chris Wilson Reviewed-by: Tvrtko Ursulin --- drivers/gpu/drm/i915/selftests/intel_breadcrumbs.c | 107 + drivers/gpu/drm/i915/selftests/mock_engine.h | 6 ++ 2 files changed, 113 insertions(+) diff --git a/drivers/gpu/drm/i915/selftests/intel_breadcrumbs.c b/drivers/gpu/drm/i915/selftests/intel_breadcrumbs.c index 6b5acf9de65b..32a27e56c353 100644 --- a/drivers/gpu/drm/i915/selftests/intel_breadcrumbs.c +++ b/drivers/gpu/drm/i915/selftests/intel_breadcrumbs.c @@ -64,6 +64,27 @@ static int check_rbtree(struct intel_engine_cs *engine, return 0; } +static int check_completion(struct intel_engine_cs *engine, + const unsigned long *bitmap, + const struct intel_wait *waiters, + const int count) +{ + int n; + + for (n = 0; n < count; n++) { + if (intel_wait_complete(&waiters[n]) != !!test_bit(n, bitmap)) + continue; + + pr_err("waiter[%d, seqno=%d] is %s, but expected %s\n", + n, waiters[n].seqno, + intel_wait_complete(&waiters[n]) ? "complete" : "active", + test_bit(n, bitmap) ? "active" : "complete"); + return -EINVAL; + } + + return 0; +} + static int check_rbtree_empty(struct intel_engine_cs *engine) { struct intel_breadcrumbs *b = &engine->breadcrumbs; @@ -153,10 +174,96 @@ static int igt_random_insert_remove(void *arg) return err; } +static int igt_insert_complete(void *arg) +{ + const u32 seqno_bias = 0x1000; + struct intel_engine_cs *engine = arg; + struct intel_wait *waiters; + const int count = 4096; + unsigned long *bitmap; + int err = -ENOMEM; + int n, m; + + mock_engine_reset(engine); + + waiters = drm_malloc_gfp(count, sizeof(*waiters), GFP_TEMPORARY); + if (!waiters) + goto out_engines; + + bitmap = kcalloc(DIV_ROUND_UP(count, BITS_PER_LONG), sizeof(*bitmap), +GFP_TEMPORARY); + if (!bitmap) + goto out_waiters; + + for (n = 0; n < count; n++) { + intel_wait_init(&waiters[n], n + seqno_bias); + intel_engine_add_wait(engine, &waiters[n]); + __set_bit(n, bitmap); + } + err = check_rbtree(engine, bitmap, waiters, count); + if (err) + goto out_bitmap; + + /* On each step, we advance the seqno so that several waiters are then +* complete (we increase the seqno by increasingly larger values to +* retire more and more waiters at once). All retired waiters should +* be woken and removed from the rbtree, and so that we check. +*/ + for (n = 0; n < count; n = m) { + int seqno = 2 * n; + + GEM_BUG_ON(find_first_bit(bitmap, count) != n); + + if (intel_wait_complete(&waiters[n])) { + pr_err("waiter[%d, seqno=%d] completed too early\n", + n, waiters[n].seqno); + err = -EINVAL; + goto out_bitmap; + } + + /* complete the following waiters */ + mock_seqno_advance(engine, seqno + seqno_bias); + for (m = n; m <= seqno; m++) { + if (m == count) + break; + + GEM_BUG_ON(!test_bit(m, bitmap)); + __clear_bit(m, bitmap); + } + + intel_engine_remove_wait(engine, &waiters[n]); + RB_CLEAR_NODE(&waiters[n].node); + + err = check_rbtree(engine, bitmap, waiters, count); + if (err) { + pr_err("rbtree corrupt after seqno advance to %d\n", + seqno + seqno_bias); + goto out_bitmap; + } + + err = check_completion(engine, bitmap, waiters, count); + if (err) { + pr_err("completions after seqno advance to %d failed\n", + seqno + seqno_bias); + goto out_bitmap; + } + } + + err = check_rbtree_empty(engine); +out_bitmap: + kfree(bitmap); +out_waiters: + drm_free_large(waiters); +out_engines: + mock_engine_flush(engine); + return err; +} + int intel_breadcrumbs_mock_selftests(void) { static const struct i915_subtest tests[] = { SUBTEST(igt_random_insert_remove), + SUBTEST(igt_insert_complete), }; struct intel_engine_cs *engine; int err; diff --git a/drivers/gpu/drm/i915/selftests/mock_engine.h b/drivers/gpu/drm/i915/selftests/mock
[Intel-gfx] [PATCH 03/46] drm/i915: Unbind any residual objects/vma from the Global GTT on shutdown
We may unload the PCI device before all users (such as dma-buf) are completely shutdown. This may leave VMA in the global GTT which we want to revoke, whilst keeping the objects themselves around to service the dma-buf. Signed-off-by: Chris Wilson --- drivers/gpu/drm/i915/i915_gem_gtt.c | 9 + 1 file changed, 9 insertions(+) diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c index b7bcb1e62ce4..65425e71f3a5 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.c +++ b/drivers/gpu/drm/i915/i915_gem_gtt.c @@ -2812,6 +2812,15 @@ int i915_gem_init_ggtt(struct drm_i915_private *dev_priv) void i915_ggtt_cleanup_hw(struct drm_i915_private *dev_priv) { struct i915_ggtt *ggtt = &dev_priv->ggtt; + struct i915_vma *vma, *vn; + + ggtt->base.closed = true; + + mutex_lock(&dev_priv->drm.struct_mutex); + WARN_ON(!list_empty(&ggtt->base.active_list)); + list_for_each_entry_safe(vma, vn, &ggtt->base.inactive_list, vm_link) + WARN_ON(i915_vma_unbind(vma)); + mutex_unlock(&dev_priv->drm.struct_mutex); if (dev_priv->mm.aliasing_ppgtt) { struct i915_hw_ppgtt *ppgtt = dev_priv->mm.aliasing_ppgtt; -- 2.11.0 ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/intel-gfx
[Intel-gfx] [PATCH 02/46] drm/i915: Split device release from unload
We may need to keep our memory management alive after we have unloaded the physical pci device. For example, if we have exported an object via dmabuf, that will keep the device around but the pci device may be removed before the dmabuf itself is released, use of the pci hardware will be revoked, but the memory and object management needs to persist for the dmabuf. Signed-off-by: Chris Wilson --- drivers/gpu/drm/i915/i915_drv.c | 12 +++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index 267d5f8c49e1..8bba6c4eb4ed 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -1299,7 +1299,8 @@ int i915_driver_load(struct pci_dev *pdev, const struct pci_device_id *ent) pci_disable_device(pdev); out_free_priv: i915_load_error(dev_priv, "Device initialization failed (%d)\n", ret); - drm_dev_unref(&dev_priv->drm); + drm_dev_fini(&dev_priv->drm); + kfree(dev_priv); return ret; } @@ -1358,8 +1359,16 @@ void i915_driver_unload(struct drm_device *dev) i915_driver_cleanup_mmio(dev_priv); intel_display_power_put(dev_priv, POWER_DOMAIN_INIT); +} + +static void i915_driver_release(struct drm_device *dev) +{ + struct drm_i915_private *dev_priv = to_i915(dev); i915_driver_cleanup_early(dev_priv); + drm_dev_fini(&dev_priv->drm); + + kfree(dev_priv); } static int i915_driver_open(struct drm_device *dev, struct drm_file *file) @@ -2601,6 +2610,7 @@ static struct drm_driver driver = { .driver_features = DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED | DRIVER_GEM | DRIVER_PRIME | DRIVER_RENDER | DRIVER_MODESET, + .release = i915_driver_release, .open = i915_driver_open, .lastclose = i915_driver_lastclose, .preclose = i915_driver_preclose, -- 2.11.0 ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/intel-gfx
[Intel-gfx] [PATCH 05/46] drm/i915: Provide a hook for selftests
Some pieces of code are independent of hardware but are very tricky to exercise through the normal userspace ABI or via debugfs hooks. Being able to create mock unit tests and execute them through CI is vital. Start by adding a central point where we can execute unit tests and a parameter to enable them. This is disabled by default as the expectation is that these tests will occasionally explode. To facilitate integration with igt, any parameter beginning with i915.igt__ is interpreted as a subtest executable independently via igt/drv_selftest. Two classes of selftests are recognised: mock unit tests and integration tests. Mock unit tests are run as soon as the module is loaded, before the device is probed. At that point there is no driver instantiated and all hw interactions must be "mocked". This is very useful for writing universal tests to exercise code not typically run on a broad range of architectures. Alternatively, you can hook into the live selftests and run when the device has been instantiated - hw interactions are real. v2: Add a macro for compiling conditional code for mock objects inside real objects. v3: Differentiate between mock unit tests and late integration test. v4: List the tests in natural order, use igt to sort after modparam. v5: s/late/live/ v6: s/unsigned long/unsigned int/ v7: Use igt_ prefixes for long helpers. Signed-off-by: Chris Wilson Reviewed-by: Tvrtko Ursulin #v1 --- drivers/gpu/drm/i915/Kconfig.debug | 16 ++ drivers/gpu/drm/i915/Makefile | 3 + drivers/gpu/drm/i915/i915_pci.c| 31 ++- drivers/gpu/drm/i915/i915_selftest.h | 102 + .../gpu/drm/i915/selftests/i915_live_selftests.h | 11 + .../gpu/drm/i915/selftests/i915_mock_selftests.h | 11 + drivers/gpu/drm/i915/selftests/i915_random.c | 63 ++ drivers/gpu/drm/i915/selftests/i915_random.h | 50 + drivers/gpu/drm/i915/selftests/i915_selftest.c | 250 + tools/testing/selftests/drivers/gpu/i915.sh| 1 + 10 files changed, 531 insertions(+), 7 deletions(-) create mode 100644 drivers/gpu/drm/i915/i915_selftest.h create mode 100644 drivers/gpu/drm/i915/selftests/i915_live_selftests.h create mode 100644 drivers/gpu/drm/i915/selftests/i915_mock_selftests.h create mode 100644 drivers/gpu/drm/i915/selftests/i915_random.c create mode 100644 drivers/gpu/drm/i915/selftests/i915_random.h create mode 100644 drivers/gpu/drm/i915/selftests/i915_selftest.c diff --git a/drivers/gpu/drm/i915/Kconfig.debug b/drivers/gpu/drm/i915/Kconfig.debug index 598551dbf62c..a4d8cfd77c3c 100644 --- a/drivers/gpu/drm/i915/Kconfig.debug +++ b/drivers/gpu/drm/i915/Kconfig.debug @@ -26,6 +26,7 @@ config DRM_I915_DEBUG select DRM_DEBUG_MM if DRM=y select DRM_DEBUG_MM_SELFTEST select DRM_I915_SW_FENCE_DEBUG_OBJECTS + select DRM_I915_SELFTEST default n help Choose this option to turn on extra driver debugging that may affect @@ -59,3 +60,18 @@ config DRM_I915_SW_FENCE_DEBUG_OBJECTS Recommended for driver developers only. If in doubt, say "N". + +config DRM_I915_SELFTEST + bool "Enable selftests upon driver load" + depends on DRM_I915 + default n + select PRIME_NUMBERS + help + Choose this option to allow the driver to perform selftests upon + loading; also requires the i915.selftest=1 module parameter. To + exit the module after running the selftests (i.e. to prevent normal + module initialisation afterwards) use i915.selftest=-1. + + Recommended for driver developers only. + + If in doubt, say "N". diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile index c62ab45683c0..bac62fd5b438 100644 --- a/drivers/gpu/drm/i915/Makefile +++ b/drivers/gpu/drm/i915/Makefile @@ -116,6 +116,9 @@ i915-y += dvo_ch7017.o \ # Post-mortem debug and GPU hang state capture i915-$(CONFIG_DRM_I915_CAPTURE_ERROR) += i915_gpu_error.o +i915-$(CONFIG_DRM_I915_SELFTEST) += \ + selftests/i915_random.o \ + selftests/i915_selftest.o # virtual gpu code i915-y += i915_vgpu.o diff --git a/drivers/gpu/drm/i915/i915_pci.c b/drivers/gpu/drm/i915/i915_pci.c index df2051b41fa1..732101ed57fb 100644 --- a/drivers/gpu/drm/i915/i915_pci.c +++ b/drivers/gpu/drm/i915/i915_pci.c @@ -27,6 +27,7 @@ #include #include "i915_drv.h" +#include "i915_selftest.h" #define GEN_DEFAULT_PIPEOFFSETS \ .pipe_offsets = { PIPE_A_OFFSET, PIPE_B_OFFSET, \ @@ -473,10 +474,19 @@ static const struct pci_device_id pciidlist[] = { }; MODULE_DEVICE_TABLE(pci, pciidlist); +static void i915_pci_remove(struct pci_dev *pdev) +{ + struct drm_device *dev = pci_get_drvdata(pdev); + + i915_driver_unload(dev); + drm_dev_unref(dev); +} + static int i915_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) { struct intel_de
[Intel-gfx] [PATCH 12/46] drm/i915: Mock infrastructure for request emission
Create a fake engine that runs requests using a timer to simulate hw. v2: Prevent leaks of ctx->name along error paths Signed-off-by: Chris Wilson Reviewed-by: Tvrtko Ursulin --- drivers/gpu/drm/i915/i915_gem_context.c| 4 + drivers/gpu/drm/i915/selftests/intel_breadcrumbs.c | 11 +- drivers/gpu/drm/i915/selftests/mock_context.c | 78 ++ drivers/gpu/drm/i915/selftests/mock_context.h | 34 drivers/gpu/drm/i915/selftests/mock_engine.c | 172 +++-- drivers/gpu/drm/i915/selftests/mock_engine.h | 18 ++- drivers/gpu/drm/i915/selftests/mock_gem_device.c | 95 +++- drivers/gpu/drm/i915/selftests/mock_gem_device.h | 1 + drivers/gpu/drm/i915/selftests/mock_request.c | 44 ++ drivers/gpu/drm/i915/selftests/mock_request.h | 44 ++ 10 files changed, 483 insertions(+), 18 deletions(-) create mode 100644 drivers/gpu/drm/i915/selftests/mock_context.c create mode 100644 drivers/gpu/drm/i915/selftests/mock_context.h create mode 100644 drivers/gpu/drm/i915/selftests/mock_request.c create mode 100644 drivers/gpu/drm/i915/selftests/mock_request.h diff --git a/drivers/gpu/drm/i915/i915_gem_context.c b/drivers/gpu/drm/i915/i915_gem_context.c index 680105421bb9..e6208e361356 100644 --- a/drivers/gpu/drm/i915/i915_gem_context.c +++ b/drivers/gpu/drm/i915/i915_gem_context.c @@ -1188,3 +1188,7 @@ int i915_gem_context_reset_stats_ioctl(struct drm_device *dev, return 0; } + +#if IS_ENABLED(CONFIG_DRM_I915_SELFTEST) +#include "selftests/mock_context.c" +#endif diff --git a/drivers/gpu/drm/i915/selftests/intel_breadcrumbs.c b/drivers/gpu/drm/i915/selftests/intel_breadcrumbs.c index fb368eb37660..55795cab483c 100644 --- a/drivers/gpu/drm/i915/selftests/intel_breadcrumbs.c +++ b/drivers/gpu/drm/i915/selftests/intel_breadcrumbs.c @@ -25,6 +25,7 @@ #include "../i915_selftest.h" #include "i915_random.h" +#include "mock_gem_device.h" #include "mock_engine.h" static int check_rbtree(struct intel_engine_cs *engine, @@ -466,15 +467,15 @@ int intel_breadcrumbs_mock_selftests(void) SUBTEST(igt_insert_complete), SUBTEST(igt_wakeup), }; - struct intel_engine_cs *engine; + struct drm_i915_private *i915; int err; - engine = mock_engine("mock"); - if (!engine) + i915 = mock_gem_device(); + if (!i915) return -ENOMEM; - err = i915_subtests(tests, engine); - kfree(engine); + err = i915_subtests(tests, i915->engine[RCS]); + drm_dev_unref(&i915->drm); return err; } diff --git a/drivers/gpu/drm/i915/selftests/mock_context.c b/drivers/gpu/drm/i915/selftests/mock_context.c new file mode 100644 index ..8d3a90c3f8ac --- /dev/null +++ b/drivers/gpu/drm/i915/selftests/mock_context.c @@ -0,0 +1,78 @@ +/* + * Copyright © 2016 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + * + */ + +#include "mock_context.h" +#include "mock_gtt.h" + +struct i915_gem_context * +mock_context(struct drm_i915_private *i915, +const char *name) +{ + struct i915_gem_context *ctx; + int ret; + + ctx = kzalloc(sizeof(*ctx), GFP_KERNEL); + if (!ctx) + return NULL; + + kref_init(&ctx->ref); + INIT_LIST_HEAD(&ctx->link); + ctx->i915 = i915; + + ret = ida_simple_get(&i915->context_hw_ida, +0, MAX_CONTEXT_HW_ID, GFP_KERNEL); + if (ret < 0) + goto err_free; + ctx->hw_id = ret; + + if (name) { + ctx->name = kstrdup(name, GFP_KERNEL); + if (!ctx->name) + goto err_put; + + ctx->ppgtt = mock_ppgtt(i915, name); + if (!ctx->ppgtt) + goto err_put; + } + + return ctx; + +err_free: + kfree(ctx);
[Intel-gfx] [PATCH 07/46] drm/i915: Add unit tests for the breadcrumb rbtree, insert/remove
First retroactive test, make sure that the waiters are in global seqno order after random inserts and removals. Signed-off-by: Chris Wilson Reviewed-by: Tvrtko Ursulin --- drivers/gpu/drm/i915/intel_breadcrumbs.c | 21 +++ drivers/gpu/drm/i915/intel_engine_cs.c | 4 + drivers/gpu/drm/i915/intel_ringbuffer.h| 2 + .../gpu/drm/i915/selftests/i915_mock_selftests.h | 1 + drivers/gpu/drm/i915/selftests/intel_breadcrumbs.c | 172 + drivers/gpu/drm/i915/selftests/mock_engine.c | 55 +++ drivers/gpu/drm/i915/selftests/mock_engine.h | 32 7 files changed, 287 insertions(+) create mode 100644 drivers/gpu/drm/i915/selftests/intel_breadcrumbs.c create mode 100644 drivers/gpu/drm/i915/selftests/mock_engine.c create mode 100644 drivers/gpu/drm/i915/selftests/mock_engine.h diff --git a/drivers/gpu/drm/i915/intel_breadcrumbs.c b/drivers/gpu/drm/i915/intel_breadcrumbs.c index 9fd002bcebb6..1f36756f8759 100644 --- a/drivers/gpu/drm/i915/intel_breadcrumbs.c +++ b/drivers/gpu/drm/i915/intel_breadcrumbs.c @@ -107,6 +107,18 @@ static void __intel_breadcrumbs_enable_irq(struct intel_breadcrumbs *b) if (b->rpm_wakelock) return; + if (I915_SELFTEST_ONLY(b->mock)) { + /* For our mock objects we want to avoid interaction +* with the real hardware (which is not set up). So +* we simply pretend we have enabled the powerwell +* and the irq, and leave it up to the mock +* implementation to call intel_engine_wakeup() +* itself when it wants to simulate a user interrupt, +*/ + b->rpm_wakelock = true; + return; + } + /* Since we are waiting on a request, the GPU should be busy * and should have its own rpm reference. For completeness, * record an rpm reference for ourselves to cover the @@ -142,6 +154,11 @@ static void __intel_breadcrumbs_disable_irq(struct intel_breadcrumbs *b) if (!b->rpm_wakelock) return; + if (I915_SELFTEST_ONLY(b->mock)) { + b->rpm_wakelock = false; + return; + } + if (b->irq_enabled) { irq_disable(engine); b->irq_enabled = false; @@ -661,3 +678,7 @@ unsigned int intel_breadcrumbs_busy(struct drm_i915_private *i915) return mask; } + +#if IS_ENABLED(CONFIG_DRM_I915_SELFTEST) +#include "selftests/intel_breadcrumbs.c" +#endif diff --git a/drivers/gpu/drm/i915/intel_engine_cs.c b/drivers/gpu/drm/i915/intel_engine_cs.c index 69a6416d1223..538d845d7251 100644 --- a/drivers/gpu/drm/i915/intel_engine_cs.c +++ b/drivers/gpu/drm/i915/intel_engine_cs.c @@ -524,3 +524,7 @@ void intel_engine_get_instdone(struct intel_engine_cs *engine, break; } } + +#if IS_ENABLED(CONFIG_DRM_I915_SELFTEST) +#include "selftests/mock_engine.c" +#endif diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.h b/drivers/gpu/drm/i915/intel_ringbuffer.h index b9c15cd40fbf..c2f0ecf612b9 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.h +++ b/drivers/gpu/drm/i915/intel_ringbuffer.h @@ -5,6 +5,7 @@ #include "i915_gem_batch_pool.h" #include "i915_gem_request.h" #include "i915_gem_timeline.h" +#include "i915_selftest.h" #define I915_CMD_HASH_ORDER 9 @@ -247,6 +248,7 @@ struct intel_engine_cs { bool irq_enabled : 1; bool rpm_wakelock : 1; + I915_SELFTEST_DECLARE(bool mock : 1); } breadcrumbs; /* diff --git a/drivers/gpu/drm/i915/selftests/i915_mock_selftests.h b/drivers/gpu/drm/i915/selftests/i915_mock_selftests.h index 5f0bdda42ed8..80458e2a2b04 100644 --- a/drivers/gpu/drm/i915/selftests/i915_mock_selftests.h +++ b/drivers/gpu/drm/i915/selftests/i915_mock_selftests.h @@ -10,3 +10,4 @@ */ selftest(sanitycheck, i915_mock_sanitycheck) /* keep first (igt selfcheck) */ selftest(scatterlist, scatterlist_mock_selftests) +selftest(breadcrumbs, intel_breadcrumbs_mock_selftests) diff --git a/drivers/gpu/drm/i915/selftests/intel_breadcrumbs.c b/drivers/gpu/drm/i915/selftests/intel_breadcrumbs.c new file mode 100644 index ..6b5acf9de65b --- /dev/null +++ b/drivers/gpu/drm/i915/selftests/intel_breadcrumbs.c @@ -0,0 +1,172 @@ +/* + * Copyright © 2016 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copie
[Intel-gfx] Moah selftests
Fewer wide ranging review comments, lots more r-b, we seem to be settling on a compromise... -Chris ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/intel-gfx
[Intel-gfx] [PATCH 20/46] drm/i915: Live testing of empty requests
Primarily to emphasize the difference between just advancing the breadcrumb using a bare request and the overhead of dispatching an execbuffer. Signed-off-by: Chris Wilson --- drivers/gpu/drm/i915/selftests/i915_gem_request.c | 155 ++ 1 file changed, 155 insertions(+) diff --git a/drivers/gpu/drm/i915/selftests/i915_gem_request.c b/drivers/gpu/drm/i915/selftests/i915_gem_request.c index f9c171d1a05b..92fa55bd68c8 100644 --- a/drivers/gpu/drm/i915/selftests/i915_gem_request.c +++ b/drivers/gpu/drm/i915/selftests/i915_gem_request.c @@ -301,6 +301,160 @@ static int live_nop_request(void *arg) return err; } +static struct i915_vma *empty_batch(struct drm_i915_private *i915) +{ + struct drm_i915_gem_object *obj; + struct i915_vma *vma; + u32 *cmd; + int err; + + obj = i915_gem_object_create_internal(i915, PAGE_SIZE); + if (IS_ERR(obj)) + return ERR_CAST(obj); + + cmd = i915_gem_object_pin_map(obj, I915_MAP_WB); + if (IS_ERR(cmd)) { + err = PTR_ERR(cmd); + goto err; + } + *cmd = MI_BATCH_BUFFER_END; + i915_gem_object_unpin_map(obj); + + err = i915_gem_object_set_to_gtt_domain(obj, false); + if (err) + goto err; + + vma = i915_vma_instance(obj, &i915->ggtt.base, NULL); + if (IS_ERR(vma)) { + err = PTR_ERR(vma); + goto err; + } + + err = i915_vma_pin(vma, 0, 0, PIN_USER | PIN_GLOBAL); + if (err) + goto err; + + return vma; + +err: + i915_gem_object_put(obj); + return ERR_PTR(err); +} + +static struct drm_i915_gem_request * +empty_request(struct intel_engine_cs *engine, + struct i915_vma *batch) +{ + struct drm_i915_gem_request *request; + int err; + + request = i915_gem_request_alloc(engine, +engine->i915->kernel_context); + if (IS_ERR(request)) + return request; + + err = engine->emit_flush(request, EMIT_INVALIDATE); + if (err) + goto out_request; + + err = i915_switch_context(request); + if (err) + goto out_request; + + err = engine->emit_bb_start(request, + batch->node.start, + batch->node.size, + I915_DISPATCH_SECURE); + if (err) + goto out_request; + +out_request: + __i915_add_request(request, err == 0); + return err ? ERR_PTR(err) : request; +} + +static int live_empty_request(void *arg) +{ + struct drm_i915_private *i915 = arg; + struct intel_engine_cs *engine; + struct live_test t; + struct i915_vma *batch; + unsigned int id; + int err = 0; + + /* Submit various sized batches of empty requests, to each engine +* (individually), and wait for the batch to complete. We can check +* the overhead of submitting requests to the hardware. +*/ + + mutex_lock(&i915->drm.struct_mutex); + + batch = empty_batch(i915); + if (IS_ERR(batch)) { + err = PTR_ERR(batch); + goto out_unlock; + } + + for_each_engine(engine, i915, id) { + IGT_TIMEOUT(end_time); + struct drm_i915_gem_request *request; + unsigned long n, prime; + ktime_t times[2] = {}; + + err = begin_live_test(&t, i915, __func__, engine->name); + if (err) + goto out_batch; + + /* Warmup / preload */ + request = empty_request(engine, batch); + if (IS_ERR(request)) { + err = PTR_ERR(request); + goto out_batch; + } + i915_wait_request(request, + I915_WAIT_LOCKED, + MAX_SCHEDULE_TIMEOUT); + + for_each_prime_number_from(prime, 1, 8192) { + times[1] = ktime_get_raw(); + + for (n = 0; n < prime; n++) { + request = empty_request(engine, batch); + if (IS_ERR(request)) { + err = PTR_ERR(request); + goto out_batch; + } + } + i915_wait_request(request, + I915_WAIT_LOCKED, + MAX_SCHEDULE_TIMEOUT); + + times[1] = ktime_sub(ktime_get_raw(), times[1]); + if (prime == 1) + times[0] = times[1]; + + if (__igt_timeout(end_time, NULL)) + break; + } + + err = e
[Intel-gfx] [PATCH 16/46] drm/i915: Add a simple fence selftest to i915_gem_request
Do a quick selftest on in the interoperability of dma_fence_wait on a i915_gem_request. Signed-off-by: Chris Wilson Reviewed-by: Tvrtko Ursulin --- drivers/gpu/drm/i915/selftests/i915_gem_request.c | 49 +++ 1 file changed, 49 insertions(+) diff --git a/drivers/gpu/drm/i915/selftests/i915_gem_request.c b/drivers/gpu/drm/i915/selftests/i915_gem_request.c index 14584b67c4a0..bc6f5618f22b 100644 --- a/drivers/gpu/drm/i915/selftests/i915_gem_request.c +++ b/drivers/gpu/drm/i915/selftests/i915_gem_request.c @@ -94,11 +94,60 @@ static int igt_wait_request(void *arg) return err; } +static int igt_fence_wait(void *arg) +{ + const long T = HZ / 4; + struct drm_i915_private *i915 = arg; + struct drm_i915_gem_request *request; + int err = -EINVAL; + + /* Submit a request, treat it as a fence and wait upon it */ + + mutex_lock(&i915->drm.struct_mutex); + request = mock_request(i915->engine[RCS], i915->kernel_context, T); + if (!request) { + err = -ENOMEM; + goto out_locked; + } + + i915_add_request(request); + mutex_unlock(&i915->drm.struct_mutex); + + if (dma_fence_is_signaled(&request->fence)) { + pr_err("fence signaled immediately!\n"); + goto out_device; + } + + if (dma_fence_wait_timeout(&request->fence, false, T / 2) != -ETIME) { + pr_err("fence wait success after submit (expected timeout)!\n"); + goto out_device; + } + + if (dma_fence_wait_timeout(&request->fence, false, T) <= 0) { + pr_err("fence wait timed out (expected success)!\n"); + goto out_device; + } + + if (!dma_fence_is_signaled(&request->fence)) { + pr_err("fence unsignaled after waiting!\n"); + goto out_device; + } + + err = 0; +out_device: + mutex_lock(&i915->drm.struct_mutex); +out_locked: + mock_device_flush(i915); + mutex_unlock(&i915->drm.struct_mutex); + return err; +} + int i915_gem_request_mock_selftests(void) { static const struct i915_subtest tests[] = { SUBTEST(igt_add_request), SUBTEST(igt_wait_request), + SUBTEST(igt_fence_wait), }; struct drm_i915_private *i915; int err; -- 2.11.0 ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/intel-gfx
[Intel-gfx] [PATCH 18/46] drm/i915: Test simultaneously submitting requests to all engines
Use a recursive-batch to busy spin on each to ensure that each is being run simultaneously. Signed-off-by: Chris Wilson Reviewed-by: Joonas Lahtinen --- drivers/gpu/drm/i915/selftests/i915_gem_request.c | 173 ++ 1 file changed, 173 insertions(+) diff --git a/drivers/gpu/drm/i915/selftests/i915_gem_request.c b/drivers/gpu/drm/i915/selftests/i915_gem_request.c index b5c7cd6633f0..570cfa196ca7 100644 --- a/drivers/gpu/drm/i915/selftests/i915_gem_request.c +++ b/drivers/gpu/drm/i915/selftests/i915_gem_request.c @@ -301,10 +301,183 @@ static int live_nop_request(void *arg) return err; } +static struct i915_vma *recursive_batch(struct drm_i915_private *i915) +{ + struct i915_gem_context *ctx = i915->kernel_context; + struct i915_address_space *vm = ctx->ppgtt ? &ctx->ppgtt->base : &i915->ggtt.base; + struct drm_i915_gem_object *obj; + const int gen = INTEL_GEN(i915); + struct i915_vma *vma; + u32 *cmd; + int err; + + obj = i915_gem_object_create_internal(i915, PAGE_SIZE); + if (IS_ERR(obj)) + return ERR_CAST(obj); + + vma = i915_vma_instance(obj, vm, NULL); + if (IS_ERR(vma)) { + err = PTR_ERR(vma); + goto err; + } + + err = i915_vma_pin(vma, 0, 0, PIN_USER); + if (err) + goto err; + + err = i915_gem_object_set_to_gtt_domain(obj, true); + if (err) + goto err; + + cmd = i915_gem_object_pin_map(obj, I915_MAP_WC); + if (IS_ERR(cmd)) { + err = PTR_ERR(cmd); + goto err; + } + + if (gen >= 8) { + *cmd++ = MI_BATCH_BUFFER_START | 1 << 8 | 1; + *cmd++ = lower_32_bits(vma->node.start); + *cmd++ = upper_32_bits(vma->node.start); + } else if (gen >= 6) { + *cmd++ = MI_BATCH_BUFFER_START | 1 << 8; + *cmd++ = lower_32_bits(vma->node.start); + } else if (gen >= 4) { + *cmd++ = MI_BATCH_BUFFER_START | MI_BATCH_GTT; + *cmd++ = lower_32_bits(vma->node.start); + } else { + *cmd++ = MI_BATCH_BUFFER_START | MI_BATCH_GTT | 1; + *cmd++ = lower_32_bits(vma->node.start); + } + *cmd++ = MI_BATCH_BUFFER_END; /* terminate early in case of error */ + + wmb(); + i915_gem_object_unpin_map(obj); + + return vma; + +err: + i915_gem_object_put(obj); + return ERR_PTR(err); +} + +static int live_all_engines(void *arg) +{ + struct drm_i915_private *i915 = arg; + struct intel_engine_cs *engine; + struct drm_i915_gem_request *request[I915_NUM_ENGINES]; + struct i915_vma *batch; + struct live_test t; + unsigned int id; + u32 *cmd; + int err; + + /* Check we can submit requests to all engines simultaneously. We +* send a recursive batch to each engine - checking that we don't +* block doing so, and that they don't complete too soon. +*/ + + mutex_lock(&i915->drm.struct_mutex); + + err = begin_live_test(&t, i915, __func__, ""); + if (err) + goto out_unlock; + + batch = recursive_batch(i915); + if (IS_ERR(batch)) { + err = PTR_ERR(batch); + pr_err("%s: Unable to create batch, err=%d\n", __func__, err); + goto out_unlock; + } + + for_each_engine(engine, i915, id) { + request[id] = i915_gem_request_alloc(engine, +i915->kernel_context); + if (IS_ERR(request[id])) { + err = PTR_ERR(request[id]); + pr_err("%s: Request allocation failed with err=%d\n", + __func__, err); + goto out_request; + } + + err = engine->emit_flush(request[id], EMIT_INVALIDATE); + GEM_BUG_ON(err); + + err = i915_switch_context(request[id]); + GEM_BUG_ON(err); + + err = engine->emit_bb_start(request[id], + batch->node.start, + batch->node.size, + 0); + GEM_BUG_ON(err); + request[id]->batch = batch; + + if (!i915_gem_object_has_active_reference(batch->obj)) { + i915_gem_object_get(batch->obj); + i915_gem_object_set_active_reference(batch->obj); + } + + i915_vma_move_to_active(batch, request[id], 0); + i915_gem_request_get(request[id]); + i915_add_request(request[id]); + } + + for_each_engine(engine, i915, id) { + if (i915_gem_request_completed(request[id])) { + pr_err("%s(%s): request completed too early!\n", +
[Intel-gfx] [PATCH 22/46] drm/i915: Add a live seftest for GEM objects
Starting with a placeholder test just to reassure that we can create a test object, Signed-off-by: Chris Wilson Reviewed-by: Matthew Auld --- drivers/gpu/drm/i915/selftests/i915_gem_object.c | 49 ++ .../gpu/drm/i915/selftests/i915_live_selftests.h | 1 + 2 files changed, 50 insertions(+) diff --git a/drivers/gpu/drm/i915/selftests/i915_gem_object.c b/drivers/gpu/drm/i915/selftests/i915_gem_object.c index db8f631e4993..d7330db70063 100644 --- a/drivers/gpu/drm/i915/selftests/i915_gem_object.c +++ b/drivers/gpu/drm/i915/selftests/i915_gem_object.c @@ -100,6 +100,46 @@ static int igt_phys_object(void *arg) return err; } +static int igt_gem_huge(void *arg) +{ + const unsigned int nreal = 509; /* just to be awkward */ + struct drm_i915_private *i915 = arg; + struct drm_i915_gem_object *obj; + unsigned int n; + int err; + + /* Basic sanitycheck of our huge fake object allocation */ + + obj = huge_gem_object(i915, + nreal * PAGE_SIZE, + i915->ggtt.base.total + PAGE_SIZE); + if (IS_ERR(obj)) + return PTR_ERR(obj); + + err = i915_gem_object_pin_pages(obj); + if (err) { + pr_err("Failed to allocate %u pages (%lu total), err=%d\n", + nreal, obj->base.size / PAGE_SIZE, err); + goto out; + } + + for (n = 0; n < obj->base.size / PAGE_SIZE; n++) { + if (i915_gem_object_get_page(obj, n) != + i915_gem_object_get_page(obj, n % nreal)) { + pr_err("Page lookup mismatch at index %u [%u]\n", + n, n % nreal); + err = -EINVAL; + goto out_unpin; + } + } + +out_unpin: + i915_gem_object_unpin_pages(obj); +out: + i915_gem_object_put(obj); + return err; +} + int i915_gem_object_mock_selftests(void) { static const struct i915_subtest tests[] = { @@ -118,3 +158,12 @@ int i915_gem_object_mock_selftests(void) drm_dev_unref(&i915->drm); return err; } + +int i915_gem_object_live_selftests(struct drm_i915_private *i915) +{ + static const struct i915_subtest tests[] = { + SUBTEST(igt_gem_huge), + }; + + return i915_subtests(tests, i915); +} diff --git a/drivers/gpu/drm/i915/selftests/i915_live_selftests.h b/drivers/gpu/drm/i915/selftests/i915_live_selftests.h index 09bf538826df..1822ac99d577 100644 --- a/drivers/gpu/drm/i915/selftests/i915_live_selftests.h +++ b/drivers/gpu/drm/i915/selftests/i915_live_selftests.h @@ -10,3 +10,4 @@ */ selftest(sanitycheck, i915_live_sanitycheck) /* keep first (igt selfcheck) */ selftest(requests, i915_gem_request_live_selftests) +selftest(object, i915_gem_object_live_selftests) -- 2.11.0 ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/intel-gfx
[Intel-gfx] [PATCH 13/46] drm/i915: Create a fake object for testing huge allocations
We would like to be able to exercise huge allocations even on memory constrained devices. To do this we create an object that allocates only a few pages and remaps them across its whole range - each page is reused multiple times. We can therefore pretend we are rendering into a much larger object. Signed-off-by: Chris Wilson Reviewed-by: Matthew Auld --- drivers/gpu/drm/i915/i915_gem.c | 1 + drivers/gpu/drm/i915/i915_gem_object.h | 20 ++-- drivers/gpu/drm/i915/selftests/huge_gem_object.c | 135 +++ drivers/gpu/drm/i915/selftests/huge_gem_object.h | 45 4 files changed, 193 insertions(+), 8 deletions(-) create mode 100644 drivers/gpu/drm/i915/selftests/huge_gem_object.c create mode 100644 drivers/gpu/drm/i915/selftests/huge_gem_object.h diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 778a659a7836..f35fda5d0abc 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -4972,4 +4972,5 @@ i915_gem_object_get_dma_address(struct drm_i915_gem_object *obj, #if IS_ENABLED(CONFIG_DRM_I915_SELFTEST) #include "selftests/scatterlist.c" #include "selftests/mock_gem_device.c" +#include "selftests/huge_gem_object.c" #endif diff --git a/drivers/gpu/drm/i915/i915_gem_object.h b/drivers/gpu/drm/i915/i915_gem_object.h index 33a7d031e749..0da69546970b 100644 --- a/drivers/gpu/drm/i915/i915_gem_object.h +++ b/drivers/gpu/drm/i915/i915_gem_object.h @@ -167,14 +167,18 @@ struct drm_i915_gem_object { /** Record of address bit 17 of each page at last unbind. */ unsigned long *bit_17; - struct i915_gem_userptr { - uintptr_t ptr; - unsigned read_only :1; - - struct i915_mm_struct *mm; - struct i915_mmu_object *mmu_object; - struct work_struct *work; - } userptr; + union { + struct i915_gem_userptr { + uintptr_t ptr; + unsigned read_only :1; + + struct i915_mm_struct *mm; + struct i915_mmu_object *mmu_object; + struct work_struct *work; + } userptr; + + unsigned long scratch; + }; /** for phys allocated objects */ struct drm_dma_handle *phys_handle; diff --git a/drivers/gpu/drm/i915/selftests/huge_gem_object.c b/drivers/gpu/drm/i915/selftests/huge_gem_object.c new file mode 100644 index ..4e681fc13be4 --- /dev/null +++ b/drivers/gpu/drm/i915/selftests/huge_gem_object.c @@ -0,0 +1,135 @@ +/* + * Copyright © 2016 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + * + */ + +#include "huge_gem_object.h" + +static void huge_free_pages(struct drm_i915_gem_object *obj, + struct sg_table *pages) +{ + unsigned long nreal = obj->scratch / PAGE_SIZE; + struct scatterlist *sg; + + for (sg = pages->sgl; sg && nreal--; sg = __sg_next(sg)) + __free_page(sg_page(sg)); + + sg_free_table(pages); + kfree(pages); +} + +static struct sg_table * +huge_get_pages(struct drm_i915_gem_object *obj) +{ +#define GFP (GFP_KERNEL | __GFP_NOWARN | __GFP_NORETRY) + const unsigned long nreal = obj->scratch / PAGE_SIZE; + const unsigned long npages = obj->base.size / PAGE_SIZE; + struct scatterlist *sg, *src, *end; + struct sg_table *pages; + unsigned long n; + + pages = kmalloc(sizeof(*pages), GFP); + if (!pages) + return ERR_PTR(-ENOMEM); + + if (sg_alloc_table(pages, npages, GFP)) { + kfree(pages); + return ERR_PTR(-ENOMEM); + } + + sg = pages->sgl; + for (n = 0; n < nreal; n++) { + struct page *page; + + page = alloc_page(GFP | __GFP_HIGHMEM); +
[Intel-gfx] [PATCH 11/46] drm/i915: Mock a GGTT for self-testing
A very simple mockery, just a random manager and timeline. Useful for inserting objects and ordering retirement; and not much else. v2: mock_fini_ggtt() to complement mock_init_ggtt(). Signed-off-by: Chris Wilson Reviewed-by: Matthew Auld --- drivers/gpu/drm/i915/i915_gem_gtt.c | 4 + drivers/gpu/drm/i915/selftests/mock_gem_device.c | 31 + drivers/gpu/drm/i915/selftests/mock_gtt.c| 138 +++ drivers/gpu/drm/i915/selftests/mock_gtt.h| 35 ++ 4 files changed, 208 insertions(+) create mode 100644 drivers/gpu/drm/i915/selftests/mock_gtt.c create mode 100644 drivers/gpu/drm/i915/selftests/mock_gtt.h diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c index 65425e71f3a5..afdb2859be05 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.c +++ b/drivers/gpu/drm/i915/i915_gem_gtt.c @@ -3751,3 +3751,7 @@ int i915_gem_gtt_insert(struct i915_address_space *vm, size, alignment, color, start, end, DRM_MM_INSERT_EVICT); } + +#if IS_ENABLED(CONFIG_DRM_I915_SELFTEST) +#include "selftests/mock_gtt.c" +#endif diff --git a/drivers/gpu/drm/i915/selftests/mock_gem_device.c b/drivers/gpu/drm/i915/selftests/mock_gem_device.c index 15d0a7ccc9d1..dbd32b125d15 100644 --- a/drivers/gpu/drm/i915/selftests/mock_gem_device.c +++ b/drivers/gpu/drm/i915/selftests/mock_gem_device.c @@ -26,6 +26,7 @@ #include "mock_gem_device.h" #include "mock_gem_object.h" +#include "mock_gtt.h" static void mock_device_release(struct drm_device *dev) { @@ -33,6 +34,12 @@ static void mock_device_release(struct drm_device *dev) i915_gem_drain_freed_objects(i915); + mutex_lock(&i915->drm.struct_mutex); + mock_fini_ggtt(i915); + i915_gem_timeline_fini(&i915->gt.global_timeline); + mutex_unlock(&i915->drm.struct_mutex); + + kmem_cache_destroy(i915->vmas); kmem_cache_destroy(i915->objects); drm_dev_fini(&i915->drm); @@ -84,19 +91,43 @@ struct drm_i915_private *mock_gem_device(void) i915->drm.pdev = pdev; i915->drm.dev_private = i915; + /* Using the global GTT may ask questions about KMS users, so prepare */ + drm_mode_config_init(&i915->drm); + mkwrite_device_info(i915)->gen = -1; spin_lock_init(&i915->mm.object_stat_lock); INIT_WORK(&i915->mm.free_work, __i915_gem_free_work); init_llist_head(&i915->mm.free_list); + INIT_LIST_HEAD(&i915->mm.unbound_list); + INIT_LIST_HEAD(&i915->mm.bound_list); i915->objects = KMEM_CACHE(mock_object, SLAB_HWCACHE_ALIGN); if (!i915->objects) goto put_device; + i915->vmas = KMEM_CACHE(i915_vma, SLAB_HWCACHE_ALIGN); + if (!i915->vmas) + goto err_objects; + + mutex_lock(&i915->drm.struct_mutex); + INIT_LIST_HEAD(&i915->gt.timelines); + err = i915_gem_timeline_init__global(i915); + if (err) { + mutex_unlock(&i915->drm.struct_mutex); + goto err_vmas; + } + + mock_init_ggtt(i915); + mutex_unlock(&i915->drm.struct_mutex); + return i915; +err_vmas: + kmem_cache_destroy(i915->vmas); +err_objects: + kmem_cache_destroy(i915->objects); put_device: put_device(&pdev->dev); err: diff --git a/drivers/gpu/drm/i915/selftests/mock_gtt.c b/drivers/gpu/drm/i915/selftests/mock_gtt.c new file mode 100644 index ..a61309c7cb3e --- /dev/null +++ b/drivers/gpu/drm/i915/selftests/mock_gtt.c @@ -0,0 +1,138 @@ +/* + * Copyright © 2016 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + * + */ + +#include "mock_gtt.h" + +static void mock_insert_page(struct i915_address_space *vm, +dma_addr_t addr, +u64 offset, +
[Intel-gfx] [PATCH 24/46] drm/i915: Test exhaustion of the mmap space
An unlikely error condition that we can simulate by stealing most of the range before trying to insert new objects. Signed-off-by: Chris Wilson Reviewed-by: Matthew Auld --- drivers/gpu/drm/i915/selftests/i915_gem_object.c | 138 +++ 1 file changed, 138 insertions(+) diff --git a/drivers/gpu/drm/i915/selftests/i915_gem_object.c b/drivers/gpu/drm/i915/selftests/i915_gem_object.c index 140bae2c8ad2..3cdeb83f8742 100644 --- a/drivers/gpu/drm/i915/selftests/i915_gem_object.c +++ b/drivers/gpu/drm/i915/selftests/i915_gem_object.c @@ -25,6 +25,7 @@ #include "../i915_selftest.h" #include "mock_gem_device.h" +#include "huge_gem_object.h" static int igt_gem_object(void *arg) { @@ -432,6 +433,142 @@ next_tiling: ; return err; } +static int make_obj_busy(struct drm_i915_gem_object *obj) +{ + struct drm_i915_private *i915 = to_i915(obj->base.dev); + struct drm_i915_gem_request *rq; + struct i915_vma *vma; + int err; + + vma = i915_vma_instance(obj, &i915->ggtt.base, NULL); + if (IS_ERR(vma)) + return PTR_ERR(vma); + + err = i915_vma_pin(vma, 0, 0, PIN_USER); + if (err) + return err; + + rq = i915_gem_request_alloc(i915->engine[RCS], i915->kernel_context); + if (IS_ERR(rq)) { + i915_vma_unpin(vma); + return PTR_ERR(rq); + } + + i915_vma_move_to_active(vma, rq, 0); + i915_add_request(rq); + + i915_gem_object_set_active_reference(obj); + i915_vma_unpin(vma); + return 0; +} + +static bool assert_mmap_offset(struct drm_i915_private *i915, + unsigned long size, + int expected) +{ + struct drm_i915_gem_object *obj; + int err; + + obj = i915_gem_object_create_internal(i915, size); + if (IS_ERR(obj)) + return PTR_ERR(obj); + + err = i915_gem_object_create_mmap_offset(obj); + i915_gem_object_put(obj); + + return err == expected; +} + +static int igt_mmap_offset_exhaustion(void *arg) +{ + struct drm_i915_private *i915 = arg; + struct drm_mm *mm = &i915->drm.vma_offset_manager->vm_addr_space_mm; + struct drm_i915_gem_object *obj; + struct drm_mm_node resv, *hole; + u64 hole_start, hole_end; + int loop, err; + + /* Trim the device mmap space to only a page */ + memset(&resv, 0, sizeof(resv)); + drm_mm_for_each_hole(hole, mm, hole_start, hole_end) { + resv.start = hole_start; + resv.size = hole_end - hole_start - 1; /* PAGE_SIZE units */ + err = drm_mm_reserve_node(mm, &resv); + if (err) { + pr_err("Failed to trim VMA manager, err=%d\n", err); + return err; + } + break; + } + + /* Just fits! */ + if (!assert_mmap_offset(i915, PAGE_SIZE, 0)) { + pr_err("Unable to insert object into single page hole\n"); + err = -EINVAL; + goto out; + } + + /* Too large */ + if (!assert_mmap_offset(i915, 2*PAGE_SIZE, -ENOSPC)) { + pr_err("Unexpectedly succeeded in inserting too large object into single page hole\n"); + err = -EINVAL; + goto out; + } + + /* Fill the hole, further allocation attempts should then fail */ + obj = i915_gem_object_create_internal(i915, PAGE_SIZE); + if (IS_ERR(obj)) { + err = PTR_ERR(obj); + goto out; + } + + err = i915_gem_object_create_mmap_offset(obj); + if (err) { + pr_err("Unable to insert object into reclaimed hole\n"); + goto err_obj; + } + + if (!assert_mmap_offset(i915, PAGE_SIZE, -ENOSPC)) { + pr_err("Unexpectedly succeeded in inserting object into no holes!\n"); + err = -EINVAL; + goto err_obj; + } + + i915_gem_object_put(obj); + + /* Now fill with busy dead objects that we expect to reap */ + for (loop = 0; loop < 3; loop++) { + obj = i915_gem_object_create_internal(i915, PAGE_SIZE); + if (IS_ERR(obj)) { + err = PTR_ERR(obj); + goto out; + } + + mutex_lock(&i915->drm.struct_mutex); + err = make_obj_busy(obj); + mutex_unlock(&i915->drm.struct_mutex); + if (err) { + pr_err("[loop %d] Failed to busy the object\n", loop); + goto err_obj; + } + + GEM_BUG_ON(!i915_gem_object_is_active(obj)); + err = i915_gem_object_create_mmap_offset(obj); + if (err) { + pr_err("[loop %d] i915_gem_object_create_mmap_offset failed with err=%d\n", + loop, err); +
[Intel-gfx] [PATCH 19/46] drm/i915: Test request ordering between engines
A request on one engine with a dependency on a request on another engine must wait for completion of the first request before starting. Signed-off-by: Chris Wilson --- drivers/gpu/drm/i915/selftests/i915_gem_request.c | 137 ++ 1 file changed, 137 insertions(+) diff --git a/drivers/gpu/drm/i915/selftests/i915_gem_request.c b/drivers/gpu/drm/i915/selftests/i915_gem_request.c index 570cfa196ca7..f9c171d1a05b 100644 --- a/drivers/gpu/drm/i915/selftests/i915_gem_request.c +++ b/drivers/gpu/drm/i915/selftests/i915_gem_request.c @@ -473,11 +473,148 @@ static int live_all_engines(void *arg) return err; } +static int live_sequential_engines(void *arg) +{ + struct drm_i915_private *i915 = arg; + struct drm_i915_gem_request *request[I915_NUM_ENGINES] = {}; + struct drm_i915_gem_request *prev = NULL; + struct intel_engine_cs *engine; + struct live_test t; + unsigned int id; + int err; + + /* Check we can submit requests to all engines sequentially, such +* that each successive request waits for the earlier ones. This +* tests that we don't execute requests out of order, even though +* they are running on independent engines. +*/ + + mutex_lock(&i915->drm.struct_mutex); + + err = begin_live_test(&t, i915, __func__, ""); + if (err) + goto out_unlock; + + for_each_engine(engine, i915, id) { + struct i915_vma *batch; + + batch = recursive_batch(i915); + if (IS_ERR(batch)) { + err = PTR_ERR(batch); + pr_err("%s: Unable to create batch for %s, err=%d\n", + __func__, engine->name, err); + goto out_unlock; + } + + request[id] = i915_gem_request_alloc(engine, +i915->kernel_context); + if (IS_ERR(request[id])) { + err = PTR_ERR(request[id]); + pr_err("%s: Request allocation failed for %s with err=%d\n", + __func__, engine->name, err); + goto out_request; + } + + if (prev) { + err = i915_gem_request_await_dma_fence(request[id], + &prev->fence); + if (err) { + i915_add_request(request[id]); + pr_err("%s: Request await failed for %s with err=%d\n", + __func__, engine->name, err); + goto out_request; + } + } + + err = engine->emit_flush(request[id], EMIT_INVALIDATE); + GEM_BUG_ON(err); + + err = i915_switch_context(request[id]); + GEM_BUG_ON(err); + + err = engine->emit_bb_start(request[id], + batch->node.start, + batch->node.size, + 0); + GEM_BUG_ON(err); + request[id]->batch = batch; + + i915_vma_move_to_active(batch, request[id], 0); + i915_gem_object_set_active_reference(batch->obj); + i915_vma_get(batch); + + i915_gem_request_get(request[id]); + i915_add_request(request[id]); + + prev = request[id]; + } + + for_each_engine(engine, i915, id) { + long timeout; + u32 *cmd; + + if (i915_gem_request_completed(request[id])) { + pr_err("%s(%s): request completed too early!\n", + __func__, engine->name); + err = -EINVAL; + goto out_request; + } + + cmd = i915_gem_object_pin_map(request[id]->batch->obj, + I915_MAP_WC); + if (IS_ERR(cmd)) { + err = PTR_ERR(cmd); + pr_err("%s: failed to WC map batch, err=%d\n", __func__, err); + goto out_request; + } + *cmd = MI_BATCH_BUFFER_END; + wmb(); + i915_gem_object_unpin_map(request[id]->batch->obj); + + timeout = i915_wait_request(request[id], + I915_WAIT_LOCKED, + MAX_SCHEDULE_TIMEOUT); + if (timeout < 0) { + err = timeout; + pr_err("%s: error waiting for request on %s, err=%d\n", + __func__, engine->name, err); + goto out_request; + } + + GEM_BUG
[Intel-gfx] [PATCH 14/46] drm/i915: Add selftests for i915_gem_request
Simple starting point for adding seltests for i915_gem_request, first mock a device (with engines and contexts) that allows us to construct and execute a request, along with waiting for the request to complete. Signed-off-by: Chris Wilson Reviewed-by: Tvrtko Ursulin --- drivers/gpu/drm/i915/i915_gem_request.c| 5 ++ drivers/gpu/drm/i915/selftests/i915_gem_request.c | 68 ++ .../gpu/drm/i915/selftests/i915_mock_selftests.h | 1 + 3 files changed, 74 insertions(+) create mode 100644 drivers/gpu/drm/i915/selftests/i915_gem_request.c diff --git a/drivers/gpu/drm/i915/i915_gem_request.c b/drivers/gpu/drm/i915/i915_gem_request.c index 72b7f7d9461d..bd2aeb290cad 100644 --- a/drivers/gpu/drm/i915/i915_gem_request.c +++ b/drivers/gpu/drm/i915/i915_gem_request.c @@ -1193,3 +1193,8 @@ void i915_gem_retire_requests(struct drm_i915_private *dev_priv) for_each_engine(engine, dev_priv, id) engine_retire_requests(engine); } + +#if IS_ENABLED(CONFIG_DRM_I915_SELFTEST) +#include "selftests/mock_request.c" +#include "selftests/i915_gem_request.c" +#endif diff --git a/drivers/gpu/drm/i915/selftests/i915_gem_request.c b/drivers/gpu/drm/i915/selftests/i915_gem_request.c new file mode 100644 index ..9921d1c317c0 --- /dev/null +++ b/drivers/gpu/drm/i915/selftests/i915_gem_request.c @@ -0,0 +1,68 @@ +/* + * Copyright © 2016 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + * + */ + +#include "../i915_selftest.h" + +#include "mock_gem_device.h" + +static int igt_add_request(void *arg) +{ + struct drm_i915_private *i915 = arg; + struct drm_i915_gem_request *request; + int err = -ENOMEM; + + /* Basic preliminary test to create a request and let it loose! */ + + mutex_lock(&i915->drm.struct_mutex); + request = mock_request(i915->engine[RCS], + i915->kernel_context, + HZ / 10); + if (!request) + goto out_unlock; + + i915_add_request(request); + + err = 0; +out_unlock: + mutex_unlock(&i915->drm.struct_mutex); + return err; +} + +int i915_gem_request_mock_selftests(void) +{ + static const struct i915_subtest tests[] = { + SUBTEST(igt_add_request), + }; + struct drm_i915_private *i915; + int err; + + i915 = mock_gem_device(); + if (!i915) + return -ENOMEM; + + err = i915_subtests(tests, i915); + drm_dev_unref(&i915->drm); + + return err; +} diff --git a/drivers/gpu/drm/i915/selftests/i915_mock_selftests.h b/drivers/gpu/drm/i915/selftests/i915_mock_selftests.h index 80458e2a2b04..bda982404ad3 100644 --- a/drivers/gpu/drm/i915/selftests/i915_mock_selftests.h +++ b/drivers/gpu/drm/i915/selftests/i915_mock_selftests.h @@ -11,3 +11,4 @@ selftest(sanitycheck, i915_mock_sanitycheck) /* keep first (igt selfcheck) */ selftest(scatterlist, scatterlist_mock_selftests) selftest(breadcrumbs, intel_breadcrumbs_mock_selftests) +selftest(requests, i915_gem_request_mock_selftests) -- 2.11.0 ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/intel-gfx
[Intel-gfx] [PATCH 26/46] drm/i915: Move uncore selfchecks to live selftest infrastructure
Now that the kselftest infrastructure exists, put it to use and add to it the existing consistency checks on the fw register lookup tables. v2: s/tabke/table/ Signed-off-by: Chris Wilson Cc: Tvrtko Ursulin Reviewed-by: Matthew Auld --- drivers/gpu/drm/i915/intel_uncore.c| 52 +--- .../gpu/drm/i915/selftests/i915_live_selftests.h | 1 + drivers/gpu/drm/i915/selftests/intel_uncore.c | 99 ++ 3 files changed, 104 insertions(+), 48 deletions(-) create mode 100644 drivers/gpu/drm/i915/selftests/intel_uncore.c diff --git a/drivers/gpu/drm/i915/intel_uncore.c b/drivers/gpu/drm/i915/intel_uncore.c index 3d243fefe09b..9bc103a00b72 100644 --- a/drivers/gpu/drm/i915/intel_uncore.c +++ b/drivers/gpu/drm/i915/intel_uncore.c @@ -642,33 +642,6 @@ find_fw_domain(struct drm_i915_private *dev_priv, u32 offset) return entry->domains; } -static void -intel_fw_table_check(struct drm_i915_private *dev_priv) -{ - const struct intel_forcewake_range *ranges; - unsigned int num_ranges; - s32 prev; - unsigned int i; - - if (!IS_ENABLED(CONFIG_DRM_I915_DEBUG)) - return; - - ranges = dev_priv->uncore.fw_domains_table; - if (!ranges) - return; - - num_ranges = dev_priv->uncore.fw_domains_table_entries; - - for (i = 0, prev = -1; i < num_ranges; i++, ranges++) { - WARN_ON_ONCE(IS_GEN9(dev_priv) && -(prev + 1) != (s32)ranges->start); - WARN_ON_ONCE(prev >= (s32)ranges->start); - prev = ranges->start; - WARN_ON_ONCE(prev >= (s32)ranges->end); - prev = ranges->end; - } -} - #define GEN_FW_RANGE(s, e, d) \ { .start = (s), .end = (e), .domains = (d) } @@ -707,23 +680,6 @@ static const i915_reg_t gen8_shadowed_regs[] = { /* TODO: Other registers are not yet used */ }; -static void intel_shadow_table_check(void) -{ - const i915_reg_t *reg = gen8_shadowed_regs; - s32 prev; - u32 offset; - unsigned int i; - - if (!IS_ENABLED(CONFIG_DRM_I915_DEBUG)) - return; - - for (i = 0, prev = -1; i < ARRAY_SIZE(gen8_shadowed_regs); i++, reg++) { - offset = i915_mmio_reg_offset(*reg); - WARN_ON_ONCE(prev >= (s32)offset); - prev = offset; - } -} - static int mmio_reg_cmp(u32 key, const i915_reg_t *reg) { u32 offset = i915_mmio_reg_offset(*reg); @@ -1404,10 +1360,6 @@ void intel_uncore_init(struct drm_i915_private *dev_priv) break; } - intel_fw_table_check(dev_priv); - if (INTEL_GEN(dev_priv) >= 8) - intel_shadow_table_check(); - i915_check_and_clear_faults(dev_priv); } #undef ASSIGN_WRITE_MMIO_VFUNCS @@ -1925,3 +1877,7 @@ intel_uncore_forcewake_for_reg(struct drm_i915_private *dev_priv, return fw_domains; } + +#if IS_ENABLED(CONFIG_DRM_I915_SELFTEST) +#include "selftests/intel_uncore.c" +#endif diff --git a/drivers/gpu/drm/i915/selftests/i915_live_selftests.h b/drivers/gpu/drm/i915/selftests/i915_live_selftests.h index fde9ef22cfe8..c060bf24928e 100644 --- a/drivers/gpu/drm/i915/selftests/i915_live_selftests.h +++ b/drivers/gpu/drm/i915/selftests/i915_live_selftests.h @@ -9,6 +9,7 @@ * Tests are executed in order by igt/drv_selftest */ selftest(sanitycheck, i915_live_sanitycheck) /* keep first (igt selfcheck) */ +selftest(uncore, intel_uncore_live_selftests) selftest(requests, i915_gem_request_live_selftests) selftest(object, i915_gem_object_live_selftests) selftest(coherency, i915_gem_coherency_live_selftests) diff --git a/drivers/gpu/drm/i915/selftests/intel_uncore.c b/drivers/gpu/drm/i915/selftests/intel_uncore.c new file mode 100644 index ..6b27dca78f69 --- /dev/null +++ b/drivers/gpu/drm/i915/selftests/intel_uncore.c @@ -0,0 +1,99 @@ +/* + * Copyright © 2016 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARI
[Intel-gfx] [PATCH 27/46] drm/i915: Test all fw tables during mock selftests
In addition to just testing the fw table we load, during the initial mock testing we can test that all tables are valid (so the testing is not limited to just the platforms that load that particular table). Signed-off-by: Chris Wilson Cc: Tvrtko Ursulin Reviewed-by: Matthew Auld --- .../gpu/drm/i915/selftests/i915_mock_selftests.h | 1 + drivers/gpu/drm/i915/selftests/intel_uncore.c | 49 -- 2 files changed, 37 insertions(+), 13 deletions(-) diff --git a/drivers/gpu/drm/i915/selftests/i915_mock_selftests.h b/drivers/gpu/drm/i915/selftests/i915_mock_selftests.h index 2ed94e3a71b7..c61e08de7913 100644 --- a/drivers/gpu/drm/i915/selftests/i915_mock_selftests.h +++ b/drivers/gpu/drm/i915/selftests/i915_mock_selftests.h @@ -10,6 +10,7 @@ */ selftest(sanitycheck, i915_mock_sanitycheck) /* keep first (igt selfcheck) */ selftest(scatterlist, scatterlist_mock_selftests) +selftest(uncore, intel_uncore_mock_selftests) selftest(breadcrumbs, intel_breadcrumbs_mock_selftests) selftest(requests, i915_gem_request_mock_selftests) selftest(objects, i915_gem_object_mock_selftests) diff --git a/drivers/gpu/drm/i915/selftests/intel_uncore.c b/drivers/gpu/drm/i915/selftests/intel_uncore.c index 6b27dca78f69..c563962eaad7 100644 --- a/drivers/gpu/drm/i915/selftests/intel_uncore.c +++ b/drivers/gpu/drm/i915/selftests/intel_uncore.c @@ -24,20 +24,16 @@ #include "../i915_selftest.h" -static int intel_fw_table_check(struct drm_i915_private *i915) +static int intel_fw_table_check(const struct intel_forcewake_range *ranges, + unsigned int num_ranges, + bool is_watertight) { - const struct intel_forcewake_range *ranges; - unsigned int num_ranges, i; + unsigned int i; s32 prev; - ranges = i915->uncore.fw_domains_table; - if (!ranges) - return 0; - - num_ranges = i915->uncore.fw_domains_table_entries; for (i = 0, prev = -1; i < num_ranges; i++, ranges++) { /* Check that the table is watertight */ - if (IS_GEN9(i915) && (prev + 1) != (s32)ranges->start) { + if (is_watertight && (prev + 1) != (s32)ranges->start) { pr_err("%s: entry[%d]:(%x, %x) is not watertight to previous (%x)\n", __func__, i, ranges->start, ranges->end, prev); return -EINVAL; @@ -83,15 +79,42 @@ static int intel_shadow_table_check(void) return 0; } -int intel_uncore_live_selftests(struct drm_i915_private *i915) +int intel_uncore_mock_selftests(void) { - int err; + struct { + const struct intel_forcewake_range *ranges; + unsigned int num_ranges; + bool is_watertight; + } fw[] = { + { __vlv_fw_ranges, ARRAY_SIZE(__vlv_fw_ranges), false }, + { __chv_fw_ranges, ARRAY_SIZE(__chv_fw_ranges), false }, + { __gen9_fw_ranges, ARRAY_SIZE(__gen9_fw_ranges), true }, + }; + int err, i; + + for (i = 0; i < ARRAY_SIZE(fw); i++) { + err = intel_fw_table_check(fw[i].ranges, + fw[i].num_ranges, + fw[i].is_watertight); + if (err) + return err; + } - err = intel_fw_table_check(i915); + err = intel_shadow_table_check(); if (err) return err; - err = intel_shadow_table_check(); + return 0; +} + +int intel_uncore_live_selftests(struct drm_i915_private *i915) +{ + int err; + + /* Confirm the table we load is still valid */ + err = intel_fw_table_check(i915->uncore.fw_domains_table, + i915->uncore.fw_domains_table_entries, + INTEL_GEN(i915) >= 9); if (err) return err; -- 2.11.0 ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/intel-gfx
[Intel-gfx] [PATCH 21/46] drm/i915: Add selftests for object allocation, phys
The phys object is a rarely used device (only very old machines require a chunk of physically contiguous pages for a few hardware interactions). As such, it is not exercised by CI and to combat that we want to add a test that exercises the phys object on all platforms. Signed-off-by: Chris Wilson Reviewed-by: Tvrtko Ursulin --- drivers/gpu/drm/i915/i915_gem.c| 1 + drivers/gpu/drm/i915/selftests/i915_gem_object.c | 120 + .../gpu/drm/i915/selftests/i915_mock_selftests.h | 1 + 3 files changed, 122 insertions(+) create mode 100644 drivers/gpu/drm/i915/selftests/i915_gem_object.c diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index f35fda5d0abc..429c5e4350f7 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -4973,4 +4973,5 @@ i915_gem_object_get_dma_address(struct drm_i915_gem_object *obj, #include "selftests/scatterlist.c" #include "selftests/mock_gem_device.c" #include "selftests/huge_gem_object.c" +#include "selftests/i915_gem_object.c" #endif diff --git a/drivers/gpu/drm/i915/selftests/i915_gem_object.c b/drivers/gpu/drm/i915/selftests/i915_gem_object.c new file mode 100644 index ..db8f631e4993 --- /dev/null +++ b/drivers/gpu/drm/i915/selftests/i915_gem_object.c @@ -0,0 +1,120 @@ +/* + * Copyright © 2016 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + * + */ + +#include "../i915_selftest.h" + +#include "mock_gem_device.h" + +static int igt_gem_object(void *arg) +{ + struct drm_i915_private *i915 = arg; + struct drm_i915_gem_object *obj; + int err = -ENOMEM; + + /* Basic test to ensure we can create an object */ + + obj = i915_gem_object_create(i915, PAGE_SIZE); + if (IS_ERR(obj)) { + err = PTR_ERR(obj); + pr_err("i915_gem_object_create failed, err=%d\n", err); + goto out; + } + + err = 0; + i915_gem_object_put(obj); +out: + return err; +} + +static int igt_phys_object(void *arg) +{ + struct drm_i915_private *i915 = arg; + struct drm_i915_gem_object *obj; + int err = -ENOMEM; + + /* Create an object and bind it to a contiguous set of physical pages, +* i.e. exercise the i915_gem_object_phys API. +*/ + + obj = i915_gem_object_create(i915, PAGE_SIZE); + if (IS_ERR(obj)) { + err = PTR_ERR(obj); + pr_err("i915_gem_object_create failed, err=%d\n", err); + goto out; + } + + err = -EINVAL; + mutex_lock(&i915->drm.struct_mutex); + err = i915_gem_object_attach_phys(obj, PAGE_SIZE); + mutex_unlock(&i915->drm.struct_mutex); + if (err) { + pr_err("i915_gem_object_attach_phys failed, err=%d\n", err); + goto out_obj; + } + + if (obj->ops != &i915_gem_phys_ops) { + pr_err("i915_gem_object_attach_phys did not create a phys object\n"); + goto out_obj; + } + + if (!atomic_read(&obj->mm.pages_pin_count)) { + pr_err("i915_gem_object_attach_phys did not pin its phys pages\n"); + goto out_obj; + } + + /* Make the object dirty so that put_pages must do copy back the data */ + mutex_lock(&i915->drm.struct_mutex); + err = i915_gem_object_set_to_gtt_domain(obj, true); + mutex_unlock(&i915->drm.struct_mutex); + if (err) { + pr_err("i915_gem_object_set_to_gtt_domain failed with err=%d\n", + err); + goto out_obj; + } + + err = 0; +out_obj: + i915_gem_object_put(obj); +out: + return err; +} + +int i915_gem_object_mock_selftests(void) +{ + static const struct i915_subtest tests[] = { + SUBTEST(igt_gem_object), + SUBTEST(igt_phys_object), +
[Intel-gfx] [PATCH 15/46] drm/i915: Add a simple request selftest for waiting
A trivial kselftest to submit a request and wait upon it. Signed-off-by: Chris Wilson Reviewed-by: Tvrtko Ursulin --- drivers/gpu/drm/i915/selftests/i915_gem_request.c | 46 +++ 1 file changed, 46 insertions(+) diff --git a/drivers/gpu/drm/i915/selftests/i915_gem_request.c b/drivers/gpu/drm/i915/selftests/i915_gem_request.c index 9921d1c317c0..14584b67c4a0 100644 --- a/drivers/gpu/drm/i915/selftests/i915_gem_request.c +++ b/drivers/gpu/drm/i915/selftests/i915_gem_request.c @@ -49,10 +49,56 @@ static int igt_add_request(void *arg) return err; } +static int igt_wait_request(void *arg) +{ + const long T = HZ / 4; + struct drm_i915_private *i915 = arg; + struct drm_i915_gem_request *request; + int err = -EINVAL; + + /* Submit a request, then wait upon it */ + + mutex_lock(&i915->drm.struct_mutex); + request = mock_request(i915->engine[RCS], i915->kernel_context, T); + if (!request) { + err = -ENOMEM; + goto out_unlock; + } + + i915_add_request(request); + + if (i915_gem_request_completed(request)) { + pr_err("request completed immediately!\n"); + goto out_unlock; + } + + if (i915_wait_request(request, I915_WAIT_LOCKED, T / 2) != -ETIME) { + pr_err("request wait succeeded (expected tiemout!)\n"); + goto out_unlock; + } + + if (i915_wait_request(request, I915_WAIT_LOCKED, T) == -ETIME) { + pr_err("request wait timed out!\n"); + goto out_unlock; + } + + if (!i915_gem_request_completed(request)) { + pr_err("request not complete after waiting!\n"); + goto out_unlock; + } + + err = 0; +out_unlock: + mock_device_flush(i915); + mutex_unlock(&i915->drm.struct_mutex); + return err; +} + int i915_gem_request_mock_selftests(void) { static const struct i915_subtest tests[] = { SUBTEST(igt_add_request), + SUBTEST(igt_wait_request), }; struct drm_i915_private *i915; int err; -- 2.11.0 ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/intel-gfx
[Intel-gfx] [PATCH 17/46] drm/i915: Simple selftest to exercise live requests
Just create several batches of requests and expect it to not fall over! Signed-off-by: Chris Wilson Reviewed-by: Joonas Lahtinen --- drivers/gpu/drm/i915/selftests/i915_gem_request.c | 147 + .../gpu/drm/i915/selftests/i915_live_selftests.h | 1 + 2 files changed, 148 insertions(+) diff --git a/drivers/gpu/drm/i915/selftests/i915_gem_request.c b/drivers/gpu/drm/i915/selftests/i915_gem_request.c index bc6f5618f22b..b5c7cd6633f0 100644 --- a/drivers/gpu/drm/i915/selftests/i915_gem_request.c +++ b/drivers/gpu/drm/i915/selftests/i915_gem_request.c @@ -22,6 +22,8 @@ * */ +#include + #include "../i915_selftest.h" #include "mock_gem_device.h" @@ -161,3 +163,148 @@ int i915_gem_request_mock_selftests(void) return err; } + +struct live_test { + struct drm_i915_private *i915; + const char *func; + const char *name; + + unsigned int reset_count; +}; + +static int begin_live_test(struct live_test *t, + struct drm_i915_private *i915, + const char *func, + const char *name) +{ + int err; + + t->i915 = i915; + t->func = func; + t->name = name; + + err = i915_gem_wait_for_idle(i915, I915_WAIT_LOCKED); + if (err) { + pr_err("%s(%s): failed to idle before, with err=%d!", + func, name, err); + return err; + } + + i915_gem_retire_requests(i915); + + i915->gpu_error.missed_irq_rings = 0; + t->reset_count = i915_reset_count(&i915->gpu_error); + + return 0; +} + +static int end_live_test(struct live_test *t) +{ + struct drm_i915_private *i915 = t->i915; + + if (wait_for(intel_execlists_idle(i915), 1)) { + pr_err("%s(%s): GPU not idle\n", t->func, t->name); + return -EIO; + } + + if (t->reset_count != i915_reset_count(&i915->gpu_error)) { + pr_err("%s(%s): GPU was reset %d times!\n", + t->func, t->name, + i915_reset_count(&i915->gpu_error) - t->reset_count); + return -EIO; + } + + if (i915->gpu_error.missed_irq_rings) { + pr_err("%s(%s): Missed interrupts on engines %lx\n", + t->func, t->name, i915->gpu_error.missed_irq_rings); + return -EIO; + } + + return 0; +} + +static int live_nop_request(void *arg) +{ + struct drm_i915_private *i915 = arg; + struct intel_engine_cs *engine; + struct live_test t; + unsigned int id; + int err; + + /* Submit various sized batches of empty requests, to each engine +* (individually), and wait for the batch to complete. We can check +* the overhead of submitting requests to the hardware. +*/ + + mutex_lock(&i915->drm.struct_mutex); + + for_each_engine(engine, i915, id) { + IGT_TIMEOUT(end_time); + struct drm_i915_gem_request *request; + unsigned long n, prime; + ktime_t times[2] = {}; + + err = begin_live_test(&t, i915, __func__, engine->name); + if (err) + goto out_unlock; + + for_each_prime_number_from(prime, 1, 8192) { + times[1] = ktime_get_raw(); + + for (n = 0; n < prime; n++) { + request = i915_gem_request_alloc(engine, + i915->kernel_context); + if (IS_ERR(request)) { + err = PTR_ERR(request); + goto out_unlock; + } + + /* This space is left intentionally blank. +* +* We do not actually want to perform any +* action with this request, we just want +* to measure the latency in allocation +* and submission of our breadcrumbs - +* ensuring that the bare request is sufficient +* for the system to work (i.e. proper HEAD +* tracking of the rings, interrupt handling, +* etc). It also gives us the lowest bounds +* for latency. +*/ + + i915_add_request(request); + } + i915_wait_request(request, + I915_WAIT_LOCKED, + MAX_SCHEDULE_TIMEOUT); + + times[1] = ktime_sub(ktime_get_raw(), times[1]); + if (prime == 1) +
[Intel-gfx] [PATCH 32/46] drm/i915: Exercise filling the top/bottom portions of the ppgtt
Allocate objects with varying number of pages (which should hopefully consist of a mixture of contiguous page chunks and so coalesced sg lists) and check that the sg walkers in insert_pages cope. v2: Check both small <-> large Signed-off-by: Chris Wilson --- drivers/gpu/drm/i915/selftests/i915_gem_gtt.c | 362 ++ 1 file changed, 362 insertions(+) diff --git a/drivers/gpu/drm/i915/selftests/i915_gem_gtt.c b/drivers/gpu/drm/i915/selftests/i915_gem_gtt.c index 5c09dc920cb8..4cd55fc0820a 100644 --- a/drivers/gpu/drm/i915/selftests/i915_gem_gtt.c +++ b/drivers/gpu/drm/i915/selftests/i915_gem_gtt.c @@ -22,8 +22,101 @@ * */ +#include + #include "../i915_selftest.h" +#include "mock_drm.h" + +static void fake_free_pages(struct drm_i915_gem_object *obj, + struct sg_table *pages) +{ + sg_free_table(pages); + kfree(pages); +} + +static struct sg_table * +fake_get_pages(struct drm_i915_gem_object *obj) +{ +#define GFP (GFP_KERNEL | __GFP_NOWARN | __GFP_NORETRY) +#define PFN_BIAS 0x1000 + struct sg_table *pages; + struct scatterlist *sg; + typeof(obj->base.size) rem; + + pages = kmalloc(sizeof(*pages), GFP); + if (!pages) + return ERR_PTR(-ENOMEM); + + rem = round_up(obj->base.size, BIT(31)) >> 31; + if (sg_alloc_table(pages, rem, GFP)) { + kfree(pages); + return ERR_PTR(-ENOMEM); + } + + rem = obj->base.size; + for (sg = pages->sgl; sg; sg = sg_next(sg)) { + unsigned long len = min_t(typeof(rem), rem, BIT(31)); + + sg_set_page(sg, pfn_to_page(PFN_BIAS), len, 0); + sg_dma_address(sg) = page_to_phys(sg_page(sg)); + sg_dma_len(sg) = len; + + rem -= len; + } + + return pages; +#undef GFP +} + +static void fake_put_pages(struct drm_i915_gem_object *obj, + struct sg_table *pages) +{ + fake_free_pages(obj, pages); + obj->mm.dirty = false; +} + +static void fake_release(struct drm_i915_gem_object *obj) +{ + __i915_gem_object_unpin_pages(obj); +} + +static const struct drm_i915_gem_object_ops fake_ops = { + .get_pages = fake_get_pages, + .put_pages = fake_put_pages, + .release = fake_release +}; + +static struct drm_i915_gem_object * +fake_dma_object(struct drm_i915_private *i915, u64 size) +{ + struct drm_i915_gem_object *obj; + + GEM_BUG_ON(!size); + GEM_BUG_ON(!IS_ALIGNED(size, I915_GTT_PAGE_SIZE)); + + if (overflows_type(size, obj->base.size)) + return ERR_PTR(-E2BIG); + + obj = i915_gem_object_alloc(i915); + if (!obj) + return ERR_PTR(-ENOMEM); + + drm_gem_private_object_init(&i915->drm, &obj->base, size); + i915_gem_object_init(obj, &fake_ops); + + obj->base.write_domain = I915_GEM_DOMAIN_CPU; + obj->base.read_domains = I915_GEM_DOMAIN_CPU; + obj->cache_level = I915_CACHE_NONE; + + if (i915_gem_object_pin_pages(obj)) { + i915_gem_object_free(obj); + return ERR_PTR(-ENOMEM); + } + + return obj; +} + static int igt_ppgtt_alloc(void *arg) { struct drm_i915_private *dev_priv = arg; @@ -87,10 +180,279 @@ static int igt_ppgtt_alloc(void *arg) return err; } +static void close_object_list(struct list_head *objects, + struct i915_address_space *vm) +{ + struct drm_i915_gem_object *obj, *on; + + list_for_each_entry_safe(obj, on, objects, batch_pool_link) { + struct i915_vma *vma; + + vma = i915_vma_instance(obj, vm, NULL); + if (!IS_ERR(vma)) + i915_vma_close(vma); + + list_del(&obj->batch_pool_link); + i915_gem_object_put(obj); + } +} + +static int fill_hole(struct drm_i915_private *i915, +struct i915_address_space *vm, +u64 hole_start, u64 hole_end, +unsigned long end_time) +{ +#define FLAGS (PIN_USER | PIN_OFFSET_FIXED) + const u64 hole_size = hole_end - hole_start; + struct drm_i915_gem_object *obj; + const unsigned long max_pages = + min_t(u64, ULONG_MAX - 1, hole_size/2 >> PAGE_SHIFT); + const unsigned long max_step = max(int_sqrt(max_pages), 2UL); + unsigned long npages, prime; + struct i915_vma *vma; + LIST_HEAD(objects); + int err; + + /* Try binding many VMA working inwards from either edge */ + + for_each_prime_number_from(prime, 2, max_step) { + for (npages = 1; npages <= max_pages; npages *= prime) { + const u64 full_size = npages << PAGE_SHIFT; + const struct { + const char *name; + u64 offset; + int step; + }
[Intel-gfx] [PATCH 25/46] drm/i915: Test coherency of and barriers between cache domains
Write into an object using WB, WC, GTT, and GPU paths and make sure that our internal API is sufficient to ensure coherent reads and writes. v2: Avoid invalid free upon allocation error Signed-off-by: Chris Wilson Reviewed-by: Matthew Auld --- drivers/gpu/drm/i915/i915_gem.c| 1 + .../gpu/drm/i915/selftests/i915_gem_coherency.c| 364 + .../gpu/drm/i915/selftests/i915_live_selftests.h | 1 + 3 files changed, 366 insertions(+) create mode 100644 drivers/gpu/drm/i915/selftests/i915_gem_coherency.c diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 429c5e4350f7..2749c64a35a3 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -4974,4 +4974,5 @@ i915_gem_object_get_dma_address(struct drm_i915_gem_object *obj, #include "selftests/mock_gem_device.c" #include "selftests/huge_gem_object.c" #include "selftests/i915_gem_object.c" +#include "selftests/i915_gem_coherency.c" #endif diff --git a/drivers/gpu/drm/i915/selftests/i915_gem_coherency.c b/drivers/gpu/drm/i915/selftests/i915_gem_coherency.c new file mode 100644 index ..b5de1828221d --- /dev/null +++ b/drivers/gpu/drm/i915/selftests/i915_gem_coherency.c @@ -0,0 +1,364 @@ +/* + * Copyright © 2017 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + * + */ + +#include + +#include "../i915_selftest.h" +#include "i915_random.h" + +static int cpu_set(struct drm_i915_gem_object *obj, + unsigned long offset, + u32 v) +{ + unsigned int needs_clflush; + struct page *page; + typeof(v) *map; + int err; + + err = i915_gem_obj_prepare_shmem_write(obj, &needs_clflush); + if (err) + return err; + + page = i915_gem_object_get_page(obj, offset >> PAGE_SHIFT); + map = kmap_atomic(page); + if (needs_clflush & CLFLUSH_BEFORE) + clflush(map+offset_in_page(offset) / sizeof(*map)); + map[offset_in_page(offset) / sizeof(*map)] = v; + if (needs_clflush & CLFLUSH_AFTER) + clflush(map+offset_in_page(offset) / sizeof(*map)); + kunmap_atomic(map); + + i915_gem_obj_finish_shmem_access(obj); + return 0; +} + +static int cpu_get(struct drm_i915_gem_object *obj, + unsigned long offset, + u32 *v) +{ + unsigned int needs_clflush; + struct page *page; + typeof(v) map; + int err; + + err = i915_gem_obj_prepare_shmem_read(obj, &needs_clflush); + if (err) + return err; + + page = i915_gem_object_get_page(obj, offset >> PAGE_SHIFT); + map = kmap_atomic(page); + if (needs_clflush & CLFLUSH_BEFORE) + clflush(map+offset_in_page(offset) / sizeof(*map)); + *v = map[offset_in_page(offset) / sizeof(*map)]; + kunmap_atomic(map); + + i915_gem_obj_finish_shmem_access(obj); + return 0; +} + +static int gtt_set(struct drm_i915_gem_object *obj, + unsigned long offset, + u32 v) +{ + struct i915_vma *vma; + typeof(v) *map; + int err; + + err = i915_gem_object_set_to_gtt_domain(obj, true); + if (err) + return err; + + vma = i915_gem_object_ggtt_pin(obj, NULL, 0, 0, PIN_MAPPABLE); + if (IS_ERR(vma)) + return PTR_ERR(vma); + + map = i915_vma_pin_iomap(vma); + i915_vma_unpin(vma); + if (IS_ERR(map)) + return PTR_ERR(map); + + map[offset / sizeof(*map)] = v; + i915_vma_unpin_iomap(vma); + + return 0; +} + +static int gtt_get(struct drm_i915_gem_object *obj, + unsigned long offset, + u32 *v) +{ + struct i915_vma *vma; + typeof(v) map; + int err; + + err = i915_gem_object_set_to_gtt_domain(obj, false); +
[Intel-gfx] [PATCH 28/46] drm/i915: Sanity check all registers for matching fw domains
Add a late selftest that walks over all forcewake registers (those below 0x4) and uses the mmio debug register to check to see if any are unclaimed. This is possible if we fail to wake the appropriate powerwells for the register. Signed-off-by: Chris Wilson Reviewed-by: Matthew Auld --- drivers/gpu/drm/i915/selftests/intel_uncore.c | 53 +++ 1 file changed, 53 insertions(+) diff --git a/drivers/gpu/drm/i915/selftests/intel_uncore.c b/drivers/gpu/drm/i915/selftests/intel_uncore.c index c563962eaad7..2fb8122944b2 100644 --- a/drivers/gpu/drm/i915/selftests/intel_uncore.c +++ b/drivers/gpu/drm/i915/selftests/intel_uncore.c @@ -107,6 +107,55 @@ int intel_uncore_mock_selftests(void) return 0; } +static int intel_uncore_check_forcewake_domains(struct drm_i915_private *dev_priv) +{ +#define FW_RANGE 0x4 + unsigned long *valid; + u32 offset; + int err; + + if (!HAS_FPGA_DBG_UNCLAIMED(dev_priv) && + !IS_VALLEYVIEW(dev_priv) && + !IS_CHERRYVIEW(dev_priv)) + return 0; + + valid = kzalloc(BITS_TO_LONGS(FW_RANGE) * sizeof(*valid), + GFP_TEMPORARY); + if (!valid) + return -ENOMEM; + + intel_uncore_forcewake_get(dev_priv, FORCEWAKE_ALL); + + check_for_unclaimed_mmio(dev_priv); + for (offset = 0; offset < FW_RANGE; offset += 4) { + i915_reg_t reg = { offset }; + + (void)I915_READ_FW(reg); + if (!check_for_unclaimed_mmio(dev_priv)) + set_bit(offset, valid); + } + + intel_uncore_forcewake_put(dev_priv, FORCEWAKE_ALL); + + err = 0; + for_each_set_bit(offset, valid, FW_RANGE) { + i915_reg_t reg = { offset }; + + intel_uncore_forcewake_reset(dev_priv, false); + check_for_unclaimed_mmio(dev_priv); + + (void)I915_READ(reg); + if (check_for_unclaimed_mmio(dev_priv)) { + pr_err("Unclaimed mmio read to register 0x%04x\n", + offset); + err = -EINVAL; + } + } + + kfree(valid); + return err; +} + int intel_uncore_live_selftests(struct drm_i915_private *i915) { int err; @@ -118,5 +167,9 @@ int intel_uncore_live_selftests(struct drm_i915_private *i915) if (err) return err; + err = intel_uncore_check_forcewake_domains(i915); + if (err) + return err; + return 0; } -- 2.11.0 ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/intel-gfx
[Intel-gfx] [PATCH 33/46] drm/i915: Exercise filling the top/bottom portions of the global GTT
Same test as previously for the per-process GTT instead applied to the global GTT. Signed-off-by: Chris Wilson Reviewed-by: Joonas Lahtinen --- drivers/gpu/drm/i915/selftests/i915_gem_gtt.c | 61 ++- 1 file changed, 60 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/selftests/i915_gem_gtt.c b/drivers/gpu/drm/i915/selftests/i915_gem_gtt.c index 4cd55fc0820a..e1121d157d76 100644 --- a/drivers/gpu/drm/i915/selftests/i915_gem_gtt.c +++ b/drivers/gpu/drm/i915/selftests/i915_gem_gtt.c @@ -22,6 +22,7 @@ * */ +#include #include #include "../i915_selftest.h" @@ -189,7 +190,8 @@ static void close_object_list(struct list_head *objects, struct i915_vma *vma; vma = i915_vma_instance(obj, vm, NULL); - if (!IS_ERR(vma)) + /* Only ppgtt vma may be closed before the object is freed */ + if (!IS_ERR(vma) && !i915_vma_is_ggtt(vma)) i915_vma_close(vma); list_del(&obj->batch_pool_link); @@ -448,12 +450,69 @@ static int igt_ppgtt_fill(void *arg) return exercise_ppgtt(arg, fill_hole); } +static int sort_holes(void *priv, struct list_head *A, struct list_head *B) +{ + struct drm_mm_node *a = list_entry(A, typeof(*a), hole_stack); + struct drm_mm_node *b = list_entry(B, typeof(*b), hole_stack); + + if (a->start < b->start) + return -1; + else + return 1; +} + +static int exercise_ggtt(struct drm_i915_private *i915, +int (*func)(struct drm_i915_private *i915, +struct i915_address_space *vm, +u64 hole_start, u64 hole_end, +unsigned long end_time)) +{ + struct i915_ggtt *ggtt = &i915->ggtt; + u64 hole_start, hole_end, last = 0; + struct drm_mm_node *node; + IGT_TIMEOUT(end_time); + int err; + + mutex_lock(&i915->drm.struct_mutex); +restart: + list_sort(NULL, &ggtt->base.mm.hole_stack, sort_holes); + drm_mm_for_each_hole(node, &ggtt->base.mm, hole_start, hole_end) { + if (hole_start < last) + continue; + + if (ggtt->base.mm.color_adjust) + ggtt->base.mm.color_adjust(node, 0, + &hole_start, &hole_end); + if (hole_start >= hole_end) + continue; + + err = func(i915, &ggtt->base, hole_start, hole_end, end_time); + if (err) + break; + + /* As we have manipulated the drm_mm, the list may be corrupt */ + last = hole_end; + goto restart; + } + mutex_unlock(&i915->drm.struct_mutex); + + return err; +} + +static int igt_ggtt_fill(void *arg) +{ + return exercise_ggtt(arg, fill_hole); +} + int i915_gem_gtt_live_selftests(struct drm_i915_private *i915) { static const struct i915_subtest tests[] = { SUBTEST(igt_ppgtt_alloc), SUBTEST(igt_ppgtt_fill), + SUBTEST(igt_ggtt_fill), }; + GEM_BUG_ON(offset_in_page(i915->ggtt.base.total)); + return i915_subtests(tests, i915); } -- 2.11.0 ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/intel-gfx
[Intel-gfx] [PATCH 31/46] drm/i915: Add initial selftests for i915_gem_gtt
Simple starting point for adding selftests for i915_gem_gtt, first try creating a ppGTT and filling it. Signed-off-by: Chris Wilson Reviewed-by: Matthew Auld --- drivers/gpu/drm/i915/i915_gem_gtt.c| 1 + drivers/gpu/drm/i915/selftests/i915_gem_gtt.c | 97 ++ .../gpu/drm/i915/selftests/i915_live_selftests.h | 1 + 3 files changed, 99 insertions(+) create mode 100644 drivers/gpu/drm/i915/selftests/i915_gem_gtt.c diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c index afdb2859be05..ec360ab939b8 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.c +++ b/drivers/gpu/drm/i915/i915_gem_gtt.c @@ -3754,4 +3754,5 @@ int i915_gem_gtt_insert(struct i915_address_space *vm, #if IS_ENABLED(CONFIG_DRM_I915_SELFTEST) #include "selftests/mock_gtt.c" +#include "selftests/i915_gem_gtt.c" #endif diff --git a/drivers/gpu/drm/i915/selftests/i915_gem_gtt.c b/drivers/gpu/drm/i915/selftests/i915_gem_gtt.c new file mode 100644 index ..5c09dc920cb8 --- /dev/null +++ b/drivers/gpu/drm/i915/selftests/i915_gem_gtt.c @@ -0,0 +1,97 @@ +/* + * Copyright © 2016 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + * + */ + +#include "../i915_selftest.h" + +static int igt_ppgtt_alloc(void *arg) +{ + struct drm_i915_private *dev_priv = arg; + struct i915_hw_ppgtt *ppgtt; + u64 size, last; + int err; + + /* Allocate a ppggt and try to fill the entire range */ + + if (!USES_PPGTT(dev_priv)) + return 0; + + ppgtt = kzalloc(sizeof(*ppgtt), GFP_KERNEL); + if (!ppgtt) + return -ENOMEM; + + err = __hw_ppgtt_init(ppgtt, dev_priv); + if (err) + goto err_ppgtt; + + if (!ppgtt->base.allocate_va_range) + goto err_ppgtt_cleanup; + + /* Check we can allocate the entire range */ + for (size = 4096; +size <= ppgtt->base.total; +size <<= 2) { + err = ppgtt->base.allocate_va_range(&ppgtt->base, 0, size); + if (err) { + if (err == -ENOMEM) { + pr_info("[1] Ran out of memory for va_range [0 + %llx] [bit %d]\n", + size, ilog2(size)); + err = 0; /* virtual space too large! */ + } + goto err_ppgtt_cleanup; + } + + ppgtt->base.clear_range(&ppgtt->base, 0, size); + } + + /* Check we can incrementally allocate the entire range */ + for (last = 0, size = 4096; +size <= ppgtt->base.total; +last = size, size <<= 2) { + err = ppgtt->base.allocate_va_range(&ppgtt->base, + last, size - last); + if (err) { + if (err == -ENOMEM) { + pr_info("[2] Ran out of memory for va_range [%llx + %llx] [bit %d]\n", + last, size - last, ilog2(size)); + err = 0; /* virtual space too large! */ + } + goto err_ppgtt_cleanup; + } + } + +err_ppgtt_cleanup: + ppgtt->base.cleanup(&ppgtt->base); +err_ppgtt: + kfree(ppgtt); + return err; +} + +int i915_gem_gtt_live_selftests(struct drm_i915_private *i915) +{ + static const struct i915_subtest tests[] = { + SUBTEST(igt_ppgtt_alloc), + }; + + return i915_subtests(tests, i915); +} diff --git a/drivers/gpu/drm/i915/selftests/i915_live_selftests.h b/drivers/gpu/drm/i915/selftests/i915_live_selftests.h index 1d26ca1f8bc8..16d6dde29fca 100644 --- a/drivers/gpu/drm/i915/selftests/i915_live_selftests.h +++ b/drivers/gpu/drm/i915/selftests/i915_live_selftests.h @@
[Intel-gfx] [PATCH 36/46] drm/i915: Test creation of VMA
Simple test to exercise creation and lookup of VMA within an object. Signed-off-by: Chris Wilson Reviewed-by: Joonas Lahtinen --- drivers/gpu/drm/i915/i915_vma.c| 3 + .../gpu/drm/i915/selftests/i915_mock_selftests.h | 1 + drivers/gpu/drm/i915/selftests/i915_vma.c | 224 + 3 files changed, 228 insertions(+) create mode 100644 drivers/gpu/drm/i915/selftests/i915_vma.c diff --git a/drivers/gpu/drm/i915/i915_vma.c b/drivers/gpu/drm/i915/i915_vma.c index 155906e84812..5c32d12b2d8d 100644 --- a/drivers/gpu/drm/i915/i915_vma.c +++ b/drivers/gpu/drm/i915/i915_vma.c @@ -687,3 +687,6 @@ int i915_vma_unbind(struct i915_vma *vma) return 0; } +#if IS_ENABLED(CONFIG_DRM_I915_SELFTEST) +#include "selftests/i915_vma.c" +#endif diff --git a/drivers/gpu/drm/i915/selftests/i915_mock_selftests.h b/drivers/gpu/drm/i915/selftests/i915_mock_selftests.h index 955a4d6ccdaf..b450eab7e6e1 100644 --- a/drivers/gpu/drm/i915/selftests/i915_mock_selftests.h +++ b/drivers/gpu/drm/i915/selftests/i915_mock_selftests.h @@ -15,3 +15,4 @@ selftest(breadcrumbs, intel_breadcrumbs_mock_selftests) selftest(requests, i915_gem_request_mock_selftests) selftest(objects, i915_gem_object_mock_selftests) selftest(dmabuf, i915_gem_dmabuf_mock_selftests) +selftest(vma, i915_vma_mock_selftests) diff --git a/drivers/gpu/drm/i915/selftests/i915_vma.c b/drivers/gpu/drm/i915/selftests/i915_vma.c new file mode 100644 index ..e60f3a962f56 --- /dev/null +++ b/drivers/gpu/drm/i915/selftests/i915_vma.c @@ -0,0 +1,224 @@ +/* + * Copyright © 2016 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + * + */ + +#include + +#include "../i915_selftest.h" + +#include "mock_gem_device.h" +#include "mock_context.h" + +static bool assert_vma(struct i915_vma *vma, + struct drm_i915_gem_object *obj, + struct i915_gem_context *ctx) +{ + bool ok = true; + + if (vma->vm != &ctx->ppgtt->base) { + pr_err("VMA created with wrong VM\n"); + ok = false; + } + + if (vma->size != obj->base.size) { + pr_err("VMA created with wrong size, found %llu, expected %zu\n", + vma->size, obj->base.size); + ok = false; + } + + if (vma->ggtt_view.type != I915_GGTT_VIEW_NORMAL) { + pr_err("VMA created with wrong type [%d]\n", + vma->ggtt_view.type); + ok = false; + } + + return ok; +} + +static struct i915_vma * +checked_vma_instance(struct drm_i915_gem_object *obj, +struct i915_address_space *vm, +struct i915_ggtt_view *view) +{ + struct i915_vma *vma; + bool ok = true; + + vma = i915_vma_instance(obj, vm, view); + if (IS_ERR(vma)) + return vma; + + /* Manual checks, will be reinforced by i915_vma_compare! */ + if (vma->vm != vm) { + pr_err("VMA's vm [%p] does not match request [%p]\n", + vma->vm, vm); + ok = false; + } + + if (i915_is_ggtt(vm) != i915_vma_is_ggtt(vma)) { + pr_err("VMA ggtt status [%d] does not match parent [%d]\n", + i915_vma_is_ggtt(vma), i915_is_ggtt(vm)); + ok = false; + } + + if (i915_vma_compare(vma, vm, view)) { + pr_err("i915_vma_compare failed with create parmaters!\n"); + return ERR_PTR(-EINVAL); + } + + if (i915_vma_compare(vma, vma->vm, +i915_vma_is_ggtt(vma) ? &vma->ggtt_view : NULL)) { + pr_err("i915_vma_compare failed with itself\n"); + return ERR_PTR(-EINVAL); + } + + if (!ok) { + pr_err("i915_vma_compare failed to detect the difference!\n"); + retur
[Intel-gfx] [PATCH 39/46] drm/i915: Test creation of partial VMA
Mock testing to ensure we can create and lookup partial VMA. v2: Named phases Signed-off-by: Chris Wilson Reviewed-by: Joonas Lahtinen --- drivers/gpu/drm/i915/selftests/i915_vma.c | 192 ++ 1 file changed, 192 insertions(+) diff --git a/drivers/gpu/drm/i915/selftests/i915_vma.c b/drivers/gpu/drm/i915/selftests/i915_vma.c index 4a737a670199..bb42b6191c7a 100644 --- a/drivers/gpu/drm/i915/selftests/i915_vma.c +++ b/drivers/gpu/drm/i915/selftests/i915_vma.c @@ -530,12 +530,204 @@ static int igt_vma_rotate(void *arg) return err; } +static bool assert_partial(struct drm_i915_gem_object *obj, + struct i915_vma *vma, + unsigned long offset, + unsigned long size) +{ + struct sgt_iter sgt; + dma_addr_t dma; + + for_each_sgt_dma(dma, sgt, vma->pages) { + dma_addr_t src; + + if (!size) { + pr_err("Partial scattergather list too long\n"); + return false; + } + + src = i915_gem_object_get_dma_address(obj, offset); + if (src != dma) { + pr_err("DMA mismatch for partial page offset %lu\n", + offset); + return false; + } + + offset++; + size--; + } + + return true; +} + +static bool assert_pin(struct i915_vma *vma, + struct i915_ggtt_view *view, + u64 size, + const char *name) +{ + bool ok = true; + + if (vma->size != size) { + pr_err("(%s) VMA is wrong size, expected %llu, found %llu\n", + name, size, vma->size); + ok = false; + } + + if (vma->node.size < vma->size) { + pr_err("(%s) VMA binding too small, expected %llu, found %llu\n", + name, vma->size, vma->node.size); + ok = false; + } + + if (view && view->type != I915_GGTT_VIEW_NORMAL) { + if (memcmp(&vma->ggtt_view, view, sizeof(*view))) { + pr_err("(%s) VMA mismatch upon creation!\n", + name); + ok = false; + } + + if (vma->pages == vma->obj->mm.pages) { + pr_err("(%s) VMA using original object pages!\n", + name); + ok = false; + } + } else { + if (vma->ggtt_view.type != I915_GGTT_VIEW_NORMAL) { + pr_err("Not the normal ggtt view! Found %d\n", + vma->ggtt_view.type); + ok = false; + } + + if (vma->pages != vma->obj->mm.pages) { + pr_err("VMA not using object pages!\n"); + ok = false; + } + } + + return ok; +} + +static int igt_vma_partial(void *arg) +{ + struct drm_i915_private *i915 = arg; + struct i915_address_space *vm = &i915->ggtt.base; + const unsigned int npages = 1021; /* prime! */ + struct drm_i915_gem_object *obj; + const struct phase { + const char *name; + } phases[] = { + { "create" }, + { "lookup" }, + { }, + }, *p; + unsigned int sz, offset; + struct i915_vma *vma; + int err = -ENOMEM; + + /* Create lots of different VMA for the object and check that +* we are returned the same VMA when we later request the same range. +*/ + + obj = i915_gem_object_create_internal(i915, npages*PAGE_SIZE); + if (IS_ERR(obj)) + goto out; + + for (p = phases; p->name; p++) { /* exercise both create/lookup */ + unsigned int count, nvma; + + nvma = 0; + for_each_prime_number_from(sz, 1, npages) { + for_each_prime_number_from(offset, 0, npages - sz) { + struct i915_ggtt_view view; + + view.type = I915_GGTT_VIEW_PARTIAL; + view.partial.offset = offset; + view.partial.size = sz; + + if (sz == npages) + view.type = I915_GGTT_VIEW_NORMAL; + + vma = checked_vma_instance(obj, vm, &view); + if (IS_ERR(vma)) { + err = PTR_ERR(vma); + goto out_object; + } + + err = i915_vma_pin(vma, 0, 0, PIN_GLOBAL); + if (err) + goto out_object; + +
[Intel-gfx] [PATCH 34/46] drm/i915: Fill different pages of the GTT
Exercise filling different pages of the GTT v2: Walk all holes until we timeout Signed-off-by: Chris Wilson Reviewed-by: Joonas Lahtinen --- drivers/gpu/drm/i915/selftests/i915_gem_gtt.c | 89 +++ 1 file changed, 89 insertions(+) diff --git a/drivers/gpu/drm/i915/selftests/i915_gem_gtt.c b/drivers/gpu/drm/i915/selftests/i915_gem_gtt.c index e1121d157d76..7d695cdcd20a 100644 --- a/drivers/gpu/drm/i915/selftests/i915_gem_gtt.c +++ b/drivers/gpu/drm/i915/selftests/i915_gem_gtt.c @@ -408,6 +408,83 @@ static int fill_hole(struct drm_i915_private *i915, #undef FLAGS } +static int walk_hole(struct drm_i915_private *i915, +struct i915_address_space *vm, +u64 hole_start, u64 hole_end, +unsigned long end_time) +{ + const u64 hole_size = hole_end - hole_start; + const unsigned long max_pages = + min_t(u64, ULONG_MAX - 1, hole_size >> PAGE_SHIFT); + u64 size; + + /* Try binding a single VMA in different positions within the hole */ + + for_each_prime_number_from(size, 1, max_pages) { + struct drm_i915_gem_object *obj; + struct i915_vma *vma; + u64 addr; + int err = 0; + + obj = fake_dma_object(i915, size << PAGE_SHIFT); + if (IS_ERR(obj)) + break; + + vma = i915_vma_instance(obj, vm, NULL); + if (IS_ERR(vma)) { + err = PTR_ERR(vma); + goto err; + } + + for (addr = hole_start; +addr + obj->base.size < hole_end; +addr += obj->base.size) { + err = i915_vma_pin(vma, 0, 0, + addr | PIN_OFFSET_FIXED | PIN_USER); + if (err) { + pr_err("%s bind failed at %llx + %llx [hole %llx- %llx] with err=%d\n", + __func__, addr, vma->size, + hole_start, hole_end, err); + goto err; + } + i915_vma_unpin(vma); + + if (!drm_mm_node_allocated(&vma->node) || + i915_vma_misplaced(vma, 0, 0, addr | PIN_OFFSET_FIXED)) { + pr_err("%s incorrect at %llx + %llx\n", + __func__, addr, vma->size); + err = -EINVAL; + goto err; + } + + err = i915_vma_unbind(vma); + if (err) { + pr_err("%s unbind failed at %llx + %llx with err=%d\n", + __func__, addr, vma->size, err); + goto err; + } + + GEM_BUG_ON(drm_mm_node_allocated(&vma->node)); + + if (igt_timeout(end_time, + "%s timed out at %llx\n", + __func__, addr)) { + err = -EINTR; + goto err; + } + } + +err: + if (!i915_vma_is_ggtt(vma)) + i915_vma_close(vma); + i915_gem_object_put(obj); + if (err) + return err; + } + + return 0; +} + static int exercise_ppgtt(struct drm_i915_private *dev_priv, int (*func)(struct drm_i915_private *i915, struct i915_address_space *vm, @@ -450,6 +527,11 @@ static int igt_ppgtt_fill(void *arg) return exercise_ppgtt(arg, fill_hole); } +static int igt_ppgtt_walk(void *arg) +{ + return exercise_ppgtt(arg, walk_hole); +} + static int sort_holes(void *priv, struct list_head *A, struct list_head *B) { struct drm_mm_node *a = list_entry(A, typeof(*a), hole_stack); @@ -504,11 +586,18 @@ static int igt_ggtt_fill(void *arg) return exercise_ggtt(arg, fill_hole); } +static int igt_ggtt_walk(void *arg) +{ + return exercise_ggtt(arg, walk_hole); +} + int i915_gem_gtt_live_selftests(struct drm_i915_private *i915) { static const struct i915_subtest tests[] = { SUBTEST(igt_ppgtt_alloc), + SUBTEST(igt_ppgtt_walk), SUBTEST(igt_ppgtt_fill), + SUBTEST(igt_ggtt_walk), SUBTEST(igt_ggtt_fill), }; -- 2.11.0 ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/intel-gfx
[Intel-gfx] [PATCH 40/46] drm/i915: Live testing for context execution
Check we can create and execution within a context. v2: Write one set of dwords through each context/engine to exercise more contexts within the same time period. Signed-off-by: Chris Wilson --- drivers/gpu/drm/i915/i915_gem_context.c| 1 + drivers/gpu/drm/i915/selftests/i915_gem_context.c | 400 + .../gpu/drm/i915/selftests/i915_live_selftests.h | 1 + 3 files changed, 402 insertions(+) create mode 100644 drivers/gpu/drm/i915/selftests/i915_gem_context.c diff --git a/drivers/gpu/drm/i915/i915_gem_context.c b/drivers/gpu/drm/i915/i915_gem_context.c index e6208e361356..baec4bbdffa6 100644 --- a/drivers/gpu/drm/i915/i915_gem_context.c +++ b/drivers/gpu/drm/i915/i915_gem_context.c @@ -1191,4 +1191,5 @@ int i915_gem_context_reset_stats_ioctl(struct drm_device *dev, #if IS_ENABLED(CONFIG_DRM_I915_SELFTEST) #include "selftests/mock_context.c" +#include "selftests/i915_gem_context.c" #endif diff --git a/drivers/gpu/drm/i915/selftests/i915_gem_context.c b/drivers/gpu/drm/i915/selftests/i915_gem_context.c new file mode 100644 index ..0e6ad1b3d3aa --- /dev/null +++ b/drivers/gpu/drm/i915/selftests/i915_gem_context.c @@ -0,0 +1,400 @@ +/* + * Copyright © 2017 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + * + */ + +#include "../i915_selftest.h" + +#include "mock_drm.h" +#include "huge_gem_object.h" + +#define DW_PER_PAGE (PAGE_SIZE / sizeof(u32)) + +static struct i915_vma * +gpu_fill_dw(struct i915_vma *vma, u64 offset, unsigned long count, u32 value) +{ + struct drm_i915_gem_object *obj; + const int gen = INTEL_GEN(vma->vm->i915); + unsigned long n; + u32 *cmd; + int err; + + n = (4*count + 1)*sizeof(u32); + obj = i915_gem_object_create_internal(vma->vm->i915, + round_up(n, PAGE_SIZE)); + if (IS_ERR(obj)) + return ERR_CAST(obj); + + cmd = i915_gem_object_pin_map(obj, I915_MAP_WB); + if (IS_ERR(cmd)) { + err = PTR_ERR(cmd); + goto err; + } + + GEM_BUG_ON(offset + (count - 1) * PAGE_SIZE > vma->node.size); + offset += vma->node.start; + + for (n = 0; n < count; n++) { + if (gen >= 8) { + *cmd++ = MI_STORE_DWORD_IMM_GEN4; + *cmd++ = lower_32_bits(offset); + *cmd++ = upper_32_bits(offset); + *cmd++ = value; + } else if (gen >= 4) { + *cmd++ = MI_STORE_DWORD_IMM_GEN4 | + (gen < 6 ? 1 << 22 : 0); + *cmd++ = 0; + *cmd++ = offset; + *cmd++ = value; + } else { + *cmd++ = MI_STORE_DWORD_IMM | 1 << 22; + *cmd++ = offset; + *cmd++ = value; + } + offset += PAGE_SIZE; + } + *cmd = MI_BATCH_BUFFER_END; + wmb(); + i915_gem_object_unpin_map(obj); + + err = i915_gem_object_set_to_gtt_domain(obj, false); + if (err) + goto err; + + vma = i915_vma_instance(obj, vma->vm, NULL); + if (IS_ERR(vma)) { + err = PTR_ERR(vma); + goto err; + } + + err = i915_vma_pin(vma, 0, 0, PIN_USER); + if (err) + goto err; + + return vma; + +err: + i915_gem_object_put(obj); + return ERR_PTR(err); +} + +static unsigned long real_page_count(struct drm_i915_gem_object *obj) +{ + return huge_gem_object_phys_size(obj) >> PAGE_SHIFT; +} + +static unsigned long fake_page_count(struct drm_i915_gem_object *obj) +{ + return huge_gem_object_dma_size(obj) >> PAGE_SHIFT; +} + +static int gpu_fill(struct drm_i915_gem_object *obj, + struct i915_gem_context *ct
[Intel-gfx] [PATCH 29/46] drm/i915: Add some mock tests for dmabuf interop
Check that we can create both dmabuf and objects from dmabuf. v2: Cleanups, correct include, fix unpin on dead path and prevent explosion on dmabuf init failure Signed-off-by: Chris Wilson Reviewed-by: Matthew Auld --- drivers/gpu/drm/i915/i915_gem_dmabuf.c | 5 + drivers/gpu/drm/i915/selftests/i915_gem_dmabuf.c | 294 + .../gpu/drm/i915/selftests/i915_mock_selftests.h | 1 + drivers/gpu/drm/i915/selftests/mock_dmabuf.c | 176 drivers/gpu/drm/i915/selftests/mock_dmabuf.h | 41 +++ 5 files changed, 517 insertions(+) create mode 100644 drivers/gpu/drm/i915/selftests/i915_gem_dmabuf.c create mode 100644 drivers/gpu/drm/i915/selftests/mock_dmabuf.c create mode 100644 drivers/gpu/drm/i915/selftests/mock_dmabuf.h diff --git a/drivers/gpu/drm/i915/i915_gem_dmabuf.c b/drivers/gpu/drm/i915/i915_gem_dmabuf.c index d037adcda6f2..3e276eee0450 100644 --- a/drivers/gpu/drm/i915/i915_gem_dmabuf.c +++ b/drivers/gpu/drm/i915/i915_gem_dmabuf.c @@ -307,3 +307,8 @@ struct drm_gem_object *i915_gem_prime_import(struct drm_device *dev, return ERR_PTR(ret); } + +#if IS_ENABLED(CONFIG_DRM_I915_SELFTEST) +#include "selftests/mock_dmabuf.c" +#include "selftests/i915_gem_dmabuf.c" +#endif diff --git a/drivers/gpu/drm/i915/selftests/i915_gem_dmabuf.c b/drivers/gpu/drm/i915/selftests/i915_gem_dmabuf.c new file mode 100644 index ..a2393fcf9fa8 --- /dev/null +++ b/drivers/gpu/drm/i915/selftests/i915_gem_dmabuf.c @@ -0,0 +1,294 @@ +/* + * Copyright © 2016 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + * + */ + +#include "../i915_selftest.h" + +#include "mock_gem_device.h" +#include "mock_dmabuf.h" + +static int igt_dmabuf_export(void *arg) +{ + struct drm_i915_private *i915 = arg; + struct drm_i915_gem_object *obj; + struct dma_buf *dmabuf; + + obj = i915_gem_object_create(i915, PAGE_SIZE); + if (IS_ERR(obj)) + return PTR_ERR(obj); + + dmabuf = i915_gem_prime_export(&i915->drm, &obj->base, 0); + i915_gem_object_put(obj); + if (IS_ERR(dmabuf)) { + pr_err("i915_gem_prime_export failed with err=%d\n", + (int)PTR_ERR(dmabuf)); + return PTR_ERR(dmabuf); + } + + dma_buf_put(dmabuf); + return 0; +} + +static int igt_dmabuf_import_self(void *arg) +{ + struct drm_i915_private *i915 = arg; + struct drm_i915_gem_object *obj; + struct drm_gem_object *import; + struct dma_buf *dmabuf; + int err; + + obj = i915_gem_object_create(i915, PAGE_SIZE); + if (IS_ERR(obj)) + return PTR_ERR(obj); + + dmabuf = i915_gem_prime_export(&i915->drm, &obj->base, 0); + if (IS_ERR(dmabuf)) { + pr_err("i915_gem_prime_export failed with err=%d\n", + (int)PTR_ERR(dmabuf)); + err = PTR_ERR(dmabuf); + goto out; + } + + import = i915_gem_prime_import(&i915->drm, dmabuf); + if (IS_ERR(import)) { + pr_err("i915_gem_prime_import failed with err=%d\n", + (int)PTR_ERR(import)); + err = PTR_ERR(import); + goto out_dmabuf; + } + + if (import != &obj->base) { + pr_err("i915_gem_prime_import created a new object!\n"); + err = -EINVAL; + goto out_import; + } + + err = 0; +out_import: + i915_gem_object_put(to_intel_bo(import)); +out_dmabuf: + dma_buf_put(dmabuf); +out: + i915_gem_object_put(obj); + return err; +} + +static int igt_dmabuf_import(void *arg) +{ + struct drm_i915_private *i915 = arg; + struct drm_i915_gem_object *obj; + struct dma_buf *dmabuf; + void *obj_map, *dma_map; + u32 pattern[] = { 0, 0xaa, 0xcc, 0x55, 0xff }; + int err, i; + +
[Intel-gfx] [PATCH 30/46] drm/i915: Add a live dmabuf selftest
Though we have good coverage of our dmabuf interface through the mock tests, we also want to check the heavy module unload paths of the live i915 driver. Signed-off-by: Chris Wilson --- drivers/gpu/drm/i915/selftests/i915_gem_dmabuf.c | 9 + drivers/gpu/drm/i915/selftests/i915_live_selftests.h | 1 + 2 files changed, 10 insertions(+) diff --git a/drivers/gpu/drm/i915/selftests/i915_gem_dmabuf.c b/drivers/gpu/drm/i915/selftests/i915_gem_dmabuf.c index a2393fcf9fa8..817bef74bbcb 100644 --- a/drivers/gpu/drm/i915/selftests/i915_gem_dmabuf.c +++ b/drivers/gpu/drm/i915/selftests/i915_gem_dmabuf.c @@ -292,3 +292,12 @@ int i915_gem_dmabuf_mock_selftests(void) drm_dev_unref(&i915->drm); return err; } + +int i915_gem_dmabuf_live_selftests(struct drm_i915_private *i915) +{ + static const struct i915_subtest tests[] = { + SUBTEST(igt_dmabuf_export), + }; + + return i915_subtests(tests, i915); +} diff --git a/drivers/gpu/drm/i915/selftests/i915_live_selftests.h b/drivers/gpu/drm/i915/selftests/i915_live_selftests.h index c060bf24928e..1d26ca1f8bc8 100644 --- a/drivers/gpu/drm/i915/selftests/i915_live_selftests.h +++ b/drivers/gpu/drm/i915/selftests/i915_live_selftests.h @@ -12,4 +12,5 @@ selftest(sanitycheck, i915_live_sanitycheck) /* keep first (igt selfcheck) */ selftest(uncore, intel_uncore_live_selftests) selftest(requests, i915_gem_request_live_selftests) selftest(object, i915_gem_object_live_selftests) +selftest(dmabuf, i915_gem_dmabuf_live_selftests) selftest(coherency, i915_gem_coherency_live_selftests) -- 2.11.0 ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/intel-gfx
[Intel-gfx] [PATCH 23/46] drm/i915: Test partial mappings
Create partial mappings to cover a large object, investigating tiling (fenced regions) and VMA reuse. Signed-off-by: Chris Wilson Reviewed-by: Matthew Auld --- drivers/gpu/drm/i915/selftests/i915_gem_object.c | 293 +++ 1 file changed, 293 insertions(+) diff --git a/drivers/gpu/drm/i915/selftests/i915_gem_object.c b/drivers/gpu/drm/i915/selftests/i915_gem_object.c index d7330db70063..140bae2c8ad2 100644 --- a/drivers/gpu/drm/i915/selftests/i915_gem_object.c +++ b/drivers/gpu/drm/i915/selftests/i915_gem_object.c @@ -140,6 +140,298 @@ static int igt_gem_huge(void *arg) return err; } +struct tile { + unsigned int width; + unsigned int height; + unsigned int stride; + unsigned int size; + unsigned int tiling; + unsigned int swizzle; +}; + +static u64 swizzle_bit(unsigned int bit, u64 offset) +{ + return (offset & BIT_ULL(bit)) >> (bit - 6); +} + +static u64 tiled_offset(const struct tile *tile, u64 v) +{ + u64 x, y; + + if (tile->tiling == I915_TILING_NONE) + return v; + + y = div64_u64_rem(v, tile->stride, &x); + v = div64_u64_rem(y, tile->height, &y) * tile->stride * tile->height; + + if (tile->tiling == I915_TILING_X) { + v += y * tile->width; + v += div64_u64_rem(x, tile->width, &x) << tile->size; + v += x; + } else { + const unsigned int ytile_span = 16; + const unsigned int ytile_height = 32 * ytile_span; + + v += y * ytile_span; + v += div64_u64_rem(x, ytile_span, &x) * ytile_height; + v += x; + } + + switch (tile->swizzle) { + case I915_BIT_6_SWIZZLE_9: + v ^= swizzle_bit(9, v); + break; + case I915_BIT_6_SWIZZLE_9_10: + v ^= swizzle_bit(9, v) ^ swizzle_bit(10, v); + break; + case I915_BIT_6_SWIZZLE_9_11: + v ^= swizzle_bit(9, v) ^ swizzle_bit(11, v); + break; + case I915_BIT_6_SWIZZLE_9_10_11: + v ^= swizzle_bit(9, v) ^ swizzle_bit(10, v) ^ swizzle_bit(11, v); + break; + } + + return v; +} + +static int check_partial_mapping(struct drm_i915_gem_object *obj, +const struct tile *tile, +unsigned long end_time) +{ + const unsigned int nreal = obj->scratch / PAGE_SIZE; + const unsigned long npages = obj->base.size / PAGE_SIZE; + struct i915_vma *vma; + unsigned long page; + int err; + + if (igt_timeout(end_time, + "%s: timed out before tiling=%d stride=%d\n", + __func__, tile->tiling, tile->stride)) + return -EINTR; + + err = i915_gem_object_set_tiling(obj, tile->tiling, tile->stride); + if (err) + return err; + + GEM_BUG_ON(i915_gem_object_get_tiling(obj) != tile->tiling); + GEM_BUG_ON(i915_gem_object_get_stride(obj) != tile->stride); + + for_each_prime_number_from(page, 1, npages) { + struct i915_ggtt_view view = + compute_partial_view(obj, page, MIN_CHUNK_PAGES); + u32 __iomem *io; + struct page *p; + unsigned int n; + u64 offset; + u32 *cpu; + + GEM_BUG_ON(view.partial.size > nreal); + + err = i915_gem_object_set_to_gtt_domain(obj, true); + if (err) + return err; + + vma = i915_gem_object_ggtt_pin(obj, &view, 0, 0, PIN_MAPPABLE); + if (IS_ERR(vma)) { + pr_err("Failed to pin partial view: offset=%lu\n", + page); + return PTR_ERR(vma); + } + + n = page - view.partial.offset; + GEM_BUG_ON(n >= view.partial.size); + + io = i915_vma_pin_iomap(vma); + i915_vma_unpin(vma); + if (IS_ERR(io)) { + pr_err("Failed to iomap partial view: offset=%lu\n", + page); + return PTR_ERR(io); + } + + err = i915_vma_get_fence(vma); + if (err) { + pr_err("Failed to get fence for partial view: offset=%lu\n", + page); + i915_vma_unpin_iomap(vma); + return err; + } + + iowrite32(page, io + n * PAGE_SIZE/sizeof(*io)); + i915_vma_unpin_iomap(vma); + + offset = tiled_offset(tile, page << PAGE_SHIFT); + if (offset >= obj->base.size) + continue; + + i915_gem_object_flush_gtt_write_domain(obj); + + p = i915_gem_object_get_page(obj, offset >> PAGE_SHIFT); +
[Intel-gfx] [PATCH 35/46] drm/i915: Exercise filling and removing random ranges from the live GTT
Test the low-level i915_address_space interfaces to sanity check the live insertion/removal of address ranges. Signed-off-by: Chris Wilson Reviewed-by: Matthew Auld --- drivers/gpu/drm/i915/selftests/i915_gem_gtt.c | 93 +++ 1 file changed, 93 insertions(+) diff --git a/drivers/gpu/drm/i915/selftests/i915_gem_gtt.c b/drivers/gpu/drm/i915/selftests/i915_gem_gtt.c index 7d695cdcd20a..abde71d857e0 100644 --- a/drivers/gpu/drm/i915/selftests/i915_gem_gtt.c +++ b/drivers/gpu/drm/i915/selftests/i915_gem_gtt.c @@ -26,6 +26,7 @@ #include #include "../i915_selftest.h" +#include "i915_random.h" #include "mock_drm.h" @@ -485,6 +486,86 @@ static int walk_hole(struct drm_i915_private *i915, return 0; } +static int drunk_hole(struct drm_i915_private *i915, + struct i915_address_space *vm, + u64 hole_start, u64 hole_end, + unsigned long end_time) +{ + I915_RND_STATE(seed_prng); + unsigned int size; + + /* Keep creating larger objects until one cannot fit into the hole */ + for (size = 12; (hole_end - hole_start) >> size; size++) { + I915_RND_SUBSTATE(prng, seed_prng); + struct drm_i915_gem_object *obj; + unsigned int *order, count, n; + u64 hole_size; + + hole_size = (hole_end - hole_start) >> size; + if (hole_size > KMALLOC_MAX_SIZE / sizeof(u32)) + hole_size = KMALLOC_MAX_SIZE / sizeof(u32); + count = hole_size; + do { + count >>= 1; + order = i915_random_order(count, &prng); + } while (!order && count); + if (!order) + break; + + /* Ignore allocation failures (i.e. don't report them as +* a test failure) as we are purposefully allocating very +* large objects without checking that we have sufficient +* memory. We expect to hit -ENOMEM. +*/ + + obj = fake_dma_object(i915, BIT_ULL(size)); + if (IS_ERR(obj)) { + kfree(order); + break; + } + + GEM_BUG_ON(obj->base.size != BIT_ULL(size)); + + if (i915_gem_object_pin_pages(obj)) { + i915_gem_object_put(obj); + kfree(order); + break; + } + + for (n = 0; n < count; n++) { + if (vm->allocate_va_range && + vm->allocate_va_range(vm, + order[n] * BIT_ULL(size), + BIT_ULL(size))) + break; + + vm->insert_entries(vm, obj->mm.pages, + order[n] * BIT_ULL(size), + I915_CACHE_NONE, 0); + if (igt_timeout(end_time, + "%s timed out after %d/%d\n", + __func__, n, count)) { + hole_start = hole_end; /* quit */ + break; + } + } + count = n; + + i915_random_reorder(order, count, &prng); + for (n = 0; n < count; n++) + vm->clear_range(vm, + order[n] * BIT_ULL(size), + BIT_ULL(size)); + + i915_gem_object_unpin_pages(obj); + i915_gem_object_put(obj); + + kfree(order); + } + + return 0; +} + static int exercise_ppgtt(struct drm_i915_private *dev_priv, int (*func)(struct drm_i915_private *i915, struct i915_address_space *vm, @@ -532,6 +613,11 @@ static int igt_ppgtt_walk(void *arg) return exercise_ppgtt(arg, walk_hole); } +static int igt_ppgtt_drunk(void *arg) +{ + return exercise_ppgtt(arg, drunk_hole); +} + static int sort_holes(void *priv, struct list_head *A, struct list_head *B) { struct drm_mm_node *a = list_entry(A, typeof(*a), hole_stack); @@ -591,12 +677,19 @@ static int igt_ggtt_walk(void *arg) return exercise_ggtt(arg, walk_hole); } +static int igt_ggtt_drunk(void *arg) +{ + return exercise_ggtt(arg, drunk_hole); +} + int i915_gem_gtt_live_selftests(struct drm_i915_private *i915) { static const struct i915_subtest tests[] = { SUBTEST(igt_ppgtt_alloc), + SUBTEST(igt_ppgtt_drunk), SUBTEST(igt_ppgtt_walk), SUBTEST(igt_ppgtt_fill), + SUBTEST(igt_ggtt_drunk), SUBTEST(igt_ggtt_walk),
[Intel-gfx] [PATCH 38/46] drm/i915: Verify page layout for rotated VMA
Exercise creating rotated VMA and checking the page order within. v2: Be more creative in rotated params Signed-off-by: Chris Wilson --- drivers/gpu/drm/i915/selftests/i915_vma.c | 179 ++ 1 file changed, 179 insertions(+) diff --git a/drivers/gpu/drm/i915/selftests/i915_vma.c b/drivers/gpu/drm/i915/selftests/i915_vma.c index 095d8348f5f0..4a737a670199 100644 --- a/drivers/gpu/drm/i915/selftests/i915_vma.c +++ b/drivers/gpu/drm/i915/selftests/i915_vma.c @@ -352,11 +352,190 @@ static int igt_vma_pin1(void *arg) return err; } +static unsigned long rotated_index(const struct intel_rotation_info *r, + unsigned int n, + unsigned int x, + unsigned int y) +{ + return (r->plane[n].stride * (r->plane[n].height - y - 1) + + r->plane[n].offset + x); +} + +static struct scatterlist * +assert_rotated(struct drm_i915_gem_object *obj, + const struct intel_rotation_info *r, unsigned int n, + struct scatterlist *sg) +{ + unsigned int x, y; + + for (x = 0; x < r->plane[n].width; x++) { + for (y = 0; y < r->plane[n].height; y++) { + unsigned long src_idx; + dma_addr_t src; + + if (!sg) { + pr_err("Invalid sg table: too short at plane %d, (%d, %d)!\n", + n, x, y); + return ERR_PTR(-EINVAL); + } + + src_idx = rotated_index(r, n, x, y); + src = i915_gem_object_get_dma_address(obj, src_idx); + + if (sg_dma_len(sg) != PAGE_SIZE) { + pr_err("Invalid sg.length, found %d, expected %lu for rotated page (%d, %d) [src index %lu]\n", + sg_dma_len(sg), PAGE_SIZE, + x, y, src_idx); + return ERR_PTR(-EINVAL); + } + + if (sg_dma_address(sg) != src) { + pr_err("Invalid address for rotated page (%d, %d) [src index %lu]\n", + x, y, src_idx); + return ERR_PTR(-EINVAL); + } + + sg = sg_next(sg); + } + } + + return sg; +} + +static unsigned int rotated_size(const struct intel_rotation_plane_info *a, +const struct intel_rotation_plane_info *b) +{ + return a->width * a->height + b->width * b->height; +} + +static int igt_vma_rotate(void *arg) +{ + struct drm_i915_private *i915 = arg; + struct i915_address_space *vm = &i915->ggtt.base; + struct drm_i915_gem_object *obj; + const struct intel_rotation_plane_info planes[] = { + { .width = 1, .height = 1, .stride = 1 }, + { .width = 2, .height = 2, .stride = 2 }, + { .width = 4, .height = 4, .stride = 4 }, + { .width = 8, .height = 8, .stride = 8 }, + + { .width = 3, .height = 5, .stride = 3 }, + { .width = 3, .height = 5, .stride = 4 }, + { .width = 3, .height = 5, .stride = 5 }, + + { .width = 5, .height = 3, .stride = 5 }, + { .width = 5, .height = 3, .stride = 7 }, + { .width = 5, .height = 3, .stride = 9 }, + + { .width = 4, .height = 6, .stride = 6 }, + { .width = 6, .height = 4, .stride = 6 }, + { } + }, *a, *b; + const unsigned int max_pages = 64; + int err = -ENOMEM; + + /* Create VMA for many different combinations of planes and check +* that the page layout within the rotated VMA match our expectations. +*/ + + obj = i915_gem_object_create_internal(i915, max_pages * PAGE_SIZE); + if (IS_ERR(obj)) + goto out; + + for (a = planes; a->width; a++) { + for (b = planes + ARRAY_SIZE(planes); b-- != planes; ) { + struct i915_ggtt_view view; + unsigned int n, max_offset; + + max_offset = max(a->stride * a->height, +b->stride * b->height); + GEM_BUG_ON(max_offset > max_pages); + max_offset = max_pages - max_offset; + + view.type = I915_GGTT_VIEW_ROTATED; + view.rotated.plane[0] = *a; + view.rotated.plane[1] = *b; + + for_each_prime_number_from(view.rotated.plane[0].offset, 0, max_offset) { + for_each_prime_number_from(view.rotated.plane[1].offset, 0, max_offset) { + struct scat
[Intel-gfx] [PATCH 37/46] drm/i915: Exercise i915_vma_pin/i915_vma_insert
High-level testing of the struct drm_mm by verifying our handling of weird requests to i915_vma_pin. Signed-off-by: Chris Wilson Reviewed-by: Joonas Lahtinen --- drivers/gpu/drm/i915/i915_vma.c | 4 +- drivers/gpu/drm/i915/i915_vma.h | 4 +- drivers/gpu/drm/i915/selftests/i915_vma.c | 151 ++ 3 files changed, 155 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_vma.c b/drivers/gpu/drm/i915/i915_vma.c index 5c32d12b2d8d..341c3f82ec1f 100644 --- a/drivers/gpu/drm/i915/i915_vma.c +++ b/drivers/gpu/drm/i915/i915_vma.c @@ -324,8 +324,8 @@ void i915_vma_unpin_and_release(struct i915_vma **p_vma) __i915_gem_object_release_unless_active(obj); } -bool -i915_vma_misplaced(struct i915_vma *vma, u64 size, u64 alignment, u64 flags) +bool i915_vma_misplaced(const struct i915_vma *vma, + u64 size, u64 alignment, u64 flags) { if (!drm_mm_node_allocated(&vma->node)) return false; diff --git a/drivers/gpu/drm/i915/i915_vma.h b/drivers/gpu/drm/i915/i915_vma.h index e39d922cfb6f..2e03f81dddbe 100644 --- a/drivers/gpu/drm/i915/i915_vma.h +++ b/drivers/gpu/drm/i915/i915_vma.h @@ -228,8 +228,8 @@ i915_vma_compare(struct i915_vma *vma, int i915_vma_bind(struct i915_vma *vma, enum i915_cache_level cache_level, u32 flags); bool i915_gem_valid_gtt_space(struct i915_vma *vma, unsigned long cache_level); -bool -i915_vma_misplaced(struct i915_vma *vma, u64 size, u64 alignment, u64 flags); +bool i915_vma_misplaced(const struct i915_vma *vma, + u64 size, u64 alignment, u64 flags); void __i915_vma_set_map_and_fenceable(struct i915_vma *vma); int __must_check i915_vma_unbind(struct i915_vma *vma); void i915_vma_close(struct i915_vma *vma); diff --git a/drivers/gpu/drm/i915/selftests/i915_vma.c b/drivers/gpu/drm/i915/selftests/i915_vma.c index e60f3a962f56..095d8348f5f0 100644 --- a/drivers/gpu/drm/i915/selftests/i915_vma.c +++ b/drivers/gpu/drm/i915/selftests/i915_vma.c @@ -202,10 +202,161 @@ static int igt_vma_create(void *arg) return err; } +struct pin_mode { + u64 size; + u64 flags; + bool (*assert)(const struct i915_vma *, + const struct pin_mode *mode, + int result); + const char *string; +}; + +static bool assert_pin_valid(const struct i915_vma *vma, +const struct pin_mode *mode, +int result) +{ + if (result) + return false; + + if (i915_vma_misplaced(vma, mode->size, 0, mode->flags)) + return false; + + return true; +} + +__maybe_unused +static bool assert_pin_e2big(const struct i915_vma *vma, +const struct pin_mode *mode, +int result) +{ + return result == -E2BIG; +} + +__maybe_unused +static bool assert_pin_enospc(const struct i915_vma *vma, + const struct pin_mode *mode, + int result) +{ + return result == -ENOSPC; +} + +__maybe_unused +static bool assert_pin_einval(const struct i915_vma *vma, + const struct pin_mode *mode, + int result) +{ + return result == -EINVAL; +} + +static int igt_vma_pin1(void *arg) +{ + struct drm_i915_private *i915 = arg; + const struct pin_mode modes[] = { +#define VALID(sz, fl) { .size = (sz), .flags = (fl), .assert = assert_pin_valid, .string = #sz ", " #fl ", (valid) " } +#define __INVALID(sz, fl, check, eval) { .size = (sz), .flags = (fl), .assert = (check), .string = #sz ", " #fl ", (invalid " #eval ")" } +#define INVALID(sz, fl) __INVALID(sz, fl, assert_pin_einval, EINVAL) +#define TOOBIG(sz, fl) __INVALID(sz, fl, assert_pin_e2big, E2BIG) +#define NOSPACE(sz, fl) __INVALID(sz, fl, assert_pin_enospc, ENOSPC) + VALID(0, PIN_GLOBAL), + VALID(0, PIN_GLOBAL | PIN_MAPPABLE), + + VALID(0, PIN_GLOBAL | PIN_OFFSET_BIAS | 4096), + VALID(0, PIN_GLOBAL | PIN_OFFSET_BIAS | 8192), + VALID(0, PIN_GLOBAL | PIN_OFFSET_BIAS | (i915->ggtt.mappable_end - 4096)), + VALID(0, PIN_GLOBAL | PIN_MAPPABLE | PIN_OFFSET_BIAS | (i915->ggtt.mappable_end - 4096)), + VALID(0, PIN_GLOBAL | PIN_OFFSET_BIAS | (i915->ggtt.base.total - 4096)), + + VALID(0, PIN_GLOBAL | PIN_MAPPABLE | PIN_OFFSET_FIXED | (i915->ggtt.mappable_end - 4096)), + INVALID(0, PIN_GLOBAL | PIN_MAPPABLE | PIN_OFFSET_FIXED | i915->ggtt.mappable_end), + VALID(0, PIN_GLOBAL | PIN_OFFSET_FIXED | (i915->ggtt.base.total - 4096)), + INVALID(0, PIN_GLOBAL | PIN_OFFSET_FIXED | i915->ggtt.base.total), + INVALID(0, PIN_GLOBAL | PIN_OFFSET_FIXED | round_down(U64_MAX, PAGE_SIZE)), + + VALID(4096, PIN_GLOBAL), + VALID(8192, P
[Intel-gfx] [PATCH 43/46] drm/i915: Add mock exercise for i915_gem_gtt_insert
i915_gem_gtt_insert should allocate from the available free space in the GTT, evicting as necessary to create space. Signed-off-by: Chris Wilson Reviewed-by: Joonas Lahtinen --- drivers/gpu/drm/i915/selftests/i915_gem_gtt.c | 208 ++ 1 file changed, 208 insertions(+) diff --git a/drivers/gpu/drm/i915/selftests/i915_gem_gtt.c b/drivers/gpu/drm/i915/selftests/i915_gem_gtt.c index f4b627eb63f6..c1c7a8837ffd 100644 --- a/drivers/gpu/drm/i915/selftests/i915_gem_gtt.c +++ b/drivers/gpu/drm/i915/selftests/i915_gem_gtt.c @@ -857,10 +857,218 @@ static int igt_gtt_reserve(void *arg) return err; } +static int igt_gtt_insert(void *arg) +{ + struct drm_i915_private *i915 = arg; + struct drm_i915_gem_object *obj, *on; + struct drm_mm_node tmp = {}; + const struct invalid_insert { + u64 size; + u64 alignment; + u64 start, end; + } invalid_insert[] = { + { + i915->ggtt.base.total + I915_GTT_PAGE_SIZE, 0, + 0, i915->ggtt.base.total, + }, + { + 2*I915_GTT_PAGE_SIZE, 0, + 0, I915_GTT_PAGE_SIZE, + }, + { + -(u64)I915_GTT_PAGE_SIZE, 0, + 0, 4*I915_GTT_PAGE_SIZE, + }, + { + -(u64)2*I915_GTT_PAGE_SIZE, 2*I915_GTT_PAGE_SIZE, + 0, 4*I915_GTT_PAGE_SIZE, + }, + { + I915_GTT_PAGE_SIZE, I915_GTT_MIN_ALIGNMENT << 1, + I915_GTT_MIN_ALIGNMENT, I915_GTT_MIN_ALIGNMENT << 1, + }, + {} + }, *ii; + LIST_HEAD(objects); + u64 total; + int err; + + /* i915_gem_gtt_insert() tries to allocate some free space in the GTT +* to the node, evicting if required. +*/ + + /* Check a couple of obviously invalid requests */ + for (ii = invalid_insert; ii->size; ii++) { + err = i915_gem_gtt_insert(&i915->ggtt.base, &tmp, + ii->size, ii->alignment, + I915_COLOR_UNEVICTABLE, + ii->start, ii->end, + 0); + if (err != -ENOSPC) { + pr_err("Invalid i915_gem_gtt_insert(.size=%llx, .alignment=%llx, .start=%llx, .end=%llx) succeeded (err=%d)\n", + ii->size, ii->alignment, ii->start, ii->end, + err); + return -EINVAL; + } + } + + /* Start by filling the GGTT */ + for (total = 0; +total + I915_GTT_PAGE_SIZE <= i915->ggtt.base.total; +total += I915_GTT_PAGE_SIZE) { + struct i915_vma *vma; + + obj = i915_gem_object_create_internal(i915, I915_GTT_PAGE_SIZE); + if (IS_ERR(obj)) { + err = PTR_ERR(obj); + goto out; + } + + err = i915_gem_object_pin_pages(obj); + if (err) { + i915_gem_object_put(obj); + goto out; + } + + list_add(&obj->batch_pool_link, &objects); + + vma = i915_vma_instance(obj, &i915->ggtt.base, NULL); + if (IS_ERR(vma)) { + err = PTR_ERR(vma); + goto out; + } + + err = i915_gem_gtt_insert(&i915->ggtt.base, &vma->node, + obj->base.size, 0, obj->cache_level, + 0, i915->ggtt.base.total, + 0); + if (err == -ENOSPC) { + /* maxed out the GGTT space */ + i915_gem_object_put(obj); + break; + } + if (err) { + pr_err("i915_gem_gtt_insert (pass 1) failed at %llu/%llu with err=%d\n", + total, i915->ggtt.base.total, err); + goto out; + } + track_vma_bind(vma); + __i915_vma_pin(vma); + + GEM_BUG_ON(!drm_mm_node_allocated(&vma->node)); + } + + list_for_each_entry(obj, &objects, batch_pool_link) { + struct i915_vma *vma; + + vma = i915_vma_instance(obj, &i915->ggtt.base, NULL); + if (IS_ERR(vma)) { + err = PTR_ERR(vma); + goto out; + } + + if (!drm_mm_node_allocated(&vma->node)) { + pr_err("VMA was unexpectedly evicted!\n"); + err = -EINVAL; + goto out; +
[Intel-gfx] [PATCH 41/46] drm/i915: Initial selftests for exercising eviction
Very simple tests to just ask eviction to find some free space in a full GTT and one with some available space. Signed-off-by: Chris Wilson Reviewed-by: Matthew Auld --- drivers/gpu/drm/i915/i915_gem_evict.c | 4 + drivers/gpu/drm/i915/selftests/i915_gem_evict.c| 260 + .../gpu/drm/i915/selftests/i915_mock_selftests.h | 1 + 3 files changed, 265 insertions(+) create mode 100644 drivers/gpu/drm/i915/selftests/i915_gem_evict.c diff --git a/drivers/gpu/drm/i915/i915_gem_evict.c b/drivers/gpu/drm/i915/i915_gem_evict.c index c181b1bb3d2c..609a8fcb48ca 100644 --- a/drivers/gpu/drm/i915/i915_gem_evict.c +++ b/drivers/gpu/drm/i915/i915_gem_evict.c @@ -387,3 +387,7 @@ int i915_gem_evict_vm(struct i915_address_space *vm, bool do_idle) return 0; } + +#if IS_ENABLED(CONFIG_DRM_I915_SELFTEST) +#include "selftests/i915_gem_evict.c" +#endif diff --git a/drivers/gpu/drm/i915/selftests/i915_gem_evict.c b/drivers/gpu/drm/i915/selftests/i915_gem_evict.c new file mode 100644 index ..97af353db218 --- /dev/null +++ b/drivers/gpu/drm/i915/selftests/i915_gem_evict.c @@ -0,0 +1,260 @@ +/* + * Copyright © 2016 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + * + */ + +#include "../i915_selftest.h" + +#include "mock_gem_device.h" + +static int populate_ggtt(struct drm_i915_private *i915) +{ + struct drm_i915_gem_object *obj; + u64 size; + + for (size = 0; +size + I915_GTT_PAGE_SIZE <= i915->ggtt.base.total; +size += I915_GTT_PAGE_SIZE) { + struct i915_vma *vma; + + obj = i915_gem_object_create_internal(i915, I915_GTT_PAGE_SIZE); + if (IS_ERR(obj)) + return PTR_ERR(obj); + + vma = i915_gem_object_ggtt_pin(obj, NULL, 0, 0, 0); + if (IS_ERR(vma)) + return PTR_ERR(vma); + } + + if (!list_empty(&i915->mm.unbound_list)) { + size = 0; + list_for_each_entry(obj, &i915->mm.unbound_list, global_link) + size++; + + pr_err("Found %lld objects unbound!\n", size); + return -EINVAL; + } + + if (list_empty(&i915->ggtt.base.inactive_list)) { + pr_err("No objects on the GGTT inactive list!\n"); + return -EINVAL; + } + + return 0; +} + +static void unpin_ggtt(struct drm_i915_private *i915) +{ + struct i915_vma *vma; + + list_for_each_entry(vma, &i915->ggtt.base.inactive_list, vm_link) + i915_vma_unpin(vma); +} + +static void cleanup_objects(struct drm_i915_private *i915) +{ + struct drm_i915_gem_object *obj, *on; + + list_for_each_entry_safe(obj, on, &i915->mm.unbound_list, global_link) + i915_gem_object_put(obj); + + list_for_each_entry_safe(obj, on, &i915->mm.bound_list, global_link) + i915_gem_object_put(obj); + + mutex_unlock(&i915->drm.struct_mutex); + + i915_gem_drain_freed_objects(i915); + + mutex_lock(&i915->drm.struct_mutex); +} + +static int igt_evict_something(void *arg) +{ + struct drm_i915_private *i915 = arg; + struct i915_ggtt *ggtt = &i915->ggtt; + int err; + + /* Fill the GGTT with pinned objects and try to evict one. */ + + err = populate_ggtt(i915); + if (err) + goto cleanup; + + /* Everything is pinned, nothing should happen */ + err = i915_gem_evict_something(&ggtt->base, + I915_GTT_PAGE_SIZE, 0, 0, + 0, U64_MAX, + 0); + if (err != -ENOSPC) { + pr_err("i915_gem_evict_something failed on a full GGTT with err=%d\n", + err); + goto cleanup; + } + + unpin_ggtt(i915)
Re: [Intel-gfx] [PATCH 05/46] drm/i915: Provide a hook for selftests
On Thu, Feb 02, 2017 at 09:08:24AM +, Chris Wilson wrote: > Some pieces of code are independent of hardware but are very tricky to > exercise through the normal userspace ABI or via debugfs hooks. Being > able to create mock unit tests and execute them through CI is vital. > Start by adding a central point where we can execute unit tests and > a parameter to enable them. This is disabled by default as the > expectation is that these tests will occasionally explode. > > To facilitate integration with igt, any parameter beginning with > i915.igt__ is interpreted as a subtest executable independently via > igt/drv_selftest. > > Two classes of selftests are recognised: mock unit tests and integration > tests. Mock unit tests are run as soon as the module is loaded, before > the device is probed. At that point there is no driver instantiated and > all hw interactions must be "mocked". This is very useful for writing > universal tests to exercise code not typically run on a broad range of > architectures. Alternatively, you can hook into the live selftests and > run when the device has been instantiated - hw interactions are real. > > v2: Add a macro for compiling conditional code for mock objects inside > real objects. > v3: Differentiate between mock unit tests and late integration test. > v4: List the tests in natural order, use igt to sort after modparam. > v5: s/late/live/ > v6: s/unsigned long/unsigned int/ > v7: Use igt_ prefixes for long helpers. v8: Deobfuscate macros overriding functions, stop using -I$(src) -- Chris Wilson, Intel Open Source Technology Centre ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/intel-gfx
[Intel-gfx] [PATCH 46/46] drm/i915: Add initial selftests for hang detection and resets
Check that we can reset the GPU and continue executing from the next request. Signed-off-by: Chris Wilson --- drivers/gpu/drm/i915/i915_drv.h| 4 +- drivers/gpu/drm/i915/intel_hangcheck.c | 4 + .../gpu/drm/i915/selftests/i915_live_selftests.h | 1 + drivers/gpu/drm/i915/selftests/intel_hangcheck.c | 531 + 4 files changed, 538 insertions(+), 2 deletions(-) create mode 100644 drivers/gpu/drm/i915/selftests/intel_hangcheck.c diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 4a7e4b10c0a9..f82c59768f65 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -3356,8 +3356,8 @@ int __must_check i915_gem_init(struct drm_i915_private *dev_priv); int __must_check i915_gem_init_hw(struct drm_i915_private *dev_priv); void i915_gem_init_swizzling(struct drm_i915_private *dev_priv); void i915_gem_cleanup_engines(struct drm_i915_private *dev_priv); -int __must_check i915_gem_wait_for_idle(struct drm_i915_private *dev_priv, - unsigned int flags); +int i915_gem_wait_for_idle(struct drm_i915_private *dev_priv, + unsigned int flags); int __must_check i915_gem_suspend(struct drm_i915_private *dev_priv); void i915_gem_resume(struct drm_i915_private *dev_priv); int i915_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf); diff --git a/drivers/gpu/drm/i915/intel_hangcheck.c b/drivers/gpu/drm/i915/intel_hangcheck.c index f05971f5586f..dce742243ba6 100644 --- a/drivers/gpu/drm/i915/intel_hangcheck.c +++ b/drivers/gpu/drm/i915/intel_hangcheck.c @@ -480,3 +480,7 @@ void intel_hangcheck_init(struct drm_i915_private *i915) INIT_DELAYED_WORK(&i915->gpu_error.hangcheck_work, i915_hangcheck_elapsed); } + +#if IS_ENABLED(CONFIG_DRM_I915_SELFTEST) +#include "selftests/intel_hangcheck.c" +#endif diff --git a/drivers/gpu/drm/i915/selftests/i915_live_selftests.h b/drivers/gpu/drm/i915/selftests/i915_live_selftests.h index 15fb4e0dd503..d0d4f4bcd837 100644 --- a/drivers/gpu/drm/i915/selftests/i915_live_selftests.h +++ b/drivers/gpu/drm/i915/selftests/i915_live_selftests.h @@ -16,3 +16,4 @@ selftest(dmabuf, i915_gem_dmabuf_live_selftests) selftest(coherency, i915_gem_coherency_live_selftests) selftest(gtt, i915_gem_gtt_live_selftests) selftest(context, i915_gem_context_live_selftests) +selftest(hangcheck, intel_hangcheck_live_selftests) diff --git a/drivers/gpu/drm/i915/selftests/intel_hangcheck.c b/drivers/gpu/drm/i915/selftests/intel_hangcheck.c new file mode 100644 index ..2131d8707dfd --- /dev/null +++ b/drivers/gpu/drm/i915/selftests/intel_hangcheck.c @@ -0,0 +1,531 @@ +/* + * Copyright © 2016 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + * + */ + +#include "../i915_selftest.h" + +struct hang { + struct drm_i915_private *i915; + struct drm_i915_gem_object *hws; + struct drm_i915_gem_object *obj; + u32 *seqno; + u32 *batch; +}; + +static int hang_init(struct hang *h, struct drm_i915_private *i915) +{ + void *vaddr; + int err; + + memset(h, 0, sizeof(*h)); + h->i915 = i915; + + h->hws = i915_gem_object_create_internal(i915, PAGE_SIZE); + if (IS_ERR(h->hws)) + return PTR_ERR(h->hws); + + h->obj = i915_gem_object_create_internal(i915, PAGE_SIZE); + if (IS_ERR(h->obj)) { + err = PTR_ERR(h->obj); + goto err_hws; + } + + i915_gem_object_set_cache_level(h->hws, I915_CACHE_LLC); + vaddr = i915_gem_object_pin_map(h->hws, I915_MAP_WB); + if (IS_ERR(vaddr)) { + err = PTR_ERR(vaddr); + goto err_obj; + } + h->seqno = memset(vaddr, 0xff, PAGE_SIZE); + + vaddr = i915_gem_object_pin_map(h->obj, +
[Intel-gfx] [PATCH 45/46] drm/i915: Exercise manipulate of single pages in the GGTT
Move a single page of an object around within the GGTT and check coherency of writes and reads. Signed-off-by: Chris Wilson --- drivers/gpu/drm/i915/selftests/i915_gem_gtt.c | 91 +++ 1 file changed, 91 insertions(+) diff --git a/drivers/gpu/drm/i915/selftests/i915_gem_gtt.c b/drivers/gpu/drm/i915/selftests/i915_gem_gtt.c index 7ec6fb2208a6..27e380a3bae5 100644 --- a/drivers/gpu/drm/i915/selftests/i915_gem_gtt.c +++ b/drivers/gpu/drm/i915/selftests/i915_gem_gtt.c @@ -684,6 +684,96 @@ static int igt_ggtt_drunk(void *arg) return exercise_ggtt(arg, drunk_hole); } +static int igt_ggtt_page(void *arg) +{ + const unsigned int count = PAGE_SIZE/sizeof(u32); + I915_RND_STATE(prng); + struct drm_i915_private *i915 = arg; + struct i915_ggtt *ggtt = &i915->ggtt; + struct drm_i915_gem_object *obj; + struct drm_mm_node tmp; + unsigned int *order, n; + int err; + + mutex_lock(&i915->drm.struct_mutex); + + obj = i915_gem_object_create_internal(i915, PAGE_SIZE); + if (IS_ERR(obj)) { + err = PTR_ERR(obj); + goto out_unlock; + } + + err = i915_gem_object_pin_pages(obj); + if (err) + goto out_free; + + memset(&tmp, 0, sizeof(tmp)); + err = drm_mm_insert_node_in_range(&ggtt->base.mm, &tmp, + 1024 * PAGE_SIZE, 0, + I915_COLOR_UNEVICTABLE, + 0, ggtt->mappable_end, + DRM_MM_INSERT_LOW); + if (err) + goto out_unpin; + + order = i915_random_order(count, &prng); + if (!order) { + err = -ENOMEM; + goto out_remove; + } + + for (n = 0; n < count; n++) { + u64 offset = tmp.start + order[n] * PAGE_SIZE; + u32 __iomem *vaddr; + + ggtt->base.insert_page(&ggtt->base, + i915_gem_object_get_dma_address(obj, 0), + offset, I915_CACHE_NONE, 0); + + vaddr = io_mapping_map_atomic_wc(&ggtt->mappable, offset); + iowrite32(n, vaddr + n); + io_mapping_unmap_atomic(vaddr); + + wmb(); + ggtt->base.clear_range(&ggtt->base, offset, PAGE_SIZE); + } + + i915_random_reorder(order, count, &prng); + for (n = 0; n < count; n++) { + u64 offset = tmp.start + order[n] * PAGE_SIZE; + u32 __iomem *vaddr; + u32 val; + + ggtt->base.insert_page(&ggtt->base, + i915_gem_object_get_dma_address(obj, 0), + offset, I915_CACHE_NONE, 0); + + vaddr = io_mapping_map_atomic_wc(&ggtt->mappable, offset); + val = ioread32(vaddr + n); + io_mapping_unmap_atomic(vaddr); + + ggtt->base.clear_range(&ggtt->base, offset, PAGE_SIZE); + + if (val != n) { + pr_err("insert page failed: found %d, expected %d\n", + val, n); + err = -EINVAL; + break; + } + } + + kfree(order); +out_remove: + drm_mm_remove_node(&tmp); +out_unpin: + i915_gem_object_unpin_pages(obj); +out_free: + i915_gem_object_put(obj); +out_unlock: + mutex_unlock(&i915->drm.struct_mutex); + return err; +} + static void track_vma_bind(struct i915_vma *vma) { struct drm_i915_gem_object *obj = vma->obj; @@ -1138,6 +1228,7 @@ int i915_gem_gtt_live_selftests(struct drm_i915_private *i915) SUBTEST(igt_ggtt_drunk), SUBTEST(igt_ggtt_walk), SUBTEST(igt_ggtt_fill), + SUBTEST(igt_ggtt_page), }; GEM_BUG_ON(offset_in_page(i915->ggtt.base.total)); -- 2.11.0 ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/intel-gfx
[Intel-gfx] [PATCH 42/46] drm/i915: Add mock exercise for i915_gem_gtt_reserve
i915_gem_gtt_reserve should put the node exactly as requested in the GTT, evicting as required. Signed-off-by: Chris Wilson Reviewed-by: Joonas Lahtinen --- drivers/gpu/drm/i915/selftests/i915_gem_gtt.c | 195 + .../gpu/drm/i915/selftests/i915_mock_selftests.h | 1 + 2 files changed, 196 insertions(+) diff --git a/drivers/gpu/drm/i915/selftests/i915_gem_gtt.c b/drivers/gpu/drm/i915/selftests/i915_gem_gtt.c index abde71d857e0..f4b627eb63f6 100644 --- a/drivers/gpu/drm/i915/selftests/i915_gem_gtt.c +++ b/drivers/gpu/drm/i915/selftests/i915_gem_gtt.c @@ -29,6 +29,7 @@ #include "i915_random.h" #include "mock_drm.h" +#include "mock_gem_device.h" static void fake_free_pages(struct drm_i915_gem_object *obj, struct sg_table *pages) @@ -682,6 +683,200 @@ static int igt_ggtt_drunk(void *arg) return exercise_ggtt(arg, drunk_hole); } +static void track_vma_bind(struct i915_vma *vma) +{ + struct drm_i915_gem_object *obj = vma->obj; + + obj->bind_count++; /* track for eviction later */ + __i915_gem_object_pin_pages(obj); + + vma->pages = obj->mm.pages; + list_move_tail(&vma->vm_link, &vma->vm->inactive_list); +} + +static int igt_gtt_reserve(void *arg) +{ + struct drm_i915_private *i915 = arg; + struct drm_i915_gem_object *obj, *on; + LIST_HEAD(objects); + u64 total; + int err; + + /* i915_gem_gtt_reserve() tries to reserve the precise range +* for the node, and evicts if it has to. So our test checks that +* it can give us the requsted space and prevent overlaps. +*/ + + /* Start by filling the GGTT */ + for (total = 0; +total + 2*I915_GTT_PAGE_SIZE <= i915->ggtt.base.total; +total += 2*I915_GTT_PAGE_SIZE) { + struct i915_vma *vma; + + obj = i915_gem_object_create_internal(i915, 2*PAGE_SIZE); + if (IS_ERR(obj)) { + err = PTR_ERR(obj); + goto out; + } + + err = i915_gem_object_pin_pages(obj); + if (err) { + i915_gem_object_put(obj); + goto out; + } + + list_add(&obj->batch_pool_link, &objects); + + vma = i915_vma_instance(obj, &i915->ggtt.base, NULL); + if (IS_ERR(vma)) { + err = PTR_ERR(vma); + goto out; + } + + err = i915_gem_gtt_reserve(&i915->ggtt.base, &vma->node, + obj->base.size, + total, + obj->cache_level, + 0); + if (err) { + pr_err("i915_gem_gtt_reserve (pass 1) failed at %llu/%llu with err=%d\n", + total, i915->ggtt.base.total, err); + goto out; + } + track_vma_bind(vma); + + GEM_BUG_ON(!drm_mm_node_allocated(&vma->node)); + if (vma->node.start != total || + vma->node.size != 2*I915_GTT_PAGE_SIZE) { + pr_err("i915_gem_gtt_reserve (pass 1) placement failed, found (%llx + %llx), expected (%llx + %lx)\n", + vma->node.start, vma->node.size, + total, 2*I915_GTT_PAGE_SIZE); + err = -EINVAL; + goto out; + } + } + + /* Now we start forcing evictions */ + for (total = I915_GTT_PAGE_SIZE; +total + 2*I915_GTT_PAGE_SIZE <= i915->ggtt.base.total; +total += 2*I915_GTT_PAGE_SIZE) { + struct i915_vma *vma; + + obj = i915_gem_object_create_internal(i915, 2*PAGE_SIZE); + if (IS_ERR(obj)) { + err = PTR_ERR(obj); + goto out; + } + + err = i915_gem_object_pin_pages(obj); + if (err) { + i915_gem_object_put(obj); + goto out; + } + + list_add(&obj->batch_pool_link, &objects); + + vma = i915_vma_instance(obj, &i915->ggtt.base, NULL); + if (IS_ERR(vma)) { + err = PTR_ERR(vma); + goto out; + } + + err = i915_gem_gtt_reserve(&i915->ggtt.base, &vma->node, + obj->base.size, + total, + obj->cache_level, + 0); + if (err) { + pr_err("i915_gem_gtt_reserve (pass 2) failed at %llu/%llu with err=%d\n", + total, i915->ggtt.base.tot
[Intel-gfx] [PATCH 44/46] drm/i915: Add mock tests for GTT/VMA handling
Use the live tests against the mock ppgtt for quick testing on all platforms of the VMA layer. Signed-off-by: Chris Wilson --- drivers/gpu/drm/i915/selftests/i915_gem_gtt.c | 43 +++ 1 file changed, 43 insertions(+) diff --git a/drivers/gpu/drm/i915/selftests/i915_gem_gtt.c b/drivers/gpu/drm/i915/selftests/i915_gem_gtt.c index c1c7a8837ffd..7ec6fb2208a6 100644 --- a/drivers/gpu/drm/i915/selftests/i915_gem_gtt.c +++ b/drivers/gpu/drm/i915/selftests/i915_gem_gtt.c @@ -28,6 +28,7 @@ #include "../i915_selftest.h" #include "i915_random.h" +#include "mock_context.h" #include "mock_drm.h" #include "mock_gem_device.h" @@ -694,6 +695,45 @@ static void track_vma_bind(struct i915_vma *vma) list_move_tail(&vma->vm_link, &vma->vm->inactive_list); } +static int exercise_mock(struct drm_i915_private *i915, +int (*func)(struct drm_i915_private *i915, +struct i915_address_space *vm, +u64 hole_start, u64 hole_end, +unsigned long end_time)) +{ + struct i915_gem_context *ctx; + struct i915_hw_ppgtt *ppgtt; + IGT_TIMEOUT(end_time); + int err; + + ctx = mock_context(i915, "mock"); + if (!ctx) + return -ENOMEM; + + ppgtt = ctx->ppgtt; + GEM_BUG_ON(!ppgtt); + + err = func(i915, &ppgtt->base, 0, ppgtt->base.total, end_time); + + mock_context_close(ctx); + return err; +} + +static int igt_mock_fill(void *arg) +{ + return exercise_mock(arg, fill_hole); +} + +static int igt_mock_walk(void *arg) +{ + return exercise_mock(arg, walk_hole); +} + +static int igt_mock_drunk(void *arg) +{ + return exercise_mock(arg, drunk_hole); +} + static int igt_gtt_reserve(void *arg) { struct drm_i915_private *i915 = arg; @@ -1067,6 +1107,9 @@ static int igt_gtt_insert(void *arg) int i915_gem_gtt_mock_selftests(void) { static const struct i915_subtest tests[] = { + SUBTEST(igt_mock_drunk), + SUBTEST(igt_mock_walk), + SUBTEST(igt_mock_fill), SUBTEST(igt_gtt_reserve), SUBTEST(igt_gtt_insert), }; -- 2.11.0 ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/intel-gfx
[Intel-gfx] [PATCH igt] intel-ci: Add all driver selftests to BAT
These are meant to be fast and sensitive to new (and old) bugs... Signed-off-by: Chris Wilson Cc: Petri Latvala --- tests/intel-ci/fast-feedback.testlist | 19 +++ 1 file changed, 19 insertions(+) diff --git a/tests/intel-ci/fast-feedback.testlist b/tests/intel-ci/fast-feedback.testlist index 828bd3ff..a0c3f848 100644 --- a/tests/intel-ci/fast-feedback.testlist +++ b/tests/intel-ci/fast-feedback.testlist @@ -249,4 +249,23 @@ igt@drv_module_reload@basic-reload igt@drv_module_reload@basic-no-display igt@drv_module_reload@basic-reload-inject igt@drv_module_reload@basic-reload-final +igt@drv_selftest@mock_sanitycheck +igt@drv_selftest@mock_scatterlist +igt@drv_selftest@mock_uncore +igt@drv_selftest@mock_breadcrumbs +igt@drv_selftest@mock_requests +igt@drv_selftest@mock_objects +igt@drv_selftest@mock_dmabuf +igt@drv_selftest@mock_vma +igt@drv_selftest@mock_evict +igt@drv_selftest@mock_gtt +igt@drv_selftest@live_sanitycheck +igt@drv_selftest@live_uncore +igt@drv_selftest@live_requests +igt@drv_selftest@live_object +igt@drv_selftest@live_dmabuf +igt@drv_selftest@live_coherency +igt@drv_selftest@live_gtt +igt@drv_selftest@live_context +igt@drv_selftest@live_hangcheck igt@gvt_basic@invalid-placeholder-test -- 2.11.0 ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/intel-gfx
Re: [Intel-gfx] [PATCH 01/46] drm: Provide a driver hook for drm_dev_release()
Hi Chris, Thank you for the patch. On Thursday 02 Feb 2017 09:08:20 Chris Wilson wrote: > Some state is coupled into the device lifetime outside of the > load/unload timeframe and requires teardown during final unreference > from drm_dev_release(). For example, dmabufs hold both a device and > module reference and may live longer than expected (i.e. the current > pattern of the driver tearing down its state and then releasing a > reference to the drm device) and yet touch driver private state when > destroyed. > > v2: Export drm_dev_fini() and move the responsibility for finalizing the > drm_device and freeing it to the release callback. (If no callback is > provided, the core will call drm_dev_fini() and kfree(dev) as before.) > v3: Remember to add drm_dev_fini() to drm_drv.h > v4: Tidy language for kerneldoc > v5: Cross reference from drm_dev_init() to note that driver->release() > allows for arbitrary embedding. > > Signed-off-by: Chris Wilson > Cc: Laurent Pinchart > Cc: Daniel Vetter > --- > drivers/gpu/drm/drm_drv.c | 65 ++-- > include/drm/drm_drv.h | 13 ++ > 2 files changed, 58 insertions(+), 20 deletions(-) > > diff --git a/drivers/gpu/drm/drm_drv.c b/drivers/gpu/drm/drm_drv.c > index a8ce3179c07c..fe611d601916 100644 > --- a/drivers/gpu/drm/drm_drv.c > +++ b/drivers/gpu/drm/drm_drv.c > @@ -465,7 +465,10 @@ static void drm_fs_inode_free(struct inode *inode) > * that do embed &struct drm_device it must be placed first in the overall > * structure, and the overall structure must be allocated using kmalloc(): > The * drm core's release function unconditionally calls kfree() on the @dev > pointer - * when the final reference is released. > + * when the final reference is released. To override this behaviour, and so > + * allow embedding of the drm_device inside the driver's device struct at > an + * arbitrary offset, you must supply a driver->release() callback and > control + * the finalization explicitly. > * > * RETURNS: > * 0 on success, or error code on failure. > @@ -553,6 +556,41 @@ int drm_dev_init(struct drm_device *dev, > EXPORT_SYMBOL(drm_dev_init); > > /** > + * drm_dev_fini - Finalize a dead DRM device > + * @dev: DRM device > + * > + * Finalize a dead DRM device. This is the converse to drm_dev_init() and > + * frees up all state allocated by it. All driver state should be finalized > + * first. Note that this function does not free the @dev, that is left to > the + * caller. > + * > + * The ref-count of @dev must be zero, and drm_dev_fini() should only be > called + * from a drm_driver->release() callback. > + */ > +void drm_dev_fini(struct drm_device *dev) > +{ > + drm_vblank_cleanup(dev); > + > + if (drm_core_check_feature(dev, DRIVER_GEM)) > + drm_gem_destroy(dev); > + > + drm_legacy_ctxbitmap_cleanup(dev); > + drm_ht_remove(&dev->map_hash); > + drm_fs_inode_free(dev->anon_inode); > + > + drm_minor_free(dev, DRM_MINOR_PRIMARY); > + drm_minor_free(dev, DRM_MINOR_RENDER); > + drm_minor_free(dev, DRM_MINOR_CONTROL); > + > + mutex_destroy(&dev->master_mutex); > + mutex_destroy(&dev->ctxlist_mutex); > + mutex_destroy(&dev->filelist_mutex); > + mutex_destroy(&dev->struct_mutex); > + kfree(dev->unique); > +} > +EXPORT_SYMBOL(drm_dev_fini); > + > +/** > * drm_dev_alloc - Allocate new DRM device > * @driver: DRM driver to allocate device for > * @parent: Parent device object > @@ -598,25 +636,12 @@ static void drm_dev_release(struct kref *ref) > { > struct drm_device *dev = container_of(ref, struct drm_device, ref); > > - drm_vblank_cleanup(dev); > - > - if (drm_core_check_feature(dev, DRIVER_GEM)) > - drm_gem_destroy(dev); > - > - drm_legacy_ctxbitmap_cleanup(dev); > - drm_ht_remove(&dev->map_hash); > - drm_fs_inode_free(dev->anon_inode); > - > - drm_minor_free(dev, DRM_MINOR_PRIMARY); > - drm_minor_free(dev, DRM_MINOR_RENDER); > - drm_minor_free(dev, DRM_MINOR_CONTROL); > - > - mutex_destroy(&dev->master_mutex); > - mutex_destroy(&dev->ctxlist_mutex); > - mutex_destroy(&dev->filelist_mutex); > - mutex_destroy(&dev->struct_mutex); > - kfree(dev->unique); > - kfree(dev); > + if (dev->driver->release) { > + dev->driver->release(dev); > + } else { > + drm_dev_fini(dev); > + kfree(dev); > + } > } > > /** > diff --git a/include/drm/drm_drv.h b/include/drm/drm_drv.h > index 732e85652d1e..d0d2fa83d06c 100644 > --- a/include/drm/drm_drv.h > +++ b/include/drm/drm_drv.h > @@ -102,6 +102,17 @@ struct drm_driver { >* >*/ > void (*unload) (struct drm_device *); > + > + /** > + * @release: > + * > + * Optional callback for destroying device state after the final Nitpicking, I'd talk about "device data" or "device memory" instead of "device state", as the latter could be confused with the device a
[Intel-gfx] ✓ Fi.CI.BAT: success for series starting with [v2,1/5] drm/i915: Generate i915_params {} using a macro
== Series Details == Series: series starting with [v2,1/5] drm/i915: Generate i915_params {} using a macro URL : https://patchwork.freedesktop.org/series/18973/ State : success == Summary == Series 18973v1 Series without cover letter https://patchwork.freedesktop.org/api/1.0/series/18973/revisions/1/mbox/ fi-bdw-5557u total:247 pass:233 dwarn:0 dfail:0 fail:0 skip:14 fi-bsw-n3050 total:247 pass:208 dwarn:0 dfail:0 fail:0 skip:39 fi-bxt-j4205 total:247 pass:225 dwarn:0 dfail:0 fail:0 skip:22 fi-bxt-t5700 total:78 pass:65 dwarn:0 dfail:0 fail:0 skip:12 fi-byt-j1900 total:247 pass:220 dwarn:0 dfail:0 fail:0 skip:27 fi-byt-n2820 total:247 pass:216 dwarn:0 dfail:0 fail:0 skip:31 fi-hsw-4770 total:247 pass:228 dwarn:0 dfail:0 fail:0 skip:19 fi-hsw-4770r total:247 pass:228 dwarn:0 dfail:0 fail:0 skip:19 fi-ivb-3520m total:247 pass:226 dwarn:0 dfail:0 fail:0 skip:21 fi-ivb-3770 total:247 pass:226 dwarn:0 dfail:0 fail:0 skip:21 fi-kbl-7500u total:247 pass:224 dwarn:0 dfail:0 fail:2 skip:21 fi-skl-6260u total:247 pass:234 dwarn:0 dfail:0 fail:0 skip:13 fi-skl-6700hqtotal:247 pass:227 dwarn:0 dfail:0 fail:0 skip:20 fi-skl-6700k total:247 pass:222 dwarn:4 dfail:0 fail:0 skip:21 fi-skl-6770hqtotal:247 pass:234 dwarn:0 dfail:0 fail:0 skip:13 fi-snb-2520m total:247 pass:216 dwarn:0 dfail:0 fail:0 skip:31 fi-snb-2600 total:247 pass:215 dwarn:0 dfail:0 fail:0 skip:32 a0cc425b0034c42eb3830f7dd612ac2a132a874c drm-tip: 2017y-02m-01d-17h-17m-34s UTC integration manifest 4f19807 drm/i915: Show the current i915_params in debugfs/i915_capabilites 8819d2b drm/i915: Capture module parameters for the GPU error state 9afd98b drm/i915: Use bool i915_param.alpha_support 9e99506 drm/i915: Convert i915_params to use shortnames for its types e80e338 drm/i915: Generate i915_params {} using a macro == Logs == For more details see: https://intel-gfx-ci.01.org/CI/Patchwork_3671/ ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/intel-gfx
[Intel-gfx] [PATCH v6] drm: Provide a driver hook for drm_dev_release()
Some state is coupled into the device lifetime outside of the load/unload timeframe and requires teardown during final unreference from drm_dev_release(). For example, dmabufs hold both a device and module reference and may live longer than expected (i.e. the current pattern of the driver tearing down its state and then releasing a reference to the drm device) and yet touch driver private state when destroyed. v2: Export drm_dev_fini() and move the responsibility for finalizing the drm_device and freeing it to the release callback. (If no callback is provided, the core will call drm_dev_fini() and kfree(dev) as before.) v3: Remember to add drm_dev_fini() to drm_drv.h v4: Tidy language for kerneldoc v5: Cross reference from drm_dev_init() to note that driver->release() allows for arbitrary embedding. v6: Refer to driver data rather than driver state, as state is now becoming associated with the struct drm_atomic_state and friends. Signed-off-by: Chris Wilson Cc: Laurent Pinchart Cc: Daniel Vetter Reviewed-by: Laurent Pinchart --- drivers/gpu/drm/drm_drv.c | 65 --- include/drm/drm_drv.h | 13 ++ 2 files changed, 58 insertions(+), 20 deletions(-) diff --git a/drivers/gpu/drm/drm_drv.c b/drivers/gpu/drm/drm_drv.c index a8ce3179c07c..e122e4d022f8 100644 --- a/drivers/gpu/drm/drm_drv.c +++ b/drivers/gpu/drm/drm_drv.c @@ -465,7 +465,10 @@ static void drm_fs_inode_free(struct inode *inode) * that do embed &struct drm_device it must be placed first in the overall * structure, and the overall structure must be allocated using kmalloc(): The * drm core's release function unconditionally calls kfree() on the @dev pointer - * when the final reference is released. + * when the final reference is released. To override this behaviour, and so + * allow embedding of the drm_device inside the driver's device struct at an + * arbitrary offset, you must supply a driver->release() callback and control + * the finalization explicitly. * * RETURNS: * 0 on success, or error code on failure. @@ -553,6 +556,41 @@ int drm_dev_init(struct drm_device *dev, EXPORT_SYMBOL(drm_dev_init); /** + * drm_dev_fini - Finalize a dead DRM device + * @dev: DRM device + * + * Finalize a dead DRM device. This is the converse to drm_dev_init() and + * frees up all data allocated by it. All driver private data should be + * finalized first. Note that this function does not free the @dev, that is + * left to the caller. + * + * The ref-count of @dev must be zero, and drm_dev_fini() should only be called + * from a drm_driver->release() callback. + */ +void drm_dev_fini(struct drm_device *dev) +{ + drm_vblank_cleanup(dev); + + if (drm_core_check_feature(dev, DRIVER_GEM)) + drm_gem_destroy(dev); + + drm_legacy_ctxbitmap_cleanup(dev); + drm_ht_remove(&dev->map_hash); + drm_fs_inode_free(dev->anon_inode); + + drm_minor_free(dev, DRM_MINOR_PRIMARY); + drm_minor_free(dev, DRM_MINOR_RENDER); + drm_minor_free(dev, DRM_MINOR_CONTROL); + + mutex_destroy(&dev->master_mutex); + mutex_destroy(&dev->ctxlist_mutex); + mutex_destroy(&dev->filelist_mutex); + mutex_destroy(&dev->struct_mutex); + kfree(dev->unique); +} +EXPORT_SYMBOL(drm_dev_fini); + +/** * drm_dev_alloc - Allocate new DRM device * @driver: DRM driver to allocate device for * @parent: Parent device object @@ -598,25 +636,12 @@ static void drm_dev_release(struct kref *ref) { struct drm_device *dev = container_of(ref, struct drm_device, ref); - drm_vblank_cleanup(dev); - - if (drm_core_check_feature(dev, DRIVER_GEM)) - drm_gem_destroy(dev); - - drm_legacy_ctxbitmap_cleanup(dev); - drm_ht_remove(&dev->map_hash); - drm_fs_inode_free(dev->anon_inode); - - drm_minor_free(dev, DRM_MINOR_PRIMARY); - drm_minor_free(dev, DRM_MINOR_RENDER); - drm_minor_free(dev, DRM_MINOR_CONTROL); - - mutex_destroy(&dev->master_mutex); - mutex_destroy(&dev->ctxlist_mutex); - mutex_destroy(&dev->filelist_mutex); - mutex_destroy(&dev->struct_mutex); - kfree(dev->unique); - kfree(dev); + if (dev->driver->release) { + dev->driver->release(dev); + } else { + drm_dev_fini(dev); + kfree(dev); + } } /** diff --git a/include/drm/drm_drv.h b/include/drm/drm_drv.h index 732e85652d1e..5699f42195fe 100644 --- a/include/drm/drm_drv.h +++ b/include/drm/drm_drv.h @@ -102,6 +102,17 @@ struct drm_driver { * */ void (*unload) (struct drm_device *); + + /** +* @release: +* +* Optional callback for destroying device data after the final +* reference is released, i.e. the device is being destroyed. Drivers +* using this callback are responsible for calling drm_dev_fini() +* to finalize the device and then freeing the struct them
Re: [Intel-gfx] [PATCH v2 1/5] drm/i915: Generate i915_params {} using a macro
On Thu, 02 Feb 2017, Chris Wilson wrote: > I want to print the struct from the error state and so would like to use > the existing struct definition as the template ala DEV_INFO* > > v2: Use MEMBER() rather than p(). > > Signed-off-by: Chris Wilson > Reviewed-by: Joonas Lahtinen I've been telling everyone who complains about testing specific firmware blob versions to add a module parameter to specify and override the default filename. AFAICT this series does not make string parameters any harder, but please do double check. I think they expect a static allocation for the string buffer too, so the struct assignment should be fine as well. On the series, Acked-by: Jani Nikula > --- > drivers/gpu/drm/i915/i915_params.h | 81 > -- > 1 file changed, 43 insertions(+), 38 deletions(-) > > diff --git a/drivers/gpu/drm/i915/i915_params.h > b/drivers/gpu/drm/i915/i915_params.h > index 8e433de04679..9a8c60342a82 100644 > --- a/drivers/gpu/drm/i915/i915_params.h > +++ b/drivers/gpu/drm/i915/i915_params.h > @@ -27,46 +27,51 @@ > > #include /* for __read_mostly */ > > +#define I915_PARAMS_FOR_EACH(func) \ > + func(int, modeset); \ > + func(int, panel_ignore_lid); \ > + func(int, semaphores); \ > + func(int, lvds_channel_mode); \ > + func(int, panel_use_ssc); \ > + func(int, vbt_sdvo_panel_type); \ > + func(int, enable_rc6); \ > + func(int, enable_dc); \ > + func(int, enable_fbc); \ > + func(int, enable_ppgtt); \ > + func(int, enable_execlists); \ > + func(int, enable_psr); \ > + func(unsigned int, alpha_support); \ > + func(int, disable_power_well); \ > + func(int, enable_ips); \ > + func(int, invert_brightness); \ > + func(int, enable_guc_loading); \ > + func(int, enable_guc_submission); \ > + func(int, guc_log_level); \ > + func(int, use_mmio_flip); \ > + func(int, mmio_debug); \ > + func(int, edp_vswing); \ > + func(unsigned int, inject_load_failure); \ > + /* leave bools at the end to not create holes */ \ > + func(bool, enable_cmd_parser); \ > + func(bool, enable_hangcheck); \ > + func(bool, fastboot); \ > + func(bool, prefault_disable); \ > + func(bool, load_detect_test); \ > + func(bool, force_reset_modeset_test); \ > + func(bool, reset); \ > + func(bool, error_capture); \ > + func(bool, disable_display); \ > + func(bool, verbose_state_checks); \ > + func(bool, nuclear_pageflip); \ > + func(bool, enable_dp_mst); \ > + func(bool, enable_dpcd_backlight); \ > + func(bool, enable_gvt) > + > +#define MEMBER(T, member) T member > struct i915_params { > - int modeset; > - int panel_ignore_lid; > - int semaphores; > - int lvds_channel_mode; > - int panel_use_ssc; > - int vbt_sdvo_panel_type; > - int enable_rc6; > - int enable_dc; > - int enable_fbc; > - int enable_ppgtt; > - int enable_execlists; > - int enable_psr; > - unsigned int alpha_support; > - int disable_power_well; > - int enable_ips; > - int invert_brightness; > - int enable_guc_loading; > - int enable_guc_submission; > - int guc_log_level; > - int use_mmio_flip; > - int mmio_debug; > - int edp_vswing; > - unsigned int inject_load_failure; > - /* leave bools at the end to not create holes */ > - bool enable_cmd_parser; > - bool enable_hangcheck; > - bool fastboot; > - bool prefault_disable; > - bool load_detect_test; > - bool force_reset_modeset_test; > - bool reset; > - bool error_capture; > - bool disable_display; > - bool verbose_state_checks; > - bool nuclear_pageflip; > - bool enable_dp_mst; > - bool enable_dpcd_backlight; > - bool enable_gvt; > + I915_PARAMS_FOR_EACH(MEMBER); > }; > +#undef MEMBER > > extern struct i915_params i915 __read_mostly; -- Jani Nikula, Intel Open Source Technology Center ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/intel-gfx
Re: [Intel-gfx] [PATCH v6] drm: Provide a driver hook for drm_dev_release()
On Thu, Feb 02, 2017 at 09:36:32AM +, Chris Wilson wrote: > Some state is coupled into the device lifetime outside of the > load/unload timeframe and requires teardown during final unreference > from drm_dev_release(). For example, dmabufs hold both a device and > module reference and may live longer than expected (i.e. the current > pattern of the driver tearing down its state and then releasing a > reference to the drm device) and yet touch driver private state when > destroyed. > > v2: Export drm_dev_fini() and move the responsibility for finalizing the > drm_device and freeing it to the release callback. (If no callback is > provided, the core will call drm_dev_fini() and kfree(dev) as before.) > v3: Remember to add drm_dev_fini() to drm_drv.h > v4: Tidy language for kerneldoc > v5: Cross reference from drm_dev_init() to note that driver->release() > allows for arbitrary embedding. > v6: Refer to driver data rather than driver state, as state is now > becoming associated with the struct drm_atomic_state and friends. > > Signed-off-by: Chris Wilson > Cc: Laurent Pinchart > Cc: Daniel Vetter > Reviewed-by: Laurent Pinchart > --- > drivers/gpu/drm/drm_drv.c | 65 > --- > include/drm/drm_drv.h | 13 ++ > 2 files changed, 58 insertions(+), 20 deletions(-) > > diff --git a/drivers/gpu/drm/drm_drv.c b/drivers/gpu/drm/drm_drv.c > index a8ce3179c07c..e122e4d022f8 100644 > --- a/drivers/gpu/drm/drm_drv.c > +++ b/drivers/gpu/drm/drm_drv.c > @@ -465,7 +465,10 @@ static void drm_fs_inode_free(struct inode *inode) > * that do embed &struct drm_device it must be placed first in the overall > * structure, and the overall structure must be allocated using kmalloc(): > The > * drm core's release function unconditionally calls kfree() on the @dev > pointer > - * when the final reference is released. > + * when the final reference is released. To override this behaviour, and so > + * allow embedding of the drm_device inside the driver's device struct at an > + * arbitrary offset, you must supply a driver->release() callback and control The new official way to reference a struct member is &foo.bar. I've applied this polish to both places and applied your patch, thanks a lot. -Daniel > + * the finalization explicitly. > * > * RETURNS: > * 0 on success, or error code on failure. > @@ -553,6 +556,41 @@ int drm_dev_init(struct drm_device *dev, > EXPORT_SYMBOL(drm_dev_init); > > /** > + * drm_dev_fini - Finalize a dead DRM device > + * @dev: DRM device > + * > + * Finalize a dead DRM device. This is the converse to drm_dev_init() and > + * frees up all data allocated by it. All driver private data should be > + * finalized first. Note that this function does not free the @dev, that is > + * left to the caller. > + * > + * The ref-count of @dev must be zero, and drm_dev_fini() should only be > called > + * from a drm_driver->release() callback. > + */ > +void drm_dev_fini(struct drm_device *dev) > +{ > + drm_vblank_cleanup(dev); > + > + if (drm_core_check_feature(dev, DRIVER_GEM)) > + drm_gem_destroy(dev); > + > + drm_legacy_ctxbitmap_cleanup(dev); > + drm_ht_remove(&dev->map_hash); > + drm_fs_inode_free(dev->anon_inode); > + > + drm_minor_free(dev, DRM_MINOR_PRIMARY); > + drm_minor_free(dev, DRM_MINOR_RENDER); > + drm_minor_free(dev, DRM_MINOR_CONTROL); > + > + mutex_destroy(&dev->master_mutex); > + mutex_destroy(&dev->ctxlist_mutex); > + mutex_destroy(&dev->filelist_mutex); > + mutex_destroy(&dev->struct_mutex); > + kfree(dev->unique); > +} > +EXPORT_SYMBOL(drm_dev_fini); > + > +/** > * drm_dev_alloc - Allocate new DRM device > * @driver: DRM driver to allocate device for > * @parent: Parent device object > @@ -598,25 +636,12 @@ static void drm_dev_release(struct kref *ref) > { > struct drm_device *dev = container_of(ref, struct drm_device, ref); > > - drm_vblank_cleanup(dev); > - > - if (drm_core_check_feature(dev, DRIVER_GEM)) > - drm_gem_destroy(dev); > - > - drm_legacy_ctxbitmap_cleanup(dev); > - drm_ht_remove(&dev->map_hash); > - drm_fs_inode_free(dev->anon_inode); > - > - drm_minor_free(dev, DRM_MINOR_PRIMARY); > - drm_minor_free(dev, DRM_MINOR_RENDER); > - drm_minor_free(dev, DRM_MINOR_CONTROL); > - > - mutex_destroy(&dev->master_mutex); > - mutex_destroy(&dev->ctxlist_mutex); > - mutex_destroy(&dev->filelist_mutex); > - mutex_destroy(&dev->struct_mutex); > - kfree(dev->unique); > - kfree(dev); > + if (dev->driver->release) { > + dev->driver->release(dev); > + } else { > + drm_dev_fini(dev); > + kfree(dev); > + } > } > > /** > diff --git a/include/drm/drm_drv.h b/include/drm/drm_drv.h > index 732e85652d1e..5699f42195fe 100644 > --- a/include/drm/drm_drv.h > +++ b/include/drm/drm_drv.h > @@ -102,6 +102,17 @@ struct drm_driver { >
[Intel-gfx] [PATCH] drm/i915: fix i915 running as dom0 under Xen
Commit 920cf4194954ec ("drm/i915: Introduce an internal allocator for disposable private objects") introduced a regression for the kernel running as Xen dom0: when switching to graphics mode a GPU HANG occurred. Reason seems to be a missing adaption similar to that done in commit 7453c549f5f648 ("swiotlb: Export swiotlb_max_segment to users") to i915_gem_object_get_pages_internal(). So limit the maximum page order to be used according to the maximum swiotlb segment size instead to the complete swiotlb size. Signed-off-by: Juergen Gross --- Please consider for 4.10 as otherwise 4.10 will be unusable as Xen dom0 with i915 graphics. --- drivers/gpu/drm/i915/i915_gem_internal.c | 12 ++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_gem_internal.c b/drivers/gpu/drm/i915/i915_gem_internal.c index 4b3ff3e..d09c749 100644 --- a/drivers/gpu/drm/i915/i915_gem_internal.c +++ b/drivers/gpu/drm/i915/i915_gem_internal.c @@ -66,8 +66,16 @@ i915_gem_object_get_pages_internal(struct drm_i915_gem_object *obj) max_order = MAX_ORDER; #ifdef CONFIG_SWIOTLB - if (swiotlb_nr_tbl()) /* minimum max swiotlb size is IO_TLB_SEGSIZE */ - max_order = min(max_order, ilog2(IO_TLB_SEGPAGES)); + if (swiotlb_nr_tbl()) { + unsigned int max_segment; + + max_segment = swiotlb_max_segment(); + if (max_segment) { + max_segment = max_t(unsigned int, max_segment, + PAGE_SIZE) >> PAGE_SHIFT; + max_order = min(max_order, ilog2(max_segment)); + } + } #endif gfp = GFP_KERNEL | __GFP_HIGHMEM | __GFP_RECLAIMABLE; -- 2.10.2 ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/intel-gfx
Re: [Intel-gfx] [PATCH 4/6] drm: scrambling support in drm layer
On Thu, Feb 02, 2017 at 11:18:51AM +0530, Sharma, Shashank wrote: > Regards > > Shashank > > > On 2/1/2017 10:02 PM, Ville Syrjälä wrote: > > On Wed, Feb 01, 2017 at 06:14:39PM +0530, Shashank Sharma wrote: > >> HDMI 2.0 spec mandates scrambling for modes with pixel clock higher > >> than 340Mhz. This patch adds few new functions in drm layer for > >> core drivers to enable/disable scrambling. > >> > >> This patch adds: > >> - A function to detect scrambling support parsing HF-VSDB > >> - A function to check scrambling status runtime using SCDC read. > >> - Two functions to enable/disable scrambling using SCDC read/write. > >> - Few new bools to reflect scrambling support and status. > >> > >> Signed-off-by: Shashank Sharma > >> --- > >> drivers/gpu/drm/drm_edid.c | 131 > >> +++- > >> include/drm/drm_connector.h | 24 > >> include/drm/drm_edid.h | 6 +- > >> 3 files changed, 159 insertions(+), 2 deletions(-) > >> > >> diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c > >> index 37902e5..f0d940a 100644 > >> --- a/drivers/gpu/drm/drm_edid.c > >> +++ b/drivers/gpu/drm/drm_edid.c > >> @@ -37,6 +37,7 @@ > >> #include > >> #include > >> #include > >> +#include > >> > >> #define version_greater(edid, maj, min) \ > >>(((edid)->version > (maj)) || \ > >> @@ -3814,6 +3815,132 @@ static void drm_detect_hdmi_scdc(struct > >> drm_connector *connector, > >>} > >> } > >> > >> +static void drm_detect_hdmi_scrambling(struct drm_connector *connector, > >> + const u8 *hf_vsdb) > > That names seems off. Should probably be drm_parse_hdmi_forum_vsdb() or > > something. > Actually, unlike the last patch set, we are not parsing the whole > hf_vsdb, but parsing it only for > scrambling status byte (hf_vsdb[5]). But may be I can make it > drm_detect_scrambling_from_hfvsdb > ot something similar. We will have more hf_vsdb parsing for 3d flags, > yuv420_deep_color etc. Well, so far I'm not seeing much point in splitting it up. So I'd stuff it all into one place, for now at least. -- Ville Syrjälä Intel OTC ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/intel-gfx
Re: [Intel-gfx] [PATCH 2/7] drm/i915: add DisplayPort amp unmute for LPE audio mode
On Tue, 31 Jan 2017 22:36:44 +0100, Takashi Iwai wrote: > > From: Pierre-Louis Bossart > > Enable unmute/mute amp notification. This doesn't seem to affect > HDMI support so this is done unconditionally. > > An earlier version of this patch set a chicken bit at address 0x62F38 > prior to the mute/unmute but this register doesn't seem to do anything > so this phase was removed. Sorry, this seems like a wrong result. It worked yesterday, but when I retested the latest code today, it didn't work any longer. Then, after setting the chicken bit, it starts working again. But now I can't make it broken again. Turn off the monitor, turn off the machine, DPMS off, suspend/resume... All still works without chicken bit set. Also, the chicken bit of the register 0x62f38 couldn't be read back. The register always returns zero when read. So the chicken bit helps definitely something on a device here, but it's still mystery how it works. I'll send an additional patch to re-add the audio chicken bit stuff. thanks, Takashi > > Signed-off-by: Pierre-Louis Bossart > Signed-off-by: Takashi Iwai > --- > drivers/gpu/drm/i915/i915_reg.h| 10 ++ > drivers/gpu/drm/i915/intel_lpe_audio.c | 17 + > 2 files changed, 27 insertions(+) > > diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h > index a9ffc8df241b..8fcc80cb864b 100644 > --- a/drivers/gpu/drm/i915/i915_reg.h > +++ b/drivers/gpu/drm/i915/i915_reg.h > @@ -2061,6 +2061,16 @@ enum skl_disp_power_wells { > #define I915_HDMI_LPE_AUDIO_BASE (VLV_DISPLAY_BASE + 0x65000) > #define I915_HDMI_LPE_AUDIO_SIZE 0x1000 > > +/* DisplayPort Audio w/ LPE */ > +#define VLV_AUD_PORT_EN_B_DBG(VLV_DISPLAY_BASE + 0x62F20) > +#define VLV_AUD_PORT_EN_C_DBG(VLV_DISPLAY_BASE + 0x62F30) > +#define VLV_AUD_PORT_EN_D_DBG(VLV_DISPLAY_BASE + 0x62F34) > +#define VLV_AUD_PORT_EN_DBG(port)_MMIO_PORT3((port) - PORT_B, \ > + VLV_AUD_PORT_EN_B_DBG, \ > + VLV_AUD_PORT_EN_C_DBG, \ > + VLV_AUD_PORT_EN_D_DBG) > +#define VLV_AMP_MUTE (1 << 1) > + > #define GEN6_BSD_RNCID _MMIO(0x12198) > > #define GEN7_FF_THREAD_MODE _MMIO(0x20a0) > diff --git a/drivers/gpu/drm/i915/intel_lpe_audio.c > b/drivers/gpu/drm/i915/intel_lpe_audio.c > index 245523e14418..f95624a46f27 100644 > --- a/drivers/gpu/drm/i915/intel_lpe_audio.c > +++ b/drivers/gpu/drm/i915/intel_lpe_audio.c > @@ -337,15 +337,25 @@ void intel_lpe_audio_notify(struct drm_i915_private > *dev_priv, > { > unsigned long irq_flags; > struct intel_hdmi_lpe_audio_pdata *pdata = NULL; > + u32 audio_enable; > + i915_reg_t mmio; > > if (!HAS_LPE_AUDIO(dev_priv)) > return; > > + if (port == PORT_A) { > + DRM_ERROR("PORT_A is not valid for HDMI/DP usages\n"); > + return; > + } > + > pdata = dev_get_platdata( > &(dev_priv->lpe_audio.platdev->dev)); > > spin_lock_irqsave(&pdata->lpe_audio_slock, irq_flags); > > + mmio = VLV_AUD_PORT_EN_DBG(port); > + audio_enable = I915_READ(mmio); > + > if (eld != NULL) { > memcpy(pdata->eld.eld_data, eld, > HDMI_MAX_ELD_BYTES); > @@ -357,11 +367,18 @@ void intel_lpe_audio_notify(struct drm_i915_private > *dev_priv, > pdata->tmds_clock_speed = tmds_clk_speed; > if (link_rate) > pdata->link_rate = link_rate; > + > + /* Unmute the amp for both DP and HDMI */ > + I915_WRITE(mmio, audio_enable & ~VLV_AMP_MUTE); > + > } else { > memset(pdata->eld.eld_data, 0, > HDMI_MAX_ELD_BYTES); > pdata->hdmi_connected = false; > pdata->dp_output = false; > + > + /* Mute the amp for both DP and HDMI */ > + I915_WRITE(mmio, audio_enable | VLV_AMP_MUTE); > } > > if (pdata->notify_audio_lpe) > -- > 2.11.0 > ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/intel-gfx
[Intel-gfx] [PATCH] drm/i915/dp: Read link status more times when EQ not done
From: "Lee, Shawn C" When user space link status, display driver read DPCD register 0x202, 0x203 and 0x204 to identify sink status. When PSR exit is ongoing before EQ done. Panel will report EQ & symbol lock not done. Both of them are under progressing at the same time to cause this issue. This WA try to read link status more times if EQ not done. Panel spec request at least 1000us for fast link train when PSR exit. So driver will wait 1000us~1500us then retrieve sink link status again. Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=99639 TEST=Reboot DUT and no flicking on local display at login screen Cc: Cooper Chiou Cc: Wei Shun Chen Cc: Gary C Wang Cc: Jani Nikula Signed-off-by: Lee, Shawn C --- drivers/gpu/drm/i915/intel_dp.c | 33 - 1 file changed, 28 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index e80d620846c8..a9a6ce476438 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -4136,13 +4136,36 @@ static void intel_dp_handle_test_request(struct intel_dp *intel_dp) return; /* if link training is requested we should perform it always */ - if ((intel_dp->compliance.test_type == DP_TEST_LINK_TRAINING) || - (!drm_dp_channel_eq_ok(link_status, intel_dp->lane_count))) { - DRM_DEBUG_KMS("%s: channel EQ not ok, retraining\n", - intel_encoder->base.name); + if (intel_dp->compliance.test_type == DP_TEST_LINK_TRAINING) { + DRM_DEBUG_KMS("%s: compliance test mode, retraining\n", + intel_encoder->base.name); + } else { + u8 retry; + + for (retry = 0; retry < 3; retry++) { + if (!drm_dp_channel_eq_ok(link_status, intel_dp->lane_count)) { + /* +* EQ not ok may caused by fast link train while exit PSR active, +* wait at least 1000 us then read it again. +*/ + DRM_DEBUG_KMS("%s: channel EQ not ok, retry = %d, DPCD 0x202 = 0x%x, 0x203 = 0x%x, 0x204 = 0x%x\n", + intel_encoder->base.name, retry, link_status[0], link_status[1], link_status[2]); + usleep_range(1000, 1500); + if (!intel_dp_get_link_status(intel_dp, link_status)) { + DRM_ERROR("Failed to get link status\n"); + return; + } + } else { + /* channel EQ is fine */ + return; + } + } - intel_dp_retrain_link(intel_dp); + DRM_DEBUG_KMS("%s: channel EQ not ok, retraining\n", + intel_encoder->base.name); } + + intel_dp_retrain_link(intel_dp); } /* -- 1.7.9.5 ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/intel-gfx
Re: [Intel-gfx] [PATCH 5/6] drm/i915: enable scrambling
On Thu, Feb 02, 2017 at 11:23:19AM +0530, Sharma, Shashank wrote: > Regards > > Shashank > > > On 2/1/2017 10:06 PM, Ville Syrjälä wrote: > > On Wed, Feb 01, 2017 at 06:14:40PM +0530, Shashank Sharma wrote: > >> Geminilake platform has a native HDMI 2.0 controller, and is > >> capable of driving pixel-clocks upto 594Mhz. HDMI 2.0 spec > >> mendates scrambling for these higher clocks, for reduced RF footprint. > >> > >> This patch checks if the monitor supports scrambling, and if required, > >> enables it during the modeset. > >> > >> Signed-off-by: Shashank Sharma > >> --- > >> drivers/gpu/drm/i915/i915_reg.h | 2 ++ > >> drivers/gpu/drm/i915/intel_ddi.c | 5 + > >> drivers/gpu/drm/i915/intel_drv.h | 2 ++ > >> drivers/gpu/drm/i915/intel_hdmi.c | 42 > >> +++ > >> 4 files changed, 51 insertions(+) > >> > >> diff --git a/drivers/gpu/drm/i915/i915_reg.h > >> b/drivers/gpu/drm/i915/i915_reg.h > >> index 495b789..cc85892 100644 > >> --- a/drivers/gpu/drm/i915/i915_reg.h > >> +++ b/drivers/gpu/drm/i915/i915_reg.h > >> @@ -7807,6 +7807,8 @@ enum { > >> #define TRANS_DDI_EDP_INPUT_C_ONOFF (6<<12) > >> #define TRANS_DDI_DP_VC_PAYLOAD_ALLOC (1<<8) > >> #define TRANS_DDI_BFI_ENABLE(1<<4) > >> +#define TRANS_DDI_HIGH_TMDS_CHAR_RATE(1<<4) > >> +#define TRANS_DDI_HDMI_SCRAMBLING(1<<0) > >> > >> /* DisplayPort Transport Control */ > >> #define _DP_TP_CTL_A 0x64040 > >> diff --git a/drivers/gpu/drm/i915/intel_ddi.c > >> b/drivers/gpu/drm/i915/intel_ddi.c > >> index 9a9a670..aea81ce 100644 > >> --- a/drivers/gpu/drm/i915/intel_ddi.c > >> +++ b/drivers/gpu/drm/i915/intel_ddi.c > >> @@ -1278,6 +1278,11 @@ void intel_ddi_enable_transcoder_func(struct > >> drm_crtc *crtc) > >>temp |= TRANS_DDI_MODE_SELECT_HDMI; > >>else > >>temp |= TRANS_DDI_MODE_SELECT_DVI; > >> + > >> + if (IS_GEMINILAKE(dev_priv)) { > >> + temp |= intel_hdmi_check_scrambling(intel_encoder, > >> + &intel_crtc->config->base.adjusted_mode); > >> + } > >>} else if (type == INTEL_OUTPUT_ANALOG) { > >>temp |= TRANS_DDI_MODE_SELECT_FDI; > >>temp |= (intel_crtc->config->fdi_lanes - 1) << 1; > >> diff --git a/drivers/gpu/drm/i915/intel_drv.h > >> b/drivers/gpu/drm/i915/intel_drv.h > >> index 393f243..aafce7f 100644 > >> --- a/drivers/gpu/drm/i915/intel_drv.h > >> +++ b/drivers/gpu/drm/i915/intel_drv.h > >> @@ -1588,6 +1588,8 @@ void intel_hdmi_init_connector(struct > >> intel_digital_port *intel_dig_port, > >> bool intel_hdmi_compute_config(struct intel_encoder *encoder, > >> struct intel_crtc_state *pipe_config, > >> struct drm_connector_state *conn_state); > >> +uint32_t intel_hdmi_check_scrambling(struct intel_encoder *intel_encoder, > >> + struct drm_display_mode *mode); > >> void intel_dp_dual_mode_set_tmds_output(struct intel_hdmi *hdmi, bool > >> enable); > >> > >> > >> diff --git a/drivers/gpu/drm/i915/intel_hdmi.c > >> b/drivers/gpu/drm/i915/intel_hdmi.c > >> index ebae2bd..92dd9bc 100644 > >> --- a/drivers/gpu/drm/i915/intel_hdmi.c > >> +++ b/drivers/gpu/drm/i915/intel_hdmi.c > >> @@ -1795,6 +1795,48 @@ static void intel_hdmi_destroy(struct drm_connector > >> *connector) > >>intel_hdmi->aspect_ratio = HDMI_PICTURE_ASPECT_NONE; > >> } > >> > >> +static void > >> +intel_hdmi_enable_scrambling(struct drm_connector *connector) > >> +{ > >> + struct drm_i915_private *dev_priv = connector->dev->dev_private; > >> + struct intel_hdmi *intel_hdmi = intel_attached_hdmi(connector); > >> + struct i2c_adapter *adapter = > >> + intel_gmbus_get_adapter(dev_priv, intel_hdmi->ddc_bus); > >> + > >> + if (!drm_enable_scrambling(connector, adapter, true)) > >> + DRM_ERROR("Request to enable scrambling failed\n"); > >> +} > > I don't like hiding this somewhere deep like this. It should be > > somewhere much higher up. > Why ? All we need to do here is enable two bits in transcoder control > register, which is already being > programmed in a calling function, so I dont see the use case, but I > might be missing some bigger picture. > Can you please elaborate on this ? We're talking to the display here, which is rather surprising to happen from a function thing that on the first glance doesn't even seem to touch the hardware. > > > > And I'm thinkign we might want to track the scrambler state > > in the crtc state. > Yes, that's a pretty good way to track dynamic status of scrambler, do > you think we should add this in > drm_crtc_state itself ? I'd just start with intel specific state and later we can see what everyone else wants to do and potentially unify a bit. > > - Shashank > >> + > >> +uint32_t intel_hdmi_check_scrambling(struct intel_encoder *intel_encoder, > >> +
Re: [Intel-gfx] [PATCH v2 1/5] drm/i915: Generate i915_params {} using a macro
On Thu, Feb 02, 2017 at 11:37:06AM +0200, Jani Nikula wrote: > On Thu, 02 Feb 2017, Chris Wilson wrote: > > I want to print the struct from the error state and so would like to use > > the existing struct definition as the template ala DEV_INFO* > > > > v2: Use MEMBER() rather than p(). > > > > Signed-off-by: Chris Wilson > > Reviewed-by: Joonas Lahtinen > > I've been telling everyone who complains about testing specific firmware > blob versions to add a module parameter to specify and override the > default filename. AFAICT this series does not make string parameters any > harder, but please do double check. I think they expect a static > allocation for the string buffer too, so the struct assignment should be > fine as well. charp which is the dynamically allocated string might be easier, certainly for 0400 parameters. Hmm. Except for copying into the error state, 0600 charp will take a bit more work (another iterator to kstrdup). diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index 86649610b9eb..2d32dacebeb3 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -76,6 +76,13 @@ static void seq_param_uint(struct seq_file *m, const char *name, param_uint x) seq_printf(m, "i915.%s=%u\n", name, x); } +static void seq_param_charp(struct seq_file *m, const char *name, param_charp x) +{ + kernel_param_lock(THIS_MODULE); + seq_printf(m, "i915.%s=%s\n", name, x); + kernel_param_unlock(THIS_MODULE); +} + static int i915_capabilities(struct seq_file *m, void *data) { struct drm_i915_private *dev_priv = node_to_i915(m->private); diff --git a/drivers/gpu/drm/i915/i915_gpu_error.c b/drivers/gpu/drm/i915/i915_gpu_error.c index b8f2b671fc0a..35602935dba8 100644 --- a/drivers/gpu/drm/i915/i915_gpu_error.c +++ b/drivers/gpu/drm/i915/i915_gpu_error.c @@ -567,6 +567,15 @@ static void err_param_uint(struct drm_i915_error_state_buf *m, err_printf(m, "%s: %u\n", name, x); } +static void err_param_charp(struct drm_i915_error_state_buf *m, + const char *name, + param_charp x) +{ + kernel_param_lock(THIS_MODULE); + err_printf(m, "%s: %s\n", name, x); + kernel_param_unlock(THIS_MODULE); +} + static void err_print_params(struct drm_i915_error_state_buf *m, const struct i915_params *p) { diff --git a/drivers/gpu/drm/i915/i915_params.c b/drivers/gpu/drm/i915/i915_params.c index f1fa51190dc6..f9cc170577c2 100644 --- a/drivers/gpu/drm/i915/i915_params.c +++ b/drivers/gpu/drm/i915/i915_params.c @@ -65,6 +65,8 @@ struct i915_params i915 __read_mostly = { .enable_gvt = false, }; +module_param_named_unsafe(my_string, i915.my_string, charp, 0400); + module_param_named(modeset, i915.modeset, int, 0400); MODULE_PARM_DESC(modeset, "Use kernel modesetting [KMS] (0=disable, " diff --git a/drivers/gpu/drm/i915/i915_params.h b/drivers/gpu/drm/i915/i915_params.h index 87ac6ed995d3..bc5aea9e3fb6 100644 --- a/drivers/gpu/drm/i915/i915_params.h +++ b/drivers/gpu/drm/i915/i915_params.h @@ -30,6 +30,7 @@ typedef bool param_bool; typedef int param_int; typedef unsigned int param_uint; +typedef char *param_charp; #define I915_PARAMS_FOR_EACH(func) \ func(param_int, modeset); \ @@ -54,6 +55,7 @@ typedef unsigned int param_uint; func(param_int, mmio_debug); \ func(param_int, edp_vswing); \ func(param_uint, inject_load_failure); \ + func(param_charp, my_string); \ /* leave bools at the end to not create holes */ \ func(param_bool, alpha_support); \ func(param_bool, enable_cmd_parser); \ -- Chris Wilson, Intel Open Source Technology Centre ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/intel-gfx
Re: [Intel-gfx] [PATCH 2/7] drm/i915: add DisplayPort amp unmute for LPE audio mode
On Thu, Feb 02, 2017 at 10:57:30AM +0100, Takashi Iwai wrote: > On Tue, 31 Jan 2017 22:36:44 +0100, > Takashi Iwai wrote: > > > > From: Pierre-Louis Bossart > > > > Enable unmute/mute amp notification. This doesn't seem to affect > > HDMI support so this is done unconditionally. > > > > An earlier version of this patch set a chicken bit at address 0x62F38 > > prior to the mute/unmute but this register doesn't seem to do anything > > so this phase was removed. > > Sorry, this seems like a wrong result. It worked yesterday, but when > I retested the latest code today, it didn't work any longer. > Then, after setting the chicken bit, it starts working again. > > But now I can't make it broken again. Turn off the monitor, turn off > the machine, DPMS off, suspend/resume... All still works without > chicken bit set. > > Also, the chicken bit of the register 0x62f38 couldn't be read back. > The register always returns zero when read. The docs do say it's write-only actually. -- Ville Syrjälä Intel OTC ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/intel-gfx
Re: [Intel-gfx] [PATCH 2/7] drm/i915: add DisplayPort amp unmute for LPE audio mode
On Thu, 02 Feb 2017 11:06:05 +0100, Ville Syrjälä wrote: > > On Thu, Feb 02, 2017 at 10:57:30AM +0100, Takashi Iwai wrote: > > On Tue, 31 Jan 2017 22:36:44 +0100, > > Takashi Iwai wrote: > > > > > > From: Pierre-Louis Bossart > > > > > > Enable unmute/mute amp notification. This doesn't seem to affect > > > HDMI support so this is done unconditionally. > > > > > > An earlier version of this patch set a chicken bit at address 0x62F38 > > > prior to the mute/unmute but this register doesn't seem to do anything > > > so this phase was removed. > > > > Sorry, this seems like a wrong result. It worked yesterday, but when > > I retested the latest code today, it didn't work any longer. > > Then, after setting the chicken bit, it starts working again. > > > > But now I can't make it broken again. Turn off the monitor, turn off > > the machine, DPMS off, suspend/resume... All still works without > > chicken bit set. > > > > Also, the chicken bit of the register 0x62f38 couldn't be read back. > > The register always returns zero when read. > > The docs do say it's write-only actually. OK, thanks for confirmation! Takashi ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/intel-gfx
Re: [Intel-gfx] [PATCH 4/6] drm: scrambling support in drm layer
Regards Shashank On 2/2/2017 3:21 PM, Ville Syrjälä wrote: On Thu, Feb 02, 2017 at 11:18:51AM +0530, Sharma, Shashank wrote: Regards Shashank On 2/1/2017 10:02 PM, Ville Syrjälä wrote: On Wed, Feb 01, 2017 at 06:14:39PM +0530, Shashank Sharma wrote: HDMI 2.0 spec mandates scrambling for modes with pixel clock higher than 340Mhz. This patch adds few new functions in drm layer for core drivers to enable/disable scrambling. This patch adds: - A function to detect scrambling support parsing HF-VSDB - A function to check scrambling status runtime using SCDC read. - Two functions to enable/disable scrambling using SCDC read/write. - Few new bools to reflect scrambling support and status. Signed-off-by: Shashank Sharma --- drivers/gpu/drm/drm_edid.c | 131 +++- include/drm/drm_connector.h | 24 include/drm/drm_edid.h | 6 +- 3 files changed, 159 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c index 37902e5..f0d940a 100644 --- a/drivers/gpu/drm/drm_edid.c +++ b/drivers/gpu/drm/drm_edid.c @@ -37,6 +37,7 @@ #include #include #include +#include #define version_greater(edid, maj, min) \ (((edid)->version > (maj)) || \ @@ -3814,6 +3815,132 @@ static void drm_detect_hdmi_scdc(struct drm_connector *connector, } } +static void drm_detect_hdmi_scrambling(struct drm_connector *connector, +const u8 *hf_vsdb) That names seems off. Should probably be drm_parse_hdmi_forum_vsdb() or something. Actually, unlike the last patch set, we are not parsing the whole hf_vsdb, but parsing it only for scrambling status byte (hf_vsdb[5]). But may be I can make it drm_detect_scrambling_from_hfvsdb ot something similar. We will have more hf_vsdb parsing for 3d flags, yuv420_deep_color etc. Well, so far I'm not seeing much point in splitting it up. So I'd stuff it all into one place, for now at least. I had published a patch just doing as you suggested which was parsing complete hf-vsdb in one shot, and adding info in hdmi_info structure, to accommodate it. (Patch https://patchwork.freedesktop.org/patch/128963/ and https://patchwork.freedesktop.org/patch/128962/) But you gave a review comment not to add anything which is not being used in the patch series: https://patchwork.freedesktop.org/patch/128962/ That was the only reason I have split hf-vsdb parsing patch into 3 parts - parse SCDC and scrambling info (here) - with YUV420 deep color ( upcoming ) - with 3d handling (upcoming) So I am confused, split or no split :-) ? - Shashank ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/intel-gfx
Re: [Intel-gfx] [PATCH 4/6] drm: scrambling support in drm layer
On Thu, Feb 02, 2017 at 03:46:55PM +0530, Sharma, Shashank wrote: > Regards > > Shashank > > > On 2/2/2017 3:21 PM, Ville Syrjälä wrote: > > On Thu, Feb 02, 2017 at 11:18:51AM +0530, Sharma, Shashank wrote: > >> Regards > >> > >> Shashank > >> > >> > >> On 2/1/2017 10:02 PM, Ville Syrjälä wrote: > >>> On Wed, Feb 01, 2017 at 06:14:39PM +0530, Shashank Sharma wrote: > HDMI 2.0 spec mandates scrambling for modes with pixel clock higher > than 340Mhz. This patch adds few new functions in drm layer for > core drivers to enable/disable scrambling. > > This patch adds: > - A function to detect scrambling support parsing HF-VSDB > - A function to check scrambling status runtime using SCDC read. > - Two functions to enable/disable scrambling using SCDC read/write. > - Few new bools to reflect scrambling support and status. > > Signed-off-by: Shashank Sharma > --- > drivers/gpu/drm/drm_edid.c | 131 > +++- > include/drm/drm_connector.h | 24 > include/drm/drm_edid.h | 6 +- > 3 files changed, 159 insertions(+), 2 deletions(-) > > diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c > index 37902e5..f0d940a 100644 > --- a/drivers/gpu/drm/drm_edid.c > +++ b/drivers/gpu/drm/drm_edid.c > @@ -37,6 +37,7 @@ > #include > #include > #include > +#include > > #define version_greater(edid, maj, min) \ > (((edid)->version > (maj)) || \ > @@ -3814,6 +3815,132 @@ static void drm_detect_hdmi_scdc(struct > drm_connector *connector, > } > } > > +static void drm_detect_hdmi_scrambling(struct drm_connector *connector, > + const u8 *hf_vsdb) > >>> That names seems off. Should probably be drm_parse_hdmi_forum_vsdb() or > >>> something. > >> Actually, unlike the last patch set, we are not parsing the whole > >> hf_vsdb, but parsing it only for > >> scrambling status byte (hf_vsdb[5]). But may be I can make it > >> drm_detect_scrambling_from_hfvsdb > >> ot something similar. We will have more hf_vsdb parsing for 3d flags, > >> yuv420_deep_color etc. > > Well, so far I'm not seeing much point in splitting it up. So I'd stuff > > it all into one place, for now at least. > I had published a patch just doing as you suggested which was parsing > complete hf-vsdb in one shot, and adding info in > hdmi_info structure, to accommodate it. > (Patch https://patchwork.freedesktop.org/patch/128963/ and > https://patchwork.freedesktop.org/patch/128962/) > > But you gave a review comment not to add anything which is not being > used in the patch series: > https://patchwork.freedesktop.org/patch/128962/ That's doesn't require the things that are left to be split into separate functions. > > That was the only reason I have split hf-vsdb parsing patch into 3 parts > - parse SCDC and scrambling info (here) > - with YUV420 deep color ( upcoming ) > - with 3d handling (upcoming) > > So I am confused, split or no split :-) ? > > - Shashank -- Ville Syrjälä Intel OTC ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/intel-gfx
[Intel-gfx] [PATCH v8] drm/i915/scheduler: emulate a scheduler for guc
This emulates execlists on top of the GuC in order to defer submission of requests to the hardware. This deferral allows time for high priority requests to gazump their way to the head of the queue, however it nerfs the GuC by converting it back into a simple execlist (where the CPU has to wake up after every request to feed new commands into the GuC). v2: Drop hack status - though iirc there is still a lockdep inversion between fence and engine->timeline->lock (which is impossible as the nesting only occurs on different fences - hopefully just requires some judicious lockdep annotation) v3: Apply lockdep nesting to enabling signaling on the request, using the pattern we already have in __i915_gem_request_submit(); v4: Replaying requests after a hang also now needs the timeline spinlock, to disable the interrupts at least v5: Hold wq lock for completeness, and emit a tracepoint for enabling signal v6: Reorder interrupt checking for a happier gcc. v7: Only signal the tasklet after a user-interrupt if using guc scheduling v8: Restore lost update of rq through the i915_guc_irq_handler (Tvrtko) Signed-off-by: Chris Wilson Cc: Tvrtko Ursulin Reviewed-by: Tvrtko Ursulin --- drivers/gpu/drm/i915/i915_guc_submission.c | 110 +++-- drivers/gpu/drm/i915/i915_irq.c| 13 +++- drivers/gpu/drm/i915/intel_lrc.c | 5 +- 3 files changed, 114 insertions(+), 14 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_guc_submission.c b/drivers/gpu/drm/i915/i915_guc_submission.c index 8ced9e26f075..d99185aafe58 100644 --- a/drivers/gpu/drm/i915/i915_guc_submission.c +++ b/drivers/gpu/drm/i915/i915_guc_submission.c @@ -25,6 +25,8 @@ #include "i915_drv.h" #include "intel_uc.h" +#include + /** * DOC: GuC-based command submission * @@ -348,7 +350,7 @@ int i915_guc_wq_reserve(struct drm_i915_gem_request *request) u32 freespace; int ret; - spin_lock(&client->wq_lock); + spin_lock_irq(&client->wq_lock); freespace = CIRC_SPACE(client->wq_tail, desc->head, client->wq_size); freespace -= client->wq_rsvd; if (likely(freespace >= wqi_size)) { @@ -358,7 +360,7 @@ int i915_guc_wq_reserve(struct drm_i915_gem_request *request) client->no_wq_space++; ret = -EAGAIN; } - spin_unlock(&client->wq_lock); + spin_unlock_irq(&client->wq_lock); return ret; } @@ -370,9 +372,9 @@ void i915_guc_wq_unreserve(struct drm_i915_gem_request *request) GEM_BUG_ON(READ_ONCE(client->wq_rsvd) < wqi_size); - spin_lock(&client->wq_lock); + spin_lock_irq(&client->wq_lock); client->wq_rsvd -= wqi_size; - spin_unlock(&client->wq_lock); + spin_unlock_irq(&client->wq_lock); } /* Construct a Work Item and append it to the GuC's Work Queue */ @@ -532,10 +534,97 @@ static void __i915_guc_submit(struct drm_i915_gem_request *rq) static void i915_guc_submit(struct drm_i915_gem_request *rq) { - i915_gem_request_submit(rq); + __i915_gem_request_submit(rq); __i915_guc_submit(rq); } +static void nested_enable_signaling(struct drm_i915_gem_request *rq) +{ + /* If we use dma_fence_enable_sw_signaling() directly, lockdep +* detects an ordering issue between the fence lockclass and the +* global_timeline. This circular dependency can only occur via 2 +* different fences (but same fence lockclass), so we use the nesting +* annotation here to prevent the warn, equivalent to the nesting +* inside i915_gem_request_submit() for when we also enable the +* signaler. +*/ + + if (test_and_set_bit(DMA_FENCE_FLAG_ENABLE_SIGNAL_BIT, +&rq->fence.flags)) + return; + + GEM_BUG_ON(test_bit(DMA_FENCE_FLAG_SIGNALED_BIT, &rq->fence.flags)); + trace_dma_fence_enable_signal(&rq->fence); + + spin_lock_nested(&rq->lock, SINGLE_DEPTH_NESTING); + intel_engine_enable_signaling(rq); + spin_unlock(&rq->lock); +} + +static bool i915_guc_dequeue(struct intel_engine_cs *engine) +{ + struct execlist_port *port = engine->execlist_port; + struct drm_i915_gem_request *last = port[0].request; + unsigned long flags; + struct rb_node *rb; + bool submit = false; + + spin_lock_irqsave(&engine->timeline->lock, flags); + rb = engine->execlist_first; + while (rb) { + struct drm_i915_gem_request *cursor = + rb_entry(rb, typeof(*cursor), priotree.node); + + if (last && cursor->ctx != last->ctx) { + if (port != engine->execlist_port) + break; + + i915_gem_request_assign(&port->request, last); + nested_enable_signaling(last); + port++; + } + + rb = rb_next(rb); + rb_erase(&cursor->priotre
Re: [Intel-gfx] [PATCH 4/6] drm: scrambling support in drm layer
Regards Shashank On 2/2/2017 3:58 PM, Ville Syrjälä wrote: On Thu, Feb 02, 2017 at 03:46:55PM +0530, Sharma, Shashank wrote: Regards Shashank On 2/2/2017 3:21 PM, Ville Syrjälä wrote: On Thu, Feb 02, 2017 at 11:18:51AM +0530, Sharma, Shashank wrote: Regards Shashank On 2/1/2017 10:02 PM, Ville Syrjälä wrote: On Wed, Feb 01, 2017 at 06:14:39PM +0530, Shashank Sharma wrote: HDMI 2.0 spec mandates scrambling for modes with pixel clock higher than 340Mhz. This patch adds few new functions in drm layer for core drivers to enable/disable scrambling. This patch adds: - A function to detect scrambling support parsing HF-VSDB - A function to check scrambling status runtime using SCDC read. - Two functions to enable/disable scrambling using SCDC read/write. - Few new bools to reflect scrambling support and status. Signed-off-by: Shashank Sharma --- drivers/gpu/drm/drm_edid.c | 131 +++- include/drm/drm_connector.h | 24 include/drm/drm_edid.h | 6 +- 3 files changed, 159 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c index 37902e5..f0d940a 100644 --- a/drivers/gpu/drm/drm_edid.c +++ b/drivers/gpu/drm/drm_edid.c @@ -37,6 +37,7 @@ #include #include #include +#include #define version_greater(edid, maj, min) \ (((edid)->version > (maj)) || \ @@ -3814,6 +3815,132 @@ static void drm_detect_hdmi_scdc(struct drm_connector *connector, } } +static void drm_detect_hdmi_scrambling(struct drm_connector *connector, +const u8 *hf_vsdb) That names seems off. Should probably be drm_parse_hdmi_forum_vsdb() or something. Actually, unlike the last patch set, we are not parsing the whole hf_vsdb, but parsing it only for scrambling status byte (hf_vsdb[5]). But may be I can make it drm_detect_scrambling_from_hfvsdb ot something similar. We will have more hf_vsdb parsing for 3d flags, yuv420_deep_color etc. Well, so far I'm not seeing much point in splitting it up. So I'd stuff it all into one place, for now at least. I had published a patch just doing as you suggested which was parsing complete hf-vsdb in one shot, and adding info in hdmi_info structure, to accommodate it. (Patch https://patchwork.freedesktop.org/patch/128963/ and https://patchwork.freedesktop.org/patch/128962/) But you gave a review comment not to add anything which is not being used in the patch series: https://patchwork.freedesktop.org/patch/128962/ That's doesn't require the things that are left to be split into separate functions. So please let me know if my understanding is correct. - Name the function as *_parse_hfvsdb only - Call it while parsing the EDID extension blocks (the same place) - Keep on adding parsing of the HF-VSDB blocks, in the same function, in an incremental way, as we add patches for them. In this way the function won't be split into multiple small functions, but all the parsing will be done in one function. - Shashank That was the only reason I have split hf-vsdb parsing patch into 3 parts - parse SCDC and scrambling info (here) - with YUV420 deep color ( upcoming ) - with 3d handling (upcoming) So I am confused, split or no split :-) ? - Shashank ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/intel-gfx
Re: [Intel-gfx] [PATCH 5/6] drm/i915: enable scrambling
Regards Shashank On 2/2/2017 3:32 PM, Ville Syrjälä wrote: On Thu, Feb 02, 2017 at 11:23:19AM +0530, Sharma, Shashank wrote: Regards Shashank On 2/1/2017 10:06 PM, Ville Syrjälä wrote: On Wed, Feb 01, 2017 at 06:14:40PM +0530, Shashank Sharma wrote: Geminilake platform has a native HDMI 2.0 controller, and is capable of driving pixel-clocks upto 594Mhz. HDMI 2.0 spec mendates scrambling for these higher clocks, for reduced RF footprint. This patch checks if the monitor supports scrambling, and if required, enables it during the modeset. Signed-off-by: Shashank Sharma --- drivers/gpu/drm/i915/i915_reg.h | 2 ++ drivers/gpu/drm/i915/intel_ddi.c | 5 + drivers/gpu/drm/i915/intel_drv.h | 2 ++ drivers/gpu/drm/i915/intel_hdmi.c | 42 +++ 4 files changed, 51 insertions(+) diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 495b789..cc85892 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -7807,6 +7807,8 @@ enum { #define TRANS_DDI_EDP_INPUT_C_ONOFF (6<<12) #define TRANS_DDI_DP_VC_PAYLOAD_ALLOC (1<<8) #define TRANS_DDI_BFI_ENABLE(1<<4) +#define TRANS_DDI_HIGH_TMDS_CHAR_RATE (1<<4) +#define TRANS_DDI_HDMI_SCRAMBLING (1<<0) /* DisplayPort Transport Control */ #define _DP_TP_CTL_A 0x64040 diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c index 9a9a670..aea81ce 100644 --- a/drivers/gpu/drm/i915/intel_ddi.c +++ b/drivers/gpu/drm/i915/intel_ddi.c @@ -1278,6 +1278,11 @@ void intel_ddi_enable_transcoder_func(struct drm_crtc *crtc) temp |= TRANS_DDI_MODE_SELECT_HDMI; else temp |= TRANS_DDI_MODE_SELECT_DVI; + + if (IS_GEMINILAKE(dev_priv)) { + temp |= intel_hdmi_check_scrambling(intel_encoder, + &intel_crtc->config->base.adjusted_mode); + } } else if (type == INTEL_OUTPUT_ANALOG) { temp |= TRANS_DDI_MODE_SELECT_FDI; temp |= (intel_crtc->config->fdi_lanes - 1) << 1; diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 393f243..aafce7f 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -1588,6 +1588,8 @@ void intel_hdmi_init_connector(struct intel_digital_port *intel_dig_port, bool intel_hdmi_compute_config(struct intel_encoder *encoder, struct intel_crtc_state *pipe_config, struct drm_connector_state *conn_state); +uint32_t intel_hdmi_check_scrambling(struct intel_encoder *intel_encoder, + struct drm_display_mode *mode); void intel_dp_dual_mode_set_tmds_output(struct intel_hdmi *hdmi, bool enable); diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c index ebae2bd..92dd9bc 100644 --- a/drivers/gpu/drm/i915/intel_hdmi.c +++ b/drivers/gpu/drm/i915/intel_hdmi.c @@ -1795,6 +1795,48 @@ static void intel_hdmi_destroy(struct drm_connector *connector) intel_hdmi->aspect_ratio = HDMI_PICTURE_ASPECT_NONE; } +static void +intel_hdmi_enable_scrambling(struct drm_connector *connector) +{ + struct drm_i915_private *dev_priv = connector->dev->dev_private; + struct intel_hdmi *intel_hdmi = intel_attached_hdmi(connector); + struct i2c_adapter *adapter = + intel_gmbus_get_adapter(dev_priv, intel_hdmi->ddc_bus); + + if (!drm_enable_scrambling(connector, adapter, true)) + DRM_ERROR("Request to enable scrambling failed\n"); +} I don't like hiding this somewhere deep like this. It should be somewhere much higher up. Why ? All we need to do here is enable two bits in transcoder control register, which is already being programmed in a calling function, so I dont see the use case, but I might be missing some bigger picture. Can you please elaborate on this ? We're talking to the display here, which is rather surprising to happen from a function thing that on the first glance doesn't even seem to touch the hardware. I kind of agree with this, and I am also tempted now to shift this call upwards, but I want to keep this close to port enabling as well, as the HDMI 2.0 spec says: "Max time period between a source enables scrambling on monitor, and starts sending scrambled video should be 100ms" else the sink might choose to disable scrambling. Considering this, where do you think would be right place to enabled scrambling on monitor ? - Shashank And I'm thinkign we might want to track the scrambler state in the crtc state. Yes, that's a pretty good way to track dynamic status of scrambler, do you think we should add this in drm_crtc_state itself ? I'd just start with intel specific state and later we can see what everyone else wants to
Re: [Intel-gfx] [PATCH] drm/i915: fix i915 running as dom0 under Xen
On Thu, Feb 02, 2017 at 10:47:11AM +0100, Juergen Gross wrote: > Commit 920cf4194954ec ("drm/i915: Introduce an internal allocator for > disposable private objects") introduced a regression for the kernel > running as Xen dom0: when switching to graphics mode a GPU HANG > occurred. > > Reason seems to be a missing adaption similar to that done in > commit 7453c549f5f648 ("swiotlb: Export swiotlb_max_segment to users") > to i915_gem_object_get_pages_internal(). > > So limit the maximum page order to be used according to the maximum > swiotlb segment size instead to the complete swiotlb size. > > Signed-off-by: Juergen Gross Fixes: 920cf4194954 ("drm/i915: Introduce an internal allocator for disposable private objects") Cc: Chris Wilson Cc: Tvrtko Ursulin Cc: Daniel Vetter Cc: Jani Nikula Cc: intel-gfx@lists.freedesktop.org Cc: # v4.10-rc1+ We have a nice script for these :-) -Daniel > --- > Please consider for 4.10 as otherwise 4.10 will be unusable as Xen dom0 > with i915 graphics. > --- > drivers/gpu/drm/i915/i915_gem_internal.c | 12 ++-- > 1 file changed, 10 insertions(+), 2 deletions(-) > > diff --git a/drivers/gpu/drm/i915/i915_gem_internal.c > b/drivers/gpu/drm/i915/i915_gem_internal.c > index 4b3ff3e..d09c749 100644 > --- a/drivers/gpu/drm/i915/i915_gem_internal.c > +++ b/drivers/gpu/drm/i915/i915_gem_internal.c > @@ -66,8 +66,16 @@ i915_gem_object_get_pages_internal(struct > drm_i915_gem_object *obj) > > max_order = MAX_ORDER; > #ifdef CONFIG_SWIOTLB > - if (swiotlb_nr_tbl()) /* minimum max swiotlb size is IO_TLB_SEGSIZE */ > - max_order = min(max_order, ilog2(IO_TLB_SEGPAGES)); > + if (swiotlb_nr_tbl()) { > + unsigned int max_segment; > + > + max_segment = swiotlb_max_segment(); > + if (max_segment) { > + max_segment = max_t(unsigned int, max_segment, > + PAGE_SIZE) >> PAGE_SHIFT; > + max_order = min(max_order, ilog2(max_segment)); > + } > + } > #endif > > gfp = GFP_KERNEL | __GFP_HIGHMEM | __GFP_RECLAIMABLE; > -- > 2.10.2 > > ___ > Intel-gfx mailing list > Intel-gfx@lists.freedesktop.org > https://lists.freedesktop.org/mailman/listinfo/intel-gfx -- Daniel Vetter Software Engineer, Intel Corporation http://blog.ffwll.ch ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/intel-gfx
Re: [Intel-gfx] [PATCH 2/4] drm/i915/lspcon: Fix resume time initialization due to unasserted HPD
Reviewed-by: Shashank Sharma Regards Shashank On 1/29/2017 9:43 PM, Imre Deak wrote: On Sun, Jan 29, 2017 at 10:33:07AM +0530, Sharma, Shashank wrote: Regards Shashank On 1/28/2017 1:47 PM, Imre Deak wrote: On Sat, Jan 28, 2017 at 10:32:03AM +0530, Sharma, Shashank wrote: Regards Shashank On 1/27/2017 3:09 PM, Imre Deak wrote: During system resume time initialization the HPD level on LSPCON ports can stay low for an extended amount of time, leading to failed AUX transfers and LSPCON initialization. Fix this by waiting for HPD to get asserted. Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=99178 Cc: Shashank Sharma Cc: Jani Nikula Cc: Ville Syrjälä Cc: Daniel Vetter Cc: # v4.9+ Signed-off-by: Imre Deak --- drivers/gpu/drm/i915/intel_dp.c | 4 ++-- drivers/gpu/drm/i915/intel_drv.h| 2 ++ drivers/gpu/drm/i915/intel_lspcon.c | 5 - 3 files changed, 8 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index e0f9b9e..a7785ce 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -4400,8 +4400,8 @@ static bool bxt_digital_port_connected(struct drm_i915_private *dev_priv, * * Return %true if @port is connected, %false otherwise. */ -static bool intel_digital_port_connected(struct drm_i915_private *dev_priv, -struct intel_digital_port *port) +bool intel_digital_port_connected(struct drm_i915_private *dev_priv, + struct intel_digital_port *port) { if (HAS_PCH_IBX(dev_priv)) return ibx_digital_port_connected(dev_priv, port); diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index b71fece..b9cde11 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -1489,6 +1489,8 @@ bool __intel_dp_read_desc(struct intel_dp *intel_dp, bool intel_dp_read_desc(struct intel_dp *intel_dp); int intel_dp_link_required(int pixel_clock, int bpp); int intel_dp_max_data_rate(int max_link_clock, int max_lanes); +bool intel_digital_port_connected(struct drm_i915_private *dev_priv, + struct intel_digital_port *port); /* intel_dp_aux_backlight.c */ int intel_dp_aux_init_backlight_funcs(struct intel_connector *intel_connector); diff --git a/drivers/gpu/drm/i915/intel_lspcon.c b/drivers/gpu/drm/i915/intel_lspcon.c index f6d4e69..c300647 100644 --- a/drivers/gpu/drm/i915/intel_lspcon.c +++ b/drivers/gpu/drm/i915/intel_lspcon.c @@ -158,6 +158,8 @@ static bool lspcon_probe(struct intel_lspcon *lspcon) static void lspcon_resume_in_pcon_wa(struct intel_lspcon *lspcon) { struct intel_dp *intel_dp = lspcon_to_intel_dp(lspcon); + struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp); + struct drm_i915_private *dev_priv = to_i915(dig_port->base.base.dev); unsigned long start = jiffies; if (!lspcon->desc_valid) @@ -173,7 +175,8 @@ static void lspcon_resume_in_pcon_wa(struct intel_lspcon *lspcon) if (!__intel_dp_read_desc(intel_dp, &desc)) return; - if (!memcmp(&intel_dp->desc, &desc, sizeof(desc))) { + if (intel_digital_port_connected(dev_priv, dig_port) && when in PCON mode, live_status is always up for LSPCON port, so this check will be always true, isn't it ? Not at least in case of the MegaChips LSPCON I've seen, there it takes a while for HPD to get asserted. And while it's not asserted AUX transactions will either: - return garbage in case of native AUX transactions - hang the chip/FW until next cold reboot in case of I2C-over-AUX transactions - simply not get a reply if the chip/FW initialization has reached a certain phase Based on the DP specification the sink/branch device is not required to respond in case the HPD is not asserted, so the 3rd scenario is compliant, but the first two are not. In PCON mode after initialization and HPD getting asserted, HPD will stay asserted except for the short pulses signaling an output connect/disconnect. The reason might be, that LSPCON resumes in LS type2 adapter state, where the live_status behavior is normal and reflects the real HPD line, but the moment we move to PCON mode, HPD gets asserted low. No, this chip/firmware resumes in PCON mode not in LS mode. Otherwise native AUX transfers wouldn't return any reply (per LSPCON specification) and HPD wouldn't get asserted on its own without a display connected. Notice that we only check the LS/PCON state and change it to PCON mode if necessary only after HPD gets asserted. --Imre I know you would have tested this well, but I also want to test this code and logic first, before we go ahead with the patch. Shashank --Imre - Shashank + !memcmp(&intel_dp->desc, &desc, sizeof(desc))) { DRM_DEBUG_KMS("LSPCON recovering in PCON mode after %u ms\n"
Re: [Intel-gfx] [PATCH 3/4] drm/i915/lspcon: Remove DPCD compare based resume time workaround
Reviewed-by: Shashank Sharma Regards Shashank On 1/28/2017 1:49 PM, Imre Deak wrote: On Sat, Jan 28, 2017 at 10:36:16AM +0530, Sharma, Shashank wrote: Regards Shashank On 1/27/2017 3:09 PM, Imre Deak wrote: This effectively reverts commit 489375c866c111f16cea93b2467ebe59c9022cc7 Author: Imre Deak Date: Mon Oct 24 19:33:31 2016 +0300 drm/i915/lspcon: Add workaround for resuming in PCON mode The workaround was added without considering that HPD is low during the failed AUX transfers the WA fixed. Since the previous patch we wait for HPD to get asserted. My tests also show that this happens _after_ the DPCD reads start to return correct values. This suggests that we don't need this WA any more, let's try to remove it to reduce the clutter. Cc: Shashank Sharma Cc: Jani Nikula Cc: Ville Syrjälä Cc: Daniel Vetter Signed-off-by: Imre Deak --- drivers/gpu/drm/i915/intel_drv.h| 1 - drivers/gpu/drm/i915/intel_lspcon.c | 17 ++--- 2 files changed, 2 insertions(+), 16 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index b9cde11..b2882ff 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -989,7 +989,6 @@ struct intel_dp { struct intel_lspcon { bool active; enum drm_lspcon_mode mode; - bool desc_valid; }; struct intel_digital_port { diff --git a/drivers/gpu/drm/i915/intel_lspcon.c b/drivers/gpu/drm/i915/intel_lspcon.c index c300647..71cbe9c 100644 --- a/drivers/gpu/drm/i915/intel_lspcon.c +++ b/drivers/gpu/drm/i915/intel_lspcon.c @@ -162,21 +162,8 @@ static void lspcon_resume_in_pcon_wa(struct intel_lspcon *lspcon) struct drm_i915_private *dev_priv = to_i915(dig_port->base.base.dev); unsigned long start = jiffies; - if (!lspcon->desc_valid) - return; - while (1) { - struct intel_dp_desc desc; - - /* -* The w/a only applies in PCON mode and we don't expect any -* AUX errors. -*/ - if (!__intel_dp_read_desc(intel_dp, &desc)) - return; - - if (intel_digital_port_connected(dev_priv, dig_port) && - !memcmp(&intel_dp->desc, &desc, sizeof(desc))) { + if (intel_digital_port_connected(dev_priv, dig_port)) { Again, does it matter, as in PCON mode live_status will be always true ? See my answer for the previous patch. - Shashank DRM_DEBUG_KMS("LSPCON recovering in PCON mode after %u ms\n", jiffies_to_msecs(jiffies - start)); return; @@ -253,7 +240,7 @@ bool lspcon_init(struct intel_digital_port *intel_dig_port) return false; } - lspcon->desc_valid = intel_dp_read_desc(dp); + intel_dp_read_desc(dp); DRM_DEBUG_KMS("Success: LSPCON init\n"); return true; ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/intel-gfx
Re: [Intel-gfx] [PATCH] drm/i915: fix i915 running as dom0 under Xen
On Thu, Feb 02, 2017 at 11:48:21AM +0100, Daniel Vetter wrote: > On Thu, Feb 02, 2017 at 10:47:11AM +0100, Juergen Gross wrote: > > Commit 920cf4194954ec ("drm/i915: Introduce an internal allocator for > > disposable private objects") introduced a regression for the kernel > > running as Xen dom0: when switching to graphics mode a GPU HANG > > occurred. > > > > Reason seems to be a missing adaption similar to that done in > > commit 7453c549f5f648 ("swiotlb: Export swiotlb_max_segment to users") > > to i915_gem_object_get_pages_internal(). > > > > So limit the maximum page order to be used according to the maximum > > swiotlb segment size instead to the complete swiotlb size. > > > > Signed-off-by: Juergen Gross > Fixes: 920cf4194954 ("drm/i915: Introduce an internal allocator for > disposable private objects") > Cc: Chris Wilson > Cc: Tvrtko Ursulin > Cc: Daniel Vetter > Cc: Jani Nikula > Cc: intel-gfx@lists.freedesktop.org > Cc: # v4.10-rc1+ > > We have a nice script for these :-) Pffifle. 7453c549f5f648 allowed Xen to change it and silently conflicted with those that already used the previous limits, which didn't land in our tree until v4.10-rc3. -Chris -- Chris Wilson, Intel Open Source Technology Centre ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/intel-gfx
Re: [Intel-gfx] [PATCH] drm/i915/dp: Read link status more times when EQ not done
On Thu, 02 Feb 2017, "Lee, Shawn C" wrote: > From: "Lee, Shawn C" > > When user space link status, display driver read DPCD register > 0x202, 0x203 and 0x204 to identify sink status. When PSR exit > is ongoing before EQ done. Panel will report EQ & symbol lock > not done. Both of them are under progressing at the same time > to cause this issue. > > This WA try to read link status more times if EQ not done. > Panel spec request at least 1000us for fast link train when > PSR exit. So driver will wait 1000us~1500us then retrieve > sink link status again. I'm not sure about the patch, but no matter what it needs to be rebased on top of current drm-tip to even be considered. If you're working around a specific eDP PSR issue, why do this on *all* DP? BR, Jani. > > Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=99639 > TEST=Reboot DUT and no flicking on local display at login screen > > Cc: Cooper Chiou > Cc: Wei Shun Chen > Cc: Gary C Wang > Cc: Jani Nikula > > Signed-off-by: Lee, Shawn C > --- > drivers/gpu/drm/i915/intel_dp.c | 33 - > 1 file changed, 28 insertions(+), 5 deletions(-) > > diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c > index e80d620846c8..a9a6ce476438 100644 > --- a/drivers/gpu/drm/i915/intel_dp.c > +++ b/drivers/gpu/drm/i915/intel_dp.c > @@ -4136,13 +4136,36 @@ static void intel_dp_handle_test_request(struct > intel_dp *intel_dp) > return; > > /* if link training is requested we should perform it always */ > - if ((intel_dp->compliance.test_type == DP_TEST_LINK_TRAINING) || > - (!drm_dp_channel_eq_ok(link_status, intel_dp->lane_count))) { > - DRM_DEBUG_KMS("%s: channel EQ not ok, retraining\n", > - intel_encoder->base.name); > + if (intel_dp->compliance.test_type == DP_TEST_LINK_TRAINING) { > + DRM_DEBUG_KMS("%s: compliance test mode, retraining\n", > + intel_encoder->base.name); > + } else { > + u8 retry; > + > + for (retry = 0; retry < 3; retry++) { > + if (!drm_dp_channel_eq_ok(link_status, > intel_dp->lane_count)) { > + /* > + * EQ not ok may caused by fast link train > while exit PSR active, > + * wait at least 1000 us then read it again. > + */ > + DRM_DEBUG_KMS("%s: channel EQ not ok, retry = > %d, DPCD 0x202 = 0x%x, 0x203 = 0x%x, 0x204 = 0x%x\n", > + intel_encoder->base.name, retry, > link_status[0], link_status[1], link_status[2]); > + usleep_range(1000, 1500); > + if (!intel_dp_get_link_status(intel_dp, > link_status)) { > + DRM_ERROR("Failed to get link > status\n"); > + return; > + } > + } else { > + /* channel EQ is fine */ > + return; > + } > + } > > - intel_dp_retrain_link(intel_dp); > + DRM_DEBUG_KMS("%s: channel EQ not ok, retraining\n", > + intel_encoder->base.name); > } > + > + intel_dp_retrain_link(intel_dp); > } > > /* -- Jani Nikula, Intel Open Source Technology Center ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/intel-gfx
[Intel-gfx] [PATCH i-g-t v2] tests/kms_plane_multiple: Test only with maximum number of planes
To be more suitable for BAT testing, let's modify the test such a way that it only uses the maximum number of available planes. This reduces the total number of subtests. v2: Fix broken kms_plane_multiple --list-subtests (Petri) Cc: Petri Latvala Cc: Robert Foss Signed-off-by: Mika Kahola --- tests/kms_plane_multiple.c | 141 + 1 file changed, 65 insertions(+), 76 deletions(-) diff --git a/tests/kms_plane_multiple.c b/tests/kms_plane_multiple.c index bb84878..4930286 100644 --- a/tests/kms_plane_multiple.c +++ b/tests/kms_plane_multiple.c @@ -171,7 +171,7 @@ create_fb_for_mode_position(data_t *data, igt_output_t *output, drmModeModeInfo mode->hdisplay, mode->vdisplay, color->red, color->green, color->blue); - for (int i = 0; i <= max_planes; i++) { + for (int i = 0; i < max_planes; i++) { if (data->plane[i]->type == DRM_PLANE_TYPE_PRIMARY) continue; igt_paint_color(cr, rect_x[i], rect_y[i], @@ -211,7 +211,7 @@ prepare_planes(data_t *data, enum pipe pipe_id, color_t *color, /* planes with random positions */ x[primary->index] = 0; y[primary->index] = 0; - for (i = 1; i <= max_planes; i++) { + for (i = 0; i < max_planes; i++) { igt_plane_t *plane = igt_output_get_plane(output, i); if (plane->type == DRM_PLANE_TYPE_PRIMARY) @@ -247,7 +247,7 @@ prepare_planes(data_t *data, enum pipe pipe_id, color_t *color, static void test_atomic_plane_position_with_output(data_t *data, enum pipe pipe, igt_output_t *output, int n_planes, - int max_planes, uint64_t tiling) + uint64_t tiling) { char buf[256]; struct drm_event *e = (void *)buf; @@ -270,7 +270,7 @@ test_atomic_plane_position_with_output(data_t *data, enum pipe pipe, } igt_info("Testing connector %s using pipe %s with %d planes %s with seed %d\n", -igt_output_name(output), kmstest_pipe_name(pipe), max_planes, +igt_output_name(output), kmstest_pipe_name(pipe), n_planes, info, opt.seed); test_init(data, pipe, n_planes); @@ -280,7 +280,7 @@ test_atomic_plane_position_with_output(data_t *data, enum pipe pipe, i = 0; while (i < iterations || loop_forever) { - prepare_planes(data, pipe, &blue, tiling, max_planes, output); + prepare_planes(data, pipe, &blue, tiling, n_planes, output); vblank_start = kmstest_get_vblank(data->display.drm_fd, pipe, DRM_VBLANK_NEXTONMISS); @@ -316,7 +316,7 @@ test_atomic_plane_position_with_output(data_t *data, enum pipe pipe, static void test_legacy_plane_position_with_output(data_t *data, enum pipe pipe, igt_output_t *output, int n_planes, - int max_planes, uint64_t tiling) + uint64_t tiling) { test_position_t test = { .data = data }; color_t blue = { 0.0f, 0.0f, 1.0f }; @@ -336,7 +336,7 @@ test_legacy_plane_position_with_output(data_t *data, enum pipe pipe, } igt_info("Testing connector %s using pipe %s with %d planes %s with seed %d\n", -igt_output_name(output), kmstest_pipe_name(pipe), max_planes, +igt_output_name(output), kmstest_pipe_name(pipe), n_planes, info, opt.seed); test_init(data, pipe, n_planes); @@ -346,7 +346,7 @@ test_legacy_plane_position_with_output(data_t *data, enum pipe pipe, i = 0; while (i < iterations || loop_forever) { - prepare_planes(data, pipe, &blue, tiling, max_planes, output); + prepare_planes(data, pipe, &blue, tiling, n_planes, output); igt_display_commit2(&data->display, COMMIT_LEGACY); @@ -365,19 +365,16 @@ test_legacy_plane_position_with_output(data_t *data, enum pipe pipe, } static void -test_plane_position(data_t *data, enum pipe pipe, bool atomic, int n_planes, - int max_planes, uint64_t tiling) +test_plane_position(data_t *data, enum pipe pipe, bool atomic, uint64_t tiling) { igt_output_t *output; int connected_outs; int devid = intel_get_drm_devid(data->drm_fd); + int n_planes = data->display.pipes[pipe].n_planes; if (atomic) igt_require(data->display.is_atomic); - igt_skip_on(pipe >= data->display.n_pipes); - igt_skip_on(max_planes >= data->display.pipes[pipe].n_planes); - if ((tiling == LOCAL_I915_FORMAT_MOD_Y_TILED || tiling == LOCAL_I915_FORMAT_MOD_Yf_TILED)) igt_require(AT_LEAST_GEN(devid, 9)); @@ -392,14 +389,12 @@ test_plane
Re: [Intel-gfx] [PATCH 1/6] drm: Add SCDC helpers
On Wed, 01 Feb 2017, Shashank Sharma wrote: > From: Thierry Reding > > SCDC is a mechanism defined in the HDMI 2.0 specification that allows > the source and sink devices to communicate. > > This commit introduces helpers to access the SCDC and provides the > symbolic names for the various registers defined in the specification. > > Signed-off-by: Thierry Reding One process note, you need to add your own Signed-off-by under the original author's sign-off, even when you're posting them unchanged. Signed-off-by means https://developercertificate.org/ BR, Jani. > --- > Documentation/gpu/drm-kms-helpers.rst | 12 > drivers/gpu/drm/Makefile | 3 +- > drivers/gpu/drm/drm_scdc_helper.c | 111 > include/drm/drm_scdc_helper.h | 132 > ++ > 4 files changed, 257 insertions(+), 1 deletion(-) > create mode 100644 drivers/gpu/drm/drm_scdc_helper.c > create mode 100644 include/drm/drm_scdc_helper.h > > diff --git a/Documentation/gpu/drm-kms-helpers.rst > b/Documentation/gpu/drm-kms-helpers.rst > index 03040aa..7592756 100644 > --- a/Documentation/gpu/drm-kms-helpers.rst > +++ b/Documentation/gpu/drm-kms-helpers.rst > @@ -217,6 +217,18 @@ EDID Helper Functions Reference > .. kernel-doc:: drivers/gpu/drm/drm_edid.c > :export: > > +SCDC Helper Functions Reference > +=== > + > +.. kernel-doc:: drivers/gpu/drm/drm_scdc_helper.c > + :doc: scdc helpers > + > +.. kernel-doc:: include/drm/drm_scdc_helper.h > + :internal: > + > +.. kernel-doc:: drivers/gpu/drm/drm_scdc_helper.c > + :export: > + > Rectangle Utilities Reference > = > > diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile > index 92de399..ad91cd9 100644 > --- a/drivers/gpu/drm/Makefile > +++ b/drivers/gpu/drm/Makefile > @@ -31,7 +31,8 @@ drm-$(CONFIG_DEBUG_FS) += drm_debugfs.o drm_debugfs_crc.o > drm_kms_helper-y := drm_crtc_helper.o drm_dp_helper.o drm_probe_helper.o \ > drm_plane_helper.o drm_dp_mst_topology.o drm_atomic_helper.o \ > drm_kms_helper_common.o drm_dp_dual_mode_helper.o \ > - drm_simple_kms_helper.o drm_modeset_helper.o > + drm_simple_kms_helper.o drm_modeset_helper.o \ > + drm_scdc_helper.o > > drm_kms_helper-$(CONFIG_DRM_LOAD_EDID_FIRMWARE) += drm_edid_load.o > drm_kms_helper-$(CONFIG_DRM_FBDEV_EMULATION) += drm_fb_helper.o > diff --git a/drivers/gpu/drm/drm_scdc_helper.c > b/drivers/gpu/drm/drm_scdc_helper.c > new file mode 100644 > index 000..fe0e121 > --- /dev/null > +++ b/drivers/gpu/drm/drm_scdc_helper.c > @@ -0,0 +1,111 @@ > +/* > + * Copyright (c) 2015 NVIDIA Corporation. All rights reserved. > + * > + * Permission is hereby granted, free of charge, to any person obtaining a > + * copy of this software and associated documentation files (the "Software"), > + * to deal in the Software without restriction, including without limitation > + * the rights to use, copy, modify, merge, publish, distribute, sub license, > + * and/or sell copies of the Software, and to permit persons to whom the > + * Software is furnished to do so, subject to the following conditions: > + * > + * The above copyright notice and this permission notice (including the > + * next paragraph) shall be included in all copies or substantial portions > + * of the Software. > + * > + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR > + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, > + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL > + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER > + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING > + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER > + * DEALINGS IN THE SOFTWARE. > + */ > + > +#include > + > +#include > + > +/** > + * DOC: scdc helpers > + * > + * Status and Control Data Channel (SCDC) is a mechanism introduced by the > + * HDMI 2.0 specification. It is a point-to-point protocol that allows the > + * HDMI source and HDMI sink to exchange data. The same I2C interface that > + * is used to access EDID serves as the transport mechanism for SCDC. > + */ > + > +#define SCDC_I2C_SLAVE_ADDRESS 0x54 > + > +/** > + * drm_scdc_read - read a block of data from SCDC > + * @adapter: I2C controller > + * @offset: start offset of block to read > + * @buffer: return location for the block to read > + * @size: size of the block to read > + * > + * Reads a block of data from SCDC, starting at a given offset. > + * > + * Returns: > + * The number of bytes read from SCDC or a negative error code on failure. > + */ > +ssize_t drm_scdc_read(struct i2c_adapter *adapter, u8 offset, void *buffer, > + size_t size) > +{ > + struct i2c_msg msgs[2] = { > + { > + .addr = SCDC_I2C_SL
[Intel-gfx] ✗ Fi.CI.BAT: failure for series starting with [v6] drm: Provide a driver hook for drm_dev_release() (rev2)
== Series Details == Series: series starting with [v6] drm: Provide a driver hook for drm_dev_release() (rev2) URL : https://patchwork.freedesktop.org/series/18974/ State : failure == Summary == CC [M] drivers/gpu/drm/i915/gvt/firmware.o CC [M] drivers/gpu/drm/i915/gvt/trace_points.o CC [M] drivers/gpu/drm/i915/gvt/vgpu.o CC [M] drivers/gpu/drm/i915/gvt/interrupt.o CC [M] drivers/gpu/drm/i915/gvt/display.o CC [M] drivers/gpu/drm/i915/gvt/mmio.o CC [M] drivers/gpu/drm/i915/gvt/cfg_space.o CC [M] drivers/gpu/drm/i915/gvt/edid.o CC [M] drivers/gpu/drm/i915/gvt/opregion.o CC [M] drivers/gpu/drm/i915/gvt/scheduler.o CC [M] drivers/gpu/drm/i915/gvt/execlist.o CC [M] drivers/gpu/drm/i915/gvt/gtt.o CC [M] drivers/gpu/drm/i915/gvt/sched_policy.o CC [M] drivers/gpu/drm/i915/gvt/render.o CC [M] drivers/gpu/drm/i915/intel_lpe_audio.o CC [M] drivers/gpu/drm/i915/gvt/cmd_parser.o LD drivers/tty/serial/8250/8250.o LD [M] drivers/mmc/core/mmc_block.o LD drivers/usb/storage/usb-storage.o LD drivers/mmc/built-in.o LD drivers/usb/storage/built-in.o LD lib/raid6/raid6_pq.o LD [M] drivers/gpu/drm/vgem/vgem.o LD lib/raid6/built-in.o LD drivers/scsi/scsi_mod.o LD drivers/acpi/acpica/acpi.o LD drivers/video/console/built-in.o LD drivers/video/built-in.o LD drivers/spi/built-in.o LD drivers/acpi/acpica/built-in.o LD [M] drivers/net/ethernet/intel/e1000/e1000.o LD drivers/usb/gadget/libcomposite.o LD net/ipv6/ipv6.o LD drivers/acpi/built-in.o LD net/ipv6/built-in.o LD drivers/usb/gadget/udc/udc-core.o LD drivers/usb/gadget/udc/built-in.o LD drivers/usb/gadget/built-in.o In file included from drivers/gpu/drm/i915/i915_gem_gtt.c:3764:0: drivers/gpu/drm/i915/selftests/i915_gem_gtt.c: In function ‘igt_ggtt_page’: drivers/gpu/drm/i915/selftests/i915_gem_gtt.c:715:8: error: ‘DRM_MM_INSERT_LOW’ undeclared (first use in this function) DRM_MM_INSERT_LOW); ^ drivers/gpu/drm/i915/selftests/i915_gem_gtt.c:715:8: note: each undeclared identifier is reported only once for each function it appears in drivers/gpu/drm/i915/selftests/i915_gem_gtt.c:711:8: error: too many arguments to function ‘drm_mm_insert_node_in_range’ err = drm_mm_insert_node_in_range(&ggtt->base.mm, &tmp, ^ In file included from ./include/drm/drmP.h:75:0, from drivers/gpu/drm/i915/i915_gem_gtt.c:31: ./include/drm/drm_mm.h:356:19: note: declared here static inline int drm_mm_insert_node_in_range(struct drm_mm *mm, ^ LD drivers/gpu/drm/drm.o scripts/Makefile.build:293: recipe for target 'drivers/gpu/drm/i915/i915_gem_gtt.o' failed make[4]: *** [drivers/gpu/drm/i915/i915_gem_gtt.o] Error 1 make[4]: *** Waiting for unfinished jobs LD drivers/scsi/sd_mod.o LD [M] sound/pci/hda/snd-hda-codec-generic.o LD drivers/scsi/built-in.o LD sound/pci/built-in.o LD sound/built-in.o LD drivers/tty/serial/8250/8250_base.o LD drivers/tty/serial/8250/built-in.o LD drivers/tty/serial/built-in.o LD net/ipv4/built-in.o LD [M] drivers/net/ethernet/intel/igb/igb.o LD drivers/md/md-mod.o LD drivers/md/built-in.o AR lib/lib.a LD drivers/usb/core/usbcore.o EXPORTS lib/lib-ksyms.o LD drivers/usb/core/built-in.o CC arch/x86/kernel/cpu/capflags.o LD arch/x86/kernel/cpu/built-in.o LD arch/x86/kernel/built-in.o LD drivers/tty/vt/built-in.o LD drivers/tty/built-in.o LD lib/built-in.o LD fs/btrfs/btrfs.o LD arch/x86/built-in.o LD fs/btrfs/built-in.o LD drivers/usb/host/xhci-hcd.o LD fs/ext4/ext4.o LD fs/ext4/built-in.o LD fs/built-in.o LD drivers/usb/host/built-in.o LD drivers/usb/built-in.o LD [M] drivers/net/ethernet/intel/e1000e/e1000e.o LD net/core/built-in.o LD net/built-in.o LD drivers/net/ethernet/built-in.o LD drivers/net/built-in.o scripts/Makefile.build:551: recipe for target 'drivers/gpu/drm/i915' failed make[3]: *** [drivers/gpu/drm/i915] Error 2 scripts/Makefile.build:551: recipe for target 'drivers/gpu/drm' failed make[2]: *** [drivers/gpu/drm] Error 2 scripts/Makefile.build:551: recipe for target 'drivers/gpu' failed make[1]: *** [drivers/gpu] Error 2 Makefile:988: recipe for target 'drivers' failed make: *** [drivers] Error 2 ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/intel-gfx
Re: [Intel-gfx] [PATCH] drm/i915: Release the forgotten connector reference
On Thu, Feb 02, 2017 at 08:16:23AM +, Chris Wilson wrote: > On Thu, Feb 02, 2017 at 10:08:57AM +0200, Joonas Lahtinen wrote: > > On ke, 2017-02-01 at 19:58 +, Chris Wilson wrote: > > > The reference was gained in > > > intel_modeset_update_connector_atomic_state() [called from > > > intel_modeset_setup_hw_state()] and is never lost if no client ever > > > performs a modeset. > > > > > > [ 649.836069] WARNING: CPU: 6 PID: 8865 at > > > drivers/gpu/drm/drm_mode_config.c:424 drm_mode_config_cleanup+0x21b/0x290 > > > [drm] > > > [ 649.836078] Modules linked in: i915(-) intel_gtt drm_kms_helper > > > cfbfillrect syscopyarea cfbimgblt sysfillrect sysimgblt fb_sys_fops > > > cfbcopyarea drm > > > [ 649.836099] CPU: 6 PID: 8865 Comm: drv_selftest Not tainted > > > 4.10.0-rc6+ #908 > > > [ 649.836106] Hardware name: Intel Corporation 2012 Client > > > Platform/Emerald Lake 2, BIOS ACRVMBY1.86C.0078.P00.1201161002 01/16/2012 > > > [ 649.836114] Call Trace: > > > [ 649.836125] dump_stack+0x4d/0x6f > > > [ 649.836136] __warn+0xc1/0xe0 > > > [ 649.836144] warn_slowpath_null+0x18/0x20 > > > [ 649.836163] drm_mode_config_cleanup+0x21b/0x290 [drm] > > > [ 649.836213] intel_modeset_cleanup+0x59/0xa0 [i915] > > > [ 649.836242] i915_driver_unload+0x84/0x170 [i915] > > > [ 649.836277] i915_pci_remove+0x14/0x20 [i915] > > > [ 649.836287] pci_device_remove+0x28/0x60 > > > [ 649.836301] device_release_driver_internal+0x132/0x1d0 > > > [ 649.836313] driver_detach+0x3a/0x80 > > > [ 649.836324] bus_remove_driver+0x47/0xa0 > > > [ 649.836335] driver_unregister+0x27/0x50 > > > [ 649.836344] pci_unregister_driver+0x34/0xa0 > > > [ 649.836387] i915_exit+0x1a/0x71 [i915] > > > [ 649.836401] SyS_delete_module+0x173/0x1c0 > > > [ 649.836413] entry_SYSCALL_64_fastpath+0x17/0x98 > > > [ 649.836422] RIP: 0033:0x7f8d5a841ee7 > > > [ 649.836432] RSP: 002b:7fff89161a28 EFLAGS: 0206 ORIG_RAX: > > > 00b0 > > > [ 649.836448] RAX: ffda RBX: 55f6cd1db5c0 RCX: > > > 7f8d5a841ee7 > > > [ 649.836458] RDX: RSI: 0800 RDI: > > > 55f6cd1da7b8 > > > [ 649.836467] RBP: 7f8d5aaee440 R08: R09: > > > 7fff89161a58 > > > [ 649.836476] R10: 0062 R11: 0206 R12: > > > > > > [ 649.836486] R13: 55f6cd1d9010 R14: 003a R15: > > > 7fff891609f0 > > > [ 649.836514] ---[ end trace 0e529da316e2a3d1 ]--- > > > [ 649.836536] [drm:drm_mode_config_cleanup [drm]] *ERROR* connector > > > VGA-1 leaked! > > > > > > Signed-off-by: Chris Wilson > > > > Reviewed-by: Joonas Lahtinen > > I'm hoping that this won't be required after Maarten's force disable all > CRTC on unload. We will see. Yeah, I think landing that would be better, but if this is annoying CI or something like that, I'm ok with merging already with a FIXME comment added. -Daniel -- Daniel Vetter Software Engineer, Intel Corporation http://blog.ffwll.ch ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/intel-gfx
[Intel-gfx] [PATCH v4 2/2] drm: kselftest for drm_mm and bottom-up allocation
Check that if we request bottom-up allocation from drm_mm_insert_node() we receive the next available hole from the bottom. Signed-off-by: Chris Wilson Reviewed-by: Joonas Lahtinen --- drivers/gpu/drm/selftests/drm_mm_selftests.h | 1 + drivers/gpu/drm/selftests/test-drm_mm.c | 100 +++ 2 files changed, 101 insertions(+) diff --git a/drivers/gpu/drm/selftests/drm_mm_selftests.h b/drivers/gpu/drm/selftests/drm_mm_selftests.h index 6a4575fdc1c0..37bbdac52896 100644 --- a/drivers/gpu/drm/selftests/drm_mm_selftests.h +++ b/drivers/gpu/drm/selftests/drm_mm_selftests.h @@ -17,6 +17,7 @@ selftest(align32, igt_align32) selftest(align64, igt_align64) selftest(evict, igt_evict) selftest(evict_range, igt_evict_range) +selftest(bottomup, igt_bottomup) selftest(topdown, igt_topdown) selftest(color, igt_color) selftest(color_evict, igt_color_evict) diff --git a/drivers/gpu/drm/selftests/test-drm_mm.c b/drivers/gpu/drm/selftests/test-drm_mm.c index bb5b7480e0b4..1e71bc182ca9 100644 --- a/drivers/gpu/drm/selftests/test-drm_mm.c +++ b/drivers/gpu/drm/selftests/test-drm_mm.c @@ -1697,6 +1697,106 @@ static int igt_topdown(void *ignored) return ret; } +static int igt_bottomup(void *ignored) +{ + const struct insert_mode *bottomup = &insert_modes[BOTTOMUP]; + DRM_RND_STATE(prng, random_seed); + const unsigned int count = 8192; + unsigned int size; + unsigned long *bitmap; + struct drm_mm mm; + struct drm_mm_node *nodes, *node, *next; + unsigned int *order, n, m, o = 0; + int ret; + + /* Like igt_topdown, but instead of searching for the last hole, +* we search for the first. +*/ + + ret = -ENOMEM; + nodes = vzalloc(count * sizeof(*nodes)); + if (!nodes) + goto err; + + bitmap = kzalloc(count / BITS_PER_LONG * sizeof(unsigned long), +GFP_TEMPORARY); + if (!bitmap) + goto err_nodes; + + order = drm_random_order(count, &prng); + if (!order) + goto err_bitmap; + + ret = -EINVAL; + for (size = 1; size <= 64; size <<= 1) { + drm_mm_init(&mm, 0, size*count); + for (n = 0; n < count; n++) { + if (!expect_insert(&mm, &nodes[n], + size, 0, n, + bottomup)) { + pr_err("bottomup insert failed, size %u step %d\n", size, n); + goto out; + } + + if (!assert_one_hole(&mm, size*(n + 1), size*count)) + goto out; + } + + if (!assert_continuous(&mm, size)) + goto out; + + drm_random_reorder(order, count, &prng); + for_each_prime_number_from(n, 1, min(count, max_prime)) { + for (m = 0; m < n; m++) { + node = &nodes[order[(o + m) % count]]; + drm_mm_remove_node(node); + __set_bit(node_index(node), bitmap); + } + + for (m = 0; m < n; m++) { + unsigned int first; + + node = &nodes[order[(o + m) % count]]; + if (!expect_insert(&mm, node, + size, 0, 0, + bottomup)) { + pr_err("insert failed, step %d/%d\n", m, n); + goto out; + } + + first = find_first_bit(bitmap, count); + if (node_index(node) != first) { + pr_err("node %d/%d not inserted into bottom hole, expected %d, found %d\n", + m, n, first, node_index(node)); + goto out; + } + __clear_bit(first, bitmap); + } + + DRM_MM_BUG_ON(find_first_bit(bitmap, count) != count); + + o += n; + } + + drm_mm_for_each_node_safe(node, next, &mm) + drm_mm_remove_node(node); + DRM_MM_BUG_ON(!drm_mm_clean(&mm)); + } + + ret = 0; +out: + drm_mm_for_each_node_safe(node, next, &mm) + drm_mm_remove_node(node); + drm_mm_takedown(&mm); + kfree(order); +err_bitmap: + kfree(bitmap); +err_nodes: + vfree(nodes); +err: + return ret; +} + static void separate_adjacent_colors(const struct drm_mm_node *node, unsigned long color,
[Intel-gfx] [PATCH v4 1/2] drm: Improve drm_mm search (and fix topdown allocation) with rbtrees
The drm_mm range manager claimed to support top-down insertion, but it was neither searching for the top-most hole that could fit the allocation request nor fitting the request to the hole correctly. In order to search the range efficiently, we create a secondary index for the holes using either their size or their address. This index allows us to find the smallest hole or the hole at the bottom or top of the range efficiently, whilst keeping the hole stack to rapidly service evictions. v2: Search for holes both high and low. Rename flags to mode. v3: Discover rb_entry_safe() and use it! v4: Kerneldoc for enum drm_mm_insert_mode. Signed-off-by: Chris Wilson Reviewed-by: Joonas Lahtinen Cc: Alex Deucher Cc: "Christian König" Cc: David Airlie Cc: Russell King Cc: Daniel Vetter Cc: Jani Nikula Cc: Sean Paul Cc: Lucas Stach Cc: Christian Gmeiner Cc: Rob Clark Cc: Thierry Reding Cc: Stephen Warren Cc: Alexandre Courbot Cc: Eric Anholt Cc: Sinclair Yeh Cc: Thomas Hellstrom --- drivers/gpu/drm/amd/amdgpu/amdgpu_gtt_mgr.c | 16 +- drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c | 20 +- drivers/gpu/drm/armada/armada_gem.c | 4 +- drivers/gpu/drm/drm_mm.c | 488 +++ drivers/gpu/drm/drm_vma_manager.c| 3 +- drivers/gpu/drm/etnaviv/etnaviv_mmu.c| 16 +- drivers/gpu/drm/i915/i915_gem.c | 10 +- drivers/gpu/drm/i915/i915_gem_evict.c| 9 +- drivers/gpu/drm/i915/i915_gem_execbuffer.c | 5 +- drivers/gpu/drm/i915/i915_gem_gtt.c | 39 +-- drivers/gpu/drm/i915/i915_gem_stolen.c | 6 +- drivers/gpu/drm/msm/msm_gem.c| 3 +- drivers/gpu/drm/msm/msm_gem_vma.c| 3 +- drivers/gpu/drm/selftests/test-drm_mm.c | 58 ++-- drivers/gpu/drm/sis/sis_mm.c | 6 +- drivers/gpu/drm/tegra/gem.c | 4 +- drivers/gpu/drm/ttm/ttm_bo_manager.c | 18 +- drivers/gpu/drm/vc4/vc4_crtc.c | 2 +- drivers/gpu/drm/vc4/vc4_hvs.c| 3 +- drivers/gpu/drm/vc4/vc4_plane.c | 6 +- drivers/gpu/drm/via/via_mm.c | 4 +- drivers/gpu/drm/vmwgfx/vmwgfx_cmdbuf.c | 10 +- include/drm/drm_mm.h | 184 +- 23 files changed, 470 insertions(+), 447 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gtt_mgr.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_gtt_mgr.c index e4eb6dd3798a..0335c2f331e9 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gtt_mgr.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gtt_mgr.c @@ -97,8 +97,7 @@ int amdgpu_gtt_mgr_alloc(struct ttm_mem_type_manager *man, { struct amdgpu_gtt_mgr *mgr = man->priv; struct drm_mm_node *node = mem->mm_node; - enum drm_mm_search_flags sflags = DRM_MM_SEARCH_BEST; - enum drm_mm_allocator_flags aflags = DRM_MM_CREATE_DEFAULT; + enum drm_mm_insert_mode mode; unsigned long fpfn, lpfn; int r; @@ -115,15 +114,14 @@ int amdgpu_gtt_mgr_alloc(struct ttm_mem_type_manager *man, else lpfn = man->size; - if (place && place->flags & TTM_PL_FLAG_TOPDOWN) { - sflags = DRM_MM_SEARCH_BELOW; - aflags = DRM_MM_CREATE_TOP; - } + mode = DRM_MM_INSERT_BEST; + if (place && place->flags & TTM_PL_FLAG_TOPDOWN) + mode = DRM_MM_INSERT_HIGH; spin_lock(&mgr->lock); - r = drm_mm_insert_node_in_range_generic(&mgr->mm, node, mem->num_pages, - mem->page_alignment, 0, - fpfn, lpfn, sflags, aflags); + r = drm_mm_insert_node_in_range(&mgr->mm, node, + mem->num_pages, mem->page_alignment, 0, + fpfn, lpfn, mode); spin_unlock(&mgr->lock); if (!r) { diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c index ac9007986c11..9e577e3d3147 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c @@ -97,8 +97,7 @@ static int amdgpu_vram_mgr_new(struct ttm_mem_type_manager *man, struct amdgpu_vram_mgr *mgr = man->priv; struct drm_mm *mm = &mgr->mm; struct drm_mm_node *nodes; - enum drm_mm_search_flags sflags = DRM_MM_SEARCH_DEFAULT; - enum drm_mm_allocator_flags aflags = DRM_MM_CREATE_DEFAULT; + enum drm_mm_insert_mode mode; unsigned long lpfn, num_nodes, pages_per_node, pages_left; unsigned i; int r; @@ -121,10 +120,9 @@ static int amdgpu_vram_mgr_new(struct ttm_mem_type_manager *man, if (!nodes) return -ENOMEM; - if (place->flags & TTM_PL_FLAG_TOPDOWN) { - sflags = DRM_MM_SEARCH_BELOW; - aflags = DRM_MM_CREATE_TOP; - } + mode = DRM_MM_INSERT_BEST; +
Re: [Intel-gfx] [PATCH 1/6] drm: Add SCDC helpers
Sure, Thanks for the information, will add that in V2. Regards Shashank -Original Message- From: Jani Nikula [mailto:jani.nik...@linux.intel.com] Sent: Thursday, February 2, 2017 4:55 PM To: Sharma, Shashank ; dri-de...@lists.freedesktop.org; intel-gfx@lists.freedesktop.org; ville.syrj...@linux.intel.com Cc: jose.ab...@synopsys.com; =daniel.vet...@intel.com; Thierry Reding ; thierry.red...@gmail.com Subject: Re: [Intel-gfx] [PATCH 1/6] drm: Add SCDC helpers On Wed, 01 Feb 2017, Shashank Sharma wrote: > From: Thierry Reding > > SCDC is a mechanism defined in the HDMI 2.0 specification that allows > the source and sink devices to communicate. > > This commit introduces helpers to access the SCDC and provides the > symbolic names for the various registers defined in the specification. > > Signed-off-by: Thierry Reding One process note, you need to add your own Signed-off-by under the original author's sign-off, even when you're posting them unchanged. Signed-off-by means https://developercertificate.org/ BR, Jani. > --- > Documentation/gpu/drm-kms-helpers.rst | 12 > drivers/gpu/drm/Makefile | 3 +- > drivers/gpu/drm/drm_scdc_helper.c | 111 > include/drm/drm_scdc_helper.h | 132 > ++ > 4 files changed, 257 insertions(+), 1 deletion(-) create mode 100644 > drivers/gpu/drm/drm_scdc_helper.c create mode 100644 > include/drm/drm_scdc_helper.h > > diff --git a/Documentation/gpu/drm-kms-helpers.rst > b/Documentation/gpu/drm-kms-helpers.rst > index 03040aa..7592756 100644 > --- a/Documentation/gpu/drm-kms-helpers.rst > +++ b/Documentation/gpu/drm-kms-helpers.rst > @@ -217,6 +217,18 @@ EDID Helper Functions Reference .. kernel-doc:: > drivers/gpu/drm/drm_edid.c > :export: > > +SCDC Helper Functions Reference > +=== > + > +.. kernel-doc:: drivers/gpu/drm/drm_scdc_helper.c > + :doc: scdc helpers > + > +.. kernel-doc:: include/drm/drm_scdc_helper.h > + :internal: > + > +.. kernel-doc:: drivers/gpu/drm/drm_scdc_helper.c > + :export: > + > Rectangle Utilities Reference > = > > diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile index > 92de399..ad91cd9 100644 > --- a/drivers/gpu/drm/Makefile > +++ b/drivers/gpu/drm/Makefile > @@ -31,7 +31,8 @@ drm-$(CONFIG_DEBUG_FS) += drm_debugfs.o > drm_debugfs_crc.o drm_kms_helper-y := drm_crtc_helper.o drm_dp_helper.o > drm_probe_helper.o \ > drm_plane_helper.o drm_dp_mst_topology.o drm_atomic_helper.o \ > drm_kms_helper_common.o drm_dp_dual_mode_helper.o \ > - drm_simple_kms_helper.o drm_modeset_helper.o > + drm_simple_kms_helper.o drm_modeset_helper.o \ > + drm_scdc_helper.o > > drm_kms_helper-$(CONFIG_DRM_LOAD_EDID_FIRMWARE) += drm_edid_load.o > drm_kms_helper-$(CONFIG_DRM_FBDEV_EMULATION) += drm_fb_helper.o diff > --git a/drivers/gpu/drm/drm_scdc_helper.c > b/drivers/gpu/drm/drm_scdc_helper.c > new file mode 100644 > index 000..fe0e121 > --- /dev/null > +++ b/drivers/gpu/drm/drm_scdc_helper.c > @@ -0,0 +1,111 @@ > +/* > + * Copyright (c) 2015 NVIDIA Corporation. All rights reserved. > + * > + * Permission is hereby granted, free of charge, to any person > +obtaining a > + * copy of this software and associated documentation files (the > +"Software"), > + * to deal in the Software without restriction, including without > +limitation > + * the rights to use, copy, modify, merge, publish, distribute, sub > +license, > + * and/or sell copies of the Software, and to permit persons to whom > +the > + * Software is furnished to do so, subject to the following conditions: > + * > + * The above copyright notice and this permission notice (including > +the > + * next paragraph) shall be included in all copies or substantial > +portions > + * of the Software. > + * > + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, > +EXPRESS OR > + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF > +MERCHANTABILITY, > + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT > +SHALL > + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES > +OR OTHER > + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, > +ARISING > + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR > +OTHER > + * DEALINGS IN THE SOFTWARE. > + */ > + > +#include > + > +#include > + > +/** > + * DOC: scdc helpers > + * > + * Status and Control Data Channel (SCDC) is a mechanism introduced > +by the > + * HDMI 2.0 specification. It is a point-to-point protocol that > +allows the > + * HDMI source and HDMI sink to exchange data. The same I2C interface > +that > + * is used to access EDID serves as the transport mechanism for SCDC. > + */ > + > +#define SCDC_I2C_SLAVE_ADDRESS 0x54 > + > +/** > + * drm_scdc_read - read a block of data from SCDC > + * @
Re: [Intel-gfx] [PATCH] drm/i915: fix i915 running as dom0 under Xen
On 02/02/2017 09:47, Juergen Gross wrote: Commit 920cf4194954ec ("drm/i915: Introduce an internal allocator for disposable private objects") introduced a regression for the kernel running as Xen dom0: when switching to graphics mode a GPU HANG occurred. Reason seems to be a missing adaption similar to that done in commit 7453c549f5f648 ("swiotlb: Export swiotlb_max_segment to users") to i915_gem_object_get_pages_internal(). So limit the maximum page order to be used according to the maximum swiotlb segment size instead to the complete swiotlb size. Signed-off-by: Juergen Gross --- Please consider for 4.10 as otherwise 4.10 will be unusable as Xen dom0 with i915 graphics. --- drivers/gpu/drm/i915/i915_gem_internal.c | 12 ++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_gem_internal.c b/drivers/gpu/drm/i915/i915_gem_internal.c index 4b3ff3e..d09c749 100644 --- a/drivers/gpu/drm/i915/i915_gem_internal.c +++ b/drivers/gpu/drm/i915/i915_gem_internal.c @@ -66,8 +66,16 @@ i915_gem_object_get_pages_internal(struct drm_i915_gem_object *obj) max_order = MAX_ORDER; #ifdef CONFIG_SWIOTLB - if (swiotlb_nr_tbl()) /* minimum max swiotlb size is IO_TLB_SEGSIZE */ - max_order = min(max_order, ilog2(IO_TLB_SEGPAGES)); + if (swiotlb_nr_tbl()) { + unsigned int max_segment; + + max_segment = swiotlb_max_segment(); + if (max_segment) { + max_segment = max_t(unsigned int, max_segment, + PAGE_SIZE) >> PAGE_SHIFT; + max_order = min(max_order, ilog2(max_segment)); + } + } #endif gfp = GFP_KERNEL | __GFP_HIGHMEM | __GFP_RECLAIMABLE; Looks OK to me. We could bikeshed it to only use swiotlb_max_segment() which I think was the intention when that API was added but can leave that for the future. Reviewed-by: Tvrtko Ursulin Regards, Tvrtko ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/intel-gfx
[Intel-gfx] ✗ Fi.CI.BAT: failure for drm/i915: fix i915 running as dom0 under Xen
== Series Details == Series: drm/i915: fix i915 running as dom0 under Xen URL : https://patchwork.freedesktop.org/series/18979/ State : failure == Summary == Series 18979v1 drm/i915: fix i915 running as dom0 under Xen https://patchwork.freedesktop.org/api/1.0/series/18979/revisions/1/mbox/ Test gem_exec_flush: Subgroup basic-wb-ro-default: pass -> INCOMPLETE (fi-byt-j1900) Test kms_pipe_crc_basic: Subgroup nonblocking-crc-pipe-c-frame-sequence: fail -> PASS (fi-skl-6770hq) fi-bdw-5557u total:247 pass:233 dwarn:0 dfail:0 fail:0 skip:14 fi-bsw-n3050 total:247 pass:208 dwarn:0 dfail:0 fail:0 skip:39 fi-bxt-j4205 total:247 pass:225 dwarn:0 dfail:0 fail:0 skip:22 fi-bxt-t5700 total:78 pass:65 dwarn:0 dfail:0 fail:0 skip:12 fi-byt-j1900 total:56 pass:46 dwarn:0 dfail:0 fail:0 skip:9 fi-byt-n2820 total:247 pass:216 dwarn:0 dfail:0 fail:0 skip:31 fi-hsw-4770 total:247 pass:228 dwarn:0 dfail:0 fail:0 skip:19 fi-hsw-4770r total:247 pass:228 dwarn:0 dfail:0 fail:0 skip:19 fi-ivb-3520m total:247 pass:226 dwarn:0 dfail:0 fail:0 skip:21 fi-ivb-3770 total:247 pass:226 dwarn:0 dfail:0 fail:0 skip:21 fi-kbl-7500u total:247 pass:224 dwarn:0 dfail:0 fail:2 skip:21 fi-skl-6260u total:247 pass:234 dwarn:0 dfail:0 fail:0 skip:13 fi-skl-6700hqtotal:247 pass:227 dwarn:0 dfail:0 fail:0 skip:20 fi-skl-6700k total:247 pass:222 dwarn:4 dfail:0 fail:0 skip:21 fi-skl-6770hqtotal:247 pass:234 dwarn:0 dfail:0 fail:0 skip:13 fi-snb-2520m total:247 pass:216 dwarn:0 dfail:0 fail:0 skip:31 fi-snb-2600 total:247 pass:215 dwarn:0 dfail:0 fail:0 skip:32 ce4c6eb9b0d270df56813af310cd918298ac7ba2 drm-tip: 2017y-02m-02d-10h-12m-30s UTC integration manifest a372572 drm/i915: fix i915 running as dom0 under Xen == Logs == For more details see: https://intel-gfx-ci.01.org/CI/Patchwork_3673/ ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/intel-gfx
Re: [Intel-gfx] [PATCH] drm/i915: fix i915 running as dom0 under Xen
On Thu, Feb 02, 2017 at 12:11:29PM +, Tvrtko Ursulin wrote: > > On 02/02/2017 09:47, Juergen Gross wrote: > >Commit 920cf4194954ec ("drm/i915: Introduce an internal allocator for > >disposable private objects") introduced a regression for the kernel > >running as Xen dom0: when switching to graphics mode a GPU HANG > >occurred. > > > >Reason seems to be a missing adaption similar to that done in > >commit 7453c549f5f648 ("swiotlb: Export swiotlb_max_segment to users") > >to i915_gem_object_get_pages_internal(). > > > >So limit the maximum page order to be used according to the maximum > >swiotlb segment size instead to the complete swiotlb size. > > > >Signed-off-by: Juergen Gross > >--- > >Please consider for 4.10 as otherwise 4.10 will be unusable as Xen dom0 > >with i915 graphics. > >--- > > drivers/gpu/drm/i915/i915_gem_internal.c | 12 ++-- > > 1 file changed, 10 insertions(+), 2 deletions(-) > > > >diff --git a/drivers/gpu/drm/i915/i915_gem_internal.c > >b/drivers/gpu/drm/i915/i915_gem_internal.c > >index 4b3ff3e..d09c749 100644 > >--- a/drivers/gpu/drm/i915/i915_gem_internal.c > >+++ b/drivers/gpu/drm/i915/i915_gem_internal.c > >@@ -66,8 +66,16 @@ i915_gem_object_get_pages_internal(struct > >drm_i915_gem_object *obj) > > > > max_order = MAX_ORDER; > > #ifdef CONFIG_SWIOTLB > >-if (swiotlb_nr_tbl()) /* minimum max swiotlb size is IO_TLB_SEGSIZE */ > >-max_order = min(max_order, ilog2(IO_TLB_SEGPAGES)); > >+if (swiotlb_nr_tbl()) { > >+unsigned int max_segment; > >+ > >+max_segment = swiotlb_max_segment(); > >+if (max_segment) { > >+max_segment = max_t(unsigned int, max_segment, > >+PAGE_SIZE) >> PAGE_SHIFT; > >+max_order = min(max_order, ilog2(max_segment)); > >+} > >+} > > #endif > > > > gfp = GFP_KERNEL | __GFP_HIGHMEM | __GFP_RECLAIMABLE; > > > > Looks OK to me. We could bikeshed it to only use > swiotlb_max_segment() which I think was the intention when that API > was added but can leave that for the future. > > Reviewed-by: Tvrtko Ursulin Pushed, I imagine this has been added to the list of sg cleanups you have :) -Chris -- Chris Wilson, Intel Open Source Technology Centre ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/intel-gfx
Re: [Intel-gfx] [PATCH 5/6] drm/i915: enable scrambling
On Thu, Feb 02, 2017 at 04:15:21PM +0530, Sharma, Shashank wrote: > Regards > > Shashank > > > On 2/2/2017 3:32 PM, Ville Syrjälä wrote: > > On Thu, Feb 02, 2017 at 11:23:19AM +0530, Sharma, Shashank wrote: > >> Regards > >> > >> Shashank > >> > >> > >> On 2/1/2017 10:06 PM, Ville Syrjälä wrote: > >>> On Wed, Feb 01, 2017 at 06:14:40PM +0530, Shashank Sharma wrote: > Geminilake platform has a native HDMI 2.0 controller, and is > capable of driving pixel-clocks upto 594Mhz. HDMI 2.0 spec > mendates scrambling for these higher clocks, for reduced RF footprint. > > This patch checks if the monitor supports scrambling, and if required, > enables it during the modeset. > > Signed-off-by: Shashank Sharma > --- > drivers/gpu/drm/i915/i915_reg.h | 2 ++ > drivers/gpu/drm/i915/intel_ddi.c | 5 + > drivers/gpu/drm/i915/intel_drv.h | 2 ++ > drivers/gpu/drm/i915/intel_hdmi.c | 42 > +++ > 4 files changed, 51 insertions(+) > > diff --git a/drivers/gpu/drm/i915/i915_reg.h > b/drivers/gpu/drm/i915/i915_reg.h > index 495b789..cc85892 100644 > --- a/drivers/gpu/drm/i915/i915_reg.h > +++ b/drivers/gpu/drm/i915/i915_reg.h > @@ -7807,6 +7807,8 @@ enum { > #define TRANS_DDI_EDP_INPUT_C_ONOFF (6<<12) > #define TRANS_DDI_DP_VC_PAYLOAD_ALLOC(1<<8) > #define TRANS_DDI_BFI_ENABLE (1<<4) > +#define TRANS_DDI_HIGH_TMDS_CHAR_RATE (1<<4) > +#define TRANS_DDI_HDMI_SCRAMBLING (1<<0) > > /* DisplayPort Transport Control */ > #define _DP_TP_CTL_A 0x64040 > diff --git a/drivers/gpu/drm/i915/intel_ddi.c > b/drivers/gpu/drm/i915/intel_ddi.c > index 9a9a670..aea81ce 100644 > --- a/drivers/gpu/drm/i915/intel_ddi.c > +++ b/drivers/gpu/drm/i915/intel_ddi.c > @@ -1278,6 +1278,11 @@ void intel_ddi_enable_transcoder_func(struct > drm_crtc *crtc) > temp |= TRANS_DDI_MODE_SELECT_HDMI; > else > temp |= TRANS_DDI_MODE_SELECT_DVI; > + > +if (IS_GEMINILAKE(dev_priv)) { > +temp |= > intel_hdmi_check_scrambling(intel_encoder, > + > &intel_crtc->config->base.adjusted_mode); > +} > } else if (type == INTEL_OUTPUT_ANALOG) { > temp |= TRANS_DDI_MODE_SELECT_FDI; > temp |= (intel_crtc->config->fdi_lanes - 1) << 1; > diff --git a/drivers/gpu/drm/i915/intel_drv.h > b/drivers/gpu/drm/i915/intel_drv.h > index 393f243..aafce7f 100644 > --- a/drivers/gpu/drm/i915/intel_drv.h > +++ b/drivers/gpu/drm/i915/intel_drv.h > @@ -1588,6 +1588,8 @@ void intel_hdmi_init_connector(struct > intel_digital_port *intel_dig_port, > bool intel_hdmi_compute_config(struct intel_encoder *encoder, > struct intel_crtc_state *pipe_config, > struct drm_connector_state *conn_state); > +uint32_t intel_hdmi_check_scrambling(struct intel_encoder > *intel_encoder, > +struct drm_display_mode *mode); > void intel_dp_dual_mode_set_tmds_output(struct intel_hdmi *hdmi, bool > enable); > > > diff --git a/drivers/gpu/drm/i915/intel_hdmi.c > b/drivers/gpu/drm/i915/intel_hdmi.c > index ebae2bd..92dd9bc 100644 > --- a/drivers/gpu/drm/i915/intel_hdmi.c > +++ b/drivers/gpu/drm/i915/intel_hdmi.c > @@ -1795,6 +1795,48 @@ static void intel_hdmi_destroy(struct > drm_connector *connector) > intel_hdmi->aspect_ratio = HDMI_PICTURE_ASPECT_NONE; > } > > +static void > +intel_hdmi_enable_scrambling(struct drm_connector *connector) > +{ > +struct drm_i915_private *dev_priv = connector->dev->dev_private; > +struct intel_hdmi *intel_hdmi = intel_attached_hdmi(connector); > +struct i2c_adapter *adapter = > +intel_gmbus_get_adapter(dev_priv, > intel_hdmi->ddc_bus); > + > +if (!drm_enable_scrambling(connector, adapter, true)) > +DRM_ERROR("Request to enable scrambling failed\n"); > +} > >>> I don't like hiding this somewhere deep like this. It should be > >>> somewhere much higher up. > >> Why ? All we need to do here is enable two bits in transcoder control > >> register, which is already being > >> programmed in a calling function, so I dont see the use case, but I > >> might be missing some bigger picture. > >> Can you please elaborate on this ? > > We're talking to the display here, which is rather surprising to happen > > from a function thing that on the fir
Re: [Intel-gfx] [PATCH] drm/i915: Release the forgotten connector reference
On Thu, Feb 02, 2017 at 12:35:26PM +0100, Daniel Vetter wrote: > On Thu, Feb 02, 2017 at 08:16:23AM +, Chris Wilson wrote: > > On Thu, Feb 02, 2017 at 10:08:57AM +0200, Joonas Lahtinen wrote: > > > On ke, 2017-02-01 at 19:58 +, Chris Wilson wrote: > > > > The reference was gained in > > > > intel_modeset_update_connector_atomic_state() [called from > > > > intel_modeset_setup_hw_state()] and is never lost if no client ever > > > > performs a modeset. > > > > > > > > [ 649.836069] WARNING: CPU: 6 PID: 8865 at > > > > drivers/gpu/drm/drm_mode_config.c:424 > > > > drm_mode_config_cleanup+0x21b/0x290 [drm] > > > > [ 649.836078] Modules linked in: i915(-) intel_gtt drm_kms_helper > > > > cfbfillrect syscopyarea cfbimgblt sysfillrect sysimgblt fb_sys_fops > > > > cfbcopyarea drm > > > > [ 649.836099] CPU: 6 PID: 8865 Comm: drv_selftest Not tainted > > > > 4.10.0-rc6+ #908 > > > > [ 649.836106] Hardware name: Intel Corporation 2012 Client > > > > Platform/Emerald Lake 2, BIOS ACRVMBY1.86C.0078.P00.1201161002 > > > > 01/16/2012 > > > > [ 649.836114] Call Trace: > > > > [ 649.836125] dump_stack+0x4d/0x6f > > > > [ 649.836136] __warn+0xc1/0xe0 > > > > [ 649.836144] warn_slowpath_null+0x18/0x20 > > > > [ 649.836163] drm_mode_config_cleanup+0x21b/0x290 [drm] > > > > [ 649.836213] intel_modeset_cleanup+0x59/0xa0 [i915] > > > > [ 649.836242] i915_driver_unload+0x84/0x170 [i915] > > > > [ 649.836277] i915_pci_remove+0x14/0x20 [i915] > > > > [ 649.836287] pci_device_remove+0x28/0x60 > > > > [ 649.836301] device_release_driver_internal+0x132/0x1d0 > > > > [ 649.836313] driver_detach+0x3a/0x80 > > > > [ 649.836324] bus_remove_driver+0x47/0xa0 > > > > [ 649.836335] driver_unregister+0x27/0x50 > > > > [ 649.836344] pci_unregister_driver+0x34/0xa0 > > > > [ 649.836387] i915_exit+0x1a/0x71 [i915] > > > > [ 649.836401] SyS_delete_module+0x173/0x1c0 > > > > [ 649.836413] entry_SYSCALL_64_fastpath+0x17/0x98 > > > > [ 649.836422] RIP: 0033:0x7f8d5a841ee7 > > > > [ 649.836432] RSP: 002b:7fff89161a28 EFLAGS: 0206 ORIG_RAX: > > > > 00b0 > > > > [ 649.836448] RAX: ffda RBX: 55f6cd1db5c0 RCX: > > > > 7f8d5a841ee7 > > > > [ 649.836458] RDX: RSI: 0800 RDI: > > > > 55f6cd1da7b8 > > > > [ 649.836467] RBP: 7f8d5aaee440 R08: R09: > > > > 7fff89161a58 > > > > [ 649.836476] R10: 0062 R11: 0206 R12: > > > > > > > > [ 649.836486] R13: 55f6cd1d9010 R14: 003a R15: > > > > 7fff891609f0 > > > > [ 649.836514] ---[ end trace 0e529da316e2a3d1 ]--- > > > > [ 649.836536] [drm:drm_mode_config_cleanup [drm]] *ERROR* connector > > > > VGA-1 leaked! > > > > > > > > Signed-off-by: Chris Wilson > > > > > > Reviewed-by: Joonas Lahtinen > > > > I'm hoping that this won't be required after Maarten's force disable all > > CRTC on unload. We will see. > > Yeah, I think landing that would be better, but if this is annoying CI or > something like that, I'm ok with merging already with a FIXME comment > added. By itself the first force disable CRTCs on unload wasn't enough, but Maarten has a second patch to apply more force that does. This patch is not required. -Chris -- Chris Wilson, Intel Open Source Technology Centre ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/intel-gfx
Re: [Intel-gfx] [PATCH v2 03/38] drm/i915: Add some selftests for sg_table manipulation
On 01/02/2017 11:34, Chris Wilson wrote: On Wed, Feb 01, 2017 at 11:17:39AM +, Tvrtko Ursulin wrote: + + for (npages = npages_funcs; *npages; npages++) { + prandom_seed_state(&prng, + i915_selftest.random_seed); + if (!alloc_table(&pt, sz, sz, *npages, &prng)) + return 0; /* out of memory, give up */ You don't have skip status? Sounds not ideal to silently abort. It runs until we use all physical memory, if left to its own devices. It's not a skip if we have already completed some tests. ENOMEM of the test setup itself is not what I'm testing for here, the test is for the iterators. But suppose you mess up the test so the starting condition asks for impossible amount of memory but the test claims it passed. I don't think that is a good behaviour. +static int igt_sg_trim(void *ignored) +{ + IGT_TIMEOUT(end_time); + const unsigned long max = PAGE_SIZE; /* not prime! */ + struct pfn_table pt; + unsigned long prime; + + for_each_prime_number(prime, max) { + const npages_fn_t *npages; + int err; + + for (npages = npages_funcs; *npages; npages++) { + struct rnd_state prng; + + prandom_seed_state(&prng, i915_selftest.random_seed); + if (!alloc_table(&pt, prime, max, *npages, &prng)) + return 0; /* out of memory, give up */ + + err = 0; + if (i915_sg_trim(&pt.st)) { + if (pt.st.orig_nents != prime || + pt.st.nents != prime) { + pr_err("i915_sg_trim failed (nents %u, orig_nents %u), expected %lu\n", + pt.st.nents, pt.st.orig_nents, prime); + err = -EINVAL; + } else { + prandom_seed_state(&prng, + i915_selftest.random_seed); + err = expect_pfn_sgtable(&pt, +*npages, &prng, +"i915_sg_trim", +end_time); + } + } Similar to alloc_table failures above - no log or action when i915_sg_trim fails due out of memory? No, simply because that's an expected and acceptable result. The question should be whether we always want to check after sg_trim. Same as above really, I think that creates a big doubt in the test output. Regards, Tvrtko ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/intel-gfx
Re: [Intel-gfx] [PATCH 09/46] drm/i915: Add unit tests for the breadcrumb rbtree, wakeups
On 02/02/2017 09:08, Chris Wilson wrote: Third retroactive test, make sure that the seqno waiters are woken. v2: Smattering of comments, rearrange code v3: Fix assert. Signed-off-by: Chris Wilson --- drivers/gpu/drm/i915/selftests/intel_breadcrumbs.c | 201 + 1 file changed, 201 insertions(+) diff --git a/drivers/gpu/drm/i915/selftests/intel_breadcrumbs.c b/drivers/gpu/drm/i915/selftests/intel_breadcrumbs.c index 32a27e56c353..fb368eb37660 100644 --- a/drivers/gpu/drm/i915/selftests/intel_breadcrumbs.c +++ b/drivers/gpu/drm/i915/selftests/intel_breadcrumbs.c @@ -259,11 +259,212 @@ static int igt_insert_complete(void *arg) return err; } +struct igt_wakeup { + struct task_struct *tsk; + atomic_t *ready, *set, *done; + struct intel_engine_cs *engine; + unsigned long flags; +#define STOP 0 +#define IDLE 1 + wait_queue_head_t *wq; + u32 seqno; +}; + +static int wait_atomic(atomic_t *p) +{ + schedule(); + return 0; +} + +static int wait_atomic_timeout(atomic_t *p) +{ + return schedule_timeout(10 * HZ) ? 0 : -ETIMEDOUT; +} + +static bool wait_for_ready(struct igt_wakeup *w) +{ + DEFINE_WAIT(ready); + + if (atomic_dec_and_test(w->done)) + wake_up_atomic_t(w->done); + + if (test_bit(STOP, &w->flags)) + goto out; + + set_bit(IDLE, &w->flags); I think this needs to be before atomic_dec_and_test(w->done), to avoid that same assert racing with the threads. Because immediately after the wake_up_atomic above the main loop starts asserting the IDLE bit which is not guaranteed to be set yet. Regards, Tvrtko + for (;;) { + prepare_to_wait(w->wq, &ready, TASK_INTERRUPTIBLE); + if (atomic_read(w->ready) == 0) + break; + + schedule(); + } + finish_wait(w->wq, &ready); + clear_bit(IDLE, &w->flags); + +out: + if (atomic_dec_and_test(w->set)) + wake_up_atomic_t(w->set); + + return !test_bit(STOP, &w->flags); +} + +static int igt_wakeup_thread(void *arg) +{ + struct igt_wakeup *w = arg; + struct intel_wait wait; + + while (wait_for_ready(w)) { + GEM_BUG_ON(kthread_should_stop()); + + intel_wait_init(&wait, w->seqno); + intel_engine_add_wait(w->engine, &wait); + for (;;) { + set_current_state(TASK_UNINTERRUPTIBLE); + if (i915_seqno_passed(intel_engine_get_seqno(w->engine), + w->seqno)) + break; + + if (test_bit(STOP, &w->flags)) /* emergency escape */ + break; + + schedule(); + } + intel_engine_remove_wait(w->engine, &wait); + __set_current_state(TASK_RUNNING); + } + + return 0; +} + +static void igt_wake_all_sync(atomic_t *ready, + atomic_t *set, + atomic_t *done, + wait_queue_head_t *wq, + int count) +{ + atomic_set(set, count); + atomic_set(ready, 0); + wake_up_all(wq); + + wait_on_atomic_t(set, wait_atomic, TASK_UNINTERRUPTIBLE); + atomic_set(ready, count); + atomic_set(done, count); +} + +static int igt_wakeup(void *arg) +{ + I915_RND_STATE(prng); + const int state = TASK_UNINTERRUPTIBLE; + struct intel_engine_cs *engine = arg; + struct igt_wakeup *waiters; + DECLARE_WAIT_QUEUE_HEAD_ONSTACK(wq); + const int count = 4096; + const u32 max_seqno = count / 4; + atomic_t ready, set, done; + int err = -ENOMEM; + int n, step; + + mock_engine_reset(engine); + + waiters = drm_malloc_gfp(count, sizeof(*waiters), GFP_TEMPORARY); + if (!waiters) + goto out_engines; + + /* Create a large number of threads, each waiting on a random seqno. +* Multiple waiters will be waiting for the same seqno. +*/ + atomic_set(&ready, count); + for (n = 0; n < count; n++) { + waiters[n].wq = &wq; + waiters[n].ready = &ready; + waiters[n].set = &set; + waiters[n].done = &done; + waiters[n].engine = engine; + waiters[n].flags = BIT(IDLE); + + waiters[n].tsk = kthread_run(igt_wakeup_thread, &waiters[n], +"i915/igt:%d", n); + if (IS_ERR(waiters[n].tsk)) + goto out_waiters; + + get_task_struct(waiters[n].tsk); + } + + for (step = 1; step <= max_seqno; step <<= 1) { + u32 seqno; + + /* The waiter threads start paused as we assign them a random +* seqno and reset the engi
Re: [Intel-gfx] [PATCH 38/46] drm/i915: Verify page layout for rotated VMA
On 02/02/2017 09:08, Chris Wilson wrote: Exercise creating rotated VMA and checking the page order within. v2: Be more creative in rotated params v3: ... Signed-off-by: Chris Wilson --- drivers/gpu/drm/i915/selftests/i915_vma.c | 179 ++ 1 file changed, 179 insertions(+) diff --git a/drivers/gpu/drm/i915/selftests/i915_vma.c b/drivers/gpu/drm/i915/selftests/i915_vma.c index 095d8348f5f0..4a737a670199 100644 --- a/drivers/gpu/drm/i915/selftests/i915_vma.c +++ b/drivers/gpu/drm/i915/selftests/i915_vma.c @@ -352,11 +352,190 @@ static int igt_vma_pin1(void *arg) return err; } +static unsigned long rotated_index(const struct intel_rotation_info *r, + unsigned int n, + unsigned int x, + unsigned int y) +{ + return (r->plane[n].stride * (r->plane[n].height - y - 1) + + r->plane[n].offset + x); +} + +static struct scatterlist * +assert_rotated(struct drm_i915_gem_object *obj, + const struct intel_rotation_info *r, unsigned int n, + struct scatterlist *sg) +{ + unsigned int x, y; + + for (x = 0; x < r->plane[n].width; x++) { + for (y = 0; y < r->plane[n].height; y++) { + unsigned long src_idx; + dma_addr_t src; + + if (!sg) { + pr_err("Invalid sg table: too short at plane %d, (%d, %d)!\n", + n, x, y); + return ERR_PTR(-EINVAL); + } + + src_idx = rotated_index(r, n, x, y); + src = i915_gem_object_get_dma_address(obj, src_idx); + + if (sg_dma_len(sg) != PAGE_SIZE) { + pr_err("Invalid sg.length, found %d, expected %lu for rotated page (%d, %d) [src index %lu]\n", + sg_dma_len(sg), PAGE_SIZE, + x, y, src_idx); + return ERR_PTR(-EINVAL); + } + + if (sg_dma_address(sg) != src) { + pr_err("Invalid address for rotated page (%d, %d) [src index %lu]\n", + x, y, src_idx); + return ERR_PTR(-EINVAL); + } + + sg = sg_next(sg); + } + } + + return sg; +} + +static unsigned int rotated_size(const struct intel_rotation_plane_info *a, +const struct intel_rotation_plane_info *b) +{ + return a->width * a->height + b->width * b->height; +} + +static int igt_vma_rotate(void *arg) +{ + struct drm_i915_private *i915 = arg; + struct i915_address_space *vm = &i915->ggtt.base; + struct drm_i915_gem_object *obj; + const struct intel_rotation_plane_info planes[] = { + { .width = 1, .height = 1, .stride = 1 }, + { .width = 2, .height = 2, .stride = 2 }, + { .width = 4, .height = 4, .stride = 4 }, + { .width = 8, .height = 8, .stride = 8 }, + + { .width = 3, .height = 5, .stride = 3 }, + { .width = 3, .height = 5, .stride = 4 }, + { .width = 3, .height = 5, .stride = 5 }, + + { .width = 5, .height = 3, .stride = 5 }, + { .width = 5, .height = 3, .stride = 7 }, + { .width = 5, .height = 3, .stride = 9 }, + + { .width = 4, .height = 6, .stride = 6 }, + { .width = 6, .height = 4, .stride = 6 }, + { } + }, *a, *b; + const unsigned int max_pages = 64; + int err = -ENOMEM; + + /* Create VMA for many different combinations of planes and check +* that the page layout within the rotated VMA match our expectations. +*/ + + obj = i915_gem_object_create_internal(i915, max_pages * PAGE_SIZE); + if (IS_ERR(obj)) + goto out; + + for (a = planes; a->width; a++) { + for (b = planes + ARRAY_SIZE(planes); b-- != planes; ) { + struct i915_ggtt_view view; + unsigned int n, max_offset; + + max_offset = max(a->stride * a->height, +b->stride * b->height); + GEM_BUG_ON(max_offset > max_pages); + max_offset = max_pages - max_offset; + + view.type = I915_GGTT_VIEW_ROTATED; + view.rotated.plane[0] = *a; + view.rotated.plane[1] = *b; + + for_each_prime_number_from(view.rotated.plane[0].offset, 0, max_offset) { + for_each_prime_number_from(view.rotated.plane[1].offset, 0, max_offset)
Re: [Intel-gfx] [PATCH 09/46] drm/i915: Add unit tests for the breadcrumb rbtree, wakeups
On Thu, Feb 02, 2017 at 12:49:58PM +, Tvrtko Ursulin wrote: > > On 02/02/2017 09:08, Chris Wilson wrote: > >+static bool wait_for_ready(struct igt_wakeup *w) > >+{ > >+DEFINE_WAIT(ready); > >+ > >+if (atomic_dec_and_test(w->done)) > >+wake_up_atomic_t(w->done); > >+ > >+if (test_bit(STOP, &w->flags)) > >+goto out; > >+ > >+set_bit(IDLE, &w->flags); > > I think this needs to be before atomic_dec_and_test(w->done), to > avoid that same assert racing with the threads. Because immediately > after the wake_up_atomic above the main loop starts asserting the > IDLE bit which is not guaranteed to be set yet. Before wake_up_atomic_t which is the same thing, yup. -Chris -- Chris Wilson, Intel Open Source Technology Centre ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/intel-gfx