LCOV - code coverage report
Current view: top level - drivers/gpu/drm/i915/gt/uc - intel_guc.c (source / functions) Hit Total Coverage
Test: combined.info Lines: 0 301 0.0 %
Date: 2022-03-28 13:20:08 Functions: 0 22 0.0 %
Branches: 0 110 0.0 %

           Branch data     Line data    Source code
       1                 :            : // SPDX-License-Identifier: MIT
       2                 :            : /*
       3                 :            :  * Copyright © 2014-2019 Intel Corporation
       4                 :            :  */
       5                 :            : 
       6                 :            : #include "gt/intel_gt.h"
       7                 :            : #include "gt/intel_gt_irq.h"
       8                 :            : #include "gt/intel_gt_pm_irq.h"
       9                 :            : #include "intel_guc.h"
      10                 :            : #include "intel_guc_ads.h"
      11                 :            : #include "intel_guc_submission.h"
      12                 :            : #include "i915_drv.h"
      13                 :            : 
      14                 :            : /**
      15                 :            :  * DOC: GuC
      16                 :            :  *
      17                 :            :  * The GuC is a microcontroller inside the GT HW, introduced in gen9. The GuC is
      18                 :            :  * designed to offload some of the functionality usually performed by the host
      19                 :            :  * driver; currently the main operations it can take care of are:
      20                 :            :  *
      21                 :            :  * - Authentication of the HuC, which is required to fully enable HuC usage.
      22                 :            :  * - Low latency graphics context scheduling (a.k.a. GuC submission).
      23                 :            :  * - GT Power management.
      24                 :            :  *
      25                 :            :  * The enable_guc module parameter can be used to select which of those
      26                 :            :  * operations to enable within GuC. Note that not all the operations are
      27                 :            :  * supported on all gen9+ platforms.
      28                 :            :  *
      29                 :            :  * Enabling the GuC is not mandatory and therefore the firmware is only loaded
      30                 :            :  * if at least one of the operations is selected. However, not loading the GuC
      31                 :            :  * might result in the loss of some features that do require the GuC (currently
      32                 :            :  * just the HuC, but more are expected to land in the future).
      33                 :            :  */
      34                 :            : 
      35                 :          0 : void intel_guc_notify(struct intel_guc *guc)
      36                 :            : {
      37                 :          0 :         struct intel_gt *gt = guc_to_gt(guc);
      38                 :            : 
      39                 :            :         /*
      40                 :            :          * On Gen11+, the value written to the register is passes as a payload
      41                 :            :          * to the FW. However, the FW currently treats all values the same way
      42                 :            :          * (H2G interrupt), so we can just write the value that the HW expects
      43                 :            :          * on older gens.
      44                 :            :          */
      45                 :          0 :         intel_uncore_write(gt->uncore, guc->notify_reg, GUC_SEND_TRIGGER);
      46                 :          0 : }
      47                 :            : 
      48                 :          0 : static inline i915_reg_t guc_send_reg(struct intel_guc *guc, u32 i)
      49                 :            : {
      50                 :          0 :         GEM_BUG_ON(!guc->send_regs.base);
      51                 :          0 :         GEM_BUG_ON(!guc->send_regs.count);
      52                 :          0 :         GEM_BUG_ON(i >= guc->send_regs.count);
      53                 :            : 
      54                 :          0 :         return _MMIO(guc->send_regs.base + 4 * i);
      55                 :            : }
      56                 :            : 
      57                 :          0 : void intel_guc_init_send_regs(struct intel_guc *guc)
      58                 :            : {
      59         [ #  # ]:          0 :         struct intel_gt *gt = guc_to_gt(guc);
      60                 :          0 :         enum forcewake_domains fw_domains = 0;
      61                 :          0 :         unsigned int i;
      62                 :            : 
      63         [ #  # ]:          0 :         if (INTEL_GEN(gt->i915) >= 11) {
      64                 :          0 :                 guc->send_regs.base =
      65                 :            :                                 i915_mmio_reg_offset(GEN11_SOFT_SCRATCH(0));
      66                 :          0 :                 guc->send_regs.count = GEN11_SOFT_SCRATCH_COUNT;
      67                 :            :         } else {
      68                 :          0 :                 guc->send_regs.base = i915_mmio_reg_offset(SOFT_SCRATCH(0));
      69                 :          0 :                 guc->send_regs.count = GUC_MAX_MMIO_MSG_LEN;
      70                 :          0 :                 BUILD_BUG_ON(GUC_MAX_MMIO_MSG_LEN > SOFT_SCRATCH_COUNT);
      71                 :            :         }
      72                 :            : 
      73         [ #  # ]:          0 :         for (i = 0; i < guc->send_regs.count; i++) {
      74                 :          0 :                 fw_domains |= intel_uncore_forcewake_for_reg(gt->uncore,
      75                 :            :                                         guc_send_reg(guc, i),
      76                 :            :                                         FW_REG_READ | FW_REG_WRITE);
      77                 :            :         }
      78                 :          0 :         guc->send_regs.fw_domains = fw_domains;
      79                 :          0 : }
      80                 :            : 
      81                 :          0 : static void gen9_reset_guc_interrupts(struct intel_guc *guc)
      82                 :            : {
      83                 :          0 :         struct intel_gt *gt = guc_to_gt(guc);
      84                 :            : 
      85                 :          0 :         assert_rpm_wakelock_held(&gt->i915->runtime_pm);
      86                 :            : 
      87                 :          0 :         spin_lock_irq(&gt->irq_lock);
      88                 :          0 :         gen6_gt_pm_reset_iir(gt, gt->pm_guc_events);
      89                 :          0 :         spin_unlock_irq(&gt->irq_lock);
      90                 :          0 : }
      91                 :            : 
      92                 :          0 : static void gen9_enable_guc_interrupts(struct intel_guc *guc)
      93                 :            : {
      94                 :          0 :         struct intel_gt *gt = guc_to_gt(guc);
      95                 :            : 
      96                 :          0 :         assert_rpm_wakelock_held(&gt->i915->runtime_pm);
      97                 :            : 
      98                 :          0 :         spin_lock_irq(&gt->irq_lock);
      99         [ #  # ]:          0 :         if (!guc->interrupts.enabled) {
     100   [ #  #  #  # ]:          0 :                 WARN_ON_ONCE(intel_uncore_read(gt->uncore, GEN8_GT_IIR(2)) &
     101                 :            :                              gt->pm_guc_events);
     102                 :          0 :                 guc->interrupts.enabled = true;
     103                 :          0 :                 gen6_gt_pm_enable_irq(gt, gt->pm_guc_events);
     104                 :            :         }
     105                 :          0 :         spin_unlock_irq(&gt->irq_lock);
     106                 :          0 : }
     107                 :            : 
     108                 :          0 : static void gen9_disable_guc_interrupts(struct intel_guc *guc)
     109                 :            : {
     110                 :          0 :         struct intel_gt *gt = guc_to_gt(guc);
     111                 :            : 
     112                 :          0 :         assert_rpm_wakelock_held(&gt->i915->runtime_pm);
     113                 :            : 
     114                 :          0 :         spin_lock_irq(&gt->irq_lock);
     115                 :          0 :         guc->interrupts.enabled = false;
     116                 :            : 
     117                 :          0 :         gen6_gt_pm_disable_irq(gt, gt->pm_guc_events);
     118                 :            : 
     119                 :          0 :         spin_unlock_irq(&gt->irq_lock);
     120                 :          0 :         intel_synchronize_irq(gt->i915);
     121                 :            : 
     122                 :          0 :         gen9_reset_guc_interrupts(guc);
     123                 :          0 : }
     124                 :            : 
     125                 :          0 : static void gen11_reset_guc_interrupts(struct intel_guc *guc)
     126                 :            : {
     127                 :          0 :         struct intel_gt *gt = guc_to_gt(guc);
     128                 :            : 
     129                 :          0 :         spin_lock_irq(&gt->irq_lock);
     130                 :          0 :         gen11_gt_reset_one_iir(gt, 0, GEN11_GUC);
     131                 :          0 :         spin_unlock_irq(&gt->irq_lock);
     132                 :          0 : }
     133                 :            : 
     134                 :          0 : static void gen11_enable_guc_interrupts(struct intel_guc *guc)
     135                 :            : {
     136                 :          0 :         struct intel_gt *gt = guc_to_gt(guc);
     137                 :            : 
     138                 :          0 :         spin_lock_irq(&gt->irq_lock);
     139         [ #  # ]:          0 :         if (!guc->interrupts.enabled) {
     140                 :          0 :                 u32 events = REG_FIELD_PREP(ENGINE1_MASK, GUC_INTR_GUC2HOST);
     141                 :            : 
     142   [ #  #  #  # ]:          0 :                 WARN_ON_ONCE(gen11_gt_reset_one_iir(gt, 0, GEN11_GUC));
     143                 :          0 :                 intel_uncore_write(gt->uncore,
     144                 :            :                                    GEN11_GUC_SG_INTR_ENABLE, events);
     145                 :          0 :                 intel_uncore_write(gt->uncore,
     146                 :            :                                    GEN11_GUC_SG_INTR_MASK, ~events);
     147                 :          0 :                 guc->interrupts.enabled = true;
     148                 :            :         }
     149                 :          0 :         spin_unlock_irq(&gt->irq_lock);
     150                 :          0 : }
     151                 :            : 
     152                 :          0 : static void gen11_disable_guc_interrupts(struct intel_guc *guc)
     153                 :            : {
     154                 :          0 :         struct intel_gt *gt = guc_to_gt(guc);
     155                 :            : 
     156                 :          0 :         spin_lock_irq(&gt->irq_lock);
     157                 :          0 :         guc->interrupts.enabled = false;
     158                 :            : 
     159                 :          0 :         intel_uncore_write(gt->uncore, GEN11_GUC_SG_INTR_MASK, ~0);
     160                 :          0 :         intel_uncore_write(gt->uncore, GEN11_GUC_SG_INTR_ENABLE, 0);
     161                 :            : 
     162                 :          0 :         spin_unlock_irq(&gt->irq_lock);
     163                 :          0 :         intel_synchronize_irq(gt->i915);
     164                 :            : 
     165                 :          0 :         gen11_reset_guc_interrupts(guc);
     166                 :          0 : }
     167                 :            : 
     168                 :          0 : void intel_guc_init_early(struct intel_guc *guc)
     169                 :            : {
     170                 :          0 :         struct drm_i915_private *i915 = guc_to_gt(guc)->i915;
     171                 :            : 
     172                 :          0 :         intel_guc_fw_init_early(guc);
     173                 :          0 :         intel_guc_ct_init_early(&guc->ct);
     174                 :          0 :         intel_guc_log_init_early(&guc->log);
     175                 :          0 :         intel_guc_submission_init_early(guc);
     176                 :            : 
     177                 :          0 :         mutex_init(&guc->send_mutex);
     178         [ #  # ]:          0 :         spin_lock_init(&guc->irq_lock);
     179         [ #  # ]:          0 :         if (INTEL_GEN(i915) >= 11) {
     180                 :          0 :                 guc->notify_reg = GEN11_GUC_HOST_INTERRUPT;
     181                 :          0 :                 guc->interrupts.reset = gen11_reset_guc_interrupts;
     182                 :          0 :                 guc->interrupts.enable = gen11_enable_guc_interrupts;
     183                 :          0 :                 guc->interrupts.disable = gen11_disable_guc_interrupts;
     184                 :            :         } else {
     185                 :          0 :                 guc->notify_reg = GUC_SEND_INTERRUPT;
     186                 :          0 :                 guc->interrupts.reset = gen9_reset_guc_interrupts;
     187                 :          0 :                 guc->interrupts.enable = gen9_enable_guc_interrupts;
     188                 :          0 :                 guc->interrupts.disable = gen9_disable_guc_interrupts;
     189                 :            :         }
     190                 :          0 : }
     191                 :            : 
     192                 :          0 : static u32 guc_ctl_debug_flags(struct intel_guc *guc)
     193                 :            : {
     194                 :          0 :         u32 level = intel_guc_log_get_level(&guc->log);
     195                 :          0 :         u32 flags = 0;
     196                 :            : 
     197         [ #  # ]:          0 :         if (!GUC_LOG_LEVEL_IS_VERBOSE(level))
     198                 :            :                 flags |= GUC_LOG_DISABLED;
     199                 :            :         else
     200                 :          0 :                 flags |= GUC_LOG_LEVEL_TO_VERBOSITY(level) <<
     201                 :            :                          GUC_LOG_VERBOSITY_SHIFT;
     202                 :            : 
     203                 :          0 :         return flags;
     204                 :            : }
     205                 :            : 
     206                 :          0 : static u32 guc_ctl_feature_flags(struct intel_guc *guc)
     207                 :            : {
     208                 :          0 :         u32 flags = 0;
     209                 :            : 
     210                 :          0 :         if (!intel_guc_is_submission_supported(guc))
     211                 :          0 :                 flags |= GUC_CTL_DISABLE_SCHEDULER;
     212                 :            : 
     213                 :          0 :         return flags;
     214                 :            : }
     215                 :            : 
     216                 :          0 : static u32 guc_ctl_ctxinfo_flags(struct intel_guc *guc)
     217                 :            : {
     218                 :          0 :         u32 flags = 0;
     219                 :            : 
     220                 :          0 :         if (intel_guc_is_submission_supported(guc)) {
     221                 :          0 :                 u32 ctxnum, base;
     222                 :            : 
     223                 :          0 :                 base = intel_guc_ggtt_offset(guc, guc->stage_desc_pool);
     224                 :          0 :                 ctxnum = GUC_MAX_STAGE_DESCRIPTORS / 16;
     225                 :            : 
     226                 :          0 :                 base >>= PAGE_SHIFT;
     227                 :          0 :                 flags |= (base << GUC_CTL_BASE_ADDR_SHIFT) |
     228                 :            :                         (ctxnum << GUC_CTL_CTXNUM_IN16_SHIFT);
     229                 :            :         }
     230                 :          0 :         return flags;
     231                 :            : }
     232                 :            : 
     233                 :          0 : static u32 guc_ctl_log_params_flags(struct intel_guc *guc)
     234                 :            : {
     235                 :          0 :         u32 offset = intel_guc_ggtt_offset(guc, guc->log.vma) >> PAGE_SHIFT;
     236                 :          0 :         u32 flags;
     237                 :            : 
     238                 :            :         #if (((CRASH_BUFFER_SIZE) % SZ_1M) == 0)
     239                 :            :         #define UNIT SZ_1M
     240                 :            :         #define FLAG GUC_LOG_ALLOC_IN_MEGABYTE
     241                 :            :         #else
     242                 :            :         #define UNIT SZ_4K
     243                 :            :         #define FLAG 0
     244                 :            :         #endif
     245                 :            : 
     246                 :          0 :         BUILD_BUG_ON(!CRASH_BUFFER_SIZE);
     247                 :          0 :         BUILD_BUG_ON(!IS_ALIGNED(CRASH_BUFFER_SIZE, UNIT));
     248                 :          0 :         BUILD_BUG_ON(!DPC_BUFFER_SIZE);
     249                 :          0 :         BUILD_BUG_ON(!IS_ALIGNED(DPC_BUFFER_SIZE, UNIT));
     250                 :          0 :         BUILD_BUG_ON(!ISR_BUFFER_SIZE);
     251                 :          0 :         BUILD_BUG_ON(!IS_ALIGNED(ISR_BUFFER_SIZE, UNIT));
     252                 :            : 
     253                 :          0 :         BUILD_BUG_ON((CRASH_BUFFER_SIZE / UNIT - 1) >
     254                 :            :                         (GUC_LOG_CRASH_MASK >> GUC_LOG_CRASH_SHIFT));
     255                 :          0 :         BUILD_BUG_ON((DPC_BUFFER_SIZE / UNIT - 1) >
     256                 :            :                         (GUC_LOG_DPC_MASK >> GUC_LOG_DPC_SHIFT));
     257                 :          0 :         BUILD_BUG_ON((ISR_BUFFER_SIZE / UNIT - 1) >
     258                 :            :                         (GUC_LOG_ISR_MASK >> GUC_LOG_ISR_SHIFT));
     259                 :            : 
     260                 :          0 :         flags = GUC_LOG_VALID |
     261                 :            :                 GUC_LOG_NOTIFY_ON_HALF_FULL |
     262                 :            :                 FLAG |
     263                 :            :                 ((CRASH_BUFFER_SIZE / UNIT - 1) << GUC_LOG_CRASH_SHIFT) |
     264                 :            :                 ((DPC_BUFFER_SIZE / UNIT - 1) << GUC_LOG_DPC_SHIFT) |
     265                 :            :                 ((ISR_BUFFER_SIZE / UNIT - 1) << GUC_LOG_ISR_SHIFT) |
     266                 :          0 :                 (offset << GUC_LOG_BUF_ADDR_SHIFT);
     267                 :            : 
     268                 :            :         #undef UNIT
     269                 :            :         #undef FLAG
     270                 :            : 
     271                 :          0 :         return flags;
     272                 :            : }
     273                 :            : 
     274                 :          0 : static u32 guc_ctl_ads_flags(struct intel_guc *guc)
     275                 :            : {
     276                 :          0 :         u32 ads = intel_guc_ggtt_offset(guc, guc->ads_vma) >> PAGE_SHIFT;
     277                 :          0 :         u32 flags = ads << GUC_ADS_ADDR_SHIFT;
     278                 :            : 
     279                 :          0 :         return flags;
     280                 :            : }
     281                 :            : 
     282                 :            : /*
     283                 :            :  * Initialise the GuC parameter block before starting the firmware
     284                 :            :  * transfer. These parameters are read by the firmware on startup
     285                 :            :  * and cannot be changed thereafter.
     286                 :            :  */
     287                 :          0 : static void guc_init_params(struct intel_guc *guc)
     288                 :            : {
     289                 :          0 :         u32 *params = guc->params;
     290                 :          0 :         int i;
     291                 :            : 
     292                 :          0 :         BUILD_BUG_ON(sizeof(guc->params) != GUC_CTL_MAX_DWORDS * sizeof(u32));
     293                 :            : 
     294         [ #  # ]:          0 :         params[GUC_CTL_CTXINFO] = guc_ctl_ctxinfo_flags(guc);
     295         [ #  # ]:          0 :         params[GUC_CTL_LOG_PARAMS] = guc_ctl_log_params_flags(guc);
     296         [ #  # ]:          0 :         params[GUC_CTL_FEATURE] = guc_ctl_feature_flags(guc);
     297         [ #  # ]:          0 :         params[GUC_CTL_DEBUG] = guc_ctl_debug_flags(guc);
     298                 :          0 :         params[GUC_CTL_ADS] = guc_ctl_ads_flags(guc);
     299                 :            : 
     300         [ #  # ]:          0 :         for (i = 0; i < GUC_CTL_MAX_DWORDS; i++)
     301                 :          0 :                 DRM_DEBUG_DRIVER("param[%2d] = %#x\n", i, params[i]);
     302                 :          0 : }
     303                 :            : 
     304                 :            : /*
     305                 :            :  * Initialise the GuC parameter block before starting the firmware
     306                 :            :  * transfer. These parameters are read by the firmware on startup
     307                 :            :  * and cannot be changed thereafter.
     308                 :            :  */
     309                 :          0 : void intel_guc_write_params(struct intel_guc *guc)
     310                 :            : {
     311                 :          0 :         struct intel_uncore *uncore = guc_to_gt(guc)->uncore;
     312                 :          0 :         int i;
     313                 :            : 
     314                 :            :         /*
     315                 :            :          * All SOFT_SCRATCH registers are in FORCEWAKE_BLITTER domain and
     316                 :            :          * they are power context saved so it's ok to release forcewake
     317                 :            :          * when we are done here and take it again at xfer time.
     318                 :            :          */
     319                 :          0 :         intel_uncore_forcewake_get(uncore, FORCEWAKE_BLITTER);
     320                 :            : 
     321                 :          0 :         intel_uncore_write(uncore, SOFT_SCRATCH(0), 0);
     322                 :            : 
     323         [ #  # ]:          0 :         for (i = 0; i < GUC_CTL_MAX_DWORDS; i++)
     324                 :          0 :                 intel_uncore_write(uncore, SOFT_SCRATCH(1 + i), guc->params[i]);
     325                 :            : 
     326                 :          0 :         intel_uncore_forcewake_put(uncore, FORCEWAKE_BLITTER);
     327                 :          0 : }
     328                 :            : 
     329                 :          0 : int intel_guc_init(struct intel_guc *guc)
     330                 :            : {
     331                 :          0 :         struct intel_gt *gt = guc_to_gt(guc);
     332                 :          0 :         int ret;
     333                 :            : 
     334                 :          0 :         ret = intel_uc_fw_init(&guc->fw);
     335         [ #  # ]:          0 :         if (ret)
     336                 :          0 :                 goto err_fetch;
     337                 :            : 
     338                 :          0 :         ret = intel_guc_log_create(&guc->log);
     339         [ #  # ]:          0 :         if (ret)
     340                 :          0 :                 goto err_fw;
     341                 :            : 
     342                 :          0 :         ret = intel_guc_ads_create(guc);
     343         [ #  # ]:          0 :         if (ret)
     344                 :          0 :                 goto err_log;
     345                 :          0 :         GEM_BUG_ON(!guc->ads_vma);
     346                 :            : 
     347                 :          0 :         ret = intel_guc_ct_init(&guc->ct);
     348         [ #  # ]:          0 :         if (ret)
     349                 :          0 :                 goto err_ads;
     350                 :            : 
     351         [ #  # ]:          0 :         if (intel_guc_is_submission_supported(guc)) {
     352                 :            :                 /*
     353                 :            :                  * This is stuff we need to have available at fw load time
     354                 :            :                  * if we are planning to enable submission later
     355                 :            :                  */
     356                 :          0 :                 ret = intel_guc_submission_init(guc);
     357         [ #  # ]:          0 :                 if (ret)
     358                 :          0 :                         goto err_ct;
     359                 :            :         }
     360                 :            : 
     361                 :            :         /* now that everything is perma-pinned, initialize the parameters */
     362                 :          0 :         guc_init_params(guc);
     363                 :            : 
     364                 :            :         /* We need to notify the guc whenever we change the GGTT */
     365                 :          0 :         i915_ggtt_enable_guc(gt->ggtt);
     366                 :            : 
     367                 :          0 :         return 0;
     368                 :            : 
     369                 :            : err_ct:
     370                 :          0 :         intel_guc_ct_fini(&guc->ct);
     371                 :          0 : err_ads:
     372                 :          0 :         intel_guc_ads_destroy(guc);
     373                 :          0 : err_log:
     374                 :          0 :         intel_guc_log_destroy(&guc->log);
     375                 :          0 : err_fw:
     376                 :          0 :         intel_uc_fw_fini(&guc->fw);
     377                 :          0 : err_fetch:
     378                 :          0 :         intel_uc_fw_cleanup_fetch(&guc->fw);
     379                 :          0 :         DRM_DEV_DEBUG_DRIVER(gt->i915->drm.dev, "failed with %d\n", ret);
     380                 :          0 :         return ret;
     381                 :            : }
     382                 :            : 
     383                 :          0 : void intel_guc_fini(struct intel_guc *guc)
     384                 :            : {
     385         [ #  # ]:          0 :         struct intel_gt *gt = guc_to_gt(guc);
     386                 :            : 
     387         [ #  # ]:          0 :         if (!intel_uc_fw_is_available(&guc->fw))
     388                 :            :                 return;
     389                 :            : 
     390                 :          0 :         i915_ggtt_disable_guc(gt->ggtt);
     391                 :            : 
     392         [ #  # ]:          0 :         if (intel_guc_is_submission_supported(guc))
     393                 :          0 :                 intel_guc_submission_fini(guc);
     394                 :            : 
     395                 :          0 :         intel_guc_ct_fini(&guc->ct);
     396                 :            : 
     397                 :          0 :         intel_guc_ads_destroy(guc);
     398                 :          0 :         intel_guc_log_destroy(&guc->log);
     399                 :          0 :         intel_uc_fw_fini(&guc->fw);
     400                 :          0 :         intel_uc_fw_cleanup_fetch(&guc->fw);
     401                 :            : 
     402                 :          0 :         intel_uc_fw_change_status(&guc->fw, INTEL_UC_FIRMWARE_DISABLED);
     403                 :            : }
     404                 :            : 
     405                 :            : /*
     406                 :            :  * This function implements the MMIO based host to GuC interface.
     407                 :            :  */
     408                 :          0 : int intel_guc_send_mmio(struct intel_guc *guc, const u32 *action, u32 len,
     409                 :            :                         u32 *response_buf, u32 response_buf_size)
     410                 :            : {
     411                 :          0 :         struct intel_uncore *uncore = guc_to_gt(guc)->uncore;
     412                 :          0 :         u32 status;
     413                 :          0 :         int i;
     414                 :          0 :         int ret;
     415                 :            : 
     416                 :          0 :         GEM_BUG_ON(!len);
     417                 :          0 :         GEM_BUG_ON(len > guc->send_regs.count);
     418                 :            : 
     419                 :            :         /* We expect only action code */
     420                 :          0 :         GEM_BUG_ON(*action & ~INTEL_GUC_MSG_CODE_MASK);
     421                 :            : 
     422                 :            :         /* If CT is available, we expect to use MMIO only during init/fini */
     423                 :          0 :         GEM_BUG_ON(*action != INTEL_GUC_ACTION_REGISTER_COMMAND_TRANSPORT_BUFFER &&
     424                 :            :                    *action != INTEL_GUC_ACTION_DEREGISTER_COMMAND_TRANSPORT_BUFFER);
     425                 :            : 
     426                 :          0 :         mutex_lock(&guc->send_mutex);
     427                 :          0 :         intel_uncore_forcewake_get(uncore, guc->send_regs.fw_domains);
     428                 :            : 
     429         [ #  # ]:          0 :         for (i = 0; i < len; i++)
     430                 :          0 :                 intel_uncore_write(uncore, guc_send_reg(guc, i), action[i]);
     431                 :            : 
     432                 :          0 :         intel_uncore_posting_read(uncore, guc_send_reg(guc, i - 1));
     433                 :            : 
     434                 :          0 :         intel_guc_notify(guc);
     435                 :            : 
     436                 :            :         /*
     437                 :            :          * No GuC command should ever take longer than 10ms.
     438                 :            :          * Fast commands should still complete in 10us.
     439                 :            :          */
     440                 :          0 :         ret = __intel_wait_for_register_fw(uncore,
     441                 :            :                                            guc_send_reg(guc, 0),
     442                 :            :                                            INTEL_GUC_MSG_TYPE_MASK,
     443                 :            :                                            INTEL_GUC_MSG_TYPE_RESPONSE <<
     444                 :            :                                            INTEL_GUC_MSG_TYPE_SHIFT,
     445                 :            :                                            10, 10, &status);
     446                 :            :         /* If GuC explicitly returned an error, convert it to -EIO */
     447   [ #  #  #  # ]:          0 :         if (!ret && !INTEL_GUC_MSG_IS_RESPONSE_SUCCESS(status))
     448                 :            :                 ret = -EIO;
     449                 :            : 
     450         [ #  # ]:          0 :         if (ret) {
     451                 :          0 :                 DRM_ERROR("MMIO: GuC action %#x failed with error %d %#x\n",
     452                 :            :                           action[0], ret, status);
     453                 :          0 :                 goto out;
     454                 :            :         }
     455                 :            : 
     456         [ #  # ]:          0 :         if (response_buf) {
     457                 :          0 :                 int count = min(response_buf_size, guc->send_regs.count - 1);
     458                 :            : 
     459         [ #  # ]:          0 :                 for (i = 0; i < count; i++)
     460                 :          0 :                         response_buf[i] = intel_uncore_read(uncore,
     461                 :          0 :                                                             guc_send_reg(guc, i + 1));
     462                 :            :         }
     463                 :            : 
     464                 :            :         /* Use data from the GuC response as our return value */
     465                 :          0 :         ret = INTEL_GUC_MSG_TO_DATA(status);
     466                 :            : 
     467                 :          0 : out:
     468                 :          0 :         intel_uncore_forcewake_put(uncore, guc->send_regs.fw_domains);
     469                 :          0 :         mutex_unlock(&guc->send_mutex);
     470                 :            : 
     471                 :          0 :         return ret;
     472                 :            : }
     473                 :            : 
     474                 :          0 : int intel_guc_to_host_process_recv_msg(struct intel_guc *guc,
     475                 :            :                                        const u32 *payload, u32 len)
     476                 :            : {
     477                 :          0 :         u32 msg;
     478                 :            : 
     479         [ #  # ]:          0 :         if (unlikely(!len))
     480                 :            :                 return -EPROTO;
     481                 :            : 
     482                 :            :         /* Make sure to handle only enabled messages */
     483                 :          0 :         msg = payload[0] & guc->msg_enabled_mask;
     484                 :            : 
     485         [ #  # ]:          0 :         if (msg & (INTEL_GUC_RECV_MSG_FLUSH_LOG_BUFFER |
     486                 :            :                    INTEL_GUC_RECV_MSG_CRASH_DUMP_POSTED))
     487                 :          0 :                 intel_guc_log_handle_flush_event(&guc->log);
     488                 :            : 
     489                 :            :         return 0;
     490                 :            : }
     491                 :            : 
     492                 :          0 : int intel_guc_sample_forcewake(struct intel_guc *guc)
     493                 :            : {
     494         [ #  # ]:          0 :         struct drm_i915_private *dev_priv = guc_to_gt(guc)->i915;
     495                 :          0 :         u32 action[2];
     496                 :            : 
     497                 :          0 :         action[0] = INTEL_GUC_ACTION_SAMPLE_FORCEWAKE;
     498                 :            :         /* WaRsDisableCoarsePowerGating:skl,cnl */
     499   [ #  #  #  #  :          0 :         if (!HAS_RC6(dev_priv) || NEEDS_WaRsDisableCoarsePowerGating(dev_priv))
          #  #  #  #  #  
                #  #  # ]
     500                 :          0 :                 action[1] = 0;
     501                 :            :         else
     502                 :            :                 /* bit 0 and 1 are for Render and Media domain separately */
     503                 :          0 :                 action[1] = GUC_FORCEWAKE_RENDER | GUC_FORCEWAKE_MEDIA;
     504                 :            : 
     505                 :          0 :         return intel_guc_send(guc, action, ARRAY_SIZE(action));
     506                 :            : }
     507                 :            : 
     508                 :            : /**
     509                 :            :  * intel_guc_auth_huc() - Send action to GuC to authenticate HuC ucode
     510                 :            :  * @guc: intel_guc structure
     511                 :            :  * @rsa_offset: rsa offset w.r.t ggtt base of huc vma
     512                 :            :  *
     513                 :            :  * Triggers a HuC firmware authentication request to the GuC via intel_guc_send
     514                 :            :  * INTEL_GUC_ACTION_AUTHENTICATE_HUC interface. This function is invoked by
     515                 :            :  * intel_huc_auth().
     516                 :            :  *
     517                 :            :  * Return:      non-zero code on error
     518                 :            :  */
     519                 :          0 : int intel_guc_auth_huc(struct intel_guc *guc, u32 rsa_offset)
     520                 :            : {
     521                 :          0 :         u32 action[] = {
     522                 :            :                 INTEL_GUC_ACTION_AUTHENTICATE_HUC,
     523                 :            :                 rsa_offset
     524                 :            :         };
     525                 :            : 
     526                 :          0 :         return intel_guc_send(guc, action, ARRAY_SIZE(action));
     527                 :            : }
     528                 :            : 
     529                 :            : /**
     530                 :            :  * intel_guc_suspend() - notify GuC entering suspend state
     531                 :            :  * @guc:        the guc
     532                 :            :  */
     533                 :          0 : int intel_guc_suspend(struct intel_guc *guc)
     534                 :            : {
     535         [ #  # ]:          0 :         struct intel_uncore *uncore = guc_to_gt(guc)->uncore;
     536                 :          0 :         int ret;
     537                 :          0 :         u32 status;
     538                 :          0 :         u32 action[] = {
     539                 :            :                 INTEL_GUC_ACTION_ENTER_S_STATE,
     540                 :            :                 GUC_POWER_D1, /* any value greater than GUC_POWER_D0 */
     541                 :            :         };
     542                 :            : 
     543                 :            :         /*
     544                 :            :          * If GuC communication is enabled but submission is not supported,
     545                 :            :          * we do not need to suspend the GuC.
     546                 :            :          */
     547   [ #  #  #  # ]:          0 :         if (!intel_guc_submission_is_enabled(guc))
     548                 :            :                 return 0;
     549                 :            : 
     550                 :            :         /*
     551                 :            :          * The ENTER_S_STATE action queues the save/restore operation in GuC FW
     552                 :            :          * and then returns, so waiting on the H2G is not enough to guarantee
     553                 :            :          * GuC is done. When all the processing is done, GuC writes
     554                 :            :          * INTEL_GUC_SLEEP_STATE_SUCCESS to scratch register 14, so we can poll
     555                 :            :          * on that. Note that GuC does not ensure that the value in the register
     556                 :            :          * is different from INTEL_GUC_SLEEP_STATE_SUCCESS while the action is
     557                 :            :          * in progress so we need to take care of that ourselves as well.
     558                 :            :          */
     559                 :            : 
     560                 :          0 :         intel_uncore_write(uncore, SOFT_SCRATCH(14),
     561                 :            :                            INTEL_GUC_SLEEP_STATE_INVALID_MASK);
     562                 :            : 
     563                 :          0 :         ret = intel_guc_send(guc, action, ARRAY_SIZE(action));
     564         [ #  # ]:          0 :         if (ret)
     565                 :            :                 return ret;
     566                 :            : 
     567                 :          0 :         ret = __intel_wait_for_register(uncore, SOFT_SCRATCH(14),
     568                 :            :                                         INTEL_GUC_SLEEP_STATE_INVALID_MASK,
     569                 :            :                                         0, 0, 10, &status);
     570         [ #  # ]:          0 :         if (ret)
     571                 :            :                 return ret;
     572                 :            : 
     573         [ #  # ]:          0 :         if (status != INTEL_GUC_SLEEP_STATE_SUCCESS) {
     574                 :          0 :                 DRM_ERROR("GuC failed to change sleep state. "
     575                 :            :                           "action=0x%x, err=%u\n",
     576                 :            :                           action[0], status);
     577                 :          0 :                 return -EIO;
     578                 :            :         }
     579                 :            : 
     580                 :            :         return 0;
     581                 :            : }
     582                 :            : 
     583                 :            : /**
     584                 :            :  * intel_guc_reset_engine() - ask GuC to reset an engine
     585                 :            :  * @guc:        intel_guc structure
     586                 :            :  * @engine:     engine to be reset
     587                 :            :  */
     588                 :          0 : int intel_guc_reset_engine(struct intel_guc *guc,
     589                 :            :                            struct intel_engine_cs *engine)
     590                 :            : {
     591                 :            :         /* XXX: to be implemented with submission interface rework */
     592                 :            : 
     593                 :          0 :         return -ENODEV;
     594                 :            : }
     595                 :            : 
     596                 :            : /**
     597                 :            :  * intel_guc_resume() - notify GuC resuming from suspend state
     598                 :            :  * @guc:        the guc
     599                 :            :  */
     600                 :          0 : int intel_guc_resume(struct intel_guc *guc)
     601                 :            : {
     602                 :          0 :         u32 action[] = {
     603                 :            :                 INTEL_GUC_ACTION_EXIT_S_STATE,
     604                 :            :                 GUC_POWER_D0,
     605                 :            :         };
     606                 :            : 
     607                 :            :         /*
     608                 :            :          * If GuC communication is enabled but submission is not supported,
     609                 :            :          * we do not need to resume the GuC but we do need to enable the
     610                 :            :          * GuC communication on resume (above).
     611                 :            :          */
     612   [ #  #  #  # ]:          0 :         if (!intel_guc_submission_is_enabled(guc))
     613                 :            :                 return 0;
     614                 :            : 
     615                 :          0 :         return intel_guc_send(guc, action, ARRAY_SIZE(action));
     616                 :            : }
     617                 :            : 
     618                 :            : /**
     619                 :            :  * DOC: GuC Memory Management
     620                 :            :  *
     621                 :            :  * GuC can't allocate any memory for its own usage, so all the allocations must
     622                 :            :  * be handled by the host driver. GuC accesses the memory via the GGTT, with the
     623                 :            :  * exception of the top and bottom parts of the 4GB address space, which are
     624                 :            :  * instead re-mapped by the GuC HW to memory location of the FW itself (WOPCM)
     625                 :            :  * or other parts of the HW. The driver must take care not to place objects that
     626                 :            :  * the GuC is going to access in these reserved ranges. The layout of the GuC
     627                 :            :  * address space is shown below:
     628                 :            :  *
     629                 :            :  * ::
     630                 :            :  *
     631                 :            :  *     +===========> +====================+ <== FFFF_FFFF
     632                 :            :  *     ^             |      Reserved      |
     633                 :            :  *     |             +====================+ <== GUC_GGTT_TOP
     634                 :            :  *     |             |                    |
     635                 :            :  *     |             |        DRAM        |
     636                 :            :  *    GuC            |                    |
     637                 :            :  *  Address    +===> +====================+ <== GuC ggtt_pin_bias
     638                 :            :  *   Space     ^     |                    |
     639                 :            :  *     |       |     |                    |
     640                 :            :  *     |      GuC    |        GuC         |
     641                 :            :  *     |     WOPCM   |       WOPCM        |
     642                 :            :  *     |      Size   |                    |
     643                 :            :  *     |       |     |                    |
     644                 :            :  *     v       v     |                    |
     645                 :            :  *     +=======+===> +====================+ <== 0000_0000
     646                 :            :  *
     647                 :            :  * The lower part of GuC Address Space [0, ggtt_pin_bias) is mapped to GuC WOPCM
     648                 :            :  * while upper part of GuC Address Space [ggtt_pin_bias, GUC_GGTT_TOP) is mapped
     649                 :            :  * to DRAM. The value of the GuC ggtt_pin_bias is the GuC WOPCM size.
     650                 :            :  */
     651                 :            : 
     652                 :            : /**
     653                 :            :  * intel_guc_allocate_vma() - Allocate a GGTT VMA for GuC usage
     654                 :            :  * @guc:        the guc
     655                 :            :  * @size:       size of area to allocate (both virtual space and memory)
     656                 :            :  *
     657                 :            :  * This is a wrapper to create an object for use with the GuC. In order to
     658                 :            :  * use it inside the GuC, an object needs to be pinned lifetime, so we allocate
     659                 :            :  * both some backing storage and a range inside the Global GTT. We must pin
     660                 :            :  * it in the GGTT somewhere other than than [0, GUC ggtt_pin_bias) because that
     661                 :            :  * range is reserved inside GuC.
     662                 :            :  *
     663                 :            :  * Return:      A i915_vma if successful, otherwise an ERR_PTR.
     664                 :            :  */
     665                 :          0 : struct i915_vma *intel_guc_allocate_vma(struct intel_guc *guc, u32 size)
     666                 :            : {
     667                 :          0 :         struct intel_gt *gt = guc_to_gt(guc);
     668                 :          0 :         struct drm_i915_gem_object *obj;
     669                 :          0 :         struct i915_vma *vma;
     670                 :          0 :         u64 flags;
     671                 :          0 :         int ret;
     672                 :            : 
     673                 :          0 :         obj = i915_gem_object_create_shmem(gt->i915, size);
     674         [ #  # ]:          0 :         if (IS_ERR(obj))
     675                 :            :                 return ERR_CAST(obj);
     676                 :            : 
     677                 :          0 :         vma = i915_vma_instance(obj, &gt->ggtt->vm, NULL);
     678         [ #  # ]:          0 :         if (IS_ERR(vma))
     679                 :          0 :                 goto err;
     680                 :            : 
     681                 :          0 :         flags = PIN_GLOBAL | PIN_OFFSET_BIAS | i915_ggtt_pin_bias(vma);
     682                 :          0 :         ret = i915_vma_pin(vma, 0, 0, flags);
     683         [ #  # ]:          0 :         if (ret) {
     684                 :          0 :                 vma = ERR_PTR(ret);
     685                 :          0 :                 goto err;
     686                 :            :         }
     687                 :            : 
     688                 :          0 :         return i915_vma_make_unshrinkable(vma);
     689                 :            : 
     690                 :          0 : err:
     691                 :          0 :         i915_gem_object_put(obj);
     692                 :          0 :         return vma;
     693                 :            : }
     694                 :            : 
     695                 :            : /**
     696                 :            :  * intel_guc_allocate_and_map_vma() - Allocate and map VMA for GuC usage
     697                 :            :  * @guc:        the guc
     698                 :            :  * @size:       size of area to allocate (both virtual space and memory)
     699                 :            :  * @out_vma:    return variable for the allocated vma pointer
     700                 :            :  * @out_vaddr:  return variable for the obj mapping
     701                 :            :  *
     702                 :            :  * This wrapper calls intel_guc_allocate_vma() and then maps the allocated
     703                 :            :  * object with I915_MAP_WB.
     704                 :            :  *
     705                 :            :  * Return:      0 if successful, a negative errno code otherwise.
     706                 :            :  */
     707                 :          0 : int intel_guc_allocate_and_map_vma(struct intel_guc *guc, u32 size,
     708                 :            :                                    struct i915_vma **out_vma, void **out_vaddr)
     709                 :            : {
     710                 :          0 :         struct i915_vma *vma;
     711                 :          0 :         void *vaddr;
     712                 :            : 
     713                 :          0 :         vma = intel_guc_allocate_vma(guc, size);
     714         [ #  # ]:          0 :         if (IS_ERR(vma))
     715                 :          0 :                 return PTR_ERR(vma);
     716                 :            : 
     717                 :          0 :         vaddr = i915_gem_object_pin_map(vma->obj, I915_MAP_WB);
     718         [ #  # ]:          0 :         if (IS_ERR(vaddr)) {
     719                 :          0 :                 i915_vma_unpin_and_release(&vma, 0);
     720                 :          0 :                 return PTR_ERR(vaddr);
     721                 :            :         }
     722                 :            : 
     723                 :          0 :         *out_vma = vma;
     724                 :          0 :         *out_vaddr = vaddr;
     725                 :            : 
     726                 :          0 :         return 0;
     727                 :            : }

Generated by: LCOV version 1.14