2016-11-25 18:59:35 +01:00
/*
* 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 "intel_uc.h"
2017-11-16 19:02:41 +05:30
# include "intel_guc_submission.h"
2017-10-04 18:13:42 +00:00
# include "i915_drv.h"
2016-11-25 18:59:35 +01:00
2017-03-14 15:28:11 +01:00
/* Reset GuC providing us with fresh state for both GuC and HuC.
*/
static int __intel_uc_reset_hw ( struct drm_i915_private * dev_priv )
{
int ret ;
u32 guc_status ;
2017-10-30 11:56:14 -07:00
ret = intel_reset_guc ( dev_priv ) ;
2017-03-14 15:28:11 +01:00
if ( ret ) {
2017-10-30 11:56:14 -07:00
DRM_ERROR ( " Failed to reset GuC, ret = %d \n " , ret ) ;
2017-03-14 15:28:11 +01:00
return ret ;
}
guc_status = I915_READ ( GUC_STATUS ) ;
WARN ( ! ( guc_status & GS_MIA_IN_RESET ) ,
" GuC status: 0x%x, MIA core expected to be in reset \n " ,
guc_status ) ;
return ret ;
}
2017-03-14 15:28:10 +01:00
void intel_uc_sanitize_options ( struct drm_i915_private * dev_priv )
{
if ( ! HAS_GUC ( dev_priv ) ) {
2017-09-19 19:38:44 +00:00
if ( i915_modparams . enable_guc_loading > 0 | |
i915_modparams . enable_guc_submission > 0 )
2017-03-15 13:37:41 +00:00
DRM_INFO ( " Ignoring GuC options, no hardware \n " ) ;
2017-03-14 15:28:10 +01:00
2017-09-19 19:38:44 +00:00
i915_modparams . enable_guc_loading = 0 ;
i915_modparams . enable_guc_submission = 0 ;
2017-03-15 13:37:41 +00:00
return ;
2017-03-14 15:28:10 +01:00
}
2017-03-14 15:28:13 +01:00
2017-03-15 13:37:41 +00:00
/* A negative value means "use platform default" */
2017-09-19 19:38:44 +00:00
if ( i915_modparams . enable_guc_loading < 0 )
i915_modparams . enable_guc_loading = HAS_GUC_UCODE ( dev_priv ) ;
2017-03-15 13:37:41 +00:00
/* Verify firmware version */
2017-09-19 19:38:44 +00:00
if ( i915_modparams . enable_guc_loading ) {
2017-12-06 13:53:11 +00:00
if ( ! intel_uc_fw_is_selected ( & dev_priv - > guc . fw ) )
2017-09-19 19:38:44 +00:00
i915_modparams . enable_guc_loading = 0 ;
2017-03-14 15:28:13 +01:00
}
2017-03-15 13:37:41 +00:00
/* Can't enable guc submission without guc loaded */
2017-09-19 19:38:44 +00:00
if ( ! i915_modparams . enable_guc_loading )
i915_modparams . enable_guc_submission = 0 ;
2017-03-15 13:37:41 +00:00
/* A negative value means "use platform default" */
2017-09-19 19:38:44 +00:00
if ( i915_modparams . enable_guc_submission < 0 )
i915_modparams . enable_guc_submission = HAS_GUC_SCHED ( dev_priv ) ;
2017-03-14 15:28:10 +01:00
}
2017-10-04 15:33:27 +00:00
void intel_uc_init_early ( struct drm_i915_private * dev_priv )
{
2017-10-04 18:13:41 +00:00
intel_guc_init_early ( & dev_priv - > guc ) ;
2017-12-06 13:53:10 +00:00
intel_huc_init_early ( & dev_priv - > huc ) ;
2017-10-04 15:33:27 +00:00
}
2017-03-14 15:28:09 +01:00
void intel_uc_init_fw ( struct drm_i915_private * dev_priv )
{
2017-10-04 15:33:25 +00:00
intel_uc_fw_fetch ( dev_priv , & dev_priv - > huc . fw ) ;
intel_uc_fw_fetch ( dev_priv , & dev_priv - > guc . fw ) ;
2017-03-14 15:28:09 +01:00
}
2017-03-22 10:39:46 -07:00
void intel_uc_fini_fw ( struct drm_i915_private * dev_priv )
{
2017-10-04 15:33:25 +00:00
intel_uc_fw_fini ( & dev_priv - > guc . fw ) ;
intel_uc_fw_fini ( & dev_priv - > huc . fw ) ;
2017-03-22 10:39:46 -07:00
}
2017-10-04 15:33:24 +00:00
/**
* intel_uc_init_mmio - setup uC MMIO access
*
* @ dev_priv : device private
*
* Setup minimal state necessary for MMIO accesses later in the
* initialization sequence .
*/
void intel_uc_init_mmio ( struct drm_i915_private * dev_priv )
{
2017-10-04 18:13:41 +00:00
intel_guc_init_send_regs ( & dev_priv - > guc ) ;
2017-10-04 15:33:24 +00:00
}
2017-05-22 10:50:28 -07:00
static void guc_capture_load_err_log ( struct intel_guc * guc )
{
2017-09-19 19:38:44 +00:00
if ( ! guc - > log . vma | | i915_modparams . guc_log_level < 0 )
2017-05-22 10:50:28 -07:00
return ;
if ( ! guc - > load_err_log )
guc - > load_err_log = i915_gem_object_get ( guc - > log . vma - > obj ) ;
return ;
}
static void guc_free_load_err_log ( struct intel_guc * guc )
{
if ( guc - > load_err_log )
i915_gem_object_put ( guc - > load_err_log ) ;
}
2017-05-02 10:32:42 +00:00
static int guc_enable_communication ( struct intel_guc * guc )
{
2017-05-26 11:13:25 +00:00
struct drm_i915_private * dev_priv = guc_to_i915 ( guc ) ;
if ( HAS_GUC_CT ( dev_priv ) )
return intel_guc_enable_ct ( guc ) ;
2017-05-02 10:32:42 +00:00
guc - > send = intel_guc_send_mmio ;
return 0 ;
}
static void guc_disable_communication ( struct intel_guc * guc )
{
2017-05-26 11:13:25 +00:00
struct drm_i915_private * dev_priv = guc_to_i915 ( guc ) ;
if ( HAS_GUC_CT ( dev_priv ) )
intel_guc_disable_ct ( guc ) ;
2017-05-02 10:32:42 +00:00
guc - > send = intel_guc_send_nop ;
}
2017-03-14 15:28:11 +01:00
int intel_uc_init_hw ( struct drm_i915_private * dev_priv )
{
2017-05-02 10:32:42 +00:00
struct intel_guc * guc = & dev_priv - > guc ;
2017-03-14 15:28:11 +01:00
int ret , attempts ;
2017-09-19 19:38:44 +00:00
if ( ! i915_modparams . enable_guc_loading )
2017-03-28 09:53:47 -07:00
return 0 ;
2017-05-02 10:32:42 +00:00
guc_disable_communication ( guc ) ;
2017-03-14 15:28:11 +01:00
gen9_reset_guc_interrupts ( dev_priv ) ;
/* We need to notify the guc whenever we change the GGTT */
i915_ggtt_enable_guc ( dev_priv ) ;
2017-09-19 19:38:44 +00:00
if ( i915_modparams . enable_guc_submission ) {
2017-03-22 10:39:52 -07:00
/*
* This is stuff we need to have available at fw load time
* if we are planning to enable submission later
*/
2017-11-16 19:02:39 +05:30
ret = intel_guc_submission_init ( guc ) ;
2017-03-22 10:39:52 -07:00
if ( ret )
goto err_guc ;
}
2017-03-14 15:28:11 +01:00
2017-04-06 17:18:52 -07:00
/* init WOPCM */
I915_WRITE ( GUC_WOPCM_SIZE , intel_guc_wopcm_size ( dev_priv ) ) ;
I915_WRITE ( DMA_GUC_WOPCM_OFFSET ,
GUC_WOPCM_OFFSET_VALUE | HUC_LOADING_AGENT_GUC ) ;
2017-03-14 15:28:11 +01:00
/* WaEnableuKernelHeaderValidFix:skl */
/* WaEnableGuCBootHashCheckNotSet:skl,bxt,kbl */
if ( IS_GEN9 ( dev_priv ) )
attempts = 3 ;
else
attempts = 1 ;
while ( attempts - - ) {
/*
* Always reset the GuC just before ( re ) loading , so
* that the state and timing are fairly predictable
*/
ret = __intel_uc_reset_hw ( dev_priv ) ;
if ( ret )
goto err_submission ;
intel_huc_init_hw ( & dev_priv - > huc ) ;
2017-10-16 14:47:11 +00:00
intel_guc_init_params ( guc ) ;
2017-10-16 14:47:14 +00:00
ret = intel_guc_fw_upload ( guc ) ;
2017-03-14 15:28:11 +01:00
if ( ret = = 0 | | ret ! = - EAGAIN )
break ;
DRM_DEBUG_DRIVER ( " GuC fw load failed: %d; will reset and "
" retry %d more time(s) \n " , ret , attempts ) ;
}
/* Did we succeded or run out of retries? */
if ( ret )
2017-05-22 10:50:28 -07:00
goto err_log_capture ;
2017-03-14 15:28:11 +01:00
2017-05-02 10:32:42 +00:00
ret = guc_enable_communication ( guc ) ;
if ( ret )
2017-05-22 10:50:28 -07:00
goto err_log_capture ;
2017-05-02 10:32:42 +00:00
2017-09-26 12:47:16 +05:30
intel_huc_auth ( & dev_priv - > huc ) ;
2017-09-19 19:38:44 +00:00
if ( i915_modparams . enable_guc_submission ) {
if ( i915_modparams . guc_log_level > = 0 )
2017-03-14 15:28:11 +01:00
gen9_enable_guc_interrupts ( dev_priv ) ;
2017-11-16 19:02:39 +05:30
ret = intel_guc_submission_enable ( guc ) ;
2017-03-14 15:28:11 +01:00
if ( ret )
2017-03-22 10:39:46 -07:00
goto err_interrupts ;
2017-03-14 15:28:11 +01:00
}
2017-10-16 14:47:17 +00:00
dev_info ( dev_priv - > drm . dev , " GuC %s (firmware %s [version %u.%u]) \n " ,
i915_modparams . enable_guc_submission ? " submission enabled " :
" loaded " ,
guc - > fw . path ,
guc - > fw . major_ver_found , guc - > fw . minor_ver_found ) ;
2017-03-14 15:28:11 +01:00
return 0 ;
/*
* We ' ve failed to load the firmware : (
*
* Decide whether to disable GuC submission and fall back to
* execlist mode , and whether to hide the error by returning
* zero or to return - EIO , which the caller will treat as a
* nonfatal error ( i . e . it doesn ' t prevent driver load , but
* marks the GPU as wedged until reset ) .
*/
2017-03-22 10:39:46 -07:00
err_interrupts :
2017-05-02 10:32:42 +00:00
guc_disable_communication ( guc ) ;
2017-03-22 10:39:46 -07:00
gen9_disable_guc_interrupts ( dev_priv ) ;
2017-05-22 10:50:28 -07:00
err_log_capture :
guc_capture_load_err_log ( guc ) ;
2017-03-14 15:28:11 +01:00
err_submission :
2017-09-19 19:38:44 +00:00
if ( i915_modparams . enable_guc_submission )
2017-11-16 19:02:39 +05:30
intel_guc_submission_fini ( guc ) ;
2017-03-22 10:39:46 -07:00
err_guc :
2017-03-14 15:28:11 +01:00
i915_ggtt_disable_guc ( dev_priv ) ;
2017-09-19 19:38:44 +00:00
if ( i915_modparams . enable_guc_loading > 1 | |
2017-10-16 14:47:22 +00:00
i915_modparams . enable_guc_submission > 1 ) {
DRM_ERROR ( " GuC init failed. Firmware loading disabled. \n " ) ;
2017-03-14 15:28:11 +01:00
ret = - EIO ;
2017-10-16 14:47:22 +00:00
} else {
DRM_NOTE ( " GuC init failed. Firmware loading disabled. \n " ) ;
2017-03-14 15:28:11 +01:00
ret = 0 ;
2017-10-16 14:47:22 +00:00
}
2017-03-14 15:28:11 +01:00
2017-09-19 19:38:44 +00:00
if ( i915_modparams . enable_guc_submission ) {
i915_modparams . enable_guc_submission = 0 ;
2017-03-14 15:28:11 +01:00
DRM_NOTE ( " Falling back from GuC submission to execlist mode \n " ) ;
}
2017-09-19 19:38:44 +00:00
i915_modparams . enable_guc_loading = 0 ;
2017-06-05 10:12:51 -07:00
2017-03-14 15:28:11 +01:00
return ret ;
}
2017-03-22 10:39:46 -07:00
void intel_uc_fini_hw ( struct drm_i915_private * dev_priv )
{
2017-11-16 19:02:39 +05:30
struct intel_guc * guc = & dev_priv - > guc ;
guc_free_load_err_log ( guc ) ;
2017-06-05 10:12:51 -07:00
2017-09-19 19:38:44 +00:00
if ( ! i915_modparams . enable_guc_loading )
2017-03-28 09:53:47 -07:00
return ;
2017-09-19 19:38:44 +00:00
if ( i915_modparams . enable_guc_submission )
2017-11-16 19:02:39 +05:30
intel_guc_submission_disable ( guc ) ;
2017-05-26 11:13:24 +00:00
2017-11-16 19:02:39 +05:30
guc_disable_communication ( guc ) ;
2017-05-26 11:13:24 +00:00
2017-09-19 19:38:44 +00:00
if ( i915_modparams . enable_guc_submission ) {
2017-03-22 10:39:46 -07:00
gen9_disable_guc_interrupts ( dev_priv ) ;
2017-11-16 19:02:39 +05:30
intel_guc_submission_fini ( guc ) ;
2017-03-22 10:39:46 -07:00
}
2017-05-26 11:13:24 +00:00
2017-03-22 10:39:46 -07:00
i915_ggtt_disable_guc ( dev_priv ) ;
}