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 uint32_t read_doorbell_id(void *mqd)
 230{
 231        struct cik_mqd *m = (struct cik_mqd *)mqd;
 232
 233        return m->queue_doorbell_id0;
 234}
 235
 236static void update_mqd_hawaii(struct mqd_manager *mm, void *mqd,
 237                        struct queue_properties *q)
 238{
 239        __update_mqd(mm, mqd, q, 0);
 240}
 241
 242static void update_mqd_sdma(struct mqd_manager *mm, void *mqd,
 243                                struct queue_properties *q)
 244{
 245        struct cik_sdma_rlc_registers *m;
 246
 247        m = get_sdma_mqd(mqd);
 248        m->sdma_rlc_rb_cntl = order_base_2(q->queue_size / 4)
 249                        << SDMA0_RLC0_RB_CNTL__RB_SIZE__SHIFT |
 250                        q->vmid << SDMA0_RLC0_RB_CNTL__RB_VMID__SHIFT |
 251                        1 << SDMA0_RLC0_RB_CNTL__RPTR_WRITEBACK_ENABLE__SHIFT |
 252                        6 << SDMA0_RLC0_RB_CNTL__RPTR_WRITEBACK_TIMER__SHIFT;
 253
 254        m->sdma_rlc_rb_base = lower_32_bits(q->queue_address >> 8);
 255        m->sdma_rlc_rb_base_hi = upper_32_bits(q->queue_address >> 8);
 256        m->sdma_rlc_rb_rptr_addr_lo = lower_32_bits((uint64_t)q->read_ptr);
 257        m->sdma_rlc_rb_rptr_addr_hi = upper_32_bits((uint64_t)q->read_ptr);
 258        m->sdma_rlc_doorbell =
 259                q->doorbell_off << SDMA0_RLC0_DOORBELL__OFFSET__SHIFT;
 260
 261        m->sdma_rlc_virtual_addr = q->sdma_vm_addr;
 262
 263        m->sdma_engine_id = q->sdma_engine_id;
 264        m->sdma_queue_id = q->sdma_queue_id;
 265
 266        q->is_active = QUEUE_IS_ACTIVE(*q);
 267}
 268
 269static int destroy_mqd(struct mqd_manager *mm, void *mqd,
 270                        enum kfd_preempt_type type,
 271                        unsigned int timeout, uint32_t pipe_id,
 272                        uint32_t queue_id)
 273{
 274        return mm->dev->kfd2kgd->hqd_destroy(mm->dev->kgd, mqd, type, timeout,
 275                                        pipe_id, queue_id);
 276}
 277
 278/*
 279 * preempt type here is ignored because there is only one way
 280 * to preempt sdma queue
 281 */
 282static int destroy_mqd_sdma(struct mqd_manager *mm, void *mqd,
 283                                enum kfd_preempt_type type,
 284                                unsigned int timeout, uint32_t pipe_id,
 285                                uint32_t queue_id)
 286{
 287        return mm->dev->kfd2kgd->hqd_sdma_destroy(mm->dev->kgd, mqd, timeout);
 288}
 289
 290static bool is_occupied(struct mqd_manager *mm, void *mqd,
 291                        uint64_t queue_address, uint32_t pipe_id,
 292                        uint32_t queue_id)
 293{
 294
 295        return mm->dev->kfd2kgd->hqd_is_occupied(mm->dev->kgd, queue_address,
 296                                        pipe_id, queue_id);
 297
 298}
 299
 300static bool is_occupied_sdma(struct mqd_manager *mm, void *mqd,
 301                        uint64_t queue_address, uint32_t pipe_id,
 302                        uint32_t queue_id)
 303{
 304        return mm->dev->kfd2kgd->hqd_sdma_is_occupied(mm->dev->kgd, mqd);
 305}
 306
 307/*
 308 * HIQ MQD Implementation, concrete implementation for HIQ MQD implementation.
 309 * The HIQ queue in Kaveri is using the same MQD structure as all the user mode
 310 * queues but with different initial values.
 311 */
 312
 313static void init_mqd_hiq(struct mqd_manager *mm, void **mqd,
 314                struct kfd_mem_obj *mqd_mem_obj, uint64_t *gart_addr,
 315                struct queue_properties *q)
 316{
 317        init_mqd(mm, mqd, mqd_mem_obj, gart_addr, q);
 318}
 319
 320static void update_mqd_hiq(struct mqd_manager *mm, void *mqd,
 321                                struct queue_properties *q)
 322{
 323        struct cik_mqd *m;
 324
 325        m = get_mqd(mqd);
 326        m->cp_hqd_pq_control = DEFAULT_RPTR_BLOCK_SIZE |
 327                                DEFAULT_MIN_AVAIL_SIZE |
 328                                PRIV_STATE |
 329                                KMD_QUEUE;
 330
 331        /*
 332         * Calculating queue size which is log base 2 of actual queue
 333         * size -1 dwords
 334         */
 335        m->cp_hqd_pq_control |= order_base_2(q->queue_size / 4) - 1;
 336        m->cp_hqd_pq_base_lo = lower_32_bits((uint64_t)q->queue_address >> 8);
 337        m->cp_hqd_pq_base_hi = upper_32_bits((uint64_t)q->queue_address >> 8);
 338        m->cp_hqd_pq_rptr_report_addr_lo = lower_32_bits((uint64_t)q->read_ptr);
 339        m->cp_hqd_pq_rptr_report_addr_hi = upper_32_bits((uint64_t)q->read_ptr);
 340        m->cp_hqd_pq_doorbell_control = DOORBELL_OFFSET(q->doorbell_off);
 341
 342        m->cp_hqd_vmid = q->vmid;
 343
 344        q->is_active = QUEUE_IS_ACTIVE(*q);
 345
 346        set_priority(m, q);
 347}
 348
 349#if defined(CONFIG_DEBUG_FS)
 350
 351static int debugfs_show_mqd(struct seq_file *m, void *data)
 352{
 353        seq_hex_dump(m, "    ", DUMP_PREFIX_OFFSET, 32, 4,
 354                     data, sizeof(struct cik_mqd), false);
 355        return 0;
 356}
 357
 358static int debugfs_show_mqd_sdma(struct seq_file *m, void *data)
 359{
 360        seq_hex_dump(m, "    ", DUMP_PREFIX_OFFSET, 32, 4,
 361                     data, sizeof(struct cik_sdma_rlc_registers), false);
 362        return 0;
 363}
 364
 365#endif
 366
 367
 368struct mqd_manager *mqd_manager_init_cik(enum KFD_MQD_TYPE type,
 369                struct kfd_dev *dev)
 370{
 371        struct mqd_manager *mqd;
 372
 373        if (WARN_ON(type >= KFD_MQD_TYPE_MAX))
 374                return NULL;
 375
 376        mqd = kzalloc(sizeof(*mqd), GFP_KERNEL);
 377        if (!mqd)
 378                return NULL;
 379
 380        mqd->dev = dev;
 381
 382        switch (type) {
 383        case KFD_MQD_TYPE_CP:
 384                mqd->allocate_mqd = allocate_mqd;
 385                mqd->init_mqd = init_mqd;
 386                mqd->free_mqd = free_mqd;
 387                mqd->load_mqd = load_mqd;
 388                mqd->update_mqd = update_mqd;
 389                mqd->destroy_mqd = destroy_mqd;
 390                mqd->is_occupied = is_occupied;
 391                mqd->mqd_size = sizeof(struct cik_mqd);
 392#if defined(CONFIG_DEBUG_FS)
 393                mqd->debugfs_show_mqd = debugfs_show_mqd;
 394#endif
 395                break;
 396        case KFD_MQD_TYPE_HIQ:
 397                mqd->allocate_mqd = allocate_hiq_mqd;
 398                mqd->init_mqd = init_mqd_hiq;
 399                mqd->free_mqd = free_mqd_hiq_sdma;
 400                mqd->load_mqd = load_mqd;
 401                mqd->update_mqd = update_mqd_hiq;
 402                mqd->destroy_mqd = destroy_mqd;
 403                mqd->is_occupied = is_occupied;
 404                mqd->mqd_size = sizeof(struct cik_mqd);
 405#if defined(CONFIG_DEBUG_FS)
 406                mqd->debugfs_show_mqd = debugfs_show_mqd;
 407#endif
 408                mqd->read_doorbell_id = read_doorbell_id;
 409                break;
 410        case KFD_MQD_TYPE_DIQ:
 411                mqd->allocate_mqd = allocate_mqd;
 412                mqd->init_mqd = init_mqd_hiq;
 413                mqd->free_mqd = free_mqd;
 414                mqd->load_mqd = load_mqd;
 415                mqd->update_mqd = update_mqd_hiq;
 416                mqd->destroy_mqd = destroy_mqd;
 417                mqd->is_occupied = is_occupied;
 418                mqd->mqd_size = sizeof(struct cik_mqd);
 419#if defined(CONFIG_DEBUG_FS)
 420                mqd->debugfs_show_mqd = debugfs_show_mqd;
 421#endif
 422                break;
 423        case KFD_MQD_TYPE_SDMA:
 424                mqd->allocate_mqd = allocate_sdma_mqd;
 425                mqd->init_mqd = init_mqd_sdma;
 426                mqd->free_mqd = free_mqd_hiq_sdma;
 427                mqd->load_mqd = load_mqd_sdma;
 428                mqd->update_mqd = update_mqd_sdma;
 429                mqd->destroy_mqd = destroy_mqd_sdma;
 430                mqd->is_occupied = is_occupied_sdma;
 431                mqd->mqd_size = sizeof(struct cik_sdma_rlc_registers);
 432#if defined(CONFIG_DEBUG_FS)
 433                mqd->debugfs_show_mqd = debugfs_show_mqd_sdma;
 434#endif
 435                break;
 436        default:
 437                kfree(mqd);
 438                return NULL;
 439        }
 440
 441        return mqd;
 442}
 443
 444struct mqd_manager *mqd_manager_init_cik_hawaii(enum KFD_MQD_TYPE type,
 445                        struct kfd_dev *dev)
 446{
 447        struct mqd_manager *mqd;
 448
 449        mqd = mqd_manager_init_cik(type, dev);
 450        if (!mqd)
 451                return NULL;
 452        if (type == KFD_MQD_TYPE_CP)
 453                mqd->update_mqd = update_mqd_hawaii;
 454        return mqd;
 455}
 456