linux/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_cik.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 <linux/printk.h>
  25#include <linux/slab.h>
  26#include <linux/mm_types.h>
  27
  28#include "kfd_priv.h"
  29#include "kfd_mqd_manager.h"
  30#include "cik_regs.h"
  31#include "cik_structs.h"
  32#include "oss/oss_2_4_sh_mask.h"
  33
  34static inline struct cik_mqd *get_mqd(void *mqd)
  35{
  36        return (struct cik_mqd *)mqd;
  37}
  38
  39static inline struct cik_sdma_rlc_registers *get_sdma_mqd(void *mqd)
  40{
  41        return (struct cik_sdma_rlc_registers *)mqd;
  42}
  43
  44static void update_cu_mask(struct mqd_manager *mm, void *mqd,
  45                        struct queue_properties *q)
  46{
  47        struct cik_mqd *m;
  48        uint32_t se_mask[4] = {0}; /* 4 is the max # of SEs */
  49
  50        if (q->cu_mask_count == 0)
  51                return;
  52
  53        mqd_symmetrically_map_cu_mask(mm,
  54                q->cu_mask, q->cu_mask_count, se_mask);
  55
  56        m = get_mqd(mqd);
  57        m->compute_static_thread_mgmt_se0 = se_mask[0];
  58        m->compute_static_thread_mgmt_se1 = se_mask[1];
  59        m->compute_static_thread_mgmt_se2 = se_mask[2];
  60        m->compute_static_thread_mgmt_se3 = se_mask[3];
  61
  62        pr_debug("Update cu mask to %#x %#x %#x %#x\n",
  63                m->compute_static_thread_mgmt_se0,
  64                m->compute_static_thread_mgmt_se1,
  65                m->compute_static_thread_mgmt_se2,
  66                m->compute_static_thread_mgmt_se3);
  67}
  68
  69static void set_priority(struct cik_mqd *m, struct queue_properties *q)
  70{
  71        m->cp_hqd_pipe_priority = pipe_priority_map[q->priority];
  72        m->cp_hqd_queue_priority = q->priority;
  73}
  74
  75static struct kfd_mem_obj *allocate_mqd(struct kfd_dev *kfd,
  76                                        struct queue_properties *q)
  77{
  78        struct kfd_mem_obj *mqd_mem_obj;
  79
  80        if (kfd_gtt_sa_allocate(kfd, sizeof(struct cik_mqd),
  81                        &mqd_mem_obj))
  82                return NULL;
  83
  84        return mqd_mem_obj;
  85}
  86
  87static void init_mqd(struct mqd_manager *mm, void **mqd,
  88                struct kfd_mem_obj *mqd_mem_obj, uint64_t *gart_addr,
  89                struct queue_properties *q)
  90{
  91        uint64_t addr;
  92        struct cik_mqd *m;
  93
  94        m = (struct cik_mqd *) mqd_mem_obj->cpu_ptr;
  95        addr = mqd_mem_obj->gpu_addr;
  96
  97        memset(m, 0, ALIGN(sizeof(struct cik_mqd), 256));
  98
  99        m->header = 0xC0310800;
 100        m->compute_pipelinestat_enable = 1;
 101        m->compute_static_thread_mgmt_se0 = 0xFFFFFFFF;
 102        m->compute_static_thread_mgmt_se1 = 0xFFFFFFFF;
 103        m->compute_static_thread_mgmt_se2 = 0xFFFFFFFF;
 104        m->compute_static_thread_mgmt_se3 = 0xFFFFFFFF;
 105
 106        /*
 107         * Make sure to use the last queue state saved on mqd when the cp
 108         * reassigns the queue, so when queue is switched on/off (e.g over
 109         * subscription or quantum timeout) the context will be consistent
 110         */
 111        m->cp_hqd_persistent_state =
 112                                DEFAULT_CP_HQD_PERSISTENT_STATE | PRELOAD_REQ;
 113
 114        m->cp_mqd_control             = MQD_CONTROL_PRIV_STATE_EN;
 115        m->cp_mqd_base_addr_lo        = lower_32_bits(addr);
 116        m->cp_mqd_base_addr_hi        = upper_32_bits(addr);
 117
 118        m->cp_hqd_quantum = QUANTUM_EN | QUANTUM_SCALE_1MS |
 119                                QUANTUM_DURATION(10);
 120
 121        /*
 122         * Pipe Priority
 123         * Identifies the pipe relative priority when this queue is connected
 124         * to the pipeline. The pipe priority is against the GFX pipe and HP3D.
 125         * In KFD we are using a fixed pipe priority set to CS_MEDIUM.
 126         * 0 = CS_LOW (typically below GFX)
 127         * 1 = CS_MEDIUM (typically between HP3D and GFX
 128         * 2 = CS_HIGH (typically above HP3D)
 129         */
 130        set_priority(m, q);
 131
 132        if (q->format == KFD_QUEUE_FORMAT_AQL)
 133                m->cp_hqd_iq_rptr = AQL_ENABLE;
 134
 135        *mqd = m;
 136        if (gart_addr)
 137                *gart_addr = addr;
 138        mm->update_mqd(mm, m, q);
 139}
 140
 141static void init_mqd_sdma(struct mqd_manager *mm, void **mqd,
 142                        struct kfd_mem_obj *mqd_mem_obj, uint64_t *gart_addr,
 143                        struct queue_properties *q)
 144{
 145        struct cik_sdma_rlc_registers *m;
 146
 147        m = (struct cik_sdma_rlc_registers *) mqd_mem_obj->cpu_ptr;
 148
 149        memset(m, 0, sizeof(struct cik_sdma_rlc_registers));
 150
 151        *mqd = m;
 152        if (gart_addr)
 153                *gart_addr = mqd_mem_obj->gpu_addr;
 154
 155        mm->update_mqd(mm, m, q);
 156}
 157
 158static void free_mqd(struct mqd_manager *mm, void *mqd,
 159                        struct kfd_mem_obj *mqd_mem_obj)
 160{
 161        kfd_gtt_sa_free(mm->dev, mqd_mem_obj);
 162}
 163
 164
 165static int load_mqd(struct mqd_manager *mm, void *mqd, uint32_t pipe_id,
 166                    uint32_t queue_id, struct queue_properties *p,
 167                    struct mm_struct *mms)
 168{
 169        /* AQL write pointer counts in 64B packets, PM4/CP counts in dwords. */
 170        uint32_t wptr_shift = (p->format == KFD_QUEUE_FORMAT_AQL ? 4 : 0);
 171        uint32_t wptr_mask = (uint32_t)((p->queue_size / 4) - 1);
 172
 173        return mm->dev->kfd2kgd->hqd_load(mm->dev->kgd, mqd, pipe_id, queue_id,
 174                                          (uint32_t __user *)p->write_ptr,
 175                                          wptr_shift, wptr_mask, mms);
 176}
 177
 178static int load_mqd_sdma(struct mqd_manager *mm, void *mqd,
 179                         uint32_t pipe_id, uint32_t queue_id,
 180                         struct queue_properties *p, struct mm_struct *mms)
 181{
 182        return mm->dev->kfd2kgd->hqd_sdma_load(mm->dev->kgd, mqd,
 183                                               (uint32_t __user *)p->write_ptr,
 184                                               mms);
 185}
 186
 187static void __update_mqd(struct mqd_manager *mm, void *mqd,
 188                        struct queue_properties *q, unsigned int atc_bit)
 189{
 190        struct cik_mqd *m;
 191
 192        m = get_mqd(mqd);
 193        m->cp_hqd_pq_control = DEFAULT_RPTR_BLOCK_SIZE |
 194                                DEFAULT_MIN_AVAIL_SIZE;
 195        m->cp_hqd_ib_control = DEFAULT_MIN_IB_AVAIL_SIZE;
 196        if (atc_bit) {
 197                m->cp_hqd_pq_control |= PQ_ATC_EN;
 198                m->cp_hqd_ib_control |= IB_ATC_EN;
 199        }
 200
 201        /*
 202         * Calculating queue size which is log base 2 of actual queue size -1
 203         * dwords and another -1 for ffs
 204         */
 205        m->cp_hqd_pq_control |= order_base_2(q->queue_size / 4) - 1;
 206        m->cp_hqd_pq_base_lo = lower_32_bits((uint64_t)q->queue_address >> 8);
 207        m->cp_hqd_pq_base_hi = upper_32_bits((uint64_t)q->queue_address >> 8);
 208        m->cp_hqd_pq_rptr_report_addr_lo = lower_32_bits((uint64_t)q->read_ptr);
 209        m->cp_hqd_pq_rptr_report_addr_hi = upper_32_bits((uint64_t)q->read_ptr);
 210        m->cp_hqd_pq_doorbell_control = DOORBELL_OFFSET(q->doorbell_off);
 211
 212        m->cp_hqd_vmid = q->vmid;
 213
 214        if (q->format == KFD_QUEUE_FORMAT_AQL)
 215                m->cp_hqd_pq_control |= NO_UPDATE_RPTR;
 216
 217        update_cu_mask(mm, mqd, q);
 218        set_priority(m, q);
 219
 220        q->is_active = QUEUE_IS_ACTIVE(*q);
 221}
 222
 223static void update_mqd(struct mqd_manager *mm, void *mqd,
 224                        struct queue_properties *q)
 225{
 226        __update_mqd(mm, mqd, q, 1);
 227}
 228
 229static void update_mqd_hawaii(struct mqd_manager *mm, void *mqd,
 230                        struct queue_properties *q)
 231{
 232        __update_mqd(mm, mqd, q, 0);
 233}
 234
 235static void update_mqd_sdma(struct mqd_manager *mm, void *mqd,
 236                                struct queue_properties *q)
 237{
 238        struct cik_sdma_rlc_registers *m;
 239
 240        m = get_sdma_mqd(mqd);
 241        m->sdma_rlc_rb_cntl = order_base_2(q->queue_size / 4)
 242                        << SDMA0_RLC0_RB_CNTL__RB_SIZE__SHIFT |
 243                        q->vmid << SDMA0_RLC0_RB_CNTL__RB_VMID__SHIFT |
 244                        1 << SDMA0_RLC0_RB_CNTL__RPTR_WRITEBACK_ENABLE__SHIFT |
 245                        6 << SDMA0_RLC0_RB_CNTL__RPTR_WRITEBACK_TIMER__SHIFT;
 246
 247        m->sdma_rlc_rb_base = lower_32_bits(q->queue_address >> 8);
 248        m->sdma_rlc_rb_base_hi = upper_32_bits(q->queue_address >> 8);
 249        m->sdma_rlc_rb_rptr_addr_lo = lower_32_bits((uint64_t)q->read_ptr);
 250        m->sdma_rlc_rb_rptr_addr_hi = upper_32_bits((uint64_t)q->read_ptr);
 251        m->sdma_rlc_doorbell =
 252                q->doorbell_off << SDMA0_RLC0_DOORBELL__OFFSET__SHIFT;
 253
 254        m->sdma_rlc_virtual_addr = q->sdma_vm_addr;
 255
 256        m->sdma_engine_id = q->sdma_engine_id;
 257        m->sdma_queue_id = q->sdma_queue_id;
 258
 259        q->is_active = QUEUE_IS_ACTIVE(*q);
 260}
 261
 262static int destroy_mqd(struct mqd_manager *mm, void *mqd,
 263                        enum kfd_preempt_type type,
 264                        unsigned int timeout, uint32_t pipe_id,
 265                        uint32_t queue_id)
 266{
 267        return mm->dev->kfd2kgd->hqd_destroy(mm->dev->kgd, mqd, type, timeout,
 268                                        pipe_id, queue_id);
 269}
 270
 271/*
 272 * preempt type here is ignored because there is only one way
 273 * to preempt sdma queue
 274 */
 275static int destroy_mqd_sdma(struct mqd_manager *mm, void *mqd,
 276                                enum kfd_preempt_type type,
 277                                unsigned int timeout, uint32_t pipe_id,
 278                                uint32_t queue_id)
 279{
 280        return mm->dev->kfd2kgd->hqd_sdma_destroy(mm->dev->kgd, mqd, timeout);
 281}
 282
 283static bool is_occupied(struct mqd_manager *mm, void *mqd,
 284                        uint64_t queue_address, uint32_t pipe_id,
 285                        uint32_t queue_id)
 286{
 287
 288        return mm->dev->kfd2kgd->hqd_is_occupied(mm->dev->kgd, queue_address,
 289                                        pipe_id, queue_id);
 290
 291}
 292
 293static bool is_occupied_sdma(struct mqd_manager *mm, void *mqd,
 294                        uint64_t queue_address, uint32_t pipe_id,
 295                        uint32_t queue_id)
 296{
 297        return mm->dev->kfd2kgd->hqd_sdma_is_occupied(mm->dev->kgd, mqd);
 298}
 299
 300/*
 301 * HIQ MQD Implementation, concrete implementation for HIQ MQD implementation.
 302 * The HIQ queue in Kaveri is using the same MQD structure as all the user mode
 303 * queues but with different initial values.
 304 */
 305
 306static void init_mqd_hiq(struct mqd_manager *mm, void **mqd,
 307                struct kfd_mem_obj *mqd_mem_obj, uint64_t *gart_addr,
 308                struct queue_properties *q)
 309{
 310        init_mqd(mm, mqd, mqd_mem_obj, gart_addr, q);
 311}
 312
 313static void update_mqd_hiq(struct mqd_manager *mm, void *mqd,
 314                                struct queue_properties *q)
 315{
 316        struct cik_mqd *m;
 317
 318        m = get_mqd(mqd);
 319        m->cp_hqd_pq_control = DEFAULT_RPTR_BLOCK_SIZE |
 320                                DEFAULT_MIN_AVAIL_SIZE |
 321                                PRIV_STATE |
 322                                KMD_QUEUE;
 323
 324        /*
 325         * Calculating queue size which is log base 2 of actual queue
 326         * size -1 dwords
 327         */
 328        m->cp_hqd_pq_control |= order_base_2(q->queue_size / 4) - 1;
 329        m->cp_hqd_pq_base_lo = lower_32_bits((uint64_t)q->queue_address >> 8);
 330        m->cp_hqd_pq_base_hi = upper_32_bits((uint64_t)q->queue_address >> 8);
 331        m->cp_hqd_pq_rptr_report_addr_lo = lower_32_bits((uint64_t)q->read_ptr);
 332        m->cp_hqd_pq_rptr_report_addr_hi = upper_32_bits((uint64_t)q->read_ptr);
 333        m->cp_hqd_pq_doorbell_control = DOORBELL_OFFSET(q->doorbell_off);
 334
 335        m->cp_hqd_vmid = q->vmid;
 336
 337        q->is_active = QUEUE_IS_ACTIVE(*q);
 338
 339        set_priority(m, q);
 340}
 341
 342#if defined(CONFIG_DEBUG_FS)
 343
 344static int debugfs_show_mqd(struct seq_file *m, void *data)
 345{
 346        seq_hex_dump(m, "    ", DUMP_PREFIX_OFFSET, 32, 4,
 347                     data, sizeof(struct cik_mqd), false);
 348        return 0;
 349}
 350
 351static int debugfs_show_mqd_sdma(struct seq_file *m, void *data)
 352{
 353        seq_hex_dump(m, "    ", DUMP_PREFIX_OFFSET, 32, 4,
 354                     data, sizeof(struct cik_sdma_rlc_registers), false);
 355        return 0;
 356}
 357
 358#endif
 359
 360
 361struct mqd_manager *mqd_manager_init_cik(enum KFD_MQD_TYPE type,
 362                struct kfd_dev *dev)
 363{
 364        struct mqd_manager *mqd;
 365
 366        if (WARN_ON(type >= KFD_MQD_TYPE_MAX))
 367                return NULL;
 368
 369        mqd = kzalloc(sizeof(*mqd), GFP_KERNEL);
 370        if (!mqd)
 371                return NULL;
 372
 373        mqd->dev = dev;
 374
 375        switch (type) {
 376        case KFD_MQD_TYPE_CP:
 377        case KFD_MQD_TYPE_COMPUTE:
 378                mqd->allocate_mqd = allocate_mqd;
 379                mqd->init_mqd = init_mqd;
 380                mqd->free_mqd = free_mqd;
 381                mqd->load_mqd = load_mqd;
 382                mqd->update_mqd = update_mqd;
 383                mqd->destroy_mqd = destroy_mqd;
 384                mqd->is_occupied = is_occupied;
 385                mqd->mqd_size = sizeof(struct cik_mqd);
 386#if defined(CONFIG_DEBUG_FS)
 387                mqd->debugfs_show_mqd = debugfs_show_mqd;
 388#endif
 389                break;
 390        case KFD_MQD_TYPE_HIQ:
 391                mqd->allocate_mqd = allocate_hiq_mqd;
 392                mqd->init_mqd = init_mqd_hiq;
 393                mqd->free_mqd = free_mqd_hiq_sdma;
 394                mqd->load_mqd = load_mqd;
 395                mqd->update_mqd = update_mqd_hiq;
 396                mqd->destroy_mqd = destroy_mqd;
 397                mqd->is_occupied = is_occupied;
 398                mqd->mqd_size = sizeof(struct cik_mqd);
 399#if defined(CONFIG_DEBUG_FS)
 400                mqd->debugfs_show_mqd = debugfs_show_mqd;
 401#endif
 402                break;
 403        case KFD_MQD_TYPE_DIQ:
 404                mqd->allocate_mqd = allocate_hiq_mqd;
 405                mqd->init_mqd = init_mqd_hiq;
 406                mqd->free_mqd = free_mqd;
 407                mqd->load_mqd = load_mqd;
 408                mqd->update_mqd = update_mqd_hiq;
 409                mqd->destroy_mqd = destroy_mqd;
 410                mqd->is_occupied = is_occupied;
 411                mqd->mqd_size = sizeof(struct cik_mqd);
 412#if defined(CONFIG_DEBUG_FS)
 413                mqd->debugfs_show_mqd = debugfs_show_mqd;
 414#endif
 415                break;
 416        case KFD_MQD_TYPE_SDMA:
 417                mqd->allocate_mqd = allocate_sdma_mqd;
 418                mqd->init_mqd = init_mqd_sdma;
 419                mqd->free_mqd = free_mqd_hiq_sdma;
 420                mqd->load_mqd = load_mqd_sdma;
 421                mqd->update_mqd = update_mqd_sdma;
 422                mqd->destroy_mqd = destroy_mqd_sdma;
 423                mqd->is_occupied = is_occupied_sdma;
 424                mqd->mqd_size = sizeof(struct cik_sdma_rlc_registers);
 425#if defined(CONFIG_DEBUG_FS)
 426                mqd->debugfs_show_mqd = debugfs_show_mqd_sdma;
 427#endif
 428                break;
 429        default:
 430                kfree(mqd);
 431                return NULL;
 432        }
 433
 434        return mqd;
 435}
 436
 437struct mqd_manager *mqd_manager_init_cik_hawaii(enum KFD_MQD_TYPE type,
 438                        struct kfd_dev *dev)
 439{
 440        struct mqd_manager *mqd;
 441
 442        mqd = mqd_manager_init_cik(type, dev);
 443        if (!mqd)
 444                return NULL;
 445        if ((type == KFD_MQD_TYPE_CP) || (type == KFD_MQD_TYPE_COMPUTE))
 446                mqd->update_mqd = update_mqd_hawaii;
 447        return mqd;
 448}
 449