root/drivers/gpu/drm/i915/gt/intel_mocs.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. get_mocs_settings
  2. mocs_register
  3. get_entry_control
  4. intel_mocs_init_engine
  5. intel_mocs_init_global
  6. emit_mocs_control_table
  7. get_entry_l3cc
  8. l3cc_combine
  9. emit_mocs_l3cc_table
  10. intel_mocs_init_l3cc_table
  11. intel_mocs_emit
  12. intel_mocs_init

   1 /*
   2  * Copyright (c) 2015 Intel Corporation
   3  *
   4  * Permission is hereby granted, free of charge, to any person obtaining a
   5  * copy of this software and associated documentation files (the "Software"),
   6  * to deal in the Software without restriction, including without limitation
   7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
   8  * and/or sell copies of the Software, and to permit persons to whom the
   9  * Software is furnished to do so, subject to the following conditions: *
  10  * The above copyright notice and this permission notice (including the next
  11  * paragraph) shall be included in all copies or substantial portions of the
  12  * Software.
  13  *
  14  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  17  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  18  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  19  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  20  * SOFTWARE.
  21  */
  22 
  23 #include "i915_drv.h"
  24 
  25 #include "intel_engine.h"
  26 #include "intel_gt.h"
  27 #include "intel_mocs.h"
  28 #include "intel_lrc.h"
  29 
  30 /* structures required */
  31 struct drm_i915_mocs_entry {
  32         u32 control_value;
  33         u16 l3cc_value;
  34         u16 used;
  35 };
  36 
  37 struct drm_i915_mocs_table {
  38         unsigned int size;
  39         unsigned int n_entries;
  40         const struct drm_i915_mocs_entry *table;
  41 };
  42 
  43 /* Defines for the tables (XXX_MOCS_0 - XXX_MOCS_63) */
  44 #define _LE_CACHEABILITY(value) ((value) << 0)
  45 #define _LE_TGT_CACHE(value)    ((value) << 2)
  46 #define LE_LRUM(value)          ((value) << 4)
  47 #define LE_AOM(value)           ((value) << 6)
  48 #define LE_RSC(value)           ((value) << 7)
  49 #define LE_SCC(value)           ((value) << 8)
  50 #define LE_PFM(value)           ((value) << 11)
  51 #define LE_SCF(value)           ((value) << 14)
  52 #define LE_COS(value)           ((value) << 15)
  53 #define LE_SSE(value)           ((value) << 17)
  54 
  55 /* Defines for the tables (LNCFMOCS0 - LNCFMOCS31) - two entries per word */
  56 #define L3_ESC(value)           ((value) << 0)
  57 #define L3_SCC(value)           ((value) << 1)
  58 #define _L3_CACHEABILITY(value) ((value) << 4)
  59 
  60 /* Helper defines */
  61 #define GEN9_NUM_MOCS_ENTRIES   62  /* 62 out of 64 - 63 & 64 are reserved. */
  62 #define GEN11_NUM_MOCS_ENTRIES  64  /* 63-64 are reserved, but configured. */
  63 
  64 /* (e)LLC caching options */
  65 /*
  66  * Note: LE_0_PAGETABLE works only up to Gen11; for newer gens it means
  67  * the same as LE_UC
  68  */
  69 #define LE_0_PAGETABLE          _LE_CACHEABILITY(0)
  70 #define LE_1_UC                 _LE_CACHEABILITY(1)
  71 #define LE_2_WT                 _LE_CACHEABILITY(2)
  72 #define LE_3_WB                 _LE_CACHEABILITY(3)
  73 
  74 /* Target cache */
  75 #define LE_TC_0_PAGETABLE       _LE_TGT_CACHE(0)
  76 #define LE_TC_1_LLC             _LE_TGT_CACHE(1)
  77 #define LE_TC_2_LLC_ELLC        _LE_TGT_CACHE(2)
  78 #define LE_TC_3_LLC_ELLC_ALT    _LE_TGT_CACHE(3)
  79 
  80 /* L3 caching options */
  81 #define L3_0_DIRECT             _L3_CACHEABILITY(0)
  82 #define L3_1_UC                 _L3_CACHEABILITY(1)
  83 #define L3_2_RESERVED           _L3_CACHEABILITY(2)
  84 #define L3_3_WB                 _L3_CACHEABILITY(3)
  85 
  86 #define MOCS_ENTRY(__idx, __control_value, __l3cc_value) \
  87         [__idx] = { \
  88                 .control_value = __control_value, \
  89                 .l3cc_value = __l3cc_value, \
  90                 .used = 1, \
  91         }
  92 
  93 /*
  94  * MOCS tables
  95  *
  96  * These are the MOCS tables that are programmed across all the rings.
  97  * The control value is programmed to all the rings that support the
  98  * MOCS registers. While the l3cc_values are only programmed to the
  99  * LNCFCMOCS0 - LNCFCMOCS32 registers.
 100  *
 101  * These tables are intended to be kept reasonably consistent across
 102  * HW platforms, and for ICL+, be identical across OSes. To achieve
 103  * that, for Icelake and above, list of entries is published as part
 104  * of bspec.
 105  *
 106  * Entries not part of the following tables are undefined as far as
 107  * userspace is concerned and shouldn't be relied upon.  For Gen < 12
 108  * they will be initialized to PTE. Gen >= 12 onwards don't have a setting for
 109  * PTE and will be initialized to an invalid value.
 110  *
 111  * The last two entries are reserved by the hardware. For ICL+ they
 112  * should be initialized according to bspec and never used, for older
 113  * platforms they should never be written to.
 114  *
 115  * NOTE: These tables are part of bspec and defined as part of hardware
 116  *       interface for ICL+. For older platforms, they are part of kernel
 117  *       ABI. It is expected that, for specific hardware platform, existing
 118  *       entries will remain constant and the table will only be updated by
 119  *       adding new entries, filling unused positions.
 120  */
 121 #define GEN9_MOCS_ENTRIES \
 122         MOCS_ENTRY(I915_MOCS_UNCACHED, \
 123                    LE_1_UC | LE_TC_2_LLC_ELLC, \
 124                    L3_1_UC), \
 125         MOCS_ENTRY(I915_MOCS_PTE, \
 126                    LE_0_PAGETABLE | LE_TC_2_LLC_ELLC | LE_LRUM(3), \
 127                    L3_3_WB)
 128 
 129 static const struct drm_i915_mocs_entry skylake_mocs_table[] = {
 130         GEN9_MOCS_ENTRIES,
 131         MOCS_ENTRY(I915_MOCS_CACHED,
 132                    LE_3_WB | LE_TC_2_LLC_ELLC | LE_LRUM(3),
 133                    L3_3_WB)
 134 };
 135 
 136 /* NOTE: the LE_TGT_CACHE is not used on Broxton */
 137 static const struct drm_i915_mocs_entry broxton_mocs_table[] = {
 138         GEN9_MOCS_ENTRIES,
 139         MOCS_ENTRY(I915_MOCS_CACHED,
 140                    LE_1_UC | LE_TC_2_LLC_ELLC | LE_LRUM(3),
 141                    L3_3_WB)
 142 };
 143 
 144 #define GEN11_MOCS_ENTRIES \
 145         /* Entries 0 and 1 are defined per-platform */ \
 146         /* Base - L3 + LLC */ \
 147         MOCS_ENTRY(2, \
 148                    LE_3_WB | LE_TC_1_LLC | LE_LRUM(3), \
 149                    L3_3_WB), \
 150         /* Base - Uncached */ \
 151         MOCS_ENTRY(3, \
 152                    LE_1_UC | LE_TC_1_LLC, \
 153                    L3_1_UC), \
 154         /* Base - L3 */ \
 155         MOCS_ENTRY(4, \
 156                    LE_1_UC | LE_TC_1_LLC, \
 157                    L3_3_WB), \
 158         /* Base - LLC */ \
 159         MOCS_ENTRY(5, \
 160                    LE_3_WB | LE_TC_1_LLC | LE_LRUM(3), \
 161                    L3_1_UC), \
 162         /* Age 0 - LLC */ \
 163         MOCS_ENTRY(6, \
 164                    LE_3_WB | LE_TC_1_LLC | LE_LRUM(1), \
 165                    L3_1_UC), \
 166         /* Age 0 - L3 + LLC */ \
 167         MOCS_ENTRY(7, \
 168                    LE_3_WB | LE_TC_1_LLC | LE_LRUM(1), \
 169                    L3_3_WB), \
 170         /* Age: Don't Chg. - LLC */ \
 171         MOCS_ENTRY(8, \
 172                    LE_3_WB | LE_TC_1_LLC | LE_LRUM(2), \
 173                    L3_1_UC), \
 174         /* Age: Don't Chg. - L3 + LLC */ \
 175         MOCS_ENTRY(9, \
 176                    LE_3_WB | LE_TC_1_LLC | LE_LRUM(2), \
 177                    L3_3_WB), \
 178         /* No AOM - LLC */ \
 179         MOCS_ENTRY(10, \
 180                    LE_3_WB | LE_TC_1_LLC | LE_LRUM(3) | LE_AOM(1), \
 181                    L3_1_UC), \
 182         /* No AOM - L3 + LLC */ \
 183         MOCS_ENTRY(11, \
 184                    LE_3_WB | LE_TC_1_LLC | LE_LRUM(3) | LE_AOM(1), \
 185                    L3_3_WB), \
 186         /* No AOM; Age 0 - LLC */ \
 187         MOCS_ENTRY(12, \
 188                    LE_3_WB | LE_TC_1_LLC | LE_LRUM(1) | LE_AOM(1), \
 189                    L3_1_UC), \
 190         /* No AOM; Age 0 - L3 + LLC */ \
 191         MOCS_ENTRY(13, \
 192                    LE_3_WB | LE_TC_1_LLC | LE_LRUM(1) | LE_AOM(1), \
 193                    L3_3_WB), \
 194         /* No AOM; Age:DC - LLC */ \
 195         MOCS_ENTRY(14, \
 196                    LE_3_WB | LE_TC_1_LLC | LE_LRUM(2) | LE_AOM(1), \
 197                    L3_1_UC), \
 198         /* No AOM; Age:DC - L3 + LLC */ \
 199         MOCS_ENTRY(15, \
 200                    LE_3_WB | LE_TC_1_LLC | LE_LRUM(2) | LE_AOM(1), \
 201                    L3_3_WB), \
 202         /* Self-Snoop - L3 + LLC */ \
 203         MOCS_ENTRY(18, \
 204                    LE_3_WB | LE_TC_1_LLC | LE_LRUM(3) | LE_SSE(3), \
 205                    L3_3_WB), \
 206         /* Skip Caching - L3 + LLC(12.5%) */ \
 207         MOCS_ENTRY(19, \
 208                    LE_3_WB | LE_TC_1_LLC | LE_LRUM(3) | LE_SCC(7), \
 209                    L3_3_WB), \
 210         /* Skip Caching - L3 + LLC(25%) */ \
 211         MOCS_ENTRY(20, \
 212                    LE_3_WB | LE_TC_1_LLC | LE_LRUM(3) | LE_SCC(3), \
 213                    L3_3_WB), \
 214         /* Skip Caching - L3 + LLC(50%) */ \
 215         MOCS_ENTRY(21, \
 216                    LE_3_WB | LE_TC_1_LLC | LE_LRUM(3) | LE_SCC(1), \
 217                    L3_3_WB), \
 218         /* Skip Caching - L3 + LLC(75%) */ \
 219         MOCS_ENTRY(22, \
 220                    LE_3_WB | LE_TC_1_LLC | LE_LRUM(3) | LE_RSC(1) | LE_SCC(3), \
 221                    L3_3_WB), \
 222         /* Skip Caching - L3 + LLC(87.5%) */ \
 223         MOCS_ENTRY(23, \
 224                    LE_3_WB | LE_TC_1_LLC | LE_LRUM(3) | LE_RSC(1) | LE_SCC(7), \
 225                    L3_3_WB), \
 226         /* HW Reserved - SW program but never use */ \
 227         MOCS_ENTRY(62, \
 228                    LE_3_WB | LE_TC_1_LLC | LE_LRUM(3), \
 229                    L3_1_UC), \
 230         /* HW Reserved - SW program but never use */ \
 231         MOCS_ENTRY(63, \
 232                    LE_3_WB | LE_TC_1_LLC | LE_LRUM(3), \
 233                    L3_1_UC)
 234 
 235 static const struct drm_i915_mocs_entry tigerlake_mocs_table[] = {
 236         /* Base - Error (Reserved for Non-Use) */
 237         MOCS_ENTRY(0, 0x0, 0x0),
 238         /* Base - Reserved */
 239         MOCS_ENTRY(1, 0x0, 0x0),
 240 
 241         GEN11_MOCS_ENTRIES,
 242 
 243         /* Implicitly enable L1 - HDC:L1 + L3 + LLC */
 244         MOCS_ENTRY(48,
 245                    LE_3_WB | LE_TC_1_LLC | LE_LRUM(3),
 246                    L3_3_WB),
 247         /* Implicitly enable L1 - HDC:L1 + L3 */
 248         MOCS_ENTRY(49,
 249                    LE_1_UC | LE_TC_1_LLC,
 250                    L3_3_WB),
 251         /* Implicitly enable L1 - HDC:L1 + LLC */
 252         MOCS_ENTRY(50,
 253                    LE_3_WB | LE_TC_1_LLC | LE_LRUM(3),
 254                    L3_1_UC),
 255         /* Implicitly enable L1 - HDC:L1 */
 256         MOCS_ENTRY(51,
 257                    LE_1_UC | LE_TC_1_LLC,
 258                    L3_1_UC),
 259         /* HW Special Case (CCS) */
 260         MOCS_ENTRY(60,
 261                    LE_3_WB | LE_TC_1_LLC | LE_LRUM(3),
 262                    L3_1_UC),
 263         /* HW Special Case (Displayable) */
 264         MOCS_ENTRY(61,
 265                    LE_1_UC | LE_TC_1_LLC,
 266                    L3_3_WB),
 267 };
 268 
 269 static const struct drm_i915_mocs_entry icelake_mocs_table[] = {
 270         /* Base - Uncached (Deprecated) */
 271         MOCS_ENTRY(I915_MOCS_UNCACHED,
 272                    LE_1_UC | LE_TC_1_LLC,
 273                    L3_1_UC),
 274         /* Base - L3 + LeCC:PAT (Deprecated) */
 275         MOCS_ENTRY(I915_MOCS_PTE,
 276                    LE_0_PAGETABLE | LE_TC_1_LLC,
 277                    L3_3_WB),
 278 
 279         GEN11_MOCS_ENTRIES
 280 };
 281 
 282 static bool get_mocs_settings(struct intel_gt *gt,
 283                               struct drm_i915_mocs_table *table)
 284 {
 285         struct drm_i915_private *i915 = gt->i915;
 286         bool result = false;
 287 
 288         if (INTEL_GEN(i915) >= 12) {
 289                 table->size  = ARRAY_SIZE(tigerlake_mocs_table);
 290                 table->table = tigerlake_mocs_table;
 291                 table->n_entries = GEN11_NUM_MOCS_ENTRIES;
 292                 result = true;
 293         } else if (IS_GEN(i915, 11)) {
 294                 table->size  = ARRAY_SIZE(icelake_mocs_table);
 295                 table->table = icelake_mocs_table;
 296                 table->n_entries = GEN11_NUM_MOCS_ENTRIES;
 297                 result = true;
 298         } else if (IS_GEN9_BC(i915) || IS_CANNONLAKE(i915)) {
 299                 table->size  = ARRAY_SIZE(skylake_mocs_table);
 300                 table->n_entries = GEN9_NUM_MOCS_ENTRIES;
 301                 table->table = skylake_mocs_table;
 302                 result = true;
 303         } else if (IS_GEN9_LP(i915)) {
 304                 table->size  = ARRAY_SIZE(broxton_mocs_table);
 305                 table->n_entries = GEN9_NUM_MOCS_ENTRIES;
 306                 table->table = broxton_mocs_table;
 307                 result = true;
 308         } else {
 309                 WARN_ONCE(INTEL_GEN(i915) >= 9,
 310                           "Platform that should have a MOCS table does not.\n");
 311         }
 312 
 313         /* WaDisableSkipCaching:skl,bxt,kbl,glk */
 314         if (IS_GEN(i915, 9)) {
 315                 int i;
 316 
 317                 for (i = 0; i < table->size; i++)
 318                         if (WARN_ON(table->table[i].l3cc_value &
 319                                     (L3_ESC(1) | L3_SCC(0x7))))
 320                                 return false;
 321         }
 322 
 323         return result;
 324 }
 325 
 326 static i915_reg_t mocs_register(enum intel_engine_id engine_id, int index)
 327 {
 328         switch (engine_id) {
 329         case RCS0:
 330                 return GEN9_GFX_MOCS(index);
 331         case VCS0:
 332                 return GEN9_MFX0_MOCS(index);
 333         case BCS0:
 334                 return GEN9_BLT_MOCS(index);
 335         case VECS0:
 336                 return GEN9_VEBOX_MOCS(index);
 337         case VCS1:
 338                 return GEN9_MFX1_MOCS(index);
 339         case VCS2:
 340                 return GEN11_MFX2_MOCS(index);
 341         default:
 342                 MISSING_CASE(engine_id);
 343                 return INVALID_MMIO_REG;
 344         }
 345 }
 346 
 347 /*
 348  * Get control_value from MOCS entry taking into account when it's not used:
 349  * I915_MOCS_PTE's value is returned in this case.
 350  */
 351 static u32 get_entry_control(const struct drm_i915_mocs_table *table,
 352                              unsigned int index)
 353 {
 354         if (table->table[index].used)
 355                 return table->table[index].control_value;
 356 
 357         return table->table[I915_MOCS_PTE].control_value;
 358 }
 359 
 360 /**
 361  * intel_mocs_init_engine() - emit the mocs control table
 362  * @engine:     The engine for whom to emit the registers.
 363  *
 364  * This function simply emits a MI_LOAD_REGISTER_IMM command for the
 365  * given table starting at the given address.
 366  */
 367 void intel_mocs_init_engine(struct intel_engine_cs *engine)
 368 {
 369         struct intel_gt *gt = engine->gt;
 370         struct intel_uncore *uncore = gt->uncore;
 371         struct drm_i915_mocs_table table;
 372         unsigned int index;
 373         u32 unused_value;
 374 
 375         /* Platforms with global MOCS do not need per-engine initialization. */
 376         if (HAS_GLOBAL_MOCS_REGISTERS(gt->i915))
 377                 return;
 378 
 379         /* Called under a blanket forcewake */
 380         assert_forcewakes_active(uncore, FORCEWAKE_ALL);
 381 
 382         if (!get_mocs_settings(gt, &table))
 383                 return;
 384 
 385         /* Set unused values to PTE */
 386         unused_value = table.table[I915_MOCS_PTE].control_value;
 387 
 388         for (index = 0; index < table.size; index++) {
 389                 u32 value = get_entry_control(&table, index);
 390 
 391                 intel_uncore_write_fw(uncore,
 392                                       mocs_register(engine->id, index),
 393                                       value);
 394         }
 395 
 396         /* All remaining entries are also unused */
 397         for (; index < table.n_entries; index++)
 398                 intel_uncore_write_fw(uncore,
 399                                       mocs_register(engine->id, index),
 400                                       unused_value);
 401 }
 402 
 403 static void intel_mocs_init_global(struct intel_gt *gt)
 404 {
 405         struct intel_uncore *uncore = gt->uncore;
 406         struct drm_i915_mocs_table table;
 407         unsigned int index;
 408 
 409         GEM_BUG_ON(!HAS_GLOBAL_MOCS_REGISTERS(gt->i915));
 410 
 411         if (!get_mocs_settings(gt, &table))
 412                 return;
 413 
 414         if (GEM_DEBUG_WARN_ON(table.size > table.n_entries))
 415                 return;
 416 
 417         for (index = 0; index < table.size; index++)
 418                 intel_uncore_write(uncore,
 419                                    GEN12_GLOBAL_MOCS(index),
 420                                    table.table[index].control_value);
 421 
 422         /*
 423          * Ok, now set the unused entries to the invalid entry (index 0). These
 424          * entries are officially undefined and no contract for the contents and
 425          * settings is given for these entries.
 426          */
 427         for (; index < table.n_entries; index++)
 428                 intel_uncore_write(uncore,
 429                                    GEN12_GLOBAL_MOCS(index),
 430                                    table.table[0].control_value);
 431 }
 432 
 433 static int emit_mocs_control_table(struct i915_request *rq,
 434                                    const struct drm_i915_mocs_table *table)
 435 {
 436         enum intel_engine_id engine = rq->engine->id;
 437         unsigned int index;
 438         u32 unused_value;
 439         u32 *cs;
 440 
 441         if (GEM_WARN_ON(table->size > table->n_entries))
 442                 return -ENODEV;
 443 
 444         /* Set unused values to PTE */
 445         unused_value = table->table[I915_MOCS_PTE].control_value;
 446 
 447         cs = intel_ring_begin(rq, 2 + 2 * table->n_entries);
 448         if (IS_ERR(cs))
 449                 return PTR_ERR(cs);
 450 
 451         *cs++ = MI_LOAD_REGISTER_IMM(table->n_entries);
 452 
 453         for (index = 0; index < table->size; index++) {
 454                 u32 value = get_entry_control(table, index);
 455 
 456                 *cs++ = i915_mmio_reg_offset(mocs_register(engine, index));
 457                 *cs++ = value;
 458         }
 459 
 460         /* All remaining entries are also unused */
 461         for (; index < table->n_entries; index++) {
 462                 *cs++ = i915_mmio_reg_offset(mocs_register(engine, index));
 463                 *cs++ = unused_value;
 464         }
 465 
 466         *cs++ = MI_NOOP;
 467         intel_ring_advance(rq, cs);
 468 
 469         return 0;
 470 }
 471 
 472 /*
 473  * Get l3cc_value from MOCS entry taking into account when it's not used:
 474  * I915_MOCS_PTE's value is returned in this case.
 475  */
 476 static u16 get_entry_l3cc(const struct drm_i915_mocs_table *table,
 477                           unsigned int index)
 478 {
 479         if (table->table[index].used)
 480                 return table->table[index].l3cc_value;
 481 
 482         return table->table[I915_MOCS_PTE].l3cc_value;
 483 }
 484 
 485 static inline u32 l3cc_combine(const struct drm_i915_mocs_table *table,
 486                                u16 low,
 487                                u16 high)
 488 {
 489         return low | high << 16;
 490 }
 491 
 492 static int emit_mocs_l3cc_table(struct i915_request *rq,
 493                                 const struct drm_i915_mocs_table *table)
 494 {
 495         u16 unused_value;
 496         unsigned int i;
 497         u32 *cs;
 498 
 499         if (GEM_WARN_ON(table->size > table->n_entries))
 500                 return -ENODEV;
 501 
 502         /* Set unused values to PTE */
 503         unused_value = table->table[I915_MOCS_PTE].l3cc_value;
 504 
 505         cs = intel_ring_begin(rq, 2 + table->n_entries);
 506         if (IS_ERR(cs))
 507                 return PTR_ERR(cs);
 508 
 509         *cs++ = MI_LOAD_REGISTER_IMM(table->n_entries / 2);
 510 
 511         for (i = 0; i < table->size / 2; i++) {
 512                 u16 low = get_entry_l3cc(table, 2 * i);
 513                 u16 high = get_entry_l3cc(table, 2 * i + 1);
 514 
 515                 *cs++ = i915_mmio_reg_offset(GEN9_LNCFCMOCS(i));
 516                 *cs++ = l3cc_combine(table, low, high);
 517         }
 518 
 519         /* Odd table size - 1 left over */
 520         if (table->size & 0x01) {
 521                 u16 low = get_entry_l3cc(table, 2 * i);
 522 
 523                 *cs++ = i915_mmio_reg_offset(GEN9_LNCFCMOCS(i));
 524                 *cs++ = l3cc_combine(table, low, unused_value);
 525                 i++;
 526         }
 527 
 528         /* All remaining entries are also unused */
 529         for (; i < table->n_entries / 2; i++) {
 530                 *cs++ = i915_mmio_reg_offset(GEN9_LNCFCMOCS(i));
 531                 *cs++ = l3cc_combine(table, unused_value, unused_value);
 532         }
 533 
 534         *cs++ = MI_NOOP;
 535         intel_ring_advance(rq, cs);
 536 
 537         return 0;
 538 }
 539 
 540 static void intel_mocs_init_l3cc_table(struct intel_gt *gt)
 541 {
 542         struct intel_uncore *uncore = gt->uncore;
 543         struct drm_i915_mocs_table table;
 544         unsigned int i;
 545         u16 unused_value;
 546 
 547         if (!get_mocs_settings(gt, &table))
 548                 return;
 549 
 550         /* Set unused values to PTE */
 551         unused_value = table.table[I915_MOCS_PTE].l3cc_value;
 552 
 553         for (i = 0; i < table.size / 2; i++) {
 554                 u16 low = get_entry_l3cc(&table, 2 * i);
 555                 u16 high = get_entry_l3cc(&table, 2 * i + 1);
 556 
 557                 intel_uncore_write(uncore,
 558                                    GEN9_LNCFCMOCS(i),
 559                                    l3cc_combine(&table, low, high));
 560         }
 561 
 562         /* Odd table size - 1 left over */
 563         if (table.size & 0x01) {
 564                 u16 low = get_entry_l3cc(&table, 2 * i);
 565 
 566                 intel_uncore_write(uncore,
 567                                    GEN9_LNCFCMOCS(i),
 568                                    l3cc_combine(&table, low, unused_value));
 569                 i++;
 570         }
 571 
 572         /* All remaining entries are also unused */
 573         for (; i < table.n_entries / 2; i++)
 574                 intel_uncore_write(uncore,
 575                                    GEN9_LNCFCMOCS(i),
 576                                    l3cc_combine(&table, unused_value,
 577                                                 unused_value));
 578 }
 579 
 580 /**
 581  * intel_mocs_emit() - program the MOCS register.
 582  * @rq: Request to use to set up the MOCS tables.
 583  *
 584  * This function will emit a batch buffer with the values required for
 585  * programming the MOCS register values for all the currently supported
 586  * rings.
 587  *
 588  * These registers are partially stored in the RCS context, so they are
 589  * emitted at the same time so that when a context is created these registers
 590  * are set up. These registers have to be emitted into the start of the
 591  * context as setting the ELSP will re-init some of these registers back
 592  * to the hw values.
 593  *
 594  * Return: 0 on success, otherwise the error status.
 595  */
 596 int intel_mocs_emit(struct i915_request *rq)
 597 {
 598         struct drm_i915_mocs_table t;
 599         int ret;
 600 
 601         if (HAS_GLOBAL_MOCS_REGISTERS(rq->i915) ||
 602             rq->engine->class != RENDER_CLASS)
 603                 return 0;
 604 
 605         if (get_mocs_settings(rq->engine->gt, &t)) {
 606                 /* Program the RCS control registers */
 607                 ret = emit_mocs_control_table(rq, &t);
 608                 if (ret)
 609                         return ret;
 610 
 611                 /* Now program the l3cc registers */
 612                 ret = emit_mocs_l3cc_table(rq, &t);
 613                 if (ret)
 614                         return ret;
 615         }
 616 
 617         return 0;
 618 }
 619 
 620 void intel_mocs_init(struct intel_gt *gt)
 621 {
 622         intel_mocs_init_l3cc_table(gt);
 623 
 624         if (HAS_GLOBAL_MOCS_REGISTERS(gt->i915))
 625                 intel_mocs_init_global(gt);
 626 }

/* [<][>][^][v][top][bottom][index][help] */