linux/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager_vi.c
<<
>>
Prefs
   1/*
   2 * Copyright 2014 Advanced Micro Devices, Inc.
   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 *
  11 * The above copyright notice and this permission notice shall be included in
  12 * all copies or substantial portions of the 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
  18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
  19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
  20 * OTHER DEALINGS IN THE SOFTWARE.
  21 *
  22 */
  23
  24#include "kfd_device_queue_manager.h"
  25#include "gca/gfx_8_0_enum.h"
  26#include "gca/gfx_8_0_sh_mask.h"
  27#include "gca/gfx_8_0_enum.h"
  28#include "oss/oss_3_0_sh_mask.h"
  29
  30static bool set_cache_memory_policy_vi(struct device_queue_manager *dqm,
  31                                   struct qcm_process_device *qpd,
  32                                   enum cache_policy default_policy,
  33                                   enum cache_policy alternate_policy,
  34                                   void __user *alternate_aperture_base,
  35                                   uint64_t alternate_aperture_size);
  36static int register_process_vi(struct device_queue_manager *dqm,
  37                                        struct qcm_process_device *qpd);
  38static int initialize_cpsch_vi(struct device_queue_manager *dqm);
  39static void init_sdma_vm(struct device_queue_manager *dqm, struct queue *q,
  40                                struct qcm_process_device *qpd);
  41
  42void device_queue_manager_init_vi(struct device_queue_manager_asic_ops *ops)
  43{
  44        ops->set_cache_memory_policy = set_cache_memory_policy_vi;
  45        ops->register_process = register_process_vi;
  46        ops->initialize = initialize_cpsch_vi;
  47        ops->init_sdma_vm = init_sdma_vm;
  48}
  49
  50static uint32_t compute_sh_mem_bases_64bit(unsigned int top_address_nybble)
  51{
  52        /* In 64-bit mode, we can only control the top 3 bits of the LDS,
  53         * scratch and GPUVM apertures.
  54         * The hardware fills in the remaining 59 bits according to the
  55         * following pattern:
  56         * LDS:         X0000000'00000000 - X0000001'00000000 (4GB)
  57         * Scratch:     X0000001'00000000 - X0000002'00000000 (4GB)
  58         * GPUVM:       Y0010000'00000000 - Y0020000'00000000 (1TB)
  59         *
  60         * (where X/Y is the configurable nybble with the low-bit 0)
  61         *
  62         * LDS and scratch will have the same top nybble programmed in the
  63         * top 3 bits of SH_MEM_BASES.PRIVATE_BASE.
  64         * GPUVM can have a different top nybble programmed in the
  65         * top 3 bits of SH_MEM_BASES.SHARED_BASE.
  66         * We don't bother to support different top nybbles
  67         * for LDS/Scratch and GPUVM.
  68         */
  69
  70        BUG_ON((top_address_nybble & 1) || top_address_nybble > 0xE ||
  71                top_address_nybble == 0);
  72
  73        return top_address_nybble << 12 |
  74                        (top_address_nybble << 12) <<
  75                        SH_MEM_BASES__SHARED_BASE__SHIFT;
  76}
  77
  78static bool set_cache_memory_policy_vi(struct device_queue_manager *dqm,
  79                                   struct qcm_process_device *qpd,
  80                                   enum cache_policy default_policy,
  81                                   enum cache_policy alternate_policy,
  82                                   void __user *alternate_aperture_base,
  83                                   uint64_t alternate_aperture_size)
  84{
  85        uint32_t default_mtype;
  86        uint32_t ape1_mtype;
  87
  88        default_mtype = (default_policy == cache_policy_coherent) ?
  89                        MTYPE_CC :
  90                        MTYPE_NC;
  91
  92        ape1_mtype = (alternate_policy == cache_policy_coherent) ?
  93                        MTYPE_CC :
  94                        MTYPE_NC;
  95
  96        qpd->sh_mem_config = (qpd->sh_mem_config &
  97                        SH_MEM_CONFIG__ADDRESS_MODE_MASK) |
  98                SH_MEM_ALIGNMENT_MODE_UNALIGNED <<
  99                                SH_MEM_CONFIG__ALIGNMENT_MODE__SHIFT |
 100                default_mtype << SH_MEM_CONFIG__DEFAULT_MTYPE__SHIFT |
 101                ape1_mtype << SH_MEM_CONFIG__APE1_MTYPE__SHIFT |
 102                SH_MEM_CONFIG__PRIVATE_ATC_MASK;
 103
 104        return true;
 105}
 106
 107static int register_process_vi(struct device_queue_manager *dqm,
 108                                        struct qcm_process_device *qpd)
 109{
 110        struct kfd_process_device *pdd;
 111        unsigned int temp;
 112
 113        BUG_ON(!dqm || !qpd);
 114
 115        pdd = qpd_to_pdd(qpd);
 116
 117        /* check if sh_mem_config register already configured */
 118        if (qpd->sh_mem_config == 0) {
 119                qpd->sh_mem_config =
 120                        SH_MEM_ALIGNMENT_MODE_UNALIGNED <<
 121                                SH_MEM_CONFIG__ALIGNMENT_MODE__SHIFT |
 122                        MTYPE_CC << SH_MEM_CONFIG__DEFAULT_MTYPE__SHIFT |
 123                        MTYPE_CC << SH_MEM_CONFIG__APE1_MTYPE__SHIFT |
 124                        SH_MEM_CONFIG__PRIVATE_ATC_MASK;
 125
 126                qpd->sh_mem_ape1_limit = 0;
 127                qpd->sh_mem_ape1_base = 0;
 128        }
 129
 130        if (qpd->pqm->process->is_32bit_user_mode) {
 131                temp = get_sh_mem_bases_32(pdd);
 132                qpd->sh_mem_bases = temp << SH_MEM_BASES__SHARED_BASE__SHIFT;
 133                qpd->sh_mem_config |= SH_MEM_ADDRESS_MODE_HSA32 <<
 134                                        SH_MEM_CONFIG__ADDRESS_MODE__SHIFT;
 135        } else {
 136                temp = get_sh_mem_bases_nybble_64(pdd);
 137                qpd->sh_mem_bases = compute_sh_mem_bases_64bit(temp);
 138                qpd->sh_mem_config |= SH_MEM_ADDRESS_MODE_HSA64 <<
 139                        SH_MEM_CONFIG__ADDRESS_MODE__SHIFT;
 140        }
 141
 142        pr_debug("kfd: is32bit process: %d sh_mem_bases nybble: 0x%X and register 0x%X\n",
 143                qpd->pqm->process->is_32bit_user_mode, temp, qpd->sh_mem_bases);
 144
 145        return 0;
 146}
 147
 148static void init_sdma_vm(struct device_queue_manager *dqm, struct queue *q,
 149                                struct qcm_process_device *qpd)
 150{
 151        uint32_t value = (1 << SDMA0_RLC0_VIRTUAL_ADDR__ATC__SHIFT);
 152
 153        if (q->process->is_32bit_user_mode)
 154                value |= (1 << SDMA0_RLC0_VIRTUAL_ADDR__PTR32__SHIFT) |
 155                                get_sh_mem_bases_32(qpd_to_pdd(qpd));
 156        else
 157                value |= ((get_sh_mem_bases_nybble_64(qpd_to_pdd(qpd))) <<
 158                                SDMA0_RLC0_VIRTUAL_ADDR__SHARED_BASE__SHIFT) &
 159                                SDMA0_RLC0_VIRTUAL_ADDR__SHARED_BASE_MASK;
 160
 161        q->properties.sdma_vm_addr = value;
 162}
 163
 164static int initialize_cpsch_vi(struct device_queue_manager *dqm)
 165{
 166        return 0;
 167}
 168