linux/drivers/gpu/drm/amd/amdkfd/kfd_packet_manager.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/slab.h>
  25#include <linux/mutex.h>
  26#include "kfd_device_queue_manager.h"
  27#include "kfd_kernel_queue.h"
  28#include "kfd_priv.h"
  29
  30static inline void inc_wptr(unsigned int *wptr, unsigned int increment_bytes,
  31                                unsigned int buffer_size_bytes)
  32{
  33        unsigned int temp = *wptr + increment_bytes / sizeof(uint32_t);
  34
  35        WARN((temp * sizeof(uint32_t)) > buffer_size_bytes,
  36             "Runlist IB overflow");
  37        *wptr = temp;
  38}
  39
  40static void pm_calc_rlib_size(struct packet_manager *pm,
  41                                unsigned int *rlib_size,
  42                                bool *over_subscription)
  43{
  44        unsigned int process_count, queue_count, compute_queue_count, gws_queue_count;
  45        unsigned int map_queue_size;
  46        unsigned int max_proc_per_quantum = 1;
  47        struct kfd_dev *dev = pm->dqm->dev;
  48
  49        process_count = pm->dqm->processes_count;
  50        queue_count = pm->dqm->active_queue_count;
  51        compute_queue_count = pm->dqm->active_cp_queue_count;
  52        gws_queue_count = pm->dqm->gws_queue_count;
  53
  54        /* check if there is over subscription
  55         * Note: the arbitration between the number of VMIDs and
  56         * hws_max_conc_proc has been done in
  57         * kgd2kfd_device_init().
  58         */
  59        *over_subscription = false;
  60
  61        if (dev->max_proc_per_quantum > 1)
  62                max_proc_per_quantum = dev->max_proc_per_quantum;
  63
  64        if ((process_count > max_proc_per_quantum) ||
  65            compute_queue_count > get_cp_queues_num(pm->dqm) ||
  66            gws_queue_count > 1) {
  67                *over_subscription = true;
  68                pr_debug("Over subscribed runlist\n");
  69        }
  70
  71        map_queue_size = pm->pmf->map_queues_size;
  72        /* calculate run list ib allocation size */
  73        *rlib_size = process_count * pm->pmf->map_process_size +
  74                     queue_count * map_queue_size;
  75
  76        /*
  77         * Increase the allocation size in case we need a chained run list
  78         * when over subscription
  79         */
  80        if (*over_subscription)
  81                *rlib_size += pm->pmf->runlist_size;
  82
  83        pr_debug("runlist ib size %d\n", *rlib_size);
  84}
  85
  86static int pm_allocate_runlist_ib(struct packet_manager *pm,
  87                                unsigned int **rl_buffer,
  88                                uint64_t *rl_gpu_buffer,
  89                                unsigned int *rl_buffer_size,
  90                                bool *is_over_subscription)
  91{
  92        int retval;
  93
  94        if (WARN_ON(pm->allocated))
  95                return -EINVAL;
  96
  97        pm_calc_rlib_size(pm, rl_buffer_size, is_over_subscription);
  98
  99        mutex_lock(&pm->lock);
 100
 101        retval = kfd_gtt_sa_allocate(pm->dqm->dev, *rl_buffer_size,
 102                                        &pm->ib_buffer_obj);
 103
 104        if (retval) {
 105                pr_err("Failed to allocate runlist IB\n");
 106                goto out;
 107        }
 108
 109        *(void **)rl_buffer = pm->ib_buffer_obj->cpu_ptr;
 110        *rl_gpu_buffer = pm->ib_buffer_obj->gpu_addr;
 111
 112        memset(*rl_buffer, 0, *rl_buffer_size);
 113        pm->allocated = true;
 114
 115out:
 116        mutex_unlock(&pm->lock);
 117        return retval;
 118}
 119
 120static int pm_create_runlist_ib(struct packet_manager *pm,
 121                                struct list_head *queues,
 122                                uint64_t *rl_gpu_addr,
 123                                size_t *rl_size_bytes)
 124{
 125        unsigned int alloc_size_bytes;
 126        unsigned int *rl_buffer, rl_wptr, i;
 127        int retval, processes_mapped;
 128        struct device_process_node *cur;
 129        struct qcm_process_device *qpd;
 130        struct queue *q;
 131        struct kernel_queue *kq;
 132        bool is_over_subscription;
 133
 134        rl_wptr = retval = processes_mapped = 0;
 135
 136        retval = pm_allocate_runlist_ib(pm, &rl_buffer, rl_gpu_addr,
 137                                &alloc_size_bytes, &is_over_subscription);
 138        if (retval)
 139                return retval;
 140
 141        *rl_size_bytes = alloc_size_bytes;
 142        pm->ib_size_bytes = alloc_size_bytes;
 143
 144        pr_debug("Building runlist ib process count: %d queues count %d\n",
 145                pm->dqm->processes_count, pm->dqm->active_queue_count);
 146
 147        /* build the run list ib packet */
 148        list_for_each_entry(cur, queues, list) {
 149                qpd = cur->qpd;
 150                /* build map process packet */
 151                if (processes_mapped >= pm->dqm->processes_count) {
 152                        pr_debug("Not enough space left in runlist IB\n");
 153                        pm_release_ib(pm);
 154                        return -ENOMEM;
 155                }
 156
 157                retval = pm->pmf->map_process(pm, &rl_buffer[rl_wptr], qpd);
 158                if (retval)
 159                        return retval;
 160
 161                processes_mapped++;
 162                inc_wptr(&rl_wptr, pm->pmf->map_process_size,
 163                                alloc_size_bytes);
 164
 165                list_for_each_entry(kq, &qpd->priv_queue_list, list) {
 166                        if (!kq->queue->properties.is_active)
 167                                continue;
 168
 169                        pr_debug("static_queue, mapping kernel q %d, is debug status %d\n",
 170                                kq->queue->queue, qpd->is_debug);
 171
 172                        retval = pm->pmf->map_queues(pm,
 173                                                &rl_buffer[rl_wptr],
 174                                                kq->queue,
 175                                                qpd->is_debug);
 176                        if (retval)
 177                                return retval;
 178
 179                        inc_wptr(&rl_wptr,
 180                                pm->pmf->map_queues_size,
 181                                alloc_size_bytes);
 182                }
 183
 184                list_for_each_entry(q, &qpd->queues_list, list) {
 185                        if (!q->properties.is_active)
 186                                continue;
 187
 188                        pr_debug("static_queue, mapping user queue %d, is debug status %d\n",
 189                                q->queue, qpd->is_debug);
 190
 191                        retval = pm->pmf->map_queues(pm,
 192                                                &rl_buffer[rl_wptr],
 193                                                q,
 194                                                qpd->is_debug);
 195
 196                        if (retval)
 197                                return retval;
 198
 199                        inc_wptr(&rl_wptr,
 200                                pm->pmf->map_queues_size,
 201                                alloc_size_bytes);
 202                }
 203        }
 204
 205        pr_debug("Finished map process and queues to runlist\n");
 206
 207        if (is_over_subscription) {
 208                if (!pm->is_over_subscription)
 209                        pr_warn("Runlist is getting oversubscribed. Expect reduced ROCm performance.\n");
 210                retval = pm->pmf->runlist(pm, &rl_buffer[rl_wptr],
 211                                        *rl_gpu_addr,
 212                                        alloc_size_bytes / sizeof(uint32_t),
 213                                        true);
 214        }
 215        pm->is_over_subscription = is_over_subscription;
 216
 217        for (i = 0; i < alloc_size_bytes / sizeof(uint32_t); i++)
 218                pr_debug("0x%2X ", rl_buffer[i]);
 219        pr_debug("\n");
 220
 221        return retval;
 222}
 223
 224int pm_init(struct packet_manager *pm, struct device_queue_manager *dqm)
 225{
 226        switch (dqm->dev->device_info->asic_family) {
 227        case CHIP_KAVERI:
 228        case CHIP_HAWAII:
 229                /* PM4 packet structures on CIK are the same as on VI */
 230        case CHIP_CARRIZO:
 231        case CHIP_TONGA:
 232        case CHIP_FIJI:
 233        case CHIP_POLARIS10:
 234        case CHIP_POLARIS11:
 235        case CHIP_POLARIS12:
 236        case CHIP_VEGAM:
 237                pm->pmf = &kfd_vi_pm_funcs;
 238                break;
 239        case CHIP_VEGA10:
 240        case CHIP_VEGA12:
 241        case CHIP_VEGA20:
 242        case CHIP_RAVEN:
 243        case CHIP_RENOIR:
 244        case CHIP_ARCTURUS:
 245        case CHIP_NAVI10:
 246        case CHIP_NAVI12:
 247        case CHIP_NAVI14:
 248        case CHIP_SIENNA_CICHLID:
 249        case CHIP_NAVY_FLOUNDER:
 250        case CHIP_VANGOGH:
 251        case CHIP_DIMGREY_CAVEFISH:
 252        case CHIP_BEIGE_GOBY:
 253        case CHIP_YELLOW_CARP:
 254                pm->pmf = &kfd_v9_pm_funcs;
 255                break;
 256        case CHIP_ALDEBARAN:
 257                pm->pmf = &kfd_aldebaran_pm_funcs;
 258                break;
 259        default:
 260                WARN(1, "Unexpected ASIC family %u",
 261                     dqm->dev->device_info->asic_family);
 262                return -EINVAL;
 263        }
 264
 265        pm->dqm = dqm;
 266        mutex_init(&pm->lock);
 267        pm->priv_queue = kernel_queue_init(dqm->dev, KFD_QUEUE_TYPE_HIQ);
 268        if (!pm->priv_queue) {
 269                mutex_destroy(&pm->lock);
 270                return -ENOMEM;
 271        }
 272        pm->allocated = false;
 273
 274        return 0;
 275}
 276
 277void pm_uninit(struct packet_manager *pm, bool hanging)
 278{
 279        mutex_destroy(&pm->lock);
 280        kernel_queue_uninit(pm->priv_queue, hanging);
 281}
 282
 283int pm_send_set_resources(struct packet_manager *pm,
 284                                struct scheduling_resources *res)
 285{
 286        uint32_t *buffer, size;
 287        int retval = 0;
 288
 289        size = pm->pmf->set_resources_size;
 290        mutex_lock(&pm->lock);
 291        kq_acquire_packet_buffer(pm->priv_queue,
 292                                        size / sizeof(uint32_t),
 293                                        (unsigned int **)&buffer);
 294        if (!buffer) {
 295                pr_err("Failed to allocate buffer on kernel queue\n");
 296                retval = -ENOMEM;
 297                goto out;
 298        }
 299
 300        retval = pm->pmf->set_resources(pm, buffer, res);
 301        if (!retval)
 302                kq_submit_packet(pm->priv_queue);
 303        else
 304                kq_rollback_packet(pm->priv_queue);
 305
 306out:
 307        mutex_unlock(&pm->lock);
 308
 309        return retval;
 310}
 311
 312int pm_send_runlist(struct packet_manager *pm, struct list_head *dqm_queues)
 313{
 314        uint64_t rl_gpu_ib_addr;
 315        uint32_t *rl_buffer;
 316        size_t rl_ib_size, packet_size_dwords;
 317        int retval;
 318
 319        retval = pm_create_runlist_ib(pm, dqm_queues, &rl_gpu_ib_addr,
 320                                        &rl_ib_size);
 321        if (retval)
 322                goto fail_create_runlist_ib;
 323
 324        pr_debug("runlist IB address: 0x%llX\n", rl_gpu_ib_addr);
 325
 326        packet_size_dwords = pm->pmf->runlist_size / sizeof(uint32_t);
 327        mutex_lock(&pm->lock);
 328
 329        retval = kq_acquire_packet_buffer(pm->priv_queue,
 330                                        packet_size_dwords, &rl_buffer);
 331        if (retval)
 332                goto fail_acquire_packet_buffer;
 333
 334        retval = pm->pmf->runlist(pm, rl_buffer, rl_gpu_ib_addr,
 335                                        rl_ib_size / sizeof(uint32_t), false);
 336        if (retval)
 337                goto fail_create_runlist;
 338
 339        kq_submit_packet(pm->priv_queue);
 340
 341        mutex_unlock(&pm->lock);
 342
 343        return retval;
 344
 345fail_create_runlist:
 346        kq_rollback_packet(pm->priv_queue);
 347fail_acquire_packet_buffer:
 348        mutex_unlock(&pm->lock);
 349fail_create_runlist_ib:
 350        pm_release_ib(pm);
 351        return retval;
 352}
 353
 354int pm_send_query_status(struct packet_manager *pm, uint64_t fence_address,
 355                        uint64_t fence_value)
 356{
 357        uint32_t *buffer, size;
 358        int retval = 0;
 359
 360        if (WARN_ON(!fence_address))
 361                return -EFAULT;
 362
 363        size = pm->pmf->query_status_size;
 364        mutex_lock(&pm->lock);
 365        kq_acquire_packet_buffer(pm->priv_queue,
 366                        size / sizeof(uint32_t), (unsigned int **)&buffer);
 367        if (!buffer) {
 368                pr_err("Failed to allocate buffer on kernel queue\n");
 369                retval = -ENOMEM;
 370                goto out;
 371        }
 372
 373        retval = pm->pmf->query_status(pm, buffer, fence_address, fence_value);
 374        if (!retval)
 375                kq_submit_packet(pm->priv_queue);
 376        else
 377                kq_rollback_packet(pm->priv_queue);
 378
 379out:
 380        mutex_unlock(&pm->lock);
 381        return retval;
 382}
 383
 384int pm_send_unmap_queue(struct packet_manager *pm, enum kfd_queue_type type,
 385                        enum kfd_unmap_queues_filter filter,
 386                        uint32_t filter_param, bool reset,
 387                        unsigned int sdma_engine)
 388{
 389        uint32_t *buffer, size;
 390        int retval = 0;
 391
 392        size = pm->pmf->unmap_queues_size;
 393        mutex_lock(&pm->lock);
 394        kq_acquire_packet_buffer(pm->priv_queue,
 395                        size / sizeof(uint32_t), (unsigned int **)&buffer);
 396        if (!buffer) {
 397                pr_err("Failed to allocate buffer on kernel queue\n");
 398                retval = -ENOMEM;
 399                goto out;
 400        }
 401
 402        retval = pm->pmf->unmap_queues(pm, buffer, type, filter, filter_param,
 403                                       reset, sdma_engine);
 404        if (!retval)
 405                kq_submit_packet(pm->priv_queue);
 406        else
 407                kq_rollback_packet(pm->priv_queue);
 408
 409out:
 410        mutex_unlock(&pm->lock);
 411        return retval;
 412}
 413
 414void pm_release_ib(struct packet_manager *pm)
 415{
 416        mutex_lock(&pm->lock);
 417        if (pm->allocated) {
 418                kfd_gtt_sa_free(pm->dqm->dev, pm->ib_buffer_obj);
 419                pm->allocated = false;
 420        }
 421        mutex_unlock(&pm->lock);
 422}
 423
 424#if defined(CONFIG_DEBUG_FS)
 425
 426int pm_debugfs_runlist(struct seq_file *m, void *data)
 427{
 428        struct packet_manager *pm = data;
 429
 430        mutex_lock(&pm->lock);
 431
 432        if (!pm->allocated) {
 433                seq_puts(m, "  No active runlist\n");
 434                goto out;
 435        }
 436
 437        seq_hex_dump(m, "  ", DUMP_PREFIX_OFFSET, 32, 4,
 438                     pm->ib_buffer_obj->cpu_ptr, pm->ib_size_bytes, false);
 439
 440out:
 441        mutex_unlock(&pm->lock);
 442        return 0;
 443}
 444
 445int pm_debugfs_hang_hws(struct packet_manager *pm)
 446{
 447        uint32_t *buffer, size;
 448        int r = 0;
 449
 450        size = pm->pmf->query_status_size;
 451        mutex_lock(&pm->lock);
 452        kq_acquire_packet_buffer(pm->priv_queue,
 453                        size / sizeof(uint32_t), (unsigned int **)&buffer);
 454        if (!buffer) {
 455                pr_err("Failed to allocate buffer on kernel queue\n");
 456                r = -ENOMEM;
 457                goto out;
 458        }
 459        memset(buffer, 0x55, size);
 460        kq_submit_packet(pm->priv_queue);
 461
 462        pr_info("Submitting %x %x %x %x %x %x %x to HIQ to hang the HWS.",
 463                buffer[0], buffer[1], buffer[2], buffer[3],
 464                buffer[4], buffer[5], buffer[6]);
 465out:
 466        mutex_unlock(&pm->lock);
 467        return r;
 468}
 469
 470
 471#endif
 472
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.